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