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

📄 cset.c

📁 早期freebsd实现
💻 C
字号:
/*- * 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[] = "@(#)cset.c	8.1 (Berkeley) 6/6/93";#endif /* not lint */#include "whoami.h"#include "0.h"#include "tree.h"#include "opcode.h"#include "objfmt.h"#include "tree_ty.h"#ifdef PC#include "pc.h"#include <pcc.h>#include "align.h"#endif PC/* * CONSETS causes compile time constant sets to be constructed here. * * COMPSETSZE defines the maximum number of longs to be used in *	constant set construction */#define CONSETS#define COMPSETSZE 10#define BITSPERBYTE 8#define BITSPERLONG 32#define LG2BITSBYTE 3#define MSKBITSBYTE 0x07#define LG2BITSLONG 5#define MSKBITSLONG 0x1f/* *	rummage through a `constant' set (i.e. anything within [ ]'s) tree *	and decide if this is a compile time constant set or a runtime set. *	this information is returned in a structure passed from the caller. *	while rummaging, this also reorders the tree so that all ranges *	preceed all singletons. */boolprecset( r , settype , csetp )	struct tnode	*r;	struct nl	*settype;	struct csetstr	*csetp;{	register struct tnode	*e;	register struct nl	*t;	register struct nl	*exptype;	register struct tnode	*el;	register struct tnode	*pairp;	register struct tnode	*singp;	struct tnode		*ip;	int			lower;	int			upper;	bool			setofint;	csetp -> csettype = NIL;	csetp -> paircnt = 0;	csetp -> singcnt = 0;	csetp -> comptime = TRUE;	setofint = FALSE;	if ( settype != NIL ) {	    if ( settype -> class == SET ) {		    /*		     *	the easy case, we are told the type of the set.		     */		exptype = settype -> type;	    } else {		    /*		     *	we are told the type, but it's not a set		     *	supposedly possible if someone tries		     *	e.g string context [1,2] = 'abc'		     */		error("Constant set involved in non set context");		return csetp -> comptime;	    }	} else {		/*		 * So far we have no indication		 * of what the set type should be.		 * We "look ahead" and try to infer		 * The type of the constant set		 * by evaluating one of its members.		 */	    e = r->cset_node.el_list;	    if (e == NIL) {		    /*		     *	tentative for [], return type of `intset'		     */		settype = lookup( (char *) intset );		if ( settype == NIL ) {		    panic( "empty set" );		}		settype = settype -> type;		if ( settype == NIL ) {		    return csetp -> comptime;		}		if ( isnta( settype , "t" ) ) {		    error("Set default type \"intset\" is not a set");		    return csetp -> comptime;		}		csetp -> csettype = settype;		setran( settype -> type );		if (((set.uprbp + 1) >> LG2BITSLONG) >= COMPSETSZE)			csetp -> comptime = FALSE;		return csetp -> comptime;	    }	    e = e->list_node.list;	    if (e == NIL) {		return csetp -> comptime;	    }	    if (e->tag == T_RANG) {		    e = e->rang.expr1;	    }	    codeoff();	    t = rvalue(e, NLNIL , RREQ );	    codeon();	    if (t == NIL) {		return csetp -> comptime;	    }		/*		 * The type of the set, settype, is		 * deemed to be a set of the base type		 * of t, which we call exptype.  If,		 * however, this would involve a		 * "set of integer", we cop out		 * and use "intset"'s current scoped		 * type instead.		 */	    if (isa(t, "r")) {		    error("Sets may not have 'real' elements");		    return csetp -> comptime;	    }	    if (isnta(t, "bcsi")) {		    error("Set elements must be scalars, not %ss", nameof(t));		    return csetp -> comptime;	    }	    if (isa(t, "i")) {		    settype = lookup((char *) intset);		    if (settype == NIL)			    panic("intset");		    settype = settype->type;		    if (settype == NIL)			    return csetp -> comptime;		    if (isnta(settype, "t")) {			    error("Set default type \"intset\" is not a set");			    return csetp -> comptime;		    }		    exptype = settype->type;			/*			 *	say we are doing an intset			 *	but, if we get out of range errors for intset			 *	we punt constructing the set at	compile time.			 */		    setofint = TRUE;	    } else {			exptype = t->type;			if (exptype == NIL)				return csetp -> comptime;			if (exptype->class != RANGE)				exptype = exptype->type;			settype = defnl((char *) 0, SET, exptype, 0);	    }	}	csetp -> csettype = settype;#	ifndef CONSETS	    csetp -> comptime = FALSE;#	endif CONSETS	setran( exptype );	if (((set.uprbp + 1) >> LG2BITSLONG) >= COMPSETSZE)		csetp -> comptime = FALSE;	lower = set.lwrb;	upper = set.lwrb + set.uprbp;	pairp = NIL;	singp = NIL;	codeoff();	while ( el = r->cset_node.el_list ) {		e = el->list_node.list;		if (e == NIL) {			    /*			     *	don't hang this one anywhere.			     */			csetp -> csettype = NIL;			r->cset_node.el_list = el->list_node.next;			continue;		}		if (e->tag == T_RANG) {			if ( csetp -> comptime && constval( e->rang.expr2 ) ) {#ifdef CONSETS			    t = con.ctype;			    if ( con.crval < lower || con.crval > upper ) {				if ( setofint ) {				    csetp -> comptime = FALSE;				} else {				    error("Range upper bound of %D out of set bounds" , ((long)con.crval) );				    csetp -> csettype = NIL;				}			    }#endif CONSETS			} else {			    csetp -> comptime = FALSE;			    t = rvalue(e->rang.expr2, NLNIL , RREQ );			    if (t == NIL) {				    (void) rvalue(e->rang.expr1, NLNIL , RREQ );				    goto pairhang;			    }			}			if (incompat(t, exptype, e->rang.expr2)) {				cerror("Upper bound of element type clashed with set type in constant set");			}			if ( csetp -> comptime && constval( e->rang.expr1 ) ) {#ifdef CONSETS			    t = con.ctype;			    if ( con.crval < lower || con.crval > upper ) {				if ( setofint ) {				    csetp -> comptime = FALSE;				} else {				    error("Range lower bound of %D out of set bounds" , ((long)con.crval) );				    csetp -> csettype = NIL;				}			    }#endif CONSETS			} else {			    csetp -> comptime = FALSE;			    t = rvalue(e->rang.expr1, NLNIL , RREQ );			    if (t == NIL) {				    goto pairhang;			    }			}			if (incompat(t, exptype, e->rang.expr1)) {				cerror("Lower bound of element type clashed with set type in constant set");			}pairhang:			    /*			     *	remove this range from the tree list and 			     *	hang it on the pairs list.			     */			ip = el->list_node.next;			el->list_node.next = pairp;			pairp = r->cset_node.el_list;			r->cset_node.el_list = ip;			csetp -> paircnt++;		} else {			if ( csetp -> comptime && constval( e ) ) {#ifdef CONSETS			    t = con.ctype;			    if ( con.crval < lower || con.crval > upper ) {				if ( setofint ) {				    csetp -> comptime = FALSE;				} else {				    error("Value of %D out of set bounds" , ((long)con.crval) );				    csetp -> csettype = NIL;				}			    }#endif CONSETS			} else {			    csetp -> comptime = FALSE;			    t = rvalue( e, NLNIL , RREQ );			    if (t == NIL) {				    goto singhang;			    }			}			if (incompat(t, exptype, e)) {				cerror("Element type clashed with set type in constant set");			}singhang:			    /*			     *	take this expression off the tree list and			     *	hang it on the list of singletons.			     */			ip = el->list_node.next;			el->list_node.next = singp;			singp = r->cset_node.el_list;			r->cset_node.el_list = ip;			csetp -> singcnt++;		}	}	codeon();#	ifdef PC	    if ( pairp != NIL ) {		for ( el = pairp ; el->list_node.next != NIL ; el = el->list_node.next ) /* void */;		el->list_node.next = singp;		r->cset_node.el_list = pairp;	    } else {		r->cset_node.el_list = singp;	    }#	endif PC#	ifdef OBJ	    if ( singp != NIL ) {		for ( el = singp ; el->list_node.next != NIL ; el = el->list_node.next ) /* void */;		el->list_node.next = pairp;		r->cset_node.el_list = singp;	    } else {		r->cset_node.el_list = pairp;	    }#	endif OBJ	if ( csetp -> csettype == NIL ) {	    csetp -> comptime = TRUE;	}	return csetp -> comptime;}#ifdef CONSETS    /*     *	mask[i] has the low i bits turned off.     */long	mask[] = {	#		ifdef DEC11		    0xffffffff , 0xfffffffe , 0xfffffffc , 0xfffffff8 ,		    0xfffffff0 , 0xffffffe0 , 0xffffffc0 , 0xffffff80 ,		    0xffffff00 , 0xfffffe00 , 0xfffffc00 , 0xfffff800 ,		    0xfffff000 , 0xffffe000 , 0xffffc000 , 0xffff8000 ,		    0xffff0000 , 0xfffe0000 , 0xfffc0000 , 0xfff80000 ,		    0xfff00000 , 0xffe00000 , 0xffc00000 , 0xff800000 ,		    0xff000000 , 0xfe000000 , 0xfc000000 , 0xf8000000 ,		    0xf0000000 , 0xe0000000 , 0xc0000000 , 0x80000000 ,		    0x00000000#		else		    0xffffffff , 0xfeffffff , 0xfcffffff , 0xf8ffffff ,		    0xf0ffffff , 0xe0ffffff , 0xc0ffffff , 0x80ffffff ,		    0x00ffffff , 0x00feffff , 0x00fcffff , 0x00f8ffff ,		    0x00f0ffff , 0x00e0ffff , 0x00c0ffff , 0x0080ffff ,		    0x0000ffff , 0x0000feff , 0x0000fcff , 0x0000f8ff ,		    0x0000f0ff , 0x0000e0ff , 0x0000c0ff , 0x000080ff ,		    0x000000ff , 0x000000fe , 0x000000fc , 0x000000f8 ,		    0x000000f0 , 0x000000e0 , 0x000000c0 , 0x00000080 ,		    0x00000000#		endif DEC11	    };    /*     *	given a csetstr, either     *	    put out a compile time constant set and an lvalue to it.     *	or     *	    put out rvalues for the singletons and the pairs     *	    and counts of each.     */#endif CONSETSpostcset( r , csetp )    struct tnode	*r;    struct csetstr	*csetp;    {	register struct tnode	*el;	register struct tnode	*e;	int		lower;	int		upper;	int		lowerdiv;	int		lowermod;	int		upperdiv;	int		uppermod;	long		*lp;	long		*limit;	long		tempset[ COMPSETSZE ];	long		temp;	char		*cp;#	ifdef PC	    int		label;	    char	labelname[ BUFSIZ ];#	endif PC	if ( csetp -> comptime ) {#ifdef CONSETS	    setran( ( csetp -> csettype ) -> type );	    limit = &tempset[ ( set.uprbp >> LG2BITSLONG ) + 1 ];	    for ( lp = &tempset[0] ; lp < limit ; lp++ ) {		*lp = 0;	    }	    for ( el = r->cset_node.el_list ; el != NIL ; el = el->list_node.next ) {		e = el->list_node.list;		if ( e->tag == T_RANG ) {		    (void) constval( e->rang.expr1 );		    lower = con.crval;		    (void) constval( e->rang.expr2 );		    upper = con.crval;		    if ( upper < lower ) {			continue;		    }		    lowerdiv = ( lower - set.lwrb ) >> LG2BITSLONG;		    lowermod = ( lower - set.lwrb ) & MSKBITSLONG;		    upperdiv = ( upper - set.lwrb ) >> LG2BITSLONG;		    uppermod = ( upper - set.lwrb ) & MSKBITSLONG;		    temp = mask[ lowermod ];		    if ( lowerdiv == upperdiv ) {			temp &= ~mask[ uppermod + 1 ];		    }		    tempset[ lowerdiv ] |= temp;		    limit = &tempset[ upperdiv-1 ];		    for ( lp = &tempset[ lowerdiv+1 ] ; lp <= limit ; lp++ ) {			*lp |= 0xffffffff;		    }		    if ( lowerdiv != upperdiv ) {			tempset[ upperdiv ] |= ~mask[ uppermod + 1 ];		    }		} else {		    (void) constval( e );		    temp = con.crval - set.lwrb;		    cp = (char *)tempset;		    cp[temp >> LG2BITSBYTE] |= (1 << (temp & MSKBITSBYTE));		}	    }	    if ( !CGENNING )		return;#	    ifdef PC		label = (int) getlab();		putprintf("	.data" , 0 );		aligndot(A_SET);		(void) putlab( (char *) label );		lp = &( tempset[0] );		limit = &tempset[ ( set.uprbp >> LG2BITSLONG ) + 1 ];		while (lp < limit) {		    putprintf("	.long	0x%x", 1, (int) (*lp++));		    for (temp = 2 ; temp <= 8 && lp < limit ; temp++) {			putprintf(",0x%x", 1, (int) (*lp++));		    }		    putprintf("", 0);		}		putprintf("	.text", 0);		sprintf( labelname , PREFIXFORMAT , LABELPREFIX , (char *) label );		putleaf( PCC_ICON , 0 , 0 , PCCTM_PTR | PCCT_STRTY , labelname );#	    endif PC#	    ifdef OBJ		(void) put(2, O_CON, (int)(((set.uprbp >> LG2BITSLONG) + 1) *				 (BITSPERLONG >> LG2BITSBYTE)));		lp = &( tempset[0] );		limit = &tempset[ ( set.uprbp >> LG2BITSLONG ) + 1 ];		while ( lp < limit ) {		    (void) put(2, O_CASE4, (int) (*lp ++));		}#	    endif OBJ#else		panic("const cset");#endif CONSETS	} else {#	    ifdef PC		putleaf( PCC_ICON , (int) csetp -> paircnt , 0 , PCCT_INT , (char *) 0 );		putop( PCC_CM , PCCT_INT );		putleaf( PCC_ICON , (int) csetp -> singcnt , 0 , PCCT_INT , (char *) 0 );		putop( PCC_CM , PCCT_INT );		for ( el = r->cset_node.el_list ; el != NIL ; el = el->list_node.next ) {		    e = el->list_node.list;		    if ( e->tag == T_RANG ) {			(void) rvalue( e->rang.expr2 , NLNIL , RREQ );			putop( PCC_CM , PCCT_INT );			(void) rvalue( e->rang.expr1 , NLNIL , RREQ );			putop( PCC_CM , PCCT_INT );		    } else {			(void) rvalue( e , NLNIL , RREQ );			putop( PCC_CM , PCCT_INT );		    }		}#	    endif PC#	    ifdef OBJ		for ( el = r->cset_node.el_list ; el != NIL ; el = el->list_node.next ) {		    e = el->list_node.list;		    if ( e->tag == T_RANG ) {			(void) stkrval( e->rang.expr1 , NLNIL , (long) RREQ );			(void) stkrval( e->rang.expr2 , NLNIL , (long) RREQ );		    } else {			(void) stkrval( e , NLNIL , (long) RREQ );		    }		}		(void) put(2 , O_CON24 , (int)csetp -> singcnt );		(void) put(2 , O_CON24 , (int)csetp -> paircnt );#	    endif OBJ	}}

⌨️ 快捷键说明

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