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