1 /* quick and dirty copy of the
2 * highlight (http://freshmeat.net/projects/highlight/) command */
3 #include "ex_utils.h"
4
5 #include <sys/time.h>
6 #include <time.h>
7
8 static struct
9 {
10 const char *name;
11 const char *seq;
12 size_t off;
13 size_t eoff;
14 size_t len;
15 } ex_hl_seqs[] =
16 /* This assumes a certain style...
17
18 for instance neither of...
19
20 if(foo)
21 foo;if (bar)
22
23 ...will be seen as an if statement, as there is no space before and after
24 the if. And using TABs instead of spaces will make it not work.
25 These are all features, as the style should be the same.
26 */
27 #define EX_HL_SEQ_T(x, y) \
28 x, " " y " ", 1, 1, 0 }, \
29 { x, "(" y " ", 1, 1, 0 }, \
30 { x, " " y ")", 1, 1, 0 }, \
31 { x, "(" y ")", 1, 1, 0 }, \
32 { x, "*" y " ", 1, 1, 0 }, \
33 { x, "\n" y " ", 1, 1, 0
34 #define EX_HL_SEQ_SP(x, y) \
35 x, " " y " ", 1, 1, 0
36 #define EX_HL_SEQ_WS(x, y) \
37 x, " " y " ", 1, 1, 0 }, \
38 { x, " " y "\n", 1, 1, 0
39 /* custom for default and break */
40 #define EX_HL_SEQ_DEF(x, y) \
41 x, " " y ": ", 1, 2, 0 }, \
42 { x, " " y ":\n", 1, 2, 0
43 #define EX_HL_SEQ_BRK(x, y) \
44 x, " " y ";\n", 1, 2, 0
45 #define EX_HL_SEQ_SB(x, y) \
46 x, " " y " (", 1, 2, 0
47 #define EX_HL_SEQ_RET(x, y) \
48 x, " " y " (", 1, 2, 0 }, \
49 { x, " " y ";\n", 1, 2, 0
50 #define EX_HL_SEQ_B(x, y) \
51 x, " " y "(", 1, 1, 0
52 #define EX_HL_SEQ_VAL(x, y) \
53 x, " " y " ", 1, 1, 0 }, \
54 { x, " " y "\n", 1, 1, 0 }, \
55 { x, " " y ";", 1, 1, 0 }, \
56 { x, " " y ",", 1, 1, 0 }, \
57 { x, " " y ")", 1, 1, 0 }, \
58 { x, "(" y " ", 1, 1, 0 }, \
59 { x, "(" y ")", 1, 1, 0 }, \
60 { x, "(" y ",", 1, 1, 0
61 #define EX_HL_SEQ_CPP(x, y) \
62 x, "#" y " ", 1, 1, 0 }, \
63 { x, "#" y "\n", 1, 1, 0 }, \
64 { x, "# " y " ", 2, 1, 0 }, \
65 { x, "# " y "\n", 2, 1, 0 }, \
66 { x, "# " y " ", 3, 1, 0 }, \
67 { x, "# " y "\n", 3, 1, 0 }, \
68 { x, "# " y " ", 4, 1, 0 }, \
69 { x, "# " y "\n", 4, 1, 0 }, \
70 { x, "# " y " ", 5, 1, 0 }, \
71 { x, "# " y "\n", 5, 1, 0
72 {
73 /* order matters */
74 { EX_HL_SEQ_T("vstrbase", "Vstr_base") },
75 { EX_HL_SEQ_T("vstrsects", "Vstr_sects") },
76 { EX_HL_SEQ_T("vstrfmt", "Vstr_fmt_spec") },
77 { EX_HL_SEQ_T("pollfd", "struct pollfd") },
78 { EX_HL_SEQ_T("mpzt", "mpz_t") },
79
80 { EX_HL_SEQ_CPP("cppif", "if") },
81 { EX_HL_SEQ_CPP("cppifndef", "ifndef") },
82 { EX_HL_SEQ_CPP("cppifdef", "ifdef") },
83 { EX_HL_SEQ_CPP("cppelse", "else") },
84 { EX_HL_SEQ_CPP("cppendif", "endif") },
85 { EX_HL_SEQ_CPP("cppdefine", "define") },
86 { EX_HL_SEQ_CPP("cppinclude", "include") },
87 { EX_HL_SEQ_CPP("cppelif", "elif") },
88 { EX_HL_SEQ_SB("cppdefined", "defined") },
89 { EX_HL_SEQ_B("cppdefined", "defined") },
90
91 { EX_HL_SEQ_SB("if", "if") },
92 { EX_HL_SEQ_WS("else", "else") },
93 { EX_HL_SEQ_WS("do", "do") },
94 { EX_HL_SEQ_SB("while", "while") },
95 { EX_HL_SEQ_SB("for", "for") },
96 { EX_HL_SEQ_RET("return", "return") },
97 { EX_HL_SEQ_SB("switch", "switch") },
98 { EX_HL_SEQ_SP("case", "case") },
99 { EX_HL_SEQ_DEF("default", "default") },
100 { EX_HL_SEQ_BRK("break", "break") },
101 { EX_HL_SEQ_SP("goto", "goto") },
102 { EX_HL_SEQ_T("extern", "extern") },
103 { EX_HL_SEQ_T("static", "static") },
104 { EX_HL_SEQ_T("const", "const") },
105 { EX_HL_SEQ_T("restrict", "restrict") },
106 { EX_HL_SEQ_T("inline", "inline") },
107 { EX_HL_SEQ_T("void", "void") },
108 { EX_HL_SEQ_T("unsigned", "unsigned") },
109 { EX_HL_SEQ_T("char", "char") },
110 { EX_HL_SEQ_T("short", "short") },
111 { EX_HL_SEQ_T("int", "int") },
112 { EX_HL_SEQ_T("long", "long") },
113 { EX_HL_SEQ_T("float", "float") },
114 { EX_HL_SEQ_T("double", "double") },
115 { EX_HL_SEQ_T("ssizet", "ssize_t") },
116 { EX_HL_SEQ_T("sizet", "size_t") },
117 { EX_HL_SEQ_T("offt", "off_t") },
118 { EX_HL_SEQ_T("off64t", "off64_t") },
119 { EX_HL_SEQ_T("intmaxt", "intmax_t") },
120 { EX_HL_SEQ_T("uintmaxt", "uintmax_t") },
121
122 { EX_HL_SEQ_SB("exit", "exit") },
123 { EX_HL_SEQ_SB("abort", "abort") },
124 { EX_HL_SEQ_B("err", "err") },
125 { EX_HL_SEQ_B("err", "errx") },
126 { EX_HL_SEQ_B("warn", "warn") },
127 { EX_HL_SEQ_B("warn", "warnx") },
128 { EX_HL_SEQ_B("assert", "assert") },
129 { EX_HL_SEQ_B("assert", "ASSERT") },
130 { EX_HL_SEQ_B("assert", "assert_ret") },
131 { EX_HL_SEQ_B("assert", "ASSERT_RET") },
132 { EX_HL_SEQ_B("assert", "assert_ret_void") },
133 { EX_HL_SEQ_B("assert", "ASSERT_RET_VOID") },
134 { EX_HL_SEQ_B("assert", "assert_no_switch_def") },
135 { EX_HL_SEQ_B("assert", "ASSERT_NO_SWITCH_DEF") },
136
137 { EX_HL_SEQ_VAL("compdate", "__DATE__") },
138 { EX_HL_SEQ_VAL("compversion", "__VERSION__") },
139 { EX_HL_SEQ_VAL("compfile", "__FILE__") },
140 { EX_HL_SEQ_VAL("compline", "__LINE__") },
141 { EX_HL_SEQ_VAL("charbit", "CHAR_BIT") },
142 { EX_HL_SEQ_VAL("intmax", "INT_MAX") },
143 { EX_HL_SEQ_VAL("intmin", "INT_MIN") },
144 { EX_HL_SEQ_VAL("intjmax", "INTMAX_MAX") },
145 { EX_HL_SEQ_VAL("intjmin", "INTMAX_MIN") },
146 { EX_HL_SEQ_VAL("stdin", "stdin") },
147 { EX_HL_SEQ_VAL("stdout", "stdout") },
148 { EX_HL_SEQ_VAL("stderr", "stderr") },
149 { EX_HL_SEQ_VAL("stdin", "STDIN_FILENO") },
150 { EX_HL_SEQ_VAL("stdout", "STDOUT_FILENO") },
151 { EX_HL_SEQ_VAL("stderr", "STDERR_FILENO") },
152 { EX_HL_SEQ_VAL("errno", "errno") },
153 { EX_HL_SEQ_VAL("exitsucs", "EXIT_SUCCESS") },
154 { EX_HL_SEQ_VAL("exitfail", "EXIT_FAILURE") },
155 { EX_HL_SEQ_VAL("true", "TRUE") },
156 { EX_HL_SEQ_VAL("false", "FALSE") },
157 { EX_HL_SEQ_VAL("null", "NULL") },
158 { EX_HL_SEQ_VAL("num0", "0") },
159 { EX_HL_SEQ_VAL("numm1", "-1") },
160
161 {NULL, NULL, 0, 0, 0},
162 };
163 static size_t ex_hl_max_seq_len = 0;
164
165 #define C_DEF 0
166 #define C_SEQ 1
167 #define C_STR 2
168 #define C_CHR 3
169 #define C_CMO 4
170 #define C_CMN 5
171
ex_hl_mov_clean(Vstr_base * s1,Vstr_base * s2,size_t len)172 static void ex_hl_mov_clean(Vstr_base *s1, Vstr_base *s2, size_t len)
173 { /* html the elements... */
174 while (len > 0)
175 {
176 size_t count = vstr_cspn_cstr_chrs_fwd(s2, 1, len, "&<>");
177
178 vstr_add_vstr(s1, s1->len, s2, 1, count, VSTR_TYPE_ADD_BUF_REF);
179 vstr_del(s2, 1, count);
180 len -= count;
181
182 if (count)
183 continue;
184
185 --len;
186
187 switch (vstr_export_chr(s2, 1))
188 {
189 case '<': /* html stuff ... */
190 vstr_add_cstr_ptr(s1, s1->len, "<");
191 vstr_del(s2, 1, 1);
192 continue;
193
194 case '>':
195 vstr_add_cstr_ptr(s1, s1->len, ">");
196 vstr_del(s2, 1, 1);
197 continue;
198
199 case '&':
200 vstr_add_cstr_ptr(s1, s1->len, "&");
201 vstr_del(s2, 1, 1);
202 continue;
203
204 default:
205 ASSERT(FALSE);
206 break;
207 }
208 }
209 }
210
211 static int first_time = FALSE;
212
ex_hl_process(Vstr_base * s1,Vstr_base * s2,int last)213 static int ex_hl_process(Vstr_base *s1, Vstr_base *s2, int last)
214 {
215 static unsigned int state = C_DEF;
216
217 /* we don't want to create more data, if we are over our limit */
218 if (s1->len > EX_MAX_W_DATA_INCORE)
219 return (FALSE);
220
221 if (s2->len < ex_hl_max_seq_len)
222 {
223 if (!s2->len || !last)
224 return (FALSE);
225 }
226
227 while (((s2->len >= ex_hl_max_seq_len) || (s2->len && last)) &&
228 (s1->len <= EX_MAX_W_DATA_INCORE))
229 {
230 size_t len = 0;
231
232 switch (state)
233 {
234 case C_DEF:
235 /* this is pretty intimately tied with the array above */
236 len = vstr_cspn_cstr_chrs_fwd(s2, 1, s2->len, "# \n(*\"'/&<>");
237 vstr_add_vstr(s1, s1->len, s2, 1, len, VSTR_TYPE_ADD_BUF_REF);
238 vstr_del(s2, 1, len);
239 state = C_SEQ;
240 break;
241
242 case C_SEQ:
243 {
244 unsigned int scan = 0;
245 const char *seq = NULL;
246
247 switch (vstr_export_chr(s2, 1))
248 {
249 case '\'':
250 state = C_CHR;
251 vstr_add_cstr_ptr(s1, s1->len, "<span class=\"chr\">'");
252 vstr_del(s2, 1, 1);
253 continue;
254
255 case '/':
256 if (s2->len < 2)
257 break;
258
259 if (vstr_cmp_cstr_eq(s2, 1, 2, "/*"))
260 {
261 state = C_CMO;
262 vstr_add_cstr_ptr(s1, s1->len, "<span class=\"comment\">/*");
263 vstr_del(s2, 1, 2);
264 continue;
265 }
266 if (vstr_cmp_cstr_eq(s2, 1, 2, "//"))
267 {
268 state = C_CMN;
269 vstr_add_cstr_ptr(s1, s1->len, "<span class=\"comment\">//");
270 vstr_del(s2, 1, 2);
271 continue;
272 }
273 break;
274
275 case '"':
276 state = C_STR;
277 vstr_add_cstr_ptr(s1, s1->len, "<span class=\"str\">\"");
278 vstr_del(s2, 1, 1);
279 continue;
280
281 case '<': /* html stuff ... */
282 vstr_add_cstr_ptr(s1, s1->len, "<");
283 vstr_del(s2, 1, 1);
284 continue;
285
286 case '>':
287 vstr_add_cstr_ptr(s1, s1->len, ">");
288 vstr_del(s2, 1, 1);
289 continue;
290
291 case '&':
292 vstr_add_cstr_ptr(s1, s1->len, "&");
293 vstr_del(s2, 1, 1);
294 continue;
295
296 default:
297 break;
298 }
299
300 while (ex_hl_seqs[scan].name)
301 {
302 seq = ex_hl_seqs[scan].seq;
303 len = ex_hl_seqs[scan].len;
304
305 if ((len <= s2->len) && vstr_cmp_buf_eq(s2, 1, len, seq, len))
306 {
307 size_t off = ex_hl_seqs[scan].off;
308 size_t eoff = ex_hl_seqs[scan].eoff;
309 unsigned int mid = len - (off + eoff);
310
311 if (first_time)
312 {
313 ASSERT(off && (vstr_export_chr(s2, 1) == '\n'));
314 vstr_del(s2, 1, 1);
315 --off;
316 first_time = FALSE;
317 }
318
319 vstr_add_vstr(s1, s1->len, s2, 1, off, VSTR_TYPE_ADD_BUF_REF);
320 vstr_del(s2, 1, off);
321
322 vstr_add_cstr_ptr(s1, s1->len, "<span class=\"");
323 vstr_add_cstr_ptr(s1, s1->len, ex_hl_seqs[scan].name);
324 vstr_add_cstr_ptr(s1, s1->len, "\">");
325
326 vstr_add_vstr(s1, s1->len, s2, 1, mid, VSTR_TYPE_ADD_BUF_REF);
327 vstr_del(s2, 1, mid);
328
329 vstr_add_cstr_ptr(s1, s1->len, "</span>");
330 /* don't output end marker */
331 break;
332 }
333
334 ++scan;
335 }
336
337 if (!ex_hl_seqs[scan].name)
338 {
339 if (first_time)
340 {
341 ASSERT(vstr_export_chr(s2, 1) == '\n');
342 first_time = FALSE;
343 }
344 else
345 vstr_add_vstr(s1, s1->len, s2, 1, 1, VSTR_TYPE_ADD_BUF_REF);
346 vstr_del(s2, 1, 1);
347 }
348
349 state = C_DEF;
350 }
351 break;
352
353 case C_CMO:
354 len = vstr_srch_cstr_buf_fwd(s2, 1, s2->len, "*/");
355 if (!len)
356 {
357 ex_hl_mov_clean(s1, s2, s2->len);
358 return (TRUE);
359 }
360
361 ++len; /* move to last character */
362
363 state = C_DEF;
364 ex_hl_mov_clean(s1, s2, len);
365 vstr_add_cstr_ptr(s1, s1->len, "</span>");
366 break;
367
368 case C_CMN:
369 len = vstr_srch_chr_fwd(s2, 1, s2->len, '\n');
370 if (!len)
371 {
372 ex_hl_mov_clean(s1, s2, s2->len);
373 return (TRUE);
374 }
375
376 state = C_DEF;
377 ex_hl_mov_clean(s1, s2, len);
378 vstr_add_cstr_ptr(s1, s1->len, "</span>");
379 break;
380
381 case C_CHR:
382 len = vstr_srch_cstr_buf_fwd(s2, 1, s2->len, "'");
383 if (!len)
384 {
385 ex_hl_mov_clean(s1, s2, s2->len);
386 return (TRUE);
387 }
388
389 if ((len == 1) || /* even number of \'s going backwards */
390 (!(vstr_spn_cstr_chrs_rev(s2, 1, len - 1, "\\") & 1)))
391 state = C_DEF;
392 ex_hl_mov_clean(s1, s2, len);
393 if (state == C_DEF)
394 vstr_add_cstr_ptr(s1, s1->len, "</span>");
395 break;
396
397 case C_STR:
398 len = vstr_srch_cstr_buf_fwd(s2, 1, s2->len, "\"");
399 if (!len)
400 {
401 ex_hl_mov_clean(s1, s2, s2->len);
402 return (TRUE);
403 }
404
405 if ((len == 1) || /* even number of \'s going backwards */
406 (!(vstr_spn_cstr_chrs_rev(s2, 1, len - 1, "\\") & 1)))
407 state = C_DEF;
408 ex_hl_mov_clean(s1, s2, len);
409 if (state == C_DEF)
410 vstr_add_cstr_ptr(s1, s1->len, "</span>");
411 break;
412
413
414 default:
415 ASSERT(FALSE);
416 }
417 }
418
419 return (TRUE);
420 }
421
ex_hl_process_limit(Vstr_base * s1,Vstr_base * s2,unsigned int lim)422 static void ex_hl_process_limit(Vstr_base *s1, Vstr_base *s2, unsigned int lim)
423 {
424 while (s2->len > lim)
425 {
426 int proc_data = ex_hl_process(s1, s2, !lim);
427 if (!proc_data && (io_put(s1, STDOUT_FILENO) == IO_BLOCK))
428 io_block(-1, STDOUT_FILENO);
429 }
430 }
431
ex_hl_read_fd_write_stdout(Vstr_base * s1,Vstr_base * s2,int fd)432 static void ex_hl_read_fd_write_stdout(Vstr_base *s1, Vstr_base *s2, int fd)
433 {
434 while (TRUE)
435 {
436 int io_w_state = IO_OK;
437 int io_r_state = io_get(s2, fd);
438
439 if (io_r_state == IO_EOF)
440 break;
441
442 ex_hl_process(s1, s2, FALSE);
443
444 io_w_state = io_put(s1, 1);
445
446 io_limit(io_r_state, fd, io_w_state, 1, s1);
447 }
448
449 ex_hl_process_limit(s1, s2, 0);
450 }
451
ex_hl_ctime(time_t val)452 static const char *ex_hl_ctime(time_t val)
453 {
454 static char ret[4096];
455
456 strftime(ret, sizeof(ret), "%c", localtime(&val));
457
458 return (ret);
459 }
460
base_fname(const char * s1)461 static const char *base_fname(const char *s1)
462 {
463 const char *sname = strrchr(s1, '/');
464
465 if (sname)
466 ++sname;
467 else
468 sname = s1;
469
470 return (sname);
471 }
472
ex_hl_block_beg(Vstr_base * s1,const char * block_type,const char * block_beg,const char * attr_id,const char * attr_class)473 static void ex_hl_block_beg(Vstr_base *s1, const char *block_type,
474 const char *block_beg,
475 const char *attr_id, const char *attr_class)
476 {
477 vstr_add_fmt(s1, s1->len, "<%s", block_type);
478 if (attr_id)
479 vstr_add_fmt(s1, s1->len, " id=\"%s\"", attr_id);
480 if (attr_class)
481 vstr_add_fmt(s1, s1->len, " class=\"%s\"", attr_class);
482 vstr_add_fmt(s1, s1->len, ">%s", block_beg);
483 }
ex_hl_block_end(Vstr_base * s1,const char * block_end,const char * block_type,unsigned int comments,time_t timestamp,const char * fname)484 static void ex_hl_block_end(Vstr_base *s1, const char *block_end,
485 const char *block_type,
486 unsigned int comments,
487 time_t timestamp, const char *fname)
488 {
489 vstr_add_fmt(s1, s1->len, "%s</%s>\n", block_end, block_type);
490 if (comments)
491 vstr_add_fmt(s1, s1->len,
492 "<!-- C to html convertion of %s -->\n"
493 "<!-- done on %s -->\n"
494 "<!-- done by jhighlight -->\n",
495 fname, ex_hl_ctime(timestamp));
496 }
497
main(int argc,char * argv[])498 int main(int argc, char *argv[])
499 {
500 Vstr_base *s2 = NULL;
501 Vstr_base *s1 = ex_init(&s2);
502 int count = 1;
503 time_t now = time(NULL);
504 unsigned int use_mmap = FALSE;
505 unsigned int comments = TRUE;
506 const char *cssfile = NULL;
507 const char *block_type = NULL;
508 const char *block_beg = "\n";
509 const char *block_end = NULL;
510 const char *attr_id = NULL;
511 const char *attr_class = "c2html";
512
513 {
514 size_t scan = 0;
515
516 while (ex_hl_seqs[scan].name)
517 {
518 size_t len = strlen(ex_hl_seqs[scan].seq);
519
520 ex_hl_seqs[scan].len = len;
521
522 if (ex_hl_max_seq_len < len)
523 ex_hl_max_seq_len = len;
524
525 ++scan;
526 }
527 }
528
529 /* parse command line arguments... */
530 while (count < argc)
531 { /* quick hack getopt_long */
532 if (!strcmp("--", argv[count]))
533 {
534 ++count;
535 break;
536 }
537 else if (!strcmp("--comments", argv[count])) /* toggle use of mmap */
538 comments = !comments;
539 else if (!strcmp("--mmap", argv[count])) /* toggle use of mmap */
540 use_mmap = !use_mmap;
541 EX_UTILS_GETOPT_CSTR("beg", block_beg);
542 EX_UTILS_GETOPT_CSTR("cssfile", cssfile);
543 EX_UTILS_GETOPT_CSTR("css-file", cssfile);
544 EX_UTILS_GETOPT_CSTR("cssfilename", cssfile);
545 EX_UTILS_GETOPT_CSTR("css-filename", cssfile);
546 EX_UTILS_GETOPT_CSTR("class", attr_class);
547 EX_UTILS_GETOPT_CSTR("end", block_end);
548 EX_UTILS_GETOPT_CSTR("id", attr_id);
549 EX_UTILS_GETOPT_CSTR("type", block_type);
550 else if (!strcmp("--version", argv[count]))
551 { /* print version and exit */
552 vstr_add_fmt(s1, 0, "%s", "\
553 jhighlight 1.0.0\n\
554 Written by James Antill\n\
555 \n\
556 Uses Vstr string library.\n\
557 ");
558 goto out;
559 }
560 else if (!strcmp("--help", argv[count]))
561 { /* print version and exit */
562 vstr_add_fmt(s1, 0, "%s", "\
563 Usage: jhighlight [STRING]...\n\
564 or: jhighlight OPTION\n\
565 Output filenames in html converteed from C.\n\
566 \n\
567 --help - Display this help and exit\n\
568 --version - Output version information and exit\n\
569 --mmap - Toggle use of mmap() to load input files\n\
570 --comments - Toggle output of attribution comments\n\
571 --beg - Extra text to output at the begining\n\
572 --css-filename - Location of css used in HTML.\n\
573 --class - Class name for block\n\
574 --end - Extra text to output at the ending\n\
575 --id - Id name for block\n\
576 --type - Name for block (Eg. \"pre\" or \"code\" etc.)\n\
577 -- - Treat rest of cmd line as input filenames\n\
578 \n\
579 Report bugs to James Antill <james@and.org>.\n\
580 ");
581 goto out;
582 }
583 else
584 break;
585 ++count;
586 }
587
588 if (cssfile && !*cssfile) cssfile = NULL;
589 if (block_type && !*block_type) block_type = NULL;
590 if (attr_id && !*attr_id) attr_id = NULL;
591 if (attr_class && !*attr_class) attr_class = NULL;
592
593 if (!block_type) block_type = "pre";
594 if (!block_end) block_end = "";
595
596 if (cssfile)
597 {
598 int scan = count;
599
600 vstr_add_cstr_ptr(s1, s1->len, "\
601 <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n\
602 <html>\n\
603 <head>\n\
604 <title>");
605
606 if (scan >= argc)
607 vstr_add_cstr_ptr(s1, s1->len, "c2html for: STDIN");
608 else
609 vstr_add_fmt(s1, s1->len, "c2html for: %s", base_fname(argv[scan++]));
610
611 while (scan < argc)
612 vstr_add_fmt(s1, s1->len, ", %s", base_fname(argv[scan++]));
613
614 vstr_add_cstr_ptr(s1, s1->len, "</title>\n\
615 <link rel=\"stylesheet\" type=\"text/css\" href=\"");
616 vstr_add_cstr_ptr(s1, s1->len, cssfile);
617 vstr_add_cstr_ptr(s1, s1->len, "\">\n\
618 </head>\n\
619 <body>\n");
620 }
621
622 /* if no arguments are given just do stdin to stdout */
623 if (count >= argc)
624 {
625 io_fd_set_o_nonblock(STDIN_FILENO);
626
627 if (cssfile)
628 vstr_add_cstr_ptr(s1, s1->len, " <h1>STDIN</h1>\n");
629
630 ex_hl_block_beg(s1, block_type, block_beg, attr_id, attr_class);
631 first_time = TRUE;
632 vstr_add_rep_chr(s2, s2->len, '\n', 1);
633 ex_hl_read_fd_write_stdout(s1, s2, STDIN_FILENO);
634 ex_hl_block_end(s1, block_end, block_type, comments, now, "stdin");
635 }
636
637 /* loop through all arguments, open the file specified
638 * and do the read/write loop */
639 while (count < argc)
640 {
641 unsigned int ern = 0;
642
643 ASSERT(!s2->len);
644 first_time = TRUE;
645 vstr_add_rep_chr(s2, s2->len, '\n', 1); /* add to begining */
646
647 if (use_mmap && (s2->len <= EX_MAX_R_DATA_INCORE))
648 vstr_sc_mmap_file(s2, s2->len, argv[count], 0, 0, &ern);
649
650 if (cssfile)
651 vstr_add_fmt(s1, s1->len, " <h1>%s</h1>\n", base_fname(argv[count]));
652
653 ex_hl_block_beg(s1, block_type, block_beg, attr_id, attr_class);
654
655 if (!use_mmap ||
656 (ern == VSTR_TYPE_SC_MMAP_FILE_ERR_FSTAT_ERRNO) ||
657 (ern == VSTR_TYPE_SC_MMAP_FILE_ERR_MMAP_ERRNO) ||
658 (ern == VSTR_TYPE_SC_MMAP_FILE_ERR_TOO_LARGE))
659 {
660 int fd = io_open(argv[count]);
661
662 ex_hl_read_fd_write_stdout(s1, s2, fd);
663
664 if (close(fd) == -1)
665 warn("close(%s)", argv[count]);
666 }
667 else if (ern && (ern != VSTR_TYPE_SC_MMAP_FILE_ERR_CLOSE_ERRNO))
668 err(EXIT_FAILURE, "mmap");
669 else
670 ex_hl_process_limit(s1, s2, 0);
671
672 ex_hl_block_end(s1, block_end, block_type, comments, now, argv[count]);
673
674 ++count;
675 }
676
677 if (cssfile)
678 {
679 vstr_add_cstr_ptr(s1, s1->len, "\n\
680 </body>\n\
681 </html>\n");
682 }
683
684 out:
685 io_put_all(s1, STDOUT_FILENO);
686
687 exit (ex_exit(s1, s2));
688 }
689