|
|
1.1 ! root 1: ! 2: /* A Bison parser, made from OSUnserializeXML.y ! 3: by GNU Bison version 1.28 */ ! 4: ! 5: #define YYBISON 1 /* Identify Bison output. */ ! 6: ! 7: #define yyparse OSUnserializeXMLparse ! 8: #define yylex OSUnserializeXMLlex ! 9: #define yyerror OSUnserializeXMLerror ! 10: #define yylval OSUnserializeXMLlval ! 11: #define yychar OSUnserializeXMLchar ! 12: #define yydebug OSUnserializeXMLdebug ! 13: #define yynerrs OSUnserializeXMLnerrs ! 14: #define KEY 257 ! 15: #define NUMBER 258 ! 16: #define STRING 259 ! 17: #define DATA 260 ! 18: #define IDREF 261 ! 19: #define BOOLEAN 262 ! 20: #define SYNTAX_ERROR 263 ! 21: ! 22: #line 49 "OSUnserializeXML.y" ! 23: ! 24: #include <string.h> ! 25: #include <libkern/c++/OSMetaClass.h> ! 26: #include <libkern/c++/OSContainers.h> ! 27: #include <libkern/c++/OSLib.h> ! 28: ! 29: typedef struct object { ! 30: struct object *next; ! 31: struct object *free; ! 32: struct object *elements; ! 33: OSObject *object; ! 34: const OSSymbol *key; // for dictionary ! 35: int size; ! 36: void *data; // for data ! 37: char *string; // for string & symbol ! 38: long long number; // for number ! 39: int idref; ! 40: } object_t; ! 41: ! 42: static int yyparse(); ! 43: static int yyerror(char *s); ! 44: static int yylex(); ! 45: ! 46: static object_t * newObject(); ! 47: static void freeObject(object_t *o); ! 48: ! 49: static object_t *buildOSDictionary(object_t *); ! 50: static object_t *buildOSArray(object_t *); ! 51: static object_t *buildOSSet(object_t *); ! 52: static object_t *buildOSString(object_t *); ! 53: static object_t *buildKey(object_t *); ! 54: static object_t *buildOSData(object_t *); ! 55: static object_t *buildOSNumber(object_t *); ! 56: static object_t *buildOSBoolean(object_t *o); ! 57: ! 58: static void rememberObject(int, OSObject *); ! 59: static object_t *retrieveObject(int); ! 60: ! 61: // resultant object of parsed text ! 62: static OSObject *parsedObject; ! 63: ! 64: #define YYSTYPE object_t * ! 65: ! 66: extern "C" { ! 67: extern void *kern_os_malloc(size_t size); ! 68: extern void *kern_os_realloc(void * addr, size_t size); ! 69: extern void kern_os_free(void * addr); ! 70: ! 71: //XXX shouldn't have to define these ! 72: extern long strtol(const char *, char **, int); ! 73: extern unsigned long strtoul(const char *, char **, int); ! 74: ! 75: } /* extern "C" */ ! 76: ! 77: #define malloc(s) kern_os_malloc(s) ! 78: #define realloc(a, s) kern_os_realloc(a, s) ! 79: #define free(a) kern_os_free(a) ! 80: ! 81: #ifndef YYSTYPE ! 82: #define YYSTYPE int ! 83: #endif ! 84: #include <stddef.h> ! 85: ! 86: #ifndef __cplusplus ! 87: #ifndef __STDC__ ! 88: #define const ! 89: #endif ! 90: #endif ! 91: ! 92: ! 93: ! 94: #define YYFINAL 37 ! 95: #define YYFLAG -32768 ! 96: #define YYNTBASE 16 ! 97: ! 98: #define YYTRANSLATE(x) ((unsigned)(x) <= 263 ? yytranslate[x] : 30) ! 99: ! 100: static const char yytranslate[] = { 0, ! 101: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 102: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 103: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 104: 2, 2, 2, 2, 2, 2, 2, 2, 2, 12, ! 105: 13, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 106: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 107: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 108: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 109: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 110: 14, 2, 15, 2, 2, 2, 2, 2, 2, 2, ! 111: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 112: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 113: 2, 2, 10, 2, 11, 2, 2, 2, 2, 2, ! 114: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 115: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 116: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 117: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 118: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 119: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 120: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 121: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 122: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 123: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 124: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 125: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ! 126: 2, 2, 2, 2, 2, 1, 3, 4, 5, 6, ! 127: 7, 8, 9 ! 128: }; ! 129: ! 130: #if YYDEBUG != 0 ! 131: static const short yyprhs[] = { 0, ! 132: 0, 1, 3, 5, 7, 9, 11, 13, 15, 17, ! 133: 19, 21, 24, 28, 30, 33, 36, 38, 41, 45, ! 134: 48, 52, 54, 57, 59, 61, 63, 65 ! 135: }; ! 136: ! 137: static const short yyrhs[] = { -1, ! 138: 17, 0, 9, 0, 18, 0, 22, 0, 23, 0, ! 139: 27, 0, 26, 0, 25, 0, 29, 0, 28, 0, ! 140: 10, 11, 0, 10, 19, 11, 0, 20, 0, 19, ! 141: 20, 0, 21, 17, 0, 3, 0, 12, 13, 0, ! 142: 12, 24, 13, 0, 14, 15, 0, 14, 24, 15, ! 143: 0, 17, 0, 24, 17, 0, 4, 0, 6, 0, ! 144: 5, 0, 7, 0, 8, 0 ! 145: }; ! 146: ! 147: #endif ! 148: ! 149: #if YYDEBUG != 0 ! 150: static const short yyrline[] = { 0, ! 151: 117, 118, 123, 129, 130, 131, 132, 133, 134, 135, ! 152: 136, 149, 152, 157, 158, 163, 171, 176, 179, 184, ! 153: 187, 192, 195, 202, 205, 208, 211, 214 ! 154: }; ! 155: #endif ! 156: ! 157: ! 158: #if YYDEBUG != 0 || defined (YYERROR_VERBOSE) ! 159: ! 160: static const char * const yytname[] = { "$","error","$undefined.","KEY","NUMBER", ! 161: "STRING","DATA","IDREF","BOOLEAN","SYNTAX_ERROR","'{'","'}'","'('","')'","'['", ! 162: "']'","input","object","dict","pairs","pair","key","array","set","elements", ! 163: "number","data","string","idref","boolean", NULL ! 164: }; ! 165: #endif ! 166: ! 167: static const short yyr1[] = { 0, ! 168: 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, ! 169: 17, 18, 18, 19, 19, 20, 21, 22, 22, 23, ! 170: 23, 24, 24, 25, 26, 27, 28, 29 ! 171: }; ! 172: ! 173: static const short yyr2[] = { 0, ! 174: 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, ! 175: 1, 2, 3, 1, 2, 2, 1, 2, 3, 2, ! 176: 3, 1, 2, 1, 1, 1, 1, 1 ! 177: }; ! 178: ! 179: static const short yydefact[] = { 1, ! 180: 24, 26, 25, 27, 28, 3, 0, 0, 0, 2, ! 181: 4, 5, 6, 9, 8, 7, 11, 10, 17, 12, ! 182: 0, 14, 0, 18, 22, 0, 20, 0, 13, 15, ! 183: 16, 19, 23, 21, 0, 0, 0 ! 184: }; ! 185: ! 186: static const short yydefgoto[] = { 35, ! 187: 25, 11, 21, 22, 23, 12, 13, 26, 14, 15, ! 188: 16, 17, 18 ! 189: }; ! 190: ! 191: static const short yypact[] = { 25, ! 192: -32768,-32768,-32768,-32768,-32768,-32768, 16, 36, -3,-32768, ! 193: -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, ! 194: 64,-32768, 58,-32768,-32768, 47,-32768, 10,-32768,-32768, ! 195: -32768,-32768,-32768,-32768, 6, 8,-32768 ! 196: }; ! 197: ! 198: static const short yypgoto[] = {-32768, ! 199: 0,-32768,-32768, -11,-32768,-32768,-32768, 4,-32768,-32768, ! 200: -32768,-32768,-32768 ! 201: }; ! 202: ! 203: ! 204: #define YYLAST 75 ! 205: ! 206: ! 207: static const short yytable[] = { 10, ! 208: 1, 2, 3, 4, 5, 36, 7, 37, 8, 30, ! 209: 9, 27, 28, 1, 2, 3, 4, 5, 19, 7, ! 210: 0, 8, 31, 9, 34, 33, 20, 33, 1, 2, ! 211: 3, 4, 5, 6, 7, 0, 8, 0, 9, 1, ! 212: 2, 3, 4, 5, 0, 7, 0, 8, 24, 9, ! 213: 1, 2, 3, 4, 5, 0, 7, 0, 8, 32, ! 214: 9, 1, 2, 3, 4, 5, 19, 7, 0, 8, ! 215: 0, 9, 0, 0, 29 ! 216: }; ! 217: ! 218: static const short yycheck[] = { 0, ! 219: 4, 5, 6, 7, 8, 0, 10, 0, 12, 21, ! 220: 14, 15, 9, 4, 5, 6, 7, 8, 3, 10, ! 221: -1, 12, 23, 14, 15, 26, 11, 28, 4, 5, ! 222: 6, 7, 8, 9, 10, -1, 12, -1, 14, 4, ! 223: 5, 6, 7, 8, -1, 10, -1, 12, 13, 14, ! 224: 4, 5, 6, 7, 8, -1, 10, -1, 12, 13, ! 225: 14, 4, 5, 6, 7, 8, 3, 10, -1, 12, ! 226: -1, 14, -1, -1, 11 ! 227: }; ! 228: /* -*-C-*- Note some compilers choke on comments on `#line' lines. */ ! 229: #line 3 "/usr/share/bison.simple" ! 230: /* This file comes from bison-1.28. */ ! 231: ! 232: /* Skeleton output parser for bison, ! 233: Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. ! 234: ! 235: This program is free software; you can redistribute it and/or modify ! 236: it under the terms of the GNU General Public License as published by ! 237: the Free Software Foundation; either version 2, or (at your option) ! 238: any later version. ! 239: ! 240: This program is distributed in the hope that it will be useful, ! 241: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 242: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 243: GNU General Public License for more details. ! 244: ! 245: You should have received a copy of the GNU General Public License ! 246: along with this program; if not, write to the Free Software ! 247: Foundation, Inc., 59 Temple Place - Suite 330, ! 248: Boston, MA 02111-1307, USA. */ ! 249: ! 250: /* As a special exception, when this file is copied by Bison into a ! 251: Bison output file, you may use that output file without restriction. ! 252: This special exception was added by the Free Software Foundation ! 253: in version 1.24 of Bison. */ ! 254: ! 255: /* This is the parser code that is written into each bison parser ! 256: when the %semantic_parser declaration is not specified in the grammar. ! 257: It was written by Richard Stallman by simplifying the hairy parser ! 258: used when %semantic_parser is specified. */ ! 259: ! 260: #ifndef YYSTACK_USE_ALLOCA ! 261: #ifdef alloca ! 262: #define YYSTACK_USE_ALLOCA ! 263: #else /* alloca not defined */ ! 264: #ifdef __GNUC__ ! 265: #define YYSTACK_USE_ALLOCA ! 266: #define alloca __builtin_alloca ! 267: #else /* not GNU C. */ ! 268: #if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) ! 269: #define YYSTACK_USE_ALLOCA ! 270: #include <alloca.h> ! 271: #else /* not sparc */ ! 272: /* We think this test detects Watcom and Microsoft C. */ ! 273: /* This used to test MSDOS, but that is a bad idea ! 274: since that symbol is in the user namespace. */ ! 275: #if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) ! 276: #if 0 /* No need for malloc.h, which pollutes the namespace; ! 277: instead, just don't use alloca. */ ! 278: #include <malloc.h> ! 279: #endif ! 280: #else /* not MSDOS, or __TURBOC__ */ ! 281: #if defined(_AIX) ! 282: /* I don't know what this was needed for, but it pollutes the namespace. ! 283: So I turned it off. rms, 2 May 1997. */ ! 284: /* #include <malloc.h> */ ! 285: #pragma alloca ! 286: #define YYSTACK_USE_ALLOCA ! 287: #else /* not MSDOS, or __TURBOC__, or _AIX */ ! 288: #if 0 ! 289: #ifdef __hpux /* [email protected] says this works for HPUX 9.05 and up, ! 290: and on HPUX 10. Eventually we can turn this on. */ ! 291: #define YYSTACK_USE_ALLOCA ! 292: #define alloca __builtin_alloca ! 293: #endif /* __hpux */ ! 294: #endif ! 295: #endif /* not _AIX */ ! 296: #endif /* not MSDOS, or __TURBOC__ */ ! 297: #endif /* not sparc */ ! 298: #endif /* not GNU C */ ! 299: #endif /* alloca not defined */ ! 300: #endif /* YYSTACK_USE_ALLOCA not defined */ ! 301: ! 302: #ifdef YYSTACK_USE_ALLOCA ! 303: #define YYSTACK_ALLOC alloca ! 304: #else ! 305: #define YYSTACK_ALLOC malloc ! 306: #endif ! 307: ! 308: /* Note: there must be only one dollar sign in this file. ! 309: It is replaced by the list of actions, each action ! 310: as one case of the switch. */ ! 311: ! 312: #define yyerrok (yyerrstatus = 0) ! 313: #define yyclearin (yychar = YYEMPTY) ! 314: #define YYEMPTY -2 ! 315: #define YYEOF 0 ! 316: #define YYACCEPT goto yyacceptlab ! 317: #define YYABORT goto yyabortlab ! 318: #define YYERROR goto yyerrlab1 ! 319: /* Like YYERROR except do call yyerror. ! 320: This remains here temporarily to ease the ! 321: transition to the new meaning of YYERROR, for GCC. ! 322: Once GCC version 2 has supplanted version 1, this can go. */ ! 323: #define YYFAIL goto yyerrlab ! 324: #define YYRECOVERING() (!!yyerrstatus) ! 325: #define YYBACKUP(token, value) \ ! 326: do \ ! 327: if (yychar == YYEMPTY && yylen == 1) \ ! 328: { yychar = (token), yylval = (value); \ ! 329: yychar1 = YYTRANSLATE (yychar); \ ! 330: YYPOPSTACK; \ ! 331: goto yybackup; \ ! 332: } \ ! 333: else \ ! 334: { yyerror ("syntax error: cannot back up"); YYERROR; } \ ! 335: while (0) ! 336: ! 337: #define YYTERROR 1 ! 338: #define YYERRCODE 256 ! 339: ! 340: #ifndef YYPURE ! 341: #define YYLEX yylex() ! 342: #endif ! 343: ! 344: #ifdef YYPURE ! 345: #ifdef YYLSP_NEEDED ! 346: #ifdef YYLEX_PARAM ! 347: #define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) ! 348: #else ! 349: #define YYLEX yylex(&yylval, &yylloc) ! 350: #endif ! 351: #else /* not YYLSP_NEEDED */ ! 352: #ifdef YYLEX_PARAM ! 353: #define YYLEX yylex(&yylval, YYLEX_PARAM) ! 354: #else ! 355: #define YYLEX yylex(&yylval) ! 356: #endif ! 357: #endif /* not YYLSP_NEEDED */ ! 358: #endif ! 359: ! 360: /* If nonreentrant, generate the variables here */ ! 361: ! 362: #ifndef YYPURE ! 363: ! 364: int yychar; /* the lookahead symbol */ ! 365: YYSTYPE yylval; /* the semantic value of the */ ! 366: /* lookahead symbol */ ! 367: ! 368: #ifdef YYLSP_NEEDED ! 369: YYLTYPE yylloc; /* location data for the lookahead */ ! 370: /* symbol */ ! 371: #endif ! 372: ! 373: int yynerrs; /* number of parse errors so far */ ! 374: #endif /* not YYPURE */ ! 375: ! 376: #if YYDEBUG != 0 ! 377: int yydebug; /* nonzero means print parse trace */ ! 378: /* Since this is uninitialized, it does not stop multiple parsers ! 379: from coexisting. */ ! 380: #endif ! 381: ! 382: /* YYINITDEPTH indicates the initial size of the parser's stacks */ ! 383: ! 384: #ifndef YYINITDEPTH ! 385: #define YYINITDEPTH 200 ! 386: #endif ! 387: ! 388: /* YYMAXDEPTH is the maximum size the stacks can grow to ! 389: (effective only if the built-in stack extension method is used). */ ! 390: ! 391: #if YYMAXDEPTH == 0 ! 392: #undef YYMAXDEPTH ! 393: #endif ! 394: ! 395: #ifndef YYMAXDEPTH ! 396: #define YYMAXDEPTH 10000 ! 397: #endif ! 398: ! 399: /* Define __yy_memcpy. Note that the size argument ! 400: should be passed with type unsigned int, because that is what the non-GCC ! 401: definitions require. With GCC, __builtin_memcpy takes an arg ! 402: of type size_t, but it can handle unsigned int. */ ! 403: ! 404: #if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ ! 405: #define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) ! 406: #else /* not GNU C or C++ */ ! 407: #ifndef __cplusplus ! 408: ! 409: /* This is the most reliable way to avoid incompatibilities ! 410: in available built-in functions on various systems. */ ! 411: static void ! 412: __yy_memcpy (to, from, count) ! 413: char *to; ! 414: char *from; ! 415: unsigned int count; ! 416: { ! 417: register char *f = from; ! 418: register char *t = to; ! 419: register int i = count; ! 420: ! 421: while (i-- > 0) ! 422: *t++ = *f++; ! 423: } ! 424: ! 425: #else /* __cplusplus */ ! 426: ! 427: /* This is the most reliable way to avoid incompatibilities ! 428: in available built-in functions on various systems. */ ! 429: static void ! 430: __yy_memcpy (char *to, char *from, unsigned int count) ! 431: { ! 432: register char *t = to; ! 433: register char *f = from; ! 434: register int i = count; ! 435: ! 436: while (i-- > 0) ! 437: *t++ = *f++; ! 438: } ! 439: ! 440: #endif ! 441: #endif ! 442: ! 443: #line 217 "/usr/share/bison.simple" ! 444: ! 445: /* The user can define YYPARSE_PARAM as the name of an argument to be passed ! 446: into yyparse. The argument should have type void *. ! 447: It should actually point to an object. ! 448: Grammar actions can access the variable by casting it ! 449: to the proper pointer type. */ ! 450: ! 451: #ifdef YYPARSE_PARAM ! 452: #ifdef __cplusplus ! 453: #define YYPARSE_PARAM_ARG void *YYPARSE_PARAM ! 454: #define YYPARSE_PARAM_DECL ! 455: #else /* not __cplusplus */ ! 456: #define YYPARSE_PARAM_ARG YYPARSE_PARAM ! 457: #define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; ! 458: #endif /* not __cplusplus */ ! 459: #else /* not YYPARSE_PARAM */ ! 460: #define YYPARSE_PARAM_ARG ! 461: #define YYPARSE_PARAM_DECL ! 462: #endif /* not YYPARSE_PARAM */ ! 463: ! 464: /* Prevent warning if -Wstrict-prototypes. */ ! 465: #ifdef __GNUC__ ! 466: #ifdef YYPARSE_PARAM ! 467: int yyparse (void *); ! 468: #else ! 469: int yyparse (void); ! 470: #endif ! 471: #endif ! 472: ! 473: int ! 474: yyparse(YYPARSE_PARAM_ARG) ! 475: YYPARSE_PARAM_DECL ! 476: { ! 477: register int yystate; ! 478: register int yyn; ! 479: register short *yyssp; ! 480: register YYSTYPE *yyvsp; ! 481: int yyerrstatus; /* number of tokens to shift before error messages enabled */ ! 482: int yychar1 = 0; /* lookahead token as an internal (translated) token number */ ! 483: ! 484: short yyssa[YYINITDEPTH]; /* the state stack */ ! 485: YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ ! 486: ! 487: short *yyss = yyssa; /* refer to the stacks thru separate pointers */ ! 488: YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ ! 489: ! 490: #ifdef YYLSP_NEEDED ! 491: YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ ! 492: YYLTYPE *yyls = yylsa; ! 493: YYLTYPE *yylsp; ! 494: ! 495: #define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) ! 496: #else ! 497: #define YYPOPSTACK (yyvsp--, yyssp--) ! 498: #endif ! 499: ! 500: int yystacksize = YYINITDEPTH; ! 501: int yyfree_stacks = 0; ! 502: ! 503: #ifdef YYPURE ! 504: int yychar; ! 505: YYSTYPE yylval; ! 506: int yynerrs; ! 507: #ifdef YYLSP_NEEDED ! 508: YYLTYPE yylloc; ! 509: #endif ! 510: #endif ! 511: ! 512: YYSTYPE yyval; /* the variable used to return */ ! 513: /* semantic values from the action */ ! 514: /* routines */ ! 515: ! 516: int yylen; ! 517: ! 518: #if YYDEBUG != 0 ! 519: if (yydebug) ! 520: fprintf(stderr, "Starting parse\n"); ! 521: #endif ! 522: ! 523: yystate = 0; ! 524: yyerrstatus = 0; ! 525: yynerrs = 0; ! 526: yychar = YYEMPTY; /* Cause a token to be read. */ ! 527: ! 528: /* Initialize stack pointers. ! 529: Waste one element of value and location stack ! 530: so that they stay on the same level as the state stack. ! 531: The wasted elements are never initialized. */ ! 532: ! 533: yyssp = yyss - 1; ! 534: yyvsp = yyvs; ! 535: #ifdef YYLSP_NEEDED ! 536: yylsp = yyls; ! 537: #endif ! 538: ! 539: /* Push a new state, which is found in yystate . */ ! 540: /* In all cases, when you get here, the value and location stacks ! 541: have just been pushed. so pushing a state here evens the stacks. */ ! 542: yynewstate: ! 543: ! 544: *++yyssp = yystate; ! 545: ! 546: if (yyssp >= yyss + yystacksize - 1) ! 547: { ! 548: /* Give user a chance to reallocate the stack */ ! 549: /* Use copies of these so that the &'s don't force the real ones into memory. */ ! 550: YYSTYPE *yyvs1 = yyvs; ! 551: short *yyss1 = yyss; ! 552: #ifdef YYLSP_NEEDED ! 553: YYLTYPE *yyls1 = yyls; ! 554: #endif ! 555: ! 556: /* Get the current used size of the three stacks, in elements. */ ! 557: int size = yyssp - yyss + 1; ! 558: ! 559: #ifdef yyoverflow ! 560: /* Each stack pointer address is followed by the size of ! 561: the data in use in that stack, in bytes. */ ! 562: #ifdef YYLSP_NEEDED ! 563: /* This used to be a conditional around just the two extra args, ! 564: but that might be undefined if yyoverflow is a macro. */ ! 565: yyoverflow("parser stack overflow", ! 566: &yyss1, size * sizeof (*yyssp), ! 567: &yyvs1, size * sizeof (*yyvsp), ! 568: &yyls1, size * sizeof (*yylsp), ! 569: &yystacksize); ! 570: #else ! 571: yyoverflow("parser stack overflow", ! 572: &yyss1, size * sizeof (*yyssp), ! 573: &yyvs1, size * sizeof (*yyvsp), ! 574: &yystacksize); ! 575: #endif ! 576: ! 577: yyss = yyss1; yyvs = yyvs1; ! 578: #ifdef YYLSP_NEEDED ! 579: yyls = yyls1; ! 580: #endif ! 581: #else /* no yyoverflow */ ! 582: /* Extend the stack our own way. */ ! 583: if (yystacksize >= YYMAXDEPTH) ! 584: { ! 585: yyerror("parser stack overflow"); ! 586: if (yyfree_stacks) ! 587: { ! 588: free (yyss); ! 589: free (yyvs); ! 590: #ifdef YYLSP_NEEDED ! 591: free (yyls); ! 592: #endif ! 593: } ! 594: return 2; ! 595: } ! 596: yystacksize *= 2; ! 597: if (yystacksize > YYMAXDEPTH) ! 598: yystacksize = YYMAXDEPTH; ! 599: #ifndef YYSTACK_USE_ALLOCA ! 600: yyfree_stacks = 1; ! 601: #endif ! 602: yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); ! 603: __yy_memcpy ((char *)yyss, (char *)yyss1, ! 604: size * (unsigned int) sizeof (*yyssp)); ! 605: yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); ! 606: __yy_memcpy ((char *)yyvs, (char *)yyvs1, ! 607: size * (unsigned int) sizeof (*yyvsp)); ! 608: #ifdef YYLSP_NEEDED ! 609: yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); ! 610: __yy_memcpy ((char *)yyls, (char *)yyls1, ! 611: size * (unsigned int) sizeof (*yylsp)); ! 612: #endif ! 613: #endif /* no yyoverflow */ ! 614: ! 615: yyssp = yyss + size - 1; ! 616: yyvsp = yyvs + size - 1; ! 617: #ifdef YYLSP_NEEDED ! 618: yylsp = yyls + size - 1; ! 619: #endif ! 620: ! 621: #if YYDEBUG != 0 ! 622: if (yydebug) ! 623: fprintf(stderr, "Stack size increased to %d\n", yystacksize); ! 624: #endif ! 625: ! 626: if (yyssp >= yyss + yystacksize - 1) ! 627: YYABORT; ! 628: } ! 629: ! 630: #if YYDEBUG != 0 ! 631: if (yydebug) ! 632: fprintf(stderr, "Entering state %d\n", yystate); ! 633: #endif ! 634: ! 635: goto yybackup; ! 636: yybackup: ! 637: ! 638: /* Do appropriate processing given the current state. */ ! 639: /* Read a lookahead token if we need one and don't already have one. */ ! 640: /* yyresume: */ ! 641: ! 642: /* First try to decide what to do without reference to lookahead token. */ ! 643: ! 644: yyn = yypact[yystate]; ! 645: if (yyn == YYFLAG) ! 646: goto yydefault; ! 647: ! 648: /* Not known => get a lookahead token if don't already have one. */ ! 649: ! 650: /* yychar is either YYEMPTY or YYEOF ! 651: or a valid token in external form. */ ! 652: ! 653: if (yychar == YYEMPTY) ! 654: { ! 655: #if YYDEBUG != 0 ! 656: if (yydebug) ! 657: fprintf(stderr, "Reading a token: "); ! 658: #endif ! 659: yychar = YYLEX; ! 660: } ! 661: ! 662: /* Convert token to internal form (in yychar1) for indexing tables with */ ! 663: ! 664: if (yychar <= 0) /* This means end of input. */ ! 665: { ! 666: yychar1 = 0; ! 667: yychar = YYEOF; /* Don't call YYLEX any more */ ! 668: ! 669: #if YYDEBUG != 0 ! 670: if (yydebug) ! 671: fprintf(stderr, "Now at end of input.\n"); ! 672: #endif ! 673: } ! 674: else ! 675: { ! 676: yychar1 = YYTRANSLATE(yychar); ! 677: ! 678: #if YYDEBUG != 0 ! 679: if (yydebug) ! 680: { ! 681: fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); ! 682: /* Give the individual parser a way to print the precise meaning ! 683: of a token, for further debugging info. */ ! 684: #ifdef YYPRINT ! 685: YYPRINT (stderr, yychar, yylval); ! 686: #endif ! 687: fprintf (stderr, ")\n"); ! 688: } ! 689: #endif ! 690: } ! 691: ! 692: yyn += yychar1; ! 693: if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) ! 694: goto yydefault; ! 695: ! 696: yyn = yytable[yyn]; ! 697: ! 698: /* yyn is what to do for this token type in this state. ! 699: Negative => reduce, -yyn is rule number. ! 700: Positive => shift, yyn is new state. ! 701: New state is final state => don't bother to shift, ! 702: just return success. ! 703: 0, or most negative number => error. */ ! 704: ! 705: if (yyn < 0) ! 706: { ! 707: if (yyn == YYFLAG) ! 708: goto yyerrlab; ! 709: yyn = -yyn; ! 710: goto yyreduce; ! 711: } ! 712: else if (yyn == 0) ! 713: goto yyerrlab; ! 714: ! 715: if (yyn == YYFINAL) ! 716: YYACCEPT; ! 717: ! 718: /* Shift the lookahead token. */ ! 719: ! 720: #if YYDEBUG != 0 ! 721: if (yydebug) ! 722: fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); ! 723: #endif ! 724: ! 725: /* Discard the token being shifted unless it is eof. */ ! 726: if (yychar != YYEOF) ! 727: yychar = YYEMPTY; ! 728: ! 729: *++yyvsp = yylval; ! 730: #ifdef YYLSP_NEEDED ! 731: *++yylsp = yylloc; ! 732: #endif ! 733: ! 734: /* count tokens shifted since error; after three, turn off error status. */ ! 735: if (yyerrstatus) yyerrstatus--; ! 736: ! 737: yystate = yyn; ! 738: goto yynewstate; ! 739: ! 740: /* Do the default action for the current state. */ ! 741: yydefault: ! 742: ! 743: yyn = yydefact[yystate]; ! 744: if (yyn == 0) ! 745: goto yyerrlab; ! 746: ! 747: /* Do a reduction. yyn is the number of a rule to reduce with. */ ! 748: yyreduce: ! 749: yylen = yyr2[yyn]; ! 750: if (yylen > 0) ! 751: yyval = yyvsp[1-yylen]; /* implement default value of the action */ ! 752: ! 753: #if YYDEBUG != 0 ! 754: if (yydebug) ! 755: { ! 756: int i; ! 757: ! 758: fprintf (stderr, "Reducing via rule %d (line %d), ", ! 759: yyn, yyrline[yyn]); ! 760: ! 761: /* Print the symbols being reduced, and their result. */ ! 762: for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) ! 763: fprintf (stderr, "%s ", yytname[yyrhs[i]]); ! 764: fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); ! 765: } ! 766: #endif ! 767: ! 768: ! 769: switch (yyn) { ! 770: ! 771: case 1: ! 772: #line 117 "OSUnserializeXML.y" ! 773: { parsedObject = (OSObject *)NULL; YYACCEPT; ; ! 774: break;} ! 775: case 2: ! 776: #line 118 "OSUnserializeXML.y" ! 777: { parsedObject = yyvsp[0]->object; ! 778: yyvsp[0]->object = 0; ! 779: freeObject(yyvsp[0]); ! 780: YYACCEPT; ! 781: ; ! 782: break;} ! 783: case 3: ! 784: #line 123 "OSUnserializeXML.y" ! 785: { ! 786: yyerror("syntax error"); ! 787: YYERROR; ! 788: ; ! 789: break;} ! 790: case 4: ! 791: #line 129 "OSUnserializeXML.y" ! 792: { yyval = buildOSDictionary(yyvsp[0]); ; ! 793: break;} ! 794: case 5: ! 795: #line 130 "OSUnserializeXML.y" ! 796: { yyval = buildOSArray(yyvsp[0]); ; ! 797: break;} ! 798: case 6: ! 799: #line 131 "OSUnserializeXML.y" ! 800: { yyval = buildOSSet(yyvsp[0]); ; ! 801: break;} ! 802: case 7: ! 803: #line 132 "OSUnserializeXML.y" ! 804: { yyval = buildOSString(yyvsp[0]); ; ! 805: break;} ! 806: case 8: ! 807: #line 133 "OSUnserializeXML.y" ! 808: { yyval = buildOSData(yyvsp[0]); ; ! 809: break;} ! 810: case 9: ! 811: #line 134 "OSUnserializeXML.y" ! 812: { yyval = buildOSNumber(yyvsp[0]); ; ! 813: break;} ! 814: case 10: ! 815: #line 135 "OSUnserializeXML.y" ! 816: { yyval = buildOSBoolean(yyvsp[0]); ; ! 817: break;} ! 818: case 11: ! 819: #line 136 "OSUnserializeXML.y" ! 820: { yyval = retrieveObject(yyvsp[0]->idref); ! 821: if (yyval) { ! 822: yyval->object->retain(); ! 823: } else { ! 824: yyerror("forward reference detected"); ! 825: YYERROR; ! 826: } ! 827: freeObject(yyvsp[0]); ! 828: ; ! 829: break;} ! 830: case 12: ! 831: #line 149 "OSUnserializeXML.y" ! 832: { yyval = yyvsp[-1]; ! 833: yyval->elements = NULL; ! 834: ; ! 835: break;} ! 836: case 13: ! 837: #line 152 "OSUnserializeXML.y" ! 838: { yyval = yyvsp[-2]; ! 839: yyval->elements = yyvsp[-1]; ! 840: ; ! 841: break;} ! 842: case 15: ! 843: #line 158 "OSUnserializeXML.y" ! 844: { yyval = yyvsp[0]; ! 845: yyval->next = yyvsp[-1]; ! 846: ; ! 847: break;} ! 848: case 16: ! 849: #line 163 "OSUnserializeXML.y" ! 850: { yyval = yyvsp[-1]; ! 851: yyval->next = NULL; ! 852: yyval->object = yyvsp[0]->object; ! 853: yyvsp[0]->object = 0; ! 854: freeObject(yyvsp[0]); ! 855: ; ! 856: break;} ! 857: case 17: ! 858: #line 171 "OSUnserializeXML.y" ! 859: { yyval = buildKey(yyvsp[0]); ; ! 860: break;} ! 861: case 18: ! 862: #line 176 "OSUnserializeXML.y" ! 863: { yyval = yyvsp[-1]; ! 864: yyval->elements = NULL; ! 865: ; ! 866: break;} ! 867: case 19: ! 868: #line 179 "OSUnserializeXML.y" ! 869: { yyval = yyvsp[-2]; ! 870: yyval->elements = yyvsp[-1]; ! 871: ; ! 872: break;} ! 873: case 20: ! 874: #line 184 "OSUnserializeXML.y" ! 875: { yyval = yyvsp[-1]; ! 876: yyval->elements = NULL; ! 877: ; ! 878: break;} ! 879: case 21: ! 880: #line 187 "OSUnserializeXML.y" ! 881: { yyval = yyvsp[-2]; ! 882: yyval->elements = yyvsp[-1]; ! 883: ; ! 884: break;} ! 885: case 22: ! 886: #line 192 "OSUnserializeXML.y" ! 887: { yyval = yyvsp[0]; ! 888: yyval->next = NULL; ! 889: ; ! 890: break;} ! 891: case 23: ! 892: #line 195 "OSUnserializeXML.y" ! 893: { yyval = yyvsp[0]; ! 894: yyval->next = yyvsp[-1]; ! 895: ; ! 896: break;} ! 897: } ! 898: /* the action file gets copied in in place of this dollarsign */ ! 899: #line 543 "/usr/share/bison.simple" ! 900: ! 901: yyvsp -= yylen; ! 902: yyssp -= yylen; ! 903: #ifdef YYLSP_NEEDED ! 904: yylsp -= yylen; ! 905: #endif ! 906: ! 907: #if YYDEBUG != 0 ! 908: if (yydebug) ! 909: { ! 910: short *ssp1 = yyss - 1; ! 911: fprintf (stderr, "state stack now"); ! 912: while (ssp1 != yyssp) ! 913: fprintf (stderr, " %d", *++ssp1); ! 914: fprintf (stderr, "\n"); ! 915: } ! 916: #endif ! 917: ! 918: *++yyvsp = yyval; ! 919: ! 920: #ifdef YYLSP_NEEDED ! 921: yylsp++; ! 922: if (yylen == 0) ! 923: { ! 924: yylsp->first_line = yylloc.first_line; ! 925: yylsp->first_column = yylloc.first_column; ! 926: yylsp->last_line = (yylsp-1)->last_line; ! 927: yylsp->last_column = (yylsp-1)->last_column; ! 928: yylsp->text = 0; ! 929: } ! 930: else ! 931: { ! 932: yylsp->last_line = (yylsp+yylen-1)->last_line; ! 933: yylsp->last_column = (yylsp+yylen-1)->last_column; ! 934: } ! 935: #endif ! 936: ! 937: /* Now "shift" the result of the reduction. ! 938: Determine what state that goes to, ! 939: based on the state we popped back to ! 940: and the rule number reduced by. */ ! 941: ! 942: yyn = yyr1[yyn]; ! 943: ! 944: yystate = yypgoto[yyn - YYNTBASE] + *yyssp; ! 945: if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) ! 946: yystate = yytable[yystate]; ! 947: else ! 948: yystate = yydefgoto[yyn - YYNTBASE]; ! 949: ! 950: goto yynewstate; ! 951: ! 952: yyerrlab: /* here on detecting error */ ! 953: ! 954: if (! yyerrstatus) ! 955: /* If not already recovering from an error, report this error. */ ! 956: { ! 957: ++yynerrs; ! 958: ! 959: #ifdef YYERROR_VERBOSE ! 960: yyn = yypact[yystate]; ! 961: ! 962: if (yyn > YYFLAG && yyn < YYLAST) ! 963: { ! 964: int size = 0; ! 965: char *msg; ! 966: int x, count; ! 967: ! 968: count = 0; ! 969: /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ ! 970: for (x = (yyn < 0 ? -yyn : 0); ! 971: x < (sizeof(yytname) / sizeof(char *)); x++) ! 972: if (yycheck[x + yyn] == x) ! 973: size += strlen(yytname[x]) + 15, count++; ! 974: msg = (char *) malloc(size + 15); ! 975: if (msg != 0) ! 976: { ! 977: strcpy(msg, "parse error"); ! 978: ! 979: if (count < 5) ! 980: { ! 981: count = 0; ! 982: for (x = (yyn < 0 ? -yyn : 0); ! 983: x < (sizeof(yytname) / sizeof(char *)); x++) ! 984: if (yycheck[x + yyn] == x) ! 985: { ! 986: strcat(msg, count == 0 ? ", expecting `" : " or `"); ! 987: strcat(msg, yytname[x]); ! 988: strcat(msg, "'"); ! 989: count++; ! 990: } ! 991: } ! 992: yyerror(msg); ! 993: free(msg); ! 994: } ! 995: else ! 996: yyerror ("parse error; also virtual memory exceeded"); ! 997: } ! 998: else ! 999: #endif /* YYERROR_VERBOSE */ ! 1000: yyerror("parse error"); ! 1001: } ! 1002: ! 1003: goto yyerrlab1; ! 1004: yyerrlab1: /* here on error raised explicitly by an action */ ! 1005: ! 1006: if (yyerrstatus == 3) ! 1007: { ! 1008: /* if just tried and failed to reuse lookahead token after an error, discard it. */ ! 1009: ! 1010: /* return failure if at end of input */ ! 1011: if (yychar == YYEOF) ! 1012: YYABORT; ! 1013: ! 1014: #if YYDEBUG != 0 ! 1015: if (yydebug) ! 1016: fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); ! 1017: #endif ! 1018: ! 1019: yychar = YYEMPTY; ! 1020: } ! 1021: ! 1022: /* Else will try to reuse lookahead token ! 1023: after shifting the error token. */ ! 1024: ! 1025: yyerrstatus = 3; /* Each real token shifted decrements this */ ! 1026: ! 1027: goto yyerrhandle; ! 1028: ! 1029: yyerrdefault: /* current state does not do anything special for the error token. */ ! 1030: ! 1031: #if 0 ! 1032: /* This is wrong; only states that explicitly want error tokens ! 1033: should shift them. */ ! 1034: yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ ! 1035: if (yyn) goto yydefault; ! 1036: #endif ! 1037: ! 1038: yyerrpop: /* pop the current state because it cannot handle the error token */ ! 1039: ! 1040: if (yyssp == yyss) YYABORT; ! 1041: yyvsp--; ! 1042: yystate = *--yyssp; ! 1043: #ifdef YYLSP_NEEDED ! 1044: yylsp--; ! 1045: #endif ! 1046: ! 1047: #if YYDEBUG != 0 ! 1048: if (yydebug) ! 1049: { ! 1050: short *ssp1 = yyss - 1; ! 1051: fprintf (stderr, "Error: state stack now"); ! 1052: while (ssp1 != yyssp) ! 1053: fprintf (stderr, " %d", *++ssp1); ! 1054: fprintf (stderr, "\n"); ! 1055: } ! 1056: #endif ! 1057: ! 1058: yyerrhandle: ! 1059: ! 1060: yyn = yypact[yystate]; ! 1061: if (yyn == YYFLAG) ! 1062: goto yyerrdefault; ! 1063: ! 1064: yyn += YYTERROR; ! 1065: if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) ! 1066: goto yyerrdefault; ! 1067: ! 1068: yyn = yytable[yyn]; ! 1069: if (yyn < 0) ! 1070: { ! 1071: if (yyn == YYFLAG) ! 1072: goto yyerrpop; ! 1073: yyn = -yyn; ! 1074: goto yyreduce; ! 1075: } ! 1076: else if (yyn == 0) ! 1077: goto yyerrpop; ! 1078: ! 1079: if (yyn == YYFINAL) ! 1080: YYACCEPT; ! 1081: ! 1082: #if YYDEBUG != 0 ! 1083: if (yydebug) ! 1084: fprintf(stderr, "Shifting error token, "); ! 1085: #endif ! 1086: ! 1087: *++yyvsp = yylval; ! 1088: #ifdef YYLSP_NEEDED ! 1089: *++yylsp = yylloc; ! 1090: #endif ! 1091: ! 1092: yystate = yyn; ! 1093: goto yynewstate; ! 1094: ! 1095: yyacceptlab: ! 1096: /* YYACCEPT comes here. */ ! 1097: if (yyfree_stacks) ! 1098: { ! 1099: free (yyss); ! 1100: free (yyvs); ! 1101: #ifdef YYLSP_NEEDED ! 1102: free (yyls); ! 1103: #endif ! 1104: } ! 1105: return 0; ! 1106: ! 1107: yyabortlab: ! 1108: /* YYABORT comes here. */ ! 1109: if (yyfree_stacks) ! 1110: { ! 1111: free (yyss); ! 1112: free (yyvs); ! 1113: #ifdef YYLSP_NEEDED ! 1114: free (yyls); ! 1115: #endif ! 1116: } ! 1117: return 1; ! 1118: } ! 1119: #line 217 "OSUnserializeXML.y" ! 1120: ! 1121: ! 1122: static int lineNumber = 0; ! 1123: static const char *parseBuffer; ! 1124: static int parseBufferIndex; ! 1125: ! 1126: #define currentChar() (parseBuffer[parseBufferIndex]) ! 1127: #define nextChar() (parseBuffer[++parseBufferIndex]) ! 1128: #define prevChar() (parseBuffer[parseBufferIndex - 1]) ! 1129: ! 1130: #define isSpace(c) ((c) == ' ' || (c) == '\t') ! 1131: #define isAlpha(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z')) ! 1132: #define isDigit(c) ((c) >= '0' && (c) <= '9') ! 1133: #define isAlphaDigit(c) ((c) >= 'a' && (c) <= 'f') ! 1134: #define isHexDigit(c) (isDigit(c) || isAlphaDigit(c)) ! 1135: #define isAlphaNumeric(c) (isAlpha(c) || isDigit(c) || ((c) == '-')) ! 1136: ! 1137: static char yyerror_message[128]; ! 1138: ! 1139: int ! 1140: yyerror(char *s) /* Called by yyparse on error */ ! 1141: { ! 1142: sprintf(yyerror_message, "OSUnserializeXML: %s near line %d\n", s, lineNumber); ! 1143: return 0; ! 1144: } ! 1145: ! 1146: #define TAG_MAX_LENGTH 32 ! 1147: #define TAG_MAX_ATTRIBUTES 32 ! 1148: #define TAG_BAD 0 ! 1149: #define TAG_START 1 ! 1150: #define TAG_END 2 ! 1151: #define TAG_EMPTY 3 ! 1152: #define TAG_COMMENT 4 ! 1153: ! 1154: static int ! 1155: getTag(char tag[TAG_MAX_LENGTH], ! 1156: int *attributeCount, ! 1157: char attributes[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH], ! 1158: char values[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH] ) ! 1159: { ! 1160: int length = 0;; ! 1161: int c = currentChar(); ! 1162: int tagType = TAG_START; ! 1163: ! 1164: *attributeCount = 0; ! 1165: ! 1166: if (c != '<') return TAG_BAD; ! 1167: c = nextChar(); // skip '<' ! 1168: ! 1169: if (c == '?' || c == '!') { ! 1170: while ((c = nextChar()) != 0) { ! 1171: if (c == '\n') lineNumber++; ! 1172: if (c == '>') { ! 1173: (void)nextChar(); ! 1174: return TAG_COMMENT; ! 1175: } ! 1176: } ! 1177: } ! 1178: ! 1179: if (c == '/') { ! 1180: c = nextChar(); // skip '/' ! 1181: tagType = TAG_END; ! 1182: } ! 1183: if (!isAlpha(c)) return TAG_BAD; ! 1184: ! 1185: /* find end of tag while copying it */ ! 1186: while (isAlphaNumeric(c)) { ! 1187: tag[length++] = c; ! 1188: c = nextChar(); ! 1189: if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD; ! 1190: } ! 1191: ! 1192: tag[length] = 0; ! 1193: ! 1194: //printf("tag %s, type %d\n", tag, tagType); ! 1195: ! 1196: // look for attributes of the form attribute = "value" ... ! 1197: while ((c != '>') && (c != '/')) { ! 1198: while (isSpace(c)) c = nextChar(); ! 1199: ! 1200: length = 0; ! 1201: while (isAlphaNumeric(c)) { ! 1202: attributes[*attributeCount][length++] = c; ! 1203: if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD; ! 1204: c = nextChar(); ! 1205: } ! 1206: attributes[*attributeCount][length] = 0; ! 1207: ! 1208: while (isSpace(c)) c = nextChar(); ! 1209: ! 1210: if (c != '=') return TAG_BAD; ! 1211: c = nextChar(); ! 1212: ! 1213: while (isSpace(c)) c = nextChar(); ! 1214: ! 1215: if (c != '"') return TAG_BAD; ! 1216: c = nextChar(); ! 1217: length = 0; ! 1218: while (c != '"') { ! 1219: values[*attributeCount][length++] = c; ! 1220: if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD; ! 1221: c = nextChar(); ! 1222: } ! 1223: values[*attributeCount][length] = 0; ! 1224: ! 1225: c = nextChar(); // skip closing quote ! 1226: ! 1227: //printf(" attribute '%s' = '%s', nextchar = '%c'\n", attributes[*attributeCount], values[*attributeCount], c); ! 1228: ! 1229: (*attributeCount)++; ! 1230: if (*attributeCount >= TAG_MAX_ATTRIBUTES) return TAG_BAD; ! 1231: } ! 1232: ! 1233: if (c == '/') { ! 1234: c = nextChar(); // skip '/' ! 1235: tagType = TAG_EMPTY; ! 1236: } ! 1237: if (c != '>') return TAG_BAD; ! 1238: c = nextChar(); // skip '>' ! 1239: ! 1240: return tagType; ! 1241: } ! 1242: ! 1243: static char * ! 1244: getString() ! 1245: { ! 1246: int c = currentChar(); ! 1247: ! 1248: int start, length, i, j;; ! 1249: char * tempString; ! 1250: ! 1251: start = parseBufferIndex; ! 1252: /* find end of string */ ! 1253: ! 1254: while (c != 0) { ! 1255: if (c == '\n') lineNumber++; ! 1256: if (c == '<') { ! 1257: break; ! 1258: } ! 1259: c = nextChar(); ! 1260: } ! 1261: ! 1262: if (c != '<') return 0; ! 1263: ! 1264: length = parseBufferIndex - start; ! 1265: ! 1266: /* copy to null terminated buffer */ ! 1267: tempString = (char *)malloc(length + 1); ! 1268: if (tempString == 0) { ! 1269: printf("OSUnserializeXML: can't alloc temp memory\n"); ! 1270: return 0; ! 1271: } ! 1272: ! 1273: // copy out string in tempString ! 1274: // "&" -> '&', "<" -> '<', ">" -> '>' ! 1275: ! 1276: i = j = 0; ! 1277: while (i < length) { ! 1278: c = parseBuffer[start + i++]; ! 1279: if (c != '&') { ! 1280: tempString[j++] = c; ! 1281: } else { ! 1282: if ((i+3) > length) goto error; ! 1283: c = parseBuffer[start + i++]; ! 1284: if (c == 'l') { ! 1285: if (parseBuffer[start + i++] != 't') goto error; ! 1286: if (parseBuffer[start + i++] != ';') goto error; ! 1287: tempString[j++] = '<'; ! 1288: continue; ! 1289: } ! 1290: if (c == 'g') { ! 1291: if (parseBuffer[start + i++] != 't') goto error; ! 1292: if (parseBuffer[start + i++] != ';') goto error; ! 1293: tempString[j++] = '>'; ! 1294: continue; ! 1295: } ! 1296: if ((i+3) > length) goto error; ! 1297: if (c == 'a') { ! 1298: if (parseBuffer[start + i++] != 'm') goto error; ! 1299: if (parseBuffer[start + i++] != 'p') goto error; ! 1300: if (parseBuffer[start + i++] != ';') goto error; ! 1301: tempString[j++] = '&'; ! 1302: continue; ! 1303: } ! 1304: goto error; ! 1305: } ! 1306: } ! 1307: tempString[j] = 0; ! 1308: ! 1309: //printf("string %s\n", tempString); ! 1310: ! 1311: return tempString; ! 1312: ! 1313: error: ! 1314: if (tempString) free(tempString); ! 1315: return 0; ! 1316: } ! 1317: ! 1318: static long long ! 1319: getNumber() ! 1320: { ! 1321: unsigned long long n = 0; ! 1322: int base = 10; ! 1323: int c = currentChar(); ! 1324: ! 1325: if (!isDigit (c)) return 0; ! 1326: ! 1327: if (c == '0') { ! 1328: c = nextChar(); ! 1329: if (c == 'x') { ! 1330: base = 16; ! 1331: c = nextChar(); ! 1332: } ! 1333: } ! 1334: if (base == 10) { ! 1335: while(isDigit(c)) { ! 1336: n = (n * base + c - '0'); ! 1337: c = nextChar(); ! 1338: } ! 1339: } else { ! 1340: while(isHexDigit(c)) { ! 1341: if (isDigit(c)) { ! 1342: n = (n * base + c - '0'); ! 1343: } else { ! 1344: n = (n * base + 0xa + c - 'a'); ! 1345: } ! 1346: c = nextChar(); ! 1347: } ! 1348: } ! 1349: //printf("number 0x%x\n", (unsigned long)n); ! 1350: return n; ! 1351: } ! 1352: ! 1353: // taken from CFXMLParsing/CFPropertyList.c ! 1354: ! 1355: static const signed char __CFPLDataDecodeTable[128] = { ! 1356: /* 000 */ -1, -1, -1, -1, -1, -1, -1, -1, ! 1357: /* 010 */ -1, -1, -1, -1, -1, -1, -1, -1, ! 1358: /* 020 */ -1, -1, -1, -1, -1, -1, -1, -1, ! 1359: /* 030 */ -1, -1, -1, -1, -1, -1, -1, -1, ! 1360: /* ' ' */ -1, -1, -1, -1, -1, -1, -1, -1, ! 1361: /* '(' */ -1, -1, -1, 62, -1, -1, -1, 63, ! 1362: /* '0' */ 52, 53, 54, 55, 56, 57, 58, 59, ! 1363: /* '8' */ 60, 61, -1, -1, -1, 0, -1, -1, ! 1364: /* '@' */ -1, 0, 1, 2, 3, 4, 5, 6, ! 1365: /* 'H' */ 7, 8, 9, 10, 11, 12, 13, 14, ! 1366: /* 'P' */ 15, 16, 17, 18, 19, 20, 21, 22, ! 1367: /* 'X' */ 23, 24, 25, -1, -1, -1, -1, -1, ! 1368: /* '`' */ -1, 26, 27, 28, 29, 30, 31, 32, ! 1369: /* 'h' */ 33, 34, 35, 36, 37, 38, 39, 40, ! 1370: /* 'p' */ 41, 42, 43, 44, 45, 46, 47, 48, ! 1371: /* 'x' */ 49, 50, 51, -1, -1, -1, -1, -1 ! 1372: }; ! 1373: ! 1374: #define OSDATA_ALLOC_SIZE 4096 ! 1375: ! 1376: static void * ! 1377: getData(unsigned int *size) ! 1378: { ! 1379: int numeq = 0, acc = 0, cntr = 0; ! 1380: int tmpbufpos = 0, tmpbuflen = 0; ! 1381: unsigned char *tmpbuf = (unsigned char *)malloc(OSDATA_ALLOC_SIZE); ! 1382: ! 1383: int c = currentChar(); ! 1384: *size = 0; ! 1385: ! 1386: while (c != '<') { ! 1387: c &= 0x7f; ! 1388: if (c == 0) { ! 1389: free(tmpbuf); ! 1390: return 0; ! 1391: } ! 1392: if (c == '=') numeq++; else numeq = 0; ! 1393: if (c == '\n') lineNumber++; ! 1394: if (__CFPLDataDecodeTable[c] < 0) { ! 1395: c = nextChar(); ! 1396: continue; ! 1397: } ! 1398: cntr++; ! 1399: acc <<= 6; ! 1400: acc += __CFPLDataDecodeTable[c]; ! 1401: if (0 == (cntr & 0x3)) { ! 1402: if (tmpbuflen <= tmpbufpos + 2) { ! 1403: tmpbuflen += OSDATA_ALLOC_SIZE; ! 1404: tmpbuf = (unsigned char *)realloc(tmpbuf, tmpbuflen); ! 1405: } ! 1406: tmpbuf[tmpbufpos++] = (acc >> 16) & 0xff; ! 1407: if (numeq < 2) ! 1408: tmpbuf[tmpbufpos++] = (acc >> 8) & 0xff; ! 1409: if (numeq < 1) ! 1410: tmpbuf[tmpbufpos++] = acc & 0xff; ! 1411: } ! 1412: c = nextChar(); ! 1413: } ! 1414: *size = tmpbufpos; ! 1415: return tmpbuf; ! 1416: } ! 1417: ! 1418: static int ! 1419: yylex() ! 1420: { ! 1421: int c; ! 1422: int tagType; ! 1423: char tag[TAG_MAX_LENGTH]; ! 1424: int attributeCount; ! 1425: char attributes[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH]; ! 1426: char values[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH]; ! 1427: ! 1428: if (parseBufferIndex == 0) lineNumber = 1; ! 1429: ! 1430: top: ! 1431: c = currentChar(); ! 1432: ! 1433: /* skip white space */ ! 1434: if (isSpace(c)) while ((c = nextChar()) != 0 && isSpace(c)) {}; ! 1435: ! 1436: /* keep track of line number, don't return \n's */ ! 1437: if (c == '\n') { ! 1438: lineNumber++; ! 1439: (void)nextChar(); ! 1440: goto top; ! 1441: } ! 1442: ! 1443: if (!c || c == ',') { ! 1444: (void)nextChar(); ! 1445: return c; ! 1446: } ! 1447: ! 1448: tagType = getTag(tag, &attributeCount, attributes, values); ! 1449: if (tagType == TAG_BAD) return SYNTAX_ERROR; ! 1450: if (tagType == TAG_COMMENT) goto top; ! 1451: ! 1452: // this code handles empty tags, for idrefs we ignore the tag ! 1453: // for this to work all idrefs must be unique across the whole serialization ! 1454: if (tagType == TAG_EMPTY) { ! 1455: if (!strcmp(tag, "true") || !strcmp(tag, "false")) { ! 1456: yylval = newObject(); ! 1457: yylval->number = *tag == 't'; ! 1458: return BOOLEAN; ! 1459: } ! 1460: for (int i=0; i < attributeCount; i++) { ! 1461: if (!strcmp(attributes[i], "IDREF")) { ! 1462: yylval = newObject(); ! 1463: yylval->idref = strtol(values[i], NULL, 0); ! 1464: return IDREF; ! 1465: } ! 1466: } ! 1467: return SYNTAX_ERROR; ! 1468: } ! 1469: ! 1470: // handle allocation and check of "ID" tag up front ! 1471: yylval = newObject(); ! 1472: yylval->idref = -1; ! 1473: for (int i=0; i < attributeCount; i++) { ! 1474: if (attributes[i][0] == 'I' && attributes[i][1] == 'D' && !attributes[i][2]) { ! 1475: yylval->idref = strtol(values[i], NULL, 0); ! 1476: } ! 1477: } ! 1478: ! 1479: switch (*tag) { ! 1480: case 'a': ! 1481: if (!strcmp(tag, "array")) { ! 1482: return (tagType == TAG_START) ? '(' : ')'; ! 1483: } ! 1484: break; ! 1485: case 'd': ! 1486: if (!strcmp(tag, "dict")) { ! 1487: return (tagType == TAG_START) ? '{' : '}'; ! 1488: } ! 1489: if (!strcmp(tag, "data")) { ! 1490: unsigned int size; ! 1491: yylval->data = getData(&size); ! 1492: yylval->size = size; ! 1493: if ((getTag(tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "data")) { ! 1494: return SYNTAX_ERROR; ! 1495: } ! 1496: return DATA; ! 1497: } ! 1498: break; ! 1499: case 'i': ! 1500: if (!strcmp(tag, "integer")) { ! 1501: yylval->number = getNumber(); ! 1502: yylval->size = 64; // default ! 1503: for (int i=0; i < attributeCount; i++) { ! 1504: if (!strcmp(attributes[i], "size")) { ! 1505: yylval->size = strtoul(values[i], NULL, 0); ! 1506: } ! 1507: } ! 1508: if ((getTag(tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "integer")) { ! 1509: return SYNTAX_ERROR; ! 1510: } ! 1511: return NUMBER; ! 1512: } ! 1513: break; ! 1514: case 'k': ! 1515: if (!strcmp(tag, "key")) { ! 1516: yylval->string = getString(); ! 1517: if (!yylval->string) { ! 1518: return SYNTAX_ERROR; ! 1519: } ! 1520: if ((getTag(tag, &attributeCount, attributes, values) != TAG_END) ! 1521: || strcmp(tag, "key")) { ! 1522: return SYNTAX_ERROR; ! 1523: } ! 1524: return KEY; ! 1525: } ! 1526: break; ! 1527: case 'p': ! 1528: if (!strcmp(tag, "plist")) { ! 1529: freeObject(yylval); ! 1530: goto top; ! 1531: } ! 1532: break; ! 1533: case 's': ! 1534: if (!strcmp(tag, "string")) { ! 1535: yylval->string = getString(); ! 1536: if (!yylval->string) { ! 1537: return SYNTAX_ERROR; ! 1538: } ! 1539: if ((getTag(tag, &attributeCount, attributes, values) != TAG_END) ! 1540: || strcmp(tag, "string")) { ! 1541: return SYNTAX_ERROR; ! 1542: } ! 1543: return STRING; ! 1544: } ! 1545: if (!strcmp(tag, "set")) { ! 1546: if (tagType == TAG_START) { ! 1547: return '['; ! 1548: } else { ! 1549: return ']'; ! 1550: } ! 1551: } ! 1552: break; ! 1553: ! 1554: default: ! 1555: // XXX should we ignore invalid tags? ! 1556: return SYNTAX_ERROR; ! 1557: break; ! 1558: } ! 1559: ! 1560: return 0; ! 1561: } ! 1562: ! 1563: // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# ! 1564: // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# ! 1565: // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# ! 1566: ! 1567: // "java" like allocation, if this code hits a syntax error in the ! 1568: // the middle of the parsed string we just bail with pointers hanging ! 1569: // all over place, so this code helps keeps all together ! 1570: ! 1571: static object_t *objects = 0; ! 1572: static object_t *freeObjects = 0; ! 1573: ! 1574: object_t * ! 1575: newObject() ! 1576: { ! 1577: object_t *o; ! 1578: ! 1579: if (freeObjects) { ! 1580: o = freeObjects; ! 1581: freeObjects = freeObjects->next; ! 1582: } else { ! 1583: o = (object_t *)malloc(sizeof(object_t)); ! 1584: bzero(o, sizeof(object_t)); ! 1585: o->free = objects; ! 1586: objects = o; ! 1587: } ! 1588: ! 1589: return o; ! 1590: } ! 1591: ! 1592: void ! 1593: freeObject(object_t *o) ! 1594: { ! 1595: o->next = freeObjects; ! 1596: freeObjects = o; ! 1597: } ! 1598: ! 1599: void ! 1600: cleanupObjects() ! 1601: { ! 1602: object_t *t, *o = objects; ! 1603: ! 1604: while (o) { ! 1605: if (o->object) { ! 1606: printf("OSUnserializeXML: releasing object o=%x object=%x\n", (int)o, (int)o->object); ! 1607: o->object->release(); ! 1608: } ! 1609: if (o->data) { ! 1610: printf("OSUnserializeXML: freeing object o=%x data=%x\n", (int)o, (int)o->data); ! 1611: free(o->data); ! 1612: } ! 1613: if (o->key) { ! 1614: printf("OSUnserializeXML: releasing object o=%x key=%x\n", (int)o, (int)o->key); ! 1615: o->key->release(); ! 1616: } ! 1617: if (o->string) { ! 1618: printf("OSUnserializeXML: freeing object o=%x string=%x\n", (int)o, (int)o->string); ! 1619: free(o->string); ! 1620: } ! 1621: ! 1622: t = o; ! 1623: o = o->free; ! 1624: free(t); ! 1625: } ! 1626: } ! 1627: ! 1628: // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# ! 1629: // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# ! 1630: // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# ! 1631: ! 1632: static OSDictionary *tags; ! 1633: ! 1634: static void ! 1635: rememberObject(int tag, OSObject *o) ! 1636: { ! 1637: char key[16]; ! 1638: sprintf(key, "%u", tag); ! 1639: ! 1640: //printf("remember key %s\n", key); ! 1641: ! 1642: tags->setObject(key, o); ! 1643: } ! 1644: ! 1645: static object_t * ! 1646: retrieveObject(int tag) ! 1647: { ! 1648: char key[16]; ! 1649: sprintf(key, "%u", tag); ! 1650: ! 1651: //printf("retrieve key '%s'\n", key); ! 1652: ! 1653: OSObject *ref = tags->getObject(key); ! 1654: if (!ref) return 0; ! 1655: ! 1656: object_t *o = newObject(); ! 1657: o->object = ref; ! 1658: return o; ! 1659: } ! 1660: ! 1661: // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# ! 1662: // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# ! 1663: // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# ! 1664: ! 1665: object_t * ! 1666: buildOSDictionary(object_t * header) ! 1667: { ! 1668: object_t *o, *t; ! 1669: int count = 0; ! 1670: ! 1671: // get count and reverse order ! 1672: o = header->elements; ! 1673: header->elements = 0; ! 1674: while (o) { ! 1675: count++; ! 1676: t = o; ! 1677: o = o->next; ! 1678: ! 1679: t->next = header->elements; ! 1680: header->elements = t; ! 1681: } ! 1682: ! 1683: OSDictionary *d = OSDictionary::withCapacity(count); ! 1684: ! 1685: if (header->idref >= 0) rememberObject(header->idref, d); ! 1686: ! 1687: o = header->elements; ! 1688: while (o) { ! 1689: d->setObject(o->key, o->object); ! 1690: o->object->release(); ! 1691: o->object = 0; ! 1692: o->key->release(); ! 1693: o->key = 0; ! 1694: t = o; ! 1695: o = o->next; ! 1696: freeObject(t); ! 1697: } ! 1698: o = header; ! 1699: o->object = d; ! 1700: return o; ! 1701: }; ! 1702: ! 1703: object_t * ! 1704: buildOSArray(object_t * header) ! 1705: { ! 1706: object_t *o, *t; ! 1707: int count = 0; ! 1708: ! 1709: // get count and reverse order ! 1710: o = header->elements; ! 1711: header->elements = 0; ! 1712: while (o) { ! 1713: count++; ! 1714: t = o; ! 1715: o = o->next; ! 1716: ! 1717: t->next = header->elements; ! 1718: header->elements = t; ! 1719: } ! 1720: ! 1721: OSArray *a = OSArray::withCapacity(count); ! 1722: ! 1723: if (header->idref >= 0) rememberObject(header->idref, a); ! 1724: ! 1725: o = header->elements; ! 1726: while (o) { ! 1727: a->setObject(o->object); ! 1728: o->object->release(); ! 1729: o->object = 0; ! 1730: t = o; ! 1731: o = o->next; ! 1732: freeObject(t); ! 1733: } ! 1734: o = header; ! 1735: o->object = a; ! 1736: return o; ! 1737: }; ! 1738: ! 1739: object_t * ! 1740: buildOSSet(object_t *o) ! 1741: { ! 1742: o = buildOSArray(o); ! 1743: OSArray *a = (OSArray *)o->object; ! 1744: ! 1745: OSSet *s = OSSet::withArray(a, a->getCapacity()); ! 1746: ! 1747: //write over reference created in array ! 1748: if (o->idref >= 0) rememberObject(o->idref, s); ! 1749: ! 1750: a->release(); ! 1751: o->object = s; ! 1752: return o; ! 1753: }; ! 1754: ! 1755: object_t * ! 1756: buildOSString(object_t *o) ! 1757: { ! 1758: OSString *s = OSString::withCString(o->string); ! 1759: ! 1760: if (o->idref >= 0) rememberObject(o->idref, s); ! 1761: ! 1762: free(o->string); ! 1763: o->string = 0; ! 1764: o->object = s; ! 1765: ! 1766: return o; ! 1767: }; ! 1768: ! 1769: object_t * ! 1770: buildKey(object_t *o) ! 1771: { ! 1772: const OSSymbol *s = OSSymbol::withCString(o->string); ! 1773: ! 1774: free(o->string); ! 1775: o->string = 0; ! 1776: o->key = s; ! 1777: ! 1778: return o; ! 1779: }; ! 1780: ! 1781: object_t * ! 1782: buildOSData(object_t *o) ! 1783: { ! 1784: OSData *d; ! 1785: ! 1786: if (o->size) { ! 1787: d = OSData::withBytes(o->data, o->size); ! 1788: free(o->data); ! 1789: } else { ! 1790: d = OSData::withCapacity(0); ! 1791: } ! 1792: if (o->idref >= 0) rememberObject(o->idref, d); ! 1793: ! 1794: o->data = 0; ! 1795: o->object = d; ! 1796: return o; ! 1797: }; ! 1798: ! 1799: object_t * ! 1800: buildOSNumber(object_t *o) ! 1801: { ! 1802: OSNumber *n = OSNumber::withNumber(o->number, o->size); ! 1803: ! 1804: if (o->idref >= 0) rememberObject(o->idref, n); ! 1805: ! 1806: o->object = n; ! 1807: return o; ! 1808: }; ! 1809: ! 1810: object_t * ! 1811: buildOSBoolean(object_t *o) ! 1812: { ! 1813: OSBoolean *b = OSBoolean::withBoolean(o->number != 0); ! 1814: o->object = b; ! 1815: return o; ! 1816: }; ! 1817: ! 1818: __BEGIN_DECLS ! 1819: #include <kern/lock.h> ! 1820: __END_DECLS ! 1821: ! 1822: static mutex_t *lock = 0; ! 1823: ! 1824: OSObject* ! 1825: OSUnserializeXML(const char *buffer, OSString **errorString) ! 1826: { ! 1827: OSObject *object; ! 1828: ! 1829: if (!lock) { ! 1830: lock = mutex_alloc(ETAP_IO_AHA); ! 1831: _mutex_lock(lock); ! 1832: } else { ! 1833: _mutex_lock(lock); ! 1834: ! 1835: } ! 1836: ! 1837: objects = 0; ! 1838: freeObjects = 0; ! 1839: yyerror_message[0] = 0; //just in case ! 1840: parseBuffer = buffer; ! 1841: parseBufferIndex = 0; ! 1842: tags = OSDictionary::withCapacity(128); ! 1843: if (yyparse() == 0) { ! 1844: object = parsedObject; ! 1845: if (errorString) *errorString = 0; ! 1846: } else { ! 1847: object = 0; ! 1848: if (errorString) ! 1849: *errorString = OSString::withCString(yyerror_message); ! 1850: } ! 1851: ! 1852: cleanupObjects(); ! 1853: tags->release(); ! 1854: mutex_unlock(lock); ! 1855: ! 1856: return object; ! 1857: } ! 1858: ! 1859: ! 1860: // ! 1861: // ! 1862: // ! 1863: // ! 1864: // ! 1865: // DO NOT EDIT OSUnserializeXML.cpp! ! 1866: // ! 1867: // this means you! ! 1868: // ! 1869: // ! 1870: // ! 1871: // ! 1872: //
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.