From c52a9a28223c570445e9d81d0ed7ad4ee61ab2b7 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Mon, 6 Mar 2006 18:27:37 +0000 Subject: [PATCH] New doc/xdump. --- doc/xdump | 776 +++++++++++++++++++++++++++++++++++++++ src/lib/commands/xdump.c | 30 +- 2 files changed, 793 insertions(+), 13 deletions(-) create mode 100644 doc/xdump diff --git a/doc/xdump b/doc/xdump new file mode 100644 index 000000000..b7caac5cc --- /dev/null +++ b/doc/xdump @@ -0,0 +1,776 @@ +Introduction + +Empire is designed as a smart server with dumb clients. An Empire +client need to know nothing about the game. Even telnet would do. In +fact, emp_client is just as a slightly specialized telnet. + +In such a design, presentation is in the server, and it is designed +for human consumption. Ideally, presentation and logic are cleanly +separated, for easy selection between different presentations. +There's no such separation in the Empire server, and separating them +now would be a herculean effort. + +Thus, smart clients have to work with output designed for humans. +That's not especially hard, just an awful lot of tedious work, and the +result gets easily broken by minor changes in output format, which +humans hardly notice. + +Instead of making smart clients parse output of commands designed for +humans, one can add commands designed for machines. Such commands can +share the code implementing game rules with their counterparts for +humans. To do that cleanly means separating logic and presentation. +Implementing them with their own copy of the code is no good --- how +would you ensure that the two copies implement precisely the same game +rules? + +Except for commands that actually don't do anything. There's a useful +class of such commands: commands to show game configuration and state +without altering it. The only game rules involved are those that +govern who gets to see what. Ensuring that those are satisfied is +tractable. + +Empire has had one such command since the beginning: dump. Empire +4.0.6 added more: sdump, ldump, pdump and ndump. 4.0.7 added lost and +support for incremental dumps. These commands have served smart +clients well. However, they cover just the most important part of the +game state (sectors, ships, planes, land units, nukes), and no game +configuration. They are not quite complete even for what they attempt +to cover. Finally, their output is harder to parse than necessary. + +The xdump command is designed to be the dump to end all dumps. + +Like many good ideas, xdump has secondary uses. Dumping game state as +text can be one half of a game export/import facility. Useful to +migrate games to different machines or even, with some text mangling +perhaps, different server versions. We will see below that xdump +isn't quite sufficient for that, but it's a start. + +If you can import game state, you can import game configuration, or in +other words: customize your game. As we will see, configuration files +have different requirements, which xdump doesn't satisfy without some +extensions. + +If game import code can edit everything, then a deity command capable +of editing everything is possible. Proof-of-concept code exists (not +in the tree yet). + + +Analysis of the data to dump + +Game state consists of a fixed set of table files (sector, ship, ...), +telegram files, and a few miscellaneous files. Game configuration +consists of a fixed set of configuration tables and scalar parameters. + +A table is an ordered set of records (table rows). All records have +the same fields (table columns), which are statically typed. + +Fields may be integers, floating-point numbers, x- or y-coordinates, +symbols and symbol sets encoded as integers in a way specific to the +server version, and character arrays. Configuration table fields may +be pointers to zero-terminated strings, null pointers allowed. No +other pointers occur. Unions do not occur. + + +Requirements analysis + +Requirements: + +* Capable to dump all tables. + +* Can do incremental dumps. + +* Output is text. + +* Output is reasonably compact. + +* Output is trivial to parse. Triviality test: if it's easy in AWK, C + (no lex & yacc, just stdio), Lisp (just reader) and Perl (base + language, no modules), then it's trivial enough. + +* Output identifies itself. + +* Output is self-contained; symbol encoding is explicit. + +* KISS: keep it simple, keep it stupid. + +Non-requirements: + +* Generality. We're not trying to design a general mechanism for + dumping C data. + +* Completeness. We're not trying to dump stuff other than tables. + +* Abstraction. We're not trying to hide how things are stored in the + server. When storage changes, xdump output will change as well, and + consumers need to be updated. This is not because abstraction + wouldn't be nice to have, just because we don't feel up to the task + of designing one. + + +Principles of Design + +Traditional dumps have a dump function for every table. These +functions are simple, but exceedingly dull and repetitive. + +The selector code works differently. Each table has a descriptor, +which among other things defines a dictionary of selector descriptors. +A selector descriptor describes a field (table column) visible to +players. This is what we call meta-data (data about data). The +selector code knows nothing about the individual tables, it just +interprets meta-data. That's smart, as it keeps the dull, repetitive +parts in more easily maintainable meta-data rather than code. + +xdump follows the selector design, and uses the existing selector +meta-data. This requires extending the meta-data to configuration +tables, which weren't previously covered. It also requires some +generalization of selector descriptors, so that all fields can be +covered. + +To sum up, meta-data consists of a table of tables, and for each table +a table of selectors (table of columns, so to speak). It is specific +to the server version and how it is compiled on the host. + +To interpret a table xdump, you need its meta-data, because without it +you have no idea what the columns mean. As meta-data is just a bunch +of tables, xdump can dump it. But now you need meta-meta-data to make +sense of the meta-data. Fortunately, meta-meta-data is the same for +all xdumps, and therefore the recursion terminates with a single +meta-meta-table. + +xdump dumps symbols and symbol sets as integers. To decode them, you +need to know what the symbol numbers and symbol set bits mean. For +this purpose, field meta-data includes the table ID of a symbol table. +A symbol table is a table of value-name pairs, with the value in the +leftmost column. You decode a symbol value by looking it up in the +symbol table. You decode a symbol set value by looking up its bits +(powers of two) in the symbol table. + +Some integer fields are actually keys in other tables. For instance, +ship field type is a key in the table of ship types ship-chr, and +plane field ship is a key in the ship table. Key value -1 is special: +it's a null key. Meta-data encodes these table reference just like +for symbols: the meta-data has the ID of the referenced table, and +that table has the key in the leftmost column. Obviously, that +leftmost column is a table key as well, referencing the table itself. + +A table with its key in the leftmost column can be dumped partially. +Without such a key, you need to count records to find the record +index, and that works only if you can see a prefix of the complete +table. + +The special table "ver" collects all scalar configuration parameters +in a single record. It does not occur in the table of tables. + + +Syntax of xdump command + +See info xdump. + + +The xdump output Language + +Because the output is to be parsed by machines, it needs to be +precisely specified. We use EBNF (ISO 14977) for syntax, except we +use '-' in meta-identifiers and omit the concatenation symbol ','. + + table = header { record } footer ; + header = "XDUMP" space [ "meta" space ] name space timestamp newline ; + name = name-chr { name-chr } ; + name-chr = ? ASCII characters 33..126 ? ; + timestamp = intnum ; + footer = "/" number newline ; + record = [ fields ] newline ; + fields = field { space field } ; + field = intnum | flonum | string ; + intnum = ? integer in printf %d format ? ; + flonum = ? floating-point in printf %g format ? ; + string = "nil" + | '"' { str-char } '"' ; + str-char = "\\" octal-digit octal-digit octal-digit + | ? ASCII characters 33..126 except '"' and '\\' ? ; + octal-digit = ? '0'..'7' ? ; + space = ' ' ; + newline = ? ASCII character 10 ? ; + +Notes: + +* The syntax for flonum is debatable. Precise conversion between + floating-point and decimal is hard, and C libraries are not required + to be precise. Using C99's %a format for flonum would avoid the + issue, but some programming environments may have trouble converting + that back to floating-point. We may change to %a anyway in the + future. Clients are advised to accept both. + +* Strings syntax could perhaps profit from the remaining C escape + sequences. Except for '\"': adding that would complicate regular + expressions matching the string, and thus violate the `trivial to + parse' requirement + +* Space is to be taken literally: a single space character. Not a + non-empty sequence of whitespace. + +Semantics: + +* The table name in the header is one of the names in xdump table. + +* The timestamp increases monotonically. It has a noticeable + granularity: game state may change between an xdump and the next + timestamp increase. If the table has a timestamp field, clients can + xdump incrementally by using a conditional ?timestamp>T, where T is + one less than the timestamp received with the last xdump of that + table. + + Timestamp values are currently seconds since the epoch, but this + might change, and clients are advised not to rely on it. + +* The number in the footer matches the number of records. + +* Fields match their meta-data (see Meta-Data below). + +* "nil" represents a null string (which is not the same as an empty + string). Otherwise, fields are to be interpreted just like C + literals. + + +Meta-Data + +Table meta-data is in xdump table. Fields: + +* uid: The table ID, key for xdump table. IDs depend on the server + version; clients should not hard-code them. This is the leftmost + field. + +* name: The table name. Clients may identify tables by name. + +Field meta-data for table T is in xdump meta T. The order of fields +in the xdump T matches the order of records in xdump meta T. Fields +of xdump meta T are: + +* name: The field name. Matches the selector name. Clients may + identify fields by name. This is the leftmost field. + +* type: The field's data type, a symbol. Clients should use this only + as key for the symbol table. Symbols are: + - "d", field uses intnum syntax + - "g", field uses flonum syntax + - "s", field uses string syntax + - "c", field uses string syntax + +* flags: The field's flags, a symbol set. Flags are: + - "deity", field visible only to deities + - "extra", field not to be dumped + - "const", field cannot be changed (see xundump below) + - "bits", field is a symbol set, field type must encode symbol "d", + field table must not be -1. + +* len: If non-zero, then the record encodes an array with that many + elements. If field type encodes symbol "c", it is a character + array, which is dumped as a single string field. Else, the array is + dumped as len fields. + +* table: Key for xdump table. Unless -1, it defines the table + referenced by the field value. Field type must encode symbol "d" + then. + +Symbol table fields: + +* value: The symbol's encoding as integer. If the symbol can be + element of a symbol set, this is a power of two. + +* name: The symbol's name. + + +Notes on xdump Implementation + +Overall impact on the server code is low. + +To keeps xdump simple, storage of game state and game configuration +tables has been unified under the common empfile abstraction, making +nxtitem-iterators and selectors equally applicable to all tables. + +xdump required a few extensions to meta-data, which may become useful +in other places as well: + +* Selectors can now deal with arrays (revived struct castr member + ca_len). Not yet available on the Empire command line. + +* Selector meta-data can now express that a selector value is a key + for another table (new struct castr member ca_table). The selector + code doesn't use that, yet. + +* Selector flag NSC_EXTRA to flag redundant selectors, so that xdump + can ignore them. + +Meta-data is in empfile[] (table meta-data), src/lib/global/nsc.c +(selector meta-data), src/lib/global/symbol.c (symbol tables). The +command is in src/lib/commands/xdump.c, unsurprisingly. + + +Hints on Using xdump in Clients + +Let's explore how to dump a game. To make sense of a table, we need +its meta-data, and to make sense of that table, we need meta-meta +data. So we start with that: + + [14:640] Command : xdump meta meta + XDUMP meta meta 1139555204 + "name" 3 4 0 -1 + "type" 5 4 0 32 + "flags" 6 12 0 33 + "len" 8 4 0 -1 + "table" 9 4 0 -1 + /5 + +To interpret this table, we have to know the field names and their +meanings. Clients hard-code them. They should be prepared to accept +and ignore additional fields, and to cope with changes in field order, +except they may rely on "name" coming first. + +A word on hard-coding. Clients hard-code *names*. The numbers used +for table IDs and to encode symbols are none of the client's business. + +The encoding doesn't normally change within a game. Except when the +game is migrated to a sufficiently different server. That's a +difficult and risky thing to do, especially as there are no tools to +help with migrating (yet). Clients may wish to provide for such +changes anyway, by decoupling the client's encoding from the server's, +and dumping fresh meta-data on login. Incremental meta-data dump +would be nice to have. + +So we don't know how symbol type and symbol set flags are encoded. To +decode them, we need their symbol tables. However, we need flags and +type only for tables we don't know, and there's one more table we do +know, namely the table of tables. Let's dump that next, starting with +its meta-data: + + [31:640] Command : xdump meta table + XDUMP meta table 1139556230 + "uid" 9 0 0 26 + "name" 3 4 0 -1 + /2 + +Because xdump table is referenced from elsewhere (xdump meta meta +field table), the leftmost field must contain the key. Thus, the +leftmost field's meta-data field table must be the table ID of xdump +table itself. Let's try it: + + [30:640] Command : xdump 26 * + XDUMP table 1139556210 + 0 "sect" + 1 "ship" +[...] + 9 "nat" +[...] + 16 "sect-chr" + 17 "ship-chr" +[...] + 26 "table" +[...] + /45 + +It worked! Mind that the special table "ver" is not in the table of +tables. + +Now dump the two symbol tables we postponed. Because xdump accepts +table IDs as well as names, we don't have to know their names: + + [14:640] Command : xdump meta 32 + XDUMP meta meta-type 1139555298 + "value" 9 4 0 -1 + "name" 3 0 0 -1 + /2 + + [15:640] Command : xdump 32 * + XDUMP meta-type 1139555826 + 1 "d" + 2 "g" + 3 "s" + 4 "d" + 5 "d" + 6 "d" + 7 "d" + 8 "d" + 9 "d" + 10 "d" + 11 "d" + 12 "d" + 13 "g" + 14 "c" + /14 + + [15:640] Command : xdump meta 33 + XDUMP meta meta-flags 1139555303 + "value" 9 4 0 -1 + "name" 3 0 0 -1 + /2 + + [24:640] Command : xdump 33 * + XDUMP meta-flags 1139555829 + 1 "deity" + 2 "extra" + 4 "const" + 8 "bits" + /4 + +We now have complete meta-meta information: + + name type flags len table + ----------------------------------------- + name s (const) 0 + type d (const) 0 meta-type + flags d (bits const) 0 meta-flags + len d (const) 0 + table d (const) 0 + +Dumping the remaining tables is easy: just walk the table of tables. +Here's the first one: + + [36:640] Command : xdump meta 0 + XDUMP meta sect 1139556498 + "owner" 6 0 0 9 + "xloc" 10 0 0 -1 + "yloc" 11 0 0 -1 + "des" 4 0 0 16 +[...] + /69 + +A whole load of tables referenced! Only one of them (not shown above) +is a symbol table. + +owner references table nat. No surprise. + +xloc and yloc together reference the sector table, but that's not +expressed in meta-data (yet). + +Let's stop here before this gets too long and boring. Experiment +yourself! Check out example Perl code src/xdump.pl. + + +Analysis of xdump as Configuration File Format + +xdump makes a lousy configuration format because it is unwieldy to +edit for humans. That's because configuration files have different +requirements than dumps: + +* Can be edited by humans with common tools, including text editors + and spreadsheets. + + Using text editors requires a nice fixed-width table layout. + Spreadsheet import requires trivial field separation. Tab character + field separator or fixed width columns should do. The syntax should + allow all that, but not require it. + + Trouble spots: + + - xdump's rigid horizontal and vertical spacing makes it impossible + to align things visually. + + - xdump uses one line per record, which can lead to excessively long + lines. + + - xdump's string syntax requires octal escape for space. + + - No comment syntax. + +* Each table is self-contained. You don't have to look into other + tables to make sense of it. + + This conflicts with xdump's separation of data and meta-data. You + need the table's meta-data to identify fields, and the referenced + symbol tables to decode symbols. + +* Easy to parse. Don't compromise legibility just to please some dumb + tool, though. + +Since we're trying to apply xdump to the configuration file problem, +we get an additional requirement: + +* Reasonably close to xdump. Translation between machine-readable and + human-readable should be straightforward, if meta-data is available. + +This leads to a human-readable dialect of the xdump language. + + +Human-Readable xdump Language + +Fundamental difference to basic, machine-readable xdump: the rigid +single space between fields is replaced by the rule known from +programming languages: whitespace (space and tab) separates tokens and +is otherwise ignored. The space non-terminal is no longer needed. + +Rationale: This allows visual alignment of columns and free mixing of +space and tab characters. + +Comments start with "#" and extend to the end of the line. They are +equivalent to a newline. + +Rationale: Follow econfig syntax. + +Tables with a record uid in the leftmost field can be `split +vertically' into multiple parts. Each part must contain the same set +of records. The leftmost field must be repeated in each part. Other +fields may be repeated. Repeated fields must be the same in all +parts. Naturally, the parts together must provide the same fields as +a table that is not split. + +Rationale: This is the cure for long lines. Line continuation would +be simpler, but turns out to be illegible. Requiring record uid is +not technically necessary, as counting records works the same whether +a table is split or not. Except humans can't count. Perhaps this +should be a recommendation for use rather than part of the language. + +EBNF changes: + +* Header and footer: + + header = "config" name newline { colhdr } newline ; + colhdr = identifier [ "(" ( intnum | identifier ) ")" ] [ "..." ] ; + footer = "/config" newline ; + + If colhdr ends with "...", the table is continued in another part, + which shall follow immediately. + + Rationale: + + - The xdump needs to identify itself as human-readable, hence change + from "XDUMP" to "config". + + - The timestamp in the header is useless for the applications we + have in mind for human-readable xdumps. The number of records in + the footer is of marginal value at best, and a pain for humans to + update. + + - The column header is due to the self-containedness requirement. + It contains just the essential bit of meta-data: the column name. + +* Symbolic fields: + + field = intnum | flonum | string | symbol | symset ; + + Rationale: + + - Syntax for symbols and sets of symbols is due to the + self-containedness requirement. Machine-readable xdump gets away + with just numbers, which have to be decoded using meta-data. + +* Friendlier numbers and strings: + + flonum = ? floating-point in scanf %g format ? ; + str-char = "\\" octal-digit octal-digit octal-digit + | ? ASCII characters 32..126 except '"' and '\\' ? ; + + Rationale: + + - Machine-readable floating-point syntax is too rigid. Accept + everything that scanf does. Could also change intnum to %i + format, which accepts octal and hexadecimal in C syntax, but that + seems not worth the documentation bother. + + - Machine-readable syntax requires \040 instead of space in strings + to allow trivial splitting into fields. This is unacceptable here + due to the legibility requirement, hence the change to str-char. + +* Parse nil as symbol: + + string = '"' { str-char } '"' ; + + Rationale: This is a technicality required to keep the parse + unambiguous. + +* Symbols: + + symbol = identifier ; + symset = "(" { symbol } ")" ; + + The special symbol "nil" is to be interpreted as null string. + + Rationale: + + - The symbol set syntax is the simplest that could work. We need to + allow space between the symbols for legibility anyway, so why not + make it the delimiter. A stop token is required to find the end + of the field, and a start token is useful for distinguishing + between symbol and symset. Bracketing with some kind of + parenthesis is an obvious solution. + +The resulting sub-language for records is a superset of +machine-readable sub-language for records. + + +See src/lib/global/*.config for examples. + +Human-readable xdump still has its shortcomings: + +* Symbolic references work only with symbol tables. Consider sect-chr + selector prd, which is a key for table product. xdump should + support use of product selector sname values as keys. Same for + product selectors ctype and type, which should support item selector + mnem values as keys. + +* item selector pkg is an array indexed by values in symbol table + packing. The column header should support symbolic index values + rather than numbers. + + +Notes on Table Configuration Implementation + +econfig key custom_tables lists table configuration files. At this +time, reading a custom table merges it with the built-in table, then +truncates the result after the last record read from the custom table. + +Some of the tables are rather ugly in C, and cumbersome to edit. We +thus moved them to configuration files (src/lib/global/*.config). The +server reads them from builtindir before reading custom tables. + +The code dealing with these files is in src/lib/common/conftab.c. + +Actual work is done by src/lib/common/xundump.c, which accepts both +human-readable and machine-readable input. The parser is not precise; +it accepts human-readable syntax even within tables whose header marks +them machine-readable. + +Configuration tables contain values that are not meant to be +customized. For instance, meta-data and symbol tables reflect the +encoding of C language constructs in the server. Selector flag +NSC_CONST marks them, so that the code can prohibit changes. + +All tables are checked against meta-data on server startup by +ef_verify(). More elaborate checking would be nice, and probably +requires additional meta-data. + + +Appendix: Empire 3 C_SYNC --- A Cautionary Tale + +Clients are just as important as the server, and it's too darn hard to +write a good client. In 1995, Ken Stevens decided to do something +about it. + +Ken cast the problem as a data synchronization problem. Quote C_SYNC +RFC 5.1, section `Abstract': + + This is a specification for a new method of synchronizing game data + in the Empire client with data in the server. + +and section `Objectives': + + This new mode of communication between the server and the client will + be called C_SYNC communication and will satisfy the following 6 + criterea: + + (1) Output format will be version independent. So if someone is + using an old EmpireToolkit, then it will still work with a newer + version of the server. + + (2) Every C_SYNC message will be a self-contained packet. i.e. the + client will not need to depend on previous messages (header messages) + to determine the meaning of a C_SYNC message. + + (3) A C_SYNC message will be able to represent any of the + player-accessible data that is contained in the server database (e.g. + enemy ships, nations). + + (4) Bandwidth will be minimized (i.e. the format will be as + concise as possible) while remaining human readable (i.e. no + binary messages). [Note that data compression may be added at a later + date, but if it is added, it will be added on a separate port to + maintain backwards compatability.] + + (5) The client will be able to tell the server whether it wants + to receive C_SYNC messages and whether these messages can be sent + asynchroniously (via "toggle sync" and "toggle async" respectively). + + (6) A portable ANSI C EmpireToolkit will be made available for + parsing C_SYNC messages and managing the data they contain. + +C_SYNC worked by hooking into ef_write() & friends so it could +`synchronize' the client on game state changes. + +Sounds jolly good, doesn't it? + +Well, it was a failure, and Wolfpack ripped it out right away. Quote +the change log: + + Changes to Empire 4.0.0 - Initial release + * Initial Wolfpack release - Long live the Wolfpack!!!! +[...] + * Removed C_SYNC. This is done for 2 reasons. 1) None of us like it or + wish to support it. 2) We envision a better scheme for doing similar + things will come along. + +But *why* did it fail? Just because Steve McClure hated it? Nope. +C_SYNC failed for several different reasons, each of them bad, but +only the last one is truly fundamental. + +a. Lack of a rigorous and complete definition. The RFC is long on + syntax, but short on semantics. For instance, the unit type was + encoded as a number. Unit characteristics happened to be dumped in + an order that matched these numbers, but that wasn't defined + anywhere. + +b. Overly complicated syntax. Trouble with encoding of strings. + +c. Buggy implementation. Malformed C_SYNC messages, duplicate + messages, missing messages, semantically incorrect messages, you + name it. + +d. Change of crew before it was finished. Wolfpack took over and + understandable wasn't interested in this half-finished mess. + +None of the above is a fundamental, inherent flaw of the idea. The +next one is more serious: + +e. It failed to achieve objective (4), and therefore slowed down + clients too much to be of use in real-time combat. When you fired + from a bunch of ships, C_SYNC would push complete records for all + the ships and the target to you. Most of that data is redundant. + + That's because C_SYNC didn't transmit state changes, it + resynchronized state, and the pieces of state it could transmit + were too large. + + The network was slower then. But let's not be complacent. I/O is + slow. Always was, most likely ever will be. + + Maybe sending the messages out of band (separate TCP stream) would + help. Maybe not. + +And here comes the killer: + +f. The data to sync is not readily available the server. + + Yup. Think about it. The game state on the server is *not* the + same as on the client. The server grants the client a carefully + limited view on certain parts of server game state on certain + events. + + To be complete, a machine readable protocol must disclose as much + information as the human readable output. Tracking server game + state changes cannot do that alone. For instance, lookout tells + you ship#, owner and location. That event does not trigger any + state change on the server! + + To be correct, a machine readable protocol must disclose no more + information than the human readable output. When you observe a + server game state change, you can only guess what event triggered + it, and what it disclosed to which player. You're stuck with + conservative assumptions. That's the death knell for completeness. + Correct assumptions will be non-obvious, so correctness is + non-obvious, too, hence hard to achieve and maintain. + + Bottom line: tracking server state change cannot support a complete + client protocol for hard theoretical reasons, and I believe it + cannot support a correct one for practical reasons. + +Oddly enough, people criticized C_SYNC for all the flaws it had (and +some it hadn't), except for f. + +What now? Throw up our hands in despair and give up? Nah. Ken tried +a shortcut, and it didn't work. That doesn't mean there's no way at +all. I believe the only way to get this done right is by tracking +*events*. Whenever something is printed to a player, be it live +connection or telegram, we need to transmit precisely the same +information in machine readable form. Much more work. + +xdump shares valuable ideas with C_SYNC, e.g. using selector +meta-data. It is, however, much more modest in scope. We're pretty +sure we can get it right and get it done in a reasonable time frame. diff --git a/src/lib/commands/xdump.c b/src/lib/commands/xdump.c index 26fa5c170..430089a03 100644 --- a/src/lib/commands/xdump.c +++ b/src/lib/commands/xdump.c @@ -31,18 +31,6 @@ * Markus Armbruster, 2004-2006 */ -#include - -#include -#include "misc.h" -#include "file.h" -#include "match.h" -#include "news.h" -#include "nsc.h" -#include "optlist.h" -#include "version.h" -#include "commands.h" - /* * Dump everything under the sun * @@ -77,9 +65,25 @@ * - Market: EF_COMM */ -/* FIXME document dump format */ +/* + * See doc/xdump for motivation, syntax, semantics, and rationale. + * Make sure to keep it up-to-date! + */ + /* TODO don't dump stuff that's useless due to options */ +#include + +#include +#include "misc.h" +#include "file.h" +#include "match.h" +#include "news.h" +#include "nsc.h" +#include "optlist.h" +#include "version.h" +#include "commands.h" + /* * Evaluate a attribute of an object into VAL, return VAL. * TYPE is the attribute's type. -- 2.43.0