26 * POSSIBILITY OF SUCH DAMAGE. |
26 * POSSIBILITY OF SUCH DAMAGE. |
27 * |
27 * |
28 */ |
28 */ |
29 #include "c2html.h" |
29 #include "c2html.h" |
30 |
30 |
31 inputfile_t *inputfilebuffer(size_t capacity) { |
31 #include "ucx/buffer.h" |
32 inputfile_t *inputfile = (inputfile_t*) malloc(sizeof(inputfile_t)); |
32 #include "ucx/list.h" |
33 inputfile->lines = (char**) malloc(capacity * sizeof(char*)); |
33 #include "ucx/utils.h" |
34 inputfile->capacity = capacity; |
|
35 inputfile->count = 0; |
|
36 inputfile->maxlinewidth = 0; |
|
37 |
|
38 return inputfile; |
|
39 } |
|
40 |
|
41 void addline(inputfile_t *inputfile, char* line, size_t width) { |
|
42 char *l = (char*) malloc(width+1); |
|
43 memcpy(l, line, width); |
|
44 l[width] = 0; |
|
45 if (inputfile->count >= inputfile->capacity) { |
|
46 inputfile->capacity <<= 1; |
|
47 inputfile->lines = realloc(inputfile->lines, |
|
48 sizeof(char*)*inputfile->capacity); |
|
49 } |
|
50 inputfile->lines[inputfile->count] = l; |
|
51 inputfile->maxlinewidth = |
|
52 width > inputfile->maxlinewidth ? width : inputfile->maxlinewidth; |
|
53 inputfile->count++; |
|
54 } |
|
55 |
|
56 void freeinputfilebuffer(inputfile_t *inputfile) { |
|
57 for (int i = 0 ; i < inputfile->count ; i++) { |
|
58 free(inputfile->lines[i]); |
|
59 } |
|
60 free(inputfile->lines); |
|
61 free(inputfile); |
|
62 } |
|
63 |
|
64 inputfile_t *readinput(char *filename) { |
|
65 |
|
66 int fd = open(filename, O_RDONLY); |
|
67 if (fd == -1) return NULL; |
|
68 |
|
69 inputfile_t *inputfile = inputfilebuffer(512); |
|
70 |
|
71 char buf[INPUTBUF_SIZE]; |
|
72 ssize_t r; |
|
73 |
|
74 size_t maxlinewidth = 256; |
|
75 char *line = (char*) malloc(maxlinewidth); |
|
76 size_t col = 0; |
|
77 |
|
78 while ((r = read(fd, buf, INPUTBUF_SIZE)) > 0) { |
|
79 for (size_t i = 0 ; i < r ; i++) { |
|
80 if (col >= maxlinewidth-4) { |
|
81 maxlinewidth <<= 1; |
|
82 line = realloc(line, maxlinewidth); |
|
83 } |
|
84 |
|
85 if (buf[i] == '\n') { |
|
86 line[col++] = '\n'; |
|
87 line[col] = 0; |
|
88 addline(inputfile, line, col); |
|
89 col = 0; |
|
90 } else { |
|
91 line[col++] = buf[i]; |
|
92 } |
|
93 } |
|
94 } |
|
95 |
|
96 free(line); |
|
97 |
|
98 close(fd); |
|
99 |
|
100 return inputfile; |
|
101 } |
|
102 |
34 |
103 void printhelp() { |
35 void printhelp() { |
104 printf("Formats source code using HTML.\n\nUsage:\n" |
36 printf("Formats source code using HTML.\n\nUsage:\n" |
105 " c2html [Options] FILE\n\n" |
37 " c2html [Options] FILE\n\n" |
106 " Options:\n" |
38 " Options:\n" |
134 fwrite(buf, 1, r, dest); |
60 fwrite(buf, 1, r, dest); |
135 } |
61 } |
136 fclose(src); |
62 fclose(src); |
137 return 0; |
63 return 0; |
138 } else { |
64 } else { |
139 return -1; |
65 return 1; |
140 } |
66 } |
141 } |
67 } |
142 |
68 |
143 #define WRITECONST(stream, out, cstr) out(cstr, 1, sizeof(cstr)-1, stream) |
69 #define WRITECONST(stream, out, cstr) out(cstr, 1, sizeof(cstr)-1, stream) |
144 int formatfile( |
70 int formatfile( |
145 highlighter_t *highlighter, |
71 highlighter_t *highlighter, |
146 inputfile_t *in, |
72 UcxList *in, |
147 fmt_write_func out, |
73 write_func out, |
148 void *stream, |
74 void *stream, |
149 _Bool showln) { |
75 int showlineno) { |
150 // formats an input file and writes the result to out |
76 size_t lines = ucx_list_size(in); |
151 |
77 |
152 char *line = malloc(in->maxlinewidth*64); |
78 UcxBuffer *line = ucx_buffer_new(NULL, 1024, UCX_BUFFER_AUTOEXTEND); |
153 if(!line) { |
79 if(!line) { |
154 return 1; |
80 return 1; |
155 } |
81 } |
156 WRITECONST(stream, out, "<pre>\n"); |
82 WRITECONST(stream, out, "<pre>\n"); |
157 |
83 |
158 int lnw = lnint(in->count); |
84 int lnw; |
159 for (int i = 0 ; i < in->count ; i++) { |
85 { |
|
86 lnw = 1; |
|
87 int p = 1; |
|
88 while ((p*=10) < lines) lnw++; |
|
89 } |
|
90 |
|
91 size_t lineno = 0; |
|
92 UCX_FOREACH(sourceline, in) { |
|
93 lineno++; |
|
94 /* TODO: backwards compatibility: replace line->space in all occasions |
|
95 * and use UcxBuffer functions |
|
96 */ |
160 if (highlighter) { |
97 if (highlighter) { |
161 highlighter->parser(in->lines[i], line, highlighter); |
98 highlighter->parser(sourceline->data, line->space, highlighter); |
162 } else { |
99 } else { |
163 char *c = in->lines[i]; |
100 char *c = sourceline->data; |
164 size_t dp = 0; |
101 size_t dp = 0; |
165 while (*c) { |
102 while (*c) { |
166 dp = writeescapedchar(line, dp, *c); |
103 dp = writeescapedchar(line->space, dp, *c); |
167 c++; |
104 c++; |
168 } |
105 } |
169 line[dp] = '\0'; |
106 line->space[dp] = '\0'; |
170 } |
107 } |
171 |
108 |
172 // write line number |
109 // write line number |
173 if (showln) { |
110 if (showlineno) { |
174 WRITECONST(stream, out, "<span class=\"c2html-lineno\">"); |
111 WRITECONST(stream, out, "<span class=\"c2html-lineno\">"); |
175 char lnbuf[128]; |
112 char lnbuf[128]; |
176 int len; |
113 int len; |
177 // line number link |
114 // line number link |
178 len = snprintf(lnbuf, 128, "<a name=\"l%d\" href=\"#l%d\">", |
115 len = snprintf(lnbuf, 128, "<a name=\"l%d\" href=\"#l%d\">", |
179 i+1, i+1); |
116 lineno, lineno); |
180 out(lnbuf, 1, len, stream); |
117 out(lnbuf, 1, len, stream); |
181 // justified line number |
118 // justified line number |
182 len = snprintf(lnbuf, 128, "%*d ", lnw, i+1); |
119 len = snprintf(lnbuf, 128, "%*d ", lnw, lineno); |
183 out(lnbuf, 1, len, stream); |
120 out(lnbuf, 1, len, stream); |
184 WRITECONST(stream, out, "</a></span> "); |
121 WRITECONST(stream, out, "</a></span> "); |
185 } |
122 } |
186 |
123 |
187 // write formated (or plain) code line |
124 // write formated (or plain) code line |
188 out(line, 1, strlen(line), stream); |
125 out(line->space, 1, strlen(line->space), stream); |
189 } |
126 } |
190 |
127 |
191 WRITECONST(stream, out, "</pre>\n"); |
128 WRITECONST(stream, out, "</pre>\n"); |
192 free(line); |
129 ucx_buffer_free(line); |
193 return 0; |
130 return 0; |
194 } |
131 } |
195 |
132 |
196 void init_c_highlighter(highlighter_t *highlighter) { |
133 void init_c_highlighter(highlighter_t *highlighter) { |
197 memset(highlighter, 0, sizeof(highlighter_t)); |
134 memset(highlighter, 0, sizeof(highlighter_t)); |
207 highlighter->istype = check_jtype; |
144 highlighter->istype = check_jtype; |
208 highlighter->keywords = jkeywords; |
145 highlighter->keywords = jkeywords; |
209 highlighter->parser = jparseline; |
146 highlighter->parser = jparseline; |
210 } |
147 } |
211 |
148 |
|
149 enum source_type { |
|
150 SOURCE_C, |
|
151 SOURCE_JAVA, |
|
152 SOURCE_PLAIN |
|
153 }; |
|
154 |
212 int main(int argc, char** argv) { |
155 int main(int argc, char** argv) { |
213 int retcode = EXIT_SUCCESS; |
156 int retcode = EXIT_SUCCESS; |
214 |
157 |
215 settings_t settings; |
158 Settings settings; |
216 memset(&settings, 0, sizeof(settings)); |
159 memset(&settings, 0, sizeof(settings)); |
217 settings.highlight = 1; |
|
218 settings.showlinenumbers = 1; |
160 settings.showlinenumbers = 1; |
219 |
161 |
220 int lang = C2HTML_C; |
162 enum source_type sourcetype = SOURCE_C; |
221 |
163 |
222 char optc; |
164 char optc; |
223 while ((optc = getopt(argc, argv, "hljo:pH:F:vV")) != -1) { |
165 while ((optc = getopt(argc, argv, "hljo:pH:F:vV")) != -1) { |
224 switch (optc) { |
166 switch (optc) { |
225 case 'o': |
167 case 'o': |
280 goto prog_end; |
222 goto prog_end; |
281 } |
223 } |
282 |
224 |
283 highlighter_t highlighter; |
225 highlighter_t highlighter; |
284 highlighter_t *hptr = &highlighter; |
226 highlighter_t *hptr = &highlighter; |
285 switch (lang) { |
227 switch (sourcetype) { |
286 case C2HTML_C: |
228 case SOURCE_C: |
287 init_c_highlighter(&highlighter); |
229 init_c_highlighter(&highlighter); |
288 break; |
230 break; |
289 case C2HTML_JAVA: |
231 case SOURCE_JAVA: |
290 init_java_highlighter(&highlighter); |
232 init_java_highlighter(&highlighter); |
291 break; |
233 break; |
292 default: |
234 case SOURCE_PLAIN: |
293 hptr = NULL; |
235 hptr = NULL; |
294 break; |
236 break; |
295 } |
237 default: /* should be unreachable */ |
296 if (!settings.highlight) { |
238 fprintf(stderr, "error in enum source_type\n"); |
297 hptr = NULL; |
239 retcode = EXIT_FAILURE; |
298 } |
240 goto prog_end; |
299 |
241 } |
300 inputfile_t *inputfile = readinput(settings.infilename); |
242 |
|
243 FILE *inputfile = fopen(settings.infilename, "r"); |
301 if (inputfile) { |
244 if (inputfile) { |
|
245 UcxBuffer *filebuf = ucx_buffer_new(NULL, |
|
246 2048, UCX_BUFFER_AUTOEXTEND); |
|
247 { |
|
248 const size_t tmpbufsize = 512; |
|
249 char *tmpbuf = malloc(tmpbufsize); |
|
250 ucx_stream_copy(inputfile, filebuf, (read_func) fread, |
|
251 (write_func) ucx_buffer_write, |
|
252 tmpbuf, tmpbufsize, (size_t)-1); |
|
253 free(tmpbuf); |
|
254 } |
|
255 fclose(inputfile); |
|
256 |
|
257 UcxList *inputlines = ucx_list_append(NULL, filebuf->space); |
|
258 for (size_t i = 1 ; i < filebuf->size ; i++) { |
|
259 if (filebuf->space[i] == '\r') { |
|
260 filebuf->space[i] = '\n'; i++; |
|
261 } |
|
262 if (filebuf->space[i] == '\n' && i+1 < filebuf->size) { |
|
263 ucx_list_append(inputlines, filebuf->space+i+1); |
|
264 } |
|
265 } |
|
266 |
302 formatfile( |
267 formatfile( |
303 hptr, |
268 hptr, |
304 inputfile, |
269 inputlines, |
305 (fmt_write_func)fwrite, |
270 (write_func) fwrite, |
306 fout, |
271 fout, |
307 settings.showlinenumbers); |
272 settings.showlinenumbers); |
308 freeinputfilebuffer(inputfile); |
273 ucx_buffer_free(filebuf); |
309 } else { |
274 } else { |
310 perror("Error opening input file"); |
275 perror("Error opening input file"); |
311 retcode = EXIT_FAILURE; |
276 retcode = EXIT_FAILURE; |
312 } |
277 } |
313 |
278 |