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