#include "config.h"
#include <stdio.h> /* for malloc */
#ifdef HAVE_STDLIB_H
#include <stdlib.h> /* for malloc */
#endif /* HAVE_STDLIB_H */
#include <string.h> /* for strlen */
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif /* HAVE_MALLOC_H */
#include "dwarfstring.h"
#ifndef TRUE
#define TRUE 1
#endif /* TRUE */
#ifndef FALSE
#define FALSE 0
#endif /* FALSE */
#ifdef HAVE_UNUSED_ATTRIBUTE
#define UNUSEDARG __attribute__ ((unused))
#else
#define UNUSEDARG
#endif
#ifndef DW_DLV_OK
#define DW_DLV_OK 0
#define DW_DLV_NO_ENTRY -1
#define DW_DLV_ERROR 1
#endif /* DW_DLV_OK */
static
unsigned
long
minimumnewlen = 30;
int
dwarfstring_constructor(
struct
dwarfstring_s *g)
{
g->s_data =
""
;
g->s_size = 0;
g->s_avail = 0;
g->s_malloc = FALSE;
return
TRUE;
}
static
int
dwarfstring_resize_to(
struct
dwarfstring_s *g,unsigned
long
newlen)
{
char
*b = 0;
unsigned
long
lastpos =
g->s_size - g->s_avail;
unsigned
long
malloclen = newlen+1;
if
(malloclen < minimumnewlen) {
malloclen = minimumnewlen;
}
b =
malloc
(malloclen);
if
(!b) {
return
FALSE;
}
if
(lastpos > 0) {
memcpy
(b,g->s_data,lastpos);
}
if
(g->s_malloc) {
free
(g->s_data);
g->s_data = 0;
}
g->s_data = b;
g->s_data[lastpos] = 0;
g->s_size = newlen;
g->s_avail = newlen - lastpos;
g->s_malloc = TRUE;
return
TRUE;
}
int
dwarfstring_reset(
struct
dwarfstring_s *g)
{
if
(!g->s_size) {
return
TRUE;
}
g->s_avail = g->s_size;
g->s_data[0] = 0;
return
TRUE;
}
int
dwarfstring_constructor_fixed(
struct
dwarfstring_s *g,unsigned
long
len)
{
int
r = FALSE;
dwarfstring_constructor(g);
if
(len == 0) {
return
TRUE;
}
r = dwarfstring_resize_to(g,len);
if
(!r) {
return
FALSE;
}
return
TRUE;
}
int
dwarfstring_constructor_static(
struct
dwarfstring_s *g,
char
* space,
unsigned
long
len)
{
dwarfstring_constructor(g);
g->s_data = space;
g->s_data[0] = 0;
g->s_size = len;
g->s_avail = len;
g->s_malloc = FALSE;
return
TRUE;
}
void
dwarfstring_destructor(
struct
dwarfstring_s *g)
{
if
(g->s_malloc) {
free
(g->s_data);
g->s_data = 0;
}
dwarfstring_constructor(g);
}
int
dwarfstring_append_length(
struct
dwarfstring_s *g,
char
*str,
unsigned
long
slen)
{
unsigned
long
lastpos = g->s_size - g->s_avail;
int
r = 0;
if
(!str || slen ==0) {
return
TRUE;
}
if
(slen >= g->s_avail) {
unsigned
long
newlen = 0;
newlen = g->s_size + slen+2;
r = dwarfstring_resize_to(g,newlen);
if
(!r) {
return
FALSE;
}
}
memcpy
(g->s_data + lastpos,str,slen);
g->s_avail -= slen;
g->s_data[g->s_size - g->s_avail] = 0;
return
TRUE;
}
int
dwarfstring_append(
struct
dwarfstring_s *g,
char
*str)
{
unsigned
long
dlen = 0;
if
(!str) {
return
TRUE;
}
dlen =
strlen
(str);
return
dwarfstring_append_length(g,str,dlen);
}
char
*
dwarfstring_string(
struct
dwarfstring_s *g)
{
return
g->s_data;
}
unsigned
long
dwarfstring_strlen(
struct
dwarfstring_s *g)
{
return
g->s_size - g->s_avail;
}
static
int
_dwarfstring_append_spaces(dwarfstring *data,
size_t
count)
{
int
res = 0;
char
spacebuf[] = {
" "
};
size_t
charct =
sizeof
(spacebuf)-1;
size_t
l = count;
while
(l > charct) {
res = dwarfstring_append_length(data,spacebuf,charct);
l -= charct;
if
(res != DW_DLV_OK) {
return
res;
}
}
res = dwarfstring_append_length(data,spacebuf,l);
return
res;
}
static
int
_dwarfstring_append_zeros(dwarfstring *data,
size_t
l)
{
int
res = 0;
static
char
zeros[] = {
"0000000000000000000000000000000000000000"
};
size_t
charct =
sizeof
(zeros)-1;
while
(l > charct) {
res = dwarfstring_append_length(data,zeros,charct);
l -= charct;
if
(res != DW_DLV_OK) {
return
res;
}
}
dwarfstring_append_length(data,zeros,l);
return
res;
}
int
dwarfstring_append_printf_s(dwarfstring *data,
char
*format,
char
*s)
{
size_t
stringlen =
strlen
(s);
size_t
next = 0;
long
val = 0;
char
*endptr = 0;
const
char
*numptr = 0;
size_t
fixedlen = 0;
long
leftjustify = 0;
size_t
prefixlen = 0;
int
res = 0;
while
(format[next] && format[next] !=
'%'
) {
++next;
++prefixlen;
}
if
(prefixlen) {
dwarfstring_append_length(data,format,prefixlen);
}
if
(!format[next]) {
return
DW_DLV_OK;
}
next++;
if
(format[next] ==
'-'
) {
leftjustify++;
next++;
}
numptr = format+next;
val =
strtol
(numptr,&endptr,10);
if
( endptr != numptr) {
fixedlen = val;
}
next = (endptr - format);
if
(format[next] !=
's'
) {
return
DW_DLV_ERROR;
}
next++;
if
(leftjustify) {
if
(fixedlen && fixedlen <= stringlen) {
dwarfstring_append_length(data,s,fixedlen);
}
else
{
dwarfstring_append_length(data,s,stringlen);
if
(fixedlen) {
size_t
trailingspaces = fixedlen - stringlen;
_dwarfstring_append_spaces(data,trailingspaces);
}
}
}
else
{
if
(fixedlen && fixedlen <= stringlen) {
dwarfstring_append_length(data,s,fixedlen);
}
else
{
if
(fixedlen) {
size_t
leadingspaces = fixedlen - stringlen;
size_t
k = 0;
for
( ; k < leadingspaces; ++k) {
dwarfstring_append_length(data,
" "
,1);
}
}
dwarfstring_append_length(data,s,stringlen);
}
}
if
(!format[next]) {
return
DW_DLV_OK;
}
{
char
* startpt = format+next;
size_t
suffixlen =
strlen
(startpt);
res = dwarfstring_append_length(data,startpt,suffixlen);
}
return
res;
}
static
char
v32m[] = {
"-2147483648"
};
static
char
v64m[] = {
"-9223372036854775808"
};
static
char
dtable[10] = {
'0'
,
'1'
,
'2'
,
'3'
,
'4'
,
'5'
,
'6'
,
'7'
,
'8'
,
'9'
};
static
char
xtable[16] = {
'0'
,
'1'
,
'2'
,
'3'
,
'4'
,
'5'
,
'6'
,
'7'
,
'8'
,
'9'
,
'a'
,
'b'
,
'c'
,
'd'
,
'e'
,
'f'
};
static
char
Xtable[16] = {
'0'
,
'1'
,
'2'
,
'3'
,
'4'
,
'5'
,
'6'
,
'7'
,
'8'
,
'9'
,
'A'
,
'B'
,
'C'
,
'D'
,
'E'
,
'F'
};
int
dwarfstring_append_printf_i(dwarfstring *data,
char
*format,
dwarfstring_i v)
{
int
res = DW_DLV_OK;
size_t
next = 0;
long
val = 0;
char
*endptr = 0;
const
char
*numptr = 0;
size_t
fixedlen = 0;
int
leadingzero = 0;
int
pluscount = 0;
int
lcount = 0;
int
ucount = 0;
int
dcount = 0;
int
xcount = 0;
int
Xcount = 0;
char
*ctable = dtable;
size_t
prefixlen = 0;
int
done = 0;
while
(format[next] && format[next] !=
'%'
) {
++next;
++prefixlen;
}
dwarfstring_append_length(data,format,prefixlen);
if
(format[next] !=
'%'
) {
return
DW_DLV_OK;
}
next++;
if
(format[next] ==
'-'
) {
next++;
}
if
(format[next] ==
'+'
) {
pluscount++;
next++;
}
if
(format[next] ==
'0'
) {
leadingzero = 1;
next++;
}
numptr = format+next;
val =
strtol
(numptr,&endptr,10);
if
( endptr != numptr) {
fixedlen = val;
}
next = (endptr - format);
#if defined(_WIN32) && defined(HAVE_NONSTANDARD_PRINTF_64_FORMAT)
if
(format[next] ==
'I'
) {
next++;
}
if
(format[next] ==
'6'
) {
next++;
}
if
(format[next] ==
'4'
) {
next++;
}
#endif /* HAVE_NONSTANDARD_PRINTF_64_FORMAT */
if
(format[next] ==
'l'
) {
lcount++;
next++;
}
if
(format[next] ==
'l'
) {
lcount++;
next++;
}
if
(format[next] ==
'u'
) {
ucount++;
next++;
}
if
(format[next] ==
'd'
) {
dcount++;
next++;
}
if
(format[next] ==
'x'
) {
xcount++;
next++;
}
if
(format[next] ==
'X'
) {
Xcount++;
next++;
}
if
(format[next] ==
's'
) {
return
DW_DLV_ERROR;
}
if
(!dcount || (lcount >2) ||
(Xcount +xcount+dcount+ucount) > 1) {
return
DW_DLV_ERROR;
}
{
char
digbuf[36];
char
*digptr = digbuf+
sizeof
(digbuf) -1;
size_t
digcharlen = 0;
dwarfstring_i remaining = v;
int
vissigned = 0;
dwarfstring_i divisor = 10;
*digptr = 0;
--digptr;
if
(v < 0) {
vissigned = 1;
if
(
sizeof
(v) == 8) {
dwarfstring_u vm = 0x7fffffffffffffffULL;
if
(vm == (dwarfstring_u)~v) {
memcpy
(digbuf,v64m,
sizeof
(v64m));
digcharlen =
sizeof
(v64m)-1;
digptr = digbuf;
done = 1;
}
else
{
remaining = -v;
}
}
else
if
(
sizeof
(v) == 4) {
dwarfstring_u vm = 0x7fffffffL;
if
(vm == (dwarfstring_u)~v) {
memcpy
(digbuf,v32m,
sizeof
(v32m));
digcharlen =
sizeof
(v32m)-1;
digptr = digbuf;
done = 1;
}
else
{
remaining = -v;
}
}
else
{
return
DW_DLV_ERROR;
}
}
if
(!done) {
for
( ;; ) {
dwarfstring_u dig = 0;
dig = remaining % divisor;
remaining /= divisor;
*digptr = ctable[dig];
digcharlen++;
if
(!remaining) {
break
;
}
--digptr;
}
if
(vissigned) {
--digptr;
digcharlen++;
*digptr =
'-'
;
}
else
if
(pluscount) {
--digptr;
digcharlen++;
*digptr =
'+'
;
}
}
if
(fixedlen > 0) {
if
(fixedlen <= digcharlen) {
dwarfstring_append_length(data,digptr,digcharlen);
}
else
{
size_t
prefixcount = fixedlen - digcharlen;
if
(!leadingzero) {
_dwarfstring_append_spaces(data,prefixcount);
dwarfstring_append_length(data,digptr,digcharlen);
}
else
{
if
(*digptr ==
'-'
) {
dwarfstring_append_length(data,
"-"
,1);
_dwarfstring_append_zeros(data,prefixcount);
digptr++;
dwarfstring_append_length(data,digptr,
digcharlen-1);
}
else
if
(*digptr ==
'+'
) {
dwarfstring_append_length(data,
"+"
,1);
_dwarfstring_append_zeros(data,prefixcount);
digptr++;
dwarfstring_append_length(data,digptr,
digcharlen-1);
}
else
{
_dwarfstring_append_zeros(data,prefixcount);
dwarfstring_append_length(data,digptr,
digcharlen);
}
}
}
}
else
{
res = dwarfstring_append_length(data,digptr,digcharlen);
}
}
if
(format[next]) {
size_t
trailinglen =
strlen
(format+next);
res = dwarfstring_append_length(data,format+next,trailinglen);
}
return
res;
}
#if 0
static
unsigned
trimleadingzeros(
char
*ptr,unsigned digits,unsigned keepcount)
{
char
*cp = ptr;
unsigned leadzeroscount = 0;
unsigned trimoff = 0;
for
(; *cp; ++cp) {
if
(*cp ==
'0'
) {
leadzeroscount++;
continue
;
}
}
trimoff = keepcount - digits;
if
(trimoff&1) {
trimoff--;
}
return
trimoff;
}
#endif /* 0 */
int
dwarfstring_append_printf_u(dwarfstring *data,
char
*format,
dwarfstring_u v)
{
size_t
next = 0;
long
val = 0;
char
*endptr = 0;
const
char
*numptr = 0;
size_t
fixedlen = 0;
int
leadingzero = 0;
int
lcount = 0;
int
ucount = 0;
int
dcount = 0;
int
xcount = 0;
int
Xcount = 0;
char
*ctable = 0;
size_t
divisor = 0;
size_t
prefixlen = 0;
while
(format[next] && format[next] !=
'%'
) {
++next;
++prefixlen;
}
dwarfstring_append_length(data,format,prefixlen);
if
(format[next] !=
'%'
) {
return
DW_DLV_OK;
}
next++;
if
(format[next] ==
'-'
) {
next++;
}
if
(format[next] ==
'0'
) {
leadingzero = 1;
next++;
}
numptr = format+next;
val =
strtol
(numptr,&endptr,10);
if
( endptr != numptr) {
fixedlen = val;
}
next = (endptr - format);
#if defined(_WIN32) && defined(HAVE_NONSTANDARD_PRINTF_64_FORMAT)
if
(format[next] ==
'I'
) {
next++;
}
if
(format[next] ==
'6'
) {
next++;
}
if
(format[next] ==
'4'
) {
next++;
}
#endif /* HAVE_NONSTANDARD_PRINTF_64_FORMAT */
if
(format[next] ==
'l'
) {
lcount++;
next++;
}
if
(format[next] ==
'l'
) {
lcount++;
next++;
}
if
(format[next] ==
'u'
) {
ucount++;
next++;
}
if
(format[next] ==
'd'
) {
dcount++;
next++;
}
if
(format[next] ==
'x'
) {
xcount++;
next++;
}
if
(format[next] ==
'X'
) {
Xcount++;
next++;
}
if
(format[next] ==
's'
) {
return
DW_DLV_ERROR;
}
if
( (Xcount +xcount+dcount+ucount) > 1) {
return
DW_DLV_ERROR;
}
if
(lcount > 2) {
return
DW_DLV_ERROR;
}
if
(dcount > 0) {
return
DW_DLV_ERROR;
}
if
(ucount) {
divisor = 10;
ctable = dtable;
}
else
{
divisor = 16;
if
(xcount) {
ctable = xtable;
}
else
{
ctable = Xtable;
}
}
{
char
digbuf[36];
char
*digptr = 0;
unsigned digcharlen = 0;
dwarfstring_u remaining = v;
if
(divisor == 16) {
digptr = digbuf+
sizeof
(digbuf) -1;
for
( ;; ) {
dwarfstring_u dig;
dig = remaining & 0xf;
remaining = remaining >> 4;
*digptr = ctable[dig];
++digcharlen;
if
(!remaining) {
break
;
}
--digptr;
}
}
else
{
digptr = digbuf+
sizeof
(digbuf) -1;
*digptr = 0;
--digptr;
for
( ;; ) {
dwarfstring_u dig;
dig = remaining % divisor;
remaining /= divisor;
*digptr = ctable[dig];
++digcharlen;
if
(!remaining) {
break
;
}
--digptr;
}
}
if
(fixedlen <= digcharlen) {
dwarfstring_append_length(data,digptr,digcharlen);
}
else
{
if
(!leadingzero) {
size_t
justcount = fixedlen - digcharlen;
_dwarfstring_append_spaces(data,justcount);
dwarfstring_append_length(data,digptr,digcharlen);
}
else
{
size_t
prefixcount = fixedlen - digcharlen;
_dwarfstring_append_zeros(data,prefixcount);
dwarfstring_append_length(data,digptr,digcharlen);
}
}
}
if
(format[next]) {
size_t
trailinglen =
strlen
(format+next);
dwarfstring_append_length(data,format+next,trailinglen);
}
return
DW_DLV_OK;
}