/bin/prag.awk

http://shell-simulator.googlecode.com/ · AWK · 702 lines · 582 code · 2 blank · 118 comment · 193 complexity · ae297bab4f507146dbcbc0924a1aa19c MD5 · raw file

  1. #!gawk -f
  2. # Copyright (C) 1992, 1993 Holger J. Meyer, Rostock, Germany
  3. # hm@GUUG.de
  4. #
  5. # See file ``Copyright'' for terms of copyright.
  6. #
  7. # Module:
  8. # Process a grap(1) like language, to produce graphs. The input language
  9. # syntax is documented in lines marked with double hash marks ('##').
  10. # The first implementation was much inspired by the graph program from
  11. # ``Aho, A.V., Kernighan, B. W., Weinberger, P. J. "The AWK Programming
  12. # Language", Addison-Wesley, Reading, 1988''.
  13. #
  14. # Source:
  15. # NAWK
  16. #
  17. # History:
  18. # 92/4/20 hme, initial version written
  19. # 93/8/24 hme, multiple graphs, grids, etc. added
  20. # 93/10/20 hme, labeled margin boxes, generate `reset' before .PE
  21. # 95/9/24 hme, more grap conformance, improved ticks (by eduardo@nostromo.medusa.es)
  22. # 95/11/15 hme, put out only labeled margin boxes
  23. #
  24. # Layout:
  25. #
  26. # GRAPH
  27. # +----------+------------------------+----------+
  28. # | | ^ | |
  29. # | | TMARG ht/6| |
  30. # | | v | |
  31. # +----------+------------------------+----------+
  32. # | LMARG | FRAME ^ | RMARG |
  33. # | | | | |
  34. # | | | | |
  35. # | | ht | |
  36. # | | | | |
  37. # | | | | |
  38. # |<-wid/6-->|<---------wid--------v->|<--wid/6->|
  39. # +----------+------------------------+----------+
  40. # | | ^ | |
  41. # | | BMARG ht/6| |
  42. # | | v | |
  43. # +----------+------------------------+----------+
  44. #
  45. #
  46. BEGIN {
  47. MYADDR = "hm@GUUG.de";
  48. # number (RE)
  49. NUMBER = "^[-+]?([0-9]+[.]?[0-9]*|[.][0-9]+)" "([eE][-+]?[0-9]+)?$";
  50. GNAME = "GRAPH"; # label for whole picture
  51. FNAME = "FRAME"; # label for frame
  52. MNAME = "MARG"; # label for [top|....] margin boxes
  53. DEFLSTYLE = "solid";
  54. DEFCH = "\\s+2\\(bu\\s-2";
  55. MARKED = 1;
  56. MINXTICKS = 5;
  57. MINYTICKS = 5;
  58. nG1 = 0;
  59. grapinput = 0;
  60. err = 0;
  61. dot_lf = 1;
  62. warn = 1;
  63. debug = 0;
  64. }
  65. ## .G1 [width [height]]
  66. # start of graph input
  67. /^.G1/ {
  68. ++nG1;
  69. grapinput = 1;
  70. data = 0;
  71. initgraph();
  72. if (NF >= 2) {
  73. wid = $2;
  74. }
  75. if (NF >= 3) {
  76. ht = $3;
  77. }
  78. resizegraph();
  79. if (dot_lf) {
  80. printf(".lf %d %s\n", FNR, FILENAME);
  81. }
  82. next;
  83. }
  84. ## .G2
  85. # end of graph input -- draw graph
  86. /^.G2/ {
  87. if (!grapinput) {
  88. printf("\"%s\":%d: missing previous .G1\n", FILENAME, FNR) |"cat >&2";
  89. errexit(-1);
  90. }
  91. else {
  92. endgraph();
  93. grapinput = 0;
  94. }
  95. if (dot_lf) {
  96. printf(".lf %d %s\n", FNR, FILENAME);
  97. }
  98. next;
  99. }
  100. # copy all outside from .G1 and .G2
  101. !grapinput {
  102. print $0;
  103. next;
  104. }
  105. ## # comment
  106. # delete comments
  107. /^#/ {
  108. next;
  109. }
  110. ## draw line-style
  111. $1 == "draw" {
  112. if (NF != 2) {
  113. printf("\"%s\":%d: draw line-style\n", FILENAME, FNR) | "cat >&2";
  114. errexit(-1);
  115. }
  116. if ($2 == "marked") {
  117. g_flags[ngs] = MARKED;
  118. }
  119. else {
  120. g_lstyle[ngs] = $2;
  121. }
  122. next;
  123. }
  124. ## new [line-style [name [label]]]
  125. # begin new graph, put old data points out
  126. $1 == "new" {
  127. cg = ++ngs;
  128. newgraph(ngs);
  129. if (NF >= 2) {
  130. if ($2 == "marked") {
  131. g_flags[ngs] = MARKED;
  132. }
  133. else {
  134. g_lstyle[ngs] = $2;
  135. }
  136. }
  137. if (NF >= 3) {
  138. g_name[ngs] = $3;
  139. }
  140. if (NF >= 4) {
  141. $1 = $2 = $3 = "";
  142. sub(/^[ \t]*/, "");
  143. g_label[ngs] = $0;
  144. }
  145. g_ndata[ngs] = 0;
  146. next;
  147. }
  148. ## label [left | right | top | bot] label-string
  149. # left, right, top, bottom label
  150. $1 == "label" {
  151. pos = $2;
  152. if (pos == "left") {
  153. sub(/^[ \t]*label[ \t]+left[ \t]*/, "");
  154. }
  155. else if (pos == "right") {
  156. sub(/^[ \t]*label[ \t]+right[ \t]*/, "");
  157. }
  158. else if (pos == "top") {
  159. sub(/^[ \t]*label[ \t]+top[ \t]*/, "");
  160. }
  161. else if (pos == "bot") {
  162. sub(/^[ \t]*label[ \t]+bot[ \t]*/, "");
  163. }
  164. else {
  165. printf("\"%s\":%d: label [left|right|top|bot] string ...\n",
  166. FILENAME, FNR) | "cat >&2";
  167. errexit(-1);
  168. }
  169. t_label[pos] = $0;
  170. next;
  171. }
  172. ## ticks [left | right | top | bot] [where] position ...
  173. ## ticks [left | right | top | bot] [where] from begin to end [by step]
  174. # ticks for x- & y-axis, left, top, right or bottom position
  175. $1 == "ticks" {
  176. if (NF <= 3) {
  177. printf("\"%s\":%d: ticks [left|right|top|bot] [where] position ...\n",
  178. FILENAME, FNR) | "cat >&2";
  179. errexit(-1);
  180. }
  181. if ($2 != "left" && $2 != "right" && $2 != "top" && $2 != "bot") {
  182. printf("\"%s\":%d: ticks [left|right|top|bot] [where] position ...\n",
  183. FILENAME, FNR) | "cat >&2";
  184. errexit(-1);
  185. }
  186. i = 3;
  187. t_num[$2] = 0;
  188. if ($3 == "in" || $3 == "out") {
  189. t_where[$2] = $3;
  190. ++i;
  191. }
  192. if ($i != "from") {
  193. while (i <= NF) {
  194. t_pos[$2, t_num[$2]] = $i;
  195. ++t_num[$2];
  196. ++i;
  197. }
  198. }
  199. else {
  200. if ($(i+2) != "to" || NF < i+3) {
  201. printf( "\"%s\":%d: ticks [left|right|top|bot] [where] from begin to end [by step]\n",
  202. FILENAME, FNR) | "cat >&2";
  203. errexit(-1);
  204. }
  205. if ($(i+4) == "by") {
  206. if (NF == i+5) {
  207. tickstep = $(i+5);
  208. }
  209. else {
  210. printf( "\"%s\":%d: ticks [left|right|top|bot] [where] from begin to end [by step]\n",
  211. FILENAME, FNR) | "cat >&2";
  212. errexit(-1);
  213. }
  214. }
  215. else {
  216. tickstep = 1;
  217. }
  218. for (tick = $(i+1); tick <= $(i+3); tick += tickstep) {
  219. t_pos[$2, t_num[$2]] = tick;
  220. ++t_num[$2];
  221. }
  222. }
  223. next;
  224. }
  225. ## frame frame-attributes ...
  226. # frame-attributes
  227. $1 == "frame" {
  228. if (NF == 1) {
  229. printf("\"%s\":%d: frame frame-attributes ...\n",
  230. FILENAME, FNR) | "cat >&2";
  231. errexit(-1);
  232. }
  233. sub(/^[ \t]*frame[ \t]+/, "");
  234. fattr = $0;
  235. next;
  236. }
  237. ## spline
  238. ## nospline
  239. $1 == "spline" {
  240. g_spline[ngs] = "sp";
  241. next;
  242. }
  243. $1 == "nospline" {
  244. g_spline[ngs] = "";
  245. next;
  246. }
  247. ## range xmin ymin xmax ymax
  248. $1 == "range" && $2 ~ NUMBER && $3 ~ NUMBER && $4 ~ NUMBER && $5 ~ NUMBER {
  249. if (NF != 5) {
  250. printf("\"%s\":%d: range xmin ymin xmax ymax\n",
  251. FILENAME, FNR) | "cat >&2";
  252. errexit(-1);
  253. }
  254. xmin = $2;
  255. ymin = $3;
  256. xmax = $4;
  257. ymax = $5;
  258. next;
  259. }
  260. ## ht number
  261. # graph height
  262. $1 == "ht" && $2 ~ NUMBER {
  263. if (NF != 2) {
  264. printf("\"%s\":%d: ht height\n", FILENAME, FNR) | "cat >&2";
  265. errexit(-1);
  266. }
  267. ht = $2;
  268. resizegraph();
  269. next;
  270. }
  271. ## wid number
  272. # graph width
  273. $1 == "wid" && $2 ~ NUMBER {
  274. if (NF != 2) {
  275. printf("\"%s\":%d: wid width\n", FILENAME, FNR) | "cat >&2";
  276. errexit(-1);
  277. }
  278. wid = $2;
  279. resizegraph();
  280. next;
  281. }
  282. ## grid [line-style]
  283. # graph with grid
  284. $1 == "grid" {
  285. if (NF == 1) {
  286. grid = "dotted";
  287. }
  288. else if (NF == 2) {
  289. grid = $2;
  290. }
  291. else {
  292. printf("\"%s\":%d: grid [line-style]\n", FILENAME, FNR) | "cat >&2";
  293. errexit(-1);
  294. }
  295. next;
  296. }
  297. ## mark drawing-character
  298. # set default drawing character for this graph
  299. $1 == "mark" {
  300. if (NF != 2) {
  301. printf("\"%s\":%d: mark drawing-character\n", FILENAME, FNR) | "cat >&2";
  302. errexit(-1);
  303. }
  304. g_defch[ngs] = $2;
  305. g_flags[ngs] = MARKED;
  306. next;
  307. }
  308. ## .lf line-number file-name
  309. # groff's ``.lf line file''
  310. $1 == ".lf" {
  311. print $0;
  312. next;
  313. }
  314. # collecting DATA
  315. ## next [graph-name] [at] position
  316. # next point extraction: awk falls through these actions!!!
  317. $1 == "next" && $3 == "at" {
  318. found = 0;
  319. for (i = 0; i <= ngs; ++i) {
  320. if (g_name[i] == $2) {
  321. # alter cg to point temporarily to an other graph
  322. # after collecting data, it shall be restored
  323. cg = i;
  324. ++found;
  325. break;
  326. }
  327. }
  328. if (!found) {
  329. printf("\"%s\":%d: illegal graph-name \"%s\": ignored\n",
  330. FILENAME, FNR, $2) | "cat >&2";
  331. }
  332. sub(/^[ \t]*next[ \t]+[a-zA-Z]+[ \t]+at[ \t]*/, "next at ");
  333. }
  334. $1 == "next" && $2 == "at" {
  335. sub(/^[ \t]*next[ \t]+at[ \t]*/, "next ");
  336. }
  337. $1 == "next" {
  338. sub(/^[ \t]*next[ \t]*/, "");
  339. }
  340. # pairs of numbers with opt drawing char
  341. $1 ~ NUMBER && $2 ~ NUMBER {
  342. g_x[cg, g_ndata[cg]] = $1;
  343. g_y[cg, g_ndata[cg]] = $2;
  344. if (NF >= 3) {
  345. $1 = $2 = "";
  346. sub(/^[ \t]*/, "");
  347. g_ch[cg, g_ndata[cg]] = $0; # extra plotting character
  348. }
  349. else {
  350. g_ch[cg, g_ndata[cg]] = "";
  351. }
  352. ++g_ndata[cg]; # count number of data points
  353. cg = ngs; # reset current graph
  354. data = 1;
  355. next;
  356. }
  357. # a single number with opt drawing char
  358. $1 ~ NUMBER && $2 !~ NUMBER {
  359. g_y[cg, g_ndata[cg]] = $1;
  360. g_x[cg, g_ndata[cg]] = g_ndata[cg];
  361. if (NF >= 2) {
  362. $1 = "";
  363. sub(/^[ \t]*/, "");
  364. g_ch[cg, g_ndata[cg]] = $0; # extra plotting character
  365. }
  366. else {
  367. g_ch[cg, g_ndata[cg]] = "";
  368. }
  369. ++g_ndata[cg];
  370. cg = ngs; # reset current graph
  371. data = 1;
  372. next;
  373. }
  374. ## pic '{' anything '}'
  375. # rest of input goes direct to pic
  376. $1 != "pic" {
  377. if (warn) {
  378. printf("\"%s\":%d: inputline passed through pic\n",
  379. FILENAME, FNR) | "cat >&2";
  380. }
  381. }
  382. {
  383. sub(/^[ \t]*pic[ \t]*{[ \t]*/, "");
  384. sub(/[ \t]*}[ \t]*$/, "");
  385. piccode = sprintf("%s%s\n", piccode, $0);
  386. next;
  387. }
  388. END {
  389. if (err) {
  390. exit(err);
  391. }
  392. if (grapinput) {
  393. printf("\"%s\":%d: missing .G2 \n", FILENAME, FNR) | "cat >&2";
  394. endgraph();
  395. }
  396. exit(0);
  397. }
  398. #
  399. # subroutine stuff
  400. #
  401. function errexit(e) {
  402. err = e;
  403. exit(-1);
  404. }
  405. function initgraph() {
  406. ht = 2; # default frame size
  407. wid = 3;
  408. fattr = ""; # frame-attributes
  409. grid = "";
  410. ngs = 0; # number of graphs
  411. cg = 0; # current graph, may differ from ngs due to next stmnt.
  412. # struct graph {
  413. # integer g_flags, # various flags indicating mark style etc.
  414. # string g_lstyle; # line style
  415. # string g_spline; # draw graph with [sp]line
  416. # string g_name; # graph name
  417. # string g_label; # graph label
  418. # integer g_ndata; # # of data items
  419. # real g_x[]; # x coords
  420. # real g_y[]; # y coords
  421. # string g_ch[]; # optional point drawing character
  422. # string g_defch; # default drawing character
  423. # };
  424. g_defch[0] = DEFCH;
  425. g_defch[1] = "\\(*D";
  426. g_defch[2] = "\\(pl";
  427. g_defch[3] = "\\(sq";
  428. g_defch[4] = "\\(mu";
  429. newticks("left");
  430. newticks("right");
  431. newticks("top");
  432. newticks("bot");
  433. newgraph(ngs);
  434. piccode = "";
  435. xmin = xmax = ymin = ymax = 0;
  436. }
  437. function resizegraph()
  438. {
  439. # left, right, top, bot margin of frame
  440. m_size["left"] = m_size["right"] = wid/6;
  441. m_size["top"] = m_size["bot"] = ht/6;
  442. ticklen = ht/32; # default len for tick marker
  443. }
  444. function newgraph(g) {
  445. g_flags[g] = 0;
  446. g_lstyle[g] = DEFLSTYLE;
  447. g_spline[g] = "sp"; # [sp]line used for graph drawing
  448. g_name[g] = "OOPS";
  449. g_label[g] = "";
  450. g_ndata[g] = 0;
  451. }
  452. function newticks(where) {
  453. t_label[where] = "";
  454. t_where[where] = "out";
  455. t_num[where] = 0;
  456. t_pos[where, 0] = 0;
  457. }
  458. function endgraph() {
  459. grapinput = 0;
  460. if (!xmin && !xmax && !ymin && !ymax) { # no range was given
  461. xmin = xmax = g_x[0, 0];
  462. ymin = ymax = g_y[0, 0];
  463. for (g = 0; g <= ngs; ++g) {
  464. for (i = 0; i < g_ndata[g]; ++i) {
  465. if (g_x[g, i] < xmin) {
  466. xmin = g_x[g, i];
  467. }
  468. if (g_x[g, i] > xmax) {
  469. xmax = g_x[g, i];
  470. }
  471. if (g_y[g, i] < ymin) {
  472. ymin = g_y[g, i];
  473. }
  474. if (g_y[g, i] > ymax) {
  475. ymax = g_y[g, i];
  476. }
  477. }
  478. }
  479. }
  480. printf(".PS %g %g\n", wid+m_size["left"]+m_size["right"], ht+m_size["top"]+m_size["bot"]);
  481. printf("# DO NOT EDIT!\n");
  482. printf("# generated from \"%s\" by prag (C) %s\n", FILENAME, MYADDR);
  483. if (data) { # any data?
  484. cutmarg();
  485. frame();
  486. label();
  487. ticks();
  488. for (g = 0; g <= ngs; ++g) {
  489. drawgraph(g);
  490. }
  491. }
  492. if (piccode != "") {
  493. printf("%s", piccode);
  494. }
  495. printf("reset\n.PE\n");
  496. }
  497. # cut off margins without a label
  498. function cutmarg( w) {
  499. for (w in m_size) {
  500. if (t_label[w] == "") {
  501. m_size[w] = 0;
  502. }
  503. }
  504. }
  505. # create frame from graph
  506. function frame() {
  507. printf("%s:\tbox invis ht %g wid %g\n",
  508. GNAME, ht+m_size["top"]+m_size["bot"], wid+m_size["left"]+m_size["right"]);
  509. printf("%s:\tbox %s ht %g wid %g with .sw at %s.sw + (%g, %g)\n",
  510. FNAME, fattr, ht, wid, GNAME, m_size["left"], m_size["bot"]);
  511. }
  512. # center label under x-axis and left from y-axis
  513. function label() {
  514. if (t_label["left"]) {
  515. printf("%s%s:\tbox wid %g ht %g invis %s with .e at %s.w\n",
  516. MNAME, "left", m_size["left"], ht, t_label["left"], GNAME);
  517. }
  518. if (t_label["right"]) {
  519. printf("%s%s:\tbox wid %g ht %g invis %s with .w at %s.e\n",
  520. MNAME, "right", m_size["right"], ht, t_label["right"], GNAME);
  521. }
  522. if (t_label["top"]) {
  523. printf("%s%s:\tbox wid %g ht %g invis %s with .s at %s.n\n",
  524. MNAME, "top", wid, m_size["top"], t_label["top"], GNAME);
  525. }
  526. if (t_label["bot"]) {
  527. printf("%s%s:\tbox wid %g ht %g invis %s with .n at %s.s\n",
  528. MNAME, "bot", wid, m_size["bot"], t_label["bot"], GNAME);
  529. }
  530. }
  531. # create tick marks for all axes
  532. function ticks( i, user_ticks, w) {
  533. user_ticks = 0;
  534. for (i = 0; i < t_num["left"]; ++i) {
  535. printf("line %s %g at %g <%s.sw, %s.nw>\n",
  536. t_where["left"] == "out" ? "left" : "right",
  537. ticklen, w = yscale(t_pos["left", i]), FNAME, FNAME);
  538. printf("\"%s \" at last line.w rjust\n", t_pos["left", i]);
  539. if (w != 0 && w != 1 && grid != "") {
  540. printf("line %s from %g <%s.sw, %s.nw> to %g <%s.se, %s.ne>\n",
  541. grid, w, FNAME, FNAME, w, FNAME, FNAME);
  542. }
  543. ++user_ticks;
  544. }
  545. for (i = 0; i < t_num["right"]; ++i) {
  546. printf("line %s %g at %g <%s.se, %s.ne>\n",
  547. t_where["right"] == "out" ? "right" : "left",
  548. ticklen, yscale(t_pos["right", i]), FNAME, FNAME);
  549. printf("\" %s\" at last line.e ljust\n", t_pos["right", i]);
  550. ++user_ticks;
  551. }
  552. for (i = 0; i < t_num["top"]; ++i) {
  553. printf("line %s %g at %g <%s.nw, %s.ne>\n",
  554. t_where["bot"] == "out" ? "up" : "down",
  555. ticklen, xscale(t_pos["top", i]), FNAME, FNAME);
  556. printf("\"%s\" at last line.n above\n", t_pos["top", i]);
  557. ++user_ticks;
  558. }
  559. for (i = 0; i < t_num["bot"]; ++i) {
  560. printf("line %s %g at %g <%s.sw, %s.se>\n",
  561. t_where["bot"] == "out" ? "down" : "up",
  562. ticklen, w = xscale(t_pos["bot", i]), FNAME, FNAME);
  563. printf("\"%s\" at last line.s below\n", t_pos["bot", i]);
  564. if (w != 0 && w != 1 && grid != "") {
  565. printf("line %s from %g <%s.sw, %s.se> to %g <%s.nw, %s.ne>\n",
  566. grid, w, FNAME, FNAME, w, FNAME, FNAME);
  567. }
  568. ++user_ticks;
  569. }
  570. if (!user_ticks) {
  571. xmax = roundceil(MINXTICKS, xmax);
  572. ymax = roundceil(MINYTICKS, ymax);
  573. xmin = roundfloor(MINXTICKS, xmin);
  574. ymin = roundfloor(MINYTICKS, ymin);
  575. ysteps = steps(MINYTICKS, ymin, ymax);
  576. #for (i = 0; i <= ysteps; ++i) {
  577. for (i = 1; i < ysteps; ++i) {
  578. printf("line left %g at %g <%s.sw, %s.nw>\n",
  579. ticklen, w = i/ysteps, FNAME, FNAME);
  580. printf("\"%s\" at last line.w rjust\n", ymin + (ymax - ymin)*i/ysteps);
  581. if (w != 0 && w != 1 && grid != "") {
  582. printf("line %s from %g <%s.sw, %s.nw> to %g <%s.se, %s.ne>\n",
  583. grid, w, FNAME, FNAME, w, FNAME, FNAME);
  584. }
  585. }
  586. xsteps = steps(MINXTICKS, xmin, xmax);
  587. #for (i = 0; i <= xsteps; ++i) {
  588. for (i = 1; i < xsteps; ++i) {
  589. printf("line down %g at %g <%s.sw, %s.se>\n",
  590. ticklen, w = i/xsteps, FNAME, FNAME);
  591. printf("\"%s\" at last line.s below\n", xmin + (xmax - xmin)*i/xsteps);
  592. if (w != 0 && w != 1 && grid != "") {
  593. printf("line %s from %g <%s.sw, %s.se> to %g <%s.nw, %s.ne>\n",
  594. grid, w, FNAME, FNAME, w, FNAME, FNAME);
  595. }
  596. }
  597. }
  598. }
  599. # scale x-value
  600. function xscale(x) {
  601. return((x-xmin)/(xmax-xmin));
  602. }
  603. # scale y-value
  604. function yscale(y) {
  605. return((y-ymin)/(ymax-ymin));
  606. }
  607. # round ranges, VERY POOR!
  608. # round to smallest e*10^log10(val) + n*e .gt. val
  609. function roundceil(ex, val, e, v) {
  610. e = ex;
  611. while (e < val) {
  612. e *= 10;
  613. }
  614. v = val;
  615. if (int(v) % e) {
  616. v = e*(int(v/e) + 1);
  617. }
  618. while (v >= val) {
  619. v -= ex;
  620. }
  621. if (debug) {
  622. printf("roundceil(%g, %g) returns %g\n",
  623. ex, val, v + ex) | "cat >&2";
  624. }
  625. return(v + ex);
  626. }
  627. # round to greatest e*10^log10(val) - n*e .lt. val
  628. function roundfloor(ex, val, e, v) {
  629. e = ex;
  630. while (e < val) {
  631. e *= 10;
  632. }
  633. if (e > ex) {
  634. e /= 10;
  635. }
  636. v = val;
  637. if (int(v) % e) {
  638. v = e*(int(v/e));
  639. }
  640. while (v <= val) {
  641. v += ex;
  642. }
  643. if (debug) {
  644. printf("roundfloor(%g, %g) returns %g\n",
  645. ex, val, v - ex) | "cat >&2";
  646. }
  647. return(v - ex);
  648. }
  649. # count of ticks
  650. function steps(defsteps, min, max)
  651. {
  652. # very simple solution
  653. return(defsteps);
  654. }
  655. # sorting routine
  656. function swap(g, i, j, t) {
  657. t = g_x[g, i];
  658. g_x[g, i] = g_x[g, j];
  659. g_x[g, j] = t;
  660. t = g_y[g, i];
  661. g_y[g, i] = g_y[g, j];
  662. g_y[g, j] = t;
  663. t = g_ch[g, i];
  664. g_ch[g, i] = g_ch[g, j];
  665. g_ch[g, j] = t;
  666. }
  667. # insertion sort
  668. function sort(g, i, j) {
  669. for (i = 1; i < g_ndata[g]; ++i) {
  670. for (j = i; j > 0 && g_x[g, j - 1] > g_x[g, j]; --j) {
  671. swap(g, j - 1, j);
  672. }
  673. }
  674. }
  675. # create data points
  676. function drawgraph(g, i) {
  677. if (g_ndata[g] == 0) {
  678. return;
  679. }
  680. sort(g);
  681. printf("G_%s: # graph no. %d\n", g_name[g], g + 1);
  682. if (g_lstyle[g] == "invis" || g_flags[g] == MARKED) {
  683. for (i = 0; i < g_ndata[g]; ++i) {
  684. printf("\"%s\" at %s.sw + (%g, %g)\n",
  685. g_ch[g, i] != "" ? g_ch[g, i] : (g_defch[g] != "" ? g_defch[g] : DEFCH),
  686. FNAME, xscale(g_x[g, i])*wid, yscale(g_y[g, i])*ht);
  687. }
  688. }
  689. if (g_lstyle[g] != "invis") {
  690. printf("%sline %s %s from %s.sw + (%g, %g)",
  691. g_spline[g], g_label[g], g_lstyle[g] == "solid" ? "" : g_lstyle[g],
  692. FNAME, xscale(g_x[g, 0])*wid, yscale(g_y[g, 0])*ht);
  693. for (i = 1; i < g_ndata[g]; ++i) {
  694. printf("\t\\\n\tthen to %s.sw + (%g, %g)", FNAME,
  695. xscale(g_x[g, i])*wid, yscale(g_y[g, i])*ht);
  696. }
  697. printf("\n");
  698. }
  699. }
  700. #vi: set tabstop=5 shiftwidth=5: