summaryrefslogtreecommitdiffabout
path: root/libkcal/versit/vcc.c
Unidiff
Diffstat (limited to 'libkcal/versit/vcc.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libkcal/versit/vcc.c2162
1 files changed, 2162 insertions, 0 deletions
diff --git a/libkcal/versit/vcc.c b/libkcal/versit/vcc.c
new file mode 100644
index 0000000..350cac3
--- a/dev/null
+++ b/libkcal/versit/vcc.c
@@ -0,0 +1,2162 @@
1
2/* A Bison parser, made from ./vcc.y
3 by GNU Bison version 1.28 */
4
5#define YYBISON 1 /* Identify Bison output. */
6
7#ifdef _WIN32_
8#define strcasecmp _stricmp
9#endif
10
11 #define EQ257
12 #define COLON258
13 #define DOT259
14 #define SEMICOLON260
15 #define SPACE261
16 #define HTAB262
17 #define LINESEP263
18 #define NEWLINE264
19 #define BEGIN_VCARD265
20 #define END_VCARD266
21 #define BEGIN_VCAL267
22 #define END_VCAL268
23 #define BEGIN_VEVENT269
24 #define END_VEVENT270
25 #define BEGIN_VTODO271
26 #define END_VTODO272
27 #define ID273
28 #define STRING274
29
30#line 1 "./vcc.y"
31
32
33/***************************************************************************
34(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
35Business Machines Corporation and Siemens Rolm Communications Inc.
36
37For purposes of this license notice, the term Licensors shall mean,
38collectively, Apple Computer, Inc., AT&T Corp., International
39Business Machines Corporation and Siemens Rolm Communications Inc.
40The term Licensor shall mean any of the Licensors.
41
42Subject to acceptance of the following conditions, permission is hereby
43granted by Licensors without the need for written agreement and without
44license or royalty fees, to use, copy, modify and distribute this
45software for any purpose.
46
47The above copyright notice and the following four paragraphs must be
48reproduced in all copies of this software and any software including
49this software.
50
51THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
52ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
53MODIFICATIONS.
54
55IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
56INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
57OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
58DAMAGE.
59
60EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
61INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
62IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
63PURPOSE.
64
65The software is provided with RESTRICTED RIGHTS. Use, duplication, or
66disclosure by the government are subject to restrictions set forth in
67DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
68
69***************************************************************************/
70
71/*
72 * src: vcc.c
73 * doc: Parser for vCard and vCalendar. Note that this code is
74 * generated by a yacc parser generator. Generally it should not
75 * be edited by hand. The real source is vcc.y. The #line directives
76 * can be commented out here to make it easier to trace through
77 * in a debugger. However, if a bug is found it should
78 * be fixed in vcc.y and this file regenerated.
79 */
80
81
82/* debugging utilities */
83#if __DEBUG
84#define DBG_(x) printf x
85#else
86#define DBG_(x)
87#endif
88
89/**** External Functions ****/
90
91/* assign local name to parser variables and functions so that
92 we can use more than one yacc based parser.
93*/
94
95#define yyparse mime_parse
96#define yylex mime_lex
97#define yyerror mime_error
98#define yychar mime_char
99/* #define p_yyval p_mime_val */
100#undef yyval
101#define yyval mime_yyval
102/* #define p_yylval p_mime_lval */
103#undef yylval
104#define yylval mime_yylval
105#define yydebug mime_debug
106#define yynerrs mime_nerrs
107#define yyerrflag mime_errflag
108#define yyss mime_ss
109#define yyssp mime_ssp
110#define yyvs mime_vs
111#define yyvsp mime_vsp
112#define yylhs mime_lhs
113#define yylen mime_len
114#define yydefred mime_defred
115#define yydgoto mime_dgoto
116#define yysindex mime_sindex
117#define yyrindex mime_rindex
118#define yygindex mime_gindex
119#define yytable mime_table
120#define yycheck mime_check
121#define yyname mime_name
122#define yyrule mime_rule
123#undef YYPREFIX
124#define YYPREFIX "mime_"
125
126
127#ifndef _NO_LINE_FOLDING
128#define _SUPPORT_LINE_FOLDING 1
129#endif
130
131#include <string.h>
132#ifndef __FreeBSD__
133#include <malloc.h>
134#endif
135#include <stdio.h>
136#include <stdlib.h>
137#include <ctype.h>
138#include "vcc.h"
139
140/* The following is a hack that I hope will get things compiling
141 * on SunOS 4.1.x systems
142 */
143#ifndef SEEK_SET
144#define SEEK_SET 0 /* Seek from beginning of file. */
145#define SEEK_CUR 1 /* Seek from current position. */
146#define SEEK_END 2 /* Seek from end of file. */
147#endif
148
149/**** Types, Constants ****/
150
151 #define YYDEBUG 0/* 1 to compile in some debugging code */
152 #define MAXTOKEN 256/* maximum token (line) length */
153 #define YYSTACKSIZE 1000/* ~unref ? */
154 #define MAXLEVEL 10/* max # of nested objects parseable */
155 /* (includes outermost) */
156
157
158/**** Global Variables ****/
159int mime_lineNum, mime_numErrors; /* yyerror() can use these */
160static VObject* vObjList;
161static VObject *curProp;
162static VObject *curObj;
163static VObject* ObjStack[MAXLEVEL];
164static int ObjStackTop;
165
166
167/* A helpful utility for the rest of the app. */
168#if __CPLUSPLUS__
169extern "C" {
170#endif
171
172 /* static void Parse_Debug(const char *s);*/
173 static void yyerror(char *s);
174
175#if __CPLUSPLUS__
176 };
177#endif
178
179int yyparse();
180static int yylex();
181enum LexMode {
182 L_NORMAL,
183 L_VCARD,
184 L_VCAL,
185 L_VEVENT,
186 L_VTODO,
187 L_VALUES,
188 L_BASE64,
189 L_QUOTED_PRINTABLE
190 };
191
192/**** Private Forward Declarations ****/
193static int pushVObject(const char *prop);
194static VObject* popVObject();
195char* lexDataFromBase64();
196static void lexPopMode(int top);
197static int lexWithinMode(enum LexMode mode);
198static void lexPushMode(enum LexMode mode);
199static void enterProps(const char *s);
200static void enterAttr(const char *s1, const char *s2);
201/* static void enterValues(const char *value); */
202static void appendValue(const char *value);
203static void mime_error_(char *s);
204
205
206#line 181 "./vcc.y"
207typedef union {
208 char *str;
209 VObject *vobj;
210 } YYSTYPE;
211#include <stdio.h>
212
213#ifndef __cplusplus
214#ifndef __STDC__
215#define const
216#endif
217#endif
218
219
220
221 #define YYFINAL 62
222 #define YYFLAG -32768
223 #define YYNTBASE21
224
225#define YYTRANSLATE(x) ((unsigned)(x) <= 274 ? yytranslate[x] : 51)
226
227static const char yytranslate[] = { 0,
228 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
229 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
230 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
231 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
232 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
233 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
234 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
235 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
236 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
237 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
238 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
239 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
240 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
241 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
242 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
243 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
244 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
245 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
246 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
247 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
248 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
249 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
250 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
251 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
252 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
253 2, 2, 2, 2, 2, 1, 3, 4, 5, 6,
254 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
255 17, 18, 19, 20
256};
257
258#if YYDEBUG != 0
259static const short yyprhs[] = { 0,
260 0, 2, 3, 7, 9, 11, 13, 14, 19, 20,
261 24, 27, 29, 30, 36, 38, 39, 43, 45, 48,
262 50, 53, 55, 59, 61, 62, 67, 69, 71, 72,
263 73, 78, 79, 83, 86, 88, 90, 92, 94, 95,
264 100, 101, 105, 106, 111, 112
265};
266
267static const short yyrhs[] = { 22,
268 0, 0, 24, 23, 22, 0, 24, 0, 25, 0,
269 40, 0, 0, 11, 26, 28, 12, 0, 0, 11,
270 27, 12, 0, 29, 28, 0, 29, 0, 0, 31,
271 4, 30, 37, 9, 0, 1, 0, 0, 36, 32,
272 33, 0, 36, 0, 34, 33, 0, 34, 0, 6,
273 35, 0, 36, 0, 36, 3, 36, 0, 19, 0,
274 0, 39, 6, 38, 37, 0, 39, 0, 20, 0,
275 0, 0, 13, 41, 43, 14, 0, 0, 13, 42,
276 14, 0, 44, 43, 0, 44, 0, 45, 0, 48,
277 0, 28, 0, 0, 15, 46, 28, 16, 0, 0,
278 15, 47, 16, 0, 0, 17, 49, 28, 18, 0,
279 0, 17, 50, 18, 0
280};
281
282#endif
283
284#if YYDEBUG != 0
285static const short yyrline[] = { 0,
286 209, 212, 215, 215, 219, 220, 223, 229, 234, 240,
287 246, 247, 250, 254, 260, 263, 268, 268, 274, 275,
288 278, 281, 285, 292, 295, 296, 296, 300, 301, 305,
289 309, 311, 314, 317, 318, 321, 323, 324, 327, 334,
290 339, 345, 351, 358, 363, 369
291};
292#endif
293
294
295#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
296
297static const char * const yytname[] = { "$","error","$undefined.","EQ","COLON",
298"DOT","SEMICOLON","SPACE","HTAB","LINESEP","NEWLINE","BEGIN_VCARD","END_VCARD",
299"BEGIN_VCAL","END_VCAL","BEGIN_VEVENT","END_VEVENT","BEGIN_VTODO","END_VTODO",
300"ID","STRING","mime","vobjects","@1","vobject","vcard","@2","@3","items","item",
301"@4","prop","@5","attr_params","attr_param","attr","name","values","@6","value",
302"vcal","@7","@8","calitems","calitem","eventitem","@9","@10","todoitem","@11",
303"@12", NULL
304};
305#endif
306
307static const short yyr1[] = { 0,
308 21, 23, 22, 22, 24, 24, 26, 25, 27, 25,
309 28, 28, 30, 29, 29, 32, 31, 31, 33, 33,
310 34, 35, 35, 36, 38, 37, 37, 39, 39, 41,
311 40, 42, 40, 43, 43, 44, 44, 44, 46, 45,
312 47, 45, 49, 48, 50, 48
313};
314
315static const short yyr2[] = { 0,
316 1, 0, 3, 1, 1, 1, 0, 4, 0, 3,
317 2, 1, 0, 5, 1, 0, 3, 1, 2, 1,
318 2, 1, 3, 1, 0, 4, 1, 1, 0, 0,
319 4, 0, 3, 2, 1, 1, 1, 1, 0, 4,
320 0, 3, 0, 4, 0, 3
321};
322
323static const short yydefact[] = { 0,
324 7, 30, 1, 2, 5, 6, 0, 0, 0, 0,
325 0, 15, 24, 0, 0, 0, 16, 10, 39, 43,
326 38, 0, 0, 36, 37, 33, 3, 8, 11, 13,
327 0, 0, 0, 0, 0, 31, 34, 29, 0, 17,
328 20, 0, 42, 0, 46, 28, 0, 27, 21, 22,
329 19, 40, 44, 14, 25, 0, 29, 23, 26, 0,
330 0, 0
331};
332
333static const short yydefgoto[] = { 60,
334 3, 11, 4, 5, 7, 8, 21, 15, 38, 16,
335 31, 40, 41, 49, 17, 47, 57, 48, 6, 9,
336 10, 22, 23, 24, 32, 33, 25, 34, 35
337};
338
339static const short yypact[] = { -9,
340 -6, -5,-32768, 7,-32768,-32768, 2, -1, 19, 15,
341 -9,-32768,-32768, 1, 0, 26, 27,-32768, 16, 17,
342-32768, 23, 9,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
343 33, 2, 24, 2, 25,-32768,-32768, 13, 22,-32768,
344 33, 28,-32768, 29,-32768,-32768, 36, 40,-32768, 39,
345-32768,-32768,-32768,-32768,-32768, 22, 13,-32768,-32768, 48,
346 49,-32768
347};
348
349static const short yypgoto[] = {-32768,
350 41,-32768,-32768,-32768,-32768,-32768, -7,-32768,-32768,-32768,
351-32768, 10,-32768,-32768, -34, -4,-32768,-32768,-32768,-32768,
352-32768, 31,-32768,-32768,-32768,-32768,-32768,-32768,-32768
353};
354
355
356 #define YYLAST 54
357
358
359static const short yytable[] = { 14,
360 12, 1, 12, 2, 50, -9, -4, 29, -32, 12,
361 18, -12, 28, -12, -12, -12, -12, -12, 13, 12,
362 13, 58, -35, 19, 42, 20, 44, 13, 26, 30,
363 -18, -41, 46, 19, -45, 20, 36, 13, 39, 43,
364 13, 56, 45, 52, 54, 55, 53, 61, 62, 0,
365 51, 27, 59, 37
366};
367
368static const short yycheck[] = { 7,
369 1, 11, 1, 13, 39, 12, 0, 15, 14, 1,
370 12, 12, 12, 14, 15, 16, 17, 18, 19, 1,
371 19, 56, 14, 15, 32, 17, 34, 19, 14, 4,
372 4, 16, 20, 15, 18, 17, 14, 19, 6, 16,
373 19, 3, 18, 16, 9, 6, 18, 0, 0, -1,
374 41, 11, 57, 23
375};
376/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
377#line 3 "/usr/share/bison.simple"
378/* This file comes from bison-1.28. */
379
380/* Skeleton output parser for bison,
381 Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
382
383 This program is free software; you can redistribute it and/or modify
384 it under the terms of the GNU General Public License as published by
385 the Free Software Foundation; either version 2, or (at your option)
386 any later version.
387
388 This program is distributed in the hope that it will be useful,
389 but WITHOUT ANY WARRANTY; without even the implied warranty of
390 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
391 GNU General Public License for more details.
392
393 You should have received a copy of the GNU General Public License
394 along with this program; if not, write to the Free Software
395 Foundation, Inc., 59 Temple Place - Suite 330,
396 Boston, MA 02111-1307, USA. */
397
398/* As a special exception, when this file is copied by Bison into a
399 Bison output file, you may use that output file without restriction.
400 This special exception was added by the Free Software Foundation
401 in version 1.24 of Bison. */
402
403/* This is the parser code that is written into each bison parser
404 when the %semantic_parser declaration is not specified in the grammar.
405 It was written by Richard Stallman by simplifying the hairy parser
406 used when %semantic_parser is specified. */
407
408#ifndef YYSTACK_USE_ALLOCA
409#ifdef alloca
410#define YYSTACK_USE_ALLOCA
411#else /* alloca not defined */
412#ifdef __GNUC__
413#define YYSTACK_USE_ALLOCA
414#define alloca __builtin_alloca
415#else /* not GNU C. */
416#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
417#define YYSTACK_USE_ALLOCA
418#include <alloca.h>
419#else /* not sparc */
420/* We think this test detects Watcom and Microsoft C. */
421/* This used to test MSDOS, but that is a bad idea
422 since that symbol is in the user namespace. */
423#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
424#if 0 /* No need for malloc.h, which pollutes the namespace;
425 instead, just don't use alloca. */
426#include <malloc.h>
427#endif
428#else /* not MSDOS, or __TURBOC__ */
429#if defined(_AIX)
430/* I don't know what this was needed for, but it pollutes the namespace.
431 So I turned it off. rms, 2 May 1997. */
432/* #include <malloc.h> */
433 #pragma alloca
434#define YYSTACK_USE_ALLOCA
435#else /* not MSDOS, or __TURBOC__, or _AIX */
436#if 0
437#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
438 and on HPUX 10. Eventually we can turn this on. */
439#define YYSTACK_USE_ALLOCA
440#define alloca __builtin_alloca
441#endif /* __hpux */
442#endif
443#endif /* not _AIX */
444#endif /* not MSDOS, or __TURBOC__ */
445#endif /* not sparc */
446#endif /* not GNU C */
447#endif /* alloca not defined */
448#endif /* YYSTACK_USE_ALLOCA not defined */
449
450#ifdef YYSTACK_USE_ALLOCA
451#define YYSTACK_ALLOC alloca
452#else
453#define YYSTACK_ALLOC malloc
454#endif
455
456/* Note: there must be only one dollar sign in this file.
457 It is replaced by the list of actions, each action
458 as one case of the switch. */
459
460 #define yyerrok (yyerrstatus = 0)
461 #define yyclearin(yychar = YYEMPTY)
462 #define YYEMPTY -2
463 #define YYEOF 0
464 #define YYACCEPTgoto yyacceptlab
465 #define YYABORT goto yyabortlab
466 #define YYERROR goto yyerrlab1
467/* Like YYERROR except do call yyerror.
468 This remains here temporarily to ease the
469 transition to the new meaning of YYERROR, for GCC.
470 Once GCC version 2 has supplanted version 1, this can go. */
471 #define YYFAIL goto yyerrlab
472#define YYRECOVERING() (!!yyerrstatus)
473#define YYBACKUP(token, value) \
474 do \
475 if (yychar == YYEMPTY && yylen == 1) \
476 { yychar = (token), yylval = (value); \
477 yychar1 = YYTRANSLATE (yychar); \
478 YYPOPSTACK; \
479 goto yybackup; \
480 } \
481 else \
482 { yyerror ("syntax error: cannot back up"); YYERROR; }\
483while (0)
484
485 #define YYTERROR1
486 #define YYERRCODE256
487
488#ifndef YYPURE
489 #define YYLEX yylex()
490#endif
491
492#ifdef YYPURE
493#ifdef YYLSP_NEEDED
494#ifdef YYLEX_PARAM
495 #define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)
496#else
497 #define YYLEX yylex(&yylval, &yylloc)
498#endif
499#else /* not YYLSP_NEEDED */
500#ifdef YYLEX_PARAM
501 #define YYLEX yylex(&yylval, YYLEX_PARAM)
502#else
503 #define YYLEX yylex(&yylval)
504#endif
505#endif /* not YYLSP_NEEDED */
506#endif
507
508/* If nonreentrant, generate the variables here */
509
510#ifndef YYPURE
511
512 int yychar; /* the lookahead symbol */
513 YYSTYPE yylval; /* the semantic value of the */
514 /* lookahead symbol */
515
516#ifdef YYLSP_NEEDED
517 YYLTYPE yylloc; /* location data for the lookahead*/
518 /* symbol */
519#endif
520
521 int yynerrs; /* number of parse errors so far */
522#endif /* not YYPURE */
523
524#if YYDEBUG != 0
525 int yydebug; /* nonzero means print parse trace*/
526/* Since this is uninitialized, it does not stop multiple parsers
527 from coexisting. */
528#endif
529
530 /* YYINITDEPTH indicates the initial size of the parser's stacks*/
531
532 #ifndefYYINITDEPTH
533#define YYINITDEPTH 200
534#endif
535
536/* YYMAXDEPTH is the maximum size the stacks can grow to
537 (effective only if the built-in stack extension method is used). */
538
539#if YYMAXDEPTH == 0
540#undef YYMAXDEPTH
541#endif
542
543#ifndef YYMAXDEPTH
544#define YYMAXDEPTH 10000
545#endif
546
547/* Define __yy_memcpy. Note that the size argument
548 should be passed with type unsigned int, because that is what the non-GCC
549 definitions require. With GCC, __builtin_memcpy takes an arg
550 of type size_t, but it can handle unsigned int. */
551
552 #if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
553 #define __yy_memcpy(TO,FROM,COUNT)__builtin_memcpy(TO,FROM,COUNT)
554 #else /* not GNU C or C++ */
555#ifndef __cplusplus
556
557/* This is the most reliable way to avoid incompatibilities
558 in available built-in functions on various systems. */
559static void
560__yy_memcpy (to, from, count)
561 char *to;
562 char *from;
563 unsigned int count;
564{
565 register char *f = from;
566 register char *t = to;
567 register int i = count;
568
569 while (i-- > 0)
570 *t++ = *f++;
571}
572
573#else /* __cplusplus */
574
575/* This is the most reliable way to avoid incompatibilities
576 in available built-in functions on various systems. */
577static void
578__yy_memcpy (char *to, char *from, unsigned int count)
579{
580 register char *t = to;
581 register char *f = from;
582 register int i = count;
583
584 while (i-- > 0)
585 *t++ = *f++;
586}
587
588#endif
589#endif
590
591#line 217 "/usr/share/bison.simple"
592
593/* The user can define YYPARSE_PARAM as the name of an argument to be passed
594 into yyparse. The argument should have type void *.
595 It should actually point to an object.
596 Grammar actions can access the variable by casting it
597 to the proper pointer type. */
598
599#ifdef YYPARSE_PARAM
600#ifdef __cplusplus
601#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
602#define YYPARSE_PARAM_DECL
603#else /* not __cplusplus */
604#define YYPARSE_PARAM_ARG YYPARSE_PARAM
605#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
606#endif /* not __cplusplus */
607#else /* not YYPARSE_PARAM */
608#define YYPARSE_PARAM_ARG
609#define YYPARSE_PARAM_DECL
610#endif /* not YYPARSE_PARAM */
611
612/* Prevent warning if -Wstrict-prototypes. */
613#if defined (__GNUC__) && ! defined (__cplusplus)
614#ifdef YYPARSE_PARAM
615int yyparse (void *);
616#else
617int yyparse (void);
618#endif
619#endif
620
621int
622yyparse(YYPARSE_PARAM_ARG)
623 YYPARSE_PARAM_DECL
624{
625 register int yystate;
626 register int yyn;
627 register short *yyssp;
628 register YYSTYPE *yyvsp;
629 int yyerrstatus;/* number of tokens to shift before error messages enabled */
630 int yychar1 = 0; /* lookahead token as an internal (translated) token number */
631
632 short yyssa[YYINITDEPTH]; /* the state stack */
633 YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
634
635 short *yyss = yyssa; /* refer to the stacks thru separate pointers */
636 YYSTYPE *yyvs = yyvsa;/* to allow yyoverflow to reallocate them elsewhere */
637
638#ifdef YYLSP_NEEDED
639 YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
640 YYLTYPE *yyls = yylsa;
641 YYLTYPE *yylsp;
642
643#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
644#else
645#define YYPOPSTACK (yyvsp--, yyssp--)
646#endif
647
648 int yystacksize = YYINITDEPTH;
649 int yyfree_stacks = 0;
650
651#ifdef YYPURE
652 int yychar;
653 YYSTYPE yylval;
654 int yynerrs;
655#ifdef YYLSP_NEEDED
656 YYLTYPE yylloc;
657#endif
658#endif
659
660 YYSTYPE yyval; /* the variable used to return */
661 /* semantic values from the action*/
662 /* routines */
663
664 int yylen;
665
666#if YYDEBUG != 0
667 if (yydebug)
668 fprintf(stderr, "Starting parse\n");
669#endif
670
671 yystate = 0;
672 yyerrstatus = 0;
673 yynerrs = 0;
674 yychar = YYEMPTY; /* Cause a token to be read. */
675
676 /* Initialize stack pointers.
677 Waste one element of value and location stack
678 so that they stay on the same level as the state stack.
679 The wasted elements are never initialized. */
680
681 yyssp = yyss - 1;
682 yyvsp = yyvs;
683#ifdef YYLSP_NEEDED
684 yylsp = yyls;
685#endif
686
687/* Push a new state, which is found in yystate . */
688/* In all cases, when you get here, the value and location stacks
689 have just been pushed. so pushing a state here evens the stacks. */
690yynewstate:
691
692 *++yyssp = yystate;
693
694 if (yyssp >= yyss + yystacksize - 1)
695 {
696 /* Give user a chance to reallocate the stack */
697 /* Use copies of these so that the &'s don't force the real ones into memory. */
698 YYSTYPE *yyvs1 = yyvs;
699 short *yyss1 = yyss;
700#ifdef YYLSP_NEEDED
701 YYLTYPE *yyls1 = yyls;
702#endif
703
704 /* Get the current used size of the three stacks, in elements. */
705 int size = yyssp - yyss + 1;
706
707#ifdef yyoverflow
708 /* Each stack pointer address is followed by the size of
709 the data in use in that stack, in bytes. */
710#ifdef YYLSP_NEEDED
711 /* This used to be a conditional around just the two extra args,
712 but that might be undefined if yyoverflow is a macro. */
713 yyoverflow("parser stack overflow",
714 &yyss1, size * sizeof (*yyssp),
715 &yyvs1, size * sizeof (*yyvsp),
716 &yyls1, size * sizeof (*yylsp),
717 &yystacksize);
718#else
719 yyoverflow("parser stack overflow",
720 &yyss1, size * sizeof (*yyssp),
721 &yyvs1, size * sizeof (*yyvsp),
722 &yystacksize);
723#endif
724
725 yyss = yyss1; yyvs = yyvs1;
726#ifdef YYLSP_NEEDED
727 yyls = yyls1;
728#endif
729#else /* no yyoverflow */
730 /* Extend the stack our own way. */
731 if (yystacksize >= YYMAXDEPTH)
732 {
733 yyerror("parser stack overflow");
734 if (yyfree_stacks)
735 {
736 free (yyss);
737 free (yyvs);
738#ifdef YYLSP_NEEDED
739 free (yyls);
740#endif
741 }
742 return 2;
743 }
744 yystacksize *= 2;
745 if (yystacksize > YYMAXDEPTH)
746 yystacksize = YYMAXDEPTH;
747#ifndef YYSTACK_USE_ALLOCA
748 yyfree_stacks = 1;
749#endif
750 yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
751 __yy_memcpy ((char *)yyss, (char *)yyss1,
752 size * (unsigned int) sizeof (*yyssp));
753 yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
754 __yy_memcpy ((char *)yyvs, (char *)yyvs1,
755 size * (unsigned int) sizeof (*yyvsp));
756#ifdef YYLSP_NEEDED
757 yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
758 __yy_memcpy ((char *)yyls, (char *)yyls1,
759 size * (unsigned int) sizeof (*yylsp));
760#endif
761#endif /* no yyoverflow */
762
763 yyssp = yyss + size - 1;
764 yyvsp = yyvs + size - 1;
765#ifdef YYLSP_NEEDED
766 yylsp = yyls + size - 1;
767#endif
768
769#if YYDEBUG != 0
770 if (yydebug)
771 fprintf(stderr, "Stack size increased to %d\n", yystacksize);
772#endif
773
774 if (yyssp >= yyss + yystacksize - 1)
775 YYABORT;
776 }
777
778#if YYDEBUG != 0
779 if (yydebug)
780 fprintf(stderr, "Entering state %d\n", yystate);
781#endif
782
783 goto yybackup;
784 yybackup:
785
786/* Do appropriate processing given the current state. */
787/* Read a lookahead token if we need one and don't already have one. */
788/* yyresume: */
789
790 /* First try to decide what to do without reference to lookahead token. */
791
792 yyn = yypact[yystate];
793 if (yyn == YYFLAG)
794 goto yydefault;
795
796 /* Not known => get a lookahead token if don't already have one. */
797
798 /* yychar is either YYEMPTY or YYEOF
799 or a valid token in external form. */
800
801 if (yychar == YYEMPTY)
802 {
803#if YYDEBUG != 0
804 if (yydebug)
805 fprintf(stderr, "Reading a token: ");
806#endif
807 yychar = YYLEX;
808 }
809
810 /* Convert token to internal form (in yychar1) for indexing tables with */
811
812 if (yychar <= 0) /* This means end of input. */
813 {
814 yychar1 = 0;
815 yychar = YYEOF; /* Don't call YYLEX any more */
816
817#if YYDEBUG != 0
818 if (yydebug)
819 fprintf(stderr, "Now at end of input.\n");
820#endif
821 }
822 else
823 {
824 yychar1 = YYTRANSLATE(yychar);
825
826#if YYDEBUG != 0
827 if (yydebug)
828 {
829 fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
830 /* Give the individual parser a way to print the precise meaning
831 of a token, for further debugging info. */
832#ifdef YYPRINT
833 YYPRINT (stderr, yychar, yylval);
834#endif
835 fprintf (stderr, ")\n");
836 }
837#endif
838 }
839
840 yyn += yychar1;
841 if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
842 goto yydefault;
843
844 yyn = yytable[yyn];
845
846 /* yyn is what to do for this token type in this state.
847 Negative => reduce, -yyn is rule number.
848 Positive => shift, yyn is new state.
849 New state is final state => don't bother to shift,
850 just return success.
851 0, or most negative number => error. */
852
853 if (yyn < 0)
854 {
855 if (yyn == YYFLAG)
856 goto yyerrlab;
857 yyn = -yyn;
858 goto yyreduce;
859 }
860 else if (yyn == 0)
861 goto yyerrlab;
862
863 if (yyn == YYFINAL)
864 YYACCEPT;
865
866 /* Shift the lookahead token. */
867
868#if YYDEBUG != 0
869 if (yydebug)
870 fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
871#endif
872
873 /* Discard the token being shifted unless it is eof. */
874 if (yychar != YYEOF)
875 yychar = YYEMPTY;
876
877 *++yyvsp = yylval;
878#ifdef YYLSP_NEEDED
879 *++yylsp = yylloc;
880#endif
881
882 /* count tokens shifted since error; after three, turn off error status. */
883 if (yyerrstatus) yyerrstatus--;
884
885 yystate = yyn;
886 goto yynewstate;
887
888/* Do the default action for the current state. */
889yydefault:
890
891 yyn = yydefact[yystate];
892 if (yyn == 0)
893 goto yyerrlab;
894
895/* Do a reduction. yyn is the number of a rule to reduce with. */
896yyreduce:
897 yylen = yyr2[yyn];
898 if (yylen > 0)
899 yyval = yyvsp[1-yylen]; /* implement default value of the action */
900
901#if YYDEBUG != 0
902 if (yydebug)
903 {
904 int i;
905
906 fprintf (stderr, "Reducing via rule %d (line %d), ",
907 yyn, yyrline[yyn]);
908
909 /* Print the symbols being reduced, and their result. */
910 for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
911 fprintf (stderr, "%s ", yytname[yyrhs[i]]);
912 fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
913 }
914#endif
915
916
917 switch (yyn) {
918
919case 2:
920#line 213 "./vcc.y"
921{ addList(&vObjList, yyvsp[0].vobj); curObj = 0; ;
922 break;}
923case 4:
924#line 216 "./vcc.y"
925{ addList(&vObjList, yyvsp[0].vobj); curObj = 0; ;
926 break;}
927case 7:
928#line 225 "./vcc.y"
929{
930 lexPushMode(L_VCARD);
931 if (!pushVObject(VCCardProp)) YYERROR;
932 ;
933 break;}
934case 8:
935#line 230 "./vcc.y"
936{
937 lexPopMode(0);
938 yyval.vobj = popVObject();
939 ;
940 break;}
941case 9:
942#line 235 "./vcc.y"
943{
944 lexPushMode(L_VCARD);
945 if (!pushVObject(VCCardProp)) YYERROR;
946 ;
947 break;}
948case 10:
949#line 240 "./vcc.y"
950{
951 lexPopMode(0);
952 yyval.vobj = popVObject();
953 ;
954 break;}
955case 13:
956#line 251 "./vcc.y"
957{
958 lexPushMode(L_VALUES);
959 ;
960 break;}
961case 14:
962#line 255 "./vcc.y"
963{
964 if (lexWithinMode(L_BASE64) || lexWithinMode(L_QUOTED_PRINTABLE))
965 lexPopMode(0);
966 lexPopMode(0);
967 ;
968 break;}
969case 16:
970#line 264 "./vcc.y"
971{
972 enterProps(yyvsp[0].str);
973 ;
974 break;}
975case 18:
976#line 269 "./vcc.y"
977{
978 enterProps(yyvsp[0].str);
979 ;
980 break;}
981case 22:
982#line 282 "./vcc.y"
983{
984 enterAttr(yyvsp[0].str,0);
985 ;
986 break;}
987case 23:
988#line 286 "./vcc.y"
989{
990 enterAttr(yyvsp[-2].str,yyvsp[0].str);
991
992 ;
993 break;}
994case 25:
995#line 295 "./vcc.y"
996{ appendValue(yyvsp[-1].str); ;
997 break;}
998case 27:
999#line 297 "./vcc.y"
1000{ appendValue(yyvsp[0].str); ;
1001 break;}
1002case 29:
1003#line 302 "./vcc.y"
1004{ yyval.str = 0; ;
1005 break;}
1006case 30:
1007#line 307 "./vcc.y"
1008{ if (!pushVObject(VCCalProp)) YYERROR; ;
1009 break;}
1010case 31:
1011#line 310 "./vcc.y"
1012{ yyval.vobj = popVObject(); ;
1013 break;}
1014case 32:
1015#line 312 "./vcc.y"
1016{ if (!pushVObject(VCCalProp)) YYERROR; ;
1017 break;}
1018case 33:
1019#line 314 "./vcc.y"
1020{ yyval.vobj = popVObject(); ;
1021 break;}
1022case 39:
1023#line 329 "./vcc.y"
1024{
1025 lexPushMode(L_VEVENT);
1026 if (!pushVObject(VCEventProp)) YYERROR;
1027 ;
1028 break;}
1029case 40:
1030#line 335 "./vcc.y"
1031{
1032 lexPopMode(0);
1033 popVObject();
1034 ;
1035 break;}
1036case 41:
1037#line 340 "./vcc.y"
1038{
1039 lexPushMode(L_VEVENT);
1040 if (!pushVObject(VCEventProp)) YYERROR;
1041 ;
1042 break;}
1043case 42:
1044#line 345 "./vcc.y"
1045{
1046 lexPopMode(0);
1047 popVObject();
1048 ;
1049 break;}
1050case 43:
1051#line 353 "./vcc.y"
1052{
1053 lexPushMode(L_VTODO);
1054 if (!pushVObject(VCTodoProp)) YYERROR;
1055 ;
1056 break;}
1057case 44:
1058#line 359 "./vcc.y"
1059{
1060 lexPopMode(0);
1061 popVObject();
1062 ;
1063 break;}
1064case 45:
1065#line 364 "./vcc.y"
1066{
1067 lexPushMode(L_VTODO);
1068 if (!pushVObject(VCTodoProp)) YYERROR;
1069 ;
1070 break;}
1071case 46:
1072#line 369 "./vcc.y"
1073{
1074 lexPopMode(0);
1075 popVObject();
1076 ;
1077 break;}
1078}
1079 /* the action file gets copied in in place of this dollarsign */
1080#line 543 "/usr/share/bison.simple"
1081
1082 yyvsp -= yylen;
1083 yyssp -= yylen;
1084#ifdef YYLSP_NEEDED
1085 yylsp -= yylen;
1086#endif
1087
1088#if YYDEBUG != 0
1089 if (yydebug)
1090 {
1091 short *ssp1 = yyss - 1;
1092 fprintf (stderr, "state stack now");
1093 while (ssp1 != yyssp)
1094 fprintf (stderr, " %d", *++ssp1);
1095 fprintf (stderr, "\n");
1096 }
1097#endif
1098
1099 *++yyvsp = yyval;
1100
1101#ifdef YYLSP_NEEDED
1102 yylsp++;
1103 if (yylen == 0)
1104 {
1105 yylsp->first_line = yylloc.first_line;
1106 yylsp->first_column = yylloc.first_column;
1107 yylsp->last_line = (yylsp-1)->last_line;
1108 yylsp->last_column = (yylsp-1)->last_column;
1109 yylsp->text = 0;
1110 }
1111 else
1112 {
1113 yylsp->last_line = (yylsp+yylen-1)->last_line;
1114 yylsp->last_column = (yylsp+yylen-1)->last_column;
1115 }
1116#endif
1117
1118 /* Now "shift" the result of the reduction.
1119 Determine what state that goes to,
1120 based on the state we popped back to
1121 and the rule number reduced by. */
1122
1123 yyn = yyr1[yyn];
1124
1125 yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
1126 if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
1127 yystate = yytable[yystate];
1128 else
1129 yystate = yydefgoto[yyn - YYNTBASE];
1130
1131 goto yynewstate;
1132
1133yyerrlab: /* here on detecting error */
1134
1135 if (! yyerrstatus)
1136 /* If not already recovering from an error, report this error. */
1137 {
1138 ++yynerrs;
1139
1140#ifdef YYERROR_VERBOSE
1141 yyn = yypact[yystate];
1142
1143 if (yyn > YYFLAG && yyn < YYLAST)
1144 {
1145 int size = 0;
1146 char *msg;
1147 int x, count;
1148
1149 count = 0;
1150 /* Start X at -yyn if nec to avoid negative indexes in yycheck. */
1151 for (x = (yyn < 0 ? -yyn : 0);
1152 x < (sizeof(yytname) / sizeof(char *)); x++)
1153 if (yycheck[x + yyn] == x)
1154 size += strlen(yytname[x]) + 15, count++;
1155 msg = (char *) malloc(size + 15);
1156 if (msg != 0)
1157 {
1158 strcpy(msg, "parse error");
1159
1160 if (count < 5)
1161 {
1162 count = 0;
1163 for (x = (yyn < 0 ? -yyn : 0);
1164 x < (sizeof(yytname) / sizeof(char *)); x++)
1165 if (yycheck[x + yyn] == x)
1166 {
1167 strcat(msg, count == 0 ? ", expecting `" : " or `");
1168 strcat(msg, yytname[x]);
1169 strcat(msg, "'");
1170 count++;
1171 }
1172 }
1173 yyerror(msg);
1174 free(msg);
1175 }
1176 else
1177 yyerror ("parse error; also virtual memory exceeded");
1178 }
1179 else
1180#endif /* YYERROR_VERBOSE */
1181 yyerror("parse error");
1182 }
1183
1184 goto yyerrlab1;
1185yyerrlab1: /* here on error raised explicitly by an action */
1186
1187 if (yyerrstatus == 3)
1188 {
1189 /* if just tried and failed to reuse lookahead token after an error, discard it. */
1190
1191 /* return failure if at end of input */
1192 if (yychar == YYEOF)
1193 YYABORT;
1194
1195#if YYDEBUG != 0
1196 if (yydebug)
1197 fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
1198#endif
1199
1200 yychar = YYEMPTY;
1201 }
1202
1203 /* Else will try to reuse lookahead token
1204 after shifting the error token. */
1205
1206 yyerrstatus = 3; /* Each real token shifted decrements this */
1207
1208 goto yyerrhandle;
1209
1210yyerrdefault: /* current state does not do anything special for the error token. */
1211
1212#if 0
1213 /* This is wrong; only states that explicitly want error tokens
1214 should shift them. */
1215 yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
1216 if (yyn) goto yydefault;
1217#endif
1218
1219yyerrpop: /* pop the current state because it cannot handle the error token */
1220
1221 if (yyssp == yyss) YYABORT;
1222 yyvsp--;
1223 yystate = *--yyssp;
1224#ifdef YYLSP_NEEDED
1225 yylsp--;
1226#endif
1227
1228#if YYDEBUG != 0
1229 if (yydebug)
1230 {
1231 short *ssp1 = yyss - 1;
1232 fprintf (stderr, "Error: state stack now");
1233 while (ssp1 != yyssp)
1234 fprintf (stderr, " %d", *++ssp1);
1235 fprintf (stderr, "\n");
1236 }
1237#endif
1238
1239yyerrhandle:
1240
1241 yyn = yypact[yystate];
1242 if (yyn == YYFLAG)
1243 goto yyerrdefault;
1244
1245 yyn += YYTERROR;
1246 if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
1247 goto yyerrdefault;
1248
1249 yyn = yytable[yyn];
1250 if (yyn < 0)
1251 {
1252 if (yyn == YYFLAG)
1253 goto yyerrpop;
1254 yyn = -yyn;
1255 goto yyreduce;
1256 }
1257 else if (yyn == 0)
1258 goto yyerrpop;
1259
1260 if (yyn == YYFINAL)
1261 YYACCEPT;
1262
1263#if YYDEBUG != 0
1264 if (yydebug)
1265 fprintf(stderr, "Shifting error token, ");
1266#endif
1267
1268 *++yyvsp = yylval;
1269#ifdef YYLSP_NEEDED
1270 *++yylsp = yylloc;
1271#endif
1272
1273 yystate = yyn;
1274 goto yynewstate;
1275
1276 yyacceptlab:
1277 /* YYACCEPT comes here. */
1278 if (yyfree_stacks)
1279 {
1280 free (yyss);
1281 free (yyvs);
1282#ifdef YYLSP_NEEDED
1283 free (yyls);
1284#endif
1285 }
1286 return 0;
1287
1288 yyabortlab:
1289 /* YYABORT comes here. */
1290 if (yyfree_stacks)
1291 {
1292 free (yyss);
1293 free (yyvs);
1294#ifdef YYLSP_NEEDED
1295 free (yyls);
1296#endif
1297 }
1298 return 1;
1299}
1300#line 375 "./vcc.y"
1301
1302/****************************************************************************/
1303static int pushVObject(const char *prop)
1304 {
1305 VObject *newObj;
1306 if (ObjStackTop == MAXLEVEL)
1307 return FALSE;
1308
1309 ObjStack[++ObjStackTop] = curObj;
1310
1311 if (curObj) {
1312 newObj = addProp(curObj,prop);
1313 curObj = newObj;
1314 }
1315 else
1316 curObj = newVObject(prop);
1317
1318 return TRUE;
1319 }
1320
1321
1322/****************************************************************************/
1323/* This pops the recently built vCard off the stack and returns it. */
1324static VObject* popVObject()
1325 {
1326 VObject *oldObj;
1327 if (ObjStackTop < 0) {
1328 yyerror("pop on empty Object Stack\n");
1329 return 0;
1330 }
1331 oldObj = curObj;
1332 curObj = ObjStack[ObjStackTop--];
1333
1334 return oldObj;
1335 }
1336
1337
1338/* static void enterValues(const char *value) */
1339/* { */
1340/* if (fieldedProp && *fieldedProp) { */
1341 /* if (value) { */
1342 /* addPropValue(curProp,*fieldedProp,value); */
1343 /* } */
1344 /* else this field is empty, advance to next field */
1345 /* fieldedProp++; */
1346 /* } */
1347/* else { */
1348 /* if (value) { */
1349 /* setVObjectUStringZValue_(curProp,fakeUnicode(value,0)); */
1350 /* } */
1351 /* } */
1352/* deleteStr(value); */
1353/* } */
1354
1355static void appendValue(const char *value)
1356{
1357 char *p1, *p2;
1358 wchar_t *p3;
1359 int i;
1360
1361 if (fieldedProp && *fieldedProp) {
1362 if (value) {
1363 addPropValue(curProp, *fieldedProp, value);
1364 }
1365 /* else this field is empty, advance to next field */
1366 fieldedProp++;
1367 } else {
1368 if (value) {
1369 if (vObjectUStringZValue(curProp)) {
1370 p1 = fakeCString(vObjectUStringZValue(curProp));
1371 p2 = malloc(sizeof(char *) * (strlen(p1)+strlen(value)+1));
1372 strcpy(p2, p1);
1373 deleteStr(p1);
1374
1375 i = strlen(p2);
1376 p2[i] = ',';
1377 p2[i+1] = '\0';
1378 p2 = strcat(p2, value);
1379 p3 = (wchar_t *) vObjectUStringZValue(curProp);
1380 free(p3);
1381 setVObjectUStringZValue_(curProp,fakeUnicode(p2,0));
1382 deleteStr(p2);
1383 } else {
1384 setVObjectUStringZValue_(curProp,fakeUnicode(value,0));
1385 }
1386 }
1387 }
1388 deleteStr(value);
1389}
1390
1391
1392static void enterProps(const char *s)
1393 {
1394 curProp = addGroup(curObj,s);
1395 deleteStr(s);
1396 }
1397
1398static void enterAttr(const char *s1, const char *s2)
1399 {
1400 const char *p1=0L, *p2=0L;
1401 p1 = lookupProp_(s1);
1402 if (s2) {
1403 VObject *a;
1404 p2 = lookupProp_(s2);
1405 a = addProp(curProp,p1);
1406 setVObjectStringZValue(a,p2);
1407 }
1408 else
1409 addProp(curProp,p1);
1410 if (strcasecmp(p1,VCBase64Prop) == 0 || (s2 && strcasecmp(p2,VCBase64Prop)==0))
1411 lexPushMode(L_BASE64);
1412 else if (strcasecmp(p1,VCQuotedPrintableProp) == 0
1413 || (s2 && strcasecmp(p2,VCQuotedPrintableProp)==0))
1414 lexPushMode(L_QUOTED_PRINTABLE);
1415 deleteStr(s1); deleteStr(s2);
1416 }
1417
1418
1419#define MAX_LEX_LOOKAHEAD_0 32
1420#define MAX_LEX_LOOKAHEAD 64
1421#define MAX_LEX_MODE_STACK_SIZE 10
1422#define LEXMODE() (lexBuf.lexModeStack[lexBuf.lexModeStackTop])
1423
1424struct LexBuf {
1425 /* input */
1426 FILE *inputFile;
1427 char *inputString;
1428 unsigned long curPos;
1429 unsigned long inputLen;
1430 /* lookahead buffer */
1431 /* -- lookahead buffer is short instead of char so that EOF
1432 / can be represented correctly.
1433 */
1434 unsigned long len;
1435 short buf[MAX_LEX_LOOKAHEAD];
1436 unsigned long getPtr;
1437 /* context stack */
1438 unsigned long lexModeStackTop;
1439 enum LexMode lexModeStack[MAX_LEX_MODE_STACK_SIZE];
1440 /* token buffer */
1441 unsigned long maxToken;
1442 char *strs;
1443 unsigned long strsLen;
1444 } lexBuf;
1445
1446static void lexPushMode(enum LexMode mode)
1447 {
1448 if (lexBuf.lexModeStackTop == (MAX_LEX_MODE_STACK_SIZE-1))
1449 yyerror("lexical context stack overflow");
1450 else {
1451 lexBuf.lexModeStack[++lexBuf.lexModeStackTop] = mode;
1452 }
1453 }
1454
1455static void lexPopMode(int top)
1456 {
1457 /* special case of pop for ease of error recovery -- this
1458 version will never underflow */
1459 if (top)
1460 lexBuf.lexModeStackTop = 0;
1461 else
1462 if (lexBuf.lexModeStackTop > 0) lexBuf.lexModeStackTop--;
1463 }
1464
1465static int lexWithinMode(enum LexMode mode) {
1466 unsigned long i;
1467 for (i=0;i<lexBuf.lexModeStackTop;i++)
1468 if (mode == lexBuf.lexModeStack[i]) return 1;
1469 return 0;
1470 }
1471
1472static int lexGetc_()
1473 {
1474 /* get next char from input, no buffering. */
1475 if (lexBuf.curPos == lexBuf.inputLen)
1476 return EOF;
1477 else if (lexBuf.inputString)
1478 return *(lexBuf.inputString + lexBuf.curPos++);
1479 else {
1480 if (!feof(lexBuf.inputFile))
1481 return fgetc(lexBuf.inputFile);
1482 else
1483 return EOF;
1484 }
1485 }
1486
1487static int lexGeta()
1488 {
1489 ++lexBuf.len;
1490 return (lexBuf.buf[lexBuf.getPtr] = lexGetc_());
1491 }
1492
1493static int lexGeta_(int i)
1494 {
1495 ++lexBuf.len;
1496 return (lexBuf.buf[(lexBuf.getPtr+i)%MAX_LEX_LOOKAHEAD] = lexGetc_());
1497 }
1498
1499static void lexSkipLookahead() {
1500 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) {
1501 /* don't skip EOF. */
1502 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD;
1503 lexBuf.len--;
1504 }
1505 }
1506
1507static int lexLookahead() {
1508 int c = (lexBuf.len)?
1509 lexBuf.buf[lexBuf.getPtr]:
1510 lexGeta();
1511 /* do the \r\n -> \n or \r -> \n translation here */
1512 if (c == '\r') {
1513 int a = (lexBuf.len>1)?
1514 lexBuf.buf[(lexBuf.getPtr+1)%MAX_LEX_LOOKAHEAD]:
1515 lexGeta_(1);
1516 if (a == '\n') {
1517 lexSkipLookahead();
1518 }
1519 lexBuf.buf[lexBuf.getPtr] = c = '\n';
1520 }
1521 else if (c == '\n') {
1522 int a;
1523 if (lexBuf.len > 1)
1524 a = lexBuf.buf[lexBuf.getPtr];
1525 else
1526 a = lexGeta_(1);
1527 if (a == '\r') {
1528 lexSkipLookahead();
1529 }
1530 lexBuf.buf[lexBuf.getPtr] = '\n';
1531 }
1532 return c;
1533 }
1534
1535static int lexGetc() {
1536 int c = lexLookahead();
1537 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) {
1538 /* EOF will remain in lookahead buffer */
1539 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD;
1540 lexBuf.len--;
1541 }
1542 return c;
1543 }
1544
1545static void lexSkipLookaheadWord() {
1546 if (lexBuf.strsLen <= lexBuf.len) {
1547 lexBuf.len -= lexBuf.strsLen;
1548 lexBuf.getPtr = (lexBuf.getPtr + lexBuf.strsLen) % MAX_LEX_LOOKAHEAD;
1549 }
1550 }
1551
1552static void lexClearToken()
1553 {
1554 lexBuf.strsLen = 0;
1555 }
1556
1557static void lexAppendc(int c)
1558 {
1559 /* not sure if I am doing this right to fix purify report -- PGB */
1560 lexBuf.strs = (char *) realloc(lexBuf.strs, (size_t) lexBuf.strsLen + 1);
1561 lexBuf.strs[lexBuf.strsLen] = c;
1562 /* append up to zero termination */
1563 if (c == 0) return;
1564 lexBuf.strsLen++;
1565 if (lexBuf.strsLen > lexBuf.maxToken) {
1566 /* double the token string size */
1567 lexBuf.maxToken <<= 1;
1568 lexBuf.strs = (char*) realloc(lexBuf.strs,(size_t)lexBuf.maxToken);
1569 }
1570 }
1571
1572static char* lexStr() {
1573 return dupStr(lexBuf.strs,(size_t)lexBuf.strsLen+1);
1574 }
1575
1576static void lexSkipWhite() {
1577 int c = lexLookahead();
1578 while (c == ' ' || c == '\t') {
1579 lexSkipLookahead();
1580 c = lexLookahead();
1581 }
1582 }
1583
1584static char* lexGetWord() {
1585 int c;
1586 lexSkipWhite();
1587 lexClearToken();
1588 c = lexLookahead();
1589 /* some "words" have a space in them, like "NEEDS ACTION".
1590 this may be an oversight of the spec, but it is true nevertheless.
1591 while (c != EOF && !strchr("\t\n ;:=",c)) { */
1592 while (c != EOF && !strchr("\n;:=",c)) {
1593 lexAppendc(c);
1594 lexSkipLookahead();
1595 c = lexLookahead();
1596 }
1597 lexAppendc(0);
1598 return lexStr();
1599 }
1600
1601void lexPushLookahead(char *s, int len) {
1602 int putptr;
1603 if (len == 0) len = strlen(s);
1604 putptr = (int)lexBuf.getPtr - len;
1605 /* this function assumes that length of word to push back
1606 / is not greater than MAX_LEX_LOOKAHEAD.
1607 */
1608 if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD;
1609 lexBuf.getPtr = putptr;
1610 while (*s) {
1611 lexBuf.buf[putptr] = *s++;
1612 putptr = (putptr + 1) % MAX_LEX_LOOKAHEAD;
1613 }
1614 lexBuf.len += len;
1615 }
1616
1617static void lexPushLookaheadc(int c) {
1618 int putptr;
1619 /* can't putback EOF, because it never leaves lookahead buffer */
1620 if (c == EOF) return;
1621 putptr = (int)lexBuf.getPtr - 1;
1622 if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD;
1623 lexBuf.getPtr = putptr;
1624 lexBuf.buf[putptr] = c;
1625 lexBuf.len += 1;
1626 }
1627
1628static char* lexLookaheadWord() {
1629 /* this function can lookahead word with max size of MAX_LEX_LOOKAHEAD_0
1630 / and thing bigger than that will stop the lookahead and return 0;
1631 / leading white spaces are not recoverable.
1632 */
1633 int c;
1634 int len = 0;
1635 int curgetptr = 0;
1636 lexSkipWhite();
1637 lexClearToken();
1638 curgetptr = (int)lexBuf.getPtr;/* remember! */
1639 while (len < (MAX_LEX_LOOKAHEAD_0)) {
1640 c = lexGetc();
1641 len++;
1642 if (c == EOF || strchr("\t\n ;:=", c)) {
1643 lexAppendc(0);
1644 /* restore lookahead buf. */
1645 lexBuf.len += len;
1646 lexBuf.getPtr = curgetptr;
1647 return lexStr();
1648 }
1649 else
1650 lexAppendc(c);
1651 }
1652 lexBuf.len += len;/* char that has been moved to lookahead buffer */
1653 lexBuf.getPtr = curgetptr;
1654 return 0;
1655 }
1656
1657#ifdef _SUPPORT_LINE_FOLDING
1658static void handleMoreRFC822LineBreak(int c) {
1659 /* suport RFC 822 line break in cases like
1660 *ADR: foo;
1661 * morefoo;
1662 * more foo;
1663 */
1664 if (c == ';') {
1665 int a;
1666 lexSkipLookahead();
1667 /* skip white spaces */
1668 a = lexLookahead();
1669 while (a == ' ' || a == '\t') {
1670 lexSkipLookahead();
1671 a = lexLookahead();
1672 }
1673 if (a == '\n') {
1674 lexSkipLookahead();
1675 a = lexLookahead();
1676 if (a == ' ' || a == '\t') {
1677 /* continuation, throw away all the \n and spaces read so
1678 * far
1679 */
1680 lexSkipWhite();
1681 lexPushLookaheadc(';');
1682 }
1683 else {
1684 lexPushLookaheadc('\n');
1685 lexPushLookaheadc(';');
1686 }
1687 }
1688 else {
1689 lexPushLookaheadc(';');
1690 }
1691 }
1692 }
1693
1694static char* lexGet1Value() {
1695 int c;
1696 lexSkipWhite();
1697 c = lexLookahead();
1698 lexClearToken();
1699 while (c != EOF && c != ';') {
1700 if (c == '\n') {
1701 int a;
1702 lexSkipLookahead();
1703 a = lexLookahead();
1704 if (a == ' ' || a == '\t') {
1705 lexAppendc(' ');
1706 lexSkipLookahead();
1707 }
1708 else {
1709 lexPushLookaheadc('\n');
1710 break;
1711 }
1712 }
1713 else {
1714 lexAppendc(c);
1715 lexSkipLookahead();
1716 }
1717 c = lexLookahead();
1718 }
1719 lexAppendc(0);
1720 handleMoreRFC822LineBreak(c);
1721 return c==EOF?0:lexStr();
1722 }
1723#endif
1724
1725char* lexGetStrUntil(char *termset) {
1726 int c = lexLookahead();
1727 lexClearToken();
1728 while (c != EOF && !strchr(termset,c)) {
1729 lexAppendc(c);
1730 lexSkipLookahead();
1731 c = lexLookahead();
1732 }
1733 lexAppendc(0);
1734 return c==EOF?0:lexStr();
1735 }
1736
1737static int match_begin_name(int end) {
1738 char *n = lexLookaheadWord();
1739 int token = ID;
1740 if (n) {
1741 if (!strcasecmp(n,"vcard")) token = end?END_VCARD:BEGIN_VCARD;
1742 else if (!strcasecmp(n,"vcalendar")) token = end?END_VCAL:BEGIN_VCAL;
1743 else if (!strcasecmp(n,"vevent")) token = end?END_VEVENT:BEGIN_VEVENT;
1744 else if (!strcasecmp(n,"vtodo")) token = end?END_VTODO:BEGIN_VTODO;
1745 deleteStr(n);
1746 return token;
1747 }
1748 return 0;
1749 }
1750
1751
1752void initLex(const char *inputstring, unsigned long inputlen, FILE *inputfile)
1753 {
1754 /* initialize lex mode stack */
1755 lexBuf.lexModeStack[lexBuf.lexModeStackTop=0] = L_NORMAL;
1756
1757 /* iniatialize lex buffer. */
1758 lexBuf.inputString = (char*) inputstring;
1759 lexBuf.inputLen = inputlen;
1760 lexBuf.curPos = 0;
1761 lexBuf.inputFile = inputfile;
1762
1763 lexBuf.len = 0;
1764 lexBuf.getPtr = 0;
1765
1766 lexBuf.maxToken = MAXTOKEN;
1767 lexBuf.strs = (char*)malloc(MAXTOKEN);
1768 lexBuf.strsLen = 0;
1769
1770 }
1771
1772static void finiLex() {
1773 free(lexBuf.strs);
1774 }
1775
1776
1777/****************************************************************************/
1778/* This parses and converts the base64 format for binary encoding into
1779 * a decoded buffer (allocated with new). See RFC 1521.
1780 */
1781static char * lexGetDataFromBase64()
1782 {
1783 unsigned long bytesLen = 0, bytesMax = 0;
1784 int quadIx = 0, pad = 0;
1785 unsigned long trip = 0;
1786 unsigned char b;
1787 int c;
1788 unsigned char *bytes = NULL;
1789 unsigned char *oldBytes = NULL;
1790
1791 DBG_(("db: lexGetDataFromBase64\n"));
1792 while (1) {
1793 c = lexGetc();
1794 if (c == '\n') {
1795 ++mime_lineNum;
1796 if (lexLookahead() == '\n') {
1797 /* a '\n' character by itself means end of data */
1798 break;
1799 }
1800 else continue; /* ignore '\n' */
1801 }
1802 else {
1803 if ((c >= 'A') && (c <= 'Z'))
1804 b = (unsigned char)(c - 'A');
1805 else if ((c >= 'a') && (c <= 'z'))
1806 b = (unsigned char)(c - 'a') + 26;
1807 else if ((c >= '0') && (c <= '9'))
1808 b = (unsigned char)(c - '0') + 52;
1809 else if (c == '+')
1810 b = 62;
1811 else if (c == '/')
1812 b = 63;
1813 else if (c == '=') {
1814 b = 0;
1815 pad++;
1816 } else if ((c == ' ') || (c == '\t')) {
1817 continue;
1818 } else { /* error condition */
1819 if (bytes) free(bytes);
1820 else if (oldBytes) free(oldBytes);
1821 /* error recovery: skip until 2 adjacent newlines. */
1822 DBG_(("db: invalid character 0x%x '%c'\n", c,c));
1823 if (c != EOF) {
1824 c = lexGetc();
1825 while (c != EOF) {
1826 if (c == '\n' && lexLookahead() == '\n') {
1827 ++mime_lineNum;
1828 break;
1829 }
1830 c = lexGetc();
1831 }
1832 }
1833 return NULL;
1834 }
1835 trip = (trip << 6) | b;
1836 if (++quadIx == 4) {
1837 unsigned char outBytes[3];
1838 int numOut;
1839 int i;
1840 for (i = 0; i < 3; i++) {
1841 outBytes[2-i] = (unsigned char)(trip & 0xFF);
1842 trip >>= 8;
1843 }
1844 numOut = 3 - pad;
1845 if (bytesLen + numOut > bytesMax) {
1846 if (!bytes) {
1847 bytesMax = 1024;
1848 bytes = (unsigned char*)malloc((size_t)bytesMax);
1849 }
1850 else {
1851 bytesMax <<= 2;
1852 oldBytes = bytes;
1853 bytes = (unsigned char*)realloc(bytes,(size_t)bytesMax);
1854 }
1855 if (bytes == 0) {
1856 mime_error("out of memory while processing BASE64 data\n");
1857 }
1858 }
1859 if (bytes) {
1860 memcpy(bytes + bytesLen, outBytes, numOut);
1861 bytesLen += numOut;
1862 }
1863 trip = 0;
1864 quadIx = 0;
1865 }
1866 }
1867 } /* while */
1868 DBG_(("db: bytesLen = %d\n", bytesLen));
1869 /* kludge: all this won't be necessary if we have tree form
1870 representation */
1871 if (bytes) {
1872 setValueWithSize(curProp,bytes,(unsigned int)bytesLen);
1873 free(bytes);
1874 }
1875 else if (oldBytes) {
1876 setValueWithSize(curProp,oldBytes,(unsigned int)bytesLen);
1877 free(oldBytes);
1878 }
1879 return 0;
1880 }
1881
1882static int match_begin_end_name(int end) {
1883 int token;
1884 lexSkipWhite();
1885 if (lexLookahead() != ':') return ID;
1886 lexSkipLookahead();
1887 lexSkipWhite();
1888 token = match_begin_name(end);
1889 if (token == ID) {
1890 lexPushLookaheadc(':');
1891 DBG_(("db: ID '%s'\n", yylval.str));
1892 return ID;
1893 }
1894 else if (token != 0) {
1895 lexSkipLookaheadWord();
1896 deleteStr(yylval.str);
1897 DBG_(("db: begin/end %d\n", token));
1898 return token;
1899 }
1900 return 0;
1901 }
1902
1903static char* lexGetQuotedPrintable()
1904 {
1905 char cur;
1906
1907 lexClearToken();
1908 do {
1909 cur = lexGetc();
1910 switch (cur) {
1911 case '=': {
1912 int c = 0;
1913 int next[2];
1914 int i;
1915 for (i = 0; i < 2; i++) {
1916 next[i] = lexGetc();
1917 if (next[i] >= '0' && next[i] <= '9')
1918 c = c * 16 + next[i] - '0';
1919 else if (next[i] >= 'A' && next[i] <= 'F')
1920 c = c * 16 + next[i] - 'A' + 10;
1921 else
1922 break;
1923 }
1924 if (i == 0) {
1925 /* single '=' follow by LINESEP is continuation sign? */
1926 if (next[0] == '\n') {
1927 ++mime_lineNum;
1928 }
1929 else {
1930 lexPushLookaheadc('=');
1931 goto EndString;
1932 }
1933 }
1934 else if (i == 1) {
1935 lexPushLookaheadc(next[1]);
1936 lexPushLookaheadc(next[0]);
1937 lexAppendc('=');
1938 } else {
1939 lexAppendc(c);
1940 }
1941 break;
1942 } /* '=' */
1943 case '\n': {
1944 lexPushLookaheadc('\n');
1945 goto EndString;
1946 }
1947 case (char)EOF:
1948 break;
1949 default:
1950 lexAppendc(cur);
1951 break;
1952 } /* switch */
1953 } while (cur != (char)EOF);
1954
1955EndString:
1956 lexAppendc(0);
1957 return lexStr();
1958 } /* LexQuotedPrintable */
1959
1960static int yylex() {
1961
1962 int lexmode = LEXMODE();
1963 if (lexmode == L_VALUES) {
1964 int c = lexGetc();
1965 if (c == ';') {
1966 DBG_(("db: SEMICOLON\n"));
1967 lexPushLookaheadc(c);
1968 handleMoreRFC822LineBreak(c);
1969 lexSkipLookahead();
1970 return SEMICOLON;
1971 }
1972 else if (strchr("\n",c)) {
1973 ++mime_lineNum;
1974 /* consume all line separator(s) adjacent to each other */
1975 c = lexLookahead();
1976 while (strchr("\n",c)) {
1977 lexSkipLookahead();
1978 c = lexLookahead();
1979 ++mime_lineNum;
1980 }
1981 DBG_(("db: LINESEP\n"));
1982 return LINESEP;
1983 }
1984 else {
1985 char *p = 0;
1986 lexPushLookaheadc(c);
1987 if (lexWithinMode(L_BASE64)) {
1988 /* get each char and convert to bin on the fly... */
1989 p = lexGetDataFromBase64();
1990 yylval.str = p;
1991 return STRING;
1992 }
1993 else if (lexWithinMode(L_QUOTED_PRINTABLE)) {
1994 p = lexGetQuotedPrintable();
1995 }
1996 else {
1997#ifdef _SUPPORT_LINE_FOLDING
1998 p = lexGet1Value();
1999#else
2000 p = lexGetStrUntil(";\n");
2001#endif
2002 }
2003 if (p) {
2004 DBG_(("db: STRING: '%s'\n", p));
2005 yylval.str = p;
2006 return STRING;
2007 }
2008 else return 0;
2009 }
2010 }
2011
2012 else {
2013 /* normal mode */
2014 while (1) {
2015 int c = lexGetc();
2016 switch(c) {
2017 case ':': {
2018 /* consume all line separator(s) adjacent to each other */
2019 /* ignoring linesep immediately after colon. */
2020 c = lexLookahead();
2021 while (strchr("\n",c)) {
2022 lexSkipLookahead();
2023 c = lexLookahead();
2024 ++mime_lineNum;
2025 }
2026 DBG_(("db: COLON\n"));
2027 return COLON;
2028 }
2029 case ';':
2030 DBG_(("db: SEMICOLON\n"));
2031 return SEMICOLON;
2032 case '=':
2033 DBG_(("db: EQ\n"));
2034 return EQ;
2035 /* ignore tabs/newlines in this mode. We can't ignore
2036 * spaces, because values like NEEDS ACTION have a space. */
2037 case '\t': continue;
2038 case '\n': {
2039 ++mime_lineNum;
2040 continue;
2041 }
2042 case EOF: return 0;
2043 break;
2044 default: {
2045 lexPushLookaheadc(c);
2046 /* pending lutz : why linker error with isalpha(c)? */
2047 /*if ( isalpha(c) || c == ' ') { */
2048 if ( ( c >= 'A' && c <= 'Z') || ( c >= 'a' && c <= 'z') || c == ' ') {
2049
2050 char *t = lexGetWord();
2051 yylval.str = t;
2052 if (!strcasecmp(t, "begin")) {
2053 return match_begin_end_name(0);
2054 }
2055 else if (!strcasecmp(t,"end")) {
2056 return match_begin_end_name(1);
2057 }
2058 else {
2059 DBG_(("db: ID '%s'\n", t));
2060 return ID;
2061 }
2062 }
2063 else {
2064 /* unknown token */
2065 return 0;
2066 }
2067 break;
2068 }
2069 }
2070 }
2071 }
2072
2073 return 0;
2074 }
2075
2076
2077/***************************************************************************/
2078 /*** Public Functions ****/
2079/***************************************************************************/
2080
2081static VObject* Parse_MIMEHelper()
2082 {
2083 ObjStackTop = -1;
2084 mime_numErrors = 0;
2085 mime_lineNum = 1;
2086 vObjList = 0;
2087 curObj = 0;
2088
2089 if (yyparse() != 0)
2090 return 0;
2091
2092 finiLex();
2093 return vObjList;
2094 }
2095
2096/****************************************************************************/
2097VObject* Parse_MIME(const char *input, unsigned long len)
2098 {
2099 initLex(input, len, 0);
2100 return Parse_MIMEHelper();
2101 }
2102
2103
2104VObject* Parse_MIME_FromFile(FILE *file)
2105 {
2106 VObject *result;
2107 long startPos;
2108
2109 initLex(0,(unsigned long)-1,file);
2110 startPos = ftell(file);
2111 if (!(result = Parse_MIMEHelper())) {
2112 fseek(file,startPos,SEEK_SET);
2113 }
2114 return result;
2115 }
2116
2117VObject* Parse_MIME_FromFileName(const char *fname)
2118 {
2119 FILE *fp = fopen(fname,"r");
2120 if (fp) {
2121 VObject* o = Parse_MIME_FromFile(fp);
2122 fclose(fp);
2123 return o;
2124 }
2125 else {
2126 char msg[255];
2127 sprintf(msg, "can't open file '%s' for reading\n", fname);
2128 mime_error_(msg);
2129 return 0;
2130 }
2131 }
2132
2133/****************************************************************************/
2134void YYDebug(const char *s)
2135{
2136 Parse_Debug(s);
2137}
2138
2139
2140static MimeErrorHandler mimeErrorHandler;
2141
2142void registerMimeErrorHandler(MimeErrorHandler me)
2143 {
2144 mimeErrorHandler = me;
2145 }
2146
2147static void mime_error(char *s)
2148 {
2149 char msg[256];
2150 if (mimeErrorHandler) {
2151 sprintf(msg,"%s at line %d", s, mime_lineNum);
2152 mimeErrorHandler(msg);
2153 }
2154 }
2155
2156static void mime_error_(char *s)
2157 {
2158 if (mimeErrorHandler) {
2159 mimeErrorHandler(s);
2160 }
2161 }
2162