1 #include <string.h>
2 #include <stdlib.h>
3
4 #include "main.h"
5 #include "nmtbl.h"
6 #include "token.h"
7 #include "trnod.h"
8 #include "util.h"
9
10 extern int zzparse();
11
load_predefined()12 static void load_predefined()
13 {
14 b_ring::add_cur(nm_entry::add("integer", TKN_IDENT),
15 symbol::s_type,
16 &integer_type);
17 b_ring::add_cur(nm_entry::add("real", TKN_IDENT),
18 symbol::s_type,
19 &real_type);
20 b_ring::add_cur(nm_entry::add("boolean", TKN_IDENT),
21 symbol::s_type,
22 &bool_type);
23 b_ring::add_cur(nm_entry::add("char", TKN_IDENT),
24 symbol::s_type,
25 &char_type);
26 b_ring::add_cur(nm_entry::add("text", TKN_IDENT),
27 symbol::s_type,
28 &text_type);
29 b_ring::add_cur(nm_entry::add("zero_terminated_string", TKN_IDENT),
30 nm_entry::add("char*", TKN_IDENT),
31 symbol::s_type,
32 &string_type);
33 b_ring::add_cur(nm_entry::add("true", TKN_IDENT),
34 symbol::s_const,
35 &bool_type);
36 b_ring::add_cur(nm_entry::add("false", TKN_IDENT),
37 symbol::s_const,
38 &bool_type);
39 b_ring::add_cur(nm_entry::add("nil", TKN_IDENT),
40 symbol::s_const,
41 &void_type);
42 if (hp_pascal) {
43 nm_entry::add("addr", TKN_ADDR);
44 }
45 if (turbo_pascal) {
46 b_ring::add_cur(nm_entry::add("pointer", TKN_IDENT),
47 symbol::s_type,
48 &pointer_type);
49 b_ring::add_cur(nm_entry::add("pchar", TKN_IDENT),
50 symbol::s_type,
51 &string_type);
52 b_ring::add_cur(nm_entry::add("longint", TKN_IDENT),
53 symbol::s_type,
54 &longint_type);
55 b_ring::add_cur(nm_entry::add("double", TKN_IDENT),
56 symbol::s_type,
57 &double_type);
58 b_ring::add_cur(nm_entry::add("untyped_file", TKN_IDENT),
59 symbol::s_type,
60 &text_type);
61 nested_comments = TRUE;
62 }
63 }
64
load_keywords()65 static void load_keywords()
66 {
67 for (int tag = 0; tag < TKN_LAST; tag ++ ) {
68 if (token::token_cat[tag] == CAT_ID ||
69 token::token_cat[tag] == CAT_KWD)
70 {
71 nm_entry::add(token::token_name[tag], tag);
72 }
73 }
74 }
75
76 #define MAX_NAME_LEN 1024
77
load_configuration(char * name)78 static void load_configuration(char* name) {
79 FILE* cfg = fopen(name, "r");
80 if (cfg != NULL) {
81 char buf[MAX_NAME_LEN];
82
83 while (fscanf(cfg, "%s", buf) == 1) {
84 if (strcmp(buf, "#begin(reserved)") == 0) {
85 while (fscanf(cfg, "%s", buf) == 1
86 && strcmp(buf, "#end(reserved)") != 0)
87 {
88 nm_entry::add(buf, TKN_RESERVED);
89 }
90 } else if(strcmp(buf, "#begin(macro)") == 0) {
91 while (fscanf(cfg, "%s", buf) == 1
92 && strcmp(buf, "#end(macro)") != 0)
93 {
94 nm_entry::add(buf, TKN_IDENT)->flags |= nm_entry::macro;
95 }
96 } else if(strcmp(buf, "#begin(library)") == 0) {
97 while (fscanf(cfg, "%s", buf) == 1
98 && strcmp(buf, "#end(library)") != 0)
99 {
100 b_ring::global_b_ring.add(nm_entry::add(buf, TKN_IDENT),
101 symbol::s_dummy,
102 NULL);
103 }
104 } else if(strcmp(buf, "#begin(rename)") == 0) {
105 while (fscanf(cfg, "%s", buf) == 1
106 && strcmp(buf, "#end(rename)") != 0)
107 {
108 nm_entry* nm_old = nm_entry::add(buf, TKN_IDENT);
109 fscanf(cfg, "%s", buf);
110 nm_entry* nm_new = nm_entry::add(buf, TKN_IDENT);
111 rename_item::add(nm_new, nm_old);
112 }
113 }
114 }
115 fclose(cfg);
116 if (turbo_pascal) { // sizeof is builtin Pascal function
117 nm_entry* nm_sizeof = nm_entry::find("sizeof");
118 if (nm_sizeof) {
119 *nm_sizeof->text = 'S';
120 }
121 }
122 } else {
123 fprintf(stderr, "Can't open configuration file '%s'\n",
124 name);
125 }
126 }
127
128
129 char *i_path;
130 char *input_file;
131 char *output_file;
132 char *output_suf;
133 char *prog_path;
134 bool output_not_existed_hdr;
135 bool no_array_assign_operator;
136 bool language_c;
137 bool compile_system_library;
138 bool pio_init;
139 bool use_call_graph;
140 bool short_set;
141 bool unsigned_comparison;
142 bool small_enum;
143 bool nological;
144 bool turbo_pascal;
145 bool use_c_strings;
146 bool extern_vars;
147 bool preserve_case;
148 bool nested_comments;
149 bool copy_array;
150 bool comment_tags;
151 bool use_namespaces;
152 bool smart_union;
153 bool no_index_decrement;
154 bool ignore_preprocessor_directives;
155 bool hp_pascal;
156 bool do_not_use_enums;
157 char* pascall;
158 char path_sep;
159
160 FILE *call_graph_file;
161
scan_opt(int argc,char ** argv)162 static void scan_opt (int argc, char **argv) {
163 int i;
164 unsigned j;
165 bool found;
166
167 static struct opt_str {
168 bool *flag;
169 char **value;
170 char *str;
171 char *defval;
172 char *comment;
173 } opt[] = {
174
175 // Add command options to this table:
176
177 { NULL, &i_path, "-I", ".",
178 #ifdef _WIN32
179 "Include path (semicolon separated directory list)" },
180 #else
181 "Include path (colon separated directory list)" },
182 #endif
183 { NULL, &input_file, "-in", NULL,
184 "Input pascal file" },
185 { NULL, &output_file, "-out", NULL,
186 "Output C/C++ file" },
187 { NULL, &output_suf, "-suf", ".cxx",
188 "Output C/C++ file suffix" },
189 { &language_c, NULL, "-c", NULL,
190 "Translate into ANSI C" },
191 { &no_array_assign_operator, NULL, "-assign", NULL,
192 "Do not use assignment operators for array" },
193 { &use_call_graph, NULL, "-analyze", NULL,
194 "Analyze call graph to find non-recursive functions" },
195 { &short_set, NULL, "-intset", NULL,
196 "Use integer types for short sets of enumerations" },
197 { &pio_init, NULL, "-init", NULL,
198 "Call pio_initialize() function from main()" },
199 { &small_enum, NULL, "-smallenum", NULL,
200 "Use for enumerated types as small bytes as possible" },
201 { &unsigned_comparison, NULL, "-unsigned", NULL,
202 "Generate correct code for sign/unsigned comparisons" },
203 { &output_not_existed_hdr, NULL, "-h", NULL,
204 "Output only not existed header files" },
205 { &turbo_pascal, NULL, "-turbo", NULL,
206 "Convert Turbo Pascal" },
207 { &hp_pascal, NULL, "-hp", NULL,
208 "Convert HP64000 Pascal" },
209 { &use_c_strings, NULL, "-cstring", NULL,
210 "Use char* type for string fields in records and arrays" },
211 { &nological, NULL, "-nological", NULL,
212 "Use | and & instead of || and && for boolean operations" },
213 { &extern_vars, NULL, "-extern", NULL,
214 "Declare all variables from included files as \"EXTERN\"" },
215 { &preserve_case, NULL, "-preserve", NULL,
216 "Preserve case of identifiers" },
217 { &nested_comments, NULL, "-nested", NULL,
218 "Nested comments: (* {} *)" },
219 { ©_array, NULL, "-copy", NULL,
220 "Always make a copy of array passed by value" },
221 { &comment_tags, NULL, "-comment_tags", NULL,
222 "Place in comments tags of Pascal variant records" },
223 { &smart_union, NULL, "-smartunion", NULL,
224 "Convert variant records with empty fixed part to unions" },
225 { &use_namespaces, NULL, "-namespace", NULL,
226 "Place Turbo Pascal units in separate namespaces" },
227 { &no_index_decrement, NULL, "-0based", NULL,
228 "Assume all arrays are zero based" },
229 { &ignore_preprocessor_directives, NULL, "-ignore_directives", NULL,
230 "Ignore all lines started with '$' character" },
231 { &do_not_use_enums, NULL, "-no_enums", NULL,
232 "Do not use enums for integer constants" },
233 { NULL, &pascall, "-pascall", "",
234 "Specify modifier (pascal,WINAPI...) for converted functions" }
235
236 };
237 for (j = 0; j < (sizeof(opt)/sizeof(opt_str)); j++) {
238 if (opt[j].value != NULL) {
239 *opt[j].value = opt[j].defval;
240 }
241 if (opt[j].flag != NULL) {
242 *(opt[j].flag) = FALSE; // Switch off flags
243 }
244 }
245 for (i = 1; i < argc; i++) { // Skipping program name
246 if (argv[i][0] != '-') {
247 if (input_file != NULL) {
248 fprintf(stderr, "Only one input file name is accepted\n");
249 goto Help;
250 }
251 input_file = argv[i];
252 continue;
253 }
254 found = FALSE;
255 for (j = 0; j < (sizeof(opt)/sizeof(opt_str)); j++) {
256 if (strcmp (opt[j].str, argv[i]) == 0) {
257 if (opt[j].flag != NULL) {
258 *(opt[j].flag) = TRUE;
259 }
260 if (opt[j].value != NULL) {
261 i++;
262 if (i >= argc) {
263 fprintf(stderr, "Value for option '%s' is not specified\n", opt[j].str);
264 goto Help;
265 }
266 *opt[j].value = argv[i];
267 }
268 found = TRUE;
269 break;
270 }
271 }
272 if (!found) {
273 Help:
274 fprintf (stderr, "Pascal to C/C++ converter. Version "VERSION"\n"
275 "Available options are:\n");
276
277 for (j = 0; j < (sizeof(opt)/sizeof(opt_str)); j++ ) {
278 if (opt[j].defval != NULL) {
279 char buf[256];
280 sprintf(buf, "%s [%s]", opt[j].str, opt[j].defval);
281 fprintf(stderr, "\t%-12s", buf);
282 } else {
283 fprintf(stderr, "\t%-12s", opt[j].str);
284 }
285 fprintf(stderr, "%s\n", opt[j].comment);
286 }
287 exit (1);
288 }
289 pio_init = TRUE;
290 }
291 if (input_file == NULL) {
292 goto Help;
293 }
294 #ifdef _WIN32
295 char* p = strrchr(argv[0], '\\');
296 prog_path = (p != NULL) ? dprintf("%.*s", p + 1 - argv[0], argv[0]) : (char*)"";
297 path_sep = ';';
298 #else
299 #ifdef __EMX__
300 char* p = strrchr(_fnslashify(argv[0]), '/');
301 prog_path = (p != NULL) ? dprintf("%.*s", p + 1 - argv[0], argv[0]) : (char*)"";
302 #else
303 char* p = strrchr(argv[0], '/');
304 prog_path = (p != NULL) ? dprintf("%.*s", p + 1 - argv[0], argv[0]) : (char*)"";
305 #endif
306 path_sep = ':';
307 #endif
308 i_path = dprintf("%s%c%s", i_path, path_sep, prog_path);
309 }
310
main(int argc,char * argv[])311 int main(int argc, char* argv[])
312 {
313 scan_opt (argc, argv);
314
315 if (input_file == NULL) {
316 fputs("Input file was not specified\n", stderr);
317 exit(1);
318 }
319 if (output_file == NULL) {
320 char* ext = strrchr(input_file, '.');
321 int file_name_len = ext ? ext - input_file : strlen(input_file);
322 if (language_c) output_suf = ".c";
323 output_file = dprintf("%.*s%s", file_name_len, input_file, output_suf);
324 }
325 load_predefined();
326 load_keywords();
327 load_configuration(dprintf("%s%s", prog_path, CONFIG_FILE));
328
329 if (hp_pascal) {
330 nested_comments = 1;
331 ignore_preprocessor_directives = 1;
332 }
333 if (use_call_graph) {
334 call_graph_file = fopen(CALL_GRAPH_FILE, "a");
335 FILE* f = fopen(RECURSIVE_PROC_FILE, "r");
336 if (f != NULL) {
337 char name[256];
338 while (fscanf(f, "%s", name) == 1) {
339 nm_entry::add(name, TKN_IDENT)->flags |= nm_entry::recursive;
340 }
341 fclose(f);
342 }
343 }
344
345 compile_system_library = TRUE;
346 #ifdef PREFIX
347 token::input(turbo_pascal
348 ? (char *) PREFIX "/share/ptoc/tptoc.pas"
349 : (char *) PREFIX "/share/ptoc/ptoc.pas");
350 #else
351 token::input(dprintf("%s%s", prog_path,
352 turbo_pascal ? "tptoc.pas" : "ptoc.pas"));
353 #endif
354 zzparse();
355
356 compile_system_library = FALSE;
357 token::reset();
358 token::input(input_file);
359 zzparse();
360
361 token::output(output_file);
362
363 if (call_graph_file) {
364 fclose(call_graph_file);
365 }
366 return 0;
367 }
368
369
370