Print this page
5051 import mdocml-1.12.3
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Approved by: TBD
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/mandoc/html.c
+++ new/usr/src/cmd/mandoc/html.c
1 -/* $Id: html.c,v 1.150 2011/10/05 21:35:17 kristaps Exp $ */
1 +/* $Id: html.c,v 1.152 2013/08/08 20:07:47 schwarze Exp $ */
2 2 /*
3 3 * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4 - * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
4 + * Copyright (c) 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
5 5 *
6 6 * Permission to use, copy, modify, and distribute this software for any
7 7 * purpose with or without fee is hereby granted, provided that the above
8 8 * copyright notice and this permission notice appear in all copies.
9 9 *
10 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 17 */
18 18 #ifdef HAVE_CONFIG_H
19 19 #include "config.h"
20 20 #endif
21 21
22 22 #include <sys/types.h>
23 23
24 24 #include <assert.h>
25 25 #include <ctype.h>
26 26 #include <stdarg.h>
27 27 #include <stdio.h>
28 28 #include <stdint.h>
29 29 #include <stdlib.h>
30 30 #include <string.h>
31 31 #include <unistd.h>
32 32
33 33 #include "mandoc.h"
34 34 #include "libmandoc.h"
35 35 #include "out.h"
36 36 #include "html.h"
37 37 #include "main.h"
38 38
39 39 struct htmldata {
40 40 const char *name;
41 41 int flags;
42 42 #define HTML_CLRLINE (1 << 0)
43 43 #define HTML_NOSTACK (1 << 1)
44 44 #define HTML_AUTOCLOSE (1 << 2) /* Tag has auto-closure. */
45 45 };
46 46
47 47 static const struct htmldata htmltags[TAG_MAX] = {
48 48 {"html", HTML_CLRLINE}, /* TAG_HTML */
49 49 {"head", HTML_CLRLINE}, /* TAG_HEAD */
50 50 {"body", HTML_CLRLINE}, /* TAG_BODY */
51 51 {"meta", HTML_CLRLINE | HTML_NOSTACK | HTML_AUTOCLOSE}, /* TAG_META */
52 52 {"title", HTML_CLRLINE}, /* TAG_TITLE */
53 53 {"div", HTML_CLRLINE}, /* TAG_DIV */
54 54 {"h1", 0}, /* TAG_H1 */
55 55 {"h2", 0}, /* TAG_H2 */
56 56 {"span", 0}, /* TAG_SPAN */
57 57 {"link", HTML_CLRLINE | HTML_NOSTACK | HTML_AUTOCLOSE}, /* TAG_LINK */
58 58 {"br", HTML_CLRLINE | HTML_NOSTACK | HTML_AUTOCLOSE}, /* TAG_BR */
59 59 {"a", 0}, /* TAG_A */
60 60 {"table", HTML_CLRLINE}, /* TAG_TABLE */
61 61 {"tbody", HTML_CLRLINE}, /* TAG_TBODY */
62 62 {"col", HTML_CLRLINE | HTML_NOSTACK | HTML_AUTOCLOSE}, /* TAG_COL */
63 63 {"tr", HTML_CLRLINE}, /* TAG_TR */
64 64 {"td", HTML_CLRLINE}, /* TAG_TD */
65 65 {"li", HTML_CLRLINE}, /* TAG_LI */
66 66 {"ul", HTML_CLRLINE}, /* TAG_UL */
67 67 {"ol", HTML_CLRLINE}, /* TAG_OL */
68 68 {"dl", HTML_CLRLINE}, /* TAG_DL */
69 69 {"dt", HTML_CLRLINE}, /* TAG_DT */
70 70 {"dd", HTML_CLRLINE}, /* TAG_DD */
71 71 {"blockquote", HTML_CLRLINE}, /* TAG_BLOCKQUOTE */
72 72 {"p", HTML_CLRLINE | HTML_NOSTACK | HTML_AUTOCLOSE}, /* TAG_P */
73 73 {"pre", HTML_CLRLINE }, /* TAG_PRE */
74 74 {"b", 0 }, /* TAG_B */
75 75 {"i", 0 }, /* TAG_I */
76 76 {"code", 0 }, /* TAG_CODE */
77 77 {"small", 0 }, /* TAG_SMALL */
78 78 };
79 79
80 80 static const char *const htmlattrs[ATTR_MAX] = {
81 81 "http-equiv", /* ATTR_HTTPEQUIV */
82 82 "content", /* ATTR_CONTENT */
83 83 "name", /* ATTR_NAME */
84 84 "rel", /* ATTR_REL */
85 85 "href", /* ATTR_HREF */
86 86 "type", /* ATTR_TYPE */
87 87 "media", /* ATTR_MEDIA */
88 88 "class", /* ATTR_CLASS */
89 89 "style", /* ATTR_STYLE */
90 90 "width", /* ATTR_WIDTH */
91 91 "id", /* ATTR_ID */
92 92 "summary", /* ATTR_SUMMARY */
93 93 "align", /* ATTR_ALIGN */
94 94 "colspan", /* ATTR_COLSPAN */
95 95 };
96 96
97 97 static const char *const roffscales[SCALE_MAX] = {
98 98 "cm", /* SCALE_CM */
99 99 "in", /* SCALE_IN */
100 100 "pc", /* SCALE_PC */
101 101 "pt", /* SCALE_PT */
102 102 "em", /* SCALE_EM */
103 103 "em", /* SCALE_MM */
104 104 "ex", /* SCALE_EN */
105 105 "ex", /* SCALE_BU */
106 106 "em", /* SCALE_VS */
107 107 "ex", /* SCALE_FS */
108 108 };
109 109
110 110 static void bufncat(struct html *, const char *, size_t);
111 111 static void print_ctag(struct html *, enum htmltag);
112 112 static int print_encode(struct html *, const char *, int);
113 113 static void print_metaf(struct html *, enum mandoc_esc);
114 114 static void print_attr(struct html *, const char *, const char *);
115 115 static void *ml_alloc(char *, enum htmltype);
116 116
117 117 static void *
118 118 ml_alloc(char *outopts, enum htmltype type)
119 119 {
120 120 struct html *h;
121 121 const char *toks[5];
122 122 char *v;
123 123
124 124 toks[0] = "style";
125 125 toks[1] = "man";
126 126 toks[2] = "includes";
127 127 toks[3] = "fragment";
128 128 toks[4] = NULL;
129 129
130 130 h = mandoc_calloc(1, sizeof(struct html));
131 131
132 132 h->type = type;
133 133 h->tags.head = NULL;
134 134 h->symtab = mchars_alloc();
135 135
136 136 while (outopts && *outopts)
137 137 switch (getsubopt(&outopts, UNCONST(toks), &v)) {
138 138 case (0):
139 139 h->style = v;
140 140 break;
141 141 case (1):
142 142 h->base_man = v;
143 143 break;
144 144 case (2):
145 145 h->base_includes = v;
146 146 break;
147 147 case (3):
148 148 h->oflags |= HTML_FRAGMENT;
149 149 break;
150 150 default:
151 151 break;
152 152 }
153 153
154 154 return(h);
155 155 }
156 156
157 157 void *
158 158 html_alloc(char *outopts)
159 159 {
160 160
161 161 return(ml_alloc(outopts, HTML_HTML_4_01_STRICT));
162 162 }
163 163
164 164
165 165 void *
166 166 xhtml_alloc(char *outopts)
167 167 {
168 168
169 169 return(ml_alloc(outopts, HTML_XHTML_1_0_STRICT));
170 170 }
171 171
172 172
173 173 void
174 174 html_free(void *p)
175 175 {
176 176 struct tag *tag;
177 177 struct html *h;
178 178
179 179 h = (struct html *)p;
180 180
181 181 while ((tag = h->tags.head) != NULL) {
182 182 h->tags.head = tag->next;
183 183 free(tag);
184 184 }
185 185
186 186 if (h->symtab)
187 187 mchars_free(h->symtab);
188 188
189 189 free(h);
190 190 }
191 191
192 192
193 193 void
194 194 print_gen_head(struct html *h)
195 195 {
196 196 struct htmlpair tag[4];
197 197
198 198 tag[0].key = ATTR_HTTPEQUIV;
199 199 tag[0].val = "Content-Type";
200 200 tag[1].key = ATTR_CONTENT;
201 201 tag[1].val = "text/html; charset=utf-8";
202 202 print_otag(h, TAG_META, 2, tag);
203 203
204 204 tag[0].key = ATTR_NAME;
205 205 tag[0].val = "resource-type";
206 206 tag[1].key = ATTR_CONTENT;
207 207 tag[1].val = "document";
208 208 print_otag(h, TAG_META, 2, tag);
209 209
210 210 if (h->style) {
211 211 tag[0].key = ATTR_REL;
212 212 tag[0].val = "stylesheet";
213 213 tag[1].key = ATTR_HREF;
214 214 tag[1].val = h->style;
215 215 tag[2].key = ATTR_TYPE;
216 216 tag[2].val = "text/css";
217 217 tag[3].key = ATTR_MEDIA;
218 218 tag[3].val = "all";
219 219 print_otag(h, TAG_LINK, 4, tag);
220 220 }
221 221 }
222 222
223 223 static void
224 224 print_metaf(struct html *h, enum mandoc_esc deco)
225 225 {
226 226 enum htmlfont font;
227 227
↓ open down ↓ |
213 lines elided |
↑ open up ↑ |
228 228 switch (deco) {
229 229 case (ESCAPE_FONTPREV):
230 230 font = h->metal;
231 231 break;
232 232 case (ESCAPE_FONTITALIC):
233 233 font = HTMLFONT_ITALIC;
234 234 break;
235 235 case (ESCAPE_FONTBOLD):
236 236 font = HTMLFONT_BOLD;
237 237 break;
238 + case (ESCAPE_FONTBI):
239 + font = HTMLFONT_BI;
240 + break;
238 241 case (ESCAPE_FONT):
239 242 /* FALLTHROUGH */
240 243 case (ESCAPE_FONTROMAN):
241 244 font = HTMLFONT_NONE;
242 245 break;
243 246 default:
244 247 abort();
245 248 /* NOTREACHED */
246 249 }
247 250
248 251 if (h->metaf) {
249 252 print_tagq(h, h->metaf);
250 253 h->metaf = NULL;
251 254 }
252 255
253 256 h->metal = h->metac;
254 257 h->metac = font;
255 258
256 - if (HTMLFONT_NONE != font)
257 - h->metaf = HTMLFONT_BOLD == font ?
258 - print_otag(h, TAG_B, 0, NULL) :
259 - print_otag(h, TAG_I, 0, NULL);
259 + switch (font) {
260 + case (HTMLFONT_ITALIC):
261 + h->metaf = print_otag(h, TAG_I, 0, NULL);
262 + break;
263 + case (HTMLFONT_BOLD):
264 + h->metaf = print_otag(h, TAG_B, 0, NULL);
265 + break;
266 + case (HTMLFONT_BI):
267 + h->metaf = print_otag(h, TAG_B, 0, NULL);
268 + print_otag(h, TAG_I, 0, NULL);
269 + break;
270 + default:
271 + break;
272 + }
260 273 }
261 274
262 275 int
263 276 html_strlen(const char *cp)
264 277 {
265 - int ssz, sz;
266 - const char *seq, *p;
278 + size_t rsz;
279 + int skip, sz;
267 280
268 281 /*
269 282 * Account for escaped sequences within string length
270 283 * calculations. This follows the logic in term_strlen() as we
271 284 * must calculate the width of produced strings.
272 285 * Assume that characters are always width of "1". This is
273 286 * hacky, but it gets the job done for approximation of widths.
274 287 */
275 288
276 289 sz = 0;
277 - while (NULL != (p = strchr(cp, '\\'))) {
278 - sz += (int)(p - cp);
279 - ++cp;
280 - switch (mandoc_escape(&cp, &seq, &ssz)) {
290 + skip = 0;
291 + while (1) {
292 + rsz = strcspn(cp, "\\");
293 + if (rsz) {
294 + cp += rsz;
295 + if (skip) {
296 + skip = 0;
297 + rsz--;
298 + }
299 + sz += rsz;
300 + }
301 + if ('\0' == *cp)
302 + break;
303 + cp++;
304 + switch (mandoc_escape(&cp, NULL, NULL)) {
281 305 case (ESCAPE_ERROR):
282 306 return(sz);
283 307 case (ESCAPE_UNICODE):
284 308 /* FALLTHROUGH */
285 309 case (ESCAPE_NUMBERED):
286 310 /* FALLTHROUGH */
287 311 case (ESCAPE_SPECIAL):
288 - sz++;
312 + if (skip)
313 + skip = 0;
314 + else
315 + sz++;
289 316 break;
317 + case (ESCAPE_SKIPCHAR):
318 + skip = 1;
319 + break;
290 320 default:
291 321 break;
292 322 }
293 323 }
294 -
295 - assert(sz >= 0);
296 - return(sz + strlen(cp));
324 + return(sz);
297 325 }
298 326
299 327 static int
300 328 print_encode(struct html *h, const char *p, int norecurse)
301 329 {
302 330 size_t sz;
303 331 int c, len, nospace;
304 332 const char *seq;
305 333 enum mandoc_esc esc;
306 334 static const char rejs[6] = { '\\', '<', '>', '&', ASCII_HYPH, '\0' };
307 335
308 336 nospace = 0;
309 337
310 338 while ('\0' != *p) {
339 + if (HTML_SKIPCHAR & h->flags && '\\' != *p) {
340 + h->flags &= ~HTML_SKIPCHAR;
341 + p++;
342 + continue;
343 + }
344 +
311 345 sz = strcspn(p, rejs);
312 346
313 347 fwrite(p, 1, sz, stdout);
314 348 p += (int)sz;
315 349
316 350 if ('\0' == *p)
317 351 break;
318 352
319 353 switch (*p++) {
320 354 case ('<'):
321 355 printf("<");
322 356 continue;
323 357 case ('>'):
324 358 printf(">");
325 359 continue;
326 360 case ('&'):
327 361 printf("&");
328 362 continue;
329 363 case (ASCII_HYPH):
330 364 putchar('-');
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
331 365 continue;
332 366 default:
333 367 break;
334 368 }
335 369
336 370 esc = mandoc_escape(&p, &seq, &len);
337 371 if (ESCAPE_ERROR == esc)
338 372 break;
339 373
340 374 switch (esc) {
375 + case (ESCAPE_FONT):
376 + /* FALLTHROUGH */
377 + case (ESCAPE_FONTPREV):
378 + /* FALLTHROUGH */
379 + case (ESCAPE_FONTBOLD):
380 + /* FALLTHROUGH */
381 + case (ESCAPE_FONTITALIC):
382 + /* FALLTHROUGH */
383 + case (ESCAPE_FONTBI):
384 + /* FALLTHROUGH */
385 + case (ESCAPE_FONTROMAN):
386 + if (0 == norecurse)
387 + print_metaf(h, esc);
388 + continue;
389 + case (ESCAPE_SKIPCHAR):
390 + h->flags |= HTML_SKIPCHAR;
391 + continue;
392 + default:
393 + break;
394 + }
395 +
396 + if (h->flags & HTML_SKIPCHAR) {
397 + h->flags &= ~HTML_SKIPCHAR;
398 + continue;
399 + }
400 +
401 + switch (esc) {
341 402 case (ESCAPE_UNICODE):
342 403 /* Skip passed "u" header. */
343 404 c = mchars_num2uc(seq + 1, len - 1);
344 405 if ('\0' != c)
345 406 printf("&#x%x;", c);
346 407 break;
347 408 case (ESCAPE_NUMBERED):
348 409 c = mchars_num2char(seq, len);
349 410 if ('\0' != c)
350 411 putchar(c);
351 412 break;
352 413 case (ESCAPE_SPECIAL):
353 414 c = mchars_spec2cp(h->symtab, seq, len);
354 415 if (c > 0)
355 416 printf("&#%d;", c);
356 417 else if (-1 == c && 1 == len)
357 418 putchar((int)*seq);
358 419 break;
359 - case (ESCAPE_FONT):
360 - /* FALLTHROUGH */
361 - case (ESCAPE_FONTPREV):
362 - /* FALLTHROUGH */
363 - case (ESCAPE_FONTBOLD):
364 - /* FALLTHROUGH */
365 - case (ESCAPE_FONTITALIC):
366 - /* FALLTHROUGH */
367 - case (ESCAPE_FONTROMAN):
368 - if (norecurse)
369 - break;
370 - print_metaf(h, esc);
371 - break;
372 420 case (ESCAPE_NOSPACE):
373 421 if ('\0' == *p)
374 422 nospace = 1;
375 423 break;
376 424 default:
377 425 break;
378 426 }
379 427 }
380 428
381 429 return(nospace);
382 430 }
383 431
384 432
385 433 static void
386 434 print_attr(struct html *h, const char *key, const char *val)
387 435 {
388 436 printf(" %s=\"", key);
389 437 (void)print_encode(h, val, 1);
390 438 putchar('\"');
391 439 }
392 440
393 441
394 442 struct tag *
395 443 print_otag(struct html *h, enum htmltag tag,
396 444 int sz, const struct htmlpair *p)
397 445 {
398 446 int i;
399 447 struct tag *t;
400 448
401 449 /* Push this tags onto the stack of open scopes. */
402 450
403 451 if ( ! (HTML_NOSTACK & htmltags[tag].flags)) {
404 452 t = mandoc_malloc(sizeof(struct tag));
405 453 t->tag = tag;
406 454 t->next = h->tags.head;
407 455 h->tags.head = t;
408 456 } else
409 457 t = NULL;
410 458
411 459 if ( ! (HTML_NOSPACE & h->flags))
412 460 if ( ! (HTML_CLRLINE & htmltags[tag].flags)) {
413 461 /* Manage keeps! */
414 462 if ( ! (HTML_KEEP & h->flags)) {
415 463 if (HTML_PREKEEP & h->flags)
416 464 h->flags |= HTML_KEEP;
417 465 putchar(' ');
418 466 } else
419 467 printf(" ");
420 468 }
421 469
422 470 if ( ! (h->flags & HTML_NONOSPACE))
423 471 h->flags &= ~HTML_NOSPACE;
424 472 else
425 473 h->flags |= HTML_NOSPACE;
426 474
427 475 /* Print out the tag name and attributes. */
428 476
429 477 printf("<%s", htmltags[tag].name);
430 478 for (i = 0; i < sz; i++)
431 479 print_attr(h, htmlattrs[p[i].key], p[i].val);
432 480
433 481 /* Add non-overridable attributes. */
434 482
435 483 if (TAG_HTML == tag && HTML_XHTML_1_0_STRICT == h->type) {
436 484 print_attr(h, "xmlns", "http://www.w3.org/1999/xhtml");
437 485 print_attr(h, "xml:lang", "en");
438 486 print_attr(h, "lang", "en");
439 487 }
440 488
441 489 /* Accommodate for XML "well-formed" singleton escaping. */
442 490
443 491 if (HTML_AUTOCLOSE & htmltags[tag].flags)
444 492 switch (h->type) {
445 493 case (HTML_XHTML_1_0_STRICT):
446 494 putchar('/');
447 495 break;
448 496 default:
449 497 break;
450 498 }
451 499
452 500 putchar('>');
453 501
454 502 h->flags |= HTML_NOSPACE;
455 503
456 504 if ((HTML_AUTOCLOSE | HTML_CLRLINE) & htmltags[tag].flags)
457 505 putchar('\n');
458 506
459 507 return(t);
460 508 }
461 509
462 510
463 511 static void
464 512 print_ctag(struct html *h, enum htmltag tag)
465 513 {
466 514
467 515 printf("</%s>", htmltags[tag].name);
468 516 if (HTML_CLRLINE & htmltags[tag].flags) {
469 517 h->flags |= HTML_NOSPACE;
470 518 putchar('\n');
471 519 }
472 520 }
473 521
474 522 void
475 523 print_gen_decls(struct html *h)
476 524 {
477 525 const char *doctype;
478 526 const char *dtd;
479 527 const char *name;
480 528
481 529 switch (h->type) {
482 530 case (HTML_HTML_4_01_STRICT):
483 531 name = "HTML";
484 532 doctype = "-//W3C//DTD HTML 4.01//EN";
485 533 dtd = "http://www.w3.org/TR/html4/strict.dtd";
486 534 break;
487 535 default:
488 536 puts("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
489 537 name = "html";
490 538 doctype = "-//W3C//DTD XHTML 1.0 Strict//EN";
491 539 dtd = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";
492 540 break;
493 541 }
494 542
495 543 printf("<!DOCTYPE %s PUBLIC \"%s\" \"%s\">\n",
496 544 name, doctype, dtd);
497 545 }
498 546
499 547 void
500 548 print_text(struct html *h, const char *word)
501 549 {
502 550
503 551 if ( ! (HTML_NOSPACE & h->flags)) {
↓ open down ↓ |
122 lines elided |
↑ open up ↑ |
504 552 /* Manage keeps! */
505 553 if ( ! (HTML_KEEP & h->flags)) {
506 554 if (HTML_PREKEEP & h->flags)
507 555 h->flags |= HTML_KEEP;
508 556 putchar(' ');
509 557 } else
510 558 printf(" ");
511 559 }
512 560
513 561 assert(NULL == h->metaf);
514 - if (HTMLFONT_NONE != h->metac)
515 - h->metaf = HTMLFONT_BOLD == h->metac ?
516 - print_otag(h, TAG_B, 0, NULL) :
517 - print_otag(h, TAG_I, 0, NULL);
562 + switch (h->metac) {
563 + case (HTMLFONT_ITALIC):
564 + h->metaf = print_otag(h, TAG_I, 0, NULL);
565 + break;
566 + case (HTMLFONT_BOLD):
567 + h->metaf = print_otag(h, TAG_B, 0, NULL);
568 + break;
569 + case (HTMLFONT_BI):
570 + h->metaf = print_otag(h, TAG_B, 0, NULL);
571 + print_otag(h, TAG_I, 0, NULL);
572 + break;
573 + default:
574 + break;
575 + }
518 576
519 577 assert(word);
520 578 if ( ! print_encode(h, word, 0)) {
521 579 if ( ! (h->flags & HTML_NONOSPACE))
522 580 h->flags &= ~HTML_NOSPACE;
523 581 } else
524 582 h->flags |= HTML_NOSPACE;
525 583
526 584 if (h->metaf) {
527 585 print_tagq(h, h->metaf);
528 586 h->metaf = NULL;
529 587 }
530 588
531 589 h->flags &= ~HTML_IGNDELIM;
532 590 }
533 591
534 592
535 593 void
536 594 print_tagq(struct html *h, const struct tag *until)
537 595 {
538 596 struct tag *tag;
539 597
540 598 while ((tag = h->tags.head) != NULL) {
541 599 /*
542 600 * Remember to close out and nullify the current
543 601 * meta-font and table, if applicable.
544 602 */
545 603 if (tag == h->metaf)
546 604 h->metaf = NULL;
547 605 if (tag == h->tblt)
548 606 h->tblt = NULL;
549 607 print_ctag(h, tag->tag);
550 608 h->tags.head = tag->next;
551 609 free(tag);
552 610 if (until && tag == until)
553 611 return;
554 612 }
555 613 }
556 614
557 615
558 616 void
559 617 print_stagq(struct html *h, const struct tag *suntil)
560 618 {
561 619 struct tag *tag;
562 620
563 621 while ((tag = h->tags.head) != NULL) {
564 622 if (suntil && tag == suntil)
565 623 return;
566 624 /*
567 625 * Remember to close out and nullify the current
568 626 * meta-font and table, if applicable.
569 627 */
570 628 if (tag == h->metaf)
571 629 h->metaf = NULL;
572 630 if (tag == h->tblt)
573 631 h->tblt = NULL;
574 632 print_ctag(h, tag->tag);
575 633 h->tags.head = tag->next;
576 634 free(tag);
577 635 }
578 636 }
579 637
580 638 void
581 639 bufinit(struct html *h)
582 640 {
583 641
584 642 h->buf[0] = '\0';
585 643 h->buflen = 0;
586 644 }
587 645
588 646 void
589 647 bufcat_style(struct html *h, const char *key, const char *val)
590 648 {
591 649
592 650 bufcat(h, key);
593 651 bufcat(h, ":");
594 652 bufcat(h, val);
595 653 bufcat(h, ";");
596 654 }
597 655
598 656 void
599 657 bufcat(struct html *h, const char *p)
600 658 {
601 659
602 660 h->buflen = strlcat(h->buf, p, BUFSIZ);
603 661 assert(h->buflen < BUFSIZ);
604 662 }
605 663
606 664 void
607 665 bufcat_fmt(struct html *h, const char *fmt, ...)
608 666 {
609 667 va_list ap;
610 668
611 669 va_start(ap, fmt);
612 670 (void)vsnprintf(h->buf + (int)h->buflen,
613 671 BUFSIZ - h->buflen - 1, fmt, ap);
614 672 va_end(ap);
615 673 h->buflen = strlen(h->buf);
616 674 }
617 675
618 676 static void
619 677 bufncat(struct html *h, const char *p, size_t sz)
620 678 {
621 679
622 680 assert(h->buflen + sz + 1 < BUFSIZ);
623 681 strncat(h->buf, p, sz);
624 682 h->buflen += sz;
625 683 }
626 684
627 685 void
628 686 buffmt_includes(struct html *h, const char *name)
629 687 {
630 688 const char *p, *pp;
631 689
632 690 pp = h->base_includes;
633 691
634 692 bufinit(h);
635 693 while (NULL != (p = strchr(pp, '%'))) {
636 694 bufncat(h, pp, (size_t)(p - pp));
637 695 switch (*(p + 1)) {
638 696 case('I'):
639 697 bufcat(h, name);
640 698 break;
641 699 default:
642 700 bufncat(h, p, 2);
643 701 break;
644 702 }
645 703 pp = p + 2;
646 704 }
647 705 if (pp)
648 706 bufcat(h, pp);
649 707 }
650 708
651 709 void
652 710 buffmt_man(struct html *h,
653 711 const char *name, const char *sec)
654 712 {
655 713 const char *p, *pp;
656 714
657 715 pp = h->base_man;
658 716
659 717 bufinit(h);
660 718 while (NULL != (p = strchr(pp, '%'))) {
661 719 bufncat(h, pp, (size_t)(p - pp));
662 720 switch (*(p + 1)) {
663 721 case('S'):
664 722 bufcat(h, sec ? sec : "1");
665 723 break;
666 724 case('N'):
667 725 bufcat_fmt(h, name);
668 726 break;
669 727 default:
670 728 bufncat(h, p, 2);
671 729 break;
672 730 }
673 731 pp = p + 2;
674 732 }
675 733 if (pp)
676 734 bufcat(h, pp);
677 735 }
678 736
679 737 void
680 738 bufcat_su(struct html *h, const char *p, const struct roffsu *su)
681 739 {
682 740 double v;
683 741
684 742 v = su->scale;
685 743 if (SCALE_MM == su->unit && 0.0 == (v /= 100.0))
686 744 v = 1.0;
687 745
688 746 bufcat_fmt(h, "%s: %.2f%s;", p, v, roffscales[su->unit]);
689 747 }
690 748
691 749 void
692 750 bufcat_id(struct html *h, const char *src)
693 751 {
694 752
695 753 /* Cf. <http://www.w3.org/TR/html4/types.html#h-6.2>. */
696 754
697 755 while ('\0' != *src)
698 756 bufcat_fmt(h, "%.2x", *src++);
699 757 }
↓ open down ↓ |
172 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX