PageRenderTime 27ms CodeModel.GetById 34ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/xdot/xdot.c

https://github.com/ekoontz/graphviz
C | 629 lines | 544 code | 69 blank | 16 comment | 51 complexity | 6daa141e912af9ee50ea30cd5a849abc MD5 | raw file
Possible License(s): CPL-1.0
  1. /* vim:set shiftwidth=4 ts=8: */
  2. /**********************************************************
  3. * This software is part of the graphviz package *
  4. * http://www.graphviz.org/ *
  5. * *
  6. * Copyright (c) 1994-2007 AT&T Corp. *
  7. * and is licensed under the *
  8. * Common Public License, Version 1.0 *
  9. * by AT&T Corp. *
  10. * *
  11. * Information and Software Systems Research *
  12. * AT&T Research, Florham Park NJ *
  13. **********************************************************/
  14. #include <xdot.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <ctype.h>
  19. #include <assert.h>
  20. #include <sys/types.h>
  21. #include <memory.h>
  22. #include <time.h>
  23. static char*
  24. parseFloat (char* s, float* fp)
  25. {
  26. int r, sz;
  27. r = sscanf(s, "%f%n", fp, &sz);
  28. assert (r == 1);
  29. return (s+sz);
  30. }
  31. static char*
  32. parseInt (char* s, int* ip)
  33. {
  34. int r, sz;
  35. r = sscanf(s, "%d%n", ip, &sz);
  36. assert (r == 1);
  37. return (s+sz);
  38. }
  39. static char*
  40. parsePoint (char* s, xdot_point* pp)
  41. {
  42. int r, sz;
  43. r = sscanf(s, "%d %d%n", &(pp->x), &(pp->y), &sz);
  44. assert (r == 2);
  45. pp->z = 0;
  46. return (s+sz);
  47. }
  48. static char*
  49. parseRect (char* s, xdot_rect* rp)
  50. {
  51. int r, sz;
  52. r = sscanf(s, "%d %d %d %d%n", &(rp->x), &(rp->y), &(rp->w), &(rp->h), &sz);
  53. assert (r == 4);
  54. return (s+sz);
  55. }
  56. static char*
  57. parsePolyline (char* s, xdot_polyline* pp)
  58. {
  59. int i;
  60. xdot_point* pts;
  61. s = parseInt (s, &i);
  62. pts = N_NEW(i, xdot_point);
  63. pp->cnt = i;
  64. for (i = 0; i < pp->cnt; i++)
  65. s = parsePoint (s, pts+i);
  66. pp->pts = pts;
  67. return s;
  68. }
  69. static char*
  70. parseString (char* s, char** sp)
  71. {
  72. int i;
  73. char* c;
  74. s = parseInt (s, &i);
  75. c = N_NEW(i+1, char);
  76. while (*s++ != '-');
  77. memcpy (c, s, i);
  78. c[i] = '\0';
  79. *sp = c;
  80. return (s+i);
  81. }
  82. static char*
  83. parseAlign (char* s, xdot_align* ap)
  84. {
  85. int i;
  86. s = parseInt (s, &i);
  87. if (i < 0) *ap = xd_left;
  88. else if (i > 0) *ap = xd_right;
  89. else *ap = xd_center;
  90. return s;
  91. }
  92. #ifdef OLDXDOT
  93. static char*
  94. parseOp (xdot_op* op, char* s)
  95. {
  96. while (isspace(*s)) s++;
  97. switch (*s++) {
  98. case 'E' :
  99. op->kind = xd_filled_ellipse;
  100. s = parseRect (s, &op->u.ellipse);
  101. op->drawfunc=DrawEllipse;
  102. break;
  103. case 'e' :
  104. op->kind = xd_unfilled_ellipse;
  105. s = parseRect (s, &op->u.ellipse);
  106. op->drawfunc=DrawEllipse;
  107. break;
  108. case 'P' :
  109. op->kind = xd_filled_polygon;
  110. s = parsePolyline (s, &op->u.polygon);
  111. op->drawfunc=DrawPolygon;
  112. break;
  113. case 'p' :
  114. op->kind = xd_unfilled_polygon;
  115. s = parsePolyline (s, &op->u.polygon);
  116. op->drawfunc=DrawPolygon;
  117. break;
  118. case 'b' :
  119. op->kind = xd_filled_bezier;
  120. s = parsePolyline (s, &op->u.bezier);
  121. op->drawfunc=DrawBeziers;
  122. break;
  123. case 'B' :
  124. op->kind = xd_unfilled_bezier;
  125. s = parsePolyline (s, &op->u.bezier);
  126. op->drawfunc=DrawBeziers;
  127. break;
  128. case 'c' :
  129. op->kind = xd_pen_color;
  130. s = parseString (s, &op->u.color);
  131. op->drawfunc=SetPenColor;
  132. break;
  133. case 'C' :
  134. op->kind = xd_fill_color;
  135. s = parseString (s, &op->u.color);
  136. op->drawfunc=SetFillColor;
  137. break;
  138. case 'L' :
  139. op->kind = xd_polyline;
  140. s = parsePolyline (s, &op->u.polyline);
  141. op->drawfunc=DrawPolyline;
  142. break;
  143. case 'T' :
  144. op->kind = xd_text;
  145. s = parseInt (s, &op->u.text.x);
  146. s = parseInt (s, &op->u.text.y);
  147. s = parseAlign (s, &op->u.text.align);
  148. s = parseInt (s, &op->u.text.width);
  149. s = parseString (s, &op->u.text.text);
  150. op->drawfunc=EmbedText;
  151. break;
  152. case 'F' :
  153. op->kind = xd_font;
  154. s = parseFloat (s, &op->u.font.size);
  155. s = parseString (s, &op->u.font.name);
  156. op->drawfunc=SetFont;
  157. break;
  158. case 'S' :
  159. op->kind = xd_style;
  160. s = parseString (s, &op->u.style);
  161. op->drawfunc=SetStyle;
  162. break;
  163. case 'I' :
  164. op->kind = xd_image;
  165. s = parseRect (s, &op->u.image.pos);
  166. s = parseString (s, &op->u.image.name);
  167. op->drawfunc=InsertImage;
  168. break;
  169. default :
  170. s = 0;
  171. break;
  172. }
  173. return s;
  174. }
  175. #else
  176. static char*
  177. parseOp (xdot_op* op, char* s, drawfunc_t ops[])
  178. {
  179. while (isspace(*s)) s++;
  180. switch (*s++) {
  181. case 'E' :
  182. op->kind = xd_filled_ellipse;
  183. s = parseRect (s, &op->u.ellipse);
  184. if (ops) op->drawfunc=ops[xop_ellipse];
  185. break;
  186. case 'e' :
  187. op->kind = xd_unfilled_ellipse;
  188. s = parseRect (s, &op->u.ellipse);
  189. if (ops) op->drawfunc=ops[xop_ellipse];
  190. break;
  191. case 'P' :
  192. op->kind = xd_filled_polygon;
  193. s = parsePolyline (s, &op->u.polygon);
  194. if (ops) op->drawfunc=ops[xop_polygon];
  195. break;
  196. case 'p' :
  197. op->kind = xd_unfilled_polygon;
  198. s = parsePolyline (s, &op->u.polygon);
  199. if (ops) op->drawfunc=ops[xop_polygon];
  200. break;
  201. case 'b' :
  202. op->kind = xd_filled_bezier;
  203. s = parsePolyline (s, &op->u.bezier);
  204. if (ops) op->drawfunc=ops[xop_bezier];
  205. break;
  206. case 'B' :
  207. op->kind = xd_unfilled_bezier;
  208. s = parsePolyline (s, &op->u.bezier);
  209. if (ops) op->drawfunc=ops[xop_bezier];
  210. break;
  211. case 'c' :
  212. op->kind = xd_pen_color;
  213. s = parseString (s, &op->u.color);
  214. if (ops) op->drawfunc=ops[xop_pen_color];
  215. break;
  216. case 'C' :
  217. op->kind = xd_fill_color;
  218. s = parseString (s, &op->u.color);
  219. if (ops) op->drawfunc=ops[xop_fill_color];
  220. break;
  221. case 'L' :
  222. op->kind = xd_polyline;
  223. s = parsePolyline (s, &op->u.polyline);
  224. if (ops) op->drawfunc=ops[xop_polyline];
  225. break;
  226. case 'T' :
  227. op->kind = xd_text;
  228. s = parseInt (s, &op->u.text.x);
  229. s = parseInt (s, &op->u.text.y);
  230. s = parseAlign (s, &op->u.text.align);
  231. s = parseInt (s, &op->u.text.width);
  232. s = parseString (s, &op->u.text.text);
  233. if (ops) op->drawfunc=ops[xop_text];
  234. break;
  235. case 'F' :
  236. op->kind = xd_font;
  237. s = parseFloat (s, &op->u.font.size);
  238. s = parseString (s, &op->u.font.name);
  239. if (ops) op->drawfunc=ops[xop_font];
  240. break;
  241. case 'S' :
  242. op->kind = xd_style;
  243. s = parseString (s, &op->u.style);
  244. if (ops) op->drawfunc=ops[xop_style];
  245. break;
  246. case 'I' :
  247. op->kind = xd_image;
  248. s = parseRect (s, &op->u.image.pos);
  249. s = parseString (s, &op->u.image.name);
  250. if (ops) op->drawfunc=ops[xop_image];
  251. break;
  252. default :
  253. s = 0;
  254. break;
  255. }
  256. return s;
  257. }
  258. #endif
  259. #define XDBSIZE 100
  260. xdot*
  261. parseXDotF (char* s, drawfunc_t fns[], int sz)
  262. {
  263. xdot* x;
  264. xdot_op op;
  265. char* ops;
  266. int bufsz = XDBSIZE;
  267. if (!s) return NULL;
  268. x = NEW(xdot);
  269. if (sz <= 0) sz = sizeof(xdot_op);
  270. ops = (char*)gmalloc(XDBSIZE*sz);
  271. x->cnt = 0;
  272. while ((s = parseOp (&op, s, fns))) {
  273. if (x->cnt == bufsz) {
  274. bufsz += XDBSIZE;
  275. ops = (char*)grealloc (ops, bufsz*sz);
  276. }
  277. *(xdot_op*)(ops + (x->cnt*sz)) = op;
  278. x->cnt++;
  279. }
  280. if (x->cnt)
  281. x->ops = (xdot_op*)grealloc (ops, x->cnt*sz);
  282. else {
  283. free (x);
  284. x = 0;
  285. }
  286. free (x);
  287. return x;
  288. }
  289. xdot*
  290. parseXDot (char* s)
  291. {
  292. return parseXDotF (s, 0, 0);
  293. }
  294. typedef void (*pf)(char*, void*);
  295. static void
  296. printRect (xdot_rect* r, pf print, void* info)
  297. {
  298. char buf[128];
  299. sprintf (buf, " %d %d %d %d", r->x, r->y, r->w, r->h);
  300. print (buf, info);
  301. }
  302. static void
  303. printPolyline (xdot_polyline* p, pf print, void* info)
  304. {
  305. int i;
  306. char buf[64];
  307. sprintf (buf, " %d", p->cnt);
  308. print (buf, info);
  309. for (i = 0; i< p->cnt; i++) {
  310. sprintf (buf, " %d %d", p->pts[i].x, p->pts[i].y);
  311. print (buf, info);
  312. }
  313. }
  314. static void
  315. printString (char* p, pf print, void* info)
  316. {
  317. char buf[30];
  318. sprintf (buf, " %d -", (int)strlen(p));
  319. print (buf, info);
  320. print (p, info);
  321. }
  322. static void
  323. printInt (int i, pf print, void* info)
  324. {
  325. char buf[30];
  326. sprintf (buf, " %d", i);
  327. print (buf, info);
  328. }
  329. static void
  330. printFloat (float f, pf print, void* info)
  331. {
  332. char buf[128];
  333. sprintf (buf, " %f", f);
  334. print (buf, info);
  335. }
  336. static void
  337. printAlign (xdot_align a, pf print, void* info)
  338. {
  339. switch (a) {
  340. case xd_left :
  341. print (" -1", info);
  342. break;
  343. case xd_right :
  344. print (" 1", info);
  345. break;
  346. case xd_center :
  347. print (" 0", info);
  348. break;
  349. }
  350. }
  351. static void
  352. printXDot_Op (xdot_op* op, pf print, void* info)
  353. {
  354. switch (op->kind) {
  355. case xd_filled_ellipse :
  356. print ("E", info);
  357. printRect (&op->u.ellipse, print, info);
  358. break;
  359. case xd_unfilled_ellipse :
  360. print ("e", info);
  361. printRect (&op->u.ellipse, print, info);
  362. break;
  363. case xd_filled_polygon :
  364. print ("P", info);
  365. printPolyline (&op->u.polygon, print, info);
  366. break;
  367. case xd_unfilled_polygon :
  368. print ("p", info);
  369. printPolyline (&op->u.polygon, print, info);
  370. break;
  371. case xd_filled_bezier :
  372. print ("b", info);
  373. op->kind = xd_filled_bezier;
  374. printPolyline (&op->u.bezier, print, info);
  375. break;
  376. case xd_unfilled_bezier :
  377. print ("B", info);
  378. printPolyline (&op->u.bezier, print, info);
  379. break;
  380. case xd_pen_color :
  381. print ("c", info);
  382. printString (op->u.color, print, info);
  383. break;
  384. case xd_fill_color :
  385. print ("C", info);
  386. printString (op->u.color, print, info);
  387. break;
  388. case xd_polyline :
  389. print ("L", info);
  390. printPolyline (&op->u.polyline, print, info);
  391. break;
  392. case xd_text :
  393. print ("T", info);
  394. printInt (op->u.text.x, print, info);
  395. printInt (op->u.text.y, print, info);
  396. printAlign (op->u.text.align, print, info);
  397. printInt (op->u.text.width, print, info);
  398. printString (op->u.text.text, print, info);
  399. break;
  400. case xd_font :
  401. print ("F", info);
  402. op->kind = xd_font;
  403. printFloat (op->u.font.size, print, info);
  404. printString (op->u.font.name, print, info);
  405. break;
  406. case xd_style :
  407. print ("S", info);
  408. printString (op->u.style, print, info);
  409. break;
  410. case xd_image :
  411. print ("I", info);
  412. printRect (&op->u.image.pos, print, info);
  413. printString (op->u.image.name, print, info);
  414. break;
  415. }
  416. }
  417. static void
  418. _printXDot (xdot* x, pf print, void* info)
  419. {
  420. int i;
  421. for (i = 0; i < x->cnt; i++) {
  422. printXDot_Op (x->ops+i, print, info);
  423. if (i < x->cnt-1) print (" ", info);
  424. }
  425. }
  426. typedef struct {
  427. unsigned char *buf; /* start of buffer */
  428. unsigned char *ptr; /* next place to write */
  429. unsigned char *eptr; /* end of buffer */
  430. int dyna; /* true if buffer is malloc'ed */
  431. } agxbuf;
  432. #define agxbputc(X,C) ((((X)->ptr >= (X)->eptr) ? agxbmore(X,1) : 0), \
  433. (int)(*(X)->ptr++ = ((unsigned char)C)))
  434. #define agxbuse(X) (agxbputc(X,'\0'),(char*)((X)->ptr = (X)->buf))
  435. static void
  436. agxbinit(agxbuf * xb, unsigned int hint, unsigned char *init)
  437. {
  438. if (init) {
  439. xb->buf = init;
  440. xb->dyna = 0;
  441. } else {
  442. if (hint == 0)
  443. hint = BUFSIZ;
  444. xb->dyna = 1;
  445. xb->buf = N_NEW(hint, unsigned char);
  446. }
  447. xb->eptr = xb->buf + hint;
  448. xb->ptr = xb->buf;
  449. *xb->ptr = '\0';
  450. }
  451. static int
  452. agxbmore(agxbuf * xb, unsigned int ssz)
  453. {
  454. int cnt; /* current no. of characters in buffer */
  455. int size; /* current buffer size */
  456. int nsize; /* new buffer size */
  457. unsigned char *nbuf; /* new buffer */
  458. size = xb->eptr - xb->buf;
  459. nsize = 2 * size;
  460. if (size + ssz > nsize)
  461. nsize = size + ssz;
  462. cnt = xb->ptr - xb->buf;
  463. if (xb->dyna) {
  464. nbuf = realloc(xb->buf, nsize);
  465. } else {
  466. nbuf = N_NEW(nsize, unsigned char);
  467. memcpy(nbuf, xb->buf, cnt);
  468. xb->dyna = 1;
  469. }
  470. xb->buf = nbuf;
  471. xb->ptr = xb->buf + cnt;
  472. xb->eptr = xb->buf + nsize;
  473. return 0;
  474. }
  475. static int
  476. agxbput(char* s, agxbuf * xb)
  477. {
  478. unsigned int ssz = strlen (s);
  479. if (xb->ptr + ssz > xb->eptr)
  480. agxbmore(xb, ssz);
  481. memcpy(xb->ptr, s, ssz);
  482. xb->ptr += ssz;
  483. return ssz;
  484. }
  485. /* agxbfree:
  486. * Free any malloced resources.
  487. */
  488. static void
  489. agxbfree(agxbuf * xb)
  490. {
  491. if (xb->dyna)
  492. free(xb->buf);
  493. }
  494. char*
  495. sprintXDot (xdot* x)
  496. {
  497. char* s;
  498. unsigned char buf[BUFSIZ];
  499. agxbuf xb;
  500. agxbinit (&xb, BUFSIZ, buf);
  501. _printXDot (x, (pf)agxbput, &xb);
  502. s = strdup(agxbuse (&xb));
  503. agxbfree (&xb);
  504. return s;
  505. }
  506. void
  507. fprintXDot (FILE* fp, xdot* x)
  508. {
  509. _printXDot (x, (pf)fputs, fp);
  510. }
  511. static void
  512. freeXOpData (xdot_op* x)
  513. {
  514. switch (x->kind) {
  515. case xd_filled_polygon :
  516. case xd_unfilled_polygon :
  517. free (x->u.polyline.pts);
  518. break;
  519. case xd_filled_bezier :
  520. case xd_unfilled_bezier :
  521. free (x->u.polyline.pts);
  522. break;
  523. case xd_polyline :
  524. free (x->u.polyline.pts);
  525. break;
  526. case xd_text :
  527. free (x->u.text.text);
  528. break;
  529. case xd_fill_color :
  530. case xd_pen_color :
  531. free (x->u.color);
  532. break;
  533. case xd_font :
  534. free (x->u.font.name);
  535. break;
  536. case xd_style :
  537. free (x->u.style);
  538. break;
  539. case xd_image :
  540. free (x->u.image.name);
  541. break;
  542. default :
  543. break;
  544. }
  545. }
  546. void
  547. freeXDot (xdot* x)
  548. {
  549. int i;
  550. for (i = 0; i < x->cnt; i++) freeXOpData (x->ops+i);
  551. free (x->ops);
  552. free (x);
  553. }
  554. #if 0
  555. static void
  556. execOp (xdot_op* op,int param)
  557. {
  558. op->drawfunc(op,param);
  559. }
  560. #endif