1*2775Sraf /*
2*2775Sraf * CDDL HEADER START
3*2775Sraf *
4*2775Sraf * The contents of this file are subject to the terms of the
5*2775Sraf * Common Development and Distribution License, Version 1.0 only
6*2775Sraf * (the "License"). You may not use this file except in compliance
7*2775Sraf * with the License.
8*2775Sraf *
9*2775Sraf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*2775Sraf * or http://www.opensolaris.org/os/licensing.
11*2775Sraf * See the License for the specific language governing permissions
12*2775Sraf * and limitations under the License.
13*2775Sraf *
14*2775Sraf * When distributing Covered Code, include this CDDL HEADER in each
15*2775Sraf * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*2775Sraf * If applicable, add the following below this CDDL HEADER, with the
17*2775Sraf * fields enclosed by brackets "[]" replaced with your own identifying
18*2775Sraf * information: Portions Copyright [yyyy] [name of copyright owner]
19*2775Sraf *
20*2775Sraf * CDDL HEADER END
21*2775Sraf */
22*2775Sraf /*
23*2775Sraf * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24*2775Sraf * Use is subject to license terms.
25*2775Sraf */
26*2775Sraf
27*2775Sraf #pragma ident "%Z%%M% %I% %E% SMI"
28*2775Sraf
29*2775Sraf /*
30*2775Sraf * Back-end functions for spec to mapfile converter
31*2775Sraf */
32*2775Sraf
33*2775Sraf #include <stdio.h>
34*2775Sraf #include <stdlib.h>
35*2775Sraf #include <ctype.h>
36*2775Sraf #include <string.h>
37*2775Sraf #include <errno.h>
38*2775Sraf #include <sys/utsname.h>
39*2775Sraf #include "xlator.h"
40*2775Sraf #include "util.h"
41*2775Sraf #include "bucket.h"
42*2775Sraf
43*2775Sraf /* Globals */
44*2775Sraf enum {
45*2775Sraf /* These first four (commented out) are defined in parser.h */
46*2775Sraf /* XLATOR_KW_NOTFOUND = 0, */
47*2775Sraf /* XLATOR_KW_FUNC, */
48*2775Sraf /* XLATOR_KW_DATA, */
49*2775Sraf /* XLATOR_KW_END, */
50*2775Sraf XLATOR_KW_VERSION = 4,
51*2775Sraf XLATOR_KW_ARCH,
52*2775Sraf XLATOR_KW_BINDING,
53*2775Sraf XLATOR_KW_FILTER,
54*2775Sraf XLATOR_KW_AUXILIARY
55*2775Sraf };
56*2775Sraf #define FIRST_TOKEN 4 /* Must match the first token in the enum above */
57*2775Sraf
58*2775Sraf static xlator_keyword_t Keywords[] = {
59*2775Sraf { "version", XLATOR_KW_VERSION },
60*2775Sraf { "arch", XLATOR_KW_ARCH },
61*2775Sraf { "binding", XLATOR_KW_BINDING },
62*2775Sraf { "filter", XLATOR_KW_FILTER },
63*2775Sraf { "auxiliary", XLATOR_KW_AUXILIARY },
64*2775Sraf { NULL, XLATOR_KW_NOTFOUND }
65*2775Sraf };
66*2775Sraf
67*2775Sraf static char const *OutputFile;
68*2775Sraf static char const *Curfile;
69*2775Sraf static char *Curfun;
70*2775Sraf static int Curline;
71*2775Sraf static Interface Iface;
72*2775Sraf
73*2775Sraf static int Verbosity;
74*2775Sraf static int TargetArchToken; /* set from -a option to front-end */
75*2775Sraf char *TargetArchStr = NULL; /* from -a option to front-end */
76*2775Sraf int IsFilterLib = 0; /* set from -F option to front-end */
77*2775Sraf static int Supported_Arch = XLATOR_ALLARCH; /* from "Arch" SPEC keyword */
78*2775Sraf static int Flags;
79*2775Sraf
80*2775Sraf /*
81*2775Sraf * WHAT!?
82*2775Sraf * from Version line
83*2775Sraf * 0 means architecture is not specified in the
84*2775Sraf * version line so it applies to all versions
85*2775Sraf */
86*2775Sraf static int Version_Arch;
87*2775Sraf int Num_versfiles = 0;
88*2775Sraf static int Has_Version;
89*2775Sraf
90*2775Sraf static char *Versfile;
91*2775Sraf
92*2775Sraf static char *getversion(const char *);
93*2775Sraf static int version_sanity(const char *value, char **subv);
94*2775Sraf static int arch_version_sanity(char *av);
95*2775Sraf static char *getfilter(const char *);
96*2775Sraf static void writemapfile(FILE *);
97*2775Sraf static int set_version_arch(const char *);
98*2775Sraf static int set_supported_arch(const char *);
99*2775Sraf
100*2775Sraf /*
101*2775Sraf * xlator_init()
102*2775Sraf * back-end initialization
103*2775Sraf * returns pointer to Keywords on success
104*2775Sraf * returns NULL pointer on failure
105*2775Sraf */
106*2775Sraf xlator_keyword_t *
xlator_init(const Translator_info * t_info)107*2775Sraf xlator_init(const Translator_info *t_info)
108*2775Sraf {
109*2775Sraf /*
110*2775Sraf * initially so we don't lose error messages from version_check
111*2775Sraf * we'll set this again later based on ti_info.ti_verbosity
112*2775Sraf */
113*2775Sraf seterrseverity(WARNING);
114*2775Sraf
115*2775Sraf /* set verbosity */
116*2775Sraf Verbosity = t_info->ti_verbosity;
117*2775Sraf seterrseverity(t_info->ti_verbosity);
118*2775Sraf
119*2775Sraf /* Obtain translator flags */
120*2775Sraf Flags = t_info->ti_flags;
121*2775Sraf
122*2775Sraf /*
123*2775Sraf * set Library Type
124*2775Sraf * 1 if filter lib, 0 otherwise
125*2775Sraf */
126*2775Sraf IsFilterLib = t_info->ti_libtype;
127*2775Sraf
128*2775Sraf /* set target architecture */
129*2775Sraf TargetArchStr = t_info->ti_arch;
130*2775Sraf TargetArchToken = t_info->ti_archtoken;
131*2775Sraf
132*2775Sraf errlog(STATUS, "Architecture set to \"%s\"", TargetArchStr);
133*2775Sraf
134*2775Sraf /* set output file */
135*2775Sraf OutputFile = t_info->ti_output_file;
136*2775Sraf if (OutputFile) {
137*2775Sraf errlog(STATUS, "Output will go into %s",
138*2775Sraf OutputFile);
139*2775Sraf } else {
140*2775Sraf OutputFile = "mapfile";
141*2775Sraf errlog(STATUS, "Using default output filename: %s",
142*2775Sraf OutputFile);
143*2775Sraf }
144*2775Sraf
145*2775Sraf /* obtain name of version file */
146*2775Sraf Versfile = t_info->ti_versfile;
147*2775Sraf
148*2775Sraf /* call create_lists() to setup for parse_versions() */
149*2775Sraf create_lists();
150*2775Sraf
151*2775Sraf /* Process Vers Files */
152*2775Sraf if (parse_versions(Versfile)) {
153*2775Sraf return (NULL);
154*2775Sraf }
155*2775Sraf
156*2775Sraf return (Keywords);
157*2775Sraf }
158*2775Sraf
159*2775Sraf /*
160*2775Sraf * xlator_startlib()
161*2775Sraf * start of library
162*2775Sraf * returns: XLATOR_SUCCESS on success
163*2775Sraf * XLATOR_SKIP if library is to be skipped
164*2775Sraf * XLATOR_NONFATAL on error
165*2775Sraf */
166*2775Sraf /*ARGSUSED*/
167*2775Sraf int
xlator_startlib(char const * libname)168*2775Sraf xlator_startlib(char const *libname)
169*2775Sraf {
170*2775Sraf errlog(TRACING, "xlator_startlib");
171*2775Sraf return (XLATOR_SUCCESS);
172*2775Sraf }
173*2775Sraf
174*2775Sraf /*
175*2775Sraf * xlator_startfile()
176*2775Sraf * start of spec file
177*2775Sraf * returns: XLATOR_SUCCESS on success
178*2775Sraf * XLATOR_SKIP if file is to be skipped
179*2775Sraf * XLATOR_NONFATAL on error
180*2775Sraf */
181*2775Sraf int
xlator_startfile(char const * filename)182*2775Sraf xlator_startfile(char const *filename)
183*2775Sraf {
184*2775Sraf errlog(TRACING, "xlator_startfile");
185*2775Sraf
186*2775Sraf Curfile = filename;
187*2775Sraf
188*2775Sraf return (XLATOR_SUCCESS);
189*2775Sraf }
190*2775Sraf
191*2775Sraf /*
192*2775Sraf * xlator_start_if ()
193*2775Sraf * start of interface specification
194*2775Sraf * returns: XLATOR_SUCCESS on success
195*2775Sraf * XLATOR_SKIP if interface is to be skipped
196*2775Sraf * XLATOR_NONFATAL on error
197*2775Sraf * XLATOR_FATAL on fatal error
198*2775Sraf */
199*2775Sraf int
xlator_start_if(const Meta_info meta_info,const int token,char * value)200*2775Sraf xlator_start_if(const Meta_info meta_info, const int token, char *value)
201*2775Sraf {
202*2775Sraf char rhs[BUFSIZ];
203*2775Sraf char *kw;
204*2775Sraf int err;
205*2775Sraf
206*2775Sraf errlog(TRACING, "xlator_start_if %s", value);
207*2775Sraf
208*2775Sraf switch (token) {
209*2775Sraf case XLATOR_KW_FUNC:
210*2775Sraf kw = "Function";
211*2775Sraf break;
212*2775Sraf case XLATOR_KW_DATA:
213*2775Sraf kw = "Data";
214*2775Sraf break;
215*2775Sraf default:
216*2775Sraf /* This should never happen */
217*2775Sraf errlog(ERROR,
218*2775Sraf "\"%s\", line %d: Implementation error! "
219*2775Sraf "Please file a bug\n", __FILE__, __LINE__);
220*2775Sraf return (XLATOR_FATAL);
221*2775Sraf }
222*2775Sraf
223*2775Sraf Curline = meta_info.mi_line_number;
224*2775Sraf seterrline(Curline, meta_info.mi_filename, kw, value);
225*2775Sraf
226*2775Sraf if (Curfun != NULL) {
227*2775Sraf errlog(INPUT|ERROR,
228*2775Sraf "Error: Interface spec is missing the "
229*2775Sraf "End keyword: %s", Curfun);
230*2775Sraf return (XLATOR_NONFATAL);
231*2775Sraf }
232*2775Sraf
233*2775Sraf err = sscanf(value, "%s", rhs);
234*2775Sraf if (err == 0 || err == EOF) {
235*2775Sraf errlog(INPUT|ERROR,
236*2775Sraf "Error: Missing argument in \"%s\" line", kw);
237*2775Sraf return (XLATOR_NONFATAL);
238*2775Sraf }
239*2775Sraf
240*2775Sraf Curfun = strdup(rhs);
241*2775Sraf
242*2775Sraf if (Curfun == NULL) {
243*2775Sraf errlog(ERROR | FATAL,
244*2775Sraf "Internal Error: strdup() failure in xlator_startif()");
245*2775Sraf }
246*2775Sraf
247*2775Sraf Iface.IF_name = Curfun;
248*2775Sraf Iface.IF_type = token; /* FUNCTION or DATA */
249*2775Sraf
250*2775Sraf Iface.IF_version = NULL;
251*2775Sraf Iface.IF_class = NULL;
252*2775Sraf Has_Version = 0;
253*2775Sraf Supported_Arch = XLATOR_ALLARCH;
254*2775Sraf Version_Arch = 0;
255*2775Sraf
256*2775Sraf Iface.IF_binding = DEFAULT;
257*2775Sraf
258*2775Sraf Iface.IF_filter = NULL;
259*2775Sraf Iface.IF_auxiliary = NULL;
260*2775Sraf
261*2775Sraf return (XLATOR_SUCCESS);
262*2775Sraf }
263*2775Sraf
264*2775Sraf /*
265*2775Sraf * xlator_take_kvpair()
266*2775Sraf * processes spec keyword-value pairs
267*2775Sraf * returns: XLATOR_SUCCESS on success
268*2775Sraf * XLATOR_NONFATAL on error
269*2775Sraf */
270*2775Sraf int
xlator_take_kvpair(const Meta_info meta_info,const int token,char * value)271*2775Sraf xlator_take_kvpair(const Meta_info meta_info, const int token,
272*2775Sraf char *value)
273*2775Sraf {
274*2775Sraf char *p;
275*2775Sraf char *subv = NULL;
276*2775Sraf char *key = Keywords[token-FIRST_TOKEN].key;
277*2775Sraf
278*2775Sraf Curline = meta_info.mi_line_number;
279*2775Sraf seterrline(Curline, meta_info.mi_filename, key, value);
280*2775Sraf
281*2775Sraf errlog(TRACING,
282*2775Sraf "take_kvpair called. ext_cnt=%d token=%d key=%s value=%s",
283*2775Sraf meta_info.mi_ext_cnt, token, key, value);
284*2775Sraf
285*2775Sraf if (Curfun == NULL) {
286*2775Sraf errlog(INPUT|ERROR, "Error: Keyword found outside "
287*2775Sraf "an interface specification block, line %d", Curline);
288*2775Sraf return (XLATOR_NONFATAL);
289*2775Sraf }
290*2775Sraf
291*2775Sraf switch (token) {
292*2775Sraf case XLATOR_KW_VERSION:
293*2775Sraf if (meta_info.mi_ext_cnt != 0)
294*2775Sraf return (XLATOR_SUCCESS);
295*2775Sraf
296*2775Sraf errlog(TRACING, "Version found. Setting Version to %s", value);
297*2775Sraf
298*2775Sraf /* Version line found ; used for auditing the SPEC */
299*2775Sraf Has_Version = 1;
300*2775Sraf
301*2775Sraf /* remove trailing white space */
302*2775Sraf p = strrchr(value, '\n');
303*2775Sraf if (p) {
304*2775Sraf while (p >= value && isspace(*p)) {
305*2775Sraf *p = '\0';
306*2775Sraf --p;
307*2775Sraf }
308*2775Sraf }
309*2775Sraf
310*2775Sraf /* is the version line valid */
311*2775Sraf switch (version_sanity(value, &subv)) {
312*2775Sraf case VS_OK: /* OK, subv not set */
313*2775Sraf break;
314*2775Sraf
315*2775Sraf case VS_INVARCH: /* Invalid Arch */
316*2775Sraf errlog(INPUT|ERROR, "Error: Invalid architecture "
317*2775Sraf "string found in spec or version file: %s", subv);
318*2775Sraf free(subv);
319*2775Sraf return (XLATOR_NONFATAL);
320*2775Sraf
321*2775Sraf case VS_INVVERS: /* Invalid Version String */
322*2775Sraf errlog(INPUT|ERROR, "Error: Invalid version string "
323*2775Sraf "in spec or version file: %s", subv);
324*2775Sraf free(subv);
325*2775Sraf return (XLATOR_NONFATAL);
326*2775Sraf
327*2775Sraf case VS_INVALID: /* Both Version and Arch are invalid */
328*2775Sraf errlog(INPUT|ERROR, "Error: Invalid version and "
329*2775Sraf "architecture string in spec or version file"
330*2775Sraf ": %s", subv);
331*2775Sraf free(subv);
332*2775Sraf return (XLATOR_NONFATAL);
333*2775Sraf
334*2775Sraf default: /* BAD IMPLEMENTATION OF version_sanity */
335*2775Sraf errlog(FATAL, "Error: bad return value from "
336*2775Sraf "version_sanity()! This should never happen!");
337*2775Sraf }
338*2775Sraf
339*2775Sraf errlog(TRACING, "Version_Arch=%d", Version_Arch);
340*2775Sraf
341*2775Sraf Iface.IF_version = getversion(value);
342*2775Sraf break;
343*2775Sraf
344*2775Sraf case XLATOR_KW_ARCH:
345*2775Sraf if (meta_info.mi_ext_cnt != 0)
346*2775Sraf return (XLATOR_SUCCESS);
347*2775Sraf
348*2775Sraf if (value[0] != '\0') {
349*2775Sraf Supported_Arch = 0;
350*2775Sraf if (set_supported_arch(value)) {
351*2775Sraf errlog(INPUT|ERROR,
352*2775Sraf "Error: Unable to parse Arch line");
353*2775Sraf return (XLATOR_NONFATAL);
354*2775Sraf }
355*2775Sraf } else {
356*2775Sraf errlog(INPUT | ERROR, "Error: Empty Arch line.");
357*2775Sraf }
358*2775Sraf
359*2775Sraf if (Supported_Arch == 0) {
360*2775Sraf errlog(INPUT | ERROR,
361*2775Sraf "Error: Unknown architecture defined in Arch line");
362*2775Sraf }
363*2775Sraf
364*2775Sraf errlog(TRACING,
365*2775Sraf "Interface %s supports the following architectures: "
366*2775Sraf "%s\tSupported_Arch=%d", Curfun, value, Supported_Arch);
367*2775Sraf break;
368*2775Sraf
369*2775Sraf case XLATOR_KW_BINDING:
370*2775Sraf
371*2775Sraf /*
372*2775Sraf * Note that we allow extends for the binding keyword by
373*2775Sraf * not checking that meta_info.mi_ext_cnt == 0 here.
374*2775Sraf */
375*2775Sraf
376*2775Sraf /* remove trailing white space */
377*2775Sraf p = strrchr(value, '\n');
378*2775Sraf if (p) {
379*2775Sraf while (p >= value && isspace(*p)) {
380*2775Sraf *p = '\0';
381*2775Sraf --p;
382*2775Sraf }
383*2775Sraf }
384*2775Sraf
385*2775Sraf if (value[0] != '\0') {
386*2775Sraf if (strcmp(value, "direct") == 0) {
387*2775Sraf Iface.IF_binding = DIRECT;
388*2775Sraf } else if (strcmp(value, "nodirect") == 0) {
389*2775Sraf Iface.IF_binding = NODIRECT;
390*2775Sraf } else if (strcmp(value, "protected") == 0) {
391*2775Sraf Iface.IF_binding = PROTECTED;
392*2775Sraf } else {
393*2775Sraf errlog(INPUT|ERROR,
394*2775Sraf "Error: Invalid binding value: %s", value);
395*2775Sraf }
396*2775Sraf } else {
397*2775Sraf errlog(INPUT | ERROR, "Error: Empty Binding line.");
398*2775Sraf }
399*2775Sraf
400*2775Sraf errlog(TRACING,
401*2775Sraf "Interface %s has binding value: "
402*2775Sraf "%s", Curfun, value);
403*2775Sraf break;
404*2775Sraf
405*2775Sraf case XLATOR_KW_FILTER:
406*2775Sraf case XLATOR_KW_AUXILIARY:
407*2775Sraf /*
408*2775Sraf * The following is for the "extends" clause. As with
409*2775Sraf * XLATOR_KW_VERSION, we do not want to follow an "extends"
410*2775Sraf * chain to get the filter or auxiliary values: we want
411*2775Sraf * the first/most-tightly-bound one (mi_ext_cnt = 0).
412*2775Sraf */
413*2775Sraf if (meta_info.mi_ext_cnt != 0)
414*2775Sraf return (XLATOR_SUCCESS);
415*2775Sraf
416*2775Sraf errlog(TRACING, "Filter[token=%d] found. Setting Filter to %s",
417*2775Sraf token, value);
418*2775Sraf
419*2775Sraf /* remove trailing white space */
420*2775Sraf p = strrchr(value, '\n');
421*2775Sraf if (p) {
422*2775Sraf while (p >= value && isspace(*p)) {
423*2775Sraf *p = '\0';
424*2775Sraf --p;
425*2775Sraf }
426*2775Sraf }
427*2775Sraf
428*2775Sraf errlog(TRACING, "Version_Arch=%d", Version_Arch);
429*2775Sraf
430*2775Sraf if (token == XLATOR_KW_FILTER) {
431*2775Sraf Iface.IF_filter = getfilter(value);
432*2775Sraf } else if (token == XLATOR_KW_AUXILIARY) {
433*2775Sraf Iface.IF_auxiliary = getfilter(value);
434*2775Sraf }
435*2775Sraf
436*2775Sraf break;
437*2775Sraf default:
438*2775Sraf errlog(INPUT|ERROR, "Error: Unrecognized keyword snuck in!"
439*2775Sraf "\tThis is a programmer error: %s", key);
440*2775Sraf return (XLATOR_NONFATAL);
441*2775Sraf }
442*2775Sraf
443*2775Sraf return (XLATOR_SUCCESS);
444*2775Sraf }
445*2775Sraf
446*2775Sraf /*
447*2775Sraf * xlator_end_if ()
448*2775Sraf * signal end of spec interface spec
449*2775Sraf * returns: XLATOR_SUCCESS on success
450*2775Sraf * XLATOR_NONFATAL on error
451*2775Sraf */
452*2775Sraf /*ARGSUSED*/
453*2775Sraf int
xlator_end_if(const Meta_info M,const char * value)454*2775Sraf xlator_end_if(const Meta_info M, const char *value)
455*2775Sraf {
456*2775Sraf int retval = XLATOR_NONFATAL;
457*2775Sraf int picky = Flags & XLATOR_PICKY_FLAG;
458*2775Sraf
459*2775Sraf seterrline(M.mi_line_number, M.mi_filename, "End", "");
460*2775Sraf errlog(TRACING, "xlator_end_if");
461*2775Sraf
462*2775Sraf if (Curfun == NULL) {
463*2775Sraf errlog(INPUT | ERROR, "Error: End without "
464*2775Sraf "matching Function or Data in file \"%s\"", Curfile);
465*2775Sraf goto cleanup;
466*2775Sraf }
467*2775Sraf
468*2775Sraf errlog(TRACING, "Interface=%s", Iface.IF_name);
469*2775Sraf
470*2775Sraf if (!Has_Version) {
471*2775Sraf if (picky) {
472*2775Sraf errlog(INPUT | ERROR, "Error: Interface has no "
473*2775Sraf "Version!\n\tInterface=%s\n\tSPEC File=%s",
474*2775Sraf Iface.IF_name, Curfile);
475*2775Sraf } else {
476*2775Sraf errlog(INPUT | WARNING, "Warning: Interface has "
477*2775Sraf "no Version!\n\tInterface=%s\n\tSPEC File=%s",
478*2775Sraf Iface.IF_name, Curfile);
479*2775Sraf retval = XLATOR_SUCCESS;
480*2775Sraf }
481*2775Sraf goto cleanup;
482*2775Sraf }
483*2775Sraf
484*2775Sraf if (Version_Arch & (~Supported_Arch)) {
485*2775Sraf errlog(INPUT | ERROR, "Error: Architectures in Version "
486*2775Sraf "line must be a subset of Architectures in Arch line\n"
487*2775Sraf "\tInterface=%s\n\tSPEC File=%s", Iface.IF_name, Curfile);
488*2775Sraf goto cleanup;
489*2775Sraf }
490*2775Sraf
491*2775Sraf if ((TargetArchToken & Supported_Arch) == 0) {
492*2775Sraf /*
493*2775Sraf * This interface is not for the architecture
494*2775Sraf * we are currently processing, so we skip it.
495*2775Sraf */
496*2775Sraf retval = XLATOR_SUCCESS;
497*2775Sraf goto cleanup;
498*2775Sraf }
499*2775Sraf
500*2775Sraf if (Iface.IF_version == NULL) {
501*2775Sraf if (picky) {
502*2775Sraf errlog(ERROR|INPUT,
503*2775Sraf "Error: Version was not found for "
504*2775Sraf "\"%s\" architecture\n\tInterface=%s",
505*2775Sraf TargetArchStr, Iface.IF_name);
506*2775Sraf } else {
507*2775Sraf errlog(WARNING | INPUT,
508*2775Sraf "Warning: Version was not found for "
509*2775Sraf "\"%s\" architecture\n\tInterface=%s",
510*2775Sraf TargetArchStr, Iface.IF_name);
511*2775Sraf retval = XLATOR_SUCCESS;
512*2775Sraf }
513*2775Sraf goto cleanup;
514*2775Sraf }
515*2775Sraf
516*2775Sraf /* check Iface.IF_type */
517*2775Sraf switch (Iface.IF_type) {
518*2775Sraf case FUNCTION:
519*2775Sraf errlog(VERBOSE, "Interface type = FUNCTION");
520*2775Sraf break;
521*2775Sraf case DATA:
522*2775Sraf errlog(VERBOSE, "Interface type = DATA");
523*2775Sraf break;
524*2775Sraf case NOTYPE:
525*2775Sraf errlog(WARNING,
526*2775Sraf "Warning: Interface is neither "
527*2775Sraf "DATA nor FUNCTION!!\n\t"
528*2775Sraf "Interface=%s\n\tSPEC File=%s",
529*2775Sraf Iface.IF_name, Curfile);
530*2775Sraf break;
531*2775Sraf default:
532*2775Sraf errlog(ERROR, "Error: Bad spec2map implementation!\n"
533*2775Sraf "\tInterface type is invalid\n"
534*2775Sraf "\tThis should never happen.\n"
535*2775Sraf "\tInterface=%s\tSPEC File=%s", Iface.IF_name, Curfile);
536*2775Sraf goto cleanup;
537*2775Sraf }
538*2775Sraf
539*2775Sraf (void) add_by_name(Iface.IF_version, &Iface);
540*2775Sraf
541*2775Sraf retval = XLATOR_SUCCESS;
542*2775Sraf
543*2775Sraf cleanup:
544*2775Sraf
545*2775Sraf /* cleanup */
546*2775Sraf Iface.IF_name = NULL;
547*2775Sraf
548*2775Sraf free(Iface.IF_version);
549*2775Sraf Iface.IF_version = NULL;
550*2775Sraf
551*2775Sraf free(Iface.IF_class);
552*2775Sraf Iface.IF_class = NULL;
553*2775Sraf
554*2775Sraf free(Curfun);
555*2775Sraf Curfun = NULL;
556*2775Sraf
557*2775Sraf Supported_Arch = XLATOR_ALLARCH;
558*2775Sraf return (retval);
559*2775Sraf }
560*2775Sraf
561*2775Sraf /*
562*2775Sraf * xlator_endfile()
563*2775Sraf * signal end of spec file
564*2775Sraf * returns: XLATOR_SUCCESS on success
565*2775Sraf * XLATOR_NONFATAL on error
566*2775Sraf */
567*2775Sraf int
xlator_endfile(void)568*2775Sraf xlator_endfile(void)
569*2775Sraf {
570*2775Sraf
571*2775Sraf errlog(TRACING, "xlator_endfile");
572*2775Sraf
573*2775Sraf Curfile = NULL;
574*2775Sraf
575*2775Sraf return (XLATOR_SUCCESS);
576*2775Sraf }
577*2775Sraf
578*2775Sraf /*
579*2775Sraf * xlator_endlib()
580*2775Sraf * signal end of library
581*2775Sraf * returns: XLATOR_SUCCESS on success
582*2775Sraf * XLATOR_NONFATAL on error
583*2775Sraf */
584*2775Sraf int
xlator_endlib(void)585*2775Sraf xlator_endlib(void)
586*2775Sraf {
587*2775Sraf FILE *mapfp;
588*2775Sraf int retval = XLATOR_SUCCESS;
589*2775Sraf
590*2775Sraf errlog(TRACING, "xlator_endlib");
591*2775Sraf
592*2775Sraf /* Pretend to print mapfile */
593*2775Sraf if (Verbosity >= TRACING) {
594*2775Sraf print_all_buckets();
595*2775Sraf }
596*2775Sraf
597*2775Sraf /* Everything read, now organize it! */
598*2775Sraf sort_buckets();
599*2775Sraf add_local();
600*2775Sraf
601*2775Sraf /* Create Output */
602*2775Sraf mapfp = fopen(OutputFile, "w");
603*2775Sraf if (mapfp == NULL) {
604*2775Sraf errlog(ERROR,
605*2775Sraf "Error: Unable to open output file \"%s\"\n\t%s",
606*2775Sraf OutputFile, strerror(errno));
607*2775Sraf retval = XLATOR_NONFATAL;
608*2775Sraf } else {
609*2775Sraf writemapfile(mapfp);
610*2775Sraf (void) fclose(mapfp);
611*2775Sraf }
612*2775Sraf
613*2775Sraf return (retval);
614*2775Sraf }
615*2775Sraf
616*2775Sraf /*
617*2775Sraf * xlator_end()
618*2775Sraf * signal end of translation
619*2775Sraf * returns: XLATOR_SUCCESS on success
620*2775Sraf * XLATOR_NONFATAL on error
621*2775Sraf */
622*2775Sraf int
xlator_end(void)623*2775Sraf xlator_end(void)
624*2775Sraf {
625*2775Sraf errlog(TRACING, "xlator_end");
626*2775Sraf
627*2775Sraf /* Destroy the list created by create_lists */
628*2775Sraf delete_lists();
629*2775Sraf
630*2775Sraf return (XLATOR_SUCCESS);
631*2775Sraf }
632*2775Sraf
633*2775Sraf /*
634*2775Sraf * getversion()
635*2775Sraf * called by xlator_take_kvpair when Version keyword is found
636*2775Sraf * parses the Version string and returns the one that matches
637*2775Sraf * the current target architecture
638*2775Sraf *
639*2775Sraf * the pointer returned by this function must be freed later.
640*2775Sraf */
641*2775Sraf static char *
getversion(const char * value)642*2775Sraf getversion(const char *value)
643*2775Sraf {
644*2775Sraf char *v, *p;
645*2775Sraf char arch[ARCHBUFLEN];
646*2775Sraf int archlen;
647*2775Sraf
648*2775Sraf /* up to ARCHBUFLEN-1 */
649*2775Sraf (void) strncpy(arch, TargetArchStr, ARCHBUFLEN-1);
650*2775Sraf arch[ARCHBUFLEN-2] = '\0';
651*2775Sraf (void) strcat(arch, "="); /* append an '=' */
652*2775Sraf archlen = strlen(arch);
653*2775Sraf
654*2775Sraf errlog(VERBOSE, "getversion: value=%s", value);
655*2775Sraf
656*2775Sraf if (strchr(value, '=') != NULL) {
657*2775Sraf if ((v = strstr(value, arch)) != NULL) {
658*2775Sraf p = strdup(v + archlen);
659*2775Sraf if (p == NULL) {
660*2775Sraf errlog(ERROR | FATAL,
661*2775Sraf "Internal Error: strdup() failure "
662*2775Sraf "in getversion()");
663*2775Sraf }
664*2775Sraf v = p;
665*2775Sraf while (!isspace(*v) && *v != '\0')
666*2775Sraf ++v;
667*2775Sraf *v = '\0';
668*2775Sraf } else {
669*2775Sraf errlog(VERBOSE, "getversion returns: NULL");
670*2775Sraf return (NULL);
671*2775Sraf }
672*2775Sraf } else {
673*2775Sraf p = strdup(value);
674*2775Sraf if (p == NULL) {
675*2775Sraf errlog(ERROR | FATAL, "Internal Error: strdup() "
676*2775Sraf "failure in getversion()");
677*2775Sraf }
678*2775Sraf }
679*2775Sraf
680*2775Sraf if (p != NULL)
681*2775Sraf errlog(VERBOSE, "getversion returns: %s", p);
682*2775Sraf else
683*2775Sraf errlog(VERBOSE, "getversion returns: NULL");
684*2775Sraf
685*2775Sraf return (p);
686*2775Sraf }
687*2775Sraf
688*2775Sraf /*
689*2775Sraf * getfilter()
690*2775Sraf * Called by xlator_take_kvpair when "filter" or "auxiliary" keyword is
691*2775Sraf * found. Parses the Filter/Auxiliary string and returns the one that
692*2775Sraf * matches the current target architecture
693*2775Sraf *
694*2775Sraf * The pointer returned by this function must be freed later.
695*2775Sraf *
696*2775Sraf * Note that returning NULL here indicates there was no desired
697*2775Sraf * arch=path item in value, i.e. for TargetArchStr the interface is
698*2775Sraf * not a filter.
699*2775Sraf */
700*2775Sraf static char *
getfilter(const char * value)701*2775Sraf getfilter(const char *value)
702*2775Sraf {
703*2775Sraf char *v, *p;
704*2775Sraf char arch[ARCHBUFLEN];
705*2775Sraf int archlen;
706*2775Sraf
707*2775Sraf /* up to ARCHBUFLEN-1 */
708*2775Sraf (void) strncpy(arch, TargetArchStr, ARCHBUFLEN-1);
709*2775Sraf arch[ARCHBUFLEN-2] = '\0';
710*2775Sraf (void) strcat(arch, "="); /* append an '=' */
711*2775Sraf archlen = strlen(arch);
712*2775Sraf
713*2775Sraf errlog(VERBOSE, "getfilter: value=%s", value);
714*2775Sraf
715*2775Sraf if (strchr(value, '=') != NULL) {
716*2775Sraf if ((v = strstr(value, arch)) != NULL) {
717*2775Sraf p = strdup(v + archlen);
718*2775Sraf if (p == NULL) {
719*2775Sraf errlog(ERROR | FATAL,
720*2775Sraf "Internal Error: strdup() failure "
721*2775Sraf "in getfilter()");
722*2775Sraf }
723*2775Sraf v = p;
724*2775Sraf while (!isspace(*v) && *v != '\0')
725*2775Sraf ++v;
726*2775Sraf *v = '\0';
727*2775Sraf } else {
728*2775Sraf errlog(VERBOSE, "getfilter returns: NULL");
729*2775Sraf return (NULL);
730*2775Sraf }
731*2775Sraf } else {
732*2775Sraf p = strdup(value);
733*2775Sraf if (p == NULL) {
734*2775Sraf errlog(ERROR | FATAL, "Internal Error: strdup() "
735*2775Sraf "failure in getfilter()");
736*2775Sraf }
737*2775Sraf }
738*2775Sraf
739*2775Sraf if (p != NULL)
740*2775Sraf errlog(VERBOSE, "getfilter returns: %s", p);
741*2775Sraf else
742*2775Sraf errlog(VERBOSE, "getfilter returns: NULL");
743*2775Sraf
744*2775Sraf return (p);
745*2775Sraf }
746*2775Sraf
747*2775Sraf /*
748*2775Sraf * version_sanity()
749*2775Sraf * for each version info in the Version line
750*2775Sraf * check for its validity.
751*2775Sraf * Set Version_arch to reflect all supported architectures if successful.
752*2775Sraf * Upon return on failure, subv will contain the last version string
753*2775Sraf * processed
754*2775Sraf * returns: VS_OK OK
755*2775Sraf * VS_INVARCH Invalid Architecture
756*2775Sraf * VS_INVVERS Invalid Version String
757*2775Sraf * VS_INVALID Both Version and Architecture are invalid;
758*2775Sraf */
759*2775Sraf static int
version_sanity(const char * value,char ** subv)760*2775Sraf version_sanity(const char *value, char **subv)
761*2775Sraf {
762*2775Sraf char *p, *v, *a;
763*2775Sraf int retval = VS_INVALID;
764*2775Sraf
765*2775Sraf if (strchr(value, '=')) {
766*2775Sraf /* Form 1: Version arch=Version_string */
767*2775Sraf v = strdup(value);
768*2775Sraf if (v == NULL) {
769*2775Sraf errlog(ERROR | FATAL,
770*2775Sraf "Internal Error: strdup() failure in "
771*2775Sraf "version_sanity()");
772*2775Sraf }
773*2775Sraf
774*2775Sraf /* process each arch=version string */
775*2775Sraf p = v;
776*2775Sraf while ((a = strtok(p, " \t\n"))) {
777*2775Sraf if ((retval = arch_version_sanity(a)) != VS_OK) {
778*2775Sraf *subv = strdup(a);
779*2775Sraf if (subv == NULL) {
780*2775Sraf errlog(ERROR | FATAL,
781*2775Sraf "Internal Error: strdup() failure "
782*2775Sraf "in version_sanity()");
783*2775Sraf }
784*2775Sraf break;
785*2775Sraf }
786*2775Sraf if ((retval = set_version_arch(a)) != VS_OK) {
787*2775Sraf /* set the global Version_arch */
788*2775Sraf *subv = strdup(a);
789*2775Sraf if (subv == NULL) {
790*2775Sraf errlog(ERROR | FATAL,
791*2775Sraf "Internal Error: strdup() failure "
792*2775Sraf "in version_sanity()");
793*2775Sraf }
794*2775Sraf break;
795*2775Sraf }
796*2775Sraf p = NULL;
797*2775Sraf }
798*2775Sraf free(v);
799*2775Sraf } else {
800*2775Sraf /* Form 2: Version Version_string */
801*2775Sraf if (valid_version(value)) {
802*2775Sraf retval = VS_OK;
803*2775Sraf } else {
804*2775Sraf *subv = strdup(value);
805*2775Sraf if (subv == NULL) {
806*2775Sraf errlog(ERROR | FATAL,
807*2775Sraf "Internal Error: strdup() failure "
808*2775Sraf "in version_sanity()");
809*2775Sraf }
810*2775Sraf }
811*2775Sraf }
812*2775Sraf return (retval);
813*2775Sraf }
814*2775Sraf
815*2775Sraf /*
816*2775Sraf * arch_version_sanity()
817*2775Sraf * checks version lines of the form "arch=version"
818*2775Sraf * av MUST be a string of the form "arch=version" (no spaces)
819*2775Sraf * returns: VS_OK OK
820*2775Sraf * VS_INVARCH Invalid Architecture
821*2775Sraf * VS_INVVERS Invalid Version String
822*2775Sraf * VS_INVALID Both Versions are invalid;
823*2775Sraf */
824*2775Sraf static int
arch_version_sanity(char * av)825*2775Sraf arch_version_sanity(char *av)
826*2775Sraf {
827*2775Sraf char *p, *v;
828*2775Sraf int retval = VS_OK;
829*2775Sraf
830*2775Sraf p = strchr(av, '=');
831*2775Sraf if (p == NULL) {
832*2775Sraf errlog(INPUT|ERROR, "Error: Incorrect format of Version line");
833*2775Sraf return (VS_INVALID);
834*2775Sraf }
835*2775Sraf
836*2775Sraf *p = '\0'; /* stick a '\0' where the '=' was */
837*2775Sraf v = p + 1;
838*2775Sraf
839*2775Sraf if (valid_arch(av) == 0)
840*2775Sraf retval = VS_INVARCH;
841*2775Sraf
842*2775Sraf if (valid_version(v) == 0)
843*2775Sraf retval += VS_INVVERS;
844*2775Sraf
845*2775Sraf *p = '='; /* restore the '=' */
846*2775Sraf
847*2775Sraf return (retval);
848*2775Sraf }
849*2775Sraf
850*2775Sraf /*
851*2775Sraf * writemapfile()
852*2775Sraf * called by xlator_endlib();
853*2775Sraf * writes out the map file
854*2775Sraf */
855*2775Sraf static void
writemapfile(FILE * mapfp)856*2775Sraf writemapfile(FILE *mapfp)
857*2775Sraf {
858*2775Sraf bucket_t *l; /* List of buckets. */
859*2775Sraf bucket_t *b; /* Bucket within list. */
860*2775Sraf struct bucketlist *bl;
861*2775Sraf table_t *t;
862*2775Sraf int i = 0, n = 0;
863*2775Sraf char **p;
864*2775Sraf
865*2775Sraf errlog(BEGIN, "writemapfile() {");
866*2775Sraf for (l = first_list(); l != NULL; l = next_list()) {
867*2775Sraf
868*2775Sraf for (b = first_from_list(l); b != NULL; b = next_from_list()) {
869*2775Sraf errlog(TRACING, "b_name = %s", b->b_name);
870*2775Sraf print_bucket(b); /* Debugging routine. */
871*2775Sraf
872*2775Sraf if (!b->b_was_printed) {
873*2775Sraf /* Ok, we can print it. */
874*2775Sraf b->b_was_printed = 1;
875*2775Sraf (void) fprintf(mapfp, "%s {\n", b->b_name);
876*2775Sraf
877*2775Sraf if (b->b_weak != 1) {
878*2775Sraf char *strtab;
879*2775Sraf
880*2775Sraf (void) fprintf(mapfp, " global:\n");
881*2775Sraf
882*2775Sraf strtab = get_stringtable(
883*2775Sraf b->b_global_table, 0);
884*2775Sraf
885*2775Sraf if (strtab == NULL) {
886*2775Sraf /*
887*2775Sraf * There were no interfaces
888*2775Sraf * in the bucket.
889*2775Sraf * Insert a dummy entry
890*2775Sraf * to avoid a "weak version"
891*2775Sraf */
892*2775Sraf (void) fprintf(mapfp,
893*2775Sraf "\t%s;\n", b->b_name);
894*2775Sraf }
895*2775Sraf } else {
896*2775Sraf (void) fprintf(mapfp,
897*2775Sraf " # Weak version\n");
898*2775Sraf }
899*2775Sraf /* Print all the interfaces in the bucket. */
900*2775Sraf t = b->b_global_table;
901*2775Sraf n = t->used;
902*2775Sraf
903*2775Sraf for (i = 0; i <= n; ++i) {
904*2775Sraf (void) fprintf(mapfp, "\t%s;\n",
905*2775Sraf get_stringtable(t, i));
906*2775Sraf }
907*2775Sraf
908*2775Sraf if (b->b_has_protecteds) {
909*2775Sraf t = b->b_protected_table;
910*2775Sraf n = t->used;
911*2775Sraf
912*2775Sraf (void) fprintf(mapfp,
913*2775Sraf " protected:\n");
914*2775Sraf
915*2775Sraf for (i = 0; i <= n; ++i) {
916*2775Sraf (void) fprintf(mapfp, "\t%s;\n",
917*2775Sraf get_stringtable(t, i));
918*2775Sraf }
919*2775Sraf }
920*2775Sraf
921*2775Sraf /* Conditionally add ``local: *;''. */
922*2775Sraf if (b->b_has_locals) {
923*2775Sraf (void) fprintf(mapfp,
924*2775Sraf " local:\n\t*;\n}");
925*2775Sraf } else {
926*2775Sraf (void) fprintf(mapfp, "}");
927*2775Sraf }
928*2775Sraf /* Print name of all parents. */
929*2775Sraf for (p = parents_of(b);
930*2775Sraf p != NULL && *p != '\0'; ++p) {
931*2775Sraf (void) fprintf(mapfp, " %s", *p);
932*2775Sraf }
933*2775Sraf bl = b->b_uncles;
934*2775Sraf while (bl != NULL) {
935*2775Sraf (void) fprintf(mapfp, " %s",
936*2775Sraf bl->bl_bucket->b_name);
937*2775Sraf bl = bl->bl_next;
938*2775Sraf }
939*2775Sraf
940*2775Sraf (void) fprintf(mapfp, ";\n\n");
941*2775Sraf } else {
942*2775Sraf /*
943*2775Sraf * We've printed this one before,
944*2775Sraf * so don't do it again.
945*2775Sraf */
946*2775Sraf /*EMPTY*/;
947*2775Sraf }
948*2775Sraf }
949*2775Sraf }
950*2775Sraf errlog(END, "}");
951*2775Sraf }
952*2775Sraf
953*2775Sraf /*
954*2775Sraf * set_version_arch ()
955*2775Sraf * input must be a string of the form "arch=version"
956*2775Sraf * turns on bits of global Version_Arch that correspond to the "arch"
957*2775Sraf * return VS_OK upon success
958*2775Sraf * VS_INVARCH if architecture is invalid
959*2775Sraf * EINVAL on other failure
960*2775Sraf */
961*2775Sraf static int
set_version_arch(const char * arch)962*2775Sraf set_version_arch(const char *arch)
963*2775Sraf {
964*2775Sraf char *a, *p;
965*2775Sraf int x;
966*2775Sraf int retval = EINVAL;
967*2775Sraf
968*2775Sraf if (arch == NULL)
969*2775Sraf return (retval);
970*2775Sraf
971*2775Sraf a = strdup(arch);
972*2775Sraf if (a == NULL) {
973*2775Sraf errlog(ERROR | FATAL,
974*2775Sraf "Internal Error: strdup() failure in "
975*2775Sraf "set_version_arch()");
976*2775Sraf }
977*2775Sraf
978*2775Sraf p = strchr(a, '=');
979*2775Sraf if (p) {
980*2775Sraf *p = '\0';
981*2775Sraf x = arch_strtoi(a);
982*2775Sraf if (x == 0) {
983*2775Sraf errlog(INPUT|ERROR,
984*2775Sraf "Error: Invalid architecture: %s", a);
985*2775Sraf retval = VS_INVARCH;
986*2775Sraf } else {
987*2775Sraf Version_Arch |= x;
988*2775Sraf retval = 0;
989*2775Sraf }
990*2775Sraf }
991*2775Sraf
992*2775Sraf free(a);
993*2775Sraf return (retval);
994*2775Sraf }
995*2775Sraf
996*2775Sraf /*
997*2775Sraf * set_supported_arch ()
998*2775Sraf * input must be a string listing the architectures to be supported
999*2775Sraf * turns on bits of global Supported_Arch that correspond to the architecture
1000*2775Sraf * return 0 upon success, EINVAL on failure
1001*2775Sraf */
1002*2775Sraf static int
set_supported_arch(const char * arch)1003*2775Sraf set_supported_arch(const char *arch)
1004*2775Sraf {
1005*2775Sraf char *a, *p, *tmp;
1006*2775Sraf int retval = EINVAL;
1007*2775Sraf
1008*2775Sraf if (arch == NULL || *arch == '\0')
1009*2775Sraf return (EINVAL);
1010*2775Sraf
1011*2775Sraf tmp = strdup(arch);
1012*2775Sraf if (tmp == NULL) {
1013*2775Sraf errlog(ERROR | FATAL, "Internal Error: strdup() failure in "
1014*2775Sraf "set_supported_arch()");
1015*2775Sraf }
1016*2775Sraf
1017*2775Sraf p = tmp;
1018*2775Sraf while ((a = strtok(p, " ,\t\n"))) {
1019*2775Sraf int x;
1020*2775Sraf x = arch_strtoi(a);
1021*2775Sraf if (x == 0) {
1022*2775Sraf errlog(INPUT|ERROR,
1023*2775Sraf "Error: Invalid architecture: %s", a);
1024*2775Sraf free(tmp);
1025*2775Sraf return (EINVAL);
1026*2775Sraf }
1027*2775Sraf Supported_Arch |= x;
1028*2775Sraf retval = 0;
1029*2775Sraf p = NULL;
1030*2775Sraf }
1031*2775Sraf
1032*2775Sraf free(tmp);
1033*2775Sraf return (retval);
1034*2775Sraf }
1035