1.fp 5 CW
2.de L		\" literal font
3.ft 5
4.if !\\$1 \&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \f1
5..
6.de LR
7.}S 5 1 \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
8..
9.de RL
10.}S 1 5 \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
11..
12.de EX		\" start example
13.ta 1i 2i 3i 4i 5i 6i
14.PP
15.RS 
16.PD 0
17.ft 5
18.nf
19..
20.de EE		\" end example
21.fi
22.ft
23.PD
24.RE
25.PP
26..
27.TH PP 3
28.SH NAME \" @(#)pp.3 (gsf@research.att.com) 04/01/92
29pp \- ANSI C preprocessor library
30.SH SYNOPSIS
31.EX
32:PACKAGE: ast
33#include <pp.h>
34%include "pptokens.yacc
35\-lpp
36.EE
37.SH DESCRIPTION
38The
39.I pp
40library provides a tokenizing implementation of the C language preprocessor
41and supports K&R (Reiser), ANSI and C++ dialects.
42The preprocessor is comprised of 12 public functions,
43a global character class table accessed by macros, and
44a single global struct with 10 public elements.
45.PP
46.I pp
47operates in two modes.
48.I Standalone
49mode is used to implement the traditional standalone C preprocessor.
50.I Tokeinizing
51mode provides a function interface to a stream of preprocessed tokens.
52.I pp
53is by default ANSI; the only default predefined symbols are
54.L __STDC__
55and
56.LR __STDPP__ .
57Dialects (K&R, C++) and local conventions are determined by
58compiler specific
59.IR probe (1)
60information that is included at runtime.
61The
62.I probe
63information can be overridden by providing a file
64.L pp_default.h
65with pragmas and definitions for each compiler implementation.
66This file is usually located in the compiler specific
67default include directory.
68.PP
69Directive, command line argument, option and pragma syntax is described in
70.IR cpp (1).
71.I pp
72specific semantics are described below.
73Most semantic differences with standard or classic implementations are in the
74form of optimizations.
75.PP
76Options and pragmas map to
77.L ppop
78function calls described below.
79For the remaining descriptions,
80``setting \f5ppop(PP_\fP\fIoperation\fP\f5)\fP''
81is a shorthand for calling
82.L ppop
83with the arguments appropriate for
84\f5PP_\fP\fIoperation\fP.
85.PP
86The library interface describes only the public functions and struct elements.
87Static structs and pointers to structs are provided by the library.
88The user should not attempt to allocate structs.
89In particular,
90.L sizeof
91is meaningless for
92.I pp
93supplied structs.
94.PP
95The global struct
96.L pp
97provides readonly information.
98Any changes to
99.L pp
100must be done using the functions described below.
101.L pp
102has the following public elements:
103.TP
104.L "char* version"
105The
106.I pp
107implementaion version string.
108.TP
109.L "char* lineid"
110The current line sync directive name.
111Used for standalone line sync output.
112The default value is the empty string.
113See the
114.L ppline
115function below.
116.TP
117.L "char* outfile"
118The current output file name.
119.TP
120.L "char* pass"
121The pragma pass name for
122.I pp.
123The default value is
124.LR pp .
125.TP
126.L "char* token"
127The string representation for the current input token.
128.TP
129.L "int flags"
130The inclusive or of:
131.RS
132.TP
133.L PP_comment
134Set if 
135.L ppop(PP_COMMENT)
136was set.
137.TP
138.L PP_compatibility
139Set if 
140.L ppop(PP_COMPATIBILITY)
141was set.
142.TP
143.L PP_linefile
144Set if standalone line syncs require a file argument.
145.TP
146.L PP_linetype
147Set if standalone line syncs require a third argument.
148The third argument is
149.L 1
150for include file push,
151.L 2
152for include file pop and null otherwise.
153.TP
154.L PP_strict
155Set if 
156.L ppop(PP_STRICT)
157was set.
158.TP
159.L PP_transition
160Set if 
161.L ppop(PP_TRANSITION)
162was set.
163.RE
164.TP
165.L "struct ppdirs* lcldirs"
166The list of directories to be searched for "..." include files.
167If the first directory name is "" then it is replaced by the
168directory of the including file at include time.
169The public elements of
170.L "struct ppdirs"
171are:
172.RS
173.TP
174.L "char* name"
175The directory pathname.
176.TP
177.L "struct ppdirs* next"
178The next directory,
179.L 0
180if it is the last in the list.
181.RE
182.TP
183.L "struct ppdirs* stddirs"
184.L pp.stddirs\->next
185is the list of directories to be searched for <...> include files.
186This list may be
187.LR 0 .
188.TP
189.L "struct ppsymbol* symbol"
190If
191.L ppop(PP_COMPILE)
192was set then
193.L pp.symbol
194points to the symbol table entry for the current identifier token.
195.L pp.symbol
196is undefined for non-identifier tokens.
197Once defined, an identifier will always have the same
198.L ppsymbol
199pointer.
200If
201.L ppop(PP_NOHASH)
202was also set then
203.L pp.symbol
204is defined for macro and keyword tokens and
205.L 0
206for all other identifiers.
207The elements of
208.L "struct ppsymbol"
209are:
210.RS
211.TP
212.L "char* name"
213The identifier name.
214.TP
215.L "int flags"
216The inclusive or of the following flags:
217.PD 0
218.RS
219.TP
220.L SYM_ACTIVE
221Currently being expanded.
222.TP
223.L SYM_BUILTIN
224Builtin macro.
225.TP
226.L SYM_DISABLED
227Macro expansion currently disabled.
228.TP
229.L SYM_FUNCTION
230Function-like macro.
231.TP
232.L SYM_INIT
233Initialization macro.
234.TP
235.L SYM_KEYWORD
236Keyword identifier.
237.TP
238.L SYM_LOADED
239Loaded checkpoint macro.
240.TP
241.L SYM_MULTILINE
242.L #macdef
243macro.
244.TP
245.L SYM_NOEXPAND
246No identifiers in macro body.
247.TP
248.L SYM_PREDEFINED
249Predefined macro.
250.TP
251.L SYM_PREDICATE
252Also a
253.L #assert
254predicate.
255.TP
256.L SYM_READONLY
257Readonly macro.
258.TP
259.L SYM_REDEFINE
260Ok to redefine.
261.TP
262.L SYM_VARIADIC
263Variadic function-like macro.
264.TP
265.L SYM_UNUSED
266First unused symbol flag bit index.
267The bits from
268.L (1<<SYM_UNUSED)
269on are initially unset and may be set by the user.
270.RE
271.PD
272.TP
273.L "struct ppmacro* macro"
274Non-zero if the identifier is a macro.
275.L "int macro\->arity"
276is the number of formal arguments for function-like macros and
277.L "char* macro\->value"
278is the macro definition value, a
279.L 0
280terminated string that may contain internal mark sequences.
281.TP
282.L "char* value"
283Initially set to
284.L 0
285and never modified by
286.IR pp .
287This field may be set by the user.
288.RE
289.TP
290.L "Hash_table_t* symtab"
291The macro and identifier
292.L "struct ppsymbol"
293hash table.
294The
295.IR hash (3)
296routines may be used to examine the table, with the exception that the
297following macros must be used for individual
298.L pp.symtab
299symbol lookup:
300.RS
301.TP
302.L "struct ppsymbol* ppsymget(Hash_table_t* table, char* name)"
303Return the
304.L ppsymbol
305pointer for
306.LR name ,
3070 if
308.L name
309not defined.
310.TP
311.L "struct ppsymbol* ppsymset(Hash_table_t* table, char* name)"
312Return the
313.L ppsymbol
314pointer for
315.LR name .
316If
317.L name
318is not defined then allocate and return a new
319.L ppsymbol
320for it.
321.RE
322.RE
323.PP
324Error messages are reported using
325.IR error (3)
326and the following globals relate to
327.IR pp :
328.TP
329.L "int error_info.errors"
330The level 2 error count.
331Error levels above 2 cause immediate exit.
332If
333.L error_info.errors
334is non-zero then the user program exit status should also be non-zero.
335.TP
336.L "char* error_info.file"
337The current input file name.
338.TP
339.L "int error_info.line"
340The current input line number.
341.TP
342.L "int error_info.trace"
343The debug trace level,
344.L 0
345by default.
346Larger negative numbers produce more trace information.
347Enabled when the user program is linked with the
348.B \-g
349.IR cc (1)
350option.
351.TP
352.L "int error_info.warnings"
353The level 1 error count.
354Warnings do not affect the exit status.
355.PP
356The functions are:
357.TP
358.L "extern int ppargs(char** argv, int last);"
359Passed to
360.IR optjoin (3)
361to parse
362.IR cpp (1)
363style options and arguments.
364The user may also supply application specific option parsers.
365Also handles non-standard options like the sun
366.L \-undef
367and GNU
368.LR \-trigraphs .
369Hello in there, ever here of
370.IR getopt (3)?
371.TP
372.L "extern void ppcpp(void);"
373This is the standalone
374.IR cpp (1)
375entry point.
376.L ppcpp
377consumes all of the input and writes the preprocessed text to the output.
378A single call to
379.L ppcpp
380is equivalent to, but more efficient than:
381.EX
382    ppop(PP_SPACEOUT, 1);
383    while (pplex())
384	ppprintf(" %s", pp.token);
385.EE
386.TP
387.L "extern int ppcomment(char* head, char* comment, char* tail, int line);"
388The default comment handler that passes comments to the output.
389May be used as an argument to
390.LR ppop(PP_COMMENT) ,
391or the user may supply an application specific handler.
392.L head
393is the comment head text,
394.L "/*"
395for C and
396.L "//"
397for C++,
398.L comment
399is the comment body,
400.L tail
401is the comment tail text,
402.L "*/"
403for C and
404.B newline
405for C++, and
406.L line
407is the comment starting line number.
408.TP
409.L "extern void pperror(int level, char* format, ...);"
410Equivalent to
411.IR error (3).
412All
413.I pp
414error and warning messages pass through
415.LR pperror .
416The user may link with an application specific
417.L pperror
418to override the library default.
419.TP
420.L "extern int ppincref(char* parent, char* file, int line, int push);"
421The default include reference handler that outputs
422.L file
423to the standard error.
424May be used as an argument to the
425.LR ppop(PP_INCREF) ,
426or the user may supply an application specific handler.
427.L parent
428is the including file name,
429.L file
430is the current include file name,
431.L line
432is the current line number in
433.LR file ,
434and 
435.L push
436is non-zero if
437.L file
438is being pushed or
439.L 0
440if file is being popped.
441.TP
442.L "extern void ppinput(char* buffer, char* file, int line);"
443Pushes the
444.L 0
445terminated
446.L buffer
447on the
448.I pp
449input stack.
450.L file
451is the pseudo file name used in line syncs for
452.L buffer
453and
454.L line
455is the starting line number.
456.TP
457.L "int pplex(void)"
458Returns the token type of the next input token.
459.L pp.token
460and where applicable
461.L pp.symbol
462are updated to refer to the new token.
463The token type constants are defined in
464.L pp.h
465for
466.L #include
467and
468.L pp.yacc
469for
470.IR yacc (1)
471.LR %include .
472The token constant names match
473.LR T_[A-Z_]* ;
474some are encoded by oring with
475.L N_[A-Z_]*
476tokens.
477.sp
478The numeric constant tokens and encodings are:
479.EX
480    T_DOUBLE          (N_NUMBER|N_REAL)
481    T_DOUBLE_L        (N_NUMBER|N_REAL|N_LONG)
482    T_FLOAT           (N_NUMBER|N_REAL|N_FLOAT)
483    T_DECIMAL         (N_NUMBER)
484    T_DECIMAL_L       (N_NUMBER|N_LONG)
485    T_DECIMAL_U       (N_NUMBER|N_UNSIGNED)
486    T_DECIMAL_UL      (N_NUMBER|N_UNSIGNED|N_LONG)
487    T_OCTAL           (N_NUMBER|N_OCTAL)
488    T_OCTAL_L         (N_NUMBER|N_OCTAL|N_LONG)
489    T_OCTAL_U         (N_NUMBER|N_OCTAL|N_UNSIGNED)
490    T_OCTAL_UL        (N_NUMBER|N_OCTAL|N_UNSIGNED|N_LONG)
491    T_HEXADECIMAL     (N_NUMBER|N_HEXADECIMAL)
492    T_HEXADECIMAL_L   (N_NUMBER|N_HEXADECIMAL|N_LONG)
493    T_HEXADECIMAL_U   (N_NUMBER|N_HEXADECIMAL|N_UNSIGNED)
494    T_HEXADECIMAL_UL  (N_NUMBER|N_HEXADECIMAL|N_UNSIGNED|N_LONG)
495.EE
496The normal C tokens are:
497.EX
498    T_ID              \fIC identifier\fP
499    T_INVALID         \fIinvalid token\fP
500    T_HEADER          <..>
501    T_CHARCONST       '..'
502    T_WCHARCONST      L'..'
503    T_STRING          ".."
504    T_WSTRING         L".."
505    T_PTRMEM          ->
506    T_ADDADD          ++
507    T_SUBSUB          --
508    T_LSHIFT          <<
509    T_RSHIFT          >>
510    T_LE              <=
511    T_GE              >=
512    T_EQ              ==
513    T_NE              !=
514    T_ANDAND          &&
515    T_OROR            ||
516    T_MPYEQ           *=
517    T_DIVEQ           /=
518    T_MODEQ           %=
519    T_ADDEQ           +=
520    T_SUBEQ           -=
521    T_LSHIFTEQ        <<=
522    T_RSHIFTEQ        >>=
523    T_ANDEQ           &=
524    T_XOREQ           ^=
525    T_OREQ            |=
526    T_TOKCAT          ##
527    T_VARIADIC        ...
528    T_DOTREF          .*    [\fIif\fP PP_PLUSPLUS]
529    T_PTRMEMREF       ->*   [\fIif\fP PP_PLUSPLUS]
530    T_SCOPE           ::    [\fIif\fP PP_PLUSPLUS]
531    T_UMINUS          \fIunary minus\fP
532.EE
533If
534.L ppop(PP_COMPILE)
535was set then the keyword tokens are also defined.
536Compiler differences and dialects are detected by the
537.I pp
538.IR probe (1)
539information, and only the appropriate keywords are enabled.
540The ANSI keyword tokens are:
541.EX
542T_AUTO          T_BREAK          T_CASE           T_CHAR
543T_CONTINUE      T_DEFAULT        T_DO             T_DOUBLE_T
544T_ELSE          T_EXTERN         T_FLOAT_T        T_FOR
545T_GOTO          T_IF             T_INT            T_LONG
546T_REGISTER      T_RETURN         T_SHORT          T_SIZEOF
547T_STATIC        T_STRUCT         T_SWITCH         T_TYPEDEF
548T_UNION         T_UNSIGNED       T_WHILE          T_CONST
549T_ENUM          T_SIGNED         T_VOID           T_VOLATILE
550.EE
551and the C++ keyword tokens are:
552.EX
553T_CATCH         T_CLASS          T_DELETE         T_FRIEND
554T_INLINE        T_NEW            T_OPERATOR       T_OVERLOAD
555T_PRIVATE       T_PROTECTED      T_PUBLIC         T_TEMPLATE
556T_THIS          T_THROW          T_TRY            T_VIRTUAL
557.EE
558In addition,
559.L T_ASM
560is recognized where appropriate.
561Additional keyword tokens
562.L ">= T_KEYWORD"
563may be added using
564.LR ppop(PP_COMPILE) .
565.sp
566Many C implementations show no restraint in adding new keywords; some
567PC compilers have tripled the number of keywords.
568For the most part these new keywords introduce noise constructs that
569can be ignored for standard
570.RI ( reasonable )
571analysis and compilation.
572The noise keywords fall in four syntactic categories that map into the two
573noise keyword tokens
574.L T_NOISE 
575and 
576.LR T_NOISES .
577For
578.L T_NOISES
579.L pp.token
580points to the entire noise construct, including the offending noise keyword.
581The basic noise keyword categories are:
582.RS
583.TP
584.L T_NOISE
585The simplest noise: a single keyword that is noise in any context and maps to
586.LR T_NOISE .
587.TP
588.L T_X_GROUP
589A noise keyword that precedes an optional grouping construct, either
590.L "(..)"
591or
592.L "{..}"
593and maps to
594.LR T_NOISES .
595.TP
596.L T_X_LINE
597A noise keyword that consumes the remaining tokens in the line
598and maps to
599.LR T_NOISES .
600.TP
601.L T_X_STATEMENT
602A noise keyword that consumes the tokens up to the next
603.L ;
604and maps to
605.LR T_NOISES .
606.RE
607.sp
608If
609.L ppop(PP_NOISE)
610is
611.L "> 0"
612then implementation specific noise constructs are mapped to either
613.L T_NOISE
614or
615.L T_NOISES ,
616otherwise if
617.L ppop(PP_NOISE)
618is
619.L "< 0"
620then noise constructs are completely ignored,
621otherwise the unmapped grouping noise tokens
622.L T_X_.*
623are returned.
624.sp
625Token encodings may be tested by the following macros:
626.RS
627.TP
628.L "int isnumber(int token);"
629Non-zero if
630.L token
631is an integral or floating point numeric constant.
632.TP
633.L "int isinteger(int token);"
634Non-zero if
635.L token
636is an integral numeric constant.
637.TP
638.L "int isreal(int token);"
639Non-zero if
640.L token
641is a floating point numeric constant.
642.TP
643.L "int isassignop(int token);"
644Non-zero if
645.L token
646is a C assignment operator.
647.TP
648.L "int isseparate(int token);"
649Non-zero if
650.L token
651must be separated from other tokens by
652.BR space .
653.TP
654.L "int isnoise(int token);"
655Non-zero if
656.L token
657is a noise keyword.
658.RE
659.TP
660.L "extern int ppline(int line, char* file);"
661The default line sync handler that outputs line sync pragmas for the C compiler
662front end.
663May be used as an argument to
664.LR ppop(PP_LINE) ,
665or the user may supply an application specific handler.
666.L line
667is the line number and
668.L file
669is the file name.
670If
671.L ppop(PP_LINEID)
672was set then the directive
673\fB#\fP \fIlineid line \fP"\fIfile\fP" is output.
674.TP
675.L "extern int ppmacref(struct ppsymbol* symbol, char* file, int line, int type);"
676The default macro reference handler that outputs a macro reference pragmas.
677May be used as an argument to
678.LR ppop(PP_MACREF) ,
679or the user may supply an application specific handler.
680.L symbol
681is the macro
682.L ppsymbol
683pointer,
684.L file
685is the reference file,
686.L line
687is the reference line,
688and if
689.L type
690is non-zero a macro value checksum is also output.
691The pragma syntax is
692\fB#pragma pp:macref\fP "\fIsymbol\->name\fP" \fIline checksum\fP.
693.TP
694.L "int ppop(int op, ...)"
695.L ppop
696is the option control interface.
697.L op
698determines the type(s) of the remaining argument(s).
699Options marked by
700.L "/*INIT*/"
701must be done before
702.LR PP_INIT .
703.RS
704.TP
705.L "(PP_ASSERT, char* string) /*INIT*/"
706.L string
707is asserted as if by
708.LR #assert .
709.TP
710.L "(PP_BUILTIN, char*(*fun)(char* buf, char* name, char* args)) /*INIT*/"
711Installs 
712.L fun
713as the unknown builtin macro handler.
714Builtin macros are of the form
715.LR "#(name args)" .
716.L fun 
717is called with
718.L name
719set to the unknown builtin macro name and
720.L args
721set to the arguments.
722.L buf
723is a
724.L MAXTOKEN+1
725buffer that can be used for the
726.L fun
727return value.
728.L 0
729should be returned on error.
730.TP
731.L "(PP_COMMENT,void (*fun)(char*head,char*body,char*tail,int line) /*INIT*/"
732.TP
733.L "(PP_COMPATIBILITY, char* string) /*INIT*/"
734.TP
735.L "(PP_COMPILE, char* string) /*INIT*/"
736.TP
737.L "(PP_DEBUG, char* string) /*INIT*/"
738.TP
739.L "(PP_DEFAULT, char* string) /*INIT*/"
740.TP
741.L "(PP_DEFINE, char* string) /*INIT*/"
742.L string
743is defined as if by
744.LR #define .
745.TP
746.L "(PP_DIRECTIVE, char* string) /*INIT*/"
747The directive
748.BI # string
749is executed.
750.TP
751.L "(PP_DONE, char* string) /*INIT*/"
752.TP
753.L "(PP_DUMP, char* string) /*INIT*/"
754.TP
755.L "(PP_FILEDEPS, char* string) /*INIT*/"
756.TP
757.L "(PP_FILENAME, char* string) /*INIT*/"
758.TP
759.L "(PP_HOSTDIR, char* string) /*INIT*/"
760.TP
761.L "(PP_HOSTED, char* string) /*INIT*/"
762.TP
763.L "(PP_ID, char* string) /*INIT*/"
764.TP
765.L "(PP_IGNORE, char* string) /*INIT*/"
766.TP
767.L "(PP_INCLUDE, char* string) /*INIT*/"
768.TP
769.L "(PP_INCREF, char* string) /*INIT*/"
770.TP
771.L "(PP_INIT, char* string) /*INIT*/"
772.TP
773.L "(PP_INPUT, char* string) /*INIT*/"
774.TP
775.L "(PP_LINE, char* string) /*INIT*/"
776.TP
777.L "(PP_LINEFILE, char* string) /*INIT*/"
778.TP
779.L "(PP_LINEID, char* string) /*INIT*/"
780.TP
781.L "(PP_LINETYPE, char* string) /*INIT*/"
782.TP
783.L "(PP_LOCAL, char* string) /*INIT*/"
784.TP
785.L "(PP_MACREF, char* string) /*INIT*/"
786.TP
787.L "(PP_MULTIPLE, char* string) /*INIT*/"
788.TP
789.L "(PP_NOHASH, char* string) /*INIT*/"
790.TP
791.L "(PP_NOID, char* string) /*INIT*/"
792.TP
793.L "(PP_NOISE, char* string) /*INIT*/"
794.TP
795.L "(PP_OPTION, char* string) /*INIT*/"
796The directive
797\fB#pragma pp:\fP\fIstring\fP
798is executed.
799.TP
800.L "(PP_OPTARG, char* string) /*INIT*/"
801.TP
802.L "(PP_OUTPUT, char* string) /*INIT*/"
803.TP
804.L "(PP_PASSNEWLINE, char* string) /*INIT*/"
805.TP
806.L "(PP_PASSTHROUGH, char* string) /*INIT*/"
807.TP
808.L "(PP_PLUSPLUS, char* string) /*INIT*/"
809.TP
810.L "(PP_PRAGMA, char* string) /*INIT*/"
811.TP
812.L "(PP_PREFIX, char* string) /*INIT*/"
813.TP
814.L "(PP_PROBE, char* string) /*INIT*/"
815.TP
816.L "(PP_READ, char* string) /*INIT*/"
817.TP
818.L "(PP_RESERVED, char* string) /*INIT*/"
819.TP
820.L "(PP_SPACEOUT, char* string) /*INIT*/"
821.TP
822.L "(PP_STANDALONE, char* string) /*INIT*/"
823.TP
824.L "(PP_STANDARD, char* string) /*INIT*/"
825.TP
826.L "(PP_STRICT, char* string) /*INIT*/"
827.TP
828.L "(PP_TEST, char* string) /*INIT*/"
829.TP
830.L "(PP_TRUNCATE, char* string) /*INIT*/"
831.TP
832.L "(PP_UNDEF, char* string) /*INIT*/"
833.TP
834.L "(PP_WARN, char* string) /*INIT*/"
835.RE
836.TP
837.L "int pppragma(char* dir, char* pass, char* name, char* value, int nl);"
838The default handler that
839copies unknown directives and pragmas to the output.
840May be used as an argument to
841.LR ppop(PP_PRAGMA) ,
842or the user may supply an application specific handler.
843This function is most often called after directive and pragma mapping.
844Any of the arguments may be
845.LR 0 .
846.L dir
847is  the directive name,
848.L pass
849is the pragma pass name,
850.L name
851is the pragma option name,
852.L value
853is the pragma option value, and
854.L nl
855is non-zero
856if a trailing newline is required if the pragma is copied to the output.
857.TP
858.L "int ppprintf(char* format, ...);"
859A
860.IR printf (3)
861interface to the standalone
862.I pp
863output buffer.
864Macros provide limited control over output buffering:
865.L "void ppflushout()"
866flushes the output buffer,
867.L "void ppcheckout()"
868flushes the output buffer if over
869.L PPBUFSIZ
870character are buffered,
871.L "int pppendout()"
872returns the number of pending character in the output buffer, and
873.L "void ppputchar(int c)"
874places the character
875.L c
876in the output buffer.
877.SH CAVEATS
878The ANSI mode is intended to be true to the standard.
879The compatibility mode has been proven in practice, but there are
880surely dark corners of some implementations that may have been omitted.
881.SH "SEE ALSO"
882cc(1), cpp(1), nmake(1), probe(1), yacc(1),
883.br
884ast(3), error(3), hash(3), optjoin(3)
885.SH AUTHOR
886Glenn Fowler
887.br
888(Dennis Ritchie provided the original table driven lexer.)
889.br
890AT&T Bell Laboratories
891