summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--library/backend/vcc.y2438
-rw-r--r--library/backend/vcc_yacc.cpp2153
2 files changed, 2298 insertions, 2293 deletions
diff --git a/library/backend/vcc.y b/library/backend/vcc.y
index bec2955..eca7c32 100644
--- a/library/backend/vcc.y
+++ b/library/backend/vcc.y
@@ -1,1219 +1,1219 @@
1%{ 1%{
2 2
3/*************************************************************************** 3/***************************************************************************
4(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International 4(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
5Business Machines Corporation and Siemens Rolm Communications Inc. 5Business Machines Corporation and Siemens Rolm Communications Inc.
6 6
7For purposes of this license notice, the term Licensors shall mean, 7For purposes of this license notice, the term Licensors shall mean,
8collectively, Apple Computer, Inc., AT&T Corp., International 8collectively, Apple Computer, Inc., AT&T Corp., International
9Business Machines Corporation and Siemens Rolm Communications Inc. 9Business Machines Corporation and Siemens Rolm Communications Inc.
10The term Licensor shall mean any of the Licensors. 10The term Licensor shall mean any of the Licensors.
11 11
12Subject to acceptance of the following conditions, permission is hereby 12Subject to acceptance of the following conditions, permission is hereby
13granted by Licensors without the need for written agreement and without 13granted by Licensors without the need for written agreement and without
14license or royalty fees, to use, copy, modify and distribute this 14license or royalty fees, to use, copy, modify and distribute this
15software for any purpose. 15software for any purpose.
16 16
17The above copyright notice and the following four paragraphs must be 17The above copyright notice and the following four paragraphs must be
18reproduced in all copies of this software and any software including 18reproduced in all copies of this software and any software including
19this software. 19this software.
20 20
21THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE 21THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
22ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR 22ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
23MODIFICATIONS. 23MODIFICATIONS.
24 24
25IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT, 25IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
26INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT 26INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
27OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 27OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
28DAMAGE. 28DAMAGE.
29 29
30EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, 30EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
31INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE 31INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
32IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 32IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
33PURPOSE. 33PURPOSE.
34 34
35The software is provided with RESTRICTED RIGHTS. Use, duplication, or 35The software is provided with RESTRICTED RIGHTS. Use, duplication, or
36disclosure by the government are subject to restrictions set forth in 36disclosure by the government are subject to restrictions set forth in
37DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. 37DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
38 38
39***************************************************************************/ 39***************************************************************************/
40 40
41/* 41/*
42 * src: vcc.c 42 * src: vcc.c
43 * doc: Parser for vCard and vCalendar. Note that this code is 43 * doc: Parser for vCard and vCalendar. Note that this code is
44 * generated by a yacc parser generator. Generally it should not 44 * generated by a yacc parser generator. Generally it should not
45 * be edited by hand. The real source is vcc.y. The #line directives 45 * be edited by hand. The real source is vcc.y. The #line directives
46 * can be commented out here to make it easier to trace through 46 * can be commented out here to make it easier to trace through
47 * in a debugger. However, if a bug is found it should 47 * in a debugger. However, if a bug is found it should
48 * be fixed in vcc.y and this file regenerated. 48 * be fixed in vcc.y and this file regenerated.
49 */ 49 */
50 50
51 51
52/* debugging utilities */ 52/* debugging utilities */
53#if __DEBUG 53#if __DEBUG
54#define DBG_(x) printf x 54#define DBG_(x) printf x
55#else 55#else
56#define DBG_(x) 56#define DBG_(x)
57#endif 57#endif
58 58
59/**** External Functions ****/ 59/**** External Functions ****/
60 60
61/* assign local name to parser variables and functions so that 61/* assign local name to parser variables and functions so that
62 we can use more than one yacc based parser. 62 we can use more than one yacc based parser.
63*/ 63*/
64 64
65#if 0 65#if 0
66#define yyparse mime_parse 66#define yyparse mime_parse
67#define yylex mime_lex 67#define yylex mime_lex
68#define yyerror mime_error 68#define yyerror mime_error
69#define yychar mime_char 69#define yychar mime_char
70/* #define p_yyval p_mime_val */ 70/* #define p_yyval p_mime_val */
71#undef yyval 71#undef yyval
72#define yyval mime_yyval 72#define yyval mime_yyval
73/* #define p_yylval p_mime_lval */ 73/* #define p_yylval p_mime_lval */
74#undef yylval 74#undef yylval
75#define yylval mime_yylval 75#define yylval mime_yylval
76#define yydebug mime_debug 76#define yydebug mime_debug
77#define yynerrs mime_nerrs 77#define yynerrs mime_nerrs
78#define yyerrflag mime_errflag 78#define yyerrflag mime_errflag
79#define yyss mime_ss 79#define yyss mime_ss
80#define yyssp mime_ssp 80#define yyssp mime_ssp
81#define yyvs mime_vs 81#define yyvs mime_vs
82#define yyvsp mime_vsp 82#define yyvsp mime_vsp
83#define yylhs mime_lhs 83#define yylhs mime_lhs
84#define yylen mime_len 84#define yylen mime_len
85#define yydefred mime_defred 85#define yydefred mime_defred
86#define yydgoto mime_dgoto 86#define yydgoto mime_dgoto
87#define yysindex mime_sindex 87#define yysindex mime_sindex
88#define yyrindex mime_rindex 88#define yyrindex mime_rindex
89#define yygindex mime_gindex 89#define yygindex mime_gindex
90#define yytable mime_table 90#define yytable mime_table
91#define yycheck mime_check 91#define yycheck mime_check
92#define yyname mime_name 92#define yyname mime_name
93#define yyrule mime_rule 93#define yyrule mime_rule
94#ifdef YYPREFIX 94#ifdef YYPREFIX
95#undef YYPREFIX 95#undef YYPREFIX
96#endif 96#endif
97#define YYPREFIX "mime_" 97#define YYPREFIX "mime_"
98#endif 98#endif
99 99
100 100
101#ifndef _NO_LINE_FOLDING 101#ifndef _NO_LINE_FOLDING
102#define _SUPPORT_LINE_FOLDING 1 102#define _SUPPORT_LINE_FOLDING 1
103#endif 103#endif
104 104
105/* undef below if compile with MFC */ 105/* undef below if compile with MFC */
106/* #define INCLUDEMFC 1 */ 106/* #define INCLUDEMFC 1 */
107 107
108#if defined(WIN32) || defined(_WIN32) 108#if defined(WIN32) || defined(_WIN32)
109#ifdef INCLUDEMFC 109#ifdef INCLUDEMFC
110#include <afx.h> 110#include <afx.h>
111#endif 111#endif
112#endif 112#endif
113 113
114#include <string.h> 114#include <string.h>
115#ifndef __MWERKS__ 115#ifndef __MWERKS__
116#include <stdlib.h> 116#include <stdlib.h>
117#endif 117#endif
118#include <stdio.h> 118#include <stdio.h>
119#include <stdlib.h> 119#include <stdlib.h>
120#include <ctype.h> 120#include <ctype.h>
121 121
122//#ifdef PALMTOPCENTER 122//#ifdef PALMTOPCENTER
123//#include <qpe/vobject_p.h> 123//#include <qpe/vobject_p.h>
124//#else 124//#else
125#include "vobject_p.h" 125#include "vobject_p.h"
126//#endif 126//#endif
127 127
128/**** Types, Constants ****/ 128/**** Types, Constants ****/
129 129
130 #define YYDEBUG 0/* 1 to compile in some debugging code */ 130 #define YYDEBUG 0/* 1 to compile in some debugging code */
131 #define MAXTOKEN 256/* maximum token (line) length */ 131 #define MAXTOKEN 256/* maximum token (line) length */
132 #define YYSTACKSIZE 100// ~unref ? 132 #define YYSTACKSIZE 100// ~unref ?
133 #define MAXLEVEL 10/* max # of nested objects parseable */ 133 #define MAXLEVEL 10/* max # of nested objects parseable */
134 /* (includes outermost) */ 134 /* (includes outermost) */
135 135
136 136
137/**** Global Variables ****/ 137/**** Global Variables ****/
138int mime_lineNum, mime_numErrors; /* yyerror() can use these */ 138int mime_lineNum, mime_numErrors; /* yyerror() can use these */
139static VObject* vObjList; 139static VObject* vObjList;
140static VObject *curProp; 140static VObject *curProp;
141static VObject *curObj; 141static VObject *curObj;
142static VObject* ObjStack[MAXLEVEL]; 142static VObject* ObjStack[MAXLEVEL];
143static int ObjStackTop; 143static int ObjStackTop;
144 144
145 145
146/* A helpful utility for the rest of the app. */ 146/* A helpful utility for the rest of the app. */
147#if __CPLUSPLUS__ 147#if __CPLUSPLUS__
148extern "C" { 148extern "C" {
149#endif 149#endif
150 150
151 extern void yyerror(char *s); 151 extern void yyerror(char *s);
152 152
153#if __CPLUSPLUS__ 153#if __CPLUSPLUS__
154 }; 154 };
155#endif 155#endif
156 156
157int yyparse(); 157int yyparse();
158 158
159enum LexMode { 159enum LexMode {
160 L_NORMAL, 160 L_NORMAL,
161 L_VCARD, 161 L_VCARD,
162 L_VCAL, 162 L_VCAL,
163 L_VEVENT, 163 L_VEVENT,
164 L_VTODO, 164 L_VTODO,
165 L_VALUES, 165 L_VALUES,
166 L_BASE64, 166 L_BASE64,
167 L_QUOTED_PRINTABLE 167 L_QUOTED_PRINTABLE
168 }; 168 };
169 169
170/**** Private Forward Declarations ****/ 170/**** Private Forward Declarations ****/
171static int pushVObject(const char *prop); 171static int pushVObject(const char *prop);
172static VObject* popVObject(); 172static VObject* popVObject();
173static void lexPopMode(int top); 173static void lexPopMode(int top);
174static int lexWithinMode(enum LexMode mode); 174static int lexWithinMode(enum LexMode mode);
175static void lexPushMode(enum LexMode mode); 175static void lexPushMode(enum LexMode mode);
176static void enterProps(const char *s); 176static void enterProps(const char *s);
177static void enterAttr(const char *s1, const char *s2); 177static void enterAttr(const char *s1, const char *s2);
178static void enterValues(const char *value); 178static void enterValues(const char *value);
179#define mime_error yyerror 179#define mime_error yyerror
180void mime_error(char *s); 180void mime_error(char *s);
181void mime_error_(char *s); 181void mime_error_(char *s);
182 182
183%} 183%}
184 184
185/***************************************************************************/ 185/***************************************************************************/
186/*** The grammar ****/ 186/*** The grammar ****/
187/***************************************************************************/ 187/***************************************************************************/
188 188
189%union { 189%union {
190 char *str; 190 char *str;
191 VObject *vobj; 191 VObject *vobj;
192 } 192 }
193 193
194%token 194%token
195 EQ COLON DOT SEMICOLON SPACE HTAB LINESEP NEWLINE 195 EQ COLON DOT SEMICOLON SPACE HTAB LINESEP NEWLINE
196 BEGIN_VCARD END_VCARD BEGIN_VCAL END_VCAL 196 BEGIN_VCARD END_VCARD BEGIN_VCAL END_VCAL
197 BEGIN_VEVENT END_VEVENT BEGIN_VTODO END_VTODO 197 BEGIN_VEVENT END_VEVENT BEGIN_VTODO END_VTODO
198 ID 198 ID
199 199
200/* 200/*
201 * NEWLINE is the token that would occur outside a vCard, 201 * NEWLINE is the token that would occur outside a vCard,
202 * while LINESEP is the token that would occur inside a vCard. 202 * while LINESEP is the token that would occur inside a vCard.
203 */ 203 */
204 204
205%token <str> 205%token <str>
206 STRING ID 206 STRING ID
207 207
208%type <str> name value 208%type <str> name value
209 209
210%type <vobj> vcard vcal vobject 210%type <vobj> vcard vcal vobject
211 211
212%start mime 212%start mime
213 213
214%% 214%%
215 215
216 216
217mime: vobjects 217mime: vobjects
218 ; 218 ;
219 219
220vobjects: vobjects vobject 220vobjects: vobjects vobject
221 { addList(&vObjList, $2); curObj = 0; } 221 { addList(&vObjList, $2); curObj = 0; }
222 | vobject 222 | vobject
223 { addList(&vObjList, $1); curObj = 0; } 223 { addList(&vObjList, $1); curObj = 0; }
224 ; 224 ;
225 225
226vobject: vcard 226vobject: vcard
227 | vcal 227 | vcal
228 ; 228 ;
229 229
230vcard: 230vcard:
231 BEGIN_VCARD 231 BEGIN_VCARD
232 { 232 {
233 lexPushMode(L_VCARD); 233 lexPushMode(L_VCARD);
234 if (!pushVObject(VCCardProp)) YYERROR; 234 if (!pushVObject(VCCardProp)) YYERROR;
235 } 235 }
236 items END_VCARD 236 items END_VCARD
237 { 237 {
238 lexPopMode(0); 238 lexPopMode(0);
239 $$ = popVObject(); 239 $$ = popVObject();
240 } 240 }
241 | BEGIN_VCARD 241 | BEGIN_VCARD
242 { 242 {
243 lexPushMode(L_VCARD); 243 lexPushMode(L_VCARD);
244 if (!pushVObject(VCCardProp)) YYERROR; 244 if (!pushVObject(VCCardProp)) YYERROR;
245 } 245 }
246 END_VCARD 246 END_VCARD
247 { 247 {
248 lexPopMode(0); 248 lexPopMode(0);
249 $$ = popVObject(); 249 $$ = popVObject();
250 } 250 }
251 ; 251 ;
252 252
253items: items item 253items: items item
254 | item 254 | item
255 ; 255 ;
256 256
257item: prop COLON 257item: prop COLON
258 { 258 {
259 lexPushMode(L_VALUES); 259 lexPushMode(L_VALUES);
260 } 260 }
261 values LINESEP 261 values LINESEP
262 { 262 {
263 if (lexWithinMode(L_BASE64) || lexWithinMode(L_QUOTED_PRINTABLE)) 263 if (lexWithinMode(L_BASE64) || lexWithinMode(L_QUOTED_PRINTABLE))
264 lexPopMode(0); 264 lexPopMode(0);
265 lexPopMode(0); 265 lexPopMode(0);
266 } 266 }
267 | error 267 | error
268 ; 268 ;
269 269
270prop: name 270prop: name
271 { 271 {
272 enterProps($1); 272 enterProps($1);
273 } 273 }
274 attr_params 274 attr_params
275 | name 275 | name
276 { 276 {
277 enterProps($1); 277 enterProps($1);
278 } 278 }
279 ; 279 ;
280 280
281attr_params: attr_params attr_param 281attr_params: attr_params attr_param
282 | attr_param 282 | attr_param
283 ; 283 ;
284 284
285attr_param: SEMICOLON attr 285attr_param: SEMICOLON attr
286 ; 286 ;
287 287
288attr: name 288attr: name
289 { 289 {
290 enterAttr($1,0); 290 enterAttr($1,0);
291 } 291 }
292 | name EQ name 292 | name EQ name
293 { 293 {
294 enterAttr($1,$3); 294 enterAttr($1,$3);
295 295
296 } 296 }
297 ; 297 ;
298 298
299name: ID 299name: ID
300 ; 300 ;
301 301
302values: value SEMICOLON { enterValues($1); } values 302values: value SEMICOLON { enterValues($1); } values
303 | value 303 | value
304 { enterValues($1); } 304 { enterValues($1); }
305 ; 305 ;
306 306
307value: STRING 307value: STRING
308 | 308 |
309 { $$ = 0; } 309 { $$ = 0; }
310 ; 310 ;
311 311
312vcal: 312vcal:
313 BEGIN_VCAL 313 BEGIN_VCAL
314 { if (!pushVObject(VCCalProp)) YYERROR; } 314 { if (!pushVObject(VCCalProp)) YYERROR; }
315 calitems 315 calitems
316 END_VCAL 316 END_VCAL
317 { $$ = popVObject(); } 317 { $$ = popVObject(); }
318 | BEGIN_VCAL 318 | BEGIN_VCAL
319 { if (!pushVObject(VCCalProp)) YYERROR; } 319 { if (!pushVObject(VCCalProp)) YYERROR; }
320 END_VCAL 320 END_VCAL
321 { $$ = popVObject(); } 321 { $$ = popVObject(); }
322 ; 322 ;
323 323
324calitems: calitems calitem 324calitems: calitems calitem
325 | calitem 325 | calitem
326 ; 326 ;
327 327
328calitem: 328calitem:
329 eventitem 329 eventitem
330 | todoitem 330 | todoitem
331 | items 331 | items
332 ; 332 ;
333 333
334eventitem: 334eventitem:
335 BEGIN_VEVENT 335 BEGIN_VEVENT
336 { 336 {
337 lexPushMode(L_VEVENT); 337 lexPushMode(L_VEVENT);
338 if (!pushVObject(VCEventProp)) YYERROR; 338 if (!pushVObject(VCEventProp)) YYERROR;
339 } 339 }
340 items 340 items
341 END_VEVENT 341 END_VEVENT
342 { 342 {
343 lexPopMode(0); 343 lexPopMode(0);
344 popVObject(); 344 popVObject();
345 } 345 }
346 | BEGIN_VEVENT 346 | BEGIN_VEVENT
347 { 347 {
348 lexPushMode(L_VEVENT); 348 lexPushMode(L_VEVENT);
349 if (!pushVObject(VCEventProp)) YYERROR; 349 if (!pushVObject(VCEventProp)) YYERROR;
350 } 350 }
351 END_VEVENT 351 END_VEVENT
352 { 352 {
353 lexPopMode(0); 353 lexPopMode(0);
354 popVObject(); 354 popVObject();
355 } 355 }
356 ; 356 ;
357 357
358todoitem: 358todoitem:
359 BEGIN_VTODO 359 BEGIN_VTODO
360 { 360 {
361 lexPushMode(L_VTODO); 361 lexPushMode(L_VTODO);
362 if (!pushVObject(VCTodoProp)) YYERROR; 362 if (!pushVObject(VCTodoProp)) YYERROR;
363 } 363 }
364 items 364 items
365 END_VTODO 365 END_VTODO
366 { 366 {
367 lexPopMode(0); 367 lexPopMode(0);
368 popVObject(); 368 popVObject();
369 } 369 }
370 | BEGIN_VTODO 370 | BEGIN_VTODO
371 { 371 {
372 lexPushMode(L_VTODO); 372 lexPushMode(L_VTODO);
373 if (!pushVObject(VCTodoProp)) YYERROR; 373 if (!pushVObject(VCTodoProp)) YYERROR;
374 } 374 }
375 END_VTODO 375 END_VTODO
376 { 376 {
377 lexPopMode(0); 377 lexPopMode(0);
378 popVObject(); 378 popVObject();
379 } 379 }
380 ; 380 ;
381 381
382%% 382%%
383/*------------------------------------*/ 383/*------------------------------------*/
384static int pushVObject(const char *prop) 384static int pushVObject(const char *prop)
385 { 385 {
386 VObject *newObj; 386 VObject *newObj;
387 if (ObjStackTop == MAXLEVEL) 387 if (ObjStackTop == MAXLEVEL)
388 return FALSE; 388 return FALSE;
389 389
390 ObjStack[++ObjStackTop] = curObj; 390 ObjStack[++ObjStackTop] = curObj;
391 391
392 if (curObj) { 392 if (curObj) {
393 newObj = addProp(curObj,prop); 393 newObj = addProp(curObj,prop);
394 curObj = newObj; 394 curObj = newObj;
395 } 395 }
396 else 396 else
397 curObj = newVObject(prop); 397 curObj = newVObject(prop);
398 398
399 return TRUE; 399 return TRUE;
400 } 400 }
401 401
402 402
403/*---------------------------------------*/ 403/*---------------------------------------*/
404/* This pops the recently built vCard off the stack and returns it. */ 404/* This pops the recently built vCard off the stack and returns it. */
405static VObject* popVObject() 405static VObject* popVObject()
406 { 406 {
407 VObject *oldObj; 407 VObject *oldObj;
408 if (ObjStackTop < 0) { 408 if (ObjStackTop < 0) {
409 yyerror("pop on empty Object Stack\n"); 409 yyerror("pop on empty Object Stack\n");
410 return 0; 410 return 0;
411 } 411 }
412 oldObj = curObj; 412 oldObj = curObj;
413 curObj = ObjStack[ObjStackTop--]; 413 curObj = ObjStack[ObjStackTop--];
414 414
415 return oldObj; 415 return oldObj;
416 } 416 }
417 417
418 418
419static void enterValues(const char *value) 419static void enterValues(const char *value)
420 { 420 {
421 if (fieldedProp && *fieldedProp) { 421 if (fieldedProp && *fieldedProp) {
422 if (value) { 422 if (value) {
423 addPropValue(curProp,*fieldedProp,value); 423 addPropValue(curProp,*fieldedProp,value);
424 } 424 }
425 /* else this field is empty, advance to next field */ 425 /* else this field is empty, advance to next field */
426 fieldedProp++; 426 fieldedProp++;
427 } 427 }
428 else { 428 else {
429 if (value) { 429 if (value) {
430 setVObjectStringZValue_(curProp,strdup( value )); 430 setVObjectStringZValue_(curProp,strdup( value ));
431 } 431 }
432 } 432 }
433 deleteStr(value); 433 deleteStr(value);
434 } 434 }
435 435
436static void enterProps(const char *s) 436static void enterProps(const char *s)
437 { 437 {
438 curProp = addGroup(curObj,s); 438 curProp = addGroup(curObj,s);
439 deleteStr(s); 439 deleteStr(s);
440 } 440 }
441 441
442static void enterAttr(const char *s1, const char *s2) 442static void enterAttr(const char *s1, const char *s2)
443 { 443 {
444 const char *p1, *p2=0; 444 const char *p1, *p2=0;
445 p1 = lookupProp_(s1); 445 p1 = lookupProp_(s1);
446 if (s2) { 446 if (s2) {
447 VObject *a; 447 VObject *a;
448 p2 = lookupProp_(s2); 448 p2 = lookupProp_(s2);
449 a = addProp(curProp,p1); 449 a = addProp(curProp,p1);
450 setVObjectStringZValue(a,p2); 450 setVObjectStringZValue(a,p2);
451 } 451 }
452 else 452 else
453 addProp(curProp,p1); 453 addProp(curProp,p1);
454 if (qstricmp(p1,VCBase64Prop) == 0 || (s2 && qstricmp(p2,VCBase64Prop)==0)) 454 if (qstricmp(p1,VCBase64Prop) == 0 || (s2 && qstricmp(p2,VCBase64Prop)==0))
455 lexPushMode(L_BASE64); 455 lexPushMode(L_BASE64);
456 else if (qstricmp(p1,VCQuotedPrintableProp) == 0 456 else if (qstricmp(p1,VCQuotedPrintableProp) == 0
457 || (s2 && qstricmp(p2,VCQuotedPrintableProp)==0)) 457 || (s2 && qstricmp(p2,VCQuotedPrintableProp)==0))
458 lexPushMode(L_QUOTED_PRINTABLE); 458 lexPushMode(L_QUOTED_PRINTABLE);
459 deleteStr(s1); deleteStr(s2); 459 deleteStr(s1); deleteStr(s2);
460 } 460 }
461 461
462 462
463#define MAX_LEX_LOOKAHEAD_0 32 463#define MAX_LEX_LOOKAHEAD_0 32
464#define MAX_LEX_LOOKAHEAD 64 464#define MAX_LEX_LOOKAHEAD 64
465#define MAX_LEX_MODE_STACK_SIZE 10 465#define MAX_LEX_MODE_STACK_SIZE 10
466#define LEXMODE() (lexBuf.lexModeStack[lexBuf.lexModeStackTop]) 466#define LEXMODE() (lexBuf.lexModeStack[lexBuf.lexModeStackTop])
467 467
468struct LexBuf { 468struct LexBuf {
469 /* input */ 469 /* input */
470#ifdef INCLUDEMFC 470#ifdef INCLUDEMFC
471 CFile *inputFile; 471 CFile *inputFile;
472#else 472#else
473 FILE *inputFile; 473 FILE *inputFile;
474#endif 474#endif
475 char *inputString; 475 char *inputString;
476 unsigned long curPos; 476 unsigned long curPos;
477 unsigned long inputLen; 477 unsigned long inputLen;
478 /* lookahead buffer */ 478 /* lookahead buffer */
479 /* -- lookahead buffer is short instead of char so that EOF 479 /* -- lookahead buffer is short instead of char so that EOF
480 / can be represented correctly. 480 / can be represented correctly.
481 */ 481 */
482 unsigned long len; 482 unsigned long len;
483 short buf[MAX_LEX_LOOKAHEAD]; 483 short buf[MAX_LEX_LOOKAHEAD];
484 unsigned long getPtr; 484 unsigned long getPtr;
485 /* context stack */ 485 /* context stack */
486 unsigned long lexModeStackTop; 486 unsigned long lexModeStackTop;
487 enum LexMode lexModeStack[MAX_LEX_MODE_STACK_SIZE]; 487 enum LexMode lexModeStack[MAX_LEX_MODE_STACK_SIZE];
488 /* token buffer */ 488 /* token buffer */
489 unsigned long maxToken; 489 unsigned long maxToken;
490 char *strs; 490 char *strs;
491 unsigned long strsLen; 491 unsigned long strsLen;
492 } lexBuf; 492 } lexBuf;
493 493
494static void lexPushMode(enum LexMode mode) 494static void lexPushMode(enum LexMode mode)
495 { 495 {
496 if (lexBuf.lexModeStackTop == (MAX_LEX_MODE_STACK_SIZE-1)) 496 if (lexBuf.lexModeStackTop == (MAX_LEX_MODE_STACK_SIZE-1))
497 yyerror("lexical context stack overflow"); 497 yyerror("lexical context stack overflow");
498 else { 498 else {
499 lexBuf.lexModeStack[++lexBuf.lexModeStackTop] = mode; 499 lexBuf.lexModeStack[++lexBuf.lexModeStackTop] = mode;
500 } 500 }
501 } 501 }
502 502
503static void lexPopMode(int top) 503static void lexPopMode(int top)
504 { 504 {
505 /* special case of pop for ease of error recovery -- this 505 /* special case of pop for ease of error recovery -- this
506 version will never underflow */ 506 version will never underflow */
507 if (top) 507 if (top)
508 lexBuf.lexModeStackTop = 0; 508 lexBuf.lexModeStackTop = 0;
509 else 509 else
510 if (lexBuf.lexModeStackTop > 0) lexBuf.lexModeStackTop--; 510 if (lexBuf.lexModeStackTop > 0) lexBuf.lexModeStackTop--;
511 } 511 }
512 512
513static int lexWithinMode(enum LexMode mode) { 513static int lexWithinMode(enum LexMode mode) {
514 unsigned long i; 514 unsigned long i;
515 for (i=0;i<lexBuf.lexModeStackTop;i++) 515 for (i=0;i<lexBuf.lexModeStackTop;i++)
516 if (mode == lexBuf.lexModeStack[i]) return 1; 516 if (mode == lexBuf.lexModeStack[i]) return 1;
517 return 0; 517 return 0;
518 } 518 }
519 519
520static int lexGetc_() 520static int lexGetc_()
521 { 521 {
522 /* get next char from input, no buffering. */ 522 /* get next char from input, no buffering. */
523 if (lexBuf.curPos == lexBuf.inputLen) 523 if (lexBuf.curPos == lexBuf.inputLen)
524 return EOF; 524 return EOF;
525 else if (lexBuf.inputString) 525 else if (lexBuf.inputString)
526 return *(lexBuf.inputString + lexBuf.curPos++); 526 return *(lexBuf.inputString + lexBuf.curPos++);
527 else { 527 else {
528#ifdef INCLUDEMFC 528#ifdef INCLUDEMFC
529 char result; 529 char result;
530 return lexBuf.inputFile->Read(&result, 1) == 1 ? result : EOF; 530 return lexBuf.inputFile->Read(&result, 1) == 1 ? result : EOF;
531#else 531#else
532 return fgetc(lexBuf.inputFile); 532 return fgetc(lexBuf.inputFile);
533#endif 533#endif
534 } 534 }
535 } 535 }
536 536
537static int lexGeta() 537static int lexGeta()
538 { 538 {
539 ++lexBuf.len; 539 ++lexBuf.len;
540 return (lexBuf.buf[lexBuf.getPtr] = lexGetc_()); 540 return (lexBuf.buf[lexBuf.getPtr] = lexGetc_());
541 } 541 }
542 542
543static int lexGeta_(int i) 543static int lexGeta_(int i)
544 { 544 {
545 ++lexBuf.len; 545 ++lexBuf.len;
546 return (lexBuf.buf[(lexBuf.getPtr+i)%MAX_LEX_LOOKAHEAD] = lexGetc_()); 546 return (lexBuf.buf[(lexBuf.getPtr+i)%MAX_LEX_LOOKAHEAD] = lexGetc_());
547 } 547 }
548 548
549static void lexSkipLookahead() { 549static void lexSkipLookahead() {
550 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) { 550 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) {
551 /* don't skip EOF. */ 551 /* don't skip EOF. */
552 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD; 552 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD;
553 lexBuf.len--; 553 lexBuf.len--;
554 } 554 }
555 } 555 }
556 556
557static int lexLookahead() { 557static int lexLookahead() {
558 int c = (lexBuf.len)? 558 int c = (lexBuf.len)?
559 lexBuf.buf[lexBuf.getPtr]: 559 lexBuf.buf[lexBuf.getPtr]:
560 lexGeta(); 560 lexGeta();
561 /* do the \r\n -> \n or \r -> \n translation here */ 561 /* do the \r\n -> \n or \r -> \n translation here */
562 if (c == '\r') { 562 if (c == '\r') {
563 int a = (lexBuf.len>1)? 563 int a = (lexBuf.len>1)?
564 lexBuf.buf[(lexBuf.getPtr+1)%MAX_LEX_LOOKAHEAD]: 564 lexBuf.buf[(lexBuf.getPtr+1)%MAX_LEX_LOOKAHEAD]:
565 lexGeta_(1); 565 lexGeta_(1);
566 if (a == '\n') { 566 if (a == '\n') {
567 lexSkipLookahead(); 567 lexSkipLookahead();
568 } 568 }
569 lexBuf.buf[lexBuf.getPtr] = c = '\n'; 569 lexBuf.buf[lexBuf.getPtr] = c = '\n';
570 } 570 }
571 else if (c == '\n') { 571 else if (c == '\n') {
572 int a = (lexBuf.len>1)? 572 int a = (lexBuf.len>1)?
573 lexBuf.buf[lexBuf.getPtr+1]: 573 lexBuf.buf[lexBuf.getPtr+1]:
574 lexGeta_(1); 574 lexGeta_(1);
575 if (a == '\r') { 575 if (a == '\r') {
576 lexSkipLookahead(); 576 lexSkipLookahead();
577 } 577 }
578 lexBuf.buf[lexBuf.getPtr] = '\n'; 578 lexBuf.buf[lexBuf.getPtr] = '\n';
579 } 579 }
580 return c; 580 return c;
581 } 581 }
582 582
583static int lexGetc() { 583static int lexGetc() {
584 int c = lexLookahead(); 584 int c = lexLookahead();
585 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) { 585 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) {
586 /* EOF will remain in lookahead buffer */ 586 /* EOF will remain in lookahead buffer */
587 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD; 587 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD;
588 lexBuf.len--; 588 lexBuf.len--;
589 } 589 }
590 return c; 590 return c;
591 } 591 }
592 592
593static void lexSkipLookaheadWord() { 593static void lexSkipLookaheadWord() {
594 if (lexBuf.strsLen <= lexBuf.len) { 594 if (lexBuf.strsLen <= lexBuf.len) {
595 lexBuf.len -= lexBuf.strsLen; 595 lexBuf.len -= lexBuf.strsLen;
596 lexBuf.getPtr = (lexBuf.getPtr + lexBuf.strsLen) % MAX_LEX_LOOKAHEAD; 596 lexBuf.getPtr = (lexBuf.getPtr + lexBuf.strsLen) % MAX_LEX_LOOKAHEAD;
597 } 597 }
598 } 598 }
599 599
600static void lexClearToken() 600static void lexClearToken()
601 { 601 {
602 lexBuf.strsLen = 0; 602 lexBuf.strsLen = 0;
603 } 603 }
604 604
605static void lexAppendc(int c) 605static void lexAppendc(int c)
606 { 606 {
607 lexBuf.strs[lexBuf.strsLen] = c; 607 lexBuf.strs[lexBuf.strsLen] = c;
608 /* append up to zero termination */ 608 /* append up to zero termination */
609 if (c == 0) return; 609 if (c == 0) return;
610 lexBuf.strsLen++; 610 lexBuf.strsLen++;
611 if (lexBuf.strsLen > lexBuf.maxToken) { 611 if (lexBuf.strsLen > lexBuf.maxToken) {
612 /* double the token string size */ 612 /* double the token string size */
613 lexBuf.maxToken <<= 1; 613 lexBuf.maxToken <<= 1;
614 lexBuf.strs = (char*) realloc(lexBuf.strs,(size_t)lexBuf.maxToken); 614 lexBuf.strs = (char*) realloc(lexBuf.strs,(size_t)lexBuf.maxToken);
615 } 615 }
616 } 616 }
617 617
618static char* lexStr() { 618static char* lexStr() {
619 return dupStr(lexBuf.strs,(size_t)lexBuf.strsLen+1); 619 return dupStr(lexBuf.strs,(size_t)lexBuf.strsLen+1);
620 } 620 }
621 621
622static void lexSkipWhite() { 622static void lexSkipWhite() {
623 int c = lexLookahead(); 623 int c = lexLookahead();
624 while (c == ' ' || c == '\t') { 624 while (c == ' ' || c == '\t') {
625 lexSkipLookahead(); 625 lexSkipLookahead();
626 c = lexLookahead(); 626 c = lexLookahead();
627 } 627 }
628 } 628 }
629 629
630static char* lexGetWord() { 630static char* lexGetWord() {
631 int c; 631 int c;
632 lexSkipWhite(); 632 lexSkipWhite();
633 lexClearToken(); 633 lexClearToken();
634 c = lexLookahead(); 634 c = lexLookahead();
635 while (c != EOF && !strchr("\t\n ;:=",c)) { 635 while (c != EOF && !strchr("\t\n ;:=",c)) {
636 lexAppendc(c); 636 lexAppendc(c);
637 lexSkipLookahead(); 637 lexSkipLookahead();
638 c = lexLookahead(); 638 c = lexLookahead();
639 } 639 }
640 lexAppendc(0); 640 lexAppendc(0);
641 return lexStr(); 641 return lexStr();
642 } 642 }
643 643
644static void lexPushLookaheadc(int c) { 644static void lexPushLookaheadc(int c) {
645 int putptr; 645 int putptr;
646 /* can't putback EOF, because it never leaves lookahead buffer */ 646 /* can't putback EOF, because it never leaves lookahead buffer */
647 if (c == EOF) return; 647 if (c == EOF) return;
648 putptr = (int)lexBuf.getPtr - 1; 648 putptr = (int)lexBuf.getPtr - 1;
649 if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD; 649 if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD;
650 lexBuf.getPtr = putptr; 650 lexBuf.getPtr = putptr;
651 lexBuf.buf[putptr] = c; 651 lexBuf.buf[putptr] = c;
652 lexBuf.len += 1; 652 lexBuf.len += 1;
653 } 653 }
654 654
655static char* lexLookaheadWord() { 655static char* lexLookaheadWord() {
656 /* this function can lookahead word with max size of MAX_LEX_LOOKAHEAD_0 656 /* this function can lookahead word with max size of MAX_LEX_LOOKAHEAD_0
657 / and thing bigger than that will stop the lookahead and return 0; 657 / and thing bigger than that will stop the lookahead and return 0;
658 / leading white spaces are not recoverable. 658 / leading white spaces are not recoverable.
659 */ 659 */
660 int c; 660 int c;
661 int len = 0; 661 int len = 0;
662 int curgetptr = 0; 662 int curgetptr = 0;
663 lexSkipWhite(); 663 lexSkipWhite();
664 lexClearToken(); 664 lexClearToken();
665 curgetptr = (int)lexBuf.getPtr;// remember! 665 curgetptr = (int)lexBuf.getPtr;// remember!
666 while (len < (MAX_LEX_LOOKAHEAD_0)) { 666 while (len < (MAX_LEX_LOOKAHEAD_0)) {
667 c = lexGetc(); 667 c = lexGetc();
668 len++; 668 len++;
669 if (c == EOF || strchr("\t\n ;:=", c)) { 669 if (c == EOF || strchr("\t\n ;:=", c)) {
670 lexAppendc(0); 670 lexAppendc(0);
671 /* restore lookahead buf. */ 671 /* restore lookahead buf. */
672 lexBuf.len += len; 672 lexBuf.len += len;
673 lexBuf.getPtr = curgetptr; 673 lexBuf.getPtr = curgetptr;
674 return lexStr(); 674 return lexStr();
675 } 675 }
676 else 676 else
677 lexAppendc(c); 677 lexAppendc(c);
678 } 678 }
679 lexBuf.len += len;/* char that has been moved to lookahead buffer */ 679 lexBuf.len += len;/* char that has been moved to lookahead buffer */
680 lexBuf.getPtr = curgetptr; 680 lexBuf.getPtr = curgetptr;
681 return 0; 681 return 0;
682 } 682 }
683 683
684#ifdef _SUPPORT_LINE_FOLDING 684#ifdef _SUPPORT_LINE_FOLDING
685static void handleMoreRFC822LineBreak(int c) { 685static void handleMoreRFC822LineBreak(int c) {
686 /* suport RFC 822 line break in cases like 686 /* suport RFC 822 line break in cases like
687 *ADR: foo; 687 *ADR: foo;
688 * morefoo; 688 * morefoo;
689 * more foo; 689 * more foo;
690 */ 690 */
691 if (c == ';') { 691 if (c == ';') {
692 int a; 692 int a;
693 lexSkipLookahead(); 693 lexSkipLookahead();
694 /* skip white spaces */ 694 /* skip white spaces */
695 a = lexLookahead(); 695 a = lexLookahead();
696 while (a == ' ' || a == '\t') { 696 while (a == ' ' || a == '\t') {
697 lexSkipLookahead(); 697 lexSkipLookahead();
698 a = lexLookahead(); 698 a = lexLookahead();
699 } 699 }
700 if (a == '\n') { 700 if (a == '\n') {
701 lexSkipLookahead(); 701 lexSkipLookahead();
702 a = lexLookahead(); 702 a = lexLookahead();
703 if (a == ' ' || a == '\t') { 703 if (a == ' ' || a == '\t') {
704 /* continuation, throw away all the \n and spaces read so 704 /* continuation, throw away all the \n and spaces read so
705 * far 705 * far
706 */ 706 */
707 lexSkipWhite(); 707 lexSkipWhite();
708 lexPushLookaheadc(';'); 708 lexPushLookaheadc(';');
709 } 709 }
710 else { 710 else {
711 lexPushLookaheadc('\n'); 711 lexPushLookaheadc('\n');
712 lexPushLookaheadc(';'); 712 lexPushLookaheadc(';');
713 } 713 }
714 } 714 }
715 else { 715 else {
716 lexPushLookaheadc(';'); 716 lexPushLookaheadc(';');
717 } 717 }
718 } 718 }
719 } 719 }
720 720
721static char* lexGet1Value() { 721static char* lexGet1Value() {
722 int c; 722 int c;
723 lexSkipWhite(); 723 lexSkipWhite();
724 c = lexLookahead(); 724 c = lexLookahead();
725 lexClearToken(); 725 lexClearToken();
726 while (c != EOF && (c != ';' || !fieldedProp)) { 726 while (c != EOF && (c != ';' || !fieldedProp)) {
727 if (c == '\\' ) { 727 if (c == '\\' ) {
728 int a; 728 int a;
729 lexSkipLookahead(); 729 lexSkipLookahead();
730 a = lexLookahead(); 730 a = lexLookahead();
731 if ( a == ';' ) { 731 if ( a == ';' ) {
732 lexAppendc( ';' ); 732 lexAppendc( ';' );
733 lexSkipLookahead(); 733 lexSkipLookahead();
734 } else if ( a == '\n' ) { 734 } else if ( a == '\n' ) {
735 lexAppendc( '\n' ); 735 lexAppendc( '\n' );
736 lexSkipLookahead(); 736 lexSkipLookahead();
737 } else if ( a == '\\' ) { 737 } else if ( a == '\\' ) {
738 lexAppendc( '\\' ); 738 lexAppendc( '\\' );
739 lexSkipLookahead(); 739 lexSkipLookahead();
740 } else { 740 } else {
741 lexAppendc('\\'); 741 lexAppendc('\\');
742 } 742 }
743 } else if (c == '\n') { 743 } else if (c == '\n') {
744 int a; 744 int a;
745 lexSkipLookahead(); 745 lexSkipLookahead();
746 a = lexLookahead(); 746 a = lexLookahead();
747 if (a == ' ' || a == '\t') { 747 if (a == ' ' || a == '\t') {
748 lexAppendc(' '); 748 lexAppendc(' ');
749 lexSkipLookahead(); 749 lexSkipLookahead();
750 } 750 }
751 else { 751 else {
752 lexPushLookaheadc('\n'); 752 lexPushLookaheadc('\n');
753 break; 753 break;
754 } 754 }
755 } 755 }
756 else { 756 else {
757 lexAppendc(c); 757 lexAppendc(c);
758 lexSkipLookahead(); 758 lexSkipLookahead();
759 } 759 }
760 c = lexLookahead(); 760 c = lexLookahead();
761 } 761 }
762 lexAppendc(0); 762 lexAppendc(0);
763 handleMoreRFC822LineBreak(c); 763 handleMoreRFC822LineBreak(c);
764 return c==EOF?0:lexStr(); 764 return c==EOF?0:lexStr();
765 } 765 }
766#endif 766#endif
767 767
768static int match_begin_name(int end) { 768static int match_begin_name(int end) {
769 char *n = lexLookaheadWord(); 769 char *n = lexLookaheadWord();
770 int token = ID; 770 int token = ID;
771 if (n) { 771 if (n) {
772 if (!qstricmp(n,"vcard")) token = end?END_VCARD:BEGIN_VCARD; 772 if (!qstricmp(n,"vcard")) token = end?END_VCARD:BEGIN_VCARD;
773 else if (!qstricmp(n,"vcalendar")) token = end?END_VCAL:BEGIN_VCAL; 773 else if (!qstricmp(n,"vcalendar")) token = end?END_VCAL:BEGIN_VCAL;
774 else if (!qstricmp(n,"vevent")) token = end?END_VEVENT:BEGIN_VEVENT; 774 else if (!qstricmp(n,"vevent")) token = end?END_VEVENT:BEGIN_VEVENT;
775 else if (!qstricmp(n,"vtodo")) token = end?END_VTODO:BEGIN_VTODO; 775 else if (!qstricmp(n,"vtodo")) token = end?END_VTODO:BEGIN_VTODO;
776 deleteStr(n); 776 deleteStr(n);
777 return token; 777 return token;
778 } 778 }
779 return 0; 779 return 0;
780 } 780 }
781 781
782 782
783#ifdef INCLUDEMFC 783#ifdef INCLUDEMFC
784void initLex(const char *inputstring, unsigned long inputlen, CFile *inputfile) 784void initLex(const char *inputstring, unsigned long inputlen, CFile *inputfile)
785#else 785#else
786void initLex(const char *inputstring, unsigned long inputlen, FILE *inputfile) 786void initLex(const char *inputstring, unsigned long inputlen, FILE *inputfile)
787#endif 787#endif
788 { 788 {
789 // initialize lex mode stack 789 // initialize lex mode stack
790 lexBuf.lexModeStack[lexBuf.lexModeStackTop=0] = L_NORMAL; 790 lexBuf.lexModeStack[lexBuf.lexModeStackTop=0] = L_NORMAL;
791 791
792 // iniatialize lex buffer. 792 // iniatialize lex buffer.
793 lexBuf.inputString = (char*) inputstring; 793 lexBuf.inputString = (char*) inputstring;
794 lexBuf.inputLen = inputlen; 794 lexBuf.inputLen = inputlen;
795 lexBuf.curPos = 0; 795 lexBuf.curPos = 0;
796 lexBuf.inputFile = inputfile; 796 lexBuf.inputFile = inputfile;
797 797
798 lexBuf.len = 0; 798 lexBuf.len = 0;
799 lexBuf.getPtr = 0; 799 lexBuf.getPtr = 0;
800 800
801 lexBuf.maxToken = MAXTOKEN; 801 lexBuf.maxToken = MAXTOKEN;
802 lexBuf.strs = (char*)malloc(MAXTOKEN); 802 lexBuf.strs = (char*)malloc(MAXTOKEN);
803 lexBuf.strsLen = 0; 803 lexBuf.strsLen = 0;
804 804
805 } 805 }
806 806
807static void finiLex() { 807static void finiLex() {
808 free(lexBuf.strs); 808 free(lexBuf.strs);
809 } 809 }
810 810
811 811
812/*-----------------------------------*/ 812/*-----------------------------------*/
813/* This parses and converts the base64 format for binary encoding into 813/* This parses and converts the base64 format for binary encoding into
814 * a decoded buffer (allocated with new). See RFC 1521. 814 * a decoded buffer (allocated with new). See RFC 1521.
815 */ 815 */
816static int lexGetDataFromBase64() 816static int lexGetDataFromBase64()
817 { 817 {
818 unsigned long bytesLen = 0, bytesMax = 0; 818 unsigned long bytesLen = 0, bytesMax = 0;
819 int quadIx = 0, pad = 0; 819 int quadIx = 0, pad = 0;
820 unsigned long trip = 0; 820 unsigned long trip = 0;
821 unsigned char b; 821 unsigned char b;
822 int c; 822 int c;
823 unsigned char *bytes = NULL; 823 unsigned char *bytes = NULL;
824 unsigned char *oldBytes = NULL; 824 unsigned char *oldBytes = NULL;
825 825
826 DBG_(("db: lexGetDataFromBase64\n")); 826 DBG_(("db: lexGetDataFromBase64\n"));
827 while (1) { 827 while (1) {
828 c = lexGetc(); 828 c = lexGetc();
829 lexSkipWhite(); 829 lexSkipWhite();
830 if (c == '\n') { 830 if (c == '\n') {
831 ++mime_lineNum; 831 ++mime_lineNum;
832 if (lexLookahead() == '\n') { 832 if (lexLookahead() == '\n') {
833 /* a '\n' character by itself means end of data */ 833 /* a '\n' character by itself means end of data */
834 break; 834 break;
835 } 835 }
836 else continue; /* ignore '\n' */ 836 else continue; /* ignore '\n' */
837 } 837 }
838 else { 838 else {
839 if ((c >= 'A') && (c <= 'Z')) 839 if ((c >= 'A') && (c <= 'Z'))
840 b = (unsigned char)(c - 'A'); 840 b = (unsigned char)(c - 'A');
841 else if ((c >= 'a') && (c <= 'z')) 841 else if ((c >= 'a') && (c <= 'z'))
842 b = (unsigned char)(c - 'a') + 26; 842 b = (unsigned char)(c - 'a') + 26;
843 else if ((c >= '0') && (c <= '9')) 843 else if ((c >= '0') && (c <= '9'))
844 b = (unsigned char)(c - '0') + 52; 844 b = (unsigned char)(c - '0') + 52;
845 else if (c == '+') 845 else if (c == '+')
846 b = 62; 846 b = 62;
847 else if (c == '/') 847 else if (c == '/')
848 b = 63; 848 b = 63;
849 else if (c == '=') { 849 else if (c == '=') {
850 b = 0; 850 b = 0;
851 pad++; 851 pad++;
852 } else { /* error condition */ 852 } else { /* error condition */
853 if (bytes) free(bytes); 853 if (bytes) free(bytes);
854 else if (oldBytes) free(oldBytes); 854 else if (oldBytes) free(oldBytes);
855 // error recovery: skip until 2 adjacent newlines. 855 // error recovery: skip until 2 adjacent newlines.
856 DBG_(("db: invalid character 0x%x '%c'\n", c,c)); 856 DBG_(("db: invalid character 0x%x '%c'\n", c,c));
857 if (c != EOF) { 857 if (c != EOF) {
858 c = lexGetc(); 858 c = lexGetc();
859 while (c != EOF) { 859 while (c != EOF) {
860 if (c == '\n') { 860 if (c == '\n') {
861 lexSkipWhite(); 861 lexSkipWhite();
862 if(lexLookahead() == '\n') { 862 if(lexLookahead() == '\n') {
863 ++mime_lineNum; 863 ++mime_lineNum;
864 break; 864 break;
865 } 865 }
866 } 866 }
867 c = lexGetc(); 867 c = lexGetc();
868 } 868 }
869 } 869 }
870 return c != EOF; 870 return c != EOF;
871 } 871 }
872 trip = (trip << 6) | b; 872 trip = (trip << 6) | b;
873 if (++quadIx == 4) { 873 if (++quadIx == 4) {
874 unsigned char outBytes[3]; 874 unsigned char outBytes[3];
875 int numOut; 875 int numOut;
876 int i; 876 int i;
877 for (i = 0; i < 3; i++) { 877 for (i = 0; i < 3; i++) {
878 outBytes[2-i] = (unsigned char)(trip & 0xFF); 878 outBytes[2-i] = (unsigned char)(trip & 0xFF);
879 trip >>= 8; 879 trip >>= 8;
880 } 880 }
881 numOut = 3 - pad; 881 numOut = 3 - pad;
882 if (bytesLen + numOut > bytesMax) { 882 if (bytesLen + numOut > bytesMax) {
883 if (!bytes) { 883 if (!bytes) {
884 bytesMax = 1024; 884 bytesMax = 1024;
885 bytes = (unsigned char*)malloc((size_t)bytesMax); 885 bytes = (unsigned char*)malloc((size_t)bytesMax);
886 } 886 }
887 else { 887 else {
888 bytesMax <<= 2; 888 bytesMax <<= 2;
889 oldBytes = bytes; 889 oldBytes = bytes;
890 bytes = (unsigned char*)realloc(bytes,(size_t)bytesMax); 890 bytes = (unsigned char*)realloc(bytes,(size_t)bytesMax);
891 } 891 }
892 if (bytes == 0) { 892 if (bytes == 0) {
893 mime_error("out of memory while processing BASE64 data\n"); 893 mime_error("out of memory while processing BASE64 data\n");
894 } 894 }
895 } 895 }
896 if (bytes) { 896 if (bytes) {
897 memcpy(bytes + bytesLen, outBytes, numOut); 897 memcpy(bytes + bytesLen, outBytes, numOut);
898 bytesLen += numOut; 898 bytesLen += numOut;
899 } 899 }
900 trip = 0; 900 trip = 0;
901 quadIx = 0; 901 quadIx = 0;
902 } 902 }
903 } 903 }
904 } /* while */ 904 } /* while */
905 DBG_(("db: bytesLen = %d\n", bytesLen)); 905 DBG_(("db: bytesLen = %d\n", bytesLen));
906 /* kludge: all this won't be necessary if we have tree form 906 /* kludge: all this won't be necessary if we have tree form
907 representation */ 907 representation */
908 if (bytes) { 908 if (bytes) {
909 setValueWithSize(curProp,bytes,(unsigned int)bytesLen); 909 setValueWithSize(curProp,bytes,(unsigned int)bytesLen);
910 free(bytes); 910 free(bytes);
911 } 911 }
912 else if (oldBytes) { 912 else if (oldBytes) {
913 setValueWithSize(curProp,oldBytes,(unsigned int)bytesLen); 913 setValueWithSize(curProp,oldBytes,(unsigned int)bytesLen);
914 free(oldBytes); 914 free(oldBytes);
915 } 915 }
916 return bytesLen; 916 return bytesLen;
917 } 917 }
918 918
919static int match_begin_end_name(int end) { 919static int match_begin_end_name(int end) {
920 int token; 920 int token;
921 lexSkipWhite(); 921 lexSkipWhite();
922 if (lexLookahead() != ':') return ID; 922 if (lexLookahead() != ':') return ID;
923 lexSkipLookahead(); 923 lexSkipLookahead();
924 lexSkipWhite(); 924 lexSkipWhite();
925 token = match_begin_name(end); 925 token = match_begin_name(end);
926 if (token == ID) { 926 if (token == ID) {
927 lexPushLookaheadc(':'); 927 lexPushLookaheadc(':');
928 DBG_(("db: ID '%s'\n", yylval.str)); 928 DBG_(("db: ID '%s'\n", yylval.str));
929 return ID; 929 return ID;
930 } 930 }
931 else if (token != 0) { 931 else if (token != 0) {
932 lexSkipLookaheadWord(); 932 lexSkipLookaheadWord();
933 deleteStr(yylval.str); 933 deleteStr(yylval.str);
934 DBG_(("db: begin/end %d\n", token)); 934 DBG_(("db: begin/end %d\n", token));
935 return token; 935 return token;
936 } 936 }
937 return 0; 937 return 0;
938 } 938 }
939 939
940static char* lexGetQuotedPrintable() 940static char* lexGetQuotedPrintable()
941{ 941{
942 int c; 942 int c;
943 lexSkipWhite(); 943 lexSkipWhite();
944 c = lexLookahead(); 944 c = lexLookahead();
945 lexClearToken(); 945 lexClearToken();
946 946
947 while (c != EOF && (c != ';' || !fieldedProp)) { 947 while (c != EOF && (c != ';' || !fieldedProp)) {
948 if (c == '\n') { 948 if (c == '\n') {
949 // break, leave '\n' on remaining chars. 949 // break, leave '\n' on remaining chars.
950 break; 950 break;
951 } else if (c == '=') { 951 } else if (c == '=') {
952 int cur = 0; 952 int cur = 0;
953 int next; 953 int next;
954 954
955 lexSkipLookahead(); // skip '=' 955 lexSkipLookahead(); // skip '='
956 next = lexLookahead(); 956 next = lexLookahead();
957 957
958 if (next == '\n') { 958 if (next == '\n') {
959 // skip and only skip the \n 959 // skip and only skip the \n
960 lexSkipLookahead(); 960 lexSkipLookahead();
961 c = lexLookahead(); 961 c = lexLookahead();
962 ++mime_lineNum; // aid in error reporting 962 ++mime_lineNum; // aid in error reporting
963 continue; 963 continue;
964 } else if (next >= '0' && next <= '9') { 964 } else if (next >= '0' && next <= '9') {
965 cur = next - '0'; 965 cur = next - '0';
966 } else if (next >= 'A' && next <= 'F') { 966 } else if (next >= 'A' && next <= 'F') {
967 cur = next - 'A' + 10; 967 cur = next - 'A' + 10;
968 } else { 968 } else {
969 // we have been sent buggy stuff. doesn't matter 969 // we have been sent buggy stuff. doesn't matter
970 // what we do so long as we keep going. 970 // what we do so long as we keep going.
971 // should probably spit an error here 971 // should probably spit an error here
972 lexSkipLookahead(); 972 lexSkipLookahead();
973 c = lexLookahead(); 973 c = lexLookahead();
974 continue; 974 continue;
975 } 975 }
976 976
977 lexSkipLookahead(); // skip A-Z0-9 977 lexSkipLookahead(); // skip A-Z0-9
978 next = lexLookahead(); 978 next = lexLookahead();
979 979
980 cur = cur * 16; 980 cur = cur * 16;
981 // this time really just expecting 0-9A-F 981 // this time really just expecting 0-9A-F
982 if (next >= '0' && next <= '9') { 982 if (next >= '0' && next <= '9') {
983 cur += next - '0'; 983 cur += next - '0';
984 } else if (next >= 'A' && next <= 'F') { 984 } else if (next >= 'A' && next <= 'F') {
985 cur += next - 'A' + 10; 985 cur += next - 'A' + 10;
986 } else { 986 } else {
987 // we have been sent buggy stuff. doesn't matter 987 // we have been sent buggy stuff. doesn't matter
988 // what we do so long as we keep going. 988 // what we do so long as we keep going.
989 // should probably spit an error here 989 // should probably spit an error here
990 lexSkipLookahead(); 990 lexSkipLookahead();
991 c = lexLookahead(); 991 c = lexLookahead();
992 continue; 992 continue;
993 } 993 }
994 994
995 // got a valid escaped =. append it. 995 // got a valid escaped =. append it.
996 lexSkipLookahead(); // skip second 0-9A-F 996 lexSkipLookahead(); // skip second 0-9A-F
997 lexAppendc(cur); 997 lexAppendc(cur);
998 } else { 998 } else {
999 lexSkipLookahead(); // skip whatever we just read. 999 lexSkipLookahead(); // skip whatever we just read.
1000 lexAppendc(c); // and append it. 1000 lexAppendc(c); // and append it.
1001 } 1001 }
1002 c = lexLookahead(); 1002 c = lexLookahead();
1003 } 1003 }
1004 lexAppendc(0); 1004 lexAppendc(0);
1005 return c==EOF?0:lexStr(); 1005 return c==EOF?0:lexStr();
1006} 1006}
1007 1007
1008static int yylex() { 1008static int yylex() {
1009 1009
1010 int lexmode = LEXMODE(); 1010 int lexmode = LEXMODE();
1011 if (lexmode == L_VALUES) { 1011 if (lexmode == L_VALUES) {
1012 int c = lexGetc(); 1012 int c = lexGetc();
1013 if (c == ';' && fieldedProp) { 1013 if (c == ';' && fieldedProp) {
1014 DBG_(("db: SEMICOLON\n")); 1014 DBG_(("db: SEMICOLON\n"));
1015 lexPushLookaheadc(c); 1015 lexPushLookaheadc(c);
1016 handleMoreRFC822LineBreak(c); 1016 handleMoreRFC822LineBreak(c);
1017 lexSkipLookahead(); 1017 lexSkipLookahead();
1018 return SEMICOLON; 1018 return SEMICOLON;
1019 } 1019 }
1020 else if (strchr("\n",c)) { 1020 else if (strchr("\n",c)) {
1021 ++mime_lineNum; 1021 ++mime_lineNum;
1022 /* consume all line separator(s) adjacent to each other */ 1022 /* consume all line separator(s) adjacent to each other */
1023 c = lexLookahead(); 1023 c = lexLookahead();
1024 while (strchr("\n",c)) { 1024 while (strchr("\n",c)) {
1025 lexSkipLookahead(); 1025 lexSkipLookahead();
1026 c = lexLookahead(); 1026 c = lexLookahead();
1027 ++mime_lineNum; 1027 ++mime_lineNum;
1028 } 1028 }
1029 DBG_(("db: LINESEP\n")); 1029 DBG_(("db: LINESEP\n"));
1030 return LINESEP; 1030 return LINESEP;
1031 } 1031 }
1032 else { 1032 else {
1033 char *p = 0; 1033 char *p = 0;
1034 lexPushLookaheadc(c); 1034 lexPushLookaheadc(c);
1035 if (lexWithinMode(L_BASE64)) { 1035 if (lexWithinMode(L_BASE64)) {
1036 /* get each char and convert to bin on the fly... */ 1036 /* get each char and convert to bin on the fly... */
1037 yylval.str = NULL; 1037 yylval.str = NULL;
1038 return lexGetDataFromBase64() ? STRING : 0; 1038 return lexGetDataFromBase64() ? STRING : 0;
1039 } 1039 }
1040 else if (lexWithinMode(L_QUOTED_PRINTABLE)) { 1040 else if (lexWithinMode(L_QUOTED_PRINTABLE)) {
1041 p = lexGetQuotedPrintable(); 1041 p = lexGetQuotedPrintable();
1042 } 1042 }
1043 else { 1043 else {
1044#ifdef _SUPPORT_LINE_FOLDING 1044#ifdef _SUPPORT_LINE_FOLDING
1045 p = lexGet1Value(); 1045 p = lexGet1Value();
1046#else 1046#else
1047 p = lexGetStrUntil(";\n"); 1047 p = lexGetStrUntil(";\n");
1048#endif 1048#endif
1049 } 1049 }
1050 if (p) { 1050 if (p) {
1051 DBG_(("db: STRING: '%s'\n", p)); 1051 DBG_(("db: STRING: '%s'\n", p));
1052 yylval.str = p; 1052 yylval.str = p;
1053 return STRING; 1053 return STRING;
1054 } 1054 }
1055 else return 0; 1055 else return 0;
1056 } 1056 }
1057 } 1057 }
1058 else { 1058 else {
1059 /* normal mode */ 1059 /* normal mode */
1060 while (1) { 1060 while (1) {
1061 int c = lexGetc(); 1061 int c = lexGetc();
1062 switch(c) { 1062 switch(c) {
1063 case ':': { 1063 case ':': {
1064 /* consume all line separator(s) adjacent to each other */ 1064 /* consume all line separator(s) adjacent to each other */
1065 /* ignoring linesep immediately after colon. */ 1065 /* ignoring linesep immediately after colon. */
1066 /* I don't see this in the spec, and it breaks null values -- WA 1066 /* I don't see this in the spec, and it breaks null values -- WA
1067 c = lexLookahead(); 1067 c = lexLookahead();
1068 while (strchr("\n",c)) { 1068 while (strchr("\n",c)) {
1069 lexSkipLookahead(); 1069 lexSkipLookahead();
1070 c = lexLookahead(); 1070 c = lexLookahead();
1071 ++mime_lineNum; 1071 ++mime_lineNum;
1072 } 1072 }
1073 */ 1073 */
1074 DBG_(("db: COLON\n")); 1074 DBG_(("db: COLON\n"));
1075 return COLON; 1075 return COLON;
1076 } 1076 }
1077 case ';': 1077 case ';':
1078 DBG_(("db: SEMICOLON\n")); 1078 DBG_(("db: SEMICOLON\n"));
1079 return SEMICOLON; 1079 return SEMICOLON;
1080 case '=': 1080 case '=':
1081 DBG_(("db: EQ\n")); 1081 DBG_(("db: EQ\n"));
1082 return EQ; 1082 return EQ;
1083 /* ignore whitespace in this mode */ 1083 /* ignore whitespace in this mode */
1084 case '\t': 1084 case '\t':
1085 case ' ': continue; 1085 case ' ': continue;
1086 case '\n': { 1086 case '\n': {
1087 ++mime_lineNum; 1087 ++mime_lineNum;
1088 continue; 1088 continue;
1089 } 1089 }
1090 case EOF: return 0; 1090 case EOF: return 0;
1091 break; 1091 break;
1092 default: { 1092 default: {
1093 lexPushLookaheadc(c); 1093 lexPushLookaheadc(c);
1094 if (isalnum(c)) { 1094 if (isalnum(c)) {
1095 char *t = lexGetWord(); 1095 char *t = lexGetWord();
1096 yylval.str = t; 1096 yylval.str = t;
1097 if (!qstricmp(t, "begin")) { 1097 if (!qstricmp(t, "begin")) {
1098 return match_begin_end_name(0); 1098 return match_begin_end_name(0);
1099 } 1099 }
1100 else if (!qstricmp(t,"end")) { 1100 else if (!qstricmp(t,"end")) {
1101 return match_begin_end_name(1); 1101 return match_begin_end_name(1);
1102 } 1102 }
1103 else { 1103 else {
1104 DBG_(("db: ID '%s'\n", t)); 1104 DBG_(("db: ID '%s'\n", t));
1105 return ID; 1105 return ID;
1106 } 1106 }
1107 } 1107 }
1108 else { 1108 else {
1109 /* unknow token */ 1109 /* unknow token */
1110 return 0; 1110 return 0;
1111 } 1111 }
1112 break; 1112 break;
1113 } 1113 }
1114 } 1114 }
1115 } 1115 }
1116 } 1116 }
1117 return 0; 1117 return 0;
1118 } 1118 }
1119 1119
1120 1120
1121/***************************************************************************/ 1121/***************************************************************************/
1122 /*** Public Functions ****/ 1122 /*** Public Functions ****/
1123/***************************************************************************/ 1123/***************************************************************************/
1124 1124
1125static VObject* Parse_MIMEHelper() 1125static VObject* Parse_MIMEHelper()
1126 { 1126 {
1127 ObjStackTop = -1; 1127 ObjStackTop = -1;
1128 mime_numErrors = 0; 1128 mime_numErrors = 0;
1129 mime_lineNum = 1; 1129 mime_lineNum = 1;
1130 vObjList = 0; 1130 vObjList = 0;
1131 curObj = 0; 1131 curObj = 0;
1132 1132
1133 if (yyparse() != 0) 1133 if (yyparse() != 0)
1134 return 0; 1134 return 0;
1135 1135
1136 finiLex(); 1136 finiLex();
1137 return vObjList; 1137 return vObjList;
1138 } 1138 }
1139 1139
1140/*--------------------------------------------*/ 1140/*--------------------------------------------*/
1141DLLEXPORT(VObject*) Parse_MIME(const char *input, unsigned long len) 1141DLLEXPORT(VObject*) Parse_MIME(const char *input, unsigned long len)
1142 { 1142 {
1143 initLex(input, len, 0); 1143 initLex(input, len, 0);
1144 return Parse_MIMEHelper(); 1144 return Parse_MIMEHelper();
1145 } 1145 }
1146 1146
1147 1147
1148#if INCLUDEMFC 1148#if INCLUDEMFC
1149 1149
1150DLLEXPORT(VObject*) Parse_MIME_FromFile(CFile *file) 1150DLLEXPORT(VObject*) Parse_MIME_FromFile(CFile *file)
1151 { 1151 {
1152 unsigned long startPos; 1152 unsigned long startPos;
1153 VObject *result; 1153 VObject *result;
1154 1154
1155 initLex(0,-1,file); 1155 initLex(0,-1,file);
1156 startPos = file->GetPosition(); 1156 startPos = file->GetPosition();
1157 if (!(result = Parse_MIMEHelper())) 1157 if (!(result = Parse_MIMEHelper()))
1158 file->Seek(startPos, CFile::begin); 1158 file->Seek(startPos, CFile::begin);
1159 return result; 1159 return result;
1160 } 1160 }
1161 1161
1162#else 1162#else
1163 1163
1164VObject* Parse_MIME_FromFile(FILE *file) 1164VObject* Parse_MIME_FromFile(FILE *file)
1165 { 1165 {
1166 VObject *result; 1166 VObject *result;
1167 long startPos; 1167 long startPos;
1168 1168
1169 initLex(0,(unsigned long)-1,file); 1169 initLex(0,(unsigned long)-1,file);
1170 startPos = ftell(file); 1170 startPos = ftell(file);
1171 if (!(result = Parse_MIMEHelper())) { 1171 if (!(result = Parse_MIMEHelper())) {
1172 fseek(file,startPos,SEEK_SET); 1172 fseek(file,startPos,SEEK_SET);
1173 } 1173 }
1174 return result; 1174 return result;
1175 } 1175 }
1176 1176
1177DLLEXPORT(VObject*) Parse_MIME_FromFileName(char *fname) 1177DLLEXPORT(VObject*) Parse_MIME_FromFileName(char *fname)
1178 { 1178 {
1179 FILE *fp = fopen(fname,"r"); 1179 FILE *fp = fopen(fname,"r");
1180 if (fp) { 1180 if (fp) {
1181 VObject* o = Parse_MIME_FromFile(fp); 1181 VObject* o = Parse_MIME_FromFile(fp);
1182 fclose(fp); 1182 fclose(fp);
1183 return o; 1183 return o;
1184 } 1184 }
1185 else { 1185 else {
1186 char msg[80]; 1186 char msg[80];
1187 sprintf(msg, "can't open file '%s' for reading\n", fname); 1187 sprintf(msg, "can't open file '%s' for reading\n", fname);
1188 mime_error_(msg); 1188 mime_error_(msg);
1189 return 0; 1189 return 0;
1190 } 1190 }
1191 } 1191 }
1192 1192
1193#endif 1193#endif
1194 1194
1195/*-------------------------------------*/ 1195/*-------------------------------------*/
1196 1196
1197static MimeErrorHandler mimeErrorHandler; 1197static MimeErrorHandler mimeErrorHandler;
1198 1198
1199DLLEXPORT(void) registerMimeErrorHandler(MimeErrorHandler me) 1199DLLEXPORT(void) registerMimeErrorHandler(MimeErrorHandler me)
1200 { 1200 {
1201 mimeErrorHandler = me; 1201 mimeErrorHandler = me;
1202 } 1202 }
1203 1203
1204void mime_error(char *s) 1204void mime_error(char *s)
1205 { 1205 {
1206 char msg[256]; 1206 char msg[256];
1207 if (mimeErrorHandler) { 1207 if (mimeErrorHandler) {
1208 sprintf(msg,"%s at line %d", s, mime_lineNum); 1208 sprintf(msg,"%s at line %d", s, mime_lineNum);
1209 mimeErrorHandler(msg); 1209 mimeErrorHandler(msg);
1210 } 1210 }
1211 } 1211 }
1212 1212
1213void mime_error_(char *s) 1213void mime_error_(char *s)
1214 { 1214 {
1215 if (mimeErrorHandler) { 1215 if (mimeErrorHandler) {
1216 mimeErrorHandler(s); 1216 mimeErrorHandler(s);
1217 } 1217 }
1218 } 1218 }
1219 1219
diff --git a/library/backend/vcc_yacc.cpp b/library/backend/vcc_yacc.cpp
index 4006bc2..bc05f87 100644
--- a/library/backend/vcc_yacc.cpp
+++ b/library/backend/vcc_yacc.cpp
@@ -29,202 +29,207 @@ static char yyrcsid[] = "$Id$";
29#define yyrindex vccrindex 29#define yyrindex vccrindex
30#define yygindex vccgindex 30#define yygindex vccgindex
31#define yytable vcctable 31#define yytable vcctable
32#define yycheck vcccheck 32#define yycheck vcccheck
33#define yyname vccname 33#define yyname vccname
34#define yyrule vccrule 34#define yyrule vccrule
35#define YYPREFIX "vcc" 35#define YYPREFIX "vcc"
36#line 1 "backend/vcc.y" 36#line 1 "backend/vcc.y"
37 37
38 38
39/*************************************************************************** 39/***************************************************************************
40(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International 40(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
41Business Machines Corporation and Siemens Rolm Communications Inc. 41Business Machines Corporation and Siemens Rolm Communications Inc.
42 42
43For purposes of this license notice, the term Licensors shall mean, 43For purposes of this license notice, the term Licensors shall mean,
44collectively, Apple Computer, Inc., AT&T Corp., International 44collectively, Apple Computer, Inc., AT&T Corp., International
45Business Machines Corporation and Siemens Rolm Communications Inc. 45Business Machines Corporation and Siemens Rolm Communications Inc.
46The term Licensor shall mean any of the Licensors. 46The term Licensor shall mean any of the Licensors.
47 47
48Subject to acceptance of the following conditions, permission is hereby 48Subject to acceptance of the following conditions, permission is hereby
49granted by Licensors without the need for written agreement and without 49granted by Licensors without the need for written agreement and without
50license or royalty fees, to use, copy, modify and distribute this 50license or royalty fees, to use, copy, modify and distribute this
51software for any purpose. 51software for any purpose.
52 52
53The above copyright notice and the following four paragraphs must be 53The above copyright notice and the following four paragraphs must be
54reproduced in all copies of this software and any software including 54reproduced in all copies of this software and any software including
55this software. 55this software.
56 56
57THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE 57THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
58ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR 58ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
59MODIFICATIONS. 59MODIFICATIONS.
60 60
61IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT, 61IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
62INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT 62INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
63OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 63OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
64DAMAGE. 64DAMAGE.
65 65
66EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, 66EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
67INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE 67INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
68IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 68IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
69PURPOSE. 69PURPOSE.
70 70
71The software is provided with RESTRICTED RIGHTS. Use, duplication, or 71The software is provided with RESTRICTED RIGHTS. Use, duplication, or
72disclosure by the government are subject to restrictions set forth in 72disclosure by the government are subject to restrictions set forth in
73DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. 73DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
74 74
75***************************************************************************/ 75***************************************************************************/
76 76
77/* 77/*
78 * src: vcc.c 78 * src: vcc.c
79 * doc: Parser for vCard and vCalendar. Note that this code is 79 * doc: Parser for vCard and vCalendar. Note that this code is
80 * generated by a yacc parser generator. Generally it should not 80 * generated by a yacc parser generator. Generally it should not
81 * be edited by hand. The real source is vcc.y. The #line directives 81 * be edited by hand. The real source is vcc.y. The #line directives
82 * can be commented out here to make it easier to trace through 82 * can be commented out here to make it easier to trace through
83 * in a debugger. However, if a bug is found it should 83 * in a debugger. However, if a bug is found it should
84 * be fixed in vcc.y and this file regenerated. 84 * be fixed in vcc.y and this file regenerated.
85 */ 85 */
86 86
87 87
88/* debugging utilities */ 88/* debugging utilities */
89#if __DEBUG 89#if __DEBUG
90#define DBG_(x) printf x 90#define DBG_(x) printf x
91#else 91#else
92#define DBG_(x) 92#define DBG_(x)
93#endif 93#endif
94 94
95/**** External Functions ****/ 95/**** External Functions ****/
96 96
97/* assign local name to parser variables and functions so that 97/* assign local name to parser variables and functions so that
98 we can use more than one yacc based parser. 98 we can use more than one yacc based parser.
99*/ 99*/
100 100
101#if 0 101#if 0
102#define yyparse mime_parse 102#define yyparse mime_parse
103#define yylex mime_lex 103#define yylex mime_lex
104#define yyerror mime_error 104#define yyerror mime_error
105#define yychar mime_char 105#define yychar mime_char
106/* #define p_yyval p_mime_val */ 106/* #define p_yyval p_mime_val */
107#undef yyval 107#undef yyval
108#define yyval mime_yyval 108#define yyval mime_yyval
109/* #define p_yylval p_mime_lval */ 109/* #define p_yylval p_mime_lval */
110#undef yylval 110#undef yylval
111#define yylval mime_yylval 111#define yylval mime_yylval
112#define yydebug mime_debug 112#define yydebug mime_debug
113#define yynerrs mime_nerrs 113#define yynerrs mime_nerrs
114#define yyerrflag mime_errflag 114#define yyerrflag mime_errflag
115#define yyss mime_ss 115#define yyss mime_ss
116#define yyssp mime_ssp 116#define yyssp mime_ssp
117#define yyvs mime_vs 117#define yyvs mime_vs
118#define yyvsp mime_vsp 118#define yyvsp mime_vsp
119#define yylhs mime_lhs 119#define yylhs mime_lhs
120#define yylen mime_len 120#define yylen mime_len
121#define yydefred mime_defred 121#define yydefred mime_defred
122#define yydgoto mime_dgoto 122#define yydgoto mime_dgoto
123#define yysindex mime_sindex 123#define yysindex mime_sindex
124#define yyrindex mime_rindex 124#define yyrindex mime_rindex
125#define yygindex mime_gindex 125#define yygindex mime_gindex
126#define yytable mime_table 126#define yytable mime_table
127#define yycheck mime_check 127#define yycheck mime_check
128#define yyname mime_name 128#define yyname mime_name
129#define yyrule mime_rule 129#define yyrule mime_rule
130#ifdef YYPREFIX 130#ifdef YYPREFIX
131#undef YYPREFIX 131#undef YYPREFIX
132#endif 132#endif
133#define YYPREFIX "mime_" 133#define YYPREFIX "mime_"
134#endif 134#endif
135 135
136 136
137#ifndef _NO_LINE_FOLDING 137#ifndef _NO_LINE_FOLDING
138#define _SUPPORT_LINE_FOLDING 1 138#define _SUPPORT_LINE_FOLDING 1
139#endif 139#endif
140 140
141/* undef below if compile with MFC */ 141/* undef below if compile with MFC */
142/* #define INCLUDEMFC 1 */ 142/* #define INCLUDEMFC 1 */
143 143
144#if defined(WIN32) || defined(_WIN32) 144#if defined(WIN32) || defined(_WIN32)
145#ifdef INCLUDEMFC 145#ifdef INCLUDEMFC
146#include <afx.h> 146#include <afx.h>
147#endif 147#endif
148#endif 148#endif
149 149
150#include <string.h> 150#include <string.h>
151#ifndef __MWERKS__ 151#ifndef __MWERKS__
152#include <stdlib.h> 152#include <stdlib.h>
153#endif 153#endif
154#include <stdio.h> 154#include <stdio.h>
155#include <stdlib.h> 155#include <stdlib.h>
156#include <ctype.h> 156#include <ctype.h>
157 157
158/*#ifdef PALMTOPCENTER */ 158/*#ifdef PALMTOPCENTER
159/*#include <qpe/vobject_p.h> */ 159*/
160/*#else */ 160/*#include <qpe/vobject_p.h>
161#include "vobject_p.h" 161*/
162/*#endif */ 162/*#else
163 163*/
164/**** Types, Constants ****/ 164#include "vobject_p.h"
165 165/*#endif
166 #define YYDEBUG 0/* 1 to compile in some debugging code */ 166*/
167 #define MAXTOKEN 256/* maximum token (line) length */ 167
168 #define YYSTACKSIZE 100/* ~unref ? */ 168/**** Types, Constants ****/
169 #define MAXLEVEL 10/* max # of nested objects parseable */ 169
170 /* (includes outermost) */ 170 #define YYDEBUG 0/* 1 to compile in some debugging code */
171 171 #define MAXTOKEN 256/* maximum token (line) length */
172 172 #define YYSTACKSIZE 100/* ~unref ?
173/**** Global Variables ****/ 173*/
174int mime_lineNum, mime_numErrors; /* yyerror() can use these */ 174 #define MAXLEVEL 10/* max # of nested objects parseable */
175static VObject* vObjList; 175 /* (includes outermost) */
176static VObject *curProp; 176
177static VObject *curObj; 177
178static VObject* ObjStack[MAXLEVEL]; 178/**** Global Variables ****/
179static int ObjStackTop; 179int mime_lineNum, mime_numErrors; /* yyerror() can use these */
180 180static VObject* vObjList;
181 181static VObject *curProp;
182/* A helpful utility for the rest of the app. */ 182static VObject *curObj;
183#if __CPLUSPLUS__ 183static VObject* ObjStack[MAXLEVEL];
184extern "C" { 184static int ObjStackTop;
185#endif 185
186 186
187 extern void yyerror(char *s); 187/* A helpful utility for the rest of the app. */
188 188#if __CPLUSPLUS__
189#if __CPLUSPLUS__ 189extern "C" {
190 }; 190#endif
191#endif 191
192 192 extern void yyerror(char *s);
193int yyparse(); 193
194 194#if __CPLUSPLUS__
195enum LexMode { 195 };
196 L_NORMAL, 196#endif
197 L_VCARD, 197
198 L_VCAL, 198int yyparse();
199 L_VEVENT, 199
200 L_VTODO, 200enum LexMode {
201 L_VALUES, 201 L_NORMAL,
202 L_BASE64, 202 L_VCARD,
203 L_QUOTED_PRINTABLE 203 L_VCAL,
204 }; 204 L_VEVENT,
205 205 L_VTODO,
206/**** Private Forward Declarations ****/ 206 L_VALUES,
207static int pushVObject(const char *prop); 207 L_BASE64,
208static VObject* popVObject(); 208 L_QUOTED_PRINTABLE
209static void lexPopMode(int top); 209 };
210static int lexWithinMode(enum LexMode mode); 210
211static void lexPushMode(enum LexMode mode); 211/**** Private Forward Declarations ****/
212static void enterProps(const char *s); 212static int pushVObject(const char *prop);
213static void enterAttr(const char *s1, const char *s2); 213static VObject* popVObject();
214static void enterValues(const char *value); 214static void lexPopMode(int top);
215#define mime_error yyerror 215static int lexWithinMode(enum LexMode mode);
216void mime_error(char *s); 216static void lexPushMode(enum LexMode mode);
217void mime_error_(char *s); 217static void enterProps(const char *s);
218 218static void enterAttr(const char *s1, const char *s2);
219static void enterValues(const char *value);
220#define mime_error yyerror
221void mime_error(char *s);
222void mime_error_(char *s);
223
219#line 189 "backend/vcc.y" 224#line 189 "backend/vcc.y"
220typedef union { 225typedef union {
221 char *str; 226 char *str;
222 VObject *vobj; 227 VObject *vobj;
223 } YYSTYPE; 228 } YYSTYPE;
224#line 225 "y.tab.c" 229#line 225 "y.tab.c"
225#define EQ 257 230#define EQ 257
226#define COLON 258 231#define COLON 258
227#define DOT 259 232#define DOT 259
228#define SEMICOLON 260 233#define SEMICOLON 260
229#define SPACE 261 234#define SPACE 261
230#define HTAB 262 235#define HTAB 262
@@ -394,854 +399,854 @@ int yychar;
394short *yyssp; 399short *yyssp;
395YYSTYPE *yyvsp; 400YYSTYPE *yyvsp;
396YYSTYPE yyval; 401YYSTYPE yyval;
397YYSTYPE yylval; 402YYSTYPE yylval;
398short yyss[YYSTACKSIZE]; 403short yyss[YYSTACKSIZE];
399YYSTYPE yyvs[YYSTACKSIZE]; 404YYSTYPE yyvs[YYSTACKSIZE];
400#define yystacksize YYSTACKSIZE 405#define yystacksize YYSTACKSIZE
401#line 382 "backend/vcc.y" 406#line 382 "backend/vcc.y"
402 407
403/*------------------------------------*/ 408/*------------------------------------*/
404static int pushVObject(const char *prop) 409static int pushVObject(const char *prop)
405 { 410 {
406 VObject *newObj; 411 VObject *newObj;
407 if (ObjStackTop == MAXLEVEL) 412 if (ObjStackTop == MAXLEVEL)
408 return FALSE; 413 return FALSE;
409 414
410 ObjStack[++ObjStackTop] = curObj; 415 ObjStack[++ObjStackTop] = curObj;
411 416
412 if (curObj) { 417 if (curObj) {
413 newObj = addProp(curObj,prop); 418 newObj = addProp(curObj,prop);
414 curObj = newObj; 419 curObj = newObj;
415 } 420 }
416 else 421 else
417 curObj = newVObject(prop); 422 curObj = newVObject(prop);
418 423
419 return TRUE; 424 return TRUE;
420 } 425 }
421 426
422 427
423/*---------------------------------------*/ 428/*---------------------------------------*/
424/* This pops the recently built vCard off the stack and returns it. */ 429/* This pops the recently built vCard off the stack and returns it. */
425static VObject* popVObject() 430static VObject* popVObject()
426 { 431 {
427 VObject *oldObj; 432 VObject *oldObj;
428 if (ObjStackTop < 0) { 433 if (ObjStackTop < 0) {
429 yyerror("pop on empty Object Stack\n"); 434 yyerror("pop on empty Object Stack\n");
430 return 0; 435 return 0;
431 } 436 }
432 oldObj = curObj; 437 oldObj = curObj;
433 curObj = ObjStack[ObjStackTop--]; 438 curObj = ObjStack[ObjStackTop--];
434 439
435 return oldObj; 440 return oldObj;
436 } 441 }
437 442
438 443
439static void enterValues(const char *value) 444static void enterValues(const char *value)
440 { 445 {
441 if (fieldedProp && *fieldedProp) { 446 if (fieldedProp && *fieldedProp) {
442 if (value) { 447 if (value) {
443 addPropValue(curProp,*fieldedProp,value); 448 addPropValue(curProp,*fieldedProp,value);
444 } 449 }
445 /* else this field is empty, advance to next field */ 450 /* else this field is empty, advance to next field */
446 fieldedProp++; 451 fieldedProp++;
447 } 452 }
448 else { 453 else {
449 if (value) { 454 if (value) {
450 setVObjectStringZValue_(curProp,strdup( value )); 455 setVObjectStringZValue_(curProp,strdup( value ));
451 } 456 }
452 } 457 }
453 deleteStr(value); 458 deleteStr(value);
454 } 459 }
455 460
456static void enterProps(const char *s) 461static void enterProps(const char *s)
457 { 462 {
458 curProp = addGroup(curObj,s); 463 curProp = addGroup(curObj,s);
459 deleteStr(s); 464 deleteStr(s);
460 } 465 }
461 466
462static void enterAttr(const char *s1, const char *s2) 467static void enterAttr(const char *s1, const char *s2)
463 { 468 {
464 const char *p1, *p2=0; 469 const char *p1, *p2=0;
465 p1 = lookupProp_(s1); 470 p1 = lookupProp_(s1);
466 if (s2) { 471 if (s2) {
467 VObject *a; 472 VObject *a;
468 p2 = lookupProp_(s2); 473 p2 = lookupProp_(s2);
469 a = addProp(curProp,p1); 474 a = addProp(curProp,p1);
470 setVObjectStringZValue(a,p2); 475 setVObjectStringZValue(a,p2);
471 } 476 }
472 else 477 else
473 addProp(curProp,p1); 478 addProp(curProp,p1);
474 if (qstricmp(p1,VCBase64Prop) == 0 || (s2 && qstricmp(p2,VCBase64Prop)==0)) 479 if (qstricmp(p1,VCBase64Prop) == 0 || (s2 && qstricmp(p2,VCBase64Prop)==0))
475 lexPushMode(L_BASE64); 480 lexPushMode(L_BASE64);
476 else if (qstricmp(p1,VCQuotedPrintableProp) == 0 481 else if (qstricmp(p1,VCQuotedPrintableProp) == 0
477 || (s2 && qstricmp(p2,VCQuotedPrintableProp)==0)) 482 || (s2 && qstricmp(p2,VCQuotedPrintableProp)==0))
478 lexPushMode(L_QUOTED_PRINTABLE); 483 lexPushMode(L_QUOTED_PRINTABLE);
479 deleteStr(s1); deleteStr(s2); 484 deleteStr(s1); deleteStr(s2);
480 } 485 }
481 486
482 487
483#define MAX_LEX_LOOKAHEAD_0 32 488#define MAX_LEX_LOOKAHEAD_0 32
484#define MAX_LEX_LOOKAHEAD 64 489#define MAX_LEX_LOOKAHEAD 64
485#define MAX_LEX_MODE_STACK_SIZE 10 490#define MAX_LEX_MODE_STACK_SIZE 10
486#define LEXMODE() (lexBuf.lexModeStack[lexBuf.lexModeStackTop]) 491#define LEXMODE() (lexBuf.lexModeStack[lexBuf.lexModeStackTop])
487 492
488struct LexBuf { 493struct LexBuf {
489 /* input */ 494 /* input */
490#ifdef INCLUDEMFC 495#ifdef INCLUDEMFC
491 CFile *inputFile; 496 CFile *inputFile;
492#else 497#else
493 FILE *inputFile; 498 FILE *inputFile;
494#endif 499#endif
495 char *inputString; 500 char *inputString;
496 unsigned long curPos; 501 unsigned long curPos;
497 unsigned long inputLen; 502 unsigned long inputLen;
498 /* lookahead buffer */ 503 /* lookahead buffer */
499 /* -- lookahead buffer is short instead of char so that EOF 504 /* -- lookahead buffer is short instead of char so that EOF
500 / can be represented correctly. 505 / can be represented correctly.
501 */ 506 */
502 unsigned long len; 507 unsigned long len;
503 short buf[MAX_LEX_LOOKAHEAD]; 508 short buf[MAX_LEX_LOOKAHEAD];
504 unsigned long getPtr; 509 unsigned long getPtr;
505 /* context stack */ 510 /* context stack */
506 unsigned long lexModeStackTop; 511 unsigned long lexModeStackTop;
507 enum LexMode lexModeStack[MAX_LEX_MODE_STACK_SIZE]; 512 enum LexMode lexModeStack[MAX_LEX_MODE_STACK_SIZE];
508 /* token buffer */ 513 /* token buffer */
509 unsigned long maxToken; 514 unsigned long maxToken;
510 char *strs; 515 char *strs;
511 unsigned long strsLen; 516 unsigned long strsLen;
512 } lexBuf; 517 } lexBuf;
513 518
514static void lexPushMode(enum LexMode mode) 519static void lexPushMode(enum LexMode mode)
515 { 520 {
516 if (lexBuf.lexModeStackTop == (MAX_LEX_MODE_STACK_SIZE-1)) 521 if (lexBuf.lexModeStackTop == (MAX_LEX_MODE_STACK_SIZE-1))
517 yyerror("lexical context stack overflow"); 522 yyerror("lexical context stack overflow");
518 else { 523 else {
519 lexBuf.lexModeStack[++lexBuf.lexModeStackTop] = mode; 524 lexBuf.lexModeStack[++lexBuf.lexModeStackTop] = mode;
520 } 525 }
521 } 526 }
522 527
523static void lexPopMode(int top) 528static void lexPopMode(int top)
524 { 529 {
525 /* special case of pop for ease of error recovery -- this 530 /* special case of pop for ease of error recovery -- this
526 version will never underflow */ 531 version will never underflow */
527 if (top) 532 if (top)
528 lexBuf.lexModeStackTop = 0; 533 lexBuf.lexModeStackTop = 0;
529 else 534 else
530 if (lexBuf.lexModeStackTop > 0) lexBuf.lexModeStackTop--; 535 if (lexBuf.lexModeStackTop > 0) lexBuf.lexModeStackTop--;
531 } 536 }
532 537
533static int lexWithinMode(enum LexMode mode) { 538static int lexWithinMode(enum LexMode mode) {
534 unsigned long i; 539 unsigned long i;
535 for (i=0;i<lexBuf.lexModeStackTop;i++) 540 for (i=0;i<lexBuf.lexModeStackTop;i++)
536 if (mode == lexBuf.lexModeStack[i]) return 1; 541 if (mode == lexBuf.lexModeStack[i]) return 1;
537 return 0; 542 return 0;
538 } 543 }
539 544
540static int lexGetc_() 545static int lexGetc_()
541 { 546 {
542 /* get next char from input, no buffering. */ 547 /* get next char from input, no buffering. */
543 if (lexBuf.curPos == lexBuf.inputLen) 548 if (lexBuf.curPos == lexBuf.inputLen)
544 return EOF; 549 return EOF;
545 else if (lexBuf.inputString) 550 else if (lexBuf.inputString)
546 return *(lexBuf.inputString + lexBuf.curPos++); 551 return *(lexBuf.inputString + lexBuf.curPos++);
547 else { 552 else {
548#ifdef INCLUDEMFC 553#ifdef INCLUDEMFC
549 char result; 554 char result;
550 return lexBuf.inputFile->Read(&result, 1) == 1 ? result : EOF; 555 return lexBuf.inputFile->Read(&result, 1) == 1 ? result : EOF;
551#else 556#else
552 return fgetc(lexBuf.inputFile); 557 return fgetc(lexBuf.inputFile);
553#endif 558#endif
554 } 559 }
555 } 560 }
556 561
557static int lexGeta() 562static int lexGeta()
558 { 563 {
559 ++lexBuf.len; 564 ++lexBuf.len;
560 return (lexBuf.buf[lexBuf.getPtr] = lexGetc_()); 565 return (lexBuf.buf[lexBuf.getPtr] = lexGetc_());
561 } 566 }
562 567
563static int lexGeta_(int i) 568static int lexGeta_(int i)
564 { 569 {
565 ++lexBuf.len; 570 ++lexBuf.len;
566 return (lexBuf.buf[(lexBuf.getPtr+i)%MAX_LEX_LOOKAHEAD] = lexGetc_()); 571 return (lexBuf.buf[(lexBuf.getPtr+i)%MAX_LEX_LOOKAHEAD] = lexGetc_());
567 } 572 }
568 573
569static void lexSkipLookahead() { 574static void lexSkipLookahead() {
570 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) { 575 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) {
571 /* don't skip EOF. */ 576 /* don't skip EOF. */
572 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD; 577 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD;
573 lexBuf.len--; 578 lexBuf.len--;
574 } 579 }
575 } 580 }
576 581
577static int lexLookahead() { 582static int lexLookahead() {
578 int c = (lexBuf.len)? 583 int c = (lexBuf.len)?
579 lexBuf.buf[lexBuf.getPtr]: 584 lexBuf.buf[lexBuf.getPtr]:
580 lexGeta(); 585 lexGeta();
581 /* do the \r\n -> \n or \r -> \n translation here */ 586 /* do the \r\n -> \n or \r -> \n translation here */
582 if (c == '\r') { 587 if (c == '\r') {
583 int a = (lexBuf.len>1)? 588 int a = (lexBuf.len>1)?
584 lexBuf.buf[(lexBuf.getPtr+1)%MAX_LEX_LOOKAHEAD]: 589 lexBuf.buf[(lexBuf.getPtr+1)%MAX_LEX_LOOKAHEAD]:
585 lexGeta_(1); 590 lexGeta_(1);
586 if (a == '\n') { 591 if (a == '\n') {
587 lexSkipLookahead(); 592 lexSkipLookahead();
588 } 593 }
589 lexBuf.buf[lexBuf.getPtr] = c = '\n'; 594 lexBuf.buf[lexBuf.getPtr] = c = '\n';
590 } 595 }
591 else if (c == '\n') { 596 else if (c == '\n') {
592 int a = (lexBuf.len>1)? 597 int a = (lexBuf.len>1)?
593 lexBuf.buf[lexBuf.getPtr+1]: 598 lexBuf.buf[lexBuf.getPtr+1]:
594 lexGeta_(1); 599 lexGeta_(1);
595 if (a == '\r') { 600 if (a == '\r') {
596 lexSkipLookahead(); 601 lexSkipLookahead();
597 } 602 }
598 lexBuf.buf[lexBuf.getPtr] = '\n'; 603 lexBuf.buf[lexBuf.getPtr] = '\n';
599 } 604 }
600 return c; 605 return c;
601 } 606 }
602 607
603static int lexGetc() { 608static int lexGetc() {
604 int c = lexLookahead(); 609 int c = lexLookahead();
605 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) { 610 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) {
606 /* EOF will remain in lookahead buffer */ 611 /* EOF will remain in lookahead buffer */
607 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD; 612 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD;
608 lexBuf.len--; 613 lexBuf.len--;
609 } 614 }
610 return c; 615 return c;
611 } 616 }
612 617
613static void lexSkipLookaheadWord() { 618static void lexSkipLookaheadWord() {
614 if (lexBuf.strsLen <= lexBuf.len) { 619 if (lexBuf.strsLen <= lexBuf.len) {
615 lexBuf.len -= lexBuf.strsLen; 620 lexBuf.len -= lexBuf.strsLen;
616 lexBuf.getPtr = (lexBuf.getPtr + lexBuf.strsLen) % MAX_LEX_LOOKAHEAD; 621 lexBuf.getPtr = (lexBuf.getPtr + lexBuf.strsLen) % MAX_LEX_LOOKAHEAD;
617 } 622 }
618 } 623 }
619 624
620static void lexClearToken() 625static void lexClearToken()
621 { 626 {
622 lexBuf.strsLen = 0; 627 lexBuf.strsLen = 0;
623 } 628 }
624 629
625static void lexAppendc(int c) 630static void lexAppendc(int c)
626 { 631 {
627 lexBuf.strs[lexBuf.strsLen] = c; 632 lexBuf.strs[lexBuf.strsLen] = c;
628 /* append up to zero termination */ 633 /* append up to zero termination */
629 if (c == 0) return; 634 if (c == 0) return;
630 lexBuf.strsLen++; 635 lexBuf.strsLen++;
631 if (lexBuf.strsLen > lexBuf.maxToken) { 636 if (lexBuf.strsLen > lexBuf.maxToken) {
632 /* double the token string size */ 637 /* double the token string size */
633 lexBuf.maxToken <<= 1; 638 lexBuf.maxToken <<= 1;
634 lexBuf.strs = (char*) realloc(lexBuf.strs,(size_t)lexBuf.maxToken); 639 lexBuf.strs = (char*) realloc(lexBuf.strs,(size_t)lexBuf.maxToken);
635 } 640 }
636 } 641 }
637 642
638static char* lexStr() { 643static char* lexStr() {
639 return dupStr(lexBuf.strs,(size_t)lexBuf.strsLen+1); 644 return dupStr(lexBuf.strs,(size_t)lexBuf.strsLen+1);
640 } 645 }
641 646
642static void lexSkipWhite() { 647static void lexSkipWhite() {
643 int c = lexLookahead(); 648 int c = lexLookahead();
644 while (c == ' ' || c == '\t') { 649 while (c == ' ' || c == '\t') {
645 lexSkipLookahead(); 650 lexSkipLookahead();
646 c = lexLookahead(); 651 c = lexLookahead();
647 } 652 }
648 } 653 }
649 654
650static char* lexGetWord() { 655static char* lexGetWord() {
651 int c; 656 int c;
652 lexSkipWhite(); 657 lexSkipWhite();
653 lexClearToken(); 658 lexClearToken();
654 c = lexLookahead(); 659 c = lexLookahead();
655 while (c != EOF && !strchr("\t\n ;:=",c)) { 660 while (c != EOF && !strchr("\t\n ;:=",c)) {
656 lexAppendc(c); 661 lexAppendc(c);
657 lexSkipLookahead(); 662 lexSkipLookahead();
658 c = lexLookahead(); 663 c = lexLookahead();
659 } 664 }
660 lexAppendc(0); 665 lexAppendc(0);
661 return lexStr(); 666 return lexStr();
662 } 667 }
663 668
664static void lexPushLookaheadc(int c) { 669static void lexPushLookaheadc(int c) {
665 int putptr; 670 int putptr;
666 /* can't putback EOF, because it never leaves lookahead buffer */ 671 /* can't putback EOF, because it never leaves lookahead buffer */
667 if (c == EOF) return; 672 if (c == EOF) return;
668 putptr = (int)lexBuf.getPtr - 1; 673 putptr = (int)lexBuf.getPtr - 1;
669 if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD; 674 if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD;
670 lexBuf.getPtr = putptr; 675 lexBuf.getPtr = putptr;
671 lexBuf.buf[putptr] = c; 676 lexBuf.buf[putptr] = c;
672 lexBuf.len += 1; 677 lexBuf.len += 1;
673 } 678 }
674 679
675static char* lexLookaheadWord() { 680static char* lexLookaheadWord() {
676 /* this function can lookahead word with max size of MAX_LEX_LOOKAHEAD_0 681 /* this function can lookahead word with max size of MAX_LEX_LOOKAHEAD_0
677 / and thing bigger than that will stop the lookahead and return 0; 682 / and thing bigger than that will stop the lookahead and return 0;
678 / leading white spaces are not recoverable. 683 / leading white spaces are not recoverable.
679 */ 684 */
680 int c; 685 int c;
681 int len = 0; 686 int len = 0;
682 int curgetptr = 0; 687 int curgetptr = 0;
683 lexSkipWhite(); 688 lexSkipWhite();
684 lexClearToken(); 689 lexClearToken();
685 curgetptr = (int)lexBuf.getPtr;// remember! 690 curgetptr = (int)lexBuf.getPtr;// remember!
686 while (len < (MAX_LEX_LOOKAHEAD_0)) { 691 while (len < (MAX_LEX_LOOKAHEAD_0)) {
687 c = lexGetc(); 692 c = lexGetc();
688 len++; 693 len++;
689 if (c == EOF || strchr("\t\n ;:=", c)) { 694 if (c == EOF || strchr("\t\n ;:=", c)) {
690 lexAppendc(0); 695 lexAppendc(0);
691 /* restore lookahead buf. */ 696 /* restore lookahead buf. */
692 lexBuf.len += len; 697 lexBuf.len += len;
693 lexBuf.getPtr = curgetptr; 698 lexBuf.getPtr = curgetptr;
694 return lexStr(); 699 return lexStr();
695 } 700 }
696 else 701 else
697 lexAppendc(c); 702 lexAppendc(c);
698 } 703 }
699 lexBuf.len += len;/* char that has been moved to lookahead buffer */ 704 lexBuf.len += len;/* char that has been moved to lookahead buffer */
700 lexBuf.getPtr = curgetptr; 705 lexBuf.getPtr = curgetptr;
701 return 0; 706 return 0;
702 } 707 }
703 708
704#ifdef _SUPPORT_LINE_FOLDING 709#ifdef _SUPPORT_LINE_FOLDING
705static void handleMoreRFC822LineBreak(int c) { 710static void handleMoreRFC822LineBreak(int c) {
706 /* suport RFC 822 line break in cases like 711 /* suport RFC 822 line break in cases like
707 *ADR: foo; 712 *ADR: foo;
708 * morefoo; 713 * morefoo;
709 * more foo; 714 * more foo;
710 */ 715 */
711 if (c == ';') { 716 if (c == ';') {
712 int a; 717 int a;
713 lexSkipLookahead(); 718 lexSkipLookahead();
714 /* skip white spaces */ 719 /* skip white spaces */
715 a = lexLookahead(); 720 a = lexLookahead();
716 while (a == ' ' || a == '\t') { 721 while (a == ' ' || a == '\t') {
717 lexSkipLookahead(); 722 lexSkipLookahead();
718 a = lexLookahead(); 723 a = lexLookahead();
719 } 724 }
720 if (a == '\n') { 725 if (a == '\n') {
721 lexSkipLookahead(); 726 lexSkipLookahead();
722 a = lexLookahead(); 727 a = lexLookahead();
723 if (a == ' ' || a == '\t') { 728 if (a == ' ' || a == '\t') {
724 /* continuation, throw away all the \n and spaces read so 729 /* continuation, throw away all the \n and spaces read so
725 * far 730 * far
726 */ 731 */
727 lexSkipWhite(); 732 lexSkipWhite();
728 lexPushLookaheadc(';'); 733 lexPushLookaheadc(';');
729 } 734 }
730 else { 735 else {
731 lexPushLookaheadc('\n'); 736 lexPushLookaheadc('\n');
732 lexPushLookaheadc(';'); 737 lexPushLookaheadc(';');
733 } 738 }
734 } 739 }
735 else { 740 else {
736 lexPushLookaheadc(';'); 741 lexPushLookaheadc(';');
737 } 742 }
738 } 743 }
739 } 744 }
740 745
741static char* lexGet1Value() { 746static char* lexGet1Value() {
742 int c; 747 int c;
743 lexSkipWhite(); 748 lexSkipWhite();
744 c = lexLookahead(); 749 c = lexLookahead();
745 lexClearToken(); 750 lexClearToken();
746 while (c != EOF && (c != ';' || !fieldedProp)) { 751 while (c != EOF && (c != ';' || !fieldedProp)) {
747 if (c == '\\' ) { 752 if (c == '\\' ) {
748 int a; 753 int a;
749 lexSkipLookahead(); 754 lexSkipLookahead();
750 a = lexLookahead(); 755 a = lexLookahead();
751 if ( a == ';' ) { 756 if ( a == ';' ) {
752 lexAppendc( ';' ); 757 lexAppendc( ';' );
753 lexSkipLookahead(); 758 lexSkipLookahead();
754 } else if ( a == '\n' ) { 759 } else if ( a == '\n' ) {
755 lexAppendc( '\n' ); 760 lexAppendc( '\n' );
756 lexSkipLookahead(); 761 lexSkipLookahead();
757 } else if ( a == '\\' ) { 762 } else if ( a == '\\' ) {
758 lexAppendc( '\\' ); 763 lexAppendc( '\\' );
759 lexSkipLookahead(); 764 lexSkipLookahead();
760 } else { 765 } else {
761 lexAppendc('\\'); 766 lexAppendc('\\');
762 } 767 }
763 } else if (c == '\n') { 768 } else if (c == '\n') {
764 int a; 769 int a;
765 lexSkipLookahead(); 770 lexSkipLookahead();
766 a = lexLookahead(); 771 a = lexLookahead();
767 if (a == ' ' || a == '\t') { 772 if (a == ' ' || a == '\t') {
768 lexAppendc(' '); 773 lexAppendc(' ');
769 lexSkipLookahead(); 774 lexSkipLookahead();
770 } 775 }
771 else { 776 else {
772 lexPushLookaheadc('\n'); 777 lexPushLookaheadc('\n');
773 break; 778 break;
774 } 779 }
775 } 780 }
776 else { 781 else {
777 lexAppendc(c); 782 lexAppendc(c);
778 lexSkipLookahead(); 783 lexSkipLookahead();
779 } 784 }
780 c = lexLookahead(); 785 c = lexLookahead();
781 } 786 }
782 lexAppendc(0); 787 lexAppendc(0);
783 handleMoreRFC822LineBreak(c); 788 handleMoreRFC822LineBreak(c);
784 return c==EOF?0:lexStr(); 789 return c==EOF?0:lexStr();
785 } 790 }
786#endif 791#endif
787 792
788static int match_begin_name(int end) { 793static int match_begin_name(int end) {
789 char *n = lexLookaheadWord(); 794 char *n = lexLookaheadWord();
790 int token = ID; 795 int token = ID;
791 if (n) { 796 if (n) {
792 if (!qstricmp(n,"vcard")) token = end?END_VCARD:BEGIN_VCARD; 797 if (!qstricmp(n,"vcard")) token = end?END_VCARD:BEGIN_VCARD;
793 else if (!qstricmp(n,"vcalendar")) token = end?END_VCAL:BEGIN_VCAL; 798 else if (!qstricmp(n,"vcalendar")) token = end?END_VCAL:BEGIN_VCAL;
794 else if (!qstricmp(n,"vevent")) token = end?END_VEVENT:BEGIN_VEVENT; 799 else if (!qstricmp(n,"vevent")) token = end?END_VEVENT:BEGIN_VEVENT;
795 else if (!qstricmp(n,"vtodo")) token = end?END_VTODO:BEGIN_VTODO; 800 else if (!qstricmp(n,"vtodo")) token = end?END_VTODO:BEGIN_VTODO;
796 deleteStr(n); 801 deleteStr(n);
797 return token; 802 return token;
798 } 803 }
799 return 0; 804 return 0;
800 } 805 }
801 806
802 807
803#ifdef INCLUDEMFC 808#ifdef INCLUDEMFC
804void initLex(const char *inputstring, unsigned long inputlen, CFile *inputfile) 809void initLex(const char *inputstring, unsigned long inputlen, CFile *inputfile)
805#else 810#else
806void initLex(const char *inputstring, unsigned long inputlen, FILE *inputfile) 811void initLex(const char *inputstring, unsigned long inputlen, FILE *inputfile)
807#endif 812#endif
808 { 813 {
809 // initialize lex mode stack 814 // initialize lex mode stack
810 lexBuf.lexModeStack[lexBuf.lexModeStackTop=0] = L_NORMAL; 815 lexBuf.lexModeStack[lexBuf.lexModeStackTop=0] = L_NORMAL;
811 816
812 // iniatialize lex buffer. 817 // iniatialize lex buffer.
813 lexBuf.inputString = (char*) inputstring; 818 lexBuf.inputString = (char*) inputstring;
814 lexBuf.inputLen = inputlen; 819 lexBuf.inputLen = inputlen;
815 lexBuf.curPos = 0; 820 lexBuf.curPos = 0;
816 lexBuf.inputFile = inputfile; 821 lexBuf.inputFile = inputfile;
817 822
818 lexBuf.len = 0; 823 lexBuf.len = 0;
819 lexBuf.getPtr = 0; 824 lexBuf.getPtr = 0;
820 825
821 lexBuf.maxToken = MAXTOKEN; 826 lexBuf.maxToken = MAXTOKEN;
822 lexBuf.strs = (char*)malloc(MAXTOKEN); 827 lexBuf.strs = (char*)malloc(MAXTOKEN);
823 lexBuf.strsLen = 0; 828 lexBuf.strsLen = 0;
824 829
825 } 830 }
826 831
827static void finiLex() { 832static void finiLex() {
828 free(lexBuf.strs); 833 free(lexBuf.strs);
829 } 834 }
830 835
831 836
832/*-----------------------------------*/ 837/*-----------------------------------*/
833/* This parses and converts the base64 format for binary encoding into 838/* This parses and converts the base64 format for binary encoding into
834 * a decoded buffer (allocated with new). See RFC 1521. 839 * a decoded buffer (allocated with new). See RFC 1521.
835 */ 840 */
836static int lexGetDataFromBase64() 841static int lexGetDataFromBase64()
837 { 842 {
838 unsigned long bytesLen = 0, bytesMax = 0; 843 unsigned long bytesLen = 0, bytesMax = 0;
839 int quadIx = 0, pad = 0; 844 int quadIx = 0, pad = 0;
840 unsigned long trip = 0; 845 unsigned long trip = 0;
841 unsigned char b; 846 unsigned char b;
842 int c; 847 int c;
843 unsigned char *bytes = NULL; 848 unsigned char *bytes = NULL;
844 unsigned char *oldBytes = NULL; 849 unsigned char *oldBytes = NULL;
845 850
846 DBG_(("db: lexGetDataFromBase64\n")); 851 DBG_(("db: lexGetDataFromBase64\n"));
847 while (1) { 852 while (1) {
848 c = lexGetc(); 853 c = lexGetc();
849 lexSkipWhite(); 854 lexSkipWhite();
850 if (c == '\n') { 855 if (c == '\n') {
851 ++mime_lineNum; 856 ++mime_lineNum;
852 if (lexLookahead() == '\n') { 857 if (lexLookahead() == '\n') {
853 /* a '\n' character by itself means end of data */ 858 /* a '\n' character by itself means end of data */
854 break; 859 break;
855 } 860 }
856 else continue; /* ignore '\n' */ 861 else continue; /* ignore '\n' */
857 } 862 }
858 else { 863 else {
859 if ((c >= 'A') && (c <= 'Z')) 864 if ((c >= 'A') && (c <= 'Z'))
860 b = (unsigned char)(c - 'A'); 865 b = (unsigned char)(c - 'A');
861 else if ((c >= 'a') && (c <= 'z')) 866 else if ((c >= 'a') && (c <= 'z'))
862 b = (unsigned char)(c - 'a') + 26; 867 b = (unsigned char)(c - 'a') + 26;
863 else if ((c >= '0') && (c <= '9')) 868 else if ((c >= '0') && (c <= '9'))
864 b = (unsigned char)(c - '0') + 52; 869 b = (unsigned char)(c - '0') + 52;
865 else if (c == '+') 870 else if (c == '+')
866 b = 62; 871 b = 62;
867 else if (c == '/') 872 else if (c == '/')
868 b = 63; 873 b = 63;
869 else if (c == '=') { 874 else if (c == '=') {
870 b = 0; 875 b = 0;
871 pad++; 876 pad++;
872 } else { /* error condition */ 877 } else { /* error condition */
873 if (bytes) free(bytes); 878 if (bytes) free(bytes);
874 else if (oldBytes) free(oldBytes); 879 else if (oldBytes) free(oldBytes);
875 // error recovery: skip until 2 adjacent newlines. 880 // error recovery: skip until 2 adjacent newlines.
876 DBG_(("db: invalid character 0x%x '%c'\n", c,c)); 881 DBG_(("db: invalid character 0x%x '%c'\n", c,c));
877 if (c != EOF) { 882 if (c != EOF) {
878 c = lexGetc(); 883 c = lexGetc();
879 while (c != EOF) { 884 while (c != EOF) {
880 if (c == '\n') { 885 if (c == '\n') {
881 lexSkipWhite(); 886 lexSkipWhite();
882 if(lexLookahead() == '\n') { 887 if(lexLookahead() == '\n') {
883 ++mime_lineNum; 888 ++mime_lineNum;
884 break; 889 break;
885 } 890 }
886 } 891 }
887 c = lexGetc(); 892 c = lexGetc();
888 } 893 }
889 } 894 }
890 return c != EOF; 895 return c != EOF;
891 } 896 }
892 trip = (trip << 6) | b; 897 trip = (trip << 6) | b;
893 if (++quadIx == 4) { 898 if (++quadIx == 4) {
894 unsigned char outBytes[3]; 899 unsigned char outBytes[3];
895 int numOut; 900 int numOut;
896 int i; 901 int i;
897 for (i = 0; i < 3; i++) { 902 for (i = 0; i < 3; i++) {
898 outBytes[2-i] = (unsigned char)(trip & 0xFF); 903 outBytes[2-i] = (unsigned char)(trip & 0xFF);
899 trip >>= 8; 904 trip >>= 8;
900 } 905 }
901 numOut = 3 - pad; 906 numOut = 3 - pad;
902 if (bytesLen + numOut > bytesMax) { 907 if (bytesLen + numOut > bytesMax) {
903 if (!bytes) { 908 if (!bytes) {
904 bytesMax = 1024; 909 bytesMax = 1024;
905 bytes = (unsigned char*)malloc((size_t)bytesMax); 910 bytes = (unsigned char*)malloc((size_t)bytesMax);
906 } 911 }
907 else { 912 else {
908 bytesMax <<= 2; 913 bytesMax <<= 2;
909 oldBytes = bytes; 914 oldBytes = bytes;
910 bytes = (unsigned char*)realloc(bytes,(size_t)bytesMax); 915 bytes = (unsigned char*)realloc(bytes,(size_t)bytesMax);
911 } 916 }
912 if (bytes == 0) { 917 if (bytes == 0) {
913 mime_error("out of memory while processing BASE64 data\n"); 918 mime_error("out of memory while processing BASE64 data\n");
914 } 919 }
915 } 920 }
916 if (bytes) { 921 if (bytes) {
917 memcpy(bytes + bytesLen, outBytes, numOut); 922 memcpy(bytes + bytesLen, outBytes, numOut);
918 bytesLen += numOut; 923 bytesLen += numOut;
919 } 924 }
920 trip = 0; 925 trip = 0;
921 quadIx = 0; 926 quadIx = 0;
922 } 927 }
923 } 928 }
924 } /* while */ 929 } /* while */
925 DBG_(("db: bytesLen = %d\n", bytesLen)); 930 DBG_(("db: bytesLen = %d\n", bytesLen));
926 /* kludge: all this won't be necessary if we have tree form 931 /* kludge: all this won't be necessary if we have tree form
927 representation */ 932 representation */
928 if (bytes) { 933 if (bytes) {
929 setValueWithSize(curProp,bytes,(unsigned int)bytesLen); 934 setValueWithSize(curProp,bytes,(unsigned int)bytesLen);
930 free(bytes); 935 free(bytes);
931 } 936 }
932 else if (oldBytes) { 937 else if (oldBytes) {
933 setValueWithSize(curProp,oldBytes,(unsigned int)bytesLen); 938 setValueWithSize(curProp,oldBytes,(unsigned int)bytesLen);
934 free(oldBytes); 939 free(oldBytes);
935 } 940 }
936 return bytesLen; 941 return bytesLen;
937 } 942 }
938 943
939static int match_begin_end_name(int end) { 944static int match_begin_end_name(int end) {
940 int token; 945 int token;
941 lexSkipWhite(); 946 lexSkipWhite();
942 if (lexLookahead() != ':') return ID; 947 if (lexLookahead() != ':') return ID;
943 lexSkipLookahead(); 948 lexSkipLookahead();
944 lexSkipWhite(); 949 lexSkipWhite();
945 token = match_begin_name(end); 950 token = match_begin_name(end);
946 if (token == ID) { 951 if (token == ID) {
947 lexPushLookaheadc(':'); 952 lexPushLookaheadc(':');
948 DBG_(("db: ID '%s'\n", yylval.str)); 953 DBG_(("db: ID '%s'\n", yylval.str));
949 return ID; 954 return ID;
950 } 955 }
951 else if (token != 0) { 956 else if (token != 0) {
952 lexSkipLookaheadWord(); 957 lexSkipLookaheadWord();
953 deleteStr(yylval.str); 958 deleteStr(yylval.str);
954 DBG_(("db: begin/end %d\n", token)); 959 DBG_(("db: begin/end %d\n", token));
955 return token; 960 return token;
956 } 961 }
957 return 0; 962 return 0;
958 } 963 }
959 964
960static char* lexGetQuotedPrintable() 965static char* lexGetQuotedPrintable()
961{ 966{
962 int c; 967 int c;
963 lexSkipWhite(); 968 lexSkipWhite();
964 c = lexLookahead(); 969 c = lexLookahead();
965 lexClearToken(); 970 lexClearToken();
966 971
967 while (c != EOF && (c != ';' || !fieldedProp)) { 972 while (c != EOF && (c != ';' || !fieldedProp)) {
968 if (c == '\n') { 973 if (c == '\n') {
969 // break, leave '\n' on remaining chars. 974 // break, leave '\n' on remaining chars.
970 break; 975 break;
971 } else if (c == '=') { 976 } else if (c == '=') {
972 int cur = 0; 977 int cur = 0;
973 int next; 978 int next;
974 979
975 lexSkipLookahead(); // skip '=' 980 lexSkipLookahead(); // skip '='
976 next = lexLookahead(); 981 next = lexLookahead();
977 982
978 if (next == '\n') { 983 if (next == '\n') {
979 // skip and only skip the \n 984 // skip and only skip the \n
980 lexSkipLookahead(); 985 lexSkipLookahead();
981 c = lexLookahead(); 986 c = lexLookahead();
982 ++mime_lineNum; // aid in error reporting 987 ++mime_lineNum; // aid in error reporting
983 continue; 988 continue;
984 } else if (next >= '0' && next <= '9') { 989 } else if (next >= '0' && next <= '9') {
985 cur = next - '0'; 990 cur = next - '0';
986 } else if (next >= 'A' && next <= 'F') { 991 } else if (next >= 'A' && next <= 'F') {
987 cur = next - 'A' + 10; 992 cur = next - 'A' + 10;
988 } else { 993 } else {
989 // we have been sent buggy stuff. doesn't matter 994 // we have been sent buggy stuff. doesn't matter
990 // what we do so long as we keep going. 995 // what we do so long as we keep going.
991 // should probably spit an error here 996 // should probably spit an error here
992 lexSkipLookahead(); 997 lexSkipLookahead();
993 c = lexLookahead(); 998 c = lexLookahead();
994 continue; 999 continue;
995 } 1000 }
996 1001
997 lexSkipLookahead(); // skip A-Z0-9 1002 lexSkipLookahead(); // skip A-Z0-9
998 next = lexLookahead(); 1003 next = lexLookahead();
999 1004
1000 cur = cur * 16; 1005 cur = cur * 16;
1001 // this time really just expecting 0-9A-F 1006 // this time really just expecting 0-9A-F
1002 if (next >= '0' && next <= '9') { 1007 if (next >= '0' && next <= '9') {
1003 cur += next - '0'; 1008 cur += next - '0';
1004 } else if (next >= 'A' && next <= 'F') { 1009 } else if (next >= 'A' && next <= 'F') {
1005 cur += next - 'A' + 10; 1010 cur += next - 'A' + 10;
1006 } else { 1011 } else {
1007 // we have been sent buggy stuff. doesn't matter 1012 // we have been sent buggy stuff. doesn't matter
1008 // what we do so long as we keep going. 1013 // what we do so long as we keep going.
1009 // should probably spit an error here 1014 // should probably spit an error here
1010 lexSkipLookahead(); 1015 lexSkipLookahead();
1011 c = lexLookahead(); 1016 c = lexLookahead();
1012 continue; 1017 continue;
1013 } 1018 }
1014 1019
1015 // got a valid escaped =. append it. 1020 // got a valid escaped =. append it.
1016 lexSkipLookahead(); // skip second 0-9A-F 1021 lexSkipLookahead(); // skip second 0-9A-F
1017 lexAppendc(cur); 1022 lexAppendc(cur);
1018 } else { 1023 } else {
1019 lexSkipLookahead(); // skip whatever we just read. 1024 lexSkipLookahead(); // skip whatever we just read.
1020 lexAppendc(c); // and append it. 1025 lexAppendc(c); // and append it.
1021 } 1026 }
1022 c = lexLookahead(); 1027 c = lexLookahead();
1023 } 1028 }
1024 lexAppendc(0); 1029 lexAppendc(0);
1025 return c==EOF?0:lexStr(); 1030 return c==EOF?0:lexStr();
1026} 1031}
1027 1032
1028static int yylex() { 1033static int yylex() {
1029 1034
1030 int lexmode = LEXMODE(); 1035 int lexmode = LEXMODE();
1031 if (lexmode == L_VALUES) { 1036 if (lexmode == L_VALUES) {
1032 int c = lexGetc(); 1037 int c = lexGetc();
1033 if (c == ';' && fieldedProp) { 1038 if (c == ';' && fieldedProp) {
1034 DBG_(("db: SEMICOLON\n")); 1039 DBG_(("db: SEMICOLON\n"));
1035 lexPushLookaheadc(c); 1040 lexPushLookaheadc(c);
1036 handleMoreRFC822LineBreak(c); 1041 handleMoreRFC822LineBreak(c);
1037 lexSkipLookahead(); 1042 lexSkipLookahead();
1038 return SEMICOLON; 1043 return SEMICOLON;
1039 } 1044 }
1040 else if (strchr("\n",c)) { 1045 else if (strchr("\n",c)) {
1041 ++mime_lineNum; 1046 ++mime_lineNum;
1042 /* consume all line separator(s) adjacent to each other */ 1047 /* consume all line separator(s) adjacent to each other */
1043 c = lexLookahead(); 1048 c = lexLookahead();
1044 while (strchr("\n",c)) { 1049 while (strchr("\n",c)) {
1045 lexSkipLookahead(); 1050 lexSkipLookahead();
1046 c = lexLookahead(); 1051 c = lexLookahead();
1047 ++mime_lineNum; 1052 ++mime_lineNum;
1048 } 1053 }
1049 DBG_(("db: LINESEP\n")); 1054 DBG_(("db: LINESEP\n"));
1050 return LINESEP; 1055 return LINESEP;
1051 } 1056 }
1052 else { 1057 else {
1053 char *p = 0; 1058 char *p = 0;
1054 lexPushLookaheadc(c); 1059 lexPushLookaheadc(c);
1055 if (lexWithinMode(L_BASE64)) { 1060 if (lexWithinMode(L_BASE64)) {
1056 /* get each char and convert to bin on the fly... */ 1061 /* get each char and convert to bin on the fly... */
1057 yylval.str = NULL; 1062 yylval.str = NULL;
1058 return lexGetDataFromBase64() ? STRING : 0; 1063 return lexGetDataFromBase64() ? STRING : 0;
1059 } 1064 }
1060 else if (lexWithinMode(L_QUOTED_PRINTABLE)) { 1065 else if (lexWithinMode(L_QUOTED_PRINTABLE)) {
1061 p = lexGetQuotedPrintable(); 1066 p = lexGetQuotedPrintable();
1062 } 1067 }
1063 else { 1068 else {
1064#ifdef _SUPPORT_LINE_FOLDING 1069#ifdef _SUPPORT_LINE_FOLDING
1065 p = lexGet1Value(); 1070 p = lexGet1Value();
1066#else 1071#else
1067 p = lexGetStrUntil(";\n"); 1072 p = lexGetStrUntil(";\n");
1068#endif 1073#endif
1069 } 1074 }
1070 if (p) { 1075 if (p) {
1071 DBG_(("db: STRING: '%s'\n", p)); 1076 DBG_(("db: STRING: '%s'\n", p));
1072 yylval.str = p; 1077 yylval.str = p;
1073 return STRING; 1078 return STRING;
1074 } 1079 }
1075 else return 0; 1080 else return 0;
1076 } 1081 }
1077 } 1082 }
1078 else { 1083 else {
1079 /* normal mode */ 1084 /* normal mode */
1080 while (1) { 1085 while (1) {
1081 int c = lexGetc(); 1086 int c = lexGetc();
1082 switch(c) { 1087 switch(c) {
1083 case ':': { 1088 case ':': {
1084 /* consume all line separator(s) adjacent to each other */ 1089 /* consume all line separator(s) adjacent to each other */
1085 /* ignoring linesep immediately after colon. */ 1090 /* ignoring linesep immediately after colon. */
1086 /* I don't see this in the spec, and it breaks null values -- WA 1091 /* I don't see this in the spec, and it breaks null values -- WA
1087 c = lexLookahead(); 1092 c = lexLookahead();
1088 while (strchr("\n",c)) { 1093 while (strchr("\n",c)) {
1089 lexSkipLookahead(); 1094 lexSkipLookahead();
1090 c = lexLookahead(); 1095 c = lexLookahead();
1091 ++mime_lineNum; 1096 ++mime_lineNum;
1092 } 1097 }
1093 */ 1098 */
1094 DBG_(("db: COLON\n")); 1099 DBG_(("db: COLON\n"));
1095 return COLON; 1100 return COLON;
1096 } 1101 }
1097 case ';': 1102 case ';':
1098 DBG_(("db: SEMICOLON\n")); 1103 DBG_(("db: SEMICOLON\n"));
1099 return SEMICOLON; 1104 return SEMICOLON;
1100 case '=': 1105 case '=':
1101 DBG_(("db: EQ\n")); 1106 DBG_(("db: EQ\n"));
1102 return EQ; 1107 return EQ;
1103 /* ignore whitespace in this mode */ 1108 /* ignore whitespace in this mode */
1104 case '\t': 1109 case '\t':
1105 case ' ': continue; 1110 case ' ': continue;
1106 case '\n': { 1111 case '\n': {
1107 ++mime_lineNum; 1112 ++mime_lineNum;
1108 continue; 1113 continue;
1109 } 1114 }
1110 case EOF: return 0; 1115 case EOF: return 0;
1111 break; 1116 break;
1112 default: { 1117 default: {
1113 lexPushLookaheadc(c); 1118 lexPushLookaheadc(c);
1114 if (isalnum(c)) { 1119 if (isalnum(c)) {
1115 char *t = lexGetWord(); 1120 char *t = lexGetWord();
1116 yylval.str = t; 1121 yylval.str = t;
1117 if (!qstricmp(t, "begin")) { 1122 if (!qstricmp(t, "begin")) {
1118 return match_begin_end_name(0); 1123 return match_begin_end_name(0);
1119 } 1124 }
1120 else if (!qstricmp(t,"end")) { 1125 else if (!qstricmp(t,"end")) {
1121 return match_begin_end_name(1); 1126 return match_begin_end_name(1);
1122 } 1127 }
1123 else { 1128 else {
1124 DBG_(("db: ID '%s'\n", t)); 1129 DBG_(("db: ID '%s'\n", t));
1125 return ID; 1130 return ID;
1126 } 1131 }
1127 } 1132 }
1128 else { 1133 else {
1129 /* unknow token */ 1134 /* unknow token */
1130 return 0; 1135 return 0;
1131 } 1136 }
1132 break; 1137 break;
1133 } 1138 }
1134 } 1139 }
1135 } 1140 }
1136 } 1141 }
1137 return 0; 1142 return 0;
1138 } 1143 }
1139 1144
1140 1145
1141/***************************************************************************/ 1146/***************************************************************************/
1142 /*** Public Functions ****/ 1147 /*** Public Functions ****/
1143/***************************************************************************/ 1148/***************************************************************************/
1144 1149
1145static VObject* Parse_MIMEHelper() 1150static VObject* Parse_MIMEHelper()
1146 { 1151 {
1147 ObjStackTop = -1; 1152 ObjStackTop = -1;
1148 mime_numErrors = 0; 1153 mime_numErrors = 0;
1149 mime_lineNum = 1; 1154 mime_lineNum = 1;
1150 vObjList = 0; 1155 vObjList = 0;
1151 curObj = 0; 1156 curObj = 0;
1152 1157
1153 if (yyparse() != 0) 1158 if (yyparse() != 0)
1154 return 0; 1159 return 0;
1155 1160
1156 finiLex(); 1161 finiLex();
1157 return vObjList; 1162 return vObjList;
1158 } 1163 }
1159 1164
1160/*--------------------------------------------*/ 1165/*--------------------------------------------*/
1161DLLEXPORT(VObject*) Parse_MIME(const char *input, unsigned long len) 1166DLLEXPORT(VObject*) Parse_MIME(const char *input, unsigned long len)
1162 { 1167 {
1163 initLex(input, len, 0); 1168 initLex(input, len, 0);
1164 return Parse_MIMEHelper(); 1169 return Parse_MIMEHelper();
1165 } 1170 }
1166 1171
1167 1172
1168#if INCLUDEMFC 1173#if INCLUDEMFC
1169 1174
1170DLLEXPORT(VObject*) Parse_MIME_FromFile(CFile *file) 1175DLLEXPORT(VObject*) Parse_MIME_FromFile(CFile *file)
1171 { 1176 {
1172 unsigned long startPos; 1177 unsigned long startPos;
1173 VObject *result; 1178 VObject *result;
1174 1179
1175 initLex(0,-1,file); 1180 initLex(0,-1,file);
1176 startPos = file->GetPosition(); 1181 startPos = file->GetPosition();
1177 if (!(result = Parse_MIMEHelper())) 1182 if (!(result = Parse_MIMEHelper()))
1178 file->Seek(startPos, CFile::begin); 1183 file->Seek(startPos, CFile::begin);
1179 return result; 1184 return result;
1180 } 1185 }
1181 1186
1182#else 1187#else
1183 1188
1184VObject* Parse_MIME_FromFile(FILE *file) 1189VObject* Parse_MIME_FromFile(FILE *file)
1185 { 1190 {
1186 VObject *result; 1191 VObject *result;
1187 long startPos; 1192 long startPos;
1188 1193
1189 initLex(0,(unsigned long)-1,file); 1194 initLex(0,(unsigned long)-1,file);
1190 startPos = ftell(file); 1195 startPos = ftell(file);
1191 if (!(result = Parse_MIMEHelper())) { 1196 if (!(result = Parse_MIMEHelper())) {
1192 fseek(file,startPos,SEEK_SET); 1197 fseek(file,startPos,SEEK_SET);
1193 } 1198 }
1194 return result; 1199 return result;
1195 } 1200 }
1196 1201
1197DLLEXPORT(VObject*) Parse_MIME_FromFileName(char *fname) 1202DLLEXPORT(VObject*) Parse_MIME_FromFileName(char *fname)
1198 { 1203 {
1199 FILE *fp = fopen(fname,"r"); 1204 FILE *fp = fopen(fname,"r");
1200 if (fp) { 1205 if (fp) {
1201 VObject* o = Parse_MIME_FromFile(fp); 1206 VObject* o = Parse_MIME_FromFile(fp);
1202 fclose(fp); 1207 fclose(fp);
1203 return o; 1208 return o;
1204 } 1209 }
1205 else { 1210 else {
1206 char msg[80]; 1211 char msg[80];
1207 sprintf(msg, "can't open file '%s' for reading\n", fname); 1212 sprintf(msg, "can't open file '%s' for reading\n", fname);
1208 mime_error_(msg); 1213 mime_error_(msg);
1209 return 0; 1214 return 0;
1210 } 1215 }
1211 } 1216 }
1212 1217
1213#endif 1218#endif
1214 1219
1215/*-------------------------------------*/ 1220/*-------------------------------------*/
1216 1221
1217static MimeErrorHandler mimeErrorHandler; 1222static MimeErrorHandler mimeErrorHandler;
1218 1223
1219DLLEXPORT(void) registerMimeErrorHandler(MimeErrorHandler me) 1224DLLEXPORT(void) registerMimeErrorHandler(MimeErrorHandler me)
1220 { 1225 {
1221 mimeErrorHandler = me; 1226 mimeErrorHandler = me;
1222 } 1227 }
1223 1228
1224void mime_error(char *s) 1229void mime_error(char *s)
1225 { 1230 {
1226 char msg[256]; 1231 char msg[256];
1227 if (mimeErrorHandler) { 1232 if (mimeErrorHandler) {
1228 sprintf(msg,"%s at line %d", s, mime_lineNum); 1233 sprintf(msg,"%s at line %d", s, mime_lineNum);
1229 mimeErrorHandler(msg); 1234 mimeErrorHandler(msg);
1230 } 1235 }
1231 } 1236 }
1232 1237
1233void mime_error_(char *s) 1238void mime_error_(char *s)
1234 { 1239 {
1235 if (mimeErrorHandler) { 1240 if (mimeErrorHandler) {
1236 mimeErrorHandler(s); 1241 mimeErrorHandler(s);
1237 } 1242 }
1238 } 1243 }
1239 1244
1240#line 1241 "y.tab.c" 1245#line 1241 "y.tab.c"
1241#define YYABORT goto yyabort 1246#define YYABORT goto yyabort
1242#define YYREJECT goto yyabort 1247#define YYREJECT goto yyabort
1243#define YYACCEPT goto yyaccept 1248#define YYACCEPT goto yyaccept
1244#define YYERROR goto yyerrlab 1249#define YYERROR goto yyerrlab
1245int 1250int
1246#if defined(__STDC__) 1251#if defined(__STDC__)
1247yyparse(void) 1252yyparse(void)
@@ -1383,79 +1388,79 @@ case 2:
1383{ addList(&vObjList, yyvsp[0].vobj); curObj = 0; } 1388{ addList(&vObjList, yyvsp[0].vobj); curObj = 0; }
1384break; 1389break;
1385case 3: 1390case 3:
1386#line 223 "backend/vcc.y" 1391#line 223 "backend/vcc.y"
1387{ addList(&vObjList, yyvsp[0].vobj); curObj = 0; } 1392{ addList(&vObjList, yyvsp[0].vobj); curObj = 0; }
1388break; 1393break;
1389case 6: 1394case 6:
1390#line 232 "backend/vcc.y" 1395#line 232 "backend/vcc.y"
1391{ 1396{
1392 lexPushMode(L_VCARD); 1397 lexPushMode(L_VCARD);
1393 if (!pushVObject(VCCardProp)) YYERROR; 1398 if (!pushVObject(VCCardProp)) YYERROR;
1394 } 1399 }
1395break; 1400break;
1396case 7: 1401case 7:
1397#line 237 "backend/vcc.y" 1402#line 237 "backend/vcc.y"
1398{ 1403{
1399 lexPopMode(0); 1404 lexPopMode(0);
1400 yyval.vobj = popVObject(); 1405 yyval.vobj = popVObject();
1401 } 1406 }
1402break; 1407break;
1403case 8: 1408case 8:
1404#line 242 "backend/vcc.y" 1409#line 242 "backend/vcc.y"
1405{ 1410{
1406 lexPushMode(L_VCARD); 1411 lexPushMode(L_VCARD);
1407 if (!pushVObject(VCCardProp)) YYERROR; 1412 if (!pushVObject(VCCardProp)) YYERROR;
1408 } 1413 }
1409break; 1414break;
1410case 9: 1415case 9:
1411#line 247 "backend/vcc.y" 1416#line 247 "backend/vcc.y"
1412{ 1417{
1413 lexPopMode(0); 1418 lexPopMode(0);
1414 yyval.vobj = popVObject(); 1419 yyval.vobj = popVObject();
1415 } 1420 }
1416break; 1421break;
1417case 12: 1422case 12:
1418#line 258 "backend/vcc.y" 1423#line 258 "backend/vcc.y"
1419{ 1424{
1420 lexPushMode(L_VALUES); 1425 lexPushMode(L_VALUES);
1421 } 1426 }
1422break; 1427break;
1423case 13: 1428case 13:
1424#line 262 "backend/vcc.y" 1429#line 262 "backend/vcc.y"
1425{ 1430{
1426 if (lexWithinMode(L_BASE64) || lexWithinMode(L_QUOTED_PRINTABLE)) 1431 if (lexWithinMode(L_BASE64) || lexWithinMode(L_QUOTED_PRINTABLE))
1427 lexPopMode(0); 1432 lexPopMode(0);
1428 lexPopMode(0); 1433 lexPopMode(0);
1429 } 1434 }
1430break; 1435break;
1431case 15: 1436case 15:
1432#line 271 "backend/vcc.y" 1437#line 271 "backend/vcc.y"
1433{ 1438{
1434 enterProps(yyvsp[0].str); 1439 enterProps(yyvsp[0].str);
1435 } 1440 }
1436break; 1441break;
1437case 17: 1442case 17:
1438#line 276 "backend/vcc.y" 1443#line 276 "backend/vcc.y"
1439{ 1444{
1440 enterProps(yyvsp[0].str); 1445 enterProps(yyvsp[0].str);
1441 } 1446 }
1442break; 1447break;
1443case 21: 1448case 21:
1444#line 289 "backend/vcc.y" 1449#line 289 "backend/vcc.y"
1445{ 1450{
1446 enterAttr(yyvsp[0].str,0); 1451 enterAttr(yyvsp[0].str,0);
1447 } 1452 }
1448break; 1453break;
1449case 22: 1454case 22:
1450#line 293 "backend/vcc.y" 1455#line 293 "backend/vcc.y"
1451{ 1456{
1452 enterAttr(yyvsp[-2].str,yyvsp[0].str); 1457 enterAttr(yyvsp[-2].str,yyvsp[0].str);
1453 1458
1454 } 1459 }
1455break; 1460break;
1456case 24: 1461case 24:
1457#line 302 "backend/vcc.y" 1462#line 302 "backend/vcc.y"
1458{ enterValues(yyvsp[-1].str); } 1463{ enterValues(yyvsp[-1].str); }
1459break; 1464break;
1460case 26: 1465case 26:
1461#line 304 "backend/vcc.y" 1466#line 304 "backend/vcc.y"
@@ -1478,68 +1483,68 @@ case 31:
1478{ if (!pushVObject(VCCalProp)) YYERROR; } 1483{ if (!pushVObject(VCCalProp)) YYERROR; }
1479break; 1484break;
1480case 32: 1485case 32:
1481#line 321 "backend/vcc.y" 1486#line 321 "backend/vcc.y"
1482{ yyval.vobj = popVObject(); } 1487{ yyval.vobj = popVObject(); }
1483break; 1488break;
1484case 38: 1489case 38:
1485#line 336 "backend/vcc.y" 1490#line 336 "backend/vcc.y"
1486{ 1491{
1487 lexPushMode(L_VEVENT); 1492 lexPushMode(L_VEVENT);
1488 if (!pushVObject(VCEventProp)) YYERROR; 1493 if (!pushVObject(VCEventProp)) YYERROR;
1489 } 1494 }
1490break; 1495break;
1491case 39: 1496case 39:
1492#line 342 "backend/vcc.y" 1497#line 342 "backend/vcc.y"
1493{ 1498{
1494 lexPopMode(0); 1499 lexPopMode(0);
1495 popVObject(); 1500 popVObject();
1496 } 1501 }
1497break; 1502break;
1498case 40: 1503case 40:
1499#line 347 "backend/vcc.y" 1504#line 347 "backend/vcc.y"
1500{ 1505{
1501 lexPushMode(L_VEVENT); 1506 lexPushMode(L_VEVENT);
1502 if (!pushVObject(VCEventProp)) YYERROR; 1507 if (!pushVObject(VCEventProp)) YYERROR;
1503 } 1508 }
1504break; 1509break;
1505case 41: 1510case 41:
1506#line 352 "backend/vcc.y" 1511#line 352 "backend/vcc.y"
1507{ 1512{
1508 lexPopMode(0); 1513 lexPopMode(0);
1509 popVObject(); 1514 popVObject();
1510 } 1515 }
1511break; 1516break;
1512case 42: 1517case 42:
1513#line 360 "backend/vcc.y" 1518#line 360 "backend/vcc.y"
1514{ 1519{
1515 lexPushMode(L_VTODO); 1520 lexPushMode(L_VTODO);
1516 if (!pushVObject(VCTodoProp)) YYERROR; 1521 if (!pushVObject(VCTodoProp)) YYERROR;
1517 } 1522 }
1518break; 1523break;
1519case 43: 1524case 43:
1520#line 366 "backend/vcc.y" 1525#line 366 "backend/vcc.y"
1521{ 1526{
1522 lexPopMode(0); 1527 lexPopMode(0);
1523 popVObject(); 1528 popVObject();
1524 } 1529 }
1525break; 1530break;
1526case 44: 1531case 44:
1527#line 371 "backend/vcc.y" 1532#line 371 "backend/vcc.y"
1528{ 1533{
1529 lexPushMode(L_VTODO); 1534 lexPushMode(L_VTODO);
1530 if (!pushVObject(VCTodoProp)) YYERROR; 1535 if (!pushVObject(VCTodoProp)) YYERROR;
1531 } 1536 }
1532break; 1537break;
1533case 45: 1538case 45:
1534#line 376 "backend/vcc.y" 1539#line 376 "backend/vcc.y"
1535{ 1540{
1536 lexPopMode(0); 1541 lexPopMode(0);
1537 popVObject(); 1542 popVObject();
1538 } 1543 }
1539break; 1544break;
1540#line 1541 "y.tab.c" 1545#line 1541 "y.tab.c"
1541 } 1546 }
1542 yyssp -= yym; 1547 yyssp -= yym;
1543 yystate = *yyssp; 1548 yystate = *yyssp;
1544 yyvsp -= yym; 1549 yyvsp -= yym;
1545 yym = yylhs[yyn]; 1550 yym = yylhs[yyn];