bc9bf742e89a5fcbe6bc6f164a15516d1c01a4fc kent Thu Aug 8 12:17:48 2013 -0700 Got output to compile. Added a test script. diff --git src/utils/raToStructGen/raToStructGen.c src/utils/raToStructGen/raToStructGen.c index 3cab43c..2390794 100644 --- src/utils/raToStructGen/raToStructGen.c +++ src/utils/raToStructGen/raToStructGen.c @@ -1,49 +1,52 @@ /* raToStructGen - Write C code that will read/write a C structure from a ra file.. */ #include "common.h" #include "linefile.h" #include "hash.h" #include "options.h" #include "obscure.h" #include "sqlNum.h" #include "ra.h" #include "asParse.h" /* Command line globals. */ char *requiredAsComma = NULL; char *computedAsComma = NULL; +boolean testMain = FALSE; void usage() /* Explain usage and exit. */ { errAbort( "raToStructGen - Write C code that will read/write a C structure from a ra file.\n" "In some ways a poor cousin to AutoSql. Only handles numeric and string types, and\n" "arrays of these.\n" "usage:\n" " raToStructGen guide.as output.c\n" "options:\n" " -required=comma,sep,list - comma separated list of required fields.\n" " -computed=comma,sep,list - comma separated list of fields that are computed not parsed\n" " These fields will be ignored if in input\n" + " -testMain - generate a main() routine to help test\n" ); } /* Command line validation table. */ static struct optionSpec options[] = { {"required", OPTION_STRING}, {"computed", OPTION_STRING}, + {"testMain", OPTION_BOOLEAN}, {NULL, 0}, }; struct raToStructReader /* Something to help us parse RAs into C structures. */ { struct raToStructReader *next; char *name; /* Name of structure */ int fieldCount; /* Number of fields. */ char **fields; /* Names of all fields - not allocated here. */ char **requiredFields; /* Names of required fields - not allocated here */ int requiredFieldCount; /* Count of required fields. */ struct hash *fieldIds; /* So we can do hashLookup/switch instead of strcmp chain */ int *requiredFieldIds; /* An array of IDs of required fields. */ bool *fieldsObserved; /* An entry for each field we've observed. */ @@ -105,67 +108,104 @@ /* Make sure that all required files have been seen in the stanza we just parsed. */ { int *requiredFieldIds = reader->requiredFieldIds; bool *fieldsObserved = reader->fieldsObserved; int i; for (i=0; i<reader->requiredFieldCount; ++i) { if (!fieldsObserved[requiredFieldIds[i]]) { errAbort("Required field %s not found line %d of %s", reader->requiredFields[i], lf->lineIx, lf->fileName); } } } +void addTestMain(FILE *f, struct asObject *as) +/* Print out a main routine that will do a little testing. */ +{ +fprintf(f, +"int main(int argc, char *argv[])\n" +"/* Process command line and test. */\n" +"{\n" +"if (argc != 2)\n" +" errAbort(\"expecting exactly one command line argument\");\n" +"struct %s *list = %sLoadRa(argv[1]);\n" +"printf(\"Got %%d elements in %%s\\n\", slCount(list), argv[1]);\n" +"return 0;\n" +"}\n" +"\n" +, as->name, as->name); +} + void raToStructGen(char *guideFile, char *outFileC) /* raToStructGen - Write C code that will read/write a C structure from a ra file. */ { struct hash *ignoreHash = hashNew(0); +/* Convert comma separated computeAsComma list to ignoreHash */ int computedCount = 0; if (computedAsComma != NULL) { if (lastChar(computedAsComma) == ',') trimLastChar(computedAsComma); computedCount = chopByChar(computedAsComma, ',', NULL, 0); char **computedFields = NULL; AllocArray(computedFields, computedCount); chopByChar(computedAsComma, ',', computedFields, computedCount); int i; for (i=0; i<computedCount; ++i) hashAdd(ignoreHash, computedFields[i], NULL); } +/* Parse through requiredAsComma */ int requiredCount = 0; char **requiredFields = NULL; if (requiredAsComma != NULL) { if (lastChar(requiredAsComma) == ',') trimLastChar(requiredAsComma); requiredCount = chopByChar(requiredAsComma, ',', NULL, 0); AllocArray(requiredFields, requiredCount); chopByChar(requiredAsComma, ',', requiredFields, requiredCount); } struct asObject *as = asParseFile(guideFile); if (as == NULL) errAbort("Nothing in %s", guideFile); if (as->next != NULL) errAbort("Multiple objects in %s, only one allowed", guideFile); FILE *f = mustOpen(outFileC, "w"); +/* Print out header. */ +fprintf(f, +"/* Parser to read in a %s from a ra file where tags in ra file correspond to fields in a\n" +" * struct. This program was generated by raToStructGen. */\n" +"\n" +"#include \"common.h\"\n" +"#include \"linefile.h\"\n" +"#include \"hash.h\"\n" +"#include \"obscure.h\"\n" +"#include \"sqlNum.h\"\n" +"#include \"sqlList.h\"\n" +"#include \"ra.h\"\n" +"#include \"raToStruct.h\"\n" +, as->name); +if (testMain) + fprintf(f, "#include \"testStruct.h\"\n"); +fprintf(f, "\n"); + /* Print out start of reader-maker function. */ fprintf(f, "struct raToStructReader *%sRaReader()\n" "/* Make a raToStructReader for %s */\n" "{\n" "static char *fields[] = {\n" , as->name, as->name); /* Print out all field names */ struct asColumn *col; for (col = as->columnList; col != NULL; col = col->next) if (!skipColumn(col, ignoreHash)) fprintf(f, " \"%s\",\n", col->name); fprintf(f, " };\n"); @@ -345,32 +385,36 @@ /* Print out single record reader. */ fprintf(f, "struct %s *%sOneFromRa(char *fileName)\n" "/* Return %s in file and insist there be exactly one record. */\n" "{\n" "struct %s *one = %sLoadRa(fileName);\n" "if (one == NULL)\n" " errAbort(\"No data in %%s\", fileName);\n" "if (one->next != NULL)\n" " errAbort(\"Multiple records in %%s\", fileName);\n" "return one;\n" "}\n" "\n" , as->name, as->name, as->name, as->name, as->name); +if (testMain) + addTestMain(f, as); + carefulClose(&f); verbose(1, "Generated parser for %d required fields, %d computed fields, %d total fields\n", requiredCount, computedCount, slCount(as->columnList)); } int main(int argc, char *argv[]) /* Process command line. */ { optionInit(&argc, argv, options); if (argc != 3) usage(); requiredAsComma = optionVal("required", NULL); computedAsComma = optionVal("computed", NULL); +testMain = optionExists("testMain"); raToStructGen(argv[1], argv[2]); return 0; }