libdoom-umapinfo
1.0.0
Parser for Doom UMAPINFO data
|
Parser for Doom UMAPINFO data ============================= This library provides a parser for Doom UMAPINFO data. Official specification: <https://github.com/kraflab/umapinfo/blob/master/docs/spec.md> This library uses a liberal interpretation of the specification that requires no special formating or whitespace between the tokens. The implemented syntax is formally defined in the file "SYNTAX". The development goals of this implementation are: - C90 conformance - Error tolerance General ------- The MAPINFO lump describes meta-data associated with levels (such as their name, music, sky texture, par time, etc.): <https://doomwiki.org/wiki/MAPINFO> Different Doom source ports have adopted different MAPINFO systems. UMAPINFO seeks to mitigate this problem by being a cross-port standard. API --- This library occupies the namespaces with "doom_umi1_" and "DOOM_UMI1_" prefix. The namespaces with "doom_umi1_i_" and "DOOM_UMI1_I_" prefix are reserved for internal use, never use it outside of the library (the shared library may not even export such symbols). Public data types of this library do not use the suffix "_t", because it is reserved by POSIX for all header files: <https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html> (Section 2.2.2) See HTML documentation of this library for API details and error codes. Error handling -------------- The API uses return values to indicate success or error. The return value zero means success, negative values indicate an error. Positive values are reserved for future use and should not be treated as errors for this major version. In general errors are reported to the caller without internal handling. Eample: To check a negative return value for "out of memory" condition, use (DOOM_UMI1_ERR_MEMORY == retval). Some fatal errors can be internally handled via assert(). Such errors, like internal data corruption, indicate bugs in the library or the calling program. For maximum performance internal checks can be disabled with: CPPFLAGS=-DNDEBUG The build system of the library does not set this option by default. Versioning scheme ----------------- The release version contains 3 numbers "x.y.z": - Major (x) The major number is incremented for every API/ABI change that is not backward compatible. - Minor (y) The minor number is incremented for API/ABI extensions that are backward compatible. - Patch (z) The patch number is incremented for changes that don't modify the API/ABI. In other words: Releases with the same major and minor numbers are drop-in replacements. Up- and downgrades between such versions are possible without touching programs that use the library. Releases with the same major, but different minor numbers are backward, but not forward compatible. Upgrades are possible, downgrades can break programs that use the library. Releases with different major numbers require changes in all programs that use the library. Versions with different major numbers can be installed in parallel (including header files). Binaries can be linked against multiple instances of the library with different major versions (no problem if dependencies are using different major versions). Thread safety ------------- The doom_umi1_create(), doom_umi1_destroy() and doom_umi1_register_mmanager() API functions are not thread-safe. All other API functions are thread-safe. This means that importing multiple UMAPINFO lumps simultaneously is not supported, but simultaneous access to existing data objects is allowed. Known bugs ---------- Lexer: - The code generated by flex allocates memory for internal structures of the lexer. If the memory allocation fails, the generated code directly calls exit(). This means the library cannot handle such errors gracefully by returning the error code DOOM_UMI1_ERR_MEMORY from doom_umi1_create(). Parser: - Some memory is not freed by doom_umi1_destroy() function after "make regen". Berkeley yacc must be compiled with "--disable-leaks" option to fix this. The distibuted code is generated with this option enabled. EOF
Syntax for UMAPINFO Rev 2.2 =========================== Based on UMAPINFO specification: <https://github.com/kraflab/umapinfo/blob/master/docs/spec.md> Changelog for older revisions: <https://doomwiki.org/wiki/UMAPINFO#Revisions> No encoding for the data is defined, therefore the specification is interpreted as US-ASCII according to RFC 20: <https://www.rfc-editor.org/rfc/rfc20> Unfortunately the UMAPINFO specification provides no formal syntax definition. The following, inofficial syntax is accepted by the parser of this library. It uses ABNF notation according to RFC 5234: <https://www.rfc-editor.org/rfc/rfc5234> Note: Generators should always use a conservative, human readable subset (that follows the example in the specification). The data is processed by this library as octet stream with arbitrary terminal values. This means that all octets are supported inside quoted strings (except the delimiting double quote itself). The C data type "unsigned int" is used by this library for the nonterminal symbol <number>. This means the accepted range is at least 0...2^16-1. Note that <white_space> contains all C0 control characters and is optional. Toplevel map list ----------------- umapinfo_list = *map ; Empty list is valid map = [white_space] "MAP" [white_space] map_name data_block white_space = 1*(CTL / SP) ; CTL and SP from RFC 5234 Appendix B map_name = map_name_doom1 | map_name_doom2 map_name_doom1 = "MAP" number map_name_doom2 = "E" number "M" number number = 1*DIGIT ; DIGIT from RFC 5234 Appendix B Data block associated with each map list entry ---------------------------------------------- data_block = [white_space] obrace expr_list cbrace [white_space] obrace = %x7B ; Opening brace cbrace = %x7D ; Closing brace expr_list = *assign_expr ; Empty list is valid assign_expr = [white_space] keyword equal value_list [white_space] keyword = "levelname" / "label" / "author" / "levelpic" / "next" / "nextsecret" / "skytexture" / "music" / "exitpic" / "enterpic" / "partime" / "endgame" / "endpic" / "endbunny" / "endcast" / "nointermission" / "intertext" / "intertextsecret" / "interbackdrop" / "intermusic" / "episode" / "bossaction" equal = [white_space] %x3D [white_space] value_list = value *(comma value) ; Empty list is invalid value = string / number / identifier comma = [white_space] %x2C [white_space] Values for keys --------------- string = 1*quoted_string ; Concatenation is allowed quoted_string = DQUOTE *string_octet DQUOTE ; DQUOTE from RFC 5234 Appendix B string_octet = %x00-21 / %x23-FF ; All octets except DQUOTE identifier = "true" / "false" / "clear" / thing_type Thingtypes ---------- thing_type = "DoomPlayer" / "ZombieMan" / "ShotgunGuy" / "Archvile" / "ArchvileFire" / "Revenant" / "RevenantTracer" / "RevenantTracerSmoke" / "Fatso" / "FatShot" / "ChaingunGuy" / "DoomImp" / "Demon" / "Spectre" / "Cacodemon" / "BaronOfHell" / "BaronBall" / "HellKnight" / "LostSoul" / "SpiderMastermind" / "Arachnotron" / "Cyberdemon" / "PainElemental" / "WolfensteinSS" / "CommanderKeen" / "BossBrain" / "BossEye" / "BossTarget" / "SpawnShot" / "SpawnFire" / "ExplosiveBarrel" / "DoomImpBall" / "CacodemonBall" / "Rocket" / "PlasmaBall" / "BFGBall" / "ArachnotronPlasma" / "BulletPuff" / "Blood" / "TeleportFog" / "ItemFog" / "TeleportDest" / "BFGExtra" / "GreenArmor" / "BlueArmor" / "HealthBonus" / "ArmorBonus" / "BlueCard" / "RedCard" / "YellowCard" / "YellowSkull" / "RedSkull" / "BlueSkull" / "Stimpack" / "Medikit" / "Soulsphere" / "InvulnerabilitySphere" / "Berserk" / "BlurSphere" / "RadSuit" / "Allmap" / "Infrared" / "Megasphere" / "Clip" / "ClipBox" / "RocketAmmo" / "RocketBox" / "Cell" / "CellPack" / "Shell" / "ShellBox" / "Backpack" / "BFG9000" / "Chaingun" / "Chainsaw" / "RocketLauncher" / "PlasmaRifle" / "Shotgun" / "SuperShotgun" / "TechLamp" / "TechLamp2" / "Column" / "TallGreenColumn" / "ShortGreenColumn" / "TallRedColumn" / "ShortRedColumn" / "SkullColumn" / "HeartColumn" / "EvilEye" / "FloatingSkull" / "TorchTree" / "BlueTorch" / "GreenTorch" / "RedTorch" / "ShortBlueTorch" / "ShortGreenTorch" / "ShortRedTorch" / "Stalagtite" / "TechPillar" / "CandleStick" / "Candelabra" / "BloodyTwitch" / "Meat2" / "Meat3" / "Meat4" / "Meat5" / "NonsolidMeat2" / "NonsolidMeat4" / "NonsolidMeat3" / "NonsolidMeat5" / "NonsolidTwitch" / "DeadCacodemon" / "DeadMarine" / "DeadZombieMan" / "DeadDemon" / "DeadLostSoul" / "DeadDoomImp" / "DeadShotgunGuy" / "GibbedMarine" / "GibbedMarineExtra" / "HeadsOnAStick" / "Gibs" / "HeadOnAStick" / "HeadCandles" / "DeadStick" / "LiveStick" / "BigTree" / "BurningBarrel" / "HangNoGuts" / "HangBNoBrain" / "HangTLookingDown" / "HangTSkull" / "HangTLookingUp" / "HangTNoBrain" / "ColonGibs" / "SmallBloodPool" / "BrainStem" / "PointPusher" / "PointPuller" / "MBFHelperDog" / "PlasmaBall1" / "PlasmaBall2" / "EvilSceptre" / "UnholyBible" / "MusicChanger" / deh_actor deh_actor = "Deh_Actor_" deh_num deh_num = (%x31 %x34 %x35-39) / (%x31 %x35-39 %x30-39) / (%x32 %x30-34 %x30-39) ; DEH actor number range: 145-249 EOF