1 %{
2 /*
3  * Simple XML grammar, with call-back functions.
4  *
5  * Part of HTML-XML-utils, see:
6  * http://www.w3.org/Tools/HTML-XML-utils/
7  *
8  * Copyright © 1994-2000 World Wide Web Consortium
9  * See http://www.w3.org/Consortium/Legal/copyright-software
10  *
11  * Author: Bert Bos <bert@w3.org>
12  * Created: 1997
13  **/
14 #include "config.h"
15 #include <assert.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include "export.h"
20 #include "types.e"
21 
22 /* The types of the various callback routines */
23 
24 EXPORT typedef void (*html_handle_error_fn)
25   (void *clientdata, const string s, int lineno);
26 EXPORT typedef void* (*html_handle_start_fn)
27   (void);
28 EXPORT typedef void (*html_handle_end_fn)
29   (void *clientdata);
30 EXPORT typedef void (*html_handle_comment_fn)
31   (void *clientdata, const string commenttext);
32 EXPORT typedef void (*html_handle_text_fn)
33   (void *clientdata, const string text);
34 EXPORT typedef void (*html_handle_decl_fn)
35   (void *clientdata, const string gi, const string fpi, const string url);
36 EXPORT typedef void (*html_handle_pi_fn)
37   (void *clientdata, const string pi_text);
38 EXPORT typedef void (*html_handle_starttag_fn)
39   (void *clientdata, const string name, pairlist attribs);
40 EXPORT typedef void (*html_handle_emptytag_fn)
41   (void *clientdata, const string name, pairlist attribs);
42 EXPORT typedef void (*html_handle_endtag_fn)
43   (void *clientdata, const string name);
44 EXPORT typedef void (*html_handle_endincl_fn)
45   (void *clientdata);
46 
47 /* yyparse -- entry point for the parser */
48 EXPORT extern int yyparse(void);
49 
50 /* Store client data */
51 static void *data;
52 
53 /* All callback routines */
54 static struct {
55   html_handle_error_fn error;
56   html_handle_start_fn start;
57   html_handle_end_fn end;
58   html_handle_comment_fn comment;
59   html_handle_text_fn text;
60   html_handle_decl_fn decl;
61   html_handle_pi_fn pi;
62   html_handle_starttag_fn starttag;
63   html_handle_emptytag_fn emptytag;
64   html_handle_endtag_fn endtag;
65   html_handle_endincl_fn endincl;
66 } h = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
67 
68 /* Routines to bind concrete routines to the callbacks */
set_error_handler(html_handle_error_fn f)69 EXPORT void set_error_handler(html_handle_error_fn f) {h.error = f;}
set_start_handler(html_handle_start_fn f)70 EXPORT void set_start_handler(html_handle_start_fn f) {h.start = f;}
set_end_handler(html_handle_end_fn f)71 EXPORT void set_end_handler(html_handle_end_fn f) {h.end = f;}
set_comment_handler(html_handle_comment_fn f)72 EXPORT void set_comment_handler(html_handle_comment_fn f) {h.comment = f;}
set_text_handler(html_handle_text_fn f)73 EXPORT void set_text_handler(html_handle_text_fn f) {h.text = f;}
set_decl_handler(html_handle_decl_fn f)74 EXPORT void set_decl_handler(html_handle_decl_fn f) {h.decl = f;}
set_pi_handler(html_handle_pi_fn f)75 EXPORT void set_pi_handler(html_handle_pi_fn f) {h.pi = f;}
set_starttag_handler(html_handle_starttag_fn f)76 EXPORT void set_starttag_handler(html_handle_starttag_fn f){h.starttag = f;}
set_emptytag_handler(html_handle_emptytag_fn f)77 EXPORT void set_emptytag_handler(html_handle_emptytag_fn f){h.emptytag = f;}
set_endtag_handler(html_handle_endtag_fn f)78 EXPORT void set_endtag_handler(html_handle_endtag_fn f) {h.endtag = f;}
set_endincl_handler(html_handle_endincl_fn f)79 EXPORT void set_endincl_handler(html_handle_endincl_fn f) {h.endincl = f;}
80 
81 extern int yylex(void);
82 EXPORT int lineno = 1;		/* Line number in input file */
83 
84 static int nrerrors = 0;
85 #define MAX_ERRORS_REPORTED 20
86 
87 /* yyerror -- report parse error */
yyerror(const string s)88 static void yyerror(const string s)
89 {
90   nrerrors++;
91   if (nrerrors < MAX_ERRORS_REPORTED)
92     h.error(data, s, lineno);
93   else if (nrerrors == MAX_ERRORS_REPORTED)
94     h.error(data, "too many errors", lineno);
95   else
96     ; /* don't report any more errors */
97 }
98 
99 /* call -- if the function exists, call it with the given aguments */
100 #define call(fn, args) do {if (fn) (fn)args;} while (0)
101 %}
102 
103 %union {
104     string s;
105     pairlist p;
106 }
107 
108 %token <s> TEXT COMMENT START END NAME STRING PROCINS
109 %token EMPTYEND DOCTYPE ENDINCL
110 
111 %type <p> attribute attributes
112 
113 %%
114 
115 start
116 :					{data = h.start ? h.start() : NULL;}
117     document				{call(h.end, (data));}
118   ;
119 document
120   : document COMMENT			{call(h.comment, (data, $2));}
121   | document TEXT			{call(h.text, (data, $2));}
122   | document starttag
123   | document endtag
124   | document decl
125   | document PROCINS			{call(h.pi, (data, $2));}
126   | document ENDINCL			{call(h.endincl, (data));}
127   | document error
128   | /* empty */
129   ;
130 starttag
131   : START attributes '>'		{call(h.starttag, (data, $1, $2));}
132   | START attributes EMPTYEND		{call(h.emptytag, (data, $1, $2));}
133   ;
134 attributes
135   : attribute attributes		{$$ = $1; $$->next = $2;}
136   | /* empty */				{$$ = NULL;}
137   ;
138 attribute
139   : NAME				{pairlist h = malloc(sizeof(*h));
140 					 assert(h != NULL); h->name = $1;
141 					 h->value=NULL; $$ = h;}
142   | NAME '=' NAME			{pairlist h = malloc(sizeof(*h));
143 					 assert(h != NULL); h->name = $1;
144 					 h->value = $3; $$ = h;}
145   | NAME '=' STRING			{pairlist h = malloc(sizeof(*h));
146 					 assert(h != NULL); h->name = $1;
147 					 h->value = $3; $$ = h;}
148   ;
149 endtag
150   : END '>'				{call(h.endtag, (data, $1));}
151   ;
152 decl
153   : DOCTYPE NAME NAME STRING STRING '>'	{call(h.decl, (data, $2, $4, $5));}
154   | DOCTYPE NAME NAME STRING '>'	{if (strcasecmp($3, "public") == 0)
155 				     	   call(h.decl, (data, $2, $4, NULL));
156 					 else /* "system" */
157 					   call(h.decl, (data, $2, NULL, $4));}
158   | DOCTYPE NAME '>'			{call(h.decl, (data, $2, NULL, NULL));}
159   ;
160