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