PageRenderTime 63ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/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
  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. pxdoc->free(pxdoc, selectedfields);
  1689. PX_close(pxdoc);
  1690. exit(1);
  1691. }
  1692. }
  1693. pxf++;
  1694. }
  1695. }
  1696. /* Only output data if we have at least one record */
  1697. if(PX_get_num_records(pxdoc) > 0) {
  1698. if((data = (char *) pxdoc->malloc(pxdoc, recordsize, _("Could not allocate memory for record."))) == NULL) {
  1699. if(selectedfields)
  1700. pxdoc->free(pxdoc, selectedfields);
  1701. PX_close(pxdoc);
  1702. exit(1);
  1703. }
  1704. for(j=0; j<PX_get_num_records(pxdoc); j++) {
  1705. int offset;
  1706. str_buffer_clear(pxdoc, sbuf);
  1707. str_buffer_print(pxdoc, sbuf, "INSERT INTO %s VALUES (", tablename);
  1708. if(PX_get_record(pxdoc, j, data)) {
  1709. first = 0; // set to 1 when first field has been output
  1710. offset = 0;
  1711. pxf = PX_get_fields(pxdoc);
  1712. for(i=0; i<PX_get_num_fields(pxdoc); i++) {
  1713. if(fieldregex == NULL || selectedfields[i]) {
  1714. if(first == 1)
  1715. str_buffer_print(pxdoc, sbuf, ",");
  1716. switch(pxf->px_ftype) {
  1717. case pxfAlpha: {
  1718. char *value;
  1719. int ret;
  1720. if(0 < (ret = PX_get_data_alpha(pxdoc, &data[offset], pxf->px_flen, &value))) {
  1721. if(strchr(value, '\'')) {
  1722. str_buffer_print(pxdoc, sbuf, "'");
  1723. str_buffer_printmask(pxdoc, sbuf, value, '\'', '\'');
  1724. str_buffer_print(pxdoc, sbuf, "'");
  1725. } else
  1726. str_buffer_print(pxdoc, sbuf, "'%s'", value);
  1727. pxdoc->free(pxdoc, value);
  1728. } else if(ret == 0) {
  1729. str_buffer_print(pxdoc, sbuf, "NULL");
  1730. } else {
  1731. fprintf(stderr, "Error while reading data of field number %d", i+1);
  1732. fprintf(stderr, "\n");
  1733. }
  1734. first = 1;
  1735. break;
  1736. }
  1737. case pxfDate: {
  1738. long value;
  1739. if(0 < PX_get_data_long(pxdoc, &data[offset], pxf->px_flen, &value)) {
  1740. char *str = PX_timestamp2string(pxdoc, (double) value*1000.0*86400.0, date_format);
  1741. str_buffer_print(pxdoc, sbuf, "%s", str);
  1742. pxdoc->free(pxdoc, str);
  1743. } else {
  1744. str_buffer_print(pxdoc, sbuf, "NULL");
  1745. }
  1746. first = 1;
  1747. break;
  1748. }
  1749. case pxfShort: {
  1750. short int value;
  1751. if(0 < PX_get_data_short(pxdoc, &data[offset], pxf->px_flen, &value)) {
  1752. str_buffer_print(pxdoc, sbuf, "%d", value);
  1753. } else {
  1754. str_buffer_print(pxdoc, sbuf, "NULL");
  1755. }
  1756. first = 1;
  1757. break;
  1758. }
  1759. case pxfAutoInc:
  1760. case pxfLong: {
  1761. long value;
  1762. if(0 < PX_get_data_long(pxdoc, &data[offset], pxf->px_flen, &value)) {
  1763. str_buffer_print(pxdoc, sbuf, "%ld", value);
  1764. } else {
  1765. str_buffer_print(pxdoc, sbuf, "NULL");
  1766. }
  1767. first = 1;
  1768. break;
  1769. }
  1770. case pxfTimestamp: {
  1771. double value;
  1772. if(0 < PX_get_data_double(pxdoc, &data[offset], pxf->px_flen, &value)) {
  1773. char *str = PX_timestamp2string(pxdoc, value, "Y-m-d H:i:s");
  1774. str_buffer_print(pxdoc, sbuf, "'%s'", str);
  1775. pxdoc->free(pxdoc, str);
  1776. } else {
  1777. str_buffer_print(pxdoc, sbuf, "NULL");
  1778. }
  1779. first = 1;
  1780. break;
  1781. }
  1782. case pxfTime: {
  1783. long value;
  1784. if(0 < PX_get_data_long(pxdoc, &data[offset], pxf->px_flen, &value)) {
  1785. char *str = PX_timestamp2string(pxdoc, (double) value, time_format);
  1786. str_buffer_print(pxdoc, sbuf, "%s", str);
  1787. pxdoc->free(pxdoc, str);
  1788. } else {
  1789. str_buffer_print(pxdoc, sbuf, "NULL");
  1790. }
  1791. first = 1;
  1792. break;
  1793. }
  1794. case pxfCurrency:
  1795. case pxfNumber: {
  1796. double value;
  1797. if(0 < PX_get_data_double(pxdoc, &data[offset], pxf->px_flen, &value)) {
  1798. str_buffer_print(pxdoc, sbuf, "%g", value);
  1799. } else {
  1800. str_buffer_print(pxdoc, sbuf, "NULL");
  1801. }
  1802. first = 1;
  1803. break;
  1804. }
  1805. case pxfLogical: {
  1806. char value;
  1807. if(0 < PX_get_data_byte(pxdoc, &data[offset], pxf->px_flen, &value)) {
  1808. if(value)
  1809. str_buffer_print(pxdoc, sbuf, "1");
  1810. else
  1811. str_buffer_print(pxdoc, sbuf, "0");
  1812. } else {
  1813. str_buffer_print(pxdoc, sbuf, "NULL");
  1814. }
  1815. first = 1;
  1816. break;
  1817. }
  1818. case pxfMemoBLOb:
  1819. case pxfBLOb:
  1820. case pxfFmtMemoBLOb:
  1821. case pxfGraphic:
  1822. case pxfOLE: {
  1823. char *blobdata;
  1824. char filename[200];
  1825. FILE *fp;
  1826. int mod_nr, size, ret;
  1827. if(pxf->px_ftype == pxfGraphic)
  1828. ret = PX_get_data_graphic(pxdoc, &data[offset], pxf->px_flen, &mod_nr, &size, &blobdata);
  1829. else
  1830. ret = PX_get_data_blob(pxdoc, &data[offset], pxf->px_flen, &mod_nr, &size, &blobdata);
  1831. str_buffer_print(pxdoc, sbuf, "'");
  1832. if(ret > 0) {
  1833. if(blobdata) {
  1834. if(pxf->px_ftype == pxfFmtMemoBLOb || pxf->px_ftype == pxfMemoBLOb) {
  1835. int i;
  1836. for(i=0; i<size; i++) {
  1837. if(blobdata[i] == '\'')
  1838. str_buffer_print(pxdoc, sbuf, "'");
  1839. str_buffer_print(pxdoc, sbuf, "%c", blobdata[i]);
  1840. }
  1841. } else {
  1842. sprintf(filename, "%s_%d.%s", blobprefix, mod_nr, blobextension);
  1843. fp = fopen(filename, "w");
  1844. if(fp) {
  1845. fwrite(blobdata, size, 1, fp);
  1846. fclose(fp);
  1847. str_buffer_print(pxdoc, sbuf, "%s", filename);
  1848. } else {
  1849. fprintf(stderr, "Couldn't open file '%s' for blob data\n", filename);
  1850. }
  1851. }
  1852. pxdoc->free(pxdoc, blobdata);
  1853. } else {
  1854. fprintf(stderr, "Couldn't get blob data for %d\n", mod_nr);
  1855. }
  1856. }
  1857. str_buffer_print(pxdoc, sbuf, "'");
  1858. first = 1;
  1859. break;
  1860. }
  1861. case pxfBCD: {
  1862. char *value;
  1863. int ret;
  1864. if(0 < (ret = PX_get_data_bcd(pxdoc, &data[offset], pxf->px_fdc, &value))) {
  1865. str_buffer_print(pxdoc, sbuf, "%s", value);
  1866. pxdoc->free(pxdoc, value);
  1867. } else if(ret == 0) {
  1868. str_buffer_print(pxdoc, sbuf, "NULL");
  1869. } else {
  1870. fprintf(stderr, "Could not read data of bcd field '%s'\n", pxf->px_fname);
  1871. }
  1872. first = 1;
  1873. break;
  1874. }
  1875. default:
  1876. str_buffer_print(pxdoc, sbuf, "NULL");
  1877. }
  1878. }
  1879. offset += pxf->px_flen;
  1880. pxf++;
  1881. }
  1882. str_buffer_print(pxdoc, sbuf, ");\n");
  1883. } else {
  1884. fprintf(stderr, _("Couldn't get record number %d\n"), j);
  1885. }
  1886. if(SQLITE_OK != sqlite_exec(sql, str_buffer_get(pxdoc, sbuf), NULL, NULL, &sqlerror)) {
  1887. sqlite_close(sql);
  1888. fprintf(stderr, "%s\n", sqlerror);
  1889. str_buffer_delete(pxdoc, sbuf);
  1890. pxdoc->free(pxdoc, data);
  1891. if(selectedfields)
  1892. pxdoc->free(pxdoc, selectedfields);
  1893. PX_close(pxdoc);
  1894. exit(1);
  1895. }
  1896. }
  1897. }
  1898. str_buffer_delete(pxdoc, sbuf);
  1899. pxdoc->free(pxdoc, data);
  1900. sqlite_close(sql);
  1901. }
  1902. /* }}} */
  1903. #endif
  1904. /* Output data as HTML Table {{{
  1905. */
  1906. if(outputhtml) {
  1907. int numrecords;
  1908. int isdeleted, presetdeleted;
  1909. /* Allocate memory for record data */
  1910. if((data = (char *) pxdoc->malloc(pxdoc, recordsize, _("Could not allocate memory for record."))) == NULL) {
  1911. if(selectedfields)
  1912. pxdoc->free(pxdoc, selectedfields);
  1913. PX_close(pxdoc);
  1914. exit(1);
  1915. }
  1916. if(outputdeleted) {
  1917. numrecords = theonumrecords;
  1918. presetdeleted = 1;
  1919. } else {
  1920. numrecords = PX_get_num_records(pxdoc);
  1921. presetdeleted = 0;
  1922. }
  1923. fprintf(outfp, "<table>\n");
  1924. fprintf(outfp, " <caption>%s</caption>\n", tablename);
  1925. fprintf(outfp, " <tr>\n");
  1926. /* output field name */
  1927. pxf = PX_get_fields(pxdoc);
  1928. for(i=0; i<PX_get_num_fields(pxdoc); i++) {
  1929. if(fieldregex == NULL || selectedfields[i]) {
  1930. fprintf(outfp, " <th>");
  1931. if(strlen(pxf->px_fname))
  1932. fprintf(outfp, "%s", pxf->px_fname);
  1933. else
  1934. fprintf(outfp, "column%d", i+1);
  1935. switch(pxf->px_ftype) {
  1936. case pxfAlpha:
  1937. fprintf(outfp, ",A,%d", pxf->px_flen);
  1938. break;
  1939. case pxfDate:
  1940. fprintf(outfp, ",D,%d", pxf->px_flen);
  1941. break;
  1942. case pxfShort:
  1943. fprintf(outfp, ",S,%d", pxf->px_flen);
  1944. break;
  1945. case pxfAutoInc:
  1946. fprintf(outfp, ",+,%d", pxf->px_flen);
  1947. break;
  1948. case pxfTimestamp:
  1949. fprintf(outfp, ",@,%d", pxf->px_flen);
  1950. break;
  1951. case pxfLong:
  1952. fprintf(outfp, ",I,%d", pxf->px_flen);
  1953. break;
  1954. case pxfTime:
  1955. fprintf(outfp, ",T,%d", pxf->px_flen);
  1956. break;
  1957. case pxfCurrency:
  1958. fprintf(outfp, ",$,%d", pxf->px_flen);
  1959. break;
  1960. case pxfNumber:
  1961. fprintf(outfp, ",N,%d", pxf->px_flen);
  1962. break;
  1963. case pxfLogical:
  1964. fprintf(outfp, ",L,%d", pxf->px_flen);
  1965. break;
  1966. case pxfGraphic:
  1967. fprintf(outfp, ",G,%d", pxf->px_flen);
  1968. break;
  1969. case pxfBLOb:
  1970. fprintf(outfp, ",B,%d", pxf->px_flen);
  1971. break;
  1972. case pxfOLE:
  1973. fprintf(outfp, ",O,%d", pxf->px_flen);
  1974. break;
  1975. case pxfFmtMemoBLOb:
  1976. fprintf(outfp, ",F,%d", pxf->px_flen);
  1977. break;
  1978. case pxfMemoBLOb:
  1979. fprintf(outfp, ",M,%d", pxf->px_flen);
  1980. break;
  1981. case pxfBytes:
  1982. fprintf(outfp, ",Y,%d", pxf->px_flen);
  1983. break;
  1984. case pxfBCD:
  1985. fprintf(outfp, ",#,%d,%d", pxf->px_flen*2, pxf->px_fdc);
  1986. break;
  1987. }
  1988. fprintf(outfp, "</th>\n");
  1989. }
  1990. pxf++;
  1991. }
  1992. if(markdeleted) {
  1993. fprintf(outfp, " <th>deleted</th>\n");
  1994. }
  1995. fprintf(outfp, " </tr>\n");
  1996. for(j=0; j<numrecords; j++) {
  1997. int offset;
  1998. isdeleted = presetdeleted;
  1999. if(NULL != PX_get_record2(pxdoc, j, data, &isdeleted, NULL)) {
  2000. pxf = PX_get_fields(pxdoc);
  2001. offset = 0;
  2002. fprintf(outfp, " <tr valign=\"top\">\n");
  2003. for(i=0; i<PX_get_num_fields(pxdoc); i++) {
  2004. if(fieldregex == NULL || selectedfields[i]) {
  2005. fprintf(outfp, " <td>");
  2006. switch(pxf->px_ftype) {
  2007. case pxfAlpha: {
  2008. char *value;
  2009. int ret;
  2010. if(0 < (ret = PX_get_data_alpha(pxdoc, &data[offset], pxf->px_flen, &value))) {
  2011. fprintf(outfp, "%s", value);
  2012. pxdoc->free(pxdoc, value);
  2013. } else if(ret < 0) {
  2014. fprintf(stderr, "Error while reading data of field number %d", i+1);
  2015. fprintf(stderr, "\n");
  2016. }
  2017. break;
  2018. }
  2019. case pxfDate: {
  2020. long value;
  2021. if(0 < PX_get_data_long(pxdoc, &data[offset], pxf->px_flen, &value)) {
  2022. char *str = PX_timestamp2string(pxdoc, (double) value*1000.0*86400.0, date_format);
  2023. fprintf(outfp, "%s", str);
  2024. pxdoc->free(pxdoc, str);
  2025. }
  2026. break;
  2027. }
  2028. case pxfShort: {
  2029. short int value;
  2030. if(0 < PX_get_data_short(pxdoc, &data[offset], pxf->px_flen, &value)) {
  2031. fprintf(outfp, "%d", value);
  2032. }
  2033. break;
  2034. }
  2035. case pxfAutoInc:
  2036. case pxfLong: {
  2037. long value;
  2038. if(0 < PX_get_data_long(pxdoc, &data[offset], pxf->px_flen, &value)) {
  2039. fprintf(outfp, "%ld", value);
  2040. }
  2041. break;
  2042. }
  2043. case pxfTime: {
  2044. long value;
  2045. if(0 < PX_get_data_long(pxdoc, &data[offset], pxf->px_flen, &value)) {
  2046. char *str = PX_timestamp2string(pxdoc, (double) value, time_format);
  2047. fprintf(outfp, "%s", str);
  2048. pxdoc->free(pxdoc, str);
  2049. }
  2050. break;
  2051. }
  2052. case pxfCurrency:
  2053. case pxfNumber: {
  2054. double value;
  2055. if(0 < PX_get_data_double(pxdoc, &data[offset], pxf->px_flen, &value)) {
  2056. fprintf(outfp, "%g", value);
  2057. }
  2058. break;
  2059. }
  2060. case pxfTimestamp: {
  2061. double value;
  2062. if(0 < PX_get_data_double(pxdoc, &data[offset], pxf->px_flen, &value)) {
  2063. char *str = PX_timestamp2string(pxdoc, value, "Y-m-d H:i:s");
  2064. fprintf(outfp, str);
  2065. pxdoc->free(pxdoc, str);
  2066. }
  2067. break;
  2068. }
  2069. case pxfLogical: {
  2070. char value;
  2071. if(0 < PX_get_data_byte(pxdoc, &data[offset], pxf->px_flen, &value)) {
  2072. if(value)
  2073. fprintf(outfp, "1");
  2074. else
  2075. fprintf(outfp, "0");
  2076. }
  2077. break;
  2078. }
  2079. case pxfGraphic:
  2080. case pxfBLOb:
  2081. case pxfFmtMemoBLOb:
  2082. case pxfMemoBLOb:
  2083. case pxfOLE: {
  2084. char *blobdata;
  2085. char filename[200];
  2086. FILE *fp;
  2087. int mod_nr, size, ret;
  2088. if(pxf->px_ftype == pxfGraphic)
  2089. ret = PX_get_data_graphic(pxdoc, &data[offset], pxf->px_flen, &mod_nr, &size, &blobdata);
  2090. else
  2091. ret = PX_get_data_blob(pxdoc, &data[offset], pxf->px_flen, &mod_nr, &size, &blobdata);
  2092. if(ret > 0) {
  2093. if(blobdata) {
  2094. if(pxf->px_ftype == pxfFmtMemoBLOb || pxf->px_ftype == pxfMemoBLOb) {
  2095. int i;
  2096. for(i=0; i<size; i++) {
  2097. fputc(blobdata[i], outfp);
  2098. }
  2099. } else {
  2100. sprintf(filename, "%s_%d.%s", blobprefix, mod_nr, blobextension);
  2101. fp = fopen(filename, "w");
  2102. if(fp) {
  2103. fwrite(blobdata, size, 1, fp);
  2104. fclose(fp);
  2105. fprintf(outfp, "%s", filename);
  2106. } else {
  2107. fprintf(stderr, "Couldn't open file '%s' for blob data\n", filename);
  2108. }
  2109. }
  2110. pxdoc->free(pxdoc, blobdata);
  2111. } else {
  2112. fprintf(stderr, "Couldn't get blob data for %d\n", mod_nr);
  2113. }
  2114. }
  2115. break;
  2116. }
  2117. case pxfBCD: {
  2118. char *value;
  2119. if(0 < PX_get_data_bcd(pxdoc, &data[offset], pxf->px_fdc, &value)) {
  2120. fprintf(outfp, "%s", value);
  2121. pxdoc->free(pxdoc, value);
  2122. }
  2123. first = 1;
  2124. break;
  2125. }
  2126. default:
  2127. break;
  2128. // fprintf(outfp, "");
  2129. }
  2130. fprintf(outfp, "</td>\n");
  2131. }
  2132. offset += pxf->px_flen;
  2133. pxf++;
  2134. }
  2135. if(filetype == pxfFileTypPrimIndex) {
  2136. short int value;
  2137. if(0 < PX_get_data_short(pxdoc, &data[offset], 2, &value)) {
  2138. fprintf(outfp, " <td>%d</td>\n", value);
  2139. }
  2140. offset += 2;
  2141. if(0 < PX_get_data_short(pxdoc, &data[offset], 2, &value)) {
  2142. fprintf(outfp, " <td>%d</td>\n", value);
  2143. }
  2144. offset += 2;
  2145. if(0 < PX_get_data_short(pxdoc, &data[offset], 2, &value)) {
  2146. fprintf(outfp, " <td>%d</td>\n", value);
  2147. }
  2148. }
  2149. if(markdeleted) {
  2150. fprintf(outfp, " <td>%d</td>\n", isdeleted);
  2151. }
  2152. fprintf(outfp, " <tr>\n");
  2153. } else {
  2154. fprintf(stderr, _("Couldn't get record number %d\n"), j);
  2155. }
  2156. }
  2157. fprintf(outfp, "</table>\n");
  2158. pxdoc->free(pxdoc, data);
  2159. }
  2160. /* }}} */
  2161. /* Output data as sql statements {{{
  2162. */
  2163. if(outputsql) {
  2164. if((filetype != pxfFileTypIndexDB) &&
  2165. (filetype != pxfFileTypNonIndexDB)) {
  2166. fprintf(stderr, _("SQL output is only reasonable for DB files."));
  2167. fprintf(stderr, "\n");
  2168. PX_close(pxdoc);
  2169. exit(1);
  2170. }
  2171. /* check if existing table shall be delete */
  2172. if(deletetable) {
  2173. fprintf(outfp, "DROP TABLE %s;\n", tablename);
  2174. }
  2175. /* Output table schema */
  2176. if(!skipschema) {
  2177. fprintf(outfp, "CREATE TABLE %s (\n", tablename);
  2178. first = 0; // set to 1 when first field has been output
  2179. pxf = PX_get_fields(pxdoc);
  2180. for(i=0; i<PX_get_num_fields(pxdoc); i++) {
  2181. if(fieldregex == NULL || selectedfields[i]) {
  2182. strrep(pxf->px_fname, ' ', '_');
  2183. if(first == 1)
  2184. fprintf(outfp, ",\n");
  2185. switch(pxf->px_ftype) {
  2186. case pxfAlpha:
  2187. case pxfDate:
  2188. case pxfShort:
  2189. case pxfLong:
  2190. case pxfAutoInc:
  2191. case pxfCurrency:
  2192. case pxfNumber:
  2193. case pxfLogical:
  2194. case pxfTime:
  2195. case pxfTimestamp:
  2196. case pxfBytes:
  2197. case pxfMemoBLOb:
  2198. case pxfBLOb:
  2199. case pxfFmtMemoBLOb:
  2200. case pxfGraphic:
  2201. case pxfOLE:
  2202. fprintf(outfp, " %s ", pxf->px_fname);
  2203. fprintf(outfp, "%s", get_sql_type(typemap, pxf->px_ftype, pxf->px_flen));
  2204. first = 1;
  2205. break;
  2206. case pxfBCD:
  2207. fprintf(outfp, " %s ", pxf->px_fname);
  2208. fprintf(outfp, "%s", get_sql_type(typemap, pxf->px_ftype, pxf->px_fdc));
  2209. first = 1;
  2210. break;
  2211. }
  2212. // if(i < primarykeyfields)
  2213. // fprintf(outfp, " unique");
  2214. }
  2215. pxf++;
  2216. }
  2217. if(primarykeyfields) {
  2218. first = 0; // set to 1 when first field has been output
  2219. pxf = PX_get_fields(pxdoc);
  2220. fprintf(outfp, ",\n unique(");
  2221. for(i=0; i<primarykeyfields; i++) {
  2222. if(fieldregex == NULL || selectedfields[i]) {
  2223. strrep(pxf->px_fname, ' ', '_');
  2224. if(first == 1)
  2225. fprintf(outfp, ",");
  2226. fprintf(outfp, "%s", pxf->px_fname);
  2227. first = 1;
  2228. }
  2229. pxf++;
  2230. }
  2231. fprintf(outfp, ")");
  2232. }
  2233. fprintf(outfp, "\n);\n");
  2234. /* Create the indexes */
  2235. pxf = PX_get_fields(pxdoc);
  2236. for(i=0; i<primarykeyfields; i++) {
  2237. if(fieldregex == NULL || selectedfields[i]) {
  2238. strrep(pxf->px_fname, ' ', '_');
  2239. fprintf(outfp, "CREATE INDEX %s_%s_index on %s (%s);\n", tablename, pxf->px_fname, tablename, pxf->px_fname);
  2240. }
  2241. pxf++;
  2242. }
  2243. }
  2244. /* Only output data if we have at least one record */
  2245. if(PX_get_num_records(pxdoc) > 0) {
  2246. if((data = (char *) pxdoc->malloc(pxdoc, recordsize, _("Could not allocate memory for record."))) == NULL) {
  2247. if(selectedfields)
  2248. pxdoc->free(pxdoc, selectedfields);
  2249. PX_close(pxdoc);
  2250. exit(1);
  2251. }
  2252. if(usecopy) {
  2253. fprintf(outfp, "COPY %s (", tablename);
  2254. first = 0; // set to 1 when first field has been output
  2255. pxf = PX_get_fields(pxdoc);
  2256. /* output field name */
  2257. for(i=0; i<PX_get_num_fields(pxdoc); i++) {
  2258. if(fieldregex == NULL || selectedfields[i]) {
  2259. if(first == 1)
  2260. fprintf(outfp, ", ");
  2261. switch(pxf->px_ftype) {
  2262. case pxfAlpha:
  2263. case pxfDate:
  2264. case pxfShort:
  2265. case pxfLong:
  2266. case pxfAutoInc:
  2267. case pxfTime:
  2268. case pxfCurrency:
  2269. case pxfNumber:
  2270. case pxfLogical:
  2271. case pxfBCD:
  2272. case pxfTimestamp:
  2273. case pxfBytes:
  2274. case pxfMemoBLOb:
  2275. case pxfBLOb:
  2276. case pxfFmtMemoBLOb:
  2277. case pxfGraphic:
  2278. case pxfOLE:
  2279. fprintf(outfp, "%s", pxf->px_fname);
  2280. first = 1;
  2281. break;
  2282. }
  2283. }
  2284. pxf++;
  2285. }
  2286. fprintf(outfp, ") FROM stdin;\n");
  2287. for(j=0; j<PX_get_num_records(pxdoc); j++) {
  2288. int offset;
  2289. if(PX_get_record(pxdoc, j, data)) {
  2290. first = 0; // set to 1 when first field has been output
  2291. offset = 0;
  2292. pxf = PX_get_fields(pxdoc);
  2293. for(i=0; i<PX_get_num_fields(pxdoc); i++) {
  2294. if(fieldregex == NULL || selectedfields[i]) {
  2295. if(first == 1)
  2296. fprintf(outfp, "\t");
  2297. switch(pxf->px_ftype) {
  2298. case pxfAlpha: {
  2299. char *value;
  2300. int ret;
  2301. if(0 < (ret = PX_get_data_alpha(pxdoc, &data[offset], pxf->px_flen, &value))) {
  2302. if(strchr(value, '\t'))
  2303. printmask(outfp, value, '\t', '\\');
  2304. else
  2305. fprintf(outfp, "%s", value);
  2306. pxdoc->free(pxdoc, value);
  2307. } else if(ret == 0) {
  2308. if(emptystringisnull)
  2309. fprintf(outfp, "\\N");
  2310. } else {
  2311. fprintf(stderr, "Error while reading data of field number %d", i+1);
  2312. fprintf(stderr, "\n");
  2313. }
  2314. first = 1;
  2315. break;
  2316. }
  2317. case pxfDate: {
  2318. long value;
  2319. if(0 < PX_get_data_long(pxdoc, &data[offset], pxf->px_flen, &value)) {
  2320. char *str = PX_timestamp2string(pxdoc, (double) value*1000.0*86400.0, date_format);
  2321. fprintf(outfp, "%s", str);
  2322. pxdoc->free(pxdoc, str);
  2323. } else {
  2324. fprintf(outfp, "\\N");
  2325. }
  2326. first = 1;
  2327. break;
  2328. }
  2329. case pxfShort: {
  2330. short int value;
  2331. if(0 < PX_get_data_short(pxdoc, &data[offset], pxf->px_flen, &value)) {
  2332. fprintf(outfp, "%d", value);
  2333. } else {
  2334. fprintf(outfp, "\\N");
  2335. }
  2336. first = 1;
  2337. break;
  2338. }
  2339. case pxfAutoInc:
  2340. case pxfLong: {
  2341. long value;
  2342. if(0 < PX_get_data_long(pxdoc, &data[offset], pxf->px_flen, &value)) {
  2343. fprintf(outfp, "%ld", value);
  2344. } else {
  2345. fprintf(outfp, "\\N");
  2346. }
  2347. first = 1;
  2348. break;
  2349. }
  2350. case pxfTimestamp: {
  2351. double value;
  2352. if(0 < PX_get_data_double(pxdoc, &data[offset], pxf->px_flen, &value)) {
  2353. char *str = PX_timestamp2string(pxdoc, value, "Y-m-d H:i:s");
  2354. fprintf(outfp, str);
  2355. pxdoc->free(pxdoc, str);
  2356. } else {
  2357. fprintf(outfp, "\\N");
  2358. }
  2359. first = 1;
  2360. break;
  2361. }
  2362. case pxfTime: {
  2363. long value;
  2364. if(0 < PX_get_data_long(pxdoc, &data[offset], pxf->px_flen, &value)) {
  2365. char *str = PX_timestamp2string(pxdoc, (double) value, time_format);
  2366. fprintf(outfp, "%s", str);
  2367. pxdoc->free(pxdoc, str);
  2368. } else {
  2369. fprintf(outfp, "\\N");
  2370. }
  2371. first = 1;
  2372. break;
  2373. }
  2374. case pxfCurrency:
  2375. case pxfNumber: {
  2376. double value;
  2377. if(0 < PX_get_data_double(pxdoc, &data[offset], pxf->px_flen, &value)) {
  2378. fprintf(outfp, "%g", value);
  2379. } else {
  2380. fprintf(outfp, "\\N");
  2381. }
  2382. first = 1;
  2383. break;
  2384. }
  2385. case pxfLogical: {
  2386. char value;
  2387. if(0 < PX_get_data_byte(pxdoc, &data[offset], pxf->px_flen, &value)) {
  2388. if(value)
  2389. fprintf(outfp, "TRUE");
  2390. else
  2391. fprintf(outfp, "FALSE");
  2392. } else {
  2393. fprintf(outfp, "\\N");
  2394. }
  2395. first = 1;
  2396. break;
  2397. }
  2398. case pxfBLOb:
  2399. case pxfGraphic:
  2400. case pxfOLE:
  2401. case pxfMemoBLOb:
  2402. case pxfFmtMemoBLOb: {
  2403. char *blobdata;
  2404. char filename[200];
  2405. FILE *fp;
  2406. int mod_nr, size, ret;
  2407. if(pxf->px_ftype == pxfGraphic)
  2408. ret = PX_get_data_graphic(pxdoc, &data[offset], pxf->px_flen, &mod_nr, &size, &blobdata);
  2409. else
  2410. ret = PX_get_data_blob(pxdoc, &data[offset], pxf->px_flen, &mod_nr, &size, &blobdata);
  2411. if(ret > 0) {
  2412. if(blobdata) {
  2413. if(pxf->px_ftype == pxfFmtMemoBLOb || pxf->px_ftype == pxfMemoBLOb) {
  2414. int i;
  2415. for(i=0; i<size; i++) {
  2416. if(blobdata[i] == '\t')
  2417. fputc('\\', outfp);
  2418. fputc(blobdata[i], outfp);
  2419. }
  2420. } else {
  2421. sprintf(filename, "%s_%d.%s", blobprefix, mod_nr, blobextension);
  2422. fp = fopen(filename, "w");
  2423. if(fp) {
  2424. fwrite(blobdata, size, 1, fp);
  2425. fclose(fp);
  2426. fprintf(outfp, "%s", filename);
  2427. } else {
  2428. fprintf(stderr, "Couldn't open file '%s' for blob data\n", filename);
  2429. }
  2430. }
  2431. pxdoc->free(pxdoc, blobdata);
  2432. } else {
  2433. fprintf(stderr, "Couldn't get blob data for %d\n", mod_nr);
  2434. }
  2435. }
  2436. first = 1;
  2437. break;
  2438. }
  2439. case pxfBCD: {
  2440. char *value;
  2441. int ret;
  2442. if(0 < (ret = PX_get_data_bcd(pxdoc, &data[offset], pxf->px_fdc, &value))) {
  2443. fprintf(outfp, "%s", value);
  2444. pxdoc->free(pxdoc, value);
  2445. } else if(ret == 0) {
  2446. fprintf(outfp, "NULL");
  2447. } else {
  2448. fprintf(stderr, "Could not read data of bcd field '%s'\n", pxf->px_fname);
  2449. }
  2450. first = 1;
  2451. break;
  2452. }
  2453. case pxfBytes:
  2454. fprintf(outfp, "\\N");
  2455. break;
  2456. default:
  2457. break;
  2458. // fprintf(outfp, "");
  2459. }
  2460. }
  2461. offset += pxf->px_flen;
  2462. pxf++;
  2463. }
  2464. fprintf(outfp, "\n");
  2465. } else {
  2466. fprintf(stderr, _("Couldn't get record number %d\n"), j);
  2467. }
  2468. }
  2469. fprintf(outfp, "\\.\n");
  2470. } else {
  2471. struct str_buffer *sbuf;
  2472. if(!shortinsert) {
  2473. if((sbuf = str_buffer_new(pxdoc, 20)) == NULL) {
  2474. if(selectedfields)
  2475. pxdoc->free(pxdoc, selectedfields);
  2476. PX_close(pxdoc);
  2477. exit(1);
  2478. }
  2479. str_buffer_print(pxdoc, sbuf, "(");
  2480. first = 0; // set to 1 when first field has been output
  2481. pxf = PX_get_fields(pxdoc);
  2482. /* output field name */
  2483. for(i=0; i<PX_get_num_fields(pxdoc); i++) {
  2484. if(fieldregex == NULL || selectedfields[i]) {
  2485. if(first == 1)
  2486. str_buffer_print(pxdoc, sbuf, ", ");
  2487. switch(pxf->px_ftype) {
  2488. case pxfAlpha:
  2489. case pxfDate:
  2490. case pxfShort:
  2491. case pxfLong:
  2492. case pxfAutoInc:
  2493. case pxfTime:
  2494. case pxfCurrency:
  2495. case pxfNumber:
  2496. case pxfLogical:
  2497. case pxfBCD:
  2498. case pxfTimestamp:
  2499. case pxfBytes:
  2500. case pxfMemoBLOb:
  2501. case pxfFmtMemoBLOb:
  2502. case pxfBLOb:
  2503. case pxfGraphic:
  2504. case pxfOLE:
  2505. str_buffer_print(pxdoc, sbuf, "%s", pxf->px_fname);
  2506. first = 1;
  2507. break;
  2508. }
  2509. }
  2510. pxf++;
  2511. }
  2512. str_buffer_print(pxdoc, sbuf, ")");
  2513. }
  2514. for(j=0; j<PX_get_num_records(pxdoc); j++) {
  2515. int offset;
  2516. if(PX_get_record(pxdoc, j, data)) {
  2517. first = 0; // set to 1 when first field has been output
  2518. offset = 0;
  2519. if(shortinsert)
  2520. fprintf(outfp, "insert into %s values (", tablename);
  2521. else
  2522. fprintf(outfp, "insert into %s %s values (", tablename, str_buffer_get(pxdoc, sbuf));
  2523. pxf = PX_get_fields(pxdoc);
  2524. for(i=0; i<PX_get_num_fields(pxdoc); i++) {
  2525. if(fieldregex == NULL || selectedfields[i]) {
  2526. if(first == 1)
  2527. fprintf(outfp, ", ");
  2528. switch(pxf->px_ftype) {
  2529. case pxfAlpha: {
  2530. char *value;
  2531. int ret;
  2532. if(0 < (ret = PX_get_data_alpha(pxdoc, &data[offset], pxf->px_flen, &value))) {
  2533. if(strchr(value, '\'')) {
  2534. fprintf(outfp, "'");
  2535. printmask(outfp, value, '\'', '\\');
  2536. fprintf(outfp, "'");
  2537. } else
  2538. fprintf(outfp, "'%s'", value);
  2539. pxdoc->free(pxdoc, value);
  2540. } else if(ret == 0) {
  2541. if(emptystringisnull)
  2542. fprintf(outfp, "NULL");
  2543. else
  2544. fprintf(outfp, "''");
  2545. } else {
  2546. fprintf(stderr, "Error while reading data of field number %d", i+1);
  2547. fprintf(stderr, "\n");
  2548. }
  2549. first = 1;
  2550. break;
  2551. }
  2552. case pxfDate: {
  2553. long value;
  2554. if(0 < PX_get_data_long(pxdoc, &data[offset], pxf->px_flen, &value)) {
  2555. char *str = PX_timestamp2string(pxdoc, (double) value*1000.0*86400.0, date_format);
  2556. fprintf(outfp, "%s", str);
  2557. pxdoc->free(pxdoc, str);
  2558. } else {
  2559. fprintf(outfp, "NULL");
  2560. }
  2561. first = 1;
  2562. break;
  2563. }
  2564. case pxfShort: {
  2565. short int value;
  2566. if(0 < PX_get_data_short(pxdoc, &data[offset], pxf->px_flen, &value)) {
  2567. fprintf(outfp, "%d", value);
  2568. } else {
  2569. fprintf(outfp, "NULL");
  2570. }
  2571. first = 1;
  2572. break;
  2573. }
  2574. case pxfAutoInc:
  2575. case pxfLong: {
  2576. long value;
  2577. if(0 < PX_get_data_long(pxdoc, &data[offset], pxf->px_flen, &value)) {
  2578. fprintf(outfp, "%ld", value);
  2579. } else {
  2580. fprintf(outfp, "NULL");
  2581. }
  2582. first = 1;
  2583. break;
  2584. }
  2585. case pxfTimestamp: {
  2586. double value;
  2587. if(0 < PX_get_data_double(pxdoc, &data[offset], pxf->px_flen, &value)) {
  2588. char *str = PX_timestamp2string(pxdoc, value, "Y-m-d H:i:s");
  2589. fprintf(outfp, "'%s'", str);
  2590. pxdoc->free(pxdoc, str);
  2591. } else {
  2592. fprintf(outfp, "NULL");
  2593. }
  2594. first = 1;
  2595. break;
  2596. }
  2597. case pxfTime: {
  2598. long value;
  2599. if(0 < PX_get_data_long(pxdoc, &data[offset], pxf->px_flen, &value)) {
  2600. char *str = PX_timestamp2string(pxdoc, (double) value, time_format);
  2601. fprintf(outfp, "%s", str);
  2602. pxdoc->free(pxdoc, str);
  2603. } else {
  2604. fprintf(outfp, "NULL");
  2605. }
  2606. first = 1;
  2607. break;
  2608. }
  2609. case pxfCurrency:
  2610. case pxfNumber: {
  2611. double value;
  2612. if(0 < PX_get_data_double(pxdoc, &data[offset], pxf->px_flen, &value)) {
  2613. fprintf(outfp, "%g", value);
  2614. } else {
  2615. fprintf(outfp, "NULL");
  2616. }
  2617. first = 1;
  2618. break;
  2619. }
  2620. case pxfLogical: {
  2621. char value;
  2622. if(0 < PX_get_data_byte(pxdoc, &data[offset], pxf->px_flen, &value)) {
  2623. if(value)
  2624. fprintf(outfp, "TRUE");
  2625. else
  2626. fprintf(outfp, "FALSE");
  2627. } else {
  2628. fprintf(outfp, "NULL");
  2629. }
  2630. first = 1;
  2631. break;
  2632. }
  2633. case pxfBLOb:
  2634. case pxfGraphic:
  2635. case pxfOLE:
  2636. case pxfMemoBLOb:
  2637. case pxfFmtMemoBLOb: {
  2638. char *blobdata;
  2639. char filename[200];
  2640. FILE *fp;
  2641. int mod_nr, size, ret;
  2642. if(pxf->px_ftype == pxfGraphic)
  2643. ret = PX_get_data_graphic(pxdoc, &data[offset], pxf->px_flen, &mod_nr, &size, &blobdata);
  2644. else
  2645. ret = PX_get_data_blob(pxdoc, &data[offset], pxf->px_flen, &mod_nr, &size, &blobdata);
  2646. fputc('\'', outfp);
  2647. if(ret > 0) {
  2648. if(blobdata) {
  2649. if(pxf->px_ftype == pxfFmtMemoBLOb || pxf->px_ftype == pxfMemoBLOb) {
  2650. int i;
  2651. for(i=0; i<size; i++) {
  2652. if(blobdata[i] == '\'')
  2653. fputc('\\', outfp);
  2654. fputc(blobdata[i], outfp);
  2655. }
  2656. } else {
  2657. sprintf(filename, "%s_%d.%s", blobprefix, mod_nr, blobextension);
  2658. fp = fopen(filename, "w");
  2659. if(fp) {
  2660. fwrite(blobdata, size, 1, fp);
  2661. fclose(fp);
  2662. fprintf(outfp, "%s", filename);
  2663. } else {
  2664. fprintf(stderr, "Couldn't open file '%s' for blob data\n", filename);
  2665. }
  2666. }
  2667. pxdoc->free(pxdoc, blobdata);
  2668. } else {
  2669. fprintf(stderr, "Couldn't get blob data for %d\n", mod_nr);
  2670. }
  2671. }
  2672. fputc('\'', outfp);
  2673. first = 1;
  2674. break;
  2675. }
  2676. case pxfBCD: {
  2677. char *value;
  2678. int ret;
  2679. if(0 < (ret = PX_get_data_bcd(pxdoc, &data[offset], pxf->px_fdc, &value))) {
  2680. fprintf(outfp, "%s", value);
  2681. pxdoc->free(pxdoc, value);
  2682. } else if(ret == 0) {
  2683. fprintf(outfp, "NULL");
  2684. } else {
  2685. fprintf(stderr, "Could not read data of bcd field '%s'\n", pxf->px_fname);
  2686. }
  2687. first = 1;
  2688. break;
  2689. }
  2690. case pxfBytes:
  2691. fprintf(outfp, "NULL");
  2692. first = 1;
  2693. break;
  2694. default:
  2695. break;
  2696. // fprintf(outfp, "");
  2697. }
  2698. }
  2699. offset += pxf->px_flen;
  2700. pxf++;
  2701. }
  2702. fprintf(outfp, ");\n");
  2703. } else {
  2704. fprintf(stderr, _("Couldn't get record number %d\n"), j);
  2705. }
  2706. }
  2707. if(!shortinsert)
  2708. str_buffer_delete(pxdoc, sbuf);
  2709. }
  2710. pxdoc->free(pxdoc, data);
  2711. }
  2712. }
  2713. /* }}} */
  2714. /* Output debug {{{
  2715. */
  2716. if(outputdebug) {
  2717. int numrecords;
  2718. int isdeleted, presetdeleted;
  2719. if((data = (char *) pxdoc->malloc(pxdoc, recordsize, _("Could not allocate memory for record."))) == NULL) {
  2720. if(selectedfields)
  2721. pxdoc->free(pxdoc, selectedfields);
  2722. PX_close(pxdoc);
  2723. exit(1);
  2724. }
  2725. if(outputdeleted) {
  2726. numrecords = theonumrecords;
  2727. presetdeleted = 1;
  2728. } else {
  2729. numrecords = PX_get_num_records(pxdoc);
  2730. presetdeleted = 0;
  2731. }
  2732. for(j=0; j<numrecords; j++) {
  2733. int offset;
  2734. pxdatablockinfo_t pxdbinfo;
  2735. isdeleted = presetdeleted;
  2736. if(PX_get_record2(pxdoc, j, data, &isdeleted, &pxdbinfo)) {
  2737. fprintf(outfp, _("Previous block number according to header: "));
  2738. fprintf(outfp, "%d\n", pxdbinfo.prev);
  2739. fprintf(outfp, _("Next block number according to header: "));
  2740. fprintf(outfp, "%d\n", pxdbinfo.next);
  2741. fprintf(outfp, _("Real block number in file: "));
  2742. fprintf(outfp, "%d\n", pxdbinfo.number);
  2743. fprintf(outfp, _("Block size: "));
  2744. fprintf(outfp, "%d\n", pxdbinfo.size);
  2745. fprintf(outfp, _("Record number in block: "));
  2746. fprintf(outfp, "%d\n", pxdbinfo.recno);
  2747. fprintf(outfp, _("Number of records in block: "));
  2748. fprintf(outfp, "%d\n", pxdbinfo.numrecords);
  2749. fprintf(outfp, _("Block position in file: "));
  2750. fprintf(outfp, "%ld (0x%X)\n", pxdbinfo.blockpos, (unsigned int) pxdbinfo.blockpos);
  2751. fprintf(outfp, _("Record position in file: "));
  2752. fprintf(outfp, "%ld (0x%X)\n", pxdbinfo.recordpos, (unsigned int) pxdbinfo.recordpos);
  2753. if(markdeleted) {
  2754. fprintf(outfp, _("Record deleted: "));
  2755. fprintf(outfp, "%d\n", isdeleted);
  2756. }
  2757. pxf = PX_get_fields(pxdoc);
  2758. offset = 0;
  2759. first = 0; // set to 1 when first field has been output
  2760. for(i=0; i<PX_get_num_fields(pxdoc); i++) {
  2761. if(fieldregex == NULL || selectedfields[i]) {
  2762. fprintf(outfp, "%s: ", pxf->px_fname);
  2763. hex_dump(outfp, &data[offset], pxf->px_flen);
  2764. fprintf(outfp, "\n");
  2765. }
  2766. switch(pxf->px_ftype) {
  2767. case pxfFmtMemoBLOb:
  2768. case pxfMemoBLOb:
  2769. case pxfBLOb: {
  2770. long size, index, mod_nr, boffset;
  2771. size = get_long_le(&data[offset+pxf->px_flen-10+4]);
  2772. index = get_long_le(&data[offset+pxf->px_flen-10]) & 0x000000ff;
  2773. mod_nr = get_short_le(&data[offset+pxf->px_flen-10+8]);
  2774. boffset = get_long_le(&data[offset+pxf->px_flen-10]) & 0xffffff00;
  2775. fprintf(outfp, "size=%ld, index=%ld, mod_nr=%d, offset=%ld\n", size, index, mod_nr, boffset);
  2776. }
  2777. }
  2778. offset += pxf->px_flen;
  2779. pxf++;
  2780. }
  2781. fprintf(outfp, "\n");
  2782. } else {
  2783. fprintf(stderr, _("Couldn't get record number %d\n"), j);
  2784. }
  2785. }
  2786. pxdoc->free(pxdoc, data);
  2787. }
  2788. /* }}} */
  2789. /* FIXME: not to free typemap->sqltype */
  2790. if(typemap) {
  2791. free_sql_types(typemap);
  2792. free(typemap);
  2793. }
  2794. if(tablename)
  2795. free(tablename);
  2796. /* Free resources and close files {{{
  2797. */
  2798. if(selectedfields)
  2799. pxdoc->free(pxdoc, selectedfields);
  2800. if(pindexfile) {
  2801. PX_close(pindexdoc);
  2802. PX_delete(pindexdoc);
  2803. }
  2804. PX_close(pxdoc);
  2805. PX_delete(pxdoc);
  2806. #ifdef HAVE_GSF
  2807. if(PX_has_gsf_support() && usegsf) {
  2808. gsf_shutdown();
  2809. }
  2810. #endif
  2811. /* }}} */
  2812. #ifdef MEMORY_DEBUGGING
  2813. PX_mp_list_unfreed();
  2814. #endif
  2815. exit(0);
  2816. }
  2817. /* }}} */
  2818. /*
  2819. * Local variables:
  2820. * tab-width: 4
  2821. * c-basic-offset: 4
  2822. * End:
  2823. * vim600: sw=4 ts=4 fdm=marker
  2824. * vim<600: sw=4 ts=4
  2825. */