home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 357_01 / cstar1.exe / TOK.C < prev    next >
C/C++ Source or Header  |  1991-06-18  |  4KB  |  266 lines

  1. /*
  2.     C* -- Token parsing routines (character routines) for the preprocessor.
  3.  
  4.     source:  tok.c
  5.     started: October 7, 1985
  6.     version:
  7.         January 6, 1987
  8.         March 7, 1989
  9.  
  10.     PUBLIC DOMAIN SOFTWARE
  11.  
  12.     The CSTAR program was placed in    the public domain on June 15, 1991,
  13.     by its author and sole owner,
  14.  
  15.         Edward K. Ream
  16.         1617 Monroe Street
  17.         Madison, WI 53711
  18.         (608) 257-0802
  19.  
  20.     CSTAR may be used for any commercial or non-commercial purpose.
  21.  
  22.     See cstar.h or cstar.c for a DISCLAIMER OF WARRANTIES.
  23. */
  24. #include "cstar.h"
  25.  
  26. /*
  27.     Externally visible routines:
  28. */
  29. int    t_number    (void);
  30. void    t_string    (char * symbol);
  31. void    t_comment    (void);
  32. void    t_id        (char * symbol);
  33.  
  34. /*
  35.     Scan past a comment. Allow nested comments if nest_flag is TRUE.
  36.     Surprisingly, this routine needs to be as fast as possible.
  37. */
  38. void
  39. t_comment(void)
  40. {
  41.     register int clevel;
  42.     int start_line;
  43.     char line [LONG_DIGITS];
  44.  
  45.     TICK("t_comment");
  46.  
  47.     /* Save starting line number for run-on comments. */
  48.     start_line = t_line;
  49.     clevel = 1;
  50.  
  51.     for (;;) {
  52.         switch (ch) {
  53.  
  54.         /* Don't read past end of file. */
  55.         case END_FILE:
  56.             goto runon;
  57.  
  58.         case '\n':
  59.             /* Keep track of line numbering. */
  60.             sysnext();
  61.  
  62.             /*
  63.                 Bump the line count and output a newline
  64.                 if this is used in a standalone preprocessor.
  65.                 Do NOT allow directives here.
  66.             */
  67.             do_nl();
  68.             begin_line(FALSE);
  69.             TRACEP("t_comment", printf("new line %d\n", t_line));
  70.             continue;
  71.  
  72.         case '\r':
  73.             sysnext();
  74.             continue;
  75.  
  76.         case '/':
  77.  
  78.             sysnext();
  79.             if (ch == '*') {
  80.                 sysnext();
  81.                 if (nest_flag) {
  82.                     clevel++;
  83.                 }
  84.             }
  85.             continue;
  86.  
  87.         case '*':
  88.  
  89.             sysnext();
  90.             if (ch == '/') {
  91.                 sysnext();
  92.                 if (--clevel == 0) {
  93.                     return;
  94.                 }
  95.             }
  96.             continue;
  97.  
  98.  
  99.         default:
  100.             sysnext();
  101.         }
  102.     }
  103.  
  104. runon:
  105.     (void) conv2s(start_line, line);
  106.     t_2error("File ends in a comment starting at line ", line);
  107. }
  108.  
  109. /*
  110.     Put an identifier into symbol[] and its length in the global t_length.
  111.     Surprisingly, this routine should be as fast as possible.
  112. */
  113. void
  114. t_id(register char * symbol)
  115. {
  116.     register int length;
  117.     register char ch1;
  118.  
  119.     TICK("t_id");
  120.  
  121.     length = 0;
  122.     while (ch1 = ch, isid2(ch1)) {
  123.         *symbol++ = ch1;
  124.         length++;
  125.         sysnext();
  126.     }
  127.     *symbol = '\0';
  128.     t_length = length;
  129. }
  130.  
  131. /*
  132.     Parse an integer constant (octal, decimal or hexadecimal).
  133.     Put the value in t_value.
  134.     Return the token type (INT_TYPE, LONG_TYPE).
  135.  
  136.     Legal forms:    ddd,    0ddd,    0xddd
  137. */
  138. int
  139. t_number(void)
  140. {
  141.     TICK("t_number");
  142.  
  143.     /* Defaults. */
  144.     t_value = 0;
  145.  
  146.     /* Leading 0 or 0x changes base. */    
  147.     if (ch == '0') {
  148.         sysnext();
  149.         if (ch == 'x' || ch == 'X') {
  150.             sysnext();
  151.             scan_number(16);
  152.         }
  153.         else if (isdigit(ch)) {
  154.             scan_number(8);
  155.         }
  156.         else {
  157.             /* Lone '0'. */
  158.             t_value = 0;
  159.         }
  160.     }
  161.     else {
  162.         scan_number(10);
  163.     }
  164.  
  165.     if (ch == 'l' || ch == 'L') {
  166.         sysnext();
  167.         return LONG_TOK;
  168.     }
  169.     else {
  170.         return INT_TOK;
  171.     }
  172. }
  173.  
  174. /*
  175.     Put a string into symbol[] and its length in the global t_length.
  176.  
  177.     This is used to parse both strings and character constants.
  178. */
  179. void
  180. t_string(register char * symbol)
  181. {
  182.     register char delim;
  183.     register int length;
  184.     int start_line;
  185.     char msg [100];
  186.     char line [10];
  187.  
  188.     TICK("t_string");
  189.  
  190.     /* Save starting line number for error messages. */
  191.     start_line = t_line;
  192.  
  193.     /* Skip over the opening double quote */
  194.     delim = ch;
  195.     sysnext();
  196.  
  197.     length = 0;
  198.     while (length < MAX_SYMBOL - 1) {
  199.  
  200.         TICK("t_string1");
  201.  
  202.         switch(ch) {
  203.  
  204.         case END_FILE:
  205.         case '\n':
  206.             goto runon1;
  207.  
  208.         case '\r':
  209.             sysnext();
  210.             continue;
  211.  
  212.         case '"':
  213.         case '\'':
  214.             if (ch == delim) {
  215.                 sysnext();
  216.                 *symbol++ = '\0';
  217.                 t_length  = length;
  218.                 return;
  219.             }
  220.             else{
  221.                 *symbol++ = ch;
  222.                 length++;
  223.                 sysnext();
  224.             }
  225.             continue;
  226.  
  227.         case '\\':
  228.  
  229.             sysnext();
  230.             if (ch == END_FILE) {
  231.                 goto runon1;
  232.             }
  233.             else if (skip_crlf()) {
  234.                 /* Ignore back slash and newline. */
  235.                 t_line++;
  236.             }
  237.             else {
  238.                 *symbol++ = '\\';
  239.                 *symbol++ = ch;
  240.                 length += 2;
  241.                 sysnext();
  242.             }
  243.             continue;
  244.  
  245.         default:
  246.             *symbol++ = ch;
  247.             length++;
  248.             sysnext();
  249.         }
  250.     }
  251.  
  252.     conv2s(start_line, line);
  253.     strcpy(msg, "String starting at line ");
  254.     strcat(msg, line);
  255.     strcat(msg, " is too long.");
  256.     t_error(msg);
  257.     *symbol = '\0';
  258.     t_length = length;
  259.     return;
  260.  
  261. runon1:
  262.     t_error("String crosses a line.");
  263.     *symbol = '\0';
  264.     t_length = length;
  265. }
  266.