|
|
1.1 ! root 1: #include <stdio.h> ! 2: #include "pic.h" ! 3: #include "y.tab.h" ! 4: #define dprintf if(dbg)printf ! 5: ! 6: #define PI 3.141592654 ! 7: #define PI2 PI/2 ! 8: #define SCALE 200 /* default scale: units/inch */ ! 9: #define WID 150 /* default width for boxes and ellipses */ ! 10: #define HT 100 /* default height and line length */ ! 11: ! 12: /* But there's one of these in pic.h? -Bart ! 13: #define MAXOBJ 400 ! 14: */ ! 15: struct obj *objlist[MAXOBJ]; /* store the elements here */ ! 16: int nobj = 0; ! 17: ! 18: struct attr attr[40]; /* attributes stored here as collected */ ! 19: int nattr = 0; /* number of entries in attr_list */ ! 20: ! 21: #define MAXTEXT 200 ! 22: struct text text[MAXTEXT]; /* text strings stored here as collected */ ! 23: int ntext = 0; ! 24: int ntext1 = 0; /* record ntext here on entry to each figure */ ! 25: ! 26: #define SYMTAB 200 ! 27: struct symtab symtab[SYMTAB]; ! 28: int nsymtab = 0; ! 29: ! 30: coord curx = 0; ! 31: coord cury = 0; ! 32: ! 33: int hvmode = R_DIR; /* R => join left to right, D => top to bottom, etc. */ ! 34: ! 35: #define MAXTYPE 12 ! 36: int first[MAXTYPE]; /* indicates whether first of particular type */ ! 37: /* has been seen within this picture */ ! 38: ! 39: int codegen = 0; /* 1=>output for this picture; 0=>no output */ ! 40: ! 41: struct obj *makenode(); ! 42: char *malloc(); ! 43: ! 44: float deltx = 6; /* max x value in output, for scaling */ ! 45: float delty = 6; /* max y value in output, for scaling */ ! 46: float scale = 0; /* implies simply scaling by this value; no crop or shift */ ! 47: int dbg = 0; ! 48: extern FILE *yyin; /* input file pointer */ ! 49: int lineno = 0; ! 50: char *filename = "-"; ! 51: int synerr = 0; ! 52: char *cmdname; ! 53: int crop = 1; /* trim off exterior white space if non-zero */ ! 54: ! 55: #define DEV202 1 ! 56: #define DEVAPS 2 ! 57: #define DEVCAT 3 ! 58: #define DEV450 4 ! 59: ! 60: /* You may want to change this if you don't have a 202... */ ! 61: ! 62: int devtype = DEV202; ! 63: int res = 972; /* default is 202 */ ! 64: int DX = 4; /* used only for old-style troff */ ! 65: int DY = 4; ! 66: ! 67: /* mandatory values for graphic systems CAT: */ ! 68: /* ! 69: int devtype = DEVCAT; ! 70: int res = 432; ! 71: int DX = 3; ! 72: int DY = 3; ! 73: */ ! 74: ! 75: float hshift = 0; /* move this far left for text (in em's) */ ! 76: float vshift = 0.2; /* this far down */ ! 77: ! 78: coord sxmin; /* lower limit from s command */ ! 79: coord symin; ! 80: coord sxmax = 4096; /* upper */ ! 81: coord symax = 4096; ! 82: ! 83: coord xmin = 30000; /* min values found in actual data */ ! 84: coord ymin = 30000; ! 85: coord xmax = -30000; /* max */ ! 86: coord ymax = -30000; ! 87: ! 88: extern float atof(); ! 89: ! 90: main(argc,argv) ! 91: char **argv; ! 92: { ! 93: int casel, c; ! 94: ! 95: cmdname = argv[0]; ! 96: casel = 0; ! 97: while (argc > 1 && *argv[1] == '-') { ! 98: switch (c = argv[1][1]) { ! 99: case 'T': ! 100: if (strcmp(&argv[1][2], "aps") == 0) { ! 101: res = 720; ! 102: devtype = DEVAPS; ! 103: DX = DY = 1; ! 104: } else if (strcmp(&argv[1][2], "cat") == 0) { ! 105: res = 432; ! 106: devtype = DEVCAT; ! 107: DX = DY = 3; ! 108: } else if (strcmp(&argv[1][2], "450") == 0) { ! 109: res = 240; ! 110: devtype = DEV450; ! 111: } else { ! 112: res = atoi(&argv[1][2]); ! 113: } ! 114: break; ! 115: case 'c': ! 116: crop = 0; ! 117: break; ! 118: case 'l': ! 119: delty = atof(&argv[1][2]); ! 120: casel = 0; ! 121: break; ! 122: case 'w': ! 123: case 's': ! 124: if (argv[1][2] == 0) { ! 125: argv++; ! 126: argc--; ! 127: deltx = atof(&argv[1][0]); ! 128: } else ! 129: deltx = atof(&argv[1][2]); ! 130: if (c == 's') ! 131: scale = deltx; ! 132: break; ! 133: case 'd': ! 134: dbg = 1; ! 135: break; ! 136: } ! 137: argc--; ! 138: argv++; ! 139: } ! 140: if (!casel) ! 141: delty = deltx; ! 142: setdefaults(); ! 143: if (argc <= 1) { ! 144: yyin = stdin; ! 145: getdata(yyin); ! 146: } else ! 147: while (argc-- > 1) { ! 148: if ((yyin = fopen(*++argv, "r")) == NULL) { ! 149: fprintf(stderr, "pic: can't open %s\n", *argv); ! 150: exit(1); ! 151: } ! 152: filename = *argv; ! 153: getdata(yyin); ! 154: fclose(yyin); ! 155: } ! 156: exit(0); ! 157: } ! 158: ! 159: setdefaults() /* set default sizes for variables like boxht */ ! 160: { ! 161: static struct { ! 162: char *name; ! 163: int val; ! 164: } defaults[] ={ ! 165: "lineht", HT, ! 166: "linewid", HT, ! 167: "moveht", HT, ! 168: "movewid", HT, ! 169: "dashwid", HT/10, ! 170: "boxht", HT, ! 171: "boxwid", WID, ! 172: "circlerad", HT/2, ! 173: "arcrad", HT/2, ! 174: "ellipseht", HT, ! 175: "ellipsewid", WID, ! 176: "arrowht", HT/5, ! 177: "arrowwid", HT/10, ! 178: "textht", HT, ! 179: "textwid", WID, ! 180: "scale", SCALE, ! 181: NULL, 0 ! 182: }; ! 183: int i; ! 184: ! 185: for (i = 0; defaults[i].name != NULL; i++) ! 186: makevar(defaults[i].name, VARNAME, defaults[i].val); ! 187: } ! 188: ! 189: getdata(fin) ! 190: register FILE *fin; ! 191: { ! 192: char buf[1000], buf1[50]; ! 193: FILE *svyyin; ! 194: int svlineno; ! 195: char *svfilename, *p; ! 196: ! 197: lineno = 0; ! 198: while (fgets(buf, sizeof buf, fin) != NULL) { ! 199: lineno++; ! 200: if (*buf == '.' && *(buf+1) == 'P' && *(buf+2) == 'S') { ! 201: for (p = &buf[3]; *p == ' '; p++) ! 202: ; ! 203: if (*p++ == '<') { ! 204: svyyin = yyin; ! 205: svlineno = lineno; ! 206: svfilename = filename; ! 207: sscanf(p, "%s", buf1); ! 208: if ((yyin = fopen(buf1, "r")) == NULL) { ! 209: fprintf(stderr, "pic: can't open %s\n", buf1); ! 210: exit(1); ! 211: } ! 212: lineno = 0; ! 213: filename = p; ! 214: getdata(yyin); ! 215: fclose(yyin); ! 216: lineno = svlineno; ! 217: yyin = svyyin; ! 218: filename = svfilename; ! 219: continue; ! 220: } ! 221: reset(); ! 222: yyparse(); ! 223: if (buf[3] == ' ') /* assume next thing is width */ ! 224: deltx = delty = atof(&buf[4]); ! 225: else { /* use scale to determine size */ ! 226: int t; ! 227: t = xmax - xmin; ! 228: if (t == 0) ! 229: t = ymax - ymin; ! 230: deltx = delty = (float) t / (float)getvar(lookup("scale")); ! 231: } ! 232: dprintf("deltx = %.3f\n", deltx); ! 233: if (codegen && !synerr) { ! 234: openpl(&buf[3]); /* puts out .PS, with ht & wid stuck in */ ! 235: print(); /* assumes \n at end */ ! 236: closepl(); /* this does the .PE */ ! 237: } ! 238: } ! 239: else ! 240: fputs(buf, stdout); ! 241: } ! 242: } ! 243: ! 244: print() ! 245: { ! 246: struct obj *p; ! 247: int i, j, m; ! 248: coord x0, y0, x1, y1, ox, oy, dx, dy; ! 249: ! 250: for (i = 0; i < nobj; i++) { ! 251: p = objlist[i]; ! 252: ox = p->o_x; ! 253: oy = p->o_y; ! 254: x1 = p->o_val[0]; ! 255: y1 = p->o_val[1]; ! 256: m = p->o_mode; ! 257: switch (p->o_type) { ! 258: case TROFF: ! 259: troff(text[p->o_nt1].t_val); ! 260: break; ! 261: case BOX: ! 262: move(ox, oy); ! 263: dotext(p); /* if there are any text strings */ ! 264: x0 = ox - (x1+1) / 2; ! 265: y0 = oy - (y1+1) / 2; ! 266: x1 = ox + x1 / 2; ! 267: y1 = oy + y1 / 2; ! 268: if (p->o_attr & INVIS) ! 269: ; /* nothing at all */ ! 270: else if (p->o_dotdash == 0) ! 271: box(x0, y0, x1, y1); ! 272: else ! 273: dotbox(x0, y0, x1, y1, p->o_dotdash, p->o_ddval); ! 274: if (ishor(m)) ! 275: move(isright(m) ? x1 : x0, oy); /* right side */ ! 276: else ! 277: move(ox, isdown(m) ? y0 : y1); /* bottom */ ! 278: break; ! 279: case CIRCLE: ! 280: move(ox, oy); ! 281: dotext(p); ! 282: if ((p->o_attr & INVIS) == 0) ! 283: circle(ox, oy, x1); ! 284: if (ishor(m)) ! 285: move(ox + isright(m) ? x1 : -x1, oy); ! 286: else ! 287: move(ox, oy + isup(m) ? x1 : -x1); ! 288: break; ! 289: case ELLIPSE: ! 290: move(ox, oy); ! 291: dotext(p); ! 292: if ((p->o_attr & INVIS) == 0) ! 293: ellipse(ox, oy, x1, y1); ! 294: if (ishor(m)) ! 295: move(ox + isright(m) ? x1 : -x1, oy); ! 296: else ! 297: move(ox, oy - isdown(m) ? y1 : -y1); ! 298: break; ! 299: case ARC: ! 300: move(ox, oy); ! 301: dotext(p); ! 302: if (p->o_attr & HEAD1) ! 303: arrow(x1 - (y1 - oy), y1 + (x1 - ox), ! 304: x1, y1, p->o_val[4], p->o_val[5]); ! 305: if (p->o_attr & INVIS) ! 306: /* probably wrong when it's cw */ ! 307: move(x1, y1); ! 308: else ! 309: arc(ox, oy, x1, y1, p->o_val[2], p->o_val[3]); ! 310: if (p->o_attr & HEAD2) ! 311: arrow(p->o_val[2] + p->o_val[3] - oy, p->o_val[3] - (p->o_val[2] - ox), ! 312: p->o_val[2], p->o_val[3], p->o_val[4], p->o_val[5]); ! 313: if (p->o_attr & CW_ARC) ! 314: move(x1, y1); /* because drawn backwards */ ! 315: break; ! 316: case LINE: ! 317: case ARROW: ! 318: case SPLINE: ! 319: move((ox + x1)/2, (oy + y1)/2); /* center */ ! 320: dotext(p); ! 321: if (p->o_attr & HEAD1) ! 322: arrow(ox + p->o_val[5], oy + p->o_val[6], ox, oy, p->o_val[2], p->o_val[3]); ! 323: if (p->o_attr & INVIS) ! 324: move(x1, y1); ! 325: else if (p->o_type == SPLINE) ! 326: spline(ox, oy, p->o_val[4], &p->o_val[5]); ! 327: else { ! 328: int i, j, ndx, ndy; ! 329: dx = ox; ! 330: dy = oy; ! 331: for (i=0, j=5; i < p->o_val[4]; i++, j += 2) { ! 332: ndx = dx + p->o_val[j]; ! 333: ndy = dy + p->o_val[j+1]; ! 334: if (p->o_dotdash == 0) ! 335: line(dx, dy, ndx, ndy); ! 336: else ! 337: dotline(dx, dy, ndx, ndy, p->o_dotdash, p->o_ddval); ! 338: dx = ndx; ! 339: dy = ndy; ! 340: } ! 341: } ! 342: if (p->o_attr & HEAD2) { ! 343: int i, j; ! 344: dx = ox; ! 345: dy = oy; ! 346: for (i = 0, j = 5; i < p->o_val[4] - 1; i++, j += 2) { ! 347: dx += p->o_val[j]; ! 348: dy += p->o_val[j+1]; ! 349: } ! 350: arrow(dx, dy, x1, y1, p->o_val[2], p->o_val[3]); ! 351: } ! 352: break; ! 353: case MOVE: ! 354: move(ox, oy); ! 355: dotext(p); ! 356: break; ! 357: case TEXT: ! 358: move(ox, oy); ! 359: label(x1, y1, 0); ! 360: free(x1); ! 361: break; ! 362: } ! 363: } ! 364: } ! 365: ! 366: dotline(x0, y0, x1, y1, ddtype, ddval) /* dotted line */ ! 367: coord x0, y0, x1, y1; ! 368: int ddtype; ! 369: int ddval; ! 370: { ! 371: static int prevval = SCALE/20; /* 20 per inch by default */ ! 372: int i, numdots; ! 373: double a, b, sqrt(), dx, dy; ! 374: ! 375: if (ddval == 0) ! 376: ddval = prevval; ! 377: prevval = ddval; ! 378: /* don't save dot/dash value */ ! 379: dx = x1 - x0; ! 380: dy = y1 - y0; ! 381: if (ddtype == DOT) { ! 382: numdots = sqrt(dx*dx + dy*dy) / prevval + 0.5; ! 383: for (i = 0; i <= numdots; i++) { ! 384: a = (float) i / (float) numdots; ! 385: move(x0 + (int)(a * dx), y0 + (int)(a * dy)); ! 386: dot(); ! 387: } ! 388: } else if (ddtype == DASH) { ! 389: double d, dashsize, spacesize; ! 390: d = sqrt(dx*dx + dy*dy) + 0.5; ! 391: if (d <= 2 * prevval) { ! 392: line(x0, y0, x1, y1); ! 393: return; ! 394: } ! 395: numdots = d / (2 * prevval - 1) + 1; /* ceiling */ ! 396: dashsize = prevval; ! 397: spacesize = (d - numdots * dashsize) / (numdots - 1); ! 398: for (i = 0; i < numdots-1; i++) { ! 399: a = i * (dashsize + spacesize) / d; ! 400: b = a + dashsize / d; ! 401: line(x0 + (int)(a*dx), y0 + (int)(a*dy), x0 + (int)(b*dx), y0 + (int)(b*dy)); ! 402: a = b; ! 403: b = a + spacesize / d; ! 404: move(x0 + (int)(a*dx), y0 + (int)(a*dy)); ! 405: } ! 406: line(x0 + (int)(b * dx), y0 + (int)(b * dy), x1, y1); ! 407: } ! 408: prevval = SCALE/20; ! 409: } ! 410: ! 411: dotbox(x0, y0, x1, y1, ddtype, ddval) /* dotted or dashed box */ ! 412: coord x0, y0, x1, y1; ! 413: int ddtype; ! 414: int ddval; ! 415: { ! 416: dotline(x0, y0, x1, y0, ddtype, ddval); ! 417: dotline(x1, y0, x1, y1, ddtype, ddval); ! 418: dotline(x1, y1, x0, y1, ddtype, ddval); ! 419: dotline(x0, y1, x0, y0, ddtype, ddval); ! 420: } ! 421: ! 422: dotext(p) /* print text strings of p in proper vertical spacing */ ! 423: struct obj *p; ! 424: { ! 425: int i, nhalf; ! 426: ! 427: nhalf = p->o_nt2 - p->o_nt1 - 1; ! 428: for (i = p->o_nt1; i < p->o_nt2; i++) { ! 429: label(text[i].t_val, text[i].t_type, nhalf); ! 430: nhalf -= 2; ! 431: } ! 432: } ! 433: ! 434: reset() ! 435: { ! 436: int i; ! 437: ! 438: for (i = 0; i < nobj; i++) ! 439: free(objlist[i]); ! 440: nobj = 0; ! 441: nattr = 0; ! 442: for (i = 0; i < ntext; i++) ! 443: free(text[i].t_val); ! 444: ntext = ntext1 = 0; ! 445: for (i = 0; i < MAXTYPE; i++) ! 446: first[i] = 0; ! 447: codegen = synerr = 0; ! 448: curx = cury = 0; ! 449: hvmode = R_DIR; ! 450: sxmin = symin = 0; ! 451: sxmax = symax = 4096; ! 452: xmin = ymin = 30000; ! 453: xmax = ymax = -30000; ! 454: } ! 455: ! 456: coord xstack[20]; /* store curx here for pushdown {...} */ ! 457: coord ystack[20]; ! 458: int hvstack[20]; ! 459: int nstack = 0; ! 460: ! 461: push() ! 462: { ! 463: xstack[nstack] = curx; ! 464: ystack[nstack] = cury; ! 465: hvstack[nstack] = hvmode; ! 466: nstack++; ! 467: } ! 468: ! 469: pop() ! 470: { ! 471: struct obj *p; ! 472: ! 473: nstack--; ! 474: curx = xstack[nstack]; ! 475: cury = ystack[nstack]; ! 476: hvmode = hvstack[nstack]; ! 477: p = makenode(MOVE, 0); ! 478: dprintf("M %d %d\n", curx, cury); ! 479: } ! 480: ! 481: setvar(n, v, t) /* store v in variable in table slot n */ ! 482: { ! 483: symtab[n].s_val = v; ! 484: symtab[n].s_type = t; ! 485: } ! 486: ! 487: getvar(n) /* return value of variable in slot n */ ! 488: { ! 489: return(symtab[n].s_val); ! 490: } ! 491: ! 492: setdir(n) /* set direction from n */ ! 493: int n; ! 494: { ! 495: switch (n) { ! 496: case UP: hvmode = U_DIR; break; ! 497: case DOWN: hvmode = D_DIR; break; ! 498: case LEFT: hvmode = L_DIR; break; ! 499: case RIGHT: hvmode = R_DIR; break; ! 500: } ! 501: return(hvmode); ! 502: } ! 503: ! 504: coord getcomp(p, t) /* return component of a position */ ! 505: struct obj *p; ! 506: int t; ! 507: { ! 508: switch (t) { ! 509: case DOTX: ! 510: return(p->o_x); ! 511: case DOTY: ! 512: return(p->o_y); ! 513: case DOTWID: ! 514: switch (p->o_type) { ! 515: case BOX: ! 516: return(p->o_val[0]); ! 517: case CIRCLE: ! 518: case ELLIPSE: ! 519: return(2 * p->o_val[0]); ! 520: case LINE: ! 521: case ARROW: ! 522: return(p->o_val[0] - p->o_x); ! 523: } ! 524: case DOTHT: ! 525: switch (p->o_type) { ! 526: case BOX: ! 527: return(p->o_val[1]); ! 528: case CIRCLE: ! 529: case ELLIPSE: ! 530: return(2 * p->o_val[1]); ! 531: case LINE: ! 532: case ARROW: ! 533: return(p->o_val[1] - p->o_y); ! 534: } ! 535: case DOTRAD: ! 536: switch (p->o_type) { ! 537: case CIRCLE: ! 538: case ELLIPSE: ! 539: return(p->o_val[0]); ! 540: } ! 541: } ! 542: } ! 543: ! 544: ! 545: makeattr(type, val) /* add attribute type and val */ ! 546: int type; ! 547: int val; /* typing probably wrong */ ! 548: { ! 549: if (type == 0 && val == 0) { /* clear table for next stat */ ! 550: nattr = 0; ! 551: return; ! 552: } ! 553: dprintf("attr %d: %d %d\n", nattr, type, val); ! 554: attr[nattr].a_type = type; ! 555: attr[nattr].a_val = val; ! 556: nattr++; ! 557: } ! 558: ! 559: troffgen(s) /* save away a string of troff commands */ ! 560: char *s; ! 561: { ! 562: savetext(CENTER, s); /* use the existing text mechanism */ ! 563: makenode(TROFF, 0); ! 564: } ! 565: ! 566: printexpr(n) /* print expression for debugging */ ! 567: int n; ! 568: { ! 569: dprintf("%d\n", n); ! 570: } ! 571: ! 572: struct obj *boxgen(type) ! 573: { ! 574: static int prevh = HT; ! 575: static int prevw = WID; /* golden mean, sort of */ ! 576: int i, invis, at, ddtype, ddval; ! 577: int with, xwith, ywith; ! 578: int h, w; ! 579: coord x0, y0, x1, y1; ! 580: struct obj *p, *ppos; ! 581: ! 582: /* EXPENSIVE! */ ! 583: h = getvar(lookup("boxht")); ! 584: w = getvar(lookup("boxwid")); ! 585: invis = at = 0; ! 586: with = xwith = ywith = 0; ! 587: ddtype = ddval = 0; ! 588: for (i = 0; i < nattr; i++) { ! 589: switch (attr[i].a_type) { ! 590: case HEIGHT: ! 591: h = attr[i].a_val; ! 592: break; ! 593: case WIDTH: ! 594: w = attr[i].a_val; ! 595: break; ! 596: case SAME: ! 597: h = prevh; ! 598: w = prevw; ! 599: break; ! 600: case WITH: ! 601: with = attr[i].a_val; /* corner */ ! 602: break; ! 603: case AT: ! 604: ppos = (struct obj *) attr[i].a_val; ! 605: curx = ppos->o_x; ! 606: cury = ppos->o_y; ! 607: at++; ! 608: break; ! 609: case INVIS: ! 610: invis = INVIS; ! 611: break; ! 612: case DOT: ! 613: case DASH: ! 614: ddtype = attr[i].a_type; ! 615: ddval = attr[i].a_val; ! 616: if (ddval == 0) ! 617: ddval = getvar(lookup("dashwid")); ! 618: break; ! 619: case LJUST: case RJUST: case CENTER: case SPREAD: case FILL: case ABOVE: case BELOW: ! 620: savetext(attr[i].a_type, attr[i].a_val); ! 621: break; ! 622: } ! 623: } ! 624: if (with) { ! 625: switch (with) { ! 626: case NORTH: ywith = -((h+1) / 2); break; ! 627: case SOUTH: ywith = h / 2; break; ! 628: case EAST: xwith = -((w+1) / 2); break; ! 629: case WEST: xwith = w / 2; break; ! 630: case NE: xwith = -((w+1) / 2); ywith = -((h+1) / 2); break; ! 631: case SE: xwith = -((w+1) / 2); ywith = h / 2; break; ! 632: case NW: xwith = w / 2; ywith = -((h+1) / 2); break; ! 633: case SW: xwith = w / 2; ywith = h / 2; break; ! 634: } ! 635: curx += xwith; ! 636: cury += ywith; ! 637: } ! 638: if (!at) { ! 639: if (isright(hvmode)) ! 640: curx += (w+1) / 2; ! 641: else if (isleft(hvmode)) ! 642: curx -= w / 2; ! 643: else if (isup(hvmode)) ! 644: cury += (h+1) / 2; ! 645: else ! 646: cury -= h / 2; ! 647: } ! 648: x0 = curx - w / 2; ! 649: y0 = cury - h / 2; ! 650: x1 = curx + (w+1) / 2; ! 651: y1 = cury + (h+1) / 2; ! 652: extreme(x0, y0); ! 653: extreme(x1, y1); ! 654: p = makenode(BOX, 2); ! 655: p->o_val[0] = w; ! 656: p->o_val[1] = h; ! 657: p->o_dotdash = ddtype; ! 658: p->o_ddval = ddval; ! 659: p->o_attr = invis; ! 660: dprintf("B %d %d %d %d at %d %d, h=%d, w=%d\n", x0, y0, x1, y1, curx, cury, h, w); ! 661: if (isright(hvmode)) ! 662: curx = x1; ! 663: else if (isleft(hvmode)) ! 664: curx = x0; ! 665: else if (isup(hvmode)) ! 666: cury = y1; ! 667: else ! 668: cury = y0; ! 669: prevh = h; ! 670: prevw = w; ! 671: return(p); ! 672: } ! 673: ! 674: savetext(t, s) /* record text elements for current object */ ! 675: int t; ! 676: char *s; ! 677: { ! 678: switch (t) { ! 679: case CENTER: t = 'C'; break; ! 680: case LJUST: t = 'L'; break; ! 681: case RJUST: t = 'R'; break; ! 682: case SPREAD: t = 'S'; break; ! 683: case FILL: t = 'F'; break; ! 684: case ABOVE: t = 'A'; break; ! 685: case BELOW: t = 'B'; break; ! 686: } ! 687: if (ntext >= MAXTEXT) { ! 688: fprintf(stderr, "too many text strings (%d)\n", ntext); ! 689: exit(1); ! 690: } ! 691: text[ntext].t_type = t; ! 692: text[ntext].t_val = s; ! 693: dprintf("saving %c text %s at %d\n", t, s, ntext); ! 694: ntext++; ! 695: } ! 696: ! 697: struct obj *circgen(type) ! 698: { ! 699: static int rad[2] = { HT/2, WID/2 }; ! 700: static int rad2[2] = { HT/2, HT/2 }; ! 701: static coord x0, y0, x1, y1, x2, y2; ! 702: int i, at, t, invis; ! 703: int with, xwith, ywith; ! 704: int r, r2; ! 705: struct obj *p, *ppos; ! 706: ! 707: at = invis = 0; ! 708: with = xwith = ywith = 0; ! 709: t = (type == CIRCLE) ? 0 : 1; ! 710: if (type == CIRCLE) ! 711: r = r2 = getvar(lookup("circlerad")); ! 712: else if (type == ELLIPSE) { ! 713: r = getvar(lookup("ellipsewid")) / 2; ! 714: r2 = getvar(lookup("ellipseht")) / 2; ! 715: } ! 716: for (i = 0; i < nattr; i++) ! 717: switch (attr[i].a_type) { ! 718: case LJUST: case RJUST: case CENTER: case SPREAD: case FILL: case ABOVE: case BELOW: ! 719: savetext(attr[i].a_type, attr[i].a_val); ! 720: break; ! 721: case RADIUS: ! 722: r = attr[i].a_val; ! 723: break; ! 724: case DIAMETER: ! 725: case WIDTH: ! 726: r = (attr[i].a_val + 1) / 2; ! 727: break; ! 728: case HEIGHT: ! 729: r2 = (attr[i].a_val + 1) / 2; ! 730: break; ! 731: case SAME: ! 732: r = rad[t]; ! 733: r2 = rad2[t]; ! 734: break; ! 735: case WITH: ! 736: with = attr[i].a_val; ! 737: break; ! 738: case AT: ! 739: ppos = (struct obj *) attr[i].a_val; ! 740: curx = ppos->o_x; ! 741: cury = ppos->o_y; ! 742: at++; ! 743: break; ! 744: case INVIS: ! 745: invis = INVIS; ! 746: break; ! 747: } ! 748: if (type == CIRCLE) ! 749: r2 = r; /* probably superfluous */ ! 750: if (with) { ! 751: switch (with) { ! 752: case NORTH: ywith = -r2; break; ! 753: case SOUTH: ywith = r2; break; ! 754: case EAST: xwith = -r; break; ! 755: case WEST: xwith = r; break; ! 756: case NE: xwith = -r * 0.707; ywith = -r2 * 0.707; break; ! 757: case SE: xwith = -r * 0.707; ywith = r2 * 0.707; break; ! 758: case NW: xwith = r * 0.707; ywith = -r2 * 0.707; break; ! 759: case SW: xwith = r * 0.707; ywith = r2 * 0.707; break; ! 760: } ! 761: curx += xwith; ! 762: cury += ywith; ! 763: } ! 764: if (!at) { ! 765: if (isright(hvmode)) ! 766: curx += r; ! 767: else if (isleft(hvmode)) ! 768: curx -= r; ! 769: else if (isup(hvmode)) ! 770: cury += r2; ! 771: else ! 772: cury -= r2; ! 773: } ! 774: p = makenode(type, 2); ! 775: p->o_val[0] = rad[t] = r; ! 776: p->o_val[1] = rad2[t] = r2; ! 777: if (r <= 0 || r2 <= 0) { ! 778: yyerror("%s has invalid radius %d\n", (type==CIRCLE) ? "circle" : "ellipse", r<r2 ? r : r2); ! 779: } ! 780: p->o_attr = invis; ! 781: extreme(curx+r, cury+r2); ! 782: extreme(curx-r, cury-r2); ! 783: if (type == CIRCLE) ! 784: dprintf("C %d %d %d\n", curx, cury, r); ! 785: if (type == ELLIPSE) ! 786: dprintf("E %d %d %d %d\n", curx, cury, r, r2); ! 787: if (isright(hvmode)) ! 788: curx += r; ! 789: else if (isleft(hvmode)) ! 790: curx -= r; ! 791: else if (isup(hvmode)) ! 792: cury += r2; ! 793: else ! 794: cury -= r2; ! 795: return(p); ! 796: } ! 797: ! 798: struct obj *arcgen(type) /* handles circular and (eventually) elliptical arcs */ ! 799: { ! 800: static int prevw = HT/10; ! 801: static int prevh = HT/5; ! 802: static int prevrad = HT/2; ! 803: static int dtox[2][4] ={ 1, -1, -1, 1, 1, 1, -1, -1 }; ! 804: static int dtoy[2][4] ={ 1, 1, -1, -1, -1, 1, 1, -1 }; ! 805: static int dctrx[2][4] ={ 0, -1, 0, 1, 0, 1, 0, -1 }; ! 806: static int dctry[2][4] ={ 1, 0, -1, 0, -1, 0, 1, 0 }; ! 807: static int nexthv[2][4] ={ U_DIR, L_DIR, D_DIR, R_DIR, D_DIR, R_DIR, U_DIR, L_DIR }; ! 808: double sqrt(), atan2(), sin(), cos(); ! 809: float dx2, dy2, ht, phi, r, d; ! 810: int i, head, to, at, cw, invis; ! 811: struct obj *p, *ppos; ! 812: coord fromx, fromy, tox, toy; ! 813: ! 814: prevrad = getvar(lookup("arcrad")); ! 815: prevh = getvar(lookup("arrowht")); ! 816: prevw = getvar(lookup("arrowwid")); ! 817: fromx = curx; ! 818: fromy = cury; ! 819: head = to = at = cw = invis = 0; ! 820: for (i = 0; i < nattr; i++) { ! 821: switch (attr[i].a_type) { ! 822: case LJUST: case RJUST: case CENTER: case SPREAD: case FILL: case ABOVE: case BELOW: ! 823: savetext(attr[i].a_type, attr[i].a_val); ! 824: break; ! 825: case HEAD: ! 826: head += attr[i].a_val; ! 827: break; ! 828: case INVIS: ! 829: invis = INVIS; ! 830: break; ! 831: case HEIGHT: /* length of arrowhead */ ! 832: prevh = attr[i].a_val; ! 833: break; ! 834: case WIDTH: /* width of arrowhead */ ! 835: prevw = attr[i].a_val; ! 836: break; ! 837: case RADIUS: ! 838: prevrad = attr[i].a_val; ! 839: break; ! 840: case DIAMETER: ! 841: prevrad = attr[i].a_val / 2; ! 842: break; ! 843: case CW: ! 844: cw = 1; ! 845: break; ! 846: case FROM: /* start point of arc */ ! 847: ppos = (struct obj *) attr[i].a_val; ! 848: fromx = ppos->o_x; ! 849: fromy = ppos->o_y; ! 850: break; ! 851: case TO: /* end point of arc */ ! 852: ppos = (struct obj *) attr[i].a_val; ! 853: tox = ppos->o_x; ! 854: toy = ppos->o_y; ! 855: to++; ! 856: break; ! 857: case AT: /* center of arc */ ! 858: ppos = (struct obj *) attr[i].a_val; ! 859: curx = ppos->o_x; ! 860: cury = ppos->o_y; ! 861: at = 1; ! 862: break; ! 863: case UP: ! 864: hvmode = U_DIR; ! 865: break; ! 866: case DOWN: ! 867: hvmode = D_DIR; ! 868: break; ! 869: case RIGHT: ! 870: hvmode = R_DIR; ! 871: break; ! 872: case LEFT: ! 873: hvmode = L_DIR; ! 874: break; ! 875: } ! 876: } ! 877: if (!at && !to) { /* the defaults are mostly OK */ ! 878: curx = fromx + prevrad * dctrx[cw][hvmode]; ! 879: cury = fromy + prevrad * dctry[cw][hvmode]; ! 880: tox = fromx + prevrad * dtox[cw][hvmode]; ! 881: toy = fromy + prevrad * dtoy[cw][hvmode]; ! 882: hvmode = nexthv[cw][hvmode]; ! 883: } ! 884: else if (!at) { ! 885: dx2 = (float)(tox - fromx) / 2; ! 886: dy2 = (float)(toy - fromy) / 2; ! 887: phi = atan2(dy2, dx2) + (cw ? -PI2 : PI2); ! 888: for (r=prevrad; (d = r*r - (dx2*dx2+dy2*dy2)) <= 0.0; r *= 2) ! 889: ; /* this kludge gets around too-small radii */ ! 890: ht = sqrt(d); ! 891: curx = fromx + dx2 + ht * cos(phi) + 0.5; ! 892: cury = fromy + dy2 + ht * sin(phi) + 0.5; ! 893: dprintf("dx2,dy2=%g,%g, phi=%g, r,ht=%g,%g\n", ! 894: dx2, dy2, phi, r, ht); ! 895: } ! 896: else if (at && !to) { /* do we have all the cases??? */ ! 897: tox = fromx + prevrad * dtox[cw][hvmode]; ! 898: toy = fromy + prevrad * dtoy[cw][hvmode]; ! 899: hvmode = nexthv[cw][hvmode]; ! 900: } ! 901: if (cw) { /* interchange roles of from-to and heads */ ! 902: coord temp; ! 903: temp = fromx; fromx = tox; tox = temp; ! 904: temp = fromy; fromy = toy; toy = temp; ! 905: if (head == HEAD1) ! 906: head = HEAD2; ! 907: else if (head == HEAD2) ! 908: head = HEAD1; ! 909: } ! 910: p = makenode(type, 6); ! 911: /* these are wrong in general */ ! 912: extreme(fromx, fromy); ! 913: extreme(tox, toy); ! 914: p->o_val[0] = fromx; ! 915: p->o_val[1] = fromy; ! 916: p->o_val[2] = tox; ! 917: p->o_val[3] = toy; ! 918: if (cw) { ! 919: curx = fromx; ! 920: cury = fromy; ! 921: } else { ! 922: curx = tox; ! 923: cury = toy; ! 924: } ! 925: p->o_val[4] = prevw; ! 926: p->o_val[5] = prevh; ! 927: p->o_attr = head | (cw ? CW_ARC : 0) | invis; ! 928: dprintf("arc at %d %d from %d %d to %d %d head %d %d\n", ! 929: p->o_x, p->o_y, ! 930: p->o_val[0], p->o_val[1], p->o_val[2], p->o_val[3], p->o_val[4], p->o_val[5]); ! 931: return(p); ! 932: } ! 933: ! 934: struct obj *linegen(type) ! 935: { ! 936: static int prevdx = HT; ! 937: static int prevdy = 0; ! 938: static int prevw = HT/10; ! 939: static int prevh = HT/5; ! 940: int i, j, some, head, ddtype, ddval, invis; ! 941: int chop, chop1, chop2, x0, y0, x1, y1; ! 942: double sin(), cos(), atan2(), theta; ! 943: int defx, defy; ! 944: struct obj *p, *ppos; ! 945: static int xtab[] = { 1, 0, -1, 0 }; /* R=0, U=1, L=2, D=3 */ ! 946: static int ytab[] = { 0, 1, 0, -1 }; ! 947: int ndxy, dx[50], dy[50]; ! 948: coord nx, ny; ! 949: ! 950: nx = curx; ! 951: ny = cury; ! 952: defx = getvar(lookup("linewid")); ! 953: defy = getvar(lookup("lineht")); ! 954: prevh = getvar(lookup("arrowht")); ! 955: prevw = getvar(lookup("arrowwid")); ! 956: dx[0] = dy[0] = ndxy = some = head = invis = 0; ! 957: chop = chop1 = chop2 = 0; ! 958: ddtype = ddval = 0; ! 959: for (i = 0; i < nattr; i++) { ! 960: switch (attr[i].a_type) { ! 961: case LJUST: case RJUST: case CENTER: case SPREAD: case FILL: case ABOVE: case BELOW: ! 962: savetext(attr[i].a_type, attr[i].a_val); ! 963: break; ! 964: case HEAD: ! 965: head += attr[i].a_val; ! 966: break; ! 967: case INVIS: ! 968: invis = INVIS; ! 969: break; ! 970: case CHOP: ! 971: if (chop++ == 0) ! 972: chop1 = chop2 = attr[i].a_val; ! 973: else ! 974: chop2 = attr[i].a_val; ! 975: break; ! 976: case DOT: ! 977: case DASH: ! 978: ddtype = attr[i].a_type; ! 979: ddval = attr[i].a_val; ! 980: if (ddval == 0) ! 981: ddval = getvar(lookup("dashwid")); ! 982: break; ! 983: case SAME: ! 984: dx[ndxy] = prevdx; ! 985: dy[ndxy] = prevdy; ! 986: some++; ! 987: break; ! 988: case LEFT: ! 989: dx[ndxy] -= (attr[i].a_val==0) ? defx : attr[i].a_val; ! 990: some++; ! 991: hvmode = L_DIR; ! 992: break; ! 993: case RIGHT: ! 994: dx[ndxy] += (attr[i].a_val==0) ? defx : attr[i].a_val; ! 995: some++; ! 996: hvmode = R_DIR; ! 997: break; ! 998: case UP: ! 999: dy[ndxy] += (attr[i].a_val==0) ? defy : attr[i].a_val; ! 1000: some++; ! 1001: hvmode = U_DIR; ! 1002: break; ! 1003: case DOWN: ! 1004: dy[ndxy] -= (attr[i].a_val==0) ? defy : attr[i].a_val; ! 1005: some++; ! 1006: hvmode = D_DIR; ! 1007: break; ! 1008: case HEIGHT: /* length of arrowhead */ ! 1009: prevh = attr[i].a_val; ! 1010: break; ! 1011: case WIDTH: /* width of arrowhead */ ! 1012: prevw = attr[i].a_val; ! 1013: break; ! 1014: case TO: ! 1015: if (some) { ! 1016: nx += dx[ndxy]; ! 1017: ny += dy[ndxy]; ! 1018: ndxy++; ! 1019: dx[ndxy] = dy[ndxy] = some = 0; ! 1020: } ! 1021: ppos = (struct obj *) attr[i].a_val; ! 1022: dx[ndxy] = ppos->o_x - nx; ! 1023: dy[ndxy] = ppos->o_y - ny; ! 1024: some++; ! 1025: break; ! 1026: case BY: ! 1027: ppos = (struct obj *) attr[i].a_val; ! 1028: dx[ndxy] = ppos->o_x; ! 1029: dy[ndxy] = ppos->o_y; ! 1030: some++; ! 1031: break; ! 1032: case THEN: /* turn off any previous accumulation */ ! 1033: if (some) { ! 1034: nx += dx[ndxy]; ! 1035: ny += dy[ndxy]; ! 1036: ndxy++; ! 1037: dx[ndxy] = dy[ndxy] = some = 0; ! 1038: } ! 1039: break; ! 1040: case FROM: ! 1041: case AT: ! 1042: ppos = (struct obj *) attr[i].a_val; ! 1043: nx = curx = ppos->o_x; ! 1044: ny = cury = ppos->o_y; ! 1045: break; ! 1046: } ! 1047: } ! 1048: if (some) { ! 1049: nx += dx[ndxy]; ! 1050: ny += dy[ndxy]; ! 1051: ndxy++; ! 1052: defx = dx[ndxy-1]; ! 1053: defy = dy[ndxy-1]; ! 1054: } else { ! 1055: defx *= xtab[hvmode]; ! 1056: defy *= ytab[hvmode]; ! 1057: dx[ndxy] = defx; ! 1058: dy[ndxy] = defy; ! 1059: ndxy++; ! 1060: nx += defx; ! 1061: ny += defy; ! 1062: } ! 1063: prevdx = defx; ! 1064: prevdy = defy; ! 1065: if (chop) { ! 1066: if (chop == 1 && chop1 == 0) /* just said "chop", so use default */ ! 1067: chop1 = chop2 = getvar(lookup("circlerad")); ! 1068: theta = atan2((float) defy, (float) defx); ! 1069: x0 = chop1 * cos(theta); ! 1070: y0 = chop1 * sin(theta); ! 1071: curx += x0; ! 1072: cury += y0; ! 1073: x1 = chop2 * cos(theta); ! 1074: y1 = chop2 * sin(theta); ! 1075: nx -= x1; ! 1076: ny -= y1; ! 1077: dx[0] -= x0; ! 1078: dy[0] -= y0; ! 1079: dx[ndxy-1] -= x1; ! 1080: dy[ndxy-1] -= y1; ! 1081: if(dbg)printf("chopping %d %d %d %d; cur=%d,%d end=%d,%d\n", ! 1082: x0, y0, x1, y1, curx, cury, nx, ny); ! 1083: } ! 1084: p = makenode(type, 5 + 2 * ndxy); ! 1085: curx = p->o_val[0] = nx; ! 1086: cury = p->o_val[1] = ny; ! 1087: if (head || type == ARROW) { ! 1088: p->o_val[2] = prevw; ! 1089: p->o_val[3] = prevh; ! 1090: if (head == 0) ! 1091: head = HEAD2; /* default arrow head */ ! 1092: } ! 1093: p->o_attr = head | invis; ! 1094: p->o_val[4] = ndxy; ! 1095: nx = p->o_x; ! 1096: ny = p->o_y; ! 1097: for (i = 0, j = 5; i < ndxy; i++, j += 2) { ! 1098: p->o_val[j] = dx[i]; ! 1099: p->o_val[j+1] = dy[i]; ! 1100: extreme(nx += dx[i], ny += dy[i]); ! 1101: } ! 1102: p->o_dotdash = ddtype; ! 1103: p->o_ddval = ddval; ! 1104: if (dbg) { ! 1105: printf("S or L from %d %d to %d %d with %d elements:\n", p->o_x, p->o_y, curx, cury, ndxy); ! 1106: for (i = 0, j = 5; i < ndxy; i++, j += 2) ! 1107: printf("%d %d\n", p->o_val[j], p->o_val[j+1]); ! 1108: } ! 1109: extreme(p->o_x, p->o_y); ! 1110: extreme(curx, cury); ! 1111: return(p); ! 1112: } ! 1113: ! 1114: struct obj *splinegen(type) ! 1115: { ! 1116: linegen(type); ! 1117: } ! 1118: ! 1119: struct obj *movegen(type) ! 1120: { ! 1121: static int prevdx, prevdy; ! 1122: int i, dx, dy, some; ! 1123: int defx, defy; ! 1124: struct obj *p; ! 1125: struct obj *ppos; ! 1126: static int xtab[] = { 1, 0, -1, 0 }; /* R=0, U=1, L=2, D=3 */ ! 1127: static int ytab[] = { 0, 1, 0, -1 }; ! 1128: ! 1129: defx = getvar(lookup("movewid")); ! 1130: defy = getvar(lookup("moveht")); ! 1131: dx = dy = some = 0; ! 1132: for (i = 0; i < nattr; i++) { ! 1133: switch (attr[i].a_type) { ! 1134: case LJUST: case RJUST: case CENTER: case SPREAD: case FILL: case ABOVE: case BELOW: ! 1135: savetext(attr[i].a_type, attr[i].a_val); ! 1136: break; ! 1137: case SAME: ! 1138: dx = prevdx; ! 1139: dy = prevdy; ! 1140: some++; ! 1141: break; ! 1142: case LEFT: ! 1143: dx -= (attr[i].a_val==0) ? defx : attr[i].a_val; ! 1144: some++; ! 1145: hvmode = L_DIR; ! 1146: break; ! 1147: case RIGHT: ! 1148: dx += (attr[i].a_val==0) ? defx : attr[i].a_val; ! 1149: some++; ! 1150: hvmode = R_DIR; ! 1151: break; ! 1152: case UP: ! 1153: dy += (attr[i].a_val==0) ? defy : attr[i].a_val; ! 1154: some++; ! 1155: hvmode = U_DIR; ! 1156: break; ! 1157: case DOWN: ! 1158: dy -= (attr[i].a_val==0) ? defy : attr[i].a_val; ! 1159: some++; ! 1160: hvmode = D_DIR; ! 1161: break; ! 1162: case TO: ! 1163: ppos = (struct obj *) attr[i].a_val; ! 1164: dx = ppos->o_x - curx; ! 1165: dy = ppos->o_y - cury; ! 1166: some++; ! 1167: break; ! 1168: case BY: ! 1169: ppos = (struct obj *) attr[i].a_val; ! 1170: dx = ppos->o_x; ! 1171: dy = ppos->o_y; ! 1172: some++; ! 1173: break; ! 1174: case FROM: ! 1175: case AT: ! 1176: ppos = (struct obj *) attr[i].a_val; ! 1177: curx = ppos->o_x; ! 1178: cury = ppos->o_y; ! 1179: break; ! 1180: } ! 1181: } ! 1182: if (some) { ! 1183: defx = dx; ! 1184: defy = dy; ! 1185: } else { ! 1186: defx *= xtab[hvmode]; ! 1187: defy *= ytab[hvmode]; ! 1188: } ! 1189: prevdx = defx; ! 1190: prevdy = defy; ! 1191: extreme(curx, cury); ! 1192: curx += defx; ! 1193: cury += defy; ! 1194: extreme(curx, cury); ! 1195: p = makenode(MOVE, 0); ! 1196: dprintf("M %d %d\n", curx, cury); ! 1197: return(p); ! 1198: } ! 1199: ! 1200: struct obj *textgen(s, garb) ! 1201: { ! 1202: static int prevdx, prevdy, prevrad = 10; ! 1203: int i, dx, dy, some, type; ! 1204: struct obj *p, *ppos; ! 1205: ! 1206: type = 'C'; ! 1207: some = dx = dy = 0; ! 1208: for (i = 0; i < nattr; i++) ! 1209: switch (attr[i].a_type) { ! 1210: case LEFT: ! 1211: dx -= attr[i].a_val; ! 1212: some++; ! 1213: break; ! 1214: case RIGHT: ! 1215: dx += attr[i].a_val; ! 1216: some++; ! 1217: break; ! 1218: case UP: ! 1219: dy += attr[i].a_val; ! 1220: some++; ! 1221: break; ! 1222: case DOWN: ! 1223: dy -= attr[i].a_val; ! 1224: some++; ! 1225: break; ! 1226: case AT: ! 1227: ppos = (struct obj *) attr[i].a_val; ! 1228: curx = ppos->o_x; ! 1229: cury = ppos->o_y; ! 1230: break; ! 1231: case LJUST: ! 1232: type = 'L'; ! 1233: break; ! 1234: case RJUST: ! 1235: type = 'R'; ! 1236: break; ! 1237: case SPREAD: ! 1238: type = 'S'; ! 1239: break; ! 1240: case FILL: ! 1241: type = 'F'; ! 1242: break; ! 1243: case ABOVE: ! 1244: type = 'A'; ! 1245: break; ! 1246: case BELOW: ! 1247: type = 'B'; ! 1248: break; ! 1249: } ! 1250: dprintf("T %c %s\n", type, s); ! 1251: if (some) { ! 1252: prevdx = dx; ! 1253: prevdy = dy; ! 1254: } else { ! 1255: dx = prevdx; ! 1256: dy = prevdy; ! 1257: } ! 1258: extreme(curx, cury); ! 1259: curx += dx; ! 1260: cury += dy; ! 1261: extreme(curx, cury); /* wrong */ ! 1262: p = makenode(TEXT, 2); ! 1263: p->o_val[0] = s; ! 1264: p->o_val[1] = type; ! 1265: return(p); ! 1266: } ! 1267: ! 1268: char *tostring(s) ! 1269: register char *s; ! 1270: { ! 1271: register char *p; ! 1272: ! 1273: p = malloc(strlen(s)+1); ! 1274: if (p == NULL) { ! 1275: fprintf(stderr, "pic: out of space in tostring on %s", s); ! 1276: exit(1); ! 1277: } ! 1278: strcpy(p, s); ! 1279: return(p); ! 1280: } ! 1281: ! 1282: makevar(s, t, v) /* make variable named s in table */ ! 1283: char *s; ! 1284: int t; ! 1285: int v; /* maybe wrong later */ ! 1286: { ! 1287: int i; ! 1288: ! 1289: for (i = 0; i < nsymtab; i++) ! 1290: if (strcmp(s, symtab[i].s_name) == 0) ! 1291: return(i); ! 1292: if (nsymtab >= SYMTAB) ! 1293: yyerror("symbol table overflow (%d)", SYMTAB); ! 1294: symtab[nsymtab].s_name = tostring(s); ! 1295: symtab[nsymtab].s_type = t; ! 1296: symtab[nsymtab].s_val = v; ! 1297: return(nsymtab++); ! 1298: } ! 1299: ! 1300: lookup(s) /* find s in symtab */ ! 1301: char *s; ! 1302: { ! 1303: int i; ! 1304: ! 1305: for (i = 0; i < nsymtab; i++) ! 1306: if (strcmp(s, symtab[i].s_name) == 0) ! 1307: return(i); ! 1308: return(-1); ! 1309: } ! 1310: ! 1311: struct obj *makepos(x, y) /* make a position cell */ ! 1312: coord x; ! 1313: coord y; ! 1314: { ! 1315: struct obj *p; ! 1316: ! 1317: p = makenode(PLACE, 0); ! 1318: p->o_x = x; ! 1319: p->o_y = y; ! 1320: return(p); ! 1321: } ! 1322: ! 1323: struct obj *getpos(p, corner) /* find position of point */ ! 1324: struct obj *p; ! 1325: int corner; ! 1326: { ! 1327: coord x, y, x1, y1; ! 1328: ! 1329: dprintf("getpos %o %d\n", p, corner); ! 1330: x = p->o_x; ! 1331: y = p->o_y; ! 1332: x1 = p->o_val[0]; ! 1333: y1 = p->o_val[1]; ! 1334: switch (p->o_type) { ! 1335: case PLACE: ! 1336: break; ! 1337: case BOX: ! 1338: switch (corner) { ! 1339: case NORTH: y += y1 / 2; break; ! 1340: case SOUTH: y -= y1 / 2; break; ! 1341: case EAST: x += x1 / 2; break; ! 1342: case WEST: x -= x1 / 2; break; ! 1343: case NE: x += x1 / 2; y += y1 / 2; break; ! 1344: case SW: x -= x1 / 2; y -= y1 / 2; break; ! 1345: case SE: x += x1 / 2; y -= y1 / 2; break; ! 1346: case NW: x -= x1 / 2; y += y1 / 2; break; ! 1347: } ! 1348: break; ! 1349: case CIRCLE: ! 1350: case ELLIPSE: ! 1351: switch (corner) { ! 1352: case NORTH: y += y1; break; ! 1353: case SOUTH: y -= y1; break; ! 1354: case EAST: x += x1; break; ! 1355: case WEST: x -= x1; break; ! 1356: case NE: x += 0.707 * x1; y += 0.707 * y1; break; ! 1357: case SE: x += 0.707 * x1; y -= 0.707 * y1; break; ! 1358: case NW: x -= 0.707 * x1; y += 0.707 * y1; break; ! 1359: case SW: x -= 0.707 * x1; y -= 0.707 * y1; break; ! 1360: } ! 1361: break; ! 1362: case LINE: ! 1363: case ARROW: ! 1364: case MOVE: ! 1365: switch (corner) { ! 1366: case START: break; /* already in place */ ! 1367: case END: x = x1; y = y1; break; ! 1368: case CENTER: x = (x+x1)/2; y = (y+y1)/2; break; ! 1369: case NORTH: if (y1 > y) { x = x1; y = y1; } break; ! 1370: case SOUTH: if (y1 < y) { x = x1; y = y1; } break; ! 1371: case EAST: if (x1 > x) { x = x1; y = y1; } break; ! 1372: case WEST: if (x1 < x) { x = x1; y = y1; } break; ! 1373: } ! 1374: break; ! 1375: case ARC: ! 1376: switch (corner) { ! 1377: case START: ! 1378: if (p->o_attr & CW_ARC) { ! 1379: x = p->o_val[2]; y = p->o_val[3]; ! 1380: } else { ! 1381: x = x1; y = y1; ! 1382: } ! 1383: break; ! 1384: case END: ! 1385: if (p->o_attr & CW_ARC) { ! 1386: x = x1; y = y1; ! 1387: } else { ! 1388: x = p->o_val[2]; y = p->o_val[3]; ! 1389: } ! 1390: break; ! 1391: } ! 1392: break; ! 1393: case SPLINE: ! 1394: switch (corner) { ! 1395: case END: ! 1396: x = p->o_val[0]; ! 1397: y = p->o_val[1]; ! 1398: break; ! 1399: } ! 1400: break; ! 1401: } ! 1402: dprintf("getpos returns %d %d\n", x, y); ! 1403: return(makepos(x, y)); ! 1404: } ! 1405: ! 1406: struct obj *gethere(n) /* make a place for curx,cury */ ! 1407: { ! 1408: dprintf("gethere %d %d\n", curx, cury); ! 1409: return(makepos(curx, cury)); ! 1410: } ! 1411: ! 1412: struct obj *getlast(n, t) /* find n-th previous occurrence of type t */ ! 1413: int n, t; ! 1414: { ! 1415: int i, k; ! 1416: struct obj *p; ! 1417: ! 1418: k = n; ! 1419: for (i = nobj-1; i >= 0; i--) { ! 1420: p = objlist[i]; ! 1421: if (p->o_type != t) ! 1422: continue; ! 1423: if (--k > 0) ! 1424: continue; /* not there yes */ ! 1425: dprintf("got a last of x,y= %d,%d\n", p->o_x, p->o_y); ! 1426: return(p); ! 1427: } ! 1428: yyerror("there is no %dth last", n); ! 1429: } ! 1430: ! 1431: struct obj *getfirst(n, t) /* find n-th occurrence of type t */ ! 1432: int n, t; ! 1433: { ! 1434: int i, k; ! 1435: struct obj *p; ! 1436: ! 1437: k = n; ! 1438: for (i = 0; i < nobj; i++) { ! 1439: p = objlist[i]; ! 1440: if (p->o_type != t) ! 1441: continue; ! 1442: if (--k > 0) ! 1443: continue; /* not there yes */ ! 1444: dprintf("got a first of x,y= %d,%d\n", p->o_x, p->o_y); ! 1445: return(p); ! 1446: yyerror("there is no %dth ", n); ! 1447: } ! 1448: } ! 1449: ! 1450: struct obj *fixpos(p, x, y) ! 1451: struct obj *p; ! 1452: coord x, y; ! 1453: { ! 1454: dprintf("fixpos returns %d %d\n", p->o_x + x, p->o_y + y); ! 1455: return(makepos(p->o_x + x, p->o_y + y)); ! 1456: } ! 1457: ! 1458: struct obj *makenode(type, n) ! 1459: int type, n; ! 1460: { ! 1461: struct obj *p; ! 1462: ! 1463: p = (struct obj *) malloc(sizeof(struct obj) + (n-1)*sizeof(coord)); ! 1464: if (p == NULL) { ! 1465: fprintf(stderr, "pic: out of space in makenode\n"); ! 1466: exit(1); ! 1467: } ! 1468: p->o_type = type; ! 1469: p->o_count = n; ! 1470: p->o_mode = hvmode; ! 1471: p->o_x = curx; ! 1472: p->o_y = cury; ! 1473: p->o_nt1 = ntext1; ! 1474: p->o_nt2 = ntext; ! 1475: ntext1 = ntext; /* ready for next caller */ ! 1476: p->o_attr = p->o_dotdash = p->o_ddval = 0; ! 1477: if (nobj >= MAXOBJ) { ! 1478: fprintf(stderr, "pic: objlist overflow\n"); ! 1479: exit(1); ! 1480: } ! 1481: objlist[nobj++] = p; ! 1482: return(p); ! 1483: } ! 1484: ! 1485: extreme(x, y) /* record max and min x and y values */ ! 1486: { ! 1487: if (x > xmax) ! 1488: xmax = x; ! 1489: if (y > ymax) ! 1490: ymax = y; ! 1491: if (x < xmin) ! 1492: xmin = x; ! 1493: if (y < ymin) ! 1494: ymin = y; ! 1495: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.