00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "csv.h"
00011
00012 typedef struct {
00013 char *name;
00014 char *upper;
00015 datatype type;
00016 int indx;
00017 } FIELD;
00018
00019 int code_source(void);
00020 int code_header(void);
00021 int desc_dump(void);
00022 int desc_load(void);
00023 char *type_to_string(datatype);
00024 int usage(void);
00025
00026
00027
00028
00029 FILE *cfp;
00030 FILE *hfp;
00031 char *progname;
00032 int verbose;
00033
00034 u_int field_cnt;
00035 FIELD *fields;
00036
00037 int
00038 main(int argc, char *argv[])
00039 {
00040 int ch;
00041 char *cfile, *hfile;
00042
00043
00044 if ((progname = strrchr(argv[0], '/')) == NULL)
00045 progname = argv[0];
00046 else
00047 ++progname;
00048
00049
00050 cfile = "csv_local.c";
00051 hfile = "csv_local.h";
00052
00053
00054 while ((ch = getopt(argc, argv, "c:f:h:v")) != EOF)
00055 switch (ch) {
00056 case 'c':
00057 cfile = optarg;
00058 break;
00059 case 'f':
00060 if (freopen(optarg, "r", stdin) == NULL) {
00061 fprintf(stderr,
00062 "%s: %s\n", optarg, strerror(errno));
00063 return (EXIT_FAILURE);
00064 }
00065 break;
00066 case 'h':
00067 hfile = optarg;
00068 break;
00069 case 'v':
00070 ++verbose;
00071 break;
00072 case '?':
00073 default:
00074 return (usage());
00075 }
00076 argc -= optind;
00077 argv += optind;
00078
00079 if (*argv != NULL)
00080 return (usage());
00081
00082
00083 if (desc_load())
00084 return (EXIT_FAILURE);
00085
00086
00087 if (verbose && desc_dump())
00088 return (EXIT_FAILURE);
00089
00090
00091 if ((cfp = fopen(cfile, "w")) == NULL) {
00092 fprintf(stderr,
00093 "%s: %s: %s\n", progname, cfile, strerror(errno));
00094 return (EXIT_FAILURE);
00095 }
00096 if ((hfp = fopen(hfile, "w")) == NULL) {
00097 fprintf(stderr,
00098 "%s: %s: %s\n", progname, hfile, strerror(errno));
00099 return (EXIT_FAILURE);
00100 }
00101
00102
00103 if (code_header())
00104 return (EXIT_FAILURE);
00105 if (code_source())
00106 return (EXIT_FAILURE);
00107
00108 return (EXIT_SUCCESS);
00109 }
00110
00111
00112
00113
00114
00115 int
00116 desc_load()
00117 {
00118 u_int field_alloc;
00119 int version;
00120 char *p, *t, save_ch, buf[256];
00121
00122 field_alloc = version = 0;
00123 while (fgets(buf, sizeof(buf), stdin) != NULL) {
00124 if ((p = strchr(buf, '\n')) == NULL) {
00125 fprintf(stderr, "%s: input line too long\n", progname);
00126 return (1);
00127 }
00128 *p = '\0';
00129
00130
00131 for (p = buf; isspace(*p); ++p)
00132 ;
00133
00134
00135 if (*p == '\0' || *p == '#')
00136 continue;
00137
00138
00139 if (!version) {
00140 if (strncasecmp(
00141 p, "version", sizeof("version") - 1) == 0) {
00142 version = 1;
00143 continue;
00144 }
00145 fprintf(stderr,
00146 "%s: expected \"version\" line\n", progname);
00147 return (1);
00148 }
00149
00150
00151
00152
00153
00154 if (*p == '}') {
00155 version = 0;
00156 continue;
00157 }
00158
00159
00160 if (field_cnt == field_alloc &&
00161 (fields = realloc(fields, field_alloc += 100)) == NULL) {
00162 fprintf(stderr, "%s: %s\n", progname, strerror(errno));
00163 return (1);
00164 }
00165
00166
00167 for (t = p; *t != '\0' && !isspace(*t); ++t)
00168 ;
00169 save_ch = *t;
00170 *t = '\0';
00171 if ((fields[field_cnt].name = strdup(p)) == NULL ||
00172 (fields[field_cnt].upper = strdup(p)) == NULL) {
00173 fprintf(stderr, "%s: %s\n", progname, strerror(errno));
00174 return (1);
00175 }
00176 *t = save_ch;
00177 p = t;
00178
00179 fields[field_cnt].indx = 0;
00180 fields[field_cnt].type = NOTSET;
00181 for (;;) {
00182
00183 for (; *p != '\0' && isspace(*p); ++p)
00184 ;
00185 if (*p == '\0')
00186 break;
00187
00188
00189 for (t = p; *t != '\0' && !isspace(*t); ++t)
00190 ;
00191 save_ch = *t;
00192 *t = '\0';
00193 if (strcasecmp(p, "double") == 0)
00194 fields[field_cnt].type = DOUBLE;
00195 else if (strcasecmp(p, "index") == 0)
00196 fields[field_cnt].indx = 1;
00197 else if (strcasecmp(p, "string") == 0)
00198 fields[field_cnt].type = STRING;
00199 else if (strcasecmp(p, "ulong") == 0)
00200 fields[field_cnt].type = ULONG;
00201 else {
00202 fprintf(stderr,
00203 "%s: unknown keyword: %s\n", progname, p);
00204 return (1);
00205 }
00206 *t = save_ch;
00207 p = t;
00208 }
00209
00210
00211 for (p = fields[field_cnt].upper; *p != '\0'; ++p)
00212 if (islower(*p))
00213 *p = (char)toupper(*p);
00214 ++field_cnt;
00215 }
00216 if (ferror(stdin)) {
00217 fprintf(stderr, "%s: stdin: %s\n", progname, strerror(errno));
00218 return (1);
00219 }
00220 return (0);
00221 }
00222
00223
00224
00225
00226
00227 int
00228 desc_dump()
00229 {
00230 FIELD *f;
00231 u_int i;
00232
00233 for (f = fields, i = 0; i < field_cnt; ++i, ++f) {
00234 fprintf(stderr, "field {%s}: (", f->name);
00235 switch (f->type) {
00236 case NOTSET:
00237 fprintf(stderr, "ignored");
00238 break;
00239 case DOUBLE:
00240 fprintf(stderr, "double");
00241 break;
00242 case STRING:
00243 fprintf(stderr, "string");
00244 break;
00245 case ULONG:
00246 fprintf(stderr, "ulong");
00247 break;
00248 }
00249 if (f->indx)
00250 fprintf(stderr, ", indexed");
00251 fprintf(stderr, ")\n");
00252 }
00253 return (0);
00254 }
00255
00256
00257
00258
00259
00260 int
00261 code_header()
00262 {
00263 FIELD *f;
00264 u_int i;
00265
00266 fprintf(hfp, "/*\n");
00267 fprintf(hfp, " * DO NOT EDIT: automatically built by %s.\n", progname);
00268 fprintf(hfp, " *\n");
00269 fprintf(hfp, " * Record structure.\n");
00270 fprintf(hfp, " */\n");
00271 fprintf(hfp, "typedef struct __DbRecord {\n");
00272 fprintf(hfp, "\tu_int32_t\t recno;\t\t/* Record number */\n");
00273 fprintf(hfp, "\n");
00274 fprintf(hfp, "\t/*\n");
00275 fprintf(hfp, "\t * Management fields\n");
00276 fprintf(hfp, "\t */\n");
00277 fprintf(hfp, "\tvoid\t\t*raw;\t\t/* Memory returned by DB */\n");
00278 fprintf(hfp, "\tu_char\t\t*record;\t/* Raw record */\n");
00279 fprintf(hfp, "\tsize_t\t\t record_len;\t/* Raw record length */\n\n");
00280 fprintf(hfp, "\tu_int32_t\t field_count;\t/* Field count */\n");
00281 fprintf(hfp, "\tu_int32_t\t version;\t/* Record version */\n\n");
00282 fprintf(hfp, "\tu_int32_t\t*offset;\t/* Offset table */\n");
00283 fprintf(hfp, "\n");
00284
00285 fprintf(hfp, "\t/*\n");
00286 fprintf(hfp, "\t * Indexed fields\n");
00287 fprintf(hfp, "\t */\n");
00288 for (f = fields, i = 0; i < field_cnt; ++i, ++f) {
00289 if (f->type == NOTSET)
00290 continue;
00291 if (i != 0)
00292 fprintf(hfp, "\n");
00293 fprintf(hfp, "#define CSV_INDX_%s\t%d\n", f->upper, i + 1);
00294 switch (f->type) {
00295 case NOTSET:
00296
00297 abort();
00298 break;
00299 case DOUBLE:
00300 fprintf(hfp, "\tdouble\t\t %s;\n", f->name);
00301 break;
00302 case STRING:
00303 fprintf(hfp, "\tchar\t\t*%s;\n", f->name);
00304 break;
00305 case ULONG:
00306 fprintf(hfp, "\tu_long\t\t %s;\n", f->name);
00307 break;
00308 }
00309 }
00310 fprintf(hfp, "} DbRecord;\n");
00311
00312 return (0);
00313 }
00314
00315
00316
00317
00318
00319 int
00320 code_source()
00321 {
00322 FIELD *f;
00323 u_int i;
00324
00325 fprintf(cfp, "/*\n");
00326 fprintf(cfp,
00327 " * DO NOT EDIT: automatically built by %s.\n", progname);
00328 fprintf(cfp, " *\n");
00329 fprintf(cfp, " * Initialized record structure.\n");
00330 fprintf(cfp, " */\n");
00331 fprintf(cfp, "\n");
00332 fprintf(cfp, "#include \"csv.h\"\n");
00333 fprintf(cfp, "#include \"csv_local.h\"\n");
00334 fprintf(cfp, "\n");
00335 fprintf(cfp, "DbRecord DbRecord_base = {\n");
00336 fprintf(cfp, "\t0,\t\t/* Record number */\n");
00337 fprintf(cfp, "\tNULL,\t\t/* Memory returned by DB */\n");
00338 fprintf(cfp, "\tNULL,\t\t/* Raw record */\n");
00339 fprintf(cfp, "\t0,\t\t/* Raw record length */\n");
00340 fprintf(cfp, "\t%d,\t\t/* Field count */\n", field_cnt);
00341 fprintf(cfp, "\t0,\t\t/* Record version */\n");
00342 fprintf(cfp, "\tNULL,\t\t/* Offset table */\n");
00343 fprintf(cfp, "\n");
00344 for (f = fields, i = 0; i < field_cnt; ++i, ++f) {
00345 if (f->type == NOTSET)
00346 continue;
00347 switch (f->type) {
00348 case NOTSET:
00349 abort();
00350
00351 break;
00352 case DOUBLE:
00353 case ULONG:
00354 fprintf(cfp, "\t0,\t\t/* %s */\n", f->name);
00355 break;
00356 case STRING:
00357 fprintf(cfp, "\tNULL,\t\t/* %s */\n", f->name);
00358 break;
00359 }
00360 }
00361 fprintf(cfp, "};\n");
00362
00363 fprintf(cfp, "\n");
00364 fprintf(cfp, "DbField fieldlist[] = {\n");
00365 for (f = fields, i = 0; i < field_cnt; ++i, ++f) {
00366 if (f->type == NOTSET)
00367 continue;
00368 fprintf(cfp, "\t{ \"%s\",", f->name);
00369 fprintf(cfp, " CSV_INDX_%s,", f->upper);
00370 fprintf(cfp, "\n\t %s,", type_to_string(f->type));
00371 fprintf(cfp, " %d,", f->indx ? 1 : 0);
00372 fprintf(cfp, " NULL,");
00373 fprintf(cfp, " FIELD_OFFSET(%s)},\n", f->name);
00374 }
00375 fprintf(cfp, "\t{NULL, 0, STRING, 0, NULL, 0}\n};\n");
00376
00377 return (0);
00378 }
00379
00380 char *
00381 type_to_string(type)
00382 datatype type;
00383 {
00384 switch (type) {
00385 case NOTSET:
00386 return ("NOTSET");
00387 case DOUBLE:
00388 return ("DOUBLE");
00389 case STRING:
00390 return ("STRING");
00391 case ULONG:
00392 return ("ULONG");
00393 }
00394
00395 abort();
00396
00397 }
00398
00399 int
00400 usage()
00401 {
00402 (void)fprintf(stderr,
00403 "usage: %s [-v] [-c source-file] [-f input] [-h header-file]\n",
00404 progname);
00405 exit(1);
00406 }