/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar	1.9 (Berkeley) 02/21/93" */
/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */

// NOLINTBEGIN

#define YYBYACC 1
#define YYMAJOR 1
#define YYMINOR 9
#define YYPATCH 20150711

#define YYEMPTY        (-1)
#define yyclearin      (yychar = YYEMPTY)
#define yyerrok        (yyerrflag = 0)
#define YYRECOVERING() (yyerrflag != 0)
#define YYENOMEM       (-2)
#define YYEOF          0

#ifndef yyparse
#define yyparse    mime_parse
#endif /* yyparse */

#ifndef yylex
#define yylex      mime_lex
#endif /* yylex */

#ifndef yyerror
#define yyerror    mime_error
#endif /* yyerror */

#ifndef yychar
#define yychar     mime_char
#endif /* yychar */

#ifndef yyval
#define yyval      mime_val
#endif /* yyval */

#ifndef yylval
#define yylval     mime_lval
#endif /* yylval */

#ifndef yydebug
#define yydebug    mime_debug
#endif /* yydebug */

#ifndef yynerrs
#define yynerrs    mime_nerrs
#endif /* yynerrs */

#ifndef yyerrflag
#define yyerrflag  mime_errflag
#endif /* yyerrflag */

#ifndef yylhs
#define yylhs      mime_lhs
#endif /* yylhs */

#ifndef yylen
#define yylen      mime_len
#endif /* yylen */

#ifndef yydefred
#define yydefred   mime_defred
#endif /* yydefred */

#ifndef yydgoto
#define yydgoto    mime_dgoto
#endif /* yydgoto */

#ifndef yysindex
#define yysindex   mime_sindex
#endif /* yysindex */

#ifndef yyrindex
#define yyrindex   mime_rindex
#endif /* yyrindex */

#ifndef yygindex
#define yygindex   mime_gindex
#endif /* yygindex */

#ifndef yytable
#define yytable    mime_table
#endif /* yytable */

#ifndef yycheck
#define yycheck    mime_check
#endif /* yycheck */

#ifndef yyname
#define yyname     mime_name
#endif /* yyname */

#ifndef yyrule
#define yyrule     mime_rule
#endif /* yyrule */
#define YYPREFIX "mime_"

#define YYPURE 0

#line 2 "vcc.y"

/***************************************************************************
SPDX-FileCopyrightText: 1996 Apple Computer, Inc., AT&T Corp., International
Business Machines Corporation and Siemens Rolm Communications Inc.

SPDX-License-Identifier: LicenseRef-APPLEMIT

The software is provided with RESTRICTED RIGHTS.  Use, duplication, or
disclosure by the government are subject to restrictions set forth in
DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.

***************************************************************************/

/*
 * src: vcc.c
 * doc: Parser for vCard and vCalendar. Note that this code is
 * generated by a yacc parser generator. Generally it should not
 * be edited by hand. The real source is vcc.y. The #line directives
 * can be commented out here to make it easier to trace through
 * in a debugger. However, if a bug is found it should
 * be fixed in vcc.y and this file regenerated.
 */

/* debugging utilities */
#ifdef __DEBUG
#define DBG_(x) printf x
#else
#define DBG_(x)
#endif

/****  External Functions  ****/

/* assign local name to parser variables and functions so that
   we can use more than one yacc based parser.
*/

#define yyparse mime_parse
#define yylex mime_lex
#define yyerror mime_error
#define yychar mime_char
/* #define p_yyval p_mime_val */
#undef yyval
#define yyval mime_yyval
/* #define p_yylval p_mime_lval */
#undef yylval
#define yylval mime_yylval
#define yydebug mime_debug
#define yynerrs mime_nerrs
#define yyerrflag mime_errflag
#define yyss mime_ss
#define yyssp mime_ssp
#define yyvs mime_vs
#define yyvsp mime_vsp
#define yylhs mime_lhs
#define yylen mime_len
#define yydefred mime_defred
#define yydgoto mime_dgoto
#define yysindex mime_sindex
#define yyrindex mime_rindex
#define yygindex mime_gindex
#define yytable mime_table
#define yycheck mime_check
#define yyname mime_name
#define yyrule mime_rule
#define YYPREFIX "mime_"

#ifndef _NO_LINE_FOLDING
#define _SUPPORT_LINE_FOLDING 1
#endif

/* undef below if compile with MFC */
/* #define INCLUDEMFC 1 */

#if defined(WIN32) || defined(_WIN32)
#ifdef INCLUDEMFC
#include <afx.h>
#endif
#endif

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <ctype.h>
#include "vcc.h"

/****  Types, Constants  ****/

#define YYDEBUG         1       /* 1 to compile in some debugging code */
#define MAXTOKEN        256     /* maximum token (line) length */
#define YYSTACKSIZE     50      /* ~unref ? */
#define MAXLEVEL        10      /* max # of nested objects parseable */
                                /* (includes outermost) */

/****  Global Variables  ****/
int mime_lineNum, mime_numErrors; /* yyerror() can use these */
static VObject* vObjList;
static VObject *curProp;
static VObject *curObj;
static VObject* ObjStack[MAXLEVEL];
static int ObjStackTop;

/* A helpful utility for the rest of the app. */
#if defined(__CPLUSPLUS__)
extern "C" {
#endif

    extern void Parse_Debug(const char *s);
    static void yyerror(const char *s);

#if defined(__CPLUSPLUS__)
    };
#endif

int yylex(void);

enum LexMode {
        L_NORMAL,
        L_VCARD,
        L_VCAL,
        L_VEVENT,
        L_VTODO,
        L_VALUES,
        L_BASE64,
        L_QUOTED_PRINTABLE
        };

/****  Private Forward Declarations  ****/
static void lexClearToken(void);
static char* lexGet1Value(void);
static int lexGeta(void);
static int lexGetc(void);
static char lexGetc_(void);
static char* lexGetDataFromBase64(void);
static char* lexGetQuotedPrintable(void);
static char* lexGetWord(void);
static int lexLookahead(void);
static char* lexLookaheadWord(void);
static void lexPopMode(int top);
static void lexPushMode(enum LexMode mode);
static void lexSkipLookahead(void);
static void lexSkipLookaheadWord(void);
static void lexSkipWhite(void);
static char* lexStr(void);
static int lexWithinMode(enum LexMode mode);
static void enterAttr(const char *s1, const char *s2);
static void enterProps(const char *s);
static void enterValues(const char *value);
static void finiLex(void);
static void mime_error_(const char *s);
static VObject* Parse_MIMEHelper(void);
static VObject* popVObject(void);
static int pushVObject(const char *prop);

#line 202 "vcc.y"
#ifdef YYSTYPE
#undef  YYSTYPE_IS_DECLARED
#define YYSTYPE_IS_DECLARED 1
#endif
#ifndef YYSTYPE_IS_DECLARED
#define YYSTYPE_IS_DECLARED 1
typedef union {
    char *str;
    VObject *vobj;
    } YYSTYPE;
#endif /* !YYSTYPE_IS_DECLARED */
#line 308 "vcc.c"

/* compatibility with bison */
#ifdef YYPARSE_PARAM
/* compatibility with FreeBSD */
# ifdef YYPARSE_PARAM_TYPE
#  define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM)
# else
#  define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
# endif
#else
# define YYPARSE_DECL() yyparse(void)
#endif

/* Parameters sent to lex. */
#ifdef YYLEX_PARAM
# define YYLEX_DECL() yylex(void *YYLEX_PARAM)
# define YYLEX yylex(YYLEX_PARAM)
#else
# define YYLEX_DECL() yylex(void)
# define YYLEX yylex()
#endif

/* Parameters sent to yyerror. */
#ifndef YYERROR_DECL
#define YYERROR_DECL() yyerror(const char *s)
#endif
#ifndef YYERROR_CALL
#define YYERROR_CALL(msg) yyerror(msg)
#endif

extern int YYPARSE_DECL();

#define EQ 257
#define COLON 258
#define DOT 259
#define SEMICOLON 260
#define SPACE 261
#define HTAB 262
#define LINESEP 263
#define NEWLINE 264
#define BEGIN_VCARD 265
#define END_VCARD 266
#define BEGIN_VCAL 267
#define END_VCAL 268
#define BEGIN_VEVENT 269
#define END_VEVENT 270
#define BEGIN_VTODO 271
#define END_VTODO 272
#define STRING 273
#define ID 274
#define YYERRCODE 256
typedef short YYINT;
static const YYINT mime_lhs[] = {                        -1,
    0,    7,    6,    6,    5,    5,    9,    3,   10,    3,
    8,    8,   14,   11,   11,   16,   12,   12,   15,   15,
   17,   18,   18,    1,   19,   13,   13,    2,    2,   21,
    4,   22,    4,   20,   20,   23,   23,   23,   26,   24,
   27,   24,   28,   25,   29,   25,
};
static const YYINT mime_len[] = {                         2,
    1,    0,    3,    1,    1,    1,    0,    4,    0,    3,
    2,    1,    0,    5,    1,    0,    3,    1,    2,    1,
    2,    1,    3,    1,    0,    4,    1,    1,    0,    0,
    4,    0,    3,    2,    1,    1,    1,    1,    0,    4,
    0,    3,    0,    4,    0,    3,
};
static const YYINT mime_defred[] = {                      0,
    0,    0,    0,    5,    6,    0,    1,    0,    0,    0,
    0,    0,   15,   24,    0,    0,    0,    0,   10,    0,
    0,   38,    0,    0,   36,   37,   33,    3,    0,    8,
   11,   13,    0,    0,    0,    0,   31,   34,    0,   17,
    0,    0,    0,   42,    0,   46,    0,   21,   19,   28,
    0,    0,   40,   44,    0,   25,   14,   23,    0,   26,
};
static const YYINT mime_dgoto[] = {                       3,
   15,   51,    4,    5,    6,    7,   12,   22,    8,    9,
   17,   18,   52,   42,   40,   29,   41,   48,   59,   23,
   10,   11,   24,   25,   26,   33,   34,   35,   36,
};
static const YYINT mime_sindex[] = {                   -227,
    0,    0,    0,    0,    0,    0,    0, -246, -260, -253,
 -257, -227,    0,    0,    0, -234, -246, -215,    0,    0,
    0,    0, -223, -253,    0,    0,    0,    0, -214,    0,
    0,    0, -246, -222, -246, -225,    0,    0, -224,    0,
 -214, -221, -217,    0, -218,    0, -208,    0,    0,    0,
 -209, -207,    0,    0, -224,    0,    0,    0, -221,    0,
};
static const YYINT mime_rindex[] = {                      0,
 -244, -254,    0,    0,    0,    1,    0,    0,    0,    0,
    0,    0,    0,    0, -219,    0, -235,    0,    0, -251,
 -248,    0,    0, -213,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
 -201, -256,    0,    0,    0,    0, -216,    0,    0,    0,
 -205,    0,    0,    0,    0,    0,    0,    0, -256,    0,
};
static const YYINT mime_gindex[] = {                      0,
  -26,    0,    0,    0,    0,   47,    0,   -8,    0,    0,
    0,    0,    2,    0,   19,    0,    0,    0,    0,   38,
    0,    0,    0,    0,    0,    0,    0,    0,    0,
};
#define YYTABLESIZE 268
static const YYINT mime_table[] = {                      16,
    4,   30,   13,   29,   39,   19,   29,   43,   31,   13,
   27,    7,   47,   32,   30,   20,   30,   21,   41,   30,
   14,    9,   39,   45,   43,   43,   45,   14,   58,    7,
   12,   30,   12,   12,   12,   12,   12,    1,   18,    2,
   16,   22,   32,   22,   37,   39,   46,   44,   55,   14,
   56,   50,   53,   54,   35,   57,   20,   27,   28,   49,
   60,   38,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    2,    0,    2,
};
static const YYINT mime_check[] = {                       8,
    0,  256,  256,  260,  256,  266,  263,  256,   17,  256,
  268,  256,   39,  268,  269,  269,  271,  271,  270,  274,
  274,  266,  274,  272,   33,  274,   35,  274,   55,  274,
  266,  266,  268,  269,  270,  271,  272,  265,  258,  267,
  260,  258,  258,  260,  268,  260,  272,  270,  257,  274,
  260,  273,  270,  272,  268,  263,  258,  263,   12,   41,
   59,   24,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,  265,   -1,  267,
};
#define YYFINAL 3
#ifndef YYDEBUG
#define YYDEBUG 0
#endif
#define YYMAXTOKEN 274
#define YYUNDFTOKEN 306
#define YYTRANSLATE(a) ((a) > YYMAXTOKEN ? YYUNDFTOKEN : (a))
#if YYDEBUG
static const char *const mime_name[] = {

"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,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"EQ","COLON","DOT","SEMICOLON",
"SPACE","HTAB","LINESEP","NEWLINE","BEGIN_VCARD","END_VCARD","BEGIN_VCAL",
"END_VCAL","BEGIN_VEVENT","END_VEVENT","BEGIN_VTODO","END_VTODO","STRING","ID",
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,"illegal-symbol",
};
static const char *const mime_rule[] = {
"$accept : mime",
"mime : vobjects",
"$$1 :",
"vobjects : vobject $$1 vobjects",
"vobjects : vobject",
"vobject : vcard",
"vobject : vcal",
"$$2 :",
"vcard : BEGIN_VCARD $$2 items END_VCARD",
"$$3 :",
"vcard : BEGIN_VCARD $$3 END_VCARD",
"items : item items",
"items : item",
"$$4 :",
"item : prop COLON $$4 values LINESEP",
"item : error",
"$$5 :",
"prop : name $$5 attr_params",
"prop : name",
"attr_params : attr_param attr_params",
"attr_params : attr_param",
"attr_param : SEMICOLON attr",
"attr : name",
"attr : name EQ name",
"name : ID",
"$$6 :",
"values : value SEMICOLON $$6 values",
"values : value",
"value : STRING",
"value :",
"$$7 :",
"vcal : BEGIN_VCAL $$7 calitems END_VCAL",
"$$8 :",
"vcal : BEGIN_VCAL $$8 END_VCAL",
"calitems : calitem calitems",
"calitems : calitem",
"calitem : eventitem",
"calitem : todoitem",
"calitem : items",
"$$9 :",
"eventitem : BEGIN_VEVENT $$9 items END_VEVENT",
"$$10 :",
"eventitem : BEGIN_VEVENT $$10 END_VEVENT",
"$$11 :",
"todoitem : BEGIN_VTODO $$11 items END_VTODO",
"$$12 :",
"todoitem : BEGIN_VTODO $$12 END_VTODO",

};
#endif

int      yydebug;
int      yynerrs;

int      yyerrflag;
int      yychar;
YYSTYPE  yyval;
YYSTYPE  yylval;

/* define the initial stack-sizes */
#ifdef YYSTACKSIZE
#undef YYMAXDEPTH
#define YYMAXDEPTH  YYSTACKSIZE
#else
#ifdef YYMAXDEPTH
#define YYSTACKSIZE YYMAXDEPTH
#else
#define YYSTACKSIZE 10000
#define YYMAXDEPTH  10000
#endif
#endif

#define YYINITSTACKSIZE 200

typedef struct {
    unsigned stacksize;
    YYINT    *s_base;
    YYINT    *s_mark;
    YYINT    *s_last;
    YYSTYPE  *l_base;
    YYSTYPE  *l_mark;
} YYSTACKDATA;
/* variables for the parser stack */
static YYSTACKDATA yystack;
#line 395 "vcc.y"
static int pushVObject(const char *prop)
    {
    VObject *newObj;
    if (ObjStackTop == MAXLEVEL)
        return 0; /*FALSE*/

    ObjStack[++ObjStackTop] = curObj;

    if (curObj) {
        newObj = addProp(curObj,prop);
        curObj = newObj;
        }
    else
        curObj = newVObject(prop);

    return 1; /*TRUE*/
    }

/* This pops the recently built vCard off the stack and returns it. */
static VObject* popVObject(void)
    {
    VObject *oldObj;
    if (ObjStackTop < 0) {
        yyerror("pop on empty Object Stack\n");
        return 0;
        }
    oldObj = curObj;
    curObj = ObjStack[ObjStackTop--];

    return oldObj;
    }

static void enterValues(const char *value)
    {
    if (fieldedProp && *fieldedProp) {
        if (value) {
            (void) addPropValue(curProp,*fieldedProp,value);
            }
        /* else this field is empty, advance to next field */
        fieldedProp++;
        }
    else {
        if (value) {
            char *p1, *p2;
            wchar_t *p3;
            size_t i;

            /* If the property already has a string value, we append this one,
               using ';' to separate the values. */
            if (vObjectUStringZValue(curProp)) {
                p1 = fakeCString(vObjectUStringZValue(curProp));
                i = strlen(p1)+strlen(value)+2;
                p2 = malloc(i);
                snprintf(p2,i,"%s;%s",p1,value);
                deleteStr(p1);
                p3 = (wchar_t *) vObjectUStringZValue(curProp);
                free(p3);
                setVObjectUStringZValue_(curProp,fakeUnicode(p2,0));
                free(p2);
            } else {
            setVObjectUStringZValue_(curProp,fakeUnicode(value,0));
            }
        }
    }
    deleteStr(value);
    }

static void enterProps(const char *s)
    {
    curProp = addGroup(curObj,s);
    deleteStr(s);
    }

static void enterAttr(const char *s1, const char *s2)
    {
    const char *p1, *p2 = NULL;
    p1 = lookupProp_(s1);
    if (s2) {
        VObject *a;
        p2 = lookupProp_(s2);
        a = addProp(curProp,p1);
        setVObjectStringZValue(a,p2);
        }
    else
        (void)addProp(curProp,p1);
    if (strcasecmp(p1,VCBase64Prop) == 0 || (p2 && strcasecmp(p2,VCBase64Prop)==0))
        lexPushMode(L_BASE64);
    else if (strcasecmp(p1,VCQuotedPrintableProp) == 0
            || (p2 && strcasecmp(p2,VCQuotedPrintableProp)==0))
        lexPushMode(L_QUOTED_PRINTABLE);
    deleteStr(s1); deleteStr(s2);
    }

#define MAX_LEX_LOOKAHEAD_0 32
#define MAX_LEX_LOOKAHEAD 64
#define MAX_LEX_MODE_STACK_SIZE 10
#define LEXMODE() (lexBuf.lexModeStack[lexBuf.lexModeStackTop])

struct LexBuf {
        /* input */
#ifdef INCLUDEMFC
    CFile *inputFile;
#else
    FILE *inputFile;
#endif
    char *inputString;
    unsigned long curPos;
    unsigned long inputLen;
        /* lookahead buffer */
        /*   -- lookahead buffer is short instead of char so that EOF
         /      can be represented correctly.
        */
    unsigned long len;
    short buf[MAX_LEX_LOOKAHEAD+1];
    unsigned long getPtr;
        /* context stack */
    unsigned long lexModeStackTop;
    enum LexMode lexModeStack[MAX_LEX_MODE_STACK_SIZE];
        /* token buffer */
    unsigned long maxToken;
    char *strs;
    unsigned long strsLen;
    } lexBuf;

static void lexPushMode(enum LexMode mode)
    {
    if (lexBuf.lexModeStackTop == (MAX_LEX_MODE_STACK_SIZE-1))
        yyerror("lexical context stack overflow");
    else {
        lexBuf.lexModeStack[++lexBuf.lexModeStackTop] = mode;
        }
    }

static void lexPopMode(int top)
    {
    /* special case of pop for ease of error recovery -- this
        version will never underflow */
    if (top)
        lexBuf.lexModeStackTop = 0;
    else
        if (lexBuf.lexModeStackTop > 0) lexBuf.lexModeStackTop--;
    }

static int lexWithinMode(enum LexMode mode) {
    unsigned long i;
    for (i=0;i<lexBuf.lexModeStackTop;i++)
        if (mode == lexBuf.lexModeStack[i]) return 1;
    return 0;
    }

static char lexGetc_(void)
    {
    /* get next char from input, no buffering. */
    if (lexBuf.curPos == lexBuf.inputLen)
        return EOF;
    else if (lexBuf.inputString)
        return *(lexBuf.inputString + lexBuf.curPos++);
    else {
#ifdef INCLUDEMFC
        char result;
        return lexBuf.inputFile->Read(&result, 1) == 1 ? result : EOF;
#else
        return (char)fgetc(lexBuf.inputFile);
#endif
        }
    }

static int lexGeta(void)
    {
    ++lexBuf.len;
    return (lexBuf.buf[lexBuf.getPtr] = lexGetc_());
    }

static int lexGeta_(int i)
    {
    ++lexBuf.len;
    return (lexBuf.buf[(lexBuf.getPtr+i)%MAX_LEX_LOOKAHEAD] = lexGetc_());
    }

static void lexSkipLookahead(void) {
    if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=((char) EOF)) {
        /* don't skip EOF. */
        lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD;
        lexBuf.len--;
        }
    }

static int lexLookahead(void) {
    int c = (lexBuf.len)?
        lexBuf.buf[lexBuf.getPtr]:
        lexGeta();
    /* do the \r\n -> \n or \r -> \n translation here */
    if (c == '\r') {
        int a = (lexBuf.len>1)?
            lexBuf.buf[(lexBuf.getPtr+1)%MAX_LEX_LOOKAHEAD]:
            lexGeta_(1);
        if (a == '\n') {
            lexSkipLookahead();
            }
        lexBuf.buf[lexBuf.getPtr] = c = '\n';
        }
    else if (c == '\n') {
        int a = (lexBuf.len>1)?
            lexBuf.buf[lexBuf.getPtr+1]:
            lexGeta_(1);
        if (a == '\r') {
            lexSkipLookahead();
            }
        lexBuf.buf[lexBuf.getPtr] = '\n';
        }
    return c;
    }

static int lexGetc(void) {
    int c = lexLookahead();
    if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=((char) EOF)) {
        /* EOF will remain in lookahead buffer */
        lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD;
        lexBuf.len--;
        }
    return c;
    }

static void lexSkipLookaheadWord(void) {
    if (lexBuf.strsLen <= lexBuf.len) {
        lexBuf.len -= lexBuf.strsLen;
        lexBuf.getPtr = (lexBuf.getPtr + lexBuf.strsLen) % MAX_LEX_LOOKAHEAD;
        }
    }

static void lexClearToken(void)
    {
    lexBuf.strsLen = 0;
    }

static void lexAppendc(int c)
    {
    lexBuf.strs[lexBuf.strsLen] = c;
    /* append up to zero termination */
    if (c == 0) return;
    lexBuf.strsLen++;
    if (lexBuf.strsLen >= lexBuf.maxToken) {
        /* double the token string size */
        lexBuf.maxToken <<= 1;
        lexBuf.strs = (char*) realloc(lexBuf.strs,(size_t)lexBuf.maxToken);
        }
    }

static char* lexStr(void) {
    return dupStr(lexBuf.strs,(size_t)lexBuf.strsLen+1);
    }

static void lexSkipWhite(void) {
    int c = lexLookahead();
    while (c == ' ' || c == '\t') {
        lexSkipLookahead();
        c = lexLookahead();
        }
    }

static char* lexGetWord(void) {
    int c;
    lexSkipWhite();
    lexClearToken();
    c = lexLookahead();
    while (c != ((char) EOF) && !strchr("\t\n ;:=",c)) {
        lexAppendc(c);
        lexSkipLookahead();
        c = lexLookahead();
        }
    lexAppendc(0);
    return lexStr();
    }

static void lexPushLookaheadc(int c) {
    int putptr;
    /* can't putback EOF, because it never leaves lookahead buffer */
    if (((char) c) == ((char) EOF)) return;
    putptr = (int)lexBuf.getPtr - 1;
    if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD;
    lexBuf.getPtr = (unsigned long)putptr;
    lexBuf.buf[putptr] = c;
    lexBuf.len += 1;
    }

static char* lexLookaheadWord(void) {
    /* this function can lookahead word with max size of MAX_LEX_LOOKAHEAD_0
     /  and thing bigger than that will stop the lookahead and return 0;
     / leading white spaces are not recoverable.
     */
    int c;
    int len = 0;
    int curgetptr = 0;
    lexSkipWhite();
    lexClearToken();
    curgetptr = (int)lexBuf.getPtr;     /* remember! */
    while (len < (MAX_LEX_LOOKAHEAD_0)) {
        c = lexGetc();
        len++;
        if (c == ((char) EOF) || strchr("\t\n ;:=", c)) {
            lexAppendc(0);
            /* restore lookahead buf. */
            lexBuf.len += len;
            lexBuf.getPtr = (unsigned long)curgetptr;
            return lexStr();
            }
        else
            lexAppendc(c);
        }
    lexBuf.len += len;  /* char that has been moved to lookahead buffer */
    lexBuf.getPtr = (unsigned long)curgetptr;
    return 0;
    }

#ifdef _SUPPORT_LINE_FOLDING
static void handleMoreRFC822LineBreak(int c) {
    /* support RFC 822 line break in cases like
     *  ADR: foo;
     *    morefoo;
     *    more foo;
     */
    if (c == ';') {
        int a;
        lexSkipLookahead();
        /* skip white spaces */
        a = lexLookahead();
        while (a == ' ' || a == '\t') {
            lexSkipLookahead();
            a = lexLookahead();
            }
        if (a == '\n') {
            lexSkipLookahead();
            a = lexLookahead();
            if (a == ' ' || a == '\t') {
                /* continuation, throw away all the \n and spaces read so
                 * far
                 */
                lexSkipWhite();
                lexPushLookaheadc(';');
                }
            else {
                lexPushLookaheadc('\n');
                lexPushLookaheadc(';');
                }
            }
        else {
            lexPushLookaheadc(';');
            }
        }
    }

static char* lexGet1Value(void) {
    int c;
    lexSkipWhite();
    c = lexLookahead();
    lexClearToken();
    while (c != ((char) EOF) && c != ';') {
        if (c == '\n') {
            int a;
            lexSkipLookahead();
            a  = lexLookahead();
            if (a == ' ' || a == '\t') {
                lexAppendc(' ');
                lexSkipLookahead();
                }
            else {
                lexPushLookaheadc('\n');
                break;
                }
            }
        else {
            lexAppendc(c);
            lexSkipLookahead();
            }
        c = lexLookahead();
        }
    lexAppendc(0);
    handleMoreRFC822LineBreak(c);
    return c==((char) EOF)?0:lexStr();
    }
#endif

static int match_begin_name(int end) {
    char *n = lexLookaheadWord();
    int token = ID;
    if (n) {
        if (!strcasecmp(n,"vcard")) token = end?END_VCARD:BEGIN_VCARD;
        else if (!strcasecmp(n,"vcalendar")) token = end?END_VCAL:BEGIN_VCAL;
        else if (!strcasecmp(n,"vevent")) token = end?END_VEVENT:BEGIN_VEVENT;
        else if (!strcasecmp(n,"vtodo")) token = end?END_VTODO:BEGIN_VTODO;
        deleteStr(n);
        return token;
        }
    return 0;
    }

#ifdef INCLUDEMFC
void initLex(const char *inputstring, unsigned long inputlen, CFile *inputfile)
#else
void initLex(const char *inputstring, unsigned long inputlen, FILE *inputfile)
#endif
    {
    /* initialize lex mode stack */
    lexBuf.lexModeStack[lexBuf.lexModeStackTop=0] = L_NORMAL;

    /* iniatialize lex buffer. */
    lexBuf.inputString = (char*) inputstring;
    lexBuf.inputLen = inputlen;
    lexBuf.curPos = 0;
    lexBuf.inputFile = inputfile;

    lexBuf.len = 0;
    lexBuf.getPtr = 0;

    lexBuf.maxToken = MAXTOKEN;
    lexBuf.strs = (char*)malloc(MAXTOKEN);
    lexBuf.strsLen = 0;
    }

static void finiLex(void) {
    VObject* vobj, *topobj = 0;
    while(vobj = popVObject(), vobj) {
        topobj = vobj;
    }
    if(topobj)
        cleanVObject(topobj);
    free(lexBuf.strs);
    }

/* This parses and converts the base64 format for binary encoding into
 * a decoded buffer (allocated with new).  See RFC 1521.
 */
static char * lexGetDataFromBase64(void)
    {
    size_t bytesLen = 0, bytesMax = 0;
    int quadIx = 0, pad = 0;
    unsigned long trip = 0;
    unsigned char b;
    int c;
    unsigned char *bytes = NULL;
    unsigned char *oldBytes = NULL;

    DBG_(("db: lexGetDataFromBase64\n"));
    while (1) {
        c = lexGetc();
        if (c == '\n') {
            ++mime_lineNum;
            if (lexLookahead() == '\n') {
                /* a '\n' character by itself means end of data */
                break;
                }
            else continue; /* ignore '\n' */
            }
        else {
            if ((c >= 'A') && (c <= 'Z'))
                b = (unsigned char)(c - 'A');
            else if ((c >= 'a') && (c <= 'z'))
                b = (unsigned char)(c - 'a') + 26;
            else if ((c >= '0') && (c <= '9'))
                b = (unsigned char)(c - '0') + 52;
            else if (c == '+')
                b = 62;
            else if (c == '/')
                b = 63;
            else if (c == '=') {
                b = 0;
                pad++;
            } else if ((c == ' ') || (c == '\t')) {
                continue;
            } else { /* error condition */
                if (bytes) free(bytes);
                else if (oldBytes) free(oldBytes);
                /* error recovery: skip until 2 adjacent newlines. */
                DBG_(("db: invalid character 0x%x '%c'\n", c,c));
                if (c != ((char) EOF))  {
                    c = lexGetc();
                    while (c != ((char) EOF)) {
                        if (c == '\n' && lexLookahead() == '\n') {
                            ++mime_lineNum;
                            break;
                            }
                        c = lexGetc();
                        }
                    }
                return NULL;
                }
            trip = (trip << 6) | b;
            if (++quadIx == 4) {
                unsigned char outBytes[3];
                size_t numOut;
                int i;
                for (i = 0; i < 3; i++) {
                    outBytes[2-i] = (unsigned char)(trip & 0xFF);
                    trip >>= 8;
                    }
                numOut = (size_t)(3 - pad);
                if (bytesLen + numOut > bytesMax) {
                    if (!bytes) {
                        bytesMax = 1024;
                        bytes = (unsigned char*)malloc((size_t)bytesMax);
                        }
                    else {
                        bytesMax <<= 2;
                        oldBytes = bytes;
                        bytes = (unsigned char*)realloc(bytes,(size_t)bytesMax);
                        }
                    if (bytes == 0) {
                        mime_error("out of memory while processing BASE64 data\n");
                        }
                    }
                if (bytes) {
                    memcpy(bytes + bytesLen, outBytes, numOut);
                    bytesLen += numOut;
                    }
                trip = 0;
                quadIx = 0;
                }
            }
        } /* while */
    DBG_(("db: bytesLen = %lu\n", (unsigned long)bytesLen));
    /* kludge: all this won't be necessary if we have tree form
        representation */
    if (bytes) {
        (void)setValueWithSize(curProp,bytes,(unsigned int)bytesLen);
        free(bytes);
        }
    else if (oldBytes) {
        (void)setValueWithSize(curProp,oldBytes,(unsigned int)bytesLen);
        free(oldBytes);
        }
    return 0;
    }

static int match_begin_end_name(int end) {
    int token;
    lexSkipWhite();
    if (lexLookahead() != ':') return ID;
    lexSkipLookahead();
    lexSkipWhite();
    token = match_begin_name(end);
    if (token == ID) {
        lexPushLookaheadc(':');
        DBG_(("db: ID '%s'\n", yylval.str));
        return ID;
        }
    else if (token != 0) {
        lexSkipLookaheadWord();
        deleteStr(yylval.str);
        DBG_(("db: begin/end %d\n", token));
        return token;
        }
    return 0;
    }

static char* lexGetQuotedPrintable(void)
    {
    char cur;

    lexClearToken();
    do {
        cur = lexGetc();
        switch (cur) {
            case '=': {
                int c = 0;
                int next[2];
                int i;
                for (i = 0; i < 2; i++) {
                    next[i] = lexGetc();
                    if (next[i] >= '0' && next[i] <= '9')
                        c = c * 16 + next[i] - '0';
                    else if (next[i] >= 'A' && next[i] <= 'F')
                        c = c * 16 + next[i] - 'A' + 10;
                    else
                        break;
                    }
                if (i == 0) {
                    /* single '=' follow by LINESEP is continuation sign? */
                    if (next[0] == '\n') {
                        ++mime_lineNum;
                        }
                    else {
                        lexPushLookaheadc('=');
                        goto EndString;
                        }
                    }
                else if (i == 1) {
                    lexPushLookaheadc(next[1]);
                    lexPushLookaheadc(next[0]);
                    lexAppendc('=');
                } else {
                    lexAppendc(c);
                    }
                break;
                } /* '=' */
            case '\n': {
                lexPushLookaheadc('\n');
                goto EndString;
                }
            case (char)EOF:
                break;
            default:
                lexAppendc(cur);
                break;
            } /* switch */
        } while (cur != (char)EOF);

EndString:
    lexAppendc(0);
    return lexStr();
    } /* LexQuotedPrintable */

int yylex(void) {

    int lexmode = LEXMODE();
    if (lexmode == L_VALUES) {
        int c = lexGetc();
        if (c == ';') {
            DBG_(("db: SEMICOLON\n"));
            lexPushLookaheadc(c);
#ifdef _SUPPORT_LINE_FOLDING
            handleMoreRFC822LineBreak(c);
#endif
            lexSkipLookahead();
            return SEMICOLON;
            }
        else if (strchr("\n",c)) {
            ++mime_lineNum;
            /* consume all line separator(s) adjacent to each other */
            c = lexLookahead();
            while (strchr("\n",c)) {
                lexSkipLookahead();
                c = lexLookahead();
                ++mime_lineNum;
                }
            DBG_(("db: LINESEP\n"));
            return LINESEP;
            }
        else {
            char *p = 0;
            lexPushLookaheadc(c);
            if (lexWithinMode(L_BASE64)) {
                /* get each char and convert to bin on the fly... */
                p = lexGetDataFromBase64();
                yylval.str = p;
                return STRING;
                }
            else if (lexWithinMode(L_QUOTED_PRINTABLE)) {
                p = lexGetQuotedPrintable();
                }
            else {
#ifdef _SUPPORT_LINE_FOLDING
                p = lexGet1Value();
#else
                p = lexGetStrUntil(";\n");
#endif
                }
            if (p) {
                DBG_(("db: STRING: '%s'\n", p));
                yylval.str = p;
                return STRING;
                }
            else return 0;
            }
        }
    else {
        /* normal mode */
        while (1) {
            int c = lexGetc();
            switch(c) {
                case ':': {
                    /* consume all line separator(s) adjacent to each other */
                    /* ignoring linesep immediately after colon. */
                    c = lexLookahead();
                    while (strchr("\n",c)) {
                        lexSkipLookahead();
                        c = lexLookahead();
                        ++mime_lineNum;
                    }
                    DBG_(("db: COLON\n"));
                    return COLON;
                    }
                case ';':
                    DBG_(("db: SEMICOLON\n"));
                    return SEMICOLON;
                case '=':
                    DBG_(("db: EQ\n"));
                    return EQ;
                /* ignore whitespace in this mode */
                case '\t':
                case ' ': continue;
                case '\n': {
                    ++mime_lineNum;
                    continue;
                    }
                case ((char) EOF): return 0;
                    break;
                default: {
                    lexPushLookaheadc(c);
                    if (isalpha(c)) {
                        char *t = lexGetWord();
                        yylval.str = t;
                        if (!strcasecmp(t, "begin")) {
                            return match_begin_end_name(0);
                            }
                        else if (!strcasecmp(t,"end")) {
                            return match_begin_end_name(1);
                            }
                        else {
                            DBG_(("db: ID '%s'\n", t));
                            return ID;
                            }
                        }
                    else {
                        /* unknown token */
                        return 0;
                        }
                    break;
                    }
                }
            }
        }
    return 0;
    }

/***************************************************************************/
/***                                                    Public Functions                                                ****/
/***************************************************************************/

static VObject* Parse_MIMEHelper(void)
    {
    ObjStackTop = -1;
    mime_numErrors = 0;
    mime_lineNum = 1;
    vObjList = 0;
    curObj = 0;
    curProp = 0;

    if (yyparse() != 0) {
        finiLex();
        return 0;
    }

    finiLex();
    return vObjList;
    }

VObject* Parse_MIME(const char *input, unsigned long len)
    {
    initLex(input, len, 0);
    return Parse_MIMEHelper();
    }

#ifdef INCLUDEMFC

VObject* Parse_MIME_FromFile(CFile *file)
    {
    unsigned long startPos;
    VObject *result;

    initLex(0,-1,file);
    startPos = file->GetPosition();
    if (!(result = Parse_MIMEHelper()))
        file->Seek(startPos, CFile::begin);
    return result;
    }

#else

VObject* Parse_MIME_FromFile(FILE *file)
    {
    VObject *result;
    long startPos;

    initLex(0,(unsigned long)-1,file);
    startPos = ftell(file);
    if (!(result = Parse_MIMEHelper())) {
        if (startPos >= 0)
            (void)fseek(file,startPos,SEEK_SET);
        }
    return result;
    }

VObject* Parse_MIME_FromFileName(const char *fname)
    {
    FILE *fp = fopen(fname,"r");
    if (fp) {
        VObject* o = Parse_MIME_FromFile(fp);
        fclose(fp);
        return o;
        }
    else {
        char msg[256];
        snprintf(msg, sizeof(msg), "can't open file '%s' for reading\n", fname);
        mime_error_(msg);
        return 0;
        }
    }

#endif

static MimeErrorHandler mimeErrorHandler;

void registerMimeErrorHandler(MimeErrorHandler me)
    {
    mimeErrorHandler = me;
    }

static void mime_error(const char *s)
    {
    char msg[256];
    if (mimeErrorHandler) {
        snprintf(msg,sizeof(msg),"%s at line %d", s, mime_lineNum);
        mimeErrorHandler(msg);
        }
    }

static void mime_error_(const char *s)
    {
    if (mimeErrorHandler) {
        mimeErrorHandler(s);
        }
    }
#line 1398 "vcc.c"

#if YYDEBUG
#include <stdio.h>		/* needed for printf */
#endif

#include <stdlib.h>	/* needed for malloc, etc */
#include <string.h>	/* needed for memset */

/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
{
    int i;
    unsigned newsize;
    YYINT *newss;
    YYSTYPE *newvs;

    if ((newsize = data->stacksize) == 0)
        newsize = YYINITSTACKSIZE;
    else if (newsize >= YYMAXDEPTH)
        return YYENOMEM;
    else if ((newsize *= 2) > YYMAXDEPTH)
        newsize = YYMAXDEPTH;

    i = (int) (data->s_mark - data->s_base);
    newss = (YYINT *)realloc(data->s_base, newsize * sizeof(*newss));
    if (newss == 0)
        return YYENOMEM;

    data->s_base = newss;
    data->s_mark = newss + i;

    newvs = (YYSTYPE *)realloc(data->l_base, newsize * sizeof(*newvs));
    if (newvs == 0)
        return YYENOMEM;

    data->l_base = newvs;
    data->l_mark = newvs + i;

    data->stacksize = newsize;
    data->s_last = data->s_base + newsize - 1;
    return 0;
}

#if YYPURE || defined(YY_NO_LEAKS)
static void yyfreestack(YYSTACKDATA *data)
{
    free(data->s_base);
    free(data->l_base);
    memset(data, 0, sizeof(*data));
}
#else
#define yyfreestack(data) /* nothing */
#endif

#define YYABORT  goto yyabort
#define YYREJECT goto yyabort
#define YYACCEPT goto yyaccept
#define YYERROR  goto yyerrlab

int
YYPARSE_DECL()
{
    int yym, yyn, yystate;
#if YYDEBUG
    const char *yys;

    if ((yys = getenv("YYDEBUG")) != 0)
    {
        yyn = *yys;
        if (yyn >= '0' && yyn <= '9')
            yydebug = yyn - '0';
    }
#endif

    yynerrs = 0;
    yyerrflag = 0;
    yychar = YYEMPTY;
/*    yystate = 0; never read, says scan-view */

#if YYPURE
    memset(&yystack, 0, sizeof(yystack));
#endif

    if (yystack.s_base == NULL && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
    yystack.s_mark = yystack.s_base;
    yystack.l_mark = yystack.l_base;
    yystate = 0;
    *yystack.s_mark = 0;

yyloop:
    if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
    if (yychar < 0)
    {
        if ((yychar = YYLEX) < 0) yychar = YYEOF;
#if YYDEBUG
        if (yydebug)
        {
            yys = yyname[YYTRANSLATE(yychar)];
            printf("%sdebug: state %d, reading %d (%s)\n",
                    YYPREFIX, yystate, yychar, yys);
        }
#endif
    }
    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
    {
#if YYDEBUG
        if (yydebug)
            printf("%sdebug: state %d, shifting to state %d\n",
                    YYPREFIX, yystate, yytable[yyn]);
#endif
        if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM)
        {
            goto yyoverflow;
        }
        yystate = yytable[yyn];
        *++yystack.s_mark = yytable[yyn];
        *++yystack.l_mark = yylval;
        yychar = YYEMPTY;
        if (yyerrflag > 0)  --yyerrflag;
        goto yyloop;
    }
    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
    {
        yyn = yytable[yyn];
        goto yyreduce;
    }
    if (yyerrflag) goto yyinrecovery;

    YYERROR_CALL("syntax error");

    goto yyerrlab;

yyerrlab:
    ++yynerrs;

yyinrecovery:
    if (yyerrflag < 3)
    {
        yyerrflag = 3;
        for (;;)
        {
            if ((yyn = yysindex[*yystack.s_mark]) && (yyn += YYERRCODE) >= 0 &&
                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
            {
#if YYDEBUG
                if (yydebug)
                    printf("%sdebug: state %d, error recovery shifting\
 to state %d\n", YYPREFIX, *yystack.s_mark, yytable[yyn]);
#endif
                if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM)
                {
                    goto yyoverflow;
                }
                yystate = yytable[yyn];
                *++yystack.s_mark = yytable[yyn];
                *++yystack.l_mark = yylval;
                goto yyloop;
            }
            else
            {
#if YYDEBUG
                if (yydebug)
                    printf("%sdebug: error recovery discarding state %d\n",
                            YYPREFIX, *yystack.s_mark);
#endif
                if (yystack.s_mark <= yystack.s_base) goto yyabort;
                --yystack.s_mark;
                --yystack.l_mark;
            }
        }
    }
    else
    {
        if (yychar == YYEOF) goto yyabort;
#if YYDEBUG
        if (yydebug)
        {
            yys = yyname[YYTRANSLATE(yychar)];
            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
                    YYPREFIX, yystate, yychar, yys);
        }
#endif
        yychar = YYEMPTY;
        goto yyloop;
    }

yyreduce:
#if YYDEBUG
    if (yydebug)
        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
                YYPREFIX, yystate, yyn, yyrule[yyn]);
#endif
    yym = yylen[yyn];
    if (yym)
        yyval = yystack.l_mark[1-yym];
    else
        memset(&yyval, 0, sizeof yyval);
    switch (yyn)
    {
case 2:
#line 233 "vcc.y"
	{ addList(&vObjList, yystack.l_mark[0].vobj); curObj = 0; }
break;
case 4:
#line 236 "vcc.y"
	{ addList(&vObjList, yystack.l_mark[0].vobj); curObj = 0; }
break;
case 7:
#line 245 "vcc.y"
	{
        lexPushMode(L_VCARD);
        if (!pushVObject(VCCardProp)) YYERROR;
        }
break;
case 8:
#line 250 "vcc.y"
	{
        lexPopMode(0);
        yyval.vobj = popVObject();
        }
break;
case 9:
#line 255 "vcc.y"
	{
        lexPushMode(L_VCARD);
        if (!pushVObject(VCCardProp)) YYERROR;
        }
break;
case 10:
#line 260 "vcc.y"
	{
        lexPopMode(0);
        yyval.vobj = popVObject();
        }
break;
case 13:
#line 271 "vcc.y"
	{
        lexPushMode(L_VALUES);
        }
break;
case 14:
#line 275 "vcc.y"
	{
        if (lexWithinMode(L_BASE64) || lexWithinMode(L_QUOTED_PRINTABLE))
           lexPopMode(0);
        lexPopMode(0);
        }
break;
case 16:
#line 284 "vcc.y"
	{
        enterProps(yystack.l_mark[0].str);
        }
break;
case 18:
#line 289 "vcc.y"
	{
        enterProps(yystack.l_mark[0].str);
        }
break;
case 22:
#line 302 "vcc.y"
	{
        enterAttr(yystack.l_mark[0].str,0);
        }
break;
case 23:
#line 306 "vcc.y"
	{
        enterAttr(yystack.l_mark[-2].str,yystack.l_mark[0].str);
        }
break;
case 25:
#line 315 "vcc.y"
	{ enterValues(yystack.l_mark[-1].str); }
break;
case 27:
#line 317 "vcc.y"
	{ enterValues(yystack.l_mark[0].str); }
break;
case 29:
#line 321 "vcc.y"
	{ yyval.str = 0; }
break;
case 30:
#line 326 "vcc.y"
	{ if (!pushVObject(VCCalProp)) YYERROR; }
break;
case 31:
#line 329 "vcc.y"
	{ yyval.vobj = popVObject(); }
break;
case 32:
#line 331 "vcc.y"
	{ if (!pushVObject(VCCalProp)) YYERROR; }
break;
case 33:
#line 333 "vcc.y"
	{ yyval.vobj = popVObject(); }
break;
case 39:
#line 348 "vcc.y"
	{
        lexPushMode(L_VEVENT);
        if (!pushVObject(VCEventProp)) YYERROR;
        }
break;
case 40:
#line 354 "vcc.y"
	{
        lexPopMode(0);
        (void)popVObject();
        }
break;
case 41:
#line 359 "vcc.y"
	{
        lexPushMode(L_VEVENT);
        if (!pushVObject(VCEventProp)) YYERROR;
        }
break;
case 42:
#line 364 "vcc.y"
	{
        lexPopMode(0);
        (void)popVObject();
        }
break;
case 43:
#line 372 "vcc.y"
	{
        lexPushMode(L_VTODO);
        if (!pushVObject(VCTodoProp)) YYERROR;
        }
break;
case 44:
#line 378 "vcc.y"
	{
        lexPopMode(0);
        (void)popVObject();
        }
break;
case 45:
#line 383 "vcc.y"
	{
        lexPushMode(L_VTODO);
        if (!pushVObject(VCTodoProp)) YYERROR;
        }
break;
case 46:
#line 388 "vcc.y"
	{
        lexPopMode(0);
        (void)popVObject();
        }
break;
#line 1759 "vcc.c"
    }
    yystack.s_mark -= yym;
    yystate = *yystack.s_mark;
    yystack.l_mark -= yym;
    yym = yylhs[yyn];
    if (yystate == 0 && yym == 0)
    {
#if YYDEBUG
        if (yydebug)
            printf("%sdebug: after reduction, shifting from state 0 to\
 state %d\n", YYPREFIX, YYFINAL);
#endif
        yystate = YYFINAL;
        *++yystack.s_mark = YYFINAL;
        *++yystack.l_mark = yyval;
        if (yychar < 0)
        {
            if ((yychar = YYLEX) < 0) yychar = YYEOF;
#if YYDEBUG
            if (yydebug)
            {
                yys = yyname[YYTRANSLATE(yychar)];
                printf("%sdebug: state %d, reading %d (%s)\n",
                        YYPREFIX, YYFINAL, yychar, yys);
            }
#endif
        }
        if (yychar == YYEOF) goto yyaccept;
        goto yyloop;
    }
    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
        yystate = yytable[yyn];
    else
        yystate = yydgoto[yym];
#if YYDEBUG
    if (yydebug)
        printf("%sdebug: after reduction, shifting from state %d \
to state %d\n", YYPREFIX, *yystack.s_mark, yystate);
#endif
    if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM)
    {
        goto yyoverflow;
    }
    *++yystack.s_mark = (YYINT) yystate;
    *++yystack.l_mark = yyval;
    goto yyloop;

yyoverflow:
    YYERROR_CALL("yacc stack overflow");

yyabort:
    yyfreestack(&yystack);
    return (1);

yyaccept:
    yyfreestack(&yystack);
    return (0);
}

// NOLINTEND
