1 // Copyright 2014 PDFium Authors. All rights reserved.
\r
2 // Use of this source code is governed by a BSD-style license that can be
\r
3 // found in the LICENSE file.
\r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
\r
7 #include "xfa_fm2js.h"
\r
9 static FX_LPCWSTR inc(FX_LPCWSTR &p)
\r
14 static FX_LPCWSTR dec(FX_LPCWSTR &p)
\r
19 static uint16_t get(FX_LPCWSTR p)
\r
23 static FX_BOOL isWhiteSpace(FX_LPCWSTR p)
\r
25 return (*p) == 0x09 || (*p) == 0x0b || (*p) == 0x0c || (*p) == 0x20;
\r
27 static FX_BOOL isLineTerminator(FX_LPCWSTR p)
\r
29 return *p == 0x0A || *p == 0x0D;
\r
31 static FX_BOOL isBinary(FX_LPCWSTR p)
\r
33 return (*p) >= '0' && (*p) <= '1';
\r
35 static FX_BOOL isOctal(FX_LPCWSTR p)
\r
37 return (*p) >= '0' && (*p) <= '7';
\r
39 static FX_BOOL isDigital(FX_LPCWSTR p)
\r
41 return (*p) >= '0' && (*p) <= '9';
\r
43 static FX_BOOL isHex(FX_LPCWSTR p)
\r
45 return isDigital(p) || ((*p) >= 'a' && (*p) <= 'f') || ((*p) >= 'A' && (*p) <= 'F');
\r
47 static FX_BOOL isAlpha(FX_LPCWSTR p)
\r
49 return ((*p) <= 'z' && (*p) >= 'a') || ((*p) <= 'Z' && (*p) >= 'A');
\r
51 static FX_BOOL isAvalid(FX_LPCWSTR p, FX_BOOL flag = 0);
\r
52 static FX_BOOL string2number(FX_LPCWSTR s, FX_DOUBLE *pValue, FX_LPCWSTR &pEnd);
\r
53 static FX_BOOL isUnicodeAlpha(uint16_t ch);
\r
55 inline FX_BOOL XFA_FMDChar::isAvalid(FX_LPCWSTR p, FX_BOOL flag)
\r
60 if ((*p <= 0x0A && *p >= 0x09) || *p == 0x0D || (*p <= 0xd7ff && *p >= 0x20) || (*p <= 0xfffd && *p >= 0xe000)) {
\r
64 if (*p == 0x0B || *p == 0x0C) {
\r
70 inline FX_BOOL XFA_FMDChar::string2number(FX_LPCWSTR s, FX_DOUBLE *pValue, FX_LPCWSTR &pEnd)
\r
73 *pValue = wcstod((wchar_t *)s, (wchar_t **)&pEnd);
\r
77 inline FX_BOOL XFA_FMDChar::isUnicodeAlpha(uint16_t ch)
\r
79 if (ch == 0 || ch == 0x0A || ch == 0x0D || ch == 0x09 || ch == 0x0B || ch == 0x0C || ch == 0x20 || ch == '.'
\r
80 || ch == ';' || ch == '"' || ch == '=' || ch == '<' || ch == '>' || ch == ',' || ch == '(' || ch == ')'
\r
81 || ch == ']' || ch == '[' || ch == '&' || ch == '|' || ch == '+' || ch == '-' || ch == '*' || ch == '/') {
\r
87 static XFA_FMKeyword keyWords[] = {
\r
88 {TOKand, 0x00000026, L"&"},
\r
89 {TOKlparen, 0x00000028, L"("},
\r
90 {TOKrparen, 0x00000029, L")"},
\r
91 {TOKmul, 0x0000002a, L"*"},
\r
92 {TOKplus, 0x0000002b, L"+"},
\r
93 {TOKcomma, 0x0000002c, L","},
\r
94 {TOKminus, 0x0000002d, L"-"},
\r
95 {TOKdot, 0x0000002e, L"."},
\r
96 {TOKdiv, 0x0000002f, L"/"},
\r
97 {TOKlt, 0x0000003c, L"<"},
\r
98 {TOKassign, 0x0000003d, L"="},
\r
99 {TOKgt, 0x0000003e, L">"},
\r
100 {TOKlbracket, 0x0000005b, L"["},
\r
101 {TOKrbracket, 0x0000005d, L"]"},
\r
102 {TOKor, 0x0000007c, L"|"},
\r
103 {TOKdotscream, 0x0000ec11, L".#"},
\r
104 {TOKdotstar, 0x0000ec18, L".*"},
\r
105 {TOKdotdot, 0x0000ec1c, L".."},
\r
106 {TOKle, 0x000133f9, L"<="},
\r
107 {TOKne, 0x000133fa, L"<>"},
\r
108 {TOKeq, 0x0001391a, L"=="},
\r
109 {TOKge, 0x00013e3b, L">="},
\r
110 {TOKdo, 0x00020153, L"do"},
\r
111 {TOKkseq, 0x00020676, L"eq"},
\r
112 {TOKksge, 0x000210ac, L"ge"},
\r
113 {TOKksgt, 0x000210bb, L"gt"},
\r
114 {TOKif, 0x00021aef, L"if"},
\r
115 {TOKin, 0x00021af7, L"in"},
\r
116 {TOKksle, 0x00022a51, L"le"},
\r
117 {TOKkslt, 0x00022a60, L"lt"},
\r
118 {TOKksne, 0x00023493, L"ne"},
\r
119 {TOKksor, 0x000239c1, L"or"},
\r
120 {TOKnull, 0x052931bb, L"null"},
\r
121 {TOKbreak, 0x05518c25, L"break"},
\r
122 {TOKksand, 0x09f9db33, L"and"},
\r
123 {TOKend, 0x0a631437, L"end"},
\r
124 {TOKeof, 0x0a63195a, L"eof"},
\r
125 {TOKfor, 0x0a7d67a7, L"for"},
\r
126 {TOKnan, 0x0b4f91dd, L"nan"},
\r
127 {TOKksnot, 0x0b4fd9b1, L"not"},
\r
128 {TOKvar, 0x0c2203e9, L"var"},
\r
129 {TOKthen, 0x2d5738cf, L"then"},
\r
130 {TOKelse, 0x45f65ee9, L"else"},
\r
131 {TOKexit, 0x4731d6ba, L"exit"},
\r
132 {TOKdownto, 0x4caadc3b, L"downto"},
\r
133 {TOKreturn, 0x4db8bd60, L"return"},
\r
134 {TOKinfinity, 0x5c0a010a, L"infinity"},
\r
135 {TOKendwhile, 0x5c64bff0, L"endwhile"},
\r
136 {TOKforeach, 0x67e31f38, L"foreach"},
\r
137 {TOKendfunc, 0x68f984a3, L"endfunc"},
\r
138 {TOKelseif, 0x78253218, L"elseif"},
\r
139 {TOKwhile, 0x84229259, L"while"},
\r
140 {TOKendfor, 0x8ab49d7e, L"endfor"},
\r
141 {TOKthrow, 0x8db05c94, L"throw"},
\r
142 {TOKstep, 0xa7a7887c, L"step"},
\r
143 {TOKupto, 0xb5155328, L"upto"},
\r
144 {TOKcontinue, 0xc0340685, L"continue"},
\r
145 {TOKfunc, 0xcdce60ec, L"func"},
\r
146 {TOKendif, 0xe0e8fee6, L"endif"},
\r
148 static const FX_WORD KEYWORD_START = TOKdo;
\r
149 static const FX_WORD KEYWORD_END = TOKendif;
\r
150 FX_LPCWSTR XFA_FM_KeywordToString(XFA_FM_TOKEN op)
\r
152 return keyWords[op].m_keword;
\r
154 CXFA_FMToken::CXFA_FMToken()
\r
156 m_type = TOKreserver;
\r
160 CXFA_FMToken::CXFA_FMToken( FX_DWORD uLineNum )
\r
162 m_type = TOKreserver;
\r
163 m_uLinenum = uLineNum;
\r
166 CXFA_FMToken::~CXFA_FMToken()
\r
169 CXFA_FMLexer::CXFA_FMLexer(FX_WSTR wsFormCalc, CXFA_FMErrorInfo *pErrorInfo)
\r
171 m_pScript = wsFormCalc.GetPtr();
\r
172 m_uLength = wsFormCalc.GetLength();
\r
173 m_uCurrentLine = 1;
\r
176 m_pErrorInfo = pErrorInfo;
\r
178 CXFA_FMToken *CXFA_FMLexer::NextToken()
\r
180 CXFA_FMToken *t = 0;
\r
184 if (m_pToken->m_pNext) {
\r
185 t = m_pToken->m_pNext;
\r
196 CXFA_FMToken * CXFA_FMLexer::Scan()
\r
199 CXFA_FMToken * p = FX_NEW CXFA_FMToken(m_uCurrentLine);
\r
200 if (!XFA_FMDChar::isAvalid(m_ptr)) {
\r
201 ch = XFA_FMDChar::get(m_ptr);
\r
202 Error(FMERR_UNSUPPORTED_CHAR, ch);
\r
207 if (!XFA_FMDChar::isAvalid(m_ptr)) {
\r
208 ch = XFA_FMDChar::get(m_ptr);
\r
209 Error(FMERR_UNSUPPORTED_CHAR, ch);
\r
212 ch = XFA_FMDChar::get(m_ptr);
\r
215 p->m_type = TOKeof;
\r
219 p->m_uLinenum = m_uCurrentLine;
\r
220 XFA_FMDChar::inc(m_ptr);
\r
223 XFA_FMDChar::inc(m_ptr);
\r
226 FX_LPCWSTR pTemp = 0;
\r
227 Comment(m_ptr, pTemp);
\r
232 FX_LPCWSTR pTemp = 0;
\r
233 p->m_type = TOKstring;
\r
234 iRet = String(p, m_ptr, pTemp);
\r
251 p->m_type = TOKnumber;
\r
252 FX_LPCWSTR pTemp = 0;
\r
253 iRet = Number(p, m_ptr, pTemp);
\r
256 Error(FMERR_BAD_SUFFIX_NUMBER);
\r
262 XFA_FMDChar::inc(m_ptr);
\r
263 if (XFA_FMDChar::isAvalid(m_ptr)) {
\r
264 ch = XFA_FMDChar::get(m_ptr);
\r
267 XFA_FMDChar::inc(m_ptr);
\r
270 p->m_type = TOKassign;
\r
274 ch = XFA_FMDChar::get(m_ptr);
\r
275 Error(FMERR_UNSUPPORTED_CHAR, ch);
\r
280 XFA_FMDChar::inc(m_ptr);
\r
281 if (XFA_FMDChar::isAvalid(m_ptr)) {
\r
282 ch = XFA_FMDChar::get(m_ptr);
\r
285 XFA_FMDChar::inc(m_ptr);
\r
287 } else if (ch == '>') {
\r
289 XFA_FMDChar::inc(m_ptr);
\r
296 ch = XFA_FMDChar::get(m_ptr);
\r
297 Error(FMERR_UNSUPPORTED_CHAR, ch);
\r
302 XFA_FMDChar::inc(m_ptr);
\r
303 if (XFA_FMDChar::isAvalid(m_ptr)) {
\r
304 ch = XFA_FMDChar::get(m_ptr);
\r
307 XFA_FMDChar::inc(m_ptr);
\r
314 ch = XFA_FMDChar::get(m_ptr);
\r
315 Error(FMERR_UNSUPPORTED_CHAR, ch);
\r
320 p->m_type = TOKcomma;
\r
321 XFA_FMDChar::inc(m_ptr);
\r
324 p->m_type = TOKlparen;
\r
325 XFA_FMDChar::inc(m_ptr);
\r
328 p->m_type = TOKrparen;
\r
329 XFA_FMDChar::inc(m_ptr);
\r
332 p->m_type = TOKlbracket;
\r
333 XFA_FMDChar::inc(m_ptr);
\r
336 p->m_type = TOKrbracket;
\r
337 XFA_FMDChar::inc(m_ptr);
\r
340 XFA_FMDChar::inc(m_ptr);
\r
341 p->m_type = TOKand;
\r
344 XFA_FMDChar::inc(m_ptr);
\r
348 XFA_FMDChar::inc(m_ptr);
\r
349 p->m_type = TOKplus;
\r
352 XFA_FMDChar::inc(m_ptr);
\r
353 p->m_type = TOKminus;
\r
356 XFA_FMDChar::inc(m_ptr);
\r
357 p->m_type = TOKmul;
\r
360 XFA_FMDChar::inc(m_ptr);
\r
361 if (XFA_FMDChar::isAvalid(m_ptr)) {
\r
362 ch = XFA_FMDChar::get(m_ptr);
\r
364 FX_LPCWSTR pTemp = 0;
\r
365 Comment(m_ptr, pTemp);
\r
369 p->m_type = TOKdiv;
\r
373 ch = XFA_FMDChar::get(m_ptr);
\r
374 Error(FMERR_UNSUPPORTED_CHAR, ch);
\r
379 XFA_FMDChar::inc(m_ptr);
\r
380 if (XFA_FMDChar::isAvalid(m_ptr)) {
\r
381 ch = XFA_FMDChar::get(m_ptr);
\r
383 p->m_type = TOKdotdot;
\r
384 XFA_FMDChar::inc(m_ptr);
\r
386 } else if (ch == '*') {
\r
387 p->m_type = TOKdotstar;
\r
388 XFA_FMDChar::inc(m_ptr);
\r
390 } else if (ch == '#') {
\r
391 p->m_type = TOKdotscream;
\r
392 XFA_FMDChar::inc(m_ptr);
\r
394 } else if (ch <= '9' && ch >= '0') {
\r
395 p->m_type = TOKnumber;
\r
396 FX_LPCWSTR pTemp = 0;
\r
397 XFA_FMDChar::dec(m_ptr);
\r
398 iRet = Number(p, m_ptr, pTemp);
\r
401 Error(FMERR_BAD_SUFFIX_NUMBER);
\r
405 p->m_type = TOKdot;
\r
409 ch = XFA_FMDChar::get(m_ptr);
\r
410 Error(FMERR_UNSUPPORTED_CHAR, ch);
\r
417 XFA_FMDChar::inc(m_ptr);
\r
420 FX_LPCWSTR pTemp = 0;
\r
421 iRet = Identifiers(p, m_ptr, pTemp);
\r
426 p->m_type = IsKeyword(p->m_wstring);
\r
432 FX_DWORD CXFA_FMLexer::Number(CXFA_FMToken *t, FX_LPCWSTR p, FX_LPCWSTR &pEnd)
\r
434 FX_DOUBLE number = 0;
\r
435 if (XFA_FMDChar::string2number(p, &number, pEnd)) {
\r
438 if (pEnd && XFA_FMDChar::isAlpha(pEnd)) {
\r
441 t->m_wstring = CFX_WideStringC(p, (pEnd - p));
\r
444 FX_DWORD CXFA_FMLexer::String(CXFA_FMToken *t, FX_LPCWSTR p, FX_LPCWSTR &pEnd)
\r
446 FX_LPCWSTR pStart = p;
\r
448 XFA_FMDChar::inc(p);
\r
449 ch = XFA_FMDChar::get(p);
\r
451 if (!XFA_FMDChar::isAvalid(p)) {
\r
452 ch = XFA_FMDChar::get(p);
\r
454 t->m_wstring = CFX_WideStringC(pStart, (pEnd - pStart));
\r
455 Error(FMERR_UNSUPPORTED_CHAR, ch);
\r
459 XFA_FMDChar::inc(p);
\r
460 if (!XFA_FMDChar::isAvalid(p)) {
\r
461 ch = XFA_FMDChar::get(p);
\r
463 t->m_wstring = CFX_WideStringC(pStart, (pEnd - pStart));
\r
464 Error(FMERR_UNSUPPORTED_CHAR, ch);
\r
467 ch = XFA_FMDChar::get(p);
\r
475 XFA_FMDChar::inc(p);
\r
476 ch = XFA_FMDChar::get(p);
\r
479 t->m_wstring = CFX_WideStringC(pStart, (pEnd - pStart));
\r
482 FX_DWORD CXFA_FMLexer::Identifiers(CXFA_FMToken *t, FX_LPCWSTR p, FX_LPCWSTR &pEnd)
\r
484 FX_LPCWSTR pStart = p;
\r
486 ch = XFA_FMDChar::get(p);
\r
487 XFA_FMDChar::inc(p);
\r
488 if (!XFA_FMDChar::isAvalid(p)) {
\r
490 t->m_wstring = CFX_WideStringC(pStart, (pEnd - pStart));
\r
491 Error(FMERR_UNSUPPORTED_CHAR, ch);
\r
494 ch = XFA_FMDChar::get(p);
\r
496 if (!XFA_FMDChar::isAvalid(p)) {
\r
498 t->m_wstring = CFX_WideStringC(pStart, (pEnd - pStart));
\r
499 Error(FMERR_UNSUPPORTED_CHAR, ch);
\r
502 ch = XFA_FMDChar::get(p);
\r
503 if (XFA_FMDChar::isUnicodeAlpha(ch)) {
\r
504 XFA_FMDChar::inc(p);
\r
507 t->m_wstring = CFX_WideStringC(pStart, (pEnd - pStart));
\r
512 t->m_wstring = CFX_WideStringC(pStart, (pEnd - pStart));
\r
515 void CXFA_FMLexer::Comment( FX_LPCWSTR p, FX_LPCWSTR &pEnd )
\r
518 XFA_FMDChar::inc(p);
\r
519 ch = XFA_FMDChar::get(p);
\r
522 XFA_FMDChar::inc(p);
\r
528 XFA_FMDChar::inc(p);
\r
532 XFA_FMDChar::inc(p);
\r
533 ch = XFA_FMDChar::get(p);
\r
537 XFA_FM_TOKEN CXFA_FMLexer::IsKeyword(FX_WSTR str)
\r
539 int32_t iLength = str.GetLength();
\r
540 uint32_t uHash = FX_HashCode_String_GetW(str.GetPtr(), iLength, TRUE);
\r
541 int32_t iStart = KEYWORD_START, iEnd = KEYWORD_END;
\r
542 int32_t iMid = (iStart + iEnd) / 2;
\r
543 XFA_FMKeyword keyword;
\r
545 iMid = (iStart + iEnd) / 2;
\r
546 keyword = keyWords[iMid];
\r
547 if (uHash == keyword.m_uHash) {
\r
548 return keyword.m_type;
\r
549 } else if (uHash < keyword.m_uHash) {
\r
554 } while (iStart <= iEnd);
\r
555 return TOKidentifier;
\r
557 CXFA_FMLexer::~CXFA_FMLexer()
\r
562 CXFA_FMToken *t1 = m_pToken;
\r
563 CXFA_FMToken *t2 = t1->m_pNext;
\r
574 void CXFA_FMLexer::Error(XFA_FM_ERRMSG msg, ...)
\r
576 m_pErrorInfo->linenum = m_uCurrentLine;
\r
577 FX_LPCWSTR lpMessageInfo = XFA_FM_ErrorMsg(msg);
\r
580 m_pErrorInfo->message.FormatV(lpMessageInfo, ap);
\r
583 FX_BOOL CXFA_FMLexer::HasError() const
\r
585 if (m_pErrorInfo->message.IsEmpty()) {
\r