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
		
			
				
	
	
		
			1232 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			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(<ime);
 | |
|     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 */
 |