]> git.pond.sub.org Git - empserver/blob - src/lib/commands/xdump.c
(xdprval): Passed ptrdiff_t as field width.
[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_STRING, 0, 0, offsetof(struct plchrstr, pl_planename), "planename"},
134     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_lcm), "lcm"},
135     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_hcm), "hcm"},
136     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_cost), "cost"},
137     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_tech), "tech"},
138     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_acc), "acc"},
139     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_load), "load"},
140     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_att), "att"},
141     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_def), "def"},
142     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_range), "range"},
143     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_crew), "crew"},
144     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_fuel), "fuel"},
145     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_stealth), "stealth"},
146     {NSC_INT, 0, 0, offsetof(struct plchrstr, pl_flags), "flags"},
147     {NSC_NOTYPE, 0, 0, 0, NULL}
148 };
149
150 static struct castr lchr_ca[] = {
151     {NSC_STRING, 0, 0, offsetof(struct lchrstr, l_name), "name"},
152     {NSC_USHORT, 0, I_MAX+1, offsetof(struct mchrstr, m_item), "item"},
153     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_lcm), "lcm"},
154     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_hcm), "hcm"},
155     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_gun), "gun"},
156     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_shell), "shell"},
157     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_tech), "tech"},
158     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_cost), "cost"},
159     {NSC_FLOAT, 0, 0, offsetof(struct lchrstr, l_att), "att"},
160     {NSC_FLOAT, 0, 0, offsetof(struct lchrstr, l_def), "def"},
161     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_vul), "vul"},
162     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_spd), "spd"},
163     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_vis), "vis"},
164     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_spy), "spy"},
165     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_rad), "rad"},
166     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_frg), "frg"},
167     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_acc), "acc"},
168     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_dam), "dam"},
169     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_ammo), "ammo"},
170     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_aaf), "aaf"},
171     {NSC_UCHAR, 0, 0, offsetof(struct lchrstr, l_fuelc), "fuelc"},
172     {NSC_UCHAR, 0, 0, offsetof(struct lchrstr, l_fuelu), "fuelu"},
173     {NSC_UCHAR, 0, 0, offsetof(struct lchrstr, l_nxlight), "nxlight"},
174     {NSC_UCHAR, 0, 0, offsetof(struct lchrstr, l_mxland), "mxland"},
175     {NSC_INT, 0, 0, offsetof(struct lchrstr, l_flags), "flags"},
176     {NSC_NOTYPE, 0, 0, 0, NULL}
177 };
178
179 static struct castr nchr_ca[] = {
180     {NSC_STRING, 0, 0, offsetof(struct nchrstr, n_name), "name"},
181     {NSC_INT, 0, 0, offsetof(struct nchrstr, n_lcm), "lcm"},
182     {NSC_INT, 0, 0, offsetof(struct nchrstr, n_hcm), "hcm"},
183     {NSC_INT, 0, 0, offsetof(struct nchrstr, n_oil), "oil"},
184     {NSC_INT, 0, 0, offsetof(struct nchrstr, n_rad), "rad"},
185     {NSC_INT, 0, 0, offsetof(struct nchrstr, n_blast), "blast"},
186     {NSC_INT, 0, 0, offsetof(struct nchrstr, n_dam), "dam"},
187     {NSC_INT, 0, 0, offsetof(struct nchrstr, n_cost), "cost"},
188     {NSC_INT, 0, 0, offsetof(struct nchrstr, n_tech), "tech"},
189     {NSC_INT, 0, 0, offsetof(struct nchrstr, n_weight), "weight"},
190     {NSC_INT, 0, 0, offsetof(struct nchrstr, n_flags), "flags"},
191     {NSC_NOTYPE, 0, 0, 0, NULL}
192 };
193
194 /* Characteristics table meta data */
195 struct camap {
196     char *name;                 /* name for lookup */
197     struct castr *ca;           /* selector descriptors */
198     void *chr;                  /* characteristics table */
199     size_t size;                /* size of characteristics table element */
200 };
201
202 /* Table of characteristics tables */
203 static struct camap chr_camap[] = {
204     {"item", ichr_ca, ichr, sizeof(ichr[0])},
205     {"product", pchr_ca, pchr, sizeof(pchr[0])},
206     {"ship chr", mchr_ca, mchr, sizeof(mchr[0])},
207     {"plane chr", plchr_ca, plchr, sizeof(plchr[0])},
208     {"land chr", lchr_ca, lchr, sizeof(lchr[0])},
209     {"nuke chr", nchr_ca, nchr, sizeof(nchr[0])},
210     {NULL, NULL, NULL, 0}
211 };
212
213 /*
214  * Search chr_camap[] for element named NAME, return its index.
215  * Return M_NOTFOUND if there are no matches, M_NOTUNIQUE if there are
216  * several.
217  */
218 static int
219 chridx_by_name(char *name)
220 {
221     return stmtch(name, chr_camap, offsetof(struct camap, name),
222                   sizeof(chr_camap[0]));
223 }
224
225 /*
226  * Evaluate a attribute of an object into VAL.
227  * TYPE is the attribute's type.
228  * PTR points to the context object.
229  * The attribute is stored there at offset OFF + IDX * S, where S is
230  * its size.
231  */
232 static struct valstr *
233 xdeval(struct valstr *val, nsc_type type, void *ptr, ptrdiff_t off, int idx)
234 {
235     val->val_type = type;
236     val->val_cat = NSC_OFF;
237     val->val_as_type = -1;
238     val->val_as.sym.off = off;
239     val->val_as.sym.idx = idx;
240     nstr_exec_val(val, player->cnum, ptr, 0);
241     return val;                 /* FIXME nstr_exec_val() should return VAL */
242 }
243
244 /* Dump VAL prefixed with SEP, return " ".  */
245 static char *
246 xdprval(struct valstr *val, char *sep)
247 {
248     char *s, *e;
249
250     switch (val->val_type) {
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     }
271     return " ";
272 }
273
274 /*
275  * Dump field values of a context object.
276  * CA[] describes fields.
277  * PTR points to context object.
278  */
279 static void
280 xdflds(struct castr ca[], void *ptr)
281 {
282     int i, j;
283     struct valstr val;
284     char *sep = "";
285
286     for (i = 0; ca[i].ca_name; ++i) {
287         if (ca[i].ca_flags & NSC_DEITY && !player->god)
288             continue;
289         j = 0;
290         do {
291             xdeval(&val, ca[i].ca_type, ptr, ca[i].ca_off, j);
292             sep = xdprval(&val, sep);
293         } while (++j < ca[i].ca_len);
294     }
295 }
296
297 /* Dump field names; CA[] describes fields.  */
298 static void
299 xdfldnam(struct castr ca[])
300 {
301     int i;
302     char *sep = "";
303
304     for (i = 0; ca[i].ca_name; ++i) {
305         if (ca[i].ca_flags & NSC_DEITY && !player->god)
306             continue;
307         pr("%s%s", sep, ca[i].ca_name);
308         if (ca[i].ca_len)
309             pr(" %d", ca[i].ca_len);
310         sep = " ";
311     }
312 }
313
314 /* Dump header for dump NAME with fields described by CA[].  */
315 static void
316 xdhdr(char *name, struct castr ca[])
317 {
318     prdate();
319     pr("DUMP %s %ld\n", name, (long)time(NULL));
320
321     xdfldnam(ca);
322     pr("\n");
323 }
324
325 /* Dump footer for a dump that dumped N objects.  */
326 static void
327 xdftr(int n)
328 {
329     pr("dumped %d\n", n);
330 }
331
332 /*
333  * Dump items of type TYPE selected by ARG.
334  * Return RET_OK on success, RET_SYN on error.
335  */
336 static int
337 xditem(int type, char *arg)
338 {
339     struct castr *ca;
340     struct nstr_item ni;
341     int n;
342     s_char buf[2048];           /* FIXME buffer size? */
343
344     ca = ef_cadef(type);
345     if (!ca)
346         return RET_SYN;
347
348     if (!snxtitem(&ni, type, arg))
349         return RET_SYN;
350
351     xdhdr(ef_nameof(type), ca);
352
353     n = 0;
354     while (nxtitem(&ni, buf)) {
355         if (!player->owner)
356             continue;
357         ++n;
358         xdflds(ca, buf);
359         pr("\n");
360     }
361
362     xdftr(n);
363
364     return RET_OK;
365 }
366
367 /*
368  * Dump characteristics described by chr_camap[IDX].
369  * Return RET_OK on success, RET_SYN if IDX < 0.
370  */
371 static int
372 xdchr(int chridx)
373 {
374     struct camap *cm;
375     char *p;
376     struct valstr val;
377     int n;
378
379     if (chridx < 0)
380         return RET_SYN;
381     cm = &chr_camap[chridx];
382
383     xdhdr(cm->name, cm->ca);
384
385     n = 0;
386     for (p = cm->chr; ; p += cm->size) {
387         val.val_type = cm->ca[0].ca_type;
388         val.val_cat = NSC_OFF;
389         val.val_as_type = -1;
390         val.val_as.sym.off = cm->ca[0].ca_off;
391         val.val_as.sym.idx = 0;
392         nstr_exec_val(&val, player->cnum, p, NSC_STRING);
393         if (!val.val_as.str || !*val.val_as.str)
394             break;
395         ++n;
396         xdflds(cm->ca, p);
397         pr("\n");
398     }
399
400     xdftr(n);
401
402     return RET_OK;
403 }
404
405 /* Experimental extended dump command */
406 int
407 xdump(void)
408 {
409     s_char *p;
410     char buf[1024];
411     int type;
412
413     p = getstarg(player->argp[1], "What? ", buf);
414     if (!p)
415         return RET_SYN;
416
417     type = ef_byname(p);
418     if (type >= 0) {
419         return xditem(type, player->argp[2]);
420     } else if (!strncmp(p, "chr", strlen(p)) && player->argp[2]) {
421         return xdchr(chridx_by_name(player->argp[2]));
422     }
423
424     return RET_SYN;
425 }