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