/src/xpdf-4.06/xpdf/Lexer.cc
Line | Count | Source |
1 | | //======================================================================== |
2 | | // |
3 | | // Lexer.cc |
4 | | // |
5 | | // Copyright 1996-2003 Glyph & Cog, LLC |
6 | | // |
7 | | //======================================================================== |
8 | | |
9 | | #include <aconf.h> |
10 | | |
11 | | #include <stdlib.h> |
12 | | #include <stddef.h> |
13 | | #include <string.h> |
14 | | #include <ctype.h> |
15 | | #include "gmempp.h" |
16 | | #include "Lexer.h" |
17 | | #include "Error.h" |
18 | | |
19 | | //------------------------------------------------------------------------ |
20 | | |
21 | | // A '1' in this array means the character is white space. A '1' or |
22 | | // '2' means the character ends a name or command. |
23 | | static char specialChars[256] = { |
24 | | 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x |
25 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x |
26 | | 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x |
27 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x |
28 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x |
29 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x |
30 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x |
31 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x |
32 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x |
33 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x |
34 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax |
35 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx |
36 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx |
37 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx |
38 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex |
39 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx |
40 | | }; |
41 | | |
42 | | //------------------------------------------------------------------------ |
43 | | // Lexer |
44 | | //------------------------------------------------------------------------ |
45 | | |
46 | 611k | Lexer::Lexer(XRef *xref, Stream *str) { |
47 | 611k | Object obj; |
48 | | |
49 | 611k | curStr.initStream(str); |
50 | 611k | streams = new Array(xref); |
51 | 611k | streams->add(curStr.copy(&obj)); |
52 | 611k | strPtr = 0; |
53 | 611k | freeArray = gTrue; |
54 | 611k | curStr.streamReset(); |
55 | 611k | } |
56 | | |
57 | 48.3k | Lexer::Lexer(XRef *xref, Object *obj) { |
58 | 48.3k | Object obj2; |
59 | | |
60 | 48.3k | if (obj->isStream()) { |
61 | 47.8k | streams = new Array(xref); |
62 | 47.8k | freeArray = gTrue; |
63 | 47.8k | streams->add(obj->copy(&obj2)); |
64 | 47.8k | } else { |
65 | 523 | streams = obj->getArray(); |
66 | 523 | freeArray = gFalse; |
67 | 523 | } |
68 | 48.3k | strPtr = 0; |
69 | 48.3k | if (streams->getLength() > 0) { |
70 | 48.3k | streams->get(strPtr, &curStr); |
71 | 48.3k | curStr.streamReset(); |
72 | 48.3k | } |
73 | 48.3k | } |
74 | | |
75 | 659k | Lexer::~Lexer() { |
76 | 659k | if (!curStr.isNone()) { |
77 | 328k | curStr.streamClose(); |
78 | 328k | curStr.free(); |
79 | 328k | } |
80 | 659k | if (freeArray) { |
81 | 658k | delete streams; |
82 | 658k | } |
83 | 659k | } |
84 | | |
85 | 2.82G | int Lexer::getChar() { |
86 | 2.82G | int c; |
87 | | |
88 | 2.82G | c = EOF; |
89 | 2.82G | while (!curStr.isNone() && (c = curStr.streamGetChar()) == EOF) { |
90 | 331k | curStr.streamClose(); |
91 | 331k | curStr.free(); |
92 | 331k | ++strPtr; |
93 | 331k | if (strPtr < streams->getLength()) { |
94 | 1.40k | streams->get(strPtr, &curStr); |
95 | 1.40k | curStr.streamReset(); |
96 | 1.40k | } |
97 | 331k | } |
98 | 2.82G | return c; |
99 | 2.82G | } |
100 | | |
101 | 482M | int Lexer::lookChar() { |
102 | 482M | if (curStr.isNone()) { |
103 | 2.66k | return EOF; |
104 | 2.66k | } |
105 | 482M | return curStr.streamLookChar(); |
106 | 482M | } |
107 | | |
108 | 233M | Object *Lexer::getObj(Object *obj) { |
109 | 233M | char *p; |
110 | 233M | int c, c2; |
111 | 233M | GBool comment, neg, doubleMinus, done, invalid; |
112 | 233M | int numParen, nErrors; |
113 | 233M | int xi; |
114 | 233M | double xf, scale; |
115 | 233M | GString *s; |
116 | 233M | int n, m; |
117 | | |
118 | | // skip whitespace and comments |
119 | 233M | comment = gFalse; |
120 | 1.69G | while (1) { |
121 | 1.69G | if ((c = getChar()) == EOF) { |
122 | 129M | return obj->initEOF(); |
123 | 129M | } |
124 | 1.56G | if (comment) { |
125 | 24.0M | if (c == '\r' || c == '\n') |
126 | 299k | comment = gFalse; |
127 | 1.54G | } else if (c == '%') { |
128 | 301k | comment = gTrue; |
129 | 1.54G | } else if (specialChars[c] != 1) { |
130 | 103M | break; |
131 | 103M | } |
132 | 1.56G | } |
133 | | |
134 | | // start reading token |
135 | 103M | switch (c) { |
136 | | |
137 | | // number |
138 | 16.0M | case '0': case '1': case '2': case '3': case '4': |
139 | 21.8M | case '5': case '6': case '7': case '8': case '9': |
140 | 23.7M | case '+': case '-': case '.': |
141 | | // Adobe's number lexer has some "interesting" behavior: |
142 | | // "--123" is interpreted as 0 |
143 | | // "--123.4" is interpreted as -123.4 [I've seen this in the wild] |
144 | | // "50-100" is interpreted as 50 [I've seen this in the wild] |
145 | | // "50--100" is interpreted as 50 |
146 | | // "50-100.0" is an error -- but older versions of Acrobat may |
147 | | // have interpreted it as 50100.0 (?) |
148 | | // "50--100.0" is an error -- but older versions of Acrobat may |
149 | | // have interpreted it as 50100.0 (?) |
150 | | // "50.0-100" is interpreted as 50.0 (or maybe 50.0100?) |
151 | | // "50.0--100" is interpreted as 50.0 (or maybe 50.0100?) |
152 | | // "-50-100" is interpreted as -50 |
153 | | // "-" is interpreted as 0 |
154 | | // "-." is interpreted as 0.0 |
155 | 23.7M | neg = gFalse; |
156 | 23.7M | doubleMinus = gFalse; |
157 | 23.7M | xf = xi = 0; |
158 | 23.7M | if (c == '+') { |
159 | | // just ignore it |
160 | 23.6M | } else if (c == '-') { |
161 | 956k | neg = gTrue; |
162 | 956k | if (lookChar() == '-') { |
163 | 14.4k | doubleMinus = gTrue; |
164 | 22.8k | do { |
165 | 22.8k | getChar(); |
166 | 22.8k | } while (lookChar() == '-'); |
167 | 14.4k | } |
168 | 22.7M | } else if (c == '.') { |
169 | 846k | goto doReal; |
170 | 21.8M | } else { |
171 | 21.8M | xf = xi = c - '0'; |
172 | 21.8M | } |
173 | 63.8M | while (1) { |
174 | 63.8M | c = lookChar(); |
175 | 63.8M | if (isdigit(c)) { |
176 | 40.9M | getChar(); |
177 | 40.9M | xi = xi * 10 + (c - '0'); |
178 | 40.9M | if (xf < 1e20) { |
179 | 33.1M | xf = xf * 10 + (c - '0'); |
180 | 33.1M | } |
181 | 40.9M | } else if (c == '.') { |
182 | 2.83M | getChar(); |
183 | 2.83M | goto doReal; |
184 | 20.0M | } else { |
185 | 20.0M | break; |
186 | 20.0M | } |
187 | 63.8M | } |
188 | 20.2M | while ((c = lookChar()) == '-' || isdigit(c)) { |
189 | 152k | getChar(); |
190 | 152k | } |
191 | 20.0M | if (neg) { |
192 | 716k | xi = -xi; |
193 | 716k | } |
194 | 20.0M | if (doubleMinus) { |
195 | 12.6k | xi = 0; |
196 | 12.6k | } |
197 | 20.0M | obj->initInt(xi); |
198 | 20.0M | break; |
199 | 3.68M | doReal: |
200 | 3.68M | scale = 0.1; |
201 | 12.1M | while (1) { |
202 | 12.1M | c = lookChar(); |
203 | 12.1M | if (c == '-') { |
204 | 38.2k | error(errSyntaxWarning, getPos(), "Badly formatted number"); |
205 | 38.2k | getChar(); |
206 | 38.2k | continue; |
207 | 38.2k | } |
208 | 12.1M | if (!isdigit(c)) { |
209 | 3.68M | break; |
210 | 3.68M | } |
211 | 8.42M | getChar(); |
212 | 8.42M | xf = xf + scale * (c - '0'); |
213 | 8.42M | scale *= 0.1; |
214 | 8.42M | } |
215 | 3.68M | while ((c = lookChar()) == '-' || isdigit(c)) { |
216 | 0 | getChar(); |
217 | 0 | } |
218 | 3.68M | if (neg) { |
219 | 240k | xf = -xf; |
220 | 240k | } |
221 | 3.68M | obj->initReal(xf); |
222 | 3.68M | break; |
223 | | |
224 | | // string |
225 | 655k | case '(': |
226 | 655k | p = tokBuf; |
227 | 655k | n = 0; |
228 | 655k | numParen = 1; |
229 | 655k | done = gFalse; |
230 | 655k | s = NULL; |
231 | 655M | do { |
232 | 655M | c2 = EOF; |
233 | 655M | switch (c = getChar()) { |
234 | | |
235 | 14.8k | case EOF: |
236 | 14.8k | error(errSyntaxError, getPos(), "Unterminated string"); |
237 | 14.8k | done = gTrue; |
238 | 14.8k | break; |
239 | | |
240 | 3.06M | case '(': |
241 | 3.06M | ++numParen; |
242 | 3.06M | c2 = c; |
243 | 3.06M | break; |
244 | | |
245 | 2.30M | case ')': |
246 | 2.30M | if (--numParen == 0) { |
247 | 639k | done = gTrue; |
248 | 1.66M | } else { |
249 | 1.66M | c2 = c; |
250 | 1.66M | } |
251 | 2.30M | break; |
252 | | |
253 | 9.25M | case '\r': |
254 | | // The PDF spec says that any literal end-of-line sequence |
255 | | // (LF, CR, CR+LF) is translated to a single LF char. |
256 | 9.25M | c = lookChar(); |
257 | 9.25M | if (c == '\n') { |
258 | 179k | getChar(); |
259 | 179k | } |
260 | 9.25M | c2 = '\n'; |
261 | 9.25M | break; |
262 | | |
263 | 1.16M | case '\\': |
264 | 1.16M | switch (c = getChar()) { |
265 | 6.07k | case 'n': |
266 | 6.07k | c2 = '\n'; |
267 | 6.07k | break; |
268 | 61.9k | case 'r': |
269 | 61.9k | c2 = '\r'; |
270 | 61.9k | break; |
271 | 26.4k | case 't': |
272 | 26.4k | c2 = '\t'; |
273 | 26.4k | break; |
274 | 8.05k | case 'b': |
275 | 8.05k | c2 = '\b'; |
276 | 8.05k | break; |
277 | 4.69k | case 'f': |
278 | 4.69k | c2 = '\f'; |
279 | 4.69k | break; |
280 | 30.1k | case '\\': |
281 | 67.6k | case '(': |
282 | 101k | case ')': |
283 | 101k | c2 = c; |
284 | 101k | break; |
285 | 80.9k | case '0': case '1': case '2': case '3': |
286 | 125k | case '4': case '5': case '6': case '7': |
287 | 125k | c2 = c - '0'; |
288 | 125k | c = lookChar(); |
289 | 125k | if (c >= '0' && c <= '7') { |
290 | 59.0k | getChar(); |
291 | 59.0k | c2 = (c2 << 3) + (c - '0'); |
292 | 59.0k | c = lookChar(); |
293 | 59.0k | if (c >= '0' && c <= '7') { |
294 | 39.4k | getChar(); |
295 | 39.4k | c2 = (c2 << 3) + (c - '0'); |
296 | 39.4k | } |
297 | 59.0k | } |
298 | 125k | break; |
299 | 7.82k | case '\r': |
300 | 7.82k | c = lookChar(); |
301 | 7.82k | if (c == '\n') { |
302 | 1.19k | getChar(); |
303 | 1.19k | } |
304 | 7.82k | break; |
305 | 10.2k | case '\n': |
306 | 10.2k | break; |
307 | 964 | case EOF: |
308 | 964 | error(errSyntaxError, getPos(), "Unterminated string"); |
309 | 964 | done = gTrue; |
310 | 964 | break; |
311 | 815k | default: |
312 | 815k | c2 = c; |
313 | 815k | break; |
314 | 1.16M | } |
315 | 1.16M | break; |
316 | | |
317 | 639M | default: |
318 | 639M | c2 = c; |
319 | 639M | break; |
320 | 655M | } |
321 | | |
322 | 655M | if (c2 != EOF) { |
323 | 654M | if (n == tokBufSize) { |
324 | 4.99M | if (!s) |
325 | 102k | s = new GString(tokBuf, tokBufSize); |
326 | 4.88M | else |
327 | 4.88M | s->append(tokBuf, tokBufSize); |
328 | 4.99M | p = tokBuf; |
329 | 4.99M | n = 0; |
330 | 4.99M | } |
331 | 654M | *p++ = (char)c2; |
332 | 654M | ++n; |
333 | 654M | } |
334 | 655M | } while (!done); |
335 | 655k | if (!s) |
336 | 552k | s = new GString(tokBuf, n); |
337 | 102k | else |
338 | 102k | s->append(tokBuf, n); |
339 | 655k | obj->initString(s); |
340 | 655k | break; |
341 | | |
342 | | // name |
343 | 10.0M | case '/': |
344 | 10.0M | p = tokBuf; |
345 | 10.0M | n = 0; |
346 | 10.0M | s = NULL; |
347 | 10.0M | invalid = gFalse; |
348 | 50.7M | while ((c = lookChar()) != EOF && !specialChars[c]) { |
349 | 40.7M | getChar(); |
350 | 40.7M | if (c == '#') { |
351 | 854k | c2 = lookChar(); |
352 | 854k | if (c2 >= '0' && c2 <= '9') { |
353 | 4.76k | c = c2 - '0'; |
354 | 850k | } else if (c2 >= 'A' && c2 <= 'F') { |
355 | 49.6k | c = c2 - 'A' + 10; |
356 | 800k | } else if (c2 >= 'a' && c2 <= 'f') { |
357 | 100k | c = c2 - 'a' + 10; |
358 | 700k | } else { |
359 | 700k | error(errSyntaxError, getPos(), "Invalid hex escape in name"); |
360 | 700k | goto notEscChar; |
361 | 700k | } |
362 | 154k | getChar(); |
363 | 154k | c2 = lookChar(); |
364 | 154k | if (c2 >= '0' && c2 <= '9') { |
365 | 28.8k | c = (c << 4) + (c2 - '0'); |
366 | 125k | } else if (c2 >= 'A' && c2 <= 'F') { |
367 | 46.7k | c = (c << 4) + (c2 - 'A' + 10); |
368 | 79.0k | } else if (c2 >= 'a' && c2 <= 'f') { |
369 | 4.10k | c = (c << 4) + (c2 - 'a' + 10); |
370 | 74.9k | } else { |
371 | 74.9k | error(errSyntaxError, getPos(), "Invalid hex escape in name"); |
372 | 74.9k | goto notEscChar; |
373 | 74.9k | } |
374 | 79.7k | getChar(); |
375 | 79.7k | if (c == 0) { |
376 | 1.03k | invalid = gTrue; |
377 | 1.03k | } |
378 | 79.7k | } |
379 | 40.7M | notEscChar: |
380 | | // the PDF spec claims that names are limited to 127 chars, but |
381 | | // Distiller 8 will produce longer names, and Acrobat 8 will |
382 | | // accept longer names |
383 | 40.7M | ++n; |
384 | 40.7M | if (n < tokBufSize) { |
385 | 39.5M | *p++ = (char)c; |
386 | 39.5M | } else if (n == tokBufSize) { |
387 | 8.28k | *p = (char)c; |
388 | 8.28k | s = new GString(tokBuf, n); |
389 | 1.23M | } else { |
390 | 1.23M | s->append((char)c); |
391 | 1.23M | } |
392 | 40.7M | } |
393 | 10.0M | if (invalid) { |
394 | 1.03k | error(errSyntaxError, getPos(), "Null character in name"); |
395 | 1.03k | obj->initError(); |
396 | 1.03k | if (s) { |
397 | 315 | delete s; |
398 | 315 | } |
399 | 10.0M | } else if (n < tokBufSize) { |
400 | 10.0M | *p = '\0'; |
401 | 10.0M | obj->initName(tokBuf); |
402 | 10.0M | } else { |
403 | 7.97k | obj->initName(s->getCString()); |
404 | 7.97k | delete s; |
405 | 7.97k | } |
406 | 10.0M | break; |
407 | | |
408 | | // array punctuation |
409 | 10.2M | case '[': |
410 | 11.0M | case ']': |
411 | 11.0M | tokBuf[0] = (char)c; |
412 | 11.0M | tokBuf[1] = '\0'; |
413 | 11.0M | obj->initCmd(tokBuf); |
414 | 11.0M | break; |
415 | | |
416 | | // hex string or dict punctuation |
417 | 19.2M | case '<': |
418 | 19.2M | c = lookChar(); |
419 | | |
420 | | // dict punctuation |
421 | 19.2M | if (c == '<') { |
422 | 3.71M | getChar(); |
423 | 3.71M | tokBuf[0] = tokBuf[1] = '<'; |
424 | 3.71M | tokBuf[2] = '\0'; |
425 | 3.71M | obj->initCmd(tokBuf); |
426 | | |
427 | | // hex string |
428 | 15.5M | } else { |
429 | 15.5M | p = tokBuf; |
430 | 15.5M | m = n = 0; |
431 | 15.5M | c2 = 0; |
432 | 15.5M | s = NULL; |
433 | 15.5M | nErrors = 0; |
434 | 97.9M | while (nErrors < 100) { |
435 | 97.7M | c = getChar(); |
436 | 97.7M | if (c == '>') { |
437 | 15.3M | break; |
438 | 82.4M | } else if (c == EOF) { |
439 | 6.71k | error(errSyntaxError, getPos(), "Unterminated hex string"); |
440 | 6.71k | break; |
441 | 82.3M | } else if (specialChars[c] != 1) { |
442 | 72.7M | c2 = c2 << 4; |
443 | 72.7M | if (c >= '0' && c <= '9') { |
444 | 12.1M | c2 += c - '0'; |
445 | 60.5M | } else if (c >= 'A' && c <= 'F') { |
446 | 1.16M | c2 += c - 'A' + 10; |
447 | 59.4M | } else if (c >= 'a' && c <= 'f') { |
448 | 21.1M | c2 += c - 'a' + 10; |
449 | 38.2M | } else { |
450 | 38.2M | error(errSyntaxError, getPos(), |
451 | 38.2M | "Illegal character <{0:02x}> in hex string", c); |
452 | 38.2M | ++nErrors; |
453 | 38.2M | } |
454 | 72.7M | if (++m == 2) { |
455 | 29.0M | if (n == tokBufSize) { |
456 | 13.0k | if (!s) |
457 | 9.64k | s = new GString(tokBuf, tokBufSize); |
458 | 3.36k | else |
459 | 3.36k | s->append(tokBuf, tokBufSize); |
460 | 13.0k | p = tokBuf; |
461 | 13.0k | n = 0; |
462 | 13.0k | } |
463 | 29.0M | *p++ = (char)c2; |
464 | 29.0M | ++n; |
465 | 29.0M | c2 = 0; |
466 | 29.0M | m = 0; |
467 | 29.0M | } |
468 | 72.7M | } |
469 | 97.7M | } |
470 | 15.5M | if (!s) |
471 | 15.5M | s = new GString(tokBuf, n); |
472 | 9.64k | else |
473 | 9.64k | s->append(tokBuf, n); |
474 | 15.5M | if (m == 1) |
475 | 14.6M | s->append((char)(c2 << 4)); |
476 | 15.5M | obj->initString(s); |
477 | 15.5M | } |
478 | 19.2M | break; |
479 | | |
480 | | // dict punctuation |
481 | 4.97M | case '>': |
482 | 4.97M | c = lookChar(); |
483 | 4.97M | if (c == '>') { |
484 | 2.39M | getChar(); |
485 | 2.39M | tokBuf[0] = tokBuf[1] = '>'; |
486 | 2.39M | tokBuf[2] = '\0'; |
487 | 2.39M | obj->initCmd(tokBuf); |
488 | 2.57M | } else { |
489 | 2.57M | error(errSyntaxError, getPos(), "Illegal character '>'"); |
490 | 2.57M | obj->initError(); |
491 | 2.57M | } |
492 | 4.97M | break; |
493 | | |
494 | | // error |
495 | 1.54M | case ')': |
496 | 2.21M | case '{': |
497 | 2.40M | case '}': |
498 | 2.40M | error(errSyntaxError, getPos(), "Illegal character '{0:c}'", c); |
499 | 2.40M | obj->initError(); |
500 | 2.40M | break; |
501 | | |
502 | | // command |
503 | 31.2M | default: |
504 | 31.2M | p = tokBuf; |
505 | 31.2M | *p++ = (char)c; |
506 | 31.2M | n = 1; |
507 | 296M | while ((c = lookChar()) != EOF && !specialChars[c]) { |
508 | 266M | getChar(); |
509 | 266M | if (++n == tokBufSize) { |
510 | 1.13M | error(errSyntaxError, getPos(), "Command token too long"); |
511 | 1.13M | break; |
512 | 1.13M | } |
513 | 265M | *p++ = (char)c; |
514 | 265M | } |
515 | 31.2M | *p = '\0'; |
516 | 31.2M | if (tokBuf[0] == 't' && !strcmp(tokBuf, "true")) { |
517 | 146k | obj->initBool(gTrue); |
518 | 31.1M | } else if (tokBuf[0] == 'f' && !strcmp(tokBuf, "false")) { |
519 | 13.8k | obj->initBool(gFalse); |
520 | 31.1M | } else if (tokBuf[0] == 'n' && !strcmp(tokBuf, "null")) { |
521 | 15.2k | obj->initNull(); |
522 | 31.1M | } else { |
523 | 31.1M | obj->initCmd(tokBuf); |
524 | 31.1M | } |
525 | 31.2M | break; |
526 | 103M | } |
527 | | |
528 | 103M | return obj; |
529 | 103M | } |
530 | | |
531 | 210k | void Lexer::skipToNextLine() { |
532 | 210k | int c; |
533 | | |
534 | 555k | while (1) { |
535 | 555k | c = getChar(); |
536 | 555k | if (c == EOF || c == '\n') { |
537 | 97.5k | return; |
538 | 97.5k | } |
539 | 457k | if (c == '\r') { |
540 | 113k | if ((c = lookChar()) == '\n') { |
541 | 100k | getChar(); |
542 | 100k | } |
543 | 113k | return; |
544 | 113k | } |
545 | 457k | } |
546 | 210k | } |
547 | | |
548 | 57.9k | void Lexer::skipToEOF() { |
549 | 3.18M | while (getChar() != EOF) ; |
550 | 57.9k | } |
551 | | |
552 | 245M | GBool Lexer::isSpace(int c) { |
553 | 245M | return c >= 0 && c <= 0xff && specialChars[c] == 1; |
554 | 245M | } |