]> www.fi.muni.cz Git - evince.git/blob - pdf/xpdf/Parser.cc
Compiles at least :)
[evince.git] / pdf / xpdf / Parser.cc
1 //========================================================================
2 //
3 // Parser.cc
4 //
5 // Copyright 1996 Derek B. Noonburg
6 //
7 //========================================================================
8
9 #ifdef __GNUC__
10 #pragma implementation
11 #endif
12
13 #include <stddef.h>
14 #include "Object.h"
15 #include "Array.h"
16 #include "Dict.h"
17 #include "Parser.h"
18 #include "Error.h"
19
20 Parser::Parser(Lexer *lexer1) {
21   lexer = lexer1;
22   inlineImg = 0;
23   lexer->getObj(&buf1);
24   lexer->getObj(&buf2);
25 }
26
27 Parser::~Parser() {
28   buf1.free();
29   buf2.free();
30   delete lexer;
31 }
32
33 Object *Parser::getObj(Object *obj) {
34   char *key;
35   Stream *str;
36   Object obj2;
37   int num;
38
39   // refill buffer after inline image data
40   if (inlineImg == 2) {
41     buf1.free();
42     buf2.free();
43     lexer->getObj(&buf1);
44     lexer->getObj(&buf2);
45     inlineImg = 0;
46   }
47
48   // array
49   if (buf1.isCmd("[")) {
50     shift();
51     obj->initArray();
52     while (!buf1.isCmd("]") && !buf1.isEOF())
53       obj->arrayAdd(getObj(&obj2));
54     if (buf1.isEOF())
55       error(getPos(), "End of file inside array");
56     shift();
57
58   // dictionary or stream
59   } else if (buf1.isCmd("<<")) {
60     shift();
61     obj->initDict();
62     while (!buf1.isCmd(">>") && !buf1.isEOF()) {
63       if (!buf1.isName()) {
64         error(getPos(), "Dictionary key must be a name object");
65         shift();
66       } else {
67         key = copyString(buf1.getName());
68         shift();
69         if (buf1.isEOF() || buf1.isError())
70           break;
71         obj->dictAdd(key, getObj(&obj2));
72       }
73     }
74     if (buf1.isEOF())
75       error(getPos(), "End of file inside dictionary");
76     if (buf2.isCmd("stream")) {
77       if ((str = makeStream(obj))) {
78         obj->initStream(str);
79       } else {
80         obj->free();
81         obj->initError();
82       }
83     } else {
84       shift();
85     }
86
87   // indirect reference or integer
88   } else if (buf1.isInt()) {
89     num = buf1.getInt();
90     shift();
91     if (buf1.isInt() && buf2.isCmd("R")) {
92       obj->initRef(num, buf1.getInt());
93       shift();
94       shift();
95     } else {
96       obj->initInt(num);
97     }
98
99   // simple object
100   } else {
101     buf1.copy(obj);
102     shift();
103   }
104
105   return obj;
106 }
107
108 Stream *Parser::makeStream(Object *dict) {
109   Object obj;
110   Stream *str;
111   int pos, length;
112
113   // get stream start position
114   lexer->skipToNextLine();
115   pos = lexer->getPos();
116
117   // get length
118   dict->dictLookup("Length", &obj);
119   if (obj.isInt()) {
120     length = obj.getInt();
121     obj.free();
122   } else {
123     error(getPos(), "Bad 'Length' attribute in stream");
124     obj.free();
125     return NULL;
126   }
127
128   // make base stream
129   str = new FileStream(lexer->getStream()->getFile(), pos, length, dict);
130
131   // get filters
132   str = str->addFilters(dict);
133
134   // skip over stream data
135   lexer->setPos(pos + length);
136
137   // refill token buffers and check for 'endstream'
138   shift();  // kill '>>'
139   shift();  // kill 'stream'
140   if (buf1.isCmd("endstream"))
141     shift();
142   else
143     error(getPos(), "Missing 'endstream'");
144
145   return str;
146 }
147
148 void Parser::shift() {
149   if (inlineImg > 0) {
150     ++inlineImg;
151   } else if (buf2.isCmd("ID")) {
152     lexer->skipChar();          // skip char after 'ID' command
153     inlineImg = 1;
154   }
155   buf1.free();
156   buf1 = buf2;
157   if (inlineImg > 0)            // don't buffer inline image data
158     buf2.initNull();
159   else
160     lexer->getObj(&buf2);
161 }