1 /********************************************************************/
2 /* */
3 /* s7 Seed7 interpreter */
4 /* Copyright (C) 1990 - 2013 Thomas Mertes */
5 /* */
6 /* This program is free software; you can redistribute it and/or */
7 /* modify it under the terms of the GNU General Public License as */
8 /* published by the Free Software Foundation; either version 2 of */
9 /* the License, or (at your option) any later version. */
10 /* */
11 /* This program is distributed in the hope that it will be useful, */
12 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14 /* GNU General Public License for more details. */
15 /* */
16 /* You should have received a copy of the GNU General Public */
17 /* License along with this program; if not, write to the */
18 /* Free Software Foundation, Inc., 51 Franklin Street, */
19 /* Fifth Floor, Boston, MA 02110-1301, USA. */
20 /* */
21 /* Module: Analyzer - Infile */
22 /* File: seed7/src/infile.c */
23 /* Changes: 1990 - 1994, 2013 Thomas Mertes */
24 /* Content: Procedures to open, close and read the source file. */
25 /* */
26 /********************************************************************/
27
28 #define LOG_FUNCTIONS 0
29 #define VERBOSE_EXCEPTIONS 0
30
31 #include "version.h"
32
33 #include "stdlib.h"
34 #include "stdio.h"
35 #include "string.h"
36
37 #include "common.h"
38 #include "data.h"
39 #include "os_decls.h"
40 #include "heaputl.h"
41 #include "flistutl.h"
42 #include "striutl.h"
43 #include "info.h"
44 #include "stat.h"
45 #include "errno.h"
46
47 #if HAS_MMAP
48 #include "sys/types.h"
49 #include "sys/stat.h"
50 #include "sys/mman.h"
51 #include "stat_drv.h"
52 #endif
53
54 #undef EXTERN
55 #define EXTERN
56 #define DO_INIT
57 #include "infile.h"
58
59
60 #define GET_INFILE_BUFFER TRUE
61 #define SIZE_IN_BUFFER 32768
62
63
64 static inFileType file_pointer = NULL;
65 static fileNumType file_counter = 0;
66
67
68
69 #if USE_ALTERNATE_NEXT_CHARACTER
fill_buf(void)70 int fill_buf (void)
71
72 {
73 #if !HAS_MMAP
74 memSizeType chars_read;
75 #endif
76 int ch;
77
78 /* fill_buf */
79 logFunction(printf("fill_buf\n"););
80 #if HAS_MMAP
81 ch = EOF;
82 #else
83 if (in_file.fil != NULL &&
84 (chars_read = fread(in_file.start, 1,
85 (size_t) in_file.buffer_size, in_file.fil)) != 0) {
86 in_file.nextch = in_file.start;
87 in_file.beyond = in_file.start + chars_read;
88 ch = next_character();
89 } else {
90 ch = EOF;
91 } /* if */
92 #endif
93 logFunction(printf("fill_buf --> %d\n", ch););
94 return ch;
95 } /* fill_buf */
96 #endif
97
98
99
speedup(void)100 static inline boolType speedup (void)
101
102 {
103 boolType okay;
104 #if HAS_MMAP
105 int file_no;
106 os_fstat_struct file_stat;
107 memSizeType file_length;
108 #endif
109
110 /* speedup */
111 logFunction(printf("speedup\n"););
112 okay = TRUE;
113 #if USE_ALTERNATE_NEXT_CHARACTER
114 #if HAS_MMAP
115 file_no = fileno(in_file.fil);
116 if (file_no != -1 && os_fstat(file_no, &file_stat) == 0) {
117 if (file_stat.st_size >= 0 && (unsigned_os_off_t) file_stat.st_size < MAX_MEMSIZETYPE) {
118 file_length = (memSizeType) file_stat.st_size;
119 if ((in_file.start = (ustriType) mmap(NULL, file_length,
120 PROT_READ, MAP_PRIVATE, file_no, 0)) != (ustriType) -1) {
121 in_file.nextch = in_file.start;
122 in_file.beyond = in_file.start + file_length;
123 in_file.buffer_size = 0;
124 } else {
125 if (ALLOC_UBYTES(in_file.start, file_length)) {
126 if (fread(in_file.start, 1, file_length, in_file.fil) ==
127 file_length) {
128 in_file.nextch = in_file.start;
129 in_file.beyond = in_file.start + file_length;
130 in_file.buffer_size = file_length;
131 fseek(in_file.fil, 0, SEEK_SET);
132 } else {
133 FREE_BYTES(in_file.start, file_length);
134 okay = FALSE;
135 } /* if */
136 } else {
137 okay = FALSE;
138 } /* if */
139 } /* if */
140 } else {
141 okay = FALSE;
142 } /* if */
143 } else {
144 okay = FALSE;
145 } /* if */
146 #else
147 if (GET_INFILE_BUFFER) {
148 in_file.buffer_size = SIZE_IN_BUFFER;
149 } else {
150 in_file.buffer_size = 512;
151 } /* if */
152 if (ALLOC_UBYTES(in_file.start, in_file.buffer_size)) {
153 in_file.nextch = in_file.start + in_file.buffer_size;
154 in_file.beyond = in_file.start;
155 } else {
156 in_file.buffer_size = 512;
157 if (ALLOC_UBYTES(in_file.start, in_file.buffer_size)) {
158 in_file.nextch = in_file.start + in_file.buffer_size;
159 in_file.beyond = in_file.start;
160 } else {
161 okay = FALSE;
162 } /* if */
163 } /* if */
164 #endif
165 #else
166 #if USE_INFILE_BUFFER
167 if (GET_INFILE_BUFFER) {
168 if (ALLOC_UBYTES(in_file.buffer, SIZE_IN_BUFFER)) {
169 setvbuf(in_file.fil, in_file.buffer, _IOFBF,
170 (size_t) SIZE_IN_BUFFER);
171 } /* if */
172 } else {
173 in_file.buffer = NULL;
174 } /* if */
175 #endif
176 #endif
177 logFunction(printf("speedup --> %d\n", okay););
178 return okay;
179 } /* speedup */
180
181
182
openInfile(const_striType sourceFileName,boolType write_library_names,boolType write_line_numbers,errInfoType * err_info)183 boolType openInfile (const_striType sourceFileName, boolType write_library_names,
184 boolType write_line_numbers, errInfoType *err_info)
185
186 {
187 os_striType os_path;
188 inFileType new_file;
189 FILE *in_fil;
190 ustriType name_ustri;
191 memSizeType name_length;
192 striType in_name;
193 int path_info = PATH_IS_NORMAL;
194 boolType isOpen = FALSE;
195
196 /* openInfile */
197 logFunction(printf("openInfile(\"%s\", %d, %d, err_info=%d)\n",
198 striAsUnquotedCStri(sourceFileName),
199 write_library_names, write_line_numbers,
200 *err_info););
201 os_path = cp_to_os_path(sourceFileName, &path_info, err_info);
202 if (likely(os_path != NULL)) {
203 in_fil = os_fopen(os_path, os_mode_rb);
204 /* printf("fopen(\"" FMT_S_OS "\") --> " FMT_U_MEM "\n",
205 os_path, (memSizeType) in_fil); */
206 if (in_fil == NULL) {
207 logError(printf("openInfile: "
208 "fopen(\"" FMT_S_OS "\", \"" FMT_S_OS "\") failed:\n"
209 "errno=%d\nerror: %s\n",
210 os_path, os_mode_rb, errno, strerror(errno)););
211 *err_info = FILE_ERROR;
212 } else {
213 if (!ALLOC_FILE(new_file)) {
214 fclose(in_fil);
215 *err_info = MEMORY_ERROR;
216 } else {
217 name_ustri = (ustriType) stri_to_cstri8(sourceFileName, err_info);
218 if (name_ustri != NULL) {
219 /* printf("name_ustri: \"%s\"\n", name_ustri); */
220 name_length = strlen((cstriType) name_ustri);
221 name_ustri = REALLOC_USTRI(name_ustri, max_utf8_size(sourceFileName->size), name_length);
222 if (name_ustri == NULL) {
223 *err_info = MEMORY_ERROR;
224 } /* if */
225 } /* if */
226 if (name_ustri == NULL) {
227 fclose(in_fil);
228 } else if (!ALLOC_STRI_CHECK_SIZE(in_name, sourceFileName->size)) {
229 free_cstri8(name_ustri, sourceFileName);
230 fclose(in_fil);
231 *err_info = MEMORY_ERROR;
232 } else {
233 in_name->size = sourceFileName->size;
234 memcpy(in_name->mem, sourceFileName->mem, sourceFileName->size * sizeof(strElemType));
235 if (in_file.curr_infile != NULL) {
236 memcpy(in_file.curr_infile, &in_file, sizeof(inFileRecord));
237 } /* if */
238 in_file.fil = in_fil;
239 if (!speedup()) {
240 fclose(in_file.fil);
241 free_cstri8(name_ustri, sourceFileName);
242 FREE_STRI(in_name, sourceFileName->size);
243 if (in_file.curr_infile != NULL) {
244 memcpy(&in_file, in_file.curr_infile, sizeof(inFileRecord));
245 } else {
246 in_file.fil = NULL;
247 } /* if */
248 logError(printf("openInfile: speedup() failed.\n"
249 "os_path: \"" FMT_S_OS "\"\n", os_path););
250 *err_info = FILE_ERROR;
251 } else {
252 COUNT_USTRI(name_length, count.fnam, count.fnam_bytes);
253 in_file.name_ustri = name_ustri;
254 in_file.name = in_name;
255 in_file.character = next_character();
256 in_file.line = 1;
257 file_counter++;
258 in_file.file_number = file_counter;
259 if (in_file.curr_infile != NULL) {
260 in_file.owningProg = in_file.curr_infile->owningProg;
261 } else {
262 in_file.owningProg = NULL; /* Is set in analyze_prog() */
263 } /* if */
264 open_compilation_info(write_library_names, write_line_numbers);
265 in_file.end_of_file = FALSE;
266 in_file.up_infile = in_file.curr_infile;
267 in_file.curr_infile = new_file;
268 in_file.next = file_pointer;
269 file_pointer = new_file;
270 memcpy(new_file, &in_file, sizeof(inFileRecord));
271 isOpen = TRUE;
272 } /* if */
273 } /* if */
274 } /* if */
275 } /* if */
276 os_stri_free(os_path);
277 } /* if */
278 logFunction(printf("openInfile --> %d (err_info=%d)\n", isOpen, *err_info););
279 return isOpen;
280 } /* openInfile */
281
282
283
closeInfile(void)284 void closeInfile (void)
285
286 { /* closeInfile */
287 logFunction(printf("closeInfile\n"););
288 /* printf("\nclose(\"%s\");\n", in_file.name); */
289 #if WITH_COMPILATION_INFO
290 if (in_file.write_line_numbers) {
291 NL_LIN_INFO();
292 } else {
293 if (in_file.write_library_names) {
294 NL_FIL_LIN_INFO();
295 } /* if */
296 } /* if */
297 total_lines = total_lines + ((unsigned long) in_file.line);
298 #endif
299 #if USE_ALTERNATE_NEXT_CHARACTER
300 if (in_file.start != NULL) {
301 if (in_file.buffer_size == 0) {
302 #if HAS_MMAP
303 if (in_file.fil != NULL) {
304 munmap(in_file.start, (size_t) (in_file.beyond - in_file.start));
305 } /* if */
306 #endif
307 } else {
308 FREE_BYTES(in_file.start, in_file.buffer_size);
309 } /* if */
310 } /* if */
311 #endif
312 if (in_file.fil != NULL) {
313 fclose(in_file.fil);
314 in_file.fil = NULL;
315 } /* if */
316 #if !USE_ALTERNATE_NEXT_CHARACTER
317 #if USE_INFILE_BUFFER
318 if (in_file.BUFFER != NULL) {
319 FREE_BYTES(in_file.buffer, SIZE_IN_BUFFER);
320 } /* if */
321 #endif
322 #endif
323 if (in_file.curr_infile != NULL) {
324 memcpy(in_file.curr_infile, &in_file, sizeof(inFileRecord));
325 } /* if */
326 if (in_file.up_infile != NULL) {
327 memcpy(&in_file, in_file.up_infile, sizeof(inFileRecord));
328 display_compilation_info();
329 } else {
330 in_file.curr_infile = NULL;
331 } /* if */
332 in_file.next_msg_line = in_file.line + in_file.incr_message_line;
333 logFunction(printf("END closeInfile\n"););
334 } /* closeInfile */
335
336
337
openString(bstriType inputString,boolType write_library_names,boolType write_line_numbers,errInfoType * err_info)338 boolType openString (bstriType inputString, boolType write_library_names,
339 boolType write_line_numbers, errInfoType *err_info)
340
341 {
342 const char sourceFileName[] = "STRING";
343 inFileType new_file;
344 memSizeType name_length;
345 ustriType name_ustri;
346 striType in_name;
347 boolType isOpen = FALSE;
348
349 /* openString */
350 logFunction(printf("openString(\"%s\", %d, %d, err_info=%d)\n",
351 bstriAsUnquotedCStri(inputString),
352 write_library_names, write_line_numbers,
353 *err_info););
354 #if USE_ALTERNATE_NEXT_CHARACTER
355 if (*err_info == OKAY_NO_ERROR) {
356 if (!ALLOC_FILE(new_file)) {
357 *err_info = MEMORY_ERROR;
358 } else {
359 name_length = STRLEN(sourceFileName);
360 if (!ALLOC_USTRI(name_ustri, name_length)) {
361 *err_info = MEMORY_ERROR;
362 } else if (!ALLOC_STRI_SIZE_OK(in_name, name_length)) {
363 UNALLOC_USTRI(name_ustri, name_length);
364 *err_info = MEMORY_ERROR;
365 } else {
366 COUNT_USTRI(name_length, count.fnam, count.fnam_bytes);
367 strcpy((cstriType) name_ustri, sourceFileName);
368 in_name->size = name_length;
369 memcpy_to_strelem(in_name->mem, name_ustri, name_length);
370 if (in_file.curr_infile != NULL) {
371 memcpy(in_file.curr_infile, &in_file, sizeof(inFileRecord));
372 } /* if */
373 in_file.fil = NULL;
374 in_file.name_ustri = name_ustri;
375 in_file.name = in_name;
376 in_file.start = inputString->mem;
377 in_file.nextch = in_file.start;
378 in_file.beyond = in_file.start + inputString->size;
379 in_file.buffer_size = 0;
380 in_file.character = next_character();
381 in_file.line = 1;
382 file_counter++;
383 in_file.file_number = file_counter;
384 in_file.owningProg = NULL; /* Is set in analyze_prog() */
385 open_compilation_info(write_library_names, write_line_numbers);
386 in_file.end_of_file = FALSE;
387 in_file.up_infile = in_file.curr_infile;
388 in_file.curr_infile = new_file;
389 in_file.next = file_pointer;
390 file_pointer = new_file;
391 memcpy(new_file, &in_file, sizeof(inFileRecord));
392 isOpen = TRUE;
393 } /* if */
394 } /* if */
395 } /* if */
396 #endif
397 logFunction(printf("openString --> %d (err_info=%d)\n", isOpen, *err_info););
398 return isOpen;
399 } /* openString */
400
401
402
freeFile(inFileType old_file)403 static void freeFile (inFileType old_file)
404
405 {
406 memSizeType name_length;
407
408 /* freeFile */
409 logFunction(printf("freeFile\n"););
410 name_length = strlen((cstriType) old_file->name_ustri);
411 FREE_USTRI(old_file->name_ustri, name_length, count.fnam, count.fnam_bytes);
412 FREE_STRI(old_file->name, old_file->name->size);
413 FREE_FILE(old_file);
414 logFunction(printf("freeFile -->\n"););
415 } /* freeFile */
416
417
418
removeProgFiles(progType currentProg)419 void removeProgFiles (progType currentProg)
420
421 {
422 inFileType aFile;
423 inFileType *fileAddr;
424 inFileType currFile;
425
426 /* removeProgFiles */
427 logFunction(printf("removeProgFiles\n"););
428 aFile = file_pointer;
429 fileAddr = &file_pointer;
430 while (aFile != NULL) {
431 currFile = aFile;
432 aFile = aFile->next;
433 /* printf("removeProgFiles: %s %lx %lx\n", currFile->name_ustri,
434 (unsigned long) currFile->owningProg, (unsigned long) currentProg); */
435 if (currFile->owningProg == currentProg) {
436 freeFile(currFile);
437 *fileAddr = aFile;
438 } else {
439 fileAddr = &currFile->next;
440 } /* if */
441 } /* if */
442 logFunction(printf("removeProgFiles -->\n"););
443 } /* removeProgFiles */
444
445
446
next_file(void)447 void next_file (void)
448
449 { /* next_file */
450 logFunction(printf("next_file\n"););
451 in_file.line--;
452 if (in_file.up_infile != NULL) {
453 closeInfile();
454 } else {
455 in_file.end_of_file = TRUE;
456 } /* if */
457 logFunction(printf("next_file -->\n"););
458 } /* next_file */
459
460
461
462 #ifdef OUT_OF_ORDER
next_line(void)463 int next_line (void)
464
465 {
466 register int character;
467
468 /* next_line */
469 logFunction(printf("next_line\n"););
470 SKIP_CR_SP(character);
471 INCR_LINE_COUNT(in_file.line);
472 logFunction(printf("next_line -->\n"););
473 return character;
474 } /* next_line */
475 #endif
476
477
478
get_file_name(fileNumType file_num)479 striType get_file_name (fileNumType file_num)
480
481 {
482 static striType question_mark = NULL;
483 register inFileType help_file;
484 striType file_name;
485
486 /* get_file_name */
487 logFunction(printf("get_file_name(%u)\n", file_num););
488 help_file = file_pointer;
489 while (help_file != NULL && help_file->file_number != file_num) {
490 help_file = help_file->next;
491 } /* while */
492 if (help_file != NULL) {
493 file_name = help_file->name;
494 } else {
495 if (question_mark == NULL) {
496 question_mark = CSTRI_LITERAL_TO_STRI("?");
497 } /* if */
498 file_name = question_mark;
499 } /* if */
500 logFunction(printf("get_file_name --> \"%s\"\n",
501 striAsUnquotedCStri(file_name)););
502 return file_name;
503 } /* get_file_name */
504
505
506
get_file_name_ustri(fileNumType file_num)507 const_ustriType get_file_name_ustri (fileNumType file_num)
508
509 {
510 inFileType help_file;
511 const_ustriType file_name;
512
513 /* get_file_name_ustri */
514 logFunction(printf("get_file_name_ustri\n"););
515 help_file = file_pointer;
516 while (help_file != NULL && help_file->file_number != file_num) {
517 help_file = help_file->next;
518 } /* while */
519 if (help_file != NULL) {
520 file_name = help_file->name_ustri;
521 } else {
522 file_name = (const_ustriType) "?";
523 } /* if */
524 logFunction(printf("get_file_name_ustri -->\n"););
525 return file_name;
526 } /* get_file_name_ustri */
527