36 |
36 |
37 #define INPUTBUF_SIZE 2048 |
37 #define INPUTBUF_SIZE 2048 |
38 #define WORDBUF_SIZE 64 |
38 #define WORDBUF_SIZE 64 |
39 |
39 |
40 const char* ckeywords[] = { |
40 const char* ckeywords[] = { |
41 "auto", "break", "case", "char", "const", "continue", "default", "do", |
41 "auto", "break", "case", "char", "const", "continue", "default", "do", |
42 "double", "else", "enum", "extern", "float", "for", "goto", "if", "int", |
42 "double", "else", "enum", "extern", "float", "for", "goto", "if", "int", |
43 "long", "register", "return", "short", "signed", "sizeof", "static", |
43 "long", "register", "return", "short", "signed", "sizeof", "static", |
44 "struct", "switch", "typedef", "union", "unsigned", "void", "volatile", |
44 "struct", "switch", "typedef", "union", "unsigned", "void", "volatile", |
45 "while", NULL |
45 "while", NULL |
46 }; |
46 }; |
47 |
47 |
48 const char* jkeywords[] = { |
48 const char* jkeywords[] = { |
49 "abstract", "continue", "for", "new", "switch", "assert", "default", "goto", |
49 "abstract", "continue", "for", "new", "switch", "assert", "default", "goto", |
50 "package", "synchronized", "boolean", "do", "if", "private", "this", |
50 "package", "synchronized", "boolean", "do", "if", "private", "this", |
51 "break", "double", "implements", "protected", "throw", "byte", "else", |
51 "break", "double", "implements", "protected", "throw", "byte", "else", |
52 "import", "public", "throws", "case", "enum", "instanceof", "return", |
52 "import", "public", "throws", "case", "enum", "instanceof", "return", |
53 "transient", "catch", "extends", "int", "short", "try", "char", "final", |
53 "transient", "catch", "extends", "int", "short", "try", "char", "final", |
54 "interface", "static", "void", "class", "finally", "long", "strictfp", |
54 "interface", "static", "void", "class", "finally", "long", "strictfp", |
55 "volatile", "const", "float", "native", "super", "while", NULL |
55 "volatile", "const", "float", "native", "super", "while", NULL |
56 }; |
56 }; |
57 |
57 |
58 #define iswordcharacter(c) (isalnum(c) || c=='_' || c=='#' || c=='@') |
58 #define iswordcharacter(c) (isalnum(c) || c=='_' || c=='#' || c=='@') |
59 |
59 |
60 int isctype(char *word, size_t len) { |
60 int isctype(char *word, size_t len) { |
61 return (word[len-2] == '_' && word[len-1] == 't'); |
61 return (word[len-2] == '_' && word[len-1] == 't'); |
62 } |
62 } |
63 |
63 |
64 int iscdirective(char *word) { |
64 int iscdirective(char *word) { |
65 return (word[0] == '#'); |
65 return (word[0] == '#'); |
66 } |
66 } |
67 |
67 |
68 int isjtype(char *word, size_t len) { |
68 int isjtype(char *word, size_t len) { |
69 return isupper(word[0]); |
69 return isupper(word[0]); |
70 } |
70 } |
71 |
71 |
72 int isjdirective(char *word) { |
72 int isjdirective(char *word) { |
73 return word[0] == '@'; |
73 return word[0] == '@'; |
74 } |
74 } |
75 |
75 |
76 typedef struct { |
76 typedef struct { |
77 const char** keywords; |
77 const char** keywords; |
78 int(*istype)(char*,size_t); |
78 int(*istype)(char*,size_t); |
79 int(*isdirective)(char*); |
79 int(*isdirective)(char*); |
80 } highlighter_t; |
80 } highlighter_t; |
81 |
81 |
82 typedef struct { |
82 typedef struct { |
83 char* outfilename; |
83 char* outfilename; |
84 char* infilename; |
84 char* infilename; |
85 int highlight; |
85 int highlight; |
86 } settings_t; |
86 } settings_t; |
87 |
87 |
88 typedef struct { |
88 typedef struct { |
89 size_t count; |
89 size_t count; |
90 size_t capacity; |
90 size_t capacity; |
91 size_t maxlinewidth; |
91 size_t maxlinewidth; |
92 char** lines; |
92 char** lines; |
93 } inputfile_t; |
93 } inputfile_t; |
94 |
94 |
95 inputfile_t *inputfilebuffer(size_t capacity) { |
95 inputfile_t *inputfilebuffer(size_t capacity) { |
96 inputfile_t *inputfile = (inputfile_t*) malloc(sizeof(inputfile_t)); |
96 inputfile_t *inputfile = (inputfile_t*) malloc(sizeof(inputfile_t)); |
97 inputfile->lines = (char**) malloc(capacity * sizeof(char*)); |
97 inputfile->lines = (char**) malloc(capacity * sizeof(char*)); |
98 inputfile->capacity = capacity; |
98 inputfile->capacity = capacity; |
99 inputfile->count = 0; |
99 inputfile->count = 0; |
100 inputfile->maxlinewidth = 0; |
100 inputfile->maxlinewidth = 0; |
101 |
101 |
102 return inputfile; |
102 return inputfile; |
103 } |
103 } |
104 |
104 |
105 void addline(inputfile_t *inputfile, char* line, size_t width) { |
105 void addline(inputfile_t *inputfile, char* line, size_t width) { |
106 char *l = (char*) malloc(width+1); |
106 char *l = (char*) malloc(width+1); |
107 memcpy(l, line, width); |
107 memcpy(l, line, width); |
108 l[width] = 0; |
108 l[width] = 0; |
109 if (inputfile->count >= inputfile->capacity) { |
109 if (inputfile->count >= inputfile->capacity) { |
110 inputfile->capacity <<= 1; |
110 inputfile->capacity <<= 1; |
111 inputfile->lines = realloc(inputfile->lines, inputfile->capacity); |
111 inputfile->lines = realloc(inputfile->lines, inputfile->capacity); |
112 } |
112 } |
113 inputfile->lines[inputfile->count] = l; |
113 inputfile->lines[inputfile->count] = l; |
114 inputfile->maxlinewidth = |
114 inputfile->maxlinewidth = |
115 width > inputfile->maxlinewidth ? width : inputfile->maxlinewidth; |
115 width > inputfile->maxlinewidth ? width : inputfile->maxlinewidth; |
116 inputfile->count++; |
116 inputfile->count++; |
117 } |
117 } |
118 |
118 |
119 void freeinputfilebuffer(inputfile_t *inputfile) { |
119 void freeinputfilebuffer(inputfile_t *inputfile) { |
120 for (int i = 0 ; i < inputfile->count ; i++) { |
120 for (int i = 0 ; i < inputfile->count ; i++) { |
121 free(inputfile->lines[i]); |
121 free(inputfile->lines[i]); |
122 } |
122 } |
123 free(inputfile->lines); |
123 free(inputfile->lines); |
124 free(inputfile); |
124 free(inputfile); |
125 } |
125 } |
126 |
126 |
127 inputfile_t *readinput(char *filename) { |
127 inputfile_t *readinput(char *filename) { |
128 |
128 |
129 int fd = open(filename, O_RDONLY); |
129 int fd = open(filename, O_RDONLY); |
130 if (fd == -1) return NULL; |
130 if (fd == -1) return NULL; |
131 |
131 |
132 inputfile_t *inputfile = inputfilebuffer(512); |
132 inputfile_t *inputfile = inputfilebuffer(512); |
133 |
133 |
134 char buf[INPUTBUF_SIZE]; |
134 char buf[INPUTBUF_SIZE]; |
135 ssize_t r; |
135 ssize_t r; |
136 |
136 |
137 size_t maxlinewidth = 256; |
137 size_t maxlinewidth = 256; |
138 char *line = (char*) malloc(maxlinewidth); |
138 char *line = (char*) malloc(maxlinewidth); |
139 size_t col = 0; |
139 size_t col = 0; |
140 |
140 |
141 while ((r = read(fd, buf, INPUTBUF_SIZE)) > 0) { |
141 while ((r = read(fd, buf, INPUTBUF_SIZE)) > 0) { |
142 for (size_t i = 0 ; i < r ; i++) { |
142 for (size_t i = 0 ; i < r ; i++) { |
143 if (col >= maxlinewidth-4) { |
143 if (col >= maxlinewidth-4) { |
144 maxlinewidth <<= 1; |
144 maxlinewidth <<= 1; |
145 line = realloc(line, maxlinewidth); |
145 line = realloc(line, maxlinewidth); |
146 } |
146 } |
147 |
147 |
148 if (buf[i] == '\n') { |
148 if (buf[i] == '\n') { |
149 line[col++] = '\n'; |
149 line[col++] = '\n'; |
150 line[col] = 0; |
150 line[col] = 0; |
151 addline(inputfile, line, col); |
151 addline(inputfile, line, col); |
152 col = 0; |
152 col = 0; |
153 } else { |
153 } else { |
154 line[col++] = buf[i]; |
154 line[col++] = buf[i]; |
155 } |
155 } |
156 } |
156 } |
157 } |
157 } |
158 |
158 |
159 free(line); |
159 free(line); |
160 |
160 |
161 close(fd); |
161 close(fd); |
162 |
162 |
163 return inputfile; |
163 return inputfile; |
164 } |
164 } |
165 |
165 |
166 size_t writeescapedchar(char *dest, size_t dp, char c) { |
166 size_t writeescapedchar(char *dest, size_t dp, char c) { |
167 if (c == '>') { |
167 if (c == '>') { |
168 dest[dp++] = '&'; dest[dp++] = 'g'; |
168 dest[dp++] = '&'; dest[dp++] = 'g'; dest[dp++] = 't'; dest[dp++] = ';'; |
169 dest[dp++] = 't'; dest[dp++] = ';'; |
169 } else if (c == '<') { |
170 } else if (c == '<') { |
170 dest[dp++] = '&'; dest[dp++] = 'l'; dest[dp++] = 't'; dest[dp++] = ';'; |
171 dest[dp++] = '&'; dest[dp++] = 'l'; |
171 } else { |
172 dest[dp++] = 't'; dest[dp++] = ';'; |
172 dest[dp++] = c; |
173 } else { |
173 } |
174 dest[dp++] = c; |
174 |
175 } |
175 return dp; |
176 |
|
177 return dp; |
|
178 } |
176 } |
179 |
177 |
180 int iskeyword(char *word, const char** keywords) { |
178 int iskeyword(char *word, const char** keywords) { |
181 for (int i = 0 ; keywords[i] ; i++) { |
179 for (int i = 0 ; keywords[i] ; i++) { |
182 if (strncmp(keywords[i], word, WORDBUF_SIZE) == 0) { |
180 if (strncmp(keywords[i], word, WORDBUF_SIZE) == 0) { |
183 return 1; |
181 return 1; |
184 } |
182 } |
185 } |
183 } |
186 return 0; |
184 return 0; |
187 } |
185 } |
188 |
186 |
189 int iscapsonly(char *word, size_t wp) { |
187 int iscapsonly(char *word, size_t wp) { |
190 for (size_t i = 0 ; i < wp ; i++) { |
188 for (size_t i = 0 ; i < wp ; i++) { |
191 if (!isupper(word[i]) && word[i] != '_') { |
189 if (!isupper(word[i]) && word[i] != '_') { |
192 return 0; |
190 return 0; |
193 } |
191 } |
194 } |
192 } |
195 return 1; |
193 return 1; |
196 } |
194 } |
197 |
195 |
198 void parseline(char *src, char *dest, highlighter_t *highlighter) { |
196 void parseline(char *src, char *dest, highlighter_t *highlighter) { |
199 size_t sp = 0, dp = 0; |
197 size_t sp = 0, dp = 0; |
200 /* indent */ |
198 /* indent */ |
201 while (isspace(src[sp])) { |
199 while (isspace(src[sp])) { |
202 dest[dp++] = src[sp++]; |
200 dest[dp++] = src[sp++]; |
203 } |
201 } |
204 |
202 |
205 static char word[WORDBUF_SIZE]; |
203 static char word[WORDBUF_SIZE]; |
206 static char includefile[FILENAME_MAX]; |
204 static char includefile[FILENAME_MAX]; |
207 |
205 |
208 memset(word, 0, WORDBUF_SIZE); |
206 memset(word, 0, WORDBUF_SIZE); |
209 size_t wp = 0, ifp = 0; |
207 size_t wp = 0, ifp = 0; |
210 int isstring = 0, iscomment = 0, isinclude = 0, parseinclude = 0; |
208 int isstring = 0, iscomment = 0, isinclude = 0, parseinclude = 0; |
211 static int iscommentml; |
209 static int iscommentml; |
212 int isescaping = 0; |
210 int isescaping = 0; |
213 |
211 |
214 if (iscommentml) { |
212 if (iscommentml) { |
215 iscomment = 1; |
|
216 memcpy(&(dest[dp]), "<span class=\"c2html-comment\">", 29); |
|
217 dp += 29; |
|
218 } |
|
219 |
|
220 for (char c = src[sp] ; c ; c=src[++sp]) { |
|
221 /* comments */ |
|
222 if (c == '/') { |
|
223 if (iscommentml && sp > 0 && src[sp-1] == '*') { |
|
224 iscomment = 0; |
|
225 iscommentml = 0; |
|
226 memcpy(&(dest[dp]), "/</span>", 8); |
|
227 dp += 8; |
|
228 continue; |
|
229 } else if (!iscomment && (src[sp+1] == '/' || src[sp+1] == '*')) { |
|
230 iscomment = 1; |
213 iscomment = 1; |
231 iscommentml = (src[sp+1] == '*'); |
|
232 memcpy(&(dest[dp]), "<span class=\"c2html-comment\">", 29); |
214 memcpy(&(dest[dp]), "<span class=\"c2html-comment\">", 29); |
233 dp += 29; |
215 dp += 29; |
234 } |
216 } |
235 } |
217 |
236 |
218 for (char c = src[sp] ; c ; c=src[++sp]) { |
237 if (iscomment) { |
219 /* comments */ |
238 if (c == '\n') { |
220 if (c == '/') { |
239 memcpy(&(dest[dp]), "</span>", 7); |
221 if (iscommentml && sp > 0 && src[sp-1] == '*') { |
240 dp += 7; |
222 iscomment = 0; |
241 } |
223 iscommentml = 0; |
242 dp = writeescapedchar(dest, dp, c); |
224 memcpy(&(dest[dp]), "/</span>", 8); |
243 } else if (isinclude) { |
225 dp += 8; |
244 if (c == '<') { |
226 continue; |
245 memcpy(&(dest[dp]), "<span class=\"c2html-stdinclude\">", 32); |
227 } else if (!iscomment && (src[sp+1] == '/' || src[sp+1] == '*')) { |
246 dp += 32; |
228 iscomment = 1; |
247 dp = writeescapedchar(dest, dp, c); |
229 iscommentml = (src[sp+1] == '*'); |
248 } else if (c == '\"') { |
230 memcpy(&(dest[dp]), "<span class=\"c2html-comment\">", 29); |
249 if (parseinclude) { |
231 dp += 29; |
250 dest[dp++] = '\"'; |
232 } |
251 dest[dp++] = '>'; |
233 } |
252 memcpy(&(dest[dp]), includefile, ifp); |
234 |
253 dp += ifp; |
235 if (iscomment) { |
254 |
236 if (c == '\n') { |
255 dp = writeescapedchar(dest, dp, c); |
237 memcpy(&(dest[dp]), "</span>", 7); |
256 memcpy(&(dest[dp]), "</a>", 4); |
238 dp += 7; |
257 dp += 4; |
239 } |
258 parseinclude = 0; |
240 dp = writeescapedchar(dest, dp, c); |
|
241 } else if (isinclude) { |
|
242 if (c == '<') { |
|
243 memcpy(&(dest[dp]), "<span class=\"c2html-stdinclude\">", 32); |
|
244 dp += 32; |
|
245 dp = writeescapedchar(dest, dp, c); |
|
246 } else if (c == '\"') { |
|
247 if (parseinclude) { |
|
248 dest[dp++] = '\"'; |
|
249 dest[dp++] = '>'; |
|
250 memcpy(&(dest[dp]), includefile, ifp); |
|
251 dp += ifp; |
|
252 |
|
253 dp = writeescapedchar(dest, dp, c); |
|
254 memcpy(&(dest[dp]), "</a>", 4); |
|
255 dp += 4; |
|
256 parseinclude = 0; |
|
257 } else { |
|
258 memcpy(&(dest[dp]), |
|
259 "<a class=\"c2html-userinclude\" href=", 35); |
|
260 dp += 35; |
|
261 dp = writeescapedchar(dest, dp, c); |
|
262 ifp = 0; |
|
263 includefile[ifp++] = '\"'; |
|
264 parseinclude = 1; |
|
265 } |
|
266 } else if (c == '>') { |
|
267 dp = writeescapedchar(dest, dp, c); |
|
268 memcpy(&(dest[dp]), "</span>", 7); |
|
269 dp += 7; |
|
270 } else { |
|
271 if (parseinclude) { |
|
272 includefile[ifp++] = c; |
|
273 } |
|
274 dp = writeescapedchar(dest, dp, c); |
|
275 } |
259 } else { |
276 } else { |
260 memcpy(&(dest[dp]), "<a class=\"c2html-userinclude\" href=", 35); |
277 /* strings */ |
261 dp += 35; |
278 if (!isescaping && (c == '\'' || c == '\"')) { |
262 dp = writeescapedchar(dest, dp, c); |
279 isstring ^= 1; |
263 ifp = 0; |
280 if (isstring) { |
264 includefile[ifp++] = '\"'; |
281 memcpy(&(dest[dp]), "<span class=\"c2html-string\">", 28); |
265 parseinclude = 1; |
282 dp += 28; |
266 } |
283 dp = writeescapedchar(dest, dp, c); |
267 } else if (c == '>') { |
284 } else { |
268 dp = writeescapedchar(dest, dp, c); |
285 dp = writeescapedchar(dest, dp, c); |
269 memcpy(&(dest[dp]), "</span>", 7); |
286 memcpy(&(dest[dp]), "</span>", 7); |
270 dp += 7; |
287 dp += 7; |
271 } else { |
288 } |
272 if (parseinclude) { |
289 } else { |
273 includefile[ifp++] = c; |
290 if (isstring) { |
274 } |
291 dp = writeescapedchar(dest, dp, c); |
275 dp = writeescapedchar(dest, dp, c); |
292 } else if (!iswordcharacter(c)) { |
276 } |
293 /* interpret word int_t */ |
|
294 if (wp > 0 && wp < WORDBUF_SIZE) { |
|
295 int closespan = 1; |
|
296 if (iskeyword(word, highlighter->keywords)) { |
|
297 memcpy(&(dest[dp]), |
|
298 "<span class=\"c2html-keyword\">", 29); |
|
299 dp += 29; |
|
300 } else if (highlighter->istype(word, wp)) { |
|
301 memcpy(&(dest[dp]), |
|
302 "<span class=\"c2html-type\">", 26); |
|
303 dp += 26; |
|
304 } else if (highlighter->isdirective(word)) { |
|
305 isinclude = !strncmp( |
|
306 "#include", word, WORDBUF_SIZE); |
|
307 memcpy(&(dest[dp]), |
|
308 "<span class=\"c2html-directive\">", 31); |
|
309 dp += 31; |
|
310 } else if (iscapsonly(word, wp)) { |
|
311 memcpy(&(dest[dp]), |
|
312 "<span class=\"c2html-macroconst\">", 32); |
|
313 dp += 32; |
|
314 } else { |
|
315 closespan = 0; |
|
316 } |
|
317 for (int i = 0 ; i < wp ; i++) { |
|
318 dp = writeescapedchar(dest, dp, word[i]); |
|
319 } |
|
320 if (closespan) { |
|
321 memcpy(&(dest[dp]), "</span>", 7); |
|
322 dp += 7; |
|
323 } |
|
324 } |
|
325 memset(word, 0, WORDBUF_SIZE); |
|
326 wp = 0; |
|
327 dp = writeescapedchar(dest, dp, c); |
|
328 } else { |
|
329 /* read word */ |
|
330 if (wp < WORDBUF_SIZE) { |
|
331 word[wp++] = c; |
|
332 } else if (wp == WORDBUF_SIZE) { |
|
333 for (int i = 0 ; i < WORDBUF_SIZE ; i++) { |
|
334 dp = writeescapedchar(dest, dp, word[i]); |
|
335 } |
|
336 wp++; |
|
337 dp = writeescapedchar(dest, dp, c); |
|
338 } else { |
|
339 dp = writeescapedchar(dest, dp, c); |
|
340 } |
|
341 } |
|
342 } |
|
343 |
|
344 isescaping = !isescaping & (c == '\\'); |
|
345 } |
|
346 } |
|
347 dest[dp] = 0; |
|
348 } |
|
349 |
|
350 void printhelp() { |
|
351 printf("Formats source code using HTML.\n\nUsage:\n" |
|
352 " c2html [Options] FILE\n\n" |
|
353 " Options:\n" |
|
354 " -h Prints this help message\n" |
|
355 " -j Highlight Java instead of C source code\n" |
|
356 " -o <output> Output file (stdout, if not specified)\n" |
|
357 " -p Disable highlighting (plain text)\n" |
|
358 "\n"); |
|
359 |
|
360 |
|
361 } |
|
362 |
|
363 int lnint(size_t lnc) { |
|
364 int w = 1, p = 1; |
|
365 while ((p*=10) < lnc) w++; |
|
366 return w; |
|
367 } |
|
368 |
|
369 int main(int argc, char** argv) { |
|
370 |
|
371 settings_t settings; |
|
372 settings.outfilename = NULL; |
|
373 settings.highlight = 1; |
|
374 |
|
375 highlighter_t highlighter; |
|
376 highlighter.isdirective = iscdirective; |
|
377 highlighter.istype = isctype; |
|
378 highlighter.keywords = ckeywords; |
|
379 |
|
380 char optc; |
|
381 while ((optc = getopt(argc, argv, "hjo:p")) != -1) { |
|
382 switch (optc) { |
|
383 case 'o': |
|
384 if (!(optarg[0] == '-' && optarg[1] == 0)) { |
|
385 settings.outfilename = optarg; |
|
386 } |
|
387 break; |
|
388 case 'j': |
|
389 highlighter.isdirective = isjdirective; |
|
390 highlighter.istype = isjtype; |
|
391 highlighter.keywords = jkeywords; |
|
392 break; |
|
393 case 'p': |
|
394 settings.highlight = 0; |
|
395 break; |
|
396 case 'h': |
|
397 printhelp(); |
|
398 return 0; |
|
399 default: |
|
400 return 1; |
|
401 } |
|
402 } |
|
403 |
|
404 if (optind != argc-1) { |
|
405 printhelp(); |
|
406 return 1; |
277 } else { |
407 } else { |
278 /* strings */ |
408 settings.infilename = argv[optind]; |
279 if (!isescaping && (c == '\'' || c == '\"')) { |
409 |
280 isstring ^= 1; |
410 inputfile_t *inputfile = readinput(settings.infilename); |
281 if (isstring) { |
411 if (inputfile) { |
282 memcpy(&(dest[dp]), "<span class=\"c2html-string\">", 28); |
412 FILE *fout; |
283 dp += 28; |
413 char *line; |
284 dp = writeescapedchar(dest, dp, c); |
414 if (settings.highlight) { |
285 } else { |
415 line = (char*) malloc(inputfile->maxlinewidth*64); |
286 dp = writeescapedchar(dest, dp, c); |
|
287 memcpy(&(dest[dp]), "</span>", 7); |
|
288 dp += 7; |
|
289 } |
|
290 } else { |
|
291 if (isstring) { |
|
292 dp = writeescapedchar(dest, dp, c); |
|
293 } else if (!iswordcharacter(c)) { |
|
294 /* interpret word int_t */ |
|
295 if (wp > 0 && wp < WORDBUF_SIZE) { |
|
296 int closespan = 1; |
|
297 if (iskeyword(word, highlighter->keywords)) { |
|
298 memcpy(&(dest[dp]), "<span class=\"c2html-keyword\">", 29); |
|
299 dp += 29; |
|
300 } else if (highlighter->istype(word, wp)) { |
|
301 memcpy(&(dest[dp]), "<span class=\"c2html-type\">", 26); |
|
302 dp += 26; |
|
303 } else if (highlighter->isdirective(word)) { |
|
304 isinclude = !strncmp("#include", word, WORDBUF_SIZE); |
|
305 memcpy(&(dest[dp]), "<span class=\"c2html-directive\">", 31); |
|
306 dp += 31; |
|
307 } else if (iscapsonly(word, wp)) { |
|
308 memcpy(&(dest[dp]), "<span class=\"c2html-macroconst\">", 32); |
|
309 dp += 32; |
|
310 } else { |
416 } else { |
311 closespan = 0; |
417 line = NULL; |
312 } |
418 } |
313 for (int i = 0 ; i < wp ; i++) { |
419 if (settings.outfilename) { |
314 dp = writeescapedchar(dest, dp, word[i]); |
420 fout = fopen(settings.outfilename, "w"); |
315 } |
421 } else { |
316 if (closespan) { |
422 fout = stdout; |
317 memcpy(&(dest[dp]), "</span>", 7); |
423 } |
318 dp += 7; |
424 fprintf(fout, "<pre>\n"); |
319 } |
425 int lnw = lnint(inputfile->count); |
320 } |
426 for (int i = 0 ; i < inputfile->count ; i++) { |
321 memset(word, 0, WORDBUF_SIZE); |
427 if (settings.highlight) { |
322 wp = 0; |
428 parseline(inputfile->lines[i], line, &highlighter); |
323 dp = writeescapedchar(dest, dp, c); |
429 } else { |
324 } else { |
430 line = inputfile->lines[i]; |
325 /* read word */ |
431 } |
326 if (wp < WORDBUF_SIZE) { |
432 fprintf(fout, "<span class=\"c2html-lineno\">%*d:</span> %s", |
327 word[wp++] = c; |
433 lnw, i+1, line); |
328 } else if (wp == WORDBUF_SIZE) { |
434 } |
329 for (int i = 0 ; i < WORDBUF_SIZE ; i++) { |
435 if (settings.highlight) { |
330 dp = writeescapedchar(dest, dp, word[i]); |
436 free(line); |
331 } |
437 } |
332 wp++; |
438 fprintf(fout, "</pre>\n"); |
333 dp = writeescapedchar(dest, dp, c); |
439 |
334 } else { |
440 if (fout != stdout) { |
335 dp = writeescapedchar(dest, dp, c); |
441 fclose(fout); |
336 } |
442 } |
337 } |
443 |
338 } |
444 freeinputfilebuffer(inputfile); |
339 |
445 } |
340 isescaping = !isescaping & (c == '\\'); |
446 |
341 } |
|
342 } |
|
343 dest[dp] = 0; |
|
344 } |
|
345 |
|
346 void printhelp() { |
|
347 printf("Formats source code using HTML.\n\nUsage:\n" |
|
348 " c2html [Options] FILE\n\n" |
|
349 " Options:\n" |
|
350 " -h Prints this help message\n" |
|
351 " -j Highlight Java instead of C source code\n" |
|
352 " -o <output> Output file (if not specified, stdout is used)\n" |
|
353 " -p Disable highlighting (plain text)\n" |
|
354 "\n"); |
|
355 |
|
356 |
|
357 } |
|
358 |
|
359 int lnint(size_t lnc) { |
|
360 int w = 1, p = 1; |
|
361 while ((p*=10) < lnc) w++; |
|
362 return w; |
|
363 } |
|
364 |
|
365 int main(int argc, char** argv) { |
|
366 |
|
367 settings_t settings; |
|
368 settings.outfilename = NULL; |
|
369 settings.highlight = 1; |
|
370 |
|
371 highlighter_t highlighter; |
|
372 highlighter.isdirective = iscdirective; |
|
373 highlighter.istype = isctype; |
|
374 highlighter.keywords = ckeywords; |
|
375 |
|
376 char optc; |
|
377 while ((optc = getopt(argc, argv, "hjo:p")) != -1) { |
|
378 switch (optc) { |
|
379 case 'o': |
|
380 if (!(optarg[0] == '-' && optarg[1] == 0)) { |
|
381 settings.outfilename = optarg; |
|
382 } |
|
383 break; |
|
384 case 'j': |
|
385 highlighter.isdirective = isjdirective; |
|
386 highlighter.istype = isjtype; |
|
387 highlighter.keywords = jkeywords; |
|
388 break; |
|
389 case 'p': |
|
390 settings.highlight = 0; |
|
391 break; |
|
392 case 'h': |
|
393 printhelp(); |
|
394 return 0; |
447 return 0; |
395 default: |
448 } |
396 return 1; |
449 } |
397 } |
450 |
398 } |
|
399 |
|
400 if (optind != argc-1) { |
|
401 printhelp(); |
|
402 return 1; |
|
403 } else { |
|
404 settings.infilename = argv[optind]; |
|
405 |
|
406 inputfile_t *inputfile = readinput(settings.infilename); |
|
407 if (inputfile) { |
|
408 FILE *fout; |
|
409 char *line; |
|
410 if (settings.highlight) { |
|
411 line = (char*) malloc(inputfile->maxlinewidth*64); |
|
412 } else { |
|
413 line = NULL; |
|
414 } |
|
415 if (settings.outfilename) { |
|
416 fout = fopen(settings.outfilename, "w"); |
|
417 } else { |
|
418 fout = stdout; |
|
419 } |
|
420 fprintf(fout, "<pre>\n"); |
|
421 int lnw = lnint(inputfile->count); |
|
422 for (int i = 0 ; i < inputfile->count ; i++) { |
|
423 if (settings.highlight) { |
|
424 parseline(inputfile->lines[i], line, &highlighter); |
|
425 } else { |
|
426 line = inputfile->lines[i]; |
|
427 } |
|
428 fprintf(fout, "<span class=\"c2html-lineno\">%*d:</span> %s", |
|
429 lnw, i+1, line); |
|
430 } |
|
431 if (settings.highlight) { |
|
432 free(line); |
|
433 } |
|
434 fprintf(fout, "</pre>\n"); |
|
435 |
|
436 if (fout != stdout) { |
|
437 fclose(fout); |
|
438 } |
|
439 |
|
440 freeinputfilebuffer(inputfile); |
|
441 } |
|
442 |
|
443 return 0; |
|
444 } |
|
445 } |
|
446 |
|