|
|
1.1 root 1: /* Copyright (c) 1988 AT&T */
2: /* All Rights Reserved */
3:
4: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
5: /* The copyright notice above does not evidence any */
6: /* actual or intended publication of such source code. */
7:
8: /* @(#)picasso:main.c 1.0 */
9:
10: #include <ctype.h>
11: #include <signal.h>
12: #include <sys/types.h>
13: #include <sys/stat.h>
14: #include "picasso.h"
15: #include "y.tab.h"
16:
17: extern int yydebug;
18:
19: YYSTYPE origin;
20: obj *objhead = NULL;
21: obj *objtail = NULL;
22:
23: Attr *attr = NULL; /* attributes stored here as collected */
24: int nattrlist = 0;
25: int nattr = 0; /* number of entries in attr_list */
26:
27: Text *text = NULL; /* text strings stored here as collected */
28: int ntextlist = 0; /* size of text[] array */
29: int ntext = 0;
30: int ntext1 = 0; /* record ntext here on entry to each figure */
31:
32: float *exprlist = NULL;
33: int nexprlist = 0;
34: int nexpr = 0;
35: float curx = 0;
36: float cury = 0;
37:
38: rgb *rgbtable = NULL;
39: int nrgbtable = 0;
40: int nrgb = 0;
41:
42: int hvmode = R_DIR; /* R => left->right, D => top->bottom, etc. */
43: int codegen = 0; /* 1=>output for this picture; 0=>no output */
44: int PEseen = 0; /* 1=> PE seen during parsing */
45: int pass_thru = 0; /* 1=> prepare output to go through troff */
46: int nosqueeze = 0; /* 0=> translate/scale to fit page */
47: int objbuf = 0; /* >0 => print out objects as buffer fills */
48: int pic_compat = 0; /* !0 => interpret input PIC-style */
49: int parsing = 0; /* controls entrance to eqn pipeline */
50: int draftlayer= 0;
51: int margin = 1; /* margin (in points) around a picture */
52: float magnification = 1.0;
53: float eqn_move = .03; /* vertical adjustment for eqn stuff */
54: int verbose = 0;
55: int lineno = 0;
56: int batch = 0;
57: char *filename = "-";
58: int synerr = 0;
59: int anyerr = 0; /* becomes 1 if synerr ever 1 */
60: char *cmdname;
61: float Gbox[4] = { 32767, 32767, -32767, -32767 };
62: double pght = 11,
63: pgwid = 8.5;
64: valtype cur_xform[6];
65: FILE *textfp = stdout;
66: char *gwblib = GWBFILES;
67: char *fontdir = FONTDIR;
68:
69: main(argc, argv)
70: int argc;
71: char *argv[];
72: {
73: extern int fpecatch();
74: extern double atof();
75: extern char *strchr();
76: extern FILE *tmpfile();
77: extern char *optarg;
78: extern int optind;
79: int n;
80: char *str, buf[20];
81:
82: signal(SIGFPE, fpecatch);
83: cmdname = argv[0];
84: while ((n = getopt(argc, argv, "b:F:I:l:m:M:p:e:tvx")) != EOF) {
85: switch (n) {
86: case 'I':
87: gwblib = optarg;
88: break;
89: case 'F':
90: fontdir = optarg;
91: break;
92: case 'b':
93: objbuf = atoi(optarg);
94: break;
95: case 'l':
96: draftlayer = -atoi(optarg);
97: break;
98: case 'm':
99: margin = atoi(optarg);
100: break;
101: case 'M':
102: magnification = atof(optarg);
103: break;
104: case 'e':
105: eqn_move = atof(optarg);
106: case 'p':
107: if ((str=strchr(optarg,'x')) == NULL) {
108: if ((pght=atof(optarg)) <= 0)
109: pght = 11;
110: }
111: else {
112: if ((pgwid=atof(optarg)) <= 0)
113: pgwid = 8.5;
114: if ((pght=atof(str+1)) <= 0)
115: pght = 11;
116: }
117: break;
118: case 't':
119: pass_thru = 1;
120: break;
121: case 'v':
122: verbose = 1;
123: break;
124: case 'x':
125: nosqueeze = 1;
126: break;
127: }
128: }
129: batch = (! Xokay()) || pass_thru || nosqueeze;
130: if (!batch) { /* if otherwise interactive but stdin is a pipe,
131: assume we should batch process the input */
132: struct stat statbuf;
133:
134: /*
135: if (fstat(fileno(stdin), &statbuf) == 0)
136: if ((statbuf.st_mode & S_IFMT) == S_IFIFO ||
137: (statbuf.st_mode & S_IFMT) == S_IFREG)
138: */
139: batch = 1;
140: }
141: if (batch && optind >= argc && isatty(fileno(stdin)) == 1) {
142: fprintf(stderr, "usage: %s -t file | troff-pipeline\n\
143: or: %s file > postscript-file\n\
144: or: other-command file | %s options ...\n", argv[0], argv[0], argv[0]);
145: exit(1);
146: }
147: argc -= --optind;
148: argv += optind;
149: if (pass_thru && (textfp = tmpfile()) == NULL) {
150: fprintf(stderr, "%s: can't open internal temporary file\n",
151: cmdname);
152: exit(1);
153: }
154: text = (Text *) grow((char *)text, "text", ntextlist += 1000,
155: sizeof(Text));
156: attr = (Attr *) grow((char *)attr, "attr", nattrlist += 100,
157: sizeof(Attr));
158: exprlist = (float *) grow((char *)exprlist, "exprlist",
159: nexprlist += 256, sizeof(float));
160: devinit("post");
161: sprintf(buf, "/%d/", getpid());
162: pushsrc(pString, buf);
163: definition("pid");
164: origin.o = objhead = (obj *) calloc(1, sizeof(obj));
165: objtail = (obj *) calloc(1, sizeof(obj));
166: objhead->o_next = objtail;
167: objtail->o_prev = objhead;
168: objhead->o_type = PLACE;
169: makevar(tostring("O"),PLACENAME,origin);
170: primaries();
171: setdefaults();
172:
173: pushsrc(File, curfile = infile);
174: if (argc <= 1) {
175: curfile->fin = batch ? stdin : NULL;
176: curfile->fname = tostring("-");
177: getdata(curfile);
178: } else {
179: batch = 1; /* because file names specified */
180: while (argc-- > 1) {
181: if ((curfile->fin = fopen(*++argv, "r")) == NULL) {
182: fprintf(stderr, "%s: can't open %s\n",
183: cmdname, *argv);
184: exit(1);
185: }
186: curfile->fname = tostring(*argv);
187: getdata(curfile);
188: fclose(curfile->fin);
189: free(curfile->fname);
190: }
191: }
192: if (!batch)
193: Xloop();
194: if (pass_thru) {
195: fflush(textfp);
196: rewind(textfp);
197: while(fgets(buf, BUFSIZ, textfp) != NULL)
198: fputs(buf, stdout);
199: fclose(textfp);
200: }
201: else
202: if (batch)
203: endpl();
204: else
205: Xendpl();
206: exit(anyerr);
207: }
208:
209: struct clor {
210: char *c_name;
211: float c_red;
212: float c_green;
213: float c_blue;
214: unsigned long c_pixel;
215: } dfcols[] = {
216: { "black", 0., 0., 0., 0 }, /* Indexes 0 and 1 correspond */
217: { "white", 1., 1., 1., 0 }, /* to grayscale values 0 and 1*/
218: { "red", 1., 0., 0., 0 }, /* This "pun" is deliberate; */
219: { "green", 0., 1., 0., 0 }, /* gray output depends on it. */
220: { "blue", 0., 0., 1., 0 },
221: { "yellow", 1., 1., 0., 0 },
222: { "magenta", 1., 0., 1., 0 },
223: { "cyan", 0., 1., 1., 0 },
224: { "lightgrey", 0.6588, 0.6588, 0.6588, 0 },
225: { "navy", 0.1372, 0.1372, 0.5568, 0 },
226: { "skyblue", 0.196, 0.6, 0.8, 0 },
227: { "orange", 0.8, 0.2, 0.2, 0 },
228: { "sienna", 0.5568, 0.4196, 0.1372, 0 },
229: { "palegreen", 0.5607, 0.7372, 0.5607, 0 },
230: { "darkgreen", 0.1843, 0.3098, 0.1843, 0 },
231: { "blueviolet",0.6235, 0.3725, 0.6235, 0 },
232: { NULL, 0., 0., 0., 0 }
233: };
234:
235: primaries () /* set up initial 8-color color table */
236: {
237: int i;
238: char *s;
239:
240: for (i = 0; (s = dfcols[i].c_name) != NULL; i++)
241: makeindex(s, dfcols[i].c_red, dfcols[i].c_green,
242: dfcols[i].c_blue);
243: }
244:
245: makeindex (s, r, g, b) /* simulate user color definition for s */
246: char *s;
247: double r, g, b;
248: {
249: YYSTYPE v;
250:
251: exprlist[0] = r; exprlist[1] = g; exprlist[2] = b; nexpr = 3;
252: v.f = setrgbindex();
253: makevar(tostring(s), VARNAME, v);
254: }
255:
256: fpecatch()
257: {
258: fatal("floating point exception");
259: }
260:
261: char *grow(ptr, name, num, size) /* make array bigger */
262: char *ptr, *name;
263: int num, size;
264: {
265: char *p;
266:
267: if (ptr == NULL)
268: p = malloc(num * size);
269: else
270: p = realloc(ptr, num * size);
271: if (p == NULL)
272: fatal("can't grow %s to %d", name, num * size);
273: return p;
274: }
275:
276: struct {
277: char *name;
278: float val;
279: short scalable; /* 1 => adjust when scale changes */
280: } defaults[] ={
281: "flatness", 0, 0,
282: "miterlimit", 0, 0,
283: "linecap", -1, 0,
284: "linejoin", -1, 0,
285: "textsize", 10, 0,
286: "textspace", 12, 0,
287: "textcolor", 0, 0,
288: "textfont", 0, 0,
289: "moveht", HT, 1,
290: "movewid", HT, 1,
291: "arrowht", HT5, 1,
292: "arrowwid", HT10, 1,
293: "arrowend", 0, 0,
294: "arrowfill", 1, 0, /* arrowhead style */
295: "lineht", HT, 1,
296: "linewid", HT, 1,
297: "linerad", 0, 1,
298: "dashwid", HT10, 1,
299: "boxht", HT, 1,
300: "boxwid", WID, 1,
301: "boxrad", 0, 1,
302: "ellipseht", HT, 1,
303: "ellipsewid", WID, 1,
304: "arcrad", HT2, 1,
305: "circlerad", HT2, 1,
306: "fillcolor", 0, 0,
307: "linecolor", 0, 0,
308: "lineweight", 0, 1,
309: "curlayer", 0, 0, /* current drawing layer */
310: NULL, 0
311: };
312:
313: int top_layer = 0; /* high-water mark */
314:
315: setdefaults() /* set default sizes for variables like boxht */
316: {
317: int i;
318: YYSTYPE v;
319:
320: for (i = 0; defaults[i].name != NULL; i++) {
321: v.f = defaults[i].val;
322: makevar(tostring(defaults[i].name), VARNAME, v);
323: }
324: }
325:
326: resetvar() /* reset variables listed */
327: {
328: int i, j;
329:
330: if (nattr == 0) { /* none listed, so do all */
331: setdefaults();
332: pic_compat = 0;
333: return;
334: }
335: for (i = 0; i < nattr; i++) {
336: if (strcmp(attr[i].a_val.p, "p_i_c") == 0)
337: pic_compat = 1;
338: else for (j = 0; defaults[j].name != NULL; j++)
339: if (strcmp(defaults[j].name, attr[i].a_val.p) == 0) {
340: setfval(defaults[j].name, defaults[j].val);
341: break;
342: }
343: }
344: }
345:
346: static float savevars[sizeof defaults / sizeof defaults[0]];
347:
348: savepicvars() /* save current values, restore original values */
349: {
350: int i;
351: char *s;
352:
353: for (i = 0; (s = defaults[i].name) != NULL; i++) {
354: savevars[i] = getfval(s);
355: setfval(s, defaults[i].val);
356: }
357: }
358:
359: restorepicvars() /* restore values saved above */
360: {
361: int i;
362: char *s;
363:
364: for (i = 0; (s = defaults[i].name) != NULL; i++)
365: setfval(s, savevars[i]);
366: }
367:
368: checkscale(v) /* adjust default variables dependent on scale */
369: double v;
370: {
371: int i;
372:
373: for (i = 1; defaults[i].name != NULL; i++) {
374: if (defaults[i].scalable)
375: setfval(defaults[i].name,
376: defaults[i].val * v);
377: }
378: }
379:
380: getdata()
381: {
382: char *p, buf[1000], buf1[100];
383: int ln;
384: int ineqn = 0;
385:
386: if (curfile->fin == NULL) { /* only happens in interactive mode */
387: batch = 1;
388: reset();
389: batch = 0;
390: ln = nosqueeze;
391: nosqueeze = 1;
392: Xopenpl("");
393: Xprint('E');
394: Xallexpose();
395: nosqueeze = ln;
396: return;
397: }
398: curfile->lineno = 0;
399: while (fgets(buf, sizeof buf, curfile->fin) != NULL) {
400: curfile->lineno++;
401: if (*buf == '.' && buf[1] == 'P' && buf[2] == 'S') {
402: for (p = &buf[3]; *p == ' '; p++)
403: ;
404: if (*p++ == '<') {
405: Infile svfile;
406: svfile = *curfile;
407: sscanf(p, "%s", buf1);
408: if ((curfile->fin=fopen(buf1, "r")) == NULL)
409: fatal("can't open %s", buf1);
410: curfile->fname = tostring(buf1);
411: getdata();
412: fclose(curfile->fin);
413: free(curfile->fname);
414: *curfile = svfile;
415: if (batch)
416: continue;
417: else
418: break;
419: }
420: reset();
421: parsing = 1;
422: yyparse();
423: parsing = 0;
424: anyerr += synerr;
425: /* added for PIC compatibility -- 4/18/90 -- DBK */
426: scale_pic();
427: /* end of PIC compatibility addition */
428: /* yylval.i now contains 'E', 'F' or 'N' from .PE etc.*/
429:
430: #if 0
431: if (codegen && !synerr) {
432: if (batch) {
433: openpl(buf+3);
434: print(yylval.i);
435: closepl(buf+3); /* assumes \n at end */
436: }
437: else {
438: ln = nosqueeze;
439: nosqueeze = 1;
440: Xopenpl(buf+3);
441: Xprint(yylval.i);
442: Xallexpose();
443: nosqueeze = ln;
444: }
445: break;
446: }
447: #else
448: /* this is a change made 2/20/90 by DBK */
449: /* and a further change 4/13/90 */
450: /* if batch mode
451: if some objects and no errors, print page
452: read rest of file
453: if interactive mode
454: if any objects
455: display objects
456: abandon file
457: else
458: read more of file */
459: /* behaves same way in batch mode */
460: /* tries to display data up to this point in interactive, but
461: throws away rest of file */
462: if (codegen && !synerr && batch) {
463: openpl(buf+3);
464: print(yylval.i);
465: closepl(buf+3); /* assumes \n at end */
466: }
467: /* else if (codegen && !batch) { */
468: else if (!batch) { /* no codegen for config */
469: ln = nosqueeze;
470: nosqueeze = 1;
471: Xopenpl(buf+3);
472: Xprint(yylval.i);
473: Xallexpose();
474: nosqueeze = ln;
475: break;
476: }
477: #endif
478: }
479: else if (buf[0] == '.' && buf[1] == 'l' && buf[2] == 'f') {
480: if (sscanf(buf+3, "%d %s", &ln, buf1) == 2) {
481: free(curfile->fname);
482: curfile->fname = tostring(buf1);
483: curfile->lineno = ln; /* off by one?? */
484: }
485: }
486: else if (pass_thru) {
487: fputs(buf, textfp);
488: if (*buf == '.') /* track .ps, .ft, .vs, .ec */
489: troff(buf);
490: else {
491: int dumft = 0, dumps = 0;
492: while (parse_text(buf, &dumft, &dumps))
493: ;
494: }
495: }
496: if (buf[0] == '.' && buf[1] == 'E' && buf[2] == 'Q')
497: ineqn = 1;
498: else if (buf[0] == '.' && buf[1] == 'E' && buf[2] == 'N')
499: ineqn = 0;
500: else if (ineqn == 1)
501: scan_delim(buf);
502: /* should also check no_eqn--DBK--3/29/90 */
503: }
504: }
505:
506: reset()
507: {
508: extern int nstack, errno;
509: obj *op, *op1;
510: int i;
511:
512:
513: if (batch) {
514: for (op = objhead->o_next; op != objtail; ) {
515: if (op->o_type == BLOCK)
516: freesymtab(op->o_val[N_VAL+1].s);
517: op1 = op;
518: op = op->o_next;
519: free(op1);
520: }
521: for (i = 0; i < ntext; i++) {
522: if (text[i].t_val)
523: free(text[i].t_val);
524: text[i].t_line = 0;
525: }
526: ntextlines = ntext = ntext1 = 0;
527: nstack = 0;
528: Gbox[0] = Gbox[1] = 32767;
529: Gbox[2] = Gbox[3] = -32767;
530: }
531: objhead->o_next = objtail;
532: objtail->o_prev = objhead;
533: nattr = 0;
534: objcount = top_layer = 0;
535: errno = codegen = synerr = 0;
536: curx = cury = 0;
537: PEseen = 0;
538: hvmode = R_DIR;
539: cur_xform[0].f = cur_xform[3].f = 1;
540: cur_xform[1].f = cur_xform[2].f =
541: cur_xform[4].f = cur_xform[5].f = 0;
542: if (!batch)
543: Xclosepl("");
544: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.