1# This is a shell archive.  Save it in a file, remove anything before
2# this line, and then unpack it by entering "sh file".  Note, it may
3# create directories; files and directories will be owned by you and
4# have default permissions.
5#
6# This archive contains:
7#
8#	cpp1.c
9#	cpp3.c
10#	cpp4.c
11#
12echo x - cpp1.c
13sed 's/^X//' >cpp1.c << 'END-of-cpp1.c'
14X/*
15X * CPP main program.
16X *
17X * Edit history
18X * 21-May-84	MM	"Field test" release
19X * 23-May-84	MM	Some minor hacks.
20X * 30-May-84	ARF	Didn't get enough memory for __DATE__
21X *			Added code to read stdin if no input
22X *			files are provided.
23X * 29-Jun-84	MM	Added ARF's suggestions, Unixifying cpp.
24X * 11-Jul-84	MM	"Official" first release (that's what I thought!)
25X * 22-Jul-84	MM/ARF/SCK Fixed line number bugs, added cpp recognition
26X *			of #line, fixed problems with #include.
27X * 23-Jul-84	MM	More (minor) include hacking, some documentation.
28X *			Also, redid cpp's #include files
29X * 25-Jul-84	MM	#line filename isn't used for #include searchlist
30X *			#line format is <number> <optional name>
31X * 25-Jul-84	ARF/MM	Various bugs, mostly serious.  Removed homemade doprint
32X * 01-Aug-84	MM	Fixed recursion bug, remove extra newlines and
33X *			leading whitespace from cpp output.
34X * 02-Aug-84	MM	Hacked (i.e. optimized) out blank lines and unneeded
35X *			whitespace in general.  Cleaned up unget()'s.
36X * 03-Aug-84	Keie	Several bug fixes from Ed Keizer, Vrije Universitet.
37X *			-- corrected arg. count in -D and pre-defined
38X *			macros.  Also, allow \n inside macro actual parameter
39X *			lists.
40X * 06-Aug-84	MM	If debugging, dump the preset vector at startup.
41X * 12-Aug-84	MM/SCK	Some small changes from Sam Kendall
42X * 15-Aug-84	Keie/MM	cerror, cwarn, etc. take a single string arg.
43X *			cierror, etc. take a single int. arg.
44X *			changed LINE_PREFIX slightly so it can be
45X *			changed in the makefile.
46X * 31-Aug-84	MM	USENET net.sources release.
47X *  7-Sep-84	SCH/ado Lint complaints
48X * 10-Sep-84	Keie	Char's can't be signed in some implementations
49X * 11-Sep-84	ado	Added -C flag, pathological line number fix
50X * 13-Sep-84	ado	Added -E flag (does nothing) and "-" file for stdin.
51X * 14-Sep-84	MM	Allow # 123 as a synonym for #line 123
52X * 19-Sep-84	MM	scanid always reads to token, make sure #line is
53X *			written to a new line, even if -C switch given.
54X *			Also, cpp - - reads stdin, writes stdout.
55X * 03-Oct-84	ado/MM	Several changes to line counting and keepcomments
56X *			stuff.  Also a rewritten control() hasher -- much
57X *			simpler and no less "perfect". Note also changes
58X *			in cpp3.c to fix numeric scanning.
59X * 04-Oct-84	MM	Added recognition of macro formal parameters if
60X *			they are the only thing in a string, per the
61X *			draft standard.
62X * 08-Oct-84	MM	One more attack on scannumber
63X * 15-Oct-84	MM/ado	Added -N to disable predefined symbols.  Fixed
64X *			linecount if COMMENT_INVISIBLE enabled.
65X * 22-Oct-84	MM	Don't evaluate the #if/#ifdef argument if
66X *			compilation is supressed.  This prevents
67X *			unnecessary error messages in sequences such as
68X *			    #ifdef FOO		-- undefined
69X *			    #if FOO == 10	-- shouldn't print warning
70X * 25-Oct-84	MM	Fixed bug in false ifdef supression.  On vms,
71X *			#include <foo> should open foo.h -- this duplicates
72X *			the behavior of Vax-C
73X * 31-Oct-84	ado/MM	Parametized $ in indentifiers.  Added a better
74X *			token concatenator and took out the trial
75X *			concatenation code.  Also improved #ifdef code
76X *			and cleaned up the macro recursion tester.
77X *  2-Nov-84	MM/ado	Some bug fixes in token concatenation, also
78X *			a variety of minor (uninteresting) hacks.
79X *  6-Nov-84	MM	Happy Birthday.  Broke into 4 files and added
80X *			#if sizeof (basic_types)
81X *  9-Nov-84	MM	Added -S* for pointer type sizes
82X * 13-Nov-84	MM	Split cpp1.c, added vms defaulting
83X * 23-Nov-84	MM/ado	-E supresses error exit, added CPP_INCLUDE,
84X *			fixed strncpy bug.
85X *  3-Dec-84	ado/MM	Added OLD_PREPROCESSOR
86X *  7-Dec-84	MM	Stuff in Nov 12 Draft Standard
87X * 17-Dec-84	george	Fixed problems with recursive macros
88X * 17-Dec-84	MM	Yet another attack on #if's (f/t)level removed.
89X * 07-Jan-85	ado	Init defines before doing command line options
90X *			so -Uunix works.
91X */
92X
93X/*)BUILD
94X	$(PROGRAM)	= cpp
95X	$(FILES)	= { cpp1 cpp2 cpp3 cpp4 cpp5 cpp6 }
96X	$(INCLUDE)	= { cppdef.h cpp.h }
97X	$(STACK)	= 2000
98X	$(TKBOPTIONS)	= {
99X		STACK	= 2000
100X	}
101X*/
102X
103X#ifdef	DOCUMENTATION
104X
105Xtitle	cpp		C Pre-Processor
106Xindex			C pre-processor
107X
108Xsynopsis
109X	.s.nf
110X	cpp [-options] [infile [outfile]]
111X	.s.f
112Xdescription
113X
114X	CPP reads a C source file, expands macros and include
115X	files, and writes an input file for the C compiler.
116X	If no file arguments are given, CPP reads from stdin
117X	and writes to stdout.  If one file argument is given,
118X	it will define the input file, while two file arguments
119X	define both input and output files.  The file name "-"
120X	is a synonym for stdin or stdout as appropriate.
121X
122X	The following options are supported.  Options may
123X	be given in either case.
124X	.lm +16
125X	.p -16
126X	-C		If set, source-file comments are written
127X	to the output file.  This allows the output of CPP to be
128X	used as the input to a program, such as lint, that expects
129X	commands embedded in specially-formatted comments.
130X	.p -16
131X	-Dname=value	Define the name as if the programmer wrote
132X
133X	    #define name value
134X
135X	at the start of the first file.  If "=value" is not
136X	given, a value of "1" will be used.
137X
138X	On non-unix systems, all alphabetic text will be forced
139X	to upper-case.
140X	.p -16
141X	-E		Always return "success" to the operating
142X	system, even if errors were detected.  Note that some fatal
143X	errors, such as a missing #include file, will terminate
144X	CPP, returning "failure" even if the -E option is given.
145X	.p -16
146X	-Idirectory	Add this directory to the list of
147X	directories searched for #include "..." and #include <...>
148X	commands.  Note that there is no space between the
149X	"-I" and the directory string.  More than one -I command
150X	is permitted.  On non-Unix systems "directory" is forced
151X	to upper-case.
152X	.p -16
153X	-N		CPP normally predefines some symbols defining
154X	the target computer and operating system.  If -N is specified,
155X	no symbols will be predefined.  If -N -N is specified, the
156X	"always present" symbols, __LINE__, __FILE__, and __DATE__
157X	are not defined.
158X	.p -16
159X	-Stext		CPP normally assumes that the size of
160X	the target computer's basic variable types is the same as the size
161X	of these types of the host computer.  (This can be overridden
162X	when CPP is compiled, however.)  The -S option allows dynamic
163X	respecification of these values.  "text" is a string of
164X	numbers, separated by commas, that specifies correct sizes.
165X	The sizes must be specified in the exact order:
166X
167X	    char short int long float double
168X
169X	If you specify the option as "-S*text", pointers to these
170X	types will be specified.  -S* takes one additional argument
171X	for pointer to function (e.g. int (*)())
172X
173X	For example, to specify sizes appropriate for a PDP-11,
174X	you would write:
175X
176X	       c s i l f d func
177X	     -S1,2,2,2,4,8,
178X	    -S*2,2,2,2,2,2,2
179X
180X	Note that all values must be specified.
181X	.p -16
182X	-Uname		Undefine the name as if
183X
184X	    #undef name
185X
186X	were given.  On non-Unix systems, "name" will be forced to
187X	upper-case.
188X	.p -16
189X	-Xnumber	Enable debugging code.  If no value is
190X	given, a value of 1 will be used.  (For maintenence of
191X	CPP only.)
192X	.s.lm -16
193X
194XPre-Defined Variables
195X
196X	When CPP begins processing, the following variables will
197X	have been defined (unless the -N option is specified):
198X	.s
199X	Target computer (as appropriate):
200X	.s
201X	    pdp11, vax, M68000 m68000 m68k
202X	.s
203X	Target operating system (as appropriate):
204X	.s
205X	    rsx, rt11, vms, unix
206X	.s
207X	Target compiler (as appropriate):
208X	.s
209X	    decus, vax11c
210X	.s
211X	The implementor may add definitions to this list.
212X	The default definitions match the definition of the
213X	host computer, operating system, and C compiler.
214X	.s
215X	The following are always available unless undefined (or
216X	-N was specified twice):
217X	.lm +16
218X	.p -12
219X	__FILE__	The input (or #include) file being compiled
220X	(as a quoted string).
221X	.p -12
222X	__LINE__	The line number being compiled.
223X	.p -12
224X	__DATE__	The date and time of compilation as
225X	a Unix ctime quoted string (the trailing newline is removed).
226X	Thus,
227X	.s
228X	    printf("Bug at line %s,", __LINE__);
229X	    printf(" source file %s", __FILE__);
230X	    printf(" compiled on %s", __DATE__);
231X	.s.lm -16
232X
233XDraft Proposed Ansi Standard Considerations
234X
235X	The current version of the Draft Proposed Standard
236X	explicitly states that "readers are requested not to specify
237X	or claim conformance to this draft."  Readers and users
238X	of Decus CPP should not assume that Decus CPP conforms
239X	to the standard, or that it will conform to the actual
240X	C Language Standard.
241X
242X	When CPP is itself compiled, many features of the Draft
243X	Proposed Standard that are incompatible with existing
244X	preprocessors may be disabled.  See the comments in CPP's
245X	source for details.
246X
247X	The latest version of the Draft Proposed Standard (as reflected
248X	in Decus CPP) is dated November 12, 1984.
249X
250X	Comments are removed from the input text.  The comment
251X	is replaced by a single space character.  The -C option
252X	preserves comments, writing them to the output file.
253X
254X	The '$' character is considered to be a letter.  This is
255X	a permitted extension.
256X
257X	The following new features of C are processed by CPP:
258X	.s.comment Note: significant spaces, not tabs, .br quotes #if, #elif
259X	.br;####_#elif expression    (_#else _#if)
260X	.br;####'_\xNNN'             (Hexadecimal constant)
261X	.br;####'_\a'                (Ascii BELL)
262X	.br;####'_\v'                (Ascii Vertical Tab)
263X	.br;####_#if defined NAME    1 if defined, 0 if not
264X	.br;####_#if defined (NAME)  1 if defined, 0 if not
265X	.br;####_#if sizeof (basic type)
266X	.br;####unary +
267X	.br;####123U, 123LU          Unsigned ints and longs.
268X	.br;####12.3L                Long double numbers
269X	.br;####token_#token         Token concatenation
270X	.br;####_#include token      Expands to filename
271X
272X	The Draft Proposed Standard has extended C, adding a constant
273X	string concatenation operator, where
274X
275X	    "foo" "bar"
276X
277X	is regarded as the single string "foobar".  (This does not
278X	affect CPP's processing but does permit a limited form of
279X	macro argument substitution into strings as will be discussed.)
280X
281X	The Standard Committee plans to add token concatenation
282X	to #define command lines.  One suggested implementation
283X	is as follows:  the sequence "Token1#Token2" is treated
284X	as if the programmer wrote "Token1Token2".  This could
285X	be used as follows:
286X
287X	    #line 123
288X	    #define ATLINE foo#__LINE__
289X
290X	ATLINE would be defined as foo123.
291X
292X	Note that "Token2" must either have the format of an
293X	identifier or be a string of digits.  Thus, the string
294X
295X	    #define ATLINE foo#1x3
296X
297X	generates two tokens: "foo1" and "x3".
298X
299X	If the tokens T1 and T2 are concatenated into T3,
300X	this implementation operates as follows:
301X
302X	  1. Expand T1 if it is a macro.
303X	  2. Expand T2 if it is a macro.
304X	  3. Join the tokens, forming T3.
305X	  4. Expand T3 if it is a macro.
306X
307X	A macro formal parameter will be substituted into a string
308X	or character constant if it is the only component of that
309X	constant:
310X
311X	    #define VECSIZE 123
312X	    #define vprint(name, size) \
313X	      printf("name" "[" "size" "] = {\n")
314X	      ... vprint(vector, VECSIZE);
315X
316X	expands (effectively) to
317X
318X	      vprint("vector[123] = {\n");
319X
320X	Note that this will be useful if your C compiler supports
321X	the new string concatenation operation noted above.
322X	As implemented here, if you write
323X
324X	    #define string(arg) "arg"
325X	      ... string("foo") ...
326X
327X	This implementation generates "foo", rather than the strictly
328X	correct ""foo"" (which will probably generate an error message).
329X	This is, strictly speaking, an error in CPP and may be removed
330X	from future releases.
331X
332Xerror messages
333X
334X	Many.  CPP prints warning or error messages if you try to
335X	use multiple-byte character constants (non-transportable)
336X	if you #undef a symbol that was not defined, or if your
337X	program has potentially nested comments.
338X
339Xauthor
340X
341X	Martin Minow
342X
343Xbugs
344X
345X	The #if expression processor uses signed integers only.
346X	I.e, #if 0xFFFFu < 0 may be TRUE.
347X
348X#endif
349X
350X#include	<stdio.h>
351X#include	<ctype.h>
352X#include	"cppdef.h"
353X#include	"cpp.h"
354X
355X/*
356X * Commonly used global variables:
357X * line		is the current input line number.
358X * wrongline	is set in many places when the actual output
359X *		line is out of sync with the numbering, e.g,
360X *		when expanding a macro with an embedded newline.
361X *
362X * token	holds the last identifier scanned (which might
363X *		be a candidate for macro expansion).
364X * errors	is the running cpp error counter.
365X * infile	is the head of a linked list of input files (extended by
366X *		#include and macros being expanded).  infile always points
367X *		to the current file/macro.  infile->parent to the includer,
368X *		etc.  infile->fd is NULL if this input stream is a macro.
369X */
370Xint		line;			/* Current line number		*/
371Xint		wrongline;		/* Force #line to compiler	*/
372Xchar		token[IDMAX + 1];	/* Current input token		*/
373Xint		errors;			/* cpp error counter		*/
374XFILEINFO	*infile = NULL;		/* Current input file		*/
375X#if DEBUG
376Xint		debug;			/* TRUE if debugging now	*/
377X#endif
378X/*
379X * This counter is incremented when a macro expansion is initiated.
380X * If it exceeds a built-in value, the expansion stops -- this tests
381X * for a runaway condition:
382X *	#define X Y
383X *	#define Y X
384X *	X
385X * This can be disabled by falsifying rec_recover.  (Nothing does this
386X * currently: it is a hook for an eventual invocation flag.)
387X */
388Xint		recursion;		/* Infinite recursion counter	*/
389Xint		rec_recover = TRUE;	/* Unwind recursive macros	*/
390X
391X/*
392X * instring is set TRUE when a string is scanned.  It modifies the
393X * behavior of the "get next character" routine, causing all characters
394X * to be passed to the caller (except <DEF_MAGIC>).  Note especially that
395X * comments and \<newline> are not removed from the source.  (This
396X * prevents cpp output lines from being arbitrarily long).
397X *
398X * inmacro is set by #define -- it absorbs comments and converts
399X * form-feed and vertical-tab to space, but returns \<newline>
400X * to the caller.  Strictly speaking, this is a bug as \<newline>
401X * shouldn't delimit tokens, but we'll worry about that some other
402X * time -- it is more important to prevent infinitly long output lines.
403X *
404X * instring and inmarcor are parameters to the get() routine which
405X * were made global for speed.
406X */
407Xint		instring = FALSE;	/* TRUE if scanning string	*/
408Xint		inmacro = FALSE;	/* TRUE if #defining a macro	*/
409X
410X/*
411X * work[] and workp are used to store one piece of text in a temporay
412X * buffer.  To initialize storage, set workp = work.  To store one
413X * character, call save(c);  (This will fatally exit if there isn't
414X * room.)  To terminate the string, call save(EOS).  Note that
415X * the work buffer is used by several subroutines -- be sure your
416X * data won't be overwritten.  The extra byte in the allocation is
417X * needed for string formal replacement.
418X */
419Xchar		work[NWORK + 1];	/* Work buffer			*/
420Xchar		*workp;			/* Work buffer pointer		*/
421X
422X/*
423X * keepcomments is set TRUE by the -C option.  If TRUE, comments
424X * are written directly to the output stream.  This is needed if
425X * the output from cpp is to be passed to lint (which uses commands
426X * embedded in comments).  cflag contains the permanent state of the
427X * -C flag.  keepcomments is always falsified when processing #control
428X * commands and when compilation is supressed by a false #if
429X *
430X * If eflag is set, CPP returns "success" even if non-fatal errors
431X * were detected.
432X *
433X * If nflag is non-zero, no symbols are predefined except __LINE__.
434X * __FILE__, and __DATE__.  If nflag > 1, absolutely no symbols
435X * are predefined.
436X */
437Xint		keepcomments = FALSE;	/* Write out comments flag	*/
438Xint		cflag = FALSE;		/* -C option (keep comments)	*/
439Xint		eflag = FALSE;		/* -E option (never fail)	*/
440Xint		nflag = 0;		/* -N option (no predefines)	*/
441X
442X/*
443X * ifstack[] holds information about nested #if's.  It is always
444X * accessed via *ifptr.  The information is as follows:
445X *	WAS_COMPILING	state of compiling flag at outer level.
446X *	ELSE_SEEN	set TRUE when #else seen to prevent 2nd #else.
447X *	TRUE_SEEN	set TRUE when #if or #elif succeeds
448X * ifstack[0] holds the compiling flag.  It is TRUE if compilation
449X * is currently enabled.  Note that this must be initialized TRUE.
450X */
451Xchar		ifstack[BLK_NEST] = { TRUE };	/* #if information	*/
452Xchar		*ifptr = ifstack;		/* -> current ifstack[] */
453X
454X/*
455X * incdir[] stores the -i directories (and the system-specific
456X * #include <...> directories.
457X */
458Xchar	*incdir[NINCLUDE];		/* -i directories		*/
459Xchar	**incend = incdir;		/* -> free space in incdir[]	*/
460X
461X/*
462X * This is the table used to predefine target machine and operating
463X * system designators.  It may need hacking for specific circumstances.
464X * Note: it is not clear that this is part of the Ansi Standard.
465X * The -N option supresses preset definitions.
466X */
467Xchar	*preset[] = {			/* names defined at cpp start	*/
468X#ifdef	MACHINE
469X	MACHINE,
470X#endif
471X#ifdef	SYSTEM
472X	SYSTEM,
473X#endif
474X#ifdef	COMPILER
475X	COMPILER,
476X#endif
477X#if	DEBUG
478X	"decus_cpp",			/* Ourselves!			*/
479X#endif
480X	NULL				/* Must be last			*/
481X};
482X
483X/*
484X * The value of these predefined symbols must be recomputed whenever
485X * they are evaluated.  The order must not be changed.
486X */
487Xchar	*magic[] = {			/* Note: order is important	*/
488X	"__LINE__",
489X	"__FILE__",
490X	NULL				/* Must be last			*/
491X};
492X
493Xmain(argc, argv)
494Xint		argc;
495Xchar		*argv[];
496X{
497X	register int	i;
498X
499X#if HOST == SYS_VMS
500X	argc = getredirection(argc, argv);	/* vms >file and <file	*/
501X#endif
502X	initdefines();				/* O.S. specific def's	*/
503X	i = dooptions(argc, argv);		/* Command line -flags	*/
504X	switch (i) {
505X	case 3:
506X	    /*
507X	     * Get output file, "-" means use stdout.
508X	     */
509X	    if (!streq(argv[2], "-")) {
510X#if HOST == SYS_VMS
511X		/*
512X		 * On vms, reopen stdout with "vanilla rms" attributes.
513X		 */
514X		if ((i = creat(argv[2], 0, "rat=cr", "rfm=var")) == -1
515X		 || dup2(i, fileno(stdout)) == -1) {
516X#else
517X		if (freopen(argv[2], "w", stdout) == NULL) {
518X#endif
519X		    perror(argv[2]);
520X		    cerror("Can't open output file \"%s\"", argv[2]);
521X		    exit(IO_ERROR);
522X		}
523X	    }				/* Continue by opening input	*/
524X	case 2:				/* One file -> stdin		*/
525X	    /*
526X	     * Open input file, "-" means use stdin.
527X	     */
528X	    if (!streq(argv[1], "-")) {
529X		if (freopen(argv[1], "r", stdin) == NULL) {
530X		    perror(argv[1]);
531X		    cerror("Can't open input file \"%s\"", argv[1]);
532X		    exit(IO_ERROR);
533X		}
534X		strcpy(work, argv[1]);	/* Remember input filename	*/
535X		break;
536X	    }				/* Else, just get stdin		*/
537X	case 0:				/* No args?			*/
538X	case 1:				/* No files, stdin -> stdout	*/
539X#if HOST == SYS_UNIX
540X	    work[0] = EOS;		/* Unix can't find stdin name	*/
541X#else
542X	    fgetname(stdin, work);	/* Vax-11C, Decus C know name	*/
543X#endif
544X	    break;
545X
546X	default:
547X	    exit(IO_ERROR);		/* Can't happen			*/
548X	}
549X	setincdirs();			/* Setup -I include directories	*/
550X	addfile(stdin, work);		/* "open" main input file	*/
551X#if DEBUG
552X	if (debug > 0)
553X	    dumpdef("preset #define symbols");
554X#endif
555X	cppmain();			/* Process main file		*/
556X	if ((i = (ifptr - &ifstack[0])) != 0) {
557X#if OLD_PREPROCESSOR
558X	    ciwarn("Inside #ifdef block at end of input, depth = %d", i);
559X#else
560X	    cierror("Inside #ifdef block at end of input, depth = %d", i);
561X#endif
562X	}
563X	fclose(stdout);
564X	if (errors > 0) {
565X	    fprintf(stderr, (errors == 1)
566X		? "%d error in preprocessor\n"
567X		: "%d errors in preprocessor\n", errors);
568X	    if (!eflag)
569X		exit(IO_ERROR);
570X	}
571X	exit(IO_NORMAL);		/* No errors or -E option set	*/
572X}
573X
574XFILE_LOCAL
575Xcppmain()
576X/*
577X * Main process for cpp -- copies tokens from the current input
578X * stream (main file, include file, or a macro) to the output
579X * file.
580X */
581X{
582X	register int		c;		/* Current character	*/
583X	register int		counter;	/* newlines and spaces	*/
584X	extern int		output();	/* Output one character	*/
585X
586X	/*
587X	 * Explicitly output a #line at the start of cpp output so
588X	 * that lint (etc.) knows the name of the original source
589X	 * file.  If we don't do this explicitly, we may get
590X	 * the name of the first #include file instead.
591X	 */
592X	sharp();
593X	/*
594X	 * This loop is started "from the top" at the beginning of each line
595X	 * wrongline is set TRUE in many places if it is necessary to write
596X	 * a #line record.  (But we don't write them when expanding macros.)
597X	 *
598X	 * The counter variable has two different uses:  at
599X	 * the start of a line, it counts the number of blank lines that
600X	 * have been skipped over.  These are then either output via
601X	 * #line records or by outputting explicit blank lines.
602X 	 * When expanding tokens within a line, the counter remembers
603X	 * whether a blank/tab has been output.  These are dropped
604X	 * at the end of the line, and replaced by a single blank
605X	 * within lines.
606X	 */
607X	for (;;) {
608X	    counter = 0;			/* Count empty lines	*/
609X	    for (;;) {				/* For each line, ...	*/
610X		while (type[(c = get())] == SPA) /* Skip leading blanks	*/
611X		    ;				/* in this line.	*/
612X		if (c == '\n')			/* If line's all blank,	*/
613X		    ++counter;			/* Do nothing now	*/
614X		else if (c == '#') {		/* Is 1st non-space '#'	*/
615X		    keepcomments = FALSE;	/* Don't pass comments	*/
616X		    counter = control(counter);	/* Yes, do a #command	*/
617X		    keepcomments = (cflag && compiling);
618X		}
619X		else if (c == EOF_CHAR)		/* At end of file?	*/
620X		    break;
621X		else if (!compiling) {		/* #ifdef false?	*/
622X		    skipnl();			/* Skip to newline	*/
623X		    counter++;			/* Count it, too.	*/
624X		}
625X		else {
626X		    break;			/* Actual token		*/
627X		}
628X	    }
629X	    if (c == EOF_CHAR)			/* Exit process at	*/
630X		break;				/* End of file		*/
631X	    /*
632X	     * If the loop didn't terminate because of end of file, we
633X	     * know there is a token to compile.  First, clean up after
634X	     * absorbing newlines.  counter has the number we skipped.
635X	     */
636X	    if ((wrongline && infile->fp != NULL) || counter > 4)
637X		sharp();			/* Output # line number	*/
638X	    else {				/* If just a few, stuff	*/
639X		while (--counter >= 0)		/* them out ourselves	*/
640X		    putchar('\n');
641X	    }
642X	    /*
643X	     * Process each token on this line.
644X	     */
645X	    unget();				/* Reread the char.	*/
646X	    for (;;) {				/* For the whole line,	*/
647X		do {				/* Token concat. loop	*/
648X		    for (counter = 0; (type[(c = get())] == SPA);) {
649X#if COMMENT_INVISIBLE
650X			if (c != COM_SEP)
651X			    counter++;
652X#else
653X			counter++;		/* Skip over blanks	*/
654X#endif
655X		    }
656X		    if (c == EOF_CHAR || c == '\n')
657X			goto end_line;		/* Exit line loop	*/
658X		    else if (counter > 0)	/* If we got any spaces	*/
659X			putchar(' ');		/* Output one space	*/
660X		    c = macroid(c);		/* Grab the token	*/
661X		} while (type[c] == LET && catenate());
662X		if (c == EOF_CHAR || c == '\n')	/* From macro exp error	*/
663X		    goto end_line;		/* Exit line loop	*/
664X		switch (type[c]) {
665X		case LET:
666X		    fputs(token, stdout);	/* Quite ordinary token	*/
667X		    break;
668X
669X
670X		case DIG:			/* Output a number	*/
671X		case DOT:			/* Dot may begin floats	*/
672X		    scannumber(c, output);
673X		    break;
674X
675X		case QUO:			/* char or string const	*/
676X		    scanstring(c, output);	/* Copy it to output	*/
677X		    break;
678X
679X		default:			/* Some other character	*/
680X		    cput(c);			/* Just output it	*/
681X		    break;
682X		}				/* Switch ends		*/
683X	    }					/* Line for loop	*/
684Xend_line:   if (c == '\n') {			/* Compiling at EOL?	*/
685X		putchar('\n');			/* Output newline, if	*/
686X		if (infile->fp == NULL)		/* Expanding a macro,	*/
687X		    wrongline = TRUE;		/* Output # line later	*/
688X	    }
689X	}					/* Continue until EOF	*/
690X}
691X
692Xoutput(c)
693Xint		c;
694X/*
695X * Output one character to stdout -- output() is passed as an
696X * argument to scanstring()
697X */
698X{
699X#if COMMENT_INVISIBLE
700X	if (c != TOK_SEP && c != COM_SEP)
701X#else
702X	if (c != TOK_SEP)
703X#endif
704X	    putchar(c);
705X}
706X
707Xstatic char	*sharpfilename = NULL;
708X
709XFILE_LOCAL
710Xsharp()
711X/*
712X * Output a line number line.
713X */
714X{
715X	register char		*name;
716X
717X	if (keepcomments)			/* Make sure # comes on	*/
718X	    putchar('\n');			/* a fresh, new line.	*/
719X	printf("#%s %d", LINE_PREFIX, line);
720X	if (infile->fp != NULL) {
721X	    name = (infile->progname != NULL)
722X		? infile->progname : infile->filename;
723X	    if (sharpfilename == NULL
724X	     || sharpfilename != NULL && !streq(name, sharpfilename)) {
725X		if (sharpfilename != NULL)
726X		    free(sharpfilename);
727X		sharpfilename = savestring(name);
728X		printf(" \"%s\"", name);
729X	     }
730X	}
731X	putchar('\n');
732X	wrongline = FALSE;
733X}
734END-of-cpp1.c
735echo x - cpp3.c
736sed 's/^X//' >cpp3.c << 'END-of-cpp3.c'
737X/*
738X *				C P P 3 . C
739X *
740X *		    File open and command line options
741X *
742X * Edit history
743X * 13-Nov-84	MM	Split from cpp1.c
744X */
745X
746X#include	<stdio.h>
747X#include	<ctype.h>
748X#include	"cppdef.h"
749X#include	"cpp.h"
750X#if DEBUG && (HOST == SYS_VMS || HOST == SYS_UNIX)
751X#include	<signal.h>
752Xextern int	abort();		/* For debugging		*/
753X#endif
754X
755Xint
756Xopenfile(filename)
757Xchar		*filename;
758X/*
759X * Open a file, add it to the linked list of open files.
760X * This is called only from openfile() above.
761X */
762X{
763X	register FILE		*fp;
764X
765X	if ((fp = fopen(filename, "r")) == NULL) {
766X#if DEBUG
767X	    perror(filename);
768X#endif
769X	    return (FALSE);
770X	}
771X#if DEBUG
772X	if (debug)
773X	    fprintf(stderr, "Reading from \"%s\"\n", filename);
774X#endif
775X	addfile(fp, filename);
776X	return (TRUE);
777X}
778X
779Xaddfile(fp, filename)
780XFILE		*fp;			/* Open file pointer		*/
781Xchar		*filename;		/* Name of the file		*/
782X/*
783X * Initialize tables for this open file.  This is called from openfile()
784X * above (for #include files), and from the entry to cpp to open the main
785X * input file.  It calls a common routine, getfile() to build the FILEINFO
786X * structure which is used to read characters.  (getfile() is also called
787X * to setup a macro replacement.)
788X */
789X{
790X	register FILEINFO	*file;
791X	extern FILEINFO		*getfile();
792X
793X	file = getfile(NBUFF, filename);
794X	file->fp = fp;			/* Better remember FILE *	*/
795X	file->buffer[0] = EOS;		/* Initialize for first read	*/
796X	line = 1;			/* Working on line 1 now	*/
797X	wrongline = TRUE;		/* Force out initial #line	*/
798X}
799X
800Xsetincdirs()
801X/*
802X * Append system-specific directories to the include directory list.
803X * Called only when cpp is started.
804X */
805X{
806X
807X#ifdef	CPP_INCLUDE
808X	*incend++ = CPP_INCLUDE;
809X#define	IS_INCLUDE	1
810X#else
811X#define	IS_INCLUDE	0
812X#endif
813X
814X#if HOST == SYS_UNIX
815X	*incend++ = "/usr/include";
816X#define	MAXINCLUDE	(NINCLUDE - 1 - IS_INCLUDE)
817X#endif
818X
819X#if HOST == SYS_VMS
820X	extern char	*getenv();
821X
822X	if (getenv("C$LIBRARY") != NULL)
823X	    *incend++ = "C$LIBRARY:";
824X	*incend++ = "SYS$LIBRARY:";
825X#define	MAXINCLUDE	(NINCLUDE - 2 - IS_INCLUDE)
826X#endif
827X
828X#if HOST == SYS_RSX
829X	extern int	$$rsts;			/* TRUE on RSTS/E	*/
830X	extern int	$$pos;			/* TRUE on PRO-350 P/OS	*/
831X	extern int	$$vms;			/* TRUE on VMS compat.	*/
832X
833X	if ($$pos) {				/* P/OS?		*/
834X	    *incend++ = "SY:[ZZDECUSC]";	/* C #includes		*/
835X	    *incend++ = "LB:[1,5]";		/* RSX library		*/
836X	}
837X	else if ($$rsts) {			/* RSTS/E?		*/
838X	    *incend++ = "SY:@";			/* User-defined account	*/
839X	    *incend++ = "C:";			/* Decus-C library	*/
840X	    *incend++ = "LB:[1,1]";		/* RSX library		*/
841X	}
842X	else if ($$vms) {			/* VMS compatibility?	*/
843X	    *incend++ = "C:";
844X	}
845X	else {					/* Plain old RSX/IAS	*/
846X	    *incend++ = "LB:[1,1]";
847X	}
848X#define	MAXINCLUDE	(NINCLUDE - 3 - IS_INCLUDE)
849X#endif
850X
851X#if HOST == SYS_RT11
852X	extern int	$$rsts;			/* RSTS/E emulation?	*/
853X
854X	if ($$rsts)
855X	    *incend++ = "SY:@";			/* User-defined account	*/
856X	*incend++ = "C:";			/* Decus-C library disk	*/
857X	*incend++ = "SY:";			/* System (boot) disk	*/
858X#define	MAXINCLUDE	(NINCLUDE - 3 - IS_INCLUDE)
859X#endif
860X}
861X
862Xint
863Xdooptions(argc, argv)
864Xint		argc;
865Xchar		*argv[];
866X/*
867X * dooptions is called to process command line arguments (-Detc).
868X * It is called only at cpp startup.
869X */
870X{
871X	register char		*ap;
872X	register DEFBUF		*dp;
873X	register int		c;
874X	int			i, j;
875X	char			*arg;
876X	SIZES			*sizp;		/* For -S		*/
877X	int			size;		/* For -S		*/
878X	int			isdatum;	/* FALSE for -S*	*/
879X	int			endtest;	/* For -S		*/
880X
881X	for (i = j = 1; i < argc; i++) {
882X	    arg = ap = argv[i];
883X	    if (*ap++ != '-' || *ap == EOS)
884X		argv[j++] = argv[i];
885X	    else {
886X		c = *ap++;			/* Option byte		*/
887X		if (islower(c))			/* Normalize case	*/
888X		    c = toupper(c);
889X		switch (c) {			/* Command character	*/
890X		case 'C':			/* Keep comments	*/
891X		    cflag = TRUE;
892X		    keepcomments = TRUE;
893X		    break;
894X
895X		case 'D':			/* Define symbol	*/
896X#if HOST != SYS_UNIX
897X		    zap_uc(ap);			/* Force define to U.C.	*/
898X#endif
899X		    /*
900X		     * If the option is just "-Dfoo", make it -Dfoo=1
901X		     */
902X		    while (*ap != EOS && *ap != '=')
903X			ap++;
904X		    if (*ap == EOS)
905X			ap = "1";
906X		    else
907X			*ap++ = EOS;
908X		    /*
909X		     * Now, save the word and its definition.
910X		     */
911X		    dp = defendel(argv[i] + 2, FALSE);
912X		    dp->repl = savestring(ap);
913X		    dp->nargs = DEF_NOARGS;
914X		    break;
915X
916X		case 'E':			/* Ignore non-fatal	*/
917X		    eflag = TRUE;		/* errors.		*/
918X		    break;
919X
920X		case 'I':			/* Include directory	*/
921X		    if (incend >= &incdir[MAXINCLUDE])
922X			cfatal("Too many include directories", NULLST);
923X		    *incend++ = ap;
924X		    break;
925X
926X		case 'N':			/* No predefineds	*/
927X		    nflag++;			/* Repeat to undefine	*/
928X		    break;			/* __LINE__, etc.	*/
929X
930X		case 'S':
931X		    sizp = size_table;
932X		    if (isdatum = (*ap != '*'))	/* If it's just -S,	*/
933X			endtest = T_FPTR;	/* Stop here		*/
934X		    else {			/* But if it's -S*	*/
935X			ap++;			/* Step over '*'	*/
936X			endtest = 0;		/* Stop at end marker	*/
937X		    }
938X		    while (sizp->bits != endtest && *ap != EOS) {
939X			if (!isdigit(*ap)) {	/* Skip to next digit	*/
940X			    ap++;
941X			    continue;
942X			}
943X			size = 0;		/* Compile the value	*/
944X			while (isdigit(*ap)) {
945X			    size *= 10;
946X			    size += (*ap++ - '0');
947X			}
948X			if (isdatum)
949X			    sizp->size = size;	/* Datum size		*/
950X			else
951X			    sizp->psize = size;	/* Pointer size		*/
952X			sizp++;
953X		    }
954X		    if (sizp->bits != endtest)
955X			cwarn("-S, too few values specified in %s", argv[i]);
956X		    else if (*ap != EOS)
957X			cwarn("-S, too many values, \"%s\" unused", ap);
958X		    break;
959X
960X		case 'U':			/* Undefine symbol	*/
961X#if HOST != SYS_UNIX
962X		    zap_uc(ap);
963X#endif
964X		    if (defendel(ap, TRUE) == NULL)
965X			cwarn("\"%s\" wasn't defined", ap);
966X		    break;
967X
968X#if DEBUG
969X		case 'X':			/* Debug		*/
970X		    debug = (isdigit(*ap)) ? atoi(ap) : 1;
971X#if (HOST == SYS_VMS || HOST == SYS_UNIX)
972X		    signal(SIGINT, abort);	/* Trap "interrupt"	*/
973X#endif
974X		    fprintf(stderr, "Debug set to %d\n", debug);
975X		    break;
976X#endif
977X
978X		default:			/* What is this one?	*/
979X		    cwarn("Unknown option \"%s\"", arg);
980X		    fprintf(stderr, "The following options are valid:\n\
981X  -C\t\t\tWrite source file comments to output\n\
982X  -Dsymbol=value\tDefine a symbol with the given (optional) value\n\
983X  -Idirectory\t\tAdd a directory to the #include search list\n\
984X  -N\t\t\tDon't predefine target-specific names\n\
985X  -Stext\t\tSpecify sizes for #if sizeof\n\
986X  -Usymbol\t\tUndefine symbol\n");
987X#if DEBUG
988X		    fprintf(stderr, "  -Xvalue\t\tSet internal debug flag\n");
989X#endif
990X		    break;
991X		}			/* Switch on all options	*/
992X	    }				/* If it's a -option		*/
993X	}				/* For all arguments		*/
994X	if (j > 3) {
995X	    cerror(
996X		"Too many file arguments.  Usage: cpp [input [output]]",
997X		NULLST);
998X	}
999X	return (j);			/* Return new argc		*/
1000X}
1001X
1002X#if HOST != SYS_UNIX
1003XFILE_LOCAL
1004Xzap_uc(ap)
1005Xregister char	*ap;
1006X/*
1007X * Dec operating systems mangle upper-lower case in command lines.
1008X * This routine forces the -D and -U arguments to uppercase.
1009X * It is called only on cpp startup by dooptions().
1010X */
1011X{
1012X	while (*ap != EOS) {
1013X	    /*
1014X	     * Don't use islower() here so it works with Multinational
1015X	     */
1016X	    if (*ap >= 'a' && *ap <= 'z')
1017X		*ap = toupper(*ap);
1018X	    ap++;
1019X	}
1020X}
1021X#endif
1022X
1023Xinitdefines()
1024X/*
1025X * Initialize the built-in #define's.  There are two flavors:
1026X * 	#define decus	1		(static definitions)
1027X *	#define	__FILE__ ??		(dynamic, evaluated by magic)
1028X * Called only on cpp startup.
1029X *
1030X * Note: the built-in static definitions are supressed by the -N option.
1031X * __LINE__, __FILE__, and __DATE__ are always present.
1032X */
1033X{
1034X	register char		**pp;
1035X	register char		*tp;
1036X	register DEFBUF		*dp;
1037X	int			i;
1038X	long			tvec;
1039X	extern char		*ctime();
1040X
1041X	/*
1042X	 * Predefine the built-in symbols.  Allow the
1043X	 * implementor to pre-define a symbol as "" to
1044X	 * eliminate it.
1045X	 */
1046X	if (nflag == 0) {
1047X	    for (pp = preset; *pp != NULL; pp++) {
1048X		if (*pp[0] != EOS) {
1049X		    dp = defendel(*pp, FALSE);
1050X		    dp->repl = savestring("1");
1051X		    dp->nargs = DEF_NOARGS;
1052X		}
1053X	    }
1054X	}
1055X	/*
1056X	 * The magic pre-defines (__FILE__ and __LINE__ are
1057X	 * initialized with negative argument counts.  expand()
1058X	 * notices this and calls the appropriate routine.
1059X	 * DEF_NOARGS is one greater than the first "magic" definition.
1060X	 */
1061X	if (nflag < 2) {
1062X	    for (pp = magic, i = DEF_NOARGS; *pp != NULL; pp++) {
1063X		dp = defendel(*pp, FALSE);
1064X		dp->nargs = --i;
1065X	    }
1066X#if OK_DATE
1067X	    /*
1068X	     * Define __DATE__ as today's date.
1069X	     */
1070X	    dp = defendel("__DATE__", FALSE);
1071X	    dp->repl = tp = getmem(27);
1072X	    dp->nargs = DEF_NOARGS;
1073X	    time(&tvec);
1074X	    *tp++ = '"';
1075X	    strcpy(tp, ctime(&tvec));
1076X	    tp[24] = '"';			/* Overwrite newline	*/
1077X#endif
1078X	}
1079X}
1080X
1081X#if HOST == SYS_VMS
1082X/*
1083X * getredirection() is intended to aid in porting C programs
1084X * to VMS (Vax-11 C) which does not support '>' and '<'
1085X * I/O redirection.  With suitable modification, it may
1086X * useful for other portability problems as well.
1087X */
1088X
1089Xint
1090Xgetredirection(argc, argv)
1091Xint		argc;
1092Xchar		**argv;
1093X/*
1094X * Process vms redirection arg's.  Exit if any error is seen.
1095X * If getredirection() processes an argument, it is erased
1096X * from the vector.  getredirection() returns a new argc value.
1097X *
1098X * Warning: do not try to simplify the code for vms.  The code
1099X * presupposes that getredirection() is called before any data is
1100X * read from stdin or written to stdout.
1101X *
1102X * Normal usage is as follows:
1103X *
1104X *	main(argc, argv)
1105X *	int		argc;
1106X *	char		*argv[];
1107X *	{
1108X *		argc = getredirection(argc, argv);
1109X *	}
1110X */
1111X{
1112X	register char		*ap;	/* Argument pointer	*/
1113X	int			i;	/* argv[] index		*/
1114X	int			j;	/* Output index		*/
1115X	int			file;	/* File_descriptor 	*/
1116X	extern int		errno;	/* Last vms i/o error 	*/
1117X
1118X	for (j = i = 1; i < argc; i++) {   /* Do all arguments	*/
1119X	    switch (*(ap = argv[i])) {
1120X	    case '<':			/* <file		*/
1121X		if (freopen(++ap, "r", stdin) == NULL) {
1122X		    perror(ap);		/* Can't find file	*/
1123X		    exit(errno);	/* Is a fatal error	*/
1124X		}
1125X		break;
1126X
1127X	    case '>':			/* >file or >>file	*/
1128X		if (*++ap == '>') {	/* >>file		*/
1129X		    /*
1130X		     * If the file exists, and is writable by us,
1131X		     * call freopen to append to the file (using the
1132X		     * file's current attributes).  Otherwise, create
1133X		     * a new file with "vanilla" attributes as if the
1134X		     * argument was given as ">filename".
1135X		     * access(name, 2) returns zero if we can write on
1136X		     * the specified file.
1137X		     */
1138X		    if (access(++ap, 2) == 0) {
1139X			if (freopen(ap, "a", stdout) != NULL)
1140X			    break;	/* Exit case statement	*/
1141X			perror(ap);	/* Error, can't append	*/
1142X			exit(errno);	/* After access test	*/
1143X		    }			/* If file accessable	*/
1144X		}
1145X		/*
1146X		 * On vms, we want to create the file using "standard"
1147X		 * record attributes.  creat(...) creates the file
1148X		 * using the caller's default protection mask and
1149X		 * "variable length, implied carriage return"
1150X		 * attributes. dup2() associates the file with stdout.
1151X		 */
1152X		if ((file = creat(ap, 0, "rat=cr", "rfm=var")) == -1
1153X		 || dup2(file, fileno(stdout)) == -1) {
1154X		    perror(ap);		/* Can't create file	*/
1155X		    exit(errno);	/* is a fatal error	*/
1156X		}			/* If '>' creation	*/
1157X		break;			/* Exit case test	*/
1158X
1159X	    default:
1160X		argv[j++] = ap;		/* Not a redirector	*/
1161X		break;			/* Exit case test	*/
1162X	    }
1163X	}				/* For all arguments	*/
1164X	argv[j] = NULL;			/* Terminate argv[]	*/
1165X	return (j);			/* Return new argc	*/
1166X}
1167X#endif
1168X
1169X
1170X
1171END-of-cpp3.c
1172echo x - cpp4.c
1173sed 's/^X//' >cpp4.c << 'END-of-cpp4.c'
1174X/*
1175X *			    C P P 4 . C
1176X *		M a c r o  D e f i n i t i o n s
1177X *
1178X * Edit History
1179X * 31-Aug-84	MM	USENET net.sources release
1180X * 04-Oct-84	MM	__LINE__ and __FILE__ must call ungetstring()
1181X *			so they work correctly with token concatenation.
1182X *			Added string formal recognition.
1183X * 25-Oct-84	MM	"Short-circuit" evaluate #if's so that we
1184X *			don't print unnecessary error messages for
1185X *			#if !defined(FOO) && FOO != 0 && 10 / FOO ...
1186X * 31-Oct-84	ado/MM	Added token concatenation
1187X *  6-Nov-84	MM	Split off eval stuff
1188X */
1189X
1190X#include	<stdio.h>
1191X#include	<ctype.h>
1192X#include	"cppdef.h"
1193X#include	"cpp.h"
1194X/*
1195X * parm[], parmp, and parlist[] are used to store #define() argument
1196X * lists.  nargs contains the actual number of parameters stored.
1197X */
1198Xstatic char	parm[NPARMWORK + 1];	/* define param work buffer 	*/
1199Xstatic char	*parmp;			/* Free space in parm		*/
1200Xstatic char	*parlist[LASTPARM];	/* -> start of each parameter	*/
1201Xstatic int	nargs;			/* Parameters for this macro	*/
1202X
1203Xdodefine()
1204X/*
1205X * Called from control when a #define is scanned.  This module
1206X * parses formal parameters and the replacement string.  When
1207X * the formal parameter name is encountered in the replacement
1208X * string, it is replaced by a character in the range 128 to
1209X * 128+NPARAM (this allows up to 32 parameters within the
1210X * Dec Multinational range).  If cpp is ported to an EBCDIC
1211X * machine, you will have to make other arrangements.
1212X *
1213X * There is some special case code to distinguish
1214X *	#define foo	bar
1215X * from	#define foo()	bar
1216X *
1217X * Also, we make sure that
1218X *	#define	foo	foo
1219X * expands to "foo" but doesn't put cpp into an infinite loop.
1220X *
1221X * A warning message is printed if you redefine a symbol to a
1222X * different text.  I.e,
1223X *	#define	foo	123
1224X *	#define foo	123
1225X * is ok, but
1226X *	#define foo	123
1227X *	#define	foo	+123
1228X * is not.
1229X *
1230X * The following subroutines are called from define():
1231X * checkparm	called when a token is scanned.  It checks through the
1232X *		array of formal parameters.  If a match is found, the
1233X *		token is replaced by a control byte which will be used
1234X *		to locate the parameter when the macro is expanded.
1235X * textput	puts a string in the macro work area (parm[]), updating
1236X *		parmp to point to the first free byte in parm[].
1237X *		textput() tests for work buffer overflow.
1238X * charput	puts a single character in the macro work area (parm[])
1239X *		in a manner analogous to textput().
1240X */
1241X{
1242X	register int		c;
1243X	register DEFBUF		*dp;		/* -> new definition	*/
1244X	int			isredefine;	/* TRUE if redefined	*/
1245X	char			*old;		/* Remember redefined	*/
1246X	extern int		save();		/* Save char in work[]	*/
1247X
1248X	if (type[(c = skipws())] != LET)
1249X	    goto bad_define;
1250X	isredefine = FALSE;			/* Set if redefining	*/
1251X	if ((dp = lookid(c)) == NULL)		/* If not known now	*/
1252X	    dp = defendel(token, FALSE);	/* Save the name	*/
1253X	else {					/* It's known:		*/
1254X	    isredefine = TRUE;			/* Remember this fact	*/
1255X	    old = dp->repl;			/* Remember replacement	*/
1256X	    dp->repl = NULL;			/* No replacement now	*/
1257X	}
1258X	parlist[0] = parmp = parm;		/* Setup parm buffer	*/
1259X	if ((c = get()) == '(') {		/* With arguments?	*/
1260X	    nargs = 0;				/* Init formals counter	*/
1261X	    do {				/* Collect formal parms	*/
1262X		if (nargs >= LASTPARM)
1263X		    cfatal("Too many arguments for macro", NULLST);
1264X		else if ((c = skipws()) == ')')
1265X		    break;			/* Got them all		*/
1266X		else if (type[c] != LET)	/* Bad formal syntax	*/
1267X		    goto bad_define;
1268X		scanid(c);			/* Get the formal param	*/
1269X		parlist[nargs++] = parmp;	/* Save its start	*/
1270X		textput(token);			/* Save text in parm[]	*/
1271X	    } while ((c = skipws()) == ',');	/* Get another argument	*/
1272X	    if (c != ')')			/* Must end at )	*/
1273X		goto bad_define;
1274X	    c = ' ';				/* Will skip to body	*/
1275X	}
1276X	else {
1277X	    /*
1278X	     * DEF_NOARGS is needed to distinguish between
1279X	     * "#define foo" and "#define foo()".
1280X	     */
1281X	    nargs = DEF_NOARGS;			/* No () parameters	*/
1282X	}
1283X	if (type[c] == SPA)			/* At whitespace?	*/
1284X	    c = skipws();			/* Not any more.	*/
1285X	workp = work;				/* Replacement put here	*/
1286X	inmacro = TRUE;				/* Keep \<newline> now	*/
1287X	while (c != EOF_CHAR && c != '\n') {	/* Compile macro body	*/
1288X#if OK_CONCAT
1289X	    if (c == '#') {			/* Token concatenation?	*/
1290X		while (workp > work && type[workp[-1]] == SPA)
1291X		    --workp;			/* Erase leading spaces	*/
1292X		save(TOK_SEP);			/* Stuff a delimiter	*/
1293X		c = skipws();			/* Eat whitespace	*/
1294X		if (type[c] == LET)		/* Another token here?	*/
1295X		    ;				/* Stuff it normally	*/
1296X		else if (type[c] == DIG) {	/* Digit string after?	*/
1297X		    while (type[c] == DIG) {	/* Stuff the digits	*/
1298X			save(c);
1299X			c = get();
1300X		    }
1301X		    save(TOK_SEP);		/* Delimit 2nd token	*/
1302X		}
1303X		else {
1304X		    ciwarn("Strange character after # (%d.)", c);
1305X		}
1306X		continue;
1307X	    }
1308X#endif
1309X	    switch (type[c]) {
1310X	    case LET:
1311X		checkparm(c, dp);		/* Might be a formal	*/
1312X		break;
1313X
1314X	    case DIG:				/* Number in mac. body	*/
1315X	    case DOT:				/* Maybe a float number	*/
1316X		scannumber(c, save);		/* Scan it off		*/
1317X		break;
1318X
1319X	    case QUO:				/* String in mac. body	*/
1320X#if STRING_FORMAL
1321X		stparmscan(c, dp);		/* Do string magic	*/
1322X#else
1323X		stparmscan(c);
1324X#endif
1325X		break;
1326X
1327X	    case BSH:				/* Backslash		*/
1328X		save('\\');
1329X		if ((c = get()) == '\n')
1330X		    wrongline = TRUE;
1331X		save(c);
1332X		break;
1333X
1334X	    case SPA:				/* Absorb whitespace	*/
1335X		/*
1336X		 * Note: the "end of comment" marker is passed on
1337X		 * to allow comments to separate tokens.
1338X		 */
1339X		if (workp[-1] == ' ')		/* Absorb multiple	*/
1340X		    break;			/* spaces		*/
1341X		else if (c == '\t')
1342X		    c = ' ';			/* Normalize tabs	*/
1343X		/* Fall through to store character			*/
1344X	    default:				/* Other character	*/
1345X		save(c);
1346X		break;
1347X	    }
1348X	    c = get();
1349X	}
1350X	inmacro = FALSE;			/* Stop newline hack	*/
1351X	unget();				/* For control check	*/
1352X	if (workp > work && workp[-1] == ' ')	/* Drop trailing blank	*/
1353X	    workp--;
1354X	*workp = EOS;				/* Terminate work	*/
1355X	dp->repl = savestring(work);		/* Save the string	*/
1356X	dp->nargs = nargs;			/* Save arg count	*/
1357X#if DEBUG
1358X	if (debug)
1359X	    dumpadef("macro definition", dp);
1360X#endif
1361X	if (isredefine) {			/* Error if redefined	*/
1362X	    if ((old != NULL && dp->repl != NULL && !streq(old, dp->repl))
1363X	     || (old == NULL && dp->repl != NULL)
1364X	     || (old != NULL && dp->repl == NULL)) {
1365X		cerror("Redefining defined variable \"%s\"", dp->name);
1366X	    }
1367X	    if (old != NULL)			/* We don't need the	*/
1368X		free(old);			/* old definition now.	*/
1369X	}
1370X	return;
1371X
1372Xbad_define:
1373X	cerror("#define syntax error", NULLST);
1374X	inmacro = FALSE;			/* Stop <newline> hack	*/
1375X}
1376X
1377Xcheckparm(c, dp)
1378Xregister int	c;
1379XDEFBUF		*dp;
1380X/*
1381X * Replace this param if it's defined.  Note that the macro name is a
1382X * possible replacement token.  We stuff DEF_MAGIC in front of the token
1383X * which is treated as a LETTER by the token scanner and eaten by
1384X * the output routine.  This prevents the macro expander from
1385X * looping if someone writes "#define foo foo".
1386X */
1387X{
1388X	register int		i;
1389X	register char		*cp;
1390X
1391X	scanid(c);				/* Get parm to token[]	*/
1392X	for (i = 0; i < nargs; i++) {		/* For each argument	*/
1393X	    if (streq(parlist[i], token)) {	/* If it's known	*/
1394X		save(i + MAC_PARM);		/* Save a magic cookie	*/
1395X		return;				/* And exit the search	*/
1396X	    }
1397X	}
1398X	if (streq(dp->name, token))		/* Macro name in body?	*/
1399X	    save(DEF_MAGIC);			/* Save magic marker	*/
1400X	for (cp = token; *cp != EOS;)		/* And save		*/
1401X	    save(*cp++);			/* The token itself	*/
1402X}
1403X
1404X#if STRING_FORMAL
1405Xstparmscan(delim, dp)
1406Xint		delim;
1407Xregister DEFBUF	*dp;
1408X/*
1409X * Scan the string (starting with the given delimiter).
1410X * The token is replaced if it is the only text in this string or
1411X * character constant.  The algorithm follows checkparm() above.
1412X * Note that scanstring() has approved of the string.
1413X */
1414X{
1415X	register int		c;
1416X
1417X	/*
1418X	 * Warning -- this code hasn't been tested for a while.
1419X	 * It exists only to preserve compatibility with earlier
1420X	 * implementations of cpp.  It is not part of the Draft
1421X	 * ANSI Standard C language.
1422X	 */
1423X	save(delim);
1424X	instring = TRUE;
1425X	while ((c = get()) != delim
1426X	     && c != '\n'
1427X	     && c != EOF_CHAR) {
1428X	    if (type[c] == LET)			/* Maybe formal parm	*/
1429X		checkparm(c, dp);
1430X	    else {
1431X		save(c);
1432X		if (c == '\\')
1433X		    save(get());
1434X	    }
1435X	}
1436X	instring = FALSE;
1437X	if (c != delim)
1438X	    cerror("Unterminated string in macro body", NULLST);
1439X	save(c);
1440X}
1441X#else
1442Xstparmscan(delim)
1443Xint		delim;
1444X/*
1445X * Normal string parameter scan.
1446X */
1447X{
1448X	register char		*wp;
1449X	register int		i;
1450X	extern int		save();
1451X
1452X	wp = workp;			/* Here's where it starts	*/
1453X	if (!scanstring(delim, save))
1454X	    return;			/* Exit on scanstring error	*/
1455X	workp[-1] = EOS;		/* Erase trailing quote		*/
1456X	wp++;				/* -> first string content byte	*/
1457X	for (i = 0; i < nargs; i++) {
1458X	    if (streq(parlist[i], wp)) {
1459X		*wp++ = MAC_PARM + PAR_MAC;	/* Stuff a magic marker	*/
1460X		*wp++ = (i + MAC_PARM);		/* Make a formal marker	*/
1461X		*wp = wp[-3];			/* Add on closing quote	*/
1462X		workp = wp + 1;			/* Reset string end	*/
1463X		return;
1464X	    }
1465X	}
1466X	workp[-1] = wp[-1];		/* Nope, reset end quote.	*/
1467X}
1468X#endif
1469X
1470Xdoundef()
1471X/*
1472X * Remove the symbol from the defined list.
1473X * Called from the #control processor.
1474X */
1475X{
1476X	register int		c;
1477X
1478X	if (type[(c = skipws())] != LET)
1479X	    cerror("Illegal #undef argument", NULLST);
1480X	else {
1481X	    scanid(c);				/* Get name to token[]	*/
1482X	    if (defendel(token, TRUE) == NULL) {
1483X		cwarn("Symbol \"%s\" not defined in #undef", token);
1484X	    }
1485X	}
1486X}
1487X
1488Xtextput(text)
1489Xchar		*text;
1490X/*
1491X * Put the string in the parm[] buffer.
1492X */
1493X{
1494X	register int	size;
1495X
1496X	size = strlen(text) + 1;
1497X	if ((parmp + size) >= &parm[NPARMWORK])
1498X	    cfatal("Macro work area overflow", NULLST);
1499X	else {
1500X	    strcpy(parmp, text);
1501X	    parmp += size;
1502X	}
1503X}
1504X
1505Xcharput(c)
1506Xregister int	c;
1507X/*
1508X * Put the byte in the parm[] buffer.
1509X */
1510X{
1511X	if (parmp >= &parm[NPARMWORK])
1512X	    cfatal("Macro work area overflow", NULLST);
1513X	else {
1514X	    *parmp++ = c;
1515X	}
1516X}
1517X
1518X/*
1519X *		M a c r o   E x p a n s i o n
1520X */
1521X
1522Xstatic DEFBUF	*macro;		/* Catches start of infinite macro	*/
1523X
1524Xexpand(tokenp)
1525Xregister DEFBUF	*tokenp;
1526X/*
1527X * Expand a macro.  Called from the cpp mainline routine (via subroutine
1528X * macroid()) when a token is found in the symbol table.  It calls
1529X * expcollect() to parse actual parameters, checking for the correct number.
1530X * It then creates a "file" containing a single line containing the
1531X * macro with actual parameters inserted appropriately.  This is
1532X * "pushed back" onto the input stream.  (When the get() routine runs
1533X * off the end of the macro line, it will dismiss the macro itself.)
1534X */
1535X{
1536X	register int		c;
1537X	register FILEINFO	*file;
1538X	extern FILEINFO		*getfile();
1539X
1540X#if DEBUG
1541X	if (debug)
1542X	    dumpadef("expand entry", tokenp);
1543X#endif
1544X	/*
1545X	 * If no macro is pending, save the name of this macro
1546X	 * for an eventual error message.
1547X	 */
1548X	if (recursion++ == 0)
1549X	    macro = tokenp;
1550X	else if (recursion == RECURSION_LIMIT) {
1551X	    cerror("Recursive macro definition of \"%s\"", tokenp->name);
1552X	    fprintf(stderr, "(Defined by \"%s\")\n", macro->name);
1553X	    if (rec_recover) {
1554X		do {
1555X		    c = get();
1556X		} while (infile != NULL && infile->fp == NULL);
1557X		unget();
1558X		recursion = 0;
1559X		return;
1560X	    }
1561X	}
1562X	/*
1563X	 * Here's a macro to expand.
1564X	 */
1565X	nargs = 0;				/* Formals counter	*/
1566X	parmp = parm;				/* Setup parm buffer	*/
1567X	switch (tokenp->nargs) {
1568X	case (-2):				/* __LINE__		*/
1569X	    sprintf(work, "%d", line);
1570X	    ungetstring(work);
1571X	    break;
1572X
1573X	case (-3):				/* __FILE__		*/
1574X	    for (file = infile; file != NULL; file = file->parent) {
1575X		if (file->fp != NULL) {
1576X		    sprintf(work, "\"%s\"", (file->progname != NULL)
1577X			? file->progname : file->filename);
1578X		    ungetstring(work);
1579X		    break;
1580X		}
1581X	    }
1582X	    break;
1583X
1584X	default:
1585X	    /*
1586X	     * Nothing funny about this macro.
1587X	     */
1588X	    if (tokenp->nargs < 0)
1589X		cfatal("Bug: Illegal __ macro \"%s\"", tokenp->name);
1590X	    while ((c = skipws()) == '\n')	/* Look for (, skipping	*/
1591X		wrongline = TRUE;		/* spaces and newlines	*/
1592X	    if (c != '(') {
1593X		/*
1594X		 * If the programmer writes
1595X		 *	#define foo() ...
1596X		 *	...
1597X		 *	foo [no ()]
1598X		 * just write foo to the output stream.
1599X		 */
1600X		unget();
1601X		cwarn("Macro \"%s\" needs arguments", tokenp->name);
1602X		fputs(tokenp->name, stdout);
1603X		return;
1604X	    }
1605X	    else if (expcollect()) {		/* Collect arguments	*/
1606X		if (tokenp->nargs != nargs) {	/* Should be an error?	*/
1607X		    cwarn("Wrong number of macro arguments for \"%s\"",
1608X			tokenp->name);
1609X		}
1610X#if DEBUG
1611X		if (debug)
1612X		    dumpparm("expand");
1613X#endif
1614X	    }				/* Collect arguments		*/
1615X	case DEF_NOARGS:		/* No parameters just stuffs	*/
1616X	    expstuff(tokenp);		/* Do actual parameters		*/
1617X	}				/* nargs switch			*/
1618X}
1619X
1620XFILE_LOCAL int
1621Xexpcollect()
1622X/*
1623X * Collect the actual parameters for this macro.  TRUE if ok.
1624X */
1625X{
1626X	register int	c;
1627X	register int	paren;			/* For embedded ()'s	*/
1628X	extern int	charput();
1629X
1630X	for (;;) {
1631X	    paren = 0;				/* Collect next arg.	*/
1632X	    while ((c = skipws()) == '\n')	/* Skip over whitespace	*/
1633X		wrongline = TRUE;		/* and newlines.	*/
1634X	    if (c == ')') {			/* At end of all args?	*/
1635X		/*
1636X		 * Note that there is a guard byte in parm[]
1637X		 * so we don't have to check for overflow here.
1638X		 */
1639X		*parmp = EOS;			/* Make sure terminated	*/
1640X		break;				/* Exit collection loop	*/
1641X	    }
1642X	    else if (nargs >= LASTPARM)
1643X		cfatal("Too many arguments in macro expansion", NULLST);
1644X	    parlist[nargs++] = parmp;		/* At start of new arg	*/
1645X	    for (;; c = cget()) {		/* Collect arg's bytes	*/
1646X		if (c == EOF_CHAR) {
1647X		    cerror("end of file within macro argument", NULLST);
1648X		    return (FALSE);		/* Sorry.		*/
1649X		}
1650X		else if (c == '\\') {		/* Quote next character	*/
1651X		    charput(c);			/* Save the \ for later	*/
1652X		    charput(cget());		/* Save the next char.	*/
1653X		    continue;			/* And go get another	*/
1654X		}
1655X		else if (type[c] == QUO) {	/* Start of string?	*/
1656X		    scanstring(c, charput);	/* Scan it off		*/
1657X		    continue;			/* Go get next char	*/
1658X		}
1659X		else if (c == '(')		/* Worry about balance	*/
1660X		    paren++;			/* To know about commas	*/
1661X		else if (c == ')') {		/* Other side too	*/
1662X		    if (paren == 0) {		/* At the end?		*/
1663X			unget();		/* Look at it later	*/
1664X			break;			/* Exit arg getter.	*/
1665X		    }
1666X		    paren--;			/* More to come.	*/
1667X		}
1668X		else if (c == ',' && paren == 0) /* Comma delimits args	*/
1669X		    break;
1670X		else if (c == '\n')		/* Newline inside arg?	*/
1671X		    wrongline = TRUE;		/* We'll need a #line	*/
1672X		charput(c);			/* Store this one	*/
1673X	    }					/* Collect an argument	*/
1674X	    charput(EOS);			/* Terminate argument	*/
1675X#if DEBUG
1676X	    if (debug)
1677X	        printf("parm[%d] = \"%s\"\n", nargs, parlist[nargs - 1]);
1678X#endif
1679X	}					/* Collect all args.	*/
1680X	return (TRUE);				/* Normal return	*/
1681X}
1682X
1683XFILE_LOCAL
1684Xexpstuff(tokenp)
1685XDEFBUF		*tokenp;		/* Current macro being expanded	*/
1686X/*
1687X * Stuff the macro body, replacing formal parameters by actual parameters.
1688X */
1689X{
1690X	register int	c;			/* Current character	*/
1691X	register char	*inp;			/* -> repl string	*/
1692X	register char	*defp;			/* -> macro output buff	*/
1693X	int		size;			/* Actual parm. size	*/
1694X	char		*defend;		/* -> output buff end	*/
1695X	int		string_magic;		/* String formal hack	*/
1696X	FILEINFO	*file;			/* Funny #include	*/
1697X	extern FILEINFO	*getfile();
1698X
1699X	file = getfile(NBUFF, tokenp->name);
1700X	inp = tokenp->repl;			/* -> macro replacement	*/
1701X	defp = file->buffer;			/* -> output buffer	*/
1702X	defend = defp + (NBUFF - 1);		/* Note its end		*/
1703X	if (inp != NULL) {
1704X	    while ((c = (*inp++ & 0xFF)) != EOS) {
1705X		if (c >= MAC_PARM && c <= (MAC_PARM + PAR_MAC)) {
1706X		    string_magic = (c == (MAC_PARM + PAR_MAC));
1707X		    if (string_magic)
1708X		 	c = (*inp++ & 0xFF);
1709X		    /*
1710X		     * Replace formal parameter by actual parameter string.
1711X		     */
1712X		    if ((c -= MAC_PARM) < nargs) {
1713X			size = strlen(parlist[c]);
1714X			if ((defp + size) >= defend)
1715X			    goto nospace;
1716X			/*
1717X			 * Erase the extra set of quotes.
1718X			 */
1719X			if (string_magic && defp[-1] == parlist[c][0]) {
1720X			    strcpy(defp-1, parlist[c]);
1721X			    defp += (size - 2);
1722X			}
1723X			else {
1724X			    strcpy(defp, parlist[c]);
1725X			    defp += size;
1726X			}
1727X		    }
1728X		}
1729X		else if (defp >= defend) {
1730Xnospace:	    cfatal("Out of space in macro \"%s\" arg expansion",
1731X			tokenp->name);
1732X		}
1733X		else {
1734X		    *defp++ = c;
1735X		}
1736X	    }
1737X	}
1738X	*defp = EOS;
1739X#if DEBUG
1740X	if (debug > 1)
1741X	    printf("macroline: \"%s\"\n", file->buffer);
1742X#endif
1743X}
1744X
1745X#if DEBUG
1746Xdumpparm(why)
1747Xchar		*why;
1748X/*
1749X * Dump parameter list.
1750X */
1751X{
1752X	register int	i;
1753X
1754X	printf("dump of %d parameters (%d bytes total) %s\n",
1755X	    nargs, parmp - parm, why);
1756X	for (i = 0; i < nargs; i++) {
1757X	    printf("parm[%d] (%d) = \"%s\"\n",
1758X		i + 1, strlen(parlist[i]), parlist[i]);
1759X	}
1760X}
1761X#endif
1762END-of-cpp4.c
1763exit
1764