]>
git.cameronkatri.com Git - mandoc.git/blob - html.c
1 /* $Id: html.c,v 1.51 2009/09/21 14:56:56 kristaps Exp $ */
3 * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include <sys/types.h>
18 #include <sys/queue.h>
30 #define DOCTYPE "-//W3C//DTD HTML 4.01//EN"
31 #define DTD "http://www.w3.org/TR/html4/strict.dtd"
36 #define HTML_CLRLINE (1 << 0)
37 #define HTML_NOSTACK (1 << 1)
40 static const struct htmldata htmltags
[TAG_MAX
] = {
41 {"html", HTML_CLRLINE
}, /* TAG_HTML */
42 {"head", HTML_CLRLINE
}, /* TAG_HEAD */
43 {"body", HTML_CLRLINE
}, /* TAG_BODY */
44 {"meta", HTML_CLRLINE
| HTML_NOSTACK
}, /* TAG_META */
45 {"title", HTML_CLRLINE
}, /* TAG_TITLE */
46 {"div", HTML_CLRLINE
}, /* TAG_DIV */
47 {"h1", 0}, /* TAG_H1 */
48 {"h2", 0}, /* TAG_H2 */
49 {"p", HTML_CLRLINE
}, /* TAG_P */
50 {"span", 0}, /* TAG_SPAN */
51 {"link", HTML_CLRLINE
| HTML_NOSTACK
}, /* TAG_LINK */
52 {"br", HTML_CLRLINE
| HTML_NOSTACK
}, /* TAG_LINK */
54 {"table", HTML_CLRLINE
}, /* TAG_TABLE */
55 {"col", HTML_CLRLINE
| HTML_NOSTACK
}, /* TAG_COL */
56 {"tr", HTML_CLRLINE
}, /* TAG_TR */
57 {"td", HTML_CLRLINE
}, /* TAG_TD */
58 {"li", HTML_CLRLINE
}, /* TAG_LI */
59 {"ul", HTML_CLRLINE
}, /* TAG_UL */
60 {"ol", HTML_CLRLINE
}, /* TAG_OL */
61 {"base", HTML_CLRLINE
| HTML_NOSTACK
}, /* TAG_BASE */
64 static const char *const htmlattrs
[ATTR_MAX
] = {
79 extern int getsubopt(char **, char * const *, char **);
83 html_alloc(char *outopts
)
92 if (NULL
== (h
= calloc(1, sizeof(struct html
))))
98 if (NULL
== (h
->symtab
= chars_init(CHARS_HTML
))) {
103 while (outopts
&& *outopts
)
104 switch (getsubopt(&outopts
, toks
, &v
)) {
126 h
= (struct html
*)p
;
128 while ( ! SLIST_EMPTY(&h
->ords
)) {
129 ord
= SLIST_FIRST(&h
->ords
);
130 SLIST_REMOVE_HEAD(&h
->ords
, entry
);
134 while ( ! SLIST_EMPTY(&h
->tags
)) {
135 tag
= SLIST_FIRST(&h
->tags
);
136 SLIST_REMOVE_HEAD(&h
->tags
, entry
);
141 chars_free(h
->symtab
);
147 print_gen_head(struct html
*h
)
149 struct htmlpair tag
[4];
151 tag
[0].key
= ATTR_HTTPEQUIV
;
152 tag
[0].val
= "Content-Type";
153 tag
[1].key
= ATTR_CONTENT
;
154 tag
[1].val
= "text/html; charset=utf-8";
155 print_otag(h
, TAG_META
, 2, tag
);
157 tag
[0].key
= ATTR_NAME
;
158 tag
[0].val
= "resource-type";
159 tag
[1].key
= ATTR_CONTENT
;
160 tag
[1].val
= "document";
161 print_otag(h
, TAG_META
, 2, tag
);
164 tag
[0].key
= ATTR_REL
;
165 tag
[0].val
= "stylesheet";
166 tag
[1].key
= ATTR_HREF
;
167 tag
[1].val
= h
->style
;
168 tag
[2].key
= ATTR_TYPE
;
169 tag
[2].val
= "text/css";
170 tag
[3].key
= ATTR_MEDIA
;
172 print_otag(h
, TAG_LINK
, 4, tag
);
176 tag
[0].key
= ATTR_HREF
;
177 tag
[1].val
= h
->base
;
178 print_otag(h
, TAG_BASE
, 1, tag
);
184 print_spec(struct html
*h
, const char *p
, int len
)
190 rhs
= chars_a2ascii(h
->symtab
, p
, (size_t)len
, &sz
);
194 for (i
= 0; i
< (int)sz
; i
++)
200 print_res(struct html
*h
, const char *p
, int len
)
206 rhs
= chars_a2res(h
->symtab
, p
, (size_t)len
, &sz
);
210 for (i
= 0; i
< (int)sz
; i
++)
216 print_escape(struct html
*h
, const char **p
)
231 if (0 == *wp
|| 0 == *(wp
+ 1)) {
232 *p
= 0 == *wp
? wp
: wp
+ 1;
236 print_spec(h
, wp
, 2);
240 } else if ('*' == *wp
) {
249 if (0 == *wp
|| 0 == *(wp
+ 1)) {
250 *p
= 0 == *wp
? wp
: wp
+ 1;
266 } else if ('f' == *wp
) {
291 } else if ('[' != *wp
) {
292 print_spec(h
, wp
, 1);
298 for (j
= 0; *wp
&& ']' != *wp
; wp
++, j
++)
307 print_spec(h
, wp
- j
, j
);
309 print_res(h
, wp
- j
, j
);
316 print_encode(struct html
*h
, const char *p
)
343 print_otag(struct html
*h
, enum htmltag tag
,
344 int sz
, const struct htmlpair
*p
)
349 if ( ! (HTML_NOSTACK
& htmltags
[tag
].flags
)) {
350 if (NULL
== (t
= malloc(sizeof(struct tag
))))
351 err(EXIT_FAILURE
, "malloc");
353 SLIST_INSERT_HEAD(&h
->tags
, t
, entry
);
357 if ( ! (HTML_NOSPACE
& h
->flags
))
358 if ( ! (HTML_CLRLINE
& htmltags
[tag
].flags
))
361 printf("<%s", htmltags
[tag
].name
);
362 for (i
= 0; i
< sz
; i
++) {
363 printf(" %s=\"", htmlattrs
[p
[i
].key
]);
365 print_encode(h
, p
[i
].val
);
370 h
->flags
|= HTML_NOSPACE
;
371 if (HTML_CLRLINE
& htmltags
[tag
].flags
)
372 h
->flags
|= HTML_NEWLINE
;
374 h
->flags
&= ~HTML_NEWLINE
;
382 print_ctag(struct html
*h
, enum htmltag tag
)
385 printf("</%s>", htmltags
[tag
].name
);
386 if (HTML_CLRLINE
& htmltags
[tag
].flags
)
387 h
->flags
|= HTML_NOSPACE
;
388 if (HTML_CLRLINE
& htmltags
[tag
].flags
)
389 h
->flags
|= HTML_NEWLINE
;
391 h
->flags
&= ~HTML_NEWLINE
;
397 print_gen_doctype(struct html
*h
)
400 printf("<!DOCTYPE HTML PUBLIC \"%s\" \"%s\">", DOCTYPE
, DTD
);
405 print_text(struct html
*h
, const char *p
)
408 if (*p
&& 0 == *(p
+ 1))
427 h
->flags
|= HTML_NOSPACE
;
433 if ( ! (h
->flags
& HTML_NOSPACE
))
436 h
->flags
&= ~HTML_NOSPACE
;
437 h
->flags
&= ~HTML_NEWLINE
;
442 if (*p
&& 0 == *(p
+ 1))
449 h
->flags
|= HTML_NOSPACE
;
458 print_tagq(struct html
*h
, const struct tag
*until
)
462 while ( ! SLIST_EMPTY(&h
->tags
)) {
463 tag
= SLIST_FIRST(&h
->tags
);
464 print_ctag(h
, tag
->tag
);
465 SLIST_REMOVE_HEAD(&h
->tags
, entry
);
467 if (until
&& tag
== until
)
474 print_stagq(struct html
*h
, const struct tag
*suntil
)
478 while ( ! SLIST_EMPTY(&h
->tags
)) {
479 tag
= SLIST_FIRST(&h
->tags
);
480 if (suntil
&& tag
== suntil
)
482 print_ctag(h
, tag
->tag
);
483 SLIST_REMOVE_HEAD(&h
->tags
, entry
);