diff options
Diffstat (limited to 'lib/util')
-rw-r--r-- | lib/util/mallocvar.c | 8 | ||||
-rw-r--r-- | lib/util/mallocvar.h | 18 | ||||
-rw-r--r-- | lib/util/nstring.c | 105 | ||||
-rw-r--r-- | lib/util/nstring.h | 33 | ||||
-rw-r--r-- | lib/util/pm_c_util.h | 13 | ||||
-rw-r--r-- | lib/util/runlength.c | 103 | ||||
-rw-r--r-- | lib/util/runlength.h | 3 | ||||
-rw-r--r-- | lib/util/shhopt.c | 58 | ||||
-rw-r--r-- | lib/util/shhopt.h | 66 | ||||
-rw-r--r-- | lib/util/wordaccess.h | 75 | ||||
-rw-r--r-- | lib/util/wordaccess_64_le.h | 28 | ||||
-rw-r--r-- | lib/util/wordaccess_be_aligned.h | 35 | ||||
-rw-r--r-- | lib/util/wordaccess_be_unaligned.h | 20 | ||||
-rw-r--r-- | lib/util/wordaccess_generic.h | 29 | ||||
-rw-r--r-- | lib/util/wordintclz.h | 93 |
15 files changed, 248 insertions, 439 deletions
diff --git a/lib/util/mallocvar.c b/lib/util/mallocvar.c index 339d5d61..f75bd94d 100644 --- a/lib/util/mallocvar.c +++ b/lib/util/mallocvar.c @@ -30,7 +30,7 @@ allocarrayNoHeap(void ** const rowIndex, void * rowSpace; mallocProduct(&rowSpace, cols, elementSize); - + if (rowSpace == NULL) { unsigned int row; @@ -123,7 +123,7 @@ pm_mallocarray2(void ** const resultP, if (rowheap) { unsigned int row; - + for (row = 0; row < rows; ++row) rowIndex[row] = &(rowheap[row * cols * elementSize]); } @@ -133,7 +133,7 @@ pm_mallocarray2(void ** const resultP, format. */ rowIndex[rows+1] = NULL; /* Declare it fragmented format */ - + allocarrayNoHeap(rowIndex, rows, cols, elementSize, &failed); } rowIndex[rows+0] = NULL; /* mark end of rows */ @@ -151,7 +151,7 @@ array2RowCount(void ** const rowIndex) { /*---------------------------------------------------------------------------- Return the number of rows in the 2-dimensional array. -----------------------------------------------------------------------------*/ - /* The end of the rows is marked by a null pointer where a row + /* The end of the rows is marked by a null pointer where a row pointer otherwise would be. */ diff --git a/lib/util/mallocvar.h b/lib/util/mallocvar.h index e92e3fe4..00ba6484 100644 --- a/lib/util/mallocvar.h +++ b/lib/util/mallocvar.h @@ -1,5 +1,5 @@ /* These are some dynamic memory allocation facilities. They are essentially - an extension to C, as they do allocations with a cognizance of C + an extension to C, as they do allocations with a cognizance of C variables. You can use them to make C read more like a high level language. @@ -23,7 +23,7 @@ extern "C" { #endif static __inline__ void -mallocProduct(void ** const resultP, +mallocProduct(void ** const resultP, unsigned int const factor1, unsigned int const factor2) { /*---------------------------------------------------------------------------- @@ -44,10 +44,10 @@ mallocProduct(void ** const resultP, if (factor1 == 0 || factor2 == 0) *resultP = malloc(1); else { - if (UINT_MAX / factor2 < factor1) + if (UINT_MAX / factor2 < factor1) *resultP = NULL; - else - *resultP = malloc(factor1 * factor2); + else + *resultP = malloc(factor1 * factor2); } } @@ -61,11 +61,11 @@ reallocProduct(void ** const blockP, void * const oldBlockP = *blockP; void * newBlockP; - - if (UINT_MAX / factor2 < factor1) + + if (UINT_MAX / factor2 < factor1) newBlockP = NULL; - else - newBlockP = realloc(oldBlockP, factor1 * factor2); + else + newBlockP = realloc(oldBlockP, factor1 * factor2); if (newBlockP) *blockP = newBlockP; diff --git a/lib/util/nstring.c b/lib/util/nstring.c index 093cf99f..aff90ff3 100644 --- a/lib/util/nstring.c +++ b/lib/util/nstring.c @@ -3,7 +3,7 @@ * THIS MODULE WAS ADAPTED FOR NETPBM BY BRYAN HENDERSON ON 2002.03.24. - Bryan got the base from + Bryan got the base from http://www.ijs.si/software/snprintf/snprintf-2.2.tar.gz, but made a lot of changes and additions. The code from ww.ijs.si was written by @@ -105,6 +105,7 @@ */ +#define _DEFAULT_SOURCE /* New name for SVID & BSD source defines */ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ #define _BSD_SOURCE /* Make sure strdup() is in string.h */ #define _GNU_SOURCE @@ -186,6 +187,19 @@ static char credits[] = "\n\ @(#)snprintf.c, v2.2: http://www.ijs.si/software/snprintf/\n"; +/* MacOS X before 10.7, for one, does not have strnlen */ +size_t +pm_strnlen(const char * const s, + size_t const maxlen) { + + unsigned int i; + + for (i = 0; i < maxlen && s[i]; ++i) {} + + return i; +} + + void pm_vsnprintf(char * const str, @@ -193,7 +207,7 @@ pm_vsnprintf(char * const str, const char * const fmt, va_list ap, size_t * const sizeP) { - + size_t str_l = 0; const char *p = fmt; @@ -218,7 +232,6 @@ pm_vsnprintf(char * const str, } p += n; str_l += n; } else { - const char *starting_p; size_t min_field_width; size_t precision = 0; bool precision_specified; @@ -260,7 +273,6 @@ pm_vsnprintf(char * const str, str_arg = credits; /* just to make compiler happy (defined but not used) */ str_arg = NULL; - starting_p = p; ++p; /* skip '%' */ /* parse flags */ @@ -397,7 +409,7 @@ pm_vsnprintf(char * const str, str_arg_l = 0; else if (!precision_specified) /* truncate string if necessary as requested by - precision + precision */ str_arg_l = strlen(str_arg); else if (precision == 0) @@ -449,7 +461,7 @@ pm_vsnprintf(char * const str, undefined. (Actually %hp converts only 16-bits of address and %llp treats address as 64-bit data which is incompatible with (void *) - argument on a 32-bit system). + argument on a 32-bit system). */ length_modifier = '\0'; @@ -582,7 +594,7 @@ pm_vsnprintf(char * const str, && !(zero_padding_insertion_ind < str_arg_l && tmp[zero_padding_insertion_ind] == '0')) { /* assure leading zero for alternate-form - octal numbers + octal numbers */ if (!precision_specified || precision < num_of_digits+1) { @@ -596,7 +608,7 @@ pm_vsnprintf(char * const str, } } /* zero padding to specified precision? */ - if (num_of_digits < precision) + if (num_of_digits < precision) number_of_zeros_to_pad = precision - num_of_digits; } /* zero padding to specified minimal field width? */ @@ -748,7 +760,7 @@ pm_snprintf(char * const dest, va_list ap; va_start(ap, fmt); - + pm_vsnprintf(dest, str_m, fmt, ap, &size); va_end(ap); @@ -787,12 +799,12 @@ pm_strdup(const char * const arg) { void PM_GNU_PRINTF_ATTR(2,3) pm_asprintf(const char ** const resultP, - const char * const fmt, + const char * const fmt, ...) { const char * result; va_list varargs; - + #if HAVE_VASPRINTF int rc; va_start(varargs, fmt); @@ -802,7 +814,7 @@ pm_asprintf(const char ** const resultP, result = pm_strsol; #else size_t dryRunLen; - + va_start(varargs, fmt); pm_vsnprintf(NULL, 0, fmt, varargs, &dryRunLen); @@ -823,7 +835,7 @@ pm_asprintf(const char ** const resultP, va_start(varargs, fmt); pm_vsnprintf(buffer, allocSize, fmt, varargs, &realLen); - + assert(realLen == dryRunLen); va_end(varargs); @@ -851,7 +863,7 @@ pm_strfree(const char * const string) { const char * pm_strsep(char ** const stringP, const char * const delim) { - const char * retval; + const char * retval; if (stringP == NULL || *stringP == NULL) retval = NULL; @@ -861,16 +873,16 @@ pm_strsep(char ** const stringP, const char * const delim) { retval = *stringP; for (p = *stringP; *p && strchr(delim, *p) == NULL; ++p); - + if (*p) { - /* We hit a delimiter, not end-of-string. So null out the + /* We hit a delimiter, not end-of-string. So null out the delimiter and advance user's pointer to the next token */ *p++ = '\0'; *stringP = p; } else { - /* We ran out of string. So the end-of-string delimiter is - already there, and we set the user's pointer to NULL to + /* We ran out of string. So the end-of-string delimiter is + already there, and we set the user's pointer to NULL to indicate there are no more tokens. */ *stringP = NULL; @@ -894,7 +906,7 @@ pm_stripeq(const char * const comparand, const char * px; const char * qx; bool equal; - + /* Make p and q point to the first non-blank character in each string. If there are no non-blank characters, make them point to the terminating NUL. @@ -987,39 +999,50 @@ pm_strishex(const char * const subject) { void -pm_interpret_uint(const char * const string, - unsigned int * const valueP, +pm_string_to_uint(const char * const string, + unsigned int * const uintP, const char ** const errorP) { - if (string[0] == '\0') - pm_asprintf(errorP, "Null string."); + if (strlen(string) == 0) + pm_asprintf(errorP, "Value is a null string"); else { - /* strtoul() does a bizarre thing where if the number is out + char * tailptr; + long longValue; + + /* We can't use 'strtoul'. Contrary to expectations, though as + designed, it returns junk if there is a minus sign. + */ + + /* strtol() does a bizarre thing where if the number is out of range, it returns a clamped value but tells you about it by setting errno = ERANGE. If it is not out of range, - strtoul() leaves errno alone. + strtol() leaves errno alone. */ - char * tail; - unsigned long ulongValue; - errno = 0; /* So we can tell if strtoul() overflowed */ - ulongValue = strtoul(string, &tail, 10); - - if (tail[0] != '\0') - pm_asprintf(errorP, "Non-digit stuff in string: %s", tail); - else if (errno == ERANGE) - pm_asprintf(errorP, "Number too large"); - else if (ulongValue > UINT_MAX) - pm_asprintf(errorP, "Number too large"); - else if (string[0] == '-') - pm_asprintf(errorP, "Negative number"); - /* Sleazy code; string may have leading spaces. */ + longValue = strtol(string, &tailptr, 10); + + if (*tailptr != '\0') + pm_asprintf(errorP, "Non-numeric crap in string: '%s'", tailptr); else { - *valueP = ulongValue; - *errorP = NULL; + if (errno == ERANGE) + pm_asprintf(errorP, "Number is too large for computation"); + else { + if (longValue < 0) + pm_asprintf(errorP, "Number is negative"); + else { + if ((unsigned int)longValue != longValue) + pm_asprintf(errorP, + "Number is too large for computation"); + else { + *uintP = (unsigned int)longValue; + *errorP = NULL; + } + } + } } } } + diff --git a/lib/util/nstring.h b/lib/util/nstring.h index 7238a76e..5159277c 100644 --- a/lib/util/nstring.h +++ b/lib/util/nstring.h @@ -3,6 +3,7 @@ #include <stdarg.h> #include <string.h> +#include <strings.h> /* For strncasecmp */ #include <ctype.h> #include "pm_c_util.h" @@ -59,15 +60,21 @@ static __inline__ int memeq(const void * const comparand, const void * const comparator, size_t const size) { - + return memcmp(comparand, comparator, size) == 0; } -/* The Standard C Library may not declare strcasecmp() if the including - source file doesn't request BSD functions, with _BSD_SOURCE. So - we don't define functions that use strcasecmp() in that case. +/* The Standard C Library may not declare strcasecmp() if the including source + file doesn't request BSD functions, with _BSD_SOURCE or SUSv2 function, + with _XOPEN_SOURCE >= 500. So we don't define functions that use + strcasecmp() in that case. + + (Actually, _XOPEN_SOURCE 500 is stronger than you need for strcasecmp - + _XOPEN_SOURCE_EXTENDED, which asks for XPG 4, would do, whereas + _XOPEN_SOURCE 500 asks for XPG 5, but for simplicity, we don't use + _XOPEN_SOURCE_EXTENDED in Netpbm. */ -#ifdef _BSD_SOURCE +#if defined(_BSD_SOURCE) || (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE - 0) >= 500) static __inline__ int strcaseeq(const char * const comparand, const char * const comparator) { @@ -85,7 +92,7 @@ strncaseeq(const char * const comparand, #endif -/* The standard C library routines isdigit(), for some weird +/* The standard C library routines isdigit(), for some weird historical reason, does not take a character (type 'char') as its argument. Instead it takes an integer. When the integer is a whole number, it represents a character in the obvious way using the local @@ -125,7 +132,7 @@ strncaseeq(const char * const comparand, Netpbm must include them in its own libraries, and because some standard C libraries have some of them, Netpbm must use different names for them. - + The GNU C library has all of them. All but the oldest standard C libraries have snprintf(). @@ -149,6 +156,10 @@ strncaseeq(const char * const comparand, extern const char * const pm_strsol; +size_t +pm_strnlen(const char * const s, + size_t const maxlen); + int pm_snprintf(char * const dest, size_t const str_m, @@ -178,7 +189,7 @@ pm_vasprintf(const char ** const resultP, bool pm_vasprintf_knows_float(void); -void +void pm_strfree(const char * const string); const char * @@ -198,9 +209,9 @@ bool pm_strishex(const char * const subject); void -pm_interpret_uint(const char * const string, - unsigned int * const valueP, - const char ** const errorP); +pm_string_to_uint(const char * const string, + unsigned int * const uintP, + const char ** const errorP); #ifdef __cplusplus } diff --git a/lib/util/pm_c_util.h b/lib/util/pm_c_util.h index 01a07657..a093adb6 100644 --- a/lib/util/pm_c_util.h +++ b/lib/util/pm_c_util.h @@ -20,6 +20,13 @@ #define ROUND(X) (((X) >= 0) ? (int)((X)+0.5) : (int)((X)-0.5)) #undef ROUNDU #define ROUNDU(X) ((unsigned int)((X)+0.5)) + /* Note that imprecision in floating point arithmetic can make an exact + half fractional part round down instead of up. What should be + 1000.5 might actually be 1000.49999999999. + + Use 'pnm_unnormalized_sample' instead of ROUNDU(samplen*maxval) to get + consistent rounding up when you are unnormalizing sample values. + */ /* ROUNDUP rounds up to a specified multiple. E.g. ROUNDUP(22, 8) == 24 */ @@ -53,9 +60,11 @@ #else /* The test for __STDC__ is paranoid. It is there just in case some nonstandard compiler defines __STDC_VERSION__ in an arbitrary manner. + + We know GCC 2.95.3 has stdbool; not sure about earlier GCC 2. */ - #if ( defined(__GNUC__) && (__GNUC__ >= 3) ) || \ - ( defined(__STDC__) && (__STDC__ ==1) && \ + #if ( defined(__GNUC__) && (__GNUC__ >= 2) ) || \ + ( defined(__STDC__) && (__STDC__ == 1) && \ defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) ) #include <stdbool.h> #else diff --git a/lib/util/runlength.c b/lib/util/runlength.c index e5c60db0..62e3bf0c 100644 --- a/lib/util/runlength.c +++ b/lib/util/runlength.c @@ -12,8 +12,8 @@ documentation. This software is provided "as is" without express or implied warranty. - Functions pm_rlenc_byte() and pm_rlenc_word() are based on algorithm - originally by Robert A. Knop (rknop@mop.caltech.edu). + Functions pm_rlenc_compressbyte() and pm_rlenc_compressword() are based + on algorithm originally by Robert A. Knop (rknop@mop.caltech.edu). Those who wish to incorporate the code herein into their own programs are strongly discouraged from removing the comments within borders consisting @@ -22,9 +22,9 @@ =============================================================================== - Packbits is a simple yet efficient simple run-length compression method. It - has a provision for uncompressed sequences which allows efficient encoding - of noisy input. + Packbits is a simple yet efficient simple run-length compression method. + It has a provision for uncompressed sequences which allows efficient + encoding of noisy input. A survey of netpbm source code in 2015 found Packbits encoding in the following Netpbm programs: pbmtoescp2, pbmtomacp, pnmtopalm, pnmtopclxl, @@ -34,19 +34,20 @@ images that use Packbits compression, but does so via code in the TIFF library (not part of Netpbm). - Variants of Packbits are employed in pnmtosgi, pamtopdbimg, pbmtoppa - and pbmtogo. + Variants of Packbits are employed in pnmtosgi, pamtopdbimg, pbmtoppa + pbmtogo and pamtotga. All the above programs formerly did the same compression through different code. This redundancy bloated the Netpbm package and made maintenance difficult. This maintenance difficulty surfaced as an issue when tests with valgrind revealed multiple memory-related problems in the above programs. - Indeed, just determining which programs do this compression by this method + Indeed, just determining which programs do compression by this method was not simple because of differences in terminology. "Packbits" is often called "run length encoding." In ppmtoilbm the name is "byterun1." - Today, all Netpbm programs that do Packbits compression use the facilities - in this file for it. + Today, all Netpbm programs that do Packbits compression with the exception + of pamtotiff, pbmtoppa, pbmtogo and pamtotga use the facilities in this + file for it. =============================================================================*/ #include <string.h> @@ -68,11 +69,11 @@ static const char * const errorUndefinedMode = In this simple run-length encoding scheme, compressed and uncompressed strings follow a single index or "flag" byte N. There are several - variations, differing in the format of the flag byte, maximum string length - and element size (byte or word). + variations, differing in the format of the flag byte, maximum string + length and element size (byte or word). - In the most widely used version, Packbits, the meaning of the flag byte N - is defined as follows: + In the most widely used version, Packbits, the meaning of the flag byte + N is defined as follows: 0-127 means the next N+1 bytes are uncompressed. 129-255 means the next byte is to be repeated 257-N times. @@ -99,7 +100,7 @@ pm_rlenc_compressbyte(const unsigned char * const inbuf, Always encode 3-byte repeat sequences. Encode 2-byte repeat sequences only when they are at the start of the block. - This ensures that the output is never unnecessary bloated. + This ensures that the output is never unnecessarily bloated. Original algorithm by Robert A. Knop (rknop@mop.caltech.edu) -----------------------------------------------------------------------------*/ @@ -107,8 +108,17 @@ pm_rlenc_compressbyte(const unsigned char * const inbuf, size_t inCurs, outCurs; - if (mode != PM_RLE_PACKBITS) - pm_error(errorUndefinedMode, mode); + int packBase; + int packSign; + + switch (mode) { + case PM_RLE_PACKBITS: + packBase = 257 ; packSign = -1; break; + case PM_RLE_PALMPDB: + packBase = 127 ; packSign = +1; break; + default: + pm_error(errorUndefinedMode, mode); + } for (inCurs = 0, outCurs = 0; inCurs < inSize; ) { if ((inCurs < inSize - 1) && (inbuf[inCurs] == inbuf[inCurs+1])) { @@ -121,8 +131,7 @@ pm_rlenc_compressbyte(const unsigned char * const inbuf, count < maxRun; ++inCurs, ++count) ; - - outbuf[outCurs++] = (unsigned char)(257 - count); + outbuf[outCurs++] = (unsigned char) (packBase + packSign * count); outbuf[outCurs++] = inbuf[hold]; } else { /*Do a non-run*/ @@ -176,11 +185,11 @@ pm_rlenc_compressword(const uint16_t * const inbuf, size_t const inSize, size_t * const outputSizeP) { /*--------------------------------------------------------------------------- - Similar to pm_rlenc_byte(), but this works with two-byte elements. The - difference between SGI16 and PALM16 is the size of the flag. SGI16 : 16 - bits; PALM16 : 8 bits + Similar to pm_rlenc_compressbyte(), but this works with two-byte elements. + The difference between SGI16 and PALM16 is the size of the flag. + SGI16 : 16 bits; PALM16 : 8 bits - 'inSize' is a number of words,but *outputSizeP is a number of bytes. + 'inSize' is a number of words, but *outputSizeP is a number of bytes. -----------------------------------------------------------------------------*/ size_t inCurs, outCurs; size_t flagSz; @@ -258,6 +267,8 @@ pm_rlenc_compressword(const uint16_t * const inbuf, number of flag bytes. The worst case happens when there are no repeat sequences in the input. + The encoder in this file is an efficient one. + The key to an efficient encoder is correct handling of short, inefficient sequences. The following algorithm (not actually used in this file) describes the idea. @@ -267,9 +278,9 @@ pm_rlenc_compressword(const uint16_t * const inbuf, different from its neighbors. A compressed block is one that encodes a sequence of identical values - (which could be a run or just part of a run) as a value and a count. - count. An uncompressed block is one that encodes a sequence of any values - by listing the values individually. + (which could be a run or just part of a very long run) as a value and + a count. An uncompressed block is one that encodes a sequence of any + values by listing the values individually. Start by encoding the entire input as uncompressed blocks. Seek runs that can be encoded with compressed blocks, but only if doing so doesn't make @@ -288,6 +299,16 @@ pm_rlenc_compressword(const uint16_t * const inbuf, - Whenever savings are larger than the added overhead, encode the run as a compressed block. + + ----------------------------------------------------------------------- + + MS-DOS/Windows BMP format note + + The compression method for BMP is a variant of packbits. + We could support the 8-bit version with some modifications to functions + in this file. Determining the worst-case output size of an efficient + coder is rather complicated because uncompressed blocks may not be less + than three bytes long and are indicated by two-byte flags. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ @@ -310,23 +331,31 @@ pm_rlenc_maxbytes(size_t const inSize, /* number of elements */ /* The upper limit could be raised above INT_MAX, but no program needs that today. */ - size_t blockSize; - size_t flagSize; - size_t itemSize; - size_t miscSize; - size_t overhead; + size_t blockSize; /* Number of items in data block */ + size_t flagSize; /* Size of flag, in bytes */ + size_t itemSize; /* Size of item, in bytes */ + size_t miscSize; /* Size of other elements such as term code, in bytes */ + size_t overhead; /* Worst-case overhead, in bytes */ + /* return value: Worst-case output size, in bytes */ switch (mode) { case PM_RLE_PACKBITS: - blockSize = 128; flagSize = 1; itemSize = 1; miscSize = 0; break; + case PM_RLE_PALMPDB: + blockSize = 128; flagSize = 1; itemSize = 1; miscSize = 0; + break; case PM_RLE_SGI8: - blockSize = 127; flagSize = 1; itemSize = 1; miscSize = 0; break; - case PM_RLE_GRAPHON: case PM_RLE_PPA: - blockSize = 64; flagSize = 1; itemSize = 1; miscSize = 0; break; + blockSize = 127; flagSize = 1; itemSize = 1; miscSize = 0; + break; + case PM_RLE_GRAPHON: + case PM_RLE_PPA: + blockSize = 64; flagSize = 1; itemSize = 1; miscSize = 0; + break; case PM_RLE_SGI16: - blockSize = 127; flagSize = 2; itemSize = 2; miscSize = 2; break; + blockSize = 127; flagSize = 2; itemSize = 2; miscSize = 2; + break; case PM_RLE_PALM16: - blockSize = 128; flagSize = 1; itemSize = 2; miscSize = 0; break; + blockSize = 128; flagSize = 1; itemSize = 2; miscSize = 0; + break; default: pm_error(errorUndefinedMode, mode); } diff --git a/lib/util/runlength.h b/lib/util/runlength.h index 4857ae61..de921650 100644 --- a/lib/util/runlength.h +++ b/lib/util/runlength.h @@ -18,7 +18,8 @@ enum pm_RleMode { PM_RLE_PACKBITS, /* most common mode */ PM_RLE_PPA, /* reserved */ PM_RLE_SGI8, /* reserved */ PM_RLE_SGI16, - PM_RLE_PALM16 + PM_RLE_PALM16, + PM_RLE_PALMPDB }; size_t diff --git a/lib/util/shhopt.c b/lib/util/shhopt.c index ccf2d1eb..ab489fef 100644 --- a/lib/util/shhopt.c +++ b/lib/util/shhopt.c @@ -168,7 +168,7 @@ optString(const optEntry opte, int lng) } - + static optEntry optStructToEntry(const optStruct opt) { /*---------------------------------------------------------------------------- @@ -202,7 +202,7 @@ optStructTblToEntryTbl(const optStruct optStructTable[]) { int i; optEntry *optEntryTable; /* malloc'ed array */ - + /* Count the entries in optStructTable[] */ for (i = 0; optStructTable[i].type != OPT_END && i < 500; i++); count = i+1; @@ -210,7 +210,7 @@ optStructTblToEntryTbl(const optStruct optStructTable[]) { optEntryTable = (optEntry *) malloc(count * sizeof(optEntry)); if (optEntryTable) { int i; - for (i = 0; i < count; i++) + for (i = 0; i < count; i++) optEntryTable[i] = optStructToEntry(optStructTable[i]); } return(optEntryTable); @@ -284,7 +284,7 @@ getToken(const char * const tokenStart, doesn't necessarily advance. -----------------------------------------------------------------------------*/ const char * error; - + pm_gettoken(tokenStart, delimiter, tokenP, nextP, &error); if (error) @@ -383,7 +383,7 @@ parseStringList(const char * const listText, | | FUNCTION Perform the action of an option. | - | INPUT opt element in array of defined options that + | INPUT opt element in array of defined options that | applies to this option | arg argument to option, if it applies. | lng was the option given as a long option? @@ -411,7 +411,7 @@ optExecute(optEntry const opt, char *arg, int lng) case OPT_LONG: { long tmp; char *e; - + if (arg == NULL) optFatal("internal error: optExecute() called with NULL argument " "'%s'", optString(opt, lng)); @@ -429,12 +429,12 @@ optExecute(optEntry const opt, char *arg, int lng) *((long *) opt.arg) = tmp; } } break; - + case OPT_UINT: case OPT_ULONG: { unsigned long tmp; char * tailPtr; - + if (arg == NULL) optFatal("internal error: optExecute() called with NULL argument " "'%s'", optString(opt, lng)); @@ -460,7 +460,7 @@ optExecute(optEntry const opt, char *arg, int lng) case OPT_FLOAT: { float tmp; char *e; - + if (arg == NULL) optFatal("internal error: optExecute() called with NULL argument " "'%s'", optString(opt, lng)); @@ -597,7 +597,7 @@ pm_optParseOptions(int *argc, char *argv[], optStruct opt[], int allowNegNum) arg = NULL; if ((p = strchr(argv[ai], '=')) != NULL) arg = p + 1; - + /* does this option take an argument? */ optarg = -1; if (optNeedsArgument(opt_table[mi])) { @@ -666,7 +666,7 @@ pm_optParseOptions(int *argc, char *argv[], optStruct opt[], int allowNegNum) static void parse_short_option_token(char *argv[], const int argc, const int ai, - const optEntry opt_table[], + const optEntry opt_table[], int * const tokens_consumed_p) { /*---------------------------------------------------------------------------- Parse a cluster of short options, e.g. -walne . @@ -681,7 +681,7 @@ parse_short_option_token(char *argv[], const int argc, const int ai, char *arg; int mi; /* index into option table */ unsigned char processed_arg; /* boolean */ - /* We processed an argument to one of the one-character options. + /* We processed an argument to one of the one-character options. This necessarily means there are no more options in this token to process. */ @@ -707,7 +707,7 @@ parse_short_option_token(char *argv[], const int argc, const int ai, (*tokens_consumed_p)++; } processed_arg = 1; - } else + } else arg = NULL; /* perform the action of this option. */ optExecute(opt_table[mi], arg, 0); @@ -761,7 +761,7 @@ parse_long_option(char * const argv[], int const argc, int const ai, int const namepos, - optEntry const opt_table[], + optEntry const opt_table[], int * const tokens_consumed_p) { /*---------------------------------------------------------------------------- Parse a long option, e.g. -verbose or --verbose. @@ -788,11 +788,11 @@ parse_long_option(char * const argv[], fatalUnrecognizedLongOption(argv[ai], opt_table); /* possibly locate the argument to this option. */ - { + { char *p; if ((p = strchr(argv[ai], '=')) != NULL) equals_arg = p + 1; - else + else equals_arg = NULL; } /* does this option take an argument? */ @@ -812,7 +812,7 @@ parse_long_option(char * const argv[], optFatal("option `%s' doesn't allow an argument, but you " "have specified it in the form name=value", optString(opt_table[mi], 1)); - else + else arg = NULL; } /* perform the action of this option. */ @@ -849,7 +849,7 @@ parse_long_option(char * const argv[], | | This differs from pm_optParseOptions in that it accepts | long options with just one hyphen and doesn't accept - | any short options. It also has accommodations for + | any short options. It also has accommodations for | future expansion. | | Options and arguments used are removed from the argv- @@ -858,11 +858,11 @@ parse_long_option(char * const argv[], | Any error leads to program abortion. */ void -pm_optParseOptions2(int * const argc_p, char *argv[], const optStruct2 opt, +pm_optParseOptions2(int * const argc_p, char *argv[], const optStruct2 opt, const unsigned long flags) /*---------------------------------------------------------------------------- This does the same thing as pm_optParseOptions3(), except that there is no - "specified" return value. + "specified" return value. This function exists for backward compatibility. -----------------------------------------------------------------------------*/ @@ -877,7 +877,7 @@ pm_optParseOptions2(int * const argc_p, char *argv[], const optStruct2 opt, if (opt3.opt_table == NULL) optFatal("Memory allocation failed (trying to allocate space for " "new-format option table)"); - + pm_optParseOptions3(argc_p, argv, opt3, sizeof(opt3), flags); free(opt3.opt_table); @@ -914,13 +914,13 @@ zero_specified(optEntry opt_table[]) { | Size of "opt" (since the caller may be older | than this function, it may be using a structure | with fewer fields than exist today. We use this - | parameter to handle those older callers). + | parameter to handle those older callers). | flags Result is undefined if not zero. | For future expansion. | | OUTPUT argc new argument count. | argv array with arguments removed. - | + | | Areas pointed to by pointers in 'opt' get updated with | option values and counts. | @@ -934,7 +934,7 @@ zero_specified(optEntry opt_table[]) { | | This differs from pm_optParseOptions in that it accepts | long options with just one hyphen and doesn't accept - | any short options. It also has accommodations for + | any short options. It also has accommodations for | future expansion. | | Options and arguments used are removed from the argv- @@ -943,7 +943,7 @@ zero_specified(optEntry opt_table[]) { | Any error leads to program abortion. */ void -pm_optParseOptions3(int * const argc_p, char *argv[], const optStruct3 opt, +pm_optParseOptions3(int * const argc_p, char *argv[], const optStruct3 opt, const unsigned int optStructSize, const unsigned long flags) { int ai; /* argv index. */ @@ -958,10 +958,10 @@ pm_optParseOptions3(int * const argc_p, char *argv[], const optStruct3 opt, */ no_more_options = 0; /* initial value */ for (ai = 0; ai < *argc_p; ) { - if (no_more_options) + if (no_more_options) /* Can't be an option -- there aren't any more */ ai++; - else if (argv[ai][0] != '-') + else if (argv[ai][0] != '-') /* Can't be an option -- doesn't start with a dash */ ai++; else { @@ -980,7 +980,7 @@ pm_optParseOptions3(int * const argc_p, char *argv[], const optStruct3 opt, /* The entire thing is "--". That means no more options */ tokens_consumed = 1; no_more_options = 1; - } else + } else /* It's an option that starts with "--" */ parse_long_option(argv, *argc_p, ai, 2, opt.opt_table, &tokens_consumed); @@ -994,7 +994,7 @@ pm_optParseOptions3(int * const argc_p, char *argv[], const optStruct3 opt, parse_long_option(argv, *argc_p, ai, 1, opt.opt_table, &tokens_consumed); } - + } /* remove option and any argument from the argv-array. */ { diff --git a/lib/util/shhopt.h b/lib/util/shhopt.h index 9a446290..d9304f9f 100644 --- a/lib/util/shhopt.h +++ b/lib/util/shhopt.h @@ -4,7 +4,7 @@ HERE IS AN EXAMPLE OF THE USE OF SHHOPT: #include <shhopt.h> -int +int main ( int argc, char **argv ) { /* initial values here are just to demonstrate what gets set and @@ -18,19 +18,21 @@ main ( int argc, char **argv ) { int height=7; int verbose_flag=7; int debug_flag=7; + char ** methodlist; struct optNameValue * optlist; - + optStruct3 opt; unsigned int option_def_index = 0; optEntry * option_def; MALLOCARRAY(option_def, 100); - OPTENT3(0, "help", OPT_FLAG, &help_flag, &help_spec, 0); - OPTENT3(0, "height", OPT_INT, &height, &height_spec, 0); - OPTENT3('n', "name", OPT_STRING, &name, &name_spec, 0); - OPTENT3('v', "verbose", OPT_FLAG, &verbose_flag, NULL, 0); - OPTENT3('g', "debug", OPT_FLAG, &debug_flag, NULL, 0); - OPTENT3(0, "options", OPT_NAMELIST, &optlist, NULL, 0); + OPTENT3(0, "help", OPT_FLAG, &help_flag, &help_spec, 0); + OPTENT3(0, "height", OPT_INT, &height, &height_spec, 0); + OPTENT3('n', "name", OPT_STRING, &name, &name_spec, 0); + OPTENT3('v', "verbose", OPT_FLAG, &verbose_flag, NULL, 0); + OPTENT3('g', "debug", OPT_FLAG, &debug_flag, NULL, 0); + OPTENT3(0, "methods", OPT_STRINGLIST, &methodlist, NULL, 0); + OPTENT3(0, "options", OPT_NAMELIST, &optlist, NULL, 0); opt.opt_table = option_def; opt.short_allowed = 1; @@ -38,7 +40,7 @@ main ( int argc, char **argv ) { pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0); - + printf("argc=%d\n", argc); printf("help_flag=%d\n", help_flag); @@ -50,13 +52,24 @@ main ( int argc, char **argv ) { printf("verbose_flag=%d\n", verbose_flag); printf("debug_flag=%d\n", verbose_flag); + if (methodlist) { + unsigned int i; + printf("methods: "); + while (methodlist[i]) { + printf("'%s', ", methodlist[i]); + ++i; + } + free(methodlist); + } else + printf("No -options\n"); + if (optlist) { unsigned int i; while (optlist[i].name) { printf("option '%s' = '%s'\n", optlist[i].name, optlist[i].value); ++i; } - optDestroyNameValueList(optlist); + pm_optDestroyNameValueList(optlist); } else printf("No -options\n"); } @@ -116,7 +129,7 @@ typedef struct { * or pointer to function if type == OPT_FUNC. */ int flags; /* modifier flags. */ } optStruct; - + typedef struct { /* This structure describes a single program option in a form for use by the pm_optParseOptions3() function. @@ -124,10 +137,10 @@ typedef struct { char shortName; /* short option name. */ const char *longName; /* long option name, not including '--' or '-' */ optArgType type; /* option type. */ - void *arg; + void *arg; /* pointer to variable in which to return option's argument (or TRUE - if it's a flag option), or pointer to function if - type == OPT_FUNC. If the option is specified multiple times, only + if it's a flag option), or pointer to function if + type == OPT_FUNC. If the option is specified multiple times, only the rightmost one affects this return value. */ unsigned int *specified; @@ -136,7 +149,7 @@ typedef struct { */ int flags; /* modifier flags. */ } optEntry; - + typedef struct { /* This structure describes the options of a program in a form for @@ -146,20 +159,20 @@ typedef struct { /* The syntax may include short (i.e. one-character) options. These options may be stacked within a single token (e.g. -abc = -a -b -c). If this value is not true, the short option - member of the option table entry is meaningless and long + member of the option table entry is meaningless and long options may have either one or two dashes. */ unsigned char allowNegNum; /* boolean */ /* Anything that starts with - and then a digit is a numeric - parameter, not an option + parameter, not an option */ optStruct *opt_table; } optStruct2; typedef struct { /* Same as optStruct2, but for pm_optParseOptions3() */ - unsigned char short_allowed; - unsigned char allowNegNum; + unsigned char short_allowed; + unsigned char allowNegNum; optEntry *opt_table; } optStruct3; @@ -173,9 +186,9 @@ typedef struct { optStruct *option_def = malloc(100*sizeof(optStruct)); OPTENTRY('h', "help", OPT_FLAG, &help_flag, 0); OPTENTRY(0, "alphaout", OPT_STRING, &alpha_filename, 0); -*/ +*/ -/* If you name your variables option_def and option_def_index like in the +/* If you name your variables option_def and option_def_index like in the example above, everything's easy. If you want to use OPTENTRY with other variables, define macros OPTION_DEF and OPTION_DEF_INDEX before calling OPTENTRY. @@ -217,7 +230,10 @@ typedef struct { OPTENTRY(shortvalue, longvalue, typevalue, outputvalue, flagvalue) \ } -#define OPTENTINIT OPTION_DEF[0].type = OPT_END +#define OPTENTINIT \ + do {OPTION_DEF_INDEX=0; \ + OPTION_DEF[OPTION_DEF_INDEX].type = OPT_END; \ + } while (0) struct optNameValue { @@ -226,7 +242,7 @@ struct optNameValue { }; - + void pm_optSetFatalFunc(void (*f)(const char *, ...)); @@ -234,10 +250,10 @@ void pm_optParseOptions(int *argc, char *argv[], optStruct opt[], int allowNegNum); void -pm_optParseOptions2(int * const argc_p, char *argv[], const optStruct2 opt, +pm_optParseOptions2(int * const argc_p, char *argv[], const optStruct2 opt, const unsigned long flags); void -pm_optParseOptions3(int * const argc_p, char *argv[], const optStruct3 opt, +pm_optParseOptions3(int * const argc_p, char *argv[], const optStruct3 opt, const unsigned int optStructSize, const unsigned long flags); void diff --git a/lib/util/wordaccess.h b/lib/util/wordaccess.h deleted file mode 100644 index df0eaf12..00000000 --- a/lib/util/wordaccess.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef WORDACCESS_H_INCLUDED -#define WORDACCESS_H_INCLUDED - -/* These are facilities for accessing data in C programs in ways that - exploit the way the machine defines words in order to squeeze out - speed and CPU efficiency. - - In particular, routines in this file exploit the endianness of the - machine and use explicit machine instructions to access C - variables. - - A word is the amount of data that fits in a register; the amount of - data that a single machine instruction can process. For example, - on IA32, a word is 32 bits because a single load or store - instruction moves that many bits and a single add instruction - operates on that many bits. - - - These facilities revolve around two data types: wordInt and - wordIntBytes. - - wordint is an unsigned integer with precision (size) of one word. - It is just the number -- nothing is implied about how it is - represented in memory. - - wordintBytes is an array of bytes that represent a word-sized - unsigned integer. x[0] is the high order 8 digits of the binary - coding of the integer, x[1] the next highest 8 digits, etc. - Note that it has big-endian form, regardless of what endianness the - underlying machine uses. - - The actual size of word differs by machine. Usually it is 32 or 64 - bits. Logically it can be as small as one byte. Fixed bit sequences - in each program impose a lower limit of word width. For example, the - longest bit sequence in pbmtog3 has 13 bits, so an 8-bit word won't - work with that. - - We also assume that a char is 8 bits. - - HAVE_GCC_BITCOUNT and HAVE_GCC_BSWAP are set in pm_config.h - - BITS_PER_LONG is the number of bits in long int. -*/ - -#include "pm_config.h" - -#if defined(WORDACCESS_GENERIC) - /* User wants this, regardless of whether machine can do better */ - #include "wordaccess_generic.h" -#elif BYTE_ORDER == BIG_ENDIAN - #if UNALIGNED_OK - #include "wordaccess_be_unaligned.h" - #else - /* Sparc */ - #include "wordaccess_be_aligned.h" - #endif -#elif HAVE_GCC_BITCOUNT - #if (BITS_PER_LONG == 64) - /* AMD Athlon 64, Intel x86_64, Intel Itanium, etc. */ - #include "wordaccess_64_le.h" - #elif (BITS_PER_LONG == 32) - /* Intel x86_32 (80386, 80486, Pentium), etc. */ - #include "wordaccess_generic.h" - #else - /* Extremely rare case. - If long is neither 32 nor 64 bits, (say, 128) it comes here. - */ - #include "wordaccess_generic.h" - #endif -#else - /* Non GCC or GCC prior to v.3.4; little-endian */ - #include "wordaccess_generic.h" -#endif - -#endif diff --git a/lib/util/wordaccess_64_le.h b/lib/util/wordaccess_64_le.h deleted file mode 100644 index 4d148ad2..00000000 --- a/lib/util/wordaccess_64_le.h +++ /dev/null @@ -1,28 +0,0 @@ -/*============================================================================= - This file is the part of wordaccess.h for use under these - conditions: - - * GCC (>=3.4) (__builtin_clz appears in GCC 3.4) - * Little-Endian machines (IA64, X86-64, AMD64) - * 64 bit long - -=============================================================================*/ - -#include "intcode.h" - -typedef uint64_t wordint; -typedef unsigned char wordintBytes[sizeof(wordint)]; - - -static __inline__ wordint -bytesToWordint(wordintBytes const bytes) { - return (wordint) pm_uintFromBigend64(*(bigend64*)bytes); -} - - - -static __inline__ void -wordintToBytes(wordintBytes * const bytesP, - wordint const wordInt) { - *(bigend64*)bytesP = pm_bigendFromUint64(wordInt); -} diff --git a/lib/util/wordaccess_be_aligned.h b/lib/util/wordaccess_be_aligned.h deleted file mode 100644 index f3bbb841..00000000 --- a/lib/util/wordaccess_be_aligned.h +++ /dev/null @@ -1,35 +0,0 @@ -/*============================================================================= - This file is the part of wordaccess.h for use under with big-endian - machines that require word accesses to be word-aligned. -*===========================================================================*/ - -typedef unsigned long int wordint; -typedef unsigned char wordintBytes[sizeof(wordint)]; - -static __inline__ wordint -bytesToWordint(wordintBytes bytes) { - uint16_t const hi = *((uint16_t *) (bytes + 0)); - uint16_t const mh = *((uint16_t *) (bytes + 2)); - uint16_t const ml = *((uint16_t *) (bytes + 4)); - uint16_t const lo = *((uint16_t *) (bytes + 6)); - return - (((wordint) hi) << 48) | - (((wordint) mh) << 32) | - (((wordint) ml) << 24) | - (((wordint) lo) << 0); -} - - - -static __inline__ void -wordintToBytes(wordintBytes * const bytesP, - wordint const wordInt) { - uint16_t const hi = ((wordInt >> 48) & 0xFF); - uint16_t const mh = ((wordInt >> 32) & 0xFF); - uint16_t const ml = ((wordInt >> 24) & 0xFF); - uint16_t const lo = ((wordInt >> 0) & 0xFF); - *(uint16_t *)(bytesP + 0) = hi; - *(uint16_t *)(bytesP + 2) = mh; - *(uint16_t *)(bytesP + 4) = ml; - *(uint16_t *)(bytesP + 6) = lo; -} diff --git a/lib/util/wordaccess_be_unaligned.h b/lib/util/wordaccess_be_unaligned.h deleted file mode 100644 index 95b68ac7..00000000 --- a/lib/util/wordaccess_be_unaligned.h +++ /dev/null @@ -1,20 +0,0 @@ -/*============================================================================= - This file is the part of wordaccess.h for use on a big-endian machine - that does not require word accesses to be word-aligned. -*===========================================================================*/ - -typedef unsigned long int wordint; -typedef unsigned char wordintBytes[sizeof(wordint)]; - -static __inline__ wordint -bytesToWordint(wordintBytes bytes) { - return *((wordint *)bytes); -} - - - -static __inline__ void -wordintToBytes(wordintBytes * const bytesP, - wordint const wordInt) { - *(wordint *)bytesP = wordInt; -} diff --git a/lib/util/wordaccess_generic.h b/lib/util/wordaccess_generic.h deleted file mode 100644 index 6e0a20ef..00000000 --- a/lib/util/wordaccess_generic.h +++ /dev/null @@ -1,29 +0,0 @@ -/*============================================================================= - - This file is the part of wordaccess.h for use under any of these - conditions: - - * Compiler other than GCC - * GCC before version 3.4 - * Requested by the user with WORDACCESS_GENERIC -=============================================================================*/ - -#include "intcode.h" - -typedef uint32_t wordint; -typedef unsigned char wordintBytes[sizeof(wordint)]; - - -static __inline__ wordint -bytesToWordint(wordintBytes const bytes) { - - return (wordint) pm_uintFromBigend32( * (bigend32*) bytes); -} - - -static __inline__ void -wordintToBytes(wordintBytes * const bytesP, - wordint const wordInt) { - - * (bigend32*) bytesP = pm_bigendFromUint32((uint32_t)wordInt); -} diff --git a/lib/util/wordintclz.h b/lib/util/wordintclz.h deleted file mode 100644 index 32e6ade8..00000000 --- a/lib/util/wordintclz.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef WORDINTCLZ_H_INCLUDED -#define WORDINTCLZ_H_INCLUDED - -#if (!defined(WORDACCESS_GENERIC) && HAVE_GCC_BITCOUNT ) -/* - Compiler is GCC and has __builtin_clz() - wordint is long - - __builtin_clz is available on GCC 3.4 and above - - Note that the clz scheme does not work and requires adjustment - if long type does not make use of all bits for data storage. - - This is unlikely. According to GNU MP (http://www.swox.com/gmp/), - in rare cases such as Cray, there are smaller data types that take up - the same space as long, but leave the higher bits silent. - Currently, there are no known such cases for data type long. - */ - -static __inline__ unsigned int -wordintClz(wordint const x){ - - assert(sizeof(unsigned long int) == sizeof(wordint)); - - if (x == 0) - return sizeof(wordint) * 8; - else - return (__builtin_clzl( (unsigned long int) x )); -} - -#else - -/* wordint is uint32_t: exactly 32 bits wide */ - -static unsigned char const clz8[256]= { - 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - - - -static __inline__ unsigned int -clz16(wordint const x) { - - if (x >> 8 != 0) - return clz8[x >> 8]; - else - return clz8[x] + 8; -} - - - -static __inline__ unsigned int -clz32(wordint const x) { - - if (x >> 16 != 0) - return clz16(x >> 16); - else - return clz16(x) + 16; -} - - - -static __inline__ unsigned int -wordintClz(wordint const x) { - - assert(sizeof(wordint) == 4); - - return clz32(x); -} - -/* Another way to calculate leading zeros: - x == 0 ? 32 : 31 - floor(log(x)/log(2)) - (Beware: insufficient precision will cause errors) -*/ - -#endif - -#endif |