+++ /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