Annotation of researchv10no/cmd/dag/dag.c, revision 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.