ed4005a839e943367d40fb25e0ed1a605f8190ad kent Tue Aug 6 17:43:49 2013 -0700 Making it generate a new function. diff --git src/utils/raToStructGen/raToStructGen.c src/utils/raToStructGen/raToStructGen.c index c21ff63..4f0fe58 100644 --- src/utils/raToStructGen/raToStructGen.c +++ src/utils/raToStructGen/raToStructGen.c @@ -4,48 +4,48 @@ #include "hash.h" #include "options.h" #include "obscure.h" #include "sqlNum.h" #include "ra.h" #include "asParse.h" char *requiredAsComma = NULL; 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" + "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" ); } /* Command line validation table. */ static struct optionSpec options[] = { {"required", OPTION_STRING}, {NULL, 0}, }; struct raToStructReader /* Something to help us parse RAs into C structures. */ { - struct xyzReader *next; + 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. */ }; struct raToStructReader *raToStructReaderNew(char *name, int fieldCount, char **fields, int requiredFieldCount, char **requiredFields) /* Create a helper object for parsing an ra file into a C structure. This structure will * contain */ { @@ -88,91 +88,120 @@ freeMem(reader->fieldsObserved); freez(pReader); } } void raToStructReaderCheckRequiredFields(struct raToStructReader *reader, struct lineFile *lf) /* 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; irequiredFieldCount; ++i) { if (!fieldsObserved[requiredFieldIds[i]]) { - errAbort("Required field %s not found line %d of %s\n", reader->requiredFields[i], + errAbort("Required field %s not found line %d of %s", reader->requiredFields[i], lf->lineIx, lf->fileName); } } } - void raToStructGen(char *guideFile, char *outFileC) /* raToStructGen - Write C code that will read/write a C structure from a ra file. */ { 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); -uglyf("%d of %d fields of %s are required\n", requiredCount, slCount(as->columnList), as->name); FILE *f = mustOpen(outFileC, "w"); +/* 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) + fprintf(f, " \"%s\",\n", col->name); +fprintf(f, " };\n"); + +char *rfString = "NULL"; +if (requiredCount > 0) + { + fprintf(f, "static char *requiredFields[] = {\n"); + int i; + for (i=0; imaker function. */ +fprintf(f, + "return raToStructReaderNew(\"%s\", %d, fields, %d, %s);\n" + "}\n" + "\n" + , as->name, slCount(as->columnList), requiredCount, rfString); + /* Print out start of parsing function. */ fprintf(f, "\n" -"struct %s *%sFromNextRaStanza(struct lineFile *lf, struct raToStructReader *reader)\n" +"struct %s *%sFromNextRa(struct lineFile *lf, struct raToStructReader *reader)\n" "/* Return next stanza put into an %s. */\n" "{\n" "if (!raSkipLeadingEmptyLines(lf, NULL))\n" " return NULL;\n" "\n" "struct %s *el;\n" "AllocVar(el);\n" "\n" "bool *fieldsObserved = reader->fieldsObserved;\n" "bzero(fieldsObserved, reader->fieldCount);\n" "\n" "char *tag, *val;\n" "while (raNextTagVal(lf, &tag, &val, NULL))\n" " {\n" " struct hashEl *hel = hashLookup(reader->fieldIds, tag);\n" " if (hel != NULL)\n" " {\n" " int id = ptToInt(hel->val);\n" " if (fieldsObserved[id])\n" " errAbort(\"Duplicate tag %%s line %%d of %%s\\n\", tag, lf->lineIx, lf->fileName);\n" " fieldsObserved[id] = TRUE;\n" " switch (id)\n" " {\n" , as->name, as->name, as->name, as->name); /* Now loop through and print out cases for each field. */ -struct asColumn *col; int colIx = 0; for (col = as->columnList; col != NULL; col = col->next) { fprintf(f, " case %d:\n", colIx++); fprintf(f, " {\n"); struct asTypeInfo *lt = col->lowType; enum asTypes type = lt->type; if (col->isList) { switch (type) { /* Handle numerical types */ case t_float: case t_double: case t_int: @@ -239,27 +268,29 @@ " default:\n" " internalErr();\n" " break;\n" " }\n" " }\n" " }\n" "\n" "if (reader->requiredFieldIds != NULL)\n" " raToStructReaderCheckRequiredFields(reader, lf);\n" "return el;\n" "}\n" "\n" ); carefulClose(&f); +verbose(1, "Generated parser for %d required fields, %d total fields\n", + requiredCount, slCount(as->columnList)); } int main(int argc, char *argv[]) /* Process command line. */ { optionInit(&argc, argv, options); if (argc != 3) usage(); requiredAsComma = optionVal("required", NULL); raToStructGen(argv[1], argv[2]); return 0; }