PageRenderTime 54ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/graphviz-cmake/lib/common/htmlparse.y

https://bitbucket.org/akristmann/custom_build
Happy | 598 lines | 503 code | 95 blank | 0 comment | 0 complexity | 25562fc67fe7c53c2d2d7762315d2e4a MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, EPL-1.0, CPL-1.0, BSD-3-Clause, LGPL-2.1
  1. /* $Id: htmlparse.y,v 1.22 2011/04/05 19:34:59 dperry Exp $ $Revision: 1.22 $ */
  2. /* vim:set shiftwidth=4 ts=8: */
  3. /*************************************************************************
  4. * Copyright (c) 2011 AT&T Intellectual Property
  5. * All rights reserved. This program and the accompanying materials
  6. * are made available under the terms of the Eclipse Public License v1.0
  7. * which accompanies this distribution, and is available at
  8. * http://www.eclipse.org/legal/epl-v10.html
  9. *
  10. * Contributors: See CVS logs. Details at http://www.graphviz.org/
  11. *************************************************************************/
  12. %{
  13. #include "render.h"
  14. #include "htmltable.h"
  15. #include "htmllex.h"
  16. extern int yyparse(void);
  17. typedef struct sfont_t {
  18. htmlfont_t *cfont;
  19. struct sfont_t *pfont;
  20. } sfont_t;
  21. static struct {
  22. htmllabel_t* lbl; /* Generated label */
  23. htmltbl_t* tblstack; /* Stack of tables maintained during parsing */
  24. Dt_t* fitemList; /* Dictionary for font text items */
  25. Dt_t* fparaList;
  26. agxbuf* str; /* Buffer for text */
  27. sfont_t* fontstack;
  28. } HTMLstate;
  29. /* free_ritem:
  30. * Free row. This closes and frees row's list, then
  31. * the pitem itself is freed.
  32. */
  33. static void
  34. free_ritem(Dt_t* d, pitem* p,Dtdisc_t* ds)
  35. {
  36. dtclose (p->u.rp);
  37. free (p);
  38. }
  39. /* free_item:
  40. * Generic Dt free. Only frees container, assuming contents
  41. * have been copied elsewhere.
  42. */
  43. static void
  44. free_item(Dt_t* d, void* p,Dtdisc_t* ds)
  45. {
  46. free (p);
  47. }
  48. /* cleanTbl:
  49. * Clean up table if error in parsing.
  50. */
  51. static void
  52. cleanTbl (htmltbl_t* tp)
  53. {
  54. dtclose (tp->u.p.rows);
  55. free_html_data (&tp->data);
  56. free (tp);
  57. }
  58. /* cleanCell:
  59. * Clean up cell if error in parsing.
  60. */
  61. static void
  62. cleanCell (htmlcell_t* cp)
  63. {
  64. if (cp->child.kind == HTML_TBL) cleanTbl (cp->child.u.tbl);
  65. else if (cp->child.kind == HTML_TEXT) free_html_text (cp->child.u.txt);
  66. free_html_data (&cp->data);
  67. free (cp);
  68. }
  69. /* free_citem:
  70. * Free cell item during parsing. This frees cell and pitem.
  71. */
  72. static void
  73. free_citem(Dt_t* d, pitem* p,Dtdisc_t* ds)
  74. {
  75. cleanCell (p->u.cp);
  76. free (p);
  77. }
  78. static Dtdisc_t rowDisc = {
  79. offsetof(pitem,u),
  80. sizeof(void*),
  81. offsetof(pitem,link),
  82. NIL(Dtmake_f),
  83. (Dtfree_f)free_ritem,
  84. NIL(Dtcompar_f),
  85. NIL(Dthash_f),
  86. NIL(Dtmemory_f),
  87. NIL(Dtevent_f)
  88. };
  89. static Dtdisc_t cellDisc = {
  90. offsetof(pitem,u),
  91. sizeof(void*),
  92. offsetof(pitem,link),
  93. NIL(Dtmake_f),
  94. (Dtfree_f)free_item,
  95. NIL(Dtcompar_f),
  96. NIL(Dthash_f),
  97. NIL(Dtmemory_f),
  98. NIL(Dtevent_f)
  99. };
  100. typedef struct {
  101. Dtlink_t link;
  102. textpara_t ti;
  103. } fitem;
  104. typedef struct {
  105. Dtlink_t link;
  106. htextpara_t lp;
  107. } fpara;
  108. static void
  109. free_fitem(Dt_t* d, fitem* p, Dtdisc_t* ds)
  110. {
  111. if (p->ti.str)
  112. free (p->ti.str);
  113. if (p->ti.font)
  114. free_html_font (p->ti.font);
  115. free (p);
  116. }
  117. static void
  118. free_fpara(Dt_t* d, fpara* p, Dtdisc_t* ds)
  119. {
  120. textpara_t* ti;
  121. if (p->lp.nitems) {
  122. int i;
  123. ti = p->lp.items;
  124. for (i = 0; i < p->lp.nitems; i++) {
  125. if (ti->str) free (ti->str);
  126. if (ti->font) free_html_font (ti->font);
  127. ti++;
  128. }
  129. free (p->lp.items);
  130. }
  131. free (p);
  132. }
  133. static Dtdisc_t fstrDisc = {
  134. 0,
  135. 0,
  136. offsetof(fitem,link),
  137. NIL(Dtmake_f),
  138. (Dtfree_f)free_item,
  139. NIL(Dtcompar_f),
  140. NIL(Dthash_f),
  141. NIL(Dtmemory_f),
  142. NIL(Dtevent_f)
  143. };
  144. static Dtdisc_t fparaDisc = {
  145. 0,
  146. 0,
  147. offsetof(fpara,link),
  148. NIL(Dtmake_f),
  149. (Dtfree_f)free_item,
  150. NIL(Dtcompar_f),
  151. NIL(Dthash_f),
  152. NIL(Dtmemory_f),
  153. NIL(Dtevent_f)
  154. };
  155. /* dupFont:
  156. */
  157. static htmlfont_t *
  158. dupFont (htmlfont_t *f)
  159. {
  160. if (f) f->cnt++;
  161. return f;
  162. }
  163. /* appendFItemList:
  164. * Append a new fitem to the list.
  165. */
  166. static void
  167. appendFItemList (agxbuf *ag)
  168. {
  169. fitem *fi = NEW(fitem);
  170. fi->ti.str = strdup(agxbuse(ag));
  171. fi->ti.font = dupFont (HTMLstate.fontstack->cfont);
  172. dtinsert(HTMLstate.fitemList, fi);
  173. }
  174. /* appendFLineList:
  175. */
  176. static void
  177. appendFLineList (int v)
  178. {
  179. int cnt;
  180. fpara *ln = NEW(fpara);
  181. fitem *fi;
  182. Dt_t *ilist = HTMLstate.fitemList;
  183. cnt = dtsize(ilist);
  184. ln->lp.nitems = cnt;
  185. ln->lp.just = v;
  186. if (cnt) {
  187. int i = 0;
  188. ln->lp.items = N_NEW(cnt, textpara_t);
  189. fi = (fitem*)dtflatten(ilist);
  190. for (; fi; fi = (fitem*)dtlink(fitemList,(Dtlink_t*)fi)) {
  191. ln->lp.items[i] = fi->ti;
  192. i++;
  193. }
  194. }
  195. dtclear(ilist);
  196. dtinsert(HTMLstate.fparaList, ln);
  197. }
  198. static htmltxt_t*
  199. mkText(void)
  200. {
  201. int cnt;
  202. Dt_t * ipara = HTMLstate.fparaList;
  203. fpara *fl ;
  204. htmltxt_t *hft = NEW(htmltxt_t);
  205. if (dtsize (HTMLstate.fitemList))
  206. appendFLineList (UNSET_ALIGN);
  207. cnt = dtsize(ipara);
  208. hft->nparas = cnt;
  209. if (cnt) {
  210. int i = 0;
  211. hft->paras = N_NEW(cnt,htextpara_t);
  212. for(fl=(fpara *)dtfirst(ipara); fl; fl=(fpara *)dtnext(ipara,fl)) {
  213. hft->paras[i] = fl->lp;
  214. i++;
  215. }
  216. }
  217. dtclear(ipara);
  218. return hft;
  219. }
  220. /* addRow:
  221. * Add new cell row to current table.
  222. */
  223. static void addRow (void)
  224. {
  225. Dt_t* dp = dtopen(&cellDisc, Dtqueue);
  226. htmltbl_t* tbl = HTMLstate.tblstack;
  227. pitem* sp = NEW(pitem);
  228. sp->u.rp = dp;
  229. dtinsert (tbl->u.p.rows, sp);
  230. }
  231. /* setCell:
  232. * Set cell body and type and attach to row
  233. */
  234. static void setCell (htmlcell_t* cp, void* obj, int kind)
  235. {
  236. pitem* sp = NEW(pitem);
  237. htmltbl_t* tbl = HTMLstate.tblstack;
  238. pitem* rp = (pitem*)dtlast (tbl->u.p.rows);
  239. Dt_t* row = rp->u.rp;
  240. sp->u.cp = cp;
  241. dtinsert (row, sp);
  242. cp->child.kind = kind;
  243. if(kind == HTML_TEXT)
  244. cp->child.u.txt = (htmltxt_t*)obj;
  245. else if (kind == HTML_IMAGE)
  246. cp->child.u.img = (htmlimg_t*)obj;
  247. else
  248. cp->child.u.tbl = (htmltbl_t*)obj;
  249. }
  250. /* mkLabel:
  251. * Create label, given body and type.
  252. */
  253. static htmllabel_t* mkLabel (void* obj, int kind)
  254. {
  255. htmllabel_t* lp = NEW(htmllabel_t);
  256. lp->kind = kind;
  257. if (kind == HTML_TEXT)
  258. lp->u.txt = (htmltxt_t*)obj;
  259. else
  260. lp->u.tbl = (htmltbl_t*)obj;
  261. return lp;
  262. }
  263. /* freeFontstack:
  264. * Free all stack items but the last, which is
  265. * put on artificially during in parseHTML.
  266. */
  267. static void
  268. freeFontstack(void)
  269. {
  270. sfont_t* s;
  271. sfont_t* next;
  272. for (s = HTMLstate.fontstack; (next = s->pfont); s = next) {
  273. free_html_font (s->cfont);
  274. free(s);
  275. }
  276. }
  277. /* cleanup:
  278. * Called on error. Frees resources allocated during parsing.
  279. * This includes a label, plus a walk down the stack of
  280. * tables. Note that we use the free_citem function to actually
  281. * free cells.
  282. */
  283. static void cleanup (void)
  284. {
  285. htmltbl_t* tp = HTMLstate.tblstack;
  286. htmltbl_t* next;
  287. if (HTMLstate.lbl) {
  288. free_html_label (HTMLstate.lbl,1);
  289. HTMLstate.lbl = NULL;
  290. }
  291. cellDisc.freef = (Dtfree_f)free_citem;
  292. while (tp) {
  293. next = tp->u.p.prev;
  294. cleanTbl (tp);
  295. tp = next;
  296. }
  297. cellDisc.freef = (Dtfree_f)free_item;
  298. fstrDisc.freef = (Dtfree_f)free_fitem;
  299. dtclear (HTMLstate.fitemList);
  300. fstrDisc.freef = (Dtfree_f)free_item;
  301. fparaDisc.freef = (Dtfree_f)free_fpara;
  302. dtclear (HTMLstate.fparaList);
  303. fparaDisc.freef = (Dtfree_f)free_item;
  304. freeFontstack();
  305. }
  306. /* nonSpace:
  307. * Return 1 if s contains a non-space character.
  308. */
  309. static int nonSpace (char* s)
  310. {
  311. char c;
  312. while ((c = *s++)) {
  313. if (c != ' ') return 1;
  314. }
  315. return 0;
  316. }
  317. /* pushFont:
  318. * Fonts are allocated in the lexer.
  319. */
  320. static void
  321. pushFont (htmlfont_t *f)
  322. {
  323. sfont_t *ft = NEW(sfont_t);
  324. htmlfont_t* curfont = HTMLstate.fontstack->cfont;
  325. if (curfont) {
  326. if (!f->color && curfont->color)
  327. f->color = strdup(curfont->color);
  328. if ((f->size < 0.0) && (curfont->size >= 0.0))
  329. f->size = curfont->size;
  330. if (!f->name && curfont->name)
  331. f->name = strdup(curfont->name);
  332. if (curfont->flags)
  333. f->flags |= curfont->flags;
  334. }
  335. ft->cfont = dupFont (f);
  336. ft->pfont = HTMLstate.fontstack;
  337. HTMLstate.fontstack = ft;
  338. }
  339. /* popFont:
  340. */
  341. static void
  342. popFont (void)
  343. {
  344. sfont_t* curfont = HTMLstate.fontstack;
  345. sfont_t* prevfont = curfont->pfont;
  346. free_html_font (curfont->cfont);
  347. free (curfont);
  348. HTMLstate.fontstack = prevfont;
  349. }
  350. %}
  351. %union {
  352. int i;
  353. htmltxt_t* txt;
  354. htmlcell_t* cell;
  355. htmltbl_t* tbl;
  356. htmlfont_t* font;
  357. htmlimg_t* img;
  358. }
  359. %token T_end_br T_end_img T_row T_end_row T_html T_end_html
  360. %token T_end_table T_end_cell T_end_font T_string T_error
  361. %token T_n_italic T_n_bold T_n_underline T_n_sup T_n_sub
  362. %token <i> T_BR T_br
  363. %token <img> T_IMG T_img
  364. %token <tbl> T_table
  365. %token <cell> T_cell
  366. %token <font> T_font T_italic T_bold T_underline T_sup T_sub
  367. %type <txt> fonttext
  368. %type <i> br
  369. %type <tbl> table fonttable
  370. %type <img> image
  371. %start html
  372. %%
  373. html : T_html fonttext T_end_html { HTMLstate.lbl = mkLabel($2,HTML_TEXT); }
  374. | T_html fonttable T_end_html { HTMLstate.lbl = mkLabel($2,HTML_TBL); }
  375. | error { cleanup(); YYABORT; }
  376. ;
  377. fonttext : text { $$ = mkText(); }
  378. ;
  379. text : text textitem
  380. | textitem
  381. ;
  382. textitem : string { appendFItemList(HTMLstate.str);}
  383. | br {appendFLineList($1);}
  384. | font text n_font
  385. | italic text n_italic
  386. | underline text n_underline
  387. | bold text n_bold
  388. | sup text n_sup
  389. | sub text n_sub
  390. ;
  391. font : T_font { pushFont ($1); }
  392. ;
  393. n_font : T_end_font { popFont (); }
  394. ;
  395. italic : T_italic {pushFont($1);}
  396. ;
  397. n_italic : T_n_italic {popFont();}
  398. ;
  399. bold : T_bold {pushFont($1);}
  400. ;
  401. n_bold : T_n_bold {popFont();}
  402. ;
  403. underline : T_underline {pushFont($1);}
  404. ;
  405. n_underline : T_n_underline {popFont();}
  406. ;
  407. sup : T_sup {pushFont($1);}
  408. ;
  409. n_sup : T_n_sup {popFont();}
  410. ;
  411. sub : T_sub {pushFont($1);}
  412. ;
  413. n_sub : T_n_sub {popFont();}
  414. ;
  415. br : T_br T_end_br { $$ = $1; }
  416. | T_BR { $$ = $1; }
  417. ;
  418. string : T_string
  419. | string T_string
  420. ;
  421. table : opt_space T_table {
  422. if (nonSpace(agxbuse(HTMLstate.str))) {
  423. yyerror ("Syntax error: non-space string used before <TABLE>");
  424. cleanup(); YYABORT;
  425. }
  426. $2->u.p.prev = HTMLstate.tblstack;
  427. $2->u.p.rows = dtopen(&rowDisc, Dtqueue);
  428. HTMLstate.tblstack = $2;
  429. $2->font = dupFont (HTMLstate.fontstack->cfont);
  430. $<tbl>$ = $2;
  431. }
  432. rows T_end_table opt_space {
  433. if (nonSpace(agxbuse(HTMLstate.str))) {
  434. yyerror ("Syntax error: non-space string used after </TABLE>");
  435. cleanup(); YYABORT;
  436. }
  437. $$ = HTMLstate.tblstack;
  438. HTMLstate.tblstack = HTMLstate.tblstack->u.p.prev;
  439. }
  440. ;
  441. fonttable : table { $$ = $1; }
  442. | font table n_font { $$=$2; }
  443. | italic table n_italic { $$=$2; }
  444. | underline table n_underline { $$=$2; }
  445. | bold table n_bold { $$=$2; }
  446. ;
  447. opt_space : string
  448. | /* empty*/
  449. ;
  450. rows : row
  451. | rows row
  452. ;
  453. row : T_row { addRow (); } cells T_end_row
  454. ;
  455. cells : cell
  456. | cells cell
  457. ;
  458. cell : T_cell fonttable { setCell($1,$2,HTML_TBL); } T_end_cell
  459. | T_cell fonttext { setCell($1,$2,HTML_TEXT); } T_end_cell
  460. | T_cell image { setCell($1,$2,HTML_IMAGE); } T_end_cell
  461. | T_cell { setCell($1,mkText(),HTML_TEXT); } T_end_cell
  462. ;
  463. image : T_img T_end_img { $$ = $1; }
  464. | T_IMG { $$ = $1; }
  465. ;
  466. %%
  467. /* parseHTML:
  468. * Return parsed label or NULL if failure.
  469. * Set warn to 0 on success; 1 for warning message; 2 if no expat.
  470. */
  471. htmllabel_t*
  472. parseHTML (char* txt, int* warn, int charset)
  473. {
  474. unsigned char buf[SMALLBUF];
  475. agxbuf str;
  476. htmllabel_t* l;
  477. sfont_t dfltf;
  478. dfltf.cfont = NULL;
  479. dfltf.pfont = NULL;
  480. HTMLstate.fontstack = &dfltf;
  481. HTMLstate.tblstack = 0;
  482. HTMLstate.lbl = 0;
  483. HTMLstate.fitemList = dtopen(&fstrDisc, Dtqueue);
  484. HTMLstate.fparaList = dtopen(&fparaDisc, Dtqueue);
  485. agxbinit (&str, SMALLBUF, buf);
  486. HTMLstate.str = &str;
  487. if (initHTMLlexer (txt, &str, charset)) {/* failed: no libexpat - give up */
  488. *warn = 2;
  489. l = NULL;
  490. }
  491. else {
  492. yyparse();
  493. *warn = clearHTMLlexer ();
  494. l = HTMLstate.lbl;
  495. }
  496. dtclose (HTMLstate.fitemList);
  497. dtclose (HTMLstate.fparaList);
  498. HTMLstate.fitemList = NULL;
  499. HTMLstate.fparaList = NULL;
  500. HTMLstate.fontstack = NULL;
  501. agxbfree (&str);
  502. return l;
  503. }