All pastes #402963 Raw Edit

Mine

public c v1 · immutable
·published 2007-03-20 02:44 UTC
rendered paste body
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include "main.h"/* Soon to be merged */#include "util.h"#include "tconfig.h"struct tconfig_block *parse_config(const char *filename){  FILE   *cfile;  char   *fbuf   = NULL;  char   *eip    = NULL;  struct tconfig_block *block = NULL;  struct tconfig_block *head  = NULL;  size_t  size   = 0;  size_t  i      = 0;  size_t  count  = 0;  /* For debug purposes */  int line       = 1;    /* No memory allocated at this point, we don't need    * to die nicely   */  if ((cfile = fopen(filename,"r")) == NULL)  {    fprintf(stderr,"Could not open configuration file: %s\n",filename);    exit(EXIT_FAILURE);  }  fbuf = tmalloc0(BUFFER_SIZE);  /* Read the entire file into memory */  for(i=0;(count = fread(&fbuf[i],1,1024,cfile)) == 1024;i+=1024)  {    if ((fbuf = realloc(fbuf,i+1024+1024)) == NULL)    {      fprintf(stderr,"Could not allocate memory for config file, barfing.\n");      exit(EXIT_FAILURE);    }  }    /* If NOT the end-of-file, we must have had an error of some sort, barf and die */  if (!feof(cfile))  {    fprintf(stderr, "An error occurred while reading the config file\n");    exit(EXIT_FAILURE);  }   /* Terminate it with a NULL */  fbuf[i+count] = '\0';  fclose(cfile);  block = tmalloc(sizeof(struct tconfig_block));  block->parent = NULL;  block->child  = NULL;  block->prev   = NULL;  block->next   = NULL;  block->key    = NULL;  block->value  = NULL;  head = block;    eip = fbuf;  while(*eip)  {    switch (*eip)    {      case '{':        block->child = tmalloc(sizeof(struct tconfig_block));        block->child->parent = block;        block                = block->child;        block->child         = NULL;        block->prev          = NULL;        block->next          = NULL;        block->key           = NULL;        block->value         = NULL;        break;            /* The very left element in tree should have the parent */      case '}':        /* Rewind the list the very left */        while (block->prev != NULL)          block = block->prev;               if (block->parent == NULL)        {          fprintf(stderr, "Mismatched } around line: %d\n",line);          exit(EXIT_FAILURE);        }          block              = block->parent;        break;      /* Ugly comment parsing routines */      case '/':        if (*(eip+1) != '*' && *(eip+1) != '/')        {          fprintf(stderr,"Stray / on line: %d\n",line);          exit(EXIT_FAILURE);        }        /* If comment takes C form */        if (*(eip+1) == '*')        {          /* Skip over / and * */          eip+=2;          /* Go until terminating -> */          while (*eip != '\0')           {            if (*(eip+1) == '\0')            {              fprintf(stderr,"Reached end of file while looking for */\n");              exit(EXIT_FAILURE);            }            if (*eip == '*' && *(eip+1) == '/')            {              /* loop increases eip, so only add 1 */              eip++;              break; /* Found end of comment */            }             if (*eip == '\r' && *(eip+1) == '\n')            {              eip++;              line++;            }            else if (*eip == '\n')            {              line++;            }            else if (*eip == '\r')            {              line++;            }            eip++;          }          if (eip == '\0')          {            return head;          }           }        else /* // comment, go until \r\n, \n, or \r */        {          eip+=2; /* Skip over // */                   while (*eip != '\0')          {            if (*eip == '\r')            {              /* This just means the file is over, not an error */              if (*(eip+1) == '\0')                return head;              if (*(eip+1) != '\n')              {                eip++;                line++;                break;              }              else              {                line++;                break;              }            }            else if (*eip == '\n')            {              line++;              break;            }            eip++;            }          if (*eip == '\0')            return head;                        }        break;      case '\r':        if (*(eip+1) == '\n')        {          eip++;          line++;        }        else          line++;        if (eip == '\0')          return head;        break;      case '\n':        line++;                  break;      case '\t':        break;      case ' ':        break;      default:        if (block->key != NULL)        {          block->next = tmalloc(sizeof(struct tconfig_block));           block->next->prev = block;          block             = block->next;          block->next       = NULL;          block->parent     = NULL;          block->key        = NULL;          block->value      = NULL;        }        /* Do a wasteful scan so I don't have to deal with realloc */        if (*eip == '"')        {          eip++; /* Skip the first " */          for (i=0;*(eip+i) != '\0' && *(eip+i) != '\n' && *(eip+i) != '\r' &&                   *(eip+i) != '"';i++);          if (*(eip+i) != '"')          {            fprintf(stderr, "Unmatched \" on line %d\n",line);            exit(EXIT_FAILURE);          }        }        else        {           for (i=0;*(eip+i) != '\0' && *(eip+i) != ' ' && *(eip+i) != '\t';i++);                      if (*(eip+i) != ' ' && *(eip+i) != '\t')          {            fprintf(stderr, "Unmatched key on line %d\n",line);            exit(EXIT_FAILURE);          }        }        size = i;          block->key = tmalloc0(size+1);        for (i=0;i<size;i++)        {          *(block->key+i) = *(eip++);        }        block->key[size] = '\0';           /* Skip over trailing " if exists, this could be a problem if key is next to value */        if (*eip == '"')          eip++;        /* Skip over whitespace, print error if EOF or there's a newline reached before text */        while(*eip == '\t' || *eip == ' ' || *eip == '\r' || *eip == '\n' || *eip == '\0')        {          if (*eip == '\0')          {            fprintf(stderr, "Reached end of file looking for %s's value on line %d\n",block->key,line);            exit(EXIT_FAILURE);          }          if (*eip == '\r' || *eip == '\n')          {            fprintf(stderr, "Reached end of line looking for %s's value on line %d\n",block->key,line);            exit(EXIT_FAILURE);          }              eip++;        }        /* Now to scan the value */        /* Do a wasteful scan so I don't have to deal with realloc */        if (*eip == '"')        {          eip++; /* Skip the first " */          for (i=0;*(eip+i) != '\0' && *(eip+i) != '\n' && *(eip+i) != '\r' &&                   *(eip+i) != '"';i++);          if (*(eip+i) != '"')          {            fprintf(stderr, "Unmatched \" on line %d\n",line);            exit(EXIT_FAILURE);          }        }        else        {          for (i=0;*(eip+i) != '\0' && *(eip+i) != ' ' && *(eip+i) != '\t' &&                   *(eip+i) != '\r' && *(eip+i) != '\n';i++);          if (*(eip+i) != ' ' && *(eip+i) != '\t' && *(eip+i) != '\r' && *(eip+i) != '\n')          {            fprintf(stderr, "Unmatched key on line %d\n",line);            exit(EXIT_FAILURE);          }        }        size = i;        block->value = tmalloc0(size+1);        for (i=0;i<size;i++)        {          *(block->value+i) = *(eip++);        }        block->value[size] = '\0';         break;              }       eip++; /* While loop increase */  }  return head;}void free_tconfig(struct tconfig_block *tcfg){  struct tconfig_block *tmp;  struct tconfig_block *search;  tmp = tcfg;  /* Rewind to the top left, it should be there already */  while (tmp->prev != NULL && tmp->parent != NULL)    tmp = (tmp->parent) ? tmp->parent : tmp->prev;     }