dp.c 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947
  1. /*
  2. * Copyright 2021
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. * SPDX-License-Identifier: GPL-3.0+
  18. * License-Filename: LICENSE
  19. */
  20. /*
  21. To improve this C there are guides for mission-critical software
  22. and similar guides collected at
  23. https://github.com/abougouffa/awesome-coding-standards
  24. This are few rules from nasa at
  25. https://en.wikipedia.org/wiki/The_Power_of_10:_Rules_for_Developing_Safety-Critical_Code
  26. Avoid complex flow constructs, such as goto and recursion.
  27. All loops must have fixed bounds. This prevents runaway code.
  28. Avoid heap memory allocation.
  29. Restrict functions to a single printed page.
  30. Use a minimum of two runtime assertions per function.
  31. Restrict the scope of data to the smallest possible.
  32. Check the return value of all non-void functions, or cast to void to indicate the return value is useless.
  33. Use the preprocessor sparingly.
  34. Limit pointer use to a single dereference, and do not use function pointers.
  35. Compile with all possible warnings active; all warnings should then be addressed before release of the software.
  36. */
  37. #include "config.h"
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <strings.h>
  42. #include <zlib.h>
  43. #include "splay-tree.h"
  44. #include "main.h"
  45. #include "dp.h"
  46. #include "dpus.h"
  47. #include "dpun.h"
  48. #include "dpmisc.h"
  49. #include "dpcolor.h"
  50. #include "lex.yy.h"
  51. #include "dot.tab.h"
  52. #include "dpn.h"
  53. #include "dpe.h"
  54. #include "dpg.h"
  55. #include "dpmem.h"
  56. char dp_errmsg[256];
  57. int dp_cclass = 0;
  58. int dp_sgnr = 0; /* uniq graph number */
  59. /* all nodes */
  60. struct dpnlink *dp_anodes = NULL;
  61. static struct dpnlink *dp_anodesend = NULL;
  62. /* all edges */
  63. struct dpelink *dp_aedges = NULL;
  64. static struct dpelink *dp_aedgesend = NULL;
  65. /* all edge points */
  66. static struct dpeplink *dp_epl = NULL;
  67. static struct dpeplink *dp_eplend = NULL;
  68. /* all head edge points */
  69. static struct dpeplink *dp_headepl = NULL;
  70. static struct dpeplink *dp_headeplend = NULL;
  71. /* all subgraphs but not rootgraph */
  72. static struct dpglink *dp_asubg = NULL;
  73. static struct dpglink *dp_asubgend = NULL;
  74. /* tmp edges during edge building */
  75. static struct dptelink *dp_tmpe = NULL;
  76. static struct dptelink *dp_tmpeend = NULL;
  77. /* edge nesting */
  78. static int dp_enest = 0;
  79. /* node id number */
  80. static int dp_nodenum = 0;
  81. /* edge numbers */
  82. static int dp_edgenum = 0;
  83. /* splay tree with nested graphs */
  84. static splay_tree dpgraphs = NULL;
  85. /* the root graph */
  86. struct dpgraph *dp_groot = NULL;
  87. /* the current graph */
  88. struct dpgraph *dp_curgraph = NULL;
  89. struct dpnode *dp_curnode = NULL;
  90. struct dpedge *dp_curedge = NULL;
  91. static void dp_nodelink(struct dpnode *node, int mode);
  92. static void dp_eplink(struct dpepoint *epoint);
  93. static void dp_endel_n2n(struct dpepoint *fn, struct dpepoint *tn);
  94. static void dp_endel_n2g(struct dpepoint *fn, struct dpepoint *tn);
  95. static void dp_endel_g2n(struct dpepoint *fn, struct dpepoint *tn);
  96. static void dp_endel_g2g(struct dpepoint *fn, struct dpepoint *tn);
  97. static void dp_clredges(void);
  98. /* return 0 if no errors, >0 at error */
  99. int dp_chkerr(void)
  100. {
  101. return ((int)strlen(dp_errmsg));
  102. }
  103. /* */
  104. static void dp_pushgraph(struct dpgraph *g)
  105. {
  106. int ix = 0;
  107. splay_tree_node spn;
  108. spn = splay_tree_max(dpgraphs);
  109. if (spn == NULL) {
  110. ix = 0;
  111. } else {
  112. ix = (int)spn->key;
  113. ix++;
  114. }
  115. splay_tree_insert(dpgraphs, (splay_tree_key) ix, (splay_tree_value) g);
  116. dp_curgraph = g;
  117. return;
  118. }
  119. /* */
  120. static struct dpgraph *dp_pullgraph(void)
  121. {
  122. struct dpgraph *ret = NULL;
  123. int ix = 0;
  124. splay_tree_node spn = NULL;
  125. spn = splay_tree_max(dpgraphs);
  126. if (spn == NULL) {
  127. printf("dot %s(): shouldnothappen near line %d\n", __func__, yylineno);
  128. return (NULL);
  129. }
  130. ix = (int)spn->key;
  131. if ((ix - 1) < 0) {
  132. /* remove last element ix=0 */
  133. splay_tree_remove(dpgraphs, (splay_tree_key) ix);
  134. printf("dot %s(): removed last element near line %d\n", __func__, yylineno);
  135. return (NULL);
  136. }
  137. spn = splay_tree_lookup(dpgraphs, (splay_tree_key) (ix - 1));
  138. if (spn == NULL) {
  139. /* shouldnothappen */
  140. printf("dot %s(): could not find %d element near line %d\n", __func__, (ix - 1), yylineno);
  141. ret = NULL;
  142. } else {
  143. ret = (struct dpgraph *)spn->value;
  144. splay_tree_remove(dpgraphs, (splay_tree_key) ix);
  145. }
  146. dp_curgraph = ret;
  147. return (ret);
  148. }
  149. /* at start of graph, etype is -- or -> */
  150. void dp_sg(char *etype, char *gname)
  151. {
  152. memset(dp_errmsg, 0, 256);
  153. /* node id number */
  154. dp_nodenum = 0;
  155. /* edge numbers */
  156. dp_edgenum = 0;
  157. /* graph numbers */
  158. dp_sgnr = 0;
  159. /* edge nesting */
  160. dp_enest = 0;
  161. dpgraphs = splay_tree_new(splay_tree_compare_ints, NULL, NULL);
  162. /* fresh root graph */
  163. dp_groot = (struct dpgraph *)dp_calloc(1, sizeof(struct dpgraph));
  164. /* root graph has uniq number 0 */
  165. dp_groot->nr = dp_sgnr;
  166. dp_sgnr++;
  167. dp_groot->type = DP_SG_ROOT;
  168. /* set factory defaults */
  169. dp_graphfdef(dp_groot);
  170. if (gname == NULL) {
  171. /* no graphname, make it "" */
  172. dp_groot->graphname = dp_uniqstr((char *)"");
  173. } else {
  174. dp_groot->graphname = gname;
  175. }
  176. /* type of edge, -- or -> */
  177. dp_groot->yylineno = yylineno;
  178. dp_groot->etype = etype;
  179. dp_groot->rootedon = NULL;
  180. dp_groot->tag = DP_TGRAPH;
  181. /* splay with node/edge/graph parsed settings */
  182. dp_groot->gattr = splay_tree_new(splay_tree_compare_strings, NULL, NULL);
  183. dp_groot->nattr = splay_tree_new(splay_tree_compare_strings, NULL, NULL);
  184. dp_groot->eattr = splay_tree_new(splay_tree_compare_strings, NULL, NULL);
  185. /* node with default settings */
  186. dp_groot->defnode = (struct dpnode *)dp_calloc(1, sizeof(struct dpnode));
  187. /* set factory defaults */
  188. dp_nodefdef(dp_groot->defnode);
  189. dp_groot->defnode->name = dp_uniqstr((char *)"default");
  190. dp_groot->defnode->label = dp_uniqstr((char *)"default");
  191. /* edge with default settings */
  192. dp_groot->defedge = (struct dpedge *)dp_calloc(1, sizeof(struct dpedge));
  193. /* set factory defaults */
  194. dp_edgefdef(dp_groot->defedge);
  195. /* add root to array of graphs */
  196. dp_pushgraph(dp_groot);
  197. dp_cclass = DP_TGRAPH;
  198. return;
  199. }
  200. /* subgraph with optional name
  201. * types of subgraphs:
  202. * #define DP_SG_ROOT 0 * root graph type
  203. * #define DP_SG_CO 1 * compound subgraph {}
  204. * #define DP_SG_NM 2 * named subgrph
  205. * #define DP_SG_CL 3 * cluster subgraph
  206. * #define DP_SG_NN 4 * no name subgraph
  207. */
  208. void dp_nsubg(struct dpgraph *sg, char *gname, int type)
  209. {
  210. if (sg == NULL) {
  211. /* shouldnothappen */
  212. return;
  213. }
  214. if (gname == NULL) {
  215. /* type is now DP_SG_CO (compound) or DP_SG_NN (no-name) */
  216. sg->type = type;
  217. /* no graphname, make it "" */
  218. sg->graphname = NULL;
  219. } else {
  220. /* name or "" */
  221. sg->graphname = gname;
  222. sg->type = DP_SG_NM;
  223. /*
  224. * when subgraph name starts with cluster
  225. * it gets special meaning in dot language
  226. */
  227. if (strncmp(sg->graphname, "cluster", 7) == 0) {
  228. sg->cluster = 1;
  229. sg->type = DP_SG_CL;
  230. }
  231. }
  232. /* type of edge, -- or -> */
  233. sg->etype = dp_groot->etype;
  234. sg->rootedon = dp_curgraph;
  235. sg->tag = DP_TGRAPH;
  236. /* splay with node/edge/graph parsed settings */
  237. sg->gattr = splay_tree_new(splay_tree_compare_strings, NULL, NULL);
  238. sg->nattr = splay_tree_new(splay_tree_compare_strings, NULL, NULL);
  239. sg->eattr = splay_tree_new(splay_tree_compare_strings, NULL, NULL);
  240. /* node with default settings */
  241. sg->defnode = (struct dpnode *)dp_calloc(1, sizeof(struct dpnode));
  242. sg->defnode->name = dp_uniqstr((char *)"default");
  243. sg->defnode->label = dp_uniqstr((char *)"default");
  244. /* set factory defaults */
  245. dp_nodefdef(sg->defnode);
  246. dp_nodegdef(dp_curgraph->defnode, sg->defnode);
  247. /* edge with default settings */
  248. sg->defedge = (struct dpedge *)dp_calloc(1, sizeof(struct dpedge));
  249. /* set factory defaults */
  250. dp_edgefdef(sg->defedge);
  251. dp_edgegdef(dp_curgraph->defedge, sg->defedge);
  252. /* set factory defaults */
  253. sg->yylineno = yylineno;
  254. /* factory defaults */
  255. dp_graphfdef(sg);
  256. /* get data from rooted on subgraph */
  257. /* set graph default */
  258. dp_graphgdef(sg->rootedon, sg);
  259. return;
  260. }
  261. /* end graph */
  262. void dp_eg(void)
  263. {
  264. return;
  265. }
  266. void dp_atype_graph(void)
  267. {
  268. dp_cclass = DP_TGRAPH;
  269. return;
  270. }
  271. void dp_atype_sgraph(void)
  272. {
  273. dp_cclass = DP_SGRAPH;
  274. return;
  275. }
  276. void dp_atype_node(void)
  277. {
  278. dp_cclass = DP_TNODE;
  279. return;
  280. }
  281. void dp_atype_edge(void)
  282. {
  283. dp_cclass = DP_TEDGE;
  284. return;
  285. }
  286. void dp_atype_graphdef(void)
  287. {
  288. dp_cclass = DP_TGRAPHDEF;
  289. return;
  290. }
  291. void dp_atype_nodedef(void)
  292. {
  293. dp_cclass = DP_TNODEDEF;
  294. return;
  295. }
  296. void dp_atype_edgedef(void)
  297. {
  298. dp_cclass = DP_TEDGEDEF;
  299. return;
  300. }
  301. /* set attribute with last arg set to 1 if r is a <html-label>, otherwise r="a-string" */
  302. void dp_aset(char *l, char *r, int ishtml)
  303. {
  304. char *dval = NULL;
  305. splay_tree_node spn = NULL;
  306. int htmllabel = 0;
  307. /* safety */
  308. if (l == NULL) {
  309. printf("%s(): dot shouldnothappen l is nil\n", __func__);
  310. return;
  311. }
  312. if (yydebug || 0) {
  313. printf("%s(): attribute \"%s\" has arg \"%s\" ishtml=%d\n", __func__, l, r, ishtml);
  314. }
  315. htmllabel = 0;
  316. if (ishtml) {
  317. if (strcmp(l, "label") == 0) {
  318. htmllabel = 1;
  319. } else {
  320. printf("%s(): html-label only supported for label attribute but not for \"%s=%s\" attribute\n", __func__, l, r);
  321. return;
  322. }
  323. }
  324. if (r) {
  325. dval = r;
  326. } else {
  327. dval = dp_uniqstr((char *)"");
  328. }
  329. switch (dp_cclass) {
  330. /* example : "aa"[color=red] */
  331. case DP_TNODE:
  332. {
  333. dp_do_nattr(l, r, ishtml);
  334. }
  335. break;
  336. /* example: node[color=red] */
  337. case DP_TNODEDEF:
  338. {
  339. spn = splay_tree_lookup(dp_curgraph->nattr, (splay_tree_key) l);
  340. if (spn == NULL) {
  341. splay_tree_insert(dp_curgraph->nattr, (splay_tree_key) l, (splay_tree_value) dval);
  342. } else {
  343. /*
  344. if (0)
  345. {
  346. printf
  347. ("dot %s(): attempt to redefine node attribute `%s=%s' with value `%s' near line %d\n",
  348. __func__, l, (char *) spn->value, r, yylineno);
  349. fflush (stdout);
  350. }
  351. */
  352. spn->value = (splay_tree_value) dval;
  353. }
  354. dp_do_nattr(l, r, ishtml);
  355. }
  356. break;
  357. case DP_TEDGE:
  358. {
  359. if (htmllabel == 0) {
  360. dp_do_eattr(l, r);
  361. } else {
  362. printf("%s(): html-label not supported for edge attributes\n", __func__);
  363. }
  364. }
  365. break;
  366. case DP_TEDGEDEF:
  367. {
  368. spn = splay_tree_lookup(dp_curgraph->eattr, (splay_tree_key) l);
  369. if (spn == NULL) {
  370. splay_tree_insert(dp_curgraph->eattr, (splay_tree_key) l, (splay_tree_value) dval);
  371. } else {
  372. /*
  373. if (0)
  374. {
  375. printf
  376. ("dot %s(): attempt to redefine edge attribute `%s=%s' with value `%s' near line %d\n",
  377. __func__, l, (char *) spn->value, r, yylineno);
  378. fflush (stdout);
  379. }
  380. */
  381. spn->value = (splay_tree_value) dval;
  382. }
  383. if (htmllabel == 0) {
  384. dp_do_eattr(l, r);
  385. } else {
  386. printf("%s(): html-label not supported for edge attributes\n", __func__);
  387. }
  388. }
  389. break;
  390. case DP_TGRAPHDEF:
  391. case DP_TGRAPH:
  392. {
  393. spn = splay_tree_lookup(dp_curgraph->gattr, (splay_tree_key) l);
  394. if (spn == NULL) {
  395. splay_tree_insert(dp_curgraph->gattr, (splay_tree_key) l, (splay_tree_value) dval);
  396. } else {
  397. /*
  398. if (0)
  399. {
  400. printf
  401. ("dot %s(): attempt to redefine graph attribute `%s=%s' with value `%s' near line %d\n",
  402. __func__, l, (char *) spn->value, r, yylineno);
  403. fflush (stdout);
  404. }
  405. */
  406. spn->value = (splay_tree_value) dval;
  407. }
  408. if (htmllabel == 0) {
  409. dp_do_gattr(l, r);
  410. } else {
  411. /* todo */
  412. printf("%s(): html-label not supported for graph attributes\n", __func__);
  413. }
  414. }
  415. break;
  416. case DP_SGRAPH:
  417. /* attribute after subgraph */
  418. break;
  419. default:
  420. {
  421. printf("dot %s(): shouldnothappen dp_cclass=%d\n", __func__, dp_cclass);
  422. fflush(stdout);
  423. }
  424. break;
  425. }
  426. return;
  427. }
  428. /* add node as global node and to subgraph nodelist if mode is 0 */
  429. static void dp_nodelink(struct dpnode *node, int mode)
  430. {
  431. struct dpnlink *nl = NULL;
  432. if (0) {
  433. printf("%s(): add node \"%s\" \"%s\"\n", __func__, node->name, node->label);
  434. }
  435. /* if mode is 1, do not add as global node. */
  436. if (mode == 0) {
  437. /* add node to global nodelist */
  438. nl = (struct dpnlink *)dp_calloc(1, sizeof(struct dpnlink));
  439. nl->n = node;
  440. if (dp_anodes == NULL) {
  441. dp_anodes = nl;
  442. dp_anodesend = nl;
  443. } else {
  444. dp_anodesend->next = nl;
  445. dp_anodesend = nl;
  446. }
  447. }
  448. /* add node to current subgraph */
  449. nl = (struct dpnlink *)dp_calloc(1, sizeof(struct dpnlink));
  450. nl->n = node;
  451. if (dp_curgraph->dpnodes == NULL) {
  452. dp_curgraph->dpnodes = nl;
  453. dp_curgraph->dpnodesend = nl;
  454. } else {
  455. dp_curgraph->dpnodesend->next = nl;
  456. dp_curgraph->dpnodesend = nl;
  457. }
  458. return;
  459. }
  460. /* add edge point */
  461. static void dp_eplink(struct dpepoint *epoint)
  462. {
  463. struct dpeplink *el = NULL;
  464. /* add point to global pointlist */
  465. el = (struct dpeplink *)dp_calloc(1, sizeof(struct dpeplink));
  466. el->ep = epoint;
  467. if (dp_epl == NULL) {
  468. dp_epl = el;
  469. dp_eplend = el;
  470. } else {
  471. dp_eplend->next = el;
  472. dp_eplend = el;
  473. }
  474. /* add point to global pointlist */
  475. el = (struct dpeplink *)dp_calloc(1, sizeof(struct dpeplink));
  476. el->ep = epoint;
  477. if (dp_curgraph->dpeplist == NULL) {
  478. dp_curgraph->dpeplist = el;
  479. dp_curgraph->dpeplistend = el;
  480. } else {
  481. dp_curgraph->dpeplistend->next = el;
  482. dp_curgraph->dpeplistend = el;
  483. }
  484. return;
  485. }
  486. /* recursive clear all eppoint's */
  487. static void dp_clrep_r(struct dpgraph *gr)
  488. {
  489. struct dpglink *ng = NULL;
  490. struct dpeplink *el = NULL;
  491. struct dpeplink *elnext = NULL;
  492. if (gr == NULL) {
  493. return;
  494. }
  495. ng = gr->dpsubg;
  496. while (ng) {
  497. dp_clrep_r(ng->sg);
  498. ng = ng->next;
  499. }
  500. el = gr->dpeplist;
  501. while (el) {
  502. elnext = el->next;
  503. el = (struct dpeplink *)dp_free(el);
  504. if (el) {
  505. }
  506. el = elnext;
  507. }
  508. gr->dpeplist = NULL;
  509. gr->dpeplistend = NULL;
  510. return;
  511. }
  512. /* clear all eppoint's */
  513. void dp_clrep(void)
  514. {
  515. struct dpeplink *el = NULL;
  516. struct dpeplink *elnext = NULL;
  517. /* recursive clear in subgraphs */
  518. dp_clrep_r(dp_groot);
  519. /* clear epl itself */
  520. el = dp_epl;
  521. while (el) {
  522. elnext = el->next;
  523. if (el->ep) {
  524. el->ep = (struct dpepoint *)dp_free((void *)el->ep);
  525. }
  526. el = (struct dpeplink *)dp_free((void *)el);
  527. if (el) {
  528. }
  529. el = elnext;
  530. }
  531. dp_epl = NULL;
  532. dp_eplend = NULL;
  533. return;
  534. }
  535. /* free nodes in subgraphs and rootgraph */
  536. static void dp_clrnodes_r(struct dpgraph *gr)
  537. {
  538. struct dpglink *ng = NULL;
  539. struct dpnlink *nl = NULL;
  540. struct dpnlink *nlnext = NULL;
  541. if (gr == NULL) {
  542. return;
  543. }
  544. ng = gr->dpsubg;
  545. while (ng) {
  546. dp_clrnodes_r(ng->sg);
  547. ng = ng->next;
  548. }
  549. nl = gr->dpnodes;
  550. while (nl) {
  551. nlnext = nl->next;
  552. nl = (struct dpnlink *)dp_free((void *)nl);
  553. if (nl) {
  554. }
  555. nl = nlnext;
  556. }
  557. gr->dpnodes = NULL;
  558. gr->dpnodesend = NULL;
  559. return;
  560. }
  561. /* clear all nodes */
  562. static void dp_clrnodesli(struct dppart *info)
  563. {
  564. int i = 0;
  565. struct dppart *info2 = NULL;
  566. if (info == NULL) {
  567. return;
  568. }
  569. for (i = 0; i < info->ndpparts; i++) {
  570. if (info->parts[i]) {
  571. dp_clrnodesli(info->parts[i]);
  572. }
  573. }
  574. if (info->parts) {
  575. info->parts = (struct dppart **)dp_free((void *)info->parts);
  576. }
  577. info2 = (struct dppart *)dp_free(info);
  578. if (info2) {
  579. }
  580. return;
  581. }
  582. /* free ilist */
  583. static void dp_freememil(struct tdldata *td)
  584. {
  585. struct ilist *ilptr = NULL; /* text items in td or 0 */
  586. struct ilist *ilptrnext = NULL; /* text items in td or 0 */
  587. if (td == NULL) {
  588. return;
  589. }
  590. if (td->tdd == NULL) {
  591. return;
  592. }
  593. if (td->tdd->il) {
  594. ilptr = td->tdd->il;
  595. while (ilptr) {
  596. ilptrnext = ilptr->next;
  597. if (ilptr->items) {
  598. ilptr->items = (struct item *)dp_free((void *)ilptr->items);
  599. }
  600. ilptr = (struct ilist *)dp_free((void *)ilptr);
  601. if (ilptr) {
  602. }
  603. ilptr = ilptrnext;
  604. }
  605. td->tdd->il = NULL;
  606. td->tdd->ilend = NULL;
  607. }
  608. return;
  609. }
  610. /* free <tr> */
  611. static void dp_freememtr(struct trlist *tr)
  612. {
  613. struct tdldata *tdlptr = NULL; /* td items in tr */
  614. struct tdldata *tdlptrnext = NULL;
  615. if (tr == NULL) {
  616. return;
  617. }
  618. if (tr->tritem == NULL) {
  619. return;
  620. }
  621. /* <td> data */
  622. tdlptr = tr->tritem->td;
  623. while (tdlptr) {
  624. tdlptrnext = tdlptr->next;
  625. /* tdptr is free'ed later */
  626. /* free il data in <td> */
  627. if (tdlptr->tdd) {
  628. dp_freememil(tdlptr);
  629. tdlptr->tdd = (struct tddata *)dp_free((void *)tdlptr->tdd);
  630. }
  631. tdlptr = (struct tdldata *)dp_free((void *)tdlptr);
  632. if (tdlptr) {
  633. }
  634. tdlptr = tdlptrnext;
  635. }
  636. tr->tritem->td = NULL;
  637. tr->tritem->tdend = NULL;
  638. tr->tritem = (struct trdata *)dp_free((void *)tr->tritem);
  639. if (tr->tritem) {
  640. }
  641. return;
  642. }
  643. static void dp_freememt_r(struct tlist *tl)
  644. {
  645. struct tlist *tlptr = NULL; /* list of table items */
  646. struct tlist *tlptrnext = NULL; /* list of table items */
  647. struct trlist *trptr = NULL; /* tr items */
  648. struct trlist *trptrnext = NULL; /* end tr items */
  649. if (tl == NULL) {
  650. /* shouldnothappen */
  651. return;
  652. }
  653. if (tl->titem == NULL) {
  654. /* shouldnothappen */
  655. return;
  656. }
  657. if (tl->titem->tabdata) {
  658. /* clear sub tables if any */
  659. if (tl->titem->tabdata->tl) {
  660. tlptr = tl->titem->tabdata->tl;
  661. while (tlptr) {
  662. tlptrnext = tlptr->next;
  663. dp_freememt_r(tlptr);
  664. if (tlptr->titem) {
  665. tlptr->titem = (struct tableldata *)dp_free((void *)tlptr->titem);
  666. }
  667. tlptr = (struct tlist *)dp_free((void *)tlptr);
  668. if (tlptr) {
  669. }
  670. tlptr = tlptrnext;
  671. }
  672. tl->titem->tabdata->tl = NULL;
  673. tl->titem->tabdata->tlend = NULL;
  674. }
  675. /* <tr> data */
  676. if (tl->titem->tabdata->tr) {
  677. trptr = tl->titem->tabdata->tr;
  678. while (trptr) {
  679. trptrnext = trptr->next;
  680. dp_freememtr(trptr);
  681. if (trptr->tritem) {
  682. trptr->tritem = (struct trdata *)dp_free((void *)trptr->tritem);
  683. }
  684. trptr = (struct trlist *)dp_free((void *)trptr);
  685. if (trptr) {
  686. }
  687. trptr = trptrnext;
  688. }
  689. tl->titem->tabdata->tr = NULL;
  690. tl->titem->tabdata->trend = NULL;
  691. }
  692. if (tl->titem->tabdata) {
  693. tl->titem->tabdata = (struct tabledata *)dp_free((void *)tl->titem->tabdata);
  694. }
  695. }
  696. if (tl->titem) {
  697. tl->titem = (struct tableldata *)dp_free((void *)tl->titem);
  698. }
  699. return;
  700. }
  701. /* clear hlinfo of one node */
  702. static void dp_clearhlinfonode(struct dpnode *node)
  703. {
  704. struct tlist *tlptr = NULL; /* list of table items */
  705. struct tlist *tlptrnext = NULL; /* list of table items */
  706. struct ilist *pil = NULL;
  707. struct ilist *pilnext = NULL;
  708. if (node == NULL) { /* shoudlothappen */
  709. return;
  710. }
  711. if (node->hlinfo == NULL) { /* shouldnothappen */
  712. return;
  713. }
  714. /* item data to free */
  715. if (node->hlinfo->il) {
  716. pil = node->hlinfo->il;
  717. while (pil) {
  718. pilnext = pil->next;
  719. if (pil->items) {
  720. pil->items = (struct item *)dp_free((void *)pil->items);
  721. }
  722. pil = (struct ilist *)dp_free((void *)pil);
  723. if (pil) {
  724. }
  725. pil = pilnext;
  726. }
  727. node->hlinfo->il = NULL;
  728. node->hlinfo->ilend = NULL;
  729. }
  730. /* table data to free */
  731. if (node->hlinfo->tl) {
  732. /* */
  733. tlptr = node->hlinfo->tl;
  734. while (tlptr) {
  735. tlptrnext = tlptr->next;
  736. dp_freememt_r(tlptr);
  737. if (tlptr->titem) {
  738. tlptr->titem = (struct tableldata *)dp_free((void *)tlptr->titem);
  739. }
  740. tlptr = (struct tlist *)dp_free((void *)tlptr);
  741. if (tlptr) {
  742. }
  743. tlptr = tlptrnext;
  744. }
  745. /* ready */
  746. node->hlinfo->tl = NULL;
  747. node->hlinfo->tlend = NULL;
  748. }
  749. return;
  750. }
  751. static void dp_clrnodes(void)
  752. {
  753. struct dpnlink *nl = NULL;
  754. struct dpnlink *nlnext = NULL;
  755. dp_clrnodes_r(dp_groot);
  756. nl = dp_anodes;
  757. while (nl) {
  758. nlnext = nl->next;
  759. if (nl->n->labelinfo) {
  760. dp_clrnodesli(nl->n->labelinfo);
  761. }
  762. if (nl->n->hlinfo) {
  763. dp_clearhlinfonode(nl->n);
  764. nl->n->hlinfo = (struct hlpart *)dp_free(nl->n->hlinfo);
  765. if (nl->n->hlinfo) {
  766. }
  767. }
  768. if (nl->n) {
  769. nl->n = (struct dpnode *)dp_free((void *)nl->n);
  770. }
  771. nl = (struct dpnlink *)dp_free((void *)nl);
  772. if (nl) {
  773. }
  774. nl = nlnext;
  775. }
  776. dp_anodes = NULL;
  777. dp_anodesend = NULL;
  778. return;
  779. }
  780. static void dp_clrgraph_r(struct dpgraph *gr)
  781. {
  782. struct dpglink *ng = NULL;
  783. struct dpglink *gl = NULL;
  784. struct dpglink *glnext = NULL;
  785. if (gr == NULL) {
  786. return;
  787. }
  788. ng = gr->dpsubg;
  789. while (ng) {
  790. dp_clrgraph_r(ng->sg);
  791. ng = ng->next;
  792. }
  793. gl = gr->dpsubg;
  794. while (gl) {
  795. glnext = gl->next;
  796. if (gl->sg->defnode) {
  797. gl->sg->defnode = (struct dpnode *)dp_free((void *)gl->sg->defnode);
  798. }
  799. if (gl->sg->defedge) {
  800. gl->sg->defedge = (struct dpedge *)dp_free((void *)gl->sg->defedge);
  801. }
  802. gl->sg->gattr = splay_tree_delete(gl->sg->gattr);
  803. gl->sg->nattr = splay_tree_delete(gl->sg->nattr);
  804. gl->sg->eattr = splay_tree_delete(gl->sg->eattr);
  805. gl = (struct dpglink *)dp_free((void *)gl);
  806. if (gl) {
  807. }
  808. gl = glnext;
  809. }
  810. gr->dpsubg = NULL;
  811. gr->dpsubgend = NULL;
  812. return;
  813. }
  814. /* clear all garphs */
  815. static void dp_clrgraphs(void)
  816. {
  817. struct dpglink *dpl = NULL;
  818. struct dpglink *dplnext = NULL;
  819. dp_clrgraph_r(dp_groot);
  820. if (dp_asubg) {
  821. dpl = dp_asubg;
  822. while (dpl) {
  823. dplnext = dpl->next;
  824. if (dpl->sg) {
  825. dpl->sg = (struct dpgraph *)dp_free((void *)dpl->sg);
  826. }
  827. dpl = (struct dpglink *)dp_free((void *)dpl);
  828. if (dpl) {
  829. }
  830. dpl = dplnext;
  831. }
  832. }
  833. dp_asubg = NULL;
  834. dp_asubgend = NULL;
  835. return;
  836. }
  837. /* free edges in subgraphs and rootgraph */
  838. static void dp_clredges_r(struct dpgraph *gr)
  839. {
  840. struct dpglink *ng = NULL;
  841. struct dpelink *el = NULL;
  842. struct dpelink *elnext = NULL;
  843. if (gr == NULL) {
  844. return;
  845. }
  846. ng = gr->dpsubg;
  847. while (ng) {
  848. dp_clredges_r(ng->sg);
  849. ng = ng->next;
  850. }
  851. el = gr->dpedges;
  852. while (el) {
  853. elnext = el->next;
  854. /* edge ->e is free()'ed in dp_clredges() */
  855. el = (struct dpelink *)dp_free((void *)el);
  856. if (el) {
  857. }
  858. el = elnext;
  859. }
  860. gr->dpedges = NULL;
  861. gr->dpedgesend = NULL;
  862. return;
  863. }
  864. /* clear all edges */
  865. static void dp_clredges(void)
  866. {
  867. struct dpelink *el = NULL;
  868. struct dpelink *elnext = NULL;
  869. dp_clredges_r(dp_groot);
  870. el = dp_aedges;
  871. while (el) {
  872. elnext = el->next;
  873. if (el->e) {
  874. el->e = (struct dpedge *)dp_free((void *)el->e);
  875. }
  876. el = (struct dpelink *)dp_free((void *)el);
  877. if (el) {
  878. }
  879. el = elnext;
  880. }
  881. dp_aedges = NULL;
  882. dp_aedgesend = NULL;
  883. return;
  884. }
  885. /* clear edge head nodes */
  886. void dp_clrheade(void)
  887. {
  888. struct dpeplink *el = NULL;
  889. struct dpeplink *elnext = NULL;
  890. el = dp_headepl;
  891. while (el) {
  892. elnext = el->next;
  893. if (el->ep) {
  894. el->ep = (struct dpepoint *)dp_free((void *)el->ep);
  895. }
  896. el = (struct dpeplink *)dp_free((void *)el);
  897. if (el) {
  898. }
  899. el = elnext;
  900. }
  901. dp_headepl = NULL;
  902. dp_headeplend = NULL;
  903. return;
  904. }
  905. /* clear tmp edges during edge building */
  906. static void dp_clrtmpe(void)
  907. {
  908. struct dptelink *te = NULL;
  909. struct dptelink *tenext = NULL;
  910. te = dp_tmpe;
  911. while (te) {
  912. tenext = te->next;
  913. if (te->e) {
  914. te->e = (struct dptmpe *)dp_free((void *)te->e);
  915. }
  916. te = (struct dptelink *)dp_free((void *)te);
  917. if (te) {
  918. }
  919. te = tenext;
  920. }
  921. dp_tmpe = NULL;
  922. dp_tmpeend = NULL;
  923. return;
  924. }
  925. /* add graph to lists */
  926. static void dp_graphlink(struct dpgraph *sg)
  927. {
  928. struct dpglink *ng = NULL;
  929. /* add node to global nodelist */
  930. ng = (struct dpglink *)dp_calloc(1, sizeof(struct dpglink));
  931. ng->sg = sg;
  932. /* all subgraphs in one list */
  933. if (dp_asubg == NULL) {
  934. dp_asubg = ng;
  935. dp_asubgend = ng;
  936. } else {
  937. dp_asubgend->next = ng;
  938. dp_asubgend = ng;
  939. }
  940. /* add node to current subgraph */
  941. ng = (struct dpglink *)dp_calloc(1, sizeof(struct dpglink));
  942. ng->sg = sg;
  943. if (dp_curgraph->dpsubg == NULL) {
  944. dp_curgraph->dpsubg = ng;
  945. dp_curgraph->dpsubgend = ng;
  946. } else {
  947. dp_curgraph->dpsubgend->next = ng;
  948. dp_curgraph->dpsubgend = ng;
  949. }
  950. return;
  951. }
  952. /* create node at nodestatement
  953. * dot allows to redefine a node.
  954. * node name can be ""
  955. * node label can be ""
  956. */
  957. void dp_mknode0(char *name)
  958. {
  959. struct dpnode *n = NULL;
  960. /* check if node is in database */
  961. n = dpuniqnode(name);
  962. if (n) {
  963. /* node exist and being redefined now */
  964. /* only if earlier defined by a node statement */
  965. /* todo this does not work */
  966. if (n->bitflags0.defbynode == 1 || 0) {
  967. if (0) {
  968. printf("dot %s(): node `%s' line %d is redefined at line %d\n", __func__, n->name, n->yylineno, yylineno);
  969. fflush(stdout);
  970. }
  971. }
  972. if (dp_groot != dp_curgraph) {
  973. dp_nodegdef(dp_curgraph->defnode, n);
  974. }
  975. dp_curnode = n;
  976. /* add node to curgraph but not in nodelist */
  977. dp_nodelink(n, 1);
  978. } else {
  979. /* fresh new node */
  980. n = (struct dpnode *)dp_calloc(1, sizeof(struct dpnode));
  981. n->name = name; /* uniq node name */
  982. n->label = name; /* label text \N */
  983. /* set factory defaults */
  984. dp_nodefdef(n);
  985. /* set node defaults for this graph */
  986. dp_nodegdef(dp_groot->defnode, n);
  987. if (dp_groot != dp_curgraph || 0) {
  988. dp_nodegdef(dp_curgraph->defnode, n);
  989. }
  990. /* setparams */
  991. n->root = dp_curgraph;
  992. dp_nodenum++;
  993. n->nr = dp_nodenum; /* uniq node number */
  994. n->yylineno = yylineno; /* line where node is defined */
  995. dp_groot->nnodes++; /* number of nodes in graph */
  996. if (dp_groot != dp_curgraph) {
  997. dp_curgraph->nnodes++; /* number of nodes in sub graph */
  998. }
  999. n->bitflags0.defbynode = 1;
  1000. /* add as uniqnode */
  1001. dpuniqnode_add(n);
  1002. /* add node as global node and to subgraph nodelist */
  1003. dp_nodelink(n, 0);
  1004. /* set current node being parsed */
  1005. dp_curnode = n;
  1006. }
  1007. return;
  1008. }
  1009. /* edge point with node name and port/compass */
  1010. struct dpepoint *dp_mknid(char *name, char *port, char *compass)
  1011. {
  1012. struct dpnode *n = NULL;
  1013. struct dpepoint *nid = NULL;
  1014. char *compass2 = NULL;
  1015. char *port2 = NULL;
  1016. int yes = 0;
  1017. port2 = port;
  1018. compass2 = compass;
  1019. if (compass) {
  1020. yes = dp_iscompass(compass);
  1021. if (yes == 0) {
  1022. memset(dp_errmsg, 0, 256);
  1023. snprintf(dp_errmsg, (256 - 1),
  1024. "dot %s(): syntax error invalid compass point `%s' at node `%s' near line %dexpected one of these compass points: n,ne,e,se,s,sw,w,nw,c,_\n\n",
  1025. __func__, compass, name, yylineno);
  1026. /* continue and error message will soon appear */
  1027. }
  1028. }
  1029. if (compass == NULL) {
  1030. if (port) {
  1031. yes = dp_iscompass(port);
  1032. if (yes == 1) {
  1033. /* turn port into compass */
  1034. compass2 = port;
  1035. port2 = NULL;
  1036. }
  1037. }
  1038. }
  1039. /* check if node is in database */
  1040. n = dpuniqnode(name);
  1041. if (n == NULL) {
  1042. /* node in edge did not exist and create now */
  1043. /* fresh new node */
  1044. n = (struct dpnode *)dp_calloc(1, sizeof(struct dpnode));
  1045. /* setparams */
  1046. n->name = name; /* uniq node name */
  1047. n->label = name; /* label text \N */
  1048. /* set factory defaults */
  1049. dp_nodefdef(n);
  1050. /* set node defaults for this graph */
  1051. dp_nodegdef(dp_groot->defnode, n);
  1052. if (dp_groot != dp_curgraph || 0) {
  1053. dp_nodegdef(dp_curgraph->defnode, n);
  1054. }
  1055. n->root = dp_curgraph; /* subgraph where node is defined */
  1056. dp_nodenum++;
  1057. n->nr = dp_nodenum; /* uniq node number */
  1058. n->yylineno = yylineno; /* line where node is defined */
  1059. dp_groot->nnodes++; /* number of nodes in graph */
  1060. if (dp_groot != dp_curgraph) {
  1061. dp_curgraph->nnodes++; /* number of nodes in sub graph */
  1062. }
  1063. /* add as uniqnode */
  1064. dpuniqnode_add(n);
  1065. /* add node as global node and to subgraph nodelist */
  1066. dp_nodelink(n, 0);
  1067. }
  1068. nid = (struct dpepoint *)dp_calloc(1, sizeof(struct dpepoint));
  1069. nid->n = n;
  1070. nid->port = port2; /* port or compass point */
  1071. nid->compass = compass2;
  1072. nid->type = 0; /* type 0: this is a node */
  1073. nid->root = n->root;
  1074. return (nid);
  1075. }
  1076. /* start edge at nid */
  1077. void dp_starte1(struct dpepoint *ep)
  1078. {
  1079. struct dpepoint *epnew = NULL;
  1080. struct dpeplink *el = NULL;
  1081. dp_enest++;
  1082. dp_curgraph->enest++;
  1083. /* add point to global pointlist */
  1084. el = (struct dpeplink *)dp_calloc(1, sizeof(struct dpeplink));
  1085. epnew = (struct dpepoint *)dp_calloc(1, sizeof(struct dpepoint));
  1086. epnew->port = ep->port;
  1087. epnew->compass = ep->compass;
  1088. epnew->type = ep->type;
  1089. epnew->root = ep->root;
  1090. epnew->n = ep->n;
  1091. el->ep = epnew;
  1092. dp_eplink(ep);
  1093. if (dp_headepl == NULL) {
  1094. dp_headepl = el;
  1095. dp_headeplend = el;
  1096. } else {
  1097. dp_headeplend->next = el;
  1098. dp_headeplend = el;
  1099. }
  1100. return;
  1101. }
  1102. /* start edge at sstatements */
  1103. void dp_starte2(struct dpepoint *ep)
  1104. {
  1105. struct dpepoint *epnew = NULL;
  1106. struct dpeplink *el = NULL;
  1107. dp_enest++;
  1108. dp_curgraph->enest++;
  1109. /* add point to global pointlist */
  1110. el = (struct dpeplink *)dp_calloc(1, sizeof(struct dpeplink));
  1111. epnew = (struct dpepoint *)dp_calloc(1, sizeof(struct dpepoint));
  1112. epnew->port = ep->port;
  1113. epnew->compass = ep->compass;
  1114. epnew->type = ep->type;
  1115. epnew->root = ep->root;
  1116. epnew->n = ep->n;
  1117. el->ep = epnew;
  1118. dp_eplink(ep);
  1119. if (dp_headepl == NULL) {
  1120. dp_headepl = el;
  1121. dp_headeplend = el;
  1122. } else {
  1123. dp_headeplend->next = el;
  1124. dp_headeplend = el;
  1125. }
  1126. return;
  1127. }
  1128. /* inside edge statement */
  1129. void dp_ine(struct dpepoint *ep)
  1130. {
  1131. dp_eplink(ep);
  1132. return;
  1133. }
  1134. /* setup new edge for edge attribute */
  1135. void dp_newe(void)
  1136. {
  1137. dp_curedge = (struct dpedge *)dp_calloc(1, sizeof(struct dpedge));
  1138. dp_curedge->yylineno = yylineno;
  1139. dp_edgegdef(dp_curgraph->defedge, dp_curedge);
  1140. dp_atype_edge();
  1141. return;
  1142. }
  1143. static void dp_endeprlink(struct dpeplink *el)
  1144. {
  1145. struct dpgraph *g = NULL;
  1146. struct dpeplink *eptr = NULL;
  1147. struct dpnlink *nodes = NULL;
  1148. int ltype = 0;
  1149. eptr = el;
  1150. while (eptr) {
  1151. ltype = eptr->ep->type;
  1152. printf("\tltype=%d", ltype);
  1153. if (eptr->ep->type == 0) {
  1154. /* type 0: this is a node */
  1155. printf("`%s' %p ", eptr->ep->n->name, (void *)eptr->ep->root);
  1156. } else if (eptr->ep->type == 1) {
  1157. printf("`subgraph-%p' : ", (void *)eptr->ep->root);
  1158. /* type 1: this is a subgraph */
  1159. g = eptr->ep->root;
  1160. nodes = g->dpnodes;
  1161. if (nodes) {
  1162. while (nodes) {
  1163. printf("`%s' ", nodes->n->name);
  1164. nodes = nodes->next;
  1165. }
  1166. } else {
  1167. printf("no-nodes");
  1168. }
  1169. } else {
  1170. printf("dp_endeprlink()-unknown-ep->type");
  1171. }
  1172. printf("\n");
  1173. eptr = eptr->next;
  1174. }
  1175. return;
  1176. }
  1177. /* make edges edges */
  1178. static void dp_mkedges(void)
  1179. {
  1180. struct dpelink *nel = NULL;
  1181. struct dpedge *newedge = NULL;
  1182. struct dptelink *tl = NULL;
  1183. tl = dp_tmpe;
  1184. while (tl) {
  1185. newedge = (struct dpedge *)dp_calloc(1, sizeof(struct dpedge));
  1186. dp_edgenum++;
  1187. newedge->nr = dp_edgenum;
  1188. newedge->rootedon = dp_curgraph;
  1189. newedge->fn = tl->e->fn;
  1190. newedge->fport = tl->e->fport;
  1191. newedge->fcompass = tl->e->fcompass;
  1192. newedge->tn = tl->e->tn;
  1193. newedge->tport = tl->e->tport;
  1194. newedge->tcompass = tl->e->tcompass;
  1195. newedge->yylineno = yylineno;
  1196. /* copy edge attributes */
  1197. dp_edgegdef(dp_curedge, newedge);
  1198. nel = (struct dpelink *)dp_calloc(1, sizeof(struct dpelink));
  1199. nel->e = newedge;
  1200. if (dp_aedges == NULL) {
  1201. dp_aedges = nel;
  1202. dp_aedgesend = nel;
  1203. } else {
  1204. dp_aedgesend->next = nel;
  1205. dp_aedgesend = nel;
  1206. }
  1207. nel = (struct dpelink *)dp_calloc(1, sizeof(struct dpelink));
  1208. nel->e = newedge;
  1209. /* */
  1210. if (tl->e->fn->root->dpedges == NULL) {
  1211. tl->e->fn->root->dpedges = nel; /* edges starting in this graph */
  1212. tl->e->fn->root->dpedgesend = nel; /* edges starting in this graph */
  1213. } else {
  1214. tl->e->fn->root->dpedgesend->next = nel; /* edges starting in this graph */
  1215. tl->e->fn->root->dpedgesend = nel; /* edges starting in this graph */
  1216. }
  1217. tl = tl->next;
  1218. }
  1219. return;
  1220. }
  1221. /* print all edges */
  1222. static void dp_prtae(void)
  1223. {
  1224. struct dpelink *nel = NULL;
  1225. printf("dot %s(): all edges:\n", __func__);
  1226. nel = dp_aedges;
  1227. while (nel) {
  1228. printf(" `%s'->`%s'\n", nel->e->fn->name, nel->e->tn->name);
  1229. nel = nel->next;
  1230. }
  1231. printf("dot %s(): end all edges\n", __func__);
  1232. return;
  1233. }
  1234. /* print tmp edges */
  1235. static void dp_prte(void)
  1236. {
  1237. struct dptelink *tl = NULL;
  1238. tl = dp_tmpe;
  1239. while (tl) {
  1240. printf("dot %s(): `%s'->`%s' %p->%p\n", __func__, tl->e->fn->name,
  1241. tl->e->tn->name, (void *)tl->e->fn->root, (void *)tl->e->tn->root);
  1242. tl = tl->next;
  1243. } return;
  1244. }
  1245. /* create tmp edges */
  1246. static void dp_addte(struct dpnode *fn, char *fport, char *fcompass, struct dpnode *tn, char *tport, char *tcompass)
  1247. {
  1248. struct dptmpe *te = NULL;
  1249. struct dptelink *tl = NULL;
  1250. te = (struct dptmpe *)dp_calloc(1, sizeof(struct dptmpe));
  1251. te->fn = fn;
  1252. te->fport = fport;
  1253. te->fcompass = fcompass;
  1254. te->tn = tn;
  1255. te->tport = tport;
  1256. te->tcompass = tcompass;
  1257. tl = (struct dptelink *)dp_calloc(1, sizeof(struct dptelink));
  1258. tl->e = te;
  1259. if (dp_tmpe == NULL) {
  1260. dp_tmpe = tl;
  1261. dp_tmpeend = tl;
  1262. } else {
  1263. dp_tmpeend->next = tl;
  1264. dp_tmpeend = tl;
  1265. }
  1266. return;
  1267. }
  1268. static void dp_endel_n2n(struct dpepoint *fn, struct dpepoint *tn)
  1269. {
  1270. if (yydebug) {
  1271. printf("%s(1): `%s'->`%s'\n", __func__, fn->n->name, tn->n->name);
  1272. }
  1273. dp_addte(fn->n, fn->port, fn->compass, tn->n, tn->port, tn->compass);
  1274. return;
  1275. }
  1276. static void dp_endel_n2g(struct dpepoint *fn, struct dpepoint *tn)
  1277. {
  1278. struct dpgraph *g = NULL;
  1279. struct dpnlink *nodes = NULL;
  1280. g = tn->root;
  1281. nodes = g->dpnodes;
  1282. while (nodes) {
  1283. if (yydebug) {
  1284. printf("%s(1): `%s'->`%s'\n", __func__, fn->n->name, nodes->n->name);
  1285. }
  1286. dp_addte(fn->n, fn->port, fn->compass, nodes->n, NULL, NULL);
  1287. nodes = nodes->next;
  1288. }
  1289. return;
  1290. }
  1291. /* subgraph to node as in {}->x */
  1292. static void dp_endel_g2n(struct dpepoint *fn, struct dpepoint *tn)
  1293. {
  1294. struct dpgraph *g = NULL;
  1295. struct dpnlink *nodes = NULL;
  1296. g = fn->root;
  1297. nodes = g->dpnodes;
  1298. while (nodes) {
  1299. if (yydebug || 0) {
  1300. printf("%s(1): `%s'->`%s'\n", __func__, nodes->n->name, tn->n->name);
  1301. }
  1302. dp_addte(nodes->n, NULL, NULL, tn->n, tn->port, tn->compass);
  1303. nodes = nodes->next;
  1304. }
  1305. return;
  1306. }
  1307. static void dp_endel_g2g(struct dpepoint *fn, struct dpepoint *tn)
  1308. {
  1309. struct dpgraph *g = NULL;
  1310. struct dpnlink *nodes = NULL;
  1311. struct dpgraph *g2 = NULL;
  1312. struct dpnlink *nodes2 = NULL;
  1313. g = fn->root;
  1314. nodes = g->dpnodes;
  1315. while (nodes) {
  1316. g2 = tn->root;
  1317. nodes2 = g2->dpnodes;
  1318. while (nodes2) {
  1319. if (yydebug) {
  1320. printf("%s(1): `%s'->`%s'\n", __func__, nodes->n->name, nodes2->n->name);
  1321. }
  1322. dp_addte(nodes->n, NULL, NULL, nodes2->n, NULL, NULL);
  1323. nodes2 = nodes2->next;
  1324. }
  1325. nodes = nodes->next;
  1326. }
  1327. return;
  1328. }
  1329. /* main */
  1330. static void dp_endel(struct dpeplink *el)
  1331. {
  1332. struct dpeplink *eptr = NULL;
  1333. struct dpepoint *fn = NULL;
  1334. struct dpepoint *tn = NULL;
  1335. int ltype = 0;
  1336. int rtype = 0;
  1337. eptr = el;
  1338. if (yydebug || 0) {
  1339. printf("%s(start): dp_enest=%d eptr=%p eptr->next=%p\n", __func__, dp_enest, (void *)eptr, (void *)eptr->next);
  1340. }
  1341. if (dp_enest > 1) {
  1342. printf("dot %s(): nested edges not supported at line %d\n", __func__, yylineno);
  1343. fflush(stdout);
  1344. }
  1345. if (eptr && eptr->next == NULL) {
  1346. if (dp_headepl == NULL) {
  1347. /* shouldnothappen */
  1348. return;
  1349. }
  1350. /* from and to node */
  1351. fn = dp_headepl->ep;
  1352. tn = eptr->ep;
  1353. ltype = fn->type;
  1354. rtype = tn->type;
  1355. /* check type of from and to node */
  1356. if (ltype == 0 && rtype == 0) {
  1357. dp_endel_n2n(fn, tn);
  1358. } else if (ltype == 0 && rtype == 1) {
  1359. dp_endel_n2g(fn, tn);
  1360. } else if (ltype == 1 && rtype == 0) {
  1361. dp_endel_g2n(fn, tn);
  1362. } else if (ltype == 1 && rtype == 1) {
  1363. dp_endel_g2g(fn, tn);
  1364. } else {
  1365. printf("%s(1): ltype=%d rtype=%d shouldnothappen\n", __func__, ltype, rtype);
  1366. }
  1367. } else {
  1368. while (eptr) {
  1369. if (eptr->next == NULL) {
  1370. break;
  1371. }
  1372. fn = eptr->ep;
  1373. tn = eptr->next->ep;
  1374. fflush(stdout);
  1375. ltype = fn->type;
  1376. rtype = tn->type;
  1377. if (dp_enest) {
  1378. if (fn->root == tn->root) {
  1379. if (ltype == 0 && rtype == 0) {
  1380. dp_endel_n2n(fn, tn);
  1381. } else if (ltype == 0 && rtype == 1) {
  1382. dp_endel_n2g(fn, tn);
  1383. } else if (ltype == 1 && rtype == 0) {
  1384. dp_endel_g2n(fn, tn);
  1385. } else if (ltype == 1 && rtype == 1) {
  1386. dp_endel_g2g(fn, tn);
  1387. } else {
  1388. printf("%s(2): ltype=%d rtype=%d shouldnothappen\n", __func__, ltype, rtype);
  1389. }
  1390. }
  1391. } else {
  1392. /* nest is 0 */
  1393. if (ltype == 0 && rtype == 0) {
  1394. dp_endel_n2n(fn, tn);
  1395. } else if (ltype == 0 && rtype == 1) {
  1396. dp_endel_n2g(fn, tn);
  1397. } else if (ltype == 1 && rtype == 0) {
  1398. dp_endel_g2n(fn, tn);
  1399. } else if (ltype == 1 && rtype == 1) {
  1400. dp_endel_g2g(fn, tn);
  1401. } else {
  1402. printf
  1403. ("%s(3): ltype=%d rtype=%d fn=%s tn=%s shouldnothappen\n",
  1404. __func__, ltype, rtype, fn->n->name, tn->n->name);
  1405. }
  1406. }
  1407. eptr = eptr->next;
  1408. }
  1409. }
  1410. if (yydebug || 0) {
  1411. printf("%s(end):\n", __func__);
  1412. }
  1413. return;
  1414. }
  1415. /* end edge statement */
  1416. void dp_ende(void)
  1417. {
  1418. struct dpgraph *g = NULL;
  1419. struct dpglink *sg = NULL;
  1420. int en = 0;
  1421. en = dp_curgraph->enest;
  1422. if (yydebug || 0) {
  1423. printf
  1424. ("dot %s(): curgraph=%p now dp_curgraph->enest from %d to %d and enest from %d to %d\n",
  1425. __func__, (void *)dp_curgraph, en, en - 1, dp_enest, dp_enest - 1);
  1426. }
  1427. dp_enest--;
  1428. if (dp_enest < 0) {
  1429. dp_enest = 0;
  1430. }
  1431. dp_curgraph->enest--;
  1432. if (dp_curgraph->enest < 0) {
  1433. dp_curgraph->enest = 0;
  1434. }
  1435. if (yydebug || 0) {
  1436. printf("dot %s(): dp_epl list:\n", __func__);
  1437. dp_endeprlink(dp_epl);
  1438. g = dp_groot;
  1439. printf(" root graph:\n");
  1440. dp_endeprlink(g->dpeplist);
  1441. sg = g->dpsubg;
  1442. while (sg) {
  1443. printf(" subgraph:\n");
  1444. dp_endeprlink(sg->sg->dpeplist);
  1445. sg = sg->next;
  1446. }
  1447. printf("dot %s(): end dp_epl list\n", __func__);
  1448. printf("dot %s(): dp_headepl list:\n", __func__);
  1449. dp_endeprlink(dp_headepl);
  1450. printf("dot %s(): end dp_headepl list\n", __func__);
  1451. fflush(stdout);
  1452. }
  1453. dp_endel(dp_epl);
  1454. /* and full end of edge statement, handle the rest */
  1455. if (dp_enest == 0) {
  1456. if (yydebug || 0) {
  1457. printf("dot %s(): Wipe headepl\n", __func__);
  1458. /* print tmp edges */
  1459. dp_prte();
  1460. }
  1461. /* make real edges */
  1462. dp_mkedges();
  1463. if (yydebug || 0) { /* print all edges */
  1464. dp_prtae();
  1465. }
  1466. dp_curedge = (struct dpedge *)dp_free((void *)dp_curedge);
  1467. if (dp_curedge) {
  1468. }
  1469. dp_clrheade();
  1470. dp_clrtmpe();
  1471. dp_enest = 0;
  1472. }
  1473. dp_atype_graph();
  1474. fflush(stdout);
  1475. return;
  1476. }
  1477. /* subg without name, also in edge like a->{b->c}
  1478. * or with a name as in subgraph "ho" { }
  1479. * or with empty name as in subgraph { }
  1480. * or with nil name as in { }
  1481. * types of subgraphs:
  1482. * #define DP_SG_ROOT 0 * root graph type
  1483. * #define DP_SG_CO 1 * compound subgraph {}
  1484. * #define DP_SG_NM 2 * named subgrph
  1485. * #define DP_SG_CL 3 * cluster subgraph
  1486. * #define DP_SG_NN 4 * no name subgraph
  1487. */
  1488. void dp_namedsubg(char *sgname, int type)
  1489. {
  1490. struct dpgraph *nsg = NULL;
  1491. nsg = (struct dpgraph *)dp_calloc(1, sizeof(struct dpgraph));
  1492. /* uniq graph number */
  1493. nsg->nr = dp_sgnr;
  1494. dp_sgnr++;
  1495. /* set factory defaults */
  1496. dp_graphfdef(nsg);
  1497. dp_nsubg(nsg, sgname, type);
  1498. dp_graphlink(nsg);
  1499. dp_pushgraph(nsg);
  1500. return;
  1501. }
  1502. /* end ssatement in edge */
  1503. struct dpepoint *dp_endss(void)
  1504. {
  1505. struct dpepoint *newe = NULL;
  1506. struct dpgraph *g = NULL;
  1507. newe = (struct dpepoint *)dp_calloc(1, sizeof(struct dpepoint));
  1508. newe->type = 1; /* type 1: this is a subgraph edge point */
  1509. newe->root = dp_curgraph;
  1510. g = dp_pullgraph();
  1511. if (g) {
  1512. }
  1513. return (newe);
  1514. }
  1515. void dp_cke(char *edgetype)
  1516. {
  1517. if (strcmp(edgetype, dp_groot->etype)) {
  1518. memset(dp_errmsg, 0, 256);
  1519. snprintf(dp_errmsg, (256 - 1),
  1520. "dot %s(): syntax error edgetype `%s' but expected `%s' near line %d\n",
  1521. __func__, edgetype, dp_groot->etype, yylineno);
  1522. }
  1523. return;
  1524. }
  1525. /* 'add' strings in a new string */
  1526. char *dp_ccat(char *a, char *b)
  1527. {
  1528. size_t lena = 0;
  1529. size_t lenb = 0;
  1530. char *tmpp = NULL;
  1531. char *res = NULL;
  1532. /* add safety */
  1533. if (a == NULL) {
  1534. return (dp_uniqstr((char *)""));
  1535. }
  1536. /* add safety */
  1537. if (b == NULL) {
  1538. return (dp_uniqstr((char *)""));
  1539. }
  1540. lena = strlen(a);
  1541. lenb = strlen(b);
  1542. tmpp = (char *)dp_calloc(1, (lena + lenb + 1));
  1543. strcpy(tmpp, a);
  1544. strcat(tmpp, b);
  1545. res = dp_uniqstr(tmpp);
  1546. tmpp = (char *)dp_free((void *)tmpp);
  1547. if (tmpp) {
  1548. }
  1549. return (res);
  1550. }
  1551. /* clear all memory in use zzz */
  1552. void dp_clearall(void)
  1553. {
  1554. dp_clrep();
  1555. dp_clrheade();
  1556. dp_clrtmpe();
  1557. /* clear all edges in graph */
  1558. dp_clredges();
  1559. dp_clrnodes();
  1560. dp_clrgraphs();
  1561. if (dp_groot) {
  1562. dp_groot->gattr = splay_tree_delete(dp_groot->gattr);
  1563. dp_groot->nattr = splay_tree_delete(dp_groot->nattr);
  1564. dp_groot->eattr = splay_tree_delete(dp_groot->eattr);
  1565. if (dp_groot->defnode) {
  1566. dp_groot->defnode = (struct dpnode *)dp_free((void *)dp_groot->defnode);
  1567. }
  1568. if (dp_groot->defedge) {
  1569. dp_groot->defedge = (struct dpedge *)dp_free((void *)dp_groot->defedge);
  1570. }
  1571. dp_groot = (struct dpgraph *)dp_free((void *)dp_groot);
  1572. if (dp_groot) {
  1573. }
  1574. }
  1575. dpgraphs = splay_tree_delete(dpgraphs);
  1576. dp_curgraph = NULL;
  1577. dp_groot = NULL;
  1578. clear_dpuniqnode();
  1579. dp_colorcode_clear();
  1580. dp_clear_uniqstr();
  1581. return;
  1582. }
  1583. /* end */