1232633Smp/* $Header: /p/tcsh/cvsroot/tcsh/gethost.c,v 1.15 2012/01/15 17:14: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 35232633SmpRCSID("$tcsh: gethost.c,v 1.15 2012/01/15 17:14: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 *); 94232633Smpstatic 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} 145232633Smp 146232633Smpstatic char * 147232633Smpcat(const char *a, const char *b, size_t len) 148232633Smp{ 149232633Smp size_t l; 150232633Smp char *r; 151232633Smp 152232633Smp if (len == 0) 153232633Smp len = strlen(b); 154232633Smp l = strlen(a) + len + 1; 155232633Smp if ((r = malloc(l)) == NULL) 156232633Smp abort(); 157232633Smp snprintf(r, l, "%s%.*s", a, (int)len, b); 158232633Smp return r; 159232633Smp} 160232633Smp 161232633Smpstatic const char * 162232633Smpexplode(const char *defs) 163232633Smp{ 164232633Smp static const char def[] = "defined("; /* ) */ 165232633Smp static char *buf; 166232633Smp size_t len; 167232633Smp const char *ptr, *bptr, *eptr = NULL, *name; 168232633Smp size_t buflen = 0; 169232633Smp 170232633Smp if (strstr(defs, "#machine(" /* ) */)) 171232633Smp return defs; 172232633Smp 173232633Smp free(buf); 174232633Smp buf = strdup("("); /* ) */ 175232633Smp for (ptr = defs; (bptr = strstr(ptr, def)) != NULL; ptr = eptr + 1) { 176232633Smp if (ptr != bptr) 177232633Smp buf = cat(buf, ptr, bptr - ptr); 178232633Smp if ((eptr = strchr(ptr + sizeof(def) - 1, ')')) == NULL) { 179232633Smp (void) fprintf(stderr, "%s: missing close paren `%s'\n", 180232633Smp pname, defs); 181232633Smp return defs; 182232633Smp } 183232633Smp buf = cat(buf, bptr, eptr - bptr + 1); 184232633Smp name = bptr + sizeof(def) - 1; 185232633Smp len = eptr - name; 186232633Smp if (len < 1) { 187232633Smp (void) fprintf(stderr, "%s: empty define `%s'\n", 188232633Smp pname, defs); 189232633Smp return defs; 190232633Smp } 191232633Smp if (*name != '_') { 192232633Smp char *undername = malloc(len + 10); 193232633Smp buf = cat(buf, " || defined(", 0); 194232633Smp snprintf(undername, len + 10, "__%.*s__)", (int)len, 195232633Smp name); 196232633Smp buf = cat(buf, undername, len + 5); 197232633Smp buf = cat(buf, " || defined(", 0); 198232633Smp snprintf(undername, len + 10, "__%.*s)", (int)len, 199232633Smp name); 200232633Smp buf = cat(buf, undername, len + 3); 201232633Smp } 202232633Smp } 203232633Smp if (!eptr) { 204232633Smp (void) fprintf(stderr, "%s: invalid input `%s'\n", pname, defs); 205232633Smp return defs; 206232633Smp } 207232633Smp buf = cat(buf, eptr + 1, 0); 208232633Smp buf = cat(buf, ")", 0); 209232633Smp return buf; 210232633Smp} 21159243Sobrien 21259243Sobrien 21359243Sobrienint 214167465Smpmain(int argc, char *argv[]) 21559243Sobrien{ 21659243Sobrien char line[INBUFSIZE]; 217131962Smp const char *fname = "stdin"; 21859243Sobrien char *ptr, *tok; 21959243Sobrien char defs[INBUFSIZE]; 22059243Sobrien char stmt[INBUFSIZE]; 22159243Sobrien FILE *fp = stdin; 22259243Sobrien int lineno = 0; 22359243Sobrien int inprocess = 0; 22459243Sobrien int token, state; 22559243Sobrien int errs = 0; 22659243Sobrien 22759243Sobrien if ((pname = strrchr(argv[0], '/')) == NULL) 22859243Sobrien pname = argv[0]; 22959243Sobrien else 23059243Sobrien pname++; 23159243Sobrien 23259243Sobrien if (argc > 2) { 23359243Sobrien (void) fprintf(stderr, "Usage: %s [<filename>]\n", pname); 23459243Sobrien return 1; 23559243Sobrien } 23659243Sobrien 23759243Sobrien if (argc == 2) 23859243Sobrien if ((fp = fopen(fname = argv[1], "r")) == NULL) { 23959243Sobrien (void) fprintf(stderr, "%s: Cannot open `%s'\n", pname, fname); 24059243Sobrien return 1; 24159243Sobrien } 24259243Sobrien 24359243Sobrien state = S_DISCARD; 24459243Sobrien 24559243Sobrien while ((ptr = fgets(line, sizeof(line), fp)) != NULL) { 24659243Sobrien lineno++; 24759243Sobrien switch (token = findtoken(gettoken(&ptr, defs))) { 24859243Sobrien case T_NEWCODE: 24959243Sobrien state = S_CODE; 25059243Sobrien break; 25159243Sobrien 25259243Sobrien case T_ENDCODE: 25359243Sobrien state = S_DISCARD; 25459243Sobrien break; 25559243Sobrien 25659243Sobrien case T_COMMENT: 25759243Sobrien state = S_COMMENT; 25859243Sobrien break; 25959243Sobrien 26059243Sobrien case T_NEWDEF: 26159243Sobrien state = S_KEYWORD; 26259243Sobrien break; 26359243Sobrien 26459243Sobrien case T_ENDDEF: 26559243Sobrien state = S_DISCARD; 26659243Sobrien break; 26759243Sobrien 26859243Sobrien case T_VENDOR: 26959243Sobrien state = S_KEYWORD; 27059243Sobrien break; 27159243Sobrien 27259243Sobrien case T_HOSTTYPE: 27359243Sobrien state = S_KEYWORD; 27459243Sobrien break; 27559243Sobrien 27659243Sobrien case T_MACHTYPE: 27759243Sobrien state = S_KEYWORD; 27859243Sobrien break; 27959243Sobrien 28059243Sobrien case T_OSTYPE: 28159243Sobrien state = S_KEYWORD; 28259243Sobrien break; 28359243Sobrien 28459243Sobrien case T_MACRO: 28559243Sobrien if (gettoken(&ptr, defs) == NULL) { 28659243Sobrien (void) fprintf(stderr, "%s: \"%s\", %d: Missing macro name\n", 28759243Sobrien pname, fname, lineno); 28859243Sobrien break; 28959243Sobrien } 29059243Sobrien if (gettoken(&ptr, stmt) == NULL) { 29159243Sobrien (void) fprintf(stderr, "%s: \"%s\", %d: Missing macro body\n", 29259243Sobrien pname, fname, lineno); 29359243Sobrien break; 29459243Sobrien } 29559243Sobrien (void) fprintf(stdout, "\n#if %s\n# define %s\n#endif\n\n", stmt, 29659243Sobrien defs); 29759243Sobrien break; 29859243Sobrien 29959243Sobrien case T_NONE: 300232633Smp if (state != S_CODE && *defs != '\0') { 30159243Sobrien (void) fprintf(stderr, "%s: \"%s\", %d: Discarded\n", 30259243Sobrien pname, fname, lineno); 30359243Sobrien if (++errs == 30) { 30459243Sobrien (void) fprintf(stderr, "%s: Too many errors\n", pname); 30559243Sobrien return 1; 30659243Sobrien } 30759243Sobrien break; 30859243Sobrien } 30959243Sobrien (void) fprintf(stdout, "%s", line); 31059243Sobrien break; 31159243Sobrien 31259243Sobrien default: 31359243Sobrien (void) fprintf(stderr, "%s: \"%s\", %d: Unexpected token\n", 31459243Sobrien pname, fname, lineno); 31559243Sobrien return 1; 31659243Sobrien } 31759243Sobrien 31859243Sobrien switch (state) { 31959243Sobrien case S_DISCARD: 32059243Sobrien if (inprocess) { 32159243Sobrien inprocess = 0; 32259243Sobrien (void) fprintf(stdout, "#endif\n"); 32359243Sobrien } 32459243Sobrien break; 32559243Sobrien 32659243Sobrien case S_KEYWORD: 32759243Sobrien tok = gettoken(&ptr, defs); 32859243Sobrien if (token == T_NEWDEF) { 32959243Sobrien if (inprocess) { 33059243Sobrien (void) fprintf(stderr, "%s: \"%s\", %d: Missing enddef\n", 33159243Sobrien pname, fname, lineno); 33259243Sobrien return 1; 33359243Sobrien } 33459243Sobrien if (tok == NULL) { 33559243Sobrien (void) fprintf(stderr, "%s: \"%s\", %d: No defs\n", 33659243Sobrien pname, fname, lineno); 33759243Sobrien return 1; 33859243Sobrien } 33959243Sobrien (void) fprintf(stdout, "\n\n"); 34059243Sobrien#ifdef LINEDIRECTIVE 34159243Sobrien (void) fprintf(stdout, "# %d \"%s\"\n", lineno + 1, fname); 34259243Sobrien#endif /* LINEDIRECTIVE */ 34359243Sobrien (void) fprintf(stdout, "#if %s\n", defs); 34459243Sobrien inprocess = 1; 34559243Sobrien } 34659243Sobrien else { 34759243Sobrien if (tok && *tok) 34859243Sobrien (void) fprintf(stdout, "# if (%s) && !defined(_%s_)\n", 349232633Smp explode(defs), keyword[token]); 35059243Sobrien else 35159243Sobrien (void) fprintf(stdout, "# if !defined(_%s_)\n", 35259243Sobrien keyword[token]); 35359243Sobrien 35459243Sobrien if (gettoken(&ptr, stmt) == NULL) { 35559243Sobrien (void) fprintf(stderr, "%s: \"%s\", %d: No statement\n", 35659243Sobrien pname, fname, lineno); 35759243Sobrien return 1; 35859243Sobrien } 35959243Sobrien (void) fprintf(stdout, "# define _%s_\n", keyword[token]); 36059243Sobrien (void) fprintf(stdout, " %s = %s;\n", keyword[token], stmt); 36159243Sobrien (void) fprintf(stdout, "# endif\n"); 36259243Sobrien } 36359243Sobrien break; 36459243Sobrien 36559243Sobrien case S_COMMENT: 36659243Sobrien if (gettoken(&ptr, defs)) 36759243Sobrien (void) fprintf(stdout, " /* %s */\n", defs); 36859243Sobrien break; 36959243Sobrien 37059243Sobrien case S_CODE: 37159243Sobrien if (token == T_NEWCODE) { 37259243Sobrien#ifdef LINEDIRECTIVE 37359243Sobrien (void) fprintf(stdout, "# %d \"%s\"\n", lineno + 1, fname); 37459243Sobrien#endif /* LINEDIRECTIVE */ 37559243Sobrien } 37659243Sobrien break; 37759243Sobrien 37859243Sobrien default: 37959243Sobrien (void) fprintf(stderr, "%s: \"%s\", %d: Unexpected state\n", 38059243Sobrien pname, fname, lineno); 38159243Sobrien return 1; 38259243Sobrien } 38359243Sobrien } 38459243Sobrien 38559243Sobrien if (inprocess) { 38659243Sobrien (void) fprintf(stderr, "%s: \"%s\", %d: Missing enddef\n", 38759243Sobrien pname, fname, lineno); 38859243Sobrien return 1; 38959243Sobrien } 39059243Sobrien 39159243Sobrien if (fp != stdin) 39259243Sobrien (void) fclose(fp); 39359243Sobrien 39459243Sobrien return 0; 39559243Sobrien} 396