home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 4 / DATAFILE_PDCD4.iso / utilities / utilsf / indent / Source / c / lexi < prev    next >
Text File  |  1995-10-27  |  16KB  |  615 lines

  1. /*
  2.  * Copyright (c) 1985 Sun Microsystems, Inc.
  3.  * Copyright (c) 1980 The Regents of the University of California.
  4.  * Copyright (c) 1976 Board of Trustees of the University of Illinois.
  5.  * All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms are permitted
  8.  * provided that the above copyright notice and this paragraph are
  9.  * duplicated in all such forms and that any documentation,
  10.  * advertising materials, and other materials related to such
  11.  * distribution and use acknowledge that the software was developed
  12.  * by the University of California, Berkeley, the University of Illinois,
  13.  * Urbana, and Sun Microsystems, Inc.  The name of either University
  14.  * or Sun Microsystems may not be used to endorse or promote products
  15.  * derived from this software without specific prior written permission.
  16.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  18.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19.  */
  20.  
  21. /* Archimedes port by Steven Flintham
  22.    Wednesday 25th October 1995
  23.    Friday 27th October 1995 */
  24.  
  25. #ifndef lint
  26. static char sccsid[] = "@(#)lexi.c    5.11 (Berkeley) 9/15/88";
  27. #endif /* not lint */
  28.  
  29. /*
  30.  * Here we have the token scanner for indent.  It scans off one token and puts
  31.  * it in the global variable "token".  It returns a code, indicating the type
  32.  * of token scanned.
  33.  */
  34.  
  35. #ifndef __riscos /* SF */
  36. #include "indent_globs.h"
  37. #include "indent_codes.h"
  38. #else
  39. #include "indntglobs.h"
  40. #include "indntcodes.h"
  41. #endif /* __riscos */
  42. #include "ctype.h"
  43.  
  44. typedef enum char_type {
  45.     alphanum = 1,
  46.     opchar = 3,
  47.     colonchar = 4
  48. } char_type;
  49.  
  50. struct templ {
  51.     char       *rwd;
  52.     int         rwcode;
  53.     cplus_flag        cplus;
  54. };
  55.  
  56. struct templ specials[100] =
  57. {
  58.     "switch", 1, c_and_cplus,
  59.     "case", 2, c_and_cplus,
  60.     "break", 0, c_and_cplus,
  61.     "struct", 3, c_and_cplus,
  62.     "union", 3, c_and_cplus,
  63.     "enum", 3, c_and_cplus,
  64.     "default", 2, c_and_cplus,
  65.     "int", 4, c_and_cplus,
  66.     "char", 4, c_and_cplus,
  67.     "float", 4, c_and_cplus,
  68.     "double", 4, c_and_cplus,
  69.     "long", 4, c_and_cplus,
  70.     "short", 4, c_and_cplus,
  71.     "typedef", 8, c_and_cplus,
  72.     "unsigned", 4, c_and_cplus,
  73.     "register", 4, c_and_cplus,
  74.     "static", 4, c_and_cplus,
  75.     "global", 4, c_and_cplus,
  76.     "extern", 4, c_and_cplus,
  77.     "void", 4, c_and_cplus,
  78.     "goto", 0, c_and_cplus,
  79.     "return", 0, c_and_cplus,
  80.     "if", 5, c_and_cplus,
  81.     "while", 5, c_and_cplus,
  82.     "for", 5, c_and_cplus,
  83.     "else", 6, c_and_cplus,
  84.     "do", 6, c_and_cplus,
  85.     "sizeof", 7, c_and_cplus,
  86.     "class", 3, cplus_only,
  87.     "public", 2, cplus_only,
  88.     "private", 2, cplus_only,
  89.     "protected", 2, cplus_only,
  90.     "volatile", 4, c_and_cplus,
  91.  
  92.     0, 0
  93. };
  94.  
  95. char   chartype[128] =
  96. {                /* this is used to facilitate the decision of
  97.                  * what type (alphanumeric, operator) each
  98.                  * character is */
  99.     0, 0, 0, 0, 0, 0, 0, 0,
  100.     0, 0, 0, 0, 0, 0, 0, 0,
  101.     0, 0, 0, 0, 0, 0, 0, 0,
  102.     0, 0, 0, 0, 0, 0, 0, 0,
  103.     0, 3, 0, 0, 1, 3, 3, 0,
  104.     0, 0, 3, 3, 0, 3, 0, 3,
  105.     1, 1, 1, 1, 1, 1, 1, 1,
  106.     1, 1, 4, 0, 3, 3, 3, 3,
  107.     0, 1, 1, 1, 1, 1, 1, 1,
  108.     1, 1, 1, 1, 1, 1, 1, 1,
  109.     1, 1, 1, 1, 1, 1, 1, 1,
  110.     1, 1, 1, 0, 0, 0, 3, 1,
  111.     0, 1, 1, 1, 1, 1, 1, 1,
  112.     1, 1, 1, 1, 1, 1, 1, 1,
  113.     1, 1, 1, 1, 1, 1, 1, 1,
  114.     1, 1, 1, 0, 3, 0, 3, 0
  115. };
  116.  
  117.  
  118.  
  119.  
  120. int
  121. lexi()
  122. {
  123.     register char *tok;        /* local pointer to next char in token */
  124.     int         unary_delim;    /* this is set to 1 if the current token
  125.                  *
  126.                  * forces a following operator to be unary */
  127.     static int  last_code;    /* the last token type returned */
  128.     static int  l_struct;    /* set to 1 if the last token was 'struct' */
  129.     static int  l_struct_start; /* set at struct, cleared at { or ; */
  130.     static int  l_class;    /* in c++, class name coming next. */
  131.     int         code;        /* internal code to be returned */
  132.     char        qchar;        /* the delimiter character for a string */
  133.  
  134.     tok = token;        /* point to start of place to save token */
  135.     unary_delim = false;
  136.     ps.col_1 = ps.last_nl;    /* tell world that this token started in
  137.                  * column 1 iff the last thing scanned was nl */
  138.     ps.last_nl = false;
  139.  
  140.     while (*buf_ptr == ' ' || *buf_ptr == '\t') {    /* get rid of blanks */
  141.     ps.col_1 = false;    /* leading blanks imply token is not in column
  142.                  * 1 */
  143.     if (++buf_ptr >= buf_end)
  144.         fill_buffer();
  145.     }
  146.  
  147.     /* Scan an alphanumeric token */
  148.     /* In c++, :: starting token is aok, as is ~ sometimes */
  149.     /* well, int x = ~y; will work oddly here */
  150.     if (((char_type)chartype[*buf_ptr] == alphanum || buf_ptr[0] == '.' && isdigit(buf_ptr[1])) ||
  151.     (cplus && buf_ptr[0] == ':' && buf_ptr[1] == ':') ||
  152.     (cplus && ps.in_decl && *buf_ptr == '~'
  153.      && (char_type)chartype[buf_ptr[1]] == alphanum) /* destructors in classdefs */
  154.     ) {
  155.     /*
  156.      * we have a character or number
  157.      */
  158.     register char *j;    /* used for searching thru list of
  159.                  *
  160.                  * reserved words */
  161.     register struct templ *p;
  162.  
  163.     if (isdigit(*buf_ptr) || buf_ptr[0] == '.' && isdigit(buf_ptr[1])) {
  164.         int         seendot = 0,
  165.                     seenexp = 0;
  166.         if (*buf_ptr == '0' &&
  167.             (buf_ptr[1] == 'x' || buf_ptr[1] == 'X')) {
  168.         *tok++ = *buf_ptr++;
  169.         *tok++ = *buf_ptr++;
  170.         while (isxdigit(*buf_ptr))
  171.             *tok++ = *buf_ptr++;
  172.         }
  173.         else
  174.         while (1) {
  175.             if (*buf_ptr == '.')
  176.             if (seendot)
  177.                 break;
  178.             else
  179.                 seendot++;
  180.             *tok++ = *buf_ptr++;
  181.             if (!isdigit(*buf_ptr) && *buf_ptr != '.')
  182.             if ((*buf_ptr != 'E' && *buf_ptr != 'e') || seenexp)
  183.                 break;
  184.             else {
  185.                 seenexp++;
  186.                 seendot++;
  187.                 *tok++ = *buf_ptr++;
  188.                 if (*buf_ptr == '+' || *buf_ptr == '-')
  189.                 *tok++ = *buf_ptr++;
  190.             }
  191.         }
  192.         if (*buf_ptr == 'L' || *buf_ptr == 'l')
  193.         *tok++ = *buf_ptr++;
  194.     }
  195.     else {
  196.         int first;
  197.         first = 1;
  198.         while ((char_type)chartype[*buf_ptr] == alphanum ||
  199.            (buf_ptr[0] == ':' && buf_ptr[1] == ':' && cplus) ||
  200.            (cplus && first && buf_ptr[0] == '~'))
  201.         {            /* copy it over */
  202.         int colonp;
  203.         first = 0;
  204.         colonp = *buf_ptr == ':';
  205.         *tok++ = *buf_ptr++;
  206.         if(colonp) {
  207.             *tok++ = *buf_ptr++;
  208.             /* foo::~foo */
  209.             if(*buf_ptr == '~') *tok++ = *buf_ptr++;
  210.             colonp = 0;
  211.         }
  212.         if (buf_ptr >= buf_end)
  213.             fill_buffer();
  214.         }
  215.     }
  216.     *tok++ = '\0';
  217.     while (*buf_ptr == ' ' || *buf_ptr == '\t') {    /* get rid of blanks */
  218.         if (++buf_ptr >= buf_end)
  219.         fill_buffer();
  220.     }
  221.     ps.its_a_keyword = false;
  222.     ps.sizeof_keyword = false;
  223.     if (l_struct) {        /* if last token was 'struct', then this token
  224.                  * should be treated as a declaration */
  225.         if(l_class) addkey(tok, 4);
  226.         l_class = false;
  227.         l_struct = false;
  228.         last_code = ident;
  229.         ps.last_u_d = true;
  230.         return (decl);
  231.     }
  232.     ps.last_u_d = false;    /* Operator after indentifier is binary */
  233.     last_code = ident;    /* Remember that this is the code we will
  234.                  * return */
  235.  
  236.     /*
  237.      * This loop will check if the token is a keyword.
  238.      */
  239.     for (p = specials; (j = p->rwd) != 0; p++) {
  240.         tok = token;    /* point at scanned token */
  241.         if (*j++ != *tok++ || *j++ != *tok++)
  242.         continue;    /* This test depends on the fact that
  243.                  * identifiers are always at least 1 character
  244.                  * long (ie. the first two bytes of the
  245.                  * identifier are always meaningful) */
  246.         if (tok[-1] == 0)
  247.         break;        /* If its a one-character identifier */
  248.         while (*tok++ == *j)
  249.         if (*j++ == 0 &&
  250.             (p->cplus == c_and_cplus ||
  251.              (cplus && p->cplus == cplus_only) ||
  252.              (!cplus && p->cplus == c_only)))
  253.             goto found_keyword;    /* I wish that C had a multi-level
  254.                      * break... */
  255.     }
  256.     if (p->rwd) {        /* we have a keyword */
  257.     found_keyword:
  258.         ps.its_a_keyword = true;
  259.         ps.last_u_d = true;
  260.         switch (p->rwcode) {
  261.         case 1:        /* it is a switch */
  262.         return (swstmt);
  263.         case 2:        /* a case or default */
  264.         return (casestmt);
  265.  
  266.         case 3:        /* a "struct" */
  267.         if (ps.p_l_follow)
  268.             break;    /* inside parens: cast */
  269.         l_struct = true;
  270.         if(cplus)l_struct_start = true;
  271.         /* automatically note keywords */
  272.         if(cplus && strcmp(tok, "class") == 0 ||
  273.            strcmp(tok, "struct") == 0 ||
  274.            strcmp(tok, "union") == 0 ||
  275.            strcmp(tok, "enum") == 0)
  276.             l_class =