1753d2d2eSraf /*
2753d2d2eSraf  * CDDL HEADER START
3753d2d2eSraf  *
4753d2d2eSraf  * The contents of this file are subject to the terms of the
5753d2d2eSraf  * Common Development and Distribution License, Version 1.0 only
6753d2d2eSraf  * (the "License").  You may not use this file except in compliance
7753d2d2eSraf  * with the License.
8753d2d2eSraf  *
9753d2d2eSraf  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10753d2d2eSraf  * or http://www.opensolaris.org/os/licensing.
11753d2d2eSraf  * See the License for the specific language governing permissions
12753d2d2eSraf  * and limitations under the License.
13753d2d2eSraf  *
14753d2d2eSraf  * When distributing Covered Code, include this CDDL HEADER in each
15753d2d2eSraf  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16753d2d2eSraf  * If applicable, add the following below this CDDL HEADER, with the
17753d2d2eSraf  * fields enclosed by brackets "[]" replaced with your own identifying
18753d2d2eSraf  * information: Portions Copyright [yyyy] [name of copyright owner]
19753d2d2eSraf  *
20753d2d2eSraf  * CDDL HEADER END
21753d2d2eSraf  */
22753d2d2eSraf /*
23753d2d2eSraf  * Copyright (c) 1997-2001 by Sun Microsystems, Inc.
24753d2d2eSraf  * All rights reserved.
25753d2d2eSraf  */
26753d2d2eSraf 
27753d2d2eSraf /*
28753d2d2eSraf  *
29753d2d2eSraf  * trace.c -- a  simple translator from spec source to c source for
30753d2d2eSraf  *	a apptrace interposer library.  This file implements the
31753d2d2eSraf  *	(interface to) the front end. Other files implement the middle
32753d2d2eSraf  *	and databases, and generate.c implements the back end.
33753d2d2eSraf  *
34753d2d2eSraf  */
35753d2d2eSraf 
36753d2d2eSraf #include <stdio.h>
37753d2d2eSraf #include <errno.h>
38753d2d2eSraf #include <stdlib.h>
39753d2d2eSraf #include <sys/types.h>
40753d2d2eSraf #include <time.h>
41753d2d2eSraf #include <string.h>
42753d2d2eSraf 
43753d2d2eSraf #include "parser.h"
44753d2d2eSraf #include "trace.h"
45753d2d2eSraf 
46753d2d2eSraf #include "util.h"
47753d2d2eSraf #include "db.h"
48753d2d2eSraf #include "symtab.h"
49753d2d2eSraf #include "io.h"
50753d2d2eSraf #include "printfuncs.h"
51753d2d2eSraf #include "errlog.h"
52753d2d2eSraf #include "parseproto.h"
53753d2d2eSraf 
54753d2d2eSraf static int  Verbose;
55753d2d2eSraf 
56753d2d2eSraf /* File globals. This would be better as a class. */
57753d2d2eSraf /* The first four (commented out) of these enums are defined in parser.h */
58753d2d2eSraf enum {
59753d2d2eSraf 	/* XLATOR_KW_NOTFOUND = 0, */
60753d2d2eSraf 	/* XLATOR_KW_FUNC, */
61753d2d2eSraf 	/* XLATOR_KW_DATA */
62753d2d2eSraf 	/* XLATOR_KW_END */
63753d2d2eSraf 	XLATOR_KW_EXCP = 4,
64753d2d2eSraf 	XLATOR_KW_DECL,
65753d2d2eSraf 	XLATOR_KW_INCL,
66753d2d2eSraf 	XLATOR_KW_ERRNO,
67753d2d2eSraf 	XLATOR_KW_ERRVAL,
68753d2d2eSraf 	XLATOR_KW_ARCH,
69753d2d2eSraf 	XLATOR_KW_WEAK
70753d2d2eSraf };
71753d2d2eSraf #define	FIRST_TOKEN 4	/* Must match the first token in the above enum */
72753d2d2eSraf 
73753d2d2eSraf static xlator_keyword_t Keywords[] = {
74753d2d2eSraf 	{ "exception", XLATOR_KW_EXCP },
75753d2d2eSraf 	{ "declaration", XLATOR_KW_DECL },
76753d2d2eSraf 	{ "include", XLATOR_KW_INCL },
77753d2d2eSraf 	{ "errno", XLATOR_KW_ERRNO },
78753d2d2eSraf 	{ "errval", XLATOR_KW_ERRVAL},
79753d2d2eSraf 	{ "arch", XLATOR_KW_ARCH},
80753d2d2eSraf 	{ "weak", XLATOR_KW_WEAK},
81753d2d2eSraf 	{ "weakfor", XLATOR_KW_WEAK},
82753d2d2eSraf 	{ "alias", XLATOR_KW_WEAK},
83753d2d2eSraf 	{ NULL, XLATOR_KW_NOTFOUND }
84753d2d2eSraf };
85753d2d2eSraf 
86753d2d2eSraf static struct stats_t {
87753d2d2eSraf 	int	libraries,
88753d2d2eSraf 		files,
89753d2d2eSraf 		interfaces,
90753d2d2eSraf 		lines;
91753d2d2eSraf 	int	errors,
92753d2d2eSraf 		warnings,
93753d2d2eSraf 		skips;
94753d2d2eSraf 	time_t	start,
95753d2d2eSraf 		end;
96753d2d2eSraf } Statistics;
97753d2d2eSraf 
98753d2d2eSraf #define	LINE	(m.mi_line_number-(m.mi_nlines-1))
99753d2d2eSraf 
100753d2d2eSraf static void stats_init(void);
101753d2d2eSraf static void stats_report(void);
102753d2d2eSraf 
103753d2d2eSraf static int collect_binding(int const, char *, int);
104753d2d2eSraf static int collect_prototype(char *, int, int);
105753d2d2eSraf static int collect_include(char *, int);
106753d2d2eSraf static int collect_errval(char *, int);
107753d2d2eSraf static int collect_arch(char *);
108753d2d2eSraf 
109753d2d2eSraf static void generate_includes(void);
110753d2d2eSraf static void generate_init(void);
111753d2d2eSraf static void generate_interface(void);
112753d2d2eSraf static void generate_closedown(void);
113753d2d2eSraf static int generate_aux_file();
114753d2d2eSraf 
115753d2d2eSraf /* Local (static) parsing functions. */
116753d2d2eSraf static char *to_actual();
117753d2d2eSraf static int to_basetype(char *);
118753d2d2eSraf static char *de_const(char *);
119753d2d2eSraf static char *strpqcpy(char *, char *, char *);
120753d2d2eSraf 
121753d2d2eSraf /*
122753d2d2eSraf  * xlator_init -- initialize translator, called at startup-time
123753d2d2eSraf  *	with a struct translator_info of information the translator
124753d2d2eSraf  *	might need, returning a list of ``interesting'' spec keywords
125753d2d2eSraf  *	for the front end to select and pass to the back end translator.
126753d2d2eSraf  *
127753d2d2eSraf  */
128753d2d2eSraf xlator_keyword_t *
xlator_init(const Translator_info * t_info)129753d2d2eSraf xlator_init(const Translator_info *t_info)
130753d2d2eSraf {
131753d2d2eSraf 	int	i;
132753d2d2eSraf 
133753d2d2eSraf 	errlog(BEGIN, "xlator_init() {");
134753d2d2eSraf 
135753d2d2eSraf 	/* Save interesting parameters. */
136753d2d2eSraf 	stats_init();
137753d2d2eSraf 	db_set_source_directory(".");
138753d2d2eSraf 	db_set_target_directory(".");
139753d2d2eSraf 	Verbose = t_info->ti_verbosity;
140753d2d2eSraf 	seterrseverity(Verbose); /* Ditto. */
141753d2d2eSraf 	db_set_output_file(t_info->ti_output_file);
142753d2d2eSraf 	db_set_arch(t_info->ti_arch);
143753d2d2eSraf 
144753d2d2eSraf 	/* Display passed argument and return value. */
145753d2d2eSraf 	errlog(VERBOSE, "Keywords[] = {");
146753d2d2eSraf 	for (i = 0; Keywords[i].key != NULL; i++) {
147753d2d2eSraf 		errlog(VERBOSE, "    \"%s\", ", Keywords[i].key);
148753d2d2eSraf 	}
149753d2d2eSraf 	errlog(VERBOSE, "    (char *) NULL");
150753d2d2eSraf 	errlog(VERBOSE, "};");
151753d2d2eSraf 
152753d2d2eSraf 	errlog(END, "}");
153753d2d2eSraf 	return (Keywords);
154753d2d2eSraf }
155753d2d2eSraf 
156753d2d2eSraf /*
157753d2d2eSraf  * xlator_startlib -- called on starting a new library, so back end
158753d2d2eSraf  *	translator can decide to change output file/directory if desired.
159753d2d2eSraf  */
160753d2d2eSraf int
xlator_startlib(char const * libname)161753d2d2eSraf xlator_startlib(char const *libname)
162753d2d2eSraf {
163753d2d2eSraf 	errlog(BEGIN, "xlator_startlib() ");
164753d2d2eSraf 
165753d2d2eSraf 	Statistics.libraries++;
166753d2d2eSraf 	db_set_current_library(libname);
167753d2d2eSraf 	errlog(VERBOSE, "now in library \"%s\"", libname);
168753d2d2eSraf 	errlog(END, "}");
169753d2d2eSraf 	return (SUCCESS_RC);
170753d2d2eSraf }
171753d2d2eSraf 
172753d2d2eSraf /*
173753d2d2eSraf  * xlator_startfile -- ditto, called on starting each new spec file in the
174753d2d2eSraf  *	specified library.
175753d2d2eSraf  */
176753d2d2eSraf int
xlator_startfile(char const * filename)177753d2d2eSraf xlator_startfile(char const *filename)
178753d2d2eSraf {
179753d2d2eSraf 	int	rc = SUCCESS_RC;
180753d2d2eSraf 	char	infile[MAXLINE],
181753d2d2eSraf 		outfile[MAXLINE],
182753d2d2eSraf 		*lib = db_get_current_library();
183753d2d2eSraf 
184753d2d2eSraf 	seterrline(0, filename, "", "");
185753d2d2eSraf 	errlog(BEGIN, "xlator_startfile() {");
186753d2d2eSraf 	Statistics.files++;
187753d2d2eSraf 	db_set_current_file(filename);
188753d2d2eSraf 	errlog(TRACING, "now in file \"%s\" in lib \"%s\"",
189753d2d2eSraf 		filename, lib);
190753d2d2eSraf 
191753d2d2eSraf 	/* Generate filenames. */
192753d2d2eSraf 	(void) snprintf(infile, sizeof (infile), "%s", filename);
193753d2d2eSraf 	(void) snprintf(outfile, sizeof (outfile), "%s.c",
194753d2d2eSraf 		db_get_output_file());
195753d2d2eSraf 
196753d2d2eSraf 	/* Open .c file. */
197753d2d2eSraf 	if (open_code_file() == NO) {
198753d2d2eSraf 		rc = ERROR_RC;
199753d2d2eSraf 	}
200753d2d2eSraf 
201753d2d2eSraf 	generate_init(); /* Write stuff to the c file. */
202753d2d2eSraf 	symtab_clear_includes(); /* Clear out the per-file data. */
203753d2d2eSraf 	errlog(END, "}");
204753d2d2eSraf 	return (rc);
205753d2d2eSraf }
206753d2d2eSraf 
207753d2d2eSraf /*
208753d2d2eSraf  * xlator_start_if -- tritto, called on starting each new
209753d2d2eSraf  *	interface in the spec file.
210753d2d2eSraf  */
211753d2d2eSraf int
xlator_start_if(const Meta_info m,int const token,char * value)212753d2d2eSraf xlator_start_if(const Meta_info m, int const token, char *value)
213753d2d2eSraf {
214753d2d2eSraf 	char ifname[BUFSIZ];
215753d2d2eSraf 	char *kw;
216753d2d2eSraf 
217753d2d2eSraf 	switch (token) {
218753d2d2eSraf 	case XLATOR_KW_FUNC:
219753d2d2eSraf 		kw = "Function";
220753d2d2eSraf 		break;
221753d2d2eSraf 	case XLATOR_KW_DATA:
222753d2d2eSraf 		kw = "Data";
223753d2d2eSraf 		break;
224753d2d2eSraf 	default:
225753d2d2eSraf 		/* This should never happen */
226753d2d2eSraf 		errlog(ERROR,
227753d2d2eSraf 		    "\"%s\", line %d: Implementation error! "
228753d2d2eSraf 		    "Please file a bug\n", __FILE__, __LINE__);
229753d2d2eSraf 		return (XLATOR_FATAL);
230753d2d2eSraf 	}
231753d2d2eSraf 
232753d2d2eSraf 	seterrline(LINE, m.mi_filename, kw, value);
233753d2d2eSraf 	errlog(BEGIN, "xlator_start_if() {");
234753d2d2eSraf 
235753d2d2eSraf /*
236753d2d2eSraf  * XXX Note whether interface is function or data in some state data item.
237753d2d2eSraf  * We'll need it later when writing interceptors.
238753d2d2eSraf  */
239753d2d2eSraf 
240753d2d2eSraf 	Statistics.interfaces++;
241753d2d2eSraf 	(void) strpqcpy(ifname, value, nextsep2(value));
242753d2d2eSraf 	if (*ifname == '\0') {
243753d2d2eSraf 		errlog(INPUT|ERROR|FATAL,
244753d2d2eSraf 		    "missing argument in \"%s\" line", kw);
245753d2d2eSraf 	}
246753d2d2eSraf 	db_set_current_interface(ifname);
247753d2d2eSraf 	errlog(VERBOSE, "interface='%s'", value);
248753d2d2eSraf 	if (token == XLATOR_KW_DATA) {
249753d2d2eSraf 		Statistics.skips++;
250753d2d2eSraf 		errlog(VERBOSE, "telling front end to skip '%s'", value);
251753d2d2eSraf 		errlog(END, "}");
252753d2d2eSraf 		return (SKIP_RC); /* Tell front end to skip it for us. */
253753d2d2eSraf 	}
254753d2d2eSraf 
255753d2d2eSraf 	errlog(TRACING, "now in interface \"%s\"", value);
256753d2d2eSraf 
257753d2d2eSraf 	symtab_new_function(m.mi_line_number, m.mi_filename);
258753d2d2eSraf 		/* Also cleans junk out of symbol table. */
259753d2d2eSraf 	errlog(END, "}");
260753d2d2eSraf 	return (SUCCESS_RC);
261753d2d2eSraf }
262753d2d2eSraf 
263753d2d2eSraf /*
264753d2d2eSraf  * xlator_take_kvpair -- the primary call: collect a datum provide by the
265753d2d2eSraf  *	front-end wrapper.
266753d2d2eSraf  */
267753d2d2eSraf int
xlator_take_kvpair(Meta_info m,int const token,char * value)268753d2d2eSraf xlator_take_kvpair(Meta_info m, int const token, char *value)
269753d2d2eSraf {
270753d2d2eSraf 	int retval;
271753d2d2eSraf 	char *key = Keywords[token-FIRST_TOKEN].key;
272753d2d2eSraf 
273753d2d2eSraf 	int line = LINE; /* TBD */
274753d2d2eSraf 	symtab_set_filename(m.mi_filename);
275753d2d2eSraf 
276753d2d2eSraf 	value = strnormalize(value);
277753d2d2eSraf 
278753d2d2eSraf 	seterrline(line, m.mi_filename, key, value);
279753d2d2eSraf 	errlog(BEGIN, "xlator_take_kvpair() {");
280753d2d2eSraf 	Statistics.lines++;
281753d2d2eSraf 	errlog(VERBOSE, "key='%s', value='%s'",
282753d2d2eSraf 	    (key) ? key : "<nil>",
283753d2d2eSraf 	    (value) ? value : "<nil>");
284753d2d2eSraf 	switch (token) {
285753d2d2eSraf 	case XLATOR_KW_DECL:
286753d2d2eSraf 
287753d2d2eSraf 	/*
288753d2d2eSraf 	 * XXX Check state item to see that it is a function,
289753d2d2eSraf 	 * else do not emit interceptor
290753d2d2eSraf 	 */
291753d2d2eSraf 		symtab_clear_function(); /* Always use last one. */
292753d2d2eSraf 		errlog(END, "}");
293753d2d2eSraf 		retval = collect_prototype(value, line, m.mi_ext_cnt);
294753d2d2eSraf 		break;
295753d2d2eSraf 
296753d2d2eSraf 	case XLATOR_KW_INCL:
297753d2d2eSraf 		errlog(END, "}"); /* Use union of all includes. */
298753d2d2eSraf 		retval = collect_include(value, line);
299753d2d2eSraf 		if (retval == ERROR_RC) {
300753d2d2eSraf 			errlog(FATAL|INPUT, "Bad include line in spec file");
301753d2d2eSraf 		}
302753d2d2eSraf 		break;
303753d2d2eSraf 
304753d2d2eSraf 	case XLATOR_KW_EXCP:
305753d2d2eSraf 		symtab_clear_exception(); /* Always use last. */
306753d2d2eSraf 		retval = collect_binding(token, value, line);
307753d2d2eSraf 		break;
308753d2d2eSraf 
309753d2d2eSraf 	case XLATOR_KW_ERRNO:
310753d2d2eSraf 		symtab_clear_errval(); /* Always use last. */
311753d2d2eSraf 		retval = collect_errval("errno", line);
312753d2d2eSraf 		break;
313753d2d2eSraf 
314753d2d2eSraf 	case XLATOR_KW_ERRVAL:
315753d2d2eSraf 		symtab_clear_errval(); /* Always use last. */
316753d2d2eSraf 		retval =  collect_errval(value, line);
317753d2d2eSraf 		break;
318753d2d2eSraf 
319753d2d2eSraf 	case XLATOR_KW_ARCH:
320753d2d2eSraf 		retval = collect_arch(value);
321753d2d2eSraf 		break;
322753d2d2eSraf 
323753d2d2eSraf 	case XLATOR_KW_WEAK:
324753d2d2eSraf 		if (m.mi_extended == 1) {
325753d2d2eSraf 			errlog(ERROR, "\"%s\", line %d: "
326753d2d2eSraf 			    "Warning: Cannot use extends with a weak "
327753d2d2eSraf 			    "interface",
328753d2d2eSraf 			    m.mi_filename,
329753d2d2eSraf 			    m.mi_line_number);
330753d2d2eSraf 		}
331753d2d2eSraf 		retval = SUCCESS_RC;
332753d2d2eSraf 		break;
333753d2d2eSraf 	default:
334753d2d2eSraf 		retval = ERROR_RC;
335753d2d2eSraf 	}
336753d2d2eSraf 
337753d2d2eSraf 	errlog(END, "}");
338753d2d2eSraf 
339753d2d2eSraf 	return (retval);
340753d2d2eSraf }
341753d2d2eSraf 
342753d2d2eSraf /*
343753d2d2eSraf  * xlator_end_if -- called at the end of the interface, to trigger
344753d2d2eSraf  *	per-interface processing now entire thing has been seen.
345753d2d2eSraf  */
346753d2d2eSraf /*ARGSUSED*/
347753d2d2eSraf int
xlator_end_if(const Meta_info m,char const * value)348753d2d2eSraf xlator_end_if(const Meta_info m, char const *value)
349753d2d2eSraf {
350753d2d2eSraf 	seterrline(LINE, m.mi_filename, "end", value);
351753d2d2eSraf 	errlog(BEGIN, "xlator_end_if() {");
352753d2d2eSraf 	if (symtab_get_skip() == YES) {
353753d2d2eSraf 		symtab_set_skip(NO);
354753d2d2eSraf 		Statistics.skips++;
355753d2d2eSraf 	} else {
356753d2d2eSraf 		generate_interface();
357753d2d2eSraf 	}
358753d2d2eSraf 	errlog(END, "}");
359753d2d2eSraf 	return (SUCCESS_RC);
360753d2d2eSraf }
361753d2d2eSraf 
362753d2d2eSraf /*
363753d2d2eSraf  * xlator_endfile -- called at the end of the file, to trigger per-file
364753d2d2eSraf  * processing.
365753d2d2eSraf  */
366753d2d2eSraf int
xlator_endfile(void)367753d2d2eSraf xlator_endfile(void)
368753d2d2eSraf {
369753d2d2eSraf 	errlog(BEGIN, "xlator_endfile() {");
370753d2d2eSraf 
371753d2d2eSraf 	generate_closedown();
372753d2d2eSraf 	errlog(END, "}");
373753d2d2eSraf 	return ((commit_code_file() == YES)? SUCCESS_RC: ERROR_RC);
374753d2d2eSraf }
375753d2d2eSraf 
376753d2d2eSraf /*
377753d2d2eSraf  * xlator_endlib -- ditto, at the end of the library.
378753d2d2eSraf  */
379753d2d2eSraf int
xlator_endlib(void)380753d2d2eSraf xlator_endlib(void)
381753d2d2eSraf {
382753d2d2eSraf 	errlog(BEGIN, "xlator_endlib() {");
383753d2d2eSraf 	errlog(END, "}");
384753d2d2eSraf 	return (SUCCESS_RC);
385753d2d2eSraf }
386753d2d2eSraf 
387753d2d2eSraf /*
388753d2d2eSraf  * xlator_end -- the end of the processing, called so translator
389753d2d2eSraf  *	can do cleanup, write makefiles, etc.
390753d2d2eSraf  */
391753d2d2eSraf int
xlator_end(void)392753d2d2eSraf xlator_end(void)
393753d2d2eSraf {
394753d2d2eSraf 	int	rc = SUCCESS_RC;
395753d2d2eSraf 
396753d2d2eSraf 	errlog(BEGIN, "xlator_end() {");
397753d2d2eSraf 	rc += !generate_aux_file();
398753d2d2eSraf 	stats_report();
399753d2d2eSraf 	errlog(END, "}");
400753d2d2eSraf 	return (rc);
401753d2d2eSraf }
402753d2d2eSraf 
403753d2d2eSraf 
404753d2d2eSraf /*
405753d2d2eSraf ** utilities for this layer/phase only.
406753d2d2eSraf */
407753d2d2eSraf 
408753d2d2eSraf /*
409753d2d2eSraf  * stats_init -- note what time it is...
410753d2d2eSraf  */
411753d2d2eSraf static void
stats_init(void)412753d2d2eSraf stats_init(void)
413753d2d2eSraf {
414753d2d2eSraf 	Statistics.start = time(NULL);
415753d2d2eSraf }
416753d2d2eSraf 
417753d2d2eSraf /*
418753d2d2eSraf  * stats_report -- say how much we just did
419753d2d2eSraf  */
420753d2d2eSraf #define	max(a, b) (a > b)? a: b
421753d2d2eSraf 
422753d2d2eSraf static void
stats_report(void)423753d2d2eSraf stats_report(void)
424753d2d2eSraf {
425753d2d2eSraf 	double	seconds;
426753d2d2eSraf 
427753d2d2eSraf 	Statistics.end = time(NULL);
428753d2d2eSraf 	seconds = difftime(Statistics.end, Statistics.start);
429753d2d2eSraf 
430753d2d2eSraf 	switch (Verbose) {
431753d2d2eSraf 	default:
432753d2d2eSraf 		/*FALLTHROUGH*/
433753d2d2eSraf 	case 1:
434753d2d2eSraf 		(void) fprintf(stderr, "Statistics:\n"
435753d2d2eSraf 		    "    %d libraries\n    %d files\n"
436753d2d2eSraf 		    "    %d interfaces\n    %d lines\n"
437753d2d2eSraf 		    "    %d errors\n    %d warnings\n"
438753d2d2eSraf 		    "    %d skips\n"
439753d2d2eSraf 		    "in %.0f seconds, at %.1f lines/minute.\n",
440753d2d2eSraf 		    Statistics.libraries, Statistics.files,
441753d2d2eSraf 		    Statistics.interfaces, Statistics.lines,
442753d2d2eSraf 		    Statistics.errors, Statistics.warnings,
443753d2d2eSraf 		    Statistics.skips,
444753d2d2eSraf 		    seconds, Statistics.lines*60.0/seconds);
445753d2d2eSraf 		break;
446753d2d2eSraf 	case 0:
447753d2d2eSraf 		if (Statistics.errors != 0 || Statistics.warnings != 0) {
448753d2d2eSraf 			(void) fprintf(stderr,
449753d2d2eSraf 			    "spec2trace: %d errors %d warnings.\n",
450753d2d2eSraf 			    Statistics.errors, Statistics.warnings);
451753d2d2eSraf 		}
452753d2d2eSraf 		break;
453753d2d2eSraf 	}
454753d2d2eSraf }
455753d2d2eSraf 
456753d2d2eSraf 
457753d2d2eSraf /*
458753d2d2eSraf  * Tiny stats class...
459753d2d2eSraf  */
460753d2d2eSraf void
stats_add_warning(void)461753d2d2eSraf stats_add_warning(void)
462753d2d2eSraf {
463753d2d2eSraf 	Statistics.warnings++;
464753d2d2eSraf }
465753d2d2eSraf 
466753d2d2eSraf void
stats_add_error(void)467753d2d2eSraf stats_add_error(void)
468753d2d2eSraf {
469753d2d2eSraf 	Statistics.errors++;
470753d2d2eSraf }
471753d2d2eSraf 
472753d2d2eSraf /*
473753d2d2eSraf  * collect_includes -- collect a global list of include files,
474753d2d2eSraf  *	converting the comma- or space-separated input list into a
475753d2d2eSraf  *	structure for the database to store.
476753d2d2eSraf  *	As this can cause problems will ill-structured
477753d2d2eSraf  *	files, there is a mechanism to allow exclusion of
478753d2d2eSraf  *	certain files, (or certain combinations).  At
479753d2d2eSraf  *	the moment, the mechanism is TBD, as is the second arg.
480753d2d2eSraf  */
481753d2d2eSraf /*ARGSUSED1*/
482753d2d2eSraf int
collect_include(char * p,int line)483753d2d2eSraf collect_include(char *p, int line)
484753d2d2eSraf {
485753d2d2eSraf 	char	*include;
486753d2d2eSraf 	int	len;
487753d2d2eSraf 
488753d2d2eSraf 	errlog(BEGIN, "collect_include() {");
489753d2d2eSraf 	if ((include = strtok(p, ", ")) != NULL) {
490753d2d2eSraf 		for (; include != NULL; include = strtok(NULL, ", ")) {
491753d2d2eSraf 			include  = skipb(include);
492753d2d2eSraf 
493753d2d2eSraf 			/*
494753d2d2eSraf 			 * Make sure the include file's name
495753d2d2eSraf 			 * has legitimate C syntax - i.e. it's in double
496753d2d2eSraf 			 * quotes or angle brackets.
497753d2d2eSraf 			 */
498753d2d2eSraf 			if (*include != '"' && *include != '<')
499753d2d2eSraf 				return (ERROR_RC);
500753d2d2eSraf 
501753d2d2eSraf 			len = strlen(include);
502753d2d2eSraf 
503753d2d2eSraf 			if (include[len-1] != '"' && include[len-1] != '>')
504753d2d2eSraf 				return (ERROR_RC);
505753d2d2eSraf 
506753d2d2eSraf 			/*
507753d2d2eSraf 			 * If include filename syntax is OK, add it to
508753d2d2eSraf 			 * the list
509753d2d2eSraf 			 */
510753d2d2eSraf 			symtab_add_includes(include);
511753d2d2eSraf 		}
512753d2d2eSraf 	}
513753d2d2eSraf 	errlog(END, "}");
514753d2d2eSraf 	return (SUCCESS_RC);
515753d2d2eSraf }
516753d2d2eSraf 
517753d2d2eSraf /*
518753d2d2eSraf  * collect_binding -- take a binding and stuff it into the database
519753d2d2eSraf  *	in canonical form (with the word return in it).
520753d2d2eSraf  */
521753d2d2eSraf int
collect_binding(int const token,char * value,int line)522753d2d2eSraf collect_binding(int const token, char *value, int line)
523753d2d2eSraf {
524753d2d2eSraf 	char	*file = db_get_current_file();
525753d2d2eSraf 
526753d2d2eSraf 	errlog(BEGIN, "collect_binding() {");
527753d2d2eSraf 	errlog(VERBOSE, "name=\"%s\", value=\"%s\", line=%d\n",
528753d2d2eSraf 	    Keywords[token-FIRST_TOKEN].key, value, line);
529753d2d2eSraf 
530753d2d2eSraf 	if (token == XLATOR_KW_EXCP) {
531753d2d2eSraf 		symtab_set_exception(value, line, file);
532753d2d2eSraf 	} else {
533753d2d2eSraf 		errlog(FATAL|INPUT, "programmer error: impossible binding.");
534753d2d2eSraf 	}
535753d2d2eSraf 	errlog(END, "}");
536753d2d2eSraf 	return (SUCCESS_RC);
537753d2d2eSraf }
538753d2d2eSraf 
539753d2d2eSraf /*
540753d2d2eSraf  * collect_errval -- collect the error variable name (only)
541753d2d2eSraf  *	from the line.  This is expected to be the first
542753d2d2eSraf  *	or only thing in a space- or comma-separated list.
543753d2d2eSraf  *	Collecting errno/errval possible value is left TBD.
544753d2d2eSraf  */
545753d2d2eSraf int
collect_errval(char * p,int line)546753d2d2eSraf collect_errval(char *p, int line)
547753d2d2eSraf {
548753d2d2eSraf 	char	*name;
549753d2d2eSraf 
550753d2d2eSraf 	errlog(BEGIN, "collect_errval() {");
551753d2d2eSraf 	name = strtok(p, " \t\n\r");
552753d2d2eSraf 	symtab_set_errval(name, line, db_get_current_file(), "int", "int", 0);
553753d2d2eSraf 	errlog(END, "}");
554753d2d2eSraf 	return (SUCCESS_RC);
555753d2d2eSraf }
556753d2d2eSraf 
557753d2d2eSraf /*
558753d2d2eSraf  * collect_arch -- collect architecture.
559753d2d2eSraf  */
560753d2d2eSraf int
collect_arch(char * value)561753d2d2eSraf collect_arch(char *value)
562753d2d2eSraf {
563753d2d2eSraf 	char const	*arch = db_get_arch();
564753d2d2eSraf 	char	*buf, *p;
565753d2d2eSraf 	char	*t;
566753d2d2eSraf 
567753d2d2eSraf 	errlog(BEGIN, "collect_arch() {");
568753d2d2eSraf 	if (value == 0 || *value == '\0')
569753d2d2eSraf 		errlog(FATAL|INPUT, "No architectures defined in ARCH line");
570753d2d2eSraf 
571753d2d2eSraf 	if ((buf = strdup(value)) == NULL)
572753d2d2eSraf 		errlog(FATAL, "Could not allocate memory in ARCH directive");
573753d2d2eSraf 
574753d2d2eSraf 	t = buf;
575753d2d2eSraf 	while ((p = strtok(t, " \r\t\n")) != NULL) {
576753d2d2eSraf 		if (strcmp(p, arch) == 0 || strcmp(p, "all") == 0)
577753d2d2eSraf 			goto cleanup;
578753d2d2eSraf 		t = NULL;
579753d2d2eSraf 	}
580753d2d2eSraf 	symtab_set_skip(YES);
581753d2d2eSraf 
582753d2d2eSraf cleanup:
583753d2d2eSraf 	free(buf);
584753d2d2eSraf 	return (SUCCESS_RC);
585753d2d2eSraf }
586753d2d2eSraf 
587753d2d2eSraf /*
588753d2d2eSraf  * de_const -- get rid of const meta-types. This is actually a
589753d2d2eSraf  *	dodge to avoid writing a base-type function early in the
590753d2d2eSraf  *	process. This may turn into to_basetype() or to_primitivetype().
591753d2d2eSraf  */
592753d2d2eSraf static char *
de_const(char * type)593753d2d2eSraf de_const(char *type)
594753d2d2eSraf {
595753d2d2eSraf 	char *p, *q;
596753d2d2eSraf 	int i;
597753d2d2eSraf 
598753d2d2eSraf 	p = skipb(type);
599753d2d2eSraf 
600753d2d2eSraf 	q = strstr(type, "const");
601753d2d2eSraf 	if (q > p) {
602753d2d2eSraf 		for (i = 0; i < 5; i++) {
603753d2d2eSraf 			*q++ = '\0';
604753d2d2eSraf 		}
605753d2d2eSraf 		(void) sprintf(type, "%s%s", strnormalize(p), q);
606753d2d2eSraf 		return (type);
607753d2d2eSraf 	} else if (p == q) {
608753d2d2eSraf 		return (skipb(nextsep(p)));
609753d2d2eSraf 	} else {
610753d2d2eSraf 		return (type);
611753d2d2eSraf 	}
612753d2d2eSraf 
613753d2d2eSraf }
614753d2d2eSraf 
615753d2d2eSraf /*
616753d2d2eSraf  * to_basetype -- convert a C type declaration into its base type and return
617753d2d2eSraf  * 	the number of levels of indirection.
618753d2d2eSraf  *	Destructive and eats ``const''.
619753d2d2eSraf  */
620753d2d2eSraf static int
to_basetype(char * str)621753d2d2eSraf to_basetype(char *str)
622753d2d2eSraf {
623753d2d2eSraf 	char	*p = str,
624753d2d2eSraf 		buffer[MAXLINE+1],
625753d2d2eSraf 		*q = &buffer[0];
626753d2d2eSraf 	int	levels = 0;
627753d2d2eSraf 
628753d2d2eSraf 	assert(strlen(str) < MAXLINE, "string exceeded MAXLINE");
629*07c94cbfSToomas Soome 	buffer[0] = '\0';
630*07c94cbfSToomas Soome 	for (; *p != '\0'; p++) {
631753d2d2eSraf 		switch (*p) {
632753d2d2eSraf 		case ' ': /* Convert spaces to single ' '. */
633753d2d2eSraf 			if (*(q-1) != ' ')
634753d2d2eSraf 				*q++ = ' ';
635753d2d2eSraf 			break;
636753d2d2eSraf 		case '*': /* Convert * to _P. */
637753d2d2eSraf 			if (*(q-1) != ' ')
638753d2d2eSraf 				*q++ = ' ';
639753d2d2eSraf 			levels++;
640753d2d2eSraf 			break;
641753d2d2eSraf 		case 'c': /* This might be a const */
642753d2d2eSraf 			if (strncmp(p, "const", 5) == 0) {
643753d2d2eSraf 				p += 4;
644753d2d2eSraf 			} else {
645753d2d2eSraf 				*q++ = *p;
646753d2d2eSraf 			}
647753d2d2eSraf 			break;
648753d2d2eSraf 		default:
649753d2d2eSraf 			/* Otherwise just copy. */
650753d2d2eSraf 			*q++ = *p;
651753d2d2eSraf 			break;
652753d2d2eSraf 		}
653*07c94cbfSToomas Soome 		*q = '\0';
654753d2d2eSraf 	}
655753d2d2eSraf 	assert(q < &buffer[MAXLINE], "q fell off end of buffer");
656753d2d2eSraf 	q--;
657753d2d2eSraf 	while (*q == ' ') {
658*07c94cbfSToomas Soome 		*q-- = '\0';
659753d2d2eSraf 	}
660753d2d2eSraf 	assert(strlen(buffer) < MAXLINE, "buffer length exceeded MAXLINE");
661753d2d2eSraf 	(void) strcpy(str, buffer);
662753d2d2eSraf 	return (levels);
663753d2d2eSraf }
664753d2d2eSraf 
665753d2d2eSraf /*
666753d2d2eSraf  * to_actual -- create an actual-argument list for use
667753d2d2eSraf  *	when calling the function.
668753d2d2eSraf  */
669753d2d2eSraf static char *
to_actual(void)670753d2d2eSraf to_actual(void)
671753d2d2eSraf {
672753d2d2eSraf 	ENTRY	*p;
673753d2d2eSraf 	static char buffer[MAXLINE+1];
674753d2d2eSraf 	int	n;
675753d2d2eSraf 
676*07c94cbfSToomas Soome 	*buffer = '\0';
677753d2d2eSraf 	if ((p = symtab_get_first_arg()) != NULL) {
678753d2d2eSraf 		n = MAXLINE - snprintf(buffer, MAXLINE, "%s", name_of(p));
679753d2d2eSraf 		for (p = symtab_get_next_arg(); p != NULL;
680753d2d2eSraf 						p = symtab_get_next_arg()) {
681*07c94cbfSToomas Soome 			if (*name_of(p) != '\0')
682753d2d2eSraf 				n -= snprintf(strend(buffer), n,
683753d2d2eSraf 					", %s", name_of(p));
684753d2d2eSraf 		}
685753d2d2eSraf 	}
686753d2d2eSraf 	return (buffer);
687753d2d2eSraf }
688753d2d2eSraf 
689753d2d2eSraf /*
690753d2d2eSraf  * strpqcpy -- string copy that takes whatever begins with p and ends
691753d2d2eSraf  *	just before q.
692753d2d2eSraf  */
693753d2d2eSraf static char *
strpqcpy(char * target,char * p,char * q)694753d2d2eSraf strpqcpy(char *target, char *p, char *q)
695753d2d2eSraf {
696753d2d2eSraf 	char	saved;
697753d2d2eSraf 
698753d2d2eSraf 	saved = *q;
699*07c94cbfSToomas Soome 	*q = '\0';
700753d2d2eSraf 	(void) strcpy(target, p);
701753d2d2eSraf 	*q = saved;
702753d2d2eSraf 	return (target);
703753d2d2eSraf }
704753d2d2eSraf 
705753d2d2eSraf #ifndef lint
706753d2d2eSraf int
breakpoint(void)707753d2d2eSraf breakpoint(void)
708753d2d2eSraf {
709753d2d2eSraf 	return (0);
710753d2d2eSraf }
711753d2d2eSraf #endif
712753d2d2eSraf 
713753d2d2eSraf 
714753d2d2eSraf int
collect_prototype(char * p,int line,int extcnt)715753d2d2eSraf collect_prototype(char *p, int line, int extcnt)
716753d2d2eSraf {
717753d2d2eSraf 	char	f_type[BUFSIZ];	/* The function. */
718753d2d2eSraf 	char	f_basetype[BUFSIZ];
719753d2d2eSraf 	char	f_name[BUFSIZ];
720753d2d2eSraf 	char	a_name[BUFSIZ];	/* The arguments. */
721753d2d2eSraf 	char	a_basetype[BUFSIZ];
722753d2d2eSraf 	char	a_type[BUFSIZ];
723753d2d2eSraf 	char	*file = db_get_current_file();
724753d2d2eSraf 	char	*interface = db_get_current_interface();
725753d2d2eSraf 	char	*q;
726753d2d2eSraf 	char const *parse_err;
727753d2d2eSraf 	char	tmp_proto[BUFSIZ], buf[BUFSIZ];
728753d2d2eSraf 	decl_t	*pp, *funargs;
729753d2d2eSraf 	type_t	*tp;
730753d2d2eSraf 	int	levels, a_levels;
731753d2d2eSraf 
732753d2d2eSraf 	tmp_proto[BUFSIZ-1] = 0;
733753d2d2eSraf 	errlog(BEGIN, "collect_prototype() {");
734753d2d2eSraf 	if (p[strlen(p)-1] != ';')
735753d2d2eSraf 		(void) snprintf(tmp_proto, BUFSIZ, "%s;", p);
736753d2d2eSraf 	else
737753d2d2eSraf 		(void) snprintf(tmp_proto, BUFSIZ, "%s", p);
738753d2d2eSraf 
739753d2d2eSraf 	/* save prototype in symbol table */
740753d2d2eSraf 	symtab_set_prototype(p);
741753d2d2eSraf 
742753d2d2eSraf 	errlog(VERBOSE, "parsing prototype: %s\n", tmp_proto);
743753d2d2eSraf 
744753d2d2eSraf 	/* Parse Prototype */
745753d2d2eSraf 	if ((parse_err = decl_Parse(tmp_proto, &pp)) != NULL) {
746753d2d2eSraf 		errlog(FATAL|INPUT, "bad prototype: %s\n\t%s\n", parse_err, p);
747753d2d2eSraf 	}
748753d2d2eSraf 
749753d2d2eSraf 	if (extcnt == 0) {
750753d2d2eSraf 		char *dname = decl_GetName(pp);
751753d2d2eSraf 		if (strcmp(interface, dname) != 0)
752753d2d2eSraf 			errlog(FATAL|INPUT, "function and declaration"
753753d2d2eSraf 			    " name mismatch\nfunction name = %s,"
754753d2d2eSraf 			    " declaration name = %s\n", interface,
755753d2d2eSraf 			    dname);
756753d2d2eSraf 	}
757753d2d2eSraf 
758753d2d2eSraf 	tp = decl_GetType(pp);
759753d2d2eSraf 
760753d2d2eSraf 	if (type_IsPtrFun(tp)) {
761753d2d2eSraf 		errlog(FATAL|INPUT, "function %s is declared as a data item"
762753d2d2eSraf 		    " (pointer to function)\n", interface);
763753d2d2eSraf 	} else if (!type_IsFunction(tp)) {
764753d2d2eSraf 		errlog(FATAL|INPUT, "function %s is declared as a data item",
765753d2d2eSraf 		    interface);
766753d2d2eSraf 	}
767753d2d2eSraf 
768753d2d2eSraf 	if (type_IsVarargs(tp)) {
769753d2d2eSraf 		symtab_set_skip(YES);
770753d2d2eSraf 		decl_Destroy(pp);
771753d2d2eSraf 		return (SUCCESS_RC);
772753d2d2eSraf 	}
773753d2d2eSraf 
774753d2d2eSraf 	decl_GetTraceInfo(pp, f_type, f_basetype, &funargs);
775753d2d2eSraf 	(void) sprintf(buf, "%s", strnormalize(f_type));
776753d2d2eSraf 	(void) strcpy(f_type, buf);
777753d2d2eSraf 	(void) sprintf(buf, "%s", strnormalize(f_basetype));
778753d2d2eSraf 	(void) strcpy(f_basetype, buf);
779753d2d2eSraf 	levels = to_basetype(f_basetype);
780753d2d2eSraf 
781753d2d2eSraf 	/* get interface name from 'Begin' line */
782753d2d2eSraf 	(void) strpqcpy(f_name, interface, nextsep(interface));
783753d2d2eSraf 	(void) decl_SetName(pp, f_name);
784753d2d2eSraf 
785753d2d2eSraf 	errlog(VERBOSE, "f_name=%s, f_basetype=%s, f_type=%s\n",
786753d2d2eSraf 		f_name, f_basetype, f_type);
787753d2d2eSraf 
788753d2d2eSraf 	symtab_set_function(f_name, line, file, f_type, f_basetype, levels);
789753d2d2eSraf 
790753d2d2eSraf 	db_add_print_types(f_basetype,
791753d2d2eSraf 	    (q = de_const(type_of(symtab_get_function()))));
792753d2d2eSraf 
793753d2d2eSraf 	symtab_add_print_types(f_basetype, q);
794753d2d2eSraf 
795753d2d2eSraf 	/* args list */
796753d2d2eSraf 	while (funargs) {
797753d2d2eSraf 		(void) snprintf(a_type, BUFSIZ, "%s ",
798753d2d2eSraf 			strnormalize(declspec_ToString(buf, funargs->d_ds)));
799753d2d2eSraf 		(void) snprintf(a_basetype, BUFSIZ, "%s",
800753d2d2eSraf 			strnormalize(de_const(declspec_ToString(buf,
801753d2d2eSraf 			funargs->d_ds))));
802753d2d2eSraf 
803753d2d2eSraf 		tp = funargs->d_type;
804753d2d2eSraf 
805753d2d2eSraf 		for (a_levels = 0; tp; ) {
806753d2d2eSraf 			if (tp->t_dt == DD_PTR || tp->t_dt == DD_ARY) {
807753d2d2eSraf 				(void) strcat(a_type, "*");
808753d2d2eSraf 				a_levels++;
809753d2d2eSraf 			}
810753d2d2eSraf 			tp = tp->t_next;
811753d2d2eSraf 		}
812753d2d2eSraf 
813753d2d2eSraf 		/*
814753d2d2eSraf 		 * XXX: This is a hack to work around bug in yacc parser
815753d2d2eSraf 		 *  "int foo(void)" prototypes get interpreted as having 1
816753d2d2eSraf 		 *  argument with the d_name of the argument being NULL.
817753d2d2eSraf 		 */
818753d2d2eSraf 		if (funargs->d_name) {
819753d2d2eSraf 			(void) snprintf(a_name, 20, "%s", funargs->d_name);
820753d2d2eSraf 
821753d2d2eSraf 			errlog(VERBOSE,
822753d2d2eSraf 			    "a_name = %s, a_basetype = %s, a_type = %s\n",
823753d2d2eSraf 			    a_name, a_basetype, a_type);
824753d2d2eSraf 
825753d2d2eSraf 			symtab_add_args(a_name, line, file,
826753d2d2eSraf 			    a_type, a_basetype, a_levels);
827753d2d2eSraf 			db_add_print_types(a_basetype,
828753d2d2eSraf 			    q = de_const(type_of(symtab_get_last_arg())));
829753d2d2eSraf 			symtab_add_print_types(a_basetype, q);
830753d2d2eSraf 		}
831753d2d2eSraf 
832753d2d2eSraf 		funargs = funargs->d_next;
833753d2d2eSraf 	}
834753d2d2eSraf 	symtab_set_formals(decl_ToFormal(pp));
835753d2d2eSraf 	symtab_set_actuals(to_actual());
836753d2d2eSraf 
837753d2d2eSraf 	symtab_set_cast(decl_ToString(buf, DTS_CAST, pp, NULL));
838753d2d2eSraf 
839753d2d2eSraf 	decl_Destroy(pp);
840753d2d2eSraf 
841753d2d2eSraf 	errlog(END, "}");
842753d2d2eSraf 	return (SUCCESS_RC);
843753d2d2eSraf }
844753d2d2eSraf 
845753d2d2eSraf 
846753d2d2eSraf /*
847753d2d2eSraf  * generators
848753d2d2eSraf  */
849753d2d2eSraf 
850753d2d2eSraf /*
851753d2d2eSraf  * generate_init -- prime the code generator as required.
852753d2d2eSraf  */
853753d2d2eSraf static void
generate_init(void)854753d2d2eSraf generate_init(void)
855753d2d2eSraf {
856753d2d2eSraf 	errlog(BEGIN, "generate_init() {");
857753d2d2eSraf 
858753d2d2eSraf 	(void) fprintf(Headfp,
859753d2d2eSraf 	    "/*\n"
860753d2d2eSraf 	    " * Generated by spec2trace %s: do not edit this file.\n */\n\n",
861753d2d2eSraf 	    TRACE_VERSION);
862753d2d2eSraf 
863753d2d2eSraf 	(void) fprintf(Headfp,
864753d2d2eSraf 	    "#ifndef true\n"
865753d2d2eSraf 	    "#define\ttrue 1\n"
866753d2d2eSraf 	    "#define\tfalse 0\n"
867753d2d2eSraf 	    "#endif\n\n"
868753d2d2eSraf 	    "static char const *oparen = \"(\";\n"
869753d2d2eSraf 	    "static char const *retstr = \"  return = \";\n"
870753d2d2eSraf 	    "static char const *errnostr = \" errno = \";\n"
871753d2d2eSraf 	    "static char const *nilstr = \"<nil>\";\n"
872753d2d2eSraf 	    "\n");
873753d2d2eSraf 
874753d2d2eSraf 	errlog(END, "}");
875753d2d2eSraf }
876753d2d2eSraf 
877753d2d2eSraf 
878753d2d2eSraf /*
879753d2d2eSraf  * generate_interface -- call the two main parts of the per-interface
880753d2d2eSraf  *	code generation.
881753d2d2eSraf  */
882753d2d2eSraf static void
generate_interface(void)883753d2d2eSraf generate_interface(void)
884753d2d2eSraf {
885753d2d2eSraf 	ENTRY	*function = symtab_get_function();
886753d2d2eSraf 
887753d2d2eSraf 	errlog(BEGIN, "generate_interface() {");
888753d2d2eSraf 	/* Check for required information. */
889753d2d2eSraf 	if (validity_of(function) == NO) {
890753d2d2eSraf 		symtab_set_skip(YES);
891753d2d2eSraf 		errlog(WARNING|INPUT, "no prototype for interface "
892753d2d2eSraf 			"it will be skipped");
893753d2d2eSraf 		errlog(END, "}");
894753d2d2eSraf 		return;
895753d2d2eSraf 	}
896753d2d2eSraf 
897753d2d2eSraf 	/* Generate the current interface 's print-functions declarations. */
898753d2d2eSraf 	generate_print_declarations(Bodyfp);
899753d2d2eSraf 
900753d2d2eSraf 	/* Generate the linkage part (a function and a struct */
901753d2d2eSraf 	generate_linkage(function);
902753d2d2eSraf 
903753d2d2eSraf 	/* Generate the actual interceptor. */
904753d2d2eSraf 	generate_interceptor(function);
905753d2d2eSraf 	errlog(END, "}");
906753d2d2eSraf }
907753d2d2eSraf 
908753d2d2eSraf 
909753d2d2eSraf /*
910753d2d2eSraf  * generate_closedown -- produce includes.
911753d2d2eSraf  */
912753d2d2eSraf static void
generate_closedown(void)913753d2d2eSraf generate_closedown(void)
914753d2d2eSraf {
915753d2d2eSraf 	errlog(BEGIN, "generate_closedown() {");
916753d2d2eSraf 
917753d2d2eSraf 	/* Print includes to primary file. */
918753d2d2eSraf 	generate_includes();
919753d2d2eSraf 	(void) putc('\n', Headfp);
920753d2d2eSraf 	errlog(END, "}");
921753d2d2eSraf }
922753d2d2eSraf 
923753d2d2eSraf /*
924753d2d2eSraf  * generate_aux_file -- generate one additional .pf file with
925753d2d2eSraf  *	print-function pointers.
926753d2d2eSraf  */
927753d2d2eSraf static int
generate_aux_file(void)928753d2d2eSraf generate_aux_file(void)
929753d2d2eSraf {
930753d2d2eSraf 	FILE	*fp;
931753d2d2eSraf 	char	pathname[MAXLINE];
932753d2d2eSraf 
933753d2d2eSraf 	errlog(BEGIN, "generate_aux_file() {");
934753d2d2eSraf 	/* Open file */
935753d2d2eSraf 	(void) snprintf(pathname, sizeof (pathname), "%s.pf",
936753d2d2eSraf 		db_get_output_file());
937753d2d2eSraf 	errlog(TRACING,  "output file = '%s'", pathname);
938753d2d2eSraf 	if ((fp = fopen(pathname, "w")) == NULL) {
939753d2d2eSraf 		errlog(FATAL, "%s: %s", pathname, strerror(errno));
940753d2d2eSraf 	}
941753d2d2eSraf 
942753d2d2eSraf 	/*
943753d2d2eSraf 	 * Declare and initialize all print function pointers to null.
944753d2d2eSraf 	 * Some spec files result in nothing being put into the .pf
945753d2d2eSraf 	 * file.  We must create the file since make(1) does not cope
946753d2d2eSraf 	 * well with absent files that it expects to have built.  So
947753d2d2eSraf 	 * now the build gets empty compilation unit warnings...  So
948753d2d2eSraf 	 * we unconditionally create a static pointer.
949753d2d2eSraf 	 */
950753d2d2eSraf 	(void) fprintf(fp,
951753d2d2eSraf 	    "/* Do not edit this file: it is a generated one. */\n\n"
952753d2d2eSraf 	    "static char const *__abi_place_holder;\n\n");
953753d2d2eSraf 
954753d2d2eSraf 	generate_print_definitions(fp);
955753d2d2eSraf 
956753d2d2eSraf 	/* Close file */
957753d2d2eSraf 	if (fclose(fp) != 0) {
958753d2d2eSraf 		errlog(FATAL, "fclose %s: %s", pathname, strerror(errno));
959753d2d2eSraf 	}
960753d2d2eSraf 	errlog(END, "}");
961753d2d2eSraf 	return (YES);
962753d2d2eSraf }
963753d2d2eSraf 
964753d2d2eSraf 
965753d2d2eSraf 
966753d2d2eSraf /*
967753d2d2eSraf  * generate_includes -- generate #includes to Headfp
968753d2d2eSraf  */
969753d2d2eSraf static void
generate_includes(void)970753d2d2eSraf generate_includes(void)
971753d2d2eSraf {
972753d2d2eSraf 	char	*include;
973753d2d2eSraf 
974753d2d2eSraf 	errlog(BEGIN, "generate_includes() {");
975753d2d2eSraf 	errlog(TRACING,  "includes=");
976753d2d2eSraf 	for (include = symtab_get_first_include(); include != NULL;
977753d2d2eSraf 	    include = symtab_get_next_include())
978753d2d2eSraf 		(void) fprintf(Headfp, "#include %s\n", include);
979753d2d2eSraf 
980753d2d2eSraf 	(void) fprintf(Headfp, "\n#include <stdio.h>\n"
981753d2d2eSraf 	    "#include <dlfcn.h>\n"
982753d2d2eSraf 	    "#include <apptrace.h>\n\n");
983753d2d2eSraf 
984753d2d2eSraf 	errlog(TRACING,  "\n");
985753d2d2eSraf 	errlog(END, "}");
986753d2d2eSraf }
987