home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / cpp114.zoo / src / process.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-20  |  5.3 KB  |  218 lines

  1.  
  2. /*---------------------------------------------------------------------*\
  3. |                                    |
  4. | CPP -- a stand-alone C preprocessor                    |
  5. | Copyright (c) 1993-95 Hacker Ltd.        Author: Scott Bigham    |
  6. |                                    |
  7. | Permission is granted to anyone to use this software for any purpose    |
  8. | on any computer system, and to redistribute it freely, with the    |
  9. | following restrictions:                        |
  10. | - No charge may be made other than reasonable charges for repro-    |
  11. |     duction.                                |
  12. | - Modified versions must be clearly marked as such.            |
  13. | - The author is not responsible for any harmful consequences of    |
  14. |     using this software, even if they result from defects therein.    |
  15. |                                    |
  16. | process.c -- general input processing and output            |
  17. \*---------------------------------------------------------------------*/
  18.  
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include "global.h"
  23.  
  24. struct file_state {
  25.   char *old_curfile;
  26.   char *old_curdir;
  27.   FILE *old_inf;
  28.   unsigned long old_lastline, old_thisline, old_nextline;
  29. };
  30.  
  31. #define MAX_BLANK_LINES 5
  32.  
  33. /*
  34.    sync_line() -- generate a synchronization line of the form "# line-num
  35.    filename", where line-num is determined by |this_line|. Sets |last_line|
  36.    to |this_line|.  |n| is an additional parameter to print on the line, 1
  37.    when you enter a file and 2 when you leave it; normally it is 0 and not
  38.    printed
  39. */
  40. void sync_line(n)
  41.   int n;
  42. {
  43.   switch (sl_style) {
  44.   case SL_NONE:
  45.     break;
  46.   case SL_LINE:
  47.     fprintf(outf, "#line %lu \"%s\"\n", this_line, cur_file);
  48.     break;
  49.   case SL_NORMAL:
  50.     switch (n) {
  51.     case 0:
  52.       fprintf(outf, "# %lu \"%s\"\n", this_line, cur_file);
  53.       break;
  54.     case 1:
  55.     case 2:
  56.       fprintf(outf, "# %lu \"%s\" %d\n", this_line, cur_file, n);
  57.       break;
  58.     default:
  59.       bugchk("can't sync_line(%lu,%d)\n", this_line, n);
  60.       exit(1);
  61.     }
  62.     break;
  63.   }
  64.   last_line = this_line;
  65. }
  66.  
  67. /*
  68.    synchronize() -- synchronize the line number in the output file with the
  69.    input file, either by spitting line feeds or generating a synch line. This
  70.    should not be used if the filename has changed; use sync_line() for that.
  71. */
  72. void synchronize()
  73. {
  74.   if (last_line > this_line || this_line - last_line > MAX_BLANK_LINES)
  75.     sync_line(0);
  76.   else
  77.     for (; last_line < this_line; last_line++)
  78.       fputc('\n', outf);
  79. }
  80.  
  81. /*
  82.    process_line() -- read a line from the input file token by token, doing
  83.    the appropriate thing
  84. */
  85. static int process_line()
  86. {
  87.   register TokenP T;
  88.   register int start_of_line = 1;
  89.  
  90.   for (;;) {
  91.  
  92.     /*
  93.        We must be careful here -- the '#' for a directive cannot come from a
  94.        macro expansion.
  95.     */
  96.     T = (start_of_line ? token(): exp_token());
  97.     if (T->type == EOF_) {
  98.       free_token(T);
  99.       return 0;
  100.     }
  101.     if (T->type == EOL) {
  102.       if (keep_comments) {
  103.     print_token(T);
  104.     last_line++;
  105.       } else if (!start_of_line) {
  106.     fputc('\n', outf);
  107.     last_line++;
  108.       }
  109.       free_token(T);
  110.       if (start_of_line)
  111.     continue;
  112.       else
  113.     break;
  114.     }
  115.     if (start_of_line) {
  116.       /* check for preprocessor directive */
  117.       if (T->type == POUND) {
  118.     free_token(T);
  119.     directive();
  120.     continue;
  121.       }
  122.  
  123.       /*
  124.          If we're in the false branch of an #ifdef and we're not a
  125.          preprocessor directive, just pitch the line and get the next one.
  126.       */
  127.       if (!cond_true()) {
  128.     free_token(T);
  129.     flush_line();
  130.     continue;
  131.       }
  132.  
  133.       /*
  134.          If we get here, we're dealing with a normal line.  We push back
  135.          the token we just read, jump back to the top of the loop and
  136.          re-read it with exp_token() to make sure it gets expanded.
  137.       */
  138.       if (start_of_line && !in_config_file)
  139.     synchronize();
  140.       start_of_line = 0;
  141.       push_tlist(T);
  142.       continue;
  143.     }
  144.     print_token(T);
  145.     free_token(T);
  146.   }
  147.   return 1;
  148. }
  149.  
  150. /* path_of_file() -- extract the pathlist from filename |fnam| */
  151. static char *path_of_file(fnam)
  152.   char *fnam;
  153. {
  154.   char *s, *path;
  155.  
  156.   if (!(s = strrchr(fnam, PATH_SEP))) {
  157.     path = mallok(2);
  158.     path[0] = '.';
  159.     path[1] = '\0';
  160.   } else
  161.     path = copy_filename(fnam, (int)(s - fnam));
  162.   return path;
  163. }
  164.  
  165. /*
  166.    save_state() -- save various values particular to the current input file,
  167.    just before opening a new file to process
  168. */
  169. static void save_state(FS)
  170.   register struct file_state *FS;
  171. {
  172.   FS->old_curfile = cur_file;
  173.   FS->old_curdir = I_list[0];
  174.   FS->old_lastline = last_line;
  175.   FS->old_thisline = this_line;
  176.   FS->old_nextline = next_line;
  177.   FS->old_inf = inf;
  178. }
  179.  
  180. /* restore_state() -- restore values saved with save_state() */
  181. static void restore_state(FS)
  182.   register struct file_state *FS;
  183. {
  184.   cur_file = FS->old_curfile;
  185.   I_list[0] = FS->old_curdir;
  186.   last_line = FS->old_lastline;
  187.   this_line = FS->old_thisline;
  188.   next_line = FS->old_nextline;
  189.   inf = FS->old_inf;
  190. }
  191.  
  192. /* process_file() -- open and process file |fnam| */
  193. void process_file(fnam)
  194.   char *fnam;
  195. {
  196.   struct file_state FS;
  197.  
  198.   /* save state values from the previous file */
  199.   save_state(&FS);
  200.   if (streq(fnam, STDIN_NAME))
  201.     inf = stdin;
  202.   else if (!(inf = xfopen(fnam, "r")))
  203.     fatal("cannot open input file %s", fnam);
  204.   cur_file = strdup(fnam);
  205.   I_list[0] = path_of_file(fnam);
  206.   this_line = next_line = 1;
  207.   if (!in_config_file)
  208.     sync_line(1);
  209.   while (process_line()) ;
  210.   if (include_level == 0)
  211.     endif_check();
  212.   if (inf != stdin)
  213.     fclose(inf);
  214.   free(cur_file);
  215.   free(I_list[0]);
  216.   restore_state(&FS);
  217. }
  218.