]> git.pond.sub.org Git - empserver/blob - src/lib/common/nstreval.c
Clean up library dependencies
[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 "file.h"
40 #include "nat.h"
41 #include "nsc.h"
42 #include "optlist.h"
43
44
45 /*
46  * Evaluate VAL.
47  * If VAL is symbolic, evaluate it into a promoted value type.
48  * Use coordinate system of country CNUM.
49  * PTR points to a context object of the type that was used to compile
50  * the value.
51  * Unless WANT is NSC_NOTYPE, coerce the value to promoted value type
52  * WANT.  VAL must be coercible.  That's the case if a previous
53  * nstr_coerce_val(VAL, WANT, STR) succeeded.
54  */
55 void
56 nstr_exec_val(struct valstr *val, natid cnum, void *ptr, nsc_type want)
57 {
58     char *memb_ptr;
59     nsc_type valtype;
60     int idx;
61     struct natstr *natp;
62
63     switch (val->val_cat) {
64     default:
65         CANT_REACH();
66         /* fall through */
67     case NSC_VAL:
68         valtype = val->val_type;
69         break;
70     case NSC_OFF:
71         valtype = NSC_LONG;
72         memb_ptr = ptr;
73         memb_ptr += val->val_as.sym.off;
74         idx = val->val_as.sym.idx;
75         switch (val->val_type) {
76         case NSC_CHAR:
77             val->val_as.lng = ((signed char *)memb_ptr)[idx];
78             break;
79         case NSC_UCHAR:
80             val->val_as.lng = ((unsigned char *)memb_ptr)[idx];
81             break;
82         case NSC_SHORT:
83             val->val_as.lng = ((short *)memb_ptr)[idx];
84             break;
85         case NSC_USHORT:
86             val->val_as.lng = ((unsigned short *)memb_ptr)[idx];
87             break;
88         case NSC_INT:
89             val->val_as.lng = ((int *)memb_ptr)[idx];
90             break;
91         case NSC_LONG:
92             val->val_as.lng = ((long *)memb_ptr)[idx];
93             break;
94         case NSC_XCOORD:
95             val->val_as.lng = xrel(getnatp(cnum), ((short *)memb_ptr)[idx]);
96             break;
97         case NSC_YCOORD:
98             val->val_as.lng = yrel(getnatp(cnum), ((short *)memb_ptr)[idx]);
99             break;
100         case NSC_HIDDEN:
101             val->val_as.lng = -1;
102             if (CANT_HAPPEN(((struct natstr *)ptr)->ef_type != EF_NATION))
103                 break;
104             natp = getnatp(cnum);
105             if (!opt_HIDDEN
106                 || natp->nat_stat == STAT_GOD
107                 || (getcontact(natp, idx) && getcontact(ptr, idx)))
108                 val->val_as.lng = ((unsigned char *)memb_ptr)[idx];
109             break;
110         case NSC_FLOAT:
111             val->val_as.dbl = ((float *)memb_ptr)[idx];
112             valtype = NSC_DOUBLE;
113             break;
114         case NSC_DOUBLE:
115             val->val_as.dbl = ((double *)memb_ptr)[idx];
116             valtype = NSC_DOUBLE;
117             break;
118         case NSC_STRINGY:
119             CANT_HAPPEN(idx);
120             val->val_as.str.maxsz = val->val_as.sym.len;
121             val->val_as.str.base = (char *)memb_ptr;
122             valtype = NSC_STRING;
123             break;
124         case NSC_STRING:
125             val->val_as.str.base = ((char **)memb_ptr)[idx];
126             val->val_as.str.maxsz = INT_MAX;
127             valtype = NSC_STRING;
128             break;
129         case NSC_TIME:
130             val->val_as.lng = ((time_t *)memb_ptr)[idx];
131             break;
132         default:
133             CANT_REACH();
134             val->val_as.lng = 0;
135         }
136         val->val_cat = NSC_VAL;
137     }
138
139     if (valtype == want)
140         ;
141     else if (want == NSC_DOUBLE) {
142         if (valtype == NSC_LONG) {
143             valtype = want;
144             val->val_as.dbl = val->val_as.lng;
145         }
146     } else if (want == NSC_STRING)
147         CANT_REACH();           /* FIXME implement */
148
149     if (CANT_HAPPEN(valtype != want && want != NSC_NOTYPE)) {
150         valtype = want;
151         switch (want) {
152         case NSC_LONG: val->val_as.lng = 0; break;
153         case NSC_DOUBLE: val->val_as.dbl = 0.0; break;
154         case NSC_STRING: val->val_as.str.base = NULL; break;
155         default:
156             CANT_REACH();
157         }
158     }
159
160     val->val_type = valtype;
161 }
162
163 char *
164 symbol_by_value(int key, struct symbol *table)
165 {
166     int i;
167
168     for (i = 0; table[i].name; i++)
169         if (key == table[i].value)
170             return table[i].name;
171
172     return NULL;
173 }