home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume18 / treepar / part01 / tfile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-12  |  8.7 KB  |  406 lines

  1. /* tfile.c - routines to read a tabular text file
  2.  *
  3.  * 12.Aug.87  jimmc  Initial definition
  4.  * 18.Jan.88  jimmc  Remove struct defs to tfile.h; lint cleanup
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <varargs.h>
  9. #include <strings.h>
  10. #include "xalloc.h"
  11. #include "tklex.h"
  12. #include "tfile.h"
  13.  
  14. #define NIL 0
  15.  
  16. extern char *index();
  17.  
  18. static struct {
  19.     char *name;
  20.     int tktype;
  21. } tktypetable[] = {
  22.     { "i", TkNumber },
  23.     { "s", TkString },
  24. };
  25. static int tktypetablesize = sizeof(tktypetable)/sizeof(tktypetable[0]);
  26.  
  27. static
  28. EatToParen(tkhandle)
  29. TkHandle tkhandle;
  30. {
  31. int t;
  32.  
  33.     for (t=TkGet(tkhandle);t!=TkEOF&&t!=TkCParen;t=TkGet(tkhandle))
  34.         ;    /* EMPTY - scan until EOF or close paren */
  35. }
  36.  
  37. static
  38. TFsymbol *
  39. FindSymbol(fh,name)
  40. TFstuff *fh;
  41. char *name;
  42. {
  43. TFsymbol *k;
  44.  
  45.     for (k=fh->symbols;k;k=k->next) {
  46.         if (strcmp(name,k->name)==0) return k;
  47.     }
  48.     return NIL;
  49. }
  50.  
  51. static
  52. TFsymbol *
  53. NewSymbol(fh,name)
  54. TFstuff *fh;
  55. char *name;
  56. {
  57. TFsymbol *k;
  58.  
  59.     k = XCALLOC(TFsymbol,1);
  60.     k->next = fh->symbols;
  61.     fh->symbols = k;
  62.     k->name = XALLOC(char,strlen(name)+1);
  63.     strcpy(k->name,name);
  64.     return k;
  65. }
  66.  
  67. static
  68. AddFieldToSymbol(fh,k,s)
  69. TFstuff *fh;        /* in case of errors */
  70. TFsymbol *k;        /* where to add the field name to */
  71. char *s;        /* the field name and type to add */
  72. {
  73. char *st;
  74. TFfiledef *filedef;
  75. int tktype;
  76. TFprogdef *progdef;
  77. TkHandle tkhandle;
  78. int n;
  79.  
  80.     tkhandle = fh->tkhandle;
  81.     st = index(s,'.');    /* look for type specifier */
  82.     if (!st) {
  83.         fileerror(tkhandle,"no type for field %s",s);
  84.         return;
  85.     }
  86.     *st = 0;    /* null terminate the name portion */
  87.     st++;        /* point to type itself */
  88.     for (n=0; n<tktypetablesize; n++) {
  89.         if (strcmp(st,tktypetable[n].name)==0) break;
  90.     }
  91.     if (n>=tktypetablesize) {
  92.         fileerror(tkhandle,"bad type code %s for symbol %s",
  93.             st,s);
  94. /*** abort the scan here? */
  95.         tktype = TkEOF;
  96.     }
  97.     else tktype=tktypetable[n].tktype;
  98. /*** check for field name conflict */
  99.     filedef = XCALLOC(TFfiledef,1);
  100.     if (k->filedeftail) k->filedeftail->next = filedef;
  101.     k->filedeftail = filedef;
  102.     if (!k->filedef) k->filedef = filedef;
  103.     filedef->fieldname = s;
  104.     filedef->fieldtype = st;
  105.     filedef->tktype = tktype;
  106. /* correlate against progdef info, set up destaddr */
  107.     for (progdef=k->progdef;progdef;progdef=progdef->next) {
  108.         if (strcmp(progdef->name,s)==0) break;
  109.     }
  110.     if (progdef) {    /* if we found the name */
  111.         if (progdef->tktype!=filedef->tktype) {
  112.             fileerror(tkhandle,
  113.                 "type mismatch on field %s in table %s",
  114.                 filedef->fieldname,k->name);
  115. /*** what to do about this error? */
  116.         }
  117. /*** we should really be switching on the tktype here... */
  118.         filedef->destaddr.i = fh->args+progdef->argnum;
  119.     }
  120. }
  121.  
  122. static
  123. TFScanSchema(fh,s)    /* reads a schema definition line from the file */
  124. TFstuff *fh;
  125. char *s;        /* name of the file schema to be defined */
  126. /* The next token to be read is the open paren */
  127. {
  128. TkHandle tkhandle;
  129. int t;
  130. TFsymbol *k;
  131. char *sv;
  132.  
  133.     tkhandle = fh->tkhandle;
  134.     k = FindSymbol(fh,s);    /* see if a duplicate definition */
  135.     if (k && k->filedef) {
  136.         fileerror(tkhandle,"Symbol %s redefined",s);
  137.         EatToParen(tkhandle);
  138.         return;
  139.     }
  140.     t = TkGet(tkhandle);
  141.     if (t!=TkOParen) {
  142.         fileerror(tkhandle,"Expected open paren for schema for %s",s);
  143.         EatToParen(tkhandle);
  144.         return;
  145.     }
  146.     if (!k) k = NewSymbol(fh,s);
  147.     t = TkGet(tkhandle);
  148.     while (t==TkString) {    /* read until we come to a close paren */
  149.         sv = TkStringValue(tkhandle);
  150.         AddFieldToSymbol(fh,k,sv);
  151.         t = TkGet(tkhandle);
  152.     }
  153.     if (t!=TkCParen) {
  154.         fileerror(tkhandle,"Expected string or close parenthesis");
  155.         EatToParen(tkhandle);
  156.     }
  157.     return;
  158. }
  159.  
  160. static
  161. TFScanData(fh,s)    /* reads a data line from the file */
  162. TFstuff *fh;
  163. char *s;        /* name of the data type to be read */
  164. /* The open paren has just been read */
  165. {
  166. TkHandle tkhandle;
  167. TFsymbol *k;
  168. TFfiledef *f;
  169. int t;
  170. int i;
  171.  
  172.     tkhandle = fh->tkhandle;
  173.     k = FindSymbol(fh,s);
  174.     if (!k) {
  175.         fileerror(tkhandle,"No definition for symbol %s",s);
  176.         EatToParen(tkhandle);
  177.         return;
  178.     }
  179.     f = k->filedef;        /* point to list of fields */
  180.     for (i=0; i<k->progdefcount; i++) fh->args[i]=0;
  181.     t = TkGet(tkhandle);
  182.     while (t!=TkCParen && t!=TkEOF) {
  183.         if (!f) {
  184.             fileerror(tkhandle,"too many fields for type %s",s);
  185.             EatToParen(tkhandle);
  186.             return;
  187.         }
  188.         switch (f->tktype) {
  189.         case TkNumber:
  190.             if (t!=TkNumber) {
  191.                 fileerror(tkhandle,
  192.                     "expected integer for field %s",
  193.                     f->fieldname);
  194.                 EatToParen(tkhandle);
  195.                 return;
  196.             }
  197.             if (f->destaddr.i)
  198.                 *(f->destaddr.i) = TkNumberValue(tkhandle);
  199.             break;
  200.         case TkString:
  201.             if (t!=TkString) {
  202.                 fileerror(tkhandle,
  203.                     "expected string for field %s",
  204.                     f->fieldname);
  205.                 EatToParen(tkhandle);
  206.                 return;
  207.             }
  208.             if (f->destaddr.s)
  209.                 *(f->destaddr.s) = TkStringValue(tkhandle);
  210.             break;
  211.         case TkEOF:    /* earlier error */
  212.             break;        /* ignore it */
  213.         default:    /* should never happen */
  214.             printf("internal error!! line %d, file %s\n",__LINE__,
  215.                 __FILE__);
  216.             break;
  217.         }
  218.         f = f->next;
  219.         t = TkGet(tkhandle);
  220.     }
  221.     if (f) {
  222.         fileerror(tkhandle,"not enough fields");
  223.         return;
  224.     }
  225. /* now call the function as requested */
  226.     t = (*k->funcp)(fh->args[0],fh->args[1],fh->args[2],
  227.             fh->args[3],fh->args[4],fh->args[5],
  228.             fh->args[6],fh->args[7],fh->args[8],
  229.             fh->args[9],fh->args[10],fh->args[11]);
  230. /*** what does the return value mean? */
  231. }
  232.  
  233. static
  234. int            /* returns 0 if no more reading to do */
  235. TFScanOne(fh)        /* read one "line" (terminated by close paren) */
  236. TFstuff *fh;
  237. {
  238. TkHandle tkhandle;
  239. int t;
  240. char *s,*s2;
  241.  
  242.     tkhandle = fh->tkhandle;
  243.     t = TkGet(tkhandle);
  244.     if (t==TkEOF) return 0;        /* normal completion */
  245.     if (t==TkOParen) {    /* another data item of same type as last */
  246.         if (!fh->lasttype) {
  247.             fileerror(tkhandle,"no previous type specified");
  248.             EatToParen(tkhandle);
  249.             return 1;
  250.         }
  251.         TFScanData(fh,fh->lasttype);
  252.         return 1;
  253.     }
  254.     if (t!=TkSymbol) {
  255.         fileerror(tkhandle,"Expected start symbol");
  256.         EatToParen(tkhandle);
  257.         return 1;
  258.     }
  259.     s = TkStringValue(tkhandle);    /* same symbol value */
  260.     if (fh->lasttype) free(fh->lasttype);
  261.     fh->lasttype = s;
  262.     t = TkGet(tkhandle);
  263.     if (t==TkOParen) {
  264.         TFScanData(fh,s);
  265.     }
  266.     else if (t==TkSymbol) {
  267.         s2 = TkStringValue(tkhandle);
  268.         if (strcmp(s2,"schema")==0) {
  269.             TFScanSchema(fh,s);
  270.         }
  271.         else {
  272.             fileerror(tkhandle,
  273.                 "Bad keyword '%s' after symbol '%s'",s2,s);
  274.             EatToParen(tkhandle);
  275.         }
  276.         free(s2);
  277.     }
  278.     else {
  279.         fileerror(tkhandle,
  280.             "Expected open parenthesis after symbol %s",s);
  281.         EatToParen(tkhandle);
  282.     }
  283.     return 1;    /* continue */
  284. }
  285.  
  286. int        /* returns status code (*** what is it?) */
  287. TFScan(handle)    /* top level file scan */
  288. TFhandle handle;
  289. {
  290. TFstuff *fh;
  291.  
  292.     fh = (TFstuff *)handle;
  293.     if (!fh) {
  294.         printf("No handle for TFScan\n");
  295.         return 0;
  296.     }
  297.  
  298.     while (TFScanOne(fh)) ;    /* EMPTY - read until done */
  299.     return 1;    /*** what to return? */
  300. }
  301.  
  302. /* VARARGS - really varargs3, but lint doesn't understand va_alist */
  303. TFSetup(va_alist)
  304. /* args are: handle, name, funcp, args...; null terminates list */
  305. va_dcl
  306. {
  307. va_list v;
  308. TFhandle handle;
  309. char *name;
  310. IFP funcp;    /* pointer to func returning int */
  311. TFstuff *fh;
  312. TFsymbol *k;
  313. TFprogdef *p;
  314. char *fd, *fdtype;
  315. int n;
  316. int tktype;
  317.  
  318.     va_start(v);
  319.     handle = va_arg(v,TFhandle);
  320.     name = va_arg(v,char *);
  321.     funcp = va_arg(v,IFP);
  322.     fh = (TFstuff *)handle;
  323.     if (!fh) {
  324.         printf("No handle for TFSetup of %s\n",name);
  325.         goto end;    /* do va_end and return */
  326.     }
  327.     k = FindSymbol(fh,name);
  328.     if (k && k->progdef) {
  329.         printf("Symbol %s re-setup\n",name);
  330.         goto end;    /* do va_end and return */
  331.     }
  332.     if (!k) k = NewSymbol(fh,name);
  333.     k->funcp = funcp;
  334.     fd = va_arg(v,char *);        /* start looking at field defs */
  335.     while (fd) {
  336.         fdtype = index(fd,'.');
  337.         if (!fdtype) {
  338.             printf("no type for field %s in setup %s\n",
  339.                 fd,name);
  340.             tktype = TkEOF;
  341.             fdtype = fd+strlen(fd)+1;    /* for later sub */
  342.         }
  343.         else {
  344.             fdtype++;
  345.             for (n=0; n<tktypetablesize; n++) {
  346.                 if (strcmp(fdtype,tktypetable[n].name)==0)
  347.                     break;
  348.             }
  349.             if (n>=tktypetablesize) {
  350.                 printf("bad type for field %s in setup %s\n",
  351.                     fd,name);
  352.                 tktype = TkEOF;
  353.             }
  354.             else tktype=tktypetable[n].tktype;
  355.         }
  356. /*** eventually we would like to add a constant capability */
  357.         p = XCALLOC(TFprogdef,1);
  358.         p->name = XALLOC(char,fdtype-fd);
  359.         strncpy(p->name,fd,fdtype-fd-1);
  360.         p->name[fdtype-fd-1]=0;
  361.         p->tktype = tktype;
  362.         if (k->progdeftail) k->progdeftail->next = p;
  363.         if (!k->progdef) k->progdef = p;
  364.         k->progdeftail = p;
  365.         if ((p->argnum=k->progdefcount++) > MAXARGS) {
  366.             printf("too many pass-back args for setup %s (max=%d)\n",
  367.                 name,MAXARGS);
  368.         }
  369.         fd = va_arg(v,char *);
  370.     }
  371. end:
  372.     va_end(v);
  373. }
  374.  
  375. TFhandle
  376. TFInit(filename)
  377. char *filename;
  378. {
  379. TFstuff *fh;
  380. TkHandle tkhandle;
  381.  
  382.     tkhandle = TkInit(filename);
  383.     if (!tkhandle) {
  384.         printf("can't init file %s\n",filename);
  385.         return 0;
  386.     }
  387.     fh = XCALLOC(TFstuff,1);
  388.     fh->tkhandle = tkhandle;
  389.     return (TFhandle)fh;
  390. }
  391.  
  392. TFDone(handle)
  393. TFhandle handle;
  394. {
  395. TFstuff *fh;
  396.  
  397.     fh = (TFstuff *)handle;
  398.     if (!fh) {
  399.         printf("No handle for TFDone\n");
  400.     }
  401. /*** if anything needs to be freed, do it here */
  402.     if (fh->tkhandle) TkDone(fh->tkhandle);
  403. }
  404.  
  405. /* end */
  406.