gethost.c revision 167466
1/* $Header: /p/tcsh/cvsroot/tcsh/gethost.c,v 1.12 2006/03/02 18:46:44 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
35RCSID("$tcsh: gethost.c,v 1.12 2006/03/02 18:46:44 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
61static 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
92static int findtoken (char *);
93static char *gettoken (char **, char  *);
94
95int main (int, char *[]);
96
97/* findtoken():
98 *	Return the token number of the given token
99 */
100static int
101findtoken(char *ptr)
102{
103    int i;
104
105    if (ptr == NULL || *ptr == '\0')
106	return T_NONE;
107
108    for (i = 0; keyword[i] != NULL; i++)
109	if (strcmp(keyword[i], ptr) == 0)
110	    return i;
111
112    return T_NONE;
113}
114
115
116/* gettoken():
117 *	Get : delimited token and remove leading/trailing blanks/newlines
118 */
119static char *
120gettoken(char **pptr, char *token)
121{
122    char *ptr = *pptr;
123    char *tok = token;
124
125    for (; *ptr && ISSPACE(*ptr); ptr++)
126	continue;
127
128    for (; *ptr && *ptr != ':'; *tok++ = *ptr++)
129	continue;
130
131    if (*ptr == ':')
132	ptr++;
133    else
134	tok--;
135
136    for (tok--; tok >= token && *tok && ISSPACE(*tok); tok--)
137	continue;
138
139    *++tok = '\0';
140
141    *pptr = ptr;
142    return token;
143}
144
145
146int
147main(int argc, char *argv[])
148{
149    char line[INBUFSIZE];
150    char *pname;
151    const char *fname = "stdin";
152    char *ptr, *tok;
153    char defs[INBUFSIZE];
154    char stmt[INBUFSIZE];
155    FILE *fp = stdin;
156    int lineno = 0;
157    int inprocess = 0;
158    int token, state;
159    int errs = 0;
160
161    if ((pname = strrchr(argv[0], '/')) == NULL)
162	pname = argv[0];
163    else
164	pname++;
165
166    if (argc > 2) {
167	(void) fprintf(stderr, "Usage: %s [<filename>]\n", pname);
168	return 1;
169    }
170
171    if (argc == 2)
172	if ((fp = fopen(fname = argv[1], "r")) == NULL) {
173	    (void) fprintf(stderr, "%s: Cannot open `%s'\n", pname, fname);
174	    return 1;
175	}
176
177    state = S_DISCARD;
178
179    while ((ptr = fgets(line, sizeof(line), fp)) != NULL) {
180	lineno++;
181	switch (token = findtoken(gettoken(&ptr, defs))) {
182	case T_NEWCODE:
183	    state = S_CODE;
184	    break;
185
186	case T_ENDCODE:
187	    state = S_DISCARD;
188	    break;
189
190	case T_COMMENT:
191	    state = S_COMMENT;
192	    break;
193
194	case T_NEWDEF:
195	    state = S_KEYWORD;
196	    break;
197
198	case T_ENDDEF:
199	    state = S_DISCARD;
200	    break;
201
202	case T_VENDOR:
203	    state = S_KEYWORD;
204	    break;
205
206	case T_HOSTTYPE:
207	    state = S_KEYWORD;
208	    break;
209
210	case T_MACHTYPE:
211	    state = S_KEYWORD;
212	    break;
213
214	case T_OSTYPE:
215	    state = S_KEYWORD;
216	    break;
217
218	case T_MACRO:
219	    if (gettoken(&ptr, defs) == NULL) {
220		(void) fprintf(stderr, "%s: \"%s\", %d: Missing macro name\n",
221			       pname, fname, lineno);
222		break;
223	    }
224	    if (gettoken(&ptr, stmt) == NULL) {
225		(void) fprintf(stderr, "%s: \"%s\", %d: Missing macro body\n",
226			       pname, fname, lineno);
227		break;
228	    }
229	    (void) fprintf(stdout, "\n#if %s\n# define %s\n#endif\n\n", stmt,
230			   defs);
231	    break;
232
233	case T_NONE:
234	    if (state != S_CODE && defs && *defs != '\0') {
235		(void) fprintf(stderr, "%s: \"%s\", %d: Discarded\n",
236			       pname, fname, lineno);
237		if (++errs == 30) {
238		    (void) fprintf(stderr, "%s: Too many errors\n", pname);
239		    return 1;
240		}
241		break;
242	    }
243	    (void) fprintf(stdout, "%s", line);
244	    break;
245
246	default:
247	    (void) fprintf(stderr, "%s: \"%s\", %d: Unexpected token\n",
248			   pname, fname, lineno);
249	    return 1;
250	}
251
252	switch (state) {
253	case S_DISCARD:
254	    if (inprocess) {
255		inprocess = 0;
256		(void) fprintf(stdout, "#endif\n");
257	    }
258	    break;
259
260	case S_KEYWORD:
261	    tok = gettoken(&ptr, defs);
262	    if (token == T_NEWDEF) {
263		if (inprocess) {
264		    (void) fprintf(stderr, "%s: \"%s\", %d: Missing enddef\n",
265				   pname, fname, lineno);
266		    return 1;
267		}
268		if (tok == NULL) {
269		    (void) fprintf(stderr, "%s: \"%s\", %d: No defs\n",
270				   pname, fname, lineno);
271		    return 1;
272		}
273		(void) fprintf(stdout, "\n\n");
274#ifdef LINEDIRECTIVE
275		(void) fprintf(stdout, "# %d \"%s\"\n", lineno + 1, fname);
276#endif /* LINEDIRECTIVE */
277		(void) fprintf(stdout, "#if %s\n", defs);
278		inprocess = 1;
279	    }
280	    else {
281		if (tok && *tok)
282		    (void) fprintf(stdout, "# if (%s) && !defined(_%s_)\n",
283				   defs, keyword[token]);
284		else
285		    (void) fprintf(stdout, "# if !defined(_%s_)\n",
286				   keyword[token]);
287
288		if (gettoken(&ptr, stmt) == NULL) {
289		    (void) fprintf(stderr, "%s: \"%s\", %d: No statement\n",
290				   pname, fname, lineno);
291		    return 1;
292		}
293		(void) fprintf(stdout, "# define _%s_\n", keyword[token]);
294		(void) fprintf(stdout, "    %s = %s;\n", keyword[token], stmt);
295		(void) fprintf(stdout, "# endif\n");
296	    }
297	    break;
298
299	case S_COMMENT:
300	    if (gettoken(&ptr, defs))
301		(void) fprintf(stdout, "    /* %s */\n", defs);
302	    break;
303
304	case S_CODE:
305	    if (token == T_NEWCODE) {
306#ifdef LINEDIRECTIVE
307		(void) fprintf(stdout, "# %d \"%s\"\n", lineno + 1, fname);
308#endif /* LINEDIRECTIVE */
309	    }
310	    break;
311
312	default:
313	    (void) fprintf(stderr, "%s: \"%s\", %d: Unexpected state\n",
314			   pname, fname, lineno);
315	    return 1;
316	}
317    }
318
319    if (inprocess) {
320	(void) fprintf(stderr, "%s: \"%s\", %d: Missing enddef\n",
321		       pname, fname, lineno);
322	return 1;
323    }
324
325    if (fp != stdin)
326	(void) fclose(fp);
327
328    return 0;
329}
330