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

📄 expr.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
		result =
		    memcmp ((const void *) s, (const void *) (p->sptr + diff),
			    (size_t) len);
		if (result == 0) {
		    EXPR   *ep = mk_lcon (p->label);

		    if (diff) {
			ep =
			    mk_node (en_add, ep,
				     mk_icon ((IVAL) diff, tp_pointer),
				     tp_pointer);
		    }
		    return ep;
		}
	    }
	    q = p;
	}
    }
    /*
     *      If we reach this point, either the string does not exist
     *      or we are operating in 'traditional' mode.       We must therefore
     *      create a new string.   The actual string text is allocated
     *      in local space if in traditional mode, and global otherwise
     *      (so we can check for strings already generated).
     */
    global_flag = 0;		/* always allocate from local space. */
    lp = (STRING *) xalloc (sizeof (STRING));

    lp->label = nextlabel++;
    global_flag = lang_option >= LANG_C90;
    lp->str = s;
    lp->len = len;
    lp->next = strtab;
    strtab = lp;
    if (lang_option >= LANG_C90) {
	/*
	 *      traditional mode not set, so create a new entry for
	 *      our tree of already generated strings.
	 */
	p = (STREE *) xalloc (sizeof (STREE));
	p->label = lp->label;
	p->sptr = lp->str;
	p->len = lp->len;
	p->less = p->more = NIL_STREE;
	if (q == NIL_STREE) {
	    strtree = p;
	} else if (result < 0) {
	    q->less = p;
	} else {
	    q->more = p;
	}
    }
    global_flag = local_global;
    return mk_lcon (lp->label);
}


/*
 * generates the cast node if required for an integral promotion
 */
static EXPR *integral_promotion P1 (EXPR *, ep)
{
    TYP    *tp = unary_conversion (ep->etp);

    if (tp != ep->etp) {
	return implicit_castop (ep, tp);
    }
    return ep;
}

static EXPR *mk_enode P2 (EXPRTYPE, nt, TYP *, tp)
{
    EXPR   *ep = (EXPR *) xalloc (sizeof (EXPR));

    ep->nodetype = nt;
    ep->etp = tp;
    return ep;
}

EXPR   *copynode P1 (const EXPR *, ep)
{
    EXPR   *temp;

    if (ep == NIL_EXPR) {
	return NIL_EXPR;
    }
    temp = (EXPR *) xalloc (sizeof (EXPR));

    *temp = *ep;
    return temp;
}

/*
 * build an expression node with a node type of nt and values v1 and v2.
 */
EXPR   *mk_node P4 (EXPRTYPE, nt, EXPR *, v1, EXPR *, v2, TYP *, tp)
{
    EXPR   *ep = mk_enode (nt, tp);

#ifndef FLOAT_SUPPORT
    switch (tp->type) {
    case bt_float:
    case bt_double:
    case bt_longdouble:
    case bt_floatcomplex:
    case bt_doublecomplex:
    case bt_longdoublecomplex:
	message (ERR_NOFLOATSUPPORT);
	break;
    default:
	break;
    }
    
#endif	/* FLOAT_SUPPORT */
#ifndef LONGLONG_SUPPORT
    switch (tp->type) {
    case bt_longlong:
    case bt_ulonglong:
	message (ERR_NOLONGLONGSUPPORT);
	break;
    default:
	break;
    }
    
#endif	/* LONGLONG_SUPPORT */
    ep->v.p[0] = v1;
    ep->v.p[1] = v2;
    return ep;
}

/*
 * build an expression node forming an integer constant
 */
EXPR   *mk_icon P2 (IVAL, i, TYP *, tp)
{
    EXPR   *ep = mk_enode (en_icon, tp);

    ep->v.i = i;
    return ep;
}

/*
 * build an expression node forming an size constant
 */ 
static EXPR *mk_size P2 (SIZE, size, TYP *, tp) 
{
    EXPR  *ep = mk_enode (en_icon, tp);

    ep->v.i = (IVAL) size;
    
    return ep;
}



/*
 * build an expression node forming a string constant
 */
EXPR   *mk_scon P2 (const CHAR *, str, TYP *, tp)
{
    EXPR   *ep = mk_enode (en_str, tp);

    ep->v.str = str;
    return ep;
}

#ifdef FLOAT_SUPPORT
/*
 * build an expression node forming a floating point constant
 */
#ifndef TMS320C30
static
#endif				/* TMS320C30 */
EXPR   *mk_fcon P2 (const RVAL *, fp, TYP *, tp)
{
    EXPR   *ep = mk_enode (en_fcon, tp);

    FASSIGN (ep->v.f, *fp);
    return ep;
}
#endif

/*
 * build an expression node forming a label
 */
EXPR   *mk_lcon P1 (LABEL, lab)
{
    EXPR   *ep = mk_enode (en_labcon, tp_pointer);

    ep->v.l = lab;
    return ep;
}

EXPR   *mk_ref P2 (EXPR *, ep, TYP *, tp)
{
    return mk_node (en_ref, ep, NIL_EXPR, tp);
}

EXPR   *mk_symnode P1 (SYM *, sp)
{
    EXPR   *ep = mk_enode (en_sym, typeof (sp));

    ep->v.sp = sp;
    return ep;
}

EXPR   *mk_autocon P1 (SIZE, offset)
{
    EXPR   *ep = mk_node (en_autocon, NIL_EXPR, NIL_EXPR, tp_pointer);

    ep->v.i = (IVAL) offset;
    return ep;
}

EXPR   *mk_litval P2 (EXPR *, ep1, SIZE, offset)
{
    EXPR   *ep =

	mk_node (en_litval, ep1, mk_size (offset, tp_size), ep1->etp);

    return ep;
}

/*
 * build the proper dereference operation for a node using the type pointer
 * tp.
 */
static EXPR *deref P2 (EXPR *, ep, TYP *, tp)
{
    switch (tp->type) {
    case bt_func:		/* ANSI - functions automatically dereferenced */
#ifndef SYNTAX_CORRECT
	if (lang_option == LANG_KANDR) {
	    message (ERR_DEREF);
	}
	/*lint -fallthrough */
#endif /* SYNTAX_CORRECT */
    case bt_bool:
    case bt_char:
    case bt_charu:
    case bt_uchar:
    case bt_schar:
    case bt_short:
    case bt_ushort:
    case bt_int16:
    case bt_uint16:
    case bt_pointer16:
    case bt_int32:
    case bt_uint32:
    case bt_long:
    case bt_pointer32:
    case bt_ulong:
    case bt_longlong:
    case bt_ulonglong:
    case bt_struct:
    case bt_union:
    case bt_float:
    case bt_double:
    case bt_longdouble:
    case bt_floatcomplex:
    case bt_doublecomplex:
    case bt_longdoublecomplex:
    case bt_floatimaginary:
    case bt_doubleimaginary:
    case bt_longdoubleimaginary:
	ep = mk_ref (ep, tp);
	break;
    case bt_ubitfield:
	ep = mk_node (en_fieldref, ep, NIL_EXPR, tp_uint);
	ep->v.bit.width = bitfield_width (tp);
	ep->v.bit.offset = bitfield_offset (tp);
	break;
    case bt_bitfield:
	ep = mk_node (en_fieldref, ep, NIL_EXPR, tp_int);
	ep->v.bit.width = bitfield_width (tp);
	ep->v.bit.offset = bitfield_offset (tp);
	break;
    case bt_bbitfield:
	ep = mk_node (en_fieldref, ep, NIL_EXPR, tp_bool);
	ep->v.bit.width = bitfield_width (tp);
	ep->v.bit.offset = bitfield_offset (tp);
	break;
    case bt_void:
	if (is_qualified_type (tp)) {
	    ep = mk_ref (ep, tp);
	    break;
	}
	/*lint -fallthrough */
    default:
#ifndef SYNTAX_CORRECT
	message (ERR_DEREF);
#endif /* SYNTAX_CORRECT */
	break;
    }
    return ep;
}

/*
 * dereference the node if state is not STATE_DERIVED
 * If state is STATE_DERIVED and tp is a bt_pointer (array reference)
 *	   set the size field to the pointer size
 */
static EXPR *cond_deref P2 (EXPR *, ep, TYP *, tp)
{
    if (is_derived_type (tp)) {
	/*
	 * Here, the information on array sizes is lost.
	 */
	if (is_pointer_type (tp)) {
	    if (sizeof_flag) {
		ep->nodetype = en_size;
		ep->v.i = (IVAL) tp->size;
	    }
	    tp = mk_type (tp_array, referenced_type (tp));
	    tp->size = tp_pointer->size;
	    set_derived (tp);
	} else if (is_function_type (tp)) {
	    tp = mk_type (tp_pointer, tp);
	    set_derived (tp);
	}
	ep->etp = tp;
    } else {
	ep = deref (ep, tp);
    }
    return ep;
}


/*
 *	 nameref() will build an expression tree that references an identifier.
 *
 *	 Non-value references generate an additional level of indirection.
 */
static EXPR *nameref P0 (void)
{
    EXPR   *ep;
    SYM    *sp;
    TYP    *tp;

    sp = identifier ();
    tp = typeof (sp);
    symbol_used (sp);
    switch (storageof (sp)) {
    case sc_register:
#ifndef SYNTAX_CORRECT
	if (address_flag) {
	    if (is_array_type (tp) || is_structure_type (tp)) {
		message (ERR_ADDREGVAR, nameof (sp));
	    }
	} else if (!sizeof_flag && is_array_type (tp)) {
	    message (ERR_IMPLICITADDR, nameof (sp));
	}
	/*lint -fallthrough */
#endif /* SYNTAX_CORRECT */
    case sc_static:
    case sc_global:
    case sc_external:
    case sc_auto:
    case sc_parms:
	if (address_flag || is_array_type (tp) || is_structure_type (tp)) {
	    symbol_set (sp);
	}
	ep = mk_symnode (sp);
	break;
    case sc_const:
	ep = mk_icon (sp->value.i, tp);
	break;
    default:
#ifndef SYNTAX_CORRECT
	message (ERR_ILLCLASS);
	ep = mk_autocon ((SIZE) sp->value.i);
#endif /* SYNTAX_CORRECT */
	break;
    }
    address_flag = FALSE;
    return cond_deref (ep, tp);
}


#ifdef FORMAT_CHECK
#ifndef SYNTAX_CORRECT
static void check_parameter P4 (const CHAR *, fname, int, num, const TYP *,
				tp1, const TYP *, tp2)
{
    if (tp1 == NIL_TYP) {
	message (WARN_COUNTPARAM, fname);
    } else if (!is_same_type (tp1, tp2)) {
	message (WARN_FORMAT, num, fname);
    }
}

static void check_pointer_parameter P4 (const CHAR *, fname, int, num,
					const TYP *, tp1, const TYP *, tp2)
{
    if (tp1 == NIL_TYP) {
	message (WARN_COUNTPARAM, fname);
    } else if (!is_pointer_type (tp1)
	       || !is_same_type (referenced_type (tp1), tp2)) {
	message (WARN_FORMAT, num, fname);
    }
}

static void check_array_parameter P3 (const CHAR *, fname, int, num,
				      const TYP *, tp1)
{
    if (tp1 == NIL_TYP) {
	message (WARN_COUNTPARAM, fname);
    } else if (!is_pointer_type (tp1)) {
	message (WARN_FORMAT, num, fname);
    } else {
	switch (referenced_type (tp1)->type) {
	case bt_char:
	case bt_uchar:
	case bt_schar:
	case bt_charu:
	    break;
	default:
	    message (WARN_FORMAT, num, fname);
	    break;
	}
    }
}

static const CHAR *check_printf P5 (const CHAR *, fname, int, num,
				    const CHAR *, fstr, enum fpos *, pos,
				    const TYP *, ptp)
{
    CHAR    optional;
    TYP    *tp;

    if (fstr == NIL_CHAR || *fstr == (CHAR) 0) {
	if (ptp != NIL_TYP) {
	    message (WARN_COUNTPARAM, fname);
	}
	return NIL_CHAR;
    }
    switch (*pos) {
    case format_start:
	for (; *fstr; fstr++) {
	    if (*fstr == (CHAR) '%') {
		fstr++;
		switch (*fstr) {
		case '%':
		    continue;
		case '\0':
		    message (WARN_FORMATEND, fname);
		    return NIL_CHAR;
		default:
		    break;
		}
		break;
	    }
	}

	/* flags */
	for (optional = (CHAR) 1; optional && *fstr;) {
	    switch (*fstr) {
	    case '-':
	    case '+':
	    case ' ':
	    case '#':
	    case '0':
		fstr++;
		break;
	    default:
		optional = (CHAR) 0;
		break;
	    }
	}

	/* field width */
	for (; *fstr; fstr++) {
	    if (*fstr == (CHAR) '*') {
		*pos = format_precision;
		check_parameter (fname, num, ptp, tp_int);
		return fstr + 1;
	    }
	    if ((*fstr < '0') || (*fstr > '9')) {
		break;
	    }
	}
	/*lint -fallthrough */
    case format_precision:
	/* precision */
	if (*fstr == (CHAR) '.') {
	    for (fstr++; *fstr; fstr++) {
		if (*fstr == (CHAR) '*') {
		    *pos = format_optional;
		    check_parameter (fname, num, ptp, tp_int);
		    return fstr + 1;
		}
		if ((*fstr < '0') || (*fstr > '9')) {
		    break;
		}
	    }
	}
	/*lint -fallthrough */
    case format_optional:
	/* optional */
	*pos = format_start;
	switch (*fstr) {
	case 'h':
	case 'l':
	case 'L':
	    optional = *fstr++;
	    break;
	case 'j':
	case 'z':
	case 't':
	    if (lang_option >= LANG_C99) {
		optional = *fstr++;
		break;
	    }
	    /*lint -fallthrough*/
	default:
	    optional = (CHAR) 0;
	    break;
	}

	/* type */
	switch (*fstr) {
	case 'c':
	case 'd':
	case 'i':
	    switch (optional) {
	    case 'l':
		tp = tp_long;
		break;
	    case 'h':
		tp = tp_short;
		break;
	    case 'j':
		tp = tp_int;
		break;
	    case 't':
		tp = tp_ptrdiff;
		break;
	    case 'z':
		tp = tp_size;
		break;
	    default:
		tp = tp_int;
		break;
	    }
	    check_parameter (fname, num, ptp, promote_type (tp));
	    return fstr + 1;
	case 'o':
	case 'u':
	case 'x':
	case 'X':
	    switch (optional) {
	    case 'l':
		tp = tp_ulong;
		break;
	    case 'h':
		tp = tp_ushort;
		break;

⌨️ 快捷键说明

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