]> git.pond.sub.org Git - empserver/blob - src/lib/commands/xdump.c
(NSC_EXTRA): New.
[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         if (ca[i].ca_flags & NSC_EXTRA)
293             continue;
294         j = 0;
295         do {
296             xdeval(&val, ca[i].ca_type, ptr, ca[i].ca_off, j);
297             sep = xdprval(&val, sep);
298         } while (++j < ca[i].ca_len);
299     }
300 }
301
302 /* Dump field names; CA[] describes fields.  */
303 static void
304 xdfldnam(struct castr ca[])
305 {
306     int i;
307     char *sep = "";
308
309     for (i = 0; ca[i].ca_name; ++i) {
310         if (ca[i].ca_flags & NSC_DEITY && !player->god)
311             continue;
312         if (ca[i].ca_flags & NSC_EXTRA)
313             continue;
314         pr("%s%s", sep, ca[i].ca_name);
315         if (ca[i].ca_len)
316             pr(" %d", ca[i].ca_len);
317         sep = " ";
318     }
319 }
320
321 /* Dump header for dump NAME with fields described by CA[].  */
322 static void
323 xdhdr(char *name, struct castr ca[])
324 {
325     prdate();
326     pr("DUMP %s %ld\n", name, (long)time(NULL));
327
328     xdfldnam(ca);
329     pr("\n");
330 }
331
332 /* Dump footer for a dump that dumped N objects.  */
333 static void
334 xdftr(int n)
335 {
336     pr("dumped %d\n", n);
337 }
338
339 /*
340  * Dump items of type TYPE selected by ARG.
341  * Return RET_OK on success, RET_SYN on error.
342  */
343 static int
344 xditem(int type, char *arg)
345 {
346     struct castr *ca;
347     struct nstr_item ni;
348     int n;
349     s_char buf[2048];           /* FIXME buffer size? */
350
351     ca = ef_cadef(type);
352     if (!ca)
353         return RET_SYN;
354
355     if (!snxtitem(&ni, type, arg))
356         return RET_SYN;
357
358     xdhdr(ef_nameof(type), ca);
359
360     n = 0;
361     while (nxtitem(&ni, buf)) {
362         if (!player->owner)
363             continue;
364         ++n;
365         xdflds(ca, buf);
366         pr("\n");
367     }
368
369     xdftr(n);
370
371     return RET_OK;
372 }
373
374 /*
375  * Dump characteristics described by chr_camap[IDX].
376  * Return RET_OK on success, RET_SYN if IDX < 0.
377  */
378 static int
379 xdchr(int chridx)
380 {
381     struct camap *cm;
382     char *p;
383     struct valstr val;
384     int n;
385
386     if (chridx < 0)
387         return RET_SYN;
388     cm = &chr_camap[chridx];
389
390     xdhdr(cm->name, cm->ca);
391
392     n = 0;
393     for (p = cm->chr; ; p += cm->size) {
394         val.val_type = cm->ca[0].ca_type;
395         val.val_cat = NSC_OFF;
396         val.val_as_type = -1;
397         val.val_as.sym.off = cm->ca[0].ca_off;
398         val.val_as.sym.idx = 0;
399         nstr_exec_val(&val, player->cnum, p, NSC_STRING);
400         if (!val.val_as.str || !*val.val_as.str)
401             break;
402         ++n;
403         xdflds(cm->ca, p);
404         pr("\n");
405     }
406
407     xdftr(n);
408
409     return RET_OK;
410 }
411
412 /* Experimental extended dump command */
413 int
414 xdump(void)
415 {
416     s_char *p;
417     char buf[1024];
418     int type;
419
420     p = getstarg(player->argp[1], "What? ", buf);
421     if (!p)
422         return RET_SYN;
423
424     type = ef_byname(p);
425     if (type >= 0) {
426         return xditem(type, player->argp[2]);
427     } else if (!strncmp(p, "chr", strlen(p)) && player->argp[2]) {
428         return xdchr(chridx_by_name(player->argp[2]));
429     }
430
431     return RET_SYN;
432 }