2133 lines
62 KiB
C++
2133 lines
62 KiB
C++
//#ifndef __MWERKS__
|
|
#include "stdafx.h"
|
|
//#endif
|
|
#ifndef lint
|
|
static char yysccsid[] = "@(#)yaccpar 1.10 (Berkeley) 09/07/95 swb";
|
|
#endif
|
|
#define YYBYACC 1
|
|
#define YYMAJOR 1
|
|
#define YYMINOR 10
|
|
#define yyclearin (yychar=(-1))
|
|
#define yyerrok (yyerrflag=0)
|
|
#define YYRECOVERING (yyerrflag!=0)
|
|
#ifdef __cplusplus
|
|
#define CFUNCTIONS extern "C" {
|
|
#define END_CFUNCTIONS }
|
|
#else
|
|
#define CFUNCTIONS
|
|
#define END_CFUNCTIONS
|
|
#endif
|
|
#define yyparse msv_parse
|
|
#define yylex msv_lex
|
|
#define yyerror msv_error
|
|
#define yychar msv_char
|
|
#define p_yyval p_msv_val
|
|
#undef yyval
|
|
#define yyval (*p_msv_val)
|
|
#define p_yylval p_msv_lval
|
|
#undef yylval
|
|
#define yylval (*p_msv_lval)
|
|
#define yydebug msv_debug
|
|
#define yynerrs msv_nerrs
|
|
#define yyerrflag msv_errflag
|
|
#define yyss msv_ss
|
|
#define yyssp msv_ssp
|
|
#define yyvs msv_vs
|
|
#define yyvsp msv_vsp
|
|
#define yylhs msv_lhs
|
|
#define yylen msv_len
|
|
#define yydefred msv_defred
|
|
#define yydgoto msv_dgoto
|
|
#define yysindex msv_sindex
|
|
#define yyrindex msv_rindex
|
|
#define yygindex msv_gindex
|
|
#define yytable msv_table
|
|
#define yycheck msv_check
|
|
#define yyname msv_name
|
|
#define yyrule msv_rule
|
|
#define YYPREFIX "msv_"
|
|
#line 2 "msv.y"
|
|
|
|
/***************************************************************************
|
|
(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
|
|
Business Machines Corporation and Siemens Rolm Communications Inc.
|
|
|
|
For purposes of this license notice, the term Licensors shall mean,
|
|
collectively, Apple Computer, Inc., AT&T Corp., International
|
|
Business Machines Corporation and Siemens Rolm Communications Inc.
|
|
The term Licensor shall mean any of the Licensors.
|
|
|
|
Subject to acceptance of the following conditions, permission is hereby
|
|
granted by Licensors without the need for written agreement and without
|
|
license or royalty fees, to use, copy, modify and distribute this
|
|
software for any purpose.
|
|
|
|
The above copyright notice and the following four paragraphs must be
|
|
reproduced in all copies of this software and any software including
|
|
this software.
|
|
|
|
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
|
|
ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
|
|
MODIFICATIONS.
|
|
|
|
IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
|
|
INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
|
|
OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
DAMAGE.
|
|
|
|
EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
|
|
INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
PURPOSE.
|
|
|
|
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.
|
|
|
|
***************************************************************************/
|
|
|
|
/*
|
|
To invoke this parser, see the "Public Interface" section below.
|
|
|
|
This MS/V parser accepts input such as the following:
|
|
[vCard
|
|
O=AT&T/Versit;
|
|
FN=Roland H. Alden
|
|
TITLE=Consultant (Versit Project Office)
|
|
N=Alden;Roland
|
|
A:DOM,POSTAL,PARCEL,HOME,WORK=Suite 2208;One Pine Street;San Francisco;CA;94111;U.S.A.
|
|
A.FADR:DOM,POSTAL,PARCEL,HOME,WORK=Roland H. Alden\
|
|
Suite 2208\
|
|
One Pine Street\
|
|
San Francisco, CA 94111
|
|
A.FADR:POSTAL,PARCEL,HOME,WORK=Roland H. Alden\
|
|
Suite 2208\
|
|
One Pine Street\
|
|
San Francisco, CA 94111\
|
|
U.S.A.
|
|
B.T:HOME,WORK,PREF,MSG=+1 (415) 296-9106
|
|
C.T:WORK,FAX=+1 (415) 296-9016
|
|
D.T:MSG,CELL=+1 (415) 608-5981
|
|
E.EMAIL:WORK,PREF,INTERNET=sf!rincon!ralden@alden.attmail.com
|
|
F.EMAIL:INTERNET=ralden@sfgate.com
|
|
G.EMAIL:HOME,MCIMail=242-2200
|
|
PN=ROW-LAND ALL-DEN
|
|
PN:WAV,BASE64=<bindata>
|
|
UklGRtQ4AABXQVZFZm10IBAAAAABAAEAESsAABErAAABAAgAZGF0Ya84AACAgoSD
|
|
...
|
|
e319fYCAg4WEhIAA
|
|
</bindata>
|
|
]
|
|
|
|
For the purposes of the following grammar, a LINESEP token indicates either
|
|
a \r char (0x0D), a \n char (0x0A), or a combination of one of each,
|
|
in either order (\r\n or \n\r). This is a bit more lenient than the spec.
|
|
*/
|
|
|
|
|
|
#ifdef _WIN32
|
|
#include <wchar.h>
|
|
#else
|
|
#include "wchar.h"
|
|
#endif
|
|
#include <string.h>
|
|
#include <malloc.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "clist.h"
|
|
#include "vcard.h"
|
|
#include "msv.h"
|
|
|
|
#if defined(_WIN32) || defined(__MWERKS__)
|
|
#define HNEW(_t, _n) new _t[_n]
|
|
#define HFREE(_h) delete [] _h
|
|
#else
|
|
#define HNEW(_t, _n) (_t __huge *)_halloc(_n, 1)
|
|
/*#define HNEW(_t, _n) (_t __huge *)_halloc(_n, 1); {char buf[40]; sprintf(buf, "_halloc(%ld)\n", _n); Parse_Debug(buf);}*/
|
|
#define HFREE(_h) _hfree(_h)
|
|
#endif
|
|
|
|
|
|
/**** Types, Constants ****/
|
|
|
|
#define YYDEBUG 1 /* 1 to compile in some debugging code */
|
|
#define MAXTOKEN 256 /* maximum token (line) length */
|
|
#define MAXFLAGS ((MAXTOKEN / 2) / sizeof(char *))
|
|
#define YYSTACKSIZE 50
|
|
#define MAXASSOCKEY 24
|
|
#define MAXASSOCVALUE 64
|
|
#define MAXCARD 2 /* max # of nested cards parseable */
|
|
/* (includes outermost) */
|
|
|
|
typedef struct {
|
|
const char* known[MAXFLAGS];
|
|
char extended[MAXTOKEN / 2];
|
|
} FLAGS_STRUCT;
|
|
|
|
typedef struct {
|
|
char key[MAXASSOCKEY];
|
|
char value[MAXASSOCVALUE];
|
|
} AssocEntry; /* a simple key/value association, impl'd using CList */
|
|
|
|
/* some fake property names that represent special cases */
|
|
#define msv_fam_given "family;given"
|
|
#define msv_orgname_orgunit "org_name;org_unit"
|
|
#define msv_address "six part address"
|
|
|
|
/*
|
|
* These strings are defined as a courtesy for the rest of the app code.
|
|
* They are useful here because the tail end of each is the cleartext
|
|
* string to match according to this grammar.
|
|
*/
|
|
const char* vcDefaultLang = "en-US";
|
|
|
|
const char* vcISO9070Prefix = VCISO9070Prefix;
|
|
const char* vcClipboardFormatVCard = VCClipboardFormatVCard;
|
|
|
|
const char* vcISO639Type = VCISO639Type;
|
|
const char* vcStrIdxType = VCStrIdxType;
|
|
const char* vcFlagsType = VCFlagsType;
|
|
const char* vcNextObjectType = VCNextObjectType;
|
|
const char* vcOctetsType = VCOctetsType;
|
|
const char* vcGIFType = VCGIFType;
|
|
const char* vcWAVType = VCWAVType;
|
|
const char* vcNullType = VCNullType;
|
|
|
|
const char* vcRootObject = VCRootObject;
|
|
const char* vcBodyObject = VCBodyObject;
|
|
const char* vcPartObject = VCPartObject;
|
|
const char* vcBodyProp = VCBodyProp;
|
|
const char* vcPartProp = VCPartProp;
|
|
const char* vcNextObjectProp = VCNextObjectProp;
|
|
|
|
const char* vcLogoProp = VCLogoProp;
|
|
const char* vcPhotoProp = VCPhotoProp;
|
|
const char* vcDeliveryLabelProp = VCDeliveryLabelProp;
|
|
const char* vcPostalBoxProp = VCPostalBoxProp;
|
|
const char* vcStreetAddressProp = VCStreetAddressProp;
|
|
const char* vcExtAddressProp = VCExtAddressProp;
|
|
const char* vcCountryNameProp = VCCountryNameProp;
|
|
const char* vcPostalCodeProp = VCPostalCodeProp;
|
|
const char* vcRegionProp = VCRegionProp;
|
|
const char* vcCityProp = VCCityProp;
|
|
const char* vcFullNameProp = VCFullNameProp;
|
|
const char* vcTitleProp = VCTitleProp;
|
|
const char* vcOrgNameProp = VCOrgNameProp;
|
|
const char* vcOrgUnitProp = VCOrgUnitProp;
|
|
const char* vcOrgUnit2Prop = VCOrgUnit2Prop;
|
|
const char* vcOrgUnit3Prop = VCOrgUnit3Prop;
|
|
const char* vcOrgUnit4Prop = VCOrgUnit4Prop;
|
|
const char* vcFamilyNameProp = VCFamilyNameProp;
|
|
const char* vcGivenNameProp = VCGivenNameProp;
|
|
const char* vcAdditionalNamesProp = VCAdditionalNamesProp;
|
|
const char* vcNamePrefixesProp = VCNamePrefixesProp;
|
|
const char* vcNameSuffixesProp = VCNameSuffixesProp;
|
|
const char* vcPronunciationProp = VCPronunciationProp;
|
|
const char* vcLanguageProp = VCLanguageProp;
|
|
const char* vcTelephoneProp = VCTelephoneProp;
|
|
const char* vcEmailAddressProp = VCEmailAddressProp;
|
|
const char* vcTimeZoneProp = VCTimeZoneProp;
|
|
const char* vcLocationProp = VCLocationProp;
|
|
const char* vcCommentProp = VCCommentProp;
|
|
const char* vcCharSetProp = VCCharSetProp;
|
|
const char* vcLastRevisedProp = VCLastRevisedProp;
|
|
const char* vcUniqueStringProp = VCUniqueStringProp;
|
|
const char* vcPublicKeyProp = VCPublicKeyProp;
|
|
const char* vcMailerProp = VCMailerProp;
|
|
const char* vcAgentProp = VCAgentProp;
|
|
const char* vcBirthDateProp = VCBirthDateProp;
|
|
const char* vcBusinessRoleProp = VCBusinessRoleProp;
|
|
const char* vcCaptionProp = VCCaptionProp;
|
|
const char* vcURLProp = VCURLProp;
|
|
|
|
const char* vcDomesticProp = VCDomesticProp;
|
|
const char* vcInternationalProp = VCInternationalProp;
|
|
const char* vcPostalProp = VCPostalProp;
|
|
const char* vcParcelProp = VCParcelProp;
|
|
const char* vcHomeProp = VCHomeProp;
|
|
const char* vcWorkProp = VCWorkProp;
|
|
const char* vcPreferredProp = VCPreferredProp;
|
|
const char* vcVoiceProp = VCVoiceProp;
|
|
const char* vcFaxProp = VCFaxProp;
|
|
const char* vcMessageProp = VCMessageProp;
|
|
const char* vcCellularProp = VCCellularProp;
|
|
const char* vcPagerProp = VCPagerProp;
|
|
const char* vcBBSProp = VCBBSProp;
|
|
const char* vcModemProp = VCModemProp;
|
|
const char* vcCarProp = VCCarProp;
|
|
const char* vcISDNProp = VCISDNProp;
|
|
const char* vcVideoProp = VCVideoProp;
|
|
|
|
const char* vcInlineProp = VCInlineProp;
|
|
const char* vcURLValueProp = VCURLValueProp;
|
|
const char* vcContentIDProp = VCContentIDProp;
|
|
|
|
const char* vc7bitProp = VC7bitProp;
|
|
const char* vcQuotedPrintableProp = VCQuotedPrintableProp;
|
|
const char* vcBase64Prop = VCBase64Prop;
|
|
|
|
const char* vcAOLProp = VCAOLProp;
|
|
const char* vcAppleLinkProp = VCAppleLinkProp;
|
|
const char* vcATTMailProp = VCATTMailProp;
|
|
const char* vcCISProp = VCCISProp;
|
|
const char* vcEWorldProp = VCEWorldProp;
|
|
const char* vcInternetProp = VCInternetProp;
|
|
const char* vcIBMMailProp = VCIBMMailProp;
|
|
const char* vcMSNProp = VCMSNProp;
|
|
const char* vcMCIMailProp = VCMCIMailProp;
|
|
const char* vcPowerShareProp = VCPowerShareProp;
|
|
const char* vcProdigyProp = VCProdigyProp;
|
|
const char* vcTLXProp = VCTLXProp;
|
|
const char* vcX400Prop = VCX400Prop;
|
|
|
|
const char* vcGIFProp = VCGIFProp;
|
|
const char* vcCGMProp = VCCGMProp;
|
|
const char* vcWMFProp = VCWMFProp;
|
|
const char* vcBMPProp = VCBMPProp;
|
|
const char* vcMETProp = VCMETProp;
|
|
const char* vcPMBProp = VCPMBProp;
|
|
const char* vcDIBProp = VCDIBProp;
|
|
const char* vcPICTProp = VCPICTProp;
|
|
const char* vcTIFFProp = VCTIFFProp;
|
|
const char* vcAcrobatProp = VCAcrobatProp;
|
|
const char* vcPSProp = VCPSProp;
|
|
const char* vcJPEGProp = VCJPEGProp;
|
|
const char* vcQuickTimeProp = VCQuickTimeProp;
|
|
const char* vcMPEGProp = VCMPEGProp;
|
|
const char* vcMPEG2Prop = VCMPEG2Prop;
|
|
const char* vcAVIProp = VCAVIProp;
|
|
|
|
const char* vcWAVEProp = VCWAVEProp;
|
|
const char* vcAIFFProp = VCAIFFProp;
|
|
const char* vcPCMProp = VCPCMProp;
|
|
|
|
const char* vcX509Prop = VCX509Prop;
|
|
const char* vcPGPProp = VCPGPProp;
|
|
|
|
const char* vcNodeNameProp = VCNodeNameProp;
|
|
|
|
typedef struct {
|
|
const char *name;
|
|
unsigned long value;
|
|
} VC_FLAG_PAIR;
|
|
|
|
static VC_FLAG_PAIR generalFlags[] = {
|
|
vcDomesticProp, VC_DOM,
|
|
vcInternationalProp, VC_INTL,
|
|
vcPostalProp, VC_POSTAL,
|
|
vcParcelProp, VC_PARCEL,
|
|
vcHomeProp, VC_HOME,
|
|
vcWorkProp, VC_WORK,
|
|
vcPreferredProp, VC_PREF,
|
|
vcVoiceProp, VC_VOICE,
|
|
vcFaxProp, VC_FAX,
|
|
vcMessageProp, VC_MSG,
|
|
vcCellularProp, VC_CELL,
|
|
vcPagerProp, VC_PAGER,
|
|
vcBBSProp, VC_BBS,
|
|
vcModemProp, VC_MODEM,
|
|
vcCarProp, VC_CAR,
|
|
vcISDNProp, VC_ISDN,
|
|
vcVideoProp, VC_VIDEO,
|
|
vcBase64Prop, VC_BASE64,
|
|
NULL, NULL
|
|
};
|
|
|
|
static VC_FLAG_PAIR emailFlags[] = {
|
|
vcAOLProp, VC_AOL,
|
|
vcAppleLinkProp, VC_AppleLink,
|
|
vcATTMailProp, VC_ATTMail,
|
|
vcCISProp, VC_CIS,
|
|
vcEWorldProp, VC_eWorld,
|
|
vcInternetProp, VC_INTERNET,
|
|
vcIBMMailProp, VC_IBMMail,
|
|
vcMSNProp, VC_MSN,
|
|
vcMCIMailProp, VC_MCIMail,
|
|
vcPowerShareProp, VC_POWERSHARE,
|
|
vcProdigyProp, VC_PRODIGY,
|
|
vcTLXProp, VC_TLX,
|
|
vcX400Prop, VC_X400,
|
|
NULL, NULL
|
|
};
|
|
|
|
static VC_FLAG_PAIR videoFlags[] = {
|
|
vcGIFProp, VC_GIF,
|
|
vcCGMProp, VC_CGM,
|
|
vcWMFProp, VC_WMF,
|
|
vcBMPProp, VC_BMP,
|
|
vcMETProp, VC_MET,
|
|
vcPMBProp, VC_PMB,
|
|
vcDIBProp, VC_DIB,
|
|
vcPICTProp, VC_PICT,
|
|
vcTIFFProp, VC_TIFF,
|
|
vcAcrobatProp, VC_ACROBAT,
|
|
vcPSProp, VC_PS,
|
|
NULL, NULL
|
|
};
|
|
|
|
static VC_FLAG_PAIR audioFlags[] = {
|
|
vcWAVEProp, VC_WAV,
|
|
NULL, NULL
|
|
};
|
|
|
|
static const char *addrProps[] = {
|
|
vcExtAddressProp,
|
|
vcStreetAddressProp,
|
|
vcCityProp,
|
|
vcRegionProp,
|
|
vcPostalCodeProp,
|
|
vcCountryNameProp,
|
|
NULL
|
|
};
|
|
|
|
static const char *nameProps[] = {
|
|
vcFamilyNameProp,
|
|
vcGivenNameProp,
|
|
vcAdditionalNamesProp,
|
|
vcNamePrefixesProp,
|
|
vcNameSuffixesProp,
|
|
NULL
|
|
};
|
|
|
|
static const char *orgProps[] = {
|
|
vcOrgNameProp,
|
|
vcOrgUnitProp,
|
|
vcOrgUnit2Prop,
|
|
vcOrgUnit3Prop,
|
|
vcOrgUnit4Prop,
|
|
NULL
|
|
};
|
|
|
|
|
|
/**** Global Variables ****/
|
|
|
|
int msv_lineNum, msv_numErrors; /* yyerror() can use these */
|
|
|
|
static S32 curPos, inputLen;
|
|
static int pendingToken;
|
|
static const char *inputString;
|
|
static CFile* inputFile;
|
|
static BOOL stringExpected, flagExpected, inBinary, semiSpecial;
|
|
static CList *mapProps;
|
|
static char __huge *longString;
|
|
static S32 longStringLen, longStringMax;
|
|
static CList* global_vcList;
|
|
|
|
static CVCard *cardBuilt;
|
|
static CVCard* cardToBuild[MAXCARD];
|
|
static int curCard;
|
|
static CVCNode *bodyToBuild;
|
|
|
|
|
|
/**** External Functions ****/
|
|
|
|
CFUNCTIONS
|
|
|
|
extern void Parse_Debug(const char *s);
|
|
extern void yyerror(char *s);
|
|
|
|
END_CFUNCTIONS
|
|
|
|
|
|
/**** Private Forward Declarations ****/
|
|
|
|
CFUNCTIONS
|
|
|
|
/* A helpful utility for the rest of the app. */
|
|
CVCNode* FindOrCreatePart(CVCNode *node, const char *name);
|
|
|
|
static BOOL StrToFlags(const char *s, FLAGS_STRUCT *flags, VC_PTR_FLAGS capFlags);
|
|
static void StrCat(char *dst, const char *src1, const char *src2);
|
|
static void ExpectString(void);
|
|
static BOOL Parse_Assoc(
|
|
const char *groups, const char *prop, FLAGS_STRUCT *flags,
|
|
const char *value);
|
|
static BOOL Parse_SemiValue(
|
|
const char *groups, const char *prop, FLAGS_STRUCT *flags,
|
|
char *parts, const char **props);
|
|
static BOOL Parse_TwoPart(
|
|
const char *groups, const char *prop, FLAGS_STRUCT *flags,
|
|
char *parts);
|
|
static BOOL Parse_Agent(
|
|
const char *groups, const char *prop, FLAGS_STRUCT *flags,
|
|
CVCard *agentCard);
|
|
static void AddAssoc(CList *table, const char *key, const char *value);
|
|
/*static void SetAssoc(CList *table, const char *key, const char *value);*/
|
|
static const char *Lookup(CList *table, const char *key);
|
|
static void RemoveAll(CList *table);
|
|
static void InitMapProps(void);
|
|
int yyparse();
|
|
static U8 __huge * DataFromBase64(
|
|
const char __huge *str, S32 strLen, S32 *len);
|
|
static BOOL PushVCard();
|
|
static CVCard* PopVCard();
|
|
static int flagslen(const char **flags);
|
|
static BOOL FlagsHave(FLAGS_STRUCT *flags, const char *propName);
|
|
static void AddBoolProps(CVCNode *node, FLAGS_STRUCT *flags);
|
|
|
|
END_CFUNCTIONS
|
|
|
|
#line 428 "msv.y"
|
|
typedef union
|
|
{
|
|
char str[MAXTOKEN];
|
|
FLAGS_STRUCT flags;
|
|
CVCard *vCard;
|
|
} YYSTYPE;
|
|
#line 478 "msv_tab.cpp"
|
|
#define OBRKT 257
|
|
#define CBRKT 258
|
|
#define EQ 259
|
|
#define COLON 260
|
|
#define DOT 261
|
|
#define COMMA 262
|
|
#define SEMI 263
|
|
#define SPACE 264
|
|
#define HTAB 265
|
|
#define LINESEP 266
|
|
#define NEWLINE 267
|
|
#define VCARD 268
|
|
#define BBINDATA 269
|
|
#define EBINDATA 270
|
|
#define BKSLASH 271
|
|
#define TERM 272
|
|
#define WORD 273
|
|
#define STRING 274
|
|
#define PROP 275
|
|
#define PROP_A 276
|
|
#define PROP_N 277
|
|
#define PROP_O 278
|
|
#define PROP_AGENT 279
|
|
#define FLAG 280
|
|
#define YYERRCODE 256
|
|
short msv_lhs[] = { -1,
|
|
11, 11, 11, 12, 12, 13, 13, 13, 13, 13,
|
|
13, 13, 0, 0, 0, 0, 14, 16, 10, 15,
|
|
15, 19, 17, 20, 17, 21, 17, 22, 17, 17,
|
|
17, 7, 7, 24, 24, 24, 24, 18, 18, 6,
|
|
6, 6, 25, 26, 5, 1, 1, 1, 1, 8,
|
|
8, 2, 2, 3, 3, 3, 3, 4, 4, 9,
|
|
27, 9, 9, 23,
|
|
};
|
|
short msv_len[] = { 2,
|
|
3, 2, 1, 2, 1, 2, 2, 2, 2, 2,
|
|
1, 1, 3, 2, 2, 1, 0, 0, 8, 2,
|
|
1, 0, 8, 0, 8, 0, 8, 0, 8, 8,
|
|
2, 1, 1, 2, 2, 1, 1, 1, 1, 1,
|
|
1, 1, 0, 0, 9, 4, 3, 1, 2, 3,
|
|
1, 3, 1, 2, 3, 1, 1, 3, 1, 3,
|
|
0, 3, 1, 0,
|
|
};
|
|
short msv_defred[] = { 0,
|
|
0, 11, 0, 12, 0, 3, 0, 0, 5, 8,
|
|
6, 17, 7, 9, 10, 2, 0, 0, 4, 0,
|
|
1, 0, 0, 48, 0, 0, 33, 49, 0, 18,
|
|
0, 0, 46, 0, 36, 37, 59, 0, 0, 0,
|
|
21, 57, 0, 31, 0, 0, 0, 0, 0, 0,
|
|
19, 20, 34, 35, 0, 61, 0, 63, 0, 0,
|
|
0, 0, 58, 0, 0, 0, 0, 39, 0, 0,
|
|
0, 0, 0, 62, 60, 22, 24, 26, 28, 0,
|
|
0, 0, 0, 0, 0, 0, 43, 0, 41, 0,
|
|
42, 51, 0, 0, 0, 0, 0, 23, 0, 25,
|
|
27, 29, 30, 0, 50, 53, 0, 0, 52, 0,
|
|
0, 0, 45,
|
|
};
|
|
short msv_dgoto[] = { 5,
|
|
25, 107, 38, 39, 89, 90, 92, 93, 57, 6,
|
|
7, 8, 9, 20, 40, 32, 41, 67, 81, 82,
|
|
83, 84, 68, 69, 97, 110, 65,
|
|
};
|
|
short msv_sindex[] = { -227,
|
|
-224, 0, -221, 0, 0, 0, -227, -227, 0, 0,
|
|
0, 0, 0, 0, 0, 0, -227, -227, 0, -236,
|
|
0, -227, -257, 0, -237, -214, 0, 0, -212, 0,
|
|
-218, -254, 0, -196, 0, 0, 0, -184, -201, -241,
|
|
0, 0, -206, 0, -170, -170, -170, -170, -170, -145,
|
|
0, 0, 0, 0, -130, 0, -177, 0, -177, -177,
|
|
-177, -177, 0, -145, -148, -147, -125, 0, -243, -124,
|
|
-123, -122, -121, 0, 0, 0, 0, 0, 0, -118,
|
|
-185, -236, -236, -236, -128, -190, 0, -237, 0, -120,
|
|
0, 0, -143, -142, -141, -119, -117, 0, -236, 0,
|
|
0, 0, 0, -133, 0, 0, -116, -132, 0, -190,
|
|
-127, -190, 0,
|
|
};
|
|
short msv_rindex[] = { 0,
|
|
0, 0, 0, 0, 0, 0, 144, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 145, 148, 0, -115,
|
|
0, 152, 0, 0, -137, 0, 0, 0, 0, 0,
|
|
-198, -179, 0, 0, 0, 0, 0, 0, 0, -179,
|
|
0, 0, -174, 0, -193, -193, -193, -193, -193, -169,
|
|
0, 0, 0, 0, 0, 0, -106, 0, -106, -106,
|
|
-106, -106, 0, -164, 0, 0, 0, 0, -217, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
-115, -136, -136, -136, 0, -115, 0, -112, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, -136, 0,
|
|
0, 0, 0, 0, 0, 0, 0, -187, 0, -114,
|
|
0, -115, 0,
|
|
};
|
|
short msv_gindex[] = { 0,
|
|
74, 0, 0, 114, 0, 0, -19, -2, 70, -4,
|
|
150, 32, 29, 0, 0, 0, 119, -55, 0, 0,
|
|
0, 0, -20, -24, 0, 0, 0,
|
|
};
|
|
#define YYTABLESIZE 159
|
|
short msv_table[] = { 27,
|
|
26, 34, 16, 70, 71, 72, 73, 43, 28, 35,
|
|
36, 42, 21, 16, 34, 43, 51, 21, 37, 42,
|
|
53, 54, 35, 36, 58, 58, 58, 58, 58, 1,
|
|
96, 37, 10, 29, 23, 14, 19, 24, 17, 2,
|
|
3, 38, 11, 12, 4, 19, 15, 13, 38, 22,
|
|
19, 30, 38, 31, 111, 33, 113, 53, 54, 50,
|
|
91, 27, 27, 27, 47, 64, 37, 47, 64, 44,
|
|
64, 64, 47, 35, 36, 86, 44, 44, 27, 105,
|
|
94, 95, 44, 87, 66, 23, 35, 36, 24, 56,
|
|
45, 46, 47, 48, 49, 64, 64, 64, 64, 64,
|
|
56, 56, 56, 56, 56, 54, 54, 54, 54, 54,
|
|
55, 55, 55, 55, 55, 59, 60, 61, 62, 99,
|
|
99, 99, 100, 101, 102, 32, 64, 63, 32, 64,
|
|
64, 74, 75, 76, 77, 78, 79, 80, 85, 12,
|
|
106, 109, 112, 16, 15, 98, 103, 14, 104, 108,
|
|
64, 13, 64, 40, 88, 64, 55, 18, 52,
|
|
};
|
|
short msv_check[] = { 20,
|
|
20, 256, 7, 59, 60, 61, 62, 32, 266, 264,
|
|
265, 32, 17, 18, 256, 40, 258, 22, 273, 40,
|
|
264, 265, 264, 265, 45, 46, 47, 48, 49, 257,
|
|
86, 273, 257, 271, 271, 257, 8, 274, 7, 267,
|
|
268, 259, 267, 268, 272, 17, 268, 272, 266, 18,
|
|
22, 266, 270, 266, 110, 274, 112, 264, 265, 261,
|
|
81, 82, 83, 84, 263, 259, 273, 266, 262, 266,
|
|
264, 265, 271, 264, 265, 80, 264, 265, 99, 99,
|
|
83, 84, 270, 269, 262, 271, 264, 265, 274, 260,
|
|
275, 276, 277, 278, 279, 275, 276, 277, 278, 279,
|
|
275, 276, 277, 278, 279, 275, 276, 277, 278, 279,
|
|
275, 276, 277, 278, 279, 46, 47, 48, 49, 263,
|
|
263, 263, 266, 266, 266, 263, 263, 273, 266, 266,
|
|
261, 280, 280, 259, 259, 259, 259, 259, 257, 268,
|
|
274, 274, 270, 0, 0, 266, 266, 0, 266, 266,
|
|
266, 0, 259, 266, 81, 270, 43, 8, 40,
|
|
};
|
|
#define YYFINAL 5
|
|
#ifndef YYDEBUG
|
|
#define YYDEBUG 0
|
|
#endif
|
|
#define YYMAXTOKEN 280
|
|
#if YYDEBUG
|
|
char *msv_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,"OBRKT","CBRKT","EQ","COLON",
|
|
"DOT","COMMA","SEMI","SPACE","HTAB","LINESEP","NEWLINE","VCARD","BBINDATA",
|
|
"EBINDATA","BKSLASH","TERM","WORD","STRING","PROP","PROP_A","PROP_N","PROP_O",
|
|
"PROP_AGENT","FLAG",
|
|
};
|
|
char *msv_rule[] = {
|
|
"$accept : msv",
|
|
"vcards : vcards junk vcard",
|
|
"vcards : vcards vcard",
|
|
"vcards : vcard",
|
|
"junk : junk atom",
|
|
"junk : atom",
|
|
"atom : OBRKT NEWLINE",
|
|
"atom : OBRKT TERM",
|
|
"atom : OBRKT OBRKT",
|
|
"atom : VCARD OBRKT",
|
|
"atom : VCARD VCARD",
|
|
"atom : NEWLINE",
|
|
"atom : TERM",
|
|
"msv : junk vcards junk",
|
|
"msv : junk vcards",
|
|
"msv : vcards junk",
|
|
"msv : vcards",
|
|
"$$1 :",
|
|
"$$2 :",
|
|
"vcard : OBRKT VCARD $$1 opt_str LINESEP $$2 items CBRKT",
|
|
"items : items item",
|
|
"items : item",
|
|
"$$3 :",
|
|
"item : groups PROP flags opt_ws EQ $$3 value LINESEP",
|
|
"$$4 :",
|
|
"item : groups PROP_A flags opt_ws EQ $$4 semistrings LINESEP",
|
|
"$$5 :",
|
|
"item : groups PROP_N flags opt_ws EQ $$5 semistrings LINESEP",
|
|
"$$6 :",
|
|
"item : groups PROP_O flags opt_ws EQ $$6 semistrings LINESEP",
|
|
"item : groups PROP_AGENT flags opt_ws EQ vcard opt_ws LINESEP",
|
|
"item : error LINESEP",
|
|
"opt_str : string",
|
|
"opt_str : empty",
|
|
"ws : ws SPACE",
|
|
"ws : ws HTAB",
|
|
"ws : SPACE",
|
|
"ws : HTAB",
|
|
"opt_ws : ws",
|
|
"opt_ws : empty",
|
|
"value : string",
|
|
"value : binary",
|
|
"value : empty",
|
|
"$$7 :",
|
|
"$$8 :",
|
|
"binary : BBINDATA $$7 LINESEP lines LINESEP $$8 opt_ws EBINDATA opt_ws",
|
|
"string : string BKSLASH LINESEP STRING",
|
|
"string : string BKSLASH LINESEP",
|
|
"string : STRING",
|
|
"string : BKSLASH LINESEP",
|
|
"semistrings : semistrings SEMI opt_str",
|
|
"semistrings : opt_str",
|
|
"lines : lines LINESEP STRING",
|
|
"lines : STRING",
|
|
"groups : grouplist DOT",
|
|
"groups : ws grouplist DOT",
|
|
"groups : ws",
|
|
"groups : empty",
|
|
"grouplist : grouplist DOT WORD",
|
|
"grouplist : WORD",
|
|
"flags : flags COMMA FLAG",
|
|
"$$9 :",
|
|
"flags : COLON $$9 FLAG",
|
|
"flags : empty",
|
|
"empty :",
|
|
};
|
|
#endif
|
|
#ifdef YYSTACKSIZE
|
|
#undef YYMAXDEPTH
|
|
#define YYMAXDEPTH YYSTACKSIZE
|
|
#else
|
|
#ifdef YYMAXDEPTH
|
|
#define YYSTACKSIZE YYMAXDEPTH
|
|
#else
|
|
#define YYSTACKSIZE 500
|
|
#define YYMAXDEPTH 500
|
|
#endif
|
|
#endif
|
|
int yydebug;
|
|
int yynerrs;
|
|
int yyerrflag;
|
|
int yychar;
|
|
short *yyssp;
|
|
YYSTYPE *yyvsp;
|
|
YYSTYPE *p_yyval;
|
|
YYSTYPE *p_yylval;
|
|
short *yyss; /* YYSTACKSIZE long */
|
|
YYSTYPE *yyvs; /* YYSTACKSIZE long */
|
|
#undef yylval
|
|
#define yylval (*p_yylval)
|
|
#undef yyval
|
|
#define yyval (*p_yyval)
|
|
#define yystacksize YYSTACKSIZE
|
|
CFUNCTIONS
|
|
#line 665 "msv.y"
|
|
|
|
/***************************************************************************/
|
|
/*** The lexical analyzer ****/
|
|
/***************************************************************************/
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
#define IsLineBreak(_c) ((_c == '\n') || (_c == '\r'))
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
/* This appends onto yylval.str, unless MAXTOKEN has been exceeded.
|
|
* In that case, yylval.str is set to 0 length, and longString is used.
|
|
*/
|
|
static void AppendCharToToken(char c, S32 *len)
|
|
{
|
|
if (*len < MAXTOKEN - 1) {
|
|
yylval.str[*len] = c; yylval.str[++(*len)] = 0;
|
|
} else if (*len == MAXTOKEN - 1) { /* copy to "longString" */
|
|
if (!longString) {
|
|
longStringMax = MAXTOKEN * 2;
|
|
longString = HNEW(char, longStringMax);
|
|
}
|
|
memcpy(longString, yylval.str, (size_t)*len + 1);
|
|
longString[*len] = c; longString[++(*len)] = 0;
|
|
yylval.str[0] = 0;
|
|
longStringLen = *len;
|
|
} else {
|
|
if (longStringLen == longStringMax - 1) {
|
|
char __huge *newStr = HNEW(char, longStringMax * 2);
|
|
_hmemcpy((U8 __huge *)newStr, (U8 __huge *)longString, longStringLen + 1);
|
|
longStringMax *= 2;
|
|
HFREE(longString);
|
|
longString = newStr;
|
|
}
|
|
longString[*len] = c; longString[++(*len)] = 0;
|
|
longStringLen = *len;
|
|
}
|
|
}
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
/* StrCat appends onto dst, ensuring that longString is used appropriately.
|
|
* src1 may be of 0 length, in which case "longString" should be used.
|
|
* "longString" would never be used for src2.
|
|
*/
|
|
static void StrCat(char *dst, const char *src1, const char *src2)
|
|
{
|
|
S32 src1Len = strlen(src1);
|
|
S32 src2Len = strlen(src2);
|
|
S32 req;
|
|
|
|
if (!src1Len && longString) {
|
|
src1Len = longStringLen;
|
|
src1 = longString;
|
|
}
|
|
if ((req = src1Len + src2Len + 1) > MAXTOKEN) {
|
|
if (longString) { /* longString == src1 */
|
|
if (longStringMax - longStringLen < src2Len) {
|
|
/* since src2Len must be < MAXTOKEN, doubling longString
|
|
is guaranteed to be enough room */
|
|
char __huge *newStr = HNEW(char, longStringMax * 2);
|
|
_hmemcpy((U8 __huge *)newStr, (U8 __huge *)longString, longStringLen + 1);
|
|
longStringMax *= 2;
|
|
HFREE(longString);
|
|
longString = newStr;
|
|
}
|
|
_hmemcpy((U8 __huge *)(longString + longStringLen), (U8 __huge *)src2, src2Len + 1);
|
|
longStringLen += src2Len;
|
|
} else { /* haven't yet used longString, so set it up */
|
|
longStringMax = MAXTOKEN * 2;
|
|
longString = HNEW(char, longStringMax);
|
|
memcpy(longString, src1, (size_t)src1Len + 1);
|
|
memcpy(longString + src1Len, src2, (size_t)src2Len + 1);
|
|
longStringLen = src1Len + src2Len;
|
|
}
|
|
*dst = 0; /* indicate result is in longString */
|
|
} else { /* both will fit in MAXTOKEN, so src1 can't be longString */
|
|
if (dst != src1)
|
|
strcpy(dst, src1);
|
|
strcat(dst, src2);
|
|
}
|
|
}
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
/* Set up the lexor to parse a string value. */
|
|
static void ExpectString(void)
|
|
{
|
|
stringExpected = TRUE;
|
|
if (longString) {
|
|
HFREE(longString); longString = NULL;
|
|
longStringLen = 0;
|
|
}
|
|
flagExpected = FALSE;
|
|
}
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
#define FlushWithPending(_t) { \
|
|
if (len) { \
|
|
pendingToken = _t; \
|
|
goto Pending; \
|
|
} else { \
|
|
msv_lineNum += ((_t == LINESEP) || (_t == NEWLINE)); \
|
|
return _t; \
|
|
} \
|
|
}
|
|
|
|
static int peekn;
|
|
static char peekc[2];
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
static char lex_getc()
|
|
{
|
|
if (peekn) {
|
|
return peekc[--peekn];
|
|
}
|
|
if (curPos == inputLen)
|
|
return EOF;
|
|
else if (inputString)
|
|
return *(inputString + curPos++);
|
|
else {
|
|
char result;
|
|
return inputFile->Read(&result, 1) == 1 ? result : EOF;
|
|
}
|
|
}
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
static void lex_ungetc(char c)
|
|
{
|
|
ASSERT(peekn < 2);
|
|
peekc[peekn++] = c;
|
|
}
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
/* Collect up a string value. */
|
|
static int LexString()
|
|
{
|
|
char cur;
|
|
S32 len = 0;
|
|
|
|
do {
|
|
cur = lex_getc();
|
|
switch (cur) {
|
|
case '\\': { /* check for CR-LF combos after the backslash */
|
|
char next = lex_getc();
|
|
if (semiSpecial && (next == ';')) {
|
|
AppendCharToToken(';', &len);
|
|
} else if (!inBinary && ((next == '\r') || (next == '\n'))) {
|
|
char next2;
|
|
next2 = lex_getc();
|
|
if (!(((next2 == '\r') || (next2 == '\n')) && (next != next2)))
|
|
lex_ungetc(next2);
|
|
lex_ungetc(next); /* so that we'll pick up the LINESEP again */
|
|
pendingToken = BKSLASH;
|
|
goto EndString;
|
|
} else if (!inBinary && (next == '\\')) {
|
|
/* double backslash detected */
|
|
next = lex_getc();
|
|
if ((next == '\r') || (next == '\n')) {
|
|
/* found \\ at end of line */
|
|
char next2;
|
|
next2 = lex_getc();
|
|
if (!(((next2 == '\r') || (next2 == '\n')) && (next != next2)))
|
|
lex_ungetc(next2);
|
|
AppendCharToToken('\\', &len);
|
|
pendingToken = LINESEP;
|
|
goto EndString;
|
|
}
|
|
/* within a line */
|
|
AppendCharToToken('\\', &len);
|
|
lex_ungetc(next); /* now pointing at second backslash */
|
|
/* here we let the top level switch handle it the next
|
|
time around */
|
|
} else {
|
|
AppendCharToToken(cur, &len);
|
|
}
|
|
break;
|
|
} /* backslash */
|
|
case ';':
|
|
if (semiSpecial) {
|
|
pendingToken = SEMI;
|
|
goto EndString;
|
|
} else
|
|
AppendCharToToken(cur, &len);
|
|
break;
|
|
case '\r':
|
|
case '\n': {
|
|
char next = lex_getc();
|
|
if (!(((next == '\r') || (next == '\n')) && (cur != next)))
|
|
lex_ungetc(next);
|
|
pendingToken = LINESEP;
|
|
goto EndString;
|
|
}
|
|
case (char)EOF:
|
|
pendingToken = EOF;
|
|
break;
|
|
default:
|
|
AppendCharToToken(cur, &len);
|
|
break;
|
|
} /* switch */
|
|
} while (cur != (char)EOF);
|
|
|
|
EndString:
|
|
if (strncmp(yylval.str + strspn(yylval.str, " \t"), "<bindata>", 9) == 0)
|
|
return BBINDATA;
|
|
else if (strncmp(yylval.str + strspn(yylval.str, " \t"), "</bindata>", 10) == 0)
|
|
return EBINDATA;
|
|
else if (!len) {
|
|
/* must have hit something immediately, in which case pendingToken
|
|
is set. return it. */
|
|
int result = pendingToken;
|
|
pendingToken = 0;
|
|
msv_lineNum += ((result == LINESEP) || (result == NEWLINE));
|
|
return result;
|
|
}
|
|
|
|
return STRING;
|
|
} /* LexString */
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
/*
|
|
* Read chars from the input.
|
|
* Return one of the token types (or -1 for EOF).
|
|
* Set yylval to indicate the value of the token, if any.
|
|
*/
|
|
int msv_lex();
|
|
int msv_lex()
|
|
{
|
|
char cur;
|
|
S32 len = 0;
|
|
|
|
if (pendingToken) {
|
|
int result = pendingToken;
|
|
pendingToken = 0;
|
|
msv_lineNum += ((result == LINESEP) || (result == NEWLINE));
|
|
return result;
|
|
}
|
|
|
|
yylval.str[0] = 0;
|
|
|
|
if (stringExpected)
|
|
return LexString();
|
|
else if (curCard == -1) {
|
|
do {
|
|
cur = lex_getc();
|
|
switch (cur) {
|
|
case '[': FlushWithPending(OBRKT);
|
|
case ' ':
|
|
case '\t':
|
|
if (len) goto Pending;
|
|
break;
|
|
case '\r':
|
|
case '\n': {
|
|
char next = lex_getc();
|
|
if (!(((next == '\r') || (next == '\n')) && (cur != next)))
|
|
lex_ungetc(next);
|
|
FlushWithPending(NEWLINE);
|
|
}
|
|
case (char)EOF: FlushWithPending(EOF);
|
|
default:
|
|
yylval.str[len] = cur; yylval.str[++len] = 0;
|
|
break;
|
|
} /* switch */
|
|
} while (len < MAXTOKEN-1);
|
|
goto Pending;
|
|
}
|
|
|
|
do {
|
|
cur = lex_getc();
|
|
switch (cur) {
|
|
case '[': FlushWithPending(OBRKT);
|
|
case ']': FlushWithPending(CBRKT);
|
|
case '=': FlushWithPending(EQ);
|
|
case ':': FlushWithPending(COLON);
|
|
case '.': FlushWithPending(DOT);
|
|
case ',': FlushWithPending(COMMA);
|
|
case ' ': FlushWithPending(SPACE);
|
|
case '\t': FlushWithPending(HTAB);
|
|
case '\\': FlushWithPending(BKSLASH);
|
|
case '\r':
|
|
case '\n': {
|
|
char next = lex_getc();
|
|
if (!(((next == '\r') || (next == '\n')) && (cur != next)))
|
|
lex_ungetc(next);
|
|
FlushWithPending(LINESEP);
|
|
}
|
|
case (char)EOF: FlushWithPending(EOF);
|
|
default:
|
|
yylval.str[len] = cur; yylval.str[++len] = 0;
|
|
break;
|
|
} /* switch */
|
|
} while (len < MAXTOKEN-1);
|
|
return WORD;
|
|
|
|
Pending:
|
|
{
|
|
if (strcmp(yylval.str, "vCard") == 0) {
|
|
if (pendingToken == NEWLINE)
|
|
pendingToken = LINESEP;
|
|
return VCARD;
|
|
}
|
|
if (flagExpected) {
|
|
FLAGS_STRUCT flags;
|
|
if (StrToFlags(yylval.str, &flags, NULL)) {
|
|
yylval.flags = flags;
|
|
return FLAG;
|
|
} else {
|
|
char buf[40];
|
|
sprintf(buf, "unknown flag name \"%s\"", yylval.str);
|
|
yyerror(buf);
|
|
}
|
|
} else if ((curCard != -1) && Lookup(mapProps, yylval.str)
|
|
|| (strnicmp(yylval.str, "X-", 2) == 0)) {
|
|
#if YYDEBUG
|
|
if (yydebug) {
|
|
char buf[80];
|
|
sprintf(buf, "property \"%s\"\n", yylval.str);
|
|
Parse_Debug(buf);
|
|
}
|
|
#endif
|
|
/* check for special props that are tokens */
|
|
if (stricmp(yylval.str, "A") == 0)
|
|
return PROP_A;
|
|
else if (stricmp(yylval.str, "N") == 0)
|
|
return PROP_N;
|
|
else if (stricmp(yylval.str, "O") == 0)
|
|
return PROP_O;
|
|
else if (stricmp(yylval.str, "AGENT") == 0)
|
|
return PROP_AGENT;
|
|
else
|
|
return PROP;
|
|
}
|
|
}
|
|
return (curCard == -1) ? TERM : WORD;
|
|
}
|
|
|
|
|
|
/***************************************************************************/
|
|
/*** Public Functions ****/
|
|
/***************************************************************************/
|
|
|
|
static BOOL Parse_MSVHelper(CList *vcList)
|
|
{
|
|
BOOL success = FALSE;
|
|
|
|
curCard = -1;
|
|
msv_numErrors = 0;
|
|
InitMapProps();
|
|
pendingToken = 0;
|
|
msv_lineNum = 1;
|
|
peekn = 0;
|
|
global_vcList = vcList;
|
|
|
|
stringExpected = flagExpected = FALSE;
|
|
longString = NULL; longStringLen = 0; longStringMax = 0;
|
|
|
|
/* this winds up invoking the Parse_* callouts. */
|
|
if (yyparse() != 0)
|
|
goto Done;
|
|
|
|
success = TRUE;
|
|
|
|
Done:
|
|
if (longString) { HFREE(longString); longString = NULL; }
|
|
RemoveAll(mapProps); delete mapProps; mapProps = NULL;
|
|
if (!success) {
|
|
for (int i = 0; i < MAXCARD; i++)
|
|
if (cardToBuild[i]) {
|
|
delete cardToBuild[i];
|
|
cardToBuild[i] = NULL;
|
|
}
|
|
if (cardBuilt) delete cardBuilt;
|
|
}
|
|
cardBuilt = NULL;
|
|
return success;
|
|
}
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
/* This is the public API to call to parse a buffer and create a CVCard. */
|
|
BOOL Parse_MSV(
|
|
const char *input, /* In */
|
|
S32 len, /* In */
|
|
CVCard **card) /* Out */
|
|
{
|
|
CList vcList;
|
|
BOOL result;
|
|
|
|
inputString = input;
|
|
inputLen = len;
|
|
curPos = 0;
|
|
inputFile = NULL;
|
|
result = Parse_MSVHelper(&vcList);
|
|
if (vcList.GetCount()) {
|
|
BOOL first = TRUE;
|
|
for (CLISTPOSITION pos = vcList.GetHeadPosition(); pos; ) {
|
|
CVCard *vCard = (CVCard *)vcList.GetNext(pos);
|
|
if (first) {
|
|
*card = vCard;
|
|
first = FALSE;
|
|
} else
|
|
delete vCard;
|
|
}
|
|
} else
|
|
*card = NULL;
|
|
return result;
|
|
}
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
/* This is the public API to call to parse a buffer and create a CVCard. */
|
|
extern BOOL Parse_Many_MSV(
|
|
const char *input, /* In */
|
|
S32 len, /* In */
|
|
CList *vcList) /* Out: CVCard objects added to existing list */
|
|
{
|
|
inputString = input;
|
|
inputLen = len;
|
|
curPos = 0;
|
|
inputFile = NULL;
|
|
return Parse_MSVHelper(vcList);
|
|
}
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
/* This is the public API to call to parse a buffer and create a CVCard. */
|
|
BOOL Parse_MSV_FromFile(
|
|
CFile *file, /* In */
|
|
CVCard **card) /* Out */
|
|
{
|
|
CList vcList;
|
|
BOOL result;
|
|
DWORD startPos;
|
|
|
|
inputString = NULL;
|
|
inputLen = -1;
|
|
curPos = 0;
|
|
inputFile = file;
|
|
startPos = file->GetPosition();
|
|
result = Parse_MSVHelper(&vcList);
|
|
if (vcList.GetCount()) {
|
|
BOOL first = TRUE;
|
|
for (CLISTPOSITION pos = vcList.GetHeadPosition(); pos; ) {
|
|
CVCard *vCard = (CVCard *)vcList.GetNext(pos);
|
|
if (first) {
|
|
*card = vCard;
|
|
first = FALSE;
|
|
} else
|
|
delete vCard;
|
|
}
|
|
} else {
|
|
*card = NULL;
|
|
file->Seek(startPos, CFile::begin);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
extern BOOL Parse_Many_MSV_FromFile(
|
|
CFile *file, /* In */
|
|
CList *vcList) /* Out: CVCard objects added to existing list */
|
|
{
|
|
DWORD startPos;
|
|
BOOL result;
|
|
|
|
inputString = NULL;
|
|
inputLen = -1;
|
|
curPos = 0;
|
|
inputFile = file;
|
|
startPos = file->GetPosition();
|
|
if (!(result = Parse_MSVHelper(vcList)))
|
|
file->Seek(startPos, CFile::begin);
|
|
return result;
|
|
}
|
|
|
|
|
|
/***************************************************************************/
|
|
/*** Parser Callout Functions ****/
|
|
/***************************************************************************/
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
static void YYDebug(const char *s)
|
|
{
|
|
Parse_Debug(s);
|
|
}
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
static BOOL StrToFlags(const char *s, FLAGS_STRUCT *flags, VC_PTR_FLAGS capFlags)
|
|
{
|
|
int i;
|
|
|
|
memset(flags, 0, sizeof(*flags));
|
|
|
|
if (strnicmp(s, "X-", 2) == 0) {
|
|
strcpy(flags->extended, s);
|
|
return TRUE;
|
|
}
|
|
|
|
for (i = 0; generalFlags[i].name; i++)
|
|
if (stricmp(s, strrchr(generalFlags[i].name, '/') + 1) == 0) {
|
|
flags->known[0] = generalFlags[i].name;
|
|
if (capFlags) capFlags->general |= generalFlags[i].value;
|
|
return TRUE;
|
|
}
|
|
for (i = 0; emailFlags[i].name; i++)
|
|
if (stricmp(s, strrchr(emailFlags[i].name, '/') + 1) == 0) {
|
|
flags->known[0] = emailFlags[i].name;
|
|
if (capFlags)
|
|
capFlags->email = (VC_EMAIL_TYPE)emailFlags[i].value;
|
|
return TRUE;
|
|
}
|
|
for (i = 0; videoFlags[i].name; i++)
|
|
if (stricmp(s, strrchr(videoFlags[i].name, '/') + 1) == 0) {
|
|
flags->known[0] = videoFlags[i].name;
|
|
if (capFlags)
|
|
capFlags->video = (VC_VIDEO_TYPE)videoFlags[i].value;
|
|
return TRUE;
|
|
}
|
|
if (stricmp(s, "WAV") == 0) {
|
|
flags->known[0] = audioFlags[0].name;
|
|
if (capFlags)
|
|
capFlags->audio = (VC_AUDIO_TYPE)audioFlags[0].value;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL NeedsQP(const char* str)
|
|
{
|
|
while (*str) {
|
|
if (!((*str >= 32 && *str <= 60) || (*str >= 62 && *str <= 126)))
|
|
return TRUE;
|
|
str++;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
static BOOL Parse_Assoc(
|
|
const char *groups, const char *prop, FLAGS_STRUCT *flags, const char *value)
|
|
{
|
|
CVCNode *node = NULL;
|
|
const char *propName;
|
|
const char *val = *value ? value : longString;
|
|
S32 valLen = *value ? strlen(value) : longStringLen;
|
|
|
|
if (!valLen)
|
|
return TRUE; /* don't treat an empty value as a syntax error */
|
|
|
|
propName = Lookup(mapProps, prop);
|
|
/* prop is a word like "PN", and propName is now */
|
|
/* the real prop name of the form "+//ISBN 1-887687-00-9::versit..." */
|
|
if (*groups) {
|
|
node = FindOrCreatePart(bodyToBuild, groups);
|
|
} else { /* this is a "top level" property name */
|
|
node = bodyToBuild->AddPart();
|
|
}
|
|
|
|
if (!propName) { /* it's an extended property */
|
|
if (FlagsHave(flags, vcBase64Prop)) {
|
|
U8 __huge *bytes;
|
|
S32 len;
|
|
bytes = DataFromBase64(val, valLen, &len);
|
|
if (bytes) {
|
|
node->AddProp(new CVCProp(prop, vcOctetsType, bytes, len));
|
|
HFREE(bytes);
|
|
AddBoolProps(node, flags);
|
|
} else
|
|
return FALSE;
|
|
} else {
|
|
node->AddStringProp(prop, value);
|
|
AddBoolProps(node, flags);
|
|
node->AddBoolProp(vcQuotedPrintableProp);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
if ((strcmp(propName, vcLogoProp) == 0)
|
|
|| (strcmp(propName, vcPhotoProp) == 0)) {
|
|
if (FlagsHave(flags, vcGIFProp) && FlagsHave(flags, vcBase64Prop)) {
|
|
U8 *bytes;
|
|
S32 len;
|
|
bytes = DataFromBase64(val, valLen, &len);
|
|
if (bytes) {
|
|
node->AddProp(new CVCProp(propName, VCGIFType, bytes, len));
|
|
HFREE(bytes);
|
|
AddBoolProps(node, flags);
|
|
} else
|
|
return FALSE;
|
|
}
|
|
} else if (strcmp(propName, vcPronunciationProp) == 0) {
|
|
if (FlagsHave(flags, vcBase64Prop)) {
|
|
if (FlagsHave(flags, vcWAVEProp) && FlagsHave(flags, vcBase64Prop)) {
|
|
U8 __huge *bytes;
|
|
S32 len;
|
|
bytes = DataFromBase64(val, valLen, &len);
|
|
if (bytes) {
|
|
node->AddProp(new CVCProp(propName, VCWAVType, bytes, len));
|
|
HFREE(bytes);
|
|
AddBoolProps(node, flags);
|
|
} else
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
node->AddStringProp(propName, value);
|
|
AddBoolProps(node, flags);
|
|
if (NeedsQP(value))
|
|
node->AddBoolProp(vcQuotedPrintableProp);
|
|
}
|
|
} else if ((strcmp(propName, vcPublicKeyProp) == 0)
|
|
&& FlagsHave(flags, vcBase64Prop)) {
|
|
U8 __huge *bytes;
|
|
S32 len;
|
|
bytes = DataFromBase64(val, valLen, &len);
|
|
if (bytes) {
|
|
node->AddProp(new CVCProp(propName, VCOctetsType, bytes, len));
|
|
HFREE(bytes);
|
|
AddBoolProps(node, flags);
|
|
} else
|
|
return FALSE;
|
|
} else {
|
|
node->AddStringProp(propName, value);
|
|
AddBoolProps(node, flags);
|
|
if (NeedsQP(value))
|
|
node->AddBoolProp(vcQuotedPrintableProp);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
static BOOL Parse_SemiValue(
|
|
const char *groups, const char *prop, FLAGS_STRUCT *flags,
|
|
char *parts, const char **props)
|
|
{
|
|
CVCNode *node = NULL;
|
|
const char *propName = Lookup(mapProps, prop);
|
|
char *p = *parts ? parts : longString;
|
|
int i = 0;
|
|
char *sep;
|
|
BOOL needsQP = FALSE;
|
|
|
|
if (!*p)
|
|
return TRUE; /* don't treat an empty value as a syntax error */
|
|
|
|
do {
|
|
if ((sep = strchr(p, '\177')))
|
|
*sep = 0;
|
|
if (strlen(p)) {
|
|
if (!node) {
|
|
if (*groups) {
|
|
node = FindOrCreatePart(bodyToBuild, groups);
|
|
} else { /* this is a "top level" property name */
|
|
node = bodyToBuild->AddPart();
|
|
}
|
|
}
|
|
node->AddStringProp(props[i], p);
|
|
needsQP |= NeedsQP(p);
|
|
}
|
|
if (sep)
|
|
p = sep + 1;
|
|
} while (sep && props[++i]);
|
|
|
|
if (node) {
|
|
AddBoolProps(node, flags);
|
|
if (needsQP)
|
|
node->AddBoolProp(vcQuotedPrintableProp);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
static BOOL Parse_Agent(
|
|
const char *groups, const char *prop, FLAGS_STRUCT *flags,
|
|
CVCard *agentCard)
|
|
{
|
|
CVCNode *node = NULL;
|
|
|
|
if (*groups) {
|
|
node = FindOrCreatePart(bodyToBuild, groups);
|
|
} else { /* this is a "top level" property name */
|
|
node = bodyToBuild->AddPart();
|
|
}
|
|
|
|
node->AddProp(new CVCProp(vcAgentProp, VCNextObjectType, agentCard));
|
|
AddBoolProps(node, flags);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/***************************************************************************/
|
|
/*** Private Utility Functions ****/
|
|
/***************************************************************************/
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
static void AddAssoc(CList *table, const char *key, const char *value)
|
|
{
|
|
AssocEntry *entry = new AssocEntry;
|
|
int len;
|
|
|
|
if ((len = strlen(key)) < MAXASSOCKEY)
|
|
strcpy(entry->key, key);
|
|
else {
|
|
strncpy(entry->key, key, MAXASSOCKEY - 1);
|
|
entry->key[MAXASSOCKEY - 1] = 0;
|
|
}
|
|
|
|
if ((len = strlen(value)) < MAXASSOCVALUE)
|
|
strcpy(entry->value, value);
|
|
else {
|
|
strncpy(entry->value, value, MAXASSOCVALUE - 1);
|
|
entry->value[MAXASSOCVALUE - 1] = 0;
|
|
}
|
|
table->AddTail(entry);
|
|
}
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
# if 0
|
|
static void SetAssoc(CList *table, const char *key, const char *value)
|
|
{
|
|
for (CLISTPOSITION pos = table->GetHeadPosition(); pos; ) {
|
|
AssocEntry *entry = (AssocEntry *)table->GetNext(pos);
|
|
if (strcmp(key, entry->key) == 0) {
|
|
int len;
|
|
if ((len = strlen(value)) < MAXASSOCVALUE)
|
|
strcpy(entry->value, value);
|
|
else {
|
|
strncpy(entry->value, value, MAXASSOCVALUE - 1);
|
|
entry->value[MAXASSOCVALUE - 1] = 0;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
AddAssoc(table, key, value);
|
|
}
|
|
#endif
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
static const char *Lookup(CList *table, const char *key)
|
|
{
|
|
for (CLISTPOSITION pos = table->GetHeadPosition(); pos; ) {
|
|
AssocEntry *entry = (AssocEntry *)table->GetNext(pos);
|
|
if (stricmp(key, entry->key) == 0)
|
|
return entry->value;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
static void RemoveAll(CList *table)
|
|
{
|
|
for (CLISTPOSITION pos = table->GetHeadPosition(); pos; ) {
|
|
AssocEntry *entry = (AssocEntry *)table->GetNext(pos);
|
|
delete entry;
|
|
}
|
|
table->RemoveAll();
|
|
}
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
/* "name" is of the form A.FOO.BAZ, where each is a node name. */
|
|
/* Walk the node tree starting at "node" looking for part objects */
|
|
/* having the given name for that level. At each level, if a part */
|
|
/* object isn't found, create one and give it that name. */
|
|
CVCNode* FindOrCreatePart(CVCNode *node, const char *name)
|
|
{
|
|
const char *remain = name;
|
|
char *dot = strchr(remain, '.');
|
|
int size, len;
|
|
char thisName[128];
|
|
wchar_t *thisUnicode;
|
|
CVCNode *thisNode = node, *thisPart;
|
|
CList *props;
|
|
|
|
do {
|
|
if (dot) {
|
|
len = dot - remain;
|
|
strncpy(thisName, remain, len);
|
|
*(thisName + len) = 0;
|
|
} else
|
|
strcpy(thisName, remain);
|
|
thisUnicode = FakeUnicode(thisName, &size);
|
|
props = thisNode->GetProps();
|
|
thisPart = NULL;
|
|
|
|
for (CLISTPOSITION pos = props->GetHeadPosition(); pos; ) {
|
|
CVCProp *prop = (CVCProp *)props->GetNext(pos);
|
|
|
|
if (strcmp(prop->GetName(), vcPartProp) != 0)
|
|
continue;
|
|
|
|
CVCNode *part = (CVCNode *)prop->FindValue(
|
|
VCNextObjectType)->GetValue();
|
|
CVCProp *nodeNameProp;
|
|
if (!(nodeNameProp = part->GetProp(vcNodeNameProp)))
|
|
continue;
|
|
if (wcscmp(thisUnicode, (wchar_t *)nodeNameProp->FindValue(VCStrIdxType)->GetValue()) == 0) {
|
|
thisPart = part;
|
|
break;
|
|
}
|
|
}
|
|
|
|
delete [] thisUnicode;
|
|
|
|
if (!thisPart) {
|
|
thisPart = thisNode->AddPart();
|
|
thisPart->AddStringProp(vcNodeNameProp, thisName);
|
|
}
|
|
|
|
if (!dot)
|
|
return thisPart;
|
|
|
|
remain = dot + 1;
|
|
dot = strchr(remain, '.');
|
|
thisNode = thisPart;
|
|
} while (TRUE);
|
|
return NULL; /* never reached */
|
|
} /* FindOrCreatePart */
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
static void InitMapProps(void)
|
|
{
|
|
mapProps = new CList;
|
|
|
|
AddAssoc(mapProps, "LOGO", vcLogoProp);
|
|
AddAssoc(mapProps, "PHOTO", vcPhotoProp);
|
|
AddAssoc(mapProps, "FADR", vcDeliveryLabelProp);
|
|
AddAssoc(mapProps, "A", msv_address);
|
|
AddAssoc(mapProps, "FN", vcFullNameProp);
|
|
AddAssoc(mapProps, "TITLE", vcTitleProp);
|
|
AddAssoc(mapProps, "O", msv_orgname_orgunit);
|
|
AddAssoc(mapProps, "N", msv_fam_given);
|
|
AddAssoc(mapProps, "PN", vcPronunciationProp);
|
|
AddAssoc(mapProps, "LANG", vcLanguageProp);
|
|
AddAssoc(mapProps, "T", vcTelephoneProp);
|
|
AddAssoc(mapProps, "EMAIL", vcEmailAddressProp);
|
|
AddAssoc(mapProps, "TZ", vcTimeZoneProp);
|
|
AddAssoc(mapProps, "GEO", vcLocationProp);
|
|
AddAssoc(mapProps, "NOTE", vcCommentProp);
|
|
AddAssoc(mapProps, "URL", vcURLProp);
|
|
AddAssoc(mapProps, "CS", vcCharSetProp);
|
|
AddAssoc(mapProps, "REV", vcLastRevisedProp);
|
|
AddAssoc(mapProps, "UID", vcUniqueStringProp);
|
|
AddAssoc(mapProps, "KEY", vcPublicKeyProp);
|
|
AddAssoc(mapProps, "MAILER", vcMailerProp);
|
|
AddAssoc(mapProps, "AGENT", vcAgentProp);
|
|
AddAssoc(mapProps, "BD", vcBirthDateProp);
|
|
AddAssoc(mapProps, "ROLE", vcBusinessRoleProp);
|
|
}
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
/* This parses and converts the base64 format for binary encoding into
|
|
* a decoded buffer (allocated with new). See RFC 1521.
|
|
*/
|
|
static U8 __huge * DataFromBase64(
|
|
const char __huge *str, S32 strLen, S32 *len)
|
|
{
|
|
S32 cur = 0, bytesLen = 0, bytesMax = 0;
|
|
int quadIx = 0, pad = 0;
|
|
U32 trip = 0;
|
|
U8 b;
|
|
char c;
|
|
U8 __huge *bytes = NULL;
|
|
|
|
while (cur < strLen) {
|
|
c = str[cur];
|
|
if ((c >= 'A') && (c <= 'Z'))
|
|
b = (U8)(c - 'A');
|
|
else if ((c >= 'a') && (c <= 'z'))
|
|
b = (U8)(c - 'a') + 26;
|
|
else if ((c >= '0') && (c <= '9'))
|
|
b = (U8)(c - '0') + 52;
|
|
else if (c == '+')
|
|
b = 62;
|
|
else if (c == '/')
|
|
b = 63;
|
|
else if (c == '=') {
|
|
b = 0;
|
|
pad++;
|
|
} else if ((c == '\n') || (c == ' ') || (c == '\t')) {
|
|
cur++;
|
|
continue;
|
|
} else { /* error condition */
|
|
if (bytes) delete [] bytes;
|
|
return NULL;
|
|
}
|
|
trip = (trip << 6) | b;
|
|
if (++quadIx == 4) {
|
|
U8 outBytes[3];
|
|
int numOut;
|
|
for (int i = 0; i < 3; i++) {
|
|
outBytes[2-i] = (U8)(trip & 0xFF);
|
|
trip >>= 8;
|
|
}
|
|
numOut = 3 - pad;
|
|
if (bytesLen + numOut > bytesMax) {
|
|
if (!bytes) {
|
|
bytes = HNEW(U8, 1024L);
|
|
bytesMax = 1024;
|
|
} else {
|
|
U8 __huge *newBytes = HNEW(U8, bytesMax * 2);
|
|
_hmemcpy(newBytes, bytes, bytesLen);
|
|
HFREE(bytes);
|
|
bytes = newBytes;
|
|
bytesMax *= 2;
|
|
}
|
|
}
|
|
memcpy(bytes + bytesLen, outBytes, numOut);
|
|
bytesLen += numOut;
|
|
trip = 0;
|
|
quadIx = 0;
|
|
}
|
|
cur++;
|
|
} /* while */
|
|
*len = bytesLen;
|
|
return bytes;
|
|
}
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
/* This creates an empty CVCard shell with an English body in preparation
|
|
* for parsing properties onto it. This is used for both the outermost
|
|
* card, as well as any AGENT properties, which are themselves vCards.
|
|
*/
|
|
static BOOL PushVCard()
|
|
{
|
|
CVCard *card;
|
|
CVCNode *root, *english;
|
|
|
|
if (curCard == MAXCARD - 1)
|
|
return FALSE;
|
|
|
|
card = new CVCard;
|
|
card->AddObject(root = new CVCNode); /* create root */
|
|
root->AddProp(new CVCProp(VCRootObject)); /* mark it so */
|
|
|
|
/* add a body having the default language */
|
|
english = root->AddObjectProp(vcBodyProp, VCBodyObject);
|
|
cardToBuild[++curCard] = card;
|
|
bodyToBuild = english;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
/* This pops the recently built vCard off the stack and returns it. */
|
|
static CVCard* PopVCard()
|
|
{
|
|
CVCard *result = cardToBuild[curCard];
|
|
|
|
cardToBuild[curCard--] = NULL;
|
|
bodyToBuild = (curCard == -1) ? NULL : cardToBuild[curCard]->FindBody();
|
|
|
|
return result;
|
|
}
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
static int flagslen(const char **flags)
|
|
{
|
|
int i;
|
|
for (i = 0; *flags; flags++, i++) ;
|
|
return i;
|
|
}
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
static BOOL FlagsHave(FLAGS_STRUCT *flags, const char *propName)
|
|
{
|
|
const char **kf = flags->known;
|
|
|
|
while (*kf)
|
|
if (*kf++ == propName)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
/*/////////////////////////////////////////////////////////////////////////*/
|
|
static void AddBoolProps(CVCNode *node, FLAGS_STRUCT *flags)
|
|
{
|
|
const char **kf = flags->known;
|
|
const char *ext = flags->extended;
|
|
|
|
// process the known boolean properties
|
|
while (*kf) {
|
|
node->AddBoolProp(*kf);
|
|
kf++;
|
|
}
|
|
|
|
// process the extended boolean properties
|
|
while (*ext) {
|
|
node->AddBoolProp(ext);
|
|
ext += strlen(ext) + 1;
|
|
}
|
|
}
|
|
|
|
#line 1712 "msv_tab.cpp"
|
|
#define YYABORT goto yyabort
|
|
#define YYREJECT goto yyabort
|
|
#define YYACCEPT goto yyaccept
|
|
#define YYERROR goto yyerrlab
|
|
int
|
|
yyparse()
|
|
{
|
|
int yym, yyn, yystate, yyresult;
|
|
#if YYDEBUG
|
|
char *yys;
|
|
char debugbuf[1024];
|
|
|
|
if (yys = getenv("YYDEBUG"))
|
|
{
|
|
yyn = *yys;
|
|
if (yyn >= '0' && yyn <= '9')
|
|
yydebug = yyn - '0';
|
|
}
|
|
#endif
|
|
|
|
p_yyval = NULL; p_yylval = NULL; yyss = NULL; yyvs = NULL;
|
|
if ((p_yyval = (YYSTYPE*)malloc(sizeof(*p_yyval))) == NULL) goto yyabort;
|
|
if ((p_yylval = (YYSTYPE*)malloc(sizeof(*p_yylval))) == NULL) goto yyabort;
|
|
if ((yyss = (short*)malloc(sizeof(*yyss) * YYSTACKSIZE)) == NULL) goto yyabort;
|
|
if ((yyvs = (YYSTYPE*)malloc(sizeof(*yyvs) * YYSTACKSIZE)) == NULL) goto yyabort;
|
|
|
|
yynerrs = 0;
|
|
yyerrflag = 0;
|
|
yychar = (-1);
|
|
|
|
yyssp = yyss;
|
|
yyvsp = yyvs;
|
|
*yyssp = yystate = 0;
|
|
|
|
yyloop:
|
|
if (yyn = yydefred[yystate]) goto yyreduce;
|
|
if (yychar < 0)
|
|
{
|
|
if ((yychar = yylex()) < 0) yychar = 0;
|
|
#if YYDEBUG
|
|
if (yydebug)
|
|
{
|
|
yys = 0;
|
|
if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
|
|
if (!yys) yys = "illegal-symbol";
|
|
sprintf(debugbuf, "%sdebug: state %d, reading %d (%s)\n",
|
|
YYPREFIX, yystate, yychar, yys); YYDebug(debugbuf);
|
|
}
|
|
#endif
|
|
}
|
|
if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
|
|
yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
|
|
{
|
|
#if YYDEBUG
|
|
if (yydebug) {
|
|
sprintf(debugbuf, "%sdebug: state %d, shifting to state %d\n",
|
|
YYPREFIX, yystate, yytable[yyn]); YYDebug(debugbuf);}
|
|
#endif
|
|
if (yyssp >= yyss + yystacksize - 1)
|
|
{
|
|
goto yyoverflow;
|
|
}
|
|
*++yyssp = yystate = yytable[yyn];
|
|
*++yyvsp = yylval;
|
|
yychar = (-1);
|
|
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;
|
|
#ifdef lint
|
|
goto yynewerror;
|
|
#endif
|
|
yynewerror:
|
|
yyerror("syntax error");
|
|
#ifdef lint
|
|
goto yyerrlab;
|
|
#endif
|
|
yyerrlab:
|
|
++yynerrs;
|
|
yyinrecovery:
|
|
if (yyerrflag < 3)
|
|
{
|
|
yyerrflag = 3;
|
|
for (;;)
|
|
{
|
|
if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
|
|
yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
|
|
{
|
|
#if YYDEBUG
|
|
if (yydebug) {
|
|
sprintf(debugbuf,
|
|
"%sdebug: state %d, error recovery shifting to state %d\n",
|
|
YYPREFIX, *yyssp, yytable[yyn]); YYDebug(debugbuf);}
|
|
#endif
|
|
if (yyssp >= yyss + yystacksize - 1)
|
|
{
|
|
goto yyoverflow;
|
|
}
|
|
*++yyssp = yystate = yytable[yyn];
|
|
*++yyvsp = yylval;
|
|
goto yyloop;
|
|
}
|
|
else
|
|
{
|
|
#if YYDEBUG
|
|
if (yydebug) {
|
|
sprintf(debugbuf, "%sdebug: error recovery discarding state %d\n",
|
|
YYPREFIX, *yyssp); YYDebug(debugbuf);}
|
|
#endif
|
|
if (yyssp <= yyss) goto yyabort;
|
|
--yyssp;
|
|
--yyvsp;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (yychar == 0) goto yyabort;
|
|
#if YYDEBUG
|
|
if (yydebug)
|
|
{
|
|
yys = 0;
|
|
if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
|
|
if (!yys) yys = "illegal-symbol";
|
|
sprintf(debugbuf, "%sdebug: state %d, error recovery discards token %d(%s)\n",
|
|
YYPREFIX, yystate, yychar, yys); YYDebug(debugbuf);
|
|
}
|
|
#endif
|
|
yychar = (-1);
|
|
goto yyloop;
|
|
}
|
|
yyreduce:
|
|
#if YYDEBUG
|
|
if (yydebug) {
|
|
sprintf(debugbuf, "%sdebug: state %d, reducing by rule %d (%s)\n",
|
|
YYPREFIX, yystate, yyn, yyrule[yyn]); YYDebug(debugbuf);}
|
|
#endif
|
|
yym = yylen[yyn];
|
|
yyval = yyvsp[1-yym];
|
|
switch (yyn)
|
|
{
|
|
case 1:
|
|
#line 472 "msv.y"
|
|
{ global_vcList->AddTail(yyvsp[0].vCard); }
|
|
break;
|
|
case 2:
|
|
#line 474 "msv.y"
|
|
{ global_vcList->AddTail(yyvsp[0].vCard); }
|
|
break;
|
|
case 3:
|
|
#line 476 "msv.y"
|
|
{ global_vcList->AddTail(yyvsp[0].vCard); }
|
|
break;
|
|
case 17:
|
|
#line 499 "msv.y"
|
|
{
|
|
if (!PushVCard())
|
|
YYERROR;
|
|
ExpectString();
|
|
}
|
|
break;
|
|
case 18:
|
|
#line 505 "msv.y"
|
|
{ stringExpected = FALSE; }
|
|
break;
|
|
case 19:
|
|
#line 507 "msv.y"
|
|
{ yyval.vCard = PopVCard(); }
|
|
break;
|
|
case 22:
|
|
#line 515 "msv.y"
|
|
{ ExpectString(); }
|
|
break;
|
|
case 23:
|
|
#line 517 "msv.y"
|
|
{
|
|
if (!Parse_Assoc(yyvsp[-7].str, yyvsp[-6].str, &(yyvsp[-5].flags), yyvsp[-1].str))
|
|
YYERROR;
|
|
}
|
|
break;
|
|
case 24:
|
|
#line 522 "msv.y"
|
|
{ ExpectString(); semiSpecial = TRUE; }
|
|
break;
|
|
case 25:
|
|
#line 524 "msv.y"
|
|
{
|
|
semiSpecial = stringExpected = FALSE;
|
|
if (!Parse_SemiValue(yyvsp[-7].str, yyvsp[-6].str, &(yyvsp[-5].flags), yyvsp[-1].str, addrProps))
|
|
YYERROR;
|
|
}
|
|
break;
|
|
case 26:
|
|
#line 530 "msv.y"
|
|
{ ExpectString(); semiSpecial = TRUE; }
|
|
break;
|
|
case 27:
|
|
#line 532 "msv.y"
|
|
{
|
|
semiSpecial = stringExpected = FALSE;
|
|
if (!Parse_SemiValue(yyvsp[-7].str, yyvsp[-6].str, &(yyvsp[-5].flags), yyvsp[-1].str, nameProps))
|
|
YYERROR;
|
|
}
|
|
break;
|
|
case 28:
|
|
#line 538 "msv.y"
|
|
{ ExpectString(); semiSpecial = TRUE; }
|
|
break;
|
|
case 29:
|
|
#line 540 "msv.y"
|
|
{
|
|
semiSpecial = stringExpected = FALSE;
|
|
if (!Parse_SemiValue(yyvsp[-7].str, yyvsp[-6].str, &(yyvsp[-5].flags), yyvsp[-1].str, orgProps))
|
|
YYERROR;
|
|
}
|
|
break;
|
|
case 30:
|
|
#line 546 "msv.y"
|
|
{
|
|
if (!Parse_Agent(yyvsp[-7].str, yyvsp[-6].str, &(yyvsp[-5].flags), yyvsp[-2].vCard)) {
|
|
delete yyvsp[-2].vCard;
|
|
YYERROR;
|
|
}
|
|
}
|
|
break;
|
|
case 31:
|
|
#line 553 "msv.y"
|
|
{
|
|
stringExpected = flagExpected = FALSE;
|
|
yyerrok;
|
|
yyclearin;
|
|
}
|
|
break;
|
|
case 33:
|
|
#line 560 "msv.y"
|
|
{ yyval.str[0] = 0; }
|
|
break;
|
|
case 40:
|
|
#line 573 "msv.y"
|
|
{ stringExpected = FALSE; }
|
|
break;
|
|
case 41:
|
|
#line 575 "msv.y"
|
|
{ stringExpected = FALSE; }
|
|
break;
|
|
case 42:
|
|
#line 577 "msv.y"
|
|
{
|
|
yyval.str[0] = 0;
|
|
stringExpected = FALSE;
|
|
}
|
|
break;
|
|
case 43:
|
|
#line 583 "msv.y"
|
|
{ inBinary = TRUE; }
|
|
break;
|
|
case 44:
|
|
#line 585 "msv.y"
|
|
{ inBinary = FALSE; }
|
|
break;
|
|
case 45:
|
|
#line 586 "msv.y"
|
|
{
|
|
StrCat(yyval.str, yyvsp[-5].str, "");
|
|
}
|
|
break;
|
|
case 46:
|
|
#line 592 "msv.y"
|
|
{
|
|
StrCat(yyval.str, yyvsp[-3].str, "\n");
|
|
StrCat(yyval.str, yyval.str, yyvsp[0].str);
|
|
}
|
|
break;
|
|
case 47:
|
|
#line 597 "msv.y"
|
|
{
|
|
StrCat(yyval.str, yyvsp[-2].str, "\n");
|
|
}
|
|
break;
|
|
case 49:
|
|
#line 602 "msv.y"
|
|
{
|
|
StrCat(yyval.str, "\n", "");
|
|
}
|
|
break;
|
|
case 50:
|
|
#line 608 "msv.y"
|
|
{
|
|
StrCat(yyval.str, yyvsp[-2].str, "\177");
|
|
StrCat(yyval.str, yyval.str, yyvsp[0].str);
|
|
}
|
|
break;
|
|
case 52:
|
|
#line 616 "msv.y"
|
|
{
|
|
StrCat(yyval.str, yyvsp[-2].str, "\n");
|
|
StrCat(yyval.str, yyval.str, yyvsp[0].str);
|
|
}
|
|
break;
|
|
case 55:
|
|
#line 625 "msv.y"
|
|
{ StrCat(yyval.str, yyvsp[-1].str, ""); }
|
|
break;
|
|
case 56:
|
|
#line 627 "msv.y"
|
|
{ yyval.str[0] = 0; }
|
|
break;
|
|
case 57:
|
|
#line 629 "msv.y"
|
|
{ yyval.str[0] = 0; }
|
|
break;
|
|
case 58:
|
|
#line 633 "msv.y"
|
|
{
|
|
strcpy(yyval.str, yyvsp[-2].str);
|
|
strcat(yyval.str, ".");
|
|
strcat(yyval.str, yyvsp[0].str);
|
|
}
|
|
break;
|
|
case 60:
|
|
#line 642 "msv.y"
|
|
{
|
|
yyval.flags = yyvsp[-2].flags;
|
|
if (yyvsp[0].flags.known[0]) {
|
|
int len = flagslen(yyvsp[-2].flags.known);
|
|
yyval.flags.known[len] = yyvsp[0].flags.known[0];
|
|
yyval.flags.known[len+1] = NULL;
|
|
} else {
|
|
char *p = yyval.flags.extended;
|
|
int len = strlen(yyvsp[0].flags.extended);
|
|
while (*p) p += strlen(p) + 1;
|
|
memcpy(p, yyvsp[0].flags.extended, len + 1);
|
|
*(p + len + 1) = 0;
|
|
}
|
|
}
|
|
break;
|
|
case 61:
|
|
#line 656 "msv.y"
|
|
{ flagExpected = TRUE; }
|
|
break;
|
|
case 62:
|
|
#line 657 "msv.y"
|
|
{ yyval.flags = yyvsp[0].flags; }
|
|
break;
|
|
case 63:
|
|
#line 659 "msv.y"
|
|
{ yyval.flags.known[0] = NULL; yyval.flags.extended[0] = 0; }
|
|
break;
|
|
#line 2067 "msv_tab.cpp"
|
|
}
|
|
yyssp -= yym;
|
|
yystate = *yyssp;
|
|
yyvsp -= yym;
|
|
yym = yylhs[yyn];
|
|
if (yystate == 0 && yym == 0)
|
|
{
|
|
#if YYDEBUG
|
|
if (yydebug) {
|
|
sprintf(debugbuf,
|
|
"%sdebug: after reduction, shifting from state 0 to state %d\n",
|
|
YYPREFIX, YYFINAL); YYDebug(debugbuf);}
|
|
#endif
|
|
yystate = YYFINAL;
|
|
*++yyssp = YYFINAL;
|
|
*++yyvsp = yyval;
|
|
if (yychar < 0)
|
|
{
|
|
if ((yychar = yylex()) < 0) yychar = 0;
|
|
#if YYDEBUG
|
|
if (yydebug)
|
|
{
|
|
yys = 0;
|
|
if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
|
|
if (!yys) yys = "illegal-symbol";
|
|
sprintf(debugbuf, "%sdebug: state %d, reading %d (%s)\n",
|
|
YYPREFIX, YYFINAL, yychar, yys); YYDebug(debugbuf);
|
|
}
|
|
#endif
|
|
}
|
|
if (yychar == 0) 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) {
|
|
sprintf(debugbuf,
|
|
"%sdebug: after reduction, shifting from state %d to state %d\n",
|
|
YYPREFIX, *yyssp, yystate); YYDebug(debugbuf);}
|
|
#endif
|
|
if (yyssp >= yyss + yystacksize - 1)
|
|
{
|
|
goto yyoverflow;
|
|
}
|
|
*++yyssp = yystate;
|
|
*++yyvsp = yyval;
|
|
goto yyloop;
|
|
yyoverflow:
|
|
yyerror("yacc stack overflow");
|
|
yyabort:
|
|
yyresult = 1;
|
|
goto yyfinish;
|
|
yyaccept:
|
|
yyresult = 0;
|
|
yyfinish:
|
|
if (p_yyval) free(p_yyval);
|
|
if (p_yylval) free(p_yylval);
|
|
if (yyss) free(yyss);
|
|
if (yyvs) free(yyvs);
|
|
return yyresult;
|
|
}
|
|
END_CFUNCTIONS
|