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