2006-05-04 16:36:51 +00:00
|
|
|
/*---------------------------------------------------------------------------*
|
|
|
|
| PDFlib - A library for generating PDF on the fly |
|
|
|
|
+---------------------------------------------------------------------------+
|
2008-10-20 14:35:00 +00:00
|
|
|
| Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
|
2006-05-04 16:36:51 +00:00
|
|
|
+---------------------------------------------------------------------------+
|
|
|
|
| |
|
|
|
|
| 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. |
|
|
|
|
| |
|
|
|
|
*---------------------------------------------------------------------------*/
|
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
/* $Id: pc_util.c,v 1.4 2009-03-23 08:51:17 guy Exp $
|
2006-05-04 16:36:51 +00:00
|
|
|
*
|
|
|
|
* PDFlib various utility routines
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#include "pc_util.h"
|
2008-10-20 14:35:00 +00:00
|
|
|
#include "pc_file.h"
|
|
|
|
#include "pc_ctype.h"
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
#ifdef AS400
|
|
|
|
#include <qp0z1170.h> /* for getenv() emulation */
|
|
|
|
#endif
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
#ifdef __sun
|
|
|
|
#include <ieeefp.h> /* for finite */
|
|
|
|
#endif
|
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
#if defined (isfinite)
|
|
|
|
#define PDC_ISFINITE isfinite
|
|
|
|
#else /* isfinite */
|
2008-10-20 14:35:00 +00:00
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
#include <windows.h>
|
|
|
|
#include <float.h>
|
|
|
|
#define PDC_ISFINITE _finite
|
|
|
|
#else /* _WIN32 */
|
2008-10-20 14:35:00 +00:00
|
|
|
|
|
|
|
#ifdef OS_ZOS_SASC
|
|
|
|
#define PDC_ISFINITE isfinite
|
|
|
|
#else /* OS_ZOS_SASC */
|
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
#define PDC_ISFINITE finite
|
|
|
|
#endif
|
|
|
|
#endif
|
2008-10-20 14:35:00 +00:00
|
|
|
#endif
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
/* ---------------------- finite() workarounds -------------------------- */
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
|
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
/*
|
|
|
|
* pdc_check_number checks whether a floating-point number
|
|
|
|
* is valid and within the specified range. If not, an exception
|
|
|
|
* will be thrown.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
pdc_check_number_limits(pdc_core *pdc, const char *paramname, double dz,
|
|
|
|
double dmin, double dmax)
|
|
|
|
{
|
|
|
|
if (!PDC_ISFINITE(dz))
|
|
|
|
{
|
|
|
|
pdc_error(pdc, PDC_E_ILLARG_FLOAT_NAN, paramname, 0, 0, 0);
|
|
|
|
}
|
|
|
|
else if (dz < dmin)
|
|
|
|
{
|
|
|
|
pdc_error(pdc, PDC_E_ILLARG_FLOAT_TOOSMALL, paramname,
|
|
|
|
pdc_errprintf(pdc, "%f", dz),
|
|
|
|
pdc_errprintf(pdc, "%f", dmin), 0);
|
|
|
|
}
|
|
|
|
else if (dz > dmax)
|
|
|
|
{
|
|
|
|
pdc_error(pdc, PDC_E_ILLARG_FLOAT_TOOLARGE, paramname,
|
|
|
|
pdc_errprintf(pdc, "%f", dz),
|
|
|
|
pdc_errprintf(pdc, "%f", dmax), 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
pdc_check_number(pdc_core *pdc, const char *paramname, double dz)
|
|
|
|
{
|
|
|
|
pdc_check_number_limits(pdc, paramname, dz, PDC_FLOAT_MIN, PDC_FLOAT_MAX);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
pdc_check_number_zero(pdc_core *pdc, const char *paramname, double dz)
|
|
|
|
{
|
|
|
|
pdc_check_number_limits(pdc, paramname, dz, PDC_FLOAT_MIN, PDC_FLOAT_MAX);
|
|
|
|
|
|
|
|
if (PDC_FLOAT_ISNULL(dz))
|
|
|
|
{
|
|
|
|
pdc_error(pdc, PDC_E_ILLARG_FLOAT_ZERO, paramname,
|
|
|
|
pdc_errprintf(pdc, "%f", dz), 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
int
|
|
|
|
pdc_check_text_length(pdc_core *pdc, const char **text, int len, int maxlen)
|
|
|
|
{
|
|
|
|
if (*text == NULL)
|
|
|
|
{
|
|
|
|
len = 0;
|
|
|
|
*text = "";
|
|
|
|
}
|
|
|
|
else if (len == 0)
|
|
|
|
{
|
|
|
|
len = (int) strlen(*text);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (len < 0 || len > maxlen)
|
|
|
|
{
|
|
|
|
pdc_error(pdc, PDC_E_ILLARG_STRINGLEN,
|
|
|
|
pdc_errprintf(pdc, "%d", len),
|
|
|
|
pdc_errprintf(pdc, "%d", maxlen), 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------- "unsupported feature" error message ------------------ */
|
|
|
|
|
|
|
|
void
|
|
|
|
pdc_set_unsupp_error(pdc_core *pdc, int err_config, int err_lite,
|
|
|
|
pdc_bool warning)
|
|
|
|
{
|
|
|
|
(void) err_config;
|
|
|
|
(void) err_lite;
|
|
|
|
|
|
|
|
/* this feature is sufficient for non public version */
|
|
|
|
if (warning)
|
|
|
|
pdc_warning(pdc, err_lite, 0, 0, 0, 0);
|
|
|
|
else
|
|
|
|
pdc_error(pdc, err_lite, 0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------- error message with ASCII strings -------------------- */
|
|
|
|
|
|
|
|
void
|
|
|
|
pdc_ascii_error(pdc_core *pdc, int errnum, int flags, const char *parm1,
|
|
|
|
const char *parm2, const char *parm3, const char *parm4)
|
|
|
|
{
|
|
|
|
if (flags & (1<<0))
|
|
|
|
{
|
|
|
|
parm1 = pdc_errprintf(pdc, "%a", parm1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & (1<<1))
|
|
|
|
{
|
|
|
|
parm2 = pdc_errprintf(pdc, "%a", parm2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & (1<<2))
|
|
|
|
{
|
|
|
|
parm3 = pdc_errprintf(pdc, "%a", parm3);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & (1<<3))
|
|
|
|
{
|
|
|
|
parm4 = pdc_errprintf(pdc, "%a", parm4);
|
|
|
|
}
|
|
|
|
|
|
|
|
pdc_error(pdc, errnum, parm1, parm2, parm3, parm4);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
/* -------------------------- Time functions ------------------------------ */
|
|
|
|
|
|
|
|
#ifndef WINCE
|
|
|
|
#ifndef __USE_POSIX
|
|
|
|
#define __USE_POSIX
|
|
|
|
#endif
|
|
|
|
#include <time.h>
|
|
|
|
#else
|
|
|
|
#include <winbase.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* our private localtime() function. this one circumvents platform
|
|
|
|
** quirks we found on WINCE and Solaris, and perhaps some more in
|
|
|
|
** the future.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
pdc_localtime(pdc_time *t)
|
|
|
|
{
|
|
|
|
#ifdef WINCE
|
|
|
|
|
|
|
|
SYSTEMTIME st;
|
|
|
|
|
|
|
|
GetLocalTime (&st);
|
|
|
|
|
|
|
|
t->second = st.wSecond;
|
|
|
|
t->minute = st.wMinute;
|
|
|
|
t->hour = st.wHour;
|
|
|
|
t->mday = st.wDay;
|
|
|
|
t->wday = st.wDayOfWeek;
|
|
|
|
t->month = st.wMonth;
|
|
|
|
t->year = st.wYear;
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
time_t timer;
|
2008-10-20 14:35:00 +00:00
|
|
|
struct tm ltime;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
time(&timer);
|
|
|
|
|
|
|
|
#if defined(PDC_NEEDS_R_FUNCTIONS)
|
|
|
|
|
|
|
|
/* the localtime() function isn't thread safe on this platform.
|
|
|
|
** a thread safe variant must be used instead.
|
|
|
|
*/
|
|
|
|
(void) localtime_r(&timer, <ime);
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
ltime = *localtime(&timer);
|
|
|
|
|
|
|
|
#endif /* !PDC_NEEDS_R_FUNCTIONS */
|
|
|
|
|
|
|
|
t->second = ltime.tm_sec;
|
|
|
|
t->minute = ltime.tm_min;
|
|
|
|
t->hour = ltime.tm_hour;
|
|
|
|
t->mday = ltime.tm_mday;
|
|
|
|
t->wday = ltime.tm_wday;
|
|
|
|
t->month = ltime.tm_mon;
|
|
|
|
t->year = ltime.tm_year;
|
|
|
|
|
|
|
|
#endif /* !WINCE */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
pdc_localtime_r(const time_t *timer, struct tm *res)
|
|
|
|
{
|
|
|
|
#if defined(PDC_NEEDS_R_FUNCTIONS)
|
|
|
|
(void) localtime_r(timer, res);
|
|
|
|
#else
|
|
|
|
*res = *localtime(timer);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
pdc_gmtime_r(const time_t *timer, struct tm *res)
|
|
|
|
{
|
|
|
|
#if defined(PDC_NEEDS_R_FUNCTIONS)
|
|
|
|
(void) gmtime_r(timer, res);
|
|
|
|
#else
|
|
|
|
*res = *gmtime(timer);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_get_timestr(char *str, pdc_bool ktoascii)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
|
|
|
#ifndef WINCE
|
|
|
|
time_t timer, gtimer;
|
|
|
|
struct tm ltime;
|
|
|
|
double diffminutes;
|
|
|
|
int utcoffset;
|
|
|
|
#else
|
|
|
|
SYSTEMTIME st;
|
|
|
|
#endif
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
(void) ktoascii;
|
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
#ifndef WINCE
|
|
|
|
time(&timer);
|
|
|
|
|
|
|
|
#if !defined(I370)
|
|
|
|
pdc_gmtime_r(&timer, <ime);
|
|
|
|
gtimer = mktime(<ime);
|
|
|
|
pdc_localtime_r(&timer, <ime);
|
|
|
|
ltime.tm_isdst = 0;
|
|
|
|
diffminutes = difftime(mktime(<ime), gtimer) / 60;
|
|
|
|
if (diffminutes >= 0)
|
|
|
|
utcoffset = (int)(diffminutes + 0.5);
|
|
|
|
else
|
|
|
|
utcoffset = (int)(diffminutes - 0.5);
|
|
|
|
#else
|
|
|
|
utcoffset = 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Get local time again, previous data is damaged by mktime(). */
|
|
|
|
pdc_localtime_r(&timer, <ime);
|
|
|
|
|
|
|
|
if (utcoffset > 0)
|
|
|
|
sprintf(str, "D:%04d%02d%02d%02d%02d%02d+%02d'%02d'",
|
|
|
|
ltime.tm_year + 1900, ltime.tm_mon + 1, ltime.tm_mday,
|
|
|
|
ltime.tm_hour, ltime.tm_min, ltime.tm_sec,
|
|
|
|
utcoffset / 60, utcoffset % 60);
|
|
|
|
else if (utcoffset < 0)
|
|
|
|
sprintf(str, "D:%04d%02d%02d%02d%02d%02d-%02d'%02d'",
|
|
|
|
ltime.tm_year + 1900, ltime.tm_mon + 1, ltime.tm_mday,
|
|
|
|
ltime.tm_hour, ltime.tm_min, ltime.tm_sec,
|
|
|
|
abs(utcoffset) / 60, abs(utcoffset) % 60);
|
|
|
|
else
|
|
|
|
sprintf(str, "D:%04d%02d%02d%02d%02d%02dZ",
|
|
|
|
ltime.tm_year + 1900, ltime.tm_mon + 1, ltime.tm_mday,
|
|
|
|
ltime.tm_hour, ltime.tm_min, ltime.tm_sec);
|
|
|
|
|
|
|
|
#else
|
|
|
|
GetLocalTime (&st);
|
|
|
|
sprintf(str, "D:%04d%02d%02d%02d%02d%02d",
|
|
|
|
st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
|
|
|
|
#endif /* !WINCE */
|
2008-10-20 14:35:00 +00:00
|
|
|
|
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------- Environment ------------------------------ */
|
|
|
|
|
|
|
|
char *
|
|
|
|
pdc_getenv(const char *name)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_ENVVARS
|
|
|
|
return getenv(name);
|
|
|
|
#else
|
|
|
|
(void) name;
|
|
|
|
|
|
|
|
return (char *) 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ------------------------ Language Code ------------------------------ */
|
|
|
|
|
|
|
|
/* ISO 639 Windows and Mac Language codes */
|
|
|
|
static const char lang_codes_ISO639[] =
|
|
|
|
"ab aa af sq am ar hy as ay az ba eu bn dz bh bi br bg my be km ca zh co"
|
|
|
|
"hr cs da nl en eo et fo fa fj fi fr fy gl gd gv ka de el kl gn gu ha he"
|
|
|
|
"hi hu is id ia ie iu ik ga it ja jv kn ks kk rw ky rn ko ku lo la lv li"
|
|
|
|
"ln lt mk mg ms ml mt mi mr mo mn na ne no oc or om ps pl pt pa qu rm ro"
|
|
|
|
"ru sm sg sa sr sh st tn sn sd si ss sk sl so es su sw sv tl tg ta tt te"
|
|
|
|
"th bo ti to ts tr tk tw ug uk ur uz vi vo cy wo xh yi yo zu"
|
|
|
|
"pt-br en-gb en-us de-de de-ch";
|
|
|
|
|
|
|
|
pdc_bool
|
|
|
|
pdc_check_lang_code(pdc_core *pdc, const char* lang_code)
|
|
|
|
{
|
|
|
|
pdc_bool valid = pdc_false;
|
|
|
|
int i;
|
|
|
|
char* country_code;
|
|
|
|
char* language;
|
|
|
|
|
|
|
|
if ((lang_code != NULL) && *lang_code)
|
|
|
|
{
|
|
|
|
/* do not check for IANA or private languages */
|
|
|
|
if (!(valid = ((lang_code[0] == 'i') || (lang_code[0] == 'x'))))
|
|
|
|
{
|
|
|
|
language = pdc_strdup(pdc, lang_code);
|
|
|
|
for (i = 0; i < (int)strlen(language); i++)
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
if (pdc_isupper(language[i]))
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
language[i] = (char) pdc_tolower((int)language[i]);
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
country_code = (char *)strstr(lang_codes_ISO639, language);
|
2006-05-04 16:36:51 +00:00
|
|
|
valid = (country_code != NULL);
|
|
|
|
|
|
|
|
if (!valid && (strlen(language) > 2))
|
|
|
|
{
|
|
|
|
country_code = strchr(language, '-');
|
|
|
|
if (country_code != NULL)
|
|
|
|
{
|
|
|
|
country_code[0] = '\0';
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
country_code = (char *)strstr(lang_codes_ISO639, language);
|
2006-05-04 16:36:51 +00:00
|
|
|
valid = (country_code != NULL);
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
if (!valid)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
|
|
|
pdc_warning(pdc, PDC_E_ILLARG_LANG_CODE,
|
|
|
|
lang_code, 0, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pdc_free(pdc, language);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return valid;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------- Bit arryas ------------------------------ */
|
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
/* set bit right to left within a byte */
|
2006-05-04 16:36:51 +00:00
|
|
|
void
|
|
|
|
pdc_setbit(char *bitarr, int bit)
|
|
|
|
{
|
|
|
|
bitarr[bit/8] |= (char) (1<<(bit%8));
|
|
|
|
}
|
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
/* set bit left to right within a byte */
|
|
|
|
void
|
|
|
|
pdc_setbit_l2r(char *bitarr, int bit)
|
|
|
|
{
|
|
|
|
bitarr[bit/8] |= (char) (0x80>>(bit%8));
|
|
|
|
}
|
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
pdc_bool
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_getbit(const char *bitarr, int bit)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
|
|
|
return (pdc_bool) (bitarr[bit/8] & (1<<(bit%8)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
pdc_setbit_text(char *bitarr, const pdc_byte *text, int len,
|
|
|
|
int nbits, int size)
|
|
|
|
{
|
|
|
|
int i, bit;
|
|
|
|
pdc_ushort *ustext = (pdc_ushort *) text;
|
|
|
|
|
|
|
|
for (i = 0; i < len; i += size)
|
|
|
|
{
|
|
|
|
if (size == sizeof(pdc_byte))
|
|
|
|
bit = (int) text[i];
|
|
|
|
else
|
|
|
|
bit = ustext[i/size];
|
|
|
|
if (bit < nbits) pdc_setbit(bitarr, bit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------- Get functions of integer binary data types --------------- */
|
|
|
|
|
|
|
|
pdc_short
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_get_le_short(const pdc_byte *data)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
|
|
|
return (pdc_short) ((pdc_short) (data[1] << 8) | data[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
pdc_ushort
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_get_le_ushort(const pdc_byte *data)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
|
|
|
return (pdc_ushort) ((data[1] << 8) | data[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
pdc_uint32
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_get_le_ulong3(const pdc_byte *data)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
|
|
|
return (pdc_uint32) (((((data[2]) << 8) | data[1]) << 8) | data[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
pdc_sint32
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_get_le_long(const pdc_byte *data)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
|
|
|
return ((pdc_sint32)
|
|
|
|
(((((data[3] << 8) | data[2]) << 8) | data[1]) << 8) | data[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
pdc_uint32
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_get_le_ulong(const pdc_byte *data)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
|
|
|
return (pdc_uint32)
|
|
|
|
((((((data[3] << 8) | data[2]) << 8) | data[1]) << 8) | data[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
pdc_short
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_get_be_short(const pdc_byte *data)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
|
|
|
return (pdc_short) ((pdc_short) (data[0] << 8) | data[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
pdc_ushort
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_get_be_ushort(const pdc_byte *data)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
|
|
|
return (pdc_ushort) ((data[0] << 8) | data[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
pdc_uint32
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_get_be_ulong3(const pdc_byte *data)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
|
|
|
return (pdc_uint32) (((((data[0]) << 8) | data[1]) << 8) | data[2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
pdc_sint32
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_get_be_long(const pdc_byte *data)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
|
|
|
return ((pdc_sint32)
|
|
|
|
(((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3]);
|
|
|
|
}
|
|
|
|
|
|
|
|
pdc_uint32
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_get_be_ulong(const pdc_byte *data)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
|
|
|
return (pdc_uint32)
|
|
|
|
((((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ----------------- String handling for Unicode too ------------------- */
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
/* strlen() for wide character strings, which are double null terminated.
|
|
|
|
* pdc_wstrlen() returns the number of bytes in the Unicode string,
|
|
|
|
* NOT including the two terminating null bytes.
|
2006-05-04 16:36:51 +00:00
|
|
|
*/
|
2008-10-20 14:35:00 +00:00
|
|
|
size_t
|
|
|
|
pdc_wstrlen(const char *str)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
|
|
|
size_t len = 0;
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
while(str[len] != 0 || str[len+1] != 0)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
|
|
|
len += 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function returns the length in bytes for C and Unicode strings.
|
|
|
|
*/
|
|
|
|
size_t
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_strlen(const char *str)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
if (pdc_is_utf16be_unicode(str) || pdc_is_utf16le_unicode(str))
|
|
|
|
return pdc_wstrlen(str);
|
2006-05-04 16:36:51 +00:00
|
|
|
else
|
2008-10-20 14:35:00 +00:00
|
|
|
return strlen(str);
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Allocate a local buffer and copy the string including
|
|
|
|
* the terminating sentinel. If the string starts with the Unicode BOM
|
|
|
|
* it is considered a Unicode string, and must be terminated by
|
|
|
|
* two null bytes. Otherwise it is considered a plain C string and
|
|
|
|
* must be terminated by a single null byte.
|
|
|
|
* The caller is responsible for freeing the buffer.
|
2008-10-20 14:35:00 +00:00
|
|
|
*
|
2009-03-23 08:55:58 +00:00
|
|
|
* The special functions pdc_strdup, pdc_strdup_tmp and pdc_strdup_withbom
|
2008-10-20 14:35:00 +00:00
|
|
|
* should be replaced by the more sophisticated function pdc_strdup_ext.
|
|
|
|
* There: flags (see pc_unicode.h):
|
|
|
|
*
|
2009-03-23 08:55:58 +00:00
|
|
|
* PDC_CONV_TMPALLOC, PDC_CONV_EBCDIC, PDC_CONV_ASCII,
|
|
|
|
* PDC_CONV_WITHBOM, PDC_CONV_NOBOM, PDC_CONV_MAXSTRLEN
|
2008-10-20 14:35:00 +00:00
|
|
|
*
|
2006-05-04 16:36:51 +00:00
|
|
|
*/
|
2008-10-20 14:35:00 +00:00
|
|
|
char *
|
|
|
|
pdc_strdup_ext(pdc_core *pdc, const char *text, int flags, const char *fn)
|
|
|
|
{
|
|
|
|
char *buf = NULL;
|
|
|
|
|
|
|
|
if (text != NULL)
|
|
|
|
{
|
|
|
|
size_t len = pdc_strlen(text) + 1;
|
2009-03-23 08:55:58 +00:00
|
|
|
size_t is = 0, it = 0;
|
|
|
|
|
|
|
|
if ((flags & PDC_CONV_MAXSTRLEN) && len > PDC_ERR_MAXSTRLEN)
|
|
|
|
len = PDC_ERR_MAXSTRLEN;
|
|
|
|
|
|
|
|
if ((flags & PDC_CONV_NOBOM) && pdc_is_utf8_bytecode(text))
|
|
|
|
is = 3;
|
2008-10-20 14:35:00 +00:00
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
if ((flags & PDC_CONV_WITHBOM) && !pdc_is_utf8_bytecode(text))
|
|
|
|
it = 3;
|
|
|
|
|
|
|
|
len += it - is;
|
2008-10-20 14:35:00 +00:00
|
|
|
if (flags & PDC_CONV_TMPALLOC)
|
|
|
|
buf = (char *) pdc_malloc_tmp(pdc, len + 1, fn, NULL, NULL);
|
|
|
|
else
|
|
|
|
buf = (char *) pdc_malloc(pdc, len + 1, fn);
|
2009-03-23 08:55:58 +00:00
|
|
|
|
|
|
|
memcpy(&buf[it], &text[is], len - it);
|
2008-10-20 14:35:00 +00:00
|
|
|
buf[len] = 0;
|
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
|
|
|
|
if (it == 3)
|
|
|
|
pdc_copy_utf8_bom(buf);
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
/* Convenience functions
|
|
|
|
*/
|
2006-05-04 16:36:51 +00:00
|
|
|
char *
|
2009-03-23 08:55:58 +00:00
|
|
|
pdc_strdup_tmp(pdc_core *pdc, const char *text)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2009-03-23 08:55:58 +00:00
|
|
|
static const char fn[] = "pdc_strdup_tmp";
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
return pdc_strdup_ext(pdc, text, PDC_CONV_TMPALLOC, fn);
|
|
|
|
}
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
char *
|
|
|
|
pdc_strdup_withbom(pdc_core *pdc, const char *text)
|
|
|
|
{
|
|
|
|
static const char fn[] = "pdc_strdup_withbom";
|
2008-10-20 14:35:00 +00:00
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
return pdc_strdup_ext(pdc, text, PDC_CONV_WITHBOM, fn);
|
2008-10-20 14:35:00 +00:00
|
|
|
}
|
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
/* Rapid function
|
|
|
|
*/
|
2008-10-20 14:35:00 +00:00
|
|
|
char *
|
2009-03-23 08:55:58 +00:00
|
|
|
pdc_strdup(pdc_core *pdc, const char *text)
|
2008-10-20 14:35:00 +00:00
|
|
|
{
|
|
|
|
char *buf = NULL;
|
2009-03-23 08:55:58 +00:00
|
|
|
static const char fn[] = "pdc_strdup";
|
2008-10-20 14:35:00 +00:00
|
|
|
|
|
|
|
if (text != NULL)
|
|
|
|
{
|
2009-03-23 08:55:58 +00:00
|
|
|
size_t len = pdc_strlen(text) + 1;
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
buf = (char *) pdc_malloc(pdc, len + 1, fn);
|
|
|
|
memcpy(buf, text, len);
|
|
|
|
buf[len] = 0;
|
|
|
|
}
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
2009-03-23 08:55:58 +00:00
|
|
|
pdc_strdup2(pdc_core *pdc, const char *text, size_t len)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
char *buf = NULL;
|
2009-03-23 08:55:58 +00:00
|
|
|
static const char fn[] = "pdc_strdup2";
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
if (text != NULL)
|
|
|
|
{
|
2009-03-23 08:55:58 +00:00
|
|
|
buf = (char *) pdc_malloc(pdc, len + 1, fn);
|
2008-10-20 14:35:00 +00:00
|
|
|
memcpy(buf, text, len);
|
|
|
|
buf[len] = 0;
|
|
|
|
}
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
/* Convert Pascal string to a null terminated C string.
|
|
|
|
* Size of C string: at least 256 bytes
|
2006-05-04 16:36:51 +00:00
|
|
|
*/
|
2009-03-23 08:55:58 +00:00
|
|
|
int
|
|
|
|
pdc_convert_pascal_str(const char *pstr, char *cstr)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2009-03-23 08:55:58 +00:00
|
|
|
int len = (int) *((pdc_byte *) pstr);
|
2008-10-20 14:35:00 +00:00
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
memcpy(cstr, pstr + 1, (size_t) len);
|
|
|
|
cstr[len] = 0;
|
2008-10-20 14:35:00 +00:00
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
return len;
|
2008-10-20 14:35:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
pdc_strdup_convert(pdc_core *pdc, pdc_encoding encto, pdc_encoding encfrom,
|
|
|
|
const char *text, int flags, const char *fn)
|
|
|
|
{
|
|
|
|
pdc_encodingvector *evfrom, *evto;
|
|
|
|
char *buf;
|
|
|
|
size_t len;
|
|
|
|
int i;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
evto = pdc_get_encoding_vector(pdc, encto);
|
|
|
|
evfrom = pdc_get_encoding_vector(pdc, encfrom);
|
|
|
|
buf = pdc_strdup_ext(pdc, text, flags, fn);
|
|
|
|
len = strlen(buf);
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
for (i = 0; i < (int) len; i++)
|
|
|
|
buf[i] = (char) pdc_transform_bytecode(pdc, evto, evfrom,
|
|
|
|
(pdc_byte) text[i]);
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_bool
|
|
|
|
pdc_logg_isprint(int c)
|
|
|
|
{
|
|
|
|
if (c < 0x20 || (c >= 0x7F && c < 0xA0))
|
|
|
|
return pdc_false;
|
|
|
|
return pdc_true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
/*
|
|
|
|
* Put out an arbitrary string.
|
|
|
|
*
|
|
|
|
* strform = readable: Direct byte output with replacing not
|
|
|
|
* printable bytes by their octal codes.
|
|
|
|
* = readable0: Like readable, but byte 0 will be displayed as space.
|
|
|
|
* = octal: All bytes will be put out as octal.
|
|
|
|
* = hexa: All bytes will be put out as hexadecimal value.
|
|
|
|
* = java: Like readable, but Unicode strings and not printable
|
|
|
|
* bytes will be put out in Java notation \uxxxx,
|
|
|
|
*
|
|
|
|
* Output string is temporarily allocated.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
pdc_strprint(pdc_core *pdc, const char *str, int leni, int maxchar,
|
|
|
|
pdc_strform_kind strform)
|
|
|
|
{
|
|
|
|
static const char fn[] = "pdc_strprint";
|
|
|
|
|
|
|
|
if (str != NULL)
|
|
|
|
{
|
|
|
|
pdc_bool isunicode = pdc_false;
|
|
|
|
int len = leni;
|
|
|
|
|
|
|
|
if (!leni)
|
|
|
|
len = (int) strlen(str);
|
|
|
|
|
|
|
|
if (len)
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_strform_kind sf = strform;
|
2006-05-04 16:36:51 +00:00
|
|
|
char *ts, *tmpstr;
|
|
|
|
pdc_byte c = ' ', cp = '.';
|
|
|
|
pdc_ushort *ush = (pdc_ushort *) str;
|
|
|
|
int i, im;
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
/* because of strform_java: \uxxxx: factor 6 */
|
|
|
|
tmpstr = (char *) pdc_calloc_tmp(pdc, (size_t) (6 * (len + 4)), fn,
|
2006-05-04 16:36:51 +00:00
|
|
|
NULL, NULL);
|
|
|
|
ts = tmpstr;
|
|
|
|
|
|
|
|
if (strform == strform_java)
|
|
|
|
{
|
|
|
|
if (leni && !(leni % 2))
|
|
|
|
isunicode = pdc_true;
|
|
|
|
else
|
|
|
|
strform = strform_readable;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (maxchar <= 0)
|
|
|
|
maxchar = len;
|
|
|
|
im = (maxchar < len) ? maxchar : len;
|
|
|
|
if (isunicode)
|
|
|
|
im = im/2;
|
|
|
|
for (i = 0; i < im; i++)
|
|
|
|
{
|
|
|
|
if (isunicode)
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
if (ush[i] > PDC_UNICODE_MAXLATIN1)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
|
|
|
sf = strform_java;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
c = (pdc_byte) ush[i];
|
2008-10-20 14:35:00 +00:00
|
|
|
sf = strform;
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
c = (pdc_byte) str[i];
|
|
|
|
sf = strform;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (sf)
|
|
|
|
{
|
|
|
|
case strform_hexa:
|
|
|
|
ts += sprintf(ts, "\\x%02X", c);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case strform_octal:
|
|
|
|
ts += sprintf(ts, "\\%03o", c);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case strform_java:
|
|
|
|
ts += sprintf(ts, "\\u%04X", ush[i]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2008-10-20 14:35:00 +00:00
|
|
|
if (c == 0x00 && sf == strform_readable0)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
c = 0x20;
|
|
|
|
|
|
|
|
*ts = (char) c;
|
|
|
|
ts++;
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
if (!pdc_logg_isprint((int) c))
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
if (isunicode)
|
|
|
|
ts += sprintf(ts, "\\u%04X", c);
|
|
|
|
else
|
|
|
|
ts += sprintf(ts, "\\%03o", c);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (c == '"')
|
|
|
|
{
|
|
|
|
*ts = '\\';
|
|
|
|
ts++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*ts = (char) c;
|
2006-05-04 16:36:51 +00:00
|
|
|
ts++;
|
|
|
|
}
|
2008-10-20 14:35:00 +00:00
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (maxchar < len)
|
|
|
|
{
|
|
|
|
switch (strform)
|
|
|
|
{
|
|
|
|
case strform_hexa:
|
|
|
|
ts += sprintf(ts, "\\x%02X\\x%02X\\x%02X", cp, cp, cp);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case strform_octal:
|
|
|
|
ts += sprintf(ts, "\\%03o\\%03o\\%03o", cp, cp, cp);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case strform_java:
|
|
|
|
ts += sprintf(ts, "\\u%04X\\u%04X\\u%04X", cp, cp, cp);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ts += sprintf(ts, "%c%c%c", cp, cp, cp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return tmpstr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (char *) pdc_calloc_tmp(pdc, 1, fn, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
/*
|
|
|
|
* Returned string is temporary allocated.
|
|
|
|
*/
|
2006-05-04 16:36:51 +00:00
|
|
|
const char *
|
|
|
|
pdc_utf8strprint(pdc_core *pdc, const char *str)
|
|
|
|
{
|
2009-03-23 08:55:58 +00:00
|
|
|
static const char fn[] = "pdc_utf8strprint";
|
|
|
|
|
|
|
|
return pdc_strdup_ext(pdc, str,
|
|
|
|
PDC_CONV_TMPALLOC | PDC_CONV_NOBOM | PDC_CONV_MAXSTRLEN, fn);
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Split a given text string into single strings which are separated by
|
|
|
|
* arbitrary characters. This characters must be specified in a string.
|
|
|
|
* If this string is NULL, " \f\n\r\t\v" (standard white spaces) is assumed.
|
|
|
|
*
|
|
|
|
* There is the convention that text inside braces {} will be taken verbatim.
|
|
|
|
* Inside brace expressions braces must exist only in pairs. Braces are
|
|
|
|
* masked by backslash.
|
|
|
|
*
|
|
|
|
* The caller is responsible for freeing the resultated string list
|
|
|
|
* by calling the function pdc_cleanup_stringlist.
|
|
|
|
*
|
|
|
|
* Not for unicode strings.
|
|
|
|
*
|
|
|
|
* Return value: Number of strings.
|
|
|
|
* If braces aren't balanced the number is negative.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
pdc_split_stringlist(pdc_core *pdc, const char *text, const char *i_separstr,
|
2008-10-20 14:35:00 +00:00
|
|
|
int flags, char ***stringlist)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
|
|
|
static const char fn[] = "pdc_split_stringlist";
|
|
|
|
const char *separstr = " \f\n\r\t\v";
|
|
|
|
const char *oldtext;
|
2009-03-23 08:55:58 +00:00
|
|
|
char **strlist = NULL, *newtext = NULL;
|
2008-10-20 14:35:00 +00:00
|
|
|
int it, len, jt = 0, jtb = 0, maxk = 0, count = 0, inside = 0;
|
|
|
|
int ns, nbs = 0, nbss;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
if (stringlist)
|
|
|
|
*stringlist = NULL;
|
|
|
|
if (i_separstr)
|
|
|
|
separstr = i_separstr;
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
if (text == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
/* check for empty string */
|
2008-10-20 14:35:00 +00:00
|
|
|
ns = (int) strspn(text, separstr);
|
|
|
|
oldtext = &text[ns];
|
2006-05-04 16:36:51 +00:00
|
|
|
len = (int) strlen(oldtext);
|
2009-03-23 08:55:58 +00:00
|
|
|
if (!len)
|
|
|
|
return 0;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
/* check for UTF-8-BOM */
|
|
|
|
if (pdc_is_utf8_bytecode(oldtext))
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
oldtext = &text[ns + 3];
|
2006-05-04 16:36:51 +00:00
|
|
|
len -= 3;
|
2008-10-20 14:35:00 +00:00
|
|
|
ns = (int) strspn(oldtext, separstr);
|
|
|
|
oldtext = &oldtext[ns];
|
|
|
|
len -= ns;
|
2009-03-23 08:55:58 +00:00
|
|
|
if (!len)
|
|
|
|
return 0;
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* new string */
|
2009-03-23 08:55:58 +00:00
|
|
|
if (stringlist != NULL)
|
|
|
|
newtext = (char *) pdc_malloc(pdc, (size_t) (len + 1), fn);
|
2006-05-04 16:36:51 +00:00
|
|
|
for (it = 0; it <= len; it++)
|
|
|
|
{
|
|
|
|
/* check for separators */
|
|
|
|
if (it == len)
|
2008-10-20 14:35:00 +00:00
|
|
|
ns = 1;
|
2006-05-04 16:36:51 +00:00
|
|
|
else if (inside <= 0)
|
2008-10-20 14:35:00 +00:00
|
|
|
ns = (int) strspn(&oldtext[it], separstr);
|
2006-05-04 16:36:51 +00:00
|
|
|
else
|
2008-10-20 14:35:00 +00:00
|
|
|
ns = 0;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
/* close text part */
|
2008-10-20 14:35:00 +00:00
|
|
|
if (ns)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2009-03-23 08:55:58 +00:00
|
|
|
if (stringlist != NULL)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2009-03-23 08:55:58 +00:00
|
|
|
newtext[jt] = 0;
|
|
|
|
if (count == maxk)
|
|
|
|
{
|
|
|
|
maxk += 16;
|
|
|
|
strlist = (char **) pdc_realloc(pdc, strlist,
|
|
|
|
maxk * sizeof(char *), fn);
|
|
|
|
}
|
|
|
|
strlist[count] = &newtext[jtb];
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
count++;
|
|
|
|
|
|
|
|
/* Exit */
|
2008-10-20 14:35:00 +00:00
|
|
|
it += ns;
|
2006-05-04 16:36:51 +00:00
|
|
|
if (it >= len ) break;
|
|
|
|
|
|
|
|
/* new text part */
|
|
|
|
jt++;
|
|
|
|
jtb = jt;
|
|
|
|
}
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
/* option list */
|
2009-03-23 08:55:58 +00:00
|
|
|
if (flags & PDC_SPLIT_ISOPTLIST)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
/* save backslash counter */
|
|
|
|
nbss = nbs;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
/* backslash */
|
|
|
|
if (oldtext[it] == '\\')
|
|
|
|
{
|
|
|
|
nbs++;
|
|
|
|
if (!(nbs % 2) && inside <= 1)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nbs = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* open and close brace */
|
|
|
|
if (oldtext[it] == '{')
|
|
|
|
{
|
|
|
|
if (!(nbss % 2))
|
|
|
|
{
|
|
|
|
inside++;
|
|
|
|
if (inside == 1)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (inside <= 1)
|
|
|
|
{
|
|
|
|
jt--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (oldtext[it] == '}')
|
|
|
|
{
|
|
|
|
if (!(nbss % 2))
|
|
|
|
{
|
|
|
|
inside--;
|
|
|
|
if (inside == 0)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (inside <= 1)
|
|
|
|
{
|
|
|
|
jt--;
|
|
|
|
}
|
|
|
|
}
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
/* argument list */
|
|
|
|
else if (flags & PDC_SPLIT_ISARGLIST)
|
|
|
|
{
|
|
|
|
/* save backslash counter */
|
|
|
|
nbss = nbs;
|
|
|
|
|
|
|
|
/* backslash */
|
|
|
|
if (oldtext[it] == '\\')
|
|
|
|
{
|
|
|
|
nbs++;
|
|
|
|
if (!(nbs % 2))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nbs = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* open and close quotation mark */
|
|
|
|
if (oldtext[it] == '"')
|
|
|
|
{
|
|
|
|
if (!(nbss % 2))
|
|
|
|
{
|
|
|
|
inside = 1 - inside;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
jt--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
/* save character */
|
2009-03-23 08:55:58 +00:00
|
|
|
if (stringlist != NULL)
|
|
|
|
{
|
|
|
|
newtext[jt] = oldtext[it];
|
|
|
|
jt++;
|
|
|
|
}
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
if (stringlist != NULL)
|
2006-05-04 16:36:51 +00:00
|
|
|
*stringlist = strlist;
|
2008-10-20 14:35:00 +00:00
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
return inside ? -count : count;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
pdc_cleanup_stringlist(pdc_core *pdc, char **stringlist)
|
|
|
|
{
|
|
|
|
if(stringlist != NULL)
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
if(stringlist[0] != NULL)
|
|
|
|
pdc_free(pdc, stringlist[0]);
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_free(pdc, stringlist);
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Substitute a list of variables in a string by its values recursively.
|
|
|
|
* A variable begins with the character 'vchar' and ends at a character
|
|
|
|
* in 'delimiters' or at the end of string resp..
|
|
|
|
*
|
|
|
|
* The character 'vchar' must be masked by 'vchar'.
|
|
|
|
*
|
|
|
|
* If at least one of a variable was substituted, a new allocated null
|
|
|
|
* terminated string is returned. Otherwise the original pointer.
|
|
|
|
*
|
|
|
|
* The caller is responsible for freeing the new string.
|
|
|
|
*
|
|
|
|
* string null terminated string with variables
|
|
|
|
* vchar begin character for a variable
|
|
|
|
* delimiters string with characters delimiting a variable name
|
|
|
|
* varslist list of variable names
|
|
|
|
* valslist list of variable values
|
|
|
|
* nvars number of variables
|
|
|
|
* errind[2] contains index and length of an unkown variable in string
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
static char *
|
|
|
|
substitute_variables(pdc_core *pdc, char *string, int ibeg, int *level,
|
|
|
|
const char **varslist, const char **valslist, int nvars, char vchar,
|
|
|
|
const char *separstr, int *errind)
|
|
|
|
{
|
|
|
|
static const char fn[] = "substitue_variables";
|
|
|
|
int i, j, l;
|
|
|
|
|
|
|
|
j = ibeg;
|
|
|
|
for (i = ibeg; string[i] != 0; i++)
|
|
|
|
{
|
|
|
|
if (string[i] == vchar)
|
|
|
|
{
|
|
|
|
if (string[i + 1] == vchar)
|
|
|
|
i++;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
string[j] = string[i];
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (string[i] != 0)
|
|
|
|
{
|
|
|
|
char *s = &string[i + 1];
|
|
|
|
size_t n = strcspn(s, separstr);
|
|
|
|
|
|
|
|
for (l = 0; l < nvars; l++)
|
|
|
|
{
|
|
|
|
if (n == strlen(varslist[l]) && !strncmp(s, varslist[l], n))
|
|
|
|
{
|
|
|
|
char *newstring;
|
|
|
|
int k = (int) (i + n + 1);
|
|
|
|
size_t nv = strlen(valslist[l]);
|
|
|
|
size_t nr = strlen(&string[k]);
|
|
|
|
size_t nb = (size_t) j + nv + nr + 1;
|
|
|
|
|
|
|
|
newstring = (char *) pdc_malloc(pdc, nb, fn);
|
|
|
|
strncpy(newstring, string, (size_t) j);
|
|
|
|
strncpy(&newstring[j], valslist[l], nv);
|
|
|
|
strcpy(&newstring[j + nv], &string[k]);
|
|
|
|
|
|
|
|
pdc_free(pdc, string);
|
|
|
|
(*level)++;
|
|
|
|
|
|
|
|
string = substitute_variables(pdc, newstring, j, level,
|
|
|
|
varslist, valslist, nvars, vchar, separstr,
|
|
|
|
errind);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (l == nvars)
|
|
|
|
{
|
|
|
|
errind[0] = i;
|
|
|
|
errind[1] = (int) (n + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
string[j] = 0;
|
|
|
|
}
|
|
|
|
return string;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
pdc_substitute_variables(pdc_core *pdc, const char *string, char vchar,
|
|
|
|
const char *delimiters, const char **varslist,
|
|
|
|
const char **valslist, int nvars, int *errind)
|
|
|
|
{
|
|
|
|
static const char fn[] = "pdc_substitue_variables";
|
|
|
|
char *subststr, *newstring, separstr[64];
|
|
|
|
int level = 0;
|
|
|
|
|
|
|
|
newstring = pdc_strdup_ext(pdc, string, 0, fn);
|
|
|
|
|
|
|
|
separstr[0] = vchar;
|
|
|
|
separstr[1] = 0;
|
|
|
|
strcat(separstr, delimiters);
|
|
|
|
|
|
|
|
errind[0] = -1;
|
|
|
|
errind[1] = 0;
|
|
|
|
subststr = substitute_variables(pdc, newstring, 0, &level,
|
|
|
|
varslist, valslist, nvars, vchar, separstr, errind);
|
|
|
|
|
|
|
|
return subststr;
|
|
|
|
}
|
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
/*
|
|
|
|
* Compares its arguments and returns an integer less than,
|
|
|
|
* equal to, or greater than zero, depending on whether s1
|
|
|
|
* is lexicographically less than, equal to, or greater than s2.
|
|
|
|
* Null pointer values for s1 and s2 are treated the same as pointers
|
|
|
|
* to empty strings.
|
|
|
|
*
|
|
|
|
* Presupposition: basic character set
|
|
|
|
*
|
|
|
|
* Return value: < 0 s1 < s2;
|
2008-10-20 14:35:00 +00:00
|
|
|
* = 0 s1 == s2;
|
|
|
|
* > 0 s1 > s2;
|
2006-05-04 16:36:51 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
int
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_strcmp(const char *s1, const char *s2)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
if (s1 == s2) return (0);
|
|
|
|
if (s1 == NULL) return (-1);
|
|
|
|
if (s2 == NULL) return (1);
|
|
|
|
|
|
|
|
return strcmp(s1, s2);
|
|
|
|
}
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
int
|
|
|
|
pdc_stricmp(const char *s1, const char *s2)
|
|
|
|
{
|
2006-05-04 16:36:51 +00:00
|
|
|
if (s1 == s2) return (0);
|
|
|
|
if (s1 == NULL) return (-1);
|
|
|
|
if (s2 == NULL) return (1);
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
for (; *s1; ++s1, ++s2)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
if (pdc_tolower(*s1) != pdc_tolower(*s2))
|
|
|
|
break;
|
|
|
|
}
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
return (pdc_tolower(*s1) - pdc_tolower(*s2));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
pdc_stricmp_a(const char *s1, const char *s2)
|
|
|
|
{
|
|
|
|
if (s1 == s2) return (0);
|
|
|
|
if (s1 == NULL) return (-1);
|
|
|
|
if (s2 == NULL) return (1);
|
|
|
|
|
|
|
|
for (; *s1; ++s1, ++s2)
|
|
|
|
{
|
|
|
|
if (pdc_tolower_a(*s1) != pdc_tolower_a(*s2))
|
|
|
|
break;
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
return (pdc_tolower_a(*s1) - pdc_tolower_a(*s2));
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
/*
|
|
|
|
* Same like pdc_strcmp, except that the strings can be
|
|
|
|
* wide character strings with nulls and double null terminated.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
pdc_wstrcmp(const char *s1, const char *s2)
|
|
|
|
{
|
|
|
|
size_t len1, len2, len;
|
|
|
|
int res;
|
|
|
|
|
|
|
|
if (s1 == s2) return (0);
|
|
|
|
if (s1 == NULL) return (-1);
|
|
|
|
if (s2 == NULL) return (1);
|
|
|
|
|
|
|
|
len1 = pdc_strlen(s1);
|
|
|
|
len2 = pdc_strlen(s2);
|
|
|
|
len = MIN(len1, len2);
|
|
|
|
|
|
|
|
res = memcmp(s1, s2, len);
|
|
|
|
|
|
|
|
if (!res && len1 != len2)
|
|
|
|
res = (len1 < len2) ? -1 : 1;
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Compares its arguments and returns an integer less than,
|
|
|
|
* equal to, or greater than zero, depending on whether s1
|
|
|
|
* is lexicographically less than, equal to, or greater than s2.
|
|
|
|
* But only up to n characters compared (n less than or equal
|
|
|
|
* to zero yields equality).Null pointer values for s1 and s2
|
|
|
|
* are treated the same as pointers to empty strings.
|
|
|
|
*
|
|
|
|
* Presupposition: basic character set
|
|
|
|
*
|
|
|
|
* Return value: < 0 s1 < s2;
|
2008-10-20 14:35:00 +00:00
|
|
|
* = 0 s1 == s2;
|
|
|
|
* > 0 s1 > s2;
|
2006-05-04 16:36:51 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
pdc_strincmp(const char *s1, const char *s2, int n)
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
int i;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
if (s1 == s2) return (0);
|
|
|
|
if (s1 == NULL) return (-1);
|
|
|
|
if (s2 == NULL) return (1);
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
for (i = 0; i < n && *s1 && *s2; ++i, ++s1, ++s2)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
if (pdc_tolower(*s1) != pdc_tolower(*s2))
|
|
|
|
break;
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
2008-10-20 14:35:00 +00:00
|
|
|
|
|
|
|
return (i == n) ? 0 : (pdc_tolower(*s1) - pdc_tolower(*s2));
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* pdc_strtrim removes trailing white space characters from an input string.
|
|
|
|
* pdc_str2trim removes leading and trailing white space characters from an
|
|
|
|
* input string..
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
pdc_strtrim(char *str)
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
int i, n;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
n = (int) strlen(str);
|
|
|
|
for (i = n - 1; i >= 0; i--)
|
|
|
|
if (!pdc_isspace(str[i])) break;
|
2006-05-04 16:36:51 +00:00
|
|
|
str[i + 1] = '\0';
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
pdc_str2trim(char *str)
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
int i, n;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
n = (int) strlen(str);
|
|
|
|
for (i = n - 1; i >= 0; i--)
|
|
|
|
if (!pdc_isspace(str[i])) break;
|
2006-05-04 16:36:51 +00:00
|
|
|
str[i + 1] = '\0';
|
|
|
|
|
|
|
|
for (i = 0; ; i++)
|
2008-10-20 14:35:00 +00:00
|
|
|
if (!pdc_isspace(str[i])) break;
|
2006-05-04 16:36:51 +00:00
|
|
|
if (i > 0)
|
|
|
|
memmove(str, &str[i], strlen(&str[i]) + 1);
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
char *
|
|
|
|
pdc_strtoupper(char *str)
|
|
|
|
{
|
|
|
|
int i, n;
|
|
|
|
|
|
|
|
n = (int) strlen(str);
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
str[i] = (char) pdc_toupper(str[i]);
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
pdc_strtolower(char *str)
|
|
|
|
{
|
|
|
|
int i, n;
|
|
|
|
|
|
|
|
n = (int) strlen(str);
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
str[i] = (char) pdc_tolower(str[i]);
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
void
|
2009-03-23 08:55:58 +00:00
|
|
|
pdc_swap_bytes2(const char *instring, int inlen, char *outstring)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2009-03-23 08:55:58 +00:00
|
|
|
pdc_ushort *inp, *outp;
|
|
|
|
int i;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
if (instring == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (outstring == NULL)
|
2009-03-23 08:55:58 +00:00
|
|
|
outstring = (char *) instring;
|
|
|
|
|
|
|
|
inp = (pdc_ushort *) instring;
|
|
|
|
outp = (pdc_ushort *) outstring;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
inlen /= sizeof(pdc_ushort);
|
2006-05-04 16:36:51 +00:00
|
|
|
for (i = 0; i < inlen; i++)
|
|
|
|
{
|
2009-03-23 08:55:58 +00:00
|
|
|
outp[i] = (pdc_ushort) (((inp[i] & (pdc_ushort)0x00FFu) << 8) |
|
|
|
|
((inp[i] & (pdc_ushort)0xFF00u) >> 8));
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-03-23 08:55:58 +00:00
|
|
|
pdc_swap_bytes4(const char *instring, int inlen, char *outstring)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2009-03-23 08:55:58 +00:00
|
|
|
pdc_uint32 *inp, *outp;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (instring == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (outstring == NULL)
|
|
|
|
outstring = (char *) instring;
|
|
|
|
|
|
|
|
inp = (pdc_uint32 *) instring;
|
|
|
|
outp = (pdc_uint32 *) outstring;
|
|
|
|
|
|
|
|
inlen /= sizeof(pdc_uint32);
|
|
|
|
for (i = 0; i < inlen; i++)
|
|
|
|
{
|
|
|
|
outp[i] = (pdc_uint32) (((inp[i] & (pdc_uint32)0x000000FFu) << 24) |
|
|
|
|
((inp[i] & (pdc_uint32)0x0000FF00u) << 8) |
|
|
|
|
((inp[i] & (pdc_uint32)0x00FF0000u) >> 8) |
|
|
|
|
((inp[i] & (pdc_uint32)0xFF000000u) >> 24));
|
|
|
|
}
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
pdc_inflate_ascii(const char *instring, int inlen, char *outstring,
|
|
|
|
pdc_text_format textformat)
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
pdc_bool is_bigendian = (textformat == pdc_utf16be) ||
|
|
|
|
(textformat == pdc_utf16 && PDC_ISBIGENDIAN);
|
|
|
|
|
|
|
|
j = 0;
|
|
|
|
for (i = 0; i < inlen; i++)
|
|
|
|
{
|
|
|
|
if (is_bigendian)
|
|
|
|
{
|
|
|
|
outstring[j] = 0;
|
|
|
|
j++;
|
|
|
|
outstring[j] = instring[i];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
outstring[j] = instring[i];
|
|
|
|
j++;
|
|
|
|
outstring[j] = 0;
|
|
|
|
}
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
/*
|
|
|
|
* pdc_stresc --
|
|
|
|
* Remove from a string containing escaped non-printable cha-
|
|
|
|
* racters. The string must follows the C-standard escape
|
|
|
|
* mechanism: an escaped character is preceeded by an escape
|
|
|
|
* character which is a backslash '\' character and followed
|
|
|
|
* by one or more characters to define the non-printable
|
|
|
|
* character to be inserted here. The supported escapes are
|
|
|
|
*
|
|
|
|
* \a bell (ASCII/EBCDIC-BEL)
|
|
|
|
* \b backspace (ASCII/EBCDIC-BS)
|
|
|
|
* \e escape charater (ASCII/EBCDIC-ESC)
|
|
|
|
* \f formfeed (ASCII/EBCDIC-FF)
|
|
|
|
* \n linefeed (ASCII/EBCDIC-LF)
|
|
|
|
* \r return (ASCII/EBCDIC-CR)
|
|
|
|
* \t tab character (ASCII/EBCDIC-TAB)
|
|
|
|
* \v vertical tab (ASCII/EBCDIC-VT)
|
|
|
|
* \\ the slash itself
|
|
|
|
* \xnn two hex digits n to define a
|
|
|
|
* character numerically as ASCII/EBCDIC value.
|
|
|
|
* \nnn three octal digits n to define a
|
|
|
|
* character numerically as ASCII/EBCDIC value.
|
|
|
|
*
|
|
|
|
* For example: \x0A, \x0a or \012 has the same effect in ASCII
|
|
|
|
* as \n (i.e linefeed).
|
|
|
|
* Note, if the last character in a string is the backslash
|
|
|
|
* then the backslash is illegal.
|
|
|
|
* The special characters a,b,e,f, and so on are recognized in
|
|
|
|
* lower case only.
|
|
|
|
*
|
|
|
|
* textformat:
|
|
|
|
* pdc_bytes: Latin1 or EBCDIC bytes on EBCDIC platforms
|
|
|
|
* pdc_utf8: Latin1
|
|
|
|
* pdc_ebcdicutf8: EBCDIC - only on EBCDIC platforms
|
|
|
|
* pdc_utf16: 2 bytes Latin1
|
|
|
|
*
|
|
|
|
* If a illegal escaped sequence was detected an exception will
|
|
|
|
* be thrown (verbose == pdc_true) or the sequence will be taken
|
|
|
|
* as it (verbose == pdc_false).
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
static const pdc_keyconn pdc_ascii_escape_keylist[] =
|
|
|
|
{
|
|
|
|
{"\\", 0x5C},
|
|
|
|
{"a", 0x07},
|
|
|
|
{"b", 0x08},
|
|
|
|
{"e", 0x1B},
|
|
|
|
{"f", 0x0C},
|
|
|
|
{"n", 0x0A},
|
|
|
|
{"r", 0x0D},
|
|
|
|
{"t", 0x09},
|
|
|
|
{"v", 0x0B},
|
|
|
|
{"x", 0x78},
|
|
|
|
{NULL, 0}
|
|
|
|
};
|
|
|
|
|
|
|
|
pdc_ushort
|
|
|
|
pdc_get_string_value(pdc_byte *str, int i, int charlen)
|
|
|
|
{
|
|
|
|
pdc_ushort retval = 0;
|
|
|
|
|
|
|
|
if (charlen == 1)
|
|
|
|
{
|
|
|
|
retval = (pdc_ushort) str[i];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pdc_ushort *ustr = (pdc_ushort *) str;
|
|
|
|
|
|
|
|
retval = ustr[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
pdc_subst_backslash(pdc_core *pdc, pdc_byte *str, int len,
|
|
|
|
pdc_encodingvector *ev, pdc_text_format textformat,
|
|
|
|
pdc_bool verbose)
|
|
|
|
{
|
|
|
|
pdc_ushort *ustr = (pdc_ushort *) str;
|
|
|
|
int charlen = (textformat == pdc_utf16) ? 2 : 1;
|
|
|
|
pdc_byte bschar = '\\';
|
|
|
|
pdc_ushort uv;
|
|
|
|
int i, j, k, code;
|
|
|
|
|
|
|
|
if (ev != NULL)
|
|
|
|
{
|
|
|
|
code = pdc_get_encoding_bytecode(pdc, ev, PDC_UNICODE_BACKSLASH);
|
|
|
|
if (code != -1)
|
|
|
|
bschar = (pdc_byte) code;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
j = 0;
|
|
|
|
len /= charlen;
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
{
|
|
|
|
uv = pdc_get_string_value(str, i, charlen);
|
|
|
|
if (uv > PDC_UNICODE_MAXLATIN1)
|
|
|
|
{
|
|
|
|
ustr[j] = uv;
|
|
|
|
j++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* backslash found */
|
|
|
|
if (uv == bschar)
|
|
|
|
{
|
|
|
|
pdc_byte escseq[4], stemp[6];
|
|
|
|
pdc_bool kerror = pdc_false;
|
|
|
|
|
|
|
|
i++;
|
|
|
|
if (i < len)
|
|
|
|
{
|
|
|
|
uv = pdc_get_string_value(str, i, charlen);
|
|
|
|
if (uv > PDC_UNICODE_MAXLATIN1)
|
|
|
|
goto PDC_OVERFLOW_EXIT;
|
|
|
|
|
|
|
|
escseq[0] = (pdc_byte) uv;
|
|
|
|
escseq[1] = 0;
|
|
|
|
|
|
|
|
code = pdc_get_keycode((char *) escseq,
|
|
|
|
pdc_ascii_escape_keylist);
|
|
|
|
if (code != PDC_KEY_NOTFOUND)
|
|
|
|
{
|
|
|
|
/* hex number */
|
|
|
|
if (code == 0x78)
|
|
|
|
{
|
|
|
|
for (k = 0; k < 2; k++)
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
if (i < len)
|
|
|
|
{
|
|
|
|
uv = pdc_get_string_value(str, i, charlen);
|
|
|
|
if (uv > PDC_UNICODE_MAXLATIN1)
|
|
|
|
goto PDC_OVERFLOW_EXIT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
uv = 0;
|
|
|
|
}
|
|
|
|
escseq[k] = (pdc_byte) uv;
|
|
|
|
}
|
|
|
|
escseq[k] = 0;
|
|
|
|
if (i >= len ||
|
|
|
|
!pdc_str2integer((char *) escseq, PDC_INT_UNICODE,
|
|
|
|
&uv))
|
|
|
|
{
|
|
|
|
strcpy((char *) stemp, "\\x");
|
|
|
|
strcat((char *) stemp, (char *) escseq);
|
|
|
|
kerror = pdc_true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pdc_char c = (pdc_char) code;
|
|
|
|
uv = (pdc_ushort) (pdc_byte) c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* octal number */
|
|
|
|
for (k = 0; k < 3; k++)
|
|
|
|
{
|
|
|
|
if (k) i++;
|
|
|
|
if (i < len)
|
|
|
|
{
|
|
|
|
uv = pdc_get_string_value(str, i, charlen);
|
|
|
|
if (uv > PDC_UNICODE_MAXLATIN1)
|
|
|
|
goto PDC_OVERFLOW_EXIT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
uv = 0;
|
|
|
|
}
|
|
|
|
escseq[k] = (pdc_byte) uv;
|
|
|
|
}
|
|
|
|
escseq[k] = 0;
|
|
|
|
if (i >= len ||
|
|
|
|
!pdc_str2integer((char *) escseq,
|
|
|
|
PDC_INT_SHORT |
|
|
|
|
PDC_INT_UNSIGNED |
|
|
|
|
PDC_INT_OCTAL,
|
|
|
|
&uv) ||
|
|
|
|
(charlen == 1 && uv > 0xFF))
|
|
|
|
{
|
|
|
|
strcpy((char *) stemp, "\\");
|
|
|
|
strcat((char *) stemp, (char *) escseq);
|
|
|
|
kerror = pdc_true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
strcpy((char *) stemp, "\\");
|
|
|
|
kerror = pdc_true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* error message */
|
|
|
|
if (kerror)
|
|
|
|
{
|
|
|
|
pdc_set_errmsg(pdc, PDC_E_STR_ILL_ESCSEQ, (char *) stemp,
|
|
|
|
0, 0, 0);
|
|
|
|
|
|
|
|
if (verbose)
|
|
|
|
pdc_error(pdc, -1, 0, 0, 0, 0);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (charlen == 1)
|
|
|
|
str[j] = (pdc_byte) uv;
|
|
|
|
else
|
|
|
|
ustr[j] = uv;
|
|
|
|
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (charlen == 1)
|
|
|
|
str[j] = 0;
|
|
|
|
else
|
|
|
|
ustr[j] = 0;
|
|
|
|
|
|
|
|
return charlen * j;
|
|
|
|
|
|
|
|
PDC_OVERFLOW_EXIT:
|
|
|
|
|
|
|
|
pdc_set_errmsg(pdc, PDC_E_STR_ILL_UNIESCSEQ,
|
|
|
|
pdc_errprintf(pdc, "%04X", uv), 0, 0, 0);
|
|
|
|
|
|
|
|
if (verbose)
|
|
|
|
pdc_error(pdc, -1, 0, 0, 0, 0);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
/* ----------------------- number converting ----------------------- */
|
|
|
|
|
|
|
|
/*
|
2008-10-20 14:35:00 +00:00
|
|
|
* pdc_str2double converts a null terminated and trimmed string
|
2006-05-04 16:36:51 +00:00
|
|
|
* to a double precision number
|
|
|
|
*/
|
|
|
|
pdc_bool
|
|
|
|
pdc_str2double(const char *string, double *o_dz)
|
|
|
|
{
|
|
|
|
const char *s = string;
|
|
|
|
double dz = 0;
|
|
|
|
int is = 1, isd = 0;
|
|
|
|
|
|
|
|
*o_dz = 0;
|
|
|
|
|
|
|
|
/* sign */
|
|
|
|
if (*s == '-')
|
|
|
|
{
|
|
|
|
is = -1;
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
else if (*s == '+')
|
|
|
|
s++;
|
|
|
|
|
|
|
|
if (!*s)
|
|
|
|
return pdc_false;
|
|
|
|
|
|
|
|
/* places before decimal point */
|
2008-10-20 14:35:00 +00:00
|
|
|
isd = pdc_isdigit(*s);
|
2006-05-04 16:36:51 +00:00
|
|
|
if (isd)
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
dz = 10 * dz + *s - '0';
|
|
|
|
s++;
|
|
|
|
}
|
2008-10-20 14:35:00 +00:00
|
|
|
while (pdc_isdigit(*s));
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* decimal point */
|
|
|
|
if (*s == '.' || *s == ',')
|
|
|
|
{
|
|
|
|
const char *sa;
|
|
|
|
double adz = 0;
|
|
|
|
|
|
|
|
s++;
|
2008-10-20 14:35:00 +00:00
|
|
|
isd = pdc_isdigit(*s);
|
2006-05-04 16:36:51 +00:00
|
|
|
if (!isd)
|
|
|
|
return pdc_false;
|
|
|
|
|
|
|
|
/* places after decimal point */
|
|
|
|
sa = s;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
adz = 10 * adz + *s - '0';
|
|
|
|
s++;
|
|
|
|
}
|
2008-10-20 14:35:00 +00:00
|
|
|
while (pdc_isdigit(*s));
|
2006-05-04 16:36:51 +00:00
|
|
|
dz += adz / pow(10.0, (double)(s - sa));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* power sign */
|
|
|
|
if (*s == 'e' || *s == 'E')
|
|
|
|
{
|
|
|
|
s++;
|
|
|
|
if (!isd)
|
|
|
|
return pdc_false;
|
|
|
|
|
|
|
|
/* sign */
|
|
|
|
if (!*s)
|
|
|
|
{
|
|
|
|
dz *= 10;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int isp = 1;
|
|
|
|
double pdz = 0, pdl = log10(dz);
|
|
|
|
|
|
|
|
if (*s == '-')
|
|
|
|
{
|
|
|
|
isp = -1;
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
else if (*s == '+')
|
|
|
|
s++;
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
if (!pdc_isdigit(*s))
|
2006-05-04 16:36:51 +00:00
|
|
|
return pdc_false;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
pdz = 10 * pdz + *s - '0';
|
|
|
|
s++;
|
|
|
|
}
|
2008-10-20 14:35:00 +00:00
|
|
|
while (pdc_isdigit(*s));
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
if (*s || fabs(pdl + pdz) > 300.0)
|
|
|
|
return pdc_false;
|
|
|
|
|
|
|
|
dz *= pow(10.0, isp * pdz);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(*s)
|
|
|
|
{
|
|
|
|
return pdc_false;
|
|
|
|
}
|
|
|
|
|
|
|
|
*o_dz = is * dz;
|
|
|
|
return pdc_true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2008-10-20 14:35:00 +00:00
|
|
|
* pdc_str2integer converts a null terminated and trimmed string
|
2006-05-04 16:36:51 +00:00
|
|
|
* to an hexadecimal or decimal integer number of arbitrary size
|
|
|
|
*/
|
|
|
|
pdc_bool
|
|
|
|
pdc_str2integer(const char *string, int flags, void *o_iz)
|
|
|
|
{
|
|
|
|
const char *s = string;
|
|
|
|
double dz = 0;
|
|
|
|
pdc_char cz = 0;
|
|
|
|
pdc_short sz = 0;
|
|
|
|
pdc_sint32 lz = 0;
|
|
|
|
pdc_byte ucz = 0;
|
|
|
|
pdc_ushort usz = 0;
|
|
|
|
pdc_uint32 ulz = 0;
|
|
|
|
int is = 1, lzd;
|
|
|
|
|
|
|
|
if (flags & PDC_INT_CHAR)
|
|
|
|
memcpy(o_iz, &cz, sizeof(pdc_char));
|
|
|
|
else if (flags & PDC_INT_SHORT)
|
|
|
|
memcpy(o_iz, &sz, sizeof(pdc_short));
|
|
|
|
else
|
|
|
|
memcpy(o_iz, &lz, sizeof(pdc_sint32));
|
|
|
|
|
|
|
|
/* sign */
|
|
|
|
if (*s == '-')
|
|
|
|
{
|
|
|
|
if (flags & PDC_INT_UNSIGNED)
|
|
|
|
return pdc_false;
|
|
|
|
is = -1;
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
else if (*s == '+')
|
|
|
|
s++;
|
|
|
|
|
|
|
|
if (!*s)
|
|
|
|
return pdc_false;
|
|
|
|
|
|
|
|
/* hexadecimal test */
|
|
|
|
if (!(flags & PDC_INT_DEC))
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
const char *ss = s;
|
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
if (*s == '<')
|
|
|
|
s += 1;
|
|
|
|
else if (*s == 'x' || *s == 'X')
|
|
|
|
s += 1;
|
|
|
|
else if (!strncmp(s, "0x", 2) || !strncmp(s, "0X", 2))
|
|
|
|
s += 2;
|
2008-10-20 14:35:00 +00:00
|
|
|
if (s > ss)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
|
|
|
if (!*s)
|
|
|
|
return pdc_false;
|
|
|
|
flags |= PDC_INT_HEXADEC;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* hexadecimal */
|
|
|
|
if (flags & PDC_INT_HEXADEC)
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
while (pdc_isxdigit(*s))
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
if (pdc_isalpha(*s))
|
|
|
|
lzd = (pdc_isupper(*s) ? 'A' : 'a') - 10;
|
2006-05-04 16:36:51 +00:00
|
|
|
else
|
|
|
|
lzd = '0';
|
|
|
|
dz = 16 * dz + *s - lzd;
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
if (*string == '<')
|
|
|
|
{
|
|
|
|
if (*s == '>')
|
|
|
|
s += 1;
|
|
|
|
else
|
|
|
|
return pdc_false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
/* octal */
|
|
|
|
if (flags & PDC_INT_OCTAL)
|
|
|
|
{
|
|
|
|
while (pdc_isdigit(*s) && *s < '8')
|
|
|
|
{
|
|
|
|
dz = 8 * dz + *s - '0';
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
/* decimal */
|
|
|
|
else
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
while (pdc_isdigit(*s))
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
|
|
|
dz = 10 * dz + *s - '0';
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (*s)
|
|
|
|
return pdc_false;
|
|
|
|
|
|
|
|
dz *= is;
|
|
|
|
if (flags & PDC_INT_CHAR)
|
|
|
|
{
|
|
|
|
if (flags & PDC_INT_UNSIGNED)
|
|
|
|
{
|
|
|
|
if (dz > PDC_UCHAR_MAX)
|
|
|
|
return pdc_false;
|
|
|
|
ucz = (pdc_byte) dz;
|
|
|
|
memcpy(o_iz, &ucz, sizeof(pdc_byte));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (dz < PDC_SCHAR_MIN || dz > PDC_SCHAR_MAX)
|
|
|
|
return pdc_false;
|
|
|
|
cz = (pdc_char) dz;
|
|
|
|
memcpy(o_iz, &cz, sizeof(pdc_char));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (flags & PDC_INT_SHORT)
|
|
|
|
{
|
|
|
|
if (flags & PDC_INT_UNSIGNED)
|
|
|
|
{
|
|
|
|
if (dz > PDC_USHRT_MAX)
|
|
|
|
return pdc_false;
|
|
|
|
usz = (pdc_ushort) dz;
|
|
|
|
memcpy(o_iz, &usz, sizeof(pdc_ushort));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (dz < PDC_SHRT_MIN || dz > PDC_SHRT_MAX)
|
|
|
|
return pdc_false;
|
|
|
|
sz = (pdc_short) dz;
|
|
|
|
memcpy(o_iz, &sz, sizeof(pdc_short));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (flags & PDC_INT_UNSIGNED)
|
|
|
|
{
|
|
|
|
if (dz > PDC_UINT_MAX)
|
|
|
|
return pdc_false;
|
|
|
|
ulz = (pdc_uint32) dz;
|
|
|
|
memcpy(o_iz, &ulz, sizeof(pdc_uint32));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (dz < PDC_INT_MIN || dz > PDC_INT_MAX)
|
|
|
|
return pdc_false;
|
|
|
|
lz = (pdc_sint32) dz;
|
|
|
|
memcpy(o_iz, &lz, sizeof(pdc_sint32));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return pdc_true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char digits[] = "0123456789ABCDEF";
|
|
|
|
|
|
|
|
static char *
|
|
|
|
pdc_ltoa(char *buf, long n, int width, char pad, int base)
|
|
|
|
{
|
|
|
|
char aux[100];
|
|
|
|
int k, i = sizeof aux;
|
|
|
|
char * dest = buf;
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_bool sign;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
if (n == 0)
|
|
|
|
{
|
|
|
|
if (width == 0)
|
|
|
|
width = 1;
|
|
|
|
|
|
|
|
for (k = 0; k < width; ++k)
|
|
|
|
*(dest++) = '0';
|
|
|
|
|
|
|
|
return dest;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (n < 0 && base == 10)
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
--width;
|
|
|
|
sign = pdc_true;
|
|
|
|
aux[--i] = digits[- (n % base)];
|
|
|
|
n = n / -base;
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
sign = pdc_false;
|
|
|
|
aux[--i] = digits[n % base];
|
|
|
|
n = n / base;
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while (0 < n)
|
|
|
|
{
|
|
|
|
aux[--i] = digits[n % base];
|
|
|
|
n = n / base;
|
|
|
|
}
|
|
|
|
|
|
|
|
width -= (int) (sizeof aux) - i;
|
|
|
|
for (k = 0; k < width; ++k)
|
|
|
|
*(dest++) = pad;
|
|
|
|
|
|
|
|
if (sign)
|
2008-10-20 14:35:00 +00:00
|
|
|
*(dest++) = '-';
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
memcpy(dest, &aux[i], sizeof aux - i);
|
|
|
|
return dest + sizeof aux - i;
|
|
|
|
} /* pdc_ltoa */
|
|
|
|
|
|
|
|
|
|
|
|
static char *
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_ulong2a(
|
|
|
|
char * buf,
|
2009-03-23 08:55:58 +00:00
|
|
|
pdc_off_t n,
|
2008-10-20 14:35:00 +00:00
|
|
|
int width,
|
|
|
|
char pad,
|
|
|
|
int base,
|
|
|
|
pdc_bool left_justify)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
|
|
|
char aux[100];
|
|
|
|
int k, i = sizeof aux;
|
|
|
|
char * dest = buf;
|
2009-03-23 08:55:58 +00:00
|
|
|
pdc_bool sign;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
if (n < 0)
|
|
|
|
{
|
|
|
|
--width;
|
|
|
|
sign = pdc_true;
|
|
|
|
aux[--i] = digits[- (n % base)];
|
|
|
|
n = n / -base;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sign = pdc_false;
|
|
|
|
aux[--i] = digits[n % base];
|
|
|
|
n = n / base;
|
|
|
|
}
|
2008-10-20 14:35:00 +00:00
|
|
|
|
|
|
|
while (0 < n)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
aux[--i] = digits[n % base];
|
|
|
|
n = n / base;
|
|
|
|
}
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
width -= (int) (sizeof aux) - i;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
if (!left_justify)
|
|
|
|
{
|
|
|
|
for (k = 0; k < width; ++k)
|
|
|
|
*(dest++) = pad;
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
if (sign)
|
|
|
|
*(dest++) = '-';
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
memcpy(dest, &aux[i], sizeof aux - i);
|
|
|
|
dest += sizeof aux - i;
|
|
|
|
|
|
|
|
if (left_justify)
|
|
|
|
{
|
|
|
|
for (k = 0; k < width; ++k)
|
|
|
|
*(dest++) = pad;
|
|
|
|
}
|
|
|
|
|
|
|
|
return dest;
|
|
|
|
} /* pdc_ulong2a */
|
|
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
pdc_off_t2a(
|
|
|
|
char * buf,
|
|
|
|
pdc_off_t n,
|
|
|
|
int width,
|
|
|
|
char pad,
|
2009-03-23 08:55:58 +00:00
|
|
|
pdc_bool left_justify,
|
|
|
|
pdc_bool pos_sign)
|
2008-10-20 14:35:00 +00:00
|
|
|
{
|
|
|
|
char aux[100];
|
|
|
|
int k, i = sizeof aux;
|
|
|
|
char * dest = buf;
|
|
|
|
pdc_bool sign;
|
|
|
|
|
|
|
|
if (n < 0)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
--width;
|
|
|
|
sign = pdc_true;
|
|
|
|
aux[--i] = digits[- (n % 10)];
|
|
|
|
n = n / -10;
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-03-23 08:55:58 +00:00
|
|
|
if (pos_sign)
|
|
|
|
--width;
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
sign = pdc_false;
|
|
|
|
aux[--i] = digits[n % 10];
|
|
|
|
n = n / 10;
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while (0 < n)
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
aux[--i] = digits[n % 10];
|
|
|
|
n = n / 10;
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
width -= (int) (sizeof aux) - i;
|
2008-10-20 14:35:00 +00:00
|
|
|
|
|
|
|
if (!left_justify)
|
|
|
|
{
|
|
|
|
for (k = 0; k < width; ++k)
|
|
|
|
*(dest++) = pad;
|
|
|
|
}
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
if (sign)
|
2009-03-23 08:55:58 +00:00
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
*(dest++) = '-';
|
2009-03-23 08:55:58 +00:00
|
|
|
}
|
|
|
|
else if (pos_sign)
|
|
|
|
{
|
|
|
|
*(dest++) = '+';
|
|
|
|
}
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
memcpy(dest, &aux[i], sizeof aux - i);
|
2008-10-20 14:35:00 +00:00
|
|
|
dest += sizeof aux - i;
|
|
|
|
|
|
|
|
if (left_justify)
|
|
|
|
{
|
|
|
|
for (k = 0; k < width; ++k)
|
|
|
|
*(dest++) = pad;
|
|
|
|
}
|
|
|
|
|
|
|
|
return dest;
|
2006-05-04 16:36:51 +00:00
|
|
|
} /* pdc_off_t2a */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* pdc_ftoa converts a floating point number to string
|
|
|
|
*
|
|
|
|
* Because of historical reason "%f" = "%.12g".
|
|
|
|
*
|
|
|
|
* The function calls sprintf() and replaces
|
|
|
|
* decimal comma by decimal point.
|
|
|
|
*
|
|
|
|
* If the number is infinite or not a number
|
|
|
|
* "nan" will be set.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
static char *
|
|
|
|
pdc_ftoa(pdc_core *pdc, const char *format, char *buf, double x)
|
|
|
|
{
|
|
|
|
char *dest = buf;
|
|
|
|
char *cd;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
(void) pdc;
|
|
|
|
|
|
|
|
/* check whether the number is valid */
|
|
|
|
if (!PDC_ISFINITE(x))
|
|
|
|
{
|
|
|
|
strcpy(dest, "nan");
|
|
|
|
return dest + 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* standard C convert */
|
|
|
|
if (!strcmp(format, "%f"))
|
|
|
|
n = sprintf(dest, "%.12g", x);
|
|
|
|
else
|
|
|
|
n = sprintf(dest, format, x);
|
|
|
|
|
|
|
|
/* normalized to decimal point */
|
|
|
|
cd = strchr(dest, ',');
|
|
|
|
if (cd != NULL)
|
|
|
|
*cd = '.';
|
|
|
|
|
|
|
|
return dest + n;
|
|
|
|
} /* pdc_ftoa */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* pdc_ftoa_pdfconf converts a floating point number to string
|
|
|
|
* PDF conforming
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
static char *
|
|
|
|
pdc_ftoa_pdfconf(pdc_core *pdc, char *buf, double x)
|
|
|
|
{
|
|
|
|
static const long pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000 };
|
|
|
|
char * dest = buf;
|
|
|
|
double integ, fract, powd;
|
|
|
|
int ifd;
|
|
|
|
long f;
|
|
|
|
|
|
|
|
/* check whether the number is valid */
|
|
|
|
if (!PDC_ISFINITE(x))
|
|
|
|
pdc_error(pdc, PDC_E_INT_ILLFLOAT, 0, 0, 0, 0);
|
|
|
|
|
|
|
|
/* small number will be mapped to 0 */
|
|
|
|
if (x < PDF_SMALLREAL && x > -PDF_SMALLREAL)
|
|
|
|
{
|
|
|
|
*dest = '0';
|
|
|
|
return dest + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* negative number */
|
|
|
|
if (x < 0)
|
|
|
|
{
|
|
|
|
x = -x;
|
|
|
|
*(dest++) = '-';
|
|
|
|
}
|
|
|
|
|
|
|
|
/* large number is invalid or will be mapped to integer */
|
|
|
|
if (x >= PDF_BIGREAL)
|
|
|
|
{
|
|
|
|
if (x > PDF_BIGINT)
|
|
|
|
pdc_error(pdc, PDC_E_INT_FLOATTOOLARGE,
|
|
|
|
pdc_errprintf(pdc, "%f", x), 0, 0, 0);
|
|
|
|
|
|
|
|
return pdc_ltoa(dest, (long) (x + 0.5), 0, ' ', 10);
|
|
|
|
}
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
ifd = pdc->floatdigits;
|
2006-05-04 16:36:51 +00:00
|
|
|
powd = pow10[ifd];
|
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
/* number <= 1/powd will be mappepd to 1/powd */
|
|
|
|
if (x <= 1 / powd)
|
|
|
|
{
|
|
|
|
*(dest++) = '0';
|
|
|
|
*(dest++) = '.';
|
|
|
|
while (--ifd)
|
|
|
|
*(dest++) = '0';
|
|
|
|
*(dest++) = '1';
|
|
|
|
return dest;
|
|
|
|
}
|
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
fract = modf(x, &integ);
|
|
|
|
f = (long) (fract * powd + 0.5);
|
|
|
|
|
|
|
|
if (f == powd)
|
|
|
|
{
|
|
|
|
integ += 1.0;
|
|
|
|
f = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (integ == 0 && f == 0) /* avoid "-0" */
|
|
|
|
dest = buf;
|
|
|
|
|
|
|
|
dest = pdc_ltoa(dest, (long) integ, 0, ' ', 10);
|
|
|
|
|
|
|
|
if (f != 0)
|
|
|
|
{
|
|
|
|
char * aux;
|
|
|
|
long rem;
|
|
|
|
|
|
|
|
*(dest++) = '.';
|
|
|
|
|
|
|
|
do /* avoid trailing zeros */
|
|
|
|
{
|
|
|
|
rem = f % 10;
|
|
|
|
f = f / 10;
|
|
|
|
--ifd;
|
|
|
|
} while (rem == 0);
|
|
|
|
|
|
|
|
aux = dest + ifd + 1;
|
|
|
|
dest[ifd--] = digits[rem];
|
|
|
|
|
|
|
|
for (; 0 <= ifd; --ifd)
|
|
|
|
{
|
|
|
|
dest[ifd] = digits[f % 10];
|
|
|
|
f = f / 10;
|
|
|
|
}
|
|
|
|
|
|
|
|
return aux;
|
|
|
|
}
|
|
|
|
|
|
|
|
return dest;
|
|
|
|
} /* pdc_ftoa_pdfconf */
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
/* flags for formatting function pdc_vxprintf()
|
|
|
|
*/
|
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
pdc_form_nolimit, /* no buffer limit supplied, no overflow check */
|
|
|
|
pdc_form_fixlimit, /* fix buffer limit, buffer overflow causes exception */
|
|
|
|
pdc_form_varlimit /* buffer overflow causes string truncation */
|
|
|
|
}
|
|
|
|
pdc_limitkind;
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
/* write to string or file
|
|
|
|
*/
|
|
|
|
static char *
|
|
|
|
write_sf(
|
|
|
|
pdc_core *pdc,
|
|
|
|
FILE *fp,
|
2009-03-23 08:55:58 +00:00
|
|
|
pdc_limitkind ltd,
|
2008-10-20 14:35:00 +00:00
|
|
|
char *dst,
|
|
|
|
char *limit,
|
|
|
|
const char *src,
|
|
|
|
int n)
|
|
|
|
{
|
|
|
|
if (fp != (FILE *) 0)
|
|
|
|
{
|
|
|
|
pdc_fwrite_ascii(pdc, src, (size_t) n, fp);
|
|
|
|
}
|
2009-03-23 08:55:58 +00:00
|
|
|
else
|
2008-10-20 14:35:00 +00:00
|
|
|
{
|
2009-03-23 08:55:58 +00:00
|
|
|
if (ltd != pdc_form_nolimit)
|
|
|
|
{
|
|
|
|
int avail = (int) (limit - dst);
|
2008-10-20 14:35:00 +00:00
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
if (avail < n)
|
|
|
|
{
|
|
|
|
if (ltd == pdc_form_fixlimit)
|
|
|
|
{
|
|
|
|
pdc_error(pdc, PDC_E_INT_FORMOVERFLOW, 0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
n = MAX(avail, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-10-20 14:35:00 +00:00
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
if (n > 0)
|
|
|
|
{
|
|
|
|
memcpy(dst, src, (size_t) n);
|
|
|
|
dst += n;
|
|
|
|
}
|
2008-10-20 14:35:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return dst;
|
|
|
|
} /* write2buf */
|
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
static int
|
|
|
|
pdc_vxprintf(
|
|
|
|
pdc_core *pdc,
|
|
|
|
pdc_bool pdfconf,
|
2009-03-23 08:55:58 +00:00
|
|
|
pdc_limitkind ltd,
|
2006-05-04 16:36:51 +00:00
|
|
|
char *cp,
|
2008-10-20 14:35:00 +00:00
|
|
|
size_t size,
|
2006-05-04 16:36:51 +00:00
|
|
|
FILE *fp,
|
|
|
|
const char *format,
|
|
|
|
va_list args)
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
static const char fn[] = "pdc_vxprintf";
|
|
|
|
|
|
|
|
char buf[1024];
|
2006-05-04 16:36:51 +00:00
|
|
|
char *dest = buf;
|
2008-10-20 14:35:00 +00:00
|
|
|
int result = 0;
|
|
|
|
char *limit = (char *) 0;
|
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
if (cp != (char *) 0 && ltd != pdc_form_nolimit)
|
2008-10-20 14:35:00 +00:00
|
|
|
limit = cp + (int) (size - 1);
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
for (/* */ ; /* */ ; /* */)
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
int width = 0; /* = no width specified */
|
|
|
|
int prec = -1; /* = no precision specified */
|
|
|
|
char pad = ' ';
|
|
|
|
pdc_bool left_justify = pdc_false;
|
2009-03-23 08:55:58 +00:00
|
|
|
pdc_bool pos_sign = pdc_false;
|
2008-10-20 14:35:00 +00:00
|
|
|
|
|
|
|
char fbuf[100]; /* format buffer for %f and %g */
|
|
|
|
char * fscan = fbuf;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
/* as long as there is no '%', just print.
|
|
|
|
*/
|
|
|
|
while (*format != 0 && *format != '%')
|
|
|
|
*(dest++) = *(format++);
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
if (dest > buf)
|
|
|
|
{
|
|
|
|
int inbuf = (int) (dest - buf);
|
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
cp = write_sf(pdc, fp, ltd, cp, limit, buf, inbuf);
|
2008-10-20 14:35:00 +00:00
|
|
|
result += inbuf;
|
|
|
|
dest = buf;
|
|
|
|
}
|
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
if (*format == 0)
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
if (cp != (char *) 0)
|
|
|
|
*cp = 0;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
return result;
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
*(fscan++) = *(format++); /* '%' */
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
/* get the "flags", if any.
|
|
|
|
*/
|
|
|
|
while (*format && strchr("+- #0", *format))
|
|
|
|
{
|
|
|
|
switch (*format)
|
|
|
|
{
|
|
|
|
case '-': left_justify = pdc_true;
|
|
|
|
break;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
case '+': pos_sign = pdc_true;
|
|
|
|
break;
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
case '0': pad = '0';
|
|
|
|
break;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
|
|
|
|
*(fscan++) = *(format++);
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
/* get the "width", if present.
|
|
|
|
*/
|
|
|
|
if (*format == '*')
|
|
|
|
{
|
|
|
|
width = va_arg(args, int);
|
|
|
|
++format;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
if (width < 0)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
width = -width;
|
|
|
|
|
|
|
|
if (!left_justify)
|
|
|
|
{
|
|
|
|
*(fscan++) = '-';
|
|
|
|
left_justify = pdc_true;
|
|
|
|
}
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
2008-10-20 14:35:00 +00:00
|
|
|
|
|
|
|
fscan += sprintf(fscan, "%d", width);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while (pdc_isdigit(*format))
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
width = 10 * width + *format - '0';
|
|
|
|
*(fscan++) = *(format++);
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
2008-10-20 14:35:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (left_justify)
|
|
|
|
pad = ' ';
|
|
|
|
|
|
|
|
/* get the "precision", if present.
|
|
|
|
*/
|
|
|
|
if (*format == '.')
|
|
|
|
{
|
|
|
|
++format;
|
|
|
|
|
|
|
|
if (*format == '*')
|
|
|
|
{
|
|
|
|
prec = va_arg(args, int);
|
|
|
|
++format;
|
|
|
|
|
|
|
|
if (prec >= 0) /* ignore negative precision */
|
|
|
|
{
|
|
|
|
fscan += sprintf(fscan, ".%d", prec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (pdc_isdigit(*format))
|
|
|
|
{
|
|
|
|
prec = 0;
|
|
|
|
*(fscan++) = '.';
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
prec = 10 * prec + *format - '0';
|
|
|
|
*(fscan++) = *(format++);
|
|
|
|
} while (pdc_isdigit(*format));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*(fscan++) = *format;
|
|
|
|
*fscan = 0;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
switch (*format)
|
|
|
|
{
|
|
|
|
case 'x':
|
|
|
|
case 'X':
|
2008-10-20 14:35:00 +00:00
|
|
|
dest = pdc_ulong2a(
|
2009-03-23 08:55:58 +00:00
|
|
|
dest, (pdc_off_t) va_arg(args, pdc_uint),
|
2008-10-20 14:35:00 +00:00
|
|
|
width, pad, 16, left_justify);
|
2006-05-04 16:36:51 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'c':
|
|
|
|
*(dest++) = (char) va_arg(args, int);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'd':
|
|
|
|
dest = pdc_off_t2a(dest, (pdc_off_t) va_arg(args, int),
|
2009-03-23 08:55:58 +00:00
|
|
|
width, pad, left_justify, pos_sign);
|
2008-10-20 14:35:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'u':
|
|
|
|
dest = pdc_ulong2a(
|
2009-03-23 08:55:58 +00:00
|
|
|
dest, (pdc_off_t) va_arg(args, pdc_ulong),
|
2008-10-20 14:35:00 +00:00
|
|
|
width, pad, 10, left_justify);
|
2006-05-04 16:36:51 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'g':
|
|
|
|
case 'f':
|
|
|
|
if (pdfconf)
|
|
|
|
{
|
|
|
|
dest = pdc_ftoa_pdfconf(pdc, dest, va_arg(args, double));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
dest = pdc_ftoa(pdc, fbuf, dest, va_arg(args, double));
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'l':
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_off_t n = 0;
|
|
|
|
pdc_bool ll = pdc_false;
|
|
|
|
|
|
|
|
if (*(++format) == 'l')
|
|
|
|
{
|
|
|
|
ll = pdc_true;
|
|
|
|
++format;
|
|
|
|
}
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
if (strchr("xXu", *format))
|
|
|
|
{
|
2009-03-23 08:55:58 +00:00
|
|
|
if (ll)
|
|
|
|
n = va_arg(args, pdc_off_t);
|
|
|
|
else
|
|
|
|
n = va_arg(args, pdc_ulong);
|
2008-10-20 14:35:00 +00:00
|
|
|
}
|
|
|
|
else if (*format == 'd')
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
if (ll)
|
|
|
|
n = va_arg(args, pdc_off_t);
|
|
|
|
else
|
|
|
|
n = va_arg(args, long);
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_error(pdc, PDC_E_INT_BADFORMAT,
|
|
|
|
pdc_errprintf(pdc, "l%c",
|
|
|
|
pdc_isprint((int) *format) ? *format : '?'),
|
|
|
|
pdc_errprintf(pdc, "0x%02X", *format),
|
|
|
|
0, 0);
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
switch (*format)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
|
|
|
case 'x':
|
|
|
|
case 'X':
|
2008-10-20 14:35:00 +00:00
|
|
|
dest = pdc_ulong2a(
|
2009-03-23 08:55:58 +00:00
|
|
|
dest, n, width, pad, 16, left_justify);
|
2006-05-04 16:36:51 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'd':
|
2009-03-23 08:55:58 +00:00
|
|
|
dest = pdc_off_t2a(dest, n, width, pad,
|
|
|
|
left_justify, pos_sign);
|
2008-10-20 14:35:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'u':
|
|
|
|
dest = pdc_ulong2a(
|
2009-03-23 08:55:58 +00:00
|
|
|
dest, n, width, pad, 10, left_justify);
|
2006-05-04 16:36:51 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2008-10-20 14:35:00 +00:00
|
|
|
break;
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 'p':
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
char tmp[64];
|
2006-05-04 16:36:51 +00:00
|
|
|
void *ptr = va_arg(args, void *);
|
2008-10-20 14:35:00 +00:00
|
|
|
|
|
|
|
sprintf(tmp, "%p", ptr);
|
|
|
|
#if defined(AIX)
|
|
|
|
if (strncmp(tmp, "0x", 2))
|
|
|
|
dest += sprintf(dest, "0x");
|
|
|
|
#endif
|
|
|
|
dest += sprintf(dest, "%s", tmp);
|
2006-05-04 16:36:51 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
case 'a':
|
2006-05-04 16:36:51 +00:00
|
|
|
case 's':
|
|
|
|
case 'T':
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
char *str = va_arg(args, char *);
|
2006-05-04 16:36:51 +00:00
|
|
|
const char *cstr = str;
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_bool tobefree = pdc_false;
|
|
|
|
size_t len;
|
2009-03-23 08:55:58 +00:00
|
|
|
int llen;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
if (str != 0)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2009-03-23 08:55:58 +00:00
|
|
|
if (*format == 'T')
|
|
|
|
{
|
|
|
|
llen = va_arg(args, int);
|
|
|
|
cstr = pdc_print_loggstring(pdc, str, llen);
|
|
|
|
}
|
|
|
|
else if (*format == 'a')
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2009-03-23 08:55:58 +00:00
|
|
|
cstr = pdc_strdup_ext(pdc, str, PDC_CONV_EBCDIC, fn);
|
|
|
|
tobefree = pdc_true;
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
}
|
2009-03-23 08:55:58 +00:00
|
|
|
else
|
2008-10-20 14:35:00 +00:00
|
|
|
{
|
2009-03-23 08:55:58 +00:00
|
|
|
cstr = "(NULL)";
|
|
|
|
if (*format == 'T')
|
|
|
|
llen = va_arg(args, int);
|
2008-10-20 14:35:00 +00:00
|
|
|
}
|
|
|
|
|
2009-03-23 08:55:58 +00:00
|
|
|
len = strlen(cstr);
|
|
|
|
|
|
|
|
if (prec != -1 && prec < len)
|
|
|
|
{
|
|
|
|
len = prec;
|
|
|
|
}
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
if (!left_justify && len < (size_t) width)
|
|
|
|
{
|
|
|
|
int inbuf = (int) (width - len);
|
|
|
|
|
|
|
|
memset(buf, pad, (size_t) inbuf);
|
2009-03-23 08:55:58 +00:00
|
|
|
cp = write_sf(pdc, fp, ltd, cp, limit, buf, inbuf);
|
2008-10-20 14:35:00 +00:00
|
|
|
result += inbuf;
|
|
|
|
}
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
if (len != 0)
|
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
result += (int) len;
|
2006-05-04 16:36:51 +00:00
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
if (fp != (FILE *) 0)
|
2006-05-04 16:36:51 +00:00
|
|
|
{
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_fwrite_ascii(pdc, cstr, len, fp);
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
2009-03-23 08:55:58 +00:00
|
|
|
else if (ltd == pdc_form_nolimit || result < (int) size)
|
|
|
|
{
|
|
|
|
memcpy(cp, cstr, len);
|
|
|
|
cp += (int) len;
|
|
|
|
}
|
|
|
|
else if (ltd == pdc_form_fixlimit)
|
|
|
|
{
|
|
|
|
pdc_error(pdc, PDC_E_INT_FORMOVERFLOW, 0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
else if (cp < limit)
|
|
|
|
{
|
|
|
|
memcpy(cp, cstr, (size_t) (limit - cp));
|
|
|
|
cp = limit;
|
|
|
|
}
|
2008-10-20 14:35:00 +00:00
|
|
|
|
|
|
|
if (tobefree)
|
|
|
|
pdc_free(pdc, (char *) cstr);
|
2006-05-04 16:36:51 +00:00
|
|
|
}
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
if (left_justify && len < (size_t) width)
|
|
|
|
{
|
|
|
|
int inbuf = (int) (width - len);
|
|
|
|
|
|
|
|
memset(buf, pad, (size_t) inbuf);
|
2009-03-23 08:55:58 +00:00
|
|
|
cp = write_sf(pdc, fp, ltd, cp, limit, buf, inbuf);
|
2008-10-20 14:35:00 +00:00
|
|
|
result += inbuf;
|
|
|
|
}
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case '%':
|
|
|
|
*(dest++) = '%';
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
pdc_error(pdc, PDC_E_INT_BADFORMAT,
|
2008-10-20 14:35:00 +00:00
|
|
|
pdc_errprintf(pdc, "%c", pdc_isprint((int) *format) ?
|
2006-05-04 16:36:51 +00:00
|
|
|
*format : '?'),
|
|
|
|
pdc_errprintf(pdc, "0x%02X", *format),
|
|
|
|
0, 0);
|
|
|
|
} /* switch */
|
|
|
|
|
|
|
|
++format;
|
|
|
|
} /* loop */
|
|
|
|
} /* pdc_vxprintf */
|
|
|
|
|
|
|
|
|
|
|
|
/* ----------------------- formatted output ----------------------- */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* formatted output to file
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
pdc_vfprintf(pdc_core *pdc, pdc_bool pdfconf, FILE *fp,
|
|
|
|
const char *format, va_list args)
|
|
|
|
{
|
2009-03-23 08:55:58 +00:00
|
|
|
return pdc_vxprintf(pdc, pdfconf, pdc_form_nolimit,
|
|
|
|
NULL, 0, fp, format, args);
|
2006-05-04 16:36:51 +00:00
|
|
|
} /* pdc_vfprintf */
|
|
|
|
|
|
|
|
int
|
|
|
|
pdc_fprintf(pdc_core *pdc, pdc_bool pdfconf, FILE *fp,
|
|
|
|
const char *format, ...)
|
|
|
|
{
|
|
|
|
int result;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, format);
|
2009-03-23 08:55:58 +00:00
|
|
|
result = pdc_vxprintf(pdc, pdfconf, pdc_form_nolimit,
|
|
|
|
NULL, 0, fp, format, ap);
|
2006-05-04 16:36:51 +00:00
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
} /* pdc_fprintf */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* formatted output to character string
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
pdc_vsprintf(pdc_core *pdc, pdc_bool pdfconf, char *buf,
|
|
|
|
const char *format, va_list args)
|
|
|
|
{
|
2009-03-23 08:55:58 +00:00
|
|
|
return pdc_vxprintf(pdc, pdfconf, pdc_form_fixlimit,
|
|
|
|
buf, PDC_GEN_BUFSIZE, NULL, format, args);
|
2006-05-04 16:36:51 +00:00
|
|
|
} /* pdc_vsprintf */
|
|
|
|
|
|
|
|
int
|
|
|
|
pdc_sprintf(pdc_core *pdc, pdc_bool pdfconf, char *buf,
|
|
|
|
const char *format, ...)
|
|
|
|
{
|
|
|
|
int result;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, format);
|
2009-03-23 08:55:58 +00:00
|
|
|
result = pdc_vxprintf(pdc, pdfconf, pdc_form_nolimit,
|
|
|
|
buf, 0, NULL, format, ap);
|
2006-05-04 16:36:51 +00:00
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
} /* pdc_sprintf */
|
|
|
|
|
2008-10-20 14:35:00 +00:00
|
|
|
int
|
|
|
|
pdc_vsnprintf(pdc_core *pdc, char *buf, size_t size,
|
|
|
|
const char *format, va_list args)
|
|
|
|
{
|
2009-03-23 08:55:58 +00:00
|
|
|
return pdc_vxprintf(pdc, pdc_false, pdc_form_varlimit,
|
|
|
|
buf, size, NULL, format, args);
|
2008-10-20 14:35:00 +00:00
|
|
|
} /* pdc_vsnprintf */
|
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
/* --------------------- name tree handling ----------------------- */
|
|
|
|
|
|
|
|
struct pdc_branch_s
|
|
|
|
{
|
|
|
|
char *name; /* name - must be allocated pointer */
|
|
|
|
void *data; /* private data - must be allocated pointer */
|
|
|
|
int nalloc; /* number of allocated kid structs */
|
|
|
|
int nkids; /* number of kids */
|
|
|
|
pdc_branch **kids; /* kids */
|
|
|
|
pdc_branch *parent; /* parent branch */
|
|
|
|
};
|
|
|
|
|
|
|
|
pdc_branch *
|
|
|
|
pdc_init_tree(pdc_core *pdc)
|
|
|
|
{
|
|
|
|
return pdc_create_treebranch(pdc, NULL, "__tree__root__",
|
|
|
|
NULL, 0, 0, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
pdc_branch *
|
|
|
|
pdc_create_treebranch(pdc_core *pdc, pdc_branch *root, const char *pathname,
|
|
|
|
void *data, int flags, int size,
|
|
|
|
pdc_branch_error *errcode, const char **name_p)
|
|
|
|
{
|
|
|
|
static const char fn[] = "pdc_create_branch";
|
|
|
|
char *name = NULL;
|
|
|
|
pdc_branch *branch = NULL;
|
|
|
|
pdc_branch *kid = NULL;
|
|
|
|
pdc_branch *parent = NULL;
|
|
|
|
char **namelist;
|
|
|
|
int i, j, k, nnames, nkids;
|
|
|
|
|
|
|
|
if (errcode) *errcode = tree_ok;
|
|
|
|
if (name_p) *name_p = "";
|
|
|
|
|
|
|
|
if (root)
|
|
|
|
{
|
|
|
|
/* search for parent branch */
|
|
|
|
parent = root;
|
2008-10-20 14:35:00 +00:00
|
|
|
nnames = pdc_split_stringlist(pdc, pathname, PDC_NAME_SEPARSTRG, 0,
|
2006-05-04 16:36:51 +00:00
|
|
|
&namelist);
|
|
|
|
for (i = 0; i < nnames; i++)
|
|
|
|
{
|
|
|
|
/* parent branch must not be a leaf branch */
|
|
|
|
if (!parent->nalloc)
|
|
|
|
{
|
|
|
|
if (errcode) *errcode = tree_isleaf;
|
|
|
|
pdc_cleanup_stringlist(pdc, namelist);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (i == nnames - 1)
|
|
|
|
break;
|
|
|
|
|
|
|
|
name = namelist[i];
|
|
|
|
if (name_p)
|
2009-03-23 08:55:58 +00:00
|
|
|
{
|
|
|
|
*name_p = pdc_utf8strprint(pdc, name);
|
|
|
|
}
|
2006-05-04 16:36:51 +00:00
|
|
|
|
|
|
|
nkids = parent->nkids;
|
|
|
|
for (j = 0; j < nkids; j++)
|
|
|
|
{
|
|
|
|
kid = parent->kids[j];
|
|
|
|
k = pdc_is_utf8_bytecode(kid->name) ? 3 : 0;
|
|
|
|
if (!strcmp(&kid->name[k], name))
|
|
|
|
{
|
|
|
|
parent = kid;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (j == nkids)
|
|
|
|
{
|
|
|
|
if (errcode) *errcode = tree_notfound;
|
|
|
|
pdc_cleanup_stringlist(pdc, namelist);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pdc_is_utf8_bytecode(pathname))
|
|
|
|
name = pdc_strdup_withbom(pdc, namelist[nnames - 1]);
|
|
|
|
else
|
|
|
|
name = pdc_strdup(pdc, namelist[nnames - 1]);
|
|
|
|
pdc_cleanup_stringlist(pdc, namelist);
|
|
|
|
|
|
|
|
/* kids must have different names */
|
|
|
|
for (j = 0; j < parent->nkids; j++)
|
|
|
|
{
|
|
|
|
kid = parent->kids[j];
|
|
|
|
if (!strcmp(kid->name, name))
|
|
|
|
{
|
|
|
|
if (errcode) *errcode = tree_nameexists;
|
2009-03-23 08:55:58 +00:00
|
|
|
if (name_p) *name_p = pdc_utf8strprint(pdc, name);
|
|
|
|
|
2006-05-04 16:36:51 +00:00
|
|
|
pdc_free(pdc, name);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
parent = NULL;
|
|
|
|
name = pdc_strdup(pdc, pathname);
|
|
|
|
}
|
|
|
|
|
|
|
|
branch = (pdc_branch *) pdc_malloc(pdc, sizeof(pdc_branch), fn);
|
|
|
|
branch->name = name;
|
|
|
|
branch->data = data;
|
|
|
|
if (flags & PDC_TREE_ISLEAF)
|
|
|
|
{
|
|
|
|
branch->nalloc = 0;
|
|
|
|
branch->nkids = 0;
|
|
|
|
branch->kids = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
branch->nalloc = PDC_KIDS_CHUNKSIZE;
|
|
|
|
branch->nkids = 0;
|
|
|
|
branch->kids = (pdc_branch **) pdc_malloc(pdc,
|
|
|
|
branch->nalloc * sizeof(pdc_branch *), fn);
|
|
|
|
}
|
|
|
|
branch->parent = parent;
|
|
|
|
|
|
|
|
/* insert kid */
|
|
|
|
if (parent)
|
|
|
|
{
|
|
|
|
if (parent->nkids == parent->nalloc)
|
|
|
|
{
|
|
|
|
parent->nalloc *= 2;
|
|
|
|
parent->kids = (pdc_branch **) pdc_realloc(pdc, parent->kids,
|
|
|
|
parent->nalloc * sizeof(pdc_branch *), fn);
|
|
|
|
}
|
|
|
|
parent->kids[parent->nkids] = branch;
|
|
|
|
(parent->nkids)++;
|
|
|
|
|
|
|
|
if ((flags & PDC_TREE_INHERIT) && parent->data)
|
|
|
|
memcpy(branch->data, parent->data, (size_t) size);
|
|
|
|
}
|
|
|
|
|
|
|
|
return branch;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
pdc_deactivate_name_treebranch(pdc_core *pdc, pdc_branch *branch)
|
|
|
|
{
|
|
|
|
static const char fn[] = "pdc_deactivate_name_treebranch";
|
|
|
|
size_t len = strlen(branch->name);
|
|
|
|
|
|
|
|
branch->name = (char *) pdc_realloc(pdc, branch->name, len + 2, fn);
|
|
|
|
branch->name[len] = PDC_NAME_SEPARSIGN;
|
|
|
|
branch->name[len+1] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
pdc_get_name_treebranch(pdc_branch *branch)
|
|
|
|
{
|
|
|
|
return branch->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
pdc_branch *
|
|
|
|
pdc_get_parent_treebranch(pdc_branch *branch)
|
|
|
|
{
|
|
|
|
return branch->parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
pdc_get_data_treebranch(pdc_branch *branch)
|
|
|
|
{
|
|
|
|
return branch->data;
|
|
|
|
}
|
|
|
|
|
|
|
|
pdc_branch **
|
|
|
|
pdc_get_kids_treebranch(pdc_branch *branch, int *nkids)
|
|
|
|
{
|
|
|
|
*nkids = branch->nkids;
|
|
|
|
return branch->kids;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
pdc_cleanup_treebranch(pdc_core *pdc, pdc_branch *branch)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (branch->name)
|
|
|
|
pdc_free(pdc, branch->name);
|
|
|
|
|
|
|
|
if (branch->data)
|
|
|
|
pdc_free(pdc, branch->data);
|
|
|
|
|
|
|
|
if (branch->kids)
|
|
|
|
{
|
|
|
|
for(i = 0; i < branch->nkids; i++)
|
|
|
|
pdc_cleanup_treebranch(pdc, branch->kids[i]);
|
|
|
|
pdc_free(pdc, branch->kids);
|
|
|
|
}
|
|
|
|
|
|
|
|
pdc_free(pdc, branch);
|
|
|
|
}
|
2008-10-20 14:35:00 +00:00
|
|
|
|
|
|
|
/***************************** memory pools *****************************/
|
|
|
|
|
|
|
|
/* the data structures and functions in this section are more than
|
|
|
|
** confusing. the funny "mp_item" structure below makes them more
|
|
|
|
** readable, believe it or not.
|
|
|
|
*/
|
|
|
|
typedef struct mp_item_s mp_item;
|
|
|
|
|
|
|
|
struct mp_item_s
|
|
|
|
{
|
|
|
|
mp_item * next;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct pdc_mempool_s
|
|
|
|
{
|
|
|
|
pdc_core * pdc;
|
|
|
|
|
|
|
|
char ** pool_tab;
|
|
|
|
mp_item * free_list;
|
|
|
|
|
|
|
|
size_t pool_incr; /* pool growth chunk size (items) */
|
|
|
|
|
|
|
|
size_t ptab_cap; /* total # of slots in pool_tab */
|
|
|
|
size_t ptab_size; /* used # of slots in pool_tab */
|
|
|
|
size_t ptab_incr; /* pool_tab growth chunk size (slots) */
|
|
|
|
|
|
|
|
size_t item_size; /* size of a single item (bytes) */
|
|
|
|
};
|
|
|
|
|
|
|
|
#undef COMMENT
|
|
|
|
#ifdef COMMENT
|
|
|
|
|
|
|
|
pool_incr = 5
|
|
|
|
ptab_incr = 4
|
|
|
|
ptab_cap = 4 (1 * ptab_incr)
|
|
|
|
|
|
|
|
|
|
|
|
+------+
|
|
|
|
| free |
|
|
|
|
+------+ +----------------------------------+
|
|
|
|
| free | +--> | | | | free | free |
|
|
|
|
+------+ | +----------------------------------+
|
|
|
|
| | ---+
|
|
|
|
+------+ +----------------------------------+
|
|
|
|
| | ------> | | | | | |
|
|
|
|
+------+ +----------------------------------+
|
|
|
|
|
|
|
|
pool_tab
|
|
|
|
|
|
|
|
#endif /* COMMENT */
|
|
|
|
|
|
|
|
|
|
|
|
pdc_mempool *
|
|
|
|
pdc_mp_new(pdc_core *pdc, size_t item_size)
|
|
|
|
{
|
|
|
|
static const char fn[] = "pdc_mp_new";
|
|
|
|
|
|
|
|
int m;
|
|
|
|
pdc_mempool *mp = (pdc_mempool *)
|
|
|
|
pdc_malloc(pdc, sizeof (pdc_mempool), fn);
|
|
|
|
|
|
|
|
if (mp != (pdc_mempool *) 0)
|
|
|
|
{
|
|
|
|
/* round up 'item_size' to a multiple of 'sizeof (mp_item)'
|
|
|
|
** to ensure proper alignment.
|
|
|
|
*/
|
|
|
|
if ((m = (int) (item_size % sizeof (mp_item))) != 0)
|
|
|
|
item_size += sizeof (mp_item) - m;
|
|
|
|
|
|
|
|
mp->pdc = pdc;
|
|
|
|
|
|
|
|
mp->pool_tab = (char **) 0;
|
|
|
|
mp->free_list = (mp_item *) 0;
|
|
|
|
mp->pool_incr = 1000;
|
|
|
|
|
|
|
|
mp->ptab_cap = 0;
|
|
|
|
mp->ptab_size = 0;
|
|
|
|
mp->ptab_incr = 100;
|
|
|
|
|
|
|
|
mp->item_size = item_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mp;
|
|
|
|
} /* pdc_mp_new */
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
pdc_mp_delete(pdc_mempool *mp)
|
|
|
|
{
|
|
|
|
/* TODO: exception if there are still alloc'd items in the pool? */
|
|
|
|
/* or, the other way round, call destructors? */
|
|
|
|
|
|
|
|
pdc_core * pdc = mp->pdc;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < (int) mp->ptab_size; ++i)
|
|
|
|
pdc_free(pdc, mp->pool_tab[i]);
|
|
|
|
|
|
|
|
if (mp->pool_tab)
|
|
|
|
pdc_free(pdc, mp->pool_tab);
|
|
|
|
|
|
|
|
pdc_free(pdc, mp);
|
|
|
|
} /* pdc_mp_delete */
|
|
|
|
|
|
|
|
|
|
|
|
void *
|
|
|
|
pdc_mp_alloc(pdc_mempool *mp)
|
|
|
|
{
|
|
|
|
static const char fn[] = "pdc_mp_alloc";
|
|
|
|
|
|
|
|
pdc_core * pdc = mp->pdc;
|
|
|
|
mp_item * result;
|
|
|
|
|
|
|
|
if (!mp->free_list)
|
|
|
|
{
|
|
|
|
char * new_chunk;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (mp->ptab_size == mp->ptab_cap)
|
|
|
|
{
|
|
|
|
mp->ptab_cap += mp->ptab_incr;
|
|
|
|
|
|
|
|
mp->pool_tab = (char **) pdc_realloc(pdc,
|
|
|
|
mp->pool_tab, mp->ptab_cap * sizeof (char **), fn);
|
|
|
|
}
|
|
|
|
|
|
|
|
new_chunk = mp->pool_tab[mp->ptab_size] = (char *)
|
|
|
|
pdc_malloc(pdc, mp->pool_incr * mp->item_size, fn);
|
|
|
|
|
|
|
|
++mp->ptab_size;
|
|
|
|
mp->free_list = (mp_item *) new_chunk;
|
|
|
|
mp->free_list->next = (mp_item *) 0;
|
|
|
|
|
|
|
|
for (i = 1; i < (int) mp->pool_incr; ++i)
|
|
|
|
{
|
|
|
|
mp_item *scan = (mp_item *) (new_chunk + i * mp->item_size);
|
|
|
|
|
|
|
|
scan->next = mp->free_list;
|
|
|
|
mp->free_list = scan;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
result = mp->free_list;
|
|
|
|
mp->free_list = result->next;
|
|
|
|
|
|
|
|
return (void *) result;
|
|
|
|
} /* pdc_mp_alloc */
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
pdc_mp_free(pdc_mempool *mp, void *item)
|
|
|
|
{
|
|
|
|
mp_item *mpi = (mp_item *) item;
|
|
|
|
|
|
|
|
mpi->next = mp->free_list;
|
|
|
|
mp->free_list = mpi;
|
|
|
|
} /* pdc_mp_free */
|
|
|
|
|
|
|
|
|
|
|
|
/***************************** miscellaneous ****************************/
|
|
|
|
|
|
|
|
/* search a sorted (strcmp order) array "names" of size "size"
|
|
|
|
** for string "name". return the index if found, otherwise -1.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
pdc_name2idx(const char **names, int size, const char *name)
|
|
|
|
{
|
|
|
|
int lo = 0, hi = size;
|
|
|
|
|
|
|
|
while (lo != hi)
|
|
|
|
{
|
|
|
|
int idx = (lo + hi) / 2;
|
|
|
|
int cmp = strcmp(name, names[idx]);
|
|
|
|
|
|
|
|
if (cmp == 0)
|
|
|
|
return idx;
|
|
|
|
|
|
|
|
if (cmp < 0)
|
|
|
|
hi = idx;
|
|
|
|
else
|
|
|
|
lo = idx + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
} /* pdc_name2idx */
|
|
|
|
|
|
|
|
|
|
|
|
/* linear search; see man page LSEARCH(3).
|
|
|
|
*/
|
|
|
|
void *
|
|
|
|
pdc_lfind(
|
|
|
|
const void *key,
|
|
|
|
const void *base,
|
|
|
|
size_t * nmemb,
|
|
|
|
size_t size,
|
|
|
|
int (*compar)(const void *, const void *))
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < *nmemb; ++i)
|
|
|
|
{
|
|
|
|
const char *cp = (const char *) base + i * size;
|
|
|
|
|
|
|
|
if (compar(key, (void *) cp) == 0)
|
|
|
|
return (void *) cp;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (void *) 0;
|
|
|
|
} /* pdc_lfind */
|
|
|
|
|
|
|
|
|
|
|
|
/********************* pseudo random numbers *********************/
|
|
|
|
|
|
|
|
int
|
|
|
|
pdc_rand(pdc_core *pdc)
|
|
|
|
{
|
|
|
|
pdc->last_rand = pdc->last_rand * 1103515245 + 12345;
|
|
|
|
|
|
|
|
return (pdc_uint)(pdc->last_rand / 65536) % 32768;
|
|
|
|
} /* pdc_rand */
|
|
|
|
|
|
|
|
void
|
|
|
|
pdc_srand(pdc_core *pdc, pdc_uint seed)
|
|
|
|
{
|
|
|
|
pdc->last_rand = seed;
|
|
|
|
} /* pdc_srand */
|