|
|
1.1 ! root 1: #ifndef lint ! 2: static char *rcsid = ! 3: "$Header: frame.c,v 1.3 87/12/14 16:51:52 sklower Exp $"; ! 4: #endif ! 5: ! 6: /* ! 7: * frame.c $Locker: $ ! 8: * non local goto handlers ! 9: * ! 10: * (c) copyright 1982, Regents of the University of California ! 11: */ ! 12: ! 13: ! 14: #include "global.h" ! 15: #include "frame.h" ! 16: ! 17: /* ! 18: * This is a collection of routines for manipulating evaluation frames. ! 19: * Such frames are generated to mark the state of execution at a certain ! 20: * spot. They are created upon entry to prog, do, catch, errset and ! 21: * other misc. functions (such as eval when in *rset mode). ! 22: * ! 23: * As described in h/frame.h, each frame is identified by a class, which ! 24: * says who created the frame. The global variable errp points to the ! 25: * first (newest) frame on the stack. ! 26: * The standard way to create a frame is to say ! 27: * ! 28: * errp = Pushframe(class,arg1,arg2); /* create and link in new ! 29: * frame of give class * / ! 30: * ! 31: * poping the frame must be done explicity if the routine was not exited by ! 32: * a non-local goto. This is done by ! 33: * errp = Popframe(); ! 34: * ! 35: * When a frame is created, it marks the current state on the runtime stack. ! 36: * Execution will continues after the Pushframe call with the value of the ! 37: * global variable 'retval' set to 0. Some time later control may be thrown ! 38: * up the stack and it will seem that Pushframe returned again. This time ! 39: * retval will contain a non-zero value indicating what caused the non-local ! 40: * jump. retval will have one of the values from C_???? in h/frame.h . ! 41: * It will not have just of the C_???? values, it will only have a value ! 42: * which makes sense. For example, coming out of a Pushframe(F_CATCH,tag,nil); ! 43: * retval will either be 0 (initially) or C_THROW, [and in addition it will ! 44: * already have been determined that the tag of the catch matches the tag ! 45: * being thrown, [[ this does not apply to GO's and PROG tags]] ]. ! 46: * ! 47: * In doing throws, goto's, returns, or errors up the stack we are always ! 48: * conscious of the possiblity of unwind-protect sitting between where ! 49: * control starts and where it wants to get. Thus it may be necessary ! 50: * to save the state of the non-local jump, give control to the unwind-protect ! 51: * and have it continue the non-local jump. ! 52: */ ! 53: ! 54: /* ! 55: * Inonlocalgo(class, arg1, arg2) :: do a general non-local goto. ! 56: * class - one of the C_???? in h/frame.h ! 57: * arg1 - tag in C_THROW, C_GO; value in C_RETURN ! 58: * arg2 - value in C_THROW; ! 59: * this handles GO's, THROW's, RETURN's but not errors, which have more ! 60: * state to throw and a lot of different things to do if there is no one ! 61: * to catch the error. ! 62: * ! 63: * This routine never returns. ! 64: */ ! 65: ! 66: Inonlocalgo(class, arg1, arg2) ! 67: lispval arg1,arg2; ! 68: { ! 69: struct frame *uwpframe, *Inlthrow(); ! 70: lispval handy; ! 71: ! 72: /* ! 73: * scan for something to match 'class', return if nothing found, or ! 74: * if we must first handle an unwind protect. ! 75: */ ! 76: while( uwpframe = Inlthrow(class,arg1,arg2) ) ! 77: { ! 78: /* build error frame description to be use to continue this throw */ ! 79: protect(lispretval = handy = newdot()); ! 80: handy->d.car = Veruwpt; ! 81: handy = handy->d.cdr = newdot(); ! 82: handy->d.car = inewint(class); /* remember type */ ! 83: handy = handy->d.cdr = newdot(); ! 84: handy->d.car = arg1; ! 85: handy = handy->d.cdr = newdot(); ! 86: handy->d.car = arg2; ! 87: retval = C_THROW; ! 88: Iretfromfr(uwpframe); ! 89: /* NOT REACHED */ ! 90: } ! 91: ! 92: /* ! 93: * nothing to go to, signal the appropriate error ! 94: */ ! 95: ! 96: switch(class) ! 97: { ! 98: case C_GO: errorh1(Vermisc, "No prog to go to with this tag ", ! 99: nil,FALSE,0,arg1); ! 100: /* NOT REACHED */ ! 101: ! 102: case C_RET: errorh(Vermisc, "No prog to return from", nil, FALSE, 0); ! 103: /* NOT REACHED */ ! 104: ! 105: case C_THROW: errorh1(Vermisc, "No catch for this tag ", nil, FALSE , 0, ! 106: arg1); ! 107: /* NOT REACHED */ ! 108: default: error("Internal Inonlocalgoto error" ,FALSE); ! 109: /* NOT REACHED */ ! 110: } ! 111: } ! 112: ! 113: /* ! 114: * Inlthrow(class,arg1,arg2) :: look up the stack for a form to handle ! 115: * a value of 'class' being thrown. If found, do the throw. If an ! 116: * unwind-protect must be done, then return a pointer to that frame ! 117: * first. If there is nothing to catch this throw, we return 0. ! 118: */ ! 119: ! 120: struct frame * ! 121: Inlthrow(class, arg1, arg2) ! 122: lispval arg1, arg2; ! 123: { ! 124: struct frame *uwpframe = (struct frame *)0; ! 125: struct frame *curp; ! 126: int pass = 1; ! 127: ! 128: restart: ! 129: for(curp = errp; curp != (struct frame *) 0; curp = curp->olderrp) ! 130: { ! 131: switch(curp->class) ! 132: { ! 133: case F_PROG: if(class == C_RET || class == C_GO) ! 134: { ! 135: if(pass == 2) return(uwpframe); ! 136: else ! 137: { ! 138: lispretval = arg1; ! 139: retval = class; ! 140: Iretfromfr(curp); ! 141: /* NOT REACHED */ ! 142: } ! 143: } ! 144: break; ! 145: ! 146: case F_CATCH: if((pass == 1) && (curp->larg1 == Veruwpt)) ! 147: { ! 148: uwpframe = curp; ! 149: pass = 2; ! 150: goto restart; ! 151: } ! 152: else if(class == C_THROW ! 153: && matchtags(arg1,curp->larg1)) ! 154: { ! 155: if(pass == 2) return(uwpframe); ! 156: else ! 157: { ! 158: lispretval = arg2; /* value thrown */ ! 159: retval = class; ! 160: Iretfromfr(curp); ! 161: /* NOT REACHED */ ! 162: } ! 163: } ! 164: break; ! 165: ! 166: case F_RESET: if(class == C_RESET) ! 167: { ! 168: if(pass == 2) return(uwpframe); ! 169: else ! 170: { ! 171: retval = class; ! 172: Iretfromfr(curp); ! 173: /* NOT REACHED */ ! 174: } ! 175: } ! 176: break; ! 177: ! 178: } ! 179: } ! 180: return((struct frame *)0); /* nobody wants it */ ! 181: } ! 182: ! 183: ! 184: #ifndef tahoe ! 185: Iretfromfr(fram) ! 186: register struct frame *fram; ! 187: { ! 188: xpopnames(fram->svbnp); ! 189: qretfromfr(); /* modified in sed script to point to real function */ ! 190: /* NOT REACHED */ ! 191: } ! 192: #endif ! 193: ! 194: /* matchtags :: return TRUE if there is any atom in common between the ! 195: * two tags. Either tag may be an atom or an list of atoms. ! 196: */ ! 197: matchtags(tag1,tag2) ! 198: lispval tag1, tag2; ! 199: { ! 200: int repeat1 = FALSE; ! 201: int repeat2 = FALSE; ! 202: lispval temp1 = tag1; ! 203: lispval temp2 = tag2; ! 204: lispval t1,t2; ! 205: ! 206: if(TYPE(tag1) == ATOM) ! 207: { ! 208: t1 = tag1; ! 209: } ! 210: else { ! 211: t1 = tag1->d.car; ! 212: repeat1 = TRUE; ! 213: } ! 214: ! 215: if(TYPE(tag2) == ATOM) ! 216: { ! 217: t2 = tag2; ! 218: } ! 219: else { ! 220: t2 = tag2->d.car; ! 221: repeat2 = TRUE; ! 222: } ! 223: ! 224: loop: ! 225: if(t1 == t2) return(TRUE); ! 226: if(repeat2) ! 227: { ! 228: if((temp2 = temp2->d.cdr) != nil) ! 229: { ! 230: t2 = temp2->d.car; ! 231: goto loop; ! 232: } ! 233: } ! 234: ! 235: if(repeat1) ! 236: { ! 237: if((temp1 = temp1->d.cdr) != nil) ! 238: { ! 239: t1 = temp1->d.car; ! 240: if(repeat2) ! 241: { ! 242: temp2 = tag2; ! 243: t2 = temp2->d.car; ! 244: goto loop; ! 245: } ! 246: else t2 = tag2; ! 247: goto loop; ! 248: } ! 249: } ! 250: return(FALSE); ! 251: } ! 252: ! 253: /* ! 254: * framedump :: debugging routine to print the contents of the error ! 255: * frame ! 256: * ! 257: */ ! 258: lispval ! 259: Lframedump() ! 260: { ! 261: struct frame *curp; ! 262: ! 263: printf("Frame dump\n"); ! 264: for(curp = errp ; curp != (struct frame *)0 ; curp=curp->olderrp) ! 265: { ! 266: printf("at %x is ",curp); ! 267: ! 268: switch(curp->class) { ! 269: case F_PROG: printf(" prog\n"); ! 270: break; ! 271: ! 272: case F_CATCH:printf(" catching "); ! 273: printr(curp->larg1,stdout); ! 274: putchar('\n'); ! 275: break; ! 276: ! 277: case F_RESET:printf(" reset \n"); ! 278: break; ! 279: ! 280: case F_EVAL: printf(" eval: "); ! 281: printr(curp->larg1,stdout); ! 282: putchar('\n'); ! 283: break; ! 284: ! 285: case F_FUNCALL: printf(" funcall: "); ! 286: printr(curp->larg1,stdout); ! 287: putchar('\n'); ! 288: break; ! 289: ! 290: case F_TO_FORT: printf(" calling fortran:\n"); ! 291: break; ! 292: ! 293: case F_TO_LISP: printf(" fortran calling lisp:\n"); ! 294: break; ! 295: ! 296: ! 297: default: ! 298: printf(" unknown: %d \n",curp->class); ! 299: } ! 300: fflush(stdout); ! 301: } ! 302: printf("End of stack\n"); ! 303: return(nil); ! 304: } ! 305:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.