c434cad322
Files correlati : Ricompilazione Demo : [ ] Commento : Riportata la versione 3.1 patch 650 git-svn-id: svn://10.65.10.50/trunk@14148 c028cbd2-c16b-5b4b-a496-9718f37d4682
1500 lines
35 KiB
C
Executable File
1500 lines
35 KiB
C
Executable File
/*---------------------------------------------------------------------------*
|
|
| PDFlib - A library for generating PDF on the fly |
|
|
+---------------------------------------------------------------------------+
|
|
| Copyright (c) 1997-2005 Thomas Merz and PDFlib GmbH. All rights reserved. |
|
|
+---------------------------------------------------------------------------+
|
|
| |
|
|
| This software is subject to the PDFlib license. It is NOT in the |
|
|
| public domain. Extended versions and commercial licenses are |
|
|
| available, please check http://www.pdflib.com. |
|
|
| |
|
|
*---------------------------------------------------------------------------*/
|
|
|
|
/* $Id: pc_core.c,v 1.2 2006-07-11 13:10:33 alex Exp $
|
|
*
|
|
* PDFlib core services
|
|
*
|
|
*/
|
|
|
|
#include "pc_util.h"
|
|
|
|
#define PDF_NonfatalError 11
|
|
#define PDF_UnknownError 12
|
|
|
|
#if defined(__ia64__) && defined (__linux__)
|
|
#define PDC_ALIGN16
|
|
#endif
|
|
|
|
|
|
/* TODO: how to make this dynamic?
|
|
** exception during pdc_core_init():
|
|
** - out of memory in pdc_sb_new()
|
|
** exception during exception:
|
|
** - out of memory in pdc_sb_vprintf()
|
|
** - format error in pdc_sb_vprintf()
|
|
*/
|
|
#define PDC_ERRPARM_SIZE 2048
|
|
#define PDC_ERRBUF_SIZE (5 * PDC_ERRPARM_SIZE)
|
|
#define PDC_XSTACK_INISIZE 10
|
|
|
|
#define PDC_CLASSLIST_SIZE 32
|
|
|
|
#define N_ERRTABS (PDC_ET_LAST / 1000)
|
|
|
|
/* temporary free store.
|
|
*/
|
|
typedef struct
|
|
{
|
|
void * mem;
|
|
pdc_destructor destr;
|
|
void * opaque;
|
|
} pdc_tmpmem;
|
|
|
|
typedef struct
|
|
{
|
|
pdc_tmpmem * tmpmem;
|
|
int capacity;
|
|
int size;
|
|
} pdc_tmpmem_list;
|
|
|
|
static void pdc_tmlist_init(pdc_tmpmem_list *tm_list);
|
|
static void pdc_tmlist_cleanup(pdc_core *pdc, pdc_tmpmem_list *tm_list);
|
|
|
|
|
|
/* exception handling frame.
|
|
*/
|
|
typedef struct
|
|
{
|
|
pdc_jmpbuf jbuf;
|
|
} pdc_xframe;
|
|
|
|
typedef struct
|
|
{
|
|
pdc_error_info * ei;
|
|
int n_entries;
|
|
} error_table;
|
|
|
|
|
|
/* ------------------------ the core core structure ---------------------- */
|
|
|
|
struct pdc_core_s {
|
|
/* ------------ try/catch ------------ */
|
|
pdc_xframe * x_stack;
|
|
#ifdef PDC_ALIGN16
|
|
char * x_alias;
|
|
#endif
|
|
int x_ssize;
|
|
int x_sp; /* exception stack pointer */
|
|
|
|
/* ------------ error handling ------------ */
|
|
pdc_bool warnings_enabled;
|
|
pdc_bool in_error;
|
|
char errbuf[PDC_ERRBUF_SIZE];
|
|
char errparms[4][PDC_ERRPARM_SIZE];
|
|
int epcount;
|
|
int errnum;
|
|
pdc_bool x_thrown; /* exception thrown and not caught */
|
|
char * apiname;
|
|
pdc_error_fp errorhandler; /* client error handler */
|
|
void * opaque; /* client specific, opaque data */
|
|
|
|
error_table err_tables[N_ERRTABS];
|
|
|
|
/* ------------------ tracing ---------------- */
|
|
pdc_bool tracestatus; /* trace status */
|
|
/* = pdc_undef: new file
|
|
* = pdc_true: enabled
|
|
* = pdc_false: disabled */
|
|
char * tracefilename; /* name of the trace file */
|
|
pdc_bool traceflush; /* trace file will be opened and
|
|
* and closed immediately */
|
|
FILE * tracefp; /* traceflush = false: file handle */
|
|
pdc_strform_kind tracestrform; /* format for trace strings */
|
|
int tracemaxchar; /* maximal number of characters
|
|
* of trace strings */
|
|
char traceclasslist[PDC_CLASSLIST_SIZE];
|
|
/* list of levels for logging classes.
|
|
* Index 0 - 9: reserved for pdcore.
|
|
* (see enum pdc_protocol_class)
|
|
* Index 10 - 63: reserved for client.
|
|
*/
|
|
pdc_bool traceclassapi; /* only api class has level > 0 */
|
|
int floatdigits; /* floating point output precision */
|
|
#ifdef PDC_DEBUG
|
|
pdc_bool hexdump; /* hexdump feature enabled? */
|
|
#endif /* PDC_DEBUG */
|
|
|
|
/* ------------ memory management ------------ */
|
|
pdc_alloc_fp allocproc;
|
|
pdc_realloc_fp reallocproc;
|
|
pdc_free_fp freeproc;
|
|
pdc_tmpmem_list tm_list;
|
|
|
|
/* ------------ encoding handling ------------ */
|
|
void * pglyphtab; /* private glyph table */
|
|
};
|
|
|
|
|
|
|
|
/* ----------- default memory management & error handling ----------- */
|
|
|
|
static void *
|
|
default_malloc(void *opaque, size_t size, const char *caller)
|
|
{
|
|
(void) opaque;
|
|
(void) caller;
|
|
|
|
return malloc(size);
|
|
}
|
|
|
|
static void *
|
|
default_realloc(void *opaque, void *mem, size_t size, const char *caller)
|
|
{
|
|
(void) opaque;
|
|
(void) caller;
|
|
|
|
return realloc(mem, size);
|
|
}
|
|
|
|
static void
|
|
default_free(void *opaque, void *mem)
|
|
{
|
|
(void) opaque;
|
|
|
|
free(mem);
|
|
}
|
|
|
|
static void
|
|
default_errorhandler(void *opaque, int errnum, const char *msg)
|
|
{
|
|
(void) opaque;
|
|
|
|
if (errnum == PDF_NonfatalError)
|
|
{
|
|
fprintf(stderr, "PDFlib warning (ignored): %s\n", msg);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "PDFlib exception (fatal): %s\n", msg);
|
|
exit(99);
|
|
}
|
|
}
|
|
|
|
pdc_bool
|
|
pdc_enter_api(pdc_core *pdc, const char *apiname, int flags)
|
|
{
|
|
char *name = NULL;
|
|
|
|
if (pdc->in_error)
|
|
return pdc_false;
|
|
|
|
if (flags & PDC_ET_NOPREFIX)
|
|
name = strchr(apiname, '_');
|
|
if (name)
|
|
name++;
|
|
else
|
|
name = (char *) apiname;
|
|
|
|
if (pdc->apiname)
|
|
pdc_free(pdc, pdc->apiname);
|
|
pdc->apiname = pdc_strdup(pdc, name);
|
|
|
|
if (flags & PDC_ET_NOSUFFIX)
|
|
{
|
|
size_t len = strlen(pdc->apiname);
|
|
len--;
|
|
if (len && pdc->apiname[len] == '2')
|
|
pdc->apiname[len] = 0;
|
|
}
|
|
|
|
pdc->errnum = 0;
|
|
return pdc_true;
|
|
}
|
|
|
|
void
|
|
pdc_set_warnings(pdc_core *pdc, pdc_bool on)
|
|
{
|
|
pdc->warnings_enabled = on;
|
|
}
|
|
|
|
pdc_bool
|
|
pdc_in_error(pdc_core *pdc)
|
|
{
|
|
return pdc->in_error;
|
|
}
|
|
|
|
|
|
/* --------------------- error table management --------------------- */
|
|
|
|
static pdc_error_info core_errors[] =
|
|
{
|
|
#define pdc_genInfo 1
|
|
#include "pc_generr.h"
|
|
};
|
|
|
|
#define N_CORE_ERRORS (sizeof core_errors / sizeof (pdc_error_info))
|
|
|
|
|
|
static void
|
|
pdc_panic(pdc_core *pdc, const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
vsprintf(pdc->errbuf, fmt, ap);
|
|
va_end(ap);
|
|
|
|
pdc->errnum = PDF_UnknownError;
|
|
(*pdc->errorhandler)(pdc->opaque, pdc->errnum, pdc->errbuf);
|
|
} /* pdc_panic */
|
|
|
|
|
|
static void
|
|
check_parms(pdc_core *pdc, pdc_error_info *ei)
|
|
{
|
|
const char *msg = ei->errmsg;
|
|
const char *dollar;
|
|
|
|
while ((dollar = strchr(msg, '$')) != (char *) 0)
|
|
{
|
|
if (isdigit((int) dollar[1]))
|
|
{
|
|
int n = dollar[1] - '0';
|
|
|
|
if (ei->nparms < n || n < 1)
|
|
pdc_panic(pdc, "illegal parameter '$%d' in error message %d",
|
|
n, ei->errnum);
|
|
}
|
|
else if (dollar[1] != '$')
|
|
{
|
|
pdc_panic(pdc,
|
|
"illegal '$' in error message %d", ei->errnum);
|
|
}
|
|
|
|
msg = dollar + 1;
|
|
}
|
|
} /* check_parms */
|
|
|
|
|
|
void
|
|
pdc_register_errtab(pdc_core *pdc, int et, pdc_error_info *ei, int n_entries)
|
|
{
|
|
int i;
|
|
int n = (et / 1000) - 1;
|
|
|
|
if (n < 0 || N_ERRTABS <= n || et % 1000 != 0)
|
|
pdc_panic(pdc, "tried to register unknown error table %d", et);
|
|
|
|
/* ignore multiple registrations of the same table.
|
|
*/
|
|
if (pdc->err_tables[n].ei != (pdc_error_info *) 0)
|
|
return;
|
|
|
|
pdc->err_tables[n].ei = ei;
|
|
pdc->err_tables[n].n_entries = n_entries;
|
|
|
|
check_parms(pdc, &ei[0]);
|
|
|
|
for (i = 1; i < n_entries; ++i)
|
|
{
|
|
if (ei[i].errnum <= ei[i-1].errnum)
|
|
{
|
|
pdc_panic(pdc,
|
|
"duplicate or misplaced error number %d", ei[i].errnum);
|
|
}
|
|
|
|
/* an error table may span several blocks.
|
|
*/
|
|
if ((ei[i].errnum / 1000) - 1 > n)
|
|
{
|
|
pdc->err_tables[n].n_entries = i; /* correct old block size */
|
|
|
|
n = (ei[i].errnum / 1000) - 1; /* new block number */
|
|
|
|
if (N_ERRTABS <= n)
|
|
pdc_panic(pdc, "invalid error number %d", ei[i].errnum);
|
|
|
|
ei += i; /* start of new block */
|
|
n_entries -= i; /* size of new block */
|
|
i = 0;
|
|
pdc->err_tables[n].ei = ei;
|
|
pdc->err_tables[n].n_entries = n_entries;
|
|
}
|
|
|
|
check_parms(pdc, &ei[i]);
|
|
}
|
|
} /* pdc_register_errtab */
|
|
|
|
|
|
/* pdc_init_core() never throws exceptions.
|
|
** it returns NULL if there's not enough memory.
|
|
*/
|
|
pdc_core *
|
|
pdc_init_core(
|
|
pdc_error_fp errorhandler,
|
|
pdc_alloc_fp allocproc,
|
|
pdc_realloc_fp reallocproc,
|
|
pdc_free_fp freeproc,
|
|
void *opaque)
|
|
{
|
|
static const char fn[] = "pdc_init_core";
|
|
|
|
pdc_core *pdc;
|
|
int i;
|
|
|
|
/* if allocproc is NULL, we use pdc's default memory handling.
|
|
*/
|
|
if (allocproc == (pdc_alloc_fp) 0)
|
|
{
|
|
allocproc = default_malloc;
|
|
reallocproc = default_realloc;
|
|
freeproc = default_free;
|
|
}
|
|
|
|
if (errorhandler == (pdc_error_fp) 0)
|
|
errorhandler = default_errorhandler;
|
|
|
|
pdc = (pdc_core *) (*allocproc)(opaque, sizeof (pdc_core), fn);
|
|
|
|
if (pdc == (pdc_core *) 0)
|
|
return (pdc_core *) 0;
|
|
|
|
pdc->errorhandler = errorhandler;
|
|
pdc->allocproc = allocproc;
|
|
pdc->reallocproc = reallocproc;
|
|
pdc->freeproc = freeproc;
|
|
pdc->opaque = opaque;
|
|
|
|
pdc->tracestatus = pdc_undef;
|
|
pdc->tracefilename = NULL;
|
|
pdc->traceflush = pdc_true;
|
|
pdc->tracefp = NULL;
|
|
pdc->tracestrform = strform_readable;
|
|
pdc->tracemaxchar = 0;
|
|
memset(pdc->traceclasslist, 0, PDC_CLASSLIST_SIZE);
|
|
pdc->traceclasslist[trc_api] = 1;
|
|
pdc->traceclassapi = pdc_true;
|
|
|
|
pdc->floatdigits = 4;
|
|
#ifdef PDC_DEBUG
|
|
pdc->hexdump = pdc_true;
|
|
#endif
|
|
|
|
/* initialize error & exception handling.
|
|
*/
|
|
pdc->warnings_enabled = pdc_true;
|
|
pdc->in_error = pdc_false;
|
|
pdc->x_thrown = pdc_false;
|
|
pdc->epcount = 0;
|
|
pdc->errnum = 0;
|
|
pdc->apiname = NULL;
|
|
pdc->x_sp = -1;
|
|
pdc->x_ssize = PDC_XSTACK_INISIZE;
|
|
|
|
#ifdef PDC_ALIGN16
|
|
pdc->x_alias = (char *)
|
|
(*allocproc)(opaque, 16 + pdc->x_ssize * sizeof (pdc_xframe), fn);
|
|
|
|
if (pdc->x_alias == (char *) 0)
|
|
pdc->x_stack = (pdc_xframe *) 0;
|
|
else
|
|
pdc->x_stack = (pdc_xframe *)
|
|
(((unsigned long) pdc->x_alias + 16) & 0xFFFFFFFFFFFFFFF0);
|
|
#else
|
|
pdc->x_stack = (pdc_xframe *)
|
|
(*allocproc)(opaque, pdc->x_ssize * sizeof (pdc_xframe), fn);
|
|
#endif
|
|
|
|
if (pdc->x_stack == (pdc_xframe *) 0)
|
|
{
|
|
(*freeproc)(opaque, pdc);
|
|
return (pdc_core *) 0;
|
|
}
|
|
|
|
pdc_tmlist_init(&pdc->tm_list);
|
|
|
|
/* initialize error tables.
|
|
*/
|
|
for (i = 0; i < N_ERRTABS; ++i)
|
|
pdc->err_tables[i].ei = (pdc_error_info *) 0;
|
|
|
|
pdc_register_errtab(pdc, PDC_ET_CORE, core_errors, N_CORE_ERRORS);
|
|
|
|
|
|
/* initialize private glyph table */
|
|
pdc->pglyphtab = NULL;
|
|
|
|
return pdc;
|
|
}
|
|
|
|
void
|
|
pdc_delete_core(pdc_core *pdc)
|
|
{
|
|
pdc_time ltime;
|
|
|
|
pdc_localtime(<ime);
|
|
pdc_trace(pdc, "[%04d-%02d-%02d %02d:%02d:%02d]\n",
|
|
ltime.year + 1900, ltime.month + 1, ltime.mday,
|
|
ltime.hour, ltime.minute, ltime.second);
|
|
|
|
if (pdc->apiname)
|
|
pdc_free(pdc, pdc->apiname);
|
|
|
|
pdc_tmlist_cleanup(pdc, &pdc->tm_list);
|
|
|
|
if (pdc->tm_list.capacity != 0)
|
|
pdc_free(pdc, pdc->tm_list.tmpmem);
|
|
|
|
#ifdef PDC_ALIGN16
|
|
pdc_free(pdc, pdc->x_alias);
|
|
#else
|
|
pdc_free(pdc, pdc->x_stack);
|
|
#endif
|
|
|
|
pdc_cleanup_pglyphtab(pdc);
|
|
pdc->pglyphtab = NULL;
|
|
|
|
if (pdc->tracefp != NULL && pdc->tracefp != stdout && pdc->tracefp !=stderr)
|
|
fclose(pdc->tracefp);
|
|
pdc->tracefp = NULL;
|
|
if (pdc->tracefilename)
|
|
pdc_free(pdc, pdc->tracefilename);
|
|
pdc->tracefilename = NULL;
|
|
pdc->tracestatus = pdc_false;
|
|
|
|
pdc_free(pdc, pdc);
|
|
}
|
|
|
|
/* --------------------------- memory management --------------------------- */
|
|
|
|
void *
|
|
pdc_malloc(pdc_core *pdc, size_t size, const char *caller)
|
|
{
|
|
void *ret;
|
|
|
|
/* the behavior of malloc(0) is undefined in ANSI C, and may
|
|
* result in a NULL pointer return value which makes PDFlib bail out.
|
|
*/
|
|
if (size == (size_t) 0 || (long) size < 0L) {
|
|
size = (size_t) 1;
|
|
pdc_warning(pdc, PDC_E_INT_ALLOC0, caller, 0, 0, 0);
|
|
}
|
|
|
|
if ((ret = (*pdc->allocproc)(pdc->opaque, size, caller)) == (void *) 0)
|
|
{
|
|
pdc_error(pdc, PDC_E_MEM_OUT, caller, 0, 0, 0);
|
|
}
|
|
|
|
pdc_trace_protocol(pdc, 1, trc_memory,
|
|
"\t%p malloced, size=%d, called from \"%s\"\n",
|
|
ret, size, caller);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* We cook up our own calloc routine, using the caller-supplied
|
|
* malloc and memset.
|
|
*/
|
|
void *
|
|
pdc_calloc(pdc_core *pdc, size_t size, const char *caller)
|
|
{
|
|
void *ret;
|
|
|
|
if (size == (size_t) 0 || (long) size < 0L) {
|
|
size = (size_t) 1;
|
|
pdc_warning(pdc, PDC_E_INT_ALLOC0, caller, 0, 0, 0);
|
|
}
|
|
|
|
if ((ret = (*pdc->allocproc)(pdc->opaque, size, caller)) == (void *) 0)
|
|
{
|
|
pdc_error(pdc, PDC_E_MEM_OUT, caller, 0, 0, 0);
|
|
}
|
|
|
|
pdc_trace_protocol(pdc, 1, trc_memory,
|
|
"\t%p calloced, size=%d, called from \"%s\"\n",
|
|
ret, size, caller);
|
|
|
|
memset(ret, 0, size);
|
|
return ret;
|
|
}
|
|
|
|
void *
|
|
pdc_realloc(pdc_core *pdc, void *mem, size_t size, const char *caller)
|
|
{
|
|
void *ret;
|
|
|
|
if (size == (size_t) 0 || (long) size < 0L) {
|
|
size = (size_t) 1;
|
|
pdc_warning(pdc, PDC_E_INT_ALLOC0, caller, 0, 0, 0);
|
|
}
|
|
|
|
if ((ret = (*pdc->reallocproc)(pdc->opaque, mem, size, caller))
|
|
== (void *) 0)
|
|
pdc_error(pdc, PDC_E_MEM_OUT, caller, 0, 0, 0);
|
|
|
|
pdc_trace_protocol(pdc, 1, trc_memory,
|
|
"\t%p realloced to\n"
|
|
"\t%p new, size=%d, called from \"%s\"\n",
|
|
mem, ret, size, caller);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void
|
|
pdc_free(pdc_core *pdc, void *mem)
|
|
{
|
|
pdc_trace_protocol(pdc, 1, trc_memory, "\t%p freed\n", mem);
|
|
|
|
/* just in case the freeproc() isn't that ANSI compatible...
|
|
*/
|
|
if (mem != NULL)
|
|
(*pdc->freeproc)(pdc->opaque, mem);
|
|
|
|
}
|
|
|
|
/* -------------------- temporary free store management -------------------- */
|
|
|
|
static void
|
|
pdc_tmlist_init(pdc_tmpmem_list *tm_list)
|
|
{
|
|
tm_list->size = tm_list->capacity = 0;
|
|
}
|
|
|
|
static void
|
|
pdc_tmlist_grow(pdc_core *pdc, pdc_tmpmem_list *tm_list)
|
|
{
|
|
static const char fn[] = "pdc_tmlist_grow";
|
|
static const int chunksize = 20;
|
|
|
|
if (tm_list->capacity == 0)
|
|
{
|
|
tm_list->capacity = chunksize;
|
|
tm_list->tmpmem = (pdc_tmpmem *) pdc_malloc(pdc,
|
|
(size_t) (tm_list->capacity * sizeof (pdc_tmpmem)), fn);
|
|
}
|
|
else
|
|
{
|
|
tm_list->capacity += chunksize;
|
|
tm_list->tmpmem = (pdc_tmpmem *) pdc_realloc(pdc, tm_list->tmpmem,
|
|
(size_t) (tm_list->capacity * sizeof (pdc_tmpmem)), fn);
|
|
}
|
|
}
|
|
|
|
static void
|
|
pdc_tmlist_cleanup(pdc_core *pdc, pdc_tmpmem_list *tm_list)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < tm_list->size; ++i)
|
|
{
|
|
if (tm_list->tmpmem[i].destr)
|
|
tm_list->tmpmem[i].destr(pdc, tm_list->tmpmem[i].mem);
|
|
|
|
pdc_free(pdc, tm_list->tmpmem[i].mem);
|
|
}
|
|
|
|
tm_list->size = 0;
|
|
}
|
|
|
|
void
|
|
pdc_insert_mem_tmp(
|
|
pdc_core * pdc,
|
|
void * memory,
|
|
void * opaque,
|
|
pdc_destructor destr)
|
|
{
|
|
pdc_tmpmem_list *tm_list = &pdc->tm_list;
|
|
|
|
if (tm_list->size == tm_list->capacity)
|
|
pdc_tmlist_grow(pdc, tm_list);
|
|
|
|
tm_list->tmpmem[tm_list->size].mem = memory;
|
|
tm_list->tmpmem[tm_list->size].destr = destr;
|
|
tm_list->tmpmem[tm_list->size].opaque = opaque;
|
|
++tm_list->size;
|
|
}
|
|
|
|
void *
|
|
pdc_malloc_tmp(
|
|
pdc_core * pdc,
|
|
size_t size,
|
|
const char * caller,
|
|
void * opaque,
|
|
pdc_destructor destr)
|
|
{
|
|
void *memory = pdc_malloc(pdc, size, caller);
|
|
|
|
pdc_insert_mem_tmp(pdc, memory, opaque, destr);
|
|
|
|
return memory;
|
|
}
|
|
|
|
void *
|
|
pdc_calloc_tmp(
|
|
pdc_core * pdc,
|
|
size_t size,
|
|
const char * caller,
|
|
void * opaque,
|
|
pdc_destructor destr)
|
|
{
|
|
void *memory = pdc_calloc(pdc, size, caller);
|
|
|
|
pdc_insert_mem_tmp(pdc, memory, opaque, destr);
|
|
|
|
return memory;
|
|
}
|
|
|
|
void *
|
|
pdc_realloc_tmp(pdc_core *pdc, void *mem, size_t size, const char *caller)
|
|
{
|
|
int i;
|
|
pdc_tmpmem_list *tm_list = &pdc->tm_list;
|
|
|
|
for (i = tm_list->size - 1; 0 <= i; --i)
|
|
if (tm_list->tmpmem[i].mem == mem)
|
|
return tm_list->tmpmem[i].mem = pdc_realloc(pdc, mem, size, caller);
|
|
|
|
pdc_error(pdc, PDC_E_INT_REALLOC_TMP, caller, 0, 0, 0);
|
|
return (void *) 0;
|
|
}
|
|
|
|
void
|
|
pdc_free_tmp(pdc_core *pdc, void *mem)
|
|
{
|
|
int i, j;
|
|
pdc_tmpmem_list *tm_list = &pdc->tm_list;
|
|
|
|
/* we search the list backwards since chances are good
|
|
** that the most recently allocated items are freed first.
|
|
*/
|
|
for (i = tm_list->size - 1; 0 <= i; --i)
|
|
{
|
|
if (tm_list->tmpmem[i].mem == mem)
|
|
{
|
|
if (tm_list->tmpmem[i].destr)
|
|
tm_list->tmpmem[i].destr(
|
|
tm_list->tmpmem[i].opaque, tm_list->tmpmem[i].mem);
|
|
|
|
pdc_free(pdc, tm_list->tmpmem[i].mem);
|
|
tm_list->tmpmem[i].mem = (void *) 0;
|
|
|
|
--tm_list->size;
|
|
for (j = i; j < tm_list->size; j++)
|
|
tm_list->tmpmem[j] = tm_list->tmpmem[j + 1];
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
pdc_error(pdc, PDC_E_INT_FREE_TMP, 0, 0, 0, 0);
|
|
}
|
|
|
|
|
|
/* --------------------------- exception handling --------------------------- */
|
|
|
|
const char *pdc_errprintf(pdc_core *pdc, const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
if (pdc->epcount < 0 || pdc->epcount > 3)
|
|
pdc->epcount = 0;
|
|
|
|
va_start(ap, fmt);
|
|
vsprintf(pdc->errparms[pdc->epcount], fmt, ap);
|
|
va_end(ap);
|
|
|
|
return pdc->errparms[pdc->epcount++];
|
|
}
|
|
|
|
static pdc_error_info *
|
|
get_error_info(pdc_core *pdc, int errnum)
|
|
{
|
|
int n = (errnum / 1000) - 1;
|
|
|
|
if (0 <= n && n < N_ERRTABS && pdc->err_tables[n].ei != 0)
|
|
{
|
|
error_table *etab = &pdc->err_tables[n];
|
|
int i;
|
|
|
|
/* LATER: binary search. */
|
|
for (i = 0; i < etab->n_entries; ++i)
|
|
{
|
|
if (etab->ei[i].errnum == errnum)
|
|
return &etab->ei[i];
|
|
}
|
|
}
|
|
|
|
pdc_panic(pdc, "Internal error: unknown error number %d", errnum);
|
|
|
|
return (pdc_error_info *) 0; /* for the compiler */
|
|
} /* get_error_info */
|
|
|
|
|
|
static void
|
|
make_errmsg(
|
|
pdc_core * pdc,
|
|
pdc_error_info * ei,
|
|
const char * parm1,
|
|
const char * parm2,
|
|
const char * parm3,
|
|
const char * parm4)
|
|
{
|
|
const char *src = ei->ce_msg ? ei->ce_msg : ei->errmsg;
|
|
char * dst = pdc->errbuf;
|
|
const char *dollar;
|
|
|
|
pdc->epcount = 0;
|
|
|
|
/* copy *src to *dst, replacing "$N" with *parmN.
|
|
*/
|
|
while ((dollar = strchr(src, '$')) != (char *) 0)
|
|
{
|
|
const char *parm = (const char *) 0;
|
|
|
|
memcpy(dst, src, (size_t) (dollar - src));
|
|
dst += dollar - src;
|
|
src = dollar + 1;
|
|
|
|
switch (*src)
|
|
{
|
|
case '1': parm = (parm1 ? parm1 : "?"); break;
|
|
case '2': parm = (parm2 ? parm2 : "?"); break;
|
|
case '3': parm = (parm3 ? parm3 : "?"); break;
|
|
case '4': parm = (parm4 ? parm4 : "?"); break;
|
|
|
|
case 0: break;
|
|
|
|
default: *(dst++) = *(src++);
|
|
break;
|
|
}
|
|
|
|
if (parm != (const char *) 0)
|
|
{
|
|
++src;
|
|
strcpy(dst, parm);
|
|
dst += strlen(parm);
|
|
}
|
|
}
|
|
|
|
strcpy(dst, src);
|
|
} /* make_errmsg */
|
|
|
|
|
|
void
|
|
pdc_set_errmsg(
|
|
pdc_core * pdc,
|
|
int errnum,
|
|
const char *parm1,
|
|
const char *parm2,
|
|
const char *parm3,
|
|
const char *parm4)
|
|
{
|
|
pdc_error_info *ei = get_error_info(pdc, errnum);
|
|
|
|
make_errmsg(pdc, ei, parm1, parm2, parm3, parm4);
|
|
pdc->errnum = errnum;
|
|
|
|
pdc_trace_protocol(pdc, 1, trc_warning,
|
|
"\tError %d: \"%s\"\n", pdc->errnum, pdc->errbuf);
|
|
} /* pdc_set_errmsg */
|
|
|
|
|
|
void
|
|
pdc_error(
|
|
pdc_core * pdc,
|
|
int errnum,
|
|
const char *parm1,
|
|
const char *parm2,
|
|
const char *parm3,
|
|
const char *parm4)
|
|
{
|
|
if (pdc->in_error) /* avoid recursive errors. */
|
|
return;
|
|
else
|
|
{
|
|
pdc->in_error = pdc_true;
|
|
pdc->x_thrown = pdc_true;
|
|
}
|
|
|
|
if (errnum != -1)
|
|
{
|
|
pdc_error_info *ei = get_error_info(pdc, errnum);
|
|
|
|
make_errmsg(pdc, ei, parm1, parm2, parm3, parm4);
|
|
pdc->errnum = errnum;
|
|
}
|
|
|
|
pdc_trace(pdc, "\n[+++ Exception %d in %s, %s +++]\n",
|
|
pdc->errnum, (pdc->errnum == 0 || !pdc->apiname) ? "" : pdc->apiname,
|
|
(pdc->x_sp == -1 ? "Error handler active" : "try/catch active"));
|
|
pdc_trace(pdc, "[\"%s\"]\n\n", pdc->errbuf);
|
|
|
|
if (pdc->x_sp == -1)
|
|
{
|
|
char errbuf[PDC_ERRBUF_SIZE];
|
|
|
|
sprintf(errbuf, "[%d] %s: %s",
|
|
pdc->errnum, pdc_get_apiname(pdc), pdc->errbuf);
|
|
|
|
pdc->errorhandler(pdc->opaque, PDF_UnknownError, errbuf);
|
|
|
|
/*
|
|
* The error handler must never return. If it does, it is severely
|
|
* broken. We cannot remedy this, so we exit.
|
|
*/
|
|
exit(99);
|
|
|
|
}
|
|
else
|
|
{
|
|
longjmp(pdc->x_stack[pdc->x_sp].jbuf.jbuf, 1);
|
|
}
|
|
|
|
} /* pdc_error */
|
|
|
|
|
|
void
|
|
pdc_warning(
|
|
pdc_core * pdc,
|
|
int errnum,
|
|
const char *parm1,
|
|
const char *parm2,
|
|
const char *parm3,
|
|
const char *parm4)
|
|
{
|
|
if (pdc->in_error)
|
|
return;
|
|
|
|
if (pdc->warnings_enabled == pdc_false)
|
|
{
|
|
if (pdc_trace_protocol_is_enabled(pdc, 1, trc_warning))
|
|
{
|
|
if (errnum != -1)
|
|
{
|
|
pdc_error_info *ei = get_error_info(pdc, errnum);
|
|
|
|
make_errmsg(pdc, ei, parm1, parm2, parm3, parm4);
|
|
pdc->errnum = errnum;
|
|
}
|
|
|
|
pdc_trace(pdc, "\tWarning %d: \"%s\"\n", pdc->errnum, pdc->errbuf);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
pdc->in_error = pdc_true;
|
|
pdc->x_thrown = pdc_true;
|
|
|
|
if (errnum != -1)
|
|
{
|
|
pdc_error_info *ei = get_error_info(pdc, errnum);
|
|
|
|
make_errmsg(pdc, ei, parm1, parm2, parm3, parm4);
|
|
pdc->errnum = errnum;
|
|
}
|
|
|
|
pdc_trace(pdc, "\n[+++ Warning %d in %s, %s +++]\n",
|
|
pdc->errnum, (pdc->errnum == 0 || !pdc->apiname) ? "" : pdc->apiname,
|
|
(pdc->x_sp == -1 ? "Error handler active" : "try/catch active"));
|
|
pdc_trace(pdc, "[\"%s\"]\n\n", pdc->errbuf);
|
|
|
|
if (pdc->x_sp == -1)
|
|
{
|
|
char errbuf[PDC_ERRBUF_SIZE];
|
|
|
|
sprintf(errbuf, "[%d] %s: %s",
|
|
pdc->errnum, pdc_get_apiname(pdc), pdc->errbuf);
|
|
|
|
(*pdc->errorhandler)(pdc->opaque, PDF_NonfatalError, errbuf);
|
|
}
|
|
else
|
|
{
|
|
longjmp(pdc->x_stack[pdc->x_sp].jbuf.jbuf, 1);
|
|
}
|
|
|
|
/* a client-supplied error handler may return after a warning */
|
|
pdc->in_error = pdc_false;
|
|
|
|
} /* pdc_warning */
|
|
|
|
|
|
pdc_jmpbuf *
|
|
pdc_jbuf(pdc_core *pdc)
|
|
{
|
|
static const char fn[] = "pdc_jbuf";
|
|
|
|
if (++pdc->x_sp == pdc->x_ssize)
|
|
{
|
|
pdc_xframe *aux;
|
|
|
|
#ifdef PDC_ALIGN16
|
|
char *cp = (char *) (*pdc->allocproc)(pdc->opaque,
|
|
16 + 2 * pdc->x_ssize * sizeof (pdc_xframe), fn);
|
|
|
|
if (cp == (char *) 0)
|
|
{
|
|
aux = (pdc_xframe *) 0;
|
|
}
|
|
else
|
|
{
|
|
pdc_free(pdc, pdc->x_alias);
|
|
pdc->x_alias = cp;
|
|
aux = (pdc_xframe *)
|
|
(((unsigned long) cp + 16) & 0xFFFFFFFFFFFFFFF0);
|
|
|
|
memcpy(aux, pdc->x_stack, pdc->x_ssize * sizeof (pdc_xframe));
|
|
}
|
|
#else
|
|
aux = (pdc_xframe *) (*pdc->reallocproc)(
|
|
pdc->opaque, pdc->x_stack,
|
|
2 * pdc->x_ssize * sizeof (pdc_xframe), fn);
|
|
#endif
|
|
|
|
if (aux == (pdc_xframe *) 0)
|
|
{
|
|
--pdc->x_sp;
|
|
pdc->x_thrown = pdc_true;
|
|
pdc->in_error = pdc_true;
|
|
|
|
pdc->errnum = PDC_E_MEM_OUT;
|
|
if (pdc->apiname)
|
|
pdc_free(pdc, pdc->apiname);
|
|
pdc->apiname = NULL;
|
|
sprintf(pdc->errbuf,
|
|
"Out of memory in TRY function (nesting level: %d)",
|
|
pdc->x_sp + 1);
|
|
|
|
longjmp(pdc->x_stack[pdc->x_sp].jbuf.jbuf, 1);
|
|
}
|
|
|
|
pdc->x_stack = aux;
|
|
pdc->x_ssize *= 2;
|
|
}
|
|
|
|
pdc->x_thrown = pdc_false;
|
|
return &pdc->x_stack[pdc->x_sp].jbuf;
|
|
} /* pdc_jbuf */
|
|
|
|
void
|
|
pdc_exit_try(pdc_core *pdc)
|
|
{
|
|
if (pdc->x_sp == -1)
|
|
{
|
|
strcpy(pdc->errbuf, "exception stack underflow");
|
|
pdc->errnum = PDC_E_INT_XSTACK;
|
|
(*pdc->errorhandler)(pdc->opaque, PDF_UnknownError, pdc->errbuf);
|
|
}
|
|
else
|
|
--pdc->x_sp;
|
|
} /* pdc_exit_try */
|
|
|
|
int
|
|
pdc_catch_intern(pdc_core *pdc)
|
|
{
|
|
pdc_bool result;
|
|
|
|
if (pdc->x_sp == -1)
|
|
{
|
|
strcpy(pdc->errbuf, "exception stack underflow");
|
|
pdc->errnum = PDC_E_INT_XSTACK;
|
|
(*pdc->errorhandler)(pdc->opaque, PDF_UnknownError, pdc->errbuf);
|
|
}
|
|
else
|
|
--pdc->x_sp;
|
|
|
|
result = pdc->x_thrown;
|
|
pdc->in_error = pdc_false;
|
|
pdc->x_thrown = pdc_false;
|
|
|
|
return result;
|
|
} /* pdc_catch_intern */
|
|
|
|
int
|
|
pdc_catch_extern(pdc_core *pdc)
|
|
{
|
|
pdc_bool result;
|
|
|
|
if (pdc->x_sp == -1)
|
|
{
|
|
strcpy(pdc->errbuf, "exception stack underflow");
|
|
pdc->errnum = PDC_E_INT_XSTACK;
|
|
(*pdc->errorhandler)(pdc->opaque, PDF_UnknownError, pdc->errbuf);
|
|
}
|
|
else
|
|
--pdc->x_sp;
|
|
|
|
result = pdc->x_thrown;
|
|
pdc->x_thrown = pdc_false;
|
|
|
|
return result;
|
|
} /* pdc_catch_extern */
|
|
|
|
void
|
|
pdc_rethrow(pdc_core *pdc)
|
|
{
|
|
pdc_error(pdc, -1, 0, 0, 0, 0);
|
|
} /* pdc_rethrow */
|
|
|
|
|
|
int
|
|
pdc_get_errnum(pdc_core *pdc)
|
|
{
|
|
return pdc->errnum;
|
|
}
|
|
|
|
const char *
|
|
pdc_get_errmsg(pdc_core *pdc)
|
|
{
|
|
return (pdc->errnum == 0) ? "" : pdc->errbuf;
|
|
}
|
|
|
|
const char *
|
|
pdc_get_apiname(pdc_core *pdc)
|
|
{
|
|
return (pdc->errnum == 0 || !pdc->apiname) ? "" : pdc->apiname;
|
|
}
|
|
|
|
|
|
/* --------------------------- debug trace --------------------------- */
|
|
|
|
void
|
|
pdc_set_tracefile(pdc_core *pdc, const char *filename)
|
|
{
|
|
if (!filename || !*filename)
|
|
return;
|
|
|
|
if (pdc->tracefilename)
|
|
pdc_free(pdc, pdc->tracefilename);
|
|
|
|
pdc->tracefilename = pdc_strdup(pdc, filename);
|
|
pdc->tracestatus = pdc_undef;
|
|
}
|
|
|
|
static const pdc_keyconn pdc_strform_keylist[] =
|
|
{
|
|
{"readable", strform_readable},
|
|
{"readable0", strform_readable0},
|
|
{"octal", strform_octal},
|
|
{"hex", strform_hexa},
|
|
{"java", strform_java},
|
|
{NULL, 0}
|
|
};
|
|
|
|
static const pdc_keyconn pdf_protoclass_keylist[] =
|
|
{
|
|
{"other", trc_other},
|
|
{"api", trc_api},
|
|
{"optlist", trc_optlist},
|
|
{"memory", trc_memory},
|
|
{"warning", trc_warning},
|
|
{"resource", trc_resource},
|
|
{"filesearch", trc_filesearch},
|
|
{"encoding", trc_encoding},
|
|
{"image", trc_image},
|
|
{"font", trc_font},
|
|
{NULL, 0}
|
|
};
|
|
|
|
static const pdc_defopt pdc_trace_options[] =
|
|
{
|
|
{"enable", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
|
|
0.0, 0.0, NULL},
|
|
|
|
{"disable", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
|
|
0.0, 0.0, NULL},
|
|
|
|
{"flush", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
|
|
0.0, 0.0, NULL},
|
|
|
|
{"remove", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
|
|
0.0, 0.0, NULL},
|
|
|
|
{"filename", pdc_stringlist, PDC_OPT_NONE, 1, 1,
|
|
0.0, 1024, NULL},
|
|
|
|
{"stringformat", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
|
|
0.0, 0.0, pdc_strform_keylist},
|
|
|
|
{"stringlimit", pdc_integerlist, PDC_OPT_NONE, 1, 1,
|
|
0.0, PDF_MAXSTRINGSIZE, NULL},
|
|
|
|
{"classes", pdc_stringlist, PDC_OPT_EVENNUM |PDC_OPT_SUBOPTLIST,
|
|
1, 2 * PDC_CLASSLIST_SIZE, 1.0, 64, NULL},
|
|
|
|
PDC_OPT_TERMINATE
|
|
};
|
|
|
|
pdc_bool
|
|
pdc_set_trace_options(pdc_core *pdc, const char *optlist)
|
|
{
|
|
pdc_resopt *resopts = NULL;
|
|
char **strlist, *keyword;
|
|
pdc_bool enable = pdc_true;
|
|
pdc_bool remfile = pdc_false;
|
|
pdc_char level;
|
|
int inum, i, pclass = 0, sumlevel = 0;
|
|
|
|
if (optlist && strlen(optlist))
|
|
{
|
|
resopts = pdc_parse_optionlist(pdc, optlist, pdc_trace_options,
|
|
NULL, pdc_true);
|
|
|
|
enable = pdc_true;
|
|
pdc_get_optvalues("enable", resopts, &enable, NULL);
|
|
if (pdc_get_optvalues("disable", resopts, &inum, NULL))
|
|
enable = !inum;
|
|
|
|
pdc_get_optvalues("flush", resopts, &pdc->traceflush, NULL);
|
|
|
|
pdc_get_optvalues("remove", resopts, &remfile, NULL);
|
|
|
|
if (pdc_get_optvalues("filename", resopts, NULL, &strlist))
|
|
pdc_set_tracefile(pdc, strlist[0]);
|
|
|
|
if (pdc_get_optvalues("stringformat", resopts, &inum, NULL))
|
|
pdc->tracestrform = (pdc_strform_kind) inum;
|
|
|
|
pdc_get_optvalues("stringlimit", resopts, &pdc->tracemaxchar, NULL);
|
|
|
|
inum = pdc_get_optvalues("classes", resopts, NULL, &strlist);
|
|
if (inum)
|
|
{
|
|
for (i = 0; i < inum; i++, i++)
|
|
{
|
|
if (!pdc_stricmp(strlist[i], "other"))
|
|
{
|
|
i++;
|
|
if (pdc_str2integer(strlist[i],
|
|
PDC_INT_CHAR | PDC_INT_UNSIGNED,
|
|
&level))
|
|
{
|
|
memset(pdc->traceclasslist, (int)level,
|
|
PDC_CLASSLIST_SIZE);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
for (i = 0; i < inum; i++)
|
|
{
|
|
keyword = strlist[i];
|
|
pclass = pdc_get_keycode_ci(keyword, pdf_protoclass_keylist);
|
|
if (pclass == PDC_KEY_NOTFOUND)
|
|
pdc_error(pdc, PDC_E_OPT_ILLKEYWORD,
|
|
"classes", keyword, 0, 0);
|
|
i++;
|
|
if (!pdc_str2integer(strlist[i],
|
|
PDC_INT_CHAR | PDC_INT_UNSIGNED,
|
|
&level))
|
|
pdc_error(pdc, PDC_E_OPT_ILLINTEGER,
|
|
keyword, strlist[i], 0, 0);
|
|
|
|
pdc->traceclasslist[pclass] = level;
|
|
}
|
|
|
|
for (i = 0; i < PDC_CLASSLIST_SIZE; i++)
|
|
sumlevel += (int) pdc->traceclasslist[i];
|
|
pdc->traceclassapi =
|
|
(sumlevel == 1 && pdc->traceclasslist[trc_api]) ?
|
|
pdc_true : pdc_false;
|
|
}
|
|
|
|
pdc_cleanup_optionlist(pdc, resopts);
|
|
}
|
|
|
|
if (!enable)
|
|
pdc_set_trace(pdc, NULL);
|
|
|
|
if (pdc->tracefp != NULL && pdc->tracefp != stdout && pdc->tracefp !=stderr)
|
|
fclose(pdc->tracefp);
|
|
pdc->tracefp = NULL;
|
|
|
|
if (enable)
|
|
{
|
|
if (pdc->tracefilename == NULL)
|
|
pdc->tracefilename = pdc_strdup(pdc, DEBUG_TRACE_FILE);
|
|
|
|
if (remfile && strcmp(pdc->tracefilename, "-"))
|
|
remove(pdc->tracefilename);
|
|
|
|
if (!pdc->traceflush)
|
|
{
|
|
if (!strcmp(pdc->tracefilename, "stdout"))
|
|
pdc->tracefp = stdout;
|
|
else if (!strcmp(pdc->tracefilename, "stderr"))
|
|
pdc->tracefp = stderr;
|
|
else
|
|
pdc->tracefp = fopen(pdc->tracefilename, APPENDMODE);
|
|
if (pdc->tracefp == NULL)
|
|
{
|
|
pdc->tracestatus = pdc_false;
|
|
pdc_error(pdc, PDC_E_IO_WROPEN, "log ", pdc->tracefilename,
|
|
0, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
return enable;
|
|
}
|
|
|
|
const char *
|
|
pdc_print_tracestring(pdc_core *pdc, const char *str, int len)
|
|
{
|
|
if (pdc->tracestatus == pdc_true)
|
|
return pdc_strprint(pdc, str, len, pdc->tracemaxchar,
|
|
pdc->tracestrform);
|
|
else
|
|
return "";
|
|
}
|
|
|
|
/* trace function without any class level check and decorations
|
|
*/
|
|
static void
|
|
pdc_trace_output(pdc_core *pdc, const char *fmt, va_list ap)
|
|
{
|
|
if (pdc->traceflush)
|
|
{
|
|
FILE *fp = NULL;
|
|
|
|
if (!strcmp(pdc->tracefilename, "stdout"))
|
|
fp = stdout;
|
|
else if (!strcmp(pdc->tracefilename, "stderr"))
|
|
fp = stderr;
|
|
else
|
|
fp = fopen(pdc->tracefilename, APPENDMODE);
|
|
|
|
if (fp == NULL)
|
|
{
|
|
pdc->tracestatus = pdc_false;
|
|
pdc_error(pdc, PDC_E_IO_WROPEN, "log ", pdc->tracefilename,
|
|
0, 0);
|
|
}
|
|
|
|
pdc_vfprintf(pdc, pdc_false, fp, fmt, ap);
|
|
|
|
if (fp != stdout && fp != stderr)
|
|
fclose(fp);
|
|
}
|
|
else
|
|
{
|
|
pdc_vfprintf(pdc, pdc_false, pdc->tracefp, fmt, ap);
|
|
fflush(pdc->tracefp);
|
|
}
|
|
}
|
|
|
|
void
|
|
pdc_trace(pdc_core *pdc, const char *fmt, ...)
|
|
{
|
|
if (pdc && pdc->tracestatus == pdc_true)
|
|
{
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
pdc_trace_output(pdc, fmt, ap);
|
|
va_end(ap);
|
|
}
|
|
}
|
|
|
|
|
|
/* start or stop (client == NULL) a trace for the supplied client program
|
|
*/
|
|
void
|
|
pdc_set_trace(pdc_core *pdc, const char *client)
|
|
{
|
|
const char *separstr =
|
|
"[ --------------------------------------------------------- ]\n";
|
|
|
|
pdc_bool old_tracestatus = pdc->tracestatus;
|
|
pdc_time ltime;
|
|
|
|
pdc_localtime(<ime);
|
|
|
|
if (old_tracestatus == pdc_true && client == NULL)
|
|
{
|
|
pdc_trace(pdc, "\n");
|
|
pdc_trace(pdc, separstr);
|
|
}
|
|
|
|
pdc->tracestatus = client ? pdc_true : pdc_false;
|
|
|
|
if (old_tracestatus == pdc_undef && pdc->tracestatus == pdc_true)
|
|
{
|
|
pdc_trace(pdc, separstr);
|
|
pdc_trace(pdc, "[ %s on %s (%s) ", client, PDF_PLATFORM,
|
|
PDC_ISBIGENDIAN ? "be" : "le");
|
|
pdc_trace(pdc, "%04d-%02d-%02d %02d:%02d:%02d ]\n",
|
|
ltime.year + 1900, ltime.month + 1, ltime.mday,
|
|
ltime.hour, ltime.minute, ltime.second);
|
|
|
|
if (pdc->traceclassapi)
|
|
pdc_trace(pdc, "[ Use %%s/\\[[^]]*\\]//g and %%s/)$/);"
|
|
"/ in vi to compile it ]\n");
|
|
pdc_trace(pdc, separstr);
|
|
}
|
|
}
|
|
|
|
/* standard trace protocol functions for api function calls
|
|
*/
|
|
void
|
|
pdc_trace_enter_api(pdc_core *pdc, const char *funame,
|
|
const char *fmt, va_list args)
|
|
{
|
|
if (pdc && pdc->tracestatus == pdc_true && pdc->traceclasslist[trc_api])
|
|
{
|
|
/* time stamp */
|
|
if (pdc->traceclasslist[trc_api] > 1)
|
|
{
|
|
pdc_time ltime;
|
|
|
|
pdc_localtime(<ime);
|
|
pdc_trace(pdc, "[%02d:%02d:%02d] ",
|
|
ltime.hour, ltime.minute, ltime.second);
|
|
}
|
|
|
|
/* function name */
|
|
pdc_trace(pdc, "%s", funame);
|
|
|
|
/* function arg list */
|
|
pdc_trace_output(pdc, fmt, args);
|
|
|
|
/* linefeed if not only API calls */
|
|
if (!pdc->traceclassapi)
|
|
pdc_trace(pdc, "\n");
|
|
}
|
|
}
|
|
|
|
void
|
|
pdc_trace_exit_api(pdc_core *pdc, pdc_bool cleanup, const char *fmt, ...)
|
|
{
|
|
if (pdc->tracestatus == pdc_true && pdc->traceclasslist[trc_api] &&
|
|
fmt != NULL)
|
|
{
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
pdc_trace_output(pdc, fmt, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
if (cleanup)
|
|
pdc_tmlist_cleanup(pdc, &pdc->tm_list);
|
|
}
|
|
|
|
/* general trace protocol functions
|
|
*/
|
|
pdc_bool
|
|
pdc_trace_protocol_is_enabled(pdc_core *pdc, int level, int pclass)
|
|
{
|
|
return pdc->tracestatus == pdc_true && level <= pdc->traceclasslist[pclass];
|
|
}
|
|
|
|
void
|
|
pdc_trace_protocol(pdc_core *pdc, int level, int pclass, const char *fmt, ...)
|
|
{
|
|
if (pdc && pdc->tracestatus == pdc_true &&
|
|
level <= pdc->traceclasslist[pclass])
|
|
{
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
pdc_trace_output(pdc, fmt, ap);
|
|
va_end(ap);
|
|
}
|
|
}
|
|
|
|
|
|
/* ------------ encoding handling ------------ */
|
|
|
|
void
|
|
pdc_set_pglyphtab_ptr(pdc_core *pdc, void *pglyphtab_ptr)
|
|
{
|
|
pdc->pglyphtab = pglyphtab_ptr;
|
|
}
|
|
|
|
void *
|
|
pdc_get_pglyphtab_ptr(pdc_core *pdc)
|
|
{
|
|
return pdc->pglyphtab;
|
|
}
|
|
|
|
|
|
|
|
/* ----------- service function to get PDF version string -------------- */
|
|
|
|
const char *
|
|
pdc_get_pdfversion(pdc_core *pdc, int compatibility)
|
|
{
|
|
return pdc_errprintf(pdc, "%d.%d", compatibility / 10, compatibility % 10);
|
|
}
|
|
|
|
|
|
/* --------------------------- float digits --------------------------- */
|
|
|
|
void
|
|
pdc_set_floatdigits(pdc_core *pdc, int val)
|
|
{
|
|
pdc->floatdigits = val;
|
|
}
|
|
|
|
int
|
|
pdc_get_floatdigits(pdc_core *pdc)
|
|
{
|
|
return pdc->floatdigits;
|
|
}
|
|
|
|
|
|
|
|
#ifdef PDC_DEBUG
|
|
/* --------------------------- debug hexdump --------------------------- */
|
|
void
|
|
pdc_enable_hexdump(pdc_core *pdc)
|
|
{
|
|
pdc->hexdump = pdc_true;
|
|
}
|
|
|
|
void
|
|
pdc_disable_hexdump(pdc_core *pdc)
|
|
{
|
|
pdc->hexdump = pdc_false;
|
|
}
|
|
|
|
void
|
|
pdc_hexdump(pdc_core *pdc, const char *msg, const char *text, int tlen)
|
|
{
|
|
if (pdc->hexdump)
|
|
{
|
|
int i, k;
|
|
|
|
if (tlen == 1)
|
|
{
|
|
printf("%s: %02X '%c'\n", msg,
|
|
(unsigned char) text[0],
|
|
isprint(text[0]) ? text[0] : '.');
|
|
}
|
|
else
|
|
{
|
|
printf("%s:\n", msg);
|
|
|
|
for (i = 0; i < tlen; i += 16)
|
|
{
|
|
for (k = 0; k < 16; ++k)
|
|
if (i + k < tlen)
|
|
printf("%02X ", (unsigned char) text[i + k]);
|
|
else
|
|
printf(" ");
|
|
|
|
printf(" ");
|
|
for (k = 0; k < 16; ++k)
|
|
if (i + k < tlen)
|
|
printf("%c", isprint(text[i + k]) ? text[i + k] : '.');
|
|
else
|
|
printf(" ");
|
|
|
|
printf("\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* PDC_DEBUG */
|