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