home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 168_01 / scn.c < prev    next >
Text File  |  1985-08-21  |  15KB  |  637 lines

  1. /* SDB - token scanning routines */
  2.  
  3. #include "stdio.h"
  4. #include "sdbio.h"
  5.  
  6. int dbv_token;                          /* current token */
  7. int dbv_tvalue;                         /* integer token value */
  8. char dbv_tstring[STRINGMAX+1];          /* string token value */
  9. struct ifile *dbv_ifp;                  /* indirect file context */
  10. struct macro *dbv_macros;               /* macro definitions */
  11. int dbv_fold;                           /* case fold alpha comparisons */
  12.  
  13. static char *iprompt,*cprompt;          /* input prompts */
  14. static char cmdline[LINEMAX+2],*lptr;   /* current line and pointer */
  15. static int atbol;                       /* flag indicating at bol */
  16. static int savech;                      /* lookahead character */
  17. static int savetkn;                     /* lookahead token */
  18. static char *keywords[] = {             /* keyword table */
  19.     "ascending",
  20.     "by",
  21.     "char",
  22.     "compress",
  23.     "create",
  24.     "define",
  25.     "delete",
  26.     "descending",
  27.     "exit",
  28.     "export",
  29.     "extract",
  30.     "from",
  31.     "help",
  32.     "insert",
  33.     "import",
  34.     "into",
  35.     "num",
  36.     "print",
  37.     "select",
  38.     "set",
  39.     "show",
  40.     "sort",
  41.     "update",
  42.     "using",
  43.     "where",
  44.     NULL
  45. };
  46. static int keytokens[] = {              /* token values for each keyword */
  47.     ASCENDING,
  48.     BY,
  49.     CHAR,
  50.     COMPRESS,
  51.     CREATE,
  52.     DEFINE,
  53.     DELETE,
  54.     DESCENDING,
  55.     EXIT,
  56.     EXPORT,
  57.     EXTRACT,
  58.     FROM,
  59.     HELP,
  60.     INSERT,
  61.     IMPORT,
  62.     INTO,
  63.     NUM,
  64.     PRINT,
  65.     SELECT,
  66.     SET,
  67.     SHOW,
  68.     SORT,
  69.     UPDATE,
  70.     USING,
  71.     WHERE,
  72.     NULL
  73. };
  74.  
  75. /* db_sinit - initialize the scanner */
  76. db_sinit()
  77. {
  78.     /* at beginning of line */
  79.     atbol = TRUE;
  80.  
  81.     /* make the command line null */
  82.     lptr = NULL;
  83.  
  84.     /* no lookahead yet */
  85.     savech = EOS;
  86.     savetkn = NULL;
  87.  
  88.     /* no indirect command files */
  89.     dbv_ifp = NULL;
  90.  
  91.     /* no macros defined */
  92.     dbv_macros = NULL;
  93.  
  94.     /* fold alpha comparisons */
  95.     dbv_fold = TRUE;
  96. }
  97.  
  98. /* db_prompt(ip,cp) - initialize prompt strings */
  99. db_prompt(ip,cp)
  100.   char *ip,*cp;
  101. {
  102.     /* save initial and continuation prompt strings */
  103.     iprompt = ip;
  104.     cprompt = cp;
  105. }
  106.  
  107. /* db_scan(fmt,args) - initiate line scan command parsing */
  108. db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
  109. {
  110.     /* convert the command line and arguments */
  111.     sprintf(cmdline,fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10);
  112.  
  113.     /* start at the beginning of the command line */
  114.     lptr = cmdline;
  115.     iprompt = NULL;
  116.     dbv_ifp = NULL;
  117.  
  118.     /* no lookahead yet */
  119.     savech = EOS;
  120.     savetkn = NULL;
  121.  
  122.     /* fold alpha comparisons */
  123.     dbv_fold = TRUE;
  124. }
  125.  
  126. /* db_flush - flush the current input line */
  127. int db_flush()
  128. {
  129.     while (savech != '\n')
  130.         if (savech > ' ')
  131.             return (db_ferror(SYNTAX));
  132.         else
  133.             savech = getchx();
  134.  
  135.     savech = EOS;
  136.     atbol = TRUE;
  137.     return (TRUE);
  138. }
  139.  
  140. /* db_gline - get a line from the current input */
  141. char *db_gline(buf)
  142.   char *buf;
  143. {
  144.     int ch,i;
  145.  
  146.     for (i = 0; (ch = getch()) != '\n' && ch != -1; )
  147.         if (i < LINEMAX)
  148.             buf[i++] = ch;
  149.         else {
  150.             printf("*** line too long ***\nRetype> ");
  151.             i = 0;
  152.         }
  153.     buf[i] = EOS;
  154.  
  155.     return (buf);
  156. }
  157.  
  158. /* db_ifile - setup an indirect command file */
  159. int db_ifile(fname)
  160.   char *fname;
  161. {
  162.     struct ifile *new_ifp;
  163.  
  164.     if ((new_ifp = malloc(sizeof(struct ifile))) == NULL)
  165.         return (db_ferror(INSMEM));
  166.     else if ((new_ifp->if_fp = fopen(fname,"r")) == NULL) {
  167.         free(new_ifp);
  168.         return (db_ferror(INDFNF));
  169.     }
  170.     new_ifp->if_mtext = NULL;
  171.     new_ifp->if_savech = savech;
  172.     new_ifp->if_lptr = lptr;
  173.     new_ifp->if_next = dbv_ifp;
  174.     dbv_ifp = new_ifp;
  175.  
  176.     /* return successfully */
  177.     return (TRUE);
  178. }
  179.  
  180. /* db_kill - kill indirect command file input */
  181. db_kill()
  182. {
  183.     struct ifile *old_ifp;
  184.  
  185.     while ((old_ifp = dbv_ifp) != NULL) {
  186.         dbv_ifp = old_ifp->if_next;
  187.         if (old_ifp->if_fp != NULL)
  188.             fclose(old_ifp->if_fp);
  189.         savech = old_ifp->if_savech;
  190.         lptr = old_ifp->if_lptr;
  191.         free(old_ifp);
  192.     }
  193.  
  194.     while (savech != '\n')
  195.         savech = getchx();
  196.  
  197.     savech = EOS;
  198.     savetkn = NULL;
  199.     atbol = TRUE;
  200. }
  201.  
  202. /* db_token - return the current input token */
  203. int db_token()
  204. {
  205.     struct macro *mptr;
  206.     struct ifile *new_ifp;
  207.  
  208.     /* find a token that's not a macro call */
  209.     while (db_xtoken() == ID) {
  210.  
  211.         /* check for a macro call */
  212.         for (mptr = dbv_macros; mptr != NULL; mptr = mptr->mc_next)
  213.             if (db_scmp(dbv_tstring,mptr->mc_name) == 0) {
  214.                 if ((new_ifp = malloc(sizeof(struct ifile))) == NULL)
  215.                     printf("*** error expanding macro: %s ***\n",dbv_tstring);
  216.                 else {
  217.                     new_ifp->if_fp = NULL;
  218.                     new_ifp->if_mtext = mptr->mc_mtext->mt_next;
  219.                     new_ifp->if_lptr = lptr; lptr = mptr->mc_mtext->mt_text;
  220.                     new_ifp->if_savech = savech; savech = EOS;
  221.                     new_ifp->if_next = dbv_ifp;
  222.                     dbv_ifp = new_ifp;
  223.                 }
  224.                 savetkn = NULL;
  225.                 break;
  226.             }
  227.  
  228.         if (mptr == NULL)
  229.             break;
  230.     }
  231.  
  232.     return (dbv_token);
  233. }
  234.  
  235. /* db_xtoken - return the current input token */
  236. int db_xtoken()
  237. {
  238.     int ch;
  239.  
  240.     /* check for a saved token */
  241.     if ((dbv_token = savetkn) != NULL)
  242.         return (dbv_token);
  243.  
  244.     /* get the next non-blank character */
  245.     ch = nextch();
  246.  
  247.     /* check type of character */
  248.     if (isalpha(ch))                    /* identifier or keyword */
  249.         get_id();
  250.     else if (isdigit(ch))               /* number */
  251.         get_number();
  252.     else if (ch == '"')                 /* string */
  253.         get_string();
  254.     else if (get_rel())                 /* relational operator */
  255.         ;
  256.     else                                /* single character token */
  257.         dbv_token = getch();
  258.  
  259.     /* save the lookahead token */
  260.     savetkn = dbv_token;
  261.  
  262.     /* return the token */
  263.     return (dbv_token);
  264. }
  265.  
  266. /* db_ntoken - get next token (after skipping the current one) */
  267. int db_ntoken()
  268. {
  269.     /* get the current token */
  270.     db_token();
  271.  
  272.     /* make sure another is read on next call */
  273.     savetkn = NULL;
  274.  
  275.     /* return the current token */
  276.     return (dbv_token);
  277. }
  278.  
  279. /* db_xntoken - get next token (after skipping the current one) */
  280. int db_xntoken()
  281. {
  282.     /* get the current token */
  283.     db_xtoken();
  284.  
  285.     /* make sure another is read on next call */
  286.     savetkn = NULL;
  287.  
  288.     /* return the current token */
  289.     return (dbv_token);
  290. }
  291.  
  292. /* db_scmp - compare two strings */
  293. int db_scmp(str1,str2)
  294.   char *str1,*str2;
  295. {
  296.     if (dbv_fold)
  297.         return (scmp(str1,str2));
  298.     else
  299.         return (strcmp(str1,str2));
  300. }
  301.  
  302. /* db_sncmp - compare two strings with a maximum length */
  303. int db_sncmp(str1,str2,len)
  304.   char *str1,*str2; int len;
  305. {
  306.     if (dbv_fold)
  307.         return (sncmp(str1,str2,len));
  308.     else
  309.         return (strncmp(str1,str2,len));
  310. }
  311.  
  312. /* scmp - compare two strings with alpha case folding */
  313. static int scmp(str1,str2)
  314.   char *str1,*str2;
  315. {
  316.     int ch1,ch2;
  317.  
  318.     /* compare each character */
  319.     while (*str1 && *str2) {
  320.  
  321.         /* fold the character from the first string */
  322.         if (isupper(*str1))
  323.             ch1 = tolower(*str1++);
  324.         else
  325.             ch1 = *str1++;
  326.  
  327.         /* fold the character from the second string */
  328.         if (isupper(*str2))
  329.             ch2 = tolower(*str2++);
  330.         else
  331.             ch2 = *str2++;
  332.  
  333.         /* compare the characters */
  334.         if (ch1 != ch2)
  335.             if (ch1 < ch2)
  336.                 return (-1);
  337.             else
  338.                 return (1);
  339.     }
  340.  
  341.     /* check for strings of different lengths */
  342.     if (*str1 == *str2)
  343.         return (0);
  344.     else if (*str1 == 0)
  345.         return (-1);
  346.     else
  347.         return (1);
  348. }
  349.  
  350. /* sncmp - compare two strings with alpha case folding and a maximum length */
  351. static int sncmp(str1,str2,len)
  352.   char *str1,*str2; int len;
  353. {
  354.     int ch1,ch2;
  355.  
  356.     /* compare each character */
  357.     while (*str1 && *str2 && len > 0) {
  358.  
  359.         /* fold the character from the first string */
  360.         if (isupper(*str1))
  361.             ch1 = tolower(*str1++);
  362.         else
  363.             ch1 = *str1++;
  364.  
  365.         /* fold the character from the second string */
  366.         if (isupper(*str2))
  367.             ch2 = tolower(*str2++);
  368.         else
  369.             ch2 = *str2++;
  370.  
  371.         /* compare the characters */
  372.         if (ch1 != ch2)
  373.             if (ch1 < ch2)
  374.                 return (-1);
  375.             else
  376.                 return (1);
  377.  
  378.         /* decrement the string length */
  379.         len--;
  380.     }
  381.  
  382.     /* check for strings of different lengths */
  383.     if (len == 0 || *str1 == *str2)
  384.         return (0);
  385.     else if (*str1 == 0)
  386.         return (-1);
  387.     else
  388.         return (1);
  389. }
  390.  
  391. /* get_id - get a keyword or a user identifier */
  392. static get_id()
  393. {
  394.     int ch,nchars,i;
  395.  
  396.     /* input letters and digits */
  397.     ch = nextch();
  398.     nchars = 0;
  399.     while (isalpha(ch) || isdigit(ch)) {
  400.         if (nchars < KEYWORDMAX)
  401.             dbv_tstring[nchars++] = ch;
  402.         getch(); ch = thisch();
  403.     }
  404.  
  405.     /* terminate the keyword */
  406.     dbv_tstring[nchars] = EOS;
  407.  
  408.     /* assume its an identifier */
  409.     dbv_token = ID;
  410.  
  411.     /* check for keywords */
  412.     for (i = 0; keywords[i] != NULL; i++)
  413.         if (db_scmp(dbv_tstring,keywords[i]) == 0)
  414.             dbv_token = keytokens[i];
  415. }
  416.  
  417. /* get_number - get a number */
  418. static get_number()
  419. {
  420.     int ch,ndigits,nodot;
  421.  
  422.     /* read digits and at most one decimal point */
  423.     ch = nextch();
  424.     ndigits = 0; nodot = TRUE;
  425.     while (isdigit(ch) || (nodot && ch == '.')) {
  426.         if (ch == '.')
  427.             nodot = FALSE;
  428.         if (ndigits < NUMBERMAX)
  429.             dbv_tstring[ndigits++] = ch;
  430.         getch(); ch = thisch();
  431.     }
  432.  
  433.     /* terminate the number */
  434.     dbv_tstring[ndigits] = EOS;
  435.  
  436.     /* get the value of the number */
  437.     sscanf(dbv_tstring,"%d",&dbv_tvalue);
  438.  
  439.     /* token is a number */
  440.     dbv_token = NUMBER;
  441. }
  442.  
  443. /* get_string - get a string */
  444. static get_string()
  445. {
  446.     int ch,nchars;
  447.  
  448.     /* skip the opening quote */
  449.     getch();
  450.  
  451.     /* read characters until a closing quote is found */
  452.     ch = thisch();
  453.     nchars = 0;
  454.     while (ch && ch != '"') {
  455.         if (nchars < STRINGMAX)
  456.             dbv_tstring[nchars++] = ch;
  457.         getch(); ch = thisch();
  458.     }
  459.  
  460.     /* terminate the string */
  461.     dbv_tstring[nchars] = EOS;
  462.  
  463.     /* skip the closing quote */
  464.     getch();
  465.  
  466.     /* token is a string */
  467.     dbv_token = STRING;
  468. }
  469.  
  470. /* get_rel - get a relational operator */
  471. static int get_rel()
  472. {
  473.     int ch;
  474.  
  475.     switch (ch = nextch()) {
  476.     case '=':
  477.             getch();
  478.             dbv_token = EQL;
  479.             return (TRUE);;
  480.     case '<':
  481.             getch(); ch = nextch();
  482.             if (ch == '>') {
  483.                 getch();
  484.                 dbv_token = NEQ;
  485.             }
  486.             else if (ch == '=') {
  487.                 getch();
  488.                 dbv_token = LEQ;
  489.             }
  490.             else
  491.                 dbv_token = LSS;
  492.             return (TRUE);;
  493.     case '>':
  494.             getch(); ch = nextch();
  495.             if (ch == '=') {
  496.                 getch();
  497.                 dbv_token = GEQ;
  498.             }
  499.             else
  500.                 dbv_token = GTR;
  501.             return (TRUE);;
  502.     default:
  503.             return (FALSE);
  504.     }
  505. }
  506.  
  507. /* getch - get the next character */
  508. static int getch()
  509. {
  510.     char fname[STRINGMAX+1];
  511.     int ch,i;
  512.  
  513.     /* return the lookahead character if there is one */
  514.     if (savech != EOS) {
  515.         ch = savech;
  516.         savech = EOS;
  517.         return (ch);
  518.     }
  519.  
  520.     /* get a character */
  521.     ch = getchx();
  522.  
  523.     /* skip spaces at the beginning of a command */
  524.     if (atbol && iprompt != NULL)
  525.         while (ch <= ' ')
  526.             ch = getchx();
  527.  
  528.     /* use continuation prompt next time */
  529.     iprompt = NULL;
  530.  
  531.     /* check for indirect command file */
  532.     while (ch == '@') {
  533.         for (i = 0; (savech = getchx()) > ' '; )
  534.             if (i < STRINGMAX)
  535.                 fname[i++] = savech;
  536.         fname[i] = 0;
  537.         if (db_ifile(fname) != TRUE)
  538.             printf("*** error opening command file: %s ***\n",fname);
  539.         ch = getchx();
  540.     }
  541.  
  542.     /* return the character */
  543.     return (ch);
  544. }
  545.  
  546. /* getchx - get the next character */
  547. static int getchx()
  548. {
  549.     struct ifile *old_ifp;
  550.     int ch;
  551.  
  552.     /* check for input from buffer */
  553.     if (lptr != NULL) {
  554.         while (*lptr == EOS)
  555.             if (dbv_ifp != NULL)
  556.                 if (dbv_ifp->if_mtext == NULL) {
  557.                     old_ifp = dbv_ifp;
  558.                     ch = dbv_ifp->if_savech; savech = EOS;
  559.                     lptr = dbv_ifp->if_lptr;
  560.                     dbv_ifp = dbv_ifp->if_next;
  561.                     free(old_ifp);
  562.                     if (ch != EOS)
  563.                         return (ch);
  564.                     if (lptr == NULL)
  565.                         break;
  566.                 }
  567.                 else {
  568.                     lptr = dbv_ifp->if_mtext->mt_text;
  569.                     dbv_ifp->if_mtext = dbv_ifp->if_mtext->mt_next;
  570.                 }
  571.             else
  572.                 return (EOS);
  573.  
  574.         if (lptr != NULL)
  575.             return (*lptr++);
  576.     }
  577.  
  578.     /* print prompt if necessary */
  579.     if (atbol && dbv_ifp == NULL)  {  /*dns*/
  580.         if (iprompt != NULL)
  581.             printf("%s",iprompt);
  582.         else if (cprompt != NULL)
  583.             printf("%s",cprompt);
  584. #ifdef Lattice
  585.         fflush(stdout); /*dns*/
  586. #endif
  587.         } /*dns*/
  588.  
  589.     if (dbv_ifp == NULL)
  590.         if ((ch = getcx(stdin)) == '\n')
  591.             atbol = TRUE;
  592.         else
  593.             atbol = FALSE;
  594.     else {
  595.         if ((ch = getcx(dbv_ifp->if_fp)) == -1) {
  596.             old_ifp = dbv_ifp;
  597.             ch = dbv_ifp->if_savech; savech = EOS;
  598.             lptr = dbv_ifp->if_lptr;
  599.             dbv_ifp = dbv_ifp->if_next;
  600.             fclose(old_ifp->if_fp);
  601.             free(old_ifp);
  602.         }
  603.     }
  604.  
  605.     /* return the character */
  606.     return (ch);
  607. }
  608.  
  609. /* thisch - get the current character */
  610. static int thisch()
  611. {
  612.     /* get a lookahead character */
  613.     if (savech == EOS)
  614.         savech = getch();
  615.  
  616.     /* return lookahead character */
  617.     return (savech);
  618. }
  619.  
  620. /* nextch - get the next non-blank character */
  621. static int nextch()
  622. {
  623.     int ch;
  624.  
  625.     /* skip blank characters */
  626.     while ((ch = thisch()) <= ' ' && ch != EOS)
  627.         getch();
  628.  
  629.     /* return the first non-blank */
  630.     return (ch);
  631. }
  632.  
  633. (textline)+1)) == NULL) {
  634.             mc_free(mptr);
  635.             return (db_ferror(INSMEM));
  636.         }
  637.