]> git.pond.sub.org Git - empserver/blob - src/lib/common/nstreval.c
dd9addc8e655d58fbb329e08018900b6657d34c5
[empserver] / src / lib / common / nstreval.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                           Ken Stevens, Steve McClure
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  *  ---
21  *
22  *  See files README, COPYING and CREDITS in the root of the source
23  *  tree for related information and legal notices.  It is expected
24  *  that future projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  nstreval.c: evaluate compiled values
29  *
30  *  Known contributors to this file:
31  *     Dave Pare, 1989
32  *     Steve McClure, 1997
33  *     Markus Armbruster, 2004-2008
34  */
35
36 #include <config.h>
37
38 #include <limits.h>
39 #include <string.h>
40 #include "file.h"
41 #include "nat.h"
42 #include "nsc.h"
43 #include "optlist.h"
44
45 /*
46  * Initialize VAL to symbolic value for selector CA with index IDX.
47  * Return VAL.
48  */
49 struct valstr *
50 nstr_mksymval(struct valstr *val, struct castr *ca, int idx)
51 {
52     val->val_type = ca->ca_type;
53     val->val_cat = NSC_OFF;
54     val->val_as.sym.off = ca->ca_off;
55     val->val_as.sym.len = ca->ca_len;
56     val->val_as.sym.idx = idx;
57     val->val_as.sym.get = ca->ca_get;
58     return val;
59 }
60
61 /*
62  * Evaluate VAL.
63  * If VAL is symbolic, evaluate it into a promoted value type.
64  * Translate it for country CNUM (coordinate system and contact
65  * status), except when CNUM is NATID_BAD.
66  * PTR points to a context object of the type that was used to compile
67  * the value.
68  * Unless WANT is NSC_NOTYPE, coerce the value to promoted value type
69  * WANT.  VAL must be coercible.
70  */
71 struct valstr *
72 nstr_exec_val(struct valstr *val, natid cnum, void *ptr, enum nsc_type want)
73 {
74     char *memb_ptr;
75     enum nsc_type valtype;
76     int idx;
77     coord c;
78     struct natstr *natp;
79
80     if (CANT_HAPPEN(want != NSC_NOTYPE && !NSC_IS_PROMOTED(want)))
81         want = nstr_promote(want);
82
83     switch (val->val_cat) {
84     case NSC_VAL:
85         valtype = val->val_type;
86         break;
87     case NSC_OFF:
88         if (val->val_as.sym.get) {
89             natp = getnatp(cnum);
90             do {
91                 ptr = val->val_as.sym.get(val, natp, ptr);
92             } while (ptr && val->val_as.sym.get);
93             if (!ptr) {
94                 valtype = val->val_type;
95                 val->val_cat = NSC_VAL;
96                 break;
97             }
98         }
99
100         valtype = NSC_LONG;
101         memb_ptr = ptr;
102         memb_ptr += val->val_as.sym.off;
103         idx = val->val_as.sym.idx;
104         switch (val->val_type) {
105         case NSC_CHAR:
106             val->val_as.lng = ((signed char *)memb_ptr)[idx];
107             break;
108         case NSC_UCHAR:
109             val->val_as.lng = ((unsigned char *)memb_ptr)[idx];
110             break;
111         case NSC_SHORT:
112             val->val_as.lng = ((short *)memb_ptr)[idx];
113             break;
114         case NSC_USHORT:
115             val->val_as.lng = ((unsigned short *)memb_ptr)[idx];
116             break;
117         case NSC_INT:
118             val->val_as.lng = ((int *)memb_ptr)[idx];
119             break;
120         case NSC_LONG:
121             val->val_as.lng = ((long *)memb_ptr)[idx];
122             break;
123         case NSC_XCOORD:
124             c = ((short *)memb_ptr)[idx];
125             if (cnum == NATID_BAD) {
126                 /* FIXME use variant of xrel() that takes orig instead of nation */
127                 if (c >= WORLD_X / 2)
128                     c -= WORLD_X;
129             } else
130                 c = xrel(getnatp(cnum), c);
131             val->val_as.lng = c;
132             break;
133         case NSC_YCOORD:
134             c = ((short *)memb_ptr)[idx];
135             if (cnum == NATID_BAD) {
136                 /* FIXME use variant of yrel() that takes orig instead of nation */
137                 if (c >= WORLD_Y / 2)
138                     c -= WORLD_Y;
139             } else
140                 c = yrel(getnatp(cnum), c);
141             val->val_as.lng = c;
142             break;
143         case NSC_HIDDEN:
144             val->val_as.lng = -1;
145             if (CANT_HAPPEN(((struct natstr *)ptr)->ef_type != EF_NATION))
146                 break;
147             if (opt_HIDDEN && cnum != NATID_BAD) {
148                 natp = getnatp(cnum);
149                 if (natp->nat_stat != STAT_GOD
150                     && !(getcontact(natp, idx) && getcontact(ptr, idx)))
151                     break;
152             }
153             val->val_as.lng = ((unsigned char *)memb_ptr)[idx];
154             break;
155         case NSC_FLOAT:
156             val->val_as.dbl = ((float *)memb_ptr)[idx];
157             valtype = NSC_DOUBLE;
158             break;
159         case NSC_DOUBLE:
160             val->val_as.dbl = ((double *)memb_ptr)[idx];
161             valtype = NSC_DOUBLE;
162             break;
163         case NSC_STRINGY:
164             CANT_HAPPEN(idx);
165             val->val_as.str.maxsz = val->val_as.sym.len;
166             val->val_as.str.base = (char *)memb_ptr;
167             valtype = NSC_STRING;
168             break;
169         case NSC_STRING:
170             val->val_as.str.base = ((char **)memb_ptr)[idx];
171             val->val_as.str.maxsz = INT_MAX;
172             valtype = NSC_STRING;
173             break;
174         case NSC_TIME:
175             val->val_as.lng = ((time_t *)memb_ptr)[idx];
176             break;
177         default:
178             CANT_REACH();
179             val->val_as.lng = 0;
180         }
181         val->val_cat = NSC_VAL;
182         break;
183     default:
184         CANT_REACH();
185         valtype = NSC_NOTYPE;
186     }
187
188     /* coerce */
189     if (valtype == want)
190         ;
191     else if (want == NSC_DOUBLE) {
192         if (valtype == NSC_LONG) {
193             valtype = want;
194             val->val_as.dbl = val->val_as.lng;
195         }
196     }
197
198     if (CANT_HAPPEN(valtype != want && want != NSC_NOTYPE)) {
199         /* make up an error value */
200         valtype = want;
201         memset(&val->val_as, 0, sizeof(val->val_as));
202     }
203
204     val->val_type = valtype;
205     return val;
206 }
207
208 /*
209  * Promote VALTYPE.
210  * If VALTYPE is an integer type, return NSC_LONG.
211  * If VALTYPE is a floating-point type, return NSC_DOUBLE.
212  * If VALTYPE is a string type, return NSC_STRING.
213  */
214 int
215 nstr_promote(int valtype)
216 {
217     switch (valtype) {
218     case NSC_LONG:
219     case NSC_DOUBLE:
220     case NSC_STRING:
221         break;
222     case NSC_CHAR:
223     case NSC_UCHAR:
224     case NSC_SHORT:
225     case NSC_USHORT:
226     case NSC_INT:
227     case NSC_XCOORD:
228     case NSC_YCOORD:
229     case NSC_HIDDEN:
230     case NSC_TIME:
231         valtype = NSC_LONG;
232         break;
233     case NSC_FLOAT:
234         valtype = NSC_DOUBLE;
235         break;
236     case NSC_STRINGY:
237         valtype = NSC_STRING;
238         break;
239     default:
240         CANT_REACH();
241         valtype = NSC_NOTYPE;
242     }
243     return valtype;
244 }
245
246 char *
247 symbol_by_value(int key, struct symbol *table)
248 {
249     int i;
250
251     for (i = 0; table[i].name; i++)
252         if (key == table[i].value)
253             return table[i].name;
254
255     return NULL;
256 }