]> git.pond.sub.org Git - empserver/blob - src/lib/commands/xdump.c
1bddea6ec2e469ff393670e274d53dc5ddf9e9c5
[empserver] / src / lib / commands / xdump.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2000, 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 the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23  *  related information and legal notices. It is expected that any future
24  *  projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  xdump.c: Experimental extended dump
29  * 
30  *  Known contributors to this file:
31  *     Markus Armbruster, 2004
32  */
33
34 #include <stddef.h>
35 #include "misc.h"
36 #include "file.h"
37 #include "match.h"
38 #include "nsc.h"
39
40 /*
41  * Dump everything under the sun
42  *
43  * Static game data (configuration):
44  * - Item characteristics: ichr[]
45  * - Land unit characteristics: lchr[]
46  * - Nuke characteristics: nchr[]
47  * - Plane characteristics: plchr[]
48  * - Product characteristics: pchr[]
49  * - Sector designation characteristics: dchr[]
50  * - Sector infrastructure characteristics: intrchr[]
51  * - Ship characteristics: mchr[]
52  * Less important:
53  * - News item characteristics: rpt[]
54  * - Treaty clause characteristics: tchr[]
55  * - Commands: coms[]
56  * - Options: Options[]
57  * - Configuration: configkeys[]
58  *
59  * Dynamic game data:
60  * - Sectors: EF_SECTOR, sect_ca[] (already have dump)
61  * - Land units: EF_LAND, land_ca[] (already have ldump)
62  * - Lost: EF_LOST, lost_ca[] (already have lost)
63  * - Nukes: EF_NUKE, nuke_ca[] (already have ndump)
64  * - Planes: EF_PLANE, plane_ca[] (already have pdump)
65  * - Ships: EF_SHIP, ship_ca[] (already have sdump)
66  * - News: EF_NEWS, news_ca[]
67  * - Treaties: EF_TREATY, treaty_ca[]
68  * - Power: EF_POWER
69  * - Nations: EF_NATION, nat_ca[]
70  * - Loans: EF_LOAN, loan_ca[]
71  * - Map: EF_MAP
72  * - Bmap: EF_BMAP
73  * - Market: EF_COMM, commodity_ca[]
74  */
75
76 /* FIXME document dump format */
77
78 /* Selector descriptors for characteristics tables */
79 /* FIXME belongs into src/lib/global/ */
80
81 static struct castr ichr_ca[] = {
82     {NSC_STRING, 0, 0, offsetof(struct ichrstr, i_name), "name"},
83     {NSC_INT, 0, 0, offsetof(struct ichrstr, i_mnem), "mnem"},
84     {NSC_INT, 0, 0, offsetof(struct ichrstr, i_vtype), "vtype"},
85     {NSC_INT, 0, 0, offsetof(struct ichrstr, i_value), "value"},
86     {NSC_INT, 0, 0, offsetof(struct ichrstr, i_sell), "sell"},
87     {NSC_INT, 0, 0, offsetof(struct ichrstr, i_lbs), "lbs"},
88     {NSC_INT, 0, NUMPKG, offsetof(struct ichrstr, i_pkg), "pkg"},
89     {NSC_NOTYPE, 0, 0, 0, NULL}
90 };
91
92 static struct castr mchr_ca[] = {
93     {NSC_STRING, 0, 0, offsetof(struct mchrstr, m_name), "name"},
94     {NSC_USHORT, 0, I_MAX+1, offsetof(struct mchrstr, m_item), "item"},
95     {NSC_INT, 0, 0, offsetof(struct mchrstr, m_lcm), "lcm"},
96     {NSC_INT, 0, 0, offsetof(struct mchrstr, m_hcm), "hcm"},
97     {NSC_INT, 0, 0, offsetof(struct mchrstr, m_armor), "armor"},
98     {NSC_INT, 0, 0, offsetof(struct mchrstr, m_speed), "speed"},
99     {NSC_INT, 0, 0, offsetof(struct mchrstr, m_visib), "visib"},
100     {NSC_INT, 0, 0, offsetof(struct mchrstr, m_vrnge), "vrnge"},
101     {NSC_INT, 0, 0, offsetof(struct mchrstr, m_glim), "glim"},
102     {NSC_UCHAR, 0, 0, offsetof(struct mchrstr, m_nxlight), "nxlight"},
103     {NSC_UCHAR, 0, 0, offsetof(struct mchrstr, m_nchoppers), "nchoppers"},
104     {NSC_UCHAR, 0, 0, offsetof(struct mchrstr, m_fuelc), "fuelc"},
105     {NSC_UCHAR, 0, 0, offsetof(struct mchrstr, m_fuelu), "fuelu"},
106     {NSC_INT, 0, 0, offsetof(struct mchrstr, m_tech), "tech"},
107     {NSC_INT, 0, 0, offsetof(struct mchrstr, m_cost), "cost"},
108     {NSC_INT, 0, 0, offsetof(struct mchrstr, m_flags), "flags"},
109     {NSC_UCHAR, 0, 0, offsetof(struct mchrstr, m_nplanes), "nplanes"},
110     {NSC_UCHAR, 0, 0, offsetof(struct mchrstr, m_nland), "nland"},
111     {NSC_NOTYPE, 0, 0, 0, NULL}
112 };
113
114 static struct castr pchr_ca[] = {
115     {NSC_STRING, 0, 0, offsetof(struct pchrstr, p_name), "name"},
116     {NSC_STRING, 0, 0, offsetof(struct pchrstr, p_sname), "sname"},
117     {NSC_UCHAR, 0, MAXPRCON, offsetof(struct pchrstr, p_ctype), "ctype"},
118     {NSC_USHORT, 0, MAXPRCON, offsetof(struct pchrstr, p_camt), "camt"},
119     {NSC_INT, 0, 0, offsetof(struct pchrstr, p_type), "type"},
120     {NSC_INT, 0, 0, offsetof(struct pchrstr, p_level), "level"},
121     {NSC_INT, 0, 0, offsetof(struct pchrstr, p_cost), "cost"},
122     {NSC_INT, 0, 0, offsetof(struct pchrstr, p_nrndx), "nrndx"},
123     {NSC_INT, 0, 0, offsetof(struct pchrstr, p_nrdep), "nrdep"},
124     {NSC_INT, 0, 0, offsetof(struct pchrstr, p_nlndx), "nlndx"},
125     {NSC_INT, 0, 0, offsetof(struct pchrstr, p_nlmin), "nlmin"},
126     {NSC_INT, 0, 0, offsetof(struct pchrstr, p_nllag), "nllag"},
127     {NSC_INT, 0, 0, offsetof(struct pchrstr, p_effic), "effic"},
128     {NSC_NOTYPE, 0, 0, 0, NULL}
129 };
130
131 static struct castr plchr_ca[] = {
132     {NSC_STRING, 0, 0, offsetof(struct plchrstr, pl_name), "name"},
133     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_lcm), "lcm"},
134     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_hcm), "hcm"},
135     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_cost), "cost"},
136     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_tech), "tech"},
137     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_acc), "acc"},
138     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_load), "load"},
139     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_att), "att"},
140     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_def), "def"},
141     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_range), "range"},
142     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_crew), "crew"},
143     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_fuel), "fuel"},
144     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_stealth), "stealth"},
145     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_flags), "flags"},
146     {NSC_NOTYPE, 0, 0, 0, NULL}
147 };
148
149 static struct castr lchr_ca[] = {
150     {NSC_STRING, 0, 0, offsetof(struct lchrstr, l_name), "name"},
151     {NSC_USHORT, 0, I_MAX+1, offsetof(struct mchrstr, m_item), "item"},
152     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_lcm), "lcm"},
153     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_hcm), "hcm"},
154     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_gun), "gun"},
155     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_shell), "shell"},
156     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_tech), "tech"},
157     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_cost), "cost"},
158     {NSC_FLOAT, 0, 0, offsetof(struct lchrstr, l_att), "att"},
159     {NSC_FLOAT, 0, 0, offsetof(struct lchrstr, l_def), "def"},
160     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_vul), "vul"},
161     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_spd), "spd"},
162     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_vis), "vis"},
163     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_spy), "spy"},
164     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_rad), "rad"},
165     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_frg), "frg"},
166     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_acc), "acc"},
167     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_dam), "dam"},
168     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_ammo), "ammo"},
169     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_aaf), "aaf"},
170     {NSC_UCHAR, 0, 0, offsetof(struct lchrstr, l_fuelc), "fuelc"},
171     {NSC_UCHAR, 0, 0, offsetof(struct lchrstr, l_fuelu), "fuelu"},
172     {NSC_UCHAR, 0, 0, offsetof(struct lchrstr, l_nxlight), "nxlight"},
173     {NSC_UCHAR, 0, 0, offsetof(struct lchrstr, l_mxland), "mxland"},
174     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_flags), "flags"},
175     {NSC_NOTYPE, 0, 0, 0, NULL}
176 };
177
178 static struct castr nchr_ca[] = {
179     {NSC_STRING, 0, 0, offsetof(struct nchrstr, n_name), "name"},
180     {NSC_INT, 0, 0, offsetof(struct nchrstr, n_lcm), "lcm"},
181     {NSC_INT, 0, 0, offsetof(struct nchrstr, n_hcm), "hcm"},
182     {NSC_INT, 0, 0, offsetof(struct nchrstr, n_oil), "oil"},
183     {NSC_INT, 0, 0, offsetof(struct nchrstr, n_rad), "rad"},
184     {NSC_INT, 0, 0, offsetof(struct nchrstr, n_blast), "blast"},
185     {NSC_INT, 0, 0, offsetof(struct nchrstr, n_dam), "dam"},
186     {NSC_INT, 0, 0, offsetof(struct nchrstr, n_cost), "cost"},
187     {NSC_INT, 0, 0, offsetof(struct nchrstr, n_tech), "tech"},
188     {NSC_INT, 0, 0, offsetof(struct nchrstr, n_weight), "weight"},
189     {NSC_INT, 0, 0, offsetof(struct nchrstr, n_flags), "flags"},
190     {NSC_NOTYPE, 0, 0, 0, NULL}
191 };
192
193 /* Characteristics table meta data */
194 struct camap {
195     char *name;                 /* name for lookup */
196     struct castr *ca;           /* selector descriptors */
197     void *chr;                  /* characteristics table */
198     size_t size;                /* size of characteristics table element */
199 };
200
201 /* Table of characteristics tables */
202 static struct camap chr_camap[] = {
203     {"item", ichr_ca, ichr, sizeof(ichr[0])},
204     {"product", pchr_ca, pchr, sizeof(pchr[0])},
205     {"ship chr", mchr_ca, mchr, sizeof(mchr[0])},
206     {"plane chr", plchr_ca, plchr, sizeof(plchr[0])},
207     {"land chr", lchr_ca, lchr, sizeof(lchr[0])},
208     {"nuke chr", nchr_ca, nchr, sizeof(nchr[0])},
209     {NULL, NULL, NULL, 0}
210 };
211
212 /*
213  * Search chr_camap[] for element named NAME, return its index.
214  * Return M_NOTFOUND if there are no matches, M_NOTUNIQUE if there are
215  * several.
216  */
217 static int
218 chridx_by_name(char *name)
219 {
220     return stmtch(name, chr_camap, offsetof(struct camap, name),
221                   sizeof(chr_camap[0]));
222 }
223
224 /*
225  * Evaluate a attribute of an object into VAL.
226  * TYPE is the attribute's type.
227  * PTR points to the context object.
228  * The attribute is stored there at offset OFF + IDX * S, where S is
229  * its size.
230  */
231 static struct valstr *
232 xdeval(struct valstr *val, nsc_type type, void *ptr, ptrdiff_t off, int idx)
233 {
234     val->val_type = type;
235     val->val_cat = NSC_OFF;
236     val->val_as_type = -1;
237     val->val_as.sym.off = off;
238     val->val_as.sym.idx = idx;
239     nstr_exec_val(val, player->cnum, ptr, NSC_NOTYPE);
240     return val;                 /* FIXME nstr_exec_val() should return VAL */
241 }
242
243 /* Dump VAL prefixed with SEP, return " ".  */
244 static char *
245 xdprval(struct valstr *val, char *sep)
246 {
247     char *s, *e;
248
249     switch (val->val_type) {
250     case NSC_TYPEID:
251     case NSC_LONG:
252         pr("%s%ld", sep, val->val_as.lng);
253         break;
254     case NSC_DOUBLE:
255         pr("%s%g", sep, val->val_as.dbl);
256         break;
257     case NSC_STRING:
258         pr("%s\"", sep);
259         s = val->val_as.str;
260         while (s && *s) {
261             for (e = s; *e != '"' && isprint(*e); ++e) ;
262             pr("%*s", (int)(e-s), s);
263             for (; *e && !isprint(*e); ++e) {
264                 pr("\\%3o", *e);
265             }
266             s = e;
267         }
268         prnf("\"");
269         break;
270     default:
271         CANT_HAPPEN("Bad VAL type");
272         pr("0");
273     }
274     return " ";
275 }
276
277 /*
278  * Dump field values of a context object.
279  * CA[] describes fields.
280  * PTR points to context object.
281  */
282 static void
283 xdflds(struct castr ca[], void *ptr)
284 {
285     int i, j;
286     struct valstr val;
287     char *sep = "";
288
289     for (i = 0; ca[i].ca_name; ++i) {
290         if (ca[i].ca_flags & NSC_DEITY && !player->god)
291             continue;
292         j = 0;
293         do {
294             xdeval(&val, ca[i].ca_type, ptr, ca[i].ca_off, j);
295             sep = xdprval(&val, sep);
296         } while (++j < ca[i].ca_len);
297     }
298 }
299
300 /* Dump field names; CA[] describes fields.  */
301 static void
302 xdfldnam(struct castr ca[])
303 {
304     int i;
305     char *sep = "";
306
307     for (i = 0; ca[i].ca_name; ++i) {
308         if (ca[i].ca_flags & NSC_DEITY && !player->god)
309             continue;
310         pr("%s%s", sep, ca[i].ca_name);
311         if (ca[i].ca_len)
312             pr(" %d", ca[i].ca_len);
313         sep = " ";
314     }
315 }
316
317 /* Dump header for dump NAME with fields described by CA[].  */
318 static void
319 xdhdr(char *name, struct castr ca[])
320 {
321     prdate();
322     pr("DUMP %s %ld\n", name, (long)time(NULL));
323
324     xdfldnam(ca);
325     pr("\n");
326 }
327
328 /* Dump footer for a dump that dumped N objects.  */
329 static void
330 xdftr(int n)
331 {
332     pr("dumped %d\n", n);
333 }
334
335 /*
336  * Dump items of type TYPE selected by ARG.
337  * Return RET_OK on success, RET_SYN on error.
338  */
339 static int
340 xditem(int type, char *arg)
341 {
342     struct castr *ca;
343     struct nstr_item ni;
344     int n;
345     s_char buf[2048];           /* FIXME buffer size? */
346
347     ca = ef_cadef(type);
348     if (!ca)
349         return RET_SYN;
350
351     if (!snxtitem(&ni, type, arg))
352         return RET_SYN;
353
354     xdhdr(ef_nameof(type), ca);
355
356     n = 0;
357     while (nxtitem(&ni, buf)) {
358         if (!player->owner)
359             continue;
360         ++n;
361         xdflds(ca, buf);
362         pr("\n");
363     }
364
365     xdftr(n);
366
367     return RET_OK;
368 }
369
370 /*
371  * Dump characteristics described by chr_camap[IDX].
372  * Return RET_OK on success, RET_SYN if IDX < 0.
373  */
374 static int
375 xdchr(int chridx)
376 {
377     struct camap *cm;
378     char *p;
379     struct valstr val;
380     int n;
381
382     if (chridx < 0)
383         return RET_SYN;
384     cm = &chr_camap[chridx];
385
386     xdhdr(cm->name, cm->ca);
387
388     n = 0;
389     for (p = cm->chr; ; p += cm->size) {
390         val.val_type = cm->ca[0].ca_type;
391         val.val_cat = NSC_OFF;
392         val.val_as_type = -1;
393         val.val_as.sym.off = cm->ca[0].ca_off;
394         val.val_as.sym.idx = 0;
395         nstr_exec_val(&val, player->cnum, p, NSC_STRING);
396         if (!val.val_as.str || !*val.val_as.str)
397             break;
398         ++n;
399         xdflds(cm->ca, p);
400         pr("\n");
401     }
402
403     xdftr(n);
404
405     return RET_OK;
406 }
407
408 /* Experimental extended dump command */
409 int
410 xdump(void)
411 {
412     s_char *p;
413     char buf[1024];
414     int type;
415
416     p = getstarg(player->argp[1], "What? ", buf);
417     if (!p)
418         return RET_SYN;
419
420     type = ef_byname(p);
421     if (type >= 0) {
422         return xditem(type, player->argp[2]);
423     } else if (!strncmp(p, "chr", strlen(p)) && player->argp[2]) {
424         return xdchr(chridx_by_name(player->argp[2]));
425     }
426
427     return RET_SYN;
428 }