1 /* $Id: html.c,v 1.150 2011/10/05 21:35:17 kristaps Exp $ */
2 /*
3 * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4 * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include <sys/types.h>
23
24 #include <assert.h>
218 tag[3].val = "all";
219 print_otag(h, TAG_LINK, 4, tag);
220 }
221 }
222
223 static void
224 print_metaf(struct html *h, enum mandoc_esc deco)
225 {
226 enum htmlfont font;
227
228 switch (deco) {
229 case (ESCAPE_FONTPREV):
230 font = h->metal;
231 break;
232 case (ESCAPE_FONTITALIC):
233 font = HTMLFONT_ITALIC;
234 break;
235 case (ESCAPE_FONTBOLD):
236 font = HTMLFONT_BOLD;
237 break;
238 case (ESCAPE_FONT):
239 /* FALLTHROUGH */
240 case (ESCAPE_FONTROMAN):
241 font = HTMLFONT_NONE;
242 break;
243 default:
244 abort();
245 /* NOTREACHED */
246 }
247
248 if (h->metaf) {
249 print_tagq(h, h->metaf);
250 h->metaf = NULL;
251 }
252
253 h->metal = h->metac;
254 h->metac = font;
255
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);
260 }
261
262 int
263 html_strlen(const char *cp)
264 {
265 int ssz, sz;
266 const char *seq, *p;
267
268 /*
269 * Account for escaped sequences within string length
270 * calculations. This follows the logic in term_strlen() as we
271 * must calculate the width of produced strings.
272 * Assume that characters are always width of "1". This is
273 * hacky, but it gets the job done for approximation of widths.
274 */
275
276 sz = 0;
277 while (NULL != (p = strchr(cp, '\\'))) {
278 sz += (int)(p - cp);
279 ++cp;
280 switch (mandoc_escape(&cp, &seq, &ssz)) {
281 case (ESCAPE_ERROR):
282 return(sz);
283 case (ESCAPE_UNICODE):
284 /* FALLTHROUGH */
285 case (ESCAPE_NUMBERED):
286 /* FALLTHROUGH */
287 case (ESCAPE_SPECIAL):
288 sz++;
289 break;
290 default:
291 break;
292 }
293 }
294
295 assert(sz >= 0);
296 return(sz + strlen(cp));
297 }
298
299 static int
300 print_encode(struct html *h, const char *p, int norecurse)
301 {
302 size_t sz;
303 int c, len, nospace;
304 const char *seq;
305 enum mandoc_esc esc;
306 static const char rejs[6] = { '\\', '<', '>', '&', ASCII_HYPH, '\0' };
307
308 nospace = 0;
309
310 while ('\0' != *p) {
311 sz = strcspn(p, rejs);
312
313 fwrite(p, 1, sz, stdout);
314 p += (int)sz;
315
316 if ('\0' == *p)
317 break;
318
319 switch (*p++) {
320 case ('<'):
321 printf("<");
322 continue;
323 case ('>'):
324 printf(">");
325 continue;
326 case ('&'):
327 printf("&");
328 continue;
329 case (ASCII_HYPH):
330 putchar('-');
331 continue;
332 default:
333 break;
334 }
335
336 esc = mandoc_escape(&p, &seq, &len);
337 if (ESCAPE_ERROR == esc)
338 break;
339
340 switch (esc) {
341 case (ESCAPE_UNICODE):
342 /* Skip passed "u" header. */
343 c = mchars_num2uc(seq + 1, len - 1);
344 if ('\0' != c)
345 printf("&#x%x;", c);
346 break;
347 case (ESCAPE_NUMBERED):
348 c = mchars_num2char(seq, len);
349 if ('\0' != c)
350 putchar(c);
351 break;
352 case (ESCAPE_SPECIAL):
353 c = mchars_spec2cp(h->symtab, seq, len);
354 if (c > 0)
355 printf("&#%d;", c);
356 else if (-1 == c && 1 == len)
357 putchar((int)*seq);
358 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 case (ESCAPE_NOSPACE):
373 if ('\0' == *p)
374 nospace = 1;
375 break;
376 default:
377 break;
378 }
379 }
380
381 return(nospace);
382 }
383
384
385 static void
386 print_attr(struct html *h, const char *key, const char *val)
387 {
388 printf(" %s=\"", key);
389 (void)print_encode(h, val, 1);
390 putchar('\"');
391 }
494
495 printf("<!DOCTYPE %s PUBLIC \"%s\" \"%s\">\n",
496 name, doctype, dtd);
497 }
498
499 void
500 print_text(struct html *h, const char *word)
501 {
502
503 if ( ! (HTML_NOSPACE & h->flags)) {
504 /* Manage keeps! */
505 if ( ! (HTML_KEEP & h->flags)) {
506 if (HTML_PREKEEP & h->flags)
507 h->flags |= HTML_KEEP;
508 putchar(' ');
509 } else
510 printf(" ");
511 }
512
513 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);
518
519 assert(word);
520 if ( ! print_encode(h, word, 0)) {
521 if ( ! (h->flags & HTML_NONOSPACE))
522 h->flags &= ~HTML_NOSPACE;
523 } else
524 h->flags |= HTML_NOSPACE;
525
526 if (h->metaf) {
527 print_tagq(h, h->metaf);
528 h->metaf = NULL;
529 }
530
531 h->flags &= ~HTML_IGNDELIM;
532 }
533
534
535 void
536 print_tagq(struct html *h, const struct tag *until)
537 {
|
1 /* $Id: html.c,v 1.152 2013/08/08 20:07:47 schwarze Exp $ */
2 /*
3 * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4 * Copyright (c) 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include <sys/types.h>
23
24 #include <assert.h>
218 tag[3].val = "all";
219 print_otag(h, TAG_LINK, 4, tag);
220 }
221 }
222
223 static void
224 print_metaf(struct html *h, enum mandoc_esc deco)
225 {
226 enum htmlfont font;
227
228 switch (deco) {
229 case (ESCAPE_FONTPREV):
230 font = h->metal;
231 break;
232 case (ESCAPE_FONTITALIC):
233 font = HTMLFONT_ITALIC;
234 break;
235 case (ESCAPE_FONTBOLD):
236 font = HTMLFONT_BOLD;
237 break;
238 case (ESCAPE_FONTBI):
239 font = HTMLFONT_BI;
240 break;
241 case (ESCAPE_FONT):
242 /* FALLTHROUGH */
243 case (ESCAPE_FONTROMAN):
244 font = HTMLFONT_NONE;
245 break;
246 default:
247 abort();
248 /* NOTREACHED */
249 }
250
251 if (h->metaf) {
252 print_tagq(h, h->metaf);
253 h->metaf = NULL;
254 }
255
256 h->metal = h->metac;
257 h->metac = font;
258
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 }
273 }
274
275 int
276 html_strlen(const char *cp)
277 {
278 size_t rsz;
279 int skip, sz;
280
281 /*
282 * Account for escaped sequences within string length
283 * calculations. This follows the logic in term_strlen() as we
284 * must calculate the width of produced strings.
285 * Assume that characters are always width of "1". This is
286 * hacky, but it gets the job done for approximation of widths.
287 */
288
289 sz = 0;
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)) {
305 case (ESCAPE_ERROR):
306 return(sz);
307 case (ESCAPE_UNICODE):
308 /* FALLTHROUGH */
309 case (ESCAPE_NUMBERED):
310 /* FALLTHROUGH */
311 case (ESCAPE_SPECIAL):
312 if (skip)
313 skip = 0;
314 else
315 sz++;
316 break;
317 case (ESCAPE_SKIPCHAR):
318 skip = 1;
319 break;
320 default:
321 break;
322 }
323 }
324 return(sz);
325 }
326
327 static int
328 print_encode(struct html *h, const char *p, int norecurse)
329 {
330 size_t sz;
331 int c, len, nospace;
332 const char *seq;
333 enum mandoc_esc esc;
334 static const char rejs[6] = { '\\', '<', '>', '&', ASCII_HYPH, '\0' };
335
336 nospace = 0;
337
338 while ('\0' != *p) {
339 if (HTML_SKIPCHAR & h->flags && '\\' != *p) {
340 h->flags &= ~HTML_SKIPCHAR;
341 p++;
342 continue;
343 }
344
345 sz = strcspn(p, rejs);
346
347 fwrite(p, 1, sz, stdout);
348 p += (int)sz;
349
350 if ('\0' == *p)
351 break;
352
353 switch (*p++) {
354 case ('<'):
355 printf("<");
356 continue;
357 case ('>'):
358 printf(">");
359 continue;
360 case ('&'):
361 printf("&");
362 continue;
363 case (ASCII_HYPH):
364 putchar('-');
365 continue;
366 default:
367 break;
368 }
369
370 esc = mandoc_escape(&p, &seq, &len);
371 if (ESCAPE_ERROR == esc)
372 break;
373
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) {
402 case (ESCAPE_UNICODE):
403 /* Skip passed "u" header. */
404 c = mchars_num2uc(seq + 1, len - 1);
405 if ('\0' != c)
406 printf("&#x%x;", c);
407 break;
408 case (ESCAPE_NUMBERED):
409 c = mchars_num2char(seq, len);
410 if ('\0' != c)
411 putchar(c);
412 break;
413 case (ESCAPE_SPECIAL):
414 c = mchars_spec2cp(h->symtab, seq, len);
415 if (c > 0)
416 printf("&#%d;", c);
417 else if (-1 == c && 1 == len)
418 putchar((int)*seq);
419 break;
420 case (ESCAPE_NOSPACE):
421 if ('\0' == *p)
422 nospace = 1;
423 break;
424 default:
425 break;
426 }
427 }
428
429 return(nospace);
430 }
431
432
433 static void
434 print_attr(struct html *h, const char *key, const char *val)
435 {
436 printf(" %s=\"", key);
437 (void)print_encode(h, val, 1);
438 putchar('\"');
439 }
542
543 printf("<!DOCTYPE %s PUBLIC \"%s\" \"%s\">\n",
544 name, doctype, dtd);
545 }
546
547 void
548 print_text(struct html *h, const char *word)
549 {
550
551 if ( ! (HTML_NOSPACE & h->flags)) {
552 /* Manage keeps! */
553 if ( ! (HTML_KEEP & h->flags)) {
554 if (HTML_PREKEEP & h->flags)
555 h->flags |= HTML_KEEP;
556 putchar(' ');
557 } else
558 printf(" ");
559 }
560
561 assert(NULL == h->metaf);
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 }
576
577 assert(word);
578 if ( ! print_encode(h, word, 0)) {
579 if ( ! (h->flags & HTML_NONOSPACE))
580 h->flags &= ~HTML_NOSPACE;
581 } else
582 h->flags |= HTML_NOSPACE;
583
584 if (h->metaf) {
585 print_tagq(h, h->metaf);
586 h->metaf = NULL;
587 }
588
589 h->flags &= ~HTML_IGNDELIM;
590 }
591
592
593 void
594 print_tagq(struct html *h, const struct tag *until)
595 {
|