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

📄 proc.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 1980, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)proc.c	8.1 (Berkeley) 6/6/93";#endif /* not lint */#include "whoami.h"#ifdef OBJ    /*     *	and the rest of the file     */#include "0.h"#include "tree.h"#include "opcode.h"#include "objfmt.h"#include "tmps.h"#include "tree_ty.h"/* * The constant EXPOSIZE specifies the number of digits in the exponent * of real numbers. * * The constant REALSPC defines the amount of forced padding preceeding * real numbers when they are printed. If REALSPC == 0, then no padding * is added, REALSPC == 1 adds one extra blank irregardless of the width * specified by the user. * * N.B. - Values greater than one require program mods. */#define EXPOSIZE	2#define	REALSPC		0/* * The following array is used to determine which classes may be read * from textfiles. It is indexed by the return value from classify. */#define rdops(x) rdxxxx[(x)-(TFIRST)]int rdxxxx[] = {	0,		/* -7 file types */	0,		/* -6 record types */	0,		/* -5 array types */	O_READE,	/* -4 scalar types */	0,		/* -3 pointer types */	0,		/* -2 set types */	0,		/* -1 string types */	0,		/*  0 nil, no type */	O_READE,	/*  1 boolean */	O_READC,	/*  2 character */	O_READ4,	/*  3 integer */	O_READ8		/*  4 real */};/* * Proc handles procedure calls. * Non-builtin procedures are "buck-passed" to func (with a flag * indicating that they are actually procedures. * builtin procedures are handled here. */proc(r)	struct tnode *r;{	register struct nl *p;	register struct tnode *alv, *al; 	register int op;	struct nl *filetype, *ap, *al1;	int argc, typ, fmtspec, strfmt, stkcnt;	struct tnode *argv; 	char fmt, format[20], *strptr, *pu;	int prec, field, strnglen, fmtlen, fmtstart;	struct tnode *pua, *pui, *puz, *file;	int i, j, k;	int itemwidth;	struct tmps soffset;	struct nl	*tempnlp;#define	CONPREC 4#define	VARPREC 8#define	CONWIDTH 1#define	VARWIDTH 2#define SKIP 16	/*	 * Verify that the name is	 * defined and is that of a	 * procedure.	 */	p = lookup(r->pcall_node.proc_id);	if (p == NIL) {		rvlist(r->pcall_node.arg);		return;	}	if (p->class != PROC && p->class != FPROC) {		error("Can't call %s, its %s not a procedure", p->symbol, classes[p->class]);		rvlist(r->pcall_node.arg);		return;	}	argv = r->pcall_node.arg;	/*	 * Call handles user defined	 * procedures and functions.	 */	if (bn != 0) {		(void) call(p, argv, PROC, bn);		return;	}	/*	 * Call to built-in procedure.	 * Count the arguments.	 */	argc = 0;	for (al = argv; al != TR_NIL; al = al->list_node.next)		argc++;	/*	 * Switch on the operator	 * associated with the built-in	 * procedure in the namelist	 */	op = p->value[0] &~ NSTAND;	if (opt('s') && (p->value[0] & NSTAND)) {		standard();		error("%s is a nonstandard procedure", p->symbol);	}	switch (op) {	case O_ABORT:		if (argc != 0)			error("null takes no arguments");		return;	case O_FLUSH:		if (argc == 0) {			(void) put(1, O_MESSAGE);			return;		}		if (argc != 1) {			error("flush takes at most one argument");			return;		}		ap = stklval(argv->list_node.list, NIL );		if (ap == NLNIL)			return;		if (ap->class != FILET) {			error("flush's argument must be a file, not %s", nameof(ap));			return;		}		(void) put(1, op);		return;	case O_MESSAGE:	case O_WRITEF:	case O_WRITLN:		/*		 * Set up default file "output"'s type		 */		file = NIL;		filetype = nl+T1CHAR;		/*		 * Determine the file implied		 * for the write and generate		 * code to make it the active file.		 */		if (op == O_MESSAGE) {			/*			 * For message, all that matters			 * is that the filetype is			 * a character file.			 * Thus "output" will suit us fine.			 */			(void) put(1, O_MESSAGE);		} else if (argv != TR_NIL && (al = argv->list_node.list)->tag !=					T_WEXP) {			/*			 * If there is a first argument which has			 * no write widths, then it is potentially			 * a file name.			 */			codeoff();			ap = stkrval(argv->list_node.list, NLNIL, (long) RREQ );			codeon();			if (ap == NLNIL)				argv = argv->list_node.next;			if (ap != NLNIL && ap->class == FILET) {				/*				 * Got "write(f, ...", make				 * f the active file, and save				 * it and its type for use in				 * processing the rest of the				 * arguments to write.				 */				file = argv->list_node.list;				filetype = ap->type;				(void) stklval(argv->list_node.list, NIL );				(void) put(1, O_UNIT);				/*				 * Skip over the first argument				 */				argv = argv->list_node.next;				argc--;			} else {				/*				 * Set up for writing on 				 * standard output.				 */				(void) put(1, O_UNITOUT);				output->nl_flags |= NUSED;			}		} else {			(void) put(1, O_UNITOUT);			output->nl_flags |= NUSED;		}		/*		 * Loop and process each		 * of the arguments.		 */		for (; argv != TR_NIL; argv = argv->list_node.next) {			/*			 * fmtspec indicates the type (CONstant or VARiable)			 *	and number (none, WIDTH, and/or PRECision)			 *	of the fields in the printf format for this			 *	output variable.			 * stkcnt is the number of bytes pushed on the stack			 * fmt is the format output indicator (D, E, F, O, X, S)			 * fmtstart = 0 for leading blank; = 1 for no blank			 */			fmtspec = NIL;			stkcnt = 0;			fmt = 'D';			fmtstart = 1;			al = argv->list_node.list;			if (al == TR_NIL)				continue;			if (al->tag == T_WEXP)				alv = al->wexpr_node.expr1;			else				alv = al;			if (alv == TR_NIL)				continue;			codeoff();			ap = stkrval(alv, NLNIL , (long) RREQ );			codeon();			if (ap == NLNIL)				continue;			typ = classify(ap);			if (al->tag == T_WEXP) {				/*				 * Handle width expressions.				 * The basic game here is that width				 * expressions get evaluated. If they				 * are constant, the value is placed				 * directly in the format string.				 * Otherwise the value is pushed onto				 * the stack and an indirection is				 * put into the format string.				 */				if (al->wexpr_node.expr3 == 						(struct tnode *) OCT)					fmt = 'O';				else if (al->wexpr_node.expr3 == 						(struct tnode *) HEX)					fmt = 'X';				else if (al->wexpr_node.expr3 != TR_NIL) {					/*					 * Evaluate second format spec					 */					if ( constval(al->wexpr_node.expr3)					    && isa( con.ctype , "i" ) ) {						fmtspec += CONPREC;						prec = con.crval;					} else {						fmtspec += VARPREC;					}					fmt = 'f';					switch ( typ ) {					case TINT:						if ( opt( 's' ) ) {						    standard();						    error("Writing %ss with two write widths is non-standard", clnames[typ]);						}						/* and fall through */					case TDOUBLE:						break;					default:						error("Cannot write %ss with two write widths", clnames[typ]);						continue;					}				}				/*				 * Evaluate first format spec				 */				if (al->wexpr_node.expr2 != TR_NIL) {					if ( constval(al->wexpr_node.expr2)					    && isa( con.ctype , "i" ) ) {						fmtspec += CONWIDTH;						field = con.crval;					} else {						fmtspec += VARWIDTH;					}				}				if ((fmtspec & CONPREC) && prec < 0 ||				    (fmtspec & CONWIDTH) && field < 0) {					error("Negative widths are not allowed");					continue;				}				if ( opt('s') &&				    ((fmtspec & CONPREC) && prec == 0 ||				    (fmtspec & CONWIDTH) && field == 0)) {					standard();					error("Zero widths are non-standard");				}			}			if (filetype != nl+T1CHAR) {				if (fmt == 'O' || fmt == 'X') {					error("Oct/hex allowed only on text files");					continue;				}				if (fmtspec) {					error("Write widths allowed only on text files");					continue;				}				/*				 * Generalized write, i.e.				 * to a non-textfile.				 */				(void) stklval(file, NIL );				(void) put(1, O_FNIL);				/*				 * file^ := ...				 */				ap = rvalue(argv->list_node.list, NLNIL, LREQ);				if (ap == NLNIL)					continue;				if (incompat(ap, filetype,						argv->list_node.list)) {					cerror("Type mismatch in write to non-text file");					continue;				}				convert(ap, filetype);				(void) put(2, O_AS, width(filetype));				/*				 * put(file)				 */				(void) put(1, O_PUT);				continue;			}			/*			 * Write to a textfile			 *			 * Evaluate the expression			 * to be written.			 */			if (fmt == 'O' || fmt == 'X') {				if (opt('s')) {					standard();					error("Oct and hex are non-standard");				}				if (typ == TSTR || typ == TDOUBLE) {					error("Can't write %ss with oct/hex", clnames[typ]);					continue;				}				if (typ == TCHAR || typ == TBOOL)					typ = TINT;			}			/*			 * Place the arguement on the stack. If there is			 * no format specified by the programmer, implement			 * the default.			 */			switch (typ) {			case TPTR:				warning();				if (opt('s')) {					standard();				}				error("Writing %ss to text files is non-standard",				    clnames[typ]);				/* and fall through */			case TINT:				if (fmt != 'f') {					ap = stkrval(alv, NLNIL, (long) RREQ );					stkcnt += sizeof(long);				} else {					ap = stkrval(alv, NLNIL, (long) RREQ );					(void) put(1, O_ITOD);					stkcnt += sizeof(double);					typ = TDOUBLE;					goto tdouble;				}				if (fmtspec == NIL) {					if (fmt == 'D')						field = 10;					else if (fmt == 'X')						field = 8;					else if (fmt == 'O')						field = 11;					else						panic("fmt1");					fmtspec = CONWIDTH;				}				break;			case TCHAR:			     tchar:				if (fmtspec == NIL) {					(void) put(1, O_FILE);					ap = stkrval(alv, NLNIL, (long) RREQ );					convert(nl + T4INT, INT_TYP);					(void) put(2, O_WRITEC,						sizeof(char *) + sizeof(int));					fmtspec = SKIP;					break;				}				ap = stkrval(alv, NLNIL , (long) RREQ );				convert(nl + T4INT, INT_TYP);				stkcnt += sizeof(int);				fmt = 'c';				break;			case TSCAL:				warning();				if (opt('s')) {					standard();				}				error("Writing %ss to text files is non-standard",				    clnames[typ]);				/* and fall through */			case TBOOL:				(void) stkrval(alv, NLNIL , (long) RREQ );				(void) put(2, O_NAM, (long)listnames(ap));				stkcnt += sizeof(char *);				fmt = 's';				break;			case TDOUBLE:				ap = stkrval(alv, (struct nl *) TDOUBLE , (long) RREQ );				stkcnt += sizeof(double);			     tdouble:				switch (fmtspec) {				case NIL:					field = 14 + (5 + EXPOSIZE);				        prec = field - (5 + EXPOSIZE);					fmt = 'e';					fmtspec = CONWIDTH + CONPREC;					break;				case CONWIDTH:					field -= REALSPC;					if (field < 1)						field = 1;				        prec = field - (5 + EXPOSIZE);					if (prec < 1)						prec = 1;					fmtspec += CONPREC;					fmt = 'e';					break;				case CONWIDTH + CONPREC:				case CONWIDTH + VARPREC:					field -= REALSPC;					if (field < 1)						field = 1;				}				format[0] = ' ';				fmtstart = 1 - REALSPC;				break;			case TSTR:				(void) constval( alv );				switch ( classify( con.ctype ) ) {				    case TCHAR:					typ = TCHAR;					goto tchar;				    case TSTR:					strptr = con.cpval;					for (strnglen = 0;  *strptr++;  strnglen++) /* void */;					strptr = con.cpval;					break;				    default:					strnglen = width(ap);					break;				}				fmt = 's';				strfmt = fmtspec;				if (fmtspec == NIL) {					fmtspec = SKIP;					break;				}				if (fmtspec & CONWIDTH) {					if (field <= strnglen) {						fmtspec = SKIP;						break;					} else						field -= strnglen;				}				/*				 * push string to implement leading blank padding				 */				(void) put(2, O_LVCON, 2);				putstr("", 0);				stkcnt += sizeof(char *);				break;			default:				error("Can't write %ss to a text file", clnames[typ]);				continue;			}			/*			 * If there is a variable precision, evaluate it onto			 * the stack			 */			if (fmtspec & VARPREC) {				ap = stkrval(al->wexpr_node.expr3, NLNIL ,						(long) RREQ );				if (ap == NIL)					continue;				if (isnta(ap,"i")) {					error("Second write width must be integer, not %s", nameof(ap));					continue;				}				if ( opt( 't' ) ) {				    (void) put(3, O_MAX, 0, 0);				}				convert(nl+T4INT, INT_TYP);				stkcnt += sizeof(int);			}			/*			 * If there is a variable width, evaluate it onto			 * the stack			 */			if (fmtspec & VARWIDTH) {				if ( ( typ == TDOUBLE && fmtspec == VARWIDTH )				    || typ == TSTR ) {					soffset = sizes[cbn].curtmps;					tempnlp = tmpalloc((long) (sizeof(long)),						nl+T4INT, REGOK);					(void) put(2, O_LV | cbn << 8 + INDX, 					    tempnlp -> value[ NL_OFFS ] );				}				ap = stkrval(al->wexpr_node.expr2, NLNIL, (long) RREQ );				if (ap == NIL)					continue;				if (isnta(ap,"i")) {					error("First write width must be integer, not %s", nameof(ap));					continue;				}				/*				 * Perform special processing on widths based				 * on data type 				 */				switch (typ) {				case TDOUBLE:					if (fmtspec == VARWIDTH) {						fmt = 'e';						(void) put(1, O_AS4);						(void) put(2, O_RV4 | cbn << 8 + INDX,						    tempnlp -> value[NL_OFFS] );					        (void) put(3, O_MAX,						    5 + EXPOSIZE + REALSPC, 1);						convert(nl+T4INT, INT_TYP);						stkcnt += sizeof(int);						(void) put(2, O_RV4 | cbn << 8 + INDX, 						    tempnlp->value[NL_OFFS] );						fmtspec += VARPREC;						tmpfree(&soffset);					}					(void) put(3, O_MAX, REALSPC, 1);					break;				case TSTR:					(void) put(1, O_AS4);					(void) put(2, O_RV4 | cbn << 8 + INDX, 					    tempnlp -> value[ NL_OFFS ] );					(void) put(3, O_MAX, strnglen, 0);					break;				default:					if ( opt( 't' ) ) {					    (void) put(3, O_MAX, 0, 0);					}					break;

⌨️ 快捷键说明

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