📄 cons.c
字号:
else fputs(buf,stderr); if (++error_count >= 10) fatal("%s has too many errors.\n", stab_val(curcmd->c_filestab)->str_ptr);}voidwhile_io(cmd)register CMD *cmd;{ register ARG *arg = cmd->c_expr; STAB *asgnstab; /* hoist "while (<channel>)" up into command block */ if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_READ) { cmd->c_flags &= ~CF_OPTIMIZE; /* clear optimization type */ cmd->c_flags |= CFT_GETS; /* and set it to do the input */ cmd->c_stab = arg[1].arg_ptr.arg_stab; if (stab_io(arg[1].arg_ptr.arg_stab)->flags & IOF_ARGV) { cmd->c_expr = l(make_op(O_ASSIGN, 2, /* fake up "$_ =" */ stab2arg(A_LVAL,defstab), arg, Nullarg)); } else { free_arg(arg); cmd->c_expr = Nullarg; } } else if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_INDREAD) { cmd->c_flags &= ~CF_OPTIMIZE; /* clear optimization type */ cmd->c_flags |= CFT_INDGETS; /* and set it to do the input */ cmd->c_stab = arg[1].arg_ptr.arg_stab; free_arg(arg); cmd->c_expr = Nullarg; } else if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_GLOB) { if ((cmd->c_flags & CF_OPTIMIZE) == CFT_ARRAY) asgnstab = cmd->c_stab; else asgnstab = defstab; cmd->c_expr = l(make_op(O_ASSIGN, 2, /* fake up "$foo =" */ stab2arg(A_LVAL,asgnstab), arg, Nullarg)); cmd->c_flags &= ~CF_OPTIMIZE; /* clear optimization type */ }}CMD *wopt(cmd)register CMD *cmd;{ register CMD *tail; CMD *newtail; register int i; if (cmd->c_expr && (cmd->c_flags & CF_OPTIMIZE) == CFT_FALSE) opt_arg(cmd,1, cmd->c_type == C_EXPR); while_io(cmd); /* add $_ =, if necessary */ /* First find the end of the true list */ tail = cmd->ucmd.ccmd.cc_true; if (tail == Nullcmd) return cmd; New(112,newtail, 1, CMD); /* guaranteed continue */ for (;;) { /* optimize "next" to point directly to continue block */ if (tail->c_type == C_EXPR && tail->ucmd.acmd.ac_expr && tail->ucmd.acmd.ac_expr->arg_type == O_NEXT && (tail->ucmd.acmd.ac_expr->arg_len == 0 || (cmd->c_label && strEQ(cmd->c_label, tail->ucmd.acmd.ac_expr[1].arg_ptr.arg_str->str_ptr) ))) { arg_free(tail->ucmd.acmd.ac_expr); tail->ucmd.acmd.ac_expr = Nullarg; tail->c_type = C_NEXT; if (cmd->ucmd.ccmd.cc_alt != Nullcmd) tail->ucmd.ccmd.cc_alt = cmd->ucmd.ccmd.cc_alt; else tail->ucmd.ccmd.cc_alt = newtail; tail->ucmd.ccmd.cc_true = Nullcmd; } else if (tail->c_type == C_IF && !tail->ucmd.ccmd.cc_alt) { if (cmd->ucmd.ccmd.cc_alt != Nullcmd) tail->ucmd.ccmd.cc_alt = cmd->ucmd.ccmd.cc_alt; else tail->ucmd.ccmd.cc_alt = newtail; } else if (tail->c_type == C_CSWITCH || tail->c_type == C_NSWITCH) { if (cmd->ucmd.ccmd.cc_alt != Nullcmd) { for (i = tail->ucmd.scmd.sc_max; i >= 0; i--) if (!tail->ucmd.scmd.sc_next[i]) tail->ucmd.scmd.sc_next[i] = cmd->ucmd.ccmd.cc_alt; } else { for (i = tail->ucmd.scmd.sc_max; i >= 0; i--) if (!tail->ucmd.scmd.sc_next[i]) tail->ucmd.scmd.sc_next[i] = newtail; } } if (!tail->c_next) break; tail = tail->c_next; } /* if there's a continue block, link it to true block and find end */ if (cmd->ucmd.ccmd.cc_alt != Nullcmd) { tail->c_next = cmd->ucmd.ccmd.cc_alt; tail = tail->c_next; for (;;) { /* optimize "next" to point directly to continue block */ if (tail->c_type == C_EXPR && tail->ucmd.acmd.ac_expr && tail->ucmd.acmd.ac_expr->arg_type == O_NEXT && (tail->ucmd.acmd.ac_expr->arg_len == 0 || (cmd->c_label && strEQ(cmd->c_label, tail->ucmd.acmd.ac_expr[1].arg_ptr.arg_str->str_ptr) ))) { arg_free(tail->ucmd.acmd.ac_expr); tail->ucmd.acmd.ac_expr = Nullarg; tail->c_type = C_NEXT; tail->ucmd.ccmd.cc_alt = newtail; tail->ucmd.ccmd.cc_true = Nullcmd; } else if (tail->c_type == C_IF && !tail->ucmd.ccmd.cc_alt) { tail->ucmd.ccmd.cc_alt = newtail; } else if (tail->c_type == C_CSWITCH || tail->c_type == C_NSWITCH) { for (i = tail->ucmd.scmd.sc_max; i >= 0; i--) if (!tail->ucmd.scmd.sc_next[i]) tail->ucmd.scmd.sc_next[i] = newtail; } if (!tail->c_next) break; tail = tail->c_next; } /*SUPPRESS 530*/ for ( ; tail->c_next; tail = tail->c_next) ; } /* Here's the real trick: link the end of the list back to the beginning, * inserting a "last" block to break out of the loop. This saves one or * two procedure calls every time through the loop, because of how cmd_exec * does tail recursion. */ tail->c_next = newtail; tail = newtail; if (!cmd->ucmd.ccmd.cc_alt) cmd->ucmd.ccmd.cc_alt = tail; /* every loop has a continue now */#ifndef lint Copy((char *)cmd, (char *)tail, 1, CMD);#endif tail->c_type = C_EXPR; tail->c_flags ^= CF_INVERT; /* turn into "last unless" */ tail->c_next = tail->ucmd.ccmd.cc_true; /* loop directly back to top */ tail->ucmd.acmd.ac_expr = make_op(O_LAST,0,Nullarg,Nullarg,Nullarg); tail->ucmd.acmd.ac_stab = Nullstab; return cmd;}CMD *over(eachstab,cmd)STAB *eachstab;register CMD *cmd;{ /* hoist "for $foo (@bar)" up into command block */ cmd->c_flags &= ~CF_OPTIMIZE; /* clear optimization type */ cmd->c_flags |= CFT_ARRAY; /* and set it to do the iteration */ cmd->c_stab = eachstab; cmd->c_short = Str_new(23,0); /* just to save a field in struct cmd */ cmd->c_short->str_u.str_useful = -1; return cmd;}voidcmd_free(cmd)register CMD *cmd;{ register CMD *tofree; register CMD *head = cmd; if (!cmd) return; if (cmd->c_head != cmd) warn("Malformed cmd links\n"); while (cmd) { if (cmd->c_type != C_WHILE) { /* WHILE block is duplicated */ if (cmd->c_label) { Safefree(cmd->c_label); cmd->c_label = Nullch; } if (cmd->c_short) { str_free(cmd->c_short); cmd->c_short = Nullstr; } if (cmd->c_expr) { arg_free(cmd->c_expr); cmd->c_expr = Nullarg; } } switch (cmd->c_type) { case C_WHILE: case C_BLOCK: case C_ELSE: case C_IF: if (cmd->ucmd.ccmd.cc_true) { cmd_free(cmd->ucmd.ccmd.cc_true); cmd->ucmd.ccmd.cc_true = Nullcmd; } break; case C_EXPR: if (cmd->ucmd.acmd.ac_expr) { arg_free(cmd->ucmd.acmd.ac_expr); cmd->ucmd.acmd.ac_expr = Nullarg; } break; } tofree = cmd; cmd = cmd->c_next; if (tofree != head) /* to get Saber to shut up */ Safefree(tofree); if (cmd && cmd == head) /* reached end of while loop */ break; } Safefree(head);}voidarg_free(arg)register ARG *arg;{ register int i; if (!arg) return; for (i = 1; i <= arg->arg_len; i++) { switch (arg[i].arg_type & A_MASK) { case A_NULL: if (arg->arg_type == O_TRANS) { Safefree(arg[i].arg_ptr.arg_cval); arg[i].arg_ptr.arg_cval = Nullch; } break; case A_LEXPR: if (arg->arg_type == O_AASSIGN && arg[i].arg_ptr.arg_arg->arg_type == O_LARRAY) { char *name = stab_name(arg[i].arg_ptr.arg_arg[1].arg_ptr.arg_stab); if (strnEQ("_GEN_",name, 5)) /* array for foreach */ hdelete(defstash,name,strlen(name)); } /* FALL THROUGH */ case A_EXPR: arg_free(arg[i].arg_ptr.arg_arg); arg[i].arg_ptr.arg_arg = Nullarg; break; case A_CMD: cmd_free(arg[i].arg_ptr.arg_cmd); arg[i].arg_ptr.arg_cmd = Nullcmd; break; case A_WORD: case A_STAB: case A_LVAL: case A_READ: case A_GLOB: case A_ARYLEN: case A_LARYLEN: case A_ARYSTAB: case A_LARYSTAB: break; case A_SINGLE: case A_DOUBLE: case A_BACKTICK: str_free(arg[i].arg_ptr.arg_str); arg[i].arg_ptr.arg_str = Nullstr; break; case A_SPAT: spat_free(arg[i].arg_ptr.arg_spat); arg[i].arg_ptr.arg_spat = Nullspat; break; } } free_arg(arg);}voidspat_free(spat)register SPAT *spat;{ register SPAT *sp; HENT *entry; if (!spat) return; if (spat->spat_runtime) { arg_free(spat->spat_runtime); spat->spat_runtime = Nullarg; } if (spat->spat_repl) { arg_free(spat->spat_repl); spat->spat_repl = Nullarg; } if (spat->spat_short) { str_free(spat->spat_short); spat->spat_short = Nullstr; } if (spat->spat_regexp) { regfree(spat->spat_regexp); spat->spat_regexp = Null(REGEXP*); } /* now unlink from spat list */ for (entry = defstash->tbl_array['_']; entry; entry = entry->hent_next) { register HASH *stash; STAB *stab = (STAB*)entry->hent_val; if (!stab) continue; stash = stab_hash(stab); if (!stash || stash->tbl_spatroot == Null(SPAT*)) continue; if (stash->tbl_spatroot == spat) stash->tbl_spatroot = spat->spat_next; else { for (sp = stash->tbl_spatroot; sp && sp->spat_next != spat; sp = sp->spat_next) /*SUPPRESS 530*/ ; if (sp) sp->spat_next = spat->spat_next; } } Safefree(spat);}/* Recursively descend a command sequence and push the address of any string * that needs saving on recursion onto the tosave array. */static intcmd_tosave(cmd,willsave)register CMD *cmd;int willsave; /* willsave passes down the tree */{ register CMD *head = cmd; int shouldsave = FALSE; /* shouldsave passes up the tree */ int tmpsave; register CMD *lastcmd = Nullcmd; while (cmd) { if (cmd->c_expr) shouldsave |= arg_tosave(cmd->c_expr,willsave); switch (cmd->c_type) { case C_WHILE: if (cmd->ucmd.ccmd.cc_true) { tmpsave = cmd_tosave(cmd->ucmd.ccmd.cc_true,willsave); /* Here we check to see if the temporary array generated for * a foreach needs to be localized because of recursion. */ if (tmpsave && (cmd->c_flags & CF_OPTIMIZE) == CFT_ARRAY) { if (lastcmd && lastcmd->c_type == C_EXPR && lastcmd->c_expr) { ARG *arg = lastcmd->c_expr; if (arg->arg_type == O_ASSIGN && arg[1].arg_type == A_LEXPR && arg[1].arg_ptr.arg_arg->arg_type == O_LARRAY && strnEQ("_GEN_", stab_name( arg[1].arg_ptr.arg_arg[1].arg_ptr.arg_stab), 5)) { /* array generated for foreach */ (void)localize(arg); } } /* in any event, save the iterator */ if (cmd->c_short) /* Better safe than sorry */ (void)apush(tosave,cmd->c_short); } shouldsave |= tmpsave; } break; case C_BLOCK: case C_ELSE: case C_IF: if (cmd->ucmd.ccmd.cc_true) shouldsave |= cmd_tosave(cmd->ucmd.ccmd.cc_true,willsave); break; case C_EXPR: if (cmd->ucmd.acmd.ac_expr) shouldsave |= arg_tosave(cmd->ucmd.acmd.ac_expr,willsave); break; } lastcmd = cmd; cmd = cmd->c_next; if (cmd && cmd == head) /* reached end of while loop */ break; } return shouldsave;}static intarg_tosave(arg,willsave)register ARG *arg;int willsave;{ register int i; int shouldsave = FALSE; for (i = arg->arg_len; i >= 1; i--) { switch (arg[i].arg_type & A_MASK) { case A_NULL: break; case A_LEXPR: case A_EXPR: shouldsave |= arg_tosave(arg[i].arg_ptr.arg_arg,shouldsave); break; case A_CMD: shouldsave |= cmd_tosave(arg[i].arg_ptr.arg_cmd,shouldsave); break; case A_WORD: case A_STAB: case A_LVAL: case A_READ: case A_GLOB: case A_ARYLEN: case A_SINGLE: case A_DOUBLE: case A_BACKTICK: break; case A_SPAT: shouldsave |= spat_tosave(arg[i].arg_ptr.arg_spat); break; } } switch (arg->arg_type) { case O_RETURN: saw_return = TRUE; break; case O_EVAL: case O_SUBR: shouldsave = TRUE; break; } if (willsave && arg->arg_ptr.arg_str) (void)apush(tosave,arg->arg_ptr.arg_str); return shouldsave;}static intspat_tosave(spat)register SPAT *spat;{ int shouldsave = FALSE; if (spat->spat_runtime) shouldsave |= arg_tosave(spat->spat_runtime,FALSE); if (spat->spat_repl) { shouldsave |= arg_tosave(spat->spat_repl,FALSE); } return shouldsave;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -