| /* |
| * 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); |
| } |
| |