📄 expr.c
字号:
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 + -