"Fossies" - the Fresh Open Source Software Archive

Member "ffe-0.3.9/src/parserc.c" (21 Oct 2017, 70202 Bytes) of package /linux/privat/ffe-0.3.9.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "parserc.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.3.7-1_vs_0.3.8.

    1 /*
    2  *    ffe - flat file extractor
    3  *
    4  *    Copyright (C) 2006 Timo Savinen
    5  *    This file is part of ffe.
    6  * 
    7  *    ffe is free software; you can redistribute it and/or modify
    8  *    it under the terms of the GNU General Public License as published by
    9  *    the Free Software Foundation; either version 2 of the License, or
   10  *    (at your option) any later version.
   11  *
   12  *    ffe is distributed in the hope that it will be useful,
   13  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
   14  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15  *    GNU General Public License for more details.
   16  *
   17  *    You should have received a copy of the GNU General Public License
   18  *    along with ffe; if not, write to the Free Software
   19  *    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   20  *
   21  */
   22 
   23 /* $Id: parserc.c,v 1.80 2010-09-15 10:49:54 timo Exp $ */
   24 /* parsing the rc-file */
   25 
   26 #include "ffe.h"
   27 #include <stdlib.h>
   28 #include <string.h>
   29 #include <ctype.h>
   30 #ifdef HAVE_PRINTF_H
   31 #include <printf.h>
   32 #endif
   33 
   34 #ifdef HAVE_PROCESS_H
   35 #include <process.h>
   36 #endif
   37 
   38 #ifdef HAVE_IO_H
   39 #include <io.h>
   40 #endif
   41 
   42 
   43 #ifdef PACKAGE
   44 static char *program = PACKAGE;
   45 #else
   46 static char *program = "ffe";
   47 #endif
   48 
   49 /* pointer to rc-file */
   50 static FILE *fp = NULL;
   51 static FILE *child = NULL;      /* read from child */
   52 
   53 /* current line number */
   54 static int lineno = 0;
   55 
   56 /* block chars */
   57 #define BLOCK_START '{'
   58 #define BLOCK_END   '}'
   59 
   60 #define COMMENT     '#'
   61 
   62 /* reading logical line states */
   63 #define LL_OPTION 1
   64 #define LL_BLOCK_START 2
   65 #define LL_BLOCK_END 3
   66 #define LL_EOF 4
   67 
   68 #define COMMAND_LEN 128
   69 static size_t command_len = COMMAND_LEN;
   70 static char *command;                    /* used in command substituion */
   71 static char *cs_temp_file = NULL;
   72 
   73 /* structure containing one rc-file option definition */
   74 struct rc_option {
   75     char *name;              /* the name */
   76     char *parameters;        /* paramters option must/may have */
   77 };
   78 
   79 char *values[100];            /* poister to option name and parameters */
   80 
   81 /* rc-file option parameter pictures 
   82    M_ = mandatory
   83    O_ = optional
   84 */
   85 #define M_STRING 'S'
   86 #define O_STRING 's' 
   87 #define M_NUMBER 'N'
   88 #define O_NUMBER 'n'
   89 #define M_CHAR 'C'
   90 #define O_CHAR 'c'
   91 
   92 /* option names */
   93 #define N_STRUCTURE         "structure"
   94 #define N_TYPE              "type"
   95 #define N_QUOTE             "quoted"
   96 #define N_HEADER            "header"
   97 #define N_OUTPUT            "output"
   98 #define N_RECORD            "record"
   99 #define N_ID                "id"
  100 #define N_RID               "rid"
  101 #define N_FIELD             "field"
  102 #define N_FIELDSFROM        "fields-from"
  103 #define N_FILE_HEADER       "file-header"
  104 #define N_FILE_TRAILER      "file-trailer"
  105 #define N_DATA              "data"
  106 #define N_SEPARATOR         "separator"
  107 #define N_RECORD_HEADER     "record-header"
  108 #define N_RECORD_TRAILER    "record-trailer"
  109 #define N_GROUP_HEADER      "group-header"
  110 #define N_ELEMENT_HEADER    "element-header"
  111 #define N_GROUP_TRAILER     "group-trailer"
  112 #define N_ELEMENT_TRAILER   "element-trailer"
  113 #define N_JUSTIFY           "justify"
  114 #define N_INDENT            "indent"
  115 #define N_FIELDLIST         "field-list"
  116 #define N_PRINT_NO_DATA     "no-data-print"
  117 #define N_FIELD_EMPTY_PRINT "field-empty-print"
  118 #define N_EMPTY_CHARS       "empty-chars"
  119 #define N_LOOKUP            "lookup"
  120 #define N_PAIR              "pair"
  121 #define N_FILE              "file"
  122 #define N_DEFAULT           "default-value"
  123 #define N_SEARCH            "search"
  124 #define N_CONST             "const"
  125 #define N_FIELD_COUNT       "field-count"
  126 #define N_OFILE             "output-file"
  127 #define N_LEVEL             "level"
  128 #define N_RECORD_LENGTH     "record-length"
  129 #define N_HEX_CAP           "hex-caps"
  130 #define N_PIPE          "filter"
  131 #define N_VARLEN        "variable-length"
  132 #define N_ANON          "anonymize"
  133 #define N_METHOD        "method"
  134 
  135 
  136 
  137 
  138 
  139 static struct rc_option rc_opts[] = {
  140     {N_STRUCTURE,"S"},
  141     {N_TYPE,"Scc"},
  142     {N_QUOTE,"c"},
  143     {N_HEADER,"S"},
  144     {N_RECORD,"S"},
  145     {N_OUTPUT,"S"},
  146     {N_ID,"NS"},
  147     {N_RID,"NS"},
  148     {N_FIELD,"Ssssss"},
  149     {N_FIELDSFROM,"S"},
  150     {N_FILE_HEADER,"S"},
  151     {N_FILE_TRAILER,"S"},
  152     {N_DATA,"S"},
  153     {N_SEPARATOR,"S"},
  154     {N_RECORD_HEADER,"S"},
  155     {N_RECORD_TRAILER,"S"},
  156     {N_GROUP_HEADER,"S"},
  157     {N_GROUP_TRAILER,"S"},
  158     {N_ELEMENT_HEADER,"S"},
  159     {N_ELEMENT_TRAILER,"S"},
  160     {N_JUSTIFY,"S"},
  161     {N_INDENT,"S"},
  162     {N_FIELDLIST,"S"},
  163     {N_PRINT_NO_DATA,"S"},
  164     {N_FIELD_EMPTY_PRINT,"S"},
  165     {N_EMPTY_CHARS,"S"},
  166     {N_LOOKUP,"S"},
  167     {N_PAIR,"SS"},
  168     {N_FILE,"Sc"},
  169     {N_DEFAULT,"S"},
  170     {N_SEARCH,"S"},
  171     {N_CONST,"SS"},
  172     {N_FIELD_COUNT,"N"},
  173     {N_OFILE,"S"},
  174     {N_LEVEL,"Nss"},
  175     {N_RECORD_LENGTH,"S"},
  176     {N_HEX_CAP,"S"},
  177     {N_PIPE,"SS"},
  178     {N_VARLEN,"SSn"},
  179     {N_ANON,"S"},
  180     {N_METHOD,"SSnns"},
  181     {NULL,NULL}
  182 };
  183 
  184 struct anon_method {
  185     char *name;
  186     int method;
  187 };
  188 
  189 
  190 static struct anon_method methods[] = {
  191     {"MASK",A_MASK},
  192     {"RANDOM",A_RANDOM},
  193     {"NRANDOM",A_NRANDOM},
  194     {"HASH",A_HASH},
  195     {"NHASH",A_NHASH},
  196     {NULL,A_UNKNOWN}
  197 };
  198 
  199 static int find_anon_method(char *name)
  200 {
  201     int i=0;
  202 
  203     while(methods[i].name != NULL)
  204     {
  205         if(strcmp(methods[i].name,name) == 0) return methods[i].method;
  206         i++;
  207     }
  208     return A_UNKNOWN;
  209 }
  210    
  211 
  212 int
  213 is_digit(char *number)
  214 {
  215     while(*number) if(!isdigit(*number++)) return 0;
  216     return 1;
  217 }
  218 
  219 void remove_temp_file()
  220 {
  221     if(cs_temp_file) unlink(cs_temp_file);
  222 }
  223 
  224 
  225 void
  226 open_rc_file(char *file)
  227 {
  228     fp = xfopen(file,"r");
  229 }
  230 
  231 void 
  232 error_in_line()
  233 {
  234     fprintf(stderr,"%s: Error in rcfile, line %d\n",program,lineno);
  235 }
  236 
  237 /* remove leading and trailing whitespace */
  238 void
  239 trim(char *buf)
  240 {
  241     register char *wpos=buf,*rpos=buf;
  242 
  243     while(isspace(*rpos)) rpos++;
  244 
  245     if(rpos != buf)
  246     {
  247         while(*rpos)
  248         {
  249             *wpos = *rpos;
  250             wpos++;
  251             rpos++;
  252         }
  253         *wpos = 0;
  254     }
  255 
  256     if(*buf)
  257     {
  258         rpos = buf;
  259         while(*rpos) rpos++;
  260         rpos--;
  261         while(isspace(*rpos)) rpos--;
  262         rpos++;
  263         *rpos = 0;
  264     }
  265 }
  266 
  267 /* parses a field list from include command or from -f option */
  268 /* returns NULL if not fields */
  269 /* comma is assumed to be escaped as \, */
  270 struct include_field *
  271 parse_include_list(char *list)
  272 {
  273     struct include_field *ret = NULL,*c = NULL;
  274     char *p = list;
  275     char *w = list;
  276     char *s = list;
  277 
  278     if(p == NULL) return NULL;
  279 
  280     while(*p)
  281     {
  282         if(*p == ',' && p[1] == ',')
  283         {
  284             p++;
  285             *w = *p;
  286             w++;
  287             p++;
  288         }
  289         *w = *p;
  290         if(*p == ',' || !p[1])
  291         {
  292             if(p[1]) *w = 0;
  293             if(strlen(s))
  294             {
  295                 if(ret == NULL)
  296                 {
  297                     ret = xmalloc(sizeof(struct include_field));
  298                     c = ret;
  299                 } else
  300                 {
  301                     c->next = xmalloc(sizeof(struct include_field));
  302                     c = c->next;
  303                 }
  304                 c->next = NULL;
  305                 c->name = xstrdup(s);
  306                 c->found = 0;
  307                 c->reported = 0;
  308             }
  309             p++;
  310             while(*p == ',') p++;
  311             s = p;
  312             w = s;
  313             p = s;
  314         } else
  315         {
  316             w++;
  317             p++;
  318         }
  319     }
  320     return ret;
  321 }
  322 
  323 /* start child for command substitution */
  324 /* returns a stream for reading from child */
  325 FILE *
  326 execute_child(char *command)
  327 {
  328     int fds[2];
  329     pid_t pid;
  330     FILE *ret = NULL;
  331 #if defined(HAVE_WORKING_FORK) && defined(HAVE_DUP2) && defined(HAVE_PIPE)
  332     if (pipe(fds) != 0) panic("Cannot create pipe",strerror(errno),NULL);
  333     pid = fork();
  334     if(pid == (pid_t) 0) /* Child */
  335     {
  336         close(fds[0]);
  337         if(dup2(fds[1],STDOUT_FILENO) == -1) panic("dup2 error",strerror(errno),NULL);
  338         if(execl(SHELL_CMD, "sh", "-c", command, NULL) == -1) panic("Starting a shell with execl failed",command,strerror(errno));
  339         close(fds[1]);
  340         _exit(EXIT_SUCCESS);
  341     } else if(pid > (pid_t) 0)
  342     {
  343         close(fds[1]);
  344         ret = fdopen(fds[0],"r");
  345         if(ret == NULL) panic("Cannot read from command",command,strerror(errno));
  346     } else
  347     {
  348         panic("Cannot fork",strerror(errno),NULL);
  349     }
  350 #elif defined(HAVE_TEMPNAM)  /* for win etc. */
  351     cs_temp_file = tempnam(NULL,"ffe");
  352     if(tmpfile == NULL) panic("Temporary file cannot be created",strerror(errno),NULL);
  353     if((size_t) (strlen(command) + 4 + strlen(cs_temp_file)) > command_len)
  354     {
  355         command_len = (size_t) (strlen(command) + 4 + strlen(cs_temp_file));
  356         command = xrealloc(command,command_len);
  357     }
  358     strcat(command," > ");
  359     strcat(command,cs_temp_file);
  360     if(system(command) == -1) panic("Command failed",command,strerror(errno));
  361     ret = fopen(cs_temp_file,"r");
  362     if(ret == NULL) panic("Temporary file cannot be read",cs_temp_file,strerror(errno));
  363 #else
  364     panic("Command substitution is not supported in this system",NULL,NULL);
  365 #endif
  366 #if defined(HAVE_SETMODE) && defined(WIN32)
  367     setmode(fileno(ret),O_TEXT);
  368 #endif
  369     return ret;
  370 }
  371 
  372 
  373 
  374 /* reads a chracter from the rc-file. */
  375 /* if command substition is used, char is read from child process */
  376 int
  377 read_char()
  378 {
  379     int c;
  380     static int char_in_buffer = 0; /* contains the "peeked" char after newline */
  381 
  382     if(child != NULL) 
  383     {
  384         if(char_in_buffer)
  385         {
  386             c = char_in_buffer;
  387             char_in_buffer = 0;
  388         } else
  389         {
  390             c = getc(child);
  391             if(c == '\n')  /* check trailing newlines */
  392             {
  393                 while((c = getc(child)) == '\n');
  394                 if(c != EOF)      /* abandon trailing newlines */
  395                 {
  396                     char_in_buffer = c; /* there is more lines, put c in safe place, return a single newline */
  397                     c = '\n';
  398                 } 
  399             }  /* No else ! */
  400 
  401             if(c == EOF) 
  402             {
  403                 fclose(child);
  404                 if(cs_temp_file) unlink(cs_temp_file);
  405                 cs_temp_file = NULL;
  406                 child = NULL;
  407                 c = read_char();
  408             }
  409         }
  410     } else
  411     {
  412         c = getc(fp);
  413         if(c == '`')  /* command subst. starts */
  414         {
  415             size_t i=0;
  416             do
  417             {
  418                 c = getc(fp);
  419                 command[i++] = c;
  420                 if(i == command_len) 
  421                 {
  422                     command_len = 2*command_len;
  423                     command = xrealloc(command,command_len);
  424                 }
  425             } while(c != '`' && c != EOF);
  426             if(c != '`')
  427             {
  428                 error_in_line();
  429                 panic("No closing '`' in command substition",NULL,NULL);
  430             }
  431             command[--i] = 0;
  432             child = execute_child(command);
  433             c = read_char();
  434         }
  435     }
  436     return c;
  437 }
  438 
  439             
  440 
  441         
  442 /* reading one logical line, returns the status of the line read */
  443 int 
  444 read_logical_line(char **buffer,size_t *bufsize)
  445 {
  446     static char last_eol_char = 0;      /* for what did previous read end */
  447     register char *bp;
  448     int prev_char = 0,c;
  449     int inside_quote = 0;
  450     register int i=0;
  451     int retval = 0;
  452 
  453     bp = *buffer;
  454 
  455     bp[0] = 0;
  456 
  457     switch(last_eol_char)
  458     {
  459         case BLOCK_START:
  460             last_eol_char = 0;
  461             return LL_BLOCK_START;
  462             break;
  463         case BLOCK_END:
  464             last_eol_char = 0;
  465             return LL_BLOCK_END;
  466             break;
  467     }
  468     
  469     do
  470     {
  471         c = read_char();
  472         if(prev_char == '\\')
  473         {
  474             switch(c)
  475             {
  476                 case 'a':
  477                     bp[i] = '\a';
  478                     c = 0;
  479                     i++;
  480                     break;
  481                 case 'b':
  482                     bp[i] = '\b';
  483                     c = 0;
  484                     i++;
  485                     break;
  486                 case 't':
  487                     bp[i] = '\t';
  488                     c = 0;
  489                     i++;
  490                     break;
  491                 case 'n':
  492                     bp[i] = '\n';
  493                     c = 0;
  494                     i++;
  495                     break;
  496                 case 'v':
  497                     bp[i] = '\v';
  498                     c = 0;
  499                     i++;
  500                     break;
  501                 case 'f':
  502                     bp[i] = '\f';
  503                     c = 0;
  504                     i++;
  505                     break;
  506                 case 'r':
  507                     bp[i] = '\r';
  508                     c = 0;
  509                     i++;
  510                     break;
  511                 case '\\':
  512                     bp[i] = '\\';
  513                     c = 0;
  514                     i++;
  515                     break;
  516                 case COMMENT:
  517                     bp[i] = COMMENT;
  518                     c = 0;
  519                     i++;
  520                     break;
  521                 case '\n':    /* newline escaped */
  522                     if(child == NULL) lineno++; 
  523                     bp[i] = read_char();
  524                     c = 0;
  525                     i++;
  526                     break;
  527                 default:
  528                     bp[i] = '\\';
  529                     i++;
  530                     break;
  531             }
  532         } else
  533         {
  534             if(c == '"') inside_quote = !inside_quote;
  535         }
  536         
  537         prev_char = c;
  538                 
  539         if(i >= *bufsize - 10) 
  540         {
  541             *bufsize *= 2;
  542             *buffer = xrealloc(*buffer,*bufsize);
  543             bp = *buffer;
  544         }
  545 
  546         if(inside_quote)
  547         {
  548             switch(c)
  549             {
  550                 case '\\':
  551                 case '\r':  /* skip win32 CR */
  552                 case 0:
  553                     break;
  554                 default:
  555                     bp[i] = (char) c;
  556                     i++;
  557                     break;
  558             }
  559 
  560         } else
  561         {
  562             switch(c)
  563             {
  564                 case COMMENT:
  565                     do
  566                     {
  567                         c = read_char();
  568                     } while (c != '\n' && c != EOF);  /* no break !*/
  569                 case '\n':
  570                     if(c == '\n' && child == NULL) lineno++;
  571                     bp[i] = 0;
  572                     retval = LL_OPTION;
  573                     break;
  574                 case BLOCK_START:
  575                     bp[i] = 0;
  576                     retval = LL_OPTION;
  577                     break;
  578                 case BLOCK_END:
  579                     bp[i] = 0;
  580                     retval = LL_OPTION;
  581                     break;
  582                 case EOF:
  583                     bp[i] = 0;
  584                     retval = LL_OPTION;
  585                     break;
  586                 case '\\':
  587                 case '\r':  /* skip win32 CR */
  588                 case 0:
  589                     break;
  590                 default:
  591                     bp[i] = (char) c;
  592                     i++;
  593                     break;
  594             }
  595         }
  596 
  597         if(retval)
  598         {
  599             trim(bp);
  600             switch(c)
  601             {
  602                 case '\n':
  603                     if(bp[0] == 0) 
  604                     {
  605                         i = 0;          /* empty line */
  606                         retval = 0;
  607                     } else
  608                     {
  609                         return retval;
  610                     }
  611                     break;
  612                 case EOF:
  613                     if(bp[0] == 0)
  614                     {
  615                          retval = LL_EOF;
  616                     }
  617                     return retval;
  618                 case BLOCK_START:
  619                     if(bp[0] == 0)
  620                     {
  621                         retval = LL_BLOCK_START;
  622                     } else
  623                     {
  624                         last_eol_char = c;
  625                     }
  626                     return retval;
  627                 case BLOCK_END:
  628                     if(bp[0] == 0)
  629                     {
  630                         retval = LL_BLOCK_END;
  631                     } else
  632                     {
  633                         last_eol_char = c;
  634                     }
  635                     return retval;
  636                     break;
  637             }
  638         }
  639     } while (1);
  640 }
  641 
  642 #define READ_BUF_SIZE 1024
  643 
  644 /* reads logical lines and parses a one option */
  645 /* option name and parameters are in values-array */
  646 /* return the number of elements in array */
  647 int parse_option(char *buf)
  648 {
  649     register char *rpos = buf;
  650     char *end = buf;
  651     char *param;
  652     register char *p;
  653     int i = 0,j;
  654     int valc = 0;
  655     int quoted;
  656 
  657     values[0] = buf;
  658 
  659     while(*end) end++;
  660 
  661     while(!isspace(*rpos) && *rpos) rpos++;
  662     *rpos = 0;
  663 
  664     p = buf;
  665 
  666     while(*p)  // convert _ to -
  667     {
  668         if(*p == '_') *p = '-';
  669         p++;
  670     }
  671 
  672     while(rc_opts[i].name != NULL && strcmp(rc_opts[i].name,values[0]) != 0) i++;
  673 
  674     if(rc_opts[i].name != NULL)  /* found */
  675     {
  676         param = rc_opts[i].parameters;
  677         while(rpos < end)
  678         {
  679             if(*param)
  680             {
  681                 rpos++;
  682                 while(isspace(*rpos)) rpos++;  /* next non space */
  683                 quoted = 0;
  684                 switch(*param)
  685                 {
  686                     case 'S':
  687                     case 's':
  688                     case 'C':
  689                     case 'c':
  690                         if(*rpos)
  691                         {
  692                             if(*rpos == '"') 
  693                             {
  694                                 rpos++;
  695                                 quoted = 1;
  696                             }
  697                             valc++;
  698                             values[valc] = rpos;
  699                             if(*(param + 1))  /* not the last possible paramter */
  700                             {
  701                                 if(quoted)
  702                                 {
  703                                     j = 0;
  704                                     while(*rpos != '"' && *rpos) 
  705                                     {
  706                                         rpos++;
  707                                         if(*rpos == '"' && *(rpos - 1) == '\\')
  708                                         {
  709                                             j++;
  710                                             *(rpos - j) = *rpos;
  711                                             rpos++;
  712                                         }
  713                                         if(j) *(rpos - j) = *rpos;
  714                                     }
  715                                     if(*rpos != '"')
  716                                     {
  717                                         error_in_line();
  718                                         panic("Quotation not ended",NULL,NULL);
  719                                     }
  720                                     *(rpos - j) = 0;
  721                                     *rpos = 0;
  722                                 } else
  723                                 {
  724                                     while(!isspace(*rpos) && *rpos) rpos++;
  725                                     *rpos=0;
  726                                 }
  727                             } else  /* last parameter, get the rest of the line */
  728                             {
  729                                 j = 0;
  730                                 while(*rpos) 
  731                                 {
  732                                     rpos++;
  733                                     if(*rpos == '"')
  734                                     {
  735                                         if(*(rpos - 1) == '\\')
  736                                         {
  737                                             j++;
  738                                             *(rpos - j) = *rpos;
  739                                             rpos++;
  740                                             if(!*rpos)
  741                                             {
  742                                                 error_in_line();
  743                                                 panic("Quotation not ended",NULL,NULL);
  744                                             }
  745                                         } else if(*(rpos + 1) && quoted)
  746                                         {
  747                                             error_in_line();
  748                                             panic("Too many parameters",values[0],NULL);
  749                                         }
  750                                     }
  751                                     if(j && *rpos) *(rpos - j) = *rpos;
  752                                 }
  753                                 if(quoted)
  754                                 {
  755                                     if(*(rpos - 1) != '"')
  756                                     {
  757                                         error_in_line();
  758                                         panic("Quotation not ended",NULL,NULL);
  759                                     }
  760                                     *(rpos - j - 1) = 0;
  761                                 } else
  762                                 {
  763                                     *(rpos - j) = 0;
  764                                 }
  765                                 *rpos = 0;
  766                             }  
  767                             if((*param == 'C' || *param == 'c') && values[valc][1])
  768                             {
  769                                 error_in_line();
  770                                 panic("Single character parameter expected",values[0],NULL);
  771                             } 
  772                         } else
  773                         {
  774                             if(*param == 'S' || *param == 'C')
  775                             {
  776                                 error_in_line();
  777                                 panic("Mandatory parameter missing",values[0],NULL);
  778                             }
  779                         }
  780                         break;
  781                     case 'N':
  782                     case 'n':
  783                         if(*rpos)
  784                         {
  785                             valc++;
  786                             values[valc] = rpos;
  787                             if(*rpos == '*' && (isspace(rpos[1]) || !rpos[1]))
  788                             {
  789                                 rpos++;
  790                                 *rpos=0;
  791                             } else
  792                             {
  793                                 if (*rpos == '-') rpos++;
  794                                 while(isdigit(*rpos)) rpos++;
  795                                 if(!isspace(*rpos) && *rpos)
  796                                 {
  797                                     error_in_line();
  798                                     panic("A number expected",values[0],NULL);
  799                                 }
  800                                 *rpos=0;
  801                             }
  802                         } else
  803                         {
  804                             if(*param == 'N')
  805                             {
  806                                 error_in_line();
  807                                 panic("Mandatory parameter missing",values[0],NULL);
  808                             }
  809                         }
  810                         break;
  811                 }
  812                 if(valc > 6)
  813                 {
  814                     error_in_line();
  815                     panic("Too many parameters",values[0],NULL);
  816                 }
  817             } else
  818             {
  819                 error_in_line();
  820                 panic("Too many parameters",values[0],NULL);
  821             }
  822             param++;
  823         }
  824         if(isupper(*param))
  825         {
  826             error_in_line();
  827             panic("Mandatory parameter missing",values[0],NULL);
  828         }
  829     } else
  830     {
  831         error_in_line();
  832         panic("Unknown option",values[0],NULL);
  833     }
  834     return valc;
  835 }
  836 
  837 /* expand tilde in path */
  838 char *
  839 expand_home(char *path)
  840 {
  841     char *r;
  842     char *home = getenv("HOME");
  843 
  844     if(*path == '~' && strncmp(&path[1],PATH_SEPARATOR_STRING,strlen(PATH_SEPARATOR_STRING)) == 0 && home != NULL)
  845     {
  846         r = xmalloc(strlen(home) + strlen(path));
  847         strcpy(r,home);
  848         strcat(r,&path[1]);
  849     } else
  850     {
  851         r = xstrdup(path);
  852     }
  853     return r;
  854 }
  855 
  856 
  857 /* read key value pairs from file */
  858 /* to struct lookup data chain */
  859 void
  860 read_lookup_from_file(struct lookup_data **data,char *file,char separator)
  861 {
  862     FILE *fp;
  863     register int line_len;
  864     size_t max_line_size = 1024;
  865     char *efile;
  866     char *line;
  867     register char *p;
  868     struct lookup_data *c_data;
  869 
  870     efile = expand_home(file);
  871     
  872     fp = xfopen(efile,"r");
  873 
  874     line = xmalloc(max_line_size);
  875 
  876     do
  877     {
  878 #ifdef HAVE_GETLINE
  879         line_len = getline(&line,&max_line_size,fp);
  880 #else
  881         if(fgets(line,max_line_size,fp) == NULL)
  882         {
  883             line_len = -1;
  884         } else
  885         {
  886             line_len = strlen(line);
  887         }
  888 #endif
  889         if(line_len > 0)
  890         {
  891             switch(line[line_len - 1])  // remove newline
  892             {
  893                 case '\n':
  894                 case '\r':
  895                     line[line_len - 1] = 0;
  896                     break;
  897             }
  898             
  899             p = line;
  900             while(*p && *p != separator) p++;
  901             if(*p)
  902             {
  903                 *p = 0;
  904                 p++;
  905 
  906                 c_data = data[hash(line,0)];
  907 
  908                 if(c_data == NULL) 
  909                 {
  910                     c_data = xmalloc(sizeof(struct lookup_data));
  911                     data[hash(line,0)] = c_data;
  912                 } else
  913                 {
  914                     while(c_data->next != NULL) c_data = c_data->next;
  915 
  916                     c_data->next = xmalloc(sizeof(struct lookup_data));
  917                     c_data = c_data->next;
  918                 }
  919                 c_data->next = NULL;
  920                 c_data->key = xstrdup(line);
  921                 c_data->value = xstrdup(p);
  922             }
  923         }
  924     } while(line_len != -1);
  925     fclose(fp);
  926     free(line);
  927     free(efile);
  928 }
  929 
  930 /* non printable characters in form \xnn will be expanded 
  931    returns id length
  932 */
  933 int
  934 expand_non_print(char *s,uint8_t **t)
  935 {
  936     char num[5];
  937     char *w;
  938     int c,len;
  939 
  940     num[0] = '0';
  941     num[1] = 'x';
  942     num[4] = 0;
  943     len = 0;
  944     
  945     *t = xstrdup(s);
  946     w = *t;
  947 
  948     while(*s)
  949     {
  950         if(*s == '\\' && s[1] == 'x' && isxdigit((int) s[2]) && isxdigit((int) s[3]))
  951         {
  952             num[2] = s[2];
  953             num[3] = s[3];
  954             sscanf(num,"%i",&c);
  955             *w = (char) c;
  956             s += 3;
  957         } else
  958         {
  959             *w = *s;
  960         }
  961         s++;
  962         w++;
  963         len++;
  964     }
  965     *w = 0;
  966     return len;
  967 }
  968 
  969 /* Parse non numeric field type */
  970     void
  971 parse_field_type(char *t,struct field *f)
  972 {
  973     if(strcmp(t,"char") == 0)
  974     {
  975         f->type = F_CHAR;
  976         f->length = sizeof(char);
  977         f->endianess = system_endianess;
  978     } else if(strcmp(t,"short") == 0)
  979     {
  980         f->type = F_INT;
  981         f->length = sizeof(short int);
  982         f->endianess = system_endianess;
  983     } else if(strcmp(t,"int") == 0) 
  984     {
  985         f->type = F_INT;
  986         f->length = sizeof(int);
  987         f->endianess = system_endianess;
  988     } else if(strcmp(t,"long") == 0) 
  989     {
  990         f->type = F_INT;
  991         f->length = sizeof(long int);
  992         f->endianess = system_endianess;
  993     } else if(strcmp(t,"llong") == 0) 
  994     {
  995         f->type = F_INT;
  996         f->length = sizeof(long long int);
  997         f->endianess = system_endianess;
  998     } else if(strcmp(t,"ushort") == 0)
  999     {
 1000         f->type = F_UINT;
 1001         f->length = sizeof(unsigned short int);
 1002         f->endianess = system_endianess;
 1003     } else if(strcmp(t,"uint") == 0) 
 1004     {
 1005         f->type = F_UINT;
 1006         f->length = sizeof(unsigned int);
 1007         f->endianess = system_endianess;
 1008     } else if(strcmp(t,"ulong") == 0) 
 1009     {
 1010         f->type = F_UINT;
 1011         f->length = sizeof(unsigned long int);
 1012         f->endianess = system_endianess;
 1013     } else if(strcmp(t,"ullong") == 0) 
 1014     {
 1015         f->type = F_UINT;
 1016         f->length = sizeof(long long int);
 1017         f->endianess = system_endianess;
 1018     } else if(strcmp(t,"float") == 0) 
 1019     {
 1020         f->type = F_FLOAT;
 1021         f->length = sizeof(float);
 1022         f->endianess = system_endianess;
 1023     } else if(strcmp(t,"float_be") == 0) 
 1024     {
 1025         f->type = F_FLOAT;
 1026         f->length = sizeof(float);
 1027         f->endianess = F_BIG_ENDIAN;
 1028     } else if(strcmp(t,"float_le") == 0) 
 1029     {
 1030         f->type = F_FLOAT;
 1031         f->length = sizeof(float);
 1032         f->endianess = F_LITTLE_ENDIAN;
 1033     } else if(strcmp(t,"double") == 0) 
 1034     {
 1035         f->type = F_DOUBLE;
 1036         f->length = sizeof(double);
 1037         f->endianess = system_endianess;
 1038     } else if(strcmp(t,"double_be") == 0) 
 1039     {
 1040         f->type = F_DOUBLE;
 1041         f->length = sizeof(double);
 1042         f->endianess = F_BIG_ENDIAN;
 1043     } else if(strcmp(t,"double_le") == 0) 
 1044     {
 1045         f->type = F_DOUBLE;
 1046         f->length = sizeof(double);
 1047         f->endianess = F_LITTLE_ENDIAN;
 1048     } else if(strcmp(t,"int8") == 0)
 1049     {
 1050         f->type = F_INT;
 1051         f->length = 1;
 1052         f->endianess = system_endianess;
 1053     } else if(strcmp(t,"int16_be") == 0) 
 1054     {
 1055         f->type = F_INT;
 1056         f->length = 2;
 1057         f->endianess = F_BIG_ENDIAN;
 1058     } else if(strcmp(t,"int16_le") == 0) 
 1059     {
 1060         f->type = F_INT;
 1061         f->length = 2;
 1062         f->endianess = F_LITTLE_ENDIAN;
 1063     } else if(strcmp(t,"int32_be") == 0) 
 1064     {
 1065         f->type = F_INT;
 1066         f->length = 4;
 1067         f->endianess = F_BIG_ENDIAN;
 1068     } else if(strcmp(t,"int32_le") == 0) 
 1069     {
 1070         f->type = F_INT;
 1071         f->length = 4;
 1072         f->endianess = F_LITTLE_ENDIAN;
 1073     } else if(strcmp(t,"int64_be") == 0) 
 1074     {
 1075         f->type = F_INT;
 1076         f->length = 8;
 1077         f->endianess = F_BIG_ENDIAN;
 1078     } else if(strcmp(t,"int64_le") == 0) 
 1079     {
 1080         f->type = F_INT;
 1081         f->length = 8;
 1082         f->endianess = F_LITTLE_ENDIAN;
 1083     } else if(strcmp(t,"uint8") == 0)
 1084     {
 1085         f->type = F_UINT;
 1086         f->length = 1;
 1087         f->endianess = system_endianess;
 1088     } else if(strcmp(t,"uint16_be") == 0) 
 1089     {
 1090         f->type = F_UINT;
 1091         f->length = 2;
 1092         f->endianess = F_BIG_ENDIAN;
 1093     } else if(strcmp(t,"uint16_le") == 0) 
 1094     {
 1095         f->type = F_UINT;
 1096         f->length = 2;
 1097         f->endianess = F_LITTLE_ENDIAN;
 1098     } else if(strcmp(t,"uint32_be") == 0) 
 1099     {
 1100         f->type = F_UINT;
 1101         f->length = 4;
 1102         f->endianess = F_BIG_ENDIAN;
 1103     } else if(strcmp(t,"uint32_le") == 0) 
 1104     {
 1105         f->type = F_UINT;
 1106         f->length = 4;
 1107         f->endianess = F_LITTLE_ENDIAN;
 1108     } else if(strcmp(t,"uint64_be") == 0) 
 1109     {
 1110         f->type = F_UINT;
 1111         f->length = 8;
 1112         f->endianess = F_BIG_ENDIAN;
 1113     } else if(strcmp(t,"uint64_le") == 0) 
 1114     {
 1115         f->type = F_UINT;
 1116         f->length = 8;
 1117         f->endianess = F_LITTLE_ENDIAN;
 1118     } else if(strncmp(t,"bcd_be_",7) == 0) 
 1119     {
 1120         f->type = F_BCD;
 1121         if(is_digit(&t[7])) sscanf(&t[7],"%i",&f->length);
 1122         f->endianess = F_BIG_ENDIAN;
 1123     } else if(strncmp(t,"bcd_le_",7) == 0) 
 1124     {
 1125         f->type = F_BCD;
 1126         if(is_digit(&t[7])) sscanf(&t[7],"%i",&f->length);
 1127         f->endianess = F_LITTLE_ENDIAN;
 1128     } else if (strncmp(t,"hex_be_",7) == 0)
 1129     {
 1130         f->type = F_HEX;
 1131         if(is_digit(&t[7])) sscanf(&t[7],"%i",&f->length);
 1132         f->endianess = F_BIG_ENDIAN;
 1133     } else if (strncmp(t,"hex_le_",7) == 0)
 1134     {
 1135         f->type = F_HEX;
 1136         if(is_digit(&t[7])) sscanf(&t[7],"%i",&f->length);
 1137         f->endianess = F_LITTLE_ENDIAN;
 1138     } else
 1139     {
 1140         error_in_line();
 1141         panic("Unknown field type",t,NULL);
 1142     }
 1143 
 1144     if(f->length < 1)
 1145     {
 1146         error_in_line();
 1147         panic("Error in field type",t,NULL);
 1148     }
 1149 }
 1150 
 1151 /* parse status values */
 1152 #define PS_MAIN 1
 1153 #define PS_STRUCT 2
 1154 #define PS_RECORD 3
 1155 #define PS_OUTPUT 4
 1156 #define PS_W_STRUCT 5
 1157 #define PS_W_RECORD 6
 1158 #define PS_W_OUTPUT 7
 1159 #define PS_LOOKUP 8
 1160 #define PS_W_LOOKUP 9
 1161 #define PS_ANON 10
 1162 #define PS_W_ANON 11
 1163 
 1164 void
 1165 print_info()
 1166 {
 1167     struct structure *s = structure;
 1168     struct record *r;
 1169     struct field *f;
 1170     int pos;
 1171 
 1172     while(s != NULL)
 1173     {
 1174         printf("Structure %s - ",s->name);
 1175         switch(s->type[0])
 1176         {
 1177             case BINARY:
 1178                 printf("binary");
 1179                 break;
 1180             case FIXED_LENGTH:
 1181                 printf("fixed length");
 1182                 break;
 1183             case SEPARATED:
 1184                 printf("separated by '%c'",(int) s->type[1]);
 1185                 break;
 1186         }
 1187         printf(" - %d\n",s->max_record_len);
 1188 
 1189         r = s->r;
 1190         while(r != NULL)
 1191         {
 1192             f = r->f;
 1193             pos = 1;
 1194             printf("  Record %s  %d%s\n",r->name,r->length,r->length_field_name != NULL ? "+" : "");
 1195             while(f != NULL)
 1196             {
 1197                 if(s->type[0] == SEPARATED)
 1198                 {
 1199                     printf("    Field %-30s%5d%5d\n",f->name == NULL ? "*" : f->name,pos,f->length);
 1200                     pos++;
 1201                 } else
 1202                 {
 1203                     printf("    Field %-30s%5d%5d\n",f->name,pos,f->length);
 1204                     pos += f->length;
 1205                 }
 1206                 f = f->next;
 1207             }
 1208             r = r->next;
 1209             printf("\n");
 1210         }
 1211         s = s->next;
 1212         printf("\n\n");
 1213     }
 1214 }
 1215 
 1216 struct format *
 1217 parse_conversion(char *conv_spec)
 1218 {
 1219     struct format *ret = NULL;
 1220     int argtypes[2];
 1221 
 1222 #ifdef HAVE_PARSE_PRINTF_FORMAT
 1223     if(conv_spec != NULL && parse_printf_format(conv_spec,2,argtypes) == 1 && !(argtypes[0] & PA_FLAG_PTR))
 1224     {
 1225         ret = xmalloc(sizeof(struct format));
 1226         ret->conversion = xstrdup(conv_spec);
 1227         ret->type = argtypes[0];
 1228     }
 1229 #else
 1230     error_in_line();
 1231     panic("printf style formatting not supported in this system (function parse_printf_format missing)",NULL,NULL);
 1232 #endif
 1233 
 1234     
 1235     return ret;
 1236 }
 1237 
 1238 
 1239 
 1240 void 
 1241 parserc(char *rcfile,char *include_field_list)
 1242 {
 1243     struct structure *c_structure = structure;
 1244     struct field *c_field = NULL;
 1245     struct pipe *c_pipe = NULL;
 1246     struct id *c_id =  NULL;
 1247     struct record *c_record = NULL;
 1248     struct output *c_output = output;
 1249     struct lookup *c_lookup = NULL;
 1250     struct lookup_data *c_lookup_data = NULL;
 1251     struct include_field *fl = parse_include_list(include_field_list);
 1252     struct anon_field *c_anon = anonymize;
 1253 
 1254     char *read_buffer;
 1255     size_t read_buffer_size;
 1256     int line_status;
 1257     int status = PS_MAIN;
 1258     int opt_count;
 1259     int field_count;
 1260     char anon_name[100];
 1261 
 1262     open_rc_file(rcfile);
 1263 
 1264     read_buffer_size = READ_BUF_SIZE;
 1265     read_buffer = xmalloc(read_buffer_size);
 1266     command = xmalloc(command_len);         /* used in command substituion */
 1267 
 1268 #ifdef HAVE_ATEXIT
 1269     atexit(remove_temp_file); /* remove possible temp-file */
 1270 #endif
 1271 
 1272     if(c_structure != NULL) while(c_structure->next != NULL) c_structure = c_structure->next;
 1273 
 1274     if(c_output != NULL) while(c_output->next != NULL) c_output = c_output->next;
 1275 
 1276     while((line_status = read_logical_line(&read_buffer,&read_buffer_size)) != LL_EOF)
 1277     {
 1278         switch(line_status)
 1279         {
 1280             case LL_OPTION:
 1281                 opt_count = parse_option(read_buffer);
 1282                 switch(status)
 1283                 {
 1284                     case PS_MAIN:
 1285                         if(strcmp(values[0],N_STRUCTURE) == 0)
 1286                         {
 1287                             if(structure == NULL)
 1288                             {
 1289                                 c_structure = xmalloc(sizeof(struct structure));
 1290                                 structure = c_structure;
 1291                             } else
 1292                             {
 1293                                 c_structure->next = xmalloc(sizeof(struct structure));
 1294                                 c_structure = c_structure->next;
 1295                             }
 1296                             c_structure->next = NULL;
 1297                             c_structure->name = xstrdup(values[1]);
 1298                             c_structure->type[0] = FIXED_LENGTH;
 1299                             c_structure->quote = 0;
 1300                             c_structure->header = 0;
 1301                             c_structure->output_name = NULL;
 1302                             c_structure->vote = 0;
 1303                             c_structure->o = NULL;
 1304                             c_structure->r = NULL;
 1305                             status = PS_W_STRUCT;
 1306                         } else if(strcmp(values[0],N_OUTPUT) == 0)
 1307                         {
 1308                             if(c_output == NULL)
 1309                             {
 1310                                 c_output = xmalloc(sizeof(struct output));
 1311                                 output = c_output;
 1312                             } else
 1313                             {
 1314                                 c_output->next = xmalloc(sizeof(struct output));
 1315                                 c_output = c_output->next;
 1316                             }
 1317                             c_output->next = NULL;
 1318                             c_output->name = xstrdup(values[1]);
 1319                             c_output->file_header = NULL;
 1320                             c_output->file_trailer = NULL;
 1321                             c_output->header = NULL;
 1322                             c_output->data = "%d";
 1323                             c_output->lookup = NULL;
 1324                             c_output->separator = NULL;
 1325                             c_output->record_header = NULL;
 1326                             c_output->record_trailer = "\n";
 1327                             c_output->group_header = NULL;
 1328                             c_output->group_trailer = NULL;
 1329                             c_output->element_header = NULL;
 1330                             c_output->element_trailer = NULL;
 1331                             c_output->justify = LEFT_JUSTIFY;
 1332                             c_output->indent = NULL;
 1333                             c_output->no_data = 1;
 1334                             c_output->hex_cap = 0;
 1335                             c_output->empty_chars = " \f\n\r\t\v";
 1336                             c_output->print_empty = 1;
 1337                             c_output->output_file = NULL;
 1338                             c_output->ofp = NULL;
 1339                             if(fl != NULL)
 1340                             {
 1341                                 c_output->fl = fl;
 1342                             } else
 1343                             {
 1344                                 c_output->fl = NULL;
 1345                             }
 1346                             status = PS_W_OUTPUT;
 1347                         } else if(strcmp(values[0],N_LOOKUP) == 0)
 1348                         {
 1349                             register int i;
 1350                             if(c_lookup == NULL)
 1351                             {
 1352                                 c_lookup = xmalloc(sizeof(struct lookup));
 1353                                 lookup = c_lookup;
 1354                             } else
 1355                             {
 1356                                 c_lookup->next = xmalloc(sizeof(struct lookup));
 1357                                 c_lookup = c_lookup->next;
 1358                             }
 1359                             c_lookup->next = NULL;
 1360                             c_lookup->name = xstrdup(values[1]);
 1361                             c_lookup->type = EXACT;
 1362                             c_lookup->default_value = "";
 1363                             for(i = 0;i < MAX_EXPR_HASH;i++) c_lookup->data[i] = NULL;
 1364                             status = PS_W_LOOKUP;
 1365                         } else if(strcmp(values[0],N_CONST) == 0)
 1366                         {
 1367                             if(const_field == NULL)
 1368                             {
 1369                                 c_field = xmalloc(sizeof(struct field));
 1370                                 const_field = c_field;
 1371                             } else
 1372                             {
 1373                                 c_field = const_field;
 1374                                 while(c_field->next != NULL) c_field = c_field->next;
 1375                                 c_field->next = xmalloc(sizeof(struct field));
 1376                                 c_field = c_field->next;
 1377                             }
 1378                             c_field->lookup_table_name = NULL;
 1379                             c_field->lookup = NULL;
 1380                             c_field->rep = NULL;
 1381                             c_field->next = NULL;
 1382                             c_field->name = xstrdup(values[1]);
 1383                             c_field->const_data = xstrdup(values[2]);
 1384                             c_field->position = 0;
 1385                             c_field->length = strlen(c_field->const_data);
 1386                             c_field->o = NULL;
 1387                             c_field->f = NULL;
 1388                         } else if(strcmp(values[0],N_PIPE) == 0)
 1389                         { 
 1390                             if (pipes == NULL)
 1391                             {
 1392                                 c_pipe = xmalloc(sizeof(struct pipe));
 1393                                 pipes = c_pipe;
 1394                             } else
 1395                             {
 1396                                 c_pipe->next = xmalloc(sizeof(struct pipe));
 1397                                 c_pipe = c_pipe->next;
 1398                             }
 1399                             c_pipe->next = NULL;
 1400                             c_pipe->name = xstrdup(values[1]);
 1401                             c_pipe->command = xstrdup(values[2]);
 1402                         } else if(strcmp(values[0],N_ANON) == 0)
 1403                         {
 1404                             strcpy(anon_name,values[1]);
 1405                             status = PS_W_ANON;
 1406                         } else 
 1407                         {
 1408                             error_in_line();
 1409                             panic("Option not inside structure, output or lookup",values[0],NULL);
 1410                         }
 1411                         break;
 1412                     case PS_STRUCT:
 1413                         if(strcmp(values[0],N_TYPE) == 0)
 1414                         {
 1415                             if(strcmp(values[1],"fixed") == 0)
 1416                             {
 1417                                 c_structure->type[0] = FIXED_LENGTH;
 1418                                 if(opt_count > 1)
 1419                                 {
 1420                                     error_in_line();
 1421                                     panic("too many parameters for",values[0],NULL);
 1422                                 }
 1423                             } else if(strcmp(values[1],"separated") == 0)
 1424                             {
 1425                                 c_structure->type[0] = SEPARATED;
 1426                                 c_structure->type[1] = ',';
 1427                                 c_structure->type[2] = 0;
 1428 
 1429                                 if(opt_count > 1)
 1430                                 {
 1431                                     c_structure->type[1] = values[2][0];
 1432                                 }
 1433                                 if(opt_count > 2)
 1434                                 {
 1435                                     if(values[3][0] == '*')
 1436                                     {
 1437                                         c_structure->type[2] = values[3][0];
 1438                                     } else
 1439                                     {
 1440                                         error_in_line();
 1441                                         panic("An \'*\' is expected",values[0],NULL);
 1442                                     }
 1443                                 }
 1444                             } else if(strcmp(values[1],"binary") == 0)
 1445                             {
 1446                                 c_structure->type[0] = BINARY;
 1447                                 if(opt_count > 1)
 1448                                 {
 1449                                     error_in_line();
 1450                                     panic("too many parameters for",values[0],NULL);
 1451                                 }
 1452                             } else
 1453                             {
 1454                                 error_in_line();
 1455                                 panic("Unknown type",NULL,NULL);
 1456                             }
 1457                         } else if(strcmp(values[0],N_HEADER) == 0)
 1458                         {
 1459                             if(strcmp(values[1],"first") == 0)
 1460                             {
 1461                                 c_structure->header = HEADER_FIRST;
 1462                             } else if(strcmp(values[1],"all") == 0)
 1463                             {
 1464                                 c_structure->header = HEADER_ALL;
 1465                             } else if(strcmp(values[1],"no") == 0)
 1466                             {
 1467                                 c_structure->header = 0;
 1468                             } else
 1469                             {
 1470                                 error_in_line();
 1471                                 panic("first, all or no expected",NULL,NULL);
 1472                             }
 1473                         } else if(strcmp(values[0],N_OUTPUT) == 0)
 1474                         {
 1475                             c_structure->output_name = xstrdup(values[1]);
 1476                         } else if(strcmp(values[0],N_RECORD) == 0)
 1477                         {
 1478                             if(c_structure->r == NULL)
 1479                             {
 1480                                 c_record = xmalloc(sizeof(struct record));
 1481                                 c_structure->r = c_record;
 1482                             } else
 1483                             {
 1484                                 c_record->next = xmalloc(sizeof(struct record));
 1485                                 c_record = c_record->next;
 1486                             }
 1487                             c_record->next = NULL;
 1488                             c_record->name = xstrdup(values[1]);
 1489                             c_record->i = NULL;
 1490                             c_record->f = NULL;
 1491                             c_record->fields_from = NULL;
 1492                             c_record->o = NULL;
 1493                             c_record->output_name = NULL;
 1494                             c_record->vote = 0;
 1495                             c_record->arb_length = RL_STRICT;
 1496                             c_record->var_length_adjust = 0;
 1497                             c_record->length_field_name = NULL;
 1498                             c_record->length_field = NULL;
 1499                             c_record->var_field_name = NULL;
 1500                             c_record->level = NULL;
 1501                             status = PS_W_RECORD;
 1502                         } else if(strcmp(values[0],N_QUOTE) == 0)
 1503                         {
 1504                             if(opt_count > 0)
 1505                             {
 1506                                 c_structure->quote = values[1][0];
 1507                             } else
 1508                             {
 1509                                 c_structure->quote = '"';
 1510                             }
 1511                         } else
 1512                         {
 1513                             error_in_line();
 1514                             panic("Unknown option in structure",NULL,NULL);
 1515                         }
 1516                         break;
 1517                     case PS_RECORD:
 1518                         if(strcmp(values[0],N_ID) == 0 || strcmp(values[0],N_RID) == 0)
 1519                         {
 1520                             if(c_record->i == NULL)
 1521                             {
 1522                                 c_id = xmalloc(sizeof(struct id));
 1523                                 c_record->i = c_id;
 1524                             } else
 1525                             {
 1526                                 c_id->next = xmalloc(sizeof(struct id));
 1527                                 c_id = c_id->next;
 1528                             }
 1529                             c_id->next = NULL;
 1530                             c_id->regexp = 0;
 1531                             if(sscanf(values[1],"%d",&c_id->position) != 1)
 1532                             {
 1533                                 error_in_line();
 1534                                 panic("Error in number",NULL,NULL);
 1535                             }
 1536                             if(c_id->position < 1)
 1537                             {
 1538                                 error_in_line();
 1539                                 panic("Position must be greater than zero",NULL,NULL);
 1540                             }
 1541                             c_id->length = expand_non_print(values[2],&c_id->key);
 1542                             if(strcmp(values[0],N_RID) == 0)
 1543                             {
 1544 #ifdef HAVE_REGEX
 1545                                 int rc,buflen;
 1546                                 char *errbuf;
 1547 
 1548                                 rc = regcomp(&c_id->reg,c_id->key,REG_EXTENDED | REG_NOSUB);
 1549                                 if(rc)
 1550                                 {
 1551                                     buflen = regerror(rc,&c_id->reg,NULL,0);
 1552                                     errbuf = xmalloc(buflen + 1);
 1553                                     regerror(rc,&c_id->reg,errbuf,buflen);
 1554                                     error_in_line();
 1555                                     panic("Error in regular expression",c_id->key,errbuf);
 1556                                 }
 1557                                 c_id->regexp = 1;
 1558 #else
 1559                                 error_in_line();
 1560                                 panic("Regular expressions are not supported in this system",NULL,NULL);
 1561 #endif
 1562                             }
 1563                         } else if(strcmp(values[0],N_FIELD) == 0)
 1564                         {
 1565                             if(c_record->f == NULL)
 1566                             {
 1567                                 c_field = xmalloc(sizeof(struct field));
 1568                                 c_record->f = c_field;
 1569                             } else
 1570                             {
 1571                                 c_field->next = xmalloc(sizeof(struct field));
 1572                                 c_field = c_field->next;
 1573                             }
 1574                             c_field->lookup_table_name = NULL;
 1575                             c_field->lookup = NULL;
 1576                             c_field->rep = NULL;
 1577                             c_field->type = F_ASC;
 1578                             c_field->next = NULL;
 1579                             c_field->const_data = NULL;
 1580                             c_field->length = 0;
 1581                             c_field->var_length = 0;
 1582                             c_field->output_name = NULL;
 1583                             c_field->o = NULL;
 1584                             c_field->pipe_name = NULL;
 1585                             c_field->p = NULL;
 1586                             c_field->a = NULL;
 1587                             c_field->f = NULL;
 1588 
 1589                             if(values[1][0] == '*' && !values[1][1])
 1590                             {
 1591                                 c_field->name = NULL;
 1592                             } else
 1593                             {
 1594                                 c_field->name = xstrdup(values[1]);
 1595                             }
 1596                             if(opt_count > 1)
 1597                             {
 1598                                 if(!(values[2][0] == '*' && !values[2][1]))
 1599                                 {
 1600                                     if(is_digit(values[2]))
 1601                                     {
 1602                                         sscanf(values[2],"%d",&c_field->length);
 1603                                     } else
 1604                                     {
 1605                                         parse_field_type(values[2],c_field);
 1606                                     }
 1607                                 }
 1608                                 if(opt_count > 2)
 1609                                 {
 1610                                     if(!(values[3][0] == '*' && !values[3][1]))
 1611                                     {
 1612                                         c_field->lookup_table_name = xstrdup(values[3]);
 1613                                     }
 1614                                     if(opt_count > 3)
 1615                                     {
 1616                                         if(!(values[4][0] == '*' && !values[4][1]))
 1617                                         {
 1618                                             c_field->output_name = xstrdup(values[4]);
 1619                                         }
 1620                                         if(opt_count > 4)
 1621                                         {
 1622                                             if(!(values[5][0] == '*' && !values[5][1]))
 1623                                             {
 1624                                                 c_field->pipe_name = xstrdup(values[5]);
 1625                                             }
 1626                                             if(opt_count > 5)
 1627                                             {
 1628                                                 c_field->f = parse_conversion(values[6]);
 1629                                                 if(c_field->f == NULL) 
 1630                                                 {
 1631 
 1632                                                     error_in_line();
 1633                                                     panic("Invalid conversion syntax",values[6],NULL);
 1634                                                 }
 1635                                             }
 1636                                         }
 1637 
 1638                                     }
 1639                                 }
 1640                                 
 1641                             } 
 1642                         } else if(strcmp(values[0],N_FIELDSFROM) == 0)
 1643                         {
 1644                             c_record->fields_from = xstrdup(values[1]);
 1645                         } else if(strcmp(values[0],N_OUTPUT) == 0)
 1646                         {
 1647                             c_record->output_name = xstrdup(values[1]);
 1648                         } else if(strcmp(values[0],N_FIELD_COUNT) == 0)
 1649                         {
 1650                             field_count = atoi(values[1]);
 1651                             while(field_count--)
 1652                             {
 1653                                 if(c_record->f == NULL)
 1654                                 {
 1655                                     c_field = xmalloc(sizeof(struct field));
 1656                                     c_record->f = c_field;
 1657                                 } else
 1658                                 {
 1659                                     c_field->next = xmalloc(sizeof(struct field));
 1660                                     c_field = c_field->next;
 1661                                 }
 1662                                 c_field->lookup_table_name = NULL;
 1663                                 c_field->lookup = NULL;
 1664                                 c_field->rep = NULL;
 1665                                 c_field->next = NULL;
 1666                                 c_field->const_data = NULL;
 1667                                 c_field->length = 0;
 1668                                 c_field->var_length = 0;
 1669                                 c_field->name = NULL;
 1670                                 c_field->output_name = NULL;
 1671                                 c_field->o = NULL;
 1672                                 c_field->p = NULL;
 1673                                 c_field->a = NULL;
 1674                                 c_field->f = NULL;
 1675                                 c_field->pipe_name = NULL;
 1676                             }
 1677                         } else if(strcmp(values[0],N_LEVEL) == 0)
 1678                         {
 1679                             c_record->level = xmalloc(sizeof(struct level));
 1680                             c_record->level->element_name = NULL;
 1681                             c_record->level->group_name = NULL;
 1682                             c_record->level->level = atoi(values[1]);
 1683                             c_record->level->indent_count = 0;
 1684                             if (c_record->level->level < 1 || c_record->level->level > MAXLEVEL)
 1685                             {
 1686                                 error_in_line();
 1687                                 panic("Invalid level value",NULL,NULL);
 1688                             }
 1689                             if(opt_count > 1 && strcmp(values[2],"*") != 0)
 1690                             {
 1691                                 c_record->level->element_name = xstrdup(values[2]);
 1692                                 c_record->level->indent_count++;
 1693                             }
 1694                             if(opt_count > 2)
 1695                             {
 1696                                 c_record->level->group_name = xstrdup(values[3]);
 1697                                 c_record->level->indent_count++;
 1698                             }
 1699                         } else if(strcmp(values[0],N_RECORD_LENGTH) == 0)
 1700                         {
 1701                             if(strcmp(values[1],"strict") == 0)
 1702                             {
 1703                                 c_record->arb_length = RL_STRICT;
 1704                             } else if(strcmp(values[1],"minimum") == 0)
 1705                             {
 1706                                 c_record->arb_length = RL_MIN;
 1707                             } else
 1708                             {
 1709                                 error_in_line();
 1710                                 panic("Unknown option value in record",NULL,NULL);
 1711                             }
 1712                         } else if(strcmp(values[0],N_VARLEN) == 0)                      
 1713                         {
 1714                             c_record->length_field_name = strdup(values[1]);
 1715                             c_record->var_field_name  = strdup(values[2]);
 1716                             if(opt_count > 2) sscanf(values[3],"%d",&c_record->var_length_adjust);
 1717                         } else
 1718                         {
 1719                             error_in_line();
 1720                             panic("Unknown option in record",NULL,NULL);
 1721                         }
 1722                         break;
 1723                     case PS_OUTPUT:
 1724                         if(strcmp(values[0],N_FILE_HEADER) == 0)
 1725                         {
 1726                             c_output->file_header = xstrdup(values[1]);
 1727                         } else if(strcmp(values[0],N_FILE_TRAILER) == 0)
 1728                         {
 1729                             c_output->file_trailer = xstrdup(values[1]);
 1730                         } else if(strcmp(values[0],N_HEADER) == 0)
 1731                         {
 1732                             c_output->header = xstrdup(values[1]);
 1733                         } else if(strcmp(values[0],N_DATA) == 0)
 1734                         {
 1735                             c_output->data = xstrdup(values[1]);
 1736                         } else if (strcmp(values[0],N_LOOKUP) == 0)
 1737                         {
 1738                             c_output->lookup = xstrdup(values[1]);
 1739                         } else if(strcmp(values[0],N_SEPARATOR) == 0)
 1740                         {
 1741                             c_output->separator = xstrdup(values[1]);
 1742                         } else if(strcmp(values[0],N_RECORD_HEADER) == 0)
 1743                         {
 1744                             c_output->record_header = xstrdup(values[1]);
 1745                         } else if(strcmp(values[0],N_RECORD_TRAILER) == 0)
 1746                         {
 1747                             if (values[1][0])
 1748                             {
 1749                                 c_output->record_trailer = xstrdup(values[1]);
 1750                             } else
 1751                             {
 1752                                 c_output->record_trailer = NULL;
 1753                             }
 1754                         } else if(strcmp(values[0],N_GROUP_HEADER) == 0)
 1755                         {
 1756                             c_output->group_header = xstrdup(values[1]);
 1757                         } else if(strcmp(values[0],N_GROUP_TRAILER) == 0)
 1758                         {
 1759                             c_output->group_trailer = xstrdup(values[1]);
 1760                         } else if(strcmp(values[0],N_ELEMENT_HEADER) == 0)
 1761                         {
 1762                             c_output->element_header = xstrdup(values[1]);
 1763                         } else if(strcmp(values[0],N_ELEMENT_TRAILER) == 0)
 1764                         {
 1765                             c_output->element_trailer = xstrdup(values[1]);
 1766                         } else if(strcmp(values[0],N_JUSTIFY) == 0)
 1767                         {
 1768                             if(!values[1][1])
 1769                             {
 1770                                 c_output->justify = values[1][0];
 1771                             } else if(strcmp(values[1],"right") == 0)
 1772                             {
 1773                                 c_output->justify = RIGHT_JUSTIFY;
 1774                             } else if(strcmp(values[1],"left") == 0)
 1775                             {
 1776                                 c_output->justify = LEFT_JUSTIFY;
 1777                             } else
 1778                             {
 1779                                 error_in_line();
 1780                                 panic("Unknown values in justify",NULL,NULL);
 1781                             }
 1782                         } else if(strcmp(values[0],N_PRINT_NO_DATA) == 0)
 1783                         {
 1784                             if(strcmp(values[1],"yes") == 0)
 1785                             {
 1786                                 c_output->no_data = 1;
 1787                             } else if(strcmp(values[1],"no") == 0)
 1788                             {
 1789                                 c_output->no_data = 0;
 1790                             } else
 1791                             {
 1792                                 error_in_line();
 1793                                 panic("Unknown values in print-no-data",NULL,NULL);
 1794                             }
 1795                         } else if(strcmp(values[0],N_INDENT) == 0)
 1796                         {
 1797                             c_output->indent = xstrdup(values[1]);
 1798                         } else if(strcmp(values[0],N_FIELDLIST) == 0)
 1799                         {
 1800                             if(c_output->fl ==  NULL) c_output->fl = parse_include_list(values[1]);
 1801                         } else if(strcmp(values[0],N_FIELD_EMPTY_PRINT) == 0)
 1802                         {
 1803                             if(strcmp(values[1],"yes") == 0)
 1804                             {
 1805                                 c_output->print_empty = 1;
 1806                             } else if(strcmp(values[1],"no") == 0)
 1807                             {
 1808                                 c_output->print_empty = 0;
 1809                             } else
 1810                             {
 1811                                 error_in_line();
 1812                                 panic("Unknown values in field-empty-print",NULL,NULL);
 1813                             }
 1814                         } else if(strcmp(values[0],N_EMPTY_CHARS) == 0)
 1815                         {
 1816                             c_output->empty_chars = xstrdup(values[1]);
 1817                         } else if(strcmp(values[0],N_OFILE) == 0)
 1818                         {
 1819                             c_output->output_file = xstrdup(values[1]);
 1820                         } else if(strcmp(values[0],N_HEX_CAP) == 0)
 1821                         {
 1822                             if(strcmp(values[1],"yes") == 0)
 1823                             {
 1824                                 c_output->hex_cap = 1;
 1825                             } else if(strcmp(values[1],"no") == 0)
 1826                             {
 1827                                 c_output->hex_cap = 0;
 1828                             } else
 1829                             {
 1830                                 error_in_line();
 1831                                 panic("Unknown values in hex_cap",NULL,NULL);
 1832                             }
 1833                         } else 
 1834                         {
 1835                             error_in_line();
 1836                             panic("Unknown option in output definition",NULL,NULL);
 1837                         }
 1838                         break;
 1839                     case PS_LOOKUP:
 1840                         if(strcmp(values[0],N_SEARCH) == 0)
 1841                         {
 1842                             if(strcmp(values[1],"exact") == 0)
 1843                             {
 1844                                 c_lookup->type = EXACT;
 1845                             } else if(strcmp(values[1],"longest") == 0)
 1846                             {
 1847                                 c_lookup->type = LONGEST;
 1848                             } else
 1849                             {
 1850                                 error_in_line();
 1851                                 panic("Unknown value for lookup tables search option",values[1],NULL);
 1852                             }
 1853                         } else if(strcmp(values[0],N_PAIR) == 0)
 1854                         {
 1855                             c_lookup_data = c_lookup->data[hash(values[1],0)];
 1856 
 1857                             if(c_lookup_data == NULL)
 1858                             {
 1859                                 c_lookup_data = xmalloc(sizeof(struct lookup_data));
 1860                                 c_lookup->data[hash(values[1],0)] = c_lookup_data;
 1861                             } else
 1862                             {
 1863                                 while(c_lookup_data->next != NULL) c_lookup_data = c_lookup_data->next;
 1864 
 1865                                 c_lookup_data->next = xmalloc(sizeof(struct lookup_data));
 1866                                 c_lookup_data = c_lookup_data->next;
 1867                             }
 1868                             c_lookup_data->next = NULL;
 1869                             c_lookup_data->key = xstrdup(values[1]);
 1870                             c_lookup_data->value = xstrdup(values[2]);
 1871                         } else if(strcmp(values[0],N_FILE) == 0)
 1872                         {
 1873                             if(opt_count == 1)
 1874                             {
 1875                                 read_lookup_from_file(c_lookup->data,values[1],';');
 1876                             } else
 1877                             {
 1878                                 read_lookup_from_file(c_lookup->data,values[1],values[2][0]);
 1879                             }
 1880                         } else if(strcmp(values[0],N_DEFAULT) == 0)
 1881                         {
 1882                             c_lookup->default_value = xstrdup(values[1]);
 1883                         } else 
 1884                         {
 1885                             error_in_line();
 1886                             panic("Unknown option for lookup",values[0],NULL);
 1887                         }
 1888                         break;
 1889                     case PS_ANON:
 1890                         if(strcmp(values[0],N_METHOD) == 0)
 1891                         {
 1892                             if(c_anon == NULL)
 1893                             {
 1894                                 c_anon = xmalloc(sizeof(struct anon_field));
 1895                                 anonymize = c_anon;
 1896                             } else
 1897                             {
 1898                                 c_anon->next = xmalloc(sizeof(struct anon_field));
 1899                                 c_anon = c_anon->next;
 1900                             }
 1901 
 1902                         c_anon->anon_name = xstrdup(anon_name);
 1903                         c_anon->field_name = xstrdup(values[1]);
 1904                         c_anon->method = find_anon_method(values[2]);
 1905                         if(c_anon->method == A_UNKNOWN) {
 1906                             error_in_line();
 1907                             panic("Unknown method for anonymization",values[2],NULL);
 1908                         }
 1909                         c_anon->start = 1;
 1910                         c_anon->length = 0;
 1911                         c_anon->next = NULL;
 1912                         c_anon->key_length = 0;
 1913                         c_anon->key = NULL;
 1914 
 1915                         if(opt_count > 2)
 1916                         {
 1917                             sscanf(values[3],"%d",&c_anon->start);
 1918                             if(c_anon->start == 0) panic("Anonymization method start cannot be zero",NULL,NULL);
 1919                             if(opt_count > 3)
 1920                             {
 1921                                 sscanf(values[4],"%d",&c_anon->length);
 1922                                 if(c_anon->length < 0)
 1923                                 {
 1924                                     error_in_line();
 1925                                     panic("Anonymization method length cannot be negative",NULL,NULL);
 1926                                 } 
 1927 
 1928                                 if(opt_count > 4)
 1929                                 {
 1930                                     c_anon->key_length = expand_non_print(values[5],&c_anon->key);
 1931                                 }
 1932                             }
 1933                         }
 1934                         } else
 1935                         {
 1936                             error_in_line();
 1937                             panic("Unknown option for anonymize",values[0],NULL);
 1938                         }
 1939                         break;
 1940                     case PS_W_RECORD:
 1941                     case PS_W_OUTPUT:
 1942                     case PS_W_STRUCT:
 1943                     case PS_W_LOOKUP:
 1944                     case PS_W_ANON:
 1945                         error_in_line();
 1946                         panic("{ expected, found",values[0],NULL);
 1947                         break;
 1948                 }
 1949                 break;
 1950             case LL_BLOCK_START:
 1951                 switch(status)
 1952                 {
 1953                     case PS_W_STRUCT:
 1954                         status = PS_STRUCT;
 1955                         break;
 1956                     case PS_W_OUTPUT:
 1957                         status = PS_OUTPUT;
 1958                         break;
 1959                     case PS_W_RECORD:
 1960                         status = PS_RECORD;
 1961                         break;
 1962                     case PS_W_LOOKUP:
 1963                         status = PS_LOOKUP;
 1964                         break;
 1965                     case PS_W_ANON:
 1966                         status = PS_ANON;
 1967                         break;
 1968                     default:
 1969                         error_in_line();
 1970                         panic("{ not expected",NULL,NULL);
 1971                         break;
 1972                 }
 1973                 break;
 1974             case LL_BLOCK_END:
 1975                 switch(status)
 1976                 {
 1977                     case PS_STRUCT:
 1978                     case PS_OUTPUT:
 1979                     case PS_LOOKUP:
 1980                     case PS_ANON:
 1981                         status = PS_MAIN;
 1982                         break;
 1983                     case PS_RECORD:
 1984                         status = PS_STRUCT;
 1985                         break;
 1986                     default:
 1987                         error_in_line();
 1988                         panic("} not expected",NULL,NULL);
 1989                 }
 1990                 break;
 1991         }
 1992     }
 1993     if(status != PS_MAIN)
 1994     {
 1995         panic("End of file reached before closing }",NULL,NULL);
 1996     }
 1997     free(read_buffer);
 1998     fclose(fp);
 1999 }
 2000