home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 4 / FreshFish_May-June1994.bin / bbs / gnu / m4-1.1-src.lha / src / amiga / m4-1.1 / input.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-02  |  20.0 KB  |  737 lines

  1. /* GNU m4 -- A simple macro processor
  2.    Copyright (C) 1989, 90, 91, 92, 93 Free Software Foundation, Inc.
  3.   
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2, or (at your option)
  7.    any later version.
  8.   
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.   
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18.  
  19. /* Handling of different input sources, and lexical analysis.  */
  20.  
  21. #include "m4.h"
  22.  
  23. /* Unread input can be either files, that should be read (eg. included
  24.    files), strings, which should be rescanned (eg. macro expansion text),
  25.    or quoted macro definitions (as returned by the builtin "defn").
  26.    Unread input are organised in a stack, implemented with an obstack.
  27.    Each input source is described by a "struct input_block".  The obstack
  28.    is "input_stack".  The top of the input stack is "isp".
  29.    
  30.    The macro "m4wrap" places the text to be saved on another input stack,
  31.    on the obstack "wrapup_stack", whose top is "wsp".  When EOF is seen
  32.    on normal input (eg, when "input_stack" is empty), input is switched
  33.    over to "wrapup_stack".  To make this easier, all references to the
  34.    current input stack, whether it be "input_stack" or "wrapup_stack",
  35.    are done through a pointer "current_input", which points to either
  36.    "input_stack" or "wrapup_stack".
  37.    
  38.    Pushing new input on the input stack is done by push_file (),
  39.    push_string (), push_wrapup () (for wrapup text), and push_macro ()
  40.    (for macro definitions).  Because macro expansion needs direct access
  41.    to the current input obstack (for optimisation), push_string () are
  42.    split in two functions, push_string_init (), which returns a pointer
  43.    to the current input stack, and push_string_finish (), which return a
  44.    pointer to the final text.  The input_block *next is used to manage
  45.    the coordination between the different push routines.
  46.    
  47.    The current file and line number are stored in two global variables,
  48.    for use by the error handling functions in m4.c.  Whenever a file
  49.    input_block is pushed, the current file name and line number is saved
  50.    in the input_block, and the two variables are reset to match the new
  51.    input file.  */
  52.  
  53. enum input_type
  54. {
  55.   INPUT_FILE,
  56.   INPUT_STRING,
  57.   INPUT_MACRO
  58. };
  59.  
  60. typedef enum input_type input_type;
  61.  
  62. struct input_block
  63. {
  64.   struct input_block *prev;    /* previous input_block on the input stack */
  65.   input_type type;        /* INPUT_FILE, INPUT_STRING or INPUT_MACRO */
  66.   union
  67.     {
  68.       struct
  69.     {
  70.       char *string;        /* string value */
  71.     }
  72.       u_s;
  73.       struct
  74.     {
  75.       FILE *file;        /* input file handle */
  76.       char *name;        /* name of PREVIOUS input file */
  77.       int lineno;        /* current line number for do */
  78.       /* Yet another attack of "The curse of global variables" (sic) */
  79.       int out_lineno;    /* current output line number do */
  80.       boolean advance_line;    /* start_of_input_line from advance_input */
  81.     }
  82.       u_f;
  83.       struct
  84.     {
  85.       builtin_func *func;    /* pointer to macros function */
  86.       boolean traced;    /* TRUE iff builtin is traced */
  87.     }
  88.       u_m;
  89.     }
  90.   u;
  91. };
  92.  
  93. typedef struct input_block input_block;
  94.  
  95.  
  96. /* Current input file name.  */
  97. char *current_file;
  98.  
  99. /* Current input line number.  */
  100. int current_line;
  101.  
  102. /* Obstack for storing individual tokens.  */
  103. static struct obstack token_stack;
  104.  
  105. /* Normal input stack.  */
  106. static struct obstack input_stack;
  107.  
  108. /* Wrapup input stack.  */
  109. static struct obstack wrapup_stack;
  110.  
  111. /* Input or wrapup.  */
  112. static struct obstack *current_input;
  113.  
  114. /* Bottom of token_stack, for obstack_free.  */
  115. static char *token_bottom;
  116.  
  117. /* Pointer to top of current_input.  */
  118. static input_block *isp;
  119.  
  120. /* Pointer to top of wrapup_stack.  */
  121. static input_block *wsp;
  122.  
  123. /* Aux. for handling split push_string ().  */
  124. static input_block *next;
  125.  
  126. /* Flag for advance_input to increment current_line.  */
  127. static boolean start_of_input_line;
  128.  
  129. #define CHAR_EOF    256    /* character return on EOF */
  130. #define CHAR_MACRO    257    /* character return for MACRO token */
  131.  
  132. /* Quote chars.  */
  133. char *rquote;
  134. char *lquote;
  135.  
  136. /* And their length.  */
  137. int len_rquote;
  138. int len_lquote;
  139.  
  140. /* And default quote chars.  */
  141. static char *def_rquote = DEF_RQUOTE;
  142. static char *def_lquote = DEF_LQUOTE;
  143.  
  144. /* And comment chars.  */
  145. char *bcomm;
  146. char *ecomm;
  147.  
  148. /* And their length.  */
  149. static int len_bcomm;
  150. static int len_ecomm;
  151.  
  152. /* And default comment chars.  */
  153. static char *def_bcomm = DEF_BCOMM;
  154. static char *def_ecomm = DEF_ECOMM;
  155.  
  156.  
  157. /*-------------------------------------------------------------------------.
  158. | push_file () pushes an input file on the input stack, saving the current |
  159. | file name and line number.  If next is non-NULL, this push invalidates a |
  160. | call to push_string_init (), whose storage are consequentely released.   |
  161. `-------------------------------------------------------------------------*/
  162.  
  163. void
  164. push_file (FILE *fp, const char *title)
  165. {
  166.   input_block *i;
  167.  
  168.   if (next != NULL)
  169.     {
  170.       obstack_free (current_input, next);
  171.       next = NULL;
  172.     }
  173.  
  174.   if (debug_level & DEBUG_TRACE_INPUT)
  175.     debug_message ("input read from %s", title);
  176.  
  177.   i = (input_block *) obstack_alloc (current_input,
  178.                      sizeof (struct input_block));
  179.   i->type = INPUT_FILE;
  180.  
  181.   i->u.u_f.name = current_file;
  182.   i->u.u_f.lineno = current_line;
  183.   i->u.u_f.out_lineno = output_current_line;
  184.   i->u.u_f.advance_line = start_of_input_line;
  185.   current_file = obstack_copy0 (current_input, title, strlen (title));
  186.   current_line = 1;
  187.   output_current_line = -1;
  188.  
  189.   i->u.u_f.file = fp;
  190.   i->prev = isp;
  191.   isp = i;
  192. }
  193.  
  194. /*-------------------------------------------------------------------------.
  195. | push_macro () pushes a builtin macros definition on the input stack.  If |
  196. | next is non-NULL, this push invalidates a call to push_string_init (),   |
  197. | whose storage are consequentely released.                   |
  198. `-------------------------------------------------------------------------*/
  199.  
  200. void
  201. push_macro (builtin_func *func, boolean traced)
  202. {
  203.   input_block *i;
  204.  
  205.   if (next != NULL)
  206.     {
  207.       obstack_free (current_input, next);
  208.       next = NULL;
  209.     }
  210.  
  211.   i = (input_block *) obstack_alloc (current_input,
  212.                      sizeof (struct input_block));
  213.   i->type = INPUT_MACRO;
  214.  
  215.   i->u.u_m.func = func;
  216.   i->u.u_m.traced = traced;
  217.   i->prev = isp;
  218.   isp = i;
  219. }
  220.  
  221. /*------------------------------------------------------------------.
  222. | First half of push_string ().  The pointer next points to the new |
  223. | input_block.                                |
  224. `------------------------------------------------------------------*/
  225.  
  226. struct obstack *
  227. push_string_init (void)
  228. {
  229.   if (next != NULL)
  230.     internal_error ("recursive push_string!");
  231.  
  232.   next = (input_block *) obstack_alloc (current_input,
  233.                         sizeof (struct input_block));
  234.   next->type = INPUT_STRING;
  235.   return current_input;
  236. }
  237.  
  238. /*------------------------------------------------------------------------.
  239. | Last half of push_string ().  If next is now NULL, a call to push_file  |
  240. | () has invalidated the previous call to push_string_init (), so we just |
  241. | give up.  If the new object is void, we do not push it.  The function      |
  242. | push_string_finish () returns a pointer to the finished object.  This      |
  243. | pointer is only for temporary use, since reading the next token might      |
  244. | release the memory used for the object.                  |
  245. `------------------------------------------------------------------------*/
  246.  
  247. char *
  248. push_string_finish (void)
  249. {
  250.   char *ret = NULL;
  251.  
  252.   if (next == NULL)
  253.     return NULL;
  254.  
  255.   if (obstack_object_size (current_input) > 0)
  256.     {
  257.       obstack_1grow (current_input, '\0');
  258.       next->u.u_s.string = obstack_finish (current_input);
  259.       next->prev = isp;
  260.       isp = next;
  261.       ret = isp->u.u_s.string;    /* for immediate use only */
  262.     }
  263.   else
  264.     obstack_free (current_input, next); /* people might leave garbage on it. */
  265.   next = NULL;
  266.   return ret;
  267. }
  268.  
  269. /*--------------------------------------------------------------------------.
  270. | The function push_wrapup () pushes a string on the wrapup stack.  When    |
  271. | he normal input stack gets empty, the wrapup stack will become the input  |
  272. | stack, and push_string () and push_file () will operate on wrapup_stack.  |
  273. | Push_wrapup should be done as push_string (), but this will suffice, as   |
  274. | long as arguments to m4_m4wrap () are moderate in size.            |
  275. `--------------------------------------------------------------------------*/
  276.  
  277. void
  278. push_wrapup (char *s)
  279. {
  280.   input_block *i = (input_block *) obstack_alloc (&wrapup_stack,
  281.                           sizeof (struct input_block));
  282.   i->prev = wsp;
  283.   i->type = INPUT_STRING;
  284.   i->u.u_s.string = obstack_copy0 (&wrapup_stack, s, strlen (s));
  285.   wsp = i;
  286. }
  287.  
  288.  
  289. /*-------------------------------------------------------------------------.
  290. | The function pop_input () pops one level of input sources.  If the       |
  291. | popped input_block is a file, current_file and current_line are reset to |
  292. | the saved values before the memory for the input_block are released.       |
  293. `-------------------------------------------------------------------------*/
  294.  
  295. static void
  296. pop_input (void)
  297. {
  298.   input_block *tmp = isp->prev;
  299.  
  300.   switch (isp->type)
  301.     {
  302.     case INPUT_STRING:
  303.     case INPUT_MACRO:
  304.       break;
  305.     case INPUT_FILE:
  306.       if (debug_level & DEBUG_TRACE_INPUT)
  307.     debug_message ("input reverted to %s, line %d",
  308.                isp->u.u_f.name, isp->u.u_f.lineno);
  309.  
  310.       fclose (isp->u.u_f.file);
  311.       current_file = isp->u.u_f.name;
  312.       current_line = isp->u.u_f.lineno;
  313.       output_current_line = isp->u.u_f.out_lineno;
  314.       start_of_input_line = isp->u.u_f.advance_line;
  315.       if (tmp != NULL)
  316.     output_current_line = -1;
  317.       break;
  318.     default:
  319.       internal_error ("Input stack botch in pop_input ()");
  320.       break;
  321.     }
  322.   obstack_free (current_input, isp);
  323.   next = NULL;            /* might be set in push_string_init () */
  324.  
  325.   isp = tmp;
  326. }
  327.  
  328. /*------------------------------------------------------------------------.
  329. | To switch input over to the wrapup stack, main () calls pop_wrapup ().  |
  330. | Since wrapup text can install new wrapup text, pop_wrapup () returns      |
  331. | FALSE when there is no wrapup text on the stack, and TRUE otherwise.      |
  332. `------------------------------------------------------------------------*/
  333.  
  334. boolean
  335. pop_wrapup (void)
  336. {
  337.   if (wsp == NULL)
  338.     return FALSE;
  339.  
  340.   current_input = &wrapup_stack;
  341.   isp = wsp;
  342.   wsp = NULL;
  343.  
  344.   return TRUE;
  345. }
  346.  
  347. /*--------------------------------------------------------------------.
  348. | When a MACRO token is seen, next_token () uses get_macro_func () to |
  349. | retrieve the value of the function pointer.                  |
  350. `--------------------------------------------------------------------*/
  351.  
  352. static void
  353. init_macro_token (token_data *td)
  354. {
  355.   if (isp->type != INPUT_MACRO)
  356.     internal_error ("Bad call to get_macro_func ()");
  357.  
  358.   TOKEN_DATA_TYPE (td) = TOKEN_FUNC;
  359.   TOKEN_DATA_FUNC (td) = isp->u.u_m.func;
  360.   TOKEN_DATA_FUNC_TRACED (td) = isp->u.u_m.traced;
  361. }
  362.  
  363.  
  364. /*------------------------------------------------------------------------.
  365. | Low level input is done a character at a time.  The function peek_input |
  366. | () is used to look at the next character in the input stream.  At any      |
  367. | given time, it reads from the input_block on the top of the current      |
  368. | input stack.                                  |
  369. `------------------------------------------------------------------------*/
  370.  
  371. int
  372. peek_input (void)
  373. {
  374.   register int ch;
  375.  
  376.   while (1)
  377.     {
  378.       if (isp == NULL)
  379.     return CHAR_EOF;
  380.  
  381.       switch (isp->type)
  382.     {
  383.     case INPUT_STRING:
  384.       ch = isp->u.u_s.string[0];
  385.       if (ch != '\0')
  386.         return ch;
  387.       break;
  388.     case INPUT_FILE:
  389.       ch = getc (isp->u.u_f.file);
  390.       if (ch != EOF)
  391.         {
  392.           ungetc (ch, isp->u.u_f.file);
  393.           return ch;
  394.         }
  395.       break;
  396.     case INPUT_MACRO:
  397.       return CHAR_MACRO;
  398.     default:
  399.       internal_error ("Input stack botch in peek_input ()");
  400.       break;
  401.     }
  402.       /* End of input source --- pop one level.  */
  403.       pop_input ();
  404.     }
  405. }
  406.  
  407. /*-------------------------------------------------------------------------.
  408. | The function next_char () is used to read and advance the input to the   |
  409. | next character.  It also manages line numbers for error messages, so       |
  410. | they do not get wrong, due to lookahead.  The token consisting of a       |
  411. | newline alone is taken as belonging to the line it ends, and the current |
  412. | line number is not incremented until the next character is read.       |
  413. `-------------------------------------------------------------------------*/
  414.  
  415. static int
  416. next_char (void)
  417. {
  418.   register int ch;
  419.  
  420.   if (start_of_input_line)
  421.     {
  422.       start_of_input_line = FALSE;
  423.       current_line++;
  424.     }
  425.  
  426.   while (1)
  427.     {
  428.       if (isp == NULL)
  429.     return CHAR_EOF;
  430.  
  431.       switch (isp->type)
  432.     {
  433.     case INPUT_STRING:
  434.       ch = *isp->u.u_s.string++;
  435.       if (ch != '\0')
  436.         return ch;
  437.       break;
  438.     case INPUT_FILE:
  439.       ch = getc (isp->u.u_f.file);
  440.       if (ch != EOF)
  441.         {
  442.           if (ch == '\n')
  443.         start_of_input_line = TRUE;
  444.           return ch;
  445.         }
  446.       break;
  447.     case INPUT_MACRO:
  448.       pop_input ();        /* INPUT_MACRO input sources has only one
  449.                    token */
  450.       return CHAR_MACRO;
  451.       break;
  452.     default:
  453.       internal_error ("Input stack botch in advance_input ()");
  454.       break;
  455.     }
  456.       /* End of input source --- pop one level.  */
  457.       pop_input ();
  458.     }
  459. }
  460.  
  461. /*------------------------------------------------------------------------.
  462. | skip_line () simply discards all immediately following characters, upto |
  463. | the first newline.  It is only used from m4_dnl ().              |
  464. `------------------------------------------------------------------------*/
  465.  
  466. void
  467. skip_line (void)
  468. {
  469.   int ch;
  470.  
  471.   while ((ch = next_char ()) != CHAR_EOF && ch != '\n')
  472.     ;
  473. }
  474.  
  475.  
  476. /*----------------------------------------------------------------------.
  477. | This function is for matching a string against a prefix of the input  |
  478. | stream.  If the string matches the input, the input is discarded,     |
  479. | otherwise the characters read are pushed back again.  The function is |
  480. | used only when multicharacter quotes or comment delimiters are used.  |
  481. `----------------------------------------------------------------------*/
  482.  
  483. static int
  484. match_input (char *s)
  485. {
  486.   int n;            /* number of characters matched */
  487.   int ch;            /* input character */
  488.   char *t;
  489.  
  490.   ch = peek_input ();
  491.   if (ch != *s)
  492.     return 0;            /* fail */
  493.   (void) next_char ();
  494.  
  495.   if (s[1] == '\0')
  496.     return 1;            /* short match */
  497.  
  498.   for (n = 1, t = s++; (ch = peek_input ()) == *s++; n++)
  499.     {
  500.       (void) next_char ();
  501.       if (*s == '\0')        /* long match */
  502.     return 1;
  503.     }
  504.  
  505.   /* Failed, push back input.  */
  506.   obstack_grow (push_string_init (), t, n);
  507.   push_string_finish ();
  508.   return 0;
  509. }
  510.  
  511. /*------------------------------------------------------------------------.
  512. | The macro MATCH() is used to match a string against the input.  The      |
  513. | first character is handled inline, for speed.  Hopefully, this will not |
  514. | hurt efficiency too much when single character quotes and comment      |
  515. | delimiters are used.                              |
  516. `------------------------------------------------------------------------*/
  517.  
  518. #define MATCH(ch, s) \
  519.   ((s)[0] == (ch) \
  520.    && (ch) != '\0' \
  521.    && ((s)[1] == '\0' \
  522.        || (match_input ((s) + 1) ? (ch) = peek_input (), 1 : 0)))
  523.  
  524.  
  525. /*----------------------------------------------------------.
  526. | Inititialise input stacks, and quote/comment characters.  |
  527. `----------------------------------------------------------*/
  528.  
  529. void
  530. input_init (void)
  531. {
  532.   current_file = "NONE";
  533.   current_line = 0;
  534.  
  535.   obstack_init (&token_stack);
  536.   obstack_init (&input_stack);
  537.   obstack_init (&wrapup_stack);
  538.  
  539.   current_input = &input_stack;
  540.  
  541.   obstack_1grow (&token_stack, '\0');
  542.   token_bottom = obstack_finish (&token_stack);
  543.  
  544.   isp = NULL;
  545.   wsp = NULL;
  546.   next = NULL;
  547.  
  548.   start_of_input_line = FALSE;
  549.  
  550.   set_quotes (NULL, NULL);
  551.   set_comment (NULL, NULL);
  552. }
  553.  
  554.  
  555. /*--------------------------------------------------------------.
  556. | Functions for setting quotes and comment delimiters.  Used by |
  557. | m4_changecom () and m4_changequote ().                |
  558. `--------------------------------------------------------------*/
  559.  
  560. void
  561. set_quotes (char *lq, char *rq)
  562. {
  563.   if (lquote != def_lquote)
  564.     xfree (lquote);
  565.   if (rquote != def_rquote)
  566.     xfree (rquote);
  567.  
  568.   lquote = (lq == NULL) ? def_lquote : xstrdup (lq);
  569.   rquote = (rq == NULL) ? def_rquote : xstrdup (rq);
  570.  
  571.   len_lquote = strlen (lquote);
  572.   len_rquote = strlen (rquote);
  573. }
  574.  
  575. void
  576. set_comment (char *bc, char *ec)
  577. {
  578.   if (bcomm != def_bcomm)
  579.     xfree (bcomm);
  580.   if (ecomm != def_ecomm)
  581.     xfree (ecomm);
  582.  
  583.   bcomm = (bc == NULL) ? def_bcomm : xstrdup (bc);
  584.   ecomm = (ec == NULL) ? def_ecomm : xstrdup (ec);
  585.  
  586.   len_bcomm = strlen (bcomm);
  587.   len_ecomm = strlen (ecomm);
  588. }
  589.  
  590.  
  591. /*-------------------------------------------------------------------------.
  592. | Parse and return a single token from the input stream.  A token can       |
  593. | either be TOKEN_EOF, if the input_stack is empty; it can be TOKEN_STRING |
  594. | for a quoted string; TOKEN_WORD for something that is a potential macro  |
  595. | name; and TOKEN_SIMPLE for any single character that is not a part of       |
  596. | any of the previous types.                           |
  597. |                                        |
  598. | Next_token () return the token type, and passes back a pointer to the       |
  599. | token data through TD.  The token text is collected on the obstack       |
  600. | token_stack, which never contains more than one token text at a time.       |
  601. | The storage pointed to by the fields in TD is therefore subject to       |
  602. | change the next time next_token () is called.                   |
  603. `-------------------------------------------------------------------------*/
  604.  
  605. token_type
  606. next_token (token_data *td)
  607. {
  608.   int ch;
  609.   int quote_level;
  610.   token_type type;
  611.  
  612.   obstack_free (&token_stack, token_bottom);
  613.   obstack_1grow (&token_stack, '\0');
  614.   token_bottom = obstack_finish (&token_stack);
  615.  
  616.   ch = peek_input ();
  617.   if (ch == CHAR_EOF)
  618.     {
  619.       return TOKEN_EOF;
  620. #ifdef DEBUG_INPUT
  621.       fprintf (stderr, "next_token -> EOF\n");
  622. #endif
  623.     }
  624.   if (ch == CHAR_MACRO)
  625.     {
  626.       init_macro_token (td);
  627.       (void) next_char ();
  628.       return TOKEN_MACDEF;
  629.     }
  630.  
  631.   (void) next_char ();
  632.   if (MATCH (ch, bcomm))
  633.     {
  634.  
  635.       obstack_grow (&token_stack, bcomm, len_bcomm);
  636.       while ((ch = next_char ()) != CHAR_EOF && !MATCH (ch, ecomm))
  637.     obstack_1grow (&token_stack, ch);
  638.       if (ch != CHAR_EOF)
  639.     obstack_grow (&token_stack, ecomm, len_ecomm);
  640.       type = TOKEN_STRING;
  641.  
  642.     }
  643.   else if (isalpha (ch) || ch == '_')
  644.     {
  645.  
  646.       obstack_1grow (&token_stack, ch);
  647.       while ((ch = peek_input ()) != CHAR_EOF && (isalnum (ch) || ch == '_'))
  648.     {
  649.       obstack_1grow (&token_stack, ch);
  650.       (void) next_char ();
  651.     }
  652.       type = TOKEN_WORD;
  653.  
  654.     }
  655.   else if (!MATCH (ch, lquote))
  656.     {
  657.  
  658.       type = TOKEN_SIMPLE;
  659.       obstack_1grow (&token_stack, ch);
  660.  
  661.     }
  662.   else
  663.     {
  664.  
  665.       quote_level = 1;
  666.       while (1)
  667.     {
  668.       ch = next_char ();
  669.       if (ch == CHAR_EOF)
  670.         fatal ("EOF in string");
  671.  
  672.       if (MATCH (ch, rquote))
  673.         {
  674.           if (--quote_level == 0)
  675.         break;
  676.           obstack_grow (&token_stack, rquote, len_rquote);
  677.         }
  678.       else if (MATCH (ch, lquote))
  679.         {
  680.           quote_level++;
  681.           obstack_grow (&token_stack, lquote, len_lquote);
  682.         }
  683.       else
  684.         obstack_1grow (&token_stack, ch);
  685.     }
  686.       type = TOKEN_STRING;
  687.     }
  688.  
  689.   obstack_1grow (&token_stack, '\0');
  690.  
  691.   TOKEN_DATA_TYPE (td) = TOKEN_TEXT;
  692.   TOKEN_DATA_TEXT (td) = obstack_finish (&token_stack);
  693. #ifdef DEBUG_INPUT
  694.   fprintf (stderr, "next_token -> %d (%s)\n", type, TOKEN_DATA_TEXT (td));
  695. #endif
  696.   return type;
  697. }
  698.  
  699.  
  700. #ifdef DEBUG_INPUT
  701.  
  702. static void
  703. print_token (char *s, token_type t, token_data *td)
  704. {
  705.   fprintf (stderr, "%s: ", s);
  706.   switch (t)
  707.     {                /* TOKSW */
  708.     case TOKEN_SIMPLE:
  709.       fprintf (stderr, "char:");
  710.       break;
  711.     case TOKEN_WORD:
  712.       fprintf (stderr, "word:");
  713.       break;
  714.     case TOKEN_STRING:
  715.       fprintf (stderr, "string:");
  716.       break;
  717.     case TOKEN_MACDEF:
  718.       fprintf (stderr, "macro: 0x%x\n", TOKEN_DATA_FUNC (td));
  719.       break;
  720.     case TOKEN_EOF:
  721.       fprintf (stderr, "eof\n");
  722.       break;
  723.     }
  724.   fprintf (stderr, "\t\"%s\"\n", TOKEN_DATA_TEXT (td));
  725. }
  726.  
  727. static void
  728. lex_debug (void)
  729. {
  730.   token_type t;
  731.   token_data td;
  732.  
  733.   while ((t = next_token (&td)) != NULL)
  734.     print_token ("lex", t, &td);
  735. }
  736. #endif
  737.