home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v941.tgz / icon.v941src.tar / icon.v941src / src / preproc / gettok.c < prev    next >
C/C++ Source or Header  |  2001-12-12  |  7KB  |  253 lines

  1. /*
  2.  * This files contains routines for getting the "next" token.
  3.  */
  4. #include "../preproc/preproc.h"
  5. #include "../preproc/ptoken.h"
  6. #include "../preproc/pproto.h"
  7.  
  8. /*
  9.  * next_tok - get the next raw token. No macros are expanded here (although
  10.  *  the tokens themselves may be the result of a macro expansion initiated
  11.  *  at a "higher" level). Only #line directives are processed here.
  12.  */
  13. struct token *next_tok()
  14.    {
  15.    struct token *t, *t1;
  16.    struct tok_lst *tlst;
  17.    struct char_src *cs;
  18.    struct str_buf *sbuf;
  19.    char *s;
  20.    char *fname;
  21.    int n;
  22.  
  23.    if (src_stack->flag == DummySrc)
  24.       return NULL;    /* source stack is empty - end of input */
  25.  
  26.    /*
  27.     * See if a directive pushed back any tokens.
  28.     */
  29.    if (src_stack->ntoks > 0)
  30.       return src_stack->toks[--src_stack->ntoks];
  31.  
  32.    switch (src_stack->flag) {
  33.       case CharSrc:
  34.          /*
  35.           * Tokens from a raw character "stream".
  36.           */
  37.          t = tokenize();
  38.          if (t != NULL && src_stack->u.cs->f != NULL)
  39.             t->flag |= LineChk;
  40.          if (t != NULL && t->tok_id == PpLine) {
  41.             /*
  42.              * #line directives must be processed here so they are not
  43.              *  put in macros.
  44.              */
  45.             cs = src_stack->u.cs;
  46.             t1 = NULL;
  47.  
  48.             /*
  49.              * Get the line number from the directive.
  50.              */
  51.             advance_tok(&t1);
  52.             if (t1->tok_id != PpNumber)
  53.                errt1(t1, "#line requires an integer argument");
  54.             n = 0;
  55.             for (s = t1->image; *s != '\0'; ++s) {
  56.                if (*s >= '0' && *s <= '9')
  57.                   n = 10 * n + (*s - '0');
  58.                else
  59.                   errt1(t1, "#line requires an integer argument");
  60.                }
  61.  
  62.             /*
  63.              * Get the file name, if there is one, from the directive.
  64.              */
  65.             advance_tok(&t1);
  66.             fname = NULL;
  67.             if (t1->tok_id == StrLit) {
  68.                sbuf = get_sbuf();
  69.                for (s = t1->image; *s != '\0'; ++s) {
  70.                   if (s[0] == '\\' && (s[1] == '\\' || s[1] == '"'))
  71.                      ++s;
  72.                   AppChar(*sbuf, *s);
  73.                   }
  74.                fname = str_install(sbuf);
  75.                rel_sbuf(sbuf);
  76.                advance_tok(&t1);
  77.                }
  78.             if (t1->tok_id != PpDirEnd)
  79.                errt1(t1, "syntax error in #line");
  80.  
  81.             /*
  82.              * Note the effect of the line directive in the character
  83.              *  source. Line number changes are handled as a relative
  84.              *  adjustments to the line numbers of following lines.
  85.              */
  86.             if (fname != NULL)
  87.                cs->fname = fname;
  88.             cs->line_adj = n - cs->line_buf[next_char - first_char + 1];
  89.             if (*next_char == '\n')
  90.                ++cs->line_adj;  /* the next lines contains no characters */
  91.  
  92.             t = next_tok();     /* the caller does not see #line directives */
  93.             }
  94.          break;
  95.  
  96.       case MacExpand:
  97.          /*
  98.           * Tokens from macro expansion.
  99.           */
  100.          t = mac_tok();
  101.          break;
  102.  
  103.       case TokLst:
  104.          /*
  105.           * Tokens from a macro argument.
  106.           */
  107.          tlst = src_stack->u.tlst;
  108.          if (tlst == NULL)
  109.             t = NULL;
  110.          else {
  111.             t = copy_t(tlst->t);
  112.             src_stack->u.tlst = tlst->next;
  113.             }
  114.          break;
  115.  
  116.       case PasteLsts:
  117.          /*
  118.           * Tokens from token Pasting.
  119.           */
  120.          return paste();
  121.       }
  122.  
  123.    if (t == NULL) {
  124.       /*
  125.        * We have exhausted this entry on the source stack without finding
  126.        *  a token to return.
  127.        */
  128.       pop_src();
  129.       return next_tok();
  130.       }
  131.    else
  132.       return t;
  133.    }
  134.  
  135. /*
  136.  * Get the next raw non-white space token, freeing token that the argument
  137.  *  used to point to.
  138.  */
  139. void nxt_non_wh(tp)
  140. struct token **tp;
  141.    {
  142.    register struct token *t;
  143.  
  144.    t = next_tok();
  145.    while (t != NULL && t->tok_id == WhiteSpace) {
  146.       free_t(t);
  147.       t = next_tok();
  148.       }
  149.    free_t(*tp);
  150.    *tp = t;
  151.    }
  152.  
  153. /*
  154.  * advance_tok - skip past white space after expanding macros and
  155.  *  executing preprocessor directives. This routine may only be
  156.  *  called from within a preprocessor directive because it assumes
  157.  *  it will not see EOF (the input routines insure that a terminating
  158.  *  new-line, and thus, for a directive, the PpDirEnd token, will be
  159.  *  seen immediately before EOF).
  160.  */
  161. void advance_tok(tp)
  162. struct token **tp;
  163.    {
  164.    struct token *t;
  165.  
  166.    t = interp_dir();
  167.    while (t->tok_id == WhiteSpace) {
  168.       free_t(t);
  169.       t = interp_dir();
  170.       }
  171.    free_t(*tp);
  172.    *tp = t;
  173.    }
  174.  
  175. /*
  176.  * merge_whsp - merge a sequence of white space tokens into one token,
  177.  *  returning it along with the next token. Whether these are raw or
  178.  *  processed tokens depends on the token source function, t_src.
  179.  */
  180. void merge_whsp(whsp, next_t, t_src)
  181. struct token **whsp;
  182. struct token **next_t;
  183. struct token *(*t_src)(void);
  184.    {
  185.    struct token *t1;
  186.    struct str_buf *sbuf;
  187.    int line = -1;
  188.    char *fname = "";
  189.    char *s;
  190.  
  191.    free_t(*whsp);
  192.    t1 = (*t_src)();
  193.    if (t1 == NULL || t1->tok_id != WhiteSpace)
  194.       *whsp  = NULL;   /* no white space here */
  195.    else {
  196.       *whsp = t1;
  197.       t1 = (*t_src)();
  198.       if (t1 != NULL && t1->tok_id == WhiteSpace) {
  199.          if (whsp_image == NoSpelling) {
  200.             /*
  201.              * We don't care what the white space looks like, so
  202.              *  discard the rest of it.
  203.              */
  204.             while (t1 != NULL && t1->tok_id == WhiteSpace) {
  205.                free_t(t1);
  206.                t1 = (*t_src)();
  207.                }
  208.             }
  209.          else {
  210.             /*
  211.              * Must actually merge white space. Put it all white space
  212.              *  in a string buffer and use that as the image of the merged
  213.              *  token. The line number and file name of the new token
  214.              *  is that of the last token whose line number and file
  215.              *  name is important for generating #line directives in
  216.              *  the output.
  217.              */
  218.             sbuf = get_sbuf();
  219.             if ((*whsp)->flag & LineChk) {
  220.                line = (*whsp)->line;
  221.                fname = (*whsp)->fname;
  222.                }
  223.             for (s = (*whsp)->image; *s != '\0'; ++s) {
  224.                AppChar(*sbuf, *s);
  225.                if (*s == '\n' && line != -1)
  226.                   ++line;
  227.                }
  228.             while (t1 != NULL && t1->tok_id == WhiteSpace) {
  229.                if (t1->flag & LineChk) {
  230.                   line = t1->line;
  231.                   fname = t1->fname;
  232.                   }
  233.                for (s = t1->image; *s != '\0'; ++s) {
  234.                   AppChar(*sbuf, *s);
  235.                   if (*s == '\n' && line != -1)
  236.                      ++line;
  237.                   }
  238.                free_t(t1);
  239.                t1 = (*t_src)();
  240.                }
  241.             (*whsp)->image = str_install(sbuf);
  242.             rel_sbuf(sbuf);
  243.             if (t1 != NULL && !(t1->flag & LineChk) && line != -1) {
  244.                t1->flag |= LineChk;
  245.                t1->line = line;
  246.                t1->fname = fname;
  247.                }
  248.             }
  249.          }
  250.       }
  251.    *next_t = t1;
  252.    }
  253.