home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / window / scanner.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-18  |  11.4 KB  |  573 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Edward Wang at The University of California, Berkeley.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. static char sccsid[] = "@(#)scanner.c    3.14 (Berkeley) 6/6/90";
  39. #endif /* not lint */
  40.  
  41. #include "value.h"
  42. #include "token.h"
  43. #include "context.h"
  44. #include "string.h"
  45.  
  46. s_getc()
  47. {
  48.     register c;
  49.  
  50.     switch (cx.x_type) {
  51.     case X_FILE:
  52.         c = getc(cx.x_fp);
  53.         if (cx.x_bol && c != EOF) {
  54.             cx.x_bol = 0;
  55.             cx.x_lineno++;
  56.         }
  57.         if (c == '\n')
  58.             cx.x_bol = 1;
  59.         return c;
  60.     case X_BUF:
  61.         if (*cx.x_bufp != 0)
  62.             return *cx.x_bufp++ & 0xff;
  63.         else
  64.             return EOF;
  65.     }
  66.     /*NOTREACHED*/
  67. }
  68.  
  69. s_ungetc(c)
  70. {
  71.     if (c == EOF)
  72.         return EOF;
  73.     switch (cx.x_type) {
  74.     case X_FILE:
  75.         cx.x_bol = 0;
  76.         return ungetc(c, cx.x_fp);
  77.     case X_BUF:
  78.         if (cx.x_bufp > cx.x_buf)
  79.             return *--cx.x_bufp = c;
  80.         else
  81.             return EOF;
  82.     }
  83.     /*NOTREACHED*/
  84. }
  85.  
  86. s_gettok()
  87. {
  88.     char buf[100];
  89.     register char *p = buf;
  90.     register c;
  91.     register state = 0;
  92.  
  93. loop:
  94.     c = s_getc();
  95.     switch (state) {
  96.     case 0:
  97.         switch (c) {
  98.         case ' ':
  99.         case '\t':
  100.             break;
  101.         case '\n':
  102.         case ';':
  103.             cx.x_token = T_EOL;
  104.             state = -1;
  105.             break;
  106.         case '#':
  107.             state = 1;
  108.             break;
  109.         case EOF:
  110.             cx.x_token = T_EOF;
  111.             state = -1;
  112.             break;
  113.         case 'a': case 'b': case 'c': case 'd': case 'e':
  114.         case 'f': case 'g': case 'h': case 'i': case 'j':
  115.         case 'k': case 'l': case 'm': case 'n': case 'o':
  116.         case 'p': case 'q': case 'r': case 's': case 't':
  117.         case 'u': case 'v': case 'w': case 'x': case 'y':
  118.         case 'z':
  119.         case 'A': case 'B': case 'C': case 'D': case 'E':
  120.         case 'F': case 'G': case 'H': case 'I': case 'J':
  121.         case 'K': case 'L': case 'M': case 'N': case 'O':
  122.         case 'P': case 'Q': case 'R': case 'S': case 'T':
  123.         case 'U': case 'V': case 'W': case 'X': case 'Y':
  124.         case 'Z':
  125.         case '_': case '.':
  126.             *p++ = c;
  127.             state = 2;
  128.             break;
  129.         case '"':
  130.             state = 3;
  131.             break;
  132.         case '\'':
  133.             state = 4;
  134.             break;
  135.         case '\\':
  136.             switch (c = s_gettok1()) {
  137.             case -1:
  138.                 break;
  139.             case -2:
  140.                 state = 0;
  141.                 break;
  142.             default:
  143.                 *p++ = c;
  144.                 state = 2;
  145.             }
  146.             break;
  147.         case '0':
  148.             cx.x_val.v_num = 0;
  149.             state = 10;
  150.             break;
  151.         case '1': case '2': case '3': case '4':
  152.         case '5': case '6': case '7': case '8': case '9':
  153.             cx.x_val.v_num = c - '0';
  154.             state = 11;
  155.             break;
  156.         case '>':
  157.             state = 20;
  158.             break;
  159.         case '<':
  160.             state = 21;
  161.             break;
  162.         case '=':
  163.             state = 22;
  164.             break;
  165.         case '!':
  166.             state = 23;
  167.             break;
  168.         case '&':
  169.             state = 24;
  170.             break;
  171.         case '|':
  172.             state = 25;
  173.             break;
  174.         case '$':
  175.             state = 26;
  176.             break;
  177.         case '~':
  178.             cx.x_token = T_COMP;
  179.             state = -1;
  180.             break;
  181.         case '+':
  182.             cx.x_token = T_PLUS;
  183.             state = -1;
  184.             break;
  185.         case '-':
  186.             cx.x_token = T_MINUS;
  187.             state = -1;
  188.             break;
  189.         case '*':
  190.             cx.x_token = T_MUL;
  191.             state = -1;
  192.             break;
  193.         case '/':
  194.             cx.x_token = T_DIV;
  195.             state = -1;
  196.             break;
  197.         case '%':
  198.             cx.x_token = T_MOD;
  199.             state = -1;
  200.             break;
  201.         case '^':
  202.             cx.x_token = T_XOR;
  203.             state = -1;
  204.             break;
  205.         case '(':
  206.             cx.x_token = T_LP;
  207.             state = -1;
  208.             break;
  209.         case ')':
  210.             cx.x_token = T_RP;
  211.             state = -1;
  212.             break;
  213.         case ',':
  214.             cx.x_token = T_COMMA;
  215.             state = -1;
  216.             break;
  217.         case '?':
  218.             cx.x_token = T_QUEST;
  219.             state = -1;
  220.             break;
  221.         case ':':
  222.             cx.x_token = T_COLON;
  223.             state = -1;
  224.             break;
  225.         case '[':
  226.             cx.x_token = T_LB;
  227.             state = -1;
  228.             break;
  229.         case ']':
  230.             cx.x_token = T_RB;
  231.             state = -1;
  232.             break;
  233.         default:
  234.             cx.x_val.v_num = c;
  235.             cx.x_token = T_CHAR;
  236.             state = -1;
  237.             break;
  238.         }
  239.         break;
  240.     case 1:                /* got # */
  241.         if (c == '\n' || c == EOF) {
  242.             (void) s_ungetc(c);
  243.             state = 0;
  244.         }
  245.         break;
  246.     case 2:                /* unquoted string */
  247.         switch (c) {
  248.         case 'a': case 'b': case 'c': case 'd': case 'e':
  249.         case 'f': case 'g': case 'h': case 'i': case 'j':
  250.         case 'k': case 'l': case 'm': case 'n': case 'o':
  251.         case 'p': case 'q': case 'r': case 's': case 't':
  252.         case 'u': case 'v': case 'w': case 'x': case 'y':
  253.         case 'z':
  254.         case 'A': case 'B': case 'C': case 'D': case 'E':
  255.         case 'F': case 'G': case 'H': case 'I': case 'J':
  256.         case 'K': case 'L': case 'M': case 'N': case 'O':
  257.         case 'P': case 'Q': case 'R': case 'S': case 'T':
  258.         case 'U': case 'V': case 'W': case 'X': case 'Y':
  259.         case 'Z':
  260.         case '_': case '.':
  261.         case '0': case '1': case '2': case '3': case '4':
  262.         case '5': case '6': case '7': case '8': case '9':
  263.             if (p < buf + sizeof buf - 1)
  264.                 *p++ = c;
  265.             break;
  266.         case '"':
  267.             state = 3;
  268.             break;
  269.         case '\'':
  270.             state = 4;
  271.             break;
  272.         case '\\':
  273.             switch (c = s_gettok1()) {
  274.             case -2:
  275.                 (void) s_ungetc(' ');
  276.             case -1:
  277.                 break;
  278.             default:
  279.                 if (p < buf + sizeof buf - 1)
  280.                     *p++ = c;
  281.             }
  282.             break;
  283.         default:
  284.             (void) s_ungetc(c);
  285.         case EOF:
  286.             *p = 0;
  287.             cx.x_token = T_STR;
  288.             switch (*buf) {
  289.             case 'i':
  290.                 if (buf[1] == 'f' && buf[2] == 0)
  291.                     cx.x_token = T_IF;
  292.                 break;
  293.             case 't':
  294.                 if (buf[1] == 'h' && buf[2] == 'e'
  295.                     && buf[3] == 'n' && buf[4] == 0)
  296.                     cx.x_token = T_THEN;
  297.                 break;
  298.             case 'e':
  299.                 if (buf[1] == 'n' && buf[2] == 'd'
  300.                     && buf[3] == 'i' && buf[4] == 'f'
  301.                     && buf[5] == 0)
  302.                     cx.x_token = T_ENDIF;
  303.                 else if (buf[1] == 'l' && buf[2] == 's')
  304.                     if (buf[3] == 'i' && buf[4] == 'f'
  305.                         && buf[5] == 0)
  306.                         cx.x_token = T_ELSIF;
  307.                     else if (buf[3] == 'e' && buf[4] == 0)
  308.                         cx.x_token = T_ELSE;
  309.                 break;
  310.             }
  311.             if (cx.x_token == T_STR
  312.                 && (cx.x_val.v_str = str_cpy(buf)) == 0) {
  313.                 p_memerror();
  314.                 cx.x_token = T_EOF;
  315.             }
  316.             state = -1;
  317.             break;
  318.         }
  319.         break;
  320.     case 3:                /* " quoted string */
  321.         switch (c) {
  322.         case '\n':
  323.             (void) s_ungetc(c);
  324.         case EOF:
  325.         case '"':
  326.             state = 2;
  327.             break;
  328.         case '\\':
  329.             switch (c = s_gettok1()) {
  330.             case -1:
  331.             case -2:    /* newlines are invisible */
  332.                 break;
  333.             default:
  334.                 if (p < buf + sizeof buf - 1)
  335.                     *p++ = c;
  336.             }
  337.             break;
  338.         default:
  339.             if (p < buf + sizeof buf - 1)
  340.                 *p++ = c;
  341.             break;
  342.         }
  343.         break;
  344.     case 4:                /* ' quoted string */
  345.         switch (c) {
  346.         case '\n':
  347.             (void) s_ungetc(c);
  348.         case EOF:
  349.         case '\'':
  350.             state = 2;
  351.             break;
  352.         case '\\':
  353.             switch (c = s_gettok1()) {
  354.             case -1:
  355.             case -2:    /* newlines are invisible */
  356.                 break;
  357.             default:
  358.                 if (p < buf + sizeof buf - 1)
  359.                     *p++ = c;
  360.             }
  361.             break;
  362.         default:
  363.             if (p < buf + sizeof buf - 1)
  364.                 *p++ = c;
  365.             break;
  366.         }
  367.         break;
  368.     case 10:            /* got 0 */
  369.         switch (c) {
  370.         case 'x':
  371.         case 'X':
  372.             cx.x_val.v_num = 0;
  373.             state = 12;
  374.             break;
  375.         case '0': case '1': case '2': case '3': case '4':
  376.         case '5': case '6': case '7':
  377.             cx.x_val.v_num = c - '0';
  378.             state = 13;
  379.             break;
  380.         case '8': case '9':
  381.             cx.x_val.v_num = c - '0';
  382.             state = 11;
  383.             break;
  384.         default:
  385.             (void) s_ungetc(c);
  386.             state = -1;
  387.             cx.x_token = T_NUM;
  388.         }
  389.         break;
  390.     case 11:            /* decimal number */
  391.         switch (c) {
  392.         case '0': case '1': case '2': case '3': case '4':
  393.         case '5': case '6': case '7': case '8': case '9':
  394.             cx.x_val.v_num = cx.x_val.v_num * 10 + c - '0';
  395.             break;
  396.         default:
  397.             (void) s_ungetc(c);
  398.             state = -1;
  399.             cx.x_token = T_NUM;
  400.         }
  401.         break;
  402.     case 12:            /* hex number */
  403.         switch (c) {
  404.         case '0': case '1': case '2': case '3': case '4':
  405.         case '5': case '6': case '7': case '8': case '9':
  406.             cx.x_val.v_num = cx.x_val.v_num * 16 + c - '0';
  407.             break;
  408.         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
  409.             cx.x_val.v_num = cx.x_val.v_num * 16 + c - 'a' + 10;
  410.             break;
  411.         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
  412.             cx.x_val.v_num = cx.x_val.v_num * 16 + c - 'A' + 10;
  413.             break;
  414.         default:
  415.             (void) s_ungetc(c);
  416.             state = -1;
  417.             cx.x_token = T_NUM;
  418.         }
  419.         break;
  420.     case 13:            /* octal number */
  421.         switch (c) {
  422.         case '0': case '1': case '2': case '3': case '4':
  423.         case '5': case '6': case '7':
  424.             cx.x_val.v_num = cx.x_val.v_num * 8 + c - '0';
  425.             break;
  426.         default:
  427.             (void) s_ungetc(c);
  428.             state = -1;
  429.             cx.x_token = T_NUM;
  430.         }
  431.         break;
  432.     case 20:            /* got > */
  433.         switch (c) {
  434.         case '=':
  435.             cx.x_token = T_GE;
  436.             state = -1;
  437.             break;
  438.         case '>':
  439.             cx.x_token = T_RS;
  440.             state = -1;
  441.             break;
  442.         default:
  443.             (void) s_ungetc(c);
  444.             cx.x_token = T_GT;
  445.             state = -1;
  446.         }
  447.         break;
  448.     case 21:            /* got < */
  449.         switch (c) {
  450.         case '=':
  451.             cx.x_token = T_LE;
  452.             state = -1;
  453.             break;
  454.         case '<':
  455.             cx.x_token = T_LS;
  456.             state = -1;
  457.             break;
  458.         default:
  459.             (void) s_ungetc(c);
  460.             cx.x_token = T_LT;
  461.             state = -1;
  462.         }
  463.         break;
  464.     case 22:            /* got = */
  465.         switch (c) {
  466.         case '=':
  467.             cx.x_token = T_EQ;
  468.             state = -1;
  469.             break;
  470.         default:
  471.             (void) s_ungetc(c);
  472.             cx.x_token = T_ASSIGN;
  473.             state = -1;
  474.         }
  475.         break;
  476.     case 23:            /* got ! */
  477.         switch (c) {
  478.         case '=':
  479.             cx.x_token = T_NE;
  480.             state = -1;
  481.             break;
  482.         default:
  483.             (void) s_ungetc(c);
  484.             cx.x_token = T_NOT;
  485.             state = -1;
  486.         }
  487.         break;
  488.     case 24:            /* got & */
  489.         switch (c) {
  490.         case '&':
  491.             cx.x_token = T_ANDAND;
  492.             state = -1;
  493.             break;
  494.         default:
  495.             (void) s_ungetc(c);
  496.             cx.x_token = T_AND;
  497.             state = -1;
  498.         }
  499.         break;
  500.     case 25:            /* got | */
  501.         switch (c) {
  502.         case '|':
  503.             cx.x_token = T_OROR;
  504.             state = -1;
  505.             break;
  506.         default:
  507.             (void) s_ungetc(c);
  508.             cx.x_token = T_OR;
  509.             state = -1;
  510.         }
  511.         break;
  512.     case 26:            /* got $ */
  513.         switch (c) {
  514.         case '?':
  515.             cx.x_token = T_DQ;
  516.             state = -1;
  517.             break;
  518.         default:
  519.             (void) s_ungetc(c);
  520.             cx.x_token = T_DOLLAR;
  521.             state = -1;
  522.         }
  523.         break;
  524.     default:
  525.         abort();
  526.     }
  527.     if (state >= 0)
  528.         goto loop;
  529.     return cx.x_token;
  530. }
  531.  
  532. s_gettok1()
  533. {
  534.     register c;
  535.     register n;
  536.  
  537.     c = s_getc();            /* got \ */
  538.     switch (c) {
  539.     case EOF:
  540.         return -1;
  541.     case '\n':
  542.         return -2;
  543.     case 'b':
  544.         return '\b';
  545.     case 'f':
  546.         return '\f';
  547.     case 'n':
  548.         return '\n';
  549.     case 'r':
  550.         return '\r';
  551.     case 't':
  552.         return '\t';
  553.     default:
  554.         return c;
  555.     case '0': case '1': case '2': case '3': case '4':
  556.     case '5': case '6': case '7':
  557.         break;
  558.     }
  559.     n = c - '0';
  560.     c = s_getc();            /* got \[0-7] */
  561.     if (c < '0' || c > '7') {
  562.         (void) s_ungetc(c);
  563.         return n;
  564.     }
  565.     n = n * 8 + c - '0';
  566.     c = s_getc();            /* got \[0-7][0-7] */
  567.     if (c < '0' || c > '7') {
  568.         (void) s_ungetc(c);
  569.         return n;
  570.     }
  571.     return n * 8 + c - '0';
  572. }
  573.