Merge pull request #1 from evanmiller/no-glib

Remove GLib dependency
This commit is contained in:
Evan Miller 2020-08-06 13:19:25 -04:00 committed by GitHub
commit 63e8cb54ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 694 additions and 106 deletions

View File

@ -17,7 +17,7 @@ before_script:
- autoreconf -i -f -Wno-portability - autoreconf -i -f -Wno-portability
script: script:
- ./configure --disable-man --disable-silent-rules - ./configure --disable-man --disable-silent-rules --disable-glib
- make - make
- ./src/util/mdb-array test/data/ASampleDatabase.accdb "Asset Items" - ./src/util/mdb-array test/data/ASampleDatabase.accdb "Asset Items"
- ./src/util/mdb-array test/data/nwind.mdb "Customers" - ./src/util/mdb-array test/data/nwind.mdb "Customers"

View File

@ -51,69 +51,24 @@ Builds on libmdb to provide a SQL engine (aka Jet)
Provids command line utilities, including: Provids command line utilities, including:
### mdb-ver | Command | Description |
| ------- | ----------- |
Prints the version (JET 3 or 4) of an mdb file. | mdb-ver | Prints the version (JET 3 or 4) of an mdb file. |
| mdb-schema | Prints DDL for the specified table. |
### mdb-schema | mdb-export | Export table to CSV format. |
| mdb-tables | A simple dump of table names to be used with shell scripts. |
Prints DDL for the specified table. | mdb-count | A simple count of number of rows in a table, to be used in shell scripts and ETL pipelines. |
| mdb-header | Generates a C header to be used in exporting mdb data to a C prog. |
### mdb-export | mdb-parsecsv | Generates a C program given a CSV file made with mdb-export. |
| mdb-sql | A simple SQL engine (also used by ODBC and gmdb). |
Export table to CSV format. | prcat | Prints the catalog table from an mdb file. |
| prkkd | Dump of information about design view data given the offset to it. |
### mdb-tables | prtable | Dump of a table definition. |
| prdata | Dump of the data given a table name. |
A simple dump of table names to be used with shell scripts. | prole | Dump of ole columns given a table name and sargs. |
| odbc | An ODBC driver for use with unixODBC or iODBC driver manager. Allows one to use MDB files with PHP for example. |
### mdb-count | gmdb2 | The Gnome MDB File Viewer and debugger. Still alpha. |
| mdb-hexdump | (in src/extras) Simple hex dump utility that I've been using to look at mdb files. |
A simple count of number of rows in a table, to be used in shell scripts and ETL pipelines.
### mdb-header
Generates a C header to be used in exporting mdb data to a C prog.
### mdb-parsecsv
Generates a C program given a CSV file made with mdb-export.
### mdb-sql
A simple SQL engine (also used by ODBC and gmdb).
### prcat
Prints the catalog table from an mdb file.
### prkkd
Dump of information about design view data given the offset to it.
### prtable
Dump of a table definition.
### prdata
Dump of the data given a table name.
### prole
Dump of ole columns given a table name and sargs.
## odbc
An ODBC driver for use with unixODBC or iODBC driver manager. Allows one to use MDB files with PHP for example.
## gmdb2
The Gnome MDB File Viewer and debugger. Still alpha, but making great progress.
## src/extras/mdb-hexdump
Simple hex dump utility that I've been using to look at mdb files.
# License # License
@ -150,7 +105,7 @@ If you want to generate the html version of the docbook, you'll need
Last version is available at https://github.com/evanmiller/mdbtools Last version is available at https://github.com/evanmiller/mdbtools
```bash ```bash
$ autoreconf -i -f $ autoreconf -i -f -Wno-portability
``` ```
If you want to build the html version of the docbook documentation, you need to If you want to build the html version of the docbook documentation, you need to
@ -169,6 +124,13 @@ OR for a complete install (requires bison, flex, and unixODBC):
$ ./configure --with-unixodbc=/usr/local $ ./configure --with-unixodbc=/usr/local
``` ```
By default, MDB Tools is linked against the copy of
[GLib](https://developer.gnome.org/glib/) returned by pkg-config. You can
point to a different GLib installation using the `GLIB_CFLAGS` and `GLIB_LIBS`
enivornment variables. Or, you can disable GLib entirely with the
`--disable-glib` flag, in which case MDB Tools will use an internal
implementation of GLib's functions.
configure can be passed any of the following flags to turn on other configure can be passed any of the following flags to turn on other
capabilities. Note that the options `--with-unixodbc` and `--with-iodbc` are capabilities. Note that the options `--with-unixodbc` and `--with-iodbc` are
mutually exclusive. mutually exclusive.

View File

@ -22,14 +22,12 @@ build_script:
if ($env:TOOLCHAIN -eq "msys2") if ($env:TOOLCHAIN -eq "msys2")
{ {
$env:MSYSTEM="MINGW64" $env:MSYSTEM="MINGW64"
C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-x86_64-glib2"
C:\msys64\usr\bin\bash -l -c "cd /c/projects/mdbtools && autoreconf -i -f -Wno-portability" C:\msys64\usr\bin\bash -l -c "cd /c/projects/mdbtools && autoreconf -i -f -Wno-portability"
C:\msys64\usr\bin\bash -l -c "cd /c/projects/mdbtools && ./configure --disable-man --disable-silent-rules" C:\msys64\usr\bin\bash -l -c "cd /c/projects/mdbtools && ./configure --disable-man --disable-silent-rules"
C:\msys64\usr\bin\bash -l -c "cd /c/projects/mdbtools && make" C:\msys64\usr\bin\bash -l -c "cd /c/projects/mdbtools && make"
} }
else else
{ {
C:\cygwin64\setup-x86_64.exe -qP libglib2.0-devel
C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && autoreconf -i -f -Wno-portability" C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && autoreconf -i -f -Wno-portability"
C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && ./configure --disable-man --disable-silent-rules" C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && ./configure --disable-man --disable-silent-rules"
C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && make" C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && make"

View File

@ -21,6 +21,9 @@ AC_HEADER_STDC
AC_CHECK_HEADERS(fcntl.h limits.h unistd.h) AC_CHECK_HEADERS(fcntl.h limits.h unistd.h)
AC_CHECK_HEADERS(wordexp.h) AC_CHECK_HEADERS(wordexp.h)
AC_CHECK_LIB(mswstr, DBLCMapStringW) AC_CHECK_LIB(mswstr, DBLCMapStringW)
AC_CHECK_DECLS([program_invocation_short_name], [], [], [[
#define _GNU_SOURCE
#include <errno.h>]])
dnl Checks for typedefs, structures, and compiler characteristics. dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST AC_C_CONST
@ -46,7 +49,11 @@ AC_MSG_RESULT( no - SQL engine disable);
sql=false sql=false
fi fi
if ! $YACC -V >/dev/null 2>&1; then if $YACC -V >/dev/null 2>&1; then
if $YACC -Wno-conflicts-sr -V >/dev/null 2>&1; then
YFLAGS="$YFLAGS -Wno-conflicts-sr"
fi
else
sql=false sql=false
fi fi
@ -61,9 +68,11 @@ AM_CONDITIONAL(SQL, test x$sql = xtrue)
AC_SUBST(SQL) AC_SUBST(SQL)
AC_SUBST(LFLAGS) AC_SUBST(LFLAGS)
CFLAGS="$CFLAGS -Wall -Wstrict-prototypes" CFLAGS="$CFLAGS -Wall -Wstrict-prototypes -Werror"
AS_CASE([$host], AS_CASE([$host],
[*mingw*|*cygwin*], [LDFLAGS="$LDFLAGS -no-undefined"], []) [*mingw*|*cygwin*], [LDFLAGS="$LDFLAGS -no-undefined"], [])
AS_CASE([$host],
[*mingw*], [LDFLAGS="$LDFLAGS -lWs2_32"], [])
dnl Enable -Wl,--as-needed by default to prevent overlinking dnl Enable -Wl,--as-needed by default to prevent overlinking
AC_ARG_ENABLE([as-needed], AC_ARG_ENABLE([as-needed],
@ -146,14 +155,22 @@ pkg-config is required.
See pkg-config.freedesktop.org]) See pkg-config.freedesktop.org])
fi fi
dnl See if GLib is present and wanted
AC_ARG_ENABLE(glib,
AS_HELP_STRING([--disable-glib], [do not link with GLib]),
[enable_glib=$enableval], [enable_glib=yes])
dnl check for glib/gtk/gnome if test "$enable_glib" = "yes"; then
PKG_CHECK_MODULES([GLIB], [glib-2.0], , PKG_CHECK_MODULES([GLIB], [glib-2.0], HAVE_GLIB=true, HAVE_GLIB=false)
AC_MSG_ERROR([ if test "x$HAVE_GLIB" = "xtrue"; then
glib 2.0 is required by MDB Tools (runtime and devel). GLIB_CFLAGS="$GLIB_CFLAGS -DHAVE_GLIB=1"
It can be downloaded at www.gtk.org. else
])) enable_glib=no
fi
fi
AM_CONDITIONAL(FAKE_GLIB, test "x$enable_glib" != "xyes")
dnl check for gtk/gnome
PKG_CHECK_MODULES([GNOME], [gtk+-2.0 >= 2.14 libglade-2.0 libgnomeui-2.0], HAVE_GNOME=true, HAVE_GNOME=false) PKG_CHECK_MODULES([GNOME], [gtk+-2.0 >= 2.14 libglade-2.0 libgnomeui-2.0], HAVE_GNOME=true, HAVE_GNOME=false)
GNOME_DOC_INIT GNOME_DOC_INIT
@ -277,6 +294,8 @@ if test x$sql = xtrue; then summary=${bold_green}enabled; else summary=${bold_re
AC_MSG_NOTICE([ SQL : ${summary}${reset}]) AC_MSG_NOTICE([ SQL : ${summary}${reset}])
if test x$HAVE_ODBC = xtrue; then summary=${bold_green}enabled; else summary=${bold_red}disabled; fi if test x$HAVE_ODBC = xtrue; then summary=${bold_green}enabled; else summary=${bold_red}disabled; fi
AC_MSG_NOTICE([ ODBC : ${summary}${reset}]) AC_MSG_NOTICE([ ODBC : ${summary}${reset}])
if test x$enable_glib = xyes; then summary=${bold_green}enabled; else summary=${bold_red}disabled; fi
AC_MSG_NOTICE([ GLib : ${summary}${reset}])
if test x$build_gmdb2 = xyes; then summary=${bold_green}enabled; else summary=${bold_red}disabled; fi if test x$build_gmdb2 = xyes; then summary=${bold_green}enabled; else summary=${bold_red}disabled; fi
AC_MSG_NOTICE([ UI : ${summary}${reset}]) AC_MSG_NOTICE([ UI : ${summary}${reset}])
if test x$enable_gtk_doc = xyes; then summary=${bold_green}enabled; else summary=${bold_red}disabled; fi if test x$enable_gtk_doc = xyes; then summary=${bold_green}enabled; else summary=${bold_red}disabled; fi

View File

@ -1,2 +1,5 @@
include_HEADERS = mdbtools.h mdbsql.h mdbver.h include_HEADERS = mdbtools.h mdbsql.h mdbver.h
if FAKE_GLIB
include_HEADERS += mdbfakeglib.h
endif
noinst_HEADERS = mdbprivate.h noinst_HEADERS = mdbprivate.h

157
include/mdbfakeglib.h Normal file
View File

@ -0,0 +1,157 @@
#ifndef _mdbfakeglib_h_
#define _mdbfakeglib_h_
#include <time.h>
#include <locale.h>
#include <inttypes.h>
#include <strings.h>
// for ntohl
#ifdef _WIN32
#include <winsock.h>
#else
#include <arpa/inet.h>
#endif
typedef uint16_t guint16;
typedef uint32_t guint32;
typedef uint64_t guint64;
typedef int32_t gint32;
typedef char gchar;
typedef int gboolean;
typedef int gint;
typedef unsigned int guint;
typedef void * gpointer;
typedef const void * gconstpointer;
typedef uint8_t guint8;
typedef guint32 GQuark;
typedef guint (*GHashFunc)(gconstpointer);
typedef int (*GCompareFunc)(gconstpointer, gconstpointer);
typedef gboolean (*GEqualFunc)(gconstpointer, gconstpointer);
typedef void (*GFunc) (gpointer data, gpointer user_data);
typedef void (*GHFunc)(gpointer key, gpointer value, gpointer data);
typedef gboolean (*GHRFunc)(gpointer key, gpointer value, gpointer data);
typedef struct GPtrArray {
void **pdata;
int len;
} GPtrArray;
typedef struct GList {
gpointer data;
struct GList *next;
struct GList *prev;
} GList;
typedef struct GHashTable {
GEqualFunc compare;
GPtrArray *array;
} GHashTable;
typedef struct GError {
GQuark domain;
gint code;
gchar *message;
} GError;
typedef enum GOptionArg {
G_OPTION_ARG_NONE,
G_OPTION_ARG_STRING,
G_OPTION_ARG_INT
} GOptionArg;
typedef enum GOptionFlags {
G_OPTION_FLAG_NONE,
G_OPTION_FLAG_REVERSE
} GOptionFlags;
typedef struct GOptionEntry {
const gchar *long_name;
gchar short_name;
gint flags;
GOptionArg arg;
gpointer arg_data;
const gchar *description;
const gchar *arg_description;
} GOptionEntry;
typedef struct GOptionContext {
const char *desc;
const GOptionEntry *entries;
} GOptionContext;
#define g_str_hash NULL
#define G_GUINT32_FORMAT PRIu32
#define g_return_val_if_fail(a, b) if (!a) { return b; }
#define g_ascii_strcasecmp strcasecmp
#define g_malloc0(len) calloc(1, len)
#define g_malloc malloc
#define g_free free
#define g_realloc realloc
#define G_STR_DELIMITERS "_-|> <."
#define g_ptr_array_index(array, i) \
((void **)array->pdata)[i]
#define TRUE 1
#define FALSE 0
#define GUINT16_FROM_LE(l) (uint16_t)l
#define GUINT32_FROM_LE(l) (uint32_t)l
#define GUINT64_FROM_LE(l) (uint64_t)l
#define GINT32_FROM_LE(l) (uint32_t)l
#define GINT32_FROM_BE(l) (int32_t)ntohl(l)
#define GUINT32_SWAP_LE_BE(l) (uint32_t)ntohl(l)
#define GINT32_TO_LE(l) (int32_t)l
#define GINT32_TO_BE(l) (int32_t)ntohl(l)
/* string functions */
void *g_memdup(const void *src, size_t len);
int g_str_equal(const void *str1, const void *str2);
char **g_strsplit(const char *haystack, const char *needle, int something);
void g_strfreev(char **dir);
char *g_strconcat(const char *first, ...);
char *g_strdup(const char *src);
char *g_strdup_printf(const char *format, ...);
gchar *g_strdelimit(gchar *string, const gchar *delimiters, gchar new_delimiter);
/* GHashTable */
void *g_hash_table_lookup(GHashTable *tree, const void *key);
void g_hash_table_insert(GHashTable *tree, void *key, void *value);
GHashTable *g_hash_table_new(GHashFunc hashes, GEqualFunc equals);
void g_hash_table_foreach(GHashTable *tree, GHFunc function, void *data);
void g_hash_table_foreach_remove(GHashTable *tree, GHRFunc function, void *data);
void g_hash_table_destroy(GHashTable *tree);
/* GPtrArray */
void g_ptr_array_sort(GPtrArray *array, GCompareFunc func);
void g_ptr_array_foreach(GPtrArray *array, GFunc function, gpointer user_data);
GPtrArray *g_ptr_array_new(void);
void g_ptr_array_add(GPtrArray *array, void *entry);
void g_ptr_array_free(GPtrArray *array, gboolean something);
/* GList */
GList *g_list_append(GList *list, void *data);
GList *g_list_last(GList *list);
GList *g_list_remove(GList *list, void *data);
void g_list_free(GList *list);
/* GOption */
GOptionContext *g_option_context_new(const char *description);
void g_option_context_add_main_entries (GOptionContext *context,
const GOptionEntry *entries,
const gchar *translation_domain);
gchar *g_option_context_get_help (GOptionContext *context,
gboolean main_help, void *group);
gboolean g_option_context_parse (GOptionContext *context,
gint *argc, gchar ***argv, GError **error);
void g_option_context_free (GOptionContext *context);
#endif

View File

@ -25,7 +25,11 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#ifdef HAVE_GLIB
#include <glib.h> #include <glib.h>
#else
#include <mdbfakeglib.h>
#endif
#include <mdbtools.h> #include <mdbtools.h>
typedef struct { typedef struct {

View File

@ -30,7 +30,12 @@
#include <unistd.h> #include <unistd.h>
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#ifdef HAVE_GLIB
#include <glib.h> #include <glib.h>
#else
#include <mdbfakeglib.h>
#endif
#ifdef HAVE_ICONV #ifdef HAVE_ICONV
#include <iconv.h> #include <iconv.h>
@ -284,8 +289,7 @@ typedef struct {
int object_type; int object_type;
unsigned long table_pg; /* misnomer since object may not be a table */ unsigned long table_pg; /* misnomer since object may not be a table */
//int num_props; please use props->len //int num_props; please use props->len
GArray *props; /* GArray of MdbProperties */ GPtrArray *props; /* GPtrArray of MdbProperties */
GArray *columns;
int flags; int flags;
} MdbCatalogEntry; } MdbCatalogEntry;
@ -575,7 +579,7 @@ extern gint32 mdb_map_find_next(MdbHandle *mdb, unsigned char *map, unsigned int
/* props.c */ /* props.c */
extern void mdb_free_props(MdbProperties *props); extern void mdb_free_props(MdbProperties *props);
extern void mdb_dump_props(MdbProperties *props, FILE *outfile, int show_name); extern void mdb_dump_props(MdbProperties *props, FILE *outfile, int show_name);
extern GArray* mdb_kkd_to_props(MdbHandle *mdb, void *kkd, size_t len); extern GPtrArray* mdb_kkd_to_props(MdbHandle *mdb, void *kkd, size_t len);
/* worktable.c */ /* worktable.c */

View File

@ -1,5 +1,8 @@
lib_LTLIBRARIES = libmdb.la lib_LTLIBRARIES = libmdb.la
libmdb_la_SOURCES= catalog.c mem.c file.c table.c data.c dump.c backend.c money.c sargs.c index.c like.c write.c stats.c map.c props.c worktable.c options.c iconv.c libmdb_la_SOURCES= catalog.c mem.c file.c table.c data.c dump.c backend.c money.c sargs.c index.c like.c write.c stats.c map.c props.c worktable.c options.c iconv.c
if FAKE_GLIB
libmdb_la_SOURCES += fakeglib.c
endif
libmdb_la_LDFLAGS = -version-info 2:1:0 -export-symbols-regex '^(mdb_|_mdb_put_int16$$|_mdb_put_int32$$)' libmdb_la_LDFLAGS = -version-info 2:1:0 -export-symbols-regex '^(mdb_|_mdb_put_int16$$|_mdb_put_int32$$)'
AM_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS) AM_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS)
LIBS = $(GLIB_LIBS) @LIBS@ @LIBICONV@ LIBS = $(GLIB_LIBS) @LIBS@ @LIBICONV@

View File

@ -184,7 +184,7 @@ enum {
MDB_BACKEND_SQLITE, MDB_BACKEND_SQLITE,
}; };
static gboolean mdb_drop_backend(gpointer key, gpointer value, gpointer data); static void mdb_drop_backend(gpointer key, gpointer value, gpointer data);
static gchar* static gchar*
quote_generic(const gchar *value, gchar quote_char, gchar escape_char) { quote_generic(const gchar *value, gchar quote_char, gchar escape_char) {
@ -451,14 +451,13 @@ mdb_remove_backends())
void void
_mdb_remove_backends() _mdb_remove_backends()
{ {
g_hash_table_foreach_remove(mdb_backends, mdb_drop_backend, NULL); g_hash_table_foreach(mdb_backends, mdb_drop_backend, NULL);
g_hash_table_destroy(mdb_backends); g_hash_table_destroy(mdb_backends);
} }
static gboolean mdb_drop_backend(gpointer key, gpointer value, gpointer data) static void mdb_drop_backend(gpointer key, gpointer value, gpointer data)
{ {
MdbBackend *backend = (MdbBackend *)value; MdbBackend *backend = (MdbBackend *)value;
g_free (backend); g_free (backend);
return TRUE;
} }
/** /**

View File

@ -57,8 +57,8 @@ void mdb_free_catalog(MdbHandle *mdb)
if (entry) { if (entry) {
if (entry->props) { if (entry->props) {
for (j=0; j<entry->props->len; j++) for (j=0; j<entry->props->len; j++)
mdb_free_props(g_array_index(entry->props, MdbProperties*, j)); mdb_free_props(g_ptr_array_index(entry->props, j));
g_array_free(entry->props, TRUE); g_ptr_array_free(entry->props, TRUE);
} }
g_free(entry); g_free(entry);
} }

View File

@ -140,9 +140,9 @@ int mdb_find_row(MdbHandle *mdb, int row, int *start, size_t *len)
mdb_get_int16(mdb->pg_buf, rco + row*2) & OFFSET_MASK; mdb_get_int16(mdb->pg_buf, rco + row*2) & OFFSET_MASK;
*len = next_start - (*start & OFFSET_MASK); *len = next_start - (*start & OFFSET_MASK);
if ((*start & OFFSET_MASK) >= mdb->fmt->pg_size || if ((*start & OFFSET_MASK) >= mdb->fmt->pg_size ||
next_start > mdb->fmt->pg_size) next_start > mdb->fmt->pg_size)
return -1; return -1;
return 0; return 0;
} }
@ -304,8 +304,8 @@ int mdb_read_row(MdbTableDef *table, unsigned int row)
num_fields = mdb_crack_row(table, row_start, row_start + row_size - 1, num_fields = mdb_crack_row(table, row_start, row_start + row_size - 1,
fields); fields);
if (num_fields < 0) if (num_fields < 0)
return 0; return 0;
if (!mdb_test_sargs(table, fields, num_fields)) return 0; if (!mdb_test_sargs(table, fields, num_fields)) return 0;
#if MDB_DEBUG #if MDB_DEBUG

416
src/libmdb/fakeglib.c Normal file
View File

@ -0,0 +1,416 @@
#define _GNU_SOURCE
#include "mdbfakeglib.h"
#include <stddef.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include <errno.h>
/* string functions */
void *g_memdup(const void *src, size_t len) {
void *dst = malloc(len);
memcpy(dst, src, len);
return dst;
}
int g_str_equal(const void *str1, const void *str2) {
return strcmp(str1, str2) == 0;
}
char **g_strsplit(const char *haystack, const char *needle, int something) {
char **ret = NULL;
char *found = NULL;
size_t components = 1;
while ((found = strstr(haystack, needle))) {
components++;
haystack = found + strlen(needle);
}
ret = malloc(components * sizeof(char *));
int i = 0;
while ((found = strstr(haystack, needle))) {
// Windows lacks strndup
size_t chunk_len = found - haystack;
char *chunk = malloc(chunk_len + 1);
memcpy(chunk, haystack, chunk_len);
chunk[chunk_len] = 0;
ret[i++] = chunk;
haystack = found + strlen(needle);
}
ret[i] = strdup(haystack);
return ret;
}
void g_strfreev(char **dir) {
int i=0;
while (dir[i]) {
free(dir[i]);
i++;
}
free(dir);
}
char *g_strconcat(const char *first, ...) {
char *ret = NULL;
size_t len = strlen(first);
char *arg = NULL;
va_list argp;
va_start(argp, first);
while ((arg = va_arg(argp, char *))) {
len += strlen(arg);
}
va_end(argp);
ret = malloc(len+1);
char *pos = strcpy(ret, first) + strlen(first);
va_start(argp, first);
while ((arg = va_arg(argp, char *))) {
pos = strcpy(pos, arg) + strlen(arg);
}
va_end(argp);
ret[len] = '\0';
return ret;
}
#if defined _WIN32
int vasprintf(char **ret, const char *format, va_list ap) {
int len;
int retval;
char *result;
if ((len = _vscprintf(format, ap)) < 0)
return -1;
if ((result = malloc(len+1)) == NULL)
return -1;
if ((retval = vsprintf_s(result, len+1, format, ap)) == -1) {
free(result);
return -1;
}
*ret = result;
return retval;
}
#endif
char *g_strdup(const char *input) {
size_t len = strlen(input);
return g_memdup(input, len+1);
}
char *g_strdup_printf(const char *format, ...) {
char *ret = NULL;
va_list argp;
va_start(argp, format);
#ifdef __CYGWIN__
size_t len = 0;
ret = vasnprintf(ret, &len, format, argp);
#else
int gcc_is_dumb = vasprintf(&ret, format, argp);
(void)gcc_is_dumb;
#endif
va_end(argp);
return ret;
}
gchar *g_strdelimit(gchar *string, const gchar *delimiters, gchar new_delimiter) {
char *orig = string;
if (delimiters == NULL)
delimiters = G_STR_DELIMITERS;
size_t n = strlen(delimiters);
while (*string) {
size_t i;
for (i=0; i<n; i++) {
if (*string == delimiters[i]) {
*string = new_delimiter;
break;
}
}
string++;
}
return orig;
}
/* GHashTable */
typedef struct MyNode {
char *key;
void *value;
} MyNode;
void *g_hash_table_lookup(GHashTable *table, const void *key) {
int i;
for (i=0; i<table->array->len; i++) {
MyNode *node = g_ptr_array_index(table->array, i);
if (table->compare(key, node->key))
return node->value;
}
return NULL;
}
void g_hash_table_insert(GHashTable *table, void *key, void *value) {
MyNode *node = calloc(1, sizeof(MyNode));
node->value = value;
node->key = key;
g_ptr_array_add(table->array, node);
}
GHashTable *g_hash_table_new(GHashFunc hashes, GEqualFunc equals) {
GHashTable *table = calloc(1, sizeof(GHashTable));
table->array = g_ptr_array_new();
table->compare = equals;
return table;
}
void g_hash_table_foreach(GHashTable *table, GHFunc function, void *data) {
int i;
for (i=0; i<table->array->len; i++) {
MyNode *node = g_ptr_array_index(table->array, i);
function(node->key, node->value, data);
}
}
void g_hash_table_destroy(GHashTable *table) {
int i;
for (i=0; i<table->array->len; i++) {
MyNode *node = g_ptr_array_index(table->array, i);
free(node);
}
g_ptr_array_free(table->array, TRUE);
free(table);
}
/* GPtrArray */
void g_ptr_array_sort(GPtrArray *array, GCompareFunc func) {
qsort(array->pdata, array->len, sizeof(void *), func);
}
void g_ptr_array_foreach(GPtrArray *array, GFunc function, gpointer user_data) {
int i;
for (i=0; i<array->len; i++) {
function(g_ptr_array_index(array, i), user_data);
}
}
GPtrArray *g_ptr_array_new() {
GPtrArray *array = malloc(sizeof(GPtrArray));
array->len = 0;
array->pdata = NULL;
return array;
}
void g_ptr_array_add(GPtrArray *array, void *entry) {
array->pdata = realloc(array->pdata, (array->len+1) * sizeof(void *));
array->pdata[array->len++] = entry;
}
void g_ptr_array_free(GPtrArray *array, gboolean something) {
free(array->pdata);
free(array);
}
/* GList */
GList *g_list_append(GList *list, void *data) {
GList *new_list = calloc(1, sizeof(GList));
new_list->data = data;
new_list->next = list;
if (list)
list->prev = new_list;
return new_list;
}
GList *g_list_last(GList *list) {
while (list && list->next) {
list = list->next;
}
return list;
}
GList *g_list_remove(GList *list, void *data) {
GList *link = list;
while (link) {
if (link->data == data) {
GList *return_list = list;
if (link->prev)
link->prev->next = link->next;
if (link->next)
link->next->prev = link->prev;
if (link == list)
return_list = link->next;
free(link);
return return_list;
}
link = link->next;
}
return list;
}
void g_list_free(GList *list) {
GList *next = NULL;
while (list) {
next = list->next;
free(list);
list = next;
}
}
/* GOption */
void g_option_context_add_main_entries (GOptionContext *context,
const GOptionEntry *entries,
const gchar *translation_domain) {
context->entries = entries;
}
gchar *g_option_context_get_help (GOptionContext *context,
gboolean main_help, void *group) {
#if defined(__APPLE__) || defined(__FreeBSD__)
const char * appname = getprogname();
#elif HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
const char * appname = program_invocation_short_name;
#else
const char * appname = "mdb-util";
#endif
char *help = malloc(4096);
char *end = help + 4096;
char *p = help;
p += snprintf(p, end - p,
"Usage:\n %s [OPTION\xE2\x80\xA6] %s\n\n", appname, context->desc);
p += snprintf(p, end - p,
"Help Options:\n -h, --%-20s%s\n\n", "help", "Show help options");
p += snprintf(p, end - p,
"Application Options:\n");
int i=0;
for (i=0; context->entries[i].long_name; i++) {
p += snprintf(p, end - p, " ");
if (context->entries[i].short_name) {
p += snprintf(p, end - p, "-%c, ", context->entries[i].short_name);
}
p += snprintf(p, end - p, "--");
if (context->entries[i].arg_description) {
char *long_name = g_strconcat(
context->entries[i].long_name, "=",
context->entries[i].arg_description, NULL);
p += snprintf(p, end - p, "%-20s", long_name);
free(long_name);
} else {
p += snprintf(p, end - p, "%-20s", context->entries[i].long_name);
}
if (!context->entries[i].short_name) {
p += snprintf(p, end - p, " ");
}
p += snprintf(p, end - p, "%s\n", context->entries[i].description);
}
p += snprintf(p, end - p, "\n");
return help;
}
GOptionContext *g_option_context_new(const char *description) {
GOptionContext *ctx = calloc(1, sizeof(GOptionContext));
ctx->desc = description;
return ctx;
}
gboolean g_option_context_parse(GOptionContext *context,
gint *argc, gchar ***argv, GError **error) {
int i;
int count = 0;
int len = 0;
if (*argc == 2 &&
(strcmp((*argv)[1], "-h") == 0 || strcmp((*argv)[1], "--help") == 0)) {
fprintf(stderr, "%s", g_option_context_get_help(context, TRUE, NULL));
exit(0);
}
for (i=0; context->entries[i].long_name; i++) {
GOptionArg arg = context->entries[i].arg;
count++;
len++;
if (arg == G_OPTION_ARG_STRING || arg == G_OPTION_ARG_INT) {
len++;
}
}
struct option *long_opts = calloc(count+1, sizeof(struct option));
char *short_opts = calloc(1, len+1);
int j=0;
for (i=0; i<count; i++) {
const GOptionEntry *entry = &context->entries[i];
GOptionArg arg = entry->arg;
short_opts[j++] = entry->short_name;
if (arg == G_OPTION_ARG_STRING || arg == G_OPTION_ARG_INT) {
short_opts[j++] = ':';
}
long_opts[i].name = entry->long_name;
long_opts[i].has_arg = entry->arg == G_OPTION_ARG_NONE ? no_argument : required_argument;
}
int c;
int longindex = 0;
opterr = 0;
while ((c = getopt_long(*argc, *argv, short_opts, long_opts, &longindex)) != -1) {
if (c == '?') {
*error = malloc(sizeof(GError));
(*error)->message = malloc(100);
if (optopt) {
snprintf((*error)->message, 100, "Unrecognized option: -%c", optopt);
} else {
snprintf((*error)->message, 100, "Unrecognized option: %s", (*argv)[optind-1]);
}
free(short_opts);
free(long_opts);
return FALSE;
}
const GOptionEntry *entry = NULL;
if (c == 0) {
entry = &context->entries[longindex];
} else {
for (i=0; i<count; i++) {
if (context->entries[i].short_name == c) {
entry = &context->entries[i];
break;
}
}
}
if (entry->arg == G_OPTION_ARG_NONE) {
*(int *)entry->arg_data = !(entry->flags & G_OPTION_FLAG_REVERSE);
} else if (entry->arg == G_OPTION_ARG_INT) {
char *endptr = NULL;
*(int *)entry->arg_data = strtol(optarg, &endptr, 10);
if (*endptr) {
*error = malloc(sizeof(GError));
(*error)->message = malloc(100);
snprintf((*error)->message, 100, "Argument to --%s must be an integer", entry->long_name);
free(short_opts);
free(long_opts);
return FALSE;
}
} else if (entry->arg == G_OPTION_ARG_STRING) {
*(char **)entry->arg_data = strdup(optarg);
}
}
*argc -= (optind - 1);
*argv += (optind - 1);
free(short_opts);
free(long_opts);
return TRUE;
}
void g_option_context_free(GOptionContext *context) {
free(context);
}

View File

@ -23,6 +23,10 @@
#include "dmalloc.h" #include "dmalloc.h"
#endif #endif
#ifndef MIN
#define MIN(a,b) (a>b ? b : a)
#endif
/* /*
* This function is used in reading text data from an MDB table. * This function is used in reading text data from an MDB table.
*/ */

View File

@ -176,16 +176,16 @@ mdb_dump_props(MdbProperties *props, FILE *outfile, int show_name) {
/* /*
* That function takes a raw KKD/MR2 binary buffer, * That function takes a raw KKD/MR2 binary buffer,
* typically read from LvProp in table MSysbjects * typically read from LvProp in table MSysbjects
* and returns a GArray of MdbProps* * and returns a GPtrArray of MdbProps*
*/ */
GArray* GPtrArray*
mdb_kkd_to_props(MdbHandle *mdb, void *buffer, size_t len) { mdb_kkd_to_props(MdbHandle *mdb, void *buffer, size_t len) {
guint32 record_len; guint32 record_len;
guint16 record_type; guint16 record_type;
size_t pos; size_t pos;
GPtrArray *names = NULL; GPtrArray *names = NULL;
MdbProperties *props; MdbProperties *props;
GArray *result; GPtrArray *result;
#if MDB_DEBUG #if MDB_DEBUG
mdb_buffer_dump(buffer, 0, len); mdb_buffer_dump(buffer, 0, len);
@ -198,7 +198,7 @@ mdb_kkd_to_props(MdbHandle *mdb, void *buffer, size_t len) {
return NULL; return NULL;
} }
result = g_array_new(0, 0, sizeof(MdbProperties*)); result = g_ptr_array_new();
pos = 4; pos = 4;
while (pos < len) { while (pos < len) {
@ -219,7 +219,7 @@ mdb_kkd_to_props(MdbHandle *mdb, void *buffer, size_t len) {
break; break;
} }
props = mdb_read_props(mdb, names, (char*)buffer+pos+6, record_len - 6); props = mdb_read_props(mdb, names, (char*)buffer+pos+6, record_len - 6);
g_array_append_val(result, props); g_ptr_array_add(result, props);
//mdb_dump_props(props, stderr, 1); //mdb_dump_props(props, stderr, 1);
break; break;
default: default:

View File

@ -108,7 +108,7 @@ MdbTableDef *mdb_read_table(MdbCatalogEntry *entry)
if (entry->props) if (entry->props)
for (i=0; i<entry->props->len; ++i) { for (i=0; i<entry->props->len; ++i) {
MdbProperties *props = g_array_index(entry->props, MdbProperties*, i); MdbProperties *props = g_ptr_array_index(entry->props, i);
if (!props->name) if (!props->name)
table->props = props; table->props = props;
} }
@ -222,7 +222,7 @@ GPtrArray *mdb_read_columns(MdbTableDef *table)
unsigned int i, j; unsigned int i, j;
int cur_pos; int cur_pos;
size_t name_sz; size_t name_sz;
GArray *allprops; GPtrArray *allprops;
table->columns = g_ptr_array_new(); table->columns = g_ptr_array_new();
@ -315,8 +315,8 @@ GPtrArray *mdb_read_columns(MdbTableDef *table)
for (i=0;i<table->num_cols;i++) { for (i=0;i<table->num_cols;i++) {
pcol = g_ptr_array_index(table->columns, i); pcol = g_ptr_array_index(table->columns, i);
for (j=0; j<allprops->len; ++j) { for (j=0; j<allprops->len; ++j) {
MdbProperties *props = g_array_index(allprops, MdbProperties*, j); MdbProperties *props = g_ptr_array_index(allprops, j);
if (props->name && pcol->name && !strcmp(props->name, pcol->name)) { if (props->name && !strcmp(props->name, pcol->name)) {
pcol->props = props; pcol->props = props;
break; break;
} }

View File

@ -58,7 +58,7 @@ static int GetNextItem (FILE* stream, char** name, char** value);
#endif //HAVE_SQLGETPRIVATEPROFILESTRING #endif //HAVE_SQLGETPRIVATEPROFILESTRING
static void visit (gpointer key, gpointer value, gpointer user_data); static void visit (gpointer key, gpointer value, gpointer user_data);
static gboolean cleanup (gpointer key, gpointer value, gpointer user_data); static void cleanup (gpointer key, gpointer value, gpointer user_data);
/* /*
* Allocate create a ConnectParams object * Allocate create a ConnectParams object
@ -91,7 +91,7 @@ void FreeConnectParams (ConnectParams* params)
g_string_free (params->iniFileName, TRUE); g_string_free (params->iniFileName, TRUE);
if (params->table) if (params->table)
{ {
g_hash_table_foreach_remove (params->table, cleanup, NULL); g_hash_table_foreach (params->table, cleanup, NULL);
g_hash_table_destroy (params->table); g_hash_table_destroy (params->table);
} }
g_free(params); g_free(params);
@ -514,12 +514,10 @@ static void visit (gpointer key, gpointer value, gpointer user_data)
fprintf(output, "Parameter: %s, Value: %s\n", (char*)key, (char*)value); fprintf(output, "Parameter: %s, Value: %s\n", (char*)key, (char*)value);
} }
static gboolean cleanup (gpointer key, gpointer value, gpointer user_data) static void cleanup (gpointer key, gpointer value, gpointer user_data)
{ {
g_free (key); g_free (key);
g_free (value); g_free (value);
return TRUE;
} }

View File

@ -1,7 +1,11 @@
AUTOMAKE_OPTIONS = subdir-objects
BUILT_SOURCES = parser.h BUILT_SOURCES = parser.h
AM_YFLAGS = -d AM_YFLAGS = -d
lib_LTLIBRARIES = libmdbsql.la lib_LTLIBRARIES = libmdbsql.la
libmdbsql_la_SOURCES= mdbsql.c parser.y lexer.l libmdbsql_la_SOURCES= mdbsql.c parser.y lexer.l
if FAKE_GLIB
libmdbsql_la_SOURCES += ../libmdb/fakeglib.c
endif
libmdbsql_la_LDFLAGS = -version-info 2:0:0 -export-symbols-regex '^mdb_sql_' libmdbsql_la_LDFLAGS = -version-info 2:0:0 -export-symbols-regex '^mdb_sql_'
CLEANFILES = parser.c parser.h lexer.c CLEANFILES = parser.c parser.h lexer.c
AM_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS) AM_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS)

View File

@ -1,7 +1,24 @@
AUTOMAKE_OPTIONS = subdir-objects
SUBDIRS = bash-completion SUBDIRS = bash-completion
bin_PROGRAMS = mdb-export mdb-array mdb-schema mdb-tables mdb-parsecsv mdb-header mdb-sql mdb-ver mdb-prop mdb-count bin_PROGRAMS = mdb-export mdb-array mdb-schema mdb-tables mdb-parsecsv mdb-header mdb-sql mdb-ver mdb-prop mdb-count
noinst_PROGRAMS = mdb-import prtable prcat prdata prkkd prdump prole updrow prindex noinst_PROGRAMS = mdb-import prtable prcat prdata prkkd prdump prole updrow prindex
LIBS = $(GLIB_LIBS) @LIBS@ mdb_export_SOURCES = mdb-export.c
mdb_schema_SOURCES = mdb-schema.c
mdb_tables_SOURCES = mdb-tables.c
mdb_sql_SOURCES = mdb-sql.c
mdb_ver_SOURCES = mdb-ver.c
mdb_import_SOURCES = mdb-import.c
updrow_SOURCES = updrow.c
if FAKE_GLIB
mdb_export_SOURCES += ../libmdb/fakeglib.c
mdb_schema_SOURCES += ../libmdb/fakeglib.c
mdb_tables_SOURCES += ../libmdb/fakeglib.c
mdb_sql_SOURCES += ../libmdb/fakeglib.c
mdb_ver_SOURCES += ../libmdb/fakeglib.c
mdb_import_SOURCES += ../libmdb/fakeglib.c
updrow_SOURCES += ../libmdb/fakeglib.c
endif
LIBS = $(GLIB_LIBS) @LIBS@
DEFS = @DEFS@ -DLOCALEDIR=\"$(localedir)\" DEFS = @DEFS@ -DLOCALEDIR=\"$(localedir)\"
AM_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS) AM_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS)
LDADD = ../libmdb/libmdb.la LDADD = ../libmdb/libmdb.la

View File

@ -91,12 +91,12 @@ main(int argc, char **argv)
} }
void dump_kkd(MdbHandle *mdb, void *kkd, size_t len) void dump_kkd(MdbHandle *mdb, void *kkd, size_t len)
{ {
GArray *aprops = mdb_kkd_to_props(mdb, kkd, len); GPtrArray *aprops = mdb_kkd_to_props(mdb, kkd, len);
int i; int i;
if (!aprops) if (!aprops)
return; return;
for (i=0; i<aprops->len; ++i) { for (i=0; i<aprops->len; ++i) {
MdbProperties *props = g_array_index(aprops, MdbProperties*, i); MdbProperties *props = g_ptr_array_index(aprops, i);
mdb_dump_props(props, stdout, 1); mdb_dump_props(props, stdout, 1);
} }
} }