campo-sirio/pdf/pdcore/pc_core.c
guy 3bf951f42c Patch level : 10.0
Files correlati     : pdflib
Ricompilazione Demo : [ ]
Commento            :
Aggiornata pdflib.dll alla versione 7.0.4


git-svn-id: svn://10.65.10.50/trunk@18580 c028cbd2-c16b-5b4b-a496-9718f37d4682
2009-03-23 08:55:58 +00:00

1232 lines
28 KiB
C
Executable File

/*---------------------------------------------------------------------------*
| PDFlib - A library for generating PDF on the fly |
+---------------------------------------------------------------------------+
| Copyright (c) 1997-2006 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.4 2009-03-23 08:51:17 guy Exp $
*
* PDFlib core services
*
*/
#include "pc_util.h"
#include "pc_string.h"
#include "pc_ctype.h"
#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_bs_new()
*/
#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;
/* exception handling frame.
*/
typedef struct
{
pdc_jmpbuf jbuf;
} pdc_xframe;
typedef struct
{
const pdc_error_info * ei;
int n_entries;
} error_table;
/* ------------------------ the core private structure ---------------------- */
struct pdc_core_priv_s
{
/* ------------ try/catch ------------ */
pdc_xframe * x_stack;
#ifdef PDC_ALIGN16
char * x_alias;
#endif
int x_ssize;
int x_sp; /* exception stack pointer */
int x_sp0; /* exception stack pointer at */
/* the time of pdc_enter_api() */
/* ------------ error handling ------------ */
pdc_bool in_error; /* while initializing pdcore or */
/* while creating error resp. */
char * premsg;
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[32];
pdc_error_fp errorhandler; /* client error handler */
void * opaque; /* client specific, opaque data */
error_table err_tables[N_ERRTABS];
#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;
};
/* ----------- 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;
(void) errnum;
fprintf(stderr, "fatal exception: %s\n", msg);
exit(99);
}
pdc_bool
pdc_enter_api(pdc_core *pdc, const char *apiname)
{
char *name = NULL;
if (pdc->pr->in_error)
return pdc_false;
if (pdc->objorient)
name = (char *) strchr(apiname, '_');
if (name)
name++;
else
name = (char *) apiname;
if (name[0] == '\n')
name++;
strcpy(pdc->pr->apiname, name);
if (pdc->binding != NULL)
{
size_t len = strlen(pdc->pr->apiname);
len--;
if (len && pdc->pr->apiname[len] == '2')
pdc->pr->apiname[len] = 0;
}
pdc->pr->errnum = 0;
pdc->pr->x_sp0 = pdc->pr->x_sp;
return pdc_true;
}
pdc_bool
pdc_in_error(pdc_core *pdc)
{
return pdc->pr->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);
#if defined (PDC_NO_VSNPRINTF)
vsprintf(pdc->pr->errbuf, fmt, ap);
#else
#if defined(WIN32)
_vsnprintf(pdc->pr->errbuf, PDC_ERRPARM_SIZE, fmt, ap);
#else
vsnprintf(pdc->pr->errbuf, PDC_ERRPARM_SIZE, fmt, ap);
#endif
#endif
va_end(ap);
(*pdc->pr->errorhandler)(pdc->pr->opaque, PDF_UnknownError,
pdc->pr->errbuf);
} /* pdc_panic */
static void
check_parms(pdc_core *pdc, const pdc_error_info *ei)
{
const char *msg = ei->errmsg;
const char *dollar;
while ((dollar = strchr(msg, '$')) != (char *) 0)
{
if (pdc_isdigit(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,
const 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->pr->err_tables[n].ei != (pdc_error_info *) 0)
return;
pdc->pr->err_tables[n].ei = ei;
pdc->pr->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->pr->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->pr->err_tables[n].ei = ei;
pdc->pr->err_tables[n].n_entries = n_entries;
}
check_parms(pdc, &ei[i]);
}
} /* pdc_register_errtab */
/* pdc_new_core() never throws exceptions.
** it returns NULL if there's not enough memory.
*/
pdc_core *
pdc_new_core(
pdc_error_fp errorhandler,
pdc_alloc_fp allocproc,
pdc_realloc_fp reallocproc,
pdc_free_fp freeproc,
void *opaque,
const char *prodname,
const char *version)
{
static const char fn[] = "pdc_new_core";
pdc_core_priv *pdc_pr;
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_pr = (pdc_core_priv *)
(*allocproc)(opaque, sizeof (pdc_core_priv), fn);
if (pdc_pr == (pdc_core_priv *) 0)
return (pdc_core *) 0;
pdc = (pdc_core *)
(*allocproc)(opaque, sizeof (pdc_core), fn);
if (pdc == (pdc_core *) 0)
return (pdc_core *) 0;
pdc->pr = pdc_pr;
/* initialize client members
*/
pdc->reslist = NULL;
pdc->filesystem = NULL;
pdc->logg = NULL;
pdc->loggenv = pdc_false;
pdc->encstack = NULL;
pdc->pglyphtab = NULL;
pdc->bstr_pool = NULL;
pdc->ustr_pool = NULL;
pdc->last_rand = 1;
pdc->prodname = prodname;
pdc->version = version;
pdc->binding = NULL;
pdc->unicaplang = pdc_false;
pdc->objorient = pdc_false;
pdc->hastobepos = pdc_false;
pdc->ptfrun = pdc_false;
pdc->smokerun = pdc_false;
pdc->charref = pdc_false;
pdc->escapesequ = pdc_false;
pdc->honorlang = pdc_false;
pdc->compatibility = PDC_X_X_LAST;
pdc->floatdigits = 4;
pdc->uniqueno = 0;
#ifdef PDC_DEBUG
pdc->pr->hexdump = pdc_true;
#endif
/* set diverse handlers
*/
pdc->pr->errorhandler = errorhandler;
pdc->pr->allocproc = allocproc;
pdc->pr->reallocproc = reallocproc;
pdc->pr->freeproc = freeproc;
pdc->pr->opaque = opaque;
/* initialize error & exception handling.
*/
pdc->pr->in_error = pdc_true; /* disable error messages */
pdc->pr->x_thrown = pdc_false;
pdc->pr->epcount = 0;
pdc->pr->errnum = 0;
pdc->pr->premsg = NULL;
pdc->pr->errbuf[0] = 0;
pdc->pr->apiname[0] = 0;
pdc->pr->x_sp = -1;
pdc->pr->x_ssize = PDC_XSTACK_INISIZE;
#ifdef PDC_ALIGN16
pdc->pr->x_alias = (char *)
(*allocproc)(opaque, 16 + pdc->pr->x_ssize * sizeof (pdc_xframe), fn);
if (pdc->pr->x_alias == (char *) 0)
pdc->pr->x_stack = (pdc_xframe *) 0;
else
pdc->pr->x_stack = (pdc_xframe *)
(((unsigned long) pdc->pr->x_alias + 16) & 0xFFFFFFFFFFFFFFF0);
#else
pdc->pr->x_stack = (pdc_xframe *)
(*allocproc)(opaque, pdc->pr->x_ssize * sizeof (pdc_xframe), fn);
#endif
if (pdc->pr->x_stack == (pdc_xframe *) 0)
{
(*freeproc)(opaque, pdc);
return (pdc_core *) 0;
}
pdc_tmlist_init(pdc);
/* initialize error tables.
*/
for (i = 0; i < N_ERRTABS; ++i)
pdc->pr->err_tables[i].ei = (pdc_error_info *) 0;
pdc_register_errtab(pdc, PDC_ET_CORE, core_errors, N_CORE_ERRORS);
/* initialize mempool for strings
*/
pdc_init_strings(pdc);
if (pdc->bstr_pool == NULL || pdc->ustr_pool == NULL)
{
(*freeproc)(opaque, pdc);
return (pdc_core *) 0;
}
/* enable error messages
*/
pdc->pr->in_error = pdc_false;
return pdc;
}
void
pdc_delete_core(pdc_core *pdc)
{
pdc_free_fp freeproc = pdc->pr->freeproc;
void *opaque = pdc->pr->opaque;
pdc_time ltime;
pdc_localtime(&ltime);
pdc_logg(pdc, "[%04d-%02d-%02d %02d:%02d:%02d]\n",
ltime.year + 1900, ltime.month + 1, ltime.mday,
ltime.hour, ltime.minute, ltime.second);
pdc_delete_reslist(pdc);
pdc_delete_filesystem(pdc);
pdc_delete_encodingstack(pdc);
pdc_delete_pglyphtab(pdc);
pdc_cleanup_strings(pdc);
if (pdc->binding)
pdc_free(pdc, pdc->binding);
pdc_pop_errmsg(pdc);
pdc_tmlist_cleanup(pdc);
if (pdc->pr->tm_list.capacity != 0)
pdc_free(pdc, pdc->pr->tm_list.tmpmem);
#ifdef PDC_ALIGN16
pdc_free(pdc, pdc->pr->x_alias);
#else
pdc_free(pdc, pdc->pr->x_stack);
#endif
pdc_delete_logg(pdc);
(*freeproc)(opaque, pdc->pr);
(*freeproc)(opaque, pdc);
}
/* --------------------------- memory management --------------------------- */
void *
pdc_malloc(pdc_core *pdc, size_t size, const char *caller)
{
void *ret;
pdc_bool logg1 = pdc_logg_is_enabled(pdc, 1, trc_memory);
if (logg1)
pdc_logg(pdc, "\ttry to malloc %ld bytes\n", size);
/* 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_error(pdc, PDC_E_INT_ALLOC0, caller, 0, 0, 0);
}
if ((ret = (*pdc->pr->allocproc)(pdc->pr->opaque, size, caller)) ==
(void *) 0)
{
pdc_error(pdc, PDC_E_MEM_OUT, caller, 0, 0, 0);
}
if (logg1)
pdc_logg(pdc, "\t%p malloced, size=%ld, 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;
pdc_bool logg1 = pdc_logg_is_enabled(pdc, 1, trc_memory);
if (logg1)
pdc_logg(pdc, "\ttry to calloc %ld bytes\n", size);
if (size == (size_t) 0 || (long) size < 0L)
{
size = (size_t) 1;
pdc_error(pdc, PDC_E_INT_ALLOC0, caller, 0, 0, 0);
}
if ((ret = (*pdc->pr->allocproc)(pdc->pr->opaque, size, caller)) ==
(void *) 0)
{
pdc_error(pdc, PDC_E_MEM_OUT, caller, 0, 0, 0);
}
if (logg1)
pdc_logg(pdc, "\t%p calloced, size=%ld, 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;
pdc_bool logg1 = pdc_logg_is_enabled(pdc, 1, trc_memory);
if (logg1)
pdc_logg(pdc, "\ttry to realloc %p to %ld bytes\n", mem, size);
if (size == (size_t) 0 || (long) size < 0L)
{
size = (size_t) 1;
pdc_error(pdc, PDC_E_INT_ALLOC0, caller, 0, 0, 0);
}
ret = (mem == (void *) 0) ?
(*pdc->pr->allocproc)(pdc->pr->opaque, size, caller) :
(*pdc->pr->reallocproc)(pdc->pr->opaque, mem, size, caller);
if (ret == (void *) 0)
pdc_error(pdc, PDC_E_MEM_OUT, caller, 0, 0, 0);
pdc_logg_cond(pdc, 1, trc_memory,
"\t%p realloced to\n"
"\t%p new, size=%ld, called from \"%s\"\n",
mem, ret, size, caller);
return ret;
}
void
pdc_free(pdc_core *pdc, void *mem)
{
pdc_logg_cond(pdc, 1, trc_memory, "\t%p freed\n", mem);
/* just in case the freeproc() isn't that ANSI compatible...
*/
if (mem != NULL)
(*pdc->pr->freeproc)(pdc->pr->opaque, mem);
}
/* -------------------- temporary free store management -------------------- */
void
pdc_tmlist_init(pdc_core *pdc)
{
pdc->pr->tm_list.size = pdc->pr->tm_list.capacity = 0;
}
static void
pdc_tmlist_grow(pdc_core *pdc)
{
static const char fn[] = "pdc_tmlist_grow";
pdc_tmpmem_list *tm_list = &pdc->pr->tm_list;
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);
}
}
void
pdc_tmlist_cleanup(pdc_core *pdc)
{
pdc_tmpmem_list *tm_list = &pdc->pr->tm_list;
int i;
for (i = 0; i < tm_list->size; ++i)
{
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->size = 0;
}
void
pdc_insert_mem_tmp(
pdc_core * pdc,
void * memory,
void * opaque,
pdc_destructor destr)
{
pdc_tmpmem_list *tm_list = &pdc->pr->tm_list;
if (tm_list->size == tm_list->capacity)
pdc_tmlist_grow(pdc);
pdc_logg_cond(pdc, 2, trc_memory,
"\tTemporary memory %p was created\n", memory);
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)
{
pdc_tmpmem_list *tm_list = &pdc->pr->tm_list;
int i;
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)
{
pdc_tmpmem_list *tm_list = &pdc->pr->tm_list;
int i, j;
pdc_logg_cond(pdc, 2, trc_memory,
"\tTemporary memory %p to be freed\n", mem);
/* 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->pr->epcount < 0 || pdc->pr->epcount > 3)
pdc->pr->epcount = 0;
va_start(ap, fmt);
pdc_vsnprintf(pdc, pdc->pr->errparms[pdc->pr->epcount], PDC_ERRPARM_SIZE,
fmt, ap);
va_end(ap);
return pdc->pr->errparms[pdc->pr->epcount++];
}
static const pdc_error_info *
get_error_info(pdc_core *pdc, int errnum)
{
int n = (errnum / 1000) - 1;
if (0 <= n && n < N_ERRTABS && pdc->pr->err_tables[n].ei != 0)
{
error_table *etab = &pdc->pr->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,
const pdc_error_info *ei,
const char * parm1,
const char * parm2,
const char * parm3,
const char * parm4,
pdc_bool popmsg)
{
const char *src = ei->ce_msg ? ei->ce_msg : ei->errmsg;
char * dst = pdc->pr->errbuf;
const char *dollar;
if (pdc->pr->premsg != NULL)
{
strcpy(dst, pdc->pr->premsg);
dst += strlen(pdc->pr->premsg);
if (popmsg)
pdc_pop_errmsg(pdc);
}
pdc->pr->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_pop_errmsg(pdc_core *pdc)
{
if (pdc->pr->premsg)
{
pdc_free(pdc, pdc->pr->premsg);
pdc->pr->premsg = NULL;
}
} /* pdc_pop_errmsg */
void
pdc_push_errmsg(
pdc_core * pdc,
int errnum,
const char *parm1,
const char *parm2,
const char *parm3,
const char *parm4)
{
static const char fn[] = "pdc_push_errmsg";
const pdc_error_info *ei = get_error_info(pdc, errnum);
pdc_pop_errmsg(pdc);
pdc->pr->errnum = 0;
make_errmsg(pdc, ei, parm1, parm2, parm3, parm4, pdc_false);
pdc->pr->premsg = pdc_strdup_ext(pdc, pdc->pr->errbuf, 0, fn);
} /* pdc_push_errmsg */
void
pdc_set_errmsg(
pdc_core * pdc,
int errnum,
const char *parm1,
const char *parm2,
const char *parm3,
const char *parm4)
{
if (errnum != 0)
{
const pdc_error_info *ei = get_error_info(pdc, errnum);
make_errmsg(pdc, ei, parm1, parm2, parm3, parm4, pdc_false);
}
pdc->pr->errnum = errnum;
if (errnum)
pdc_logg_cond(pdc, 2, trc_warning,
"[Reason for error message %d: \"%s\"]\n",
pdc->pr->errnum, pdc->pr->errbuf);
} /* pdc_set_errmsg */
void
pdc_set_warnmsg(
pdc_core * pdc,
int errnum,
const char *parm1,
const char *parm2,
const char *parm3,
const char *parm4)
{
char errbuf[PDC_ERRBUF_SIZE];
strcpy(errbuf, pdc->pr->errbuf);
if (errnum != -1)
{
const pdc_error_info *ei = get_error_info(pdc, errnum);
make_errmsg(pdc, ei, parm1, parm2, parm3, parm4, pdc_false);
}
pdc_logg_cond(pdc, 1, trc_warning,
"\n[Warning message %d: \"%s\"]\n",
errnum, pdc->pr->errbuf);
strcpy(pdc->pr->errbuf, errbuf);
} /* pdc_set_warnmsg */
void
pdc_error(
pdc_core * pdc,
int errnum,
const char *parm1,
const char *parm2,
const char *parm3,
const char *parm4)
{
const char *logmsg = NULL;
/* avoid recursive errors, but allow rethrow.
*/
if (errnum != -1 && pdc->pr->in_error)
return;
pdc->pr->in_error = pdc_true;
pdc->pr->x_thrown = pdc_true;
if (errnum != -1)
{
const pdc_error_info *ei = get_error_info(pdc, errnum);
make_errmsg(pdc, ei, parm1, parm2, parm3, parm4, pdc_true);
pdc->pr->errnum = errnum;
}
if (pdc->pr->x_sp > pdc->pr->x_sp0)
{
if (pdc_logg_is_enabled(pdc, 2, trc_warning))
logmsg = "[Nested exception %d in %s]";
}
else
{
logmsg = "\n[Last exception %d in %s]";
}
if (logmsg != NULL)
{
pdc_logg(pdc, logmsg, pdc->pr->errnum,
(pdc->pr->errnum == 0 || !pdc->pr->apiname) ? "" : pdc->pr->apiname,
pdc->pr->x_sp0 + 1, pdc->pr->x_sp - pdc->pr->x_sp0);
pdc_logg(pdc, "[\"%s\"]\n\n", pdc->pr->errbuf);
}
if (pdc->pr->x_sp == -1)
{
char errbuf[PDC_ERRBUF_SIZE];
const char *apiname = pdc_get_apiname(pdc);
const char *errmsg = pdc->pr->errbuf;
if (strlen(apiname))
{
sprintf(errbuf, "[%d] %s: %s", pdc->pr->errnum, apiname, errmsg);
errmsg = errbuf;
}
(*pdc->pr->errorhandler)(pdc->pr->opaque, PDF_UnknownError, errmsg);
/*
* 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->pr->x_stack[pdc->pr->x_sp].jbuf.jbuf, 1);
}
} /* pdc_error */
pdc_jmpbuf *
pdc_jbuf(pdc_core *pdc)
{
static const char fn[] = "pdc_jbuf";
pdc_logg_cond(pdc, 3, trc_api,
"[TRY to level %d]\n", pdc->pr->x_sp + 1);
if (++pdc->pr->x_sp == pdc->pr->x_ssize)
{
pdc_xframe *aux;
#ifdef PDC_ALIGN16
char *cp = (char *) (*pdc->pr->allocproc)(pdc->pr->opaque,
16 + 2 * pdc->pr->x_ssize * sizeof (pdc_xframe), fn);
if (cp == (char *) 0)
{
aux = (pdc_xframe *) 0;
}
else
{
/* remember the pointer in order to free it only after the memcpy
* below, as pdc->pr->x_stack points into the memory allocated
* to pdc->pr->x_alias
*/
char *free_me_later = pdc->pr->x_alias;
pdc->pr->x_alias = cp;
aux = (pdc_xframe *)
(((unsigned long) cp + 16) & 0xFFFFFFFFFFFFFFF0);
memcpy(aux, pdc->pr->x_stack,
pdc->pr->x_ssize * sizeof (pdc_xframe));
pdc_free(pdc, free_me_later);
}
#else
aux = (pdc_xframe *) (*pdc->pr->reallocproc)(
pdc->pr->opaque, pdc->pr->x_stack,
2 * pdc->pr->x_ssize * sizeof (pdc_xframe), fn);
#endif
if (aux == (pdc_xframe *) 0)
{
--pdc->pr->x_sp;
pdc->pr->x_thrown = pdc_true;
pdc->pr->in_error = pdc_true;
pdc->pr->errnum = PDC_E_MEM_OUT;
pdc->pr->apiname[0] = 0;
sprintf(pdc->pr->errbuf,
"Out of memory in TRY function (nesting level: %d)",
pdc->pr->x_sp + 1);
longjmp(pdc->pr->x_stack[pdc->pr->x_sp].jbuf.jbuf, 1);
}
pdc->pr->x_stack = aux;
pdc->pr->x_ssize *= 2;
}
pdc->pr->x_thrown = pdc_false;
return &pdc->pr->x_stack[pdc->pr->x_sp].jbuf;
} /* pdc_jbuf */
void
pdc_exit_try(pdc_core *pdc)
{
pdc_logg_cond(pdc, 3, trc_api,
"[EXIT_TRY at level %d]\n", pdc->pr->x_sp);
if (pdc->pr->x_sp == -1)
{
strcpy(pdc->pr->errbuf, "exception stack underflow");
pdc->pr->errnum = PDC_E_INT_XSTACK;
(*pdc->pr->errorhandler)(pdc->pr->opaque, PDF_UnknownError,
pdc->pr->errbuf);
}
else
--pdc->pr->x_sp;
} /* pdc_exit_try */
int
pdc_catch_intern(pdc_core *pdc)
{
pdc_bool result;
pdc_logg_cond(pdc, 3, trc_api,
"[CATCH intern at level %d]\n", pdc->pr->x_sp);
if (pdc->pr->x_sp == -1)
{
strcpy(pdc->pr->errbuf, "exception stack underflow");
pdc->pr->errnum = PDC_E_INT_XSTACK;
(*pdc->pr->errorhandler)(pdc->pr->opaque, PDF_UnknownError,
pdc->pr->errbuf);
}
else
--pdc->pr->x_sp;
result = pdc->pr->x_thrown;
pdc->pr->in_error = pdc_false;
pdc->pr->x_thrown = pdc_false;
return result;
} /* pdc_catch_intern */
int
pdc_catch_extern(pdc_core *pdc)
{
pdc_bool result;
pdc_logg_cond(pdc, 3, trc_api,
"[CATCH at level %d]\n", pdc->pr->x_sp);
if (pdc->pr->x_sp == -1)
{
strcpy(pdc->pr->errbuf, "exception stack underflow");
pdc->pr->errnum = PDC_E_INT_XSTACK;
(*pdc->pr->errorhandler)(pdc->pr->opaque, PDF_UnknownError,
pdc->pr->errbuf);
}
else
--pdc->pr->x_sp;
result = pdc->pr->x_thrown;
pdc->pr->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 */
/* this function should be called in the PDC_CATCH branch of
** a function before it returns -1.
*/
void
pdc_check_rethrow(pdc_core *pdc)
{
if (pdc->pr->errnum == PDC_E_MEM_OUT)
pdc_error(pdc, -1, 0, 0, 0, 0);
} /* pdc_check_rethrow */
int
pdc_get_errnum(pdc_core *pdc)
{
return pdc->pr->errnum;
}
const char *
pdc_get_errmsg(pdc_core *pdc)
{
return (pdc->pr->errnum == 0) ? "" : pdc->pr->errbuf;
}
const char *
pdc_get_apiname(pdc_core *pdc)
{
return pdc->pr->apiname;
}
const char *
pdc_get_errpref(pdc_core *pdc)
{
return pdc->pr->premsg;
}
#ifdef PDC_DEBUG
/* --------------------------- debug hexdump --------------------------- */
void
pdc_enable_hexdump(pdc_core *pdc)
{
pdc->pr->hexdump = pdc_true;
}
void
pdc_disable_hexdump(pdc_core *pdc)
{
pdc->pr->hexdump = pdc_false;
}
void
pdc_hexdump(pdc_core *pdc, const char *msg, const char *text, int tlen)
{
if (pdc->pr->hexdump)
{
int i, k;
if (tlen == 1)
{
printf("%s: %02X '%c'\n", msg,
(unsigned char) text[0],
pdc_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",
pdc_isprint(text[i + k]) ? text[i + k] : '.');
}
else
printf(" ");
printf("\n");
}
}
}
}
#endif /* PDC_DEBUG */