Annotation of researchv10no/cmd/dag/dag.c, revision 1.1.1.1

1.1       root        1: /* DAG - draw a directed graph
                      2:  * Gansner North Vo
                      3:  */
                      4: 
                      5: const char*    Version                 =       "\n@(#)Version M-03/31/89\0\n";
                      6: 
                      7: #include "draw_dag.h"
                      8: #include "dag.h"
                      9: #include "parsedag.h"
                     10: #include "TrieFA.ins.c"
                     11: 
                     12: /* useful constants */
                     13: const double   Pi                      = 3.1415926537;
                     14: const double   IPP                     = .01;  // real inches per point of type 
                     15: const int              Resolution      = 72;   // points per virtual inch
                     16: 
                     17: /*** globals ***/
                     18: Infile                 Current_file;
                     19: boolean                        Uselib  =       true;   // user specified lib with -l option
                     20: char*                  Lib_path;                       // library directory 
                     21: int                            N;                      // number of nodes
                     22: int                            Extent;         // extent of node and edge array including spares
                     23: DAG_node_t**   Node;           // node list
                     24: DAG_edge_t**   Edge;           // edge list
                     25: user_info_t            User;           // user options from .GS line
                     26: options_t              Options;        // user options from graph input (for draw_dag)
                     27: char*                  Cmd_name;       // from command line
                     28: output_lang_t  Output_type;
                     29: int                            Xmax,Ymax;
                     30: Point                  Page_size;
                     31: Point                  Margin = {36,36};
                     32: 
                     33: void dumprank(int * rank) {
                     34:        if (rank)
                     35:                while (*rank >= 0) fprintf(stderr,"%d ",*rank++);
                     36:        fprintf(stderr,"\n");
                     37: }
                     38: 
                     39: void dumpgraph() {
                     40:        fprintf(stderr,"global ranksep %d nodesep %d\n",Options.ranksep,Options.nodesep);
                     41:        for (int i = 0; i < N; i++) {
                     42:                fprintf(stderr,"%s -> ",Node[i]->name);
                     43:                for (DAG_edge_t *e = Edge[i]; e; e = e->nextof())
                     44:                        fprintf(stderr,"%s ",Node[e->node]->name);
                     45:                fprintf(stderr,"\n      size %d %d\n",Node[i]->height,Node[i]->width);
                     46:        }
                     47:        fprintf(stderr,"min rank: "); dumprank(Options.source_nodes);
                     48:        fprintf(stderr,"max rank: "); dumprank(Options.sink_nodes);
                     49:        for (i = 0; i < Options.n_same_nodes; i++) {
                     50:                fprintf(stderr,"rank %d: ",i);
                     51:                dumprank(Options.same_nodes[i]);
                     52:        }
                     53: }
                     54: 
                     55: /*
                     56:  *     translate draw_dag coordinates to preferred system.
                     57:  */
                     58: 
                     59: void translate() {
                     60:        int node;
                     61:        if (!User.rotated) {
                     62:                switch(Output_type) {
                     63:                        case Pic:
                     64:                        case Cip:
                     65:                        case Postscript:
                     66:                        case Graphdraw:
                     67:                                for (node = 0; node < N; node++) {
                     68:                                        Node[node]->pos.y = Ymax - Node[node]->pos.y;
                     69:                                        for (DAG_edge_t *e = Edge[node]; e; e = e->nextof()) {
                     70:                                                for (int sp = 0; e->splinept[sp].x >= 0; sp++)
                     71:                                                        e->splinept[sp].y = Ymax - e->splinept[sp].y;
                     72:                                                e->top.y = Ymax - e->top.y;
                     73:                                                e->bottom.y = Ymax - e->bottom.y;
                     74:                                        }
                     75:                                }
                     76:                                break;
                     77:                }
                     78:        }
                     79:        else {
                     80:                swap(Xmax,Ymax);
                     81:                switch(Output_type) {
                     82:                        case Pic:
                     83:                        case Cip:
                     84:                        case Postscript:
                     85:                        case Graphdraw:
                     86:                                for (node = 0; node < N; node++) {
                     87:                                        swap(Node[node]->pos.x,Node[node]->pos.y);
                     88:                                        for (DAG_edge_t *e = Edge[node]; e; e = e->nextof()) {
                     89:                                                for (int sp = 0; e->splinept[sp].x >= 0; sp++)
                     90:                                                        swap(e->splinept[sp].x,e->splinept[sp].y);
                     91:                                                swap(e->top.x,e->top.y);
                     92:                                                swap(e->bottom.x,e->bottom.y);
                     93:                                        }
                     94:                                }
                     95:                                break;
                     96:                }
                     97:        }
                     98: }
                     99: 
                    100: /*
                    101:  *  compute Xmax, Ymax of drawing region
                    102:  */
                    103: void find_drawing_size() {
                    104:        int node;
                    105:        Xmax = 0; Ymax = 0;
                    106: 
                    107:        /* find extent of drawing region */
                    108:        for (node = 0; node < N; node++) {
                    109:                Xmax = max(Xmax,Node[node]->pos.x + (Node[node]->width + 1) / 2);
                    110:                Ymax = max(Ymax,Node[node]->pos.y + (Node[node]->height + 1) / 2);
                    111:                for (DAG_edge_t *e = Edge[node]; e; e = e->nextof()) {
                    112:                        for (int sp = 0; e->splinept[sp].x >= 0; sp++) {
                    113:                                Xmax = max(Xmax,e->splinept[sp].x);
                    114:                                Ymax = max(Ymax,e->splinept[sp].y);
                    115:                        }
                    116:                }
                    117:        }
                    118: }
                    119: 
                    120: void make_drawing() {
                    121:        if (N <= 0) return;
                    122: 
                    123:        draw_dag(N,(node_t**)Node,(edge_t**)Edge,Options);
                    124:        find_drawing_size();
                    125:        translate();
                    126: 
                    127:        switch (Output_type) {
                    128:                case Pic:
                    129:                case Cip:
                    130:                        emit_pic();
                    131:                        break;
                    132:                case Postscript:
                    133:                        emit_ps();
                    134:                        break;
                    135:                case Graphdraw:
                    136:                        emit_graphdraw();
                    137:                        break;
                    138:        }
                    139: }
                    140: 
                    141: void global_init(char *cmdname) {
                    142:        Node    =       new DAG_node_t*[Init_extent];
                    143:        Edge    =       new DAG_edge_t*[Init_extent];
                    144:        Extent  =       Init_extent;
                    145:        Cmd_name = cmdname;
                    146:        Options = reset_options();
                    147: }
                    148: 
                    149: void graph_init() {
                    150:        N = 0;
                    151:        Syntax_error = 0;
                    152:        User = user_info_t();
                    153:        Default_node = Reset_node;
                    154:        Default_edge = Reset_edge;
                    155: }
                    156: 
                    157: void reclaim_nodes() {
                    158:        for (int i = 0; i < N; i++) delete Node[i];
                    159: }
                    160: 
                    161: void reclaim_edges() {
                    162:        DAG_edge_t      *e,*f;
                    163:        for (int node = 0; node < N; node++) {
                    164:                if (e = Edge[node]) {
                    165:                        if (e->splinept) delete e->splinept;
                    166:                        while (e) {
                    167:                                f = e->nextof();
                    168:                                delete e;
                    169:                                e = f;
                    170:                        }
                    171:                        Edge[node] = 0;
                    172:                }
                    173:        }
                    174: }
                    175: 
                    176: void reclaim_samenodesets() {
                    177:        delete Options.source_nodes;
                    178:        Options.source_nodes = 0;
                    179:        delete Options.sink_nodes;
                    180:        Options.sink_nodes = 0;
                    181:        for (int i = 0; i < Options.n_same_nodes; i++) {
                    182:                delete Options.same_nodes[i];
                    183:                Options.same_nodes[i] = 0;
                    184:        }
                    185:        Options.same_nodes = 0;
                    186:        Options.n_same_nodes = 0;
                    187: }
                    188: 
                    189: void reclaim_storage() {
                    190:        reclaim_nodes();
                    191:        reclaim_edges();
                    192:        reclaim_hashtable();
                    193:        reclaim_samenodesets();
                    194:        freestrings();
                    195: }
                    196: 
                    197: main(int argc, char**argv) {
                    198:        char **args = argv;
                    199:        int nfiles = 0;
                    200:        boolean use_stdin = true;
                    201: 
                    202:        global_init(argv[0]);
                    203:        for (int arg = 1; arg < argc; arg++) {
                    204:                if (*argv[arg] == '-') {
                    205:                        switch(argv[arg][1]) {
                    206:                                case 'O':
                    207:                                        Options.quick = false;
                    208:                                        break;
                    209:                                case 'l':
                    210:                                        Uselib = false;
                    211:                                        break;
                    212:                                case 'v':
                    213:                                        Options.verbose = true;
                    214:                                        break;
                    215:                                case 'T':       // type of output
                    216:                                        set_output_type(&argv[arg][2]);
                    217:                                        break;
                    218:                                case 'p':
                    219:                                        set_page_size(&argv[arg][2]);
                    220:                                        break;
                    221:                        }
                    222:                }
                    223:                else {nfiles++; use_stdin = false;}
                    224:        }
                    225:        if (use_stdin) nfiles = 1;
                    226: 
                    227:        for (int file = 0; file < nfiles; file++) {
                    228:                char buf[BUFSIZ];
                    229:                if (!use_stdin) Current_file = nextfile(args);
                    230:                if (!Current_file.fp) continue;
                    231:                if (Output_type == Pic) printf(".lf 1 %s\n",Current_file.name);
                    232:                while (Current_file.gets(buf,sizeof(buf))) {
                    233:                        if (buf[0] == '.' && buf[1] == 'G' &&((buf[2] == 'D')||(buf[2] == 'R'))) {
                    234:                                /* they're playing our song */
                    235:                                graph_init();
                    236:                                if (buf[2] == 'R') User.set_rotate();
                    237:                                double userwidth = 0., userheight = 0.;
                    238:                                char fill[80]; fill[0] = 0;
                    239:                                sscanf(&buf[3],"%lf %lf %s",&userwidth,&userheight,fill);
                    240:                                User.set_size(userwidth,userheight);
                    241:                                if (!strcmp(fill,"fill"))
                    242:                                        set_bounds(userwidth,userheight);
                    243:                                yyparse();
                    244:                                reclaim_storage();
                    245:                        }
                    246:                        else if ((Output_type == Pic) && buf[0] == '.' && buf[1] == 'l' && buf[2] == 'f') {
                    247:                                char auxbuf[BUFSIZ];
                    248:                                int line_number;
                    249:                                if (sscanf(buf + 3,"%d %s",&line_number,auxbuf) == 2) {
                    250:                                        free(Current_file.name);
                    251:                                        printf(".lf %d %s\n",Current_file.line_number = line_number,
                    252:                                                Current_file.name = strcpy(new char[strlen(auxbuf)+1],auxbuf));
                    253:                                }
                    254:                                else
                    255:                                        printf(".lf %d\n",Current_file.line_number = line_number);
                    256:                        }
                    257:                        else fputs(buf,stdout);
                    258:                }
                    259:                if (!use_stdin) {
                    260:                        free(Current_file.name);
                    261:                        fclose(Current_file.fp);
                    262:                }
                    263:        }
                    264: }
                    265: 
                    266: /*** the lexer ***/
                    267: 
                    268: static char tokenbuf[BUFSIZ];
                    269: static char lexbuf[BUFSIZ];
                    270: static char *lexbufptr;
                    271: 
                    272: static char *eatwhitespace(char *p) {
                    273:        while (isspace(*p)) p++;
                    274:        return p;
                    275: }
                    276: 
                    277: /* grab drawing-code enclosed in matching curly braces.  strip braces. */
                    278: static char *scandesc() {
                    279:        char sidebuf[BUFSIZ],*p;
                    280:        int left = BUFSIZ - 1;
                    281:        int depth = 1;  // eat opening curlybrace
                    282: 
                    283:        p = sidebuf;
                    284:        while (left) {
                    285:                if (!*lexbufptr) {
                    286:                        lexbufptr = Current_file.gets(lexbuf,sizeof(lexbuf));
                    287:                        if (!lexbufptr) {
                    288:                                yyerror("unmatched '{' in drawing information");
                    289:                                return 0;
                    290:                        }
                    291:                }
                    292:                if (*lexbufptr == '}') {
                    293:                        depth--;
                    294:                        if (depth == 0) {
                    295:                                *p = 0;
                    296:                                lexbufptr++;
                    297:                                return newstring(sidebuf);
                    298:                        }
                    299:                }
                    300:                else if (*lexbufptr == '{') depth++;
                    301:                *p++ = *lexbufptr++;
                    302:                left--;
                    303:        }
                    304:        yyerror("overran buffer for drawing info");
                    305:        return 0;
                    306: }
                    307: 
                    308: /* bump p and return pointer to (static) null delimited copy of name token */
                    309: char *delimitname(char* &p) {
                    310:        char *q = tokenbuf;
                    311: 
                    312:        p = eatwhitespace(p);
                    313:        if (!*p) return 0;
                    314:        while ((*p) && !isspace(*p) && (*p != ';') && (*p != '{') && (*p != '}') 
                    315:                && (*p != ',') && (*p != '\"'))
                    316:                *q++ = *p++;
                    317:        *q = 0;
                    318:        return tokenbuf;
                    319: }
                    320: 
                    321: /* delimit a quoted string */
                    322: char *quotelimit(char* &p) {
                    323:        char *q = tokenbuf;
                    324: 
                    325:        ++p;
                    326:        while ((*p) && *p != '\"') {
                    327:                if ((*p == '\\') && (*(p + 1) == '\"')) p++;
                    328:                *q++ = *p++;
                    329:        }
                    330:        if (!*p) yyerror("quoted string ran off end of line");
                    331:        p++;
                    332:        *q = 0;
                    333:        return tokenbuf;
                    334: }
                    335: 
                    336: int squirrelbufinuse,squirrelbufsize;
                    337: char *squirrelbuf;
                    338: void squirrel(const char*p)
                    339: {
                    340:        int l = strlen(p);
                    341:        if (l > squirrelbufsize - squirrelbufinuse) {
                    342:                if (!squirrelbuf) squirrelbuf = (char*)malloc(BUFSIZ);
                    343:                else squirrelbuf = (char*)realloc(squirrelbuf,squirrelbufsize += BUFSIZ);
                    344:        }
                    345:        strcpy(squirrelbuf + squirrelbufinuse,p);
                    346:        squirrelbufinuse += l;
                    347: }
                    348: void unsquirrel()
                    349: {
                    350:        if (squirrelbuf) fputs(squirrelbuf,stdout);
                    351:        squirrelbufinuse = 0;
                    352: }
                    353: 
                    354: void copyPS()
                    355: {
                    356:        char buf[BUFSIZ];
                    357:        char *p;
                    358:        while (p = Current_file.gets(buf,sizeof(buf))) {
                    359:                if (p[0] == '.' && p[1] == 'P' && p[2] == 'E') return;
                    360:                else squirrel(buf);
                    361:        }
                    362:        yyerror("unmatched .PS inside .GS");
                    363: }
                    364: 
                    365: int myyylex()
                    366: {
                    367:        int rv = myyylex();
                    368:        fprintf(stderr,"returning %d\n",rv);
                    369:        if (rv == STRING || rv == DESC ) fprintf(stderr,"string val is %s\n",yylval.s);
                    370:        return rv;
                    371: }
                    372: 
                    373: int yylex()
                    374: {
                    375:        if (lexbufptr) lexbufptr = eatwhitespace(lexbufptr);
                    376:        while (!lexbufptr || !*lexbufptr) {
                    377:                while ((lexbufptr = Current_file.gets(lexbuf,sizeof(lexbuf)))
                    378:                && (lexbuf[0] == '.')) {
                    379:                        if (lexbuf[1] == 'P' && lexbuf[2] == 'S') copyPS();
                    380:                        else {
                    381:                                if (lexbuf[1] == 'G' && lexbuf[2] == 'E') {lexbufptr = 0;return EOF;}
                    382:                                else squirrel(lexbuf);  // assume it's a troff control
                    383:                        }
                    384:                }
                    385:                if (!lexbufptr) {
                    386:                        yyerror("unmatched .GS");
                    387:                        return EOF;
                    388:                }
                    389:                lexbufptr = eatwhitespace(lexbufptr);
                    390:        }
                    391: 
                    392:        switch(*lexbufptr) {
                    393:                case ',':
                    394:                case ';':
                    395:                        return *lexbufptr++;
                    396:                case '\"':
                    397:                        yylval.s = newstring(quotelimit(lexbufptr));
                    398:                        return STRING;
                    399:                case '}':
                    400:                        yyerror("unexpected '}'");
                    401:                        lexbufptr++;
                    402:                        return ';';
                    403:                case '{' :
                    404:                        lexbufptr++;
                    405:                        yylval.s = scandesc();
                    406:                        return DESC;
                    407:        }
                    408:        char *tokenptr = delimitname(lexbufptr);
                    409:        char *p = tokenptr;
                    410: 
                    411:        TFA_Init();
                    412:        while (*p) {
                    413:                TFA_Advance(*p);
                    414:                p++;
                    415:        }
                    416:        int token = TFA_Definition();
                    417:        if (token != -1) return token;
                    418:        yylval.s =  newstring(tokenptr);
                    419:        return STRING;
                    420: }
                    421: 
                    422: void error_context()
                    423: {
                    424:        char *p,*q;
                    425:        if (!lexbufptr) return;
                    426:        fprintf(stderr,"context is: ");
                    427:        for (p = lexbufptr - 1; (p > lexbuf) && (!isspace(*p)); p--);
                    428:        for (q = lexbuf; q < p; q++) fputc(*q,stderr);
                    429:        fputs(" >>> ",stderr);
                    430:        for (; q < lexbufptr; q++)fputc(*q,stderr);
                    431:        fputs(" <<< ",stderr);
                    432:        fputs(lexbufptr,stderr);
                    433: }
                    434: void yyerror(char*s,char *s1, char* s2, char *s3, char *s4) {
                    435:        extern void error_context();
                    436: 
                    437:        if (Syntax_error) return;
                    438:        Syntax_error = 1;
                    439:        fprintf(stderr, "%s: ", Cmd_name);
                    440:        fprintf(stderr, s, s1, s2, s3, s4);
                    441:        fprintf(stderr, " near line %d, file %s\n",Current_file.line_number,
                    442:                Current_file.name);
                    443:        error_context();
                    444: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.