/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/*
** Copyright (c) 2013 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the Simplified BSD License (also
** known as the "2-Clause License" or "FreeBSD License".)
**
** This program is distributed in the hope that it will be useful,
** but without any warranty; without even the implied warranty of
** merchantability or fitness for a particular purpose.
**
** Author contact information:
** drh@hwaci.com
** http://www.hwaci.com/drh/
**
*******************************************************************************
**
*/
/* Force assert() to always work... */
#if defined(NDEBUG)
#undef NDEBUG
#define DEBUG 1
#endif
#include <assert.h>
#include <stdlib.h> /* atexit() */
#include <string.h> /* strlen() */
#include "fossil/fossil.h"
#include "fsl_internal.h" /* only for testing */
#define MARKER(pfexp) \
do{ printf("MARKER: %s:%d:%s():\t",__FILE__,__LINE__,__func__); \
printf pfexp; \
} while(0)
#define VERBOSE(pfexp) \
if(App.verbose) do { \
printf("VERBOSE: %s:%d:%s():\t",__FILE__,__LINE__,__func__); \
printf pfexp; \
} while(0)
static struct _App {
fsl_cx * f;
char const * name;
char const * dbFile;
char verbose;
char traceSql;
char const * checkoutDir;
} App = {
NULL/*f*/,
NULL/*name*/,
NULL/*dbFile*/,
0/*verbose*/,
0/*traceSql*/,
NULL/*checkoutDir*/
};
static int test_buffer_0(){
fsl_buffer buf = fsl_buffer_empty;
int rc;
fsl_cx * f = App.f;
fsl_size_t sz, szOrig;
char const * infile = 0
? __FILE__
: "fsl_buffer.c";
assert(f);
rc = fsl_buffer_fill_from_filename(&buf, infile);
assert(!rc);
sz = szOrig = buf.used;
rc = fsl_buffer_compress( &buf, &buf );
assert(!rc);
assert(buf.used < sz);
MARKER(("Compressed [%s]. Size: %"FSL_SIZE_T_PFMT
" => %"FSL_SIZE_T_PFMT"\n", infile, szOrig, buf.used));
sz = buf.used;
rc = fsl_buffer_uncompress(&buf, &buf);
assert(!rc);
MARKER(("Uncompressed [%s]. Size: %"FSL_SIZE_T_PFMT
" => %"FSL_SIZE_T_PFMT"\n", infile, sz, buf.used));
assert(szOrig == buf.used);
if(0){
fsl_buffer sql = fsl_buffer_empty;
fsl_buffer_reset(&buf);
rc = fsl_buffer_appendf(&buf, "this isn't a quoted value.");
fsl_buffer_appendf(&sql,"/*%%b*/ SELECT x FROM a WHERE a=%b\n",
&buf);
fsl_output(f, sql.mem, sql.used );
fsl_buffer_reset(&sql);
fsl_buffer_appendf(&sql,"/*%%B*/ SELECT x FROM a WHERE a=%B\n",
&buf);
fsl_output(f, sql.mem, sql.used );
rc = fsl_buffer_reserve(&sql, 0);
assert(!rc);
}
rc = fsl_buffer_reserve(&buf, 0);
assert(!rc);
return rc;
}
static int test0(){
fsl_cx * f = NULL;
int rc;
#if 1
fsl_init_param init = fsl_init_param_empty;
init.output = fsl_outputer_FILE;
init.output.state.state = stdout;
init.config.traceSql = App.traceSql;
rc = fsl_cx_init( &f, &init );
#elif 0
fsl_init_param init = fsl_init_param_default;
init.output.state.state = stdout;
init.config.traceSql = App.traceSql;
rc = fsl_cx_init( &f, &init );
#else
rc = fsl_cx_init( &f, NULL );
#endif
assert(!rc);
App.f = f;
VERBOSE(("Initialized fsl @%p\n", (void const *)f));
if(App.checkoutDir){
fsl_buffer dir = fsl_buffer_empty;
char const * dirName;
rc = fsl_file_canonical_name( ".", &dir, 0);
assert(!rc);
dirName = (char const *)fsl_buffer_cstr(&dir);
VERBOSE(("Trying to open checkout from [%s]...\n",
dirName));
rc = fsl_cx_checkout_open(f, dirName, fsl_buffer_size(&dir));
VERBOSE(("Checkout-open RC=%d (%s)\n", rc, fsl_rc_cstr(rc)));
if(rc){
char const * msg;
int code = fsl_cx_err_get(f, &msg, NULL);
MARKER(("Checkout open failed. rc=%d: %s\n", code, msg));
}
if(!rc){
VERBOSE(("Checkout DB name: %s\n",
fsl_buffer_cstr(&f->fileCkout)));
if(f->fileRepo.used){
VERBOSE(("Opened repo db: %s\n", fsl_buffer_cstr(&f->fileRepo)));
}
}
else{
if(!fsl_cx_err_get(f,NULL,NULL)){
rc = fsl_cx_err_set(f, rc, "Opening of checkout under "
"[%s] failed with code %d (%s).",
dirName, rc, fsl_rc_cstr(rc));
}
}
fsl_buffer_reserve(&dir, 0);
if(rc) return rc;
}
if(App.dbFile){
VERBOSE(("Trying to open repo db file [%s]...\n", App.dbFile));
rc = fsl_cx_repo_open_db( f, App.dbFile, 0 );
if(rc) return rc;
VERBOSE(("Opened db file [%s]\n", App.dbFile));
}
return rc;
}
static void my_atexit(){
if(App.f){
int rc = 0;
fsl_cx * f = App.f;
App.f = NULL;
VERBOSE(("Finalizing fsl @%p\n", (void const *)f));
if(0 &&
fsl_cx_db_checkout(f)){
/* For testing/demo only: this is implicit
when we call fsl_cx_finalize().
*/
rc = fsl_cx_checkout_close(f, 1);
assert(0==rc);
VERBOSE(("Closed checkout/repo db(s).\n"));
}
rc = fsl_cx_finalize( f );
assert(!rc);
}
}
static int process_argv( int argc, char * const * argv ){
int i;
for( i = 1; i < argc; ++i ){
char const * arg = argv[i];
#define ARG(F) if(0==strcmp(F,arg))
ARG("-r") {
App.dbFile = argv[++i];
continue;
}
ARG("-v") {
App.verbose = 1;
continue;
}
ARG("-c"){
App.checkoutDir = ".";
continue;
}
ARG("-S") {
App.traceSql = 1;
}
else if('-' == *arg){
MARKER(("Unknown flag: %s\n", arg));
return FSL_RC_MISUSE;
}
#undef ARG
}
return 0;
}
int main(int argc, char * const * argv ){
int rc;
rc = process_argv( argc, argv );
if(rc) goto end;
atexit( my_atexit );
rc = test0();
if(1 && !rc) rc = test_buffer_0();
end:
MARKER(("Done! rc=%d (%s)\n", rc, fsl_rc_cstr(rc)));
if(rc && App.f){
char const * msg = NULL;
int errRc = fsl_cx_err_get( App.f, &msg, NULL );
if(msg){
MARKER(("Fossil says: error code #%d (%s): %s\n",
errRc, fsl_rc_cstr(errRc), msg));
}
}
return rc;
}
#undef MARKER
#undef VERBOSE