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