1
/* Time-stamp: <2007-09-22 19:43:29 poser> */
3
* Copyright (C) 2006-2007 William J. Poser.
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of version 2 of the GNU Lesser General
6
* Public License as published by the Free Software Foundation.
8
* This library is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
* Lesser General Public License for more details.
13
* You should have received a copy of the GNU Lesser General Public
14
* License along with this library; if not, write to the Free Software
15
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
#define TGE(op1, op2) (mpz_cmp(op1, op2) >= 0 )
19
#define TGT(op1, op2) (mpz_cmp(op1, op2) > 0 )
20
#define TLE(op1, op2) (mpz_cmp(op1, op2) <= 0 )
21
#define TLT(op1, op2) (mpz_cmp(op1, op2) < 0 )
22
#define TEQ(op1, op2) (mpz_cmp(op1, op2) == 0 )
23
#define TNE(op1, op2) (mpz_cmp(op1, op2) != 0 )
24
#define UGE(op1, op2) (mpz_cmp_ui(op1, op2) >= 0 )
25
#define UGT(op1, op2) (mpz_cmp_ui(op1, op2) > 0 )
26
#define ULE(op1, op2) (mpz_cmp_ui(op1, op2) <= 0 )
27
#define ULT(op1, op2) (mpz_cmp_ui(op1, op2) < 0 )
28
#define UEQ(op1, op2) (mpz_cmp_ui(op1, op2) == 0 )
29
#define UNE(op1, op2) (mpz_cmp_ui(op1, op2) != 0 )
32
* These functions convert UTF-32 strings representing integers in various
33
* writing systems to unsigned long integers or to ASCII decimal strings
34
* in the Indo-Arabic number system.
38
#define ucslen(x) wcslen((signed long *) x)
39
#define ucscpy(x,y) (UTF32 *)wcscpy((signed long *)x,(signed long *)y)
40
#define ucscat(x,y) (UTF32 *)wcscat((signed long *)x,(signed long *)y)
41
#define ucschr(x,y) (UTF32 *)wcschr((signed long *)x,(signed long)y)
42
#define ucsrchr(x,y) (UTF32 *)wcsrchr((signed long *)x,(signed long)y)
66
int uninum_err; /* Exported for error detection */
67
UTF32 uninum_badchar; /* Exported for error detection */
68
UTF16 tcl_uninum_badchar; /* Exported for error detection */
69
short uninum_ns_type; /* Exported for sanity-checking */
71
/* Exported for parameter setting */
72
int Uninum_Input_Base = 10;
73
int Uninum_Output_Base = 10;
74
int Uninum_Output_General_Group_Size = 0;
75
int Uninum_Output_First_Group_Size = 3;
76
UTF16 Uninum_Output_Group_Separator = 0x002C; /* Comma */
77
int Uninum_Generate_Roman_With_Bar_P = 0;
79
/* We're currently not dealing with non-integers - this is just forward-looking */
80
static UTF32 Uninum_Output_Decimal_Separator = 0x002E;
82
/* (10^97)-1, in hex for compactness and speed of conversion to binary */
83
#define MAXCHINESEHEX "4AE825771DC07672DDD0F8E8AC39250971AC4210CECB6F656CAEB9109FFFFFFFFFFFFFFFFFFFFFFFF"
84
#define CYRILLIC_THOUSANDS_SIGN 0x0482
85
#define CYRILLIC_TITLO 0x0483
86
#define TENGWAR_DECIMAL_MARKER 0xE06C
87
#define TENGWAR_DUODECIMAL_MARKER 0xE06D
88
#define TENGWAR_DUODECIMAL_LSD_MARKER 0xE06E
89
#define TENGWAR_DEC 0xE06A
90
#define TENGWAR_EL 0xE06B
92
char *uninum_version(void) {
96
#ifdef HAVE_LOCALECONV
98
void GetLocaleGroupInfo (){
101
setlocale(LC_NUMERIC,"");
102
lcptr = localeconv();
104
fprintf(stderr,"Attempt to obtain locale information was unsuccessful.\n");
107
Uninum_Output_Group_Separator = (UTF16) (lcptr->thousands_sep[0]);
108
Uninum_Output_First_Group_Size = lcptr->grouping[0];
109
if(lcptr->grouping[1] != 0) Uninum_Output_General_Group_Size = lcptr->grouping[1];
110
else Uninum_Output_General_Group_Size = Uninum_Output_First_Group_Size;
116
/* Auxiliary functions */
118
unsigned long ipow(int base, int cnt) {
120
unsigned long Result;
124
while (i++ <= cnt) Result *= base;
129
* Copy a string and return a pointer to the
130
* terminal null of the copy. The target must
131
* have sufficient storage.
133
static char *strpcpy(char *dest, const char *src) {
147
* Case-insenstive ascii string comparison.
148
* Emulates BSD 4.4 function emulated by GNU
150
static int mystrcasecmp(char *a, char *b) {
156
if(ac < bc) return (-1);
157
if(ac > bc) return (1);
159
if(*b != '\0') return (-1);
164
* Copy a wide string and return a pointer to the
165
* terminal null of the copy. The target must
166
* have sufficient storage.
167
* This emulates the GNU extension wcpcpy().
169
static UTF32 *ucpcpy(UTF32 *dest, const UTF32 *src) {
175
while (*s != 0x0000) {
183
* Reverse a wide string in place.
185
static UTF32 *wcsrev(UTF32 *s) {
193
h = s + (ucslen(s)/2);
203
* Prepend a character to a string, returning new storage
204
* and freeing the old.
206
static UTF32 *Prepend(UTF32 *s, UTF32 c) {
211
new = malloc(sizeof(UTF32) * (len + 2));
221
/* Remove "thousands separator"s */
222
UTF32 *wcStripSeparators(UTF32 *s) {
228
while ((c = *s++) != 0x0000){
230
case 0x0020: /* Space */
231
case 0x0027: /* Apostrophe */
232
case 0x002C: /* Comma */
233
case 0x002E: /* Period */
234
case 0x066C: /* Arabic thousands separator */
235
case 0x1361: /* Ethiopic wordspace */
236
case 0x3000: /* Ideographic space */
237
/* We can't add the Braille comma U+2802 here because Russian Braille uses
238
the same character for the digit "1" */
250
* It is the caller's responsability to free the original storage.
252
UTF32 *wcDelimitNumber(
254
UTF16 gs, /* Group separator character */
255
UTF32 ds, /* Decimal point character */
256
int GroupSize, /* Number of digits in groups in general */
257
int FirstGroupSize /* Number of digits in low-order group */
260
int New_Size; /* Characters needed for delimited string */
261
int length; /* Length of input string */
262
int commas; /* Number of delimiters to insert */
263
int Comma_Cnt; /* Number of delimiters inserted so far */
264
int digits; /* Number of digits preceding decimal point */
265
int cnt; /* Number of digits processed */
267
UTF32 *new; /* String in which to write delimited number */
268
UTF32 *point; /* Location of decimal point */
269
UTF32 *pos; /* Current position in original number */
270
UTF32 *npos; /* Current position in new number */
271
UTF32 *Non_Space_Number; /* Location of first non-space character in number */
274
if( (GroupSize < 2) || (FirstGroupSize < 2)) {
279
length = ucslen(number);
280
point = ucsrchr(number,(UTF32) '.');
281
if(point == NULL) point = number+(length-1);
282
else point-=1; /* Point now points at last digit preceding decimal/end */
283
Non_Space_Number = ucsrchr(number,0x0020);
284
if(Non_Space_Number == NULL) Non_Space_Number = number;
285
else Non_Space_Number+=1;
287
digits = 1+point - Non_Space_Number;
288
if(digits > FirstGroupSize) {
289
commas = 1 + ((digits-FirstGroupSize-1)/GroupSize);
294
New_Size = length + commas;
295
new = (UTF32 *) malloc((New_Size + 1) * sizeof(UTF32));
297
if (commas == 0) return ucscpy(new,number);
299
/* First copy right hand part of number, up to and including decimal point */
302
for(; pos > point;) *npos-- = *pos--;
304
/* Now copy lefthand part, inserting delimiters as we go */
306
if(FirstGroupSize != GroupSize) {
307
for (i = 0; i < FirstGroupSize; i++) *npos-- = *pos--; /* Copy low group */
308
*npos-- = (UTF32) gs;
309
*npos-- = *pos--; /* Low digit of second group */
312
while(pos >= Non_Space_Number){
314
if( (++cnt % GroupSize == 0) && (Comma_Cnt++ < commas )) *npos-- = (UTF32) gs;
317
while(pos >= number) *npos-- = *pos--; /* Copy leading spaces, if any */
323
* Returns a null-terminated wide string containing
324
* the specified character.
326
static UTF32 *MakeSingleDigitString(UTF32 c) {
328
new = malloc(sizeof(UTF32) * 2);
330
uninum_err = NS_ERROR_OUTOFMEMORY;
338
struct ns {char *s; int c; short type;};
339
static struct ns NumberSystemList[] = {
340
"Aegean",NS_AEGEAN,NS_TYPE_SAFE,
341
"All",NS_ALL,NS_TYPE_SPECIAL,
342
"Any",NS_ANY,NS_TYPE_SPECIAL,
343
"Arabic_Alphabetic",NS_ARABIC_ALPHABETIC,NS_TYPE_SAFE,
344
"Arabic_Persian",NS_PERSO_ARABIC,NS_TYPE_SAFE,
345
"Arabic_Western",NS_ARABIC_WESTERN,NS_TYPE_SAFE,
346
"Armenian",NS_ARMENIAN_ALPHABETIC,NS_TYPE_SAFE,
347
"Balinese",NS_BALINESE,NS_TYPE_SAFE,
348
"Bengali",NS_BENGALI,NS_TYPE_SAFE,
349
"Burmese",NS_BURMESE,NS_TYPE_SAFE,
350
"Chinese",NS_CHINESE_GENERIC,NS_TYPE_COVER,
351
"Chinese_Counting_Rod_Early",NS_CHINESE_COUNTING_ROD_EARLY_WITH_ZERO,NS_TYPE_SAFE,
352
"Chinese_Counting_Rod_Late",NS_CHINESE_COUNTING_ROD_LATE_WITH_ZERO,NS_TYPE_SAFE,
353
"Chinese_Counting_Rod_Early_No_Zero",NS_CHINESE_COUNTING_ROD_EARLY_WITHOUT_ZERO,NS_TYPE_SAFE,
354
"Chinese_Counting_Rod_Late_No_Zero",NS_CHINESE_COUNTING_ROD_LATE_WITHOUT_ZERO,NS_TYPE_SAFE,
355
"Chinese_Legal_Simplified",NS_CHINESE_LEGAL_SIMPLIFIED,NS_TYPE_SAFE,
356
"Chinese_Legal_Traditional",NS_CHINESE_LEGAL_TRADITIONAL,NS_TYPE_SAFE,
357
"Chinese_Regular_Simplified",NS_CHINESE_REGULAR_SIMPLIFIED,NS_TYPE_SAFE,
358
"Chinese_Regular_Traditional",NS_CHINESE_REGULAR_TRADITIONAL,NS_TYPE_SAFE,
359
"Chinese_Regular_Place",NS_CHINESE_REGULAR_PLACE,NS_TYPE_SAFE,
360
"Common_Braille",NS_COMMON_BRAILLE,NS_TYPE_SAFE,
361
"Counting_Rod",NS_CHINESE_COUNTING_ROD_GENERIC,NS_TYPE_COVER,
362
"Cyrillic",NS_CYRILLIC_ALPHABETIC,NS_TYPE_SAFE,
363
"Devanagari",NS_DEVANAGARI,NS_TYPE_SAFE,
364
"Egyptian",NS_EGYPTIAN,NS_TYPE_SAFE,
365
"Ethiopic",NS_ETHIOPIC,NS_TYPE_SAFE,
366
"Ewellic_Decimal",NS_EWELLIC_DECIMAL,NS_TYPE_SAFE,
367
"Ewellic_Hexadecimal",NS_EWELLIC_HEX,NS_TYPE_SAFE,
368
"French_Braille",NS_FRENCH_BRAILLE,NS_TYPE_SAFE,
369
"Glagolitic",NS_GLAGOLITIC_ALPHABETIC,NS_TYPE_SAFE,
370
"Greek",NS_GREEK_ALPHABETIC_UPPER,NS_TYPE_COVER,
371
"Greek_Lower",NS_GREEK_ALPHABETIC_LOWER,NS_TYPE_SAFE,
372
"Greek_Upper",NS_GREEK_ALPHABETIC_UPPER,NS_TYPE_SAFE,
373
"Gujarati",NS_GUJARATI,NS_TYPE_SAFE,
374
"Gurmukhi",NS_GURMUKHI,NS_TYPE_SAFE,
375
"Hebrew",NS_HEBREW_GENERIC,NS_TYPE_COVER,
376
"Hebrew_Early",NS_HEBREW_EARLY,NS_TYPE_SAFE,
377
"Hebrew_Late",NS_HEBREW_LATE,NS_TYPE_SAFE,
378
"Hexadecimal",NS_HEX,NS_TYPE_COVER,
379
"Hexadecimal_Lower",NS_HEX_LOWER,NS_TYPE_SAFE,
380
"Hexadecimal_Upper",NS_HEX_UPPER,NS_TYPE_SAFE,
381
"Japanese_Regular_Simplified",NS_CHINESE_JAPANESE_REGULAR_SIMPLIFIED,NS_TYPE_SAFE,
382
"Japanese_Regular_Traditional",NS_CHINESE_JAPANESE_REGULAR_TRADITIONAL,NS_TYPE_SAFE,
383
"Japanese_Legal_Simplified",NS_CHINESE_JAPANESE_LEGAL_SIMPLIFIED,NS_TYPE_SAFE,
384
"Japanese_Legal_Traditional",NS_CHINESE_JAPANESE_LEGAL_TRADITIONAL,NS_TYPE_SAFE,
385
"Japanese_Western_Mixed",NS_CHINESE_JAPANESE_WESTERN_MIX,NS_TYPE_SAFE,
386
"Kannada",NS_KANNADA,NS_TYPE_SAFE,
387
"Kharoshthi",NS_KHAROSHTHI,NS_TYPE_SAFE,
388
"Khmer",NS_KHMER,NS_TYPE_SAFE,
389
"Klingon",NS_KLINGON,NS_TYPE_SAFE,
390
"Lao",NS_LAO,NS_TYPE_SAFE,
391
"Limbu",NS_LIMBU,NS_TYPE_SAFE,
392
"Malayalam",NS_MALAYALAM,NS_TYPE_SAFE,
393
"Mandarin_Legal_Simplified",NS_CHINESE_MANDARIN_LEGAL_SIMPLIFIED,NS_TYPE_SAFE,
394
"Mandarin_Legal_Traditional",NS_CHINESE_MANDARIN_LEGAL_TRADITIONAL,NS_TYPE_SAFE,
395
"Mandarin_Regular_Simplified",NS_CHINESE_MANDARIN_REGULAR_SIMPLIFIED,NS_TYPE_SAFE,
396
"Mandarin_Regular_Traditional",NS_CHINESE_MANDARIN_REGULAR_TRADITIONAL,NS_TYPE_SAFE,
397
"Mongolian",NS_MONGOLIAN,NS_TYPE_SAFE,
398
"Mxedruli",NS_MXEDRULI,NS_TYPE_SAFE,
399
"New_Tai_Lue",NS_NEW_TAI_LUE,NS_TYPE_SAFE,
400
"Nko",NS_NKO,NS_TYPE_SAFE,
401
"Old_Italic",NS_OLD_ITALIC,NS_TYPE_SAFE,
402
"Old_Persian",NS_OLD_PERSIAN,NS_TYPE_SAFE,
403
"Oriya",NS_ORIYA,NS_TYPE_SAFE,
404
"Osmanya",NS_OSMANYA,NS_TYPE_SAFE,
405
"Phoenician",NS_PHOENICIAN,NS_TYPE_SAFE,
406
"Roman",NS_ROMAN_GENERIC,NS_TYPE_COVER,
407
"Roman_Lower",NS_ROMAN_LOWER,NS_TYPE_SAFE,
408
"Roman_Upper",NS_ROMAN_UPPER,NS_TYPE_SAFE,
409
"Russian_Braille",NS_RUSSIAN_BRAILLE,NS_TYPE_SAFE,
410
"Sinhala",NS_SINHALA,NS_TYPE_SAFE,
411
"Suzhou",NS_CHINESE_SUZHOU,NS_TYPE_SAFE,
412
"Tamil",NS_TAMIL_GENERIC,NS_TYPE_COVER,
413
"Tamil_Place",NS_TAMIL_PLACE,NS_TYPE_SAFE,
414
"Tamil_Traditional",NS_TAMIL_TRADITIONAL,NS_TYPE_SAFE,
415
"Telugu",NS_TELUGU,NS_TYPE_SAFE,
416
"Tengwar_Decimal",NS_TENGWAR_DECIMAL,NS_TYPE_SAFE,
417
"Tengwar_Duodecimal",NS_TENGWAR_DUODECIMAL,NS_TYPE_SAFE,
418
"Thai",NS_THAI,NS_TYPE_SAFE,
419
"Tibetan",NS_TIBETAN,NS_TYPE_SAFE,
420
"Verdurian",NS_VERDURIAN,NS_TYPE_SAFE,
421
"Western",NS_WESTERN_GENERIC,NS_TYPE_COVER,
422
"Western_Lower",NS_WESTERN_LOWER,NS_TYPE_SAFE,
423
"Western_Upper",NS_WESTERN_UPPER,NS_TYPE_SAFE,
424
"Xucuri_Lower",NS_XUCURI_LOWER,NS_TYPE_SAFE,
425
"Xucuri_Upper",NS_XUCURI_UPPER,NS_TYPE_SAFE,
426
"Unknown",NS_UNKNOWN,NS_TYPE_GUESS,
427
"All_Zero",NS_ALLZERO,NS_TYPE_GUESS
431
* Generate the list of available writing systems,
432
* returning the next string on each call unless
433
* the flag is 0, which resets to the start of the
436
* which = 0 -> list specific names usable in both directions
437
* which = 1 -> list cover terms suitable only for conversion of string to int
439
char *ListNumberSystems (int flag, int which) {
442
if(flag == 0) i = 0; /* reset */
444
top: if (i < (sizeof(NumberSystemList)/sizeof(struct ns))) {
445
if (NumberSystemList[i].type == (which? 2:1)) return NumberSystemList[i++].s;
456
* We just use linear search for the time being.
457
* Could switch to binary search for greater speed.
460
int StringToNumberSystem (char *s) {
462
for (i=0; i < (sizeof(NumberSystemList)/sizeof(struct ns)); i++) {
463
if (mystrcasecmp(s,NumberSystemList[i].s) == 0){
464
uninum_ns_type = NumberSystemList[i].type;
465
return (NumberSystemList[i].c);
472
* We just use linear search for the time being.
473
* Could switch to binary search for greater speed.
476
char *NumberSystemToString (int ns) {
478
for (i=0; i < (sizeof(NumberSystemList)/sizeof(struct ns)); i++) {
479
if (NumberSystemList[i].c == ns) return NumberSystemList[i].s;
485
* Return the maximum value expressible in the specified number system.
486
* as a decimal ascii string, or if there is no limit, "unlimited".
489
#define AEGEAN_LIMIT 99999
490
#define ARABIC_LIMIT 1999
491
#define ARMENIAN_LIMIT 9999
492
#define CYRILLIC_LIMIT 999
493
#define EGYPTIAN_LIMIT 9999999
494
#define GLAGOLITIC_LIMIT 9999
495
#define GREEK_LIMIT 9999
496
#define HEBREW_LIMIT 9999
497
#define KHAROSHTHI_LIMIT 999999
498
#define MXEDRULI_LIMIT 10000
499
#define OLD_ITALIC_LIMIT 999
500
#define OLD_PERSIAN_LIMIT 999
501
#define PHOENICIAN_LIMIT 999
502
#define ROMAN_LIMIT 9999
503
#define SINHALA_LIMIT 9999
504
#define TAMIL_LIMIT 999999
505
#define XUCURI_LIMIT 10000
507
char *UninumStringMaximumValue(int ns) {
515
case NS_CHINESE_LEGAL_SIMPLIFIED:
516
case NS_CHINESE_LEGAL_TRADITIONAL:
517
case NS_CHINESE_REGULAR_SIMPLIFIED:
518
case NS_CHINESE_REGULAR_TRADITIONAL:
519
case NS_CHINESE_MANDARIN_LEGAL_SIMPLIFIED:
520
case NS_CHINESE_MANDARIN_LEGAL_TRADITIONAL:
521
case NS_CHINESE_MANDARIN_REGULAR_SIMPLIFIED:
522
case NS_CHINESE_MANDARIN_REGULAR_TRADITIONAL:
523
case NS_CHINESE_JAPANESE_REGULAR_SIMPLIFIED:
524
case NS_CHINESE_JAPANESE_REGULAR_TRADITIONAL:
525
case NS_CHINESE_JAPANESE_WESTERN_MIX:
526
case NS_CHINESE_JAPANESE_LEGAL_SIMPLIFIED:
527
case NS_CHINESE_JAPANESE_LEGAL_TRADITIONAL:
528
mpz_init_set_str(MaxChinese,MAXCHINESEHEX,16);
529
new = malloc((mpz_sizeinbase(MaxChinese,10) + 1) * sizeof(char));
530
if(!new) {uninum_err = NS_ERROR_OUTOFMEMORY;return NULL;}
531
(void) mpz_get_str(new,10,MaxChinese);
532
mpz_clear(MaxChinese);
535
mpz_set_ui(Limit,AEGEAN_LIMIT);
537
case NS_ARABIC_ALPHABETIC:
538
mpz_set_ui(Limit,ARABIC_LIMIT);
540
case NS_ARMENIAN_ALPHABETIC:
541
mpz_set_ui(Limit,ARMENIAN_LIMIT);
543
case NS_CYRILLIC_ALPHABETIC:
544
mpz_set_ui(Limit,CYRILLIC_LIMIT);
547
mpz_set_ui(Limit,EGYPTIAN_LIMIT);
549
case NS_GLAGOLITIC_ALPHABETIC:
550
mpz_set_ui(Limit,GLAGOLITIC_LIMIT);
552
case NS_GREEK_ALPHABETIC_UPPER:
553
case NS_GREEK_ALPHABETIC_LOWER:
554
mpz_set_ui(Limit,GREEK_LIMIT);
556
case NS_HEBREW_EARLY:
558
mpz_set_ui(Limit,HEBREW_LIMIT);
561
mpz_set_ui(Limit,KHAROSHTHI_LIMIT);
564
mpz_set_ui(Limit,MXEDRULI_LIMIT);
567
mpz_set_ui(Limit,OLD_ITALIC_LIMIT);
570
mpz_set_ui(Limit,OLD_PERSIAN_LIMIT);
573
mpz_set_ui(Limit,PHOENICIAN_LIMIT);
577
mpz_set_ui(Limit,ROMAN_LIMIT);
580
mpz_set_ui(Limit,SINHALA_LIMIT);
582
case NS_TAMIL_TRADITIONAL:
583
mpz_set_ui(Limit,TAMIL_LIMIT);
585
case NS_XUCURI_LOWER:
586
case NS_XUCURI_UPPER:
587
mpz_set_ui(Limit,XUCURI_LIMIT);
590
new = malloc (sizeof(char) * (1 + strlen("unlimited")));
591
if(!new) {uninum_err = NS_ERROR_OUTOFMEMORY;return NULL;}
592
sprintf(new,"%s","unlimited");
595
new = malloc((mpz_sizeinbase(Limit,10) + 1) * sizeof(char));
596
if(!new) {uninum_err = NS_ERROR_OUTOFMEMORY;return NULL;}
597
(void) mpz_get_str(new,10,Limit);
602
#define AEGEAN_BEGIN 0x10107
603
#define AEGEAN_END 0x10133
604
#define ARABIC_BEGIN 0x0660
605
#define ARABIC_END 0x066C
606
#define ARABIC_ALPHABETIC_BEGIN 0x0627
607
#define ARABIC_ALPHABETIC_END 0x064A
608
#define PERSO_ARABIC_BEGIN 0x06F0
609
#define PERSO_ARABIC_END 0x06F9
610
#define ARMENIAN_ALPHABETIC_UPPER_BEGIN 0x0531
611
#define ARMENIAN_ALPHABETIC_UPPER_END 0x554
612
#define BALINESE_BEGIN 0x1B50
613
#define BALINESE_END 0x1B59
614
#define BENGALI_BEGIN 0x09E6
615
#define BENGALI_END 0x09EF
616
#define BURMESE_BEGIN 0x1040
617
#define BURMESE_END 0x1049
618
#define CHINESE_COUNTING_ROD_BEGIN 0x1D360
619
#define CHINESE_COUNTING_ROD_END 0x1D371
620
#define CHINESE_A_BEGIN 0x4E00
621
#define CHINESE_A_END 0x9FBB
622
#define CHINESE_B_BEGIN 0x20000
623
#define CHINESE_B_END 0x2A6D6
624
#define CYRILLIC_ALPHABETIC_UPPER_BEGIN 0x0400
625
#define CYRILLIC_ALPHABETIC_UPPER_END 0x04FF
626
#define DEVANAGARI_BEGIN 0x0966
627
#define DEVANAGARI_END 0x096F
628
#define COMMON_BRAILLE_BEGIN 0x2801
629
#define COMMON_BRAILLE_END 0x281B
630
#define ETHIOPIC_BEGIN 0x1369
631
#define ETHIOPIC_END 0x137C
632
#define EWELLIC_BEGIN 0xE6C0
633
#define EWELLIC_DECIMAL_END 0xE6C9
634
#define EWELLIC_END 0xE6CF
635
#define GLAGOLITIC_ALPHABETIC_BEGIN 0x2C00
636
#define GLAGOLITIC_ALPHABETIC_END 0x2C1E
637
#define GREEK_ALPHABETIC_LOWER_BEGIN 0x03B1
638
#define GREEK_ALPHABETIC_LOWER_END 0x03C9
639
#define GREEK_ALPHABETIC_UPPER_BEGIN 0x0391
640
#define GREEK_ALPHABETIC_UPPER_END 0x03A9
641
#define GREEK_ALPHABETIC_LOWER_DIGAMMA 0x03DD
642
#define GREEK_ALPHABETIC_UPPER_DIGAMMA 0x03DC
643
#define GREEK_ALPHABETIC_LOWER_KOPPA 0x03DF
644
#define GREEK_ALPHABETIC_UPPER_KOPPA 0x03DE
645
#define GREEK_ALPHABETIC_LOWER_SAN 0x03FB
646
#define GREEK_ALPHABETIC_UPPER_SAN 0x03FA
647
#define GREEK_ALPHABETIC_LOWER_STIGMA 0x03DB
648
#define GREEK_ALPHABETIC_UPPER_STIGMA 0x03DA
649
#define GREEK_ALPHABETIC_RIGHT_KERAIA 0x0374
650
#define GREEK_ALPHABETIC_LEFT_KERAIA 0x0375
651
#define GUJARATI_BEGIN 0x0AE6
652
#define GUJARATI_END 0x0AEF
653
#define GURMUKHI_BEGIN 0x0A66
654
#define GURMUKHI_END 0x0A6F
655
#define HEBREW_BEGIN 0x0590
656
#define HEBREW_END 0x05FF
657
#define KANNADA_BEGIN 0x0CE6
658
#define KANNADA_END 0x0CEF
659
#define KHAROSHTHI_BEGIN 0x10A40
660
#define KHAROSHTHI_END 0x10A47
661
#define KHMER_BEGIN 0x17E0
662
#define KHMER_END 0x17E9
663
#define KLINGON_BEGIN 0xF8F0
664
#define KLINGON_END 0xF8F9
665
#define LAO_BEGIN 0x0ED0
666
#define LAO_END 0x0ED9
667
#define LIMBU_BEGIN 0x1946
668
#define LIMBU_END 0x194F
669
#define MALAYALAM_BEGIN 0x0D00
670
#define MALAYALAM_END 0x0D7F
671
#define MONGOLIAN_BEGIN 0x1810
672
#define MONGOLIAN_END 0x1819
673
#define MXEDRULI_BEGIN 0x10D0
674
#define MXEDRULI_END 0x10F5
675
#define NEW_TAI_LUE_BEGIN 0x19D0
676
#define NEW_TAI_LUE_END 0x19D9
677
#define NKO_BEGIN 0x07C0
678
#define NKO_END 0x07C9
679
#define OLD_ITALIC_BEGIN 0x10320
680
#define OLD_ITALIC_END 0x10323
681
#define OLD_PERSIAN_BEGIN 0x103D1
682
#define OLD_PERSIAN_END 0x103D5
683
#define ORIYA_BEGIN 0x0B66
684
#define ORIYA_END 0x0B6F
685
#define OSMANYA_BEGIN 0x104A0
686
#define OSMANYA_END 0x104A9
687
#define PHOENICIAN_BEGIN 0x10916
688
#define PHOENICIAN_END 0x10919
689
#define SINHALA_BEGIN 0x0DE7
690
#define SINHALA_END 0x0DFA
691
#define SUZHOU_BEGIN 0x3021
692
#define SUZHOU_END 0x3029
693
#define TAMIL_BEGIN 0x0BE6
694
#define TAMIL_END 0x0BF2
695
#define TELUGU_BEGIN 0x0C66
696
#define TELUGU_END 0x0C6F
697
#define TENGWAR_BEGIN 0xE030
698
#define TENGWAR_END 0xE06E
699
#define THAI_BEGIN 0x0E50
700
#define THAI_END 0x0E59
701
#define TIBETAN_BEGIN 0x0F20
702
#define TIBETAN_END 0x0F29
703
#define VERDURIAN_BEGIN 0xE260
704
#define VERDURIAN_END 0xE26B
705
#define XUCURI_LOWER_BEGIN 0x2D00
706
#define XUCURI_LOWER_END 0x2D25
707
#define XUCURI_UPPER_BEGIN 0x10A0
708
#define XUCURI_UPPER_END 0x10C5
711
int GuessNumberSystem(UTF32 *str){
717
short FirstIsGraveP = 0;
719
uninum_err = NS_ERROR_OKAY;
720
if (!str) return (NS_UNKNOWN);
723
if((c = *s) == 0x0060) FirstIsGraveP = 1;
724
while((c = *s++) != 0x0000) {
725
if ((c >= AEGEAN_BEGIN) && (c <= AEGEAN_END)) return NS_AEGEAN;
726
if ((c >= ARABIC_BEGIN) && (c <= ARABIC_END)) return NS_ARABIC_WESTERN;
727
if ((c >= ARABIC_ALPHABETIC_BEGIN) &&
728
(c <= ARABIC_ALPHABETIC_END)) return NS_ARABIC_ALPHABETIC;
729
if ((c >= PERSO_ARABIC_BEGIN) &&
730
(c <= PERSO_ARABIC_END)) return NS_PERSO_ARABIC;
731
if (((c >= ARMENIAN_ALPHABETIC_UPPER_BEGIN) && (c <= ARMENIAN_ALPHABETIC_UPPER_END))) {
732
return NS_ARMENIAN_ALPHABETIC;
734
if ((c >= BALINESE_BEGIN) && (c <= BALINESE_END)) return NS_BALINESE;
735
if ((c >= BENGALI_BEGIN) && (c <= BENGALI_END)) return NS_BENGALI;
736
if ((c >= BURMESE_BEGIN) && (c <= BURMESE_END)) return NS_BURMESE;
737
if ((c >= CHINESE_COUNTING_ROD_BEGIN) && (c <= CHINESE_COUNTING_ROD_END)) return NS_CHINESE_COUNTING_ROD_GENERIC;
738
if ( ((c >= CHINESE_A_BEGIN) && (c <= CHINESE_A_END)) ||
739
((c >= CHINESE_B_BEGIN) && (c <= CHINESE_B_END)) ||
740
( (c >= SUZHOU_BEGIN) && (c <= SUZHOU_END)) ) return NS_CHINESE_GENERIC;
741
if (((c >= CYRILLIC_ALPHABETIC_UPPER_BEGIN) && (c <= CYRILLIC_ALPHABETIC_UPPER_END)) ||
742
(c == CYRILLIC_THOUSANDS_SIGN) || (c == CYRILLIC_TITLO)) {
743
return NS_CYRILLIC_ALPHABETIC;
745
if ((c >= DEVANAGARI_BEGIN) && (c <= DEVANAGARI_END)) return NS_DEVANAGARI;
746
if ((c >= 0x14000) && (c <= 0x143D7)) return NS_EGYPTIAN;
747
if ((c >= ETHIOPIC_BEGIN) && (c <= ETHIOPIC_END)) return NS_ETHIOPIC;
748
if ((c > EWELLIC_DECIMAL_END) && (c <= EWELLIC_END)) return NS_EWELLIC_HEX;
749
if ((c >= EWELLIC_BEGIN) && (c <= EWELLIC_DECIMAL_END)) {
750
if(FirstIsGraveP) return NS_EWELLIC_HEX;
751
else return NS_EWELLIC_DECIMAL;
753
if ((c >= GLAGOLITIC_ALPHABETIC_BEGIN) && (c <= GLAGOLITIC_ALPHABETIC_END)) return NS_GLAGOLITIC_ALPHABETIC;
754
if (((c >= GREEK_ALPHABETIC_LOWER_BEGIN) && (c <= GREEK_ALPHABETIC_LOWER_END)) ||
755
(c == GREEK_ALPHABETIC_LOWER_DIGAMMA) ||
756
(c == GREEK_ALPHABETIC_LOWER_KOPPA) ||
757
(c == GREEK_ALPHABETIC_LOWER_STIGMA) ||
758
(c == GREEK_ALPHABETIC_LOWER_SAN)) return NS_GREEK_ALPHABETIC_LOWER;
759
if (((c >= GREEK_ALPHABETIC_UPPER_BEGIN) && (c <= GREEK_ALPHABETIC_UPPER_END)) ||
760
(c == GREEK_ALPHABETIC_UPPER_DIGAMMA) ||
761
(c == GREEK_ALPHABETIC_UPPER_KOPPA) ||
762
(c == GREEK_ALPHABETIC_UPPER_STIGMA) ||
763
(c == GREEK_ALPHABETIC_UPPER_SAN)) return NS_GREEK_ALPHABETIC_UPPER;
764
if ((c >= GUJARATI_BEGIN) && (c <= GUJARATI_END)) return NS_GUJARATI;
765
if ((c >= GURMUKHI_BEGIN) && (c <= GURMUKHI_END)) return NS_GURMUKHI;
766
if ((c >= HEBREW_BEGIN) && (c <= HEBREW_END)) return NS_HEBREW_GENERIC;
767
if ((c >= KANNADA_BEGIN) && (c <= KANNADA_END)) return NS_KANNADA;
768
if ((c >= KHAROSHTHI_BEGIN) && (c <= KHAROSHTHI_END)) return NS_KHAROSHTHI;
769
if ((c >= KHMER_BEGIN) && (c <= KHMER_END)) return NS_KHMER;
770
if ((c >= KLINGON_BEGIN) && (c <= KLINGON_END)) return NS_KLINGON;
771
if ((c >= LAO_BEGIN) && (c <= LAO_END)) return NS_LAO;
772
if ((c >= LIMBU_BEGIN) && (c <= LIMBU_END)) return NS_LIMBU;
773
if ((c >= MALAYALAM_BEGIN) && (c <= MALAYALAM_END)) return NS_MALAYALAM;
774
if ((c >= MONGOLIAN_BEGIN) && (c <= MONGOLIAN_END)) return NS_MONGOLIAN;
775
if ((c >= MXEDRULI_BEGIN) && (c <= MXEDRULI_END)) return NS_MXEDRULI;
776
if ((c >= NEW_TAI_LUE_BEGIN) && (c <= NEW_TAI_LUE_END)) return NS_NEW_TAI_LUE;
777
if ((c >= NKO_BEGIN) && (c <= NKO_END)) return NS_NKO;
778
if ((c >= OLD_ITALIC_BEGIN) && (c <= OLD_ITALIC_END)) return NS_OLD_ITALIC;
779
if ((c >= OLD_PERSIAN_BEGIN) && (c <= OLD_PERSIAN_END)) return NS_OLD_PERSIAN;
780
if ((c >= ORIYA_BEGIN) && (c <= ORIYA_END)) return NS_ORIYA;
781
if ((c >= OSMANYA_BEGIN) && (c <= OSMANYA_END)) return NS_OSMANYA;
782
if ((c >= PHOENICIAN_BEGIN) && (c <= PHOENICIAN_END)) return NS_PHOENICIAN;
783
if ((c >= TAMIL_BEGIN) && (c <= TAMIL_END)) return NS_TAMIL_GENERIC;
784
if ((c >= TELUGU_BEGIN) && (c <= TELUGU_END)) return NS_TELUGU;
785
if(c == TENGWAR_DECIMAL_MARKER) return NS_TENGWAR_DECIMAL;
786
if(c == TENGWAR_DUODECIMAL_MARKER) return NS_TENGWAR_DUODECIMAL;
787
if(c == TENGWAR_DUODECIMAL_LSD_MARKER) return NS_TENGWAR_DUODECIMAL;
788
if( (c == TENGWAR_DEC) || (c == TENGWAR_EL)) return NS_TENGWAR_DUODECIMAL;
789
if ((c >= THAI_BEGIN) && (c <= THAI_END)) return NS_THAI;
790
if ((c >= TIBETAN_BEGIN) && (c <= TIBETAN_END)) return NS_TIBETAN;
791
if ((c >= VERDURIAN_BEGIN) && (c <= VERDURIAN_END)) return NS_VERDURIAN;
792
if ((c >= XUCURI_LOWER_BEGIN) && (c <= XUCURI_LOWER_END)) return NS_XUCURI_LOWER;
793
if ((c >= XUCURI_UPPER_BEGIN) && (c <= XUCURI_UPPER_END)) return NS_XUCURI_UPPER;
794
if ((c == 0x0059) || (c == 0x0079)) {
795
if (ZeroCnt && (s-1 == str+1)) return NS_HEX;
805
( (c >= 0x2160) && (c <= 0x216F))) return NS_ROMAN_UPPER;
814
( (c >= 0x2170) && (c <= 0x217F))) return NS_ROMAN_LOWER;
824
(c == 0x280A)) return NS_COMMON_BRAILLE;
834
(c == 0x282A)) return NS_FRENCH_BRAILLE;
844
(c == 0x2814)) return NS_RUSSIAN_BRAILLE;
845
if ((c >= 0x31 ) && (c <= 0x39)) {WesternCnt++;continue;}
846
if (c == 0x0030) {ZeroCnt++;WesternCnt++;continue;}
848
if(ZeroCnt == len) return (NS_ALLZERO);
849
if(WesternCnt == len) return(NS_WESTERN_GENERIC);
853
/* String to Integer conversion functions */
855
static void ArabicToInt(mpz_t mpzResult, UTF32 *s) {
856
unsigned long CurrentValue;
861
uninum_err = NS_ERROR_OKAY;
864
while ( (c = *s++) != 0x0000) {
897
uninum_err = NS_ERROR_BADCHARACTER;
902
mpz_mul_ui(Result, Result, 10L);
903
mpz_add_ui(Result, Result, CurrentValue);
905
mpz_init_set(mpzResult, Result);
909
static void ArabicExtendedToInt(mpz_t mpzResult, UTF32 *s) {
910
unsigned long CurrentValue;
914
uninum_err = NS_ERROR_OKAY;
917
while ( (c = *s++) != 0x0000) {
950
uninum_err = NS_ERROR_BADCHARACTER;
955
mpz_mul_ui(Result, Result, 10L);
956
mpz_add_ui(Result, Result, CurrentValue);
958
mpz_init_set(mpzResult, Result);
962
static void ArabicAlphabeticToInt(mpz_t mpzResult, UTF32 *s) {
963
unsigned long CurrentValue;
967
uninum_err = NS_ERROR_OKAY;
970
while ( (c = *s++) != 0x0000) {
1054
CurrentValue = 1000;
1056
default: /* Error */
1057
uninum_err = NS_ERROR_BADCHARACTER;
1062
mpz_add_ui(Result, Result, CurrentValue);
1064
mpz_init_set(mpzResult, Result);
1069
static void AegeanToInt(mpz_t mpzResult, UTF32 *s) {
1070
unsigned long CurrentValue;
1074
uninum_err = NS_ERROR_OKAY;
1077
while ( (c = *s++) != 0x0000) {
1161
CurrentValue = 1000;
1164
CurrentValue = 2000;
1167
CurrentValue = 3000;
1170
CurrentValue = 4000;
1173
CurrentValue = 5000;
1176
CurrentValue = 6000;
1179
CurrentValue = 7000;
1182
CurrentValue = 8000;
1185
CurrentValue = 9000;
1188
CurrentValue = 10000;
1191
CurrentValue = 20000;
1194
CurrentValue = 30000;
1197
CurrentValue = 40000;
1200
CurrentValue = 50000;
1203
CurrentValue = 60000;
1206
CurrentValue = 70000;
1209
CurrentValue = 80000;
1212
CurrentValue = 90000;
1214
default: /* Error */
1215
uninum_err = NS_ERROR_BADCHARACTER;
1220
mpz_add_ui(Result, Result, CurrentValue);
1222
mpz_init_set(mpzResult, Result);
1227
static void ArmenianAlphabeticToInt(mpz_t mpzResult, UTF32 *s) {
1228
unsigned long CurrentValue;
1232
uninum_err = NS_ERROR_OKAY;
1235
while ( (c = *s++) != 0x0000) {
1319
CurrentValue = 1000;
1322
CurrentValue = 2000;
1325
CurrentValue = 3000;
1328
CurrentValue = 4000;
1331
CurrentValue = 5000;
1334
CurrentValue = 6000;
1337
CurrentValue = 7000;
1340
CurrentValue = 8000;
1343
CurrentValue = 9000;
1345
default: /* Error */
1346
uninum_err = NS_ERROR_BADCHARACTER;
1351
mpz_add_ui(Result, Result, CurrentValue);
1353
mpz_init_set(mpzResult, Result);
1358
static void BalineseToInt(mpz_t mpzResult, UTF32 *s) {
1359
unsigned long CurrentValue;
1363
uninum_err = NS_ERROR_OKAY;
1366
while ( (c = *s++) != 0x0000) {
1398
default: /* Error */
1399
uninum_err = NS_ERROR_BADCHARACTER;
1404
mpz_mul_ui(Result, Result, 10L);
1405
mpz_add_ui(Result, Result, CurrentValue);
1407
mpz_init_set(mpzResult, Result);
1411
static void BengaliToInt(mpz_t mpzResult, UTF32 *s) {
1412
unsigned long CurrentValue;
1416
uninum_err = NS_ERROR_OKAY;
1419
while ( (c = *s++) != 0x0000) {
1451
default: /* Error */
1452
uninum_err = NS_ERROR_BADCHARACTER;
1457
mpz_mul_ui(Result, Result, 10L);
1458
mpz_add_ui(Result, Result, CurrentValue);
1460
mpz_init_set(mpzResult, Result);
1464
static void BurmeseToInt(mpz_t mpzResult, UTF32 *s) {
1465
unsigned long CurrentValue;
1469
uninum_err = NS_ERROR_OKAY;
1472
while ( (c = *s++) != 0x0000) {
1504
default: /* Error */
1505
uninum_err = NS_ERROR_BADCHARACTER;
1510
mpz_mul_ui(Result, Result, 10L);
1511
mpz_add_ui(Result, Result, CurrentValue);
1513
mpz_init_set(mpzResult, Result);
1518
* Replaces variant forms of Chinese numbers with their standard traditional counterparts.
1519
* Returns a newly allocated string, or a null pointer on failure of storage allocation.
1522
static UTF32 *NormalizeChineseNumbers (UTF32 *s) {
1532
* It is safe to double the string length for temp space since no
1533
* substitution does more than replace one character with two.
1537
t = alloca (((2 * len) + 1) * sizeof (UTF32));
1539
t = malloc (((2 * len) + 1) * sizeof (UTF32));
1541
if (t == NULL) return (t);
1546
while( (c = *s++) != 0x0000) {
1548
case 0x96F6: /* Traditional/Legal */
1549
case 0xF9B2: /* Compatibility */
1550
*t++ =0x3007; /* 0 - Ideographic zero - also used with Suzhou numerals*/
1552
case 0x58F1: /* Legal */
1553
case 0x58F9: /* Legal */
1554
case 0x580C: /* Legal */
1555
case 0x4E48: /* Telephone number yao - traditional */
1556
case 0x5E7A: /* Telephone number yao - simplified */
1557
case 0x3021: /* Suzhou */
1558
*t++=0x4E00; /* 1 */
1560
case 0x5F0D: /* Legal simplified */
1561
case 0x5F10: /* Modern Japanese Legal simplified */
1562
case 0x5169: /* liang traditional */
1563
case 0x8CAE: /* Legal traditional */
1564
case 0x8CB3: /* Legal traditional */
1565
case 0x8D30: /* Legal traditional */
1566
case 0x4E24: /* liang simplified */
1567
case 0x3022: /* Suzhou */
1568
case 0xF978: /* liang - compatibility */
1569
*t++ = 0x4E8C; /* 2 */
1571
case 0x53C1: /* Legal simplified */
1572
case 0x53C2: /* Modern Japanese Legal */
1573
case 0x53C3: /* Obsolete Japanese Legal */
1574
case 0x53C4: /* Legal traditional */
1575
case 0x5F0E: /* Legal simplified */
1576
case 0x3023: /* Suzhou */
1577
*t++ = 0x4E09; /* 3 */
1579
case 0x4E96: /* Obsolete Japanese variant */
1580
case 0x8086: /* Legal */
1581
case 0x3024: /* Suzhou */
1582
*t++ = 0x56DB; /* 4 */
1584
case 0x4F0D: /* Legal */
1585
case 0x3025: /* Suzhou */
1586
*t++ = 0x4E94; /* 5 */
1588
case 0x9646: /* Legal */
1589
case 0x9678: /* Legal */
1590
case 0x3026: /* Suzhou */
1591
*t++ = 0x516D; /* 6 */
1593
case 0x67D2: /* Legal */
1594
case 0x6F06: /* Legal ??????*/
1595
case 0x3027: /* Suzhou */
1596
*t++ = 0x4E03; /* 7 */
1598
case 0x634C: /* Legal */
1599
case 0x3028: /* Suzhou */
1600
*t++ = 0x516B; /* 8 */
1602
case 0x7396: /* Legal */
1603
case 0x3029: /* Suzhou */
1604
*t++ = 0x4E5D; /* 9 */
1606
case 0x3038: /* Suzhou */
1607
case 0x4EC0: /* Legal simplified - disfavored */
1608
case 0x62FE: /* Legal traditional*/
1609
*t++ = 0x5341; /* 10 */
1611
case 0x5EFF: /* Portmanteau */
1612
case 0x3039: /* Suzhou portmanteau */
1614
*t++ = 0x5341; /* 20 */
1617
case 0x5345: /* Portmanteau */
1618
case 0x303A: /* Suzhou portmanteau */
1620
*t++ = 0x5341; /* 30 */
1623
case 0x534C: /* Portmanteau */
1625
*t++ = 0x5341; /* 40 */
1628
case 0x4F70: /* Legal */
1629
case 0x964C: /* Legal */
1630
*t++ = 0x767E; /* 100 */
1632
case 0x4EDF: /* Legal */
1633
case 0x9621: /* Legal */
1634
*t++ = 0x5343; /* 1000 */
1636
case 0x842C: /* Legal */
1637
*t++ = 0x4E07; /* 10,000 */
1639
case 0x4EBF: /* Simplified */
1640
*t++ = 0x5104; /* 100,000,000 */
1648
n = malloc ( (NewLen+1) * sizeof(UTF32));
1649
if (n == NULL) return (n);
1653
free( (void *) tmp);
1659
* The Chinese functions expect standard Chinese numbers in traditional characters.
1660
* Simplified characters and variants such as Suzhou numbers can be handled
1661
* by first calling NormalizeChineseNumbers on the input.
1664
static void ChinesePlace (mpz_t Result, UTF32 *s) {
1665
unsigned long CurrentValue;
1668
while ( (c = *s++) != 0x0000) {
1711
default: /* Error */
1712
uninum_err = NS_ERROR_BADCHARACTER;
1717
mpz_mul_ui(Result,Result,10L);
1718
mpz_add_ui(Result, Result, CurrentValue);
1723
static UTF32 ChineseBarriers [] = {
1724
0x5341, /* 0 - 10^1 */
1725
0x767E, /* 1 - 10^2 */
1726
0x5343, /* 2 - 10^3 */
1727
0x4E07, /* 3 - 10^4 */
1728
0x5104, /* 4 - 10^8 */
1729
0x5146, /* 5 - 10^12 */
1730
0x4EAC, /* 6 - 10^16 */
1731
0x5793, /* 7 - 10^20 */
1732
0x25771, /* 8 - 10^24 */
1733
0x7A63, /* 9 - 10^28 */
1734
0x6E9D, /* 10 - 10^32 */
1735
0x6F97, /* 11 - 10^36 */
1736
0x6B63, /* 12 - 10^40 */
1737
0x8F09, /* 13 - 10^44 */
1738
0x6975, /* 14 - 10^48 */
1742
* We can't just initialize an array of these values since most
1743
* of them are too large to fit into an unsigned long int,
1744
* some even an unsigned long long int.
1747
static void GetChineseBarrierValue (mpz_t Result,int which) {
1750
(void) mpz_set_str(Result,"10",10);break;
1752
(void) mpz_set_str(Result,"100",10);break;
1754
(void) mpz_set_str(Result,"1000",10);break;
1756
(void) mpz_set_str(Result,"10000",10);break;
1758
(void) mpz_set_str(Result,"100000000",10);break;
1760
(void) mpz_set_str(Result,"1000000000000",10);break;
1762
(void) mpz_set_str(Result,"10000000000000000",10);break;
1764
(void) mpz_set_str(Result,"100000000000000000000",10);break;
1766
(void) mpz_set_str(Result,"1000000000000000000000000",10);break;
1768
(void) mpz_set_str(Result,"10000000000000000000000000000",10);break;
1770
(void) mpz_set_str(Result,"100000000000000000000000000000000",10);break;
1772
(void) mpz_set_str(Result,"1000000000000000000000000000000000000",10);break;
1774
(void) mpz_set_str(Result,"10000000000000000000000000000000000000000",10);break;
1776
(void) mpz_set_str(Result,"100000000000000000000000000000000000000000000",10);break;
1778
(void) mpz_set_str(Result,"1000000000000000000000000000000000000000000000000",10);break;
1780
(void) mpz_set_str(Result,"0",10);
1784
static inline UTF32 *SeekChineseBarrier (UTF32 *s, int *ri) {
1786
int bi = (sizeof(ChineseBarriers)/sizeof(UTF32))-1;
1789
while (ptr == NULL && bi >= 0) {
1790
ptr = ucschr(s,ChineseBarriers[bi--]);
1796
static void ChineseToInt_MPZ(mpz_t ReturnValue, UTF32 *s) {
1805
mpz_init(BarrierValue);
1808
mpz_init(RightValue);
1810
ptr = SeekChineseBarrier(s,&i);
1812
ChinesePlace(ReturnValue,s);
1815
SavedBarrier = *ptr; *ptr = 0x0000;
1816
ChineseToInt_MPZ(mul,s);
1817
*ptr = SavedBarrier;
1818
if (UEQ(mul,0L)) mpz_set_ui(mul,1L); /* If mul = 0, mul <= 1 */
1820
GetChineseBarrierValue(BarrierValue,i);
1821
mpz_mul(Result,mul,BarrierValue);
1823
ChineseToInt_MPZ(RightValue,ptr+1);
1824
mpz_add(Result,Result,RightValue);
1825
mpz_set(ReturnValue,Result);
1827
mpz_clear(BarrierValue);
1829
mpz_clear(RightValue);
1834
static void ChineseToInt(mpz_t mpzResult, UTF32 *s) {
1838
uninum_err = NS_ERROR_OKAY;
1840
ChineseToInt_MPZ(Result,s);
1842
mpz_init_set(mpzResult, Result);
1847
static void ChineseCountingRodToInt(mpz_t mpzResult, UTF32 *s) {
1848
unsigned long CurrentValue;
1851
enum ct {EVEN,NEUTRAL,ODD};
1852
enum ct PreviousType = NEUTRAL;
1853
enum ct CurrentType = NEUTRAL;
1856
uninum_err = NS_ERROR_OKAY;
1859
while ( (c = *s++) != 0x0000) {
1863
CurrentType = NEUTRAL;
1937
default: /* Error */
1938
uninum_err = NS_ERROR_BADCHARACTER;
1943
if( (CurrentType == PreviousType) && (CurrentType != NEUTRAL)) {
1944
mpz_mul_ui(Result, Result, 100L);
1946
else mpz_mul_ui(Result, Result, 10L);
1947
mpz_add_ui(Result, Result, CurrentValue);
1948
PreviousType = CurrentType;
1950
mpz_init_set(mpzResult, Result);
1954
static void CyrillicAlphabeticToInt(mpz_t mpzResult, UTF32 *s) {
1955
unsigned long CurrentValue=0L;
1958
short ThousandP = 0;
1960
uninum_err = NS_ERROR_OKAY;
1963
while ((c = *s++) != 0x0000) {
1965
case CYRILLIC_TITLO: /* Skip - it just marks numbers*/
1967
case CYRILLIC_THOUSANDS_SIGN:
2026
if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;}
2030
if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;}
2034
if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;}
2038
if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;}
2042
if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;}
2046
if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;}
2050
if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;}
2052
case 0x0411: /* BE */
2054
if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;}
2056
case 0x0410: /* A */
2058
if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;}
2060
default: /* Error */
2061
uninum_err = NS_ERROR_BADCHARACTER;
2066
mpz_add_ui(Result,Result,CurrentValue);
2068
mpz_init_set(mpzResult, Result);
2072
static void CommonBrailleToInt(mpz_t mpzResult, UTF32 *s) {
2073
unsigned long CurrentValue;
2077
uninum_err = NS_ERROR_OKAY;
2080
if (*s == 0x283C) s++; /* Skip number designator */
2082
while ( (c = *s++) != 0x0000) {
2114
case 0x2802: /* Ignore Braille comma */
2116
default: /* Error */
2117
uninum_err = NS_ERROR_BADCHARACTER;
2122
mpz_mul_ui(Result, Result, 10L);
2123
mpz_add_ui(Result, Result, CurrentValue);
2125
mpz_init_set(mpzResult, Result);
2129
static void DevanagariToInt(mpz_t mpzResult, UTF32 *s) {
2130
unsigned long CurrentValue;
2134
uninum_err = NS_ERROR_OKAY;
2137
while ( (c = *s++) != 0x0000) {
2169
default: /* Error */
2170
uninum_err = NS_ERROR_BADCHARACTER;
2175
mpz_mul_ui(Result, Result, 10L);
2176
mpz_add_ui(Result, Result, CurrentValue);
2178
mpz_init_set(mpzResult, Result);
2182
/* Based on Unicode proposal - not yet final as of Unicode 5.0 */
2184
static void EgyptianToInt(mpz_t mpzResult, UTF32 *s) {
2185
unsigned long CurrentValue;
2189
uninum_err = NS_ERROR_OKAY;
2192
while ( (c = *s++) != 0x0000) {
2204
CurrentValue = 1000;
2207
CurrentValue = 10000;
2210
CurrentValue = 100000;
2213
CurrentValue = 1000000;
2215
default: /* Error */
2216
uninum_err = NS_ERROR_BADCHARACTER;
2221
mpz_add_ui(Result, Result, CurrentValue);
2223
mpz_init_set(mpzResult, Result);
2227
static void EthiopicToInt(mpz_t mpzResult, UTF32 *s) {
2228
mpz_init_set_ui(mpzResult,0L);
2229
uninum_err = NS_ERROR_NUMBER_SYSTEM_UNKNOWN;
2232
static void EwellicDecimalToInt(mpz_t mpzResult, UTF32 *s) {
2233
unsigned long CurrentValue;
2237
uninum_err = NS_ERROR_OKAY;
2240
while ( (c = *s++) != 0x0000) {
2282
default: /* Error */
2283
uninum_err = NS_ERROR_BADCHARACTER;
2288
mpz_mul_ui(Result, Result, 10L);
2289
mpz_add_ui(Result, Result, CurrentValue);
2291
mpz_init_set(mpzResult, Result);
2295
static void EwellicHexToInt(mpz_t mpzResult, UTF32 *s) {
2296
unsigned long CurrentValue;
2300
uninum_err = NS_ERROR_OKAY;
2303
if( *s == 0x0060) s++; /* Skip Ewellic hex marker */
2304
while ( (c = *s++) != 0x0000) {
2364
default: /* Error */
2365
uninum_err = NS_ERROR_BADCHARACTER;
2370
mpz_mul_ui(Result, Result, 16L);
2371
mpz_add_ui(Result, Result, CurrentValue);
2373
mpz_init_set(mpzResult, Result);
2377
static void FrenchBrailleToInt(mpz_t mpzResult, UTF32 *s) {
2378
unsigned long CurrentValue;
2382
uninum_err = NS_ERROR_OKAY;
2385
if (*s == 0x2820) s++; /* Skip number designator - D6 */
2387
while ( (c = *s++) != 0x0000) {
2419
case 0x2802: /* Ignore Braille comma */
2421
default: /* Error */
2422
uninum_err = NS_ERROR_BADCHARACTER;
2427
mpz_mul_ui(Result, Result, 10L);
2428
mpz_add_ui(Result, Result, CurrentValue);
2430
mpz_init_set(mpzResult, Result);
2434
static void GeorgianAlphabeticToInt(mpz_t mpzResult, UTF32 *s) {
2435
unsigned long CurrentValue;
2439
uninum_err = NS_ERROR_OKAY;
2442
while ( (c = *s++) != 0x0000) {
2582
CurrentValue = 1000;
2587
CurrentValue = 2000;
2592
CurrentValue = 3000;
2597
CurrentValue = 4000;
2602
CurrentValue = 5000;
2607
CurrentValue = 6000;
2612
CurrentValue = 7000;
2617
CurrentValue = 8000;
2622
CurrentValue = 9000;
2627
CurrentValue = 10000;
2629
default: /* Error */
2630
uninum_err = NS_ERROR_BADCHARACTER;
2635
mpz_add_ui(Result, Result, CurrentValue);
2637
mpz_init_set(mpzResult, Result);
2642
static void GlagoliticAlphabeticToInt(mpz_t mpzResult, UTF32 *s) {
2643
unsigned long CurrentValue;
2647
uninum_err = NS_ERROR_OKAY;
2650
while ( (c = *s++) != 0x0000) {
2652
case 0x2C00: /* AZU */
2655
case 0x2C01: /* BUKY */
2658
case 0x2C02: /* VEDE */
2661
case 0x2C03: /* GLAGOLY */
2664
case 0x2C04: /* DOBRO */
2667
case 0x2C05: /* YESTU */
2670
case 0x2C06: /* ZHIVETE */
2673
case 0x2C07: /* DZELO */
2676
case 0x2C08: /* ZEMLJA */
2679
case 0x2C09: /* IZHE */
2682
case 0x2C0B: /* I */
2685
case 0x2C0C: /* DJERVI */
2688
case 0x2C0D: /* KAKO */
2691
case 0x2C0E: /* LJUDIE */
2694
case 0x2C0F: /* MYSLITE */
2697
case 0x2C10: /* NASHI */
2700
case 0x2C11: /* ONU */
2703
case 0x2C12: /* POKOJI */
2706
case 0x2C13: /* RITSI */
2709
case 0x2C14: /* SLOVO */
2712
case 0x2C15: /* TVRIDO */
2715
case 0x2C16: /* UKU */
2718
case 0x2C17: /* FRITU */
2721
case 0x2C18: /* HERU */
2724
case 0x2C19: /* OTU */
2727
case 0x2C1B: /* SHTA */
2730
case 0x2C1C: /* TSI */
2733
case 0x2C1D: /* CHRIVI */
2734
CurrentValue = 1000;
2736
case 0x2C1E: /* SHA */
2737
CurrentValue = 2000;
2739
default: /* Error */
2740
uninum_err = NS_ERROR_BADCHARACTER;
2745
mpz_add_ui(Result, Result, CurrentValue);
2747
mpz_init_set(mpzResult, Result);
2752
static void GujaratiToInt(mpz_t mpzResult, UTF32 *s) {
2753
unsigned long CurrentValue;
2757
uninum_err = NS_ERROR_OKAY;
2760
while ( (c = *s++) != 0x0000) {
2792
default: /* Error */
2793
uninum_err = NS_ERROR_BADCHARACTER;
2798
mpz_mul_ui(Result, Result, 10L);
2799
mpz_add_ui(Result, Result, CurrentValue);
2801
mpz_init_set(mpzResult, Result);
2805
static void GreekAlphabeticToInt(mpz_t mpzResult, UTF32 *s) {
2806
unsigned long CurrentValue = 0;
2808
short LeftKeraiaP = 0;
2811
uninum_err = NS_ERROR_OKAY;
2814
while ( (c = *s++) != 0x0000) {
2822
if (LeftKeraiaP) CurrentValue *= 1000;
2828
if (LeftKeraiaP) CurrentValue *= 1000;
2834
if (LeftKeraiaP) CurrentValue *= 1000;
2840
if (LeftKeraiaP) CurrentValue *= 1000;
2846
if (LeftKeraiaP) CurrentValue *= 1000;
2849
case 0x03DA: /* Stigma */
2850
case 0x03DB: /* Small stigma */
2851
case 0x03DC: /* Digamma */
2852
case 0x03DD: /* Small digamma */
2854
if (LeftKeraiaP) CurrentValue *= 1000;
2860
if (LeftKeraiaP) CurrentValue *= 1000;
2866
if (LeftKeraiaP) CurrentValue *= 1000;
2872
if (LeftKeraiaP) CurrentValue *= 1000;
2915
case 0x03D8: /* Koppa */
2960
case 0x03E1: /* Small sanpi */
2961
case 0x03E0: /* Sanpi */
2965
case 0x0374: /* Right keraia - just marks numbers - no value */
2968
default: /* Error */
2969
uninum_err = NS_ERROR_BADCHARACTER;
2974
mpz_add_ui(Result, Result, CurrentValue);
2976
mpz_init_set(mpzResult, Result);
2981
static void GurmukhiToInt(mpz_t mpzResult, UTF32 *s) {
2982
unsigned long CurrentValue;
2986
uninum_err = NS_ERROR_OKAY;
2989
while ( (c = *s++) != 0x0000) {
3021
default: /* Error */
3022
uninum_err = NS_ERROR_BADCHARACTER;
3027
mpz_mul_ui(Result, Result, 10L);
3028
mpz_add_ui(Result, Result, CurrentValue);
3030
mpz_init_set(mpzResult, Result);
3034
static void HebrewToInt(mpz_t mpzResult, UTF32 *s) {
3035
unsigned long CurrentValue;
3038
short PrevCharGereshP;
3040
uninum_err = NS_ERROR_OKAY;
3043
while ( (c = *s++) != 0x0000) {
3044
PrevCharGereshP = 0;
3127
case 0x05F3: /* geresh */
3128
case 0x0027: /* apostrophe */
3129
mpz_mul_ui(Result,Result, 1000L);
3130
PrevCharGereshP = 1;
3132
case 0x05F4: /* gershayim */
3134
case 0x0020: /* space */
3136
default: /* Error */
3137
uninum_err = NS_ERROR_BADCHARACTER;
3142
if(!PrevCharGereshP) mpz_add_ui(Result,Result,CurrentValue);
3144
mpz_init_set(mpzResult, Result);
3148
static void KannadaToInt(mpz_t mpzResult, UTF32 *s) {
3149
unsigned long CurrentValue;
3153
uninum_err = NS_ERROR_OKAY;
3156
while ( (c = *s++) != 0x0000) {
3188
default: /* Error */
3189
uninum_err = NS_ERROR_BADCHARACTER;
3194
mpz_mul_ui(Result, Result, 10L);
3195
mpz_add_ui(Result, Result, CurrentValue);
3197
mpz_init_set(mpzResult, Result);
3201
#define KHAROSHTHI_THOUSAND 0x10A47
3202
#define KHAROSHTHI_HUNDRED 0x10A46
3203
#define KHAROSHTHI_FOUR 0x10A43
3204
#define KHAROSHTHI_THREE 0x10A42
3205
#define KHAROSHTHI_TWO 0x10A41
3206
#define KHAROSHTHI_ONE 0x10A40
3209
* A Kharoshthi number consists maximally of three components:
3210
* (a) a thousand sign and its coefficient, consisting of the numerals following it.
3211
* (b) a hundred sign and its coefficient, consisting of the numerals following it.
3212
* (c) an additive component, consisting of 1s, 2s, 3s, 4s, 10s, and 20s, at the beginning.
3215
static unsigned long KharoshthiToInt_NAMPZ(UTF32 *s) {
3216
unsigned long Total;
3217
unsigned long CurrentValue;
3226
wrkcpy = alloca(sizeof(UTF32) * (1 + ucslen(s)));
3228
wrkcpy = malloc(sizeof(UTF32) * (1 + ucslen(s)));
3230
if(wrkcpy) ucscpy(wrkcpy,s);
3232
uninum_err = NS_ERROR_OUTOFMEMORY;
3236
/* Handle thousands */
3237
thptr = ucsrchr(wrkcpy,KHAROSHTHI_THOUSAND);
3239
Total += (1000L * KharoshthiToInt_NAMPZ(thptr+1));
3243
/* Handle hundreds */
3244
huptr = ucsrchr(wrkcpy,KHAROSHTHI_HUNDRED);
3246
Total += (100L * KharoshthiToInt_NAMPZ(huptr+1));
3250
/* Handle the additive component - decades and units */
3252
while ((c = *p++) != 0x0000) {
3272
default: /* Error */
3273
uninum_err = NS_ERROR_BADCHARACTER;
3277
Total += CurrentValue;
3285
static void KharoshthiToInt(mpz_t mpzResult, UTF32 *s) {
3286
uninum_err = NS_ERROR_OKAY;
3288
mpz_init_set_ui(mpzResult,KharoshthiToInt_NAMPZ(s));
3292
static void KhmerToInt(mpz_t mpzResult, UTF32 *s) {
3293
unsigned long CurrentValue;
3297
uninum_err = NS_ERROR_OKAY;
3300
while ( (c = *s++) != 0x0000) {
3332
default: /* Error */
3333
uninum_err = NS_ERROR_BADCHARACTER;
3338
mpz_mul_ui(Result, Result, 10L);
3339
mpz_add_ui(Result, Result, CurrentValue);
3341
mpz_init_set(mpzResult, Result);
3345
static void KlingonToInt(mpz_t mpzResult, UTF32 *s) {
3346
unsigned long CurrentValue;
3350
uninum_err = NS_ERROR_OKAY;
3353
while ( (c = *s++) != 0x0000) {
3385
default: /* Error */
3386
uninum_err = NS_ERROR_BADCHARACTER;
3391
mpz_mul_ui(Result, Result, 10L);
3392
mpz_add_ui(Result, Result, CurrentValue);
3394
mpz_init_set(mpzResult, Result);
3398
static void LaoToInt(mpz_t mpzResult, UTF32 *s) {
3399
unsigned long CurrentValue;
3403
uninum_err = NS_ERROR_OKAY;
3406
while ( (c = *s++) != 0x0000) {
3438
default: /* Error */
3439
uninum_err = NS_ERROR_BADCHARACTER;
3444
mpz_mul_ui(Result, Result, 10L);
3445
mpz_add_ui(Result, Result, CurrentValue);
3447
mpz_init_set(mpzResult, Result);
3451
static void LimbuToInt(mpz_t mpzResult, UTF32 *s) {
3452
unsigned long CurrentValue;
3456
uninum_err = NS_ERROR_OKAY;
3459
while ( (c = *s++) != 0x0000) {
3491
default: /* Error */
3492
uninum_err = NS_ERROR_BADCHARACTER;
3497
mpz_mul_ui(Result, Result, 10L);
3498
mpz_add_ui(Result, Result, CurrentValue);
3500
mpz_init_set(mpzResult, Result);
3504
static void MalayalamToInt(mpz_t mpzResult, UTF32 *s) {
3505
unsigned long CurrentValue;
3509
uninum_err = NS_ERROR_OKAY;
3512
while ( (c = *s++) != 0x0000) {
3544
default: /* Error */
3545
uninum_err = NS_ERROR_BADCHARACTER;
3550
mpz_mul_ui(Result, Result, 10L);
3551
mpz_add_ui(Result, Result, CurrentValue);
3553
mpz_init_set(mpzResult, Result);
3557
/* It may be desirable to reduce whitespace to a single space first */
3559
* Mayan is not yet encoded so I've made up codepoints in the PUA
3560
* Expose this subroutine once the encoding is settled.
3563
static void MayanToInt(mpz_t mpzResult, UTF32 *s) {
3564
unsigned long CurrentValue;
3569
uninum_err = NS_ERROR_OKAY;
3572
while ((c = *s++) != 0x0000) {
3574
case 0xFFC0: /* 0 - shell */
3576
case 0xFFC1: /* 1 - dot */
3579
case 0xFFC2: /* 5 - bar */
3583
if (++GroupCnt == 3) mpz_mul_ui(Result,Result,18L);
3584
else mpz_mul_ui(Result,Result,20L);
3586
default: /* Error */
3587
uninum_err = NS_ERROR_BADCHARACTER;
3592
mpz_add_ui(Result, Result, CurrentValue);
3594
mpz_init_set(mpzResult, Result);
3598
static void MongolianToInt(mpz_t mpzResult, UTF32 *s) {
3599
unsigned long CurrentValue;
3603
uninum_err = NS_ERROR_OKAY;
3606
while ( (c = *s++) != 0x0000) {
3638
default: /* Error */
3639
uninum_err = NS_ERROR_BADCHARACTER;
3644
mpz_mul_ui(Result, Result, 10L);
3645
mpz_add_ui(Result, Result, CurrentValue);
3647
mpz_init_set(mpzResult, Result);
3651
static void NewTaiLueToInt(mpz_t mpzResult, UTF32 *s) {
3652
unsigned long CurrentValue;
3656
uninum_err = NS_ERROR_OKAY;
3659
while ( (c = *s++) != 0x0000) {
3691
default: /* Error */
3692
uninum_err = NS_ERROR_BADCHARACTER;
3697
mpz_mul_ui(Result, Result, 10L);
3698
mpz_add_ui(Result, Result, CurrentValue);
3700
mpz_init_set(mpzResult, Result);
3704
static void NkoToInt(mpz_t mpzResult, UTF32 *s) {
3705
unsigned long CurrentValue;
3709
uninum_err = NS_ERROR_OKAY;
3712
while ( (c = *s++) != 0x0000) {
3744
default: /* Error */
3745
uninum_err = NS_ERROR_BADCHARACTER;
3750
mpz_mul_ui(Result, Result, 10L);
3751
mpz_add_ui(Result, Result, CurrentValue);
3753
mpz_init_set(mpzResult, Result);
3757
static void OldItalicToInt(mpz_t mpzResult, UTF32 *s) {
3758
unsigned long CurrentValue;
3762
uninum_err = NS_ERROR_OKAY;
3765
while ((c = *s++) != 0x0000) {
3767
case 0x10320: /* 1 */
3770
case 0x10321: /* 5 */
3773
case 0x10322: /* 10 */
3776
case 0x10323: /* 50 */
3779
default: /* Error */
3780
uninum_err = NS_ERROR_BADCHARACTER;
3785
mpz_add_ui(Result,Result,CurrentValue);
3787
mpz_init_set(mpzResult, Result);
3791
static void OldPersianToInt(mpz_t mpzResult, UTF32 *s) {
3792
unsigned long CurrentValue;
3796
uninum_err = NS_ERROR_OKAY;
3799
while ((c = *s++) != 0x0000) {
3801
case 0x103D1: /* 1 */
3804
case 0x103D2: /* 2 */
3807
case 0x103D3: /* 10 */
3810
case 0x103D4: /* 20 */
3813
case 0x103D5: /* 100 */
3816
default: /* Error */
3817
uninum_err = NS_ERROR_BADCHARACTER;
3822
mpz_add_ui(Result, Result, CurrentValue);
3824
mpz_init_set(mpzResult, Result);
3829
static void OriyaToInt(mpz_t mpzResult, UTF32 *s) {
3830
unsigned long CurrentValue;
3834
uninum_err = NS_ERROR_OKAY;
3837
while ( (c = *s++) != 0x0000) {
3869
default: /* Error */
3870
uninum_err = NS_ERROR_BADCHARACTER;
3875
mpz_mul_ui(Result, Result, 10L);
3876
mpz_add_ui(Result, Result, CurrentValue);
3878
mpz_init_set(mpzResult, Result);
3882
static void OsmanyaToInt(mpz_t mpzResult, UTF32 *s) {
3883
unsigned long CurrentValue;
3887
uninum_err = NS_ERROR_OKAY;
3890
while ( (c = *s++) != 0x0000) {
3922
default: /* Error */
3923
uninum_err = NS_ERROR_BADCHARACTER;
3928
mpz_mul_ui(Result, Result, 10L);
3929
mpz_add_ui(Result, Result, CurrentValue);
3931
mpz_init_set(mpzResult, Result);
3935
static void PhoenicianToInt(mpz_t mpzResult, UTF32 *s) {
3936
unsigned long CurrentValue;
3940
uninum_err = NS_ERROR_OKAY;
3943
while ((c = *s++) != 0x0000) {
3945
case 0x10916: /* 1 */
3948
case 0x10917: /* 10 */
3951
case 0x10918: /* 20 */
3954
case 0x10919: /* 100 */
3957
default: /* Error */
3958
uninum_err = NS_ERROR_BADCHARACTER;
3963
mpz_add_ui(Result, Result, CurrentValue);
3966
mpz_init_set(mpzResult, Result);
3970
static void RomanToInt(mpz_t mpzResult, UTF32 *s) {
3971
unsigned long CurrentValue;
3972
unsigned long PreviousValue = 0L;
3980
uninum_err = NS_ERROR_OKAY;
3984
while ( (c = *p++) != 0x0000) {
4026
CurrentValue = 1000;
4065
CurrentValue = 5000;
4068
CurrentValue = 10000;
4073
PreviousValue *= 1000L;
4075
case 0x2183: /* Reverse C */
4078
if(PreviousValue != 1) {uninum_err = NS_ERROR_ILLFORMED;mpz_clear(Result);return;}
4081
t = p-3; /* Point at character before I/i */
4082
while ((t >= s) && ( (*t == 'C') || (*t == 'c') || (*t == 0x216D) || (*t == 0x217D) )) {
4085
mpz_sub_ui(Result,Result,100 * Ccnt);
4086
t = p; /* Point at character following first reverse C */
4087
while ((*t == 0x2183) || (*t == 0x2184)) {Rcnt++; t++;}
4088
if (Rcnt < Ccnt) {uninum_err = NS_ERROR_ILLFORMED;mpz_clear(Result);return;}
4089
if(Ccnt > 0) CurrentValue = ipow(10,Ccnt+2);
4090
if(Rcnt != Ccnt) CurrentValue += (5 * ipow(10,Rcnt-Ccnt+1));
4093
default: /* Error */
4094
uninum_err = NS_ERROR_BADCHARACTER;
4099
if (PreviousValue >= CurrentValue) mpz_add_ui(Result,Result,PreviousValue);
4100
else mpz_sub_ui(Result,Result,PreviousValue);
4101
PreviousValue = CurrentValue;
4103
if (PreviousValue >= CurrentValue) mpz_add_ui(Result,Result,PreviousValue);
4104
else mpz_sub_ui(Result,Result,PreviousValue);
4106
mpz_init_set(mpzResult, Result);
4110
static void RussianBrailleToInt(mpz_t mpzResult, UTF32 *s) {
4111
unsigned long CurrentValue;
4115
uninum_err = NS_ERROR_OKAY;
4118
while ( (c = *s++) != 0x0000) {
4150
default: /* Error */
4151
uninum_err = NS_ERROR_BADCHARACTER;
4156
mpz_mul_ui(Result, Result, 10L);
4157
mpz_add_ui(Result, Result, CurrentValue);
4159
mpz_init_set(mpzResult, Result);
4164
* For mysterious reasons the Sinhala numerals are omitted from Unicode 5.0,
4165
* though the range for which they were proposed is left empty. This
4166
* assumes the proposed range.
4169
static void SinhalaToInt(mpz_t mpzResult, UTF32 *s) {
4170
unsigned long CurrentValue;
4174
uninum_err = NS_ERROR_OKAY;
4177
while ((c = *s++) != 0x0000) {
4237
CurrentValue = 1000;
4239
default: /* Error */
4240
uninum_err = NS_ERROR_BADCHARACTER;
4245
mpz_add_ui(Result, Result, CurrentValue);
4247
mpz_init_set(mpzResult, Result);
4251
static void TamilPlace (mpz_t Result, UTF32 *s) {
4252
unsigned long CurrentValue;
4255
while ( (c = *s++) != 0x0000) {
4287
default: /* Error */
4288
uninum_err = NS_ERROR_BADCHARACTER;
4293
mpz_mul_ui(Result,Result,10L);
4294
mpz_add_ui(Result, Result, CurrentValue);
4299
static UTF32 TamilBarriers [] = {
4305
static unsigned long TamilBarrierValue [] = {
4311
static inline UTF32 *SeekTamilBarrier (UTF32 *s, int *ri) {
4313
int bi = (sizeof(TamilBarriers)/sizeof(UTF32))-1;
4316
while (ptr == NULL && bi >= 0) {
4317
ptr = ucschr(s,TamilBarriers[bi--]);
4324
static void TamilToInt_MPZ(mpz_t ReturnValue, UTF32 *s) {
4332
ptr = SeekTamilBarrier(s,&i);
4334
TamilPlace(ReturnValue,s);
4340
mpz_init(RightValue);
4342
SavedBarrier = *ptr; *ptr = 0x0000;
4343
TamilToInt_MPZ(mul,s);
4344
*ptr = SavedBarrier;
4345
if (UEQ(mul,0L)) mpz_set_ui(mul,1L);
4347
mpz_mul_ui(Result,mul,TamilBarrierValue[i]);
4348
TamilToInt_MPZ(RightValue,ptr+1);
4349
mpz_add(Result,Result,RightValue);
4350
mpz_set(ReturnValue,Result);
4352
mpz_clear(RightValue);
4357
static void TamilToInt(mpz_t mpzResult, UTF32 *s) {
4360
uninum_err = NS_ERROR_OKAY;
4362
TamilToInt_MPZ(Result,s);
4363
mpz_init_set(mpzResult, Result);
4367
static void TeluguToInt(mpz_t mpzResult, UTF32 *s) {
4368
unsigned long CurrentValue;
4372
uninum_err = NS_ERROR_OKAY;
4375
while ( (c = *s++) != 0x0000) {
4407
default: /* Error */
4408
uninum_err = NS_ERROR_BADCHARACTER;
4413
mpz_mul_ui(Result, Result, 10L);
4414
mpz_add_ui(Result, Result, CurrentValue);
4416
mpz_init_set(mpzResult, Result);
4420
static void TengwarToInt(mpz_t mpzResult, UTF32 *s) {
4421
unsigned long CurrentValue = 0L;
4427
uninum_err = NS_ERROR_OKAY;
4429
if(ucslen(s) % 2 != 0) {
4430
uninum_err = NS_ERROR_ILLFORMED;
4434
if(s[1] == TENGWAR_DUODECIMAL_LSD_MARKER) Base = 12;
4435
else if(s[1] == TENGWAR_DUODECIMAL_MARKER) Base = 12;
4436
else if(s[1] == TENGWAR_DECIMAL_MARKER) Base = 10;
4438
uninum_err = NS_ERROR_ILLFORMED;
4445
while ((c = *p++) != 0L) {
4447
case TENGWAR_DECIMAL_MARKER:
4448
case TENGWAR_DUODECIMAL_MARKER:
4449
case TENGWAR_DUODECIMAL_LSD_MARKER:
4487
default: /* Error */
4488
uninum_err = NS_ERROR_BADCHARACTER;
4493
mpz_mul_ui(Result, Result, Base);
4494
mpz_add_ui(Result, Result, CurrentValue);
4496
mpz_init_set(mpzResult, Result);
4500
static void ThaiToInt(mpz_t mpzResult, UTF32 *s) {
4501
unsigned long CurrentValue;
4505
uninum_err = NS_ERROR_OKAY;
4508
while ( (c = *s++) != 0x0000) {
4540
default: /* Error */
4541
uninum_err = NS_ERROR_BADCHARACTER;
4546
mpz_mul_ui(Result, Result, 10L);
4547
mpz_add_ui(Result, Result, CurrentValue);
4549
mpz_init_set(mpzResult, Result);
4553
static void TibetanToInt(mpz_t mpzResult, UTF32 *s) {
4554
unsigned long CurrentValue;
4558
uninum_err = NS_ERROR_OKAY;
4561
while ( (c = *s++) != 0x0000) {
4593
default: /* Error */
4594
uninum_err = NS_ERROR_BADCHARACTER;
4599
mpz_mul_ui(Result, Result, 10L);
4600
mpz_add_ui(Result, Result, CurrentValue);
4602
mpz_init_set(mpzResult, Result);
4606
static void VerdurianToInt(mpz_t mpzResult, UTF32 *s) {
4607
unsigned long CurrentValue;
4611
uninum_err = NS_ERROR_OKAY;
4614
while ( (c = *s++) != 0L) {
4646
default: /* Error */
4647
uninum_err = NS_ERROR_BADCHARACTER;
4652
mpz_mul_ui(Result, Result, 10L);
4653
mpz_add_ui(Result, Result, CurrentValue);
4655
mpz_init_set(mpzResult, Result);
4659
void WesternGeneralToInt(mpz_t mpzResult, UTF32 *s, int Base) {
4660
unsigned long CurrentValue;
4665
uninum_err = NS_ERROR_OKAY;
4666
if ((Base > 36) || (Base < 1)) {
4667
uninum_err = NS_ERROR_BADBASE;
4671
mpz_init_set_ui(mpzResult, ucslen(s));
4675
b = (unsigned long) Base;
4677
while ( (c = *s++) != 0L) {
4678
if ( (c >= 0x0030) && (c <= 0x0039)) CurrentValue = c - 0x0030;
4679
else if ( (c >= 0x0041) && (c <= 0x005B)) CurrentValue = c - 0x0037;
4680
else if ( (c >= 0x0061) && (c <= 0x007B)) CurrentValue = c - 0x0057;
4682
uninum_err = NS_ERROR_BADCHARACTER;
4687
if (CurrentValue >= b) {
4688
uninum_err = NS_ERROR_NOTCONSISTENTWITHBASE;
4692
mpz_mul_ui(Result, Result, b);
4693
mpz_add_ui(Result, Result, CurrentValue);
4695
mpz_init_set(mpzResult, Result);
4699
static void SetRvalZero(union ns_rval *rvalp, short ReturnType) {
4700
switch(ReturnType) {
4704
case NS_TYPE_STRING:
4705
rvalp->s = malloc(2 *sizeof(char));
4710
mpz_set_ui(rvalp->m,0L);
4715
void StringToInt(union ns_rval *rvalp, UTF32 *s, short ReturnType,int NumberSystem) {
4717
uninum_err = NS_ERROR_OKAY;
4718
if ((NS_ALL == NumberSystem) || (NS_ANY == NumberSystem)) NumberSystem = GuessNumberSystem(s);
4720
wcStripSeparators(s);
4721
switch (NumberSystem)
4724
AegeanToInt(Result,s);
4726
case NS_ARABIC_WESTERN:
4727
ArabicToInt(Result,s);
4729
case NS_PERSO_ARABIC:
4730
ArabicExtendedToInt(Result,s);
4732
case NS_ARABIC_ALPHABETIC:
4733
ArabicAlphabeticToInt(Result,s);
4735
case NS_ARMENIAN_ALPHABETIC:
4736
ArmenianAlphabeticToInt(Result,s);
4739
BalineseToInt(Result,s);
4742
BengaliToInt(Result,s);
4745
BurmeseToInt(Result,s);
4747
case NS_CHINESE_GENERIC:
4748
case NS_CHINESE_REGULAR_SIMPLIFIED:
4749
case NS_CHINESE_REGULAR_TRADITIONAL:
4750
case NS_CHINESE_LEGAL_TRADITIONAL:
4751
case NS_CHINESE_LEGAL_SIMPLIFIED:
4752
case NS_CHINESE_MANDARIN_REGULAR_TRADITIONAL:
4753
case NS_CHINESE_MANDARIN_REGULAR_SIMPLIFIED:
4754
case NS_CHINESE_MANDARIN_LEGAL_TRADITIONAL:
4755
case NS_CHINESE_MANDARIN_LEGAL_SIMPLIFIED:
4756
case NS_CHINESE_JAPANESE_REGULAR_SIMPLIFIED:
4757
case NS_CHINESE_JAPANESE_REGULAR_TRADITIONAL:
4758
case NS_CHINESE_JAPANESE_LEGAL_SIMPLIFIED:
4759
case NS_CHINESE_JAPANESE_LEGAL_TRADITIONAL:
4760
case NS_CHINESE_JAPANESE_WESTERN_MIX:
4761
case NS_CHINESE_REGULAR_PLACE:
4762
case NS_CHINESE_SUZHOU:
4763
ChineseToInt(Result,NormalizeChineseNumbers(s));
4765
case NS_CHINESE_COUNTING_ROD_GENERIC:
4766
case NS_CHINESE_COUNTING_ROD_EARLY_WITH_ZERO:
4767
case NS_CHINESE_COUNTING_ROD_LATE_WITH_ZERO:
4768
case NS_CHINESE_COUNTING_ROD_EARLY_WITHOUT_ZERO:
4769
case NS_CHINESE_COUNTING_ROD_LATE_WITHOUT_ZERO:
4770
ChineseCountingRodToInt(Result,s);
4772
case NS_COMMON_BRAILLE:
4773
CommonBrailleToInt(Result,s);
4775
case NS_CYRILLIC_ALPHABETIC:
4776
CyrillicAlphabeticToInt(Result,s);
4779
DevanagariToInt(Result,s);
4782
EgyptianToInt(Result,s);
4785
EthiopicToInt(Result,s);
4787
case NS_EWELLIC_DECIMAL:
4788
EwellicDecimalToInt(Result,s);
4790
case NS_EWELLIC_HEX:
4791
EwellicHexToInt(Result,s);
4793
case NS_FRENCH_BRAILLE:
4794
FrenchBrailleToInt(Result,s);
4797
case NS_XUCURI_LOWER:
4798
case NS_XUCURI_UPPER:
4799
GeorgianAlphabeticToInt(Result,s);
4801
case NS_GLAGOLITIC_ALPHABETIC:
4802
GlagoliticAlphabeticToInt(Result,s);
4804
case NS_GREEK_ALPHABETIC_UPPER:
4805
case NS_GREEK_ALPHABETIC_LOWER:
4806
GreekAlphabeticToInt(Result,s);
4809
GujaratiToInt(Result,s);
4812
GurmukhiToInt(Result,s);
4814
case NS_HEBREW_GENERIC:
4815
case NS_HEBREW_EARLY:
4816
case NS_HEBREW_LATE:
4817
HebrewToInt(Result,s);
4822
WesternGeneralToInt(Result,s+2,16); /* s+2 to skip the initial 0x */
4825
KannadaToInt(Result,s);
4828
KharoshthiToInt(Result,s);
4831
KhmerToInt(Result,s);
4834
KlingonToInt(Result,s);
4840
LimbuToInt(Result,s);
4843
MalayalamToInt(Result,s);
4846
MayanToInt(Result,s);
4849
MongolianToInt(Result,s);
4851
case NS_NEW_TAI_LUE:
4852
NewTaiLueToInt(Result,s);
4858
OldItalicToInt(Result,s);
4860
case NS_OLD_PERSIAN:
4861
OldPersianToInt(Result,s);
4864
OriyaToInt(Result,s);
4867
OsmanyaToInt(Result,s);
4870
PhoenicianToInt(Result,s);
4872
case NS_ROMAN_GENERIC:
4873
case NS_ROMAN_UPPER:
4874
case NS_ROMAN_LOWER:
4875
RomanToInt(Result,s);
4877
case NS_RUSSIAN_BRAILLE:
4878
RussianBrailleToInt(Result,s);
4881
SinhalaToInt(Result,s);
4883
case NS_TAMIL_GENERIC:
4884
case NS_TAMIL_PLACE:
4885
case NS_TAMIL_TRADITIONAL:
4886
TamilToInt(Result,s);
4889
TeluguToInt(Result,s);
4891
case NS_TENGWAR_DECIMAL:
4892
case NS_TENGWAR_DUODECIMAL:
4893
TengwarToInt(Result,s);
4896
ThaiToInt(Result,s);
4899
TibetanToInt(Result,s);
4902
VerdurianToInt(Result,s);
4904
case NS_WESTERN_GENERIC:
4905
case NS_WESTERN_LOWER:
4906
case NS_WESTERN_UPPER:
4907
WesternGeneralToInt(Result,s,Uninum_Input_Base);
4910
uninum_err = NS_ERROR_NUMBER_SYSTEM_UNKNOWN;
4912
} /* End of switch */
4915
if (ReturnType == NS_TYPE_STRING) {
4916
rvalp->s = malloc(sizeof(char) * (1 + mpz_sizeinbase(Result,10)));
4918
uninum_err = NS_ERROR_OUTOFMEMORY;
4921
(void) mpz_get_str(rvalp->s,10,Result);
4923
else if (ReturnType == NS_TYPE_ULONG) {
4924
if(!mpz_fits_ulong_p(Result)) uninum_err = NS_ERROR_DOESNOTFIT;
4925
else rvalp->u = mpz_get_ui(Result);
4927
else mpz_set(rvalp->m,Result);
4930
if(uninum_err) SetRvalZero(rvalp,ReturnType);
4935
/* Code for generating strings from integers */
4938
* PlaceIntToString assumes that the number system has the following properties:
4939
* (a) it is place-based;
4940
* (b) its digits are contiguous and in ascending order in Unicode;
4943
#define ARABIC_ZERO 0x0660
4944
#define BALINESE_ZERO 0x1B50
4945
#define BENGALI_ZERO 0x09E6
4946
#define BURMESE_ZERO 0x1040
4947
#define CHINESE_COUNTING_ROD_EARLY_ZERO 0x1D368
4948
#define CHINESE_COUNTING_ROD_LATE_ZERO 0x1D35F
4949
#define DEVANAGARI_ZERO 0x0966
4950
#define EWELLIC_ZERO 0xE6C0
4951
#define GUJARATI_ZERO 0x0AE6
4952
#define GURMUKHI_ZERO 0x0A66
4953
#define KANNADA_ZERO 0x0CE6
4954
#define KHMER_ZERO 0x17E0
4955
#define KLINGON_ZERO 0xF8F0
4956
#define LAO_ZERO 0x0ED0
4957
#define LIMBU_ZERO 0x1946
4958
#define MALAYALAM_ZERO 0x0D66
4959
#define MONGOLIAN_ZERO 0x1810
4960
#define NEW_TAI_LUE_ZERO 0x19D0
4961
#define NKO_ZERO 0x07C0
4962
#define ORIYA_ZERO 0x0B66
4963
#define OSMANYA_ZERO 0x104A0
4964
#define PERSO_ARABIC_ZERO 0x06F0
4965
#define ROMAN_ZERO 0x0030
4966
#define SUZHOU_ZERO 0x3020
4967
#define TAMIL_ZERO 0x0BE6
4968
#define TELUGU_ZERO 0x0C66
4969
#define THAI_ZERO 0x0E50
4970
#define TIBETAN_ZERO 0x0F20
4971
#define VERDURIAN_ZERO 0xE260
4972
#define WESTERN_ZERO 0x0030
4975
PlaceIntToString(mpz_t n, UTF32 ZeroCode, unsigned int Base) {
4976
int Digits; /* Number of digits in string */
4984
unsigned long int temp;
4992
Digits = mpz_sizeinbase(k,Base);
4993
new = malloc((Digits + 1) * sizeof(UTF32));
4995
uninum_err = NS_ERROR_OUTOFMEMORY;
5003
mpz_tdiv_qr_ui(q,r,k,Base);
5004
*s++ = (ZeroCode + mpz_get_ui(r));
5006
} while (UGT(q,0L));
5008
*s = 0x0000; /* Null terminate string */
5009
s--; /* Point s at last non-null char */
5011
mpz_clear(d);mpz_clear(k);mpz_clear(q);mpz_clear(r);
5014
* Now we reverse the string. When we begin, p points at the first
5015
* character of the string, s at the last non-null character.
5027
PlaceNonContiguousIntToString(mpz_t n, UTF32 **DigitList, int Base){
5028
int Digits; /* Number of digits in string */
5035
unsigned long int temp;
5040
Digits = mpz_sizeinbase(k,Base);
5041
new = malloc((Digits + 1) * sizeof(UTF32));
5043
uninum_err = NS_ERROR_OUTOFMEMORY;
5054
mpz_tdiv_qr_ui(q,r,k,Base);
5055
*s++ = DigitList[mpz_get_ui(r)][0];
5057
} while (UGT(q,0L));
5059
*s = 0x0000; /* Null terminate string */
5060
s--; /* Point s at last non-null char */
5062
mpz_clear(k);mpz_clear(q);mpz_clear(r);
5065
* Now we reverse the string. When we begin, p points at the first
5066
* character of the string, s at the last non-null character.
5077
UTF32 tengd0[2] = {0xE030,0x0000};
5078
UTF32 tengd1[2] = {0xE033,0x0000};
5079
UTF32 tengd2[2] = {0xE062,0x0000};
5080
UTF32 tengd3[2] = {0xE063,0x0000};
5081
UTF32 tengd4[2] = {0xE064,0x0000};
5082
UTF32 tengd5[2] = {0xE065,0x0000};
5083
UTF32 tengd6[2] = {0xE066,0x0000};
5084
UTF32 tengd7[2] = {0xE067,0x0000};
5085
UTF32 tengd8[2] = {0xE068,0x0000};
5086
UTF32 tengd9[2] = {0xE069,0x0000};
5087
UTF32 tengd10[2] = {0xE06A,0x0000};
5088
UTF32 tengd11[2] = {0xE06B,0x0000};
5090
UTF32 *TengwarDigits[]={
5091
tengd0, tengd1, tengd2, tengd3, tengd4, tengd5,
5092
tengd6, tengd7, tengd8, tengd9, tengd10, tengd11
5097
TengwarToString(mpz_t n,int Base){
5098
int Digits; /* Number of digits in string */
5108
Digits = mpz_sizeinbase(k,Base);
5109
new = malloc(((2 * Digits) + 1) * sizeof(UTF32));
5111
uninum_err = NS_ERROR_OUTOFMEMORY;
5116
if(Base == 12) BaseMarker = TENGWAR_DUODECIMAL_MARKER;
5117
else BaseMarker = TENGWAR_DECIMAL_MARKER;
5125
mpz_tdiv_qr_ui(q,r,k,Base);
5126
*s++ = TengwarDigits[mpz_get_ui(r)][0];
5129
} while (UGT(q,0L));
5130
*s = 0L; /* Null terminate string */
5131
if(Base == 12) new[1] = TENGWAR_DUODECIMAL_LSD_MARKER;
5133
mpz_clear(k);mpz_clear(q);mpz_clear(r);
5138
struct vcpair ArabicAlphabeticData[]={
5171
struct vcpair AegeanData[]={
5221
struct vcpair ArmenianData[]={
5262
struct vcpair CyrillicData[]={
5294
struct vcpair EgyptianData[]={
5306
struct vcpair EthiopicData[]={
5307
{9999999,0xFFDF}, /* Dummy - real max is in subroutine */
5329
struct vcpair GlagoliticData[]={
5363
struct vcpair GreekUpperData[]={
5395
struct vcpair GreekLowerData[]={
5427
struct vcpair HebrewData[]={
5459
struct vcpair MxedruliData[]={
5501
struct vcpair PhoenicianData[]={
5510
struct vcpair OldItalicData[]={
5519
struct vcpair OldPersianData[]={
5529
struct vcpair SinhalaData[]={
5554
struct vcpair XucuriLowerData[]={
5596
struct vcpair XucuriUpperData[]={
5639
* This is based on the maximum for Egyptian. If
5640
* other systems are added, it may need to be
5643
#define ADDITIVE_CHARS_NEEDED 54
5645
AdditiveIntToString(mpz_t k, struct vcpair *data) {
5651
UTF32 tmp [ADDITIVE_CHARS_NEEDED+1];
5661
uninum_err = NS_ERROR_RANGE;
5666
uninum_err = NS_ERROR_NOZERO;
5671
mpz_init_set(Residue,k);
5673
p++; /* Skip over maximum */
5675
mpz_tdiv_q_ui(Repeat,Residue,p->v);
5676
iRepeat = mpz_get_ui(Repeat);
5677
for (i=0;i < iRepeat;i++) tmp[oi++] = p->c;
5678
mpz_submul_ui(Residue,Repeat,p->v);
5686
Digits = ucslen(tmp);
5687
new = malloc((Digits + 1) * sizeof(UTF32));
5689
uninum_err = NS_ERROR_OUTOFMEMORY;
5692
return(ucscpy(new,tmp));
5695
#define CYRILLIC_ONE 0x0410
5696
#define CYRILLIC_NINE 0x0472
5697
#define CYRILLIC_TEN 0x0406
5698
#define CYRILLIC_THOUSANDS_SIGN 0x0482
5699
#define CYRILLIC_TITLO 0x0483
5701
#define CYRILLIC_CHARS_NEEDED 6
5703
CyrillicAlphabeticIntToString(mpz_t n) {
5708
unsigned long Residue;
5709
unsigned long Thousands;
5711
UTF32 tmp [CYRILLIC_CHARS_NEEDED+1];
5715
/* Given the limited range, we'd might as well use ordinary arithmetic */
5720
uninum_err = NS_ERROR_RANGE;
5725
uninum_err = NS_ERROR_NOZERO;
5730
p++; /* Skip maximum */
5732
Thousands = k/1000L;
5734
tmp[oi++] = CYRILLIC_THOUSANDS_SIGN;
5735
tmp[oi++] = (CyrillicData + 27 - Thousands)->c;
5736
Residue -= (Thousands * 1000L);
5740
Repeat = Residue/p->v;
5741
for (i=0;i < Repeat;i++) tmp[oi++] = p->c;
5742
Residue -= (Repeat * p->v);
5745
// tmp[oi++] = CYRILLIC_TITLO;
5748
/* Reorder 11-19 to spoken order */
5749
UTF32 c1 = tmp[oi-2];
5750
UTF32 c2 = tmp[oi-1];
5751
if ( (c1 == CYRILLIC_TEN) && ( (c2 >= CYRILLIC_ONE) && (c2 <= CYRILLIC_NINE))) {
5756
Digits = ucslen(tmp);
5757
new = malloc((Digits + 1) * sizeof(UTF32));
5759
uninum_err = NS_ERROR_OUTOFMEMORY;
5762
return(ucscpy(new,tmp));
5765
#define GREEK_CHARS_NEEDED 5
5767
GreekAlphabeticIntToString(mpz_t k, short LowerCaseP) {
5773
UTF32 tmp [GREEK_CHARS_NEEDED+1];
5781
uninum_err = NS_ERROR_NOZERO;
5785
if(LowerCaseP) p = GreekLowerData;
5786
else p = GreekUpperData;
5789
uninum_err = NS_ERROR_RANGE;
5793
p++; /* Skip maximum */
5796
mpz_init_set(Residue,k);
5797
mpz_tdiv_q_ui(Repeat,k,1000);
5798
Thousands = mpz_get_ui(Repeat);
5800
tmp[oi++] = GREEK_ALPHABETIC_LEFT_KERAIA;
5801
tmp[oi++] = (p + (sizeof(GreekUpperData)/sizeof(struct vcpair)) - Thousands -2)->c;
5803
mpz_submul_ui(Residue,Repeat,1000);
5806
mpz_tdiv_q_ui(Repeat,Residue,p->v);
5807
iRepeat = mpz_get_ui(Repeat);
5808
for (i=0;i < iRepeat;i++) tmp[oi++] = p->c;
5809
mpz_submul_ui(Residue,Repeat,p->v);
5813
mpz_clear(Repeat); mpz_clear(Residue);
5816
Digits = ucslen(tmp);
5817
new = malloc((Digits + 1) * sizeof(UTF32));
5819
uninum_err = NS_ERROR_OUTOFMEMORY;
5822
return(ucscpy(new,tmp));
5825
static UTF32 RomanDigitsUpper[]={
5835
static UTF32 RomanDigitsLower[]={
5853
/* Longest number within range = MMMMMMMMM DCCC LXXX VIII */
5854
#define ROMAN_CHARS_NEEDED 21
5857
RomanToStringAux(unsigned int k, short UpperP) {
5858
int Digits; /* Number of digits in string */
5859
int oi = 0; /* Index into output array */
5861
unsigned int Thousands;
5862
unsigned int Hundreds;
5864
unsigned int Residue;
5865
UTF32 optr[ROMAN_CHARS_NEEDED+1];
5869
if(UpperP) RomanDigits = RomanDigitsUpper;
5870
else RomanDigits = RomanDigitsLower;
5873
Thousands = Residue/1000;
5874
for (i=0;i < Thousands;i++) optr[oi++] = RomanDigits[R_1000];
5875
Residue -= (Thousands * 1000);
5877
if (Residue >= 500) {
5878
if (Residue >= 900) {
5879
optr[oi++] = RomanDigits[R_100];
5880
optr[oi++] = RomanDigits[R_1000];
5884
optr[oi++] = RomanDigits[R_500];
5889
if (Residue >= 400) {
5890
optr[oi++] = RomanDigits[R_100];
5891
optr[oi++] = RomanDigits[R_500];
5895
Hundreds = Residue/100;
5896
for (i=0;i < Hundreds;i++) optr[oi++] = RomanDigits[R_100];
5897
Residue -= (Hundreds * 100);
5900
if (Residue >= 50) {
5901
if (Residue >= 90) {
5902
optr[oi++] = RomanDigits[R_10];
5903
optr[oi++] = RomanDigits[R_100];
5907
optr[oi++] = RomanDigits[R_50];
5912
if (Residue >= 40) {
5913
optr[oi++] = RomanDigits[R_10];
5914
optr[oi++] = RomanDigits[R_50];
5919
for (i=0;i < Tens;i++) optr[oi++] = RomanDigits[R_10];
5920
Residue -= (Tens * 10);
5925
optr[oi++] = RomanDigits[R_1];
5926
optr[oi++] = RomanDigits[R_10];
5930
optr[oi++] = RomanDigits[R_5];
5935
optr[oi++] = RomanDigits[R_1];
5936
optr[oi++] = RomanDigits[R_5];
5940
for (i=0;i < Residue;i++) optr[oi++] = RomanDigits[R_1];
5943
Digits = ucslen(optr);
5944
new = (UTF32 *) malloc((Digits + 1) * sizeof(UTF32));
5945
if(new) ucscpy(new,optr);
5946
else uninum_err = NS_ERROR_OUTOFMEMORY;
5951
RomanIntToString(mpz_t n, short UpperP) {
5953
unsigned int Thousands;
5960
UTF32 optr[(3 * ROMAN_CHARS_NEEDED)+1];
5962
k = (unsigned int) mpz_get_ui(n);
5963
if (k > ROMAN_LIMIT) {
5964
uninum_err = NS_ERROR_RANGE;
5969
uninum_err = NS_ERROR_NOZERO;
5973
if (Uninum_Generate_Roman_With_Bar_P) {
5974
if(k <= 2000) return RomanToStringAux(k,UpperP);
5976
Ones = k - (1000 * Thousands);
5977
aptr = RomanToStringAux(Thousands,UpperP);
5980
/* Insert combining macron */
5981
while (*sptr != 0x0000) {
5987
bptr = RomanToStringAux(Ones,UpperP);
5989
while (*sptr != 0x0000) *out++ = *sptr++;
5993
new = (UTF32 *) malloc((ucslen(optr) + 1) * sizeof(UTF32));
5994
if(new) ucscpy(new,optr);
5995
else uninum_err = NS_ERROR_OUTOFMEMORY;
5998
else return RomanToStringAux(k,UpperP);
6001
UTF32 cobd0[2] = {0x281A,0x0000}; /* 0 - D245 */
6002
UTF32 cobd1[2] = {0x2801,0x0000}; /* 1 - D1 */
6003
UTF32 cobd2[2] = {0x2803,0x0000}; /* 2 - D12 */
6004
UTF32 cobd3[2] = {0x2809,0x0000}; /* 3 - D14 */
6005
UTF32 cobd4[2] = {0x2819,0x0000}; /* 4 - D145 */
6006
UTF32 cobd5[2] = {0x2811,0x0000}; /* 5 - D15 */
6007
UTF32 cobd6[2] = {0x280B,0x0000}; /* 6 - D124 */
6008
UTF32 cobd7[2] = {0x281B,0x0000}; /* 7 - D1245 */
6009
UTF32 cobd8[2] = {0x2813,0x0000}; /* 8 - D125 */
6010
UTF32 cobd9[2] = {0x280A,0x0000}; /* 9 - D24 */
6012
UTF32 *CommonBrailleDigits[]={
6013
cobd0, cobd1, cobd2, cobd3, cobd4,
6014
cobd5, cobd6, cobd7, cobd8, cobd9
6017
UTF32 frbd0[2] = {0x283C,0x0000}; /* 0 D3456 */
6018
UTF32 frbd1[2] = {0x2821,0x0000}; /* 1 D16 */
6019
UTF32 frbd2[2] = {0x2823,0x0000}; /* 2 D126 */
6020
UTF32 frbd3[2] = {0x2829,0x0000}; /* 3 D146 */
6021
UTF32 frbd4[2] = {0x2839,0x0000}; /* 4 D1456 */
6022
UTF32 frbd5[2] = {0x2831,0x0000}; /* 5 D156 */
6023
UTF32 frbd6[2] = {0x282B,0x0000}; /* 6 D1246 */
6024
UTF32 frbd7[2] = {0x283B,0x0000}; /* 7 D12456 */
6025
UTF32 frbd8[2] = {0x2833,0x0000}; /* 8 D1256 */
6026
UTF32 frbd9[2] = {0x282A,0x0000}; /* 9 D246 */
6028
UTF32 *FrenchBrailleDigits[]={ /* Also Czech */
6029
frbd0, frbd1, frbd2, frbd3, frbd4,
6030
frbd5, frbd6, frbd7, frbd8, frbd9
6033
UTF32 rubd0[2] = {0x2834,0x0000}; /* 0 - D356 */
6034
UTF32 rubd1[2] = {0x2802,0x0000}; /* 1 - D2 */
6035
UTF32 rubd2[2] = {0x2806,0x0000}; /* 2 - D23 */
6036
UTF32 rubd3[2] = {0x2812,0x0000}; /* 3 - D25 */
6037
UTF32 rubd4[2] = {0x2832,0x0000}; /* 4 - D256 */
6038
UTF32 rubd5[2] = {0x2822,0x0000}; /* 5 - D26 */
6039
UTF32 rubd6[2] = {0x2816,0x0000}; /* 6 - D235 */
6040
UTF32 rubd7[2] = {0x2836,0x0000}; /* 7 - D2356 */
6041
UTF32 rubd8[2] = {0x2826,0x0000}; /* 8 - 236 */
6042
UTF32 rubd9[2] = {0x2814,0x0000}; /* 9 - D35 */
6044
UTF32 *RussianBrailleDigits[]={
6045
rubd0, rubd1, rubd2, rubd3, rubd4,
6046
rubd5, rubd6, rubd7, rubd8, rubd9
6049
UTF32 crsd0[2] = {0x3007,0x0000};
6050
UTF32 crsd1[2] = {0x4E00,0x0000};
6051
UTF32 crsd2[2] = {0x4E8C,0x0000};
6052
UTF32 crsd3[2] = {0x4E09,0x0000};
6053
UTF32 crsd4[2] = {0x56DB,0x0000};
6054
UTF32 crsd5[2] = {0x4E94,0x0000};
6055
UTF32 crsd6[2] = {0x516D,0x0000};
6056
UTF32 crsd7[2] = {0x4E03,0x0000};
6057
UTF32 crsd8[2] = {0x516B,0x0000};
6058
UTF32 crsd9[2] = {0x4E5D,0x0000};
6060
UTF32 *ChineseRegularSimplifiedDigits[]={
6061
crsd0, crsd1, crsd2, crsd3, crsd4,
6062
crsd5, crsd6, crsd7, crsd8, crsd9
6065
UTF32 crtd0[2] = {0x96F6,0x0000};
6066
UTF32 crtd1[2] = {0x4E00,0x0000};
6067
UTF32 crtd2[2] = {0x4E8C,0x0000};
6068
UTF32 crtd3[2] = {0x4E09,0x0000};
6069
UTF32 crtd4[2] = {0x56DB,0x0000};
6070
UTF32 crtd5[2] = {0x4E94,0x0000};
6071
UTF32 crtd6[2] = {0x516D,0x0000};
6072
UTF32 crtd7[2] = {0x4E03,0x0000};
6073
UTF32 crtd8[2] = {0x516B,0x0000};
6074
UTF32 crtd9[2] = {0x4E5D,0x0000};
6076
UTF32 *ChineseRegularTraditionalDigits[]={
6077
crtd0, crtd1, crtd2, crtd3, crtd4,
6078
crtd5, crtd6, crtd7, crtd8, crtd9
6081
UTF32 cltd0[2] = {0x96F6,0x0000};
6082
UTF32 cltd1[2] = {0x58F9,0x0000};
6083
UTF32 cltd2[2] = {0x8CB3,0x0000};
6084
UTF32 cltd3[2] = {0x53C1,0x0000};
6085
UTF32 cltd4[2] = {0x8086,0x0000};
6086
UTF32 cltd5[2] = {0x4F0D,0x0000};
6087
UTF32 cltd6[2] = {0x9646,0x0000};
6088
UTF32 cltd7[2] = {0x6F06,0x0000};
6089
UTF32 cltd8[2] = {0x634C,0x0000};
6090
UTF32 cltd9[2] = {0x7396,0x0000};
6092
UTF32 *ChineseLegalTraditionalDigits[]={
6093
cltd0, cltd1, cltd2, cltd3, cltd4,
6094
cltd5, cltd6, cltd7, cltd8, cltd9
6098
UTF32 clsd0[2] = {0x96F6,0x0000};
6099
UTF32 clsd1[2] = {0x58F1,0x0000};
6100
UTF32 clsd2[2] = {0x5F10,0x0000};
6101
UTF32 clsd3[2] = {0x53C1,0x0000};
6102
UTF32 clsd4[2] = {0x8086,0x0000};
6103
UTF32 clsd5[2] = {0x4F0D,0x0000};
6104
UTF32 clsd6[2] = {0x9678,0x0000};
6105
UTF32 clsd7[2] = {0x67D2,0x0000};
6106
UTF32 clsd8[2] = {0x634C,0x0000};
6107
UTF32 clsd9[2] = {0x7396,0x0000};
6109
UTF32 *ChineseLegalSimplifiedDigits[]={
6110
clsd0, clsd1, clsd2, clsd3, clsd4,
6111
clsd5, clsd6, clsd7, clsd8, clsd9
6114
UTF32 jltd0[2] = {0x3007,0x0000};
6115
UTF32 jltd1[2] = {0x58F9,0x0000};
6116
UTF32 jltd2[2] = {0x8CB3,0x0000};
6117
UTF32 jltd3[2] = {0x53C3,0x0000};
6118
UTF32 jltd4[2] = {0x8086,0x0000};
6119
UTF32 jltd5[2] = {0x4F0D,0x0000};
6120
UTF32 jltd6[2] = {0x9678,0x0000};
6121
UTF32 jltd7[2] = {0x67D2,0x0000};
6122
UTF32 jltd8[2] = {0x634C,0x0000};
6123
UTF32 jltd9[2] = {0x7396,0x0000};
6125
UTF32 *JapaneseLegalTraditionalDigits[]={
6126
jltd0, jltd1, jltd2, jltd3, jltd4,
6127
jltd5, jltd6, jltd7, jltd8, jltd9
6130
UTF32 jlsd0[2] = {0x3007,0x0000};
6131
UTF32 jlsd1[2] = {0x58F1,0x0000};
6132
UTF32 jlsd2[2] = {0x5F10,0x0000};
6133
UTF32 jlsd3[2] = {0x53C2,0x0000};
6134
UTF32 jlsd4[2] = {0x56DB,0x0000};
6135
UTF32 jlsd5[2] = {0x4E94,0x0000};
6136
UTF32 jlsd6[2] = {0x516D,0x0000};
6137
UTF32 jlsd7[2] = {0x4E03,0x0000};
6138
UTF32 jlsd8[2] = {0x516B,0x0000};
6139
UTF32 jlsd9[2] = {0x4E5D,0x0000};
6141
UTF32 *JapaneseLegalSimplifiedDigits[]={
6142
jlsd0, jlsd1, jlsd2, jlsd3, jlsd4,
6143
jlsd5, jlsd6, jlsd7, jlsd8, jlsd9
6147
UTF32 ccru0[2] = {0x3007,0x0000};
6148
UTF32 ccru1[2] = {0x1D360,0x0000};
6149
UTF32 ccru2[2] = {0x1D361,0x0000};
6150
UTF32 ccru3[2] = {0x1D362,0x0000};
6151
UTF32 ccru4[2] = {0x1D363,0x0000};
6152
UTF32 ccru5[2] = {0x1D364,0x0000};
6153
UTF32 ccru6[2] = {0x1D365,0x0000};
6154
UTF32 ccru7[2] = {0x1D366,0x0000};
6155
UTF32 ccru8[2] = {0x1D367,0x0000};
6156
UTF32 ccru9[2] = {0x1D368,0x0000};
6158
UTF32 *ChineseCountingRodDigits[]={
6159
ccru0, ccru1, ccru2, ccru3, ccru4,
6160
ccru5, ccru6, ccru7, ccru8, ccru9
6164
UTF32 ccrd0[2] = {0x3007,0x0000};
6165
UTF32 ccrd1[2] = {0x1D369,0x0000};
6166
UTF32 ccrd2[2] = {0x1D36A,0x0000};
6167
UTF32 ccrd3[2] = {0x1D36B,0x0000};
6168
UTF32 ccrd4[2] = {0x1D36C,0x0000};
6169
UTF32 ccrd5[2] = {0x1D36D,0x0000};
6170
UTF32 ccrd6[2] = {0x1D36E,0x0000};
6171
UTF32 ccrd7[2] = {0x1D36F,0x0000};
6172
UTF32 ccrd8[2] = {0x1D370,0x0000};
6173
UTF32 ccrd9[2] = {0x1D371,0x0000};
6175
UTF32 *ChineseCountingRodDecades[]={
6176
ccrd0, ccrd1, ccrd2, ccrd3, ccrd4,
6177
ccrd5, ccrd6, ccrd7, ccrd8, ccrd9
6180
/* Japanese traditional barriers 10^4 = 84C2l, 10^3 = 9621 (financial), 10^2 = 4F70 (financial),
6183
static UTF32 ChineseRegularTraditionalBarriers[] = {
6184
0x5341, /* 0 - 10^1 */
6185
0x767E, /* 1 - 10^2 */
6186
0x5343, /* 2 - 10^3 */
6187
0x842C, /* 3 - 10^4 */
6188
0x5104, /* 4 - 10^8 */
6189
0x5146, /* 5 - 10^12 */
6190
0x4EAC, /* 6 - 10^16 */
6191
0x5793, /* 7 - 10^20 */
6192
0x25771, /* 8 - 10^24 */
6193
0x7A63, /* 9 - 10^28 */
6194
0x6E9D, /* 10 - 10^32 */
6195
0x6F97, /* 11 - 10^36 */
6196
0x6B63, /* 12 - 10^40 */
6197
0x8F09, /* 13 - 10^44 */
6198
0x6975, /* 14 - 10^48 */
6201
static UTF32 ChineseRegularSimplifiedBarriers[] = {
6202
0x5341, /* 0 - 10^1 */
6203
0x767E, /* 1 - 10^2 */
6204
0x5343, /* 2 - 10^3 */
6205
0x4E07, /* 3 - 10^4 */
6206
0x4EBF, /* 4 - 10^8 */
6207
0x5146, /* 5 - 10^12 */
6208
0x4EAC, /* 6 - 10^16 */
6209
0x5793, /* 7 - 10^20 */
6210
0x25771, /* 8 - 10^24 */
6211
0x7A63, /* 9 - 10^28 */
6212
0x6C9F, /* 10 - 10^32 */
6213
0x6DA7, /* 11 - 10^36 */
6214
0x6B63, /* 12 - 10^40 */
6215
0x8F7D, /* 13 - 10^44 */
6216
0x6781, /* 14 - 10^48 */
6219
static UTF32 ChineseLegalTraditionalBarriers[] = {
6220
0x62FE, /* 0 - 10^1 */
6221
0x767E, /* 1 - 10^2 */
6222
0x4EDF, /* 2 - 10^3 */
6223
0x842C, /* 3 - 10^4 */
6224
0x5104, /* 4 - 10^8 */
6225
0x5146, /* 5 - 10^12 */
6226
0x4EAC, /* 6 - 10^16 */
6227
0x5793, /* 7 - 10^20 */
6228
0x25771, /* 8 - 10^24 */
6229
0x7A63, /* 9 - 10^28 */
6230
0x6E9D, /* 10 - 10^32 */
6231
0x6F97, /* 11 - 10^36 */
6232
0x6B63, /* 12 - 10^40 */
6233
0x8F09, /* 13 - 10^44 */
6234
0x6975, /* 14 - 10^48 */
6237
static UTF32 ChineseLegalSimplifiedBarriers[] = {
6238
0x5341, /* 0 - 10^1 */
6239
0x767E, /* 1 - 10^2 */
6240
0x4EDF, /* 2 - 10^3 */
6241
0x842C, /* 3 - 10^4 */
6242
0x5104, /* 4 - 10^8 */
6243
0x5146, /* 5 - 10^12 */
6244
0x4EAC, /* 6 - 10^16 */
6245
0x5793, /* 7 - 10^20 */
6246
0x25771, /* 8 - 10^24 */
6247
0x7A63, /* 9 - 10^28 */
6248
0x6C9F, /* 10 - 10^32 */
6249
0x6DA7, /* 11 - 10^36 */
6250
0x6B63, /* 12 - 10^40 */
6251
0x8F7D, /* 13 - 10^44 */
6252
0x6781, /* 14 - 10^48 */
6255
static UTF32 JapaneseRegularSimplifiedBarriers[] = {
6256
0x5341, /* 0 - 10^1 */
6257
0x767E, /* 1 - 10^2 */
6258
0x5343, /* 2 - 10^3 */
6259
0x4E07, /* 3 - 10^4 */
6260
0x5104, /* 4 - 10^8 */
6261
0x5146, /* 5 - 10^12 */
6262
0x4EAC, /* 6 - 10^16 */
6263
0x5793, /* 7 - 10^20 */
6264
0x25771, /* 8 - 10^24 */
6265
0x7A63, /* 9 - 10^28 */
6266
0x6E9D, /* 10 - 10^32 */
6267
0x6F97, /* 11 - 10^36 */
6268
0x6B63, /* 12 - 10^40 */
6269
0x8F09, /* 13 - 10^44 */
6270
0x6975, /* 14 - 10^48 */
6273
static UTF32 JapaneseLegalTraditionalBarriers[] = {
6274
0x62FE, /* 0 - 10^1 */
6275
0x767E, /* 1 - 10^2 */
6276
0x4EDF, /* 2 - 10^3 */
6277
0x842C, /* 3 - 10^4 */
6278
0x5104, /* 4 - 10^8 */
6279
0x5146, /* 5 - 10^12 */
6280
0x4EAC, /* 6 - 10^16 */
6281
0x5793, /* 7 - 10^20 */
6282
0x25771, /* 8 - 10^24 */
6283
0x7A63, /* 9 - 10^28 */
6284
0x6E9D, /* 10 - 10^32 */
6285
0x6F97, /* 11 - 10^36 */
6286
0x6B63, /* 12 - 10^40 */
6287
0x8F09, /* 13 - 10^44 */
6288
0x6975, /* 14 - 10^48 */
6291
static UTF32 JapaneseLegalSimplifiedBarriers[] = {
6292
0x5341, /* 0 - 10^1 */
6293
0x767E, /* 1 - 10^2 */
6294
0x4EDF, /* 2 - 10^3 */
6295
0x842C, /* 3 - 10^4 */
6296
0x5104, /* 4 - 10^8 */
6297
0x5146, /* 5 - 10^12 */
6298
0x4EAC, /* 6 - 10^16 */
6299
0x5793, /* 7 - 10^20 */
6300
0x25771, /* 8 - 10^24 */
6301
0x7A63, /* 9 - 10^28 */
6302
0x6C9F, /* 10 - 10^32 */
6303
0x6DA7, /* 11 - 10^36 */
6304
0x6B63, /* 12 - 10^40 */
6305
0x8F7D, /* 13 - 10^44 */
6306
0x6781, /* 14 - 10^48 */
6310
/* Remove the leading 1 from 10-19 */
6312
FixChineseTeens(UTF32 *s){
6316
if( ((len == 3) || (len == 2)) && (s[0] == 0x4E00) && (s[1] == 0x5341)) {
6324
* In Mandarin and Chao Zhou a special form of 2 (liang/no) is used before units greater than 10.
6325
* This subroutine changes 2 to liang/no where appropriate.
6327
void FixLiang(UTF32 *s) {
6331
while(*p != 0x0000) {
6332
if((*p == 0x4E8C) || (*p == 0x8CB3) || (*p == 0x5F10)) { /* 2 */
6333
if (*(p+1) == 0x0000) break; /* 2 in final position */
6334
if (*(p+1) == 0x5341) { /* 2 immediately precedes 10 */
6338
*p = 0x4E24; /* Replace with liang */
6344
void StripLeadingChineseOne(UTF32 *s) {
6347
if( (*s == 0x4E00) && (ucslen(s) > 1)) {
6349
while (*p != 0x0000) {
6356
void ReduceChineseZeroSequences(UTF32 *s) {
6360
enum {START,PREVIOUS_ZERO} State = START;
6363
while ( (c = *ip) != 0x0000) {
6364
if ( (c == 0x3007) || (c == 0x96F6)) {
6365
if (State == START) {
6367
State = PREVIOUS_ZERO;
6379
void StripTrailingChineseZero(UTF32 *s) {
6381
Last_Index = ucslen(s) -1;
6382
if ( (s[Last_Index] == 0x3007) || (s[Last_Index] == 0x96F6)) s[Last_Index] = 0x0000;
6386
#define CHINESE_BARRIER_CNT 15
6387
#define CHINESE_CHARS_NEEDED 300
6388
static UTF32 *ChineseIntToString(mpz_t n,UTF32 **DigitList, UTF32 *Barriers, short ZeroP){
6394
UTF32 obuf[CHINESE_CHARS_NEEDED+1];
6398
mpz_t MaxChinese; /* Maximum value convertible to Chinese string */
6400
/* (10^97)-1, in hex for compactness and speed of conversion to binary */
6401
mpz_init_set_str(MaxChinese,MAXCHINESEHEX,16);
6402
if(TGE(n,MaxChinese)) {
6403
uninum_err = NS_ERROR_RANGE;
6406
mpz_clear(MaxChinese);
6408
if (mpz_cmp_ui(n,0) > 0-ZeroP) {
6410
return(MakeSingleDigitString(DigitList[k][0]));
6415
mpz_init(q);mpz_init(r);mpz_init(t);mpz_init(val);
6416
for(i= CHINESE_BARRIER_CNT-1; i >= 0;i--) {
6417
GetChineseBarrierValue(val,i);
6418
mpz_tdiv_qr(q,r,n,val);
6420
rptr = ChineseIntToString(q,DigitList,Barriers,ZeroP);
6422
ptr=ucpcpy(obuf,rptr);
6424
*ptr++ = Barriers[i];
6429
GetChineseBarrierValue(val,i-1);
6430
mpz_tdiv_q(t,r,val);
6431
if(UEQ(t,0)) ucscat(obuf,DigitList[0]);
6434
rptr = ChineseIntToString(r,DigitList,Barriers,ZeroP);
6440
} /* end of if q > 0 */
6442
if(ZeroP) ucscat(obuf,DigitList[0]);
6445
mpz_clear(q);mpz_clear(r);mpz_clear(t);mpz_clear(val);
6446
ptr = (UTF32 *) malloc ((1 + ucslen(obuf)) * sizeof(UTF32));
6447
if(ptr) ucscpy(ptr,obuf);
6448
else uninum_err = NS_ERROR_OUTOFMEMORY;
6453
#define CHINESE_WESTERN_CHARS_NEEDED 300
6454
static UTF32 *ChineseWesternIntToString(mpz_t n,UTF32 **DigitList, UTF32 *Barriers){
6459
UTF32 obuf[CHINESE_WESTERN_CHARS_NEEDED+1];
6464
mpz_t MaxChinese; /* Maximum value convertible to Chinese string */
6466
mpz_init_set_str(MaxChinese,MAXCHINESEHEX,16);
6467
if(TGT(n,MaxChinese)) {
6468
uninum_err = NS_ERROR_RANGE;
6469
mpz_clear(MaxChinese);
6472
mpz_clear(MaxChinese);
6477
return(MakeSingleDigitString(DigitList[k][0]));
6482
mpz_init(q);mpz_init(r);mpz_init(val);
6483
for(i= CHINESE_BARRIER_CNT-1; i >= 0;i--) {
6484
GetChineseBarrierValue(val,i);
6485
mpz_tdiv_qr(q,r,n,val);
6488
tmpptr = PlaceIntToString(q,WESTERN_ZERO,10);
6489
rptr = wcDelimitNumber(tmpptr,0x002C,0x002E,3,3);
6490
if (tmpptr != rptr) free(tmpptr);
6492
else rptr = ChineseWesternIntToString(q,DigitList,Barriers);
6494
ptr=ucpcpy(obuf,rptr);
6497
*ptr++= Barriers[i];
6500
tmpptr = PlaceIntToString(r,WESTERN_ZERO,10);
6501
rptr = wcDelimitNumber(tmpptr,0x002C,0x002E,3,3);
6502
if (tmpptr != rptr) free(tmpptr);
6504
else rptr = ChineseWesternIntToString(r,DigitList,Barriers);
6506
if( (UGE(r,10000)) || (*rptr != WESTERN_ZERO)) {
6514
mpz_clear(q);mpz_clear(r);mpz_clear(val);
6515
ptr = (UTF32 *) malloc ((1 + ucslen(obuf)) * sizeof(UTF32));
6516
if(ptr) ucscpy(ptr,obuf);
6521
/* This is a fairly slight adaptation of PlaceNonContiguousIntToString */
6524
ChineseCountingRodIntToString(mpz_t n, short EarlyP) {
6534
unsigned long int temp;
6536
UTF32 **EvenDigitList;
6537
UTF32 **OddDigitList;
6540
Digits = mpz_sizeinbase(k,10);
6541
new = malloc((Digits + 1) * sizeof(UTF32));
6543
uninum_err = NS_ERROR_OUTOFMEMORY;
6553
EvenDigitList = ChineseCountingRodDecades;
6554
OddDigitList = ChineseCountingRodDigits;
6557
EvenDigitList = ChineseCountingRodDigits;
6558
OddDigitList = ChineseCountingRodDecades;
6562
end = new + Digits-1;
6566
mpz_tdiv_qr_ui(q,r,k,10);
6567
if ((end - s)%2) *s++ = EvenDigitList[mpz_get_ui(r)][0];
6568
else *s++ = OddDigitList[mpz_get_ui(r)][0];
6570
} while (UGT(q,0L));
6572
*s = 0L; /* Null terminate string */
6573
s--; /* Point s at last non-null char */
6575
mpz_clear(d);mpz_clear(k);mpz_clear(q);mpz_clear(r);
6578
* Now we reverse the string. When we begin, p points at the first
6579
* character of the string, s at the last non-null character.
6590
/* define number addresses */
6591
#define ETH_ONE 0x1369
6592
#define ETH_TEN ETH_ONE + 9
6593
#define ETH_HUNDRED ETH_TEN + 9
6594
#define ETH_TENTHOUSAND ETH_HUNDRED + 1
6598
* This is based loosely on Daniel Jacob's function but heavily rewritten.
6602
EthiopicIntToString(mpz_t n) {
6607
int EthiopicCharCnt = 0;
6608
char asciiOne, asciiTen;
6609
UTF32 OnesPlace, TensPlace, HundredSep;
6614
Number=mpz_get_str(NULL,10,n);
6615
MaxTenPower = strlen( Number) - 1;
6616
if (MaxTenPower == 0) {
6617
FinalResult = (UTF32 *) malloc ( 2 * sizeof (UTF32) );
6618
FinalResult[0] = Number[0] + ETH_ONE - '1';
6619
FinalResult[1] = '\0';
6620
return (FinalResult);
6622
else if ( (MaxTenPower % 2) == 0 ) {
6624
* Precondition the string to always have the leading tens place populated.
6626
tmp = (char *) malloc ((MaxTenPower+2)*sizeof(char) );
6627
sprintf (tmp,"0%s",Number);
6633
Result = (UTF32 *) malloc (((4 * MaxTenPower)+1) * sizeof (UTF32));
6634
if(!Result) {uninum_err = NS_ERROR_OUTOFMEMORY;return(NULL);}
6636
for (CurrentPower = MaxTenPower; CurrentPower >= 0; CurrentPower-- ) {
6637
OnesPlace = TensPlace = 0x0;
6638
asciiTen = Number[MaxTenPower-CurrentPower];
6640
asciiOne = Number[MaxTenPower-CurrentPower];
6642
if (asciiOne != '0') OnesPlace = asciiOne + (ETH_ONE - '1');
6643
if (asciiTen != '0') TensPlace = asciiTen + (ETH_TEN - '1');
6645
/* Choose the HundredSeparator for this group */
6646
OddSubgroupP = (CurrentPower % 4) / 2;
6647
if(CurrentPower > 0) {
6649
if(OnesPlace || TensPlace) HundredSep = ETH_HUNDRED;
6650
else HundredSep = 0;
6652
else HundredSep = ETH_TENTHOUSAND;
6654
else HundredSep = 0;
6657
* If we have a one without a leading ten
6658
* or following 100 or in initial position, remove the one.
6660
if ( (OnesPlace == ETH_ONE ) && TensPlace == 0) {
6661
if ( (HundredSep == ETH_HUNDRED ) || (CurrentPower+1) == MaxTenPower) OnesPlace = 0;
6664
/* Assemble this group */
6665
if (TensPlace) Result[EthiopicCharCnt++] = TensPlace;
6666
if (OnesPlace) Result[EthiopicCharCnt++] = OnesPlace;
6667
if (HundredSep) Result[EthiopicCharCnt++] = HundredSep;
6668
} /* End of for loop over input digits */
6670
Result[EthiopicCharCnt] = (UTF32) 0;
6672
FinalResult = (UTF32 *) malloc ((EthiopicCharCnt+1) * sizeof (UTF32));
6673
if(!FinalResult) {uninum_err = NS_ERROR_OUTOFMEMORY;return(NULL);}
6674
ucscpy(FinalResult,Result);
6676
return (FinalResult);
6679
#define HEBREW_CHARS_NEEDED 7 /* unit, decade, 100, 2nd 100, 3d 100, geresh, 1000 */
6680
#define HEBREW_DATA_ENTRIES 29
6682
/* This is a slight variant on AdditiveIntToString */
6684
HebrewIntToString(mpz_t k, struct vcpair *data, short EarlyP) {
6690
UTF32 tmp[HEBREW_CHARS_NEEDED+1];
6699
uninum_err = NS_ERROR_RANGE;
6704
uninum_err = NS_ERROR_NOZERO;
6712
mpz_tdiv_qr_ui(Repeat,Residue,k,1000L);
6713
tmp[oi++] = (data + HEBREW_DATA_ENTRIES -1 - mpz_get_ui(Repeat))->c;
6714
tmp[oi++] = 0x05F3; /* Geresh */
6716
else mpz_set(Residue,k);
6718
if (EarlyP) p = data+6;
6721
if(UEQ(Residue,15)) {
6724
mpz_sub_ui(Residue,Residue,15);
6726
else if(UEQ(Residue,16)) {
6729
mpz_sub_ui(Residue,Residue,16);
6732
mpz_tdiv_q_ui(Repeat,Residue,p->v);
6733
iRepeat = mpz_get_ui(Repeat);
6734
for (i=0;i < iRepeat;i++) tmp[oi++] = p->c;
6735
mpz_submul_ui(Residue,Repeat,p->v);
6743
Digits = ucslen(tmp);
6744
new = malloc((Digits + 1) * sizeof(UTF32));
6746
uninum_err = NS_ERROR_OUTOFMEMORY;
6749
return(ucscpy(new,tmp));
6753
struct vcpair KharoshthiData[]={ /* Max is stored in subroutine in this case */
6760
* Computation of max chars needed:
6761
* 77 + (100 * 7) + (1000 * (77 + (100 * 7))) = 777,777 (longer than 999,999)
6765
#define KHAROSHTHI_CHARS_NEEDED 27
6766
UTF32 *KharoshthiIntToString(mpz_t n){
6767
int Digits; /* Number of digits in string */
6768
int oi = 0; /* Index into output array */
6774
unsigned int iRepeat;
6776
UTF32 tmp[KHAROSHTHI_CHARS_NEEDED+1];
6783
if (UGT(n,999999L)) {
6784
uninum_err = NS_ERROR_RANGE;
6789
uninum_err = NS_ERROR_NOZERO;
6793
mpz_init(Thousands);
6803
mpz_tdiv_q_ui(Thousands,Residue,1000L);
6804
if(UGT(Thousands,0)) {
6805
ptr = KharoshthiIntToString(Thousands);
6806
op = ucpcpy(op,ptr);
6808
*op++ = KHAROSHTHI_THOUSAND;
6811
mpz_submul_ui(Residue,Thousands,1000L);
6814
mpz_tdiv_q_ui(Hundreds,Residue,100L);
6815
if(UGT(Hundreds,0)) {
6816
ptr = KharoshthiIntToString(Hundreds);
6817
op = ucpcpy(op,ptr);
6819
*op++ = KHAROSHTHI_HUNDRED;
6822
mpz_submul_ui(Residue,Hundreds,100L);
6827
mpz_tdiv_q_ui(Repeat,Residue,p->v);
6828
iRepeat = mpz_get_ui(Repeat);
6829
for (i=0;i < iRepeat;i++) *op++ = p->c;
6830
mpz_submul_ui(Residue,Repeat,p->v);
6835
/* Although numerals exist for 2 and 3, only 1 and 4 enter into combination */
6836
/* 6 = 4 + 1 +1 not 4 + 2 or 3 + 3, 7 = 4 + 1 +1 +1, not 4 + 3 */
6838
k = mpz_get_ui(Residue);
6841
*op++ =KHAROSHTHI_ONE;
6844
*op++ =KHAROSHTHI_TWO;
6847
*op++ =KHAROSHTHI_THREE;
6850
*op++ =KHAROSHTHI_FOUR;
6853
*op++ =KHAROSHTHI_FOUR;
6854
*op++ =KHAROSHTHI_ONE;
6857
*op++ =KHAROSHTHI_FOUR;
6858
*op++ =KHAROSHTHI_ONE;
6859
*op++ =KHAROSHTHI_ONE;
6862
*op++ =KHAROSHTHI_FOUR;
6863
*op++ =KHAROSHTHI_ONE;
6864
*op++ =KHAROSHTHI_ONE;
6865
*op++ =KHAROSHTHI_ONE;
6868
*op++ =KHAROSHTHI_FOUR;
6869
*op++ =KHAROSHTHI_FOUR;
6872
*op++ =KHAROSHTHI_FOUR;
6873
*op++ =KHAROSHTHI_FOUR;
6874
*op++ =KHAROSHTHI_ONE;
6882
mpz_clear(Thousands);
6883
mpz_clear(Hundreds);
6887
Digits = ucslen(tmp);
6888
new = malloc((Digits + 1) * sizeof(UTF32));
6890
uninum_err = NS_ERROR_OUTOFMEMORY;
6894
return(ucscpy(new,tmp));
6898
UTF32 tamd0[2] = {0x0BE6,0x0000};
6899
UTF32 tamd1[2] = {0x0BE7,0x0000};
6900
UTF32 tamd2[2] = {0x0BE8,0x0000};
6901
UTF32 tamd3[2] = {0x0BE9,0x0000};
6902
UTF32 tamd4[2] = {0x0BEA,0x0000};
6903
UTF32 tamd5[2] = {0x0BEB,0x0000};
6904
UTF32 tamd6[2] = {0x0BEC,0x0000};
6905
UTF32 tamd7[2] = {0x0BED,0x0000};
6906
UTF32 tamd8[2] = {0x0BEE,0x0000};
6907
UTF32 tamd9[2] = {0x0BEF,0x0000};
6909
UTF32 *TamilDigits[]={
6910
tamd0, tamd1, tamd2, tamd3, tamd4,
6911
tamd5, tamd6, tamd7, tamd8, tamd9
6915
#define TAMIL_CHARS_NEEDED 10
6916
static UTF32 *TamilTraditionalIntToString(mpz_t n){
6921
UTF32 obuf[TAMIL_CHARS_NEEDED+1];
6927
uninum_err = NS_ERROR_RANGE;
6933
return(MakeSingleDigitString(TamilDigits[k][0]));
6936
mpz_init(q);mpz_init(r);mpz_init(val);
6937
for(i= (sizeof(TamilBarriers)/sizeof(UTF32))-1; i >= 0;i--) {
6939
mpz_tdiv_qr_ui(q,r,n,TamilBarrierValue[i]);
6941
rptr = TamilTraditionalIntToString(q);
6942
ptr=ucpcpy(obuf,rptr);
6943
if (UGT(q, 10L)) free(rptr);
6944
*ptr++= TamilBarriers[i];
6946
rptr = TamilTraditionalIntToString(r);
6948
if (UGT(r, 10L)) free(rptr);
6952
mpz_clear(q);mpz_clear(r);mpz_clear(val);
6953
ptr = (UTF32 *) malloc ((1 + ucslen(obuf)) * sizeof(UTF32));
6954
if(ptr) ucscpy(ptr,obuf);
6960
UTF32 UpperAlphaDigits[]={
6999
UTF32 LowerAlphaDigits[]={
7039
WesternGeneralIntToString(mpz_t n, int Base, short UpperP) {
7040
unsigned long Digits;
7049
unsigned long int temp;
7052
if ((Base > 36) || (Base < 1)) {
7053
uninum_err = NS_ERROR_BADBASE;
7059
uninum_err = NS_ERROR_NOZERO;
7062
if(!mpz_fits_ulong_p(n)) {
7063
uninum_err = NS_ERROR_DOESNOTFIT;
7066
Digits = mpz_get_ui(n);
7068
else Digits = mpz_sizeinbase(n,Base);
7069
new = malloc((Digits + 1) * sizeof(UTF32));
7071
uninum_err = NS_ERROR_OUTOFMEMORY;
7076
if (UpperP) ZeroCode = UpperAlphaDigits;
7077
else ZeroCode = LowerAlphaDigits;
7080
for (i = 0; i < Digits; i++) *s++ = 0x0030;
7081
*s = 0x0000; /* Null terminate string */
7087
mpz_init_set_ui(b,Base);
7091
mpz_tdiv_qr(q,r,k,b);
7092
*s++ = *(ZeroCode + mpz_get_ui(r));
7094
} while (UGT(q,0L));
7096
*s = 0x0000; /* Null terminate string */
7097
s--; /* Point s at last non-null char */
7100
* Now we reverse the string. When we begin, p points at the first
7101
* character of the string, s at the last non-null character.
7109
mpz_clear(b);mpz_clear(k);mpz_clear(q);mpz_clear(r);
7115
/* Reorder 11-19 to spoken order */
7116
#define GLAGOLITIC_ONE 0x2C00
7117
#define GLAGOLITIC_NINE 0x2C08
7118
#define GLAGOLITIC_TEN 0x2C09
7119
static void FixGlagoliticTeens(UTF32 *s){
7120
int oi; /* Index of final null */
7127
if ( (c1 == GLAGOLITIC_TEN) && ( (c2 >= GLAGOLITIC_ONE) && (c2 <= GLAGOLITIC_NINE))) {
7133
UTF32 *SupplyIsolatedChineseZero (short TraditionalP) {
7135
new = malloc(sizeof(UTF32) * 2);
7137
fprintf(stderr,"Out of memory.\n");
7140
if(TraditionalP) new[0] = 0x96F6;
7141
else new[0] = 0x3007;
7146
// s[0] s[1] s[2] s[3] len = 3, lim = 2, max(i) = 2
7154
/* Delete a zero neither of whose immediate neighbors is a zero or an edge */
7155
void MinimizeCountingRodZeroes(UTF32 *s) {
7163
tmp = alloca( (len+1) * sizeof(UTF32));
7165
tmp = malloc( (len+1) * sizeof(UTF32));
7170
for(i=1;i < len; i++){
7171
if((s[i] == 0x3007) && (s[i-1] != 0x3007) && (s[i+1] != 0x3007) && (s[i+1] != 0x0000)) ;
7183
* This subroutine takes care of two special features of Suzhou numbers.
7184
* One is that the zero does not immediately precede the other digits
7185
* in Unicode order, so we first generate the numbers with the codepoint
7186
* preceding Suzhou 1 (U+3020) and then replace it here with the proper
7189
* The other is that the numbers one through three have both vertical forms, used by
7190
* default, and horizontal forms, which are used when the preceding character
7191
* is one of the three vertical characters. PlaceIntToString generates
7192
* the defaults only, so here we replace them with their horizontal counterparts
7196
static void FixSuzhou(UTF32 *s){
7198
enum {START,PREVIOUS_VERTICAL} State = START;
7201
while(*p != 0x0000) {
7207
if(State == PREVIOUS_VERTICAL) {
7211
else State = PREVIOUS_VERTICAL;
7214
if(State == PREVIOUS_VERTICAL) {
7218
else State = PREVIOUS_VERTICAL;
7221
if(State == PREVIOUS_VERTICAL) {
7225
else State = PREVIOUS_VERTICAL;
7234
/* This is the main string-generating function */
7236
IntToString(union ns_rval *n,int ns, short InputType) {
7241
uninum_err = NS_ERROR_OKAY;
7249
case NS_TYPE_STRING:
7250
mpz_set_str(z,n->s,10);
7258
uninum_err = NS_ERROR_RANGE;
7265
ptr = AdditiveIntToString(z,AegeanData);
7267
case NS_ARABIC_WESTERN:
7268
ptr = PlaceIntToString(z,ARABIC_ZERO,10);
7270
case NS_ARABIC_ALPHABETIC:
7271
ptr = AdditiveIntToString(z,ArabicAlphabeticData);
7273
case NS_PERSO_ARABIC:
7274
ptr = PlaceIntToString(z,PERSO_ARABIC_ZERO,10);
7276
case NS_ARMENIAN_ALPHABETIC:
7277
ptr = AdditiveIntToString(z,ArmenianData);
7280
ptr = PlaceIntToString(z,BALINESE_ZERO,10);
7283
ptr = PlaceIntToString(z,BENGALI_ZERO,10);
7286
ptr = PlaceIntToString(z,BURMESE_ZERO,10);
7288
case NS_CHINESE_COUNTING_ROD_EARLY_WITH_ZERO:
7289
ptr = ChineseCountingRodIntToString(z,1);
7291
case NS_CHINESE_COUNTING_ROD_EARLY_WITHOUT_ZERO:
7292
ptr = ChineseCountingRodIntToString(z,1);
7293
if(ptr) MinimizeCountingRodZeroes(ptr);
7295
case NS_CHINESE_COUNTING_ROD_LATE_WITH_ZERO:
7296
ptr = ChineseCountingRodIntToString(z,0);
7298
case NS_CHINESE_COUNTING_ROD_LATE_WITHOUT_ZERO:
7299
ptr = ChineseCountingRodIntToString(z,0);
7300
if(ptr) MinimizeCountingRodZeroes(ptr);
7302
case NS_CHINESE_LEGAL_SIMPLIFIED:
7303
if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(0);
7304
else ptr = ChineseIntToString(z,ChineseLegalSimplifiedDigits,ChineseLegalSimplifiedBarriers,0);
7306
case NS_CHINESE_LEGAL_TRADITIONAL:
7307
if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(0);
7308
else ptr = ChineseIntToString(z,ChineseLegalTraditionalDigits,ChineseLegalTraditionalBarriers,0);
7310
case NS_CHINESE_REGULAR_SIMPLIFIED:
7311
if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(0);
7313
ptr = ChineseIntToString(z,ChineseRegularSimplifiedDigits,ChineseRegularSimplifiedBarriers,0);
7314
if (ptr) FixChineseTeens(ptr);
7317
case NS_CHINESE_REGULAR_TRADITIONAL:
7318
if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(1);
7320
ptr = ChineseIntToString(z,ChineseRegularTraditionalDigits,ChineseRegularTraditionalBarriers,0);
7321
if (ptr) FixChineseTeens(ptr);
7324
case NS_CHINESE_MANDARIN_LEGAL_SIMPLIFIED:
7325
if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(0);
7327
ptr = ChineseIntToString(z,ChineseLegalSimplifiedDigits,ChineseLegalSimplifiedBarriers,0);
7328
if (ptr) FixLiang(ptr);
7331
case NS_CHINESE_MANDARIN_LEGAL_TRADITIONAL:
7332
if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(1);
7334
ptr = ChineseIntToString(z,ChineseLegalTraditionalDigits,ChineseLegalTraditionalBarriers,0);
7335
if(ptr) FixLiang(ptr);
7338
case NS_CHINESE_MANDARIN_REGULAR_SIMPLIFIED:
7339
if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(0);
7341
ptr = ChineseIntToString(z,ChineseRegularSimplifiedDigits,ChineseRegularSimplifiedBarriers,1);
7343
ReduceChineseZeroSequences(ptr);
7344
StripTrailingChineseZero(ptr);
7345
FixChineseTeens(ptr);
7350
case NS_CHINESE_MANDARIN_REGULAR_TRADITIONAL:
7351
if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(1);
7353
ptr = ChineseIntToString(z,ChineseRegularTraditionalDigits,ChineseRegularTraditionalBarriers,1);
7355
ReduceChineseZeroSequences(ptr);
7356
StripTrailingChineseZero(ptr);
7357
FixChineseTeens(ptr);
7362
case NS_CHINESE_REGULAR_PLACE:
7363
ptr = PlaceNonContiguousIntToString(z,ChineseRegularSimplifiedDigits,10);
7365
case NS_CHINESE_JAPANESE_REGULAR_TRADITIONAL:
7366
if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(1);
7368
ptr = ChineseIntToString(z,ChineseRegularTraditionalDigits,ChineseRegularTraditionalBarriers,0);
7369
if(ptr) StripLeadingChineseOne(ptr);
7372
case NS_CHINESE_JAPANESE_REGULAR_SIMPLIFIED:
7373
if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(0);
7375
ptr = ChineseIntToString(z,ChineseRegularSimplifiedDigits,JapaneseRegularSimplifiedBarriers,0);
7376
if(ptr) StripLeadingChineseOne(ptr);
7379
case NS_CHINESE_JAPANESE_LEGAL_TRADITIONAL:
7380
if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(1);
7381
else ptr = ChineseIntToString(z,JapaneseLegalTraditionalDigits,JapaneseLegalTraditionalBarriers,0);
7383
case NS_CHINESE_JAPANESE_LEGAL_SIMPLIFIED:
7384
if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(0);
7385
else ptr = ChineseIntToString(z,JapaneseLegalSimplifiedDigits,JapaneseLegalSimplifiedBarriers,0);
7387
case NS_CHINESE_JAPANESE_WESTERN_MIX:
7388
if (ULT(z,10000)) ptr = PlaceIntToString(z,WESTERN_ZERO,10);
7389
else ptr = ChineseWesternIntToString(z,ChineseRegularSimplifiedDigits,
7390
JapaneseRegularSimplifiedBarriers);
7392
case NS_COMMON_BRAILLE:
7393
ptr = PlaceNonContiguousIntToString(z,CommonBrailleDigits,10);
7395
case NS_CYRILLIC_ALPHABETIC:
7396
ptr = CyrillicAlphabeticIntToString(z);
7399
ptr = PlaceIntToString(z,DEVANAGARI_ZERO,10);
7402
ptr = AdditiveIntToString(z,EgyptianData);
7405
ptr = EthiopicIntToString(z);
7407
case NS_EWELLIC_DECIMAL:
7408
ptr = PlaceIntToString(z,EWELLIC_ZERO,10);
7410
case NS_EWELLIC_HEX:
7411
ptr = PlaceIntToString(z,EWELLIC_ZERO,16);
7412
if(ptr) ptr = Prepend(ptr,0x0060);
7414
case NS_FRENCH_BRAILLE:
7415
ptr = PlaceNonContiguousIntToString(z,FrenchBrailleDigits,10);
7417
case NS_GLAGOLITIC_ALPHABETIC:
7418
ptr = AdditiveIntToString(z,GlagoliticData);
7419
if(ptr) FixGlagoliticTeens(ptr);
7421
case NS_GREEK_ALPHABETIC_LOWER:
7422
ptr = GreekAlphabeticIntToString(z,1);
7424
case NS_GREEK_ALPHABETIC_UPPER:
7425
ptr = GreekAlphabeticIntToString(z,0);
7428
ptr = PlaceIntToString(z,GUJARATI_ZERO,10);
7431
ptr = PlaceIntToString(z,GURMUKHI_ZERO,10);
7433
case NS_HEBREW_EARLY:
7434
ptr = HebrewIntToString(z,HebrewData,1);
7436
case NS_HEBREW_LATE:
7437
ptr = HebrewIntToString(z,HebrewData,0);
7440
ptr = WesternGeneralIntToString(z,16,0);
7441
if(ptr) ptr = Prepend(ptr,0x0078);
7442
if(ptr) ptr = Prepend(ptr,0x0030);
7445
ptr = WesternGeneralIntToString(z,16,1);
7446
if(ptr) ptr = Prepend(ptr,0x0078);
7447
if(ptr) ptr = Prepend(ptr,0x0030);
7450
ptr = PlaceIntToString(z,KANNADA_ZERO,10);
7453
ptr = KharoshthiIntToString(z);
7456
ptr = PlaceIntToString(z,KHMER_ZERO,10);
7459
ptr = PlaceIntToString(z,KLINGON_ZERO,10);
7462
ptr = PlaceIntToString(z,LAO_ZERO,10);
7465
ptr = PlaceIntToString(z,LIMBU_ZERO,10);
7468
ptr = PlaceIntToString(z,MALAYALAM_ZERO,10);
7471
ptr = PlaceIntToString(z,MONGOLIAN_ZERO,10);
7474
ptr = AdditiveIntToString(z,MxedruliData);
7476
case NS_NEW_TAI_LUE:
7477
ptr = PlaceIntToString(z,NEW_TAI_LUE_ZERO,10);
7480
ptr = PlaceIntToString(z,NKO_ZERO,10);
7483
ptr = AdditiveIntToString(z,OldItalicData);
7485
case NS_OLD_PERSIAN:
7486
ptr = AdditiveIntToString(z,OldPersianData);
7489
ptr = PlaceIntToString(z,ORIYA_ZERO,10);
7492
ptr = PlaceIntToString(z,OSMANYA_ZERO,10);
7495
ptr = AdditiveIntToString(z,PhoenicianData);
7497
case NS_ROMAN_UPPER:
7498
ptr = RomanIntToString(z,1);
7500
case NS_ROMAN_LOWER:
7501
ptr = RomanIntToString(z,0);
7503
case NS_RUSSIAN_BRAILLE:
7504
ptr = PlaceNonContiguousIntToString(z,RussianBrailleDigits,10);
7507
ptr = AdditiveIntToString(z,SinhalaData);
7509
case NS_CHINESE_SUZHOU:
7510
ptr = PlaceIntToString(z,SUZHOU_ZERO,10);
7511
if(ptr) FixSuzhou(ptr);
7513
case NS_TAMIL_PLACE:
7514
ptr = PlaceIntToString(z,TAMIL_ZERO,10);
7516
case NS_TAMIL_TRADITIONAL:
7517
ptr = TamilTraditionalIntToString(z);
7520
ptr = PlaceIntToString(z,TELUGU_ZERO,10);
7522
case NS_TENGWAR_DECIMAL:
7523
ptr = TengwarToString(z,10);
7525
case NS_TENGWAR_DUODECIMAL:
7526
ptr = TengwarToString(z,12);
7529
ptr = PlaceIntToString(z,THAI_ZERO,10);
7532
ptr = PlaceIntToString(z,TIBETAN_ZERO,10);
7535
ptr = PlaceIntToString(z,VERDURIAN_ZERO,10);
7537
case NS_WESTERN_LOWER:
7538
ptr = WesternGeneralIntToString(z,Uninum_Output_Base,0);
7540
case NS_WESTERN_UPPER:
7541
ptr = WesternGeneralIntToString(z,Uninum_Output_Base,1);
7543
case NS_XUCURI_LOWER:
7544
ptr = AdditiveIntToString(z,XucuriLowerData);
7546
case NS_XUCURI_UPPER:
7547
ptr = AdditiveIntToString(z,XucuriUpperData);
7550
uninum_err = NS_ERROR_NUMBER_SYSTEM_UNKNOWN;
7554
if(ptr && Uninum_Output_General_Group_Size){
7555
tmpptr =wcDelimitNumber(ptr,
7556
Uninum_Output_Group_Separator,
7557
Uninum_Output_Decimal_Separator,
7558
Uninum_Output_General_Group_Size,
7559
Uninum_Output_First_Group_Size);
7570
* Generate the list of available writing systems,
7572
* which = 0 -> list specific names usable in both directions
7573
* which = 1 -> list cover terms suitable only for conversion of string to int
7575
char *Tcl_ListNumberSystems (int which) {
7578
int CharsNeeded = 0;
7582
uninum_err = NS_ERROR_OKAY;
7583
Entries = sizeof(NumberSystemList)/sizeof(struct ns);
7584
for (i=0; i<Entries; i++) {
7585
if (NumberSystemList[i].type == (which? 2:1)) CharsNeeded += strlen(NumberSystemList[i].s);
7586
CharsNeeded += 1; /* For space */
7588
new = malloc(sizeof(char) * CharsNeeded);
7590
uninum_err = NS_ERROR_OUTOFMEMORY;
7594
for (i=0; i<Entries; i++) {
7595
if (NumberSystemList[i].type == (which? 2:1)) {
7596
p = strpcpy(p,NumberSystemList[i].s);
7603
int uninum_utf16len(UTF16 *s) {
7605
while(*s++ != 0) len++;
7609
char *UNStrToWNStr(UTF16 *s,char *sns){
7618
len = uninum_utf16len(s);
7620
tt = alloca((len+1) * sizeof(UTF32));
7622
tt = malloc((len+1) * sizeof(UTF32));
7625
for (i = 0; i < len; i++) *tptr++ = *s++;
7627
ns = StringToNumberSystem(sns);
7628
if(ns == NS_UNKNOWN) {
7629
uninum_err = NS_ERROR_NUMBER_SYSTEM_UNKNOWN;
7630
es = malloc(2 * sizeof(char));
7631
if(!es) exit(OUTOFMEMORY);
7636
StringToInt(&val,tt,NS_TYPE_STRING,ns);
7637
tcl_uninum_badchar = (UTF16) uninum_badchar;
7644
UCS2 *WNStrToUNStr(char *sns, char *NumberSystem){
7654
ns = StringToNumberSystem(NumberSystem);
7655
if(ns == NS_UNKNOWN) {
7656
uninum_err = NS_ERROR_NUMBER_SYSTEM_UNKNOWN;
7657
optr = malloc(2 * sizeof(UTF32));
7658
if(!optr) exit(OUTOFMEMORY);
7659
optr[0] = UNI_REPLACEMENT_CHAR;
7664
optr = IntToString(&val,ns,NS_TYPE_STRING);
7666
optr = malloc(2 * sizeof(UTF32));
7667
if(!optr) exit(OUTOFMEMORY);
7668
optr[0] = UNI_REPLACEMENT_CHAR;
7672
/* Check whether there are characters outside the BMP */
7674
while((c = *s++) != 0x0000){
7676
uninum_err = NS_ERROR_OUTSIDE_BMP;
7677
optr[0] = UNI_REPLACEMENT_CHAR;
7683
/* The C API generates UTF32. Convert this to UCS-2 (UTF-16 without surrogates) for Tcl */
7685
tclptr = malloc((len+1) * sizeof(UCS2));
7687
uninum_err = NS_ERROR_OUTOFMEMORY;
7693
while(*s != 0x0000) *t++ = (UTF16) (0x0000FFFF & *s++);
7699
char *StrGuessNumberSystem(UTF16 *s){
7706
len = uninum_utf16len(s);
7708
t = alloca((len+1) * sizeof(UTF32));
7710
t = malloc((len+1) * sizeof(UTF32));
7713
for (i = 0; i < len; i++) *tptr++ = *s++;
7715
ns = GuessNumberSystem(t);
7719
return(NumberSystemToString(ns));
7722
char *UninumNumberSystemMaximumValue (char *nsn){
7726
uninum_err = NS_ERROR_OKAY;
7727
ns = StringToNumberSystem(nsn);
7728
if(ns == NS_UNKNOWN) {
7729
uninum_err = NS_ERROR_NUMBER_SYSTEM_UNKNOWN;
7732
rval = UninumStringMaximumValue(ns);