1255715Sdb/*-
2255715Sdb * Copyright (c) 2013 Diane Bruce
3255715Sdb * All rights reserved.
4255715Sdb *
5255715Sdb * Redistribution and use in source and binary forms, with or without
6255715Sdb * modification, are permitted provided that the following conditions
7255715Sdb * are met:
8255715Sdb * 1. Redistributions of source code must retain the above copyright
9255715Sdb *    notice, this list of conditions and the following disclaimer.
10255715Sdb * 2. Redistributions in binary form must reproduce the above copyright
11255715Sdb *    notice, this list of conditions and the following disclaimer in the
12255715Sdb *    documentation and/or other materials provided with the distribution.
13255715Sdb *
14255715Sdb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15255715Sdb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16255715Sdb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17255715Sdb * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18255715Sdb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19255715Sdb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20255715Sdb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21255715Sdb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22255715Sdb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23255715Sdb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24255715Sdb * SUCH DAMAGE.
25255715Sdb *
26255715Sdb * $FreeBSD$
27255715Sdb */
28255715Sdb
29255715Sdb/* calendar fake cpp does a very limited cpp version */
30255715Sdb
31255715Sdb#include <sys/param.h>
32255715Sdb#include <sys/stat.h>
33255715Sdb#include <sys/wait.h>
34255715Sdb#include <assert.h>
35255715Sdb#include <ctype.h>
36255715Sdb#include <err.h>
37255715Sdb#include <errno.h>
38255715Sdb#include <langinfo.h>
39255715Sdb#include <locale.h>
40255715Sdb#include <pwd.h>
41255715Sdb#include <stdio.h>
42255715Sdb#include <stdlib.h>
43255715Sdb#include <string.h>
44255715Sdb#include <unistd.h>
45255715Sdb
46255715Sdb#include "pathnames.h"
47255715Sdb#include "calendar.h"
48255715Sdb
49255715Sdb#define MAXFPSTACK	50
50255715Sdbstatic FILE *fpstack[MAXFPSTACK];
51255715Sdbstatic int curfpi;
52255715Sdbstatic void pushfp(FILE *fp);
53255715Sdbstatic FILE *popfp(void);
54255715Sdbstatic int tokenscpp(char *buf, char *string);
55255715Sdb
56255715Sdb#define T_INVALID	-1
57255715Sdb#define T_INCLUDE	0
58255715Sdb#define T_DEFINE	1
59255715Sdb#define T_IFNDEF	2
60255715Sdb#define T_ENDIF		3
61255715Sdb
62255715Sdb#define MAXSYMS		100
63255715Sdbstatic char *symtable[MAXSYMS];
64255715Sdbstatic void addsym(const char *name);
65255715Sdbstatic int findsym(const char *name);
66255715Sdb
67255715SdbFILE *
68255715Sdbfincludegets(char *buf, int size, FILE *fp)
69255715Sdb{
70255715Sdb	char name[MAXPATHLEN];
71255715Sdb	FILE *nfp=NULL;
72255715Sdb	char *p;
73255715Sdb	int ch;
74255715Sdb
75255715Sdb	if (fp == NULL)
76255715Sdb		return(NULL);
77255715Sdb
78255715Sdb	if (fgets(buf, size, fp) == NULL) {
79255715Sdb		*buf = '\0';
80255715Sdb		fclose(fp);
81255715Sdb		fp = popfp();
82255715Sdb		return (fp);
83255715Sdb	}
84255715Sdb	if ((p = strchr(buf, '\n')) != NULL)
85255715Sdb		*p = '\0';
86255715Sdb	else {
87255715Sdb		/* Flush this line */
88255715Sdb		while ((ch = fgetc(fp)) != '\n' && ch != EOF);
89255715Sdb		if (ch == EOF) {
90255715Sdb			*buf = '\0';
91255715Sdb			fclose(fp);
92255715Sdb			fp = popfp();
93255715Sdb			return(fp);
94255715Sdb		}
95255715Sdb	}
96255715Sdb	switch (tokenscpp(buf, name)) {
97255715Sdb	case T_INCLUDE:
98255715Sdb		*buf = '\0';
99255715Sdb		if ((nfp = fopen(name, "r")) != NULL) {
100255715Sdb			pushfp(fp);
101255715Sdb			fp = nfp;
102255715Sdb		}
103255715Sdb		break;
104255715Sdb	case T_DEFINE:
105255715Sdb		addsym(name);
106255715Sdb		break;
107255715Sdb	case T_IFNDEF:
108255715Sdb		if (findsym(name)) {
109255715Sdb			fclose(fp);
110255715Sdb			fp = popfp();
111255715Sdb			*buf = '\0';
112255715Sdb		}
113255715Sdb		break;
114255715Sdb	case T_ENDIF:
115255715Sdb		*buf = '\0';
116255715Sdb		break;
117255715Sdb	default:
118255715Sdb		break;
119255715Sdb	}
120255715Sdb	return (fp);
121255715Sdb}
122255715Sdb
123255715Sdbstatic int
124255715Sdbtokenscpp(char *buf, char *string)
125255715Sdb{
126255715Sdb	char *p;
127255715Sdb	char *s;
128255715Sdb
129255715Sdb	if ((p = strstr(buf, "#define")) != NULL) {
130255715Sdb		p += 8;
131255715Sdb		while (isspace((unsigned char)*p))
132255715Sdb			p++;
133255715Sdb		s = p;
134255715Sdb		while(!isspace((unsigned char)*p))
135255715Sdb			p++;
136255715Sdb		strncpy(string, s, MAXPATHLEN);
137255715Sdb		return(T_DEFINE);
138255715Sdb	} else if ((p = strstr(buf, "#ifndef")) != NULL) {
139255715Sdb		p += 8;
140255715Sdb		while (isspace((unsigned char)*p))
141255715Sdb			p++;
142255715Sdb		s = p;
143255715Sdb		while(!isspace((unsigned char)*p))
144255715Sdb			p++;
145255715Sdb		*p = '\0';
146255715Sdb		strncpy(string, s, MAXPATHLEN);
147255715Sdb		return(T_IFNDEF);
148255715Sdb	} else if ((p = strstr(buf, "#endif")) != NULL) {
149255715Sdb		return(T_ENDIF);
150255715Sdb	} if ((p = strstr(buf, "#include")) != NULL) {
151255715Sdb		p += 8;
152255715Sdb		while (isspace((unsigned char)*p))
153255715Sdb			p++;
154255715Sdb		if (*p == '<') {
155255715Sdb			s = p+1;
156255715Sdb			if ((p = strchr(s, '>')) != NULL)
157255715Sdb				*p = '\0';
158255715Sdb			snprintf (string, MAXPATHLEN, "%s/%s",
159255715Sdb				_PATH_INCLUDE, s);
160255715Sdb		} else if (*p == '(') {
161255715Sdb			s = p+1;
162255715Sdb			if ((p = strchr(p, '>')) != NULL)
163255715Sdb				*p = '\0';
164255715Sdb			snprintf (string, MAXPATHLEN, "%s", s);
165255715Sdb		}
166255715Sdb		return(T_INCLUDE);
167255715Sdb	}
168255715Sdb	return(T_INVALID);
169255715Sdb}
170255715Sdb
171255715Sdbstatic void
172255715Sdbpushfp(FILE *fp)
173255715Sdb{
174255715Sdb	curfpi++;
175255715Sdb	if (curfpi == MAXFPSTACK)
176255715Sdb		errx(1, "Max #include reached");
177255715Sdb	fpstack[curfpi] = fp;
178255715Sdb}
179255715Sdb
180255715Sdbstatic
181255715SdbFILE *popfp(void)
182255715Sdb{
183255715Sdb	FILE *tmp;
184255715Sdb
185255715Sdb	assert(curfpi >= 0);
186255715Sdb	tmp = fpstack[curfpi];
187255715Sdb	curfpi--;
188255715Sdb	return(tmp);
189255715Sdb}
190255715Sdb
191255715Sdbvoid
192255715Sdbinitcpp(void)
193255715Sdb{
194255715Sdb	int i;
195255715Sdb
196255715Sdb	for (i=0; i < MAXSYMS; i++)
197255715Sdb		symtable[i] = NULL;
198255715Sdb	fpstack[0] = NULL;
199255715Sdb	curfpi = 0;
200255715Sdb}
201255715Sdb
202255715Sdb
203255715Sdbstatic void
204255715Sdbaddsym(const char *name)
205255715Sdb{
206255715Sdb	int i;
207255715Sdb
208255715Sdb	if (!findsym(name))
209255715Sdb		for (i=0; i < MAXSYMS; i++) {
210255715Sdb			if (symtable[i] == NULL) {
211255715Sdb				symtable[i] = strdup(name);
212255715Sdb				if (symtable[i] == NULL)
213255715Sdb					errx(1, "malloc error in addsym");
214255715Sdb				return;
215255715Sdb			}
216255715Sdb		}
217255715Sdb	errx(1, "symbol table full\n");
218255715Sdb}
219255715Sdb
220255715Sdbstatic int
221255715Sdbfindsym(const char *name)
222255715Sdb{
223255715Sdb	int i;
224255715Sdb
225255715Sdb	for (i=0; i < MAXSYMS; i++)
226255715Sdb		if (symtable[i] != NULL && strcmp(symtable[i],name) == 0)
227255715Sdb			return (1);
228255715Sdb	return (0);
229255715Sdb}
230