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