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

📄 eval.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	case Node_mod:		if (x2 == 0)			fatal("division by zero attempted in mod");#ifndef FMOD_MISSING		return tmp_number(fmod (x1, x2));#else		(void) modf(x1 / x2, &x);		return tmp_number(x1 - x * x2);#endif	case Node_plus:		return tmp_number(x1 + x2);	case Node_minus:		return tmp_number(x1 - x2);	case Node_var_array:		fatal("attempt to use an array in a scalar context");	default:		fatal("illegal type (%d) in tree_eval", tree->type);	}	return 0;}/* Is TREE true or false?  Returns 0==false, non-zero==true */static inteval_condition(tree)register NODE *tree;{	register NODE *t1;	register int ret;	if (tree == NULL)	/* Null trees are the easiest kinds */		return 1;	if (tree->type == Node_line_range) {		/*		 * Node_line_range is kind of like Node_match, EXCEPT: the		 * lnode field (more properly, the condpair field) is a node		 * of a Node_cond_pair; whether we evaluate the lnode of that		 * node or the rnode depends on the triggered word.  More		 * precisely:  if we are not yet triggered, we tree_eval the		 * lnode; if that returns true, we set the triggered word. 		 * If we are triggered (not ELSE IF, note), we tree_eval the		 * rnode, clear triggered if it succeeds, and perform our		 * action (regardless of success or failure).  We want to be		 * able to begin and end on a single input record, so this		 * isn't an ELSE IF, as noted above.		 */		if (!tree->triggered)			if (!eval_condition(tree->condpair->lnode))				return 0;			else				tree->triggered = 1;		/* Else we are triggered */		if (eval_condition(tree->condpair->rnode))			tree->triggered = 0;		return 1;	}	/*	 * Could just be J.random expression. in which case, null and 0 are	 * false, anything else is true 	 */	t1 = tree_eval(tree);	if (t1->flags & MAYBE_NUM)		(void) force_number(t1);	if (t1->flags & NUMBER)		ret = t1->numbr != 0.0;	else		ret = t1->stlen != 0;	free_temp(t1);	return ret;}/* * compare two nodes, returning negative, 0, positive */intcmp_nodes(t1, t2)register NODE *t1, *t2;{	register int ret;	register int len1, len2;	if (t1 == t2)		return 0;	if (t1->flags & MAYBE_NUM)		(void) force_number(t1);	if (t2->flags & MAYBE_NUM)		(void) force_number(t2);	if ((t1->flags & NUMBER) && (t2->flags & NUMBER)) {		if (t1->numbr == t2->numbr) return 0;		else if (t1->numbr - t2->numbr < 0)  return -1;		else return 1;	}	(void) force_string(t1);	(void) force_string(t2);	len1 = t1->stlen;	len2 = t2->stlen;	if (len1 == 0 || len2 == 0)		return len1 - len2;	ret = memcmp(t1->stptr, t2->stptr, len1 <= len2 ? len1 : len2);	return ret == 0 ? len1-len2 : ret;}static NODE *op_assign(tree)register NODE *tree;{	AWKNUM rval, lval;	NODE **lhs;	AWKNUM t1, t2;	long ltemp;	NODE *tmp;	Func_ptr after_assign = NULL;	lhs = get_lhs(tree->lnode, &after_assign);	lval = force_number(*lhs);	/*	 * Can't unref *lhs until we know the type; doing so	 * too early breaks   x += x   sorts of things.	 */	switch(tree->type) {	case Node_preincrement:	case Node_predecrement:		unref(*lhs);		*lhs = make_number(lval +			       (tree->type == Node_preincrement ? 1.0 : -1.0));		if (after_assign)			(*after_assign)();		return *lhs;	case Node_postincrement:	case Node_postdecrement:		unref(*lhs);		*lhs = make_number(lval +			       (tree->type == Node_postincrement ? 1.0 : -1.0));		if (after_assign)			(*after_assign)();		return tmp_number(lval);	default:		break;	/* handled below */	}	tmp = tree_eval(tree->rnode);	rval = force_number(tmp);	free_temp(tmp);	unref(*lhs);	switch(tree->type) {	case Node_assign_exp:		if ((ltemp = rval) == rval) {	/* integer exponent */			if (ltemp == 0)				*lhs = make_number((AWKNUM) 1);			else if (ltemp == 1)				*lhs = make_number(lval);			else {				/* doing it this way should be more precise */				for (t1 = t2 = lval; --ltemp; )					t1 *= t2;				*lhs = make_number(t1);			}		} else			*lhs = make_number((AWKNUM) pow((double) lval, (double) rval));		break;	case Node_assign_times:		*lhs = make_number(lval * rval);		break;	case Node_assign_quotient:		if (rval == (AWKNUM) 0)			fatal("division by zero attempted in /=");#ifdef _CRAY		/*		 * special case for integer division, put in for Cray		 */		ltemp = rval;		if (ltemp == 0) {			*lhs = make_number(lval / rval);			break;		}		ltemp = (long) lval / ltemp;		if (ltemp * lval == rval)			*lhs = make_number((AWKNUM) ltemp);		else#endif			*lhs = make_number(lval / rval);		break;	case Node_assign_mod:		if (rval == (AWKNUM) 0)			fatal("division by zero attempted in %=");#ifndef FMOD_MISSING		*lhs = make_number(fmod(lval, rval));#else		(void) modf(lval / rval, &t1);		t2 = lval - rval * t1;		*lhs = make_number(t2);#endif		break;	case Node_assign_plus:		*lhs = make_number(lval + rval);		break;	case Node_assign_minus:		*lhs = make_number(lval - rval);		break;	default:		cant_happen();	}	if (after_assign)		(*after_assign)();	return *lhs;}NODE **stack_ptr;static NODE *func_call(name, arg_list)NODE *name;		/* name is a Node_val giving function name */NODE *arg_list;		/* Node_expression_list of calling args. */{	register NODE *arg, *argp, *r;	NODE *n, *f;	jmp_buf volatile func_tag_stack;	jmp_buf volatile loop_tag_stack;	int volatile save_loop_tag_valid = 0;	NODE **volatile save_stack, *save_ret_node;	NODE **volatile local_stack = NULL, **sp;	int count;	extern NODE *ret_node;	/*	 * retrieve function definition node	 */	f = lookup(name->stptr);	if (!f || f->type != Node_func)		fatal("function `%s' not defined", name->stptr);#ifdef FUNC_TRACE	fprintf(stderr, "function %s called\n", name->stptr);#endif	count = f->lnode->param_cnt;	if (count)		emalloc(local_stack, NODE **, count*sizeof(NODE *), "func_call");	sp = local_stack;	/*	 * for each calling arg. add NODE * on stack	 */	for (argp = arg_list; count && argp != NULL; argp = argp->rnode) {		arg = argp->lnode;		getnode(r);		r->type = Node_var;		/*		 * call by reference for arrays; see below also		 */		if (arg->type == Node_param_list)			arg = stack_ptr[arg->param_cnt];		if (arg->type == Node_var_array)			*r = *arg;		else {			n = tree_eval(arg);			r->lnode = dupnode(n);			r->rnode = (NODE *) NULL;			free_temp(n);  		}		*sp++ = r;		count--;	}	if (argp != NULL)	/* left over calling args. */		warning(		    "function `%s' called with more arguments than declared",		    name->stptr);	/*	 * add remaining params. on stack with null value	 */	while (count-- > 0) {		getnode(r);		r->type = Node_var;		r->lnode = Nnull_string;		r->rnode = (NODE *) NULL;		*sp++ = r;	}	/*	 * Execute function body, saving context, as a return statement	 * will longjmp back here.	 *	 * Have to save and restore the loop_tag stuff so that a return	 * inside a loop in a function body doesn't scrog any loops going	 * on in the main program.  We save the necessary info in variables	 * local to this function so that function nesting works OK.	 * We also only bother to save the loop stuff if we're in a loop	 * when the function is called.	 */	if (loop_tag_valid) {		int junk = 0;		save_loop_tag_valid = (volatile int) loop_tag_valid;		PUSH_BINDING(loop_tag_stack, loop_tag, junk);		loop_tag_valid = 0;	}	save_stack = stack_ptr;	stack_ptr = local_stack;	PUSH_BINDING(func_tag_stack, func_tag, func_tag_valid);	save_ret_node = ret_node;	ret_node = Nnull_string;	/* default return value */	if (setjmp(func_tag) == 0)		(void) interpret(f->rnode);	r = ret_node;	ret_node = (NODE *) save_ret_node;	RESTORE_BINDING(func_tag_stack, func_tag, func_tag_valid);	stack_ptr = (NODE **) save_stack;	/*	 * here, we pop each parameter and check whether	 * it was an array.  If so, and if the arg. passed in was	 * a simple variable, then the value should be copied back.	 * This achieves "call-by-reference" for arrays.	 */	sp = local_stack;	count = f->lnode->param_cnt;	for (argp = arg_list; count > 0 && argp != NULL; argp = argp->rnode) {		arg = argp->lnode;		if (arg->type == Node_param_list)			arg = stack_ptr[arg->param_cnt];		n = *sp++;		if (arg->type == Node_var && n->type == Node_var_array) {			/* should we free arg->var_value ? */			arg->var_array = n->var_array;			arg->type = Node_var_array;		}		unref(n->lnode);		freenode(n);		count--;	}	while (count-- > 0) {		n = *sp++;		/* if n is an (local) array, all the elements should be freed */		if (n->type == Node_var_array) {			assoc_clear(n);			free(n->var_array);		}		unref(n->lnode);		freenode(n);	}	if (local_stack)		free((char *) local_stack);	/* Restore the loop_tag stuff if necessary. */	if (save_loop_tag_valid) {		int junk = 0;		loop_tag_valid = (int) save_loop_tag_valid;		RESTORE_BINDING(loop_tag_stack, loop_tag, junk);	}	if (!(r->flags & PERM))		r->flags |= TEMP;	return r;}/* * This returns a POINTER to a node pointer. get_lhs(ptr) is the current * value of the var, or where to store the var's new value  */NODE **get_lhs(ptr, assign)register NODE *ptr;Func_ptr *assign;{	register NODE **aptr = NULL;	register NODE *n;	switch (ptr->type) {	case Node_var_array:		fatal("attempt to use an array in a scalar context");	case Node_var:		aptr = &(ptr->var_value);#ifdef DEBUG		if (ptr->var_value->stref <= 0)			cant_happen();#endif		break;	case Node_FIELDWIDTHS:		aptr = &(FIELDWIDTHS_node->var_value);		if (assign)			*assign = set_FIELDWIDTHS;		break;	case Node_RS:		aptr = &(RS_node->var_value);		if (assign)			*assign = set_RS;		break;	case Node_FS:		aptr = &(FS_node->var_value);		if (assign)			*assign = set_FS;		break;	case Node_FNR:		unref(FNR_node->var_value);		FNR_node->var_value = make_number((AWKNUM) FNR);		aptr = &(FNR_node->var_value);		if (assign)			*assign = set_FNR;		break;	case Node_NR:		unref(NR_node->var_value);		NR_node->var_value = make_number((AWKNUM) NR);		aptr = &(NR_node->var_value);		if (assign)			*assign = set_NR;		break;	case Node_NF:		if (NF == -1)			(void) get_field(HUGE-1, assign); /* parse record */		unref(NF_node->var_value);		NF_node->var_value = make_number((AWKNUM) NF);		aptr = &(NF_node->var_value);		if (assign)			*assign = set_NF;		break;	case Node_IGNORECASE:		unref(IGNORECASE_node->var_value);		IGNORECASE_node->var_value = make_number((AWKNUM) IGNORECASE);		aptr = &(IGNORECASE_node->var_value);		if (assign)			*assign = set_IGNORECASE;		break;	case Node_OFMT:		aptr = &(OFMT_node->var_value);		if (assign)			*assign = set_OFMT;		break;	case Node_CONVFMT:		aptr = &(CONVFMT_node->var_value);		if (assign)			*assign = set_CONVFMT;		break;	case Node_ORS:		aptr = &(ORS_node->var_value);		if (assign)			*assign = set_ORS;		break;	case Node_OFS:		aptr = &(OFS_node->var_value);		if (assign)			*assign = set_OFS;		break;	case Node_param_list:		aptr = &(stack_ptr[ptr->param_cnt]->var_value);		break;	case Node_field_spec:		{		int field_num;		n = tree_eval(ptr->lnode);		field_num = (int) force_number(n);		free_temp(n);		if (field_num < 0)			fatal("attempt to access field %d", field_num);		if (field_num == 0 && field0_valid) {	/* short circuit */			aptr = &fields_arr[0];			if (assign)				*assign = reset_record;			break;		}		aptr = get_field(field_num, assign);		break;		}	case Node_subscript:		n = ptr->lnode;		if (n->type == Node_param_list)			n = stack_ptr[n->param_cnt];		aptr = assoc_lookup(n, concat_exp(ptr->rnode));		break;	case Node_func:		fatal ("`%s' is a function, assignment is not allowed",			ptr->lnode->param);	default:		cant_happen();	}	return aptr;}static NODE *match_op(tree)register NODE *tree;{	register NODE *t1;	register Regexp *rp;	int i;	int match = 1;	if (tree->type == Node_nomatch)		match = 0;	if (tree->type == Node_regex)		t1 = *get_field(0, (Func_ptr *) 0);	else {		t1 = force_string(tree_eval(tree->lnode));		tree = tree->rnode;	}	rp = re_update(tree);	i = research(rp, t1->stptr, 0, t1->stlen, 0);	i = (i == -1) ^ (match == 1);	free_temp(t1);	return tmp_number((AWKNUM) i);}voidset_IGNORECASE(){	static int warned = 0;	if ((do_lint || do_unix) && ! warned) {		warned = 1;		warning("IGNORECASE not supported in compatibility mode");	}	IGNORECASE = (force_number(IGNORECASE_node->var_value) != 0.0);	set_FS();}voidset_OFS(){	OFS = force_string(OFS_node->var_value)->stptr;	OFSlen = OFS_node->var_value->stlen;	OFS[OFSlen] = '\0';}voidset_ORS(){	ORS = force_string(ORS_node->var_value)->stptr;	ORSlen = ORS_node->var_value->stlen;	ORS[ORSlen] = '\0';}static NODE **fmt_list = NULL;static int fmt_ok P((NODE *n));static int fmt_index P((NODE *n));static intfmt_ok(n)NODE *n;{	/* to be done later */	return 1;}static intfmt_index(n)NODE *n;{	register int ix = 0;	static int fmt_num = 4;	static int fmt_hiwater = 0;	if (fmt_list == NULL)		emalloc(fmt_list, NODE **, fmt_num*sizeof(*fmt_list), "fmt_index");	(void) force_string(n);	while (ix < fmt_hiwater) {		if (cmp_nodes(fmt_list[ix], n) == 0)			return ix;		ix++;	}	/* not found */	n->stptr[n->stlen] = '\0';	if (!fmt_ok(n))		warning("bad FMT specification");	if (fmt_hiwater >= fmt_num) {		fmt_num *= 2;		emalloc(fmt_list, NODE **, fmt_num, "fmt_index");	}	fmt_list[fmt_hiwater] = dupnode(n);	return fmt_hiwater++;}voidset_OFMT(){	OFMTidx = fmt_index(OFMT_node->var_value);	OFMT = fmt_list[OFMTidx]->stptr;}voidset_CONVFMT(){	CONVFMTidx = fmt_index(CONVFMT_node->var_value);	CONVFMT = fmt_list[CONVFMTidx]->stptr;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -