Back to index

lightning-sunbird  0.9+nobinonly
nsVCard.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /***************************************************************************
00039 (C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International             
00040 Business Machines Corporation and Siemens Rolm Communications Inc.             
00041                                                                                
00042 For purposes of this license notice, the term Licensors shall mean,            
00043 collectively, Apple Computer, Inc., AT&T Corp., International                  
00044 Business Machines Corporation and Siemens Rolm Communications Inc.             
00045 The term Licensor shall mean any of the Licensors.                             
00046                                                                                
00047 Subject to acceptance of the following conditions, permission is hereby        
00048 granted by Licensors without the need for written agreement and without        
00049 license or royalty fees, to use, copy, modify and distribute this              
00050 software for any purpose.                                                      
00051                                                                                
00052 The above copyright notice and the following four paragraphs must be           
00053 reproduced in all copies of this software and any software including           
00054 this software.                                                                 
00055                                                                                
00056 THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE       
00057 ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR       
00058 MODIFICATIONS.                                                                 
00059                                                                                
00060 IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,              
00061 INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT         
00062 OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH         
00063 DAMAGE.                                                                        
00064                                                                                
00065 EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,       
00066 INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE            
00067 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR             
00068 PURPOSE.                                                                       
00069 
00070 The software is provided with RESTRICTED RIGHTS.  Use, duplication, or         
00071 disclosure by the government are subject to restrictions set forth in          
00072 DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.                         
00073 
00074 ***************************************************************************/
00075 
00076 /*
00077  * src: vcc.c
00078  * doc: Parser for vCard and vCalendar. Note that this code is
00079  * generated by a yacc parser generator. Generally it should not
00080  * be edited by hand. The real source is vcc.y. The #line directives
00081  * can be commented out here to make it easier to trace through
00082  * in a debugger. However, if a bug is found it should 
00083  *
00084  * the vcc.y that _this_ vcc.c comes from is lost.
00085  * I couldn't find it in the 4.x tree
00086  * I bet we took it from IMC's original SDK, but the SDK has been taken down.
00087  * see http://www.imc.org/imc-vcard/mail-archive/msg00460.html
00088  *
00089  * for what it's worth, see 
00090  * http://softwarestudio.org/libical/
00091  * http://lxr.mozilla.org/mozilla/source/other-licenses/libical/src/libicalvcal/vcc.y
00092  * http://lxr.mozilla.org/mozilla/source/other-licenses/libical/src/libicalvcal/vcc.c
00093  */
00094 #include "nsVCard.h"
00095 #include "nsVCardObj.h"
00096 #include "nsFileStream.h"
00097 #include "prprf.h"
00098 
00099 #ifndef lint
00100 char yysccsid[] = "@(#)yaccpar     1.4 (Berkeley) 02/25/90";
00101 #endif
00102 /*#line 2 "vcc.y" */
00103 
00104 /* debugging utilities */
00105 #define DBG_(x)
00106 
00107 #ifndef _NO_LINE_FOLDING
00108 #define _SUPPORT_LINE_FOLDING
00109 #endif
00110 
00111 /****  External Functions  ****/
00112 
00113 /* assign local name to parser variables and functions so that
00114    we can use more than one yacc based parser.
00115 */
00116 
00117 #define yyparse mime_parse
00118 #define yylex mime_lex
00119 #define yyerror mime_error
00120 #define yychar mime_char
00121 /* #define p_yyval p_mime_val */
00122 #undef yyval
00123 #define yyval mime_yyval
00124 /* #define p_yylval p_mime_lval */
00125 #undef yylval
00126 #define yylval mime_yylval
00127 #define yydebug mime_debug
00128 #define yynerrs mime_nerrs
00129 #define yyerrflag mime_errflag
00130 #define yyss mime_ss
00131 #define yyssp mime_ssp
00132 #define yyvs mime_vs
00133 #define yyvsp mime_vsp
00134 #define yylhs mime_lhs
00135 #define yylen mime_len
00136 #define yydefred mime_defred
00137 #define yydgoto mime_dgoto
00138 #define yysindex mime_sindex
00139 #define yyrindex mime_rindex
00140 #define yygindex mime_gindex
00141 #define yytable mime_table
00142 #define yycheck mime_check
00143 #define yyname mime_name
00144 #define yyrule mime_rule
00145 #define YYPREFIX "mime_"
00146 
00147 #include "prmem.h"
00148 #include "plstr.h"
00149 
00150 #ifndef FALSE
00151 #define FALSE 0
00152 #endif
00153 #ifndef TRUE
00154 #define TRUE 1
00155 #endif
00156 
00157 /****  Types, Constants  ****/
00158 
00159 #define YYDEBUG             0      /* 1 to compile in some debugging code */
00160 #define PR_MAXTOKEN  256    /* maximum token (line) length */
00161 #define YYSTACKSIZE  50     /* ~unref ?*/
00162 #define PR_MAXLEVEL  10     /* max # of nested objects parseable */
00163                             /* (includes outermost) */
00164 
00165 
00166 /****  Global Variables  ****/
00167 int mime_lineNum, mime_numErrors; /* yyerror() can use these */
00168 static VObject* vObjList;
00169 static VObject *curProp;
00170 static VObject *curObj;
00171 static VObject* ObjStack[PR_MAXLEVEL];
00172 static int ObjStackTop;
00173 
00174 
00175 /* A helpful utility for the rest of the app. */
00176 #ifdef __cplusplus
00177 extern "C" {
00178 #endif
00179 
00180     extern void yyerror(char *s);
00181          extern char** fieldedProp;
00182 
00183 #ifdef __cplusplus
00184     }
00185 #endif
00186 
00187 int yyparse();
00188 
00189 enum LexMode {
00190        L_NORMAL,
00191        L_VCARD,
00192        L_VCAL,
00193        L_VEVENT,
00194        L_VTODO,
00195        L_VALUES,
00196        L_BASE64,
00197        L_QUOTED_PRINTABLE
00198        };
00199 
00200 /****  Private Forward Declarations  ****/
00201 static int pushVObject(const char *prop);
00202 static VObject* popVObject();
00203 static int lexGeta();  
00204 static int lexGetc_();
00205 static int lexGetc();
00206 static void lexSkipLookahead();
00207 static int lexLookahead();
00208 static void lexSkipWhite();
00209 static void lexClearToken();
00210 static char * lexStr();
00211 static char * lexGetDataFromBase64();
00212 static char * lexGetQuotedPrintable();
00213 static char * lexGet1Value();
00214 static char * lexGetWord();
00215 static void finiLex();
00216 
00217 static VObject* parse_MIMEHelper();
00218 
00219 /*static char* lexDataFromBase64();*/
00220 static void lexPopMode(int top);
00221 static int lexWithinMode(enum LexMode mode);
00222 static void lexPushMode(enum LexMode mode);
00223 static void enterProps(const char *s);
00224 static void enterAttr(const char *s1, const char *s2);
00225 static void enterValues(const char *value);
00226 static void mime_error_(char *s); 
00227 
00228 /*#line 250 "vcc.y" */
00229 typedef union {
00230     char *str;
00231     VObject *vobj;
00232     } YYSTYPE;
00233 /*#line 253 "y_tab.c"*/
00234 #define EQ 257
00235 #define COLON 258
00236 #define DOT 259
00237 #define SEMICOLON 260
00238 #define SPACE 261
00239 #define HTAB 262
00240 #define LINESEP 263
00241 #define NEWLINE 264
00242 #define BEGIN_VCARD 265
00243 #define END_VCARD 266
00244 #define BEGIN_VCAL 267
00245 #define END_VCAL 268
00246 #define BEGIN_VEVENT 269
00247 #define END_VEVENT 270
00248 #define BEGIN_VTODO 271
00249 #define END_VTODO 272
00250 #define ID 273
00251 #define STRING 274
00252 #define YYERRCODE 256
00253 short yylhs[] = {                                        -1,
00254     0,    7,    6,    6,    5,    5,    9,    3,   10,    3,
00255     8,    8,   14,   11,   11,   16,   12,   12,   15,   15,
00256    17,   18,   18,    1,   19,   13,   13,    2,    2,   21,
00257     4,   22,    4,   20,   20,   23,   23,   23,   26,   24,
00258    27,   24,   28,   25,   29,   25,
00259 };
00260 short yylen[] = {                                         2,
00261     1,    0,    3,    1,    1,    1,    0,    4,    0,    3,
00262     2,    1,    0,    5,    1,    0,    3,    1,    2,    1,
00263     2,    1,    3,    1,    0,    4,    1,    1,    0,    0,
00264     4,    0,    3,    2,    1,    1,    1,    1,    0,    4,
00265     0,    3,    0,    4,    0,    3,
00266 };
00267 short yydefred[] = {                                      0,
00268     0,    0,    0,    5,    6,    0,    1,    0,    0,    0,
00269     0,    0,   15,   24,    0,    0,    0,    0,   10,    0,
00270     0,   38,    0,    0,   36,   37,   33,    3,    0,    8,
00271    11,   13,    0,    0,    0,    0,   31,   34,    0,   17,
00272     0,    0,    0,   42,    0,   46,    0,   21,   19,   28,
00273     0,    0,   40,   44,    0,   25,   14,   23,    0,   26,
00274 };
00275 short yydgoto[] = {                                       3,
00276    15,   51,    4,    5,    6,    7,   12,   22,    8,    9,
00277    17,   18,   52,   42,   40,   29,   41,   48,   59,   23,
00278    10,   11,   24,   25,   26,   33,   34,   35,   36,
00279 };
00280 short yysindex[] = {                                   -227,
00281     0,    0,    0,    0,    0,    0,    0, -249, -262, -253,
00282  -258, -227,    0,    0,    0, -234, -249, -215,    0,    0,
00283     0,    0, -223, -253,    0,    0,    0,    0, -247,    0,
00284     0,    0, -249, -222, -249, -225,    0,    0, -224,    0,
00285  -247, -221, -220,    0, -218,    0, -206,    0,    0,    0,
00286  -208, -207,    0,    0, -224,    0,    0,    0, -221,    0,
00287 };
00288 short yyrindex[] = {                                      0,
00289  -245, -254,    0,    0,    0,    1,    0,    0,    0,    0,
00290     0,    0,    0,    0, -219,    0, -235,    0,    0, -244,
00291  -250,    0,    0, -213,    0,    0,    0,    0,    0,    0,
00292     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
00293  -201, -255,    0,    0,    0,    0, -216,    0,    0,    0,
00294  -205,    0,    0,    0,    0,    0,    0,    0, -255,    0,
00295 };
00296 short yygindex[] = {                                      0,
00297    -9,    0,    0,    0,    0,   47,    0,   -8,    0,    0,
00298     0,    0,    2,    0,   19,    0,    0,    0,    0,   38,
00299     0,    0,    0,    0,    0,    0,    0,    0,    0,
00300 };
00301 #define YYTABLESIZE 268
00302 short yytable[] = {                                      16,
00303     4,   30,   13,   19,   29,   43,   13,   29,   31,   27,
00304     7,   39,   39,   32,   30,   20,   30,   21,   30,   14,
00305     9,   45,   43,   14,   43,   41,   45,    7,   39,   47,
00306    12,   30,   12,   12,   12,   12,   12,    1,   18,    2,
00307    16,   22,   32,   22,   37,   58,   46,   44,   14,   53,
00308    55,   56,   50,   54,   35,   57,   20,   27,   28,   49,
00309    60,   38,    0,    0,    0,    0,    0,    0,    0,    0,
00310     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
00311     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
00312     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
00313     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
00314     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
00315     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
00316     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
00317     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
00318     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
00319     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
00320     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
00321     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
00322     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
00323     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
00324     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
00325     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
00326     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
00327     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
00328     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
00329     0,    0,    0,    0,    0,    2,    0,    2,
00330 };
00331 short yycheck[] = {                                       8,
00332     0,  256,  256,  266,  260,  256,  256,  263,   17,  268,
00333   256,  256,  260,  268,  269,  269,  271,  271,  273,  273,
00334   266,  272,  273,  273,   33,  270,   35,  273,  273,   39,
00335   266,  266,  268,  269,  270,  271,  272,  265,  258,  267,
00336   260,  258,  258,  260,  268,   55,  272,  270,  273,  270,
00337   257,  260,  274,  272,  268,  263,  258,  263,   12,   41,
00338    59,   24,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
00339    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
00340    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
00341    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
00342    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
00343    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
00344    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
00345    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
00346    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
00347    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
00348    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
00349    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
00350    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
00351    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
00352    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
00353    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
00354    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
00355    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
00356    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
00357    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
00358    -1,   -1,   -1,   -1,   -1,  265,   -1,  267,
00359 };
00360 #define YYFINAL 3
00361 #ifndef YYDEBUG
00362 #define YYDEBUG 0
00363 #endif
00364 #define YYPR_MAXTOKEN 274
00365 #if YYDEBUG
00366 char *yyname[] = {
00367 "end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00368 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00369 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00370 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00371 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00372 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00373 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"EQ","COLON","DOT","SEMICOLON",
00374 "SPACE","HTAB","LINESEP","NEWLINE","BEGIN_VCARD","END_VCARD","BEGIN_VCAL",
00375 "END_VCAL","BEGIN_VEVENT","END_VEVENT","BEGIN_VTODO","END_VTODO","ID","STRING",
00376 };
00377 char *yyrule[] = {
00378 "$accept : mime",
00379 "mime : vobjects",
00380 "$$1 :",
00381 "vobjects : vobject $$1 vobjects",
00382 "vobjects : vobject",
00383 "vobject : vcard",
00384 "vobject : vcal",
00385 "$$2 :",
00386 "vcard : BEGIN_VCARD $$2 items END_VCARD",
00387 "$$3 :",
00388 "vcard : BEGIN_VCARD $$3 END_VCARD",
00389 "items : item items",
00390 "items : item",
00391 "$$4 :",
00392 "item : prop COLON $$4 values LINESEP",
00393 "item : error",
00394 "$$5 :",
00395 "prop : name $$5 attr_params",
00396 "prop : name",
00397 "attr_params : attr_param attr_params",
00398 "attr_params : attr_param",
00399 "attr_param : SEMICOLON attr",
00400 "attr : name",
00401 "attr : name EQ name",
00402 "name : ID",
00403 "$$6 :",
00404 "values : value SEMICOLON $$6 values",
00405 "values : value",
00406 "value : STRING",
00407 "value :",
00408 "$$7 :",
00409 "vcal : BEGIN_VCAL $$7 calitems END_VCAL",
00410 "$$8 :",
00411 "vcal : BEGIN_VCAL $$8 END_VCAL",
00412 "calitems : calitem calitems",
00413 "calitems : calitem",
00414 "calitem : eventitem",
00415 "calitem : todoitem",
00416 "calitem : items",
00417 "$$9 :",
00418 "eventitem : BEGIN_VEVENT $$9 items END_VEVENT",
00419 "$$10 :",
00420 "eventitem : BEGIN_VEVENT $$10 END_VEVENT",
00421 "$$11 :",
00422 "todoitem : BEGIN_VTODO $$11 items END_VTODO",
00423 "$$12 :",
00424 "todoitem : BEGIN_VTODO $$12 END_VTODO",
00425 };
00426 #endif
00427 #define yyclearin (yychar=(-1))
00428 #define yyerrok (yyerrflag=0)
00429 #ifndef YYSTACKSIZE
00430 #ifdef YYPR_MAXDEPTH
00431 #define YYSTACKSIZE YYPR_MAXDEPTH
00432 #else
00433 #define YYSTACKSIZE 300
00434 #endif
00435 #endif
00436 int yydebug;
00437 int yynerrs;
00438 int yyerrflag;
00439 int yychar;
00440 short *yyssp;
00441 YYSTYPE *yyvsp;
00442 YYSTYPE yyval;
00443 YYSTYPE yylval;
00444 #define yystacksize YYSTACKSIZE
00445 short yyss[YYSTACKSIZE];
00446 YYSTYPE yyvs[YYSTACKSIZE];
00447 /*#line 444 "vcc.y"*/
00448 /******************************************************************************/
00449 static int pushVObject(const char *prop)
00450     {
00451     VObject *newObj;
00452     if (ObjStackTop == PR_MAXLEVEL)
00453        return FALSE;
00454 
00455     ObjStack[++ObjStackTop] = curObj;
00456 
00457     if (curObj) {
00458         newObj = addProp(curObj,prop);
00459         curObj = newObj;
00460        }
00461     else
00462        curObj = newVObject(prop);
00463 
00464     return TRUE;
00465     }
00466 
00467 
00468 /******************************************************************************/
00469 /* This pops the recently built vCard off the stack and returns it. */
00470 static VObject* popVObject()
00471     {
00472     VObject *oldObj;
00473     if (ObjStackTop < 0) {
00474        yyerror("pop on empty Object Stack\n");
00475        return 0;
00476        }
00477     oldObj = curObj;
00478     curObj = ObjStack[ObjStackTop--];
00479 
00480     return oldObj;
00481     }
00482 
00483 extern "C" void                    deleteString(char *p);
00484 
00485 static void enterValues(const char *value)
00486     {
00487     if (fieldedProp && *fieldedProp) {
00488        if (value) {
00489            addPropValue(curProp,*fieldedProp,value);
00490            }
00491        /* else this field is empty, advance to next field */
00492        fieldedProp++;
00493        }
00494     else {
00495        if (value) {
00496            setVObjectUStringZValue_(curProp,fakeUnicode(value,0));
00497            }
00498        }
00499     deleteString((char *)value);
00500     }
00501 
00502 static void enterProps(const char *s)
00503     {
00504     curProp = addGroup(curObj,s);
00505     deleteString((char *)s);
00506     }
00507 
00508 static void enterAttr(const char *s1, const char *s2)
00509 {
00510   const char *p1, *p2 = nsnull;
00511   p1 = lookupProp_(s1);
00512   if (s2) {
00513          VObject *a;
00514          p2 = lookupProp_(s2);
00515          a = addProp(curProp,p1);
00516          setVObjectStringZValue(a,p2);
00517        }
00518   else
00519          addProp(curProp,p1);
00520   if (PL_strcasecmp(p1,VCBase64Prop) == 0 || (s2 && PL_strcasecmp(p2,VCBase64Prop)==0))
00521          lexPushMode(L_BASE64);
00522   else if (PL_strcasecmp(p1,VCQuotedPrintableProp) == 0
00523            || (s2 && PL_strcasecmp(p2,VCQuotedPrintableProp)==0))
00524     lexPushMode(L_QUOTED_PRINTABLE);
00525   deleteString((char *)s1); deleteString((char *)s2);
00526 }
00527 
00528 
00529 #define PR_MAX_LEX_LOOKAHEAD_0 32
00530 #define PR_MAX_LEX_LOOKAHEAD 64
00531 #define PR_MAX_LEX_MODE_STACK_SIZE 10
00532 #define LEXMODE() (lexBuf.lexModeStack[lexBuf.lexModeStackTop])
00533 
00534 struct LexBuf {
00535        /* input */
00536     nsInputFileStream  *inputFile;
00537     char *inputString;
00538     unsigned long curPos;
00539     unsigned long inputLen;
00540        /* lookahead buffer */
00541        /*   -- lookahead buffer is short instead of char so that EOF
00542         /      can be represented correctly.
00543        */
00544     unsigned long len;
00545     short buf[PR_MAX_LEX_LOOKAHEAD];
00546     unsigned long getPtr;
00547        /* context stack */
00548     unsigned long lexModeStackTop;
00549     enum LexMode lexModeStack[PR_MAX_LEX_MODE_STACK_SIZE];
00550        /* token buffer */
00551     unsigned long maxToken;
00552     char *strs;
00553     unsigned long strsLen;
00554     } lexBuf;
00555 
00556 static void lexPushMode(enum LexMode mode)
00557     {
00558     if (lexBuf.lexModeStackTop == (PR_MAX_LEX_MODE_STACK_SIZE-1))
00559        yyerror("lexical context stack overflow");
00560     else {
00561        lexBuf.lexModeStack[++lexBuf.lexModeStackTop] = mode;
00562        }
00563     }
00564 
00565 static void lexPopMode(int top)
00566     {
00567     /* special case of pop for ease of error recovery -- this
00568        version will never underflow */
00569     if (top)
00570        lexBuf.lexModeStackTop = 0;
00571     else
00572        if (lexBuf.lexModeStackTop > 0) lexBuf.lexModeStackTop--;
00573     }
00574 
00575 static int lexWithinMode(enum LexMode mode) {
00576     unsigned long i;
00577     for (i=0;i<lexBuf.lexModeStackTop;i++)
00578        if (mode == lexBuf.lexModeStack[i]) return 1;
00579     return 0;
00580     }
00581 
00582 static int lexGetc_()
00583 {
00584   /* get next char from input, no buffering. */
00585   if (lexBuf.curPos == lexBuf.inputLen)
00586     return EOF;
00587   else if (lexBuf.inputString)
00588     return *(lexBuf.inputString + lexBuf.curPos++);
00589   else 
00590   {
00591     char        c;
00592     nsresult    status;
00593 
00594     status = lexBuf.inputFile->read(&c, 1);
00595     if (status != 1)
00596       return -1;
00597     else
00598       return c;  
00599   }
00600 }
00601 
00602 static int lexGeta()
00603     {
00604     ++lexBuf.len;
00605     return (lexBuf.buf[lexBuf.getPtr] = lexGetc_());
00606     }
00607 
00608 static int lexGeta_(int i)
00609     {
00610     ++lexBuf.len;
00611     return (lexBuf.buf[(lexBuf.getPtr+i)%PR_MAX_LEX_LOOKAHEAD] = lexGetc_());
00612     }
00613 
00614 static void lexSkipLookahead() {
00615     if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) {
00616        /* don't skip EOF. */
00617         lexBuf.getPtr = (lexBuf.getPtr + 1) % PR_MAX_LEX_LOOKAHEAD;
00618        lexBuf.len--;
00619         }
00620     }
00621 
00622 static int lexLookahead() {
00623     int c = (lexBuf.len)?
00624        lexBuf.buf[lexBuf.getPtr]:
00625        lexGeta();
00626     /* do the \r\n -> \n or \r -> \n translation here */
00627     if (c == '\r') {
00628        int a = (lexBuf.len>1)?
00629            lexBuf.buf[(lexBuf.getPtr+1)%PR_MAX_LEX_LOOKAHEAD]:
00630            lexGeta_(1);
00631        if (a == '\n') {
00632            lexSkipLookahead();
00633            }
00634        lexBuf.buf[lexBuf.getPtr] = c = '\n';
00635        }
00636     else if (c == '\n') {
00637        int a = (lexBuf.len>1)?
00638            lexBuf.buf[lexBuf.getPtr+1]:
00639            lexGeta_(1);
00640        if (a == '\r') {
00641            lexSkipLookahead();
00642            }
00643        lexBuf.buf[lexBuf.getPtr] = '\n';
00644        }
00645     return c;
00646     }
00647 
00648 static int lexGetc() {
00649     int c = lexLookahead();
00650     if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) {
00651        /* EOF will remain in lookahead buffer */
00652         lexBuf.getPtr = (lexBuf.getPtr + 1) % PR_MAX_LEX_LOOKAHEAD;
00653        lexBuf.len--;
00654         }
00655     return c;
00656     }
00657 
00658 static void lexSkipLookaheadWord() {
00659     if (lexBuf.strsLen <= lexBuf.len) {
00660        lexBuf.len -= lexBuf.strsLen;
00661        lexBuf.getPtr = (lexBuf.getPtr + lexBuf.strsLen) % PR_MAX_LEX_LOOKAHEAD;
00662        }
00663     }
00664 
00665 static void lexClearToken()
00666     {
00667     lexBuf.strsLen = 0;
00668     }
00669 
00670 static void lexAppendc(int c)
00671     {
00672     lexBuf.strs[lexBuf.strsLen] = c;
00673     /* append up to zero termination */
00674     if (c == 0) return;
00675     lexBuf.strsLen++;
00676     if (lexBuf.strsLen >= lexBuf.maxToken) {
00677        /* double the token string size */
00678        lexBuf.maxToken <<= 1;
00679        lexBuf.strs = (char*) PR_Realloc(lexBuf.strs,lexBuf.maxToken);
00680        }
00681     }
00682 
00683 static char* lexStr() {
00684     return dupStr(lexBuf.strs,lexBuf.strsLen+1);
00685     }
00686 
00687 static void lexSkipWhite() {
00688     int c = lexLookahead();
00689     while (c == ' ' || c == '\t') {
00690        lexSkipLookahead();
00691        c = lexLookahead();
00692        }
00693     }
00694 
00695 static char* lexGetWord() {
00696     int c;
00697     lexSkipWhite();
00698     lexClearToken();
00699     c = lexLookahead();
00700     while (c != EOF && !PL_strchr("\t\n ;:=",(char)c)) {
00701        lexAppendc(c);
00702        lexSkipLookahead();
00703        c = lexLookahead();
00704        }
00705     lexAppendc(0);
00706     return lexStr();
00707     }
00708 
00709 #if 0
00710 static void lexPushLookahead(char *s, int len) {
00711     int putptr;
00712     if (len == 0) len = PL_strlen(s);
00713     putptr = lexBuf.getPtr - len;
00714     /* this function assumes that length of word to push back
00715      /  is not greater than PR_MAX_LEX_LOOKAHEAD.
00716      */
00717     if (putptr < 0) putptr += PR_MAX_LEX_LOOKAHEAD;
00718     lexBuf.getPtr = putptr;
00719     while (*s) {
00720        lexBuf.buf[putptr] = *s++;
00721        putptr = (putptr + 1) % PR_MAX_LEX_LOOKAHEAD;
00722        }
00723     lexBuf.len += len;
00724     }
00725 #endif
00726 
00727 static void lexPushLookaheadc(int c) {
00728     int putptr;
00729     /* can't putback EOF, because it never leaves lookahead buffer */
00730     if (c == EOF) return;
00731     putptr = (int) lexBuf.getPtr - 1;
00732     if (putptr < 0) putptr += PR_MAX_LEX_LOOKAHEAD;
00733     lexBuf.getPtr = putptr;
00734     lexBuf.buf[putptr] = c;
00735     lexBuf.len += 1;
00736     }
00737 
00738 static char* lexLookaheadWord() {
00739     /* this function can lookahead word with max size of PR_MAX_LEX_LOOKAHEAD_0
00740      /  and thing bigger than that will stop the lookahead and return 0;
00741      / leading white spaces are not recoverable.
00742      */
00743     int c;
00744     int len = 0;
00745     int curgetptr = 0;
00746     lexSkipWhite();
00747     lexClearToken();
00748     curgetptr = (int) lexBuf.getPtr;      /* remember! */
00749     while (len < (PR_MAX_LEX_LOOKAHEAD_0)) {
00750        c = lexGetc();
00751        len++;
00752        if (c == EOF || PL_strchr("\t\n ;:=", (char)c)) {
00753            lexAppendc(0);
00754            /* restore lookahead buf. */
00755            lexBuf.len += len;
00756            lexBuf.getPtr = curgetptr;
00757            return lexStr();
00758            }
00759         else
00760            lexAppendc(c);
00761        }
00762     lexBuf.len += len;      /* char that has been moved to lookahead buffer */
00763     lexBuf.getPtr = curgetptr;
00764     return 0;
00765     }
00766 
00767 #ifdef _SUPPORT_LINE_FOLDING
00768 static void handleMoreRFC822LineBreak(int c) {
00769     /* support RFC 822 line break in cases like
00770      * ADR: foo;
00771      *    morefoo;
00772      *    more foo;
00773      */
00774     if (c == ';') {
00775        int a;
00776        lexSkipLookahead();
00777        /* skip white spaces */
00778        a = lexLookahead();
00779        while (a == ' ' || a == '\t') {
00780            lexSkipLookahead();
00781            a = lexLookahead();
00782            }
00783        if (a == '\n') {
00784            lexSkipLookahead();
00785            a = lexLookahead();
00786            if (a == ' ' || a == '\t') {
00787               /* continuation, throw away all the \n and spaces read so
00788                * far
00789                */
00790               lexSkipWhite();
00791               lexPushLookaheadc(';');
00792               }
00793            else {
00794               lexPushLookaheadc('\n');
00795               lexPushLookaheadc(';');
00796               }
00797            }
00798        else {
00799            lexPushLookaheadc(';');
00800            }
00801        }
00802     }
00803 
00804 static char* lexGet1Value() {
00805 /*  int size = 0; */
00806     int c;
00807     lexSkipWhite();
00808     c = lexLookahead();
00809     lexClearToken();
00810     while (c != EOF && c != ';') {
00811        if (c == '\n') {
00812            int a;
00813            lexSkipLookahead();
00814            a  = lexLookahead();
00815            if (a == ' ' || a == '\t') {
00816               lexAppendc(' ');
00817               lexSkipLookahead();
00818               }
00819            else {
00820               lexPushLookaheadc('\n');
00821               break;
00822               }
00823            }
00824        else if (c == '\\') {
00825            int a;
00826            lexSkipLookahead();
00827            a = lexLookahead();
00828            if (a == '\\' || a == ',' || a == ';' || a == ':') {
00829               lexAppendc(a);
00830               }
00831            else if (a == 'n' || a == 'N') {
00832               lexAppendc('\n');
00833               }
00834            else {
00835               lexAppendc(c);
00836               lexAppendc(a);
00837               }
00838            lexSkipLookahead();
00839            }
00840        else {
00841            lexAppendc(c);
00842            lexSkipLookahead();
00843            }
00844        c = lexLookahead();
00845        }
00846     lexAppendc(0);
00847     handleMoreRFC822LineBreak(c);
00848     return c==EOF?0:lexStr();
00849     }
00850 #endif
00851 
00852 
00853 #ifndef _SUPPORT_LINE_FOLDING
00854 static char* lexGetStrUntil(char *termset) {
00855     int c = lexLookahead();
00856     lexClearToken();
00857     while (c != EOF && !PL_strchr(termset,c)) {
00858        lexAppendc(c);
00859        lexSkipLookahead();
00860        c = lexLookahead();
00861        }
00862     lexAppendc(0);
00863     return c==EOF?0:lexStr();
00864     }
00865 #endif /* ! _SUPPORT_LINE_FOLDING */
00866 
00867 static int match_begin_name(int end) {
00868     char *n = lexLookaheadWord();
00869     int token = ID;
00870     if (n) {
00871        if (!PL_strcasecmp(n,"vcard")) token = end?END_VCARD:BEGIN_VCARD;
00872        else if (!PL_strcasecmp(n,"vcalendar")) token = end?END_VCAL:BEGIN_VCAL;
00873        else if (!PL_strcasecmp(n,"vevent")) token = end?END_VEVENT:BEGIN_VEVENT;
00874        else if (!PL_strcasecmp(n,"vtodo")) token = end?END_VTODO:BEGIN_VTODO;
00875        deleteString(n);
00876        return token;
00877        }
00878     return 0;
00879     }
00880 
00881 #if defined(XP_MAC) && defined(__MWERKS__)
00882 #pragma warn_possunwant off
00883 #pragma require_prototypes off
00884 #endif
00885 
00886 void initLex(const char *inputstring, unsigned long inputlen, nsInputFileStream *inputFile)
00887     {
00888     /* initialize lex mode stack */
00889     lexBuf.lexModeStack[lexBuf.lexModeStackTop=0] = L_NORMAL;
00890 
00891     /* iniatialize lex buffer. */
00892     lexBuf.inputString = (char*) inputstring;
00893     lexBuf.inputLen = inputlen;
00894     lexBuf.curPos = 0;
00895     lexBuf.inputFile = inputFile;
00896 
00897     lexBuf.len = 0;
00898     lexBuf.getPtr = 0;
00899 
00900     lexBuf.maxToken = PR_MAXTOKEN;
00901     lexBuf.strs = (char*)PR_CALLOC(PR_MAXTOKEN);
00902     lexBuf.strsLen = 0;
00903 
00904     }
00905 
00906 static void finiLex() {
00907     PR_FREEIF(lexBuf.strs);
00908     }
00909 
00910 
00911 /******************************************************************************/
00912 /* This parses and converts the base64 format for binary encoding into
00913  * a decoded buffer (allocated with new).  See RFC 1521.
00914  */
00915 static char * lexGetDataFromBase64()
00916     {
00917     unsigned long bytesLen = 0, bytesMax = 0;
00918     int quadIx = 0, pad = 0;
00919     unsigned long trip = 0;
00920     unsigned char b;
00921     int c;
00922     unsigned char *bytes = NULL;
00923     unsigned char *oldBytes = NULL;
00924 
00925     DBG_(("db: lexGetDataFromBase64\n"));
00926     while (1) {
00927        c = lexGetc();
00928        if (c == '\n') {
00929            ++mime_lineNum;
00930            if (lexLookahead() == '\n') {
00931               /* a '\n' character by itself means end of data */
00932               break;
00933               }
00934            else continue; /* ignore '\n' */
00935            }
00936        else {
00937            if ((c >= 'A') && (c <= 'Z'))
00938               b = (unsigned char)(c - 'A');
00939            else if ((c >= 'a') && (c <= 'z'))
00940               b = (unsigned char)(c - 'a') + 26;
00941            else if ((c >= '0') && (c <= '9'))
00942               b = (unsigned char)(c - '0') + 52;
00943            else if (c == '+')
00944               b = 62;
00945            else if (c == '/')
00946               b = 63;
00947       else if (c == '=' && (quadIx == 2 || quadIx == 3)) {
00948               b = 0;
00949               pad++;
00950            } else if ((c == ' ') || (c == '\t')) {
00951               continue;
00952            } else { /* error condition */
00953                 if (bytes)
00954                 PR_Free (bytes);
00955                 else if (oldBytes)
00956                 PR_Free (oldBytes);
00957               /* error recovery: skip until 2 adjacent newlines. */
00958               DBG_(("db: invalid character 0x%x '%c'\n", c,c));
00959               if (c != EOF)  {
00960                   c = lexGetc();
00961                   while (c != EOF) {
00962                      if (c == '\n' && lexLookahead() == '\n') {
00963                          ++mime_lineNum;
00964                          break;
00965                          }
00966                      c = lexGetc();
00967                      }
00968                   }
00969               return NULL;
00970               }
00971            trip = (trip << 6) | b;
00972            if (++quadIx == 4) {
00973               unsigned char outBytes[3];
00974               int numOut;
00975               int i;
00976               for (i = 0; i < 3; i++) {
00977                   outBytes[2-i] = (unsigned char)(trip & 0xFF);
00978                   trip >>= 8;
00979                   }
00980               numOut = 3 - pad;
00981               if (bytesLen + numOut > bytesMax) {
00982                   if (!bytes) {
00983                      bytesMax = 1024;
00984                      bytes = (unsigned char*)PR_CALLOC(bytesMax);
00985                      }
00986                   else {
00987                      bytesMax <<= 2;
00988                      oldBytes = bytes;
00989                      bytes = (unsigned char*)PR_Realloc(bytes,bytesMax);
00990                      }
00991                      if (bytes == 0) {
00992                      mime_error("out of memory while processing BASE64 data\n");
00993                      }
00994                   }
00995               if (bytes) {
00996                      memcpy(bytes + bytesLen, outBytes, numOut);
00997                      bytesLen += numOut;
00998               }
00999               trip = 0;
01000               quadIx = 0;
01001         pad = 0;
01002               }
01003            }
01004        } /* while */
01005     DBG_(("db: bytesLen = %d\n",  bytesLen));
01006     /* kludge: all this won't be necessary if we have tree form
01007        representation */
01008        if (bytes) {
01009        setValueWithSize(curProp,bytes,(unsigned int)bytesLen);
01010        PR_FREEIF(bytes);
01011        }
01012     else if (oldBytes) {
01013        setValueWithSize(curProp,oldBytes,(unsigned int)bytesLen);
01014        PR_FREEIF(oldBytes);
01015        }
01016     return 0;
01017     }
01018 
01019 static int match_begin_end_name(int end) {
01020     int token;
01021     lexSkipWhite();
01022     if (lexLookahead() != ':') return ID;
01023     lexSkipLookahead();
01024     lexSkipWhite();
01025     token = match_begin_name(end);
01026     if (token == ID) {
01027        lexPushLookaheadc(':');
01028        DBG_(("db: ID '%s'\n", yylval.str));
01029        return ID;
01030        }
01031     else if (token != 0) {
01032        lexSkipLookaheadWord();
01033        deleteString(yylval.str);
01034        DBG_(("db: begin/end %d\n", token));
01035        return token;
01036        }
01037     return 0;
01038     }
01039 
01040 static char* lexGetQuotedPrintable()
01041     {
01042     char cur;
01043 /*  unsigned long len = 0; */
01044 
01045     lexClearToken();
01046     do {
01047        cur = lexGetc();
01048        switch (cur) {
01049            case '=': {
01050               int c = 0;
01051               int next[2];
01052               int tab [1];
01053               int i;
01054               for (i = 0; i < 2; i++) {
01055                   next[i] = lexGetc();
01056                   if (next[i] >= '0' && next[i] <= '9')
01057                      c = c * 16 + next[i] - '0';
01058                   else if (next[i] >= 'A' && next[i] <= 'F')
01059                      c = c * 16 + next[i] - 'A' + 10;
01060                   else
01061                      break;
01062                   }
01063               if (i == 0) {
01064                   /* single '=' follow by LINESEP is continuation sign? */
01065                   if (next[0] == '\n') {
01066                      tab[0] = lexGetc();
01067                      if (tab[0] == '\t') 
01068                             lexSkipWhite();
01069                      ++mime_lineNum;
01070                      }
01071                  else {
01072                             lexAppendc(cur);
01073                             /* lexPushLookaheadc('=');
01074                             goto EndString; */
01075                      } 
01076                   }
01077               else if (i == 1) {
01078                   lexPushLookaheadc(next[1]);
01079                   lexPushLookaheadc(next[0]);
01080                   lexAppendc('=');
01081               } else {
01082                   lexAppendc(c);
01083                   }
01084               break;
01085               } /* '=' */
01086            case '\n': {
01087               lexPushLookaheadc('\n');
01088               goto EndString;
01089               }
01090            case ';': {
01091               lexPushLookaheadc(';');
01092               goto EndString;
01093               }
01094            case (char)EOF:
01095               break;
01096            default:
01097               lexAppendc(cur);
01098               break;
01099            } /* switch */
01100        } while (cur != (char)EOF);
01101 
01102 EndString:
01103     lexAppendc(0);
01104     return lexStr();
01105     } /* LexQuotedPrintable */
01106 
01107 static int yylex() {
01108 /*  int token = 0; */
01109 
01110     int lexmode = LEXMODE();
01111     if (lexmode == L_VALUES) {
01112        int c = lexGetc();
01113        if (c == ';') {
01114            DBG_(("db: SEMICOLON\n"));
01115 #ifdef _SUPPORT_LINE_FOLDING
01116            lexPushLookaheadc(c);
01117            handleMoreRFC822LineBreak(c);
01118            lexSkipLookahead();
01119 #endif
01120            return SEMICOLON;
01121            }
01122        else if (PL_strchr("\n",(char)c)) {
01123            ++mime_lineNum;
01124            /* consume all line separator(s) adjacent to each other */
01125            c = lexLookahead();
01126            while (PL_strchr("\n",(char)c)) {
01127               lexSkipLookahead();
01128               c = lexLookahead();
01129               ++mime_lineNum;
01130               }
01131            DBG_(("db: LINESEP\n"));
01132            return LINESEP;
01133            }
01134        else {
01135            char *p = 0;
01136            lexPushLookaheadc(c);
01137            if (lexWithinMode(L_BASE64)) {
01138               /* get each char and convert to bin on the fly... */
01139               p = lexGetDataFromBase64();
01140                 yylval.str = p;
01141                 return !p && lexLookahead() == EOF ? 0 : STRING;
01142             }
01143            else if (lexWithinMode(L_QUOTED_PRINTABLE)) {
01144               p = lexGetQuotedPrintable();
01145               }
01146            else {
01147 #ifdef _SUPPORT_LINE_FOLDING
01148               p = lexGet1Value();
01149 #else
01150               p = lexGetStrUntil(";\n");
01151 #endif
01152               }
01153            if (p && (*p || lexLookahead() != EOF)) {
01154               DBG_(("db: STRING: '%s'\n", p));
01155               yylval.str = p;
01156               return STRING;
01157               }
01158            else return 0;
01159            }
01160        }
01161     else {
01162        /* normal mode */
01163        while (1) {
01164            int c = lexGetc();
01165            switch(c) {
01166               case ':': {
01167                   /* consume all line separator(s) adjacent to each other */
01168                   /* ignoring linesep immediately after colon. */
01169                   c = lexLookahead();
01170                   while (PL_strchr("\n",(char)c)) {
01171                      lexSkipLookahead();
01172                      c = lexLookahead();
01173                      ++mime_lineNum;
01174                      }
01175                   DBG_(("db: COLON\n"));
01176                   return COLON;
01177                   }
01178               case ';':
01179                   DBG_(("db: SEMICOLON\n"));
01180                   return SEMICOLON;
01181               case '=':
01182                   DBG_(("db: EQ\n"));
01183                   return EQ;
01184               /* ignore whitespace in this mode */
01185               case '\t':
01186               case ' ': continue;
01187               case '\n': {
01188                   ++mime_lineNum;
01189                   continue;
01190                   }
01191               case EOF: return 0;
01192                   break;
01193               default: {
01194                   lexPushLookaheadc(c);
01195                   if (isalpha(c)) {
01196                      char *t = lexGetWord();
01197                      yylval.str = t;
01198                      if (!PL_strcasecmp(t, "BEGIN")) {
01199                          return match_begin_end_name(0);
01200                          }
01201                      else if (!PL_strcasecmp(t,"END")) {
01202                          return match_begin_end_name(1);
01203                          }
01204                       else {
01205                          DBG_(("db: ID '%s'\n", t));
01206                          return ID;
01207                          }
01208                      }
01209                   else {
01210                      /* unknow token */
01211                      return 0;
01212                      }
01213                   break;
01214                   }
01215               }
01216            }
01217        }
01218     return 0;
01219     }
01220 
01221 
01222 /***************************************************************************/
01223 /***                                             Public Functions                                        ****/
01224 /***************************************************************************/
01225 
01226 static VObject* parse_MIMEHelper()
01227     {
01228     ObjStackTop = -1;
01229     mime_numErrors = 0;
01230     mime_lineNum = 1;
01231     vObjList = 0;
01232     curObj = 0;
01233 
01234     if (yyparse() != 0)
01235        return 0;
01236 
01237     finiLex();
01238     return vObjList;
01239     }
01240 
01241 /******************************************************************************/
01242 VObject* parse_MIME(const char *input, unsigned long len)
01243     {
01244     initLex(input, len, 0);
01245     return parse_MIMEHelper();
01246     }
01247 
01248 
01249 VObject* parse_MIME_FromFile(nsInputFileStream *file)
01250 {
01251   VObject *result;   
01252   long startPos;
01253   
01254   initLex(0,(unsigned long)-1,file);
01255   startPos = file->tell();
01256   if (!(result = parse_MIMEHelper())) {
01257     file->seek(startPos);
01258   }
01259   return result;
01260 }
01261 
01262 VObject* parse_MIME_FromFileName(nsFileSpec *fname)
01263 {
01264 #if !defined(MOZADDRSTANDALONE)
01265   nsInputFileStream *fp = new nsInputFileStream(*fname);
01266   if (fp) 
01267   {
01268     VObject* o = parse_MIME_FromFile(fp);
01269     fp->close();
01270     return o;
01271   }
01272   else {
01273     char msg[80];
01274     PR_snprintf(msg, sizeof(msg), "Can't open file for reading\n");
01275     mime_error_(msg);
01276     return 0;
01277   }
01278 #else
01279   NS_ASSERTION(FALSE, "1.5 <rhp@netscape.com> 06 Jan 2000 08:00");
01280   return 0;
01281 #endif
01282 }
01283 
01284 static MimeErrorHandler mimeErrorHandler;
01285 
01286 void registerMimeErrorHandler(MimeErrorHandler me)
01287     {
01288     mimeErrorHandler = me;
01289     }
01290 
01291 void mime_error(char *s)
01292 {
01293   char msg[256];
01294   if (mimeErrorHandler) {
01295     PR_snprintf(msg, sizeof(msg), "%s at line %d", s, mime_lineNum);
01296     mimeErrorHandler(msg);
01297   }
01298 }
01299 
01300 void mime_error_(char *s)
01301     {
01302     if (mimeErrorHandler) {
01303        mimeErrorHandler(s);
01304        }
01305     }
01306 
01307 /*#line 1221 "y_tab.c"*/
01308 #define YYABORT goto yyabort
01309 #define YYACCEPT goto yyaccept
01310 #define YYERROR goto yyerrlab
01311 int
01312 yyparse()
01313 {
01314     register int yym, yyn, yystate;
01315 #if YYDEBUG
01316     register char *yys;
01317     extern char *getenv();
01318 
01319     if (yys = getenv("YYDEBUG"))
01320     {
01321         yyn = *yys;
01322         if (yyn >= '0' && yyn <= '9')
01323             yydebug = yyn - '0';
01324     }
01325 #endif
01326 
01327     yynerrs = 0;
01328     yyerrflag = 0;
01329     yychar = (-1);
01330 
01331     yyssp = yyss;
01332     yyvsp = yyvs;
01333     *yyssp = yystate = 0;
01334 
01335 yyloop:
01336     if ((yyn = yydefred[yystate])) goto yyreduce;
01337     if (yychar < 0)
01338     {
01339         if ((yychar = yylex()) < 0) yychar = 0;
01340 #if YYDEBUG
01341         if (yydebug)
01342         {
01343             yys = 0;
01344             if (yychar <= YYPR_MAXTOKEN) yys = yyname[yychar];
01345             if (!yys) yys = "illegal-symbol";
01346             printf("yydebug: state %d, reading %d (%s)\n", yystate,
01347                     yychar, yys);
01348         }
01349 #endif
01350     }
01351     if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
01352             yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
01353     {
01354 #if YYDEBUG
01355         if (yydebug)
01356             printf("yydebug: state %d, shifting to state %d\n",
01357                     yystate, yytable[yyn]);
01358 #endif
01359         if (yyssp >= yyss + yystacksize - 1)
01360         {
01361             goto yyoverflow;
01362         }
01363         *++yyssp = yystate = yytable[yyn];
01364         *++yyvsp = yylval;
01365         yychar = (-1);
01366         if (yyerrflag > 0)  --yyerrflag;
01367         goto yyloop;
01368     }
01369     if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
01370             yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
01371     {
01372         yyn = yytable[yyn];
01373         goto yyreduce;
01374     }
01375     if (yyerrflag) goto yyinrecovery;
01376 #ifdef lint
01377     goto yynewerror;
01378 #endif
01379 /*yynewerror: */
01380     yyerror("syntax error");
01381 #ifdef lint
01382     goto yyerrlab;
01383 #endif
01384 yyerrlab:
01385     ++yynerrs;
01386 yyinrecovery:
01387     if (yyerrflag < 3)
01388     {
01389         yyerrflag = 3;
01390         for (;;)
01391         {
01392             if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
01393                     yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
01394             {
01395 #if YYDEBUG
01396                 if (yydebug)
01397                     printf("yydebug: state %d, error recovery shifting\
01398  to state %d\n", *yyssp, yytable[yyn]);
01399 #endif
01400                 if (yyssp >= yyss + yystacksize - 1)
01401                 {
01402                     goto yyoverflow;
01403                 }
01404                 *++yyssp = yystate = yytable[yyn];
01405                 *++yyvsp = yylval;
01406                 goto yyloop;
01407             }
01408             else
01409             {
01410 #if YYDEBUG
01411                 if (yydebug)
01412                     printf("yydebug: error recovery discarding state %d\n",
01413                             *yyssp);
01414 #endif
01415                 if (yyssp <= yyss) goto yyabort;
01416                 --yyssp;
01417                 --yyvsp;
01418             }
01419         }
01420     }
01421     else
01422     {
01423         if (yychar == 0) goto yyabort;
01424 #if YYDEBUG
01425         if (yydebug)
01426         {
01427             yys = 0;
01428             if (yychar <= YYPR_MAXTOKEN) yys = yyname[yychar];
01429             if (!yys) yys = "illegal-symbol";
01430             printf("yydebug: state %d, error recovery discards token %d (%s)\n",
01431                     yystate, yychar, yys);
01432         }
01433 #endif
01434         yychar = (-1);
01435         goto yyloop;
01436     }
01437 yyreduce:
01438 #if YYDEBUG
01439     if (yydebug)
01440         printf("yydebug: state %d, reducing by rule %d (%s)\n",
01441                 yystate, yyn, yyrule[yyn]);
01442 #endif
01443     yym = yylen[yyn];
01444     yyval = yyvsp[1-yym];
01445     switch (yyn)
01446     {
01447 case 2:
01448 /*#line 282 "vcc.y"*/
01449 { addList(&vObjList, yyvsp[0].vobj ); curObj = 0; }
01450 break;
01451 case 4:
01452 /*#line 285 "vcc.y"*/
01453 { addList(&vObjList, yyvsp[0].vobj ); curObj = 0; }
01454 break;
01455 case 7:
01456 /*#line 294 "vcc.y"*/
01457 {
01458        lexPushMode(L_VCARD);
01459        if (!pushVObject(VCCardProp)) YYERROR;
01460        }
01461 break;
01462 case 8:
01463 /*#line 299 "vcc.y"*/
01464 {
01465        lexPopMode(0);
01466        yyval.vobj  = popVObject();
01467        }
01468 break;
01469 case 9:
01470 /*#line 304 "vcc.y"*/
01471 {
01472        lexPushMode(L_VCARD);
01473        if (!pushVObject(VCCardProp)) YYERROR;
01474        }
01475 break;
01476 case 10:
01477 /*#line 309 "vcc.y"*/
01478 {
01479        lexPopMode(0);
01480        yyval.vobj  = popVObject();
01481        }
01482 break;
01483 case 13:
01484 /*#line 320 "vcc.y"*/
01485 {
01486        lexPushMode(L_VALUES);
01487        }
01488 break;
01489 case 14:
01490 /*#line 324 "vcc.y"*/
01491 {
01492        if (lexWithinMode(L_BASE64) || lexWithinMode(L_QUOTED_PRINTABLE))
01493           lexPopMode(0);
01494        lexPopMode(0);
01495        }
01496 break;
01497 case 16:
01498 /*#line 332 "vcc.y"*/
01499 {
01500        enterProps(yyvsp[0].str );
01501        }
01502 break;
01503 case 18:
01504 /*#line 337 "vcc.y"*/
01505 {
01506        enterProps(yyvsp[0].str );
01507        }
01508 break;
01509 case 22:
01510 /*#line 350 "vcc.y"*/
01511 {
01512        enterAttr(yyvsp[0].str ,0);
01513        }
01514 break;
01515 case 23:
01516 /*#line 354 "vcc.y"*/
01517 {
01518        enterAttr(yyvsp[-2].str ,yyvsp[0].str );
01519 
01520        }
01521 break;
01522 case 25:
01523 /*#line 363 "vcc.y"*/
01524 { enterValues(yyvsp[-1].str ); }
01525 break;
01526 case 27:
01527 /*#line 365 "vcc.y"*/
01528 { enterValues(yyvsp[0].str ); }
01529 break;
01530 case 29:
01531 /*#line 370 "vcc.y"*/
01532 { yyval.str  = 0; }
01533 break;
01534 case 30:
01535 /*#line 375 "vcc.y"*/
01536 { if (!pushVObject(VCCalProp)) YYERROR; }
01537 break;
01538 case 31:
01539 /*#line 378 "vcc.y"*/
01540 { yyval.vobj  = popVObject(); }
01541 break;
01542 case 32:
01543 /*#line 380 "vcc.y"*/
01544 { if (!pushVObject(VCCalProp)) YYERROR; }
01545 break;
01546 case 33:
01547 /*#line 382 "vcc.y"*/
01548 { yyval.vobj  = popVObject(); }
01549 break;
01550 case 39:
01551 /*#line 397 "vcc.y"*/
01552 {
01553        lexPushMode(L_VEVENT);
01554        if (!pushVObject(VCEventProp)) YYERROR;
01555        }
01556 break;
01557 case 40:
01558 /*#line 403 "vcc.y"*/
01559 {
01560        lexPopMode(0);
01561        popVObject();
01562        }
01563 break;
01564 case 41:
01565 /*#line 408 "vcc.y"*/
01566 {
01567        lexPushMode(L_VEVENT);
01568        if (!pushVObject(VCEventProp)) YYERROR;
01569        }
01570 break;
01571 case 42:
01572 /*#line 413 "vcc.y"*/
01573 {
01574        lexPopMode(0);
01575        popVObject();
01576        }
01577 break;
01578 case 43:
01579 /*#line 421 "vcc.y"*/
01580 {
01581        lexPushMode(L_VTODO);
01582        if (!pushVObject(VCTodoProp)) YYERROR;
01583        }
01584 break;
01585 case 44:
01586 /*#line 427 "vcc.y"*/
01587 {
01588        lexPopMode(0);
01589        popVObject();
01590        }
01591 break;
01592 case 45:
01593 /*#line 432 "vcc.y"*/
01594 {
01595        lexPushMode(L_VTODO);
01596        if (!pushVObject(VCTodoProp)) YYERROR;
01597        }
01598 break;
01599 case 46:
01600 /*#line 437 "vcc.y"*/
01601 {
01602        lexPopMode(0);
01603        popVObject();
01604        }
01605 break;
01606 /*#line 1520 "y_tab.c"*/
01607     }
01608     yyssp -= yym;
01609     yystate = *yyssp;
01610     yyvsp -= yym;
01611     yym = yylhs[yyn];
01612     if (yystate == 0 && yym == 0)
01613     {
01614 #if YYDEBUG
01615         if (yydebug)
01616             printf("yydebug: after reduction, shifting from state 0 to\
01617  state %d\n", YYFINAL);
01618 #endif
01619         yystate = YYFINAL;
01620         *++yyssp = YYFINAL;
01621         *++yyvsp = yyval;
01622         if (yychar < 0)
01623         {
01624             if ((yychar = yylex()) < 0) yychar = 0;
01625 #if YYDEBUG
01626             if (yydebug)
01627             {
01628                 yys = 0;
01629                 if (yychar <= YYPR_MAXTOKEN) yys = yyname[yychar];
01630                 if (!yys) yys = "illegal-symbol";
01631                 printf("yydebug: state %d, reading %d (%s)\n",
01632                         YYFINAL, yychar, yys);
01633             }
01634 #endif
01635         }
01636         if (yychar == 0) goto yyaccept;
01637         goto yyloop;
01638     }
01639     if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
01640             yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
01641         yystate = yytable[yyn];
01642     else
01643         yystate = yydgoto[yym];
01644 #if YYDEBUG
01645     if (yydebug)
01646         printf("yydebug: after reduction, shifting from state %d \
01647 to state %d\n", *yyssp, yystate);
01648 #endif
01649     if (yyssp >= yyss + yystacksize - 1)
01650     {
01651         goto yyoverflow;
01652     }
01653     *++yyssp = yystate;
01654     *++yyvsp = yyval;
01655     goto yyloop;
01656 yyoverflow:
01657     yyerror("yacc stack overflow");
01658 yyabort:
01659     return (1);
01660 yyaccept:
01661     return (0);
01662 }