11573Srgrimes/* $Header: /p/tcsh/cvsroot/tcsh/gethost.c,v 1.15 2012/01/15 17:14:54 christos Exp $ */ 21573Srgrimes/* 31573Srgrimes * gethost.c: Create version file from prototype 41573Srgrimes */ 51573Srgrimes/*- 61573Srgrimes * Copyright (c) 1980, 1991 The Regents of the University of California. 71573Srgrimes * All rights reserved. 81573Srgrimes * 91573Srgrimes * Redistribution and use in source and binary forms, with or without 101573Srgrimes * modification, are permitted provided that the following conditions 111573Srgrimes * are met: 121573Srgrimes * 1. Redistributions of source code must retain the above copyright 131573Srgrimes * notice, this list of conditions and the following disclaimer. 141573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 151573Srgrimes * notice, this list of conditions and the following disclaimer in the 161573Srgrimes * documentation and/or other materials provided with the distribution. 171573Srgrimes * 3. Neither the name of the University nor the names of its contributors 181573Srgrimes * may be used to endorse or promote products derived from this software 191573Srgrimes * without specific prior written permission. 201573Srgrimes * 211573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2950476Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31185519Skeramida * SUCH DAMAGE. 321573Srgrimes */ 3379531Sru#include "sh.h" 341573Srgrimes 351573SrgrimesRCSID("$tcsh: gethost.c,v 1.15 2012/01/15 17:14:54 christos Exp $") 361573Srgrimes 3759460Sphantom#ifdef SCO 3859460Sphantom# define perror __perror 391573Srgrimes# define rename __rename 4084306Sru# define getopt __getopt 4167967Sasmodai# define system __system 421573Srgrimes#endif 431573Srgrimes#include <stdio.h> 441573Srgrimes#ifdef SCO 4579869Sru# undef perror 4679869Sru# undef rename 4779869Sru# undef getopt 4881359Ssobomax# undef system 491573Srgrimes#endif 501573Srgrimes 511573Srgrimes#include <ctype.h> 521573Srgrimes 531573Srgrimes#define ISSPACE(p) (isspace((unsigned char) (p)) && (p) != '\n') 541573Srgrimes 55185519Skeramida/* 56185519Skeramida * We cannot do that, because some compilers like #line and others 57185519Skeramida * like # <lineno> 58185519Skeramida * #define LINEDIRECTIVE 59185519Skeramida */ 60185519Skeramida 61185519Skeramidastatic const char *keyword[] = 621573Srgrimes{ 631573Srgrimes "vendor", 641573Srgrimes#define T_VENDOR 0 651573Srgrimes "hosttype", 661573Srgrimes#define T_HOSTTYPE 1 671573Srgrimes "machtype", 6879869Sru#define T_MACHTYPE 2 691573Srgrimes "ostype", 701573Srgrimes#define T_OSTYPE 3 7179869Sru "newdef", 721573Srgrimes#define T_NEWDEF 4 731573Srgrimes "enddef", 741573Srgrimes#define T_ENDDEF 5 751573Srgrimes "newcode", 7679869Sru#define T_NEWCODE 6 771573Srgrimes "endcode", 781573Srgrimes#define T_ENDCODE 7 791573Srgrimes "comment", 8079869Sru#define T_COMMENT 8 8179869Sru "macro", 821573Srgrimes#define T_MACRO 9 831573Srgrimes NULL 841573Srgrimes#define T_NONE 10 8579869Sru}; 861573Srgrimes 871573Srgrimes#define S_DISCARD 0 881573Srgrimes#define S_COMMENT 1 891573Srgrimes#define S_CODE 2 9079869Sru#define S_KEYWORD 3 911573Srgrimes 9279869Srustatic int findtoken (char *); 931573Srgrimesstatic char *gettoken (char **, char *); 9479869Srustatic char *pname; 951573Srgrimes 9679869Sruint main (int, char *[]); 971573Srgrimes 981573Srgrimes/* findtoken(): 991573Srgrimes * Return the token number of the given token 1001573Srgrimes */ 1011573Srgrimesstatic int 1021573Srgrimesfindtoken(char *ptr) 1031573Srgrimes{ 1041573Srgrimes int i; 1051573Srgrimes 1061573Srgrimes if (ptr == NULL || *ptr == '\0') 1071573Srgrimes return T_NONE; 1081573Srgrimes 10979869Sru for (i = 0; keyword[i] != NULL; i++) 1101573Srgrimes if (strcmp(keyword[i], ptr) == 0) 11179869Sru return i; 1121573Srgrimes 1131573Srgrimes return T_NONE; 1141573Srgrimes} 1151573Srgrimes 1161573Srgrimes 1171573Srgrimes/* gettoken(): 11879869Sru * Get : delimited token and remove leading/trailing blanks/newlines 11979869Sru */ 12079869Srustatic char * 12179869Srugettoken(char **pptr, char *token) 1221573Srgrimes{ 1231573Srgrimes char *ptr = *pptr; 1241573Srgrimes char *tok = token; 1251573Srgrimes 1261573Srgrimes for (; *ptr && ISSPACE(*ptr); ptr++) 1271573Srgrimes continue; 1281573Srgrimes 1291573Srgrimes for (; *ptr && *ptr != ':'; *tok++ = *ptr++) 1301573Srgrimes continue; 1311573Srgrimes 1321573Srgrimes if (*ptr == ':') 1331573Srgrimes ptr++; 1341573Srgrimes else 1351573Srgrimes tok--; 1361573Srgrimes 13715049Sjoerg for (tok--; tok >= token && *tok && ISSPACE(*tok); tok--) 138185519Skeramida continue; 13915049Sjoerg 1401573Srgrimes *++tok = '\0'; 1411573Srgrimes 1421573Srgrimes *pptr = ptr; 1431573Srgrimes return token; 1441573Srgrimes} 1451573Srgrimes 146static char * 147cat(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); 154 l = strlen(a) + len + 1; 155 if ((r = malloc(l)) == NULL) 156 abort(); 157 snprintf(r, l, "%s%.*s", a, (int)len, b); 158 return r; 159} 160 161static const char * 162explode(const char *defs) 163{ 164 static const char def[] = "defined("; /* ) */ 165 static char *buf; 166 size_t len; 167 const char *ptr, *bptr, *eptr = NULL, *name; 168 size_t buflen = 0; 169 170 if (strstr(defs, "#machine(" /* ) */)) 171 return defs; 172 173 free(buf); 174 buf = strdup("("); /* ) */ 175 for (ptr = defs; (bptr = strstr(ptr, def)) != NULL; ptr = eptr + 1) { 176 if (ptr != bptr) 177 buf = cat(buf, ptr, bptr - ptr); 178 if ((eptr = strchr(ptr + sizeof(def) - 1, ')')) == NULL) { 179 (void) fprintf(stderr, "%s: missing close paren `%s'\n", 180 pname, defs); 181 return defs; 182 } 183 buf = cat(buf, bptr, eptr - bptr + 1); 184 name = bptr + sizeof(def) - 1; 185 len = eptr - name; 186 if (len < 1) { 187 (void) fprintf(stderr, "%s: empty define `%s'\n", 188 pname, defs); 189 return defs; 190 } 191 if (*name != '_') { 192 char *undername = malloc(len + 10); 193 buf = cat(buf, " || defined(", 0); 194 snprintf(undername, len + 10, "__%.*s__)", (int)len, 195 name); 196 buf = cat(buf, undername, len + 5); 197 buf = cat(buf, " || defined(", 0); 198 snprintf(undername, len + 10, "__%.*s)", (int)len, 199 name); 200 buf = cat(buf, undername, len + 3); 201 } 202 } 203 if (!eptr) { 204 (void) fprintf(stderr, "%s: invalid input `%s'\n", pname, defs); 205 return defs; 206 } 207 buf = cat(buf, eptr + 1, 0); 208 buf = cat(buf, ")", 0); 209 return buf; 210} 211 212 213int 214main(int argc, char *argv[]) 215{ 216 char line[INBUFSIZE]; 217 const char *fname = "stdin"; 218 char *ptr, *tok; 219 char defs[INBUFSIZE]; 220 char stmt[INBUFSIZE]; 221 FILE *fp = stdin; 222 int lineno = 0; 223 int inprocess = 0; 224 int token, state; 225 int errs = 0; 226 227 if ((pname = strrchr(argv[0], '/')) == NULL) 228 pname = argv[0]; 229 else 230 pname++; 231 232 if (argc > 2) { 233 (void) fprintf(stderr, "Usage: %s [<filename>]\n", pname); 234 return 1; 235 } 236 237 if (argc == 2) 238 if ((fp = fopen(fname = argv[1], "r")) == NULL) { 239 (void) fprintf(stderr, "%s: Cannot open `%s'\n", pname, fname); 240 return 1; 241 } 242 243 state = S_DISCARD; 244 245 while ((ptr = fgets(line, sizeof(line), fp)) != NULL) { 246 lineno++; 247 switch (token = findtoken(gettoken(&ptr, defs))) { 248 case T_NEWCODE: 249 state = S_CODE; 250 break; 251 252 case T_ENDCODE: 253 state = S_DISCARD; 254 break; 255 256 case T_COMMENT: 257 state = S_COMMENT; 258 break; 259 260 case T_NEWDEF: 261 state = S_KEYWORD; 262 break; 263 264 case T_ENDDEF: 265 state = S_DISCARD; 266 break; 267 268 case T_VENDOR: 269 state = S_KEYWORD; 270 break; 271 272 case T_HOSTTYPE: 273 state = S_KEYWORD; 274 break; 275 276 case T_MACHTYPE: 277 state = S_KEYWORD; 278 break; 279 280 case T_OSTYPE: 281 state = S_KEYWORD; 282 break; 283 284 case T_MACRO: 285 if (gettoken(&ptr, defs) == NULL) { 286 (void) fprintf(stderr, "%s: \"%s\", %d: Missing macro name\n", 287 pname, fname, lineno); 288 break; 289 } 290 if (gettoken(&ptr, stmt) == NULL) { 291 (void) fprintf(stderr, "%s: \"%s\", %d: Missing macro body\n", 292 pname, fname, lineno); 293 break; 294 } 295 (void) fprintf(stdout, "\n#if %s\n# define %s\n#endif\n\n", stmt, 296 defs); 297 break; 298 299 case T_NONE: 300 if (state != S_CODE && *defs != '\0') { 301 (void) fprintf(stderr, "%s: \"%s\", %d: Discarded\n", 302 pname, fname, lineno); 303 if (++errs == 30) { 304 (void) fprintf(stderr, "%s: Too many errors\n", pname); 305 return 1; 306 } 307 break; 308 } 309 (void) fprintf(stdout, "%s", line); 310 break; 311 312 default: 313 (void) fprintf(stderr, "%s: \"%s\", %d: Unexpected token\n", 314 pname, fname, lineno); 315 return 1; 316 } 317 318 switch (state) { 319 case S_DISCARD: 320 if (inprocess) { 321 inprocess = 0; 322 (void) fprintf(stdout, "#endif\n"); 323 } 324 break; 325 326 case S_KEYWORD: 327 tok = gettoken(&ptr, defs); 328 if (token == T_NEWDEF) { 329 if (inprocess) { 330 (void) fprintf(stderr, "%s: \"%s\", %d: Missing enddef\n", 331 pname, fname, lineno); 332 return 1; 333 } 334 if (tok == NULL) { 335 (void) fprintf(stderr, "%s: \"%s\", %d: No defs\n", 336 pname, fname, lineno); 337 return 1; 338 } 339 (void) fprintf(stdout, "\n\n"); 340#ifdef LINEDIRECTIVE 341 (void) fprintf(stdout, "# %d \"%s\"\n", lineno + 1, fname); 342#endif /* LINEDIRECTIVE */ 343 (void) fprintf(stdout, "#if %s\n", defs); 344 inprocess = 1; 345 } 346 else { 347 if (tok && *tok) 348 (void) fprintf(stdout, "# if (%s) && !defined(_%s_)\n", 349 explode(defs), keyword[token]); 350 else 351 (void) fprintf(stdout, "# if !defined(_%s_)\n", 352 keyword[token]); 353 354 if (gettoken(&ptr, stmt) == NULL) { 355 (void) fprintf(stderr, "%s: \"%s\", %d: No statement\n", 356 pname, fname, lineno); 357 return 1; 358 } 359 (void) fprintf(stdout, "# define _%s_\n", keyword[token]); 360 (void) fprintf(stdout, " %s = %s;\n", keyword[token], stmt); 361 (void) fprintf(stdout, "# endif\n"); 362 } 363 break; 364 365 case S_COMMENT: 366 if (gettoken(&ptr, defs)) 367 (void) fprintf(stdout, " /* %s */\n", defs); 368 break; 369 370 case S_CODE: 371 if (token == T_NEWCODE) { 372#ifdef LINEDIRECTIVE 373 (void) fprintf(stdout, "# %d \"%s\"\n", lineno + 1, fname); 374#endif /* LINEDIRECTIVE */ 375 } 376 break; 377 378 default: 379 (void) fprintf(stderr, "%s: \"%s\", %d: Unexpected state\n", 380 pname, fname, lineno); 381 return 1; 382 } 383 } 384 385 if (inprocess) { 386 (void) fprintf(stderr, "%s: \"%s\", %d: Missing enddef\n", 387 pname, fname, lineno); 388 return 1; 389 } 390 391 if (fp != stdin) 392 (void) fclose(fp); 393 394 return 0; 395} 396