home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / m / m4v05as.zip / M4.C < prev    next >
C/C++ Source or Header  |  1992-02-22  |  9KB  |  456 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/m4.c 0.5.1.0 90/09/28 18:35:03 tho Exp $
  31.  */
  32.  
  33. #include "m4.h"
  34. #include "version.h"
  35.  
  36. #include <signal.h>
  37.  
  38. /* Operate interactively (-e) */
  39. int interactive = 0;
  40.  
  41. /* Enable sync output for /lib/cpp (-s) */
  42. int sync_output = 0;
  43.  
  44. /* Debug (-d[level]) */
  45. int debug_level = 0;
  46.  
  47. /* Hash table size (should be a prime) (-Hsize) */
  48. int hash_table_size = HASHMAX;
  49.  
  50. /* Disable GNU extensions (-G) */
  51. int no_gnu_extensions = 0;
  52.  
  53. #ifdef TRACE_MEMORY_USAGE
  54. /* Look where m4 eats up the memory (-t) */
  55. int trace_memory_usage = 0;
  56. #endif /* TRACE_MEMORY_USAGE */
  57.  
  58.  
  59. #ifdef MSDOS
  60. extern int main (int argc, char **argv);
  61. static void vmesg(char *level, char *fmt, va_list args);
  62. static void no_memory (void);
  63. static void usage (void);
  64. #endif /* MSDOS */
  65.  
  66.  
  67. /* 
  68.  * usage --- Print usage message on stderr.
  69.  */
  70. void 
  71. usage()
  72. {
  73.     fprintf(stderr, "Usage: m4 [options] file ....\n");
  74.     exit(1);
  75. }
  76.  
  77.  
  78. #define NEXTARG --argc, ++argv
  79.  
  80. int 
  81. main(argc, argv)
  82.     int argc;
  83.     char **argv;
  84. {
  85.     boolean no_more_options = false;
  86.     char *macro_value;
  87.     FILE *fp;
  88.  
  89.     /* 
  90.      * First, we decode the basic arguments, to size up tables and stuff.
  91.      */
  92.     for (NEXTARG; argc && argv[0][0] == '-'; NEXTARG) {
  93.     switch (argv[0][1]) {
  94.     case 'e':
  95.         interactive = 1;
  96.         break;
  97.  
  98.     case 'V':
  99.         fprintf(stderr,
  100. #ifdef MSDOS
  101.             "\
  102. GNU m4 %s, Copyright (C) 1989, 1990 Free Software Foundation, Inc.\n\
  103. There is ABSOLUTELY NO WARRANTY for GNU m4.  See the file\n\
  104. COPYING in the source distribution for more details.\n\
  105. $Header: e:/gnu/m4/RCS/m4.c 0.5.1.0 90/09/28 18:35:03 tho Exp $\n\
  106. (compiled " __DATE__ " " __TIME__ " MS-DOS)\n",
  107. #else /* not MSDOS */
  108.             "\
  109. GNU m4 %s, Copyright (C) 1989, 1990 Free Software Foundation, Inc.\n\
  110. There is ABSOLUTELY NO WARRANTY for GNU m4.  See the file\n\
  111. COPYING in the source distribution for more details.\n",
  112. #endif /* not MSDOS */
  113.             version);
  114.         break;
  115.  
  116.     case 's':
  117.         sync_output = 1;
  118.         break;
  119.  
  120.     case 'd':
  121.         debug_level = atoi(&argv[0][2]);
  122.         if (debug_level < 0)
  123.         debug_level = 0;
  124.         break;
  125.  
  126.     case 'H':
  127.         hash_table_size = atoi(&argv[0][2]);
  128.         if (hash_table_size <= 0)
  129.         hash_table_size = HASHMAX;
  130.         break;
  131.  
  132.     case 'G':
  133.         no_gnu_extensions = 1;
  134.         break;
  135.  
  136.     case 'B':            /* compatibility junk */
  137.     case 'S':
  138.     case 'T':
  139.         break;
  140.  
  141. #ifdef TRACE_MEMORY_USAGE
  142.     case 't':
  143.         trace_memory_usage++;
  144.         break;
  145. #endif /* TRACE_MEMORY_USAGE */
  146.  
  147.     default:
  148.         usage();
  149.  
  150.         /* These are handled later */
  151.     case '\0':            /* `-' meaning standard input */
  152.     case 'D':            /* define macro */
  153.     case 'U':            /* undefine macro */
  154.         no_more_options = true;
  155.         break;
  156.     }
  157.     if (no_more_options)
  158.         break;
  159.     }
  160.  
  161.     input_init();
  162.     output_init();
  163.     symtab_init();
  164.     builtin_init();
  165.     
  166.     /* 
  167.      * Define command line macro definitions.  Must come after
  168.      * initialisation of the symbol table.
  169.      */
  170.     no_more_options = false;
  171.     for (; argc && argv[0][0] == '-'; NEXTARG) {
  172.     switch (argv[0][1]) {
  173.     case '\0':
  174.         no_more_options = true;
  175.         break;
  176.  
  177.     case 'D':
  178.         macro_value = index(&argv[0][2], '=');
  179.         if (macro_value == nil)
  180.         macro_value = "";
  181.         else
  182.         *macro_value++ = '\0';
  183.         define_user_macro(&argv[0][2], macro_value, SYMBOL_INSERT);
  184.         break;
  185.  
  186.     case 'U':
  187.         lookup_symbol(&argv[0][2], SYMBOL_DELETE);
  188.         break;
  189.  
  190.     default:
  191.         usage();
  192.         break;
  193.     }
  194.     if (no_more_options)
  195.         break;
  196.     }
  197.  
  198.     /* 
  199.      * Interactive mode means unbuffered output, and interrupts ignored.
  200.      */
  201.     if (interactive) {
  202.     signal(SIGINT, SIG_IGN);
  203.     setbuf(stdout, (char *)NULL);
  204.     }
  205.  
  206.     /* 
  207.      * Handle the various input files.  Each file is pushed on the
  208.      * input, and the input read.  Wrapup text is handled separately
  209.      * later.
  210.      */
  211.     if (argc == 0) {
  212.     push_file(stdin, "Standard Input");
  213.     expand_input();    
  214.     } else {
  215.     for ( ; argc > 0; NEXTARG) {
  216.         if (strcmp(argv[0], "-") == 0) {
  217.         push_file(stdin, "Standard Input");
  218.         } else {
  219.         fp = fopen(argv[0], "r");
  220.         if (fp == nil) {
  221.             error("can't open %s: %s", argv[0], syserr());
  222.             continue;
  223.         } else
  224.             push_file(fp, argv[0]);
  225.         }
  226.         expand_input();
  227.     }
  228.     }
  229. #undef NEXTARG
  230.     
  231.     /* Now handle wrapup text. */
  232.     while (pop_wrapup())
  233.     expand_input();
  234.  
  235.     undivert_all();
  236.  
  237.     return 0;
  238. }
  239.  
  240.  
  241.  
  242. /* 
  243.  * The rest of this file contains error handling functions, and memory
  244.  * allocation.
  245.  */
  246.  
  247. #ifdef MSDOS            /* <stdarg.h> */
  248.  
  249. /* Basic varargs function for all error output */
  250.  
  251. void 
  252. vmesg(char *level, char *fmt, va_list args)
  253. {
  254.   fflush(stdout);
  255.   fprintf(stderr, "%s: %d: ", current_file, current_line);
  256.   if (level != nil)
  257.     fprintf(stderr, "%s: ", level);
  258.  
  259.   vfprintf(stderr, fmt, args);
  260.  
  261.   putc('\n', stderr);
  262. }
  263.  
  264. /* Internal errors -- print and dump core */
  265.  
  266. void 
  267. internal_error (char *fmt, ...)
  268. {
  269.   va_list args;
  270.  
  271.   va_start (args, fmt);
  272.   vmesg ("internal error", fmt, args);
  273.   va_end (args);
  274.  
  275.   abort();
  276. }
  277.  
  278. /* Fatal error -- print and exit */
  279.  
  280. void 
  281. fatal (char *fmt, ...)
  282. {
  283.   va_list args;
  284.  
  285.   va_start (args, fmt);
  286.   vmesg ("fatal error", fmt, args);
  287.   va_end (args);
  288.  
  289.   exit (1);
  290. }
  291.  
  292. /* "Normal" error -- just complain */
  293.  
  294. void 
  295. error (char *fmt, ...)
  296. {
  297.   va_list args;
  298.  
  299.   va_start (args, fmt);
  300.   vmesg ((char *)nil, fmt, args);
  301.   va_end (args);
  302. }
  303.  
  304. /* Warning --- for potential trouble */
  305.  
  306. void 
  307. warning (char *fmt, ...)
  308. {
  309.   va_list args;
  310.  
  311.   va_start (args, fmt);
  312.   vmesg ("warning", fmt, args);
  313.   va_end (args);
  314. }
  315.  
  316. #else /* not MSDOS */
  317.  
  318. /* Basic varargs function for all error output */
  319.  
  320. void 
  321. vmesg(level, args)
  322.     char *level;
  323.     va_list args;
  324. {
  325.     char *fmt;
  326.  
  327.     fflush(stdout);
  328.     fmt = va_arg(args, char*);
  329.     fprintf(stderr, "%s: %d: ", current_file, current_line);
  330.     if (level != nil)
  331.     fprintf(stderr, "%s: ", level);
  332.     vfprintf(stderr, fmt, args);
  333.     putc('\n', stderr);
  334. }
  335.  
  336. /* Internal errors -- print and dump core */
  337. /* VARARGS */
  338. void 
  339. internal_error(va_alist)
  340.     va_dcl
  341. {
  342.     va_list args;
  343.     va_start(args);
  344.     vmesg("internal error", args);
  345.     va_end(args);
  346.  
  347.     abort();
  348. }
  349.  
  350. /* Fatal error -- print and exit */
  351. /* VARARGS */
  352. void 
  353. fatal(va_alist)
  354.     va_dcl
  355. {
  356.     va_list args;
  357.     va_start(args);
  358.     vmesg("fatal error", args);
  359.     va_end(args);
  360.  
  361.     exit(1);
  362. }
  363.  
  364. /* "Normal" error -- just complain */
  365. /* VARARGS */
  366. void 
  367. error(va_alist)
  368.     va_dcl
  369. {
  370.     va_list args;
  371.     va_start(args);
  372.     vmesg((char *)nil, args);
  373.     va_end(args);
  374. }
  375.  
  376. /* Warning --- for potential trouble */
  377. /* VARARGS */
  378. void 
  379. warning(va_alist)
  380.     va_dcl
  381. {
  382.     va_list args;
  383.     va_start(args);
  384.     vmesg("warning", args);
  385.     va_end(args);
  386. }
  387.  
  388. #endif /* not MSDOS */
  389.  
  390.  
  391. /* 
  392.  * Memory allocation functions
  393.  */
  394.  
  395. /* Out ofmemory error -- die */
  396. void 
  397. no_memory()
  398. {
  399.     fatal("Out of memory");
  400. }
  401.  
  402. /* Free previously allocated memory */
  403. void 
  404. xfree(p)
  405.     char *p;
  406. {
  407. #ifdef TRACE_MEMORY_USAGE
  408.     if (trace_memory_usage)
  409.       fprintf (stderr, "freeing @%Fp.\n", (void _far *) p);
  410. #endif /* TRACE_MEMORY_USAGE */
  411.     free(p);
  412. }
  413.  
  414. /* Semi-safe malloc -- never returns nil */
  415. char *
  416. xmalloc(size)
  417.     unsigned int size;
  418. {
  419.     register char *cp = malloc(size);
  420. #ifdef TRACE_MEMORY_USAGE
  421.     if (trace_memory_usage)
  422.       {
  423.     fprintf (stderr, "allocating %5u (%04x) bytes ", size, size);
  424.     if (cp == nil)
  425.       fprintf (stderr, "failed.\n");
  426.     else
  427.       fprintf (stderr, "@%Fp.\n", (void _far *) cp);
  428.       }
  429. #endif /* TRACE_MEMORY_USAGE */
  430.     if (cp == nil)
  431.     no_memory();
  432.     return cp;
  433. }
  434.  
  435. #if 0
  436. /* Ditto realloc */
  437. char *
  438. xrealloc(p, size)
  439.     char *p;
  440.     unsigned int size;
  441. {
  442.     register char *cp = realloc(p, size);
  443.     if (cp == nil)
  444.     no_memory();
  445.     return cp;
  446. }
  447. #endif
  448.  
  449. /* and strdup */
  450. char *
  451. xstrdup(s)
  452.     char *s;
  453. {
  454.     return strcpy(xmalloc((unsigned int)strlen(s)+1), s);
  455. }
  456.