readsrc.c 11 KB

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