diff options
Diffstat (limited to 'src/preproc.c')
-rw-r--r-- | src/preproc.c | 812 |
1 files changed, 0 insertions, 812 deletions
diff --git a/src/preproc.c b/src/preproc.c deleted file mode 100644 index 4d69602..0000000 --- a/src/preproc.c +++ /dev/null | |||
@@ -1,812 +0,0 @@ | |||
1 | /* grecs - Gray's Extensible Configuration System | ||
2 | Copyright (C) 2007-2016 Sergey Poznyakoff | ||
3 | |||
4 | Grecs is free software; you can redistribute it and/or modify it | ||
5 | under the terms of the GNU General Public License as published by the | ||
6 | Free Software Foundation; either version 3 of the License, or (at your | ||
7 | option) any later version. | ||
8 | |||
9 | Grecs is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License along | ||
15 | with Grecs. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | #include <grecs.h> | ||
21 | #include <wordsplit.h> | ||
22 | #include <sys/types.h> | ||
23 | #include <sys/stat.h> | ||
24 | #include <sys/wait.h> | ||
25 | #include <ctype.h> | ||
26 | #include <stdio.h> | ||
27 | #include <stdlib.h> | ||
28 | #include <stdarg.h> | ||
29 | #include <string.h> | ||
30 | #include <errno.h> | ||
31 | #include <signal.h> | ||
32 | #include <glob.h> | ||
33 | #include <unistd.h> | ||
34 | |||
35 | |||
36 | int grecs_log_to_stderr = 1; | ||
37 | void (*grecs_log_setup_hook) () = NULL; | ||
38 | |||
39 | struct input_file_ident { | ||
40 | ino_t i_node; | ||
41 | dev_t device; | ||
42 | }; | ||
43 | |||
44 | struct buffer_ctx { | ||
45 | struct buffer_ctx *prev; /* Pointer to previous context */ | ||
46 | grecs_locus_t locus; /* Current input location */ | ||
47 | size_t namelen; /* Length of the file name */ | ||
48 | size_t xlines; /* Number of #line directives output so far */ | ||
49 | struct input_file_ident id; | ||
50 | FILE *infile; | ||
51 | }; | ||
52 | |||
53 | extern int grecs_grecs__flex_debug; | ||
54 | static struct buffer_ctx *context_stack; | ||
55 | static char *linebufbase = NULL; | ||
56 | static size_t linebufsize = 0; | ||
57 | |||
58 | #define INFILE context_stack->infile | ||
59 | #define LOCUS context_stack->locus | ||
60 | #define POINT context_stack->locus.beg | ||
61 | |||
62 | static char *linebuf; | ||
63 | static size_t bufsize; | ||
64 | static char *putback_buffer; | ||
65 | static size_t putback_size; | ||
66 | static size_t putback_max; | ||
67 | static glob_t include_glob; | ||
68 | static size_t include_pos; | ||
69 | static int include_once; | ||
70 | |||
71 | static int push_source (const char *name, int once); | ||
72 | static int pop_source (void); | ||
73 | static int parse_include (const char *text, int once); | ||
74 | |||
75 | ssize_t | ||
76 | grecs_getline(char **pbuf, size_t *psize, FILE *fp) | ||
77 | { | ||
78 | char *buf = *pbuf; | ||
79 | size_t size = *psize; | ||
80 | ssize_t off = 0; | ||
81 | |||
82 | if (!buf) { | ||
83 | size = 1; | ||
84 | buf = grecs_malloc(size); | ||
85 | } | ||
86 | |||
87 | do { | ||
88 | if (off == size - 1) { | ||
89 | size_t nsize = 2 * size; | ||
90 | if (nsize < size) | ||
91 | grecs_alloc_die(); | ||
92 | buf = grecs_realloc(buf, nsize); | ||
93 | size = nsize; | ||
94 | } | ||
95 | if (!fgets(buf + off, size - off, fp)) { | ||
96 | if (off == 0) | ||
97 | off = -1; | ||
98 | break; | ||
99 | } | ||
100 | off += strlen(buf + off); | ||
101 | } while (buf[off - 1] != '\n'); | ||
102 | |||
103 | *pbuf = buf; | ||
104 | *psize = size; | ||
105 | return off; | ||
106 | } | ||
107 | |||
108 | static void | ||
109 | putback(const char *str) | ||
110 | { | ||
111 | size_t len; | ||
112 | |||
113 | if (!*str) | ||
114 | return; | ||
115 | len = strlen(str) + 1; | ||
116 | if (len > putback_max) { | ||
117 | putback_max = len; | ||
118 | putback_buffer = grecs_realloc(putback_buffer, putback_max); | ||
119 | } | ||
120 | strcpy(putback_buffer, str); | ||
121 | putback_size = len - 1; | ||
122 | } | ||
123 | |||
124 | static void | ||
125 | pp_line_stmt() | ||
126 | { | ||
127 | size_t ls_size; | ||
128 | size_t pb_size; | ||
129 | |||
130 | if (grecs_asprintf(&linebufbase, &linebufsize, | ||
131 | "#line %lu \"%s\" %lu\n", | ||
132 | (unsigned long) POINT.line, | ||
133 | POINT.file, (unsigned long) context_stack->xlines)) | ||
134 | grecs_alloc_die(); | ||
135 | |||
136 | ls_size = strlen(linebufbase); | ||
137 | pb_size = putback_size + ls_size + 1; | ||
138 | |||
139 | if (pb_size > putback_max) { | ||
140 | putback_max = pb_size; | ||
141 | putback_buffer = grecs_realloc(putback_buffer, putback_max); | ||
142 | } | ||
143 | |||
144 | context_stack->xlines++; | ||
145 | strcpy(putback_buffer + putback_size, linebufbase); | ||
146 | putback_size += ls_size; | ||
147 | } | ||
148 | |||
149 | #define STRMATCH(p, len, s) (len >= sizeof(s) \ | ||
150 | && memcmp(p, s, sizeof(s) - 1) == 0 \ | ||
151 | && isspace(p[sizeof(s) - 1])) | ||
152 | |||
153 | static int | ||
154 | next_line() | ||
155 | { | ||
156 | ssize_t rc; | ||
157 | |||
158 | do { | ||
159 | if (putback_size) { | ||
160 | if (putback_size + 1 > bufsize) { | ||
161 | bufsize = putback_size + 1; | ||
162 | linebuf = grecs_realloc(linebuf, bufsize); | ||
163 | } | ||
164 | strcpy(linebuf, putback_buffer); | ||
165 | rc = putback_size; | ||
166 | putback_size = 0; | ||
167 | } | ||
168 | else if (!context_stack) | ||
169 | return 0; | ||
170 | else | ||
171 | rc = grecs_getline(&linebuf, &bufsize, INFILE); | ||
172 | } while (rc == -1 && pop_source() == 0); | ||
173 | return rc; | ||
174 | } | ||
175 | |||
176 | size_t | ||
177 | grecs_preproc_fill_buffer(char *buf, size_t size) | ||
178 | { | ||
179 | size_t bufsize = size; | ||
180 | |||
181 | while (next_line() > 0) { | ||
182 | char *p; | ||
183 | size_t len; | ||
184 | int is_line = 0; | ||
185 | |||
186 | for (p = linebuf; *p && isspace(*p); p++) | ||
187 | ; | ||
188 | if (*p == '#') { | ||
189 | size_t l; | ||
190 | for (p++; *p && isspace(*p); p++) | ||
191 | ; | ||
192 | l = strlen(p); | ||
193 | if (STRMATCH(p, l, "include_once")) { | ||
194 | if (parse_include(linebuf, 1)) | ||
195 | putback("/*include_once*/\n"); | ||
196 | continue; | ||
197 | } else if (STRMATCH(p, l, "include")) { | ||
198 | if (parse_include(linebuf, 0)) | ||
199 | putback("/*include*/\n"); | ||
200 | continue; | ||
201 | } else if (STRMATCH(p, l, "line")) | ||
202 | is_line = 1; | ||
203 | } | ||
204 | |||
205 | len = strlen(linebuf); | ||
206 | |||
207 | if (len > size) | ||
208 | len = size; | ||
209 | |||
210 | memcpy(buf, linebuf, len); | ||
211 | buf += len; | ||
212 | size -= len; | ||
213 | |||
214 | if (size == 0) { | ||
215 | putback(linebuf + len); | ||
216 | break; | ||
217 | } | ||
218 | |||
219 | if (!is_line && len > 0 && linebuf[len - 1] == '\n') | ||
220 | POINT.line++; | ||
221 | } | ||
222 | return bufsize - size; | ||
223 | } | ||
224 | |||
225 | #define STAT_ID_EQ(st,id) ((id).i_node == (st).st_ino \ | ||
226 | && (id).device == (st).st_dev) | ||
227 | |||
228 | static struct buffer_ctx * | ||
229 | ctx_lookup(struct stat *st) | ||
230 | { | ||
231 | struct buffer_ctx *ctx; | ||
232 | |||
233 | if (!context_stack) | ||
234 | return NULL; | ||
235 | |||
236 | for (ctx = context_stack->prev; ctx; ctx = ctx->prev) | ||
237 | if (STAT_ID_EQ(*st, ctx->id)) | ||
238 | break; | ||
239 | return ctx; | ||
240 | } | ||
241 | |||
242 | const char *grecs_preprocessor = NULL; | ||
243 | static struct grecs_list *grecs_usr_include_path; | ||
244 | static struct grecs_list *grecs_std_include_path; | ||
245 | |||
246 | size_t | ||
247 | grecs_include_path_count(int flag) | ||
248 | { | ||
249 | size_t count = 0; | ||
250 | if (flag & GRECS_STD_INCLUDE) | ||
251 |