17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  *  Back-end functions for spec to mapfile converter
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #include <stdio.h>
327c478bd9Sstevel@tonic-gate #include <stdlib.h>
337c478bd9Sstevel@tonic-gate #include <ctype.h>
347c478bd9Sstevel@tonic-gate #include <string.h>
357c478bd9Sstevel@tonic-gate #include <errno.h>
367c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
377c478bd9Sstevel@tonic-gate #include "xlator.h"
387c478bd9Sstevel@tonic-gate #include "util.h"
397c478bd9Sstevel@tonic-gate #include "bucket.h"
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate /* Globals */
427c478bd9Sstevel@tonic-gate enum {
437c478bd9Sstevel@tonic-gate 	/* These first four (commented out) are defined in parser.h */
447c478bd9Sstevel@tonic-gate 	/* XLATOR_KW_NOTFOUND = 0, */
457c478bd9Sstevel@tonic-gate 	/* XLATOR_KW_FUNC, */
467c478bd9Sstevel@tonic-gate 	/* XLATOR_KW_DATA, */
477c478bd9Sstevel@tonic-gate 	/* XLATOR_KW_END, */
487c478bd9Sstevel@tonic-gate 	XLATOR_KW_VERSION = 4,
497c478bd9Sstevel@tonic-gate 	XLATOR_KW_ARCH,
507c478bd9Sstevel@tonic-gate 	XLATOR_KW_BINDING,
517c478bd9Sstevel@tonic-gate 	XLATOR_KW_FILTER,
527c478bd9Sstevel@tonic-gate 	XLATOR_KW_AUXILIARY
537c478bd9Sstevel@tonic-gate };
547c478bd9Sstevel@tonic-gate #define	FIRST_TOKEN 4	/* Must match the first token in the enum above */
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate static xlator_keyword_t Keywords[] = {
577c478bd9Sstevel@tonic-gate 	{ "version", XLATOR_KW_VERSION },
587c478bd9Sstevel@tonic-gate 	{ "arch", XLATOR_KW_ARCH },
597c478bd9Sstevel@tonic-gate 	{ "binding", XLATOR_KW_BINDING },
607c478bd9Sstevel@tonic-gate 	{ "filter", XLATOR_KW_FILTER },
617c478bd9Sstevel@tonic-gate 	{ "auxiliary", XLATOR_KW_AUXILIARY },
627c478bd9Sstevel@tonic-gate 	{ NULL, XLATOR_KW_NOTFOUND }
637c478bd9Sstevel@tonic-gate };
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate static char	const *OutputFile;
667c478bd9Sstevel@tonic-gate static char	const *Curfile;
677c478bd9Sstevel@tonic-gate static char	*Curfun;
687c478bd9Sstevel@tonic-gate static int	Curline;
697c478bd9Sstevel@tonic-gate static Interface Iface;
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate static int  Verbosity;
727c478bd9Sstevel@tonic-gate static int  TargetArchToken;		/* set from -a option to front-end */
737c478bd9Sstevel@tonic-gate char *TargetArchStr = NULL;		/* from -a option to front-end */
747c478bd9Sstevel@tonic-gate int IsFilterLib = 0;			/* set from -F option to front-end */
757c478bd9Sstevel@tonic-gate static int  Supported_Arch = XLATOR_ALLARCH;	/* from "Arch" SPEC keyword */
767c478bd9Sstevel@tonic-gate static int	Flags;
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate /*
797c478bd9Sstevel@tonic-gate  * WHAT!?
807c478bd9Sstevel@tonic-gate  * from Version line
817c478bd9Sstevel@tonic-gate  * 0 means architecture is not specified in the
827c478bd9Sstevel@tonic-gate  * version line so it applies to all versions
837c478bd9Sstevel@tonic-gate  */
847c478bd9Sstevel@tonic-gate static int  Version_Arch;
857c478bd9Sstevel@tonic-gate int  Num_versfiles = 0;
867c478bd9Sstevel@tonic-gate static int  Has_Version;
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate static char *Versfile;
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate static char *getversion(const char *);
917c478bd9Sstevel@tonic-gate static int version_sanity(const char *value, char **subv);
927c478bd9Sstevel@tonic-gate static int arch_version_sanity(char *av);
937c478bd9Sstevel@tonic-gate static char *getfilter(const char *);
947c478bd9Sstevel@tonic-gate static void writemapfile(FILE *);
957c478bd9Sstevel@tonic-gate static int set_version_arch(const char *);
967c478bd9Sstevel@tonic-gate static int set_supported_arch(const char *);
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate /*
997c478bd9Sstevel@tonic-gate  * xlator_init()
1007c478bd9Sstevel@tonic-gate  *    back-end initialization
1017c478bd9Sstevel@tonic-gate  *    returns pointer to Keywords on success
1027c478bd9Sstevel@tonic-gate  *    returns NULL pointer on failure
1037c478bd9Sstevel@tonic-gate  */
1047c478bd9Sstevel@tonic-gate xlator_keyword_t *
xlator_init(const Translator_info * t_info)1057c478bd9Sstevel@tonic-gate xlator_init(const Translator_info *t_info)
1067c478bd9Sstevel@tonic-gate {
1077c478bd9Sstevel@tonic-gate 	/*
1087c478bd9Sstevel@tonic-gate 	 * initially so we don't lose error messages from version_check
1097c478bd9Sstevel@tonic-gate 	 * we'll set this again later based on ti_info.ti_verbosity
1107c478bd9Sstevel@tonic-gate 	 */
1117c478bd9Sstevel@tonic-gate 	seterrseverity(WARNING);
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	/* set verbosity */
1147c478bd9Sstevel@tonic-gate 	Verbosity = t_info->ti_verbosity;
1157c478bd9Sstevel@tonic-gate 	seterrseverity(t_info->ti_verbosity);
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	/* Obtain translator flags */
1187c478bd9Sstevel@tonic-gate 	Flags = t_info->ti_flags;
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate 	/*
1217c478bd9Sstevel@tonic-gate 	 * set Library Type
1227c478bd9Sstevel@tonic-gate 	 * 1 if filter lib, 0 otherwise
1237c478bd9Sstevel@tonic-gate 	 */
1247c478bd9Sstevel@tonic-gate 	IsFilterLib = t_info->ti_libtype;
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate 	/* set target architecture */
1277c478bd9Sstevel@tonic-gate 	TargetArchStr = t_info->ti_arch;
1287c478bd9Sstevel@tonic-gate 	TargetArchToken = t_info->ti_archtoken;
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	errlog(STATUS, "Architecture set to \"%s\"", TargetArchStr);
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 	/* set output file */
1337c478bd9Sstevel@tonic-gate 	OutputFile = t_info->ti_output_file;
1347c478bd9Sstevel@tonic-gate 	if (OutputFile) {
1357c478bd9Sstevel@tonic-gate 		errlog(STATUS, "Output will go into %s",
1367c478bd9Sstevel@tonic-gate 		    OutputFile);
1377c478bd9Sstevel@tonic-gate 	} else {
1387c478bd9Sstevel@tonic-gate 		OutputFile = "mapfile";
1397c478bd9Sstevel@tonic-gate 		errlog(STATUS, "Using default output filename: %s",
1407c478bd9Sstevel@tonic-gate 		    OutputFile);
1417c478bd9Sstevel@tonic-gate 	}
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 	/* obtain name of version file */
1447c478bd9Sstevel@tonic-gate 	Versfile = t_info->ti_versfile;
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	/* call create_lists() to setup for parse_versions() */
1477c478bd9Sstevel@tonic-gate 	create_lists();
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	/* Process Vers Files */
1507c478bd9Sstevel@tonic-gate 	if (parse_versions(Versfile)) {
1517c478bd9Sstevel@tonic-gate 		return (NULL);
1527c478bd9Sstevel@tonic-gate 	}
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	return (Keywords);
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate /*
1587c478bd9Sstevel@tonic-gate  * xlator_startlib()
1597c478bd9Sstevel@tonic-gate  *    start of library
1607c478bd9Sstevel@tonic-gate  *    returns:  XLATOR_SUCCESS	on success
1617c478bd9Sstevel@tonic-gate  *              XLATOR_SKIP		if library is to be skipped
1627c478bd9Sstevel@tonic-gate  *              XLATOR_NONFATAL	on error
1637c478bd9Sstevel@tonic-gate  */
1647c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1657c478bd9Sstevel@tonic-gate int
xlator_startlib(char const * libname)1667c478bd9Sstevel@tonic-gate xlator_startlib(char const *libname)
1677c478bd9Sstevel@tonic-gate {
1687c478bd9Sstevel@tonic-gate 	errlog(TRACING, "xlator_startlib");
1697c478bd9Sstevel@tonic-gate 	return (XLATOR_SUCCESS);
1707c478bd9Sstevel@tonic-gate }
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate /*
1737c478bd9Sstevel@tonic-gate  * xlator_startfile()
1747c478bd9Sstevel@tonic-gate  *    start of spec file
1757c478bd9Sstevel@tonic-gate  *    returns:  XLATOR_SUCCESS	on success
1767c478bd9Sstevel@tonic-gate  *              XLATOR_SKIP		if file is to be skipped
1777c478bd9Sstevel@tonic-gate  *              XLATOR_NONFATAL	on error
1787c478bd9Sstevel@tonic-gate  */
1797c478bd9Sstevel@tonic-gate int
xlator_startfile(char const * filename)1807c478bd9Sstevel@tonic-gate xlator_startfile(char const *filename)
1817c478bd9Sstevel@tonic-gate {
1827c478bd9Sstevel@tonic-gate 	errlog(TRACING, "xlator_startfile");
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	Curfile = filename;
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 	return (XLATOR_SUCCESS);
1877c478bd9Sstevel@tonic-gate }
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate /*
1907c478bd9Sstevel@tonic-gate  * xlator_start_if ()
1917c478bd9Sstevel@tonic-gate  *    start of interface specification
1927c478bd9Sstevel@tonic-gate  *    returns:  XLATOR_SUCCESS	on success
1937c478bd9Sstevel@tonic-gate  *              XLATOR_SKIP		if interface is to be skipped
1947c478bd9Sstevel@tonic-gate  *              XLATOR_NONFATAL	on error
1957c478bd9Sstevel@tonic-gate  *              XLATOR_FATAL	on fatal error
1967c478bd9Sstevel@tonic-gate  */
1977c478bd9Sstevel@tonic-gate int
xlator_start_if(const Meta_info meta_info,const int token,char * value)1987c478bd9Sstevel@tonic-gate xlator_start_if(const Meta_info meta_info, const int token, char *value)
1997c478bd9Sstevel@tonic-gate {
2007c478bd9Sstevel@tonic-gate 	char rhs[BUFSIZ];
2017c478bd9Sstevel@tonic-gate 	char *kw;
2027c478bd9Sstevel@tonic-gate 	int err;
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	errlog(TRACING, "xlator_start_if %s", value);
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	switch (token) {
2077c478bd9Sstevel@tonic-gate 	case XLATOR_KW_FUNC:
2087c478bd9Sstevel@tonic-gate 		kw = "Function";
2097c478bd9Sstevel@tonic-gate 		break;
2107c478bd9Sstevel@tonic-gate 	case XLATOR_KW_DATA:
2117c478bd9Sstevel@tonic-gate 		kw = "Data";
2127c478bd9Sstevel@tonic-gate 		break;
2137c478bd9Sstevel@tonic-gate 	default:
2147c478bd9Sstevel@tonic-gate 		/* This should never happen */
2157c478bd9Sstevel@tonic-gate 		errlog(ERROR,
2167c478bd9Sstevel@tonic-gate 		    "\"%s\", line %d: Implementation error! "
2177c478bd9Sstevel@tonic-gate 		    "Please file a bug\n", __FILE__, __LINE__);
2187c478bd9Sstevel@tonic-gate 		return (XLATOR_FATAL);
2197c478bd9Sstevel@tonic-gate 	}
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	Curline = meta_info.mi_line_number;
2227c478bd9Sstevel@tonic-gate 	seterrline(Curline, meta_info.mi_filename, kw, value);
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	if (Curfun != NULL) {
2257c478bd9Sstevel@tonic-gate 		errlog(INPUT|ERROR,
2267c478bd9Sstevel@tonic-gate 		    "Error: Interface spec is missing the "
2277c478bd9Sstevel@tonic-gate 		    "End keyword: %s", Curfun);
2287c478bd9Sstevel@tonic-gate 		return (XLATOR_NONFATAL);
2297c478bd9Sstevel@tonic-gate 	}
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 	err = sscanf(value, "%s", rhs);
2327c478bd9Sstevel@tonic-gate 	if (err == 0 || err == EOF) {
2337c478bd9Sstevel@tonic-gate 		errlog(INPUT|ERROR,
2347c478bd9Sstevel@tonic-gate 		    "Error: Missing argument in \"%s\" line", kw);
2357c478bd9Sstevel@tonic-gate 		return (XLATOR_NONFATAL);
2367c478bd9Sstevel@tonic-gate 	}
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	Curfun = strdup(rhs);
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 	if (Curfun == NULL) {
2417c478bd9Sstevel@tonic-gate 		errlog(ERROR | FATAL,
2427c478bd9Sstevel@tonic-gate 		    "Internal Error: strdup() failure in xlator_startif()");
2437c478bd9Sstevel@tonic-gate 	}
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	Iface.IF_name = Curfun;
2467c478bd9Sstevel@tonic-gate 	Iface.IF_type = token;		/* FUNCTION or DATA */
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	Iface.IF_version = NULL;
2497c478bd9Sstevel@tonic-gate 	Iface.IF_class = NULL;
2507c478bd9Sstevel@tonic-gate 	Has_Version = 0;
2517c478bd9Sstevel@tonic-gate 	Supported_Arch = XLATOR_ALLARCH;
2527c478bd9Sstevel@tonic-gate 	Version_Arch = 0;
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 	Iface.IF_binding = DEFAULT;
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 	Iface.IF_filter = NULL;
2577c478bd9Sstevel@tonic-gate 	Iface.IF_auxiliary = NULL;
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 	return (XLATOR_SUCCESS);
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate /*
2637c478bd9Sstevel@tonic-gate  * xlator_take_kvpair()
2647c478bd9Sstevel@tonic-gate  *    processes spec keyword-value pairs
2657c478bd9Sstevel@tonic-gate  *    returns:  XLATOR_SUCCESS	on success
2667c478bd9Sstevel@tonic-gate  *              XLATOR_NONFATAL	on error
2677c478bd9Sstevel@tonic-gate  */
2687c478bd9Sstevel@tonic-gate int
xlator_take_kvpair(const Meta_info meta_info,const int token,char * value)269*c473d156SToomas Soome xlator_take_kvpair(const Meta_info meta_info, const int token, char *value)
2707c478bd9Sstevel@tonic-gate {
2717c478bd9Sstevel@tonic-gate 	char *p;
2727c478bd9Sstevel@tonic-gate 	char *subv = NULL;
2737c478bd9Sstevel@tonic-gate 	char *key = Keywords[token-FIRST_TOKEN].key;
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	Curline = meta_info.mi_line_number;
2767c478bd9Sstevel@tonic-gate 	seterrline(Curline, meta_info.mi_filename, key, value);
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	errlog(TRACING,
2797c478bd9Sstevel@tonic-gate 	    "take_kvpair called. ext_cnt=%d token=%d key=%s value=%s",
2807c478bd9Sstevel@tonic-gate 	    meta_info.mi_ext_cnt, token, key, value);
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 	if (Curfun == NULL) {
2837c478bd9Sstevel@tonic-gate 		errlog(INPUT|ERROR, "Error: Keyword found outside "
2847c478bd9Sstevel@tonic-gate 		    "an interface specification block, line %d", Curline);
2857c478bd9Sstevel@tonic-gate 		return (XLATOR_NONFATAL);
2867c478bd9Sstevel@tonic-gate 	}
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 	switch (token) {
2897c478bd9Sstevel@tonic-gate 	case XLATOR_KW_VERSION:
2907c478bd9Sstevel@tonic-gate 		if (meta_info.mi_ext_cnt  !=  0)
2917c478bd9Sstevel@tonic-gate 			return (XLATOR_SUCCESS);
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 		errlog(TRACING, "Version found. Setting Version to %s", value);
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 		/* Version line found ; used for auditing the SPEC */
2967c478bd9Sstevel@tonic-gate 		Has_Version = 1;
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 		/* remove trailing white space */
2997c478bd9Sstevel@tonic-gate 		p = strrchr(value, '\n');
3007c478bd9Sstevel@tonic-gate 		if (p) {
3017c478bd9Sstevel@tonic-gate 			while (p >= value && isspace(*p)) {
3027c478bd9Sstevel@tonic-gate 				*p = '\0';
3037c478bd9Sstevel@tonic-gate 				--p;
3047c478bd9Sstevel@tonic-gate 			}
3057c478bd9Sstevel@tonic-gate 		}
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 		/* is the version line valid */
3087c478bd9Sstevel@tonic-gate 		switch (version_sanity(value, &subv)) {
3097c478bd9Sstevel@tonic-gate 		case VS_OK:		/* OK, subv not set */
3107c478bd9Sstevel@tonic-gate 			break;
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 		case VS_INVARCH:	/* Invalid Arch */
3137c478bd9Sstevel@tonic-gate 			errlog(INPUT|ERROR, "Error: Invalid architecture "
3147c478bd9Sstevel@tonic-gate 			    "string found in spec or version file: %s", subv);
3157c478bd9Sstevel@tonic-gate 			free(subv);
3167c478bd9Sstevel@tonic-gate 			return (XLATOR_NONFATAL);
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 		case VS_INVVERS:	/* Invalid Version String */
3197c478bd9Sstevel@tonic-gate 			errlog(INPUT|ERROR, "Error: Invalid version string "
3207c478bd9Sstevel@tonic-gate 			    "in spec or version file: %s", subv);
3217c478bd9Sstevel@tonic-gate 			free(subv);
3227c478bd9Sstevel@tonic-gate 			return (XLATOR_NONFATAL);
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 		case VS_INVALID:	/* Both Version and Arch are invalid */
3257c478bd9Sstevel@tonic-gate 			errlog(INPUT|ERROR, "Error: Invalid version and "
3267c478bd9Sstevel@tonic-gate 			    "architecture string in spec or version file"
327*c473d156SToomas Soome 			    ": %s", subv);
3287c478bd9Sstevel@tonic-gate 			free(subv);
3297c478bd9Sstevel@tonic-gate 			return (XLATOR_NONFATAL);
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 		default:	/* BAD IMPLEMENTATION OF version_sanity */
3327c478bd9Sstevel@tonic-gate 			errlog(FATAL, "Error: bad return value from "
3337c478bd9Sstevel@tonic-gate 			    "version_sanity()! This should never happen!");
3347c478bd9Sstevel@tonic-gate 		}
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 		errlog(TRACING, "Version_Arch=%d", Version_Arch);
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate 		Iface.IF_version = getversion(value);
3397c478bd9Sstevel@tonic-gate 		break;
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 	case XLATOR_KW_ARCH:
3427c478bd9Sstevel@tonic-gate 		if (meta_info.mi_ext_cnt  !=  0)
3437c478bd9Sstevel@tonic-gate 			return (XLATOR_SUCCESS);
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 		if (value[0] != '\0') {
3467c478bd9Sstevel@tonic-gate 			Supported_Arch = 0;
3477c478bd9Sstevel@tonic-gate 			if (set_supported_arch(value)) {
3487c478bd9Sstevel@tonic-gate 				errlog(INPUT|ERROR,
3497c478bd9Sstevel@tonic-gate 				    "Error: Unable to parse Arch line");
3507c478bd9Sstevel@tonic-gate 				return (XLATOR_NONFATAL);
3517c478bd9Sstevel@tonic-gate 			}
3527c478bd9Sstevel@tonic-gate 		} else {
3537c478bd9Sstevel@tonic-gate 			errlog(INPUT | ERROR, "Error: Empty Arch line.");
3547c478bd9Sstevel@tonic-gate 		}
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 		if (Supported_Arch == 0) {
3577c478bd9Sstevel@tonic-gate 			errlog(INPUT | ERROR,
3587c478bd9Sstevel@tonic-gate 			    "Error: Unknown architecture defined in Arch line");
3597c478bd9Sstevel@tonic-gate 		}
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 		errlog(TRACING,
3627c478bd9Sstevel@tonic-gate 		    "Interface %s supports the following architectures: "
3637c478bd9Sstevel@tonic-gate 		    "%s\tSupported_Arch=%d", Curfun, value, Supported_Arch);
3647c478bd9Sstevel@tonic-gate 		break;
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	case XLATOR_KW_BINDING:
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 		/*
3697c478bd9Sstevel@tonic-gate 		 * Note that we allow extends for the binding keyword by
3707c478bd9Sstevel@tonic-gate 		 * not checking that meta_info.mi_ext_cnt == 0 here.
3717c478bd9Sstevel@tonic-gate 		 */
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 		/* remove trailing white space */
3747c478bd9Sstevel@tonic-gate 		p = strrchr(value, '\n');
3757c478bd9Sstevel@tonic-gate 		if (p) {
3767c478bd9Sstevel@tonic-gate 			while (p >= value && isspace(*p)) {
3777c478bd9Sstevel@tonic-gate 				*p = '\0';
3787c478bd9Sstevel@tonic-gate 				--p;
3797c478bd9Sstevel@tonic-gate 			}
3807c478bd9Sstevel@tonic-gate 		}
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 		if (value[0] != '\0') {
3837c478bd9Sstevel@tonic-gate 			if (strcmp(value, "direct") == 0) {
3847c478bd9Sstevel@tonic-gate 				Iface.IF_binding = DIRECT;
3857c478bd9Sstevel@tonic-gate 			} else if (strcmp(value, "nodirect") == 0) {
3867c478bd9Sstevel@tonic-gate 				Iface.IF_binding = NODIRECT;
3877c478bd9Sstevel@tonic-gate 			} else if (strcmp(value, "protected") == 0) {
3887c478bd9Sstevel@tonic-gate 				Iface.IF_binding = PROTECTED;
3897c478bd9Sstevel@tonic-gate 			} else {
3907c478bd9Sstevel@tonic-gate 				errlog(INPUT|ERROR,
3917c478bd9Sstevel@tonic-gate 				    "Error: Invalid binding value: %s", value);
3927c478bd9Sstevel@tonic-gate 			}
3937c478bd9Sstevel@tonic-gate 		} else {
3947c478bd9Sstevel@tonic-gate 			errlog(INPUT | ERROR, "Error: Empty Binding line.");
3957c478bd9Sstevel@tonic-gate 		}
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 		errlog(TRACING,
3987c478bd9Sstevel@tonic-gate 		    "Interface %s has binding value: "
3997c478bd9Sstevel@tonic-gate 		    "%s", Curfun, value);
4007c478bd9Sstevel@tonic-gate 		break;
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	case XLATOR_KW_FILTER:
4037c478bd9Sstevel@tonic-gate 	case XLATOR_KW_AUXILIARY:
4047c478bd9Sstevel@tonic-gate 		/*
4057c478bd9Sstevel@tonic-gate 		 * The following is for the "extends" clause.  As with
4067c478bd9Sstevel@tonic-gate 		 * XLATOR_KW_VERSION, we do not want to follow an "extends"
4077c478bd9Sstevel@tonic-gate 		 * chain to get the filter or auxiliary values: we want
4087c478bd9Sstevel@tonic-gate 		 * the first/most-tightly-bound one (mi_ext_cnt = 0).
4097c478bd9Sstevel@tonic-gate 		 */
4107c478bd9Sstevel@tonic-gate 		if (meta_info.mi_ext_cnt  !=  0)
4117c478bd9Sstevel@tonic-gate 			return (XLATOR_SUCCESS);
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 		errlog(TRACING, "Filter[token=%d] found. Setting Filter to %s",
4147c478bd9Sstevel@tonic-gate 		    token, value);
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 		/* remove trailing white space */
4177c478bd9Sstevel@tonic-gate 		p = strrchr(value, '\n');
4187c478bd9Sstevel@tonic-gate 		if (p) {
4197c478bd9Sstevel@tonic-gate 			while (p >= value && isspace(*p)) {
4207c478bd9Sstevel@tonic-gate 				*p = '\0';
4217c478bd9Sstevel@tonic-gate 				--p;
4227c478bd9Sstevel@tonic-gate 			}
4237c478bd9Sstevel@tonic-gate 		}
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 		errlog(TRACING, "Version_Arch=%d", Version_Arch);
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 		if (token == XLATOR_KW_FILTER) {
4287c478bd9Sstevel@tonic-gate 			Iface.IF_filter = getfilter(value);
4297c478bd9Sstevel@tonic-gate 		} else if (token == XLATOR_KW_AUXILIARY) {
4307c478bd9Sstevel@tonic-gate 			Iface.IF_auxiliary = getfilter(value);
4317c478bd9Sstevel@tonic-gate 		}
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 		break;
4347c478bd9Sstevel@tonic-gate 	default:
4357c478bd9Sstevel@tonic-gate 		errlog(INPUT|ERROR, "Error: Unrecognized keyword snuck in!"
4367c478bd9Sstevel@tonic-gate 		    "\tThis is a programmer error: %s", key);
4377c478bd9Sstevel@tonic-gate 		return (XLATOR_NONFATAL);
4387c478bd9Sstevel@tonic-gate 	}
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	return (XLATOR_SUCCESS);
4417c478bd9Sstevel@tonic-gate }
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate /*
4447c478bd9Sstevel@tonic-gate  * xlator_end_if ()
4457c478bd9Sstevel@tonic-gate  *  signal end of spec interface spec
4467c478bd9Sstevel@tonic-gate  *     returns: XLATOR_SUCCESS on success
4477c478bd9Sstevel@tonic-gate  *		XLATOR_NONFATAL	on error
4487c478bd9Sstevel@tonic-gate  */
4497c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4507c478bd9Sstevel@tonic-gate int
xlator_end_if(const Meta_info M,const char * value)4517c478bd9Sstevel@tonic-gate xlator_end_if(const Meta_info M, const char *value)
4527c478bd9Sstevel@tonic-gate {
4537c478bd9Sstevel@tonic-gate 	int retval = XLATOR_NONFATAL;
4547c478bd9Sstevel@tonic-gate 	int picky = Flags & XLATOR_PICKY_FLAG;
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	seterrline(M.mi_line_number, M.mi_filename, "End", "");
4577c478bd9Sstevel@tonic-gate 	errlog(TRACING, "xlator_end_if");
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 	if (Curfun == NULL) {
4607c478bd9Sstevel@tonic-gate 		errlog(INPUT | ERROR, "Error: End without "
4617c478bd9Sstevel@tonic-gate 		    "matching Function or Data in file \"%s\"", Curfile);
4627c478bd9Sstevel@tonic-gate 		goto cleanup;
4637c478bd9Sstevel@tonic-gate 	}
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 	errlog(TRACING, "Interface=%s", Iface.IF_name);
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate 	if (!Has_Version) {
4687c478bd9Sstevel@tonic-gate 		if (picky) {
4697c478bd9Sstevel@tonic-gate 			errlog(INPUT | ERROR, "Error: Interface has no "
4707c478bd9Sstevel@tonic-gate 			    "Version!\n\tInterface=%s\n\tSPEC File=%s",
4717c478bd9Sstevel@tonic-gate 			    Iface.IF_name, Curfile);
4727c478bd9Sstevel@tonic-gate 		} else {
4737c478bd9Sstevel@tonic-gate 			errlog(INPUT | WARNING, "Warning: Interface has "
4747c478bd9Sstevel@tonic-gate 			    "no Version!\n\tInterface=%s\n\tSPEC File=%s",
4757c478bd9Sstevel@tonic-gate 			    Iface.IF_name, Curfile);
4767c478bd9Sstevel@tonic-gate 			retval = XLATOR_SUCCESS;
4777c478bd9Sstevel@tonic-gate 		}
4787c478bd9Sstevel@tonic-gate 		goto cleanup;
4797c478bd9Sstevel@tonic-gate 	}
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	if (Version_Arch & (~Supported_Arch)) {
4827c478bd9Sstevel@tonic-gate 		errlog(INPUT | ERROR, "Error: Architectures in Version "
4837c478bd9Sstevel@tonic-gate 		    "line must be a subset of Architectures in Arch line\n"
4847c478bd9Sstevel@tonic-gate 		    "\tInterface=%s\n\tSPEC File=%s", Iface.IF_name, Curfile);
4857c478bd9Sstevel@tonic-gate 		goto cleanup;
4867c478bd9Sstevel@tonic-gate 	}
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	if ((TargetArchToken & Supported_Arch) == 0) {
4897c478bd9Sstevel@tonic-gate 		/*
4907c478bd9Sstevel@tonic-gate 		 * This interface is not for the architecture
4917c478bd9Sstevel@tonic-gate 		 * we are currently processing, so we skip it.
4927c478bd9Sstevel@tonic-gate 		 */
4937c478bd9Sstevel@tonic-gate 		retval = XLATOR_SUCCESS;
4947c478bd9Sstevel@tonic-gate 		goto cleanup;
4957c478bd9Sstevel@tonic-gate 	}
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 	if (Iface.IF_version == NULL) {
4987c478bd9Sstevel@tonic-gate 		if (picky) {
4997c478bd9Sstevel@tonic-gate 			errlog(ERROR|INPUT,
5007c478bd9Sstevel@tonic-gate 			    "Error:  Version was not found for "
5017c478bd9Sstevel@tonic-gate 			    "\"%s\" architecture\n\tInterface=%s",
5027c478bd9Sstevel@tonic-gate 			    TargetArchStr, Iface.IF_name);
5037c478bd9Sstevel@tonic-gate 		} else {
5047c478bd9Sstevel@tonic-gate 			errlog(WARNING | INPUT,
5057c478bd9Sstevel@tonic-gate 			    "Warning:  Version was not found for "
5067c478bd9Sstevel@tonic-gate 			    "\"%s\" architecture\n\tInterface=%s",
5077c478bd9Sstevel@tonic-gate 			    TargetArchStr, Iface.IF_name);
5087c478bd9Sstevel@tonic-gate 			retval = XLATOR_SUCCESS;
5097c478bd9Sstevel@tonic-gate 		}
5107c478bd9Sstevel@tonic-gate 		goto cleanup;
5117c478bd9Sstevel@tonic-gate 	}
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 	/* check Iface.IF_type */
5147c478bd9Sstevel@tonic-gate 	switch (Iface.IF_type) {
5157c478bd9Sstevel@tonic-gate 	case FUNCTION:
5167c478bd9Sstevel@tonic-gate 		errlog(VERBOSE, "Interface type = FUNCTION");
5177c478bd9Sstevel@tonic-gate 		break;
5187c478bd9Sstevel@tonic-gate 	case DATA:
5197c478bd9Sstevel@tonic-gate 		errlog(VERBOSE, "Interface type = DATA");
5207c478bd9Sstevel@tonic-gate 		break;
5217c478bd9Sstevel@tonic-gate 	case NOTYPE:
5227c478bd9Sstevel@tonic-gate 		errlog(WARNING,
5237c478bd9Sstevel@tonic-gate 		    "Warning: Interface is neither "
5247c478bd9Sstevel@tonic-gate 		    "DATA nor FUNCTION!!\n\t"
5257c478bd9Sstevel@tonic-gate 		    "Interface=%s\n\tSPEC File=%s",
5267c478bd9Sstevel@tonic-gate 		    Iface.IF_name, Curfile);
5277c478bd9Sstevel@tonic-gate 		break;
5287c478bd9Sstevel@tonic-gate 	default:
5297c478bd9Sstevel@tonic-gate 		errlog(ERROR, "Error: Bad spec2map implementation!\n"
5307c478bd9Sstevel@tonic-gate 		    "\tInterface type is invalid\n"
5317c478bd9Sstevel@tonic-gate 		    "\tThis should never happen.\n"
5327c478bd9Sstevel@tonic-gate 		    "\tInterface=%s\tSPEC File=%s", Iface.IF_name, Curfile);
5337c478bd9Sstevel@tonic-gate 		goto cleanup;
5347c478bd9Sstevel@tonic-gate 	}
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate 	(void) add_by_name(Iface.IF_version, &Iface);
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 	retval = XLATOR_SUCCESS;
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate cleanup:
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate 	/* cleanup */
5437c478bd9Sstevel@tonic-gate 	Iface.IF_name = NULL;
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 	free(Iface.IF_version);
5467c478bd9Sstevel@tonic-gate 	Iface.IF_version = NULL;
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 	free(Iface.IF_class);
5497c478bd9Sstevel@tonic-gate 	Iface.IF_class = NULL;
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate 	free(Curfun);
5527c478bd9Sstevel@tonic-gate 	Curfun = NULL;
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 	Supported_Arch = XLATOR_ALLARCH;
5557c478bd9Sstevel@tonic-gate 	return (retval);
5567c478bd9Sstevel@tonic-gate }
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate /*
5597c478bd9Sstevel@tonic-gate  * xlator_endfile()
5607c478bd9Sstevel@tonic-gate  *   signal end of spec file
5617c478bd9Sstevel@tonic-gate  *    returns:  XLATOR_SUCCESS	on success
5627c478bd9Sstevel@tonic-gate  *              XLATOR_NONFATAL	on error
5637c478bd9Sstevel@tonic-gate  */
5647c478bd9Sstevel@tonic-gate int
xlator_endfile(void)5657c478bd9Sstevel@tonic-gate xlator_endfile(void)
5667c478bd9Sstevel@tonic-gate {
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate 	errlog(TRACING, "xlator_endfile");
5697c478bd9Sstevel@tonic-gate 
5707c478bd9Sstevel@tonic-gate 	Curfile = NULL;
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 	return (XLATOR_SUCCESS);
5737c478bd9Sstevel@tonic-gate }
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate /*
5767c478bd9Sstevel@tonic-gate  * xlator_endlib()
5777c478bd9Sstevel@tonic-gate  *   signal end of library
5787c478bd9Sstevel@tonic-gate  *    returns:  XLATOR_SUCCESS	on success
5797c478bd9Sstevel@tonic-gate  *              XLATOR_NONFATAL	on error
5807c478bd9Sstevel@tonic-gate  */
5817c478bd9Sstevel@tonic-gate int
xlator_endlib(void)5827c478bd9Sstevel@tonic-gate xlator_endlib(void)
5837c478bd9Sstevel@tonic-gate {
5847c478bd9Sstevel@tonic-gate 	FILE *mapfp;
5857c478bd9Sstevel@tonic-gate 	int retval = XLATOR_SUCCESS;
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 	errlog(TRACING, "xlator_endlib");
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 	/* Pretend to print mapfile */
5907c478bd9Sstevel@tonic-gate 	if (Verbosity >= TRACING) {
5917c478bd9Sstevel@tonic-gate 		print_all_buckets();
5927c478bd9Sstevel@tonic-gate 	}
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 	/* Everything read, now organize it! */
5957c478bd9Sstevel@tonic-gate 	sort_buckets();
5967c478bd9Sstevel@tonic-gate 	add_local();
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate 	/* Create Output */
5997c478bd9Sstevel@tonic-gate 	mapfp = fopen(OutputFile, "w");
6007c478bd9Sstevel@tonic-gate 	if (mapfp == NULL) {
6017c478bd9Sstevel@tonic-gate 		errlog(ERROR,
6027c478bd9Sstevel@tonic-gate 		    "Error: Unable to open output file \"%s\"\n\t%s",
6037c478bd9Sstevel@tonic-gate 		    OutputFile, strerror(errno));
6047c478bd9Sstevel@tonic-gate 		retval = XLATOR_NONFATAL;
6057c478bd9Sstevel@tonic-gate 	} else {
6067c478bd9Sstevel@tonic-gate 		writemapfile(mapfp);
6077c478bd9Sstevel@tonic-gate 		(void) fclose(mapfp);
6087c478bd9Sstevel@tonic-gate 	}
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 	return (retval);
6117c478bd9Sstevel@tonic-gate }
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate /*
6147c478bd9Sstevel@tonic-gate  * xlator_end()
6157c478bd9Sstevel@tonic-gate  *   signal end of translation
6167c478bd9Sstevel@tonic-gate  *    returns:  XLATOR_SUCCESS	on success
6177c478bd9Sstevel@tonic-gate  *              XLATOR_NONFATAL	on error
6187c478bd9Sstevel@tonic-gate  */
6197c478bd9Sstevel@tonic-gate int
xlator_end(void)6207c478bd9Sstevel@tonic-gate xlator_end(void)
6217c478bd9Sstevel@tonic-gate {
6227c478bd9Sstevel@tonic-gate 	errlog(TRACING, "xlator_end");
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate 	/* Destroy the list created by create_lists */
6257c478bd9Sstevel@tonic-gate 	delete_lists();
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	return (XLATOR_SUCCESS);
6287c478bd9Sstevel@tonic-gate }
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate /*
6317c478bd9Sstevel@tonic-gate  * getversion()
6327c478bd9Sstevel@tonic-gate  * called by xlator_take_kvpair when Version keyword is found
6337c478bd9Sstevel@tonic-gate  * parses the Version string and returns the one that matches
6347c478bd9Sstevel@tonic-gate  * the current target architecture
6357c478bd9Sstevel@tonic-gate  *
6367c478bd9Sstevel@tonic-gate  * the pointer returned by this function must be freed later.
6377c478bd9Sstevel@tonic-gate  */
6387c478bd9Sstevel@tonic-gate static char *
getversion(const char * value)6397c478bd9Sstevel@tonic-gate getversion(const char *value)
6407c478bd9Sstevel@tonic-gate {
6417c478bd9Sstevel@tonic-gate 	char *v, *p;
6427c478bd9Sstevel@tonic-gate 	char arch[ARCHBUFLEN];
6437c478bd9Sstevel@tonic-gate 	int archlen;
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 	/* up to ARCHBUFLEN-1 */
6467c478bd9Sstevel@tonic-gate 	(void) strncpy(arch, TargetArchStr, ARCHBUFLEN-1);
6477c478bd9Sstevel@tonic-gate 	arch[ARCHBUFLEN-2] = '\0';
6487c478bd9Sstevel@tonic-gate 	(void) strcat(arch, "=");		/* append an '=' */
6497c478bd9Sstevel@tonic-gate 	archlen = strlen(arch);
6507c478bd9Sstevel@tonic-gate 
6517c478bd9Sstevel@tonic-gate 	errlog(VERBOSE, "getversion: value=%s", value);
6527c478bd9Sstevel@tonic-gate 
6537c478bd9Sstevel@tonic-gate 	if (strchr(value, '=') != NULL) {
6547c478bd9Sstevel@tonic-gate 		if ((v = strstr(value, arch)) != NULL) {
6557c478bd9Sstevel@tonic-gate 			p = strdup(v + archlen);
6567c478bd9Sstevel@tonic-gate 			if (p == NULL) {
6577c478bd9Sstevel@tonic-gate 				errlog(ERROR | FATAL,
6587c478bd9Sstevel@tonic-gate 				    "Internal Error: strdup() failure "
6597c478bd9Sstevel@tonic-gate 				    "in getversion()");
6607c478bd9Sstevel@tonic-gate 			}
6617c478bd9Sstevel@tonic-gate 			v = p;
6627c478bd9Sstevel@tonic-gate 			while (!isspace(*v) && *v != '\0')
6637c478bd9Sstevel@tonic-gate 				++v;
6647c478bd9Sstevel@tonic-gate 			*v = '\0';
6657c478bd9Sstevel@tonic-gate 		} else {
6667c478bd9Sstevel@tonic-gate 			errlog(VERBOSE, "getversion returns: NULL");
6677c478bd9Sstevel@tonic-gate 			return (NULL);
6687c478bd9Sstevel@tonic-gate 		}
6697c478bd9Sstevel@tonic-gate 	} else {
6707c478bd9Sstevel@tonic-gate 		p = strdup(value);
6717c478bd9Sstevel@tonic-gate 		if (p == NULL) {
6727c478bd9Sstevel@tonic-gate 			errlog(ERROR | FATAL, "Internal Error: strdup() "
6737c478bd9Sstevel@tonic-gate 			    "failure in getversion()");
6747c478bd9Sstevel@tonic-gate 		}
6757c478bd9Sstevel@tonic-gate 	}
6767c478bd9Sstevel@tonic-gate 
6777c478bd9Sstevel@tonic-gate 	if (p != NULL)
6787c478bd9Sstevel@tonic-gate 		errlog(VERBOSE, "getversion returns: %s", p);
6797c478bd9Sstevel@tonic-gate 	else
6807c478bd9Sstevel@tonic-gate 		errlog(VERBOSE, "getversion returns: NULL");
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 	return (p);
6837c478bd9Sstevel@tonic-gate }
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate /*
6867c478bd9Sstevel@tonic-gate  * getfilter()
6877c478bd9Sstevel@tonic-gate  * Called by xlator_take_kvpair when "filter" or "auxiliary" keyword is
6887c478bd9Sstevel@tonic-gate  * found.  Parses the Filter/Auxiliary string and returns the one that
6897c478bd9Sstevel@tonic-gate  * matches the current target architecture
6907c478bd9Sstevel@tonic-gate  *
6917c478bd9Sstevel@tonic-gate  * The pointer returned by this function must be freed later.
6927c478bd9Sstevel@tonic-gate  *
6937c478bd9Sstevel@tonic-gate  * Note that returning NULL here indicates there was no desired
6947c478bd9Sstevel@tonic-gate  * arch=path item in value, i.e. for TargetArchStr the interface is
6957c478bd9Sstevel@tonic-gate  * not a filter.
6967c478bd9Sstevel@tonic-gate  */
6977c478bd9Sstevel@tonic-gate static char *
getfilter(const char * value)6987c478bd9Sstevel@tonic-gate getfilter(const char *value)
6997c478bd9Sstevel@tonic-gate {
7007c478bd9Sstevel@tonic-gate 	char *v, *p;
7017c478bd9Sstevel@tonic-gate 	char arch[ARCHBUFLEN];
7027c478bd9Sstevel@tonic-gate 	int archlen;
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	/* up to ARCHBUFLEN-1 */
7057c478bd9Sstevel@tonic-gate 	(void) strncpy(arch, TargetArchStr, ARCHBUFLEN-1);
7067c478bd9Sstevel@tonic-gate 	arch[ARCHBUFLEN-2] = '\0';
7077c478bd9Sstevel@tonic-gate 	(void) strcat(arch, "=");		/* append an '=' */
7087c478bd9Sstevel@tonic-gate 	archlen = strlen(arch);
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate 	errlog(VERBOSE, "getfilter: value=%s", value);
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 	if (strchr(value, '=') != NULL) {
7137c478bd9Sstevel@tonic-gate 		if ((v = strstr(value, arch)) != NULL) {
7147c478bd9Sstevel@tonic-gate 			p = strdup(v + archlen);
7157c478bd9Sstevel@tonic-gate 			if (p == NULL) {
7167c478bd9Sstevel@tonic-gate 				errlog(ERROR | FATAL,
7177c478bd9Sstevel@tonic-gate 				    "Internal Error: strdup() failure "
7187c478bd9Sstevel@tonic-gate 				    "in getfilter()");
7197c478bd9Sstevel@tonic-gate 			}
7207c478bd9Sstevel@tonic-gate 			v = p;
7217c478bd9Sstevel@tonic-gate 			while (!isspace(*v) && *v != '\0')
7227c478bd9Sstevel@tonic-gate 				++v;
7237c478bd9Sstevel@tonic-gate 			*v = '\0';
7247c478bd9Sstevel@tonic-gate 		} else {
7257c478bd9Sstevel@tonic-gate 			errlog(VERBOSE, "getfilter returns: NULL");
7267c478bd9Sstevel@tonic-gate 			return (NULL);
7277c478bd9Sstevel@tonic-gate 		}
7287c478bd9Sstevel@tonic-gate 	} else {
7297c478bd9Sstevel@tonic-gate 		p = strdup(value);
7307c478bd9Sstevel@tonic-gate 		if (p == NULL) {
7317c478bd9Sstevel@tonic-gate 			errlog(ERROR | FATAL, "Internal Error: strdup() "
7327c478bd9Sstevel@tonic-gate 			    "failure in getfilter()");
7337c478bd9Sstevel@tonic-gate 		}
7347c478bd9Sstevel@tonic-gate 	}
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate 	if (p != NULL)
7377c478bd9Sstevel@tonic-gate 		errlog(VERBOSE, "getfilter returns: %s", p);
7387c478bd9Sstevel@tonic-gate 	else
7397c478bd9Sstevel@tonic-gate 		errlog(VERBOSE, "getfilter returns: NULL");
7407c478bd9Sstevel@tonic-gate 
7417c478bd9Sstevel@tonic-gate 	return (p);
7427c478bd9Sstevel@tonic-gate }
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate /*
7457c478bd9Sstevel@tonic-gate  * version_sanity()
7467c478bd9Sstevel@tonic-gate  *    for each version info in the Version line
7477c478bd9Sstevel@tonic-gate  *    check for its validity.
7487c478bd9Sstevel@tonic-gate  *    Set Version_arch to reflect all supported architectures if successful.
7497c478bd9Sstevel@tonic-gate  *    Upon return on failure, subv will contain the last version string
7507c478bd9Sstevel@tonic-gate  *    processed
7517c478bd9Sstevel@tonic-gate  *    returns: VS_OK	OK
7527c478bd9Sstevel@tonic-gate  *             VS_INVARCH    Invalid Architecture
7537c478bd9Sstevel@tonic-gate  *             VS_INVVERS    Invalid Version String
7547c478bd9Sstevel@tonic-gate  *             VS_INVALID    Both Version and Architecture are invalid;
7557c478bd9Sstevel@tonic-gate  */
7567c478bd9Sstevel@tonic-gate static int
version_sanity(const char * value,char ** subv)7577c478bd9Sstevel@tonic-gate version_sanity(const char *value, char **subv)
7587c478bd9Sstevel@tonic-gate {
7597c478bd9Sstevel@tonic-gate 	char *p, *v, *a;
7607c478bd9Sstevel@tonic-gate 	int retval = VS_INVALID;
7617c478bd9Sstevel@tonic-gate 
7627c478bd9Sstevel@tonic-gate 	if (strchr(value, '=')) {
7637c478bd9Sstevel@tonic-gate 		/* Form 1:   Version	arch=Version_string */
7647c478bd9Sstevel@tonic-gate 		v = strdup(value);
7657c478bd9Sstevel@tonic-gate 		if (v == NULL) {
7667c478bd9Sstevel@tonic-gate 			errlog(ERROR | FATAL,
7677c478bd9Sstevel@tonic-gate 			    "Internal Error: strdup() failure in "
7687c478bd9Sstevel@tonic-gate 			    "version_sanity()");
7697c478bd9Sstevel@tonic-gate 		}
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate 		/* process each arch=version string */
7727c478bd9Sstevel@tonic-gate 		p = v;
7737c478bd9Sstevel@tonic-gate 		while ((a = strtok(p, " \t\n"))) {
7747c478bd9Sstevel@tonic-gate 			if ((retval = arch_version_sanity(a)) != VS_OK) {
7757c478bd9Sstevel@tonic-gate 				*subv = strdup(a);
7767c478bd9Sstevel@tonic-gate 				if (subv == NULL) {
7777c478bd9Sstevel@tonic-gate 					errlog(ERROR | FATAL,
7787c478bd9Sstevel@tonic-gate 					    "Internal Error: strdup() failure "
7797c478bd9Sstevel@tonic-gate 					    "in version_sanity()");
7807c478bd9Sstevel@tonic-gate 				}
7817c478bd9Sstevel@tonic-gate 				break;
7827c478bd9Sstevel@tonic-gate 			}
7837c478bd9Sstevel@tonic-gate 			if ((retval = set_version_arch(a)) != VS_OK) {
7847c478bd9Sstevel@tonic-gate 				/* set the global Version_arch */
7857c478bd9Sstevel@tonic-gate 				*subv = strdup(a);
7867c478bd9Sstevel@tonic-gate 				if (subv == NULL) {
7877c478bd9Sstevel@tonic-gate 					errlog(ERROR | FATAL,
7887c478bd9Sstevel@tonic-gate 					    "Internal Error: strdup() failure "
7897c478bd9Sstevel@tonic-gate 					    "in version_sanity()");
7907c478bd9Sstevel@tonic-gate 				}
7917c478bd9Sstevel@tonic-gate 				break;
7927c478bd9Sstevel@tonic-gate 			}
7937c478bd9Sstevel@tonic-gate 			p = NULL;
7947c478bd9Sstevel@tonic-gate 		}
7957c478bd9Sstevel@tonic-gate 		free(v);
7967c478bd9Sstevel@tonic-gate 	} else {
7977c478bd9Sstevel@tonic-gate 		/* Form 2: Version		Version_string */
7987c478bd9Sstevel@tonic-gate 		if (valid_version(value)) {
7997c478bd9Sstevel@tonic-gate 			retval = VS_OK;
8007c478bd9Sstevel@tonic-gate 		} else {
8017c478bd9Sstevel@tonic-gate 			*subv = strdup(value);
8027c478bd9Sstevel@tonic-gate 			if (subv == NULL) {
8037c478bd9Sstevel@tonic-gate 				errlog(ERROR | FATAL,
8047c478bd9Sstevel@tonic-gate 				    "Internal Error: strdup() failure "
8057c478bd9Sstevel@tonic-gate 				    "in version_sanity()");
8067c478bd9Sstevel@tonic-gate 			}
8077c478bd9Sstevel@tonic-gate 		}
8087c478bd9Sstevel@tonic-gate 	}
8097c478bd9Sstevel@tonic-gate 	return (retval);
8107c478bd9Sstevel@tonic-gate }
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate /*
8137c478bd9Sstevel@tonic-gate  * arch_version_sanity()
8147c478bd9Sstevel@tonic-gate  *    checks version lines of the form "arch=version"
8157c478bd9Sstevel@tonic-gate  *    av MUST be a string of the form "arch=version" (no spaces)
8167c478bd9Sstevel@tonic-gate  *    returns: VS_OK	OK
8177c478bd9Sstevel@tonic-gate  *             VS_INVARCH    Invalid Architecture
8187c478bd9Sstevel@tonic-gate  *             VS_INVVERS    Invalid Version String
8197c478bd9Sstevel@tonic-gate  *             VS_INVALID    Both Versions are invalid;
8207c478bd9Sstevel@tonic-gate  */
8217c478bd9Sstevel@tonic-gate static int
arch_version_sanity(char * av)8227c478bd9Sstevel@tonic-gate arch_version_sanity(char *av)
8237c478bd9Sstevel@tonic-gate {
8247c478bd9Sstevel@tonic-gate 	char *p, *v;
8257c478bd9Sstevel@tonic-gate 	int retval = VS_OK;
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate 	p = strchr(av, '=');
8287c478bd9Sstevel@tonic-gate 	if (p == NULL) {
8297c478bd9Sstevel@tonic-gate 		errlog(INPUT|ERROR, "Error: Incorrect format of Version line");
8307c478bd9Sstevel@tonic-gate 		return (VS_INVALID);
8317c478bd9Sstevel@tonic-gate 	}
8327c478bd9Sstevel@tonic-gate 
8337c478bd9Sstevel@tonic-gate 	*p = '\0';	/* stick a '\0' where the '=' was */
8347c478bd9Sstevel@tonic-gate 	v = p + 1;
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate 	if (valid_arch(av) == 0)
8377c478bd9Sstevel@tonic-gate 		retval = VS_INVARCH;
8387c478bd9Sstevel@tonic-gate 
8397c478bd9Sstevel@tonic-gate 	if (valid_version(v) == 0)
8407c478bd9Sstevel@tonic-gate 		retval += VS_INVVERS;
8417c478bd9Sstevel@tonic-gate 
8427c478bd9Sstevel@tonic-gate 	*p = '=';	/* restore the '=' */
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate 	return (retval);
8457c478bd9Sstevel@tonic-gate }
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate /*
8487c478bd9Sstevel@tonic-gate  * writemapfile()
8497c478bd9Sstevel@tonic-gate  *    called by xlator_endlib();
8507c478bd9Sstevel@tonic-gate  *    writes out the map file
8517c478bd9Sstevel@tonic-gate  */
8527c478bd9Sstevel@tonic-gate static void
writemapfile(FILE * mapfp)8537c478bd9Sstevel@tonic-gate writemapfile(FILE *mapfp)
8547c478bd9Sstevel@tonic-gate {
8557c478bd9Sstevel@tonic-gate 	bucket_t *l;	/* List of buckets. */
8567c478bd9Sstevel@tonic-gate 	bucket_t *b;	/* Bucket within list. */
8577c478bd9Sstevel@tonic-gate 	struct bucketlist *bl;
8587c478bd9Sstevel@tonic-gate 	table_t *t;
8597c478bd9Sstevel@tonic-gate 	int i = 0, n = 0;
8607c478bd9Sstevel@tonic-gate 	char **p;
8617c478bd9Sstevel@tonic-gate 
8627c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "writemapfile() {");
8637c478bd9Sstevel@tonic-gate 	for (l = first_list(); l != NULL; l = next_list()) {
8647c478bd9Sstevel@tonic-gate 
8657c478bd9Sstevel@tonic-gate 		for (b = first_from_list(l); b != NULL; b = next_from_list()) {
8667c478bd9Sstevel@tonic-gate 			errlog(TRACING, "b_name = %s", b->b_name);
8677c478bd9Sstevel@tonic-gate 			print_bucket(b); /* Debugging routine. */
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate 			if (!b->b_was_printed) {
8707c478bd9Sstevel@tonic-gate 				/* Ok, we can print it. */
8717c478bd9Sstevel@tonic-gate 				b->b_was_printed = 1;
8727c478bd9Sstevel@tonic-gate 				(void) fprintf(mapfp, "%s {\n", b->b_name);
8737c478bd9Sstevel@tonic-gate 
8747c478bd9Sstevel@tonic-gate 				if (b->b_weak != 1) {
8757c478bd9Sstevel@tonic-gate 					char *strtab;
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate 					(void) fprintf(mapfp, "    global:\n");
8787c478bd9Sstevel@tonic-gate 
8797c478bd9Sstevel@tonic-gate 					strtab = get_stringtable(
880*c473d156SToomas Soome 					    b->b_global_table, 0);
8817c478bd9Sstevel@tonic-gate 
8827c478bd9Sstevel@tonic-gate 					if (strtab == NULL) {
8837c478bd9Sstevel@tonic-gate 						/*
8847c478bd9Sstevel@tonic-gate 						 * There were no interfaces
8857c478bd9Sstevel@tonic-gate 						 * in the bucket.
8867c478bd9Sstevel@tonic-gate 						 * Insert a dummy entry
8877c478bd9Sstevel@tonic-gate 						 * to avoid a "weak version"
8887c478bd9Sstevel@tonic-gate 						 */
8897c478bd9Sstevel@tonic-gate 						(void) fprintf(mapfp,
8907c478bd9Sstevel@tonic-gate 						    "\t%s;\n", b->b_name);
8917c478bd9Sstevel@tonic-gate 					}
8927c478bd9Sstevel@tonic-gate 				} else {
8937c478bd9Sstevel@tonic-gate 					(void) fprintf(mapfp,
8947c478bd9Sstevel@tonic-gate 					    "    # Weak version\n");
8957c478bd9Sstevel@tonic-gate 				}
8967c478bd9Sstevel@tonic-gate 				/* Print all the interfaces in the bucket. */
8977c478bd9Sstevel@tonic-gate 				t = b->b_global_table;
8987c478bd9Sstevel@tonic-gate 				n = t->used;
8997c478bd9Sstevel@tonic-gate 
9007c478bd9Sstevel@tonic-gate 				for (i = 0; i <= n; ++i) {
9017c478bd9Sstevel@tonic-gate 					(void) fprintf(mapfp, "\t%s;\n",
9027c478bd9Sstevel@tonic-gate 					    get_stringtable(t, i));
9037c478bd9Sstevel@tonic-gate 				}
9047c478bd9Sstevel@tonic-gate 
9057c478bd9Sstevel@tonic-gate 				if (b->b_has_protecteds) {
9067c478bd9Sstevel@tonic-gate 					t = b->b_protected_table;
9077c478bd9Sstevel@tonic-gate 					n = t->used;
9087c478bd9Sstevel@tonic-gate 
9097c478bd9Sstevel@tonic-gate 					(void) fprintf(mapfp,
9107c478bd9Sstevel@tonic-gate 					    "    protected:\n");
9117c478bd9Sstevel@tonic-gate 
9127c478bd9Sstevel@tonic-gate 					for (i = 0; i <= n; ++i) {
9137c478bd9Sstevel@tonic-gate 						(void) fprintf(mapfp, "\t%s;\n",
9147c478bd9Sstevel@tonic-gate 						    get_stringtable(t, i));
9157c478bd9Sstevel@tonic-gate 					}
9167c478bd9Sstevel@tonic-gate 				}
9177c478bd9Sstevel@tonic-gate 
9187c478bd9Sstevel@tonic-gate 				/* Conditionally add ``local: *;''. */
9197c478bd9Sstevel@tonic-gate 				if (b->b_has_locals) {
9207c478bd9Sstevel@tonic-gate 					(void) fprintf(mapfp,
9217c478bd9Sstevel@tonic-gate 					    "    local:\n\t*;\n}");
9227c478bd9Sstevel@tonic-gate 				} else {
9237c478bd9Sstevel@tonic-gate 					(void) fprintf(mapfp, "}");
9247c478bd9Sstevel@tonic-gate 				}
9257c478bd9Sstevel@tonic-gate 				/* Print name of all parents. */
9267c478bd9Sstevel@tonic-gate 				for (p = parents_of(b);
927*c473d156SToomas Soome 				    p !=  NULL && *p != NULL; ++p) {
9287c478bd9Sstevel@tonic-gate 					(void) fprintf(mapfp, " %s", *p);
9297c478bd9Sstevel@tonic-gate 				}
9307c478bd9Sstevel@tonic-gate 				bl = b->b_uncles;
9317c478bd9Sstevel@tonic-gate 				while (bl != NULL) {
9327c478bd9Sstevel@tonic-gate 					(void) fprintf(mapfp, " %s",
9337c478bd9Sstevel@tonic-gate 					    bl->bl_bucket->b_name);
9347c478bd9Sstevel@tonic-gate 					bl = bl->bl_next;
9357c478bd9Sstevel@tonic-gate 				}
9367c478bd9Sstevel@tonic-gate 
9377c478bd9Sstevel@tonic-gate 				(void) fprintf(mapfp, ";\n\n");
9387c478bd9Sstevel@tonic-gate 			} else {
9397c478bd9Sstevel@tonic-gate 				/*
9407c478bd9Sstevel@tonic-gate 				 * We've printed this one before,
9417c478bd9Sstevel@tonic-gate 				 * so don't do it again.
9427c478bd9Sstevel@tonic-gate 				 */
9437c478bd9Sstevel@tonic-gate 				/*EMPTY*/;
9447c478bd9Sstevel@tonic-gate 			}
9457c478bd9Sstevel@tonic-gate 		}
9467c478bd9Sstevel@tonic-gate 	}
9477c478bd9Sstevel@tonic-gate 	errlog(END, "}");
9487c478bd9Sstevel@tonic-gate }
9497c478bd9Sstevel@tonic-gate 
9507c478bd9Sstevel@tonic-gate /*
9517c478bd9Sstevel@tonic-gate  * set_version_arch ()
9527c478bd9Sstevel@tonic-gate  * input must be a string of the form "arch=version"
9537c478bd9Sstevel@tonic-gate  * turns on bits of global Version_Arch that correspond to the "arch"
9547c478bd9Sstevel@tonic-gate  * return VS_OK upon success
9557c478bd9Sstevel@tonic-gate  *  VS_INVARCH if architecture is invalid
9567c478bd9Sstevel@tonic-gate  *  EINVAL on other failure
9577c478bd9Sstevel@tonic-gate  */
9587c478bd9Sstevel@tonic-gate static int
set_version_arch(const char * arch)9597c478bd9Sstevel@tonic-gate set_version_arch(const char *arch)
9607c478bd9Sstevel@tonic-gate {
9617c478bd9Sstevel@tonic-gate 	char	*a, *p;
9627c478bd9Sstevel@tonic-gate 	int	x;
9637c478bd9Sstevel@tonic-gate 	int	retval = EINVAL;
9647c478bd9Sstevel@tonic-gate 
9657c478bd9Sstevel@tonic-gate 	if (arch == NULL)
9667c478bd9Sstevel@tonic-gate 		return (retval);
9677c478bd9Sstevel@tonic-gate 
9687c478bd9Sstevel@tonic-gate 	a = strdup(arch);
9697c478bd9Sstevel@tonic-gate 	if (a == NULL) {
9707c478bd9Sstevel@tonic-gate 		errlog(ERROR | FATAL,
9717c478bd9Sstevel@tonic-gate 		    "Internal Error: strdup() failure in "
9727c478bd9Sstevel@tonic-gate 		    "set_version_arch()");
9737c478bd9Sstevel@tonic-gate 	}
9747c478bd9Sstevel@tonic-gate 
9757c478bd9Sstevel@tonic-gate 	p = strchr(a, '=');
9767c478bd9Sstevel@tonic-gate 	if (p) {
9777c478bd9Sstevel@tonic-gate 		*p = '\0';
9787c478bd9Sstevel@tonic-gate 		x = arch_strtoi(a);
9797c478bd9Sstevel@tonic-gate 		if (x == 0) {
9807c478bd9Sstevel@tonic-gate 			errlog(INPUT|ERROR,
9817c478bd9Sstevel@tonic-gate 			    "Error: Invalid architecture: %s", a);
9827c478bd9Sstevel@tonic-gate 			retval = VS_INVARCH;
9837c478bd9Sstevel@tonic-gate 		} else {
9847c478bd9Sstevel@tonic-gate 			Version_Arch |= x;
9857c478bd9Sstevel@tonic-gate 			retval = 0;
9867c478bd9Sstevel@tonic-gate 		}
9877c478bd9Sstevel@tonic-gate 	}
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate 	free(a);
9907c478bd9Sstevel@tonic-gate 	return (retval);
9917c478bd9Sstevel@tonic-gate }
9927c478bd9Sstevel@tonic-gate 
9937c478bd9Sstevel@tonic-gate /*
9947c478bd9Sstevel@tonic-gate  * set_supported_arch ()
9957c478bd9Sstevel@tonic-gate  * input must be a string listing the architectures to be supported
9967c478bd9Sstevel@tonic-gate  * turns on bits of global Supported_Arch that correspond to the architecture
9977c478bd9Sstevel@tonic-gate  * return 0 upon success, EINVAL on failure
9987c478bd9Sstevel@tonic-gate  */
9997c478bd9Sstevel@tonic-gate static int
set_supported_arch(const char * arch)10007c478bd9Sstevel@tonic-gate set_supported_arch(const char *arch)
10017c478bd9Sstevel@tonic-gate {
10027c478bd9Sstevel@tonic-gate 	char	*a, *p, *tmp;
10037c478bd9Sstevel@tonic-gate 	int	retval = EINVAL;
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate 	if (arch == NULL || *arch == '\0')
10067c478bd9Sstevel@tonic-gate 		return (EINVAL);
10077c478bd9Sstevel@tonic-gate 
10087c478bd9Sstevel@tonic-gate 	tmp = strdup(arch);
10097c478bd9Sstevel@tonic-gate 	if (tmp == NULL) {
10107c478bd9Sstevel@tonic-gate 		errlog(ERROR | FATAL, "Internal Error: strdup() failure in "
10117c478bd9Sstevel@tonic-gate 		    "set_supported_arch()");
10127c478bd9Sstevel@tonic-gate 	}
10137c478bd9Sstevel@tonic-gate 
10147c478bd9Sstevel@tonic-gate 	p = tmp;
10157c478bd9Sstevel@tonic-gate 	while ((a = strtok(p, " ,\t\n"))) {
10167c478bd9Sstevel@tonic-gate 		int x;
10177c478bd9Sstevel@tonic-gate 		x = arch_strtoi(a);
10187c478bd9Sstevel@tonic-gate 		if (x == 0) {
10197c478bd9Sstevel@tonic-gate 			errlog(INPUT|ERROR,
10207c478bd9Sstevel@tonic-gate 			    "Error: Invalid architecture: %s", a);
10217c478bd9Sstevel@tonic-gate 			free(tmp);
10227c478bd9Sstevel@tonic-gate 			return (EINVAL);
10237c478bd9Sstevel@tonic-gate 		}
10247c478bd9Sstevel@tonic-gate 		Supported_Arch |= x;
10257c478bd9Sstevel@tonic-gate 		retval = 0;
10267c478bd9Sstevel@tonic-gate 		p = NULL;
10277c478bd9Sstevel@tonic-gate 	}
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate 	free(tmp);
10307c478bd9Sstevel@tonic-gate 	return (retval);
10317c478bd9Sstevel@tonic-gate }
1032