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