/* Time-stamp: <2007-09-22 19:43:29 poser> */ /* * Copyright (C) 2006-2007 William J. Poser. * This library is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU Lesser General * Public License as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define TGE(op1, op2) (mpz_cmp(op1, op2) >= 0 ) #define TGT(op1, op2) (mpz_cmp(op1, op2) > 0 ) #define TLE(op1, op2) (mpz_cmp(op1, op2) <= 0 ) #define TLT(op1, op2) (mpz_cmp(op1, op2) < 0 ) #define TEQ(op1, op2) (mpz_cmp(op1, op2) == 0 ) #define TNE(op1, op2) (mpz_cmp(op1, op2) != 0 ) #define UGE(op1, op2) (mpz_cmp_ui(op1, op2) >= 0 ) #define UGT(op1, op2) (mpz_cmp_ui(op1, op2) > 0 ) #define ULE(op1, op2) (mpz_cmp_ui(op1, op2) <= 0 ) #define ULT(op1, op2) (mpz_cmp_ui(op1, op2) < 0 ) #define UEQ(op1, op2) (mpz_cmp_ui(op1, op2) == 0 ) #define UNE(op1, op2) (mpz_cmp_ui(op1, op2) != 0 ) /* * These functions convert UTF-32 strings representing integers in various * writing systems to unsigned long integers or to ASCII decimal strings * in the Indo-Arabic number system. */ #define ucslen(x) wcslen((signed long *) x) #define ucscpy(x,y) (UTF32 *)wcscpy((signed long *)x,(signed long *)y) #define ucscat(x,y) (UTF32 *)wcscat((signed long *)x,(signed long *)y) #define ucschr(x,y) (UTF32 *)wcschr((signed long *)x,(signed long)y) #define ucsrchr(x,y) (UTF32 *)wcsrchr((signed long *)x,(signed long)y) #define UNINUM #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "unicode.h" #include "uninum.h" #include "nsdefs.h" #include "exitcode.h" #ifdef HAVE_LOCALE_H #include #endif int uninum_err; /* Exported for error detection */ UTF32 uninum_badchar; /* Exported for error detection */ UTF16 tcl_uninum_badchar; /* Exported for error detection */ short uninum_ns_type; /* Exported for sanity-checking */ /* Exported for parameter setting */ int Uninum_Input_Base = 10; int Uninum_Output_Base = 10; int Uninum_Output_General_Group_Size = 0; int Uninum_Output_First_Group_Size = 3; UTF16 Uninum_Output_Group_Separator = 0x002C; /* Comma */ int Uninum_Generate_Roman_With_Bar_P = 0; /* We're currently not dealing with non-integers - this is just forward-looking */ static UTF32 Uninum_Output_Decimal_Separator = 0x002E; /* (10^97)-1, in hex for compactness and speed of conversion to binary */ #define MAXCHINESEHEX "4AE825771DC07672DDD0F8E8AC39250971AC4210CECB6F656CAEB9109FFFFFFFFFFFFFFFFFFFFFFFF" #define CYRILLIC_THOUSANDS_SIGN 0x0482 #define CYRILLIC_TITLO 0x0483 #define TENGWAR_DECIMAL_MARKER 0xE06C #define TENGWAR_DUODECIMAL_MARKER 0xE06D #define TENGWAR_DUODECIMAL_LSD_MARKER 0xE06E #define TENGWAR_DEC 0xE06A #define TENGWAR_EL 0xE06B char *uninum_version(void) { return(VERSION); } #ifdef HAVE_LOCALECONV #ifdef HAVE_SETLOCALE void GetLocaleGroupInfo (){ struct lconv *lcptr; setlocale(LC_NUMERIC,""); lcptr = localeconv(); if(lcptr == NULL) { fprintf(stderr,"Attempt to obtain locale information was unsuccessful.\n"); return; } Uninum_Output_Group_Separator = (UTF16) (lcptr->thousands_sep[0]); Uninum_Output_First_Group_Size = lcptr->grouping[0]; if(lcptr->grouping[1] != 0) Uninum_Output_General_Group_Size = lcptr->grouping[1]; else Uninum_Output_General_Group_Size = Uninum_Output_First_Group_Size; } #endif #endif /* Auxiliary functions */ unsigned long ipow(int base, int cnt) { int i; unsigned long Result; i = 1; Result = 1; while (i++ <= cnt) Result *= base; return Result; } /* * Copy a string and return a pointer to the * terminal null of the copy. The target must * have sufficient storage. */ static char *strpcpy(char *dest, const char *src) { char *t; const char *s; s = src; t = dest; while (*s != 0) { *t++ = *s++; } *t = 0; return(t); } /* * Case-insenstive ascii string comparison. * Emulates BSD 4.4 function emulated by GNU */ static int mystrcasecmp(char *a, char *b) { char ac; char bc; while(*a != '\0') { ac = tolower(*a++); bc = tolower(*b++); if(ac < bc) return (-1); if(ac > bc) return (1); } if(*b != '\0') return (-1); return (0); } /* * Copy a wide string and return a pointer to the * terminal null of the copy. The target must * have sufficient storage. * This emulates the GNU extension wcpcpy(). */ static UTF32 *ucpcpy(UTF32 *dest, const UTF32 *src) { UTF32 *t; const UTF32 *s; s = src; t = dest; while (*s != 0x0000) { *t++ = *s++; } *t = 0x0000; return(t); } /* * Reverse a wide string in place. */ static UTF32 *wcsrev(UTF32 *s) { UTF32 *p; UTF32 *q; UTF32 *h; UTF32 t; p = s; q = s + ucslen(s)-1; h = s + (ucslen(s)/2); while (q >= h) { t = *p; *p++ = *q; *q-- = t; } return(s); } /* * Prepend a character to a string, returning new storage * and freeing the old. */ static UTF32 *Prepend(UTF32 *s, UTF32 c) { int len; UTF32 *new; len = ucslen(s); new = malloc(sizeof(UTF32) * (len + 2)); if(new) { new[0] = c; new[1] = 0x0000; ucscpy(new+1,s); } free(s); return(new); } /* Remove "thousands separator"s */ UTF32 *wcStripSeparators(UTF32 *s) { UTF32 *t; UTF32 *o; UTF32 c; o = t = s; while ((c = *s++) != 0x0000){ switch(c) { case 0x0020: /* Space */ case 0x0027: /* Apostrophe */ case 0x002C: /* Comma */ case 0x002E: /* Period */ case 0x066C: /* Arabic thousands separator */ case 0x1361: /* Ethiopic wordspace */ case 0x3000: /* Ideographic space */ /* We can't add the Braille comma U+2802 here because Russian Braille uses the same character for the digit "1" */ break; default: *t++ = c; } } *t = 0x0000; return o; } /* * It is the caller's responsability to free the original storage. */ UTF32 *wcDelimitNumber( UTF32 *number, UTF16 gs, /* Group separator character */ UTF32 ds, /* Decimal point character */ int GroupSize, /* Number of digits in groups in general */ int FirstGroupSize /* Number of digits in low-order group */ ) { int New_Size; /* Characters needed for delimited string */ int length; /* Length of input string */ int commas; /* Number of delimiters to insert */ int Comma_Cnt; /* Number of delimiters inserted so far */ int digits; /* Number of digits preceding decimal point */ int cnt; /* Number of digits processed */ int i; UTF32 *new; /* String in which to write delimited number */ UTF32 *point; /* Location of decimal point */ UTF32 *pos; /* Current position in original number */ UTF32 *npos; /* Current position in new number */ UTF32 *Non_Space_Number; /* Location of first non-space character in number */ /* Sanity check */ if( (GroupSize < 2) || (FirstGroupSize < 2)) { commas = 0; goto newmem; } length = ucslen(number); point = ucsrchr(number,(UTF32) '.'); if(point == NULL) point = number+(length-1); else point-=1; /* Point now points at last digit preceding decimal/end */ Non_Space_Number = ucsrchr(number,0x0020); if(Non_Space_Number == NULL) Non_Space_Number = number; else Non_Space_Number+=1; digits = 1+point - Non_Space_Number; if(digits > FirstGroupSize) { commas = 1 + ((digits-FirstGroupSize-1)/GroupSize); } else commas = 0; newmem: New_Size = length + commas; new = (UTF32 *) malloc((New_Size + 1) * sizeof(UTF32)); if(new){ if (commas == 0) return ucscpy(new,number); /* First copy right hand part of number, up to and including decimal point */ pos = number+length; npos = new+New_Size; for(; pos > point;) *npos-- = *pos--; /* Now copy lefthand part, inserting delimiters as we go */ Comma_Cnt = cnt = 0; if(FirstGroupSize != GroupSize) { for (i = 0; i < FirstGroupSize; i++) *npos-- = *pos--; /* Copy low group */ *npos-- = (UTF32) gs; *npos-- = *pos--; /* Low digit of second group */ Comma_Cnt = cnt = 1; } while(pos >= Non_Space_Number){ *npos-- = *pos--; if( (++cnt % GroupSize == 0) && (Comma_Cnt++ < commas )) *npos-- = (UTF32) gs; } while(pos >= number) *npos-- = *pos--; /* Copy leading spaces, if any */ return new; } } /* * Returns a null-terminated wide string containing * the specified character. */ static UTF32 *MakeSingleDigitString(UTF32 c) { UTF32 *new; new = malloc(sizeof(UTF32) * 2); if(!new) { uninum_err = NS_ERROR_OUTOFMEMORY; return NULL; } new[0] = c; new[1] = 0L; return(new); } struct ns {char *s; int c; short type;}; static struct ns NumberSystemList[] = { "Aegean",NS_AEGEAN,NS_TYPE_SAFE, "All",NS_ALL,NS_TYPE_SPECIAL, "Any",NS_ANY,NS_TYPE_SPECIAL, "Arabic_Alphabetic",NS_ARABIC_ALPHABETIC,NS_TYPE_SAFE, "Arabic_Persian",NS_PERSO_ARABIC,NS_TYPE_SAFE, "Arabic_Western",NS_ARABIC_WESTERN,NS_TYPE_SAFE, "Armenian",NS_ARMENIAN_ALPHABETIC,NS_TYPE_SAFE, "Balinese",NS_BALINESE,NS_TYPE_SAFE, "Bengali",NS_BENGALI,NS_TYPE_SAFE, "Burmese",NS_BURMESE,NS_TYPE_SAFE, "Chinese",NS_CHINESE_GENERIC,NS_TYPE_COVER, "Chinese_Counting_Rod_Early",NS_CHINESE_COUNTING_ROD_EARLY_WITH_ZERO,NS_TYPE_SAFE, "Chinese_Counting_Rod_Late",NS_CHINESE_COUNTING_ROD_LATE_WITH_ZERO,NS_TYPE_SAFE, "Chinese_Counting_Rod_Early_No_Zero",NS_CHINESE_COUNTING_ROD_EARLY_WITHOUT_ZERO,NS_TYPE_SAFE, "Chinese_Counting_Rod_Late_No_Zero",NS_CHINESE_COUNTING_ROD_LATE_WITHOUT_ZERO,NS_TYPE_SAFE, "Chinese_Legal_Simplified",NS_CHINESE_LEGAL_SIMPLIFIED,NS_TYPE_SAFE, "Chinese_Legal_Traditional",NS_CHINESE_LEGAL_TRADITIONAL,NS_TYPE_SAFE, "Chinese_Regular_Simplified",NS_CHINESE_REGULAR_SIMPLIFIED,NS_TYPE_SAFE, "Chinese_Regular_Traditional",NS_CHINESE_REGULAR_TRADITIONAL,NS_TYPE_SAFE, "Chinese_Regular_Place",NS_CHINESE_REGULAR_PLACE,NS_TYPE_SAFE, "Common_Braille",NS_COMMON_BRAILLE,NS_TYPE_SAFE, "Counting_Rod",NS_CHINESE_COUNTING_ROD_GENERIC,NS_TYPE_COVER, "Cyrillic",NS_CYRILLIC_ALPHABETIC,NS_TYPE_SAFE, "Devanagari",NS_DEVANAGARI,NS_TYPE_SAFE, "Egyptian",NS_EGYPTIAN,NS_TYPE_SAFE, "Ethiopic",NS_ETHIOPIC,NS_TYPE_SAFE, "Ewellic_Decimal",NS_EWELLIC_DECIMAL,NS_TYPE_SAFE, "Ewellic_Hexadecimal",NS_EWELLIC_HEX,NS_TYPE_SAFE, "French_Braille",NS_FRENCH_BRAILLE,NS_TYPE_SAFE, "Glagolitic",NS_GLAGOLITIC_ALPHABETIC,NS_TYPE_SAFE, "Greek",NS_GREEK_ALPHABETIC_UPPER,NS_TYPE_COVER, "Greek_Lower",NS_GREEK_ALPHABETIC_LOWER,NS_TYPE_SAFE, "Greek_Upper",NS_GREEK_ALPHABETIC_UPPER,NS_TYPE_SAFE, "Gujarati",NS_GUJARATI,NS_TYPE_SAFE, "Gurmukhi",NS_GURMUKHI,NS_TYPE_SAFE, "Hebrew",NS_HEBREW_GENERIC,NS_TYPE_COVER, "Hebrew_Early",NS_HEBREW_EARLY,NS_TYPE_SAFE, "Hebrew_Late",NS_HEBREW_LATE,NS_TYPE_SAFE, "Hexadecimal",NS_HEX,NS_TYPE_COVER, "Hexadecimal_Lower",NS_HEX_LOWER,NS_TYPE_SAFE, "Hexadecimal_Upper",NS_HEX_UPPER,NS_TYPE_SAFE, "Japanese_Regular_Simplified",NS_CHINESE_JAPANESE_REGULAR_SIMPLIFIED,NS_TYPE_SAFE, "Japanese_Regular_Traditional",NS_CHINESE_JAPANESE_REGULAR_TRADITIONAL,NS_TYPE_SAFE, "Japanese_Legal_Simplified",NS_CHINESE_JAPANESE_LEGAL_SIMPLIFIED,NS_TYPE_SAFE, "Japanese_Legal_Traditional",NS_CHINESE_JAPANESE_LEGAL_TRADITIONAL,NS_TYPE_SAFE, "Japanese_Western_Mixed",NS_CHINESE_JAPANESE_WESTERN_MIX,NS_TYPE_SAFE, "Kannada",NS_KANNADA,NS_TYPE_SAFE, "Kharoshthi",NS_KHAROSHTHI,NS_TYPE_SAFE, "Khmer",NS_KHMER,NS_TYPE_SAFE, "Klingon",NS_KLINGON,NS_TYPE_SAFE, "Lao",NS_LAO,NS_TYPE_SAFE, "Limbu",NS_LIMBU,NS_TYPE_SAFE, "Malayalam",NS_MALAYALAM,NS_TYPE_SAFE, "Mandarin_Legal_Simplified",NS_CHINESE_MANDARIN_LEGAL_SIMPLIFIED,NS_TYPE_SAFE, "Mandarin_Legal_Traditional",NS_CHINESE_MANDARIN_LEGAL_TRADITIONAL,NS_TYPE_SAFE, "Mandarin_Regular_Simplified",NS_CHINESE_MANDARIN_REGULAR_SIMPLIFIED,NS_TYPE_SAFE, "Mandarin_Regular_Traditional",NS_CHINESE_MANDARIN_REGULAR_TRADITIONAL,NS_TYPE_SAFE, "Mongolian",NS_MONGOLIAN,NS_TYPE_SAFE, "Mxedruli",NS_MXEDRULI,NS_TYPE_SAFE, "New_Tai_Lue",NS_NEW_TAI_LUE,NS_TYPE_SAFE, "Nko",NS_NKO,NS_TYPE_SAFE, "Old_Italic",NS_OLD_ITALIC,NS_TYPE_SAFE, "Old_Persian",NS_OLD_PERSIAN,NS_TYPE_SAFE, "Oriya",NS_ORIYA,NS_TYPE_SAFE, "Osmanya",NS_OSMANYA,NS_TYPE_SAFE, "Phoenician",NS_PHOENICIAN,NS_TYPE_SAFE, "Roman",NS_ROMAN_GENERIC,NS_TYPE_COVER, "Roman_Lower",NS_ROMAN_LOWER,NS_TYPE_SAFE, "Roman_Upper",NS_ROMAN_UPPER,NS_TYPE_SAFE, "Russian_Braille",NS_RUSSIAN_BRAILLE,NS_TYPE_SAFE, "Sinhala",NS_SINHALA,NS_TYPE_SAFE, "Suzhou",NS_CHINESE_SUZHOU,NS_TYPE_SAFE, "Tamil",NS_TAMIL_GENERIC,NS_TYPE_COVER, "Tamil_Place",NS_TAMIL_PLACE,NS_TYPE_SAFE, "Tamil_Traditional",NS_TAMIL_TRADITIONAL,NS_TYPE_SAFE, "Telugu",NS_TELUGU,NS_TYPE_SAFE, "Tengwar_Decimal",NS_TENGWAR_DECIMAL,NS_TYPE_SAFE, "Tengwar_Duodecimal",NS_TENGWAR_DUODECIMAL,NS_TYPE_SAFE, "Thai",NS_THAI,NS_TYPE_SAFE, "Tibetan",NS_TIBETAN,NS_TYPE_SAFE, "Verdurian",NS_VERDURIAN,NS_TYPE_SAFE, "Western",NS_WESTERN_GENERIC,NS_TYPE_COVER, "Western_Lower",NS_WESTERN_LOWER,NS_TYPE_SAFE, "Western_Upper",NS_WESTERN_UPPER,NS_TYPE_SAFE, "Xucuri_Lower",NS_XUCURI_LOWER,NS_TYPE_SAFE, "Xucuri_Upper",NS_XUCURI_UPPER,NS_TYPE_SAFE, "Unknown",NS_UNKNOWN,NS_TYPE_GUESS, "All_Zero",NS_ALLZERO,NS_TYPE_GUESS }; /* * Generate the list of available writing systems, * returning the next string on each call unless * the flag is 0, which resets to the start of the * sequence. * * which = 0 -> list specific names usable in both directions * which = 1 -> list cover terms suitable only for conversion of string to int */ char *ListNumberSystems (int flag, int which) { static int i = 0; if(flag == 0) i = 0; /* reset */ top: if (i < (sizeof(NumberSystemList)/sizeof(struct ns))) { if (NumberSystemList[i].type == (which? 2:1)) return NumberSystemList[i++].s; else { i++; goto top; } } i = 0; return NULL; } /* * We just use linear search for the time being. * Could switch to binary search for greater speed. */ int StringToNumberSystem (char *s) { int i; for (i=0; i < (sizeof(NumberSystemList)/sizeof(struct ns)); i++) { if (mystrcasecmp(s,NumberSystemList[i].s) == 0){ uninum_ns_type = NumberSystemList[i].type; return (NumberSystemList[i].c); } } return NS_UNKNOWN; } /* * We just use linear search for the time being. * Could switch to binary search for greater speed. */ char *NumberSystemToString (int ns) { int i; for (i=0; i < (sizeof(NumberSystemList)/sizeof(struct ns)); i++) { if (NumberSystemList[i].c == ns) return NumberSystemList[i].s; } return NULL; } /* * Return the maximum value expressible in the specified number system. * as a decimal ascii string, or if there is no limit, "unlimited". */ #define AEGEAN_LIMIT 99999 #define ARABIC_LIMIT 1999 #define ARMENIAN_LIMIT 9999 #define CYRILLIC_LIMIT 999 #define EGYPTIAN_LIMIT 9999999 #define GLAGOLITIC_LIMIT 9999 #define GREEK_LIMIT 9999 #define HEBREW_LIMIT 9999 #define KHAROSHTHI_LIMIT 999999 #define MXEDRULI_LIMIT 10000 #define OLD_ITALIC_LIMIT 999 #define OLD_PERSIAN_LIMIT 999 #define PHOENICIAN_LIMIT 999 #define ROMAN_LIMIT 9999 #define SINHALA_LIMIT 9999 #define TAMIL_LIMIT 999999 #define XUCURI_LIMIT 10000 char *UninumStringMaximumValue(int ns) { char *new; mpz_t MaxChinese; mpz_t Limit; mpz_init(Limit); switch(ns) { case NS_CHINESE_LEGAL_SIMPLIFIED: case NS_CHINESE_LEGAL_TRADITIONAL: case NS_CHINESE_REGULAR_SIMPLIFIED: case NS_CHINESE_REGULAR_TRADITIONAL: case NS_CHINESE_MANDARIN_LEGAL_SIMPLIFIED: case NS_CHINESE_MANDARIN_LEGAL_TRADITIONAL: case NS_CHINESE_MANDARIN_REGULAR_SIMPLIFIED: case NS_CHINESE_MANDARIN_REGULAR_TRADITIONAL: case NS_CHINESE_JAPANESE_REGULAR_SIMPLIFIED: case NS_CHINESE_JAPANESE_REGULAR_TRADITIONAL: case NS_CHINESE_JAPANESE_WESTERN_MIX: case NS_CHINESE_JAPANESE_LEGAL_SIMPLIFIED: case NS_CHINESE_JAPANESE_LEGAL_TRADITIONAL: mpz_init_set_str(MaxChinese,MAXCHINESEHEX,16); new = malloc((mpz_sizeinbase(MaxChinese,10) + 1) * sizeof(char)); if(!new) {uninum_err = NS_ERROR_OUTOFMEMORY;return NULL;} (void) mpz_get_str(new,10,MaxChinese); mpz_clear(MaxChinese); return new; case NS_AEGEAN: mpz_set_ui(Limit,AEGEAN_LIMIT); break; case NS_ARABIC_ALPHABETIC: mpz_set_ui(Limit,ARABIC_LIMIT); break; case NS_ARMENIAN_ALPHABETIC: mpz_set_ui(Limit,ARMENIAN_LIMIT); break; case NS_CYRILLIC_ALPHABETIC: mpz_set_ui(Limit,CYRILLIC_LIMIT); break; case NS_EGYPTIAN: mpz_set_ui(Limit,EGYPTIAN_LIMIT); break; case NS_GLAGOLITIC_ALPHABETIC: mpz_set_ui(Limit,GLAGOLITIC_LIMIT); break; case NS_GREEK_ALPHABETIC_UPPER: case NS_GREEK_ALPHABETIC_LOWER: mpz_set_ui(Limit,GREEK_LIMIT); break; case NS_HEBREW_EARLY: case NS_HEBREW_LATE: mpz_set_ui(Limit,HEBREW_LIMIT); break; case NS_KHAROSHTHI: mpz_set_ui(Limit,KHAROSHTHI_LIMIT); break; case NS_MXEDRULI: mpz_set_ui(Limit,MXEDRULI_LIMIT); break; case NS_OLD_ITALIC: mpz_set_ui(Limit,OLD_ITALIC_LIMIT); break; case NS_OLD_PERSIAN: mpz_set_ui(Limit,OLD_PERSIAN_LIMIT); break; case NS_PHOENICIAN: mpz_set_ui(Limit,PHOENICIAN_LIMIT); break; case NS_ROMAN_UPPER: case NS_ROMAN_LOWER: mpz_set_ui(Limit,ROMAN_LIMIT); break; case NS_SINHALA: mpz_set_ui(Limit,SINHALA_LIMIT); break; case NS_TAMIL_TRADITIONAL: mpz_set_ui(Limit,TAMIL_LIMIT); break; case NS_XUCURI_LOWER: case NS_XUCURI_UPPER: mpz_set_ui(Limit,XUCURI_LIMIT); break; default: new = malloc (sizeof(char) * (1 + strlen("unlimited"))); if(!new) {uninum_err = NS_ERROR_OUTOFMEMORY;return NULL;} sprintf(new,"%s","unlimited"); return new; } new = malloc((mpz_sizeinbase(Limit,10) + 1) * sizeof(char)); if(!new) {uninum_err = NS_ERROR_OUTOFMEMORY;return NULL;} (void) mpz_get_str(new,10,Limit); mpz_clear(Limit); return new; } #define AEGEAN_BEGIN 0x10107 #define AEGEAN_END 0x10133 #define ARABIC_BEGIN 0x0660 #define ARABIC_END 0x066C #define ARABIC_ALPHABETIC_BEGIN 0x0627 #define ARABIC_ALPHABETIC_END 0x064A #define PERSO_ARABIC_BEGIN 0x06F0 #define PERSO_ARABIC_END 0x06F9 #define ARMENIAN_ALPHABETIC_UPPER_BEGIN 0x0531 #define ARMENIAN_ALPHABETIC_UPPER_END 0x554 #define BALINESE_BEGIN 0x1B50 #define BALINESE_END 0x1B59 #define BENGALI_BEGIN 0x09E6 #define BENGALI_END 0x09EF #define BURMESE_BEGIN 0x1040 #define BURMESE_END 0x1049 #define CHINESE_COUNTING_ROD_BEGIN 0x1D360 #define CHINESE_COUNTING_ROD_END 0x1D371 #define CHINESE_A_BEGIN 0x4E00 #define CHINESE_A_END 0x9FBB #define CHINESE_B_BEGIN 0x20000 #define CHINESE_B_END 0x2A6D6 #define CYRILLIC_ALPHABETIC_UPPER_BEGIN 0x0400 #define CYRILLIC_ALPHABETIC_UPPER_END 0x04FF #define DEVANAGARI_BEGIN 0x0966 #define DEVANAGARI_END 0x096F #define COMMON_BRAILLE_BEGIN 0x2801 #define COMMON_BRAILLE_END 0x281B #define ETHIOPIC_BEGIN 0x1369 #define ETHIOPIC_END 0x137C #define EWELLIC_BEGIN 0xE6C0 #define EWELLIC_DECIMAL_END 0xE6C9 #define EWELLIC_END 0xE6CF #define GLAGOLITIC_ALPHABETIC_BEGIN 0x2C00 #define GLAGOLITIC_ALPHABETIC_END 0x2C1E #define GREEK_ALPHABETIC_LOWER_BEGIN 0x03B1 #define GREEK_ALPHABETIC_LOWER_END 0x03C9 #define GREEK_ALPHABETIC_UPPER_BEGIN 0x0391 #define GREEK_ALPHABETIC_UPPER_END 0x03A9 #define GREEK_ALPHABETIC_LOWER_DIGAMMA 0x03DD #define GREEK_ALPHABETIC_UPPER_DIGAMMA 0x03DC #define GREEK_ALPHABETIC_LOWER_KOPPA 0x03DF #define GREEK_ALPHABETIC_UPPER_KOPPA 0x03DE #define GREEK_ALPHABETIC_LOWER_SAN 0x03FB #define GREEK_ALPHABETIC_UPPER_SAN 0x03FA #define GREEK_ALPHABETIC_LOWER_STIGMA 0x03DB #define GREEK_ALPHABETIC_UPPER_STIGMA 0x03DA #define GREEK_ALPHABETIC_RIGHT_KERAIA 0x0374 #define GREEK_ALPHABETIC_LEFT_KERAIA 0x0375 #define GUJARATI_BEGIN 0x0AE6 #define GUJARATI_END 0x0AEF #define GURMUKHI_BEGIN 0x0A66 #define GURMUKHI_END 0x0A6F #define HEBREW_BEGIN 0x0590 #define HEBREW_END 0x05FF #define KANNADA_BEGIN 0x0CE6 #define KANNADA_END 0x0CEF #define KHAROSHTHI_BEGIN 0x10A40 #define KHAROSHTHI_END 0x10A47 #define KHMER_BEGIN 0x17E0 #define KHMER_END 0x17E9 #define KLINGON_BEGIN 0xF8F0 #define KLINGON_END 0xF8F9 #define LAO_BEGIN 0x0ED0 #define LAO_END 0x0ED9 #define LIMBU_BEGIN 0x1946 #define LIMBU_END 0x194F #define MALAYALAM_BEGIN 0x0D00 #define MALAYALAM_END 0x0D7F #define MONGOLIAN_BEGIN 0x1810 #define MONGOLIAN_END 0x1819 #define MXEDRULI_BEGIN 0x10D0 #define MXEDRULI_END 0x10F5 #define NEW_TAI_LUE_BEGIN 0x19D0 #define NEW_TAI_LUE_END 0x19D9 #define NKO_BEGIN 0x07C0 #define NKO_END 0x07C9 #define OLD_ITALIC_BEGIN 0x10320 #define OLD_ITALIC_END 0x10323 #define OLD_PERSIAN_BEGIN 0x103D1 #define OLD_PERSIAN_END 0x103D5 #define ORIYA_BEGIN 0x0B66 #define ORIYA_END 0x0B6F #define OSMANYA_BEGIN 0x104A0 #define OSMANYA_END 0x104A9 #define PHOENICIAN_BEGIN 0x10916 #define PHOENICIAN_END 0x10919 #define SINHALA_BEGIN 0x0DE7 #define SINHALA_END 0x0DFA #define SUZHOU_BEGIN 0x3021 #define SUZHOU_END 0x3029 #define TAMIL_BEGIN 0x0BE6 #define TAMIL_END 0x0BF2 #define TELUGU_BEGIN 0x0C66 #define TELUGU_END 0x0C6F #define TENGWAR_BEGIN 0xE030 #define TENGWAR_END 0xE06E #define THAI_BEGIN 0x0E50 #define THAI_END 0x0E59 #define TIBETAN_BEGIN 0x0F20 #define TIBETAN_END 0x0F29 #define VERDURIAN_BEGIN 0xE260 #define VERDURIAN_END 0xE26B #define XUCURI_LOWER_BEGIN 0x2D00 #define XUCURI_LOWER_END 0x2D25 #define XUCURI_UPPER_BEGIN 0x10A0 #define XUCURI_UPPER_END 0x10C5 int GuessNumberSystem(UTF32 *str){ UTF32 c; UTF32 *s; int WesternCnt = 0; int ZeroCnt = 0; int len; short FirstIsGraveP = 0; uninum_err = NS_ERROR_OKAY; if (!str) return (NS_UNKNOWN); len = ucslen(str); s = str; if((c = *s) == 0x0060) FirstIsGraveP = 1; while((c = *s++) != 0x0000) { if ((c >= AEGEAN_BEGIN) && (c <= AEGEAN_END)) return NS_AEGEAN; if ((c >= ARABIC_BEGIN) && (c <= ARABIC_END)) return NS_ARABIC_WESTERN; if ((c >= ARABIC_ALPHABETIC_BEGIN) && (c <= ARABIC_ALPHABETIC_END)) return NS_ARABIC_ALPHABETIC; if ((c >= PERSO_ARABIC_BEGIN) && (c <= PERSO_ARABIC_END)) return NS_PERSO_ARABIC; if (((c >= ARMENIAN_ALPHABETIC_UPPER_BEGIN) && (c <= ARMENIAN_ALPHABETIC_UPPER_END))) { return NS_ARMENIAN_ALPHABETIC; } if ((c >= BALINESE_BEGIN) && (c <= BALINESE_END)) return NS_BALINESE; if ((c >= BENGALI_BEGIN) && (c <= BENGALI_END)) return NS_BENGALI; if ((c >= BURMESE_BEGIN) && (c <= BURMESE_END)) return NS_BURMESE; if ((c >= CHINESE_COUNTING_ROD_BEGIN) && (c <= CHINESE_COUNTING_ROD_END)) return NS_CHINESE_COUNTING_ROD_GENERIC; if ( ((c >= CHINESE_A_BEGIN) && (c <= CHINESE_A_END)) || ((c >= CHINESE_B_BEGIN) && (c <= CHINESE_B_END)) || ( (c >= SUZHOU_BEGIN) && (c <= SUZHOU_END)) ) return NS_CHINESE_GENERIC; if (((c >= CYRILLIC_ALPHABETIC_UPPER_BEGIN) && (c <= CYRILLIC_ALPHABETIC_UPPER_END)) || (c == CYRILLIC_THOUSANDS_SIGN) || (c == CYRILLIC_TITLO)) { return NS_CYRILLIC_ALPHABETIC; } if ((c >= DEVANAGARI_BEGIN) && (c <= DEVANAGARI_END)) return NS_DEVANAGARI; if ((c >= 0x14000) && (c <= 0x143D7)) return NS_EGYPTIAN; if ((c >= ETHIOPIC_BEGIN) && (c <= ETHIOPIC_END)) return NS_ETHIOPIC; if ((c > EWELLIC_DECIMAL_END) && (c <= EWELLIC_END)) return NS_EWELLIC_HEX; if ((c >= EWELLIC_BEGIN) && (c <= EWELLIC_DECIMAL_END)) { if(FirstIsGraveP) return NS_EWELLIC_HEX; else return NS_EWELLIC_DECIMAL; } if ((c >= GLAGOLITIC_ALPHABETIC_BEGIN) && (c <= GLAGOLITIC_ALPHABETIC_END)) return NS_GLAGOLITIC_ALPHABETIC; if (((c >= GREEK_ALPHABETIC_LOWER_BEGIN) && (c <= GREEK_ALPHABETIC_LOWER_END)) || (c == GREEK_ALPHABETIC_LOWER_DIGAMMA) || (c == GREEK_ALPHABETIC_LOWER_KOPPA) || (c == GREEK_ALPHABETIC_LOWER_STIGMA) || (c == GREEK_ALPHABETIC_LOWER_SAN)) return NS_GREEK_ALPHABETIC_LOWER; if (((c >= GREEK_ALPHABETIC_UPPER_BEGIN) && (c <= GREEK_ALPHABETIC_UPPER_END)) || (c == GREEK_ALPHABETIC_UPPER_DIGAMMA) || (c == GREEK_ALPHABETIC_UPPER_KOPPA) || (c == GREEK_ALPHABETIC_UPPER_STIGMA) || (c == GREEK_ALPHABETIC_UPPER_SAN)) return NS_GREEK_ALPHABETIC_UPPER; if ((c >= GUJARATI_BEGIN) && (c <= GUJARATI_END)) return NS_GUJARATI; if ((c >= GURMUKHI_BEGIN) && (c <= GURMUKHI_END)) return NS_GURMUKHI; if ((c >= HEBREW_BEGIN) && (c <= HEBREW_END)) return NS_HEBREW_GENERIC; if ((c >= KANNADA_BEGIN) && (c <= KANNADA_END)) return NS_KANNADA; if ((c >= KHAROSHTHI_BEGIN) && (c <= KHAROSHTHI_END)) return NS_KHAROSHTHI; if ((c >= KHMER_BEGIN) && (c <= KHMER_END)) return NS_KHMER; if ((c >= KLINGON_BEGIN) && (c <= KLINGON_END)) return NS_KLINGON; if ((c >= LAO_BEGIN) && (c <= LAO_END)) return NS_LAO; if ((c >= LIMBU_BEGIN) && (c <= LIMBU_END)) return NS_LIMBU; if ((c >= MALAYALAM_BEGIN) && (c <= MALAYALAM_END)) return NS_MALAYALAM; if ((c >= MONGOLIAN_BEGIN) && (c <= MONGOLIAN_END)) return NS_MONGOLIAN; if ((c >= MXEDRULI_BEGIN) && (c <= MXEDRULI_END)) return NS_MXEDRULI; if ((c >= NEW_TAI_LUE_BEGIN) && (c <= NEW_TAI_LUE_END)) return NS_NEW_TAI_LUE; if ((c >= NKO_BEGIN) && (c <= NKO_END)) return NS_NKO; if ((c >= OLD_ITALIC_BEGIN) && (c <= OLD_ITALIC_END)) return NS_OLD_ITALIC; if ((c >= OLD_PERSIAN_BEGIN) && (c <= OLD_PERSIAN_END)) return NS_OLD_PERSIAN; if ((c >= ORIYA_BEGIN) && (c <= ORIYA_END)) return NS_ORIYA; if ((c >= OSMANYA_BEGIN) && (c <= OSMANYA_END)) return NS_OSMANYA; if ((c >= PHOENICIAN_BEGIN) && (c <= PHOENICIAN_END)) return NS_PHOENICIAN; if ((c >= TAMIL_BEGIN) && (c <= TAMIL_END)) return NS_TAMIL_GENERIC; if ((c >= TELUGU_BEGIN) && (c <= TELUGU_END)) return NS_TELUGU; if(c == TENGWAR_DECIMAL_MARKER) return NS_TENGWAR_DECIMAL; if(c == TENGWAR_DUODECIMAL_MARKER) return NS_TENGWAR_DUODECIMAL; if(c == TENGWAR_DUODECIMAL_LSD_MARKER) return NS_TENGWAR_DUODECIMAL; if( (c == TENGWAR_DEC) || (c == TENGWAR_EL)) return NS_TENGWAR_DUODECIMAL; if ((c >= THAI_BEGIN) && (c <= THAI_END)) return NS_THAI; if ((c >= TIBETAN_BEGIN) && (c <= TIBETAN_END)) return NS_TIBETAN; if ((c >= VERDURIAN_BEGIN) && (c <= VERDURIAN_END)) return NS_VERDURIAN; if ((c >= XUCURI_LOWER_BEGIN) && (c <= XUCURI_LOWER_END)) return NS_XUCURI_LOWER; if ((c >= XUCURI_UPPER_BEGIN) && (c <= XUCURI_UPPER_END)) return NS_XUCURI_UPPER; if ((c == 0x0059) || (c == 0x0079)) { if (ZeroCnt && (s-1 == str+1)) return NS_HEX; } if ((c == 0x0049) || (c == 0x0056) || (c == 0x0058) || (c == 0x004C) || (c == 0x0043) || (c == 0x0044) || (c == 0x004D) || (c == 0x2183) || ( (c >= 0x2160) && (c <= 0x216F))) return NS_ROMAN_UPPER; if ((c == 0x0069) || (c == 0x0076) || (c == 0x0078) || (c == 0x006C) || (c == 0x0063) || (c == 0x0064) || (c == 0x006D) || (c == 0x2184) || ( (c >= 0x2170) && (c <= 0x217F))) return NS_ROMAN_LOWER; if ((c == 0x281A) || (c == 0x2801) || (c == 0x2803) || (c == 0x2809) || (c == 0x2819) || (c == 0x2811) || (c == 0x280B) || (c == 0x281B) || (c == 0x2813) || (c == 0x280A)) return NS_COMMON_BRAILLE; if ((c == 0x283C) || (c == 0x2821) || (c == 0x2823) || (c == 0x2829) || (c == 0x2839) || (c == 0x2831) || (c == 0x282B) || (c == 0x283B) || (c == 0x2833) || (c == 0x282A)) return NS_FRENCH_BRAILLE; if ((c == 0x2834) || (c == 0x2802) || (c == 0x2806) || (c == 0x2812) || (c == 0x2832) || (c == 0x2822) || (c == 0x2816) || (c == 0x2836) || (c == 0x2826) || (c == 0x2814)) return NS_RUSSIAN_BRAILLE; if ((c >= 0x31 ) && (c <= 0x39)) {WesternCnt++;continue;} if (c == 0x0030) {ZeroCnt++;WesternCnt++;continue;} } if(ZeroCnt == len) return (NS_ALLZERO); if(WesternCnt == len) return(NS_WESTERN_GENERIC); return (NS_UNKNOWN); } /* String to Integer conversion functions */ static void ArabicToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; char *rs; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x0660: CurrentValue = 0; break; case 0x0661: CurrentValue = 1; break; case 0x0662: CurrentValue = 2; break; case 0x0663: CurrentValue = 3; break; case 0x0664: CurrentValue = 4; break; case 0x0665: CurrentValue = 5; break; case 0x0666: CurrentValue = 6; break; case 0x0667: CurrentValue = 7; break; case 0x0668: CurrentValue = 8; break; case 0x0669: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void ArabicExtendedToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x06F0: CurrentValue = 0; break; case 0x06F1: CurrentValue = 1; break; case 0x06F2: CurrentValue = 2; break; case 0x06F3: CurrentValue = 3; break; case 0x06F4: CurrentValue = 4; break; case 0x06F5: CurrentValue = 5; break; case 0x06F6: CurrentValue = 6; break; case 0x06F7: CurrentValue = 7; break; case 0x06F8: CurrentValue = 8; break; case 0x06F9: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void ArabicAlphabeticToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x0627: CurrentValue = 1; break; case 0x0628: CurrentValue = 2; break; case 0x062C: CurrentValue = 3; break; case 0x062F: CurrentValue = 4; break; case 0x0647: CurrentValue = 5; break; case 0x0648: CurrentValue = 6; break; case 0x0632: CurrentValue = 7; break; case 0x062D: CurrentValue = 8; break; case 0x0637: CurrentValue = 9; break; case 0x064A: CurrentValue = 10; break; case 0x0643: CurrentValue = 20; break; case 0x0644: CurrentValue = 30; break; case 0x0645: CurrentValue = 40; break; case 0x0646: CurrentValue = 50; break; case 0x0633: CurrentValue = 60; break; case 0x0639: CurrentValue = 70; break; case 0x0641: CurrentValue = 80; break; case 0x0635: CurrentValue = 90; break; case 0x0642: CurrentValue = 100; break; case 0x0631: CurrentValue = 200; break; case 0x0634: CurrentValue = 300; break; case 0x062A: CurrentValue = 400; break; case 0x062B: CurrentValue = 500; break; case 0x062E: CurrentValue = 600; break; case 0x0630: CurrentValue = 700; break; case 0x0636: CurrentValue = 800; break; case 0x0638: CurrentValue = 900; break; case 0x063A: CurrentValue = 1000; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); return; } static void AegeanToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x10107: CurrentValue = 1; break; case 0x10108: CurrentValue = 2; break; case 0x10109: CurrentValue = 3; break; case 0x1010A: CurrentValue = 4; break; case 0x1010B: CurrentValue = 5; break; case 0x1010C: CurrentValue = 6; break; case 0x1010D: CurrentValue = 7; break; case 0x1010E: CurrentValue = 8; break; case 0x1010F: CurrentValue = 9; break; case 0x10110: CurrentValue = 10; break; case 0x10111: CurrentValue = 20; break; case 0x10112: CurrentValue = 30; break; case 0x10113: CurrentValue = 40; break; case 0x10114: CurrentValue = 50; break; case 0x10115: CurrentValue = 60; break; case 0x10116: CurrentValue = 70; break; case 0x10117: CurrentValue = 80; break; case 0x10118: CurrentValue = 90; break; case 0x10119: CurrentValue = 100; break; case 0x1011A: CurrentValue = 200; break; case 0x1011B: CurrentValue = 300; break; case 0x1011C: CurrentValue = 400; break; case 0x1011D: CurrentValue = 500; break; case 0x1011E: CurrentValue = 600; break; case 0x1011F: CurrentValue = 700; break; case 0x10120: CurrentValue = 800; break; case 0x10121: CurrentValue = 900; break; case 0x10122: CurrentValue = 1000; break; case 0x10123: CurrentValue = 2000; break; case 0x10124: CurrentValue = 3000; break; case 0x10125: CurrentValue = 4000; break; case 0x10126: CurrentValue = 5000; break; case 0x10127: CurrentValue = 6000; break; case 0x10128: CurrentValue = 7000; break; case 0x10129: CurrentValue = 8000; break; case 0x1012A: CurrentValue = 9000; break; case 0x1012B: CurrentValue = 10000; break; case 0x1012C: CurrentValue = 20000; break; case 0x1012D: CurrentValue = 30000; break; case 0x1012E: CurrentValue = 40000; break; case 0x1012F: CurrentValue = 50000; break; case 0x10130: CurrentValue = 60000; break; case 0x10131: CurrentValue = 70000; break; case 0x10132: CurrentValue = 80000; break; case 0x10133: CurrentValue = 90000; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); return; } static void ArmenianAlphabeticToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x0531: CurrentValue = 1; break; case 0x0532: CurrentValue = 2; break; case 0x0533: CurrentValue = 3; break; case 0x0534: CurrentValue = 4; break; case 0x0535: CurrentValue = 5; break; case 0x0536: CurrentValue = 6; break; case 0x0537: CurrentValue = 7; break; case 0x0538: CurrentValue = 8; break; case 0x0539: CurrentValue = 9; break; case 0x053A: CurrentValue = 10; break; case 0x053B: CurrentValue = 20; break; case 0x053C: CurrentValue = 30; break; case 0x053D: CurrentValue = 40; break; case 0x053E: CurrentValue = 50; break; case 0x053F: CurrentValue = 60; break; case 0x0540: CurrentValue = 70; break; case 0x0541: CurrentValue = 80; break; case 0x0542: CurrentValue = 90; break; case 0x0543: CurrentValue = 100; break; case 0x0544: CurrentValue = 200; break; case 0x0545: CurrentValue = 300; break; case 0x0546: CurrentValue = 400; break; case 0x0547: CurrentValue = 500; break; case 0x0548: CurrentValue = 600; break; case 0x0549: CurrentValue = 700; break; case 0x054A: CurrentValue = 800; break; case 0x054B: CurrentValue = 900; break; case 0x054C: CurrentValue = 1000; break; case 0x054D: CurrentValue = 2000; break; case 0x054E: CurrentValue = 3000; break; case 0x054F: CurrentValue = 4000; break; case 0x0550: CurrentValue = 5000; break; case 0x0551: CurrentValue = 6000; break; case 0x0552: CurrentValue = 7000; break; case 0x0553: CurrentValue = 8000; break; case 0x0554: CurrentValue = 9000; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); return; } static void BalineseToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x1B50: CurrentValue = 0; break; case 0x1B51: CurrentValue = 1; break; case 0x1B52: CurrentValue = 2; break; case 0x1B53: CurrentValue = 3; break; case 0x1B54: CurrentValue = 4; break; case 0x1B55: CurrentValue = 5; break; case 0x1B56: CurrentValue = 6; break; case 0x1B57: CurrentValue = 7; break; case 0x1B58: CurrentValue = 8; break; case 0x1B59: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void BengaliToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x09E6: CurrentValue = 0; break; case 0x09E7: CurrentValue = 1; break; case 0x09E8: CurrentValue = 2; break; case 0x09E9: CurrentValue = 3; break; case 0x09EA: CurrentValue = 4; break; case 0x09EB: CurrentValue = 5; break; case 0x09EC: CurrentValue = 6; break; case 0x09ED: CurrentValue = 7; break; case 0x09EE: CurrentValue = 8; break; case 0x09EF: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void BurmeseToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x1040: CurrentValue = 0; break; case 0x1041: CurrentValue = 1; break; case 0x1042: CurrentValue = 2; break; case 0x1043: CurrentValue = 3; break; case 0x1044: CurrentValue = 4; break; case 0x1045: CurrentValue = 5; break; case 0x1046: CurrentValue = 6; break; case 0x1047: CurrentValue = 7; break; case 0x1048: CurrentValue = 8; break; case 0x1049: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } /* * Replaces variant forms of Chinese numbers with their standard traditional counterparts. * Returns a newly allocated string, or a null pointer on failure of storage allocation. */ static UTF32 *NormalizeChineseNumbers (UTF32 *s) { UTF32 c; UTF32 *t; UTF32 *tmp; UTF32 *n; int len; int NewLen; /* * It is safe to double the string length for temp space since no * substitution does more than replace one character with two. */ len = ucslen(s); #ifdef ALLOCAOK t = alloca (((2 * len) + 1) * sizeof (UTF32)); #else t = malloc (((2 * len) + 1) * sizeof (UTF32)); #endif if (t == NULL) return (t); tmp = t; NewLen = len; while( (c = *s++) != 0x0000) { switch (c) { case 0x96F6: /* Traditional/Legal */ case 0xF9B2: /* Compatibility */ *t++ =0x3007; /* 0 - Ideographic zero - also used with Suzhou numerals*/ break; case 0x58F1: /* Legal */ case 0x58F9: /* Legal */ case 0x580C: /* Legal */ case 0x4E48: /* Telephone number yao - traditional */ case 0x5E7A: /* Telephone number yao - simplified */ case 0x3021: /* Suzhou */ *t++=0x4E00; /* 1 */ break; case 0x5F0D: /* Legal simplified */ case 0x5F10: /* Modern Japanese Legal simplified */ case 0x5169: /* liang traditional */ case 0x8CAE: /* Legal traditional */ case 0x8CB3: /* Legal traditional */ case 0x8D30: /* Legal traditional */ case 0x4E24: /* liang simplified */ case 0x3022: /* Suzhou */ case 0xF978: /* liang - compatibility */ *t++ = 0x4E8C; /* 2 */ break; case 0x53C1: /* Legal simplified */ case 0x53C2: /* Modern Japanese Legal */ case 0x53C3: /* Obsolete Japanese Legal */ case 0x53C4: /* Legal traditional */ case 0x5F0E: /* Legal simplified */ case 0x3023: /* Suzhou */ *t++ = 0x4E09; /* 3 */ break; case 0x4E96: /* Obsolete Japanese variant */ case 0x8086: /* Legal */ case 0x3024: /* Suzhou */ *t++ = 0x56DB; /* 4 */ break; case 0x4F0D: /* Legal */ case 0x3025: /* Suzhou */ *t++ = 0x4E94; /* 5 */ break; case 0x9646: /* Legal */ case 0x9678: /* Legal */ case 0x3026: /* Suzhou */ *t++ = 0x516D; /* 6 */ break; case 0x67D2: /* Legal */ case 0x6F06: /* Legal ??????*/ case 0x3027: /* Suzhou */ *t++ = 0x4E03; /* 7 */ break; case 0x634C: /* Legal */ case 0x3028: /* Suzhou */ *t++ = 0x516B; /* 8 */ break; case 0x7396: /* Legal */ case 0x3029: /* Suzhou */ *t++ = 0x4E5D; /* 9 */ break; case 0x3038: /* Suzhou */ case 0x4EC0: /* Legal simplified - disfavored */ case 0x62FE: /* Legal traditional*/ *t++ = 0x5341; /* 10 */ break; case 0x5EFF: /* Portmanteau */ case 0x3039: /* Suzhou portmanteau */ *t++ = 0x4E8C; *t++ = 0x5341; /* 20 */ NewLen++; break; case 0x5345: /* Portmanteau */ case 0x303A: /* Suzhou portmanteau */ *t++ = 0x4E09; *t++ = 0x5341; /* 30 */ NewLen++; break; case 0x534C: /* Portmanteau */ *t++ = 0x56DB; *t++ = 0x5341; /* 40 */ NewLen++; break; case 0x4F70: /* Legal */ case 0x964C: /* Legal */ *t++ = 0x767E; /* 100 */ break; case 0x4EDF: /* Legal */ case 0x9621: /* Legal */ *t++ = 0x5343; /* 1000 */ break; case 0x842C: /* Legal */ *t++ = 0x4E07; /* 10,000 */ break; case 0x4EBF: /* Simplified */ *t++ = 0x5104; /* 100,000,000 */ break; default: *t++ = c; } } *t = 0x0000; n = malloc ( (NewLen+1) * sizeof(UTF32)); if (n == NULL) return (n); ucscpy(n,tmp); #ifndef ALLOCAOK free( (void *) tmp); #endif return n; } /* * The Chinese functions expect standard Chinese numbers in traditional characters. * Simplified characters and variants such as Suzhou numbers can be handled * by first calling NormalizeChineseNumbers on the input. */ static void ChinesePlace (mpz_t Result, UTF32 *s) { unsigned long CurrentValue; UTF32 c; while ( (c = *s++) != 0x0000) { switch (c) { case 0x3007: case 0x96F6: case 0x0030: CurrentValue = 0; break; case 0x4E00: case 0x0031: CurrentValue = 1; break; case 0x4E8C: case 0x0032: CurrentValue = 2; break; case 0x4E09: case 0x0033: CurrentValue = 3; break; case 0x56DB: case 0x0034: CurrentValue = 4; break; case 0x4E94: case 0x0035: CurrentValue = 5; break; case 0x516D: case 0x0036: CurrentValue = 6; break; case 0x4E03: case 0x0037: CurrentValue = 7; break; case 0x516B: case 0x0038: CurrentValue = 8; break; case 0x4E5D: case 0x0039: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result,Result,10L); mpz_add_ui(Result, Result, CurrentValue); } return; } static UTF32 ChineseBarriers [] = { 0x5341, /* 0 - 10^1 */ 0x767E, /* 1 - 10^2 */ 0x5343, /* 2 - 10^3 */ 0x4E07, /* 3 - 10^4 */ 0x5104, /* 4 - 10^8 */ 0x5146, /* 5 - 10^12 */ 0x4EAC, /* 6 - 10^16 */ 0x5793, /* 7 - 10^20 */ 0x25771, /* 8 - 10^24 */ 0x7A63, /* 9 - 10^28 */ 0x6E9D, /* 10 - 10^32 */ 0x6F97, /* 11 - 10^36 */ 0x6B63, /* 12 - 10^40 */ 0x8F09, /* 13 - 10^44 */ 0x6975, /* 14 - 10^48 */ }; /* * We can't just initialize an array of these values since most * of them are too large to fit into an unsigned long int, * some even an unsigned long long int. */ static void GetChineseBarrierValue (mpz_t Result,int which) { switch (which) { case 0: (void) mpz_set_str(Result,"10",10);break; case 1: (void) mpz_set_str(Result,"100",10);break; case 2: (void) mpz_set_str(Result,"1000",10);break; case 3: (void) mpz_set_str(Result,"10000",10);break; case 4: (void) mpz_set_str(Result,"100000000",10);break; case 5: (void) mpz_set_str(Result,"1000000000000",10);break; case 6: (void) mpz_set_str(Result,"10000000000000000",10);break; case 7: (void) mpz_set_str(Result,"100000000000000000000",10);break; case 8: (void) mpz_set_str(Result,"1000000000000000000000000",10);break; case 9: (void) mpz_set_str(Result,"10000000000000000000000000000",10);break; case 10: (void) mpz_set_str(Result,"100000000000000000000000000000000",10);break; case 11: (void) mpz_set_str(Result,"1000000000000000000000000000000000000",10);break; case 12: (void) mpz_set_str(Result,"10000000000000000000000000000000000000000",10);break; case 13: (void) mpz_set_str(Result,"100000000000000000000000000000000000000000000",10);break; case 14: (void) mpz_set_str(Result,"1000000000000000000000000000000000000000000000000",10);break; default: (void) mpz_set_str(Result,"0",10); } } static inline UTF32 *SeekChineseBarrier (UTF32 *s, int *ri) { UTF32 *ptr; int bi = (sizeof(ChineseBarriers)/sizeof(UTF32))-1; ptr = NULL; while (ptr == NULL && bi >= 0) { ptr = ucschr(s,ChineseBarriers[bi--]); } *ri = bi+1; return ptr; } static void ChineseToInt_MPZ(mpz_t ReturnValue, UTF32 *s) { UTF32 *ptr; UTF32 SavedBarrier; int i; mpz_t mul; mpz_t Result; mpz_t RightValue; mpz_t BarrierValue; mpz_init(BarrierValue); mpz_init(mul); mpz_init(Result); mpz_init(RightValue); ptr = SeekChineseBarrier(s,&i); if (ptr == NULL) { ChinesePlace(ReturnValue,s); } else { SavedBarrier = *ptr; *ptr = 0x0000; ChineseToInt_MPZ(mul,s); *ptr = SavedBarrier; if (UEQ(mul,0L)) mpz_set_ui(mul,1L); /* If mul = 0, mul <= 1 */ GetChineseBarrierValue(BarrierValue,i); mpz_mul(Result,mul,BarrierValue); ChineseToInt_MPZ(RightValue,ptr+1); mpz_add(Result,Result,RightValue); mpz_set(ReturnValue,Result); } mpz_clear(BarrierValue); mpz_clear(Result); mpz_clear(RightValue); mpz_clear(mul); return; } static void ChineseToInt(mpz_t mpzResult, UTF32 *s) { mpz_t Result; char *rs; uninum_err = NS_ERROR_OKAY; mpz_init(Result); ChineseToInt_MPZ(Result,s); mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void ChineseCountingRodToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; char *rs; enum ct {EVEN,NEUTRAL,ODD}; enum ct PreviousType = NEUTRAL; enum ct CurrentType = NEUTRAL; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x3007: CurrentValue = 0; CurrentType = NEUTRAL; break; case 0x1D360: CurrentValue = 1; CurrentType = EVEN; break; case 0x1D369: CurrentValue = 1; CurrentType = ODD; break; case 0x1D361: CurrentValue = 2; CurrentType = EVEN; break; case 0x1D36A: CurrentValue = 2; CurrentType = ODD; break; case 0x1D362: CurrentValue = 3; CurrentType = EVEN; break; case 0x1D36B: CurrentValue = 3; CurrentType = ODD; break; case 0x1D363: CurrentValue = 4; CurrentType = EVEN; break; case 0x1D36C: CurrentValue = 4; CurrentType = ODD; break; case 0x1D364: CurrentValue = 5; CurrentType = EVEN; break; case 0x1D36D: CurrentValue = 5; CurrentType = ODD; break; case 0x1D365: CurrentValue = 6; CurrentType = EVEN; break; case 0x1D36E: CurrentValue = 6; CurrentType = ODD; break; case 0x1D366: CurrentValue = 7; CurrentType = EVEN; break; case 0x1D36F: CurrentValue = 7; CurrentType = ODD; break; case 0x1D367: CurrentValue = 8; CurrentType = EVEN; break; case 0x1D370: CurrentValue = 8; CurrentType = ODD; break; case 0x1D368: CurrentValue = 9; CurrentType = EVEN; break; case 0x1D371: CurrentValue = 9; CurrentType = ODD; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } if( (CurrentType == PreviousType) && (CurrentType != NEUTRAL)) { mpz_mul_ui(Result, Result, 100L); } else mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); PreviousType = CurrentType; } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void CyrillicAlphabeticToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue=0L; UTF32 c; mpz_t Result; short ThousandP = 0; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ((c = *s++) != 0x0000) { switch(c) { case CYRILLIC_TITLO: /* Skip - it just marks numbers*/ break; case CYRILLIC_THOUSANDS_SIGN: ThousandP = 1; break; case 0x0426: CurrentValue=900; break; case 0x0460: CurrentValue=800; break; case 0x0470: CurrentValue=700; break; case 0x0425: CurrentValue=600; break; case 0x0424: CurrentValue=500; break; case 0x0478: CurrentValue=400; break; case 0x0422: CurrentValue=300; break; case 0x0421: CurrentValue=200; break; case 0x0420: CurrentValue=100; break; case 0x0427: CurrentValue=90; break; case 0x041F: CurrentValue=80; break; case 0x041E: CurrentValue=70; break; case 0x046E: CurrentValue=60; break; case 0x041D: CurrentValue=50; break; case 0x041C: CurrentValue=40; break; case 0x041B: CurrentValue=30; break; case 0x041A: CurrentValue=20; break; case 0x0406: CurrentValue=10; break; case 0x0472: CurrentValue=9; if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;} break; case 0x0418: CurrentValue=8; if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;} break; case 0x0417: CurrentValue=7; if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;} break; case 0x0405: CurrentValue=6; if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;} break; case 0x0415: CurrentValue=5; if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;} break; case 0x0414: CurrentValue=4; if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;} break; case 0x0413: CurrentValue=3; if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;} break; case 0x0411: /* BE */ CurrentValue=2; if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;} break; case 0x0410: /* A */ CurrentValue=1; if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;} break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_add_ui(Result,Result,CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void CommonBrailleToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); if (*s == 0x283C) s++; /* Skip number designator */ while ( (c = *s++) != 0x0000) { switch (c) { case 0x281A: CurrentValue = 0; break; case 0x2801: CurrentValue = 1; break; case 0x2803: CurrentValue = 2; break; case 0x2809: CurrentValue = 3; break; case 0x2819: CurrentValue = 4; break; case 0x2811: CurrentValue = 5; break; case 0x280B: CurrentValue = 6; break; case 0x281B: CurrentValue = 7; break; case 0x2813: CurrentValue = 8; break; case 0x280A: CurrentValue = 9; break; case 0x2802: /* Ignore Braille comma */ break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void DevanagariToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x0966: CurrentValue = 0; break; case 0x0967: CurrentValue = 1; break; case 0x0968: CurrentValue = 2; break; case 0x0969: CurrentValue = 3; break; case 0x096A: CurrentValue = 4; break; case 0x096B: CurrentValue = 5; break; case 0x096C: CurrentValue = 6; break; case 0x096D: CurrentValue = 7; break; case 0x096E: CurrentValue = 8; break; case 0x096F: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } /* Based on Unicode proposal - not yet final as of Unicode 5.0 */ static void EgyptianToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x143A1: CurrentValue = 1; break; case 0x14353: CurrentValue = 10; break; case 0x1433B: CurrentValue = 100; break; case 0x141A2: CurrentValue = 1000; break; case 0x140A7: CurrentValue = 10000; break; case 0x14173: CurrentValue = 100000; break; case 0x14064: CurrentValue = 1000000; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void EthiopicToInt(mpz_t mpzResult, UTF32 *s) { mpz_init_set_ui(mpzResult,0L); uninum_err = NS_ERROR_NUMBER_SYSTEM_UNKNOWN; } static void EwellicDecimalToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0xE6C0: case 0x0030: CurrentValue = 0; break; case 0xE6C1: case 0x0031: CurrentValue = 1; break; case 0xE6C2: case 0x0032: CurrentValue = 2; break; case 0xE6C3: case 0x0033: CurrentValue = 3; break; case 0xE6C4: case 0x0034: CurrentValue = 4; break; case 0xE6C5: case 0x0035: CurrentValue = 5; break; case 0xE6C6: case 0x0036: CurrentValue = 6; break; case 0xE6C7: case 0x0037: CurrentValue = 7; break; case 0xE6C8: case 0x0038: CurrentValue = 8; break; case 0xE6C9: case 0x0039: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void EwellicHexToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); if( *s == 0x0060) s++; /* Skip Ewellic hex marker */ while ( (c = *s++) != 0x0000) { switch (c) { case 0xE6C0: case 0x0030: CurrentValue = 0; break; case 0xE6C1: case 0x0031: CurrentValue = 1; break; case 0xE6C2: case 0x0032: CurrentValue = 2; break; case 0xE6C3: case 0x0033: CurrentValue = 3; break; case 0xE6C4: case 0x0034: CurrentValue = 4; break; case 0xE6C5: case 0x0035: CurrentValue = 5; break; case 0xE6C6: case 0x0036: CurrentValue = 6; break; case 0xE6C7: case 0x0037: CurrentValue = 7; break; case 0xE6C8: case 0x0038: CurrentValue = 8; break; case 0xE6C9: case 0x0039: CurrentValue = 9; break; case 0xE6CA: CurrentValue = 10; break; case 0xE6CB: CurrentValue = 11; break; case 0xE6CC: CurrentValue = 12; break; case 0xE6CD: CurrentValue = 13; break; case 0xE6CE: CurrentValue = 14; break; case 0xE6CF: CurrentValue = 15; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 16L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void FrenchBrailleToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); if (*s == 0x2820) s++; /* Skip number designator - D6 */ while ( (c = *s++) != 0x0000) { switch (c) { case 0x283C: CurrentValue = 0; break; case 0x2821: CurrentValue = 1; break; case 0x2823: CurrentValue = 2; break; case 0x2829: CurrentValue = 3; break; case 0x2839: CurrentValue = 4; break; case 0x2831: CurrentValue = 5; break; case 0x282B: CurrentValue = 6; break; case 0x283B: CurrentValue = 7; break; case 0x2833: CurrentValue = 8; break; case 0x282A: CurrentValue = 9; break; case 0x2802: /* Ignore Braille comma */ break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void GeorgianAlphabeticToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x10A0: case 0x2D00: case 0x10D0: CurrentValue = 1; break; case 0x10A1: case 0x2D01: case 0x10D1: CurrentValue = 2; break; case 0x10A2: case 0x2D02: case 0x10D2: CurrentValue = 3; break; case 0x10A3: case 0x2D03: case 0x10D3: CurrentValue = 4; break; case 0x10A4: case 0x2D04: case 0x10D4: CurrentValue = 5; break; case 0x10A5: case 0x2D05: case 0x10D5: CurrentValue = 6; break; case 0x10A6: case 0x2D06: case 0x10D6: CurrentValue = 7; break; case 0x10C1: case 0x2D21: case 0x10F1: CurrentValue = 8; break; case 0x10A7: case 0x2D07: case 0x10D7: CurrentValue = 9; break; case 0x10A8: case 0x2D08: case 0x10D8: CurrentValue = 10; break; case 0x10A9: case 0x2D09: case 0x10D9: CurrentValue = 20; break; case 0x10AA: case 0x2D0A: case 0x10DA: CurrentValue = 30; break; case 0x10AB: case 0x2D0B: case 0x10DB: CurrentValue = 40; break; case 0x10AC: case 0x2D0C: case 0x10DC: CurrentValue = 50; break; case 0x10C2: case 0x2D22: case 0x10F2: CurrentValue = 60; break; case 0x10AD: case 0x2D0D: case 0x10DD: CurrentValue = 70; break; case 0x10AE: case 0x2D0E: case 0x10DE: CurrentValue = 80; break; case 0x10AF: case 0x2D0F: case 0x10DF: CurrentValue = 90; break; case 0x10B0: case 0x2D10: case 0x10E0: CurrentValue = 100; break; case 0x10B1: case 0x2D11: case 0x10E1: CurrentValue = 200; break; case 0x10B2: case 0x2D12: case 0x10E2: CurrentValue = 300; break; case 0x10B3: case 0x2D13: case 0x10E3: CurrentValue = 400; break; case 0x10B4: case 0x2D14: case 0x10E4: CurrentValue = 500; break; case 0x10B5: case 0x2D15: case 0x10E5: CurrentValue = 600; break; case 0x10B6: case 0x2D16: case 0x10E6: CurrentValue = 700; break; case 0x10B7: case 0x2D17: case 0x10E7: CurrentValue = 800; break; case 0x10B8: case 0x2D18: case 0x10E8: CurrentValue = 900; break; case 0x10B9: case 0x2D19: case 0x10E9: CurrentValue = 1000; break; case 0x10BA: case 0x2D1A: case 0x10EA: CurrentValue = 2000; break; case 0x10BB: case 0x2D1B: case 0x10EB: CurrentValue = 3000; break; case 0x10BC: case 0x2D1C: case 0x10EC: CurrentValue = 4000; break; case 0x10BD: case 0x2D1D: case 0x10ED: CurrentValue = 5000; break; case 0x10BE: case 0x2D1E: case 0x10EE: CurrentValue = 6000; break; case 0x10C4: case 0x2D24: case 0x10F4: CurrentValue = 7000; break; case 0x10BF: case 0x2D1F: case 0x10EF: CurrentValue = 8000; break; case 0x10C0: case 0x2D20: case 0x10F0: CurrentValue = 9000; break; case 0x10C5: case 0x2D25: case 0x10F5: CurrentValue = 10000; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); return; } static void GlagoliticAlphabeticToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x2C00: /* AZU */ CurrentValue = 1; break; case 0x2C01: /* BUKY */ CurrentValue = 2; break; case 0x2C02: /* VEDE */ CurrentValue = 3; break; case 0x2C03: /* GLAGOLY */ CurrentValue = 4; break; case 0x2C04: /* DOBRO */ CurrentValue = 5; break; case 0x2C05: /* YESTU */ CurrentValue = 6; break; case 0x2C06: /* ZHIVETE */ CurrentValue = 7; break; case 0x2C07: /* DZELO */ CurrentValue = 8; break; case 0x2C08: /* ZEMLJA */ CurrentValue = 9; break; case 0x2C09: /* IZHE */ CurrentValue = 10; break; case 0x2C0B: /* I */ CurrentValue = 20; break; case 0x2C0C: /* DJERVI */ CurrentValue = 30; break; case 0x2C0D: /* KAKO */ CurrentValue = 40; break; case 0x2C0E: /* LJUDIE */ CurrentValue = 50; break; case 0x2C0F: /* MYSLITE */ CurrentValue = 60; break; case 0x2C10: /* NASHI */ CurrentValue = 70; break; case 0x2C11: /* ONU */ CurrentValue = 80; break; case 0x2C12: /* POKOJI */ CurrentValue = 90; break; case 0x2C13: /* RITSI */ CurrentValue = 100; break; case 0x2C14: /* SLOVO */ CurrentValue = 200; break; case 0x2C15: /* TVRIDO */ CurrentValue = 300; break; case 0x2C16: /* UKU */ CurrentValue = 400; break; case 0x2C17: /* FRITU */ CurrentValue = 500; break; case 0x2C18: /* HERU */ CurrentValue = 600; break; case 0x2C19: /* OTU */ CurrentValue = 700; break; case 0x2C1B: /* SHTA */ CurrentValue = 800; break; case 0x2C1C: /* TSI */ CurrentValue = 900; break; case 0x2C1D: /* CHRIVI */ CurrentValue = 1000; break; case 0x2C1E: /* SHA */ CurrentValue = 2000; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); return; } static void GujaratiToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x0AE6: CurrentValue = 0; break; case 0x0AE7: CurrentValue = 1; break; case 0x0AE8: CurrentValue = 2; break; case 0x0AE9: CurrentValue = 3; break; case 0x0AEA: CurrentValue = 4; break; case 0x0AEB: CurrentValue = 5; break; case 0x0AEC: CurrentValue = 6; break; case 0x0AED: CurrentValue = 7; break; case 0x0AEE: CurrentValue = 8; break; case 0x0AEF: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void GreekAlphabeticToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue = 0; UTF32 c; short LeftKeraiaP = 0; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x0375: LeftKeraiaP = 1; break; case 0x0391: case 0x03B1: CurrentValue = 1; if (LeftKeraiaP) CurrentValue *= 1000; LeftKeraiaP = 0; break; case 0x0392: case 0x03B2: CurrentValue = 2; if (LeftKeraiaP) CurrentValue *= 1000; LeftKeraiaP = 0; break; case 0x0393: case 0x03B3: CurrentValue = 3; if (LeftKeraiaP) CurrentValue *= 1000; LeftKeraiaP = 0; break; case 0x0394: case 0x03B4: CurrentValue = 4; if (LeftKeraiaP) CurrentValue *= 1000; LeftKeraiaP = 0; break; case 0x0395: case 0x03B5: CurrentValue = 5; if (LeftKeraiaP) CurrentValue *= 1000; LeftKeraiaP = 0; break; case 0x03DA: /* Stigma */ case 0x03DB: /* Small stigma */ case 0x03DC: /* Digamma */ case 0x03DD: /* Small digamma */ CurrentValue = 6; if (LeftKeraiaP) CurrentValue *= 1000; LeftKeraiaP = 0; break; case 0x0396: case 0x03B6: CurrentValue = 7; if (LeftKeraiaP) CurrentValue *= 1000; LeftKeraiaP = 0; break; case 0x0397: case 0x03B7: CurrentValue = 8; if (LeftKeraiaP) CurrentValue *= 1000; LeftKeraiaP = 0; break; case 0x0398: case 0x03B8: CurrentValue = 9; if (LeftKeraiaP) CurrentValue *= 1000; LeftKeraiaP = 0; break; case 0x0399: case 0x03B9: CurrentValue = 10; LeftKeraiaP = 0; break; case 0x039A: case 0x03BA: CurrentValue = 20; LeftKeraiaP = 0; break; case 0x039B: case 0x03BB: CurrentValue = 30; LeftKeraiaP = 0; break; case 0x039C: case 0x03BC: CurrentValue = 40; LeftKeraiaP = 0; break; case 0x039D: case 0x03BD: CurrentValue = 50; LeftKeraiaP = 0; break; case 0x039E: case 0x03BE: CurrentValue = 60; LeftKeraiaP = 0; break; case 0x039F: case 0x03BF: CurrentValue = 70; LeftKeraiaP = 0; break; case 0x03A0: case 0x03C0: CurrentValue = 80; LeftKeraiaP = 0; break; case 0x03D8: /* Koppa */ case 0x03D9: CurrentValue = 90; LeftKeraiaP = 0; break; case 0x03A1: case 0x03C1: CurrentValue = 100; LeftKeraiaP = 0; break; case 0x03A3: case 0x03C3: CurrentValue = 200; LeftKeraiaP = 0; break; case 0x03A4: case 0x03C4: CurrentValue = 300; LeftKeraiaP = 0; break; case 0x03A5: case 0x03C5: CurrentValue = 400; LeftKeraiaP = 0; break; case 0x03A6: case 0x03C6: CurrentValue = 500; LeftKeraiaP = 0; break; case 0x03A7: case 0x03C7: CurrentValue = 600; LeftKeraiaP = 0; break; case 0x03A8: case 0x03C8: CurrentValue = 700; LeftKeraiaP = 0; break; case 0x03A9: case 0x03C9: CurrentValue = 800; LeftKeraiaP = 0; break; case 0x03E1: /* Small sanpi */ case 0x03E0: /* Sanpi */ CurrentValue = 900; LeftKeraiaP = 0; break; case 0x0374: /* Right keraia - just marks numbers - no value */ LeftKeraiaP = 0; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); return; } static void GurmukhiToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x0A66: CurrentValue = 0; break; case 0x0A67: CurrentValue = 1; break; case 0x0A68: CurrentValue = 2; break; case 0x0A69: CurrentValue = 3; break; case 0x0A6A: CurrentValue = 4; break; case 0x0A6B: CurrentValue = 5; break; case 0x0A6C: CurrentValue = 6; break; case 0x0A6D: CurrentValue = 7; break; case 0x0A6E: CurrentValue = 8; break; case 0x0A6F: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void HebrewToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; short PrevCharGereshP; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { PrevCharGereshP = 0; switch (c) { case 0x05D0: CurrentValue = 1; break; case 0x05D1: CurrentValue = 2; break; case 0x05D2: CurrentValue = 3; break; case 0x05D3: CurrentValue = 4; break; case 0x05D4: CurrentValue = 5; break; case 0x05D5: CurrentValue = 6; break; case 0x05D6: CurrentValue = 7; break; case 0x05D7: CurrentValue = 8; break; case 0x05D8: CurrentValue = 9; break; case 0x05D9: CurrentValue = 10; break; case 0x05DB: CurrentValue = 20; break; case 0x05DC: CurrentValue = 30; break; case 0x05DE: CurrentValue = 40; break; case 0x05E0: CurrentValue = 50; break; case 0x05E1: CurrentValue = 60; break; case 0x05E2: CurrentValue = 70; break; case 0x05E4: CurrentValue = 80; break; case 0x05E6: CurrentValue = 90; break; case 0x05E7: CurrentValue = 100; break; case 0x05E8: CurrentValue = 200; break; case 0x05E9: CurrentValue = 300; break; case 0x05EA: CurrentValue = 400; break; case 0x05DA: CurrentValue = 500; break; case 0x05DD: CurrentValue = 600; break; case 0x05DF: CurrentValue = 700; break; case 0x05E3: CurrentValue = 800; break; case 0x05E5: CurrentValue = 900; break; case 0x05F3: /* geresh */ case 0x0027: /* apostrophe */ mpz_mul_ui(Result,Result, 1000L); PrevCharGereshP = 1; break; case 0x05F4: /* gershayim */ break; case 0x0020: /* space */ break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } if(!PrevCharGereshP) mpz_add_ui(Result,Result,CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void KannadaToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x0CE6: CurrentValue = 0; break; case 0x0CE7: CurrentValue = 1; break; case 0x0CE8: CurrentValue = 2; break; case 0x0CE9: CurrentValue = 3; break; case 0x0CEA: CurrentValue = 4; break; case 0x0CEB: CurrentValue = 5; break; case 0x0CEC: CurrentValue = 6; break; case 0x0CED: CurrentValue = 7; break; case 0x0CEE: CurrentValue = 8; break; case 0x0CEF: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } #define KHAROSHTHI_THOUSAND 0x10A47 #define KHAROSHTHI_HUNDRED 0x10A46 #define KHAROSHTHI_FOUR 0x10A43 #define KHAROSHTHI_THREE 0x10A42 #define KHAROSHTHI_TWO 0x10A41 #define KHAROSHTHI_ONE 0x10A40 /* * A Kharoshthi number consists maximally of three components: * (a) a thousand sign and its coefficient, consisting of the numerals following it. * (b) a hundred sign and its coefficient, consisting of the numerals following it. * (c) an additive component, consisting of 1s, 2s, 3s, 4s, 10s, and 20s, at the beginning. */ static unsigned long KharoshthiToInt_NAMPZ(UTF32 *s) { unsigned long Total; unsigned long CurrentValue; UTF32 c; UTF32 *p; UTF32 *thptr; UTF32 *huptr; UTF32 *wrkcpy; Total = 0L; #ifdef ALLOCAOK wrkcpy = alloca(sizeof(UTF32) * (1 + ucslen(s))); #else wrkcpy = malloc(sizeof(UTF32) * (1 + ucslen(s))); #endif if(wrkcpy) ucscpy(wrkcpy,s); else { uninum_err = NS_ERROR_OUTOFMEMORY; return 0; } /* Handle thousands */ thptr = ucsrchr(wrkcpy,KHAROSHTHI_THOUSAND); if(thptr) { Total += (1000L * KharoshthiToInt_NAMPZ(thptr+1)); *thptr = 0x0000; } /* Handle hundreds */ huptr = ucsrchr(wrkcpy,KHAROSHTHI_HUNDRED); if(huptr) { Total += (100L * KharoshthiToInt_NAMPZ(huptr+1)); *huptr = 0x0000; } /* Handle the additive component - decades and units */ p = wrkcpy; while ((c = *p++) != 0x0000) { switch (c) { case 0x10A40: CurrentValue = 1; break; case 0x10A41: CurrentValue = 2; break; case 0x10A42: CurrentValue = 3; break; case 0x10A43: CurrentValue = 4; break; case 0x10A44: CurrentValue = 10; break; case 0x10A45: CurrentValue = 20; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; return 0; } Total += CurrentValue; } #ifndef ALLOCAOK free(wrkcpy); #endif return(Total); } static void KharoshthiToInt(mpz_t mpzResult, UTF32 *s) { uninum_err = NS_ERROR_OKAY; wcsrev(s); mpz_init_set_ui(mpzResult,KharoshthiToInt_NAMPZ(s)); } static void KhmerToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x17E0: CurrentValue = 0; break; case 0x17E1: CurrentValue = 1; break; case 0x17E2: CurrentValue = 2; break; case 0x17E3: CurrentValue = 3; break; case 0x17E4: CurrentValue = 4; break; case 0x17E5: CurrentValue = 5; break; case 0x17E6: CurrentValue = 6; break; case 0x17E7: CurrentValue = 7; break; case 0x17E8: CurrentValue = 8; break; case 0x17E9: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void KlingonToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0xF8F0: CurrentValue = 0; break; case 0xF8F1: CurrentValue = 1; break; case 0xF8F2: CurrentValue = 2; break; case 0xF8F3: CurrentValue = 3; break; case 0xF8F4: CurrentValue = 4; break; case 0xF8F5: CurrentValue = 5; break; case 0xF8F6: CurrentValue = 6; break; case 0xF8F7: CurrentValue = 7; break; case 0xF8F8: CurrentValue = 8; break; case 0xF8F9: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void LaoToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x0ED0: CurrentValue = 0; break; case 0x0ED1: CurrentValue = 1; break; case 0x0ED2: CurrentValue = 2; break; case 0x0ED3: CurrentValue = 3; break; case 0x0ED4: CurrentValue = 4; break; case 0x0ED5: CurrentValue = 5; break; case 0x0ED6: CurrentValue = 6; break; case 0x0ED7: CurrentValue = 7; break; case 0x0ED8: CurrentValue = 8; break; case 0x0ED9: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void LimbuToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x1946: CurrentValue = 0; break; case 0x1947: CurrentValue = 1; break; case 0x1948: CurrentValue = 2; break; case 0x1949: CurrentValue = 3; break; case 0x194A: CurrentValue = 4; break; case 0x194B: CurrentValue = 5; break; case 0x194C: CurrentValue = 6; break; case 0x194D: CurrentValue = 7; break; case 0x194E: CurrentValue = 8; break; case 0x194F: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void MalayalamToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x0D66: CurrentValue = 0; break; case 0x0D67: CurrentValue = 1; break; case 0x0D68: CurrentValue = 2; break; case 0x0D69: CurrentValue = 3; break; case 0x0D6A: CurrentValue = 4; break; case 0x0D6B: CurrentValue = 5; break; case 0x0D6C: CurrentValue = 6; break; case 0x0D6D: CurrentValue = 7; break; case 0x0D6E: CurrentValue = 8; break; case 0x0D6F: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } /* It may be desirable to reduce whitespace to a single space first */ /* * Mayan is not yet encoded so I've made up codepoints in the PUA * Expose this subroutine once the encoding is settled. */ static void MayanToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; int GroupCnt = 1; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ((c = *s++) != 0x0000) { switch (c) { case 0xFFC0: /* 0 - shell */ break; case 0xFFC1: /* 1 - dot */ CurrentValue = 1; break; case 0xFFC2: /* 5 - bar */ CurrentValue = 5; break; case 0x0020: if (++GroupCnt == 3) mpz_mul_ui(Result,Result,18L); else mpz_mul_ui(Result,Result,20L); break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void MongolianToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x1810: CurrentValue = 0; break; case 0x1811: CurrentValue = 1; break; case 0x1812: CurrentValue = 2; break; case 0x1813: CurrentValue = 3; break; case 0x1814: CurrentValue = 4; break; case 0x1815: CurrentValue = 5; break; case 0x1816: CurrentValue = 6; break; case 0x1817: CurrentValue = 7; break; case 0x1818: CurrentValue = 8; break; case 0x1819: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void NewTaiLueToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x19D0: CurrentValue = 0; break; case 0x19D1: CurrentValue = 1; break; case 0x19D2: CurrentValue = 2; break; case 0x19D3: CurrentValue = 3; break; case 0x19D4: CurrentValue = 4; break; case 0x19D5: CurrentValue = 5; break; case 0x19D6: CurrentValue = 6; break; case 0x19D7: CurrentValue = 7; break; case 0x19D8: CurrentValue = 8; break; case 0x19D9: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void NkoToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x07C0: CurrentValue = 0; break; case 0x07C1: CurrentValue = 1; break; case 0x07C2: CurrentValue = 2; break; case 0x07C3: CurrentValue = 3; break; case 0x07C4: CurrentValue = 4; break; case 0x07C5: CurrentValue = 5; break; case 0x07C6: CurrentValue = 6; break; case 0x07C7: CurrentValue = 7; break; case 0x07C8: CurrentValue = 8; break; case 0x07C9: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void OldItalicToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ((c = *s++) != 0x0000) { switch (c) { case 0x10320: /* 1 */ CurrentValue =1; break; case 0x10321: /* 5 */ CurrentValue =5; break; case 0x10322: /* 10 */ CurrentValue =10; break; case 0x10323: /* 50 */ CurrentValue =50; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_add_ui(Result,Result,CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void OldPersianToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ((c = *s++) != 0x0000) { switch (c) { case 0x103D1: /* 1 */ CurrentValue = 1; break; case 0x103D2: /* 2 */ CurrentValue = 2; break; case 0x103D3: /* 10 */ CurrentValue = 10; break; case 0x103D4: /* 20 */ CurrentValue = 20; break; case 0x103D5: /* 100 */ CurrentValue = 100; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void OriyaToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x0B66: CurrentValue = 0; break; case 0x0B67: CurrentValue = 1; break; case 0x0B68: CurrentValue = 2; break; case 0x0B69: CurrentValue = 3; break; case 0x0B6A: CurrentValue = 4; break; case 0x0B6B: CurrentValue = 5; break; case 0x0B6C: CurrentValue = 6; break; case 0x0B6D: CurrentValue = 7; break; case 0x0B6E: CurrentValue = 8; break; case 0x0B6F: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void OsmanyaToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x104A0: CurrentValue = 0; break; case 0x104A1: CurrentValue = 1; break; case 0x104A2: CurrentValue = 2; break; case 0x104A3: CurrentValue = 3; break; case 0x104A4: CurrentValue = 4; break; case 0x104A5: CurrentValue = 5; break; case 0x104A6: CurrentValue = 6; break; case 0x104A7: CurrentValue = 7; break; case 0x104A8: CurrentValue = 8; break; case 0x104A9: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void PhoenicianToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ((c = *s++) != 0x0000) { switch (c) { case 0x10916: /* 1 */ CurrentValue = 1; break; case 0x10917: /* 10 */ CurrentValue = 10; break; case 0x10918: /* 20 */ CurrentValue = 20; break; case 0x10919: /* 100 */ CurrentValue = 100; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void RomanToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; unsigned long PreviousValue = 0L; int Ccnt; int Rcnt; UTF32 *p; UTF32 *t; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); p = s; while ( (c = *p++) != 0x0000) { switch (c) { case 'I': case 'i': case 0x2160: case 0x2170: CurrentValue = 1; break; case 'V': case 'v': case 0x2164: case 0x2174: CurrentValue = 5; break; case 'X': case 'x': case 0x2169: case 0x2179: CurrentValue = 10; break; case 'L': case 'l': case 0x216C: case 0x217C: CurrentValue = 50; break; case 'C': case 'c': case 0x216D: case 0x217D: CurrentValue = 100; break; case 'D': case 'd': case 0x216E: case 0x217E: CurrentValue = 500; break; case 'M': case 'm': case 0x216F: case 0x217F: CurrentValue = 1000; break; case 0x2161: case 0x2171: CurrentValue = 2; break; case 0x2162: case 0x2172: CurrentValue = 3; break; case 0x2163: case 0x2173: CurrentValue = 4; break; case 0x2165: case 0x2175: CurrentValue = 6; break; case 0x2166: case 0x2176: CurrentValue = 7; break; case 0x2167: case 0x2177: CurrentValue = 8; break; case 0x2168: case 0x2178: CurrentValue = 9; break; case 0x216A: case 0x217A: CurrentValue = 11; break; case 0x216B: case 0x217B: CurrentValue = 12; break; case 0x2181: CurrentValue = 5000; break; case 0x2182: CurrentValue = 10000; break; case 0x0304: case 0x0305: CurrentValue = 0; PreviousValue *= 1000L; break; case 0x2183: /* Reverse C */ case 0x2184: CurrentValue = 0; if(PreviousValue != 1) {uninum_err = NS_ERROR_ILLFORMED;mpz_clear(Result);return;} PreviousValue = 0; Ccnt = 0; Rcnt = 1; t = p-3; /* Point at character before I/i */ while ((t >= s) && ( (*t == 'C') || (*t == 'c') || (*t == 0x216D) || (*t == 0x217D) )) { t--; Ccnt++; } mpz_sub_ui(Result,Result,100 * Ccnt); t = p; /* Point at character following first reverse C */ while ((*t == 0x2183) || (*t == 0x2184)) {Rcnt++; t++;} if (Rcnt < Ccnt) {uninum_err = NS_ERROR_ILLFORMED;mpz_clear(Result);return;} if(Ccnt > 0) CurrentValue = ipow(10,Ccnt+2); if(Rcnt != Ccnt) CurrentValue += (5 * ipow(10,Rcnt-Ccnt+1)); p+=(Rcnt-1); break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } if (PreviousValue >= CurrentValue) mpz_add_ui(Result,Result,PreviousValue); else mpz_sub_ui(Result,Result,PreviousValue); PreviousValue = CurrentValue; } if (PreviousValue >= CurrentValue) mpz_add_ui(Result,Result,PreviousValue); else mpz_sub_ui(Result,Result,PreviousValue); mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void RussianBrailleToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x2834: CurrentValue = 0; break; case 0x2802: CurrentValue = 1; break; case 0x2806: CurrentValue = 2; break; case 0x2812: CurrentValue = 3; break; case 0x2832: CurrentValue = 4; break; case 0x2822: CurrentValue = 5; break; case 0x2816: CurrentValue = 6; break; case 0x2836: CurrentValue = 7; break; case 0x2826: CurrentValue = 8; break; case 0x2814: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } /* * For mysterious reasons the Sinhala numerals are omitted from Unicode 5.0, * though the range for which they were proposed is left empty. This * assumes the proposed range. */ static void SinhalaToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ((c = *s++) != 0x0000) { switch (c) { case 0x0DE7: CurrentValue = 1; break; case 0x0DE8: CurrentValue = 2; break; case 0x0DE9: CurrentValue = 3; break; case 0x0DEA: CurrentValue = 4; break; case 0x0DEB: CurrentValue = 5; break; case 0x0DEC: CurrentValue = 6; break; case 0x0DED: CurrentValue = 7; break; case 0x0DEE: CurrentValue = 8; break; case 0x0DEF: CurrentValue = 9; break; case 0x0DF5: CurrentValue = 10; break; case 0x0DF6: CurrentValue = 20; break; case 0x0DF7: CurrentValue = 30; break; case 0x0DF8: CurrentValue = 40; break; case 0x0DF9: CurrentValue = 50; break; case 0x0DFA: CurrentValue = 60; break; case 0x0DFB: CurrentValue = 70; break; case 0x0DFC: CurrentValue = 80; break; case 0x0DFD: CurrentValue = 90; break; case 0x0DFE: CurrentValue = 100; break; case 0x0DFF: CurrentValue = 1000; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void TamilPlace (mpz_t Result, UTF32 *s) { unsigned long CurrentValue; UTF32 c; while ( (c = *s++) != 0x0000) { switch (c) { case 0x0BE6: CurrentValue = 0; break; case 0x0BE7: CurrentValue = 1; break; case 0x0BE8: CurrentValue = 2; break; case 0x0BE9: CurrentValue = 3; break; case 0x0BEA: CurrentValue = 4; break; case 0x0BEB: CurrentValue = 5; break; case 0x0BEC: CurrentValue = 6; break; case 0x0BED: CurrentValue = 7; break; case 0x0BEE: CurrentValue = 8; break; case 0x0BEF: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result,Result,10L); mpz_add_ui(Result, Result, CurrentValue); } return; } static UTF32 TamilBarriers [] = { 0x0BF0, /* 10 */ 0x0BF1, /* 100 */ 0x0BF2 /* 1000 */ }; static unsigned long TamilBarrierValue [] = { 10L, 100L, 1000L }; static inline UTF32 *SeekTamilBarrier (UTF32 *s, int *ri) { UTF32 *ptr; int bi = (sizeof(TamilBarriers)/sizeof(UTF32))-1; ptr = NULL; while (ptr == NULL && bi >= 0) { ptr = ucschr(s,TamilBarriers[bi--]); } *ri = bi+1; return ptr; } static void TamilToInt_MPZ(mpz_t ReturnValue, UTF32 *s) { UTF32 *ptr; UTF32 SavedBarrier; int i; mpz_t mul; mpz_t Result; mpz_t RightValue; ptr = SeekTamilBarrier(s,&i); if (ptr == NULL) { TamilPlace(ReturnValue,s); return; } mpz_init(mul); mpz_init(Result); mpz_init(RightValue); SavedBarrier = *ptr; *ptr = 0x0000; TamilToInt_MPZ(mul,s); *ptr = SavedBarrier; if (UEQ(mul,0L)) mpz_set_ui(mul,1L); mpz_mul_ui(Result,mul,TamilBarrierValue[i]); TamilToInt_MPZ(RightValue,ptr+1); mpz_add(Result,Result,RightValue); mpz_set(ReturnValue,Result); mpz_clear(Result); mpz_clear(RightValue); mpz_clear(mul); return; } static void TamilToInt(mpz_t mpzResult, UTF32 *s) { mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); TamilToInt_MPZ(Result,s); mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void TeluguToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x0C66: CurrentValue = 0; break; case 0x0C67: CurrentValue = 1; break; case 0x0C68: CurrentValue = 2; break; case 0x0C69: CurrentValue = 3; break; case 0x0C6A: CurrentValue = 4; break; case 0x0C6B: CurrentValue = 5; break; case 0x0C6C: CurrentValue = 6; break; case 0x0C6D: CurrentValue = 7; break; case 0x0C6E: CurrentValue = 8; break; case 0x0C6F: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void TengwarToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue = 0L; UTF32 *p; UTF32 c; int Base; mpz_t Result; uninum_err = NS_ERROR_OKAY; if(ucslen(s) % 2 != 0) { uninum_err = NS_ERROR_ILLFORMED; return; } if(s[1] == TENGWAR_DUODECIMAL_LSD_MARKER) Base = 12; else if(s[1] == TENGWAR_DUODECIMAL_MARKER) Base = 12; else if(s[1] == TENGWAR_DECIMAL_MARKER) Base = 10; else { uninum_err = NS_ERROR_ILLFORMED; return; } wcsrev(s); p = s; mpz_init(Result); while ((c = *p++) != 0L) { switch (c) { case TENGWAR_DECIMAL_MARKER: case TENGWAR_DUODECIMAL_MARKER: case TENGWAR_DUODECIMAL_LSD_MARKER: continue; case 0xE030: CurrentValue = 0; break; case 0xE033: CurrentValue = 1; break; case 0xE062: CurrentValue = 2; break; case 0xE063: CurrentValue = 3; break; case 0xE064: CurrentValue = 4; break; case 0xE065: CurrentValue = 5; break; case 0xE066: CurrentValue = 6; break; case 0xE067: CurrentValue = 7; break; case 0xE068: CurrentValue = 8; break; case 0xE069: CurrentValue = 9; break; case 0xE06A: CurrentValue = 10; break; case 0xE06B: CurrentValue = 11; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, Base); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void ThaiToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x0E50: CurrentValue = 0; break; case 0x0E51: CurrentValue = 1; break; case 0x0E52: CurrentValue = 2; break; case 0x0E53: CurrentValue = 3; break; case 0x0E54: CurrentValue = 4; break; case 0x0E55: CurrentValue = 5; break; case 0x0E56: CurrentValue = 6; break; case 0x0E57: CurrentValue = 7; break; case 0x0E58: CurrentValue = 8; break; case 0x0E59: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void TibetanToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0x0000) { switch (c) { case 0x0F20: CurrentValue = 0; break; case 0x0F21: CurrentValue = 1; break; case 0x0F22: CurrentValue = 2; break; case 0x0F23: CurrentValue = 3; break; case 0x0F24: CurrentValue = 4; break; case 0x0F25: CurrentValue = 5; break; case 0x0F26: CurrentValue = 6; break; case 0x0F27: CurrentValue = 7; break; case 0x0F28: CurrentValue = 8; break; case 0x0F29: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void VerdurianToInt(mpz_t mpzResult, UTF32 *s) { unsigned long CurrentValue; UTF32 c; mpz_t Result; uninum_err = NS_ERROR_OKAY; mpz_init(Result); while ( (c = *s++) != 0L) { switch (c) { case 0xE260: CurrentValue = 0; break; case 0xE261: CurrentValue = 1; break; case 0xE262: CurrentValue = 2; break; case 0xE263: CurrentValue = 3; break; case 0xE264: CurrentValue = 4; break; case 0xE265: CurrentValue = 5; break; case 0xE266: CurrentValue = 6; break; case 0xE267: CurrentValue = 7; break; case 0xE268: CurrentValue = 8; break; case 0xE269: CurrentValue = 9; break; default: /* Error */ uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, 10L); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } void WesternGeneralToInt(mpz_t mpzResult, UTF32 *s, int Base) { unsigned long CurrentValue; UTF32 c; mpz_t Result; unsigned long b; uninum_err = NS_ERROR_OKAY; if ((Base > 36) || (Base < 1)) { uninum_err = NS_ERROR_BADBASE; return; } if(Base == 1) { mpz_init_set_ui(mpzResult, ucslen(s)); return; } b = (unsigned long) Base; mpz_init(Result); while ( (c = *s++) != 0L) { if ( (c >= 0x0030) && (c <= 0x0039)) CurrentValue = c - 0x0030; else if ( (c >= 0x0041) && (c <= 0x005B)) CurrentValue = c - 0x0037; else if ( (c >= 0x0061) && (c <= 0x007B)) CurrentValue = c - 0x0057; else { uninum_err = NS_ERROR_BADCHARACTER; uninum_badchar = c; mpz_clear(Result); return; } if (CurrentValue >= b) { uninum_err = NS_ERROR_NOTCONSISTENTWITHBASE; mpz_clear(Result); return; } mpz_mul_ui(Result, Result, b); mpz_add_ui(Result, Result, CurrentValue); } mpz_init_set(mpzResult, Result); mpz_clear(Result); } static void SetRvalZero(union ns_rval *rvalp, short ReturnType) { switch(ReturnType) { case NS_TYPE_ULONG: rvalp->u = 0L; break; case NS_TYPE_STRING: rvalp->s = malloc(2 *sizeof(char)); rvalp->s[0] = '0'; rvalp->s[1] = '\0'; break; case NS_TYPE_MPZT: mpz_set_ui(rvalp->m,0L); break; } } void StringToInt(union ns_rval *rvalp, UTF32 *s, short ReturnType,int NumberSystem) { mpz_t Result; uninum_err = NS_ERROR_OKAY; if ((NS_ALL == NumberSystem) || (NS_ANY == NumberSystem)) NumberSystem = GuessNumberSystem(s); wcStripSeparators(s); switch (NumberSystem) { case NS_AEGEAN: AegeanToInt(Result,s); break; case NS_ARABIC_WESTERN: ArabicToInt(Result,s); break; case NS_PERSO_ARABIC: ArabicExtendedToInt(Result,s); break; case NS_ARABIC_ALPHABETIC: ArabicAlphabeticToInt(Result,s); break; case NS_ARMENIAN_ALPHABETIC: ArmenianAlphabeticToInt(Result,s); break; case NS_BALINESE: BalineseToInt(Result,s); break; case NS_BENGALI: BengaliToInt(Result,s); break; case NS_BURMESE: BurmeseToInt(Result,s); break; case NS_CHINESE_GENERIC: case NS_CHINESE_REGULAR_SIMPLIFIED: case NS_CHINESE_REGULAR_TRADITIONAL: case NS_CHINESE_LEGAL_TRADITIONAL: case NS_CHINESE_LEGAL_SIMPLIFIED: case NS_CHINESE_MANDARIN_REGULAR_TRADITIONAL: case NS_CHINESE_MANDARIN_REGULAR_SIMPLIFIED: case NS_CHINESE_MANDARIN_LEGAL_TRADITIONAL: case NS_CHINESE_MANDARIN_LEGAL_SIMPLIFIED: case NS_CHINESE_JAPANESE_REGULAR_SIMPLIFIED: case NS_CHINESE_JAPANESE_REGULAR_TRADITIONAL: case NS_CHINESE_JAPANESE_LEGAL_SIMPLIFIED: case NS_CHINESE_JAPANESE_LEGAL_TRADITIONAL: case NS_CHINESE_JAPANESE_WESTERN_MIX: case NS_CHINESE_REGULAR_PLACE: case NS_CHINESE_SUZHOU: ChineseToInt(Result,NormalizeChineseNumbers(s)); break; case NS_CHINESE_COUNTING_ROD_GENERIC: case NS_CHINESE_COUNTING_ROD_EARLY_WITH_ZERO: case NS_CHINESE_COUNTING_ROD_LATE_WITH_ZERO: case NS_CHINESE_COUNTING_ROD_EARLY_WITHOUT_ZERO: case NS_CHINESE_COUNTING_ROD_LATE_WITHOUT_ZERO: ChineseCountingRodToInt(Result,s); break; case NS_COMMON_BRAILLE: CommonBrailleToInt(Result,s); break; case NS_CYRILLIC_ALPHABETIC: CyrillicAlphabeticToInt(Result,s); break; case NS_DEVANAGARI: DevanagariToInt(Result,s); break; case NS_EGYPTIAN: EgyptianToInt(Result,s); break; case NS_ETHIOPIC: EthiopicToInt(Result,s); break; case NS_EWELLIC_DECIMAL: EwellicDecimalToInt(Result,s); break; case NS_EWELLIC_HEX: EwellicHexToInt(Result,s); break; case NS_FRENCH_BRAILLE: FrenchBrailleToInt(Result,s); break; case NS_MXEDRULI: case NS_XUCURI_LOWER: case NS_XUCURI_UPPER: GeorgianAlphabeticToInt(Result,s); break; case NS_GLAGOLITIC_ALPHABETIC: GlagoliticAlphabeticToInt(Result,s); break; case NS_GREEK_ALPHABETIC_UPPER: case NS_GREEK_ALPHABETIC_LOWER: GreekAlphabeticToInt(Result,s); break; case NS_GUJARATI: GujaratiToInt(Result,s); break; case NS_GURMUKHI: GurmukhiToInt(Result,s); break; case NS_HEBREW_GENERIC: case NS_HEBREW_EARLY: case NS_HEBREW_LATE: HebrewToInt(Result,s); break; case NS_HEX: case NS_HEX_LOWER: case NS_HEX_UPPER: WesternGeneralToInt(Result,s+2,16); /* s+2 to skip the initial 0x */ break; case NS_KANNADA: KannadaToInt(Result,s); break; case NS_KHAROSHTHI: KharoshthiToInt(Result,s); break; case NS_KHMER: KhmerToInt(Result,s); break; case NS_KLINGON: KlingonToInt(Result,s); break; case NS_LAO: LaoToInt(Result,s); break; case NS_LIMBU: LimbuToInt(Result,s); break; case NS_MALAYALAM: MalayalamToInt(Result,s); break; case NS_MAYAN: MayanToInt(Result,s); break; case NS_MONGOLIAN: MongolianToInt(Result,s); break; case NS_NEW_TAI_LUE: NewTaiLueToInt(Result,s); break; case NS_NKO: NkoToInt(Result,s); break; case NS_OLD_ITALIC: OldItalicToInt(Result,s); break; case NS_OLD_PERSIAN: OldPersianToInt(Result,s); break; case NS_ORIYA: OriyaToInt(Result,s); break; case NS_OSMANYA: OsmanyaToInt(Result,s); break; case NS_PHOENICIAN: PhoenicianToInt(Result,s); break; case NS_ROMAN_GENERIC: case NS_ROMAN_UPPER: case NS_ROMAN_LOWER: RomanToInt(Result,s); break; case NS_RUSSIAN_BRAILLE: RussianBrailleToInt(Result,s); break; case NS_SINHALA: SinhalaToInt(Result,s); break; case NS_TAMIL_GENERIC: case NS_TAMIL_PLACE: case NS_TAMIL_TRADITIONAL: TamilToInt(Result,s); break; case NS_TELUGU: TeluguToInt(Result,s); break; case NS_TENGWAR_DECIMAL: case NS_TENGWAR_DUODECIMAL: TengwarToInt(Result,s); break; case NS_THAI: ThaiToInt(Result,s); break; case NS_TIBETAN: TibetanToInt(Result,s); break; case NS_VERDURIAN: VerdurianToInt(Result,s); break; case NS_WESTERN_GENERIC: case NS_WESTERN_LOWER: case NS_WESTERN_UPPER: WesternGeneralToInt(Result,s,Uninum_Input_Base); break; default: uninum_err = NS_ERROR_NUMBER_SYSTEM_UNKNOWN; break; } /* End of switch */ if(!uninum_err) { if (ReturnType == NS_TYPE_STRING) { rvalp->s = malloc(sizeof(char) * (1 + mpz_sizeinbase(Result,10))); if(!rvalp->s) { uninum_err = NS_ERROR_OUTOFMEMORY; return; } (void) mpz_get_str(rvalp->s,10,Result); } else if (ReturnType == NS_TYPE_ULONG) { if(!mpz_fits_ulong_p(Result)) uninum_err = NS_ERROR_DOESNOTFIT; else rvalp->u = mpz_get_ui(Result); } else mpz_set(rvalp->m,Result); mpz_clear(Result); } if(uninum_err) SetRvalZero(rvalp,ReturnType); return; } /* Code for generating strings from integers */ /* * PlaceIntToString assumes that the number system has the following properties: * (a) it is place-based; * (b) its digits are contiguous and in ascending order in Unicode; */ #define ARABIC_ZERO 0x0660 #define BALINESE_ZERO 0x1B50 #define BENGALI_ZERO 0x09E6 #define BURMESE_ZERO 0x1040 #define CHINESE_COUNTING_ROD_EARLY_ZERO 0x1D368 #define CHINESE_COUNTING_ROD_LATE_ZERO 0x1D35F #define DEVANAGARI_ZERO 0x0966 #define EWELLIC_ZERO 0xE6C0 #define GUJARATI_ZERO 0x0AE6 #define GURMUKHI_ZERO 0x0A66 #define KANNADA_ZERO 0x0CE6 #define KHMER_ZERO 0x17E0 #define KLINGON_ZERO 0xF8F0 #define LAO_ZERO 0x0ED0 #define LIMBU_ZERO 0x1946 #define MALAYALAM_ZERO 0x0D66 #define MONGOLIAN_ZERO 0x1810 #define NEW_TAI_LUE_ZERO 0x19D0 #define NKO_ZERO 0x07C0 #define ORIYA_ZERO 0x0B66 #define OSMANYA_ZERO 0x104A0 #define PERSO_ARABIC_ZERO 0x06F0 #define ROMAN_ZERO 0x0030 #define SUZHOU_ZERO 0x3020 #define TAMIL_ZERO 0x0BE6 #define TELUGU_ZERO 0x0C66 #define THAI_ZERO 0x0E50 #define TIBETAN_ZERO 0x0F20 #define VERDURIAN_ZERO 0xE260 #define WESTERN_ZERO 0x0030 static UTF32 * PlaceIntToString(mpz_t n, UTF32 ZeroCode, unsigned int Base) { int Digits; /* Number of digits in string */ UTF32 *s; UTF32 *p; UTF32 *new; mpz_t d; mpz_t k; mpz_t q; mpz_t r; unsigned long int temp; int offset; mpz_init(d); mpz_init(q); mpz_init(r); mpz_init_set(k,n); Digits = mpz_sizeinbase(k,Base); new = malloc((Digits + 1) * sizeof(UTF32)); if (!new) { uninum_err = NS_ERROR_OUTOFMEMORY; return NULL; } p = s = new; /* Do conversion */ do { mpz_tdiv_qr_ui(q,r,k,Base); *s++ = (ZeroCode + mpz_get_ui(r)); mpz_set(k,q); } while (UGT(q,0L)); *s = 0x0000; /* Null terminate string */ s--; /* Point s at last non-null char */ mpz_clear(d);mpz_clear(k);mpz_clear(q);mpz_clear(r); /* * Now we reverse the string. When we begin, p points at the first * character of the string, s at the last non-null character. */ while(p <= s){ temp = *p; *p++ = *s; *s-- = temp; } return new; } static UTF32 * PlaceNonContiguousIntToString(mpz_t n, UTF32 **DigitList, int Base){ int Digits; /* Number of digits in string */ UTF32 *s; UTF32 *p; UTF32 *new; mpz_t k; mpz_t q; mpz_t r; unsigned long int temp; int offset; mpz_init_set(k,n); Digits = mpz_sizeinbase(k,Base); new = malloc((Digits + 1) * sizeof(UTF32)); if (!new) { uninum_err = NS_ERROR_OUTOFMEMORY; mpz_clear(k); return NULL; } p = s = new; /* Do conversion */ mpz_init(q); mpz_init(r); do { mpz_tdiv_qr_ui(q,r,k,Base); *s++ = DigitList[mpz_get_ui(r)][0]; mpz_set(k,q); } while (UGT(q,0L)); *s = 0x0000; /* Null terminate string */ s--; /* Point s at last non-null char */ mpz_clear(k);mpz_clear(q);mpz_clear(r); /* * Now we reverse the string. When we begin, p points at the first * character of the string, s at the last non-null character. */ while(p <= s){ temp = *p; *p++ = *s; *s-- = temp; } return new; } UTF32 tengd0[2] = {0xE030,0x0000}; UTF32 tengd1[2] = {0xE033,0x0000}; UTF32 tengd2[2] = {0xE062,0x0000}; UTF32 tengd3[2] = {0xE063,0x0000}; UTF32 tengd4[2] = {0xE064,0x0000}; UTF32 tengd5[2] = {0xE065,0x0000}; UTF32 tengd6[2] = {0xE066,0x0000}; UTF32 tengd7[2] = {0xE067,0x0000}; UTF32 tengd8[2] = {0xE068,0x0000}; UTF32 tengd9[2] = {0xE069,0x0000}; UTF32 tengd10[2] = {0xE06A,0x0000}; UTF32 tengd11[2] = {0xE06B,0x0000}; UTF32 *TengwarDigits[]={ tengd0, tengd1, tengd2, tengd3, tengd4, tengd5, tengd6, tengd7, tengd8, tengd9, tengd10, tengd11 }; static UTF32 * TengwarToString(mpz_t n,int Base){ int Digits; /* Number of digits in string */ UTF32 *s; UTF32 *new; UTF32 BaseMarker; mpz_t k; mpz_t q; mpz_t r; mpz_init_set(k,n); Digits = mpz_sizeinbase(k,Base); new = malloc(((2 * Digits) + 1) * sizeof(UTF32)); if (!new) { uninum_err = NS_ERROR_OUTOFMEMORY; mpz_clear(k); return NULL; } if(Base == 12) BaseMarker = TENGWAR_DUODECIMAL_MARKER; else BaseMarker = TENGWAR_DECIMAL_MARKER; s = new; /* Do conversion */ mpz_init(q); mpz_init(r); do { mpz_tdiv_qr_ui(q,r,k,Base); *s++ = TengwarDigits[mpz_get_ui(r)][0]; *s++ = BaseMarker; mpz_set(k,q); } while (UGT(q,0L)); *s = 0L; /* Null terminate string */ if(Base == 12) new[1] = TENGWAR_DUODECIMAL_LSD_MARKER; mpz_clear(k);mpz_clear(q);mpz_clear(r); return new; } struct vcpair ArabicAlphabeticData[]={ {1999,0xFFDF}, {1000,0x063A}, {900,0x0638}, {800,0x0636}, {700,0x0630}, {600,0x062E}, {500,0x062B}, {400,0x062A}, {300,0x0634}, {200,0x0631}, {100,0x0642}, {90,0x0635}, {80,0x0641}, {70,0x0639}, {60,0x0633}, {50,0x0646}, {40,0x0645}, {30,0x0644}, {20,0x0643}, {10,0x064A}, {9,0x0637}, {8,0x062D}, {7,0x0632}, {6,0x0648}, {5,0x0647}, {4,0x062F}, {3,0x062C}, {2,0x0628}, {1,0x0627}, {0,0xFFDF} }; struct vcpair AegeanData[]={ {99999,0xFFDF}, {90000,0x10133}, {80000,0x10132}, {70000,0x10131}, {60000,0x10130}, {50000,0x1012F}, {40000,0x1012E}, {30000,0x1012D}, {20000,0x1012C}, {10000,0x1012B}, {9000,0x1012A}, {8000,0x10129}, {7000,0x10128}, {6000,0x10127}, {5000,0x10126}, {4000,0x10125}, {3000,0x10124}, {2000,0x10123}, {1000,0x10122}, {900,0x10121}, {800,0x10120}, {700,0x1011F}, {600,0x1011E}, {500,0x1011D}, {400,0x1011C}, {300,0x1011B}, {200,0x1011A}, {100,0x10119}, {90,0x10118}, {80,0x10117}, {70,0x10116}, {60,0x10115}, {50,0x10114}, {40,0x10113}, {30,0x10112}, {20,0x10111}, {10,0x10110}, {9,0x1010F}, {8,0x1010E}, {7,0x1010D}, {6,0x1010C}, {5,0x1010B}, {4,0x1010A}, {3,0x10109}, {2,0x10108}, {1,0x10107}, {0,0xFFDF} }; struct vcpair ArmenianData[]={ {9999,0xFFDF}, {9000,0x0554}, {8000,0x0553}, {7000,0x0552}, {6000,0x0551}, {5000,0x0550}, {4000,0x054F}, {3000,0x054E}, {2000,0x054D}, {1000,0x054C}, {900,0x054B}, {800,0x054A}, {700,0x0549}, {600,0x0548}, {500,0x0547}, {400,0x0546}, {300,0x0545}, {200,0x0544}, {100,0x0543}, {90,0x00542}, {80,0x0541}, {70,0x0540}, {60,0x053F}, {50,0x053E}, {40,0x053D}, {30,0x053C}, {20,0x053B}, {10,0x053A}, {9,0x0539}, {8,0x0538}, {7,0x0537}, {6,0x0536}, {5,0x0535}, {4,0x0534}, {3,0x0533}, {2,0x0532}, {1,0x0531}, {0,0xFFDF} }; struct vcpair CyrillicData[]={ {999,0xFFDF}, {900,0x0426}, {800,0x0460}, {700,0x0470}, {600,0x0425}, {500,0x0424}, {400,0x0478}, {300,0x0422}, {200,0x0421}, {100,0x0420}, {90,0x0427}, {80,0x041F}, {70,0x041E}, {60,0x046E}, {50,0x041D}, {40,0x041C}, {30,0x041B}, {20,0x041A}, {10,0x0406}, {9,0x0472}, {8,0x0418}, {7,0x0417}, {6,0x0405}, {5,0x0415}, {4,0x0414}, {3,0x0413}, {2,0x0411}, {1,0x0410}, {0,0xFFDF} }; struct vcpair EgyptianData[]={ {9999999,0xFFDF}, {1000000,0x14064}, {100000,0x14173}, {10000,0x140A7}, {1000,0x141A2}, {100,0x1433B}, {10,0x14353}, {1,0x143A1}, {0,0xFFDF} }; struct vcpair EthiopicData[]={ {9999999,0xFFDF}, /* Dummy - real max is in subroutine */ {90,0x137A}, {80,0x1379}, {70,0x1378}, {60,0x1377}, {50,0x1376}, {40,0x1375}, {30,0x1374}, {20,0x1373}, {10,0x1372}, {9,0x1371}, {8,0x1370}, {7,0x136F}, {6,0x136E}, {5,0x136D}, {4,0x136C}, {3,0x136B}, {2,0x136A}, {1,0x1369}, {0,0xFFDF} }; struct vcpair GlagoliticData[]={ {9999,0xFFDF}, {2000,0x2C1E}, {1000,0x2C1D}, {900,0x2C1C}, {800,0x2C1B}, {700,0x2C19}, {600,0x2C18}, {500,0x2C17}, {400,0x2C16}, {300,0x2C15}, {200,0x2C14}, {100,0x2C13}, {90,0x2C12}, {80,0x2C11}, {70,0x2C10}, {60,0x2C0F}, {50,0x2C0E}, {40,0x2C0D}, {30,0x2C0C}, {20,0x2C0B}, {10,0x2C09}, {9,0x2C08}, {8,0x2C07}, {7,0x2C06}, {6,0x2C05}, {5,0x2C04}, {4,0x2C03}, {3,0x2C02}, {2,0x2C01}, {1,0x2C00}, {0,0xFFDF} }; struct vcpair GreekUpperData[]={ {9999,0xFFDF}, {900,0x03E0}, {800,0x03A9}, {700,0x03A8}, {600,0x03A7}, {500,0x03A6}, {400,0x03A5}, {300,0x03A4}, {200,0x03A3}, {100,0x03A1}, {90,0x03D8}, {80,0x03A0}, {70,0x039F}, {60,0x039E}, {50,0x039D}, {40,0x039C}, {30,0x039B}, {20,0x039A}, {10,0x0399}, {9,0x0398}, {8,0x0397}, {7,0x0396}, {6,0x03DA}, {5,0x0395}, {4,0x0394}, {3,0x0393}, {2,0x0392}, {1,0x0391}, {0,0xFFDF} }; struct vcpair GreekLowerData[]={ {9999,0xFFDF}, {900,0x03E1}, {800,0x03C9}, {700,0x03C8}, {600,0x03C7}, {500,0x03C6}, {400,0x03C5}, {300,0x03C4}, {200,0x03C3}, {100,0x03C1}, {90,0x03D9}, {80,0x03C0}, {70,0x03BF}, {60,0x03BE}, {50,0x03BD}, {40,0x03BC}, {30,0x03BB}, {20,0x03BA}, {10,0x03B9}, {9,0x03B8}, {8,0x03B7}, {7,0x03B6}, {6,0x03DB}, {5,0x03B5}, {4,0x03B4}, {3,0x03B3}, {2,0x03B2}, {1,0x03B1}, {0,0xFFDF} }; struct vcpair HebrewData[]={ {9999,0xFFDF}, {900,0x05E5}, {800,0x05E3}, {700,0x05DF}, {600,0x05DD}, {500,0x05DA}, {400,0x05EA}, {300,0x05E9}, {200,0x05E8}, {100,0x05E7}, {90,0x05E6}, {80,0x05E4}, {70,0x05E2}, {60,0x05E1}, {50,0x05E0}, {40,0x05DE}, {30,0x05DC}, {20,0x05DB}, {10,0x05D9}, {9,0x05D8}, {8,0x05D7}, {7,0x05D6}, {6,0x05D5}, {5,0x05D4}, {4,0x05D3}, {3,0x05D2}, {2,0x05D1}, {1,0x05D0}, {0,0xFFDF} }; struct vcpair MxedruliData[]={ {10000,0xFFDF}, {10000,0x10f5}, {9000,0x10f0}, {8000,0x10ef}, {7000,0x10f4}, {6000,0x10ee}, {5000,0x10ed}, {4000,0x10ec}, {3000,0x10eb}, {2000,0x10ea}, {1000,0x10e9}, {900,0x10e8}, {800,0x10e7}, {700,0x10e6}, {600,0x10e5}, {500,0x10e4}, {400,0x10e3}, {300,0x10e2}, {200,0x10e1}, {100,0x10e0}, {90,0x10df}, {80,0x10de}, {70,0x10dd}, {60,0x10f2}, {50,0x10dc}, {40,0x10db}, {30,0x10da}, {20,0x10d9}, {10,0x10d8}, {9,0x10d7}, {8,0x10F1}, {7,0x10d6}, {6,0x10d5}, {5,0x10d4}, {4,0x10d3}, {3,0x10d2}, {2,0x10d1}, {1,0x10D0}, {0,0xFFDF} }; struct vcpair PhoenicianData[]={ {999,0xFFDF}, {100,0x10919}, {20,0x10918}, {10,0x10917}, {1,0x10916}, {0,0xFFDF} }; struct vcpair OldItalicData[]={ {999,0xFFDF}, {50,0x10323}, {10,0x10322}, {5,0x10321}, {1,0x10320}, {0,0xFFDF} }; struct vcpair OldPersianData[]={ {999,0xFFDF}, {100,0x103D5}, {20,0x103D4}, {10,0x103D3}, {2,0x103D2}, {1,0x103D1}, {0,0xFFDF} }; struct vcpair SinhalaData[]={ {9999,0xFFDF}, {1000,0x0DFF}, {100,0x0DFE}, {90,0x0DFD}, {80,0x0DFC}, {70,0x0DFB}, {60,0x0DFA}, {50,0x0DF9}, {40,0x0DF8}, {30,0x0DF7}, {20,0x0DF6}, {10,0x0DF5}, {9,0x0DEF}, {8,0x0DEE}, {7,0x0DED}, {6,0x0DEC}, {5,0x0DEB}, {4,0x0DEA}, {3,0x0DE9}, {2,0x0DE8}, {1,0x0DE7}, {0,0xFFDF} }; struct vcpair XucuriLowerData[]={ {10000,0xFFDF}, {10000,0x2D25}, {9000,0x2D20}, {8000,0x2D1F}, {7000,0x2D24}, {6000,0x2D1E}, {5000,0x2D1D}, {4000,0x2D1C}, {3000,0x2D1B}, {2000,0x2D1A}, {1000,0x2D19}, {900,0x2D18}, {800,0x2D17}, {700,0x2D16}, {600,0x2D15}, {500,0x2D14}, {400,0x2D13}, {300,0x2D12}, {200,0x2D11}, {100,0x2D10}, {90,0x2D0F}, {80,0x2D0E}, {70,0x2D0D}, {60,0x2D22}, {50,0x2D0C}, {40,0x2D0B}, {30,0x2D0A}, {20,0x2D09}, {10,0x2D08}, {9,0x2D07}, {8,0x2D21}, {7,0x2D06}, {6,0x2D05}, {5,0x2D04}, {4,0x2D03}, {3,0x2D02}, {2,0x2D01}, {1,0x2D00}, {0,0xFFDF} }; struct vcpair XucuriUpperData[]={ {10000,0xFFDF}, {10000,0x10C5}, {9000,0x10C0}, {8000,0x10BF}, {7000,0x10C4}, {6000,0x10BE}, {5000,0x10BD}, {4000,0x10BC}, {3000,0x10BB}, {2000,0x10BA}, {1000,0x10B9}, {900,0x10B8}, {800,0x10B7}, {700,0x10B6}, {600,0x10B5}, {500,0x10B4}, {400,0x10B3}, {300,0x10B2}, {200,0x10B1}, {100,0x10B0}, {90,0x10AF}, {80,0x10AE}, {70,0x10AD}, {60,0x10C2}, {50,0x10AC}, {40,0x10AB}, {30,0x10AA}, {20,0x10A9}, {10,0x10A8}, {9,0x10A7}, {8,0x10C1}, {7,0x10A6}, {6,0x10A5}, {5,0x10A4}, {4,0x10A3}, {3,0x10A2}, {2,0x10A1}, {1,0x10A0}, {0,0xFFDF} }; /* * This is based on the maximum for Egyptian. If * other systems are added, it may need to be * increased. */ #define ADDITIVE_CHARS_NEEDED 54 static UTF32 * AdditiveIntToString(mpz_t k, struct vcpair *data) { int Digits; int i; int iRepeat; unsigned long j; int oi = 0; UTF32 tmp [ADDITIVE_CHARS_NEEDED+1]; UTF32 *new; struct vcpair *p; mpz_t Repeat; mpz_t Residue; p = data; j = mpz_get_ui(k); if (j > p->v) { uninum_err = NS_ERROR_RANGE; return NULL; } if(UEQ(k,0)) { uninum_err = NS_ERROR_NOZERO; return NULL; } mpz_init(Repeat); mpz_init_set(Residue,k); p++; /* Skip over maximum */ while (p->v) { mpz_tdiv_q_ui(Repeat,Residue,p->v); iRepeat = mpz_get_ui(Repeat); for (i=0;i < iRepeat;i++) tmp[oi++] = p->c; mpz_submul_ui(Residue,Repeat,p->v); p++; } mpz_clear(Repeat); mpz_clear(Residue); tmp[oi] = 0x0000; Digits = ucslen(tmp); new = malloc((Digits + 1) * sizeof(UTF32)); if (!new) { uninum_err = NS_ERROR_OUTOFMEMORY; return NULL; } return(ucscpy(new,tmp)); } #define CYRILLIC_ONE 0x0410 #define CYRILLIC_NINE 0x0472 #define CYRILLIC_TEN 0x0406 #define CYRILLIC_THOUSANDS_SIGN 0x0482 #define CYRILLIC_TITLO 0x0483 #define CYRILLIC_CHARS_NEEDED 6 static UTF32 * CyrillicAlphabeticIntToString(mpz_t n) { int Digits; int i; int oi = 0; unsigned long k; unsigned long Residue; unsigned long Thousands; int Repeat; UTF32 tmp [CYRILLIC_CHARS_NEEDED+1]; UTF32 *new; struct vcpair *p; /* Given the limited range, we'd might as well use ordinary arithmetic */ k = mpz_get_ui(n); p = CyrillicData; if (k > p->v) { uninum_err = NS_ERROR_RANGE; return NULL; } if(k == 0) { uninum_err = NS_ERROR_NOZERO; return NULL; } Residue = k; p++; /* Skip maximum */ Thousands = k/1000L; if(Thousands > 0) { tmp[oi++] = CYRILLIC_THOUSANDS_SIGN; tmp[oi++] = (CyrillicData + 27 - Thousands)->c; Residue -= (Thousands * 1000L); } while (p->v) { Repeat = Residue/p->v; for (i=0;i < Repeat;i++) tmp[oi++] = p->c; Residue -= (Repeat * p->v); p++; } // tmp[oi++] = CYRILLIC_TITLO; tmp[oi] = 0x0000; /* Reorder 11-19 to spoken order */ UTF32 c1 = tmp[oi-2]; UTF32 c2 = tmp[oi-1]; if ( (c1 == CYRILLIC_TEN) && ( (c2 >= CYRILLIC_ONE) && (c2 <= CYRILLIC_NINE))) { tmp[oi-2] = c2; tmp[oi-1] = c1; } Digits = ucslen(tmp); new = malloc((Digits + 1) * sizeof(UTF32)); if (!new) { uninum_err = NS_ERROR_OUTOFMEMORY; return NULL; } return(ucscpy(new,tmp)); } #define GREEK_CHARS_NEEDED 5 static UTF32 * GreekAlphabeticIntToString(mpz_t k, short LowerCaseP) { int Digits; int i; int Thousands; int iRepeat; int oi = 0; UTF32 tmp [GREEK_CHARS_NEEDED+1]; UTF32 *new; struct vcpair *p; mpz_t Repeat; mpz_t Residue; if(UEQ(k,0)) { uninum_err = NS_ERROR_NOZERO; return NULL; } if(LowerCaseP) p = GreekLowerData; else p = GreekUpperData; if(UGT(k,p->v)) { uninum_err = NS_ERROR_RANGE; return NULL; } p++; /* Skip maximum */ mpz_init(Repeat); mpz_init_set(Residue,k); mpz_tdiv_q_ui(Repeat,k,1000); Thousands = mpz_get_ui(Repeat); if(Thousands) { tmp[oi++] = GREEK_ALPHABETIC_LEFT_KERAIA; tmp[oi++] = (p + (sizeof(GreekUpperData)/sizeof(struct vcpair)) - Thousands -2)->c; } mpz_submul_ui(Residue,Repeat,1000); while (p->v) { mpz_tdiv_q_ui(Repeat,Residue,p->v); iRepeat = mpz_get_ui(Repeat); for (i=0;i < iRepeat;i++) tmp[oi++] = p->c; mpz_submul_ui(Residue,Repeat,p->v); p++; } mpz_clear(Repeat); mpz_clear(Residue); tmp[oi] = 0x0000; Digits = ucslen(tmp); new = malloc((Digits + 1) * sizeof(UTF32)); if (!new) { uninum_err = NS_ERROR_OUTOFMEMORY; return NULL; } return(ucscpy(new,tmp)); } static UTF32 RomanDigitsUpper[]={ L'I', L'V', L'X', L'L', L'C', L'D', L'M' }; static UTF32 RomanDigitsLower[]={ L'i', L'v', L'x', L'l', L'c', L'd', L'm' }; #define R_1 0 #define R_5 1 #define R_10 2 #define R_50 3 #define R_100 4 #define R_500 5 #define R_1000 6 /* Longest number within range = MMMMMMMMM DCCC LXXX VIII */ #define ROMAN_CHARS_NEEDED 21 static UTF32 * RomanToStringAux(unsigned int k, short UpperP) { int Digits; /* Number of digits in string */ int oi = 0; /* Index into output array */ int i; unsigned int Thousands; unsigned int Hundreds; unsigned int Tens; unsigned int Residue; UTF32 optr[ROMAN_CHARS_NEEDED+1]; UTF32 *new; UTF32 *RomanDigits; if(UpperP) RomanDigits = RomanDigitsUpper; else RomanDigits = RomanDigitsLower; Residue = k; Thousands = Residue/1000; for (i=0;i < Thousands;i++) optr[oi++] = RomanDigits[R_1000]; Residue -= (Thousands * 1000); if (Residue >= 500) { if (Residue >= 900) { optr[oi++] = RomanDigits[R_100]; optr[oi++] = RomanDigits[R_1000]; Residue-= 900; } else { optr[oi++] = RomanDigits[R_500]; Residue -= 500; } } if (Residue >= 400) { optr[oi++] = RomanDigits[R_100]; optr[oi++] = RomanDigits[R_500]; Residue -= 400; } else { Hundreds = Residue/100; for (i=0;i < Hundreds;i++) optr[oi++] = RomanDigits[R_100]; Residue -= (Hundreds * 100); } if (Residue >= 50) { if (Residue >= 90) { optr[oi++] = RomanDigits[R_10]; optr[oi++] = RomanDigits[R_100]; Residue-= 90; } else { optr[oi++] = RomanDigits[R_50]; Residue -= 50; } } if (Residue >= 40) { optr[oi++] = RomanDigits[R_10]; optr[oi++] = RomanDigits[R_50]; Residue -= 40; } else { Tens = Residue/10; for (i=0;i < Tens;i++) optr[oi++] = RomanDigits[R_10]; Residue -= (Tens * 10); } if (Residue >= 5) { if (Residue == 9) { optr[oi++] = RomanDigits[R_1]; optr[oi++] = RomanDigits[R_10]; Residue -= 9; } else { optr[oi++] = RomanDigits[R_5]; Residue -= 5; } } if (Residue == 4) { optr[oi++] = RomanDigits[R_1]; optr[oi++] = RomanDigits[R_5]; Residue -= 4; } for (i=0;i < Residue;i++) optr[oi++] = RomanDigits[R_1]; optr[oi] = 0x0000; Digits = ucslen(optr); new = (UTF32 *) malloc((Digits + 1) * sizeof(UTF32)); if(new) ucscpy(new,optr); else uninum_err = NS_ERROR_OUTOFMEMORY; return new; } static UTF32 * RomanIntToString(mpz_t n, short UpperP) { unsigned int k; unsigned int Thousands; unsigned int Ones; UTF32 *aptr = NULL; UTF32 *bptr = NULL; UTF32 *out; UTF32 *new; UTF32 *sptr; UTF32 optr[(3 * ROMAN_CHARS_NEEDED)+1]; k = (unsigned int) mpz_get_ui(n); if (k > ROMAN_LIMIT) { uninum_err = NS_ERROR_RANGE; return NULL; } if (k == 0) { uninum_err = NS_ERROR_NOZERO; return NULL; } if (Uninum_Generate_Roman_With_Bar_P) { if(k <= 2000) return RomanToStringAux(k,UpperP); Thousands = k/1000; Ones = k - (1000 * Thousands); aptr = RomanToStringAux(Thousands,UpperP); out = optr; sptr = aptr; /* Insert combining macron */ while (*sptr != 0x0000) { *out++ = *sptr++; *out++ = 0x0304; } free(aptr); if(Ones) { bptr = RomanToStringAux(Ones,UpperP); sptr = bptr; while (*sptr != 0x0000) *out++ = *sptr++; free(bptr); } *out = 0x0000; new = (UTF32 *) malloc((ucslen(optr) + 1) * sizeof(UTF32)); if(new) ucscpy(new,optr); else uninum_err = NS_ERROR_OUTOFMEMORY; return new; } else return RomanToStringAux(k,UpperP); } UTF32 cobd0[2] = {0x281A,0x0000}; /* 0 - D245 */ UTF32 cobd1[2] = {0x2801,0x0000}; /* 1 - D1 */ UTF32 cobd2[2] = {0x2803,0x0000}; /* 2 - D12 */ UTF32 cobd3[2] = {0x2809,0x0000}; /* 3 - D14 */ UTF32 cobd4[2] = {0x2819,0x0000}; /* 4 - D145 */ UTF32 cobd5[2] = {0x2811,0x0000}; /* 5 - D15 */ UTF32 cobd6[2] = {0x280B,0x0000}; /* 6 - D124 */ UTF32 cobd7[2] = {0x281B,0x0000}; /* 7 - D1245 */ UTF32 cobd8[2] = {0x2813,0x0000}; /* 8 - D125 */ UTF32 cobd9[2] = {0x280A,0x0000}; /* 9 - D24 */ UTF32 *CommonBrailleDigits[]={ cobd0, cobd1, cobd2, cobd3, cobd4, cobd5, cobd6, cobd7, cobd8, cobd9 }; UTF32 frbd0[2] = {0x283C,0x0000}; /* 0 D3456 */ UTF32 frbd1[2] = {0x2821,0x0000}; /* 1 D16 */ UTF32 frbd2[2] = {0x2823,0x0000}; /* 2 D126 */ UTF32 frbd3[2] = {0x2829,0x0000}; /* 3 D146 */ UTF32 frbd4[2] = {0x2839,0x0000}; /* 4 D1456 */ UTF32 frbd5[2] = {0x2831,0x0000}; /* 5 D156 */ UTF32 frbd6[2] = {0x282B,0x0000}; /* 6 D1246 */ UTF32 frbd7[2] = {0x283B,0x0000}; /* 7 D12456 */ UTF32 frbd8[2] = {0x2833,0x0000}; /* 8 D1256 */ UTF32 frbd9[2] = {0x282A,0x0000}; /* 9 D246 */ UTF32 *FrenchBrailleDigits[]={ /* Also Czech */ frbd0, frbd1, frbd2, frbd3, frbd4, frbd5, frbd6, frbd7, frbd8, frbd9 }; UTF32 rubd0[2] = {0x2834,0x0000}; /* 0 - D356 */ UTF32 rubd1[2] = {0x2802,0x0000}; /* 1 - D2 */ UTF32 rubd2[2] = {0x2806,0x0000}; /* 2 - D23 */ UTF32 rubd3[2] = {0x2812,0x0000}; /* 3 - D25 */ UTF32 rubd4[2] = {0x2832,0x0000}; /* 4 - D256 */ UTF32 rubd5[2] = {0x2822,0x0000}; /* 5 - D26 */ UTF32 rubd6[2] = {0x2816,0x0000}; /* 6 - D235 */ UTF32 rubd7[2] = {0x2836,0x0000}; /* 7 - D2356 */ UTF32 rubd8[2] = {0x2826,0x0000}; /* 8 - 236 */ UTF32 rubd9[2] = {0x2814,0x0000}; /* 9 - D35 */ UTF32 *RussianBrailleDigits[]={ rubd0, rubd1, rubd2, rubd3, rubd4, rubd5, rubd6, rubd7, rubd8, rubd9 }; UTF32 crsd0[2] = {0x3007,0x0000}; UTF32 crsd1[2] = {0x4E00,0x0000}; UTF32 crsd2[2] = {0x4E8C,0x0000}; UTF32 crsd3[2] = {0x4E09,0x0000}; UTF32 crsd4[2] = {0x56DB,0x0000}; UTF32 crsd5[2] = {0x4E94,0x0000}; UTF32 crsd6[2] = {0x516D,0x0000}; UTF32 crsd7[2] = {0x4E03,0x0000}; UTF32 crsd8[2] = {0x516B,0x0000}; UTF32 crsd9[2] = {0x4E5D,0x0000}; UTF32 *ChineseRegularSimplifiedDigits[]={ crsd0, crsd1, crsd2, crsd3, crsd4, crsd5, crsd6, crsd7, crsd8, crsd9 }; UTF32 crtd0[2] = {0x96F6,0x0000}; UTF32 crtd1[2] = {0x4E00,0x0000}; UTF32 crtd2[2] = {0x4E8C,0x0000}; UTF32 crtd3[2] = {0x4E09,0x0000}; UTF32 crtd4[2] = {0x56DB,0x0000}; UTF32 crtd5[2] = {0x4E94,0x0000}; UTF32 crtd6[2] = {0x516D,0x0000}; UTF32 crtd7[2] = {0x4E03,0x0000}; UTF32 crtd8[2] = {0x516B,0x0000}; UTF32 crtd9[2] = {0x4E5D,0x0000}; UTF32 *ChineseRegularTraditionalDigits[]={ crtd0, crtd1, crtd2, crtd3, crtd4, crtd5, crtd6, crtd7, crtd8, crtd9 }; UTF32 cltd0[2] = {0x96F6,0x0000}; UTF32 cltd1[2] = {0x58F9,0x0000}; UTF32 cltd2[2] = {0x8CB3,0x0000}; UTF32 cltd3[2] = {0x53C1,0x0000}; UTF32 cltd4[2] = {0x8086,0x0000}; UTF32 cltd5[2] = {0x4F0D,0x0000}; UTF32 cltd6[2] = {0x9646,0x0000}; UTF32 cltd7[2] = {0x6F06,0x0000}; UTF32 cltd8[2] = {0x634C,0x0000}; UTF32 cltd9[2] = {0x7396,0x0000}; UTF32 *ChineseLegalTraditionalDigits[]={ cltd0, cltd1, cltd2, cltd3, cltd4, cltd5, cltd6, cltd7, cltd8, cltd9 }; UTF32 clsd0[2] = {0x96F6,0x0000}; UTF32 clsd1[2] = {0x58F1,0x0000}; UTF32 clsd2[2] = {0x5F10,0x0000}; UTF32 clsd3[2] = {0x53C1,0x0000}; UTF32 clsd4[2] = {0x8086,0x0000}; UTF32 clsd5[2] = {0x4F0D,0x0000}; UTF32 clsd6[2] = {0x9678,0x0000}; UTF32 clsd7[2] = {0x67D2,0x0000}; UTF32 clsd8[2] = {0x634C,0x0000}; UTF32 clsd9[2] = {0x7396,0x0000}; UTF32 *ChineseLegalSimplifiedDigits[]={ clsd0, clsd1, clsd2, clsd3, clsd4, clsd5, clsd6, clsd7, clsd8, clsd9 }; UTF32 jltd0[2] = {0x3007,0x0000}; UTF32 jltd1[2] = {0x58F9,0x0000}; UTF32 jltd2[2] = {0x8CB3,0x0000}; UTF32 jltd3[2] = {0x53C3,0x0000}; UTF32 jltd4[2] = {0x8086,0x0000}; UTF32 jltd5[2] = {0x4F0D,0x0000}; UTF32 jltd6[2] = {0x9678,0x0000}; UTF32 jltd7[2] = {0x67D2,0x0000}; UTF32 jltd8[2] = {0x634C,0x0000}; UTF32 jltd9[2] = {0x7396,0x0000}; UTF32 *JapaneseLegalTraditionalDigits[]={ jltd0, jltd1, jltd2, jltd3, jltd4, jltd5, jltd6, jltd7, jltd8, jltd9 }; UTF32 jlsd0[2] = {0x3007,0x0000}; UTF32 jlsd1[2] = {0x58F1,0x0000}; UTF32 jlsd2[2] = {0x5F10,0x0000}; UTF32 jlsd3[2] = {0x53C2,0x0000}; UTF32 jlsd4[2] = {0x56DB,0x0000}; UTF32 jlsd5[2] = {0x4E94,0x0000}; UTF32 jlsd6[2] = {0x516D,0x0000}; UTF32 jlsd7[2] = {0x4E03,0x0000}; UTF32 jlsd8[2] = {0x516B,0x0000}; UTF32 jlsd9[2] = {0x4E5D,0x0000}; UTF32 *JapaneseLegalSimplifiedDigits[]={ jlsd0, jlsd1, jlsd2, jlsd3, jlsd4, jlsd5, jlsd6, jlsd7, jlsd8, jlsd9 }; UTF32 ccru0[2] = {0x3007,0x0000}; UTF32 ccru1[2] = {0x1D360,0x0000}; UTF32 ccru2[2] = {0x1D361,0x0000}; UTF32 ccru3[2] = {0x1D362,0x0000}; UTF32 ccru4[2] = {0x1D363,0x0000}; UTF32 ccru5[2] = {0x1D364,0x0000}; UTF32 ccru6[2] = {0x1D365,0x0000}; UTF32 ccru7[2] = {0x1D366,0x0000}; UTF32 ccru8[2] = {0x1D367,0x0000}; UTF32 ccru9[2] = {0x1D368,0x0000}; UTF32 *ChineseCountingRodDigits[]={ ccru0, ccru1, ccru2, ccru3, ccru4, ccru5, ccru6, ccru7, ccru8, ccru9 }; UTF32 ccrd0[2] = {0x3007,0x0000}; UTF32 ccrd1[2] = {0x1D369,0x0000}; UTF32 ccrd2[2] = {0x1D36A,0x0000}; UTF32 ccrd3[2] = {0x1D36B,0x0000}; UTF32 ccrd4[2] = {0x1D36C,0x0000}; UTF32 ccrd5[2] = {0x1D36D,0x0000}; UTF32 ccrd6[2] = {0x1D36E,0x0000}; UTF32 ccrd7[2] = {0x1D36F,0x0000}; UTF32 ccrd8[2] = {0x1D370,0x0000}; UTF32 ccrd9[2] = {0x1D371,0x0000}; UTF32 *ChineseCountingRodDecades[]={ ccrd0, ccrd1, ccrd2, ccrd3, ccrd4, ccrd5, ccrd6, ccrd7, ccrd8, ccrd9 }; /* Japanese traditional barriers 10^4 = 84C2l, 10^3 = 9621 (financial), 10^2 = 4F70 (financial), 10^1 = 62FE */ static UTF32 ChineseRegularTraditionalBarriers[] = { 0x5341, /* 0 - 10^1 */ 0x767E, /* 1 - 10^2 */ 0x5343, /* 2 - 10^3 */ 0x842C, /* 3 - 10^4 */ 0x5104, /* 4 - 10^8 */ 0x5146, /* 5 - 10^12 */ 0x4EAC, /* 6 - 10^16 */ 0x5793, /* 7 - 10^20 */ 0x25771, /* 8 - 10^24 */ 0x7A63, /* 9 - 10^28 */ 0x6E9D, /* 10 - 10^32 */ 0x6F97, /* 11 - 10^36 */ 0x6B63, /* 12 - 10^40 */ 0x8F09, /* 13 - 10^44 */ 0x6975, /* 14 - 10^48 */ }; static UTF32 ChineseRegularSimplifiedBarriers[] = { 0x5341, /* 0 - 10^1 */ 0x767E, /* 1 - 10^2 */ 0x5343, /* 2 - 10^3 */ 0x4E07, /* 3 - 10^4 */ 0x4EBF, /* 4 - 10^8 */ 0x5146, /* 5 - 10^12 */ 0x4EAC, /* 6 - 10^16 */ 0x5793, /* 7 - 10^20 */ 0x25771, /* 8 - 10^24 */ 0x7A63, /* 9 - 10^28 */ 0x6C9F, /* 10 - 10^32 */ 0x6DA7, /* 11 - 10^36 */ 0x6B63, /* 12 - 10^40 */ 0x8F7D, /* 13 - 10^44 */ 0x6781, /* 14 - 10^48 */ }; static UTF32 ChineseLegalTraditionalBarriers[] = { 0x62FE, /* 0 - 10^1 */ 0x767E, /* 1 - 10^2 */ 0x4EDF, /* 2 - 10^3 */ 0x842C, /* 3 - 10^4 */ 0x5104, /* 4 - 10^8 */ 0x5146, /* 5 - 10^12 */ 0x4EAC, /* 6 - 10^16 */ 0x5793, /* 7 - 10^20 */ 0x25771, /* 8 - 10^24 */ 0x7A63, /* 9 - 10^28 */ 0x6E9D, /* 10 - 10^32 */ 0x6F97, /* 11 - 10^36 */ 0x6B63, /* 12 - 10^40 */ 0x8F09, /* 13 - 10^44 */ 0x6975, /* 14 - 10^48 */ }; static UTF32 ChineseLegalSimplifiedBarriers[] = { 0x5341, /* 0 - 10^1 */ 0x767E, /* 1 - 10^2 */ 0x4EDF, /* 2 - 10^3 */ 0x842C, /* 3 - 10^4 */ 0x5104, /* 4 - 10^8 */ 0x5146, /* 5 - 10^12 */ 0x4EAC, /* 6 - 10^16 */ 0x5793, /* 7 - 10^20 */ 0x25771, /* 8 - 10^24 */ 0x7A63, /* 9 - 10^28 */ 0x6C9F, /* 10 - 10^32 */ 0x6DA7, /* 11 - 10^36 */ 0x6B63, /* 12 - 10^40 */ 0x8F7D, /* 13 - 10^44 */ 0x6781, /* 14 - 10^48 */ }; static UTF32 JapaneseRegularSimplifiedBarriers[] = { 0x5341, /* 0 - 10^1 */ 0x767E, /* 1 - 10^2 */ 0x5343, /* 2 - 10^3 */ 0x4E07, /* 3 - 10^4 */ 0x5104, /* 4 - 10^8 */ 0x5146, /* 5 - 10^12 */ 0x4EAC, /* 6 - 10^16 */ 0x5793, /* 7 - 10^20 */ 0x25771, /* 8 - 10^24 */ 0x7A63, /* 9 - 10^28 */ 0x6E9D, /* 10 - 10^32 */ 0x6F97, /* 11 - 10^36 */ 0x6B63, /* 12 - 10^40 */ 0x8F09, /* 13 - 10^44 */ 0x6975, /* 14 - 10^48 */ }; static UTF32 JapaneseLegalTraditionalBarriers[] = { 0x62FE, /* 0 - 10^1 */ 0x767E, /* 1 - 10^2 */ 0x4EDF, /* 2 - 10^3 */ 0x842C, /* 3 - 10^4 */ 0x5104, /* 4 - 10^8 */ 0x5146, /* 5 - 10^12 */ 0x4EAC, /* 6 - 10^16 */ 0x5793, /* 7 - 10^20 */ 0x25771, /* 8 - 10^24 */ 0x7A63, /* 9 - 10^28 */ 0x6E9D, /* 10 - 10^32 */ 0x6F97, /* 11 - 10^36 */ 0x6B63, /* 12 - 10^40 */ 0x8F09, /* 13 - 10^44 */ 0x6975, /* 14 - 10^48 */ }; static UTF32 JapaneseLegalSimplifiedBarriers[] = { 0x5341, /* 0 - 10^1 */ 0x767E, /* 1 - 10^2 */ 0x4EDF, /* 2 - 10^3 */ 0x842C, /* 3 - 10^4 */ 0x5104, /* 4 - 10^8 */ 0x5146, /* 5 - 10^12 */ 0x4EAC, /* 6 - 10^16 */ 0x5793, /* 7 - 10^20 */ 0x25771, /* 8 - 10^24 */ 0x7A63, /* 9 - 10^28 */ 0x6C9F, /* 10 - 10^32 */ 0x6DA7, /* 11 - 10^36 */ 0x6B63, /* 12 - 10^40 */ 0x8F7D, /* 13 - 10^44 */ 0x6781, /* 14 - 10^48 */ }; /* Remove the leading 1 from 10-19 */ void FixChineseTeens(UTF32 *s){ int len; len = ucslen(s); if( ((len == 3) || (len == 2)) && (s[0] == 0x4E00) && (s[1] == 0x5341)) { s[0] = s[1]; s[1] = s[2]; s[2] = 0x0000; } } /* * In Mandarin and Chao Zhou a special form of 2 (liang/no) is used before units greater than 10. * This subroutine changes 2 to liang/no where appropriate. */ void FixLiang(UTF32 *s) { UTF32 *p; p = s; while(*p != 0x0000) { if((*p == 0x4E8C) || (*p == 0x8CB3) || (*p == 0x5F10)) { /* 2 */ if (*(p+1) == 0x0000) break; /* 2 in final position */ if (*(p+1) == 0x5341) { /* 2 immediately precedes 10 */ p++; continue; } *p = 0x4E24; /* Replace with liang */ } p++; } } void StripLeadingChineseOne(UTF32 *s) { UTF32 *p; if( (*s == 0x4E00) && (ucslen(s) > 1)) { p = s; while (*p != 0x0000) { *p = *(p+1); p++; } } } void ReduceChineseZeroSequences(UTF32 *s) { UTF32 *ip; UTF32 *op; UTF32 c; enum {START,PREVIOUS_ZERO} State = START; ip = s; op = s; while ( (c = *ip) != 0x0000) { if ( (c == 0x3007) || (c == 0x96F6)) { if (State == START) { *op++ = *ip++; State = PREVIOUS_ZERO; } else ip++; } else{ State = START; *op++ = *ip++; } } *op = 0x0000; } void StripTrailingChineseZero(UTF32 *s) { int Last_Index; Last_Index = ucslen(s) -1; if ( (s[Last_Index] == 0x3007) || (s[Last_Index] == 0x96F6)) s[Last_Index] = 0x0000; } #define CHINESE_BARRIER_CNT 15 #define CHINESE_CHARS_NEEDED 300 static UTF32 *ChineseIntToString(mpz_t n,UTF32 **DigitList, UTF32 *Barriers, short ZeroP){ int i; mpz_t q; mpz_t r; mpz_t t; mpz_t val; UTF32 obuf[CHINESE_CHARS_NEEDED+1]; UTF32 *ptr; UTF32 *rptr; int k; mpz_t MaxChinese; /* Maximum value convertible to Chinese string */ /* (10^97)-1, in hex for compactness and speed of conversion to binary */ mpz_init_set_str(MaxChinese,MAXCHINESEHEX,16); if(TGE(n,MaxChinese)) { uninum_err = NS_ERROR_RANGE; return NULL; } mpz_clear(MaxChinese); if (ULT(n,10)) { if (mpz_cmp_ui(n,0) > 0-ZeroP) { k = mpz_get_ui(n); return(MakeSingleDigitString(DigitList[k][0])); } return(NULL); } else { mpz_init(q);mpz_init(r);mpz_init(t);mpz_init(val); for(i= CHINESE_BARRIER_CNT-1; i >= 0;i--) { GetChineseBarrierValue(val,i); mpz_tdiv_qr(q,r,n,val); if (UGT(q,0)) { rptr = ChineseIntToString(q,DigitList,Barriers,ZeroP); if(rptr) { ptr=ucpcpy(obuf,rptr); free(rptr); *ptr++ = Barriers[i]; *ptr=0x0000; } if (ZeroP) { if(i>0) { GetChineseBarrierValue(val,i-1); mpz_tdiv_q(t,r,val); if(UEQ(t,0)) ucscat(obuf,DigitList[0]); } } rptr = ChineseIntToString(r,DigitList,Barriers,ZeroP); if(rptr) { ucscat(obuf,rptr); free(rptr); } break; } /* end of if q > 0 */ else { if(ZeroP) ucscat(obuf,DigitList[0]); } } /* end of for */ mpz_clear(q);mpz_clear(r);mpz_clear(t);mpz_clear(val); ptr = (UTF32 *) malloc ((1 + ucslen(obuf)) * sizeof(UTF32)); if(ptr) ucscpy(ptr,obuf); else uninum_err = NS_ERROR_OUTOFMEMORY; return ptr; } } #define CHINESE_WESTERN_CHARS_NEEDED 300 static UTF32 *ChineseWesternIntToString(mpz_t n,UTF32 **DigitList, UTF32 *Barriers){ int i; mpz_t q; mpz_t r; mpz_t val; UTF32 obuf[CHINESE_WESTERN_CHARS_NEEDED+1]; UTF32 *ptr; UTF32 *rptr; UTF32 *tmpptr; int k; mpz_t MaxChinese; /* Maximum value convertible to Chinese string */ mpz_init_set_str(MaxChinese,MAXCHINESEHEX,16); if(TGT(n,MaxChinese)) { uninum_err = NS_ERROR_RANGE; mpz_clear(MaxChinese); return NULL; } mpz_clear(MaxChinese); if (ULT(n,10)) { if (UGT(n,0)) { k = mpz_get_ui(n); return(MakeSingleDigitString(DigitList[k][0])); } return(NULL); } else { mpz_init(q);mpz_init(r);mpz_init(val); for(i= CHINESE_BARRIER_CNT-1; i >= 0;i--) { GetChineseBarrierValue(val,i); mpz_tdiv_qr(q,r,n,val); if (UGT(q,0L)) { if(ULT(q,10000)) { tmpptr = PlaceIntToString(q,WESTERN_ZERO,10); rptr = wcDelimitNumber(tmpptr,0x002C,0x002E,3,3); if (tmpptr != rptr) free(tmpptr); } else rptr = ChineseWesternIntToString(q,DigitList,Barriers); if(rptr) { ptr=ucpcpy(obuf,rptr); free(rptr); } *ptr++= Barriers[i]; *ptr=0x0000; if(ULT(r,10000)) { tmpptr = PlaceIntToString(r,WESTERN_ZERO,10); rptr = wcDelimitNumber(tmpptr,0x002C,0x002E,3,3); if (tmpptr != rptr) free(tmpptr); } else rptr = ChineseWesternIntToString(r,DigitList,Barriers); if(rptr) { if( (UGE(r,10000)) || (*rptr != WESTERN_ZERO)) { ucscat(obuf,rptr); } free(rptr); } break; } } mpz_clear(q);mpz_clear(r);mpz_clear(val); ptr = (UTF32 *) malloc ((1 + ucslen(obuf)) * sizeof(UTF32)); if(ptr) ucscpy(ptr,obuf); return ptr; } } /* This is a fairly slight adaptation of PlaceNonContiguousIntToString */ static UTF32 * ChineseCountingRodIntToString(mpz_t n, short EarlyP) { int Digits; UTF32 *s; UTF32 *p; UTF32 *new; UTF32 *end; mpz_t d; mpz_t k; mpz_t q; mpz_t r; unsigned long int temp; int offset; UTF32 **EvenDigitList; UTF32 **OddDigitList; mpz_init_set(k,n); Digits = mpz_sizeinbase(k,10); new = malloc((Digits + 1) * sizeof(UTF32)); if (!new) { uninum_err = NS_ERROR_OUTOFMEMORY; mpz_clear(k); return NULL; } mpz_init(d); mpz_init(q); mpz_init(r); if(EarlyP) { EvenDigitList = ChineseCountingRodDecades; OddDigitList = ChineseCountingRodDigits; } else { EvenDigitList = ChineseCountingRodDigits; OddDigitList = ChineseCountingRodDecades; } p = s = new; end = new + Digits-1; /* Do conversion */ do { mpz_tdiv_qr_ui(q,r,k,10); if ((end - s)%2) *s++ = EvenDigitList[mpz_get_ui(r)][0]; else *s++ = OddDigitList[mpz_get_ui(r)][0]; mpz_set(k,q); } while (UGT(q,0L)); *s = 0L; /* Null terminate string */ s--; /* Point s at last non-null char */ mpz_clear(d);mpz_clear(k);mpz_clear(q);mpz_clear(r); /* * Now we reverse the string. When we begin, p points at the first * character of the string, s at the last non-null character. */ while(p <= s){ temp = *p; *p++ = *s; *s-- = temp; } return new; } /* define number addresses */ #define ETH_ONE 0x1369 #define ETH_TEN ETH_ONE + 9 #define ETH_HUNDRED ETH_TEN + 9 #define ETH_TENTHOUSAND ETH_HUNDRED + 1 /* * This is based loosely on Daniel Jacob's function but heavily rewritten. */ static UTF32 * EthiopicIntToString(mpz_t n) { char *Number; UTF32 *Result; UTF32 *FinalResult; int MaxTenPower; int EthiopicCharCnt = 0; char asciiOne, asciiTen; UTF32 OnesPlace, TensPlace, HundredSep; int CurrentPower; int OddSubgroupP; char *tmp; Number=mpz_get_str(NULL,10,n); MaxTenPower = strlen( Number) - 1; if (MaxTenPower == 0) { FinalResult = (UTF32 *) malloc ( 2 * sizeof (UTF32) ); FinalResult[0] = Number[0] + ETH_ONE - '1'; FinalResult[1] = '\0'; return (FinalResult); } else if ( (MaxTenPower % 2) == 0 ) { /* * Precondition the string to always have the leading tens place populated. */ tmp = (char *) malloc ((MaxTenPower+2)*sizeof(char) ); sprintf (tmp,"0%s",Number); free(Number); Number = tmp; MaxTenPower++; } Result = (UTF32 *) malloc (((4 * MaxTenPower)+1) * sizeof (UTF32)); if(!Result) {uninum_err = NS_ERROR_OUTOFMEMORY;return(NULL);} for (CurrentPower = MaxTenPower; CurrentPower >= 0; CurrentPower-- ) { OnesPlace = TensPlace = 0x0; asciiTen = Number[MaxTenPower-CurrentPower]; CurrentPower--; asciiOne = Number[MaxTenPower-CurrentPower]; if (asciiOne != '0') OnesPlace = asciiOne + (ETH_ONE - '1'); if (asciiTen != '0') TensPlace = asciiTen + (ETH_TEN - '1'); /* Choose the HundredSeparator for this group */ OddSubgroupP = (CurrentPower % 4) / 2; if(CurrentPower > 0) { if(OddSubgroupP) { if(OnesPlace || TensPlace) HundredSep = ETH_HUNDRED; else HundredSep = 0; } else HundredSep = ETH_TENTHOUSAND; } else HundredSep = 0; /* * If we have a one without a leading ten * or following 100 or in initial position, remove the one. */ if ( (OnesPlace == ETH_ONE ) && TensPlace == 0) { if ( (HundredSep == ETH_HUNDRED ) || (CurrentPower+1) == MaxTenPower) OnesPlace = 0; } /* Assemble this group */ if (TensPlace) Result[EthiopicCharCnt++] = TensPlace; if (OnesPlace) Result[EthiopicCharCnt++] = OnesPlace; if (HundredSep) Result[EthiopicCharCnt++] = HundredSep; } /* End of for loop over input digits */ Result[EthiopicCharCnt] = (UTF32) 0; free (Number); FinalResult = (UTF32 *) malloc ((EthiopicCharCnt+1) * sizeof (UTF32)); if(!FinalResult) {uninum_err = NS_ERROR_OUTOFMEMORY;return(NULL);} ucscpy(FinalResult,Result); free (Result); return (FinalResult); } #define HEBREW_CHARS_NEEDED 7 /* unit, decade, 100, 2nd 100, 3d 100, geresh, 1000 */ #define HEBREW_DATA_ENTRIES 29 /* This is a slight variant on AdditiveIntToString */ static UTF32 * HebrewIntToString(mpz_t k, struct vcpair *data, short EarlyP) { int Digits; int i; int iRepeat; unsigned long j; int oi = 0; UTF32 tmp[HEBREW_CHARS_NEEDED+1]; UTF32 *new; struct vcpair *p; mpz_t Repeat; mpz_t Residue; j = mpz_get_ui(k); p = data; if (j > p->v) { uninum_err = NS_ERROR_RANGE; return NULL; } if(UEQ(k,0)) { uninum_err = NS_ERROR_NOZERO; return NULL; } mpz_init(Repeat); mpz_init(Residue); if (j > 999L) { mpz_tdiv_qr_ui(Repeat,Residue,k,1000L); tmp[oi++] = (data + HEBREW_DATA_ENTRIES -1 - mpz_get_ui(Repeat))->c; tmp[oi++] = 0x05F3; /* Geresh */ } else mpz_set(Residue,k); if (EarlyP) p = data+6; else p = data+1; while (p->v) { if(UEQ(Residue,15)) { tmp[oi++] = 0x05D8; tmp[oi++] = 0x05D5; mpz_sub_ui(Residue,Residue,15); } else if(UEQ(Residue,16)) { tmp[oi++] = 0x05D8; tmp[oi++] = 0x05D6; mpz_sub_ui(Residue,Residue,16); } else { mpz_tdiv_q_ui(Repeat,Residue,p->v); iRepeat = mpz_get_ui(Repeat); for (i=0;i < iRepeat;i++) tmp[oi++] = p->c; mpz_submul_ui(Residue,Repeat,p->v); p++; } } mpz_clear(Repeat); mpz_clear(Residue); tmp[oi++] = 0x0000; Digits = ucslen(tmp); new = malloc((Digits + 1) * sizeof(UTF32)); if (!new) { uninum_err = NS_ERROR_OUTOFMEMORY; return NULL; } return(ucscpy(new,tmp)); } struct vcpair KharoshthiData[]={ /* Max is stored in subroutine in this case */ {20,0x10A45}, {10,0x10A44}, {0,0xFFDF} }; /* * Computation of max chars needed: * 77 + (100 * 7) + (1000 * (77 + (100 * 7))) = 777,777 (longer than 999,999) * 8 1 4 1 8 1 4 */ #define KHAROSHTHI_CHARS_NEEDED 27 UTF32 *KharoshthiIntToString(mpz_t n){ int Digits; /* Number of digits in string */ int oi = 0; /* Index into output array */ int i; mpz_t Thousands; mpz_t Hundreds; mpz_t Residue; mpz_t Repeat; unsigned int iRepeat; unsigned long k; UTF32 tmp[KHAROSHTHI_CHARS_NEEDED+1]; UTF32 *op; UTF32 *new; UTF32 *ptr; UTF32 tempc; struct vcpair *p; if (UGT(n,999999L)) { uninum_err = NS_ERROR_RANGE; return NULL; } if(UEQ(n,0)) { uninum_err = NS_ERROR_NOZERO; return NULL; } mpz_init(Thousands); mpz_init(Hundreds); mpz_init(Repeat); mpz_init(Residue); op = tmp; *op=0x0000; mpz_set(Residue,n); /* Thousands */ mpz_tdiv_q_ui(Thousands,Residue,1000L); if(UGT(Thousands,0)) { ptr = KharoshthiIntToString(Thousands); op = ucpcpy(op,ptr); free(ptr); *op++ = KHAROSHTHI_THOUSAND; *op = 0x0000; } mpz_submul_ui(Residue,Thousands,1000L); /* Hundreds */ mpz_tdiv_q_ui(Hundreds,Residue,100L); if(UGT(Hundreds,0)) { ptr = KharoshthiIntToString(Hundreds); op = ucpcpy(op,ptr); free(ptr); *op++ = KHAROSHTHI_HUNDRED; *op = 0x0000; } mpz_submul_ui(Residue,Hundreds,100L); /* Decades */ p = KharoshthiData; while(p->v) { mpz_tdiv_q_ui(Repeat,Residue,p->v); iRepeat = mpz_get_ui(Repeat); for (i=0;i < iRepeat;i++) *op++ = p->c; mpz_submul_ui(Residue,Repeat,p->v); p++; } /* Units */ /* Although numerals exist for 2 and 3, only 1 and 4 enter into combination */ /* 6 = 4 + 1 +1 not 4 + 2 or 3 + 3, 7 = 4 + 1 +1 +1, not 4 + 3 */ k = mpz_get_ui(Residue); switch(k){ case 1: *op++ =KHAROSHTHI_ONE; break; case 2: *op++ =KHAROSHTHI_TWO; break; case 3: *op++ =KHAROSHTHI_THREE; break; case 4: *op++ =KHAROSHTHI_FOUR; break; case 5: *op++ =KHAROSHTHI_FOUR; *op++ =KHAROSHTHI_ONE; break; case 6: *op++ =KHAROSHTHI_FOUR; *op++ =KHAROSHTHI_ONE; *op++ =KHAROSHTHI_ONE; break; case 7: *op++ =KHAROSHTHI_FOUR; *op++ =KHAROSHTHI_ONE; *op++ =KHAROSHTHI_ONE; *op++ =KHAROSHTHI_ONE; break; case 8: *op++ =KHAROSHTHI_FOUR; *op++ =KHAROSHTHI_FOUR; break; case 9: *op++ =KHAROSHTHI_FOUR; *op++ =KHAROSHTHI_FOUR; *op++ =KHAROSHTHI_ONE; break; case 0: break; } *op=0x0000; mpz_clear(Thousands); mpz_clear(Hundreds); mpz_clear(Repeat); mpz_clear(Residue); Digits = ucslen(tmp); new = malloc((Digits + 1) * sizeof(UTF32)); if (!new) { uninum_err = NS_ERROR_OUTOFMEMORY; return NULL; } return(ucscpy(new,tmp)); } UTF32 tamd0[2] = {0x0BE6,0x0000}; UTF32 tamd1[2] = {0x0BE7,0x0000}; UTF32 tamd2[2] = {0x0BE8,0x0000}; UTF32 tamd3[2] = {0x0BE9,0x0000}; UTF32 tamd4[2] = {0x0BEA,0x0000}; UTF32 tamd5[2] = {0x0BEB,0x0000}; UTF32 tamd6[2] = {0x0BEC,0x0000}; UTF32 tamd7[2] = {0x0BED,0x0000}; UTF32 tamd8[2] = {0x0BEE,0x0000}; UTF32 tamd9[2] = {0x0BEF,0x0000}; UTF32 *TamilDigits[]={ tamd0, tamd1, tamd2, tamd3, tamd4, tamd5, tamd6, tamd7, tamd8, tamd9 }; #define TAMIL_CHARS_NEEDED 10 static UTF32 *TamilTraditionalIntToString(mpz_t n){ int i; mpz_t q; mpz_t r; mpz_t val; UTF32 obuf[TAMIL_CHARS_NEEDED+1]; UTF32 *ptr; UTF32 *rptr; int k; if(UGT(n,999999)) { uninum_err = NS_ERROR_RANGE; return NULL; } if (ULT(n,10)) { k = mpz_get_ui(n); return(MakeSingleDigitString(TamilDigits[k][0])); } else { mpz_init(q);mpz_init(r);mpz_init(val); for(i= (sizeof(TamilBarriers)/sizeof(UTF32))-1; i >= 0;i--) { mpz_tdiv_qr_ui(q,r,n,TamilBarrierValue[i]); if (UGT(q,0L)) { rptr = TamilTraditionalIntToString(q); ptr=ucpcpy(obuf,rptr); if (UGT(q, 10L)) free(rptr); *ptr++= TamilBarriers[i]; *ptr=0x0000; rptr = TamilTraditionalIntToString(r); ucscat(obuf,rptr); if (UGT(r, 10L)) free(rptr); break; } } mpz_clear(q);mpz_clear(r);mpz_clear(val); ptr = (UTF32 *) malloc ((1 + ucslen(obuf)) * sizeof(UTF32)); if(ptr) ucscpy(ptr,obuf); return ptr; } } UTF32 UpperAlphaDigits[]={ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A }; UTF32 LowerAlphaDigits[]={ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A }; static UTF32 * WesternGeneralIntToString(mpz_t n, int Base, short UpperP) { unsigned long Digits; UTF32 *s; UTF32 *p; UTF32 *new; UTF32 *ZeroCode; mpz_t k; mpz_t q; mpz_t r; mpz_t b; unsigned long int temp; unsigned long i; if ((Base > 36) || (Base < 1)) { uninum_err = NS_ERROR_BADBASE; return NULL; } if(Base == 1) { if(ULE(n,0L)) { uninum_err = NS_ERROR_NOZERO; return NULL; } if(!mpz_fits_ulong_p(n)) { uninum_err = NS_ERROR_DOESNOTFIT; return NULL; } Digits = mpz_get_ui(n); } else Digits = mpz_sizeinbase(n,Base); new = malloc((Digits + 1) * sizeof(UTF32)); if (!new) { uninum_err = NS_ERROR_OUTOFMEMORY; return NULL; } p = s = new; if (UpperP) ZeroCode = UpperAlphaDigits; else ZeroCode = LowerAlphaDigits; if (Base == 1) { for (i = 0; i < Digits; i++) *s++ = 0x0030; *s = 0x0000; /* Null terminate string */ } else { mpz_init_set(k,n); mpz_init(q); mpz_init(r); mpz_init_set_ui(b,Base); /* Do conversion */ do { mpz_tdiv_qr(q,r,k,b); *s++ = *(ZeroCode + mpz_get_ui(r)); mpz_set(k,q); } while (UGT(q,0L)); *s = 0x0000; /* Null terminate string */ s--; /* Point s at last non-null char */ /* * Now we reverse the string. When we begin, p points at the first * character of the string, s at the last non-null character. */ while(p <= s){ temp = *p; *p++ = *s; *s-- = temp; } mpz_clear(b);mpz_clear(k);mpz_clear(q);mpz_clear(r); } return new; } /* Reorder 11-19 to spoken order */ #define GLAGOLITIC_ONE 0x2C00 #define GLAGOLITIC_NINE 0x2C08 #define GLAGOLITIC_TEN 0x2C09 static void FixGlagoliticTeens(UTF32 *s){ int oi; /* Index of final null */ UTF32 c1; UTF32 c2; oi = ucslen(s); c1 = s[oi-2]; c2 = s[oi-1]; if ( (c1 == GLAGOLITIC_TEN) && ( (c2 >= GLAGOLITIC_ONE) && (c2 <= GLAGOLITIC_NINE))) { s[oi-2] = c2; s[oi-1] = c1; } } UTF32 *SupplyIsolatedChineseZero (short TraditionalP) { UTF32 *new; new = malloc(sizeof(UTF32) * 2); if(!new) { fprintf(stderr,"Out of memory.\n"); exit(OUTOFMEMORY); } if(TraditionalP) new[0] = 0x96F6; else new[0] = 0x3007; new[1] = 0x0000; return(new); } // s[0] s[1] s[2] s[3] len = 3, lim = 2, max(i) = 2 // 1 0 3 '\0' // 1 0 3 '\0' i = 1 // 1 3 3 '\0' i = 2 // 1 3 \0' '\0' /* Delete a zero neither of whose immediate neighbors is a zero or an edge */ void MinimizeCountingRodZeroes(UTF32 *s) { int i; int len; UTF32 *tmp; UTF32 *tp; len = ucslen(s); #ifdef ALLOCAOK tmp = alloca( (len+1) * sizeof(UTF32)); #else tmp = malloc( (len+1) * sizeof(UTF32)); #endif tp = tmp; *tp++ = s[0]; for(i=1;i < len; i++){ if((s[i] == 0x3007) && (s[i-1] != 0x3007) && (s[i+1] != 0x3007) && (s[i+1] != 0x0000)) ; else *tp++ = s[i]; } *tp = '\0'; ucscpy(s,tmp); #ifndef ALLOCAOK free(tmp); #endif } /* * This subroutine takes care of two special features of Suzhou numbers. * One is that the zero does not immediately precede the other digits * in Unicode order, so we first generate the numbers with the codepoint * preceding Suzhou 1 (U+3020) and then replace it here with the proper * zero character. * * The other is that the numbers one through three have both vertical forms, used by * default, and horizontal forms, which are used when the preceding character * is one of the three vertical characters. PlaceIntToString generates * the defaults only, so here we replace them with their horizontal counterparts * as necessary. */ static void FixSuzhou(UTF32 *s){ UTF32 *p; enum {START,PREVIOUS_VERTICAL} State = START; p=s; while(*p != 0x0000) { switch(*p) { case 0x3020: *p = 0x3007; break; case 0x3021: if(State == PREVIOUS_VERTICAL) { *p = 0x4E00; State = START; } else State = PREVIOUS_VERTICAL; break; case 0x3022: if(State == PREVIOUS_VERTICAL) { *p = 0x4E8C; State = START; } else State = PREVIOUS_VERTICAL; break; case 0x3023: if(State == PREVIOUS_VERTICAL) { *p = 0x4E09; State = START; } else State = PREVIOUS_VERTICAL; break; default: State = START; } p++; } } /* This is the main string-generating function */ UTF32 * IntToString(union ns_rval *n,int ns, short InputType) { mpz_t z; UTF32 *ptr; UTF32 *tmpptr; uninum_err = NS_ERROR_OKAY; mpz_init(z); switch (InputType) { case NS_TYPE_ULONG: mpz_set_ui(z,n->u); break; case NS_TYPE_STRING: mpz_set_str(z,n->s,10); break; case NS_TYPE_MPZT: mpz_set(z,n->m); break; } if(ULT(z,0) < 0) { uninum_err = NS_ERROR_RANGE; mpz_clear(z); return NULL; } switch (ns) { case NS_AEGEAN: ptr = AdditiveIntToString(z,AegeanData); break; case NS_ARABIC_WESTERN: ptr = PlaceIntToString(z,ARABIC_ZERO,10); break; case NS_ARABIC_ALPHABETIC: ptr = AdditiveIntToString(z,ArabicAlphabeticData); break; case NS_PERSO_ARABIC: ptr = PlaceIntToString(z,PERSO_ARABIC_ZERO,10); break; case NS_ARMENIAN_ALPHABETIC: ptr = AdditiveIntToString(z,ArmenianData); break; case NS_BALINESE: ptr = PlaceIntToString(z,BALINESE_ZERO,10); break; case NS_BENGALI: ptr = PlaceIntToString(z,BENGALI_ZERO,10); break; case NS_BURMESE: ptr = PlaceIntToString(z,BURMESE_ZERO,10); break; case NS_CHINESE_COUNTING_ROD_EARLY_WITH_ZERO: ptr = ChineseCountingRodIntToString(z,1); break; case NS_CHINESE_COUNTING_ROD_EARLY_WITHOUT_ZERO: ptr = ChineseCountingRodIntToString(z,1); if(ptr) MinimizeCountingRodZeroes(ptr); break; case NS_CHINESE_COUNTING_ROD_LATE_WITH_ZERO: ptr = ChineseCountingRodIntToString(z,0); break; case NS_CHINESE_COUNTING_ROD_LATE_WITHOUT_ZERO: ptr = ChineseCountingRodIntToString(z,0); if(ptr) MinimizeCountingRodZeroes(ptr); break; case NS_CHINESE_LEGAL_SIMPLIFIED: if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(0); else ptr = ChineseIntToString(z,ChineseLegalSimplifiedDigits,ChineseLegalSimplifiedBarriers,0); break; case NS_CHINESE_LEGAL_TRADITIONAL: if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(0); else ptr = ChineseIntToString(z,ChineseLegalTraditionalDigits,ChineseLegalTraditionalBarriers,0); break; case NS_CHINESE_REGULAR_SIMPLIFIED: if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(0); else { ptr = ChineseIntToString(z,ChineseRegularSimplifiedDigits,ChineseRegularSimplifiedBarriers,0); if (ptr) FixChineseTeens(ptr); } break; case NS_CHINESE_REGULAR_TRADITIONAL: if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(1); else { ptr = ChineseIntToString(z,ChineseRegularTraditionalDigits,ChineseRegularTraditionalBarriers,0); if (ptr) FixChineseTeens(ptr); } break; case NS_CHINESE_MANDARIN_LEGAL_SIMPLIFIED: if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(0); else { ptr = ChineseIntToString(z,ChineseLegalSimplifiedDigits,ChineseLegalSimplifiedBarriers,0); if (ptr) FixLiang(ptr); } break; case NS_CHINESE_MANDARIN_LEGAL_TRADITIONAL: if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(1); else { ptr = ChineseIntToString(z,ChineseLegalTraditionalDigits,ChineseLegalTraditionalBarriers,0); if(ptr) FixLiang(ptr); } break; case NS_CHINESE_MANDARIN_REGULAR_SIMPLIFIED: if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(0); else { ptr = ChineseIntToString(z,ChineseRegularSimplifiedDigits,ChineseRegularSimplifiedBarriers,1); if(ptr) { ReduceChineseZeroSequences(ptr); StripTrailingChineseZero(ptr); FixChineseTeens(ptr); FixLiang(ptr); } } break; case NS_CHINESE_MANDARIN_REGULAR_TRADITIONAL: if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(1); else { ptr = ChineseIntToString(z,ChineseRegularTraditionalDigits,ChineseRegularTraditionalBarriers,1); if(ptr) { ReduceChineseZeroSequences(ptr); StripTrailingChineseZero(ptr); FixChineseTeens(ptr); FixLiang(ptr); } } break; case NS_CHINESE_REGULAR_PLACE: ptr = PlaceNonContiguousIntToString(z,ChineseRegularSimplifiedDigits,10); break; case NS_CHINESE_JAPANESE_REGULAR_TRADITIONAL: if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(1); else { ptr = ChineseIntToString(z,ChineseRegularTraditionalDigits,ChineseRegularTraditionalBarriers,0); if(ptr) StripLeadingChineseOne(ptr); } break; case NS_CHINESE_JAPANESE_REGULAR_SIMPLIFIED: if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(0); else { ptr = ChineseIntToString(z,ChineseRegularSimplifiedDigits,JapaneseRegularSimplifiedBarriers,0); if(ptr) StripLeadingChineseOne(ptr); } break; case NS_CHINESE_JAPANESE_LEGAL_TRADITIONAL: if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(1); else ptr = ChineseIntToString(z,JapaneseLegalTraditionalDigits,JapaneseLegalTraditionalBarriers,0); break; case NS_CHINESE_JAPANESE_LEGAL_SIMPLIFIED: if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(0); else ptr = ChineseIntToString(z,JapaneseLegalSimplifiedDigits,JapaneseLegalSimplifiedBarriers,0); break; case NS_CHINESE_JAPANESE_WESTERN_MIX: if (ULT(z,10000)) ptr = PlaceIntToString(z,WESTERN_ZERO,10); else ptr = ChineseWesternIntToString(z,ChineseRegularSimplifiedDigits, JapaneseRegularSimplifiedBarriers); break; case NS_COMMON_BRAILLE: ptr = PlaceNonContiguousIntToString(z,CommonBrailleDigits,10); break; case NS_CYRILLIC_ALPHABETIC: ptr = CyrillicAlphabeticIntToString(z); break; case NS_DEVANAGARI: ptr = PlaceIntToString(z,DEVANAGARI_ZERO,10); break; case NS_EGYPTIAN: ptr = AdditiveIntToString(z,EgyptianData); break; case NS_ETHIOPIC: ptr = EthiopicIntToString(z); break; case NS_EWELLIC_DECIMAL: ptr = PlaceIntToString(z,EWELLIC_ZERO,10); break; case NS_EWELLIC_HEX: ptr = PlaceIntToString(z,EWELLIC_ZERO,16); if(ptr) ptr = Prepend(ptr,0x0060); break; case NS_FRENCH_BRAILLE: ptr = PlaceNonContiguousIntToString(z,FrenchBrailleDigits,10); break; case NS_GLAGOLITIC_ALPHABETIC: ptr = AdditiveIntToString(z,GlagoliticData); if(ptr) FixGlagoliticTeens(ptr); break; case NS_GREEK_ALPHABETIC_LOWER: ptr = GreekAlphabeticIntToString(z,1); break; case NS_GREEK_ALPHABETIC_UPPER: ptr = GreekAlphabeticIntToString(z,0); break; case NS_GUJARATI: ptr = PlaceIntToString(z,GUJARATI_ZERO,10); break; case NS_GURMUKHI: ptr = PlaceIntToString(z,GURMUKHI_ZERO,10); break; case NS_HEBREW_EARLY: ptr = HebrewIntToString(z,HebrewData,1); break; case NS_HEBREW_LATE: ptr = HebrewIntToString(z,HebrewData,0); break; case NS_HEX_LOWER: ptr = WesternGeneralIntToString(z,16,0); if(ptr) ptr = Prepend(ptr,0x0078); if(ptr) ptr = Prepend(ptr,0x0030); break; case NS_HEX_UPPER: ptr = WesternGeneralIntToString(z,16,1); if(ptr) ptr = Prepend(ptr,0x0078); if(ptr) ptr = Prepend(ptr,0x0030); break; case NS_KANNADA: ptr = PlaceIntToString(z,KANNADA_ZERO,10); break; case NS_KHAROSHTHI: ptr = KharoshthiIntToString(z); break; case NS_KHMER: ptr = PlaceIntToString(z,KHMER_ZERO,10); break; case NS_KLINGON: ptr = PlaceIntToString(z,KLINGON_ZERO,10); break; case NS_LAO: ptr = PlaceIntToString(z,LAO_ZERO,10); break; case NS_LIMBU: ptr = PlaceIntToString(z,LIMBU_ZERO,10); break; case NS_MALAYALAM: ptr = PlaceIntToString(z,MALAYALAM_ZERO,10); break; case NS_MONGOLIAN: ptr = PlaceIntToString(z,MONGOLIAN_ZERO,10); break; case NS_MXEDRULI: ptr = AdditiveIntToString(z,MxedruliData); break; case NS_NEW_TAI_LUE: ptr = PlaceIntToString(z,NEW_TAI_LUE_ZERO,10); break; case NS_NKO: ptr = PlaceIntToString(z,NKO_ZERO,10); break; case NS_OLD_ITALIC: ptr = AdditiveIntToString(z,OldItalicData); break; case NS_OLD_PERSIAN: ptr = AdditiveIntToString(z,OldPersianData); break; case NS_ORIYA: ptr = PlaceIntToString(z,ORIYA_ZERO,10); break; case NS_OSMANYA: ptr = PlaceIntToString(z,OSMANYA_ZERO,10); break; case NS_PHOENICIAN: ptr = AdditiveIntToString(z,PhoenicianData); break; case NS_ROMAN_UPPER: ptr = RomanIntToString(z,1); break; case NS_ROMAN_LOWER: ptr = RomanIntToString(z,0); break; case NS_RUSSIAN_BRAILLE: ptr = PlaceNonContiguousIntToString(z,RussianBrailleDigits,10); break; case NS_SINHALA: ptr = AdditiveIntToString(z,SinhalaData); break; case NS_CHINESE_SUZHOU: ptr = PlaceIntToString(z,SUZHOU_ZERO,10); if(ptr) FixSuzhou(ptr); break; case NS_TAMIL_PLACE: ptr = PlaceIntToString(z,TAMIL_ZERO,10); break; case NS_TAMIL_TRADITIONAL: ptr = TamilTraditionalIntToString(z); break; case NS_TELUGU: ptr = PlaceIntToString(z,TELUGU_ZERO,10); break; case NS_TENGWAR_DECIMAL: ptr = TengwarToString(z,10); break; case NS_TENGWAR_DUODECIMAL: ptr = TengwarToString(z,12); break; case NS_THAI: ptr = PlaceIntToString(z,THAI_ZERO,10); break; case NS_TIBETAN: ptr = PlaceIntToString(z,TIBETAN_ZERO,10); break; case NS_VERDURIAN: ptr = PlaceIntToString(z,VERDURIAN_ZERO,10); break; case NS_WESTERN_LOWER: ptr = WesternGeneralIntToString(z,Uninum_Output_Base,0); break; case NS_WESTERN_UPPER: ptr = WesternGeneralIntToString(z,Uninum_Output_Base,1); break; case NS_XUCURI_LOWER: ptr = AdditiveIntToString(z,XucuriLowerData); break; case NS_XUCURI_UPPER: ptr = AdditiveIntToString(z,XucuriUpperData); break; default: uninum_err = NS_ERROR_NUMBER_SYSTEM_UNKNOWN; ptr = NULL; } mpz_clear(z); if(ptr && Uninum_Output_General_Group_Size){ tmpptr =wcDelimitNumber(ptr, Uninum_Output_Group_Separator, Uninum_Output_Decimal_Separator, Uninum_Output_General_Group_Size, Uninum_Output_First_Group_Size); free(ptr); ptr = tmpptr; } return ptr; } /* Tcl API */ /* * Generate the list of available writing systems, * * which = 0 -> list specific names usable in both directions * which = 1 -> list cover terms suitable only for conversion of string to int */ char *Tcl_ListNumberSystems (int which) { int Entries; int i; int CharsNeeded = 0; char *new; char *p; uninum_err = NS_ERROR_OKAY; Entries = sizeof(NumberSystemList)/sizeof(struct ns); for (i=0; i 0xFFFF) { uninum_err = NS_ERROR_OUTSIDE_BMP; optr[0] = UNI_REPLACEMENT_CHAR; optr[1] = 0x0000; } } } } /* The C API generates UTF32. Convert this to UCS-2 (UTF-16 without surrogates) for Tcl */ len = ucslen(optr); tclptr = malloc((len+1) * sizeof(UCS2)); if(!tclptr) { uninum_err = NS_ERROR_OUTOFMEMORY; free(optr); return NULL; } s = optr; t = tclptr; while(*s != 0x0000) *t++ = (UTF16) (0x0000FFFF & *s++); *t = 0x0000; free(optr); return(tclptr); } char *StrGuessNumberSystem(UTF16 *s){ UTF32 *t; UTF32 *tptr; int len; int i; int ns; len = uninum_utf16len(s); #ifdef ALLOCAOK t = alloca((len+1) * sizeof(UTF32)); #else t = malloc((len+1) * sizeof(UTF32)); #endif tptr = t; for (i = 0; i < len; i++) *tptr++ = *s++; *tptr = 0x0000; ns = GuessNumberSystem(t); #ifndef ALLOCAOK free((void *) t); #endif return(NumberSystemToString(ns)); } char *UninumNumberSystemMaximumValue (char *nsn){ int ns; char *rval; uninum_err = NS_ERROR_OKAY; ns = StringToNumberSystem(nsn); if(ns == NS_UNKNOWN) { uninum_err = NS_ERROR_NUMBER_SYSTEM_UNKNOWN; return NULL; } rval = UninumStringMaximumValue(ns); return(rval); }