💾 Archived View for mirrors.apple2.org.za › archive › apple2.caltech.edu › source › portable.h captured on 2024-05-10 at 11:57:26.
⬅️ Previous capture (2023-01-29)
-=-=-=-=-=-=-
/********************************************************************** * * Name: * * Portable.h * * Copyright (C) 1990-1991 by Bruce Kahn & Greg Hunt * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation. This software is provided "as is" without express or * implied warranty. * * Description: * * Supported Hardware Platforms: * * Data General ECLIPSE Family * Intel 8086/80286/80386(/80486?) Family * Motorola 68000 Family (Macintosh, etc) * Motorola 88000 Family (Data General AViiON Family, etc) * IBM RX000 Family (R6000, etc) * Intel(?) 6502 Family (Apple II/II+/IIe/IIc) * Western Digital 65816 Family (Apple IIGS) * * Supported Operating Systems: * * Data General DG/UX (for the AViiON Family) * Data General AOS/VS (I & II) (for the ECLIPSE Family) * PC-DOS/MS-DOS (2.x, 3.x, or 4.x for the Intel Family) * System 6.0.x (for the Macintosh Family) * Unknow for sure (on the IBM RX000 Family) * ProDOS 8 (for the entire Apple II Family) * ProDOS 16 (for the Apple IIGS Family) * * Supported Compilers: * * GNU C (1.37 or greater) * GreenHill C (for the 88000, revision unknown) * MPW C (2.0.2 or greater) * Think C (3.0 or greater) * AOS/VS C (4.01 or greater) * MicroTek MCC68K (for the ECLIPSE, revision unknown) * MicroSoft C (5.1 or greater, maybe 5.0) * Quick C (2.0 or greater) * Turbo C (1.0 or greater) * IBM C (for the RX000, revision unknown) * MPW IIGS C (1.0.1 or greater) * Orca/C (1.1 or greater) * * This include file defines all the fundamental data types which * are to be used for defining variables and constructing all other * abstract data types, like structures and unions. Since each * different hardware, operating system, and compiler environment * defines the C data types of long, int, short, etc. differently, * using them in data definitions may make porting the code to * other environments very difficult. Instead, if these generic * data types are used, then when environments are switched, all * that should need to be done is to alter this include file to * match the new environment and recompile the product. * * Additionally, since there are so few fundamental C data types, * its easy to get confused about what types of operations are * legal on the data contained in a variable. The more commonly * used data types are defined abstractly here, and thus provide * much better clues to everyone about the legal operations on * particular data containers. * * The types defined with a size in them, like int32_type, are * guaranteed to be the same size on all architectures, regardless * of the underlying data type used to produce it. Those types * that do not have a size defined, like boolean_type, MAY be of * different sizes on different architectures. * * Signed and unsigned integers, characters, booleans, bit arrays, * bit fields, opaque types, and miscellaneous types are defined. * * Use of the C data types is strongly discouraged. * * Notes: * * Floating point data types are NOT completely hardware dependant, and * therefore no generic representations can be created!!! Use of * floating point data types represents a potential portability * problem. * * History: * * 06/12/91 1.06 BAK Converted ^I to blanks and added in some newer * and smaller types (for smaller systems who dont * need the extra overhead of larger types/values) * 05/20/91 1.05 BAK Re-added some type changes from 'typedef int foo' * to 'typedef uint16_type foo'. * 05/17/91 1.04 BAK Updated the information above to be up-to-date * with reguards to what systems are supported. * 03/29/91 1.03 BAK Merged my 'portable' include file w/1.02 to * create a more portable 'generic' file. * 03/25/91 1.02 GTH Removed long from all int types. * 01/14/91 1.01 GTH Added int8_type. * 08/09/90 1.00 GTH Created header file. * **********************************************************************/ /********************************************************************** * Check to see if we have been included already and make sure that we * are not included multiple times. **********************************************************************/ #ifndef __Portable__ #define __Portable__ /********************************************************************** * * Machine Types: * * The follow section is used to 'preset' some basic data types based on * the compiler/platform that it is being used on. To do this, the * include file ATTEMPTS to use known built-in values for different * compilers to create the proper setup. If the file can not do this, * then it will not be included properly by your compiler and you will * have to manually tweak the values/checks. * * Notes: * * It will be necessary for a value to be explicitly declared on the * command line using whatever the compiler requires, typically * a /D<value> where <value> is specified below. * * The use of both IAPX286 and IAPX386 is historical for use with * Intel development tools where the tools pre-defined EITHER value, but * not both since the code was to be hardware dependent. * * <value> Target system * IAPX286 Intel 8086/80286/80386/80486 * IAPX386 Intel 8086/80286/80386/80486 * ECLIPSE Data General ECLIPSE Family * MC680X0 Morotola 68000 Family * MC88000 Morotola 88000 Family * RX000 IBM RX000 Family * I6502 Intel(?) 6502 Family * WD65816 Western Digital 65816 Family **********************************************************************/ #ifdef IAPX286 #define LO_HI_MACH_TYPE #define INTS_R_16 #endif #ifdef IAPX386 #define LO_HI_MACH_TYPE #define INTS_R_16 #endif #ifdef ECLIPSE #define HI_LO_MACH_TYPE #define STRICT_ALIGNMENT #define INTS_R_32 #endif #ifdef MC680X0 #define HI_LO_MACH_TYPE #ifdef THINKC #define INTS_R_16 #endif #ifdef MPWC #define INTS_R_32 #endif #endif #ifdef MC88000 #define HI_LO_MACH_TYPE #define STRICT_ALIGNMENT #define INTS_R_32 #endif #ifdef RX000 #define HI_LO_MACH_TYPE #define STRICT_ALIGNMENT #define INTS_R_32 #endif #ifdef I6502 #define LO_HI_MACH_TYPE #define INTS_R_16 #endif #ifdef WD65816 #define LO_HI_MACH_TYPE #define INTS_R_16 #endif /********************************************************************** * * Integer Types * * The integer types defined here are signed and unsigned, and have * various lengths. They may be used to hold true binary integers. * The following operations are allowed which yield integer types: * * assignment <integer_type> = <integer_type> * cast (<integer_type>) <expression> * sizeof sizeof (<integer_type>) * preincrement ++<integer_type> * postincrement <integer_type>++ * predecrement --<integer_type> * postdecrement <integer_type>-- * unary minus -<integer_type> * multiplication <integer_type> * <integer_type> * division <integer_type> / <integer_type> * remainder <integer_type> % <integer_type> * addition <integer_type> + <integer_type> * subtraction <integer_type> - <integer_type> * conditional <boolean_type> ? <integer_type> : * <integer_type> * indirection *<integer_ptr_type> * * These operations yield boolean_type results: * * equals <integer_type> == <integer_type> * not equals <integer_type> != <integer_type> * less than <integer_type> < <integer_type> * less or equals <integer_type> <= <integer_type> * greater than <integer_type> > <integer_type> * greater or equals <integer_type> >= <integer_type> * * These operations yield bit array type results: * * left shift <bit_array_type> << <integer_type> * right shift <bit_array_type> >> <integer_type> * * These operations yield other types: * * subscript <expression> [<integer_type>] * address of &<integer_type> * **********************************************************************/ /* * 32-bit un/signed integer */ #ifdef INTS_R_32 typedef unsigned int uint32; /* 32-bit unsigned type */ typedef unsigned int uint32_type; /* 32-bit unsigned type */ typedef int int32; /* 32-bit signed type */ typedef int int32_type; /* 32-bit signed type */ #endif #ifdef INTS_R_16 typedef unsigned long uint32; /* 32-bit unsigned type */ typedef unsigned long uint32_type; /* 32-bit unsigned type */ typedef long int32; /* 32-bit signed type */ typedef long int32_type; /* 32-bit signed type */ #endif /* * Minimum and maximum 32-bit integer values */ #define INT32_MIN ((int32_type) 0x80000000) /* -2147483648 */ #define INT32_MAX ((int32_type) 0x7fffffff) /* 2147483647 */ #define UINT32_MAX ((uint32_type) 0xffffffff) /* 4294967295 */ /* * 16-bit un/signed integer */ #ifdef INTS_R_32 typedef unsigned short uint16; /* 16-bit unsigned type */ typedef unsigned short int uint16_type; /* 16-bit unsigned type */ typedef short int16; /* 16-bit signed type */ typedef short int int16_type; /* 16-bit signed type */ #endif #ifdef INTS_R_16 typedef unsigned int uint16; /* 16-bit unsigned type */ typedef unsigned int uint16_type; /* 16-bit unsigned type */ typedef int int16; /* 16-bit signed type */ typedef int int16_type; /* 16-bit signed type */ #endif /* * Minimum and maximum 16-bit integer values */ #define INT16_MIN ((int16_type) 0x8000) /* -32768 */ #define INT16_MAX ((int16_type) 0x7fff) /* 32767 */ #define UINT16_MAX ((uint16_type) 0xffff) /* 65535 */ /* * 8-bit un/signed integer * * Use of the int8_type is strongly discouraged because it may * require the use of a special compiler option and may cause * unwanted sign extension when char_type's are compared, and * may cause interference with other normal char_type operations. */ #ifdef INTS_R_32 typedef unsigned char uint8; /* 8-bit unsigned type */ typedef unsigned char uint8_type; /* 8-bit unsigned type */ typedef signed char int8; /* 8-bit signed type */ typedef signed char int8_type; /* 8-bit signed type */ #endif #ifdef INTS_R_16 typedef unsigned char uint8; /* 8-bit unsigned type */ typedef unsigned char uint8_type; /* 8-bit unsigned type */ typedef signed char int8; /* 8-bit signed type */ typedef signed char int8_type; /* 8-bit signed type */ #endif /* * Minimum and maximum 8-bit integer values */ #define INT8_MIN ((int8_type) 0x80) /* -128 */ #define INT8_MAX ((int8_type) 0x7f) /* 127 */ #define UINT8_MAX ((uint8_type) 0xff) /* 255 */ /********************************************************************** * * Character Type * * The character types defined here are 8 bits long. They may be used * to hold true character data, 7-bit ASCII, 8-bit ASCII, or otherwise. * The following operations are allowed which yield character types: * * assignment <character_type> = <character_type> * cast (<character_type>) <expression> * conditional <boolean_type> ? <character_type> : * <character_type> * indirection *<character_ptr_type> * * These operations yield boolean_type results: * * equals <character_type> == <character_type> * not equals <character_type> != <character_type> * * These operations yield other types: * * sizeof sizeof (<character_type>) * address of &<character_type> * **********************************************************************/ /* * 7-bit character */ typedef signed char char_type; /* * 8-bit character */ typedef unsigned char uchar_type; /********************************************************************** * * Scope control keywords * * The scope control keywords are useful for controlling what routines * are visible externally to the source code files they are found in and * which are not. **********************************************************************/ #define public /* public is default in C */ #define private static /* static really means private */ /********************************************************************** * * Boolean Type * * The boolean type defined here may be used to hold true binary * values. There is a unique FALSE value of zero, but all possible * non-zero values are considered TRUE. This means that it would be * best if you do comparisons like (if x) or (if x == FALSE) instead * of comparisons against TRUE. The following operations are allowed * which yield a boolean type: * * assignment <boolean_type> = <boolean_type> * cast (<boolean_type>) <expression> * equality <boolean_type> == <boolean_type> * inequality <boolean_type> != <boolean_type> * logical-and <boolean_type> && <boolean_type> * logical-or <boolean_type> || <boolean_type> * indirection *<boolean_ptr_type> * * These operations yield other types: * * conditional <boolean_type> ? <expression> : * <expression> * sizeof sizeof (<boolean_type>) * address of &<boolean_type> * * Note that boolean_type expressions are required in the following * statements: * * if (<boolean_type>) ... * if (<boolean_type>) ... else ... * while (<boolean_type>) ... * do ... while (<boolean_type>); * for (<expression>; <boolean_type>; <expression>) ... * **********************************************************************/ /* * Boolean */ typedef unsigned char boolean_type; /* * Boolean values */ #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif /********************************************************************** * * Bit Array Types * * The bit array types defined here have various lengths. They may be * used to hold data that is normally operated on in a bitwise fashion. * The following operations are allowed which yield bit array types: * * assignment <bit_array_type> = <bit_array_type> * cast (<bit_array_type>) <expression> * bitwise negation ~<bit_array_type> * bitwise and <bit_array_type> & <bit_array_type> * bitwise or <bit_array_type> | <bit_array_type> * bitwise xor <bit_array_type> ^ <bit_array_type> * left shift <bit_array_type> << <integer_type> * right shift <bit_array_type> >> <integer_type> * conditional <boolean_type> ? <bit_array_type> : * <bit_array_type> * indirection *<bit_array_ptr_type> * * These operations yield boolean_type results: * * equals <bit_array_type> == <bit_array_type> * not equals <bit_array_type> != <bit_array_type> * * These operations yield other types: * * sizeof sizeof (<bit_array_type>) * address of &<bit_array_type> * **********************************************************************/ /* * 32-bit bit array */ typedef uint32_type bit32_type; /* * 16-bit bit array */ typedef uint16_type bit16_type; /* * 8-bit bit array */ typedef uint8_type bit8_type; /********************************************************************** * * Bit Field Types * * These types are used for bit field definitions inside structures. * They may be used to hold data that is operated on with other * semantics, either bit array, unsigned integer, or boolean * operations. * * An example of their use is as follows: * * typedef struct a_structure_type { * field_type a : 4; * boolean_field_type b : 1; * skip_type : 3; * field_type c : 4; * align_type : 0; * field_type d : 8; * } A_STRUCTURE_TYPE ; * * * Bit fields may be used in a portable fashion provided their size is * no larger than 16 bits, fields do not span 16-bit boundaries, groups * of bit fields are aligned and padded to 32-bit boundaries, and the * structure layout is not relied upon (i.e., the compiler may reorder * bit fields for efficiency). * * A field_type has the same semantics as other unsigned integer types, * or as other bit array types. * * A boolean_field_type has the same semantics as other boolean types. * * A skip_type or align_type has no semantics (no legal operations). * * Use of skip_type or align_type implies knowledge of the layout of * the bit field and how the compiler and/or hardware handle it, and * represent potential portability problems. * **********************************************************************/ /* * Named bit field, non-zero in length */ typedef uint16_type field_type; /* * Named boolean bit field, one bit in length */ typedef uint16_type boolean_field_type; /* * Unnamed bit field (padding), non-zero in length */ typedef uint16_type skip_type; /* * Forced alignment to the next 16-bit boundary, zero in length */ typedef uint16_type align_type; /********************************************************************** * * Opaque Types * * The opaque types defined here are simply containers of various sizes * that can hold data in an unknown format. They may be used to hold * data whose format is context sensitive, and therefore can be * interpreted in different fashions. Another use for opaque types is * data hiding, where some data is held in a structure by a high level * layer, but only used in some lower level layer. Virtually no * semantics may be applied to opaque data types. It is intended that * they be cast to other types before being operated on. The following * operations are allowed which yield opaque types: * * assignment <opaque_type> = <opaque_type> * cast (<opaque_type>) <expression> * indirection *<opaque_ptr_type> * * Note that an opaque_ptr_type points to an opaque_type, but is not * opaque itself, it is a real pointer. * * These operations yield other types: * * sizeof sizeof (<opaque_type>) * address of &<opaque_type> * **********************************************************************/ /* * 32-bit opaque */ typedef uint32_type opaque32_type; /* * 16-bit opaque */ typedef uint16_type opaque16_type; /* * 8-bit opaque */ typedef uint8_type opaque8_type; /********************************************************************** * * Any Type Pointer Generation * * This type is used to generate a pointer to any other data type, * without regard to the format or size of that data. It is useful, * for example, where a routine may accept pointers of different forms * into the same argument. The pointer must then be cast to a pointer * of the proper type before the data is operated on. A pointer to an * any_type has no other semantics. The following operations are * allowed which yield a pointer to an any_type: * * assignment <any_type *> = <any_type *> * cast (<any_type *>) <expression> * conditional <boolean_type> ? <any_type *> : <any_type *> * * These operations yield boolean_type results: * * equals <any_type *> == <any_type *> * not equals <any_type *> != <any_type *> * * These operations yield other types: * * sizeof sizeof (<any_type *>) * address of &(<any_type *>) * **********************************************************************/ /* * Any type (used only for generating pointers) */ typedef void any_type; /********************************************************************** * * Null Character Value * * This value is to be used to represent a null character. A null * character terminates C strings. The null character has no other * semantics. * * assignment <char_type> = NULL_CHAR * conditional <boolean_type> ? NULL_CHAR : <expression> * * These operations yield boolean_type results: * * equals <char_type> == NULL_CHAR * not equals <char_type> != NULL_CHAR * **********************************************************************/ /* * Null character value */ #define NULL_CHAR ((char_type) 0) /********************************************************************** * * Null Pointer Value * * This value is to be used to represent an invalid pointer. It must * be cast into a pointer of the proper type. The null pointer has no * other semantics. The following operations are allowed which yield * the null pointer: * * assignment <any_type *> = NULL_PTR * cast (<any_type *>) NULL_PTR * conditional <boolean_type> ? NULL_PTR : <expression> * * These operations yield boolean_type results: * * equals <any_type *> == NULL_PTR * not equals <any_type *> != NULL_PTR * **********************************************************************/ /* * Null pointer value */ #define NULL_PTR ((any_type *) 0) /********************************************************************** * * Void Type * * This type is used to declare that a function returns nothing, or to * indicate that the result of an expression or function is being * discarded. The void type has no other semantics. The following * operations are allowed with the void type: * * declaration void_type <function declaration> * expression value (void_type) <expression> * function value (void_type) <function call> * **********************************************************************/ /* * Void type */ typedef void void_type; /********************************************************************** * * Status Return Values * * These values are to be used for comparison against the status * returned by a function. * * The following operations are allowed using status return values: * * assignment <int32_type> = <status_value> * <int16_type> = <small_status_value> * cast (<int32_type>) <status_value> * (<int16_type>) <small_status_value> * conditional <boolean_type> ? <status_value> : * <status_value> * <boolean_type> ? <small_status_value> : * <small_status_value> * * These operations yield boolean_type results: * * equals <int32_type> == <status_type> * <int16_type> == <small_status_type> * not equals <int32_type> != <status_type> * <int16_type> != <small_status_type> * **********************************************************************/ /* * Status return values */ #define STATUS_OK ((int32_type) 0) #define STATUS_ERROR ((int32_type) -1) /* * Small status return values */ #define SSTATUS_OK ((int16_type) 0) #define SSTATUS_ERROR ((int16_type) -1) /********************************************************************** * * Member Of Structure Offset * * This macro returns the offset in bytes from the beginning of the * specified structure to the beginning of the specified structure * member. This is a zero-based byte offset, not a byte count, and * is returned as a int32_type or int16_type. * * The following operation is allowed with MEMBER_OFFSET: * * typedef any_struct_type { * ..... * <type> member_name_within_struct; * ..... * } ANY_STRUCT_TYPE; * * <int32_type> = MEMBER_OFFSET (ANY_STRUCT_TYPE, * member_name_within_struct); * <int16_type> = MEMBER_OFFSET16(ANY_STRUCT_TYPE, * member_name_within_struct); * * Note that the "structure type" passed MUST be a typedef structure * name, not a typedef tag name, nor an instance of the structure. The * member name must be within the structure, and can be any type except * bit field. * **********************************************************************/ #define MEMBER_OFFSET(mo_struct, mo_member) \ ((int32_type) (char_type *) & (((mo_struct *) 0) -> mo_member)) #define MEMBER_OFFSET16(mo_struct, mo_member) \ ((int16_type) (char_type *) & (((mo_struct *) 0) -> mo_member)) /********************************************************************** * * Byte swap macros * * These macros are used for faster/efficient byte swapping independent * of the architecture the program is running on. They are also refered * to as Transparent Data Representation (TDR) macros. * **********************************************************************/ #ifdef LO_HI_MACH_TYPE #define GETINT16(x) (\ ((uint16)(x & 0x00FF) << 8) | \ ((uint16)(x & 0xFF00) >> 8) \ ) #define PUTINT16(x) GETINT16(x) #define GETINT32(x) (\ ((uint32)(x & 0x000000FF) << 24) | \ ((uint32)(x & 0x0000FF00) << 8) | \ ((uint32)(x & 0x00FF0000) >> 8) | \ ((uint32)(x & 0xFF000000) >> 24) \ ) #define PUTINT32(x) GETINT32(x) #define REVGETINT16(x) (x) #define REVGETINT32(x) (x) #endif /* LO_HI_MACH_TYPE */ #ifdef HI_LO_MACH_TYPE #define GETINT16(x) (x) #define GETINT32(x) (x) #define PUTINT16(x) (x) #define PUTINT32(x) (x) #define REVGETINT16(x) (\ ((uint16)(x & 0x00FF) << 8) | \ ((uint16)(x & 0xFF00) >> 8) \ ) #define REVGETINT32(x) (\ ((uint32)(x & 0x000000FF) << 24) | \ ((uint32)(x & 0x0000FF00) << 8) | \ ((uint32)(x & 0x00FF0000) >> 8) | \ ((uint32)(x & 0xFF000000) >> 24) \ ) #endif /* HI_LO_MACH_TYPE */ /********************************************************************** * * Byte allignment macros * * These macros are used for faster/efficient byte alligment of data * independent of the architecture the program is running on. They are also * refered to as Transparent Data Representation (TDR) macros. * **********************************************************************/ #ifdef STRICT_ALIGNMENT #define GETALIGN32(src, dest) MEMCPY( dest, src, 4 ) #define GETALIGN16(src, dest) MEMCPY( dest, src, 2 ) #else #define GETALIGN32(src, dest) (*((uint32 *)dest) = *((uint32 *)src)) #define GETALIGN16(src, dest) (*((uint16 *)dest) = *((uint16 *)src)) #endif /* !STRICT_ALIGNMENT */ #endif /* !__Portable__ */