dphl.y 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. /* gcc -fanalyzer issues in the bison generated yacc parser
  2. * dphlparser.c:533:19: warning: 'free' of 'yyss' which points to memory not on the heap [CWE-590] [-Wanalyzer-free-of-non-heap]
  3. * dphlparser.c:2270:10: warning: leak of 'yyptr' [CWE-401] [-Wanalyzer-malloc-leak]
  4. */
  5. /*
  6. * Copyright 2021
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. * SPDX-License-Identifier: GPL-3.0+
  22. * License-Filename: LICENSE
  23. */
  24. /* dphl.* is about Dot Parsing Html Labels */
  25. /* Notes:
  26. * result of parsing html label can be "" at <> as input
  27. * or <<!-- comment -->> as input.
  28. * some chars in html labels need to be escaped, this is in GNU GCC:
  29. * + As pp_write_text_to_stream, but for GraphViz HTML-like strings.
  30. * +
  31. * + Flush the formatted text of pretty-printer PP onto the attached stream,
  32. * + escaping these characters
  33. * + " & < >
  34. * + using XML escape sequences.
  35. * +
  36. * + http://www.graphviz.org/doc/info/lang.html#html states:
  37. * + special XML escape sequences for ", &, <, and > may be necessary in
  38. * + order to embed these characters in attribute values or raw text
  39. * + This doesn't list "'" (which would normally be escaped in XML
  40. * + as "&apos;" or in HTML as "&#39;");.
  41. * +
  42. * + Experiments show that escaping "'" doesn't seem to be necessary.
  43. * +
  44. * +void
  45. * +pp_write_text_as_html_like_dot_to_stream (pretty_printer *pp)
  46. * +{
  47. * + const char *text = pp_formatted_text (pp);
  48. * + const char *p = text;
  49. * + FILE *fp = pp_buffer (pp)->stream;
  50. * +
  51. * + for (;*p; p++)
  52. * + {
  53. * + switch (*p)
  54. * + {
  55. * + case '"':
  56. * + fputs ("&quot;", fp);
  57. * + break;
  58. * + case '&':
  59. * + fputs ("&amp;", fp);
  60. * + break;
  61. * + case '<':
  62. * + fputs ("&lt;", fp);
  63. * + break;
  64. * + case '>':
  65. * + fputs ("&gt;",fp);
  66. * + break;
  67. * +
  68. * + default:
  69. * + fputc (*p, fp);
  70. * + break;
  71. * + }
  72. * + }
  73. * +
  74. * + pp_clear_output_area (pp);
  75. * +}
  76. */
  77. %{
  78. #include "config.h"
  79. #include <stdio.h>
  80. #include <stdlib.h>
  81. #include <string.h>
  82. #include "splay-tree.h"
  83. #include "main.h"
  84. #include "dp.h"
  85. #include "dphl.h"
  86. #include "dpmem.h"
  87. /* make sure extra debug code is available */
  88. #define YYDEBUG 1
  89. /*
  90. * When Using Bison-2.5.1
  91. * The variable error controls the verbosity of error messages. The
  92. * use of the %error-verbose directive is deprecated in favor of
  93. * %define parse.error "verbose".
  94. */
  95. #define YYERROR_VERBOSE 1
  96. /* memory usage wrapping feature
  97. #ifndef YYFREE
  98. # define YYFREE free
  99. #endif
  100. #ifndef YYMALLOC
  101. # define YYMALLOC malloc
  102. #endif
  103. #ifndef YYREALLOC
  104. # define YYREALLOC realloc
  105. #endif
  106. */
  107. /* in lexer */
  108. extern int hllineno;
  109. extern char *hltext;
  110. extern int html_lex (void);
  111. /*
  112. * In GLR generated parser is:
  113. * YYLEX -- calling `yylex' with the right arguments.
  114. * #define YYLEX yylex (&yylval, &yylloc, pc)
  115. * YYSTYPE *lvalp, YYLTYPE *llocp, struct parser_control *pc
  116. */
  117. static int hlylex (void)
  118. {
  119. int tokencode = 0;
  120. tokencode = html_lex();
  121. if (tokencode == 0) {
  122. tokencode = EOF;
  123. }
  124. /* */
  125. return (tokencode);
  126. }
  127. static void yyerror (const char *msg)
  128. {
  129. if (strlen(dp_errmsg)==0) {
  130. snprintf(dp_errmsg,256-1,"html %s(): %s at line %d yytext is %s'\n",__func__,msg,hllineno,hltext);
  131. }
  132. printf("html %s(): %s at line %d yytext is `%s'\n",__func__,msg,hllineno,hltext);
  133. fflush(stdout);
  134. fflush(stderr);
  135. return;
  136. }
  137. %}
  138. /* prefix for internal names */
  139. /* for older bison versions use this:
  140. * %name-prefix "hly"
  141. */
  142. %define api.prefix {hly}
  143. /* not a yacc parser and gcc-11 analyzer has a problem with bison yacc parsers.
  144. * %glr-parser
  145. * the glr parser output has problems when compiled with C++ compiler
  146. * todo to find a solution
  147. */
  148. /* where to start in the grammar */
  149. %start begin
  150. /* token name array in the parser code */
  151. %token-table
  152. /* write defines file */
  153. %defines
  154. /* output file */
  155. %output "dphlparser.c"
  156. /* add verbose debug */
  157. %verbose
  158. /* add debug */
  159. %debug
  160. /* u */
  161. %union { char *string; }
  162. %token <string>HL_DATA "stringdata" /* string with data area */
  163. %token HL_HTML "<html" /* "<html" */
  164. %token HL_C_HTML "</html" /* "</html" */
  165. %token HL_B "<b" /* "<b" */
  166. %token HL_C_B "</b" /* "</b" */
  167. %token HL_BR "<br" /* "<br" */
  168. %token HL_C_BR "</br" /* "</br" */
  169. %token HL_FONT "<font" /* "<font" */
  170. %token HL_C_FONT "</font" /* "</font" */
  171. %token HL_HR "<hr" /* "<hr" */
  172. %token HL_C_HR "</hr" /* "</hr" */
  173. %token HL_I "<i" /* "<i" */
  174. %token HL_C_I "</i" /* "</i" */
  175. %token HL_IMG "<img" /* "<img" */
  176. %token HL_C_IMG "</img" /* "</img" */
  177. %token HL_O "<o" /* "<o" */
  178. %token HL_C_O "</o" /* "</o" */
  179. %token HL_S "<s" /* "<s" */
  180. %token HL_C_S "</s" /* "</s" */
  181. %token HL_SUB "<sub" /* "<sub" */
  182. %token HL_C_SUB "</sub" /* "</sub" */
  183. %token HL_SUP "<sup" /* "<sup" */
  184. %token HL_C_SUP "</sup" /* "</sup" */
  185. %token HL_TABLE "<table" /* "<table" */
  186. %token HL_C_TABLE "</table" /* "</table" */
  187. %token HL_TD "<td" /* "<td" */
  188. %token HL_C_TD "</td" /* "</td" */
  189. %token HL_TR "<tr" /* "<tr" */
  190. %token HL_C_TR "</tr" /* "</tr" */
  191. %token HL_U "<u" /* "<u" */
  192. %token HL_C_U "</u" /* "</u" */
  193. %token HL_VR "<vr" /* "<vr" */
  194. %token HL_C_VR "</vr" /* "</vr" */
  195. %token HL_SC "/>" /* "/>" */
  196. %token HL_C ">" /* ">" */
  197. %token HL_IS "=" /* "=" */
  198. %token <string>HL_QSTR "string" /* "string" */
  199. %token <string>HL_STR "text" /* attribute variable name */
  200. %token HL_ALIGN "align" /* "align" */
  201. %token HL_BALIGN "balign" /* "balign" */
  202. %token HL_BGCOLOR "bgcolor" /* "bgcolor" */
  203. %token HL_BORDER "border" /* "border" */
  204. %token HL_CELLBORDER "cellborder" /* "cellborder" */
  205. %token HL_CELLPADDING "cellpadding" /* "cellpadding" */
  206. %token HL_CELLSPACING "cellspacing" /* "cellspacing" */
  207. %token HL_COLOR "color" /* "color" */
  208. %token HL_COLUMNS "columns" /* "columns" */
  209. %token HL_COLSPAN "colspan" /* "colspan" */
  210. %token HL_FACE "face" /* "face" */
  211. %token HL_FIXEDSIZE "fixedsize" /* "fixedsize" */
  212. %token HL_GRADIENTANGLE "gradientangle" /* "gradientangle" */
  213. %token HL_HEIGHT "height" /* "height" */
  214. %token HL_HREF "href" /* "href" */
  215. %token HL_ID "id" /* "id" */
  216. %token HL_PORT "port" /* "port" */
  217. %token HL_POINTSIZE "point-size" /* "point-size" */
  218. %token HL_ROWS "rows" /* "rows" */
  219. %token HL_ROWSPAN "rowspan" /* "rowspan" */
  220. %token HL_SCALE "scale" /* "scale" */
  221. %token HL_SIDES "sides" /* "sides" */
  222. %token HL_SRC "src" /* "src" */
  223. %token HL_STYLE "style" /* "style" */
  224. %token HL_TARGET "target" /* "target" */
  225. %token HL_TITLE "title" /* "title" */
  226. %token HL_TOOLTIP "tooltip" /* "tooltip" */
  227. %token HL_VALIGN "valign" /* "valign" */
  228. %token HL_WIDTH "width" /* "width" */
  229. %%
  230. /*
  231. * html label=< > is accepted by dot
  232. * or label=<<!-- comment --> >
  233. * the html label is a list of strings
  234. * or a list of tables with data but
  235. * not both at once.
  236. * a <table> has rows and cols with text like this:
  237. *
  238. * col1 col2 col3 col4
  239. * row1 text1 text2 text3 text4
  240. * row2 text1 text2 text3 text4
  241. * row3 text1 text2 text3 text4
  242. */
  243. begin:
  244. htmlparser
  245. ;
  246. /* html string can be <...> or <html>...</html> */
  247. htmlparser:
  248. HL_HTML HL_C htmlparser2 HL_C_HTML HL_C
  249. | htmlparser2
  250. ;
  251. /* text items or table items */
  252. htmlparser2:
  253. items
  254. | fonttab2 { if (dphl_chk_err ()) { YYERROR; } }
  255. ;
  256. /* one or more text items */
  257. items:
  258. items item { if (dphl_chk_err ()) { YYERROR; } }
  259. | item { if (dphl_chk_err ()) { YYERROR; } }
  260. ;
  261. /* item can be a string
  262. * item can be a newline <br/> or <br></br>
  263. * item can be font with optional parameters
  264. * item can be italics <i> text
  265. * item can be bold <b> text
  266. * item can be underline <u> text
  267. * item can be overline <o> text
  268. * item can be subscript <sub> text
  269. * item can be superscript <sup> text
  270. * item can be strike-through <s> text
  271. */
  272. item:
  273. HL_DATA { dphl_data ($1); }
  274. | HL_BR { dphl_rbr(); } br_arg HL_SC { dphl_ebr (); }
  275. | HL_BR HL_C { dphl_rbr(); } HL_C_BR HL_C { dphl_ebr (); }
  276. | font items HL_C_FONT HL_C { dphl_efont (); }
  277. | italic items HL_C_I HL_C { dphl_ei (); }
  278. | bold items HL_C_B HL_C { dphl_eb (); }
  279. | underline items HL_C_U HL_C { dphl_eu (); }
  280. | overline items HL_C_O HL_C { dphl_eo (); }
  281. | HL_SUB HL_C { dphl_rsub(); } items HL_C_SUB HL_C { dphl_esub (); }
  282. | HL_SUP HL_C { dphl_rsup(); } items HL_C_SUP HL_C { dphl_esup (); }
  283. | HL_S HL_C { dphl_rs(); } items HL_C_S HL_C { dphl_es (); }
  284. ;
  285. /* at least one table statement.
  286. * <font ...></font> args can be empty.
  287. * tab is <table>...</table>
  288. * <table>...</table><table>...</table> is not allowed.
  289. * <td><table>...</table></td><td><table>...</table></td> is allowed.
  290. * table can be italics <i> text
  291. * table can be bold <b> text
  292. * table can be underline <u> text
  293. * table can be overline <o> text
  294. */
  295. fonttab2:
  296. tab
  297. | font tab HL_C_FONT HL_C { dphl_efont(); }
  298. | italic tab HL_C_I HL_C { dphl_ei (); }
  299. | bold tab HL_C_B HL_C { dphl_eb (); }
  300. | underline tab HL_C_U HL_C { dphl_eu (); }
  301. | overline tab HL_C_O HL_C { dphl_eo (); }
  302. ;
  303. font:
  304. HL_FONT { dphl_rfont(); } font_arg HL_C
  305. ;
  306. italic:
  307. HL_I HL_C { dphl_ri(); }
  308. ;
  309. overline:
  310. HL_O HL_C { dphl_ro(); }
  311. ;
  312. bold:
  313. HL_B HL_C { dphl_rb(); }
  314. ;
  315. underline:
  316. HL_U HL_C { dphl_ru(); }
  317. ;
  318. /* optional data before and after a <table></table> tag */
  319. tabe:
  320. HL_DATA { dphl_tabledata ($1); }
  321. | /* empty */
  322. ;
  323. /* a <table> statement can have data around it in tabe which is ignored */
  324. tab:
  325. tabe HL_TABLE { dphl_rtable(); } table_arg HL_C rows HL_C_TABLE HL_C tabe { dphl_etable(); }
  326. ;
  327. /* row can have <hr/> or <hr></hr> */
  328. rows:
  329. row
  330. | rows row
  331. | rows HL_HR HL_SC { dphl_rhr(); } row
  332. | rows HL_HR HL_C HL_C_HR HL_C { dphl_rhr(); } row
  333. ;
  334. /* <tr> cell </tr> */
  335. row:
  336. HL_TR HL_C { dphl_rtr(); } cells HL_C_TR HL_C { dphl_etr (); }
  337. ;
  338. /* cell can have <vr/> or <vr></vr> */
  339. cells:
  340. cell
  341. | cells cell
  342. | cells HL_VR HL_SC { dphl_rvr(); } cell
  343. | cells HL_VR HL_C HL_C_VR HL_C { dphl_rvr(); }cell
  344. ;
  345. /* table data is a string, or more data, or image or nothing
  346. * <td> data </td> or <td></td>
  347. * <img src="foo"/> or <img src="foo"></img> or <img/> or <img></img>
  348. */
  349. cell:
  350. celltd td_arg HL_C htmlparser HL_C_TD HL_C { dphl_etd(0); }
  351. | celltd td_arg HL_C cellimg img_arg HL_SC HL_C_TD HL_C { dphl_eimg(); dphl_etd(1); }
  352. | celltd td_arg HL_C cellimg img_arg HL_C HL_C_IMG HL_C HL_C_TD HL_C { dphl_eimg(); dphl_etd(1); }
  353. | celltd td_arg HL_C HL_C_TD HL_C { dphl_etd(2); }
  354. ;
  355. cellimg:
  356. HL_IMG { dphl_rimg(); }
  357. ;
  358. celltd:
  359. HL_TD { dphl_rtd(); }
  360. ;
  361. /* for <table> wit optional args
  362. * int align="center|left|right"
  363. * int bgcolor="colorname"
  364. * int border="int-value"
  365. * int cellborder="int-value"
  366. * int cellpadding="int-value"
  367. * int cellspacing="int-value"
  368. * int color="colorname"
  369. * char *) columns="string" only "*" allowed
  370. * int fixedsize="true|false"
  371. * int gradientangle="int-value"
  372. * int height="int-value"
  373. * (char *) href="string"
  374. * (char *) id="string"
  375. * (char *) port="string"
  376. * (char *) rows="string" only "*" allowed
  377. * (char *) sides="string"
  378. * (char *) style="string"
  379. * (char *) target="string"
  380. * (char *) title="string"
  381. * int valign="middle|bottom|top"
  382. * int width="int-value"
  383. */
  384. table_arg:
  385. table_arg table_1arg
  386. | /* empty */
  387. ;
  388. table_1arg:
  389. HL_ALIGN HL_IS HL_QSTR { if (dphl_chk_align ($3,T_TABLE)) { YYERROR; } }
  390. | HL_BGCOLOR HL_IS HL_QSTR { if (dphl_chk_bgcolor ($3,T_TABLE)) { YYERROR; } }
  391. | HL_BORDER HL_IS HL_QSTR { if (dphl_chk_border ($3,T_TABLE)) { YYERROR; } }
  392. | HL_CELLBORDER HL_IS HL_QSTR { if (dphl_chk_cellborder ($3)) { YYERROR; } }
  393. | HL_CELLPADDING HL_IS HL_QSTR { if (dphl_chk_cellpadding ($3,T_TABLE)) { YYERROR; } }
  394. | HL_CELLSPACING HL_IS HL_QSTR { if (dphl_chk_cellspacing ($3,T_TABLE)) { YYERROR; } }
  395. | HL_COLOR HL_IS HL_QSTR { if (dphl_chk_color ($3,T_TABLE)) { YYERROR; } }
  396. | HL_COLUMNS HL_IS HL_QSTR { if (dphl_chk_columns ($3)) { YYERROR; } }
  397. | HL_FIXEDSIZE HL_IS HL_QSTR { if (dphl_chk_fixedsize ($3,T_TABLE)) { YYERROR; } }
  398. | HL_GRADIENTANGLE HL_IS HL_QSTR { if (dphl_chk_gradientangle ($3,T_TABLE)) { YYERROR; } }
  399. | HL_HEIGHT HL_IS HL_QSTR { if (dphl_chk_height ($3,T_TABLE)) { YYERROR; } }
  400. | HL_HREF HL_IS HL_QSTR { if (dphl_chk_href ($3,T_TABLE)) { YYERROR; } }
  401. | HL_ID HL_IS HL_QSTR { if (dphl_chk_id ($3,T_TABLE)) { YYERROR; } }
  402. | HL_PORT HL_IS HL_QSTR { if (dphl_chk_port ($3,T_TABLE)) { YYERROR; } }
  403. | HL_ROWS HL_IS HL_QSTR { if (dphl_chk_rows ($3)) { YYERROR; } }
  404. | HL_SIDES HL_IS HL_QSTR { if (dphl_chk_sides ($3,T_TABLE)) { YYERROR; } }
  405. | HL_STYLE HL_IS HL_QSTR { if (dphl_chk_style ($3,T_TABLE)) { YYERROR; } }
  406. | HL_TARGET HL_IS HL_QSTR { if (dphl_chk_target ($3,T_TABLE)) { YYERROR; } }
  407. | HL_TITLE HL_IS HL_QSTR { if (dphl_chk_title ($3,T_TABLE)) { YYERROR; } }
  408. | HL_TOOLTIP HL_IS HL_QSTR { if (dphl_chk_title ($3,T_TABLE)) { YYERROR; } }
  409. | HL_VALIGN HL_IS HL_QSTR { if (dphl_chk_valign ($3,T_TABLE)) { YYERROR; } }
  410. | HL_WIDTH HL_IS HL_QSTR { if (dphl_chk_width ($3,T_TABLE)) { YYERROR; } }
  411. | HL_STR HL_IS HL_QSTR { dphl_attr_huh ((char *) "<table>", $1, $3); }
  412. ;
  413. /* for <td> with optional args
  414. * int align="center|left|right|text"
  415. * int balign="center|left|right"
  416. * int bgcolor="colorname"
  417. * int border="int-value"
  418. * int cellpadding="int-value"
  419. * int cellspacing="int-value"
  420. * int color="colorname"
  421. * int colspan="int-value"
  422. * int fixedsize="true|false"
  423. * int gradientangle="int-value"
  424. * int height="int-value"
  425. * (char *) href="string"
  426. * (char *) id="string"
  427. * (char *) port="string"
  428. * int rowspan="int-value"
  429. * (char *) sides="string"
  430. * (char *) style="string"
  431. * (char *) target="string"
  432. * (char *) title="string"
  433. * int valign="middle|bottom|top"
  434. * int width="int-value"
  435. */
  436. td_arg:
  437. td_arg td_1arg
  438. | /* empty */
  439. ;
  440. td_1arg:
  441. HL_ALIGN HL_IS HL_QSTR { if (dphl_chk_align ($3,T_TD)) { YYERROR; } }
  442. | HL_BALIGN HL_IS HL_QSTR { if (dphl_chk_balign ($3)) { YYERROR; } }
  443. | HL_BGCOLOR HL_IS HL_QSTR { if (dphl_chk_bgcolor ($3,T_TD)) { YYERROR; } }
  444. | HL_BORDER HL_IS HL_QSTR { if (dphl_chk_border ($3,T_TD)) { YYERROR; } }
  445. | HL_CELLPADDING HL_IS HL_QSTR { if (dphl_chk_cellpadding ($3,T_TD)) { YYERROR; } }
  446. | HL_CELLSPACING HL_IS HL_QSTR { if (dphl_chk_cellspacing ($3,T_TD)) { YYERROR; } }
  447. | HL_COLOR HL_IS HL_QSTR { if (dphl_chk_color ($3,T_TD)) { YYERROR; } }
  448. | HL_COLSPAN HL_IS HL_QSTR { if (dphl_chk_colspan ($3)) { YYERROR; } }
  449. | HL_FIXEDSIZE HL_IS HL_QSTR { if (dphl_chk_fixedsize ($3,T_TD)) { YYERROR; } }
  450. | HL_GRADIENTANGLE HL_IS HL_QSTR { if (dphl_chk_gradientangle ($3,T_TD)) { YYERROR; } }
  451. | HL_HEIGHT HL_IS HL_QSTR { if (dphl_chk_height ($3,T_TD)) { YYERROR; } }
  452. | HL_HREF HL_IS HL_QSTR { if (dphl_chk_href ($3,T_TD)) { YYERROR; } }
  453. | HL_ID HL_IS HL_QSTR { if (dphl_chk_id ($3,T_TD)) { YYERROR; } }
  454. | HL_PORT HL_IS HL_QSTR { if (dphl_chk_port ($3,T_TD)) { YYERROR; } }
  455. | HL_ROWSPAN HL_IS HL_QSTR { if (dphl_chk_rowspan ($3)) { YYERROR; } }
  456. | HL_SIDES HL_IS HL_QSTR { if (dphl_chk_sides ($3,T_TD)) { YYERROR; } }
  457. | HL_STYLE HL_IS HL_QSTR { if (dphl_chk_sides ($3,T_TD)) { YYERROR; } }
  458. | HL_TARGET HL_IS HL_QSTR { if (dphl_chk_target ($3,T_TD)) { YYERROR; } }
  459. | HL_TITLE HL_IS HL_QSTR { if (dphl_chk_title ($3,T_TD)) { YYERROR; } }
  460. | HL_TOOLTIP HL_IS HL_QSTR { if (dphl_chk_title ($3,T_TD)) { YYERROR; } }
  461. | HL_VALIGN HL_IS HL_QSTR { if (dphl_chk_valign ($3,T_TD)) { YYERROR; } }
  462. | HL_WIDTH HL_IS HL_QSTR { if (dphl_chk_width ($3,T_TD)) { YYERROR; } }
  463. | HL_STR HL_IS HL_QSTR { dphl_attr_huh ((char *) "<td>", $1, $3); }
  464. ;
  465. /* for <img> with optional args but src must be set
  466. * int scale="false|true|width|height|both"
  467. * (char *) src="imagename"
  468. * <img src=""/> is skipped and ignored.
  469. */
  470. img_arg:
  471. img_arg img_1arg
  472. | /* empty */
  473. ;
  474. img_1arg:
  475. HL_SCALE HL_IS HL_QSTR { if (dphl_chk_scale ($3)) { YYERROR; } }
  476. | HL_SRC HL_IS HL_QSTR { if (dphl_chk_src ($3)) { YYERROR; } }
  477. | HL_STR HL_IS HL_QSTR { dphl_attr_huh ((char *) "<img>", $1, $3); }
  478. ;
  479. /* for <br> with optional arg
  480. * int align="center|left|right"
  481. */
  482. br_arg:
  483. br_arg br_1arg
  484. | /* empty */
  485. ;
  486. br_1arg:
  487. HL_ALIGN HL_IS HL_QSTR { if (dphl_chk_align ($3,T_BR)) { YYERROR; } }
  488. | HL_STR HL_IS HL_QSTR { dphl_attr_huh ((char *) "<br>", $1, $3); }
  489. ;
  490. /* for <font> with optional args
  491. * int color="colorname"
  492. * (char *) face="fontname"
  493. * int point-size="int-number"
  494. */
  495. font_arg:
  496. font_arg font_1arg
  497. | /* empty */
  498. ;
  499. font_1arg:
  500. HL_COLOR HL_IS HL_QSTR { if (dphl_chk_color ($3,T_FONT)) { YYERROR; } }
  501. | HL_FACE HL_IS HL_QSTR { if (dphl_chk_face ($3)) { YYERROR; } }
  502. | HL_POINTSIZE HL_IS HL_QSTR { if (dphl_chk_pointsize ($3)) { YYERROR; } }
  503. | HL_STR HL_IS HL_QSTR { dphl_attr_huh ((char *) "<font>", $1, $3); }
  504. ;
  505. %%
  506. /* end */