+++ /dev/null
-/*
- * libtu/numparser2.h
- *
- * Copyright (c) Tuomo Valkonen 1999-2002.
- *
- * You may distribute and modify this library under the terms of either
- * the Clarified Artistic License or the GNU LGPL, version 2.1 or later.
- */
-
-#define MAX_MANTISSA 10 /* should be enough for our needs */
-#define ULONG_SIZE (sizeof(ulong)*8)
-
-enum{
- NPNUM_INT,
- NPNUM_FLOAT
-};
-
-#ifdef NP_SIMPLE_IMPL
-
-typedef struct _NPNum{
- int type;
- int base;
- bool negative;
- double fval;
- ulong ival;
-} NPNum;
-
-#define NUM_INIT {0, 0, 0, 0.0, 0}
-
-static int npnum_mulbase_add(NPNum *num, long base, long v)
-{
- double iold=num->ival;
-
- num->fval=num->fval*base+(double)v;
-
- num->ival*=base;
-
- if(num->ival<iold)
- num->type=NPNUM_FLOAT;
-
- num->ival+=v;
-
- return 0;
-}
-
-#else /* NP_SIMPLE_IMPL */
-
-typedef struct _NPNum{
- unsigned char nmantissa;
- int type;
- int base;
- bool negative;
- ulong mantissa[MAX_MANTISSA];
- long exponent;
-} NPNum;
-
-#define NUM_INIT {0, 0, 0, 0, {0,}, 0}
-
-#define ADD_EXP(NUM, X) (NUM)->exponent+=(X);
-
-#if defined(__GNUG__) && defined(i386) && !defined(NP_NO_I386_ASM)
- #define NP_I386_ASM
-#endif
-
-static int npnum_mulbase_add(NPNum *num, long base, long v)
-{
- long i, j;
- ulong overflow;
-#ifndef NP_I386_ASM
- ulong val;
-#endif
-
- for(i=num->nmantissa;i>=0;i--){
-#ifdef NP_I386_ASM
- __asm__("mul %4\n"
- : "=a" (num->mantissa[i]), "=d" (overflow)
- : "0" (num->mantissa[i]), "1" (0), "q" (base)
- : "eax", "edx");
-#else
- overflow=0;
- val=num->mantissa[i];
-
- if(val<ULONG_MAX/base){
- val*=base;
- }else if(val){
- ulong tmp=val;
- ulong old=val;
- for(j=0; j<base; j++){
- val+=tmp;
- if(val<=old)
- overflow++;
- old=val;
- }
- }
- num->mantissa[i]=val;
-#endif
- if(overflow){
- if(i==num->nmantissa){
- if(num->nmantissa==MAX_MANTISSA)
- return E_TOKZ_TOOBIG;
- num->nmantissa++;
- }
- num->mantissa[i+1]+=overflow;
- }
- }
- num->mantissa[0]+=v;
-
- return 0;
-}
-
-#undef NP_I386_ASM
-
-#endif /* NP_SIMPLE_IMPL */
-
-
-/* */
-
-
-static bool is_end(int c)
-{
- /* oops... EOF was missing */
- return (c==EOF || (c!='.' && ispunct(c)) || isspace(c) || iscntrl(c));
-}
-
-
-/* */
-
-
-static int parse_exponent(NPNum *num, Tokenizer *tokz, int c)
-{
- long exp=0;
- bool neg=FALSE;
- int err=0;
-
- c=GETCH();
-
- if(c=='-' || c=='+'){
- if(c=='-')
- neg=TRUE;
- c=GETCH();
- }
-
- for(; 1; c=GETCH()){
- if(isdigit(c)){
- exp*=10;
- exp+=c-'0';
- }else if(is_end(c)){
- UNGETCH(c);
- break;
- }else{
- err=E_TOKZ_NUMFMT;
- }
- }
-
- if(neg)
- exp*=-1;
-
-#ifndef NP_SIMPLE_IMPL
- ADD_EXP(num, exp);
-#else
- num->fval*=pow(num->base, exp);
-#endif
- return err;
-}
-
-
-static int parse_number(NPNum *num, Tokenizer *tokz, int c)
-{
- int base=10;
- int dm=1;
- int err=0;
- int tmp;
-#ifdef NP_SIMPLE_IMPL
- double divisor=base;
-#endif
-
- if(c=='-' || c=='+'){
- if(c=='-')
- num->negative=TRUE;
- c=GETCH();
- if(!isdigit(c))
- err=E_TOKZ_NUMFMT;
- }
-
- if(c=='0'){
- dm=0;
- c=GETCH();
- if(c=='x' || c=='X'){
- base=16;
- c=GETCH();
- }else if(c=='b' || c=='B'){
- base=2;
- c=GETCH();
- }else if('0'<=c && c<='7'){
- base=8;
- }else{
- dm=2;
- }
- }
-
- num->base=base;
-
- for(; 1; c=GETCH()){
- if((c=='e' || c=='E') && dm!=0){
- if(dm<2){
- err=E_TOKZ_NUMFMT;
- continue;
- }
- tmp=parse_exponent(num, tokz, c);
- if(err==0)
- err=tmp;
- break;
- }
-
- if(isxdigit(c)){
- if('0'<=c && c<='9')
- c-='0';
- else if(isupper(c))
- c-='A'-10;
- else
- c-='a'-10;
-
- if(c>=base)
- err=E_TOKZ_NUMFMT;
-
-#ifdef NP_SIMPLE_IMPL
- if(dm==3){
- num->fval+=(double)c/divisor;
- divisor*=base;
- }else
-#endif
- {
- tmp=npnum_mulbase_add(num, base, c);
- if(err==0)
- err=tmp;
- }
-
- if(dm==1)
- dm=2;
-#ifndef NP_SIMPLE_IMPL
- else if(dm==3)
- ADD_EXP(num, -1);
-#endif
- continue;
- }
-
- if(c=='.'){
- if(dm!=2){
- err=E_TOKZ_NUMFMT;
- }
- dm=3;
-#ifdef NP_SIMPLE_IMPL
- num->type=NPNUM_FLOAT;
- divisor=base;
-#endif
- continue;
- }
-
- if(is_end(c)){
- UNGETCH(c);
- break;
- }
-
- err=E_TOKZ_NUMFMT;
- }
-
-#ifndef NP_SIMPLE_IMPL
- num->type=(num->exponent==0 ? NPNUM_INT : NPNUM_FLOAT);
-#endif
-
- return err;
-}