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

Defined functions

copyopt defined in line 443; used 3 times
deb defined in line 432; used 24 times

Defined variables

str_chop defined in line 15; used 2 times
Last modified: 1988-01-31
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3472
Valid CSS Valid XHTML 1.0 Strict