1 //========================================================================
5 // Copyright 1996 Derek B. Noonburg
7 //========================================================================
10 #pragma implementation
20 //------------------------------------------------------------------------
22 // A '1' in this array means the character is white space. A '1' or
23 // '2' means the character ends a name or command.
24 static char specialChars[256] = {
25 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x
26 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x
27 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x
28 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x
29 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x
30 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x
31 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x
32 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x
33 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x
34 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x
35 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax
36 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx
37 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx
38 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx
39 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex
40 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx
43 //------------------------------------------------------------------------
45 //------------------------------------------------------------------------
47 Lexer::Lexer(Stream *str) {
50 curStr.initStream(str);
51 streams = new Array();
52 streams->add(curStr.copy(&obj));
58 Lexer::Lexer(Object *obj) {
61 if (obj->isStream()) {
62 streams = new Array();
64 streams->add(obj->copy(&obj2));
66 streams = obj->getArray();
70 if (streams->getLength() > 0) {
71 streams->get(strPtr, &curStr);
77 if (!curStr.isNone()) {
86 int Lexer::getChar() {
90 while (!curStr.isNone() && (c = curStr.streamGetChar()) == EOF) {
94 if (strPtr < streams->getLength()) {
95 streams->get(strPtr, &curStr);
102 int Lexer::lookChar() {
103 if (curStr.isNone()) {
106 return curStr.streamLookChar();
109 Object *Lexer::getObj(Object *obj) {
112 GBool comment, neg, done;
119 // skip whitespace and comments
122 if ((c = getChar()) == EOF) {
123 return obj->initEOF();
126 if (c == '\r' || c == '\n')
128 } else if (c == '%') {
130 } else if (specialChars[c] != 1) {
135 // start reading token
139 case '0': case '1': case '2': case '3': case '4':
140 case '5': case '6': case '7': case '8': case '9':
146 } else if (c == '.') {
155 xi = xi * 10 + (c - '0');
156 } else if (c == '.') {
176 xf = xf + scale * (c - '0');
193 switch (c = getChar()) {
197 // This breaks some PDF files, e.g., ones from Photoshop.
201 error(getPos(), "Unterminated string");
215 switch (c = getChar()) {
236 case '0': case '1': case '2': case '3':
237 case '4': case '5': case '6': case '7':
240 if (c >= '0' && c <= '7') {
242 c2 = (c2 << 3) + (c - '0');
244 if (c >= '0' && c <= '7') {
246 c2 = (c2 << 3) + (c - '0');
259 error(getPos(), "Unterminated string");
274 if (n == tokBufSize) {
276 s = new GString(tokBuf, tokBufSize);
278 s->append(tokBuf, tokBufSize);
287 s = new GString(tokBuf, n);
289 s->append(tokBuf, n);
297 while ((c = lookChar()) != EOF && !specialChars[c]) {
301 if (c2 >= '0' && c2 <= '9') {
303 } else if (c2 >= 'A' && c2 <= 'F') {
305 } else if (c2 >= 'a' && c2 <= 'f') {
313 if (c2 >= '0' && c2 <= '9') {
315 } else if (c2 >= 'A' && c2 <= 'F') {
317 } else if (c2 >= 'a' && c2 <= 'f') {
320 error(getPos(), "Illegal digit in hex char in name");
324 if (++n == tokBufSize) {
325 error(getPos(), "Name token too long");
331 obj->initName(tokBuf);
339 obj->initCmd(tokBuf);
342 // hex string or dict punctuation
349 tokBuf[0] = tokBuf[1] = '<';
351 obj->initCmd(tokBuf);
363 } else if (c == EOF) {
364 error(getPos(), "Unterminated hex string");
366 } else if (specialChars[c] != 1) {
368 if (c >= '0' && c <= '9')
370 else if (c >= 'A' && c <= 'F')
372 else if (c >= 'a' && c <= 'f')
375 error(getPos(), "Illegal character <%02x> in hex string", c);
377 if (n == tokBufSize) {
379 s = new GString(tokBuf, tokBufSize);
381 s->append(tokBuf, tokBufSize);
393 s = new GString(tokBuf, n);
395 s->append(tokBuf, n);
397 s->append((char)(c2 << 4));
407 tokBuf[0] = tokBuf[1] = '>';
409 obj->initCmd(tokBuf);
411 error(getPos(), "Illegal character '>'");
420 error(getPos(), "Illegal character '%c'", c);
429 while ((c = lookChar()) != EOF && !specialChars[c]) {
431 if (++n == tokBufSize) {
432 error(getPos(), "Command token too long");
438 if (tokBuf[0] == 't' && !strcmp(tokBuf, "true")) {
439 obj->initBool(gTrue);
440 } else if (tokBuf[0] == 'f' && !strcmp(tokBuf, "false")) {
441 obj->initBool(gFalse);
442 } else if (tokBuf[0] == 'n' && !strcmp(tokBuf, "null")) {
445 obj->initCmd(tokBuf);
453 void Lexer::skipToNextLine() {
458 if (c == EOF || c == '\n') {
462 if ((c = lookChar()) == '\n') {