ack/lang/cem/cemcom.ansi/expr.str
George Koehler 15950f9c95 Add long long literals like 123LL to ACK C.
For now, a long long literal must have the 'LL' or 'll' suffix.  A
literal without 'LL' or 'll' acts as before: it may become unsigned
long but not long long.  (For targets where int and long have the same
size, some literals change from unsigned int to unsigned long.)

Type `arith` may be too narrow for long long values.  Add a second
type `writh` for wide arithmetic, and change some variables from arith
to writh.  This may cause bugs if I forget to use writh, or if a
conversion from writh to arith overflows.  I mark some conversions
with (arith) or (writh) casts.

 - BigPars, SmallPars: Remove SPECIAL_ARITHMETICS.  This feature
   would change arith to a different type, but can't work, because it
   would conflict with definitions of arith in both <em_arith.h> and
   <flt_arith.h>.
 - LLlex.c: Understand 'LL' or 'll' suffix.  Cut size of constant when
   it overflows writh, not only when it overflows the target machine's
   types.  (This cut might not be necessary, because we might cut it
   again later.)  When picking signed long or unsigned long, check the
   target's long type, not the compiler's arith type; the old check
   for `val >= 0` was broken where sizeof(arith) > 4.
 - LLlex.h: Change struct token's tok_ival to writh, so it can hold a
   long long literal.
 - arith.c: Adjust to VL_VALUE being writh.  Don't convert between
   float and integer at compile-time if the integer might be too wide
   for <flt_arith.h>.  Add writh2str(), because writh might be too
   wide for long2str().
 - arith.h: Remove SPECIAL_ARITHMETICS.  Declare full_mask[] here,
   not in several *.c files.  Declare writh2str().
 - ch3.c, ch3bin.c, ch3mon.c, declarator.c, statement.g: Remove
   obsolete casts.  Adjust to VL_VALUE being writh.
 - conversion.c, stab.c: Don't declare full_mask[].
 - cstoper.c: Use writh for constant operations on VL_VALUE, and for
   full_mask[].
 - declar., field.c, ival.g: Add casts.
 - dumpidf.c: Need to #include "parameters.h" before checking DEBUG.
   Use writh2str, because "%ld" might not work.
 - eval.c, eval.h: Add casts.  Use writh when writing a wide constant
   in EM.
 - expr.c: Add and remove casts.  In fill_int_expr(), make expression
   from long long literal.  In chk_cst_expr(), allow long long as
   constant expression, so the compiler may accept `case 123LL:` in a
   switch statement.
 - expr.str: Change struct value's vl_value and struct expr's VL_VALUE
   to writh, so an expression may have a long long value at compile
   time.
 - statement.g: Remove obsolete casts.
 - switch.c, switch.str: Use writh in case entries for switch
   statements, so `switch (ll) {...}` with long long ll works.
 - tokenname.c: Add ULNGLNG so LLlex.c can use it for literals.
2019-09-04 22:14:38 -04:00

125 lines
3.9 KiB
Plaintext

/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* $Id$ */
/* EXPRESSION DESCRIPTOR */
#ifndef EXPR_H_
#define EXPR_H_
#include "parameters.h"
#include "arith.h"
#include "label.h"
#include "flt_arith.h"
/* What we want to define is the struct expr, but since it contains
a union of various goodies, we define them first; so be patient.
*/
/* classes of value */
#define Const 1
#define Name 2
#define Label 3
struct value {
int vl_class; /* Const, Name or Label */
writh vl_value; /* constant value or offset */
union {
struct idf *vl_idf; /* external name */
label vl_lbl; /* compiler-generated label */
} vl_data;
};
struct string {
char *sg_value; /* row of bytes repr. the constant */
int sg_len; /* length of the row */
};
struct oper {
struct type *op_type; /* resulting type of the operation */
struct expr *op_left;
int op_oper; /* the symbol of the operator */
struct expr *op_right;
};
/* The following constants indicate the class of the expression: */
#define Value 0 /* it is a value known at load time */
#define String 1 /* it is a string constant */
#define Float 2 /* it is a floating point constant */
#define Oper 3 /* it is a run-time expression */
#define Type 4 /* only its type is relevant */
struct expr {
char *ex_file; /* the file it (probably) comes from */
unsigned int ex_line; /* the line it (probably) comes from */
struct type *ex_type;
short ex_lvalue;
short ex_flags;
int ex_class;
int ex_depth;
union {
struct value ex_value;
struct string ex_string;
flt_arith ex_fl_arith;
struct oper ex_oper;
} ex_object;
};
/* some abbreviated selections */
#define EX_VALUE ex_object.ex_value
#define VL_CLASS EX_VALUE.vl_class
#define VL_VALUE EX_VALUE.vl_value
#define VL_IDF EX_VALUE.vl_data.vl_idf
#define VL_LBL EX_VALUE.vl_data.vl_lbl
#define SG_VALUE ex_object.ex_string.sg_value
#define SG_LEN ex_object.ex_string.sg_len
#define FL_ARITH ex_object.ex_fl_arith
#define OP_TYPE ex_object.ex_oper.op_type
#define OP_LEFT ex_object.ex_oper.op_left
#define OP_OPER ex_object.ex_oper.op_oper
#define OP_RIGHT ex_object.ex_oper.op_right
/* some bits for the ex_flag field, to keep track of various
interesting properties of an expression.
*/
#define EX_SIZEOF 0x001 /* contains sizeof operator */
#define EX_CAST 0x002 /* contains cast */
#define EX_LOGICAL 0x004 /* contains logical operator */
#define EX_COMMA 0x008 /* contains expression comma */
#define EX_PARENS 0x010 /* the top level is parenthesized */
#define EX_SIDEEFFECTS 0x020 /* expression has side effects */
#define EX_READONLY 0x040 /* read only variabele */
#define EX_VOLATILE 0x080 /* volatile variabele */
#define EX_ILVALUE 0x100 /* an illegal lvalue e.g. f().x */
#define EX_ERROR 0x200 /* the expression is wrong */
#define EX_PTRDIFF 0x400 /* subtracting 2 pointers in expr. */
#define NILEXPR ((struct expr *)0)
/* some useful tests */
#define ISNAME(e) ((e)->ex_class == Value && (e)->VL_CLASS == Name)
#define ISCOMMA(e) ((e)->ex_class == Oper && (e)->OP_OPER == INITCOMMA)
/* ALLOCDEF "expr" 20 */
int rank_of(int oper);
void dot2expr(struct expr **expp);
void idf2expr(register struct expr *expr);
void string2expr(register struct expr **expp, char *str, int len);
void int2expr(struct expr *expr);
void float2expr(register struct expr *expr);
struct expr* intexpr(arith ivalue, int fund);
void fill_int_expr(register struct expr *ex, writh ivalue, int fund);
struct expr *new_oper(struct type *tp, register struct expr *e1, int oper,
register struct expr *e2);
void chk_cst_expr(struct expr **expp);
void init_expression(register struct expr ***eppp, struct expr *expr);
int is_ld_cst(register struct expr *expr);
int is_cp_cst(struct expr *expr);
int is_fp_cst(struct expr *expr);
int is_zero_cst(register struct expr *expr);
void free_expression(register struct expr *expr);
#endif