comparison lwcc/cpp.c @ 495:5b8871fd7503

Merged previous lwcc development branch into mainline.
author William Astle <lost@l-w.ca>
date Mon, 05 Aug 2019 21:27:09 -0600
parents 670ea8f90212
children
comparison
equal deleted inserted replaced
493:6073f4a33475 495:5b8871fd7503
1 /*
2 lwcc/cpp.c
3
4 Copyright © 2013 William Astle
5
6 This file is part of LWTOOLS.
7
8 LWTOOLS is free software: you can redistribute it and/or modify it under the
9 terms of the GNU General Public License as published by the Free Software
10 Foundation, either version 3 of the License, or (at your option) any later
11 version.
12
13 This program is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 more details.
17
18 You should have received a copy of the GNU General Public License along with
19 this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include <lw_alloc.h>
28 #include <lw_string.h>
29 #include <lw_stringlist.h>
30 #include <lw_strpool.h>
31 #include "cpp.h"
32
33
34 struct token *preproc_lex_next_token(struct preproc_info *);
35
36 struct preproc_info *preproc_init(const char *fn)
37 {
38 FILE *fp;
39 struct preproc_info *pp;
40
41 if (!fn || (fn[0] == '-' && fn[1] == '0'))
42 {
43 fp = stdin;
44 }
45 else
46 {
47 fp = fopen(fn, "rb");
48 }
49 if (!fp)
50 return NULL;
51
52 pp = lw_alloc(sizeof(struct preproc_info));
53 memset(pp, 0, sizeof(struct preproc_info));
54 pp -> strpool = lw_strpool_create();
55 pp -> fn = lw_strpool_strdup(pp -> strpool, fn);
56 pp -> fp = fp;
57 pp -> ra = CPP_NOUNG;
58 pp -> unget = CPP_NOUNG;
59 pp -> ppeolseen = 1;
60 pp -> lineno = 1;
61 pp -> n = NULL;
62 pp -> quotelist = lw_stringlist_create();
63 pp -> inclist = lw_stringlist_create();
64 return pp;
65 }
66
67 void preproc_add_include(struct preproc_info *pp, char *dir, int sys)
68 {
69 if (sys)
70 lw_stringlist_addstring(pp -> inclist, dir);
71 else
72 lw_stringlist_addstring(pp -> quotelist, dir);
73 }
74
75 struct token *preproc_next_token(struct preproc_info *pp)
76 {
77 struct token *t;
78
79 if (pp -> curtok)
80 token_free(pp -> curtok);
81
82 /*
83 If there is a list of tokens to process, move it to the "unget" queue
84 with an EOF marker at the end of it.
85 */
86 if (pp -> sourcelist)
87 {
88 for (t = pp -> sourcelist; t -> next; t = t -> next)
89 /* do nothing */ ;
90 t -> next = token_create(TOK_EOF, NULL, -1, -1, "");
91 t -> next -> next = pp -> tokqueue;
92 pp -> tokqueue = pp -> sourcelist;
93 pp -> sourcelist = NULL;
94 }
95 again:
96 if (pp -> tokqueue)
97 {
98 t = pp -> tokqueue;
99 pp -> tokqueue = t -> next;
100 if (pp -> tokqueue)
101 pp -> tokqueue -> prev = NULL;
102 t -> next = NULL;
103 t -> prev = NULL;
104 pp -> curtok = t;
105 goto ret;
106 }
107 pp -> curtok = preproc_lex_next_token(pp);
108 t = pp -> curtok;
109 ret:
110 if (t -> ttype == TOK_ENDEXPAND)
111 {
112 struct expand_e *e;
113 e = pp -> expand_list;
114 pp -> expand_list = e -> next;
115 lw_free(e);
116 goto again;
117 }
118 return t;
119 }
120
121 void preproc_unget_token(struct preproc_info *pp, struct token *t)
122 {
123 t -> next = pp -> tokqueue;
124 pp -> tokqueue = t;
125 if (pp -> curtok == t)
126 pp -> curtok = NULL;
127 }
128
129 void preproc_finish(struct preproc_info *pp)
130 {
131 fclose(pp -> fp);
132 lw_stringlist_destroy(pp -> inclist);
133 lw_stringlist_destroy(pp -> quotelist);
134 if (pp -> curtok)
135 token_free(pp -> curtok);
136 while (pp -> tokqueue)
137 {
138 preproc_next_token(pp);
139 token_free(pp -> curtok);
140 }
141 lw_strpool_free(pp -> strpool);
142 lw_free(pp);
143 }
144
145 void preproc_register_error_callback(struct preproc_info *pp, void (*cb)(const char *))
146 {
147 pp -> errorcb = cb;
148 }
149
150 void preproc_register_warning_callback(struct preproc_info *pp, void (*cb)(const char *))
151 {
152 pp -> warningcb = cb;
153 }
154
155 static void preproc_throw_error_default(const char *m)
156 {
157 fprintf(stderr, "ERROR: %s\n", m);
158 }
159
160 static void preproc_throw_warning_default(const char *m)
161 {
162 fprintf(stderr, "WARNING: %s\n", m);
163 }
164
165 static void preproc_throw_message(struct preproc_info *pp, void (*cb)(const char *), const char *m, va_list args)
166 {
167 int s, s2;
168 char *b;
169
170 s2 = snprintf(NULL, 0, "(%s:%d:%d) ", pp -> fn, pp -> lineno, pp -> column);
171 s = vsnprintf(NULL, 0, m, args);
172 b = lw_alloc(s + s2 + 1);
173 snprintf(b, s2 + 1, "(%s:%d:%d) ", pp -> fn, pp -> lineno, pp -> column);
174 vsnprintf(b + s2, s + 1, m, args);
175 (*cb)(b);
176 lw_free(b);
177 }
178
179 void preproc_throw_error(struct preproc_info *pp, const char *m, ...)
180 {
181 va_list args;
182 va_start(args, m);
183 preproc_throw_message(pp, pp -> errorcb ? pp -> errorcb : preproc_throw_error_default, m, args);
184 va_end(args);
185 exit(1);
186 }
187
188 void preproc_throw_warning(struct preproc_info *pp, const char *m, ...)
189 {
190 va_list args;
191 va_start(args, m);
192 preproc_throw_message(pp, pp -> warningcb ? pp -> warningcb : preproc_throw_warning_default, m, args);
193 va_end(args);
194 }