32 #include <string.h> |
32 #include <string.h> |
33 #include <fcntl.h> |
33 #include <fcntl.h> |
34 #include <unistd.h> |
34 #include <unistd.h> |
35 #include <ctype.h> |
35 #include <ctype.h> |
36 |
36 |
|
37 #include "javacodegen.h" |
|
38 #include "ccodegen.h" |
|
39 |
37 #define INPUTBUF_SIZE 2048 |
40 #define INPUTBUF_SIZE 2048 |
38 #define WORDBUF_SIZE 64 |
|
39 |
|
40 const char* ckeywords[] = { |
|
41 "auto", "break", "case", "char", "const", "continue", "default", "do", |
|
42 "double", "else", "enum", "extern", "float", "for", "goto", "if", "int", |
|
43 "long", "register", "return", "short", "signed", "sizeof", "static", |
|
44 "struct", "switch", "typedef", "union", "unsigned", "void", "volatile", |
|
45 "while", NULL |
|
46 }; |
|
47 |
|
48 const char* jkeywords[] = { |
|
49 "abstract", "continue", "for", "new", "switch", "assert", "default", "goto", |
|
50 "package", "synchronized", "boolean", "do", "if", "private", "this", |
|
51 "break", "double", "implements", "protected", "throw", "byte", "else", |
|
52 "import", "public", "throws", "case", "enum", "instanceof", "return", |
|
53 "transient", "catch", "extends", "int", "short", "try", "char", "final", |
|
54 "interface", "static", "void", "class", "finally", "long", "strictfp", |
|
55 "volatile", "const", "float", "native", "super", "while", NULL |
|
56 }; |
|
57 |
|
58 #define iswordcharacter(c) (isalnum(c) || c=='_' || c=='#' || c=='@') |
|
59 |
|
60 int isctype(char *word, size_t len) { |
|
61 return (word[len-2] == '_' && word[len-1] == 't'); |
|
62 } |
|
63 |
|
64 int iscdirective(char *word) { |
|
65 return (word[0] == '#'); |
|
66 } |
|
67 |
|
68 int isjtype(char *word, size_t len) { |
|
69 return isupper(word[0]); |
|
70 } |
|
71 |
|
72 int isjdirective(char *word) { |
|
73 return word[0] == '@'; |
|
74 } |
|
75 |
|
76 typedef struct _highlighter_t highlighter_t; |
|
77 |
|
78 struct _highlighter_t { |
|
79 const char** keywords; |
|
80 int(*istype)(char*,size_t); |
|
81 int(*isdirective)(char*); |
|
82 void(*parser)(char*,char*,highlighter_t*); |
|
83 int iscommentml; |
|
84 char word[WORDBUF_SIZE]; |
|
85 char includefile[FILENAME_MAX]; |
|
86 }; |
|
87 |
41 |
88 typedef struct { |
42 typedef struct { |
89 char* outfilename; |
43 char* outfilename; |
90 char* infilename; |
44 char* infilename; |
91 int highlight; |
45 int highlight; |
165 free(line); |
119 free(line); |
166 |
120 |
167 close(fd); |
121 close(fd); |
168 |
122 |
169 return inputfile; |
123 return inputfile; |
170 } |
|
171 |
|
172 size_t writeescapedchar(char *dest, size_t dp, char c) { |
|
173 if (c == '>') { |
|
174 dest[dp++] = '&'; dest[dp++] = 'g'; dest[dp++] = 't'; dest[dp++] = ';'; |
|
175 } else if (c == '<') { |
|
176 dest[dp++] = '&'; dest[dp++] = 'l'; dest[dp++] = 't'; dest[dp++] = ';'; |
|
177 } else { |
|
178 dest[dp++] = c; |
|
179 } |
|
180 |
|
181 return dp; |
|
182 } |
|
183 |
|
184 int iskeyword(char *word, const char** keywords) { |
|
185 for (int i = 0 ; keywords[i] ; i++) { |
|
186 if (strncmp(keywords[i], word, WORDBUF_SIZE) == 0) { |
|
187 return 1; |
|
188 } |
|
189 } |
|
190 return 0; |
|
191 } |
|
192 |
|
193 int iscapsonly(char *word, size_t wp) { |
|
194 for (size_t i = 0 ; i < wp ; i++) { |
|
195 if (!isupper(word[i]) && word[i] != '_') { |
|
196 return 0; |
|
197 } |
|
198 } |
|
199 return 1; |
|
200 } |
|
201 |
|
202 void parseline(char *src, char *dest, highlighter_t *hltr) { |
|
203 hltr->parser(src, dest, hltr); |
|
204 } |
|
205 |
|
206 void cjparseline(char *src, char *dest, highlighter_t *hltr) { |
|
207 size_t sp = 0, dp = 0; |
|
208 /* indent */ |
|
209 while (isspace(src[sp])) { |
|
210 dest[dp++] = src[sp++]; |
|
211 } |
|
212 |
|
213 memset(hltr->word, 0, WORDBUF_SIZE); |
|
214 size_t wp = 0, ifp = 0; |
|
215 int isstring = 0, iscomment = 0, isinclude = 0, parseinclude = 0; |
|
216 int isescaping = 0; |
|
217 |
|
218 if (hltr->iscommentml) { |
|
219 iscomment = 1; |
|
220 memcpy(&(dest[dp]), "<span class=\"c2html-comment\">", 29); |
|
221 dp += 29; |
|
222 } |
|
223 |
|
224 for (char c = src[sp] ; c ; c=src[++sp]) { |
|
225 /* comments */ |
|
226 if (c == '/') { |
|
227 if (hltr->iscommentml && sp > 0 && src[sp-1] == '*') { |
|
228 iscomment = 0; |
|
229 hltr->iscommentml = 0; |
|
230 memcpy(&(dest[dp]), "/</span>", 8); |
|
231 dp += 8; |
|
232 continue; |
|
233 } else if (!iscomment && (src[sp+1] == '/' || src[sp+1] == '*')) { |
|
234 iscomment = 1; |
|
235 hltr->iscommentml = (src[sp+1] == '*'); |
|
236 memcpy(&(dest[dp]), "<span class=\"c2html-comment\">", 29); |
|
237 dp += 29; |
|
238 } |
|
239 } |
|
240 |
|
241 if (iscomment) { |
|
242 if (c == '\n') { |
|
243 memcpy(&(dest[dp]), "</span>", 7); |
|
244 dp += 7; |
|
245 } |
|
246 dp = writeescapedchar(dest, dp, c); |
|
247 } else if (isinclude) { |
|
248 if (c == '<') { |
|
249 memcpy(&(dest[dp]), "<span class=\"c2html-stdinclude\">", 32); |
|
250 dp += 32; |
|
251 dp = writeescapedchar(dest, dp, c); |
|
252 } else if (c == '\"') { |
|
253 if (parseinclude) { |
|
254 dest[dp++] = '\"'; |
|
255 dest[dp++] = '>'; |
|
256 memcpy(&(dest[dp]), hltr->includefile, ifp); |
|
257 dp += ifp; |
|
258 |
|
259 dp = writeescapedchar(dest, dp, c); |
|
260 memcpy(&(dest[dp]), "</a>", 4); |
|
261 dp += 4; |
|
262 parseinclude = 0; |
|
263 } else { |
|
264 memcpy(&(dest[dp]), |
|
265 "<a class=\"c2html-userinclude\" href=", 35); |
|
266 dp += 35; |
|
267 dp = writeescapedchar(dest, dp, c); |
|
268 ifp = 0; |
|
269 hltr->includefile[ifp++] = '\"'; |
|
270 parseinclude = 1; |
|
271 } |
|
272 } else if (c == '>') { |
|
273 dp = writeescapedchar(dest, dp, c); |
|
274 memcpy(&(dest[dp]), "</span>", 7); |
|
275 dp += 7; |
|
276 } else { |
|
277 if (parseinclude) { |
|
278 hltr->includefile[ifp++] = c; |
|
279 } |
|
280 dp = writeescapedchar(dest, dp, c); |
|
281 } |
|
282 } else { |
|
283 /* strings */ |
|
284 if (!isescaping && (c == '\'' || c == '\"')) { |
|
285 isstring ^= 1; |
|
286 if (isstring) { |
|
287 memcpy(&(dest[dp]), "<span class=\"c2html-string\">", 28); |
|
288 dp += 28; |
|
289 dp = writeescapedchar(dest, dp, c); |
|
290 } else { |
|
291 dp = writeescapedchar(dest, dp, c); |
|
292 memcpy(&(dest[dp]), "</span>", 7); |
|
293 dp += 7; |
|
294 } |
|
295 } else { |
|
296 if (isstring) { |
|
297 dp = writeescapedchar(dest, dp, c); |
|
298 } else if (!iswordcharacter(c)) { |
|
299 /* interpret word int_t */ |
|
300 if (wp > 0 && wp < WORDBUF_SIZE) { |
|
301 int closespan = 1; |
|
302 if (iskeyword(hltr->word, hltr->keywords)) { |
|
303 memcpy(&(dest[dp]), |
|
304 "<span class=\"c2html-keyword\">", 29); |
|
305 dp += 29; |
|
306 } else if (hltr->istype(hltr->word, wp)) { |
|
307 memcpy(&(dest[dp]), |
|
308 "<span class=\"c2html-type\">", 26); |
|
309 dp += 26; |
|
310 } else if (hltr->isdirective(hltr->word)) { |
|
311 isinclude = !strncmp( |
|
312 "#include", hltr->word, WORDBUF_SIZE); |
|
313 memcpy(&(dest[dp]), |
|
314 "<span class=\"c2html-directive\">", 31); |
|
315 dp += 31; |
|
316 } else if (iscapsonly(hltr->word, wp)) { |
|
317 memcpy(&(dest[dp]), |
|
318 "<span class=\"c2html-macroconst\">", 32); |
|
319 dp += 32; |
|
320 } else { |
|
321 closespan = 0; |
|
322 } |
|
323 for (int i = 0 ; i < wp ; i++) { |
|
324 dp = writeescapedchar(dest, dp, hltr->word[i]); |
|
325 } |
|
326 if (closespan) { |
|
327 memcpy(&(dest[dp]), "</span>", 7); |
|
328 dp += 7; |
|
329 } |
|
330 } |
|
331 memset(hltr->word, 0, WORDBUF_SIZE); |
|
332 wp = 0; |
|
333 dp = writeescapedchar(dest, dp, c); |
|
334 } else { |
|
335 /* read word */ |
|
336 if (wp < WORDBUF_SIZE) { |
|
337 hltr->word[wp++] = c; |
|
338 } else if (wp == WORDBUF_SIZE) { |
|
339 for (int i = 0 ; i < WORDBUF_SIZE ; i++) { |
|
340 dp = writeescapedchar(dest, dp, hltr->word[i]); |
|
341 } |
|
342 wp++; |
|
343 dp = writeescapedchar(dest, dp, c); |
|
344 } else { |
|
345 dp = writeescapedchar(dest, dp, c); |
|
346 } |
|
347 } |
|
348 } |
|
349 |
|
350 isescaping = !isescaping & (c == '\\'); |
|
351 } |
|
352 } |
|
353 dest[dp] = 0; |
|
354 } |
124 } |
355 |
125 |
356 void printhelp() { |
126 void printhelp() { |
357 printf("Formats source code using HTML.\n\nUsage:\n" |
127 printf("Formats source code using HTML.\n\nUsage:\n" |
358 " c2html [Options] FILE\n\n" |
128 " c2html [Options] FILE\n\n" |