Logo Search packages:      
Sourcecode: ffe version File versions  Download package

parserc.c

/*
 *    ffe - flat file extractor
 *
 *    Copyright (C) 2006 Timo Savinen
 *    This file is part of ffe.
 * 
 *    ffe is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    ffe is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with ffe; if not, write to the Free Software
 *    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

/* $Id: parserc.c,v 1.24 2006-04-23 16:23:01 timo Exp $ */
/* parsing the rc-file */

#include "ffe.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#ifdef PACKAGE
static char *program = PACKAGE;
#else
static char *program = "ffe";
#endif

/* pointer to rc-file */
static FILE *fp = NULL;

/* current line number */
static int lineno = 0;

/* block chars */
#define BLOCK_START '{'
#define BLOCK_END   '}'

#define COMMENT     '#'

/* reading logical line states */
#define LL_OPTION 1
#define LL_BLOCK_START 2
#define LL_BLOCK_END 3
#define LL_EOF 4

/* structure containing one rc-file option definition */
struct rc_option {
    char *name;              /* the name */
    char *parameters;        /* paramters option must/may have */
};

char *values[100];            /* poister to option name and parameters */

/* rc-file option parameter pictures 
   M_ = mandatory
   O_ = optional
*/
#define M_STRING 'S'
#define O_STRING 's' 
#define M_NUMBER 'N'
#define O_NUMBER 'n'
#define M_CHAR 'C'
#define O_CHAR 'c'

/* option names */
#define N_STRUCTURE         "structure"
#define N_TYPE              "type"
#define N_QUOTE             "quoted"
#define N_HEADER            "header"
#define N_OUTPUT            "output"
#define N_RECORD            "record"
#define N_ID                "id"
#define N_FIELD             "field"
#define N_FIELDSFROM         "fields-from"
#define N_FILE_HEADER       "file_header"
#define N_FILE_TRAILER      "file_trailer"
#define N_DATA              "data"
#define N_SEPARATOR         "separator"
#define N_RECORD_HEADER     "record_header"
#define N_RECORD_TRAILER    "record_trailer"
#define N_JUSTIFY           "justify"
#define N_INDENT            "indent"
#define N_FIELDLIST         "field-list"
#define N_PRINT_NO_DATA     "no-data-print"
#define N_FIELD_EMPTY_PRINT "field-empty-print"
#define N_EMPTY_CHARS       "empty-chars"




static struct rc_option rc_opts[] = {
    {N_STRUCTURE,"S"},
    {N_TYPE,"Scc"},
    {N_QUOTE,"c"},
    {N_HEADER,"S"},
    {N_RECORD,"S"},
    {N_OUTPUT,"S"},
    {N_ID,"NS"},
    {N_FIELD,"Sn"},
    {N_FIELDSFROM,"S"},
    {N_FILE_HEADER,"S"},
    {N_FILE_TRAILER,"S"},
    {N_DATA,"S"},
    {N_SEPARATOR,"S"},
    {N_RECORD_HEADER,"S"},
    {N_RECORD_TRAILER,"S"},
    {N_JUSTIFY,"S"},
    {N_INDENT,"S"},
    {N_FIELDLIST,"S"},
    {N_PRINT_NO_DATA,"S"},
    {N_FIELD_EMPTY_PRINT,"S"},
    {N_EMPTY_CHARS,"S"},
    {NULL,NULL}
};


void
open_rc_file(char *file)
{
    fp = fopen(file,"r");
    if (fp == NULL) panic("Error in opening file",file,strerror(errno));
}

/* remove leading and trailing whitespace */
void
trim(char *buf)
{
    char *wpos=buf,*rpos=buf;

    while(isspace(*rpos)) rpos++;

    if(rpos != buf)
    {
        while(*rpos)
        {
            *wpos = *rpos;
            wpos++;
            rpos++;
        }
        *wpos = 0;
    }

    if(*buf)
    {
        rpos = buf;
        while(*rpos) rpos++;
        rpos--;
        while(isspace(*rpos)) rpos--;
        rpos++;
        *rpos = 0;
    }
}

/* parses a field list from include command or from -f option */
/* returns NULL if not fields */
/* comma is assumed to be escaped as \, */
struct include_field *
parse_include_list(char *list)
{
    struct include_field *ret = NULL,*c = NULL;
    char *p = list;
    char *w = list;
    char *s = list;

    if(p == NULL) return NULL;

    while(*p)
    {
        if(*p == ',' && p[1] == ',')
        {
            p++;
            *w = *p;
            w++;
            p++;
        }
        *w = *p;
        if(*p == ',' || !p[1])
        {
            if(p[1]) *w = 0;
            if(strlen(s))
            {
                if(ret == NULL)
                {
                    ret = xmalloc(sizeof(struct include_field));
                    c = ret;
                } else
                {
                    c->next = xmalloc(sizeof(struct include_field));
                    c = c->next;
                }
                c->next = NULL;
                c->name = xstrdup(s);
            }
            p++;
            while(*p == ',') p++;
            s = p;
            w = s;
            p = s;
        } else
        {
            w++;
            p++;
        }
    }
    return ret;
}
        
/* reading one logical line, returns the status of the line read */
int 
read_logical_line(char *buffer, int bufsize)
{
    static char last_eol_char = 0;      /* for what did previous read end */
    int prev_char = 0,c;
    int i=0,retval = 0;

    buffer[0] = 0;

    switch(last_eol_char)
    {
        case BLOCK_START:
            last_eol_char = 0;
            return LL_BLOCK_START;
            break;
        case BLOCK_END:
            last_eol_char = 0;
            return LL_BLOCK_END;
            break;
    }
    
    do
    {
        c = getc(fp);
        if(prev_char == '\\')
        {
            switch(c)
            {
                case 'a':
                    buffer[i] = '\a';
                    c = 0;
                    i++;
                    break;
                case 'b':
                    buffer[i] = '\b';
                    c = 0;
                    i++;
                    break;
                case 't':
                    buffer[i] = '\t';
                    c = 0;
                    i++;
                    break;
                case 'n':
                    buffer[i] = '\n';
                    c = 0;
                    i++;
                    break;
                case 'v':
                    buffer[i] = '\v';
                    c = 0;
                    i++;
                    break;
                case 'f':
                    buffer[i] = '\f';
                    c = 0;
                    i++;
                    break;
                case 'r':
                    buffer[i] = '\r';
                    c = 0;
                    i++;
                    break;
                case '\\':
                    buffer[i] = '\\';
                    c = 0;
                    i++;
                    break;
                case COMMENT:
                    buffer[i] = COMMENT;
                    c = 0;
                    i++;
                    break;
                case '\n':    /* newline escaped */
                    lineno++;
                    buffer[i] = getc(fp);
                    c = 0;
                    i++;
                    break;
                default:
                    buffer[i] = '\\';
                    i++;
                    break;
            }
        }
        
        prev_char = c;

        switch(c)
        {
            case COMMENT:
                do
                {
                    c = getc(fp);
                } while (c != '\n' && c != EOF);  /* no break !*/
            case '\n':
                if(c == '\n') lineno++;
                buffer[i] = 0;
                retval = LL_OPTION;
                break;
            case BLOCK_START:
                buffer[i] = 0;
                retval = LL_OPTION;
                break;
            case BLOCK_END:
                buffer[i] = 0;
                retval = LL_OPTION;
                break;
            case EOF:
                buffer[i] = 0;
                retval = LL_OPTION;
                break;
            case '\\':
            case 0:
                break;
            default:
                if(i >= bufsize) panic("rc-file line too long",NULL,NULL);
                buffer[i] = (char) c;
                i++;
                break;
        }

        if(retval)
        {
            trim(buffer);
            switch(c)
            {
                case '\n':
                    if(buffer[0] == 0) 
                    {
                        i = 0;          /* empty line */
                        retval = 0;
                    } else
                    {
                        return retval;
                    }
                    break;
                case EOF:
                    if(buffer[0] == 0)
                    {
                         retval = LL_EOF;
                    }
                    return retval;
                case BLOCK_START:
                    if(buffer[0] == 0)
                    {
                        retval = LL_BLOCK_START;
                    } else
                    {
                        last_eol_char = c;
                    }
                    return retval;
                case BLOCK_END:
                    if(buffer[0] == 0)
                    {
                        retval = LL_BLOCK_END;
                    } else
                    {
                        last_eol_char = c;
                    }
                    return retval;
                    break;
            }
        }
    } while (1);
}

void 
error_in_line()
{
    fprintf(stderr,"%s: Error in rc-file, line %d\n",program,lineno);
}

#define READ_BUF_SIZE 1024

/* reads logical lines and parses a one option */
/* option name and parameters are in values-array */
/* return the number of elements in array */
int parse_option(char *buf)
{
    char *rpos = buf;
    char *end = buf;
    char *param;
    int i = 0,j;
    int valc = 0;
    int quoted;

    values[0] = buf;

    while(*end) end++;

    while(!isspace(*rpos) && *rpos) rpos++;
    *rpos = 0;

    while(rc_opts[i].name != NULL && strcmp(rc_opts[i].name,values[0]) != 0) i++;

    if(rc_opts[i].name != NULL)  /* found */
    {
        param = rc_opts[i].parameters;
        while(rpos < end)
        {
            if(*param)
            {
                rpos++;
                while(isspace(*rpos)) rpos++;  /* next non space */
                quoted = 0;
                switch(*param)
                {
                    case 'S':
                    case 's':
                    case 'C':
                    case 'c':
                        if(*rpos)
                        {
                            if(*rpos == '"') 
                            {
                                rpos++;
                                quoted = 1;
                            }
                            valc++;
                            values[valc] = rpos;
                            if(*(param + 1))  /* not the last possible paramter */
                            {
                                if(quoted)
                                {
                                    j = 0;
                                    while(*rpos != '"' && *rpos) 
                                    {
                                        rpos++;
                                        if(*rpos == '"' && *(rpos - 1) == '\\')
                                        {
                                            j++;
                                            *(rpos - j) = *rpos;
                                            rpos++;
                                        }
                                        if(j) *(rpos - j) = *rpos;
                                    }
                                    if(*rpos != '"')
                                    {
                                        error_in_line();
                                        panic("Quotation not ended",NULL,NULL);
                                    }
                                    *(rpos - j) = 0;
                                    *rpos = 0;
                                } else
                                {
                                    while(!isspace(*rpos) && *rpos) rpos++;
                                    *rpos=0;
                                }
                            } else  /* last parameter, get the rest of the line */
                            {
                                j = 0;
                                while(*rpos) 
                                {
                                    rpos++;
                                    if(*rpos == '"')
                                    {
                                        if(*(rpos - 1) == '\\')
                                        {
                                            j++;
                                            *(rpos - j) = *rpos;
                                            rpos++;
                                            if(!*rpos)
                                            {
                                                error_in_line();
                                                panic("Quotation not ended",NULL,NULL);
                                            }
                                        } else if(*(rpos + 1) && quoted)
                                        {
                                            error_in_line();
                                            panic("Too many parameters",values[0],NULL);
                                        }
                                    }
                                    if(j) *(rpos - j) = *rpos;
                                }
                                if(quoted)
                                {
                                    if(*(rpos - 1) != '"')
                                    {
                                        error_in_line();
                                        panic("Quotation not ended",NULL,NULL);
                                    }
                                    *(rpos - j - 1) = 0;
                                } else
                                {
                                    *(rpos - j) = 0;
                                }
                                *rpos = 0;
                            }  
                            if((*param == 'C' || *param == 'c') && values[valc][1])
                            {
                                error_in_line();
                                panic("Single character parameter expected",values[0],NULL);
                            } 
                        } else
                        {
                            if(*param == 'S' || *param == 'C')
                            {
                                error_in_line();
                                panic("Mandatory parameter missing",values[0],NULL);
                            }
                        }
                        break;
                    case 'N':
                    case 'n':
                        if(*rpos)
                        {
                            valc++;
                            values[valc] = rpos;
                            while(isdigit(*rpos)) rpos++;
                            if(!isspace(*rpos) && *rpos)
                            {
                                error_in_line();
                                panic("A number expected",values[0],NULL);
                            }
                            *rpos=0;
                        } else
                        {
                            if(*param == 'N')
                            {
                                error_in_line();
                                panic("Mandatory parameter missing",values[0],NULL);
                            }
                        }
                        break;
                }
                if(valc > 3)
                {
                    error_in_line();
                    panic("Too many parameters",values[0],NULL);
                }
            } else
            {
                error_in_line();
                panic("Too many parameters",values[0],NULL);
            }
            param++;
        }
        if(isupper(*param))
        {
            error_in_line();
            panic("Mandatory parameter missing",values[0],NULL);
        }
    } else
    {
        error_in_line();
        panic("Unknown option",values[0],NULL);
    }
    return valc;
}

                           
/* parse status values */
#define PS_MAIN 1
#define PS_STRUCT 2
#define PS_RECORD 3
#define PS_OUTPUT 4
#define PS_W_STRUCT 5
#define PS_W_RECORD 6
#define PS_W_OUTPUT 7

void
print_s()
{
    struct structure *s = structure;
    struct record *r;
    struct field *f;

    while(s != NULL)
    {
        printf("%s\n",s->name);
        r = s->r;
        while(r != NULL)
        {
            f = r->f;
            printf(" %s\n",r->name);
            while(f != NULL)
            {
                printf("  %s %d\n",f->name,f->length);
                f = f->next;
            }
            r = r->next;
        }
        s = s->next;
    }
}

void 
parserc(char *rcfile,char *include_field_list)
{
    struct structure *c_structure = structure;
    struct field *c_field = NULL;
    struct id *c_id =  NULL;
    struct record *c_record = NULL;
    struct output *c_output = output;
    struct include_field *fl = parse_include_list(include_field_list);

    char *read_buffer;
    int line_status;
    int status = PS_MAIN;
    int opt_count;

    open_rc_file(rcfile);

    read_buffer = xmalloc(READ_BUF_SIZE);

    if(c_structure != NULL) while(c_structure->next != NULL) c_structure = c_structure->next;

    if(c_output != NULL) while(c_output->next != NULL) c_output = c_output->next;

    while((line_status = read_logical_line(read_buffer,READ_BUF_SIZE)) != LL_EOF)
    {
        switch(line_status)
        {
            case LL_OPTION:
                opt_count = parse_option(read_buffer);
                switch(status)
                {
                    case PS_MAIN:
                        if(strcmp(values[0],N_STRUCTURE) == 0)
                        {
                            if(structure == NULL)
                            {
                                c_structure = xmalloc(sizeof(struct structure));
                                structure = c_structure;
                            } else
                            {
                                c_structure->next = xmalloc(sizeof(struct structure));
                                c_structure = c_structure->next;
                            }
                            c_structure->next = NULL;
                            c_structure->name = xstrdup(values[1]);
                            c_structure->type[0] = FIXED_LENGTH;
                            c_structure->quote = 0;
                            c_structure->header = 0;
                            c_structure->output_name = DEFALT_OUTPUT;
                            c_structure->vote = 0;
                            c_structure->o = NULL;
                            c_structure->r = NULL;
                            status = PS_W_STRUCT;
                        } else if(strcmp(values[0],N_OUTPUT) == 0)
                        {
                            if(c_output == NULL)
                            {
                                c_output = xmalloc(sizeof(struct output));
                                output = c_output;
                            } else
                            {
                                c_output->next = xmalloc(sizeof(struct output));
                                c_output = c_output->next;
                            }
                            c_output->next = NULL;
                            c_output->name = xstrdup(values[1]);
                            c_output->file_header = NULL;
                            c_output->file_trailer = NULL;
                            c_output->header = NULL;
                            c_output->data = "%d";
                            c_output->separator = NULL;
                            c_output->record_header = NULL;
                            c_output->record_trailer = "\n";
                            c_output->justify = LEFT_JUSTIFY;
                            c_output->indent = NULL;
                            c_output->no_data = 1;
                            c_output->empty_chars = " \f\n\r\t\v";
                            c_output->print_empty = 1;
                            if(fl != NULL)
                            {
                                c_output->fl = fl;
                            } else
                            {
                                c_output->fl = NULL;
                            }
                            status = PS_W_OUTPUT;
                        } else 
                        {
                            error_in_line();
                            panic("Option not inside structure or output",values[0],NULL);
                        }
                        break;
                    case PS_STRUCT:
                        if(strcmp(values[0],N_TYPE) == 0)
                        {
                            if(strcmp(values[1],"fixed") == 0)
                            {
                                c_structure->type[0] = FIXED_LENGTH;
                                if(opt_count > 1)
                                {
                                    error_in_line();
                                    panic("too many parameters for",values[0],NULL);
                                }
                            } else if(strcmp(values[1],"separated") == 0)
                            {
                                c_structure->type[0] = SEPARATED;
                                c_structure->type[1] = ',';
                                c_structure->type[2] = 0;

                                if(opt_count > 1)
                                {
                                    c_structure->type[1] = values[2][0];
                                }
                                if(opt_count > 2)
                                {
                                    if(values[3][0] == '*')
                                    {
                                        c_structure->type[2] = values[3][0];
                                    } else
                                    {
                                        error_in_line();
                                        panic("An \'*\' is expected",values[0],NULL);
                                    }
                                }
                            } else
                            {
                                error_in_line();
                                panic("Unknown type",NULL,NULL);
                            }
                        } else if(strcmp(values[0],N_HEADER) == 0)
                        {
                            if(strcmp(values[1],"first") == 0)
                            {
                                c_structure->header = HEADER_FIRST;
                            } else if(strcmp(values[1],"all") == 0)
                            {
                                c_structure->header = HEADER_ALL;
                            } else if(strcmp(values[1],"no") == 0)
                            {
                                c_structure->header = 0;
                            } else
                            {
                                error_in_line();
                                panic("first, all or no expected",NULL,NULL);
                            }
                        } else if(strcmp(values[0],N_OUTPUT) == 0)
                        {
                            c_structure->output_name = xstrdup(values[1]);
                        } else if(strcmp(values[0],N_RECORD) == 0)
                        {
                            if(c_structure->r == NULL)
                            {
                                c_record = xmalloc(sizeof(struct record));
                                c_structure->r = c_record;
                            } else
                            {
                                c_record->next = xmalloc(sizeof(struct record));
                                c_record = c_record->next;
                            }
                            c_record->next = NULL;
                            c_record->name = xstrdup(values[1]);
                            c_record->i = NULL;
                            c_record->f = NULL;
                            c_record->fields_from = NULL;
                            c_record->o = NULL;
                            c_record->output_name = NULL;
                            c_record->vote = 0;
                            status = PS_W_RECORD;
                        } else if(strcmp(values[0],N_QUOTE) == 0)
                        {
                            if(opt_count > 0)
                            {
                                c_structure->quote = values[1][0];
                            } else
                            {
                                c_structure->quote = '"';
                            }
                        } else
                        {
                            error_in_line();
                            panic("Unknown option in structure",NULL,NULL);
                        }
                        break;
                    case PS_RECORD:
                        if(strcmp(values[0],N_ID) == 0)
                        {
                            if(c_record->i == NULL)
                            {
                                c_id = xmalloc(sizeof(struct id));
                                c_record->i = c_id;
                            } else
                            {
                                c_id->next = xmalloc(sizeof(struct id));
                                c_id = c_id->next;
                            }
                            c_id->next = NULL;
                            if(sscanf(values[1],"%d",&c_id->position) != 1)
                            {
                                error_in_line();
                                panic("Error in number",NULL,NULL);
                            }
                            if(c_id->position < 1)
                            {
                                error_in_line();
                                panic("Position must be greater than zero",NULL,NULL);
                            }
                            c_id->key = xstrdup(values[2]);
                        } else if(strcmp(values[0],N_FIELD) == 0)
                        {
                            if(c_record->f == NULL)
                            {
                                c_field = xmalloc(sizeof(struct field));
                                c_record->f = c_field;
                            } else
                            {
                                c_field->next = xmalloc(sizeof(struct field));
                                c_field = c_field->next;
                            }
                            c_field->next = NULL;
                            if(values[1][0] == '*' && !values[1][1])
                            {
                                c_field->name = NULL;
                            } else
                            {
                                c_field->name = xstrdup(values[1]);
                            }
                            if(opt_count > 1)
                            {
                                if(sscanf(values[2],"%d",&c_field->length) != 1)
                                {
                                    error_in_line();
                                    panic("Error in number",NULL,NULL);
                                }
                            } else
                            {
                                c_field->length = 0;
                            }
                        } else if(strcmp(values[0],N_FIELDSFROM) == 0)
                        {
                            c_record->fields_from = xstrdup(values[1]);
                        } else if(strcmp(values[0],N_OUTPUT) == 0)
                        {
                            c_record->output_name = xstrdup(values[1]);
                        } else
                        {
                            error_in_line();
                            panic("Unknown option in record",NULL,NULL);
                        }
                        break;
                    case PS_OUTPUT:
                        if(strcmp(values[0],N_FILE_HEADER) == 0)
                        {
                            c_output->file_header = xstrdup(values[1]);
                        } else if(strcmp(values[0],N_FILE_TRAILER) == 0)
                        {
                            c_output->file_trailer = xstrdup(values[1]);
                        } else if(strcmp(values[0],N_HEADER) == 0)
                        {
                            c_output->header = xstrdup(values[1]);
                        } else if(strcmp(values[0],N_DATA) == 0)
                        {
                            c_output->data = xstrdup(values[1]);
                        } else if(strcmp(values[0],N_SEPARATOR) == 0)
                        {
                            c_output->separator = xstrdup(values[1]);
                        } else if(strcmp(values[0],N_RECORD_HEADER) == 0)
                        {
                            c_output->record_header = xstrdup(values[1]);
                        } else if(strcmp(values[0],N_RECORD_TRAILER) == 0)
                        {
                            c_output->record_trailer = xstrdup(values[1]);
                        } else if(strcmp(values[0],N_JUSTIFY) == 0)
                        {
                            if(!values[1][1])
                            {
                                c_output->justify = values[1][0];
                            } else if(strcmp(values[1],"right") == 0)
                            {
                                c_output->justify = RIGHT_JUSTIFY;
                            } else if(strcmp(values[1],"left") == 0)
                            {
                                c_output->justify = LEFT_JUSTIFY;
                            } else
                            {
                                error_in_line();
                                panic("Unknown values in justify",NULL,NULL);
                            }
                        } else if(strcmp(values[0],N_PRINT_NO_DATA) == 0)
                        {
                            if(strcmp(values[1],"yes") == 0)
                            {
                                c_output->no_data = 1;
                            } else if(strcmp(values[1],"no") == 0)
                            {
                                c_output->no_data = 0;
                            } else
                            {
                                error_in_line();
                                panic("Unknown values in print-no-data",NULL,NULL);
                            }
                        } else if(strcmp(values[0],N_INDENT) == 0)
                        {
                            c_output->indent = xstrdup(values[1]);
                        } else if(strcmp(values[0],N_FIELDLIST) == 0)
                        {
                            if(c_output->fl ==  NULL) c_output->fl = parse_include_list(values[1]);
                        } else if(strcmp(values[0],N_FIELD_EMPTY_PRINT) == 0)
                        {
                            if(strcmp(values[1],"yes") == 0)
                            {
                                c_output->print_empty = 1;
                            } else if(strcmp(values[1],"no") == 0)
                            {
                                c_output->print_empty = 0;
                            } else
                            {
                                error_in_line();
                                panic("Unknown values in field-empty-print",NULL,NULL);
                            }
                        } else if(strcmp(values[0],N_EMPTY_CHARS) == 0)
                        {
                            c_output->empty_chars = xstrdup(values[1]);
                        } else
                        {
                            error_in_line();
                            panic("Unknown option in output definition",NULL,NULL);
                        }
                        break;
                    case PS_W_RECORD:
                    case PS_W_OUTPUT:
                    case PS_W_STRUCT:
                        error_in_line();
                        panic("{ expected, found",values[0],NULL);
                        break;
                }
                break;
            case LL_BLOCK_START:
                switch(status)
                {
                    case PS_W_STRUCT:
                        status = PS_STRUCT;
                        break;
                    case PS_W_OUTPUT:
                        status = PS_OUTPUT;
                        break;
                    case PS_W_RECORD:
                        status = PS_RECORD;
                        break;
                    default:
                        error_in_line();
                        panic("{ not expected",NULL,NULL);
                        break;
                }
                break;
            case LL_BLOCK_END:
                switch(status)
                {
                    case PS_STRUCT:
                    case PS_OUTPUT:
                        status = PS_MAIN;
                        break;
                    case PS_RECORD:
                        status = PS_STRUCT;
                        break;
                    default:
                        error_in_line();
                        panic("} not expected",NULL,NULL);
                }
                break;
        }
    }
    if(status != PS_MAIN)
    {
        panic("End of file reached before closing }",NULL,NULL);
    }
    free(read_buffer);
    fclose(fp);
}
 

Generated by  Doxygen 1.6.0   Back to index