## Created by Anjuta
if TARGET_ILIAD
-SUBDIRS = libchimara interpreters babel player po
+SUBDIRS = libchimara interpreters player po
else
-SUBDIRS = libchimara interpreters babel player tests docs po
+SUBDIRS = libchimara interpreters player tests docs po
endif
chimaradocdir = $(datadir)/doc/chimara
+++ /dev/null
-adrift.c Treaty of Babel module for Adrift\r
-advsys.c Treaty of Babel module for AdvSys\r
-alan.c Treaty of Babel module for Alan\r
-agt.c Treaty of Babel module for AGT\r
-babel.h babel program header\r
-md5.h L. Peter Deutsch's md5 header\r
-modules.h babel module registry\r
-treaty.h Treaty of Babel header\r
-treaty_builder.h Macros to build treaty modules\r
-babel.c Babel main program\r
-babel_handler.h Babel handler header file\r
-babel_handler.c The babel handler api\r
-babel_ifiction_functions.c Babel program-specific ifiction operations\r
-babel_multi_functions.c Babel program-specific multi operations\r
-babel_story_functions.c Babel program-specific story operations\r
-blorb.c babel handler blorb module\r
-executable.c Treaty of Bable module for executables \r
-glulx.c Treaty of Babel module for glulx\r
-hugo.c Draft Treaty of Babel module for hugo\r
-ifiction.h babel ifiction header\r
-ifiction.c babel ifiction api\r
-level9.c Treaty of Babel module for level9\r
-magscrolls.c Magnetic Scrolls treaty module\r
-makefile Provisional makefile\r
-md5.c L. Peter Deutsch's md5 implementation\r
-misc.c babel memory allocator\r
-register.c babel module registry\r
-register_ifiction.c babel module registry for ifiction API\r
-tads.h Prototypes for tads2.c and tads3.c\r
-tads.c Common functions for TADS modules\r
-tads2.c Treaty of Babel module for tads2\r
-tads3.c Treaty of Babel module for tads3\r
-zcode.c Treaty of Babel module for zcode\r
-README documentation\r
-MANIFEST this file\r
-extras/babel-cache.pl Perl demo of babel interaction\r
-extras/babel-infocom.pl Special bundler for the infocom corpus\r
-extras/babel-list.c Babel API demo\r
-extras/babel-marry.pl Perl simple blorb encapsulator\r
-extras/babel-wed.pl Perl single file blorb encapsulator\r
-extras/hotload.c Dynamic loader replacement for register.c\r
-extras/hotload.h Header file for hotload.c\r
-extras/ifiction-aggregate.c Utility to combine multiple ifiction files\r
-extras/ifiction-xtract.c Ifiction API demo\r
-extras/simple-marry.c Simplified C version of babel-marry\r
-babel-get/babel-get.c The babel-get application\r
-babel-get/get_dir.c Directory source\r
-babel-get/get_ifiction.c ifiction source\r
-babel-get/get_story.c story file source\r
-babel-get/get_url.c URL source\r
-babel-get/makefile Makefile for babel-get\r
+++ /dev/null
-noinst_LTLIBRARIES = libbabel.la libifiction.la libbabel_functions.la
-
-libbabel_la_SOURCES = babel_handler.c \
- register.c \
- misc.c \
- md5.c \
- zcode.c \
- magscrolls.c \
- blorb.c \
- glulx.c \
- hugo.c \
- agt.c \
- level9.c \
- executable.c \
- advsys.c \
- tads.c \
- tads2.c \
- tads3.c \
- adrift.c \
- alan.c \
- babel.h \
- babel_handler.h \
- md5.h \
- modules.h \
- tads.h \
- treaty_builder.h \
- treaty.h
-
-libifiction_la_SOURCES = ifiction.c ifiction.h \
- register_ifiction.c
-
-libbabel_functions_la_SOURCES = babel_story_functions.c \
- babel_ifiction_functions.c \
- babel_multi_functions.c
-
--include $(top_srcdir)/git.mk
+++ /dev/null
-Version 0.2b, Treaty of Babel Revision 7\r
-This is the source code for babel, the Treaty of Babel analysis tool.\r
-\r
-Most of this code is (c) 2006 by L. Ross Raszewski\r
-\r
-The following files are public domain:\r
-zcode.c\r
-glulx.c\r
-executable.c\r
-level9.c\r
-magscrolls.c\r
-agt.c\r
-hugo.c\r
-advsys.c\r
-misc.c\r
-alan.c\r
-adrift.c\r
-treaty.h\r
-treaty_builder.h\r
-\r
-The following files are Copyright (C) 1999, 2000, 2002 Aladdin Enterprises:\r
-md5.c\r
-md5.h\r
-\r
-And are used in accordance with their licenses.\r
-\r
-All other files are (c) 2006 by L. Ross Raszewski and are released under\r
-the Creative Commons Attribution2.5 License.\r
-\r
-To view a copy of this license, visit\r
-http://creativecommons.org/licenses/by/2.5/ or send a letter to\r
-\r
-Creative Commons,\r
-543 Howard Street, 5th Floor,\r
-San Francisco, California, 94105, USA.\r
-\r
-\r
-To build babel:\r
-\r
-1. compile all the source files in this directory\r
-2. link them together\r
-3. the end\r
-\r
-For folks who find makefiles more useful than generalizations, there is a\r
-makefile provided for babel. The makefile is currently configured for\r
-Borland's 32-bit C compiler. Comment out those lines and uncomment the block\r
-which follows for gcc.\r
-\r
-To compile babel-get, first compile babel, then do the same thing in the\r
-babel-get directory.\r
-\r
-To compile ifiction-aggregate, ifiction-xtract, babel-list, and simple-marry,\r
-first compile babel, then compile the relevant C file in the extras/ directory\r
-(These may rely on #include files from the babel directory, so, for example,\r
-to compile ifiction-aggregate, "gcc -c -I.. ifiction-aggregate.c"), then link the\r
-opbject file to the babel and ifiction libraries (babel.lib and ifiction.lib\r
-under Windows, babel.a and ifiction.a most everywhere else. eg.\r
-"gcc -o ifiction-aggregate ifiction-aggregate.o ../babel.a ../ifiction.a")\r
-\r
-Babel is intended to accept contributions in the form of treaty modules\r
-as defined by the treaty of babel section 2.3.2.\r
-\r
-These modules should use the declarations made in treaty.h.\r
-The file treaty_builder.h generates a generic framework which simplifies\r
-the task of writing treaty modules. Its use is not required for treaty\r
-compliance, but it should prove useful.\r
-\r
-Parts of babel are intended for use in other programs. When adapting\r
-babel's source, the files babel.c, babel_story_functions.c and\r
-babel_ifiction_functions.c will probably not prove useful. However, you\r
-may wish to use babel_handler, which provides a framework for loading a\r
-story file, selecting the proper treaty modules, and seamlessly handling\r
-blorb-wrapped files.\r
-\r
+++ /dev/null
-/* adrift.c Treaty of Babel module for Adrift files\r
- *\r
- * PROVISIONAL - Hold for someone else\r
- *\r
- * This file depends on treaty_builder.h\r
- *\r
- * This file is public domain, but note that any changes to this file\r
- * may render it noncompliant with the Treaty of Babel\r
- */\r
-\r
-#define FORMAT adrift\r
-#define HOME_PAGE "http://www.adrift.org.uk"\r
-#define FORMAT_EXT ".taf"\r
-#define NO_METADATA\r
-#define NO_COVER\r
-\r
-#include "treaty_builder.h"\r
-\r
-#include <stdio.h>\r
-#include <limits.h>\r
-#include <stdlib.h>\r
-\r
-/* VB RNG constants */\r
-#define VB_RAND1 0x43FD43FD\r
-#define VB_RAND2 0x00C39EC3\r
-#define VB_RAND3 0x00FFFFFF\r
-#define VB_INIT 0x00A09E86\r
-static int32 vbr_state;\r
-\r
-/*\r
- Unobfuscates one byte from a taf file. This should be called on each byte\r
- in order, as the ADRIFT obfuscation function is stately.\r
-\r
- The de-obfuscation algorithm works by xoring the byte with the next\r
- byte in the sequence produced by the Visual Basic pseudorandom number\r
- generator, which is simulated here.\r
-*/\r
-static unsigned char taf_translate (unsigned char c)\r
-{\r
- int32 r;\r
-\r
- vbr_state = (vbr_state*VB_RAND1+VB_RAND2) & VB_RAND3;\r
- r=UCHAR_MAX * (unsigned) vbr_state;\r
- r/=((unsigned) VB_RAND3)+1;\r
- return r^c;\r
-}\r
-\r
-static int32 get_story_file_IFID(void *story_file, int32 extent, char *output, int32 output_extent)\r
-{\r
- int adv;\r
- unsigned char buf[4];\r
- unsigned char *sf=(unsigned char *)story_file;\r
- vbr_state=VB_INIT;\r
-\r
- if (extent <12) return INVALID_STORY_FILE_RV;\r
-\r
- buf[3]=0;\r
- /* Burn the first 8 bytes of translation */\r
- for(adv=0;adv<8;adv++) taf_translate(0);\r
- /* Bytes 8-11 contain the Adrift version number in the formay N.NN */\r
- buf[0]=taf_translate(sf[8]);\r
- taf_translate(0);\r
- buf[1]=taf_translate(sf[10]);\r
- buf[2]=taf_translate(sf[11]);\r
- adv=atoi((char *) buf);\r
- ASSERT_OUTPUT_SIZE(12);\r
- sprintf(output,"ADRIFT-%03d-",adv);\r
- return INCOMPLETE_REPLY_RV;\r
-\r
-}\r
-\r
-/* The claim algorithm for ADRIFT is to unobfuscate the first\r
- seven bytes, and check for the word "Version".\r
- It seems fairly unlikely that the obfuscated form of that\r
- word would occur in the wild\r
-*/\r
-static int32 claim_story_file(void *story_file, int32 extent)\r
-{\r
- unsigned char buf[8];\r
- int i;\r
- unsigned char *sf=(unsigned char *)story_file;\r
- buf[7]=0;\r
- vbr_state=VB_INIT;\r
- if (extent<12) return INVALID_STORY_FILE_RV;\r
- for(i=0;i<7;i++) buf[i]=taf_translate(sf[i]);\r
- if (strcmp((char *)buf,"Version")) return INVALID_STORY_FILE_RV;\r
- return VALID_STORY_FILE_RV;\r
-\r
-}\r
+++ /dev/null
-/* advsys.c Treaty of Babel module for AdvSys files\r
- * 2006 By L. Ross Raszewski\r
- *\r
- * This file depends on treaty_builder.h\r
- *\r
- * This file is public domain, but note that any changes to this file\r
- * may render it noncompliant with the Treaty of Babel\r
- */\r
-\r
-#define FORMAT advsys\r
-#define HOME_PAGE "http://www.ifarchive.org/if-archive/programming/advsys/"\r
-#define FORMAT_EXT ".dat"\r
-#define NO_METADATA\r
-#define NO_COVER\r
-\r
-#include "treaty_builder.h"\r
-#include <ctype.h>\r
-#include <stdio.h>\r
-\r
-/* IFIDs for AdvSys are formed by prepending ADVSYS- to the default\r
- MD5 ifid\r
-*/\r
-static int32 get_story_file_IFID(void *story_file, int32 extent, char *output, int32 output_extent)\r
-{\r
- /* This line suppresses a warning from the borland compiler */\r
- if (story_file || extent) { }\r
- ASSERT_OUTPUT_SIZE(8);\r
- strcpy(output,"ADVSYS-");\r
- return INCOMPLETE_REPLY_RV;\r
-\r
-}\r
-\r
-/* The Advsys claim algorithm: bytes 2-8 of the file contain the\r
- text "ADVSYS", unobfuscated in the following way:\r
- 30 is added to each byte, then the bits are reversed\r
-*/\r
-static int32 claim_story_file(void *story_file, int32 extent)\r
-{\r
- char buf[7];\r
- int i;\r
- if (extent >=8)\r
- { \r
- for(i=0;i<6;i++)\r
- buf[i]=~(((char *)story_file)[i+2]+30);\r
- buf[6]=0;\r
- if (strcmp(buf,"ADVSYS")==0) return VALID_STORY_FILE_RV;\r
- }\r
- return INVALID_STORY_FILE_RV;\r
-}\r
+++ /dev/null
-/* agt.c Treaty of Babel module for AGX-encapsulated AGT files\r
- * 2006 By L. Ross Raszewski\r
- *\r
- * This file depends on treaty_builder.h\r
- *\r
- * This file is public domain, but note that any changes to this file\r
- * may render it noncompliant with the Treaty of Babel\r
- */\r
-\r
-#define FORMAT agt\r
-#define HOME_PAGE "http://www.ifarchive.org/indexes/if-archiveXprogrammingXagt"\r
-#define FORMAT_EXT ".agx"\r
-#define NO_METADATA\r
-#define NO_COVER\r
-\r
-#include "treaty_builder.h"\r
-#include <ctype.h>\r
-#include <stdio.h>\r
-\r
-\r
-static char AGX_MAGIC[4] = { 0x58, 0xC7, 0xC1, 0x51 };\r
-\r
-/* Helper functions to unencode integers from AGT source */\r
-static int32 read_agt_short(unsigned char *sf)\r
-{\r
- return sf[0] | (int32) sf[1]<<8;\r
-}\r
-static int32 read_agt_int(unsigned char *sf)\r
-{\r
- return (read_agt_short(sf+2) << 16) | read_agt_short(sf);\r
-\r
-}\r
-\r
-static int32 get_story_file_IFID(void *story_file, int32 extent, char *output, int32 output_extent)\r
-{\r
- int32 l, game_version, game_sig;\r
- unsigned char *sf=(unsigned char *)story_file;\r
-\r
- /* Read the position of the game desciption block */\r
- l=read_agt_int(sf+32);\r
- if (extent<l+6) return INVALID_STORY_FILE_RV;\r
- game_version = read_agt_short(sf+l);\r
- game_sig=read_agt_int(sf+l+2);\r
- ASSERT_OUTPUT_SIZE(19);\r
- sprintf(output,"AGT-%05d-%08X",game_version,game_sig);\r
- return 1;\r
-}\r
-\r
-/* The claim algorithm for AGT is to check for the magic word\r
- defined above\r
-*/\r
-static int32 claim_story_file(void *story_file, int32 extent)\r
-{\r
-\r
-\r
- if (extent<36 || memcmp(story_file,AGX_MAGIC,4)) return INVALID_STORY_FILE_RV;\r
- return VALID_STORY_FILE_RV;\r
-\r
-}\r
+++ /dev/null
-/* alan.c Treaty of Babel module for ALAN files\r
- * 2006 By L. Ross Raszewski\r
- *\r
- * This file depends on treaty_builder.h\r
- *\r
- * This file is public domain, but note that any changes to this file\r
- * may render it noncompliant with the Treaty of Babel\r
- */\r
-\r
-#define FORMAT alan\r
-#define HOME_PAGE "http://www.alanif.se/"\r
-#define FORMAT_EXT ".acd"\r
-#define NO_METADATA\r
-#define NO_COVER\r
-\r
-#include "treaty_builder.h"\r
-#include <ctype.h>\r
-#include <stdio.h>\r
-\r
-static int32 read_alan_int(unsigned char *from)\r
-{\r
- return ((unsigned long int) from[3])| ((unsigned long int)from[2] << 8) |\r
- ((unsigned long int) from[1]<<16)| ((unsigned long int)from[0] << 24);\r
-}\r
-static int32 get_story_file_IFID(void *story_file, int32 extent, char *output, int32 output_extent)\r
-{\r
-\r
- if (story_file || extent) { }\r
- ASSERT_OUTPUT_SIZE(6);\r
- strcpy(output,"ALAN-");\r
- return INCOMPLETE_REPLY_RV;\r
-}\r
-/*\r
- The claim algorithm for Alan files is:\r
- * For Alan 3, check for the magic word\r
- * load the file length in blocks\r
- * check that the file length is correct\r
- * For alan 2, each word between byte address 24 and 81 is a\r
- word address within the file, so check that they're all within\r
- the file\r
- * Locate the checksum and verify that it is correct\r
-*/\r
-static int32 claim_story_file(void *story_file, int32 extent)\r
-{\r
- unsigned char *sf = (unsigned char *) story_file;\r
- int32 bf, i, crc=0;\r
- if (extent < 160) return INVALID_STORY_FILE_RV;\r
- if (memcmp(sf,"ALAN",4))\r
- { /* Identify Alan 2.x */\r
- bf=read_alan_int(sf+4);\r
- if (bf > extent/4) return INVALID_STORY_FILE_RV;\r
- for (i=24;i<81;i+=4)\r
- if (read_alan_int(sf+i) > extent/4) return INVALID_STORY_FILE_RV;\r
- for (i=160;i<(bf*4);i++)\r
- crc+=sf[i];\r
- if (crc!=read_alan_int(sf+152)) return INVALID_STORY_FILE_RV;\r
- return VALID_STORY_FILE_RV;\r
- }\r
- else\r
- { /* Identify Alan 3 */\r
- bf=read_alan_int(sf+12);\r
- if (bf > (extent/4)) return INVALID_STORY_FILE_RV;\r
- for (i=184;i<(bf*4);i++)\r
- crc+=sf[i];\r
- if (crc!=read_alan_int(sf+176)) return INVALID_STORY_FILE_RV;\r
-\r
- }\r
- return INVALID_STORY_FILE_RV;\r
-}\r
+++ /dev/null
-# provisional makefile for babel\r
-#\r
-# Note that to compile babel, it is necessary only to compile all the .c\r
-# files in this distribution and link them.\r
-#\r
-# This makefile is provided purely as a convenience.\r
-#\r
-# The following targets are available:\r
-# babel: make babel\r
-# babel.lib: make babel handler library (for Borland)\r
-# ifiction.lib: make babel ifiction library (for Borland)\r
-# babel.a: make babel handler library (for gcc)\r
-# ifiction.a: make babel ifiction library (for gcc)\r
-# dist: make babel.zip, the babel source distribution\r
-#\r
-# Note that this is a GNU makefile, and may not work with other makes\r
-#\r
-# Comment/uncomment the following lines to make the program work\r
-\r
-#CC=bcc32\r
-#OBJ=.obj\r
-#BABEL_LIB=babel.lib\r
-#IFICTION_LIB=ifiction.lib\r
-#BABEL_FLIB=babel_functions.lib\r
-#OUTPUT_BABEL=\r
-\r
-CC=gcc -g\r
-OBJ=.o\r
-BABEL_LIB=babel.a\r
-BABEL_FLIB=babel_functions.a\r
-IFICTION_LIB=ifiction.a\r
-OUTPUT_BABEL=-o babel\r
-\r
-treaty_objs = zcode${OBJ} magscrolls${OBJ} blorb${OBJ} glulx${OBJ} hugo${OBJ} agt${OBJ} level9${OBJ} executable${OBJ} advsys${OBJ} tads${OBJ} tads2${OBJ} tads3${OBJ} adrift${OBJ} alan${OBJ}\r
-bh_objs = babel_handler${OBJ} register${OBJ} misc${OBJ} md5${OBJ} ${treaty_objs}\r
-ifiction_objs = ifiction${OBJ} register_ifiction${OBJ}\r
-babel_functions = babel_story_functions${OBJ} babel_ifiction_functions${OBJ} babel_multi_functions${OBJ}\r
-babel_objs = babel${OBJ} $(BABEL_FLIB) $(IFICTION_LIB) $(BABEL_LIB)\r
-\r
-babel: ${babel_objs} \r
- ${CC} ${OUTPUT_BABEL} ${babel_objs}\r
-\r
-%${OBJ} : %.c\r
- ${CC} -c $^\r
-\r
-register${OBJ}: modules.h\r
-\r
-babel.lib: ${foreach dep,${bh_objs},${dep}.bl}\r
-\r
-ifiction.lib: ${foreach dep,${ifiction_objs},${dep}.il}\r
-\r
-babel_functions.lib: ${foreach dep,${babel_functions},${dep}.fl}\r
-\r
-%.obj.bl: %.obj\r
- tlib babel.lib +-$^\r
- echo made > $@\r
-\r
-%.obj.il: %.obj\r
- tlib ifiction.lib +-$^\r
- echo made > $@\r
-%.obj.fl: %.obj\r
- tlib babel_functions.lib +-$^\r
- echo made > $@\r
-\r
-babel.a: $(bh_objs)\r
- ar -r babel.a $^\r
-\r
-ifiction.a: $(ifiction_objs)\r
- ar -r ifiction.a $^\r
-\r
-babel_functions.a: $(babel_functions)\r
- ar -r babel_functions.a $^\r
-\r
-dist: \r
- cut -c0-31 MANIFEST | zip babel.zip -@\r
+++ /dev/null
-/* babel.c The babel command line program\r
- * (c) 2006 By L. Ross Raszewski\r
- *\r
- * This code is freely usable for all purposes.\r
- *\r
- * This work is licensed under the Creative Commons Attribution2.5 License.\r
- * To view a copy of this license, visit\r
- * http://creativecommons.org/licenses/by/2.5/ or send a letter to\r
- * Creative Commons,\r
- * 543 Howard Street, 5th Floor,\r
- * San Francisco, California, 94105, USA.\r
- *\r
- * This file depends upon misc.c and babel.h\r
- *\r
- * This file exports one variable: char *rv, which points to the file name\r
- * for an ifiction file. This is used only by babel_ifiction_verify\r
- */\r
-\r
-#include "babel.h"\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-\r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif\r
-int chdir(const char *);\r
-char *getcwd(char *, int);\r
-#ifdef __cplusplus\r
-}\r
-#endif\r
-\r
-char *fn;\r
-\r
-/* checked malloc function */\r
-void *my_malloc(int, char *);\r
-\r
-/* babel performs several fundamental operations, which are specified\r
- by command-line objects. Each of these functions corresponds to\r
- a story function (defined in babel_story_functions.c) or an\r
- ifiction function (defined in babel_ifiction_functions.c) or both.\r
- These are the types of those functions.\r
-*/\r
-\r
-typedef void (*story_function)(void);\r
-typedef void (*ifiction_function)(char *);\r
-typedef void (*multi_function)(char **, char *, int);\r
-/* This structure tells babel what to do with its command line arguments.\r
- if either of story or ifiction are NULL, babel considers this command line\r
- option inappropriate for that type of file.\r
-*/\r
-struct function_handler {\r
- char *function; /* the textual command line option */\r
- story_function story; /* handler for story files */\r
- ifiction_function ifiction; /* handler for ifiction files */\r
- char *desc; /* Textual description for help text */\r
- };\r
-\r
-struct multi_handler {\r
- char *function;\r
- char *argnames;\r
- multi_function handler;\r
- int nargsm;\r
- int nargsx;\r
- char *desc;\r
- };\r
-/* This is an array of function_handler objects which specify the legal\r
- arguments. It is terminated by a function_handler with a NULL function\r
- */\r
-static struct function_handler functions[] = {\r
- { "-ifid", babel_story_ifid, babel_ifiction_ifid, "Deduce IFID"},\r
- { "-format", babel_story_format, NULL, "Deduce story format" },\r
- { "-ifiction", babel_story_ifiction, NULL, "Extract iFiction file" },\r
- { "-meta", babel_story_meta, NULL, "Print story metadata" },\r
- { "-identify", babel_story_identify, NULL, "Describe story file" },\r
- { "-cover", babel_story_cover, NULL, "Extract cover art" },\r
- { "-story", babel_story_story, NULL, "Extract story file (ie. from a blorb)" },\r
- { "-verify", NULL, babel_ifiction_verify, "Verify integrity of iFiction file" },\r
- { "-lint", NULL, babel_ifiction_lint, "Verify style of iFiction file" },\r
- { "-fish", babel_story_fish, babel_ifiction_fish, "Extract all iFiction and cover art"},\r
- { "-unblorb", babel_story_unblorb, NULL, "As -fish, but also extract story files"},\r
- { NULL, NULL, NULL }\r
- };\r
-static struct multi_handler multifuncs[] = {\r
- { "-blorb", "<storyfile> <ifictionfile> [<cover art>]", babel_multi_blorb, 2, 3, "Bundle story file and (sparse) iFiction into blorb" },\r
- { "-blorbs", "<storyfile> <ifictionfile> [<cover art>]", babel_multi_blorb1, 2, 3, "Bundle story file and (sparse) iFiction into sensibly-named blorb" },\r
- { "-complete", "<storyfile> <ifictionfile>", babel_multi_complete, 2, 2, "Create complete iFiction file from sparse iFiction" },\r
- { NULL, NULL, NULL, 0, 0, NULL }\r
-};\r
-\r
-int main(int argc, char **argv)\r
-{\r
- char *todir=".";\r
- char cwd[512];\r
- int ok=1,i, l, ll;\r
- FILE *f;\r
- char *md=NULL;\r
- /* Set the input filename. Note that if this is invalid, babel should\r
- abort before anyone notices\r
- */\r
- fn=argv[2];\r
-\r
- if (argc < 3) ok=0;\r
- /* Detect the presence of the "-to <directory>" argument.\r
- */\r
- if (ok && argc >=5 && strcmp(argv[argc-2], "-to")==0)\r
- {\r
- todir=argv[argc-1];\r
- argc-=2;\r
- }\r
- if (ok) for(i=0;multifuncs[i].function;i++)\r
- if (strcmp(argv[1],multifuncs[i].function)==0 &&\r
- argc>= multifuncs[i].nargsm+2 &&\r
- argc <= multifuncs[i].nargsx+2)\r
- {\r
-\r
- multifuncs[i].handler(argv+2, todir, argc-2);\r
- exit(0);\r
- }\r
-\r
- if (argc!=3) ok=0;\r
-\r
- /* Find the apropriate function_handler */\r
- if (ok) {\r
- for(i=0;functions[i].function && strcmp(functions[i].function,argv[1]);i++);\r
- if (!functions[i].function) ok=0;\r
- else if (strcmp(fn,"-")) {\r
- f=fopen(argv[2],"r");\r
- if (!f) ok=0;\r
- }\r
- }\r
-\r
- /* Print usage error if anything has gone wrong */\r
- if (!ok)\r
- {\r
- printf("%s: Treaty of Babel Analysis Tool (%s, %s)\n"\r
- "Usage:\n", argv[0],BABEL_VERSION, TREATY_COMPLIANCE);\r
- for(i=0;functions[i].function;i++)\r
- {\r
- if (functions[i].story)\r
- printf(" babel %s <storyfile>\n",functions[i].function);\r
- if (functions[i].ifiction)\r
- printf(" babel %s <ifictionfile>\n",functions[i].function);\r
- printf(" %s\n",functions[i].desc);\r
- }\r
- for(i=0;multifuncs[i].function;i++)\r
- {\r
- printf("babel %s %s\n %s\n",\r
- multifuncs[i].function,\r
- multifuncs[i].argnames,\r
- multifuncs[i].desc);\r
- }\r
-\r
- printf ("\nFor functions which extract files, add \"-to <directory>\" to the command\n"\r
- "to set the output directory.\n"\r
- "The input file can be specified as \"-\" to read from standard input\n"\r
- "(This may only work for .iFiction files)\n");\r
- return 1;\r
- }\r
-\r
- /* For story files, we end up reading the file in twice. This\r
- is unfortunate, but unavoidable, since we want to be all\r
- cross-platformy, so the first time we read it in, we\r
- do the read in text mode, and the second time, we do it in binary\r
- mode, and there are platforms where this makes a difference.\r
- */\r
- ll=0;\r
- if (strcmp(fn,"-"))\r
- {\r
- fseek(f,0,SEEK_END);\r
- l=ftell(f)+1;\r
- fseek(f,0,SEEK_SET);\r
- md=(char *)my_malloc(l,"Input file buffer");\r
- fread(md,1,l-1,f);\r
- md[l-1]=0;\r
- }\r
- else\r
- while(!feof(stdin))\r
- {\r
- char *tt, mdb[1024];\r
- int ii;\r
- ii=fread(mdb,1,1024,stdin);\r
- tt=(char *)my_malloc(ll+ii,"file buffer");\r
- if (md) { memcpy(tt,md,ll); free(md); }\r
- memcpy(tt+ll,mdb,ii);\r
- md=tt;\r
- ll+=ii;\r
- if (ii<1024) break;\r
- }\r
-\r
-\r
- if (strstr(md,"<?xml version=") && strstr(md,"<ifindex"))\r
- { /* appears to be an ifiction file */\r
- char *pp;\r
- pp=strstr(md,"</ifindex>");\r
- if (pp) *(pp+10)=0;\r
- getcwd(cwd,512);\r
- chdir(todir);\r
- l=0;\r
- if (functions[i].ifiction)\r
- functions[i].ifiction(md);\r
- else\r
- fprintf(stderr,"Error: option %s is not valid for iFiction files\n",\r
- argv[1]);\r
- chdir(cwd);\r
- }\r
-\r
- if (strcmp(fn,"-"))\r
- {\r
- free(md);\r
- fclose(f);\r
- }\r
- if (l)\r
- { /* Appears to be a story */\r
- char *lt;\r
- if (functions[i].story)\r
- {\r
- if (strcmp(fn,"-")) lt=babel_init(argv[2]);\r
- else { lt=babel_init_raw(md,ll);\r
- free(md);\r
- }\r
-\r
- if (lt)\r
- {\r
- getcwd(cwd,512);\r
- chdir(todir);\r
- if (!babel_get_authoritative() && strcmp(argv[1],"-format"))\r
- printf("Warning: Story format could not be positively identified. Guessing %s\n",lt);\r
- functions[i].story();\r
-\r
- chdir(cwd);\r
- }\r
- else if (strcmp(argv[1],"-ifid")==0) /* IFID is calculable for all files */\r
- {\r
- babel_md5_ifid(cwd,512);\r
- printf("IFID: %s\n",cwd);\r
- }\r
- else\r
- fprintf(stderr,"Error: Did not recognize format of story file\n");\r
- babel_release();\r
- }\r
- else\r
- fprintf(stderr,"Error: option %s is not valid for story files\n",\r
- argv[1]);\r
- } \r
-\r
- return 0;\r
-}\r
+++ /dev/null
-/* babel.h declarations for babel\r
- * (c) 2006 By L. Ross Raszewski\r
- *\r
- * This code is freely usable for all purposes.\r
- *\r
- * This work is licensed under the Creative Commons Attribution2.5 License.\r
- * To view a copy of this license, visit\r
- * http://creativecommons.org/licenses/by/2.5/ or send a letter to\r
- * Creative Commons,\r
- * 543 Howard Street, 5th Floor,\r
- * San Francisco, California, 94105, USA.\r
- *\r
- * This file depends upon treaty.h, babel_ifiction_functions.c,\r
- * babel_story_functions.c, and babel_handler.c\r
- *\r
- */\r
-\r
-#define BABEL_VERSION "0.2b"\r
-\r
-#include "treaty.h"\r
-#include "babel_handler.h"\r
-#include "ifiction.h"\r
-/* Functions from babel_story_functions.c\r
- *\r
- * Each of these assumes that the story file has been loaded by babel_handler\r
- *\r
- * Each function babel_story_XXXX coresponds to the command line option -XXXX\r
- */\r
-void babel_story_ifid(void);\r
-void babel_story_cover(void);\r
-void babel_story_ifiction(void);\r
-void babel_story_meta(void);\r
-void babel_story_fish(void);\r
-void babel_story_format(void);\r
-void babel_story_identify(void);\r
-void babel_story_story(void);\r
-void babel_story_unblorb(void);\r
-/* Functions from babel_ifiction_functions.c\r
- *\r
- * as with babel_story_XXXX, but for metadata, which is handed in as the\r
- * C string parameter\r
- */\r
-void babel_ifiction_ifid(char *);\r
-void babel_ifiction_verify(char *);\r
-void babel_ifiction_fish(char *);\r
-void babel_ifiction_lint(char *);\r
-\r
-/* Functions from babel_multi_functions.c\r
- *\r
- */\r
-void babel_multi_blorb(char **, char * , int);\r
-void babel_multi_blorb1(char **, char * , int);\r
-void babel_multi_complete(char **, char *, int);\r
-\r
-/* uncomment this line on platforms which limit extensions to 3 characters */\r
-/* #define THREE_LETTER_EXTENSIONS */\r
+++ /dev/null
-/* babel_handler.c dispatches Treaty of Babel queries to the treaty modules\r
- * (c) 2006 By L. Ross Raszewski\r
- *\r
- * This code is freely usable for all purposes.\r
- *\r
- * This work is licensed under the Creative Commons Attribution2.5 License.\r
- * To view a copy of this license, visit\r
- * http://creativecommons.org/licenses/by/2.5/ or send a letter to\r
- * Creative Commons,\r
- * 543 Howard Street, 5th Floor,\r
- * San Francisco, California, 94105, USA.\r
- *\r
- * This file depends upon register.c, misc.c, babel.h, and treaty.h\r
- * and L. Peter Deutsch's md5.c\r
- * usage:\r
- * char *babel_init(char *filename)\r
- * Initializes babel to use the specified file. MUST be called before\r
- * babel_treaty. Returns the human-readable name of the format\r
- * or NULL if the format is not known. Do not call babel_treaty unless\r
- * babel_init returned a nonzero value.\r
- * The returned string will be the name of a babel format, possibly\r
- * prefixed by "blorbed " to indicate that babel will process this file\r
- * as a blorb.\r
- * int32 babel_treaty(int32 selector, void *output, void *output_extent)\r
- * Dispatches the call to the treaty handler for the currently loaded\r
- * file.\r
- * When processing a blorb, all treaty calls will be deflected to the\r
- * special blorb handler. For the case of GET_STORY_FILE_IFID_SEL,\r
- * The treaty handler for the underlying format will be called if an\r
- * IFID is not found in the blorb resources.\r
- * void babel_release()\r
- * Frees all resources allocated during babel_init.\r
- * You should do this even if babel_init returned NULL.\r
- * After this is called, do not call babel_treaty until after\r
- * another successful call to babel_init.\r
- * char *babel_get_format()\r
- * Returns the same value as the last call to babel_init (ie, the format name)\r
- * int32 babel_md5_ifid(char *buffer, int extent);\r
- * Generates an MD5 IFID from the loaded story. Returns zero if something\r
- * went seriously wrong.\r
- *\r
- * If you wish to use babel in multiple threads, you must use the contextualized\r
- * versions of the above functions.\r
- * Each function above has a companion function whose name ends in _ctx (eg.\r
- * "babel_treaty_ctx") which takes one additional argument. This argument is\r
- * the babel context. A new context is returned by void *ctx=get_babel_ctx(),\r
- * and should be released when finished by calling release_babel_ctx(ctx);\r
- */\r
-\r
- \r
-#include "treaty.h"\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <stdio.h>\r
-#include <ctype.h>\r
-#include "md5.h"\r
-\r
-void *my_malloc(int, char *);\r
-\r
-struct babel_handler\r
-{\r
- TREATY treaty_handler;\r
- TREATY treaty_backup;\r
- void *story_file;\r
- int32 story_file_extent;\r
- void *story_file_blorbed;\r
- int32 story_file_blorbed_extent;\r
- char blorb_mode;\r
- char *format_name;\r
- char auth;\r
-};\r
-\r
-static struct babel_handler default_ctx;\r
-\r
-extern TREATY treaty_registry[];\r
-extern TREATY container_registry[];\r
-\r
-static char *deeper_babel_init(char *story_name, void *bhp)\r
-{\r
- struct babel_handler *bh=(struct babel_handler *) bhp;\r
- int i;\r
- char *ext;\r
-\r
- static char buffer[TREATY_MINIMUM_EXTENT];\r
- int best_candidate;\r
- char buffert[TREATY_MINIMUM_EXTENT];\r
-\r
- if (story_name)\r
- {\r
- ext=strrchr(story_name,'.');\r
- if (ext) for(i=0;ext[i];i++) ext[i]=tolower(ext[i]);\r
- }\r
- else ext=NULL;\r
- best_candidate=-1;\r
- if (ext) /* pass 1: try best candidates */\r
- for(i=0;container_registry[i];i++)\r
- if (container_registry[i](GET_FILE_EXTENSIONS_SEL,NULL,0,buffer,TREATY_MINIMUM_EXTENT) >=0 &&\r
- strstr(buffer,ext) &&\r
- container_registry[i](CLAIM_STORY_FILE_SEL,bh->story_file,bh->story_file_extent,NULL,0)>=NO_REPLY_RV)\r
- break;\r
- if (!ext || !container_registry[i]) /* pass 2: try all candidates */\r
- {\r
- \r
- for(i=0;container_registry[i];i++)\r
- {int l=container_registry[i](CLAIM_STORY_FILE_SEL,bh->story_file,bh->story_file_extent,NULL,0);\r
- \r
- if (l==VALID_STORY_FILE_RV)\r
- break;\r
- else if (l==NO_REPLY_RV && best_candidate < 0) best_candidate=i;\r
- }\r
-}\r
- if (!container_registry[i] && best_candidate >=0) { bh->auth=0; i=best_candidate; }\r
- if (container_registry[i])\r
- {\r
- char buffer2[TREATY_MINIMUM_EXTENT];\r
- \r
- bh->treaty_handler=container_registry[i];\r
- container_registry[i](GET_FORMAT_NAME_SEL,NULL,0,buffert,TREATY_MINIMUM_EXTENT);\r
- bh->blorb_mode=1;\r
-\r
- bh->story_file_blorbed_extent=container_registry[i](CONTAINER_GET_STORY_EXTENT_SEL,bh->story_file,bh->story_file_extent,NULL,0);\r
- if (bh->story_file_blorbed_extent>0) bh->story_file_blorbed=my_malloc(bh->story_file_blorbed_extent, "contained story file");\r
- if (bh->story_file_blorbed_extent<=0 ||\r
- container_registry[i](CONTAINER_GET_STORY_FORMAT_SEL,bh->story_file,bh->story_file_extent,buffer2,TREATY_MINIMUM_EXTENT)<0 ||\r
- container_registry[i](CONTAINER_GET_STORY_FILE_SEL,bh->story_file,bh->story_file_extent,bh->story_file_blorbed,bh->story_file_blorbed_extent)<=0\r
- )\r
- return NULL;\r
- \r
- for(i=0;treaty_registry[i];i++)\r
- if (treaty_registry[i](GET_FORMAT_NAME_SEL,NULL,0,buffer,TREATY_MINIMUM_EXTENT)>=0 &&\r
- strcmp(buffer,buffer2)==0 &&\r
- treaty_registry[i](CLAIM_STORY_FILE_SEL,bh->story_file_blorbed,bh->story_file_blorbed_extent,NULL,0)>=NO_REPLY_RV)\r
- break;\r
- if (!treaty_registry[i])\r
- return NULL;\r
- bh->treaty_backup=treaty_registry[i];\r
- sprintf(buffer,"%sed %s",buffert,buffer2);\r
- return buffer;\r
- }\r
-\r
- bh->blorb_mode=0;\r
- best_candidate=-1;\r
-\r
- if (ext) /* pass 1: try best candidates */\r
- for(i=0;treaty_registry[i];i++)\r
- if (treaty_registry[i](GET_FILE_EXTENSIONS_SEL,NULL,0,buffer,TREATY_MINIMUM_EXTENT) >=0 &&\r
- strstr(buffer,ext) && \r
- treaty_registry[i](CLAIM_STORY_FILE_SEL,bh->story_file,bh->story_file_extent,NULL,0)>=NO_REPLY_RV)\r
- break;\r
- if (!ext || !treaty_registry[i]) /* pass 2: try all candidates */\r
- {\r
- \r
- for(i=0;treaty_registry[i];i++)\r
- {int l;\r
- l=treaty_registry[i](CLAIM_STORY_FILE_SEL,bh->story_file,bh->story_file_extent,NULL,0);\r
-\r
- if (l==VALID_STORY_FILE_RV)\r
- break;\r
- else if (l==NO_REPLY_RV && best_candidate < 0) best_candidate=i;\r
- }\r
- }\r
- if (!treaty_registry[i])\r
- if (best_candidate>0) { i=best_candidate; bh->auth=0; }\r
- else return NULL;\r
- bh->treaty_handler=treaty_registry[i];\r
-\r
- if (bh->treaty_handler(GET_FORMAT_NAME_SEL,NULL,0,buffer,TREATY_MINIMUM_EXTENT)>=0)\r
- return buffer;\r
- return NULL;\r
-\r
-\r
-}\r
-\r
-static char *deep_babel_init(char *story_name, void *bhp)\r
-{\r
- struct babel_handler *bh=(struct babel_handler *) bhp;\r
- FILE *file;\r
-\r
- bh->treaty_handler=NULL;\r
- bh->treaty_backup=NULL;\r
- bh->story_file=NULL;\r
- bh->story_file_extent=0;\r
- bh->story_file_blorbed=NULL;\r
- bh->story_file_blorbed_extent=0;\r
- bh->format_name=NULL;\r
- file=fopen(story_name, "rb");\r
- if (!file) return NULL;\r
- fseek(file,0,SEEK_END);\r
- bh->story_file_extent=ftell(file);\r
- fseek(file,0,SEEK_SET);\r
- bh->auth=1; \r
- bh->story_file=my_malloc(bh->story_file_extent,"story file storage");\r
- fread(bh->story_file,1,bh->story_file_extent,file);\r
- fclose(file);\r
-\r
- return deeper_babel_init(story_name, bhp);\r
-}\r
-\r
-char *babel_init_ctx(char *sf, void *bhp)\r
-{\r
- struct babel_handler *bh=(struct babel_handler *) bhp;\r
- char *b;\r
- b=deep_babel_init(sf,bh);\r
- if (b) bh->format_name=strdup(b);\r
- return b;\r
-}\r
-char *babel_init(char *sf)\r
-{\r
- return babel_init_ctx(sf, &default_ctx);\r
-}\r
-\r
-char *babel_init_raw_ctx(void *sf, int32 extent, void *bhp)\r
-{\r
- struct babel_handler *bh=(struct babel_handler *) bhp;\r
- char *b;\r
- bh->treaty_handler=NULL;\r
- bh->treaty_backup=NULL;\r
- bh->story_file=NULL;\r
- bh->story_file_extent=0;\r
- bh->story_file_blorbed=NULL;\r
- bh->story_file_blorbed_extent=0;\r
- bh->format_name=NULL;\r
- bh->story_file_extent=extent;\r
- bh->auth=1; \r
- bh->story_file=my_malloc(bh->story_file_extent,"story file storage");\r
- memcpy(bh->story_file,sf,extent);\r
-\r
- b=deeper_babel_init(NULL, bhp);\r
- if (b) bh->format_name=strdup(b);\r
- return b;\r
-}\r
-char *babel_init_raw(void *sf, int32 extent)\r
-{\r
- return babel_init_raw_ctx(sf, extent, &default_ctx);\r
-}\r
-\r
-void babel_release_ctx(void *bhp)\r
-{\r
- struct babel_handler *bh=(struct babel_handler *) bhp;\r
- if (bh->story_file) free(bh->story_file);\r
- bh->story_file=NULL;\r
- if (bh->story_file_blorbed) free(bh->story_file_blorbed);\r
- bh->story_file_blorbed=NULL;\r
- if (bh->format_name) free(bh->format_name);\r
- bh->format_name=NULL;\r
-}\r
-void babel_release()\r
-{\r
- babel_release_ctx(&default_ctx);\r
-}\r
-int32 babel_md5_ifid_ctx(char *buffer, int32 extent, void *bhp)\r
-{\r
- struct babel_handler *bh=(struct babel_handler *) bhp;\r
- md5_state_t md5;\r
- int i;\r
- unsigned char ob[16];\r
- if (extent <33 || bh->story_file==NULL)\r
- return 0;\r
- md5_init(&md5);\r
- md5_append(&md5,bh->story_file,bh->story_file_extent);\r
- md5_finish(&md5,ob);\r
- for(i=0;i<16;i++)\r
- sprintf(buffer+(2*i),"%02X",ob[i]);\r
- buffer[32]=0;\r
- return 1;\r
-\r
-}\r
-int32 babel_md5_ifid(char *buffer, int32 extent)\r
-{\r
- return babel_md5_ifid_ctx(buffer, extent,\r
- &default_ctx);\r
-}\r
-\r
-int32 babel_treaty_ctx(int32 sel, void *output, int32 output_extent,void *bhp)\r
-{\r
- int32 rv;\r
- struct babel_handler *bh=(struct babel_handler *) bhp;\r
- if (!(sel & TREATY_SELECTOR_INPUT) && bh->blorb_mode)\r
- rv=bh->treaty_backup(sel,bh->story_file_blorbed,bh->story_file_blorbed_extent,output, output_extent);\r
- else\r
- {\r
- rv=bh->treaty_handler(sel,bh->story_file,bh->story_file_extent,output,output_extent);\r
- if ((!rv|| rv==UNAVAILABLE_RV) && bh->blorb_mode)\r
- rv=bh->treaty_backup(sel,bh->story_file_blorbed,bh->story_file_blorbed_extent,output, output_extent);\r
- }\r
- if (!rv && sel==GET_STORY_FILE_IFID_SEL)\r
- return babel_md5_ifid_ctx(output,output_extent, bh);\r
- if (rv==INCOMPLETE_REPLY_RV && sel==GET_STORY_FILE_IFID_SEL)\r
- return babel_md5_ifid_ctx((void *)((char *) output+strlen((char *)output)),\r
- output_extent-strlen((char *)output),\r
- bh);\r
-\r
- return rv;\r
-}\r
-int32 babel_treaty(int32 sel, void *output, int32 output_extent)\r
-{\r
- return babel_treaty_ctx(sel, output, output_extent, &default_ctx);\r
-}\r
-char *babel_get_format_ctx(void *bhp)\r
-{\r
- struct babel_handler *bh=(struct babel_handler *) bhp;\r
- return bh->format_name;\r
-}\r
-char *babel_get_format()\r
-{\r
- return babel_get_format_ctx(&default_ctx);\r
-}\r
-void *get_babel_ctx()\r
-{\r
- return my_malloc(sizeof(struct babel_handler), "babel handler context");\r
-}\r
-void release_babel_ctx(void *b)\r
-{\r
- free(b);\r
-}\r
-\r
-int32 babel_get_length_ctx(void *bhp)\r
-{\r
- struct babel_handler *bh=(struct babel_handler *) bhp;\r
- return bh->story_file_extent;\r
-}\r
-int32 babel_get_length()\r
-{\r
- return babel_get_length_ctx(&default_ctx);\r
-}\r
-\r
-int32 babel_get_authoritative_ctx(void *bhp)\r
-{\r
- struct babel_handler *bh=(struct babel_handler *) bhp;\r
- return bh->auth;\r
-}\r
-int32 babel_get_authoritative()\r
-{\r
- return babel_get_authoritative_ctx(&default_ctx);\r
-}\r
-void *babel_get_file_ctx(void *bhp)\r
-{\r
- struct babel_handler *bh=(struct babel_handler *) bhp;\r
- return bh->story_file;\r
-}\r
-void *babel_get_file()\r
-{\r
- return babel_get_file_ctx(&default_ctx);\r
-}\r
-\r
-int32 babel_get_story_length_ctx(void *ctx)\r
-{\r
- struct babel_handler *bh=(struct babel_handler *) ctx;\r
- if (bh->blorb_mode) return bh->story_file_blorbed_extent;\r
- return bh->story_file_extent;\r
-}\r
-int32 babel_get_story_length()\r
-{\r
-\r
- return babel_get_story_length_ctx(&default_ctx);\r
-}\r
-void *babel_get_story_file_ctx(void *ctx)\r
-{\r
- struct babel_handler *bh=(struct babel_handler *) ctx;\r
- if (bh->blorb_mode) return bh->story_file_blorbed;\r
- return bh->story_file;\r
-}\r
-void *babel_get_story_file()\r
-{\r
- return babel_get_story_file_ctx(&default_ctx);\r
-}\r
+++ /dev/null
-/* babel_handler.h declarations for the babel handler API\r
- * (c) 2006 By L. Ross Raszewski\r
- *\r
- * This code is freely usable for all purposes.\r
- *\r
- * This work is licensed under the Creative Commons Attribution2.5 License.\r
- * To view a copy of this license, visit\r
- * http://creativecommons.org/licenses/by/2.5/ or send a letter to\r
- * Creative Commons,\r
- * 543 Howard Street, 5th Floor,\r
- * San Francisco, California, 94105, USA.\r
- *\r
- */\r
-\r
-#ifndef BABEL_HANDLER_H\r
-#define BABEL_HANDLER_H\r
-\r
-#include "treaty.h"\r
-\r
-/* Functions from babel_handler.c */\r
-char *babel_init(char *filename);\r
- /* initialize the babel handler */\r
-char *babel_init_raw(void *sf, int32 extent);\r
- /* Initialize from loaded data */\r
-int32 babel_treaty(int32 selector, void *output, int32 output_extent);\r
- /* Dispatch treaty calls */\r
-void babel_release(void);\r
- /* Release babel_handler resources */\r
-char *babel_get_format(void);\r
- /* return the format of the loaded file */\r
-int32 babel_md5_ifid(char *buffer, int32 extent);\r
- /* IFID generator of last resort */\r
-int32 babel_get_length(void);\r
- /* Fetch file length */\r
-int32 babel_get_story_length(void);\r
- /* Fetch file length */\r
-int32 babel_get_authoritative(void);\r
- /* Determine if babel handler has a good grasp on the format */\r
-void *babel_get_file(void);\r
- /* Get loaded story file */\r
-void *babel_get_story_file(void);\r
- /* Get loaded story file */\r
-\r
-/* threadsafe versions of above */\r
-char *babel_init_ctx(char *filename, void *);\r
- /* initialize the babel handler */\r
-int32 babel_treaty_ctx(int32 selector, void *output, int32 output_extent, void *);\r
- /* Dispatch treaty calls */\r
-void babel_release_ctx(void *);\r
- /* Release babel_handler resources */\r
-char *babel_get_format_ctx(void *);\r
- /* return the format of the loaded file */\r
-int32 babel_md5_ifid_ctx(char *buffer, int extent, void *);\r
- /* IFID generator of last resort */\r
-int32 babel_get_length_ctx(void *);\r
-int32 babel_get_story_length_ctx(void *);\r
-void *babel_get_file_ctx(void *bhp);\r
-void *babel_get_story_ctx(void *bhp);\r
-int32 babel_get_authoritative_ctx(void *bhp);\r
-char *babel_init_raw_ctx(void *sf, int32 extent, void *bhp);\r
-void *get_babel_ctx(void);\r
-void release_babel_ctx(void *);\r
- /* get and release babel contexts */\r
-\r
-#endif\r
+++ /dev/null
-/* babel_ifiction_functions.c babel top-level operations for ifiction\r
- * (c) 2006 By L. Ross Raszewski\r
- *\r
- * This code is freely usable for all purposes.\r
- *\r
- * This work is licensed under the Creative Commons Attribution2.5 License.\r
- * To view a copy of this license, visit\r
- * http://creativecommons.org/licenses/by/2.5/ or send a letter to\r
- * Creative Commons,\r
- * 543 Howard Street, 5th Floor,\r
- * San Francisco, California, 94105, USA.\r
- *\r
- * This file depends upon babel.c (for rv), babel.h, misc.c and ifiction.c\r
- */\r
-\r
-#include "babel.h"\r
-#include <string.h>\r
-#include <stdlib.h>\r
-#include <stdio.h>\r
-#include <ctype.h>\r
-\r
-#ifndef THREE_LETTER_EXTENSIONS\r
-#define IFICTION_EXT ".iFiction"\r
-#else\r
-#define IFICTION_EXT ".ifi"\r
-#endif\r
-\r
-void *my_malloc(int, char *);\r
-\r
-struct IFiction_Info\r
-{\r
- char ifid[256];\r
- int wmode;\r
-};\r
-\r
-static void write_story_to_disk(struct XMLTag *xtg, void *ctx)\r
-{\r
- char *b, *ep;\r
- char *begin, *end;\r
- char buffer[TREATY_MINIMUM_EXTENT];\r
- int32 l, j;\r
- if (ctx) { }\r
-\r
- if (strcmp(xtg->tag,"story")==0)\r
- {\r
- begin=xtg->begin;\r
- end=xtg->end;\r
- l=end-begin+1;\r
- b=(char *)my_malloc(l,"XML buffer");\r
- memcpy(b,begin,l-1);\r
- b[l]=0;\r
- j=ifiction_get_IFID(b,buffer,TREATY_MINIMUM_EXTENT);\r
- if (!j)\r
- {\r
- fprintf(stderr,"No IFID found for this story\n");\r
- free(b);\r
- return;\r
- }\r
- ep=strtok(buffer,",");\r
- while(ep)\r
- {\r
- char buf2[256];\r
- FILE *f;\r
- sprintf(buf2,"%s%s",ep,IFICTION_EXT);\r
- f=fopen(buf2,"w");\r
-\r
- if (!f ||\r
- fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"\r
- "<!-- Metadata extracted by Babel -->"\r
- "<ifindex version=\"1.0\" xmlns=\"http://babel.ifarchive.org/protocol/iFiction/\">\n"\r
- " <story>",\r
- f)==EOF ||\r
- fputs(b,f)==EOF ||\r
- fputs("/<story>\n</ifindex>\n",f)==EOF\r
- )\r
- {\r
- fprintf(stderr,"Error writing to file %s\n",buf2);\r
- } else\r
- printf("Extracted %s\n",buf2);\r
- if (f) fclose(f);\r
-\r
- ep=strtok(NULL,",");\r
- }\r
-\r
- free(b);\r
- }\r
-}\r
-\r
-void babel_ifiction_ifid(char *md)\r
-{\r
- char output[TREATY_MINIMUM_EXTENT];\r
- int i;\r
- char *ep;\r
- i=ifiction_get_IFID(md,output,TREATY_MINIMUM_EXTENT);\r
- if (!i)\r
-\r
- {\r
- fprintf(stderr,"Error: No IFIDs found in iFiction file\n");\r
- return;\r
- }\r
- ep=strtok(output,",");\r
- while(ep)\r
- {\r
- printf("IFID: %s\n",ep);\r
- ep=strtok(NULL,",");\r
- }\r
-\r
-}\r
-\r
-static char isok;\r
-\r
-static void examine_tag(struct XMLTag *xtg, void *ctx)\r
-{\r
- struct IFiction_Info *xti=(struct IFiction_Info *)ctx;\r
-\r
- if (strcmp("ifid",xtg->tag)==0 && strcmp(xti->ifid,"UNKNOWN")==0)\r
- {\r
- memcpy(xti->ifid,xtg->begin,xtg->end-xtg->begin);\r
- xti->ifid[xtg->end-xtg->begin]=0;\r
- }\r
-\r
-}\r
-static void verify_eh(char *e, void *ctx)\r
-{\r
- if (*((int *)ctx) < 0) return;\r
- if (*((int *)ctx) || strncmp(e,"Warning",7))\r
- { isok=0;\r
- fprintf(stderr, "%s\n",e);\r
- }\r
-}\r
-\r
-\r
-\r
-void babel_ifiction_fish(char *md)\r
-{\r
- int i=-1;\r
- ifiction_parse(md,write_story_to_disk,NULL,verify_eh,&i);\r
-}\r
-\r
-void deep_ifiction_verify(char *md, int f)\r
-{\r
- struct IFiction_Info ii;\r
- int i=0;\r
- ii.wmode=0;\r
- isok=1;\r
- strcpy(ii.ifid,"UNKNOWN");\r
- ifiction_parse(md,examine_tag,&ii,verify_eh,&i);\r
- if (f&& isok) printf("Verified %s\n",ii.ifid);\r
-}\r
-void babel_ifiction_verify(char *md)\r
-{\r
- deep_ifiction_verify(md,1);\r
-\r
-}\r
-\r
-\r
-void babel_ifiction_lint(char *md)\r
-{\r
- struct IFiction_Info ii;\r
- int i=1;\r
- ii.wmode=1;\r
- isok=1;\r
- strcpy(ii.ifid,"UNKNOWN");\r
- ifiction_parse(md,examine_tag,&ii,verify_eh,&i);\r
- if (isok) printf("%s conforms to iFiction style guidelines\n",ii.ifid);\r
-}\r
-\r
-\r
+++ /dev/null
-#include "babel.h"\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <ctype.h>\r
-\r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif\r
-int chdir(const char *);\r
-char *getcwd(char *, int);\r
-#ifdef __cplusplus\r
-}\r
-#endif\r
-\r
-void deep_ifiction_verify(char *md, int f);\r
-void * my_malloc(int32, char *);\r
-char *blorb_chunk_for_name(char *name);\r
-#ifndef THREE_LETTER_EXTENSIONS\r
-static char *ext_table[] = { "zcode", ".zblorb",\r
- "glulx", ".gblorb",\r
- NULL, NULL\r
- };\r
-#else\r
-static char *ext_table[] = { "zcode", ".zlb",\r
- "glulx", ".glb",\r
- NULL, NULL\r
- };\r
-\r
-#endif\r
-char *blorb_ext_for_name(char *fmt)\r
-{\r
- int i;\r
- for(i=0;ext_table[i];i+=2)\r
- if (strcmp(ext_table[i],fmt)==0) return ext_table[i+1];\r
-#ifndef THREE_LETTER_EXTENSIONS\r
- return ".blorb";\r
-#else\r
- return ".blb";\r
-#endif\r
-}\r
-\r
-char *deep_complete_ifiction(char *fn, char *ifid, char *format)\r
-{\r
- FILE *f;\r
- int32 i;\r
- char *md;\r
- char *id, *idp;\r
- char *idb;\r
- f=fopen(fn,"r");\r
- if (!f) { fprintf(stderr,"Error: Can not open file %s\n",fn);\r
- return NULL;\r
- }\r
- fseek(f,0,SEEK_END);\r
- i=ftell(f);\r
- fseek(f,0,SEEK_SET);\r
- md=(char *) my_malloc(i+1,"Metadata buffer");\r
- fread(md,1,i,f);\r
- md[i]=0;\r
- id=strstr(md,"</ifindex>");\r
- if (id) *(id+10)=0;\r
- fclose(f);\r
- id=strdup(ifid);\r
- idp=strtok(id,",");\r
- /* Find the identification chunk */\r
- {\r
- char *bp, *ep;\r
- bp=strstr(md,"<identification>");\r
- if (!bp)\r
- {\r
- idb=(char *)my_malloc(TREATY_MINIMUM_EXTENT+128,"ident buffer");\r
- sprintf(idb,"<format>%s</format>\n", format);\r
- }\r
- else\r
- {\r
- int ii;\r
- ep=strstr(bp,"</identification>");\r
- idb=(char *)my_malloc(TREATY_MINIMUM_EXTENT+128+(ep-bp),"ident buffer");\r
- for(ii=16;bp+ii<ep;ii++)\r
- idb[ii-16]=bp[ii];\r
- idb[ii]=0;\r
- for(ep+=18;*ep;ep++)\r
- *bp++=*ep;\r
- *bp=0;\r
- bp=strstr(idb,"<format>");\r
- if (bp)\r
- if (memcmp(bp+8,format,strlen(format)))\r
- fprintf(stderr,"Error: Format in sparse .iFiction does not match story\n");\r
-\r
- }\r
-\r
- }\r
- /* Insert the new ifids */\r
- while(idp)\r
- {\r
- char bfr[TREATY_MINIMUM_EXTENT];\r
- sprintf(bfr,"<ifid>%s</ifid>",idp);\r
- if (!strstr(idb,bfr)) { strcat(idb,bfr); strcat(idb,"\n"); }\r
- idp=strtok(NULL,",");\r
-\r
- }\r
- free(id);\r
- idp=(char *) my_malloc(strlen(md)+strlen(idb)+64, "Output metadata");\r
-/* printf("%d bytes for metadata\n",strlen(md)+strlen(idb)+64);*/\r
- id=strstr(md,"<story>");\r
- id[0]=0;\r
- id+=7;\r
- strcpy(idp,md);\r
- strcat(idp,"<story>\n <identification>\n");\r
- strcat(idp,idb);\r
- free(idb);\r
- strcat(idp," </identification>\n");\r
- strcat(idp,id);\r
- free(md);\r
- md=idp;\r
- deep_ifiction_verify(md, 0);\r
- return md;\r
-}\r
-\r
-void write_int(int32 i, FILE *f)\r
-{\r
- char bf[4];\r
- bf[0]=(((unsigned) i) >> 24) & 0xFF;\r
- bf[1]=(((unsigned) i) >> 16) & 0xFF;\r
- bf[2]=(((unsigned) i) >> 8) & 0xFF;\r
- bf[3]=(((unsigned) i)) & 0xFF;\r
- fwrite(bf,1,4,f);\r
-}\r
-static void _babel_multi_blorb(char *outfile, char **args, char *todir , int argc)\r
-{\r
- int32 total, storyl, coverl, i;\r
- char buffer[TREATY_MINIMUM_EXTENT+10];\r
- char b2[TREATY_MINIMUM_EXTENT];\r
-\r
- char cwd[512];\r
- char *cover, *md, *cvrf, *ep;\r
-\r
- FILE *f, *c;\r
- if (argc!=2 && argc !=3)\r
- {\r
- fprintf(stderr,"Invalid usage\n");\r
- return;\r
- }\r
- if (!babel_init(args[0]))\r
- {\r
- fprintf(stderr,"Error: Could not determine the format of file %s\n",args[0]);\r
- return;\r
- }\r
- if (babel_treaty(GET_STORY_FILE_IFID_SEL,buffer,TREATY_MINIMUM_EXTENT)<=0 ||\r
- babel_treaty(GET_FORMAT_NAME_SEL,b2,TREATY_MINIMUM_EXTENT)<0\r
- )\r
- {\r
- fprintf(stderr,"Error: Could not deduce an IFID for file %s\n",args[0]);\r
- return;\r
- }\r
- if (babel_get_length() != babel_get_story_length())\r
- {\r
- fprintf(stderr,"Warning: Story file will be extacted from container before blorbing\n");\r
- }\r
-/* printf("Completing ifiction\n");*/\r
- md=deep_complete_ifiction(args[1],buffer,b2);\r
-/* printf("Ifiction is %d bytes long\n",strlen(md));*/\r
- ep=strchr(buffer,',');\r
- if (ep) *ep=0;\r
- if (outfile)\r
- strcpy(buffer,outfile);\r
- strcat(buffer,blorb_ext_for_name(b2));\r
- getcwd(cwd,512);\r
- chdir(todir);\r
- f=fopen(buffer,"wb");\r
- chdir(cwd);\r
- if (!f)\r
- {\r
- fprintf(stderr,"Error: Error writing to file %s\n",buffer);\r
- return;\r
- }\r
- storyl=babel_get_story_length();\r
- total=storyl + (storyl%2) + 36;\r
- if (md) total+=8+strlen(md)+strlen(md)%2;\r
- if (argc==3)\r
- {\r
- c=fopen(args[2],"rb");\r
- if (c)\r
- {\r
- fseek(c,0,SEEK_END);\r
- coverl=ftell(c);\r
- if (coverl > 5){\r
-\r
- cover=(char *) my_malloc(coverl+2,"Cover art buffer");\r
- fseek(c,0,SEEK_SET);\r
- fread(cover,1,coverl,c);\r
- if (memcmp(cover+1,"PNG",3)==0) cvrf="PNG ";\r
- else cvrf="JPEG";\r
- total += 32+coverl + (coverl%2);\r
- }\r
- else argc=2;\r
- fclose(c);\r
- }\r
- else argc=2;\r
- }\r
-/* printf("Writing header\n;");*/\r
- fwrite("FORM",1,4,f);\r
- write_int(total,f);\r
-/* printf("Writing index\n;");*/\r
- fwrite("IFRSRIdx",1,8,f);\r
- write_int(argc==3 ? 28:16,f);\r
- write_int(argc==3 ? 2:1,f);\r
-/* printf("Writing story\n;");*/\r
- fwrite("Exec", 1,4,f);\r
- write_int(0,f);\r
- write_int(argc==3 ? 48:36,f);\r
- if (argc==3)\r
- {\r
-/* printf("Writing image\n;"); */\r
- fwrite("Pict", 1,4,f);\r
- write_int(1,f);\r
- write_int(56+storyl+(storyl%2),f);\r
- }\r
-/* printf("Invoking chunk for name %s\n",b2); */\r
- fwrite(blorb_chunk_for_name(b2),1,4,f);\r
- write_int(storyl,f);\r
-/* printf("Writing story data\n"); */\r
- fwrite(babel_get_story_file(),1,storyl,f);\r
- if (storyl%2) fwrite("\0",1,1,f);\r
- if (argc==3)\r
- {\r
-/* printf("Writing cover data header %s\n",cvrf); */\r
- fwrite(cvrf,1,4,f);\r
-/* printf("Writing cover data size %d\n",coverl); */\r
- write_int(coverl,f);\r
-/* printf("Writing cover data\n"); */\r
- fwrite(cover,1,coverl,f);\r
- if (coverl%2) fwrite("\0",1,1,f);\r
-/* printf("Done with cover\n");*/\r
-/* free(cover);*/\r
-/* printf("Writing frontispiece\n;");*/\r
- fwrite("Fspc\0\0\0\004\0\0\0\001",1,12,f);\r
- }\r
-\r
- if (md) {\r
-/* printf("Writing metadata\n;");*/\r
- fwrite("IFmd",1,4,f);\r
- write_int(strlen(md),f);\r
- fwrite(md,1,strlen(md),f);\r
- if (strlen(md)%2)\r
- fwrite("\0",1,1,f);\r
- free(md);\r
- }\r
-\r
- fclose(f);\r
- printf("Created %s\n",buffer);\r
- \r
-}\r
-void babel_multi_complete(char **args, char *todir, int argc)\r
-{\r
- char buffer[TREATY_MINIMUM_EXTENT+10];\r
- char b2[TREATY_MINIMUM_EXTENT];\r
- char cwd[512];\r
- char *ep, *md;\r
- FILE *f;\r
- if (argc!=2)\r
- {\r
- fprintf(stderr,"Invalid usage\n");\r
- return;\r
- }\r
- if (!babel_init(args[0]))\r
- {\r
- fprintf(stderr,"Error: Could not determine the format of file %s\n",args[0]);\r
- return;\r
- }\r
- if (babel_treaty(GET_STORY_FILE_IFID_SEL,buffer,TREATY_MINIMUM_EXTENT)<=0\r
- || babel_treaty(GET_FORMAT_NAME_SEL,b2,TREATY_MINIMUM_EXTENT)<0)\r
- {\r
- fprintf(stderr,"Error: Could not deduce an IFID for file %s\n",args[0]);\r
- return;\r
- }\r
- md=deep_complete_ifiction(args[1],buffer, b2);\r
- if (!md) return;\r
- ep=strchr(buffer,',');\r
- if (ep) *ep=0;\r
- strcat(buffer,".iFiction");\r
- getcwd(cwd,512);\r
- chdir(todir);\r
- f=fopen(buffer,"w");\r
- chdir(cwd);\r
- if (!f || !fputs(md,f))\r
- {\r
- fprintf(stderr,"Error: Error writing to file %s\n",buffer);\r
- return;\r
- }\r
- fclose(f);\r
- free(md);\r
- printf("Created %s\n",buffer);\r
-}\r
-void babel_multi_blorb(char **args, char *todir , int argc)\r
-{\r
- _babel_multi_blorb(NULL,args,todir,argc);\r
-}\r
-void babel_multi_blorb1(char **args, char *todir , int argc)\r
-{\r
- char *buf;\r
- char *bb;\r
- buf=(char *)my_malloc(strlen(args[0])+1,"blorb name buffer");\r
- strcpy(buf,args[0]);\r
- bb=strrchr(buf,'.');\r
- if (bb) *bb=0;\r
- _babel_multi_blorb(buf,args,todir,argc);\r
- free(buf);\r
- \r
-\r
-}\r
+++ /dev/null
-/* babel_story_functions.c babel top-level operations for story files\r
- * (c) 2006 By L. Ross Raszewski\r
- *\r
- * This code is freely usable for all purposes.\r
- *\r
- * This work is licensed under the Creative Commons Attribution2.5 License.\r
- * To view a copy of this license, visit\r
- * http://creativecommons.org/licenses/by/2.5/ or send a letter to\r
- * Creative Commons,\r
- * 543 Howard Street, 5th Floor,\r
- * San Francisco, California, 94105, USA.\r
- *\r
- * This file depends upon babel_handler.c, babel.h, and misc.c\r
- */\r
-\r
-#include "babel.h"\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-\r
-#ifndef THREE_LETTER_EXTENSIONS\r
-#define IFICTION_EXT ".iFiction"\r
-#else\r
-#define IFICTION_EXT ".ifi"\r
-#endif\r
-void *my_malloc(int32, char *);\r
-\r
-void babel_story_ifid()\r
-{\r
- char buffer[TREATY_MINIMUM_EXTENT];\r
- char *ep;\r
- int i;\r
- i=babel_treaty(GET_STORY_FILE_IFID_SEL,buffer,TREATY_MINIMUM_EXTENT);\r
- ep=strtok(buffer, ",");\r
- while(ep)\r
- {\r
- printf("IFID: %s\n",ep);\r
- ep=strtok(NULL,",");\r
- }\r
- if (!i)\r
- fprintf(stderr,"Unable to create an IFID (A serious problem occurred while loading the file).\n");\r
-\r
-}\r
-\r
-\r
-void babel_story_format()\r
-{\r
- char *b;\r
- b=babel_get_format();\r
- if (!b) b="unknown";\r
- if (!babel_get_authoritative())\r
- printf("Format: %s (non-authoritative)\n",b); \r
- else printf("Format: %s\n",b);\r
-}\r
-\r
-static void deep_babel_ifiction(char stopped)\r
-{\r
- char buffer[TREATY_MINIMUM_EXTENT];\r
- char *md;\r
- char *ep;\r
- int32 i;\r
- FILE *f;\r
-\r
- if (stopped!=2)\r
- {\r
- i=babel_treaty(GET_STORY_FILE_IFID_SEL,buffer,TREATY_MINIMUM_EXTENT);\r
- if (i==0 && !babel_md5_ifid(buffer, TREATY_MINIMUM_EXTENT))\r
- {\r
- fprintf(stderr,"Unable to create an IFID (A serious problem occurred while loading the file).\n");\r
- return;\r
- }\r
-\r
-\r
- ep=strtok(buffer, ",");\r
- }\r
- else ep="-";\r
- i=babel_treaty(GET_STORY_FILE_METADATA_EXTENT_SEL,NULL,0);\r
- if (i<=0)\r
- {\r
- if (stopped) printf("No iFiction record for %s\n",buffer);\r
- return;\r
- }\r
- md=(char *)my_malloc(i,"Metadata buffer");\r
- if (babel_treaty(GET_STORY_FILE_METADATA_SEL,md,i)<0)\r
- {\r
- fprintf(stderr,"A serious error occurred while retrieving metadata.\n");\r
- free(md);\r
- return;\r
- }\r
- while(ep)\r
- {\r
- char epb[TREATY_MINIMUM_EXTENT+9];\r
- if (stopped!=2)\r
- {\r
- strcpy(epb,ep);\r
- strcat(epb, IFICTION_EXT);\r
-\r
- f=fopen(epb,"w");\r
- }\r
- else f=stdout;\r
-\r
- if (!f || fputs(md,f)==EOF)\r
- fprintf(stderr,"A serious error occurred writing to disk.\n");\r
- else if (stopped!=2) printf("Extracted %s\n",epb);\r
- if (f) fclose(f);\r
- if (stopped) break;\r
- ep=strtok(NULL,",");\r
- }\r
- free(md);\r
-}\r
-\r
-void babel_story_ifiction()\r
-{\r
- deep_babel_ifiction(1);\r
-}\r
-static char *get_jpeg_dim(void *img, int32 extent)\r
-{\r
- unsigned char *dp=(unsigned char *) img;\r
- unsigned char *ep=dp+extent;\r
- static char buffer[256];\r
- unsigned int t1, t2, w, h;\r
-\r
-\r
- t1=*(dp++);\r
- t2=*(dp++);\r
- if (t1!=0xff || t2!=0xD8 )\r
- {\r
- return "(invalid)";\r
- }\r
-\r
- while(1)\r
- {\r
- if (dp>ep) return "(invalid)";\r
- for(t1=*(dp++);t1!=0xff;t1=*(dp++)) if (dp>ep) return "(invalid)";\r
- do { t1=*(dp++); if (dp>ep) return "(invalid 4)";} while (t1 == 0xff);\r
-\r
- if ((t1 & 0xF0) == 0xC0 && !(t1==0xC4 || t1==0xC8 || t1==0xCC))\r
- {\r
- dp+=3;\r
- if (dp>ep) return "(invalid)";\r
- h=*(dp++) << 8;\r
- if (dp>ep) return "(invalid)";\r
- h|=*(dp++);\r
- if (dp>ep) return "(invalid)";\r
- w=*(dp++) << 8;\r
- if (dp>ep) return "(invalid)";\r
- w|=*(dp);\r
- sprintf(buffer, "(%dx%d)",w,h);\r
- return buffer;\r
- }\r
- else if (t1==0xD8 || t1==0xD9)\r
- break;\r
- else\r
- { int l;\r
-\r
- if (dp>ep) return "(invalid)";\r
- l=*(dp++) << 8;\r
- if (dp>ep) return "(invalid)";\r
- l|= *(dp++);\r
- l-=2;\r
- dp+=l;\r
- if (dp>ep) return "(invalid)";\r
- }\r
- }\r
- return "(invalid)";\r
-}\r
-\r
-static int32 read_int(unsigned char *mem)\r
-{\r
- int32 i4 = mem[0],\r
- i3 = mem[1],\r
- i2 = mem[2],\r
- i1 = mem[3];\r
- return i1 | (i2<<8) | (i3<<16) | (i4<<24);\r
-}\r
-\r
-\r
-static char *get_png_dim(void *img, int32 extent)\r
-{\r
- unsigned char *dp=(unsigned char *)img;\r
- static char buffer[256];\r
- int32 w, h;\r
- if (extent<33 ||\r
- !(dp[0]==137 && dp[1]==80 && dp[2]==78 && dp[3]==71 &&\r
- dp[4]==13 && dp[5] == 10 && dp[6] == 26 && dp[7]==10)||\r
- !(dp[12]=='I' && dp[13]=='H' && dp[14]=='D' && dp[15]=='R'))\r
- return "(invalid)";\r
- w=read_int(dp+16);\r
- h=read_int(dp+20);\r
- sprintf(buffer,"(%dx%d)",w,h);\r
- return buffer;\r
-}\r
-static char *get_image_dim(void *img, int32 extent, int fmt)\r
-{\r
- if (fmt==JPEG_COVER_FORMAT) return get_jpeg_dim(img,extent);\r
- else if (fmt==PNG_COVER_FORMAT) return get_png_dim(img, extent);\r
- return "(unknown)";\r
-\r
-}\r
-static void deep_babel_cover(char stopped)\r
-{\r
- char buffer[TREATY_MINIMUM_EXTENT];\r
- void *md;\r
- char *ep;\r
- char *ext;\r
- char *dim;\r
- int32 i,j;\r
- FILE *f;\r
- i=babel_treaty(GET_STORY_FILE_IFID_SEL,buffer,TREATY_MINIMUM_EXTENT);\r
- if (i==0)\r
- if (babel_md5_ifid(buffer, TREATY_MINIMUM_EXTENT))\r
- printf("IFID: %s\n",buffer);\r
- else\r
- {\r
- fprintf(stderr,"Unable to create an IFID (A serious problem occurred while loading the file).\n");\r
- return;\r
- }\r
- else \r
-\r
- ep=strtok(buffer, ",");\r
- i=babel_treaty(GET_STORY_FILE_COVER_EXTENT_SEL,NULL,0);\r
- j=babel_treaty(GET_STORY_FILE_COVER_FORMAT_SEL,NULL,0);\r
-\r
- if (i<=0 || j<=0)\r
- {\r
- if (stopped) printf("No cover art for %s\n",buffer);\r
- return;\r
- }\r
- if (j==PNG_COVER_FORMAT) ext=".png";\r
- else if (j==JPEG_COVER_FORMAT) ext=".jpg";\r
- md=my_malloc(i,"Image buffer");\r
- if (babel_treaty(GET_STORY_FILE_COVER_SEL,md,i)<0)\r
- {\r
- fprintf(stderr,"A serious error occurred while retrieving cover art.\n");\r
- free(md);\r
- return;\r
- }\r
- dim=get_image_dim(md,i,j);\r
- while(ep)\r
- {\r
- char epb[TREATY_MINIMUM_EXTENT+9];\r
- strcpy(epb,ep);\r
- strcat(epb, ext);\r
-\r
- f=fopen(epb,"wb");\r
- if (!f || fwrite(md,1,i,f)==EOF)\r
- fprintf(stderr,"A serious error occurred writing to disk.\n");\r
- else printf("Extracted %s %s\n",epb, dim);\r
- if (f) fclose(f);\r
- if (stopped) break;\r
- ep=strtok(NULL,",");\r
- }\r
- free(md);\r
-}\r
-\r
-void babel_story_cover()\r
-{\r
- deep_babel_cover(1);\r
-}\r
-\r
-void babel_story_fish()\r
-{\r
- deep_babel_ifiction(0);\r
- deep_babel_cover(0);\r
-}\r
-\r
-static char *get_biblio(void)\r
-{\r
- int32 i;\r
- char *md;\r
- char *bib="No bibliographic data";\r
- char *bibb; char *bibe; \r
- char *t;\r
- static char buffer[TREATY_MINIMUM_EXTENT];\r
-\r
- i=babel_treaty(GET_STORY_FILE_METADATA_EXTENT_SEL,NULL,0);\r
- if (i<=0) return bib;\r
-\r
- md=(char *) my_malloc(i,"Metadata buffer");\r
- if (babel_treaty(GET_STORY_FILE_METADATA_SEL,md,i)<0) return bib;\r
- \r
- bibb=strstr(md,"<bibliographic>");\r
- if (!bibb) { free(md); return bib; }\r
- bibe=strstr(bibb,"</bibliographic>");\r
- if (bibe) *bibe=0;\r
- t=strstr(bibb,"<title>");\r
- if (t)\r
- {\r
- t+=7;\r
- bibe=strstr(t,"</title>");\r
- if (bibe)\r
- {\r
- *bibe=0;\r
- bib=buffer;\r
- for(i=0;t[i];i++) if (t[i]<0x20 || t[i]>0x7e) t[i]='_';\r
- sprintf(buffer, "\"%s\" ",t);\r
- *bibe='<';\r
- }\r
- else strcpy(buffer,"<no title found> ");\r
- }\r
- t=strstr(bibb,"<author>");\r
- if (t)\r
- {\r
- t+=8;\r
- bibe=strstr(t,"</author>");\r
- if (bibe)\r
- {\r
- bib=buffer;\r
- *bibe=0;\r
- for(i=0;t[i];i++) if (t[i]<0x20 || t[i]>0x7e) t[i]='_';\r
- strcat(buffer, "by ");\r
- strcat(buffer, t);\r
- *bibe='<';\r
- }\r
- else strcat(buffer, "<no author found>");\r
- }\r
- free(md);\r
- return bib;\r
-\r
-}\r
-void babel_story_identify()\r
-{\r
- int32 i, j, l;\r
- char *b, *cf, *dim;\r
- char buffer[TREATY_MINIMUM_EXTENT];\r
-\r
- printf("%s\n",get_biblio());\r
- babel_story_ifid();\r
- b=babel_get_format();\r
- if (!b) b="unknown";\r
- l=babel_get_length() / 1024;\r
- \r
-\r
- i=babel_treaty(GET_STORY_FILE_COVER_EXTENT_SEL,NULL,0);\r
- j=babel_treaty(GET_STORY_FILE_COVER_FORMAT_SEL,NULL,0);\r
-\r
- if (i<=0 || j<=0)\r
- {\r
- cf="no cover"; \r
- }\r
- else\r
- {\r
- char *md=my_malloc(i,"Image buffer");\r
- if (babel_treaty(GET_STORY_FILE_COVER_SEL,md,i)<0)\r
- {\r
- cf="no cover";\r
- }\r
- else\r
- {\r
- dim=get_image_dim(md,i,j)+1;\r
- dim[strlen(dim)-1]=0;\r
- if (j==JPEG_COVER_FORMAT) cf="jpeg";\r
- else if (j==PNG_COVER_FORMAT) cf="png";\r
- else cf="unknown format";\r
- sprintf(buffer,"cover %s %s",dim,cf);\r
- cf=buffer;\r
- }\r
- }\r
- printf("%s, %dk, %s\n",b, l,cf);\r
-}\r
-\r
-void babel_story_meta()\r
-{\r
- deep_babel_ifiction(2);\r
-}\r
-\r
-void babel_story_story()\r
-{\r
- int32 j,i;\r
- void *p;\r
- FILE *f;\r
- char *ep;\r
- char buffer[TREATY_MINIMUM_EXTENT+20];\r
- j=babel_get_story_length();\r
- p=babel_get_story_file();\r
- if (!j || !p)\r
- {\r
- fprintf(stderr,"A serious error occurred while retrieving the story file.\n");\r
- return;\r
- }\r
-\r
- i=babel_treaty(GET_STORY_FILE_IFID_SEL,buffer,TREATY_MINIMUM_EXTENT);\r
- if (i==0 && !babel_md5_ifid(buffer, TREATY_MINIMUM_EXTENT))\r
- {\r
- fprintf(stderr,"Unable to create an IFID (A serious problem occurred while loading the file).\n");\r
- return;\r
- }\r
- ep=strchr(buffer, ',');\r
- if (!ep) ep=buffer+strlen(buffer);\r
- *ep=0;\r
- babel_treaty(GET_STORY_FILE_EXTENSION_SEL,ep,19);\r
- f=fopen(buffer,"wb");\r
- if (!f || !fwrite(p,1,j,f))\r
- {\r
- fprintf(stderr,"A serious error occurred writing to disk.\n");\r
- return;\r
- }\r
- fclose(f);\r
- printf("Extracted %s\n",buffer);\r
-\r
- \r
-\r
-}\r
-\r
-void babel_story_unblorb()\r
-{\r
- deep_babel_ifiction(1);\r
- deep_babel_cover(1);\r
- babel_story_story();\r
-\r
-}\r
+++ /dev/null
-/* blorb.c Babel interface to blorb files\r
- * Copyright 2006 by L. Ross Raszewski\r
- *\r
- * This code is freely usable for all purposes.\r
- *\r
- * This work is licensed under the Creative Commons Attribution2.5 License.\r
- * To view a copy of this license, visit\r
- * http://creativecommons.org/licenses/by/2.5/ or send a letter to\r
- * Creative Commons,\r
- * 543 Howard Street, 5th Floor,\r
- * San Francisco, California, 94105, USA.\r
- *\r
- * This file depends upon treaty_builder.h, misc.c and ifiction.c\r
- *\r
- * Header note: to add support for new executable chunk types, see\r
- * TranslateExec.\r
- *\r
- * This file defines a Treaty of Babel compatable module for handling blorb\r
- * files. However, blorb files are not themselves a babel format. This module\r
- * is used internally by the babel program to handle blorbs.\r
- *\r
- * As a result, if GET_STORY_FILE_IFID_SEL returns NO_REPLY_RV,\r
- * you should check the story file against the babel registry before resorting\r
- * to the default IFID calculation.\r
- *\r
- */\r
-#define FORMAT blorb\r
-#define HOME_PAGE "http://eblong.com/zarf/blorb"\r
-#define FORMAT_EXT ".blorb,.blb,.zblorb,.zlb,.gblorb,.glb"\r
-#define CONTAINER_FORMAT\r
-#include "treaty_builder.h"\r
-#include <stdlib.h>\r
-#include <ctype.h>\r
-\r
-extern TREATY treaty_registry[];\r
-/* The following is the translation table of Blorb chunk types to\r
- babel formats. it is NULL-terminated. */\r
-static char *TranslateExec[] = { "ZCOD", "zcode",\r
- "GLUL", "glulx",\r
- "TAD2", "tads2",\r
- "TAD3", "tads3",\r
- NULL, NULL };\r
-\r
-void *my_malloc(int32, char *);\r
-int32 ifiction_get_IFID(char *, char *, int32);\r
-\r
-static int32 read_int(void *inp)\r
-{\r
- unsigned char *mem=(unsigned char *)inp;\r
- int32 i4 = mem[0],\r
- i3 = mem[1],\r
- i2 = mem[2],\r
- i1 = mem[3];\r
- return i1 | (i2<<8) | (i3<<16) | (i4<<24);\r
-}\r
-\r
-\r
-static int32 blorb_get_chunk(void *blorb_file, int32 extent, char *id, int32 *begin, int32 *output_extent)\r
-{\r
- int32 i=12, j;\r
- while(i<extent-8)\r
- {\r
- if (memcmp(((char *)blorb_file)+i,id,4)==0)\r
- {\r
- *output_extent=read_int((char *)blorb_file+i+4);\r
- if (*output_extent > extent) return NO_REPLY_RV;\r
- *begin=i+8;\r
- return 1;\r
- }\r
-\r
- j=read_int((char *)blorb_file+i+4);\r
- if (j%2) j++;\r
- i+=j+8;\r
-\r
- }\r
- return NO_REPLY_RV;\r
-}\r
-static int32 blorb_get_resource(void *blorb_file, int32 extent, char *rid, int32 number, int32 *begin, int32 *output_extent)\r
-{\r
- int32 ridx_len;\r
- int32 i,j;\r
- void *ridx;\r
- if (blorb_get_chunk(blorb_file, extent,"RIdx",&i,&ridx_len)==NO_REPLY_RV)\r
- return NO_REPLY_RV;\r
-\r
- ridx=(char *)blorb_file+i+4;\r
- ridx_len=read_int((char *)blorb_file+i);\r
- for(i=0;i<ridx_len;i++)\r
- { \r
- if(memcmp((char *)ridx+(i*12),rid,4)==0 && read_int((char *)ridx+(i*12)+4)==number)\r
- {\r
- j=i;\r
- i=read_int((char *)ridx+(j*12)+8);\r
- *begin=i+8;\r
- *output_extent=read_int((char *)blorb_file+i+4);\r
- return 1;\r
- }\r
- }\r
- return NO_REPLY_RV;\r
-}\r
-static int32 blorb_get_story_file(void *blorb_file, int32 extent, int32 *begin, int32 *output_extent)\r
-{\r
- return blorb_get_resource(blorb_file, extent, "Exec", 0, begin, output_extent);\r
-\r
-}\r
-\r
-static int32 get_story_extent(void *blorb_file, int32 extent)\r
-{\r
- int32 i,j;\r
- if (blorb_get_resource(blorb_file, extent, "Exec", 0, &i, &j))\r
- {\r
- return j;\r
- }\r
- return NO_REPLY_RV;\r
-\r
-}\r
-static int32 get_story_file(void *blorb_file, int32 extent, void *output, int32 output_extent)\r
-{\r
- int32 i,j;\r
- if (blorb_get_resource(blorb_file, extent, "Exec", 0, &i, &j))\r
- {\r
- ASSERT_OUTPUT_SIZE(j);\r
- memcpy(output,(char *)blorb_file+i,j);\r
- return j;\r
- }\r
- return NO_REPLY_RV;\r
-\r
-}\r
-\r
-char *blorb_chunk_for_name(char *name)\r
-{\r
- static char buffer[5];\r
- int j;\r
- for(j=0;TranslateExec[j];j+=2)\r
- if (strcmp(name,TranslateExec[j+1])==0) return TranslateExec[j];\r
- for(j=0;j<4 && name[j];j++) buffer[j]=toupper(buffer[j]);\r
- while(j<4) buffer[j++]=' ';\r
- buffer[4]=0;\r
- return buffer;\r
-\r
-}\r
-static char *blorb_get_story_format(void *blorb_file, int32 extent)\r
-{\r
- int32 i, j;\r
-\r
- for(j=0;treaty_registry[j];j++)\r
- {\r
- static char fn[512];\r
- treaty_registry[j](GET_FORMAT_NAME_SEL,NULL,0,fn,512);\r
- if (blorb_get_chunk(blorb_file,extent,blorb_chunk_for_name(fn),&i, &i)) return fn;\r
- }\r
- return NULL;\r
-}\r
-\r
-static int32 get_story_format(void *blorb_file, int32 extent, char *output, int32 output_extent)\r
-{\r
- char *o;\r
- o=blorb_get_story_format(blorb_file, extent);\r
- if (!o) return NO_REPLY_RV;\r
- ASSERT_OUTPUT_SIZE((signed) strlen(o)+1);\r
- strcpy(output,o);\r
- return strlen(o)+1;\r
-}\r
-static int32 get_story_file_metadata_extent(void *blorb_file, int32 extent)\r
-{\r
- int32 i,j;\r
- if (blorb_get_chunk(blorb_file,extent,"IFmd",&i,&j)) return j+1;\r
- return NO_REPLY_RV;\r
-}\r
-static int32 blorb_get_cover(void *blorb_file, int32 extent, int32 *begin, int32 *output_extent)\r
-{\r
- int i,j;\r
- if (blorb_get_chunk(blorb_file,extent,"Fspc",&i,&j))\r
- {\r
- if (j<4) return NO_REPLY_RV;\r
- i=read_int((char *)blorb_file+i);\r
- if (!blorb_get_resource(blorb_file,extent,"Pict",i,&i,&j)) return NO_REPLY_RV;\r
- *begin=i;\r
- *output_extent=j;\r
- if (memcmp((char *)blorb_file+i-8,"PNG ",4)==0) return PNG_COVER_FORMAT;\r
- else if (memcmp((char *)blorb_file+i-8,"JPEG",4)==0) return JPEG_COVER_FORMAT;\r
- }\r
- return NO_REPLY_RV;\r
-\r
-}\r
-\r
-static int32 get_story_file_cover_extent(void *blorb_file, int32 extent)\r
-{\r
- int32 i,j;\r
- if (blorb_get_cover(blorb_file,extent,&i,&j)) return j;\r
- return NO_REPLY_RV;\r
-}\r
-\r
-static int32 get_story_file_cover_format(void *blorb_file, int32 extent)\r
-{\r
- int32 i,j;\r
- return blorb_get_cover(blorb_file, extent, &i,&j);\r
-}\r
-\r
-static int32 get_story_file_IFID(void *b, int32 e, char *output, int32 output_extent)\r
-{\r
- int32 j;\r
- char *md;\r
- j=get_story_file_metadata_extent(b,e);\r
- if (j<=0) return NO_REPLY_RV;\r
- md=(char *)my_malloc(j, "Metadata buffer");\r
- j=get_story_file_metadata(b,e,md,j);\r
- if (j<=0) return NO_REPLY_RV;\r
-\r
- j=ifiction_get_IFID(md,output,output_extent);\r
- free(md);\r
- return j;\r
-}\r
-\r
-static int32 get_story_file_metadata(void *blorb_file, int32 extent, char *output, int32 output_extent)\r
-{\r
- int32 i,j;\r
- if (!blorb_get_chunk(blorb_file, extent,"IFmd",&i,&j)) return NO_REPLY_RV;\r
- ASSERT_OUTPUT_SIZE(j+1);\r
- memcpy(output,(char *)blorb_file+i,j);\r
- output[j]=0;\r
- return j+1;\r
-}\r
-static int32 get_story_file_cover(void *blorb_file, int32 extent, void *output, int32 output_extent)\r
-{\r
- int32 i,j;\r
- if (!blorb_get_cover(blorb_file, extent,&i,&j)) return NO_REPLY_RV;\r
- ASSERT_OUTPUT_SIZE(j);\r
- memcpy(output,(char *)blorb_file+i,j);\r
- return j;\r
-}\r
-\r
-static int32 claim_story_file(void *story_file, int32 extent)\r
-{\r
- int i;\r
-\r
- if (extent<16 ||\r
- memcmp(story_file,"FORM",4) ||\r
- memcmp((char *)story_file+8,"IFRS",4) \r
- ) i= INVALID_STORY_FILE_RV;\r
- else i= NO_REPLY_RV;\r
- \r
- return i;\r
-\r
-}\r
+++ /dev/null
-/* executable.c Treaty of Babel module for Z-code files\r
- * 2006 By L. Ross Raszewski\r
- *\r
- * This file depends on treaty_builder.h\r
- *\r
- * This file is public domain, but note that any changes to this file\r
- * may render it noncompliant with the Treaty of Babel\r
- */\r
-\r
-#define FORMAT executable\r
-#define HOME_PAGE "http://http://en.wikipedia.org/wiki/Executable"\r
-#define FORMAT_EXT ".exe"\r
-#define NO_METADATA\r
-#define NO_COVER\r
-\r
-#include "treaty_builder.h"\r
-#include <ctype.h>\r
-#include <stdio.h>\r
-\r
-static char elfmagic[] = { 0x7f, 0x45, 0x4c, 0x46, 0 };\r
-static char javamagic[] = { 0xCA, 0xFE, 0xBA, 0xBE, 0 };\r
-static char amigamagic[] = { 0, 0, 3, 0xe7, 0 };\r
-static char machomagic[] = { 0xFE, 0xED, 0xFA, 0xCE, 0};\r
-struct exetype\r
-{\r
- char *magic;\r
- char *name;\r
- int len;\r
-};\r
-static struct exetype magic[]= { { "MZ", "MZ", 2 },\r
- { elfmagic, "ELF", 4 },\r
- { javamagic, "JAVA", 4 },\r
- { amigamagic, "AMIGA", 4 },\r
- { "#! ", "SCRIPT", 3 },\r
- { machomagic, "MACHO",4 },\r
- { "APPL", "MAC",4 },\r
- { NULL, NULL, 0 } };\r
-\r
-static char *deduce_magic(void *sf, int32 extent)\r
-{\r
- int i;\r
- for(i=0;magic[i].magic;i++)\r
- if (extent >= magic[i].len && memcmp(magic[i].magic,sf,magic[i].len)==0)\r
- return magic[i].name;\r
- return NULL;\r
-}\r
- \r
-static int32 claim_story_file(void *sf, int32 extent)\r
-{\r
- if (deduce_magic(sf,extent)) return VALID_STORY_FILE_RV;\r
- return NO_REPLY_RV;\r
-}\r
-static int32 get_story_file_IFID(void *sf, int32 extent, char *output, int32 output_extent)\r
-{\r
- char *o;\r
- o=deduce_magic(sf,extent);\r
- if (!o) return 0;\r
- ASSERT_OUTPUT_SIZE((signed) strlen(o)+2);\r
- strcpy(output,o);\r
- strcat(output,"-");\r
- return INCOMPLETE_REPLY_RV;\r
-}\r
+++ /dev/null
-/* glulx.c Treaty of Babel module for Glulx files\r
- * 2006 By L. Ross Raszewski\r
- *\r
- * This file depends on treaty_builder.h\r
- *\r
- * This file is public domain, but note that any changes to this file\r
- * may render it noncompliant with the Treaty of Babel\r
- */\r
-\r
-#define FORMAT glulx\r
-#define HOME_PAGE "http://eblong.com/zarf/glulx"\r
-#define FORMAT_EXT ".ulx"\r
-#define NO_METADATA\r
-#define NO_COVER\r
-\r
-#include "treaty_builder.h"\r
-#include <ctype.h>\r
-#include <stdio.h>\r
-\r
-static int32 read_int(unsigned char *mem)\r
-{\r
- int32 i4 = mem[0],\r
- i3 = mem[1],\r
- i2 = mem[2],\r
- i1 = mem[3];\r
- return i1 | (i2<<8) | (i3<<16) | (i4<<24);\r
-}\r
-\r
-\r
-\r
-static int32 get_story_file_IFID(void *story_file, int32 extent, char *output, int32 output_extent)\r
-{\r
- int32 i,j, k;\r
- char ser[7];\r
- char buffer[32];\r
-\r
-\r
- if (extent<256) return INVALID_STORY_FILE_RV;\r
- for(i=0;i<extent;i++) if (memcmp((char *)story_file+i,"UUID://",7)==0) break;\r
- if (i<extent) /* Found explicit IFID */\r
- {\r
- for(j=i+7;j<extent && ((char *)story_file)[j]!='/';j++);\r
- if (j<extent)\r
- {\r
- i+=7;\r
- ASSERT_OUTPUT_SIZE(j-i);\r
- memcpy(output,(char *)story_file+i,j-i);\r
- output[j-i]=0;\r
- return 1;\r
- }\r
- }\r
-\r
- /* Did not find intact IFID. Build one */\r
-\r
- j=read_int((unsigned char *)story_file+32);\r
- k=read_int((unsigned char *)story_file+12);\r
- if (memcmp((char *)story_file+36,"Info",4)==0)\r
- { /* Inform generated */\r
- char *bb=(char *)story_file+52;\r
- k= (int) bb[0]<<8 | (int) bb[1];\r
- memcpy(ser,bb+2,6);\r
- ser[6]=0;\r
- for(i=0;i<6;i++) if (!isalnum(ser[i])) ser[i]='-';\r
- sprintf(buffer,"GLULX-%u-%s-%04X",k,ser,j);\r
- }\r
- else\r
- sprintf(buffer,"GLULX-%08X-%08X",k,j);\r
-\r
- ASSERT_OUTPUT_SIZE((signed) strlen(buffer)+1);\r
- strcpy((char *)output,buffer);\r
- return 1;\r
-\r
-}\r
-\r
-static int32 claim_story_file(void *story_file, int32 extent)\r
-{\r
- if (extent<256 ||\r
- memcmp(story_file,"Glul",4)\r
- ) return INVALID_STORY_FILE_RV;\r
- return VALID_STORY_FILE_RV;\r
-}\r
+++ /dev/null
-/* hugo.c Treaty of Babel module for hugo files\r
- * 2006 By L. Ross Raszewski\r
- *\r
- * This file depends on treaty_builder.h\r
- *\r
- * This file is public domain, but note that any changes to this file\r
- * may render it noncompliant with the Treaty of Babel\r
- */\r
-\r
-#define FORMAT hugo\r
-#define HOME_PAGE "http://www.generalcoffee.com"\r
-#define FORMAT_EXT ".hex"\r
-#define NO_METADATA\r
-#define NO_COVER\r
-\r
-#include "treaty_builder.h"\r
-#include <ctype.h>\r
-#include <stdio.h>\r
-\r
-static int32 get_story_file_IFID(void *s_file, int32 extent, char *output, int32 output_extent)\r
-{\r
-\r
- int32 i,j;\r
- char ser[9];\r
- char buffer[32];\r
- char *story_file = (char *) s_file;\r
-\r
-\r
- if (extent<0x0B) return INVALID_STORY_FILE_RV;\r
-\r
- for(i=0;i<extent;i++) if (memcmp((char *)story_file+i,"UUID://",7)==0) break;\r
- if (i<extent) /* Found explicit IFID */\r
- {\r
- for(j=i+7;j<extent && ((char *)story_file)[j]!='/';j++);\r
- if (j<extent)\r
- {\r
- i+=7;\r
- ASSERT_OUTPUT_SIZE(j-i);\r
- memcpy(output,(char *)story_file+i,j-i);\r
- output[j-i]=0;\r
- return 1;\r
- }\r
- }\r
- \r
- memcpy(ser, (char *) story_file+0x03, 8);\r
- ser[8]=0;\r
-\r
- for(j=0;j<8;j++)\r
- if (!isalnum(ser[j])) ser[j]='-';\r
-\r
-\r
- sprintf(buffer,"HUGO-%d-%02X-%02X-%s",story_file[0],story_file[1], story_file[2],ser);\r
-\r
- ASSERT_OUTPUT_SIZE((signed) strlen(buffer)+1);\r
- strcpy((char *)output,buffer);\r
- return 1;\r
-}\r
-\r
-static int32 read_hugo_addx(unsigned char *from)\r
-{\r
- return ((unsigned int) from[0])| ((unsigned int)from[1] << 8);\r
-}\r
-\r
-static int32 claim_story_file(void *story_file, int32 extent)\r
-{\r
- unsigned char *sf=(unsigned char *)story_file;\r
- int32 i;\r
- int32 scale;\r
-\r
- if (!story_file || extent < 0x28) return INVALID_STORY_FILE_RV;\r
-\r
- if (sf[0]<34) scale=4;\r
- else scale=16;\r
- for(i=3;i<0x0B;i++) if (sf[i]<0x20 || sf[i]>0x7e) return INVALID_STORY_FILE_RV;\r
- for(i=0x0b;i<0x18;i+=2)\r
- if (read_hugo_addx(sf+i) * scale > extent) return INVALID_STORY_FILE_RV;\r
-\r
- return VALID_STORY_FILE_RV;\r
-}\r
+++ /dev/null
-/* ifiction.c common babel interface for processing ifiction metadata\r
- * (c) 2006 By L. Ross Raszewski\r
- *\r
- * This code is freely usable for all purposes.\r
- *\r
- * This work is licensed under the Creative Commons Attribution2.5 License.\r
- * To view a copy of this license, visit\r
- * http://creativecommons.org/licenses/by/2.5/ or send a letter to\r
- * Creative Commons,\r
- * 543 Howard Street, 5th Floor,\r
- * San Francisco, California, 94105, USA.\r
- *\r
- * This file depends on treaty.h\r
- *\r
- * This file contains common routines for handling ifiction metadata strings\r
- *\r
- * int32 ifiction_get_IFID(char *metadata, char *output, int32 output_extent)\r
- * does what the babel treaty function GET_STORY_FILE_IFID_SEL would do for ifiction\r
- *\r
- * void ifiction_parse(char *md, IFCloseTag close_tag, void *close_ctx,\r
- * IFErrorHandler error_handler, void *error_ctx)\r
- * parses the given iFiction metadata. close_tag(struct XMLtag xtg, close_ctx)\r
- * is called for each tag as it is closed, error_handler(char *error, error_ctx)\r
- * is called each time a structural or logical error is found in the iFiction\r
- * This is a very simple XML parser, and probably not as good as any "real"\r
- * XML parser. Its only two benefits are that (1) it's really small, and (2)\r
- * it strictly checks the ifiction record against the Treaty of Babel\r
- * requirements\r
- *\r
- */\r
-\r
-#include "ifiction.h"\r
-#include <string.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <ctype.h>\r
-\r
-void *my_malloc(int, char *);\r
-extern char *format_registry[];\r
-\r
-\r
-static int32 llp;\r
-static char *lnlst;\r
-\r
-static char utfeol[3] = { 0xe2, 0x80, 0xa8 };\r
-static int32 getln(char *endp)\r
-{\r
- for(;lnlst<endp;lnlst++) if (*lnlst=='\n' || memcmp(lnlst,utfeol,3)==0) llp++;\r
- return llp;\r
-}\r
-\r
-\r
-static int32 ifiction_get_first_IFID(char *metadata, char *output, int32 output_extent)\r
-{\r
- char *ifid_begin, *ifid_end;\r
- \r
- ifid_begin=strstr(metadata,"<ifid>");\r
- if (!ifid_begin) return NO_REPLY_RV;\r
- ifid_begin+=6;\r
-\r
- ifid_end=strstr(ifid_begin,"</ifid>");\r
- if (!ifid_end) return NO_REPLY_RV;\r
- if (output_extent<=(ifid_end-ifid_begin)) return INVALID_USAGE_RV;\r
-\r
- memcpy(output,ifid_begin,ifid_end-ifid_begin);\r
-\r
- output[ifid_end-ifid_begin]=0;\r
-\r
- return ifid_end-metadata+7;\r
-}\r
-\r
-\r
-int32 ifiction_get_IFID(char *metadata, char *output, int32 output_extent)\r
-{\r
- int32 j=0, k;\r
-\r
- while(*metadata)\r
- {\r
- if ((k=ifiction_get_first_IFID(metadata,output,output_extent)) <= 0) break;\r
- j++;\r
- metadata+=k;\r
- output_extent-=strlen(output)+1;\r
- output+=strlen(output);\r
- *output=',';\r
- output++;\r
- }\r
- if (*(output-1)==',') *(output-1)=0;\r
- return j;\r
-}\r
-\r
-\r
-static char *leaf_tags[] = { "ifid",\r
- "format",\r
- "bafn",\r
- "title",\r
- "author",\r
- "headline",\r
- "firstpublished",\r
- "genre",\r
- "group",\r
- "description",\r
- "leafname",\r
- "url",\r
- "authoremail",\r
- "height",\r
- "width",\r
-\r
- NULL\r
- };\r
-static char *one_per[] = { "identification",\r
- "bibliographic",\r
- "format",\r
- "title",\r
- "author",\r
- "headline",\r
- "firstpublished",\r
- "genre",\r
- "group",\r
- "description",\r
- "leafname",\r
- "height",\r
- "width",\r
- "forgiveness",\r
- "colophon",\r
- NULL\r
- };\r
-\r
-static char *required[] = {\r
- "cover", "height",\r
- "cover", "width",\r
- "cover", "format",\r
- "resources", "auxiliary",\r
- "auxiliary", "leafname",\r
- "auxiliary", "description",\r
- "ifiction", "story",\r
- "story", "identification",\r
- "story", "bibliographic",\r
- "identification", "ifid",\r
- "identification", "format",\r
- "bibliographic", "title",\r
- "bibliographic", "author",\r
- "colophon", "generator",\r
- "colophon", "originated",\r
- NULL, NULL\r
- };\r
-static char *zarfian[] = {\r
- "Merciful",\r
- "Polite",\r
- "Tough",\r
- "Nasty",\r
- "Cruel",\r
- NULL\r
- };\r
-\r
-struct ifiction_info {\r
- int32 width;\r
- int32 height;\r
- int format;\r
- };\r
-static void ifiction_validate_tag(struct XMLTag *xtg, struct ifiction_info *xti, IFErrorHandler err_h, void *ectx)\r
-{\r
- int i;\r
- char ebuf[512];\r
- struct XMLTag *parent=xtg->next;\r
- if (parent)\r
- {\r
- for(i=0;leaf_tags[i];i++)\r
- if (strcmp(parent->tag,leaf_tags[i])==0)\r
- {\r
- sprintf(ebuf, "Error: (line %d) Tag <%s> is not permitted within tag <%s>",\r
- xtg->beginl,xtg->tag,parent->tag);\r
- err_h(ebuf,ectx);\r
- }\r
- for(i=0;required[i];i+=2)\r
- if (strcmp(required[i],parent->tag)==0 && strcmp(required[i+1],xtg->tag)==0)\r
- parent->rocurrences[i]=1;\r
- for(i=0;one_per[i];i++)\r
- if (strcmp(one_per[i],xtg->tag)==0)\r
- if (parent->occurences[i]) { \r
- sprintf(ebuf,"Error: (line %d) Found more than one <%s> within <%s>",xtg->beginl,xtg->tag,\r
- parent->tag);\r
- err_h(ebuf,ectx);\r
- }\r
- else parent->occurences[i]=1;\r
- }\r
- for(i=0;required[i];i+=2)\r
- if (strcmp(required[i],xtg->tag)==0 && !xtg->rocurrences[i])\r
- {\r
- sprintf(ebuf,"Error: (line %d) Tag <%s> is required within <%s>",xtg->beginl, required[i+1],xtg->tag);\r
- err_h(ebuf,ectx);\r
- }\r
- if (parent && strcmp(parent->tag,"identification")==0)\r
- {\r
- if (strcmp(xtg->tag,"format")==0)\r
- {\r
- int i;\r
- for(i=0;format_registry[i];i++) if (memcmp(xtg->begin,format_registry[i],strlen(format_registry[i]))==0) break;\r
- if (format_registry[i]) xti->format=i;\r
- else\r
- {\r
- char bf[256];\r
- memcpy(bf,xtg->begin,xtg->end-xtg->begin);\r
- bf[xtg->end-xtg->begin]=0;\r
- xti->format=-1;\r
- sprintf(ebuf,"Warning: (line %d) Unknown format %s.",xtg->beginl,bf);\r
- err_h(ebuf,ectx);\r
- }\r
- }\r
- }\r
- if (parent && strcmp(parent->tag,"cover")==0)\r
- {\r
- if (strcmp(xtg->tag,"width")==0)\r
- {\r
- int i;\r
- sscanf(xtg->begin,"%d",&i);\r
- if (i<120)\r
- {\r
- sprintf(ebuf,"Warning: (line %d) Cover art width should not be less than 120.",xtg->beginl);\r
- err_h(ebuf,ectx);\r
- }\r
- if (i>1200)\r
- {\r
- sprintf(ebuf,"Warning: (line %d) Cover art width should not exceed 1200.",xtg->beginl);\r
- err_h(ebuf,ectx);\r
- }\r
- if (!xti->width) xti->width=i;\r
- if (xti->height && (xti->width> 2 * xti->height || xti->height > 2 * xti->width))\r
- {\r
- sprintf(ebuf,"Warning: (line %d) Cover art aspect ratio exceeds 2:1.",xtg->beginl);\r
- err_h(ebuf,ectx);\r
- }\r
-\r
- }\r
- if (strcmp(xtg->tag,"height")==0)\r
- {\r
- int i;\r
- sscanf(xtg->begin,"%d",&i);\r
- if (i<120)\r
- {\r
- sprintf(ebuf,"Warning: (line %d) Cover art height should not be less than 120.",xtg->beginl);\r
- err_h(ebuf,ectx);\r
- }\r
- if (i>1200)\r
- {\r
- sprintf(ebuf,"Warning: (line %d) Cover art height should not exceed 1200.",xtg->beginl);\r
- err_h(ebuf,ectx);\r
- }\r
- if (!xti->height) xti->height=i;\r
- if (xti->width && (xti->width> 2 * xti->height || xti->height > 2 * xti->width))\r
- {\r
- sprintf(ebuf,"Warning: (line %d) Cover art aspect ratio exceeds 2:1.",xtg->beginl);\r
- err_h(ebuf,ectx);\r
- }\r
-\r
- }\r
- if (strcmp(xtg->tag,"format")==0 && memcmp(xtg->begin,"jpg",3) && memcmp(xtg->begin,"png",3))\r
- {\r
- sprintf(ebuf,"Warning: (line %d) <format> should be one of: png, jpg.",xtg->beginl);\r
- err_h(ebuf,ectx);\r
- }\r
- }\r
- if (parent && strcmp(parent->tag,"bibliographic")==0)\r
- {\r
- char *p;\r
- if (isspace(*xtg->begin)|| isspace(*(xtg->end-1)))\r
- {\r
- sprintf(ebuf,"Warning: (line %d) Extraneous spaces at beginning or end of tag <%s>.",xtg->beginl,xtg->tag);\r
- err_h(ebuf,ectx);\r
- }\r
- for(p=xtg->begin;p<xtg->end-1;p++)\r
-/* Obsoleted by Revision 6\r
- if (isspace(*p) && isspace(*(p+1)))\r
- {\r
- sprintf(ebuf,"Warning: (line %d) Extraneous spaces found in tag <%s>.",xtg->beginl, xtg->tag);\r
- err_h(ebuf,ectx);\r
- }\r
- else if (isspace(*p) && *p!=' ')\r
- {\r
- sprintf(ebuf,"Warning: (line %d) Improper whitespace character found in tag <%s>.",xtg->beginl, xtg->tag);\r
- err_h(ebuf,ectx);\r
-\r
- }\r
-*/\r
- if (strcmp(xtg->tag, "description") && xtg->end-xtg->begin > 240)\r
- { \r
- sprintf(ebuf,"Warning: (line %d) Tag <%s> length exceeds treaty guidelines",xtg->beginl, xtg->tag);\r
- err_h(ebuf,ectx);\r
- }\r
- if (strcmp(xtg->tag, "description")==0 && xtg->end-xtg->begin > 2400)\r
- {\r
- sprintf(ebuf,"Warning: (line %d) Tag <%s> length exceeds treaty guidelines",xtg->beginl, xtg->tag);\r
- err_h(ebuf,ectx);\r
- }\r
- if (strcmp(xtg->tag,"firstpublished")==0)\r
- {\r
- int l=xtg->end-xtg->begin;\r
- if ((l!=4 && l!=10) ||\r
- (!isdigit(xtg->begin[0]) ||\r
- !isdigit(xtg->begin[1]) ||\r
- !isdigit(xtg->begin[2]) ||\r
- !isdigit(xtg->begin[3])) ||\r
- (l==10 && ( xtg->begin[4]!='-' ||\r
- xtg->begin[7]!='-' ||\r
- !isdigit(xtg->begin[5]) ||\r
- !isdigit(xtg->begin[6]) ||\r
- !(xtg->begin[5]=='0' || xtg->begin[5]=='1') ||\r
- !(xtg->begin[5]=='0' || xtg->begin[6]<='2') ||\r
- !isdigit(xtg->begin[8]) ||\r
- !isdigit(xtg->begin[9]))))\r
- {\r
- sprintf(ebuf,"Warning: (line %d) Tag <%s> should be format YYYY or YYYY-MM-DD",xtg->beginl, xtg->tag);\r
- err_h(ebuf,ectx);\r
- }\r
- }\r
- if (strcmp(xtg->tag,"seriesnumber")==0)\r
- {\r
- char *l;\r
- if (*xtg->begin=='0' && xtg->end!=xtg->begin+1)\r
- {\r
- sprintf(ebuf,"Warning: (line %d) Tag <%s> should not use leading zeroes",xtg->beginl, xtg->tag);\r
- err_h(ebuf,ectx);\r
- }\r
-\r
- for(l=xtg->begin;l<xtg->end;l++) if (!isdigit(*l))\r
- {\r
- sprintf(ebuf,"Warning: (line %d) Tag <%s> should be a positive number",xtg->beginl, xtg->tag);\r
- err_h(ebuf,ectx);\r
- }\r
- }\r
- if (strcmp(xtg->tag,"forgiveness")==0)\r
- {\r
- int l;\r
- for(l=0;zarfian[l];l++) if (memcmp(xtg->begin,zarfian[l],strlen(zarfian[l]))==0) break;\r
- if (!zarfian[l])\r
- {\r
- sprintf(ebuf,"Warning: (line %d) <forgiveness> should be one of: Merciful, Polite, Tough, Cruel",xtg->beginl);\r
- err_h(ebuf,ectx);\r
- }\r
- }\r
- }\r
- if (xti->format>0)\r
- { \r
- for(i=0;format_registry[i];i++) if (strcmp(xtg->tag,format_registry[i])==0) break;\r
- if (format_registry[i] && xti->format !=i)\r
- {\r
- sprintf(ebuf,"Warning: (line %d) Found <%s> tag, but story is identified as %s.",xtg->beginl, xtg->tag, format_registry[xti->format]);\r
- err_h(ebuf,ectx);\r
- }\r
- }\r
- if (strcmp(xtg->tag,"story")==0)\r
- {\r
- xti->format=-1;\r
- xti->width=0;\r
- xti->height=0;\r
- }\r
-\r
-}\r
-\r
-\r
-\r
-void ifiction_parse(char *md, IFCloseTag close_tag, void *close_ctx, IFErrorHandler error_handler, void *error_ctx)\r
-{\r
-char *xml, buffer[2400], *aep, *mda=md, ebuffer[512];\r
-struct XMLTag *parse=NULL, *xtg;\r
-struct ifiction_info xti;\r
-char BOM[3]={ 0xEF, 0xBB, 0xBF};\r
-xti.width=0;\r
-xti.height=0;\r
-xti.format=-1;\r
-llp=1;\r
-lnlst=md;\r
-\r
-while(*mda && isspace(*mda)) mda++;\r
-if (memcmp(mda,BOM,3)==0)\r
-{ mda+=3;\r
- while(*mda && isspace(*mda)) mda++;\r
-}\r
-\r
-\r
-if (strncmp("<?xml version=\"1.0\" encoding=\"UTF-8\"?>",mda,\r
- strlen("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"))\r
- &&\r
- strncmp("<?xml version=\"1.0\" encoding=\"utf-8\"?>",mda,\r
- strlen("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"))\r
- )\r
-{\r
- error_handler("Error: XML header not found.",error_ctx);\r
- return;\r
-}\r
-\r
-xml=strstr(md,"<ifindex");\r
-if (!xml) {\r
- error_handler("Error: <ifindex> not found",error_ctx);\r
- return;\r
- }\r
-while(xml && *xml)\r
-{\r
- char *bp, *ep, *tp;\r
- while(*xml&&*xml!='<') xml++;\r
- if (!*xml) break;\r
- bp=xml;\r
- tp=strchr(bp+1,'<');\r
- ep=strchr(bp+1,'>');\r
- if (!ep) break;\r
- if (tp && tp < ep)\r
- { xml=tp; continue; }\r
- if (!tp) tp=ep+1; \r
- if (bp[1]=='/') /* end tag */\r
- {\r
- strncpy(buffer,bp+2,(ep-bp)-2);\r
- buffer[(ep-bp)-2]=0;\r
- if (parse && strcmp(buffer,parse->tag)==0)\r
- { /* copasetic. Close the tag */\r
- xtg=parse;\r
- parse=xtg->next;\r
- xtg->end=ep-strlen(buffer)-2;\r
- ifiction_validate_tag(xtg,&xti,error_handler, error_ctx);\r
- close_tag(xtg,close_ctx);\r
- free(xtg);\r
- }\r
- else\r
- {\r
- for(xtg=parse;xtg && strcmp(buffer,xtg->tag);xtg=xtg->next);\r
- if (xtg) /* Intervening unclosed tags */\r
- { for(xtg=parse;xtg && strcmp(buffer,parse->tag);xtg=parse)\r
- {\r
- xtg->end=xml-1;\r
- parse=xtg->next;\r
- sprintf(ebuffer,"Error: (line %d) unclosed <%s> tag",xtg->beginl,xtg->tag);\r
- error_handler(ebuffer,error_ctx);\r
- ifiction_validate_tag(xtg,&xti,error_handler, error_ctx);\r
- close_tag(xtg,close_ctx);\r
- free(xtg);\r
- }\r
- xtg=parse;\r
- if (xtg)\r
- {\r
- xtg->end=xml-1;\r
- parse=xtg->next;\r
- ifiction_validate_tag(xtg,&xti, error_handler, error_ctx);\r
- close_tag(xtg,close_ctx);\r
- free(xtg);\r
- }\r
- }\r
- else\r
- { \r
- sprintf(ebuffer,"Error: (line %d) saw </%s> without <%s>",getln(xml), buffer,buffer);\r
- error_handler(ebuffer,error_ctx);\r
- }\r
- }\r
-\r
- }\r
- else if(*(ep-1)=='/' || bp[1]=='!') /* unterminated tag */\r
- {\r
- /* Do nothing */\r
- }\r
- else /* Terminated tag beginning */\r
- {\r
- int i;\r
- xtg=(struct XMLTag *)my_malloc(sizeof(struct XMLTag),"XML Tag");\r
- xtg->next=parse;\r
- xtg->beginl=getln(bp);\r
- for(i=0;bp[i+1]=='_' || bp[i+1]=='-' || isalnum(bp[i+1]);i++)\r
- xtg->tag[i]=bp[i+1];\r
- if (i==0)\r
- { xml=tp;\r
- free(xtg);\r
- continue;\r
- }\r
- parse=xtg;\r
- parse->tag[i]=0;\r
- strncpy(parse->fulltag,bp+1,ep-bp-1);\r
- parse->fulltag[ep-bp-1]=0;\r
- parse->begin=ep+1;\r
- }\r
- xml=tp;\r
-}\r
- while (parse)\r
- {\r
- xtg=parse;\r
- xtg->end=aep-1;\r
- parse=xtg->next;\r
- sprintf(ebuffer,"Error: (line %d) Unclosed tag <%s>",xtg->beginl,xtg->tag);\r
- ifiction_validate_tag(xtg,&xti,error_handler, error_ctx);\r
- close_tag(xtg,close_ctx);\r
- free(xtg);\r
- }\r
-}\r
-\r
-struct get_tag\r
-{\r
- char *tag;\r
- char *parent;\r
- char *output;\r
- char *target;\r
-};\r
-\r
-static void ifiction_null_eh(char *e, void *c)\r
-{\r
- if (e || c) { }\r
-\r
-}\r
-\r
-static void ifiction_find_value(struct XMLTag *xtg, void *xti)\r
-{\r
- struct get_tag *gt=(struct get_tag *)xti;\r
-\r
- if (gt->output && !gt->target) return;\r
- if (gt->target && gt->output && strcmp(gt->output,gt->target)==0) { gt->target=NULL; free(gt->output); gt->output=NULL; }\r
- if (((!xtg->next && !gt->parent) || (xtg->next && gt->parent && strcmp(xtg->next->tag,gt->parent)==0)) &&\r
- strcmp(xtg->tag,gt->tag)==0)\r
- {\r
- int32 l = xtg->end-xtg->begin;\r
-\r
- if (gt->output) free(gt->output);\r
- gt->output=(char *)my_malloc(l+1, "ifiction tag buffer");\r
- memcpy(gt->output, xtg->begin, l);\r
- gt->output[l]=0;\r
-\r
- }\r
-}\r
-\r
-\r
-char *ifiction_get_tag(char *md, char *p, char *t, char *from)\r
-{\r
- struct get_tag gt;\r
- gt.output=NULL;\r
- gt.parent=p;\r
- gt.tag=t;\r
- gt.target=from;\r
- ifiction_parse(md,ifiction_find_value,>,ifiction_null_eh,NULL);\r
- if (gt.target){ if (gt.output) free(gt.output); return NULL; }\r
- return gt.output;\r
-}\r
+++ /dev/null
-/* ifiction.h declarations for the babel ifiction API\r
- * (c) 2006 By L. Ross Raszewski\r
- *\r
- * This code is freely usable for all purposes.\r
- *\r
- * This work is licensed under the Creative Commons Attribution2.5 License.\r
- * To view a copy of this license, visit\r
- * http://creativecommons.org/licenses/by/2.5/ or send a letter to\r
- * Creative Commons,\r
- * 543 Howard Street, 5th Floor,\r
- * San Francisco, California, 94105, USA.\r
- *\r
- */\r
-\r
-#ifndef IFICTION_H\r
-#define IFICTION_H\r
-\r
-#include "treaty.h"\r
-\r
-/* Babel's notion of an XML tag */\r
-struct XMLTag\r
-{\r
- int32 beginl; /* Beginning line number */\r
- char tag[256]; /* name of the tag */\r
- char fulltag[256]; /* Full text of the opening tag */\r
- char *begin; /* Points to the beginning of the tag's content */\r
- char *end; /* Points to the end of the tag's content.\r
- setting *end=0 will turn begin into a string\r
- containing the tag's content (But if you do this, you\r
- should restore the original value of *end before\r
- allowing control to return to the ifiction parser) */\r
- char occurences[256]; /* Tables used internally to find missing required tags */\r
- char rocurrences[256];\r
- struct XMLTag *next; /* The tag's parent */\r
-\r
-};\r
-\r
-typedef void (*IFCloseTag)(struct XMLTag *, void *);\r
-typedef void (*IFErrorHandler)(char *, void *);\r
-\r
-\r
-void ifiction_parse(char *md, IFCloseTag close_tag, void *close_ctx, IFErrorHandler error_handler, void *error_ctx);\r
-int32 ifiction_get_IFID(char *metadata, char *output, int32 output_extent);\r
-char *ifiction_get_tag(char *md, char *p, char *t, char *from);\r
-#endif\r
+++ /dev/null
-/* level9.c Treaty of Babel module for Level 9 files\r
- * 2006 By L. Ross Raszewski\r
- *\r
- * Note that this module will handle both bare Level 9 A-Code and\r
- * Spectrum .SNA snapshots. It will not handle compressed .Z80 images.\r
- *\r
- * The Level 9 identification algorithm is based in part on the algorithm\r
- * used by Paul David Doherty's l9cut program.\r
- *\r
- * This file depends on treaty_builder.h\r
- *\r
- * This file is public domain, but note that any changes to this file\r
- * may render it noncompliant with the Treaty of Babel\r
- */\r
-\r
-#define FORMAT level9\r
-#define HOME_PAGE "http://www.if-legends.org/~l9memorial/html/home.html"\r
-#define FORMAT_EXT ".l9,.sna"\r
-#define NO_METADATA\r
-#define NO_COVER\r
-\r
-#include "treaty_builder.h"\r
-#include <ctype.h>\r
-#include <stdio.h>\r
-#include <string.h>\r
-\r
-struct l9rec {\r
- int32 length;\r
- unsigned char chk;\r
- char *ifid;\r
-};\r
-\r
-\r
-static struct l9rec l9_registry[] = {\r
- { 0x3a31, 0xe5, "LEVEL9-001-1" },\r
- { 0x8333, 0xb7, "LEVEL9-001-1" },\r
- { 0x7c6f, 0x0f, "LEVEL9-001-1" },\r
- { 0x72fa, 0x8b, "LEVEL9-001-1" },\r
- { 0x38dd, 0x31, "LEVEL9-001-A" },\r
- { 0x39c0, 0x44, "LEVEL9-001-B" },\r
- { 0x3a12, 0x8f, "LEVEL9-001-C" },\r
- { 0x37f1, 0x77, "LEVEL9-001-2" },\r
- { 0x844d, 0x50, "LEVEL9-001-2" },\r
- { 0x738e, 0x5b, "LEVEL9-001-2" },\r
- { 0x3900, 0x1c, "LEVEL9-001-3" },\r
- { 0x8251, 0x5f, "LEVEL9-001-3" },\r
- { 0x7375, 0xe5, "LEVEL9-001-3" },\r
- { 0x3910, 0xac, "LEVEL9-001-4" },\r
- { 0x7a78, 0x5e, "LEVEL9-001-4" },\r
- { 0x78d5, 0xe3, "LEVEL9-001-4" },\r
- { 0x3ad6, 0xa7, "LEVEL9-001-5" },\r
- { 0x38a5, 0x0f, "LEVEL9-001-6" },\r
- { 0x361e, 0x7e, "LEVEL9-001-7" },\r
- { 0x3934, 0x75, "LEVEL9-001-8" },\r
- { 0x3511, 0xcc, "LEVEL9-001-9" },\r
- { 0x593a, 0xaf, "LEVEL9-002-1" },\r
- { 0x7931, 0xb9, "LEVEL9-002-1" },\r
- { 0x6841, 0x4a, "LEVEL9-002-1" },\r
- { 0x57e6, 0x8a, "LEVEL9-002-2" },\r
- { 0x7cdf, 0xa5, "LEVEL9-002-2" },\r
- { 0x6bc0, 0x62, "LEVEL9-002-2" },\r
- { 0x5819, 0xcd, "LEVEL9-002-3" },\r
- { 0x7a0c, 0x97, "LEVEL9-002-3" },\r
- { 0x692c, 0x21, "LEVEL9-002-3" },\r
- { 0x579b, 0xad, "LEVEL9-002-4" },\r
- { 0x7883, 0xe2, "LEVEL9-002-4" },\r
- { 0x670a, 0x94, "LEVEL9-002-4" },\r
- { 0x5323, 0xb7, "LEVEL9-003" },\r
- { 0x6e60, 0x83, "LEVEL9-003" },\r
- { 0x5b58, 0x50, "LEVEL9-003" },\r
- { 0x63b6, 0x2e, "LEVEL9-003" },\r
- { 0x6968, 0x32, "LEVEL9-003" },\r
- { 0x5b50, 0x66, "LEVEL9-003" },\r
- { 0x6970, 0xd6, "LEVEL9-003" },\r
- { 0x5ace, 0x11, "LEVEL9-003" },\r
- { 0x6e5c, 0xf6, "LEVEL9-003" },\r
- { 0x1929, 0x00, "LEVEL9-004-DEMO" },\r
- { 0x40e0, 0x02, "LEVEL9-004-DEMO" },\r
- { 0x3ebb, 0x00, "LEVEL9-004-en" },\r
- { 0x3e4f, 0x00, "LEVEL9-004-en" },\r
- { 0x3e8f, 0x00, "LEVEL9-004-en" },\r
- { 0x0fd8, 0x00, "LEVEL9-004-en" },\r
- { 0x14a3, 0x00, "LEVEL9-004-en" },\r
- { 0x110f, 0x00, "LEVEL9-004-fr" },\r
- { 0x4872, 0x00, "LEVEL9-004-de" },\r
- { 0x4846, 0x00, "LEVEL9-004-de" },\r
- { 0x11f5, 0x00, "LEVEL9-004-de" },\r
- { 0x11f5, 0x00, "LEVEL9-004-de" },\r
- { 0x76f4, 0x5e, "LEVEL9-005" },\r
- { 0x5b16, 0x3b, "LEVEL9-005" },\r
- { 0x6c8e, 0xb6, "LEVEL9-005" },\r
- { 0x6f4d, 0xcb, "LEVEL9-005" },\r
- { 0x6f6a, 0xa5, "LEVEL9-005" },\r
- { 0x5e31, 0x7c, "LEVEL9-005" },\r
- { 0x6f70, 0x40, "LEVEL9-005" },\r
- { 0x6f6e, 0x78, "LEVEL9-005" },\r
- { 0x5a8e, 0xf2, "LEVEL9-005" },\r
- { 0x76f4, 0x5a, "LEVEL9-005" },\r
- { 0x630e, 0x8d, "LEVEL9-006" },\r
- { 0x630e, 0xbe, "LEVEL9-006" },\r
- { 0x6f0c, 0x95, "LEVEL9-006" },\r
- { 0x593a, 0x80, "LEVEL9-006" },\r
- { 0x6bd2, 0x65, "LEVEL9-006" },\r
- { 0x6dc0, 0x63, "LEVEL9-006" },\r
- { 0x58a6, 0x24, "LEVEL9-006" },\r
- { 0x6de8, 0x4c, "LEVEL9-006" },\r
- { 0x58a3, 0x38, "LEVEL9-006" },\r
- { 0x63be, 0xd6, "LEVEL9-007" },\r
- { 0x378c, 0x8d, "LEVEL9-007" },\r
- { 0x63be, 0x0a, "LEVEL9-007" },\r
- { 0x34b3, 0x20, "LEVEL9-008" },\r
- { 0x34b3, 0xc7, "LEVEL9-008" },\r
- { 0x34b3, 0x53, "LEVEL9-008" },\r
- { 0xb1a9, 0x80, "LEVEL9-009-1" },\r
- { 0x908e, 0x0d, "LEVEL9-009-1" },\r
- { 0xad41, 0xa8, "LEVEL9-009-1" },\r
- { 0xb1aa, 0xad, "LEVEL9-009-1" },\r
- { 0x8aab, 0xc0, "LEVEL9-009-1" },\r
- { 0xb0ec, 0xc2, "LEVEL9-009-1" },\r
- { 0xb19e, 0x92, "LEVEL9-009-1" },\r
- { 0x5ff0, 0xf8, "LEVEL9-009-1" },\r
- { 0x52aa, 0xdf, "LEVEL9-009-1" },\r
- { 0xab9d, 0x31, "LEVEL9-009-2" },\r
- { 0x8f6f, 0x0a, "LEVEL9-009-2" },\r
- { 0xa735, 0xf7, "LEVEL9-009-2" },\r
- { 0xab8b, 0xbf, "LEVEL9-009-2" },\r
- { 0x8ac8, 0x9a, "LEVEL9-009-2" },\r
- { 0xaf82, 0x83, "LEVEL9-009-2" },\r
- { 0x6024, 0x01, "LEVEL9-009-2" },\r
- { 0x6ffa, 0xdb, "LEVEL9-009-2" },\r
- { 0xae28, 0x87, "LEVEL9-009-3" },\r
- { 0x9060, 0xbb, "LEVEL9-009-3" },\r
- { 0xa9c0, 0x9e, "LEVEL9-009-3" },\r
- { 0xae16, 0x81, "LEVEL9-009-3" },\r
- { 0x8a93, 0x4f, "LEVEL9-009-3" },\r
- { 0xb3e6, 0xab, "LEVEL9-009-3" },\r
- { 0x6036, 0x3d, "LEVEL9-009-3" },\r
- { 0x723a, 0x69, "LEVEL9-009-3" },\r
- { 0xd188, 0x13, "LEVEL9-010-1" },\r
- { 0x9089, 0xce, "LEVEL9-010-1" },\r
- { 0xb770, 0x03, "LEVEL9-010-1" },\r
- { 0xd19b, 0xad, "LEVEL9-010-1" },\r
- { 0x8ab7, 0x68, "LEVEL9-010-1" },\r
- { 0xd183, 0x83, "LEVEL9-010-1" },\r
- { 0x5a38, 0xf7, "LEVEL9-010-1" },\r
- { 0x76a0, 0x3a, "LEVEL9-010-1" },\r
- { 0xc594, 0x03, "LEVEL9-010-2" },\r
- { 0x908d, 0x80, "LEVEL9-010-2" },\r
- { 0xb741, 0xb6, "LEVEL9-010-2" },\r
- { 0xc5a5, 0xfe, "LEVEL9-010-2" },\r
- { 0x8b1e, 0x84, "LEVEL9-010-2" },\r
- { 0xc58f, 0x65, "LEVEL9-010-2" },\r
- { 0x531a, 0xed, "LEVEL9-010-2" },\r
- { 0x7674, 0x0b, "LEVEL9-010-2" },\r
- { 0xd79f, 0xb5, "LEVEL9-010-3" },\r
- { 0x909e, 0x9f, "LEVEL9-010-3" },\r
- { 0xb791, 0xa1, "LEVEL9-010-3" },\r
- { 0xd7ae, 0x9e, "LEVEL9-010-3" },\r
- { 0x8b1c, 0xa8, "LEVEL9-010-3" },\r
- { 0xd79a, 0x57, "LEVEL9-010-3" },\r
- { 0x57e4, 0x19, "LEVEL9-010-3" },\r
- { 0x765e, 0xba, "LEVEL9-010-3" },\r
- { 0xbb93, 0x36, "LEVEL9-011-1" },\r
- { 0x898a, 0x43, "LEVEL9-011-1" },\r
- { 0x8970, 0x6b, "LEVEL9-011-1" },\r
- { 0xbb6e, 0xa6, "LEVEL9-011-1" },\r
- { 0x86d0, 0xb7, "LEVEL9-011-1" },\r
- { 0xbb6e, 0xad, "LEVEL9-011-1" },\r
- { 0x46ec, 0x64, "LEVEL9-011-1" },\r
- { 0x74e0, 0x92, "LEVEL9-011-1" },\r
- { 0xc58e, 0x4a, "LEVEL9-011-2" },\r
- { 0x8b9f, 0x61, "LEVEL9-011-2" },\r
- { 0x8b90, 0x4e, "LEVEL9-011-2" },\r
- { 0xc58e, 0x43, "LEVEL9-011-2" },\r
- { 0x8885, 0x22, "LEVEL9-011-2" },\r
- { 0x6140, 0x18, "LEVEL9-011-2" },\r
- { 0x6dbc, 0x97, "LEVEL9-011-2" },\r
- { 0xcb9a, 0x0f, "LEVEL9-011-3" },\r
- { 0x8af9, 0x61, "LEVEL9-011-3" },\r
- { 0x8aea, 0x4e, "LEVEL9-011-3" },\r
- { 0xcb9a, 0x08, "LEVEL9-011-3" },\r
- { 0x87e5, 0x0e, "LEVEL9-011-3" },\r
- { 0x640e, 0xc1, "LEVEL9-011-3" },\r
- { 0x7402, 0x07, "LEVEL9-011-3" },\r
- { 0xbba4, 0x94, "LEVEL9-012-1" },\r
- { 0xc0cf, 0x4e, "LEVEL9-012-1" },\r
- { 0x8afc, 0x07, "LEVEL9-012-1" },\r
- { 0x8feb, 0xba, "LEVEL9-012-1" },\r
- { 0xb4c9, 0x94, "LEVEL9-012-1" },\r
- { 0xc0bd, 0x57, "LEVEL9-012-1" },\r
- { 0x8ade, 0xf2, "LEVEL9-012-1" },\r
- { 0x4fd2, 0x9d, "LEVEL9-012-1" },\r
- { 0x5c7a, 0x44, "LEVEL9-012-1" },\r
- { 0x768c, 0xe8, "LEVEL9-012-1" },\r
- { 0xd0c0, 0x56, "LEVEL9-012-2" },\r
- { 0xd5e9, 0x6a, "LEVEL9-012-2" },\r
- { 0x8aec, 0x13, "LEVEL9-012-2" },\r
- { 0x8f6b, 0xfa, "LEVEL9-012-2" },\r
- { 0xb729, 0x51, "LEVEL9-012-2" },\r
- { 0xd5d7, 0x99, "LEVEL9-012-2" },\r
- { 0x8b0e, 0xfb, "LEVEL9-012-2" },\r
- { 0x4dac, 0xa8, "LEVEL9-012-2" },\r
- { 0x53a2, 0x1e, "LEVEL9-012-2" },\r
- { 0x76b0, 0x1d, "LEVEL9-012-2" },\r
- { 0xb6ac, 0xc6, "LEVEL9-012-3" },\r
- { 0xbb8f, 0x1a, "LEVEL9-012-3" },\r
- { 0x8aba, 0x0d, "LEVEL9-012-3" },\r
- { 0x8f71, 0x2f, "LEVEL9-012-3" },\r
- { 0xb702, 0xe4, "LEVEL9-012-3" },\r
- { 0xbb7d, 0x17, "LEVEL9-012-3" },\r
- { 0x8ab3, 0xc1, "LEVEL9-012-3" },\r
- { 0x4f96, 0x22, "LEVEL9-012-3" },\r
- { 0x5914, 0x22, "LEVEL9-012-3" },\r
- { 0x765e, 0x4f, "LEVEL9-012-3" },\r
- { 0x5eb9, 0x30, "LEVEL9-013" },\r
- { 0x5eb9, 0x5d, "LEVEL9-013" },\r
- { 0x5eb9, 0x6e, "LEVEL9-013" },\r
- { 0xb257, 0xf8, "LEVEL9-013" },\r
- { 0xb576, 0x2a, "LEVEL9-013" },\r
- { 0x8d78, 0x3a, "LEVEL9-013" },\r
- { 0x9070, 0x43, "LEVEL9-013" },\r
- { 0xb38c, 0x37, "LEVEL9-013" },\r
- { 0xb563, 0x6a, "LEVEL9-013" },\r
- { 0xb57c, 0x44, "LEVEL9-013" },\r
- { 0xb260, 0xe5, "LEVEL9-013" },\r
- { 0x8950, 0xa1, "LEVEL9-013" },\r
- { 0xb579, 0x89, "LEVEL9-013" },\r
- { 0x579e, 0x97, "LEVEL9-013" },\r
- { 0x69fe, 0x56, "LEVEL9-013" },\r
- { 0x6f1e, 0xda, "LEVEL9-013" },\r
- { 0x5671, 0xbc, "LEVEL9-014" },\r
- { 0x6fc6, 0x14, "LEVEL9-014" },\r
- { 0x5aa4, 0xc1, "LEVEL9-014" },\r
- { 0x7410, 0x5e, "LEVEL9-014" },\r
- { 0x5aa4, 0xc1, "LEVEL9-014" },\r
- { 0x5aa4, 0xc1, "LEVEL9-014" },\r
- { 0xb797, 0x1f, "LEVEL9-014" },\r
- { 0xbaca, 0x3a, "LEVEL9-014" },\r
- { 0x8c46, 0xf0, "LEVEL9-014" },\r
- { 0x8f51, 0xb2, "LEVEL9-014" },\r
- { 0xb451, 0xa8, "LEVEL9-014" },\r
- { 0xbab2, 0x87, "LEVEL9-014" },\r
- { 0xbac7, 0x7f, "LEVEL9-014" },\r
- { 0xb7a0, 0x7e, "LEVEL9-014" },\r
- { 0x8a60, 0x2a, "LEVEL9-014" },\r
- { 0xbac4, 0x80, "LEVEL9-014" },\r
- { 0x579a, 0x2a, "LEVEL9-014" },\r
- { 0x5a50, 0xa9, "LEVEL9-014" },\r
- { 0x6108, 0xdd, "LEVEL9-014" },\r
- { 0x506c, 0xf0, "LEVEL9-015" },\r
- { 0x505d, 0x32, "LEVEL9-015" },\r
- { 0xa398, 0x82, "LEVEL9-015" },\r
- { 0xa692, 0xd1, "LEVEL9-015" },\r
- { 0x8d56, 0xd3, "LEVEL9-015" },\r
- { 0x903f, 0x6b, "LEVEL9-015" },\r
- { 0xa4e2, 0xa6, "LEVEL9-015" },\r
- { 0xa67c, 0xb8, "LEVEL9-015" },\r
- { 0xa69e, 0x6c, "LEVEL9-015" },\r
- { 0xa3a4, 0xdf, "LEVEL9-015" },\r
- { 0x8813, 0x11, "LEVEL9-015" },\r
- { 0xa698, 0x41, "LEVEL9-015" },\r
- { 0x5500, 0x50, "LEVEL9-015" },\r
- { 0x6888, 0x8d, "LEVEL9-015" },\r
- { 0x6da0, 0xb8, "LEVEL9-015" },\r
- { 0x6064, 0xbd, "LEVEL9-016" },\r
- { 0x6064, 0x01, "LEVEL9-016" },\r
- { 0x6047, 0x6c, "LEVEL9-016" },\r
- { 0x6064, 0xda, "LEVEL9-016" },\r
- { 0x6064, 0x95, "LEVEL9-016" },\r
- { 0x60c4, 0x28, "LEVEL9-016" },\r
- { 0x5cb7, 0xfe, "LEVEL9-016" },\r
- { 0x5ca1, 0x33, "LEVEL9-016" },\r
- { 0x5cb7, 0x64, "LEVEL9-016" },\r
- { 0x7d16, 0xe6, "LEVEL9-016" },\r
- { 0x639c, 0x8b, "LEVEL9-016" },\r
- { 0x60f7, 0x68, "LEVEL9-016" },\r
- { 0x772f, 0xca, "LEVEL9-016" },\r
- { 0x7cff, 0xf8, "LEVEL9-016" },\r
- { 0x7cf8, 0x24, "LEVEL9-016" },\r
- { 0x7d14, 0xe8, "LEVEL9-016" },\r
- { 0x7c55, 0x18, "LEVEL9-016" },\r
- { 0x5f43, 0xca, "LEVEL9-016" },\r
- { 0xc132, 0x14, "LEVEL9-017-1" },\r
- { 0xbeab, 0x2d, "LEVEL9-017-1" },\r
- { 0x9058, 0xcf, "LEVEL9-017-1" },\r
- { 0xbe94, 0xcc, "LEVEL9-017-1" },\r
- { 0x8a21, 0xf4, "LEVEL9-017-1" },\r
- { 0x55ce, 0xa1, "LEVEL9-017-1" },\r
- { 0x5cbc, 0xa5, "LEVEL9-017-1" },\r
- { 0x762e, 0x82, "LEVEL9-017-1" },\r
- { 0x99bd, 0x65, "LEVEL9-017-2" },\r
- { 0x8f43, 0xc9, "LEVEL9-017-2" },\r
- { 0x8a12, 0xe3, "LEVEL9-017-2" },\r
- { 0x54a6, 0xa9, "LEVEL9-017-2" },\r
- { 0x5932, 0x4e, "LEVEL9-017-2" },\r
- { 0x5bd6, 0x35, "LEVEL9-017-2" },\r
- { 0xbcb6, 0x7a, "LEVEL9-017-3 (Amiga/PC/ST)" },\r
- { 0x90ac, 0x68, "LEVEL9-017-3" },\r
- { 0x8a16, 0xcc, "LEVEL9-017-3" },\r
- { 0x51bc, 0xe3, "LEVEL9-017-3" },\r
- { 0x5860, 0x95, "LEVEL9-017-3" },\r
- { 0x6fa8, 0xa4, "LEVEL9-017-3" },\r
- { 0x5fab, 0x5c, "LEVEL9-018" },\r
- { 0x5fab, 0x2f, "LEVEL9-018" },\r
- { 0x7b31, 0x6e, "LEVEL9-018" },\r
- { 0x67a3, 0x9d, "LEVEL9-018" },\r
- { 0x6bf8, 0x3f, "LEVEL9-018" },\r
- { 0x7363, 0x65, "LEVEL9-018" },\r
- { 0x7b2f, 0x70, "LEVEL9-018" },\r
- { 0x7b2f, 0x70, "LEVEL9-018" },\r
- { 0x6541, 0x02, "LEVEL9-018" },\r
- { 0x5834, 0x42, "LEVEL9-019-1" },\r
- { 0x765d, 0xcd, "LEVEL9-019-1" },\r
- { 0x6ce5, 0x58, "LEVEL9-019-1" },\r
- { 0x56dd, 0x51, "LEVEL9-019-2" },\r
- { 0x6e58, 0x07, "LEVEL9-019-2" },\r
- { 0x68da, 0xc1, "LEVEL9-019-2" },\r
- { 0x5801, 0x53, "LEVEL9-019-3" },\r
- { 0x7e98, 0x6a, "LEVEL9-019-3" },\r
- { 0x6c67, 0x9a, "LEVEL9-019-3" },\r
- { 0x54a4, 0x01, "LEVEL9-019-4" },\r
- { 0x81e2, 0xd5, "LEVEL9-019-4" },\r
- { 0x6d91, 0xb9, "LEVEL9-019-4" },\r
- { 0x5828, 0xbd, "LEVEL9-020" },\r
- { 0x6d84, 0xf9, "LEVEL9-020" },\r
- { 0x6d84, 0xc8, "LEVEL9-020" },\r
- { 0x6030, 0x47, "LEVEL9-020" },\r
- { 0x772b, 0xcd, "LEVEL9-020" },\r
- { 0x546c, 0xb7, "LEVEL9-020" },\r
- { 0x7cd9, 0x0c, "LEVEL9-020" },\r
- { 0x60dd, 0xf2, "LEVEL9-020" },\r
- { 0x6161, 0xf3, "LEVEL9-020" },\r
- { 0x788d, 0x72, "LEVEL9-020" },\r
- { 0x7cd7, 0x0e, "LEVEL9-020" },\r
- { 0x5ebb, 0xf1, "LEVEL9-020" },\r
-\r
- { 0, 0, NULL }\r
-};\r
-\r
-\r
-\r
-static int32 read_l9_int(unsigned char *sf)\r
-{\r
- return ((int32) sf[1]) << 8 | sf[0];\r
-\r
-}\r
-static int v2_recognition (unsigned char *sf, int32 extent, int32 *l, unsigned char *c)\r
-{\r
- int32 i, j;\r
- for (i=0;i<extent-20;i++)\r
- if ((read_l9_int(sf+i+4) == 0x0020) &&\r
- (read_l9_int(sf+i+0x0a) == 0x8000) &&\r
- (read_l9_int(sf+i+0x14) == read_l9_int(sf+i+0x16)))\r
- {\r
- *l=read_l9_int(sf+i+0x1c);\r
- if (*l && *l+i <=extent)\r
- {\r
- *c=0;\r
- for(j=0;j<=*l;j++)\r
- *c+=sf[i+j];\r
- return 2;\r
- }\r
- }\r
- return 0;\r
-}\r
-static int v1_recognition(unsigned char *sf, int32 extent, char **ifid)\r
-{\r
- int32 i;\r
- unsigned char a = 0xff, b = 0xff;\r
-\r
- for (i=0;i<extent-20;i++)\r
- if (memcmp(sf+i,"ATTAC",5)==0 && sf[i+5]==0xcb)\r
- { \r
- a = sf[i+6];\r
- break;\r
- }\r
- for (;i<(extent-20);i++)\r
- if (memcmp(sf+i,"BUNC",4)==0 && sf[i+4]==0xc8)\r
- {\r
- b = sf[i + 5];\r
- break;\r
- }\r
- if (a == 0xff && b == 0xff)\r
- return 0;\r
- if (a == 0x14 && b == 0xff) *ifid="LEVEL9-006";\r
- else if (a == 0x15 && b == 0x5d) *ifid="LEVEL9-013";\r
- else if (a == 0x1a && b == 0x24) *ifid="LEVEL9-005";\r
- else if (a == 0x20 && b == 0x3b) *ifid="LEVEL9-003";\r
- else *ifid=NULL;\r
- return 1;\r
-}\r
-static int v3_recognition_phase (int phase,unsigned char *sf, int32 extent, int32 *l, unsigned char *c)\r
-{\r
- int32 end, i, j, ll;\r
- ll=0;\r
- for (i=0;i<extent-20;i++)\r
- {\r
- if (ll) break;\r
- *l = read_l9_int(sf+i);\r
- end=*l+i;\r
- if (phase!=3)\r
- {\r
- if (end <= (extent - 2) &&\r
- (\r
- ((phase == 2) ||\r
- (((sf[end-1] == 0) &&\r
- (sf[end-2] == 0)) ||\r
- ((sf[end+1] == 0) &&\r
- (sf[end+2] == 0))))\r
- && (*l>0x4000) && (*l<=0xdb00)))\r
- if ((*l!=0) && (sf[i+0x0d] == 0))\r
- for (j=i;j<i+16;j+=2)\r
- if (((read_l9_int(sf+j)+read_l9_int(sf+j+2))==read_l9_int(sf+j+4))\r
- && ((read_l9_int(sf+j)+read_l9_int(sf+j+2))))\r
- ll++;\r
- }\r
- else\r
- {\r
- if ((extent>0x0fd0) && (end <= (extent - 2)) &&\r
- (((read_l9_int(sf+i+2) + read_l9_int(sf+i+4))==read_l9_int(sf+i+6))\r
- && (read_l9_int(sf+i+2) != 0) && (read_l9_int(sf+i+4)) != 0) &&\r
- (((read_l9_int(sf+i+6) + read_l9_int(sf+i+8)) == read_l9_int(sf+i+10))\r
- && ((sf[i + 18] == 0x2a) || (sf[i + 18] == 0x2c))\r
- && (sf[i + 19] == 0) && (sf[i + 20] == 0) && (sf[i + 21] == 0)))\r
- ll = 2;\r
- }\r
- if (ll>1)\r
- {\r
- *c=0;\r
- if (phase==3) ll=1;\r
- else\r
- { char checksum=0;\r
- *c = sf[end];\r
- for (j=i;j<=end;j++)\r
- checksum += sf[j];\r
- if (!checksum) ll=1;\r
- else ll=0;\r
- }\r
- } else ll=0;\r
- }\r
-\r
- if (ll) return *l < 0x8500 ? 3:4;\r
- return 0;\r
-}\r
-static char *get_l9_ifid(int32 length, unsigned char chk)\r
-{\r
- int i;\r
- for(i=0;l9_registry[i].length;i++)\r
- if (length==l9_registry[i].length && chk==l9_registry[i].chk) return l9_registry[i].ifid;\r
- return NULL;\r
-}\r
-static int get_l9_version(unsigned char *sf, int32 extent, char **ifid)\r
-{\r
- int i;\r
- int32 l;\r
- unsigned char c;\r
- if (v2_recognition(sf,extent, &l, &c)) { *ifid=get_l9_ifid(l,c); return 2; }\r
- l=0; c=0;\r
- i=v3_recognition_phase(1,sf,extent, &l, &c);\r
- if (i) { *ifid=get_l9_ifid(l,c); return i; }\r
- if (v1_recognition(sf,extent, ifid)) return 1;\r
- l=0; c=0;\r
- i=v3_recognition_phase(2,sf,extent, &l, &c);\r
- if (i) { *ifid=get_l9_ifid(l,c); return i; }\r
- i=v3_recognition_phase(3,sf,extent, &l, &c);\r
- *ifid=NULL;\r
- return i;\r
-}\r
-\r
-static int32 claim_story_file(void *story, int32 extent)\r
-{\r
- char *ifid=NULL;\r
- if (get_l9_version((unsigned char *) story,extent, &ifid))\r
- if (ifid) return VALID_STORY_FILE_RV;\r
- else return NO_REPLY_RV;\r
- return INVALID_STORY_FILE_RV; \r
-}\r
-\r
-\r
-\r
-static int32 get_story_file_IFID(void *story_file, int32 extent, char *output, int32 output_extent)\r
-{\r
- char *ifid=NULL;\r
- int i=get_l9_version((unsigned char *)story_file, extent, &ifid);\r
- if (!i) return INVALID_STORY_FILE_RV;\r
- if (ifid)\r
- {\r
- ASSERT_OUTPUT_SIZE((signed) strlen(ifid)+1);\r
- strcpy(output,ifid);\r
- return 1;\r
- }\r
- ASSERT_OUTPUT_SIZE(10);\r
- sprintf(output,"LEVEL9-%d-",i);\r
- return INCOMPLETE_REPLY_RV;\r
-}\r
+++ /dev/null
-/* magscrolls.c Treaty of Babel module for Z-code files\r
- * 2006 By L. Ross Raszewski\r
- *\r
- * This file depends on treaty_builder.h\r
- *\r
- * This file is public domain, but note that any changes to this file\r
- * may render it noncompliant with the Treaty of Babel\r
- */\r
-\r
-#define FORMAT magscrolls\r
-#define HOME_PAGE "http://www.if-legends.org/~msmemorial/memorial.htm"\r
-#define FORMAT_EXT ".mag"\r
-#define NO_COVER\r
-#define NO_METADATA\r
-\r
-#include "treaty_builder.h"\r
-#include <ctype.h>\r
-#include <stdio.h>\r
-\r
-struct maginfo\r
-{\r
- int gv;\r
- char header[21];\r
- char *title;\r
- int bafn;\r
- int year;\r
- char *ifid;\r
- char *author;\r
- char *meta;\r
-};\r
-\r
-\r
-static struct maginfo manifest[] = {\r
- { 0, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000",\r
- "The Pawn",\r
- 0,\r
- 1985,\r
- "MAGNETIC-1",\r
- "Rob Steggles",\r
- },\r
- { 1, "\000\004\000\001\007\370\000\000\340\000\000\000\041\064\000\000\040\160\000\000",\r
- "Guild of Thieves",\r
- 0,\r
- 1987,\r
- "MAGNETIC-2",\r
- "Rob Steggles",\r
- },\r
- { 2, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000",\r
- "Jinxter",\r
- 0,\r
- 1987,\r
- "MAGNETIC-3",\r
- "Georgina Sinclair and Michael Bywater",\r
- },\r
- { 4, "\000\004\000\001\045\140\000\001\000\000\000\000\161\017\000\000\035\210\000\001",\r
- "Corruption",\r
- 0,\r
- 1988,\r
- "MAGNETIC-4",\r
- "Rob Steggles and Hugh Steers",\r
- },\r
- { 4, "\000\004\000\001\044\304\000\001\000\000\000\000\134\137\000\000\040\230\000\001",\r
- "Fish!",\r
- 0,\r
- 1988,\r
- "MAGNETIC-5",\r
- "John Molloy, Pete Kemp, Phil South, Rob Steggles",\r
- },\r
- { 4, "\000\003\000\000\377\000\000\000\340\000\000\000\221\000\000\000\036\000\000\001",\r
- "Corruption",\r
- 0,\r
- 1988,\r
- "MAGNETIC-4",\r
- "Rob Steggles and Hugh Steers",\r
- },\r
- { 4, "\000\003\000\001\000\000\000\000\340\000\000\000\175\000\000\000\037\000\000\001",\r
- "Fish!",\r
- 0,\r
- 1988,\r
- "MAGNETIC-5",\r
- "John Molloy, Pete Kemp, Phil South, Rob Steggles",\r
- },\r
- { 4, "\000\003\000\000\335\000\000\000\140\000\000\000\064\000\000\000\023\000\000\000",\r
- "Myth",\r
- 0,\r
- 1989,\r
- "MAGNETIC-6",\r
- "Paul Findley",\r
- },\r
- { 4, "\000\004\000\001\122\074\000\001\000\000\000\000\114\146\000\000\057\240\000\001",\r
- "Wonderland",\r
- 0,\r
- 1990,\r
- "MAGNETIC-7",\r
- "David Bishop",\r
- },\r
- { 0, "0", NULL, 0, 0, NULL, NULL }\r
- };\r
-\r
-static int32 get_story_file_IFID(void *story_file, int32 extent, char *output, int32 output_extent)\r
-{\r
- int i;\r
- unsigned char *sf=(unsigned char *)story_file;\r
- if (extent < 42) return INVALID_STORY_FILE_RV;\r
-\r
- for(i=0;manifest[i].title;i++)\r
- if ((sf[13]<3 && manifest[i].gv==sf[13]) || memcmp(manifest[i].header,sf+12,20)==0)\r
- {\r
- ASSERT_OUTPUT_SIZE(((int32) strlen(manifest[i].ifid)+1));\r
- strcpy(output,manifest[i].ifid);\r
- return 1;\r
- }\r
- strcpy(output,"MAGNETIC-");\r
- return INCOMPLETE_REPLY_RV;\r
-}\r
-\r
-static int32 claim_story_file(void *story_file, int32 extent)\r
-{\r
- if (extent<42 ||\r
- memcmp(story_file,"MaSc",4)\r
- ) return INVALID_STORY_FILE_RV;\r
- return VALID_STORY_FILE_RV;\r
-}\r
-\r
+++ /dev/null
-/*
- Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-
- L. Peter Deutsch
- ghost@aladdin.com
-
- */
-/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
-/*
- Independent implementation of MD5 (RFC 1321).
-
- This code implements the MD5 Algorithm defined in RFC 1321, whose
- text is available at
- http://www.ietf.org/rfc/rfc1321.txt
- The code is derived from the text of the RFC, including the test suite
- (section A.5) but excluding the rest of Appendix A. It does not include
- any code or documentation that is identified in the RFC as being
- copyrighted.
-
- The original and principal author of md5.c is L. Peter Deutsch
- <ghost@aladdin.com>. Other authors are noted in the change history
- that follows (in reverse chronological order):
-
- 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
- either statically or dynamically; added missing #include <string.h>
- in library.
- 2002-03-11 lpd Corrected argument list for main(), and added int return
- type, in test program and T value program.
- 2002-02-21 lpd Added missing #include <stdio.h> in test program.
- 2000-07-03 lpd Patched to eliminate warnings about "constant is
- unsigned in ANSI C, signed in traditional"; made test program
- self-checking.
- 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
- 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
- 1999-05-03 lpd Original version.
- */
-
-#include "md5.h"
-#include <string.h>
-
-#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
-#ifdef ARCH_IS_BIG_ENDIAN
-# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
-#else
-# define BYTE_ORDER 0
-#endif
-
-#define T_MASK ((md5_word_t)~0)
-#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
-#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
-#define T3 0x242070db
-#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
-#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
-#define T6 0x4787c62a
-#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
-#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
-#define T9 0x698098d8
-#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
-#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
-#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
-#define T13 0x6b901122
-#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
-#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
-#define T16 0x49b40821
-#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
-#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
-#define T19 0x265e5a51
-#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
-#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
-#define T22 0x02441453
-#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
-#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
-#define T25 0x21e1cde6
-#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
-#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
-#define T28 0x455a14ed
-#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
-#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
-#define T31 0x676f02d9
-#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
-#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
-#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
-#define T35 0x6d9d6122
-#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
-#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
-#define T38 0x4bdecfa9
-#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
-#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
-#define T41 0x289b7ec6
-#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
-#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
-#define T44 0x04881d05
-#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
-#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
-#define T47 0x1fa27cf8
-#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
-#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
-#define T50 0x432aff97
-#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
-#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
-#define T53 0x655b59c3
-#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
-#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
-#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
-#define T57 0x6fa87e4f
-#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
-#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
-#define T60 0x4e0811a1
-#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
-#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
-#define T63 0x2ad7d2bb
-#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
-
-
-static void
-md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
-{
- md5_word_t
- a = pms->abcd[0], b = pms->abcd[1],
- c = pms->abcd[2], d = pms->abcd[3];
- md5_word_t t;
-#if BYTE_ORDER > 0
- /* Define storage only for big-endian CPUs. */
- md5_word_t X[16];
-#else
- /* Define storage for little-endian or both types of CPUs. */
- md5_word_t xbuf[16];
- const md5_word_t *X;
-#endif
-
- {
-#if BYTE_ORDER == 0
- /*
- * Determine dynamically whether this is a big-endian or
- * little-endian machine, since we can use a more efficient
- * algorithm on the latter.
- */
- static const int w = 1;
-
- if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
-#endif
-#if BYTE_ORDER <= 0 /* little-endian */
- {
- /*
- * On little-endian machines, we can process properly aligned
- * data without copying it.
- */
- if (!((data - (const md5_byte_t *)0) & 3)) {
- /* data are properly aligned */
- X = (const md5_word_t *)data;
- } else {
- /* not aligned */
- memcpy(xbuf, data, 64);
- X = xbuf;
- }
- }
-#endif
-#if BYTE_ORDER == 0
- else /* dynamic big-endian */
-#endif
-#if BYTE_ORDER >= 0 /* big-endian */
- {
- /*
- * On big-endian machines, we must arrange the bytes in the
- * right order.
- */
- const md5_byte_t *xp = data;
- int i;
-
-# if BYTE_ORDER == 0
- X = xbuf; /* (dynamic only) */
-# else
-# define xbuf X /* (static only) */
-# endif
- for (i = 0; i < 16; ++i, xp += 4)
- xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
- }
-#endif
- }
-
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
-
- /* Round 1. */
- /* Let [abcd k s i] denote the operation
- a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
-#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + F(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 0, 7, T1);
- SET(d, a, b, c, 1, 12, T2);
- SET(c, d, a, b, 2, 17, T3);
- SET(b, c, d, a, 3, 22, T4);
- SET(a, b, c, d, 4, 7, T5);
- SET(d, a, b, c, 5, 12, T6);
- SET(c, d, a, b, 6, 17, T7);
- SET(b, c, d, a, 7, 22, T8);
- SET(a, b, c, d, 8, 7, T9);
- SET(d, a, b, c, 9, 12, T10);
- SET(c, d, a, b, 10, 17, T11);
- SET(b, c, d, a, 11, 22, T12);
- SET(a, b, c, d, 12, 7, T13);
- SET(d, a, b, c, 13, 12, T14);
- SET(c, d, a, b, 14, 17, T15);
- SET(b, c, d, a, 15, 22, T16);
-#undef SET
-
- /* Round 2. */
- /* Let [abcd k s i] denote the operation
- a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
-#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + G(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 1, 5, T17);
- SET(d, a, b, c, 6, 9, T18);
- SET(c, d, a, b, 11, 14, T19);
- SET(b, c, d, a, 0, 20, T20);
- SET(a, b, c, d, 5, 5, T21);
- SET(d, a, b, c, 10, 9, T22);
- SET(c, d, a, b, 15, 14, T23);
- SET(b, c, d, a, 4, 20, T24);
- SET(a, b, c, d, 9, 5, T25);
- SET(d, a, b, c, 14, 9, T26);
- SET(c, d, a, b, 3, 14, T27);
- SET(b, c, d, a, 8, 20, T28);
- SET(a, b, c, d, 13, 5, T29);
- SET(d, a, b, c, 2, 9, T30);
- SET(c, d, a, b, 7, 14, T31);
- SET(b, c, d, a, 12, 20, T32);
-#undef SET
-
- /* Round 3. */
- /* Let [abcd k s t] denote the operation
- a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + H(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 5, 4, T33);
- SET(d, a, b, c, 8, 11, T34);
- SET(c, d, a, b, 11, 16, T35);
- SET(b, c, d, a, 14, 23, T36);
- SET(a, b, c, d, 1, 4, T37);
- SET(d, a, b, c, 4, 11, T38);
- SET(c, d, a, b, 7, 16, T39);
- SET(b, c, d, a, 10, 23, T40);
- SET(a, b, c, d, 13, 4, T41);
- SET(d, a, b, c, 0, 11, T42);
- SET(c, d, a, b, 3, 16, T43);
- SET(b, c, d, a, 6, 23, T44);
- SET(a, b, c, d, 9, 4, T45);
- SET(d, a, b, c, 12, 11, T46);
- SET(c, d, a, b, 15, 16, T47);
- SET(b, c, d, a, 2, 23, T48);
-#undef SET
-
- /* Round 4. */
- /* Let [abcd k s t] denote the operation
- a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
-#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + I(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 0, 6, T49);
- SET(d, a, b, c, 7, 10, T50);
- SET(c, d, a, b, 14, 15, T51);
- SET(b, c, d, a, 5, 21, T52);
- SET(a, b, c, d, 12, 6, T53);
- SET(d, a, b, c, 3, 10, T54);
- SET(c, d, a, b, 10, 15, T55);
- SET(b, c, d, a, 1, 21, T56);
- SET(a, b, c, d, 8, 6, T57);
- SET(d, a, b, c, 15, 10, T58);
- SET(c, d, a, b, 6, 15, T59);
- SET(b, c, d, a, 13, 21, T60);
- SET(a, b, c, d, 4, 6, T61);
- SET(d, a, b, c, 11, 10, T62);
- SET(c, d, a, b, 2, 15, T63);
- SET(b, c, d, a, 9, 21, T64);
-#undef SET
-
- /* Then perform the following additions. (That is increment each
- of the four registers by the value it had before this block
- was started.) */
- pms->abcd[0] += a;
- pms->abcd[1] += b;
- pms->abcd[2] += c;
- pms->abcd[3] += d;
-}
-
-void
-md5_init(md5_state_t *pms)
-{
- pms->count[0] = pms->count[1] = 0;
- pms->abcd[0] = 0x67452301;
- pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
- pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
- pms->abcd[3] = 0x10325476;
-}
-
-void
-md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
-{
- const md5_byte_t *p = data;
- int left = nbytes;
- int offset = (pms->count[0] >> 3) & 63;
- md5_word_t nbits = (md5_word_t)(nbytes << 3);
-
- if (nbytes <= 0)
- return;
-
- /* Update the message length. */
- pms->count[1] += nbytes >> 29;
- pms->count[0] += nbits;
- if (pms->count[0] < nbits)
- pms->count[1]++;
-
- /* Process an initial partial block. */
- if (offset) {
- int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
-
- memcpy(pms->buf + offset, p, copy);
- if (offset + copy < 64)
- return;
- p += copy;
- left -= copy;
- md5_process(pms, pms->buf);
- }
-
- /* Process full blocks. */
- for (; left >= 64; p += 64, left -= 64)
- md5_process(pms, p);
-
- /* Process a final partial block. */
- if (left)
- memcpy(pms->buf, p, left);
-}
-
-void
-md5_finish(md5_state_t *pms, md5_byte_t digest[16])
-{
- static const md5_byte_t pad[64] = {
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- md5_byte_t data[8];
- int i;
-
- /* Save the length before padding. */
- for (i = 0; i < 8; ++i)
- data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
- /* Pad to 56 bytes mod 64. */
- md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
- /* Append the length. */
- md5_append(pms, data, 8);
- for (i = 0; i < 16; ++i)
- digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
-}
+++ /dev/null
-/*
- Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-
- L. Peter Deutsch
- ghost@aladdin.com
-
- */
-/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
-/*
- Independent implementation of MD5 (RFC 1321).
-
- This code implements the MD5 Algorithm defined in RFC 1321, whose
- text is available at
- http://www.ietf.org/rfc/rfc1321.txt
- The code is derived from the text of the RFC, including the test suite
- (section A.5) but excluding the rest of Appendix A. It does not include
- any code or documentation that is identified in the RFC as being
- copyrighted.
-
- The original and principal author of md5.h is L. Peter Deutsch
- <ghost@aladdin.com>. Other authors are noted in the change history
- that follows (in reverse chronological order):
-
- 2002-04-13 lpd Removed support for non-ANSI compilers; removed
- references to Ghostscript; clarified derivation from RFC 1321;
- now handles byte order either statically or dynamically.
- 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
- 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
- added conditionalization for C++ compilation from Martin
- Purschke <purschke@bnl.gov>.
- 1999-05-03 lpd Original version.
- */
-
-#ifndef md5_INCLUDED
-# define md5_INCLUDED
-
-/*
- * This package supports both compile-time and run-time determination of CPU
- * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
- * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
- * defined as non-zero, the code will be compiled to run only on big-endian
- * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
- * run on either big- or little-endian CPUs, but will run slightly less
- * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
- */
-
-typedef unsigned char md5_byte_t; /* 8-bit byte */
-typedef unsigned int md5_word_t; /* 32-bit word */
-
-/* Define the state of the MD5 Algorithm. */
-typedef struct md5_state_s {
- md5_word_t count[2]; /* message length in bits, lsw first */
- md5_word_t abcd[4]; /* digest buffer */
- md5_byte_t buf[64]; /* accumulate block */
-} md5_state_t;
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/* Initialize the algorithm. */
-void md5_init(md5_state_t *pms);
-
-/* Append a string to the message. */
-void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
-
-/* Finish the message and return the digest. */
-void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
-
-#ifdef __cplusplus
-} /* end extern "C" */
-#endif
-
-#endif /* md5_INCLUDED */
+++ /dev/null
-/* misc.h : miscellany for babel\r
- * This file is public domain\r
- * 2006 by L. Ross Raszewski\r
- */\r
-\r
-#include <stdlib.h>\r
-#include <stdio.h>\r
-\r
-void *my_malloc(int size, char *rs)\r
-{\r
- void *buf=calloc(size,1);\r
- if (size && !buf)\r
- {\r
- fprintf(stderr,"Error: Memory exceeded (%d for %s)!\n",size,rs);\r
- exit(2);\r
- }\r
- return buf;\r
-}\r
-\r
+++ /dev/null
-/* modules.h Declaration of treaty modules for the babel program\r
- * (c) 2006 By L. Ross Raszewski\r
- *\r
- * This code is freely usable for all purposes.\r
- *\r
- * This work is licensed under the Creative Commons Attribution2.5 License.\r
- * To view a copy of this license, visit\r
- * http://creativecommons.org/licenses/by/2.5/ or send a letter to\r
- * Creative Commons,\r
- * 543 Howard Street, 5th Floor,\r
- * San Francisco, California, 94105, USA.\r
- *\r
- * This file depends upon treaty.h and all the references treaty modules\r
- *\r
- * Persons wishing to add support for a new module to babel need only\r
- * add a line in the form below. New modules should be positioned according\r
- * to their popularity. If this file is being used in tandem with register.c\r
- * (as it is in babel), then being dishonest about the popularity of an added\r
- * system will make the program non-compliant with the treaty of Babel\r
- *\r
- * REGISTER_NAME is used as a placeholder for formats which are specified\r
- * as existing by the treaty but for which no handler yet exists.\r
- * remove the REGISTER_NAME for any format which has a registered treaty.\r
- */\r
-\r
-\r
-#include "treaty.h"\r
-#undef REGISTER_TREATY\r
-#undef REGISTER_CONTAINER\r
-#undef REGISTER_NAME\r
-#ifdef TREATY_REGISTER\r
-#ifdef CONTAINER_REGISTER\r
-#ifdef FORMAT_REGISTER\r
-#define REGISTER_TREATY(x) #x,\r
-#define REGISTER_NAME(x) #x,\r
-#define REGISTER_CONTAINER(x)\r
-#else\r
-#define REGISTER_TREATY(x)\r
-#define REGISTER_CONTAINER(x) x##_treaty,\r
-#define REGISTER_NAME(x)\r
-#endif\r
-#else\r
-#define REGISTER_TREATY(x) x##_treaty,\r
-#define REGISTER_CONTAINER(x)\r
-#define REGISTER_NAME(x)\r
-#endif\r
-#else\r
-#define REGISTER_TREATY(x) int32 x##_treaty(int32, void *, int32, void *, int32);\r
-#define REGISTER_CONTAINER(x) int32 x##_treaty(int32, void *, int32, void *, int32);\r
-#define REGISTER_NAME(x)\r
-#endif\r
-\r
-\r
-REGISTER_CONTAINER(blorb)\r
-REGISTER_TREATY(zcode)\r
-REGISTER_TREATY(glulx)\r
-REGISTER_TREATY(tads2)\r
-REGISTER_TREATY(tads3)\r
-REGISTER_TREATY(hugo)\r
-REGISTER_TREATY(alan)\r
-REGISTER_TREATY(adrift)\r
-REGISTER_TREATY(level9)\r
-REGISTER_TREATY(agt)\r
-REGISTER_TREATY(magscrolls)\r
-REGISTER_TREATY(advsys)\r
-REGISTER_TREATY(executable)\r
-\r
-\r
-\r
-\r
+++ /dev/null
-/* register.c Register modules for the babel handler api\r
- *\r
- * 2006 by L. Ross Raszewski\r
- *\r
- * This code is freely usable for all purposes.\r
- *\r
- * This work is licensed under the Creative Commons Attribution2.5 License.\r
- * To view a copy of this license, visit\r
- * http://creativecommons.org/licenses/by/2.5/ or send a letter to\r
- * Creative Commons,\r
- * 543 Howard Street, 5th Floor,\r
- * San Francisco, California, 94105, USA.\r
- *\r
- * This file depends on modules.h\r
- *\r
- * The purpose of this file is to create the treaty_registry array.\r
- * This array is a null-terminated list of the known treaty modules.\r
- */\r
-\r
-#include <stdlib.h>\r
-#include "modules.h"\r
-\r
-\r
-TREATY treaty_registry[] = {\r
- #define TREATY_REGISTER\r
- #include "modules.h"\r
- NULL\r
- };\r
-\r
-TREATY container_registry[] = {\r
- #define CONTAINER_REGISTER\r
- #include "modules.h"\r
- NULL\r
-\r
-};\r
-\r
+++ /dev/null
-/* register_ifiction.c Register modules for babel's ifiction API\r
- *\r
- * 2006 by L. Ross Raszewski\r
- *\r
- * This code is freely usable for all purposes.\r
- *\r
- * This work is licensed under the Creative Commons Attribution2.5 License.\r
- * To view a copy of this license, visit\r
- * http://creativecommons.org/licenses/by/2.5/ or send a letter to\r
- * Creative Commons,\r
- * 543 Howard Street, 5th Floor,\r
- * San Francisco, California, 94105, USA.\r
- *\r
- * This file depends on modules.h\r
- *\r
- * This version of register.c is stripped down to include only the\r
- * needed functionality for the ifiction api\r
- */\r
-\r
-#include <stdlib.h>\r
-#include "treaty.h"\r
-\r
-char *format_registry[] = {\r
- #define TREATY_REGISTER\r
- #define CONTAINER_REGISTER\r
- #define FORMAT_REGISTER\r
- #include "modules.h"\r
- NULL\r
-};\r
+++ /dev/null
-/* \r
- * tads.c - Treaty of Babel common functions for tads2 and tads3 modules\r
- * \r
- * This file depends on treaty_builder.h\r
- * \r
- * This file is public domain, but note that any changes to this file may\r
- * render it noncompliant with the Treaty of Babel\r
- * \r
- * Modified\r
- *. 04/08/2006 LRRaszewski - changed babel API calls to threadsafe versions\r
- *. 04/08/2006 MJRoberts - initial implementation\r
- */\r
-\r
-\r
-#include "treaty.h"\r
-#include <ctype.h>\r
-#include <stdio.h>\r
-#include <string.h>\r
-#include <stdlib.h>\r
-#include "tads.h"\r
-#include "md5.h"\r
-\r
-#define ASSERT_OUTPUT_SIZE(x) \\r
- do { if (output_extent < (x)) return INVALID_USAGE_RV; } while (0)\r
-\r
-#define T2_SIGNATURE "TADS2 bin\012\015\032"\r
-#define T3_SIGNATURE "T3-image\015\012\032"\r
-\r
-#ifndef FALSE\r
-#define FALSE 0\r
-#endif\r
-#ifndef TRUE\r
-#define TRUE 1\r
-#endif\r
-\r
-/* ------------------------------------------------------------------------ */\r
-/*\r
- * private structures \r
- */\r
-\r
-/*\r
- * resource information structure - this encapsulates the location and size\r
- * of a binary resource object embedded in a story file \r
- */\r
-typedef struct resinfo resinfo;\r
-struct resinfo\r
-{\r
- /* pointer and length of the data in the story file buffer */\r
- const char *ptr;\r
- int32 len;\r
-\r
- /* tads major version (currently, 2 or 3) */\r
- int tads_version;\r
-};\r
-\r
-/*\r
- * Name/value pair list entry \r
- */\r
-typedef struct valinfo valinfo;\r
-struct valinfo\r
-{\r
- const char *name;\r
- size_t name_len;\r
-\r
- /* value string */\r
- char *val;\r
- size_t val_len;\r
-\r
- /* next entry in the list */\r
- valinfo *nxt;\r
-};\r
-\r
-\r
-/* ------------------------------------------------------------------------ */\r
-/*\r
- * forward declarations \r
- */\r
-static valinfo *parse_game_info(const void *story_file, int32 story_len,\r
- int *version);\r
-static int find_resource(const void *story_file, int32 story_len,\r
- const char *resname, resinfo *info);\r
-static int find_cover_art(const void *story_file, int32 story_len,\r
- resinfo *resp, int32 *image_format,\r
- int32 *width, int32 *height);\r
-static int t2_find_res(const void *story_file, int32 story_len,\r
- const char *resname, resinfo *info);\r
-static int t3_find_res(const void *story_file, int32 story_len,\r
- const char *resname, resinfo *info);\r
-static valinfo *find_by_key(valinfo *list_head, const char *key);\r
-static void delete_valinfo_list(valinfo *head);\r
-static int32 generate_md5_ifid(void *story_file, int32 extent,\r
- char *output, int32 output_extent);\r
-static int32 synth_ifiction(valinfo *vals, int tads_version,\r
- char *buf, int32 bufsize,\r
- void *story_file, int32 extent);\r
-static int get_png_dim(const void *img, int32 extent,\r
- int32 *xout, int32 *yout);\r
-static int get_jpeg_dim(const void *img, int32 extent,\r
- int32 *xout, int32 *yout);\r
-\r
-\r
-\r
-/* ------------------------------------------------------------------------ */\r
-/*\r
- * Get the IFID for a given story file. \r
- */\r
-int32 tads_get_story_file_IFID(void *story_file, int32 extent,\r
- char *output, int32 output_extent)\r
-{\r
- valinfo *vals;\r
- \r
- /* if we have GameInfo, try looking for an IFID there */\r
- if ((vals = parse_game_info(story_file, extent, 0)) != 0)\r
- {\r
- valinfo *val;\r
- int found = 0;\r
- \r
- /* find the "IFID" key */\r
- if ((val = find_by_key(vals, "IFID")) != 0)\r
- {\r
- char *p;\r
- \r
- /* copy the output as a null-terminated string */\r
- ASSERT_OUTPUT_SIZE((int32)val->val_len + 1);\r
- memcpy(output, val->val, val->val_len);\r
- output[val->val_len] = '\0';\r
-\r
- /* \r
- * count up the IFIDs in the buffer - there might be more than\r
- * one, separated by commas \r
- */\r
- for (found = 1, p = output ; *p != '\0' ; ++p)\r
- {\r
- /* if this is a comma, it delimits a new IFID */\r
- if (*p == ',')\r
- ++found;\r
- }\r
- }\r
-\r
- /* delete the GameInfo list */\r
- delete_valinfo_list(vals);\r
-\r
- /* if we found an IFID, indicate how many results we found */\r
- if (found != 0)\r
- return found;\r
- }\r
-\r
- /* \r
- * we didn't find an IFID in the GameInfo, so generate a default IFID\r
- * using the MD5 method \r
- */\r
- return generate_md5_ifid(story_file, extent, output, output_extent);\r
-}\r
-\r
-/*\r
- * Get the size of the ifiction metadata for the game \r
- */\r
-int32 tads_get_story_file_metadata_extent(void *story_file, int32 extent)\r
-{\r
- valinfo *vals;\r
- int32 ret;\r
- int ver;\r
- \r
- /*\r
- * First, make sure we have a GameInfo record. If we don't, simply\r
- * indicate that there's no metadata to fetch. \r
- */\r
- if ((vals = parse_game_info(story_file, extent, &ver)) == 0)\r
- return NO_REPLY_RV;\r
-\r
- /*\r
- * Run the ifiction synthesizer with no output buffer, to calculate the\r
- * size we need. \r
- */\r
- ret = synth_ifiction(vals, ver, 0, 0, story_file, extent);\r
-\r
- /* delete the value list */\r
- delete_valinfo_list(vals);\r
-\r
- /* return the required size */\r
- return ret;\r
-}\r
-\r
-/*\r
- * Get the ifiction metadata for the game\r
- */\r
-int32 tads_get_story_file_metadata(void *story_file, int32 extent,\r
- char *buf, int32 bufsize)\r
-{\r
- valinfo *vals;\r
- int32 ret;\r
- int ver;\r
-\r
- /* make sure we have metadata to fetch */\r
- if ((vals = parse_game_info(story_file, extent, &ver)) == 0)\r
- return NO_REPLY_RV;\r
-\r
- /* synthesize the ifiction data into the output buffer */\r
- ret = synth_ifiction(vals, ver, buf, bufsize, story_file, extent);\r
-\r
- /* if that required more space than we had available, return an error */\r
- if (ret > bufsize)\r
- ret = INVALID_USAGE_RV;\r
-\r
- /* delete the value list */\r
- delete_valinfo_list(vals);\r
-\r
- /* return the result */\r
- return ret;\r
-}\r
-\r
-/*\r
- * Get the size of the cover art \r
- */\r
-int32 tads_get_story_file_cover_extent(void *story_file, int32 story_len)\r
-{\r
- resinfo res;\r
- \r
- /* look for the cover art resource */\r
- if (find_cover_art(story_file, story_len, &res, 0, 0, 0))\r
- return res.len;\r
- else\r
- return NO_REPLY_RV;\r
-}\r
-\r
-/*\r
- * Get the format of the cover art \r
- */\r
-int32 tads_get_story_file_cover_format(void *story_file, int32 story_len)\r
-{\r
- int32 typ;\r
-\r
- /* look for CoverArt.jpg */\r
- if (find_cover_art(story_file, story_len, 0, &typ, 0, 0))\r
- return typ;\r
- else\r
- return NO_REPLY_RV;\r
-}\r
-\r
-/*\r
- * Get the cover art data \r
- */\r
-int32 tads_get_story_file_cover(void *story_file, int32 story_len,\r
- void *outbuf, int32 output_extent)\r
-{\r
- resinfo res;\r
-\r
- /* look for CoverArt.jpg, then for CoverArt.png */\r
- if (find_cover_art(story_file, story_len, &res, 0, 0, 0))\r
- {\r
- /* got it - copy the data to the buffer */\r
- ASSERT_OUTPUT_SIZE(res.len);\r
- memcpy(outbuf, res.ptr, res.len);\r
-\r
- /* success */\r
- return res.len;\r
- }\r
-\r
- /* otherwise, we didn't find it */\r
- return NO_REPLY_RV;\r
-}\r
-\r
-/* ------------------------------------------------------------------------ */\r
-/*\r
- * Generate a default IFID using the MD5 hash method \r
- */\r
-static int32 generate_md5_ifid(void *story_file, int32 extent,\r
- char *output, int32 output_extent)\r
-{\r
- md5_state_t md5;\r
- unsigned char md5_buf[16];\r
- char *p;\r
- int i;\r
-\r
- /* calculate the MD5 hash of the story file */\r
- md5_init(&md5);\r
- md5_append(&md5, story_file, extent);\r
- md5_finish(&md5, md5_buf);\r
-\r
- /* make sure we have room to store the result */\r
- ASSERT_OUTPUT_SIZE(39);\r
-\r
- /* the prefix is "TADS2-" or "TADS3-", depending on the format */\r
- if (tads_match_sig(story_file, extent, T2_SIGNATURE))\r
- strcpy(output, "TADS2-");\r
- else\r
- strcpy(output, "TADS3-");\r
-\r
- /* the rest is the MD5 hash of the file, as hex digits */\r
- for (i = 0, p = output + strlen(output) ; i < 16 ; p += 2, ++i)\r
- sprintf(p, "%02X", md5_buf[i]);\r
-\r
- /* indicate that we found one result */\r
- return 1;\r
-}\r
-\r
-/* ------------------------------------------------------------------------ */\r
-/*\r
- * Some UTF-8 utility functions and macros. We use our own rather than the\r
- * ctype.h macros because we're parsing UTF-8 text. \r
- */\r
-\r
-/* is c a space? */\r
-#define u_isspace(c) ((unsigned char)(c) < 128 && isspace(c))\r
-\r
-/* is c a horizontal space? */\r
-#define u_ishspace(c) (u_isspace(c) && (c) != '\n' && (c) != '\r')\r
-\r
-/* is-newline - matches \n, \r, and \u2028 */\r
-static int u_isnl(const char *p, int32 len)\r
-{\r
- return (*p == '\n' \r
- || *p == '\r'\r
- || (len >= 3\r
- && *(unsigned char *)p == 0xe2\r
- && *(unsigned char *)(p+1) == 0x80\r
- && *(unsigned char *)(p+2) == 0xa8));\r
-}\r
-\r
-/* skip to the next utf-8 character */\r
-static void nextc(const char **p, int32 *len)\r
-{\r
- /* skip the first byte */\r
- if (*len != 0)\r
- ++*p, --*len;\r
-\r
- /* skip continuation bytes */\r
- while (*len != 0 && (**p & 0xC0) == 0x80)\r
- ++*p, --*len;\r
-}\r
-\r
-/* skip to the previous utf-8 character */\r
-static void prevc(const char **p, int32 *len)\r
-{\r
- /* move back one byte */\r
- --*p, ++*len;\r
-\r
- /* keep skipping as long as we're looking at continuation characters */\r
- while ((**p & 0xC0) == 0x80)\r
- --*p, ++*len;\r
-}\r
-\r
-/*\r
- * Skip a newline sequence. Skips all common conventions, including \n,\r
- * \r, \n\r, \r\n, and \u2028. \r
- */\r
-static void skip_newline(const char **p, int32 *rem)\r
-{\r
- /* make sure we have something to skip */\r
- if (*rem == 0)\r
- return;\r
-\r
- /* check what we have */\r
- switch (**(const unsigned char **)p)\r
- {\r
- case '\n':\r
- /* skip \n or \n\r */\r
- nextc(p, rem);\r
- if (**p == '\r')\r
- nextc(p, rem);\r
- break;\r
-\r
- case '\r':\r
- /* skip \r or \r\n */\r
- nextc(p, rem);\r
- if (**p == '\n')\r
- nextc(p, rem);\r
- break;\r
-\r
- case 0xe2:\r
- /* \u2028 (unicode line separator) - just skip the one character */\r
- nextc(p, rem);\r
- break;\r
- }\r
-}\r
-\r
-/*\r
- * Skip to the next line \r
- */\r
-static void skip_to_next_line(const char **p, int32 *rem)\r
-{\r
- /* look for the next newline */\r
- for ( ; *rem != 0 ; nextc(p, rem))\r
- {\r
- /* if this is a newline of some kind, we're at the end of the line */\r
- if (u_isnl(*p, *rem))\r
- {\r
- /* skip the newline, and we're done */\r
- skip_newline(p, rem);\r
- break;\r
- }\r
- }\r
-}\r
-\r
-\r
-/* ------------------------------------------------------------------------ */\r
-/*\r
- * ifiction synthesizer output context \r
- */\r
-typedef struct synthctx synthctx;\r
-struct synthctx\r
-{\r
- /* the current output pointer */\r
- char *buf;\r
-\r
- /* the number of bytes remaining in the output buffer */\r
- int32 buf_size;\r
-\r
- /* \r
- * the total number of bytes needed for the output (this might be more\r
- * than we've actually written, since we count up the bytes required\r
- * even if we need more space than the buffer provides) \r
- */\r
- int32 total_size;\r
-\r
- /* the head of the name/value pair list from the parsed GameInfo */\r
- valinfo *vals;\r
-};\r
-\r
-/* initialize a synthesizer context */\r
-static void init_synthctx(synthctx *ctx, char *buf, int32 bufsize,\r
- valinfo *vals)\r
-{\r
- /* set up at the beginning of the output buffer */\r
- ctx->buf = buf;\r
- ctx->buf_size = bufsize;\r
-\r
- /* we haven't written anything to the output buffer yet */\r
- ctx->total_size = 0;\r
-\r
- /* remember the name/value pair list */\r
- ctx->vals = vals;\r
-}\r
-\r
-/* \r
- * Write out a chunk to a synthesized ifiction record, updating pointers\r
- * and counters. We won't copy past the end of the buffer, but we'll\r
- * continue counting the output length needed in any case. \r
- */\r
-static void write_ifiction(synthctx *ctx, const char *src, size_t srclen)\r
-{\r
- int32 copy_len;\r
-\r
- /* copy as much as we can, up to the remaining buffer size */\r
- copy_len = srclen;\r
- if (copy_len > ctx->buf_size)\r
- copy_len = ctx->buf_size;\r
-\r
- /* do the copying, if any */\r
- if (copy_len != 0)\r
- {\r
- /* copy the bytes */\r
- memcpy(ctx->buf, src, (size_t)copy_len);\r
-\r
- /* adjust the buffer pointer and output buffer size remaining */\r
- ctx->buf += copy_len;\r
- ctx->buf_size -= copy_len;\r
- }\r
-\r
- /* count this source data in the total size */\r
- ctx->total_size += srclen;\r
-}\r
-\r
-/* write a null-terminated chunk to the synthesized ifiction record */\r
-static void write_ifiction_z(synthctx *ctx, const char *src)\r
-{\r
- write_ifiction(ctx, src, strlen(src));\r
-}\r
-\r
-/*\r
- * Write a PCDATA string to the synthesized ifiction record. In\r
- * particular, we rewrite '<', '>', and '&' as '<', '>', and '&',\r
- * respectively; we trim off leading and trailing spaces; and we compress\r
- * each run of whitespace down to a single \u0020 (' ') character.\r
- */\r
-static void write_ifiction_pcdata(synthctx *ctx, const char *p, size_t len)\r
-{\r
- /* first, skip any leading whitespace */\r
- for ( ; len != 0 && u_ishspace(*p) ; ++p, --len) ;\r
-\r
- /* keep going until we run out of string */\r
- for (;;)\r
- {\r
- const char *start;\r
- \r
- /* scan to the next whitespace or markup-significant character */\r
- for (start = p ;\r
- len != 0 && !u_ishspace(*p)\r
- && *p != '<' && *p != '>' && *p != '&' ; ++p, --len) ;\r
-\r
- /* write the part up to here */\r
- if (p != start)\r
- write_ifiction(ctx, start, p - start);\r
-\r
- /* if we've reached the end of the string, we can stop */\r
- if (len == 0)\r
- break;\r
-\r
- /* check what stopped us */\r
- switch (*p)\r
- {\r
- case '<':\r
- write_ifiction_z(ctx, "<");\r
- ++p, --len;\r
- break;\r
-\r
- case '>':\r
- write_ifiction_z(ctx, ">");\r
- ++p, --len;\r
- break;\r
-\r
- case '&':\r
- write_ifiction_z(ctx, "&");\r
- ++p, --len;\r
- break;\r
-\r
- default:\r
- /* \r
- * The only other thing that could have stopped us is\r
- * whitespace. Skip all consecutive whitespace. \r
- */\r
- for ( ; len != 0 && u_ishspace(*p) ; ++p, --len);\r
-\r
- /* \r
- * if that's not the end of the string, replace the run of\r
- * whitespace with a single space character in the output; if\r
- * we've reached the end of the string, we don't even want to\r
- * do that, since we want to trim off trailing spaces \r
- */\r
- if (len != 0)\r
- write_ifiction_z(ctx, " ");\r
- break;\r
- }\r
- }\r
-}\r
-\r
-/*\r
- * Translate a GameInfo keyed value to the corresponding ifiction tagged\r
- * value. We find the GameInfo value keyed by 'gameinfo_key', and write\r
- * out the same string under the ifiction XML tag 'ifiction_tag'. We write\r
- * a complete XML container sequence - <tag>value</tag>.\r
- * \r
- * If the given GameInfo key doesn't exist, we use the default value string\r
- * 'dflt', if given. If the GameInfo key doesn't exist and 'dflt' is null,\r
- * we don't write anything - we don't even write the open/close tags.\r
- * \r
- * If 'html' is true, we assume the value is in html format, and we write\r
- * it untranslated. Otherwise, we write it as PCDATA, translating markup\r
- * characters into '&' entities and compressing whitespace. \r
- */\r
-static void write_ifiction_xlat_base(synthctx *ctx, int indent,\r
- const char *gameinfo_key,\r
- const char *ifiction_tag,\r
- const char *dflt, int html)\r
-{\r
- valinfo *val;\r
- const char *valstr;\r
- size_t vallen;\r
- \r
- /* look up the GameInfo key */\r
- if ((val = find_by_key(ctx->vals, gameinfo_key)) != 0)\r
- {\r
- /* we found the GameInfo value - use it */\r
- valstr = val->val;\r
- vallen = val->val_len;\r
- }\r
- else if (dflt != 0)\r
- {\r
- /* the GameInfo value doesn't exist, but we have a default - use it */\r
- valstr = dflt;\r
- vallen = strlen(dflt);\r
- }\r
- else\r
- {\r
- /* there's no GameInfo value and no default, so write nothing */\r
- return;\r
- }\r
-\r
- /* write the indentation */\r
- while (indent != 0)\r
- {\r
- static const char spaces[] = " ";\r
- size_t cur;\r
-\r
- /* figure how much we can write on this round */\r
- cur = indent;\r
- if (cur > sizeof(spaces) - 1)\r
- cur = sizeof(spaces) - 1;\r
-\r
- /* write it */\r
- write_ifiction(ctx, spaces, cur);\r
-\r
- /* deduct it from the amount remaining */\r
- indent -= cur;\r
- }\r
-\r
- /* write the open tag */\r
- write_ifiction_z(ctx, "<");\r
- write_ifiction_z(ctx, ifiction_tag);\r
- write_ifiction_z(ctx, ">");\r
-\r
- /* write the value, applying pcdata translations */\r
- if (html)\r
- write_ifiction(ctx, valstr, vallen);\r
- else\r
- write_ifiction_pcdata(ctx, valstr, vallen);\r
-\r
- /* write the close tag */\r
- write_ifiction_z(ctx, "</");\r
- write_ifiction_z(ctx, ifiction_tag);\r
- write_ifiction_z(ctx, ">\n");\r
-}\r
-\r
-#define write_ifiction_xlat(ctx, indent, gikey, iftag, dflt) \\r
- write_ifiction_xlat_base(ctx, indent, gikey, iftag, dflt, FALSE)\r
-\r
-#define write_ifiction_xlat_html(ctx, indent, gikey, iftag, dflt) \\r
- write_ifiction_xlat_base(ctx, indent, gikey, iftag, dflt, TRUE)\r
-\r
-\r
-/*\r
- * Retrieve the next author name from the GameInfo "Author" format. The\r
- * format is as follows:\r
- * \r
- * name <email> <email>... ; ...\r
- * \r
- * That is, each author is listed with a name followed by one or more email\r
- * addresses in angle brackets, and multiple authors are separated by\r
- * semicolons. \r
- */\r
-static int scan_author_name(const char **p, size_t *len,\r
- const char **start, const char **end)\r
-{\r
- /* keep going until we find a non-empty author name */\r
- for (;;)\r
- {\r
- /* skip leading spaces */\r
- for ( ; *len != 0 && u_ishspace(**p) ; ++*p, --*len) ;\r
-\r
- /* if we ran out of string, there's definitely no author name */\r
- if (*len == 0)\r
- return FALSE;\r
-\r
- /* \r
- * Find the end of this author name. The author name ends at the\r
- * next semicolon or angle bracket. \r
- */\r
- for (*start = *p ; *len != 0 && **p != ';' && **p != '<' ;\r
- ++*p, --*len) ;\r
-\r
- /* trim off any trailing spaces */\r
- for (*end = *p ; *end > *start && u_ishspace(*(*end - 1)) ; --*end) ;\r
-\r
- /* now skip any email addresses */\r
- while (*len != 0 && **p == '<')\r
- {\r
- /* skip to the closing bracket */\r
- for (++*p, --*len ; *len != 0 && **p != '>' ; ++*p, --*len) ;\r
-\r
- /* skip the bracket */\r
- if (*len != 0)\r
- ++*p, --*len;\r
-\r
- /* skip whitespace */\r
- for ( ; *len != 0 && u_ishspace(**p) ; ++*p, --*len) ;\r
-\r
- /* \r
- * if we're not at a semicolon, another angle bracket, or the\r
- * end of the string, it's a syntax error \r
- */\r
- if (*len != 0 && **p != '<' && **p != ';')\r
- {\r
- *len = 0;\r
- return FALSE;\r
- }\r
- }\r
-\r
- /* if we're at a semicolon, skip it */\r
- if (*len != 0 && **p == ';')\r
- ++*p, --*len;\r
-\r
- /* \r
- * if we found a non-empty name, return it; otherwise, continue on\r
- * to the next semicolon section \r
- */\r
- if (*end != *start)\r
- return TRUE;\r
- }\r
-}\r
-\r
-\r
-/*\r
- * Synthesize an ifiction record for the given GameInfo name/value pair\r
- * list. Returns the number of bytes required for the result, including\r
- * null termination. We'll copy as much as we can to the output buffer, up\r
- * to bufsize; if the buffer size is insufficient to hold the result, we'll\r
- * still indicate the length needed for the full result, but we're careful\r
- * not to actually copy anything past the end of the buffer. \r
- */\r
-static int32 synth_ifiction(valinfo *vals, int tads_version,\r
- char *buf, int32 bufsize,\r
- void *story_file, int32 extent)\r
-{\r
- char default_ifid[TREATY_MINIMUM_EXTENT];\r
- valinfo *ifid = find_by_key(vals, "IFID");\r
- const char *ifid_val;\r
- size_t ifid_len;\r
- valinfo *author = find_by_key(vals, "AuthorEmail");\r
- valinfo *url = find_by_key(vals, "Url");\r
- synthctx ctx;\r
- const char *p;\r
- size_t rem;\r
- int32 art_fmt;\r
- int32 art_wid, art_ht;\r
-\r
- /* initialize the output content */\r
- init_synthctx(&ctx, buf, bufsize, vals);\r
-\r
- /* make sure the tads version is one we know how to handle */\r
- if (tads_version != 2 && tads_version != 3)\r
- return NO_REPLY_RV;\r
-\r
- /* \r
- * The IFID is mandatory. If there's not an IFID specifically listed\r
- * in the GameInfo, we need to generate the default IFID based on the\r
- * MD5 hash of the game file. \r
- */\r
- if (ifid != 0)\r
- {\r
- /* use the explicit IFID(s) listed in the GameInfo */\r
- ifid_val = ifid->val;\r
- ifid_len = ifid->val_len;\r
- }\r
- else\r
- {\r
- /* generate the default IFID */\r
- generate_md5_ifid(story_file, extent,\r
- default_ifid, TREATY_MINIMUM_EXTENT);\r
-\r
- /* use this as the IFID */\r
- ifid_val = default_ifid;\r
- ifid_len = strlen(default_ifid);\r
- }\r
-\r
- /* write the header, and start the <identification> section */\r
- write_ifiction_z(\r
- &ctx,\r
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"\r
- "<ifindex version=\"1.0\" "\r
- "xmlns=\"http://babel.ifarchive.org/protocol/iFiction/\">\n"\r
- " <!-- Bibliographic data translated from TADS GameInfo -->\n"\r
- " <story>\n"\r
- " <colophon>\n"\r
- " <generator>Babel</generator>\n"\r
- " <generatorversion>" TREATY_VERSION "</generatorversion>\n"\r
- " <originated>2006-04-14</originated>\n"\r
- " </colophon>\n"\r
- " <identification>\n");\r
-\r
- /* write each IFID (there might be several) */\r
- for (p = ifid_val, rem = ifid_len ; rem != 0 ; )\r
- {\r
- const char *start;\r
- const char *end;\r
-\r
- /* skip leading spaces */\r
- for ( ; rem != 0 && u_ishspace(*p) ; ++p, --rem) ;\r
- \r
- /* find the end of this IFID */\r
- for (start = p ; rem != 0 && *p != ',' ; ++p, --rem) ;\r
-\r
- /* remove trailing spaces */\r
- for (end = p ; end > start && u_ishspace(*(end-1)) ; --end) ;\r
-\r
- /* if we found one, write it out */\r
- if (end != start)\r
- {\r
- write_ifiction_z(&ctx, " <ifid>");\r
- write_ifiction(&ctx, start, end - start);\r
- write_ifiction_z(&ctx, "</ifid>\n");\r
- }\r
-\r
- /* skip the comma */\r
- if (rem != 0 && *p == ',')\r
- ++p, --rem;\r
- }\r
-\r
- /* add the format information */\r
- write_ifiction_z(&ctx,\r
- tads_version == 2\r
- ? " <format>tads2</format>\n"\r
- : " <format>tads3</format>\n");\r
-\r
- /* close the <identification> section and start the <bibliographic> */\r
- write_ifiction_z(&ctx,\r
- " </identification>\n"\r
- " <bibliographic>\n");\r
-\r
- /* write the various bibliographic data */\r
- write_ifiction_xlat(&ctx, 6, "Name", "title", "An Interactive Fiction");\r
- write_ifiction_xlat(&ctx, 6, "Headline", "headline", 0);\r
- write_ifiction_xlat(&ctx, 6, "Desc", "description", 0);\r
- write_ifiction_xlat(&ctx, 6, "Genre", "genre", 0);\r
- write_ifiction_xlat(&ctx, 6, "Forgiveness", "forgiveness", 0);\r
- write_ifiction_xlat(&ctx, 6, "Series", "series", 0);\r
- write_ifiction_xlat(&ctx, 6, "SeriesNumber", "seriesnumber", 0);\r
- write_ifiction_xlat(&ctx, 6, "Language", "language", 0);\r
- write_ifiction_xlat(&ctx, 6, "FirstPublished", "firstpublished", 0);\r
-\r
- /* if there's an author, write the list of author names */\r
- if (author != 0)\r
- {\r
- int cnt;\r
- int i;\r
- const char *start;\r
- const char *end;\r
-\r
- /* start the <author> tag */\r
- write_ifiction_z(&ctx, " <author>");\r
- \r
- /* \r
- * first, count up the number of authors - authors are separated by\r
- * semicolons, so there's one more author than there are semicolons\r
- */\r
- for (p = author->val, rem = author->val_len, cnt = 1 ;\r
- scan_author_name(&p, &rem, &start, &end) ; ) ;\r
-\r
- /* \r
- * Now generate the list of authors. If there are multiple\r
- * authors, use commas to separate them. \r
- */\r
- for (p = author->val, rem = author->val_len, i = 0 ; ; ++i)\r
- {\r
- /* scan this author's name */\r
- if (!scan_author_name(&p, &rem, &start, &end))\r
- break;\r
- \r
- /* write out this author name */\r
- write_ifiction_pcdata(&ctx, start, end - start);\r
-\r
- /* if there's another name to come, write a separator */\r
- if (i + 1 < cnt)\r
- {\r
- /* \r
- * write just "and" to separate two items; write ","\r
- * between items in lists of more than two, with ",and"\r
- * between the last two items \r
- */\r
- write_ifiction_z(&ctx,\r
- cnt == 2 ? " and " :\r
- i + 2 < cnt ? ", " : ", and ");\r
- }\r
- }\r
-\r
- /* end the <author> tag */\r
- write_ifiction_z(&ctx, "</author>\n");\r
- }\r
-\r
- /* end the biblio section */\r
- write_ifiction_z(&ctx, " </bibliographic>\n");\r
-\r
- /* if there's cover art, add its information */\r
- if (find_cover_art(story_file, extent, 0, &art_fmt, &art_wid, &art_ht)\r
- && (art_fmt == PNG_COVER_FORMAT || art_fmt == JPEG_COVER_FORMAT))\r
- {\r
- char buf[200];\r
- \r
- sprintf(buf,\r
- " <cover>\n"\r
- " <format>%s</format>\n"\r
- " <height>%lu</height>\n"\r
- " <width>%lu</width>\n"\r
- " </cover>\n",\r
- art_fmt == PNG_COVER_FORMAT ? "png" : "jpg",\r
- (long)art_ht, (long)art_wid);\r
-\r
- write_ifiction_z(&ctx, buf);\r
- }\r
-\r
- /* if there's an author email, include it */\r
- if (author != 0 || url != 0)\r
- {\r
- const char *p;\r
- size_t rem;\r
- int i;\r
- \r
- /* open the section */\r
- write_ifiction_z(&ctx, " <contacts>\n");\r
-\r
- /* add the author email, if provided */\r
- if (author != 0)\r
- {\r
- /* write the email list */\r
- for (i = 0, p = author->val, rem = author->val_len ; ; ++i)\r
- {\r
- const char *start;\r
- \r
- /* skip to the next email address */\r
- for ( ; rem != 0 && *p != '<' ; ++p, --rem) ;\r
- \r
- /* if we didn't find an email address, we're done */\r
- if (rem == 0)\r
- break;\r
- \r
- /* find the matching '>' */\r
- for (++p, --rem, start = p ; rem != 0 && *p != '>' ;\r
- ++p, --rem) ;\r
-\r
- /* \r
- * if this is the first one, open the section; otherwise,\r
- * add a comma \r
- */\r
- if (i == 0)\r
- write_ifiction_z(&ctx, " <authoremail>");\r
- else\r
- write_ifiction_z(&ctx, ",");\r
- \r
- /* write this address */\r
- write_ifiction(&ctx, start, p - start);\r
- \r
- /* \r
- * skip the closing bracket, if there is one; if we're out\r
- * of string, we're done \r
- */\r
- if (rem != 0)\r
- ++p, --rem;\r
- else\r
- break;\r
- }\r
-\r
- /* if we found any emails to write, end the section */\r
- if (i != 0)\r
- write_ifiction_z(&ctx, "</authoremail>\n");\r
- }\r
-\r
- /* if there's a URL, add it */\r
- if (url != 0)\r
- {\r
- write_ifiction_z(&ctx, " <url>");\r
- write_ifiction(&ctx, url->val, url->val_len);\r
- write_ifiction_z(&ctx, "</url>\n");\r
- }\r
-\r
- /* close the section */\r
- write_ifiction_z(&ctx, " </contacts>\n");\r
- }\r
-\r
- /* add the tads-specific section */\r
- write_ifiction_z(&ctx, " <tads>\n");\r
- \r
- write_ifiction_xlat(&ctx, 6, "Version", "version", 0);\r
- write_ifiction_xlat(&ctx, 6, "ReleaseDate", "releasedate", 0);\r
- write_ifiction_xlat(&ctx, 6, "PresentationProfile",\r
- "presentationprofile", 0);\r
- write_ifiction_xlat(&ctx, 6, "Byline", "byline", 0);\r
-\r
- write_ifiction_z(&ctx, " </tads>\n");\r
-\r
- /* close the story section and the main body */\r
- write_ifiction_z(&ctx, " </story>\n</ifindex>\n");\r
- \r
- /* add the null terminator */\r
- write_ifiction(&ctx, "", 1);\r
-\r
- /* return the total output size */\r
- return ctx.total_size;\r
-}\r
-\r
-/* ------------------------------------------------------------------------ */\r
-/*\r
- * Check a data block to see if it starts with the given signature. \r
- */\r
-int tads_match_sig(const void *buf, int32 len, const char *sig)\r
-{\r
- /* note the length of the signature string */\r
- size_t sig_len = strlen(sig);\r
- \r
- /* if matches if the buffer starts with the signature string */\r
- return (len >= (int32)sig_len && memcmp(buf, sig, sig_len) == 0);\r
-}\r
-\r
-\r
-/* ------------------------------------------------------------------------ */\r
-/*\r
- * portable-to-native format conversions \r
- */\r
-#define osbyte(p, ofs) \\r
- (*(((unsigned char *)(p)) + (ofs)))\r
-\r
-#define osrp1(p) \\r
- ((unsigned int)osbyte(p, 0))\r
-\r
-#define osrp2(p) \\r
- ((unsigned int)osbyte(p, 0) \\r
- + ((unsigned int)osbyte(p, 1) << 8))\r
-\r
-#define osrp4(p) \\r
- (((unsigned long)osbyte(p, 0)) \\r
- + (((unsigned long)osbyte(p, 1)) << 8) \\r
- + (((unsigned long)osbyte(p, 2)) << 16) \\r
- + (((unsigned long)osbyte(p, 3)) << 24))\r
-\r
-\r
-/* ------------------------------------------------------------------------ */\r
-/*\r
- * Parse a game file and retrieve the GameInfo data. Returns the head of a\r
- * linked list of valinfo entries.\r
- */\r
-static valinfo *parse_game_info(const void *story_file, int32 story_len,\r
- int *tads_version)\r
-{\r
- resinfo res;\r
- const char *p;\r
- int32 rem;\r
- valinfo *val_head = 0;\r
-\r
- /* \r
- * first, find the GameInfo resource - if it's not there, there's no\r
- * game information to parse \r
- */\r
- if (!find_resource(story_file, story_len, "GameInfo.txt", &res))\r
- return 0;\r
-\r
- /* if the caller wants the TADS version number, hand it back */\r
- if (tads_version != 0)\r
- *tads_version = res.tads_version;\r
-\r
- /* parse the data */\r
- for (p = res.ptr, rem = res.len ; rem != 0 ; )\r
- {\r
- const char *name_start;\r
- size_t name_len;\r
- const char *val_start;\r
- valinfo *val;\r
- const char *inp;\r
- int32 inlen;\r
- char *outp;\r
-\r
- /* skip any leading whitespace */\r
- while (rem != 0 && u_isspace(*p))\r
- ++p, --rem;\r
-\r
- /* if the line starts with '#', it's a comment, so skip it */\r
- if (rem != 0 && *p == '#')\r
- {\r
- skip_to_next_line(&p, &rem);\r
- continue;\r
- }\r
-\r
- /* we must have the start of a name - note it */\r
- name_start = p;\r
-\r
- /* skip ahead to a space or colon */\r
- while (rem != 0 && *p != ':' && !u_ishspace(*p))\r
- nextc(&p, &rem);\r
-\r
- /* note the length of the name */\r
- name_len = p - name_start;\r
-\r
- /* skip any whitespace before the presumed colon */\r
- while (rem != 0 && u_ishspace(*p))\r
- nextc(&p, &rem);\r
-\r
- /* if we're not at a colon, the line is ill-formed, so skip it */\r
- if (rem == 0 || *p != ':')\r
- {\r
- /* skip the entire line, and go back for the next one */\r
- skip_to_next_line(&p, &rem);\r
- continue;\r
- }\r
-\r
- /* skip the colon and any whitespace immediately after it */\r
- for (nextc(&p, &rem) ; rem != 0 && u_ishspace(*p) ; nextc(&p, &rem)) ;\r
-\r
- /* note where the value starts */\r
- val_start = p;\r
-\r
- /*\r
- * Scan the value to get its length. The value runs from here to\r
- * the next newline that's not followed immediately by a space. \r
- */\r
- while (rem != 0)\r
- {\r
- const char *nl;\r
- int32 nlrem;\r
- \r
- /* skip to the next line */\r
- skip_to_next_line(&p, &rem);\r
-\r
- /* if we're at eof, we can stop now */\r
- if (rem == 0)\r
- break;\r
-\r
- /* note where this line starts */\r
- nl = p;\r
- nlrem = rem;\r
-\r
- /* \r
- * if we're at a non-whitespace character, it's definitely not\r
- * a continuation line \r
- */\r
- if (!u_ishspace(*p))\r
- break;\r
-\r
- /* \r
- * check for spaces followed by a non-space character - this\r
- * would signify a continuation line\r
- */\r
- for ( ; rem != 0 && u_ishspace(*p) ; nextc(&p, &rem)) ;\r
- if (rem == 0 || u_isnl(p, rem))\r
- {\r
- /* \r
- * we're at end of file, we found a line with nothing but\r
- * whitespace, so this isn't a continuation line; go back\r
- * to the start of this line and end the value here \r
- */\r
- p = nl;\r
- rem = nlrem;\r
- break;\r
- }\r
-\r
- /* \r
- * We found whitespace followed by non-whitespace, so this is a\r
- * continuation line. Keep going for now.\r
- */\r
- }\r
-\r
- /* remove any trailing newlines */\r
- while (p > val_start)\r
- {\r
- /* move back one character */\r
- prevc(&p, &rem);\r
-\r
- /* \r
- * if it's a newline, keep going; otherwise, keep this\r
- * character and stop trimming \r
- */\r
- if (!u_isnl(p, rem))\r
- {\r
- nextc(&p, &rem);\r
- break;\r
- }\r
- }\r
-\r
- /* \r
- * Allocate a new value entry. Make room for the entry itself plus\r
- * a copy of the value. We don't need to make a copy of the name,\r
- * since we can just use the original copy from the story file\r
- * buffer. We do need a copy of the value because we might need to\r
- * transform it slightly, to remove newlines and leading spaces on\r
- * continuation lines. \r
- */\r
- val = (valinfo *)malloc(sizeof(valinfo) + (p - val_start));\r
-\r
- /* link it into our list */\r
- val->nxt = val_head;\r
- val_head = val;\r
-\r
- /* point the name directly to the name in the buffer */\r
- val->name = name_start;\r
- val->name_len = name_len;\r
-\r
- /* point the value to the space allocated along with the valinfo */\r
- val->val = (char *)(val + 1);\r
-\r
- /* store the name, removing newlines and continuation-line spaces */\r
- for (outp = val->val, inp = val_start, inlen = p - val_start ;\r
- inlen != 0 ; )\r
- {\r
- const char *l;\r
- \r
- /* find the next newline */\r
- for (l = inp ; inlen != 0 && !u_isnl(inp, inlen) ;\r
- nextc(&inp, &inlen)) ;\r
-\r
- /* copy this line to the output */\r
- memcpy(outp, l, inp - l);\r
- outp += inp - l;\r
-\r
- /* if we're out of input, we're done */\r
- if (inlen == 0)\r
- break;\r
-\r
- /* we're at a newline: replace it with a space in the output */\r
- *outp++ = ' ';\r
-\r
- /* skip the newline and subsequent whitespace in the input */\r
- for (skip_newline(&inp, &inlen) ;\r
- inlen != 0 && u_ishspace(*inp) ; nextc(&inp, &inlen)) ;\r
- }\r
-\r
- /* set the length of the parsed value */\r
- val->val_len = outp - val->val;\r
-\r
- /* skip to the next line and continue parsing */\r
- skip_to_next_line(&p, &rem);\r
- }\r
-\r
- /* return the head of the linked list of value entries */\r
- return val_head;\r
-}\r
-static int my_memicmp(const void *aa, const void *bb, int l)\r
-{\r
- int s=0,i;\r
- char *a=(char *) aa;\r
- char *b=(char *) bb;\r
- for(i=0;i<l && !s;i++)\r
- s=tolower(a[i])-tolower(b[i]);\r
- return s;\r
-}\r
-\r
-/* ------------------------------------------------------------------------ */\r
-/*\r
- * Given a valinfo list obtained from parse_game_info(), find the value for\r
- * the given key \r
- */\r
-static valinfo *find_by_key(valinfo *list_head, const char *key)\r
-{\r
- valinfo *p;\r
- size_t key_len = strlen(key);\r
- \r
- /* scan the list for the given key */\r
- for (p = list_head ; p != 0 ; p = p->nxt)\r
- {\r
- /* if this one matches the key we're looking for, return it */\r
- if (p->name_len == key_len && my_memicmp(p->name, key, key_len) == 0)\r
- return p;\r
- }\r
-\r
- /* no luck */\r
- return 0;\r
-}\r
-\r
-/* ------------------------------------------------------------------------ */\r
-/*\r
- * Delete a valinfo list obtained from parse_game_info() \r
- */\r
-static void delete_valinfo_list(valinfo *head)\r
-{\r
- /* keep going until we run out of entries */\r
- while (head != 0)\r
- {\r
- /* remember the next entry, before we delete this one */\r
- valinfo *nxt = head->nxt;\r
-\r
- /* delete this one */\r
- free(head);\r
-\r
- /* move on to the next one */\r
- head = nxt;\r
- }\r
-}\r
-\r
-/* ------------------------------------------------------------------------ */\r
-/*\r
- * Find the cover art resource. We'll look for CoverArt.jpg and\r
- * CoverArt.png, in that order. \r
- */\r
-static int find_cover_art(const void *story_file, int32 story_len,\r
- resinfo *resp, int32 *image_format,\r
- int32 *width, int32 *height)\r
-{\r
- resinfo res;\r
- int32 x, y;\r
-\r
- /* if they didn't want the resource info, provide a placeholder */\r
- if (resp == 0)\r
- resp = &res;\r
-\r
- /* look for CoverArt.jpg first */\r
- if (find_resource(story_file, story_len, "CoverArt.jpg", resp))\r
- {\r
- /* get the width and height */\r
- if (!get_jpeg_dim(resp->ptr, resp->len, &x, &y))\r
- return FALSE;\r
-\r
- /* hand back the width and height if it was requested */\r
- if (width != 0)\r
- *width = x;\r
- if (height != 0)\r
- *height = y;\r
-\r
- /* tell them it's a JPEG image */\r
- if (image_format != 0)\r
- *image_format = JPEG_COVER_FORMAT;\r
-\r
- /* indicate success */\r
- return TRUE;\r
- }\r
-\r
- /* look for CoverArt.png second */\r
- if (find_resource(story_file, story_len, "CoverArt.png", resp))\r
- {\r
- /* get the width and height */\r
- if (!get_png_dim(resp->ptr, resp->len, &x, &y))\r
- return FALSE;\r
-\r
- /* hand back the width and height if it was requested */\r
- if (width != 0)\r
- *width = x;\r
- if (height != 0)\r
- *height = y;\r
-\r
- /* tell them it's a PNG image */\r
- if (image_format != 0)\r
- *image_format = PNG_COVER_FORMAT;\r
-\r
- /* indicate success */\r
- return TRUE;\r
- }\r
-\r
- /* didn't find it */\r
- return FALSE;\r
-}\r
-\r
-/* ------------------------------------------------------------------------ */\r
-/*\r
- * Find a resource in a TADS 2 or 3 story file that's been loaded into\r
- * memory. On success, fills in the offset and size of the resource and\r
- * returns TRUE; if the resource isn't found, returns FALSE.\r
- */\r
-static int find_resource(const void *story_file, int32 story_len,\r
- const char *resname, resinfo *info)\r
-{\r
- /* if there's no file, there's no resource */\r
- if (story_file == 0)\r
- return FALSE;\r
-\r
- /* check for tads 2 */\r
- if (tads_match_sig(story_file, story_len, T2_SIGNATURE))\r
- {\r
- info->tads_version = 2;\r
- return t2_find_res(story_file, story_len, resname, info);\r
- }\r
-\r
- /* check for tads 3 */\r
- if (tads_match_sig(story_file, story_len, T3_SIGNATURE))\r
- {\r
- info->tads_version = 3;\r
- return t3_find_res(story_file, story_len, resname, info);\r
- }\r
-\r
- /* it's not one of ours */\r
- return FALSE;\r
-}\r
-\r
-/* ------------------------------------------------------------------------ */\r
-/*\r
- * Find a resource in a tads 2 game file \r
- */\r
-static int t2_find_res(const void *story_file, int32 story_len,\r
- const char *resname, resinfo *info)\r
-{\r
- const char *basep = (const char *)story_file;\r
- const char *endp = basep + story_len;\r
- const char *p;\r
- size_t resname_len;\r
-\r
- /* note the length of the name we're seeking */\r
- resname_len = strlen(resname);\r
-\r
- /* \r
- * skip past the tads 2 file header (13 bytes for the signature, 7\r
- * bytes for the version header, 2 bytes for the flags, 26 bytes for\r
- * the timestamp) \r
- */\r
- p = basep + 13 + 7 + 2 + 26;\r
-\r
- /* \r
- * scan the sections in the file; stop on $EOF, and skip everything\r
- * else but HTMLRES, which is the section type that \r
- */\r
- while (p < endp)\r
- {\r
- unsigned long endofs;\r
-\r
- /*\r
- * We're pointing to a section block header, which looks like this:\r
- * \r
- *. <byte> type-length\r
- *. <byte * type-length> type-name\r
- *. <uint32> next-section-address\r
- */\r
-\r
- /* read the ending offset */\r
- endofs = osrp4(p + 1 + osrp1(p));\r
-\r
- /* check the type */\r
- if (p[0] == 7 && memcmp(p + 1, "HTMLRES", 7) == 0)\r
- {\r
- unsigned long found_ofs;\r
- int found;\r
- unsigned long entry_cnt;\r
-\r
- /* we haven't found the resource yet */\r
- found = FALSE;\r
-\r
- /* \r
- * It's a multimedia resource block. Skip the section block\r
- * header and look at the index table - the index table\r
- * consists of a uint32 giving the number of entries, followed\r
- * by a reserved uint32, followed by the entries. \r
- */\r
- p += 12;\r
- entry_cnt = osrp4(p);\r
-\r
- /* skip to the first index entry */\r
- p += 8;\r
-\r
- /* scan the index entries */\r
- for ( ; entry_cnt != 0 ; --entry_cnt)\r
- {\r
- unsigned long res_ofs;\r
- unsigned long res_siz;\r
- size_t name_len;\r
-\r
- /*\r
- * We're at the next index entry, which looks like this:\r
- *\r
- *. <uint32> resource-address (bytes from end of index)\r
- *. <uint32> resource-length (in bytes)\r
- *. <uint2> name-length\r
- *. <byte * name-length> name\r
- */\r
- res_ofs = osrp4(p);\r
- res_siz = osrp4(p + 4);\r
- name_len = osrp2(p + 8);\r
- p += 10;\r
-\r
- /* check for a match to the name we're looking for */\r
- if (name_len == resname_len\r
- && my_memicmp(resname, p, name_len) == 0)\r
- {\r
- /* \r
- * it's the one we want - note its resource location\r
- * and size, but keep scanning for now, since we need\r
- * to find the end of the index before we'll know where\r
- * the actual resources begin \r
- */\r
- found = TRUE;\r
- found_ofs = res_ofs;\r
- info->len = res_siz;\r
- }\r
-\r
- /* skip this one's name */\r
- p += name_len;\r
- }\r
-\r
- /* \r
- * if we found our resource, the current seek position is the\r
- * base of the offset we found in the directory; so we can\r
- * finally fix up the offset to give the actual file location\r
- * and return the result \r
- */\r
- if (found)\r
- {\r
- /* fix up the offset with the actual file location */\r
- info->ptr = p + found_ofs;\r
-\r
- /* tell the caller we found it */\r
- return TRUE;\r
- }\r
- }\r
- else if (p[0] == 4 && memcmp(p + 1, "$EOF", 4) == 0)\r
- {\r
- /* \r
- * that's the end of the file - we've finished without finding\r
- * the resource, so return failure \r
- */\r
- return FALSE;\r
- }\r
-\r
- /* move to the next section */\r
- p = basep + endofs;\r
- }\r
-\r
- /* \r
- * reached EOF without an $EOF marker - file must be corrupted; return\r
- * 'not found' \r
- */\r
- return FALSE;\r
-}\r
-\r
-/* ------------------------------------------------------------------------ */\r
-/*\r
- * Find a resource in a T3 image file \r
- */\r
-static int t3_find_res(const void *story_file, int32 story_len,\r
- const char *resname, resinfo *info)\r
-{\r
- const char *basep = (const char *)story_file;\r
- const char *endp = basep + story_len;\r
- const char *p;\r
- size_t resname_len;\r
-\r
- /* note the length of the name we're seeking */\r
- resname_len = strlen(resname);\r
-\r
- /* \r
- * skip the file header - 11 bytes for the signature, 2 bytes for the\r
- * format version, 32 reserved bytes, and 24 bytes for the timestamp \r
- */\r
- p = basep + 11 + 2 + 32 + 24;\r
-\r
- /* scan the data blocks */\r
- while (p < endp)\r
- {\r
- unsigned long siz;\r
-\r
- /*\r
- * We're at the next block header, which looks like this:\r
- *\r
- *. <byte * 4> type-name\r
- *. <uint32> block-size\r
- *. <uint16> flags\r
- */\r
-\r
- /* get the block size */\r
- siz = osrp4(p + 4);\r
-\r
- /* check the type */\r
- if (memcmp(p, "MRES", 4) == 0)\r
- {\r
- unsigned int entry_cnt;\r
- unsigned int i;\r
- const char *blockp;\r
-\r
- /* skip the header */\r
- p += 10;\r
-\r
- /* \r
- * remember the location of the base of the block - the data\r
- * seek location for each index entry is given as an offset\r
- * from this location \r
- */\r
- blockp = p;\r
-\r
- /* the first thing in the table is the number of entries */\r
- entry_cnt = osrp2(p);\r
- p += 2;\r
-\r
- /* read the entries */\r
- for (i = 0 ; i < entry_cnt ; ++i)\r
- {\r
- unsigned long entry_ofs;\r
- unsigned long entry_siz;\r
- size_t entry_name_len;\r
- char namebuf[256];\r
- char *xp;\r
- size_t xi;\r
-\r
- /* \r
- * Parse this index entry:\r
- * \r
- *. <uint32> address (as offset from the block base)\r
- *. <uint32> size (in bytes)\r
- *. <uint8> name-length\r
- *. <byte * name-length> name (all bytes XORed with 0xFF)\r
- */\r
- entry_ofs = osrp4(p);\r
- entry_siz = osrp4(p + 4);\r
- entry_name_len = (unsigned char)p[8];\r
-\r
- /* unmask the name */\r
- memcpy(namebuf, p + 9, resname_len);\r
- for (xi = resname_len, xp = namebuf ; xi != 0 ; --xi)\r
- *xp++ ^= 0xFF;\r
-\r
- /* if this is the one we're looking for, return it */\r
- if (entry_name_len == resname_len\r
- && my_memicmp(resname, namebuf, resname_len) == 0)\r
- {\r
- /* \r
- * fill in the return information - note that the entry\r
- * offset given in the header is an offset from data\r
- * block's starting location, so fix this up to an\r
- * absolute seek location for the return value \r
- */\r
- info->ptr = blockp + entry_ofs;\r
- info->len = entry_siz;\r
-\r
- /* return success */\r
- return TRUE;\r
- }\r
-\r
- /* skip this entry (header + name length) */\r
- p += 9 + entry_name_len;\r
- }\r
-\r
- /* \r
- * if we got this far, we didn't find the name; so skip past\r
- * the MRES section by adding the section length to the base\r
- * pointer, and resume the main file scan \r
- */\r
- p = blockp + siz;\r
- }\r
- else if (memcmp(p, "EOF ", 4) == 0)\r
- {\r
- /* \r
- * end of file - we've finished without finding the resource,\r
- * so return failure \r
- */\r
- return FALSE;\r
- }\r
- else\r
- {\r
- /* \r
- * we don't care about anything else - just skip this block and\r
- * keep going; to skip the block, simply seek ahead past the\r
- * block header and then past the block's contents, using the\r
- * size given the in block header \r
- */\r
- p += siz + 10;\r
- }\r
- }\r
-\r
- /* \r
- * reached EOF without an EOF marker - file must be corrupted; return\r
- * 'not found' \r
- */\r
- return FALSE;\r
-}\r
-\r
-/* ------------------------------------------------------------------------ */\r
-/*\r
- * JPEG and PNG information extraction (based on the versions in\r
- * babel_story_functions.c) \r
- */\r
-static int get_jpeg_dim(const void *img, int32 extent,\r
- int32 *xout, int32 *yout)\r
-{\r
- const unsigned char *dp=(const unsigned char *) img;\r
- const unsigned char *ep=dp+extent;\r
- unsigned int t1, t2, w, h;\r
-\r
- t1 = *dp++;\r
- t2 = *dp++;\r
- if (t1 != 0xff || t2 != 0xD8)\r
- return FALSE;\r
-\r
- while(1)\r
- {\r
- if (dp>ep) return FALSE;\r
- for(t1=*(dp++);t1!=0xff;t1=*(dp++)) if (dp>ep) return FALSE;\r
- do { t1=*(dp++); if (dp>ep) return FALSE;} while (t1 == 0xff);\r
-\r
- if ((t1 & 0xF0) == 0xC0 && !(t1==0xC4 || t1==0xC8 || t1==0xCC))\r
- {\r
- dp+=3;\r
- if (dp>ep) return FALSE;\r
- h=*(dp++) << 8;\r
- if (dp>ep) return FALSE;\r
- h|=*(dp++);\r
- if (dp>ep) return FALSE;\r
- w=*(dp++) << 8;\r
- if (dp>ep) return FALSE;\r
- w|=*(dp);\r
-\r
- *xout = w;\r
- *yout = h;\r
- return TRUE;\r
- }\r
- else if (t1==0xD8 || t1==0xD9)\r
- break;\r
- else\r
- {\r
- int l;\r
-\r
- if (dp>ep) return FALSE;\r
- l=*(dp++) << 8;\r
- if (dp>ep) return FALSE;\r
- l|= *(dp++);\r
- l-=2;\r
- dp+=l;\r
- if (dp>ep) return FALSE;\r
- }\r
- }\r
- return FALSE;\r
-}\r
-\r
-static int32 png_read_int(const unsigned char *mem)\r
-{\r
- int32 i4 = mem[0],\r
- i3 = mem[1],\r
- i2 = mem[2],\r
- i1 = mem[3];\r
- return i1 | (i2<<8) | (i3<<16) | (i4<<24);\r
-}\r
-\r
-\r
-static int get_png_dim(const void *img, int32 extent,\r
- int32 *xout, int32 *yout)\r
-{\r
- const unsigned char *dp=(const unsigned char *)img;\r
-\r
- if (extent<33 ||\r
- !(dp[0]==137 && dp[1]==80 && dp[2]==78 && dp[3]==71 &&\r
- dp[4]==13 && dp[5] == 10 && dp[6] == 26 && dp[7]==10)||\r
- !(dp[12]=='I' && dp[13]=='H' && dp[14]=='D' && dp[15]=='R'))\r
- return FALSE;\r
-\r
- *xout = png_read_int(dp+16);\r
- *yout = png_read_int(dp+20);\r
- return TRUE;\r
-}\r
-\r
-/* ------------------------------------------------------------------------ */\r
-/*\r
- * Testing main() - this implements a set of unit tests on the tads\r
- * version. \r
- */\r
-\r
-#ifdef TADS_TEST\r
-\r
-#include "babel_handler.h"\r
-\r
-void main(int argc, char **argv)\r
-{\r
- FILE *fp;\r
- int32 siz;\r
- void *buf;\r
- valinfo *head;\r
- int32 rv;\r
- int tadsver;\r
- char outbuf[TREATY_MINIMUM_EXTENT];\r
-\r
- /* check arguments */\r
- if (argc != 2)\r
- {\r
- printf("usage: tads <game-file>\n");\r
- exit(1);\r
- }\r
-\r
- /* initialize the babel subsystems */\r
- babel_init(argv[1]);\r
-\r
- /* open the story file */\r
- if ((fp = fopen(argv[1], "rb")) == 0)\r
- {\r
- printf("error opening input file\n");\r
- exit(2);\r
- }\r
-\r
- /* check the file size */\r
- fseek(fp, 0, SEEK_END);\r
- siz = ftell(fp);\r
- fseek(fp, 0, SEEK_SET);\r
-\r
- /* allocate space for it */\r
- if ((buf = malloc(siz)) == 0)\r
- {\r
- printf("error allocating space to load file\n");\r
- exit(2);\r
- }\r
-\r
- /* load it */\r
- if ((int32)fread(buf, 1, siz, fp) != siz)\r
- {\r
- printf("error reading file\n");\r
- exit(2);\r
- }\r
-\r
- /* done with the file */\r
- fclose(fp);\r
-\r
-\r
-\r
- /* ===== test 1 - basic parse_game_info() test ===== */\r
-\r
- /* parse the gameinfo record and print the results */\r
- if ((head = parse_game_info(buf, siz, &tadsver)) != 0)\r
- {\r
- valinfo *val;\r
-\r
- printf("found GameInfo - tads major version = %d\n", tadsver);\r
- for (val = head ; val != 0 ; val = val->nxt)\r
- {\r
- printf("%.*s=[%.*s]\n",\r
- (int)val->name_len, val->name,\r
- (int)val->val_len, val->val);\r
- }\r
- printf("\n");\r
- }\r
- else\r
- printf("no GameInfo found\n\n");\r
-\r
-\r
-\r
- /* ===== test 2 - test the get_story_file_IFID generator ===== */\r
- rv = tads_get_story_file_IFID(buf, siz, outbuf, TREATY_MINIMUM_EXTENT);\r
- if (rv == 1)\r
- printf("IFID = [%s]\n\n", outbuf);\r
- else\r
- printf("IFID return code = %ld\n", rv);\r
-\r
-\r
-\r
- /* ===== test 3 - test the ifiction synthesizer ===== */\r
- if ((rv = tads_get_story_file_metadata_extent(buf, siz)) > 0)\r
- {\r
- char *ifbuf;\r
-\r
- /* try allocating the space */\r
- if ((ifbuf = malloc((size_t)rv)) != 0)\r
- {\r
- /* synthesize the story file */\r
- rv = tads_get_story_file_metadata(buf, siz, ifbuf, rv);\r
- if (rv > 0)\r
- printf("ifiction metadata:\n=====\n%.*s\n=====\n\n",\r
- (int)rv, ifbuf);\r
- else\r
- printf("tads_get_story_file_metadata result = %ld\n", rv);\r
- }\r
- else\r
- printf("unable to allocate %ld bytes for metadata record\n", rv);\r
- }\r
- else\r
- printf("tads_get_story_file_metadata_extent result code = %ld\n", rv);\r
- \r
-\r
- /* free the loaded story file buffer */\r
- free(buf);\r
-}\r
-\r
-\r
-#endif TADS_TEST\r
-\r
+++ /dev/null
-/*\r
- * tads.h - Treaty of Babel common declarations for tads2 and tads3 modules\r
- * \r
- * This file depends on treaty_builder.h\r
- * \r
- * This file is public domain, but note that any changes to this file may\r
- * render it noncompliant with the Treaty of Babel\r
- * \r
- * Modified\r
- *. 04/18/2006 MJRoberts - creation\r
- */\r
-\r
-#ifndef TADS_H\r
-#define TADS_H\r
-\r
-/* match a TADS file signature */\r
-int tads_match_sig(const void *buf, int32 len, const char *sig);\r
-\r
-/* get the IFID for a tads story file */\r
-int32 tads_get_story_file_IFID(void *story_file, int32 extent,\r
- char *output, int32 output_extent);\r
-\r
-/* get the synthesized iFiction record from a tads story file */\r
-int32 tads_get_story_file_metadata(void *story_file, int32 extent,\r
- char *buf, int32 bufsize);\r
-\r
-/* get the size of the synthesized iFiction record for a tads story file */\r
-int32 tads_get_story_file_metadata_extent(void *story_file, int32 extent);\r
-\r
-/* get the cover art from a tads story file */\r
-int32 tads_get_story_file_cover(void *story_file, int32 extent,\r
- void *buf, int32 bufsize);\r
-\r
-/* get the size of the cover art from a tads story file */\r
-int32 tads_get_story_file_cover_extent(void *story_file, int32 extent);\r
-\r
-/* get the image format (jpeg, png) of the covert art in a tads story file */\r
-int32 tads_get_story_file_cover_format(void *story_file, int32 extent);\r
-\r
-#endif /* TADS_H */\r
+++ /dev/null
-/* \r
- * tads2.c - Treaty of Babel module for Tads 2 files\r
- * \r
- * This file depends on treaty_builder.h\r
- * \r
- * This file is public domain, but note that any changes to this file may\r
- * render it noncompliant with the Treaty of Babel\r
- * \r
- * Modified\r
- *. 04/15/2006 LRRaszewski - Separated tads2.c and tads3.c \r
- *. 04/08/2006 LRRaszewski - changed babel API calls to threadsafe versions\r
- *. 04/08/2006 MJRoberts - initial implementation\r
- */\r
-\r
-#define FORMAT tads2\r
-#define HOME_PAGE "http://www.tads.org"\r
-#define FORMAT_EXT ".gam"\r
-\r
-\r
-#include "treaty_builder.h"\r
-#include "tads.h"\r
-\r
-#define T2_SIGNATURE "TADS2 bin\012\015\032"\r
-\r
-#ifndef FALSE\r
-#define FALSE 0\r
-#endif\r
-#ifndef TRUE\r
-#define TRUE 1\r
-#endif\r
-\r
-/*\r
- * get a story file's IFID\r
- */\r
-static int32 get_story_file_IFID(void *story_file, int32 extent,\r
- char *output, int32 output_extent)\r
-{\r
- /* use the common tads IFID extractor/generator */\r
- return tads_get_story_file_IFID(story_file, extent,\r
- output, output_extent);\r
-}\r
-\r
-/*\r
- * determine if a given story file is one of ours \r
- */\r
-static int32 claim_story_file(void *story_file, int32 extent)\r
-{\r
- /* check our signature */\r
- if (tads_match_sig(story_file, extent, T2_SIGNATURE))\r
- return VALID_STORY_FILE_RV;\r
-\r
- /* not one of ours */\r
- return INVALID_STORY_FILE_RV;\r
-}\r
-\r
-/*\r
- * Get the size of the iFiction metadata for the game \r
- */\r
-static int32 get_story_file_metadata_extent(void *story_file, int32 extent)\r
-{\r
- /* use the common tads iFiction synthesizer */\r
- return tads_get_story_file_metadata_extent(story_file, extent);\r
-}\r
-\r
-/*\r
- * Get the iFiction metadata for the game\r
- */\r
-static int32 get_story_file_metadata(void *story_file, int32 extent,\r
- char *buf, int32 bufsize)\r
-{\r
- /* use the common tads iFiction synthesizer */\r
- return tads_get_story_file_metadata(story_file, extent, buf, bufsize);\r
-}\r
-\r
-static int32 get_story_file_cover_extent(void *story_file, int32 story_len)\r
-{\r
- /* use the common tads cover file extractor */\r
- return tads_get_story_file_cover_extent(story_file, story_len);\r
-}\r
-\r
-/*\r
- * Get the format of the cover art \r
- */\r
-static int32 get_story_file_cover_format(void *story_file, int32 story_len)\r
-{\r
- /* use the common tads cover file extractor */\r
- return tads_get_story_file_cover_format(story_file, story_len);\r
-}\r
-\r
-/*\r
- * Get the cover art data \r
- */\r
-static int32 get_story_file_cover(void *story_file, int32 story_len,\r
- void *outbuf, int32 output_extent)\r
-{\r
- /* use the common tads cover file extractor */\r
- return tads_get_story_file_cover(story_file, story_len,\r
- outbuf, output_extent);\r
-}\r
-\r
+++ /dev/null
-/* \r
- * tads3.c - Treaty of Babel module for Tads 3 files\r
- * \r
- * This file depends on treaty_builder.h\r
- * \r
- * This file is public domain, but note that any changes to this file may\r
- * render it noncompliant with the Treaty of Babel\r
- * \r
- * Modified\r
- *. 04/15/2006 LRRaszewski - Separated tads2.c and tads3.c \r
- *. 04/08/2006 LRRaszewski - changed babel API calls to threadsafe versions\r
- *. 04/08/2006 MJRoberts - initial implementation\r
- */\r
-\r
-#define FORMAT tads3\r
-#define HOME_PAGE "http://www.tads.org"\r
-#define FORMAT_EXT ".t3"\r
-\r
-\r
-#include "treaty_builder.h"\r
-#include "tads.h"\r
-\r
-#define T3_SIGNATURE "T3-image\015\012\032"\r
-\r
-#ifndef FALSE\r
-#define FALSE 0\r
-#endif\r
-#ifndef TRUE\r
-#define TRUE 1\r
-#endif\r
-\r
-/*\r
- * get a story file's IFID \r
- */\r
-static int32 get_story_file_IFID(void *story_file, int32 extent,\r
- char *output, int32 output_extent)\r
-{\r
- /* use the common tads IFID extractor/generator */\r
- return tads_get_story_file_IFID(story_file, extent,\r
- output, output_extent);\r
-}\r
-\r
-/*\r
- * determine if a given story file is one of ours \r
- */\r
-static int32 claim_story_file(void *story_file, int32 extent)\r
-{\r
- /* check our signature */\r
- if (tads_match_sig(story_file, extent, T3_SIGNATURE))\r
- return VALID_STORY_FILE_RV;\r
-\r
- /* not one of ours */\r
- return INVALID_STORY_FILE_RV;\r
-}\r
-\r
-/*\r
- * Get the size of the iFiction metadata for the game \r
- */\r
-static int32 get_story_file_metadata_extent(void *story_file, int32 extent)\r
-{\r
- /* use the common tads iFiction synthesizer */\r
- return tads_get_story_file_metadata_extent(story_file, extent);\r
-}\r
-\r
-/*\r
- * Get the iFiction metadata for the game\r
- */\r
-static int32 get_story_file_metadata(void *story_file, int32 extent,\r
- char *buf, int32 bufsize)\r
-{\r
- /* use the common tads iFiction synthesizer */\r
- return tads_get_story_file_metadata(story_file, extent, buf, bufsize);\r
-}\r
-\r
-static int32 get_story_file_cover_extent(void *story_file, int32 story_len)\r
-{\r
- /* use the common tads cover file extractor */\r
- return tads_get_story_file_cover_extent(story_file, story_len);\r
-}\r
-\r
-/*\r
- * Get the format of the cover art \r
- */\r
-static int32 get_story_file_cover_format(void *story_file, int32 story_len)\r
-{\r
- /* use the common tads cover file extractor */\r
- return tads_get_story_file_cover_format(story_file, story_len);\r
-}\r
-\r
-/*\r
- * Get the cover art data \r
- */\r
-static int32 get_story_file_cover(void *story_file, int32 story_len,\r
- void *outbuf, int32 output_extent)\r
-{\r
- /* use the common tads cover file extractor */\r
- return tads_get_story_file_cover(story_file, story_len,\r
- outbuf, output_extent);\r
-}\r
-\r
+++ /dev/null
-/* treaty.h Header file for Treaty of Babel compliant format modules\r
- * By L. Ross Raszewski\r
- * Version 3b\r
- *\r
- * This file is public domain, but please note that derived versions\r
- * may not not be compliant with the Treaty of Babel.\r
- *\r
- * It would be wise for derived works to change the value of\r
- * TREATY_COMPLIANCE to reflect deviations\r
- */\r
-\r
-#ifndef TREATY_H\r
-\r
-#define TREATY_H\r
-\r
-#define TREATY_COMPLIANCE "Treaty of Babel revision 7"\r
-#define TREATY_VERSION "r7"\r
-\r
-/* return codes */\r
-#define NO_REPLY_RV 0\r
-#define INVALID_STORY_FILE_RV -1\r
-#define UNAVAILABLE_RV -2\r
-#define INVALID_USAGE_RV -3\r
-#define INCOMPLETE_REPLY_RV -4\r
-#define VALID_STORY_FILE_RV 1\r
-\r
-#define PNG_COVER_FORMAT 1\r
-#define JPEG_COVER_FORMAT 2\r
-\r
-/* Treaty bitmasks. These are not required by the treaty, but are here\r
- as a convenience.\r
-*/\r
-#define TREATY_SELECTOR_INPUT 0x100\r
-#define TREATY_SELECTOR_OUTPUT 0x200\r
-#define TREATY_SELECTOR_NUMBER 0xFF\r
-\r
-#define TREATY_CONTAINER_SELECTOR 0x400\r
-\r
-/* Treaty selectors */\r
-#define GET_HOME_PAGE_SEL 0x201\r
-#define GET_FORMAT_NAME_SEL 0x202\r
-#define GET_FILE_EXTENSIONS_SEL 0x203\r
-#define CLAIM_STORY_FILE_SEL 0x104\r
-#define GET_STORY_FILE_METADATA_EXTENT_SEL 0x105\r
-#define GET_STORY_FILE_COVER_EXTENT_SEL 0x106\r
-#define GET_STORY_FILE_COVER_FORMAT_SEL 0x107\r
-#define GET_STORY_FILE_IFID_SEL 0x308\r
-#define GET_STORY_FILE_METADATA_SEL 0x309\r
-#define GET_STORY_FILE_COVER_SEL 0x30A\r
-#define GET_STORY_FILE_EXTENSION_SEL 0x30B\r
-\r
-/* Container selectors */\r
-#define CONTAINER_GET_STORY_FORMAT_SEL 0x710\r
-#define CONTAINER_GET_STORY_EXTENT_SEL 0x511\r
-#define CONTAINER_GET_STORY_FILE_SEL 0x711\r
-\r
-\r
-\r
-\r
-/* Other magic size limits */\r
-#define TREATY_MINIMUM_EXTENT 512\r
-\r
-\r
-#include <limits.h>\r
-\r
-/* 32-bit integer types */\r
-#ifndef VAX\r
-#if SCHAR_MAX >= 0x7FFFFFFFL && SCHAR_MIN <= -0x7FFFFFFFL\r
- typedef signed char int32;\r
-#elif SHRT_MAX >= 0x7FFFFFFFL && SHRT_MIN <= -0x7FFFFFFFL\r
- typedef signed short int int32;\r
-#elif INT_MAX >= 0x7FFFFFFFL && INT_MIN <= -0x7FFFFFFFL\r
- typedef signed int int32;\r
-#elif LONG_MAX >= 0x7FFFFFFFL && LONG_MIN <= -0x7FFFFFFFL\r
- typedef signed long int int32;\r
-#else\r
-#error No type large enough to support 32-bit integers.\r
-#endif\r
-#else\r
- /* VAX C does not provide these limit constants, contrary to ANSI */\r
- typedef int int32;\r
-#endif\r
-\r
-\r
-\r
-/* Pointer to treaty function. Treaty functions must follow this prototype */\r
-\r
-typedef int32 (*TREATY)(int32 selector, void *, int32, void *, int32);\r
-\r
-#endif\r
-\r
+++ /dev/null
-/* treaty_builder.h common macros to build a treaty module\r
- *\r
- * 2006 By L. Ross Raszewski\r
- *\r
- * This file is public domain, but be aware that any changes to it may\r
- * cause it to cease to be compliant with the Treaty of Babel.\r
- *\r
- * This file depends on treaty.h\r
- *\r
- * The purpose of this file is to simplify the building of a treaty\r
- * module. It automatically generates a generic treaty function.\r
- *\r
- * Usage:\r
- *\r
- * #define the following values:\r
- * FORMAT The treaty name of the format\r
- * HOME_PAGE A string containing the URL of the format home page\r
- * FORMAT_EXT A string containing a comma separated list of common\r
- * extensions for game files in this format\r
- * NO_METADATA If the format does not support metadata\r
- * NO_COVER If the format does not support cover art\r
- * CUSTOM_EXTENSION If game files should not always use the first listed extension\r
- *\r
- * (Note: Formats which support metadata and cover art via a container should\r
- * define NO_METADATA and NO_COVER as container support is handled separately)\r
- *\r
- * #include "treaty_builder.h"\r
- * Define the following functions:\r
- * static int32 get_story_file_IFID(void *, int32, char *, int32);\r
- * static int32 claim_story_file(void *, int32);\r
- * Define the following functions if NO_METADATA is not defined:\r
- * static int32 get_story_file_metadata_extent(void *, int32);\r
- * static int32 get_story_file_metadata(void *, int32, char *, int32);\r
- * Define the following functions if NO_COVER is not defined\r
- * static int32 get_story_file_cover_extent(void *, int32);\r
- * static int32 get_story_file_cover_format(void *, int32);\r
- * static int32 get_story_file_cover(void *, int32, void *, int32);\r
- * Define the following if CUSTOM_EXTENSION is defined\r
- * static int32 get_story_file_extension(void *, int32, char *, int32);\r
- *\r
- * The two-parameter functions take the story file and story file extent\r
- * as parameters. The four-parameter ones also take the output\r
- * buffer and its extent. They perform the corresponding task to the\r
- * similarly-named selector.\r
- *\r
- * This file also defines the macro ASSERT_OUTPUT_SIZE(x) which\r
- * returns INVALID_USAGE_RV if output_extent is less than x.\r
- *\r
- * #define CONTAINER_FORMAT before inclusion to generate a container\r
- * module. A container module should define three additional functions:\r
- * static int32 get_story_format(void *, int32, char *, int32);\r
- * static int32 get_story_extent(void *, int32);\r
- * static int32 get_story_file(void *, int32, void *, int32);\r
- *\r
- */\r
-\r
-#ifndef TREATY_BUILDER\r
-#define TREATY_BUILDER\r
-\r
-#include "treaty.h"\r
-#include <string.h>\r
-\r
-#define ASSERT_OUTPUT_SIZE(x) do { if (output_extent < (x)) return INVALID_USAGE_RV; } while (0)\r
-\r
-#ifndef NO_METADATA\r
-static int32 get_story_file_metadata_extent(void *, int32);\r
-static int32 get_story_file_metadata(void *, int32, char *, int32);\r
-#endif\r
-#ifndef NO_COVER\r
-static int32 get_story_file_cover_extent(void *, int32);\r
-static int32 get_story_file_cover_format(void *, int32);\r
-static int32 get_story_file_cover(void *, int32, void *, int32);\r
-#endif\r
-static int32 get_story_file_IFID(void *, int32, char *, int32);\r
-static int32 claim_story_file(void *, int32);\r
-#ifdef CONTAINER_FORMAT\r
-static int32 get_story_file(void *, int32, void *, int32);\r
-static int32 get_story_format(void *, int32, char *, int32);\r
-static int32 get_story_extent(void *, int32);\r
-#endif\r
-#ifdef CUSTOM_EXTENSION\r
-static int32 get_story_file_extension(void *, int32, char *, int32);\r
-#else\r
-#include <stdio.h>\r
-static int32 get_story_file_extension(void *sf, int32 extent, char *out, int32 output_extent)\r
-{\r
- int i;\r
-\r
- if (!sf || !extent) return INVALID_STORY_FILE_RV;\r
-\r
- for(i=0;FORMAT_EXT[i] && FORMAT_EXT[i]!=',';i++);\r
- ASSERT_OUTPUT_SIZE(i+1);\r
- memcpy(out,FORMAT_EXT,i);\r
- out[i]=0;\r
- return strlen(out);\r
-}\r
-\r
-#endif\r
-\r
-#define TREATY_FUNCTION(X) DEEP_TREATY_FUNCTION(X)\r
-#define DEEP_TREATY_FUNCTION(X) X ## _treaty\r
-#define dSTRFRY(X) #X\r
-#define STRFRY(X) dSTRFRY(X)\r
-\r
-int32 TREATY_FUNCTION(FORMAT)(int32 selector,\r
- void *story_file, int32 extent,\r
- void *output, int32 output_extent)\r
-{\r
- int32 ll, csf;\r
- if ((TREATY_SELECTOR_INPUT & selector) &&\r
- (csf=claim_story_file(story_file, extent))<NO_REPLY_RV)\r
- return INVALID_STORY_FILE_RV;\r
- \r
-\r
- if ((TREATY_SELECTOR_OUTPUT & selector) &&\r
- (output_extent ==0 ||\r
- output==NULL))\r
- return INVALID_USAGE_RV;\r
- switch(selector)\r
- {\r
- case GET_HOME_PAGE_SEL:\r
- ASSERT_OUTPUT_SIZE((signed) strlen(HOME_PAGE)+1);\r
- strcpy((char *) output,HOME_PAGE);\r
- return NO_REPLY_RV;\r
- case GET_FORMAT_NAME_SEL:\r
- ASSERT_OUTPUT_SIZE(512);\r
- strncpy((char *) output,STRFRY(FORMAT),output_extent-1);\r
- return NO_REPLY_RV;\r
- case GET_FILE_EXTENSIONS_SEL:\r
- ll=(strlen(FORMAT_EXT)+1) < 512 ? (strlen(FORMAT_EXT)+1):512;\r
- ASSERT_OUTPUT_SIZE(ll);\r
- strncpy((char *) output, FORMAT_EXT, output_extent);\r
- return NO_REPLY_RV;\r
- case CLAIM_STORY_FILE_SEL:\r
- return csf;\r
- case GET_STORY_FILE_METADATA_EXTENT_SEL:\r
-#ifndef NO_METADATA\r
- return get_story_file_metadata_extent(story_file, extent);\r
-#endif\r
- case GET_STORY_FILE_METADATA_SEL:\r
-#ifndef NO_METADATA\r
- return get_story_file_metadata(story_file, extent, (char *)output, output_extent);\r
-#else\r
- return NO_REPLY_RV;\r
-#endif\r
- case GET_STORY_FILE_COVER_EXTENT_SEL:\r
-#ifndef NO_COVER\r
- return get_story_file_cover_extent(story_file, extent);\r
-#endif\r
- case GET_STORY_FILE_COVER_FORMAT_SEL:\r
-#ifndef NO_COVER\r
- return get_story_file_cover_format(story_file, extent);\r
-#endif\r
- case GET_STORY_FILE_COVER_SEL:\r
-#ifndef NO_COVER\r
- return get_story_file_cover(story_file, extent, output, output_extent);\r
-#else\r
- return NO_REPLY_RV;\r
-#endif\r
- case GET_STORY_FILE_IFID_SEL:\r
- return get_story_file_IFID(story_file, extent, (char *)output, output_extent);\r
- case GET_STORY_FILE_EXTENSION_SEL:\r
- return get_story_file_extension(story_file, extent, (char *)output, output_extent);\r
-#ifdef CONTAINER_FORMAT\r
- case CONTAINER_GET_STORY_FORMAT_SEL:\r
- return get_story_format(story_file, extent, (char *)output, output_extent);\r
- case CONTAINER_GET_STORY_EXTENT_SEL:\r
- return get_story_extent(story_file, extent);\r
- case CONTAINER_GET_STORY_FILE_SEL:\r
- return get_story_file(story_file, extent, output, output_extent);\r
-#endif\r
-\r
- }\r
- return UNAVAILABLE_RV;\r
-}\r
-\r
-\r
-#else\r
-#error "treaty_builder should be used as most once in any source file";\r
-#endif\r
+++ /dev/null
-/* zcode.c Treaty of Babel module for Z-code files\r
- * 2006 By L. Ross Raszewski\r
- *\r
- * This file depends on treaty_builder.h\r
- *\r
- * This file is public domain, but note that any changes to this file\r
- * may render it noncompliant with the Treaty of Babel\r
- */\r
-\r
-#define FORMAT zcode\r
-#define HOME_PAGE "http://www.inform-fiction.org"\r
-#define FORMAT_EXT ".z3,.z4,.z5,.z6,.z7,.z8"\r
-#define NO_METADATA\r
-#define NO_COVER\r
-#define CUSTOM_EXTENSION\r
-#include "treaty_builder.h"\r
-#include <ctype.h>\r
-#include <stdio.h>\r
-\r
-static int32 get_story_file_IFID(void *story_file, int32 extent, char *output, int32 output_extent)\r
-{\r
- int32 i,j;\r
- char ser[7];\r
- char buffer[32];\r
-\r
-\r
- if (extent<0x1D) return INVALID_STORY_FILE_RV;\r
- memcpy(ser, (char *) story_file+0x12, 6);\r
- ser[6]=0;\r
- /* Detect vintage story files */\r
- if (!(ser[0]=='8' || ser[0]=='9' ||\r
- (ser[0]=='0' && ser[1]>='0' && ser[1]<='5')))\r
- {\r
- for(i=0;i<extent;i++) if (memcmp((char *)story_file+i,"UUID://",7)==0) break;\r
- if (i<extent) /* Found explicit IFID */\r
- {\r
- for(j=i+7;j<extent && ((char *)story_file)[j]!='/';j++);\r
- if (j<extent)\r
- {\r
- i+=7;\r
- ASSERT_OUTPUT_SIZE(j-i);\r
- memcpy(output,(char *)story_file+i,j-i);\r
- output[j-i]=0;\r
- return 1;\r
- }\r
- }\r
- }\r
- /* Did not find intact IFID. Build one */\r
- i=((unsigned char *)story_file)[2] << 8 |((unsigned char *)story_file)[3];\r
- for(j=0;j<6;j++)\r
- if (!isalnum(ser[j])) ser[j]='-';\r
-\r
- j=((unsigned char *)story_file)[0x1C] << 8 |((unsigned char *)story_file)[0x1D];\r
-\r
- if (strcmp(ser,"000000") && isdigit(ser[0]) && ser[0]!='8')\r
- sprintf(buffer,"ZCODE-%d-%s-%04X",i,ser,j);\r
- else\r
- sprintf(buffer,"ZCODE-%d-%s",i,ser);\r
-\r
- ASSERT_OUTPUT_SIZE((signed) strlen(buffer)+1);\r
- strcpy((char *)output,buffer);\r
- return 1;\r
-\r
-}\r
-\r
-static int32 read_zint(unsigned char *sf)\r
-{\r
- return ((int32)sf[0] << 8) | ((int32) sf[1]);\r
-\r
-}\r
-static int32 claim_story_file(void *story_file, int32 extent)\r
-{\r
- unsigned char *sf=(unsigned char *)story_file;\r
- int32 i,j;\r
- if (extent<0x3c ||\r
- sf[0] < 1 ||\r
- sf[0] > 8\r
- ) return INVALID_STORY_FILE_RV;\r
- for(i=4;i<=14;i+=2)\r
- {\r
- j=read_zint(sf+i);\r
- if (j>extent || j < 0x40) return INVALID_STORY_FILE_RV;\r
- }\r
-\r
- return VALID_STORY_FILE_RV;\r
-}\r
-static int32 get_story_file_extension(void *sf, int32 extent, char *out, int32 output_extent)\r
-{\r
- int v;\r
- if (!extent) return INVALID_STORY_FILE_RV;\r
- v= ((char *) sf)[0];\r
- if (v>9) ASSERT_OUTPUT_SIZE(5);\r
- else ASSERT_OUTPUT_SIZE(4);\r
- sprintf(out,".z%d",v);\r
- return 3+(v>9);\r
-\r
-}\r
glib-2.0 >= $GLIB_REQUIRED_VERSION
gtk+-3.0 >= $GTK_REQUIRED_VERSION
gmodule-2.0
- dnl libgda-4.0
- libsoup-2.4
])
# Libraries needed to build test programs
PKG_CHECK_MODULES([TEST], [
docs/reference/version.xml
docs/reference/build-selector-table.pl
po/Makefile.in
-babel/Makefile
])
# Do it
-export-symbols-regex "^glk_main$$" \
-rpath $(abs_builddir)
-noinst_PROGRAMS = test-multisession glulxercise plugin-loader test-close babeltest
+noinst_PROGRAMS = test-multisession glulxercise plugin-loader test-close
test_multisession_SOURCES = test-multisession.c
test_multisession_CFLAGS = @TEST_CFLAGS@ $(AM_CFLAGS)
test_close_CFLAGS = @TEST_CFLAGS@ $(AM_CFLAGS)
test_close_LDADD = @TEST_LIBS@ $(top_builddir)/libchimara/libchimara.la
-babeltest_SOURCES = babeltest.c
-babeltest_CFLAGS = @PLAYER_CFLAGS@ $(AM_CFLAGS)
-babeltest_LDADD = @PLAYER_LIBS@ $(top_builddir)/babel/libbabel_functions.la $(top_builddir)/babel/libbabel.la $(top_builddir)/babel/libifiction.la
-
noinst_LTLIBRARIES = first.la model.la gridtest.la splittest.la multiwin.la \
styletest.la soundtest.la test-userstyle.la fileio.la
+++ /dev/null
-#include "babel/babel_handler.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <glib.h>
-#include <glib/gprintf.h>
-#include <libgda/libgda.h>
-#include <libgda/sql-parser/gda-sql-parser.h>
-#include <libsoup/soup.h>
-
-typedef struct _metadata {
- const gchar *element_name;
- gchar *ifid;
- gchar *title;
- gchar *author;
- gchar *firstpublished;
- gboolean error;
- gchar *error_message;
- gchar *error_code;
-} metadata;
-
-void start_element(
- GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- gpointer data,
- GError **error)
-{
- metadata *md = (metadata*) data;
- md->element_name = element_name;
-
- if( !strcmp(element_name, "errorCode") ) {
- md->error = 1;
- md->error_message = "";
- md->error_code = "";
- }
-
- if( !strcmp(element_name, "ifindex") ) {
- md->ifid = "";
- md->title = "";
- md->author = "";
- md->firstpublished = "";
- }
-}
-
-void text(
- GMarkupParseContext *context,
- const gchar *text,
- gsize text_len,
- gpointer data,
- GError **error)
-{
- metadata *md = (metadata*) data;
-
- if( !strcmp(md->element_name, "errorCode") ) {
- md->error_code = g_strndup(text, text_len);
- }
- else if( !strcmp(md->element_name, "errorMessage") ) {
- md->error_message = g_strndup(text, text_len);
- }
- else if( !strcmp(md->element_name, "ifid") ) {
- if( strlen(md->ifid) < text_len )
- md->ifid = g_strndup(text, text_len);
- }
- else if( !strcmp(md->element_name, "title") ) {
- if( strlen(md->title) < text_len )
- md->title = g_strndup(text, text_len);
- }
- else if( !strcmp(md->element_name, "author") ) {
- if( strlen(md->author) < text_len )
- md->author = g_strndup(text, text_len);
- }
- else if( !strcmp(md->element_name, "firstpublished") ) {
- if( strlen(md->firstpublished) < text_len )
- md->firstpublished = g_strndup(text, text_len);
- }
-}
-
-void end_element(
- GMarkupParseContext *context,
- const gchar *element_name,
- gpointer data,
- GError **error)
-{
- if( !strcmp(element_name, "ifindex") ) {
- metadata *md = (metadata*) data;
- printf("IFID: %s\nTitle: %s\nAuthor: %s\nFirst published: %s\n", md->ifid, md->title, md->author, md->firstpublished);
- }
-}
-
-/*
- * run a non SELECT command and stops if an error occurs
- */
-void
-run_sql_non_select(GdaConnection *cnc, const gchar *sql)
-{
- GdaStatement *stmt;
- GError *error = NULL;
- gint nrows;
- const gchar *remain;
- GdaSqlParser *parser;
-
- parser = g_object_get_data(G_OBJECT(cnc), "parser");
- stmt = gda_sql_parser_parse_string(parser, sql, &remain, &error);
- if(remain)
- g_print ("REMAINS: %s\n", remain);
-
- nrows = gda_connection_statement_execute_non_select(cnc, stmt, NULL, NULL, &error);
- if(nrows == -1)
- g_error("NON SELECT error: %s\n", error && error->message ? error->message : "no detail");
- g_object_unref(stmt);
-}
-
-int main(int argc, char **argv) {
- GError *err = NULL;
- metadata data;
- data.error = 0;
-
- if(argc < 2) {
- fprintf(stderr, "Usage: %s <story file>\n", argv[0]);
- return 1;
- }
-
- g_type_init();
-
- babel_init(argv[1]);
- int len = babel_treaty(GET_STORY_FILE_METADATA_EXTENT_SEL, NULL, 0);
- gchar *ifiction;
- if(len) {
- printf("Metadata found in file.\n");
- gchar *buffer = malloc(len * sizeof(gchar));
- babel_treaty(GET_STORY_FILE_METADATA_SEL, buffer, len);
- ifiction = g_strndup(buffer, len);
- g_free(buffer);
- } else {
- printf("No metadata found in file, performing IFDB lookup.\n");
- gchar *ifid = malloc(TREATY_MINIMUM_EXTENT * sizeof(gchar));
- if( !babel_treaty(GET_STORY_FILE_IFID_SEL, ifid, TREATY_MINIMUM_EXTENT) ) {
- fprintf(stderr, "Unable to create an IFID (A serious problem occurred while loading the file).\n");
- babel_release();
- return 1;
- }
- printf("Looking up IFID: %s.\n", ifid);
- babel_release();
-
- SoupSession *session = soup_session_async_new();
- char *uri_string = g_strconcat("http://ifdb.tads.org/viewgame?ifiction&ifid=", ifid, NULL);
- SoupMessage *message = soup_message_new("GET", uri_string);
- g_free(uri_string);
- soup_message_headers_append(message->request_headers, "Connection", "close");
- if(soup_session_send_message(session, message) != 200)
- g_printerr("ERROR: did not get HTTP status 200\n");
- ifiction = g_strndup(message->response_body->data, message->response_body->length);
- g_object_unref(message);
- g_object_unref(session);
- }
-
- ifiction = g_strchomp(ifiction);
-
- GMarkupParser xml_parser = {start_element, end_element, text, NULL, NULL};
- GMarkupParseContext *context = g_markup_parse_context_new(&xml_parser, 0, &data, NULL);
-
- if( g_markup_parse_context_parse(context, ifiction, strlen(ifiction), &err) == FALSE ) {
- fprintf(stderr, "Metadata parse failed: %s\n", err->message);
- }
-
- g_markup_parse_context_free(context);
- g_free(ifiction);
-
- babel_release();
-
- // Check for errors
- if(data.error) {
- fprintf(stderr, "ERROR %s: %s\n", data.error_code, data.error_message);
- return 1;
- }
-
- // Open DB connection
- GdaConnection *cnc;
- GdaSqlParser *sql_parser;
-
- gda_init();
- cnc = gda_connection_open_from_string("SQLite", "DB_DIR=.;DB_NAME=library", NULL, GDA_CONNECTION_OPTIONS_NONE, &err);
- if(!cnc) {
- fprintf(stderr, "Could not open connection to SQLite database in library.db file: %s\n", err && err->message ? err->message : "No details");
- return 1;
- }
-
- sql_parser = gda_connection_create_parser(cnc);
- if(!sql_parser) // cnc does not provide its own parser, use default one
- sql_parser = gda_sql_parser_new();
-
- g_object_set_data_full(G_OBJECT(cnc), "parser", sql_parser, g_object_unref);
-
- // Create stories table
- //run_sql_non_select(cnc, "DROP TABLE IF EXISTS stories");
- run_sql_non_select(cnc, "CREATE TABLE IF NOT EXISTS stories (ifid text not null primary key, title text, author text, firstpublished text)");
-
- // Populate the table
- GValue *v1, *v2, *v3, *v4;
- v1 = gda_value_new_from_string(data.ifid, G_TYPE_STRING);
- v2 = gda_value_new_from_string(data.title, G_TYPE_STRING);
- v3 = gda_value_new_from_string(data.author, G_TYPE_STRING);
- v4 = gda_value_new_from_string(data.firstpublished, G_TYPE_STRING);
-
- if( !gda_insert_row_into_table(cnc, "stories", &err, "ifid", v1, "title", v2, "author", v3, "firstpublished", v4, NULL) ) {
- g_warning("Could not INSERT data into the 'stories' table: %s\n", err && err->message ? err->message : "No details");
- }
-
- gda_value_free(v1);
- gda_value_free(v2);
- gda_value_free(v3);
- gda_value_free(v4);
-
- // Dump the table contents
- GdaDataModel *data_model;
- GdaStatement *stmt = gda_sql_parser_parse_string(sql_parser, "SELECT * FROM stories", NULL, NULL);
- data_model = gda_connection_statement_execute_select(cnc, stmt, NULL, &err);
- if(!data_model)
- g_error("Could not get the contents of the 'stories' table: %s\n", err && err->message ? err->message : "No details");
- printf("Dumping library table:\n");
- gda_data_model_dump(data_model, stdout);
-
- g_object_unref(stmt);
- g_object_unref(data_model);
-
- gda_connection_close(cnc);
- return 0;
-}