Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cemcom / ch7mon.c
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  */
5 /* $Id: ch7mon.c,v 3.24 1994/06/24 12:02:32 ceriel Exp $ */
6 /* SEMANTIC ANALYSIS (CHAPTER 7RM) -- MONADIC OPERATORS */
7
8 #include        "botch_free.h"
9 #include        <alloc.h>
10 #include        "nofloat.h"
11 #include        "nobitfield.h"
12 #include        "Lpars.h"
13 #include        "arith.h"
14 #include        "type.h"
15 #include        "label.h"
16 #include        "expr.h"
17 #include        "idf.h"
18 #include        "def.h"
19
20 extern char options[];
21 extern long full_mask[/*MAXSIZE*/];     /* cstoper.c */
22 char *symbol2str();
23
24 ch7mon(oper, expp)
25         register struct expr **expp;
26 {
27         /*      The monadic prefix operator oper is applied to *expp.
28         */
29         register struct expr *expr;
30
31         switch (oper)   {
32         case '*':                       /* RM 7.2 */
33                 /* no FIELD type allowed        */
34                 if ((*expp)->ex_type->tp_fund == ARRAY)
35                         array2pointer(*expp);
36                 if ((*expp)->ex_type->tp_fund != POINTER)       {
37                         expr_error(*expp,
38                                 "* applied to non-pointer (%s)",
39                                 symbol2str((*expp)->ex_type->tp_fund));
40                 }
41                 else {
42                         expr = *expp;
43                         if (expr->ex_lvalue == 0 && expr->ex_class != String)
44                                 /* dereference in administration only */
45                                 expr->ex_type = expr->ex_type->tp_up;
46                         else    /* runtime code */
47                                 *expp = new_oper(expr->ex_type->tp_up, NILEXPR,
48                                                         '*', expr);
49                         (*expp)->ex_lvalue = (
50                                 (*expp)->ex_type->tp_fund != ARRAY &&
51                                 (*expp)->ex_type->tp_fund != FUNCTION);
52                 }
53                 break;
54         case '&':
55                 if ((*expp)->ex_type->tp_fund == ARRAY) {
56                         expr_warning(*expp, "& before array ignored");
57                         array2pointer(*expp);
58                 }
59                 else
60                 if ((*expp)->ex_type->tp_fund == FUNCTION) {
61                         expr_warning(*expp, "& before function ignored");
62                         function2pointer(*expp);
63                 }
64                 else
65 #ifndef NOBITFIELD
66                 if ((*expp)->ex_type->tp_fund == FIELD)
67                         expr_error(*expp, "& applied to field variable");
68                 else
69 #endif /* NOBITFIELD */
70                 if (!(*expp)->ex_lvalue)
71                         expr_error(*expp, "& applied to non-lvalue");
72                 else {
73                         /* assume that enums are already filtered out   */
74                         if (ISNAME(*expp)) {
75                                 register struct def *def =
76                                         (*expp)->VL_IDF->id_def;
77
78                                 /*      &<var> indicates that <var>
79                                         cannot be used as register
80                                         anymore
81                                 */
82                                 if (def->df_sc == REGISTER) {
83                                         expr_error(*expp,
84                                         "& on register variable not allowed");
85                                         break;  /* break case '&' */
86                                 }
87                         }
88                         (*expp)->ex_type = pointer_to((*expp)->ex_type);
89                         (*expp)->ex_lvalue = 0;
90                 }
91                 break;
92         case '~':
93 #ifndef NOFLOAT
94         {
95                 int fund = (*expp)->ex_type->tp_fund;
96
97                 if (fund == FLOAT || fund == DOUBLE)    {
98                         expr_error(
99                                 *expp,
100                                 "~ not allowed on %s operands",
101                                 symbol2str(fund)
102                         );
103                         erroneous2int(expp);
104                         break;
105                 }
106                 /* FALLTHROUGH */
107         }
108 #endif /* NOFLOAT */
109         case '-':
110                 any2arith(expp, oper);
111                 if (is_cp_cst(*expp))   {
112                         arith o1 = (*expp)->VL_VALUE;
113
114                         o1 = (oper == '-') ? -o1 : ~o1;
115                         (*expp)->VL_VALUE =
116                           ((*expp)->ex_type->tp_unsigned ?
117                                 o1 & full_mask[(*expp)->ex_type->tp_size] :
118                                 o1
119                           );
120                 }
121                 else
122 #ifndef NOFLOAT
123                 if (is_fp_cst(*expp))
124                         switch_sign_fp(*expp);
125                 else
126 #endif /* NOFLOAT */
127                         *expp = new_oper((*expp)->ex_type,
128                                         NILEXPR, oper, *expp);
129                 break;
130         case '!':
131                 if ((*expp)->ex_type->tp_fund == FUNCTION)
132                         function2pointer(*expp);
133                 if ((*expp)->ex_type->tp_fund != POINTER)
134                         any2arith(expp, oper);
135                 opnd2test(expp, '!');
136                 if (is_cp_cst(*expp))   {
137                         (*expp)->VL_VALUE = !((*expp)->VL_VALUE);
138                         (*expp)->ex_type = int_type;    /* a cast ???(EB) */
139                 }
140                 else
141                         *expp = new_oper(int_type, NILEXPR, oper, *expp);
142                 (*expp)->ex_flags |= EX_LOGICAL;
143                 break;
144         case PLUSPLUS:
145         case MINMIN:
146                 ch7incr(expp, oper);
147                 break;
148         case SIZEOF:
149                 if (ISNAME(*expp) && (*expp)->VL_IDF->id_def->df_formal_array)
150                         expr_warning(*expp, "sizeof formal array %s is sizeof pointer!",
151                                 (*expp)->VL_IDF->id_text);
152                 expr = intexpr((*expp)->ex_class == String ?
153                                    (arith)((*expp)->SG_LEN) :
154                                    size_of_type((*expp)->ex_type, "object"),
155                                 INT);
156                 expr->ex_flags |= EX_SIZEOF;
157                 free_expression(*expp);
158                 *expp = expr;
159                 break;
160         }
161 }