/* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */ /* The copyright notice above does not evidence any */ /* actual or intended publication of such source code. */ /* @(#)picasso:main.c 1.0 */ #include <ctype.h> #include <signal.h> #include <sys/types.h> #include <sys/stat.h> #include "picasso.h" #include "y.tab.h" extern int yydebug; YYSTYPE origin; obj *objhead = NULL; obj *objtail = NULL; Attr *attr = NULL; /* attributes stored here as collected */ int nattrlist = 0; int nattr = 0; /* number of entries in attr_list */ Text *text = NULL; /* text strings stored here as collected */ int ntextlist = 0; /* size of text[] array */ int ntext = 0; int ntext1 = 0; /* record ntext here on entry to each figure */ float *exprlist = NULL; int nexprlist = 0; int nexpr = 0; float curx = 0; float cury = 0; rgb *rgbtable = NULL; int nrgbtable = 0; int nrgb = 0; int hvmode = R_DIR; /* R => left->right, D => top->bottom, etc. */ int codegen = 0; /* 1=>output for this picture; 0=>no output */ int PEseen = 0; /* 1=> PE seen during parsing */ int pass_thru = 0; /* 1=> prepare output to go through troff */ int nosqueeze = 0; /* 0=> translate/scale to fit page */ int objbuf = 0; /* >0 => print out objects as buffer fills */ int pic_compat = 0; /* !0 => interpret input PIC-style */ int parsing = 0; /* controls entrance to eqn pipeline */ int draftlayer= 0; int margin = 1; /* margin (in points) around a picture */ float magnification = 1.0; float eqn_move = .03; /* vertical adjustment for eqn stuff */ int verbose = 0; int lineno = 0; int batch = 0; char *filename = "-"; int synerr = 0; int anyerr = 0; /* becomes 1 if synerr ever 1 */ char *cmdname; float Gbox[4] = { 32767, 32767, -32767, -32767 }; double pght = 11, pgwid = 8.5; valtype cur_xform[6]; FILE *textfp = stdout; char *gwblib = GWBFILES; char *fontdir = FONTDIR; main(argc, argv) int argc; char *argv[]; { extern int fpecatch(); extern double atof(); extern char *strchr(); extern FILE *tmpfile(); extern char *optarg; extern int optind; int n; char *str, buf[20]; signal(SIGFPE, fpecatch); cmdname = argv[0]; while ((n = getopt(argc, argv, "b:F:I:l:m:M:p:e:tvx")) != EOF) { switch (n) { case 'I': gwblib = optarg; break; case 'F': fontdir = optarg; break; case 'b': objbuf = atoi(optarg); break; case 'l': draftlayer = -atoi(optarg); break; case 'm': margin = atoi(optarg); break; case 'M': magnification = atof(optarg); break; case 'e': eqn_move = atof(optarg); case 'p': if ((str=strchr(optarg,'x')) == NULL) { if ((pght=atof(optarg)) <= 0) pght = 11; } else { if ((pgwid=atof(optarg)) <= 0) pgwid = 8.5; if ((pght=atof(str+1)) <= 0) pght = 11; } break; case 't': pass_thru = 1; break; case 'v': verbose = 1; break; case 'x': nosqueeze = 1; break; } } batch = (! Xokay()) || pass_thru || nosqueeze; if (!batch) { /* if otherwise interactive but stdin is a pipe, assume we should batch process the input */ struct stat statbuf; /* if (fstat(fileno(stdin), &statbuf) == 0) if ((statbuf.st_mode & S_IFMT) == S_IFIFO || (statbuf.st_mode & S_IFMT) == S_IFREG) */ batch = 1; } if (batch && optind >= argc && isatty(fileno(stdin)) == 1) { fprintf(stderr, "usage: %s -t file | troff-pipeline\n\ or: %s file > postscript-file\n\ or: other-command file | %s options ...\n", argv[0], argv[0], argv[0]); exit(1); } argc -= --optind; argv += optind; if (pass_thru && (textfp = tmpfile()) == NULL) { fprintf(stderr, "%s: can't open internal temporary file\n", cmdname); exit(1); } text = (Text *) grow((char *)text, "text", ntextlist += 1000, sizeof(Text)); attr = (Attr *) grow((char *)attr, "attr", nattrlist += 100, sizeof(Attr)); exprlist = (float *) grow((char *)exprlist, "exprlist", nexprlist += 256, sizeof(float)); devinit("post"); sprintf(buf, "/%d/", getpid()); pushsrc(pString, buf); definition("pid"); origin.o = objhead = (obj *) calloc(1, sizeof(obj)); objtail = (obj *) calloc(1, sizeof(obj)); objhead->o_next = objtail; objtail->o_prev = objhead; objhead->o_type = PLACE; makevar(tostring("O"),PLACENAME,origin); primaries(); setdefaults(); pushsrc(File, curfile = infile); if (argc <= 1) { curfile->fin = batch ? stdin : NULL; curfile->fname = tostring("-"); getdata(curfile); } else { batch = 1; /* because file names specified */ while (argc-- > 1) { if ((curfile->fin = fopen(*++argv, "r")) == NULL) { fprintf(stderr, "%s: can't open %s\n", cmdname, *argv); exit(1); } curfile->fname = tostring(*argv); getdata(curfile); fclose(curfile->fin); free(curfile->fname); } } if (!batch) Xloop(); if (pass_thru) { fflush(textfp); rewind(textfp); while(fgets(buf, BUFSIZ, textfp) != NULL) fputs(buf, stdout); fclose(textfp); } else if (batch) endpl(); else Xendpl(); exit(anyerr); } struct clor { char *c_name; float c_red; float c_green; float c_blue; unsigned long c_pixel; } dfcols[] = { { "black", 0., 0., 0., 0 }, /* Indexes 0 and 1 correspond */ { "white", 1., 1., 1., 0 }, /* to grayscale values 0 and 1*/ { "red", 1., 0., 0., 0 }, /* This "pun" is deliberate; */ { "green", 0., 1., 0., 0 }, /* gray output depends on it. */ { "blue", 0., 0., 1., 0 }, { "yellow", 1., 1., 0., 0 }, { "magenta", 1., 0., 1., 0 }, { "cyan", 0., 1., 1., 0 }, { "lightgrey", 0.6588, 0.6588, 0.6588, 0 }, { "navy", 0.1372, 0.1372, 0.5568, 0 }, { "skyblue", 0.196, 0.6, 0.8, 0 }, { "orange", 0.8, 0.2, 0.2, 0 }, { "sienna", 0.5568, 0.4196, 0.1372, 0 }, { "palegreen", 0.5607, 0.7372, 0.5607, 0 }, { "darkgreen", 0.1843, 0.3098, 0.1843, 0 }, { "blueviolet",0.6235, 0.3725, 0.6235, 0 }, { NULL, 0., 0., 0., 0 } }; primaries () /* set up initial 8-color color table */ { int i; char *s; for (i = 0; (s = dfcols[i].c_name) != NULL; i++) makeindex(s, dfcols[i].c_red, dfcols[i].c_green, dfcols[i].c_blue); } makeindex (s, r, g, b) /* simulate user color definition for s */ char *s; double r, g, b; { YYSTYPE v; exprlist[0] = r; exprlist[1] = g; exprlist[2] = b; nexpr = 3; v.f = setrgbindex(); makevar(tostring(s), VARNAME, v); } fpecatch() { fatal("floating point exception"); } char *grow(ptr, name, num, size) /* make array bigger */ char *ptr, *name; int num, size; { char *p; if (ptr == NULL) p = malloc(num * size); else p = realloc(ptr, num * size); if (p == NULL) fatal("can't grow %s to %d", name, num * size); return p; } struct { char *name; float val; short scalable; /* 1 => adjust when scale changes */ } defaults[] ={ "flatness", 0, 0, "miterlimit", 0, 0, "linecap", -1, 0, "linejoin", -1, 0, "textsize", 10, 0, "textspace", 12, 0, "textcolor", 0, 0, "textfont", 0, 0, "moveht", HT, 1, "movewid", HT, 1, "arrowht", HT5, 1, "arrowwid", HT10, 1, "arrowend", 0, 0, "arrowfill", 1, 0, /* arrowhead style */ "lineht", HT, 1, "linewid", HT, 1, "linerad", 0, 1, "dashwid", HT10, 1, "boxht", HT, 1, "boxwid", WID, 1, "boxrad", 0, 1, "ellipseht", HT, 1, "ellipsewid", WID, 1, "arcrad", HT2, 1, "circlerad", HT2, 1, "fillcolor", 0, 0, "linecolor", 0, 0, "lineweight", 0, 1, "curlayer", 0, 0, /* current drawing layer */ NULL, 0 }; int top_layer = 0; /* high-water mark */ setdefaults() /* set default sizes for variables like boxht */ { int i; YYSTYPE v; for (i = 0; defaults[i].name != NULL; i++) { v.f = defaults[i].val; makevar(tostring(defaults[i].name), VARNAME, v); } } resetvar() /* reset variables listed */ { int i, j; if (nattr == 0) { /* none listed, so do all */ setdefaults(); pic_compat = 0; return; } for (i = 0; i < nattr; i++) { if (strcmp(attr[i].a_val.p, "p_i_c") == 0) pic_compat = 1; else for (j = 0; defaults[j].name != NULL; j++) if (strcmp(defaults[j].name, attr[i].a_val.p) == 0) { setfval(defaults[j].name, defaults[j].val); break; } } } static float savevars[sizeof defaults / sizeof defaults[0]]; savepicvars() /* save current values, restore original values */ { int i; char *s; for (i = 0; (s = defaults[i].name) != NULL; i++) { savevars[i] = getfval(s); setfval(s, defaults[i].val); } } restorepicvars() /* restore values saved above */ { int i; char *s; for (i = 0; (s = defaults[i].name) != NULL; i++) setfval(s, savevars[i]); } checkscale(v) /* adjust default variables dependent on scale */ double v; { int i; for (i = 1; defaults[i].name != NULL; i++) { if (defaults[i].scalable) setfval(defaults[i].name, defaults[i].val * v); } } getdata() { char *p, buf[1000], buf1[100]; int ln; int ineqn = 0; if (curfile->fin == NULL) { /* only happens in interactive mode */ batch = 1; reset(); batch = 0; ln = nosqueeze; nosqueeze = 1; Xopenpl(""); Xprint('E'); Xallexpose(); nosqueeze = ln; return; } curfile->lineno = 0; while (fgets(buf, sizeof buf, curfile->fin) != NULL) { curfile->lineno++; if (*buf == '.' && buf[1] == 'P' && buf[2] == 'S') { for (p = &buf[3]; *p == ' '; p++) ; if (*p++ == '<') { Infile svfile; svfile = *curfile; sscanf(p, "%s", buf1); if ((curfile->fin=fopen(buf1, "r")) == NULL) fatal("can't open %s", buf1); curfile->fname = tostring(buf1); getdata(); fclose(curfile->fin); free(curfile->fname); *curfile = svfile; if (batch) continue; else break; } reset(); parsing = 1; yyparse(); parsing = 0; anyerr += synerr; /* added for PIC compatibility -- 4/18/90 -- DBK */ scale_pic(); /* end of PIC compatibility addition */ /* yylval.i now contains 'E', 'F' or 'N' from .PE etc.*/ #if 0 if (codegen && !synerr) { if (batch) { openpl(buf+3); print(yylval.i); closepl(buf+3); /* assumes \n at end */ } else { ln = nosqueeze; nosqueeze = 1; Xopenpl(buf+3); Xprint(yylval.i); Xallexpose(); nosqueeze = ln; } break; } #else /* this is a change made 2/20/90 by DBK */ /* and a further change 4/13/90 */ /* if batch mode if some objects and no errors, print page read rest of file if interactive mode if any objects display objects abandon file else read more of file */ /* behaves same way in batch mode */ /* tries to display data up to this point in interactive, but throws away rest of file */ if (codegen && !synerr && batch) { openpl(buf+3); print(yylval.i); closepl(buf+3); /* assumes \n at end */ } /* else if (codegen && !batch) { */ else if (!batch) { /* no codegen for config */ ln = nosqueeze; nosqueeze = 1; Xopenpl(buf+3); Xprint(yylval.i); Xallexpose(); nosqueeze = ln; break; } #endif } else if (buf[0] == '.' && buf[1] == 'l' && buf[2] == 'f') { if (sscanf(buf+3, "%d %s", &ln, buf1) == 2) { free(curfile->fname); curfile->fname = tostring(buf1); curfile->lineno = ln; /* off by one?? */ } } else if (pass_thru) { fputs(buf, textfp); if (*buf == '.') /* track .ps, .ft, .vs, .ec */ troff(buf); else { int dumft = 0, dumps = 0; while (parse_text(buf, &dumft, &dumps)) ; } } if (buf[0] == '.' && buf[1] == 'E' && buf[2] == 'Q') ineqn = 1; else if (buf[0] == '.' && buf[1] == 'E' && buf[2] == 'N') ineqn = 0; else if (ineqn == 1) scan_delim(buf); /* should also check no_eqn--DBK--3/29/90 */ } } reset() { extern int nstack, errno; obj *op, *op1; int i; if (batch) { for (op = objhead->o_next; op != objtail; ) { if (op->o_type == BLOCK) freesymtab(op->o_val[N_VAL+1].s); op1 = op; op = op->o_next; free(op1); } for (i = 0; i < ntext; i++) { if (text[i].t_val) free(text[i].t_val); text[i].t_line = 0; } ntextlines = ntext = ntext1 = 0; nstack = 0; Gbox[0] = Gbox[1] = 32767; Gbox[2] = Gbox[3] = -32767; } objhead->o_next = objtail; objtail->o_prev = objhead; nattr = 0; objcount = top_layer = 0; errno = codegen = synerr = 0; curx = cury = 0; PEseen = 0; hvmode = R_DIR; cur_xform[0].f = cur_xform[3].f = 1; cur_xform[1].f = cur_xform[2].f = cur_xform[4].f = cur_xform[5].f = 0; if (!batch) Xclosepl(""); }