home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / m / m4v05as.zip / OUTPUT.C < prev    next >
C/C++ Source or Header  |  1992-02-22  |  7KB  |  280 lines

  1. /*
  2.  * GNU m4 -- A simple macro processor
  3.  * Copyright (C) 1989, 1990 Free Software Foundation, Inc. 
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 1, or (at your option)
  8.  * any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. /*
  21.  * MS-DOS port (c) 1990 by Thorsten Ohl, ohl@gnu.ai.mit.edu
  22.  * This port is also distributed under the terms of the
  23.  * GNU General Public License as published by the
  24.  * Free Software Foundation.
  25.  *
  26.  * Please note that this file is not identical to the
  27.  * original GNU release, you should have received this
  28.  * code as patch to the official release.
  29.  *
  30.  * $Header: e:/gnu/m4/RCS/output.c 0.5.1.0 90/09/28 18:36:42 tho Exp $
  31.  */
  32.  
  33. #include "m4.h"
  34.  
  35. #ifdef MSDOS
  36. #include <io.h>
  37. #include <malloc.h>
  38. int mkstemp (char *tmpl);
  39. #endif /* MSDOS */
  40.  
  41. /* 
  42.  * Output functions.  Most of the complexity is for handling cpp like
  43.  * sync lines.
  44.  *
  45.  * This code is fairly entangled with the code in input.c, and maybe it
  46.  * belongs there?
  47.  */
  48.  
  49. /* number of output lines for current input line */
  50. int output_lines;
  51.  
  52. /* number of input line we are generating output for */
  53. int output_current_line;
  54.  
  55.  
  56. /* current output stream */
  57. static FILE *output;
  58.  
  59. /* table of diversion files */
  60. static FILE **divtab;
  61.  
  62. /* number of diversions allocated */
  63. static int ndivertion;
  64.  
  65.  
  66. /* 
  67.  * Output initialisation.  It handles allocation of memory for
  68.  * diversions.  This is done dynamically, in case we want to expand it
  69.  * later.
  70.  */
  71. void 
  72. output_init()
  73. {
  74.     int i;
  75.  
  76.     output = stdout;
  77.  
  78.     ndivertion = 10;
  79.     divtab = (FILE **)xmalloc(ndivertion * sizeof(FILE *));
  80.     for (i = 0; i < ndivertion; i++)
  81.     divtab[i] = nil;
  82.     divtab[0] = stdout;
  83. }
  84.  
  85.  
  86. /* 
  87.  * Output a sync line for line number LINE, with an optional file name
  88.  * FILE specified.
  89.  */
  90.  
  91. void 
  92. sync_line(line, file)
  93.     int line;
  94.     char *file;
  95. {
  96.     if (output == nil)
  97.     return;
  98.  
  99.     fprintf(output, "#line %d", line);
  100.     if (file != nil)
  101.     fprintf(output, " \"%s\"", file);
  102.     putc('\n', output);
  103. }
  104.  
  105. /* 
  106.  * Output TEXT to either an obstack or a file.  If OBS is nil, and there
  107.  * is no output file, the text is discarded.
  108.  *
  109.  * If we are generating sync lines, the output have to be examined,
  110.  * because we need to know how much output each input line generates.
  111.  * In general, sync lines are output whenever a single input lines
  112.  * generates several output lines, or when several input lines does not
  113.  * generate any output.
  114.  */
  115. void 
  116. shipout_text(obs, text)
  117.     struct obstack *obs;
  118.     char *text;
  119. {
  120.     static boolean start_of_output_line = true;
  121.  
  122.     if (obs != nil) {            /* output to obstack OBS */
  123.     obstack_grow(obs, text, strlen(text));
  124.     return;
  125.     }
  126.     if (output == nil)            /* discard TEXT */
  127.     return;
  128.  
  129.     if (!sync_output)
  130.     fputs(text, output);
  131.     else {
  132.     for (; *text != '\0'; text++) {
  133.         if (start_of_output_line) {
  134.         start_of_output_line = false;
  135.  
  136. #ifdef DEBUG_OUTPUT
  137.         printf("DEBUG: cur %d, cur out %d, out %d\n",
  138.                current_line, output_current_line, output_lines);
  139. #endif
  140.  
  141.         if (current_line - output_current_line > 1 || output_lines > 1)
  142.             sync_line(current_line, nil);
  143.         
  144.         output_current_line = current_line;
  145.         }
  146.         putc(*text, output);
  147.         if (*text == '\n') {
  148.         output_lines++;
  149.         start_of_output_line = true;
  150.         }
  151.     }
  152.     }
  153. }
  154.  
  155. /* 
  156.  * Functions for use by diversions.
  157.  */
  158.  
  159. #if defined(USG) || defined(ultrix)
  160. /* 
  161.  * This does not avoid any races, but its there.  Poor bastards.
  162.  */
  163. #include <fcntl.h>
  164.  
  165. int 
  166. mkstemp(tmpl)
  167.     char *tmpl;
  168. {
  169.     mktemp(tmpl);
  170.     return open(tmpl, O_RDWR|O_TRUNC|O_CREAT, 0600);
  171. }
  172. #endif /* USG */
  173.  
  174.  
  175. #ifdef MSDOS
  176. char template_base[] = "/m4%02dXXXXXX";
  177. char *template;
  178. #endif /* MSDOS */
  179.  
  180. /* 
  181.  * Make a file for diversion DIVNUM, and install it in the diversion
  182.  * table "divtab".  The file is opened read-write, so we can unlink it
  183.  * immediately.
  184.  */
  185. void 
  186. make_divertion(divnum)
  187.     int divnum;
  188. {
  189.     char buf[256];
  190.     int fd;
  191.  
  192.     if (output != nil)
  193.     fflush(output);
  194.  
  195.     if (divnum < 0 || divnum > ndivertion) {
  196.     output = nil;
  197.     return;
  198.     }
  199.  
  200.     if (divtab[divnum] == nil) {
  201. #ifdef MSDOS
  202.       {
  203.         char *p;
  204.  
  205.         if ((p = getenv ("TMP")) || (p = getenv ("TEMP")))
  206.           {
  207.         int len = strlen (p);
  208.         template = (char *) alloca (sizeof (template_base) + len + 1);
  209.         strcpy (template, p);
  210.         p = template + len - 1;
  211.         if (*p == '/' || *p == '\\')    /*  strip trailing slash */
  212.           *p = '\0';
  213.           }
  214.         else
  215.           {
  216.         template = (char *) alloca (sizeof (template_base) + 2);
  217.         strcpy (template, ".");
  218.           }
  219.         strcat (template, template_base);
  220.       }
  221.         sprintf(buf, template, divnum);
  222. #else /* not MSDOS */
  223.     sprintf(buf, "/tmp/m4.%02d.XXXXXX", divnum);
  224. #endif /* not MSDOS */
  225.     fd = mkstemp(buf);
  226.     if (fd < 0)
  227.         fatal("can't create file for diversion: %s", syserr());
  228.     divtab[divnum] = fdopen(fd, "w+");
  229.     unlink(buf);
  230.     }
  231.     output = divtab[divnum];
  232.  
  233.     if (sync_output)
  234.     sync_line(current_line, current_file);
  235. }
  236.  
  237. /* 
  238.  * Insert diversion number DIVNUM into the current output file.  The
  239.  * diversion is NOT placed on the expansion obstack, because it must not
  240.  * be rescanned.  When the file is closed, it is deleted by the system.
  241.  */
  242. void 
  243. insert_divertion(divnum)
  244.     int divnum;
  245. {
  246.     FILE *div;
  247.     int ch;
  248.  
  249.     if (divnum < 0 || divnum > ndivertion)
  250.     return;
  251.  
  252.     div  = divtab[divnum];
  253.     if (div == nil || div == output)
  254.     return;
  255.  
  256.     if (output != nil) {
  257.     rewind(div);
  258.     while ((ch = getc(div)) != EOF)
  259.         putc(ch, output);
  260.     
  261.     if (sync_output)
  262.         sync_line(current_line, current_file); /* BUG HERE -- undivert in the middle of line*/
  263.     }
  264.     fclose(div);
  265. }
  266.  
  267.  
  268. /* 
  269.  * Get back all diversions.  This is done just before exiting from
  270.  * main(), and from m4_undivert(), if called without arguments.
  271.  */
  272. void 
  273. undivert_all()
  274. {
  275.     int divnum;
  276.  
  277.     for (divnum = 1; divnum < ndivertion; divnum++)
  278.     insert_divertion(divnum);
  279. }
  280.