1: /* $Header: cmd.c,v 1.0.1.1 88/01/21 21:24:16 root Exp $
   2:  *
   3:  * $Log:	cmd.c,v $
   4:  * Revision 1.0.1.1  88/01/21  21:24:16  root
   5:  * The redo cmd got a segmentation fault because trace context stack overflowed.
   6:  *
   7:  * Revision 1.0  87/12/18  13:04:51  root
   8:  * Initial revision
   9:  *
  10:  */
  11: 
  12: #include "handy.h"
  13: #include "EXTERN.h"
  14: #include "search.h"
  15: #include "util.h"
  16: #include "perl.h"
  17: 
  18: static STR str_chop;
  19: 
  20: /* This is the main command loop.  We try to spend as much time in this loop
  21:  * as possible, so lots of optimizations do their activities in here.  This
  22:  * means things get a little sloppy.
  23:  */
  24: 
  25: STR *
  26: cmd_exec(cmd)
  27: register CMD *cmd;
  28: {
  29:     SPAT *oldspat;
  30: #ifdef DEBUGGING
  31:     int olddlevel;
  32:     int entdlevel;
  33: #endif
  34:     register STR *retstr;
  35:     register char *tmps;
  36:     register int cmdflags;
  37:     register bool match;
  38:     register char *go_to = goto_targ;
  39:     ARG *arg;
  40:     FILE *fp;
  41: 
  42:     retstr = &str_no;
  43: #ifdef DEBUGGING
  44:     entdlevel = dlevel;
  45: #endif
  46: tail_recursion_entry:
  47: #ifdef DEBUGGING
  48:     dlevel = entdlevel;
  49: #endif
  50:     if (cmd == Nullcmd)
  51:     return retstr;
  52:     cmdflags = cmd->c_flags;    /* hopefully load register */
  53:     if (go_to) {
  54:     if (cmd->c_label && strEQ(go_to,cmd->c_label))
  55:         goto_targ = go_to = Nullch;     /* here at last */
  56:     else {
  57:         switch (cmd->c_type) {
  58:         case C_IF:
  59:         oldspat = curspat;
  60: #ifdef DEBUGGING
  61:         olddlevel = dlevel;
  62: #endif
  63:         retstr = &str_yes;
  64:         if (cmd->ucmd.ccmd.cc_true) {
  65: #ifdef DEBUGGING
  66:             debname[dlevel] = 't';
  67:             debdelim[dlevel++] = '_';
  68: #endif
  69:             retstr = cmd_exec(cmd->ucmd.ccmd.cc_true);
  70:         }
  71:         if (!goto_targ) {
  72:             go_to = Nullch;
  73:         } else {
  74:             retstr = &str_no;
  75:             if (cmd->ucmd.ccmd.cc_alt) {
  76: #ifdef DEBUGGING
  77:             debname[dlevel] = 'e';
  78:             debdelim[dlevel++] = '_';
  79: #endif
  80:             retstr = cmd_exec(cmd->ucmd.ccmd.cc_alt);
  81:             }
  82:         }
  83:         if (!goto_targ)
  84:             go_to = Nullch;
  85:         curspat = oldspat;
  86: #ifdef DEBUGGING
  87:         dlevel = olddlevel;
  88: #endif
  89:         break;
  90:         case C_BLOCK:
  91:         case C_WHILE:
  92:         if (!(cmdflags & CF_ONCE)) {
  93:             cmdflags |= CF_ONCE;
  94:             loop_ptr++;
  95:             loop_stack[loop_ptr].loop_label = cmd->c_label;
  96: #ifdef DEBUGGING
  97:             if (debug & 4) {
  98:             deb("(Pushing label #%d %s)\n",
  99:               loop_ptr,cmd->c_label);
 100:             }
 101: #endif
 102:         }
 103:         switch (setjmp(loop_stack[loop_ptr].loop_env)) {
 104:         case O_LAST:    /* not done unless go_to found */
 105:             go_to = Nullch;
 106:             retstr = &str_no;
 107: #ifdef DEBUGGING
 108:             olddlevel = dlevel;
 109: #endif
 110:             curspat = oldspat;
 111: #ifdef DEBUGGING
 112:             if (debug & 4) {
 113:             deb("(Popping label #%d %s)\n",loop_ptr,
 114:                 loop_stack[loop_ptr].loop_label);
 115:             }
 116: #endif
 117:             loop_ptr--;
 118:             cmd = cmd->c_next;
 119:             goto tail_recursion_entry;
 120:         case O_NEXT:    /* not done unless go_to found */
 121:             go_to = Nullch;
 122:             goto next_iter;
 123:         case O_REDO:    /* not done unless go_to found */
 124:             go_to = Nullch;
 125:             goto doit;
 126:         }
 127:         oldspat = curspat;
 128: #ifdef DEBUGGING
 129:         olddlevel = dlevel;
 130: #endif
 131:         if (cmd->ucmd.ccmd.cc_true) {
 132: #ifdef DEBUGGING
 133:             debname[dlevel] = 't';
 134:             debdelim[dlevel++] = '_';
 135: #endif
 136:             cmd_exec(cmd->ucmd.ccmd.cc_true);
 137:         }
 138:         if (!goto_targ) {
 139:             go_to = Nullch;
 140:             goto next_iter;
 141:         }
 142: #ifdef DEBUGGING
 143:         dlevel = olddlevel;
 144: #endif
 145:         if (cmd->ucmd.ccmd.cc_alt) {
 146: #ifdef DEBUGGING
 147:             debname[dlevel] = 'a';
 148:             debdelim[dlevel++] = '_';
 149: #endif
 150:             cmd_exec(cmd->ucmd.ccmd.cc_alt);
 151:         }
 152:         if (goto_targ)
 153:             break;
 154:         go_to = Nullch;
 155:         goto finish_while;
 156:         }
 157:         cmd = cmd->c_next;
 158:         if (cmd && cmd->c_head == cmd)  /* reached end of while loop */
 159:         return retstr;      /* targ isn't in this block */
 160:         goto tail_recursion_entry;
 161:     }
 162:     }
 163: 
 164: until_loop:
 165: 
 166: #ifdef DEBUGGING
 167:     if (debug & 2) {
 168:     deb("%s	(%lx)	r%lx	t%lx	a%lx	n%lx	cs%lx\n",
 169:         cmdname[cmd->c_type],cmd,cmd->c_expr,
 170:         cmd->ucmd.ccmd.cc_true,cmd->ucmd.ccmd.cc_alt,cmd->c_next,curspat);
 171:     }
 172:     debname[dlevel] = cmdname[cmd->c_type][0];
 173:     debdelim[dlevel++] = '!';
 174: #endif
 175:     while (tmps_max >= 0)       /* clean up after last eval */
 176:     str_free(tmps_list[tmps_max--]);
 177: 
 178:     /* Here is some common optimization */
 179: 
 180:     if (cmdflags & CF_COND) {
 181:     switch (cmdflags & CF_OPTIMIZE) {
 182: 
 183:     case CFT_FALSE:
 184:         retstr = cmd->c_first;
 185:         match = FALSE;
 186:         if (cmdflags & CF_NESURE)
 187:         goto maybe;
 188:         break;
 189:     case CFT_TRUE:
 190:         retstr = cmd->c_first;
 191:         match = TRUE;
 192:         if (cmdflags & CF_EQSURE)
 193:         goto flipmaybe;
 194:         break;
 195: 
 196:     case CFT_REG:
 197:         retstr = STAB_STR(cmd->c_stab);
 198:         match = str_true(retstr);   /* => retstr = retstr, c2 should fix */
 199:         if (cmdflags & (match ? CF_EQSURE : CF_NESURE))
 200:         goto flipmaybe;
 201:         break;
 202: 
 203:     case CFT_ANCHOR:    /* /^pat/ optimization */
 204:         if (multiline) {
 205:         if (*cmd->c_first->str_ptr && !(cmdflags & CF_EQSURE))
 206:             goto scanner;   /* just unanchor it */
 207:         else
 208:             break;      /* must evaluate */
 209:         }
 210:         /* FALL THROUGH */
 211:     case CFT_STROP:     /* string op optimization */
 212:         retstr = STAB_STR(cmd->c_stab);
 213:         if (*cmd->c_first->str_ptr == *str_get(retstr) &&
 214:             strnEQ(cmd->c_first->str_ptr, str_get(retstr),
 215:               cmd->c_flen) ) {
 216:         if (cmdflags & CF_EQSURE) {
 217:             match = !(cmdflags & CF_FIRSTNEG);
 218:             retstr = &str_yes;
 219:             goto flipmaybe;
 220:         }
 221:         }
 222:         else if (cmdflags & CF_NESURE) {
 223:         match = cmdflags & CF_FIRSTNEG;
 224:         retstr = &str_no;
 225:         goto flipmaybe;
 226:         }
 227:         break;          /* must evaluate */
 228: 
 229:     case CFT_SCAN:          /* non-anchored search */
 230:       scanner:
 231:         retstr = STAB_STR(cmd->c_stab);
 232:         if (instr(str_get(retstr),cmd->c_first->str_ptr)) {
 233:         if (cmdflags & CF_EQSURE) {
 234:             match = !(cmdflags & CF_FIRSTNEG);
 235:             retstr = &str_yes;
 236:             goto flipmaybe;
 237:         }
 238:         }
 239:         else if (cmdflags & CF_NESURE) {
 240:         match = cmdflags & CF_FIRSTNEG;
 241:         retstr = &str_no;
 242:         goto flipmaybe;
 243:         }
 244:         break;          /* must evaluate */
 245: 
 246:     case CFT_GETS:          /* really a while (<file>) */
 247:         last_in_stab = cmd->c_stab;
 248:         fp = last_in_stab->stab_io->fp;
 249:         retstr = defstab->stab_val;
 250:         if (fp && str_gets(retstr, fp)) {
 251:         last_in_stab->stab_io->lines++;
 252:         match = TRUE;
 253:         }
 254:         else if (last_in_stab->stab_io->flags & IOF_ARGV)
 255:         goto doeval;    /* doesn't necessarily count as EOF yet */
 256:         else {
 257:         retstr = &str_no;
 258:         match = FALSE;
 259:         }
 260:         goto flipmaybe;
 261:     case CFT_EVAL:
 262:         break;
 263:     case CFT_UNFLIP:
 264:         retstr = eval(cmd->c_expr,Null(char***));
 265:         match = str_true(retstr);
 266:         if (cmd->c_expr->arg_type == O_FLIP)    /* undid itself? */
 267:         cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
 268:         goto maybe;
 269:     case CFT_CHOP:
 270:         retstr = cmd->c_stab->stab_val;
 271:         match = (retstr->str_cur != 0);
 272:         tmps = str_get(retstr);
 273:         tmps += retstr->str_cur - match;
 274:         str_set(&str_chop,tmps);
 275:         *tmps = '\0';
 276:         retstr->str_nok = 0;
 277:         retstr->str_cur = tmps - retstr->str_ptr;
 278:         retstr = &str_chop;
 279:         goto flipmaybe;
 280:     }
 281: 
 282:     /* we have tried to make this normal case as abnormal as possible */
 283: 
 284:     doeval:
 285:     retstr = eval(cmd->c_expr,Null(char***));
 286:     match = str_true(retstr);
 287:     goto maybe;
 288: 
 289:     /* if flipflop was true, flop it */
 290: 
 291:     flipmaybe:
 292:     if (match && cmdflags & CF_FLIP) {
 293:         if (cmd->c_expr->arg_type == O_FLOP) {  /* currently toggled? */
 294:         retstr = eval(cmd->c_expr,Null(char***)); /* let eval undo it */
 295:         cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
 296:         }
 297:         else {
 298:         retstr = eval(cmd->c_expr,Null(char***)); /* let eval do it */
 299:         if (cmd->c_expr->arg_type == O_FLOP)    /* still toggled? */
 300:             cmdflags = copyopt(cmd,cmd->c_expr[4].arg_ptr.arg_cmd);
 301:         }
 302:     }
 303:     else if (cmdflags & CF_FLIP) {
 304:         if (cmd->c_expr->arg_type == O_FLOP) {  /* currently toggled? */
 305:         match = TRUE;               /* force on */
 306:         }
 307:     }
 308: 
 309:     /* at this point, match says whether our expression was true */
 310: 
 311:     maybe:
 312:     if (cmdflags & CF_INVERT)
 313:         match = !match;
 314:     if (!match && cmd->c_type != C_IF) {
 315:         cmd = cmd->c_next;
 316:         goto tail_recursion_entry;
 317:     }
 318:     }
 319: 
 320:     /* now to do the actual command, if any */
 321: 
 322:     switch (cmd->c_type) {
 323:     case C_NULL:
 324:     fatal("panic: cmd_exec\n");
 325:     case C_EXPR:            /* evaluated for side effects */
 326:     if (cmd->ucmd.acmd.ac_expr) {   /* more to do? */
 327:         retstr = eval(cmd->ucmd.acmd.ac_expr,Null(char***));
 328:     }
 329:     break;
 330:     case C_IF:
 331:     oldspat = curspat;
 332: #ifdef DEBUGGING
 333:     olddlevel = dlevel;
 334: #endif
 335:     if (match) {
 336:         retstr = &str_yes;
 337:         if (cmd->ucmd.ccmd.cc_true) {
 338: #ifdef DEBUGGING
 339:         debname[dlevel] = 't';
 340:         debdelim[dlevel++] = '_';
 341: #endif
 342:         retstr = cmd_exec(cmd->ucmd.ccmd.cc_true);
 343:         }
 344:     }
 345:     else {
 346:         retstr = &str_no;
 347:         if (cmd->ucmd.ccmd.cc_alt) {
 348: #ifdef DEBUGGING
 349:         debname[dlevel] = 'e';
 350:         debdelim[dlevel++] = '_';
 351: #endif
 352:         retstr = cmd_exec(cmd->ucmd.ccmd.cc_alt);
 353:         }
 354:     }
 355:     curspat = oldspat;
 356: #ifdef DEBUGGING
 357:     dlevel = olddlevel;
 358: #endif
 359:     break;
 360:     case C_BLOCK:
 361:     case C_WHILE:
 362:     if (!(cmdflags & CF_ONCE)) {    /* first time through here? */
 363:         cmdflags |= CF_ONCE;
 364:         loop_ptr++;
 365:         loop_stack[loop_ptr].loop_label = cmd->c_label;
 366: #ifdef DEBUGGING
 367:         if (debug & 4) {
 368:         deb("(Pushing label #%d %s)\n",
 369:           loop_ptr,cmd->c_label);
 370:         }
 371: #endif
 372:     }
 373:     switch (setjmp(loop_stack[loop_ptr].loop_env)) {
 374:     case O_LAST:
 375:         retstr = &str_no;
 376:         curspat = oldspat;
 377: #ifdef DEBUGGING
 378:         if (debug & 4) {
 379:         deb("(Popping label #%d %s)\n",loop_ptr,
 380:             loop_stack[loop_ptr].loop_label);
 381:         }
 382: #endif
 383:         loop_ptr--;
 384:         cmd = cmd->c_next;
 385:         goto tail_recursion_entry;
 386:     case O_NEXT:
 387:         goto next_iter;
 388:     case O_REDO:
 389: #ifdef DEBUGGING
 390:         dlevel = olddlevel;
 391: #endif
 392:         goto doit;
 393:     }
 394:     oldspat = curspat;
 395: #ifdef DEBUGGING
 396:     olddlevel = dlevel;
 397: #endif
 398:     doit:
 399:     if (cmd->ucmd.ccmd.cc_true) {
 400: #ifdef DEBUGGING
 401:         debname[dlevel] = 't';
 402:         debdelim[dlevel++] = '_';
 403: #endif
 404:         cmd_exec(cmd->ucmd.ccmd.cc_true);
 405:     }
 406:     /* actually, this spot is never reached anymore since the above
 407: 	 * cmd_exec() returns through longjmp().  Hooray for structure.
 408: 	 */
 409:       next_iter:
 410: #ifdef DEBUGGING
 411:     dlevel = olddlevel;
 412: #endif
 413:     if (cmd->ucmd.ccmd.cc_alt) {
 414: #ifdef DEBUGGING
 415:         debname[dlevel] = 'a';
 416:         debdelim[dlevel++] = '_';
 417: #endif
 418:         cmd_exec(cmd->ucmd.ccmd.cc_alt);
 419:     }
 420:       finish_while:
 421:     curspat = oldspat;
 422: #ifdef DEBUGGING
 423:     dlevel = olddlevel - 1;
 424: #endif
 425:     if (cmd->c_type != C_BLOCK)
 426:         goto until_loop;    /* go back and evaluate conditional again */
 427:     }
 428:     if (cmdflags & CF_LOOP) {
 429:     cmdflags |= CF_COND;        /* now test the condition */
 430:     goto until_loop;
 431:     }
 432:     cmd = cmd->c_next;
 433:     goto tail_recursion_entry;
 434: }
 435: 
 436: #ifdef DEBUGGING
 437: /*VARARGS1*/
 438: deb(pat,a1,a2,a3,a4,a5,a6,a7,a8)
 439: char *pat;
 440: {
 441:     register int i;
 442: 
 443:     for (i=0; i<dlevel; i++)
 444:     fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
 445:     fprintf(stderr,pat,a1,a2,a3,a4,a5,a6,a7,a8);
 446: }
 447: #endif
 448: 
 449: copyopt(cmd,which)
 450: register CMD *cmd;
 451: register CMD *which;
 452: {
 453:     cmd->c_flags &= CF_ONCE|CF_COND|CF_LOOP;
 454:     cmd->c_flags |= which->c_flags;
 455:     cmd->c_first = which->c_first;
 456:     cmd->c_flen = which->c_flen;
 457:     cmd->c_stab = which->c_stab;
 458:     return cmd->c_flags;
 459: }

Defined functions

copyopt defined in line 449; used 3 times
deb defined in line 438; used 24 times

Defined variables

str_chop defined in line 18; used 2 times
Last modified: 1988-02-03
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2083
Valid CSS Valid XHTML 1.0 Strict