1262918Simp/*-
2262918Simp * Copyright (c) 2013 Diane Bruce
3262918Simp * All rights reserved.
4262918Simp *
5262918Simp * Redistribution and use in source and binary forms, with or without
6262918Simp * modification, are permitted provided that the following conditions
7262918Simp * are met:
8262918Simp * 1. Redistributions of source code must retain the above copyright
9262918Simp *    notice, this list of conditions and the following disclaimer.
10262918Simp * 2. Redistributions in binary form must reproduce the above copyright
11262918Simp *    notice, this list of conditions and the following disclaimer in the
12262918Simp *    documentation and/or other materials provided with the distribution.
13262918Simp *
14262918Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15262918Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16262918Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17262918Simp * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18262918Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19262918Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20262918Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21262918Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22262918Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23262918Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24262918Simp * SUCH DAMAGE.
25262918Simp *
26262918Simp * $FreeBSD$
27262918Simp */
28262918Simp
29262918Simp/* calendar fake cpp does a very limited cpp version */
30262918Simp
31262918Simp#include <sys/param.h>
32262918Simp#include <sys/stat.h>
33262918Simp#include <sys/wait.h>
34262918Simp#include <assert.h>
35262918Simp#include <ctype.h>
36262918Simp#include <err.h>
37262918Simp#include <errno.h>
38262918Simp#include <langinfo.h>
39262918Simp#include <locale.h>
40262918Simp#include <pwd.h>
41262918Simp#include <stdio.h>
42262918Simp#include <stdlib.h>
43262918Simp#include <string.h>
44262918Simp#include <unistd.h>
45
46#include "pathnames.h"
47#include "calendar.h"
48
49#define MAXFPSTACK	50
50static FILE *fpstack[MAXFPSTACK];
51static int curfpi;
52static void pushfp(FILE *fp);
53static FILE *popfp(void);
54static int tokenscpp(char *buf, char *string);
55
56#define T_INVALID	-1
57#define T_INCLUDE	0
58#define T_DEFINE	1
59#define T_IFNDEF	2
60#define T_ENDIF		3
61
62#define MAXSYMS		100
63static char *symtable[MAXSYMS];
64static void addsym(const char *name);
65static int findsym(const char *name);
66
67FILE *
68fincludegets(char *buf, int size, FILE *fp)
69{
70	char name[MAXPATHLEN];
71	FILE *nfp=NULL;
72	char *p;
73	int ch;
74
75	if (fp == NULL)
76		return(NULL);
77
78	if (fgets(buf, size, fp) == NULL) {
79		*buf = '\0';
80		fclose(fp);
81		fp = popfp();
82		return (fp);
83	}
84	if ((p = strchr(buf, '\n')) != NULL)
85		*p = '\0';
86	else {
87		/* Flush this line */
88		while ((ch = fgetc(fp)) != '\n' && ch != EOF);
89		if (ch == EOF) {
90			*buf = '\0';
91			fclose(fp);
92			fp = popfp();
93			return(fp);
94		}
95	}
96	switch (tokenscpp(buf, name)) {
97	case T_INCLUDE:
98		*buf = '\0';
99		if ((nfp = fopen(name, "r")) != NULL) {
100			pushfp(fp);
101			fp = nfp;
102		}
103		break;
104	case T_DEFINE:
105		addsym(name);
106		break;
107	case T_IFNDEF:
108		if (findsym(name)) {
109			fclose(fp);
110			fp = popfp();
111			*buf = '\0';
112		}
113		break;
114	case T_ENDIF:
115		*buf = '\0';
116		break;
117	default:
118		break;
119	}
120	return (fp);
121}
122
123static int
124tokenscpp(char *buf, char *string)
125{
126	char *p;
127	char *s;
128
129	if ((p = strstr(buf, "#define")) != NULL) {
130		p += 8;
131		while (isspace((unsigned char)*p))
132			p++;
133		s = p;
134		while(!isspace((unsigned char)*p))
135			p++;
136		strncpy(string, s, MAXPATHLEN);
137		return(T_DEFINE);
138	} else if ((p = strstr(buf, "#ifndef")) != NULL) {
139		p += 8;
140		while (isspace((unsigned char)*p))
141			p++;
142		s = p;
143		while(!isspace((unsigned char)*p))
144			p++;
145		*p = '\0';
146		strncpy(string, s, MAXPATHLEN);
147		return(T_IFNDEF);
148	} else if ((p = strstr(buf, "#endif")) != NULL) {
149		return(T_ENDIF);
150	} if ((p = strstr(buf, "#include")) != NULL) {
151		p += 8;
152		while (isspace((unsigned char)*p))
153			p++;
154		if (*p == '<') {
155			s = p+1;
156			if ((p = strchr(s, '>')) != NULL)
157				*p = '\0';
158			snprintf (string, MAXPATHLEN, "%s/%s",
159				_PATH_INCLUDE, s);
160		} else if (*p == '(') {
161			s = p+1;
162			if ((p = strchr(p, '>')) != NULL)
163				*p = '\0';
164			snprintf (string, MAXPATHLEN, "%s", s);
165		}
166		return(T_INCLUDE);
167	}
168	return(T_INVALID);
169}
170
171static void
172pushfp(FILE *fp)
173{
174	curfpi++;
175	if (curfpi == MAXFPSTACK)
176		errx(1, "Max #include reached");
177	fpstack[curfpi] = fp;
178}
179
180static
181FILE *popfp(void)
182{
183	FILE *tmp;
184
185	assert(curfpi >= 0);
186	tmp = fpstack[curfpi];
187	curfpi--;
188	return(tmp);
189}
190
191void
192initcpp(void)
193{
194	int i;
195
196	for (i=0; i < MAXSYMS; i++)
197		symtable[i] = NULL;
198	fpstack[0] = NULL;
199	curfpi = 0;
200}
201
202
203static void
204addsym(const char *name)
205{
206	int i;
207
208	if (!findsym(name))
209		for (i=0; i < MAXSYMS; i++) {
210			if (symtable[i] == NULL) {
211				symtable[i] = strdup(name);
212				if (symtable[i] == NULL)
213					errx(1, "malloc error in addsym");
214				return;
215			}
216		}
217	errx(1, "symbol table full\n");
218}
219
220static int
221findsym(const char *name)
222{
223	int i;
224
225	for (i=0; i < MAXSYMS; i++)
226		if (symtable[i] != NULL && strcmp(symtable[i],name) == 0)
227			return (1);
228	return (0);
229}
230