-rw-r--r-- | library/backend/vcc.y | 53 |
1 files changed, 41 insertions, 12 deletions
diff --git a/library/backend/vcc.y b/library/backend/vcc.y index eca7c32..00e8fed 100644 --- a/library/backend/vcc.y +++ b/library/backend/vcc.y | |||
@@ -47,12 +47,14 @@ DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. | |||
47 | * in a debugger. However, if a bug is found it should | 47 | * in a debugger. However, if a bug is found it should |
48 | * be fixed in vcc.y and this file regenerated. | 48 | * be fixed in vcc.y and this file regenerated. |
49 | */ | 49 | */ |
50 | 50 | ||
51 | 51 | ||
52 | /* debugging utilities */ | 52 | /* debugging utilities */ |
53 | #define __DEBUG 1 | ||
54 | |||
53 | #if __DEBUG | 55 | #if __DEBUG |
54 | #define DBG_(x) printf x | 56 | #define DBG_(x) printf x |
55 | #else | 57 | #else |
56 | #define DBG_(x) | 58 | #define DBG_(x) |
57 | #endif | 59 | #endif |
58 | 60 | ||
@@ -132,12 +134,13 @@ DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. | |||
132 | #define YYSTACKSIZE 100// ~unref ? | 134 | #define YYSTACKSIZE 100// ~unref ? |
133 | #define MAXLEVEL 10/* max # of nested objects parseable */ | 135 | #define MAXLEVEL 10/* max # of nested objects parseable */ |
134 | /* (includes outermost) */ | 136 | /* (includes outermost) */ |
135 | 137 | ||
136 | 138 | ||
137 | /**** Global Variables ****/ | 139 | /**** Global Variables ****/ |
140 | int q_DontDecodeBase64Photo = 0; | ||
138 | int mime_lineNum, mime_numErrors; /* yyerror() can use these */ | 141 | int mime_lineNum, mime_numErrors; /* yyerror() can use these */ |
139 | static VObject* vObjList; | 142 | static VObject* vObjList; |
140 | static VObject *curProp; | 143 | static VObject *curProp; |
141 | static VObject *curObj; | 144 | static VObject *curObj; |
142 | static VObject* ObjStack[MAXLEVEL]; | 145 | static VObject* ObjStack[MAXLEVEL]; |
143 | static int ObjStackTop; | 146 | static int ObjStackTop; |
@@ -155,12 +158,13 @@ extern "C" { | |||
155 | #endif | 158 | #endif |
156 | 159 | ||
157 | int yyparse(); | 160 | int yyparse(); |
158 | 161 | ||
159 | enum LexMode { | 162 | enum LexMode { |
160 | L_NORMAL, | 163 | L_NORMAL, |
164 | L_PARAMWORD, | ||
161 | L_VCARD, | 165 | L_VCARD, |
162 | L_VCAL, | 166 | L_VCAL, |
163 | L_VEVENT, | 167 | L_VEVENT, |
164 | L_VTODO, | 168 | L_VTODO, |
165 | L_VALUES, | 169 | L_VALUES, |
166 | L_BASE64, | 170 | L_BASE64, |
@@ -286,16 +290,20 @@ attr_param: SEMICOLON attr | |||
286 | ; | 290 | ; |
287 | 291 | ||
288 | attr: name | 292 | attr: name |
289 | { | 293 | { |
290 | enterAttr($1,0); | 294 | enterAttr($1,0); |
291 | } | 295 | } |
292 | | name EQ name | 296 | | name EQ |
293 | { | 297 | { |
294 | enterAttr($1,$3); | 298 | lexPushMode(L_PARAMWORD); |
295 | 299 | } | |
300 | name | ||
301 | { | ||
302 | lexPopMode(0); | ||
303 | enterAttr($1,$4); | ||
296 | } | 304 | } |
297 | ; | 305 | ; |
298 | 306 | ||
299 | name: ID | 307 | name: ID |
300 | ; | 308 | ; |
301 | 309 | ||
@@ -448,16 +456,21 @@ static void enterAttr(const char *s1, const char *s2) | |||
448 | p2 = lookupProp_(s2); | 456 | p2 = lookupProp_(s2); |
449 | a = addProp(curProp,p1); | 457 | a = addProp(curProp,p1); |
450 | setVObjectStringZValue(a,p2); | 458 | setVObjectStringZValue(a,p2); |
451 | } | 459 | } |
452 | else | 460 | else |
453 | addProp(curProp,p1); | 461 | addProp(curProp,p1); |
454 | if (qstricmp(p1,VCBase64Prop) == 0 || (s2 && qstricmp(p2,VCBase64Prop)==0)) | 462 | /* Lookup strings so we can quickly use pointer comparison */ |
463 | static const char* base64 = lookupProp_(VCBase64Prop); | ||
464 | static const char* qp = lookupProp_(VCQuotedPrintableProp); | ||
465 | static const char* photo = lookupProp_(VCPhotoProp); | ||
466 | static const char* encoding = lookupProp_(VCEncodingProp); | ||
467 | if ((!q_DontDecodeBase64Photo || vObjectName(curProp) != photo) | ||
468 | && (p1 == base64 || p1 == encoding && p2 == base64)) | ||
455 | lexPushMode(L_BASE64); | 469 | lexPushMode(L_BASE64); |
456 | else if (qstricmp(p1,VCQuotedPrintableProp) == 0 | 470 | else if (p1 == qp || p1 == encoding && p2 == qp) |
457 | || (s2 && qstricmp(p2,VCQuotedPrintableProp)==0)) | ||
458 | lexPushMode(L_QUOTED_PRINTABLE); | 471 | lexPushMode(L_QUOTED_PRINTABLE); |
459 | deleteStr(s1); deleteStr(s2); | 472 | deleteStr(s1); deleteStr(s2); |
460 | } | 473 | } |
461 | 474 | ||
462 | 475 | ||
463 | #define MAX_LEX_LOOKAHEAD_0 32 | 476 | #define MAX_LEX_LOOKAHEAD_0 32 |
@@ -638,12 +651,26 @@ static char* lexGetWord() { | |||
638 | c = lexLookahead(); | 651 | c = lexLookahead(); |
639 | } | 652 | } |
640 | lexAppendc(0); | 653 | lexAppendc(0); |
641 | return lexStr(); | 654 | return lexStr(); |
642 | } | 655 | } |
643 | 656 | ||
657 | static char* lexGetParamWord() | ||
658 | { | ||
659 | int c; | ||
660 | lexClearToken(); | ||
661 | c = lexLookahead(); | ||
662 | while (c >= ' ' && c < 127 && !strchr("[]:=,.;",c)) { | ||
663 | lexAppendc(c); | ||
664 | lexSkipLookahead(); | ||
665 | c = lexLookahead(); | ||
666 | } | ||
667 | lexAppendc(0); | ||
668 | return lexStr(); | ||
669 | } | ||
670 | |||
644 | static void lexPushLookaheadc(int c) { | 671 | static void lexPushLookaheadc(int c) { |
645 | int putptr; | 672 | int putptr; |
646 | /* can't putback EOF, because it never leaves lookahead buffer */ | 673 | /* can't putback EOF, because it never leaves lookahead buffer */ |
647 | if (c == EOF) return; | 674 | if (c == EOF) return; |
648 | putptr = (int)lexBuf.getPtr - 1; | 675 | putptr = (int)lexBuf.getPtr - 1; |
649 | if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD; | 676 | if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD; |
@@ -1007,26 +1034,26 @@ static char* lexGetQuotedPrintable() | |||
1007 | 1034 | ||
1008 | static int yylex() { | 1035 | static int yylex() { |
1009 | 1036 | ||
1010 | int lexmode = LEXMODE(); | 1037 | int lexmode = LEXMODE(); |
1011 | if (lexmode == L_VALUES) { | 1038 | if (lexmode == L_VALUES) { |
1012 | int c = lexGetc(); | 1039 | int c = lexGetc(); |
1040 | int c2; | ||
1013 | if (c == ';' && fieldedProp) { | 1041 | if (c == ';' && fieldedProp) { |
1014 | DBG_(("db: SEMICOLON\n")); | 1042 | DBG_(("db: SEMICOLON\n")); |
1015 | lexPushLookaheadc(c); | 1043 | lexPushLookaheadc(c); |
1016 | handleMoreRFC822LineBreak(c); | 1044 | handleMoreRFC822LineBreak(c); |
1017 | lexSkipLookahead(); | 1045 | lexSkipLookahead(); |
1018 | return SEMICOLON; | 1046 | return SEMICOLON; |
1019 | } | 1047 | } |
1020 | else if (strchr("\n",c)) { | 1048 | else if (strchr("\n",c) && (c2 = lexLookahead()) != ' ' && c2 != '\t') { |
1021 | ++mime_lineNum; | 1049 | ++mime_lineNum; |
1022 | /* consume all line separator(s) adjacent to each other */ | 1050 | /* consume all line separator(s) adjacent to each other */ |
1023 | c = lexLookahead(); | 1051 | while (strchr("\n",c2)) { |
1024 | while (strchr("\n",c)) { | ||
1025 | lexSkipLookahead(); | 1052 | lexSkipLookahead(); |
1026 | c = lexLookahead(); | 1053 | c2 = lexLookahead(); |
1027 | ++mime_lineNum; | 1054 | ++mime_lineNum; |
1028 | } | 1055 | } |
1029 | DBG_(("db: LINESEP\n")); | 1056 | DBG_(("db: LINESEP\n")); |
1030 | return LINESEP; | 1057 | return LINESEP; |
1031 | } | 1058 | } |
1032 | else { | 1059 | else { |
@@ -1051,14 +1078,16 @@ static int yylex() { | |||
1051 | DBG_(("db: STRING: '%s'\n", p)); | 1078 | DBG_(("db: STRING: '%s'\n", p)); |
1052 | yylval.str = p; | 1079 | yylval.str = p; |
1053 | return STRING; | 1080 | return STRING; |
1054 | } | 1081 | } |
1055 | else return 0; | 1082 | else return 0; |
1056 | } | 1083 | } |
1057 | } | 1084 | } else if (lexmode == L_PARAMWORD) { |
1058 | else { | 1085 | yylval.str = lexGetParamWord(); |
1086 | return ID; | ||
1087 | } else { | ||
1059 | /* normal mode */ | 1088 | /* normal mode */ |
1060 | while (1) { | 1089 | while (1) { |
1061 | int c = lexGetc(); | 1090 | int c = lexGetc(); |
1062 | switch(c) { | 1091 | switch(c) { |
1063 | case ':': { | 1092 | case ':': { |
1064 | /* consume all line separator(s) adjacent to each other */ | 1093 | /* consume all line separator(s) adjacent to each other */ |