⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cons.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
    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 + -