1
by Juan Cespedes
Import upstream version 0.16.14 |
1 |
/* readsrc.c - read source files for assembler */
|
2 |
||
3 |
#include "syshead.h" |
|
4 |
#include "const.h" |
|
5 |
#include "type.h" |
|
6 |
#include "flag.h" |
|
7 |
#include "file.h" |
|
8 |
#include "globvar.h" |
|
9 |
#include "macro.h" |
|
10 |
#include "scan.h" |
|
11 |
#undef EXTERN
|
|
12 |
#define EXTERN
|
|
13 |
#include "source.h" |
|
14 |
||
15 |
/*
|
|
16 |
* Ok, lots of hack & slash here.
|
|
17 |
* 1) Added BIG buffer to load entire _primary_ file into memory.
|
|
18 |
* 2) This means the primary file can be standard input.
|
|
19 |
* 3) Fixed so 'get/include' processing now works.
|
|
20 |
* 4) Altered for a 'normal' style buffer otherwise (MINIBUF)
|
|
21 |
* 5) Have the option of completely unbuffered if you need the last Kb.
|
|
22 |
*
|
|
23 |
* RDB.
|
|
24 |
*/
|
|
25 |
||
26 |
#ifndef __AS386_16__
|
|
27 |
#ifndef BIGBUFFER
|
|
28 |
#define BIGBUFFER 1 /* For most machines we have the memory */ |
|
29 |
#endif
|
|
30 |
#endif
|
|
31 |
||
32 |
#ifdef MSDOS
|
|
33 |
#define off_t long /* Not a typedef! */ |
|
34 |
#endif
|
|
35 |
||
36 |
#ifndef MINIBUF
|
|
37 |
#define MINIBUF 1 /* Add in a reasonable buffer */ |
|
38 |
#endif
|
|
39 |
||
40 |
struct get_s /* to record included files */ |
|
41 |
{
|
|
42 |
fd_t fd; |
|
43 |
unsigned line; |
|
44 |
off_t position; |
|
45 |
};
|
|
46 |
||
47 |
PRIVATE char hid_filnambuf[FILNAMLEN + 1]; /* buffer for file name */ |
|
48 |
||
49 |
PRIVATE struct get_s hid_getstak[MAXGET]; /* GET stack */ |
|
50 |
PRIVATE struct get_s *getstak; /* ptr */ |
|
51 |
||
52 |
#if BIGBUFFER == 1
|
|
1.1.1
by Matthias Klose
Import upstream version 0.16.17 |
53 |
PRIVATE char *mem_start = 0, *mem_end; |
1
by Juan Cespedes
Import upstream version 0.16.14 |
54 |
#endif
|
55 |
||
56 |
PRIVATE char hid_linebuf[LINLEN]; /* line buffer */ |
|
57 |
PRIVATE char *eol_ptr; |
|
58 |
||
59 |
PRIVATE char *maclinebuf; |
|
60 |
PRIVATE char *maclineptr; |
|
61 |
||
62 |
#if MINIBUF == 1
|
|
63 |
PRIVATE void inp_seek P((int fd, long posn)); |
|
64 |
PRIVATE long inp_tell P((int fd)); |
|
65 |
PRIVATE int inp_line P((int fd, char * buf, int size)); |
|
66 |
#endif
|
|
67 |
||
68 |
FORWARD void clearsource P((void)); |
|
69 |
FORWARD void line_too_long P((void)); |
|
70 |
||
71 |
PRIVATE void clearsource() |
|
72 |
{
|
|
73 |
}
|
|
74 |
||
75 |
PRIVATE void line_too_long() |
|
76 |
{
|
|
77 |
symname = linebuf + (LINLEN - 1); /* spot for the error */ |
|
78 |
error(LINLONG); /* so error is shown in column LINLEN - 1 */ |
|
79 |
}
|
|
80 |
||
81 |
/* initialise private variables */
|
|
82 |
||
83 |
PUBLIC void initsource() |
|
84 |
{
|
|
85 |
filnamptr = hid_filnambuf; |
|
86 |
getstak = hid_getstak; |
|
87 |
clearsource(); /* sentinel to invoke blank skipping */ |
|
88 |
}
|
|
89 |
||
90 |
PUBLIC fd_t open_input(name) |
|
91 |
char *name; |
|
92 |
{
|
|
93 |
fd_t fd; |
|
94 |
#if BIGBUFFER == 1
|
|
95 |
off_t filelength = -1; |
|
96 |
||
97 |
if( mem_start == 0 && strcmp(name, "-") == 0 ) |
|
98 |
fd = 0; |
|
99 |
else
|
|
100 |
#endif
|
|
101 |
#ifdef O_BINARY
|
|
102 |
if ((unsigned) (fd = open(name, O_RDONLY|O_BINARY)) > 255) |
|
103 |
as_abort("error opening input file"); |
|
104 |
#else
|
|
105 |
if ((unsigned) (fd = open(name, O_RDONLY)) > 255) |
|
106 |
as_abort("error opening input file"); |
|
107 |
#endif
|
|
108 |
||
109 |
#if BIGBUFFER == 1
|
|
110 |
if( mem_start == 0 ) |
|
111 |
{
|
|
1.1.1
by Matthias Klose
Import upstream version 0.16.17 |
112 |
size_t memsize = 0; |
113 |
int cc; |
|
114 |
||
1
by Juan Cespedes
Import upstream version 0.16.14 |
115 |
if(fd) |
116 |
{
|
|
117 |
struct stat st; |
|
118 |
if( fstat(fd, &st) >= 0 ) |
|
119 |
filelength = st.st_size; |
|
120 |
if( filelength > (((unsigned)-1)>>1)-3 ) |
|
121 |
{
|
|
122 |
mem_end = mem_start = "\n\n"; |
|
123 |
goto cant_do_this; |
|
124 |
}
|
|
125 |
}
|
|
1.1.1
by Matthias Klose
Import upstream version 0.16.17 |
126 |
|
127 |
if (filelength > 0) { |
|
128 |
if( (mem_start = malloc(filelength+4)) == 0 ) |
|
1
by Juan Cespedes
Import upstream version 0.16.14 |
129 |
{
|
130 |
mem_end = mem_start = "\n\n"; |
|
131 |
goto cant_do_this; |
|
1.1.1
by Matthias Klose
Import upstream version 0.16.17 |
132 |
}
|
133 |
memsize = filelength; |
|
134 |
||
1
by Juan Cespedes
Import upstream version 0.16.14 |
135 |
filelength = read(fd, mem_start, filelength); |
1.1.1
by Matthias Klose
Import upstream version 0.16.17 |
136 |
} else |
1
by Juan Cespedes
Import upstream version 0.16.14 |
137 |
filelength = 0; |
138 |
||
1.1.1
by Matthias Klose
Import upstream version 0.16.17 |
139 |
for(;;) |
140 |
{
|
|
141 |
if( filelength >= memsize ) |
|
142 |
{
|
|
143 |
if (memsize > 16000) |
|
144 |
mem_start = asrealloc(mem_start, (memsize+=16384)+4); |
|
145 |
else
|
|
146 |
mem_start = asrealloc(mem_start, (memsize+=memsize+32)+4); |
|
147 |
}
|
|
148 |
cc = read(fd, mem_start+filelength, |
|
149 |
(size_t)(memsize-filelength)); |
|
150 |
if( cc <= 0 ) break; |
|
151 |
filelength+=cc; |
|
1
by Juan Cespedes
Import upstream version 0.16.14 |
152 |
}
|
1.1.1
by Matthias Klose
Import upstream version 0.16.17 |
153 |
|
1
by Juan Cespedes
Import upstream version 0.16.14 |
154 |
*(mem_end=mem_start+filelength) = '\n'; |
155 |
mem_end[1] = '\0'; |
|
156 |
||
157 |
infiln = infil0 = 0; /* Assemble from memory */ |
|
158 |
if(fd) close(fd); |
|
159 |
fd = -1; |
|
160 |
}
|
|
161 |
cant_do_this: |
|
162 |
#endif
|
|
163 |
||
164 |
clearsource(); |
|
165 |
return fd; |
|
166 |
}
|
|
167 |
||
168 |
/*
|
|
169 |
handle GET pseudo_op
|
|
170 |
stack state of current file, open new file and reset global state vars
|
|
171 |
file must be seekable for the buffer discard/restore method to work
|
|
172 |
*/
|
|
173 |
||
174 |
PUBLIC void pget() |
|
175 |
{
|
|
176 |
if (infiln >= MAXGET) |
|
177 |
error(GETOV); |
|
178 |
else
|
|
179 |
{
|
|
180 |
char save; |
|
181 |
||
182 |
skipline(); |
|
183 |
listline(); |
|
184 |
||
185 |
getstak->fd = infil; |
|
186 |
getstak->line = linum; |
|
187 |
if (infiln != 0) |
|
188 |
#if MINIBUF == 1
|
|
189 |
getstak->position = inp_tell(infil); |
|
190 |
#else
|
|
191 |
getstak->position = lseek(infil, 0L, 1); |
|
192 |
#endif
|
|
193 |
else
|
|
194 |
getstak->position = (off_t)eol_ptr; |
|
195 |
++getstak; |
|
196 |
++infiln; |
|
197 |
linum = 0; |
|
198 |
||
199 |
for(lineptr=symname; *lineptr != EOLCHAR; lineptr++) |
|
200 |
if( *lineptr <= ' ' ) break; |
|
201 |
save = *lineptr; *lineptr = '\0'; |
|
202 |
infil = open_input(symname); |
|
203 |
*lineptr = save; |
|
204 |
getsym(); |
|
205 |
}
|
|
206 |
}
|
|
207 |
||
208 |
/* process end of file */
|
|
209 |
/* close file, unstack old file if current one is included */
|
|
210 |
/* otherwise switch pass 0 to pass 1 or exit on pass 2 */
|
|
211 |
/* end of file may be from phyical end of file or an END statement */
|
|
212 |
||
213 |
PUBLIC void pproceof() |
|
214 |
{
|
|
215 |
if (infiln != 0) |
|
216 |
close(infil); |
|
217 |
if (infiln == infil0) |
|
218 |
/* all conditionals must be closed before end of main file (not GETs) */
|
|
219 |
{
|
|
220 |
if (blocklevel != 0) |
|
221 |
error(EOFBLOCK); |
|
222 |
if (iflevel != 0) |
|
223 |
error(EOFIF); |
|
224 |
if (pass && (lcdata & UNDBIT)) |
|
225 |
error(EOFLC); |
|
226 |
lcptr->data = lcdata; |
|
227 |
lcptr->lc = lc; |
|
228 |
}
|
|
229 |
/* macros must be closed before end of all files */
|
|
230 |
if (macload) |
|
231 |
error(EOFMAC); |
|
232 |
if (linebuf != lineptr) |
|
233 |
listline(); /* last line or line after last if error */ |
|
234 |
if (infiln != infil0) |
|
235 |
{
|
|
236 |
--getstak; |
|
237 |
infil = getstak->fd; |
|
238 |
linum = getstak->line; |
|
239 |
if (--infiln == 0) |
|
240 |
eol_ptr = (void*)getstak->position; |
|
241 |
else
|
|
242 |
#if MINIBUF == 1
|
|
243 |
inp_seek(infil, getstak->position); |
|
244 |
#else
|
|
245 |
lseek(infil, getstak->position, 0); |
|
246 |
#endif
|
|
247 |
}
|
|
248 |
else if (pass!=last_pass) |
|
249 |
{
|
|
250 |
pass++; |
|
251 |
if( last_pass>1 && last_pass<30 && dirty_pass && pass==last_pass ) |
|
252 |
last_pass++; |
|
253 |
||
254 |
if( pass==last_pass ) |
|
255 |
objheader(); /* while pass 1 data all valid */ |
|
256 |
binmbuf = 0; /* reset zero variables */ |
|
257 |
maclevel = iflevel = blocklevel = |
|
258 |
totwarn = toterr = linum = macnum = 0; |
|
259 |
initp1p2(); /* reset other varaiables */ |
|
260 |
if(pass==last_pass) |
|
261 |
binaryc = binaryg; |
|
262 |
#ifdef I80386
|
|
263 |
defsize = idefsize; |
|
264 |
cpuid = origcpuid; |
|
265 |
#endif
|
|
266 |
if(pass==last_pass) |
|
267 |
{
|
|
268 |
list.current = list.global; |
|
269 |
maclist.current = maclist.global; |
|
270 |
as_warn.current = TRUE; |
|
271 |
if (as_warn.semaphore < 0) |
|
272 |
as_warn.current = FALSE; |
|
273 |
}
|
|
274 |
||
275 |
if (infiln != 0) |
|
276 |
infil = open_input(filnamptr); |
|
277 |
else
|
|
278 |
eol_ptr=0; |
|
279 |
||
280 |
if(pass==last_pass) |
|
281 |
binheader(); |
|
282 |
||
283 |
line_zero(); |
|
284 |
}
|
|
285 |
else
|
|
286 |
finishup(); |
|
287 |
}
|
|
288 |
||
289 |
/*
|
|
290 |
read 1 line of source.
|
|
291 |
Source line ends with '\n', line returned is null terminated without '\n'.
|
|
292 |
Control characters other than blank, tab and newline are discarded.
|
|
293 |
Long lines (length > LINLEN) are truncated, and an error is generated.
|
|
294 |
On EOF, calls pproceof(), and gets next line unless loading a macro.
|
|
295 |
This is where macro lines are recursively expanded.
|
|
296 |
*/
|
|
297 |
||
298 |
PUBLIC void readline() |
|
299 |
{
|
|
300 |
int cc = 0; |
|
301 |
||
302 |
listpre = FALSE; /* not listed yet */ |
|
303 |
if (maclevel != 0) |
|
304 |
{
|
|
305 |
register char *bufptr; /* hold *bufptr in a reg char variable */ |
|
306 |
register char *reglineptr; /* if possible (not done here) */ |
|
307 |
char *oldbufptr; |
|
308 |
struct schain_s *parameters; |
|
309 |
char paramnum; |
|
310 |
unsigned int remaining; /* space remaining in line + 2 */ |
|
311 |
/* value 0 not used except for temp predec */
|
|
312 |
/* value 1 means error already gen */
|
|
313 |
/* values 1 and 2 mean no space */
|
|
314 |
||
315 |
for (; maclevel != 0; |
|
316 |
macpar = macstak->parameters, ++macstak, --maclevel) |
|
317 |
if (*(bufptr = macstak->text) != ETB) |
|
318 |
/* nonempty macro, process it and return without continuing the for loop */
|
|
319 |
{
|
|
320 |
if (!macflag) |
|
321 |
{
|
|
322 |
maclinebuf = linebuf; |
|
323 |
maclineptr = lineptr; |
|
324 |
macflag = TRUE; |
|
325 |
}
|
|
326 |
remaining = LINLEN + 2; |
|
327 |
lineptr = linebuf = reglineptr = hid_linebuf; |
|
328 |
while (*bufptr++ != EOLCHAR) |
|
329 |
{
|
|
330 |
if (bufptr[-1] == MACROCHAR && *bufptr >= '0' && *bufptr <= '9') |
|
331 |
{
|
|
332 |
parameters = macstak->parameters; |
|
333 |
for (paramnum = *bufptr++; paramnum-- != '0';) |
|
334 |
if ((parameters = parameters->next) == NUL_PTR) |
|
335 |
break; |
|
336 |
if (parameters != NUL_PTR) |
|
337 |
{
|
|
338 |
for (oldbufptr = bufptr, bufptr = parameters->string; |
|
339 |
*bufptr++ != 0;) |
|
340 |
{
|
|
341 |
if (--remaining <= 1) |
|
342 |
{
|
|
343 |
if (remaining != 0) |
|
344 |
line_too_long(); |
|
345 |
remaining = 1; |
|
346 |
break; /* forget rest, param on 1 line */ |
|
347 |
}
|
|
348 |
*reglineptr++ = bufptr[-1]; |
|
349 |
}
|
|
350 |
bufptr = oldbufptr; |
|
351 |
}
|
|
352 |
}
|
|
353 |
else
|
|
354 |
{
|
|
355 |
if (--remaining <= 1) |
|
356 |
{
|
|
357 |
if (remaining != 0) |
|
358 |
line_too_long(); |
|
359 |
remaining = 1; |
|
360 |
}
|
|
361 |
else
|
|
362 |
*reglineptr++ = bufptr[-1]; |
|
363 |
}
|
|
364 |
}
|
|
365 |
macstak->text = bufptr; |
|
366 |
#if 0
|
|
367 |
*reglineptr = 0;
|
|
368 |
printf("MLINE:%s.\n", lineptr);
|
|
369 |
#endif
|
|
370 |
*reglineptr = EOLCHAR; |
|
371 |
return; |
|
372 |
}
|
|
373 |
}
|
|
374 |
if (macflag) |
|
375 |
{
|
|
376 |
linebuf = maclinebuf; |
|
377 |
lineptr = maclineptr; |
|
378 |
macflag = FALSE; |
|
379 |
}
|
|
380 |
/* End of macro expansion processing */
|
|
381 |
||
382 |
again: /* On EOF for main or included files */ |
|
383 |
++linum; |
|
384 |
||
385 |
#if BIGBUFFER == 1
|
|
386 |
if( infiln == 0 ) |
|
387 |
{
|
|
388 |
if( eol_ptr == 0 ) eol_ptr = mem_start-1; |
|
389 |
else *eol_ptr = '\n'; |
|
390 |
linebuf = lineptr = eol_ptr + 1; |
|
391 |
cc = (mem_end - linebuf); |
|
392 |
||
393 |
/* memchr not strchr 'cause some implementations of strchr are like:
|
|
394 |
memchr(x,y,strlen(x)); this is _BAD_ with BIGBUFFER
|
|
395 |
*/
|
|
396 |
if((eol_ptr = memchr(linebuf, '\n', cc)) == 0 && cc > 0) |
|
397 |
cc = -1; |
|
398 |
}
|
|
399 |
else
|
|
400 |
#endif
|
|
401 |
{
|
|
402 |
lineptr = linebuf = hid_linebuf; |
|
403 |
*(hid_linebuf+sizeof(hid_linebuf)-2) = '\0'; /* Term */ |
|
404 |
||
405 |
#if MINIBUF == 1
|
|
406 |
cc = inp_line(infil, linebuf, sizeof(hid_linebuf)-2); |
|
407 |
if( cc >= 0 ) |
|
408 |
eol_ptr = linebuf+cc-1; |
|
409 |
#else
|
|
410 |
cc = read(infil, linebuf, sizeof(hid_linebuf)-2); |
|
411 |
if( cc > 0 ) |
|
412 |
{
|
|
413 |
eol_ptr = memchr(linebuf, '\n', cc); |
|
414 |
if( eol_ptr == 0 ) |
|
415 |
eol_ptr = hid_linebuf+sizeof(hid_linebuf)-2; |
|
416 |
else
|
|
417 |
lseek(infil, (long)(eol_ptr+1-hid_linebuf)-cc, 1); |
|
418 |
}
|
|
419 |
#endif
|
|
420 |
}
|
|
421 |
||
422 |
if( cc <= 0 ) |
|
423 |
{
|
|
424 |
if( cc < 0 ) as_abort("error reading input"); |
|
425 |
||
426 |
clearsource(); |
|
427 |
pproceof(); |
|
428 |
listpre = FALSE; |
|
429 |
if (macload) |
|
430 |
{
|
|
431 |
symname = lineptr; |
|
432 |
return; /* macro not allowed across eof */ |
|
433 |
}
|
|
434 |
goto again; |
|
435 |
}
|
|
436 |
||
437 |
#if 0
|
|
438 |
*eol_ptr = 0;
|
|
439 |
printf("LINE:%s.\n", lineptr);
|
|
440 |
#endif
|
|
441 |
*eol_ptr = EOLCHAR; |
|
442 |
}
|
|
443 |
||
444 |
PUBLIC void skipline() |
|
445 |
{
|
|
446 |
if(macflag) |
|
447 |
lineptr = strchr(hid_linebuf, EOLCHAR); |
|
448 |
else
|
|
449 |
lineptr = eol_ptr; |
|
450 |
}
|
|
451 |
||
452 |
#if MINIBUF == 1
|
|
453 |
PRIVATE char input_buf[1024]; /* input buffer */ |
|
454 |
PRIVATE int in_start=0, in_end=0; |
|
455 |
PRIVATE long ftpos = 0; |
|
456 |
PRIVATE int lastfd = -1; |
|
457 |
||
458 |
PRIVATE int inp_line(fd, buf, size) |
|
459 |
int fd; |
|
460 |
char * buf; |
|
461 |
int size; |
|
462 |
{
|
|
463 |
int offt = 0; |
|
464 |
if( fd!=lastfd ) inp_seek(-1, 0L); |
|
465 |
for(;;) |
|
466 |
{
|
|
467 |
if(in_start >= in_end) |
|
468 |
{
|
|
469 |
lastfd = -1; |
|
470 |
ftpos = lseek(fd, 0L, 1); |
|
471 |
in_start = 0; |
|
472 |
in_end = read(fd, input_buf, sizeof(input_buf)); |
|
473 |
if( in_end <=0 ) return in_end; |
|
474 |
lastfd = fd; |
|
475 |
}
|
|
476 |
if( (buf[offt++] = input_buf[in_start++]) == '\n' || offt >= size ) |
|
477 |
break; |
|
478 |
}
|
|
479 |
return offt; |
|
480 |
}
|
|
481 |
||
482 |
PRIVATE long inp_tell(fd) |
|
483 |
int fd; |
|
484 |
{
|
|
485 |
if( fd != lastfd ) |
|
486 |
return lseek(fd, 0L, 1); |
|
487 |
else
|
|
488 |
return ftpos + in_start; |
|
489 |
}
|
|
490 |
||
491 |
PRIVATE void inp_seek(fd, posn) |
|
492 |
int fd; |
|
493 |
long posn; |
|
494 |
{
|
|
495 |
if( lastfd != -1 ) |
|
496 |
lseek(lastfd, ftpos+in_start, 0); |
|
497 |
lastfd = -1; |
|
498 |
in_end = 0; |
|
499 |
if( fd >= 0 ) |
|
500 |
lseek(fd, posn, 0); |
|
501 |
}
|
|
502 |
||
503 |
#endif
|