38#ifndef XML_STATUS_ERROR
39#define XML_STATUS_ERROR 0
77typedef int (*attrFn) (
void *,
char *);
78typedef int (*bcmpfn) (
const void *,
const void *);
86#define ISIZE (sizeof(attr_item))
91static int icmp(
const void *name,
const void *
item) {
92 const attr_item *j =
item;
93 return strcasecmp(name, j->name);
116 unsigned short flags = 0;
134 agwarningf(
"Unrecognized character '%c' (%d) in sides attribute\n", c, c);
145 p->
title = strdup(v);
172 agwarningf(
"Illegal value %.*s for STYLE - ignored\n", (
int)tk.
size,
199static int doInt(
char *v,
char *
s,
int min,
int max,
long *ul)
203 long b = strtol(v, &ep, 10);
206 agwarningf(
"Improper %s value %s - ignored",
s, v);
208 }
else if (b > max) {
209 agwarningf(
"%s value %s > %d - too large - ignored",
s, v, max);
211 }
else if (b < min) {
212 agwarningf(
"%s value %s < %d - too small - ignored",
s, v, min);
220static int gradientanglefn(
htmldata_t * p,
char *v)
224 if (doInt(v,
"GRADIENTANGLE", 0, 360, &u))
235 if (doInt(v,
"BORDER", 0, UCHAR_MAX, &u))
237 p->
border = (
unsigned char) u;
242static int cellpaddingfn(
htmldata_t * p,
char *v)
246 if (doInt(v,
"CELLPADDING", 0, UCHAR_MAX, &u))
248 p->
pad = (
unsigned char) u;
253static int cellspacingfn(
htmldata_t * p,
char *v)
257 if (doInt(v,
"CELLSPACING", SCHAR_MIN, SCHAR_MAX, &u))
259 p->
space = (
signed char) u;
264static int cellborderfn(
htmltbl_t * p,
char *v)
268 if (doInt(v,
"CELLBORDER", 0,
INT8_MAX, &u))
274static int columnsfn(
htmltbl_t * p,
char *v)
277 agwarningf(
"Unknown value %s for COLUMNS - ignored\n", v);
287 agwarningf(
"Unknown value %s for ROWS - ignored\n", v);
294static int fixedsizefn(
htmldata_t * p,
char *v)
297 if (!strcasecmp(v,
"TRUE"))
299 else if (strcasecmp(v,
"FALSE")) {
300 agwarningf(
"Illegal value %s for FIXEDSIZE - ignored\n", v);
309 if (!strcasecmp(v,
"BOTTOM"))
311 else if (!strcasecmp(v,
"TOP"))
313 else if (strcasecmp(v,
"MIDDLE")) {
314 agwarningf(
"Illegal value %s for VALIGN - ignored\n", v);
323 if (!strcasecmp(v,
"LEFT"))
325 else if (!strcasecmp(v,
"RIGHT"))
327 else if (strcasecmp(v,
"CENTER")) {
328 agwarningf(
"Illegal value %s for ALIGN - ignored\n", v);
334static int cell_halignfn(
htmldata_t * p,
char *v)
337 if (!strcasecmp(v,
"LEFT"))
339 else if (!strcasecmp(v,
"RIGHT"))
341 else if (!strcasecmp(v,
"TEXT"))
343 else if (strcasecmp(v,
"CENTER"))
346 agwarningf(
"Illegal value %s for ALIGN in TD - ignored\n", v);
353 if (!strcasecmp(v,
"LEFT"))
355 else if (!strcasecmp(v,
"RIGHT"))
357 else if (strcasecmp(v,
"CENTER"))
360 agwarningf(
"Illegal value %s for BALIGN in TD - ignored\n", v);
368 if (doInt(v,
"HEIGHT", 0, USHRT_MAX, &u))
370 p->
height = (
unsigned short) u;
378 if (doInt(v,
"WIDTH", 0, USHRT_MAX, &u))
380 p->
width = (
unsigned short) u;
391 agwarningf(
"ROWSPAN value cannot be 0 - ignored\n");
405 agwarningf(
"COLSPAN value cannot be 0 - ignored\n");
412static int fontcolorfn(
textfont_t * p,
char *v)
428 if (doInt(v,
"POINT-SIZE", 0, UCHAR_MAX, &u))
430 p->
size = (double) u;
440static int scalefn(
htmlimg_t * p,
char *v)
442 p->
scale = strdup(v);
446static int alignfn(
int *p,
char *v)
449 if (!strcasecmp(v,
"RIGHT"))
451 else if (!strcasecmp(v,
"LEFT"))
453 else if (!strcasecmp(v,
"CENTER"))
456 agwarningf(
"Illegal value %s for ALIGN - ignored\n", v);
463static attr_item tbl_items[] = {
464 {
"align", (attrFn) halignfn},
465 {
"bgcolor", (attrFn) bgcolorfn},
466 {
"border", (attrFn) borderfn},
467 {
"cellborder", (attrFn) cellborderfn},
468 {
"cellpadding", (attrFn) cellpaddingfn},
469 {
"cellspacing", (attrFn) cellspacingfn},
470 {
"color", (attrFn) pencolorfn},
471 {
"columns", (attrFn) columnsfn},
472 {
"fixedsize", (attrFn) fixedsizefn},
473 {
"gradientangle", (attrFn) gradientanglefn},
474 {
"height", (attrFn) heightfn},
475 {
"href", (attrFn) hreffn},
476 {
"id", (attrFn) idfn},
477 {
"port", (attrFn) portfn},
478 {
"rows", (attrFn) rowsfn},
479 {
"sides", (attrFn) sidesfn},
480 {
"style", (attrFn) stylefn},
481 {
"target", (attrFn) targetfn},
482 {
"title", (attrFn) titlefn},
483 {
"tooltip", (attrFn) titlefn},
484 {
"valign", (attrFn) valignfn},
485 {
"width", (attrFn) widthfn},
488static attr_item cell_items[] = {
489 {
"align", (attrFn) cell_halignfn},
490 {
"balign", (attrFn) balignfn},
491 {
"bgcolor", (attrFn) bgcolorfn},
492 {
"border", (attrFn) borderfn},
493 {
"cellpadding", (attrFn) cellpaddingfn},
494 {
"cellspacing", (attrFn) cellspacingfn},
495 {
"color", (attrFn) pencolorfn},
496 {
"colspan", (attrFn) colspanfn},
497 {
"fixedsize", (attrFn) fixedsizefn},
498 {
"gradientangle", (attrFn) gradientanglefn},
499 {
"height", (attrFn) heightfn},
500 {
"href", (attrFn) hreffn},
501 {
"id", (attrFn) idfn},
502 {
"port", (attrFn) portfn},
503 {
"rowspan", (attrFn) rowspanfn},
504 {
"sides", (attrFn) sidesfn},
505 {
"style", (attrFn) stylefn},
506 {
"target", (attrFn) targetfn},
507 {
"title", (attrFn) titlefn},
508 {
"tooltip", (attrFn) titlefn},
509 {
"valign", (attrFn) valignfn},
510 {
"width", (attrFn) widthfn},
513static attr_item font_items[] = {
514 {
"color", (attrFn) fontcolorfn},
515 {
"face", (attrFn) facefn},
516 {
"point-size", (attrFn) ptsizefn},
519static attr_item img_items[] = {
520 {
"scale", (attrFn) scalefn},
521 {
"src", (attrFn) srcfn},
524static attr_item br_items[] = {
525 {
"align", (attrFn) alignfn},
536static void doAttrs(
htmllexstate_t *ctx,
void *tp, attr_item *items,
size_t nel,
char **atts,
542 while ((name = *atts++) !=
NULL) {
544 ip = bsearch(name, items, nel, ISIZE, icmp);
546 ctx->
warn |= ip->action(tp, val);
548 agwarningf(
"Illegal attribute %s in %s - ignored\n", name,
558 doAttrs(ctx, &ctx->
htmllval->
i, br_items,
sizeof(br_items) / ISIZE, atts,
"<BR>");
565 doAttrs(ctx, img, img_items,
sizeof(img_items) / ISIZE, atts,
"<IMG>");
575 assert(
flags <= FLAGS_MAX);
576 tf.
flags = (
unsigned char)(
flags & FLAGS_MAX);
578 doAttrs(ctx, &tf, font_items,
sizeof(font_items) / ISIZE, atts,
"<FONT>");
589 doAttrs(ctx,
cell, cell_items,
sizeof(cell_items) / ISIZE, atts,
"<TD>");
601 doAttrs(ctx, tbl, tbl_items,
sizeof(tbl_items) / ISIZE, atts,
"<TABLE>");
606static void startElement(
void *user,
const char *name,
char **atts)
610 if (strcasecmp(name,
"TABLE") == 0) {
614 }
else if (strcasecmp(name,
"TR") == 0 || strcasecmp(name,
"TH") == 0) {
617 }
else if (strcasecmp(name,
"TD") == 0) {
621 }
else if (strcasecmp(name,
"FONT") == 0) {
624 }
else if (strcasecmp(name,
"B") == 0) {
627 }
else if (strcasecmp(name,
"S") == 0) {
630 }
else if (strcasecmp(name,
"U") == 0) {
633 }
else if (strcasecmp(name,
"O") == 0) {
636 }
else if (strcasecmp(name,
"I") == 0) {
639 }
else if (strcasecmp(name,
"SUP") == 0) {
642 }
else if (strcasecmp(name,
"SUB") == 0) {
645 }
else if (strcasecmp(name,
"BR") == 0) {
648 }
else if (strcasecmp(name,
"HR") == 0) {
650 }
else if (strcasecmp(name,
"VR") == 0) {
652 }
else if (strcasecmp(name,
"IMG") == 0) {
655 }
else if (strcasecmp(name,
"HTML") == 0) {
662static void endElement(
void *user,
const char *name)
666 if (strcasecmp(name,
"TABLE") == 0) {
669 }
else if (strcasecmp(name,
"TR") == 0 || strcasecmp(name,
"TH") == 0) {
671 }
else if (strcasecmp(name,
"TD") == 0) {
674 }
else if (strcasecmp(name,
"HTML") == 0) {
676 }
else if (strcasecmp(name,
"FONT") == 0) {
678 }
else if (strcasecmp(name,
"B") == 0) {
680 }
else if (strcasecmp(name,
"U") == 0) {
682 }
else if (strcasecmp(name,
"O") == 0) {
684 }
else if (strcasecmp(name,
"I") == 0) {
686 }
else if (strcasecmp(name,
"SUP") == 0) {
688 }
else if (strcasecmp(name,
"SUB") == 0) {
690 }
else if (strcasecmp(name,
"S") == 0) {
692 }
else if (strcasecmp(name,
"BR") == 0) {
697 }
else if (strcasecmp(name,
"HR") == 0) {
702 }
else if (strcasecmp(name,
"VR") == 0) {
707 }
else if (strcasecmp(name,
"IMG") == 0) {
724static void characterData(
void *user,
const char *
s,
int length)
732 for (i =
length; i; i--) {
760 XML_SetUserData(ctx->parser, ctx);
761 XML_SetElementHandler(ctx->parser,
762 (XML_StartElementHandler) startElement,
764 XML_SetCharacterDataHandler(ctx->parser, characterData);
772 static atomic_flag first;
773 if (!atomic_flag_test_and_set(&first)) {
775 "Not built with libexpat. Table formatting is not available.\n");
786 XML_ParserFree(ctx->parser);
818 while (depth && (c = *
s++)) {
846 t = eatComment(ctx, t + 3);
848 while (*t && *t !=
'>')
851 agwarningf(
"Label closed before end of HTML element\n");
857 while ((c = *t) && c !=
'<') {
858 if (c ==
'&' && *(t+1) !=
'#') {
886static void protect_rsqb(
agxbuf *xb) {
895 size_t size = strlen(data);
897 if (data[size - 1] !=
']') {
903 data[size - 1] =
'\0';
918 return XML_GetCurrentLineNumber(ctx->parser);
1050 const char *token_text =
agxbuse(ctx->
xb);
1051 fprintf(stderr,
"%s \"%s\"\n",
s, token_text);
1054 fprintf(stderr,
"%s\n",
s);
1062 static char *begin_html =
"<HTML>";
1063 static char *end_html =
"</HTML>";
1076 if (ctx->
mode == 0) {
1088 endp = findNext(ctx,
s,&ctx->
lb);
1089 len = (size_t)(endp -
s);
1093 protect_rsqb(&ctx->
lb);
1098 assert(llen <= INT_MAX &&
"XML token too long for expat API");
1099 rv = XML_Parse(ctx->parser,
agxbuse(&ctx->
lb), (
int)llen, 0);
1101 assert(
len <= INT_MAX &&
"XML token too long for expat API");
1102 rv = XML_Parse(ctx->parser,
s, (
int)
len,
len ? 0 : 1);
1115 }
while (ctx->
tok == 0);
1117 printTok (ctx, ctx->
tok);
static void agxbfree(agxbuf *xb)
free any malloced resources
static WUR char * agxbuse(agxbuf *xb)
static size_t agxblen(const agxbuf *xb)
return number of characters currently stored
static int agxbputc(agxbuf *xb, char c)
add character to buffer
Memory allocation wrappers that exit on failure.
static char * gv_strdup(const char *original)
static void * gv_alloc(size_t size)
char * scanEntity(char *t, agxbuf *xb)
static Extype_t length(Exid_t *rhs, Exdisc_t *disc)
static double len(glCompPoint p)
static int cnt(Dict_t *d, Dtlink_t **set)
void agwarningf(const char *fmt,...)
void agerrorf(const char *fmt,...)
int agerr(agerrlevel_t level, const char *fmt,...)
replacements for ctype.h functions
static char gv_tolower(int c)
int htmllex(union HTMLSTYPE *htmllval, htmlscan_t *scanner)
static UNUSED void agxbput_move(agxbuf *dst, const char *src)
agxbput, but assume that source and destination may overlap
unsigned long htmllineno(htmlscan_t *scanner)
static void error_context(htmllexstate_t *ctx)
int clearHTMLlexer(htmlscan_t *scanner)
int initHTMLlexer(htmlscan_t *scanner, char *src, agxbuf *xb, htmlenv_t *env)
void htmlerror(htmlscan_t *scanner, const char *msg)
static unsigned long htmllineno_ctx(htmllexstate_t *ctx)
static void free_ritem(row_t *p)
Free row. This closes and frees row’s list, then the item itself is freed.
static bool startswith(const char *s, const char *prefix)
does the string s begin with the string prefix?
platform abstraction for case-insensitive string functions
result of partitioning available space, part of maze
size_t row_count
number of rows
bool hrule
horizontal rule
a non-owning string reference
const char * data
start of the pointed to string
size_t size
extent of the string in bytes
state for an in-progress string tokenization
Non-owning string references.
static bool strview_case_str_eq(strview_t a, const char *b)
compare a string reference to a string for case insensitive equality
#define GV_TEXTFONT_FLAGS_WIDTH
static strview_t tok_get(const tok_t *t)
get the current token
static tok_t tok(const char *input, const char *separators)
begin tokenization of a new string
static bool tok_end(const tok_t *t)
is this tokenizer exhausted?
static void tok_next(tok_t *t)
advance to the next token in the string being scanned
abstraction for squashing compiler warnings for unused symbols