Code

r11451@tres: ted | 2006-04-17 22:21:33 -0700
[inkscape.git] / src / dom / js / jsstr.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  *
3  * ***** BEGIN LICENSE BLOCK *****
4  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5  *
6  * The contents of this file are subject to the Mozilla Public License Version
7  * 1.1 (the "License"); you may not use this file except in compliance with
8  * the License. You may obtain a copy of the License at
9  * http://www.mozilla.org/MPL/
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  *
16  * The Original Code is Mozilla Communicator client code, released
17  * March 31, 1998.
18  *
19  * The Initial Developer of the Original Code is
20  * Netscape Communications Corporation.
21  * Portions created by the Initial Developer are Copyright (C) 1998
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Alternatively, the contents of this file may be used under the terms of
27  * either of the GNU General Public License Version 2 or later (the "GPL"),
28  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29  * in which case the provisions of the GPL or the LGPL are applicable instead
30  * of those above. If you wish to allow use of your version of this file only
31  * under the terms of either the GPL or the LGPL, and not to allow others to
32  * use your version of this file under the terms of the MPL, indicate your
33  * decision by deleting the provisions above and replace them with the notice
34  * and other provisions required by the GPL or the LGPL. If you do not delete
35  * the provisions above, a recipient may use your version of this file under
36  * the terms of any one of the MPL, the GPL or the LGPL.
37  *
38  * ***** END LICENSE BLOCK ***** */
40 /*
41  * JS string type implementation.
42  *
43  * In order to avoid unnecessary js_LockGCThing/js_UnlockGCThing calls, these
44  * native methods store strings (possibly newborn) converted from their 'this'
45  * parameter and arguments on the stack: 'this' conversions at argv[-1], arg
46  * conversions at their index (argv[0], argv[1]).  This is a legitimate method
47  * of rooting things that might lose their newborn root due to subsequent GC
48  * allocations in the same native method.
49  */
50 #include "jsstddef.h"
51 #include <stdlib.h>
52 #include <string.h>
53 #include "jstypes.h"
54 #include "jsutil.h" /* Added by JSIFY */
55 #include "jshash.h" /* Added by JSIFY */
56 #include "jsprf.h"
57 #include "jsapi.h"
58 #include "jsarray.h"
59 #include "jsatom.h"
60 #include "jsbool.h"
61 #include "jscntxt.h"
62 #include "jsconfig.h"
63 #include "jsgc.h"
64 #include "jsinterp.h"
65 #include "jslock.h"
66 #include "jsnum.h"
67 #include "jsobj.h"
68 #include "jsopcode.h"
69 #include "jsregexp.h"
70 #include "jsstr.h"
72 #if JS_HAS_REPLACE_LAMBDA
73 #include "jsinterp.h"
74 #endif
76 #define JSSTRDEP_RECURSION_LIMIT        100
78 size_t
79 js_MinimizeDependentStrings(JSString *str, int level, JSString **basep)
80 {
81     JSString *base;
82     size_t start, length;
84     JS_ASSERT(JSSTRING_IS_DEPENDENT(str));
85     base = JSSTRDEP_BASE(str);
86     start = JSSTRDEP_START(str);
87     if (JSSTRING_IS_DEPENDENT(base)) {
88         if (level < JSSTRDEP_RECURSION_LIMIT) {
89             start += js_MinimizeDependentStrings(base, level + 1, &base);
90         } else {
91             do {
92                 start += JSSTRDEP_START(base);
93                 base = JSSTRDEP_BASE(base);
94             } while (JSSTRING_IS_DEPENDENT(base));
95         }
96         if (start == 0) {
97             JS_ASSERT(JSSTRING_IS_PREFIX(str));
98             JSPREFIX_SET_BASE(str, base);
99         } else if (start <= JSSTRDEP_START_MASK) {
100             length = JSSTRDEP_LENGTH(str);
101             JSSTRDEP_SET_START_AND_LENGTH(str, start, length);
102             JSSTRDEP_SET_BASE(str, base);
103         }
104     }
105     *basep = base;
106     return start;
109 jschar *
110 js_GetDependentStringChars(JSString *str)
112     size_t start;
113     JSString *base;
115     start = js_MinimizeDependentStrings(str, 0, &base);
116     JS_ASSERT(!JSSTRING_IS_DEPENDENT(base));
117     JS_ASSERT(start < base->length);
118     return base->chars + start;
121 jschar *
122 js_GetStringChars(JSString *str)
124     if (JSSTRING_IS_DEPENDENT(str) && !js_UndependString(NULL, str))
125         return NULL;
127     *js_GetGCThingFlags(str) &= ~GCF_MUTABLE;
128     return str->chars;
131 JSString *
132 js_ConcatStrings(JSContext *cx, JSString *left, JSString *right)
134     size_t rn, ln, lrdist, n;
135     jschar *rs, *ls, *s;
136     JSDependentString *ldep;    /* non-null if left should become dependent */
137     JSString *str;
139     if (JSSTRING_IS_DEPENDENT(right)) {
140         rn = JSSTRDEP_LENGTH(right);
141         rs = JSSTRDEP_CHARS(right);
142     } else {
143         rn = right->length;
144         rs = right->chars;
145     }
146     if (rn == 0)
147         return left;
149     if (JSSTRING_IS_DEPENDENT(left) ||
150         !(*js_GetGCThingFlags(left) & GCF_MUTABLE)) {
151         /* We must copy if left does not own a buffer to realloc. */
152         ln = JSSTRING_LENGTH(left);
153         if (ln == 0)
154             return right;
155         ls = JSSTRING_CHARS(left);
156         s = (jschar *) JS_malloc(cx, (ln + rn + 1) * sizeof(jschar));
157         if (!s)
158             return NULL;
159         js_strncpy(s, ls, ln);
160         ldep = NULL;
161     } else {
162         /* We can realloc left's space and make it depend on our result. */
163         ln = left->length;
164         if (ln == 0)
165             return right;
166         ls = left->chars;
167         s = (jschar *) JS_realloc(cx, ls, (ln + rn + 1) * sizeof(jschar));
168         if (!s)
169             return NULL;
170  
171         /* Take care: right could depend on left! */
172         lrdist = (size_t)(rs - ls);
173         if (lrdist < ln)
174             rs = s + lrdist;
175         left->chars = ls = s;
176         ldep = JSSTRDEP(left);
177     }
179     js_strncpy(s + ln, rs, rn);
180     n = ln + rn;
181     s[n] = 0;
182     str = js_NewString(cx, s, n, GCF_MUTABLE);
183     if (!str) {
184         /* Out of memory: clean up any space we (re-)allocated. */
185         if (!ldep) {
186             JS_free(cx, s);
187         } else {
188             s = JS_realloc(cx, ls, (ln + 1) * sizeof(jschar));
189             if (s)
190                 left->chars = s;
191         }
192     } else {
193         /* Morph left into a dependent prefix if we realloc'd its buffer. */
194         if (ldep) {
195             JSPREFIX_SET_LENGTH(ldep, ln);
196             JSPREFIX_SET_BASE(ldep, str);
197 #ifdef DEBUG
198           {
199             JSRuntime *rt = cx->runtime;
200             JS_RUNTIME_METER(rt, liveDependentStrings);
201             JS_RUNTIME_METER(rt, totalDependentStrings);
202             JS_LOCK_RUNTIME_VOID(rt,
203                 (rt->strdepLengthSum += (double)ln,
204                  rt->strdepLengthSquaredSum += (double)ln * (double)ln));
205           }
206 #endif
207         }
208     }
210     return str;
213 /*
214  * May be called with null cx by js_GetStringChars, above; and by the jslock.c
215  * MAKE_STRING_IMMUTABLE file-local macro.
216  */
217 const jschar *
218 js_UndependString(JSContext *cx, JSString *str)
220     size_t n, size;
221     jschar *s;
223     if (JSSTRING_IS_DEPENDENT(str)) {
224         n = JSSTRDEP_LENGTH(str);
225         size = (n + 1) * sizeof(jschar);
226         s = (jschar *) (cx ? JS_malloc(cx, size) : malloc(size));
227         if (!s)
228             return NULL;
230         js_strncpy(s, JSSTRDEP_CHARS(str), n);
231         s[n] = 0;
232         str->length = n;
233         str->chars = s;
235 #ifdef DEBUG
236         if (cx) {
237             JSRuntime *rt = cx->runtime;
238             JS_RUNTIME_UNMETER(rt, liveDependentStrings);
239             JS_RUNTIME_UNMETER(rt, totalDependentStrings);
240             JS_LOCK_RUNTIME_VOID(rt,
241                 (rt->strdepLengthSum -= (double)n,
242                  rt->strdepLengthSquaredSum -= (double)n * (double)n));
243         }
244 #endif
245     }
247     return str->chars;
250 /*
251  * Forward declarations for URI encode/decode and helper routines
252  */
253 static JSBool
254 str_decodeURI(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
255               jsval *rval);
257 static JSBool
258 str_decodeURI_Component(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
259                         jsval *rval);
261 static JSBool
262 str_encodeURI(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
263               jsval *rval);
265 static JSBool
266 str_encodeURI_Component(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
267                         jsval *rval);
269 static int
270 OneUcs4ToUtf8Char(uint8 *utf8Buffer, uint32 ucs4Char);
272 static uint32
273 Utf8ToOneUcs4Char(const uint8 *utf8Buffer, int utf8Length);
275 /*
276  * Contributions from the String class to the set of methods defined for the
277  * global object.  escape and unescape used to be defined in the Mocha library,
278  * but as ECMA decided to spec them, they've been moved to the core engine
279  * and made ECMA-compliant.  (Incomplete escapes are interpreted as literal
280  * characters by unescape.)
281  */
283 /*
284  * Stuff to emulate the old libmocha escape, which took a second argument
285  * giving the type of escape to perform.  Retained for compatibility, and
286  * copied here to avoid reliance on net.h, mkparse.c/NET_EscapeBytes.
287  */
289 #define URL_XALPHAS     ((uint8) 1)
290 #define URL_XPALPHAS    ((uint8) 2)
291 #define URL_PATH        ((uint8) 4)
293 static const uint8 urlCharType[256] =
294 /*      Bit 0           xalpha          -- the alphas
295  *      Bit 1           xpalpha         -- as xalpha but
296  *                             converts spaces to plus and plus to %20
297  *      Bit 2 ...       path            -- as xalphas but doesn't escape '/'
298  */
299     /*   0 1 2 3 4 5 6 7 8 9 A B C D E F */
300     {    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,       /* 0x */
301          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,       /* 1x */
302          0,0,0,0,0,0,0,0,0,0,7,4,0,7,7,4,       /* 2x   !"#$%&'()*+,-./  */
303          7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0,       /* 3x  0123456789:;<=>?  */
304          7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,       /* 4x  @ABCDEFGHIJKLMNO  */
305          7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,7,       /* 5X  PQRSTUVWXYZ[\]^_  */
306          0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,       /* 6x  `abcdefghijklmno  */
307          7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,       /* 7X  pqrstuvwxyz{\}~  DEL */
308          0, };
310 /* This matches the ECMA escape set when mask is 7 (default.) */
312 #define IS_OK(C, mask) (urlCharType[((uint8) (C))] & (mask))
314 /* See ECMA-262 15.1.2.4. */
315 JSBool
316 js_str_escape(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
318     JSString *str;
319     size_t i, ni, length, newlength;
320     const jschar *chars;
321     jschar *newchars;
322     jschar ch;
323     jsint mask;
324     jsdouble d;
325     const char digits[] = {'0', '1', '2', '3', '4', '5', '6', '7',
326                            '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
328     mask = URL_XALPHAS | URL_XPALPHAS | URL_PATH;
329     if (argc > 1) {
330         if (!js_ValueToNumber(cx, argv[1], &d))
331             return JS_FALSE;
332         if (!JSDOUBLE_IS_FINITE(d) ||
333             (mask = (jsint)d) != d ||
334             mask & ~(URL_XALPHAS | URL_XPALPHAS | URL_PATH))
335         {
336             char numBuf[12];
337             JS_snprintf(numBuf, sizeof numBuf, "%lx", (unsigned long) mask);
338             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
339                                  JSMSG_BAD_STRING_MASK, numBuf);
340             return JS_FALSE;
341         }
342     }
344     str = js_ValueToString(cx, argv[0]);
345     if (!str)
346         return JS_FALSE;
347     argv[0] = STRING_TO_JSVAL(str);
349     chars = JSSTRING_CHARS(str);
350     length = newlength = JSSTRING_LENGTH(str);
352     /* Take a first pass and see how big the result string will need to be. */
353     for (i = 0; i < length; i++) {
354         if ((ch = chars[i]) < 128 && IS_OK(ch, mask))
355             continue;
356         if (ch < 256) {
357             if (mask == URL_XPALPHAS && ch == ' ')
358                 continue;   /* The character will be encoded as '+' */
359             newlength += 2; /* The character will be encoded as %XX */
360         } else {
361             newlength += 5; /* The character will be encoded as %uXXXX */
362         }
363     }
365     newchars = (jschar *) JS_malloc(cx, (newlength + 1) * sizeof(jschar));
366     if (!newchars)
367         return JS_FALSE;
368     for (i = 0, ni = 0; i < length; i++) {
369         if ((ch = chars[i]) < 128 && IS_OK(ch, mask)) {
370             newchars[ni++] = ch;
371         } else if (ch < 256) {
372             if (mask == URL_XPALPHAS && ch == ' ') {
373                 newchars[ni++] = '+'; /* convert spaces to pluses */
374             } else {
375                 newchars[ni++] = '%';
376                 newchars[ni++] = digits[ch >> 4];
377                 newchars[ni++] = digits[ch & 0xF];
378             }
379         } else {
380             newchars[ni++] = '%';
381             newchars[ni++] = 'u';
382             newchars[ni++] = digits[ch >> 12];
383             newchars[ni++] = digits[(ch & 0xF00) >> 8];
384             newchars[ni++] = digits[(ch & 0xF0) >> 4];
385             newchars[ni++] = digits[ch & 0xF];
386         }
387     }
388     JS_ASSERT(ni == newlength);
389     newchars[newlength] = 0;
391     str = js_NewString(cx, newchars, newlength, 0);
392     if (!str) {
393         JS_free(cx, newchars);
394         return JS_FALSE;
395     }
396     *rval = STRING_TO_JSVAL(str);
397     return JS_TRUE;
399 #undef IS_OK
401 /* See ECMA-262 15.1.2.5 */
402 static JSBool
403 str_unescape(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
405     JSString *str;
406     size_t i, ni, length;
407     const jschar *chars;
408     jschar *newchars;
409     jschar ch;
411     str = js_ValueToString(cx, argv[0]);
412     if (!str)
413         return JS_FALSE;
414     argv[0] = STRING_TO_JSVAL(str);
416     chars = JSSTRING_CHARS(str);
417     length = JSSTRING_LENGTH(str);
419     /* Don't bother allocating less space for the new string. */
420     newchars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
421     if (!newchars)
422         return JS_FALSE;
423     ni = i = 0;
424     while (i < length) {
425         ch = chars[i++];
426         if (ch == '%') {
427             if (i + 1 < length &&
428                 JS7_ISHEX(chars[i]) && JS7_ISHEX(chars[i + 1]))
429             {
430                 ch = JS7_UNHEX(chars[i]) * 16 + JS7_UNHEX(chars[i + 1]);
431                 i += 2;
432             } else if (i + 4 < length && chars[i] == 'u' &&
433                        JS7_ISHEX(chars[i + 1]) && JS7_ISHEX(chars[i + 2]) &&
434                        JS7_ISHEX(chars[i + 3]) && JS7_ISHEX(chars[i + 4]))
435             {
436                 ch = (((((JS7_UNHEX(chars[i + 1]) << 4)
437                         + JS7_UNHEX(chars[i + 2])) << 4)
438                       + JS7_UNHEX(chars[i + 3])) << 4)
439                     + JS7_UNHEX(chars[i + 4]);
440                 i += 5;
441             }
442         }
443         newchars[ni++] = ch;
444     }
445     newchars[ni] = 0;
447     str = js_NewString(cx, newchars, ni, 0);
448     if (!str) {
449         JS_free(cx, newchars);
450         return JS_FALSE;
451     }
452     *rval = STRING_TO_JSVAL(str);
453     return JS_TRUE;
456 #if JS_HAS_UNEVAL
457 static JSBool
458 str_uneval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
460     JSString *str;
462     str = js_ValueToSource(cx, argv[0]);
463     if (!str)
464         return JS_FALSE;
465     *rval = STRING_TO_JSVAL(str);
466     return JS_TRUE;
468 #endif
470 const char js_escape_str[] = "escape";
471 const char js_unescape_str[] = "unescape";
472 #if JS_HAS_UNEVAL
473 const char js_uneval_str[] = "uneval";
474 #endif
475 const char js_decodeURI_str[] = "decodeURI";
476 const char js_encodeURI_str[] = "encodeURI";
477 const char js_decodeURIComponent_str[] = "decodeURIComponent";
478 const char js_encodeURIComponent_str[] = "encodeURIComponent";
480 static JSFunctionSpec string_functions[] = {
481     {js_escape_str,             js_str_escape,              1,0,0},
482     {js_unescape_str,           str_unescape,               1,0,0},
483 #if JS_HAS_UNEVAL
484     {js_uneval_str,             str_uneval,                 1,0,0},
485 #endif
486     {js_decodeURI_str,          str_decodeURI,              1,0,0},
487     {js_encodeURI_str,          str_encodeURI,              1,0,0},
488     {js_decodeURIComponent_str, str_decodeURI_Component,    1,0,0},
489     {js_encodeURIComponent_str, str_encodeURI_Component,    1,0,0},
491     {0,0,0,0,0}
492 };
494 jschar      js_empty_ucstr[]  = {0};
495 JSSubString js_EmptySubString = {0, js_empty_ucstr};
497 enum string_tinyid {
498     STRING_LENGTH = -1
499 };
501 static JSPropertySpec string_props[] = {
502     {js_length_str,     STRING_LENGTH,
503                         JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED, 0,0},
504     {0,0,0,0,0}
505 };
507 static JSBool
508 str_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
510     JSString *str;
511     jsint slot;
513     if (!JSVAL_IS_INT(id))
514         return JS_TRUE;
515     str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
516     if (!str)
517         return JS_FALSE;
518     slot = JSVAL_TO_INT(id);
519     if (slot == STRING_LENGTH)
520         *vp = INT_TO_JSVAL((jsint) JSSTRING_LENGTH(str));
521     return JS_TRUE;
524 #define STRING_ELEMENT_ATTRS (JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT)
526 static JSBool
527 str_enumerate(JSContext *cx, JSObject *obj)
529     JSString *str, *str1;
530     size_t i, length;
532     str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
533     if (!str)
534         return JS_FALSE;
535     length = JSSTRING_LENGTH(str);
536     for (i = 0; i < length; i++) {
537         str1 = js_NewDependentString(cx, str, i, 1, 0);
538         if (!str1)
539             return JS_FALSE;
540         if (!OBJ_DEFINE_PROPERTY(cx, obj, INT_TO_JSVAL(i),
541                                  STRING_TO_JSVAL(str1), NULL, NULL,
542                                  STRING_ELEMENT_ATTRS, NULL)) {
543             return JS_FALSE;
544         }
545     }
546     return JS_TRUE;
549 static JSBool
550 str_resolve(JSContext *cx, JSObject *obj, jsval id)
552     JSString *str, *str1;
553     jsint slot;
555     if (!JSVAL_IS_INT(id))
556         return JS_TRUE;
558     str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
559     if (!str)
560         return JS_FALSE;
561     slot = JSVAL_TO_INT(id);
562     if ((size_t)slot < JSSTRING_LENGTH(str)) {
563         str1 = js_NewDependentString(cx, str, (size_t)slot, 1, 0);
564         if (!str1)
565             return JS_FALSE;
566         if (!OBJ_DEFINE_PROPERTY(cx, obj, INT_TO_JSVAL(slot),
567                                  STRING_TO_JSVAL(str1), NULL, NULL,
568                                  STRING_ELEMENT_ATTRS, NULL)) {
569             return JS_FALSE;
570         }
571     }
572     return JS_TRUE;
575 static JSClass string_class = {
576     js_String_str,
577     JSCLASS_HAS_PRIVATE,
578     JS_PropertyStub,  JS_PropertyStub,  str_getProperty,  JS_PropertyStub,
579     str_enumerate,    str_resolve,      JS_ConvertStub,   JS_FinalizeStub,
580     JSCLASS_NO_OPTIONAL_MEMBERS
581 };
583 #if JS_HAS_TOSOURCE
585 /*
586  * String.prototype.quote is generic (as are most string methods), unlike
587  * toSource, toString, and valueOf.
588  */
589 static JSBool
590 str_quote(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
592     JSString *str;
594     str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
595     if (!str)
596         return JS_FALSE;
597     str = js_QuoteString(cx, str, '"');
598     if (!str)
599         return JS_FALSE;
600     *rval = STRING_TO_JSVAL(str);
601     return JS_TRUE;
604 static JSBool
605 str_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
607     jsval v;
608     JSString *str;
609     size_t i, j, k, n;
610     char buf[16];
611     jschar *s, *t;
613     if (!JS_InstanceOf(cx, obj, &string_class, argv))
614         return JS_FALSE;
615     v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
616     if (!JSVAL_IS_STRING(v))
617         return js_obj_toSource(cx, obj, argc, argv, rval);
618     str = js_QuoteString(cx, JSVAL_TO_STRING(v), '"');
619     if (!str)
620         return JS_FALSE;
621     j = JS_snprintf(buf, sizeof buf, "(new %s(", string_class.name);
622     s = JSSTRING_CHARS(str);
623     k = JSSTRING_LENGTH(str);
624     n = j + k + 2;
625     t = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar));
626     if (!t)
627         return JS_FALSE;
628     for (i = 0; i < j; i++)
629         t[i] = buf[i];
630     for (j = 0; j < k; i++, j++)
631         t[i] = s[j];
632     t[i++] = ')';
633     t[i++] = ')';
634     t[i] = 0;
635     str = js_NewString(cx, t, n, 0);
636     if (!str) {
637         JS_free(cx, t);
638         return JS_FALSE;
639     }
640     *rval = STRING_TO_JSVAL(str);
641     return JS_TRUE;
644 #endif /* JS_HAS_TOSOURCE */
646 static JSBool
647 str_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
649     jsval v;
651     if (!JS_InstanceOf(cx, obj, &string_class, argv))
652         return JS_FALSE;
653     v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
654     if (!JSVAL_IS_STRING(v))
655         return js_obj_toString(cx, obj, argc, argv, rval);
656     *rval = v;
657     return JS_TRUE;
660 static JSBool
661 str_valueOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
663     if (!JS_InstanceOf(cx, obj, &string_class, argv))
664         return JS_FALSE;
665     *rval = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
666     return JS_TRUE;
669 /*
670  * Java-like string native methods.
671  */
672 static JSBool
673 str_substring(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
674               jsval *rval)
676     JSString *str;
677     jsdouble d;
678     jsdouble length, begin, end;
680     str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
681     if (!str)
682         return JS_FALSE;
683     argv[-1] = STRING_TO_JSVAL(str);
685     if (argc != 0) {
686         if (!js_ValueToNumber(cx, argv[0], &d))
687             return JS_FALSE;
688         length = JSSTRING_LENGTH(str);
689         begin = js_DoubleToInteger(d);
690         if (begin < 0)
691             begin = 0;
692         else if (begin > length)
693             begin = length;
695         if (argc == 1) {
696             end = length;
697         } else {
698             if (!js_ValueToNumber(cx, argv[1], &d))
699                 return JS_FALSE;
700             end = js_DoubleToInteger(d);
701             if (end < 0)
702                 end = 0;
703             else if (end > length)
704                 end = length;
705             if (end < begin) {
706                 if (cx->version != JSVERSION_1_2) {
707                     /* XXX emulate old JDK1.0 java.lang.String.substring. */
708                     jsdouble tmp = begin;
709                     begin = end;
710                     end = tmp;
711                 } else {
712                     end = begin;
713                 }
714             }
715         }
717         str = js_NewDependentString(cx, str, (size_t)begin,
718                                     (size_t)(end - begin), 0);
719         if (!str)
720             return JS_FALSE;
721     }
722     *rval = STRING_TO_JSVAL(str);
723     return JS_TRUE;
726 static JSBool
727 str_toLowerCase(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
728                 jsval *rval)
730     JSString *str;
731     size_t i, n;
732     jschar *s, *news;
734     str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
735     if (!str)
736         return JS_FALSE;
737     n = JSSTRING_LENGTH(str);
738     news = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar));
739     if (!news)
740         return JS_FALSE;
741     s = JSSTRING_CHARS(str);
742     for (i = 0; i < n; i++)
743         news[i] = JS_TOLOWER(s[i]);
744     news[n] = 0;
745     str = js_NewString(cx, news, n, 0);
746     if (!str) {
747         JS_free(cx, news);
748         return JS_FALSE;
749     }
750     *rval = STRING_TO_JSVAL(str);
751     return JS_TRUE;
754 static JSBool
755 str_toLocaleLowerCase(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
756                 jsval *rval)
758     JSString *str;
760     /*
761      * Forcefully ignore the first (or any) argument and return toLowerCase(),
762      * ECMA has reserved that argument, presumably for defining the locale.
763      */
764     if (cx->localeCallbacks && cx->localeCallbacks->localeToLowerCase) {
765         str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
766         if (!str)
767             return JS_FALSE;
768         return cx->localeCallbacks->localeToLowerCase(cx, str, rval);
769     }
770     return str_toLowerCase(cx, obj, 0, argv, rval);
773 static JSBool
774 str_toUpperCase(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
775                 jsval *rval)
777     JSString *str;
778     size_t i, n;
779     jschar *s, *news;
781     str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
782     if (!str)
783         return JS_FALSE;
784     n = JSSTRING_LENGTH(str);
785     news = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar));
786     if (!news)
787         return JS_FALSE;
788     s = JSSTRING_CHARS(str);
789     for (i = 0; i < n; i++)
790         news[i] = JS_TOUPPER(s[i]);
791     news[n] = 0;
792     str = js_NewString(cx, news, n, 0);
793     if (!str) {
794         JS_free(cx, news);
795         return JS_FALSE;
796     }
797     *rval = STRING_TO_JSVAL(str);
798     return JS_TRUE;
801 static JSBool
802 str_toLocaleUpperCase(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
803                 jsval *rval)
805     JSString *str;
807     /*
808      * Forcefully ignore the first (or any) argument and return toUpperCase(),
809      * ECMA has reserved that argument, presumbaly for defining the locale.
810      */
811     if (cx->localeCallbacks && cx->localeCallbacks->localeToUpperCase) {
812         str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
813         if (!str)
814             return JS_FALSE;
815         return cx->localeCallbacks->localeToUpperCase(cx, str, rval);
816     }
817     return str_toUpperCase(cx, obj, 0, argv, rval);
820 static JSBool
821 str_localeCompare(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
822                   jsval *rval)
824     JSString *str, *thatStr;
826     str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
827     if (!str)
828         return JS_FALSE;
829     argv[-1] = STRING_TO_JSVAL(str);
831     if (argc == 0) {
832         *rval = JSVAL_ZERO;
833     } else {
834         thatStr = js_ValueToString(cx, argv[0]);
835         if (!thatStr)
836             return JS_FALSE;
837         if (cx->localeCallbacks && cx->localeCallbacks->localeCompare)
838             return cx->localeCallbacks->localeCompare(cx, str, thatStr, rval);
839         *rval = INT_TO_JSVAL(js_CompareStrings(str, thatStr));
840     }
841     return JS_TRUE;
844 static JSBool
845 str_charAt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
847     JSString *str;
848     jsdouble d;
849     size_t index;
851     str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
852     if (!str)
853         return JS_FALSE;
854     argv[-1] = STRING_TO_JSVAL(str);
856     if (argc == 0) {
857         d = 0.0;
858     } else {
859         if (!js_ValueToNumber(cx, argv[0], &d))
860             return JS_FALSE;
861         d = js_DoubleToInteger(d);
862     }
864     if (d < 0 || JSSTRING_LENGTH(str) <= d) {
865         *rval = JS_GetEmptyStringValue(cx);
866     } else {
867         index = (size_t)d;
868         str = js_NewDependentString(cx, str, index, 1, 0);
869         if (!str)
870             return JS_FALSE;
871         *rval = STRING_TO_JSVAL(str);
872     }
873     return JS_TRUE;
876 static JSBool
877 str_charCodeAt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
878                jsval *rval)
880     JSString *str;
881     jsdouble d;
882     size_t index;
884     str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
885     if (!str)
886         return JS_FALSE;
887     argv[-1] = STRING_TO_JSVAL(str);
889     if (argc == 0) {
890         d = 0.0;
891     } else {
892         if (!js_ValueToNumber(cx, argv[0], &d))
893             return JS_FALSE;
894         d = js_DoubleToInteger(d);
895     }
897     if (d < 0 || JSSTRING_LENGTH(str) <= d) {
898         *rval = JS_GetNaNValue(cx);
899     } else {
900         index = (size_t)d;
901         *rval = INT_TO_JSVAL((jsint) JSSTRING_CHARS(str)[index]);
902     }
903     return JS_TRUE;
906 jsint
907 js_BoyerMooreHorspool(const jschar *text, jsint textlen,
908                       const jschar *pat, jsint patlen,
909                       jsint start)
911     jsint i, j, k, m;
912     uint8 skip[BMH_CHARSET_SIZE];
913     jschar c;
915     JS_ASSERT(0 < patlen && patlen <= BMH_PATLEN_MAX);
916     for (i = 0; i < BMH_CHARSET_SIZE; i++)
917         skip[i] = (uint8)patlen;
918     m = patlen - 1;
919     for (i = 0; i < m; i++) {
920         c = pat[i];
921         if (c >= BMH_CHARSET_SIZE)
922             return BMH_BAD_PATTERN;
923         skip[c] = (uint8)(m - i);
924     }
925     for (k = start + m;
926          k < textlen;
927          k += ((c = text[k]) >= BMH_CHARSET_SIZE) ? patlen : skip[c]) {
928         for (i = k, j = m; ; i--, j--) {
929             if (j < 0)
930                 return i + 1;
931             if (text[i] != pat[j])
932                 break;
933         }
934     }
935     return -1;
938 static JSBool
939 str_indexOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
941     JSString *str, *str2;
942     jsint i, j, index, textlen, patlen;
943     const jschar *text, *pat;
944     jsdouble d;
946     str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
947     if (!str)
948         return JS_FALSE;
949     argv[-1] = STRING_TO_JSVAL(str);
950     text = JSSTRING_CHARS(str);
951     textlen = (jsint) JSSTRING_LENGTH(str);
953     str2 = js_ValueToString(cx, argv[0]);
954     if (!str2)
955         return JS_FALSE;
956     argv[0] = STRING_TO_JSVAL(str2);
957     pat = JSSTRING_CHARS(str2);
958     patlen = (jsint) JSSTRING_LENGTH(str2);
960     if (argc > 1) {
961         if (!js_ValueToNumber(cx, argv[1], &d))
962             return JS_FALSE;
963         d = js_DoubleToInteger(d);
964         if (d < 0)
965             i = 0;
966         else if (d > textlen)
967             i = textlen;
968         else
969             i = (jsint)d;
970     } else {
971         i = 0;
972     }
973     if (patlen == 0) {
974         *rval = INT_TO_JSVAL(i);
975         return JS_TRUE;
976     }
978     /* XXX tune the BMH threshold (512) */
979     if ((jsuint)(patlen - 2) <= BMH_PATLEN_MAX - 2 && textlen >= 512) {
980         index = js_BoyerMooreHorspool(text, textlen, pat, patlen, i);
981         if (index != BMH_BAD_PATTERN)
982             goto out;
983     }
985     index = -1;
986     j = 0;
987     while (i + j < textlen) {
988         if (text[i + j] == pat[j]) {
989             if (++j == patlen) {
990                 index = i;
991                 break;
992             }
993         } else {
994             i++;
995             j = 0;
996         }
997     }
999 out:
1000     *rval = INT_TO_JSVAL(index);
1001     return JS_TRUE;
1004 static JSBool
1005 str_lastIndexOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
1006                   jsval *rval)
1008     JSString *str, *str2;
1009     const jschar *text, *pat;
1010     jsint i, j, textlen, patlen;
1011     jsdouble d;
1013     str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
1014     if (!str)
1015         return JS_FALSE;
1016     argv[-1] = STRING_TO_JSVAL(str);
1017     text = JSSTRING_CHARS(str);
1018     textlen = (jsint) JSSTRING_LENGTH(str);
1020     str2 = js_ValueToString(cx, argv[0]);
1021     if (!str2)
1022         return JS_FALSE;
1023     argv[0] = STRING_TO_JSVAL(str2);
1024     pat = JSSTRING_CHARS(str2);
1025     patlen = (jsint) JSSTRING_LENGTH(str2);
1027     if (argc > 1) {
1028         if (!js_ValueToNumber(cx, argv[1], &d))
1029             return JS_FALSE;
1030         if (JSDOUBLE_IS_NaN(d)) {
1031             i = textlen;
1032         } else {
1033             d = js_DoubleToInteger(d);
1034             if (d < 0)
1035                 i = 0;
1036             else if (d > textlen - patlen)
1037                 i = textlen - patlen;
1038             else
1039                 i = (jsint)d;
1040         }
1041     } else {
1042         i = textlen;
1043     }
1045     if (patlen == 0) {
1046         *rval = INT_TO_JSVAL(i);
1047         return JS_TRUE;
1048     }
1050     j = 0;
1051     while (i >= 0) {
1052         /* Don't assume that text is NUL-terminated: it could be dependent. */
1053         if (i + j < textlen && text[i + j] == pat[j]) {
1054             if (++j == patlen)
1055                 break;
1056         } else {
1057             i--;
1058             j = 0;
1059         }
1060     }
1061     *rval = INT_TO_JSVAL(i);
1062     return JS_TRUE;
1065 /*
1066  * Perl-inspired string functions.
1067  */
1068 #if JS_HAS_REGEXPS
1069 typedef struct GlobData {
1070     uintN       flags;          /* inout: mode and flag bits, see below */
1071     uintN       optarg;         /* in: index of optional flags argument */
1072     JSString    *str;           /* out: 'this' parameter object as string */
1073     JSRegExp    *regexp;        /* out: regexp parameter object private data */
1074 } GlobData;
1076 /*
1077  * Mode and flag bit definitions for match_or_replace's GlobData.flags field.
1078  */
1079 #define MODE_MATCH      0x00    /* in: return match array on success */
1080 #define MODE_REPLACE    0x01    /* in: match and replace */
1081 #define MODE_SEARCH     0x02    /* in: search only, return match index or -1 */
1082 #define GET_MODE(f)     ((f) & 0x03)
1083 #define FORCE_FLAT      0x04    /* in: force flat (non-regexp) string match */
1084 #define KEEP_REGEXP     0x08    /* inout: keep GlobData.regexp alive for caller
1085                                           of match_or_replace; if set on input
1086                                           but clear on output, regexp ownership
1087                                           does not pass to caller */
1088 #define GLOBAL_REGEXP   0x10    /* out: regexp had the 'g' flag */
1090 static JSBool
1091 match_or_replace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
1092                  JSBool (*glob)(JSContext *cx, jsint count, GlobData *data),
1093                  GlobData *data, jsval *rval)
1095     JSString *str, *src, *opt;
1096     JSObject *reobj;
1097     JSRegExp *re;
1098     size_t index, length;
1099     JSBool ok, test;
1100     jsint count;
1102     str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
1103     if (!str)
1104         return JS_FALSE;
1105     argv[-1] = STRING_TO_JSVAL(str);
1106     data->str = str;
1108     if (JSVAL_IS_REGEXP(cx, argv[0])) {
1109         reobj = JSVAL_TO_OBJECT(argv[0]);
1110         re = (JSRegExp *) JS_GetPrivate(cx, reobj);
1111     } else {
1112         src = js_ValueToString(cx, argv[0]);
1113         if (!src)
1114             return JS_FALSE;
1115         if (data->optarg < argc) {
1116             argv[0] = STRING_TO_JSVAL(src);
1117             opt = js_ValueToString(cx, argv[data->optarg]);
1118             if (!opt)
1119                 return JS_FALSE;
1120         } else {
1121             opt = NULL;
1122         }
1123         re = js_NewRegExpOpt(cx, NULL, src, opt,
1124                              (data->flags & FORCE_FLAT) != 0);
1125         if (!re)
1126             return JS_FALSE;
1127         reobj = NULL;
1128     }
1129     data->regexp = re;
1131     if (re->flags & JSREG_GLOB)
1132         data->flags |= GLOBAL_REGEXP;
1133     index = 0;
1134     if (GET_MODE(data->flags) == MODE_SEARCH) {
1135         ok = js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, rval);
1136         if (ok) {
1137             *rval = (*rval == JSVAL_TRUE)
1138                     ? INT_TO_JSVAL(cx->regExpStatics.leftContext.length)
1139                     : INT_TO_JSVAL(-1);
1140         }
1141     } else if (data->flags & GLOBAL_REGEXP) {
1142         if (reobj) {
1143             /* Set the lastIndex property's reserved slot to 0. */
1144             ok = js_SetLastIndex(cx, reobj, 0);
1145             if (!ok)
1146                 return JS_FALSE;
1147         } else {
1148             ok = JS_TRUE;
1149         }
1150         length = JSSTRING_LENGTH(str);
1151         for (count = 0; index <= length; count++) {
1152             ok = js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, rval);
1153             if (!ok || *rval != JSVAL_TRUE)
1154                 break;
1155             ok = glob(cx, count, data);
1156             if (!ok)
1157                 break;
1158             if (cx->regExpStatics.lastMatch.length == 0) {
1159                 if (index == length)
1160                     break;
1161                 index++;
1162             }
1163         }
1164     } else {
1165         if (GET_MODE(data->flags) == MODE_REPLACE) {
1166             test = JS_TRUE;
1167         } else {
1168             /*
1169              * MODE_MATCH implies str_match is being called from a script or a
1170              * scripted function.  If the caller cares only about testing null
1171              * vs. non-null return value, optimize away the array object that
1172              * would normally be returned in *rval.
1173              */
1174             JS_ASSERT(*cx->fp->down->pc == JSOP_CALL ||
1175                       *cx->fp->down->pc == JSOP_NEW);
1176             JS_ASSERT(js_CodeSpec[*cx->fp->down->pc].length == 3);
1177             switch (cx->fp->down->pc[3]) {
1178               case JSOP_POP:
1179               case JSOP_IFEQ:
1180               case JSOP_IFNE:
1181               case JSOP_IFEQX:
1182               case JSOP_IFNEX:
1183                 test = JS_TRUE;
1184                 break;
1185               default:
1186                 test = JS_FALSE;
1187                 break;
1188             }
1189         }
1190         ok = js_ExecuteRegExp(cx, re, str, &index, test, rval);
1191     }
1193     if (reobj) {
1194         /* Tell our caller that it doesn't need to destroy data->regexp. */
1195         data->flags &= ~KEEP_REGEXP;
1196     } else if (!(data->flags & KEEP_REGEXP)) {
1197         /* Caller didn't want to keep data->regexp, so null and destroy it.  */
1198         data->regexp = NULL;
1199         js_DestroyRegExp(cx, re);
1200     }
1201     return ok;
1204 typedef struct MatchData {
1205     GlobData    base;
1206     jsval       *arrayval;      /* NB: local root pointer */
1207 } MatchData;
1209 static JSBool
1210 match_glob(JSContext *cx, jsint count, GlobData *data)
1212     MatchData *mdata;
1213     JSObject *arrayobj;
1214     JSSubString *matchsub;
1215     JSString *matchstr;
1216     jsval v;
1218     mdata = (MatchData *)data;
1219     arrayobj = JSVAL_TO_OBJECT(*mdata->arrayval);
1220     if (!arrayobj) {
1221         arrayobj = js_ConstructObject(cx, &js_ArrayClass, NULL, NULL, 0, NULL);
1222         if (!arrayobj)
1223             return JS_FALSE;
1224         *mdata->arrayval = OBJECT_TO_JSVAL(arrayobj);
1225     }
1226     matchsub = &cx->regExpStatics.lastMatch;
1227     matchstr = js_NewStringCopyN(cx, matchsub->chars, matchsub->length, 0);
1228     if (!matchstr)
1229         return JS_FALSE;
1230     v = STRING_TO_JSVAL(matchstr);
1231     return js_SetProperty(cx, arrayobj, INT_TO_JSVAL(count), &v);
1234 static JSBool
1235 str_match(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1237     MatchData mdata;
1238     JSBool ok;
1240     mdata.base.flags = MODE_MATCH;
1241     mdata.base.optarg = 1;
1242     mdata.arrayval = &argv[2];
1243     *mdata.arrayval = JSVAL_NULL;
1244     ok = match_or_replace(cx, obj, argc, argv, match_glob, &mdata.base, rval);
1245     if (ok && !JSVAL_IS_NULL(*mdata.arrayval))
1246         *rval = *mdata.arrayval;
1247     return ok;
1250 static JSBool
1251 str_search(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1253     GlobData data;
1255     data.flags = MODE_SEARCH;
1256     data.optarg = 1;
1257     return match_or_replace(cx, obj, argc, argv, NULL, &data, rval);
1260 typedef struct ReplaceData {
1261     GlobData    base;           /* base struct state */
1262     JSObject    *lambda;        /* replacement function object or null */
1263     JSString    *repstr;        /* replacement string */
1264     jschar      *dollar;        /* null or pointer to first $ in repstr */
1265     jschar      *dollarEnd;     /* limit pointer for js_strchr_limit */
1266     jschar      *chars;         /* result chars, null initially */
1267     size_t      length;         /* result length, 0 initially */
1268     jsint       index;          /* index in result of next replacement */
1269     jsint       leftIndex;      /* left context index in base.str->chars */
1270     JSSubString dollarStr;      /* for "$$" interpret_dollar result */
1271 } ReplaceData;
1273 static JSSubString *
1274 interpret_dollar(JSContext *cx, jschar *dp, ReplaceData *rdata, size_t *skip)
1276     JSRegExpStatics *res;
1277     jschar dc, *cp;
1278     uintN num, tmp;
1279     JSString *str;
1281     JS_ASSERT(*dp == '$');
1283     /*
1284      * Allow a real backslash (literal "\\" before "$1") to escape "$1", e.g.
1285      * Do this only for versions strictly less than ECMAv3.
1286      */
1287     if (cx->version != JSVERSION_DEFAULT && cx->version <= JSVERSION_1_4) {
1288         if (dp > JSSTRING_CHARS(rdata->repstr) && dp[-1] == '\\')
1289             return NULL;
1290     }
1292     /* Interpret all Perl match-induced dollar variables. */
1293     res = &cx->regExpStatics;
1294     dc = dp[1];
1295     if (JS7_ISDEC(dc)) {
1296         if (cx->version != JSVERSION_DEFAULT && cx->version <= JSVERSION_1_4) {
1297             if (dc == '0')
1298                 return NULL;
1300             /* Check for overflow to avoid gobbling arbitrary decimal digits. */
1301             num = 0;
1302             cp = dp;
1303             while ((dc = *++cp) != 0 && JS7_ISDEC(dc)) {
1304                 tmp = 10 * num + JS7_UNDEC(dc);
1305                 if (tmp < num)
1306                     break;
1307                 num = tmp;
1308             }
1309         } else { /* ECMA 3, 1-9 or 01-99 */
1310             num = JS7_UNDEC(dc);
1311             if (num > res->parenCount)
1312                 return NULL;
1313             cp = dp + 2;
1314             dc = *cp;
1315             if ((dc != 0) && JS7_ISDEC(dc)) {
1316                 tmp = 10 * num + JS7_UNDEC(dc);
1317                 if (tmp <= res->parenCount) {
1318                     cp++;
1319                     num = tmp;
1320                 }
1321             }
1322             if (num == 0)
1323                 return NULL;
1324         }
1325         /* Adjust num from 1 $n-origin to 0 array-index-origin. */
1326         num--;
1327         *skip = cp - dp;
1328         return REGEXP_PAREN_SUBSTRING(res, num);
1329     }
1331     *skip = 2;
1332     switch (dc) {
1333       case '$':
1334         rdata->dollarStr.chars = dp;
1335         rdata->dollarStr.length = 1;
1336         return &rdata->dollarStr;
1337       case '&':
1338         return &res->lastMatch;
1339       case '+':
1340         return &res->lastParen;
1341       case '`':
1342         if (cx->version == JSVERSION_1_2) {
1343             /*
1344              * JS1.2 imitated the Perl4 bug where left context at each step
1345              * in an iterative use of a global regexp started from last match,
1346              * not from the start of the target string.  But Perl4 does start
1347              * $` at the beginning of the target string when it is used in a
1348              * substitution, so we emulate that special case here.
1349              */
1350             str = rdata->base.str;
1351             res->leftContext.chars = JSSTRING_CHARS(str);
1352             res->leftContext.length = res->lastMatch.chars
1353                                     - JSSTRING_CHARS(str);
1354         }
1355         return &res->leftContext;
1356       case '\'':
1357         return &res->rightContext;
1358     }
1359     return NULL;
1362 static JSBool
1363 find_replen(JSContext *cx, ReplaceData *rdata, size_t *sizep)
1365     JSString *repstr;
1366     size_t replen, skip;
1367     jschar *dp, *ep;
1368     JSSubString *sub;
1369 #if JS_HAS_REPLACE_LAMBDA
1370     JSObject *lambda;
1372     lambda = rdata->lambda;
1373     if (lambda) {
1374         uintN argc, i, j, m, n, p;
1375         jsval *sp, *oldsp, rval;
1376         void *mark;
1377         JSStackFrame *fp;
1378         JSBool ok;
1380         /*
1381          * Save the rightContext from the current regexp, since it
1382          * gets stuck at the end of the replacement string and may
1383          * be clobbered by a RegExp usage in the lambda function.
1384          */
1385         JSSubString saveRightContext = cx->regExpStatics.rightContext;
1387         /*
1388          * In the lambda case, not only do we find the replacement string's
1389          * length, we compute repstr and return it via rdata for use within
1390          * do_replace.  The lambda is called with arguments ($&, $1, $2, ...,
1391          * index, input), i.e., all the properties of a regexp match array.
1392          * For $&, etc., we must create string jsvals from cx->regExpStatics.
1393          * We grab up stack space to keep the newborn strings GC-rooted.
1394          */
1395         p = rdata->base.regexp->parenCount;
1396         argc = 1 + p + 2;
1397         sp = js_AllocStack(cx, 2 + argc, &mark);
1398         if (!sp)
1399             return JS_FALSE;
1401         /* Push lambda and its 'this' parameter. */
1402         *sp++ = OBJECT_TO_JSVAL(lambda);
1403         *sp++ = OBJECT_TO_JSVAL(OBJ_GET_PARENT(cx, lambda));
1405 #define PUSH_REGEXP_STATIC(sub)                                               \
1406     JS_BEGIN_MACRO                                                            \
1407         JSString *str = js_NewStringCopyN(cx,                                 \
1408                                           cx->regExpStatics.sub.chars,        \
1409                                           cx->regExpStatics.sub.length,       \
1410                                           0);                                 \
1411         if (!str) {                                                           \
1412             ok = JS_FALSE;                                                    \
1413             goto lambda_out;                                                  \
1414         }                                                                     \
1415         *sp++ = STRING_TO_JSVAL(str);                                         \
1416     JS_END_MACRO
1418         /* Push $&, $1, $2, ... */
1419         PUSH_REGEXP_STATIC(lastMatch);
1420         i = 0;
1421         m = cx->regExpStatics.parenCount;
1422         n = JS_MIN(m, 9);
1423         for (j = 0; i < n; i++, j++)
1424             PUSH_REGEXP_STATIC(parens[j]);
1425         for (j = 0; i < m; i++, j++)
1426             PUSH_REGEXP_STATIC(moreParens[j]);
1428 #undef PUSH_REGEXP_STATIC
1430         /* Make sure to push undefined for any unmatched parens. */
1431         for (; i < p; i++)
1432             *sp++ = JSVAL_VOID;
1434         /* Push match index and input string. */
1435         *sp++ = INT_TO_JSVAL((jsint)cx->regExpStatics.leftContext.length);
1436         *sp++ = STRING_TO_JSVAL(rdata->base.str);
1438         /* Lift current frame to include the args and do the call. */
1439         fp = cx->fp;
1440         oldsp = fp->sp;
1441         fp->sp = sp;
1442         ok = js_Invoke(cx, argc, JSINVOKE_INTERNAL);
1443         rval = fp->sp[-1];
1444         fp->sp = oldsp;
1446         if (ok) {
1447             /*
1448              * NB: we count on the newborn string root to hold any string
1449              * created by this js_ValueToString that would otherwise be GC-
1450              * able, until we use rdata->repstr in do_replace.
1451              */
1452             repstr = js_ValueToString(cx, rval);
1453             if (!repstr) {
1454                 ok = JS_FALSE;
1455             } else {
1456                 rdata->repstr = repstr;
1457                 *sizep = JSSTRING_LENGTH(repstr);
1458             }
1459         }
1461       lambda_out:
1462         js_FreeStack(cx, mark);
1463         cx->regExpStatics.rightContext = saveRightContext;
1464         return ok;
1465     }
1466 #endif /* JS_HAS_REPLACE_LAMBDA */
1468     repstr = rdata->repstr;
1469     replen = JSSTRING_LENGTH(repstr);
1470     for (dp = rdata->dollar, ep = rdata->dollarEnd; dp;
1471          dp = js_strchr_limit(dp, '$', ep)) {
1472         sub = interpret_dollar(cx, dp, rdata, &skip);
1473         if (sub) {
1474             replen += sub->length - skip;
1475             dp += skip;
1476         }
1477         else
1478             dp++;
1479     }
1480     *sizep = replen;
1481     return JS_TRUE;
1484 static void
1485 do_replace(JSContext *cx, ReplaceData *rdata, jschar *chars)
1487     JSString *repstr;
1488     jschar *bp, *cp, *dp, *ep;
1489     size_t len, skip;
1490     JSSubString *sub;
1492     repstr = rdata->repstr;
1493     bp = cp = JSSTRING_CHARS(repstr);
1494     for (dp = rdata->dollar, ep = rdata->dollarEnd; dp;
1495          dp = js_strchr_limit(dp, '$', ep)) {
1496         len = dp - cp;
1497         js_strncpy(chars, cp, len);
1498         chars += len;
1499         cp = dp;
1500         sub = interpret_dollar(cx, dp, rdata, &skip);
1501         if (sub) {
1502             len = sub->length;
1503             js_strncpy(chars, sub->chars, len);
1504             chars += len;
1505             cp += skip;
1506             dp += skip;
1507         } else {
1508             dp++;
1509         }
1510     }
1511     js_strncpy(chars, cp, JSSTRING_LENGTH(repstr) - (cp - bp));
1514 static JSBool
1515 replace_glob(JSContext *cx, jsint count, GlobData *data)
1517     ReplaceData *rdata;
1518     JSString *str;
1519     size_t leftoff, leftlen, replen, growth;
1520     const jschar *left;
1521     jschar *chars;
1523     rdata = (ReplaceData *)data;
1524     str = data->str;
1525     leftoff = rdata->leftIndex;
1526     left = JSSTRING_CHARS(str) + leftoff;
1527     leftlen = cx->regExpStatics.lastMatch.chars - left;
1528     rdata->leftIndex = cx->regExpStatics.lastMatch.chars - JSSTRING_CHARS(str);
1529     rdata->leftIndex += cx->regExpStatics.lastMatch.length;
1530     if (!find_replen(cx, rdata, &replen))
1531         return JS_FALSE;
1532     growth = leftlen + replen;
1533     chars = (jschar *)
1534         (rdata->chars
1535          ? JS_realloc(cx, rdata->chars, (rdata->length + growth + 1)
1536                                         * sizeof(jschar))
1537          : JS_malloc(cx, (growth + 1) * sizeof(jschar)));
1538     if (!chars) {
1539         JS_free(cx, rdata->chars);
1540         rdata->chars = NULL;
1541         return JS_FALSE;
1542     }
1543     rdata->chars = chars;
1544     rdata->length += growth;
1545     chars += rdata->index;
1546     rdata->index += growth;
1547     js_strncpy(chars, left, leftlen);
1548     chars += leftlen;
1549     do_replace(cx, rdata, chars);
1550     return JS_TRUE;
1553 static JSBool
1554 str_replace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1556     JSObject *lambda;
1557     JSString *repstr, *str;
1558     ReplaceData rdata;
1559     JSBool ok;
1560     jschar *chars;
1561     size_t leftlen, rightlen, length;
1563 #if JS_HAS_REPLACE_LAMBDA
1564     if (JS_TypeOfValue(cx, argv[1]) == JSTYPE_FUNCTION) {
1565         lambda = JSVAL_TO_OBJECT(argv[1]);
1566         repstr = NULL;
1567     } else
1568 #endif
1569     {
1570         if (!JS_ConvertValue(cx, argv[1], JSTYPE_STRING, &argv[1]))
1571             return JS_FALSE;
1572         repstr = JSVAL_TO_STRING(argv[1]);
1573         lambda = NULL;
1574     }
1576     /*
1577      * For ECMA Edition 3, the first argument is to be converted to a string
1578      * to match in a "flat" sense (without regular expression metachars having
1579      * special meanings) UNLESS the first arg is a RegExp object.
1580      */
1581     rdata.base.flags = MODE_REPLACE | KEEP_REGEXP;
1582     if (cx->version == JSVERSION_DEFAULT || cx->version > JSVERSION_1_4)
1583         rdata.base.flags |= FORCE_FLAT;
1584     rdata.base.optarg = 2;
1586     rdata.lambda = lambda;
1587     rdata.repstr = repstr;
1588     if (repstr) {
1589         rdata.dollarEnd = JSSTRING_CHARS(repstr) + JSSTRING_LENGTH(repstr);
1590         rdata.dollar = js_strchr_limit(JSSTRING_CHARS(repstr), '$',
1591                                        rdata.dollarEnd);
1592     } else {
1593         rdata.dollar = rdata.dollarEnd = NULL;
1594     }
1595     rdata.chars = NULL;
1596     rdata.length = 0;
1597     rdata.index = 0;
1598     rdata.leftIndex = 0;
1600     ok = match_or_replace(cx, obj, argc, argv, replace_glob, &rdata.base, rval);
1601     if (!ok)
1602         return JS_FALSE;
1604     if (!rdata.chars) {
1605         if ((rdata.base.flags & GLOBAL_REGEXP) || *rval != JSVAL_TRUE) {
1606             /* Didn't match even once. */
1607             *rval = STRING_TO_JSVAL(rdata.base.str);
1608             goto out;
1609         }
1610         leftlen = cx->regExpStatics.leftContext.length;
1611         ok = find_replen(cx, &rdata, &length);
1612         if (!ok)
1613             goto out;
1614         length += leftlen;
1615         chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
1616         if (!chars) {
1617             ok = JS_FALSE;
1618             goto out;
1619         }
1620         js_strncpy(chars, cx->regExpStatics.leftContext.chars, leftlen);
1621         do_replace(cx, &rdata, chars + leftlen);
1622         rdata.chars = chars;
1623         rdata.length = length;
1624     }
1626     rightlen = cx->regExpStatics.rightContext.length;
1627     length = rdata.length + rightlen;
1628     chars = (jschar *)
1629         JS_realloc(cx, rdata.chars, (length + 1) * sizeof(jschar));
1630     if (!chars) {
1631         JS_free(cx, rdata.chars);
1632         ok = JS_FALSE;
1633         goto out;
1634     }
1635     js_strncpy(chars + rdata.length, cx->regExpStatics.rightContext.chars,
1636                rightlen);
1637     chars[length] = 0;
1639     str = js_NewString(cx, chars, length, 0);
1640     if (!str) {
1641         JS_free(cx, chars);
1642         ok = JS_FALSE;
1643         goto out;
1644     }
1645     *rval = STRING_TO_JSVAL(str);
1647 out:
1648     /* If KEEP_REGEXP is still set, it's our job to destroy regexp now. */
1649     if (rdata.base.flags & KEEP_REGEXP)
1650         js_DestroyRegExp(cx, rdata.base.regexp);
1651     return ok;
1653 #endif /* JS_HAS_REGEXPS */
1655 /*
1656  * Subroutine used by str_split to find the next split point in str, starting
1657  * at offset *ip and looking either for the separator substring given by sep,
1658  * or for the next re match.  In the re case, return the matched separator in
1659  * *sep, and the possibly updated offset in *ip.
1660  *
1661  * Return -2 on error, -1 on end of string, >= 0 for a valid index of the next
1662  * separator occurrence if found, or str->length if no separator is found.
1663  */
1664 static jsint
1665 find_split(JSContext *cx, JSString *str, JSRegExp *re, jsint *ip,
1666            JSSubString *sep)
1668     jsint i, j, k;
1669     jschar *chars;
1670     size_t length;
1672     /*
1673      * Stop if past end of string.  If at end of string, we will compare the
1674      * null char stored there (by js_NewString*) to sep->chars[j] in the while
1675      * loop at the end of this function, so that
1676      *
1677      *  "ab,".split(',') => ["ab", ""]
1678      *
1679      * and the resulting array converts back to the string "ab," for symmetry.
1680      * However, we ape Perl and do this only if there is a sufficiently large
1681      * limit argument (see str_split).
1682      */
1683     i = *ip;
1684     if ((size_t)i > JSSTRING_LENGTH(str))
1685         return -1;
1687     /*
1688      * Perl4 special case for str.split(' '), only if the user has selected
1689      * JavaScript1.2 explicitly.  Split on whitespace, and skip leading w/s.
1690      * Strange but true, apparently modeled after awk.
1691      *
1692      * NB: we set sep->length to the length of the w/s run, so we must test
1693      * sep->chars[1] == 0 to make sure sep is just one space.
1694      */
1695     chars = JSSTRING_CHARS(str);
1696     length = JSSTRING_LENGTH(str);
1697     if (cx->version == JSVERSION_1_2 &&
1698         !re && *sep->chars == ' ' && sep->chars[1] == 0) {
1700         /* Skip leading whitespace if at front of str. */
1701         if (i == 0) {
1702             while (JS_ISSPACE(chars[i]))
1703                 i++;
1704             *ip = i;
1705         }
1707         /* Don't delimit whitespace at end of string. */
1708         if ((size_t)i == length)
1709             return -1;
1711         /* Skip over the non-whitespace chars. */
1712         while ((size_t)i < length && !JS_ISSPACE(chars[i]))
1713             i++;
1715         /* Now skip the next run of whitespace. */
1716         j = i;
1717         while ((size_t)j < length && JS_ISSPACE(chars[j]))
1718             j++;
1720         /* Update sep->length to count delimiter chars. */
1721         sep->length = (size_t)(j - i);
1722         return i;
1723     }
1725 #if JS_HAS_REGEXPS
1726     /*
1727      * Match a regular expression against the separator at or above index i.
1728      * Call js_ExecuteRegExp with true for the test argument.  On successful
1729      * match, get the separator from cx->regExpStatics.lastMatch.
1730      */
1731     if (re) {
1732         size_t index;
1733         jsval rval;
1735       again:
1736         /* JS1.2 deviated from Perl by never matching at end of string. */
1737         index = (size_t)i;
1738         if (!js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, &rval))
1739             return -2;
1740         if (rval != JSVAL_TRUE) {
1741             /* Mismatch: ensure our caller advances i past end of string. */
1742             sep->length = 1;
1743             return length;
1744         }
1745         i = (jsint)index;
1746         *sep = cx->regExpStatics.lastMatch;
1747         if (sep->length == 0) {
1748             /*
1749              * Empty string match: never split on an empty match at the start
1750              * of a find_split cycle.  Same rule as for an empty global match
1751              * in match_or_replace.
1752              */
1753             if (i == *ip) {
1754                 /*
1755                  * "Bump-along" to avoid sticking at an empty match, but don't
1756                  * bump past end of string -- our caller must do that by adding
1757                  * sep->length to our return value.
1758                  */
1759                 if ((size_t)i == length) {
1760                     if (cx->version == JSVERSION_1_2) {
1761                         sep->length = 1;
1762                         return i;
1763                     }
1764                     return -1;
1765                 }
1766                 i++;
1767                 goto again;
1768             }
1769         }
1770         JS_ASSERT((size_t)i >= sep->length);
1771         return i - sep->length;
1772     }
1773 #endif /* JS_HAS_REGEXPS */
1775     /*
1776      * Deviate from ECMA by never splitting an empty string by any separator
1777      * string into a non-empty array (an array of length 1 that contains the
1778      * empty string).
1779      */
1780     if (!JSVERSION_IS_ECMA(cx->version) && length == 0)
1781         return -1;
1783     /*
1784      * Special case: if sep is the empty string, split str into one character
1785      * substrings.  Let our caller worry about whether to split once at end of
1786      * string into an empty substring.
1787      *
1788      * For 1.2 compatibility, at the end of the string, we return the length as
1789      * the result, and set the separator length to 1 -- this allows the caller
1790      * to include an additional null string at the end of the substring list.
1791      */
1792     if (sep->length == 0) {
1793         if (cx->version == JSVERSION_1_2) {
1794             if ((size_t)i == length) {
1795                 sep->length = 1;
1796                 return i;
1797             }
1798             return i + 1;
1799         }
1800         return ((size_t)i == length) ? -1 : i + 1;
1801     }
1803     /*
1804      * Now that we know sep is non-empty, search starting at i in str for an
1805      * occurrence of all of sep's chars.  If we find them, return the index of
1806      * the first separator char.  Otherwise, return length.
1807      */
1808     j = 0;
1809     while ((size_t)(k = i + j) < length) {
1810         if (chars[k] == sep->chars[j]) {
1811             if ((size_t)++j == sep->length)
1812                 return i;
1813         } else {
1814             i++;
1815             j = 0;
1816         }
1817     }
1818     return k;
1821 static JSBool
1822 str_split(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1824     JSString *str, *sub;
1825     JSObject *arrayobj;
1826     jsval v;
1827     JSBool ok, limited;
1828     JSRegExp *re;
1829     JSSubString *sep, tmp;
1830     jsdouble d;
1831     jsint i, j;
1832     uint32 len, limit;
1834     str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
1835     if (!str)
1836         return JS_FALSE;
1837     argv[-1] = STRING_TO_JSVAL(str);
1839     arrayobj = js_ConstructObject(cx, &js_ArrayClass, NULL, NULL, 0, NULL);
1840     if (!arrayobj)
1841         return JS_FALSE;
1842     *rval = OBJECT_TO_JSVAL(arrayobj);
1844     if (argc == 0) {
1845         v = STRING_TO_JSVAL(str);
1846         ok = JS_SetElement(cx, arrayobj, 0, &v);
1847     } else {
1848 #if JS_HAS_REGEXPS
1849         if (JSVAL_IS_REGEXP(cx, argv[0])) {
1850             re = (JSRegExp *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
1851             sep = &tmp;
1853             /* Set a magic value so we can detect a successful re match. */
1854             sep->chars = NULL;
1855         } else
1856 #endif
1857         {
1858             JSString *str2 = js_ValueToString(cx, argv[0]);
1859             if (!str2)
1860                 return JS_FALSE;
1861             argv[0] = STRING_TO_JSVAL(str2);
1863             /*
1864              * Point sep at a local copy of str2's header because find_split
1865              * will modify sep->length.
1866              */
1867             tmp.length = JSSTRING_LENGTH(str2);
1868             tmp.chars = JSSTRING_CHARS(str2);
1869             sep = &tmp;
1870             re = NULL;
1871         }
1873         /* Use the second argument as the split limit, if given. */
1874         limited = (argc > 1) && !JSVAL_IS_VOID(argv[1]);
1875         limit = 0; /* Avoid warning. */
1876         if (limited) {
1877             if (!js_ValueToNumber(cx, argv[1], &d))
1878                 return JS_FALSE;
1880             /* Clamp limit between 0 and 1 + string length. */
1881             if (!js_DoubleToECMAUint32(cx, d, &limit))
1882                 return JS_FALSE;
1883             if (limit > JSSTRING_LENGTH(str))
1884                 limit = 1 + JSSTRING_LENGTH(str);
1885         }
1887         len = i = 0;
1888         while ((j = find_split(cx, str, re, &i, sep)) >= 0) {
1889             if (limited && len >= limit)
1890                 break;
1891             sub = js_NewDependentString(cx, str, i, (size_t)(j - i), 0);
1892             if (!sub)
1893                 return JS_FALSE;
1894             v = STRING_TO_JSVAL(sub);
1895             if (!JS_SetElement(cx, arrayobj, len, &v))
1896                 return JS_FALSE;
1897             len++;
1898 #if JS_HAS_REGEXPS
1899             /*
1900              * Imitate perl's feature of including parenthesized substrings
1901              * that matched part of the delimiter in the new array, after the
1902              * split substring that was delimited.
1903              */
1904             if (re && sep->chars) {
1905                 uintN num;
1906                 JSSubString *parsub;
1908                 for (num = 0; num < cx->regExpStatics.parenCount; num++) {
1909                     if (limited && len >= limit)
1910                         break;
1911                     parsub = REGEXP_PAREN_SUBSTRING(&cx->regExpStatics, num);
1912                     sub = js_NewStringCopyN(cx, parsub->chars, parsub->length,
1913                                             0);
1914                     if (!sub)
1915                         return JS_FALSE;
1916                     v = STRING_TO_JSVAL(sub);
1917                     if (!JS_SetElement(cx, arrayobj, len, &v))
1918                         return JS_FALSE;
1919                     len++;
1920                 }
1921                 sep->chars = NULL;
1922             }
1923 #endif
1924             i = j + sep->length;
1925             if (!JSVERSION_IS_ECMA(cx->version)) {
1926                 /*
1927                  * Deviate from ECMA to imitate Perl, which omits a final
1928                  * split unless a limit argument is given and big enough.
1929                  */
1930                 if (!limited && (size_t)i == JSSTRING_LENGTH(str))
1931                     break;
1932             }
1933         }
1934         ok = (j != -2);
1935     }
1936     return ok;
1939 #if JS_HAS_PERL_SUBSTR
1940 static JSBool
1941 str_substr(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1943     JSString *str;
1944     jsdouble d;
1945     jsdouble length, begin, end;
1947     str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
1948     if (!str)
1949         return JS_FALSE;
1951     if (argc != 0) {
1952         if (!js_ValueToNumber(cx, argv[0], &d))
1953             return JS_FALSE;
1954         length = JSSTRING_LENGTH(str);
1955         begin = js_DoubleToInteger(d);
1956         if (begin < 0) {
1957             begin += length;
1958             if (begin < 0)
1959                 begin = 0;
1960         } else if (begin > length) {
1961             begin = length;
1962         }
1964         if (argc == 1) {
1965             end = length;
1966         } else {
1967             if (!js_ValueToNumber(cx, argv[1], &d))
1968                 return JS_FALSE;
1969             end = js_DoubleToInteger(d);
1970             if (end < 0)
1971                 end = 0;
1972             end += begin;
1973             if (end > length)
1974                 end = length;
1975         }
1977         str = js_NewDependentString(cx, str, (size_t)begin,
1978                                     (size_t)(end - begin), 0);
1979         if (!str)
1980             return JS_FALSE;
1981     }
1982     *rval = STRING_TO_JSVAL(str);
1983     return JS_TRUE;
1985 #endif /* JS_HAS_PERL_SUBSTR */
1987 #if JS_HAS_SEQUENCE_OPS
1988 /*
1989  * Python-esque sequence operations.
1990  */
1991 static JSBool
1992 str_concat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
1994     JSString *str, *str2;
1995     uintN i;
1997     str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
1998     if (!str)
1999         return JS_FALSE;
2000     argv[-1] = STRING_TO_JSVAL(str);
2002     for (i = 0; i < argc; i++) {
2003         str2 = js_ValueToString(cx, argv[i]);
2004         if (!str2)
2005             return JS_FALSE;
2006         argv[i] = STRING_TO_JSVAL(str2);
2008         str = js_ConcatStrings(cx, str, str2);
2009         if (!str)
2010             return JS_FALSE;
2011     }
2013     *rval = STRING_TO_JSVAL(str);
2014     return JS_TRUE;
2017 static JSBool
2018 str_slice(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2020     JSString *str;
2021     jsdouble d;
2022     jsdouble length, begin, end;
2024     str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
2025     if (!str)
2026         return JS_FALSE;
2027     argv[-1] = STRING_TO_JSVAL(str);
2029     if (argc != 0) {
2030         if (!js_ValueToNumber(cx, argv[0], &d))
2031             return JS_FALSE;
2032         length = JSSTRING_LENGTH(str);
2033         begin = js_DoubleToInteger(d);
2034         if (begin < 0) {
2035             begin += length;
2036             if (begin < 0)
2037                 begin = 0;
2038         } else if (begin > length) {
2039             begin = length;
2040         }
2042         if (argc == 1) {
2043             end = length;
2044         } else {
2045             if (!js_ValueToNumber(cx, argv[1], &d))
2046                 return JS_FALSE;
2047             end = js_DoubleToInteger(d);
2048             if (end < 0) {
2049                 end += length;
2050                 if (end < 0)
2051                     end = 0;
2052             } else if (end > length) {
2053                 end = length;
2054             }
2055             if (end < begin)
2056                 end = begin;
2057         }
2059         str = js_NewDependentString(cx, str, (size_t)begin,
2060                                     (size_t)(end - begin), 0);
2061         if (!str)
2062             return JS_FALSE;
2063     }
2064     *rval = STRING_TO_JSVAL(str);
2065     return JS_TRUE;
2067 #endif /* JS_HAS_SEQUENCE_OPS */
2069 #if JS_HAS_STR_HTML_HELPERS
2070 /*
2071  * HTML composition aids.
2072  */
2073 static JSBool
2074 tagify(JSContext *cx, JSObject *obj, jsval *argv,
2075        const char *begin, const jschar *param, const char *end,
2076        jsval *rval)
2078     JSString *str;
2079     jschar *tagbuf;
2080     size_t beglen, endlen, parlen, taglen;
2081     size_t i, j;
2083     str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
2084     if (!str)
2085         return JS_FALSE;
2086     argv[-1] = STRING_TO_JSVAL(str);
2088     if (!end)
2089         end = begin;
2091     beglen = strlen(begin);
2092     taglen = 1 + beglen + 1;                            /* '<begin' + '>' */
2093     parlen = 0; /* Avoid warning. */
2094     if (param) {
2095         parlen = js_strlen(param);
2096         taglen += 2 + parlen + 1;                       /* '="param"' */
2097     }
2098     endlen = strlen(end);
2099     taglen += JSSTRING_LENGTH(str) + 2 + endlen + 1;    /* 'str</end>' */
2101     tagbuf = (jschar *) JS_malloc(cx, (taglen + 1) * sizeof(jschar));
2102     if (!tagbuf)
2103         return JS_FALSE;
2105     j = 0;
2106     tagbuf[j++] = '<';
2107     for (i = 0; i < beglen; i++)
2108         tagbuf[j++] = (jschar)begin[i];
2109     if (param) {
2110         tagbuf[j++] = '=';
2111         tagbuf[j++] = '"';
2112         js_strncpy(&tagbuf[j], param, parlen);
2113         j += parlen;
2114         tagbuf[j++] = '"';
2115     }
2116     tagbuf[j++] = '>';
2117     js_strncpy(&tagbuf[j], JSSTRING_CHARS(str), JSSTRING_LENGTH(str));
2118     j += JSSTRING_LENGTH(str);
2119     tagbuf[j++] = '<';
2120     tagbuf[j++] = '/';
2121     for (i = 0; i < endlen; i++)
2122         tagbuf[j++] = (jschar)end[i];
2123     tagbuf[j++] = '>';
2124     JS_ASSERT(j == taglen);
2125     tagbuf[j] = 0;
2127     str = js_NewString(cx, tagbuf, taglen, 0);
2128     if (!str) {
2129         free((char *)tagbuf);
2130         return JS_FALSE;
2131     }
2132     *rval = STRING_TO_JSVAL(str);
2133     return JS_TRUE;
2136 static JSBool
2137 tagify_value(JSContext *cx, JSObject *obj, jsval *argv,
2138              const char *begin, const char *end,
2139              jsval *rval)
2141     JSString *param;
2143     param = js_ValueToString(cx, argv[0]);
2144     if (!param)
2145         return JS_FALSE;
2146     argv[0] = STRING_TO_JSVAL(param);
2147     return tagify(cx, obj, argv, begin, JSSTRING_CHARS(param), end, rval);
2150 static JSBool
2151 str_bold(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2153     return tagify(cx, obj, argv, "b", NULL, NULL, rval);
2156 static JSBool
2157 str_italics(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2159     return tagify(cx, obj, argv, "i", NULL, NULL, rval);
2162 static JSBool
2163 str_fixed(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2165     return tagify(cx, obj, argv, "tt", NULL, NULL, rval);
2168 static JSBool
2169 str_fontsize(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2171     return tagify_value(cx, obj, argv, "font size", "font", rval);
2174 static JSBool
2175 str_fontcolor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
2176               jsval *rval)
2178     return tagify_value(cx, obj, argv, "font color", "font", rval);
2181 static JSBool
2182 str_link(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2184     return tagify_value(cx, obj, argv, "a href", "a", rval);
2187 static JSBool
2188 str_anchor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2190     return tagify_value(cx, obj, argv, "a name", "a", rval);
2193 static JSBool
2194 str_strike(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2196     return tagify(cx, obj, argv, "strike", NULL, NULL, rval);
2199 static JSBool
2200 str_small(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2202     return tagify(cx, obj, argv, "small", NULL, NULL, rval);
2205 static JSBool
2206 str_big(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2208     return tagify(cx, obj, argv, "big", NULL, NULL, rval);
2211 static JSBool
2212 str_blink(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2214     return tagify(cx, obj, argv, "blink", NULL, NULL, rval);
2217 static JSBool
2218 str_sup(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2220     return tagify(cx, obj, argv, "sup", NULL, NULL, rval);
2223 static JSBool
2224 str_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2226     return tagify(cx, obj, argv, "sub", NULL, NULL, rval);
2228 #endif /* JS_HAS_STR_HTML_HELPERS */
2230 static JSFunctionSpec string_methods[] = {
2231 #if JS_HAS_TOSOURCE
2232     {"quote",               str_quote,              0,0,0},
2233     {js_toSource_str,       str_toSource,           0,0,0},
2234 #endif
2236     /* Java-like methods. */
2237     {js_toString_str,       str_toString,           0,0,0},
2238     {js_valueOf_str,        str_valueOf,            0,0,0},
2239     {"substring",           str_substring,          2,0,0},
2240     {"toLowerCase",         str_toLowerCase,        0,0,0},
2241     {"toUpperCase",         str_toUpperCase,        0,0,0},
2242     {"charAt",              str_charAt,             1,0,0},
2243     {"charCodeAt",          str_charCodeAt,         1,0,0},
2244     {"indexOf",             str_indexOf,            1,0,0},
2245     {"lastIndexOf",         str_lastIndexOf,        1,0,0},
2246     {"toLocaleLowerCase",   str_toLocaleLowerCase,  0,0,0},
2247     {"toLocaleUpperCase",   str_toLocaleUpperCase,  0,0,0},
2248     {"localeCompare",       str_localeCompare,      1,0,0},
2250     /* Perl-ish methods (search is actually Python-esque). */
2251 #if JS_HAS_REGEXPS
2252     {"match",               str_match,              1,0,2},
2253     {"search",              str_search,             1,0,0},
2254     {"replace",             str_replace,            2,0,0},
2255     {"split",               str_split,              2,0,0},
2256 #endif
2257 #if JS_HAS_PERL_SUBSTR
2258     {"substr",              str_substr,             2,0,0},
2259 #endif
2261     /* Python-esque sequence methods. */
2262 #if JS_HAS_SEQUENCE_OPS
2263     {"concat",              str_concat,             0,0,0},
2264     {"slice",               str_slice,              0,0,0},
2265 #endif
2267     /* HTML string methods. */
2268 #if JS_HAS_STR_HTML_HELPERS
2269     {"bold",                str_bold,               0,0,0},
2270     {"italics",             str_italics,            0,0,0},
2271     {"fixed",               str_fixed,              0,0,0},
2272     {"fontsize",            str_fontsize,           1,0,0},
2273     {"fontcolor",           str_fontcolor,          1,0,0},
2274     {"link",                str_link,               1,0,0},
2275     {"anchor",              str_anchor,             1,0,0},
2276     {"strike",              str_strike,             0,0,0},
2277     {"small",               str_small,              0,0,0},
2278     {"big",                 str_big,                0,0,0},
2279     {"blink",               str_blink,              0,0,0},
2280     {"sup",                 str_sup,                0,0,0},
2281     {"sub",                 str_sub,                0,0,0},
2282 #endif
2284     {0,0,0,0,0}
2285 };
2287 static JSBool
2288 String(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2290     JSString *str;
2292     if (argc > 0) {
2293         str = js_ValueToString(cx, argv[0]);
2294         if (!str)
2295             return JS_FALSE;
2296     } else {
2297         str = cx->runtime->emptyString;
2298     }
2299     if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
2300         *rval = STRING_TO_JSVAL(str);
2301         return JS_TRUE;
2302     }
2303     OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, STRING_TO_JSVAL(str));
2304     return JS_TRUE;
2307 static JSBool
2308 str_fromCharCode(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
2309                  jsval *rval)
2311     jschar *chars;
2312     uintN i;
2313     uint16 code;
2314     JSString *str;
2316     chars = (jschar *) JS_malloc(cx, (argc + 1) * sizeof(jschar));
2317     if (!chars)
2318         return JS_FALSE;
2319     for (i = 0; i < argc; i++) {
2320         if (!js_ValueToUint16(cx, argv[i], &code)) {
2321             JS_free(cx, chars);
2322             return JS_FALSE;
2323         }
2324         chars[i] = (jschar)code;
2325     }
2326     chars[i] = 0;
2327     str = js_NewString(cx, chars, argc, 0);
2328     if (!str) {
2329         JS_free(cx, chars);
2330         return JS_FALSE;
2331     }
2332     *rval = STRING_TO_JSVAL(str);
2333     return JS_TRUE;
2336 static JSFunctionSpec string_static_methods[] = {
2337     {"fromCharCode",    str_fromCharCode,       1,0,0},
2338     {0,0,0,0,0}
2339 };
2341 static JSHashTable *deflated_string_cache;
2342 #ifdef DEBUG
2343 static uint32 deflated_string_cache_bytes;
2344 #endif
2345 #ifdef JS_THREADSAFE
2346 static JSLock *deflated_string_cache_lock;
2347 #endif
2349 JSBool
2350 js_InitStringGlobals(void)
2352 #ifdef JS_THREADSAFE
2353     /* Must come through here once in primordial thread to init safely! */
2354     if (!deflated_string_cache_lock) {
2355         deflated_string_cache_lock = JS_NEW_LOCK();
2356         if (!deflated_string_cache_lock)
2357             return JS_FALSE;
2358     }
2359 #endif
2360     return JS_TRUE;
2363 void
2364 js_FreeStringGlobals()
2366     if (deflated_string_cache) {
2367         JS_HashTableDestroy(deflated_string_cache);
2368         deflated_string_cache = NULL;
2369     }
2370 #ifdef JS_THREADSAFE
2371     if (deflated_string_cache_lock) {
2372         JS_DESTROY_LOCK(deflated_string_cache_lock);
2373         deflated_string_cache_lock = NULL;
2374     }
2375 #endif
2378 JSBool
2379 js_InitRuntimeStringState(JSContext *cx)
2381     JSRuntime *rt;
2382     JSString *empty;
2384     rt = cx->runtime;
2385     JS_ASSERT(!rt->emptyString);
2387     /* Make a permanently locked empty string. */
2388     empty = js_NewStringCopyN(cx, js_empty_ucstr, 0, GCF_LOCK);
2389     if (!empty)
2390         return JS_FALSE;
2392     /* Atomize it for scripts that use '' + x to convert x to string. */
2393     if (!js_AtomizeString(cx, empty, ATOM_PINNED))
2394         return JS_FALSE;
2396     rt->emptyString = empty;
2397     return JS_TRUE;
2400 void
2401 js_FinishRuntimeStringState(JSContext *cx)
2403     JSRuntime *rt = cx->runtime;
2405     js_UnlockGCThingRT(rt, rt->emptyString);
2406     rt->emptyString = NULL;
2409 JSObject *
2410 js_InitStringClass(JSContext *cx, JSObject *obj)
2412     JSObject *proto;
2414     /* Define the escape, unescape functions in the global object. */
2415     if (!JS_DefineFunctions(cx, obj, string_functions))
2416         return NULL;
2418     proto = JS_InitClass(cx, obj, NULL, &string_class, String, 1,
2419                          string_props, string_methods,
2420                          NULL, string_static_methods);
2421     if (!proto)
2422         return NULL;
2423     OBJ_SET_SLOT(cx, proto, JSSLOT_PRIVATE,
2424                  STRING_TO_JSVAL(cx->runtime->emptyString));
2425     return proto;
2428 JSString *
2429 js_NewString(JSContext *cx, jschar *chars, size_t length, uintN gcflag)
2431     JSString *str;
2433     if (length > JSSTRING_LENGTH_MASK) {
2434         JS_ReportOutOfMemory(cx);
2435         return NULL;
2436     }
2438     str = (JSString *) js_AllocGCThing(cx, gcflag | GCX_STRING);
2439     if (!str)
2440         return NULL;
2441     str->length = length;
2442     str->chars = chars;
2443 #ifdef DEBUG
2444   {
2445     JSRuntime *rt = cx->runtime;
2446     JS_RUNTIME_METER(rt, liveStrings);
2447     JS_RUNTIME_METER(rt, totalStrings);
2448     JS_LOCK_RUNTIME_VOID(rt,
2449         (rt->lengthSum += (double)length,
2450          rt->lengthSquaredSum += (double)length * (double)length));
2451   }
2452 #endif
2453     return str;
2456 JSString *
2457 js_NewDependentString(JSContext *cx, JSString *base, size_t start,
2458                       size_t length, uintN gcflag)
2460     JSDependentString *ds;
2462     if (length == 0)
2463         return cx->runtime->emptyString;
2465     if (start > JSSTRDEP_START_MASK ||
2466         (start != 0 && length > JSSTRDEP_LENGTH_MASK)) {
2467         return js_NewStringCopyN(cx, JSSTRING_CHARS(base) + start, length,
2468                                  gcflag);
2469     }
2471     ds = (JSDependentString *) js_AllocGCThing(cx, gcflag | GCX_MUTABLE_STRING);
2472     if (!ds)
2473         return NULL;
2474     if (start == 0) {
2475         JSPREFIX_SET_LENGTH(ds, length);
2476         JSPREFIX_SET_BASE(ds, base);
2477     } else {
2478         JSSTRDEP_SET_START_AND_LENGTH(ds, start, length);
2479         JSSTRDEP_SET_BASE(ds, base);
2480     }
2481 #ifdef DEBUG
2482   {
2483     JSRuntime *rt = cx->runtime;
2484     JS_RUNTIME_METER(rt, liveDependentStrings);
2485     JS_RUNTIME_METER(rt, totalDependentStrings);
2486     JS_RUNTIME_METER(rt, liveStrings);
2487     JS_RUNTIME_METER(rt, totalStrings);
2488     JS_LOCK_RUNTIME_VOID(rt,
2489         (rt->strdepLengthSum += (double)length,
2490          rt->strdepLengthSquaredSum += (double)length * (double)length));
2491     JS_LOCK_RUNTIME_VOID(rt,
2492         (rt->lengthSum += (double)length,
2493          rt->lengthSquaredSum += (double)length * (double)length));
2494   }
2495 #endif
2496     return (JSString *)ds;
2499 #ifdef DEBUG
2500 #include <math.h>
2502 void printJSStringStats(JSRuntime *rt) {
2503     double mean = 0., var = 0., sigma = 0.;
2504     jsrefcount count = rt->totalStrings;
2505     if (count > 0 && rt->lengthSum >= 0) {
2506         mean = rt->lengthSum / count;
2507         var = count * rt->lengthSquaredSum - rt->lengthSum * rt->lengthSum;
2508         if (var < 0.0 || count <= 1)
2509             var = 0.0;
2510         else
2511             var /= count * (count - 1);
2513         /* Windows says sqrt(0.0) is "-1.#J" (?!) so we must test. */
2514         sigma = (var != 0.) ? sqrt(var) : 0.;
2515     }
2516     fprintf(stderr, "%lu total strings, mean length %g (sigma %g)\n",
2517             (unsigned long)count, mean, sigma);
2519     mean = var = sigma = 0.;
2520     count = rt->totalDependentStrings;
2521     if (count > 0 && rt->strdepLengthSum >= 0) {
2522         mean = rt->strdepLengthSum / count;
2523         var = count * rt->strdepLengthSquaredSum
2524             - rt->strdepLengthSum * rt->strdepLengthSum;
2525         if (var < 0.0 || count <= 1)
2526             var = 0.0;
2527         else
2528             var /= count * (count - 1);
2530         /* Windows says sqrt(0.0) is "-1.#J" (?!) so we must test. */
2531         sigma = (var != 0.) ? sqrt(var) : 0.;
2532     }
2533     fprintf(stderr, "%lu total dependent strings, mean length %g (sigma %g)\n",
2534             (unsigned long)count, mean, sigma);
2536 #endif
2538 JSString *
2539 js_NewStringCopyN(JSContext *cx, const jschar *s, size_t n, uintN gcflag)
2541     jschar *news;
2542     JSString *str;
2544     news = (jschar *)JS_malloc(cx, (n + 1) * sizeof(jschar));
2545     if (!news)
2546         return NULL;
2547     js_strncpy(news, s, n);
2548     news[n] = 0;
2549     str = js_NewString(cx, news, n, gcflag);
2550     if (!str)
2551         JS_free(cx, news);
2552     return str;
2555 JSString *
2556 js_NewStringCopyZ(JSContext *cx, const jschar *s, uintN gcflag)
2558     size_t n, m;
2559     jschar *news;
2560     JSString *str;
2562     n = js_strlen(s);
2563     m = (n + 1) * sizeof(jschar);
2564     news = (jschar *) JS_malloc(cx, m);
2565     if (!news)
2566         return NULL;
2567     memcpy(news, s, m);
2568     str = js_NewString(cx, news, n, gcflag);
2569     if (!str)
2570         JS_free(cx, news);
2571     return str;
2574 JS_STATIC_DLL_CALLBACK(JSHashNumber)
2575 js_hash_string_pointer(const void *key)
2577     return (JSHashNumber)key >> JSVAL_TAGBITS;
2580 void
2581 js_PurgeDeflatedStringCache(JSString *str)
2583     JSHashNumber hash;
2584     JSHashEntry *he, **hep;
2586     if (!deflated_string_cache)
2587         return;
2589     hash = js_hash_string_pointer(str);
2590     JS_ACQUIRE_LOCK(deflated_string_cache_lock);
2591     hep = JS_HashTableRawLookup(deflated_string_cache, hash, str);
2592     he = *hep;
2593     if (he) {
2594 #ifdef DEBUG
2595         deflated_string_cache_bytes -= JSSTRING_LENGTH(str);
2596 #endif
2597         free(he->value);
2598         JS_HashTableRawRemove(deflated_string_cache, hep, he);
2599     }
2600     JS_RELEASE_LOCK(deflated_string_cache_lock);
2603 void
2604 js_FinalizeString(JSContext *cx, JSString *str)
2606     js_FinalizeStringRT(cx->runtime, str);
2609 void
2610 js_FinalizeStringRT(JSRuntime *rt, JSString *str)
2612     JSBool valid;
2614     JS_RUNTIME_UNMETER(rt, liveStrings);
2615     if (JSSTRING_IS_DEPENDENT(str)) {
2616         /* If JSSTRFLAG_DEPENDENT is set, this string must be valid. */
2617         JS_ASSERT(JSSTRDEP_BASE(str));
2618         JS_RUNTIME_UNMETER(rt, liveDependentStrings);
2619         valid = JS_TRUE;
2620     } else {
2621         /* A stillborn string has null chars, so is not valid. */
2622         valid = (str->chars != NULL);
2623         if (valid)
2624             free(str->chars);
2625     }
2626     if (valid) {
2627         js_PurgeDeflatedStringCache(str);
2628         str->chars = NULL;
2629     }
2630     str->length = 0;
2633 JSObject *
2634 js_StringToObject(JSContext *cx, JSString *str)
2636     JSObject *obj;
2638     obj = js_NewObject(cx, &string_class, NULL, NULL);
2639     if (!obj)
2640         return NULL;
2641     OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, STRING_TO_JSVAL(str));
2642     return obj;
2645 JSString *
2646 js_ValueToString(JSContext *cx, jsval v)
2648     JSObject *obj;
2649     JSString *str;
2651     if (JSVAL_IS_OBJECT(v)) {
2652         obj = JSVAL_TO_OBJECT(v);
2653         if (!obj)
2654             return ATOM_TO_STRING(cx->runtime->atomState.nullAtom);
2655         if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_STRING, &v))
2656             return NULL;
2657     }
2658     if (JSVAL_IS_STRING(v)) {
2659         str = JSVAL_TO_STRING(v);
2660     } else if (JSVAL_IS_INT(v)) {
2661         str = js_NumberToString(cx, JSVAL_TO_INT(v));
2662     } else if (JSVAL_IS_DOUBLE(v)) {
2663         str = js_NumberToString(cx, *JSVAL_TO_DOUBLE(v));
2664     } else if (JSVAL_IS_BOOLEAN(v)) {
2665         str = js_BooleanToString(cx, JSVAL_TO_BOOLEAN(v));
2666     } else {
2667         str = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_VOID]);
2668     }
2669     return str;
2672 JSString *
2673 js_ValueToSource(JSContext *cx, jsval v)
2675     if (JSVAL_IS_STRING(v))
2676         return js_QuoteString(cx, JSVAL_TO_STRING(v), '"');
2677     if (JSVAL_IS_PRIMITIVE(v)) {
2678         /* Special case to preserve negative zero, _contra_ toString. */
2679         if (JSVAL_IS_DOUBLE(v) && JSDOUBLE_IS_NEGZERO(*JSVAL_TO_DOUBLE(v))) {
2680             /* NB: _ucNstr rather than _ucstr to indicate non-terminated. */
2681             static const jschar js_negzero_ucNstr[] = {'-', '0'};
2683             return js_NewStringCopyN(cx, js_negzero_ucNstr, 2, 0);
2684         }
2685     } else {
2686         if (!js_TryMethod(cx, JSVAL_TO_OBJECT(v),
2687                           cx->runtime->atomState.toSourceAtom,
2688                           0, NULL, &v)) {
2689             return NULL;
2690         }
2691     }
2692     return js_ValueToString(cx, v);
2695 JSHashNumber
2696 js_HashString(JSString *str)
2698     JSHashNumber h;
2699     const jschar *s;
2700     size_t n;
2702     h = 0;
2703     for (s = JSSTRING_CHARS(str), n = JSSTRING_LENGTH(str); n; s++, n--)
2704         h = (h >> (JS_HASH_BITS - 4)) ^ (h << 4) ^ *s;
2705     return h;
2708 intN
2709 js_CompareStrings(JSString *str1, JSString *str2)
2711     size_t l1, l2, n, i;
2712     const jschar *s1, *s2;
2713     intN cmp;
2715     l1 = JSSTRING_LENGTH(str1), l2 = JSSTRING_LENGTH(str2);
2716     s1 = JSSTRING_CHARS(str1),  s2 = JSSTRING_CHARS(str2);
2717     n = JS_MIN(l1, l2);
2718     for (i = 0; i < n; i++) {
2719         cmp = s1[i] - s2[i];
2720         if (cmp != 0)
2721             return cmp;
2722     }
2723     return (intN)(l1 - l2);
2726 size_t
2727 js_strlen(const jschar *s)
2729     const jschar *t;
2731     for (t = s; *t != 0; t++)
2732         continue;
2733     return (size_t)(t - s);
2736 jschar *
2737 js_strchr(const jschar *s, jschar c)
2739     while (*s != 0) {
2740         if (*s == c)
2741             return (jschar *)s;
2742         s++;
2743     }
2744     return NULL;
2747 jschar *
2748 js_strchr_limit(const jschar *s, jschar c, const jschar *limit)
2750     while (s < limit) {
2751         if (*s == c)
2752             return (jschar *)s;
2753         s++;
2754     }
2755     return NULL;
2758 const jschar *
2759 js_SkipWhiteSpace(const jschar *s)
2761     /* JS_ISSPACE is false on a null. */
2762     while (JS_ISSPACE(*s))
2763         s++;
2764     return s;
2767 #define INFLATE_STRING_BODY                                                   \
2768     for (i = 0; i < length; i++)                                              \
2769         chars[i] = (unsigned char) bytes[i];                                  \
2770     chars[i] = 0;
2772 void
2773 js_InflateStringToBuffer(jschar *chars, const char *bytes, size_t length)
2775     size_t i;
2777     INFLATE_STRING_BODY
2780 jschar *
2781 js_InflateString(JSContext *cx, const char *bytes, size_t length)
2783     jschar *chars;
2784     size_t i;
2786     chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
2787     if (!chars)
2788         return NULL;
2790     INFLATE_STRING_BODY
2792     return chars;
2795 /*
2796  * May be called with null cx by js_GetStringBytes, see below.
2797  */
2798 char *
2799 js_DeflateString(JSContext *cx, const jschar *chars, size_t length)
2801     size_t i, size;
2802     char *bytes;
2804     size = (length + 1) * sizeof(char);
2805     bytes = (char *) (cx ? JS_malloc(cx, size) : malloc(size));
2806     if (!bytes)
2807         return NULL;
2808     for (i = 0; i < length; i++)
2809         bytes[i] = (char) chars[i];
2810     bytes[i] = 0;
2811     return bytes;
2814 static JSHashTable *
2815 GetDeflatedStringCache(void)
2817     JSHashTable *cache;
2819     cache = deflated_string_cache;
2820     if (!cache) {
2821         cache = JS_NewHashTable(8, js_hash_string_pointer,
2822                                 JS_CompareValues, JS_CompareValues,
2823                                 NULL, NULL);
2824         deflated_string_cache = cache;
2825     }
2826     return cache;
2829 JSBool
2830 js_SetStringBytes(JSString *str, char *bytes, size_t length)
2832     JSHashTable *cache;
2833     JSBool ok;
2834     JSHashNumber hash;
2835     JSHashEntry **hep;
2837     JS_ACQUIRE_LOCK(deflated_string_cache_lock);
2839     cache = GetDeflatedStringCache();
2840     if (!cache) {
2841         ok = JS_FALSE;
2842     } else {
2843         hash = js_hash_string_pointer(str);
2844         hep = JS_HashTableRawLookup(cache, hash, str);
2845         JS_ASSERT(*hep == NULL);
2846         ok = JS_HashTableRawAdd(cache, hep, hash, str, bytes) != NULL;
2847 #ifdef DEBUG
2848         if (ok)
2849             deflated_string_cache_bytes += length;
2850 #endif
2851     }
2853     JS_RELEASE_LOCK(deflated_string_cache_lock);
2854     return ok;
2857 char *
2858 js_GetStringBytes(JSString *str)
2860     JSHashTable *cache;
2861     char *bytes;
2862     JSHashNumber hash;
2863     JSHashEntry *he, **hep;
2865     JS_ACQUIRE_LOCK(deflated_string_cache_lock);
2867     cache = GetDeflatedStringCache();
2868     if (!cache) {
2869         bytes = NULL;
2870     } else {
2871         hash = js_hash_string_pointer(str);
2872         hep = JS_HashTableRawLookup(cache, hash, str);
2873         he = *hep;
2874         if (he) {
2875             bytes = (char *) he->value;
2877             /* Try to catch failure to JS_ShutDown between runtime epochs. */
2878             JS_ASSERT((*bytes == '\0' && JSSTRING_LENGTH(str) == 0) ||
2879                       *bytes == (char) JSSTRING_CHARS(str)[0]);
2880         } else {
2881             bytes = js_DeflateString(NULL, JSSTRING_CHARS(str),
2882                                      JSSTRING_LENGTH(str));
2883             if (bytes) {
2884                 if (JS_HashTableRawAdd(cache, hep, hash, str, bytes)) {
2885 #ifdef DEBUG
2886                     deflated_string_cache_bytes += JSSTRING_LENGTH(str);
2887 #endif
2888                 } else {
2889                     free(bytes);
2890                     bytes = NULL;
2891                 }
2892             }
2893         }
2894     }
2896     JS_RELEASE_LOCK(deflated_string_cache_lock);
2897     return bytes;
2900 /*
2901  * From java.lang.Character.java:
2902  *
2903  * The character properties are currently encoded into 32 bits in the
2904  * following manner:
2905  *
2906  * 10 bits      signed offset used for converting case
2907  *  1 bit       if 1, adding the signed offset converts the character to
2908  *              lowercase
2909  *  1 bit       if 1, subtracting the signed offset converts the character to
2910  *              uppercase
2911  *  1 bit       if 1, character has a titlecase equivalent (possibly itself)
2912  *  3 bits      0  may not be part of an identifier
2913  *              1  ignorable control; may continue a Unicode identifier or JS
2914  *                 identifier
2915  *              2  may continue a JS identifier but not a Unicode identifier
2916  *                 (unused)
2917  *              3  may continue a Unicode identifier or JS identifier
2918  *              4  is a JS whitespace character
2919  *              5  may start or continue a JS identifier;
2920  *                 may continue but not start a Unicode identifier (_)
2921  *              6  may start or continue a JS identifier but not a Unicode
2922  *                 identifier ($)
2923  *              7  may start or continue a Unicode identifier or JS identifier
2924  *              Thus:
2925  *                 5, 6, 7 may start a JS identifier
2926  *                 1, 2, 3, 5, 6, 7 may continue a JS identifier
2927  *                 7 may start a Unicode identifier
2928  *                 1, 3, 5, 7 may continue a Unicode identifier
2929  *                 1 is ignorable within an identifier
2930  *                 4 is JS whitespace
2931  *  2 bits      0  this character has no numeric property
2932  *              1  adding the digit offset to the character code and then
2933  *                 masking with 0x1F will produce the desired numeric value
2934  *              2  this character has a "strange" numeric value
2935  *              3  a JS supradecimal digit: adding the digit offset to the
2936  *                 character code, then masking with 0x1F, then adding 10
2937  *                 will produce the desired numeric value
2938  *  5 bits      digit offset
2939  *  4 bits      reserved for future use
2940  *  5 bits      character type
2941  */
2943 /* The X table has 1024 entries for a total of 1024 bytes. */
2945 const uint8 js_X[] = {
2946   0,   1,   2,   3,   4,   5,   6,   7,  /*  0x0000 */
2947   8,   9,  10,  11,  12,  13,  14,  15,  /*  0x0200 */
2948  16,  17,  18,  19,  20,  21,  22,  23,  /*  0x0400 */
2949  24,  25,  26,  27,  28,  28,  28,  28,  /*  0x0600 */
2950  28,  28,  28,  28,  29,  30,  31,  32,  /*  0x0800 */
2951  33,  34,  35,  36,  37,  38,  39,  40,  /*  0x0A00 */
2952  41,  42,  43,  44,  45,  46,  28,  28,  /*  0x0C00 */
2953  47,  48,  49,  50,  51,  52,  53,  28,  /*  0x0E00 */
2954  28,  28,  54,  55,  56,  57,  58,  59,  /*  0x1000 */
2955  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x1200 */
2956  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x1400 */
2957  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x1600 */
2958  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x1800 */
2959  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x1A00 */
2960  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x1C00 */
2961  60,  60,  61,  62,  63,  64,  65,  66,  /*  0x1E00 */
2962  67,  68,  69,  70,  71,  72,  73,  74,  /*  0x2000 */
2963  75,  75,  75,  76,  77,  78,  28,  28,  /*  0x2200 */
2964  79,  80,  81,  82,  83,  83,  84,  85,  /*  0x2400 */
2965  86,  85,  28,  28,  87,  88,  89,  28,  /*  0x2600 */
2966  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x2800 */
2967  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x2A00 */
2968  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x2C00 */
2969  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x2E00 */
2970  90,  91,  92,  93,  94,  56,  95,  28,  /*  0x3000 */
2971  96,  97,  98,  99,  83, 100,  83, 101,  /*  0x3200 */
2972  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x3400 */
2973  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x3600 */
2974  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x3800 */
2975  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x3A00 */
2976  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x3C00 */
2977  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x3E00 */
2978  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x4000 */
2979  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x4200 */
2980  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x4400 */
2981  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x4600 */
2982  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x4800 */
2983  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x4A00 */
2984  28,  28,  28,  28,  28,  28,  28,  28,  /*  0x4C00 */
2985  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x4E00 */
2986  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x5000 */
2987  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x5200 */
2988  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x5400 */
2989  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x5600 */
2990  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x5800 */
2991  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x5A00 */
2992  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x5C00 */
2993  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x5E00 */
2994  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x6000 */
2995  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x6200 */
2996  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x6400 */
2997  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x6600 */
2998  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x6800 */
2999  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x6A00 */
3000  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x6C00 */
3001  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x6E00 */
3002  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x7000 */
3003  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x7200 */
3004  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x7400 */
3005  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x7600 */
3006  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x7800 */
3007  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x7A00 */
3008  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x7C00 */
3009  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x7E00 */
3010  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x8000 */
3011  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x8200 */
3012  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x8400 */
3013  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x8600 */
3014  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x8800 */
3015  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x8A00 */
3016  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x8C00 */
3017  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x8E00 */
3018  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x9000 */
3019  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x9200 */
3020  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x9400 */
3021  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x9600 */
3022  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x9800 */
3023  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x9A00 */
3024  56,  56,  56,  56,  56,  56,  56,  56,  /*  0x9C00 */
3025  56,  56,  56,  56,  56,  56, 102,  28,  /*  0x9E00 */
3026  28,  28,  28,  28,  28,  28,  28,  28,  /*  0xA000 */
3027  28,  28,  28,  28,  28,  28,  28,  28,  /*  0xA200 */
3028  28,  28,  28,  28,  28,  28,  28,  28,  /*  0xA400 */
3029  28,  28,  28,  28,  28,  28,  28,  28,  /*  0xA600 */
3030  28,  28,  28,  28,  28,  28,  28,  28,  /*  0xA800 */
3031  28,  28,  28,  28,  28,  28,  28,  28,  /*  0xAA00 */
3032  56,  56,  56,  56,  56,  56,  56,  56,  /*  0xAC00 */
3033  56,  56,  56,  56,  56,  56,  56,  56,  /*  0xAE00 */
3034  56,  56,  56,  56,  56,  56,  56,  56,  /*  0xB000 */
3035  56,  56,  56,  56,  56,  56,  56,  56,  /*  0xB200 */
3036  56,  56,  56,  56,  56,  56,  56,  56,  /*  0xB400 */
3037  56,  56,  56,  56,  56,  56,  56,  56,  /*  0xB600 */
3038  56,  56,  56,  56,  56,  56,  56,  56,  /*  0xB800 */
3039  56,  56,  56,  56,  56,  56,  56,  56,  /*  0xBA00 */
3040  56,  56,  56,  56,  56,  56,  56,  56,  /*  0xBC00 */
3041  56,  56,  56,  56,  56,  56,  56,  56,  /*  0xBE00 */
3042  56,  56,  56,  56,  56,  56,  56,  56,  /*  0xC000 */
3043  56,  56,  56,  56,  56,  56,  56,  56,  /*  0xC200 */
3044  56,  56,  56,  56,  56,  56,  56,  56,  /*  0xC400 */
3045  56,  56,  56,  56,  56,  56,  56,  56,  /*  0xC600 */
3046  56,  56,  56,  56,  56,  56,  56,  56,  /*  0xC800 */
3047  56,  56,  56,  56,  56,  56,  56,  56,  /*  0xCA00 */
3048  56,  56,  56,  56,  56,  56,  56,  56,  /*  0xCC00 */
3049  56,  56,  56,  56,  56,  56,  56,  56,  /*  0xCE00 */
3050  56,  56,  56,  56,  56,  56,  56,  56,  /*  0xD000 */
3051  56,  56,  56,  56,  56,  56,  56,  56,  /*  0xD200 */
3052  56,  56,  56,  56,  56,  56,  56,  56,  /*  0xD400 */
3053  56,  56,  56,  56,  56,  56, 103,  28,  /*  0xD600 */
3054 104, 104, 104, 104, 104, 104, 104, 104,  /*  0xD800 */
3055 104, 104, 104, 104, 104, 104, 104, 104,  /*  0xDA00 */
3056 104, 104, 104, 104, 104, 104, 104, 104,  /*  0xDC00 */
3057 104, 104, 104, 104, 104, 104, 104, 104,  /*  0xDE00 */
3058 105, 105, 105, 105, 105, 105, 105, 105,  /*  0xE000 */
3059 105, 105, 105, 105, 105, 105, 105, 105,  /*  0xE200 */
3060 105, 105, 105, 105, 105, 105, 105, 105,  /*  0xE400 */
3061 105, 105, 105, 105, 105, 105, 105, 105,  /*  0xE600 */
3062 105, 105, 105, 105, 105, 105, 105, 105,  /*  0xE800 */
3063 105, 105, 105, 105, 105, 105, 105, 105,  /*  0xEA00 */
3064 105, 105, 105, 105, 105, 105, 105, 105,  /*  0xEC00 */
3065 105, 105, 105, 105, 105, 105, 105, 105,  /*  0xEE00 */
3066 105, 105, 105, 105, 105, 105, 105, 105,  /*  0xF000 */
3067 105, 105, 105, 105, 105, 105, 105, 105,  /*  0xF200 */
3068 105, 105, 105, 105, 105, 105, 105, 105,  /*  0xF400 */
3069 105, 105, 105, 105, 105, 105, 105, 105,  /*  0xF600 */
3070 105, 105, 105, 105,  56,  56,  56,  56,  /*  0xF800 */
3071 106,  28,  28,  28, 107, 108, 109, 110,  /*  0xFA00 */
3072  56,  56,  56,  56, 111, 112, 113, 114,  /*  0xFC00 */
3073 115, 116,  56, 117, 118, 119, 120, 121   /*  0xFE00 */
3074 };
3076 /* The Y table has 7808 entries for a total of 7808 bytes. */
3078 const uint8 js_Y[] = {
3079   0,   0,   0,   0,   0,   0,   0,   0,  /*    0 */
3080   0,   1,   1,   1,   1,   1,   0,   0,  /*    0 */
3081   0,   0,   0,   0,   0,   0,   0,   0,  /*    0 */
3082   0,   0,   0,   0,   0,   0,   0,   0,  /*    0 */
3083   2,   3,   3,   3,   4,   3,   3,   3,  /*    0 */
3084   5,   6,   3,   7,   3,   8,   3,   3,  /*    0 */
3085   9,   9,   9,   9,   9,   9,   9,   9,  /*    0 */
3086   9,   9,   3,   3,   7,   7,   7,   3,  /*    0 */
3087   3,  10,  10,  10,  10,  10,  10,  10,  /*    1 */
3088  10,  10,  10,  10,  10,  10,  10,  10,  /*    1 */
3089  10,  10,  10,  10,  10,  10,  10,  10,  /*    1 */
3090  10,  10,  10,   5,   3,   6,  11,  12,  /*    1 */
3091  11,  13,  13,  13,  13,  13,  13,  13,  /*    1 */
3092  13,  13,  13,  13,  13,  13,  13,  13,  /*    1 */
3093  13,  13,  13,  13,  13,  13,  13,  13,  /*    1 */
3094  13,  13,  13,   5,   7,   6,   7,   0,  /*    1 */
3095   0,   0,   0,   0,   0,   0,   0,   0,  /*    2 */
3096   0,   0,   0,   0,   0,   0,   0,   0,  /*    2 */
3097   0,   0,   0,   0,   0,   0,   0,   0,  /*    2 */
3098   0,   0,   0,   0,   0,   0,   0,   0,  /*    2 */
3099   2,   3,   4,   4,   4,   4,  15,  15,  /*    2 */
3100  11,  15,  16,   5,   7,   8,  15,  11,  /*    2 */
3101  15,   7,  17,  17,  11,  16,  15,   3,  /*    2 */
3102  11,  18,  16,   6,  19,  19,  19,   3,  /*    2 */
3103  20,  20,  20,  20,  20,  20,  20,  20,  /*    3 */
3104  20,  20,  20,  20,  20,  20,  20,  20,  /*    3 */
3105  20,  20,  20,  20,  20,  20,  20,   7,  /*    3 */
3106  20,  20,  20,  20,  20,  20,  20,  16,  /*    3 */
3107  21,  21,  21,  21,  21,  21,  21,  21,  /*    3 */
3108  21,  21,  21,  21,  21,  21,  21,  21,  /*    3 */
3109  21,  21,  21,  21,  21,  21,  21,   7,  /*    3 */
3110  21,  21,  21,  21,  21,  21,  21,  22,  /*    3 */
3111  23,  24,  23,  24,  23,  24,  23,  24,  /*    4 */
3112  23,  24,  23,  24,  23,  24,  23,  24,  /*    4 */
3113  23,  24,  23,  24,  23,  24,  23,  24,  /*    4 */
3114  23,  24,  23,  24,  23,  24,  23,  24,  /*    4 */
3115  23,  24,  23,  24,  23,  24,  23,  24,  /*    4 */
3116  23,  24,  23,  24,  23,  24,  23,  24,  /*    4 */
3117  25,  26,  23,  24,  23,  24,  23,  24,  /*    4 */
3118  16,  23,  24,  23,  24,  23,  24,  23,  /*    4 */
3119  24,  23,  24,  23,  24,  23,  24,  23,  /*    5 */
3120  24,  16,  23,  24,  23,  24,  23,  24,  /*    5 */
3121  23,  24,  23,  24,  23,  24,  23,  24,  /*    5 */
3122  23,  24,  23,  24,  23,  24,  23,  24,  /*    5 */
3123  23,  24,  23,  24,  23,  24,  23,  24,  /*    5 */
3124  23,  24,  23,  24,  23,  24,  23,  24,  /*    5 */
3125  23,  24,  23,  24,  23,  24,  23,  24,  /*    5 */
3126  27,  23,  24,  23,  24,  23,  24,  28,  /*    5 */
3127  16,  29,  23,  24,  23,  24,  30,  23,  /*    6 */
3128  24,  31,  31,  23,  24,  16,  32,  32,  /*    6 */
3129  33,  23,  24,  31,  34,  16,  35,  36,  /*    6 */
3130  23,  24,  16,  16,  35,  37,  16,  38,  /*    6 */
3131  23,  24,  23,  24,  23,  24,  38,  23,  /*    6 */
3132  24,  39,  40,  16,  23,  24,  39,  23,  /*    6 */
3133  24,  41,  41,  23,  24,  23,  24,  42,  /*    6 */
3134  23,  24,  16,  40,  23,  24,  40,  40,  /*    6 */
3135  40,  40,  40,  40,  43,  44,  45,  43,  /*    7 */
3136  44,  45,  43,  44,  45,  23,  24,  23,  /*    7 */
3137  24,  23,  24,  23,  24,  23,  24,  23,  /*    7 */
3138  24,  23,  24,  23,  24,  16,  23,  24,  /*    7 */
3139  23,  24,  23,  24,  23,  24,  23,  24,  /*    7 */
3140  23,  24,  23,  24,  23,  24,  23,  24,  /*    7 */
3141  16,  43,  44,  45,  23,  24,  46,  46,  /*    7 */
3142  46,  46,  23,  24,  23,  24,  23,  24,  /*    7 */
3143  23,  24,  23,  24,  23,  24,  23,  24,  /*    8 */
3144  23,  24,  23,  24,  23,  24,  23,  24,  /*    8 */
3145  23,  24,  23,  24,  23,  24,  23,  24,  /*    8 */
3146  46,  46,  46,  46,  46,  46,  46,  46,  /*    8 */
3147  46,  46,  46,  46,  46,  46,  46,  46,  /*    8 */
3148  46,  46,  46,  46,  46,  46,  46,  46,  /*    8 */
3149  46,  46,  46,  46,  46,  46,  46,  46,  /*    8 */
3150  46,  46,  46,  46,  46,  46,  46,  46,  /*    8 */
3151  46,  46,  46,  46,  46,  46,  46,  46,  /*    9 */
3152  46,  46,  46,  46,  46,  46,  46,  46,  /*    9 */
3153  16,  16,  16,  47,  48,  16,  49,  49,  /*    9 */
3154  50,  50,  16,  51,  16,  16,  16,  16,  /*    9 */
3155  49,  16,  16,  52,  16,  16,  16,  16,  /*    9 */
3156  53,  54,  16,  16,  16,  16,  16,  54,  /*    9 */
3157  16,  16,  55,  16,  16,  16,  16,  16,  /*    9 */
3158  16,  16,  16,  16,  16,  16,  16,  16,  /*    9 */
3159  16,  16,  16,  56,  16,  16,  16,  16,  /*   10 */
3160  56,  16,  57,  57,  16,  16,  16,  16,  /*   10 */
3161  16,  16,  58,  16,  16,  16,  16,  16,  /*   10 */
3162  16,  16,  16,  16,  16,  16,  16,  16,  /*   10 */
3163  16,  16,  16,  16,  16,  16,  16,  16,  /*   10 */
3164  16,  46,  46,  46,  46,  46,  46,  46,  /*   10 */
3165  59,  59,  59,  59,  59,  59,  59,  59,  /*   10 */
3166  59,  11,  11,  59,  59,  59,  59,  59,  /*   10 */
3167  59,  59,  11,  11,  11,  11,  11,  11,  /*   11 */
3168  11,  11,  11,  11,  11,  11,  11,  11,  /*   11 */
3169  59,  59,  11,  11,  11,  11,  11,  11,  /*   11 */
3170  11,  11,  11,  11,  11,  11,  11,  46,  /*   11 */
3171  59,  59,  59,  59,  59,  11,  11,  11,  /*   11 */
3172  11,  11,  46,  46,  46,  46,  46,  46,  /*   11 */
3173  46,  46,  46,  46,  46,  46,  46,  46,  /*   11 */
3174  46,  46,  46,  46,  46,  46,  46,  46,  /*   11 */
3175  60,  60,  60,  60,  60,  60,  60,  60,  /*   12 */
3176  60,  60,  60,  60,  60,  60,  60,  60,  /*   12 */
3177  60,  60,  60,  60,  60,  60,  60,  60,  /*   12 */
3178  60,  60,  60,  60,  60,  60,  60,  60,  /*   12 */
3179  60,  60,  60,  60,  60,  60,  60,  60,  /*   12 */
3180  60,  60,  60,  60,  60,  60,  60,  60,  /*   12 */
3181  60,  60,  60,  60,  60,  60,  60,  60,  /*   12 */
3182  60,  60,  60,  60,  60,  60,  60,  60,  /*   12 */
3183  60,  60,  60,  60,  60,  60,  46,  46,  /*   13 */
3184  46,  46,  46,  46,  46,  46,  46,  46,  /*   13 */
3185  46,  46,  46,  46,  46,  46,  46,  46,  /*   13 */
3186  46,  46,  46,  46,  46,  46,  46,  46,  /*   13 */
3187  60,  60,  46,  46,  46,  46,  46,  46,  /*   13 */
3188  46,  46,  46,  46,  46,  46,  46,  46,  /*   13 */
3189  46,  46,  46,  46,   3,   3,  46,  46,  /*   13 */
3190  46,  46,  59,  46,  46,  46,   3,  46,  /*   13 */
3191  46,  46,  46,  46,  11,  11,  61,   3,  /*   14 */
3192  62,  62,  62,  46,  63,  46,  64,  64,  /*   14 */
3193  16,  20,  20,  20,  20,  20,  20,  20,  /*   14 */
3194  20,  20,  20,  20,  20,  20,  20,  20,  /*   14 */
3195  20,  20,  46,  20,  20,  20,  20,  20,  /*   14 */
3196  20,  20,  20,  20,  65,  66,  66,  66,  /*   14 */
3197  16,  21,  21,  21,  21,  21,  21,  21,  /*   14 */
3198  21,  21,  21,  21,  21,  21,  21,  21,  /*   14 */
3199  21,  21,  16,  21,  21,  21,  21,  21,  /*   15 */
3200  21,  21,  21,  21,  67,  68,  68,  46,  /*   15 */
3201  69,  70,  38,  38,  38,  71,  72,  46,  /*   15 */
3202  46,  46,  38,  46,  38,  46,  38,  46,  /*   15 */
3203  38,  46,  23,  24,  23,  24,  23,  24,  /*   15 */
3204  23,  24,  23,  24,  23,  24,  23,  24,  /*   15 */
3205  73,  74,  16,  40,  46,  46,  46,  46,  /*   15 */
3206  46,  46,  46,  46,  46,  46,  46,  46,  /*   15 */
3207  46,  75,  75,  75,  75,  75,  75,  75,  /*   16 */
3208  75,  75,  75,  75,  75,  46,  75,  75,  /*   16 */
3209  20,  20,  20,  20,  20,  20,  20,  20,  /*   16 */
3210  20,  20,  20,  20,  20,  20,  20,  20,  /*   16 */
3211  20,  20,  20,  20,  20,  20,  20,  20,  /*   16 */
3212  20,  20,  20,  20,  20,  20,  20,  20,  /*   16 */
3213  21,  21,  21,  21,  21,  21,  21,  21,  /*   16 */
3214  21,  21,  21,  21,  21,  21,  21,  21,  /*   16 */
3215  21,  21,  21,  21,  21,  21,  21,  21,  /*   17 */
3216  21,  21,  21,  21,  21,  21,  21,  21,  /*   17 */
3217  46,  74,  74,  74,  74,  74,  74,  74,  /*   17 */
3218  74,  74,  74,  74,  74,  46,  74,  74,  /*   17 */
3219  23,  24,  23,  24,  23,  24,  23,  24,  /*   17 */
3220  23,  24,  23,  24,  23,  24,  23,  24,  /*   17 */
3221  23,  24,  23,  24,  23,  24,  23,  24,  /*   17 */
3222  23,  24,  23,  24,  23,  24,  23,  24,  /*   17 */
3223  23,  24,  15,  60,  60,  60,  60,  46,  /*   18 */
3224  46,  46,  46,  46,  46,  46,  46,  46,  /*   18 */
3225  23,  24,  23,  24,  23,  24,  23,  24,  /*   18 */
3226  23,  24,  23,  24,  23,  24,  23,  24,  /*   18 */
3227  23,  24,  23,  24,  23,  24,  23,  24,  /*   18 */
3228  23,  24,  23,  24,  23,  24,  23,  24,  /*   18 */
3229  23,  24,  23,  24,  23,  24,  23,  24,  /*   18 */
3230  23,  24,  23,  24,  23,  24,  23,  24,  /*   18 */
3231  40,  23,  24,  23,  24,  46,  46,  23,  /*   19 */
3232  24,  46,  46,  23,  24,  46,  46,  46,  /*   19 */
3233  23,  24,  23,  24,  23,  24,  23,  24,  /*   19 */
3234  23,  24,  23,  24,  23,  24,  23,  24,  /*   19 */
3235  23,  24,  23,  24,  23,  24,  23,  24,  /*   19 */
3236  23,  24,  23,  24,  46,  46,  23,  24,  /*   19 */
3237  23,  24,  23,  24,  23,  24,  46,  46,  /*   19 */
3238  23,  24,  46,  46,  46,  46,  46,  46,  /*   19 */
3239  46,  46,  46,  46,  46,  46,  46,  46,  /*   20 */
3240  46,  46,  46,  46,  46,  46,  46,  46,  /*   20 */
3241  46,  46,  46,  46,  46,  46,  46,  46,  /*   20 */
3242  46,  46,  46,  46,  46,  46,  46,  46,  /*   20 */
3243  46,  46,  46,  46,  46,  46,  46,  46,  /*   20 */
3244  46,  46,  46,  46,  46,  46,  46,  46,  /*   20 */
3245  46,  76,  76,  76,  76,  76,  76,  76,  /*   20 */
3246  76,  76,  76,  76,  76,  76,  76,  76,  /*   20 */
3247  76,  76,  76,  76,  76,  76,  76,  76,  /*   21 */
3248  76,  76,  76,  76,  76,  76,  76,  76,  /*   21 */
3249  76,  76,  76,  76,  76,  76,  76,  46,  /*   21 */
3250  46,  59,   3,   3,   3,   3,   3,   3,  /*   21 */
3251  46,  77,  77,  77,  77,  77,  77,  77,  /*   21 */
3252  77,  77,  77,  77,  77,  77,  77,  77,  /*   21 */
3253  77,  77,  77,  77,  77,  77,  77,  77,  /*   21 */
3254  77,  77,  77,  77,  77,  77,  77,  77,  /*   21 */
3255  77,  77,  77,  77,  77,  77,  77,  16,  /*   22 */
3256  46,   3,  46,  46,  46,  46,  46,  46,  /*   22 */
3257  46,  60,  60,  60,  60,  60,  60,  60,  /*   22 */
3258  60,  60,  60,  60,  60,  60,  60,  60,  /*   22 */
3259  60,  60,  46,  60,  60,  60,  60,  60,  /*   22 */
3260  60,  60,  60,  60,  60,  60,  60,  60,  /*   22 */
3261  60,  60,  60,  60,  60,  60,  60,  60,  /*   22 */
3262  60,  60,  46,  60,  60,  60,   3,  60,  /*   22 */
3263   3,  60,  60,   3,  60,  46,  46,  46,  /*   23 */
3264  46,  46,  46,  46,  46,  46,  46,  46,  /*   23 */
3265  40,  40,  40,  40,  40,  40,  40,  40,  /*   23 */
3266  40,  40,  40,  40,  40,  40,  40,  40,  /*   23 */
3267  40,  40,  40,  40,  40,  40,  40,  40,  /*   23 */
3268  40,  40,  40,  46,  46,  46,  46,  46,  /*   23 */
3269  40,  40,  40,   3,   3,  46,  46,  46,  /*   23 */
3270  46,  46,  46,  46,  46,  46,  46,  46,  /*   23 */
3271  46,  46,  46,  46,  46,  46,  46,  46,  /*   24 */
3272  46,  46,  46,  46,   3,  46,  46,  46,  /*   24 */
3273  46,  46,  46,  46,  46,  46,  46,  46,  /*   24 */
3274  46,  46,  46,   3,  46,  46,  46,   3,  /*   24 */
3275  46,  40,  40,  40,  40,  40,  40,  40,  /*   24 */
3276  40,  40,  40,  40,  40,  40,  40,  40,  /*   24 */
3277  40,  40,  40,  40,  40,  40,  40,  40,  /*   24 */
3278  40,  40,  40,  46,  46,  46,  46,  46,  /*   24 */
3279  59,  40,  40,  40,  40,  40,  40,  40,  /*   25 */
3280  40,  40,  40,  60,  60,  60,  60,  60,  /*   25 */
3281  60,  60,  60,  46,  46,  46,  46,  46,  /*   25 */
3282  46,  46,  46,  46,  46,  46,  46,  46,  /*   25 */
3283  78,  78,  78,  78,  78,  78,  78,  78,  /*   25 */
3284  78,  78,   3,   3,   3,   3,  46,  46,  /*   25 */
3285  60,  40,  40,  40,  40,  40,  40,  40,  /*   25 */
3286  40,  40,  40,  40,  40,  40,  40,  40,  /*   25 */
3287  40,  40,  40,  40,  40,  40,  40,  40,  /*   26 */
3288  40,  40,  40,  40,  40,  40,  40,  40,  /*   26 */
3289  40,  40,  40,  40,  40,  40,  40,  40,  /*   26 */
3290  40,  40,  40,  40,  40,  40,  40,  40,  /*   26 */
3291  40,  40,  40,  40,  40,  40,  40,  40,  /*   26 */
3292  40,  40,  40,  40,  40,  40,  40,  40,  /*   26 */
3293  40,  40,  40,  40,  40,  40,  40,  40,  /*   26 */
3294  46,  46,  40,  40,  40,  40,  40,  46,  /*   26 */
3295  40,  40,  40,  40,  40,  40,  40,  40,  /*   27 */
3296  40,  40,  40,  40,  40,  40,  40,  46,  /*   27 */
3297  40,  40,  40,  40,   3,  40,  60,  60,  /*   27 */
3298  60,  60,  60,  60,  60,  79,  79,  60,  /*   27 */
3299  60,  60,  60,  60,  60,  59,  59,  60,  /*   27 */
3300  60,  15,  60,  60,  60,  60,  46,  46,  /*   27 */
3301   9,   9,   9,   9,   9,   9,   9,   9,  /*   27 */
3302   9,   9,  46,  46,  46,  46,  46,  46,  /*   27 */
3303  46,  46,  46,  46,  46,  46,  46,  46,  /*   28 */
3304  46,  46,  46,  46,  46,  46,  46,  46,  /*   28 */
3305  46,  46,  46,  46,  46,  46,  46,  46,  /*   28 */
3306  46,  46,  46,  46,  46,  46,  46,  46,  /*   28 */
3307  46,  46,  46,  46,  46,  46,  46,  46,  /*   28 */
3308  46,  46,  46,  46,  46,  46,  46,  46,  /*   28 */
3309  46,  46,  46,  46,  46,  46,  46,  46,  /*   28 */
3310  46,  46,  46,  46,  46,  46,  46,  46,  /*   28 */
3311  46,  60,  60,  80,  46,  40,  40,  40,  /*   29 */
3312  40,  40,  40,  40,  40,  40,  40,  40,  /*   29 */
3313  40,  40,  40,  40,  40,  40,  40,  40,  /*   29 */
3314  40,  40,  40,  40,  40,  40,  40,  40,  /*   29 */
3315  40,  40,  40,  40,  40,  40,  40,  40,  /*   29 */
3316  40,  40,  40,  40,  40,  40,  40,  40,  /*   29 */
3317  40,  40,  40,  40,  40,  40,  40,  40,  /*   29 */
3318  40,  40,  46,  46,  60,  40,  80,  80,  /*   29 */
3319  80,  60,  60,  60,  60,  60,  60,  60,  /*   30 */
3320  60,  80,  80,  80,  80,  60,  46,  46,  /*   30 */
3321  15,  60,  60,  60,  60,  46,  46,  46,  /*   30 */
3322  40,  40,  40,  40,  40,  40,  40,  40,  /*   30 */
3323  40,  40,  60,  60,   3,   3,  81,  81,  /*   30 */
3324  81,  81,  81,  81,  81,  81,  81,  81,  /*   30 */
3325   3,  46,  46,  46,  46,  46,  46,  46,  /*   30 */
3326  46,  46,  46,  46,  46,  46,  46,  46,  /*   30 */
3327  46,  60,  80,  80,  46,  40,  40,  40,  /*   31 */
3328  40,  40,  40,  40,  40,  46,  46,  40,  /*   31 */
3329  40,  46,  46,  40,  40,  40,  40,  40,  /*   31 */
3330  40,  40,  40,  40,  40,  40,  40,  40,  /*   31 */
3331  40,  40,  40,  40,  40,  40,  40,  40,  /*   31 */
3332  40,  46,  40,  40,  40,  40,  40,  40,  /*   31 */
3333  40,  46,  40,  46,  46,  46,  40,  40,  /*   31 */
3334  40,  40,  46,  46,  60,  46,  80,  80,  /*   31 */
3335  80,  60,  60,  60,  60,  46,  46,  80,  /*   32 */
3336  80,  46,  46,  80,  80,  60,  46,  46,  /*   32 */
3337  46,  46,  46,  46,  46,  46,  46,  80,  /*   32 */
3338  46,  46,  46,  46,  40,  40,  46,  40,  /*   32 */
3339  40,  40,  60,  60,  46,  46,  81,  81,  /*   32 */
3340  81,  81,  81,  81,  81,  81,  81,  81,  /*   32 */
3341  40,  40,   4,   4,  82,  82,  82,  82,  /*   32 */
3342  19,  83,  15,  46,  46,  46,  46,  46,  /*   32 */
3343  46,  46,  60,  46,  46,  40,  40,  40,  /*   33 */
3344  40,  40,  40,  46,  46,  46,  46,  40,  /*   33 */
3345  40,  46,  46,  40,  40,  40,  40,  40,  /*   33 */
3346  40,  40,  40,  40,  40,  40,  40,  40,  /*   33 */
3347  40,  40,  40,  40,  40,  40,  40,  40,  /*   33 */
3348  40,  46,  40,  40,  40,  40,  40,  40,  /*   33 */
3349  40,  46,  40,  40,  46,  40,  40,  46,  /*   33 */
3350  40,  40,  46,  46,  60,  46,  80,  80,  /*   33 */
3351  80,  60,  60,  46,  46,  46,  46,  60,  /*   34 */
3352  60,  46,  46,  60,  60,  60,  46,  46,  /*   34 */
3353  46,  46,  46,  46,  46,  46,  46,  46,  /*   34 */
3354  46,  40,  40,  40,  40,  46,  40,  46,  /*   34 */
3355  46,  46,  46,  46,  46,  46,  81,  81,  /*   34 */
3356  81,  81,  81,  81,  81,  81,  81,  81,  /*   34 */
3357  60,  60,  40,  40,  40,  46,  46,  46,  /*   34 */
3358  46,  46,  46,  46,  46,  46,  46,  46,  /*   34 */
3359  46,  60,  60,  80,  46,  40,  40,  40,  /*   35 */
3360  40,  40,  40,  40,  46,  40,  46,  40,  /*   35 */
3361  40,  40,  46,  40,  40,  40,  40,  40,  /*   35 */
3362  40,  40,  40,  40,  40,  40,  40,  40,  /*   35 */
3363  40,  40,  40,  40,  40,  40,  40,  40,  /*   35 */
3364  40,  46,  40,  40,  40,  40,  40,  40,  /*   35 */
3365  40,  46,  40,  40,  46,  40,  40,  40,  /*   35 */
3366  40,  40,  46,  46,  60,  40,  80,  80,  /*   35 */
3367  80,  60,  60,  60,  60,  60,  46,  60,  /*   36 */
3368  60,  80,  46,  80,  80,  60,  46,  46,  /*   36 */
3369  15,  46,  46,  46,  46,  46,  46,  46,  /*   36 */
3370  46,  46,  46,  46,  46,  46,  46,  46,  /*   36 */
3371  40,  46,  46,  46,  46,  46,  81,  81,  /*   36 */
3372  81,  81,  81,  81,  81,  81,  81,  81,  /*   36 */
3373  46,  46,  46,  46,  46,  46,  46,  46,  /*   36 */
3374  46,  46,  46,  46,  46,  46,  46,  46,  /*   36 */
3375  46,  60,  80,  80,  46,  40,  40,  40,  /*   37 */
3376  40,  40,  40,  40,  40,  46,  46,  40,  /*   37 */
3377  40,  46,  46,  40,  40,  40,  40,  40,  /*   37 */
3378  40,  40,  40,  40,  40,  40,  40,  40,  /*   37 */
3379  40,  40,  40,  40,  40,  40,  40,  40,  /*   37 */
3380  40,  46,  40,  40,  40,  40,  40,  40,  /*   37 */
3381  40,  46,  40,  40,  46,  46,  40,  40,  /*   37 */
3382  40,  40,  46,  46,  60,  40,  80,  60,  /*   37 */
3383  80,  60,  60,  60,  46,  46,  46,  80,  /*   38 */
3384  80,  46,  46,  80,  80,  60,  46,  46,  /*   38 */
3385  46,  46,  46,  46,  46,  46,  60,  80,  /*   38 */
3386  46,  46,  46,  46,  40,  40,  46,  40,  /*   38 */
3387  40,  40,  46,  46,  46,  46,  81,  81,  /*   38 */
3388  81,  81,  81,  81,  81,  81,  81,  81,  /*   38 */
3389  15,  46,  46,  46,  46,  46,  46,  46,  /*   38 */
3390  46,  46,  46,  46,  46,  46,  46,  46,  /*   38 */
3391  46,  46,  60,  80,  46,  40,  40,  40,  /*   39 */
3392  40,  40,  40,  46,  46,  46,  40,  40,  /*   39 */
3393  40,  46,  40,  40,  40,  40,  46,  46,  /*   39 */
3394  46,  40,  40,  46,  40,  46,  40,  40,  /*   39 */
3395  46,  46,  46,  40,  40,  46,  46,  46,  /*   39 */
3396  40,  40,  40,  46,  46,  46,  40,  40,  /*   39 */
3397  40,  40,  40,  40,  40,  40,  46,  40,  /*   39 */
3398  40,  40,  46,  46,  46,  46,  80,  80,  /*   39 */
3399  60,  80,  80,  46,  46,  46,  80,  80,  /*   40 */
3400  80,  46,  80,  80,  80,  60,  46,  46,  /*   40 */
3401  46,  46,  46,  46,  46,  46,  46,  80,  /*   40 */
3402  46,  46,  46,  46,  46,  46,  46,  46,  /*   40 */
3403  46,  46,  46,  46,  46,  46,  46,  81,  /*   40 */
3404  81,  81,  81,  81,  81,  81,  81,  81,  /*   40 */
3405  84,  19,  19,  46,  46,  46,  46,  46,  /*   40 */
3406  46,  46,  46,  46,  46,  46,  46,  46,  /*   40 */
3407  46,  80,  80,  80,  46,  40,  40,  40,  /*   41 */
3408  40,  40,  40,  40,  40,  46,  40,  40,  /*   41 */
3409  40,  46,  40,  40,  40,  40,  40,  40,  /*   41 */
3410  40,  40,  40,  40,  40,  40,  40,  40,  /*   41 */
3411  40,  40,  40,  40,  40,  40,  40,  40,  /*   41 */
3412  40,  46,  40,  40,  40,  40,  40,  40,  /*   41 */
3413  40,  40,  40,  40,  46,  40,  40,  40,  /*   41 */
3414  40,  40,  46,  46,  46,  46,  60,  60,  /*   41 */
3415  60,  80,  80,  80,  80,  46,  60,  60,  /*   42 */
3416  60,  46,  60,  60,  60,  60,  46,  46,  /*   42 */
3417  46,  46,  46,  46,  46,  60,  60,  46,  /*   42 */
3418  46,  46,  46,  46,  46,  46,  46,  46,  /*   42 */
3419  40,  40,  46,  46,  46,  46,  81,  81,  /*   42 */
3420  81,  81,  81,  81,  81,  81,  81,  81,  /*   42 */
3421  46,  46,  46,  46,  46,  46,  46,  46,  /*   42 */
3422  46,  46,  46,  46,  46,  46,  46,  46,  /*   42 */
3423  46,  46,  80,  80,  46,  40,  40,  40,  /*   43 */
3424  40,  40,  40,  40,  40,  46,  40,  40,  /*   43 */
3425  40,  46,  40,  40,  40,  40,  40,  40,  /*   43 */
3426  40,  40,  40,  40,  40,  40,  40,  40,  /*   43 */
3427  40,  40,  40,  40,  40,  40,  40,  40,  /*   43 */
3428  40,  46,  40,  40,  40,  40,  40,  40,  /*   43 */
3429  40,  40,  40,  40,  46,  40,  40,  40,  /*   43 */
3430  40,  40,  46,  46,  46,  46,  80,  60,  /*   43 */
3431  80,  80,  80,  80,  80,  46,  60,  80,  /*   44 */
3432  80,  46,  80,  80,  60,  60,  46,  46,  /*   44 */
3433  46,  46,  46,  46,  46,  80,  80,  46,  /*   44 */
3434  46,  46,  46,  46,  46,  46,  40,  46,  /*   44 */
3435  40,  40,  46,  46,  46,  46,  81,  81,  /*   44 */
3436  81,  81,  81,  81,  81,  81,  81,  81,  /*   44 */
3437  46,  46,  46,  46,  46,  46,  46,  46,  /*   44 */
3438  46,  46,  46,  46,  46,  46,  46,  46,  /*   44 */
3439  46,  46,  80,  80,  46,  40,  40,  40,  /*   45 */
3440  40,  40,  40,  40,  40,  46,  40,  40,  /*   45 */
3441  40,  46,  40,  40,  40,  40,  40,  40,  /*   45 */
3442  40,  40,  40,  40,  40,  40,  40,  40,  /*   45 */
3443  40,  40,  40,  40,  40,  40,  40,  40,  /*   45 */
3444  40,  46,  40,  40,  40,  40,  40,  40,  /*   45 */
3445  40,  40,  40,  40,  40,  40,  40,  40,  /*   45 */
3446  40,  40,  46,  46,  46,  46,  80,  80,  /*   45 */
3447  80,  60,  60,  60,  46,  46,  80,  80,  /*   46 */
3448  80,  46,  80,  80,  80,  60,  46,  46,  /*   46 */
3449  46,  46,  46,  46,  46,  46,  46,  80,  /*   46 */
3450  46,  46,  46,  46,  46,  46,  46,  46,  /*   46 */
3451  40,  40,  46,  46,  46,  46,  81,  81,  /*   46 */
3452  81,  81,  81,  81,  81,  81,  81,  81,  /*   46 */
3453  46,  46,  46,  46,  46,  46,  46,  46,  /*   46 */
3454  46,  46,  46,  46,  46,  46,  46,  46,  /*   46 */
3455  46,  40,  40,  40,  40,  40,  40,  40,  /*   47 */
3456  40,  40,  40,  40,  40,  40,  40,  40,  /*   47 */
3457  40,  40,  40,  40,  40,  40,  40,  40,  /*   47 */
3458  40,  40,  40,  40,  40,  40,  40,  40,  /*   47 */
3459  40,  40,  40,  40,  40,  40,  40,  40,  /*   47 */
3460  40,  40,  40,  40,  40,  40,  40,   3,  /*   47 */
3461  40,  60,  40,  40,  60,  60,  60,  60,  /*   47 */
3462  60,  60,  60,  46,  46,  46,  46,   4,  /*   47 */
3463  40,  40,  40,  40,  40,  40,  59,  60,  /*   48 */
3464  60,  60,  60,  60,  60,  60,  60,  15,  /*   48 */
3465   9,   9,   9,   9,   9,   9,   9,   9,  /*   48 */
3466   9,   9,   3,   3,  46,  46,  46,  46,  /*   48 */
3467  46,  46,  46,  46,  46,  46,  46,  46,  /*   48 */
3468  46,  46,  46,  46,  46,  46,  46,  46,  /*   48 */
3469  46,  46,  46,  46,  46,  46,  46,  46,  /*   48 */
3470  46,  46,  46,  46,  46,  46,  46,  46,  /*   48 */
3471  46,  40,  40,  46,  40,  46,  46,  40,  /*   49 */
3472  40,  46,  40,  46,  46,  40,  46,  46,  /*   49 */
3473  46,  46,  46,  46,  40,  40,  40,  40,  /*   49 */
3474  46,  40,  40,  40,  40,  40,  40,  40,  /*   49 */
3475  46,  40,  40,  40,  46,  40,  46,  40,  /*   49 */
3476  46,  46,  40,  40,  46,  40,  40,   3,  /*   49 */
3477  40,  60,  40,  40,  60,  60,  60,  60,  /*   49 */
3478  60,  60,  46,  60,  60,  40,  46,  46,  /*   49 */
3479  40,  40,  40,  40,  40,  46,  59,  46,  /*   50 */
3480  60,  60,  60,  60,  60,  60,  46,  46,  /*   50 */
3481   9,   9,   9,   9,   9,   9,   9,   9,  /*   50 */
3482   9,   9,  46,  46,  40,  40,  46,  46,  /*   50 */
3483  46,  46,  46,  46,  46,  46,  46,  46,  /*   50 */
3484  46,  46,  46,  46,  46,  46,  46,  46,  /*   50 */
3485  46,  46,  46,  46,  46,  46,  46,  46,  /*   50 */
3486  46,  46,  46,  46,  46,  46,  46,  46,  /*   50 */
3487  15,  15,  15,  15,   3,   3,   3,   3,  /*   51 */
3488   3,   3,   3,   3,   3,   3,   3,   3,  /*   51 */
3489   3,   3,   3,  15,  15,  15,  15,  15,  /*   51 */
3490  60,  60,  15,  15,  15,  15,  15,  15,  /*   51 */
3491  78,  78,  78,  78,  78,  78,  78,  78,  /*   51 */
3492  78,  78,  85,  85,  85,  85,  85,  85,  /*   51 */
3493  85,  85,  85,  85,  15,  60,  15,  60,  /*   51 */
3494  15,  60,   5,   6,   5,   6,  80,  80,  /*   51 */
3495  40,  40,  40,  40,  40,  40,  40,  40,  /*   52 */
3496  46,  40,  40,  40,  40,  40,  40,  40,  /*   52 */
3497  40,  40,  40,  40,  40,  40,  40,  40,  /*   52 */
3498  40,  40,  40,  40,  40,  40,  40,  40,  /*   52 */
3499  40,  40,  40,  40,  40,  40,  40,  40,  /*   52 */
3500  40,  40,  46,  46,  46,  46,  46,  46,  /*   52 */
3501  46,  60,  60,  60,  60,  60,  60,  60,  /*   52 */
3502  60,  60,  60,  60,  60,  60,  60,  80,  /*   52 */
3503  60,  60,  60,  60,  60,   3,  60,  60,  /*   53 */
3504  60,  60,  60,  60,  46,  46,  46,  46,  /*   53 */
3505  60,  60,  60,  60,  60,  60,  46,  60,  /*   53 */
3506  46,  60,  60,  60,  60,  60,  60,  60,  /*   53 */
3507  60,  60,  60,  60,  60,  60,  60,  60,  /*   53 */
3508  60,  60,  60,  60,  60,  60,  46,  46,  /*   53 */
3509  46,  60,  60,  60,  60,  60,  60,  60,  /*   53 */
3510  46,  60,  46,  46,  46,  46,  46,  46,  /*   53 */
3511  46,  46,  46,  46,  46,  46,  46,  46,  /*   54 */
3512  46,  46,  46,  46,  46,  46,  46,  46,  /*   54 */
3513  46,  46,  46,  46,  46,  46,  46,  46,  /*   54 */
3514  46,  46,  46,  46,  46,  46,  46,  46,  /*   54 */
3515  76,  76,  76,  76,  76,  76,  76,  76,  /*   54 */
3516  76,  76,  76,  76,  76,  76,  76,  76,  /*   54 */
3517  76,  76,  76,  76,  76,  76,  76,  76,  /*   54 */
3518  76,  76,  76,  76,  76,  76,  76,  76,  /*   54 */
3519  76,  76,  76,  76,  76,  76,  46,  46,  /*   55 */
3520  46,  46,  46,  46,  46,  46,  46,  46,  /*   55 */
3521  16,  16,  16,  16,  16,  16,  16,  16,  /*   55 */
3522  16,  16,  16,  16,  16,  16,  16,  16,  /*   55 */
3523  16,  16,  16,  16,  16,  16,  16,  16,  /*   55 */
3524  16,  16,  16,  16,  16,  16,  16,  16,  /*   55 */
3525  16,  16,  16,  16,  16,  16,  16,  46,  /*   55 */
3526  46,  46,  46,   3,  46,  46,  46,  46,  /*   55 */
3527  40,  40,  40,  40,  40,  40,  40,  40,  /*   56 */
3528  40,  40,  40,  40,  40,  40,  40,  40,  /*   56 */
3529  40,  40,  40,  40,  40,  40,  40,  40,  /*   56 */
3530  40,  40,  40,  40,  40,  40,  40,  40,  /*   56 */
3531  40,  40,  40,  40,  40,  40,  40,  40,  /*   56 */
3532  40,  40,  40,  40,  40,  40,  40,  40,  /*   56 */
3533  40,  40,  40,  40,  40,  40,  40,  40,  /*   56 */
3534  40,  40,  40,  40,  40,  40,  40,  40,  /*   56 */
3535  40,  40,  40,  40,  40,  40,  40,  40,  /*   57 */
3536  40,  40,  40,  40,  40,  40,  40,  40,  /*   57 */
3537  40,  40,  40,  40,  40,  40,  40,  40,  /*   57 */
3538  40,  40,  46,  46,  46,  46,  46,  40,  /*   57 */
3539  40,  40,  40,  40,  40,  40,  40,  40,  /*   57 */
3540  40,  40,  40,  40,  40,  40,  40,  40,  /*   57 */
3541  40,  40,  40,  40,  40,  40,  40,  40,  /*   57 */
3542  40,  40,  40,  40,  40,  40,  40,  40,  /*   57 */
3543  40,  40,  40,  40,  40,  40,  40,  40,  /*   58 */
3544  40,  40,  40,  40,  40,  40,  40,  40,  /*   58 */
3545  40,  40,  40,  40,  40,  40,  40,  40,  /*   58 */
3546  40,  40,  40,  40,  40,  40,  40,  40,  /*   58 */
3547  40,  40,  40,  46,  46,  46,  46,  46,  /*   58 */
3548  40,  40,  40,  40,  40,  40,  40,  40,  /*   58 */
3549  40,  40,  40,  40,  40,  40,  40,  40,  /*   58 */
3550  40,  40,  40,  40,  40,  40,  40,  40,  /*   58 */
3551  40,  40,  40,  40,  40,  40,  40,  40,  /*   59 */
3552  40,  40,  40,  40,  40,  40,  40,  40,  /*   59 */
3553  40,  40,  40,  40,  40,  40,  40,  40,  /*   59 */
3554  40,  40,  40,  40,  40,  40,  40,  40,  /*   59 */
3555  40,  40,  40,  40,  40,  40,  40,  40,  /*   59 */
3556  40,  40,  40,  40,  40,  40,  40,  40,  /*   59 */
3557  40,  40,  40,  40,  40,  40,  40,  40,  /*   59 */
3558  40,  40,  46,  46,  46,  46,  46,  46,  /*   59 */
3559  23,  24,  23,  24,  23,  24,  23,  24,  /*   60 */
3560  23,  24,  23,  24,  23,  24,  23,  24,  /*   60 */
3561  23,  24,  23,  24,  23,  24,  23,  24,  /*   60 */
3562  23,  24,  23,  24,  23,  24,  23,  24,  /*   60 */
3563  23,  24,  23,  24,  23,  24,  23,  24,  /*   60 */
3564  23,  24,  23,  24,  23,  24,  23,  24,  /*   60 */
3565  23,  24,  23,  24,  23,  24,  23,  24,  /*   60 */
3566  23,  24,  23,  24,  23,  24,  23,  24,  /*   60 */
3567  23,  24,  23,  24,  23,  24,  23,  24,  /*   61 */
3568  23,  24,  23,  24,  23,  24,  23,  24,  /*   61 */
3569  23,  24,  23,  24,  23,  24,  16,  16,  /*   61 */
3570  16,  16,  16,  16,  46,  46,  46,  46,  /*   61 */
3571  23,  24,  23,  24,  23,  24,  23,  24,  /*   61 */
3572  23,  24,  23,  24,  23,  24,  23,  24,  /*   61 */
3573  23,  24,  23,  24,  23,  24,  23,  24,  /*   61 */
3574  23,  24,  23,  24,  23,  24,  23,  24,  /*   61 */
3575  23,  24,  23,  24,  23,  24,  23,  24,  /*   62 */
3576  23,  24,  23,  24,  23,  24,  23,  24,  /*   62 */
3577  23,  24,  23,  24,  23,  24,  23,  24,  /*   62 */
3578  23,  24,  23,  24,  23,  24,  23,  24,  /*   62 */
3579  23,  24,  23,  24,  23,  24,  23,  24,  /*   62 */
3580  23,  24,  23,  24,  23,  24,  23,  24,  /*   62 */
3581  23,  24,  23,  24,  23,  24,  23,  24,  /*   62 */
3582  23,  24,  46,  46,  46,  46,  46,  46,  /*   62 */
3583  86,  86,  86,  86,  86,  86,  86,  86,  /*   63 */
3584  87,  87,  87,  87,  87,  87,  87,  87,  /*   63 */
3585  86,  86,  86,  86,  86,  86,  46,  46,  /*   63 */
3586  87,  87,  87,  87,  87,  87,  46,  46,  /*   63 */
3587  86,  86,  86,  86,  86,  86,  86,  86,  /*   63 */
3588  87,  87,  87,  87,  87,  87,  87,  87,  /*   63 */
3589  86,  86,  86,  86,  86,  86,  86,  86,  /*   63 */
3590  87,  87,  87,  87,  87,  87,  87,  87,  /*   63 */
3591  86,  86,  86,  86,  86,  86,  46,  46,  /*   64 */
3592  87,  87,  87,  87,  87,  87,  46,  46,  /*   64 */
3593  16,  86,  16,  86,  16,  86,  16,  86,  /*   64 */
3594  46,  87,  46,  87,  46,  87,  46,  87,  /*   64 */
3595  86,  86,  86,  86,  86,  86,  86,  86,  /*   64 */
3596  87,  87,  87,  87,  87,  87,  87,  87,  /*   64 */
3597  88,  88,  89,  89,  89,  89,  90,  90,  /*   64 */
3598  91,  91,  92,  92,  93,  93,  46,  46,  /*   64 */
3599  86,  86,  86,  86,  86,  86,  86,  86,  /*   65 */
3600  87,  87,  87,  87,  87,  87,  87,  87,  /*   65 */
3601  86,  86,  86,  86,  86,  86,  86,  86,  /*   65 */
3602  87,  87,  87,  87,  87,  87,  87,  87,  /*   65 */
3603  86,  86,  86,  86,  86,  86,  86,  86,  /*   65 */
3604  87,  87,  87,  87,  87,  87,  87,  87,  /*   65 */
3605  86,  86,  16,  94,  16,  46,  16,  16,  /*   65 */
3606  87,  87,  95,  95,  96,  11,  38,  11,  /*   65 */
3607  11,  11,  16,  94,  16,  46,  16,  16,  /*   66 */
3608  97,  97,  97,  97,  96,  11,  11,  11,  /*   66 */
3609  86,  86,  16,  16,  46,  46,  16,  16,  /*   66 */
3610  87,  87,  98,  98,  46,  11,  11,  11,  /*   66 */
3611  86,  86,  16,  16,  16,  99,  16,  16,  /*   66 */
3612  87,  87, 100, 100, 101,  11,  11,  11,  /*   66 */
3613  46,  46,  16,  94,  16,  46,  16,  16,  /*   66 */
3614 102, 102, 103, 103,  96,  11,  11,  46,  /*   66 */
3615   2,   2,   2,   2,   2,   2,   2,   2,  /*   67 */
3616   2,   2,   2,   2, 104, 104, 104, 104,  /*   67 */
3617   8,   8,   8,   8,   8,   8,   3,   3,  /*   67 */
3618   5,   6,   5,   5,   5,   6,   5,   5,  /*   67 */
3619   3,   3,   3,   3,   3,   3,   3,   3,  /*   67 */
3620 105, 106, 104, 104, 104, 104, 104,  46,  /*   67 */
3621   3,   3,   3,   3,   3,   3,   3,   3,  /*   67 */
3622   3,   5,   6,   3,   3,   3,   3,  12,  /*   67 */
3623  12,   3,   3,   3,   7,   5,   6,  46,  /*   68 */
3624  46,  46,  46,  46,  46,  46,  46,  46,  /*   68 */
3625  46,  46,  46,  46,  46,  46,  46,  46,  /*   68 */
3626  46,  46,  46,  46,  46,  46,  46,  46,  /*   68 */
3627  46,  46,  46,  46,  46,  46,  46,  46,  /*   68 */
3628  46,  46, 104, 104, 104, 104, 104, 104,  /*   68 */
3629  17,  46,  46,  46,  17,  17,  17,  17,  /*   68 */
3630  17,  17,   7,   7,   7,   5,   6,  16,  /*   68 */
3631 107, 107, 107, 107, 107, 107, 107, 107,  /*   69 */
3632 107, 107,   7,   7,   7,   5,   6,  46,  /*   69 */
3633  46,  46,  46,  46,  46,  46,  46,  46,  /*   69 */
3634  46,  46,  46,  46,  46,  46,  46,  46,  /*   69 */
3635   4,   4,   4,   4,   4,   4,   4,   4,  /*   69 */
3636   4,   4,   4,   4,  46,  46,  46,  46,  /*   69 */
3637  46,  46,  46,  46,  46,  46,  46,  46,  /*   69 */
3638  46,  46,  46,  46,  46,  46,  46,  46,  /*   69 */
3639  46,  46,  46,  46,  46,  46,  46,  46,  /*   70 */
3640  46,  46,  46,  46,  46,  46,  46,  46,  /*   70 */
3641  60,  60,  60,  60,  60,  60,  60,  60,  /*   70 */
3642  60,  60,  60,  60,  60,  79,  79,  79,  /*   70 */
3643  79,  60,  46,  46,  46,  46,  46,  46,  /*   70 */
3644  46,  46,  46,  46,  46,  46,  46,  46,  /*   70 */
3645  46,  46,  46,  46,  46,  46,  46,  46,  /*   70 */
3646  46,  46,  46,  46,  46,  46,  46,  46,  /*   70 */
3647  15,  15,  38,  15,  15,  15,  15,  38,  /*   71 */
3648  15,  15,  16,  38,  38,  38,  16,  16,  /*   71 */
3649  38,  38,  38,  16,  15,  38,  15,  15,  /*   71 */
3650  38,  38,  38,  38,  38,  38,  15,  15,  /*   71 */
3651  15,  15,  15,  15,  38,  15,  38,  15,  /*   71 */
3652  38,  15,  38,  38,  38,  38,  16,  16,  /*   71 */
3653  38,  38,  15,  38,  16,  40,  40,  40,  /*   71 */
3654  40,  46,  46,  46,  46,  46,  46,  46,  /*   71 */
3655  46,  46,  46,  46,  46,  46,  46,  46,  /*   72 */
3656  46,  46,  46,  46,  46,  46,  46,  46,  /*   72 */
3657  46,  46,  46,  19,  19,  19,  19,  19,  /*   72 */
3658  19,  19,  19,  19,  19,  19,  19, 108,  /*   72 */
3659 109, 109, 109, 109, 109, 109, 109, 109,  /*   72 */
3660 109, 109, 109, 109, 110, 110, 110, 110,  /*   72 */
3661 111, 111, 111, 111, 111, 111, 111, 111,  /*   72 */
3662 111, 111, 111, 111, 112, 112, 112, 112,  /*   72 */
3663 113, 113, 113,  46,  46,  46,  46,  46,  /*   73 */
3664  46,  46,  46,  46,  46,  46,  46,  46,  /*   73 */
3665   7,   7,   7,   7,   7,  15,  15,  15,  /*   73 */
3666  15,  15,  15,  15,  15,  15,  15,  15,  /*   73 */
3667  15,  15,  15,  15,  15,  15,  15,  15,  /*   73 */
3668  15,  15,  15,  15,  15,  15,  15,  15,  /*   73 */
3669  15,  15,  15,  15,  15,  15,  15,  15,  /*   73 */
3670  15,  15,  15,  15,  15,  15,  15,  15,  /*   73 */
3671  15,  15,  15,  15,  15,  15,  15,  15,  /*   74 */
3672  15,  15,  15,  15,  15,  15,  15,  15,  /*   74 */
3673  15,  15,   7,  15,   7,  15,  15,  15,  /*   74 */
3674  15,  15,  15,  15,  15,  15,  15,  15,  /*   74 */
3675  15,  15,  15,  15,  15,  15,  15,  15,  /*   74 */
3676  15,  15,  15,  46,  46,  46,  46,  46,  /*   74 */
3677  46,  46,  46,  46,  46,  46,  46,  46,  /*   74 */
3678  46,  46,  46,  46,  46,  46,  46,  46,  /*   74 */
3679   7,   7,   7,   7,   7,   7,   7,   7,  /*   75 */
3680   7,   7,   7,   7,   7,   7,   7,   7,  /*   75 */
3681   7,   7,   7,   7,   7,   7,   7,   7,  /*   75 */
3682   7,   7,   7,   7,   7,   7,   7,   7,  /*   75 */
3683   7,   7,   7,   7,   7,   7,   7,   7,  /*   75 */
3684   7,   7,   7,   7,   7,   7,   7,   7,  /*   75 */
3685   7,   7,   7,   7,   7,   7,   7,   7,  /*   75 */
3686   7,   7,   7,   7,   7,   7,   7,   7,  /*   75 */
3687   7,   7,   7,   7,   7,   7,   7,   7,  /*   76 */
3688   7,   7,   7,   7,   7,   7,   7,   7,  /*   76 */
3689   7,   7,   7,   7,   7,   7,   7,   7,  /*   76 */
3690   7,   7,   7,   7,   7,   7,   7,   7,  /*   76 */
3691   7,   7,   7,   7,   7,   7,   7,   7,  /*   76 */
3692   7,   7,   7,   7,   7,   7,   7,   7,  /*   76 */
3693   7,   7,  46,  46,  46,  46,  46,  46,  /*   76 */
3694  46,  46,  46,  46,  46,  46,  46,  46,  /*   76 */
3695  15,  46,  15,  15,  15,  15,  15,  15,  /*   77 */
3696   7,   7,   7,   7,  15,  15,  15,  15,  /*   77 */
3697  15,  15,  15,  15,  15,  15,  15,  15,  /*   77 */
3698  15,  15,  15,  15,  15,  15,  15,  15,  /*   77 */
3699   7,   7,  15,  15,  15,  15,  15,  15,  /*   77 */
3700  15,   5,   6,  15,  15,  15,  15,  15,  /*   77 */
3701  15,  15,  15,  15,  15,  15,  15,  15,  /*   77 */
3702  15,  15,  15,  15,  15,  15,  15,  15,  /*   77 */
3703  15,  15,  15,  15,  15,  15,  15,  15,  /*   78 */
3704  15,  15,  15,  15,  15,  15,  15,  15,  /*   78 */
3705  15,  15,  15,  15,  15,  15,  15,  15,  /*   78 */
3706  15,  15,  15,  15,  15,  15,  15,  15,  /*   78 */
3707  15,  15,  15,  15,  15,  15,  15,  15,  /*   78 */
3708  15,  15,  15,  15,  15,  15,  15,  15,  /*   78 */
3709  15,  15,  15,  15,  15,  15,  15,  15,  /*   78 */
3710  15,  15,  15,  46,  46,  46,  46,  46,  /*   78 */
3711  15,  15,  15,  15,  15,  15,  15,  15,  /*   79 */
3712  15,  15,  15,  15,  15,  15,  15,  15,  /*   79 */
3713  15,  15,  15,  15,  15,  15,  15,  15,  /*   79 */
3714  15,  15,  15,  15,  15,  15,  15,  15,  /*   79 */
3715  15,  15,  15,  15,  15,  46,  46,  46,  /*   79 */
3716  46,  46,  46,  46,  46,  46,  46,  46,  /*   79 */
3717  46,  46,  46,  46,  46,  46,  46,  46,  /*   79 */
3718  46,  46,  46,  46,  46,  46,  46,  46,  /*   79 */
3719  15,  15,  15,  15,  15,  15,  15,  15,  /*   80 */
3720  15,  15,  15,  46,  46,  46,  46,  46,  /*   80 */
3721  46,  46,  46,  46,  46,  46,  46,  46,  /*   80 */
3722  46,  46,  46,  46,  46,  46,  46,  46,  /*   80 */
3723 114, 114, 114, 114, 114, 114, 114, 114,  /*   80 */
3724 114, 114, 114, 114, 114, 114, 114, 114,  /*   80 */
3725 114, 114, 114, 114,  82,  82,  82,  82,  /*   80 */
3726  82,  82,  82,  82,  82,  82,  82,  82,  /*   80 */
3727  82,  82,  82,  82,  82,  82,  82,  82,  /*   81 */
3728 115, 115, 115, 115, 115, 115, 115, 115,  /*   81 */
3729 115, 115, 115, 115, 115, 115, 115, 115,  /*   81 */
3730 115, 115, 115, 115,  15,  15,  15,  15,  /*   81 */
3731  15,  15,  15,  15,  15,  15,  15,  15,  /*   81 */
3732  15,  15,  15,  15,  15,  15,  15,  15,  /*   81 */
3733  15,  15,  15,  15,  15,  15, 116, 116,  /*   81 */
3734 116, 116, 116, 116, 116, 116, 116, 116,  /*   81 */
3735 116, 116, 116, 116, 116, 116, 116, 116,  /*   82 */
3736 116, 116, 116, 116, 116, 116, 116, 116,  /*   82 */
3737 117, 117, 117, 117, 117, 117, 117, 117,  /*   82 */
3738 117, 117, 117, 117, 117, 117, 117, 117,  /*   82 */
3739 117, 117, 117, 117, 117, 117, 117, 117,  /*   82 */
3740 117, 117, 118,  46,  46,  46,  46,  46,  /*   82 */
3741  46,  46,  46,  46,  46,  46,  46,  46,  /*   82 */
3742  46,  46,  46,  46,  46,  46,  46,  46,  /*   82 */
3743  15,  15,  15,  15,  15,  15,  15,  15,  /*   83 */
3744  15,  15,  15,  15,  15,  15,  15,  15,  /*   83 */
3745  15,  15,  15,  15,  15,  15,  15,  15,  /*   83 */
3746  15,  15,  15,  15,  15,  15,  15,  15,  /*   83 */
3747  15,  15,  15,  15,  15,  15,  15,  15,  /*   83 */
3748  15,  15,  15,  15,  15,  15,  15,  15,  /*   83 */
3749  15,  15,  15,  15,  15,  15,  15,  15,  /*   83 */
3750  15,  15,  15,  15,  15,  15,  15,  15,  /*   83 */
3751  15,  15,  15,  15,  15,  15,  15,  15,  /*   84 */
3752  15,  15,  15,  15,  15,  15,  15,  15,  /*   84 */
3753  15,  15,  15,  15,  15,  15,  46,  46,  /*   84 */
3754  46,  46,  46,  46,  46,  46,  46,  46,  /*   84 */
3755  15,  15,  15,  15,  15,  15,  15,  15,  /*   84 */
3756  15,  15,  15,  15,  15,  15,  15,  15,  /*   84 */
3757  15,  15,  15,  15,  15,  15,  15,  15,  /*   84 */
3758  15,  15,  15,  15,  15,  15,  15,  15,  /*   84 */
3759  15,  15,  15,  15,  15,  15,  15,  15,  /*   85 */
3760  15,  15,  15,  15,  15,  15,  15,  15,  /*   85 */
3761  15,  15,  15,  15,  15,  15,  15,  15,  /*   85 */
3762  15,  15,  15,  15,  15,  15,  15,  15,  /*   85 */
3763  15,  15,  15,  15,  15,  15,  15,  15,  /*   85 */
3764  15,  15,  15,  15,  15,  15,  15,  15,  /*   85 */
3765  46,  46,  46,  46,  46,  46,  46,  46,  /*   85 */
3766  46,  46,  46,  46,  46,  46,  46,  46,  /*   85 */
3767  15,  15,  15,  15,  15,  15,  15,  15,  /*   86 */
3768  15,  15,  15,  15,  15,  15,  15,  15,  /*   86 */
3769  15,  15,  15,  15,  46,  46,  46,  46,  /*   86 */
3770  46,  46,  15,  15,  15,  15,  15,  15,  /*   86 */
3771  15,  15,  15,  15,  15,  15,  15,  15,  /*   86 */
3772  15,  15,  15,  15,  15,  15,  15,  15,  /*   86 */
3773  15,  15,  15,  15,  15,  15,  15,  15,  /*   86 */
3774  15,  15,  15,  15,  15,  15,  15,  15,  /*   86 */
3775  46,  15,  15,  15,  15,  46,  15,  15,  /*   87 */
3776  15,  15,  46,  46,  15,  15,  15,  15,  /*   87 */
3777  15,  15,  15,  15,  15,  15,  15,  15,  /*   87 */
3778  15,  15,  15,  15,  15,  15,  15,  15,  /*   87 */
3779  15,  15,  15,  15,  15,  15,  15,  15,  /*   87 */
3780  46,  15,  15,  15,  15,  15,  15,  15,  /*   87 */
3781  15,  15,  15,  15,  15,  15,  15,  15,  /*   87 */
3782  15,  15,  15,  15,  15,  15,  15,  15,  /*   87 */
3783  15,  15,  15,  15,  15,  15,  15,  15,  /*   88 */
3784  15,  15,  15,  15,  46,  15,  46,  15,  /*   88 */
3785  15,  15,  15,  46,  46,  46,  15,  46,  /*   88 */
3786  15,  15,  15,  15,  15,  15,  15,  46,  /*   88 */
3787  46,  15,  15,  15,  15,  15,  15,  15,  /*   88 */
3788  46,  46,  46,  46,  46,  46,  46,  46,  /*   88 */
3789  46,  46,  46,  46,  46,  46, 119, 119,  /*   88 */
3790 119, 119, 119, 119, 119, 119, 119, 119,  /*   88 */
3791 114, 114, 114, 114, 114, 114, 114, 114,  /*   89 */
3792 114, 114,  83,  83,  83,  83,  83,  83,  /*   89 */
3793  83,  83,  83,  83,  15,  46,  46,  46,  /*   89 */
3794  15,  15,  15,  15,  15,  15,  15,  15,  /*   89 */
3795  15,  15,  15,  15,  15,  15,  15,  15,  /*   89 */
3796  15,  15,  15,  15,  15,  15,  15,  15,  /*   89 */
3797  46,  15,  15,  15,  15,  15,  15,  15,  /*   89 */
3798  15,  15,  15,  15,  15,  15,  15,  46,  /*   89 */
3799   2,   3,   3,   3,  15,  59,   3, 120,  /*   90 */
3800   5,   6,   5,   6,   5,   6,   5,   6,  /*   90 */
3801   5,   6,  15,  15,   5,   6,   5,   6,  /*   90 */
3802   5,   6,   5,   6,   8,   5,   6,   5,  /*   90 */
3803  15, 121, 121, 121, 121, 121, 121, 121,  /*   90 */
3804 121, 121,  60,  60,  60,  60,  60,  60,  /*   90 */
3805   8,  59,  59,  59,  59,  59,  15,  15,  /*   90 */
3806  46,  46,  46,  46,  46,  46,  46,  15,  /*   90 */
3807  46,  40,  40,  40,  40,  40,  40,  40,  /*   91 */
3808  40,  40,  40,  40,  40,  40,  40,  40,  /*   91 */
3809  40,  40,  40,  40,  40,  40,  40,  40,  /*   91 */
3810  40,  40,  40,  40,  40,  40,  40,  40,  /*   91 */
3811  40,  40,  40,  40,  40,  40,  40,  40,  /*   91 */
3812  40,  40,  40,  40,  40,  40,  40,  40,  /*   91 */
3813  40,  40,  40,  40,  40,  40,  40,  40,  /*   91 */
3814  40,  40,  40,  40,  40,  40,  40,  40,  /*   91 */
3815  40,  40,  40,  40,  40,  40,  40,  40,  /*   92 */
3816  40,  40,  40,  40,  40,  40,  40,  40,  /*   92 */
3817  40,  40,  40,  40,  40,  46,  46,  46,  /*   92 */
3818  46,  60,  60,  59,  59,  59,  59,  46,  /*   92 */
3819  46,  40,  40,  40,  40,  40,  40,  40,  /*   92 */
3820  40,  40,  40,  40,  40,  40,  40,  40,  /*   92 */
3821  40,  40,  40,  40,  40,  40,  40,  40,  /*   92 */
3822  40,  40,  40,  40,  40,  40,  40,  40,  /*   92 */
3823  40,  40,  40,  40,  40,  40,  40,  40,  /*   93 */
3824  40,  40,  40,  40,  40,  40,  40,  40,  /*   93 */
3825  40,  40,  40,  40,  40,  40,  40,  40,  /*   93 */
3826  40,  40,  40,  40,  40,  40,  40,  40,  /*   93 */
3827  40,  40,  40,  40,  40,  40,  40,  40,  /*   93 */
3828  40,  40,  40,  40,  40,  40,  40,  40,  /*   93 */
3829  40,  40,  40,  40,  40,  40,  40,  40,  /*   93 */
3830  40,  40,  40,   3,  59,  59,  59,  46,  /*   93 */
3831  46,  46,  46,  46,  46,  40,  40,  40,  /*   94 */
3832  40,  40,  40,  40,  40,  40,  40,  40,  /*   94 */
3833  40,  40,  40,  40,  40,  40,  40,  40,  /*   94 */
3834  40,  40,  40,  40,  40,  40,  40,  40,  /*   94 */
3835  40,  40,  40,  40,  40,  40,  40,  40,  /*   94 */
3836  40,  40,  40,  40,  40,  46,  46,  46,  /*   94 */
3837  46,  40,  40,  40,  40,  40,  40,  40,  /*   94 */
3838  40,  40,  40,  40,  40,  40,  40,  40,  /*   94 */
3839  40,  40,  40,  40,  40,  40,  40,  40,  /*   95 */
3840  40,  40,  40,  40,  40,  40,  40,  46,  /*   95 */
3841  15,  15,  85,  85,  85,  85,  15,  15,  /*   95 */
3842  15,  15,  15,  15,  15,  15,  15,  15,  /*   95 */
3843  46,  46,  46,  46,  46,  46,  46,  46,  /*   95 */
3844  46,  46,  46,  46,  46,  46,  46,  46,  /*   95 */
3845  46,  46,  46,  46,  46,  46,  46,  46,  /*   95 */
3846  46,  46,  46,  46,  46,  46,  46,  46,  /*   95 */
3847  15,  15,  15,  15,  15,  15,  15,  15,  /*   96 */
3848  15,  15,  15,  15,  15,  15,  15,  15,  /*   96 */
3849  15,  15,  15,  15,  15,  15,  15,  15,  /*   96 */
3850  15,  15,  15,  15,  15,  46,  46,  46,  /*   96 */
3851  85,  85,  85,  85,  85,  85,  85,  85,  /*   96 */
3852  85,  85,  15,  15,  15,  15,  15,  15,  /*   96 */
3853  15,  15,  15,  15,  15,  15,  15,  15,  /*   96 */
3854  15,  15,  15,  15,  15,  15,  15,  15,  /*   96 */
3855  15,  15,  15,  15,  46,  46,  46,  46,  /*   97 */
3856  46,  46,  46,  46,  46,  46,  46,  46,  /*   97 */
3857  46,  46,  46,  46,  46,  46,  46,  46,  /*   97 */
3858  46,  46,  46,  46,  46,  46,  46,  46,  /*   97 */
3859  15,  15,  15,  15,  15,  15,  15,  15,  /*   97 */
3860  15,  15,  15,  15,  15,  15,  15,  15,  /*   97 */
3861  15,  15,  15,  15,  15,  15,  15,  15,  /*   97 */
3862  15,  15,  15,  15,  46,  46,  46,  15,  /*   97 */
3863 114, 114, 114, 114, 114, 114, 114, 114,  /*   98 */
3864 114, 114,  15,  15,  15,  15,  15,  15,  /*   98 */
3865  15,  15,  15,  15,  15,  15,  15,  15,  /*   98 */
3866  15,  15,  15,  15,  15,  15,  15,  15,  /*   98 */
3867  15,  15,  15,  15,  15,  15,  15,  15,  /*   98 */
3868  15,  15,  15,  15,  15,  15,  15,  15,  /*   98 */
3869  15,  46,  46,  46,  46,  46,  46,  46,  /*   98 */
3870  46,  46,  46,  46,  46,  46,  46,  46,  /*   98 */
3871  15,  15,  15,  15,  15,  15,  15,  15,  /*   99 */
3872  15,  15,  15,  15,  46,  46,  46,  46,  /*   99 */
3873  15,  15,  15,  15,  15,  15,  15,  15,  /*   99 */
3874  15,  15,  15,  15,  15,  15,  15,  15,  /*   99 */
3875  15,  15,  15,  15,  15,  15,  15,  15,  /*   99 */
3876  15,  15,  15,  15,  15,  15,  15,  15,  /*   99 */
3877  15,  15,  15,  15,  15,  15,  15,  15,  /*   99 */
3878  15,  15,  15,  15,  15,  15,  15,  46,  /*   99 */
3879  15,  15,  15,  15,  15,  15,  15,  15,  /*  100 */
3880  15,  15,  15,  15,  15,  15,  15,  15,  /*  100 */
3881  15,  15,  15,  15,  15,  15,  15,  15,  /*  100 */
3882  15,  15,  15,  15,  15,  15,  15,  15,  /*  100 */
3883  15,  15,  15,  15,  15,  15,  15,  15,  /*  100 */
3884  15,  15,  15,  15,  15,  15,  15,  15,  /*  100 */
3885  15,  15,  15,  15,  15,  15,  15,  46,  /*  100 */
3886  46,  46,  46,  15,  15,  15,  15,  15,  /*  100 */
3887  15,  15,  15,  15,  15,  15,  15,  15,  /*  101 */
3888  15,  15,  15,  15,  15,  15,  15,  15,  /*  101 */
3889  15,  15,  15,  15,  15,  15,  15,  15,  /*  101 */
3890  15,  15,  15,  15,  15,  15,  46,  46,  /*  101 */
3891  15,  15,  15,  15,  15,  15,  15,  15,  /*  101 */
3892  15,  15,  15,  15,  15,  15,  15,  15,  /*  101 */
3893  15,  15,  15,  15,  15,  15,  15,  15,  /*  101 */
3894  15,  15,  15,  15,  15,  15,  15,  46,  /*  101 */
3895  40,  40,  40,  40,  40,  40,  40,  40,  /*  102 */
3896  40,  40,  40,  40,  40,  40,  40,  40,  /*  102 */
3897  40,  40,  40,  40,  40,  40,  40,  40,  /*  102 */
3898  40,  40,  40,  40,  40,  40,  40,  40,  /*  102 */
3899  40,  40,  40,  40,  40,  40,  46,  46,  /*  102 */
3900  46,  46,  46,  46,  46,  46,  46,  46,  /*  102 */
3901  46,  46,  46,  46,  46,  46,  46,  46,  /*  102 */
3902  46,  46,  46,  46,  46,  46,  46,  46,  /*  102 */
3903  40,  40,  40,  40,  40,  40,  40,  40,  /*  103 */
3904  40,  40,  40,  40,  40,  40,  40,  40,  /*  103 */
3905  40,  40,  40,  40,  40,  40,  40,  40,  /*  103 */
3906  40,  40,  40,  40,  40,  40,  40,  40,  /*  103 */
3907  40,  40,  40,  40,  46,  46,  46,  46,  /*  103 */
3908  46,  46,  46,  46,  46,  46,  46,  46,  /*  103 */
3909  46,  46,  46,  46,  46,  46,  46,  46,  /*  103 */
3910  46,  46,  46,  46,  46,  46,  46,  46,  /*  103 */
3911 122, 122, 122, 122, 122, 122, 122, 122,  /*  104 */
3912 122, 122, 122, 122, 122, 122, 122, 122,  /*  104 */
3913 122, 122, 122, 122, 122, 122, 122, 122,  /*  104 */
3914 122, 122, 122, 122, 122, 122, 122, 122,  /*  104 */
3915 122, 122, 122, 122, 122, 122, 122, 122,  /*  104 */
3916 122, 122, 122, 122, 122, 122, 122, 122,  /*  104 */
3917 122, 122, 122, 122, 122, 122, 122, 122,  /*  104 */
3918 122, 122, 122, 122, 122, 122, 122, 122,  /*  104 */
3919 123, 123, 123, 123, 123, 123, 123, 123,  /*  105 */
3920 123, 123, 123, 123, 123, 123, 123, 123,  /*  105 */
3921 123, 123, 123, 123, 123, 123, 123, 123,  /*  105 */
3922 123, 123, 123, 123, 123, 123, 123, 123,  /*  105 */
3923 123, 123, 123, 123, 123, 123, 123, 123,  /*  105 */
3924 123, 123, 123, 123, 123, 123, 123, 123,  /*  105 */
3925 123, 123, 123, 123, 123, 123, 123, 123,  /*  105 */
3926 123, 123, 123, 123, 123, 123, 123, 123,  /*  105 */
3927  40,  40,  40,  40,  40,  40,  40,  40,  /*  106 */
3928  40,  40,  40,  40,  40,  40,  40,  40,  /*  106 */
3929  40,  40,  40,  40,  40,  40,  40,  40,  /*  106 */
3930  40,  40,  40,  40,  40,  40,  40,  40,  /*  106 */
3931  40,  40,  40,  40,  40,  40,  40,  40,  /*  106 */
3932  40,  40,  40,  40,  40,  40,  46,  46,  /*  106 */
3933  46,  46,  46,  46,  46,  46,  46,  46,  /*  106 */
3934  46,  46,  46,  46,  46,  46,  46,  46,  /*  106 */
3935  16,  16,  16,  16,  16,  16,  16,  46,  /*  107 */
3936  46,  46,  46,  46,  46,  46,  46,  46,  /*  107 */
3937  46,  46,  46,  16,  16,  16,  16,  16,  /*  107 */
3938  46,  46,  46,  46,  46,  46,  60,  40,  /*  107 */
3939  40,  40,  40,  40,  40,  40,  40,  40,  /*  107 */
3940  40,   7,  40,  40,  40,  40,  40,  40,  /*  107 */
3941  40,  40,  40,  40,  40,  40,  40,  46,  /*  107 */
3942  40,  40,  40,  40,  40,  46,  40,  46,  /*  107 */
3943  40,  40,  46,  40,  40,  46,  40,  40,  /*  108 */
3944  40,  40,  40,  40,  40,  40,  40,  40,  /*  108 */
3945  40,  40,  40,  40,  40,  40,  40,  40,  /*  108 */
3946  40,  40,  40,  40,  40,  40,  40,  40,  /*  108 */
3947  40,  40,  40,  40,  40,  40,  40,  40,  /*  108 */
3948  40,  40,  40,  40,  40,  40,  40,  40,  /*  108 */
3949  40,  40,  40,  40,  40,  40,  40,  40,  /*  108 */
3950  40,  40,  40,  40,  40,  40,  40,  40,  /*  108 */
3951  40,  40,  40,  40,  40,  40,  40,  40,  /*  109 */
3952  40,  40,  40,  40,  40,  40,  40,  40,  /*  109 */
3953  40,  40,  40,  40,  40,  40,  40,  40,  /*  109 */
3954  40,  40,  40,  40,  40,  40,  40,  40,  /*  109 */
3955  40,  40,  40,  40,  40,  40,  40,  40,  /*  109 */
3956  40,  40,  40,  40,  40,  40,  40,  40,  /*  109 */
3957  40,  40,  46,  46,  46,  46,  46,  46,  /*  109 */
3958  46,  46,  46,  46,  46,  46,  46,  46,  /*  109 */
3959  46,  46,  46,  46,  46,  46,  46,  46,  /*  110 */
3960  46,  46,  46,  46,  46,  46,  46,  46,  /*  110 */
3961  46,  46,  46,  40,  40,  40,  40,  40,  /*  110 */
3962  40,  40,  40,  40,  40,  40,  40,  40,  /*  110 */
3963  40,  40,  40,  40,  40,  40,  40,  40,  /*  110 */
3964  40,  40,  40,  40,  40,  40,  40,  40,  /*  110 */
3965  40,  40,  40,  40,  40,  40,  40,  40,  /*  110 */
3966  40,  40,  40,  40,  40,  40,  40,  40,  /*  110 */
3967  40,  40,  40,  40,  40,  40,  40,  40,  /*  111 */
3968  40,  40,  40,  40,  40,  40,  40,  40,  /*  111 */
3969  40,  40,  40,  40,  40,  40,  40,  40,  /*  111 */
3970  40,  40,  40,  40,  40,  40,  40,  40,  /*  111 */
3971  40,  40,  40,  40,  40,  40,  40,  40,  /*  111 */
3972  40,  40,  40,  40,  40,  40,  40,  40,  /*  111 */
3973  40,  40,  40,  40,  40,  40,  40,  40,  /*  111 */
3974  40,  40,  40,  40,  40,  40,   5,   6,  /*  111 */
3975  46,  46,  46,  46,  46,  46,  46,  46,  /*  112 */
3976  46,  46,  46,  46,  46,  46,  46,  46,  /*  112 */
3977  40,  40,  40,  40,  40,  40,  40,  40,  /*  112 */
3978  40,  40,  40,  40,  40,  40,  40,  40,  /*  112 */
3979  40,  40,  40,  40,  40,  40,  40,  40,  /*  112 */
3980  40,  40,  40,  40,  40,  40,  40,  40,  /*  112 */
3981  40,  40,  40,  40,  40,  40,  40,  40,  /*  112 */
3982  40,  40,  40,  40,  40,  40,  40,  40,  /*  112 */
3983  40,  40,  40,  40,  40,  40,  40,  40,  /*  113 */
3984  40,  40,  40,  40,  40,  40,  40,  40,  /*  113 */
3985  46,  46,  40,  40,  40,  40,  40,  40,  /*  113 */
3986  40,  40,  40,  40,  40,  40,  40,  40,  /*  113 */
3987  40,  40,  40,  40,  40,  40,  40,  40,  /*  113 */
3988  40,  40,  40,  40,  40,  40,  40,  40,  /*  113 */
3989  40,  40,  40,  40,  40,  40,  40,  40,  /*  113 */
3990  40,  40,  40,  40,  40,  40,  40,  40,  /*  113 */
3991  40,  40,  40,  40,  40,  40,  40,  40,  /*  114 */
3992  46,  46,  46,  46,  46,  46,  46,  46,  /*  114 */
3993  46,  46,  46,  46,  46,  46,  46,  46,  /*  114 */
3994  46,  46,  46,  46,  46,  46,  46,  46,  /*  114 */
3995  46,  46,  46,  46,  46,  46,  46,  46,  /*  114 */
3996  46,  46,  46,  46,  46,  46,  46,  46,  /*  114 */
3997  40,  40,  40,  40,  40,  40,  40,  40,  /*  114 */
3998  40,  40,  40,  40,  46,  46,  46,  46,  /*  114 */
3999  46,  46,  46,  46,  46,  46,  46,  46,  /*  115 */
4000  46,  46,  46,  46,  46,  46,  46,  46,  /*  115 */
4001  46,  46,  46,  46,  46,  46,  46,  46,  /*  115 */
4002  46,  46,  46,  46,  46,  46,  46,  46,  /*  115 */
4003  60,  60,  60,  60,  46,  46,  46,  46,  /*  115 */
4004  46,  46,  46,  46,  46,  46,  46,  46,  /*  115 */
4005   3,   8,   8,  12,  12,   5,   6,   5,  /*  115 */
4006   6,   5,   6,   5,   6,   5,   6,   5,  /*  115 */
4007   6,   5,   6,   5,   6,  46,  46,  46,  /*  116 */
4008  46,   3,   3,   3,   3,  12,  12,  12,  /*  116 */
4009   3,   3,   3,  46,   3,   3,   3,   3,  /*  116 */
4010   8,   5,   6,   5,   6,   5,   6,   3,  /*  116 */
4011   3,   3,   7,   8,   7,   7,   7,  46,  /*  116 */
4012   3,   4,   3,   3,  46,  46,  46,  46,  /*  116 */
4013  40,  40,  40,  46,  40,  46,  40,  40,  /*  116 */
4014  40,  40,  40,  40,  40,  40,  40,  40,  /*  116 */
4015  40,  40,  40,  40,  40,  40,  40,  40,  /*  117 */
4016  40,  40,  40,  40,  40,  40,  40,  40,  /*  117 */
4017  40,  40,  40,  40,  40,  40,  40,  40,  /*  117 */
4018  40,  40,  40,  40,  40,  40,  40,  40,  /*  117 */
4019  40,  40,  40,  40,  40,  40,  40,  40,  /*  117 */
4020  40,  40,  40,  40,  40,  40,  40,  40,  /*  117 */
4021  40,  40,  40,  40,  40,  40,  40,  40,  /*  117 */
4022  40,  40,  40,  40,  40,  46,  46, 104,  /*  117 */
4023  46,   3,   3,   3,   4,   3,   3,   3,  /*  118 */
4024   5,   6,   3,   7,   3,   8,   3,   3,  /*  118 */
4025   9,   9,   9,   9,   9,   9,   9,   9,  /*  118 */
4026   9,   9,   3,   3,   7,   7,   7,   3,  /*  118 */
4027   3,  10,  10,  10,  10,  10,  10,  10,  /*  118 */
4028  10,  10,  10,  10,  10,  10,  10,  10,  /*  118 */
4029  10,  10,  10,  10,  10,  10,  10,  10,  /*  118 */
4030  10,  10,  10,   5,   3,   6,  11,  12,  /*  118 */
4031  11,  13,  13,  13,  13,  13,  13,  13,  /*  119 */
4032  13,  13,  13,  13,  13,  13,  13,  13,  /*  119 */
4033  13,  13,  13,  13,  13,  13,  13,  13,  /*  119 */
4034  13,  13,  13,   5,   7,   6,   7,  46,  /*  119 */
4035  46,   3,   5,   6,   3,   3,  40,  40,  /*  119 */
4036  40,  40,  40,  40,  40,  40,  40,  40,  /*  119 */
4037  59,  40,  40,  40,  40,  40,  40,  40,  /*  119 */
4038  40,  40,  40,  40,  40,  40,  40,  40,  /*  119 */
4039  40,  40,  40,  40,  40,  40,  40,  40,  /*  120 */
4040  40,  40,  40,  40,  40,  40,  40,  40,  /*  120 */
4041  40,  40,  40,  40,  40,  40,  40,  40,  /*  120 */
4042  40,  40,  40,  40,  40,  40,  59,  59,  /*  120 */
4043  40,  40,  40,  40,  40,  40,  40,  40,  /*  120 */
4044  40,  40,  40,  40,  40,  40,  40,  40,  /*  120 */
4045  40,  40,  40,  40,  40,  40,  40,  40,  /*  120 */
4046  40,  40,  40,  40,  40,  40,  40,  46,  /*  120 */
4047  46,  46,  40,  40,  40,  40,  40,  40,  /*  121 */
4048  46,  46,  40,  40,  40,  40,  40,  40,  /*  121 */
4049  46,  46,  40,  40,  40,  40,  40,  40,  /*  121 */
4050  46,  46,  40,  40,  40,  46,  46,  46,  /*  121 */
4051   4,   4,   7,  11,  15,   4,   4,  46,  /*  121 */
4052   7,   7,   7,   7,   7,  15,  15,  46,  /*  121 */
4053  46,  46,  46,  46,  46,  46,  46,  46,  /*  121 */
4054  46,  46,  46,  46,  46,  15,  46,  46   /*  121 */
4055 };
4057 /* The A table has 124 entries for a total of 496 bytes. */
4059 const uint32 js_A[] = {
4060 0x0001000F,  /*    0   Cc, ignorable */
4061 0x0004000F,  /*    1   Cc, whitespace */
4062 0x0004000C,  /*    2   Zs, whitespace */
4063 0x00000018,  /*    3   Po */
4064 0x0006001A,  /*    4   Sc, currency */
4065 0x00000015,  /*    5   Ps */
4066 0x00000016,  /*    6   Pe */
4067 0x00000019,  /*    7   Sm */
4068 0x00000014,  /*    8   Pd */
4069 0x00036009,  /*    9   Nd, identifier part, decimal 16 */
4070 0x0827FE01,  /*   10   Lu, hasLower (add 32), identifier start, supradecimal 31 */
4071 0x0000001B,  /*   11   Sk */
4072 0x00050017,  /*   12   Pc, underscore */
4073 0x0817FE02,  /*   13   Ll, hasUpper (subtract 32), identifier start, supradecimal 31 */
4074 0x0000000C,  /*   14   Zs */
4075 0x0000001C,  /*   15   So */
4076 0x00070002,  /*   16   Ll, identifier start */
4077 0x0000600B,  /*   17   No, decimal 16 */
4078 0x0000500B,  /*   18   No, decimal 8 */
4079 0x0000800B,  /*   19   No, strange */
4080 0x08270001,  /*   20   Lu, hasLower (add 32), identifier start */
4081 0x08170002,  /*   21   Ll, hasUpper (subtract 32), identifier start */
4082 0xE1D70002,  /*   22   Ll, hasUpper (subtract -121), identifier start */
4083 0x00670001,  /*   23   Lu, hasLower (add 1), identifier start */
4084 0x00570002,  /*   24   Ll, hasUpper (subtract 1), identifier start */
4085 0xCE670001,  /*   25   Lu, hasLower (add -199), identifier start */
4086 0x3A170002,  /*   26   Ll, hasUpper (subtract 232), identifier start */
4087 0xE1E70001,  /*   27   Lu, hasLower (add -121), identifier start */
4088 0x4B170002,  /*   28   Ll, hasUpper (subtract 300), identifier start */
4089 0x34A70001,  /*   29   Lu, hasLower (add 210), identifier start */
4090 0x33A70001,  /*   30   Lu, hasLower (add 206), identifier start */
4091 0x33670001,  /*   31   Lu, hasLower (add 205), identifier start */
4092 0x32A70001,  /*   32   Lu, hasLower (add 202), identifier start */
4093 0x32E70001,  /*   33   Lu, hasLower (add 203), identifier start */
4094 0x33E70001,  /*   34   Lu, hasLower (add 207), identifier start */
4095 0x34E70001,  /*   35   Lu, hasLower (add 211), identifier start */
4096 0x34670001,  /*   36   Lu, hasLower (add 209), identifier start */
4097 0x35670001,  /*   37   Lu, hasLower (add 213), identifier start */
4098 0x00070001,  /*   38   Lu, identifier start */
4099 0x36A70001,  /*   39   Lu, hasLower (add 218), identifier start */
4100 0x00070005,  /*   40   Lo, identifier start */
4101 0x36670001,  /*   41   Lu, hasLower (add 217), identifier start */
4102 0x36E70001,  /*   42   Lu, hasLower (add 219), identifier start */
4103 0x00AF0001,  /*   43   Lu, hasLower (add 2), hasTitle, identifier start */
4104 0x007F0003,  /*   44   Lt, hasUpper (subtract 1), hasLower (add 1), hasTitle, identifier start */
4105 0x009F0002,  /*   45   Ll, hasUpper (subtract 2), hasTitle, identifier start */
4106 0x00000000,  /*   46   unassigned */
4107 0x34970002,  /*   47   Ll, hasUpper (subtract 210), identifier start */
4108 0x33970002,  /*   48   Ll, hasUpper (subtract 206), identifier start */
4109 0x33570002,  /*   49   Ll, hasUpper (subtract 205), identifier start */
4110 0x32970002,  /*   50   Ll, hasUpper (subtract 202), identifier start */
4111 0x32D70002,  /*   51   Ll, hasUpper (subtract 203), identifier start */
4112 0x33D70002,  /*   52   Ll, hasUpper (subtract 207), identifier start */
4113 0x34570002,  /*   53   Ll, hasUpper (subtract 209), identifier start */
4114 0x34D70002,  /*   54   Ll, hasUpper (subtract 211), identifier start */
4115 0x35570002,  /*   55   Ll, hasUpper (subtract 213), identifier start */
4116 0x36970002,  /*   56   Ll, hasUpper (subtract 218), identifier start */
4117 0x36570002,  /*   57   Ll, hasUpper (subtract 217), identifier start */
4118 0x36D70002,  /*   58   Ll, hasUpper (subtract 219), identifier start */
4119 0x00070004,  /*   59   Lm, identifier start */
4120 0x00030006,  /*   60   Mn, identifier part */
4121 0x09A70001,  /*   61   Lu, hasLower (add 38), identifier start */
4122 0x09670001,  /*   62   Lu, hasLower (add 37), identifier start */
4123 0x10270001,  /*   63   Lu, hasLower (add 64), identifier start */
4124 0x0FE70001,  /*   64   Lu, hasLower (add 63), identifier start */
4125 0x09970002,  /*   65   Ll, hasUpper (subtract 38), identifier start */
4126 0x09570002,  /*   66   Ll, hasUpper (subtract 37), identifier start */
4127 0x10170002,  /*   67   Ll, hasUpper (subtract 64), identifier start */
4128 0x0FD70002,  /*   68   Ll, hasUpper (subtract 63), identifier start */
4129 0x0F970002,  /*   69   Ll, hasUpper (subtract 62), identifier start */
4130 0x0E570002,  /*   70   Ll, hasUpper (subtract 57), identifier start */
4131 0x0BD70002,  /*   71   Ll, hasUpper (subtract 47), identifier start */
4132 0x0D970002,  /*   72   Ll, hasUpper (subtract 54), identifier start */
4133 0x15970002,  /*   73   Ll, hasUpper (subtract 86), identifier start */
4134 0x14170002,  /*   74   Ll, hasUpper (subtract 80), identifier start */
4135 0x14270001,  /*   75   Lu, hasLower (add 80), identifier start */
4136 0x0C270001,  /*   76   Lu, hasLower (add 48), identifier start */
4137 0x0C170002,  /*   77   Ll, hasUpper (subtract 48), identifier start */
4138 0x00034009,  /*   78   Nd, identifier part, decimal 0 */
4139 0x00000007,  /*   79   Me */
4140 0x00030008,  /*   80   Mc, identifier part */
4141 0x00037409,  /*   81   Nd, identifier part, decimal 26 */
4142 0x00005A0B,  /*   82   No, decimal 13 */
4143 0x00006E0B,  /*   83   No, decimal 23 */
4144 0x0000740B,  /*   84   No, decimal 26 */
4145 0x0000000B,  /*   85   No */
4146 0xFE170002,  /*   86   Ll, hasUpper (subtract -8), identifier start */
4147 0xFE270001,  /*   87   Lu, hasLower (add -8), identifier start */
4148 0xED970002,  /*   88   Ll, hasUpper (subtract -74), identifier start */
4149 0xEA970002,  /*   89   Ll, hasUpper (subtract -86), identifier start */
4150 0xE7170002,  /*   90   Ll, hasUpper (subtract -100), identifier start */
4151 0xE0170002,  /*   91   Ll, hasUpper (subtract -128), identifier start */
4152 0xE4170002,  /*   92   Ll, hasUpper (subtract -112), identifier start */
4153 0xE0970002,  /*   93   Ll, hasUpper (subtract -126), identifier start */
4154 0xFDD70002,  /*   94   Ll, hasUpper (subtract -9), identifier start */
4155 0xEDA70001,  /*   95   Lu, hasLower (add -74), identifier start */
4156 0xFDE70001,  /*   96   Lu, hasLower (add -9), identifier start */
4157 0xEAA70001,  /*   97   Lu, hasLower (add -86), identifier start */
4158 0xE7270001,  /*   98   Lu, hasLower (add -100), identifier start */
4159 0xFE570002,  /*   99   Ll, hasUpper (subtract -7), identifier start */
4160 0xE4270001,  /*  100   Lu, hasLower (add -112), identifier start */
4161 0xFE670001,  /*  101   Lu, hasLower (add -7), identifier start */
4162 0xE0270001,  /*  102   Lu, hasLower (add -128), identifier start */
4163 0xE0A70001,  /*  103   Lu, hasLower (add -126), identifier start */
4164 0x00010010,  /*  104   Cf, ignorable */
4165 0x0004000D,  /*  105   Zl, whitespace */
4166 0x0004000E,  /*  106   Zp, whitespace */
4167 0x0000400B,  /*  107   No, decimal 0 */
4168 0x0000440B,  /*  108   No, decimal 2 */
4169 0x0427420A,  /*  109   Nl, hasLower (add 16), identifier start, decimal 1 */
4170 0x0427800A,  /*  110   Nl, hasLower (add 16), identifier start, strange */
4171 0x0417620A,  /*  111   Nl, hasUpper (subtract 16), identifier start, decimal 17 */
4172 0x0417800A,  /*  112   Nl, hasUpper (subtract 16), identifier start, strange */
4173 0x0007800A,  /*  113   Nl, identifier start, strange */
4174 0x0000420B,  /*  114   No, decimal 1 */
4175 0x0000720B,  /*  115   No, decimal 25 */
4176 0x06A0001C,  /*  116   So, hasLower (add 26) */
4177 0x0690001C,  /*  117   So, hasUpper (subtract 26) */
4178 0x00006C0B,  /*  118   No, decimal 22 */
4179 0x0000560B,  /*  119   No, decimal 11 */
4180 0x0007720A,  /*  120   Nl, identifier start, decimal 25 */
4181 0x0007400A,  /*  121   Nl, identifier start, decimal 0 */
4182 0x00000013,  /*  122   Cs */
4183 0x00000012   /*  123   Co */
4184 };
4186 const jschar js_uriReservedPlusPound_ucstr[] =
4187     {';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '#', 0};
4188 const jschar js_uriUnescaped_ucstr[] =
4189     {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
4190      'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
4191      'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
4192      'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
4193      'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
4194      '-', '_', '.', '!', '~', '*', '\'', '(', ')', 0};
4196 #define URI_CHUNK 64U
4198 /* Concatenate jschars onto an unshared/newborn JSString. */
4199 static JSBool
4200 AddCharsToURI(JSContext *cx, JSString *str, const jschar *chars, size_t length)
4202     size_t total;
4204     JS_ASSERT(!JSSTRING_IS_DEPENDENT(str));
4205     total = str->length + length + 1;
4206     if (!str->chars ||
4207         JS_HOWMANY(total, URI_CHUNK) > JS_HOWMANY(str->length + 1, URI_CHUNK)) {
4208         total = JS_ROUNDUP(total, URI_CHUNK);
4209         str->chars = JS_realloc(cx, str->chars, total * sizeof(jschar));
4210         if (!str->chars)
4211             return JS_FALSE;
4212     }
4213     js_strncpy(str->chars + str->length, chars, length);
4214     str->length += length;
4215     str->chars[str->length] = 0;
4216     return JS_TRUE;
4219 /*
4220  * ECMA 3, 15.1.3 URI Handling Function Properties
4221  *
4222  * The following are implementations of the algorithms
4223  * given in the ECMA specification for the hidden functions
4224  * 'Encode' and 'Decode'.
4225  */
4226 static JSBool
4227 Encode(JSContext *cx, JSString *str, const jschar *unescapedSet,
4228        const jschar *unescapedSet2, jsval *rval)
4230     size_t length, j, k, L;
4231     jschar *chars, C, C2;
4232     uint32 V;
4233     uint8 utf8buf[6];
4234     jschar hexBuf[4];
4235     static const char HexDigits[] = "0123456789ABCDEF"; /* NB: uppercase */
4236     JSString *R;
4238     R = js_NewString(cx, NULL, 0, 0);
4239     if (!R)
4240         return JS_FALSE;
4242     hexBuf[0] = '%';
4243     hexBuf[3] = 0;
4244     chars = JSSTRING_CHARS(str);
4245     length = JSSTRING_LENGTH(str);
4246     for (k = 0; k < length; k++) {
4247         C = chars[k];
4248         if (js_strchr(unescapedSet, C) ||
4249             (unescapedSet2 && js_strchr(unescapedSet2, C))) {
4250             if (!AddCharsToURI(cx, R, &C, 1))
4251                 return JS_FALSE;
4252         } else {
4253             if ((C >= 0xDC00) && (C <= 0xDFFF)) {
4254                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
4255                                  JSMSG_BAD_URI, NULL);
4256                 return JS_FALSE;
4257             }
4258             if (C < 0xD800 || C > 0xDBFF) {
4259                 V = C;
4260             } else {
4261                 k++;
4262                 if (k == length) {
4263                     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
4264                                      JSMSG_BAD_URI, NULL);
4265                     return JS_FALSE;
4266                 }
4267                 C2 = chars[k];
4268                 if ((C2 < 0xDC00) || (C2 > 0xDFFF)) {
4269                     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
4270                                      JSMSG_BAD_URI, NULL);
4271                     return JS_FALSE;
4272                 }
4273                 V = ((C - 0xD800) << 10) + (C2 - 0xDC00) + 0x10000;
4274             }
4275             L = OneUcs4ToUtf8Char(utf8buf, V);
4276             for (j = 0; j < L; j++) {
4277                 hexBuf[1] = HexDigits[utf8buf[j] >> 4];
4278                 hexBuf[2] = HexDigits[utf8buf[j] & 0xf];
4279                 if (!AddCharsToURI(cx, R, hexBuf, 3))
4280                     return JS_FALSE;
4281             }
4282         }
4283     }
4285     /*
4286      * Shrinking realloc can fail (e.g., with a BSD-style allocator), but we
4287      * don't worry about that case here.  Worst case, R hangs onto URI_CHUNK-1
4288      * more jschars than it needs.
4289      */
4290     chars = (jschar *) JS_realloc(cx, R->chars, (R->length+1) * sizeof(jschar));
4291     if (chars)
4292         R->chars = chars;
4293     *rval = STRING_TO_JSVAL(R);
4294     return JS_TRUE;
4297 static JSBool
4298 Decode(JSContext *cx, JSString *str, const jschar *reservedSet, jsval *rval)
4300     size_t length, start, k;
4301     jschar *chars, C, H;
4302     uint32 V;
4303     jsuint B;
4304     uint8 octets[6];
4305     JSString *R;
4306     intN j, n;
4308     R = js_NewString(cx, NULL, 0, 0);
4309     if (!R)
4310         return JS_FALSE;
4312     chars = JSSTRING_CHARS(str);
4313     length = JSSTRING_LENGTH(str);
4314     for (k = 0; k < length; k++) {
4315         C = chars[k];
4316         if (C == '%') {
4317             start = k;
4318             if ((k + 2) >= length)
4319                 goto bad;
4320             if (!JS7_ISHEX(chars[k+1]) || !JS7_ISHEX(chars[k+2]))
4321                 goto bad;
4322             B = JS7_UNHEX(chars[k+1]) * 16 + JS7_UNHEX(chars[k+2]);
4323             k += 2;
4324             if (!(B & 0x80)) {
4325                 C = (jschar)B;
4326             } else {
4327                 n = 1;
4328                 while (B & (0x80 >> n))
4329                     n++;
4330                 if (n == 1 || n > 6)
4331                     goto bad;
4332                 octets[0] = (uint8)B;
4333                 if (k + 3 * (n - 1) >= length)
4334                     goto bad;
4335                 for (j = 1; j < n; j++) {
4336                     k++;
4337                     if (chars[k] != '%')
4338                         goto bad;
4339                     if (!JS7_ISHEX(chars[k+1]) || !JS7_ISHEX(chars[k+2]))
4340                         goto bad;
4341                     B = JS7_UNHEX(chars[k+1]) * 16 + JS7_UNHEX(chars[k+2]);
4342                     if ((B & 0xC0) != 0x80)
4343                         goto bad;
4344                     k += 2;
4345                     octets[j] = (char)B;
4346                 }
4347                 V = Utf8ToOneUcs4Char(octets, n);
4348                 if (V >= 0x10000) {
4349                     V -= 0x10000;
4350                     if (V > 0xFFFFF)
4351                         goto bad;
4352                     C = (jschar)((V & 0x3FF) + 0xDC00);
4353                     H = (jschar)((V >> 10) + 0xD800);
4354                     if (!AddCharsToURI(cx, R, &H, 1))
4355                         return JS_FALSE;
4356                 } else {
4357                     C = (jschar)V;
4358                 }
4359             }
4360             if (js_strchr(reservedSet, C)) {
4361                 if (!AddCharsToURI(cx, R, &chars[start], (k - start + 1)))
4362                     return JS_FALSE;
4363             } else {
4364                 if (!AddCharsToURI(cx, R, &C, 1))
4365                     return JS_FALSE;
4366             }
4367         } else {
4368             if (!AddCharsToURI(cx, R, &C, 1))
4369                 return JS_FALSE;
4370         }
4371     }
4373     /*
4374      * Shrinking realloc can fail (e.g., with a BSD-style allocator), but we
4375      * don't worry about that case here.  Worst case, R hangs onto URI_CHUNK-1
4376      * more jschars than it needs.
4377      */
4378     chars = (jschar *) JS_realloc(cx, R->chars, (R->length+1) * sizeof(jschar));
4379     if (chars)
4380         R->chars = chars;
4381     *rval = STRING_TO_JSVAL(R);
4382     return JS_TRUE;
4384 bad:
4385     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_URI);
4386     return JS_FALSE;
4389 static JSBool
4390 str_decodeURI(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
4391               jsval *rval)
4393     JSString *str;
4395     str = js_ValueToString(cx, argv[0]);
4396     if (!str)
4397         return JS_FALSE;
4398     return Decode(cx, str, js_uriReservedPlusPound_ucstr, rval);
4401 static JSBool
4402 str_decodeURI_Component(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
4403                         jsval *rval)
4405     JSString *str;
4407     str = js_ValueToString(cx, argv[0]);
4408     if (!str)
4409         return JS_FALSE;
4410     return Decode(cx, str, js_empty_ucstr, rval);
4413 static JSBool
4414 str_encodeURI(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
4415               jsval *rval)
4417     JSString *str;
4419     str = js_ValueToString(cx, argv[0]);
4420     if (!str)
4421         return JS_FALSE;
4422     return Encode(cx, str, js_uriReservedPlusPound_ucstr, js_uriUnescaped_ucstr,
4423                   rval);
4426 static JSBool
4427 str_encodeURI_Component(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
4428                         jsval *rval)
4430     JSString *str;
4432     str = js_ValueToString(cx, argv[0]);
4433     if (!str)
4434         return JS_FALSE;
4435     return Encode(cx, str, js_uriUnescaped_ucstr, NULL, rval);
4438 /*
4439  * Convert one UCS-4 char and write it into a UTF-8 buffer, which must be at
4440  * least 6 bytes long.  Return the number of UTF-8 bytes of data written.
4441  */
4442 static int
4443 OneUcs4ToUtf8Char(uint8 *utf8Buffer, uint32 ucs4Char)
4445     int utf8Length = 1;
4447     JS_ASSERT(ucs4Char <= 0x7FFFFFFF);
4448     if (ucs4Char < 0x80) {
4449         *utf8Buffer = (uint8)ucs4Char;
4450     } else {
4451         int i;
4452         uint32 a = ucs4Char >> 11;
4453         utf8Length = 2;
4454         while (a) {
4455             a >>= 5;
4456             utf8Length++;
4457         }
4458         i = utf8Length;
4459         while (--i) {
4460             utf8Buffer[i] = (uint8)((ucs4Char & 0x3F) | 0x80);
4461             ucs4Char >>= 6;
4462         }
4463         *utf8Buffer = (uint8)(0x100 - (1 << (8-utf8Length)) + ucs4Char);
4464     }
4465     return utf8Length;
4468 /*
4469  * Convert a utf8 character sequence into a UCS-4 character and return that
4470  * character.  It is assumed that the caller already checked that the sequence
4471  * is valid.
4472  */
4473 static uint32
4474 Utf8ToOneUcs4Char(const uint8 *utf8Buffer, int utf8Length)
4476     uint32 ucs4Char;
4477     uint32 minucs4Char;
4478     /* from Unicode 3.1, non-shortest form is illegal */
4479     static const uint32 minucs4Table[] = {
4480         0x00000080, 0x00000800, 0x0001000, 0x0020000, 0x0400000
4481     };
4483     JS_ASSERT(utf8Length >= 1 && utf8Length <= 6);
4484     if (utf8Length == 1) {
4485         ucs4Char = *utf8Buffer;
4486         JS_ASSERT(!(ucs4Char & 0x80));
4487     } else {
4488         JS_ASSERT((*utf8Buffer & (0x100 - (1 << (7-utf8Length)))) ==
4489                   (0x100 - (1 << (8-utf8Length))));
4490         ucs4Char = *utf8Buffer++ & ((1<<(7-utf8Length))-1);
4491         minucs4Char = minucs4Table[utf8Length-2];
4492         while (--utf8Length) {
4493             JS_ASSERT((*utf8Buffer & 0xC0) == 0x80);
4494             ucs4Char = ucs4Char<<6 | (*utf8Buffer++ & 0x3F);
4495         }
4496         if (ucs4Char < minucs4Char || 
4497             ucs4Char == 0xFFFE || ucs4Char == 0xFFFF) {
4498             ucs4Char = 0xFFFD;
4499         }
4500     }
4501     return ucs4Char;