1316958Sdchagin/* $Header: /p/tcsh/cvsroot/tcsh/gethost.c,v 1.19 2014/03/09 00:11:54 christos Exp $ */ 259243Sobrien/* 359243Sobrien * gethost.c: Create version file from prototype 459243Sobrien */ 559243Sobrien/*- 659243Sobrien * Copyright (c) 1980, 1991 The Regents of the University of California. 759243Sobrien * All rights reserved. 859243Sobrien * 959243Sobrien * Redistribution and use in source and binary forms, with or without 1059243Sobrien * modification, are permitted provided that the following conditions 1159243Sobrien * are met: 1259243Sobrien * 1. Redistributions of source code must retain the above copyright 1359243Sobrien * notice, this list of conditions and the following disclaimer. 1459243Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1559243Sobrien * notice, this list of conditions and the following disclaimer in the 1659243Sobrien * documentation and/or other materials provided with the distribution. 17100616Smp * 3. Neither the name of the University nor the names of its contributors 1859243Sobrien * may be used to endorse or promote products derived from this software 1959243Sobrien * without specific prior written permission. 2059243Sobrien * 2159243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2259243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2359243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2459243Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2559243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2659243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2759243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2859243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2959243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3059243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3159243Sobrien * SUCH DAMAGE. 3259243Sobrien */ 3359243Sobrien#include "sh.h" 3459243Sobrien 35316958SdchaginRCSID("$tcsh: gethost.c,v 1.19 2014/03/09 00:11:54 christos Exp $") 3659243Sobrien 3759243Sobrien#ifdef SCO 3859243Sobrien# define perror __perror 3959243Sobrien# define rename __rename 4059243Sobrien# define getopt __getopt 4159243Sobrien# define system __system 4259243Sobrien#endif 4359243Sobrien#include <stdio.h> 4459243Sobrien#ifdef SCO 4559243Sobrien# undef perror 4659243Sobrien# undef rename 4759243Sobrien# undef getopt 4859243Sobrien# undef system 4959243Sobrien#endif 5059243Sobrien 5159243Sobrien#include <ctype.h> 5259243Sobrien 5359243Sobrien#define ISSPACE(p) (isspace((unsigned char) (p)) && (p) != '\n') 5459243Sobrien 5559243Sobrien/* 5659243Sobrien * We cannot do that, because some compilers like #line and others 5759243Sobrien * like # <lineno> 5859243Sobrien * #define LINEDIRECTIVE 5959243Sobrien */ 6059243Sobrien 6159243Sobrienstatic const char *keyword[] = 6259243Sobrien{ 6359243Sobrien "vendor", 6459243Sobrien#define T_VENDOR 0 6559243Sobrien "hosttype", 6659243Sobrien#define T_HOSTTYPE 1 6759243Sobrien "machtype", 6859243Sobrien#define T_MACHTYPE 2 6959243Sobrien "ostype", 7059243Sobrien#define T_OSTYPE 3 7159243Sobrien "newdef", 7259243Sobrien#define T_NEWDEF 4 7359243Sobrien "enddef", 7459243Sobrien#define T_ENDDEF 5 7559243Sobrien "newcode", 7659243Sobrien#define T_NEWCODE 6 7759243Sobrien "endcode", 7859243Sobrien#define T_ENDCODE 7 7959243Sobrien "comment", 8059243Sobrien#define T_COMMENT 8 8159243Sobrien "macro", 8259243Sobrien#define T_MACRO 9 8359243Sobrien NULL 8459243Sobrien#define T_NONE 10 8559243Sobrien}; 8659243Sobrien 8759243Sobrien#define S_DISCARD 0 8859243Sobrien#define S_COMMENT 1 8959243Sobrien#define S_CODE 2 9059243Sobrien#define S_KEYWORD 3 9159243Sobrien 92167465Smpstatic int findtoken (char *); 93167465Smpstatic char *gettoken (char **, char *); 94231990Smpstatic char *pname; 9559243Sobrien 96167465Smpint main (int, char *[]); 9759243Sobrien 9859243Sobrien/* findtoken(): 9959243Sobrien * Return the token number of the given token 10059243Sobrien */ 10159243Sobrienstatic int 102167465Smpfindtoken(char *ptr) 10359243Sobrien{ 10459243Sobrien int i; 10559243Sobrien 10659243Sobrien if (ptr == NULL || *ptr == '\0') 10759243Sobrien return T_NONE; 10859243Sobrien 10959243Sobrien for (i = 0; keyword[i] != NULL; i++) 11059243Sobrien if (strcmp(keyword[i], ptr) == 0) 11159243Sobrien return i; 11259243Sobrien 11359243Sobrien return T_NONE; 11459243Sobrien} 11559243Sobrien 11659243Sobrien 11759243Sobrien/* gettoken(): 11859243Sobrien * Get : delimited token and remove leading/trailing blanks/newlines 11959243Sobrien */ 12059243Sobrienstatic char * 121167465Smpgettoken(char **pptr, char *token) 12259243Sobrien{ 12359243Sobrien char *ptr = *pptr; 12459243Sobrien char *tok = token; 12559243Sobrien 12659243Sobrien for (; *ptr && ISSPACE(*ptr); ptr++) 12759243Sobrien continue; 12859243Sobrien 12959243Sobrien for (; *ptr && *ptr != ':'; *tok++ = *ptr++) 13059243Sobrien continue; 13159243Sobrien 13259243Sobrien if (*ptr == ':') 13359243Sobrien ptr++; 13459243Sobrien else 13559243Sobrien tok--; 13659243Sobrien 13759243Sobrien for (tok--; tok >= token && *tok && ISSPACE(*tok); tok--) 13859243Sobrien continue; 13959243Sobrien 14059243Sobrien *++tok = '\0'; 14159243Sobrien 14259243Sobrien *pptr = ptr; 14359243Sobrien return token; 14459243Sobrien} 145231990Smp 146231990Smpstatic char * 147231990Smpcat(const char *a, const char *b, size_t len) 148231990Smp{ 149231990Smp size_t l; 150231990Smp char *r; 151231990Smp 152231990Smp if (len == 0) 153316958Sdchagin len = strlen(b) + 1; 154316958Sdchagin if (a) 155316958Sdchagin l = strlen(a) + len; 156316958Sdchagin else 157316958Sdchagin l = len; 158231990Smp if ((r = malloc(l)) == NULL) 159231990Smp abort(); 160316958Sdchagin if (a) 161316958Sdchagin snprintf(r, l, "%s%.*s", a, (int)len, b); 162316958Sdchagin else 163316958Sdchagin snprintf(r, l, "%.*s", (int)len, b); 164231990Smp return r; 165231990Smp} 166231990Smp 167231990Smpstatic const char * 168231990Smpexplode(const char *defs) 169231990Smp{ 170231990Smp static const char def[] = "defined("; /* ) */ 171231990Smp static char *buf; 172231990Smp size_t len; 173231990Smp const char *ptr, *bptr, *eptr = NULL, *name; 174231990Smp 175231990Smp if (strstr(defs, "#machine(" /* ) */)) 176231990Smp return defs; 177316958Sdchagin if (!strstr(defs, def)) 178316958Sdchagin return defs; 179231990Smp 180231990Smp free(buf); 181316958Sdchagin buf = NULL; 182231990Smp for (ptr = defs; (bptr = strstr(ptr, def)) != NULL; ptr = eptr + 1) { 183231990Smp if (ptr != bptr) 184316958Sdchagin buf = cat(buf, ptr, bptr - ptr + 1); 185316958Sdchagin buf = cat(buf, "(", 0); /* ) */ 186231990Smp if ((eptr = strchr(ptr + sizeof(def) - 1, ')')) == NULL) { 187231990Smp (void) fprintf(stderr, "%s: missing close paren `%s'\n", 188231990Smp pname, defs); 189316958Sdchagin free(buf); 190231990Smp return defs; 191231990Smp } 192231990Smp buf = cat(buf, bptr, eptr - bptr + 1); 193231990Smp name = bptr + sizeof(def) - 1; 194231990Smp len = eptr - name; 195231990Smp if (len < 1) { 196231990Smp (void) fprintf(stderr, "%s: empty define `%s'\n", 197231990Smp pname, defs); 198316958Sdchagin free(buf); 199231990Smp return defs; 200231990Smp } 201316958Sdchagin if (*name != '_' && (*name != 'M' && name[1] != '_')) { 202231990Smp char *undername = malloc(len + 10); 203316958Sdchagin if (undername == NULL) 204316958Sdchagin abort(); 205316958Sdchagin buf = cat(buf, ") || defined(", 0); 206231990Smp snprintf(undername, len + 10, "__%.*s__)", (int)len, 207231990Smp name); 208231990Smp buf = cat(buf, undername, len + 5); 209316958Sdchagin buf = cat(buf, ") || defined(", 0); 210231990Smp snprintf(undername, len + 10, "__%.*s)", (int)len, 211231990Smp name); 212231990Smp buf = cat(buf, undername, len + 3); 213231990Smp } 214316958Sdchagin buf = cat(buf, "))", 0); 215231990Smp } 216231990Smp if (!eptr) { 217231990Smp (void) fprintf(stderr, "%s: invalid input `%s'\n", pname, defs); 218231990Smp return defs; 219231990Smp } 220231990Smp buf = cat(buf, eptr + 1, 0); 221231990Smp return buf; 222231990Smp} 22359243Sobrien 22459243Sobrien 22559243Sobrienint 226167465Smpmain(int argc, char *argv[]) 22759243Sobrien{ 22859243Sobrien char line[INBUFSIZE]; 229131962Smp const char *fname = "stdin"; 23059243Sobrien char *ptr, *tok; 23159243Sobrien char defs[INBUFSIZE]; 23259243Sobrien char stmt[INBUFSIZE]; 23359243Sobrien FILE *fp = stdin; 23459243Sobrien int lineno = 0; 23559243Sobrien int inprocess = 0; 23659243Sobrien int token, state; 23759243Sobrien int errs = 0; 23859243Sobrien 23959243Sobrien if ((pname = strrchr(argv[0], '/')) == NULL) 24059243Sobrien pname = argv[0]; 24159243Sobrien else 24259243Sobrien pname++; 24359243Sobrien 24459243Sobrien if (argc > 2) { 24559243Sobrien (void) fprintf(stderr, "Usage: %s [<filename>]\n", pname); 24659243Sobrien return 1; 24759243Sobrien } 24859243Sobrien 24959243Sobrien if (argc == 2) 25059243Sobrien if ((fp = fopen(fname = argv[1], "r")) == NULL) { 25159243Sobrien (void) fprintf(stderr, "%s: Cannot open `%s'\n", pname, fname); 25259243Sobrien return 1; 25359243Sobrien } 25459243Sobrien 25559243Sobrien state = S_DISCARD; 25659243Sobrien 25759243Sobrien while ((ptr = fgets(line, sizeof(line), fp)) != NULL) { 25859243Sobrien lineno++; 25959243Sobrien switch (token = findtoken(gettoken(&ptr, defs))) { 26059243Sobrien case T_NEWCODE: 26159243Sobrien state = S_CODE; 26259243Sobrien break; 26359243Sobrien 26459243Sobrien case T_ENDCODE: 26559243Sobrien state = S_DISCARD; 26659243Sobrien break; 26759243Sobrien 26859243Sobrien case T_COMMENT: 26959243Sobrien state = S_COMMENT; 27059243Sobrien break; 27159243Sobrien 27259243Sobrien case T_NEWDEF: 27359243Sobrien state = S_KEYWORD; 27459243Sobrien break; 27559243Sobrien 27659243Sobrien case T_ENDDEF: 27759243Sobrien state = S_DISCARD; 27859243Sobrien break; 27959243Sobrien 28059243Sobrien case T_VENDOR: 28159243Sobrien state = S_KEYWORD; 28259243Sobrien break; 28359243Sobrien 28459243Sobrien case T_HOSTTYPE: 28559243Sobrien state = S_KEYWORD; 28659243Sobrien break; 28759243Sobrien 28859243Sobrien case T_MACHTYPE: 28959243Sobrien state = S_KEYWORD; 29059243Sobrien break; 29159243Sobrien 29259243Sobrien case T_OSTYPE: 29359243Sobrien state = S_KEYWORD; 29459243Sobrien break; 29559243Sobrien 29659243Sobrien case T_MACRO: 29759243Sobrien if (gettoken(&ptr, defs) == NULL) { 29859243Sobrien (void) fprintf(stderr, "%s: \"%s\", %d: Missing macro name\n", 29959243Sobrien pname, fname, lineno); 30059243Sobrien break; 30159243Sobrien } 30259243Sobrien if (gettoken(&ptr, stmt) == NULL) { 30359243Sobrien (void) fprintf(stderr, "%s: \"%s\", %d: Missing macro body\n", 30459243Sobrien pname, fname, lineno); 30559243Sobrien break; 30659243Sobrien } 307316958Sdchagin (void) fprintf(stdout, "\n#if %s\n# define %s\n#endif\n\n", 308316958Sdchagin explode(stmt), defs); 30959243Sobrien break; 31059243Sobrien 31159243Sobrien case T_NONE: 312231990Smp if (state != S_CODE && *defs != '\0') { 31359243Sobrien (void) fprintf(stderr, "%s: \"%s\", %d: Discarded\n", 31459243Sobrien pname, fname, lineno); 31559243Sobrien if (++errs == 30) { 31659243Sobrien (void) fprintf(stderr, "%s: Too many errors\n", pname); 31759243Sobrien return 1; 31859243Sobrien } 31959243Sobrien break; 32059243Sobrien } 32159243Sobrien (void) fprintf(stdout, "%s", line); 32259243Sobrien break; 32359243Sobrien 32459243Sobrien default: 32559243Sobrien (void) fprintf(stderr, "%s: \"%s\", %d: Unexpected token\n", 32659243Sobrien pname, fname, lineno); 32759243Sobrien return 1; 32859243Sobrien } 32959243Sobrien 33059243Sobrien switch (state) { 33159243Sobrien case S_DISCARD: 33259243Sobrien if (inprocess) { 33359243Sobrien inprocess = 0; 33459243Sobrien (void) fprintf(stdout, "#endif\n"); 33559243Sobrien } 33659243Sobrien break; 33759243Sobrien 33859243Sobrien case S_KEYWORD: 33959243Sobrien tok = gettoken(&ptr, defs); 34059243Sobrien if (token == T_NEWDEF) { 34159243Sobrien if (inprocess) { 34259243Sobrien (void) fprintf(stderr, "%s: \"%s\", %d: Missing enddef\n", 34359243Sobrien pname, fname, lineno); 34459243Sobrien return 1; 34559243Sobrien } 34659243Sobrien if (tok == NULL) { 34759243Sobrien (void) fprintf(stderr, "%s: \"%s\", %d: No defs\n", 34859243Sobrien pname, fname, lineno); 34959243Sobrien return 1; 35059243Sobrien } 35159243Sobrien (void) fprintf(stdout, "\n\n"); 35259243Sobrien#ifdef LINEDIRECTIVE 35359243Sobrien (void) fprintf(stdout, "# %d \"%s\"\n", lineno + 1, fname); 35459243Sobrien#endif /* LINEDIRECTIVE */ 355316958Sdchagin (void) fprintf(stdout, "#if (%s)\n", explode(defs)); 35659243Sobrien inprocess = 1; 35759243Sobrien } 35859243Sobrien else { 35959243Sobrien if (tok && *tok) 36059243Sobrien (void) fprintf(stdout, "# if (%s) && !defined(_%s_)\n", 361231990Smp explode(defs), keyword[token]); 36259243Sobrien else 36359243Sobrien (void) fprintf(stdout, "# if !defined(_%s_)\n", 36459243Sobrien keyword[token]); 36559243Sobrien 36659243Sobrien if (gettoken(&ptr, stmt) == NULL) { 36759243Sobrien (void) fprintf(stderr, "%s: \"%s\", %d: No statement\n", 36859243Sobrien pname, fname, lineno); 36959243Sobrien return 1; 37059243Sobrien } 37159243Sobrien (void) fprintf(stdout, "# define _%s_\n", keyword[token]); 37259243Sobrien (void) fprintf(stdout, " %s = %s;\n", keyword[token], stmt); 37359243Sobrien (void) fprintf(stdout, "# endif\n"); 37459243Sobrien } 37559243Sobrien break; 37659243Sobrien 37759243Sobrien case S_COMMENT: 37859243Sobrien if (gettoken(&ptr, defs)) 37959243Sobrien (void) fprintf(stdout, " /* %s */\n", defs); 38059243Sobrien break; 38159243Sobrien 38259243Sobrien case S_CODE: 38359243Sobrien if (token == T_NEWCODE) { 38459243Sobrien#ifdef LINEDIRECTIVE 38559243Sobrien (void) fprintf(stdout, "# %d \"%s\"\n", lineno + 1, fname); 38659243Sobrien#endif /* LINEDIRECTIVE */ 38759243Sobrien } 38859243Sobrien break; 38959243Sobrien 39059243Sobrien default: 39159243Sobrien (void) fprintf(stderr, "%s: \"%s\", %d: Unexpected state\n", 39259243Sobrien pname, fname, lineno); 39359243Sobrien return 1; 39459243Sobrien } 39559243Sobrien } 39659243Sobrien 39759243Sobrien if (inprocess) { 39859243Sobrien (void) fprintf(stderr, "%s: \"%s\", %d: Missing enddef\n", 39959243Sobrien pname, fname, lineno); 40059243Sobrien return 1; 40159243Sobrien } 40259243Sobrien 40359243Sobrien if (fp != stdin) 40459243Sobrien (void) fclose(fp); 40559243Sobrien 40659243Sobrien return 0; 40759243Sobrien} 408