1 /* parse.c - global parser support functions */
2 /* (c) in 2009-2017 by Volker Barthelmann and Frank Wille */
3
4 #include "vasm.h"
5
6 int esc_sequences = 0; /* do not handle escape sequences by default */
7 int nocase_macros = 0; /* macro names are case-insensitive */
8 int maxmacparams = MAXMACPARAMS;
9 int maxmacrecurs = MAXMACRECURS;
10
11 #ifndef MACROHTABSIZE
12 #define MACROHTABSIZE 0x800
13 #endif
14 static hashtable *macrohash;
15
16 #ifndef STRUCTHTABSIZE
17 #define STRUCTHTABSIZE 0x800
18 #endif
19 static hashtable *structhash;
20
21 static macro *first_macro;
22 static macro *cur_macro;
23 static struct namelen *enddir_list;
24 static size_t enddir_minlen;
25 static struct namelen *reptdir_list;
26
27 static int rept_cnt = -1;
28 static char *rept_start,*rept_name,*rept_vals;
29
30 static section *cur_struct;
31 static section *struct_prevsect;
32
33
escape(char * s,char * code)34 char *escape(char *s,char *code)
35 {
36 char dummy;
37 int cnt;
38
39 if (*s++ != '\\')
40 ierror(0);
41 if (code == NULL)
42 code = &dummy;
43
44 if (!esc_sequences) {
45 *code='\\';
46 return s;
47 }
48
49 switch (*s) {
50 case 'b':
51 *code='\b';
52 return s+1;
53 case 'f':
54 *code='\f';
55 return s+1;
56 case 'n':
57 *code='\n';
58 return s+1;
59 case 'r':
60 *code='\r';
61 return s+1;
62 case 't':
63 *code='\t';
64 return s+1;
65 case '\\':
66 *code='\\';
67 return s+1;
68 case '\"':
69 *code='\"';
70 return s+1;
71 case '\'':
72 *code='\'';
73 return s+1;
74 case 'e':
75 *code=27;
76 return s+1;
77 case '0': case '1': case '2': case '3': case '4':
78 case '5': case '6': case '7': case '8': case '9':
79 *code=0;
80 cnt=0;
81 while (*s>='0' && *s<='9' && ++cnt<=3) {
82 *code = *code*8 + *s-'0';
83 s++;
84 }
85 return s;
86 case 'x': case 'X':
87 *code=0;
88 s++;
89 while ((*s>='0' && *s<='9') ||
90 (*s>='a' && *s<='f') || (*s>='A' && *s<='F')) {
91 if (*s>='0' && *s<='9')
92 *code = *code*16 + *s-'0';
93 else if (*s>='a' && *s<='f')
94 *code = *code*16 + *s-'a' + 10;
95 else
96 *code = *code*16 + *s -'A' + 10;
97 s++;
98 }
99 return s;
100 default:
101 general_error(35,*s);
102 return s;
103 }
104 }
105
106
cut_trail_blanks(char * s)107 char *cut_trail_blanks(char *s)
108 {
109 while (isspace((unsigned char)*(s-1))) /* cut trailing blanks */
110 s--;
111 return s;
112 }
113
114
parse_name(char ** start)115 char *parse_name(char **start)
116 /* parses a quoted or unquoted name-string and returns a pointer to it */
117 {
118 char *s = *start;
119 char c,*name;
120
121 if (*s=='\"' || *s=='\'') {
122 c = *s++;
123 name = s;
124 while (*s && *s!=c)
125 s++;
126 name = cnvstr(name,s-name);
127 if (*s)
128 s = skip(s+1);
129 }
130 #ifdef VASM_CPU_M68K
131 else if (*s=='<') {
132 s++;
133 name = s;
134 while (*s && *s!='>')
135 s++;
136 name = cnvstr(name,s-name);
137 if (*s)
138 s = skip(s+1);
139 }
140 #endif
141 else {
142 name = s;
143 while (!ISEOL(s) && !isspace((unsigned char)*s) && *s!=',')
144 s++;
145 if (s != name) {
146 name = cnvstr(name,s-name);
147 s = skip(s);
148 }
149 else
150 name = NULL; /* nothing read */
151 }
152 *start = s;
153 return name;
154 }
155
156
skip_eol(char * s,char * e)157 static char *skip_eol(char *s,char *e)
158 {
159 while (s<e && *s!='\0' && *s!='\n' && *s!='\r')
160 s++;
161 return s;
162 }
163
164
skip_line(char * s)165 char *skip_line(char *s)
166 {
167 while (*s!='\0')
168 s++;
169 return s;
170 }
171
172
skip_identifier(char * s)173 char *skip_identifier(char *s)
174 {
175 char *name = s;
176
177 if (ISIDSTART(*s)) {
178 s++;
179 while (ISIDCHAR(*s))
180 s++;
181 if (s = CHKIDEND(name,s))
182 if (!ISBADID(name,s-name))
183 return s;
184 }
185 return NULL;
186 }
187
188
parse_identifier(char ** s)189 char *parse_identifier(char **s)
190 {
191 char *name = *s;
192 char *endname;
193
194 if (endname = skip_identifier(name)) {
195 *s = endname;
196 return cnvstr(name,endname-name);
197 }
198 return NULL;
199 }
200
201
skip_string(char * s,char delim,size_t * size)202 char *skip_string(char *s,char delim,size_t *size)
203 /* skip a string, optionally store the size in bytes in size, when not NULL */
204 {
205 size_t n = 0;
206
207 if (*s != delim)
208 general_error(6,delim); /* " expected */
209 else
210 s++;
211
212 while (*s) {
213 if (*s == '\\') {
214 s = escape(s,NULL);
215 }
216 else {
217 if (*s++ == delim) {
218 if (*s == delim)
219 s++; /* allow """" to be recognized as " */
220 else
221 break;
222 }
223 }
224 n++;
225 }
226
227 if (*(s-1) != delim)
228 general_error(6,delim); /* " expected */
229 if (size)
230 *size = n;
231 return s;
232 }
233
234
read_string(char * p,char * s,char delim,int width)235 char *read_string(char *p,char *s,char delim,int width)
236 /* read string contents with width bits for each character into a buffer p,
237 optionally starting with a delim-character, excluding the terminating
238 character */
239 {
240 char c;
241
242 if (width & 7)
243 ierror(0);
244 width >>= 3;
245
246 if (*s == delim)
247 s++;
248
249 while (*s) {
250 if (*s == '\\') {
251 s = escape(s,&c);
252 }
253 else {
254 c = *s++;
255 if (c == delim) {
256 if (*s == delim)
257 s++; /* allow """" to be recognized as " */
258 else
259 break;
260 }
261 }
262 setval(BIGENDIAN,p,width,(unsigned char)c);
263 p += width;
264 }
265 return s;
266 }
267
268
parse_string(char ** str,char delim,int width)269 dblock *parse_string(char **str,char delim,int width)
270 {
271 size_t size;
272 dblock *db;
273 char *p,c;
274 char *s = *str;
275
276 if (width & 7)
277 ierror(0);
278
279 /* how many bytes do we need for the string? */
280 skip_string(s,delim,&size);
281 if (size == 1)
282 return NULL; /* it's just one char, so use eval_expr() on it */
283
284 db = new_dblock();
285 db->size = size * (size_t)(width>>3);
286 db->data = db->size ? mymalloc(db->size) : NULL;
287
288 /* now copy the string for real into the dblock */
289 s = read_string(db->data,s,delim,width);
290 *str = s;
291 return db;
292 }
293
294
parse_symbol(char ** s)295 char *parse_symbol(char **s)
296 /* return pointer to an allocated local/global symbol string, or NULL */
297 {
298 char *name;
299
300 name = get_local_label(s);
301 if (name == NULL)
302 name = parse_identifier(s);
303 return name;
304 }
305
306
parse_labeldef(char ** line,int needcolon)307 char *parse_labeldef(char **line,int needcolon)
308 /* Parse a global or local label definition at the beginning of a line.
309 Return pointer to its allocate buffer, when valid.
310 A trailing colon may be required or optional, but becomes mandatory
311 when label is not starting at first column. */
312 {
313 char *s = *line;
314 char *labname;
315
316 if (isspace((unsigned char )*s)) {
317 s = skip(s);
318 needcolon = 1; /* colon required, when label doesn't start at 1st column */
319 }
320
321 if (labname = parse_symbol(&s)) {
322 s = skip(s);
323 if (*s == ':') {
324 s++;
325 needcolon = 0;
326 }
327 if (needcolon) {
328 myfree(labname);
329 labname = NULL;
330 }
331 else
332 *line = s;
333 }
334 return labname;
335 }
336
337
338
check_indir(char * p,char * q)339 int check_indir(char *p,char *q)
340 /* returns true when the whole sequence between p and q starts and ends with */
341 /* parentheses and there are no unbalanced parentheses within */
342 {
343 char c;
344 int n;
345
346 p = skip(p);
347 if (*p++ != '(')
348 return 0;
349
350 n = 1;
351 while (n>0 && p<q) {
352 c = *p++;
353 if (c == '(')
354 n++;
355 else if (c == ')')
356 n--;
357 }
358 if (p < q)
359 p = skip(p);
360
361 return n==0 && p>=q;
362 }
363
364
include_binary_file(char * inname,long nbskip,unsigned long nbkeep)365 void include_binary_file(char *inname,long nbskip,unsigned long nbkeep)
366 /* locate a binary file and convert into a data atom */
367 {
368 char *filename;
369 FILE *f;
370
371 filename = convert_path(inname);
372 if (f = locate_file(filename,"rb")) {
373 size_t size = filesize(f);
374
375 if (size > 0) {
376 if (nbskip>=0 && nbskip<=size) {
377 dblock *db = new_dblock();
378
379 if (nbkeep > (unsigned long)(size - nbskip) || nbkeep==0)
380 db->size = size - (size_t)nbskip;
381 else
382 db->size = nbkeep;
383
384 db->data = mymalloc(size);
385 if (nbskip > 0)
386 fseek(f,nbskip,SEEK_SET);
387
388 fread(db->data,1,db->size,f);
389 add_atom(0,new_data_atom(db,1));
390 }
391 else
392 general_error(46); /* bad file-offset argument */
393 }
394 fclose(f);
395 }
396 myfree(filename);
397 }
398
399
dirlist_match(char * s,char * e,struct namelen * list)400 static struct namelen *dirlist_match(char *s,char *e,struct namelen *list)
401 /* check if a directive from the list matches the current source location */
402 {
403 size_t len;
404 size_t maxlen = e - s;
405
406 while (len = list->len) {
407 if (len <= maxlen) {
408 if (!strnicmp(s,list->name,len) && isspace((unsigned char)*(s + len)))
409 return list;
410 }
411 list++;
412 }
413 return NULL;
414 }
415
416
dirlist_minlen(struct namelen * list)417 static size_t dirlist_minlen(struct namelen *list)
418 {
419 size_t minlen;
420
421 if (list == NULL)
422 ierror(0);
423 for (minlen=list->len; list->len; list++) {
424 if (list->len < minlen)
425 minlen = list->len;
426 }
427 return minlen;
428 }
429
430
431 /* return the line number of the last real source text instance, i.e.
432 not the line within a macro or repetition */
real_line(void)433 int real_line(void)
434 {
435 source *src = cur_src;
436 int line = src->line;
437
438 while (src->num_params >= 0) {
439 line = src->parent_line;
440 src = src->parent;
441 if (src == NULL)
442 ierror(0); /* macro must have a parent */
443 }
444 return line;
445 }
446
447
new_repeat(int rcnt,char * name,char * vals,struct namelen * reptlist,struct namelen * endrlist)448 void new_repeat(int rcnt,char *name,char *vals,
449 struct namelen *reptlist,struct namelen *endrlist)
450 {
451 if (cur_macro==NULL && cur_src!=NULL && enddir_list==NULL) {
452 enddir_list = endrlist;
453 enddir_minlen = dirlist_minlen(endrlist);
454 reptdir_list = reptlist;
455 rept_start = cur_src->srcptr;
456 rept_name = name;
457 rept_vals = vals;
458 rept_cnt = rcnt; /* also REPT_IRP or REPT_IRPC */
459 }
460 else
461 ierror(0);
462 }
463
464
find_macarg_name(source * src,char * name,size_t len)465 int find_macarg_name(source *src,char *name,size_t len)
466 {
467 struct macarg *ma;
468 int idx;
469
470 /* named macro arguments */
471 if (src->macro != NULL) {
472 for (idx=0,ma=src->argnames; ma!=NULL && idx<maxmacparams;
473 idx++,ma=ma->argnext) {
474 /* @@@ case-sensitive comparison? */
475 if (ma->arglen==len && strncmp(ma->argname,name,len)==0)
476 return idx;
477 }
478 }
479
480 /* repeat-loop iterator name */
481 if (src->irpname != NULL) {
482 if (strlen(src->irpname)==len && strncmp(src->irpname,name,len)==0) {
483 /* copy current iterator value to param[MAXMACPARAMS] */
484 src->param[MAXMACPARAMS] = src->irpvals->argname;
485 src->param_len[MAXMACPARAMS] = src->irpvals->arglen;
486 return IRPVAL;
487 }
488 }
489
490 return -1;
491 }
492
493
494 /* append a macarg object at the end of the given list */
addmacarg(struct macarg ** list,char * start,char * end)495 struct macarg *addmacarg(struct macarg **list,char *start,char *end)
496 {
497 struct macarg *lastarg,*newarg;
498 int len = end-start;
499
500 /* count arguments */
501 if (lastarg = *list) {
502 while (lastarg->argnext)
503 lastarg = lastarg->argnext;
504 }
505
506 newarg = mymalloc(sizeof(struct macarg) + len);
507 newarg->argnext = NULL;
508 if (start != NULL) {
509 memcpy(newarg->argname,start,len);
510 newarg->argname[len] = '\0';
511 newarg->arglen = len;
512 }
513 else
514 newarg->arglen = MACARG_REQUIRED;
515 if (lastarg)
516 lastarg->argnext = newarg;
517 else
518 *list = newarg;
519
520 return newarg;
521 }
522
523
new_macro(char * name,struct namelen * endmlist,char * args)524 macro *new_macro(char *name,struct namelen *endmlist,char *args)
525 {
526 hashdata data;
527 macro *m = NULL;
528
529 if (cur_macro==NULL && cur_src!=NULL && enddir_list==NULL) {
530 m = mymalloc(sizeof(macro));
531 m->name = mystrdup(name);
532 if (nocase_macros)
533 strtolower(m->name);
534 m->num_argnames = -1;
535 m->argnames = m->defaults = NULL;
536 m->recursions = 0;
537 m->vararg = -1;
538
539 if (find_name_nc(mnemohash,name,&data)) {
540 int idx;
541
542 m->text = cur_src->srcptr;
543 for (idx=data.idx;
544 idx<mnemonic_cnt && !stricmp(mnemonics[idx].name,name); idx++) {
545 if (MNEMONIC_VALID(idx)) {
546 m->text = NULL;
547 general_error(51); /* name conflicts with mnemonic */
548 break;
549 }
550 }
551 }
552 else if (find_name_nc(dirhash,name,&data)) {
553 m->text = NULL;
554 general_error(52); /* name conflicts with directive */
555 }
556 else
557 m->text = cur_src->srcptr;
558
559 cur_macro = m;
560 enddir_list = endmlist;
561 enddir_minlen = dirlist_minlen(endmlist);
562 rept_cnt = -1;
563 rept_start = NULL;
564
565 if (args) {
566 /* named arguments have been given */
567 struct macarg *ma;
568 char *end;
569 int n = 0;
570
571 m->num_argnames = 0;
572 args = skip(args);
573 while (args!=NULL && !ISEOL(args)) {
574 end = SKIP_MACRO_ARGNAME(args);
575
576 if (end!=NULL && end-args!=0 && m->vararg<0) {
577 /* add another argument name */
578 ma = addmacarg(&m->argnames,args,end);
579 m->num_argnames++;
580 args = skip(end);
581 if (end = MACRO_ARG_OPTS(m,n,ma->argname,args))
582 args = skip(end); /* got defaults and qualifiers */
583 else
584 addmacarg(&m->defaults,args,args); /* default is empty */
585 n++;
586 }
587 else {
588 general_error(42); /* illegal macro argument */
589 break;
590 }
591 args = MACRO_ARG_SEP(args); /* check for separator between names */
592 }
593 }
594 }
595 else
596 ierror(0);
597
598 return m;
599 }
600
601
find_macro(char * name,int name_len)602 macro *find_macro(char *name,int name_len)
603 {
604 hashdata data;
605
606 if (nocase_macros) {
607 if (!find_namelen_nc(macrohash,name,name_len,&data))
608 return NULL;
609 }
610 else {
611 if (!find_namelen(macrohash,name,name_len,&data))
612 return NULL;
613 }
614 return data.ptr;
615 }
616
617
618 /* check if 'name' is a known macro, then execute macro context */
execute_macro(char * name,int name_len,char ** q,int * q_len,int nq,char * s)619 int execute_macro(char *name,int name_len,char **q,int *q_len,int nq,
620 char *s)
621 {
622 macro *m;
623 source *src;
624 struct macarg *ma;
625 int n;
626 struct namelen param,arg;
627 #if MAX_QUALIFIERS>0
628 char *defq[MAX_QUALIFIERS];
629 int defq_len[MAX_QUALIFIERS];
630 #endif
631 #ifdef NO_MACRO_QUALIFIERS
632 char *nptr = name;
633
634 /* Instruction qualifiers are ignored for macros on this architecture.
635 So we have to determine the length of the mnemonic again. */
636 while (*nptr && !isspace((unsigned char)*nptr))
637 nptr++;
638 name_len = nptr - name;
639 nq = 0;
640 #endif
641
642 if (!(m = find_macro(name,name_len)))
643 return 0;
644
645 /* it's a macro: read arguments and execute it */
646 if (m->recursions >= maxmacrecurs) {
647 general_error(56,maxmacrecurs); /* maximum macro recursions reached */
648 return 0;
649 }
650 m->recursions++;
651 src = new_source(m->name,m->text,m->size);
652 src->argnames = m->argnames;
653
654 #if MAX_QUALIFIERS>0
655 /* remember given qualifiers, or use the cpu's default qualifiers */
656 for (n=0; n<nq; n++) {
657 src->qual[n] = q[n];
658 src->qual_len[n] = q_len[n];
659 }
660 nq = set_default_qualifiers(defq,defq_len);
661 for (; n<nq; n++) {
662 src->qual[n] = defq[n];
663 src->qual_len[n] = defq_len[n];
664 }
665 src->num_quals = nq;
666 #endif
667
668 /* fill in the defaults first */
669 for (n=0,ma=m->defaults; n<maxmacparams; n++) {
670 if (ma != NULL) {
671 src->param[n] = ma->arglen==MACARG_REQUIRED ? NULL : ma->argname;
672 src->param_len[n] = ma->arglen==MACARG_REQUIRED ? 0 : ma->arglen;
673 ma = ma->argnext;
674 }
675 else {
676 src->param[n] = emptystr;
677 src->param_len[n] = 0;
678 }
679 }
680
681 /* read macro arguments from operand field */
682 s = skip(s);
683 n = 0;
684 while (!ISEOL(s) && n<maxmacparams) {
685 if (n>=0 && m->vararg==n) {
686 /* Varargs: take rest of line as argument */
687 char *start = s;
688 char *end = s;
689
690 while (!ISEOL(s)) {
691 s++;
692 if (!isspace((unsigned char)*s))
693 end = s; /* remember last non-blank character */
694 }
695 src->param[n] = start;
696 src->param_len[n] = end - start;
697 n++;
698 break;
699 }
700 else if ((s = parse_macro_arg(m,s,¶m,&arg)) != NULL) {
701 if (arg.len) {
702 /* argument selected by keyword */
703 if (n <= 0) {
704 n = find_macarg_name(src,arg.name,arg.len);
705 if (n >= 0) {
706 src->param[n] = param.name;
707 src->param_len[n] = param.len;
708 }
709 else
710 general_error(72); /* undefined macro argument name */
711 n = -1;
712 }
713 else
714 general_error(71); /* cannot mix positional and keyword arguments */
715 }
716 else {
717 /* argument selected by position n */
718 if (n >= 0) {
719 if (param.len > 0) {
720 src->param[n] = param.name;
721 src->param_len[n] = param.len;
722 }
723 n++;
724 }
725 else
726 general_error(71); /* cannot mix positional and keyword arguments */
727 }
728 }
729 else
730 break;
731
732 s = skip(s);
733 if (!(s = MACRO_PARAM_SEP(s))) /* check for separator between params. */
734 break;
735 }
736
737 if (n < 0)
738 n = m->num_argnames>=0 ? m->num_argnames : 0;
739 if (n > maxmacparams) {
740 general_error(27,maxmacparams); /* number of args exceeded */
741 n = maxmacparams;
742 }
743
744 src->macro = m;
745 src->num_params = n; /* >=0 indicates macro source */
746
747 for (n=0; n<maxmacparams; n++) {
748 if (src->param[n] == NULL) {
749 /* required, but missing */
750 src->param[n] = emptystr;
751 src->param_len[n] = 0;
752 general_error(73,n+1); /* required macro argument was left out */
753 }
754 }
755
756 EXEC_MACRO(src); /* syntax-module dependant initializations */
757 cur_src = src; /* execute! */
758 return 1;
759 }
760
761
leave_macro(void)762 int leave_macro(void)
763 {
764 if (cur_src->macro != NULL) {
765 end_source(cur_src);
766 return 0; /* ok */
767 }
768 general_error(36); /* no current macro to exit */
769 return -1;
770 }
771
772
773 /* remove an already defined macro from the hash table */
undef_macro(char * name)774 int undef_macro(char *name)
775 {
776 if (find_macro(name,strlen(name))) {
777 rem_hashentry(macrohash,name,nocase_macros);
778 return 1;
779 }
780 general_error(68); /* macro does not exist */
781 return 0;
782 }
783
784
start_repeat(char * rept_end)785 static void start_repeat(char *rept_end)
786 {
787 char buf[MAXPATHLEN];
788 source *src;
789 char *p,*val;
790 int i;
791
792 reptdir_list = NULL;
793 if ((rept_cnt<0 && rept_cnt!=REPT_IRP && rept_cnt!=REPT_IRPC) ||
794 cur_src==NULL || strlen(cur_src->name) + 24 >= MAXPATHLEN)
795 ierror(0);
796
797 if (rept_cnt != 0) {
798 sprintf(buf,"REPEAT:%s:line %d",cur_src->name,cur_src->line);
799 src = new_source(mystrdup(buf),rept_start,rept_end-rept_start);
800 src->irpname = rept_name;
801 src->irpvals = NULL;
802 #ifdef REPTNSYM
803 src->reptn = 0;
804 set_internal_abs(REPTNSYM,0);
805 #endif
806
807 switch (rept_cnt) {
808 case REPT_IRP: /* iterate with comma separated values */
809 p = rept_vals;
810 if (!*p) {
811 addmacarg(&src->irpvals,p,p);
812 src->repeat = 1;
813 }
814 else {
815 src->repeat = 0;
816 while (val = parse_name(&p)) {
817 addmacarg(&src->irpvals,val,val+strlen(val));
818 myfree(val);
819 src->repeat++;
820 p = skip(p);
821 if (*p == ',')
822 p = skip(p+1);
823 }
824 }
825 break;
826
827 case REPT_IRPC: /* iterate with each character */
828 p = rept_vals;
829 if (!*p) {
830 addmacarg(&src->irpvals,p,p);
831 src->repeat = 1;
832 }
833 else {
834 src->repeat = 0;
835 do {
836 while (!isspace((unsigned char )*p) && *p!=',' && !ISEOL(p)) {
837 addmacarg(&src->irpvals,p,p+1);
838 src->repeat++;
839 p++;
840 }
841 p = skip(p);
842 if (*p == ',')
843 p = skip(p+1);
844 }
845 while (!ISEOL(p));
846 }
847 break;
848
849 default: /* iterate rept_cnt times */
850 src->repeat = (unsigned long)rept_cnt;
851 break;
852 }
853
854 if (cur_src->macro != NULL) {
855 /* repetition in a macro: get parameters */
856 src->num_params = cur_src->num_params;
857 for (i=0; i<src->num_params; i++) {
858 src->param[i] = cur_src->param[i];
859 src->param_len[i] = cur_src->param_len[i];
860 }
861 #if MAX_QUALIFIERS > 0
862 src->num_quals = cur_src->num_quals;
863 for (i=0; i<src->num_quals; i++) {
864 src->qual[i] = cur_src->qual[i];
865 src->qual_len[i] = cur_src->qual_len[i];
866 }
867 #endif
868 src->argnames = cur_src->argnames;
869 }
870
871 if (src->repeat == 0)
872 ierror(0);
873 cur_src = src; /* repeat it */
874 }
875 }
876
877
add_macro(void)878 static void add_macro(void)
879 {
880 if (cur_macro!=NULL && cur_src!=NULL) {
881 if (cur_macro->text != NULL) {
882 hashdata data;
883
884 cur_macro->size = cur_src->srcptr - cur_macro->text;
885 cur_macro->next = first_macro;
886 first_macro = cur_macro;
887 data.ptr = cur_macro;
888 add_hashentry(macrohash,cur_macro->name,data);
889 }
890 cur_macro = NULL;
891 }
892 else
893 ierror(0);
894 }
895
896
897 /* copy macro parameter n to line buffer, return -1 when out of space */
copy_macro_param(source * src,int n,char * d,int len)898 int copy_macro_param(source *src,int n,char *d,int len)
899 {
900 if (n < 0) {
901 ierror(0);
902 }
903 else if ((n<src->num_params && n<maxmacparams) || n==IRPVAL) {
904 int i;
905
906 if (n == IRPVAL)
907 n = MAXMACPARAMS;
908
909 for (i=0; i<src->param_len[n] && len>0; i++,len--)
910 *d++ = src->param[n][i];
911
912 return i==src->param_len[n] ? i : -1;
913 }
914 else
915 return 0;
916 }
917
918
919 /* copy nth macro qualifier to line buffer, return -1 when out of space */
copy_macro_qual(source * src,int n,char * d,int len)920 int copy_macro_qual(source *src,int n,char *d,int len)
921 {
922 #if MAX_QUALIFIERS > 0
923 int i;
924
925 if (n < src->num_quals) {
926 for (i=0; i<src->qual_len[n] && len>0; i++,len--)
927 *d++ = src->qual[n][i];
928 }
929 return i==src->qual_len[n] ? i : -1;
930 #else
931 return 0;
932 #endif
933 }
934
935 /* Switch to a named offset section which defines the structure. */
new_structure(char * name)936 int new_structure(char *name)
937 {
938 hashdata data;
939
940 if (cur_struct) {
941 general_error(48); /* cannot declare structure within structure */
942 return 0;
943 }
944
945 struct_prevsect = current_section;
946 switch_offset_section(name,-1);
947 data.ptr = cur_struct = current_section;
948 add_hashentry(structhash,cur_struct->name,data);
949 return 1;
950 }
951
952 /* Finish the structure definition and return the previous section. */
end_structure(section ** prev)953 int end_structure(section **prev)
954 {
955 if (cur_struct) {
956 *prev = struct_prevsect;
957 cur_struct = struct_prevsect = NULL;
958 return 1;
959 }
960 general_error(49); /* no structure */
961 return 0;
962 }
963
964
find_structure(char * name,int name_len)965 section *find_structure(char *name,int name_len)
966 {
967 hashdata data;
968 section *s;
969
970 if (cur_struct!=NULL && !strcmp(cur_struct->name,name))
971 general_error(55); /* illegal structure recursion */
972
973 if (find_namelen(structhash,name,name_len,&data))
974 s = data.ptr;
975 else
976 s = NULL;
977 return s;
978 }
979
980
981 /* reads the next input line */
read_next_line(void)982 char *read_next_line(void)
983 {
984 char *s,*srcend,*d;
985 int nparam,len;
986 char *rept_end = NULL;
987
988 /* check if end of source is reached */
989 for (;;) {
990 srcend = cur_src->text + cur_src->size;
991 if (cur_src->srcptr >= srcend || *(cur_src->srcptr) == '\0') {
992 if (--cur_src->repeat > 0) {
993 struct macarg *irpval;
994
995 cur_src->srcptr = cur_src->text; /* back to start */
996 cur_src->line = 0;
997 if (cur_src->irpname!=NULL && (irpval=cur_src->irpvals)!=NULL) {
998 /* remove and deallocate leading irpval of last iteration */
999 cur_src->irpvals = irpval->argnext;
1000 myfree(irpval);
1001 }
1002 #ifdef REPTNSYM
1003 set_internal_abs(REPTNSYM,++cur_src->reptn);
1004 #endif
1005 }
1006 else {
1007 if (cur_src->macro != NULL) {
1008 if (--cur_src->macro->recursions < 0)
1009 ierror(0);
1010 }
1011 myfree(cur_src->linebuf); /* linebuf is no longer needed, saves memory */
1012 cur_src->linebuf = NULL;
1013 if (cur_src->parent == NULL)
1014 return NULL; /* no parent source means end of assembly! */
1015 cur_src = cur_src->parent; /* return to parent source */
1016 #ifdef CARGSYM
1017 if (cur_src->cargexp) {
1018 symbol *carg = internal_abs(CARGSYM);
1019 carg->expr = cur_src->cargexp; /* restore parent CARG */
1020 }
1021 #endif
1022 #ifdef REPTNSYM
1023 set_internal_abs(REPTNSYM,cur_src->reptn); /* restore parent REPTN */
1024 #endif
1025 }
1026 }
1027 else
1028 break;
1029 }
1030
1031 cur_src->line++;
1032 s = cur_src->srcptr;
1033 d = cur_src->linebuf;
1034 len = cur_src->bufsize - 2; /* excluding \0 at start and beginning */
1035 nparam = cur_src->num_params;
1036
1037 /* line buffer starts with 0, to allow checks for left-hand character */
1038 *d++ = 0;
1039
1040 if (enddir_list!=NULL && (srcend-s)>enddir_minlen) {
1041 /* reading a definition, like a macro or a repeat-block, until an
1042 end directive is found */
1043 struct namelen *dir;
1044 int rept_nest = 1;
1045
1046 if (nparam>=0 && cur_macro!=NULL)
1047 general_error(26,cur_src->name); /* macro definition inside macro */
1048
1049 while (s <= (srcend-enddir_minlen)) {
1050 if (dir = dirlist_match(s,srcend,enddir_list)) {
1051 if (cur_macro != NULL) {
1052 add_macro(); /* link macro-definition into hash-table */
1053 enddir_list = NULL;
1054 break;
1055 }
1056 else if (--rept_nest == 0) {
1057 rept_end = s;
1058 enddir_list = NULL;
1059 break;
1060 }
1061 s += dir->len;
1062 }
1063 else if (cur_macro==NULL && reptdir_list!=NULL &&
1064 (dir = dirlist_match(s,srcend,reptdir_list)) != NULL) {
1065 s += dir->len;
1066 rept_nest++;
1067 }
1068
1069 if (*s=='\"' || *s=='\'') {
1070 char c = *s++;
1071
1072 while (s<=(srcend-enddir_minlen) && *s!=c && *s!='\n' && *s!='\r') {
1073 if (*s=='\\' && (*(s+1)=='\"' || *(s+1)=='\''))
1074 s = escape(s,NULL);
1075 else
1076 s++;
1077 }
1078 }
1079
1080 if (ISEOL(s))
1081 s = skip_eol(s,srcend);
1082
1083 if (*s == '\n') {
1084 cur_src->srcptr = s + 1;
1085 cur_src->line++;
1086 }
1087 else if (*s=='\r' && *(s-1)!='\n' && (s>=(srcend-1) || *(s+1)!='\n')) {
1088 cur_src->srcptr = s + 1;
1089 cur_src->line++;
1090 }
1091 s++;
1092 }
1093
1094 if (enddir_list) {
1095 if (cur_macro)
1096 general_error(25,cur_macro->name); /* missing ENDM directive */
1097 else
1098 general_error(32); /* missing ENDR directive */
1099 }
1100
1101 /* ignore rest of line, treat as comment */
1102 s = skip_eol(s,srcend);
1103 }
1104
1105 if (nparam<0 && cur_src->irpname!=NULL)
1106 nparam = 0; /* expand current repeat-iterator symbol into source */
1107
1108 /* copy next line to linebuf */
1109 while (s<srcend && *s!='\0') {
1110 int nc;
1111
1112 if (nparam >= 0)
1113 nc = expand_macro(cur_src,&s,d,len); /* try macro arg. expansion */
1114 else
1115 nc = 0;
1116
1117 if (nc > 0) {
1118 /* expanded macro arguments */
1119 len -= nc;
1120 d += nc;
1121 }
1122 else if (nc == 0) {
1123 /* copy next character */
1124 if (*s == '\r') {
1125 if ((s>cur_src->srcptr && *(s-1)=='\n') ||
1126 (s<(srcend-1) && *(s+1)=='\n')) {
1127 /* ignore \r in \r\n and \n\r combinations */
1128 s++;
1129 }
1130 else {
1131 /* treat a single \r as \n */
1132 s++;
1133 break;
1134 }
1135 }
1136 else if (*s == '\n') {
1137 s++;
1138 break;
1139 }
1140 else if (len > 0) {
1141 *d++ = *s++;
1142 len--;
1143 }
1144 else
1145 nc = -1;
1146 }
1147
1148 if (nc < 0) {
1149 /* line buffer ran out of space, allocate a bigger one */
1150 int offs = d - cur_src->linebuf;
1151
1152 /* double its size */
1153 len += cur_src->bufsize;
1154 cur_src->bufsize += cur_src->bufsize;
1155 cur_src->linebuf = myrealloc(cur_src->linebuf,cur_src->bufsize);
1156 d = cur_src->linebuf + offs;
1157 if (debug)
1158 printf("Doubled line buffer size to %lu bytes.\n",cur_src->bufsize);
1159 }
1160 }
1161
1162 *d = '\0';
1163 cur_src->srcptr = s;
1164
1165 if (listena) {
1166 listing *new = mymalloc(sizeof(*new));
1167
1168 new->next = 0;
1169 new->line = cur_src->line;
1170 new->error = 0;
1171 new->atom = 0;
1172 new->sec = 0;
1173 new->pc = 0;
1174 new->src = cur_src;
1175 strncpy(new->txt,cur_src->linebuf+1,MAXLISTSRC);
1176 if (first_listing) {
1177 last_listing->next = new;
1178 last_listing = new;
1179 }
1180 else {
1181 first_listing = last_listing = new;
1182 }
1183 cur_listing = new;
1184 }
1185
1186 s = cur_src->linebuf+1;
1187 if (rept_end)
1188 start_repeat(rept_end);
1189 return s;
1190 }
1191
1192
init_parse(void)1193 int init_parse(void)
1194 {
1195 macrohash = new_hashtable(MACROHTABSIZE);
1196 structhash = new_hashtable(STRUCTHTABSIZE);
1197 return 1;
1198 }
1199