1*753d2d2eSraf /*
2*753d2d2eSraf * CDDL HEADER START
3*753d2d2eSraf *
4*753d2d2eSraf * The contents of this file are subject to the terms of the
5*753d2d2eSraf * Common Development and Distribution License, Version 1.0 only
6*753d2d2eSraf * (the "License"). You may not use this file except in compliance
7*753d2d2eSraf * with the License.
8*753d2d2eSraf *
9*753d2d2eSraf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*753d2d2eSraf * or http://www.opensolaris.org/os/licensing.
11*753d2d2eSraf * See the License for the specific language governing permissions
12*753d2d2eSraf * and limitations under the License.
13*753d2d2eSraf *
14*753d2d2eSraf * When distributing Covered Code, include this CDDL HEADER in each
15*753d2d2eSraf * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*753d2d2eSraf * If applicable, add the following below this CDDL HEADER, with the
17*753d2d2eSraf * fields enclosed by brackets "[]" replaced with your own identifying
18*753d2d2eSraf * information: Portions Copyright [yyyy] [name of copyright owner]
19*753d2d2eSraf *
20*753d2d2eSraf * CDDL HEADER END
21*753d2d2eSraf */
22*753d2d2eSraf /*
23*753d2d2eSraf * Copyright (c) 1997-2001 by Sun Microsystems, Inc.
24*753d2d2eSraf * All rights reserved.
25*753d2d2eSraf */
26*753d2d2eSraf
27*753d2d2eSraf #pragma ident "%Z%%M% %I% %E% SMI"
28*753d2d2eSraf
29*753d2d2eSraf /*
30*753d2d2eSraf *
31*753d2d2eSraf * trace.c -- a simple translator from spec source to c source for
32*753d2d2eSraf * a apptrace interposer library. This file implements the
33*753d2d2eSraf * (interface to) the front end. Other files implement the middle
34*753d2d2eSraf * and databases, and generate.c implements the back end.
35*753d2d2eSraf *
36*753d2d2eSraf */
37*753d2d2eSraf
38*753d2d2eSraf #include <stdio.h>
39*753d2d2eSraf #include <errno.h>
40*753d2d2eSraf #include <stdlib.h>
41*753d2d2eSraf #include <sys/types.h>
42*753d2d2eSraf #include <time.h>
43*753d2d2eSraf #include <string.h>
44*753d2d2eSraf
45*753d2d2eSraf #include "parser.h"
46*753d2d2eSraf #include "trace.h"
47*753d2d2eSraf
48*753d2d2eSraf #include "util.h"
49*753d2d2eSraf #include "db.h"
50*753d2d2eSraf #include "symtab.h"
51*753d2d2eSraf #include "io.h"
52*753d2d2eSraf #include "printfuncs.h"
53*753d2d2eSraf #include "errlog.h"
54*753d2d2eSraf #include "parseproto.h"
55*753d2d2eSraf
56*753d2d2eSraf static int Verbose;
57*753d2d2eSraf
58*753d2d2eSraf /* File globals. This would be better as a class. */
59*753d2d2eSraf /* The first four (commented out) of these enums are defined in parser.h */
60*753d2d2eSraf enum {
61*753d2d2eSraf /* XLATOR_KW_NOTFOUND = 0, */
62*753d2d2eSraf /* XLATOR_KW_FUNC, */
63*753d2d2eSraf /* XLATOR_KW_DATA */
64*753d2d2eSraf /* XLATOR_KW_END */
65*753d2d2eSraf XLATOR_KW_EXCP = 4,
66*753d2d2eSraf XLATOR_KW_DECL,
67*753d2d2eSraf XLATOR_KW_INCL,
68*753d2d2eSraf XLATOR_KW_ERRNO,
69*753d2d2eSraf XLATOR_KW_ERRVAL,
70*753d2d2eSraf XLATOR_KW_ARCH,
71*753d2d2eSraf XLATOR_KW_WEAK
72*753d2d2eSraf };
73*753d2d2eSraf #define FIRST_TOKEN 4 /* Must match the first token in the above enum */
74*753d2d2eSraf
75*753d2d2eSraf static xlator_keyword_t Keywords[] = {
76*753d2d2eSraf { "exception", XLATOR_KW_EXCP },
77*753d2d2eSraf { "declaration", XLATOR_KW_DECL },
78*753d2d2eSraf { "include", XLATOR_KW_INCL },
79*753d2d2eSraf { "errno", XLATOR_KW_ERRNO },
80*753d2d2eSraf { "errval", XLATOR_KW_ERRVAL},
81*753d2d2eSraf { "arch", XLATOR_KW_ARCH},
82*753d2d2eSraf { "weak", XLATOR_KW_WEAK},
83*753d2d2eSraf { "weakfor", XLATOR_KW_WEAK},
84*753d2d2eSraf { "alias", XLATOR_KW_WEAK},
85*753d2d2eSraf { NULL, XLATOR_KW_NOTFOUND }
86*753d2d2eSraf };
87*753d2d2eSraf
88*753d2d2eSraf static struct stats_t {
89*753d2d2eSraf int libraries,
90*753d2d2eSraf files,
91*753d2d2eSraf interfaces,
92*753d2d2eSraf lines;
93*753d2d2eSraf int errors,
94*753d2d2eSraf warnings,
95*753d2d2eSraf skips;
96*753d2d2eSraf time_t start,
97*753d2d2eSraf end;
98*753d2d2eSraf } Statistics;
99*753d2d2eSraf
100*753d2d2eSraf #define LINE (m.mi_line_number-(m.mi_nlines-1))
101*753d2d2eSraf
102*753d2d2eSraf static void stats_init(void);
103*753d2d2eSraf static void stats_report(void);
104*753d2d2eSraf
105*753d2d2eSraf static int collect_binding(int const, char *, int);
106*753d2d2eSraf static int collect_prototype(char *, int, int);
107*753d2d2eSraf static int collect_include(char *, int);
108*753d2d2eSraf static int collect_errval(char *, int);
109*753d2d2eSraf static int collect_arch(char *);
110*753d2d2eSraf
111*753d2d2eSraf static void generate_includes(void);
112*753d2d2eSraf static void generate_init(void);
113*753d2d2eSraf static void generate_interface(void);
114*753d2d2eSraf static void generate_closedown(void);
115*753d2d2eSraf static int generate_aux_file();
116*753d2d2eSraf
117*753d2d2eSraf /* Local (static) parsing functions. */
118*753d2d2eSraf static char *to_actual();
119*753d2d2eSraf static int to_basetype(char *);
120*753d2d2eSraf static char *de_const(char *);
121*753d2d2eSraf static char *strpqcpy(char *, char *, char *);
122*753d2d2eSraf
123*753d2d2eSraf /*
124*753d2d2eSraf * xlator_init -- initialize translator, called at startup-time
125*753d2d2eSraf * with a struct translator_info of information the translator
126*753d2d2eSraf * might need, returning a list of ``interesting'' spec keywords
127*753d2d2eSraf * for the front end to select and pass to the back end translator.
128*753d2d2eSraf *
129*753d2d2eSraf */
130*753d2d2eSraf xlator_keyword_t *
xlator_init(const Translator_info * t_info)131*753d2d2eSraf xlator_init(const Translator_info *t_info)
132*753d2d2eSraf {
133*753d2d2eSraf int i;
134*753d2d2eSraf
135*753d2d2eSraf errlog(BEGIN, "xlator_init() {");
136*753d2d2eSraf
137*753d2d2eSraf /* Save interesting parameters. */
138*753d2d2eSraf stats_init();
139*753d2d2eSraf db_set_source_directory(".");
140*753d2d2eSraf db_set_target_directory(".");
141*753d2d2eSraf Verbose = t_info->ti_verbosity;
142*753d2d2eSraf seterrseverity(Verbose); /* Ditto. */
143*753d2d2eSraf db_set_output_file(t_info->ti_output_file);
144*753d2d2eSraf db_set_arch(t_info->ti_arch);
145*753d2d2eSraf
146*753d2d2eSraf /* Display passed argument and return value. */
147*753d2d2eSraf errlog(VERBOSE, "Keywords[] = {");
148*753d2d2eSraf for (i = 0; Keywords[i].key != NULL; i++) {
149*753d2d2eSraf errlog(VERBOSE, " \"%s\", ", Keywords[i].key);
150*753d2d2eSraf }
151*753d2d2eSraf errlog(VERBOSE, " (char *) NULL");
152*753d2d2eSraf errlog(VERBOSE, "};");
153*753d2d2eSraf
154*753d2d2eSraf errlog(END, "}");
155*753d2d2eSraf return (Keywords);
156*753d2d2eSraf }
157*753d2d2eSraf
158*753d2d2eSraf /*
159*753d2d2eSraf * xlator_startlib -- called on starting a new library, so back end
160*753d2d2eSraf * translator can decide to change output file/directory if desired.
161*753d2d2eSraf */
162*753d2d2eSraf int
xlator_startlib(char const * libname)163*753d2d2eSraf xlator_startlib(char const *libname)
164*753d2d2eSraf {
165*753d2d2eSraf errlog(BEGIN, "xlator_startlib() ");
166*753d2d2eSraf
167*753d2d2eSraf Statistics.libraries++;
168*753d2d2eSraf db_set_current_library(libname);
169*753d2d2eSraf errlog(VERBOSE, "now in library \"%s\"", libname);
170*753d2d2eSraf errlog(END, "}");
171*753d2d2eSraf return (SUCCESS_RC);
172*753d2d2eSraf }
173*753d2d2eSraf
174*753d2d2eSraf /*
175*753d2d2eSraf * xlator_startfile -- ditto, called on starting each new spec file in the
176*753d2d2eSraf * specified library.
177*753d2d2eSraf */
178*753d2d2eSraf int
xlator_startfile(char const * filename)179*753d2d2eSraf xlator_startfile(char const *filename)
180*753d2d2eSraf {
181*753d2d2eSraf int rc = SUCCESS_RC;
182*753d2d2eSraf char infile[MAXLINE],
183*753d2d2eSraf outfile[MAXLINE],
184*753d2d2eSraf *lib = db_get_current_library();
185*753d2d2eSraf
186*753d2d2eSraf seterrline(0, filename, "", "");
187*753d2d2eSraf errlog(BEGIN, "xlator_startfile() {");
188*753d2d2eSraf Statistics.files++;
189*753d2d2eSraf db_set_current_file(filename);
190*753d2d2eSraf errlog(TRACING, "now in file \"%s\" in lib \"%s\"",
191*753d2d2eSraf filename, lib);
192*753d2d2eSraf
193*753d2d2eSraf /* Generate filenames. */
194*753d2d2eSraf (void) snprintf(infile, sizeof (infile), "%s", filename);
195*753d2d2eSraf (void) snprintf(outfile, sizeof (outfile), "%s.c",
196*753d2d2eSraf db_get_output_file());
197*753d2d2eSraf
198*753d2d2eSraf /* Open .c file. */
199*753d2d2eSraf if (open_code_file() == NO) {
200*753d2d2eSraf rc = ERROR_RC;
201*753d2d2eSraf }
202*753d2d2eSraf
203*753d2d2eSraf generate_init(); /* Write stuff to the c file. */
204*753d2d2eSraf symtab_clear_includes(); /* Clear out the per-file data. */
205*753d2d2eSraf errlog(END, "}");
206*753d2d2eSraf return (rc);
207*753d2d2eSraf }
208*753d2d2eSraf
209*753d2d2eSraf /*
210*753d2d2eSraf * xlator_start_if -- tritto, called on starting each new
211*753d2d2eSraf * interface in the spec file.
212*753d2d2eSraf */
213*753d2d2eSraf int
xlator_start_if(const Meta_info m,int const token,char * value)214*753d2d2eSraf xlator_start_if(const Meta_info m, int const token, char *value)
215*753d2d2eSraf {
216*753d2d2eSraf char ifname[BUFSIZ];
217*753d2d2eSraf char *kw;
218*753d2d2eSraf
219*753d2d2eSraf switch (token) {
220*753d2d2eSraf case XLATOR_KW_FUNC:
221*753d2d2eSraf kw = "Function";
222*753d2d2eSraf break;
223*753d2d2eSraf case XLATOR_KW_DATA:
224*753d2d2eSraf kw = "Data";
225*753d2d2eSraf break;
226*753d2d2eSraf default:
227*753d2d2eSraf /* This should never happen */
228*753d2d2eSraf errlog(ERROR,
229*753d2d2eSraf "\"%s\", line %d: Implementation error! "
230*753d2d2eSraf "Please file a bug\n", __FILE__, __LINE__);
231*753d2d2eSraf return (XLATOR_FATAL);
232*753d2d2eSraf }
233*753d2d2eSraf
234*753d2d2eSraf seterrline(LINE, m.mi_filename, kw, value);
235*753d2d2eSraf errlog(BEGIN, "xlator_start_if() {");
236*753d2d2eSraf
237*753d2d2eSraf /*
238*753d2d2eSraf * XXX Note whether interface is function or data in some state data item.
239*753d2d2eSraf * We'll need it later when writing interceptors.
240*753d2d2eSraf */
241*753d2d2eSraf
242*753d2d2eSraf Statistics.interfaces++;
243*753d2d2eSraf (void) strpqcpy(ifname, value, nextsep2(value));
244*753d2d2eSraf if (*ifname == '\0') {
245*753d2d2eSraf errlog(INPUT|ERROR|FATAL,
246*753d2d2eSraf "missing argument in \"%s\" line", kw);
247*753d2d2eSraf }
248*753d2d2eSraf db_set_current_interface(ifname);
249*753d2d2eSraf errlog(VERBOSE, "interface='%s'", value);
250*753d2d2eSraf if (token == XLATOR_KW_DATA) {
251*753d2d2eSraf Statistics.skips++;
252*753d2d2eSraf errlog(VERBOSE, "telling front end to skip '%s'", value);
253*753d2d2eSraf errlog(END, "}");
254*753d2d2eSraf return (SKIP_RC); /* Tell front end to skip it for us. */
255*753d2d2eSraf }
256*753d2d2eSraf
257*753d2d2eSraf errlog(TRACING, "now in interface \"%s\"", value);
258*753d2d2eSraf
259*753d2d2eSraf symtab_new_function(m.mi_line_number, m.mi_filename);
260*753d2d2eSraf /* Also cleans junk out of symbol table. */
261*753d2d2eSraf errlog(END, "}");
262*753d2d2eSraf return (SUCCESS_RC);
263*753d2d2eSraf }
264*753d2d2eSraf
265*753d2d2eSraf /*
266*753d2d2eSraf * xlator_take_kvpair -- the primary call: collect a datum provide by the
267*753d2d2eSraf * front-end wrapper.
268*753d2d2eSraf */
269*753d2d2eSraf int
xlator_take_kvpair(Meta_info m,int const token,char * value)270*753d2d2eSraf xlator_take_kvpair(Meta_info m, int const token, char *value)
271*753d2d2eSraf {
272*753d2d2eSraf int retval;
273*753d2d2eSraf char *key = Keywords[token-FIRST_TOKEN].key;
274*753d2d2eSraf
275*753d2d2eSraf int line = LINE; /* TBD */
276*753d2d2eSraf symtab_set_filename(m.mi_filename);
277*753d2d2eSraf
278*753d2d2eSraf value = strnormalize(value);
279*753d2d2eSraf
280*753d2d2eSraf seterrline(line, m.mi_filename, key, value);
281*753d2d2eSraf errlog(BEGIN, "xlator_take_kvpair() {");
282*753d2d2eSraf Statistics.lines++;
283*753d2d2eSraf errlog(VERBOSE, "key='%s', value='%s'",
284*753d2d2eSraf (key) ? key : "<nil>",
285*753d2d2eSraf (value) ? value : "<nil>");
286*753d2d2eSraf switch (token) {
287*753d2d2eSraf case XLATOR_KW_DECL:
288*753d2d2eSraf
289*753d2d2eSraf /*
290*753d2d2eSraf * XXX Check state item to see that it is a function,
291*753d2d2eSraf * else do not emit interceptor
292*753d2d2eSraf */
293*753d2d2eSraf symtab_clear_function(); /* Always use last one. */
294*753d2d2eSraf errlog(END, "}");
295*753d2d2eSraf retval = collect_prototype(value, line, m.mi_ext_cnt);
296*753d2d2eSraf break;
297*753d2d2eSraf
298*753d2d2eSraf case XLATOR_KW_INCL:
299*753d2d2eSraf errlog(END, "}"); /* Use union of all includes. */
300*753d2d2eSraf retval = collect_include(value, line);
301*753d2d2eSraf if (retval == ERROR_RC) {
302*753d2d2eSraf errlog(FATAL|INPUT, "Bad include line in spec file");
303*753d2d2eSraf }
304*753d2d2eSraf break;
305*753d2d2eSraf
306*753d2d2eSraf case XLATOR_KW_EXCP:
307*753d2d2eSraf symtab_clear_exception(); /* Always use last. */
308*753d2d2eSraf retval = collect_binding(token, value, line);
309*753d2d2eSraf break;
310*753d2d2eSraf
311*753d2d2eSraf case XLATOR_KW_ERRNO:
312*753d2d2eSraf symtab_clear_errval(); /* Always use last. */
313*753d2d2eSraf retval = collect_errval("errno", line);
314*753d2d2eSraf break;
315*753d2d2eSraf
316*753d2d2eSraf case XLATOR_KW_ERRVAL:
317*753d2d2eSraf symtab_clear_errval(); /* Always use last. */
318*753d2d2eSraf retval = collect_errval(value, line);
319*753d2d2eSraf break;
320*753d2d2eSraf
321*753d2d2eSraf case XLATOR_KW_ARCH:
322*753d2d2eSraf retval = collect_arch(value);
323*753d2d2eSraf break;
324*753d2d2eSraf
325*753d2d2eSraf case XLATOR_KW_WEAK:
326*753d2d2eSraf if (m.mi_extended == 1) {
327*753d2d2eSraf errlog(ERROR, "\"%s\", line %d: "
328*753d2d2eSraf "Warning: Cannot use extends with a weak "
329*753d2d2eSraf "interface",
330*753d2d2eSraf m.mi_filename,
331*753d2d2eSraf m.mi_line_number);
332*753d2d2eSraf }
333*753d2d2eSraf retval = SUCCESS_RC;
334*753d2d2eSraf break;
335*753d2d2eSraf default:
336*753d2d2eSraf retval = ERROR_RC;
337*753d2d2eSraf }
338*753d2d2eSraf
339*753d2d2eSraf errlog(END, "}");
340*753d2d2eSraf
341*753d2d2eSraf return (retval);
342*753d2d2eSraf }
343*753d2d2eSraf
344*753d2d2eSraf /*
345*753d2d2eSraf * xlator_end_if -- called at the end of the interface, to trigger
346*753d2d2eSraf * per-interface processing now entire thing has been seen.
347*753d2d2eSraf */
348*753d2d2eSraf /*ARGSUSED*/
349*753d2d2eSraf int
xlator_end_if(const Meta_info m,char const * value)350*753d2d2eSraf xlator_end_if(const Meta_info m, char const *value)
351*753d2d2eSraf {
352*753d2d2eSraf seterrline(LINE, m.mi_filename, "end", value);
353*753d2d2eSraf errlog(BEGIN, "xlator_end_if() {");
354*753d2d2eSraf if (symtab_get_skip() == YES) {
355*753d2d2eSraf symtab_set_skip(NO);
356*753d2d2eSraf Statistics.skips++;
357*753d2d2eSraf } else {
358*753d2d2eSraf generate_interface();
359*753d2d2eSraf }
360*753d2d2eSraf errlog(END, "}");
361*753d2d2eSraf return (SUCCESS_RC);
362*753d2d2eSraf }
363*753d2d2eSraf
364*753d2d2eSraf /*
365*753d2d2eSraf * xlator_endfile -- called at the end of the file, to trigger per-file
366*753d2d2eSraf * processing.
367*753d2d2eSraf */
368*753d2d2eSraf int
xlator_endfile(void)369*753d2d2eSraf xlator_endfile(void)
370*753d2d2eSraf {
371*753d2d2eSraf errlog(BEGIN, "xlator_endfile() {");
372*753d2d2eSraf
373*753d2d2eSraf generate_closedown();
374*753d2d2eSraf errlog(END, "}");
375*753d2d2eSraf return ((commit_code_file() == YES)? SUCCESS_RC: ERROR_RC);
376*753d2d2eSraf }
377*753d2d2eSraf
378*753d2d2eSraf /*
379*753d2d2eSraf * xlator_endlib -- ditto, at the end of the library.
380*753d2d2eSraf */
381*753d2d2eSraf int
xlator_endlib(void)382*753d2d2eSraf xlator_endlib(void)
383*753d2d2eSraf {
384*753d2d2eSraf errlog(BEGIN, "xlator_endlib() {");
385*753d2d2eSraf errlog(END, "}");
386*753d2d2eSraf return (SUCCESS_RC);
387*753d2d2eSraf }
388*753d2d2eSraf
389*753d2d2eSraf /*
390*753d2d2eSraf * xlator_end -- the end of the processing, called so translator
391*753d2d2eSraf * can do cleanup, write makefiles, etc.
392*753d2d2eSraf */
393*753d2d2eSraf int
xlator_end(void)394*753d2d2eSraf xlator_end(void)
395*753d2d2eSraf {
396*753d2d2eSraf int rc = SUCCESS_RC;
397*753d2d2eSraf
398*753d2d2eSraf errlog(BEGIN, "xlator_end() {");
399*753d2d2eSraf rc += !generate_aux_file();
400*753d2d2eSraf stats_report();
401*753d2d2eSraf errlog(END, "}");
402*753d2d2eSraf return (rc);
403*753d2d2eSraf }
404*753d2d2eSraf
405*753d2d2eSraf
406*753d2d2eSraf /*
407*753d2d2eSraf ** utilities for this layer/phase only.
408*753d2d2eSraf */
409*753d2d2eSraf
410*753d2d2eSraf /*
411*753d2d2eSraf * stats_init -- note what time it is...
412*753d2d2eSraf */
413*753d2d2eSraf static void
stats_init(void)414*753d2d2eSraf stats_init(void)
415*753d2d2eSraf {
416*753d2d2eSraf Statistics.start = time(NULL);
417*753d2d2eSraf }
418*753d2d2eSraf
419*753d2d2eSraf /*
420*753d2d2eSraf * stats_report -- say how much we just did
421*753d2d2eSraf */
422*753d2d2eSraf #define max(a, b) (a > b)? a: b
423*753d2d2eSraf
424*753d2d2eSraf static void
stats_report(void)425*753d2d2eSraf stats_report(void)
426*753d2d2eSraf {
427*753d2d2eSraf double seconds;
428*753d2d2eSraf
429*753d2d2eSraf Statistics.end = time(NULL);
430*753d2d2eSraf seconds = difftime(Statistics.end, Statistics.start);
431*753d2d2eSraf
432*753d2d2eSraf switch (Verbose) {
433*753d2d2eSraf default:
434*753d2d2eSraf /*FALLTHROUGH*/
435*753d2d2eSraf case 1:
436*753d2d2eSraf (void) fprintf(stderr, "Statistics:\n"
437*753d2d2eSraf " %d libraries\n %d files\n"
438*753d2d2eSraf " %d interfaces\n %d lines\n"
439*753d2d2eSraf " %d errors\n %d warnings\n"
440*753d2d2eSraf " %d skips\n"
441*753d2d2eSraf "in %.0f seconds, at %.1f lines/minute.\n",
442*753d2d2eSraf Statistics.libraries, Statistics.files,
443*753d2d2eSraf Statistics.interfaces, Statistics.lines,
444*753d2d2eSraf Statistics.errors, Statistics.warnings,
445*753d2d2eSraf Statistics.skips,
446*753d2d2eSraf seconds, Statistics.lines*60.0/seconds);
447*753d2d2eSraf break;
448*753d2d2eSraf case 0:
449*753d2d2eSraf if (Statistics.errors != 0 || Statistics.warnings != 0) {
450*753d2d2eSraf (void) fprintf(stderr,
451*753d2d2eSraf "spec2trace: %d errors %d warnings.\n",
452*753d2d2eSraf Statistics.errors, Statistics.warnings);
453*753d2d2eSraf }
454*753d2d2eSraf break;
455*753d2d2eSraf }
456*753d2d2eSraf }
457*753d2d2eSraf
458*753d2d2eSraf
459*753d2d2eSraf /*
460*753d2d2eSraf * Tiny stats class...
461*753d2d2eSraf */
462*753d2d2eSraf void
stats_add_warning(void)463*753d2d2eSraf stats_add_warning(void)
464*753d2d2eSraf {
465*753d2d2eSraf Statistics.warnings++;
466*753d2d2eSraf }
467*753d2d2eSraf
468*753d2d2eSraf void
stats_add_error(void)469*753d2d2eSraf stats_add_error(void)
470*753d2d2eSraf {
471*753d2d2eSraf Statistics.errors++;
472*753d2d2eSraf }
473*753d2d2eSraf
474*753d2d2eSraf /*
475*753d2d2eSraf * collect_includes -- collect a global list of include files,
476*753d2d2eSraf * converting the comma- or space-separated input list into a
477*753d2d2eSraf * structure for the database to store.
478*753d2d2eSraf * As this can cause problems will ill-structured
479*753d2d2eSraf * files, there is a mechanism to allow exclusion of
480*753d2d2eSraf * certain files, (or certain combinations). At
481*753d2d2eSraf * the moment, the mechanism is TBD, as is the second arg.
482*753d2d2eSraf */
483*753d2d2eSraf /*ARGSUSED1*/
484*753d2d2eSraf int
collect_include(char * p,int line)485*753d2d2eSraf collect_include(char *p, int line)
486*753d2d2eSraf {
487*753d2d2eSraf char *include;
488*753d2d2eSraf int len;
489*753d2d2eSraf
490*753d2d2eSraf errlog(BEGIN, "collect_include() {");
491*753d2d2eSraf if ((include = strtok(p, ", ")) != NULL) {
492*753d2d2eSraf for (; include != NULL; include = strtok(NULL, ", ")) {
493*753d2d2eSraf include = skipb(include);
494*753d2d2eSraf
495*753d2d2eSraf /*
496*753d2d2eSraf * Make sure the include file's name
497*753d2d2eSraf * has legitimate C syntax - i.e. it's in double
498*753d2d2eSraf * quotes or angle brackets.
499*753d2d2eSraf */
500*753d2d2eSraf if (*include != '"' && *include != '<')
501*753d2d2eSraf return (ERROR_RC);
502*753d2d2eSraf
503*753d2d2eSraf len = strlen(include);
504*753d2d2eSraf
505*753d2d2eSraf if (include[len-1] != '"' && include[len-1] != '>')
506*753d2d2eSraf return (ERROR_RC);
507*753d2d2eSraf
508*753d2d2eSraf /*
509*753d2d2eSraf * If include filename syntax is OK, add it to
510*753d2d2eSraf * the list
511*753d2d2eSraf */
512*753d2d2eSraf symtab_add_includes(include);
513*753d2d2eSraf }
514*753d2d2eSraf }
515*753d2d2eSraf errlog(END, "}");
516*753d2d2eSraf return (SUCCESS_RC);
517*753d2d2eSraf }
518*753d2d2eSraf
519*753d2d2eSraf /*
520*753d2d2eSraf * collect_binding -- take a binding and stuff it into the database
521*753d2d2eSraf * in canonical form (with the word return in it).
522*753d2d2eSraf */
523*753d2d2eSraf int
collect_binding(int const token,char * value,int line)524*753d2d2eSraf collect_binding(int const token, char *value, int line)
525*753d2d2eSraf {
526*753d2d2eSraf char *file = db_get_current_file();
527*753d2d2eSraf
528*753d2d2eSraf errlog(BEGIN, "collect_binding() {");
529*753d2d2eSraf errlog(VERBOSE, "name=\"%s\", value=\"%s\", line=%d\n",
530*753d2d2eSraf Keywords[token-FIRST_TOKEN].key, value, line);
531*753d2d2eSraf
532*753d2d2eSraf if (token == XLATOR_KW_EXCP) {
533*753d2d2eSraf symtab_set_exception(value, line, file);
534*753d2d2eSraf } else {
535*753d2d2eSraf errlog(FATAL|INPUT, "programmer error: impossible binding.");
536*753d2d2eSraf }
537*753d2d2eSraf errlog(END, "}");
538*753d2d2eSraf return (SUCCESS_RC);
539*753d2d2eSraf }
540*753d2d2eSraf
541*753d2d2eSraf /*
542*753d2d2eSraf * collect_errval -- collect the error variable name (only)
543*753d2d2eSraf * from the line. This is expected to be the first
544*753d2d2eSraf * or only thing in a space- or comma-separated list.
545*753d2d2eSraf * Collecting errno/errval possible value is left TBD.
546*753d2d2eSraf */
547*753d2d2eSraf int
collect_errval(char * p,int line)548*753d2d2eSraf collect_errval(char *p, int line)
549*753d2d2eSraf {
550*753d2d2eSraf char *name;
551*753d2d2eSraf
552*753d2d2eSraf errlog(BEGIN, "collect_errval() {");
553*753d2d2eSraf name = strtok(p, " \t\n\r");
554*753d2d2eSraf symtab_set_errval(name, line, db_get_current_file(), "int", "int", 0);
555*753d2d2eSraf errlog(END, "}");
556*753d2d2eSraf return (SUCCESS_RC);
557*753d2d2eSraf }
558*753d2d2eSraf
559*753d2d2eSraf /*
560*753d2d2eSraf * collect_arch -- collect architecture.
561*753d2d2eSraf */
562*753d2d2eSraf int
collect_arch(char * value)563*753d2d2eSraf collect_arch(char *value)
564*753d2d2eSraf {
565*753d2d2eSraf char const *arch = db_get_arch();
566*753d2d2eSraf char *buf, *p;
567*753d2d2eSraf char *t;
568*753d2d2eSraf
569*753d2d2eSraf errlog(BEGIN, "collect_arch() {");
570*753d2d2eSraf if (value == 0 || *value == '\0')
571*753d2d2eSraf errlog(FATAL|INPUT, "No architectures defined in ARCH line");
572*753d2d2eSraf
573*753d2d2eSraf if ((buf = strdup(value)) == NULL)
574*753d2d2eSraf errlog(FATAL, "Could not allocate memory in ARCH directive");
575*753d2d2eSraf
576*753d2d2eSraf t = buf;
577*753d2d2eSraf while ((p = strtok(t, " \r\t\n")) != NULL) {
578*753d2d2eSraf if (strcmp(p, arch) == 0 || strcmp(p, "all") == 0)
579*753d2d2eSraf goto cleanup;
580*753d2d2eSraf t = NULL;
581*753d2d2eSraf }
582*753d2d2eSraf symtab_set_skip(YES);
583*753d2d2eSraf
584*753d2d2eSraf cleanup:
585*753d2d2eSraf free(buf);
586*753d2d2eSraf return (SUCCESS_RC);
587*753d2d2eSraf }
588*753d2d2eSraf
589*753d2d2eSraf /*
590*753d2d2eSraf * de_const -- get rid of const meta-types. This is actually a
591*753d2d2eSraf * dodge to avoid writing a base-type function early in the
592*753d2d2eSraf * process. This may turn into to_basetype() or to_primitivetype().
593*753d2d2eSraf */
594*753d2d2eSraf static char *
de_const(char * type)595*753d2d2eSraf de_const(char *type)
596*753d2d2eSraf {
597*753d2d2eSraf char *p, *q;
598*753d2d2eSraf int i;
599*753d2d2eSraf
600*753d2d2eSraf p = skipb(type);
601*753d2d2eSraf
602*753d2d2eSraf q = strstr(type, "const");
603*753d2d2eSraf if (q > p) {
604*753d2d2eSraf for (i = 0; i < 5; i++) {
605*753d2d2eSraf *q++ = '\0';
606*753d2d2eSraf }
607*753d2d2eSraf (void) sprintf(type, "%s%s", strnormalize(p), q);
608*753d2d2eSraf return (type);
609*753d2d2eSraf } else if (p == q) {
610*753d2d2eSraf return (skipb(nextsep(p)));
611*753d2d2eSraf } else {
612*753d2d2eSraf return (type);
613*753d2d2eSraf }
614*753d2d2eSraf
615*753d2d2eSraf }
616*753d2d2eSraf
617*753d2d2eSraf /*
618*753d2d2eSraf * to_basetype -- convert a C type declaration into its base type and return
619*753d2d2eSraf * the number of levels of indirection.
620*753d2d2eSraf * Destructive and eats ``const''.
621*753d2d2eSraf */
622*753d2d2eSraf static int
to_basetype(char * str)623*753d2d2eSraf to_basetype(char *str)
624*753d2d2eSraf {
625*753d2d2eSraf char *p = str,
626*753d2d2eSraf buffer[MAXLINE+1],
627*753d2d2eSraf *q = &buffer[0];
628*753d2d2eSraf int levels = 0;
629*753d2d2eSraf
630*753d2d2eSraf assert(strlen(str) < MAXLINE, "string exceeded MAXLINE");
631*753d2d2eSraf buffer[0] = NULL;
632*753d2d2eSraf for (; *p != NULL; p++) {
633*753d2d2eSraf switch (*p) {
634*753d2d2eSraf case ' ': /* Convert spaces to single ' '. */
635*753d2d2eSraf if (*(q-1) != ' ')
636*753d2d2eSraf *q++ = ' ';
637*753d2d2eSraf break;
638*753d2d2eSraf case '*': /* Convert * to _P. */
639*753d2d2eSraf if (*(q-1) != ' ')
640*753d2d2eSraf *q++ = ' ';
641*753d2d2eSraf levels++;
642*753d2d2eSraf break;
643*753d2d2eSraf case 'c': /* This might be a const */
644*753d2d2eSraf if (strncmp(p, "const", 5) == 0) {
645*753d2d2eSraf p += 4;
646*753d2d2eSraf } else {
647*753d2d2eSraf *q++ = *p;
648*753d2d2eSraf }
649*753d2d2eSraf break;
650*753d2d2eSraf default:
651*753d2d2eSraf /* Otherwise just copy. */
652*753d2d2eSraf *q++ = *p;
653*753d2d2eSraf break;
654*753d2d2eSraf }
655*753d2d2eSraf *q = NULL;
656*753d2d2eSraf }
657*753d2d2eSraf assert(q < &buffer[MAXLINE], "q fell off end of buffer");
658*753d2d2eSraf q--;
659*753d2d2eSraf while (*q == ' ') {
660*753d2d2eSraf *q-- = NULL;
661*753d2d2eSraf }
662*753d2d2eSraf assert(strlen(buffer) < MAXLINE, "buffer length exceeded MAXLINE");
663*753d2d2eSraf (void) strcpy(str, buffer);
664*753d2d2eSraf return (levels);
665*753d2d2eSraf }
666*753d2d2eSraf
667*753d2d2eSraf /*
668*753d2d2eSraf * to_actual -- create an actual-argument list for use
669*753d2d2eSraf * when calling the function.
670*753d2d2eSraf */
671*753d2d2eSraf static char *
to_actual(void)672*753d2d2eSraf to_actual(void)
673*753d2d2eSraf {
674*753d2d2eSraf ENTRY *p;
675*753d2d2eSraf static char buffer[MAXLINE+1];
676*753d2d2eSraf int n;
677*753d2d2eSraf
678*753d2d2eSraf *buffer = NULL;
679*753d2d2eSraf if ((p = symtab_get_first_arg()) != NULL) {
680*753d2d2eSraf n = MAXLINE - snprintf(buffer, MAXLINE, "%s", name_of(p));
681*753d2d2eSraf for (p = symtab_get_next_arg(); p != NULL;
682*753d2d2eSraf p = symtab_get_next_arg()) {
683*753d2d2eSraf if (*name_of(p) != NULL)
684*753d2d2eSraf n -= snprintf(strend(buffer), n,
685*753d2d2eSraf ", %s", name_of(p));
686*753d2d2eSraf }
687*753d2d2eSraf }
688*753d2d2eSraf return (buffer);
689*753d2d2eSraf }
690*753d2d2eSraf
691*753d2d2eSraf /*
692*753d2d2eSraf * strpqcpy -- string copy that takes whatever begins with p and ends
693*753d2d2eSraf * just before q.
694*753d2d2eSraf */
695*753d2d2eSraf static char *
strpqcpy(char * target,char * p,char * q)696*753d2d2eSraf strpqcpy(char *target, char *p, char *q)
697*753d2d2eSraf {
698*753d2d2eSraf char saved;
699*753d2d2eSraf
700*753d2d2eSraf saved = *q;
701*753d2d2eSraf *q = NULL;
702*753d2d2eSraf (void) strcpy(target, p);
703*753d2d2eSraf *q = saved;
704*753d2d2eSraf return (target);
705*753d2d2eSraf }
706*753d2d2eSraf
707*753d2d2eSraf #ifndef lint
708*753d2d2eSraf int
breakpoint(void)709*753d2d2eSraf breakpoint(void)
710*753d2d2eSraf {
711*753d2d2eSraf return (0);
712*753d2d2eSraf }
713*753d2d2eSraf #endif
714*753d2d2eSraf
715*753d2d2eSraf
716*753d2d2eSraf int
collect_prototype(char * p,int line,int extcnt)717*753d2d2eSraf collect_prototype(char *p, int line, int extcnt)
718*753d2d2eSraf {
719*753d2d2eSraf char f_type[BUFSIZ]; /* The function. */
720*753d2d2eSraf char f_basetype[BUFSIZ];
721*753d2d2eSraf char f_name[BUFSIZ];
722*753d2d2eSraf char a_name[BUFSIZ]; /* The arguments. */
723*753d2d2eSraf char a_basetype[BUFSIZ];
724*753d2d2eSraf char a_type[BUFSIZ];
725*753d2d2eSraf char *file = db_get_current_file();
726*753d2d2eSraf char *interface = db_get_current_interface();
727*753d2d2eSraf char *q;
728*753d2d2eSraf char const *parse_err;
729*753d2d2eSraf char tmp_proto[BUFSIZ], buf[BUFSIZ];
730*753d2d2eSraf decl_t *pp, *funargs;
731*753d2d2eSraf type_t *tp;
732*753d2d2eSraf int levels, a_levels;
733*753d2d2eSraf
734*753d2d2eSraf tmp_proto[BUFSIZ-1] = 0;
735*753d2d2eSraf errlog(BEGIN, "collect_prototype() {");
736*753d2d2eSraf if (p[strlen(p)-1] != ';')
737*753d2d2eSraf (void) snprintf(tmp_proto, BUFSIZ, "%s;", p);
738*753d2d2eSraf else
739*753d2d2eSraf (void) snprintf(tmp_proto, BUFSIZ, "%s", p);
740*753d2d2eSraf
741*753d2d2eSraf /* save prototype in symbol table */
742*753d2d2eSraf symtab_set_prototype(p);
743*753d2d2eSraf
744*753d2d2eSraf errlog(VERBOSE, "parsing prototype: %s\n", tmp_proto);
745*753d2d2eSraf
746*753d2d2eSraf /* Parse Prototype */
747*753d2d2eSraf if ((parse_err = decl_Parse(tmp_proto, &pp)) != NULL) {
748*753d2d2eSraf errlog(FATAL|INPUT, "bad prototype: %s\n\t%s\n", parse_err, p);
749*753d2d2eSraf }
750*753d2d2eSraf
751*753d2d2eSraf if (extcnt == 0) {
752*753d2d2eSraf char *dname = decl_GetName(pp);
753*753d2d2eSraf if (strcmp(interface, dname) != 0)
754*753d2d2eSraf errlog(FATAL|INPUT, "function and declaration"
755*753d2d2eSraf " name mismatch\nfunction name = %s,"
756*753d2d2eSraf " declaration name = %s\n", interface,
757*753d2d2eSraf dname);
758*753d2d2eSraf }
759*753d2d2eSraf
760*753d2d2eSraf tp = decl_GetType(pp);
761*753d2d2eSraf
762*753d2d2eSraf if (type_IsPtrFun(tp)) {
763*753d2d2eSraf errlog(FATAL|INPUT, "function %s is declared as a data item"
764*753d2d2eSraf " (pointer to function)\n", interface);
765*753d2d2eSraf } else if (!type_IsFunction(tp)) {
766*753d2d2eSraf errlog(FATAL|INPUT, "function %s is declared as a data item",
767*753d2d2eSraf interface);
768*753d2d2eSraf }
769*753d2d2eSraf
770*753d2d2eSraf if (type_IsVarargs(tp)) {
771*753d2d2eSraf symtab_set_skip(YES);
772*753d2d2eSraf decl_Destroy(pp);
773*753d2d2eSraf return (SUCCESS_RC);
774*753d2d2eSraf }
775*753d2d2eSraf
776*753d2d2eSraf decl_GetTraceInfo(pp, f_type, f_basetype, &funargs);
777*753d2d2eSraf (void) sprintf(buf, "%s", strnormalize(f_type));
778*753d2d2eSraf (void) strcpy(f_type, buf);
779*753d2d2eSraf (void) sprintf(buf, "%s", strnormalize(f_basetype));
780*753d2d2eSraf (void) strcpy(f_basetype, buf);
781*753d2d2eSraf levels = to_basetype(f_basetype);
782*753d2d2eSraf
783*753d2d2eSraf /* get interface name from 'Begin' line */
784*753d2d2eSraf (void) strpqcpy(f_name, interface, nextsep(interface));
785*753d2d2eSraf (void) decl_SetName(pp, f_name);
786*753d2d2eSraf
787*753d2d2eSraf errlog(VERBOSE, "f_name=%s, f_basetype=%s, f_type=%s\n",
788*753d2d2eSraf f_name, f_basetype, f_type);
789*753d2d2eSraf
790*753d2d2eSraf symtab_set_function(f_name, line, file, f_type, f_basetype, levels);
791*753d2d2eSraf
792*753d2d2eSraf db_add_print_types(f_basetype,
793*753d2d2eSraf (q = de_const(type_of(symtab_get_function()))));
794*753d2d2eSraf
795*753d2d2eSraf symtab_add_print_types(f_basetype, q);
796*753d2d2eSraf
797*753d2d2eSraf /* args list */
798*753d2d2eSraf while (funargs) {
799*753d2d2eSraf (void) snprintf(a_type, BUFSIZ, "%s ",
800*753d2d2eSraf strnormalize(declspec_ToString(buf, funargs->d_ds)));
801*753d2d2eSraf (void) snprintf(a_basetype, BUFSIZ, "%s",
802*753d2d2eSraf strnormalize(de_const(declspec_ToString(buf,
803*753d2d2eSraf funargs->d_ds))));
804*753d2d2eSraf
805*753d2d2eSraf tp = funargs->d_type;
806*753d2d2eSraf
807*753d2d2eSraf for (a_levels = 0; tp; ) {
808*753d2d2eSraf if (tp->t_dt == DD_PTR || tp->t_dt == DD_ARY) {
809*753d2d2eSraf (void) strcat(a_type, "*");
810*753d2d2eSraf a_levels++;
811*753d2d2eSraf }
812*753d2d2eSraf tp = tp->t_next;
813*753d2d2eSraf }
814*753d2d2eSraf
815*753d2d2eSraf /*
816*753d2d2eSraf * XXX: This is a hack to work around bug in yacc parser
817*753d2d2eSraf * "int foo(void)" prototypes get interpreted as having 1
818*753d2d2eSraf * argument with the d_name of the argument being NULL.
819*753d2d2eSraf */
820*753d2d2eSraf if (funargs->d_name) {
821*753d2d2eSraf (void) snprintf(a_name, 20, "%s", funargs->d_name);
822*753d2d2eSraf
823*753d2d2eSraf errlog(VERBOSE,
824*753d2d2eSraf "a_name = %s, a_basetype = %s, a_type = %s\n",
825*753d2d2eSraf a_name, a_basetype, a_type);
826*753d2d2eSraf
827*753d2d2eSraf symtab_add_args(a_name, line, file,
828*753d2d2eSraf a_type, a_basetype, a_levels);
829*753d2d2eSraf db_add_print_types(a_basetype,
830*753d2d2eSraf q = de_const(type_of(symtab_get_last_arg())));
831*753d2d2eSraf symtab_add_print_types(a_basetype, q);
832*753d2d2eSraf }
833*753d2d2eSraf
834*753d2d2eSraf funargs = funargs->d_next;
835*753d2d2eSraf }
836*753d2d2eSraf symtab_set_formals(decl_ToFormal(pp));
837*753d2d2eSraf symtab_set_actuals(to_actual());
838*753d2d2eSraf
839*753d2d2eSraf symtab_set_cast(decl_ToString(buf, DTS_CAST, pp, NULL));
840*753d2d2eSraf
841*753d2d2eSraf decl_Destroy(pp);
842*753d2d2eSraf
843*753d2d2eSraf errlog(END, "}");
844*753d2d2eSraf return (SUCCESS_RC);
845*753d2d2eSraf }
846*753d2d2eSraf
847*753d2d2eSraf
848*753d2d2eSraf /*
849*753d2d2eSraf * generators
850*753d2d2eSraf */
851*753d2d2eSraf
852*753d2d2eSraf /*
853*753d2d2eSraf * generate_init -- prime the code generator as required.
854*753d2d2eSraf */
855*753d2d2eSraf static void
generate_init(void)856*753d2d2eSraf generate_init(void)
857*753d2d2eSraf {
858*753d2d2eSraf errlog(BEGIN, "generate_init() {");
859*753d2d2eSraf
860*753d2d2eSraf (void) fprintf(Headfp,
861*753d2d2eSraf "/*\n"
862*753d2d2eSraf " * Generated by spec2trace %s: do not edit this file.\n */\n\n",
863*753d2d2eSraf TRACE_VERSION);
864*753d2d2eSraf
865*753d2d2eSraf (void) fprintf(Headfp,
866*753d2d2eSraf "#ifndef true\n"
867*753d2d2eSraf "#define\ttrue 1\n"
868*753d2d2eSraf "#define\tfalse 0\n"
869*753d2d2eSraf "#endif\n\n"
870*753d2d2eSraf "static char const *oparen = \"(\";\n"
871*753d2d2eSraf "static char const *retstr = \" return = \";\n"
872*753d2d2eSraf "static char const *errnostr = \" errno = \";\n"
873*753d2d2eSraf "static char const *nilstr = \"<nil>\";\n"
874*753d2d2eSraf "\n");
875*753d2d2eSraf
876*753d2d2eSraf errlog(END, "}");
877*753d2d2eSraf }
878*753d2d2eSraf
879*753d2d2eSraf
880*753d2d2eSraf /*
881*753d2d2eSraf * generate_interface -- call the two main parts of the per-interface
882*753d2d2eSraf * code generation.
883*753d2d2eSraf */
884*753d2d2eSraf static void
generate_interface(void)885*753d2d2eSraf generate_interface(void)
886*753d2d2eSraf {
887*753d2d2eSraf ENTRY *function = symtab_get_function();
888*753d2d2eSraf
889*753d2d2eSraf errlog(BEGIN, "generate_interface() {");
890*753d2d2eSraf /* Check for required information. */
891*753d2d2eSraf if (validity_of(function) == NO) {
892*753d2d2eSraf symtab_set_skip(YES);
893*753d2d2eSraf errlog(WARNING|INPUT, "no prototype for interface "
894*753d2d2eSraf "it will be skipped");
895*753d2d2eSraf errlog(END, "}");
896*753d2d2eSraf return;
897*753d2d2eSraf }
898*753d2d2eSraf
899*753d2d2eSraf /* Generate the current interface 's print-functions declarations. */
900*753d2d2eSraf generate_print_declarations(Bodyfp);
901*753d2d2eSraf
902*753d2d2eSraf /* Generate the linkage part (a function and a struct */
903*753d2d2eSraf generate_linkage(function);
904*753d2d2eSraf
905*753d2d2eSraf /* Generate the actual interceptor. */
906*753d2d2eSraf generate_interceptor(function);
907*753d2d2eSraf errlog(END, "}");
908*753d2d2eSraf }
909*753d2d2eSraf
910*753d2d2eSraf
911*753d2d2eSraf /*
912*753d2d2eSraf * generate_closedown -- produce includes.
913*753d2d2eSraf */
914*753d2d2eSraf static void
generate_closedown(void)915*753d2d2eSraf generate_closedown(void)
916*753d2d2eSraf {
917*753d2d2eSraf errlog(BEGIN, "generate_closedown() {");
918*753d2d2eSraf
919*753d2d2eSraf /* Print includes to primary file. */
920*753d2d2eSraf generate_includes();
921*753d2d2eSraf (void) putc('\n', Headfp);
922*753d2d2eSraf errlog(END, "}");
923*753d2d2eSraf }
924*753d2d2eSraf
925*753d2d2eSraf /*
926*753d2d2eSraf * generate_aux_file -- generate one additional .pf file with
927*753d2d2eSraf * print-function pointers.
928*753d2d2eSraf */
929*753d2d2eSraf static int
generate_aux_file(void)930*753d2d2eSraf generate_aux_file(void)
931*753d2d2eSraf {
932*753d2d2eSraf FILE *fp;
933*753d2d2eSraf char pathname[MAXLINE];
934*753d2d2eSraf
935*753d2d2eSraf errlog(BEGIN, "generate_aux_file() {");
936*753d2d2eSraf /* Open file */
937*753d2d2eSraf (void) snprintf(pathname, sizeof (pathname), "%s.pf",
938*753d2d2eSraf db_get_output_file());
939*753d2d2eSraf errlog(TRACING, "output file = '%s'", pathname);
940*753d2d2eSraf if ((fp = fopen(pathname, "w")) == NULL) {
941*753d2d2eSraf errlog(FATAL, "%s: %s", pathname, strerror(errno));
942*753d2d2eSraf }
943*753d2d2eSraf
944*753d2d2eSraf /*
945*753d2d2eSraf * Declare and initialize all print function pointers to null.
946*753d2d2eSraf * Some spec files result in nothing being put into the .pf
947*753d2d2eSraf * file. We must create the file since make(1) does not cope
948*753d2d2eSraf * well with absent files that it expects to have built. So
949*753d2d2eSraf * now the build gets empty compilation unit warnings... So
950*753d2d2eSraf * we unconditionally create a static pointer.
951*753d2d2eSraf */
952*753d2d2eSraf (void) fprintf(fp,
953*753d2d2eSraf "/* Do not edit this file: it is a generated one. */\n\n"
954*753d2d2eSraf "static char const *__abi_place_holder;\n\n");
955*753d2d2eSraf
956*753d2d2eSraf generate_print_definitions(fp);
957*753d2d2eSraf
958*753d2d2eSraf /* Close file */
959*753d2d2eSraf if (fclose(fp) != 0) {
960*753d2d2eSraf errlog(FATAL, "fclose %s: %s", pathname, strerror(errno));
961*753d2d2eSraf }
962*753d2d2eSraf errlog(END, "}");
963*753d2d2eSraf return (YES);
964*753d2d2eSraf }
965*753d2d2eSraf
966*753d2d2eSraf
967*753d2d2eSraf
968*753d2d2eSraf /*
969*753d2d2eSraf * generate_includes -- generate #includes to Headfp
970*753d2d2eSraf */
971*753d2d2eSraf static void
generate_includes(void)972*753d2d2eSraf generate_includes(void)
973*753d2d2eSraf {
974*753d2d2eSraf char *include;
975*753d2d2eSraf
976*753d2d2eSraf errlog(BEGIN, "generate_includes() {");
977*753d2d2eSraf errlog(TRACING, "includes=");
978*753d2d2eSraf for (include = symtab_get_first_include(); include != NULL;
979*753d2d2eSraf include = symtab_get_next_include())
980*753d2d2eSraf (void) fprintf(Headfp, "#include %s\n", include);
981*753d2d2eSraf
982*753d2d2eSraf (void) fprintf(Headfp, "\n#include <stdio.h>\n"
983*753d2d2eSraf "#include <dlfcn.h>\n"
984*753d2d2eSraf "#include <apptrace.h>\n\n");
985*753d2d2eSraf
986*753d2d2eSraf errlog(TRACING, "\n");
987*753d2d2eSraf errlog(END, "}");
988*753d2d2eSraf }
989