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 2003 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 /* 30*753d2d2eSraf * Back-end functions for spec to mapfile converter 31*753d2d2eSraf */ 32*753d2d2eSraf 33*753d2d2eSraf #include <stdio.h> 34*753d2d2eSraf #include <stdlib.h> 35*753d2d2eSraf #include <ctype.h> 36*753d2d2eSraf #include <string.h> 37*753d2d2eSraf #include <errno.h> 38*753d2d2eSraf #include <sys/utsname.h> 39*753d2d2eSraf #include "xlator.h" 40*753d2d2eSraf #include "util.h" 41*753d2d2eSraf #include "bucket.h" 42*753d2d2eSraf 43*753d2d2eSraf /* Globals */ 44*753d2d2eSraf enum { 45*753d2d2eSraf /* These first four (commented out) are defined in parser.h */ 46*753d2d2eSraf /* XLATOR_KW_NOTFOUND = 0, */ 47*753d2d2eSraf /* XLATOR_KW_FUNC, */ 48*753d2d2eSraf /* XLATOR_KW_DATA, */ 49*753d2d2eSraf /* XLATOR_KW_END, */ 50*753d2d2eSraf XLATOR_KW_VERSION = 4, 51*753d2d2eSraf XLATOR_KW_ARCH, 52*753d2d2eSraf XLATOR_KW_BINDING, 53*753d2d2eSraf XLATOR_KW_FILTER, 54*753d2d2eSraf XLATOR_KW_AUXILIARY 55*753d2d2eSraf }; 56*753d2d2eSraf #define FIRST_TOKEN 4 /* Must match the first token in the enum above */ 57*753d2d2eSraf 58*753d2d2eSraf static xlator_keyword_t Keywords[] = { 59*753d2d2eSraf { "version", XLATOR_KW_VERSION }, 60*753d2d2eSraf { "arch", XLATOR_KW_ARCH }, 61*753d2d2eSraf { "binding", XLATOR_KW_BINDING }, 62*753d2d2eSraf { "filter", XLATOR_KW_FILTER }, 63*753d2d2eSraf { "auxiliary", XLATOR_KW_AUXILIARY }, 64*753d2d2eSraf { NULL, XLATOR_KW_NOTFOUND } 65*753d2d2eSraf }; 66*753d2d2eSraf 67*753d2d2eSraf static char const *OutputFile; 68*753d2d2eSraf static char const *Curfile; 69*753d2d2eSraf static char *Curfun; 70*753d2d2eSraf static int Curline; 71*753d2d2eSraf static Interface Iface; 72*753d2d2eSraf 73*753d2d2eSraf static int Verbosity; 74*753d2d2eSraf static int TargetArchToken; /* set from -a option to front-end */ 75*753d2d2eSraf char *TargetArchStr = NULL; /* from -a option to front-end */ 76*753d2d2eSraf int IsFilterLib = 0; /* set from -F option to front-end */ 77*753d2d2eSraf static int Supported_Arch = XLATOR_ALLARCH; /* from "Arch" SPEC keyword */ 78*753d2d2eSraf static int Flags; 79*753d2d2eSraf 80*753d2d2eSraf /* 81*753d2d2eSraf * WHAT!? 82*753d2d2eSraf * from Version line 83*753d2d2eSraf * 0 means architecture is not specified in the 84*753d2d2eSraf * version line so it applies to all versions 85*753d2d2eSraf */ 86*753d2d2eSraf static int Version_Arch; 87*753d2d2eSraf int Num_versfiles = 0; 88*753d2d2eSraf static int Has_Version; 89*753d2d2eSraf 90*753d2d2eSraf static char *Versfile; 91*753d2d2eSraf 92*753d2d2eSraf static char *getversion(const char *); 93*753d2d2eSraf static int version_sanity(const char *value, char **subv); 94*753d2d2eSraf static int arch_version_sanity(char *av); 95*753d2d2eSraf static char *getfilter(const char *); 96*753d2d2eSraf static void writemapfile(FILE *); 97*753d2d2eSraf static int set_version_arch(const char *); 98*753d2d2eSraf static int set_supported_arch(const char *); 99*753d2d2eSraf 100*753d2d2eSraf /* 101*753d2d2eSraf * xlator_init() 102*753d2d2eSraf * back-end initialization 103*753d2d2eSraf * returns pointer to Keywords on success 104*753d2d2eSraf * returns NULL pointer on failure 105*753d2d2eSraf */ 106*753d2d2eSraf xlator_keyword_t * 107*753d2d2eSraf xlator_init(const Translator_info *t_info) 108*753d2d2eSraf { 109*753d2d2eSraf /* 110*753d2d2eSraf * initially so we don't lose error messages from version_check 111*753d2d2eSraf * we'll set this again later based on ti_info.ti_verbosity 112*753d2d2eSraf */ 113*753d2d2eSraf seterrseverity(WARNING); 114*753d2d2eSraf 115*753d2d2eSraf /* set verbosity */ 116*753d2d2eSraf Verbosity = t_info->ti_verbosity; 117*753d2d2eSraf seterrseverity(t_info->ti_verbosity); 118*753d2d2eSraf 119*753d2d2eSraf /* Obtain translator flags */ 120*753d2d2eSraf Flags = t_info->ti_flags; 121*753d2d2eSraf 122*753d2d2eSraf /* 123*753d2d2eSraf * set Library Type 124*753d2d2eSraf * 1 if filter lib, 0 otherwise 125*753d2d2eSraf */ 126*753d2d2eSraf IsFilterLib = t_info->ti_libtype; 127*753d2d2eSraf 128*753d2d2eSraf /* set target architecture */ 129*753d2d2eSraf TargetArchStr = t_info->ti_arch; 130*753d2d2eSraf TargetArchToken = t_info->ti_archtoken; 131*753d2d2eSraf 132*753d2d2eSraf errlog(STATUS, "Architecture set to \"%s\"", TargetArchStr); 133*753d2d2eSraf 134*753d2d2eSraf /* set output file */ 135*753d2d2eSraf OutputFile = t_info->ti_output_file; 136*753d2d2eSraf if (OutputFile) { 137*753d2d2eSraf errlog(STATUS, "Output will go into %s", 138*753d2d2eSraf OutputFile); 139*753d2d2eSraf } else { 140*753d2d2eSraf OutputFile = "mapfile"; 141*753d2d2eSraf errlog(STATUS, "Using default output filename: %s", 142*753d2d2eSraf OutputFile); 143*753d2d2eSraf } 144*753d2d2eSraf 145*753d2d2eSraf /* obtain name of version file */ 146*753d2d2eSraf Versfile = t_info->ti_versfile; 147*753d2d2eSraf 148*753d2d2eSraf /* call create_lists() to setup for parse_versions() */ 149*753d2d2eSraf create_lists(); 150*753d2d2eSraf 151*753d2d2eSraf /* Process Vers Files */ 152*753d2d2eSraf if (parse_versions(Versfile)) { 153*753d2d2eSraf return (NULL); 154*753d2d2eSraf } 155*753d2d2eSraf 156*753d2d2eSraf return (Keywords); 157*753d2d2eSraf } 158*753d2d2eSraf 159*753d2d2eSraf /* 160*753d2d2eSraf * xlator_startlib() 161*753d2d2eSraf * start of library 162*753d2d2eSraf * returns: XLATOR_SUCCESS on success 163*753d2d2eSraf * XLATOR_SKIP if library is to be skipped 164*753d2d2eSraf * XLATOR_NONFATAL on error 165*753d2d2eSraf */ 166*753d2d2eSraf /*ARGSUSED*/ 167*753d2d2eSraf int 168*753d2d2eSraf xlator_startlib(char const *libname) 169*753d2d2eSraf { 170*753d2d2eSraf errlog(TRACING, "xlator_startlib"); 171*753d2d2eSraf return (XLATOR_SUCCESS); 172*753d2d2eSraf } 173*753d2d2eSraf 174*753d2d2eSraf /* 175*753d2d2eSraf * xlator_startfile() 176*753d2d2eSraf * start of spec file 177*753d2d2eSraf * returns: XLATOR_SUCCESS on success 178*753d2d2eSraf * XLATOR_SKIP if file is to be skipped 179*753d2d2eSraf * XLATOR_NONFATAL on error 180*753d2d2eSraf */ 181*753d2d2eSraf int 182*753d2d2eSraf xlator_startfile(char const *filename) 183*753d2d2eSraf { 184*753d2d2eSraf errlog(TRACING, "xlator_startfile"); 185*753d2d2eSraf 186*753d2d2eSraf Curfile = filename; 187*753d2d2eSraf 188*753d2d2eSraf return (XLATOR_SUCCESS); 189*753d2d2eSraf } 190*753d2d2eSraf 191*753d2d2eSraf /* 192*753d2d2eSraf * xlator_start_if () 193*753d2d2eSraf * start of interface specification 194*753d2d2eSraf * returns: XLATOR_SUCCESS on success 195*753d2d2eSraf * XLATOR_SKIP if interface is to be skipped 196*753d2d2eSraf * XLATOR_NONFATAL on error 197*753d2d2eSraf * XLATOR_FATAL on fatal error 198*753d2d2eSraf */ 199*753d2d2eSraf int 200*753d2d2eSraf xlator_start_if(const Meta_info meta_info, const int token, char *value) 201*753d2d2eSraf { 202*753d2d2eSraf char rhs[BUFSIZ]; 203*753d2d2eSraf char *kw; 204*753d2d2eSraf int err; 205*753d2d2eSraf 206*753d2d2eSraf errlog(TRACING, "xlator_start_if %s", value); 207*753d2d2eSraf 208*753d2d2eSraf switch (token) { 209*753d2d2eSraf case XLATOR_KW_FUNC: 210*753d2d2eSraf kw = "Function"; 211*753d2d2eSraf break; 212*753d2d2eSraf case XLATOR_KW_DATA: 213*753d2d2eSraf kw = "Data"; 214*753d2d2eSraf break; 215*753d2d2eSraf default: 216*753d2d2eSraf /* This should never happen */ 217*753d2d2eSraf errlog(ERROR, 218*753d2d2eSraf "\"%s\", line %d: Implementation error! " 219*753d2d2eSraf "Please file a bug\n", __FILE__, __LINE__); 220*753d2d2eSraf return (XLATOR_FATAL); 221*753d2d2eSraf } 222*753d2d2eSraf 223*753d2d2eSraf Curline = meta_info.mi_line_number; 224*753d2d2eSraf seterrline(Curline, meta_info.mi_filename, kw, value); 225*753d2d2eSraf 226*753d2d2eSraf if (Curfun != NULL) { 227*753d2d2eSraf errlog(INPUT|ERROR, 228*753d2d2eSraf "Error: Interface spec is missing the " 229*753d2d2eSraf "End keyword: %s", Curfun); 230*753d2d2eSraf return (XLATOR_NONFATAL); 231*753d2d2eSraf } 232*753d2d2eSraf 233*753d2d2eSraf err = sscanf(value, "%s", rhs); 234*753d2d2eSraf if (err == 0 || err == EOF) { 235*753d2d2eSraf errlog(INPUT|ERROR, 236*753d2d2eSraf "Error: Missing argument in \"%s\" line", kw); 237*753d2d2eSraf return (XLATOR_NONFATAL); 238*753d2d2eSraf } 239*753d2d2eSraf 240*753d2d2eSraf Curfun = strdup(rhs); 241*753d2d2eSraf 242*753d2d2eSraf if (Curfun == NULL) { 243*753d2d2eSraf errlog(ERROR | FATAL, 244*753d2d2eSraf "Internal Error: strdup() failure in xlator_startif()"); 245*753d2d2eSraf } 246*753d2d2eSraf 247*753d2d2eSraf Iface.IF_name = Curfun; 248*753d2d2eSraf Iface.IF_type = token; /* FUNCTION or DATA */ 249*753d2d2eSraf 250*753d2d2eSraf Iface.IF_version = NULL; 251*753d2d2eSraf Iface.IF_class = NULL; 252*753d2d2eSraf Has_Version = 0; 253*753d2d2eSraf Supported_Arch = XLATOR_ALLARCH; 254*753d2d2eSraf Version_Arch = 0; 255*753d2d2eSraf 256*753d2d2eSraf Iface.IF_binding = DEFAULT; 257*753d2d2eSraf 258*753d2d2eSraf Iface.IF_filter = NULL; 259*753d2d2eSraf Iface.IF_auxiliary = NULL; 260*753d2d2eSraf 261*753d2d2eSraf return (XLATOR_SUCCESS); 262*753d2d2eSraf } 263*753d2d2eSraf 264*753d2d2eSraf /* 265*753d2d2eSraf * xlator_take_kvpair() 266*753d2d2eSraf * processes spec keyword-value pairs 267*753d2d2eSraf * returns: XLATOR_SUCCESS on success 268*753d2d2eSraf * XLATOR_NONFATAL on error 269*753d2d2eSraf */ 270*753d2d2eSraf int 271*753d2d2eSraf xlator_take_kvpair(const Meta_info meta_info, const int token, 272*753d2d2eSraf char *value) 273*753d2d2eSraf { 274*753d2d2eSraf char *p; 275*753d2d2eSraf char *subv = NULL; 276*753d2d2eSraf char *key = Keywords[token-FIRST_TOKEN].key; 277*753d2d2eSraf 278*753d2d2eSraf Curline = meta_info.mi_line_number; 279*753d2d2eSraf seterrline(Curline, meta_info.mi_filename, key, value); 280*753d2d2eSraf 281*753d2d2eSraf errlog(TRACING, 282*753d2d2eSraf "take_kvpair called. ext_cnt=%d token=%d key=%s value=%s", 283*753d2d2eSraf meta_info.mi_ext_cnt, token, key, value); 284*753d2d2eSraf 285*753d2d2eSraf if (Curfun == NULL) { 286*753d2d2eSraf errlog(INPUT|ERROR, "Error: Keyword found outside " 287*753d2d2eSraf "an interface specification block, line %d", Curline); 288*753d2d2eSraf return (XLATOR_NONFATAL); 289*753d2d2eSraf } 290*753d2d2eSraf 291*753d2d2eSraf switch (token) { 292*753d2d2eSraf case XLATOR_KW_VERSION: 293*753d2d2eSraf if (meta_info.mi_ext_cnt != 0) 294*753d2d2eSraf return (XLATOR_SUCCESS); 295*753d2d2eSraf 296*753d2d2eSraf errlog(TRACING, "Version found. Setting Version to %s", value); 297*753d2d2eSraf 298*753d2d2eSraf /* Version line found ; used for auditing the SPEC */ 299*753d2d2eSraf Has_Version = 1; 300*753d2d2eSraf 301*753d2d2eSraf /* remove trailing white space */ 302*753d2d2eSraf p = strrchr(value, '\n'); 303*753d2d2eSraf if (p) { 304*753d2d2eSraf while (p >= value && isspace(*p)) { 305*753d2d2eSraf *p = '\0'; 306*753d2d2eSraf --p; 307*753d2d2eSraf } 308*753d2d2eSraf } 309*753d2d2eSraf 310*753d2d2eSraf /* is the version line valid */ 311*753d2d2eSraf switch (version_sanity(value, &subv)) { 312*753d2d2eSraf case VS_OK: /* OK, subv not set */ 313*753d2d2eSraf break; 314*753d2d2eSraf 315*753d2d2eSraf case VS_INVARCH: /* Invalid Arch */ 316*753d2d2eSraf errlog(INPUT|ERROR, "Error: Invalid architecture " 317*753d2d2eSraf "string found in spec or version file: %s", subv); 318*753d2d2eSraf free(subv); 319*753d2d2eSraf return (XLATOR_NONFATAL); 320*753d2d2eSraf 321*753d2d2eSraf case VS_INVVERS: /* Invalid Version String */ 322*753d2d2eSraf errlog(INPUT|ERROR, "Error: Invalid version string " 323*753d2d2eSraf "in spec or version file: %s", subv); 324*753d2d2eSraf free(subv); 325*753d2d2eSraf return (XLATOR_NONFATAL); 326*753d2d2eSraf 327*753d2d2eSraf case VS_INVALID: /* Both Version and Arch are invalid */ 328*753d2d2eSraf errlog(INPUT|ERROR, "Error: Invalid version and " 329*753d2d2eSraf "architecture string in spec or version file" 330*753d2d2eSraf ": %s", subv); 331*753d2d2eSraf free(subv); 332*753d2d2eSraf return (XLATOR_NONFATAL); 333*753d2d2eSraf 334*753d2d2eSraf default: /* BAD IMPLEMENTATION OF version_sanity */ 335*753d2d2eSraf errlog(FATAL, "Error: bad return value from " 336*753d2d2eSraf "version_sanity()! This should never happen!"); 337*753d2d2eSraf } 338*753d2d2eSraf 339*753d2d2eSraf errlog(TRACING, "Version_Arch=%d", Version_Arch); 340*753d2d2eSraf 341*753d2d2eSraf Iface.IF_version = getversion(value); 342*753d2d2eSraf break; 343*753d2d2eSraf 344*753d2d2eSraf case XLATOR_KW_ARCH: 345*753d2d2eSraf if (meta_info.mi_ext_cnt != 0) 346*753d2d2eSraf return (XLATOR_SUCCESS); 347*753d2d2eSraf 348*753d2d2eSraf if (value[0] != '\0') { 349*753d2d2eSraf Supported_Arch = 0; 350*753d2d2eSraf if (set_supported_arch(value)) { 351*753d2d2eSraf errlog(INPUT|ERROR, 352*753d2d2eSraf "Error: Unable to parse Arch line"); 353*753d2d2eSraf return (XLATOR_NONFATAL); 354*753d2d2eSraf } 355*753d2d2eSraf } else { 356*753d2d2eSraf errlog(INPUT | ERROR, "Error: Empty Arch line."); 357*753d2d2eSraf } 358*753d2d2eSraf 359*753d2d2eSraf if (Supported_Arch == 0) { 360*753d2d2eSraf errlog(INPUT | ERROR, 361*753d2d2eSraf "Error: Unknown architecture defined in Arch line"); 362*753d2d2eSraf } 363*753d2d2eSraf 364*753d2d2eSraf errlog(TRACING, 365*753d2d2eSraf "Interface %s supports the following architectures: " 366*753d2d2eSraf "%s\tSupported_Arch=%d", Curfun, value, Supported_Arch); 367*753d2d2eSraf break; 368*753d2d2eSraf 369*753d2d2eSraf case XLATOR_KW_BINDING: 370*753d2d2eSraf 371*753d2d2eSraf /* 372*753d2d2eSraf * Note that we allow extends for the binding keyword by 373*753d2d2eSraf * not checking that meta_info.mi_ext_cnt == 0 here. 374*753d2d2eSraf */ 375*753d2d2eSraf 376*753d2d2eSraf /* remove trailing white space */ 377*753d2d2eSraf p = strrchr(value, '\n'); 378*753d2d2eSraf if (p) { 379*753d2d2eSraf while (p >= value && isspace(*p)) { 380*753d2d2eSraf *p = '\0'; 381*753d2d2eSraf --p; 382*753d2d2eSraf } 383*753d2d2eSraf } 384*753d2d2eSraf 385*753d2d2eSraf if (value[0] != '\0') { 386*753d2d2eSraf if (strcmp(value, "direct") == 0) { 387*753d2d2eSraf Iface.IF_binding = DIRECT; 388*753d2d2eSraf } else if (strcmp(value, "nodirect") == 0) { 389*753d2d2eSraf Iface.IF_binding = NODIRECT; 390*753d2d2eSraf } else if (strcmp(value, "protected") == 0) { 391*753d2d2eSraf Iface.IF_binding = PROTECTED; 392*753d2d2eSraf } else { 393*753d2d2eSraf errlog(INPUT|ERROR, 394*753d2d2eSraf "Error: Invalid binding value: %s", value); 395*753d2d2eSraf } 396*753d2d2eSraf } else { 397*753d2d2eSraf errlog(INPUT | ERROR, "Error: Empty Binding line."); 398*753d2d2eSraf } 399*753d2d2eSraf 400*753d2d2eSraf errlog(TRACING, 401*753d2d2eSraf "Interface %s has binding value: " 402*753d2d2eSraf "%s", Curfun, value); 403*753d2d2eSraf break; 404*753d2d2eSraf 405*753d2d2eSraf case XLATOR_KW_FILTER: 406*753d2d2eSraf case XLATOR_KW_AUXILIARY: 407*753d2d2eSraf /* 408*753d2d2eSraf * The following is for the "extends" clause. As with 409*753d2d2eSraf * XLATOR_KW_VERSION, we do not want to follow an "extends" 410*753d2d2eSraf * chain to get the filter or auxiliary values: we want 411*753d2d2eSraf * the first/most-tightly-bound one (mi_ext_cnt = 0). 412*753d2d2eSraf */ 413*753d2d2eSraf if (meta_info.mi_ext_cnt != 0) 414*753d2d2eSraf return (XLATOR_SUCCESS); 415*753d2d2eSraf 416*753d2d2eSraf errlog(TRACING, "Filter[token=%d] found. Setting Filter to %s", 417*753d2d2eSraf token, value); 418*753d2d2eSraf 419*753d2d2eSraf /* remove trailing white space */ 420*753d2d2eSraf p = strrchr(value, '\n'); 421*753d2d2eSraf if (p) { 422*753d2d2eSraf while (p >= value && isspace(*p)) { 423*753d2d2eSraf *p = '\0'; 424*753d2d2eSraf --p; 425*753d2d2eSraf } 426*753d2d2eSraf } 427*753d2d2eSraf 428*753d2d2eSraf errlog(TRACING, "Version_Arch=%d", Version_Arch); 429*753d2d2eSraf 430*753d2d2eSraf if (token == XLATOR_KW_FILTER) { 431*753d2d2eSraf Iface.IF_filter = getfilter(value); 432*753d2d2eSraf } else if (token == XLATOR_KW_AUXILIARY) { 433*753d2d2eSraf Iface.IF_auxiliary = getfilter(value); 434*753d2d2eSraf } 435*753d2d2eSraf 436*753d2d2eSraf break; 437*753d2d2eSraf default: 438*753d2d2eSraf errlog(INPUT|ERROR, "Error: Unrecognized keyword snuck in!" 439*753d2d2eSraf "\tThis is a programmer error: %s", key); 440*753d2d2eSraf return (XLATOR_NONFATAL); 441*753d2d2eSraf } 442*753d2d2eSraf 443*753d2d2eSraf return (XLATOR_SUCCESS); 444*753d2d2eSraf } 445*753d2d2eSraf 446*753d2d2eSraf /* 447*753d2d2eSraf * xlator_end_if () 448*753d2d2eSraf * signal end of spec interface spec 449*753d2d2eSraf * returns: XLATOR_SUCCESS on success 450*753d2d2eSraf * XLATOR_NONFATAL on error 451*753d2d2eSraf */ 452*753d2d2eSraf /*ARGSUSED*/ 453*753d2d2eSraf int 454*753d2d2eSraf xlator_end_if(const Meta_info M, const char *value) 455*753d2d2eSraf { 456*753d2d2eSraf int retval = XLATOR_NONFATAL; 457*753d2d2eSraf int picky = Flags & XLATOR_PICKY_FLAG; 458*753d2d2eSraf 459*753d2d2eSraf seterrline(M.mi_line_number, M.mi_filename, "End", ""); 460*753d2d2eSraf errlog(TRACING, "xlator_end_if"); 461*753d2d2eSraf 462*753d2d2eSraf if (Curfun == NULL) { 463*753d2d2eSraf errlog(INPUT | ERROR, "Error: End without " 464*753d2d2eSraf "matching Function or Data in file \"%s\"", Curfile); 465*753d2d2eSraf goto cleanup; 466*753d2d2eSraf } 467*753d2d2eSraf 468*753d2d2eSraf errlog(TRACING, "Interface=%s", Iface.IF_name); 469*753d2d2eSraf 470*753d2d2eSraf if (!Has_Version) { 471*753d2d2eSraf if (picky) { 472*753d2d2eSraf errlog(INPUT | ERROR, "Error: Interface has no " 473*753d2d2eSraf "Version!\n\tInterface=%s\n\tSPEC File=%s", 474*753d2d2eSraf Iface.IF_name, Curfile); 475*753d2d2eSraf } else { 476*753d2d2eSraf errlog(INPUT | WARNING, "Warning: Interface has " 477*753d2d2eSraf "no Version!\n\tInterface=%s\n\tSPEC File=%s", 478*753d2d2eSraf Iface.IF_name, Curfile); 479*753d2d2eSraf retval = XLATOR_SUCCESS; 480*753d2d2eSraf } 481*753d2d2eSraf goto cleanup; 482*753d2d2eSraf } 483*753d2d2eSraf 484*753d2d2eSraf if (Version_Arch & (~Supported_Arch)) { 485*753d2d2eSraf errlog(INPUT | ERROR, "Error: Architectures in Version " 486*753d2d2eSraf "line must be a subset of Architectures in Arch line\n" 487*753d2d2eSraf "\tInterface=%s\n\tSPEC File=%s", Iface.IF_name, Curfile); 488*753d2d2eSraf goto cleanup; 489*753d2d2eSraf } 490*753d2d2eSraf 491*753d2d2eSraf if ((TargetArchToken & Supported_Arch) == 0) { 492*753d2d2eSraf /* 493*753d2d2eSraf * This interface is not for the architecture 494*753d2d2eSraf * we are currently processing, so we skip it. 495*753d2d2eSraf */ 496*753d2d2eSraf retval = XLATOR_SUCCESS; 497*753d2d2eSraf goto cleanup; 498*753d2d2eSraf } 499*753d2d2eSraf 500*753d2d2eSraf if (Iface.IF_version == NULL) { 501*753d2d2eSraf if (picky) { 502*753d2d2eSraf errlog(ERROR|INPUT, 503*753d2d2eSraf "Error: Version was not found for " 504*753d2d2eSraf "\"%s\" architecture\n\tInterface=%s", 505*753d2d2eSraf TargetArchStr, Iface.IF_name); 506*753d2d2eSraf } else { 507*753d2d2eSraf errlog(WARNING | INPUT, 508*753d2d2eSraf "Warning: Version was not found for " 509*753d2d2eSraf "\"%s\" architecture\n\tInterface=%s", 510*753d2d2eSraf TargetArchStr, Iface.IF_name); 511*753d2d2eSraf retval = XLATOR_SUCCESS; 512*753d2d2eSraf } 513*753d2d2eSraf goto cleanup; 514*753d2d2eSraf } 515*753d2d2eSraf 516*753d2d2eSraf /* check Iface.IF_type */ 517*753d2d2eSraf switch (Iface.IF_type) { 518*753d2d2eSraf case FUNCTION: 519*753d2d2eSraf errlog(VERBOSE, "Interface type = FUNCTION"); 520*753d2d2eSraf break; 521*753d2d2eSraf case DATA: 522*753d2d2eSraf errlog(VERBOSE, "Interface type = DATA"); 523*753d2d2eSraf break; 524*753d2d2eSraf case NOTYPE: 525*753d2d2eSraf errlog(WARNING, 526*753d2d2eSraf "Warning: Interface is neither " 527*753d2d2eSraf "DATA nor FUNCTION!!\n\t" 528*753d2d2eSraf "Interface=%s\n\tSPEC File=%s", 529*753d2d2eSraf Iface.IF_name, Curfile); 530*753d2d2eSraf break; 531*753d2d2eSraf default: 532*753d2d2eSraf errlog(ERROR, "Error: Bad spec2map implementation!\n" 533*753d2d2eSraf "\tInterface type is invalid\n" 534*753d2d2eSraf "\tThis should never happen.\n" 535*753d2d2eSraf "\tInterface=%s\tSPEC File=%s", Iface.IF_name, Curfile); 536*753d2d2eSraf goto cleanup; 537*753d2d2eSraf } 538*753d2d2eSraf 539*753d2d2eSraf (void) add_by_name(Iface.IF_version, &Iface); 540*753d2d2eSraf 541*753d2d2eSraf retval = XLATOR_SUCCESS; 542*753d2d2eSraf 543*753d2d2eSraf cleanup: 544*753d2d2eSraf 545*753d2d2eSraf /* cleanup */ 546*753d2d2eSraf Iface.IF_name = NULL; 547*753d2d2eSraf 548*753d2d2eSraf free(Iface.IF_version); 549*753d2d2eSraf Iface.IF_version = NULL; 550*753d2d2eSraf 551*753d2d2eSraf free(Iface.IF_class); 552*753d2d2eSraf Iface.IF_class = NULL; 553*753d2d2eSraf 554*753d2d2eSraf free(Curfun); 555*753d2d2eSraf Curfun = NULL; 556*753d2d2eSraf 557*753d2d2eSraf Supported_Arch = XLATOR_ALLARCH; 558*753d2d2eSraf return (retval); 559*753d2d2eSraf } 560*753d2d2eSraf 561*753d2d2eSraf /* 562*753d2d2eSraf * xlator_endfile() 563*753d2d2eSraf * signal end of spec file 564*753d2d2eSraf * returns: XLATOR_SUCCESS on success 565*753d2d2eSraf * XLATOR_NONFATAL on error 566*753d2d2eSraf */ 567*753d2d2eSraf int 568*753d2d2eSraf xlator_endfile(void) 569*753d2d2eSraf { 570*753d2d2eSraf 571*753d2d2eSraf errlog(TRACING, "xlator_endfile"); 572*753d2d2eSraf 573*753d2d2eSraf Curfile = NULL; 574*753d2d2eSraf 575*753d2d2eSraf return (XLATOR_SUCCESS); 576*753d2d2eSraf } 577*753d2d2eSraf 578*753d2d2eSraf /* 579*753d2d2eSraf * xlator_endlib() 580*753d2d2eSraf * signal end of library 581*753d2d2eSraf * returns: XLATOR_SUCCESS on success 582*753d2d2eSraf * XLATOR_NONFATAL on error 583*753d2d2eSraf */ 584*753d2d2eSraf int 585*753d2d2eSraf xlator_endlib(void) 586*753d2d2eSraf { 587*753d2d2eSraf FILE *mapfp; 588*753d2d2eSraf int retval = XLATOR_SUCCESS; 589*753d2d2eSraf 590*753d2d2eSraf errlog(TRACING, "xlator_endlib"); 591*753d2d2eSraf 592*753d2d2eSraf /* Pretend to print mapfile */ 593*753d2d2eSraf if (Verbosity >= TRACING) { 594*753d2d2eSraf print_all_buckets(); 595*753d2d2eSraf } 596*753d2d2eSraf 597*753d2d2eSraf /* Everything read, now organize it! */ 598*753d2d2eSraf sort_buckets(); 599*753d2d2eSraf add_local(); 600*753d2d2eSraf 601*753d2d2eSraf /* Create Output */ 602*753d2d2eSraf mapfp = fopen(OutputFile, "w"); 603*753d2d2eSraf if (mapfp == NULL) { 604*753d2d2eSraf errlog(ERROR, 605*753d2d2eSraf "Error: Unable to open output file \"%s\"\n\t%s", 606*753d2d2eSraf OutputFile, strerror(errno)); 607*753d2d2eSraf retval = XLATOR_NONFATAL; 608*753d2d2eSraf } else { 609*753d2d2eSraf writemapfile(mapfp); 610*753d2d2eSraf (void) fclose(mapfp); 611*753d2d2eSraf } 612*753d2d2eSraf 613*753d2d2eSraf return (retval); 614*753d2d2eSraf } 615*753d2d2eSraf 616*753d2d2eSraf /* 617*753d2d2eSraf * xlator_end() 618*753d2d2eSraf * signal end of translation 619*753d2d2eSraf * returns: XLATOR_SUCCESS on success 620*753d2d2eSraf * XLATOR_NONFATAL on error 621*753d2d2eSraf */ 622*753d2d2eSraf int 623*753d2d2eSraf xlator_end(void) 624*753d2d2eSraf { 625*753d2d2eSraf errlog(TRACING, "xlator_end"); 626*753d2d2eSraf 627*753d2d2eSraf /* Destroy the list created by create_lists */ 628*753d2d2eSraf delete_lists(); 629*753d2d2eSraf 630*753d2d2eSraf return (XLATOR_SUCCESS); 631*753d2d2eSraf } 632*753d2d2eSraf 633*753d2d2eSraf /* 634*753d2d2eSraf * getversion() 635*753d2d2eSraf * called by xlator_take_kvpair when Version keyword is found 636*753d2d2eSraf * parses the Version string and returns the one that matches 637*753d2d2eSraf * the current target architecture 638*753d2d2eSraf * 639*753d2d2eSraf * the pointer returned by this function must be freed later. 640*753d2d2eSraf */ 641*753d2d2eSraf static char * 642*753d2d2eSraf getversion(const char *value) 643*753d2d2eSraf { 644*753d2d2eSraf char *v, *p; 645*753d2d2eSraf char arch[ARCHBUFLEN]; 646*753d2d2eSraf int archlen; 647*753d2d2eSraf 648*753d2d2eSraf /* up to ARCHBUFLEN-1 */ 649*753d2d2eSraf (void) strncpy(arch, TargetArchStr, ARCHBUFLEN-1); 650*753d2d2eSraf arch[ARCHBUFLEN-2] = '\0'; 651*753d2d2eSraf (void) strcat(arch, "="); /* append an '=' */ 652*753d2d2eSraf archlen = strlen(arch); 653*753d2d2eSraf 654*753d2d2eSraf errlog(VERBOSE, "getversion: value=%s", value); 655*753d2d2eSraf 656*753d2d2eSraf if (strchr(value, '=') != NULL) { 657*753d2d2eSraf if ((v = strstr(value, arch)) != NULL) { 658*753d2d2eSraf p = strdup(v + archlen); 659*753d2d2eSraf if (p == NULL) { 660*753d2d2eSraf errlog(ERROR | FATAL, 661*753d2d2eSraf "Internal Error: strdup() failure " 662*753d2d2eSraf "in getversion()"); 663*753d2d2eSraf } 664*753d2d2eSraf v = p; 665*753d2d2eSraf while (!isspace(*v) && *v != '\0') 666*753d2d2eSraf ++v; 667*753d2d2eSraf *v = '\0'; 668*753d2d2eSraf } else { 669*753d2d2eSraf errlog(VERBOSE, "getversion returns: NULL"); 670*753d2d2eSraf return (NULL); 671*753d2d2eSraf } 672*753d2d2eSraf } else { 673*753d2d2eSraf p = strdup(value); 674*753d2d2eSraf if (p == NULL) { 675*753d2d2eSraf errlog(ERROR | FATAL, "Internal Error: strdup() " 676*753d2d2eSraf "failure in getversion()"); 677*753d2d2eSraf } 678*753d2d2eSraf } 679*753d2d2eSraf 680*753d2d2eSraf if (p != NULL) 681*753d2d2eSraf errlog(VERBOSE, "getversion returns: %s", p); 682*753d2d2eSraf else 683*753d2d2eSraf errlog(VERBOSE, "getversion returns: NULL"); 684*753d2d2eSraf 685*753d2d2eSraf return (p); 686*753d2d2eSraf } 687*753d2d2eSraf 688*753d2d2eSraf /* 689*753d2d2eSraf * getfilter() 690*753d2d2eSraf * Called by xlator_take_kvpair when "filter" or "auxiliary" keyword is 691*753d2d2eSraf * found. Parses the Filter/Auxiliary string and returns the one that 692*753d2d2eSraf * matches the current target architecture 693*753d2d2eSraf * 694*753d2d2eSraf * The pointer returned by this function must be freed later. 695*753d2d2eSraf * 696*753d2d2eSraf * Note that returning NULL here indicates there was no desired 697*753d2d2eSraf * arch=path item in value, i.e. for TargetArchStr the interface is 698*753d2d2eSraf * not a filter. 699*753d2d2eSraf */ 700*753d2d2eSraf static char * 701*753d2d2eSraf getfilter(const char *value) 702*753d2d2eSraf { 703*753d2d2eSraf char *v, *p; 704*753d2d2eSraf char arch[ARCHBUFLEN]; 705*753d2d2eSraf int archlen; 706*753d2d2eSraf 707*753d2d2eSraf /* up to ARCHBUFLEN-1 */ 708*753d2d2eSraf (void) strncpy(arch, TargetArchStr, ARCHBUFLEN-1); 709*753d2d2eSraf arch[ARCHBUFLEN-2] = '\0'; 710*753d2d2eSraf (void) strcat(arch, "="); /* append an '=' */ 711*753d2d2eSraf archlen = strlen(arch); 712*753d2d2eSraf 713*753d2d2eSraf errlog(VERBOSE, "getfilter: value=%s", value); 714*753d2d2eSraf 715*753d2d2eSraf if (strchr(value, '=') != NULL) { 716*753d2d2eSraf if ((v = strstr(value, arch)) != NULL) { 717*753d2d2eSraf p = strdup(v + archlen); 718*753d2d2eSraf if (p == NULL) { 719*753d2d2eSraf errlog(ERROR | FATAL, 720*753d2d2eSraf "Internal Error: strdup() failure " 721*753d2d2eSraf "in getfilter()"); 722*753d2d2eSraf } 723*753d2d2eSraf v = p; 724*753d2d2eSraf while (!isspace(*v) && *v != '\0') 725*753d2d2eSraf ++v; 726*753d2d2eSraf *v = '\0'; 727*753d2d2eSraf } else { 728*753d2d2eSraf errlog(VERBOSE, "getfilter returns: NULL"); 729*753d2d2eSraf return (NULL); 730*753d2d2eSraf } 731*753d2d2eSraf } else { 732*753d2d2eSraf p = strdup(value); 733*753d2d2eSraf if (p == NULL) { 734*753d2d2eSraf errlog(ERROR | FATAL, "Internal Error: strdup() " 735*753d2d2eSraf "failure in getfilter()"); 736*753d2d2eSraf } 737*753d2d2eSraf } 738*753d2d2eSraf 739*753d2d2eSraf if (p != NULL) 740*753d2d2eSraf errlog(VERBOSE, "getfilter returns: %s", p); 741*753d2d2eSraf else 742*753d2d2eSraf errlog(VERBOSE, "getfilter returns: NULL"); 743*753d2d2eSraf 744*753d2d2eSraf return (p); 745*753d2d2eSraf } 746*753d2d2eSraf 747*753d2d2eSraf /* 748*753d2d2eSraf * version_sanity() 749*753d2d2eSraf * for each version info in the Version line 750*753d2d2eSraf * check for its validity. 751*753d2d2eSraf * Set Version_arch to reflect all supported architectures if successful. 752*753d2d2eSraf * Upon return on failure, subv will contain the last version string 753*753d2d2eSraf * processed 754*753d2d2eSraf * returns: VS_OK OK 755*753d2d2eSraf * VS_INVARCH Invalid Architecture 756*753d2d2eSraf * VS_INVVERS Invalid Version String 757*753d2d2eSraf * VS_INVALID Both Version and Architecture are invalid; 758*753d2d2eSraf */ 759*753d2d2eSraf static int 760*753d2d2eSraf version_sanity(const char *value, char **subv) 761*753d2d2eSraf { 762*753d2d2eSraf char *p, *v, *a; 763*753d2d2eSraf int retval = VS_INVALID; 764*753d2d2eSraf 765*753d2d2eSraf if (strchr(value, '=')) { 766*753d2d2eSraf /* Form 1: Version arch=Version_string */ 767*753d2d2eSraf v = strdup(value); 768*753d2d2eSraf if (v == NULL) { 769*753d2d2eSraf errlog(ERROR | FATAL, 770*753d2d2eSraf "Internal Error: strdup() failure in " 771*753d2d2eSraf "version_sanity()"); 772*753d2d2eSraf } 773*753d2d2eSraf 774*753d2d2eSraf /* process each arch=version string */ 775*753d2d2eSraf p = v; 776*753d2d2eSraf while ((a = strtok(p, " \t\n"))) { 777*753d2d2eSraf if ((retval = arch_version_sanity(a)) != VS_OK) { 778*753d2d2eSraf *subv = strdup(a); 779*753d2d2eSraf if (subv == NULL) { 780*753d2d2eSraf errlog(ERROR | FATAL, 781*753d2d2eSraf "Internal Error: strdup() failure " 782*753d2d2eSraf "in version_sanity()"); 783*753d2d2eSraf } 784*753d2d2eSraf break; 785*753d2d2eSraf } 786*753d2d2eSraf if ((retval = set_version_arch(a)) != VS_OK) { 787*753d2d2eSraf /* set the global Version_arch */ 788*753d2d2eSraf *subv = strdup(a); 789*753d2d2eSraf if (subv == NULL) { 790*753d2d2eSraf errlog(ERROR | FATAL, 791*753d2d2eSraf "Internal Error: strdup() failure " 792*753d2d2eSraf "in version_sanity()"); 793*753d2d2eSraf } 794*753d2d2eSraf break; 795*753d2d2eSraf } 796*753d2d2eSraf p = NULL; 797*753d2d2eSraf } 798*753d2d2eSraf free(v); 799*753d2d2eSraf } else { 800*753d2d2eSraf /* Form 2: Version Version_string */ 801*753d2d2eSraf if (valid_version(value)) { 802*753d2d2eSraf retval = VS_OK; 803*753d2d2eSraf } else { 804*753d2d2eSraf *subv = strdup(value); 805*753d2d2eSraf if (subv == NULL) { 806*753d2d2eSraf errlog(ERROR | FATAL, 807*753d2d2eSraf "Internal Error: strdup() failure " 808*753d2d2eSraf "in version_sanity()"); 809*753d2d2eSraf } 810*753d2d2eSraf } 811*753d2d2eSraf } 812*753d2d2eSraf return (retval); 813*753d2d2eSraf } 814*753d2d2eSraf 815*753d2d2eSraf /* 816*753d2d2eSraf * arch_version_sanity() 817*753d2d2eSraf * checks version lines of the form "arch=version" 818*753d2d2eSraf * av MUST be a string of the form "arch=version" (no spaces) 819*753d2d2eSraf * returns: VS_OK OK 820*753d2d2eSraf * VS_INVARCH Invalid Architecture 821*753d2d2eSraf * VS_INVVERS Invalid Version String 822*753d2d2eSraf * VS_INVALID Both Versions are invalid; 823*753d2d2eSraf */ 824*753d2d2eSraf static int 825*753d2d2eSraf arch_version_sanity(char *av) 826*753d2d2eSraf { 827*753d2d2eSraf char *p, *v; 828*753d2d2eSraf int retval = VS_OK; 829*753d2d2eSraf 830*753d2d2eSraf p = strchr(av, '='); 831*753d2d2eSraf if (p == NULL) { 832*753d2d2eSraf errlog(INPUT|ERROR, "Error: Incorrect format of Version line"); 833*753d2d2eSraf return (VS_INVALID); 834*753d2d2eSraf } 835*753d2d2eSraf 836*753d2d2eSraf *p = '\0'; /* stick a '\0' where the '=' was */ 837*753d2d2eSraf v = p + 1; 838*753d2d2eSraf 839*753d2d2eSraf if (valid_arch(av) == 0) 840*753d2d2eSraf retval = VS_INVARCH; 841*753d2d2eSraf 842*753d2d2eSraf if (valid_version(v) == 0) 843*753d2d2eSraf retval += VS_INVVERS; 844*753d2d2eSraf 845*753d2d2eSraf *p = '='; /* restore the '=' */ 846*753d2d2eSraf 847*753d2d2eSraf return (retval); 848*753d2d2eSraf } 849*753d2d2eSraf 850*753d2d2eSraf /* 851*753d2d2eSraf * writemapfile() 852*753d2d2eSraf * called by xlator_endlib(); 853*753d2d2eSraf * writes out the map file 854*753d2d2eSraf */ 855*753d2d2eSraf static void 856*753d2d2eSraf writemapfile(FILE *mapfp) 857*753d2d2eSraf { 858*753d2d2eSraf bucket_t *l; /* List of buckets. */ 859*753d2d2eSraf bucket_t *b; /* Bucket within list. */ 860*753d2d2eSraf struct bucketlist *bl; 861*753d2d2eSraf table_t *t; 862*753d2d2eSraf int i = 0, n = 0; 863*753d2d2eSraf char **p; 864*753d2d2eSraf 865*753d2d2eSraf errlog(BEGIN, "writemapfile() {"); 866*753d2d2eSraf for (l = first_list(); l != NULL; l = next_list()) { 867*753d2d2eSraf 868*753d2d2eSraf for (b = first_from_list(l); b != NULL; b = next_from_list()) { 869*753d2d2eSraf errlog(TRACING, "b_name = %s", b->b_name); 870*753d2d2eSraf print_bucket(b); /* Debugging routine. */ 871*753d2d2eSraf 872*753d2d2eSraf if (!b->b_was_printed) { 873*753d2d2eSraf /* Ok, we can print it. */ 874*753d2d2eSraf b->b_was_printed = 1; 875*753d2d2eSraf (void) fprintf(mapfp, "%s {\n", b->b_name); 876*753d2d2eSraf 877*753d2d2eSraf if (b->b_weak != 1) { 878*753d2d2eSraf char *strtab; 879*753d2d2eSraf 880*753d2d2eSraf (void) fprintf(mapfp, " global:\n"); 881*753d2d2eSraf 882*753d2d2eSraf strtab = get_stringtable( 883*753d2d2eSraf b->b_global_table, 0); 884*753d2d2eSraf 885*753d2d2eSraf if (strtab == NULL) { 886*753d2d2eSraf /* 887*753d2d2eSraf * There were no interfaces 888*753d2d2eSraf * in the bucket. 889*753d2d2eSraf * Insert a dummy entry 890*753d2d2eSraf * to avoid a "weak version" 891*753d2d2eSraf */ 892*753d2d2eSraf (void) fprintf(mapfp, 893*753d2d2eSraf "\t%s;\n", b->b_name); 894*753d2d2eSraf } 895*753d2d2eSraf } else { 896*753d2d2eSraf (void) fprintf(mapfp, 897*753d2d2eSraf " # Weak version\n"); 898*753d2d2eSraf } 899*753d2d2eSraf /* Print all the interfaces in the bucket. */ 900*753d2d2eSraf t = b->b_global_table; 901*753d2d2eSraf n = t->used; 902*753d2d2eSraf 903*753d2d2eSraf for (i = 0; i <= n; ++i) { 904*753d2d2eSraf (void) fprintf(mapfp, "\t%s;\n", 905*753d2d2eSraf get_stringtable(t, i)); 906*753d2d2eSraf } 907*753d2d2eSraf 908*753d2d2eSraf if (b->b_has_protecteds) { 909*753d2d2eSraf t = b->b_protected_table; 910*753d2d2eSraf n = t->used; 911*753d2d2eSraf 912*753d2d2eSraf (void) fprintf(mapfp, 913*753d2d2eSraf " protected:\n"); 914*753d2d2eSraf 915*753d2d2eSraf for (i = 0; i <= n; ++i) { 916*753d2d2eSraf (void) fprintf(mapfp, "\t%s;\n", 917*753d2d2eSraf get_stringtable(t, i)); 918*753d2d2eSraf } 919*753d2d2eSraf } 920*753d2d2eSraf 921*753d2d2eSraf /* Conditionally add ``local: *;''. */ 922*753d2d2eSraf if (b->b_has_locals) { 923*753d2d2eSraf (void) fprintf(mapfp, 924*753d2d2eSraf " local:\n\t*;\n}"); 925*753d2d2eSraf } else { 926*753d2d2eSraf (void) fprintf(mapfp, "}"); 927*753d2d2eSraf } 928*753d2d2eSraf /* Print name of all parents. */ 929*753d2d2eSraf for (p = parents_of(b); 930*753d2d2eSraf p != NULL && *p != '\0'; ++p) { 931*753d2d2eSraf (void) fprintf(mapfp, " %s", *p); 932*753d2d2eSraf } 933*753d2d2eSraf bl = b->b_uncles; 934*753d2d2eSraf while (bl != NULL) { 935*753d2d2eSraf (void) fprintf(mapfp, " %s", 936*753d2d2eSraf bl->bl_bucket->b_name); 937*753d2d2eSraf bl = bl->bl_next; 938*753d2d2eSraf } 939*753d2d2eSraf 940*753d2d2eSraf (void) fprintf(mapfp, ";\n\n"); 941*753d2d2eSraf } else { 942*753d2d2eSraf /* 943*753d2d2eSraf * We've printed this one before, 944*753d2d2eSraf * so don't do it again. 945*753d2d2eSraf */ 946*753d2d2eSraf /*EMPTY*/; 947*753d2d2eSraf } 948*753d2d2eSraf } 949*753d2d2eSraf } 950*753d2d2eSraf errlog(END, "}"); 951*753d2d2eSraf } 952*753d2d2eSraf 953*753d2d2eSraf /* 954*753d2d2eSraf * set_version_arch () 955*753d2d2eSraf * input must be a string of the form "arch=version" 956*753d2d2eSraf * turns on bits of global Version_Arch that correspond to the "arch" 957*753d2d2eSraf * return VS_OK upon success 958*753d2d2eSraf * VS_INVARCH if architecture is invalid 959*753d2d2eSraf * EINVAL on other failure 960*753d2d2eSraf */ 961*753d2d2eSraf static int 962*753d2d2eSraf set_version_arch(const char *arch) 963*753d2d2eSraf { 964*753d2d2eSraf char *a, *p; 965*753d2d2eSraf int x; 966*753d2d2eSraf int retval = EINVAL; 967*753d2d2eSraf 968*753d2d2eSraf if (arch == NULL) 969*753d2d2eSraf return (retval); 970*753d2d2eSraf 971*753d2d2eSraf a = strdup(arch); 972*753d2d2eSraf if (a == NULL) { 973*753d2d2eSraf errlog(ERROR | FATAL, 974*753d2d2eSraf "Internal Error: strdup() failure in " 975*753d2d2eSraf "set_version_arch()"); 976*753d2d2eSraf } 977*753d2d2eSraf 978*753d2d2eSraf p = strchr(a, '='); 979*753d2d2eSraf if (p) { 980*753d2d2eSraf *p = '\0'; 981*753d2d2eSraf x = arch_strtoi(a); 982*753d2d2eSraf if (x == 0) { 983*753d2d2eSraf errlog(INPUT|ERROR, 984*753d2d2eSraf "Error: Invalid architecture: %s", a); 985*753d2d2eSraf retval = VS_INVARCH; 986*753d2d2eSraf } else { 987*753d2d2eSraf Version_Arch |= x; 988*753d2d2eSraf retval = 0; 989*753d2d2eSraf } 990*753d2d2eSraf } 991*753d2d2eSraf 992*753d2d2eSraf free(a); 993*753d2d2eSraf return (retval); 994*753d2d2eSraf } 995*753d2d2eSraf 996*753d2d2eSraf /* 997*753d2d2eSraf * set_supported_arch () 998*753d2d2eSraf * input must be a string listing the architectures to be supported 999*753d2d2eSraf * turns on bits of global Supported_Arch that correspond to the architecture 1000*753d2d2eSraf * return 0 upon success, EINVAL on failure 1001*753d2d2eSraf */ 1002*753d2d2eSraf static int 1003*753d2d2eSraf set_supported_arch(const char *arch) 1004*753d2d2eSraf { 1005*753d2d2eSraf char *a, *p, *tmp; 1006*753d2d2eSraf int retval = EINVAL; 1007*753d2d2eSraf 1008*753d2d2eSraf if (arch == NULL || *arch == '\0') 1009*753d2d2eSraf return (EINVAL); 1010*753d2d2eSraf 1011*753d2d2eSraf tmp = strdup(arch); 1012*753d2d2eSraf if (tmp == NULL) { 1013*753d2d2eSraf errlog(ERROR | FATAL, "Internal Error: strdup() failure in " 1014*753d2d2eSraf "set_supported_arch()"); 1015*753d2d2eSraf } 1016*753d2d2eSraf 1017*753d2d2eSraf p = tmp; 1018*753d2d2eSraf while ((a = strtok(p, " ,\t\n"))) { 1019*753d2d2eSraf int x; 1020*753d2d2eSraf x = arch_strtoi(a); 1021*753d2d2eSraf if (x == 0) { 1022*753d2d2eSraf errlog(INPUT|ERROR, 1023*753d2d2eSraf "Error: Invalid architecture: %s", a); 1024*753d2d2eSraf free(tmp); 1025*753d2d2eSraf return (EINVAL); 1026*753d2d2eSraf } 1027*753d2d2eSraf Supported_Arch |= x; 1028*753d2d2eSraf retval = 0; 1029*753d2d2eSraf p = NULL; 1030*753d2d2eSraf } 1031*753d2d2eSraf 1032*753d2d2eSraf free(tmp); 1033*753d2d2eSraf return (retval); 1034*753d2d2eSraf } 1035