35 #include <ctype.h> |
35 #include <ctype.h> |
36 |
36 |
37 #define INPUTBUF_SIZE 2048 |
37 #define INPUTBUF_SIZE 2048 |
38 #define WORDBUF_SIZE 16 |
38 #define WORDBUF_SIZE 16 |
39 |
39 |
|
40 #define istype(word, len) (word[len-2] == '_' && word[len-1] == 't') |
|
41 #define isdirective(word) (word[0] == '#') |
|
42 |
40 const char* keywords[] = { |
43 const char* keywords[] = { |
41 "auto", "break", "case", "char", "const", "continue", "default", "do", |
44 "auto", "break", "case", "char", "const", "continue", "default", "do", |
42 "double", "else", "enum", "extern", "float", "for", "goto", "if", "int", |
45 "double", "else", "enum", "extern", "float", "for", "goto", "if", "int", |
43 "long", "register", "return", "short", "signed", "sizeof", "static", "struct", |
46 "long", "register", "return", "short", "signed", "sizeof", "static", "struct", |
44 "switch", "typedef", "union", "unsigned", "void", "volatile", "while", NULL |
47 "switch", "typedef", "union", "unsigned", "void", "volatile", "while", NULL |
149 } |
152 } |
150 } |
153 } |
151 return 0; |
154 return 0; |
152 } |
155 } |
153 |
156 |
154 #define istype(word, len) (word[len-2] == '_' && word[len-1] == 't') |
157 int iscapsonly(char *word, size_t wp) { |
|
158 for (size_t i = 0 ; i < wp ; i++) { |
|
159 if (!isupper(word[i]) && word[i] != '_') { |
|
160 return 0; |
|
161 } |
|
162 } |
|
163 return 1; |
|
164 } |
155 |
165 |
156 void parseline(char *src, char *dest) { |
166 void parseline(char *src, char *dest) { |
157 size_t sp = 0, dp = 0; |
167 size_t sp = 0, dp = 0; |
158 /* indent */ |
168 /* indent */ |
159 while (isspace(src[sp])) { |
169 while (isspace(src[sp])) { |
160 dest[dp++] = src[sp++]; |
170 dest[dp++] = src[sp++]; |
161 } |
171 } |
162 char word[WORDBUF_SIZE]; |
172 |
|
173 static char word[WORDBUF_SIZE]; |
|
174 static char includefile[FILENAME_MAX]; |
|
175 |
163 memset(word, 0, WORDBUF_SIZE); |
176 memset(word, 0, WORDBUF_SIZE); |
164 size_t wp = 0; |
177 size_t wp = 0, ifp = 0; |
165 int closespan; |
178 int isstring = 0, iscomment = 0, isinclude = 0, parseinclude = 0; |
|
179 static int iscommentml; |
|
180 int isescaping = 0; |
|
181 |
|
182 if (iscommentml) { |
|
183 iscomment = 1; |
|
184 memcpy(&(dest[dp]), "<span class=\"c2html-comment\">", 29); |
|
185 dp += 29; |
|
186 } |
|
187 |
166 for (char c = src[sp] ; c ; c=src[++sp]) { |
188 for (char c = src[sp] ; c ; c=src[++sp]) { |
167 if (!isalnum(c) && c != '_') { |
189 /* comments */ |
168 /* interpret word int_t */ |
190 if (c == '/') { |
169 if (wp > 0 && wp < WORDBUF_SIZE) { |
191 if (iscommentml && sp > 0 && src[sp-1] == '*') { |
170 if (iskeyword(word)) { |
192 iscomment = 0; |
171 memcpy(&(dest[dp]), "<span class=\"c2html-keyword\">", 29); |
193 iscommentml = 0; |
172 dp += 29; |
194 memcpy(&(dest[dp]), "/</span>", 8); |
173 closespan = 1; |
195 dp += 8; |
174 } else if (istype(word, wp)) { |
196 continue; |
175 memcpy(&(dest[dp]), "<span class=\"c2html-type\">", 26); |
197 } else if (!iscomment && (src[sp+1] == '/' || src[sp+1] == '*')) { |
176 dp += 26; |
198 iscomment = 1; |
177 closespan = 1; |
199 iscommentml = (src[sp+1] == '*'); |
|
200 memcpy(&(dest[dp]), "<span class=\"c2html-comment\">", 29); |
|
201 dp += 29; |
|
202 } |
|
203 } |
|
204 |
|
205 if (iscomment) { |
|
206 if (c == '\n') { |
|
207 memcpy(&(dest[dp]), "</span>", 7); |
|
208 dp += 7; |
|
209 } |
|
210 dp = writeescapedchar(dest, dp, c); |
|
211 } else if (isinclude) { |
|
212 if (c == '<') { |
|
213 memcpy(&(dest[dp]), "<span class=\"c2html-stdinclude\">", 32); |
|
214 dp += 32; |
|
215 dp = writeescapedchar(dest, dp, c); |
|
216 } else if (c == '\"') { |
|
217 if (parseinclude) { |
|
218 dest[dp++] = '\"'; |
|
219 dest[dp++] = '>'; |
|
220 memcpy(&(dest[dp]), includefile, ifp); |
|
221 dp += ifp; |
|
222 |
|
223 dp = writeescapedchar(dest, dp, c); |
|
224 memcpy(&(dest[dp]), "</a>", 4); |
|
225 dp += 4; |
|
226 parseinclude = 0; |
178 } else { |
227 } else { |
179 closespan = 0; |
228 memcpy(&(dest[dp]), "<a class=\"c2html-userinclude\" href=", 35); |
180 } |
229 dp += 35; |
181 for (int i = 0 ; i < wp ; i++) { |
230 dp = writeescapedchar(dest, dp, c); |
182 dp = writeescapedchar(dest, dp, word[i]); |
231 ifp = 0; |
183 } |
232 includefile[ifp++] = '\"'; |
184 if (closespan) { |
233 parseinclude = 1; |
|
234 } |
|
235 } else if (c == '>') { |
|
236 dp = writeescapedchar(dest, dp, c); |
|
237 memcpy(&(dest[dp]), "</span>", 7); |
|
238 dp += 7; |
|
239 } else { |
|
240 if (parseinclude) { |
|
241 includefile[ifp++] = c; |
|
242 } |
|
243 dp = writeescapedchar(dest, dp, c); |
|
244 } |
|
245 } else { |
|
246 /* strings */ |
|
247 if (!isescaping && (c == '\'' || c == '\"')) { |
|
248 isstring ^= 1; |
|
249 if (isstring) { |
|
250 memcpy(&(dest[dp]), "<span class=\"c2html-string\">", 28); |
|
251 dp += 28; |
|
252 dp = writeescapedchar(dest, dp, c); |
|
253 } else { |
|
254 dp = writeescapedchar(dest, dp, c); |
185 memcpy(&(dest[dp]), "</span>", 7); |
255 memcpy(&(dest[dp]), "</span>", 7); |
186 dp += 7; |
256 dp += 7; |
187 } |
257 } |
188 memset(word, 0, WORDBUF_SIZE); |
|
189 wp = 0; |
|
190 } |
|
191 dp = writeescapedchar(dest, dp, c); |
|
192 } else { |
|
193 /* read word */ |
|
194 if (wp < WORDBUF_SIZE) { |
|
195 word[wp++] = c; |
|
196 } else if (wp == WORDBUF_SIZE) { |
|
197 for (int i = 0 ; i < WORDBUF_SIZE ; i++) { |
|
198 dp = writeescapedchar(dest, dp, word[i]); |
|
199 } |
|
200 wp++; |
|
201 dp = writeescapedchar(dest, dp, c); |
|
202 } else { |
258 } else { |
203 dp = writeescapedchar(dest, dp, c); |
259 if (isstring) { |
204 } |
260 dp = writeescapedchar(dest, dp, c); |
|
261 } else if (!isalnum(c) && c != '_' && c != '#' && c != '.') { |
|
262 /* interpret word int_t */ |
|
263 if (wp > 0 && wp < WORDBUF_SIZE) { |
|
264 int closespan = 1; |
|
265 if (iskeyword(word)) { |
|
266 memcpy(&(dest[dp]), "<span class=\"c2html-keyword\">", 29); |
|
267 dp += 29; |
|
268 } else if (istype(word, wp)) { |
|
269 memcpy(&(dest[dp]), "<span class=\"c2html-type\">", 26); |
|
270 dp += 26; |
|
271 } else if (isdirective(word)) { |
|
272 isinclude = !strncmp("#include", word, WORDBUF_SIZE); |
|
273 memcpy(&(dest[dp]), "<span class=\"c2html-directive\">", 31); |
|
274 dp += 31; |
|
275 } else if (iscapsonly(word, wp)) { |
|
276 memcpy(&(dest[dp]), "<span class=\"c2html-macroconst\">", 32); |
|
277 dp += 32; |
|
278 } else { |
|
279 closespan = 0; |
|
280 } |
|
281 for (int i = 0 ; i < wp ; i++) { |
|
282 dp = writeescapedchar(dest, dp, word[i]); |
|
283 } |
|
284 if (closespan) { |
|
285 memcpy(&(dest[dp]), "</span>", 7); |
|
286 dp += 7; |
|
287 } |
|
288 } |
|
289 memset(word, 0, WORDBUF_SIZE); |
|
290 wp = 0; |
|
291 dp = writeescapedchar(dest, dp, c); |
|
292 } else { |
|
293 /* read word */ |
|
294 if (wp < WORDBUF_SIZE) { |
|
295 word[wp++] = c; |
|
296 } else if (wp == WORDBUF_SIZE) { |
|
297 for (int i = 0 ; i < WORDBUF_SIZE ; i++) { |
|
298 dp = writeescapedchar(dest, dp, word[i]); |
|
299 } |
|
300 wp++; |
|
301 dp = writeescapedchar(dest, dp, c); |
|
302 } else { |
|
303 dp = writeescapedchar(dest, dp, c); |
|
304 } |
|
305 } |
|
306 } |
|
307 |
|
308 isescaping = !isescaping & (c == '\\'); |
205 } |
309 } |
206 } |
310 } |
207 dest[dp] = 0; |
311 dest[dp] = 0; |
208 } |
312 } |
209 |
313 |