Mercurial > ecos
diff packages/net/snmp/lib/current/src/int64.c @ 103:95f3e12a6327 ecos-sw-2000-06-23
Merge from eCos master repository on 2000-06-23-16:41:10-BST
| author | jlarmour |
|---|---|
| date | Fri, 23 Jun 2000 17:06:31 +0000 |
| parents | |
| children | e0c0827131d1 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/packages/net/snmp/lib/current/src/int64.c @@ -0,0 +1,456 @@ +//========================================================================== +// +// ./lib/current/src/int64.c +// +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//####UCDSNMPCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from the UCD-SNMP +// project, <http://ucd-snmp.ucdavis.edu/> from the University of +// California at Davis, which was originally based on the Carnegie Mellon +// University SNMP implementation. Portions of this software are therefore +// covered by the appropriate copyright disclaimers included herein. +// +// The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2" +// ------------------------------------------- +// +//####UCDSNMPCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-05-30 +// Purpose: Port of UCD-SNMP distribution to eCos. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== +/******************************************************************** + Copyright 1989, 1991, 1992 by Carnegie Mellon University + + Derivative Work - +Copyright 1996, 1998, 1999, 2000 The Regents of the University of California + + All Rights Reserved + +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 appears in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU and The Regents of +the University of California not be used in advertising or publicity +pertaining to distribution of the software without specific written +permission. + +CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR +THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING +FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ +/** file: test.c - test of 64-bit integer stuff +* +* +* 21-jan-1998: David Perkins <dperkins@dsperkins.com> +* +*/ + +#include <config.h> +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#if HAVE_STRING_H +#include <string.h> +#else +#include <strings.h> +#endif +#if HAVE_WINSOCK_H +#include <winsock.h> +#endif +#include "asn1.h" +#include "int64.h" + +#define TRUE 1 +#define FALSE 0 + +/** divBy10 - divide an unsigned 64-bit integer by 10 +* +* call with: +* u64 - number to be divided +* pu64Q - location to store quotient +* puR - location to store remainder +* +*/ +void +divBy10(U64 u64, + U64 *pu64Q, + unsigned int *puR) +{ + unsigned long ulT; + unsigned long ulQ; + unsigned long ulR; + + + /* top 16 bits */ + ulT = (u64.high>>16) & 0x0ffff; + ulQ = ulT/10; + ulR = ulT%10; + pu64Q->high = ulQ<<16; + + /* next 16 */ + ulT = (u64.high & 0x0ffff); + ulT += (ulR<<16); + ulQ = ulT/10; + ulR = ulT%10; + pu64Q->high = pu64Q->high | ulQ; + + /* next 16 */ + ulT = ((u64.low>>16) & 0x0ffff) + (ulR<<16); + ulQ = ulT/10; + ulR = ulT%10; + pu64Q->low = ulQ<<16; + + /* final 16 */ + ulT = (u64.low & 0x0ffff); + ulT += (ulR<<16); + ulQ = ulT/10; + ulR = ulT%10; + pu64Q->low = pu64Q->low | ulQ; + + *puR = (unsigned int)(ulR); + + +} /* divBy10 */ + + +/** multBy10 - multiply an unsigned 64-bit integer by 10 +* +* call with: +* u64 - number to be multiplied +* pu64P - location to store product +* +*/ +void +multBy10(U64 u64, + U64 *pu64P) +{ + unsigned long ulT; + unsigned long ulP; + unsigned long ulK; + + + /* lower 16 bits */ + ulT = u64.low & 0x0ffff; + ulP = ulT * 10; + ulK = ulP>>16; + pu64P->low = ulP & 0x0ffff; + + /* next 16 */ + ulT = (u64.low>>16) & 0x0ffff; + ulP = (ulT * 10) + ulK; + ulK = ulP>>16; + pu64P->low = (ulP & 0x0ffff)<<16 | pu64P->low; + + /* next 16 bits */ + ulT = u64.high & 0x0ffff; + ulP = (ulT * 10) + ulK; + ulK = ulP>>16; + pu64P->high = ulP & 0x0ffff; + + /* final 16 */ + ulT = (u64.high>>16) & 0x0ffff; + ulP = (ulT * 10) + ulK; + ulK = ulP>>16; + pu64P->high = (ulP & 0x0ffff)<<16 | pu64P->high; + + +} /* multBy10 */ + + +/** incrByU16 - add an unsigned 16-bit int to an unsigned 64-bit integer +* +* call with: +* pu64 - number to be incremented +* u16 - amount to add +* +*/ +void +incrByU16(U64 *pu64, + unsigned int u16) +{ + unsigned long ulT1; + unsigned long ulT2; + unsigned long ulR; + unsigned long ulK; + + + /* lower 16 bits */ + ulT1 = pu64->low; + ulT2 = ulT1 & 0x0ffff; + ulR = ulT2 + u16; + ulK = ulR>>16; + if (ulK == 0) { + pu64->low = ulT1 + u16; + return; + } + + /* next 16 bits */ + ulT2 = (ulT1>>16) & 0x0ffff; + ulR = ulT2+1; + ulK = ulR>>16; + if (ulK == 0) { + pu64->low = ulT1 + u16; + return; + } + + /* next 32 - ignore any overflow */ + pu64->low = (ulT1 + u16) & 0x0FFFFFFFFL; + pu64->high++; + +} /* incrByV16 */ + +void +incrByU32(U64 *pu64, + unsigned int u32) +{ + unsigned int tmp; + tmp = pu64->low; + pu64->low += u32; + if (pu64->low < tmp) + pu64->high++; +} + +/* pu64out = pu64one - pu64two */ +void +u64Subtract(U64 *pu64one, + U64 *pu64two, + U64 *pu64out) +{ + if (pu64one->low > pu64two->low) { + pu64out->low = 0xffffffff - pu64two->low + pu64one->low + 1; + pu64out->high = pu64one->high - pu64two->high - 1; + } else { + pu64out->low = pu64one->low - pu64two->low; + pu64out->high = pu64one->high - pu64two->high; + } +} + +/** zeroU64 - set an unsigned 64-bit number to zero +* +* call with: +* pu64 - number to be zero'ed +* +*/ +void +zeroU64(U64 *pu64) +{ + + pu64->low = 0; + pu64->high = 0; +} /* zeroU64 */ + + +/** isZeroU64 - check if an unsigned 64-bit number is +* +* call with: +* pu64 - number to be zero'ed +* +*/ +int +isZeroU64(U64 *pu64) +{ + + if ((pu64->low == 0) && (pu64->high == 0)) + return(TRUE); + else + return(FALSE); + +} /* isZeroU64 */ + +void +printU64(char * buf, /* char [I64CHARSZ+1]; */ + U64 *pu64) +{ + U64 u64a; + U64 u64b; + + char aRes [I64CHARSZ+1]; + unsigned int u; + int j; + + u64a.high = pu64->high; + u64a.low = pu64->low; + aRes[I64CHARSZ] = 0; + for (j = 0; j < I64CHARSZ; j++) { + divBy10(u64a, &u64b, &u); + aRes[(I64CHARSZ-1)-j] = (char)('0' + u); + u64a.high = u64b.high; + u64a.low = u64b.low; + if (isZeroU64(&u64a)) + break; + } + strcpy(buf, &aRes[(I64CHARSZ-1)-j]); +} + +void +printI64(char * buf, /* char [I64CHARSZ+1]; */ + U64 *pu64) +{ + U64 u64a; + U64 u64b; + + char aRes [I64CHARSZ+1]; + unsigned int u; + int j, sign=0; + + if (pu64->high & 0x80000000) { + u64a.high = ~pu64->high; + u64a.low = ~pu64->low; + sign = 1; + incrByU32(&u64a, 1); /* bit invert and incr by 1 to print 2s complement */ + } else { + u64a.high = pu64->high; + u64a.low = pu64->low; + } + + aRes[I64CHARSZ] = 0; + for (j = 0; j < I64CHARSZ; j++) { + divBy10(u64a, &u64b, &u); + aRes[(I64CHARSZ-1)-j] = (char)('0' + u); + u64a.high = u64b.high; + u64a.low = u64b.low; + if (isZeroU64(&u64a)) + break; + } + if (sign == 1) { + aRes[(I64CHARSZ-1)-j-1] = '-'; + strcpy(buf, &aRes[(I64CHARSZ-1)-j-1]); + return; + } + strcpy(buf, &aRes[(I64CHARSZ-1)-j]); +} + +int +read64(U64 *i64, + const char *string) +{ + U64 i64p; + unsigned int u; + int sign = 0; + int ok = 0; + + zeroU64(i64); + if (*string == '-') { + sign = 1; + string++; + } + + while (*string && isdigit(*string)) { + ok = 1; + u = *string - '0'; + multBy10(*i64, &i64p); + memcpy(i64, &i64p, sizeof(i64p)); + incrByU16(i64, u); + string++; + } + if (sign) { + i64->high = ~i64->high; + i64->low = ~i64->low; + incrByU16(i64,1); + } + return ok; +} + + + + +#ifdef TESTING +void +main(int argc, char *argv[]) +{ + int i; + int j; + int l; + unsigned int u; + U64 u64a; + U64 u64b; +#define MXSZ 20 + char aRes[MXSZ+1]; + + + if (argc < 2) { + printf("This program takes numbers from the command line\n" + "and prints them out.\n" + "Usage: test <unsignedInt>...\n"); + exit(1); + } + + aRes[MXSZ] = 0; + + for (i = 1; i < argc; i++) { + l = strlen(argv[i]); + zeroU64(&u64a); + for (j = 0; j < l; j++) { + if (!isdigit(argv[i][j])) { + printf("Argument is not a number \"%s\"\n", argv[i]); + exit(1); + } + u = argv[i][j] - '0'; + multBy10(u64a, &u64b); + u64a = u64b; + incrByU16(&u64a, u); + } + + printf("number \"%s\" in hex is '%08x%08x'h\n", + argv[i], u64a.high, u64a.low); + + printf("number is \"%s\"\n", printU64(&u64a)); + for (j = 0; j < MXSZ; j++) { + divBy10(u64a, &u64b, &u); + aRes[(MXSZ-1)-j] = (char)('0' + u); + u64a = u64b; + if (isZeroU64(&u64a)) + break; + } + + printf("number is \"%s\"\n", &aRes[(MXSZ-1)-j]); + } + exit(0); +} /* main */ +#endif /* TESTING */ + +/* file: test.c */ +
