Mass remove dangerous and needless LPCWSTR casts.
[pdfium.git] / xfa / src / fxfa / src / fm2js / xfa_lexer.cpp
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
4 \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "xfa_fm2js.h"\r
8 struct XFA_FMDChar {\r
9     static FX_LPCWSTR inc(FX_LPCWSTR &p)\r
10     {\r
11         ++p;\r
12         return p;\r
13     }\r
14     static FX_LPCWSTR dec(FX_LPCWSTR &p)\r
15     {\r
16         --p;\r
17         return p;\r
18     }\r
19     static FX_UINT16 get(FX_LPCWSTR p)\r
20     {\r
21         return *p;\r
22     }\r
23     static FX_BOOL isWhiteSpace(FX_LPCWSTR p)\r
24     {\r
25         return (*p) == 0x09 || (*p) == 0x0b || (*p) == 0x0c || (*p) == 0x20;\r
26     }\r
27     static FX_BOOL isLineTerminator(FX_LPCWSTR p)\r
28     {\r
29         return *p == 0x0A || *p == 0x0D;\r
30     }\r
31     static FX_BOOL isBinary(FX_LPCWSTR p)\r
32     {\r
33         return (*p) >= '0' && (*p) <= '1';\r
34     }\r
35     static FX_BOOL isOctal(FX_LPCWSTR p)\r
36     {\r
37         return (*p) >= '0' && (*p) <= '7';\r
38     }\r
39     static FX_BOOL isDigital(FX_LPCWSTR p)\r
40     {\r
41         return (*p) >= '0' && (*p) <= '9';\r
42     }\r
43     static FX_BOOL isHex(FX_LPCWSTR p)\r
44     {\r
45         return isDigital(p) || ((*p) >= 'a' && (*p) <= 'f') || ((*p) >= 'A' && (*p) <= 'F');\r
46     }\r
47     static FX_BOOL isAlpha(FX_LPCWSTR p)\r
48     {\r
49         return ((*p) <= 'z' && (*p) >= 'a') || ((*p) <= 'Z' && (*p) >= 'A');\r
50     }\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(FX_UINT16 ch);\r
54 };\r
55 inline FX_BOOL XFA_FMDChar::isAvalid(FX_LPCWSTR p, FX_BOOL flag)\r
56 {\r
57     if (*p == 0) {\r
58         return 1;\r
59     }\r
60     if ((*p <= 0x0A && *p >= 0x09) || *p == 0x0D || (*p <= 0xd7ff && *p >= 0x20) || (*p <= 0xfffd && *p >= 0xe000)) {\r
61         return 1;\r
62     }\r
63     if (!flag) {\r
64         if (*p == 0x0B || *p == 0x0C) {\r
65             return 1;\r
66         }\r
67     }\r
68     return 0;\r
69 }\r
70 inline FX_BOOL XFA_FMDChar::string2number(FX_LPCWSTR s, FX_DOUBLE *pValue, FX_LPCWSTR &pEnd)\r
71 {\r
72     if (s) {\r
73         *pValue = wcstod((wchar_t *)s, (wchar_t **)&pEnd);\r
74     }\r
75     return 0;\r
76 }\r
77 inline FX_BOOL XFA_FMDChar::isUnicodeAlpha(FX_UINT16 ch)\r
78 {\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
82         return FALSE;\r
83     } else {\r
84         return TRUE;\r
85     }\r
86 }\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
147 };\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
151 {\r
152     return keyWords[op].m_keword;\r
153 }\r
154 CXFA_FMToken::CXFA_FMToken()\r
155 {\r
156     m_type = TOKreserver;\r
157     m_uLinenum = 1;\r
158     m_pNext = 0;\r
159 }\r
160 CXFA_FMToken::CXFA_FMToken( FX_DWORD uLineNum )\r
161 {\r
162     m_type = TOKreserver;\r
163     m_uLinenum = uLineNum;\r
164     m_pNext = 0;\r
165 }\r
166 CXFA_FMToken::~CXFA_FMToken()\r
167 {\r
168 }\r
169 CXFA_FMLexer::CXFA_FMLexer(FX_WSTR wsFormCalc, CXFA_FMErrorInfo *pErrorInfo)\r
170 {\r
171     m_pScript = wsFormCalc.GetPtr();\r
172     m_uLength = wsFormCalc.GetLength();\r
173     m_uCurrentLine = 1;\r
174     m_ptr = m_pScript;\r
175     m_pToken = 0;\r
176     m_pErrorInfo = pErrorInfo;\r
177 }\r
178 CXFA_FMToken *CXFA_FMLexer::NextToken()\r
179 {\r
180     CXFA_FMToken *t = 0;\r
181     if (!m_pToken) {\r
182         m_pToken = Scan();\r
183     } else {\r
184         if (m_pToken->m_pNext) {\r
185             t = m_pToken->m_pNext;\r
186             delete m_pToken;\r
187             m_pToken = t;\r
188         } else {\r
189             t = m_pToken;\r
190             m_pToken = Scan();\r
191             delete t;\r
192         }\r
193     }\r
194     return m_pToken;\r
195 }\r
196 CXFA_FMToken * CXFA_FMLexer::Scan()\r
197 {\r
198     FX_UINT16 ch = 0;\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
203         return p;\r
204     }\r
205     int iRet = 0;\r
206     while (1) {\r
207         if (!XFA_FMDChar::isAvalid(m_ptr)) {\r
208             ch = XFA_FMDChar::get(m_ptr);\r
209             Error(FMERR_UNSUPPORTED_CHAR, ch);\r
210             return p;\r
211         }\r
212         ch = XFA_FMDChar::get(m_ptr);\r
213         switch (ch) {\r
214             case 0:\r
215                 p->m_type = TOKeof;\r
216                 return p;\r
217             case 0x0A:\r
218                 ++m_uCurrentLine;\r
219                 p->m_uLinenum = m_uCurrentLine;\r
220                 XFA_FMDChar::inc(m_ptr);\r
221                 break;\r
222             case 0x0D:\r
223                 XFA_FMDChar::inc(m_ptr);\r
224                 break;\r
225             case ';': {\r
226                     FX_LPCWSTR pTemp = 0;\r
227                     Comment(m_ptr, pTemp);\r
228                     m_ptr = pTemp;\r
229                 }\r
230                 break;\r
231             case '"': {\r
232                     FX_LPCWSTR pTemp = 0;\r
233                     p->m_type = TOKstring;\r
234                     iRet = String(p, m_ptr, pTemp);\r
235                     if (iRet) {\r
236                         return p;\r
237                     }\r
238                     m_ptr = pTemp;\r
239                 }\r
240                 return p;\r
241             case '0':\r
242             case '1':\r
243             case '2':\r
244             case '3':\r
245             case '4':\r
246             case '5':\r
247             case '6':\r
248             case '7':\r
249             case '8':\r
250             case '9': {\r
251                     p->m_type = TOKnumber;\r
252                     FX_LPCWSTR pTemp = 0;\r
253                     iRet = Number(p, m_ptr, pTemp);\r
254                     m_ptr = pTemp;\r
255                     if (iRet) {\r
256                         Error(FMERR_BAD_SUFFIX_NUMBER);\r
257                         return p;\r
258                     }\r
259                 }\r
260                 return p;\r
261             case '=':\r
262                 XFA_FMDChar::inc(m_ptr);\r
263                 if (XFA_FMDChar::isAvalid(m_ptr)) {\r
264                     ch = XFA_FMDChar::get(m_ptr);\r
265                     if (ch == '=') {\r
266                         p->m_type = TOKeq;\r
267                         XFA_FMDChar::inc(m_ptr);\r
268                         return p;\r
269                     } else {\r
270                         p->m_type = TOKassign;\r
271                         return p;\r
272                     }\r
273                 } else {\r
274                     ch = XFA_FMDChar::get(m_ptr);\r
275                     Error(FMERR_UNSUPPORTED_CHAR, ch);\r
276                     return p;\r
277                 }\r
278                 break;\r
279             case '<':\r
280                 XFA_FMDChar::inc(m_ptr);\r
281                 if (XFA_FMDChar::isAvalid(m_ptr)) {\r
282                     ch = XFA_FMDChar::get(m_ptr);\r
283                     if (ch == '=') {\r
284                         p->m_type = TOKle;\r
285                         XFA_FMDChar::inc(m_ptr);\r
286                         return p;\r
287                     } else if (ch == '>') {\r
288                         p->m_type = TOKne;\r
289                         XFA_FMDChar::inc(m_ptr);\r
290                         return p;\r
291                     } else {\r
292                         p->m_type = TOKlt;\r
293                         return p;\r
294                     }\r
295                 } else {\r
296                     ch = XFA_FMDChar::get(m_ptr);\r
297                     Error(FMERR_UNSUPPORTED_CHAR, ch);\r
298                     return p;\r
299                 }\r
300                 break;\r
301             case '>':\r
302                 XFA_FMDChar::inc(m_ptr);\r
303                 if (XFA_FMDChar::isAvalid(m_ptr)) {\r
304                     ch = XFA_FMDChar::get(m_ptr);\r
305                     if (ch == '=') {\r
306                         p->m_type = TOKge;\r
307                         XFA_FMDChar::inc(m_ptr);\r
308                         return p;\r
309                     } else {\r
310                         p->m_type = TOKgt;\r
311                         return p;\r
312                     }\r
313                 } else {\r
314                     ch = XFA_FMDChar::get(m_ptr);\r
315                     Error(FMERR_UNSUPPORTED_CHAR, ch);\r
316                     return p;\r
317                 }\r
318                 break;\r
319             case ',':\r
320                 p->m_type = TOKcomma;\r
321                 XFA_FMDChar::inc(m_ptr);\r
322                 return p;\r
323             case '(':\r
324                 p->m_type = TOKlparen;\r
325                 XFA_FMDChar::inc(m_ptr);\r
326                 return p;\r
327             case ')':\r
328                 p->m_type = TOKrparen;\r
329                 XFA_FMDChar::inc(m_ptr);\r
330                 return p;\r
331             case '[':\r
332                 p->m_type = TOKlbracket;\r
333                 XFA_FMDChar::inc(m_ptr);\r
334                 return p;\r
335             case ']':\r
336                 p->m_type = TOKrbracket;\r
337                 XFA_FMDChar::inc(m_ptr);\r
338                 return p;\r
339             case '&':\r
340                 XFA_FMDChar::inc(m_ptr);\r
341                 p->m_type = TOKand;\r
342                 return p;\r
343             case '|':\r
344                 XFA_FMDChar::inc(m_ptr);\r
345                 p->m_type = TOKor;\r
346                 return p;\r
347             case '+':\r
348                 XFA_FMDChar::inc(m_ptr);\r
349                 p->m_type = TOKplus;\r
350                 return p;\r
351             case '-':\r
352                 XFA_FMDChar::inc(m_ptr);\r
353                 p->m_type = TOKminus;\r
354                 return p;\r
355             case '*':\r
356                 XFA_FMDChar::inc(m_ptr);\r
357                 p->m_type = TOKmul;\r
358                 return p;\r
359             case '/':\r
360                 XFA_FMDChar::inc(m_ptr);\r
361                 if (XFA_FMDChar::isAvalid(m_ptr)) {\r
362                     ch = XFA_FMDChar::get(m_ptr);\r
363                     if (ch == '/') {\r
364                         FX_LPCWSTR pTemp = 0;\r
365                         Comment(m_ptr, pTemp);\r
366                         m_ptr = pTemp;\r
367                         break;\r
368                     } else {\r
369                         p->m_type = TOKdiv;\r
370                         return p;\r
371                     }\r
372                 } else {\r
373                     ch = XFA_FMDChar::get(m_ptr);\r
374                     Error(FMERR_UNSUPPORTED_CHAR, ch);\r
375                     return p;\r
376                 }\r
377                 break;\r
378             case '.':\r
379                 XFA_FMDChar::inc(m_ptr);\r
380                 if (XFA_FMDChar::isAvalid(m_ptr)) {\r
381                     ch = XFA_FMDChar::get(m_ptr);\r
382                     if (ch == '.') {\r
383                         p->m_type = TOKdotdot;\r
384                         XFA_FMDChar::inc(m_ptr);\r
385                         return p;\r
386                     } else if (ch == '*') {\r
387                         p->m_type = TOKdotstar;\r
388                         XFA_FMDChar::inc(m_ptr);\r
389                         return p;\r
390                     } else if (ch == '#') {\r
391                         p->m_type = TOKdotscream;\r
392                         XFA_FMDChar::inc(m_ptr);\r
393                         return p;\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
399                         m_ptr = pTemp;\r
400                         if (iRet) {\r
401                             Error(FMERR_BAD_SUFFIX_NUMBER);\r
402                         }\r
403                         return p;\r
404                     } else {\r
405                         p->m_type = TOKdot;\r
406                         return p;\r
407                     }\r
408                 } else {\r
409                     ch = XFA_FMDChar::get(m_ptr);\r
410                     Error(FMERR_UNSUPPORTED_CHAR, ch);\r
411                     return p;\r
412                 }\r
413             case 0x09:\r
414             case 0x0B:\r
415             case 0x0C:\r
416             case 0x20:\r
417                 XFA_FMDChar::inc(m_ptr);\r
418                 break;\r
419             default: {\r
420                     FX_LPCWSTR pTemp = 0;\r
421                     iRet = Identifiers(p, m_ptr, pTemp);\r
422                     m_ptr = pTemp;\r
423                     if (iRet) {\r
424                         return p;\r
425                     }\r
426                     p->m_type = IsKeyword(p->m_wstring);\r
427                 }\r
428                 return p;\r
429         }\r
430     }\r
431 }\r
432 FX_DWORD CXFA_FMLexer::Number(CXFA_FMToken *t, FX_LPCWSTR p, FX_LPCWSTR &pEnd)\r
433 {\r
434     FX_DOUBLE number = 0;\r
435     if (XFA_FMDChar::string2number(p, &number, pEnd)) {\r
436         return 1;\r
437     }\r
438     if (pEnd && XFA_FMDChar::isAlpha(pEnd)) {\r
439         return 1;\r
440     }\r
441     t->m_wstring = CFX_WideStringC(p, (pEnd - p));\r
442     return 0;\r
443 }\r
444 FX_DWORD CXFA_FMLexer::String(CXFA_FMToken *t, FX_LPCWSTR p, FX_LPCWSTR &pEnd)\r
445 {\r
446     FX_LPCWSTR pStart = p;\r
447     FX_UINT16 ch = 0;\r
448     XFA_FMDChar::inc(p);\r
449     ch = XFA_FMDChar::get(p);\r
450     while (ch) {\r
451         if (!XFA_FMDChar::isAvalid(p)) {\r
452             ch = XFA_FMDChar::get(p);\r
453             pEnd = p;\r
454             t->m_wstring = CFX_WideStringC(pStart, (pEnd - pStart));\r
455             Error(FMERR_UNSUPPORTED_CHAR, ch);\r
456             return 1;\r
457         }\r
458         if (ch == '"') {\r
459             XFA_FMDChar::inc(p);\r
460             if (!XFA_FMDChar::isAvalid(p)) {\r
461                 ch = XFA_FMDChar::get(p);\r
462                 pEnd = p;\r
463                 t->m_wstring = CFX_WideStringC(pStart, (pEnd - pStart));\r
464                 Error(FMERR_UNSUPPORTED_CHAR, ch);\r
465                 return 1;\r
466             }\r
467             ch = XFA_FMDChar::get(p);\r
468             if (ch == '"') {\r
469                 goto NEXT;\r
470             } else {\r
471                 break;\r
472             }\r
473         }\r
474 NEXT:\r
475         XFA_FMDChar::inc(p);\r
476         ch = XFA_FMDChar::get(p);\r
477     }\r
478     pEnd = p;\r
479     t->m_wstring = CFX_WideStringC(pStart, (pEnd - pStart));\r
480     return 0;\r
481 }\r
482 FX_DWORD CXFA_FMLexer::Identifiers(CXFA_FMToken *t, FX_LPCWSTR p, FX_LPCWSTR &pEnd)\r
483 {\r
484     FX_LPCWSTR pStart = p;\r
485     FX_UINT16 ch = 0;\r
486     ch = XFA_FMDChar::get(p);\r
487     XFA_FMDChar::inc(p);\r
488     if (!XFA_FMDChar::isAvalid(p)) {\r
489         pEnd = p;\r
490         t->m_wstring = CFX_WideStringC(pStart, (pEnd - pStart));\r
491         Error(FMERR_UNSUPPORTED_CHAR, ch);\r
492         return 1;\r
493     }\r
494     ch = XFA_FMDChar::get(p);\r
495     while (ch) {\r
496         if (!XFA_FMDChar::isAvalid(p)) {\r
497             pEnd = p;\r
498             t->m_wstring = CFX_WideStringC(pStart, (pEnd - pStart));\r
499             Error(FMERR_UNSUPPORTED_CHAR, ch);\r
500             return 1;\r
501         }\r
502         ch = XFA_FMDChar::get(p);\r
503         if (XFA_FMDChar::isUnicodeAlpha(ch)) {\r
504             XFA_FMDChar::inc(p);\r
505         } else {\r
506             pEnd = p;\r
507             t->m_wstring = CFX_WideStringC(pStart, (pEnd - pStart));\r
508             return 0;\r
509         }\r
510     }\r
511     pEnd = p;\r
512     t->m_wstring = CFX_WideStringC(pStart, (pEnd - pStart));\r
513     return 0;\r
514 }\r
515 void CXFA_FMLexer::Comment( FX_LPCWSTR p, FX_LPCWSTR &pEnd )\r
516 {\r
517     unsigned ch = 0;\r
518     XFA_FMDChar::inc(p);\r
519     ch = XFA_FMDChar::get(p);\r
520     while (ch) {\r
521         if (ch == 0x0D) {\r
522             XFA_FMDChar::inc(p);\r
523             pEnd = p;\r
524             return;\r
525         }\r
526         if (ch == 0x0A) {\r
527             ++m_uCurrentLine;\r
528             XFA_FMDChar::inc(p);\r
529             pEnd = p;\r
530             return;\r
531         }\r
532         XFA_FMDChar::inc(p);\r
533         ch = XFA_FMDChar::get(p);\r
534     }\r
535     pEnd = p;\r
536 }\r
537 XFA_FM_TOKEN CXFA_FMLexer::IsKeyword(FX_WSTR str)\r
538 {\r
539     FX_INT32 iLength = str.GetLength();\r
540     FX_UINT32 uHash = FX_HashCode_String_GetW(str.GetPtr(), iLength, TRUE);\r
541     FX_INT32 iStart = KEYWORD_START, iEnd = KEYWORD_END;\r
542     FX_INT32 iMid = (iStart + iEnd) / 2;\r
543     XFA_FMKeyword keyword;\r
544     do {\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
550             iEnd = iMid - 1;\r
551         } else {\r
552             iStart = iMid + 1;\r
553         }\r
554     } while (iStart <= iEnd);\r
555     return TOKidentifier;\r
556 }\r
557 CXFA_FMLexer::~CXFA_FMLexer()\r
558 {\r
559     m_pScript = 0;\r
560     m_ptr = m_pScript;\r
561     if (m_pToken) {\r
562         CXFA_FMToken *t1 = m_pToken;\r
563         CXFA_FMToken *t2 = t1->m_pNext;\r
564         while (t2) {\r
565             delete t1;\r
566             t1 = t2;\r
567             t2 = t2->m_pNext;\r
568         }\r
569         delete m_pToken;\r
570         m_pToken = 0;\r
571     }\r
572     m_pErrorInfo = 0;\r
573 }\r
574 void CXFA_FMLexer::Error(XFA_FM_ERRMSG msg, ...)\r
575 {\r
576     m_pErrorInfo->linenum = m_uCurrentLine;\r
577     FX_LPCWSTR lpMessageInfo = XFA_FM_ErrorMsg(msg);\r
578     va_list ap;\r
579     va_start(ap, msg);\r
580     m_pErrorInfo->message.FormatV(lpMessageInfo, ap);\r
581     va_end(ap);\r
582 }\r
583 FX_BOOL CXFA_FMLexer::HasError() const\r
584 {\r
585     if (m_pErrorInfo->message.IsEmpty()) {\r
586         return FALSE;\r
587     }\r
588     return TRUE;\r
589 }\r