1 #include <stdio.h>
2 #include "token.h"
3
4 //-------- First we define token dl-list members ----------------//
5
6
7 token* curr_token;
8
9 token token::dummy(CAT_SPEC, TKN_DUMMY); // Initialize token DL-ring
10
11 char* const token::token_name[] = {
12 #define DEF_TOKEN(m_text, m_cat, m_tag, m_keyword) \
13 m_text,
14 #include "token.dpp"
15 };
16
17 int const token::token_cat[] = {
18 #define DEF_TOKEN(m_text, m_cat, m_tag, m_keyword) \
19 CAT_##m_cat,
20 #include "token.dpp"
21 };
22
token(token & t)23 token::token(token& t)
24 {
25 *this = t;
26 clone = NULL;
27 t.clone = this;
28 if (bind != NULL) bind = bind->clone;
29 }
30
remove()31 void token::remove()
32 {
33 prev ->next = next;
34 next->prev = prev;
35 }
36
next_relevant()37 token* token::next_relevant()
38 {
39 token* t;
40 for (t = next; t->cat == CAT_WSPC; t = t->next);
41 return t;
42 }
43
prev_relevant()44 token* token::prev_relevant()
45 {
46 token* t;
47 for (t = prev; t->cat == CAT_WSPC; t = t->prev);
48 return t;
49 }
50
first_relevant()51 token* token::first_relevant() { return dummy.next_relevant(); }
52
last_relevant()53 token* token::last_relevant() { return dummy.prev_relevant(); }
54
remove(token * head,token * tail)55 void token::remove(token* head, token* tail)
56 {
57 head->prev->next = tail->next;
58 tail->next->prev = head->prev;
59 }
60
disable(token * head,token * tail)61 void token::disable(token* head, token* tail)
62 {
63 while(TRUE) {
64 if (head->tag != TKN_CMNT && head->tag != TKN_LN) {
65 head->disable();
66 }
67 if (head == tail) break;
68 head = head->next;
69 }
70 }
71
disappear()72 void token::disappear()
73 {
74 token* t = this;
75 do {
76 t->disable();
77 t = t->next;
78 } while (t->tag == TKN_SPACE || t->tag == TKN_LN);
79 }
80
81
get_first_token()82 token* token::get_first_token()
83 {
84 token *t;
85 for (t = this; t->tag != TKN_LN && t->tag != TKN_DUMMY; t = t->prev);
86 return t->next_relevant();
87 }
88
copy(token * head,token * tail)89 token* token::copy(token* head, token* tail)
90 {
91 token* first = head;
92 while (TRUE) {
93 (new token(*head))->insert_b(this);
94 if (head == tail) break;
95 head = head->next;
96 }
97 first->clone->pos = pos;
98 return first->clone;
99 }
100
swap(token * left_head,token * left_tail,token * right_head,token * right_tail)101 void token::swap(token* left_head, token* left_tail,
102 token* right_head, token* right_tail)
103 {
104 token* t;
105
106 left_head->prev->next = right_head;
107 left_tail->next->prev = right_tail;
108 right_head->prev->next = left_head;
109 right_tail->next->prev = left_tail;
110
111 t = right_head->prev;
112 right_head->prev = left_head->prev;
113 left_head->prev = t;
114
115 t = right_tail->next;
116 right_tail->next = left_tail->next;
117 left_tail->next = t;
118 }
119
move(token * head,token * tail)120 token* token::move(token* head, token* tail)
121 {
122 head->prev->next = tail->next;
123 tail->next->prev = head->prev;
124
125 tail->next = this;
126 head->prev = prev;
127 prev->next = head;
128 prev = tail;
129 head->pos = pos;
130
131 return head;
132 }
133
move_region(token * head,token * tail)134 token* token::move_region(token* head, token* tail)
135 {
136 while (head->prev->cat == CAT_WSPC) {
137 head = head->prev;
138 }
139 while (tail->next->cat == CAT_WSPC && tail->next->tag != TKN_LN) {
140 tail = tail->next;
141 }
142 return move(head, tail);
143 }
144
145
146 //------------------------------------------------------------------------//
147
input(char * file)148 void token::input(char *file)
149 {
150 scanner_input(file);
151 while (yylex() > 0) curr_token->insert_b (&dummy);
152 curr_token = NULL;
153 }
154
155
output_context(char * file)156 output_context::output_context(char* file)
157 {
158 f = fopen(file, "w");
159 if (f == NULL) {
160 fprintf(stderr, "Can't open output source file: %s\n", file);
161 exit(1);
162 }
163 pos = line = 0;
164 prev_tag = TKN_LN;
165 }
166
167
~output_context()168 output_context::~output_context()
169 {
170 if (f != NULL) fclose(f);
171 }
172
output(token * t)173 void output_context::output(token* t)
174 {
175 static int shift = 0;
176 int t_pos;
177
178 if (t->tag == TKN_BEG_SHIFT) {
179 shift = -t->pos;
180 return;
181 } else if (t->tag == TKN_END_SHIFT) {
182 shift = 0;
183 return;
184 }
185 t_pos = t->bind ? t->bind->pos : t->pos + shift;
186
187 if (t->out_text == NULL || (t->tag == TKN_SPACE && prev_tag == TKN_LN)) {
188 return;
189 }
190 if (t_pos > pos && t->tag != TKN_LN &&
191 ((t->attr & token::fix_pos) || t->tag == TKN_CMNT ||
192 prev_tag == TKN_LN))
193 {
194 //
195 // Set token to specified position
196 //
197 while (pos < t_pos) {
198 pos += 1;
199 putc(' ', f);
200 }
201 }
202 t->pos = pos;
203 //
204 // Separate output '>' symbols
205 //
206 if (*t->out_text == '>' && prev_tag == TKN_GT) {
207 pos += 1;
208 putc(' ', f);
209 }
210 //
211 // Ignoring starting (trailing) spaces in generated tokens
212 // if there are space tokens before (after) generated token
213 //
214 char* out = t->out_text;
215 int len = strlen(out);
216
217 if (t->cat == CAT_GEN) {
218 if (out[0] == ' ' && (prev_tag == TKN_SPACE || prev_tag == TKN_LN)) {
219 out += 1;
220 len -= 1;
221 }
222 if (out[len-1] == ' ' && t->next->tag == TKN_SPACE) {
223 len -= 1;
224 }
225 }
226 //
227 // Output text
228 //
229 prev_tag = t->tag;
230 while (-- len >= 0) {
231 switch(*out) {
232 case '\n':
233 pos = 0;
234 line += 1;
235 prev_tag = TKN_LN;
236 break;
237 case '\t':
238 pos += TAB_WIDTH - (pos % TAB_WIDTH);
239 prev_tag = TKN_SPACE;
240 break;
241 case ' ':
242 prev_tag = TKN_SPACE;
243 pos += 1;
244 break;
245 case '>':
246 prev_tag = TKN_GT;
247 pos += 1;
248 break;
249 default:
250 pos += 1;
251 prev_tag = t->tag;
252 }
253 putc(*out++, f);
254 }
255 }
256
257 extern bool output_not_existed_hdr;
258
print_rec(char * file,token * t,bool unit_spec)259 static token* print_rec (char *file, token *t, bool unit_spec) {
260 output_context ctx(file);
261 char *ip1, *ip2;
262 char *inc_file = NULL;
263 FILE* f;
264 token* nt;
265 int tag;
266 bool def_vars = FALSE;
267 bool interface_module = FALSE;
268 bool unit_implementation = FALSE;
269 bool in_namespace = false;
270 int file_name_len = 0;
271
272 printf ("Output file %s\n", file);
273
274 if (t->prev->tag == TKN_DUMMY) {
275 fputs("#include \"ptoc.h\"\n\n", ctx.file());
276 } else if (unit_spec) {
277 file_name_len = strrchr(file, '.') - file;
278 fprintf(ctx.file(), "#ifndef __%.*s_h__\n#define __%.*s_h__\n",
279 file_name_len, file, file_name_len, file);
280 interface_module = TRUE;
281 }
282 for (; (tag = t->tag) != TKN_DUMMY; t = t->next) {
283 switch (tag) {
284 case TKN_INTERFACE:
285 ip1 = strrchr(file, '.');
286 inc_file = ip1 ? dprintf("%.*s.h", ip1 - file, file)
287 : dprintf("%s.h", inc_file, file);
288 fprintf(ctx.file(), "#include \"%s\"\n", inc_file);
289 t = print_rec(inc_file, t->next, TRUE);
290 if (t->tag == TKN_IMPLEMENTATION && use_namespaces) {
291 file_name_len = strrchr(file, '.') - file;
292 fprintf(ctx.file(), "\nnamespace %.*s {\n", file_name_len, file);
293 unit_implementation = TRUE;
294 }
295 continue;
296 case TKN_PUSH_FILE:
297 case TKN_PUSH_UNIT:
298 ip1 = strrchr(t->in_text, '.');
299 ip2 = strrchr(t->out_text, '.');
300 assert (ip1 != NULL && ip2 != NULL);
301 def_vars = FALSE;
302 if (extern_vars && !turbo_pascal
303 && strcmp(ip2, ".var") == 0
304 && strncmp(t->out_text, file, ip2-t->out_text+1) == 0)
305 {
306 def_vars = TRUE;
307 }
308 if (strcmp(ip1, ".pas") == 0) {
309 strcpy(ip1, ".h");
310 strcpy(ip2, ".h");
311 } else {
312 *ip1 = '_';
313 *ip2 = '_';
314 strcat(ip1, ".h");
315 strcat(ip2, ".h");
316 }
317 if (tag == TKN_PUSH_UNIT) {
318 fprintf(ctx.file(), "#include \"%s\"\n", t->out_text);
319 } else {
320 fprintf(ctx.file(), "#include \"%s\"", t->out_text);
321 }
322 inc_file = t->in_text;
323 f = NULL;
324 if (tag == TKN_PUSH_UNIT
325 || (output_not_existed_hdr
326 && (f = fopen(inc_file, "r")) != NULL))
327 {
328 int nested = 1;
329 if (f) fclose(f);
330 do {
331 t = t->next;
332 if (t->tag == TKN_POP_FILE) nested -= 1;
333 if (t->tag == TKN_PUSH_FILE) nested += 1;
334 if (t->tag == TKN_PUSH_UNIT) nested += 1;
335 if (t->tag == TKN_UNIT_END) nested -= 1;
336 } while(nested);
337 } else {
338 t = print_rec(inc_file, t->next, FALSE);
339 }
340 if (tag != TKN_PUSH_UNIT) {
341 for (nt = t->next;
342 nt != NULL && nt->cat == CAT_WSPC &&
343 (nt->tag == TKN_SPACE || nt->tag == TKN_CMNT);
344 nt = nt->next);
345 if (nt && nt->tag != TKN_LN) {
346 fputc('\n', ctx.file());
347 }
348 }
349 continue;
350 case TKN_IMPLEMENTATION:
351 case TKN_UNIT_END:
352 case TKN_POP_FILE:
353 if (interface_module) {
354 if (!unit_spec && use_namespaces) {
355 fprintf(ctx.file(), "}\nusing namespace %.*s;\n",
356 file_name_len, file);
357 }
358 fprintf(ctx.file(), "#endif\n");
359 }
360 return t;
361 default:
362 if (t->tag > TKN_CMNT && unit_spec && use_namespaces) {
363 fprintf(ctx.file(), "namespace %.*s {\n", file_name_len, file);
364 unit_spec = false;
365 }
366 ctx.output(t);
367 }
368 }
369 if (unit_implementation) {
370 fprintf(ctx.file(), "}\n");
371 }
372 return NULL; // end of main file
373 }
374
output(char * file)375 void token::output (char *file)
376 {
377 print_rec(file, dummy.next, FALSE);
378 }
379
380
381