|
Packit |
cdaae3 |
/*
|
|
Packit |
cdaae3 |
Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved.
|
|
Packit |
cdaae3 |
Portions Copyright (C) 2013-2017 David Anderson. All Rights Reserved.
|
|
Packit |
cdaae3 |
This program is free software; you can redistribute it and/or modify it
|
|
Packit |
cdaae3 |
under the terms of version 2 of the GNU General Public License as
|
|
Packit |
cdaae3 |
published by the Free Software Foundation.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
This program is distributed in the hope that it would be useful, but
|
|
Packit |
cdaae3 |
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
cdaae3 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
Further, this software is distributed without any warranty that it is
|
|
Packit |
cdaae3 |
free of the rightful claim of any third person regarding infringement
|
|
Packit |
cdaae3 |
or the like. Any license provided herein, whether implied or
|
|
Packit |
cdaae3 |
otherwise, applies only to this software file. Patent licenses, if
|
|
Packit |
cdaae3 |
any, provided herein do not apply to combinations of this program with
|
|
Packit |
cdaae3 |
other software, or any other product whatsoever.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
You should have received a copy of the GNU General Public License along
|
|
Packit |
cdaae3 |
with this program; if not, write the Free Software Foundation, Inc., 51
|
|
Packit |
cdaae3 |
Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
|
|
Packit |
cdaae3 |
*/
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* esb.c
|
|
Packit |
cdaae3 |
extensible string buffer.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
A simple means (vaguely like a C++ class) that
|
|
Packit |
cdaae3 |
enables safely saving strings of arbitrary length built up
|
|
Packit |
cdaae3 |
in small pieces.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
We really do allow only C strings here. NUL bytes
|
|
Packit |
cdaae3 |
in a string result in adding only up to the NUL (and
|
|
Packit |
cdaae3 |
in the case of certain interfaces here a warning
|
|
Packit |
cdaae3 |
to stderr).
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
Do selftest as follows:
|
|
Packit |
cdaae3 |
gcc -DSELFTEST esb.c
|
|
Packit |
cdaae3 |
./a.out
|
|
Packit |
cdaae3 |
valgrind --leak-check=full ./a.out
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
The functions assume that
|
|
Packit |
cdaae3 |
pointer arguments of all kinds are not NULL.
|
|
Packit |
cdaae3 |
*/
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
#ifndef SELFTEST
|
|
Packit |
cdaae3 |
#include "globals.h"
|
|
Packit |
cdaae3 |
#else
|
|
Packit |
cdaae3 |
#include <stdio.h> /* SELFTEST */
|
|
Packit |
cdaae3 |
#include <string.h> /* SELFTEST */
|
|
Packit |
cdaae3 |
#include <stdlib.h> /* SELFTEST */
|
|
Packit |
cdaae3 |
typedef char * string; /* SELFTEST */
|
|
Packit |
cdaae3 |
#include <stdarg.h> /* For va_start va_arg va_list */
|
|
Packit |
cdaae3 |
#endif
|
|
Packit |
cdaae3 |
#include "esb.h"
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* INITIAL_ALLOC value takes no account of space for a trailing NUL,
|
|
Packit |
cdaae3 |
the NUL is accounted for in init_esb_string
|
|
Packit |
cdaae3 |
and in later tests against esb_allocated_size. */
|
|
Packit |
cdaae3 |
#ifdef SELFTEST
|
|
Packit |
cdaae3 |
#define INITIAL_ALLOC 1 /* SELFTEST */
|
|
Packit |
cdaae3 |
#else
|
|
Packit |
cdaae3 |
/* There is nothing magic about this size.
|
|
Packit |
cdaae3 |
It is just big enough to avoid most resizing. */
|
|
Packit |
cdaae3 |
#define INITIAL_ALLOC 16
|
|
Packit |
cdaae3 |
#endif
|
|
Packit |
cdaae3 |
/* Allow for final NUL */
|
|
Packit |
cdaae3 |
static size_t alloc_size = INITIAL_ALLOC;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* NULL device used when printing formatted strings */
|
|
Packit |
cdaae3 |
static FILE *null_device_handle = 0;
|
|
Packit |
cdaae3 |
#if _WIN32
|
|
Packit |
cdaae3 |
#define NULL_DEVICE_NAME "NUL"
|
|
Packit |
cdaae3 |
#else
|
|
Packit |
cdaae3 |
#define NULL_DEVICE_NAME "/dev/null"
|
|
Packit |
cdaae3 |
#endif /* _WIN32 */
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Open the null device used during formatting printing */
|
|
Packit |
cdaae3 |
FILE *esb_open_null_device(void)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
if (!null_device_handle) {
|
|
Packit |
cdaae3 |
null_device_handle = fopen(NULL_DEVICE_NAME,"w");
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
return null_device_handle;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Close the null device used during formatting printing */
|
|
Packit |
cdaae3 |
void esb_close_null_device(void)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
if (null_device_handle) {
|
|
Packit |
cdaae3 |
fclose(null_device_handle);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
static void
|
|
Packit |
cdaae3 |
init_esb_string(struct esb_s *data, size_t min_len)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
char* d;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (data->esb_allocated_size > 0) {
|
|
Packit |
cdaae3 |
return;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
/* Only esb_constructor applied. Allow for string space. */
|
|
Packit |
cdaae3 |
if (min_len <= alloc_size) {
|
|
Packit |
cdaae3 |
min_len = alloc_size +1;/* Allow for NUL at end */
|
|
Packit |
cdaae3 |
} else {
|
|
Packit |
cdaae3 |
min_len++ ; /* Allow for NUL at end */
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
d = malloc(min_len);
|
|
Packit |
cdaae3 |
if (!d) {
|
|
Packit |
cdaae3 |
fprintf(stderr,
|
|
Packit |
cdaae3 |
"dwarfdump is out of memory allocating %lu bytes\n",
|
|
Packit |
cdaae3 |
(unsigned long) min_len);
|
|
Packit |
cdaae3 |
exit(5);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
data->esb_string = d;
|
|
Packit |
cdaae3 |
data->esb_allocated_size = min_len;
|
|
Packit |
cdaae3 |
data->esb_string[0] = 0;
|
|
Packit |
cdaae3 |
data->esb_used_bytes = 0;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Make more room. Leaving contents unchanged, effectively.
|
|
Packit |
cdaae3 |
The NUL byte at end has room and this preserves that room.
|
|
Packit |
cdaae3 |
*/
|
|
Packit |
cdaae3 |
static void
|
|
Packit |
cdaae3 |
esb_allocate_more(struct esb_s *data, size_t len)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
size_t new_size = data->esb_allocated_size + len;
|
|
Packit |
cdaae3 |
char* newd = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (new_size < alloc_size) {
|
|
Packit |
cdaae3 |
new_size = alloc_size;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
newd = realloc(data->esb_string, new_size);
|
|
Packit |
cdaae3 |
if (!newd) {
|
|
Packit |
cdaae3 |
fprintf(stderr, "dwarfdump is out of memory re-allocating "
|
|
Packit |
cdaae3 |
"%lu bytes\n", (unsigned long) new_size);
|
|
Packit |
cdaae3 |
exit(5);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
/* If the area was reallocated by realloc() the earlier
|
|
Packit |
cdaae3 |
space was free()d by realloc(). */
|
|
Packit |
cdaae3 |
data->esb_string = newd;
|
|
Packit |
cdaae3 |
data->esb_allocated_size = new_size;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Ensure that the total buffer length is large enough that
|
|
Packit |
cdaae3 |
at least minlen bytes are available, unused,
|
|
Packit |
cdaae3 |
in the allocation. */
|
|
Packit |
cdaae3 |
void
|
|
Packit |
cdaae3 |
esb_force_allocation(struct esb_s *data, size_t minlen)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
if (data->esb_allocated_size < (data->esb_used_bytes + minlen)) {
|
|
Packit |
cdaae3 |
esb_allocate_more(data,minlen);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
static void
|
|
Packit |
cdaae3 |
esb_appendn_internal(struct esb_s *data, const char * in_string, size_t len);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
void
|
|
Packit |
cdaae3 |
esb_appendn(struct esb_s *data, const char * in_string, size_t len)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
size_t full_len = strlen(in_string);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (full_len < len) {
|
|
Packit |
cdaae3 |
fprintf(stderr, "dwarfdump esb internal error, bad string length "
|
|
Packit |
cdaae3 |
" %lu < %lu \n",
|
|
Packit |
cdaae3 |
(unsigned long) full_len, (unsigned long) len);
|
|
Packit |
cdaae3 |
len = full_len;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
esb_appendn_internal(data, in_string, len);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* The length is gotten from the in_string itself. */
|
|
Packit |
cdaae3 |
void
|
|
Packit |
cdaae3 |
esb_append(struct esb_s *data, const char * in_string)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
size_t len = 0;
|
|
Packit |
cdaae3 |
if(in_string) {
|
|
Packit |
cdaae3 |
len = strlen(in_string);
|
|
Packit |
cdaae3 |
if (len) {
|
|
Packit |
cdaae3 |
esb_appendn_internal(data, in_string, len);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* The 'len' is believed. Do not pass in strings < len bytes long. */
|
|
Packit |
cdaae3 |
static void
|
|
Packit |
cdaae3 |
esb_appendn_internal(struct esb_s *data, const char * in_string, size_t len)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
size_t remaining = 0;
|
|
Packit |
cdaae3 |
size_t needed = len;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (data->esb_allocated_size == 0) {
|
|
Packit |
cdaae3 |
size_t maxlen = (len >= alloc_size)? (len):alloc_size;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
init_esb_string(data, maxlen);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
/* ASSERT: data->esb_allocated_size > data->esb_used_bytes */
|
|
Packit |
cdaae3 |
remaining = data->esb_allocated_size - data->esb_used_bytes;
|
|
Packit |
cdaae3 |
if (remaining <= needed) {
|
|
Packit |
cdaae3 |
esb_allocate_more(data,len);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
strncpy(&data->esb_string[data->esb_used_bytes], in_string, len);
|
|
Packit |
cdaae3 |
data->esb_used_bytes += len;
|
|
Packit |
cdaae3 |
/* Insist on explicit NUL terminator */
|
|
Packit |
cdaae3 |
data->esb_string[data->esb_used_bytes] = 0;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Always returns an empty string or a non-empty string. Never 0. */
|
|
Packit |
cdaae3 |
char*
|
|
Packit |
cdaae3 |
esb_get_string(struct esb_s *data)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
if (data->esb_allocated_size == 0) {
|
|
Packit |
cdaae3 |
init_esb_string(data, alloc_size);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
return data->esb_string;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Sets esb_used_bytes to zero. The string is not freed and
|
|
Packit |
cdaae3 |
esb_allocated_size is unchanged. */
|
|
Packit |
cdaae3 |
void
|
|
Packit |
cdaae3 |
esb_empty_string(struct esb_s *data)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
if (data->esb_allocated_size == 0) {
|
|
Packit |
cdaae3 |
init_esb_string(data, alloc_size);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
data->esb_used_bytes = 0;
|
|
Packit |
cdaae3 |
data->esb_string[0] = 0;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Return esb_used_bytes. */
|
|
Packit |
cdaae3 |
size_t
|
|
Packit |
cdaae3 |
esb_string_len(struct esb_s *data)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
return data->esb_used_bytes;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* *data is presumed to contain garbage, not values, and
|
|
Packit |
cdaae3 |
is properly initialized here. */
|
|
Packit |
cdaae3 |
void
|
|
Packit |
cdaae3 |
esb_constructor(struct esb_s *data)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
memset(data, 0, sizeof(*data));
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* The string is freed, contents of *data set to zeroes. */
|
|
Packit |
cdaae3 |
void
|
|
Packit |
cdaae3 |
esb_destructor(struct esb_s *data)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
if (data->esb_string) {
|
|
Packit |
cdaae3 |
free(data->esb_string);
|
|
Packit |
cdaae3 |
data->esb_string = 0;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
esb_constructor(data);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* To get all paths in the code tested, this sets the
|
|
Packit |
cdaae3 |
allocation/reallocation to the given value, which can be quite small
|
|
Packit |
cdaae3 |
but must not be zero. */
|
|
Packit |
cdaae3 |
void
|
|
Packit |
cdaae3 |
esb_alloc_size(size_t size)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
alloc_size = size;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
size_t
|
|
Packit |
cdaae3 |
esb_get_allocated_size(struct esb_s *data)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
return data->esb_allocated_size;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Make more room. Leaving contents unchanged, effectively.
|
|
Packit |
cdaae3 |
The NUL byte at end has room and this preserves that room.
|
|
Packit |
cdaae3 |
*/
|
|
Packit |
cdaae3 |
static void
|
|
Packit |
cdaae3 |
esb_allocate_more_if_needed(struct esb_s *data,
|
|
Packit |
cdaae3 |
const char *in_string,va_list ap)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
#ifndef _WIN32
|
|
Packit |
cdaae3 |
static char a_buffer[512];
|
|
Packit |
cdaae3 |
#endif /* _WIN32*/
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
int netlen = 0;
|
|
Packit |
cdaae3 |
va_list ap_copy;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Preserve the original argument list, to be used a second time */
|
|
Packit |
cdaae3 |
va_copy(ap_copy,ap);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
#ifdef _WIN32
|
|
Packit |
cdaae3 |
netlen = vfprintf(null_device_handle,in_string,ap_copy);
|
|
Packit |
cdaae3 |
#else
|
|
Packit |
cdaae3 |
netlen = vsnprintf(a_buffer,sizeof(a_buffer),in_string,ap_copy);
|
|
Packit |
cdaae3 |
#endif /* _WIN32*/
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* "The object ap may be passed as an argument to another
|
|
Packit |
cdaae3 |
function; if that function invokes the va_arg()
|
|
Packit |
cdaae3 |
macro with parameter ap, the value of ap in the calling
|
|
Packit |
cdaae3 |
function is unspecified and shall be passed to the va_end()
|
|
Packit |
cdaae3 |
macro prior to any further reference to ap."
|
|
Packit |
cdaae3 |
Single Unix Specification. */
|
|
Packit |
cdaae3 |
va_end(ap_copy);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Allocate enough space to hold the full text */
|
|
Packit |
cdaae3 |
esb_force_allocation(data,netlen + 1);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Append a formatted string */
|
|
Packit |
cdaae3 |
void
|
|
Packit |
cdaae3 |
esb_append_printf_ap(struct esb_s *data,const char *in_string,va_list ap)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
int netlen = 0;
|
|
Packit |
cdaae3 |
int expandedlen = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Allocate enough space for the input string */
|
|
Packit |
cdaae3 |
esb_allocate_more_if_needed(data,in_string,ap);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
netlen = data->esb_allocated_size - data->esb_used_bytes;
|
|
Packit |
cdaae3 |
expandedlen =
|
|
Packit |
cdaae3 |
vsnprintf(&data->esb_string[data->esb_used_bytes],
|
|
Packit |
cdaae3 |
netlen,in_string,ap);
|
|
Packit |
cdaae3 |
if (expandedlen < 0) {
|
|
Packit |
cdaae3 |
/* There was an error.
|
|
Packit |
cdaae3 |
Do nothing. */
|
|
Packit |
cdaae3 |
return;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (netlen < expandedlen) {
|
|
Packit |
cdaae3 |
/* If data was too small, the max written was one less than
|
|
Packit |
cdaae3 |
netlen. */
|
|
Packit |
cdaae3 |
data->esb_used_bytes += netlen - 1;
|
|
Packit |
cdaae3 |
} else {
|
|
Packit |
cdaae3 |
data->esb_used_bytes += expandedlen;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Append a formatted string */
|
|
Packit |
cdaae3 |
void
|
|
Packit |
cdaae3 |
esb_append_printf(struct esb_s *data,const char *in_string, ...)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
va_list ap;
|
|
Packit |
cdaae3 |
va_start(ap,in_string);
|
|
Packit |
cdaae3 |
esb_append_printf_ap(data,in_string,ap);
|
|
Packit |
cdaae3 |
/* "The object ap may be passed as an argument to another
|
|
Packit |
cdaae3 |
function; if that function invokes the va_arg()
|
|
Packit |
cdaae3 |
macro with parameter ap, the value of ap in the calling
|
|
Packit |
cdaae3 |
function is unspecified and shall be passed to the va_end()
|
|
Packit |
cdaae3 |
macro prior to any further reference to ap."
|
|
Packit |
cdaae3 |
Single Unix Specification. */
|
|
Packit |
cdaae3 |
va_end(ap);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Get a copy of the internal data buffer.
|
|
Packit |
cdaae3 |
It is up to the code calling this
|
|
Packit |
cdaae3 |
to free() the string using the
|
|
Packit |
cdaae3 |
pointer returned here. */
|
|
Packit |
cdaae3 |
char*
|
|
Packit |
cdaae3 |
esb_get_copy(struct esb_s *data)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
char* copy = NULL;
|
|
Packit |
cdaae3 |
size_t len = esb_string_len(data);
|
|
Packit |
cdaae3 |
if (len) {
|
|
Packit |
cdaae3 |
copy = (char*)malloc(len + 1);
|
|
Packit |
cdaae3 |
strcpy(copy,esb_get_string(data));
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
return copy;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
#ifdef SELFTEST
|
|
Packit |
cdaae3 |
static int failcount = 0;
|
|
Packit |
cdaae3 |
void
|
|
Packit |
cdaae3 |
validate_esb(int instance,
|
|
Packit |
cdaae3 |
struct esb_s* d,
|
|
Packit |
cdaae3 |
size_t explen,
|
|
Packit |
cdaae3 |
size_t expalloc,
|
|
Packit |
cdaae3 |
const char *expout)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
printf(" TEST instance %d\n",instance);
|
|
Packit |
cdaae3 |
if (esb_string_len(d) != explen) {
|
|
Packit |
cdaae3 |
++failcount;
|
|
Packit |
cdaae3 |
printf(" FAIL instance %d esb_string_len() %u explen %u\n",
|
|
Packit |
cdaae3 |
instance,(unsigned)esb_string_len(d),(unsigned)explen);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (d->esb_allocated_size != expalloc) {
|
|
Packit |
cdaae3 |
++failcount;
|
|
Packit |
cdaae3 |
printf(" FAIL instance %d esb_allocated_size %u expalloc %u\n",
|
|
Packit |
cdaae3 |
instance,(unsigned)d->esb_allocated_size,(unsigned)expalloc);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if(strcmp(esb_get_string(d),expout)) {
|
|
Packit |
cdaae3 |
++failcount;
|
|
Packit |
cdaae3 |
printf(" FAIL instance %d esb_get_stringr %s expstr %s\n",
|
|
Packit |
cdaae3 |
instance,esb_get_string(d),expout);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
void
|
|
Packit |
cdaae3 |
trialprint_1(struct esb_s *d, char *format,...)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
va_list ap;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
va_start(ap,format);
|
|
Packit |
cdaae3 |
esb_append_printf_ap(d,format,ap);
|
|
Packit |
cdaae3 |
va_end(ap);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
void
|
|
Packit |
cdaae3 |
trialprint(struct esb_s *d)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
const char * s = "insert me";
|
|
Packit |
cdaae3 |
trialprint_1(d,"aaaa %s bbbb",s);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
int main()
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
#ifdef _WIN32
|
|
Packit |
cdaae3 |
/* Open the null device used during formatting printing */
|
|
Packit |
cdaae3 |
if (!esb_open_null_device())
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
fprintf(stderr, "esb: Unable to open null device.\n");
|
|
Packit |
cdaae3 |
exit(1);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
#endif /* _WIN32 */
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
struct esb_s d;
|
|
Packit |
cdaae3 |
esb_constructor(&d);
|
|
Packit |
cdaae3 |
esb_append(&d,"a");
|
|
Packit |
cdaae3 |
validate_esb(1,&d,1,2,"a");
|
|
Packit |
cdaae3 |
esb_append(&d,"b");
|
|
Packit |
cdaae3 |
validate_esb(2,&d,2,3,"ab");
|
|
Packit |
cdaae3 |
esb_append(&d,"c");
|
|
Packit |
cdaae3 |
validate_esb(3,&d,3,4,"abc");
|
|
Packit |
cdaae3 |
esb_empty_string(&d);
|
|
Packit |
cdaae3 |
validate_esb(4,&d,0,4,"");
|
|
Packit |
cdaae3 |
esb_destructor(&d);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
struct esb_s d;
|
|
Packit |
cdaae3 |
esb_constructor(&d);
|
|
Packit |
cdaae3 |
esb_append(&d,"aa");
|
|
Packit |
cdaae3 |
validate_esb(6,&d,2,3,"aa");
|
|
Packit |
cdaae3 |
esb_append(&d,"bbb");
|
|
Packit |
cdaae3 |
validate_esb(7,&d,5,6,"aabbb");
|
|
Packit |
cdaae3 |
esb_append(&d,"c");
|
|
Packit |
cdaae3 |
validate_esb(8,&d,6,7,"aabbbc");
|
|
Packit |
cdaae3 |
esb_empty_string(&d);
|
|
Packit |
cdaae3 |
validate_esb(9,&d,0,7,"");
|
|
Packit |
cdaae3 |
esb_destructor(&d);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
struct esb_s d;
|
|
Packit |
cdaae3 |
static char oddarray[7] = {'a','b',0,'c','c','d',0};
|
|
Packit |
cdaae3 |
esb_constructor(&d);
|
|
Packit |
cdaae3 |
fprintf(stderr," esb_appendn call error(intentional). Expect msg on stderr\n");
|
|
Packit |
cdaae3 |
/* This provokes a msg on stderr. Bad input. */
|
|
Packit |
cdaae3 |
esb_appendn(&d,oddarray,6);
|
|
Packit |
cdaae3 |
validate_esb(10,&d,2,3,"ab");
|
|
Packit |
cdaae3 |
esb_appendn(&d,"cc",1);
|
|
Packit |
cdaae3 |
validate_esb(11,&d,3,4,"abc");
|
|
Packit |
cdaae3 |
esb_empty_string(&d);
|
|
Packit |
cdaae3 |
validate_esb(12,&d,0,4,"");
|
|
Packit |
cdaae3 |
esb_destructor(&d);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
struct esb_s d;
|
|
Packit |
cdaae3 |
esb_constructor(&d);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
esb_force_allocation(&d,7);
|
|
Packit |
cdaae3 |
esb_append(&d,"aaaa i");
|
|
Packit |
cdaae3 |
validate_esb(13,&d,6,7,"aaaa i");
|
|
Packit |
cdaae3 |
esb_destructor(&d);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
struct esb_s d5;
|
|
Packit |
cdaae3 |
esb_constructor(&d5;;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
esb_force_allocation(&d5,50);
|
|
Packit |
cdaae3 |
trialprint(&d5;;
|
|
Packit |
cdaae3 |
validate_esb(14,&d5,19,50,"aaaa insert me bbbb");
|
|
Packit |
cdaae3 |
esb_destructor(&d5;;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
struct esb_s d;
|
|
Packit |
cdaae3 |
struct esb_s e;
|
|
Packit |
cdaae3 |
char* result = NULL;
|
|
Packit |
cdaae3 |
esb_constructor(&d);
|
|
Packit |
cdaae3 |
esb_constructor(&e);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
esb_append(&d,"abcde fghij klmno pqrst");
|
|
Packit |
cdaae3 |
validate_esb(15,&d,23,24,"abcde fghij klmno pqrst");
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
result = esb_get_copy(&d);
|
|
Packit |
cdaae3 |
esb_append(&e,result);
|
|
Packit |
cdaae3 |
validate_esb(16,&e,23,24,"abcde fghij klmno pqrst");
|
|
Packit |
cdaae3 |
esb_destructor(&d);
|
|
Packit |
cdaae3 |
esb_destructor(&e);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
#ifdef _WIN32
|
|
Packit |
cdaae3 |
/* Close the null device used during formatting printing */
|
|
Packit |
cdaae3 |
esb_close_null_device();
|
|
Packit |
cdaae3 |
#endif /* _WIN32 */
|
|
Packit |
cdaae3 |
if (failcount) {
|
|
Packit |
cdaae3 |
printf("FAIL esb test\n");
|
|
Packit |
cdaae3 |
exit(1);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
printf("PASS esb test\n");
|
|
Packit |
cdaae3 |
exit(0);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
#endif /* SELFTEST */
|