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