PageRenderTime 70ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/pxview/src/main.c

https://bitbucket.org/jsquyres/pxtools
C | 2936 lines | 2828 code | 39 blank | 69 comment | 88 complexity | 42fd63b17692abd44ed84d7f0a964154 MD5 | raw file
Possible License(s): GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <time.h>
  5. #include <stdarg.h>
  6. #include <getopt.h>
  7. #include <sys/types.h>
  8. #include <regex.h>
  9. #include <libgen.h>
  10. #include "config.h"
  11. #ifdef HAVE_LIBINTL_H
  12. #include <libintl.h>
  13. #endif
  14. #ifdef HAVE_GSF
  15. #include <paradox-gsf.h>
  16. #else
  17. #include <paradox.h>
  18. #endif
  19. #ifdef MEMORY_DEBUGGING
  20. #include <paradox-mp.h>
  21. #endif
  22. #ifdef HAVE_SQLITE
  23. #include <sqlite.h>
  24. #endif
  25. #ifdef ENABLE_NLS
  26. #define _(String) gettext(String)
  27. #else
  28. #define _(String) String
  29. #endif
  30. /* strrep() {{{
  31. * Replace a char c1 with c2
  32. */
  33. void strrep(char *str, char c1, char c2) {
  34. char *ptr = str;
  35. while(*ptr != '\0') {
  36. if(*ptr == c1)
  37. *ptr = c2;
  38. ptr++;
  39. }
  40. }
  41. /* }}} */
  42. /* str_replace() {{{
  43. * Replace th first occurence of a substring s1 in str with the string s2
  44. * Returns the new string
  45. */
  46. char * str_replace(char *str, char *s1, char *s2) {
  47. char *newstring, *newptr;
  48. char *firstoccurence;
  49. int index; /* Position of first occurence of s1 */
  50. int rep_len, find_len; /* Length of s2 and s1 */
  51. if(NULL == str || NULL == s1)
  52. return(NULL);
  53. if(NULL == s2)
  54. rep_len = 0;
  55. else
  56. rep_len = strlen(s2);
  57. find_len = strlen(s1);
  58. newstring = malloc(strlen(str) + rep_len - find_len + 1);
  59. firstoccurence = strstr(str, s1);
  60. if(NULL == firstoccurence) {
  61. memcpy(newstring, str, strlen(str)+1);
  62. return(newstring);
  63. }
  64. newptr = newstring;
  65. index = firstoccurence-str;
  66. memcpy(newptr, str, index); /* Copy string up to start of s1 */
  67. newptr += index;
  68. memcpy(newptr, s2, rep_len); /* Copy replacement string */
  69. newptr += rep_len;
  70. memcpy(newptr, firstoccurence+find_len, rep_len + 1); /* Copy rest of string */
  71. return(newstring);
  72. }
  73. /* }}} */
  74. struct str_buffer {
  75. char *buffer;
  76. size_t cur;
  77. size_t size;
  78. };
  79. /* str_buffer_new() {{{
  80. * Create a new string buffer with the given initial size
  81. */
  82. struct str_buffer *str_buffer_new(pxdoc_t *pxdoc, size_t size) {
  83. struct str_buffer *sb;
  84. if(NULL == (sb = pxdoc->malloc(pxdoc, sizeof(struct str_buffer), _("Allocate memory for string buffer"))))
  85. return NULL;
  86. if(size > 0) {
  87. if(NULL == (sb->buffer = pxdoc->malloc(pxdoc, size, _("Allocate memory for string buffer")))) {
  88. pxdoc->free(pxdoc, sb);
  89. return NULL;
  90. }
  91. sb->buffer[0] = '\0';
  92. } else {
  93. sb->buffer = NULL;
  94. }
  95. sb->size = size;
  96. sb->cur = 0;
  97. return(sb);
  98. }
  99. /* }}} */
  100. /* str_buffer_delete() {{{
  101. * Frees the memory occupied by the string buffer
  102. */
  103. void str_buffer_delete(pxdoc_t *pxdoc, struct str_buffer *sb) {
  104. if(sb->buffer)
  105. pxdoc->free(pxdoc, sb->buffer);
  106. pxdoc->free(pxdoc, sb);
  107. }
  108. /* }}} */
  109. #define MSG_BUFSIZE 256
  110. /* str_buffer_print() {{{
  111. * print a string at the end of a buffer
  112. */
  113. void str_buffer_print(pxdoc_t *pxdoc, struct str_buffer *sb, const char *fmt, ...) {
  114. char msg[MSG_BUFSIZE];
  115. va_list ap;
  116. int written;
  117. va_start(ap, fmt);
  118. written = vsnprintf(msg, MSG_BUFSIZE, fmt, ap);
  119. if(written >= MSG_BUFSIZE) {
  120. fprintf(stderr, "Fatal Error: Format string is to short\n");
  121. exit(1);
  122. }
  123. /* Enlarge memory for buffer
  124. * Enlarging it MSG_BUFSIZE ensure that the space is in any case
  125. * sufficient to add the new string.
  126. */
  127. if((sb->cur + written + 1) > sb->size) {
  128. sb->buffer = pxdoc->realloc(pxdoc, sb->buffer, sb->size+MSG_BUFSIZE, _("Get more memory for string buffer."));
  129. sb->size += MSG_BUFSIZE;
  130. }
  131. strcpy(&(sb->buffer[sb->cur]), msg);
  132. sb->cur += written;
  133. va_end(ap);
  134. }
  135. /* }}} */
  136. #undef MSG_BUFSIZE
  137. /* str_buffer_get() {{{
  138. * Returns a pointer to current buffer
  139. */
  140. const char *str_buffer_get(pxdoc_t *pxdoc, struct str_buffer *sb) {
  141. return(sb->buffer);
  142. }
  143. /* }}} */
  144. /* str_buffer_len() {{{
  145. * Returns len of string buffer
  146. */
  147. size_t str_buffer_len(pxdoc_t *pxdoc, struct str_buffer *sb) {
  148. return(sb->cur);
  149. }
  150. /* }}} */
  151. /* str_buffer_clear() {{{
  152. * Clears the string buffer but will not free the memory
  153. */
  154. void str_buffer_clear(pxdoc_t *pxdoc, struct str_buffer *sb) {
  155. sb->cur = 0;
  156. sb->buffer[0] = '\0';
  157. }
  158. /* }}} */
  159. /* str_buffer_printmask() {{{
  160. * Prints str to buffer and masks each occurence of c1 with c2.
  161. * Returns the number of written chars.
  162. */
  163. int str_buffer_printmask(pxdoc_t *pxdoc, struct str_buffer *sb, char *str, char c1, char c2 ) {
  164. char *ptr, *dst;
  165. int len = 0;
  166. int c = 0;
  167. /* Count occurences of c1 */
  168. ptr = str;
  169. while(*ptr != '\0') {
  170. if(*ptr++ == c1)
  171. c++;
  172. }
  173. c += sb->cur + strlen(str) + 1;
  174. if(c > sb->size) {
  175. sb->buffer = pxdoc->realloc(pxdoc, sb->buffer, c, _("Get more memory for string buffer."));
  176. sb->size += c;
  177. }
  178. dst = &(sb->buffer[sb->cur]);
  179. ptr = str;
  180. while(*ptr != '\0') {
  181. if(*ptr == c1) {
  182. *dst++ = c2;
  183. len ++;
  184. }
  185. *dst++ = *ptr++;
  186. len++;
  187. }
  188. *dst = '\0';
  189. sb->cur += len;
  190. return(len);
  191. }
  192. /* }}} */
  193. /* printmask() {{{
  194. * Prints str and masks each occurence of c1 with c2.
  195. * Returns the number of written chars.
  196. */
  197. int printmask(FILE *outfp, char *str, char c1, char c2 ) {
  198. char *ptr;
  199. int len = 0;
  200. ptr = str;
  201. while(*ptr != '\0') {
  202. if(*ptr == c1) {
  203. fprintf(outfp, "%c", c2);
  204. len ++;
  205. }
  206. fprintf(outfp, "%c", *ptr);
  207. len++;
  208. ptr++;
  209. }
  210. return(len);
  211. }
  212. /* }}} */
  213. struct sql_type_map {
  214. char *pxtype;
  215. char *sqltype;
  216. };
  217. /* set_default_sql_types() {{{
  218. */
  219. void set_default_sql_types(struct sql_type_map *typemap) {
  220. memset(typemap, 0, (pxfBytes+1) * sizeof(struct sql_type_map));
  221. typemap[0].pxtype = NULL;
  222. typemap[0].sqltype = NULL;
  223. typemap[pxfAlpha].pxtype = strdup("alpha");
  224. typemap[pxfAlpha].sqltype = strdup("char(%d)");
  225. typemap[pxfDate].pxtype = strdup("date");
  226. typemap[pxfDate].sqltype = strdup("date");
  227. typemap[pxfShort].pxtype = strdup("short");
  228. typemap[pxfShort].sqltype = strdup("integer");
  229. typemap[pxfLong].pxtype = strdup("long");
  230. typemap[pxfLong].sqltype = strdup("integer");
  231. typemap[pxfCurrency].pxtype = strdup("currency");
  232. typemap[pxfCurrency].sqltype = strdup("decimal(20,2)");
  233. typemap[pxfNumber].pxtype = strdup("number");
  234. typemap[pxfNumber].sqltype = strdup("real");
  235. typemap[pxfLogical].pxtype = strdup("logical");
  236. typemap[pxfLogical].sqltype = strdup("boolean");
  237. typemap[pxfMemoBLOb].pxtype = strdup("memoblob");
  238. typemap[pxfMemoBLOb].sqltype = strdup("text");
  239. typemap[pxfBLOb].pxtype = strdup("blob");
  240. typemap[pxfBLOb].sqltype = strdup("text");
  241. typemap[pxfFmtMemoBLOb].pxtype = strdup("fmtmemoblob");
  242. typemap[pxfFmtMemoBLOb].sqltype = strdup("text");
  243. typemap[pxfOLE].pxtype = strdup("ole");
  244. typemap[pxfOLE].sqltype = strdup("text");
  245. typemap[pxfGraphic].pxtype = strdup("graphic");
  246. typemap[pxfGraphic].sqltype = strdup("text");
  247. typemap[pxfTime].pxtype = strdup("time");
  248. typemap[pxfTime].sqltype = strdup("time");
  249. typemap[pxfTimestamp].pxtype = strdup("timestamp");
  250. typemap[pxfTimestamp].sqltype = strdup("timestamp");
  251. typemap[pxfAutoInc].pxtype = strdup("autoinc");
  252. typemap[pxfAutoInc].sqltype = strdup("integer");
  253. typemap[pxfBCD].pxtype = strdup("bcd");
  254. typemap[pxfBCD].sqltype = strdup("decimal(34,%d)");
  255. typemap[pxfBytes].pxtype = strdup("bytes");
  256. typemap[pxfBytes].sqltype = strdup("text");
  257. }
  258. /* }}} */
  259. /* free_sql_types() {{{
  260. */
  261. void free_sql_types(struct sql_type_map *typemap) {
  262. int i;
  263. for(i=1; i<=pxfBytes; i++) {
  264. if(typemap[i].pxtype)
  265. free(typemap[i].pxtype);
  266. if(typemap[i].sqltype)
  267. free(typemap[i].sqltype);
  268. }
  269. }
  270. /* }}} */
  271. /* set_sql_type() {{{
  272. */
  273. void set_sql_type(struct sql_type_map *typemap, int pxtype, char *sqltype) {
  274. if(pxtype < 1 || pxtype > pxfBytes) {
  275. return;
  276. }
  277. if(sqltype == NULL) {
  278. return;
  279. }
  280. if(typemap[pxtype].sqltype)
  281. free(typemap[pxtype].sqltype);
  282. typemap[pxtype].sqltype = strdup(sqltype);
  283. }
  284. /* }}} */
  285. /* get_sql_type() {{{
  286. */
  287. char *get_sql_type(struct sql_type_map *typemap, int pxtype, int len) {
  288. static char buffer[200];
  289. if(pxtype < 1 || pxtype > pxfBytes) {
  290. return NULL;
  291. }
  292. snprintf(buffer, 200, typemap[pxtype].sqltype, len);
  293. return(buffer);
  294. }
  295. /* }}} */
  296. /* errorhandler() {{{
  297. */
  298. void errorhandler(pxdoc_t *p, int error, const char *str, void *data) {
  299. fprintf(stderr, "PXLib: %s\n", str);
  300. }
  301. /* }}} */
  302. /* usage() {{{
  303. * Output usage information
  304. */
  305. void usage(char *progname) {
  306. int recode;
  307. printf(_("Version: %s %s http://sourceforge.net/projects/pxlib"), progname, PXVIEW_VERSION);
  308. printf("\n");
  309. printf(_("Copyright: Copyright (C) 2003-2005 Uwe Steinmann <uwe@steinmann.cx>"));
  310. printf("\n\n");
  311. if(!strcmp(progname, "px2csv")) {
  312. printf(_("%s reads a paradox file and outputs the file in CSV format."), progname);
  313. } else if(!strcmp(progname, "px2sql")) {
  314. printf(_("%s reads a paradox file and outputs the file in SQL format."), progname);
  315. } else if(!strcmp(progname, "px2html")) {
  316. printf(_("%s reads a paradox file and outputs the file in HTML format."), progname);
  317. } else if(!strcmp(progname, "px2sqlite")) {
  318. printf(_("%s reads a paradox file and writes the output into a sqlite database."), progname);
  319. } else {
  320. printf(_("%s reads a paradox file and outputs information about the file\nor dumps the content in CSV, HTML, SQL or sqlite format."), progname);
  321. }
  322. printf("\n\n");
  323. printf(_("Usage: %s [OPTIONS] FILE"), progname);
  324. printf("\n\n");
  325. printf(_("General options:"));
  326. printf("\n");
  327. printf(_(" -h, --help this usage information."));
  328. printf("\n");
  329. printf(_(" --version show version information."));
  330. printf("\n");
  331. printf(_(" -v, --verbose be more verbose."));
  332. printf("\n");
  333. #ifdef HAVE_GSF
  334. if(PX_has_gsf_support()) {
  335. printf(_(" --use-gsf use gsf library to read input file."));
  336. printf("\n");
  337. }
  338. #endif
  339. printf("\n");
  340. printf(_("Options to select output mode:"));
  341. printf("\n");
  342. if(!strcmp(progname, "pxview")) {
  343. printf(_(" -i, --info show information about file."));
  344. printf("\n");
  345. printf(_(" -c, --csv dump records in CSV format."));
  346. printf("\n");
  347. printf(_(" -s, --sql dump records in SQL format."));
  348. printf("\n");
  349. #ifdef HAVE_SQLITE
  350. printf(_(" -q, --sqlite dump records into sqlite database."));
  351. printf("\n");
  352. #endif
  353. printf(_(" -x, --html dump records in HTML format."));
  354. printf("\n");
  355. printf(_(" -t, --schema output schema of database."));
  356. printf("\n");
  357. printf(_(" --mode=MODE set output mode (info, csv, sql, sqlite, html or schema)."));
  358. printf("\n");
  359. }
  360. printf(_(" -o, --output-file=FILE output data into file instead of stdout."));
  361. printf("\n");
  362. printf(_(" --output-deleted output also records which were deleted."));
  363. printf("\n");
  364. printf(_(" --fields=REGEX extended regular expression to select fields."));
  365. printf("\n");
  366. printf(_(" -r, --recode=ENCODING sets the target encoding."));
  367. printf("\n");
  368. printf(_(" -n, --primary-index-file=FILE read primary index from file."));
  369. printf("\n");
  370. printf(_(" --timestamp-format=FORMAT Set format for timestamps (default Y-m-d H:i:s)."));
  371. printf("\n");
  372. printf(_(" --time-format=FORMAT Set format for times (default H:i:s)."));
  373. printf("\n");
  374. printf(_(" --date-format=FORMAT Set format for dates (default Y-m-d)."));
  375. printf("\n");
  376. printf("\n");
  377. printf(_("Options to handle blob files:"));
  378. printf("\n");
  379. printf(_(" -b, --blobfile=FILE read blob data from file."));
  380. printf("\n");
  381. printf(_(" -p, --blobprefix=PREFIX prefix for all created files with blob data."));
  382. printf("\n");
  383. printf(_(" --blobextension=EXT extension for all created files with blob data."));
  384. printf("\n");
  385. if(!strcmp(progname, "px2html") || !strcmp(progname, "pxview")) {
  386. printf("\n");
  387. printf(_("Options for html ouput:"));
  388. printf("\n");
  389. printf(_(" --tablename=NAME overwrite name of database table."));
  390. printf("\n");
  391. printf(_(" --mark-deleted add extra column with 1 for deleted records."));
  392. printf("\n");
  393. }
  394. if(!strcmp(progname, "px2sql") || !strcmp(progname, "pxview") || !strcmp(progname, "px2sqlite")) {
  395. printf("\n");
  396. printf(_("Options for sql and sqlite ouput:"));
  397. printf("\n");
  398. printf(_(" --tablename=NAME overwrite name of database table."));
  399. printf("\n");
  400. printf(_(" --delete-table delete existing sql database table."));
  401. printf("\n");
  402. printf(_(" --skip-schema do not output database table schema."));
  403. printf("\n");
  404. printf(_(" --short-insert use short insert statements."));
  405. printf("\n");
  406. printf(_(" --set-sql-type=SPEC sets the type for a sql field."));
  407. printf("\n");
  408. printf(_(" --empty-string-is-null tread empty string as null."));
  409. printf("\n");
  410. }
  411. if(!strcmp(progname, "px2sql") || !strcmp(progname, "pxview")) {
  412. printf("\n");
  413. printf(_("Options for sql output:"));
  414. printf("\n");
  415. printf(_(" --use-copy use COPY instead of INSERT statement."));
  416. printf("\n");
  417. }
  418. if(!strcmp(progname, "px2csv") || !strcmp(progname, "pxview")) {
  419. printf("\n");
  420. printf(_("Options for csv ouput:"));
  421. printf("\n");
  422. printf(_(" --separator=CHAR character used to separate field values\n (default is ',')."));
  423. printf("\n");
  424. printf(_(" --enclosure=CHAR character used to enclose field values\n (default is '\"')."));
  425. printf("\n");
  426. printf(_(" --without-head Turn off first line with field names."));
  427. printf("\n");
  428. printf(_(" --mark-deleted add extra column with 1 for deleted records."));
  429. printf("\n");
  430. }
  431. printf("\n");
  432. if(!strcmp(progname, "pxview")) {
  433. printf(_("If you do not specify any of the options -i, -c, -s, -x, -q or -t\nthen -i will be used."));
  434. printf("\n\n");
  435. }
  436. if(!strcmp(progname, "pxview")) {
  437. printf(_("The option --fields will only affect csv, html, sql and sqlite output."));
  438. printf("\n\n");
  439. }
  440. printf(_("Supported output formats: "));
  441. printf(_("csv")); printf(" ");
  442. printf(_("html")); printf(" ");
  443. printf(_("sql")); printf(" ");
  444. #ifdef HAVE_SQLITE
  445. printf(_("sqlite")); printf(" ");
  446. #endif
  447. printf("\n\n");
  448. recode = PX_has_recode_support();
  449. switch(recode) {
  450. case 1:
  451. printf(_("libpx uses librecode for recoding."));
  452. break;
  453. case 2:
  454. printf(_("libpx uses iconv for recoding."));
  455. break;
  456. case 0:
  457. printf(_("libpx has no support for recoding."));
  458. break;
  459. }
  460. printf("\n");
  461. if(PX_is_bigendian())
  462. printf(_("libpx has been compiled for big endian architecture."));
  463. else
  464. printf(_("libpx has been compiled for little endian architecture."));
  465. printf("\n");
  466. printf(_("libpx has gsf support: %s"), PX_has_gsf_support() == 1 ? _("Yes") : _("No"));
  467. printf("\n");
  468. printf(_("libpx has version: %d.%d.%d"), PX_get_majorversion(), PX_get_minorversion(), PX_get_subminorversion());
  469. printf("\n\n");
  470. }
  471. /* }}} */
  472. /* main() {{{
  473. */
  474. int main(int argc, char *argv[]) {
  475. pxhead_t *pxh;
  476. pxfield_t *pxf;
  477. pxdoc_t *pxdoc = NULL;
  478. pxdoc_t *pindexdoc = NULL;
  479. pxblob_t *pxblob = NULL;
  480. char *progname = NULL;
  481. char *selectedfields = NULL;
  482. char *data;
  483. float frecordsize, ffiletype, fprimarykeyfields, ftheonumrecords;
  484. int recordsize, filetype, primarykeyfields, theonumrecords;
  485. int i, j, c; // general counters
  486. int first; // used to indicate if output has started or not
  487. int outputcsv = 0;
  488. int outputhtml = 0;
  489. int outputinfo = 0;
  490. int outputsql = 0;
  491. int outputsqlite = 0;
  492. int outputschema = 0;
  493. int outputdebug = 0;
  494. int deletetable = 0;
  495. int skipschema = 0;
  496. int shortinsert = 0;
  497. int outputdeleted = 0;
  498. int markdeleted = 0;
  499. int usecopy = 0;
  500. int usegsf = 0;
  501. int verbose = 0;
  502. int withouthead = 0;
  503. int emptystringisnull = 0;
  504. char delimiter = ',';
  505. char enclosure = '"';
  506. char *inputfile = NULL;
  507. char *outputfile = NULL;
  508. char *blobfile = NULL;
  509. char *pindexfile = NULL;
  510. char *blobprefix = NULL;
  511. char *blobextension = NULL;
  512. char *fieldregex = NULL;
  513. char *tablename = NULL;
  514. char *targetencoding = NULL;
  515. struct sql_type_map *typemap;
  516. char *timestamp_format = NULL;
  517. char *time_format = NULL;
  518. char *date_format = NULL;
  519. FILE *outfp = NULL;
  520. /* allocate 1 more struct because the first one is not used */
  521. typemap = malloc((pxfBytes+1) * sizeof(struct sql_type_map));
  522. set_default_sql_types(typemap);
  523. #ifdef MEMORY_DEBUGGING
  524. PX_mp_init();
  525. #endif
  526. #ifdef ENABLE_NLS
  527. setlocale (LC_ALL, "");
  528. setlocale (LC_NUMERIC, "C");
  529. bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
  530. textdomain (GETTEXT_PACKAGE);
  531. #endif
  532. /* Handle program options {{{
  533. */
  534. progname = basename(strdup(argv[0]));
  535. while(1) {
  536. int this_option_optind = optind ? optind : 1;
  537. int option_index = 0;
  538. static struct option long_options[] = {
  539. {"info", 0, 0, 'i'},
  540. {"csv", 0, 0, 'c'},
  541. {"sql", 0, 0, 's'},
  542. {"html", 0, 0, 'x'},
  543. {"schema", 0, 0, 't'},
  544. {"sqlite", 0, 0, 'q'},
  545. {"verbose", 0, 0, 'v'},
  546. {"blobfile", 1, 0, 'b'},
  547. {"blobprefix", 1, 0, 'p'},
  548. {"blobextension", 1, 0, 16},
  549. {"recode", 1, 0, 'r'},
  550. {"output-file", 1, 0, 'o'},
  551. {"help", 0, 0, 'h'},
  552. {"separator", 1, 0, 0},
  553. {"enclosure", 1, 0, 1},
  554. {"fields", 1, 0, 'f'},
  555. {"tablename", 1, 0, 3},
  556. {"mode", 1, 0, 4},
  557. {"deletetable", 0, 0, 5},
  558. {"delete-table", 0, 0, 5},
  559. {"outputdeleted", 0, 0, 6},
  560. {"output-deleted", 0, 0, 6},
  561. {"markdeleted", 0, 0, 7},
  562. {"mark-deleted", 0, 0, 7},
  563. {"use-gsf", 0, 0, 8},
  564. {"use-copy", 0, 0, 9},
  565. {"without-head", 0, 0, 10},
  566. {"skip-schema", 0, 0, 12},
  567. {"short-insert", 0, 0, 13},
  568. {"set-sql-type", 1, 0, 14},
  569. {"empty-string-is-null", 0, 0, 15},
  570. {"primary-index-file", 1, 0, 'n'},
  571. {"version", 0, 0, 11},
  572. {"timestamp-format", 1, 0, 17},
  573. {"time-format", 1, 0, 18},
  574. {"date-format", 1, 0, 19},
  575. {0, 0, 0, 0}
  576. };
  577. c = getopt_long (argc, argv, "icsxqvtf:b:r:p:o:n:h",
  578. long_options, &option_index);
  579. if (c == -1)
  580. break;
  581. switch (c) {
  582. case 0:
  583. delimiter = optarg[0];
  584. break;
  585. case 1:
  586. enclosure = optarg[0];
  587. break;
  588. case 3:
  589. tablename = strdup(optarg);
  590. break;
  591. case 4:
  592. if(!strcmp(optarg, "info")) {
  593. outputinfo = 1;
  594. } else if(!strcmp(optarg, "csv")) {
  595. outputcsv = 1;
  596. } else if(!strcmp(optarg, "sql")) {
  597. outputsql = 1;
  598. } else if(!strcmp(optarg, "sqlite")) {
  599. #ifdef HAVE_SQLITE
  600. outputsqlite = 1;
  601. #else
  602. fprintf(stderr, _("No sqlite support available."));
  603. fprintf(stderr, "\n");
  604. exit(1);
  605. #endif
  606. } else if(!strcmp(optarg, "html")) {
  607. outputhtml = 1;
  608. } else if(!strcmp(optarg, "schema")) {
  609. outputschema = 1;
  610. } else if(!strcmp(optarg, "debug")) {
  611. outputdebug = 1;
  612. }
  613. break;
  614. case 5:
  615. deletetable = 1;
  616. break;
  617. case 6:
  618. outputdeleted = 1;
  619. break;
  620. case 7:
  621. markdeleted = 1;
  622. break;
  623. case 8:
  624. usegsf = 1;
  625. break;
  626. case 9:
  627. usecopy = 1;
  628. break;
  629. case 10:
  630. withouthead = 1;
  631. break;
  632. case 11:
  633. fprintf(stdout, "%s\n", PXVIEW_VERSION);
  634. if(typemap) {
  635. free_sql_types(typemap);
  636. free(typemap);
  637. }
  638. exit(0);
  639. break;
  640. case 12:
  641. skipschema = 1;
  642. break;
  643. case 13:
  644. shortinsert = 1;
  645. break;
  646. case 14: {
  647. char *delimptr;
  648. int typelen;
  649. int index = 0;
  650. delimptr = strchr(optarg, ':');
  651. if(NULL != delimptr) {
  652. typelen = delimptr-optarg;
  653. for(i=1; i<=pxfBytes; i++) {
  654. if(typemap[i].pxtype) {
  655. if(!strncmp(typemap[i].pxtype, optarg, typelen) &&
  656. (strlen(typemap[i].pxtype) == typelen)) {
  657. index = i;
  658. }
  659. }
  660. }
  661. if(index) {
  662. typemap[index].sqltype = strdup(delimptr+1);
  663. } else {
  664. fprintf(stderr, _("Unknown paradox type specified with --set-sql-type."));
  665. fprintf(stderr, "\n");
  666. }
  667. } else {
  668. fprintf(stderr, _("Argument of --set-sql-type does not contain the delimiting character ':'."));
  669. fprintf(stderr, "\n");
  670. exit(1);
  671. }
  672. break;
  673. }
  674. case 15:
  675. emptystringisnull = 1;
  676. break;
  677. case 'h':
  678. usage(progname);
  679. printf(_("Predefined paradox to sql field type mapping:"));
  680. printf("\n");
  681. for(i=1; i<pxfBytes; i++) {
  682. if(typemap[i].sqltype)
  683. printf("%s:%s\n", typemap[i].pxtype, typemap[i].sqltype);
  684. }
  685. printf("\n");
  686. if(typemap) {
  687. free_sql_types(typemap);
  688. free(typemap);
  689. }
  690. exit(0);
  691. break;
  692. case 'v':
  693. verbose = 1;
  694. break;
  695. case 't':
  696. outputschema = 1;
  697. break;
  698. case 'b':
  699. blobfile = strdup(optarg);
  700. break;
  701. case 'p':
  702. blobprefix = strdup(optarg);
  703. break;
  704. case 16:
  705. blobextension = strdup(optarg);
  706. break;
  707. case 17:
  708. timestamp_format = strdup(optarg);
  709. break;
  710. case 18:
  711. time_format = strdup(optarg);
  712. break;
  713. case 19:
  714. date_format = strdup(optarg);
  715. break;
  716. case 'r':
  717. targetencoding = strdup(optarg);
  718. break;
  719. case 'f':
  720. fieldregex = strdup(optarg);
  721. break;
  722. case 'o':
  723. outputfile = strdup(optarg);
  724. break;
  725. case 'i':
  726. outputinfo = 1;
  727. break;
  728. case 'c':
  729. outputcsv = 1;
  730. break;
  731. case 's':
  732. outputsql = 1;
  733. break;
  734. case 'x':
  735. outputhtml = 1;
  736. break;
  737. case 'q':
  738. #ifdef HAVE_SQLITE
  739. outputsqlite = 1;
  740. #else
  741. printf(_("No sqlite support available."));
  742. exit(1);
  743. #endif
  744. break;
  745. case 'n':
  746. pindexfile = strdup(optarg);
  747. break;
  748. }
  749. }
  750. if (optind < argc) {
  751. inputfile = strdup(argv[optind]);
  752. }
  753. if(!inputfile) {
  754. fprintf(stderr, _("You must at least specify an input file."));
  755. fprintf(stderr, "\n");
  756. fprintf(stderr, "\n");
  757. usage(progname);
  758. if(typemap) {
  759. free_sql_types(typemap);
  760. free(typemap);
  761. }
  762. exit(1);
  763. }
  764. /* }}} */
  765. /* Handle different program names {{{
  766. */
  767. if(!strcmp(progname, "px2sql")) {
  768. outputinfo = 0;
  769. outputcsv = 0;
  770. outputschema = 0;
  771. outputsql = 1;
  772. outputsqlite = 0;
  773. outputhtml = 0;
  774. } else if(!strcmp(progname, "px2csv")) {
  775. outputinfo = 0;
  776. outputcsv = 1;
  777. outputschema = 0;
  778. outputsql = 0;
  779. outputsqlite = 0;
  780. outputhtml = 0;
  781. } else if(!strcmp(progname, "px2html")) {
  782. outputinfo = 0;
  783. outputcsv = 0;
  784. outputschema = 0;
  785. outputsql = 0;
  786. outputsqlite = 0;
  787. outputhtml = 1;
  788. } else if(!strcmp(progname, "px2sqlite")) {
  789. outputinfo = 0;
  790. outputcsv = 0;
  791. outputschema = 0;
  792. outputsql = 0;
  793. outputsqlite = 1;
  794. outputhtml = 0;
  795. }
  796. /* }}} */
  797. /* if none the output modes is selected then display info */
  798. if(outputinfo == 0 && outputcsv == 0 && outputschema == 0 && outputsql == 0 && outputdebug == 0 && outputhtml == 0 && outputsqlite == 0)
  799. outputinfo = 1;
  800. /* Set default values for timestamp, time, date format if it was
  801. * not set by the program options
  802. */
  803. if(NULL == timestamp_format)
  804. timestamp_format = "Y-m-d H:i:s";
  805. if(NULL == time_format)
  806. time_format = "H:i:s";
  807. if(NULL == date_format)
  808. date_format = "Y-m-d";
  809. /* Create output file {{{
  810. */
  811. if((outputfile == NULL) || !strcmp(outputfile, "-")) {
  812. if(outputsqlite) {
  813. fprintf(stderr, _("sqlite database cannot be written to stdout."));
  814. fprintf(stderr, "\n");
  815. exit(1);
  816. } else {
  817. outfp = stdout;
  818. }
  819. } else {
  820. if(!outputsqlite) {
  821. outfp = fopen(outputfile, "w");
  822. if(outfp == NULL) {
  823. fprintf(stderr, _("Could not open output file."));
  824. fprintf(stderr, "\n");
  825. exit(1);
  826. }
  827. }
  828. }
  829. /* }}} */
  830. /* Open input file {{{
  831. */
  832. #ifdef MEMORY_DEBUGGING
  833. if(NULL == (pxdoc = PX_new2(errorhandler, PX_mp_malloc, PX_mp_realloc, PX_mp_free))) {
  834. #else
  835. if(NULL == (pxdoc = PX_new2(errorhandler, NULL, NULL, NULL))) {
  836. #endif
  837. fprintf(stderr, _("Could not create new paradox instance."));
  838. fprintf(stderr, "\n");
  839. exit(1);
  840. }
  841. #ifdef HAVE_GSF
  842. if(PX_has_gsf_support() && usegsf) {
  843. GsfInput *input = NULL;
  844. GsfInputStdio *in_stdio;
  845. GsfInputMemory *in_mem;
  846. GError *gerr = NULL;
  847. fprintf(stderr, "Inputfile: %s\n", inputfile);
  848. gsf_init ();
  849. in_mem = gsf_input_mmap_new (inputfile, NULL);
  850. if (in_mem == NULL) {
  851. in_stdio = gsf_input_stdio_new(inputfile, &gerr);
  852. if(in_stdio != NULL)
  853. input = GSF_INPUT (in_stdio);
  854. else {
  855. fprintf(stderr, _("Could not open gsf input file."));
  856. fprintf(stderr, "\n");
  857. g_object_unref (G_OBJECT (input));
  858. exit(1);
  859. }
  860. } else {
  861. input = GSF_INPUT (in_mem);
  862. }
  863. if(0 > PX_open_gsf(pxdoc, input)) {
  864. fprintf(stderr, _("Could not open input file."));
  865. fprintf(stderr, "\n");
  866. exit(1);
  867. }
  868. } else {
  869. #endif
  870. if(0 > PX_open_file(pxdoc, inputfile)) {
  871. fprintf(stderr, _("Could not open input file."));
  872. fprintf(stderr, "\n");
  873. exit(1);
  874. }
  875. #ifdef HAVE_GSF
  876. }
  877. #endif
  878. /* Below this point inputfile isn't used anymore. */
  879. free(inputfile);
  880. /* }}} */
  881. /* Open primary index file {{{
  882. */
  883. if(pindexfile) {
  884. pindexdoc = PX_new2(errorhandler, NULL, NULL, NULL);
  885. if(0 > PX_open_file(pindexdoc, pindexfile)) {
  886. fprintf(stderr, _("Could not open primary index file."));
  887. fprintf(stderr, "\n");
  888. exit(1);
  889. }
  890. if(0 > PX_read_primary_index(pindexdoc)) {
  891. fprintf(stderr, _("Could not read primary index file."));
  892. fprintf(stderr, "\n");
  893. exit(1);
  894. }
  895. if(0 > PX_add_primary_index(pxdoc, pindexdoc)) {
  896. fprintf(stderr, _("Could not add primary index file."));
  897. fprintf(stderr, "\n");
  898. exit(1);
  899. }
  900. }
  901. /* }}} */
  902. /* Set various variables with values from the header. */
  903. pxh = pxdoc->px_head;
  904. PX_get_value(pxdoc, "recordsize", &frecordsize);
  905. recordsize = (int) frecordsize;
  906. PX_get_value(pxdoc, "filetype", &ffiletype);
  907. filetype = (int) ffiletype;
  908. PX_get_value(pxdoc, "primarykeyfields", &fprimarykeyfields);
  909. primarykeyfields = (int) fprimarykeyfields;
  910. PX_get_value(pxdoc, "theonumrecords", &ftheonumrecords);
  911. theonumrecords = (int) ftheonumrecords;
  912. if(targetencoding != NULL)
  913. PX_set_targetencoding(pxdoc, targetencoding);
  914. /* Set tablename to the one in the header if it wasn't set before */
  915. /* FIXME: The memory for tablename must be freed later on, which isn't done yet. */
  916. if(tablename == NULL) {
  917. PX_get_parameter(pxdoc, "tablename", &tablename);
  918. tablename = strdup(tablename);
  919. // tablename = pxh->px_tablename;
  920. }
  921. strrep(tablename, '.', '_');
  922. strrep(tablename, ' ', '_');
  923. /* Open the file containing the blobs if one is given {{{
  924. */
  925. if(blobfile) {
  926. pxblob = PX_new_blob(pxdoc);
  927. if(0 > PX_open_blob_file(pxblob, blobfile)) {
  928. fprintf(stderr, _("Could not open blob file."));
  929. fprintf(stderr, "\n");
  930. PX_close(pxdoc);
  931. exit(1);
  932. }
  933. if(!blobprefix)
  934. blobprefix = tablename;
  935. if(!blobextension)
  936. blobextension = "blob";
  937. }
  938. /* }}} */
  939. /* Output info {{{
  940. */
  941. if(outputinfo) {
  942. int reclen;
  943. struct tm time_tm;
  944. char *str;
  945. float number;
  946. fprintf(outfp, _("File Version: %1.1f\n"), (float) pxh->px_fileversion/10.0);
  947. fprintf(outfp, _("File Type: "));
  948. switch(filetype) {
  949. case pxfFileTypIndexDB:
  950. fprintf(outfp, _("indexed .DB data file"));
  951. break;
  952. case pxfFileTypPrimIndex:
  953. fprintf(outfp, _("primary index .PX file"));
  954. break;
  955. case pxfFileTypNonIndexDB:
  956. fprintf(outfp, _("non-indexed .DB data file"));
  957. break;
  958. case pxfFileTypNonIncSecIndex:
  959. fprintf(outfp, _("non-incrementing secondary index .Xnn file"));
  960. break;
  961. case pxfFileTypSecIndex:
  962. fprintf(outfp, _("secondary index .Ynn file (inc or non-inc)"));
  963. break;
  964. case pxfFileTypIncSecIndex:
  965. fprintf(outfp, _("incrementing secondary index .Xnn file"));
  966. break;
  967. case pxfFileTypNonIncSecIndexG:
  968. fprintf(outfp, _("non-incrementing secondary index .XGn file"));
  969. break;
  970. case pxfFileTypSecIndexG:
  971. fprintf(outfp, _("secondary index .YGn file (inc or non inc)"));
  972. break;
  973. case pxfFileTypIncSecIndexG:
  974. fprintf(outfp, _("incrementing secondary index .XGn file"));
  975. break;
  976. }
  977. fprintf(outfp, "\n");
  978. PX_get_parameter(pxdoc, "tablename", &str);
  979. fprintf(outfp, _("Tablename: %s\n"), str);
  980. fprintf(outfp, _("Num. of Records: %d\n"), PX_get_num_records(pxdoc));
  981. fprintf(outfp, _("Theor. Num. of Rec.: %d\n"), theonumrecords);
  982. fprintf(outfp, _("Num. of Fields: %d\n"), PX_get_num_fields(pxdoc));
  983. PX_get_value(pxdoc, "headersize", &number);
  984. fprintf(outfp, _("Header size: %d (0x%X)\n"), (int) number, (int) number);
  985. PX_get_value(pxdoc, "maxtablesize", &number);
  986. fprintf(outfp, _("Max. Table size: %d (0x%X)\n"), (int) number, (int) number*0x400);
  987. PX_get_value(pxdoc, "numblocks", &number);
  988. fprintf(outfp, _("Num. of Data Blocks: %d\n"), (int) number);
  989. PX_get_value(pxdoc, "firstblock", &number);
  990. fprintf(outfp, _("Num. of 1st Data Block: %d\n"), (int) number);
  991. PX_get_value(pxdoc, "lastblock", &number);
  992. fprintf(outfp, _("Num. of last Data Block: %d\n"), (int) number);
  993. if((filetype == pxfFileTypNonIncSecIndex) ||
  994. (filetype == pxfFileTypIncSecIndex)) {
  995. fprintf(outfp, _("Num. of Index Field: %d\n"), pxh->px_indexfieldnumber);
  996. fprintf(outfp, _("Sort order of Field: %d\n"), pxh->px_refintegrity);
  997. }
  998. if((filetype == pxfFileTypIndexDB) ||
  999. (filetype == pxfFileTypNonIndexDB)) {
  1000. fprintf(outfp, _("Num. of prim. Key fields: %d\n"), primarykeyfields);
  1001. fprintf(outfp, _("Next auto inc. value: %d\n"), pxh->px_autoinc);
  1002. }
  1003. if(filetype == pxfFileTypPrimIndex) {
  1004. PX_get_value(pxdoc, "autoinc", &number);
  1005. fprintf(outfp, _("Root index block number: %d\n"), (int) number);
  1006. fprintf(outfp, _("Num. of index levels: %d\n"), pxh->px_numindexlevels);
  1007. }
  1008. fprintf(outfp, _("Write protected: %d\n"), pxh->px_writeprotected);
  1009. PX_get_value(pxdoc, "codepage", &number);
  1010. fprintf(outfp, _("Code Page: %d (0x%X)\n"), (int) number, (int) number);
  1011. fprintf(outfp, _("Encryption: 0x%X\n"), pxh->px_encryption);
  1012. localtime_r((time_t *) &(pxh->px_fileupdatetime), &time_tm);
  1013. fprintf(outfp, _("Update time: %d.%d.%d %d:%02d:%02d (%d)\n"), time_tm.tm_mday, time_tm.tm_mon+1, time_tm.tm_year+1900, time_tm.tm_hour, time_tm.tm_min, time_tm.tm_sec, pxh->px_fileupdatetime);
  1014. if(verbose) {
  1015. fprintf(outfp, _("Record size: %d (0x%X)\n"), recordsize, recordsize);
  1016. fprintf(outfp, _("Sort order: %d (0x%X)\n"), pxh->px_sortorder, pxh->px_sortorder);
  1017. fprintf(outfp, _("Auto increment: %d (0x%X)\n"), pxh->px_autoinc, pxh->px_autoinc);
  1018. fprintf(outfp, _("Modified Flags 1: %d (0x%X)\n"), pxh->px_modifiedflags1, pxh->px_modifiedflags1);
  1019. fprintf(outfp, _("Modified Flags 2: %d (0x%X)\n"), pxh->px_modifiedflags2, pxh->px_modifiedflags2);
  1020. }
  1021. fprintf(outfp, "\n");
  1022. fprintf(outfp, _("Fieldname | Type\n"));
  1023. fprintf(outfp, "------------------------------------\n");
  1024. pxf = PX_get_fields(pxdoc);
  1025. reclen = 0;
  1026. for(i=0; i<PX_get_num_fields(pxdoc); i++) {
  1027. reclen += pxf->px_flen;
  1028. fprintf(outfp, "%18s | ", pxf->px_fname);
  1029. switch(pxf->px_ftype) {
  1030. case pxfAlpha:
  1031. fprintf(outfp, "char(%d)\n", pxf->px_flen);
  1032. break;
  1033. case pxfDate:
  1034. fprintf(outfp, "date(%d)\n", pxf->px_flen);
  1035. break;
  1036. case pxfShort:
  1037. fprintf(outfp, "int(%d)\n", pxf->px_flen);
  1038. break;
  1039. case pxfLong:
  1040. fprintf(outfp, "int(%d)\n", pxf->px_flen);
  1041. break;
  1042. case pxfCurrency:
  1043. fprintf(outfp, "currency(%d)\n", pxf->px_flen);
  1044. break;
  1045. case pxfNumber:
  1046. fprintf(outfp, "double(%d)\n", pxf->px_flen);
  1047. break;
  1048. case pxfLogical:
  1049. fprintf(outfp, "boolean(%d)\n", pxf->px_flen);
  1050. break;
  1051. case pxfMemoBLOb:
  1052. fprintf(outfp, "memoblob(%d)\n", pxf->px_flen);
  1053. break;
  1054. case pxfBLOb:
  1055. fprintf(outfp, "blob(%d)\n", pxf->px_flen);
  1056. break;
  1057. case pxfFmtMemoBLOb:
  1058. fprintf(outfp, "fmtmemoblob(%d)\n", pxf->px_flen);
  1059. break;
  1060. case pxfOLE:
  1061. fprintf(outfp, "ole(%d)\n", pxf->px_flen);
  1062. break;
  1063. case pxfGraphic:
  1064. fprintf(outfp, "graphic(%d)\n", pxf->px_flen);
  1065. break;
  1066. case pxfTime:
  1067. fprintf(outfp, "time(%d)\n", pxf->px_flen);
  1068. break;
  1069. case pxfTimestamp:
  1070. fprintf(outfp, "timestamp(%d)\n", pxf->px_flen);
  1071. break;
  1072. case pxfAutoInc:
  1073. fprintf(outfp, "autoinc(%d)\n", pxf->px_flen);
  1074. break;
  1075. case pxfBCD:
  1076. fprintf(outfp, "decimal(%d,%d)\n", pxf->px_flen*2, pxf->px_fdc);
  1077. break;
  1078. case pxfBytes:
  1079. fprintf(outfp, "bytes(%d)\n", pxf->px_flen);
  1080. break;
  1081. default:
  1082. fprintf(outfp, "%c(%d)\n", pxf->px_ftype, pxf->px_flen);
  1083. }
  1084. pxf++;
  1085. }
  1086. fprintf(outfp, "------------------------------------\n");
  1087. fprintf(outfp, _(" Record length | %d (0x%X)\n"), reclen, reclen);
  1088. }
  1089. /* }}} */
  1090. /* Output Schema {{{
  1091. */
  1092. if(outputschema) {
  1093. int sumlen = 0;
  1094. if((filetype != pxfFileTypIndexDB) &&
  1095. (filetype != pxfFileTypNonIndexDB)) {
  1096. fprintf(stderr, _("Schema output is only reasonable for DB files."));
  1097. fprintf(stderr, "\n");
  1098. PX_close(pxdoc);
  1099. exit(1);
  1100. }
  1101. fprintf(outfp, "[%s]\n", tablename);
  1102. fprintf(outfp, "Filetype=Delimited\n");
  1103. fprintf(outfp, "Delimiter=%c\n", enclosure);
  1104. fprintf(outfp, "Separator=%c\n", delimiter);
  1105. fprintf(outfp, "CharSet=ANSIINTL\n");
  1106. pxf = PX_get_fields(pxdoc);
  1107. for(i=0; i<PX_get_num_fields(pxdoc); i++) {
  1108. switch(pxf->px_ftype) {
  1109. case pxfAlpha:
  1110. case pxfDate:
  1111. case pxfShort:
  1112. case pxfAutoInc:
  1113. case pxfLong:
  1114. case pxfCurrency:
  1115. case pxfNumber:
  1116. case pxfLogical:
  1117. case pxfTime:
  1118. case pxfTimestamp:
  1119. case pxfBCD:
  1120. case pxfBytes:
  1121. fprintf(outfp, "Field%d=", i+1);
  1122. fprintf(outfp, "%s,", pxf->px_fname);
  1123. break;
  1124. }
  1125. switch(pxf->px_ftype) {
  1126. case pxfAlpha:
  1127. fprintf(outfp, "Char,%d,00,%d\n", pxf->px_flen, sumlen);
  1128. sumlen += pxf->px_flen;
  1129. break;
  1130. case pxfDate:
  1131. fprintf(outfp, "ADate,11,00,%d\n", sumlen);
  1132. sumlen += 11;
  1133. break;
  1134. case pxfShort:
  1135. fprintf(outfp, "Short Integer,11,00,%d\n", sumlen);
  1136. sumlen += 11;
  1137. break;
  1138. case pxfAutoInc:
  1139. case pxfLong:
  1140. fprintf(outfp, "Long Integer,11,00,%d\n", sumlen);
  1141. sumlen += 11;
  1142. break;
  1143. case pxfCurrency:
  1144. fprintf(outfp, "Currency,20,02,%d\n", sumlen);
  1145. sumlen += 20;
  1146. break;
  1147. case pxfNumber:
  1148. fprintf(outfp, "Float,20,02,%d\n", sumlen);
  1149. sumlen += 20;
  1150. break;
  1151. case pxfLogical:
  1152. fprintf(outfp, "Boolean,%d,00,%d\n", pxf->px_flen, sumlen);
  1153. sumlen += pxf->px_flen;
  1154. break;
  1155. case pxfMemoBLOb:
  1156. case pxfBLOb:
  1157. case pxfFmtMemoBLOb:
  1158. case pxfOLE:
  1159. case pxfGraphic:
  1160. break;
  1161. case pxfTime:
  1162. fprintf(outfp, "Time,10,00,%d\n", sumlen);
  1163. sumlen += 10;
  1164. break;
  1165. case pxfTimestamp:
  1166. fprintf(outfp, "Timestamp,30,00,%d\n", sumlen);
  1167. sumlen += 30;
  1168. break;
  1169. case pxfBCD:
  1170. /* Paradox uses only 20 digits though bcd fields can be 34 */
  1171. fprintf(outfp, "Float,20,%d,%d\n", pxf->px_fdc, sumlen);
  1172. sumlen += 20;
  1173. break;
  1174. case pxfBytes:
  1175. fprintf(outfp, "Char,%d,00,%d\n", pxf->px_flen, sumlen);
  1176. sumlen += pxf->px_flen;
  1177. break;
  1178. default:
  1179. break;
  1180. }
  1181. pxf++;
  1182. }
  1183. }
  1184. /* }}} */
  1185. /* Check which fields shall be shown in output {{{
  1186. */
  1187. if(fieldregex) {
  1188. regex_t preg;
  1189. if(regcomp(&preg, fieldregex, REG_NOSUB|REG_EXTENDED|REG_ICASE)) {
  1190. fprintf(stderr, _("Could not compile regular expression to select fields."));
  1191. PX_close(pxdoc);
  1192. exit(1);
  1193. }
  1194. /* allocate memory for selected field array */
  1195. if((selectedfields = (char *) pxdoc->malloc(pxdoc, PX_get_num_fields(pxdoc), _("Could not allocate memory for array of selected fields."))) == NULL) {
  1196. PX_close(pxdoc);
  1197. exit(1);
  1198. }
  1199. memset(selectedfields, '\0', PX_get_num_fields(pxdoc));
  1200. pxf = PX_get_fields(pxdoc);
  1201. for(i=0; i<PX_get_num_fields(pxdoc); i++) {
  1202. if(0 == regexec(&preg, pxf->px_fname, 0, NULL, 0)) {
  1203. selectedfields[i] = 1;
  1204. }
  1205. pxf++;
  1206. }
  1207. }
  1208. /* }}} */
  1209. /* Output data as comma separated values {{{ */
  1210. if(outputcsv) {
  1211. int numrecords, ireccounter = 0;
  1212. int isdeleted, presetdeleted;
  1213. /* Output first line with column names */
  1214. if(!withouthead) {
  1215. first = 0; // set to 1 when first field has been output
  1216. pxf = PX_get_fields(pxdoc);
  1217. for(i=0; i<PX_get_num_fields(pxdoc); i++) {
  1218. if(fieldregex == NULL || selectedfields[i]) {
  1219. if(first == 1)
  1220. fprintf(outfp, "%c", delimiter);
  1221. if(delimiter == ',')
  1222. fprintf(outfp, "%c", enclosure);
  1223. if(strlen(pxf->px_fname))
  1224. fprintf(outfp, "%s", pxf->px_fname);
  1225. else
  1226. fprintf(outfp, "column%d", i+1);
  1227. switch(pxf->px_ftype) {
  1228. case pxfAlpha:
  1229. fprintf(outfp, ",A,%d", pxf->px_flen);
  1230. break;
  1231. case pxfDate:
  1232. fprintf(outfp, ",D,%d", pxf->px_flen);
  1233. break;
  1234. case pxfShort:
  1235. fprintf(outfp, ",S,%d", pxf->px_flen);
  1236. break;
  1237. case pxfAutoInc:
  1238. fprintf(outfp, ",+,%d", pxf->px_flen);
  1239. break;
  1240. case pxfTimestamp:
  1241. fprintf(outfp, ",@,%d", pxf->px_flen);
  1242. break;
  1243. case pxfLong:
  1244. fprintf(outfp, ",I,%d", pxf->px_flen);
  1245. break;
  1246. case pxfTime:
  1247. fprintf(outfp, ",T,%d", pxf->px_flen);
  1248. break;
  1249. case pxfCurrency:
  1250. fprintf(outfp, ",$,%d", pxf->px_flen);
  1251. break;
  1252. case pxfNumber:
  1253. fprintf(outfp, ",N,%d", pxf->px_flen);
  1254. break;
  1255. case pxfLogical:
  1256. fprintf(outfp, ",L,%d", pxf->px_flen);
  1257. break;
  1258. case pxfGraphic:
  1259. fprintf(outfp, ",G,%d", pxf->px_flen);
  1260. break;
  1261. case pxfBLOb:
  1262. fprintf(outfp, ",B,%d", pxf->px_flen);
  1263. break;
  1264. case pxfOLE:
  1265. fprintf(outfp, ",O,%d", pxf->px_flen);
  1266. break;
  1267. case pxfFmtMemoBLOb:
  1268. fprintf(outfp, ",F,%d", pxf->px_flen);
  1269. break;
  1270. case pxfMemoBLOb:
  1271. fprintf(outfp, ",M,%d", pxf->px_flen);
  1272. break;
  1273. case pxfBytes:
  1274. fprintf(outfp, ",Y,%d", pxf->px_flen);
  1275. break;
  1276. case pxfBCD:
  1277. fprintf(outfp, ",#,%d,%d", pxf->px_flen*2, pxf->px_fdc);
  1278. break;
  1279. }
  1280. if(delimiter == ',')
  1281. fprintf(outfp, "%c", enclosure);
  1282. first = 1;
  1283. }
  1284. pxf++;
  1285. }
  1286. if(filetype == pxfFileTypPrimIndex) {
  1287. fprintf(outfp, "%c", delimiter);
  1288. if(delimiter == ',')
  1289. fprintf(outfp, "%c", enclosure);
  1290. fprintf(outfp, "blocknr,I,4");
  1291. if(delimiter == ',')
  1292. fprintf(outfp, "%c", enclosure);
  1293. fprintf(outfp, "%c", delimiter);
  1294. if(delimiter == ',')
  1295. fprintf(outfp, "%c", enclosure);
  1296. fprintf(outfp, "count,I,4");
  1297. if(delimiter == ',')
  1298. fprintf(outfp, "%c", enclosure);
  1299. fprintf(outfp, "%c", delimiter);
  1300. if(delimiter == ',')
  1301. fprintf(outfp, "%c", enclosure);
  1302. fprintf(outfp, "dummy,I,4");
  1303. if(delimiter == ',')
  1304. fprintf(outfp, "%c", enclosure);
  1305. fprintf(outfp, "%c", delimiter);
  1306. if(delimiter == ',')
  1307. fprintf(outfp, "%c", enclosure);
  1308. fprintf(outfp, "thisblocknr,I,4");
  1309. if(delimiter == ',')
  1310. fprintf(outfp, "%c", enclosure);
  1311. }
  1312. if(markdeleted) {
  1313. if(delimiter == ',')
  1314. fprintf(outfp, "%c", enclosure);
  1315. fprintf(outfp, "%cdeleted,L,1", delimiter);
  1316. if(delimiter == ',')
  1317. fprintf(outfp, "%c", enclosure);
  1318. }
  1319. fprintf(outfp, "\n");
  1320. }
  1321. /* Allocate memory for record */
  1322. if((data = (char *) pxdoc->malloc(pxdoc, recordsize, _("Allocate memory for record."))) == NULL) {
  1323. if(selectedfields)
  1324. pxdoc->free(pxdoc, selectedfields);
  1325. PX_close(pxdoc);
  1326. exit(1);
  1327. }
  1328. if(outputdeleted) {
  1329. numrecords = theonumrecords;
  1330. presetdeleted = 1;
  1331. } else {
  1332. numrecords = PX_get_num_records(pxdoc);
  1333. presetdeleted = 0;
  1334. }
  1335. /* Output records */
  1336. for(j=0; j<numrecords; j++) {
  1337. int offset;
  1338. pxdatablockinfo_t pxdbinfo;
  1339. isdeleted = presetdeleted;
  1340. if(NULL != PX_get_record2(pxdoc, j, data, &isdeleted, &pxdbinfo)) {
  1341. pxf = PX_get_fields(pxdoc);
  1342. offset = 0;
  1343. first = 0; // set to 1 when first field has been output
  1344. for(i=0; i<PX_get_num_fields(pxdoc); i++) {
  1345. if(fieldregex == NULL || selectedfields[i]) {
  1346. if(first == 1)
  1347. fprintf(outfp, "%c", delimiter);
  1348. switch(pxf->px_ftype) {
  1349. case pxfAlpha: {
  1350. char *value;
  1351. int ret;
  1352. if(0 < (ret = PX_get_data_alpha(pxdoc, &data[offset], pxf->px_flen, &value))) {
  1353. if(enclosure && (strchr(value, delimiter) || strchr(value, '\n') || strchr(value, '\r'))) {
  1354. fprintf(outfp, "%c", enclosure);
  1355. if(strchr(value, enclosure))
  1356. printmask(outfp, value, enclosure, enclosure);
  1357. else
  1358. fprintf(outfp, "%s", value);
  1359. fprintf(outfp, "%c", enclosure);
  1360. } else {
  1361. if(strchr(value, enclosure)) {
  1362. fprintf(outfp, "%c", enclosure);
  1363. printmask(outfp, value, enclosure, enclosure);
  1364. fprintf(outfp, "%c", enclosure);
  1365. } else
  1366. fprintf(outfp, "%s", value);
  1367. }
  1368. pxdoc->free(pxdoc, value);
  1369. } else if(ret < 0) {
  1370. fprintf(stderr, "Error while reading data of field number %d", i+1);
  1371. fprintf(stderr, "\n");
  1372. }
  1373. first = 1;
  1374. break;
  1375. }
  1376. case pxfDate: {
  1377. long value;
  1378. int year, month, day;
  1379. if(0 < PX_get_data_long(pxdoc, &data[offset], pxf->px_flen, &value)) {
  1380. char *str = PX_timestamp2string(pxdoc, (double) value*1000.0*86400.0, date_format);
  1381. fprintf(outfp, "%s", str);
  1382. pxdoc->free(pxdoc, str);
  1383. }
  1384. first = 1;
  1385. break;
  1386. }
  1387. case pxfShort: {
  1388. short int value;
  1389. if(0 < PX_get_data_short(pxdoc, &data[offset], pxf->px_flen, &value)) {
  1390. fprintf(outfp, "%d", value);
  1391. }
  1392. first = 1;
  1393. break;
  1394. }
  1395. case pxfAutoInc:
  1396. case pxfLong: {
  1397. long value;
  1398. if(0 < PX_get_data_long(pxdoc, &data[offset], pxf->px_flen, &value)) {
  1399. fprintf(outfp, "%ld", value);
  1400. }
  1401. first = 1;
  1402. break;
  1403. }
  1404. case pxfTimestamp: {
  1405. double value;
  1406. if(0 < PX_get_data_double(pxdoc, &data[offset], pxf->px_flen, &value)) {
  1407. char *str = PX_timestamp2string(pxdoc, value, timestamp_format);
  1408. fprintf(outfp, "%s", str);
  1409. pxdoc->free(pxdoc, str);
  1410. }
  1411. first = 1;
  1412. break;
  1413. }
  1414. case pxfTime: {
  1415. long value;
  1416. if(0 < PX_get_data_long(pxdoc, &data[offset], pxf->px_flen, &value)) {
  1417. char *str = PX_timestamp2string(pxdoc, (double) value, time_format);
  1418. fprintf(outfp, "%s", str);
  1419. pxdoc->free(pxdoc, str);
  1420. }
  1421. first = 1;
  1422. break;
  1423. }
  1424. case pxfCurrency:
  1425. case pxfNumber: {
  1426. double value;
  1427. if(0 < PX_get_data_double(pxdoc, &data[offset], pxf->px_flen, &value)) {
  1428. fprintf(outfp, "%lf", value);
  1429. }
  1430. first = 1;
  1431. break;
  1432. }
  1433. case pxfLogical: {
  1434. char value;
  1435. if(0 < PX_get_data_byte(pxdoc, &data[offset], pxf->px_flen, &value)) {
  1436. if(value)
  1437. fprintf(outfp, "1");
  1438. else
  1439. fprintf(outfp, "0");
  1440. }
  1441. first = 1;
  1442. break;
  1443. }
  1444. case pxfGraphic:
  1445. case pxfBLOb:
  1446. case pxfFmtMemoBLOb:
  1447. case pxfMemoBLOb:
  1448. case pxfOLE: {
  1449. char *blobdata;
  1450. char filename[200];
  1451. FILE *fp;
  1452. int mod_nr, size, ret;
  1453. if(pxf->px_ftype == pxfGraphic)
  1454. ret = PX_get_data_graphic(pxdoc, &data[offset], pxf->px_flen, &mod_nr, &size, &blobdata);
  1455. else
  1456. ret = PX_get_data_blob(pxdoc, &data[offset], pxf->px_flen, &mod_nr, &size, &blobdata);
  1457. if(ret > 0) {
  1458. if(blobdata) {
  1459. if(pxf->px_ftype == pxfFmtMemoBLOb || pxf->px_ftype == pxfMemoBLOb) {
  1460. int i;
  1461. if(enclosure && (strchr(blobdata, delimiter) || strchr(blobdata, '\n') || strchr(blobdata, '\r')))
  1462. fprintf(outfp, "%c", enclosure);
  1463. for(i=0; i<size; i++) {
  1464. if(blobdata[i] == enclosure)
  1465. fputc(enclosure, outfp);
  1466. fputc(blobdata[i], outfp);
  1467. }
  1468. if(enclosure && (strchr(blobdata, delimiter) || strchr(blobdata, '\n') || strchr(blobdata, '\r')))
  1469. fprintf(outfp, "%c", enclosure);
  1470. } else {
  1471. sprintf(filename, "%s_%d.%s", blobprefix, mod_nr, blobextension);
  1472. fp = fopen(filename, "w");
  1473. if(fp) {
  1474. fwrite(blobdata, size, 1, fp);
  1475. fclose(fp);
  1476. fprintf(outfp, "%s", filename);
  1477. } else {
  1478. fprintf(stderr, "Couldn't open file '%s' for blob data\n", filename);
  1479. }
  1480. }
  1481. pxdoc->free(pxdoc, blobdata);
  1482. } else {
  1483. fprintf(stderr, "Couldn't get blob data for %d\n", mod_nr);
  1484. }
  1485. }
  1486. first = 1;
  1487. break;
  1488. }
  1489. case pxfBytes:
  1490. hex_dump(outfp, &data[offset], pxf->px_flen);
  1491. first = 1;
  1492. break;
  1493. case pxfBCD: {
  1494. char *value;
  1495. // hex_dump(outfp, &data[offset], pxf->px_flen);
  1496. if(0 < PX_get_data_bcd(pxdoc, &data[offset], pxf->px_fdc, &value)) {
  1497. fprintf(outfp, "%s", value);
  1498. pxdoc->free(pxdoc, value);
  1499. }
  1500. first = 1;
  1501. break;
  1502. }
  1503. default:
  1504. break;
  1505. // fprintf(outfp, "");
  1506. }
  1507. }
  1508. offset += pxf->px_flen;
  1509. pxf++;
  1510. }
  1511. if(filetype == pxfFileTypPrimIndex) {
  1512. short int value;
  1513. if(0 < PX_get_data_short(pxdoc, &data[offset], 2, &value)) {
  1514. fprintf(outfp, "%c", delimiter);
  1515. fprintf(outfp, "%d", value);
  1516. }
  1517. offset += 2;
  1518. if(0 < PX_get_data_short(pxdoc, &data[offset], 2, &value)) {
  1519. fprintf(outfp, "%c", delimiter);
  1520. fprintf(outfp, "%d", value);
  1521. ireccounter += value;
  1522. }
  1523. offset += 2;
  1524. if(0 < PX_get_data_short(pxdoc, &data[offset], 2, &value)) {
  1525. fprintf(outfp, "%c", delimiter);
  1526. fprintf(outfp, "%d", value);
  1527. }
  1528. fprintf(outfp, "%c", delimiter);
  1529. fprintf(outfp, "%d", pxdbinfo.number);
  1530. }
  1531. if(markdeleted) {
  1532. fprintf(outfp, "%c", delimiter);
  1533. fprintf(outfp, "%d", isdeleted);
  1534. }
  1535. fprintf(outfp, "\n");
  1536. } else {
  1537. fprintf(stderr, _("Couldn't get record number %d\n"), j);
  1538. }
  1539. }
  1540. /* Print sum over all records */
  1541. if(filetype == pxfFileTypPrimIndex) {
  1542. for(i=0; i<PX_get_num_fields(pxdoc); i++)
  1543. fprintf(outfp, "%c", delimiter);
  1544. fprintf(outfp, "%c", delimiter);
  1545. fprintf(outfp, "%d", ireccounter);
  1546. fprintf(outfp, "%c", delimiter);
  1547. fprintf(outfp, "\n");
  1548. }
  1549. pxdoc->free(pxdoc, data);
  1550. }
  1551. /* }}} */
  1552. #ifdef HAVE_SQLITE
  1553. /* Output data into sqlite database {{{
  1554. */
  1555. if(outputsqlite) {
  1556. int numrecords;
  1557. sqlite *sql;
  1558. struct str_buffer *sbuf;
  1559. char *sqlerror;
  1560. if((filetype != pxfFileTypIndexDB) &&
  1561. (filetype != pxfFileTypNonIndexDB)) {
  1562. fprintf(stderr, _("SQL output is only reasonable for DB files."));
  1563. fprintf(stderr, "\n");
  1564. PX_close(pxdoc);
  1565. exit(1);
  1566. }
  1567. if((data = (char *) pxdoc->malloc(pxdoc, recordsize, _("Could not allocate memory for record."))) == NULL) {
  1568. if(selectedfields)
  1569. pxdoc->free(pxdoc, selectedfields);
  1570. PX_close(pxdoc);
  1571. exit(1);
  1572. }
  1573. /* Allocate memory for string buffer.
  1574. */
  1575. if((sbuf = str_buffer_new(pxdoc, 20)) == NULL) {
  1576. if(selectedfields)
  1577. pxdoc->free(pxdoc, selectedfields);
  1578. PX_close(pxdoc);
  1579. exit(1);
  1580. }
  1581. if((sql = sqlite_open(outputfile, 0, NULL)) == NULL) {
  1582. if(selectedfields)
  1583. pxdoc->free(pxdoc, selectedfields);
  1584. PX_close(pxdoc);
  1585. exit(1);
  1586. }
  1587. /* check if existing table shall be delete */
  1588. if(deletetable) {
  1589. str_buffer_print(pxdoc, sbuf, "DROP TABLE %s;\n", tablename);
  1590. if(SQLITE_OK != sqlite_exec(sql, str_buffer_get(pxdoc, sbuf), NULL, NULL, &sqlerror)) {
  1591. fprintf(stderr, "%s\n", sqlerror);
  1592. sqlite_close(sql);
  1593. str_buffer_delete(pxdoc, sbuf);
  1594. pxdoc->free(pxdoc, data);
  1595. if(selectedfields)
  1596. pxdoc->free(pxdoc, selectedfields);
  1597. PX_close(pxdoc);
  1598. exit(1);
  1599. }
  1600. }
  1601. /* Output table schema */
  1602. if(!skipschema) {
  1603. str_buffer_clear(pxdoc, sbuf);
  1604. str_buffer_print(pxdoc, sbuf, "CREATE TABLE %s (\n", tablename);
  1605. first = 0; // set to 1 when first field has been output
  1606. pxf = PX_get_fields(pxdoc);
  1607. for(i=0; i<PX_get_num_fields(pxdoc); i++) {
  1608. if(fieldregex == NULL || selectedfields[i]) {
  1609. strrep(pxf->px_fname, ' ', '_');
  1610. if(first == 1)
  1611. str_buffer_print(pxdoc, sbuf, ",\n");
  1612. switch(pxf->px_ftype) {
  1613. case pxfAlpha:
  1614. case pxfDate:
  1615. case pxfShort:
  1616. case pxfLong:
  1617. case pxfAutoInc:
  1618. case pxfCurrency:
  1619. case pxfNumber:
  1620. case pxfLogical:
  1621. case pxfTime:
  1622. case pxfTimestamp:
  1623. case pxfBytes:
  1624. str_buffer_print(pxdoc, sbuf, " %s ", pxf->px_fname);
  1625. str_buffer_print(pxdoc, sbuf, "%s", get_sql_type(typemap, pxf->px_ftype, pxf->px_flen));
  1626. first = 1;
  1627. break;
  1628. case pxfBCD:
  1629. str_buffer_print(pxdoc, sbuf, " %s ", pxf->px_fname);
  1630. str_buffer_print(pxdoc, sbuf, "%s", get_sql_type(typemap, pxf->px_ftype, pxf->px_fdc));
  1631. first = 1;
  1632. break;
  1633. case pxfMemoBLOb:
  1634. case pxfBLOb:
  1635. case pxfFmtMemoBLOb:
  1636. case pxfGraphic:
  1637. case pxfOLE:
  1638. str_buffer_print(pxdoc, sbuf, " %s ", pxf->px_fname);
  1639. str_buffer_print(pxdoc, sbuf, "%s", get_sql_type(typemap, pxf->px_ftype, pxf->px_flen));
  1640. first = 1;
  1641. break;
  1642. }
  1643. // if(i < primarykeyfields)
  1644. // str_buffer_print(pxdoc, sbuf, " unique");
  1645. }
  1646. pxf++;
  1647. }
  1648. if(primarykeyfields) {
  1649. first = 0; // set to 1 when first field has been output
  1650. pxf = PX_get_fields(pxdoc);
  1651. str_buffer_print(pxdoc, sbuf, ",\n unique(");
  1652. for(i=0; i<primarykeyfields; i++) {
  1653. if(fieldregex == NULL || selectedfields[i]) {
  1654. strrep(pxf->px_fname, ' ', '_');
  1655. if(first == 1)
  1656. str_buffer_print(pxdoc, sbuf, ",");
  1657. str_buffer_print(pxdoc, sbuf, "%s", pxf->px_fname);
  1658. first = 1;
  1659. }
  1660. pxf++;
  1661. }
  1662. str_buffer_print(pxdoc, sbuf, ")");
  1663. }
  1664. str_buffer_print(pxdoc, sbuf, ");");
  1665. if(SQLITE_OK != sqlite_exec(sql, str_buffer_get(pxdoc, sbuf), NULL, NULL, &sqlerror)) {
  1666. sqlite_close(sql);
  1667. fprintf(stderr, "%s\n", sqlerror);
  1668. str_buffer_delete(pxdoc, sbuf);
  1669. pxdoc->free(pxdoc, data);
  1670. if(selectedfields)
  1671. pxdoc->free(pxdoc, selectedfields);
  1672. PX_close(pxdoc);
  1673. exit(1);
  1674. }
  1675. /* Create the indexes */
  1676. pxf = PX_get_fields(pxdoc);
  1677. for(i=0; i<primarykeyfields; i++) {
  1678. if(fieldregex == NULL || selectedfields[i]) {
  1679. strrep(pxf->px_fname, ' ', '_');
  1680. str_buffer_clear(pxdoc, sbuf);
  1681. str_buffer_print(pxdoc, sbuf, "CREATE INDEX %s_%s_index on %s (%s);", tablename, pxf->px_fname, tablename, pxf->px_fname);
  1682. if(SQLITE_OK != sqlite_exec(sql, str_buffer_get(pxdoc, sbuf), NULL, NULL, &sqlerror)) {
  1683. sqlite_close(sql);
  1684. fprintf(stderr, "%s\n", sqlerror);
  1685. str_buffer_delete(pxdoc, sbuf);
  1686. pxdoc->free(pxdoc, data);
  1687. if(selectedfields)
  1688. pxdo

Large files files are truncated, but you can click here to view the full file