]> git.pond.sub.org Git - empserver/blob - src/lib/common/nstreval.c
Update known contributors comments
[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  * Use country CNUM's coordinate system and access control.
65  * PTR points to a context object of the type that was used to compile
66  * the value.
67  * Unless WANT is NSC_NOTYPE, coerce the value to promoted value type
68  * WANT.  VAL must be coercible.  That's the case if a previous
69  * nstr_coerce_val(VAL, WANT, STR) succeeded.
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     struct natstr *natp;
78
79     if (CANT_HAPPEN(want != NSC_NOTYPE && !NSC_IS_PROMOTED(want)))
80         want = nstr_promote(want);
81
82     switch (val->val_cat) {
83     case NSC_VAL:
84         valtype = val->val_type;
85         break;
86     case NSC_OFF:
87         if (val->val_as.sym.get) {
88             do {
89                 ptr = val->val_as.sym.get(val, cnum, ptr);
90             } while (ptr && val->val_as.sym.get);
91             if (!ptr) {
92                 valtype = val->val_type;
93                 val->val_cat = NSC_VAL;
94                 break;
95             }
96         }
97
98         valtype = NSC_LONG;
99         memb_ptr = ptr;
100         memb_ptr += val->val_as.sym.off;
101         idx = val->val_as.sym.idx;
102         switch (val->val_type) {
103         case NSC_CHAR:
104             val->val_as.lng = ((signed char *)memb_ptr)[idx];
105             break;
106         case NSC_UCHAR:
107             val->val_as.lng = ((unsigned char *)memb_ptr)[idx];
108             break;
109         case NSC_SHORT:
110             val->val_as.lng = ((short *)memb_ptr)[idx];
111             break;
112         case NSC_USHORT:
113             val->val_as.lng = ((unsigned short *)memb_ptr)[idx];
114             break;
115         case NSC_INT:
116             val->val_as.lng = ((int *)memb_ptr)[idx];
117             break;
118         case NSC_LONG:
119             val->val_as.lng = ((long *)memb_ptr)[idx];
120             break;
121         case NSC_XCOORD:
122             val->val_as.lng = xrel(getnatp(cnum), ((short *)memb_ptr)[idx]);
123             break;
124         case NSC_YCOORD:
125             val->val_as.lng = yrel(getnatp(cnum), ((short *)memb_ptr)[idx]);
126             break;
127         case NSC_HIDDEN:
128             val->val_as.lng = -1;
129             if (CANT_HAPPEN(((struct natstr *)ptr)->ef_type != EF_NATION))
130                 break;
131             natp = getnatp(cnum);
132             if (!opt_HIDDEN
133                 || natp->nat_stat == STAT_GOD
134                 || (getcontact(natp, idx) && getcontact(ptr, idx)))
135                 val->val_as.lng = ((unsigned char *)memb_ptr)[idx];
136             break;
137         case NSC_FLOAT:
138             val->val_as.dbl = ((float *)memb_ptr)[idx];
139             valtype = NSC_DOUBLE;
140             break;
141         case NSC_DOUBLE:
142             val->val_as.dbl = ((double *)memb_ptr)[idx];
143             valtype = NSC_DOUBLE;
144             break;
145         case NSC_STRINGY:
146             CANT_HAPPEN(idx);
147             val->val_as.str.maxsz = val->val_as.sym.len;
148             val->val_as.str.base = (char *)memb_ptr;
149             valtype = NSC_STRING;
150             break;
151         case NSC_STRING:
152             val->val_as.str.base = ((char **)memb_ptr)[idx];
153             val->val_as.str.maxsz = INT_MAX;
154             valtype = NSC_STRING;
155             break;
156         case NSC_TIME:
157             val->val_as.lng = ((time_t *)memb_ptr)[idx];
158             break;
159         default:
160             CANT_REACH();
161             val->val_as.lng = 0;
162         }
163         val->val_cat = NSC_VAL;
164         break;
165     default:
166         CANT_REACH();
167         valtype = NSC_NOTYPE;
168     }
169
170     if (valtype == want)
171         ;
172     else if (want == NSC_DOUBLE) {
173         if (valtype == NSC_LONG) {
174             valtype = want;
175             val->val_as.dbl = val->val_as.lng;
176         }
177     } else if (want == NSC_STRING)
178         CANT_REACH();           /* FIXME implement */
179
180     if (CANT_HAPPEN(valtype != want && want != NSC_NOTYPE)) {
181         /* make up an error value */
182         valtype = want;
183         memset(&val->val_as, 0, sizeof(val->val_as));
184     }
185
186     val->val_type = valtype;
187     return val;
188 }
189
190 /*
191  * Promote VALTYPE.
192  * If VALTYPE is an integer type, return NSC_LONG.
193  * If VALTYPE is a floating-point type, return NSC_DOUBLE.
194  * If VALTYPE is a string type, return NSC_STRING.
195  */
196 int
197 nstr_promote(int valtype)
198 {
199     switch (valtype) {
200     case NSC_LONG:
201     case NSC_DOUBLE:
202     case NSC_STRING:
203         break;
204     case NSC_CHAR:
205     case NSC_UCHAR:
206     case NSC_SHORT:
207     case NSC_USHORT:
208     case NSC_INT:
209     case NSC_XCOORD:
210     case NSC_YCOORD:
211     case NSC_HIDDEN:
212     case NSC_TIME:
213         valtype = NSC_LONG;
214         break;
215     case NSC_FLOAT:
216         valtype = NSC_DOUBLE;
217         break;
218     case NSC_STRINGY:
219         valtype = NSC_STRING;
220         break;
221     default:
222         CANT_REACH();
223         valtype = NSC_NOTYPE;
224     }
225     return valtype;
226 }
227
228 char *
229 symbol_by_value(int key, struct symbol *table)
230 {
231     int i;
232
233     for (i = 0; table[i].name; i++)
234         if (key == table[i].value)
235             return table[i].name;
236
237     return NULL;
238 }