home *** CD-ROM | disk | FTP | other *** search
/ Dream 48 / Amiga_Dream_48.iso / Atari / c / cpp.zoo / src / process.c < prev    next >
C/C++ Source or Header  |  1993-06-03  |  5KB  |  199 lines

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