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 2004 Sun Microsystems, Inc. All rights reserved.
24*753d2d2eSraf * Use is subject to license terms.
25*753d2d2eSraf */
26*753d2d2eSraf
27*753d2d2eSraf #include <stdio.h>
28*753d2d2eSraf #include <ctype.h>
29*753d2d2eSraf #include <stdlib.h>
30*753d2d2eSraf #include <unistd.h>
31*753d2d2eSraf #include <string.h>
32*753d2d2eSraf #include <dlfcn.h>
33*753d2d2eSraf #include <dirent.h>
34*753d2d2eSraf #include <libgen.h>
35*753d2d2eSraf #include <sys/param.h>
36*753d2d2eSraf #include <errno.h>
37*753d2d2eSraf
38*753d2d2eSraf #include "parser.h"
39*753d2d2eSraf #include "errlog.h"
40*753d2d2eSraf
41*753d2d2eSraf static char const *ARCH_I386 = "i386";
42*753d2d2eSraf static char const *ARCH_SPARC = "sparc";
43*753d2d2eSraf static char const *ARCH_SPARCV9 = "sparcv9";
44*753d2d2eSraf static char const *ARCH_IA64 = "ia64";
45*753d2d2eSraf static char const *ARCH_AMD64 = "amd64";
46*753d2d2eSraf static char const *ARCH_ALL = "all";
47*753d2d2eSraf
48*753d2d2eSraf static int dofiles(const Translator_info *);
49*753d2d2eSraf static int read_spec(const Translator_info *, char *);
50*753d2d2eSraf
51*753d2d2eSraf static int Curlineno;
52*753d2d2eSraf
53*753d2d2eSraf xlator_keyword_t *keywordlist;
54*753d2d2eSraf
55*753d2d2eSraf /*
56*753d2d2eSraf * frontend entry point
57*753d2d2eSraf * returns the number of errors encountered
58*753d2d2eSraf */
59*753d2d2eSraf int
frontend(const Translator_info * T_info)60*753d2d2eSraf frontend(const Translator_info *T_info)
61*753d2d2eSraf {
62*753d2d2eSraf int retval, i = 0, errors = 0;
63*753d2d2eSraf
64*753d2d2eSraf keywordlist = xlator_init(T_info);
65*753d2d2eSraf if (keywordlist == NULL) {
66*753d2d2eSraf errlog(ERROR, "Error: Unable to get keywordlist\n");
67*753d2d2eSraf return (1);
68*753d2d2eSraf }
69*753d2d2eSraf
70*753d2d2eSraf if (T_info->ti_verbosity >= STATUS) {
71*753d2d2eSraf errlog(STATUS, "interesting keywords:\n");
72*753d2d2eSraf while (keywordlist[i].key != NULL) {
73*753d2d2eSraf errlog(STATUS, "\t%s\n", keywordlist[i].key);
74*753d2d2eSraf ++i;
75*753d2d2eSraf };
76*753d2d2eSraf }
77*753d2d2eSraf
78*753d2d2eSraf retval = xlator_startlib(T_info->ti_liblist);
79*753d2d2eSraf switch (retval) {
80*753d2d2eSraf case XLATOR_SKIP:
81*753d2d2eSraf if (T_info->ti_verbosity >= STATUS)
82*753d2d2eSraf errlog(STATUS, "Skipping %s\n", T_info->ti_liblist);
83*753d2d2eSraf retval = 0;
84*753d2d2eSraf break;
85*753d2d2eSraf
86*753d2d2eSraf case XLATOR_NONFATAL:
87*753d2d2eSraf ++errors;
88*753d2d2eSraf retval = 0;
89*753d2d2eSraf break;
90*753d2d2eSraf
91*753d2d2eSraf case XLATOR_SUCCESS:
92*753d2d2eSraf retval = dofiles(T_info);
93*753d2d2eSraf errors += retval;
94*753d2d2eSraf if ((retval = xlator_endlib()) != XLATOR_SUCCESS)
95*753d2d2eSraf ++errors;
96*753d2d2eSraf retval = 0;
97*753d2d2eSraf break;
98*753d2d2eSraf
99*753d2d2eSraf default:
100*753d2d2eSraf errlog(ERROR | FATAL,
101*753d2d2eSraf "Error: Invalid return code from xlator_startlib()\n");
102*753d2d2eSraf exit(1);
103*753d2d2eSraf }
104*753d2d2eSraf
105*753d2d2eSraf if ((retval = xlator_end()) != XLATOR_SUCCESS)
106*753d2d2eSraf ++errors;
107*753d2d2eSraf
108*753d2d2eSraf return (errors);
109*753d2d2eSraf }
110*753d2d2eSraf
111*753d2d2eSraf /*
112*753d2d2eSraf * dofiles(const Translator_info *T_info);
113*753d2d2eSraf * iterate through files specified in the command line and process
114*753d2d2eSraf * them one by one
115*753d2d2eSraf * requires spec files to have a ".spec" suffix
116*753d2d2eSraf * returns the number of errors;
117*753d2d2eSraf */
118*753d2d2eSraf static int
dofiles(const Translator_info * T_info)119*753d2d2eSraf dofiles(const Translator_info *T_info)
120*753d2d2eSraf {
121*753d2d2eSraf int nfiles, flen, findex, retval = 0, errors = 0;
122*753d2d2eSraf
123*753d2d2eSraf nfiles = T_info->ti_nfiles;
124*753d2d2eSraf
125*753d2d2eSraf for (findex = 0; findex < nfiles; ++findex) {
126*753d2d2eSraf flen = strlen(filelist[findex]);
127*753d2d2eSraf if ((flen <= 5) ||
128*753d2d2eSraf strcmp(&filelist[findex][flen-5], ".spec") != 0) {
129*753d2d2eSraf errlog(ERROR,
130*753d2d2eSraf "Error: File specified does not have the "
131*753d2d2eSraf ".spec extension: %s\n", filelist[findex]);
132*753d2d2eSraf ++errors;
133*753d2d2eSraf continue;
134*753d2d2eSraf };
135*753d2d2eSraf retval = read_spec(T_info, filelist[findex]);
136*753d2d2eSraf errors += retval;
137*753d2d2eSraf }
138*753d2d2eSraf return (errors);
139*753d2d2eSraf }
140*753d2d2eSraf
141*753d2d2eSraf /*
142*753d2d2eSraf * read_spec -
143*753d2d2eSraf * Given a filename, this function will reads the spec file to
144*753d2d2eSraf * recognize keywords which it passes along with the corresponding
145*753d2d2eSraf * value to the back-end translator to process. The following
146*753d2d2eSraf * back-end interfaces are called:
147*753d2d2eSraf * xlator_startfile
148*753d2d2eSraf * xlator_start_if
149*753d2d2eSraf * xlator_take_kvpair
150*753d2d2eSraf * xlator_end_if
151*753d2d2eSraf * xlator_endfile
152*753d2d2eSraf */
153*753d2d2eSraf static int
read_spec(const Translator_info * T_info,char * spec_filename)154*753d2d2eSraf read_spec(const Translator_info *T_info, char *spec_filename)
155*753d2d2eSraf {
156*753d2d2eSraf FILE *spec_fp;
157*753d2d2eSraf Meta_info meta_info;
158*753d2d2eSraf char key[BUFSIZ], *value = NULL, *p = NULL;
159*753d2d2eSraf char *buf2 = NULL;
160*753d2d2eSraf int retval = 0, errors = 0, ki = 0; /* keyword indicator */
161*753d2d2eSraf int start_if_fail = 0, skip_if = 0;
162*753d2d2eSraf int extends_err = 0;
163*753d2d2eSraf
164*753d2d2eSraf meta_info.mi_ext_cnt = 0; /* All info is non-extends */
165*753d2d2eSraf meta_info.mi_flags = 0;
166*753d2d2eSraf
167*753d2d2eSraf retval = xlator_startfile(spec_filename);
168*753d2d2eSraf
169*753d2d2eSraf switch (retval) {
170*753d2d2eSraf case XLATOR_SKIP:
171*753d2d2eSraf if (T_info->ti_verbosity >= WARNING)
172*753d2d2eSraf errlog(WARNING, "Warning: Skipping %s\n",
173*753d2d2eSraf spec_filename);
174*753d2d2eSraf return (errors);
175*753d2d2eSraf
176*753d2d2eSraf case XLATOR_NONFATAL:
177*753d2d2eSraf errlog(ERROR, "Error in xlator_startfile\n");
178*753d2d2eSraf ++errors;
179*753d2d2eSraf return (errors);
180*753d2d2eSraf
181*753d2d2eSraf case XLATOR_SUCCESS:
182*753d2d2eSraf break;
183*753d2d2eSraf
184*753d2d2eSraf default:
185*753d2d2eSraf errlog(ERROR,
186*753d2d2eSraf "Error: Invalid return code from xlator_startfile()\n");
187*753d2d2eSraf ++errors;
188*753d2d2eSraf return (errors);
189*753d2d2eSraf };
190*753d2d2eSraf
191*753d2d2eSraf /* file processing */
192*753d2d2eSraf spec_fp = fopen(spec_filename, "r");
193*753d2d2eSraf if (spec_fp == NULL) {
194*753d2d2eSraf errlog(ERROR, "Error: Unable to open spec file %s: %s\n",
195*753d2d2eSraf spec_filename, strerror(errno));
196*753d2d2eSraf ++errors;
197*753d2d2eSraf return (errors);
198*753d2d2eSraf }
199*753d2d2eSraf
200*753d2d2eSraf (void) strncpy(meta_info.mi_filename, spec_filename, BUFSIZ);
201*753d2d2eSraf meta_info.mi_line_number = 0;
202*753d2d2eSraf Curlineno = meta_info.mi_line_number;
203*753d2d2eSraf while (meta_info.mi_nlines = readline(&buf2, spec_fp)) {
204*753d2d2eSraf meta_info.mi_line_number += meta_info.mi_nlines;
205*753d2d2eSraf Curlineno = meta_info.mi_line_number;
206*753d2d2eSraf if (!non_empty(buf2)) {
207*753d2d2eSraf free(buf2);
208*753d2d2eSraf buf2 = NULL;
209*753d2d2eSraf continue;
210*753d2d2eSraf }
211*753d2d2eSraf p = realloc(value, sizeof (char)*(strlen(buf2)+1));
212*753d2d2eSraf if (p == NULL) {
213*753d2d2eSraf errlog(ERROR | FATAL,
214*753d2d2eSraf "Error: Unable to allocate memory for "
215*753d2d2eSraf "value: %d\n", errno);
216*753d2d2eSraf }
217*753d2d2eSraf value = p;
218*753d2d2eSraf split(buf2, key, value);
219*753d2d2eSraf ki = interesting_keyword(keywordlist, key);
220*753d2d2eSraf switch (ki) {
221*753d2d2eSraf case XLATOR_KW_FUNC: /* Function keyword */
222*753d2d2eSraf case XLATOR_KW_DATA: /* Data keyword */
223*753d2d2eSraf meta_info.mi_extended = 0;
224*753d2d2eSraf retval = xlator_start_if(meta_info, ki, value);
225*753d2d2eSraf switch (retval) {
226*753d2d2eSraf case XLATOR_FATAL: /* FATAL ERROR */
227*753d2d2eSraf if (T_info->ti_verbosity >= STATUS) {
228*753d2d2eSraf errlog(STATUS,
229*753d2d2eSraf "Error in xlator_start_if: ");
230*753d2d2eSraf }
231*753d2d2eSraf ++errors;
232*753d2d2eSraf return (errors);
233*753d2d2eSraf case XLATOR_NONFATAL: /* NON-FATAL ERROR */
234*753d2d2eSraf if (T_info->ti_verbosity >= STATUS)
235*753d2d2eSraf errlog(STATUS,
236*753d2d2eSraf "Error in xlator_start_if\n");
237*753d2d2eSraf ++errors;
238*753d2d2eSraf start_if_fail = 1;
239*753d2d2eSraf break;
240*753d2d2eSraf case XLATOR_SUCCESS: /* OK */
241*753d2d2eSraf start_if_fail = 0;
242*753d2d2eSraf extends_err = check4extends(spec_filename,
243*753d2d2eSraf value, T_info->ti_archtoken, spec_fp);
244*753d2d2eSraf switch (extends_err) {
245*753d2d2eSraf case -1: /* Error */
246*753d2d2eSraf errlog(ERROR, "\"%s\", line %d: "
247*753d2d2eSraf "Error occurred while "
248*753d2d2eSraf "checking for extends clause\n",
249*753d2d2eSraf spec_filename, Curlineno);
250*753d2d2eSraf ++errors;
251*753d2d2eSraf /*FALLTHRU*/
252*753d2d2eSraf case 0: /* No Extends */
253*753d2d2eSraf break;
254*753d2d2eSraf case 1: /* Extends */
255*753d2d2eSraf meta_info.mi_extended = 1;
256*753d2d2eSraf extends_err = do_extends(meta_info,
257*753d2d2eSraf T_info, value);
258*753d2d2eSraf if (extends_err) {
259*753d2d2eSraf errors += extends_err;
260*753d2d2eSraf }
261*753d2d2eSraf break;
262*753d2d2eSraf default: /* Programmer Error */
263*753d2d2eSraf errlog(ERROR | FATAL,
264*753d2d2eSraf "Error: invalid return from "
265*753d2d2eSraf "check4extends %d\n", extends_err);
266*753d2d2eSraf }
267*753d2d2eSraf break;
268*753d2d2eSraf case XLATOR_SKIP: /* SKIP */
269*753d2d2eSraf if (T_info->ti_verbosity >= WARNING)
270*753d2d2eSraf errlog(WARNING, "Warning: Skipping "
271*753d2d2eSraf "interface %s\n", value);
272*753d2d2eSraf skip_if = 1;
273*753d2d2eSraf start_if_fail = 0;
274*753d2d2eSraf break;
275*753d2d2eSraf default:
276*753d2d2eSraf /* Invalid Return */
277*753d2d2eSraf errlog(ERROR | FATAL,
278*753d2d2eSraf "Error: Invalid return code "
279*753d2d2eSraf "from xlator_start_if (): %d\n", retval);
280*753d2d2eSraf }
281*753d2d2eSraf break;
282*753d2d2eSraf case XLATOR_KW_END: /* END keyword */
283*753d2d2eSraf if (start_if_fail == 0 && skip_if == 0) {
284*753d2d2eSraf retval = xlator_end_if(meta_info, value);
285*753d2d2eSraf if (retval)
286*753d2d2eSraf ++errors;
287*753d2d2eSraf }
288*753d2d2eSraf skip_if = 0;
289*753d2d2eSraf break;
290*753d2d2eSraf case XLATOR_KW_NOTFOUND:
291*753d2d2eSraf if (T_info->ti_verbosity >= TRACING)
292*753d2d2eSraf errlog(TRACING, "uninteresting keyword: %s\n",
293*753d2d2eSraf key);
294*753d2d2eSraf break;
295*753d2d2eSraf default:
296*753d2d2eSraf if (skip_if == 0 && start_if_fail == 0) {
297*753d2d2eSraf retval = xlator_take_kvpair(meta_info,
298*753d2d2eSraf ki, value);
299*753d2d2eSraf if (retval) {
300*753d2d2eSraf if (T_info->ti_verbosity >= STATUS)
301*753d2d2eSraf errlog(STATUS, "Error in "
302*753d2d2eSraf "xlator_take_kvpair\n");
303*753d2d2eSraf ++errors;
304*753d2d2eSraf }
305*753d2d2eSraf }
306*753d2d2eSraf }
307*753d2d2eSraf free(buf2);
308*753d2d2eSraf buf2 = NULL;
309*753d2d2eSraf }
310*753d2d2eSraf
311*753d2d2eSraf if ((retval = xlator_endfile()) != XLATOR_SUCCESS) {
312*753d2d2eSraf if (T_info->ti_verbosity >= STATUS)
313*753d2d2eSraf errlog(STATUS, "Error in xlator_endfile\n");
314*753d2d2eSraf ++errors;
315*753d2d2eSraf }
316*753d2d2eSraf free(p);
317*753d2d2eSraf (void) fclose(spec_fp);
318*753d2d2eSraf return (errors);
319*753d2d2eSraf }
320*753d2d2eSraf
321*753d2d2eSraf /*
322*753d2d2eSraf * interesting_keyword(char **keywordlist, const char *key) {
323*753d2d2eSraf * returns the token associated with key if key is found in keywordlist
324*753d2d2eSraf * returns XLATOR_KW_NOTFOUND if key is NOT found in keywordlist
325*753d2d2eSraf * "Function" and "End" are always interesting, return XLATOR_KW_FUNC
326*753d2d2eSraf * and XLATOR_KW_DATA respectively;
327*753d2d2eSraf * "End" is always interesting, return XLATOR_KW_END;
328*753d2d2eSraf *
329*753d2d2eSraf */
330*753d2d2eSraf int
interesting_keyword(xlator_keyword_t * keywordlist,const char * key)331*753d2d2eSraf interesting_keyword(xlator_keyword_t *keywordlist, const char *key)
332*753d2d2eSraf {
333*753d2d2eSraf int i = 0;
334*753d2d2eSraf
335*753d2d2eSraf if (strcasecmp(key, "data") == 0) {
336*753d2d2eSraf return (XLATOR_KW_DATA);
337*753d2d2eSraf }
338*753d2d2eSraf if (strcasecmp(key, "function") == 0) {
339*753d2d2eSraf return (XLATOR_KW_FUNC);
340*753d2d2eSraf }
341*753d2d2eSraf
342*753d2d2eSraf if (strcasecmp(key, "end") == 0)
343*753d2d2eSraf return (XLATOR_KW_END);
344*753d2d2eSraf
345*753d2d2eSraf while (keywordlist[i].key != NULL) {
346*753d2d2eSraf if (strcasecmp(keywordlist[i].key, key) == 0)
347*753d2d2eSraf return (keywordlist[i].token);
348*753d2d2eSraf ++i;
349*753d2d2eSraf }
350*753d2d2eSraf return (XLATOR_KW_NOTFOUND);
351*753d2d2eSraf }
352*753d2d2eSraf
353*753d2d2eSraf /*
354*753d2d2eSraf * line_to_buf(char *dest, const char *src) {
355*753d2d2eSraf * appends src to dest, dynamically increasing the size of dest.
356*753d2d2eSraf * replaces the trailing '\' continuation character with a space.
357*753d2d2eSraf *
358*753d2d2eSraf * if src is continuation of dest, dest != NULL, and
359*753d2d2eSraf * the last character in dest before the newline must be a `\'
360*753d2d2eSraf * if src is not continuation of dest, then dest must be NULL
361*753d2d2eSraf */
362*753d2d2eSraf char *
line_to_buf(char * dest,const char * src)363*753d2d2eSraf line_to_buf(char *dest, const char *src)
364*753d2d2eSraf {
365*753d2d2eSraf int slen = strlen(src);
366*753d2d2eSraf int dlen;
367*753d2d2eSraf
368*753d2d2eSraf if (dest == NULL) {
369*753d2d2eSraf /* We're being called for the first time */
370*753d2d2eSraf dest = malloc(sizeof (char) * (slen + 1));
371*753d2d2eSraf if (dest == NULL) {
372*753d2d2eSraf errlog(ERROR | FATAL,
373*753d2d2eSraf "Error: Unable to allocate memory for dest\n");
374*753d2d2eSraf }
375*753d2d2eSraf (void) strcpy(dest, src);
376*753d2d2eSraf return (dest);
377*753d2d2eSraf }
378*753d2d2eSraf
379*753d2d2eSraf dlen = strlen(dest);
380*753d2d2eSraf
381*753d2d2eSraf dest = realloc(dest, (size_t)(sizeof (char) * (dlen+slen+1)));
382*753d2d2eSraf if (dest == NULL) {
383*753d2d2eSraf errlog(ERROR | FATAL,
384*753d2d2eSraf "Error: Unable to allocate memory for dest\n");
385*753d2d2eSraf }
386*753d2d2eSraf
387*753d2d2eSraf if (dlen > 1) {
388*753d2d2eSraf /*
389*753d2d2eSraf * remove continuation character
390*753d2d2eSraf * we replace the '\' from the previous line with a space
391*753d2d2eSraf */
392*753d2d2eSraf if (dest[dlen-2] == '\\') {
393*753d2d2eSraf dest[dlen-2] = ' ';
394*753d2d2eSraf }
395*753d2d2eSraf }
396*753d2d2eSraf
397*753d2d2eSraf /* join the two strings */
398*753d2d2eSraf (void) strcat(dest, src);
399*753d2d2eSraf
400*753d2d2eSraf return (dest);
401*753d2d2eSraf }
402*753d2d2eSraf
403*753d2d2eSraf /*
404*753d2d2eSraf * non_empty(const char *str)
405*753d2d2eSraf * assumes str is non null
406*753d2d2eSraf * checks if str is a non empty string
407*753d2d2eSraf * returns 1 if string contains non whitespace
408*753d2d2eSraf * returns 0 if string contains only whitespace
409*753d2d2eSraf */
410*753d2d2eSraf int
non_empty(const char * str)411*753d2d2eSraf non_empty(const char *str)
412*753d2d2eSraf {
413*753d2d2eSraf while (*str != '\0') {
414*753d2d2eSraf if (!isspace(*str))
415*753d2d2eSraf return (1);
416*753d2d2eSraf ++str;
417*753d2d2eSraf };
418*753d2d2eSraf return (0);
419*753d2d2eSraf }
420*753d2d2eSraf
421*753d2d2eSraf /*
422*753d2d2eSraf * split(const char *line, char *key, char *value);
423*753d2d2eSraf * splits the line into keyword (key) and value pair
424*753d2d2eSraf */
425*753d2d2eSraf void
split(const char * line,char * key,char * value)426*753d2d2eSraf split(const char *line, char *key, char *value)
427*753d2d2eSraf {
428*753d2d2eSraf char *p;
429*753d2d2eSraf
430*753d2d2eSraf p = (char *)line;
431*753d2d2eSraf
432*753d2d2eSraf /* skip leading whitespace */
433*753d2d2eSraf while (isspace(*p)&& *p != '\0')
434*753d2d2eSraf ++p;
435*753d2d2eSraf
436*753d2d2eSraf /* copy keyword from line into key */
437*753d2d2eSraf while (!isspace(*p) && *p != '\0')
438*753d2d2eSraf *key++ = *p++;
439*753d2d2eSraf
440*753d2d2eSraf *key = '\0';
441*753d2d2eSraf
442*753d2d2eSraf /* skip whitespace */
443*753d2d2eSraf while (isspace(*p) && *p != '\0')
444*753d2d2eSraf p++;
445*753d2d2eSraf
446*753d2d2eSraf (void) strcpy(value, p);
447*753d2d2eSraf
448*753d2d2eSraf }
449*753d2d2eSraf
450*753d2d2eSraf /*
451*753d2d2eSraf * check4extends(char *filename, char *value, int arch, FILE *fp)
452*753d2d2eSraf * if no arch keyword is found or there is a MATCHING arch keyword
453*753d2d2eSraf * returns 1 if value is of the form "data|function name extends"
454*753d2d2eSraf * -1 for error
455*753d2d2eSraf * 0 no other keyword after the function name
456*753d2d2eSraf * else
457*753d2d2eSraf * return 0
458*753d2d2eSraf *
459*753d2d2eSraf * filename is used only for error reporting
460*753d2d2eSraf */
461*753d2d2eSraf int
check4extends(const char * filename,const char * value,int arch,FILE * fp)462*753d2d2eSraf check4extends(const char *filename, const char *value, int arch, FILE *fp)
463*753d2d2eSraf {
464*753d2d2eSraf char fun[BUFSIZ];
465*753d2d2eSraf char extends[BUFSIZ];
466*753d2d2eSraf int n;
467*753d2d2eSraf
468*753d2d2eSraf if (arch_match(fp, arch)) {
469*753d2d2eSraf split(value, fun, extends);
470*753d2d2eSraf n = strlen(extends);
471*753d2d2eSraf if (extends[n-1] == '\n')
472*753d2d2eSraf extends[n-1] = '\0';
473*753d2d2eSraf if (strncasecmp("extends", extends, 7) == 0) {
474*753d2d2eSraf return (1);
475*753d2d2eSraf } else {
476*753d2d2eSraf if (*extends != '\0') {
477*753d2d2eSraf errlog(ERROR, "\"%s\", line %d: Error: "
478*753d2d2eSraf "Trailing garbage after function name\n",
479*753d2d2eSraf filename, Curlineno);
480*753d2d2eSraf return (-1);
481*753d2d2eSraf }
482*753d2d2eSraf }
483*753d2d2eSraf }
484*753d2d2eSraf return (0);
485*753d2d2eSraf }
486*753d2d2eSraf
487*753d2d2eSraf /*
488*753d2d2eSraf * remcomment (char *buf)
489*753d2d2eSraf * replace comments with single whitespace
490*753d2d2eSraf */
491*753d2d2eSraf /* XXX: There is currently no way to escape a comment character */
492*753d2d2eSraf void
remcomment(char const * buf)493*753d2d2eSraf remcomment(char const *buf)
494*753d2d2eSraf {
495*753d2d2eSraf char *p;
496*753d2d2eSraf p = strchr(buf, '#');
497*753d2d2eSraf if (p) {
498*753d2d2eSraf *p = ' ';
499*753d2d2eSraf *(p+1) = '\0';
500*753d2d2eSraf }
501*753d2d2eSraf }
502*753d2d2eSraf
503*753d2d2eSraf /*
504*753d2d2eSraf * arch_strtoi()
505*753d2d2eSraf *
506*753d2d2eSraf * input: string
507*753d2d2eSraf * return: XLATOR_I386 if string == ARCH_I386
508*753d2d2eSraf * XLATOR_SPARC if string == ARCH_SPARC
509*753d2d2eSraf * XLATOR_SPARCV9 if string == ARCH_SPARCV9
510*753d2d2eSraf * XLATOR_IA64 if string == ARCH_IA64
511*753d2d2eSraf * XLATOR_AMD64 if string == ARCH_AMD64
512*753d2d2eSraf * XLATOR_ALLARCH if string == ARCH_ALL
513*753d2d2eSraf * 0 if outside the known set {i386, sparc, sparcv9, ia64, amd64}.
514*753d2d2eSraf */
515*753d2d2eSraf int
arch_strtoi(const char * arch_str)516*753d2d2eSraf arch_strtoi(const char *arch_str)
517*753d2d2eSraf {
518*753d2d2eSraf if (arch_str != NULL) {
519*753d2d2eSraf if (strcmp(arch_str, ARCH_I386) == 0)
520*753d2d2eSraf return (XLATOR_I386);
521*753d2d2eSraf else if (strcmp(arch_str, ARCH_SPARC) == 0)
522*753d2d2eSraf return (XLATOR_SPARC);
523*753d2d2eSraf else if (strcmp(arch_str, ARCH_SPARCV9) == 0)
524*753d2d2eSraf return (XLATOR_SPARCV9);
525*753d2d2eSraf else if (strcmp(arch_str, ARCH_IA64) == 0)
526*753d2d2eSraf return (XLATOR_IA64);
527*753d2d2eSraf else if (strcmp(arch_str, ARCH_AMD64) == 0)
528*753d2d2eSraf return (XLATOR_AMD64);
529*753d2d2eSraf else if (strcmp(arch_str, ARCH_ALL) == 0)
530*753d2d2eSraf return (XLATOR_ALLARCH);
531*753d2d2eSraf } else {
532*753d2d2eSraf errlog(ERROR, "\"%s\", line %d: Error: "
533*753d2d2eSraf "arch keyword with no value");
534*753d2d2eSraf }
535*753d2d2eSraf return (0);
536*753d2d2eSraf }
537*753d2d2eSraf
538*753d2d2eSraf int
readline(char ** buffer,FILE * fp)539*753d2d2eSraf readline(char **buffer, FILE *fp)
540*753d2d2eSraf {
541*753d2d2eSraf int nlines = 0;
542*753d2d2eSraf int len;
543*753d2d2eSraf char buf[BUFSIZ];
544*753d2d2eSraf
545*753d2d2eSraf if (fgets(buf, BUFSIZ, fp)) {
546*753d2d2eSraf nlines++;
547*753d2d2eSraf /* replace comments with single whitespace */
548*753d2d2eSraf remcomment(buf);
549*753d2d2eSraf
550*753d2d2eSraf /* get complete line */
551*753d2d2eSraf *buffer = line_to_buf(*buffer, buf); /* append buf to buffer */
552*753d2d2eSraf len = strlen(buf);
553*753d2d2eSraf if (len > 1) {
554*753d2d2eSraf /* handle continuation lines */
555*753d2d2eSraf while (buf[len-2] == '\\') {
556*753d2d2eSraf if (!fgets(buf, BUFSIZ, fp)) {
557*753d2d2eSraf *buffer = line_to_buf(*buffer, buf);
558*753d2d2eSraf break;
559*753d2d2eSraf }
560*753d2d2eSraf nlines++;
561*753d2d2eSraf len = strlen(buf);
562*753d2d2eSraf *buffer = line_to_buf(*buffer, buf);
563*753d2d2eSraf }
564*753d2d2eSraf } /* end of 'get complete line' */
565*753d2d2eSraf }
566*753d2d2eSraf return (nlines);
567*753d2d2eSraf }
568