1 /* 2 * gethost.c: Create version file from prototype 3 */ 4 /*- 5 * Copyright (c) 1980, 1991 The Regents of the University of California. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 #include "sh.h" 33 34 #ifdef SCO 35 # define perror __perror 36 # define rename __rename 37 # define getopt __getopt 38 # define system __system 39 #endif 40 #include <stdio.h> 41 #ifdef SCO 42 # undef perror 43 # undef rename 44 # undef getopt 45 # undef system 46 #endif 47 48 #include <ctype.h> 49 50 #define ISSPACE(p) (isspace((unsigned char) (p)) && (p) != '\n') 51 52 /* 53 * We cannot do that, because some compilers like #line and others 54 * like # <lineno> 55 * #define LINEDIRECTIVE 56 */ 57 58 static const char *keyword[] = 59 { 60 "vendor", 61 #define T_VENDOR 0 62 "hosttype", 63 #define T_HOSTTYPE 1 64 "machtype", 65 #define T_MACHTYPE 2 66 "ostype", 67 #define T_OSTYPE 3 68 "newdef", 69 #define T_NEWDEF 4 70 "enddef", 71 #define T_ENDDEF 5 72 "newcode", 73 #define T_NEWCODE 6 74 "endcode", 75 #define T_ENDCODE 7 76 "comment", 77 #define T_COMMENT 8 78 "macro", 79 #define T_MACRO 9 80 NULL 81 #define T_NONE 10 82 }; 83 84 #define S_DISCARD 0 85 #define S_COMMENT 1 86 #define S_CODE 2 87 #define S_KEYWORD 3 88 89 static int findtoken (char *); 90 static char *gettoken (char **, char *); 91 static char *pname; 92 93 int main (int, char *[]); 94 95 /* findtoken(): 96 * Return the token number of the given token 97 */ 98 static int 99 findtoken(char *ptr) 100 { 101 int i; 102 103 if (ptr == NULL || *ptr == '\0') 104 return T_NONE; 105 106 for (i = 0; keyword[i] != NULL; i++) 107 if (strcmp(keyword[i], ptr) == 0) 108 return i; 109 110 return T_NONE; 111 } 112 113 114 /* gettoken(): 115 * Get : delimited token and remove leading/trailing blanks/newlines 116 */ 117 static char * 118 gettoken(char **pptr, char *token) 119 { 120 char *ptr = *pptr; 121 char *tok = token; 122 123 for (; *ptr && ISSPACE(*ptr); ptr++) 124 continue; 125 126 for (; *ptr && *ptr != ':'; *tok++ = *ptr++) 127 continue; 128 129 if (*ptr == ':') 130 ptr++; 131 else 132 tok--; 133 134 for (tok--; tok >= token && *tok && ISSPACE(*tok); tok--) 135 continue; 136 137 *++tok = '\0'; 138 139 *pptr = ptr; 140 return token; 141 } 142 143 static char * 144 cat(const char *a, const char *b, size_t len) 145 { 146 size_t l; 147 char *r; 148 149 if (len == 0) 150 len = strlen(b) + 1; 151 if (a) 152 l = strlen(a) + len; 153 else 154 l = len; 155 if ((r = malloc(l)) == NULL) 156 abort(); 157 if (a) 158 snprintf(r, l, "%s%.*s", a, (int)len, b); 159 else 160 snprintf(r, l, "%.*s", (int)len, b); 161 return r; 162 } 163 164 static const char * 165 explode(const char *defs) 166 { 167 static const char def[] = "defined("; /* ) */ 168 static char *buf; 169 size_t len; 170 const char *ptr, *bptr, *eptr = NULL, *name; 171 172 if (strstr(defs, "#machine(" /* ) */)) 173 return defs; 174 if (!strstr(defs, def)) 175 return defs; 176 177 free(buf); 178 buf = NULL; 179 for (ptr = defs; (bptr = strstr(ptr, def)) != NULL; ptr = eptr + 1) { 180 if (ptr != bptr) 181 buf = cat(buf, ptr, bptr - ptr + 1); 182 buf = cat(buf, "(", 0); /* ) */ 183 if ((eptr = strchr(ptr + sizeof(def) - 1, ')')) == NULL) { 184 (void) fprintf(stderr, "%s: missing close paren `%s'\n", 185 pname, defs); 186 free(buf); 187 return defs; 188 } 189 buf = cat(buf, bptr, eptr - bptr + 1); 190 name = bptr + sizeof(def) - 1; 191 len = eptr - name; 192 if (len < 1) { 193 (void) fprintf(stderr, "%s: empty define `%s'\n", 194 pname, defs); 195 free(buf); 196 return defs; 197 } 198 if (*name != '_' && (*name != 'M' && name[1] != '_')) { 199 char *undername = malloc(len + 10); 200 if (undername == NULL) 201 abort(); 202 buf = cat(buf, ") || defined(", 0); 203 snprintf(undername, len + 10, "__%.*s__)", (int)len, 204 name); 205 buf = cat(buf, undername, len + 5); 206 buf = cat(buf, ") || defined(", 0); 207 snprintf(undername, len + 10, "__%.*s)", (int)len, 208 name); 209 buf = cat(buf, undername, len + 3); 210 } 211 buf = cat(buf, "))", 0); 212 } 213 if (!eptr) { 214 (void) fprintf(stderr, "%s: invalid input `%s'\n", pname, defs); 215 return defs; 216 } 217 buf = cat(buf, eptr + 1, 0); 218 return buf; 219 } 220 221 222 int 223 main(int argc, char *argv[]) 224 { 225 char line[INBUFSIZE]; 226 const char *fname = "stdin"; 227 char *ptr, *tok; 228 char defs[INBUFSIZE]; 229 char stmt[INBUFSIZE]; 230 FILE *fp = stdin; 231 int lineno = 0; 232 int inprocess = 0; 233 int token, state; 234 int errs = 0; 235 236 if ((pname = strrchr(argv[0], '/')) == NULL) 237 pname = argv[0]; 238 else 239 pname++; 240 241 if (argc > 2) { 242 (void) fprintf(stderr, "Usage: %s [<filename>]\n", pname); 243 return 1; 244 } 245 246 if (argc == 2) 247 if ((fp = fopen(fname = argv[1], "r")) == NULL) { 248 (void) fprintf(stderr, "%s: Cannot open `%s'\n", pname, fname); 249 return 1; 250 } 251 252 state = S_DISCARD; 253 254 while ((ptr = fgets(line, sizeof(line), fp)) != NULL) { 255 lineno++; 256 switch (token = findtoken(gettoken(&ptr, defs))) { 257 case T_NEWCODE: 258 state = S_CODE; 259 break; 260 261 case T_ENDCODE: 262 state = S_DISCARD; 263 break; 264 265 case T_COMMENT: 266 state = S_COMMENT; 267 break; 268 269 case T_NEWDEF: 270 state = S_KEYWORD; 271 break; 272 273 case T_ENDDEF: 274 state = S_DISCARD; 275 break; 276 277 case T_VENDOR: 278 state = S_KEYWORD; 279 break; 280 281 case T_HOSTTYPE: 282 state = S_KEYWORD; 283 break; 284 285 case T_MACHTYPE: 286 state = S_KEYWORD; 287 break; 288 289 case T_OSTYPE: 290 state = S_KEYWORD; 291 break; 292 293 case T_MACRO: 294 if (gettoken(&ptr, defs) == NULL) { 295 (void) fprintf(stderr, "%s: \"%s\", %d: Missing macro name\n", 296 pname, fname, lineno); 297 break; 298 } 299 if (gettoken(&ptr, stmt) == NULL) { 300 (void) fprintf(stderr, "%s: \"%s\", %d: Missing macro body\n", 301 pname, fname, lineno); 302 break; 303 } 304 (void) fprintf(stdout, "\n#if %s\n# define %s\n#endif\n\n", 305 explode(stmt), defs); 306 break; 307 308 case T_NONE: 309 if (state != S_CODE && *defs != '\0') { 310 (void) fprintf(stderr, "%s: \"%s\", %d: Discarded\n", 311 pname, fname, lineno); 312 if (++errs == 30) { 313 (void) fprintf(stderr, "%s: Too many errors\n", pname); 314 return 1; 315 } 316 break; 317 } 318 (void) fprintf(stdout, "%s", line); 319 break; 320 321 default: 322 (void) fprintf(stderr, "%s: \"%s\", %d: Unexpected token\n", 323 pname, fname, lineno); 324 return 1; 325 } 326 327 switch (state) { 328 case S_DISCARD: 329 if (inprocess) { 330 inprocess = 0; 331 (void) fprintf(stdout, "#endif\n"); 332 } 333 break; 334 335 case S_KEYWORD: 336 tok = gettoken(&ptr, defs); 337 if (token == T_NEWDEF) { 338 if (inprocess) { 339 (void) fprintf(stderr, "%s: \"%s\", %d: Missing enddef\n", 340 pname, fname, lineno); 341 return 1; 342 } 343 if (tok == NULL) { 344 (void) fprintf(stderr, "%s: \"%s\", %d: No defs\n", 345 pname, fname, lineno); 346 return 1; 347 } 348 (void) fprintf(stdout, "\n\n"); 349 #ifdef LINEDIRECTIVE 350 (void) fprintf(stdout, "# %d \"%s\"\n", lineno + 1, fname); 351 #endif /* LINEDIRECTIVE */ 352 (void) fprintf(stdout, "#if (%s)\n", explode(defs)); 353 inprocess = 1; 354 } 355 else { 356 if (tok && *tok) 357 (void) fprintf(stdout, "# if (%s) && !defined(_%s_)\n", 358 explode(defs), keyword[token]); 359 else 360 (void) fprintf(stdout, "# if !defined(_%s_)\n", 361 keyword[token]); 362 363 if (gettoken(&ptr, stmt) == NULL) { 364 (void) fprintf(stderr, "%s: \"%s\", %d: No statement\n", 365 pname, fname, lineno); 366 return 1; 367 } 368 (void) fprintf(stdout, "# define _%s_\n", keyword[token]); 369 (void) fprintf(stdout, " %s = %s;\n", keyword[token], stmt); 370 (void) fprintf(stdout, "# endif\n"); 371 } 372 break; 373 374 case S_COMMENT: 375 if (gettoken(&ptr, defs)) 376 (void) fprintf(stdout, " /* %s */\n", defs); 377 break; 378 379 case S_CODE: 380 if (token == T_NEWCODE) { 381 #ifdef LINEDIRECTIVE 382 (void) fprintf(stdout, "# %d \"%s\"\n", lineno + 1, fname); 383 #endif /* LINEDIRECTIVE */ 384 } 385 break; 386 387 default: 388 (void) fprintf(stderr, "%s: \"%s\", %d: Unexpected state\n", 389 pname, fname, lineno); 390 return 1; 391 } 392 } 393 394 if (inprocess) { 395 (void) fprintf(stderr, "%s: \"%s\", %d: Missing enddef\n", 396 pname, fname, lineno); 397 return 1; 398 } 399 400 if (fp != stdin) 401 (void) fclose(fp); 402 403 return 0; 404 } 405