exception.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. #include "dat.h"
  2. #include "fns.h"
  3. #include "error.h"
  4. #include "interp.h"
  5. #include "isa.h"
  6. #include "runt.h"
  7. #include "kernel.h"
  8. #include "raise.h"
  9. static int
  10. ematch(char *pat, char *exp)
  11. {
  12. int l;
  13. if(strcmp(pat, exp) == 0)
  14. return 1;
  15. l = strlen(pat);
  16. if(l == 0)
  17. return 0;
  18. if(pat[l-1] == '*') {
  19. if(l == 1)
  20. return 1;
  21. if(strncmp(pat, exp, l-1) == 0)
  22. return 1;
  23. }
  24. return 0;
  25. }
  26. static void
  27. setstr(String *s, char *p)
  28. {
  29. if(s == H)
  30. return;
  31. if(s->len < 0 || s->max < 4)
  32. return;
  33. kstrcpy(s->Sascii, p, s->max); /* TO DO: we are assuming they aren't runes */
  34. s->len = strlen(s->Sascii);
  35. }
  36. static String *exstr;
  37. void
  38. excinit(void)
  39. {
  40. exstr = newstring(ERRMAX);
  41. poolimmutable(D2H(exstr));
  42. }
  43. static String*
  44. newestring(char *estr)
  45. {
  46. String *s;
  47. if(waserror()){
  48. setstr(exstr, estr);
  49. D2H(exstr)->ref++;
  50. return exstr;
  51. }
  52. s = c2string(estr, strlen(estr));
  53. poperror();
  54. return s;
  55. }
  56. #define NOPC 0xffffffff
  57. #define FRTYPE(f) ((f)->t == nil ? SEXTYPE(f)->reg.TR : (f)->t)
  58. /*
  59. * clear up an uncalled frame
  60. */
  61. static void
  62. freeframe(uchar *fp, int setsp)
  63. {
  64. Frame *f;
  65. f = (Frame*)fp;
  66. if(f->t == nil)
  67. unextend(f);
  68. else if(f->t->np)
  69. freeptrs(f, f->t);
  70. if(setsp)
  71. R.SP = fp;
  72. }
  73. int
  74. handler(char *estr)
  75. {
  76. Prog *p;
  77. Modlink *m, *mr;
  78. int str, ne;
  79. ulong pc, newpc;
  80. long eoff;
  81. uchar *fp, **eadr;
  82. Frame *f;
  83. Type *t, *zt;
  84. Handler *h;
  85. Except *e;
  86. void *v;
  87. p = currun();
  88. if(*estr == 0 || p == nil)
  89. return 0;
  90. str = p->exval == H || D2H(p->exval)->t == &Tstring;
  91. m = R.M;
  92. if(m->compiled)
  93. pc = (ulong)R.PC-(ulong)m->prog;
  94. else
  95. pc = R.PC-m->prog;
  96. pc--;
  97. fp = R.FP;
  98. while(fp != nil){ /* look for a handler */
  99. if((h = m->m->htab) != nil){
  100. for( ; h->etab != nil; h++){
  101. if(pc < h->pc1 || pc >= h->pc2)
  102. continue;
  103. eoff = h->eoff;
  104. zt = h->t;
  105. for(e = h->etab, ne = h->ne; e->s != nil; e++, ne--){
  106. if(ematch(e->s, estr) && (str && ne <= 0 || !str && ne > 0)){
  107. newpc = e->pc;
  108. goto found;
  109. }
  110. }
  111. newpc = e->pc;
  112. if(newpc != NOPC)
  113. goto found;
  114. }
  115. }
  116. if(!str && fp != R.FP){ /* becomes a string exception in immediate caller */
  117. v = p->exval;
  118. p->exval = *(String**)v;
  119. D2H(p->exval)->ref++;
  120. destroy(v);
  121. str = 1;
  122. continue;
  123. }
  124. f = (Frame*)fp;
  125. if(f->mr != nil)
  126. m = f->mr;
  127. if(m->compiled)
  128. pc = (ulong)f->lr-(ulong)m->prog;
  129. else
  130. pc = f->lr-m->prog;
  131. pc--;
  132. fp = f->fp;
  133. }
  134. destroy(p->exval);
  135. p->exval = H;
  136. return 0;
  137. found:
  138. {
  139. int n;
  140. char name[3*KNAMELEN];
  141. pc = modstatus(&R, name, sizeof(name));
  142. n = 10+1+strlen(name)+1+strlen(estr)+1;
  143. p->exstr = realloc(p->exstr, n);
  144. if(p->exstr != nil)
  145. snprint(p->exstr, n, "%lud %s %s", pc, name, estr);
  146. }
  147. /*
  148. * there may be an uncalled frame at the top of the stack
  149. */
  150. f = (Frame*)R.FP;
  151. t = FRTYPE(f);
  152. if(R.FP < R.EX || R.FP >= R.TS)
  153. freeframe(R.EX+OA(Stkext, reg.tos.fr), 0);
  154. else if(R.FP+t->size < R.SP)
  155. freeframe(R.FP+t->size, 1);
  156. m = R.M;
  157. while(R.FP != fp){
  158. f = (Frame*)R.FP;
  159. R.PC = f->lr;
  160. R.FP = f->fp;
  161. R.SP = (uchar*)f;
  162. mr = f->mr;
  163. if(f->t == nil)
  164. unextend(f);
  165. else if(f->t->np)
  166. freeptrs(f, f->t);
  167. if(mr != nil){
  168. m = mr;
  169. destroy(R.M);
  170. R.M = m;
  171. R.MP = m->MP;
  172. }
  173. }
  174. if(zt != nil){
  175. freeptrs(fp, zt);
  176. initmem(zt, fp);
  177. }
  178. eadr = (uchar**)(fp+eoff);
  179. destroy(*eadr);
  180. *eadr = H;
  181. if(p->exval == H)
  182. *eadr = (uchar*)newestring(estr); /* might fail */
  183. else{
  184. D2H(p->exval)->ref++;
  185. *eadr = p->exval;
  186. }
  187. if(m->compiled)
  188. R.PC = (Inst*)((ulong)m->prog+newpc);
  189. else
  190. R.PC = m->prog+newpc;
  191. memmove(&p->R, &R, sizeof(R));
  192. p->kill = nil;
  193. destroy(p->exval);
  194. p->exval = H;
  195. return 1;
  196. }