X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=babel%2Fbabel.c;fp=babel%2Fbabel.c;h=5bb7213332f4eb93fb21474b8b3e561c0b100b2f;hb=6fd0347f330cb24ef6145662023053a1c0f81a64;hp=0000000000000000000000000000000000000000;hpb=7d14a66ee234db0898de6fabb8f850ebc4bb733a;p=projects%2Fchimara%2Fchimara.git diff --git a/babel/babel.c b/babel/babel.c new file mode 100644 index 0000000..5bb7213 --- /dev/null +++ b/babel/babel.c @@ -0,0 +1,248 @@ +/* babel.c The babel command line program + * (c) 2006 By L. Ross Raszewski + * + * This code is freely usable for all purposes. + * + * This work is licensed under the Creative Commons Attribution2.5 License. + * To view a copy of this license, visit + * http://creativecommons.org/licenses/by/2.5/ or send a letter to + * Creative Commons, + * 543 Howard Street, 5th Floor, + * San Francisco, California, 94105, USA. + * + * This file depends upon misc.c and babel.h + * + * This file exports one variable: char *rv, which points to the file name + * for an ifiction file. This is used only by babel_ifiction_verify + */ + +#include "babel.h" +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +int chdir(const char *); +char *getcwd(char *, int); +#ifdef __cplusplus +} +#endif + +char *fn; + +/* checked malloc function */ +void *my_malloc(int, char *); + +/* babel performs several fundamental operations, which are specified + by command-line objects. Each of these functions corresponds to + a story function (defined in babel_story_functions.c) or an + ifiction function (defined in babel_ifiction_functions.c) or both. + These are the types of those functions. +*/ + +typedef void (*story_function)(void); +typedef void (*ifiction_function)(char *); +typedef void (*multi_function)(char **, char *, int); +/* This structure tells babel what to do with its command line arguments. + if either of story or ifiction are NULL, babel considers this command line + option inappropriate for that type of file. +*/ +struct function_handler { + char *function; /* the textual command line option */ + story_function story; /* handler for story files */ + ifiction_function ifiction; /* handler for ifiction files */ + char *desc; /* Textual description for help text */ + }; + +struct multi_handler { + char *function; + char *argnames; + multi_function handler; + int nargsm; + int nargsx; + char *desc; + }; +/* This is an array of function_handler objects which specify the legal + arguments. It is terminated by a function_handler with a NULL function + */ +static struct function_handler functions[] = { + { "-ifid", babel_story_ifid, babel_ifiction_ifid, "Deduce IFID"}, + { "-format", babel_story_format, NULL, "Deduce story format" }, + { "-ifiction", babel_story_ifiction, NULL, "Extract iFiction file" }, + { "-meta", babel_story_meta, NULL, "Print story metadata" }, + { "-identify", babel_story_identify, NULL, "Describe story file" }, + { "-cover", babel_story_cover, NULL, "Extract cover art" }, + { "-story", babel_story_story, NULL, "Extract story file (ie. from a blorb)" }, + { "-verify", NULL, babel_ifiction_verify, "Verify integrity of iFiction file" }, + { "-lint", NULL, babel_ifiction_lint, "Verify style of iFiction file" }, + { "-fish", babel_story_fish, babel_ifiction_fish, "Extract all iFiction and cover art"}, + { "-unblorb", babel_story_unblorb, NULL, "As -fish, but also extract story files"}, + { NULL, NULL, NULL } + }; +static struct multi_handler multifuncs[] = { + { "-blorb", " []", babel_multi_blorb, 2, 3, "Bundle story file and (sparse) iFiction into blorb" }, + { "-blorbs", " []", babel_multi_blorb1, 2, 3, "Bundle story file and (sparse) iFiction into sensibly-named blorb" }, + { "-complete", " ", babel_multi_complete, 2, 2, "Create complete iFiction file from sparse iFiction" }, + { NULL, NULL, NULL, 0, 0, NULL } +}; + +int main(int argc, char **argv) +{ + char *todir="."; + char cwd[512]; + int ok=1,i, l, ll; + FILE *f; + char *md=NULL; + /* Set the input filename. Note that if this is invalid, babel should + abort before anyone notices + */ + fn=argv[2]; + + if (argc < 3) ok=0; + /* Detect the presence of the "-to " argument. + */ + if (ok && argc >=5 && strcmp(argv[argc-2], "-to")==0) + { + todir=argv[argc-1]; + argc-=2; + } + if (ok) for(i=0;multifuncs[i].function;i++) + if (strcmp(argv[1],multifuncs[i].function)==0 && + argc>= multifuncs[i].nargsm+2 && + argc <= multifuncs[i].nargsx+2) + { + + multifuncs[i].handler(argv+2, todir, argc-2); + exit(0); + } + + if (argc!=3) ok=0; + + /* Find the apropriate function_handler */ + if (ok) { + for(i=0;functions[i].function && strcmp(functions[i].function,argv[1]);i++); + if (!functions[i].function) ok=0; + else if (strcmp(fn,"-")) { + f=fopen(argv[2],"r"); + if (!f) ok=0; + } + } + + /* Print usage error if anything has gone wrong */ + if (!ok) + { + printf("%s: Treaty of Babel Analysis Tool (%s, %s)\n" + "Usage:\n", argv[0],BABEL_VERSION, TREATY_COMPLIANCE); + for(i=0;functions[i].function;i++) + { + if (functions[i].story) + printf(" babel %s \n",functions[i].function); + if (functions[i].ifiction) + printf(" babel %s \n",functions[i].function); + printf(" %s\n",functions[i].desc); + } + for(i=0;multifuncs[i].function;i++) + { + printf("babel %s %s\n %s\n", + multifuncs[i].function, + multifuncs[i].argnames, + multifuncs[i].desc); + } + + printf ("\nFor functions which extract files, add \"-to \" to the command\n" + "to set the output directory.\n" + "The input file can be specified as \"-\" to read from standard input\n" + "(This may only work for .iFiction files)\n"); + return 1; + } + + /* For story files, we end up reading the file in twice. This + is unfortunate, but unavoidable, since we want to be all + cross-platformy, so the first time we read it in, we + do the read in text mode, and the second time, we do it in binary + mode, and there are platforms where this makes a difference. + */ + ll=0; + if (strcmp(fn,"-")) + { + fseek(f,0,SEEK_END); + l=ftell(f)+1; + fseek(f,0,SEEK_SET); + md=(char *)my_malloc(l,"Input file buffer"); + fread(md,1,l-1,f); + md[l-1]=0; + } + else + while(!feof(stdin)) + { + char *tt, mdb[1024]; + int ii; + ii=fread(mdb,1,1024,stdin); + tt=(char *)my_malloc(ll+ii,"file buffer"); + if (md) { memcpy(tt,md,ll); free(md); } + memcpy(tt+ll,mdb,ii); + md=tt; + ll+=ii; + if (ii<1024) break; + } + + + if (strstr(md,""); + if (pp) *(pp+10)=0; + getcwd(cwd,512); + chdir(todir); + l=0; + if (functions[i].ifiction) + functions[i].ifiction(md); + else + fprintf(stderr,"Error: option %s is not valid for iFiction files\n", + argv[1]); + chdir(cwd); + } + + if (strcmp(fn,"-")) + { + free(md); + fclose(f); + } + if (l) + { /* Appears to be a story */ + char *lt; + if (functions[i].story) + { + if (strcmp(fn,"-")) lt=babel_init(argv[2]); + else { lt=babel_init_raw(md,ll); + free(md); + } + + if (lt) + { + getcwd(cwd,512); + chdir(todir); + if (!babel_get_authoritative() && strcmp(argv[1],"-format")) + printf("Warning: Story format could not be positively identified. Guessing %s\n",lt); + functions[i].story(); + + chdir(cwd); + } + else if (strcmp(argv[1],"-ifid")==0) /* IFID is calculable for all files */ + { + babel_md5_ifid(cwd,512); + printf("IFID: %s\n",cwd); + } + else + fprintf(stderr,"Error: Did not recognize format of story file\n"); + babel_release(); + } + else + fprintf(stderr,"Error: option %s is not valid for story files\n", + argv[1]); + } + + return 0; +}