|
|
1.1 ! root 1: #ifndef lint ! 2: static char *rcsid = ! 3: "$Header: frame.c,v 1.2 83/05/07 23:46:38 jkf Exp $"; ! 4: #endif ! 5: ! 6: /* -[Sat May 7 22:27:57 1983 by jkf]- ! 7: * frame.c $Locker: sklower $ ! 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: Iretfromfr(fram) ! 185: register struct frame *fram; ! 186: { ! 187: xpopnames(fram->svbnp); ! 188: qretfromfr(); /* modified in sed script to point to real function */ ! 189: /* NOT REACHED */ ! 190: } ! 191: ! 192: /* matchtags :: return TRUE if there is any atom in common between the ! 193: * two tags. Either tag may be an atom or an list of atoms. ! 194: */ ! 195: matchtags(tag1,tag2) ! 196: lispval tag1, tag2; ! 197: { ! 198: int repeat1 = FALSE; ! 199: int repeat2 = FALSE; ! 200: lispval temp1 = tag1; ! 201: lispval temp2 = tag2; ! 202: lispval t1,t2; ! 203: ! 204: if(TYPE(tag1) == ATOM) ! 205: { ! 206: t1 = tag1; ! 207: } ! 208: else { ! 209: t1 = tag1->d.car; ! 210: repeat1 = TRUE; ! 211: } ! 212: ! 213: if(TYPE(tag2) == ATOM) ! 214: { ! 215: t2 = tag2; ! 216: } ! 217: else { ! 218: t2 = tag2->d.car; ! 219: repeat2 = TRUE; ! 220: } ! 221: ! 222: loop: ! 223: if(t1 == t2) return(TRUE); ! 224: if(repeat2) ! 225: { ! 226: if((temp2 = temp2->d.cdr) != nil) ! 227: { ! 228: t2 = temp2->d.car; ! 229: goto loop; ! 230: } ! 231: } ! 232: ! 233: if(repeat1) ! 234: { ! 235: if((temp1 = temp1->d.cdr) != nil) ! 236: { ! 237: t1 = temp1->d.car; ! 238: if(repeat2) ! 239: { ! 240: temp2 = tag2; ! 241: t2 = temp2->d.car; ! 242: goto loop; ! 243: } ! 244: else t2 = tag2; ! 245: goto loop; ! 246: } ! 247: } ! 248: return(FALSE); ! 249: } ! 250: ! 251: /* ! 252: * framedump :: debugging routine to print the contents of the error ! 253: * frame ! 254: * ! 255: */ ! 256: lispval ! 257: Lframedump() ! 258: { ! 259: struct frame *curp; ! 260: ! 261: printf("Frame dump\n"); ! 262: for(curp = errp ; curp != (struct frame *)0 ; curp=curp->olderrp) ! 263: { ! 264: printf("at %x is ",curp); ! 265: ! 266: switch(curp->class) { ! 267: case F_PROG: printf(" prog\n"); ! 268: break; ! 269: ! 270: case F_CATCH:printf(" catching "); ! 271: printr(curp->larg1,stdout); ! 272: putchar('\n'); ! 273: break; ! 274: ! 275: case F_RESET:printf(" reset \n"); ! 276: break; ! 277: ! 278: case F_EVAL: printf(" eval: "); ! 279: printr(curp->larg1,stdout); ! 280: putchar('\n'); ! 281: break; ! 282: ! 283: case F_FUNCALL: printf(" funcall: "); ! 284: printr(curp->larg1,stdout); ! 285: putchar('\n'); ! 286: break; ! 287: ! 288: case F_TO_FORT: printf(" calling fortran:\n"); ! 289: break; ! 290: ! 291: case F_TO_LISP: printf(" fortran calling lisp:\n"); ! 292: break; ! 293: ! 294: ! 295: default: ! 296: printf(" unknown: %d \n",curp->class); ! 297: } ! 298: fflush(stdout); ! 299: } ! 300: printf("End of stack\n"); ! 301: return(nil); ! 302: } ! 303:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.