From: Emden Gansner Date: Fri, 2 Mar 2012 20:51:06 +0000 (-0500) Subject: Replace setjmp/longjmp with simple returns; X-Git-Tag: LAST_LIBGRAPH~32^2~466^2~2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=77f437a2695413e1c8bf2fbeb825a42a273d2f04;p=graphviz Replace setjmp/longjmp with simple returns; give name of edge if box reclamation fails. --- diff --git a/lib/common/routespl.c b/lib/common/routespl.c index 055bddd9e..70e19390c 100644 --- a/lib/common/routespl.c +++ b/lib/common/routespl.c @@ -33,7 +33,6 @@ static edge_t *origedge; #endif static int nedges, nboxes; /* total no. of edges and boxes used in routing */ -static jmp_buf jbuf; static int routeinit; /* static data used across multiple edges */ @@ -44,7 +43,7 @@ static int polypointn; /* size of polypoints[] */ static Pedge_t *edges; /* polygon edges passed to Proutespline */ static int edgen; /* size of edges[] */ -static void checkpath(int, boxf*, path*); +static int checkpath(int, boxf*, path*); static int mkspacep(int size); static void printpath(path * pp); #ifdef DEBUG @@ -369,6 +368,25 @@ limitBoxes (boxf* boxes, int boxn, pointf *pps, int pn, int delta) #define INIT_DELTA 10 #define LOOP_TRIES 15 /* number of times to try to limiting boxes to regain space, using smaller divisions */ +/* routesplines: + * Route a path using the path info in pp. This includes start and end points + * plus a collection of contiguous boxes contain the terminal points. The boxes + * are converted into a containing polygon. A shortest path is constructed within + * the polygon from between the terminal points. If polyline is true, this path + * is converted to a spline representation. Otherwise, we call the path planner to + * convert the polyline into a smooth spline staying within the polygon. In both + * cases, the function returns an array of the computed control points. The number + * of these points is given in npoints. + * + * Note that the returned points are stored in a single array, so the points must be + * used before another call to this function. + * + * During cleanup, the function determines the x-extent of the spline in the box, so + * the box can be shrunk to the minimum width. The extra space can then be used by other + * edges. + * + * If a catastrophic error, return NULL. + */ static pointf *_routesplines(path * pp, int *npoints, int polyline) { Ppoly_t poly; @@ -396,13 +414,14 @@ static pointf *_routesplines(path * pp, int *npoints, int polyline) realedge = ED_to_orig(realedge)); if (!realedge) { agerr(AGERR, "in routesplines, cannot find NORMAL edge\n"); - longjmp (jbuf, 1); + return NULL; } boxes = pp->boxes; boxn = pp->nbox; - checkpath(boxn, boxes, pp); + if (checkpath(boxn, boxes, pp)) + return NULL; #ifdef DEBUG if (debugleveln(realedge, 1)) @@ -459,7 +478,7 @@ static pointf *_routesplines(path * pp, int *npoints, int polyline) else { if (!(prev == -1 && next == -1)) { agerr(AGERR, "in routesplines, illegal values of prev %d and next %d, line %d\n", prev, next, __LINE__); - longjmp (jbuf, 1); + return NULL; } } } @@ -492,8 +511,7 @@ static pointf *_routesplines(path * pp, int *npoints, int polyline) if (!(prev == -1 && next == -1)) { /* it went badly, e.g. degenerate box in boxlist */ agerr(AGERR, "in routesplines, illegal values of prev %d and next %d, line %d\n", prev, next, __LINE__); - longjmp (jbuf, 1); /* for correctness sake, it's best to just stop */ - return ps; /* could also be reported as a lost edge (no spline) */ + return NULL; /* for correctness sake, it's best to just stop */ } polypoints[pi].x = boxes[bi].UR.x; polypoints[pi++].y = boxes[bi].LL.y; @@ -508,7 +526,7 @@ static pointf *_routesplines(path * pp, int *npoints, int polyline) } else { agerr(AGERR, "in routesplines, edge is a loop at %s\n", agnameof(aghead(realedge))); - longjmp (jbuf, 1); + return NULL; } if (flip) { @@ -529,7 +547,7 @@ static pointf *_routesplines(path * pp, int *npoints, int polyline) eps[1].x = pp->end.p.x, eps[1].y = pp->end.p.y; if (Pshortestpath(&poly, eps, &pl) < 0) { agerr(AGERR, "in routesplines, Pshortestpath failed\n"); - longjmp (jbuf, 1); + return NULL; } #ifdef DEBUG if (debugleveln(realedge, 3)) { @@ -563,7 +581,7 @@ static pointf *_routesplines(path * pp, int *npoints, int polyline) if (Proutespline(edges, poly.pn, pl, evs, &spl) < 0) { agerr(AGERR, "in routesplines, Proutespline failed\n"); - longjmp (jbuf, 1); + return NULL; } #ifdef DEBUG if (debugleveln(realedge, 3)) { @@ -573,7 +591,7 @@ static pointf *_routesplines(path * pp, int *npoints, int polyline) #endif } if (mkspacep(spl.pn)) - longjmp (jbuf, 1); /* Bailout if no memory left */ + return NULL; /* Bailout if no memory left */ for (bi = 0; bi < boxn; bi++) { boxes[bi].LL.x = INT_MAX; @@ -612,7 +630,7 @@ static pointf *_routesplines(path * pp, int *npoints, int polyline) * loop and we can see the bad edge, and even use the showboxes scaffolding. */ Ppolyline_t polyspl; - agerr(AGWARN, "Unable to reclaim box space in spline routing. Something is probably seriously wrong.\n"); + agerr(AGWARN, "Unable to reclaim box space in spline routing for edge \"%s\" -> \"%s\". Something is probably seriously wrong.\n", agnameof(agtail(realedge)), agnameof(aghead(realedge))); make_polyline (pl, &polyspl); limitBoxes (boxes, boxn, polyspl.ps, polyspl.pn, INIT_DELTA); free (polyspl.ps); @@ -634,19 +652,11 @@ static pointf *_routesplines(path * pp, int *npoints, int polyline) pointf *routesplines(path * pp, int *npoints) { - if (setjmp (jbuf)) { - *npoints = 0; - return NULL; - } return _routesplines (pp, npoints, 0); } pointf *routepolylines(path * pp, int *npoints) { - if (setjmp (jbuf)) { - *npoints = 0; - return NULL; - } return _routesplines (pp, npoints, 1); } @@ -671,8 +681,10 @@ static int overlap(int i0, int i1, int j0, int j1) * audit process in the 5E control program - if you've given up on * fixing all the bugs, at least try to engineer around them! * in postmodern CS, we could call this "self-healing code." + * + * Return 1 on failure; 0 on success. */ -static void checkpath(int boxn, boxf* boxes, path* thepath) +static int checkpath(int boxn, boxf* boxes, path* thepath) { boxf *ba, *bb; int bi, i, errs, l, r, d, u; @@ -697,7 +709,7 @@ static void checkpath(int boxn, boxf* boxes, path* thepath) if (ba->LL.x > ba->UR.x || ba->LL.y > ba->UR.y) { agerr(AGERR, "in checkpath, box 0 has LL coord > UR coord\n"); printpath(thepath); - longjmp (jbuf, 1); + return 1; } for (bi = 0; bi < boxn - 1; bi++) { ba = &boxes[bi], bb = &boxes[bi + 1]; @@ -705,7 +717,7 @@ static void checkpath(int boxn, boxf* boxes, path* thepath) agerr(AGERR, "in checkpath, box %d has LL coord > UR coord\n", bi + 1); printpath(thepath); - longjmp (jbuf, 1); + return 1; } l = (ba->UR.x < bb->LL.x) ? 1 : 0; r = (ba->LL.x > bb->UR.x) ? 1 : 0; @@ -827,6 +839,7 @@ static void checkpath(int boxn, boxf* boxes, path* thepath) abort(); #endif } + return 0; } static int mkspacep(int size)