pscommentlexer.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2002, Dirk Schönberger <dirk.schoenberger@sz-online.de>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20#include <stdlib.h>
21#include <ctype.h>
22#include <tqstringlist.h>
23#include "pscommentlexer.h"
24
25#define CATEGORY_WHITESPACE -1
26#define CATEGORY_ALPHA -2
27#define CATEGORY_DIGIT -3
28#define CATEGORY_SPECIAL -4
29#define CATEGORY_LETTERHEX -5
30#define CATEGORY_INTTOOLONG -6
31
32#define CATEGORY_ANY -127
33
34#define MAX_INTLEN 9
35#define MIN_HEXCHARS 6
36
37#define STOP 0
38
39int iswhitespace(char c){
40 return (c==' ')||(c=='\n')||(c=='\t')||(c=='\r');
41}
42
43int isSpecial(char c){
44 return (c=='*')||(c=='_')||(c=='?')||(c=='~')||(c=='-')||(c=='^')||(c=='`')||(c=='!')||(c=='.')||(c=='@')||(c=='&')||(c=='$')||(c=='=');
45}
46
47int isletterhex(char c){
48 return (c=='A')||(c=='B')||(c=='C')||(c=='D')||(c=='E')||(c=='F');
49}
50
51const char*statetoa (State state){
52 switch (state)
53 {
54 case State_Comment : return "comment";
55 case State_CommentEncodedChar : return "encoded char (comment)";
56 default : return "unknown";
57 }
58}
59
60typedef struct {
61 State oldState;
62 signed char c;
63 State newState;
64 Action action;
65} Transition;
66
67static Transition transitions[] = {
68 { State_Comment, '\n', State_Start, Action_Output},
69 { State_Comment, '\r', State_Start, Action_Output},
70 { State_Comment, '\\', State_CommentEncodedChar, Action_InitTemp},
71 { State_Comment, CATEGORY_ANY, State_Comment, Action_Copy},
72 { State_CommentEncodedChar, '\\', State_Comment, Action_Copy},
73 { State_CommentEncodedChar, CATEGORY_DIGIT, State_CommentEncodedChar, Action_CopyTemp},
74 { State_CommentEncodedChar, CATEGORY_ANY, State_Comment, Action_DecodeUnget},
75 { State_Start, '%', State_Comment, Action_Ignore},
76 { State_Start, CATEGORY_ANY, State_Start, Action_Ignore},
77 { State_Start, STOP, State_Start, Action_Abort}
78};
79
80PSCommentLexer::PSCommentLexer(){
81}
82PSCommentLexer::~PSCommentLexer(){
83}
84
85bool PSCommentLexer::parse (TQIODevice& fin){
86 char c;
87
88 m_buffer.clear();
89 m_curState = State_Start;
90
91 parsingStarted();
92
93 while (!fin.atEnd())
94 {
95 c = fin.getch ();
96
97// tqDebug ("got %c", c);
98
99 State newState;
100 Action action;
101
102 nextStep (c, &newState, &action);
103
104 switch (action)
105 {
106 case Action_Copy :
107 m_buffer.append (c);
108 break;
109 case Action_CopyOutput :
110 m_buffer.append (c);
111 doOutput();
112 break;
113 case Action_Output :
114 doOutput();
115 break;
116 case Action_OutputUnget :
117 doOutput();
118 fin.ungetch(c);
119 break;
120 case Action_Ignore :
121 /* ignore */
122 break;
123 case Action_Abort :
124 tqWarning ( "state %s / %s char %c (%d)" , statetoa(m_curState), statetoa(newState), c, c );
125 parsingAborted();
126 return false;
127 break;
128 case Action_InitTemp :
129 m_temp.clear();
130 break;
131 case Action_CopyTemp :
132 m_temp.append (c);
133 break;
134 case Action_DecodeUnget :
135 m_buffer.append (decode());
136 fin.ungetch(c);
137 break;
138 default :
139 tqWarning ( "unknown action: %d ", action);
140 }
141
142 m_curState = newState;
143 }
144
145 parsingFinished();
146 return true;
147}
148
149void PSCommentLexer::doOutput ()
150{
151 if (m_buffer.length() == 0) return;
152 switch (m_curState)
153 {
154 case State_Comment :
155 gotComment (m_buffer.latin1());
156 break;
157 default:
158 tqWarning ( "unknown state: %d", m_curState );
159 }
160
161 m_buffer.clear();
162}
163
164void PSCommentLexer::gotComment (const char *value) {
165 tqDebug ( "gotComment: %s ", value );
166}
167
168void PSCommentLexer::parsingStarted() {
169 tqDebug ( "parsing started" );
170}
171
172void PSCommentLexer::parsingFinished() {
173 tqDebug ( "parsing finished" );
174}
175
176void PSCommentLexer::parsingAborted() {
177 tqDebug ( "parsing aborted" );
178}
179
180void PSCommentLexer::nextStep (char c, State *newState, Action *newAction) {
181 int i=0;
182
183 while (true) {
184 Transition trans = transitions[i];
185
186 if (trans.c == STOP) {
187 *newState = trans.newState;
188 *newAction = trans.action;
189 return;
190 }
191
192 bool found = false;
193
194 if (trans.oldState == m_curState) {
195 switch (trans.c) {
196 case CATEGORY_WHITESPACE : found = isspace(c); break;
197 case CATEGORY_ALPHA : found = isalpha(c); break;
198 case CATEGORY_DIGIT : found = isdigit(c); break;
199 case CATEGORY_SPECIAL : found = isSpecial(c); break;
200 case CATEGORY_LETTERHEX : found = isletterhex(c); break;
201 case CATEGORY_INTTOOLONG : found = m_buffer.length() > MAX_INTLEN; break;
202 case CATEGORY_ANY : found = true; break;
203 default : found = (trans.c == c);
204 }
205
206 if (found) {
207 *newState = trans.newState;
208 *newAction = trans.action;
209
210 return;
211 }
212 }
213
214
215 i++;
216 }
217}
218
219uchar PSCommentLexer::decode()
220{
221 uchar value = m_temp.toString().toShort(NULL, 8);
222// tqDebug ("got encoded char %c",value);
223 return value;
224}
225
226/* StringBuffer implementation */
227
228int initialSize = 20;
229int addSize = 10;
230
231StringBuffer::StringBuffer () {
232 m_buffer = (char*)calloc (initialSize, sizeof(char));
233 m_length = 0;
234 m_capacity = initialSize;
235}
236
237StringBuffer::~StringBuffer (){
238 free(m_buffer);
239}
240
241void StringBuffer::append (char c){
242 ensureCapacity(m_length + 1);
243 m_buffer[m_length] = c;
244 m_length++;
245}
246
247void StringBuffer::clear(){
248 for (uint i=0; i<m_length; i++) m_buffer[i] = '\0';
249 m_length = 0;
250}
251
252TQString StringBuffer::toString() const {
253 TQString ret(m_buffer);
254 return ret;
255}
256
257void StringBuffer::ensureCapacity (int p_capacity) {
258 if (m_capacity >= p_capacity) return;
259
260 int newSize = m_capacity + addSize;
261 if (p_capacity > newSize) newSize = p_capacity;
262
263 char* oldBuffer = m_buffer;
264 char *newBuffer = (char*)calloc (newSize, sizeof(char));
265 strcpy (newBuffer, m_buffer);
266 free(oldBuffer);
267 m_buffer = newBuffer;
268 m_capacity = newSize;
269}
270
271uint StringBuffer::length() {
272 return m_length;
273}
274
275double StringBuffer::toFloat() {
276 TQString data = toString();
277 return data.toFloat();
278}
279
280int StringBuffer::toInt() {
281 TQString data = toString();
282 return data.toInt();
283}
284
285const char *StringBuffer::latin1() {
286 return m_buffer;
287}
288
289TQString StringBuffer::mid( uint index, uint len) const {
290 TQString data = toString();
291 return data.mid(index,len);
292}
293
294/* BoundingBoxExtractor */
295BoundingBoxExtractor:: BoundingBoxExtractor() : m_llx(0), m_lly(0), m_urx(0), m_ury(0) {}
296BoundingBoxExtractor::~BoundingBoxExtractor() {}
297
298void BoundingBoxExtractor::gotComment (const char *value)
299{
300 TQString data (value);
301 if (data.find("%BoundingBox:")==-1) return;
302
303 getRectangle (value, m_llx, m_lly, m_urx, m_ury);
304}
305
306bool BoundingBoxExtractor::getRectangle (const char* input, int &llx, int &lly, int &urx, int &ury)
307{
308 if (input == NULL) return false;
309
310 TQString s(input);
311 if (s.contains ("(atend)")) return false;
312
313 TQString s2 = s.remove("%BoundingBox:");
314 TQStringList values = TQStringList::split (" ", s2.latin1());
315 tqDebug("size is %d",values.size());
316// if (values.size() < 5) return false;
317 llx = values[0].toInt();
318 lly = values[1].toInt();
319 urx = values[2].toInt();
320 ury = values[3].toInt();
321
322 return true;
323}
324