~ubuntu-branches/ubuntu/oneiric/libuninum/oneiric

« back to all changes in this revision

Viewing changes to uninum.c

  • Committer: Bazaar Package Importer
  • Author(s): Bartosz Fenski
  • Date: 2007-10-11 11:51:01 UTC
  • Revision ID: james.westby@ubuntu.com-20071011115101-lthr3ez79qz2put5
Tags: upstream-2.6
ImportĀ upstreamĀ versionĀ 2.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Time-stamp: <2007-09-22 19:43:29 poser> */
 
2
/*
 
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.
 
7
 *
 
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.
 
12
 *
 
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
 
16
 */
 
17
 
 
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 )
 
30
 
 
31
/*
 
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. 
 
35
 */
 
36
 
 
37
 
 
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)
 
43
 
 
44
#define UNINUM
 
45
 
 
46
#include "config.h"
 
47
#include <stdlib.h>
 
48
#include <unistd.h>
 
49
#include <stdio.h>
 
50
#include <math.h>
 
51
#include <limits.h>
 
52
#include <ctype.h>
 
53
#include <wchar.h>
 
54
#include <string.h>
 
55
#include <strings.h>
 
56
#include <gmp.h>
 
57
#include "unicode.h"
 
58
#include "uninum.h"
 
59
#include "nsdefs.h"
 
60
#include "exitcode.h"
 
61
 
 
62
#ifdef HAVE_LOCALE_H
 
63
#include <locale.h>
 
64
#endif
 
65
 
 
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 */
 
70
 
 
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;
 
78
 
 
79
/* We're currently not dealing with non-integers - this is just forward-looking */
 
80
static UTF32 Uninum_Output_Decimal_Separator = 0x002E;
 
81
 
 
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
 
91
 
 
92
char *uninum_version(void) {
 
93
  return(VERSION);
 
94
}
 
95
 
 
96
#ifdef HAVE_LOCALECONV
 
97
#ifdef HAVE_SETLOCALE
 
98
void GetLocaleGroupInfo (){
 
99
  struct lconv *lcptr;
 
100
 
 
101
  setlocale(LC_NUMERIC,"");
 
102
  lcptr = localeconv();
 
103
  if(lcptr == NULL) {
 
104
    fprintf(stderr,"Attempt to obtain locale information was unsuccessful.\n");
 
105
    return;
 
106
  }
 
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;
 
111
}
 
112
#endif
 
113
#endif
 
114
 
 
115
 
 
116
/* Auxiliary functions */
 
117
 
 
118
unsigned long ipow(int base, int cnt) {
 
119
  int i;
 
120
  unsigned long Result;
 
121
 
 
122
  i = 1;
 
123
  Result = 1;
 
124
  while (i++ <= cnt) Result *=  base;
 
125
  return Result;
 
126
 
127
 
 
128
/* 
 
129
 * Copy a string and return a pointer to the
 
130
 * terminal null of the copy. The target must
 
131
 * have sufficient storage.
 
132
 */
 
133
static char *strpcpy(char *dest, const char *src) {
 
134
  char *t;
 
135
  const char *s;
 
136
 
 
137
  s = src;
 
138
  t = dest;
 
139
  while (*s != 0) {
 
140
    *t++ = *s++;
 
141
  }
 
142
  *t = 0;
 
143
  return(t);
 
144
}
 
145
 
 
146
/* 
 
147
 * Case-insenstive ascii string comparison.
 
148
 * Emulates BSD 4.4 function emulated by GNU
 
149
*/
 
150
static int mystrcasecmp(char *a, char *b) {
 
151
  char ac;
 
152
  char bc;
 
153
  while(*a != '\0') {
 
154
    ac = tolower(*a++);
 
155
    bc = tolower(*b++);
 
156
    if(ac < bc) return (-1);
 
157
    if(ac > bc) return (1);
 
158
  }
 
159
  if(*b != '\0') return (-1);
 
160
  return (0);
 
161
}
 
162
 
 
163
/* 
 
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().
 
168
 */
 
169
static UTF32 *ucpcpy(UTF32 *dest, const UTF32 *src) {
 
170
  UTF32 *t;
 
171
  const UTF32 *s;
 
172
 
 
173
  s = src;
 
174
  t = dest;
 
175
  while (*s != 0x0000) {
 
176
    *t++ = *s++;
 
177
  }
 
178
  *t = 0x0000;
 
179
  return(t);
 
180
}
 
181
 
 
182
/* 
 
183
 * Reverse a wide string in place.
 
184
 */
 
185
static UTF32 *wcsrev(UTF32 *s) {
 
186
  UTF32 *p;
 
187
  UTF32 *q;
 
188
  UTF32 *h;
 
189
  UTF32 t;
 
190
 
 
191
  p = s;
 
192
  q = s + ucslen(s)-1;
 
193
  h = s + (ucslen(s)/2);
 
194
  while (q >= h) {
 
195
    t = *p;
 
196
    *p++ = *q;
 
197
    *q-- = t;
 
198
  }
 
199
  return(s);
 
200
}
 
201
 
 
202
/* 
 
203
 * Prepend a character to a string, returning new storage
 
204
 * and freeing the old.
 
205
 */
 
206
static UTF32 *Prepend(UTF32 *s, UTF32 c) {
 
207
  int len;
 
208
  UTF32 *new;
 
209
 
 
210
  len = ucslen(s);
 
211
  new = malloc(sizeof(UTF32) * (len + 2));
 
212
  if(new) {
 
213
    new[0] = c;
 
214
    new[1] = 0x0000;
 
215
    ucscpy(new+1,s);
 
216
  }
 
217
  free(s);
 
218
  return(new);
 
219
}
 
220
 
 
221
/* Remove "thousands separator"s */
 
222
UTF32 *wcStripSeparators(UTF32 *s) {
 
223
  UTF32 *t;
 
224
  UTF32 *o;
 
225
  UTF32 c;
 
226
  o = t = s;
 
227
 
 
228
  while ((c = *s++) != 0x0000){
 
229
    switch(c) {
 
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" */
 
239
      break;
 
240
    default:
 
241
      *t++ = c;
 
242
    }
 
243
  }
 
244
  *t = 0x0000;
 
245
  return o;
 
246
}
 
247
 
 
248
 
 
249
/* 
 
250
 * It is the caller's responsability to free the original storage.
 
251
 */
 
252
UTF32 *wcDelimitNumber(
 
253
         UTF32 *number,
 
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 */
 
258
         )
 
259
{
 
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 */
 
266
  int i;
 
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 */
 
272
 
 
273
  /* Sanity check */
 
274
  if( (GroupSize < 2) || (FirstGroupSize < 2)) {
 
275
    commas = 0;
 
276
    goto newmem;
 
277
  }
 
278
 
 
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;
 
286
 
 
287
  digits = 1+point - Non_Space_Number;
 
288
  if(digits > FirstGroupSize) { 
 
289
    commas = 1 +  ((digits-FirstGroupSize-1)/GroupSize);
 
290
  }
 
291
  else commas = 0;
 
292
 
 
293
 newmem:
 
294
  New_Size = length + commas;
 
295
  new = (UTF32 *) malloc((New_Size + 1) * sizeof(UTF32));
 
296
  if(new){
 
297
    if (commas == 0) return ucscpy(new,number);
 
298
 
 
299
    /* First copy right hand part of number, up to and including decimal point */
 
300
    pos = number+length;
 
301
    npos = new+New_Size;
 
302
    for(; pos > point;) *npos-- = *pos--;
 
303
 
 
304
    /* Now copy lefthand part, inserting delimiters as we go */
 
305
    Comma_Cnt = cnt = 0;
 
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 */
 
310
      Comma_Cnt = cnt = 1;
 
311
    }
 
312
    while(pos >= Non_Space_Number){
 
313
      *npos-- = *pos--;
 
314
      if( (++cnt % GroupSize == 0) && (Comma_Cnt++ < commas )) *npos-- = (UTF32) gs;
 
315
    }
 
316
 
 
317
    while(pos >= number) *npos-- = *pos--; /* Copy leading spaces, if any */
 
318
    return new;
 
319
  }
 
320
}
 
321
 
 
322
/*
 
323
 * Returns a null-terminated wide string containing
 
324
 * the specified character.
 
325
 */
 
326
static UTF32 *MakeSingleDigitString(UTF32 c) {
 
327
  UTF32 *new;
 
328
  new = malloc(sizeof(UTF32) * 2);
 
329
  if(!new) {
 
330
    uninum_err = NS_ERROR_OUTOFMEMORY;
 
331
    return NULL;
 
332
  }
 
333
  new[0] = c;
 
334
  new[1] = 0L;
 
335
  return(new);
 
336
}
 
337
 
 
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
 
428
};
 
429
 
 
430
/* 
 
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
 
434
 * sequence.
 
435
 *
 
436
 * which = 0 -> list specific names usable in both directions
 
437
 * which = 1 -> list cover terms suitable only for conversion of string to int
 
438
 */
 
439
char *ListNumberSystems (int flag, int which) {
 
440
  static int i = 0;
 
441
 
 
442
  if(flag == 0) i = 0;          /* reset */
 
443
 
 
444
top:  if (i < (sizeof(NumberSystemList)/sizeof(struct ns))) {
 
445
    if (NumberSystemList[i].type == (which? 2:1)) return NumberSystemList[i++].s;
 
446
    else {
 
447
      i++;
 
448
      goto top;
 
449
    }
 
450
  }
 
451
  i = 0;
 
452
  return NULL;
 
453
}
 
454
 
 
455
/*
 
456
 * We just use linear search for the time being.
 
457
 * Could switch to binary search for greater speed.
 
458
 */
 
459
 
 
460
int StringToNumberSystem (char *s) {
 
461
  int i;
 
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);
 
466
    }
 
467
  }
 
468
  return NS_UNKNOWN;
 
469
}
 
470
 
 
471
/*
 
472
 * We just use linear search for the time being.
 
473
 * Could switch to binary search for greater speed.
 
474
 */
 
475
 
 
476
char *NumberSystemToString (int ns) {
 
477
  int i;
 
478
  for (i=0; i < (sizeof(NumberSystemList)/sizeof(struct ns)); i++) {
 
479
    if (NumberSystemList[i].c == ns) return NumberSystemList[i].s;
 
480
  }
 
481
  return NULL;
 
482
}
 
483
 
 
484
/* 
 
485
 * Return the maximum value expressible in the specified number system.
 
486
 * as a decimal ascii string, or if there is no limit, "unlimited".
 
487
 */
 
488
 
 
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
 
506
 
 
507
char *UninumStringMaximumValue(int ns) {
 
508
  char *new;
 
509
  mpz_t MaxChinese;
 
510
  mpz_t Limit;
 
511
 
 
512
  mpz_init(Limit);
 
513
 
 
514
  switch(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);
 
533
    return new;
 
534
  case NS_AEGEAN:
 
535
    mpz_set_ui(Limit,AEGEAN_LIMIT);
 
536
    break;
 
537
  case NS_ARABIC_ALPHABETIC:
 
538
    mpz_set_ui(Limit,ARABIC_LIMIT);
 
539
    break;
 
540
  case NS_ARMENIAN_ALPHABETIC:
 
541
    mpz_set_ui(Limit,ARMENIAN_LIMIT);
 
542
    break;
 
543
  case NS_CYRILLIC_ALPHABETIC:
 
544
    mpz_set_ui(Limit,CYRILLIC_LIMIT);
 
545
    break;
 
546
  case NS_EGYPTIAN:
 
547
    mpz_set_ui(Limit,EGYPTIAN_LIMIT);
 
548
    break;
 
549
  case NS_GLAGOLITIC_ALPHABETIC:
 
550
    mpz_set_ui(Limit,GLAGOLITIC_LIMIT);
 
551
    break;
 
552
  case NS_GREEK_ALPHABETIC_UPPER:
 
553
  case NS_GREEK_ALPHABETIC_LOWER:
 
554
    mpz_set_ui(Limit,GREEK_LIMIT);
 
555
    break;
 
556
  case NS_HEBREW_EARLY:
 
557
  case NS_HEBREW_LATE:
 
558
    mpz_set_ui(Limit,HEBREW_LIMIT);
 
559
    break;
 
560
  case NS_KHAROSHTHI:
 
561
    mpz_set_ui(Limit,KHAROSHTHI_LIMIT);
 
562
    break;
 
563
  case NS_MXEDRULI:
 
564
    mpz_set_ui(Limit,MXEDRULI_LIMIT);
 
565
    break;
 
566
  case NS_OLD_ITALIC:
 
567
    mpz_set_ui(Limit,OLD_ITALIC_LIMIT);
 
568
    break;
 
569
  case NS_OLD_PERSIAN:
 
570
    mpz_set_ui(Limit,OLD_PERSIAN_LIMIT);
 
571
    break;
 
572
  case NS_PHOENICIAN:
 
573
    mpz_set_ui(Limit,PHOENICIAN_LIMIT);
 
574
    break;
 
575
  case NS_ROMAN_UPPER:
 
576
  case NS_ROMAN_LOWER:
 
577
    mpz_set_ui(Limit,ROMAN_LIMIT);
 
578
    break;
 
579
  case NS_SINHALA:
 
580
    mpz_set_ui(Limit,SINHALA_LIMIT);
 
581
    break;
 
582
  case NS_TAMIL_TRADITIONAL:
 
583
    mpz_set_ui(Limit,TAMIL_LIMIT);
 
584
    break;
 
585
  case NS_XUCURI_LOWER:
 
586
  case NS_XUCURI_UPPER:
 
587
    mpz_set_ui(Limit,XUCURI_LIMIT);
 
588
    break;
 
589
  default:
 
590
    new = malloc (sizeof(char) * (1 + strlen("unlimited")));
 
591
    if(!new) {uninum_err = NS_ERROR_OUTOFMEMORY;return NULL;}
 
592
    sprintf(new,"%s","unlimited");
 
593
    return new;
 
594
  }
 
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);
 
598
  mpz_clear(Limit);
 
599
  return new;
 
600
}
 
601
 
 
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
 
709
 
 
710
 
 
711
int GuessNumberSystem(UTF32 *str){
 
712
  UTF32 c;
 
713
  UTF32 *s;
 
714
  int WesternCnt = 0;
 
715
  int ZeroCnt = 0;
 
716
  int len;
 
717
  short FirstIsGraveP = 0;
 
718
 
 
719
  uninum_err = NS_ERROR_OKAY;
 
720
  if (!str) return (NS_UNKNOWN);
 
721
  len = ucslen(str);
 
722
  s = str;
 
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;
 
733
    }
 
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;
 
744
    }
 
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;
 
752
    }
 
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;
 
796
    }
 
797
    if ((c == 0x0049) ||
 
798
        (c == 0x0056) ||
 
799
        (c == 0x0058) ||
 
800
        (c == 0x004C) ||
 
801
        (c == 0x0043) ||
 
802
        (c == 0x0044) ||
 
803
        (c == 0x004D) ||
 
804
        (c == 0x2183) ||
 
805
        ( (c >= 0x2160) && (c <= 0x216F))) return NS_ROMAN_UPPER; 
 
806
    if ((c == 0x0069) ||
 
807
        (c == 0x0076) ||
 
808
        (c == 0x0078) ||
 
809
        (c == 0x006C) ||
 
810
        (c == 0x0063) ||
 
811
        (c == 0x0064) ||
 
812
        (c == 0x006D) ||
 
813
        (c == 0x2184) ||
 
814
        ( (c >= 0x2170) && (c <= 0x217F))) return NS_ROMAN_LOWER;
 
815
    if ((c == 0x281A) ||
 
816
        (c == 0x2801) ||
 
817
        (c == 0x2803) ||
 
818
        (c == 0x2809) ||
 
819
        (c == 0x2819) ||
 
820
        (c == 0x2811) ||
 
821
        (c == 0x280B) ||
 
822
        (c == 0x281B) ||
 
823
        (c == 0x2813) ||
 
824
        (c == 0x280A)) return NS_COMMON_BRAILLE;
 
825
    if ((c == 0x283C) ||
 
826
        (c == 0x2821) ||
 
827
        (c == 0x2823) ||
 
828
        (c == 0x2829) ||
 
829
        (c == 0x2839) ||
 
830
        (c == 0x2831) ||
 
831
        (c == 0x282B) ||
 
832
        (c == 0x283B) ||
 
833
        (c == 0x2833) ||
 
834
        (c == 0x282A)) return NS_FRENCH_BRAILLE;
 
835
    if ((c == 0x2834) ||
 
836
        (c == 0x2802) ||
 
837
        (c == 0x2806) ||
 
838
        (c == 0x2812) ||
 
839
        (c == 0x2832) ||
 
840
        (c == 0x2822) ||
 
841
        (c == 0x2816) ||
 
842
        (c == 0x2836) ||
 
843
        (c == 0x2826) ||
 
844
        (c == 0x2814)) return NS_RUSSIAN_BRAILLE;
 
845
    if ((c >= 0x31 ) && (c <= 0x39)) {WesternCnt++;continue;}
 
846
    if (c == 0x0030) {ZeroCnt++;WesternCnt++;continue;}
 
847
  }
 
848
  if(ZeroCnt == len) return (NS_ALLZERO);
 
849
  if(WesternCnt == len) return(NS_WESTERN_GENERIC);
 
850
  return (NS_UNKNOWN);
 
851
}
 
852
 
 
853
/* String to Integer conversion functions */
 
854
 
 
855
static void ArabicToInt(mpz_t mpzResult, UTF32 *s) {
 
856
  unsigned long CurrentValue; 
 
857
  UTF32 c;
 
858
  char *rs;
 
859
  mpz_t Result;
 
860
 
 
861
  uninum_err = NS_ERROR_OKAY;
 
862
  mpz_init(Result);
 
863
 
 
864
  while ( (c = *s++) != 0x0000) {
 
865
    switch (c) {
 
866
    case 0x0660:
 
867
      CurrentValue = 0;
 
868
      break;
 
869
    case 0x0661:
 
870
      CurrentValue = 1;
 
871
      break;
 
872
     case 0x0662:
 
873
      CurrentValue = 2;
 
874
      break;
 
875
    case 0x0663:
 
876
      CurrentValue = 3;
 
877
      break;
 
878
    case 0x0664:
 
879
      CurrentValue = 4;
 
880
      break;
 
881
    case 0x0665:
 
882
      CurrentValue = 5;
 
883
      break;
 
884
    case 0x0666:
 
885
      CurrentValue = 6;
 
886
      break;
 
887
    case 0x0667:
 
888
      CurrentValue = 7;
 
889
      break;
 
890
    case 0x0668:
 
891
      CurrentValue = 8;
 
892
      break;
 
893
    case 0x0669:
 
894
      CurrentValue = 9;
 
895
      break;
 
896
    default:                    /* Error */
 
897
      uninum_err = NS_ERROR_BADCHARACTER;
 
898
      uninum_badchar = c;
 
899
      mpz_clear(Result);
 
900
      return;
 
901
    }
 
902
    mpz_mul_ui(Result, Result, 10L);
 
903
    mpz_add_ui(Result, Result, CurrentValue);
 
904
  }
 
905
  mpz_init_set(mpzResult, Result);
 
906
  mpz_clear(Result);
 
907
}
 
908
 
 
909
static void ArabicExtendedToInt(mpz_t mpzResult, UTF32 *s) {
 
910
  unsigned long CurrentValue; 
 
911
  UTF32 c;
 
912
  mpz_t Result;
 
913
 
 
914
  uninum_err = NS_ERROR_OKAY;
 
915
  mpz_init(Result);
 
916
 
 
917
  while ( (c = *s++) != 0x0000) {
 
918
    switch (c) {
 
919
    case 0x06F0:
 
920
      CurrentValue = 0;
 
921
      break;
 
922
    case 0x06F1:
 
923
      CurrentValue = 1;
 
924
      break;
 
925
     case 0x06F2:
 
926
      CurrentValue = 2;
 
927
      break;
 
928
    case 0x06F3:
 
929
      CurrentValue = 3;
 
930
      break;
 
931
    case 0x06F4:
 
932
      CurrentValue = 4;
 
933
      break;
 
934
    case 0x06F5:
 
935
      CurrentValue = 5;
 
936
      break;
 
937
    case 0x06F6:
 
938
      CurrentValue = 6;
 
939
      break;
 
940
    case 0x06F7:
 
941
      CurrentValue = 7;
 
942
      break;
 
943
    case 0x06F8:
 
944
      CurrentValue = 8;
 
945
      break;
 
946
    case 0x06F9:
 
947
      CurrentValue = 9;
 
948
      break;
 
949
    default:                    /* Error */
 
950
      uninum_err = NS_ERROR_BADCHARACTER;
 
951
      uninum_badchar = c;
 
952
      mpz_clear(Result);
 
953
      return;
 
954
    }
 
955
    mpz_mul_ui(Result, Result, 10L);
 
956
    mpz_add_ui(Result, Result, CurrentValue);
 
957
  }
 
958
  mpz_init_set(mpzResult, Result);
 
959
  mpz_clear(Result);
 
960
}
 
961
 
 
962
static void ArabicAlphabeticToInt(mpz_t mpzResult, UTF32 *s) {
 
963
  unsigned long CurrentValue; 
 
964
  UTF32 c;
 
965
  mpz_t Result;
 
966
 
 
967
  uninum_err = NS_ERROR_OKAY;
 
968
  mpz_init(Result);
 
969
 
 
970
  while ( (c = *s++) != 0x0000) {
 
971
    switch (c) {
 
972
    case 0x0627:
 
973
      CurrentValue = 1;
 
974
      break;
 
975
    case 0x0628:
 
976
      CurrentValue = 2;
 
977
      break;
 
978
    case 0x062C:
 
979
      CurrentValue = 3;
 
980
      break;
 
981
    case 0x062F:
 
982
      CurrentValue = 4;
 
983
      break;
 
984
    case 0x0647:
 
985
      CurrentValue = 5;
 
986
      break;
 
987
    case 0x0648:
 
988
      CurrentValue = 6;
 
989
      break;
 
990
    case 0x0632:
 
991
      CurrentValue = 7;
 
992
      break;
 
993
    case 0x062D:
 
994
      CurrentValue = 8;
 
995
      break;
 
996
    case 0x0637:
 
997
      CurrentValue = 9;
 
998
      break;
 
999
    case 0x064A:
 
1000
      CurrentValue = 10;
 
1001
      break;
 
1002
    case 0x0643:
 
1003
      CurrentValue = 20;
 
1004
      break;
 
1005
    case 0x0644:
 
1006
      CurrentValue = 30;
 
1007
      break;
 
1008
    case 0x0645:
 
1009
      CurrentValue = 40;
 
1010
      break;
 
1011
    case 0x0646:
 
1012
      CurrentValue = 50;
 
1013
      break;
 
1014
    case 0x0633:
 
1015
      CurrentValue = 60;
 
1016
      break;
 
1017
    case 0x0639:
 
1018
      CurrentValue = 70;
 
1019
      break;
 
1020
    case 0x0641:
 
1021
      CurrentValue = 80;
 
1022
      break;
 
1023
    case 0x0635:
 
1024
      CurrentValue = 90;
 
1025
      break;
 
1026
    case 0x0642:
 
1027
      CurrentValue = 100;
 
1028
      break;
 
1029
    case 0x0631:
 
1030
      CurrentValue = 200;
 
1031
      break;
 
1032
    case 0x0634:
 
1033
      CurrentValue = 300;
 
1034
      break;
 
1035
    case 0x062A:
 
1036
      CurrentValue = 400;
 
1037
      break;
 
1038
    case 0x062B:
 
1039
      CurrentValue = 500;
 
1040
      break;
 
1041
    case 0x062E:
 
1042
      CurrentValue = 600;
 
1043
      break;
 
1044
    case 0x0630:
 
1045
      CurrentValue = 700;
 
1046
      break;
 
1047
    case 0x0636:
 
1048
      CurrentValue = 800;
 
1049
      break;
 
1050
    case 0x0638:
 
1051
      CurrentValue = 900;
 
1052
      break;
 
1053
    case 0x063A:
 
1054
      CurrentValue = 1000;
 
1055
      break;
 
1056
    default:                    /* Error */
 
1057
      uninum_err = NS_ERROR_BADCHARACTER;
 
1058
      uninum_badchar = c;
 
1059
      mpz_clear(Result);
 
1060
      return;
 
1061
    }
 
1062
    mpz_add_ui(Result, Result, CurrentValue);
 
1063
  }
 
1064
  mpz_init_set(mpzResult, Result);
 
1065
  mpz_clear(Result);
 
1066
  return;
 
1067
}
 
1068
 
 
1069
static void AegeanToInt(mpz_t mpzResult, UTF32 *s) {
 
1070
  unsigned long CurrentValue; 
 
1071
  UTF32 c;
 
1072
  mpz_t Result;
 
1073
 
 
1074
  uninum_err = NS_ERROR_OKAY;
 
1075
  mpz_init(Result);
 
1076
 
 
1077
  while ( (c = *s++) != 0x0000) {
 
1078
    switch (c) {
 
1079
    case 0x10107:
 
1080
      CurrentValue = 1;
 
1081
      break;
 
1082
    case 0x10108:
 
1083
      CurrentValue = 2;
 
1084
      break;
 
1085
    case 0x10109:
 
1086
      CurrentValue = 3;
 
1087
      break;
 
1088
    case 0x1010A:
 
1089
      CurrentValue = 4;
 
1090
      break;
 
1091
    case 0x1010B:
 
1092
      CurrentValue = 5;
 
1093
      break;
 
1094
    case 0x1010C:
 
1095
      CurrentValue = 6;
 
1096
      break;
 
1097
    case 0x1010D:
 
1098
      CurrentValue = 7;
 
1099
      break;
 
1100
    case 0x1010E:
 
1101
      CurrentValue = 8;
 
1102
      break;
 
1103
    case 0x1010F:
 
1104
      CurrentValue = 9;
 
1105
      break;
 
1106
    case 0x10110:
 
1107
      CurrentValue = 10;
 
1108
      break;
 
1109
    case 0x10111:
 
1110
      CurrentValue = 20;
 
1111
      break;
 
1112
    case 0x10112:
 
1113
      CurrentValue = 30;
 
1114
      break;
 
1115
    case 0x10113:
 
1116
      CurrentValue = 40;
 
1117
      break;
 
1118
    case 0x10114:
 
1119
      CurrentValue = 50;
 
1120
      break;
 
1121
    case 0x10115:
 
1122
      CurrentValue = 60;
 
1123
      break;
 
1124
    case 0x10116:
 
1125
      CurrentValue = 70;
 
1126
      break;
 
1127
    case 0x10117:
 
1128
      CurrentValue = 80;
 
1129
      break;
 
1130
    case 0x10118:
 
1131
      CurrentValue = 90;
 
1132
      break;
 
1133
    case 0x10119:
 
1134
      CurrentValue = 100;
 
1135
      break;
 
1136
    case 0x1011A:
 
1137
      CurrentValue = 200;
 
1138
      break;
 
1139
    case 0x1011B:
 
1140
      CurrentValue = 300;
 
1141
      break;
 
1142
    case 0x1011C:
 
1143
      CurrentValue = 400;
 
1144
      break;
 
1145
    case 0x1011D:
 
1146
      CurrentValue = 500;
 
1147
      break;
 
1148
    case 0x1011E:
 
1149
      CurrentValue = 600;
 
1150
      break;
 
1151
    case 0x1011F:
 
1152
      CurrentValue = 700;
 
1153
      break;
 
1154
    case 0x10120:
 
1155
      CurrentValue = 800;
 
1156
      break;
 
1157
    case 0x10121:
 
1158
      CurrentValue = 900;
 
1159
      break;
 
1160
    case 0x10122:
 
1161
      CurrentValue = 1000;
 
1162
      break;
 
1163
    case 0x10123:
 
1164
      CurrentValue = 2000;
 
1165
      break;
 
1166
    case 0x10124:
 
1167
      CurrentValue = 3000;
 
1168
      break;
 
1169
    case 0x10125:
 
1170
      CurrentValue = 4000;
 
1171
      break;
 
1172
    case 0x10126:
 
1173
      CurrentValue = 5000;
 
1174
      break;
 
1175
    case 0x10127:
 
1176
      CurrentValue = 6000;
 
1177
      break;
 
1178
    case 0x10128:
 
1179
      CurrentValue = 7000;
 
1180
      break;
 
1181
    case 0x10129:
 
1182
      CurrentValue = 8000;
 
1183
      break;
 
1184
    case 0x1012A:
 
1185
      CurrentValue = 9000;
 
1186
      break;
 
1187
    case 0x1012B:
 
1188
      CurrentValue = 10000;
 
1189
      break;
 
1190
    case 0x1012C:
 
1191
      CurrentValue = 20000;
 
1192
      break;
 
1193
    case 0x1012D:
 
1194
      CurrentValue = 30000;
 
1195
      break;
 
1196
    case 0x1012E:
 
1197
      CurrentValue = 40000;
 
1198
      break;
 
1199
    case 0x1012F:
 
1200
      CurrentValue = 50000;
 
1201
      break;
 
1202
    case 0x10130:
 
1203
      CurrentValue = 60000;
 
1204
      break;
 
1205
    case 0x10131:
 
1206
      CurrentValue = 70000;
 
1207
      break;
 
1208
    case 0x10132:
 
1209
      CurrentValue = 80000;
 
1210
      break;
 
1211
    case 0x10133:
 
1212
      CurrentValue = 90000;
 
1213
      break;
 
1214
    default:                    /* Error */
 
1215
      uninum_err = NS_ERROR_BADCHARACTER;
 
1216
      uninum_badchar = c;
 
1217
      mpz_clear(Result);
 
1218
      return;
 
1219
    }
 
1220
    mpz_add_ui(Result, Result, CurrentValue);
 
1221
  }
 
1222
  mpz_init_set(mpzResult, Result);
 
1223
  mpz_clear(Result);
 
1224
  return;
 
1225
}
 
1226
 
 
1227
static void ArmenianAlphabeticToInt(mpz_t mpzResult, UTF32 *s) {
 
1228
  unsigned long CurrentValue; 
 
1229
  UTF32 c;
 
1230
  mpz_t Result;
 
1231
 
 
1232
  uninum_err = NS_ERROR_OKAY;
 
1233
  mpz_init(Result);
 
1234
 
 
1235
  while ( (c = *s++) != 0x0000) {
 
1236
    switch (c) {
 
1237
    case 0x0531:
 
1238
      CurrentValue = 1;
 
1239
      break;
 
1240
    case 0x0532:
 
1241
      CurrentValue = 2;
 
1242
      break;
 
1243
    case 0x0533:
 
1244
      CurrentValue = 3;
 
1245
      break;
 
1246
    case 0x0534:
 
1247
      CurrentValue = 4;
 
1248
      break;
 
1249
    case 0x0535:
 
1250
      CurrentValue = 5;
 
1251
      break;
 
1252
    case 0x0536:
 
1253
      CurrentValue = 6;
 
1254
      break;
 
1255
    case 0x0537:
 
1256
      CurrentValue = 7;
 
1257
      break;
 
1258
    case 0x0538:
 
1259
      CurrentValue = 8;
 
1260
      break;
 
1261
    case 0x0539:
 
1262
      CurrentValue = 9;
 
1263
      break;
 
1264
    case 0x053A:
 
1265
      CurrentValue = 10;
 
1266
      break;
 
1267
    case 0x053B:
 
1268
      CurrentValue = 20;
 
1269
      break;
 
1270
    case 0x053C:
 
1271
      CurrentValue = 30;
 
1272
      break;
 
1273
    case 0x053D:
 
1274
      CurrentValue = 40;
 
1275
      break;
 
1276
    case 0x053E:
 
1277
      CurrentValue = 50;
 
1278
      break;
 
1279
    case 0x053F:
 
1280
      CurrentValue = 60;
 
1281
      break;
 
1282
    case 0x0540:
 
1283
      CurrentValue = 70;
 
1284
      break;
 
1285
    case 0x0541:
 
1286
      CurrentValue = 80;
 
1287
      break;
 
1288
    case 0x0542:
 
1289
      CurrentValue = 90;
 
1290
      break;
 
1291
    case 0x0543:
 
1292
      CurrentValue = 100;
 
1293
      break;
 
1294
    case 0x0544:
 
1295
      CurrentValue = 200;
 
1296
      break;
 
1297
    case 0x0545:
 
1298
      CurrentValue = 300;
 
1299
      break;
 
1300
    case 0x0546:
 
1301
      CurrentValue = 400;
 
1302
      break;
 
1303
    case 0x0547:
 
1304
      CurrentValue = 500;
 
1305
      break;
 
1306
    case 0x0548:
 
1307
      CurrentValue = 600;
 
1308
      break;
 
1309
    case 0x0549:
 
1310
      CurrentValue = 700;
 
1311
      break;
 
1312
    case 0x054A:
 
1313
      CurrentValue = 800;
 
1314
      break;
 
1315
    case 0x054B:
 
1316
      CurrentValue = 900;
 
1317
      break;
 
1318
    case 0x054C:
 
1319
      CurrentValue = 1000;
 
1320
      break;
 
1321
    case 0x054D:
 
1322
      CurrentValue = 2000;
 
1323
      break;
 
1324
    case 0x054E:
 
1325
      CurrentValue = 3000;
 
1326
      break;
 
1327
    case 0x054F:
 
1328
      CurrentValue = 4000;
 
1329
      break;
 
1330
    case 0x0550:
 
1331
      CurrentValue = 5000;
 
1332
      break;
 
1333
    case 0x0551:
 
1334
      CurrentValue = 6000;
 
1335
      break;
 
1336
    case 0x0552:
 
1337
      CurrentValue = 7000;
 
1338
      break;
 
1339
    case 0x0553:
 
1340
      CurrentValue = 8000;
 
1341
      break;
 
1342
    case 0x0554:
 
1343
      CurrentValue = 9000;
 
1344
      break;
 
1345
    default:                    /* Error */
 
1346
      uninum_err = NS_ERROR_BADCHARACTER;
 
1347
      uninum_badchar = c;
 
1348
      mpz_clear(Result);
 
1349
      return;
 
1350
    }
 
1351
    mpz_add_ui(Result, Result, CurrentValue);
 
1352
  }
 
1353
  mpz_init_set(mpzResult, Result);
 
1354
  mpz_clear(Result);
 
1355
  return;
 
1356
}
 
1357
 
 
1358
static void BalineseToInt(mpz_t mpzResult, UTF32 *s) {
 
1359
  unsigned long CurrentValue; 
 
1360
  UTF32 c;
 
1361
  mpz_t Result;
 
1362
 
 
1363
  uninum_err = NS_ERROR_OKAY;
 
1364
  mpz_init(Result);
 
1365
 
 
1366
  while ( (c = *s++) != 0x0000) {
 
1367
    switch (c) {
 
1368
    case 0x1B50:
 
1369
      CurrentValue = 0;
 
1370
      break;
 
1371
    case 0x1B51:
 
1372
      CurrentValue = 1;
 
1373
      break;
 
1374
    case 0x1B52:
 
1375
      CurrentValue = 2;
 
1376
      break;
 
1377
    case 0x1B53:
 
1378
      CurrentValue = 3;
 
1379
      break;
 
1380
    case 0x1B54:
 
1381
      CurrentValue = 4;
 
1382
      break;
 
1383
    case 0x1B55:
 
1384
      CurrentValue = 5;
 
1385
      break;
 
1386
    case 0x1B56:
 
1387
      CurrentValue = 6;
 
1388
      break;
 
1389
    case 0x1B57:
 
1390
      CurrentValue = 7;
 
1391
      break;
 
1392
    case 0x1B58:
 
1393
      CurrentValue = 8;
 
1394
      break;
 
1395
    case 0x1B59:
 
1396
      CurrentValue = 9;
 
1397
      break;
 
1398
    default:                    /* Error */
 
1399
      uninum_err = NS_ERROR_BADCHARACTER;
 
1400
      uninum_badchar = c;
 
1401
      mpz_clear(Result);
 
1402
      return;
 
1403
    }
 
1404
    mpz_mul_ui(Result, Result, 10L);
 
1405
    mpz_add_ui(Result, Result, CurrentValue);
 
1406
  }
 
1407
  mpz_init_set(mpzResult, Result);
 
1408
  mpz_clear(Result);
 
1409
}
 
1410
 
 
1411
static void BengaliToInt(mpz_t mpzResult, UTF32 *s) {
 
1412
  unsigned long CurrentValue; 
 
1413
  UTF32 c;
 
1414
  mpz_t Result;
 
1415
 
 
1416
  uninum_err = NS_ERROR_OKAY;
 
1417
  mpz_init(Result);
 
1418
 
 
1419
  while ( (c = *s++) != 0x0000) {
 
1420
    switch (c) {
 
1421
    case 0x09E6:
 
1422
      CurrentValue = 0;
 
1423
      break;
 
1424
    case 0x09E7:
 
1425
      CurrentValue = 1;
 
1426
      break;
 
1427
    case 0x09E8:
 
1428
      CurrentValue = 2;
 
1429
      break;
 
1430
    case 0x09E9:
 
1431
      CurrentValue = 3;
 
1432
      break;
 
1433
    case 0x09EA:
 
1434
      CurrentValue = 4;
 
1435
      break;
 
1436
    case 0x09EB:
 
1437
      CurrentValue = 5;
 
1438
      break;
 
1439
    case 0x09EC:
 
1440
      CurrentValue = 6;
 
1441
      break;
 
1442
    case 0x09ED:
 
1443
      CurrentValue = 7;
 
1444
         break;
 
1445
    case 0x09EE:
 
1446
      CurrentValue = 8;
 
1447
      break;
 
1448
    case 0x09EF:
 
1449
      CurrentValue = 9;
 
1450
      break;
 
1451
    default:                    /* Error */
 
1452
      uninum_err = NS_ERROR_BADCHARACTER;
 
1453
      uninum_badchar = c;
 
1454
      mpz_clear(Result);
 
1455
      return;
 
1456
    }
 
1457
    mpz_mul_ui(Result, Result, 10L);
 
1458
    mpz_add_ui(Result, Result, CurrentValue);
 
1459
  }
 
1460
  mpz_init_set(mpzResult, Result);
 
1461
  mpz_clear(Result);
 
1462
}
 
1463
 
 
1464
static void BurmeseToInt(mpz_t mpzResult, UTF32 *s) {
 
1465
  unsigned long CurrentValue; 
 
1466
  UTF32 c;
 
1467
  mpz_t Result;
 
1468
 
 
1469
  uninum_err = NS_ERROR_OKAY;
 
1470
  mpz_init(Result);
 
1471
 
 
1472
  while ( (c = *s++) != 0x0000) {
 
1473
    switch (c) {
 
1474
    case 0x1040:
 
1475
      CurrentValue = 0;
 
1476
      break;
 
1477
    case 0x1041:
 
1478
      CurrentValue = 1;
 
1479
      break;
 
1480
    case 0x1042:
 
1481
      CurrentValue = 2;
 
1482
      break;
 
1483
    case 0x1043:
 
1484
      CurrentValue = 3;
 
1485
      break;
 
1486
    case 0x1044:
 
1487
      CurrentValue = 4;
 
1488
      break;
 
1489
    case 0x1045:
 
1490
      CurrentValue = 5;
 
1491
      break;
 
1492
    case 0x1046:
 
1493
      CurrentValue = 6;
 
1494
      break;
 
1495
    case 0x1047:
 
1496
      CurrentValue = 7;
 
1497
         break;
 
1498
    case 0x1048:
 
1499
      CurrentValue = 8;
 
1500
      break;
 
1501
    case 0x1049:
 
1502
      CurrentValue = 9;
 
1503
      break;
 
1504
    default:                    /* Error */
 
1505
      uninum_err = NS_ERROR_BADCHARACTER;
 
1506
      uninum_badchar = c;
 
1507
      mpz_clear(Result);
 
1508
      return;
 
1509
    }
 
1510
    mpz_mul_ui(Result, Result, 10L);
 
1511
    mpz_add_ui(Result, Result, CurrentValue);
 
1512
  }
 
1513
  mpz_init_set(mpzResult, Result);
 
1514
  mpz_clear(Result);
 
1515
}
 
1516
 
 
1517
/*
 
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.
 
1520
 */
 
1521
 
 
1522
static UTF32 *NormalizeChineseNumbers (UTF32 *s) {
 
1523
  UTF32 c;
 
1524
  UTF32 *t;
 
1525
  UTF32 *tmp;
 
1526
  UTF32 *n;
 
1527
 
 
1528
  int len;
 
1529
  int NewLen;
 
1530
 
 
1531
  /* 
 
1532
   * It is safe to double the string length for temp space since no
 
1533
   * substitution does more than replace one character with two.
 
1534
   */
 
1535
  len = ucslen(s);
 
1536
#ifdef ALLOCAOK
 
1537
  t = alloca (((2 * len) + 1) * sizeof (UTF32));
 
1538
#else
 
1539
  t = malloc (((2 * len) + 1) * sizeof (UTF32));
 
1540
#endif
 
1541
  if (t == NULL) return (t);
 
1542
 
 
1543
  tmp = t;
 
1544
  NewLen = len;
 
1545
 
 
1546
  while( (c = *s++) != 0x0000) {
 
1547
    switch (c) {
 
1548
    case 0x96F6:                /* Traditional/Legal */
 
1549
    case 0xF9B2:                /* Compatibility */
 
1550
      *t++ =0x3007;             /* 0 - Ideographic zero - also used with Suzhou numerals*/
 
1551
      break;
 
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 */
 
1559
      break;
 
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 */
 
1570
      break;
 
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 */
 
1578
      break;
 
1579
    case 0x4E96:                /* Obsolete Japanese variant */
 
1580
    case 0x8086:                /* Legal */
 
1581
    case 0x3024:                /* Suzhou */
 
1582
      *t++ = 0x56DB;            /* 4 */
 
1583
      break;
 
1584
    case 0x4F0D:                /* Legal */
 
1585
    case 0x3025:                /* Suzhou */
 
1586
      *t++ = 0x4E94;            /* 5 */
 
1587
      break;
 
1588
    case 0x9646:                /* Legal */
 
1589
    case 0x9678:                /* Legal */
 
1590
    case 0x3026:                /* Suzhou */
 
1591
      *t++ = 0x516D;            /* 6 */
 
1592
      break;
 
1593
    case 0x67D2:                /* Legal */
 
1594
    case 0x6F06:                /* Legal ??????*/
 
1595
    case 0x3027:                /* Suzhou */
 
1596
      *t++ = 0x4E03;            /* 7 */
 
1597
      break;
 
1598
    case 0x634C:                /* Legal */
 
1599
    case 0x3028:                /* Suzhou */
 
1600
      *t++ = 0x516B;            /* 8 */
 
1601
      break;
 
1602
    case 0x7396:                /* Legal */
 
1603
    case 0x3029:                /* Suzhou */
 
1604
      *t++ = 0x4E5D;            /* 9 */
 
1605
      break;
 
1606
    case 0x3038:                /* Suzhou */
 
1607
    case 0x4EC0:                /* Legal simplified - disfavored */
 
1608
    case 0x62FE:                /* Legal traditional*/
 
1609
      *t++ = 0x5341;            /* 10 */
 
1610
      break;
 
1611
    case 0x5EFF:                /* Portmanteau */
 
1612
    case 0x3039:                /* Suzhou portmanteau */
 
1613
      *t++ = 0x4E8C;
 
1614
      *t++ = 0x5341;            /* 20 */
 
1615
      NewLen++;
 
1616
      break;
 
1617
    case 0x5345:                /* Portmanteau */
 
1618
    case 0x303A:                /* Suzhou portmanteau */
 
1619
      *t++ = 0x4E09;
 
1620
      *t++ = 0x5341;            /* 30 */
 
1621
      NewLen++;
 
1622
      break;
 
1623
    case 0x534C:                /* Portmanteau */
 
1624
      *t++ = 0x56DB;
 
1625
      *t++ = 0x5341;            /* 40 */
 
1626
      NewLen++;
 
1627
      break;
 
1628
    case 0x4F70:                /* Legal */
 
1629
    case 0x964C:                /* Legal */
 
1630
      *t++ = 0x767E;            /* 100 */
 
1631
      break;
 
1632
    case 0x4EDF:                /* Legal */
 
1633
    case 0x9621:                /* Legal */
 
1634
      *t++ = 0x5343;            /* 1000 */
 
1635
      break;
 
1636
    case 0x842C:                /* Legal */
 
1637
      *t++ = 0x4E07;            /* 10,000 */
 
1638
      break;
 
1639
    case 0x4EBF:                /* Simplified */
 
1640
      *t++ = 0x5104;            /* 100,000,000 */
 
1641
      break;
 
1642
    default:
 
1643
      *t++ = c;
 
1644
    }
 
1645
  }
 
1646
  *t = 0x0000;
 
1647
  
 
1648
  n = malloc ( (NewLen+1) * sizeof(UTF32));
 
1649
  if (n == NULL) return (n);
 
1650
  ucscpy(n,tmp);
 
1651
 
 
1652
#ifndef ALLOCAOK
 
1653
    free( (void *) tmp);
 
1654
#endif
 
1655
  return n;
 
1656
}
 
1657
 
 
1658
/*
 
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.
 
1662
 */
 
1663
 
 
1664
static void ChinesePlace (mpz_t Result, UTF32 *s) {
 
1665
  unsigned long CurrentValue;
 
1666
  UTF32 c;
 
1667
 
 
1668
  while ( (c = *s++) != 0x0000) {
 
1669
    switch (c) {
 
1670
    case 0x3007:
 
1671
    case 0x96F6:
 
1672
    case 0x0030:
 
1673
      CurrentValue = 0;
 
1674
      break;
 
1675
    case 0x4E00:
 
1676
    case 0x0031:
 
1677
      CurrentValue = 1;
 
1678
      break;
 
1679
    case 0x4E8C:
 
1680
    case 0x0032:
 
1681
      CurrentValue = 2;
 
1682
      break;
 
1683
    case 0x4E09:
 
1684
    case 0x0033:
 
1685
      CurrentValue = 3;
 
1686
      break;
 
1687
    case 0x56DB:
 
1688
    case 0x0034:
 
1689
      CurrentValue = 4;
 
1690
      break;
 
1691
    case 0x4E94:
 
1692
    case 0x0035:
 
1693
      CurrentValue = 5;
 
1694
      break;
 
1695
    case 0x516D:
 
1696
    case 0x0036:
 
1697
      CurrentValue = 6;
 
1698
      break;
 
1699
    case 0x4E03:
 
1700
    case 0x0037:
 
1701
      CurrentValue = 7;
 
1702
      break;
 
1703
    case 0x516B:
 
1704
    case 0x0038:
 
1705
      CurrentValue = 8;
 
1706
      break;
 
1707
    case 0x4E5D:
 
1708
    case 0x0039:
 
1709
      CurrentValue = 9;
 
1710
      break;
 
1711
    default:                    /* Error */
 
1712
      uninum_err = NS_ERROR_BADCHARACTER;
 
1713
      uninum_badchar = c;
 
1714
      mpz_clear(Result);
 
1715
      return;
 
1716
    }
 
1717
    mpz_mul_ui(Result,Result,10L);
 
1718
    mpz_add_ui(Result, Result, CurrentValue);
 
1719
  }
 
1720
  return;
 
1721
}
 
1722
 
 
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 */
 
1739
};
 
1740
 
 
1741
/* 
 
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.
 
1745
 */
 
1746
 
 
1747
static void GetChineseBarrierValue (mpz_t Result,int which) {
 
1748
  switch (which) {
 
1749
  case 0:
 
1750
    (void) mpz_set_str(Result,"10",10);break;
 
1751
  case 1:
 
1752
    (void) mpz_set_str(Result,"100",10);break;
 
1753
  case 2:
 
1754
    (void) mpz_set_str(Result,"1000",10);break;
 
1755
  case 3:
 
1756
    (void) mpz_set_str(Result,"10000",10);break;
 
1757
  case 4:
 
1758
    (void) mpz_set_str(Result,"100000000",10);break;
 
1759
  case 5:
 
1760
    (void) mpz_set_str(Result,"1000000000000",10);break;
 
1761
  case 6:
 
1762
    (void) mpz_set_str(Result,"10000000000000000",10);break;
 
1763
  case 7:
 
1764
    (void) mpz_set_str(Result,"100000000000000000000",10);break;
 
1765
  case 8:
 
1766
    (void) mpz_set_str(Result,"1000000000000000000000000",10);break;
 
1767
  case 9:
 
1768
    (void) mpz_set_str(Result,"10000000000000000000000000000",10);break;
 
1769
  case 10:
 
1770
    (void) mpz_set_str(Result,"100000000000000000000000000000000",10);break;
 
1771
  case 11:
 
1772
    (void) mpz_set_str(Result,"1000000000000000000000000000000000000",10);break;
 
1773
  case 12:
 
1774
    (void) mpz_set_str(Result,"10000000000000000000000000000000000000000",10);break;
 
1775
  case 13:
 
1776
    (void) mpz_set_str(Result,"100000000000000000000000000000000000000000000",10);break;
 
1777
  case 14:
 
1778
    (void) mpz_set_str(Result,"1000000000000000000000000000000000000000000000000",10);break;
 
1779
  default:
 
1780
    (void) mpz_set_str(Result,"0",10);
 
1781
  }
 
1782
}
 
1783
 
 
1784
static inline UTF32 *SeekChineseBarrier (UTF32 *s, int *ri) {
 
1785
  UTF32 *ptr;
 
1786
  int bi = (sizeof(ChineseBarriers)/sizeof(UTF32))-1;
 
1787
 
 
1788
  ptr = NULL;
 
1789
  while (ptr == NULL && bi >= 0) {
 
1790
    ptr = ucschr(s,ChineseBarriers[bi--]);
 
1791
  }
 
1792
  *ri = bi+1;
 
1793
  return ptr;
 
1794
}
 
1795
 
 
1796
static void ChineseToInt_MPZ(mpz_t ReturnValue, UTF32 *s) {
 
1797
  UTF32 *ptr;
 
1798
  UTF32 SavedBarrier;
 
1799
  int i;
 
1800
  mpz_t mul;
 
1801
  mpz_t Result;
 
1802
  mpz_t RightValue;
 
1803
  mpz_t BarrierValue;
 
1804
 
 
1805
  mpz_init(BarrierValue);
 
1806
  mpz_init(mul);
 
1807
  mpz_init(Result);
 
1808
  mpz_init(RightValue);
 
1809
 
 
1810
  ptr = SeekChineseBarrier(s,&i);
 
1811
  if (ptr == NULL) {
 
1812
    ChinesePlace(ReturnValue,s);
 
1813
  }
 
1814
  else {
 
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 */
 
1819
    
 
1820
    GetChineseBarrierValue(BarrierValue,i);
 
1821
    mpz_mul(Result,mul,BarrierValue);
 
1822
 
 
1823
    ChineseToInt_MPZ(RightValue,ptr+1);
 
1824
    mpz_add(Result,Result,RightValue);
 
1825
    mpz_set(ReturnValue,Result);
 
1826
  }
 
1827
  mpz_clear(BarrierValue);
 
1828
  mpz_clear(Result);
 
1829
  mpz_clear(RightValue);
 
1830
  mpz_clear(mul);
 
1831
  return;
 
1832
}
 
1833
 
 
1834
static void ChineseToInt(mpz_t mpzResult, UTF32 *s) {
 
1835
  mpz_t Result;
 
1836
  char *rs;
 
1837
 
 
1838
  uninum_err = NS_ERROR_OKAY;
 
1839
  mpz_init(Result);
 
1840
  ChineseToInt_MPZ(Result,s);
 
1841
 
 
1842
  mpz_init_set(mpzResult, Result);
 
1843
  mpz_clear(Result);
 
1844
}
 
1845
 
 
1846
 
 
1847
static void ChineseCountingRodToInt(mpz_t mpzResult, UTF32 *s) {
 
1848
  unsigned long CurrentValue; 
 
1849
  UTF32 c;
 
1850
  char *rs;
 
1851
  enum ct {EVEN,NEUTRAL,ODD};
 
1852
  enum ct PreviousType = NEUTRAL;
 
1853
  enum ct CurrentType  = NEUTRAL;
 
1854
  mpz_t Result;
 
1855
 
 
1856
  uninum_err = NS_ERROR_OKAY;
 
1857
  mpz_init(Result);
 
1858
 
 
1859
  while ( (c = *s++) != 0x0000) {
 
1860
    switch (c) {
 
1861
    case 0x3007:
 
1862
      CurrentValue = 0;
 
1863
      CurrentType = NEUTRAL;
 
1864
      break;
 
1865
    case 0x1D360:
 
1866
      CurrentValue = 1;
 
1867
      CurrentType = EVEN;
 
1868
      break;
 
1869
    case 0x1D369:
 
1870
      CurrentValue = 1;
 
1871
      CurrentType = ODD;
 
1872
      break;
 
1873
    case 0x1D361:
 
1874
      CurrentValue = 2;
 
1875
      CurrentType = EVEN;
 
1876
      break;
 
1877
    case 0x1D36A:
 
1878
      CurrentValue = 2;
 
1879
      CurrentType = ODD;
 
1880
      break;
 
1881
    case 0x1D362:
 
1882
      CurrentValue = 3;
 
1883
      CurrentType = EVEN;
 
1884
      break;
 
1885
    case 0x1D36B:
 
1886
      CurrentValue = 3;
 
1887
      CurrentType = ODD;
 
1888
      break;
 
1889
    case 0x1D363:
 
1890
      CurrentValue = 4;
 
1891
      CurrentType = EVEN;
 
1892
      break;
 
1893
    case 0x1D36C:
 
1894
      CurrentValue = 4;
 
1895
      CurrentType = ODD;
 
1896
      break;
 
1897
    case 0x1D364:
 
1898
      CurrentValue = 5;
 
1899
      CurrentType = EVEN;
 
1900
      break;
 
1901
    case 0x1D36D:
 
1902
      CurrentValue = 5;
 
1903
      CurrentType = ODD;
 
1904
      break;
 
1905
    case 0x1D365:
 
1906
      CurrentValue = 6;
 
1907
      CurrentType = EVEN;
 
1908
      break;
 
1909
    case 0x1D36E:
 
1910
      CurrentValue = 6;
 
1911
      CurrentType = ODD;
 
1912
      break;
 
1913
    case 0x1D366:
 
1914
      CurrentValue = 7;
 
1915
      CurrentType = EVEN;
 
1916
      break;
 
1917
    case 0x1D36F:
 
1918
      CurrentValue = 7;
 
1919
      CurrentType = ODD;
 
1920
      break;
 
1921
    case 0x1D367:
 
1922
      CurrentValue = 8;
 
1923
      CurrentType = EVEN;
 
1924
      break;
 
1925
    case 0x1D370:
 
1926
      CurrentValue = 8;
 
1927
      CurrentType = ODD;
 
1928
      break;
 
1929
    case 0x1D368:
 
1930
      CurrentValue = 9;
 
1931
      CurrentType = EVEN;
 
1932
      break;
 
1933
    case 0x1D371:
 
1934
      CurrentValue = 9;
 
1935
      CurrentType = ODD;
 
1936
      break;
 
1937
    default:                    /* Error */
 
1938
      uninum_err = NS_ERROR_BADCHARACTER;
 
1939
      uninum_badchar = c;
 
1940
      mpz_clear(Result);
 
1941
      return;
 
1942
    }
 
1943
    if( (CurrentType == PreviousType) && (CurrentType != NEUTRAL)) {
 
1944
      mpz_mul_ui(Result, Result, 100L);
 
1945
    }
 
1946
    else mpz_mul_ui(Result, Result, 10L);
 
1947
    mpz_add_ui(Result, Result, CurrentValue);
 
1948
    PreviousType = CurrentType;
 
1949
  }
 
1950
  mpz_init_set(mpzResult, Result);
 
1951
  mpz_clear(Result);
 
1952
}
 
1953
 
 
1954
static void CyrillicAlphabeticToInt(mpz_t mpzResult, UTF32 *s) {
 
1955
  unsigned long CurrentValue=0L; 
 
1956
  UTF32 c;
 
1957
  mpz_t Result;
 
1958
  short ThousandP = 0;
 
1959
 
 
1960
  uninum_err = NS_ERROR_OKAY;
 
1961
  mpz_init(Result);
 
1962
 
 
1963
  while ((c = *s++) != 0x0000) {
 
1964
    switch(c) {
 
1965
    case CYRILLIC_TITLO:        /* Skip - it just marks numbers*/
 
1966
      break;
 
1967
    case CYRILLIC_THOUSANDS_SIGN:
 
1968
      ThousandP = 1;
 
1969
      break;
 
1970
    case 0x0426:
 
1971
      CurrentValue=900;
 
1972
      break;
 
1973
    case 0x0460:
 
1974
      CurrentValue=800;
 
1975
      break;
 
1976
    case 0x0470:
 
1977
      CurrentValue=700;
 
1978
      break;
 
1979
    case 0x0425:
 
1980
      CurrentValue=600;
 
1981
      break;
 
1982
    case 0x0424:
 
1983
      CurrentValue=500;
 
1984
      break;
 
1985
    case 0x0478:
 
1986
      CurrentValue=400;
 
1987
      break;
 
1988
    case 0x0422:
 
1989
      CurrentValue=300;
 
1990
      break;
 
1991
    case 0x0421:
 
1992
      CurrentValue=200;
 
1993
      break;
 
1994
    case 0x0420:
 
1995
      CurrentValue=100;
 
1996
      break;
 
1997
    case 0x0427:
 
1998
      CurrentValue=90;
 
1999
      break;
 
2000
    case 0x041F:
 
2001
      CurrentValue=80;
 
2002
      break;
 
2003
    case 0x041E:
 
2004
      CurrentValue=70;
 
2005
      break;
 
2006
    case 0x046E:
 
2007
      CurrentValue=60;
 
2008
      break;
 
2009
    case 0x041D:
 
2010
      CurrentValue=50;
 
2011
      break;
 
2012
    case 0x041C:
 
2013
      CurrentValue=40;
 
2014
      break;
 
2015
    case 0x041B:
 
2016
      CurrentValue=30;
 
2017
      break;
 
2018
    case 0x041A:
 
2019
      CurrentValue=20;
 
2020
      break;
 
2021
    case 0x0406:
 
2022
      CurrentValue=10;
 
2023
      break;
 
2024
    case 0x0472:
 
2025
      CurrentValue=9;
 
2026
      if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;}
 
2027
      break;
 
2028
    case 0x0418:
 
2029
      CurrentValue=8;
 
2030
      if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;}
 
2031
      break;
 
2032
    case 0x0417:
 
2033
      CurrentValue=7;
 
2034
      if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;}
 
2035
      break;
 
2036
    case 0x0405:
 
2037
      CurrentValue=6;
 
2038
      if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;}
 
2039
      break;
 
2040
    case 0x0415:
 
2041
      CurrentValue=5;
 
2042
      if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;}
 
2043
      break;
 
2044
    case 0x0414:
 
2045
      CurrentValue=4;
 
2046
      if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;}
 
2047
      break;
 
2048
    case 0x0413:
 
2049
      CurrentValue=3;
 
2050
      if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;}
 
2051
      break;
 
2052
    case 0x0411:                /* BE */
 
2053
      CurrentValue=2;
 
2054
      if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;}
 
2055
      break;
 
2056
    case 0x0410:                /* A */
 
2057
      CurrentValue=1;
 
2058
      if (ThousandP) {CurrentValue *= 1000L; ThousandP = 0;}
 
2059
      break;
 
2060
    default:                    /* Error */
 
2061
      uninum_err = NS_ERROR_BADCHARACTER;
 
2062
      uninum_badchar = c;
 
2063
      mpz_clear(Result);
 
2064
      return;
 
2065
    }
 
2066
    mpz_add_ui(Result,Result,CurrentValue);
 
2067
  }
 
2068
  mpz_init_set(mpzResult, Result);
 
2069
  mpz_clear(Result);
 
2070
}
 
2071
 
 
2072
static void CommonBrailleToInt(mpz_t mpzResult, UTF32 *s) {
 
2073
  unsigned long CurrentValue; 
 
2074
  UTF32 c;
 
2075
  mpz_t Result;
 
2076
 
 
2077
  uninum_err = NS_ERROR_OKAY;
 
2078
  mpz_init(Result);
 
2079
 
 
2080
  if (*s == 0x283C) s++;        /* Skip number designator */
 
2081
 
 
2082
  while ( (c = *s++) != 0x0000) {
 
2083
    switch (c) {
 
2084
    case 0x281A:
 
2085
      CurrentValue = 0;
 
2086
      break;
 
2087
    case 0x2801:
 
2088
      CurrentValue = 1;
 
2089
      break;
 
2090
     case 0x2803:
 
2091
      CurrentValue = 2;
 
2092
      break;
 
2093
    case 0x2809:
 
2094
      CurrentValue = 3;
 
2095
      break;
 
2096
    case 0x2819:
 
2097
      CurrentValue = 4;
 
2098
      break;
 
2099
    case 0x2811:
 
2100
      CurrentValue = 5;
 
2101
      break;
 
2102
    case 0x280B:
 
2103
      CurrentValue = 6;
 
2104
      break;
 
2105
    case 0x281B:
 
2106
      CurrentValue = 7;
 
2107
      break;
 
2108
    case 0x2813:
 
2109
      CurrentValue = 8;
 
2110
      break;
 
2111
    case 0x280A:
 
2112
      CurrentValue = 9;
 
2113
      break;
 
2114
    case 0x2802:                /* Ignore Braille comma */
 
2115
      break;
 
2116
    default:                    /* Error */
 
2117
      uninum_err = NS_ERROR_BADCHARACTER;
 
2118
      uninum_badchar = c;
 
2119
      mpz_clear(Result);
 
2120
      return;
 
2121
    }
 
2122
    mpz_mul_ui(Result, Result, 10L);
 
2123
    mpz_add_ui(Result, Result, CurrentValue);
 
2124
  }
 
2125
  mpz_init_set(mpzResult, Result);
 
2126
  mpz_clear(Result);
 
2127
}
 
2128
 
 
2129
static void DevanagariToInt(mpz_t mpzResult, UTF32 *s) {
 
2130
  unsigned long CurrentValue; 
 
2131
  UTF32 c;
 
2132
  mpz_t Result;
 
2133
 
 
2134
  uninum_err = NS_ERROR_OKAY;
 
2135
  mpz_init(Result);
 
2136
 
 
2137
  while ( (c = *s++) != 0x0000) {
 
2138
    switch (c) {
 
2139
    case 0x0966:
 
2140
      CurrentValue = 0;
 
2141
      break;
 
2142
    case 0x0967:
 
2143
      CurrentValue = 1;
 
2144
      break;
 
2145
    case 0x0968:
 
2146
      CurrentValue = 2;
 
2147
      break;
 
2148
    case 0x0969:
 
2149
      CurrentValue = 3;
 
2150
      break;
 
2151
    case 0x096A:
 
2152
      CurrentValue = 4;
 
2153
      break;
 
2154
    case 0x096B:
 
2155
      CurrentValue = 5;
 
2156
      break;
 
2157
    case 0x096C:
 
2158
      CurrentValue = 6;
 
2159
      break;
 
2160
    case 0x096D:
 
2161
      CurrentValue = 7;
 
2162
         break;
 
2163
    case 0x096E:
 
2164
      CurrentValue = 8;
 
2165
      break;
 
2166
    case 0x096F:
 
2167
      CurrentValue = 9;
 
2168
      break;
 
2169
    default:                    /* Error */
 
2170
      uninum_err = NS_ERROR_BADCHARACTER;
 
2171
      uninum_badchar = c;
 
2172
      mpz_clear(Result);
 
2173
      return;
 
2174
    }
 
2175
    mpz_mul_ui(Result, Result, 10L);
 
2176
    mpz_add_ui(Result, Result, CurrentValue);
 
2177
  }
 
2178
  mpz_init_set(mpzResult, Result);
 
2179
  mpz_clear(Result);
 
2180
}
 
2181
 
 
2182
/* Based on Unicode proposal - not  yet final as of Unicode 5.0 */
 
2183
 
 
2184
static void EgyptianToInt(mpz_t mpzResult, UTF32 *s) {
 
2185
  unsigned long CurrentValue; 
 
2186
  UTF32 c;
 
2187
  mpz_t Result;
 
2188
 
 
2189
  uninum_err = NS_ERROR_OKAY;
 
2190
  mpz_init(Result);
 
2191
 
 
2192
  while ( (c = *s++) != 0x0000) {
 
2193
    switch (c) {
 
2194
    case 0x143A1:
 
2195
      CurrentValue = 1;
 
2196
      break;
 
2197
    case 0x14353:
 
2198
      CurrentValue = 10;
 
2199
      break;
 
2200
    case 0x1433B:
 
2201
      CurrentValue = 100;
 
2202
      break;
 
2203
    case 0x141A2:
 
2204
      CurrentValue = 1000;
 
2205
      break;
 
2206
    case 0x140A7:
 
2207
      CurrentValue =  10000;
 
2208
      break;
 
2209
    case 0x14173:
 
2210
      CurrentValue = 100000;
 
2211
      break;
 
2212
    case 0x14064:
 
2213
      CurrentValue = 1000000;
 
2214
      break;
 
2215
    default:                    /* Error */
 
2216
      uninum_err = NS_ERROR_BADCHARACTER;
 
2217
      uninum_badchar = c;
 
2218
      mpz_clear(Result);
 
2219
      return;
 
2220
    }
 
2221
    mpz_add_ui(Result, Result, CurrentValue);
 
2222
  }
 
2223
  mpz_init_set(mpzResult, Result);
 
2224
  mpz_clear(Result);
 
2225
}
 
2226
 
 
2227
static void EthiopicToInt(mpz_t mpzResult, UTF32 *s) {
 
2228
    mpz_init_set_ui(mpzResult,0L);
 
2229
    uninum_err = NS_ERROR_NUMBER_SYSTEM_UNKNOWN;
 
2230
}
 
2231
 
 
2232
static void EwellicDecimalToInt(mpz_t mpzResult, UTF32 *s) {
 
2233
  unsigned long CurrentValue; 
 
2234
  UTF32 c;
 
2235
  mpz_t Result;
 
2236
 
 
2237
  uninum_err = NS_ERROR_OKAY;
 
2238
  mpz_init(Result);
 
2239
 
 
2240
  while ( (c = *s++) != 0x0000) {
 
2241
    switch (c) {
 
2242
    case 0xE6C0:
 
2243
    case 0x0030:
 
2244
      CurrentValue = 0;
 
2245
      break;
 
2246
    case 0xE6C1:
 
2247
    case 0x0031:
 
2248
      CurrentValue = 1;
 
2249
      break;
 
2250
    case 0xE6C2:
 
2251
    case 0x0032:
 
2252
      CurrentValue = 2;
 
2253
      break;
 
2254
    case 0xE6C3:
 
2255
    case 0x0033:
 
2256
      CurrentValue = 3;
 
2257
      break;
 
2258
    case 0xE6C4:
 
2259
    case 0x0034:
 
2260
      CurrentValue = 4;
 
2261
      break;
 
2262
    case 0xE6C5:
 
2263
    case 0x0035:
 
2264
      CurrentValue = 5;
 
2265
      break;
 
2266
    case 0xE6C6:
 
2267
    case 0x0036:
 
2268
      CurrentValue = 6;
 
2269
      break;
 
2270
    case 0xE6C7:
 
2271
    case 0x0037:
 
2272
      CurrentValue = 7;
 
2273
         break;
 
2274
    case 0xE6C8:
 
2275
    case 0x0038:
 
2276
      CurrentValue = 8;
 
2277
      break;
 
2278
    case 0xE6C9:
 
2279
    case 0x0039:
 
2280
      CurrentValue = 9;
 
2281
      break;
 
2282
    default:                    /* Error */
 
2283
      uninum_err = NS_ERROR_BADCHARACTER;
 
2284
      uninum_badchar = c;
 
2285
      mpz_clear(Result);
 
2286
      return;
 
2287
    }
 
2288
    mpz_mul_ui(Result, Result, 10L);
 
2289
    mpz_add_ui(Result, Result, CurrentValue);
 
2290
  }
 
2291
  mpz_init_set(mpzResult, Result);
 
2292
  mpz_clear(Result);
 
2293
}
 
2294
 
 
2295
static void EwellicHexToInt(mpz_t mpzResult, UTF32 *s) {
 
2296
  unsigned long CurrentValue; 
 
2297
  UTF32 c;
 
2298
  mpz_t Result;
 
2299
 
 
2300
  uninum_err = NS_ERROR_OKAY;
 
2301
  mpz_init(Result);
 
2302
 
 
2303
  if( *s == 0x0060) s++;        /* Skip Ewellic hex marker */
 
2304
  while ( (c = *s++) != 0x0000) {
 
2305
    switch (c) {
 
2306
    case 0xE6C0:
 
2307
    case 0x0030:
 
2308
      CurrentValue = 0;
 
2309
      break;
 
2310
    case 0xE6C1:
 
2311
    case 0x0031:
 
2312
      CurrentValue = 1;
 
2313
      break;
 
2314
    case 0xE6C2:
 
2315
    case 0x0032:
 
2316
      CurrentValue = 2;
 
2317
      break;
 
2318
    case 0xE6C3:
 
2319
    case 0x0033:
 
2320
      CurrentValue = 3;
 
2321
      break;
 
2322
    case 0xE6C4:
 
2323
    case 0x0034:
 
2324
      CurrentValue = 4;
 
2325
      break;
 
2326
    case 0xE6C5:
 
2327
    case 0x0035:
 
2328
      CurrentValue = 5;
 
2329
      break;
 
2330
    case 0xE6C6:
 
2331
    case 0x0036:
 
2332
      CurrentValue = 6;
 
2333
      break;
 
2334
    case 0xE6C7:
 
2335
    case 0x0037:
 
2336
      CurrentValue = 7;
 
2337
      break;
 
2338
    case 0xE6C8:
 
2339
    case 0x0038:
 
2340
      CurrentValue = 8;
 
2341
      break;
 
2342
    case 0xE6C9:
 
2343
    case 0x0039:
 
2344
      CurrentValue = 9;
 
2345
      break;
 
2346
    case 0xE6CA:
 
2347
      CurrentValue = 10;
 
2348
      break;
 
2349
    case 0xE6CB:
 
2350
      CurrentValue = 11;
 
2351
      break;
 
2352
    case 0xE6CC:
 
2353
      CurrentValue = 12;
 
2354
      break;
 
2355
    case 0xE6CD:
 
2356
      CurrentValue = 13;
 
2357
      break;
 
2358
    case 0xE6CE:
 
2359
      CurrentValue = 14;
 
2360
      break;
 
2361
    case 0xE6CF:
 
2362
      CurrentValue = 15;
 
2363
      break;
 
2364
    default:                    /* Error */
 
2365
      uninum_err = NS_ERROR_BADCHARACTER;
 
2366
      uninum_badchar = c;
 
2367
      mpz_clear(Result);
 
2368
      return;
 
2369
    }
 
2370
    mpz_mul_ui(Result, Result, 16L);
 
2371
    mpz_add_ui(Result, Result, CurrentValue);
 
2372
  }
 
2373
  mpz_init_set(mpzResult, Result);
 
2374
  mpz_clear(Result);
 
2375
}
 
2376
 
 
2377
static void FrenchBrailleToInt(mpz_t mpzResult, UTF32 *s) {
 
2378
  unsigned long CurrentValue; 
 
2379
  UTF32 c;
 
2380
  mpz_t Result;
 
2381
 
 
2382
  uninum_err = NS_ERROR_OKAY;
 
2383
  mpz_init(Result);
 
2384
 
 
2385
  if (*s == 0x2820) s++;        /* Skip number designator - D6 */
 
2386
 
 
2387
  while ( (c = *s++) != 0x0000) {
 
2388
    switch (c) {
 
2389
    case 0x283C:
 
2390
      CurrentValue = 0;
 
2391
      break;
 
2392
    case 0x2821:
 
2393
      CurrentValue = 1;
 
2394
      break;
 
2395
     case 0x2823:
 
2396
      CurrentValue = 2;
 
2397
      break;
 
2398
    case 0x2829:
 
2399
      CurrentValue = 3;
 
2400
      break;
 
2401
    case 0x2839:
 
2402
      CurrentValue = 4;
 
2403
      break;
 
2404
    case 0x2831:
 
2405
      CurrentValue = 5;
 
2406
      break;
 
2407
    case 0x282B:
 
2408
      CurrentValue = 6;
 
2409
      break;
 
2410
    case 0x283B:
 
2411
      CurrentValue = 7;
 
2412
      break;
 
2413
    case 0x2833:
 
2414
      CurrentValue = 8;
 
2415
      break;
 
2416
    case 0x282A:
 
2417
      CurrentValue = 9;
 
2418
      break;
 
2419
    case 0x2802:                /* Ignore Braille comma */
 
2420
      break;
 
2421
    default:                    /* Error */
 
2422
      uninum_err = NS_ERROR_BADCHARACTER;
 
2423
      uninum_badchar = c;
 
2424
      mpz_clear(Result);
 
2425
      return;
 
2426
    }
 
2427
    mpz_mul_ui(Result, Result, 10L);
 
2428
    mpz_add_ui(Result, Result, CurrentValue);
 
2429
  }
 
2430
  mpz_init_set(mpzResult, Result);
 
2431
  mpz_clear(Result);
 
2432
}
 
2433
 
 
2434
static void GeorgianAlphabeticToInt(mpz_t mpzResult, UTF32 *s) {
 
2435
  unsigned long CurrentValue; 
 
2436
  UTF32 c;
 
2437
  mpz_t Result;
 
2438
 
 
2439
  uninum_err = NS_ERROR_OKAY;
 
2440
  mpz_init(Result);
 
2441
 
 
2442
  while ( (c = *s++) != 0x0000) {
 
2443
    switch (c) {
 
2444
    case 0x10A0:
 
2445
    case 0x2D00:
 
2446
    case 0x10D0:
 
2447
      CurrentValue = 1;
 
2448
      break;
 
2449
    case 0x10A1:
 
2450
    case 0x2D01:
 
2451
    case 0x10D1:
 
2452
      CurrentValue = 2;
 
2453
      break;
 
2454
    case 0x10A2:
 
2455
    case 0x2D02:
 
2456
    case 0x10D2:
 
2457
      CurrentValue = 3;
 
2458
      break;
 
2459
    case 0x10A3:
 
2460
    case 0x2D03:
 
2461
    case 0x10D3:
 
2462
      CurrentValue = 4;
 
2463
      break;
 
2464
    case 0x10A4:
 
2465
    case 0x2D04:
 
2466
    case 0x10D4:
 
2467
      CurrentValue = 5;
 
2468
      break;
 
2469
    case 0x10A5:
 
2470
    case 0x2D05:
 
2471
    case 0x10D5:
 
2472
      CurrentValue = 6;
 
2473
      break;
 
2474
    case 0x10A6:
 
2475
    case 0x2D06:
 
2476
    case 0x10D6:
 
2477
      CurrentValue = 7;
 
2478
      break;
 
2479
    case 0x10C1:
 
2480
    case 0x2D21:
 
2481
    case 0x10F1:
 
2482
      CurrentValue = 8;
 
2483
      break;
 
2484
    case 0x10A7:
 
2485
    case 0x2D07:
 
2486
    case 0x10D7:
 
2487
      CurrentValue = 9;
 
2488
      break;
 
2489
    case 0x10A8:
 
2490
    case 0x2D08:
 
2491
    case 0x10D8:
 
2492
      CurrentValue = 10;
 
2493
      break;
 
2494
    case 0x10A9:
 
2495
    case 0x2D09:
 
2496
    case 0x10D9:
 
2497
      CurrentValue = 20;
 
2498
      break;
 
2499
    case 0x10AA:
 
2500
    case 0x2D0A:
 
2501
    case 0x10DA:
 
2502
      CurrentValue = 30;
 
2503
      break;
 
2504
    case 0x10AB:
 
2505
    case 0x2D0B:
 
2506
    case 0x10DB:
 
2507
      CurrentValue = 40;
 
2508
      break;
 
2509
    case 0x10AC:
 
2510
    case 0x2D0C:
 
2511
    case 0x10DC:
 
2512
      CurrentValue = 50;
 
2513
      break;
 
2514
    case 0x10C2:
 
2515
    case 0x2D22:
 
2516
    case 0x10F2:
 
2517
      CurrentValue = 60;
 
2518
      break;
 
2519
    case 0x10AD:
 
2520
    case 0x2D0D:
 
2521
    case 0x10DD:
 
2522
      CurrentValue = 70;
 
2523
      break;
 
2524
    case 0x10AE:
 
2525
    case 0x2D0E:
 
2526
    case 0x10DE:
 
2527
      CurrentValue = 80;
 
2528
      break;
 
2529
    case 0x10AF:
 
2530
    case 0x2D0F:
 
2531
    case 0x10DF:
 
2532
      CurrentValue = 90;
 
2533
      break;
 
2534
    case 0x10B0:
 
2535
    case 0x2D10:
 
2536
    case 0x10E0:
 
2537
      CurrentValue = 100;
 
2538
      break;
 
2539
    case 0x10B1:
 
2540
    case 0x2D11:
 
2541
    case 0x10E1:
 
2542
      CurrentValue = 200;
 
2543
      break;
 
2544
    case 0x10B2:
 
2545
    case 0x2D12:
 
2546
    case 0x10E2:
 
2547
      CurrentValue = 300;
 
2548
      break;
 
2549
    case 0x10B3:
 
2550
    case 0x2D13:
 
2551
    case 0x10E3:
 
2552
      CurrentValue = 400;
 
2553
      break;
 
2554
    case 0x10B4:
 
2555
    case 0x2D14:
 
2556
    case 0x10E4:
 
2557
      CurrentValue = 500;
 
2558
      break;
 
2559
    case 0x10B5:
 
2560
    case 0x2D15:
 
2561
    case 0x10E5:
 
2562
      CurrentValue = 600;
 
2563
      break;
 
2564
    case 0x10B6:
 
2565
    case 0x2D16:
 
2566
    case 0x10E6:
 
2567
      CurrentValue = 700;
 
2568
      break;
 
2569
    case 0x10B7:
 
2570
    case 0x2D17:
 
2571
    case 0x10E7:
 
2572
      CurrentValue = 800;
 
2573
      break;
 
2574
    case 0x10B8:
 
2575
    case 0x2D18:
 
2576
    case 0x10E8:
 
2577
      CurrentValue = 900;
 
2578
      break;
 
2579
    case 0x10B9:
 
2580
    case 0x2D19:
 
2581
    case 0x10E9:
 
2582
      CurrentValue = 1000;
 
2583
      break;
 
2584
    case 0x10BA:
 
2585
    case 0x2D1A:
 
2586
    case 0x10EA:
 
2587
      CurrentValue = 2000;
 
2588
      break;
 
2589
    case 0x10BB:
 
2590
    case 0x2D1B:
 
2591
    case 0x10EB:
 
2592
      CurrentValue = 3000;
 
2593
      break;
 
2594
    case 0x10BC:
 
2595
    case 0x2D1C:
 
2596
    case 0x10EC:
 
2597
      CurrentValue = 4000;
 
2598
      break;
 
2599
    case 0x10BD:
 
2600
    case 0x2D1D:
 
2601
    case 0x10ED:
 
2602
      CurrentValue = 5000;
 
2603
      break;
 
2604
    case 0x10BE:
 
2605
    case 0x2D1E:
 
2606
    case 0x10EE:
 
2607
      CurrentValue = 6000;
 
2608
      break;
 
2609
    case 0x10C4:
 
2610
    case 0x2D24:
 
2611
    case 0x10F4:
 
2612
      CurrentValue = 7000;
 
2613
      break;
 
2614
    case 0x10BF:
 
2615
    case 0x2D1F:
 
2616
    case 0x10EF:
 
2617
      CurrentValue = 8000;
 
2618
      break;
 
2619
    case 0x10C0:
 
2620
    case 0x2D20:
 
2621
    case 0x10F0:
 
2622
      CurrentValue = 9000;
 
2623
      break;
 
2624
    case 0x10C5:
 
2625
    case 0x2D25:
 
2626
    case 0x10F5:
 
2627
      CurrentValue = 10000;
 
2628
      break;
 
2629
    default:                    /* Error */
 
2630
      uninum_err = NS_ERROR_BADCHARACTER;
 
2631
      uninum_badchar = c;
 
2632
      mpz_clear(Result);
 
2633
      return;
 
2634
    }
 
2635
    mpz_add_ui(Result, Result, CurrentValue);
 
2636
  }
 
2637
  mpz_init_set(mpzResult, Result);
 
2638
  mpz_clear(Result);
 
2639
  return;
 
2640
}
 
2641
 
 
2642
static void GlagoliticAlphabeticToInt(mpz_t mpzResult, UTF32 *s) {
 
2643
  unsigned long CurrentValue; 
 
2644
  UTF32 c;
 
2645
  mpz_t Result;
 
2646
 
 
2647
  uninum_err = NS_ERROR_OKAY;
 
2648
  mpz_init(Result);
 
2649
 
 
2650
  while ( (c = *s++) != 0x0000) {
 
2651
    switch (c) {
 
2652
    case 0x2C00:                /* AZU */
 
2653
      CurrentValue = 1;
 
2654
      break;
 
2655
    case 0x2C01:                /* BUKY */
 
2656
      CurrentValue = 2;
 
2657
      break;
 
2658
    case 0x2C02:                /* VEDE */
 
2659
      CurrentValue = 3;
 
2660
      break;
 
2661
    case 0x2C03:                /* GLAGOLY */
 
2662
      CurrentValue = 4;
 
2663
      break;
 
2664
    case 0x2C04:                /* DOBRO */
 
2665
      CurrentValue = 5;
 
2666
      break;
 
2667
    case 0x2C05:                /* YESTU */
 
2668
      CurrentValue = 6;
 
2669
      break;
 
2670
    case 0x2C06:                /* ZHIVETE */
 
2671
      CurrentValue = 7;
 
2672
      break;
 
2673
    case 0x2C07:                /* DZELO */
 
2674
      CurrentValue = 8;
 
2675
      break;
 
2676
    case 0x2C08:                /* ZEMLJA */
 
2677
      CurrentValue = 9;
 
2678
      break;
 
2679
    case 0x2C09:                /* IZHE */
 
2680
      CurrentValue = 10;
 
2681
      break;
 
2682
    case 0x2C0B:                /* I */
 
2683
      CurrentValue = 20;
 
2684
      break;
 
2685
    case 0x2C0C:                /* DJERVI */
 
2686
      CurrentValue = 30;
 
2687
      break;
 
2688
    case 0x2C0D:                /* KAKO */
 
2689
      CurrentValue = 40;
 
2690
      break;
 
2691
    case 0x2C0E:                /* LJUDIE */
 
2692
      CurrentValue = 50;
 
2693
      break;
 
2694
    case 0x2C0F:                /* MYSLITE */
 
2695
      CurrentValue = 60;
 
2696
      break;
 
2697
    case 0x2C10:                /* NASHI */
 
2698
      CurrentValue = 70;
 
2699
      break;
 
2700
    case 0x2C11:                /* ONU */
 
2701
      CurrentValue = 80;
 
2702
      break;
 
2703
    case 0x2C12:                /* POKOJI */
 
2704
      CurrentValue = 90;
 
2705
      break;
 
2706
    case 0x2C13:                /* RITSI */
 
2707
      CurrentValue = 100;
 
2708
      break;
 
2709
    case 0x2C14:                /* SLOVO */
 
2710
      CurrentValue = 200;
 
2711
      break;
 
2712
    case 0x2C15:                /* TVRIDO */
 
2713
      CurrentValue = 300;
 
2714
      break;
 
2715
    case 0x2C16:                /* UKU */
 
2716
      CurrentValue = 400;
 
2717
      break;
 
2718
    case 0x2C17:                /* FRITU */
 
2719
      CurrentValue = 500;
 
2720
      break;
 
2721
    case 0x2C18:                /* HERU */
 
2722
      CurrentValue = 600;
 
2723
      break;
 
2724
    case 0x2C19:                /* OTU */
 
2725
      CurrentValue = 700;
 
2726
      break;
 
2727
    case 0x2C1B:                /* SHTA */
 
2728
      CurrentValue = 800;
 
2729
      break;
 
2730
    case 0x2C1C:                /* TSI */
 
2731
      CurrentValue = 900;
 
2732
      break;
 
2733
    case 0x2C1D:                /* CHRIVI */
 
2734
      CurrentValue = 1000;
 
2735
      break;
 
2736
    case 0x2C1E:                /* SHA */
 
2737
      CurrentValue = 2000;
 
2738
      break;
 
2739
    default:                    /* Error */
 
2740
      uninum_err = NS_ERROR_BADCHARACTER;
 
2741
      uninum_badchar = c;
 
2742
      mpz_clear(Result);
 
2743
      return;
 
2744
    }
 
2745
    mpz_add_ui(Result, Result, CurrentValue);
 
2746
  }
 
2747
  mpz_init_set(mpzResult, Result);
 
2748
  mpz_clear(Result);
 
2749
  return;
 
2750
}
 
2751
 
 
2752
static void GujaratiToInt(mpz_t mpzResult, UTF32 *s) {
 
2753
  unsigned long CurrentValue; 
 
2754
  UTF32 c;
 
2755
  mpz_t Result;
 
2756
 
 
2757
  uninum_err = NS_ERROR_OKAY;
 
2758
  mpz_init(Result);
 
2759
 
 
2760
  while ( (c = *s++) != 0x0000) {
 
2761
    switch (c) {
 
2762
    case 0x0AE6:
 
2763
      CurrentValue = 0;
 
2764
      break;
 
2765
    case 0x0AE7:
 
2766
      CurrentValue = 1;
 
2767
      break;
 
2768
    case 0x0AE8:
 
2769
      CurrentValue = 2;
 
2770
      break;
 
2771
    case 0x0AE9:
 
2772
      CurrentValue = 3;
 
2773
      break;
 
2774
    case 0x0AEA:
 
2775
      CurrentValue = 4;
 
2776
      break;
 
2777
    case 0x0AEB:
 
2778
      CurrentValue = 5;
 
2779
      break;
 
2780
    case 0x0AEC:
 
2781
      CurrentValue = 6;
 
2782
      break;
 
2783
    case 0x0AED:
 
2784
      CurrentValue = 7;
 
2785
         break;
 
2786
    case 0x0AEE:
 
2787
      CurrentValue = 8;
 
2788
      break;
 
2789
    case 0x0AEF:
 
2790
      CurrentValue = 9;
 
2791
      break;
 
2792
    default:                    /* Error */
 
2793
      uninum_err = NS_ERROR_BADCHARACTER;
 
2794
      uninum_badchar = c;
 
2795
      mpz_clear(Result);
 
2796
      return;
 
2797
    }
 
2798
    mpz_mul_ui(Result, Result, 10L);
 
2799
    mpz_add_ui(Result, Result, CurrentValue);
 
2800
  }
 
2801
  mpz_init_set(mpzResult, Result);
 
2802
  mpz_clear(Result);
 
2803
}
 
2804
 
 
2805
static void GreekAlphabeticToInt(mpz_t mpzResult, UTF32 *s) {
 
2806
  unsigned long CurrentValue = 0; 
 
2807
  UTF32 c;
 
2808
  short LeftKeraiaP = 0;
 
2809
  mpz_t Result;
 
2810
 
 
2811
  uninum_err = NS_ERROR_OKAY;
 
2812
  mpz_init(Result);
 
2813
 
 
2814
  while ( (c = *s++) != 0x0000) {
 
2815
    switch (c) {
 
2816
    case 0x0375:
 
2817
      LeftKeraiaP = 1;
 
2818
      break;
 
2819
    case 0x0391:
 
2820
    case 0x03B1:
 
2821
      CurrentValue = 1;
 
2822
      if (LeftKeraiaP) CurrentValue *= 1000; 
 
2823
      LeftKeraiaP = 0;
 
2824
      break;
 
2825
    case 0x0392:
 
2826
    case 0x03B2:
 
2827
      CurrentValue = 2;
 
2828
      if (LeftKeraiaP) CurrentValue *= 1000; 
 
2829
      LeftKeraiaP = 0;
 
2830
      break;
 
2831
    case 0x0393:
 
2832
    case 0x03B3:
 
2833
      CurrentValue = 3;
 
2834
      if (LeftKeraiaP) CurrentValue *= 1000; 
 
2835
      LeftKeraiaP = 0;
 
2836
      break;
 
2837
    case 0x0394:
 
2838
    case 0x03B4:
 
2839
      CurrentValue = 4;
 
2840
      if (LeftKeraiaP) CurrentValue *= 1000; 
 
2841
      LeftKeraiaP = 0;
 
2842
      break;
 
2843
    case 0x0395:
 
2844
    case 0x03B5:
 
2845
      CurrentValue = 5;
 
2846
      if (LeftKeraiaP) CurrentValue *= 1000; 
 
2847
      LeftKeraiaP = 0;
 
2848
      break;
 
2849
    case 0x03DA:                /* Stigma */
 
2850
    case 0x03DB:                /* Small stigma */
 
2851
    case 0x03DC:                /* Digamma */
 
2852
    case 0x03DD:                /* Small digamma */
 
2853
      CurrentValue = 6;
 
2854
      if (LeftKeraiaP) CurrentValue *= 1000; 
 
2855
      LeftKeraiaP = 0;
 
2856
      break;
 
2857
    case 0x0396:
 
2858
    case 0x03B6:
 
2859
      CurrentValue = 7;
 
2860
      if (LeftKeraiaP) CurrentValue *= 1000; 
 
2861
      LeftKeraiaP = 0;
 
2862
      break;
 
2863
    case 0x0397:
 
2864
    case 0x03B7:
 
2865
      CurrentValue = 8;
 
2866
      if (LeftKeraiaP) CurrentValue *= 1000; 
 
2867
      LeftKeraiaP = 0;
 
2868
      break;
 
2869
    case 0x0398:
 
2870
    case 0x03B8:
 
2871
      CurrentValue = 9;
 
2872
      if (LeftKeraiaP) CurrentValue *= 1000; 
 
2873
      LeftKeraiaP = 0;
 
2874
      break;
 
2875
    case 0x0399:
 
2876
    case 0x03B9:
 
2877
      CurrentValue = 10;
 
2878
      LeftKeraiaP = 0;
 
2879
      break;
 
2880
    case 0x039A:
 
2881
    case 0x03BA:
 
2882
      CurrentValue = 20;
 
2883
      LeftKeraiaP = 0;
 
2884
      break;
 
2885
    case 0x039B:
 
2886
    case 0x03BB:
 
2887
      CurrentValue = 30;
 
2888
      LeftKeraiaP = 0;
 
2889
      break;
 
2890
    case 0x039C:
 
2891
    case 0x03BC:
 
2892
      CurrentValue = 40;
 
2893
      LeftKeraiaP = 0;
 
2894
      break;
 
2895
    case 0x039D:
 
2896
    case 0x03BD:
 
2897
      CurrentValue = 50;
 
2898
      LeftKeraiaP = 0;
 
2899
      break;
 
2900
    case 0x039E:
 
2901
    case 0x03BE:
 
2902
      CurrentValue = 60;
 
2903
      LeftKeraiaP = 0;
 
2904
      break;
 
2905
    case 0x039F:
 
2906
    case 0x03BF:
 
2907
      CurrentValue = 70;
 
2908
      LeftKeraiaP = 0;
 
2909
      break;
 
2910
    case 0x03A0:
 
2911
    case 0x03C0:
 
2912
      CurrentValue = 80;
 
2913
      LeftKeraiaP = 0;
 
2914
      break;
 
2915
    case 0x03D8:                /* Koppa */
 
2916
    case 0x03D9:
 
2917
      CurrentValue = 90;
 
2918
      LeftKeraiaP = 0;
 
2919
      break;
 
2920
    case 0x03A1:
 
2921
    case 0x03C1:
 
2922
      CurrentValue = 100;
 
2923
      LeftKeraiaP = 0;
 
2924
      break;
 
2925
    case 0x03A3:
 
2926
    case 0x03C3:
 
2927
      CurrentValue = 200;
 
2928
      LeftKeraiaP = 0;
 
2929
      break;
 
2930
    case 0x03A4:
 
2931
    case 0x03C4:
 
2932
      CurrentValue = 300;
 
2933
      LeftKeraiaP = 0;
 
2934
      break;
 
2935
    case 0x03A5:
 
2936
    case 0x03C5:
 
2937
      CurrentValue = 400;
 
2938
      LeftKeraiaP = 0;
 
2939
      break;
 
2940
    case 0x03A6:
 
2941
    case 0x03C6:
 
2942
      CurrentValue = 500;
 
2943
      LeftKeraiaP = 0;
 
2944
      break;
 
2945
    case 0x03A7:
 
2946
    case 0x03C7:
 
2947
      CurrentValue = 600;
 
2948
      LeftKeraiaP = 0;
 
2949
      break;
 
2950
    case 0x03A8:
 
2951
    case 0x03C8:
 
2952
      CurrentValue = 700;
 
2953
      LeftKeraiaP = 0;
 
2954
      break;
 
2955
    case 0x03A9:
 
2956
    case 0x03C9:
 
2957
      CurrentValue = 800;
 
2958
      LeftKeraiaP = 0;
 
2959
      break;
 
2960
    case 0x03E1:                /* Small sanpi */
 
2961
    case 0x03E0:                /* Sanpi */
 
2962
      CurrentValue = 900;
 
2963
      LeftKeraiaP = 0;
 
2964
      break;
 
2965
    case 0x0374:                /* Right keraia - just marks numbers - no value */
 
2966
      LeftKeraiaP = 0;
 
2967
      break;
 
2968
    default:                    /* Error */
 
2969
      uninum_err = NS_ERROR_BADCHARACTER;
 
2970
      uninum_badchar = c;
 
2971
      mpz_clear(Result);
 
2972
      return;
 
2973
    }
 
2974
    mpz_add_ui(Result, Result, CurrentValue);
 
2975
  }
 
2976
  mpz_init_set(mpzResult, Result);
 
2977
  mpz_clear(Result);
 
2978
  return;
 
2979
}
 
2980
 
 
2981
static void GurmukhiToInt(mpz_t mpzResult, UTF32 *s) {
 
2982
  unsigned long CurrentValue; 
 
2983
  UTF32 c;
 
2984
  mpz_t Result;
 
2985
 
 
2986
  uninum_err = NS_ERROR_OKAY;
 
2987
  mpz_init(Result);
 
2988
 
 
2989
  while ( (c = *s++) != 0x0000) {
 
2990
    switch (c) {
 
2991
    case 0x0A66:
 
2992
      CurrentValue = 0;
 
2993
      break;
 
2994
    case 0x0A67:
 
2995
      CurrentValue = 1;
 
2996
      break;
 
2997
     case 0x0A68:
 
2998
      CurrentValue = 2;
 
2999
      break;
 
3000
    case 0x0A69:
 
3001
      CurrentValue = 3;
 
3002
      break;
 
3003
    case 0x0A6A:
 
3004
      CurrentValue = 4;
 
3005
      break;
 
3006
    case 0x0A6B:
 
3007
      CurrentValue = 5;
 
3008
      break;
 
3009
    case 0x0A6C:
 
3010
      CurrentValue = 6;
 
3011
      break;
 
3012
    case 0x0A6D:
 
3013
      CurrentValue = 7;
 
3014
         break;
 
3015
    case 0x0A6E:
 
3016
      CurrentValue = 8;
 
3017
      break;
 
3018
    case 0x0A6F:
 
3019
      CurrentValue = 9;
 
3020
      break;
 
3021
    default:                    /* Error */
 
3022
      uninum_err = NS_ERROR_BADCHARACTER;
 
3023
      uninum_badchar = c;
 
3024
      mpz_clear(Result);
 
3025
      return;
 
3026
    }
 
3027
    mpz_mul_ui(Result, Result, 10L);
 
3028
    mpz_add_ui(Result, Result, CurrentValue);
 
3029
  }
 
3030
  mpz_init_set(mpzResult, Result);
 
3031
  mpz_clear(Result);
 
3032
}
 
3033
 
 
3034
static void HebrewToInt(mpz_t mpzResult, UTF32 *s) {
 
3035
  unsigned long CurrentValue; 
 
3036
  UTF32 c;
 
3037
  mpz_t Result;
 
3038
  short PrevCharGereshP;
 
3039
 
 
3040
  uninum_err = NS_ERROR_OKAY;
 
3041
  mpz_init(Result);
 
3042
 
 
3043
  while ( (c = *s++) != 0x0000) {
 
3044
    PrevCharGereshP = 0;
 
3045
    switch (c) {
 
3046
    case 0x05D0:
 
3047
      CurrentValue = 1;
 
3048
      break;
 
3049
    case 0x05D1:
 
3050
      CurrentValue = 2;
 
3051
      break;
 
3052
    case 0x05D2:
 
3053
      CurrentValue = 3;
 
3054
      break;
 
3055
    case 0x05D3:
 
3056
      CurrentValue = 4;
 
3057
      break;
 
3058
    case 0x05D4:
 
3059
      CurrentValue = 5;
 
3060
      break;
 
3061
    case 0x05D5:
 
3062
      CurrentValue = 6;
 
3063
      break;
 
3064
    case 0x05D6:
 
3065
      CurrentValue = 7;
 
3066
      break;
 
3067
    case 0x05D7:
 
3068
      CurrentValue = 8;
 
3069
      break;
 
3070
    case 0x05D8:
 
3071
      CurrentValue = 9;
 
3072
      break;
 
3073
    case 0x05D9:
 
3074
      CurrentValue = 10;
 
3075
      break;
 
3076
    case 0x05DB:
 
3077
      CurrentValue = 20;
 
3078
      break;
 
3079
    case 0x05DC:
 
3080
      CurrentValue = 30;
 
3081
      break;
 
3082
    case 0x05DE:
 
3083
      CurrentValue = 40;
 
3084
      break;
 
3085
    case 0x05E0:
 
3086
      CurrentValue = 50;
 
3087
      break;
 
3088
    case 0x05E1:
 
3089
      CurrentValue = 60;
 
3090
      break;
 
3091
    case 0x05E2:
 
3092
      CurrentValue = 70;
 
3093
      break;
 
3094
    case 0x05E4:
 
3095
      CurrentValue = 80;
 
3096
      break;
 
3097
    case 0x05E6:
 
3098
      CurrentValue = 90;
 
3099
      break;
 
3100
    case 0x05E7:
 
3101
      CurrentValue = 100;
 
3102
      break;
 
3103
    case 0x05E8:
 
3104
      CurrentValue = 200;
 
3105
      break;
 
3106
    case 0x05E9:
 
3107
      CurrentValue = 300;
 
3108
      break;
 
3109
    case 0x05EA:
 
3110
      CurrentValue = 400;
 
3111
      break;
 
3112
    case 0x05DA:
 
3113
      CurrentValue = 500;
 
3114
      break;
 
3115
    case 0x05DD:
 
3116
      CurrentValue = 600;
 
3117
      break;
 
3118
    case 0x05DF:
 
3119
      CurrentValue = 700;
 
3120
      break;
 
3121
    case 0x05E3:
 
3122
      CurrentValue = 800;
 
3123
      break;
 
3124
    case 0x05E5:
 
3125
      CurrentValue = 900;
 
3126
      break;
 
3127
    case 0x05F3:                /* geresh */
 
3128
    case 0x0027:                /* apostrophe */
 
3129
      mpz_mul_ui(Result,Result, 1000L);
 
3130
      PrevCharGereshP = 1;
 
3131
      break;
 
3132
    case 0x05F4:                /* gershayim */
 
3133
      break;
 
3134
    case 0x0020:                /* space */
 
3135
      break;
 
3136
    default:                    /* Error */
 
3137
      uninum_err = NS_ERROR_BADCHARACTER;
 
3138
      uninum_badchar = c;
 
3139
      mpz_clear(Result);
 
3140
      return;
 
3141
    }
 
3142
    if(!PrevCharGereshP) mpz_add_ui(Result,Result,CurrentValue);
 
3143
  }
 
3144
  mpz_init_set(mpzResult, Result);
 
3145
  mpz_clear(Result);
 
3146
}
 
3147
 
 
3148
static void KannadaToInt(mpz_t mpzResult, UTF32 *s) {
 
3149
  unsigned long CurrentValue; 
 
3150
  UTF32 c;
 
3151
  mpz_t Result;
 
3152
 
 
3153
  uninum_err = NS_ERROR_OKAY;
 
3154
  mpz_init(Result);
 
3155
 
 
3156
  while ( (c = *s++) != 0x0000) {
 
3157
    switch (c) {
 
3158
    case 0x0CE6:
 
3159
      CurrentValue = 0;
 
3160
      break;
 
3161
    case 0x0CE7:
 
3162
      CurrentValue = 1;
 
3163
      break;
 
3164
    case 0x0CE8:
 
3165
      CurrentValue = 2;
 
3166
      break;
 
3167
    case 0x0CE9:
 
3168
      CurrentValue = 3;
 
3169
      break;
 
3170
    case 0x0CEA:
 
3171
      CurrentValue = 4;
 
3172
      break;
 
3173
    case 0x0CEB:
 
3174
      CurrentValue = 5;
 
3175
      break;
 
3176
    case 0x0CEC:
 
3177
      CurrentValue = 6;
 
3178
      break;
 
3179
    case 0x0CED:
 
3180
      CurrentValue = 7;
 
3181
         break;
 
3182
    case 0x0CEE:
 
3183
      CurrentValue = 8;
 
3184
      break;
 
3185
    case 0x0CEF:
 
3186
      CurrentValue = 9;
 
3187
      break;
 
3188
    default:                    /* Error */
 
3189
      uninum_err = NS_ERROR_BADCHARACTER;
 
3190
      uninum_badchar = c;
 
3191
      mpz_clear(Result);
 
3192
      return;
 
3193
    }
 
3194
    mpz_mul_ui(Result, Result, 10L);
 
3195
    mpz_add_ui(Result, Result, CurrentValue);
 
3196
  }
 
3197
  mpz_init_set(mpzResult, Result);
 
3198
  mpz_clear(Result);
 
3199
}
 
3200
 
 
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
 
3207
 
 
3208
/* 
 
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.
 
3213
 */
 
3214
 
 
3215
static unsigned long KharoshthiToInt_NAMPZ(UTF32 *s) {
 
3216
  unsigned long Total;
 
3217
  unsigned long CurrentValue; 
 
3218
  UTF32 c;
 
3219
  UTF32 *p;
 
3220
  UTF32 *thptr;
 
3221
  UTF32 *huptr;
 
3222
  UTF32 *wrkcpy;
 
3223
 
 
3224
  Total = 0L;
 
3225
#ifdef ALLOCAOK
 
3226
  wrkcpy = alloca(sizeof(UTF32) * (1 + ucslen(s)));
 
3227
#else
 
3228
  wrkcpy = malloc(sizeof(UTF32) * (1 + ucslen(s)));
 
3229
#endif
 
3230
  if(wrkcpy) ucscpy(wrkcpy,s);
 
3231
  else {
 
3232
    uninum_err = NS_ERROR_OUTOFMEMORY;
 
3233
    return 0;
 
3234
  }
 
3235
 
 
3236
  /* Handle thousands */
 
3237
  thptr = ucsrchr(wrkcpy,KHAROSHTHI_THOUSAND);
 
3238
  if(thptr) {
 
3239
    Total += (1000L * KharoshthiToInt_NAMPZ(thptr+1));
 
3240
    *thptr = 0x0000;
 
3241
  }
 
3242
 
 
3243
  /* Handle hundreds */
 
3244
  huptr = ucsrchr(wrkcpy,KHAROSHTHI_HUNDRED);
 
3245
  if(huptr) {
 
3246
    Total += (100L * KharoshthiToInt_NAMPZ(huptr+1));
 
3247
    *huptr = 0x0000;
 
3248
  }
 
3249
 
 
3250
  /* Handle the additive component - decades and units */
 
3251
  p = wrkcpy;
 
3252
  while ((c = *p++) != 0x0000) {
 
3253
    switch (c) {
 
3254
    case 0x10A40:
 
3255
      CurrentValue = 1;
 
3256
      break;
 
3257
    case 0x10A41:
 
3258
      CurrentValue = 2;
 
3259
      break;
 
3260
    case 0x10A42:
 
3261
      CurrentValue = 3;
 
3262
      break;
 
3263
    case 0x10A43:
 
3264
      CurrentValue = 4;
 
3265
      break;
 
3266
    case 0x10A44:
 
3267
      CurrentValue = 10;
 
3268
      break;
 
3269
    case 0x10A45:
 
3270
      CurrentValue = 20;
 
3271
      break;
 
3272
    default:                    /* Error */
 
3273
      uninum_err = NS_ERROR_BADCHARACTER;
 
3274
      uninum_badchar = c;
 
3275
      return 0;
 
3276
    }
 
3277
    Total += CurrentValue;
 
3278
  }
 
3279
#ifndef ALLOCAOK
 
3280
  free(wrkcpy);
 
3281
#endif
 
3282
  return(Total);
 
3283
}
 
3284
 
 
3285
static void KharoshthiToInt(mpz_t mpzResult, UTF32 *s) {
 
3286
  uninum_err = NS_ERROR_OKAY;
 
3287
  wcsrev(s);
 
3288
  mpz_init_set_ui(mpzResult,KharoshthiToInt_NAMPZ(s));
 
3289
}
 
3290
 
 
3291
 
 
3292
static void KhmerToInt(mpz_t mpzResult, UTF32 *s) {
 
3293
  unsigned long CurrentValue; 
 
3294
  UTF32 c;
 
3295
  mpz_t Result;
 
3296
 
 
3297
  uninum_err = NS_ERROR_OKAY;
 
3298
  mpz_init(Result);
 
3299
 
 
3300
  while ( (c = *s++) != 0x0000) {
 
3301
    switch (c) {
 
3302
    case 0x17E0:
 
3303
      CurrentValue = 0;
 
3304
      break;
 
3305
    case 0x17E1:
 
3306
      CurrentValue = 1;
 
3307
      break;
 
3308
    case 0x17E2:
 
3309
      CurrentValue = 2;
 
3310
      break;
 
3311
    case 0x17E3:
 
3312
      CurrentValue = 3;
 
3313
      break;
 
3314
    case 0x17E4:
 
3315
      CurrentValue = 4;
 
3316
      break;
 
3317
    case 0x17E5:
 
3318
      CurrentValue = 5;
 
3319
      break;
 
3320
    case 0x17E6:
 
3321
      CurrentValue = 6;
 
3322
      break;
 
3323
    case 0x17E7:
 
3324
      CurrentValue = 7;
 
3325
         break;
 
3326
    case 0x17E8:
 
3327
      CurrentValue = 8;
 
3328
      break;
 
3329
    case 0x17E9:
 
3330
      CurrentValue = 9;
 
3331
      break;
 
3332
    default:                    /* Error */
 
3333
      uninum_err = NS_ERROR_BADCHARACTER;
 
3334
      uninum_badchar = c;
 
3335
      mpz_clear(Result);
 
3336
      return;
 
3337
    }
 
3338
    mpz_mul_ui(Result, Result, 10L);
 
3339
    mpz_add_ui(Result, Result, CurrentValue);
 
3340
  }
 
3341
  mpz_init_set(mpzResult, Result);
 
3342
  mpz_clear(Result);
 
3343
}
 
3344
 
 
3345
static void KlingonToInt(mpz_t mpzResult, UTF32 *s) {
 
3346
  unsigned long CurrentValue; 
 
3347
  UTF32 c;
 
3348
  mpz_t Result;
 
3349
 
 
3350
  uninum_err = NS_ERROR_OKAY;
 
3351
  mpz_init(Result);
 
3352
 
 
3353
  while ( (c = *s++) != 0x0000) {
 
3354
    switch (c) {
 
3355
    case 0xF8F0:
 
3356
      CurrentValue = 0;
 
3357
      break;
 
3358
    case 0xF8F1:
 
3359
      CurrentValue = 1;
 
3360
      break;
 
3361
    case 0xF8F2:
 
3362
      CurrentValue = 2;
 
3363
      break;
 
3364
    case 0xF8F3:
 
3365
      CurrentValue = 3;
 
3366
      break;
 
3367
    case 0xF8F4:
 
3368
      CurrentValue = 4;
 
3369
      break;
 
3370
    case 0xF8F5:
 
3371
      CurrentValue = 5;
 
3372
      break;
 
3373
    case 0xF8F6:
 
3374
      CurrentValue = 6;
 
3375
      break;
 
3376
    case 0xF8F7:
 
3377
      CurrentValue = 7;
 
3378
         break;
 
3379
    case 0xF8F8:
 
3380
      CurrentValue = 8;
 
3381
      break;
 
3382
    case 0xF8F9:
 
3383
      CurrentValue = 9;
 
3384
      break;
 
3385
    default:                    /* Error */
 
3386
      uninum_err = NS_ERROR_BADCHARACTER;
 
3387
      uninum_badchar = c;
 
3388
      mpz_clear(Result);
 
3389
      return;
 
3390
    }
 
3391
    mpz_mul_ui(Result, Result, 10L);
 
3392
    mpz_add_ui(Result, Result, CurrentValue);
 
3393
  }
 
3394
  mpz_init_set(mpzResult, Result);
 
3395
  mpz_clear(Result);
 
3396
}
 
3397
 
 
3398
static void LaoToInt(mpz_t mpzResult, UTF32 *s) {
 
3399
  unsigned long CurrentValue; 
 
3400
  UTF32 c;
 
3401
  mpz_t Result;
 
3402
 
 
3403
  uninum_err = NS_ERROR_OKAY;
 
3404
  mpz_init(Result);
 
3405
 
 
3406
  while ( (c = *s++) != 0x0000) {
 
3407
    switch (c) {
 
3408
    case 0x0ED0:
 
3409
      CurrentValue = 0;
 
3410
      break;
 
3411
    case 0x0ED1:
 
3412
      CurrentValue = 1;
 
3413
      break;
 
3414
     case 0x0ED2:
 
3415
      CurrentValue = 2;
 
3416
      break;
 
3417
    case 0x0ED3:
 
3418
      CurrentValue = 3;
 
3419
      break;
 
3420
    case 0x0ED4:
 
3421
      CurrentValue = 4;
 
3422
      break;
 
3423
    case 0x0ED5:
 
3424
      CurrentValue = 5;
 
3425
      break;
 
3426
    case 0x0ED6:
 
3427
      CurrentValue = 6;
 
3428
      break;
 
3429
    case 0x0ED7:
 
3430
      CurrentValue = 7;
 
3431
         break;
 
3432
    case 0x0ED8:
 
3433
      CurrentValue = 8;
 
3434
      break;
 
3435
    case 0x0ED9:
 
3436
      CurrentValue = 9;
 
3437
      break;
 
3438
    default:                    /* Error */
 
3439
      uninum_err = NS_ERROR_BADCHARACTER;
 
3440
      uninum_badchar = c;
 
3441
      mpz_clear(Result);
 
3442
      return;
 
3443
    }
 
3444
    mpz_mul_ui(Result, Result, 10L);
 
3445
    mpz_add_ui(Result, Result, CurrentValue);
 
3446
  }
 
3447
  mpz_init_set(mpzResult, Result);
 
3448
  mpz_clear(Result);
 
3449
}
 
3450
 
 
3451
static void LimbuToInt(mpz_t mpzResult, UTF32 *s) {
 
3452
  unsigned long CurrentValue; 
 
3453
  UTF32 c;
 
3454
  mpz_t Result;
 
3455
 
 
3456
  uninum_err = NS_ERROR_OKAY;
 
3457
  mpz_init(Result);
 
3458
 
 
3459
  while ( (c = *s++) != 0x0000) {
 
3460
    switch (c) {
 
3461
    case 0x1946:
 
3462
      CurrentValue = 0;
 
3463
      break;
 
3464
    case 0x1947:
 
3465
      CurrentValue = 1;
 
3466
      break;
 
3467
    case 0x1948:
 
3468
      CurrentValue = 2;
 
3469
      break;
 
3470
    case 0x1949:
 
3471
      CurrentValue = 3;
 
3472
      break;
 
3473
    case 0x194A:
 
3474
      CurrentValue = 4;
 
3475
      break;
 
3476
    case 0x194B:
 
3477
      CurrentValue = 5;
 
3478
      break;
 
3479
    case 0x194C:
 
3480
      CurrentValue = 6;
 
3481
      break;
 
3482
    case 0x194D:
 
3483
      CurrentValue = 7;
 
3484
         break;
 
3485
    case 0x194E:
 
3486
      CurrentValue = 8;
 
3487
      break;
 
3488
    case 0x194F:
 
3489
      CurrentValue = 9;
 
3490
      break;
 
3491
    default:                    /* Error */
 
3492
      uninum_err = NS_ERROR_BADCHARACTER;
 
3493
      uninum_badchar = c;
 
3494
      mpz_clear(Result);
 
3495
      return;
 
3496
    }
 
3497
    mpz_mul_ui(Result, Result, 10L);
 
3498
    mpz_add_ui(Result, Result, CurrentValue);
 
3499
  }
 
3500
  mpz_init_set(mpzResult, Result);
 
3501
  mpz_clear(Result);
 
3502
}
 
3503
 
 
3504
static void MalayalamToInt(mpz_t mpzResult, UTF32 *s) {
 
3505
  unsigned long CurrentValue; 
 
3506
  UTF32 c;
 
3507
  mpz_t Result;
 
3508
 
 
3509
  uninum_err = NS_ERROR_OKAY;
 
3510
  mpz_init(Result);
 
3511
 
 
3512
  while ( (c = *s++) != 0x0000) {
 
3513
    switch (c) {
 
3514
    case 0x0D66:
 
3515
      CurrentValue = 0;
 
3516
      break;
 
3517
    case 0x0D67:
 
3518
      CurrentValue = 1;
 
3519
      break;
 
3520
    case 0x0D68:
 
3521
      CurrentValue = 2;
 
3522
      break;
 
3523
    case 0x0D69:
 
3524
      CurrentValue = 3;
 
3525
      break;
 
3526
    case 0x0D6A:
 
3527
      CurrentValue = 4;
 
3528
      break;
 
3529
    case 0x0D6B:
 
3530
      CurrentValue = 5;
 
3531
      break;
 
3532
    case 0x0D6C:
 
3533
      CurrentValue = 6;
 
3534
      break;
 
3535
    case 0x0D6D:
 
3536
      CurrentValue = 7;
 
3537
      break;
 
3538
    case 0x0D6E:
 
3539
      CurrentValue = 8;
 
3540
      break;
 
3541
    case 0x0D6F:
 
3542
      CurrentValue = 9;
 
3543
      break;
 
3544
    default:                    /* Error */
 
3545
      uninum_err = NS_ERROR_BADCHARACTER;
 
3546
      uninum_badchar = c;
 
3547
      mpz_clear(Result);
 
3548
      return;
 
3549
    }
 
3550
    mpz_mul_ui(Result, Result, 10L);
 
3551
    mpz_add_ui(Result, Result, CurrentValue);
 
3552
  }
 
3553
  mpz_init_set(mpzResult, Result);
 
3554
  mpz_clear(Result);
 
3555
}
 
3556
 
 
3557
/* It may be desirable to reduce whitespace to a single space first */
 
3558
/*
 
3559
 * Mayan is not yet encoded so I've made up codepoints in the PUA 
 
3560
 * Expose this subroutine once the encoding is settled.
 
3561
 */
 
3562
 
 
3563
static void MayanToInt(mpz_t mpzResult, UTF32 *s) {
 
3564
  unsigned long CurrentValue; 
 
3565
  int GroupCnt = 1;
 
3566
  UTF32 c;
 
3567
  mpz_t Result;
 
3568
 
 
3569
  uninum_err = NS_ERROR_OKAY;
 
3570
  mpz_init(Result);
 
3571
 
 
3572
  while ((c = *s++) != 0x0000) {
 
3573
    switch (c) {
 
3574
    case 0xFFC0:                /* 0 - shell */
 
3575
      break;
 
3576
    case 0xFFC1:                /* 1 - dot */
 
3577
      CurrentValue = 1;
 
3578
      break;
 
3579
    case 0xFFC2:                /* 5 - bar */
 
3580
      CurrentValue = 5;
 
3581
      break;
 
3582
    case 0x0020:
 
3583
      if (++GroupCnt == 3) mpz_mul_ui(Result,Result,18L);
 
3584
      else mpz_mul_ui(Result,Result,20L);
 
3585
      break;
 
3586
    default:                    /* Error */
 
3587
      uninum_err = NS_ERROR_BADCHARACTER;
 
3588
      uninum_badchar = c;
 
3589
      mpz_clear(Result);
 
3590
      return;
 
3591
    }
 
3592
    mpz_add_ui(Result, Result, CurrentValue);
 
3593
  }
 
3594
  mpz_init_set(mpzResult, Result);
 
3595
  mpz_clear(Result);
 
3596
}
 
3597
 
 
3598
static void MongolianToInt(mpz_t mpzResult, UTF32 *s) {
 
3599
  unsigned long CurrentValue; 
 
3600
  UTF32 c;
 
3601
  mpz_t Result;
 
3602
 
 
3603
  uninum_err = NS_ERROR_OKAY;
 
3604
  mpz_init(Result);
 
3605
 
 
3606
  while ( (c = *s++) != 0x0000) {
 
3607
    switch (c) {
 
3608
    case 0x1810:
 
3609
      CurrentValue = 0;
 
3610
      break;
 
3611
    case 0x1811:
 
3612
      CurrentValue = 1;
 
3613
      break;
 
3614
    case 0x1812:
 
3615
      CurrentValue = 2;
 
3616
      break;
 
3617
    case 0x1813:
 
3618
      CurrentValue = 3;
 
3619
      break;
 
3620
    case 0x1814:
 
3621
      CurrentValue = 4;
 
3622
      break;
 
3623
    case 0x1815:
 
3624
      CurrentValue = 5;
 
3625
      break;
 
3626
    case 0x1816:
 
3627
      CurrentValue = 6;
 
3628
      break;
 
3629
    case 0x1817:
 
3630
      CurrentValue = 7;
 
3631
         break;
 
3632
    case 0x1818:
 
3633
      CurrentValue = 8;
 
3634
      break;
 
3635
    case 0x1819:
 
3636
      CurrentValue = 9;
 
3637
      break;
 
3638
    default:                    /* Error */
 
3639
      uninum_err = NS_ERROR_BADCHARACTER;
 
3640
      uninum_badchar = c;
 
3641
      mpz_clear(Result);
 
3642
      return;
 
3643
    }
 
3644
    mpz_mul_ui(Result, Result, 10L);
 
3645
    mpz_add_ui(Result, Result, CurrentValue);
 
3646
  }
 
3647
  mpz_init_set(mpzResult, Result);
 
3648
  mpz_clear(Result);
 
3649
}
 
3650
 
 
3651
static void NewTaiLueToInt(mpz_t mpzResult, UTF32 *s) {
 
3652
  unsigned long CurrentValue; 
 
3653
  UTF32 c;
 
3654
  mpz_t Result;
 
3655
 
 
3656
  uninum_err = NS_ERROR_OKAY;
 
3657
  mpz_init(Result);
 
3658
 
 
3659
  while ( (c = *s++) != 0x0000) {
 
3660
    switch (c) {
 
3661
    case 0x19D0:
 
3662
      CurrentValue = 0;
 
3663
      break;
 
3664
    case 0x19D1:
 
3665
      CurrentValue = 1;
 
3666
      break;
 
3667
    case 0x19D2:
 
3668
      CurrentValue = 2;
 
3669
      break;
 
3670
    case 0x19D3:
 
3671
      CurrentValue = 3;
 
3672
      break;
 
3673
    case 0x19D4:
 
3674
      CurrentValue = 4;
 
3675
      break;
 
3676
    case 0x19D5:
 
3677
      CurrentValue = 5;
 
3678
      break;
 
3679
    case 0x19D6:
 
3680
      CurrentValue = 6;
 
3681
      break;
 
3682
    case 0x19D7:
 
3683
      CurrentValue = 7;
 
3684
         break;
 
3685
    case 0x19D8:
 
3686
      CurrentValue = 8;
 
3687
      break;
 
3688
    case 0x19D9:
 
3689
      CurrentValue = 9;
 
3690
      break;
 
3691
    default:                    /* Error */
 
3692
      uninum_err = NS_ERROR_BADCHARACTER;
 
3693
      uninum_badchar = c;
 
3694
      mpz_clear(Result);
 
3695
      return;
 
3696
    }
 
3697
    mpz_mul_ui(Result, Result, 10L);
 
3698
    mpz_add_ui(Result, Result, CurrentValue);
 
3699
  }
 
3700
  mpz_init_set(mpzResult, Result);
 
3701
  mpz_clear(Result);
 
3702
}
 
3703
 
 
3704
static void NkoToInt(mpz_t mpzResult, UTF32 *s) {
 
3705
  unsigned long CurrentValue; 
 
3706
  UTF32 c;
 
3707
  mpz_t Result;
 
3708
 
 
3709
  uninum_err = NS_ERROR_OKAY;
 
3710
  mpz_init(Result);
 
3711
 
 
3712
  while ( (c = *s++) != 0x0000) {
 
3713
    switch (c) {
 
3714
    case 0x07C0:
 
3715
      CurrentValue = 0;
 
3716
      break;
 
3717
    case 0x07C1:
 
3718
      CurrentValue = 1;
 
3719
      break;
 
3720
     case 0x07C2:
 
3721
      CurrentValue = 2;
 
3722
      break;
 
3723
    case 0x07C3:
 
3724
      CurrentValue = 3;
 
3725
      break;
 
3726
    case 0x07C4:
 
3727
      CurrentValue = 4;
 
3728
      break;
 
3729
    case 0x07C5:
 
3730
      CurrentValue = 5;
 
3731
      break;
 
3732
    case 0x07C6:
 
3733
      CurrentValue = 6;
 
3734
      break;
 
3735
    case 0x07C7:
 
3736
      CurrentValue = 7;
 
3737
      break;
 
3738
    case 0x07C8:
 
3739
      CurrentValue = 8;
 
3740
      break;
 
3741
    case 0x07C9:
 
3742
      CurrentValue = 9;
 
3743
      break;
 
3744
    default:                    /* Error */
 
3745
      uninum_err = NS_ERROR_BADCHARACTER;
 
3746
      uninum_badchar = c;
 
3747
      mpz_clear(Result);
 
3748
      return;
 
3749
    }
 
3750
    mpz_mul_ui(Result, Result, 10L);
 
3751
    mpz_add_ui(Result, Result, CurrentValue);
 
3752
  }
 
3753
  mpz_init_set(mpzResult, Result);
 
3754
  mpz_clear(Result);
 
3755
}
 
3756
 
 
3757
static void OldItalicToInt(mpz_t mpzResult, UTF32 *s) {
 
3758
  unsigned long CurrentValue; 
 
3759
  UTF32 c;
 
3760
  mpz_t Result;
 
3761
 
 
3762
  uninum_err = NS_ERROR_OKAY;
 
3763
  mpz_init(Result);
 
3764
 
 
3765
  while ((c = *s++) != 0x0000) {
 
3766
    switch (c) {
 
3767
    case 0x10320:               /* 1 */
 
3768
      CurrentValue =1;
 
3769
      break;
 
3770
    case 0x10321:               /* 5 */
 
3771
      CurrentValue =5;
 
3772
      break;
 
3773
    case 0x10322:               /* 10 */
 
3774
      CurrentValue =10;
 
3775
      break;
 
3776
    case 0x10323:               /* 50 */
 
3777
      CurrentValue =50;
 
3778
      break;
 
3779
    default:                    /* Error */
 
3780
      uninum_err = NS_ERROR_BADCHARACTER;
 
3781
      uninum_badchar = c;
 
3782
      mpz_clear(Result);
 
3783
      return;
 
3784
    }
 
3785
    mpz_add_ui(Result,Result,CurrentValue);
 
3786
  }
 
3787
  mpz_init_set(mpzResult, Result);
 
3788
  mpz_clear(Result);
 
3789
}
 
3790
 
 
3791
static void OldPersianToInt(mpz_t mpzResult, UTF32 *s) {
 
3792
  unsigned long CurrentValue; 
 
3793
  UTF32 c;
 
3794
  mpz_t Result;
 
3795
 
 
3796
  uninum_err = NS_ERROR_OKAY;
 
3797
  mpz_init(Result);
 
3798
 
 
3799
  while ((c = *s++) != 0x0000) {
 
3800
    switch (c) {
 
3801
    case 0x103D1:               /* 1 */
 
3802
      CurrentValue = 1;
 
3803
      break;
 
3804
    case 0x103D2:               /* 2 */
 
3805
      CurrentValue = 2;
 
3806
      break;
 
3807
    case 0x103D3:               /* 10 */
 
3808
      CurrentValue = 10;
 
3809
      break;
 
3810
    case 0x103D4:               /* 20 */
 
3811
      CurrentValue = 20;
 
3812
      break;
 
3813
    case 0x103D5:               /* 100 */
 
3814
      CurrentValue = 100;
 
3815
      break;
 
3816
    default:                    /* Error */
 
3817
      uninum_err = NS_ERROR_BADCHARACTER;
 
3818
      uninum_badchar = c;
 
3819
      mpz_clear(Result);
 
3820
      return;
 
3821
    }
 
3822
    mpz_add_ui(Result, Result, CurrentValue);
 
3823
  }
 
3824
  mpz_init_set(mpzResult, Result);
 
3825
  mpz_clear(Result);
 
3826
}
 
3827
 
 
3828
 
 
3829
static void OriyaToInt(mpz_t mpzResult, UTF32 *s) {
 
3830
  unsigned long CurrentValue; 
 
3831
  UTF32 c;
 
3832
  mpz_t Result;
 
3833
 
 
3834
  uninum_err = NS_ERROR_OKAY;
 
3835
  mpz_init(Result);
 
3836
 
 
3837
  while ( (c = *s++) != 0x0000) {
 
3838
    switch (c) {
 
3839
    case 0x0B66:
 
3840
      CurrentValue = 0;
 
3841
      break;
 
3842
    case 0x0B67:
 
3843
      CurrentValue = 1;
 
3844
      break;
 
3845
    case 0x0B68:
 
3846
      CurrentValue = 2;
 
3847
      break;
 
3848
    case 0x0B69:
 
3849
      CurrentValue = 3;
 
3850
      break;
 
3851
    case 0x0B6A:
 
3852
      CurrentValue = 4;
 
3853
      break;
 
3854
    case 0x0B6B:
 
3855
      CurrentValue = 5;
 
3856
      break;
 
3857
    case 0x0B6C:
 
3858
      CurrentValue = 6;
 
3859
      break;
 
3860
    case 0x0B6D:
 
3861
      CurrentValue = 7;
 
3862
         break;
 
3863
    case 0x0B6E:
 
3864
      CurrentValue = 8;
 
3865
      break;
 
3866
    case 0x0B6F:
 
3867
      CurrentValue = 9;
 
3868
      break;
 
3869
    default:                    /* Error */
 
3870
      uninum_err = NS_ERROR_BADCHARACTER;
 
3871
      uninum_badchar = c;
 
3872
      mpz_clear(Result);
 
3873
      return;
 
3874
    }
 
3875
    mpz_mul_ui(Result, Result, 10L);
 
3876
    mpz_add_ui(Result, Result, CurrentValue);
 
3877
  }
 
3878
  mpz_init_set(mpzResult, Result);
 
3879
  mpz_clear(Result);
 
3880
}
 
3881
 
 
3882
static void OsmanyaToInt(mpz_t mpzResult, UTF32 *s) {
 
3883
  unsigned long CurrentValue; 
 
3884
  UTF32 c;
 
3885
  mpz_t Result;
 
3886
 
 
3887
  uninum_err = NS_ERROR_OKAY;
 
3888
  mpz_init(Result);
 
3889
 
 
3890
  while ( (c = *s++) != 0x0000) {
 
3891
    switch (c) {
 
3892
    case 0x104A0:
 
3893
      CurrentValue = 0;
 
3894
      break;
 
3895
    case 0x104A1:
 
3896
      CurrentValue = 1;
 
3897
      break;
 
3898
    case 0x104A2:
 
3899
      CurrentValue = 2;
 
3900
      break;
 
3901
    case 0x104A3:
 
3902
      CurrentValue = 3;
 
3903
      break;
 
3904
    case 0x104A4:
 
3905
      CurrentValue = 4;
 
3906
      break;
 
3907
    case 0x104A5:
 
3908
      CurrentValue = 5;
 
3909
      break;
 
3910
    case 0x104A6:
 
3911
      CurrentValue = 6;
 
3912
      break;
 
3913
    case 0x104A7:
 
3914
      CurrentValue = 7;
 
3915
         break;
 
3916
    case 0x104A8:
 
3917
      CurrentValue = 8;
 
3918
      break;
 
3919
    case 0x104A9:
 
3920
      CurrentValue = 9;
 
3921
      break;
 
3922
    default:                    /* Error */
 
3923
      uninum_err = NS_ERROR_BADCHARACTER;
 
3924
      uninum_badchar = c;
 
3925
      mpz_clear(Result);
 
3926
      return;
 
3927
    }
 
3928
    mpz_mul_ui(Result, Result, 10L);
 
3929
    mpz_add_ui(Result, Result, CurrentValue);
 
3930
  }
 
3931
  mpz_init_set(mpzResult, Result);
 
3932
  mpz_clear(Result);
 
3933
}
 
3934
 
 
3935
static void PhoenicianToInt(mpz_t mpzResult, UTF32 *s) {
 
3936
  unsigned long CurrentValue; 
 
3937
  UTF32 c;
 
3938
  mpz_t Result;
 
3939
 
 
3940
  uninum_err = NS_ERROR_OKAY;
 
3941
  mpz_init(Result);
 
3942
 
 
3943
  while ((c = *s++) != 0x0000) {
 
3944
    switch (c) {
 
3945
    case 0x10916:               /* 1 */
 
3946
      CurrentValue = 1;
 
3947
      break;
 
3948
    case 0x10917:               /* 10 */
 
3949
      CurrentValue = 10;
 
3950
      break;
 
3951
    case 0x10918:               /* 20 */
 
3952
      CurrentValue = 20;
 
3953
      break;
 
3954
    case 0x10919:               /* 100 */
 
3955
      CurrentValue = 100;
 
3956
      break;
 
3957
    default:                    /* Error */
 
3958
      uninum_err = NS_ERROR_BADCHARACTER;
 
3959
      uninum_badchar = c;
 
3960
      mpz_clear(Result);
 
3961
      return;
 
3962
    }
 
3963
    mpz_add_ui(Result, Result, CurrentValue);
 
3964
  }
 
3965
 
 
3966
  mpz_init_set(mpzResult, Result);
 
3967
  mpz_clear(Result);
 
3968
}
 
3969
 
 
3970
static void RomanToInt(mpz_t mpzResult, UTF32 *s) {
 
3971
  unsigned long CurrentValue; 
 
3972
  unsigned long PreviousValue = 0L; 
 
3973
  int Ccnt;
 
3974
  int Rcnt;
 
3975
  UTF32 *p;
 
3976
  UTF32 *t;
 
3977
  UTF32 c;
 
3978
  mpz_t Result;
 
3979
 
 
3980
  uninum_err = NS_ERROR_OKAY;
 
3981
  mpz_init(Result);
 
3982
 
 
3983
  p = s;
 
3984
  while ( (c = *p++) != 0x0000) {
 
3985
    switch (c) {
 
3986
    case 'I':
 
3987
    case 'i':
 
3988
    case 0x2160:
 
3989
    case 0x2170:
 
3990
      CurrentValue = 1;
 
3991
      break;
 
3992
    case 'V':
 
3993
    case 'v':
 
3994
    case 0x2164:
 
3995
    case 0x2174:
 
3996
      CurrentValue = 5;
 
3997
      break;
 
3998
    case 'X':
 
3999
    case 'x':
 
4000
    case 0x2169:
 
4001
    case 0x2179:
 
4002
      CurrentValue = 10;
 
4003
      break;
 
4004
    case 'L':
 
4005
    case 'l':
 
4006
    case 0x216C:
 
4007
    case 0x217C:
 
4008
      CurrentValue = 50;
 
4009
      break;
 
4010
    case 'C':
 
4011
    case 'c':
 
4012
    case 0x216D:
 
4013
    case 0x217D:
 
4014
      CurrentValue = 100;
 
4015
      break;
 
4016
    case 'D':
 
4017
    case 'd':
 
4018
    case 0x216E:
 
4019
    case 0x217E:
 
4020
      CurrentValue = 500;
 
4021
      break;
 
4022
    case 'M':
 
4023
    case 'm':
 
4024
    case 0x216F:
 
4025
    case 0x217F:
 
4026
      CurrentValue = 1000;
 
4027
         break;
 
4028
    case 0x2161:
 
4029
    case 0x2171:
 
4030
      CurrentValue = 2;
 
4031
      break;
 
4032
    case 0x2162:
 
4033
    case 0x2172:
 
4034
      CurrentValue = 3;
 
4035
      break;
 
4036
    case 0x2163:
 
4037
    case 0x2173:
 
4038
      CurrentValue = 4;
 
4039
      break;
 
4040
    case 0x2165:
 
4041
    case 0x2175:
 
4042
      CurrentValue = 6;
 
4043
      break;
 
4044
    case 0x2166:
 
4045
    case 0x2176:
 
4046
      CurrentValue = 7;
 
4047
      break;
 
4048
    case 0x2167:
 
4049
    case 0x2177:
 
4050
      CurrentValue = 8;
 
4051
      break;
 
4052
    case 0x2168:
 
4053
    case 0x2178:
 
4054
      CurrentValue = 9;
 
4055
      break;
 
4056
    case 0x216A:
 
4057
    case 0x217A:
 
4058
      CurrentValue = 11;
 
4059
      break;
 
4060
    case 0x216B:
 
4061
    case 0x217B:
 
4062
      CurrentValue = 12;
 
4063
      break;
 
4064
    case 0x2181:
 
4065
      CurrentValue = 5000;  
 
4066
      break;
 
4067
    case 0x2182:
 
4068
      CurrentValue = 10000;
 
4069
      break;
 
4070
    case 0x0304:
 
4071
    case 0x0305:
 
4072
      CurrentValue = 0;
 
4073
      PreviousValue *= 1000L;
 
4074
      break;
 
4075
    case 0x2183:                /* Reverse C */
 
4076
    case 0x2184:
 
4077
      CurrentValue = 0;
 
4078
      if(PreviousValue != 1) {uninum_err = NS_ERROR_ILLFORMED;mpz_clear(Result);return;}
 
4079
      PreviousValue = 0; 
 
4080
      Ccnt = 0; Rcnt = 1;
 
4081
      t = p-3;                  /* Point at character before  I/i */
 
4082
      while ((t >= s) && ( (*t == 'C') || (*t == 'c') || (*t == 0x216D) || (*t == 0x217D) )) {
 
4083
        t--; Ccnt++;
 
4084
      }
 
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));
 
4091
      p+=(Rcnt-1);
 
4092
      break;
 
4093
    default:                    /* Error */
 
4094
      uninum_err = NS_ERROR_BADCHARACTER;
 
4095
      uninum_badchar = c;
 
4096
      mpz_clear(Result);
 
4097
      return;
 
4098
    }
 
4099
    if (PreviousValue >= CurrentValue) mpz_add_ui(Result,Result,PreviousValue);
 
4100
    else mpz_sub_ui(Result,Result,PreviousValue);
 
4101
    PreviousValue = CurrentValue;
 
4102
  }
 
4103
  if (PreviousValue >= CurrentValue) mpz_add_ui(Result,Result,PreviousValue);
 
4104
  else mpz_sub_ui(Result,Result,PreviousValue);
 
4105
 
 
4106
  mpz_init_set(mpzResult, Result);
 
4107
  mpz_clear(Result);
 
4108
}
 
4109
 
 
4110
static void RussianBrailleToInt(mpz_t mpzResult, UTF32 *s) {
 
4111
  unsigned long CurrentValue; 
 
4112
  UTF32 c;
 
4113
  mpz_t Result;
 
4114
 
 
4115
  uninum_err = NS_ERROR_OKAY;
 
4116
  mpz_init(Result);
 
4117
 
 
4118
  while ( (c = *s++) != 0x0000) {
 
4119
    switch (c) {
 
4120
    case 0x2834:
 
4121
      CurrentValue = 0;
 
4122
      break;
 
4123
    case 0x2802:
 
4124
      CurrentValue = 1;
 
4125
      break;
 
4126
     case 0x2806:
 
4127
      CurrentValue = 2;
 
4128
      break;
 
4129
    case 0x2812:
 
4130
      CurrentValue = 3;
 
4131
      break;
 
4132
    case 0x2832:
 
4133
      CurrentValue = 4;
 
4134
      break;
 
4135
    case 0x2822:
 
4136
      CurrentValue = 5;
 
4137
      break;
 
4138
    case 0x2816:
 
4139
      CurrentValue = 6;
 
4140
      break;
 
4141
    case 0x2836:
 
4142
      CurrentValue = 7;
 
4143
      break;
 
4144
    case 0x2826:
 
4145
      CurrentValue = 8;
 
4146
      break;
 
4147
    case 0x2814:
 
4148
      CurrentValue = 9;
 
4149
      break;
 
4150
    default:                    /* Error */
 
4151
      uninum_err = NS_ERROR_BADCHARACTER;
 
4152
      uninum_badchar = c;
 
4153
      mpz_clear(Result);
 
4154
      return;
 
4155
    }
 
4156
    mpz_mul_ui(Result, Result, 10L);
 
4157
    mpz_add_ui(Result, Result, CurrentValue);
 
4158
  }
 
4159
  mpz_init_set(mpzResult, Result);
 
4160
  mpz_clear(Result);
 
4161
}
 
4162
 
 
4163
/* 
 
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.
 
4167
 */
 
4168
 
 
4169
static void SinhalaToInt(mpz_t mpzResult, UTF32 *s) {
 
4170
  unsigned long CurrentValue; 
 
4171
  UTF32 c;
 
4172
  mpz_t Result;
 
4173
 
 
4174
  uninum_err = NS_ERROR_OKAY;
 
4175
  mpz_init(Result);
 
4176
 
 
4177
  while ((c = *s++) != 0x0000) {
 
4178
    switch (c) {
 
4179
    case 0x0DE7:
 
4180
      CurrentValue = 1;
 
4181
      break;
 
4182
    case 0x0DE8:
 
4183
      CurrentValue = 2;
 
4184
      break;
 
4185
    case 0x0DE9:
 
4186
      CurrentValue = 3;
 
4187
      break;
 
4188
    case 0x0DEA:
 
4189
      CurrentValue = 4;
 
4190
      break;
 
4191
    case 0x0DEB:
 
4192
      CurrentValue = 5;
 
4193
      break;
 
4194
    case 0x0DEC:
 
4195
      CurrentValue = 6;
 
4196
      break;
 
4197
    case 0x0DED:
 
4198
      CurrentValue = 7;
 
4199
      break;
 
4200
    case 0x0DEE:
 
4201
      CurrentValue = 8;
 
4202
      break;
 
4203
    case 0x0DEF:
 
4204
      CurrentValue = 9;
 
4205
      break;
 
4206
    case 0x0DF5:
 
4207
      CurrentValue = 10;
 
4208
      break;
 
4209
    case 0x0DF6:
 
4210
      CurrentValue = 20;
 
4211
      break;
 
4212
    case 0x0DF7:
 
4213
      CurrentValue = 30;
 
4214
      break;
 
4215
    case 0x0DF8:
 
4216
      CurrentValue = 40;
 
4217
      break;
 
4218
    case 0x0DF9:
 
4219
      CurrentValue = 50;
 
4220
      break;
 
4221
    case 0x0DFA:
 
4222
      CurrentValue = 60;
 
4223
      break;
 
4224
    case 0x0DFB:
 
4225
      CurrentValue = 70;
 
4226
      break;
 
4227
    case 0x0DFC:
 
4228
      CurrentValue = 80;
 
4229
      break;
 
4230
    case 0x0DFD:
 
4231
      CurrentValue = 90;
 
4232
      break;
 
4233
    case 0x0DFE:
 
4234
      CurrentValue = 100;
 
4235
      break;
 
4236
    case 0x0DFF:
 
4237
      CurrentValue = 1000;
 
4238
      break;
 
4239
    default:                    /* Error */
 
4240
      uninum_err = NS_ERROR_BADCHARACTER;
 
4241
      uninum_badchar = c;
 
4242
      mpz_clear(Result);
 
4243
      return;
 
4244
    }
 
4245
    mpz_add_ui(Result, Result, CurrentValue);
 
4246
  }
 
4247
  mpz_init_set(mpzResult, Result);
 
4248
  mpz_clear(Result);
 
4249
}
 
4250
 
 
4251
static void TamilPlace (mpz_t Result, UTF32 *s) {
 
4252
  unsigned long CurrentValue;
 
4253
  UTF32 c;
 
4254
 
 
4255
  while ( (c = *s++) != 0x0000) {
 
4256
    switch (c) {
 
4257
    case 0x0BE6:
 
4258
      CurrentValue = 0;
 
4259
      break;
 
4260
    case 0x0BE7:
 
4261
      CurrentValue = 1;
 
4262
      break;
 
4263
    case 0x0BE8:
 
4264
      CurrentValue = 2;
 
4265
      break;
 
4266
    case 0x0BE9:
 
4267
      CurrentValue = 3;
 
4268
      break;
 
4269
    case 0x0BEA:
 
4270
      CurrentValue = 4;
 
4271
      break;
 
4272
    case 0x0BEB:
 
4273
      CurrentValue = 5;
 
4274
      break;
 
4275
    case 0x0BEC:
 
4276
      CurrentValue = 6;
 
4277
      break;
 
4278
    case 0x0BED:
 
4279
      CurrentValue = 7;
 
4280
      break;
 
4281
    case 0x0BEE:
 
4282
      CurrentValue = 8;
 
4283
      break;
 
4284
    case 0x0BEF:
 
4285
      CurrentValue = 9;
 
4286
      break;
 
4287
    default:                    /* Error */
 
4288
      uninum_err = NS_ERROR_BADCHARACTER;
 
4289
      uninum_badchar = c;
 
4290
      mpz_clear(Result);
 
4291
      return;
 
4292
    }
 
4293
    mpz_mul_ui(Result,Result,10L);
 
4294
    mpz_add_ui(Result, Result, CurrentValue);
 
4295
  }
 
4296
  return;
 
4297
}
 
4298
 
 
4299
static UTF32 TamilBarriers [] = {
 
4300
  0x0BF0,               /* 10 */
 
4301
  0x0BF1,               /* 100 */
 
4302
  0x0BF2                /* 1000 */
 
4303
};
 
4304
 
 
4305
static unsigned long TamilBarrierValue [] = {
 
4306
  10L,
 
4307
  100L,
 
4308
  1000L
 
4309
};
 
4310
 
 
4311
static inline UTF32 *SeekTamilBarrier (UTF32 *s, int *ri) {
 
4312
  UTF32 *ptr;
 
4313
  int bi = (sizeof(TamilBarriers)/sizeof(UTF32))-1;
 
4314
 
 
4315
  ptr = NULL;
 
4316
  while (ptr == NULL && bi >= 0) {
 
4317
    ptr = ucschr(s,TamilBarriers[bi--]);
 
4318
  }
 
4319
  *ri = bi+1;
 
4320
  return ptr;
 
4321
}
 
4322
 
 
4323
 
 
4324
static void TamilToInt_MPZ(mpz_t ReturnValue, UTF32 *s) {
 
4325
  UTF32 *ptr;
 
4326
  UTF32 SavedBarrier;
 
4327
  int i;
 
4328
  mpz_t mul;
 
4329
  mpz_t Result;
 
4330
  mpz_t RightValue;
 
4331
 
 
4332
  ptr = SeekTamilBarrier(s,&i);
 
4333
  if (ptr == NULL) {
 
4334
    TamilPlace(ReturnValue,s);
 
4335
    return;
 
4336
  }
 
4337
 
 
4338
  mpz_init(mul);
 
4339
  mpz_init(Result);
 
4340
  mpz_init(RightValue);
 
4341
 
 
4342
  SavedBarrier = *ptr; *ptr = 0x0000;
 
4343
  TamilToInt_MPZ(mul,s);
 
4344
  *ptr = SavedBarrier;
 
4345
  if (UEQ(mul,0L)) mpz_set_ui(mul,1L);
 
4346
 
 
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);
 
4351
  mpz_clear(Result);
 
4352
  mpz_clear(RightValue);
 
4353
  mpz_clear(mul);
 
4354
  return;
 
4355
}
 
4356
 
 
4357
static void TamilToInt(mpz_t mpzResult, UTF32 *s) {
 
4358
  mpz_t Result;
 
4359
 
 
4360
  uninum_err = NS_ERROR_OKAY;
 
4361
  mpz_init(Result);
 
4362
  TamilToInt_MPZ(Result,s);
 
4363
  mpz_init_set(mpzResult, Result);
 
4364
  mpz_clear(Result);
 
4365
}
 
4366
 
 
4367
static void TeluguToInt(mpz_t mpzResult, UTF32 *s) {
 
4368
  unsigned long CurrentValue; 
 
4369
  UTF32 c;
 
4370
  mpz_t Result;
 
4371
 
 
4372
  uninum_err = NS_ERROR_OKAY;
 
4373
  mpz_init(Result);
 
4374
 
 
4375
  while ( (c = *s++) != 0x0000) {
 
4376
    switch (c) {
 
4377
    case 0x0C66:
 
4378
      CurrentValue = 0;
 
4379
      break;
 
4380
    case 0x0C67:
 
4381
      CurrentValue = 1;
 
4382
      break;
 
4383
    case 0x0C68:
 
4384
      CurrentValue = 2;
 
4385
      break;
 
4386
    case 0x0C69:
 
4387
      CurrentValue = 3;
 
4388
      break;
 
4389
    case 0x0C6A:
 
4390
      CurrentValue = 4;
 
4391
      break;
 
4392
    case 0x0C6B:
 
4393
      CurrentValue = 5;
 
4394
      break;
 
4395
    case 0x0C6C:
 
4396
      CurrentValue = 6;
 
4397
      break;
 
4398
    case 0x0C6D:
 
4399
      CurrentValue = 7;
 
4400
         break;
 
4401
    case 0x0C6E:
 
4402
      CurrentValue = 8;
 
4403
      break;
 
4404
    case 0x0C6F:
 
4405
      CurrentValue = 9;
 
4406
      break;
 
4407
    default:                    /* Error */
 
4408
      uninum_err = NS_ERROR_BADCHARACTER;
 
4409
      uninum_badchar = c;
 
4410
      mpz_clear(Result);
 
4411
      return;
 
4412
    }
 
4413
    mpz_mul_ui(Result, Result, 10L);
 
4414
    mpz_add_ui(Result, Result, CurrentValue);
 
4415
  }
 
4416
  mpz_init_set(mpzResult, Result);
 
4417
  mpz_clear(Result);
 
4418
}
 
4419
 
 
4420
static void TengwarToInt(mpz_t mpzResult, UTF32 *s) {
 
4421
  unsigned long CurrentValue = 0L; 
 
4422
  UTF32 *p;
 
4423
  UTF32 c;
 
4424
  int Base;
 
4425
  mpz_t Result;
 
4426
 
 
4427
  uninum_err = NS_ERROR_OKAY;
 
4428
 
 
4429
  if(ucslen(s) % 2 != 0) {
 
4430
    uninum_err = NS_ERROR_ILLFORMED;
 
4431
    return;
 
4432
  }
 
4433
 
 
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;
 
4437
  else {
 
4438
    uninum_err = NS_ERROR_ILLFORMED;
 
4439
    return;
 
4440
  }
 
4441
  wcsrev(s);
 
4442
 
 
4443
  p = s;
 
4444
  mpz_init(Result);
 
4445
  while ((c = *p++) != 0L) {
 
4446
    switch (c) {
 
4447
    case TENGWAR_DECIMAL_MARKER:
 
4448
    case TENGWAR_DUODECIMAL_MARKER:
 
4449
    case TENGWAR_DUODECIMAL_LSD_MARKER:
 
4450
      continue;
 
4451
    case 0xE030:
 
4452
      CurrentValue = 0;
 
4453
      break;
 
4454
    case 0xE033:
 
4455
      CurrentValue = 1;
 
4456
      break;
 
4457
     case 0xE062:
 
4458
      CurrentValue = 2;
 
4459
      break;
 
4460
    case 0xE063:
 
4461
      CurrentValue = 3;
 
4462
      break;
 
4463
    case 0xE064:
 
4464
      CurrentValue = 4;
 
4465
      break;
 
4466
    case 0xE065:
 
4467
      CurrentValue = 5;
 
4468
      break;
 
4469
    case 0xE066:
 
4470
      CurrentValue = 6;
 
4471
      break;
 
4472
    case 0xE067:
 
4473
      CurrentValue = 7;
 
4474
      break;
 
4475
    case 0xE068:
 
4476
      CurrentValue = 8;
 
4477
      break;
 
4478
    case 0xE069:
 
4479
      CurrentValue = 9;
 
4480
      break;
 
4481
    case 0xE06A:
 
4482
      CurrentValue = 10;
 
4483
      break;
 
4484
    case 0xE06B:
 
4485
      CurrentValue = 11;
 
4486
      break;
 
4487
    default:                    /* Error */
 
4488
      uninum_err = NS_ERROR_BADCHARACTER;
 
4489
      uninum_badchar = c;
 
4490
      mpz_clear(Result);
 
4491
      return;
 
4492
    }
 
4493
    mpz_mul_ui(Result, Result, Base);
 
4494
    mpz_add_ui(Result, Result, CurrentValue);
 
4495
  }
 
4496
  mpz_init_set(mpzResult, Result);
 
4497
  mpz_clear(Result);
 
4498
}
 
4499
 
 
4500
static void ThaiToInt(mpz_t mpzResult, UTF32 *s) {
 
4501
  unsigned long CurrentValue; 
 
4502
  UTF32 c;
 
4503
  mpz_t Result;
 
4504
 
 
4505
  uninum_err = NS_ERROR_OKAY;
 
4506
  mpz_init(Result);
 
4507
 
 
4508
  while ( (c = *s++) != 0x0000) {
 
4509
    switch (c) {
 
4510
    case 0x0E50:
 
4511
      CurrentValue = 0;
 
4512
      break;
 
4513
    case 0x0E51:
 
4514
      CurrentValue = 1;
 
4515
      break;
 
4516
    case 0x0E52:
 
4517
      CurrentValue = 2;
 
4518
      break;
 
4519
    case 0x0E53:
 
4520
      CurrentValue = 3;
 
4521
      break;
 
4522
    case 0x0E54:
 
4523
      CurrentValue = 4;
 
4524
      break;
 
4525
    case 0x0E55:
 
4526
      CurrentValue = 5;
 
4527
      break;
 
4528
    case 0x0E56:
 
4529
      CurrentValue = 6;
 
4530
      break;
 
4531
    case 0x0E57:
 
4532
      CurrentValue = 7;
 
4533
      break;
 
4534
    case 0x0E58:
 
4535
      CurrentValue = 8;
 
4536
      break;
 
4537
    case 0x0E59:
 
4538
      CurrentValue = 9;
 
4539
      break;
 
4540
    default:                    /* Error */
 
4541
      uninum_err = NS_ERROR_BADCHARACTER;
 
4542
      uninum_badchar = c;
 
4543
      mpz_clear(Result);
 
4544
      return;
 
4545
    }
 
4546
    mpz_mul_ui(Result, Result, 10L);
 
4547
    mpz_add_ui(Result, Result, CurrentValue);
 
4548
  }
 
4549
  mpz_init_set(mpzResult, Result);
 
4550
  mpz_clear(Result);
 
4551
}
 
4552
 
 
4553
static void TibetanToInt(mpz_t mpzResult, UTF32 *s) {
 
4554
  unsigned long CurrentValue; 
 
4555
  UTF32 c;
 
4556
  mpz_t Result;
 
4557
 
 
4558
  uninum_err = NS_ERROR_OKAY;
 
4559
  mpz_init(Result);
 
4560
 
 
4561
  while ( (c = *s++) != 0x0000) {
 
4562
    switch (c) {
 
4563
    case 0x0F20:
 
4564
      CurrentValue = 0;
 
4565
      break;
 
4566
    case 0x0F21:
 
4567
      CurrentValue = 1;
 
4568
      break;
 
4569
     case 0x0F22:
 
4570
      CurrentValue = 2;
 
4571
      break;
 
4572
    case 0x0F23:
 
4573
      CurrentValue = 3;
 
4574
      break;
 
4575
    case 0x0F24:
 
4576
      CurrentValue = 4;
 
4577
      break;
 
4578
    case 0x0F25:
 
4579
      CurrentValue = 5;
 
4580
      break;
 
4581
    case 0x0F26:
 
4582
      CurrentValue = 6;
 
4583
      break;
 
4584
    case 0x0F27:
 
4585
      CurrentValue = 7;
 
4586
      break;
 
4587
    case 0x0F28:
 
4588
      CurrentValue = 8;
 
4589
      break;
 
4590
    case 0x0F29:
 
4591
      CurrentValue = 9;
 
4592
      break;
 
4593
    default:                    /* Error */
 
4594
      uninum_err = NS_ERROR_BADCHARACTER;
 
4595
      uninum_badchar = c;
 
4596
      mpz_clear(Result);
 
4597
      return;
 
4598
    }
 
4599
    mpz_mul_ui(Result, Result, 10L);
 
4600
    mpz_add_ui(Result, Result, CurrentValue);
 
4601
  }
 
4602
  mpz_init_set(mpzResult, Result);
 
4603
  mpz_clear(Result);
 
4604
}
 
4605
 
 
4606
static void VerdurianToInt(mpz_t mpzResult, UTF32 *s) {
 
4607
  unsigned long CurrentValue; 
 
4608
  UTF32 c;
 
4609
  mpz_t Result;
 
4610
 
 
4611
  uninum_err = NS_ERROR_OKAY;
 
4612
  mpz_init(Result);
 
4613
 
 
4614
  while ( (c = *s++) != 0L) {
 
4615
    switch (c) {
 
4616
    case 0xE260:
 
4617
      CurrentValue = 0;
 
4618
      break;
 
4619
    case 0xE261:
 
4620
      CurrentValue = 1;
 
4621
      break;
 
4622
    case 0xE262:
 
4623
      CurrentValue = 2;
 
4624
      break;
 
4625
    case 0xE263:
 
4626
      CurrentValue = 3;
 
4627
      break;
 
4628
    case 0xE264:
 
4629
      CurrentValue = 4;
 
4630
      break;
 
4631
    case 0xE265:
 
4632
      CurrentValue = 5;
 
4633
      break;
 
4634
    case 0xE266:
 
4635
      CurrentValue = 6;
 
4636
      break;
 
4637
    case 0xE267:
 
4638
      CurrentValue = 7;
 
4639
         break;
 
4640
    case 0xE268:
 
4641
      CurrentValue = 8;
 
4642
      break;
 
4643
    case 0xE269:
 
4644
      CurrentValue = 9;
 
4645
      break;
 
4646
    default:                    /* Error */
 
4647
      uninum_err = NS_ERROR_BADCHARACTER;
 
4648
      uninum_badchar = c;
 
4649
      mpz_clear(Result);
 
4650
      return;
 
4651
    }
 
4652
    mpz_mul_ui(Result, Result, 10L);
 
4653
    mpz_add_ui(Result, Result, CurrentValue);
 
4654
  }
 
4655
  mpz_init_set(mpzResult, Result);
 
4656
  mpz_clear(Result);
 
4657
}
 
4658
 
 
4659
void WesternGeneralToInt(mpz_t mpzResult, UTF32 *s, int Base) {
 
4660
  unsigned long CurrentValue; 
 
4661
  UTF32 c;
 
4662
  mpz_t Result;
 
4663
  unsigned long b;
 
4664
 
 
4665
  uninum_err = NS_ERROR_OKAY;
 
4666
  if ((Base > 36) || (Base < 1)) {
 
4667
    uninum_err = NS_ERROR_BADBASE;
 
4668
    return;
 
4669
  }
 
4670
  if(Base == 1) {
 
4671
    mpz_init_set_ui(mpzResult, ucslen(s));
 
4672
    return;
 
4673
  }
 
4674
 
 
4675
  b = (unsigned long) Base;
 
4676
  mpz_init(Result);
 
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;
 
4681
    else {
 
4682
      uninum_err = NS_ERROR_BADCHARACTER;
 
4683
      uninum_badchar = c;
 
4684
      mpz_clear(Result);
 
4685
      return;
 
4686
    }
 
4687
    if (CurrentValue >= b) {
 
4688
      uninum_err = NS_ERROR_NOTCONSISTENTWITHBASE;
 
4689
      mpz_clear(Result);
 
4690
      return;
 
4691
    }
 
4692
    mpz_mul_ui(Result, Result, b);
 
4693
    mpz_add_ui(Result, Result, CurrentValue);
 
4694
  }
 
4695
  mpz_init_set(mpzResult, Result);
 
4696
  mpz_clear(Result);
 
4697
}
 
4698
 
 
4699
static void SetRvalZero(union ns_rval *rvalp, short ReturnType) {
 
4700
  switch(ReturnType) {
 
4701
  case NS_TYPE_ULONG:
 
4702
    rvalp->u = 0L;
 
4703
    break;
 
4704
  case NS_TYPE_STRING:
 
4705
    rvalp->s = malloc(2 *sizeof(char));
 
4706
    rvalp->s[0] = '0';
 
4707
    rvalp->s[1] = '\0';
 
4708
    break;
 
4709
  case NS_TYPE_MPZT:
 
4710
    mpz_set_ui(rvalp->m,0L);
 
4711
    break;
 
4712
  }
 
4713
}
 
4714
 
 
4715
void StringToInt(union ns_rval *rvalp, UTF32 *s, short ReturnType,int NumberSystem) {
 
4716
  mpz_t Result;
 
4717
  uninum_err = NS_ERROR_OKAY;
 
4718
  if ((NS_ALL == NumberSystem) || (NS_ANY == NumberSystem)) NumberSystem = GuessNumberSystem(s);
 
4719
 
 
4720
  wcStripSeparators(s);
 
4721
  switch (NumberSystem)
 
4722
    {
 
4723
    case NS_AEGEAN:
 
4724
      AegeanToInt(Result,s);
 
4725
      break;
 
4726
    case NS_ARABIC_WESTERN:
 
4727
      ArabicToInt(Result,s);
 
4728
      break;
 
4729
    case NS_PERSO_ARABIC:
 
4730
      ArabicExtendedToInt(Result,s);
 
4731
      break;
 
4732
    case NS_ARABIC_ALPHABETIC:
 
4733
      ArabicAlphabeticToInt(Result,s);
 
4734
      break;
 
4735
    case NS_ARMENIAN_ALPHABETIC:
 
4736
      ArmenianAlphabeticToInt(Result,s);
 
4737
      break;
 
4738
    case NS_BALINESE:
 
4739
      BalineseToInt(Result,s);
 
4740
      break;
 
4741
    case NS_BENGALI:
 
4742
      BengaliToInt(Result,s);
 
4743
      break;
 
4744
    case NS_BURMESE:
 
4745
      BurmeseToInt(Result,s);
 
4746
      break;
 
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));
 
4764
      break;
 
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);
 
4771
      break;
 
4772
    case NS_COMMON_BRAILLE:
 
4773
      CommonBrailleToInt(Result,s);
 
4774
      break;
 
4775
    case NS_CYRILLIC_ALPHABETIC:
 
4776
      CyrillicAlphabeticToInt(Result,s);
 
4777
      break;
 
4778
    case NS_DEVANAGARI:
 
4779
      DevanagariToInt(Result,s);
 
4780
      break;
 
4781
    case NS_EGYPTIAN:
 
4782
      EgyptianToInt(Result,s);
 
4783
      break;
 
4784
    case NS_ETHIOPIC:
 
4785
      EthiopicToInt(Result,s);
 
4786
      break;
 
4787
    case NS_EWELLIC_DECIMAL:
 
4788
      EwellicDecimalToInt(Result,s);
 
4789
      break;
 
4790
    case NS_EWELLIC_HEX:
 
4791
      EwellicHexToInt(Result,s);
 
4792
      break;
 
4793
    case NS_FRENCH_BRAILLE:
 
4794
      FrenchBrailleToInt(Result,s);
 
4795
      break;
 
4796
    case NS_MXEDRULI:
 
4797
    case NS_XUCURI_LOWER:
 
4798
    case NS_XUCURI_UPPER:
 
4799
      GeorgianAlphabeticToInt(Result,s);
 
4800
      break;
 
4801
    case NS_GLAGOLITIC_ALPHABETIC:
 
4802
      GlagoliticAlphabeticToInt(Result,s);
 
4803
      break;
 
4804
    case NS_GREEK_ALPHABETIC_UPPER:
 
4805
    case NS_GREEK_ALPHABETIC_LOWER:
 
4806
      GreekAlphabeticToInt(Result,s);
 
4807
      break;
 
4808
    case NS_GUJARATI:
 
4809
      GujaratiToInt(Result,s);
 
4810
      break;
 
4811
    case NS_GURMUKHI:
 
4812
      GurmukhiToInt(Result,s);
 
4813
      break;
 
4814
    case NS_HEBREW_GENERIC:
 
4815
    case NS_HEBREW_EARLY:
 
4816
    case NS_HEBREW_LATE:
 
4817
      HebrewToInt(Result,s);
 
4818
      break;
 
4819
    case NS_HEX:
 
4820
    case NS_HEX_LOWER:
 
4821
    case NS_HEX_UPPER:
 
4822
      WesternGeneralToInt(Result,s+2,16);      /* s+2 to skip the initial 0x */
 
4823
      break;
 
4824
    case NS_KANNADA:
 
4825
      KannadaToInt(Result,s);
 
4826
      break;
 
4827
    case NS_KHAROSHTHI:
 
4828
      KharoshthiToInt(Result,s);
 
4829
      break;
 
4830
    case NS_KHMER:
 
4831
      KhmerToInt(Result,s);
 
4832
      break;
 
4833
    case NS_KLINGON:
 
4834
      KlingonToInt(Result,s);
 
4835
      break;
 
4836
    case NS_LAO:
 
4837
      LaoToInt(Result,s);
 
4838
      break;
 
4839
    case NS_LIMBU:
 
4840
      LimbuToInt(Result,s);
 
4841
      break;
 
4842
    case NS_MALAYALAM:
 
4843
      MalayalamToInt(Result,s);
 
4844
      break;
 
4845
    case NS_MAYAN:
 
4846
      MayanToInt(Result,s);
 
4847
      break;
 
4848
    case NS_MONGOLIAN:
 
4849
      MongolianToInt(Result,s);
 
4850
      break;
 
4851
    case NS_NEW_TAI_LUE:
 
4852
      NewTaiLueToInt(Result,s);
 
4853
      break;
 
4854
    case NS_NKO:
 
4855
      NkoToInt(Result,s);
 
4856
      break;
 
4857
    case NS_OLD_ITALIC:
 
4858
      OldItalicToInt(Result,s);
 
4859
      break;
 
4860
    case NS_OLD_PERSIAN:
 
4861
      OldPersianToInt(Result,s);
 
4862
      break;
 
4863
    case NS_ORIYA:
 
4864
      OriyaToInt(Result,s);
 
4865
      break;
 
4866
    case NS_OSMANYA:
 
4867
      OsmanyaToInt(Result,s);
 
4868
      break;
 
4869
    case NS_PHOENICIAN:
 
4870
      PhoenicianToInt(Result,s);
 
4871
      break;
 
4872
    case NS_ROMAN_GENERIC:
 
4873
    case NS_ROMAN_UPPER:
 
4874
    case NS_ROMAN_LOWER:
 
4875
      RomanToInt(Result,s);
 
4876
      break;
 
4877
    case NS_RUSSIAN_BRAILLE:
 
4878
      RussianBrailleToInt(Result,s);
 
4879
      break;
 
4880
    case NS_SINHALA:
 
4881
      SinhalaToInt(Result,s);
 
4882
      break;
 
4883
    case NS_TAMIL_GENERIC:
 
4884
    case NS_TAMIL_PLACE:
 
4885
    case NS_TAMIL_TRADITIONAL:
 
4886
      TamilToInt(Result,s);
 
4887
      break;
 
4888
    case NS_TELUGU:
 
4889
      TeluguToInt(Result,s);
 
4890
      break;
 
4891
    case NS_TENGWAR_DECIMAL:
 
4892
    case NS_TENGWAR_DUODECIMAL:
 
4893
      TengwarToInt(Result,s);
 
4894
      break;
 
4895
    case NS_THAI:
 
4896
      ThaiToInt(Result,s);
 
4897
      break;
 
4898
    case NS_TIBETAN:
 
4899
      TibetanToInt(Result,s);
 
4900
      break;
 
4901
    case NS_VERDURIAN:
 
4902
      VerdurianToInt(Result,s);
 
4903
      break;
 
4904
    case NS_WESTERN_GENERIC:
 
4905
    case NS_WESTERN_LOWER:
 
4906
    case NS_WESTERN_UPPER:
 
4907
      WesternGeneralToInt(Result,s,Uninum_Input_Base);
 
4908
      break;
 
4909
    default:
 
4910
      uninum_err = NS_ERROR_NUMBER_SYSTEM_UNKNOWN;
 
4911
      break;
 
4912
    } /* End of switch */
 
4913
 
 
4914
  if(!uninum_err) {
 
4915
    if (ReturnType == NS_TYPE_STRING) {
 
4916
      rvalp->s = malloc(sizeof(char) * (1 + mpz_sizeinbase(Result,10)));
 
4917
      if(!rvalp->s) {
 
4918
        uninum_err = NS_ERROR_OUTOFMEMORY;
 
4919
        return;
 
4920
      }
 
4921
      (void) mpz_get_str(rvalp->s,10,Result);
 
4922
    }
 
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);
 
4926
    }
 
4927
    else mpz_set(rvalp->m,Result);
 
4928
    mpz_clear(Result);
 
4929
  }
 
4930
  if(uninum_err) SetRvalZero(rvalp,ReturnType);
 
4931
  return;
 
4932
}
 
4933
 
 
4934
 
 
4935
/* Code for generating strings from integers */
 
4936
 
 
4937
/* 
 
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;
 
4941
 */
 
4942
 
 
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
 
4973
 
 
4974
static UTF32 *
 
4975
PlaceIntToString(mpz_t n, UTF32 ZeroCode, unsigned int Base) {
 
4976
  int Digits;                   /* Number of digits in string */
 
4977
  UTF32 *s;
 
4978
  UTF32 *p;
 
4979
  UTF32 *new;
 
4980
  mpz_t d;
 
4981
  mpz_t k;
 
4982
  mpz_t q;
 
4983
  mpz_t r;
 
4984
  unsigned long int temp;
 
4985
  int offset;
 
4986
 
 
4987
  mpz_init(d); 
 
4988
  mpz_init(q); 
 
4989
  mpz_init(r); 
 
4990
  mpz_init_set(k,n);
 
4991
 
 
4992
  Digits = mpz_sizeinbase(k,Base);
 
4993
  new = malloc((Digits + 1) * sizeof(UTF32));
 
4994
  if (!new) {
 
4995
    uninum_err = NS_ERROR_OUTOFMEMORY;
 
4996
    return NULL;
 
4997
  }
 
4998
 
 
4999
  p = s = new;
 
5000
  /* Do conversion */
 
5001
  
 
5002
  do {
 
5003
    mpz_tdiv_qr_ui(q,r,k,Base);
 
5004
    *s++ =  (ZeroCode + mpz_get_ui(r));
 
5005
    mpz_set(k,q);
 
5006
  } while (UGT(q,0L));
 
5007
 
 
5008
  *s = 0x0000;                  /* Null terminate string */
 
5009
  s--;                          /* Point s at last non-null char */
 
5010
 
 
5011
  mpz_clear(d);mpz_clear(k);mpz_clear(q);mpz_clear(r);
 
5012
 
 
5013
  /*
 
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.
 
5016
   */
 
5017
  
 
5018
  while(p <= s){
 
5019
    temp = *p;
 
5020
    *p++ = *s;
 
5021
    *s-- = temp;
 
5022
  }
 
5023
  return new;
 
5024
}
 
5025
 
 
5026
static UTF32 *
 
5027
PlaceNonContiguousIntToString(mpz_t n, UTF32 **DigitList, int Base){
 
5028
  int Digits;                   /* Number of digits in string */
 
5029
  UTF32 *s;
 
5030
  UTF32 *p;
 
5031
  UTF32 *new;
 
5032
  mpz_t k;
 
5033
  mpz_t q;
 
5034
  mpz_t r;
 
5035
  unsigned long int temp;
 
5036
  int offset;
 
5037
 
 
5038
  mpz_init_set(k,n);
 
5039
 
 
5040
  Digits = mpz_sizeinbase(k,Base);
 
5041
  new = malloc((Digits + 1) * sizeof(UTF32));
 
5042
  if (!new) {
 
5043
    uninum_err = NS_ERROR_OUTOFMEMORY;
 
5044
    mpz_clear(k);
 
5045
    return NULL;
 
5046
  }
 
5047
 
 
5048
  p = s = new;
 
5049
  /* Do conversion */
 
5050
 
 
5051
  mpz_init(q); 
 
5052
  mpz_init(r); 
 
5053
  do {
 
5054
    mpz_tdiv_qr_ui(q,r,k,Base);
 
5055
    *s++ =  DigitList[mpz_get_ui(r)][0];
 
5056
    mpz_set(k,q);
 
5057
  } while (UGT(q,0L));
 
5058
 
 
5059
  *s = 0x0000;                  /* Null terminate string */
 
5060
  s--;                          /* Point s at last non-null char */
 
5061
 
 
5062
  mpz_clear(k);mpz_clear(q);mpz_clear(r);
 
5063
 
 
5064
  /*
 
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.
 
5067
   */
 
5068
  
 
5069
  while(p <= s){
 
5070
    temp = *p;
 
5071
    *p++ = *s;
 
5072
    *s-- = temp;
 
5073
  }
 
5074
  return new;
 
5075
}
 
5076
 
 
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};
 
5089
 
 
5090
UTF32 *TengwarDigits[]={
 
5091
  tengd0, tengd1, tengd2, tengd3, tengd4, tengd5,
 
5092
  tengd6, tengd7, tengd8, tengd9, tengd10, tengd11
 
5093
};
 
5094
 
 
5095
 
 
5096
static UTF32 *
 
5097
TengwarToString(mpz_t n,int Base){
 
5098
  int Digits;                   /* Number of digits in string */
 
5099
  UTF32 *s;
 
5100
  UTF32 *new;
 
5101
  UTF32 BaseMarker;
 
5102
  mpz_t k;
 
5103
  mpz_t q;
 
5104
  mpz_t r;
 
5105
 
 
5106
  mpz_init_set(k,n);
 
5107
 
 
5108
  Digits = mpz_sizeinbase(k,Base);
 
5109
  new = malloc(((2 * Digits) + 1) * sizeof(UTF32));
 
5110
  if (!new) {
 
5111
    uninum_err = NS_ERROR_OUTOFMEMORY;
 
5112
    mpz_clear(k);
 
5113
    return NULL;
 
5114
  }
 
5115
 
 
5116
  if(Base == 12) BaseMarker = TENGWAR_DUODECIMAL_MARKER;
 
5117
  else BaseMarker = TENGWAR_DECIMAL_MARKER;
 
5118
 
 
5119
  s = new;
 
5120
  /* Do conversion */
 
5121
 
 
5122
  mpz_init(q); 
 
5123
  mpz_init(r); 
 
5124
  do {
 
5125
    mpz_tdiv_qr_ui(q,r,k,Base);
 
5126
    *s++ = TengwarDigits[mpz_get_ui(r)][0];
 
5127
    *s++ = BaseMarker;
 
5128
    mpz_set(k,q);
 
5129
  } while (UGT(q,0L));
 
5130
  *s = 0L;                      /* Null terminate string */
 
5131
  if(Base == 12) new[1] = TENGWAR_DUODECIMAL_LSD_MARKER;
 
5132
 
 
5133
  mpz_clear(k);mpz_clear(q);mpz_clear(r);
 
5134
  return new;
 
5135
}
 
5136
 
 
5137
 
 
5138
struct vcpair ArabicAlphabeticData[]={
 
5139
  {1999,0xFFDF},
 
5140
  {1000,0x063A},
 
5141
  {900,0x0638},
 
5142
  {800,0x0636},
 
5143
  {700,0x0630},
 
5144
  {600,0x062E},
 
5145
  {500,0x062B},
 
5146
  {400,0x062A},
 
5147
  {300,0x0634},
 
5148
  {200,0x0631},
 
5149
  {100,0x0642},
 
5150
  {90,0x0635},
 
5151
  {80,0x0641},
 
5152
  {70,0x0639},
 
5153
  {60,0x0633},
 
5154
  {50,0x0646},
 
5155
  {40,0x0645},
 
5156
  {30,0x0644},
 
5157
  {20,0x0643},
 
5158
  {10,0x064A},
 
5159
  {9,0x0637},
 
5160
  {8,0x062D},
 
5161
  {7,0x0632},
 
5162
  {6,0x0648},
 
5163
  {5,0x0647},
 
5164
  {4,0x062F},
 
5165
  {3,0x062C},
 
5166
  {2,0x0628},
 
5167
  {1,0x0627},
 
5168
  {0,0xFFDF}
 
5169
};
 
5170
 
 
5171
struct vcpair AegeanData[]={
 
5172
  {99999,0xFFDF},
 
5173
  {90000,0x10133},
 
5174
  {80000,0x10132},
 
5175
  {70000,0x10131},
 
5176
  {60000,0x10130},
 
5177
  {50000,0x1012F},
 
5178
  {40000,0x1012E},
 
5179
  {30000,0x1012D},
 
5180
  {20000,0x1012C},
 
5181
  {10000,0x1012B},
 
5182
  {9000,0x1012A},
 
5183
  {8000,0x10129},
 
5184
  {7000,0x10128},
 
5185
  {6000,0x10127},
 
5186
  {5000,0x10126},
 
5187
  {4000,0x10125},
 
5188
  {3000,0x10124},
 
5189
  {2000,0x10123},
 
5190
  {1000,0x10122},
 
5191
  {900,0x10121},
 
5192
  {800,0x10120},
 
5193
  {700,0x1011F},
 
5194
  {600,0x1011E},
 
5195
  {500,0x1011D},
 
5196
  {400,0x1011C},
 
5197
  {300,0x1011B},
 
5198
  {200,0x1011A},
 
5199
  {100,0x10119},
 
5200
  {90,0x10118},
 
5201
  {80,0x10117},
 
5202
  {70,0x10116},
 
5203
  {60,0x10115},
 
5204
  {50,0x10114},
 
5205
  {40,0x10113},
 
5206
  {30,0x10112},
 
5207
  {20,0x10111},
 
5208
  {10,0x10110},
 
5209
  {9,0x1010F},
 
5210
  {8,0x1010E},
 
5211
  {7,0x1010D},
 
5212
  {6,0x1010C},
 
5213
  {5,0x1010B},
 
5214
  {4,0x1010A},
 
5215
  {3,0x10109},
 
5216
  {2,0x10108},
 
5217
  {1,0x10107},
 
5218
  {0,0xFFDF}
 
5219
};
 
5220
 
 
5221
struct vcpair ArmenianData[]={
 
5222
  {9999,0xFFDF},
 
5223
  {9000,0x0554},
 
5224
  {8000,0x0553},
 
5225
  {7000,0x0552},
 
5226
  {6000,0x0551},
 
5227
  {5000,0x0550},
 
5228
  {4000,0x054F},
 
5229
  {3000,0x054E},
 
5230
  {2000,0x054D},
 
5231
  {1000,0x054C},
 
5232
  {900,0x054B},
 
5233
  {800,0x054A},
 
5234
  {700,0x0549},
 
5235
  {600,0x0548},
 
5236
  {500,0x0547},
 
5237
  {400,0x0546},
 
5238
  {300,0x0545},
 
5239
  {200,0x0544},
 
5240
  {100,0x0543},
 
5241
  {90,0x00542},
 
5242
  {80,0x0541},
 
5243
  {70,0x0540},
 
5244
  {60,0x053F},
 
5245
  {50,0x053E},
 
5246
  {40,0x053D},
 
5247
  {30,0x053C},
 
5248
  {20,0x053B},
 
5249
  {10,0x053A},
 
5250
  {9,0x0539},
 
5251
  {8,0x0538},
 
5252
  {7,0x0537},
 
5253
  {6,0x0536},
 
5254
  {5,0x0535},
 
5255
  {4,0x0534},
 
5256
  {3,0x0533},
 
5257
  {2,0x0532},
 
5258
  {1,0x0531},
 
5259
  {0,0xFFDF}
 
5260
};
 
5261
 
 
5262
struct vcpair CyrillicData[]={
 
5263
  {999,0xFFDF},
 
5264
  {900,0x0426},
 
5265
  {800,0x0460},
 
5266
  {700,0x0470},
 
5267
  {600,0x0425},
 
5268
  {500,0x0424},
 
5269
  {400,0x0478},
 
5270
  {300,0x0422},
 
5271
  {200,0x0421},
 
5272
  {100,0x0420},
 
5273
  {90,0x0427},
 
5274
  {80,0x041F},
 
5275
  {70,0x041E},
 
5276
  {60,0x046E},
 
5277
  {50,0x041D},
 
5278
  {40,0x041C},
 
5279
  {30,0x041B},
 
5280
  {20,0x041A},
 
5281
  {10,0x0406},
 
5282
  {9,0x0472},
 
5283
  {8,0x0418},
 
5284
  {7,0x0417},
 
5285
  {6,0x0405},
 
5286
  {5,0x0415},
 
5287
  {4,0x0414},
 
5288
  {3,0x0413},
 
5289
  {2,0x0411},
 
5290
  {1,0x0410},
 
5291
  {0,0xFFDF}
 
5292
};
 
5293
 
 
5294
struct vcpair EgyptianData[]={
 
5295
  {9999999,0xFFDF},
 
5296
  {1000000,0x14064},
 
5297
  {100000,0x14173},
 
5298
  {10000,0x140A7},
 
5299
  {1000,0x141A2},
 
5300
  {100,0x1433B},
 
5301
  {10,0x14353},
 
5302
  {1,0x143A1},
 
5303
  {0,0xFFDF}
 
5304
};
 
5305
 
 
5306
struct vcpair EthiopicData[]={
 
5307
  {9999999,0xFFDF},             /* Dummy - real max is in subroutine */
 
5308
  {90,0x137A},
 
5309
  {80,0x1379},
 
5310
  {70,0x1378},
 
5311
  {60,0x1377},
 
5312
  {50,0x1376},
 
5313
  {40,0x1375},
 
5314
  {30,0x1374},
 
5315
  {20,0x1373},
 
5316
  {10,0x1372},
 
5317
  {9,0x1371},
 
5318
  {8,0x1370},
 
5319
  {7,0x136F},
 
5320
  {6,0x136E},
 
5321
  {5,0x136D},
 
5322
  {4,0x136C},
 
5323
  {3,0x136B},
 
5324
  {2,0x136A},
 
5325
  {1,0x1369},
 
5326
  {0,0xFFDF}
 
5327
};
 
5328
 
 
5329
struct vcpair GlagoliticData[]={
 
5330
  {9999,0xFFDF},
 
5331
  {2000,0x2C1E},
 
5332
  {1000,0x2C1D},
 
5333
  {900,0x2C1C},
 
5334
  {800,0x2C1B},
 
5335
  {700,0x2C19},
 
5336
  {600,0x2C18},
 
5337
  {500,0x2C17},
 
5338
  {400,0x2C16},
 
5339
  {300,0x2C15},
 
5340
  {200,0x2C14},
 
5341
  {100,0x2C13},
 
5342
  {90,0x2C12},
 
5343
  {80,0x2C11},
 
5344
  {70,0x2C10},
 
5345
  {60,0x2C0F},
 
5346
  {50,0x2C0E},
 
5347
  {40,0x2C0D},
 
5348
  {30,0x2C0C},
 
5349
  {20,0x2C0B},
 
5350
  {10,0x2C09},
 
5351
  {9,0x2C08},
 
5352
  {8,0x2C07},
 
5353
  {7,0x2C06},
 
5354
  {6,0x2C05},
 
5355
  {5,0x2C04},
 
5356
  {4,0x2C03},
 
5357
  {3,0x2C02},
 
5358
  {2,0x2C01},
 
5359
  {1,0x2C00},
 
5360
  {0,0xFFDF}
 
5361
};
 
5362
 
 
5363
struct vcpair GreekUpperData[]={
 
5364
  {9999,0xFFDF},
 
5365
  {900,0x03E0},
 
5366
  {800,0x03A9},
 
5367
  {700,0x03A8},
 
5368
  {600,0x03A7},
 
5369
  {500,0x03A6},
 
5370
  {400,0x03A5},
 
5371
  {300,0x03A4},
 
5372
  {200,0x03A3},
 
5373
  {100,0x03A1},
 
5374
  {90,0x03D8},
 
5375
  {80,0x03A0},
 
5376
  {70,0x039F},
 
5377
  {60,0x039E},
 
5378
  {50,0x039D},
 
5379
  {40,0x039C},
 
5380
  {30,0x039B},
 
5381
  {20,0x039A},
 
5382
  {10,0x0399},
 
5383
  {9,0x0398},
 
5384
  {8,0x0397},
 
5385
  {7,0x0396},
 
5386
  {6,0x03DA},
 
5387
  {5,0x0395},
 
5388
  {4,0x0394},
 
5389
  {3,0x0393},
 
5390
  {2,0x0392},
 
5391
  {1,0x0391},
 
5392
  {0,0xFFDF}
 
5393
};
 
5394
 
 
5395
struct vcpair GreekLowerData[]={
 
5396
  {9999,0xFFDF},
 
5397
  {900,0x03E1},
 
5398
  {800,0x03C9},
 
5399
  {700,0x03C8},
 
5400
  {600,0x03C7},
 
5401
  {500,0x03C6},
 
5402
  {400,0x03C5},
 
5403
  {300,0x03C4},
 
5404
  {200,0x03C3},
 
5405
  {100,0x03C1},
 
5406
  {90,0x03D9},
 
5407
  {80,0x03C0},
 
5408
  {70,0x03BF},
 
5409
  {60,0x03BE},
 
5410
  {50,0x03BD},
 
5411
  {40,0x03BC},
 
5412
  {30,0x03BB},
 
5413
  {20,0x03BA},
 
5414
  {10,0x03B9},
 
5415
  {9,0x03B8},
 
5416
  {8,0x03B7},
 
5417
  {7,0x03B6},
 
5418
  {6,0x03DB},
 
5419
  {5,0x03B5},
 
5420
  {4,0x03B4},
 
5421
  {3,0x03B3},
 
5422
  {2,0x03B2},
 
5423
  {1,0x03B1},
 
5424
  {0,0xFFDF}
 
5425
};
 
5426
 
 
5427
struct vcpair HebrewData[]={
 
5428
  {9999,0xFFDF},
 
5429
  {900,0x05E5},
 
5430
  {800,0x05E3},
 
5431
  {700,0x05DF},
 
5432
  {600,0x05DD},
 
5433
  {500,0x05DA},
 
5434
  {400,0x05EA},
 
5435
  {300,0x05E9},
 
5436
  {200,0x05E8},
 
5437
  {100,0x05E7},
 
5438
  {90,0x05E6},
 
5439
  {80,0x05E4},
 
5440
  {70,0x05E2},
 
5441
  {60,0x05E1},
 
5442
  {50,0x05E0},
 
5443
  {40,0x05DE},
 
5444
  {30,0x05DC},
 
5445
  {20,0x05DB},
 
5446
  {10,0x05D9},
 
5447
  {9,0x05D8},
 
5448
  {8,0x05D7},
 
5449
  {7,0x05D6},
 
5450
  {6,0x05D5},
 
5451
  {5,0x05D4},
 
5452
  {4,0x05D3},
 
5453
  {3,0x05D2},
 
5454
  {2,0x05D1},
 
5455
  {1,0x05D0},
 
5456
  {0,0xFFDF}
 
5457
};
 
5458
 
 
5459
struct vcpair MxedruliData[]={
 
5460
  {10000,0xFFDF},
 
5461
  {10000,0x10f5},
 
5462
  {9000,0x10f0},
 
5463
  {8000,0x10ef},
 
5464
  {7000,0x10f4},
 
5465
  {6000,0x10ee},
 
5466
  {5000,0x10ed},
 
5467
  {4000,0x10ec},
 
5468
  {3000,0x10eb},
 
5469
  {2000,0x10ea},
 
5470
  {1000,0x10e9},
 
5471
  {900,0x10e8},
 
5472
  {800,0x10e7},
 
5473
  {700,0x10e6},
 
5474
  {600,0x10e5},
 
5475
  {500,0x10e4},
 
5476
  {400,0x10e3},
 
5477
  {300,0x10e2},
 
5478
  {200,0x10e1},
 
5479
  {100,0x10e0},
 
5480
  {90,0x10df},
 
5481
  {80,0x10de},
 
5482
  {70,0x10dd},
 
5483
  {60,0x10f2},
 
5484
  {50,0x10dc},
 
5485
  {40,0x10db},
 
5486
  {30,0x10da},
 
5487
  {20,0x10d9},
 
5488
  {10,0x10d8},
 
5489
  {9,0x10d7},
 
5490
  {8,0x10F1},
 
5491
  {7,0x10d6},
 
5492
  {6,0x10d5},
 
5493
  {5,0x10d4},
 
5494
  {4,0x10d3},
 
5495
  {3,0x10d2},
 
5496
  {2,0x10d1},
 
5497
  {1,0x10D0},
 
5498
  {0,0xFFDF}
 
5499
};
 
5500
 
 
5501
struct vcpair PhoenicianData[]={
 
5502
  {999,0xFFDF},
 
5503
  {100,0x10919},
 
5504
  {20,0x10918},
 
5505
  {10,0x10917},
 
5506
  {1,0x10916},
 
5507
  {0,0xFFDF}
 
5508
};
 
5509
 
 
5510
struct vcpair OldItalicData[]={
 
5511
  {999,0xFFDF},
 
5512
  {50,0x10323},
 
5513
  {10,0x10322},
 
5514
  {5,0x10321},
 
5515
  {1,0x10320},
 
5516
  {0,0xFFDF}
 
5517
};
 
5518
 
 
5519
struct vcpair OldPersianData[]={
 
5520
  {999,0xFFDF},
 
5521
  {100,0x103D5},
 
5522
  {20,0x103D4},
 
5523
  {10,0x103D3},
 
5524
  {2,0x103D2},
 
5525
  {1,0x103D1},
 
5526
  {0,0xFFDF}
 
5527
};
 
5528
 
 
5529
struct vcpair SinhalaData[]={
 
5530
  {9999,0xFFDF},
 
5531
  {1000,0x0DFF},
 
5532
  {100,0x0DFE},
 
5533
  {90,0x0DFD},
 
5534
  {80,0x0DFC},
 
5535
  {70,0x0DFB},
 
5536
  {60,0x0DFA},
 
5537
  {50,0x0DF9},
 
5538
  {40,0x0DF8},
 
5539
  {30,0x0DF7},
 
5540
  {20,0x0DF6},
 
5541
  {10,0x0DF5},
 
5542
  {9,0x0DEF},
 
5543
  {8,0x0DEE},
 
5544
  {7,0x0DED},
 
5545
  {6,0x0DEC},
 
5546
  {5,0x0DEB},
 
5547
  {4,0x0DEA},
 
5548
  {3,0x0DE9},
 
5549
  {2,0x0DE8},
 
5550
  {1,0x0DE7},
 
5551
  {0,0xFFDF}
 
5552
};
 
5553
 
 
5554
struct vcpair XucuriLowerData[]={
 
5555
  {10000,0xFFDF},
 
5556
  {10000,0x2D25},
 
5557
  {9000,0x2D20},
 
5558
  {8000,0x2D1F},
 
5559
  {7000,0x2D24},
 
5560
  {6000,0x2D1E},
 
5561
  {5000,0x2D1D},
 
5562
  {4000,0x2D1C},
 
5563
  {3000,0x2D1B},
 
5564
  {2000,0x2D1A},
 
5565
  {1000,0x2D19},
 
5566
  {900,0x2D18},
 
5567
  {800,0x2D17},
 
5568
  {700,0x2D16},
 
5569
  {600,0x2D15},
 
5570
  {500,0x2D14},
 
5571
  {400,0x2D13},
 
5572
  {300,0x2D12},
 
5573
  {200,0x2D11},
 
5574
  {100,0x2D10},
 
5575
  {90,0x2D0F},
 
5576
  {80,0x2D0E},
 
5577
  {70,0x2D0D},
 
5578
  {60,0x2D22},
 
5579
  {50,0x2D0C},
 
5580
  {40,0x2D0B},
 
5581
  {30,0x2D0A},
 
5582
  {20,0x2D09},
 
5583
  {10,0x2D08},
 
5584
  {9,0x2D07},
 
5585
  {8,0x2D21},
 
5586
  {7,0x2D06},
 
5587
  {6,0x2D05},
 
5588
  {5,0x2D04},
 
5589
  {4,0x2D03},
 
5590
  {3,0x2D02},
 
5591
  {2,0x2D01},
 
5592
  {1,0x2D00},
 
5593
  {0,0xFFDF}
 
5594
};
 
5595
 
 
5596
struct vcpair XucuriUpperData[]={
 
5597
  {10000,0xFFDF},
 
5598
  {10000,0x10C5},
 
5599
  {9000,0x10C0},
 
5600
  {8000,0x10BF},
 
5601
  {7000,0x10C4},
 
5602
  {6000,0x10BE},
 
5603
  {5000,0x10BD},
 
5604
  {4000,0x10BC},
 
5605
  {3000,0x10BB},
 
5606
  {2000,0x10BA},
 
5607
  {1000,0x10B9},
 
5608
  {900,0x10B8},
 
5609
  {800,0x10B7},
 
5610
  {700,0x10B6},
 
5611
  {600,0x10B5},
 
5612
  {500,0x10B4},
 
5613
  {400,0x10B3},
 
5614
  {300,0x10B2},
 
5615
  {200,0x10B1},
 
5616
  {100,0x10B0},
 
5617
  {90,0x10AF},
 
5618
  {80,0x10AE},
 
5619
  {70,0x10AD},
 
5620
  {60,0x10C2},
 
5621
  {50,0x10AC},
 
5622
  {40,0x10AB},
 
5623
  {30,0x10AA},
 
5624
  {20,0x10A9},
 
5625
  {10,0x10A8},
 
5626
  {9,0x10A7},
 
5627
  {8,0x10C1},
 
5628
  {7,0x10A6},
 
5629
  {6,0x10A5},
 
5630
  {5,0x10A4},
 
5631
  {4,0x10A3},
 
5632
  {3,0x10A2},
 
5633
  {2,0x10A1},
 
5634
  {1,0x10A0},
 
5635
  {0,0xFFDF}
 
5636
};
 
5637
 
 
5638
/*
 
5639
 * This is based on the maximum for Egyptian. If
 
5640
 * other systems are added, it may need to be
 
5641
 * increased.
 
5642
 */
 
5643
#define ADDITIVE_CHARS_NEEDED 54
 
5644
static UTF32 *
 
5645
AdditiveIntToString(mpz_t k, struct vcpair *data) {
 
5646
  int Digits;
 
5647
  int i;
 
5648
  int iRepeat;
 
5649
  unsigned long j;
 
5650
  int oi = 0;
 
5651
  UTF32 tmp [ADDITIVE_CHARS_NEEDED+1];
 
5652
  UTF32 *new;
 
5653
  struct vcpair *p;
 
5654
 
 
5655
  mpz_t Repeat;
 
5656
  mpz_t Residue;
 
5657
 
 
5658
  p = data;
 
5659
  j = mpz_get_ui(k);
 
5660
  if (j > p->v) {
 
5661
    uninum_err = NS_ERROR_RANGE;
 
5662
    return NULL;
 
5663
  }
 
5664
 
 
5665
  if(UEQ(k,0)) {
 
5666
    uninum_err = NS_ERROR_NOZERO;
 
5667
    return NULL;
 
5668
  }
 
5669
 
 
5670
  mpz_init(Repeat);
 
5671
  mpz_init_set(Residue,k);
 
5672
 
 
5673
  p++;                          /* Skip over maximum */
 
5674
  while (p->v) {
 
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);
 
5679
    p++;
 
5680
  }
 
5681
 
 
5682
  mpz_clear(Repeat);
 
5683
  mpz_clear(Residue);
 
5684
 
 
5685
  tmp[oi] = 0x0000;
 
5686
  Digits = ucslen(tmp);
 
5687
  new = malloc((Digits + 1) * sizeof(UTF32));
 
5688
  if (!new) {
 
5689
    uninum_err = NS_ERROR_OUTOFMEMORY;
 
5690
    return NULL;
 
5691
  }
 
5692
  return(ucscpy(new,tmp));
 
5693
}
 
5694
 
 
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
 
5700
 
 
5701
#define CYRILLIC_CHARS_NEEDED 6
 
5702
static UTF32 *
 
5703
CyrillicAlphabeticIntToString(mpz_t n) {
 
5704
  int Digits;
 
5705
  int i;
 
5706
  int oi = 0;
 
5707
  unsigned long k;
 
5708
  unsigned long Residue;
 
5709
  unsigned long Thousands;
 
5710
  int Repeat;
 
5711
  UTF32 tmp [CYRILLIC_CHARS_NEEDED+1];
 
5712
  UTF32 *new;
 
5713
  struct vcpair *p;
 
5714
 
 
5715
/* Given the limited range, we'd might as well use ordinary arithmetic  */
 
5716
  k = mpz_get_ui(n);
 
5717
  p = CyrillicData;
 
5718
 
 
5719
  if (k > p->v) {
 
5720
    uninum_err = NS_ERROR_RANGE;
 
5721
    return NULL;
 
5722
  }
 
5723
 
 
5724
  if(k == 0) {
 
5725
    uninum_err = NS_ERROR_NOZERO;
 
5726
    return NULL;
 
5727
  }
 
5728
 
 
5729
  Residue = k;
 
5730
  p++;                          /* Skip maximum */
 
5731
 
 
5732
  Thousands = k/1000L;
 
5733
  if(Thousands > 0) {
 
5734
    tmp[oi++] = CYRILLIC_THOUSANDS_SIGN;
 
5735
    tmp[oi++] = (CyrillicData + 27 - Thousands)->c;
 
5736
    Residue -= (Thousands * 1000L);
 
5737
  }
 
5738
 
 
5739
  while (p->v) {
 
5740
    Repeat = Residue/p->v;
 
5741
    for (i=0;i < Repeat;i++) tmp[oi++] = p->c;
 
5742
    Residue -= (Repeat * p->v);
 
5743
    p++;
 
5744
  }
 
5745
  //  tmp[oi++] = CYRILLIC_TITLO;
 
5746
  tmp[oi] = 0x0000;
 
5747
 
 
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))) {
 
5752
    tmp[oi-2] = c2;
 
5753
    tmp[oi-1] = c1;
 
5754
  } 
 
5755
 
 
5756
  Digits = ucslen(tmp);
 
5757
  new = malloc((Digits + 1) * sizeof(UTF32));
 
5758
  if (!new) {
 
5759
    uninum_err = NS_ERROR_OUTOFMEMORY;
 
5760
    return NULL;
 
5761
  }
 
5762
  return(ucscpy(new,tmp));
 
5763
}
 
5764
 
 
5765
#define GREEK_CHARS_NEEDED 5
 
5766
static UTF32 *
 
5767
GreekAlphabeticIntToString(mpz_t k, short LowerCaseP) {
 
5768
  int Digits;
 
5769
  int i;
 
5770
  int Thousands;
 
5771
  int iRepeat;
 
5772
  int oi = 0;
 
5773
  UTF32 tmp [GREEK_CHARS_NEEDED+1];
 
5774
  UTF32 *new;
 
5775
  struct vcpair *p;
 
5776
 
 
5777
  mpz_t Repeat;
 
5778
  mpz_t Residue;
 
5779
 
 
5780
  if(UEQ(k,0)) {
 
5781
    uninum_err = NS_ERROR_NOZERO;
 
5782
    return NULL;
 
5783
  }
 
5784
 
 
5785
  if(LowerCaseP) p = GreekLowerData;
 
5786
  else p = GreekUpperData;
 
5787
 
 
5788
  if(UGT(k,p->v)) {
 
5789
    uninum_err = NS_ERROR_RANGE;
 
5790
    return NULL;
 
5791
  }
 
5792
 
 
5793
  p++;                          /* Skip maximum */
 
5794
 
 
5795
  mpz_init(Repeat);
 
5796
  mpz_init_set(Residue,k);
 
5797
  mpz_tdiv_q_ui(Repeat,k,1000);
 
5798
  Thousands = mpz_get_ui(Repeat);
 
5799
  if(Thousands) {
 
5800
    tmp[oi++] = GREEK_ALPHABETIC_LEFT_KERAIA;
 
5801
    tmp[oi++] = (p + (sizeof(GreekUpperData)/sizeof(struct vcpair)) - Thousands -2)->c;
 
5802
  }
 
5803
  mpz_submul_ui(Residue,Repeat,1000);
 
5804
 
 
5805
  while (p->v) {
 
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);
 
5810
    p++;
 
5811
  }
 
5812
 
 
5813
  mpz_clear(Repeat); mpz_clear(Residue);
 
5814
 
 
5815
  tmp[oi] = 0x0000;
 
5816
  Digits = ucslen(tmp);
 
5817
  new = malloc((Digits + 1) * sizeof(UTF32));
 
5818
  if (!new) {
 
5819
    uninum_err = NS_ERROR_OUTOFMEMORY;
 
5820
    return NULL;
 
5821
  }
 
5822
  return(ucscpy(new,tmp));
 
5823
}
 
5824
 
 
5825
static UTF32 RomanDigitsUpper[]={
 
5826
  L'I',
 
5827
  L'V',
 
5828
  L'X',
 
5829
  L'L',
 
5830
  L'C',
 
5831
  L'D',
 
5832
  L'M'
 
5833
};
 
5834
 
 
5835
static UTF32 RomanDigitsLower[]={
 
5836
  L'i',
 
5837
  L'v',
 
5838
  L'x',
 
5839
  L'l',
 
5840
  L'c',
 
5841
  L'd',
 
5842
  L'm'
 
5843
};
 
5844
 
 
5845
#define R_1  0
 
5846
#define R_5  1
 
5847
#define R_10 2
 
5848
#define R_50 3
 
5849
#define R_100 4
 
5850
#define R_500 5
 
5851
#define R_1000 6
 
5852
 
 
5853
/* Longest number within range = MMMMMMMMM DCCC LXXX VIII */
 
5854
#define ROMAN_CHARS_NEEDED 21
 
5855
 
 
5856
static UTF32 *
 
5857
RomanToStringAux(unsigned int k, short UpperP) {
 
5858
  int Digits;                   /* Number of digits in string */
 
5859
  int oi = 0;                   /* Index into output array */
 
5860
  int i;
 
5861
  unsigned int Thousands;
 
5862
  unsigned int Hundreds;
 
5863
  unsigned int Tens;
 
5864
  unsigned int Residue;
 
5865
  UTF32 optr[ROMAN_CHARS_NEEDED+1];
 
5866
  UTF32 *new;
 
5867
  UTF32 *RomanDigits;
 
5868
 
 
5869
  if(UpperP) RomanDigits = RomanDigitsUpper;
 
5870
  else  RomanDigits = RomanDigitsLower;
 
5871
 
 
5872
  Residue = k;
 
5873
  Thousands = Residue/1000;
 
5874
  for (i=0;i < Thousands;i++) optr[oi++] = RomanDigits[R_1000];
 
5875
  Residue -= (Thousands * 1000);
 
5876
 
 
5877
  if (Residue >= 500) {
 
5878
    if (Residue >= 900) {
 
5879
      optr[oi++] = RomanDigits[R_100];
 
5880
      optr[oi++] =  RomanDigits[R_1000];
 
5881
      Residue-= 900;
 
5882
    }
 
5883
    else {
 
5884
      optr[oi++] = RomanDigits[R_500];
 
5885
      Residue -= 500;
 
5886
    }
 
5887
  }
 
5888
 
 
5889
  if (Residue >= 400) {
 
5890
    optr[oi++] = RomanDigits[R_100];
 
5891
    optr[oi++] = RomanDigits[R_500];
 
5892
    Residue -= 400;
 
5893
  }
 
5894
  else {
 
5895
    Hundreds = Residue/100;
 
5896
    for (i=0;i < Hundreds;i++) optr[oi++] = RomanDigits[R_100];
 
5897
    Residue -= (Hundreds * 100);
 
5898
  }
 
5899
 
 
5900
  if (Residue >= 50) {
 
5901
    if (Residue >= 90) {
 
5902
      optr[oi++] = RomanDigits[R_10];
 
5903
      optr[oi++] = RomanDigits[R_100];
 
5904
      Residue-= 90;
 
5905
    }
 
5906
    else {
 
5907
      optr[oi++] = RomanDigits[R_50];
 
5908
      Residue -= 50;
 
5909
    }
 
5910
  }
 
5911
 
 
5912
  if (Residue >= 40) {
 
5913
    optr[oi++] = RomanDigits[R_10];
 
5914
    optr[oi++] = RomanDigits[R_50];
 
5915
    Residue -= 40;
 
5916
  }
 
5917
  else {
 
5918
    Tens = Residue/10;
 
5919
    for (i=0;i < Tens;i++) optr[oi++] = RomanDigits[R_10];
 
5920
    Residue -= (Tens * 10);
 
5921
  }
 
5922
 
 
5923
  if (Residue >= 5) {
 
5924
    if (Residue == 9) {
 
5925
      optr[oi++] = RomanDigits[R_1];
 
5926
      optr[oi++] = RomanDigits[R_10];
 
5927
      Residue -= 9;
 
5928
    }
 
5929
    else {
 
5930
      optr[oi++] = RomanDigits[R_5];
 
5931
      Residue -= 5;
 
5932
    }
 
5933
  }
 
5934
  if (Residue == 4) {
 
5935
    optr[oi++] = RomanDigits[R_1];
 
5936
    optr[oi++] = RomanDigits[R_5];
 
5937
    Residue -= 4;
 
5938
  }    
 
5939
 
 
5940
  for (i=0;i < Residue;i++) optr[oi++] =  RomanDigits[R_1];
 
5941
 
 
5942
  optr[oi] = 0x0000;
 
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;
 
5947
  return new;
 
5948
}
 
5949
 
 
5950
static UTF32 *
 
5951
RomanIntToString(mpz_t n, short UpperP) {
 
5952
  unsigned int k;
 
5953
  unsigned int Thousands;
 
5954
  unsigned int Ones;
 
5955
  UTF32 *aptr = NULL;
 
5956
  UTF32 *bptr = NULL;
 
5957
  UTF32 *out;
 
5958
  UTF32 *new;
 
5959
  UTF32 *sptr;
 
5960
  UTF32 optr[(3 * ROMAN_CHARS_NEEDED)+1];
 
5961
 
 
5962
  k = (unsigned int) mpz_get_ui(n);
 
5963
  if (k > ROMAN_LIMIT) {
 
5964
    uninum_err = NS_ERROR_RANGE;
 
5965
    return NULL;
 
5966
  }
 
5967
 
 
5968
  if (k == 0) {
 
5969
    uninum_err = NS_ERROR_NOZERO;
 
5970
    return NULL;
 
5971
  }
 
5972
 
 
5973
  if (Uninum_Generate_Roman_With_Bar_P) {
 
5974
    if(k <= 2000) return RomanToStringAux(k,UpperP);
 
5975
    Thousands = k/1000;
 
5976
    Ones = k - (1000 * Thousands);
 
5977
    aptr = RomanToStringAux(Thousands,UpperP);
 
5978
    out = optr;
 
5979
    sptr = aptr;
 
5980
    /* Insert combining macron */
 
5981
    while (*sptr != 0x0000) {
 
5982
      *out++ = *sptr++;
 
5983
      *out++ = 0x0304;
 
5984
    }
 
5985
    free(aptr);
 
5986
    if(Ones) {
 
5987
      bptr = RomanToStringAux(Ones,UpperP);
 
5988
      sptr = bptr;
 
5989
      while (*sptr != 0x0000) *out++ = *sptr++;
 
5990
      free(bptr);
 
5991
    }
 
5992
    *out = 0x0000;
 
5993
    new = (UTF32 *) malloc((ucslen(optr) + 1) * sizeof(UTF32));
 
5994
    if(new) ucscpy(new,optr);
 
5995
    else uninum_err = NS_ERROR_OUTOFMEMORY;
 
5996
    return new;
 
5997
  } 
 
5998
  else return RomanToStringAux(k,UpperP);
 
5999
}
 
6000
 
 
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 */
 
6011
 
 
6012
UTF32 *CommonBrailleDigits[]={
 
6013
  cobd0, cobd1, cobd2, cobd3, cobd4,
 
6014
  cobd5, cobd6, cobd7, cobd8, cobd9
 
6015
};
 
6016
 
 
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 */
 
6027
 
 
6028
UTF32 *FrenchBrailleDigits[]={ /* Also Czech */
 
6029
  frbd0, frbd1, frbd2, frbd3, frbd4,
 
6030
  frbd5, frbd6, frbd7, frbd8, frbd9
 
6031
};
 
6032
 
 
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 */
 
6043
 
 
6044
UTF32 *RussianBrailleDigits[]={
 
6045
  rubd0, rubd1, rubd2, rubd3, rubd4,
 
6046
  rubd5, rubd6, rubd7, rubd8, rubd9
 
6047
};
 
6048
 
 
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};
 
6059
 
 
6060
UTF32 *ChineseRegularSimplifiedDigits[]={
 
6061
  crsd0, crsd1, crsd2, crsd3, crsd4,
 
6062
  crsd5, crsd6, crsd7, crsd8, crsd9
 
6063
};
 
6064
 
 
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};
 
6075
 
 
6076
UTF32 *ChineseRegularTraditionalDigits[]={
 
6077
  crtd0, crtd1, crtd2, crtd3, crtd4,
 
6078
  crtd5, crtd6, crtd7, crtd8, crtd9
 
6079
};
 
6080
 
 
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};
 
6091
 
 
6092
UTF32 *ChineseLegalTraditionalDigits[]={
 
6093
  cltd0, cltd1, cltd2, cltd3, cltd4,
 
6094
  cltd5, cltd6, cltd7, cltd8, cltd9
 
6095
};
 
6096
 
 
6097
 
 
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};
 
6108
 
 
6109
UTF32 *ChineseLegalSimplifiedDigits[]={
 
6110
  clsd0, clsd1, clsd2, clsd3, clsd4,
 
6111
  clsd5, clsd6, clsd7, clsd8, clsd9
 
6112
};
 
6113
 
 
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};
 
6124
 
 
6125
UTF32 *JapaneseLegalTraditionalDigits[]={
 
6126
  jltd0, jltd1, jltd2, jltd3, jltd4,
 
6127
  jltd5, jltd6, jltd7, jltd8, jltd9
 
6128
};
 
6129
 
 
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};
 
6140
 
 
6141
UTF32 *JapaneseLegalSimplifiedDigits[]={
 
6142
  jlsd0, jlsd1, jlsd2, jlsd3, jlsd4,
 
6143
  jlsd5, jlsd6, jlsd7, jlsd8, jlsd9
 
6144
};
 
6145
 
 
6146
 
 
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};
 
6157
 
 
6158
UTF32 *ChineseCountingRodDigits[]={
 
6159
  ccru0, ccru1, ccru2, ccru3, ccru4,
 
6160
  ccru5, ccru6, ccru7, ccru8, ccru9
 
6161
};
 
6162
 
 
6163
 
 
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};
 
6174
 
 
6175
UTF32 *ChineseCountingRodDecades[]={
 
6176
  ccrd0, ccrd1, ccrd2, ccrd3, ccrd4,
 
6177
  ccrd5, ccrd6, ccrd7, ccrd8, ccrd9
 
6178
};
 
6179
 
 
6180
/* Japanese traditional barriers 10^4 = 84C2l, 10^3 = 9621 (financial), 10^2 = 4F70 (financial),
 
6181
10^1 = 62FE */
 
6182
 
 
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 */
 
6199
};
 
6200
 
 
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 */
 
6217
};
 
6218
 
 
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 */
 
6235
};
 
6236
 
 
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 */
 
6253
};
 
6254
 
 
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 */
 
6271
};
 
6272
 
 
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 */
 
6289
};
 
6290
 
 
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 */
 
6307
};
 
6308
 
 
6309
 
 
6310
/* Remove the leading 1 from 10-19 */
 
6311
void
 
6312
FixChineseTeens(UTF32 *s){
 
6313
  int len;
 
6314
 
 
6315
  len = ucslen(s);
 
6316
  if( ((len == 3) || (len == 2)) && (s[0] == 0x4E00) && (s[1] == 0x5341)) {
 
6317
    s[0] = s[1];
 
6318
    s[1] = s[2];
 
6319
    s[2] = 0x0000;
 
6320
  }
 
6321
}
 
6322
 
 
6323
/* 
 
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.
 
6326
 */
 
6327
void FixLiang(UTF32 *s) {
 
6328
  UTF32 *p;
 
6329
 
 
6330
  p = 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 */
 
6335
        p++;
 
6336
        continue;
 
6337
      }
 
6338
      *p = 0x4E24;              /* Replace with liang */
 
6339
    }
 
6340
    p++;
 
6341
  }
 
6342
}
 
6343
 
 
6344
void StripLeadingChineseOne(UTF32 *s) {
 
6345
  UTF32 *p;
 
6346
 
 
6347
  if( (*s == 0x4E00) && (ucslen(s) > 1)) {
 
6348
    p = s;
 
6349
    while (*p != 0x0000) {
 
6350
      *p = *(p+1);
 
6351
      p++;
 
6352
    }
 
6353
  }
 
6354
}
 
6355
 
 
6356
void ReduceChineseZeroSequences(UTF32 *s) {
 
6357
  UTF32 *ip;
 
6358
  UTF32 *op;
 
6359
  UTF32 c;
 
6360
  enum {START,PREVIOUS_ZERO} State = START;
 
6361
 
 
6362
  ip = s; op = s;
 
6363
  while ( (c = *ip) != 0x0000) {
 
6364
    if ( (c == 0x3007) || (c == 0x96F6)) {
 
6365
      if (State == START) {
 
6366
        *op++ = *ip++;
 
6367
        State = PREVIOUS_ZERO;
 
6368
      }
 
6369
      else ip++;
 
6370
    }
 
6371
    else{
 
6372
      State = START;
 
6373
      *op++ = *ip++;
 
6374
    }
 
6375
  }
 
6376
  *op = 0x0000;
 
6377
}
 
6378
 
 
6379
void StripTrailingChineseZero(UTF32 *s) {
 
6380
  int Last_Index;
 
6381
  Last_Index = ucslen(s) -1;
 
6382
  if ( (s[Last_Index] == 0x3007) || (s[Last_Index] == 0x96F6)) s[Last_Index] = 0x0000;
 
6383
}
 
6384
 
 
6385
 
 
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){
 
6389
  int i;
 
6390
  mpz_t q;
 
6391
  mpz_t r;
 
6392
  mpz_t t;
 
6393
  mpz_t val;
 
6394
  UTF32 obuf[CHINESE_CHARS_NEEDED+1];
 
6395
  UTF32 *ptr;
 
6396
  UTF32 *rptr;
 
6397
  int k;
 
6398
  mpz_t MaxChinese;     /* Maximum value convertible to Chinese string */
 
6399
 
 
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;
 
6404
    return NULL;
 
6405
  }
 
6406
  mpz_clear(MaxChinese);
 
6407
  if (ULT(n,10)) {
 
6408
    if (mpz_cmp_ui(n,0) > 0-ZeroP) {
 
6409
      k = mpz_get_ui(n);
 
6410
      return(MakeSingleDigitString(DigitList[k][0]));
 
6411
    }
 
6412
    return(NULL);
 
6413
  }
 
6414
  else {
 
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);
 
6419
      if (UGT(q,0)) {
 
6420
        rptr = ChineseIntToString(q,DigitList,Barriers,ZeroP);
 
6421
        if(rptr) {
 
6422
          ptr=ucpcpy(obuf,rptr);
 
6423
          free(rptr);
 
6424
          *ptr++ = Barriers[i];
 
6425
          *ptr=0x0000;
 
6426
        }
 
6427
        if (ZeroP) {
 
6428
          if(i>0) {
 
6429
            GetChineseBarrierValue(val,i-1);
 
6430
            mpz_tdiv_q(t,r,val);
 
6431
            if(UEQ(t,0)) ucscat(obuf,DigitList[0]);
 
6432
          }
 
6433
        }
 
6434
        rptr = ChineseIntToString(r,DigitList,Barriers,ZeroP);
 
6435
        if(rptr) {
 
6436
          ucscat(obuf,rptr);
 
6437
          free(rptr);
 
6438
        }
 
6439
        break;
 
6440
      } /* end of if q > 0 */
 
6441
      else {
 
6442
        if(ZeroP) ucscat(obuf,DigitList[0]);
 
6443
      }
 
6444
    } /* end of for */
 
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;
 
6449
    return ptr;
 
6450
  }
 
6451
 
6452
 
 
6453
#define CHINESE_WESTERN_CHARS_NEEDED 300
 
6454
static UTF32 *ChineseWesternIntToString(mpz_t n,UTF32 **DigitList, UTF32 *Barriers){
 
6455
  int i;
 
6456
  mpz_t q;
 
6457
  mpz_t r;
 
6458
  mpz_t val;
 
6459
  UTF32 obuf[CHINESE_WESTERN_CHARS_NEEDED+1];
 
6460
  UTF32 *ptr;
 
6461
  UTF32 *rptr;
 
6462
  UTF32 *tmpptr;
 
6463
  int k;
 
6464
  mpz_t MaxChinese;     /* Maximum value convertible to Chinese string */
 
6465
 
 
6466
  mpz_init_set_str(MaxChinese,MAXCHINESEHEX,16);
 
6467
  if(TGT(n,MaxChinese)) {
 
6468
    uninum_err = NS_ERROR_RANGE;
 
6469
    mpz_clear(MaxChinese);
 
6470
    return NULL;
 
6471
  }
 
6472
  mpz_clear(MaxChinese);
 
6473
 
 
6474
  if (ULT(n,10)) {
 
6475
    if (UGT(n,0)) {
 
6476
      k = mpz_get_ui(n);
 
6477
      return(MakeSingleDigitString(DigitList[k][0]));
 
6478
    }
 
6479
    return(NULL);
 
6480
  }
 
6481
  else {
 
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);
 
6486
      if (UGT(q,0L)) {
 
6487
        if(ULT(q,10000)) {
 
6488
          tmpptr = PlaceIntToString(q,WESTERN_ZERO,10);
 
6489
          rptr = wcDelimitNumber(tmpptr,0x002C,0x002E,3,3);
 
6490
          if (tmpptr != rptr) free(tmpptr);
 
6491
        }
 
6492
        else rptr = ChineseWesternIntToString(q,DigitList,Barriers);
 
6493
        if(rptr) {
 
6494
          ptr=ucpcpy(obuf,rptr);
 
6495
          free(rptr);
 
6496
        }
 
6497
        *ptr++= Barriers[i];
 
6498
        *ptr=0x0000;
 
6499
        if(ULT(r,10000)) {
 
6500
          tmpptr = PlaceIntToString(r,WESTERN_ZERO,10);
 
6501
          rptr = wcDelimitNumber(tmpptr,0x002C,0x002E,3,3);
 
6502
          if (tmpptr != rptr) free(tmpptr);
 
6503
        }
 
6504
        else rptr = ChineseWesternIntToString(r,DigitList,Barriers);
 
6505
        if(rptr) {
 
6506
          if( (UGE(r,10000)) || (*rptr != WESTERN_ZERO)) {
 
6507
            ucscat(obuf,rptr);
 
6508
          }
 
6509
          free(rptr);
 
6510
        }
 
6511
        break;
 
6512
      }
 
6513
    }
 
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);
 
6517
    return ptr;
 
6518
  }
 
6519
 
6520
 
 
6521
/* This is a fairly slight adaptation of PlaceNonContiguousIntToString */
 
6522
 
 
6523
static UTF32 *
 
6524
ChineseCountingRodIntToString(mpz_t n, short EarlyP) {
 
6525
  int Digits;
 
6526
  UTF32 *s;
 
6527
  UTF32 *p;
 
6528
  UTF32 *new;
 
6529
  UTF32 *end;
 
6530
  mpz_t d;
 
6531
  mpz_t k;
 
6532
  mpz_t q;
 
6533
  mpz_t r;
 
6534
  unsigned long int temp;
 
6535
  int offset;
 
6536
  UTF32 **EvenDigitList;
 
6537
  UTF32 **OddDigitList;
 
6538
 
 
6539
  mpz_init_set(k,n);
 
6540
  Digits = mpz_sizeinbase(k,10);
 
6541
  new = malloc((Digits + 1) * sizeof(UTF32));
 
6542
  if (!new) {
 
6543
    uninum_err = NS_ERROR_OUTOFMEMORY;
 
6544
    mpz_clear(k);
 
6545
    return NULL;
 
6546
  }
 
6547
 
 
6548
  mpz_init(d); 
 
6549
  mpz_init(q); 
 
6550
  mpz_init(r); 
 
6551
 
 
6552
  if(EarlyP) {
 
6553
    EvenDigitList = ChineseCountingRodDecades;
 
6554
    OddDigitList = ChineseCountingRodDigits;
 
6555
  }
 
6556
  else {
 
6557
    EvenDigitList = ChineseCountingRodDigits;
 
6558
    OddDigitList = ChineseCountingRodDecades;
 
6559
  }
 
6560
 
 
6561
  p = s = new;
 
6562
  end = new + Digits-1;
 
6563
  /* Do conversion */
 
6564
  
 
6565
  do {
 
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];
 
6569
    mpz_set(k,q);
 
6570
  } while (UGT(q,0L));
 
6571
 
 
6572
  *s = 0L;                      /* Null terminate string */
 
6573
  s--;                          /* Point s at last non-null char */
 
6574
 
 
6575
  mpz_clear(d);mpz_clear(k);mpz_clear(q);mpz_clear(r);
 
6576
 
 
6577
  /*
 
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.
 
6580
   */
 
6581
  
 
6582
  while(p <= s){
 
6583
    temp = *p;
 
6584
    *p++ = *s;
 
6585
    *s-- = temp;
 
6586
  }
 
6587
  return new;
 
6588
}
 
6589
 
 
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
 
6595
 
 
6596
 
 
6597
/*
 
6598
 * This is based loosely on Daniel Jacob's function but heavily rewritten.
 
6599
 */
 
6600
 
 
6601
static UTF32 *
 
6602
EthiopicIntToString(mpz_t n) {
 
6603
  char *Number;
 
6604
  UTF32 *Result;
 
6605
  UTF32 *FinalResult;
 
6606
  int MaxTenPower;
 
6607
  int EthiopicCharCnt = 0;
 
6608
  char asciiOne, asciiTen;
 
6609
  UTF32 OnesPlace, TensPlace, HundredSep;
 
6610
  int CurrentPower;
 
6611
  int OddSubgroupP;
 
6612
  char *tmp; 
 
6613
 
 
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);
 
6621
  }
 
6622
  else if ( (MaxTenPower % 2) == 0 ) {
 
6623
    /*
 
6624
     * Precondition the string to always have the leading tens place populated. 
 
6625
     */
 
6626
    tmp = (char *) malloc ((MaxTenPower+2)*sizeof(char) );
 
6627
    sprintf (tmp,"0%s",Number);
 
6628
    free(Number);
 
6629
    Number = tmp;
 
6630
    MaxTenPower++;
 
6631
  }
 
6632
 
 
6633
  Result = (UTF32 *) malloc (((4 * MaxTenPower)+1) * sizeof (UTF32));
 
6634
  if(!Result) {uninum_err = NS_ERROR_OUTOFMEMORY;return(NULL);}
 
6635
 
 
6636
  for (CurrentPower = MaxTenPower; CurrentPower >= 0; CurrentPower-- ) {
 
6637
    OnesPlace   = TensPlace = 0x0;
 
6638
    asciiTen = Number[MaxTenPower-CurrentPower]; 
 
6639
    CurrentPower--;
 
6640
    asciiOne = Number[MaxTenPower-CurrentPower]; 
 
6641
 
 
6642
    if (asciiOne != '0') OnesPlace = asciiOne + (ETH_ONE - '1');
 
6643
    if (asciiTen != '0') TensPlace = asciiTen + (ETH_TEN - '1');
 
6644
 
 
6645
    /* Choose the HundredSeparator for this group */
 
6646
    OddSubgroupP = (CurrentPower % 4) / 2;
 
6647
    if(CurrentPower > 0) {
 
6648
      if(OddSubgroupP) {
 
6649
        if(OnesPlace || TensPlace) HundredSep = ETH_HUNDRED;
 
6650
        else HundredSep = 0;
 
6651
      }
 
6652
      else HundredSep = ETH_TENTHOUSAND;
 
6653
    }
 
6654
    else HundredSep = 0;
 
6655
 
 
6656
    /*
 
6657
     * If we have a one without a leading ten
 
6658
     * or following 100 or in initial position, remove the one.
 
6659
     */
 
6660
    if ( (OnesPlace == ETH_ONE ) && TensPlace == 0) {
 
6661
      if ( (HundredSep == ETH_HUNDRED ) || (CurrentPower+1) == MaxTenPower) OnesPlace = 0;
 
6662
    }
 
6663
    
 
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 */
 
6669
 
 
6670
  Result[EthiopicCharCnt] = (UTF32) 0;
 
6671
  free (Number);
 
6672
  FinalResult = (UTF32 *) malloc ((EthiopicCharCnt+1) * sizeof (UTF32));
 
6673
  if(!FinalResult) {uninum_err = NS_ERROR_OUTOFMEMORY;return(NULL);}
 
6674
  ucscpy(FinalResult,Result);
 
6675
  free (Result);
 
6676
  return (FinalResult);
 
6677
}
 
6678
 
 
6679
#define HEBREW_CHARS_NEEDED 7   /* unit, decade, 100, 2nd 100, 3d 100, geresh, 1000 */
 
6680
#define HEBREW_DATA_ENTRIES 29
 
6681
 
 
6682
/* This is a slight variant on AdditiveIntToString */
 
6683
static UTF32 *
 
6684
HebrewIntToString(mpz_t k, struct vcpair *data, short EarlyP) {
 
6685
  int Digits;
 
6686
  int i;
 
6687
  int iRepeat;
 
6688
  unsigned long j;
 
6689
  int oi = 0;
 
6690
  UTF32 tmp[HEBREW_CHARS_NEEDED+1];
 
6691
  UTF32 *new;
 
6692
  struct vcpair *p;
 
6693
  mpz_t Repeat;
 
6694
  mpz_t Residue;
 
6695
 
 
6696
  j = mpz_get_ui(k);
 
6697
  p = data;
 
6698
  if (j > p->v) {
 
6699
    uninum_err = NS_ERROR_RANGE;
 
6700
    return NULL;
 
6701
  }
 
6702
 
 
6703
  if(UEQ(k,0)) {
 
6704
    uninum_err = NS_ERROR_NOZERO;
 
6705
    return NULL;
 
6706
  }
 
6707
 
 
6708
  mpz_init(Repeat);
 
6709
  mpz_init(Residue);
 
6710
  
 
6711
  if (j > 999L) {
 
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 */
 
6715
  }
 
6716
  else mpz_set(Residue,k);
 
6717
 
 
6718
  if (EarlyP) p = data+6;
 
6719
  else p = data+1;
 
6720
  while (p->v) {
 
6721
    if(UEQ(Residue,15)) {
 
6722
      tmp[oi++] = 0x05D8;
 
6723
      tmp[oi++] = 0x05D5;
 
6724
      mpz_sub_ui(Residue,Residue,15);
 
6725
    }
 
6726
    else if(UEQ(Residue,16)) {
 
6727
      tmp[oi++] = 0x05D8;
 
6728
      tmp[oi++] = 0x05D6;
 
6729
      mpz_sub_ui(Residue,Residue,16);
 
6730
    }
 
6731
    else {
 
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);
 
6736
      p++;
 
6737
    }
 
6738
  }
 
6739
  mpz_clear(Repeat);
 
6740
  mpz_clear(Residue);
 
6741
  tmp[oi++] = 0x0000;
 
6742
 
 
6743
  Digits = ucslen(tmp);
 
6744
  new = malloc((Digits + 1) * sizeof(UTF32));
 
6745
  if (!new) {
 
6746
    uninum_err = NS_ERROR_OUTOFMEMORY;
 
6747
    return NULL;
 
6748
  }
 
6749
  return(ucscpy(new,tmp));
 
6750
}
 
6751
 
 
6752
 
 
6753
struct vcpair KharoshthiData[]={ /* Max is stored in subroutine in this case */
 
6754
  {20,0x10A45},
 
6755
  {10,0x10A44},
 
6756
  {0,0xFFDF}
 
6757
};
 
6758
 
 
6759
/* 
 
6760
 * Computation of max chars needed:
 
6761
 * 77 + (100 * 7) + (1000 * (77 + (100 * 7))) = 777,777 (longer than 999,999)
 
6762
 *  8      1   4        1     8      1   4
 
6763
 */
 
6764
 
 
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 */
 
6769
  int i;
 
6770
  mpz_t Thousands;
 
6771
  mpz_t Hundreds;
 
6772
  mpz_t Residue;
 
6773
  mpz_t Repeat;
 
6774
  unsigned int iRepeat;
 
6775
  unsigned long k;
 
6776
  UTF32 tmp[KHAROSHTHI_CHARS_NEEDED+1];
 
6777
  UTF32 *op;
 
6778
  UTF32 *new;
 
6779
  UTF32 *ptr;
 
6780
  UTF32 tempc;
 
6781
  struct vcpair *p;
 
6782
 
 
6783
  if (UGT(n,999999L)) {
 
6784
    uninum_err = NS_ERROR_RANGE;
 
6785
    return NULL;
 
6786
  }
 
6787
 
 
6788
  if(UEQ(n,0)) {
 
6789
    uninum_err = NS_ERROR_NOZERO;
 
6790
    return NULL;
 
6791
  }
 
6792
 
 
6793
  mpz_init(Thousands);
 
6794
  mpz_init(Hundreds);
 
6795
  mpz_init(Repeat);
 
6796
  mpz_init(Residue);
 
6797
 
 
6798
  op = tmp;
 
6799
  *op=0x0000;
 
6800
  mpz_set(Residue,n);
 
6801
 
 
6802
  /* Thousands */
 
6803
  mpz_tdiv_q_ui(Thousands,Residue,1000L);
 
6804
  if(UGT(Thousands,0)) {
 
6805
    ptr = KharoshthiIntToString(Thousands);
 
6806
    op = ucpcpy(op,ptr);
 
6807
    free(ptr);
 
6808
    *op++ = KHAROSHTHI_THOUSAND;
 
6809
    *op = 0x0000;
 
6810
  }
 
6811
  mpz_submul_ui(Residue,Thousands,1000L);
 
6812
 
 
6813
  /* Hundreds */
 
6814
  mpz_tdiv_q_ui(Hundreds,Residue,100L);
 
6815
  if(UGT(Hundreds,0)) {
 
6816
    ptr = KharoshthiIntToString(Hundreds);
 
6817
    op = ucpcpy(op,ptr);
 
6818
    free(ptr);
 
6819
    *op++ = KHAROSHTHI_HUNDRED;
 
6820
    *op = 0x0000;
 
6821
  }
 
6822
  mpz_submul_ui(Residue,Hundreds,100L);
 
6823
 
 
6824
  /* Decades */
 
6825
  p = KharoshthiData;
 
6826
  while(p->v) {
 
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);
 
6831
    p++;
 
6832
  }
 
6833
 
 
6834
  /* Units */
 
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 */
 
6837
 
 
6838
  k = mpz_get_ui(Residue);
 
6839
  switch(k){
 
6840
  case 1:
 
6841
    *op++ =KHAROSHTHI_ONE;
 
6842
    break;
 
6843
  case 2:
 
6844
    *op++ =KHAROSHTHI_TWO;
 
6845
    break;
 
6846
  case 3:
 
6847
    *op++ =KHAROSHTHI_THREE;
 
6848
    break;
 
6849
  case 4:
 
6850
    *op++ =KHAROSHTHI_FOUR;
 
6851
    break;
 
6852
  case 5:
 
6853
    *op++ =KHAROSHTHI_FOUR;
 
6854
    *op++ =KHAROSHTHI_ONE;
 
6855
    break;
 
6856
  case 6:
 
6857
    *op++ =KHAROSHTHI_FOUR;
 
6858
    *op++ =KHAROSHTHI_ONE;
 
6859
    *op++ =KHAROSHTHI_ONE;
 
6860
    break;
 
6861
  case 7:
 
6862
    *op++ =KHAROSHTHI_FOUR;
 
6863
    *op++ =KHAROSHTHI_ONE;
 
6864
    *op++ =KHAROSHTHI_ONE;
 
6865
    *op++ =KHAROSHTHI_ONE;
 
6866
    break;
 
6867
  case 8:
 
6868
    *op++ =KHAROSHTHI_FOUR;
 
6869
    *op++ =KHAROSHTHI_FOUR;
 
6870
    break;
 
6871
  case 9:
 
6872
    *op++ =KHAROSHTHI_FOUR;
 
6873
    *op++ =KHAROSHTHI_FOUR;
 
6874
    *op++ =KHAROSHTHI_ONE;
 
6875
    break;
 
6876
  case 0:
 
6877
    break;
 
6878
  }
 
6879
 
 
6880
  *op=0x0000;
 
6881
 
 
6882
  mpz_clear(Thousands);
 
6883
  mpz_clear(Hundreds);
 
6884
  mpz_clear(Repeat);
 
6885
  mpz_clear(Residue);
 
6886
 
 
6887
  Digits = ucslen(tmp);
 
6888
  new = malloc((Digits + 1) * sizeof(UTF32));
 
6889
  if (!new) {
 
6890
    uninum_err = NS_ERROR_OUTOFMEMORY;
 
6891
    return NULL;
 
6892
  }
 
6893
 
 
6894
  return(ucscpy(new,tmp));
 
6895
}
 
6896
 
 
6897
 
 
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};
 
6908
 
 
6909
UTF32 *TamilDigits[]={
 
6910
  tamd0, tamd1, tamd2, tamd3, tamd4,
 
6911
  tamd5, tamd6, tamd7, tamd8, tamd9
 
6912
};
 
6913
 
 
6914
 
 
6915
#define TAMIL_CHARS_NEEDED 10
 
6916
static UTF32 *TamilTraditionalIntToString(mpz_t n){
 
6917
  int i;
 
6918
  mpz_t q;
 
6919
  mpz_t r;
 
6920
  mpz_t val;
 
6921
  UTF32 obuf[TAMIL_CHARS_NEEDED+1];
 
6922
  UTF32 *ptr;
 
6923
  UTF32 *rptr;
 
6924
  int k;
 
6925
 
 
6926
  if(UGT(n,999999)) {
 
6927
    uninum_err = NS_ERROR_RANGE;
 
6928
    return NULL;
 
6929
  }
 
6930
 
 
6931
  if (ULT(n,10)) {
 
6932
    k = mpz_get_ui(n);
 
6933
    return(MakeSingleDigitString(TamilDigits[k][0]));
 
6934
  }
 
6935
  else {
 
6936
    mpz_init(q);mpz_init(r);mpz_init(val);
 
6937
    for(i= (sizeof(TamilBarriers)/sizeof(UTF32))-1; i >= 0;i--) {
 
6938
 
 
6939
      mpz_tdiv_qr_ui(q,r,n,TamilBarrierValue[i]);
 
6940
      if (UGT(q,0L)) {
 
6941
        rptr = TamilTraditionalIntToString(q);
 
6942
        ptr=ucpcpy(obuf,rptr);
 
6943
        if (UGT(q, 10L)) free(rptr);
 
6944
        *ptr++= TamilBarriers[i];
 
6945
        *ptr=0x0000;
 
6946
        rptr = TamilTraditionalIntToString(r);
 
6947
        ucscat(obuf,rptr);
 
6948
        if (UGT(r, 10L)) free(rptr);
 
6949
        break;
 
6950
      }
 
6951
    }
 
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);
 
6955
    return ptr;
 
6956
  }
 
6957
 
6958
 
 
6959
 
 
6960
UTF32 UpperAlphaDigits[]={
 
6961
  0x0030,
 
6962
  0x0031,
 
6963
  0x0032,
 
6964
  0x0033,
 
6965
  0x0034,
 
6966
  0x0035,
 
6967
  0x0036,
 
6968
  0x0037,
 
6969
  0x0038,
 
6970
  0x0039,
 
6971
  0x0041,
 
6972
  0x0042,
 
6973
  0x0043,
 
6974
  0x0044,
 
6975
  0x0045,
 
6976
  0x0046,
 
6977
  0x0047,
 
6978
  0x0048,
 
6979
  0x0049,
 
6980
  0x004A,
 
6981
  0x004B,
 
6982
  0x004C,
 
6983
  0x004D,
 
6984
  0x004E,
 
6985
  0x004F,
 
6986
  0x0050,
 
6987
  0x0051,
 
6988
  0x0052,
 
6989
  0x0053,
 
6990
  0x0054,
 
6991
  0x0055,
 
6992
  0x0056,
 
6993
  0x0057,
 
6994
  0x0058,
 
6995
  0x0059,
 
6996
  0x005A
 
6997
};
 
6998
 
 
6999
UTF32 LowerAlphaDigits[]={
 
7000
  0x0030,
 
7001
  0x0031,
 
7002
  0x0032,
 
7003
  0x0033,
 
7004
  0x0034,
 
7005
  0x0035,
 
7006
  0x0036,
 
7007
  0x0037,
 
7008
  0x0038,
 
7009
  0x0039,
 
7010
  0x0061,
 
7011
  0x0062,
 
7012
  0x0063,
 
7013
  0x0064,
 
7014
  0x0065,
 
7015
  0x0066,
 
7016
  0x0067,
 
7017
  0x0068,
 
7018
  0x0069,
 
7019
  0x006A,
 
7020
  0x006B,
 
7021
  0x006C,
 
7022
  0x006D,
 
7023
  0x006E,
 
7024
  0x006F,
 
7025
  0x0070,
 
7026
  0x0071,
 
7027
  0x0072,
 
7028
  0x0073,
 
7029
  0x0074,
 
7030
  0x0075,
 
7031
  0x0076,
 
7032
  0x0077,
 
7033
  0x0078,
 
7034
  0x0079,
 
7035
  0x007A
 
7036
};
 
7037
 
 
7038
static UTF32 *
 
7039
WesternGeneralIntToString(mpz_t n, int Base, short UpperP) {
 
7040
  unsigned long Digits;
 
7041
  UTF32 *s;
 
7042
  UTF32 *p;
 
7043
  UTF32 *new;
 
7044
  UTF32 *ZeroCode;
 
7045
  mpz_t k;
 
7046
  mpz_t q;
 
7047
  mpz_t r;
 
7048
  mpz_t b;
 
7049
  unsigned long int temp;
 
7050
  unsigned long i;
 
7051
 
 
7052
  if ((Base > 36) || (Base < 1)) {
 
7053
    uninum_err = NS_ERROR_BADBASE;
 
7054
    return NULL;
 
7055
  }
 
7056
 
 
7057
  if(Base == 1) {
 
7058
    if(ULE(n,0L)) {
 
7059
      uninum_err = NS_ERROR_NOZERO;
 
7060
      return NULL;
 
7061
    }
 
7062
    if(!mpz_fits_ulong_p(n)) {
 
7063
      uninum_err = NS_ERROR_DOESNOTFIT;
 
7064
      return NULL;
 
7065
    }
 
7066
    Digits = mpz_get_ui(n);
 
7067
  }
 
7068
  else Digits = mpz_sizeinbase(n,Base);
 
7069
  new = malloc((Digits + 1) * sizeof(UTF32));
 
7070
  if (!new) {
 
7071
    uninum_err = NS_ERROR_OUTOFMEMORY;
 
7072
    return NULL;
 
7073
  }
 
7074
 
 
7075
  p = s = new;
 
7076
  if (UpperP) ZeroCode = UpperAlphaDigits;
 
7077
  else ZeroCode = LowerAlphaDigits;
 
7078
 
 
7079
  if (Base == 1) {
 
7080
    for (i = 0; i < Digits; i++) *s++ = 0x0030;
 
7081
    *s = 0x0000;                        /* Null terminate string */
 
7082
  }
 
7083
  else {
 
7084
    mpz_init_set(k,n);
 
7085
    mpz_init(q); 
 
7086
    mpz_init(r); 
 
7087
    mpz_init_set_ui(b,Base); 
 
7088
 
 
7089
    /* Do conversion */
 
7090
    do {
 
7091
      mpz_tdiv_qr(q,r,k,b);
 
7092
      *s++ = *(ZeroCode + mpz_get_ui(r));
 
7093
      mpz_set(k,q);
 
7094
    } while (UGT(q,0L));
 
7095
 
 
7096
    *s = 0x0000;                        /* Null terminate string */
 
7097
    s--;                                /* Point s at last non-null char */
 
7098
 
 
7099
    /*
 
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.
 
7102
     */
 
7103
    
 
7104
    while(p <= s){
 
7105
      temp = *p;
 
7106
      *p++ = *s;
 
7107
      *s-- = temp;
 
7108
    }
 
7109
    mpz_clear(b);mpz_clear(k);mpz_clear(q);mpz_clear(r);
 
7110
  }
 
7111
  return new;
 
7112
}
 
7113
 
 
7114
 
 
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 */
 
7121
  UTF32 c1;
 
7122
  UTF32 c2;
 
7123
 
 
7124
  oi = ucslen(s);
 
7125
  c1 = s[oi-2];
 
7126
  c2 = s[oi-1];
 
7127
  if ( (c1 == GLAGOLITIC_TEN) && ( (c2 >= GLAGOLITIC_ONE) && (c2 <= GLAGOLITIC_NINE))) {
 
7128
    s[oi-2] = c2;
 
7129
    s[oi-1] = c1;
 
7130
  } 
 
7131
 
7132
 
 
7133
UTF32 *SupplyIsolatedChineseZero (short TraditionalP) {
 
7134
  UTF32 *new;
 
7135
  new = malloc(sizeof(UTF32) * 2);
 
7136
  if(!new) {
 
7137
    fprintf(stderr,"Out of memory.\n");
 
7138
    exit(OUTOFMEMORY);
 
7139
  }
 
7140
  if(TraditionalP) new[0] = 0x96F6;
 
7141
  else new[0] = 0x3007;
 
7142
  new[1] = 0x0000;
 
7143
  return(new);
 
7144
}
 
7145
 
 
7146
//  s[0] s[1] s[2] s[3]         len = 3, lim = 2, max(i) = 2
 
7147
//    1    0    3   '\0'
 
7148
//    1    0    3   '\0'        i = 1 
 
7149
//    1    3    3   '\0'        i = 2
 
7150
//    1    3    \0' '\0'
 
7151
 
 
7152
 
 
7153
 
 
7154
/* Delete a zero neither of whose immediate neighbors is a zero or an edge */
 
7155
void MinimizeCountingRodZeroes(UTF32 *s) {
 
7156
  int i;
 
7157
  int len;
 
7158
  UTF32 *tmp;
 
7159
  UTF32 *tp;
 
7160
 
 
7161
  len = ucslen(s);
 
7162
#ifdef ALLOCAOK
 
7163
  tmp = alloca( (len+1) * sizeof(UTF32));
 
7164
#else
 
7165
  tmp = malloc( (len+1) * sizeof(UTF32));
 
7166
#endif
 
7167
 
 
7168
  tp = tmp;
 
7169
  *tp++ = s[0];
 
7170
  for(i=1;i < len; i++){
 
7171
    if((s[i] == 0x3007) && (s[i-1] != 0x3007) && (s[i+1] != 0x3007) && (s[i+1] != 0x0000)) ;
 
7172
    else *tp++ = s[i];
 
7173
  }
 
7174
  *tp = '\0';
 
7175
  ucscpy(s,tmp);
 
7176
 
 
7177
#ifndef ALLOCAOK
 
7178
  free(tmp);
 
7179
#endif
 
7180
}
 
7181
 
 
7182
/* 
 
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
 
7187
 * zero character.
 
7188
 *
 
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
 
7193
 * as necessary.
 
7194
 */
 
7195
 
 
7196
static void FixSuzhou(UTF32 *s){
 
7197
  UTF32 *p;
 
7198
  enum  {START,PREVIOUS_VERTICAL} State = START;
 
7199
 
 
7200
  p=s;
 
7201
  while(*p != 0x0000) {
 
7202
    switch(*p) {
 
7203
    case 0x3020:
 
7204
      *p = 0x3007;
 
7205
      break;
 
7206
    case 0x3021:
 
7207
      if(State == PREVIOUS_VERTICAL) {
 
7208
        *p = 0x4E00;
 
7209
        State = START;
 
7210
      }
 
7211
      else State = PREVIOUS_VERTICAL;
 
7212
      break;
 
7213
    case 0x3022:
 
7214
      if(State == PREVIOUS_VERTICAL) {
 
7215
        *p = 0x4E8C;
 
7216
        State = START;
 
7217
      }
 
7218
      else State = PREVIOUS_VERTICAL;
 
7219
      break;
 
7220
    case 0x3023:
 
7221
      if(State == PREVIOUS_VERTICAL) {
 
7222
        *p = 0x4E09;
 
7223
        State = START;
 
7224
      }
 
7225
      else State = PREVIOUS_VERTICAL;
 
7226
      break;
 
7227
    default:
 
7228
      State = START;
 
7229
    }
 
7230
    p++;
 
7231
  }
 
7232
}
 
7233
 
 
7234
/* This is the main string-generating function */
 
7235
UTF32 *
 
7236
IntToString(union ns_rval *n,int ns, short InputType) {
 
7237
  mpz_t z;
 
7238
  UTF32 *ptr;
 
7239
  UTF32 *tmpptr;
 
7240
 
 
7241
  uninum_err = NS_ERROR_OKAY;
 
7242
  mpz_init(z);
 
7243
 
 
7244
  switch (InputType) 
 
7245
    {
 
7246
    case NS_TYPE_ULONG:
 
7247
      mpz_set_ui(z,n->u);
 
7248
      break;
 
7249
    case NS_TYPE_STRING:
 
7250
      mpz_set_str(z,n->s,10);
 
7251
      break;
 
7252
    case NS_TYPE_MPZT:
 
7253
      mpz_set(z,n->m);
 
7254
      break;
 
7255
    }
 
7256
 
 
7257
  if(ULT(z,0) < 0) {
 
7258
    uninum_err = NS_ERROR_RANGE;
 
7259
    mpz_clear(z);
 
7260
    return NULL;
 
7261
  }
 
7262
 
 
7263
  switch (ns) {
 
7264
  case NS_AEGEAN:
 
7265
    ptr = AdditiveIntToString(z,AegeanData);
 
7266
    break;
 
7267
  case NS_ARABIC_WESTERN:
 
7268
    ptr = PlaceIntToString(z,ARABIC_ZERO,10);
 
7269
    break;
 
7270
  case NS_ARABIC_ALPHABETIC:
 
7271
    ptr = AdditiveIntToString(z,ArabicAlphabeticData);
 
7272
    break;
 
7273
  case NS_PERSO_ARABIC:
 
7274
    ptr = PlaceIntToString(z,PERSO_ARABIC_ZERO,10);
 
7275
    break;
 
7276
  case NS_ARMENIAN_ALPHABETIC:
 
7277
    ptr = AdditiveIntToString(z,ArmenianData);
 
7278
    break;
 
7279
  case NS_BALINESE:
 
7280
    ptr = PlaceIntToString(z,BALINESE_ZERO,10);
 
7281
    break;
 
7282
  case NS_BENGALI:
 
7283
    ptr = PlaceIntToString(z,BENGALI_ZERO,10);
 
7284
    break;
 
7285
  case NS_BURMESE:
 
7286
    ptr = PlaceIntToString(z,BURMESE_ZERO,10);
 
7287
    break;
 
7288
  case NS_CHINESE_COUNTING_ROD_EARLY_WITH_ZERO:
 
7289
    ptr = ChineseCountingRodIntToString(z,1);
 
7290
    break;
 
7291
  case NS_CHINESE_COUNTING_ROD_EARLY_WITHOUT_ZERO:
 
7292
    ptr = ChineseCountingRodIntToString(z,1);
 
7293
    if(ptr) MinimizeCountingRodZeroes(ptr);
 
7294
    break;
 
7295
  case NS_CHINESE_COUNTING_ROD_LATE_WITH_ZERO:
 
7296
    ptr = ChineseCountingRodIntToString(z,0);
 
7297
    break;
 
7298
  case NS_CHINESE_COUNTING_ROD_LATE_WITHOUT_ZERO:
 
7299
    ptr = ChineseCountingRodIntToString(z,0);
 
7300
    if(ptr) MinimizeCountingRodZeroes(ptr);
 
7301
    break;
 
7302
  case NS_CHINESE_LEGAL_SIMPLIFIED:
 
7303
    if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(0);
 
7304
    else ptr = ChineseIntToString(z,ChineseLegalSimplifiedDigits,ChineseLegalSimplifiedBarriers,0);
 
7305
    break;
 
7306
  case NS_CHINESE_LEGAL_TRADITIONAL:
 
7307
    if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(0);
 
7308
    else ptr = ChineseIntToString(z,ChineseLegalTraditionalDigits,ChineseLegalTraditionalBarriers,0);
 
7309
    break;
 
7310
  case NS_CHINESE_REGULAR_SIMPLIFIED:
 
7311
    if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(0);
 
7312
    else {
 
7313
      ptr = ChineseIntToString(z,ChineseRegularSimplifiedDigits,ChineseRegularSimplifiedBarriers,0);
 
7314
      if (ptr) FixChineseTeens(ptr);
 
7315
    }
 
7316
    break;
 
7317
  case NS_CHINESE_REGULAR_TRADITIONAL:
 
7318
    if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(1);
 
7319
    else {
 
7320
      ptr = ChineseIntToString(z,ChineseRegularTraditionalDigits,ChineseRegularTraditionalBarriers,0);
 
7321
      if (ptr) FixChineseTeens(ptr);
 
7322
    }
 
7323
    break;
 
7324
  case NS_CHINESE_MANDARIN_LEGAL_SIMPLIFIED:
 
7325
    if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(0);
 
7326
    else {
 
7327
      ptr = ChineseIntToString(z,ChineseLegalSimplifiedDigits,ChineseLegalSimplifiedBarriers,0);
 
7328
      if (ptr) FixLiang(ptr);
 
7329
    }
 
7330
    break;
 
7331
  case NS_CHINESE_MANDARIN_LEGAL_TRADITIONAL:
 
7332
    if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(1);
 
7333
    else {
 
7334
      ptr = ChineseIntToString(z,ChineseLegalTraditionalDigits,ChineseLegalTraditionalBarriers,0);
 
7335
      if(ptr) FixLiang(ptr);
 
7336
    }
 
7337
    break;
 
7338
  case NS_CHINESE_MANDARIN_REGULAR_SIMPLIFIED:
 
7339
    if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(0);
 
7340
    else {
 
7341
      ptr = ChineseIntToString(z,ChineseRegularSimplifiedDigits,ChineseRegularSimplifiedBarriers,1);
 
7342
      if(ptr) {
 
7343
        ReduceChineseZeroSequences(ptr);
 
7344
        StripTrailingChineseZero(ptr);
 
7345
        FixChineseTeens(ptr);
 
7346
        FixLiang(ptr);
 
7347
      }
 
7348
    }
 
7349
    break;
 
7350
  case NS_CHINESE_MANDARIN_REGULAR_TRADITIONAL:
 
7351
    if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(1);
 
7352
    else {
 
7353
      ptr = ChineseIntToString(z,ChineseRegularTraditionalDigits,ChineseRegularTraditionalBarriers,1);
 
7354
      if(ptr) {
 
7355
        ReduceChineseZeroSequences(ptr);
 
7356
        StripTrailingChineseZero(ptr);
 
7357
        FixChineseTeens(ptr);
 
7358
        FixLiang(ptr);
 
7359
      }
 
7360
    }
 
7361
    break;
 
7362
  case NS_CHINESE_REGULAR_PLACE:
 
7363
    ptr = PlaceNonContiguousIntToString(z,ChineseRegularSimplifiedDigits,10);
 
7364
    break;
 
7365
  case NS_CHINESE_JAPANESE_REGULAR_TRADITIONAL:
 
7366
    if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(1);
 
7367
    else {
 
7368
      ptr = ChineseIntToString(z,ChineseRegularTraditionalDigits,ChineseRegularTraditionalBarriers,0);
 
7369
      if(ptr) StripLeadingChineseOne(ptr);
 
7370
    }
 
7371
    break;
 
7372
  case NS_CHINESE_JAPANESE_REGULAR_SIMPLIFIED:
 
7373
    if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(0);
 
7374
    else {
 
7375
      ptr = ChineseIntToString(z,ChineseRegularSimplifiedDigits,JapaneseRegularSimplifiedBarriers,0);
 
7376
      if(ptr) StripLeadingChineseOne(ptr);
 
7377
    }
 
7378
    break;
 
7379
  case NS_CHINESE_JAPANESE_LEGAL_TRADITIONAL:
 
7380
    if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(1);
 
7381
    else ptr = ChineseIntToString(z,JapaneseLegalTraditionalDigits,JapaneseLegalTraditionalBarriers,0);
 
7382
    break;
 
7383
  case NS_CHINESE_JAPANESE_LEGAL_SIMPLIFIED:
 
7384
    if(UEQ(z,0)) ptr = SupplyIsolatedChineseZero(0);
 
7385
    else ptr = ChineseIntToString(z,JapaneseLegalSimplifiedDigits,JapaneseLegalSimplifiedBarriers,0);
 
7386
    break;
 
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);
 
7391
    break;
 
7392
  case NS_COMMON_BRAILLE:
 
7393
    ptr = PlaceNonContiguousIntToString(z,CommonBrailleDigits,10);
 
7394
    break;
 
7395
  case NS_CYRILLIC_ALPHABETIC:
 
7396
    ptr = CyrillicAlphabeticIntToString(z);
 
7397
    break;
 
7398
  case NS_DEVANAGARI:
 
7399
    ptr = PlaceIntToString(z,DEVANAGARI_ZERO,10);
 
7400
    break;
 
7401
  case NS_EGYPTIAN:
 
7402
    ptr = AdditiveIntToString(z,EgyptianData);
 
7403
    break;
 
7404
  case NS_ETHIOPIC:
 
7405
    ptr = EthiopicIntToString(z);
 
7406
    break;
 
7407
  case NS_EWELLIC_DECIMAL:
 
7408
    ptr = PlaceIntToString(z,EWELLIC_ZERO,10);
 
7409
    break;
 
7410
  case NS_EWELLIC_HEX:
 
7411
    ptr = PlaceIntToString(z,EWELLIC_ZERO,16);
 
7412
    if(ptr) ptr = Prepend(ptr,0x0060);
 
7413
    break;
 
7414
  case NS_FRENCH_BRAILLE:
 
7415
    ptr = PlaceNonContiguousIntToString(z,FrenchBrailleDigits,10);
 
7416
    break;
 
7417
  case NS_GLAGOLITIC_ALPHABETIC:
 
7418
    ptr = AdditiveIntToString(z,GlagoliticData);
 
7419
    if(ptr) FixGlagoliticTeens(ptr);
 
7420
    break;
 
7421
  case NS_GREEK_ALPHABETIC_LOWER:
 
7422
    ptr = GreekAlphabeticIntToString(z,1);
 
7423
    break;
 
7424
  case NS_GREEK_ALPHABETIC_UPPER:
 
7425
    ptr = GreekAlphabeticIntToString(z,0);
 
7426
    break;
 
7427
  case NS_GUJARATI:
 
7428
    ptr = PlaceIntToString(z,GUJARATI_ZERO,10);
 
7429
    break;
 
7430
  case NS_GURMUKHI:
 
7431
    ptr = PlaceIntToString(z,GURMUKHI_ZERO,10);
 
7432
    break;
 
7433
  case NS_HEBREW_EARLY:
 
7434
    ptr = HebrewIntToString(z,HebrewData,1);
 
7435
    break;
 
7436
  case NS_HEBREW_LATE:
 
7437
    ptr = HebrewIntToString(z,HebrewData,0);
 
7438
    break;
 
7439
  case NS_HEX_LOWER:
 
7440
    ptr = WesternGeneralIntToString(z,16,0);
 
7441
    if(ptr) ptr = Prepend(ptr,0x0078);
 
7442
    if(ptr) ptr = Prepend(ptr,0x0030);
 
7443
    break;
 
7444
  case NS_HEX_UPPER:
 
7445
    ptr = WesternGeneralIntToString(z,16,1);
 
7446
    if(ptr) ptr = Prepend(ptr,0x0078);
 
7447
    if(ptr) ptr = Prepend(ptr,0x0030);
 
7448
    break;
 
7449
  case NS_KANNADA:
 
7450
    ptr = PlaceIntToString(z,KANNADA_ZERO,10);
 
7451
    break;
 
7452
  case NS_KHAROSHTHI:
 
7453
    ptr = KharoshthiIntToString(z);
 
7454
    break;
 
7455
  case NS_KHMER:
 
7456
    ptr = PlaceIntToString(z,KHMER_ZERO,10);
 
7457
    break;
 
7458
  case NS_KLINGON:
 
7459
    ptr = PlaceIntToString(z,KLINGON_ZERO,10);
 
7460
    break;
 
7461
  case NS_LAO:
 
7462
    ptr = PlaceIntToString(z,LAO_ZERO,10);
 
7463
    break;
 
7464
  case NS_LIMBU:
 
7465
    ptr = PlaceIntToString(z,LIMBU_ZERO,10);
 
7466
    break;
 
7467
  case NS_MALAYALAM:
 
7468
    ptr = PlaceIntToString(z,MALAYALAM_ZERO,10);
 
7469
    break;
 
7470
  case NS_MONGOLIAN:
 
7471
    ptr = PlaceIntToString(z,MONGOLIAN_ZERO,10);
 
7472
    break;
 
7473
  case NS_MXEDRULI:
 
7474
    ptr = AdditiveIntToString(z,MxedruliData);
 
7475
    break;
 
7476
  case NS_NEW_TAI_LUE:
 
7477
    ptr = PlaceIntToString(z,NEW_TAI_LUE_ZERO,10);
 
7478
    break;
 
7479
  case NS_NKO:
 
7480
    ptr = PlaceIntToString(z,NKO_ZERO,10);
 
7481
    break;
 
7482
  case NS_OLD_ITALIC:
 
7483
    ptr = AdditiveIntToString(z,OldItalicData);
 
7484
    break;
 
7485
  case NS_OLD_PERSIAN:
 
7486
    ptr = AdditiveIntToString(z,OldPersianData);
 
7487
    break;
 
7488
  case NS_ORIYA:
 
7489
    ptr = PlaceIntToString(z,ORIYA_ZERO,10);
 
7490
    break;
 
7491
  case NS_OSMANYA:
 
7492
    ptr = PlaceIntToString(z,OSMANYA_ZERO,10);
 
7493
    break;
 
7494
  case NS_PHOENICIAN:
 
7495
    ptr = AdditiveIntToString(z,PhoenicianData);
 
7496
    break;
 
7497
  case NS_ROMAN_UPPER:
 
7498
    ptr = RomanIntToString(z,1);
 
7499
    break;
 
7500
  case NS_ROMAN_LOWER:
 
7501
    ptr = RomanIntToString(z,0);
 
7502
    break;
 
7503
  case NS_RUSSIAN_BRAILLE:
 
7504
    ptr = PlaceNonContiguousIntToString(z,RussianBrailleDigits,10);
 
7505
    break;
 
7506
  case NS_SINHALA:
 
7507
    ptr = AdditiveIntToString(z,SinhalaData);
 
7508
    break;
 
7509
  case NS_CHINESE_SUZHOU:
 
7510
    ptr = PlaceIntToString(z,SUZHOU_ZERO,10);
 
7511
    if(ptr) FixSuzhou(ptr);
 
7512
    break;
 
7513
  case NS_TAMIL_PLACE:
 
7514
    ptr = PlaceIntToString(z,TAMIL_ZERO,10);
 
7515
    break;
 
7516
  case NS_TAMIL_TRADITIONAL:
 
7517
    ptr = TamilTraditionalIntToString(z);
 
7518
    break;
 
7519
  case NS_TELUGU:
 
7520
    ptr = PlaceIntToString(z,TELUGU_ZERO,10);
 
7521
    break;
 
7522
  case NS_TENGWAR_DECIMAL:
 
7523
    ptr = TengwarToString(z,10);
 
7524
    break;
 
7525
  case NS_TENGWAR_DUODECIMAL:
 
7526
    ptr = TengwarToString(z,12);
 
7527
    break;
 
7528
  case NS_THAI:
 
7529
    ptr = PlaceIntToString(z,THAI_ZERO,10);
 
7530
    break;
 
7531
  case NS_TIBETAN:
 
7532
    ptr = PlaceIntToString(z,TIBETAN_ZERO,10);
 
7533
    break;
 
7534
  case NS_VERDURIAN:
 
7535
    ptr = PlaceIntToString(z,VERDURIAN_ZERO,10);
 
7536
    break;
 
7537
  case NS_WESTERN_LOWER:
 
7538
    ptr = WesternGeneralIntToString(z,Uninum_Output_Base,0);
 
7539
    break;
 
7540
  case NS_WESTERN_UPPER:
 
7541
    ptr = WesternGeneralIntToString(z,Uninum_Output_Base,1);
 
7542
    break;
 
7543
  case NS_XUCURI_LOWER:
 
7544
    ptr = AdditiveIntToString(z,XucuriLowerData);
 
7545
    break;
 
7546
  case NS_XUCURI_UPPER:
 
7547
    ptr = AdditiveIntToString(z,XucuriUpperData);
 
7548
    break;
 
7549
  default:
 
7550
    uninum_err = NS_ERROR_NUMBER_SYSTEM_UNKNOWN;
 
7551
    ptr = NULL;
 
7552
  }
 
7553
  mpz_clear(z);
 
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);
 
7560
    free(ptr);
 
7561
    ptr = tmpptr;
 
7562
  }
 
7563
  return ptr;
 
7564
}
 
7565
 
 
7566
 
 
7567
/* Tcl API */
 
7568
 
 
7569
/* 
 
7570
 * Generate the list of available writing systems,
 
7571
 *
 
7572
 * which = 0 -> list specific names usable in both directions
 
7573
 * which = 1 -> list cover terms suitable only for conversion of string to int
 
7574
 */
 
7575
char *Tcl_ListNumberSystems (int which) {
 
7576
  int Entries;
 
7577
  int i;
 
7578
  int CharsNeeded = 0;
 
7579
  char *new;
 
7580
  char *p;
 
7581
 
 
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 */
 
7587
  }
 
7588
  new = malloc(sizeof(char) * CharsNeeded);
 
7589
  if(!new) {
 
7590
    uninum_err = NS_ERROR_OUTOFMEMORY;
 
7591
    return NULL;
 
7592
  }
 
7593
  p = new;
 
7594
  for (i=0; i<Entries; i++) {
 
7595
    if (NumberSystemList[i].type == (which? 2:1)) {
 
7596
      p = strpcpy(p,NumberSystemList[i].s);
 
7597
      p = strpcpy(p," ");
 
7598
    }
 
7599
  }
 
7600
  return(new);
 
7601
}
 
7602
 
 
7603
int uninum_utf16len(UTF16 *s) {
 
7604
  int len = 0;
 
7605
  while(*s++ != 0) len++;
 
7606
  return len;
 
7607
}
 
7608
 
 
7609
char *UNStrToWNStr(UTF16 *s,char *sns){
 
7610
  union ns_rval val;
 
7611
  UTF32 *tt;
 
7612
  UTF32 *tptr;
 
7613
  int len;
 
7614
  int i;
 
7615
  int ns;
 
7616
  char *es;
 
7617
 
 
7618
  len = uninum_utf16len(s);
 
7619
#ifdef ALLOCAOK
 
7620
  tt =  alloca((len+1) * sizeof(UTF32));
 
7621
#else
 
7622
  tt =  malloc((len+1) * sizeof(UTF32));
 
7623
#endif
 
7624
  tptr = tt;
 
7625
  for (i = 0; i < len; i++)  *tptr++ = *s++;
 
7626
  *tptr = 0x0000;
 
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);
 
7632
    es[0] = '?';
 
7633
    es[1] = '\0';
 
7634
    return es;
 
7635
  }
 
7636
  StringToInt(&val,tt,NS_TYPE_STRING,ns);
 
7637
  tcl_uninum_badchar = (UTF16) uninum_badchar;
 
7638
#ifndef ALLOCAOK
 
7639
  free((void *) tt);
 
7640
#endif
 
7641
  return val.s;
 
7642
}
 
7643
 
 
7644
UCS2 *WNStrToUNStr(char *sns, char *NumberSystem){
 
7645
  union ns_rval val;
 
7646
  UTF32 *optr;
 
7647
  int ns;
 
7648
  int len;
 
7649
  UCS2 *tclptr;
 
7650
  UCS2 *t;
 
7651
  UTF32 *s;
 
7652
  UTF32 c;
 
7653
 
 
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;
 
7660
    optr[1] = 0x0000;
 
7661
  }
 
7662
  else {
 
7663
    val.s = sns;
 
7664
    optr = IntToString(&val,ns,NS_TYPE_STRING);
 
7665
    if(uninum_err) {
 
7666
      optr = malloc(2 * sizeof(UTF32));
 
7667
      if(!optr) exit(OUTOFMEMORY);
 
7668
      optr[0] = UNI_REPLACEMENT_CHAR;
 
7669
      optr[1] = 0x0000;
 
7670
    }
 
7671
    else {
 
7672
      /* Check whether there are characters outside the BMP */
 
7673
      s = optr;
 
7674
      while((c = *s++) != 0x0000){
 
7675
        if(c > 0xFFFF) {
 
7676
          uninum_err = NS_ERROR_OUTSIDE_BMP;
 
7677
          optr[0] = UNI_REPLACEMENT_CHAR;
 
7678
          optr[1] = 0x0000;
 
7679
        }
 
7680
      } 
 
7681
    }
 
7682
  }
 
7683
  /* The C API generates UTF32. Convert this to UCS-2 (UTF-16 without surrogates)  for Tcl */
 
7684
  len = ucslen(optr);
 
7685
  tclptr = malloc((len+1) * sizeof(UCS2));
 
7686
  if(!tclptr) {
 
7687
    uninum_err = NS_ERROR_OUTOFMEMORY;
 
7688
    free(optr);
 
7689
    return NULL;
 
7690
  }
 
7691
  s = optr;
 
7692
  t = tclptr;
 
7693
  while(*s != 0x0000) *t++ = (UTF16) (0x0000FFFF & *s++);
 
7694
  *t = 0x0000;
 
7695
  free(optr);
 
7696
  return(tclptr);
 
7697
}
 
7698
 
 
7699
char *StrGuessNumberSystem(UTF16 *s){
 
7700
  UTF32 *t;
 
7701
  UTF32 *tptr;
 
7702
  int len;
 
7703
  int i;
 
7704
  int ns;
 
7705
 
 
7706
  len = uninum_utf16len(s);
 
7707
#ifdef ALLOCAOK
 
7708
  t =  alloca((len+1) * sizeof(UTF32));
 
7709
#else
 
7710
  t =  malloc((len+1) * sizeof(UTF32));
 
7711
#endif
 
7712
  tptr = t;
 
7713
  for (i = 0; i < len; i++)  *tptr++ = *s++;
 
7714
  *tptr = 0x0000;
 
7715
  ns = GuessNumberSystem(t);
 
7716
#ifndef ALLOCAOK
 
7717
  free((void *) t);
 
7718
#endif
 
7719
  return(NumberSystemToString(ns));
 
7720
}
 
7721
 
 
7722
char *UninumNumberSystemMaximumValue (char *nsn){
 
7723
  int ns;
 
7724
  char *rval;
 
7725
 
 
7726
  uninum_err = NS_ERROR_OKAY;
 
7727
  ns = StringToNumberSystem(nsn);
 
7728
  if(ns == NS_UNKNOWN) {
 
7729
    uninum_err = NS_ERROR_NUMBER_SYSTEM_UNKNOWN;
 
7730
    return NULL;
 
7731
  }
 
7732
  rval = UninumStringMaximumValue(ns);
 
7733
  return(rval);
 
7734
}