blob: f498967f18a8010127a8933be1d85bb68e423f6e [file] [log] [blame]
/*
* Routines for converting between native data format and
* AIF or for constructing AIF objects.
*
* Copyright (c) 1996-2002 by Guardsoft Pty Ltd.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include "aif.h"
#include "aiferr.h"
#include "aifint.h"
#if defined(WINDOWSNT) || defined(WIN32)
#define BITSPERBYTE 8
#elif defined(__APPLE__)
#include <sys/types.h>
#define BITSPERBYTE NBBY
#else /* WINDOWSNT || WIN32 */
#include <values.h>
#endif /* WINDOWSNT || WIN32 */
union ieee
{
char c;
int i;
AIFLONGEST li;
float f;
double d;
AIFDOUBLEST dd;
/*
** long enough for any conceivable precision
*/
char bytes[256/BITSPERBYTE];
};
/*
* For _aif_*_to_str() functions
*/
static char *_str_buf = NULL;
static char *_str_pos = NULL;
static int _str_buf_len = 0;
/*
* Convert base type to standard byte ordering.
*/
void
_aif_normalise(char *dst, int dstlen, char *src, int srclen)
{
#ifndef WORDS_BIGENDIAN
int i;
#endif
int len;
int pad = 0;
ResetAIFError();
if ( srclen < dstlen )
{
len = srclen;
pad = dstlen - srclen;
}
else if ( srclen >= dstlen )
len = dstlen;
#ifdef WORDS_BIGENDIAN
memcpy(dst, src+srclen-len, len);
if ( pad > 0 )
memset(dst+len, '\0', pad);
#else /* WORDS_BIGENDIAN */
for ( i = len - 1 ; i >= 0 ; i-- )
*dst++ = src[i];
if ( pad > 0 )
memset(dst, '\0', pad);
#endif /* WORDS_BIGENDIAN */
}
/*
* Normalise a value to the standard format
*/
void
AIFNormalise(char *dst, int dstlen, char *src, int srclen)
{
_aif_normalise(dst, dstlen, src, srclen);
}
/*
* Convert a pointer value to AIF data format. Result is rd.
*/
int
_pointer_to_aif(char **rd, const AIF *addr, const AIF *val)
{
char * d;
if ( rd == NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
ResetAIFError();
if( *rd == NULL ) {
*rd = (char *)_aif_alloc(AIF_LEN(addr) + AIF_LEN(val) + 1);
}
d = *rd;
*d++ = (char) AIF_PTR_NORMAL; /* indicates normal pointer value */
memcpy(d, AIF_DATA(addr), AIF_LEN(addr));
d += AIF_LEN(addr);
memcpy(d, AIF_DATA(val), AIF_LEN(val));
return 0;
}
/*
* Convert an integer value of any length to AIF data format.
* Result is rd.
*/
int
_longest_to_aif(char **rd, int len, AIFLONGEST val)
{
int srclen;
union ieee f;
if ( rd == NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
ResetAIFError();
if( *rd == NULL )
*rd = (char *)_aif_alloc(len);
if ( len <= sizeof(int) )
{
f.i = (int)val;
srclen = sizeof(int);
}
else
{
f.li = val;
srclen = sizeof(AIFLONGEST);
}
_aif_normalise(*rd, len, f.bytes, srclen);
return 0;
}
/*
* Convert a character value to AIF data format. Result is rd.
*/
int
_char_to_aif(char **rd, char val)
{
union ieee f;
if ( rd == NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
ResetAIFError();
if( *rd == NULL )
*rd = (char *)_aif_alloc(sizeof(char));
f.c = val;
AIFNormalise(*rd, sizeof(char), f.bytes, sizeof(char));
return 0;
}
/*
* Add a name to an AIF object. The object is not modified
* if it is already named.
*/
int
NameAIF(AIF *a, int name)
{
char * fmt;
if ( a == NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
ResetAIFError();
if (*AIF_FORMAT(a) != AIF_NAME) {
fmt = strdup(AIF_NAME_TYPE(name, AIF_FORMAT(a)));
_aif_free(AIF_FORMAT(a));
AIF_FORMAT(a) = fmt;
}
return 0;
}
int
AIFSetIdentifier(AIF *a, char *id)
{
return FDSSetIdentifier(&(AIF_FORMAT(a)), id);
}
char *
AIFGetIdentifier(AIF *a)
{
return FDSGetIdentifier(AIF_FORMAT(a));
}
/*
* Create an empty reference to an AIF object
*/
AIF *
ReferenceAIF(int name)
{
AIF * a;
ResetAIFError();
a = NewAIF(0, 0);
AIF_FORMAT(a) = strdup(AIF_REFERENCE_TYPE(name));
AIF_LEN(a) = 0;
return a;
}
/*
* Create a null pointer.
*
* The argument supplies the type that the pointer points to. If it is named,
* that name is used in the resulting AIF; otherwise,
* the format of the argument is used to generate the format of the new AIF.
*/
AIF *
AIFNullPointer(AIF *i)
{
int name;
AIF * a;
char * fmt;
char * oldFormat = AIF_FORMAT(i);
ResetAIFError();
a = NewAIF(0, 1);
if ( *oldFormat == FDS_NAME )
{
/*
** a reference
*/
sscanf(oldFormat, "%%%d/", &name);
fmt = strdup(AIF_REFERENCE_TYPE(name));
AIF_FORMAT(a) = strdup(AIF_POINTER_TYPE(AIF_ADDRESS_TYPE(sizeof(char *)), fmt));
_aif_free(fmt);
}
else
{
/*
** repeat the format
*/
AIF_FORMAT(a) = strdup(AIF_POINTER_TYPE(AIF_ADDRESS_TYPE(sizeof(char *)), oldFormat));
}
AIF_DATA(a)[0] = AIF_PTR_NIL;
AIF_LEN(a) = 1;
return a;
}
AIF *
PointerNameToAIF(AIF *i)
{
AIF * a;
int name;
char * fmt = AIF_FORMAT(i);
a = NewAIF(0, AIF_LEN(i)+2);
sscanf(fmt, "%%%d/", &name);
AIF_FORMAT(a) = strdup(AIF_POINTER_TYPE(AIF_ADDRESS_TYPE(sizeof(char *)), AIF_FORMAT(i)));
*(AIF_DATA(a)) = (char) AIF_PTR_NAME;
_int_to_ptrname( (int) name, AIF_DATA(a)+1);
memcpy(AIF_DATA(a)+5, AIF_DATA(i), AIF_LEN(i));
ResetAIFError();
return a;
}
AIF *
PointerReferenceToAIF(AIF *i)
{
int name;
AIF * a;
char * fmt;
char * oldFormat = AIF_FORMAT(i);
ResetAIFError();
a = NewAIF(0, 2);
if ( *oldFormat == FDS_NAME )
{
/*
** a reference
*/
sscanf(oldFormat, "%%%d/", &name);
fmt = strdup(AIF_REFERENCE_TYPE(name));
AIF_FORMAT(a) = strdup(AIF_POINTER_TYPE(AIF_ADDRESS_TYPE(sizeof(char *)), fmt));
_aif_free(fmt);
}
AIF_DATA(a)[0] = AIF_PTR_REFERENCE;
_int_to_ptrname( (int) name, AIF_DATA(a)+1);
AIF_LEN(a) = 5;
return a;
}
/*
* Create a pointer to an AIF object.
*/
AIF *
PointerToAIF(AIF *addr, AIF *i)
{
AIF * a;
a = NewAIF(0, AIF_LEN(addr)+AIF_LEN(i)+1);
AIF_FORMAT(a) = strdup(AIF_POINTER_TYPE(AIF_FORMAT(addr), AIF_FORMAT(i)));
if ( _pointer_to_aif(&AIF_DATA(a), addr, i) < 0 )
{
AIFFree(a);
return (AIF *)NULL;
}
ResetAIFError();
return a;
}
AIF *
CharPointerToAIF(AIF *addr, char *val)
{
AIF * a;
int length = strlen(val);
if ( length > 1 << (2 * BITSPERBYTE) )
{
SetAIFError(AIFERR_STRING, NULL);
return (AIF *)NULL;
}
ResetAIFError();
a = NewAIF(0, AIF_LEN(addr)+length+2);
AIF_FORMAT(a) = strdup(AIF_CHAR_POINTER_TYPE(AIF_FORMAT(addr)));
memcpy(AIF_DATA(a), AIF_DATA(addr), AIF_LEN(addr));
(AIF_DATA(a))[AIF_LEN(addr)] = (length >> 8) & 0xff;
(AIF_DATA(a))[AIF_LEN(addr)+1] = length & 0xff;
strncpy(AIF_DATA(a)+AIF_LEN(addr)+2, val, length);
return a;
}
/*
* Convert a string (defined as a pointer to a null terminated array
* of characters) to AIF format.
*/
AIF *
StringToAIF(char *i)
{
AIF * a;
int length = strlen(i);
if ( length > 1 << (2 * BITSPERBYTE) )
{
SetAIFError(AIFERR_STRING, NULL);
return (AIF *)NULL;
}
ResetAIFError();
a = NewAIF(0, length+2);
AIF_FORMAT(a) = strdup(AIF_STRING_TYPE());
(AIF_DATA(a))[0] = (length >> 8) & 0xff;
(AIF_DATA(a))[1] = length & 0xff;
strncpy(AIF_DATA(a)+2, i, length);
return a;
}
/* Converts input buffer to hexadecimal display in output string.
* String length is used since zero is legitimate.
*/
static void
ByteToHex(char *out_string, char *in_string, int in_size)
{
char hexchars[] = "0123456789ABCDEF";
char ch;
int i;
for (i=0; i<in_size; i++) {
ch = *in_string++;
*out_string++ = hexchars[(ch >> 4) & 0xf]; /* [c/16]; */
*out_string++ = hexchars[ ch & 0xf]; /* [c%16]; */
}
}
/* Get default address format with size
*
*/
static char *
GetDefaultAddress(int size)
{
int i;
const char * pattern = "00";
char * addr = (char *)malloc(size*2 + 1);
for (i=0; i < size; i++) {
memcpy(&addr[i*2], pattern, 2);
}
addr[size*2] = '\0';
return addr;
}
/*
* Converts a hexadecimal string 'in_string' representing an address of size 'in_size'
* bytes to binary and copies to 'out_string'.
*
* If 'in_string' is NULL, the null address will be used.
*
* if 'in_string' is smaller than the address size, it will be assumed to be
* padded with zeros.
*
*/
static void
HexToByte(char *out_string, char *in_string, int in_size)
{
int i;
int h_value;
int c_value;
int byte_val = 0;
int in_len;
int def_len = 0;
char * input;
char * def_input;
def_input = GetDefaultAddress(in_size);
if (in_size % 2 != 0 || in_string == NULL) {
strcpy(out_string, def_input);
free(def_input);
return;
}
in_len = strlen(in_string);
def_len = strlen(def_input);
if (in_len == def_len) {
strcpy(def_input, in_string);
} else {
for (i = def_len - in_len; i < def_len; i++) {
def_input[i] = *in_string++;
}
}
for (input = def_input, i = 0; i < in_size * 2; i++) {
if ((h_value = *input++) >= '0' && h_value <= '9')
c_value = h_value - '0';
else
c_value = 10 + (h_value & 0xf) - ('a' & 0xf);
if (!(i % 2))
byte_val = c_value * 16;
else
*out_string++ = byte_val + c_value;
}
free(def_input);
}
/*
* Convert a null terminated array of hexadecimal characters to
* an AIF address of length 'len'.
*
* If 'addr' is NULL, returns the null address. 'addr' will be assumed
* to be padded with zeros.
*/
AIF *
AddressToAIF(char *addr, int len)
{
AIF * a;
a = NewAIF(0, len);
AIF_FORMAT(a) = strdup(AIF_ADDRESS_TYPE(len));
HexToByte(AIF_DATA(a), addr, len);
return a;
}
/*
* Convert a boolean value to AIF.
*/
AIF *
BoolToAIF(int b)
{
AIF * a;
int size = 1;
int val;
a = NewAIF(0, size);
AIF_FORMAT(a) = strdup(AIF_BOOLEAN_TYPE(size));
if (b == 0) {
val = AIF_BOOLEAN_FALSE;
} else {
val = AIF_BOOLEAN_TRUE;
}
if ( _longest_to_aif(&AIF_DATA(a), size, (AIFLONGEST)val) < 0 )
{
AIFFree(a);
return (AIF *)NULL;
}
return a;
}
/*
* Convert a character to AIF.
*/
AIF *
CharToAIF(char c)
{
AIF * a;
a = NewAIF(0, sizeof(char));
AIF_FORMAT(a) = strdup(AIF_CHARACTER_TYPE());
if ( _char_to_aif(&AIF_DATA(a), c) < 0 )
{
AIFFree(a);
return (AIF *)NULL;
}
return a;
}
/*
* Convert a short integer to AIF.
*/
AIF *
ShortToAIF(short i)
{
AIF * a;
a = NewAIF(0, sizeof(short));
AIF_FORMAT(a) = strdup(AIF_INTEGER_TYPE(1, sizeof(short)));
if ( _longest_to_aif(&AIF_DATA(a), sizeof(short), (AIFLONGEST)i) < 0 )
{
AIFFree(a);
return (AIF *)NULL;
}
return a;
}
/*
* Convert an unsigned short to AIF.
*/
AIF *
UnsignedShortToAIF(unsigned short i)
{
AIF * a;
a = NewAIF(0, sizeof(unsigned short));
AIF_FORMAT(a) = strdup(AIF_INTEGER_TYPE(0, sizeof(unsigned short)));
if ( _longest_to_aif(&AIF_DATA(a), sizeof(unsigned short), (AIFLONGEST)i) < 0 )
{
AIFFree(a);
return (AIF *)NULL;
}
return a;
}
/*
* Convert an integer to AIF.
*/
AIF *
IntToAIF(int i)
{
AIF * a;
a = NewAIF(0, sizeof(int));
AIF_FORMAT(a) = strdup(AIF_INTEGER_TYPE(1, sizeof(int)));
if ( _longest_to_aif(&AIF_DATA(a), sizeof(int), (AIFLONGEST)i) < 0 )
{
AIFFree(a);
return (AIF *)NULL;
}
return a;
}
/*
* Convert an unsigned integer to AIF.
*/
AIF *
UnsignedIntToAIF(unsigned int i)
{
AIF * a;
a = NewAIF(0, sizeof(unsigned int));
AIF_FORMAT(a) = strdup(AIF_INTEGER_TYPE(0, sizeof(unsigned int)));
if ( _longest_to_aif(&AIF_DATA(a), sizeof(unsigned int), (AIFLONGEST)i) < 0 )
{
AIFFree(a);
return (AIF *)NULL;
}
return a;
}
/*
* Convert a long integer to AIF.
*/
AIF *
LongToAIF(long i)
{
AIF * a;
a = NewAIF(0, sizeof(long));
AIF_FORMAT(a) = strdup(AIF_INTEGER_TYPE(1, sizeof(long)));
if ( _longest_to_aif(&AIF_DATA(a), sizeof(long), (AIFLONGEST)i) < 0 )
{
AIFFree(a);
return (AIF *)NULL;
}
return a;
}
/*
* Convert an unsigned long to AIF.
*/
AIF *
UnsignedLongToAIF(unsigned long i)
{
AIF * a;
a = NewAIF(0, sizeof(unsigned long));
AIF_FORMAT(a) = strdup(AIF_INTEGER_TYPE(0, sizeof(unsigned long)));
if ( _longest_to_aif(&AIF_DATA(a), sizeof(unsigned long), (AIFLONGEST)i) < 0 )
{
AIFFree(a);
return (AIF *)NULL;
}
return a;
}
#ifdef CC_HAS_LONG_LONG
/*
* Convert a long long integer to AIF.
*/
AIF *
LongLongToAIF(long long i)
{
AIF * a;
a = NewAIF(0, sizeof(long long));
AIF_FORMAT(a) = strdup(AIF_INTEGER_TYPE(1, sizeof(long long)));
if ( _longest_to_aif(&AIF_DATA(a), sizeof(long long), (AIFLONGEST)i) < 0 )
{
AIFFree(a);
return (AIF *)NULL;
}
return a;
}
/*
* Convert an unsigned long long to AIF.
*/
AIF *
UnsignedLongLongToAIF(unsigned long long i)
{
AIF * a;
a = NewAIF(0, sizeof(unsigned long long));
AIF_FORMAT(a) = strdup(AIF_INTEGER_TYPE(0, sizeof(unsigned long long)));
if ( _longest_to_aif(&AIF_DATA(a), sizeof(unsigned long long), (AIFLONGEST)i) < 0 )
{
AIFFree(a);
return (AIF *)NULL;
}
return a;
}
#endif /* CC_HAS_LONG_LONG */
/*
* Convert an integer of any length to AIF.
*/
AIF *
LongestToAIF(AIFLONGEST i)
{
AIF * a;
a = NewAIF(0, sizeof(AIFLONGEST));
AIF_FORMAT(a) = strdup(AIF_INTEGER_TYPE(1, sizeof(AIFLONGEST)));
if ( _longest_to_aif(&AIF_DATA(a), sizeof(AIFLONGEST), i) < 0 )
{
AIFFree(a);
return (AIF *)NULL;
}
return a;
}
/*
* Convert a floating point value of any length to AIF data format.
* Result in rd.
*/
int
_doublest_to_aif(char **rd, int len, AIFDOUBLEST val)
{
union ieee v;
if ( rd == NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
ResetAIFError();
if( *rd == NULL )
*rd = (char *)_aif_alloc(len);
if ( len <= sizeof(float) )
v.f = (float)val;
else if ( len == sizeof(double) )
v.d = (double)val;
else
v.dd = val;
AIFNormalise(*rd, len, v.bytes, len);
return 0;
}
/*
* Convert a single precision floating point value to AIF.
*/
AIF *
FloatToAIF(float f)
{
AIF * a;
a = NewAIF(0, sizeof(float));
AIF_FORMAT(a) = strdup(AIF_FLOATING_TYPE(sizeof(float)));
if ( _doublest_to_aif(&AIF_DATA(a), sizeof(float), (AIFDOUBLEST)f) < 0 )
return (AIF *)NULL;
return a;
}
/*
* Convert a double precision floating point value to AIF.
*/
AIF *
DoubleToAIF(double f)
{
AIF * a;
a = NewAIF(0, sizeof(double));
AIF_FORMAT(a) = strdup(AIF_FLOATING_TYPE(sizeof(double)));
if ( _doublest_to_aif(&AIF_DATA(a), sizeof(double), (AIFDOUBLEST)f) < 0 )
return (AIF *)NULL;
return a;
}
/*
* Convert an array to AIF.
*
* AIF *ArrayToAIF(int rank, int *min, int *size, char *data, int len, char *btype)
*
* - rank is the rank of the array
* - min is the index lower bound, or an array of lower bounds if rank > 1
* - size is the dimension size, or an array of dimension sizes if rank > 1
* - data is a pointer to the array data, or NULL, and must be normalised
* - len is length in bytes of the entire array
* - btype is the type of the array elements
*/
AIF *
ArrayToAIF(int rank, int *min, int *size, char *data, int len, char *btype)
{
int i;
int bsize;
AIF * a;
char * itype; /* index type */
char * rtype; /* range type */
char * fds=NULL;
bsize = FDSTypeSize(btype);
a = NewAIF(0, len);
btype = strdup(btype);
itype = strdup(AIF_INTEGER_TYPE(0, sizeof(int)));
for ( i = rank - 1 ; i >= 0 ; i-- )
{
rtype = strdup(AIF_RANGE_TYPE(min[i], size[i], itype));
fds = strdup(AIF_ARRAY_TYPE(rtype, btype));
_aif_free(rtype);
_aif_free(btype);
btype = fds;
}
assert(fds!=NULL);
AIF_FORMAT(a) = fds;
if ( len > 0 && data != NULL )
memcpy(AIF_DATA(a), data, len);
_aif_free(itype);
ResetAIFError();
return a;
}
/*
* Create an empty array containing elements min..max and
* with a base type given by btype. If size = 0, create
* an array of zero elements.
*/
AIF *
EmptyArrayToAIF(int min, int size, AIF *btype)
{
AIF * a;
int len = 0;
if ((AIF_FORMAT(btype)[0] != FDS_CHAR_POINTER && AIF_FORMAT(btype)[0] != FDS_STRING) && size >= 0) {
len = size * AIFTypeSize(btype);
}
a = NewAIF(0, len);
AIF_FORMAT(a) = FDSArrayInit(min, size, AIF_FORMAT(btype));
ResetAIFError();
return a;
}
/*
* Add the element el to the array at the index given by idx.
* This is used for array construction.
*/
void
AIFAddArrayElement(AIF *a, int idx, AIF *el)
{
int min;
int size;
int len = AIFTypeSize(el);
if (AIF_FORMAT(el)[0] == FDS_CHAR_POINTER || AIF_FORMAT(el)[0] == FDS_STRING) {
AIFAddComplexArrayElement(a, el);
} else {
min = FDSArrayMinIndex(AIF_FORMAT(a), 0);
size = FDSArrayRankSize(AIF_FORMAT(a), 0);
if (idx < min || idx >= min + size) {
return;
}
memcpy(AIF_DATA(a) + len * (idx - min), AIF_DATA(el), len);
}
}
AIF *
EmptyComplexArrayToAIF(int min, int max, AIF *btype)
{
AIF * a;
a = NewAIF(0, 0);
AIF_FORMAT(a) = FDSArrayInit(min, max, AIF_FORMAT(btype));
ResetAIFError();
return a;
}
void
AIFAddComplexArrayElement(AIF *a, AIF *el)
{
char *newData;
int len = AIFTypeSize(el);
int cap = AIFTypeSize(a);
AIF_LEN(a) += len;
newData = _aif_alloc(AIF_LEN(a));
memcpy(newData, AIF_DATA(a), cap);
memcpy(newData+cap, AIF_DATA(el), len);
if (AIF_DATA(a))
_aif_free(AIF_DATA(a));
AIF_DATA(a) = _aif_alloc(AIF_LEN(a));
memcpy(AIF_DATA(a), newData, AIF_LEN(a));
_aif_free(newData);
}
/*
* Create an empty AIF enumerated type.
*/
AIF *
EmptyEnumToAIF(char *id)
{
AIF * a;
a = NewAIF(0, sizeof(int));
AIF_FORMAT(a) = FDSEnumInit(id);
ResetAIFError();
return(a);
}
/*
* Add a constant to enumerated type.
*/
int
AIFAddConstToEnum(AIF *a, char *id, AIF *content)
{
char *nfmt;
int val;
if ( AIFToInt(content, &val) < 0 )
return -1;
nfmt = FDSAddConstToEnum(AIF_FORMAT(a), id, val);
if ( nfmt == NULL )
{
return -1;
}
else
{
_aif_free(AIF_FORMAT(a));
AIF_FORMAT(a) = nfmt;
return 0;
}
}
/*
* Set AIF enum type to a particular value.
*/
int
AIFSetEnum(AIF *a, char *id)
{
int v;
if ( FDSEnumConstByName(AIF_FORMAT(a), id, &v) < 0 )
{
SetAIFError(AIFERR_FIELD, NULL);
return -1;
}
if ( _longest_to_aif(&AIF_DATA(a), sizeof(int), (AIFLONGEST)v) < 0 )
{
AIFFree(a);
return -1;
}
return 0;
}
/*
* Get current value of enum.
*/
AIF *
AIFGetEnum(AIF *a)
{
AIF * new;
char * btype;
int len;
if ( (btype = FDSBaseType(AIF_FORMAT(a))) == NULL )
return NULL;
if ( (len = FDSTypeSize(AIF_FORMAT(a))) < 0 )
return NULL;
new = NewAIF(0, len);
AIF_FORMAT(new) = strdup(btype);
AIF_LEN(new) = len;
memcpy(AIF_DATA(new), AIF_DATA(a), len);
return new;
}
/*
* Create an empty AIF union type. A union contains
* all the values in the same way as a struct, since the
* data is not simply a sequence of bytes but is structured
* in AIF.
*/
AIF *
EmptyUnionToAIF(char *id)
{
AIF * a;
a = NewAIF(0, 0);
AIF_FORMAT(a) = FDSUnionInit(id);
ResetAIFError();
return(a);
}
/*
* Add a field to an AIF union.
*/
int
AIFAddFieldToUnion(AIF *a, char *field, AIF *content)
{
int data_len;
int old_len;
int new_len;
char * new_fmt;
char * new_data;
char * dummy;
if ( !FDSUnionFieldByName(AIF_FORMAT(a), field, &dummy) )
{
_aif_free(dummy);
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
data_len = FDSDataSize(AIF_FORMAT(a), AIF_DATA(a));
old_len = AIF_LEN(a);
new_len = old_len + AIF_LEN(content);
new_data = _aif_alloc(new_len);
if (data_len > 0) {
memcpy(new_data, AIF_DATA(a), data_len);
}
memcpy(new_data+data_len, AIF_DATA(content), AIF_LEN(content));
memcpy(new_data+data_len + AIF_LEN(content), AIF_DATA(a) + data_len, old_len - data_len);
if ( AIF_DATA(a) ) {
_aif_free(AIF_DATA(a));
}
AIF_DATA(a) = _aif_alloc(new_len);
AIF_LEN(a) = new_len;
memcpy(AIF_DATA(a), new_data, new_len);
new_fmt = FDSAddFieldToUnion(AIF_FORMAT(a), field, AIF_FORMAT(content));
_aif_free(AIF_FORMAT(a));
AIF_FORMAT(a) = new_fmt;
_aif_free(new_data);
ResetAIFError();
return 0;
}
/*
* Set the value of a union.
*/
int
AIFSetUnion(AIF *a, char *field, AIF *data)
{
SetAIFError(AIFERR_NOTIMP, NULL);
return -1;
}
/*
* Get the value of a union.
*/
AIF *
AIFGetUnion(AIF *a, char *field)
{
AIF * new;
char * type;
int len;
if ( FDSUnionFieldByName(AIF_FORMAT(a), field, &type) < 0 )
{
SetAIFError(AIFERR_FIELD, NULL);
return NULL;
}
if ( (len = FDSTypeSize(type)) < 0 )
return NULL;
new = NewAIF(0, len);
AIF_FORMAT(new) = type;
AIF_LEN(new) = len;
memcpy(AIF_DATA(new), AIF_DATA(a), len);
return new;
}
/*
* Convert an AIF value to a native character.
*/
int
_aif_to_char(char *data, char *val)
{
int s;
if ( data == NULL || val == (char *)NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
ResetAIFError();
for ( s = 0 ; s < sizeof(char) ; s++ )
val[s] = data[s];
return 0;
}
/*
* Convert an AIF integer to the longest integer available.
*/
int
_aif_to_longest(char *data, int len, AIFLONGEST *val)
{
int s;
AIFLONGEST i = 0;
if ( data == NULL || val == (AIFLONGEST *)NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
if ( len > sizeof(AIFLONGEST) )
{
SetAIFError(AIFERR_CONV, NULL);
return -1;
}
ResetAIFError();
for ( s = 0 ; s < len ; s++ )
i = i * 0x100 + (data[s] & 0xff);
*val = i;
return 0;
}
/*
* Convert AIF integer to native integer. If native integer
* size is too small, return low order bytes.
*/
int
AIFToInt(AIF *a, int *val)
{
AIFLONGEST l;
if ( AIFToLongest(a, &l) < 0 )
return -1;
*val = l;
return 0;
}
/*
* Convert AIF value to longest integer available. Implicitly converts
* an floating value to an integer.
*/
int
AIFToLongest(AIF *a, AIFLONGEST *val)
{
int res = 0;
AIFDOUBLEST d;
if ( a == (AIF *)NULL || val == (AIFLONGEST *)NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
switch ( FDSType(AIF_FORMAT(a)) )
{
case AIF_INTEGER:
res = _aif_to_longest(AIF_DATA(a), AIF_LEN(a), val);
break;
case AIF_FLOATING:
if ( _aif_to_doublest(AIF_DATA(a), AIF_LEN(a), &d) < 0 )
return -1;
*val = (AIFLONGEST)d;
res = 0;
break;
default:
SetAIFError(AIFERR_TYPE, NULL);
return -1;
}
return res;
}
/*
* Convert an AIF floating data type to the largest native
* floating poing representation available.
*/
int
_aif_to_doublest(char *data, int len, AIFDOUBLEST *val)
{
union ieee f;
if ( data == NULL || val == (AIFDOUBLEST *)NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
ResetAIFError();
AIFNormalise(f.bytes, len, data, len);
if ( len == sizeof(float) )
*val = (AIFDOUBLEST)f.f;
else if ( len == sizeof(double) )
*val = (AIFDOUBLEST)f.d;
else if ( len == sizeof(AIFDOUBLEST) )
*val = f.dd;
else {
fprintf(stderr, "conversion to float: %d does not match any native precision\n", len);
*val = 0;
SetAIFError(AIFERR_CONV, NULL);
return -1;
}
return 0;
}
/*
* Convert an AIF float to a native single precision floating point value.
*/
int
AIFToFloat(AIF *a, float *val)
{
int res;
AIFDOUBLEST dd;
if ( a == (AIF *)NULL || val == (float *)NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
switch ( FDSType(AIF_FORMAT(a)) )
{
case AIF_INTEGER:
res = _aif_int_to_doublest(AIF_DATA(a), AIF_LEN(a), &dd);
break;
case AIF_FLOATING:
res = _aif_to_doublest(AIF_DATA(a), AIF_LEN(a), &dd);
break;
default:
SetAIFError(AIFERR_TYPE, NULL);
return -1;
}
if ( res < 0 )
return -1;
*val = (float)dd; /* possible loss of precision */
return 0;
}
/*
* Convert an AIF float to a native double precision floating point value.
*/
int
AIFToDouble(AIF *a, double *val)
{
AIFDOUBLEST d;
if ( a == (AIF *)NULL || val == (double *)NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
if ( AIFToDoublest(a, &d) < 0 )
return -1;
*val = (double)d; /* possible loss of precision */
return 0;
}
/*
* Convert an AIF value to a native floating point value using the
* largest precision available. Implicitly converts an integer to
* a float.
*/
int
AIFToDoublest(AIF *a, AIFDOUBLEST *val)
{
int res;
if ( a == (AIF *)NULL || val == (AIFDOUBLEST *)NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
switch ( FDSType(AIF_FORMAT(a)) )
{
case AIF_INTEGER:
res = _aif_int_to_doublest(AIF_DATA(a), AIF_LEN(a), val);
break;
case AIF_FLOATING:
res = _aif_to_doublest(AIF_DATA(a), AIF_LEN(a), val);
break;
default:
SetAIFError(AIFERR_TYPE, NULL);
return -1;
}
return res;
}
/*
* Convert an AIF integer to and AIF float using largest precision
* available.
*/
int
_aif_int_to_doublest(char *data, int len, AIFDOUBLEST *val)
{
AIFLONGEST l;
if ( _aif_to_longest(data, len, &l) < 0 )
return -1;
*val = (AIFDOUBLEST)l;
return 0;
}
/*
* Convert AIF integer to AIF float. Result is always a do.
*/
int
_aif_int_to_aif_float(char **rf, char **rd, int *rl, char *d, int l)
{
AIFDOUBLEST vd;
_aif_int_to_doublest(d, l, &vd);
if ( _doublest_to_aif(rd, sizeof(double), vd) < 0 )
return -1;
*rf = strdup(AIF_FLOATING_TYPE(sizeof(double)));
*rl = sizeof(double);
return 0;
}
/*
* Convert AIF float to AIF integer. Result is always is4 (for convenience).
*/
int
_aif_float_to_aif_int(char **rf, char **rd, int *rl, char *d, int l)
{
int vi;
AIFDOUBLEST vd;
_aif_to_doublest(d, l, &vd);
vi = (int)vd;
if ( _longest_to_aif(rd, sizeof(int), vi) < 0 )
return -1;
*rf = strdup(AIF_INTEGER_TYPE(FDS_INTEGER_SIGNED, sizeof(int)));
*rl = sizeof(int);
return 0;
}
/*
* Convert number to ascii.
*/
char
ToAscii(int n, int base)
{
if ( base < 10 || n < 10 )
return (n & 0xf) + '0';
return (n & 0xf) - 10 + 'a';
}
/*
* Create a void AIF object.
*/
AIF *
VoidToAIF(char *data, int len)
{
AIF * a;
a = NewAIF(0, len);
AIF_FORMAT(a) = strdup(AIF_VOID_TYPE(len));
if ( data != NULL && len > 0 )
memcpy(AIF_DATA(a), data, len);
return a;
}
/*
* Convert an AIF void object to its native representation.
*/
int
AIFToVoid(AIF *a, char *data, int len)
{
int size;
if ( data == NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
ResetAIFError();
if ( len > 0 )
{
size = FDSTypeSize(AIF_FORMAT(a));
memcpy(data, AIF_DATA(a), size > len ? size : len);
}
return 0;
}
/*
* Coerce an AIF object into type t if possible.
*/
AIF *
AIFCoerce(AIF *a, char *t)
{
int rl;
int tlen;
int alen;
int atype;
AIFDOUBLEST dval;
char * rd = NULL;
char * rf;
AIF * na;
ResetAIFError();
tlen = FDSTypeSize(t);
alen = AIF_LEN(a);
switch ( FDSType(t) )
{
case AIF_INTEGER:
switch ( FDSType(AIF_FORMAT(a)) )
{
case AIF_INTEGER:
if ( tlen > alen )
{
rd = (char *)_aif_alloc(tlen);
memcpy(rd, AIF_DATA(a), tlen);
return _make_aif(strdup(t), rd, tlen);
}
else if ( tlen < alen )
{
SetAIFError(AIFERR_TYPE, NULL);
return (AIF *)NULL;
}
return CopyAIF(a);
case AIF_FLOATING:
if ( _aif_float_to_aif_int(&rf, &rd, &rl, AIF_DATA(a), alen) < 0 )
return (AIF *)NULL;
return _make_aif(rf, rd, rl);
default:
SetAIFError(AIFERR_TYPE, NULL);
return (AIF *)NULL;
}
break;
case AIF_FLOATING:
switch ( atype = AIFType(a) )
{
case AIF_INTEGER:
case AIF_FLOATING:
if ( atype == AIF_INTEGER )
{
/*
** Convert integer to double.
*/
if ( _aif_int_to_doublest(AIF_DATA(a), AIF_LEN(a), &dval) < 0 )
return (AIF *)NULL;
alen = sizeof(AIFDOUBLEST);
}
else
{
/*
** Convert AIF float to double
*/
if ( _aif_to_doublest(AIF_DATA(a), AIF_LEN(a), &dval) < 0 )
return (AIF *)NULL;
}
na = NewAIF(0, tlen);
AIF_FORMAT(na) = strdup(AIF_FLOATING_TYPE(tlen));
/*
** Now take care of floating precision
*/
if ( _doublest_to_aif(&AIF_DATA(na), tlen, dval) < 0 )
return (AIF *)NULL;
return na;
default:
SetAIFError(AIFERR_TYPE, NULL);
return (AIF *)NULL;
}
break;
default:
SetAIFError(AIFERR_TYPE, NULL);
return (AIF *)NULL;
}
return na;
}
/*
* build an AIF from two ascii strings.
*/
AIF *
AsciiToAIF(char *format, char *data)
{
int flen = strlen(format);
int dlen = strlen(data);
long acc;
AIF * a;
char * bdata;
char * bdp;
char * dp;
char buf[2];
ResetAIFError();
if ( dlen % 2 != 0 )
{
SetAIFError(AIFERR_BADARG, NULL);
return (AIF *)NULL;
}
bdata = (char *) _aif_alloc(dlen/2);
bdp = bdata;
buf[1] = 0;
dp = data;
/*
** convert two chars of data to one byte of bdata
*/
while ( *dp )
{
buf[0] = *dp++;
acc = strtol(buf, 0, 16) << 4;
buf[0] = *dp++;
acc += strtol(buf, 0, 16);
*bdp++ = (char) (acc & 0xff);
}
a = NewAIF(flen + 1, dlen/2);
memcpy(AIF_DATA(a), bdata, AIF_LEN(a));
memcpy(AIF_FORMAT(a), format, flen);
_aif_free(bdata);
return a;
}
/************************************
* *
* AIFToStr()-related functions *
* *
************************************/
void
_str_init()
{
if ( _str_buf_len == 0 )
{
_str_buf = _aif_alloc(BUFSIZ);
_str_buf_len = BUFSIZ;
}
_str_pos = _str_buf;
}
void
_str_cat(char *str)
{
int len = strlen(str);
while ( _str_pos + len + 1 > _str_buf + _str_buf_len )
{
int offset = _str_pos - _str_buf;
_str_buf_len += BUFSIZ;
_str_buf = _aif_resize(_str_buf, _str_buf_len);
_str_pos = _str_buf + offset;
}
memcpy(_str_pos, str, len);
_str_pos += len;
*_str_pos = '\0';
}
void
_str_add(char ch)
{
while ( _str_pos + 2 > _str_buf + _str_buf_len )
{
int offset = _str_pos - _str_buf;
_str_buf_len += BUFSIZ;
_str_buf = _aif_resize(_str_buf, _str_buf_len);
_str_pos = _str_buf + offset;
}
*_str_pos++ = ch;
*_str_pos = '\0';
}
char *
_str_get(void)
{
return strdup(_str_buf);
}
int
_aif_bool_to_str(int depth, char **fds, char **data)
{
int bytes = FDSTypeSize(*fds);
AIFLONGEST lli;
char buf[BUFSIZ];
(*fds)++;
if ( _aif_to_longest(*data, bytes, &lli) < 0 )
return -1;
if ( lli == 0 )
snprintf(buf, BUFSIZ-1, "false");
else
snprintf(buf, BUFSIZ-1, "true");
_str_cat(buf);
*data += bytes;
return 0;
}
int
AIFBoolToStr(char **str, int depth, AIF *a)
{
char * fmt;
char * data;
if ( a == (AIF *)NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
fmt = AIF_FORMAT(a);
data = AIF_DATA(a);
_str_init();
if ( _aif_bool_to_str(depth, &fmt, &data) < 0 )
return -1;
*str = _str_get();
return 0;
}
int
_aif_char_to_str(int depth, char **fds, char **data)
{
char c;
char buf[BUFSIZ];
(*fds)++;
if ( _aif_to_char(*data, &c) < 0 )
return -1;
if ( c >= ' ' && c <= '~' )
snprintf(buf, BUFSIZ-1, "%d '%c'", c, c);
else
snprintf(buf, BUFSIZ-1, "%d '\\%03o'", c & 0xff, c & 0xff);
_str_cat(buf);
*data += sizeof(char);
return 0;
}
int
_aif_int_to_str(int depth, char **fds, char **data)
{
int bytes = FDSTypeSize(*fds);
int isSigned = FDSIsSigned(*fds);
int i;
AIFLONGEST lli;
char buf[BUFSIZ];
*fds += 2;
*fds = _fds_skipnum(*fds);
if ( _aif_to_longest(*data, bytes, &lli) < 0 )
return -1;
if ( bytes <= sizeof(int) )
{
i = (int)lli;
snprintf(buf, BUFSIZ-1, isSigned ? "%d" : "%u", i);
}
else if ( bytes == sizeof(long) )
{
#ifdef CC_HAS_LONG_LONG
long li;
li = (long)lli;
snprintf(buf, BUFSIZ-1, isSigned ? "%ld" : "%lu" , li);
#else /* CC_HAS_LONG_LONG */
snprintf(buf, BUFSIZ-1, isSigned ? "%ld" : "%lu" , lli);
#endif /* CC_HAS_LONG_LONG */
}
else
{
#ifdef CC_HAS_LONG_LONG
#ifdef WIN32
snprintf(buf, BUFSIZ-1, isSigned ? "%I64d" : "%I64u" , lli);
#else /* WIN32 */
snprintf(buf, BUFSIZ-1, isSigned ? "%lld" : "%llu" , lli);
#endif /* WIN32 */
#else /* CC_HAS_LONG_LONG */
snprintf(buf, BUFSIZ-1, isSigned ? "%ld" : "%lu" , lli);
#endif /* CC_HAS_LONG_LONG */
}
_str_cat(buf);
if ( bytes > sizeof(AIFLONGEST) )
{
snprintf(buf, BUFSIZ-1, "<truncated from %d bytes>", bytes);
_str_cat(buf);
}
*data += bytes;
return 0;
}
int
AIFIntToStr(char **str, int depth, AIF *a)
{
char * fmt;
char * data;
if ( a == (AIF *)NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
fmt = AIF_FORMAT(a);
data = AIF_DATA(a);
_str_init();
if ( _aif_int_to_str(depth, &fmt, &data) < 0 )
return -1;
*str = _str_get();
return 0;
}
int
_aif_float_to_str(int depth, char **fds, char **data)
{
AIFDOUBLEST d;
int bytes = FDSTypeSize(*fds);
char buf[BUFSIZ];
*fds += 1;
*fds = _fds_skipnum(*fds);
if ( _aif_to_doublest(*data, bytes, &d) < 0 )
return -1;
if ( bytes <= sizeof(float) )
#ifdef HAVE_LONG_DOUBLE
snprintf(buf, BUFSIZ-1, "%.8Lg", d);
#else /* HAVE_LONG_DOUBLE */
snprintf(buf, BUFSIZ-1, "%.8g", (float)d);
#endif /* HAVE_LONG_DOUBLE */
else if ( bytes == sizeof(double) )
#ifdef HAVE_LONG_DOUBLE
snprintf(buf, BUFSIZ-1, "%.16Lg", d);
else
snprintf(buf, BUFSIZ-1, "%.34Lg", d);
#else /* HAVE_LONG_DOUBLE */
snprintf(buf, BUFSIZ-1, "%.16lg", (double)d);
#endif /* HAVE_LONG_DOUBLE */
_str_cat(buf);
*data += bytes;
return 0;
}
int
AIFFloatToStr(char **str, int depth, AIF *a)
{
char * fmt;
char * data;
if ( a == (AIF *)NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
fmt = AIF_FORMAT(a);
data = AIF_DATA(a);
_str_init();
if ( _aif_float_to_str(depth, &fmt, &data) < 0 )
return -1;
*str = _str_get();
return 0;
}
int
_aif_pointer_to_str(int depth, char **fds, char **data)
{
int index;
char buf[BUFSIZ];
_str_cat("^");
switch ( _get_pointer_type(*data) )
{
case AIF_PTR_NIL: /* nil value */
if ( depth == 1 )
depth = -1;
else if ( depth > 1 )
depth--;
_str_cat("null");
_fds_skip_data(fds, data);
break;
case AIF_PTR_NORMAL: /* normal value */
if ( depth == -1 )
{
_str_cat("<normal>");
_fds_skip_data(fds, data);
break;
}
else if ( depth == 1 )
depth = -1;
else if ( depth > 1 )
depth--;
_find_target(fds, data, 0);
_aif_to_str(depth, fds, data);
break;
case AIF_PTR_NAME: /* normal value, but remember it */
index = _get_pointer_name(*data);
_find_target(fds, data, 0);
_aif_values_seen[index] = *data;
snprintf(buf, BUFSIZ-1, "<%d:>", index);
_str_cat(buf);
if ( depth == -1 )
{
_fds_skip_data(fds, data);
break;
}
else if ( depth == 1 )
depth = -1;
else if ( depth > 1 )
depth--;
_aif_to_str(depth, fds, data);
break;
case AIF_PTR_REFERENCE: /* reference to remembered value */
if ( depth == 1 )
{
char * target;
depth = -1;
_find_target(fds, data, 0);
_aif_to_str(depth, fds, &target);
}
else if ( depth > 1 )
{
char * target;
depth--;
_find_target(fds, data, 0);
_aif_to_str(depth, fds, &target);
}
else
{
index = _get_pointer_name(*data);
snprintf(buf, BUFSIZ-1, "<=%d>", index);
_str_cat(buf);
_fds_skip_data(fds, data);
}
break;
case AIF_PTR_INVALID: /* pointer is invalid */
_str_cat("<invalid>");
_fds_skip_data(fds, data);
break;
}
return 0;
}
int
AIFPointerToStr(char **str, int depth, AIF *a)
{
char * fmt;
char * data;
if ( a == (AIF *)NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
fmt = AIF_FORMAT(a);
data = AIF_DATA(a);
_str_init();
if ( _aif_pointer_to_str(depth, &fmt, &data) )
return -1;
*str = _str_get();
return 0;
}
int
_aif_region_to_str(int depth, char **fds, char **data)
{
int i;
int rank;
int size;
AIFLONGEST min;
AIFLONGEST max;
char buf[BUFSIZ];
rank = _fds_getnum(*fds + 1);
size = FDSTypeSize(FDSBaseType(*fds));
_str_cat("[");
for ( i = 0 ; i < rank ; i++ )
{
if ( i != 0 && rank > 1 )
_str_cat(", ");
if
(
_aif_to_longest(*data + 2 * i * size, size, &min) < 0
||
_aif_to_longest(*data + (2 * i + 1) * size, size, &max) < 0
)
return -1;
#ifdef CC_HAS_LONG_LONG
snprintf(buf, BUFSIZ-1, "%lld..%lld", min, max);
#else /* CC_HAS_LONG_LONG */
snprintf(buf, BUFSIZ-1, "%ld..%ld", min, max);
#endif /* CC_HAS_LONG_LONG */
_str_cat(buf);
}
_str_cat("]");
_fds_advance(fds);
return 0;
}
int
_aif_array_to_str(int depth, char **fds, char **data)
{
int i;
AIFIndex * ix;
char * fmt;
ix = FDSArrayIndexInit(*fds);
_str_cat("[");
for ( i = 0 ; i < ix->i_nel ; i++ )
{
fmt = ix->i_btype;
/*
if ( ix->i_rank == 1 )
snprintf(_str_buf, BUFSIZ-1, "(%d)", i + ix->i_min[0]);
*/
_aif_to_str(depth, &fmt, data);
if ( i < ix->i_nel - 1 )
_str_cat(", ");
}
_str_cat("]");
AIFArrayIndexFree(ix);
_fds_advance(fds); /* skip over entire array descriptor */
return 0;
}
int
AIFArrayToStr(char **str, int depth, AIF *a)
{
char * fmt;
char * data;
if ( a == (AIF *)NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
if ( AIFType(a) != AIF_ARRAY )
{
SetAIFError(AIFERR_TYPE, NULL);
return -1;
}
fmt = AIF_FORMAT(a);
data = AIF_DATA(a);
_str_init();
if ( _aif_array_to_str(depth, &fmt, &data) < 0 )
return -1;
*str = _str_get();
return 0;
}
int
AIFArrayIndexToStr(char **str, AIFIndex *ix)
{
int i;
char buf[BUFSIZ];
_str_init();
for ( i = 0 ; i < ix->i_rank ; i++ )
{
snprintf(buf, BUFSIZ-1, "[%d]", ix->i_index[i]);
_str_cat(buf);
}
*str = _str_get();
return 0;
}
int
_aif_aggregate_to_str(int depth, char **fds, char **data)
{
char * inFds;
char buf[BUFSIZ];
int isStruct = 1; /* assume it is a struct */
/* to avoid printing the semicolons if
it is a struct */
_str_cat("{");
(*fds)++; /* past open brace */
/*
** past nnn=
*/
_fds_skip_typename(fds);
while ( **fds != FDS_AGGREGATE_END )
{
if ( isStruct && (*fds)[0] == FDS_AGGREGATE_ACCESS_SEP
&& (*fds)[1] == FDS_AGGREGATE_ACCESS_SEP
&& (*fds)[2] == FDS_AGGREGATE_ACCESS_SEP )
{
(*fds) += 3;
break;
}
if ( **fds == FDS_AGGREGATE_ACCESS_SEP )
{
isStruct = 0; /* it is a class */
(*fds)++;
_str_cat("; ");
continue;
}
if ( (inFds = strchr(*fds, FDS_AGGREGATE_FIELD_NAME_END)) == NULL )
break;
*inFds = 0; /* temporarily */
snprintf(buf, BUFSIZ-1, "%s = ", *fds);
_str_cat(buf);
*inFds++ = FDS_AGGREGATE_FIELD_NAME_END;
*fds = inFds; /* to start of field */
_aif_to_str(depth, fds, data);
if ( **fds == FDS_AGGREGATE_FIELD_SEP )
{
(*fds)++;
_str_cat(", ");
}
}
_str_cat("}");
(*fds)++; /* past close brace */
return 0;
}
int
AIFAggregateToStr(char **str, int depth, AIF *a)
{
char * fmt;
char * data;
if ( a == (AIF *)NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
fmt = AIF_FORMAT(a);
data = AIF_DATA(a);
_str_init();
if ( _aif_aggregate_to_str(depth, &fmt, &data) < 0 )
return -1;
*str = _str_get();
return 0;
}
int
_aif_reference_to_str(int depth, char **fds, char **data)
{
int index;
char * effectiveFds;
(*fds)++; /* past ">" */
index = (int)strtol(*fds, NULL, 10);
*fds = _fds_skipnum(*fds); /* past name */
(*fds)++; /* past "/" */
effectiveFds = _aif_types_seen[index];
_aif_to_str(depth, &effectiveFds, data);
return 0;
}
int
AIFReferenceToStr(char **str, int depth, AIF *a)
{
char * fmt;
char * data;
if ( a == (AIF *)NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
fmt = AIF_FORMAT(a);
data = AIF_DATA(a);
_str_init();
if ( _aif_reference_to_str(depth, &fmt, &data) < 0 )
return -1;
*str = _str_get();
return 0;
}
int
_aif_string_to_str(int depth, char **fds, char **data)
{
int bytes;
char * buf;
(*fds)++; /* past "s" */
bytes = (*(*data)++ & 0xff) << 8;
bytes += *(*data)++ & 0xff;
buf = _aif_alloc(bytes+3);
*buf = '"';
strncpy(&buf[1], *data, bytes);
*(buf + bytes + 1) = '"';
*(buf + bytes + 2) = 0; /* terminator */
_str_cat(buf);
*data += bytes;
_aif_free(buf);
return 0;
}
int
_aif_void_to_str(int depth, char **fds, char **data)
{
int bytes = FDSTypeSize(*fds);
*fds += 1; /* past "v" */
*fds = _fds_skipnum(*fds);
*data += bytes;
_str_cat("VOID");
return 0;
}
int
AIFVoidToStr(char **str, int depth, AIF *a)
{
char * fmt;
char * data;
if ( a == (AIF *)NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
fmt = AIF_FORMAT(a);
data = AIF_DATA(a);
_str_init();
if ( _aif_void_to_str(depth, &fmt, &data) < 0 )
return -1;
*str = _str_get();
return 0;
}
int
_aif_union_to_str(int depth, char **fds, char **data)
{
char * inFds;
char * temp;
char * dt;
int size;
int union_size;
char buf[BUFSIZ];
_str_cat("{");
union_size = FDSTypeSize(*fds);
(*fds)++; /* past open brace */
/*
** past nnn=
*/
_fds_skip_typename(fds);
while ( **fds != FDS_UNION_END )
{
if ( (inFds = strchr(*fds, FDS_UNION_FIELD_NAME_END)) == NULL )
break;
*inFds = 0; /* temporarily */
snprintf(buf, BUFSIZ-1, "%s = ", *fds);
_str_cat(buf);
*inFds++ = FDS_UNION_FIELD_NAME_END;
*fds = inFds; /* to start of field */
size = FDSTypeSize(*fds);
temp = _aif_alloc( sizeof(char) * size );
dt = temp;
memcpy(dt, *data, size);
_aif_to_str(depth, fds, &dt);
_aif_free(temp);
if ( **fds == FDS_UNION_FIELD_SEP )
{
(*fds)++;
_str_cat(", ");
}
}
_str_cat("}");
*data += union_size;
(*fds)++; /* past close brace */
return 0;
}
int
AIFUnionToStr(char **str, int depth, AIF *a)
{
char * fmt;
char * data;
if ( a == (AIF *)NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
fmt = AIF_FORMAT(a);
data = AIF_DATA(a);
_str_init();
if ( _aif_union_to_str(depth, &fmt, &data) < 0 )
return -1;
*str = _str_get();
return 0;
}
int
_aif_function_to_str(int depth, char **fds, char **data)
{
char * p;
char end[2] = {FDS_FUNCTION_ARG_END, 0};
(*fds)++; /* past "&" */
p = _fds_skipto(*fds, end);
_str_cat(++p);
_str_cat(" ");
_str_cat(*data);
_str_cat("(");
while ( **fds != FDS_FUNCTION_ARG_END )
{
if ( **fds == FDS_UNION_FIELD_SEP )
_str_cat(", ");
else
_str_add(**fds);
(*fds)++;
}
_str_cat(")");
(*fds)++; /* past arg end */
_fds_advance(fds);
_fds_skip_data(fds, data);
return 0;
}
int
AIFFunctionToStr(char **str, int depth, AIF *a)
{
char * fmt;
char * data;
if ( a == (AIF *)NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
fmt = AIF_FORMAT(a);
data = AIF_DATA(a);
_str_init();
if ( _aif_function_to_str(depth, &fmt, &data) < 0 )
return -1;
*str = _str_get();
return 0;
}
int
_aif_enum_to_str(int depth, char **fds, char **data)
{
int bytes = FDSTypeSize(*fds);
AIFLONGEST lli;
int i;
char * string = NULL;
/* check whether it is an empty enum or not */
char * f = *fds;
while ( *f != FDS_TYPENAME_END )
f++;
f++;
if ( *f == FDS_ENUM_END )
{ /* it is an empty enum */
_str_cat("0");
*data += bytes;
_fds_advance(fds);
return 0;
}
if ( _aif_to_longest(*data, bytes, &lli) < 0 )
return -1;
i = (int) lli;
if ( FDSEnumConstByValue(*fds, &string, i) < 0)
return -1;
_str_cat(string);
_aif_free(string);
*data += bytes;
_fds_advance(fds);
return 0;
}
int
AIFEnumToStr(char **str, int depth, AIF *a)
{
char * fmt;
char * data;
if ( a == (AIF *)NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
fmt = AIF_FORMAT(a);
data = AIF_DATA(a);
_str_init();
if ( _aif_enum_to_str(depth, &fmt, &data) < 0 )
return -1;
*str = _str_get();
return 0;
}
int
_aif_name_to_str(int depth, char **fds, char **data)
{
int index;
(*fds)++; /* past "%" */
index = (int)strtol(*fds, NULL, 10);
*fds = _fds_skipnum(*fds); /* past name */
(*fds)++; /* past "/" */
_aif_types_seen[index] = *fds;
return _aif_to_str(depth, fds, data);
}
/*
* Prints the object in human-readable form to fp, advances fds and data to
* the first location after the part printed. Arithmetic values are given at
* least len bytes of significance, more if the fds indicates.
*/
int
_aif_to_str(int depth, char **fds, char **data)
{
char * tmp;
_fds_resolve(fds);
switch ( FDSType(*fds) )
{
case AIF_BOOLEAN:
return _aif_bool_to_str(depth, fds, data);
case AIF_CHARACTER:
return _aif_char_to_str(depth, fds, data);
case AIF_INTEGER:
return _aif_int_to_str(depth, fds, data);
case AIF_FLOATING:
return _aif_float_to_str(depth, fds, data);
case AIF_ARRAY:
return _aif_array_to_str(depth, fds, data);
case AIF_POINTER:
return _aif_pointer_to_str(depth, fds, data);
case AIF_REGION:
return _aif_region_to_str(depth, fds, data);
case AIF_AGGREGATE:
return _aif_aggregate_to_str(depth, fds, data);
case AIF_NAME:
return _aif_name_to_str(depth, fds, data);
case AIF_REFERENCE:
tmp = _fds_lookup(fds);
return _aif_to_str(depth, &tmp, data);
case AIF_STRING:
return _aif_string_to_str(depth, fds, data);
case AIF_ENUM:
return _aif_enum_to_str(depth, fds, data);
case AIF_UNION:
return _aif_union_to_str(depth, fds, data);
case AIF_VOID:
return _aif_void_to_str(depth, fds, data);
case AIF_FUNCTION:
return _aif_function_to_str(depth, fds, data);
default:
SetAIFError(AIFERR_TYPE, NULL);
break;
}
return -1;
}
int
AIFToStr(char **str, int depth, AIF *a)
{
char * fmt;
char * data;
if ( a == (AIF *)NULL )
{
SetAIFError(AIFERR_BADARG, NULL);
return -1;
}
fmt = AIF_FORMAT(a);
data = AIF_DATA(a);
_str_init();
if ( _aif_to_str(depth, &fmt, &data) < 0 )
return -1;
*str = _str_get();
return 0;
}
/*
* Convert a pointer name into an int (4 bytes). Advances data to
* the end of the name.
*/
void
_ptrname_to_int(char **data, int *number)
{
int s;
int i = 0;
for ( s = 0 ; s < 4 ; s++ )
i = i * 0x100 + (*(*data)++ & 0xff);
*number = i;
}
/*
* Convert an int (4 bytes) into a string for the pointer name
*/
void
_int_to_ptrname(int number, char *data)
{
union ieee f;
f.i = number;
_aif_normalise(data, 4, f.bytes, 4);
}