home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / sun / volume1 / tooltool2.1c / part05 / lex.c < prev   
Encoding:
C/C++ Source or Header  |  1989-06-06  |  12.8 KB  |  447 lines

  1. /************************************************************************/
  2. /*    Copyright 1988 by Chuck Musciano and Harris Corporation        */
  3. /*                                    */
  4. /*    Permission to use, copy, modify, and distribute this software    */
  5. /*    and its documentation for any purpose and without fee is    */
  6. /*    hereby granted, provided that the above copyright notice    */
  7. /*    appear in all copies and that both that copyright notice and    */
  8. /*    this permission notice appear in supporting documentation, and    */
  9. /*    that the name of Chuck Musciano and Harris Corporation not be    */
  10. /*    used in advertising or publicity pertaining to distribution    */
  11. /*    of the software without specific, written prior permission.    */
  12. /*    Chuck Musciano and Harris Corporation make no representations    */
  13. /*    about the suitability of this software for any purpose.  It is    */
  14. /*    provided "as is" without express or implied warranty.        */
  15. /*                                    */
  16. /*    The sale of any product based wholely or in part upon the     */
  17. /*    technology provided by tooltool is strictly forbidden without    */
  18. /*    specific, prior written permission from Harris Corporation.    */
  19. /*    Tooltool technology includes, but is not limited to, the source    */
  20. /*    code, executable binary files, specification language, and    */
  21. /*    sample specification files.                    */
  22. /************************************************************************/
  23.  
  24. #define        RETURN(x)        return(last_token = (x))
  25.  
  26. #define        FIRST_KEYWORD        ACTION
  27. #define        LAST_KEYWORD        WIDTH
  28. #define        NUM_KEYWORDS        (LAST_KEYWORD - FIRST_KEYWORD + 1)
  29.  
  30. #define        CPP            "/lib/cpp"
  31.  
  32. PRIVATE    FILE    *f;
  33. PRIVATE    int    last_token = -1;
  34. PRIVATE    char    buf[1024];
  35.  
  36. PRIVATE    struct    {char    *name;
  37.          int    value;
  38.         } token[] = {{"action",        ACTION},
  39.                  {"align",        ALIGN},
  40.                  {"application",    APPLICATION},
  41.                  {"at",        AT},
  42.                  {"base",        BASE},
  43.                  {"beep",        BEEP},
  44.                  {"bottom",        BOTTOM},
  45.                  {"break",        BREAK},
  46.                  {"button",        BUTTON},
  47.                  {"by",        BY},
  48.                  {"center",        CENTER},
  49.                  {"characters",    CHARACTERS},
  50.                  {"choice",        CHOICE},
  51.                  {"close",        CLOSE},
  52.                  {"completion",    COMPLETION},
  53.                  {"continue",    CONTINUE},
  54.                  {"control",    CONTROL},
  55.                  {"current",    CURRENT},
  56.                  {"cycle",        CYCLE},
  57.                  {"dialog",        DIALOG},
  58.                  {"disable",    DISABLE},
  59.                  {"display",    DISPLAY},
  60.                  {"else",        ELSE},
  61.                  {"end_button",    END_BUTTON},
  62.                  {"end_choice",    END_CHOICE},
  63.                  {"end_dialog",    END_DIALOG},
  64.                  {"end_gadgets",    END_GADGETS},
  65.                  {"end_key",    END_KEY},
  66.                  {"end_keys",    END_KEYS},
  67.                  {"end_label",    END_LABEL},
  68.                  {"end_menu",    END_MENU},
  69.                  {"end_mouse",    END_MOUSE},
  70.                  {"end_slider",    END_SLIDER},
  71.                  {"end_text",    END_TEXT},
  72.                  {"exit",        EXIT},
  73.                  {"font",        FONT},
  74.                  {"for",        FOR},
  75.                  {"function_keys",    FUNCTION_KEYS},
  76.                  {"gadgets",    GADGETS},
  77.                  {"horizontal",    HORIZONTAL},
  78.                  {"icon",        ICON},
  79.                  {"if",        IF},
  80.                  {"ignore",        IGNORE},
  81.                  {"initial",    INITIAL},
  82.                  {"initialize",    INITIALIZE},
  83.                  {"key",        KEY},
  84.                  {"keys",        KEYS},
  85.                  {"label",        LABEL},
  86.                  {"left",        LEFT},
  87.                  {"mark",        MARK},
  88.                  {"maximum",    MAXIMUM},
  89.                  {"menu",        MENU},
  90.                  {"meta",        META},
  91.                  {"middle",        MIDDLE},
  92.                  {"minimum",    MINIMUM},
  93.                  {"mouse",        MOUSE},
  94.                  {"nomark",        NOMARK},
  95.                  {"normal",        NORMAL},
  96.                  {"normal_keys",    NORMAL_KEYS},
  97.                  {"nothing",    NOTHING},
  98.                  {"off",        OFF},
  99.                  {"on",        ON},
  100.                  {"open",        OPEN},
  101.                  {"pixels",        PIXELS},
  102.                  {"popup",        POPUP},
  103.                  {"proportional",    PROPORTIONAL},
  104.                  {"ragged",        RAGGED},
  105.                  {"range",        RANGE},
  106.                  {"remove",        REMOVE},
  107.                  {"retain",        RETAIN},
  108.                  {"right",        RIGHT},
  109.                  {"send",        SEND},
  110.                  {"shift",        SHIFT},
  111.                  {"size",        SIZE},
  112.                  {"slider",        SLIDER},
  113.                  {"text",        TEXT},
  114.                  {"timer",        TIMER},
  115.                  {"top",        TOP},
  116.                  {"trigger",    TRIGGER},
  117.                  {"ttymenu",    TTYMENU},
  118.                  {"value",        VALUE},
  119.                  {"vertical",    VERTICAL},
  120.                  {"while",        WHILE},
  121.                  {"width",        WIDTH}};
  122.  
  123. PRIVATE    struct    {char    first;
  124.          char    next;
  125.          int    name;
  126.         } punc[] = {{'&',  '\0', LOGICAL_AND},
  127.                 {'&',  '&',  AND},
  128.                 {'&',  '=',  ASSIGN_AND},
  129.                 {':',  '\0', COLON},
  130.                 {',',  '\0', COMMA},
  131.                 {'~',  '\0', COMPLEMENT},
  132.                 {'=',  '\0', ASSIGNMENT},
  133.                 {'=',  '=',  EQUAL},
  134.                 {'>',  '\0', GREATER},
  135.                 {'>',  '=',  GREATER_EQUAL},
  136.                 {'>',  '>',  RIGHT_SHIFT},
  137.                 {'{',  '\0', LBRACE},
  138.                 {'[',  '\0', LBRACK},
  139.                 {'<',  '\0', LESS},
  140.                 {'<',  '=',  LESS_EQUAL},
  141.                 {'<',  '<',  LEFT_SHIFT},
  142.                 {'!',  '\0', LOGICAL_NOT},
  143.                 {'!',  '=',  NOT_EQUAL},
  144.                 {'|',  '\0', OR},
  145.                 {'|',  '|',  LOGICAL_OR},
  146.                 {'|',  '=',  ASSIGN_OR},
  147.                 {'(',  '\0', LPAREN},
  148.                 {'-',  '\0', MINUS},
  149.                 {'-',  '-',  DECREMENT},
  150.                 {'-',  '=',  ASSIGN_MINUS},
  151.                 {'%',  '\0', MODULO},
  152.                 {'%',  '=',  ASSIGN_MODULO},
  153.                 {'+',  '\0', PLUS},
  154.                 {'+',  '+',  INCREMENT},
  155.                 {'+',  '=',  ASSIGN_PLUS},
  156.                 {'?',  '\0', QUESTION},
  157.                 {'}',  '\0', RBRACE},
  158.                 {']',  '\0', RBRACK},
  159.                 {')',  '\0', RPAREN},
  160.                 {';',  '\0', SEMICOLON},
  161.                 {'*',  '\0', TIMES},
  162.                 {'*',  '=',  ASSIGN_TIMES},
  163.                 {'^',  '\0', XOR},
  164.                 {'^',  '=',  ASSIGN_XOR},
  165.                 {'\0', '\0', -1}};
  166.  
  167. PRIVATE    char    getch()
  168.  
  169. {    register    char    c;
  170.     static        int    first = TRUE;
  171.  
  172.     if (first) {
  173.        first = FALSE;
  174.        if ((f = popen(CPP, "r")) == NULL)
  175.           abend("could not invoke %s", CPP);
  176.        }
  177.     if (ungetc != -1)
  178.        c = ungetc, ungetc = -1;
  179.     else {
  180.        c = getc(f);
  181.        if (c == '\n')
  182.           line_count++;
  183.        }
  184.     return(c);
  185. }
  186.  
  187. PRIVATE    fix_escapes(buf)
  188.  
  189. char    *buf;
  190.  
  191. {    char    *q;
  192.     int    i;
  193.  
  194.     for (q = buf; *buf; buf++, q++)
  195.        if (*buf == '\\')
  196.           switch (*++buf) {
  197.              case 'b' : *q = '\010'; /* ^h */
  198.                         break;
  199.              case 'e' : *q = '\033'; /* esc */
  200.                       break;
  201.              case 'f' : *q = '\014'; /* ^l */
  202.                         break;
  203.              case 'n' : *q = '\012'; /* ^j */
  204.                         break;
  205.              case 'r' : *q = '\015'; /* ^m */
  206.                         break;
  207.              case 't' : *q = '\011'; /* ^i */
  208.                         break;
  209.              case '0' : 
  210.              case '1' : 
  211.              case '2' : 
  212.              case '3' : 
  213.              case '4' : 
  214.              case '5' : 
  215.              case '6' : 
  216.              case '7' : *q = *buf++ - '0';
  217.                         for (i = 0; i < 2 && *buf >= '0' && *buf <= '7'; i++)
  218.                            *q = (*q << 3) + *buf++ - '0';
  219.                         buf--;
  220.                         break;
  221.              default  : *q = *buf;
  222.                         break;
  223.              }
  224.        else if (*buf == '^' && *(buf + 1) >= '@' && *(buf + 1) <= '_')
  225.           *q = *++buf & 0x1f;
  226.        else
  227.           *q = *buf;
  228.     *q = '\0';
  229. }
  230.  
  231. PRIVATE    int    is_keyword(s)
  232.  
  233. char    *s;
  234.  
  235. {    register    int    cmp, high, low, pos;
  236.  
  237.     for (low = 0, high = NUM_KEYWORDS - 1; low <= high; )
  238.        if ((cmp = strcmp(s, token[pos = (high - low) / 2 + low].name)) == 0)
  239.           return(token[pos].value);
  240.        else if (cmp < 0)
  241.           high = pos - 1;
  242.        else
  243.           low = pos + 1;
  244.     return(NULL);
  245. }
  246.  
  247. PRIVATE    int    yylex()
  248.  
  249. {    register    char    c, c1, *p;
  250.     register    int    i, j, val;
  251.     char            *index();
  252.     double            atof();
  253.  
  254.     c = getch();
  255.     while (isspace(c))
  256.        c = getch();
  257.     if (isalpha(c)) {
  258.        p = buf;
  259.        *p++ = c;
  260.        while (isalnum(c = getch()) || c == '_')
  261.           *p++ = c;
  262.        ungetc = c;
  263.        *p = '\0';
  264.        for (p = buf; *p; p++)
  265.           if (isupper(*p))
  266.              *p = tolower(*p);
  267.        if (i = is_keyword(buf))
  268.           RETURN(i);
  269.        if ((i = strlen(buf)) == 2) { /* possible two character function key name */
  270.           if (buf[0] == 'l' && buf[1] >= '2' && buf[1] <= '9') /* l2 - l9 */
  271.              RETURN(yylval.ival = L2 + buf[1] - '2');
  272.           else if (buf[0] == 'f' && buf[1] >= '1' && buf[1] <= '9') /* f1 - f9 */
  273.              RETURN(yylval.ival = F1 + buf[1] - '1');
  274.           else if (buf[0] == 'r' && buf[1] >= '1' && buf[1] <= '9') /* r1 - r9 */
  275.              RETURN(yylval.ival = R1 + buf[1] - '1');
  276.           }
  277.        else if (i == 3) { /* possible three character function key name */
  278.           if (buf[0] == 'l' && buf[1] == '1' && buf[2] == '0')
  279.              RETURN(yylval.ival = L10);
  280.           else if (buf[0] == 'r' && buf[1] == '1' && buf[2] >= '0' && buf[2] <= '5') /* r10 - r15 */
  281.              RETURN(yylval.ival = R10 + buf[2] - '0');
  282.           }
  283.        fix_escapes(buf);
  284.        yylval.cpval = strsave(buf);
  285.        RETURN(ID);
  286.        }
  287.     else if (c == '"') {
  288.        for (p = buf; TRUE; p++)
  289.           if ((*p = getch()) == '"')
  290.              break;
  291.           else if (*p == '\\')
  292.              *++p = getch();
  293.           else if (*p == '\n' || *p == '\r') {
  294.              yyerror("Newline in string not allowed");
  295.              break;
  296.              }
  297.        *p = '\0';
  298.        fix_escapes(buf);
  299.        yylval.cpval = strsave(buf);
  300.        RETURN(STRING);
  301.        }
  302.     else if (c == '\'') {
  303.        p = buf;
  304.        for (p = buf; TRUE; p++)
  305.           if ((*p = getch()) == '\'')
  306.              break;
  307.           else if (*p == '\\')
  308.              *++p = getch();
  309.           else if (*p == '\n' || *p == '\r') {
  310.              yyerror("Newline in string not allowed");
  311.              break;
  312.              }
  313.        *p = '\0';
  314.        fix_escapes(buf);
  315.        yylval.cpval = strsave(buf);
  316.        RETURN(ICON_STRING);
  317.        }
  318.     else if (isdigit(c)) {
  319.        if (c == '0') {
  320.           if ((c = getch()) == 'x') /* hex number */
  321.              for (val = 0; isxdigit(c = getch()); )
  322.                 if (isdigit(c))
  323.                    val = val * 16 + c - '0';
  324.                 else
  325.                    val = val * 16 + c - (isupper(c)? 'A' : 'a');
  326.           else if (isdigit(c)) /* octal */
  327.              for (val = c - '0'; (c = getch()) >= '0' && c <= '7'; )
  328.                 val = val * 8 + c - '0';
  329.           else if (c == '.') {
  330.              ungetc = c;
  331.              c = '0';
  332.              goto do_real; /* with God as my witness, I'll never do this again, I swear */
  333.              }
  334.           else
  335.              val = 0;
  336.           ungetc = c;
  337.           yylval.ival = val;
  338.           RETURN(INTEGER);
  339.           }
  340.        else {
  341. do_real:      p = buf;
  342.           *p++ = c;
  343.           val = INTEGER;
  344.           while (isdigit(c = getch()))
  345.              *p++ = c;
  346.           if (c == '.')
  347.              for (*p++ = c, val = REAL; isdigit(c = getch()); )
  348.                 *p++ = c;
  349.           if (c == 'e' || c == 'E') {
  350.              *p++ = c;
  351.              if ((c = getch()) == '-' || c == '+')
  352.                 *p++ = c;
  353.              else
  354.                 ungetc = c;
  355.              for (val = REAL; isdigit(c = getch()); )
  356.                 *p++ = c;
  357.              }
  358.           *p = '\0';
  359.           ungetc = c;
  360.           if (val == INTEGER)
  361.              yylval.ival = atoi(buf);
  362.           else
  363.              yylval.rval = atof(buf);
  364.           RETURN(val);
  365.           }
  366.        }
  367.     else if (c == '/') {
  368.        if ((c = getch()) == '*') {
  369.           while (1) {
  370.              while ((c = getch()) != '*')
  371.                 ;
  372.              if ((c = getch()) == '/')
  373.                 break;
  374.              }
  375.           }
  376.        else if (c == '=')
  377.           RETURN(ASSIGN_DIVIDE);
  378.        else {
  379.           ungetc = c;
  380.           RETURN(DIVIDE);
  381.           }
  382.        }
  383.     else if (c == '#') {
  384.        if (yylex() == INTEGER) {
  385.           line_count = yylval.ival - 1; /* getch will bump by 1 when \n is read */
  386.           if (yylex() == STRING) {
  387.              if (*yylval.cpval)
  388.                 tt_curr_file = yylval.cpval;
  389.              while (getch() != '\n')
  390.                 ;
  391.              RETURN(yylex());
  392.              }
  393.           }
  394.        yyerror("Invalid cpp control sequence in source file");
  395.        }
  396.     else if (c == EOF) {
  397.        pclose(f);
  398.        RETURN(EOF);
  399.        }
  400.     else {
  401.        for (i = 0; punc[i].first; i++)
  402.           if (c == punc[i].first) {
  403.              for (c1 = getch(), j = 1; punc[i + j].first == c; j++)
  404.                 if (c1 == punc[i + j].next)
  405.                    RETURN(punc[i + j].name);
  406.              ungetc = c1;
  407.              RETURN(punc[i].name);
  408.              }
  409.        yyerror("Invalid character in source file: %c (0x%02x)", c, c);
  410.        }
  411.     RETURN(yylex());
  412. }
  413.  
  414. /************************************************************************/
  415. PRIVATE    print_last_token()
  416.  
  417. {    int    i;
  418.  
  419.     fprintf(stderr, " at or near \"");
  420.     if (last_token == INTEGER || last_token == REAL || last_token == STRING || last_token == ICON_STRING || last_token == ID)
  421.        fprintf(stderr, buf);
  422.     else if (last_token >= L2 && last_token <= L10)
  423.        fprintf(stderr, "L%d", last_token - L2 + 2);
  424.     else if (last_token >= F1 && last_token <= F9)
  425.        fprintf(stderr, "F%d", last_token - F1 + 1);
  426.     else if (last_token >= R1 && last_token <= R15)
  427.        fprintf(stderr, "R%d", last_token - R1 + 1);
  428.     else if (last_token >= AND && last_token <= XOR) {
  429.        for (i = 0; punc[i].first; i++)
  430.           if (punc[i].name == last_token) {
  431.              fprintf(stderr, "%c", punc[i].first);
  432.              if (punc[i].next)
  433.                 fprintf(stderr, "%c", punc[i].next);
  434.              break;
  435.              }
  436.        if (punc[i].first == '\0')
  437.           fprintf(stderr, "!!Geez!  Some punctuation, I don't know!!");
  438.        }
  439.     else if (last_token >= FIRST_KEYWORD && last_token <= LAST_KEYWORD)
  440.        fprintf(stderr, token[last_token - FIRST_KEYWORD].name);
  441.     else if (last_token == EOF)
  442.        fprintf(stderr, "End Of File");
  443.     else
  444.        fprintf(stderr, "!!Geez!  Some keyword, I don't know!!");
  445.     fprintf(stderr, "\"");
  446. }
  447.