~ubuntu-branches/ubuntu/utopic/linux86/utopic

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