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 >
Wrap
C/C++ Source or Header
|
1992-02-22
|
9KB
|
456 lines
/*
* GNU m4 -- A simple macro processor
* Copyright (C) 1989, 1990 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 1, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* MS-DOS port (c) 1990 by Thorsten Ohl, ohl@gnu.ai.mit.edu
* This port is also distributed under the terms of the
* GNU General Public License as published by the
* Free Software Foundation.
*
* Please note that this file is not identical to the
* original GNU release, you should have received this
* code as patch to the official release.
*
* $Header: e:/gnu/m4/RCS/m4.c 0.5.1.0 90/09/28 18:35:03 tho Exp $
*/
#include "m4.h"
#include "version.h"
#include <signal.h>
/* Operate interactively (-e) */
int interactive = 0;
/* Enable sync output for /lib/cpp (-s) */
int sync_output = 0;
/* Debug (-d[level]) */
int debug_level = 0;
/* Hash table size (should be a prime) (-Hsize) */
int hash_table_size = HASHMAX;
/* Disable GNU extensions (-G) */
int no_gnu_extensions = 0;
#ifdef TRACE_MEMORY_USAGE
/* Look where m4 eats up the memory (-t) */
int trace_memory_usage = 0;
#endif /* TRACE_MEMORY_USAGE */
#ifdef MSDOS
extern int main (int argc, char **argv);
static void vmesg(char *level, char *fmt, va_list args);
static void no_memory (void);
static void usage (void);
#endif /* MSDOS */
/*
* usage --- Print usage message on stderr.
*/
void
usage()
{
fprintf(stderr, "Usage: m4 [options] file ....\n");
exit(1);
}
#define NEXTARG --argc, ++argv
int
main(argc, argv)
int argc;
char **argv;
{
boolean no_more_options = false;
char *macro_value;
FILE *fp;
/*
* First, we decode the basic arguments, to size up tables and stuff.
*/
for (NEXTARG; argc && argv[0][0] == '-'; NEXTARG) {
switch (argv[0][1]) {
case 'e':
interactive = 1;
break;
case 'V':
fprintf(stderr,
#ifdef MSDOS
"\
GNU m4 %s, Copyright (C) 1989, 1990 Free Software Foundation, Inc.\n\
There is ABSOLUTELY NO WARRANTY for GNU m4. See the file\n\
COPYING in the source distribution for more details.\n\
$Header: e:/gnu/m4/RCS/m4.c 0.5.1.0 90/09/28 18:35:03 tho Exp $\n\
(compiled " __DATE__ " " __TIME__ " MS-DOS)\n",
#else /* not MSDOS */
"\
GNU m4 %s, Copyright (C) 1989, 1990 Free Software Foundation, Inc.\n\
There is ABSOLUTELY NO WARRANTY for GNU m4. See the file\n\
COPYING in the source distribution for more details.\n",
#endif /* not MSDOS */
version);
break;
case 's':
sync_output = 1;
break;
case 'd':
debug_level = atoi(&argv[0][2]);
if (debug_level < 0)
debug_level = 0;
break;
case 'H':
hash_table_size = atoi(&argv[0][2]);
if (hash_table_size <= 0)
hash_table_size = HASHMAX;
break;
case 'G':
no_gnu_extensions = 1;
break;
case 'B': /* compatibility junk */
case 'S':
case 'T':
break;
#ifdef TRACE_MEMORY_USAGE
case 't':
trace_memory_usage++;
break;
#endif /* TRACE_MEMORY_USAGE */
default:
usage();
/* These are handled later */
case '\0': /* `-' meaning standard input */
case 'D': /* define macro */
case 'U': /* undefine macro */
no_more_options = true;
break;
}
if (no_more_options)
break;
}
input_init();
output_init();
symtab_init();
builtin_init();
/*
* Define command line macro definitions. Must come after
* initialisation of the symbol table.
*/
no_more_options = false;
for (; argc && argv[0][0] == '-'; NEXTARG) {
switch (argv[0][1]) {
case '\0':
no_more_options = true;
break;
case 'D':
macro_value = index(&argv[0][2], '=');
if (macro_value == nil)
macro_value = "";
else
*macro_value++ = '\0';
define_user_macro(&argv[0][2], macro_value, SYMBOL_INSERT);
break;
case 'U':
lookup_symbol(&argv[0][2], SYMBOL_DELETE);
break;
default:
usage();
break;
}
if (no_more_options)
break;
}
/*
* Interactive mode means unbuffered output, and interrupts ignored.
*/
if (interactive) {
signal(SIGINT, SIG_IGN);
setbuf(stdout, (char *)NULL);
}
/*
* Handle the various input files. Each file is pushed on the
* input, and the input read. Wrapup text is handled separately
* later.
*/
if (argc == 0) {
push_file(stdin, "Standard Input");
expand_input();
} else {
for ( ; argc > 0; NEXTARG) {
if (strcmp(argv[0], "-") == 0) {
push_file(stdin, "Standard Input");
} else {
fp = fopen(argv[0], "r");
if (fp == nil) {
error("can't open %s: %s", argv[0], syserr());
continue;
} else
push_file(fp, argv[0]);
}
expand_input();
}
}
#undef NEXTARG
/* Now handle wrapup text. */
while (pop_wrapup())
expand_input();
undivert_all();
return 0;
}
/*
* The rest of this file contains error handling functions, and memory
* allocation.
*/
#ifdef MSDOS /* <stdarg.h> */
/* Basic varargs function for all error output */
void
vmesg(char *level, char *fmt, va_list args)
{
fflush(stdout);
fprintf(stderr, "%s: %d: ", current_file, current_line);
if (level != nil)
fprintf(stderr, "%s: ", level);
vfprintf(stderr, fmt, args);
putc('\n', stderr);
}
/* Internal errors -- print and dump core */
void
internal_error (char *fmt, ...)
{
va_list args;
va_start (args, fmt);
vmesg ("internal error", fmt, args);
va_end (args);
abort();
}
/* Fatal error -- print and exit */
void
fatal (char *fmt, ...)
{
va_list args;
va_start (args, fmt);
vmesg ("fatal error", fmt, args);
va_end (args);
exit (1);
}
/* "Normal" error -- just complain */
void
error (char *fmt, ...)
{
va_list args;
va_start (args, fmt);
vmesg ((char *)nil, fmt, args);
va_end (args);
}
/* Warning --- for potential trouble */
void
warning (char *fmt, ...)
{
va_list args;
va_start (args, fmt);
vmesg ("warning", fmt, args);
va_end (args);
}
#else /* not MSDOS */
/* Basic varargs function for all error output */
void
vmesg(level, args)
char *level;
va_list args;
{
char *fmt;
fflush(stdout);
fmt = va_arg(args, char*);
fprintf(stderr, "%s: %d: ", current_file, current_line);
if (level != nil)
fprintf(stderr, "%s: ", level);
vfprintf(stderr, fmt, args);
putc('\n', stderr);
}
/* Internal errors -- print and dump core */
/* VARARGS */
void
internal_error(va_alist)
va_dcl
{
va_list args;
va_start(args);
vmesg("internal error", args);
va_end(args);
abort();
}
/* Fatal error -- print and exit */
/* VARARGS */
void
fatal(va_alist)
va_dcl
{
va_list args;
va_start(args);
vmesg("fatal error", args);
va_end(args);
exit(1);
}
/* "Normal" error -- just complain */
/* VARARGS */
void
error(va_alist)
va_dcl
{
va_list args;
va_start(args);
vmesg((char *)nil, args);
va_end(args);
}
/* Warning --- for potential trouble */
/* VARARGS */
void
warning(va_alist)
va_dcl
{
va_list args;
va_start(args);
vmesg("warning", args);
va_end(args);
}
#endif /* not MSDOS */
/*
* Memory allocation functions
*/
/* Out ofmemory error -- die */
void
no_memory()
{
fatal("Out of memory");
}
/* Free previously allocated memory */
void
xfree(p)
char *p;
{
#ifdef TRACE_MEMORY_USAGE
if (trace_memory_usage)
fprintf (stderr, "freeing @%Fp.\n", (void _far *) p);
#endif /* TRACE_MEMORY_USAGE */
free(p);
}
/* Semi-safe malloc -- never returns nil */
char *
xmalloc(size)
unsigned int size;
{
register char *cp = malloc(size);
#ifdef TRACE_MEMORY_USAGE
if (trace_memory_usage)
{
fprintf (stderr, "allocating %5u (%04x) bytes ", size, size);
if (cp == nil)
fprintf (stderr, "failed.\n");
else
fprintf (stderr, "@%Fp.\n", (void _far *) cp);
}
#endif /* TRACE_MEMORY_USAGE */
if (cp == nil)
no_memory();
return cp;
}
#if 0
/* Ditto realloc */
char *
xrealloc(p, size)
char *p;
unsigned int size;
{
register char *cp = realloc(p, size);
if (cp == nil)
no_memory();
return cp;
}
#endif
/* and strdup */
char *
xstrdup(s)
char *s;
{
return strcpy(xmalloc((unsigned int)strlen(s)+1), s);
}