static void writegraph(profilenode *p, graphnode *n) { listnode *l; vertex *v; edge *e; graphedge *g; size_t i, t; for (l = n->children.head; l->next != NULL; l = l->next) { /* The following three lines are a bit excessive and result from * using class-based programming in C. These conversions would be * automatically calculated by the compiler if we were using C++ * classes. */ g = (graphedge *) ((char *) l - offsetof(graphedge, cnode)); e = (edge *) ((char *) g - offsetof(edge, gnode)); v = (vertex *) ((char *) e->gnode.child - offsetof(vertex, gnode)); if (!(e->flags & 1)) { e->flags |= 1; for (i = t = 0; i < 4; i++) if (showcounts) { t += e->data.acount[i]; if (showleaks) t -= e->data.dcount[i]; } else { t += e->data.atotal[i]; if (showleaks) t -= e->data.dtotal[i]; } if ((t > 0) || !showleaks) { fputs(" \"", graphfile); if (p == NULL) fputs("START", graphfile); else printsymbol(graphfile, p); fputs("\" -> \"", graphfile); if (&v->gnode == &graph.end) fputs("ALLOC", graphfile); else printsymbol(graphfile, v->pnode); fprintf(graphfile, "\" [label = \"%lu\"", t); if (e->flags & 2) fputs(", style = dotted", graphfile); fputs("];\n", graphfile); } writegraph(v->pnode, &v->gnode); } } if (p == NULL) for (e = (edge *) edgelist.head; e->node.next != NULL; e = (edge *) e->node.next) e->flags &= ~1; }
int main(int argc, char **argv) { char b[256]; char *f, *g; int c, e, h, r, v; g = NULL; e = h = v = 0; r = EXIT_SUCCESS; maxstack = 1; progname = __mp_basename(argv[0]); while ((c = __mp_getopt(argc, argv, __mp_shortopts(b, options_table), options_table)) != EOF) switch (c) { case OF_ADDRESSES: useaddresses = 1; break; case OF_CALLGRAPH: showgraph = 1; break; case OF_COUNTS: showcounts = 1; break; case OF_GRAPHFILE: g = __mp_optarg; break; case OF_HELP: h = 1; break; case OF_LEAKS: showleaks = 1; break; case OF_STACKDEPTH: if (!__mp_getnum(progname, __mp_optarg, (long *) &maxstack, 1)) e = 1; break; case OF_VERSION: v = 1; break; default: e = 1; break; } argc -= __mp_optindex; argv += __mp_optindex; if (v == 1) { fprintf(stdout, "%s %s\n%s %s\n\n", progname, PROGVERSION, __mp_copyright, __mp_author); fputs("This is free software, and you are welcome to redistribute it " "under certain\n", stdout); fputs("conditions; see the GNU Lesser General Public License for " "details.\n\n", stdout); fputs("For the latest mpatrol release and documentation,\n", stdout); fprintf(stdout, "visit %s.\n\n", __mp_homepage); } if (argc > 1) e = 1; if ((e == 1) || (h == 1)) { fprintf(stdout, "Usage: %s [options] [file]\n\n", progname); if (h == 0) fprintf(stdout, "Type `%s --help' for a complete list of " "options.\n", progname); else __mp_showopts(options_table); if (e == 1) exit(EXIT_FAILURE); exit(EXIT_SUCCESS); } if (argc == 1) f = argv[0]; else f = MP_PROFFILE; acount = dcount = 0; atotal = dtotal = 0; acounts = dcounts = NULL; atotals = dtotals = 0; binsize = 0; data = NULL; datasize = 0; nodes = NULL; nodesize = 0; addrs = NULL; symbols = NULL; sbound = mbound = lbound = 0; __mp_newtree(&proftree); __mp_newtree(&temptree); __mp_newlist(&edgelist); __mp_newgraph(&graph); if (strcmp(f, "-") == 0) proffile = stdin; else if ((proffile = fopen(f, "rb")) == NULL) { fprintf(stderr, "%s: Cannot open file `%s'\n", progname, f); exit(EXIT_FAILURE); } readfile(); fclose(proffile); bintable(); fputs("\n\n", stdout); directtable(); fputs("\n\n", stdout); leaktable(); /* The reason that the allocation call graph is not used for the direct * allocation and memory leak tables is that the code to build and display * the allocation call graph was added much later. Rather than convert * these tables to use the new call graph, I decided to keep the code that * already worked and only use the call graph for any new tables. */ buildgraph(); if (showgraph) { fputs("\n\n", stdout); callgraph(); } if (g != NULL) { if (strcmp(g, "stdout") == 0) graphfile = stdout; else if (strcmp(g, "stderr") == 0) graphfile = stderr; else if ((graphfile = fopen(g, "w")) == NULL) { fprintf(stderr, "%s: Cannot open file `%s'\n", progname, g); r = EXIT_FAILURE; } if (r == EXIT_SUCCESS) { fprintf(graphfile, "/* produced by %s %s from %s */\n\n", progname, PROGVERSION, f); if (showleaks) fputs("digraph \"memory leak call graph\"\n{\n", graphfile); else fputs("digraph \"allocation call graph\"\n{\n", graphfile); writegraph(NULL, &graph.start); fputs("}\n", graphfile); if ((graphfile != stdout) && (graphfile != stderr)) fclose(graphfile); } } deletegraph(); if (acounts != NULL) free(acounts); if (dcounts != NULL) free(dcounts); if (data != NULL) free(data); if (nodes != NULL) free(nodes); if (addrs != NULL) free(addrs); if (symbols != NULL) free(symbols); return r; }
void main(int argc, char *argv[]) { int c, i; int statistics = 0; int draw = 0; char initialize = 'p'; extern char *optarg; #ifndef NOTIMES srand48((long)time(NULL)); #else srand48(0); #endif //NOTIMES if (readgraph()) exit(1); if (nvertices == 0) { fprintf(stderr, "Empty graph\n"); exit(1); } if (nvertices < 200) iter[1] = 200; else iter[1] = nvertices; iter[0] = iter[1] / 20; iter[2] = iter[1] / 10; height = 0.65 * sqrt((double)nvertices); while ((c = getopt(argc, argv, "fg:i:n:osv:w:B:D:E:H:NOW:")) != EOF) { switch (c) { case 'f': flat = 1; break; case 'g': sscanf( optarg, "%d,%d,%d", &(gstep[0]), &(gstep[1]), &(gstep[2]) ); draw = 1; break; case 'i': initialize = optarg[0]; break; break; case 'n': sscanf( optarg, "%d,%d,%d", &(iter[0]), &(iter[1]), &(iter[2]) ); break; case 'o': fprintf(stdout,"%d\n",getpid()); fflush(stdout); break; case 's': statistics = 1; break; case 'v': sscanf( optarg, "%d,%d,%d", &(vstep[0]), &(vstep[1]), &(vstep[2]) ); break; case 'w': bestangle = atof( optarg ) / 180.0 * M_PI; break; case 'B': frames_begin = atoi( optarg ); break; case 'D': maxdist = atof( optarg ); break; case 'E': frames_end = atoi( optarg ); break; case 'H': height = atof( optarg ); break; case 'N': print_frame_count = 1; break; case 'O': count_only = print_frame_count = 1; break; case 'W': sleep_ms = atoi(optarg); break; case '?': fprintf(stderr, "%s: unknown option -%c\n", argv[0], c); exit(1); } } switch(initialize) { case 'r': random_positions(); break; case 's': initial_positions_planar(1); break; case 'z': zero_out_positions(); break; case 'p': initial_positions_planar(0); break; default: break; } for (i = 1; i <= nvertices; i++) { vertices[i].saved_pos.x = vertices[i].pos.x; vertices[i].saved_pos.y = vertices[i].pos.y; vertices[i].saved_pos.z = vertices[i].pos.z; } maxstep = iter[0] + iter[1] + iter[2]; #if USE_TCL if (draw > 0) { init_tk(); draw_graph(0); sprintf(tcl_command_buffer, "stop_go"); c = Tcl_Eval(interp, tcl_command_buffer); if (c != TCL_OK) { fprintf(stderr, "in Tcl_Eval: %s\n", interp->result); exit(c); } } #endif /*USE_TCL*/ if (position()) exit(1); if (writegraph()) exit(1); if (statistics) show_statistics(); #if USE_TCL if (draw > 0) exit_tk(); #endif /*USE_TCL*/ }