-rw-r--r-- | libkcal/versit/vcc.c | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/libkcal/versit/vcc.c b/libkcal/versit/vcc.c index 9be752d..5413813 100644 --- a/libkcal/versit/vcc.c +++ b/libkcal/versit/vcc.c @@ -1381,769 +1381,770 @@ yyerrlab1: goto yyerrhandle; /*-------------------------------------------------------------------. | yyerrdefault -- current state does not do anything special for the | | error token. | `-------------------------------------------------------------------*/ yyerrdefault: #if 0 /* This is wrong; only states that explicitly want error tokens should shift them. */ /* If its default is to accept any token, ok. Otherwise pop it. */ yyn = yydefact[yystate]; if (yyn) goto yydefault; #endif /*---------------------------------------------------------------. | yyerrpop -- pop the current state because it cannot handle the | | error token | `---------------------------------------------------------------*/ yyerrpop: if (yyssp == yyss) YYABORT; yyvsp--; yystate = *--yyssp; #if YYLSP_NEEDED yylsp--; #endif #if YYDEBUG if (yydebug) { short *yyssp1 = yyss - 1; YYFPRINTF (stderr, "Error: state stack now"); while (yyssp1 != yyssp) YYFPRINTF (stderr, " %d", *++yyssp1); YYFPRINTF (stderr, "\n"); } #endif /*--------------. | yyerrhandle. | `--------------*/ yyerrhandle: yyn = yypact[yystate]; if (yyn == YYFLAG) goto yyerrdefault; yyn += YYTERROR; if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) goto yyerrdefault; yyn = yytable[yyn]; if (yyn < 0) { if (yyn == YYFLAG) goto yyerrpop; yyn = -yyn; goto yyreduce; } else if (yyn == 0) goto yyerrpop; if (yyn == YYFINAL) YYACCEPT; YYDPRINTF ((stderr, "Shifting error token, ")); *++yyvsp = yylval; #if YYLSP_NEEDED *++yylsp = yylloc; #endif yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; /*---------------------------------------------. | yyoverflowab -- parser overflow comes here. | `---------------------------------------------*/ yyoverflowlab: yyerror ("parser stack overflow"); yyresult = 2; /* Fall through. */ yyreturn: #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif return yyresult; } #line 373 "vcc.y" static int pushVObject(const char *prop) { VObject *newObj; if (ObjStackTop == MAXLEVEL) return FALSE; ObjStack[++ObjStackTop] = curObj; if (curObj) { newObj = addProp(curObj,prop); curObj = newObj; } else curObj = newVObject(prop); return TRUE; } /* This pops the recently built vCard off the stack and returns it. */ static VObject* popVObject() { 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) { addPropValue(curProp,*fieldedProp,value); } /* else this field is empty, advance to next field */ fieldedProp++; } else { if (value) { char *p1, *p2; wchar_t *p3; int 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)); p2 = malloc((strlen(p1)+strlen(value)+1)); strcpy(p2, p1); deleteStr(p1); i = strlen(p2); p2[i] = ';'; p2[i+1] = '\0'; p2 = strcat(p2, value); p3 = (wchar_t *) vObjectUStringZValue(curProp); free(p3); setVObjectUStringZValue_(curProp,fakeUnicode(p2,0)); deleteStr(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; p1 = lookupProp_(s1); if (s2) { VObject *a; p2 = lookupProp_(s2); a = addProp(curProp,p1); setVObjectStringZValue(a,p2); } else addProp(curProp,p1); if (stricmp(p1,VCBase64Prop) == 0 || (s2 && stricmp(p2,VCBase64Prop)==0)) lexPushMode(L_BASE64); else if (stricmp(p1,VCQuotedPrintableProp) == 0 || (s2 && stricmp(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]; 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_() { /* 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 fgetc(lexBuf.inputFile); #endif } } static int lexGeta() { ++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() { if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) { /* don't skip EOF. */ lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD; lexBuf.len--; } } static int lexLookahead() { 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() { int c = lexLookahead(); if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) { /* EOF will remain in lookahead buffer */ lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD; lexBuf.len--; } return c; } static void lexSkipLookaheadWord() { if (lexBuf.strsLen <= lexBuf.len) { lexBuf.len -= lexBuf.strsLen; lexBuf.getPtr = (lexBuf.getPtr + lexBuf.strsLen) % MAX_LEX_LOOKAHEAD; } } static void lexClearToken() { 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() { return dupStr(lexBuf.strs,(size_t)lexBuf.strsLen+1); } static void lexSkipWhite() { int c = lexLookahead(); while (c == ' ' || c == '\t') { lexSkipLookahead(); c = lexLookahead(); } } static char* lexGetWord() { int c; lexSkipWhite(); lexClearToken(); c = lexLookahead(); - while (c != EOF && !strchr("\t\n ;:=",c)) { + // LR while (c != EOF && !strchr("\t\n ;:=",c)) { + while (c != 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 (c == EOF) return; putptr = (int)lexBuf.getPtr - 1; if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD; lexBuf.getPtr = putptr; lexBuf.buf[putptr] = c; lexBuf.len += 1; } static char* lexLookaheadWord() { /* 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 == EOF || strchr("\t\n ;:=", c)) { lexAppendc(0); /* restore lookahead buf. */ lexBuf.len += len; lexBuf.getPtr = curgetptr; return lexStr(); } else lexAppendc(c); } lexBuf.len += len; /* char that has been moved to lookahead buffer */ lexBuf.getPtr = curgetptr; return 0; } #ifdef _SUPPORT_LINE_FOLDING static void handleMoreRFC822LineBreak(int c) { /* suport 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() { int c; lexSkipWhite(); c = lexLookahead(); lexClearToken(); while (c != 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==EOF?0:lexStr(); } #endif static int match_begin_name(int end) { char *n = lexLookaheadWord(); int token = ID; if (n) { if (!stricmp(n,"vcard")) token = end?END_VCARD:BEGIN_VCARD; else if (!stricmp(n,"vcalendar")) token = end?END_VCAL:BEGIN_VCAL; else if (!stricmp(n,"vevent")) token = end?END_VEVENT:BEGIN_VEVENT; else if (!stricmp(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() { 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() { unsigned long 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 != EOF) { c = lexGetc(); while (c != EOF) { if (c == '\n' && lexLookahead() == '\n') { ++mime_lineNum; break; } c = lexGetc(); } } return NULL; } trip = (trip << 6) | b; if (++quadIx == 4) { unsigned char outBytes[3]; int numOut; int i; for (i = 0; i < 3; i++) { outBytes[2-i] = (unsigned char)(trip & 0xFF); trip >>= 8; } numOut = 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 = %d\n", bytesLen)); /* kludge: all this won't be necessary if we have tree form representation */ if (bytes) { setValueWithSize(curProp,bytes,(unsigned int)bytesLen); free(bytes); } else if (oldBytes) { 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() { 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() { 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(); |