📄 vcc.y
字号:
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)) { lexAppendc(c); lexSkipLookahead(); c = lexLookahead(); } lexAppendc(0); return lexStr(); }static char* lexGetParamWord(){ int c; lexClearToken(); c = lexLookahead(); while (c >= ' ' && c < 127 && !strchr("[]:=,.;",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_FOLDINGstatic 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 != ';' || !fieldedProp)) { if (c == '\\' ) { int a; lexSkipLookahead(); a = lexLookahead(); if ( a == ';' ) { lexAppendc( ';' ); lexSkipLookahead(); } else if ( a == '\n' ) { lexAppendc( '\n' ); lexSkipLookahead(); } else if ( a == '\\' ) { lexAppendc( '\\' ); lexSkipLookahead(); } else { lexAppendc('\\'); } } else 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(); }#endifstatic int match_begin_name(int end) { char *n = lexLookaheadWord(); int token = ID; if (n) { if (!qstricmp(n,"vcard")) token = end?END_VCARD:BEGIN_VCARD; else if (!qstricmp(n,"vcalendar")) token = end?END_VCAL:BEGIN_VCAL; else if (!qstricmp(n,"vevent")) token = end?END_VEVENT:BEGIN_VEVENT; else if (!qstricmp(n,"vtodo")) token = end?END_VTODO:BEGIN_VTODO; deleteStr(n); return token; } return 0; }#ifdef INCLUDEMFCvoid initLex(const char *inputstring, unsigned long inputlen, CFile *inputfile)#elsevoid 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 int 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(); lexSkipWhite(); 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 { /* 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') { lexSkipWhite(); if(lexLookahead() == '\n') { ++mime_lineNum; break; } } c = lexGetc(); } } return c != EOF; } 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 bytesLen; }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(){ int c; lexSkipWhite(); c = lexLookahead(); lexClearToken(); while (c != EOF && (c != ';' || !fieldedProp)) { if (c == '\n') { // break, leave '\n' on remaining chars. break; } else if (c == '=') { int cur = 0; int next; lexSkipLookahead(); // skip '=' next = lexLookahead(); if (next == '\n') { // skip and only skip the \n lexSkipLookahead(); c = lexLookahead(); ++mime_lineNum; // aid in error reporting continue; } else if (next >= '0' && next <= '9') { cur = next - '0'; } else if (next >= 'A' && next <= 'F') { cur = next - 'A' + 10; } else { // we have been sent buggy stuff. doesn't matter // what we do so long as we keep going. // should probably spit an error here lexSkipLookahead(); c = lexLookahead(); continue; } lexSkipLookahead(); // skip A-Z0-9 next = lexLookahead(); cur = cur * 16; // this time really just expecting 0-9A-F if (next >= '0' && next <= '9') { cur += next - '0'; } else if (next >= 'A' && next <= 'F') { cur += next - 'A' + 10; } else { // we have been sent buggy stuff. doesn't matter // what we do so long as we keep going. // should probably spit an error here lexSkipLookahead(); c = lexLookahead(); continue; } // got a valid escaped =. append it. lexSkipLookahead(); // skip second 0-9A-F lexAppendc(cur); } else { lexSkipLookahead(); // skip whatever we just read. lexAppendc(c); // and append it. } c = lexLookahead(); } lexAppendc(0); return c==EOF?0:lexStr();}static int yylex() { int lexmode = LEXMODE(); if (lexmode == L_VALUES) { int c = lexGetc(); int c2; if (c == ';' && fieldedProp) { DBG_(("db: SEMICOLON\n")); lexPushLookaheadc(c); handleMoreRFC822LineBreak(c); lexSkipLookahead(); return SEMICOLON; } else if (strchr("\n",c) && (c2 = lexLookahead()) != ' ' && c2 != '\t') { ++mime_lineNum; /* consume all line separator(s) adjacent to each other */ while (strchr("\n",c2)) { lexSkipLookahead(); c2 = 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... */ yylval.str = NULL; return lexGetDataFromBase64() ? STRING : 0; } 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 if (lexmode == L_PARAMWORD) { yylval.str = lexGetParamWord(); return ID; } 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. */ /* I don't see this in the spec, and it breaks null values -- WA 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 EOF: return 0; break; default: { lexPushLookaheadc(c); if (isalnum(c)) { char *t = lexGetWord(); yylval.str = t; if (!qstricmp(t, "begin")) { return match_begin_end_name(0); } else if (!qstricmp(t,"end")) { return match_begin_end_name(1); } else { DBG_(("db: ID '%s'\n", t)); return ID; } } else { /* unknow token */ return 0; } break; } } } } return 0; }/***************************************************************************//*** Public Functions ****//***************************************************************************/static VObject* Parse_MIMEHelper() { ObjStackTop = -1; mime_numErrors = 0; mime_lineNum = 1; vObjList = 0; curObj = 0; if (yyparse() != 0) return 0; finiLex(); return vObjList; }/*--------------------------------------------*/DLLEXPORT(VObject*) Parse_MIME(const char *input, unsigned long len) { initLex(input, len, 0); return Parse_MIMEHelper(); }#if INCLUDEMFCDLLEXPORT(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; }#elseVObject* Parse_MIME_FromFile(FILE *file) { VObject *result; long startPos; initLex(0,(unsigned long)-1,file); startPos = ftell(file); if (!(result = Parse_MIMEHelper())) { fseek(file,startPos,SEEK_SET); } return result; }DLLEXPORT(VObject*) Parse_MIME_FromFileName(char *fname) { FILE *fp = fopen(fname,"r"); if (fp) { VObject* o = Parse_MIME_FromFile(fp); fclose(fp); return o; } else { char msg[80]; sprintf(msg, "can't open file '%s' for reading\n", fname); mime_error_(msg); return 0; } }#endif/*-------------------------------------*/static MimeErrorHandler mimeErrorHandler;DLLEXPORT(void) registerMimeErrorHandler(MimeErrorHandler me) { mimeErrorHandler = me; }void mime_error(char *s) { char msg[256]; if (mimeErrorHandler) { sprintf(msg,"%s at line %d", s, mime_lineNum); mimeErrorHandler(msg); } }void mime_error_(char *s) { if (mimeErrorHandler) { mimeErrorHandler(s); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -