1 /* vasm.c main module for vasm */
2 /* (c) in 2002-2018 by Volker Barthelmann */
3
4 #include <stdlib.h>
5 #include <stdio.h>
6
7 #include "vasm.h"
8 #include "stabs.h"
9
10 #define _VER "vasm 1.8c"
11 char *copyright = _VER " (c) in 2002-2018 Volker Barthelmann";
12 #ifdef AMIGA
13 static const char *_ver = "$VER: " _VER " " __AMIGADATE__ "\r\n";
14 #endif
15
16 #define SRCREADINC (64*1024) /* extend buffer in these steps when reading */
17
18 /* The resolver will run another pass over the current section as long as any
19 label location or atom size has changed. It gives up at MAXPASSES, which
20 hopefully will never happen.
21 During the first FASTOPTPHASE passes all instructions of a section will be
22 optimized at the same time. After that the resolver enters a safe mode,
23 where only a single instruction per pass is changed. */
24 #define MAXPASSES 1000
25 #define FASTOPTPHASE 200
26
27 source *cur_src=NULL;
28 char *filename,*debug_filename;
29 section *current_section;
30 char *inname,*outname,*listname;
31 taddr inst_alignment;
32 int secname_attr;
33 int unnamed_sections;
34 int ignore_multinc;
35 int nocase;
36 int no_symbols;
37 int pic_check;
38 int done,final_pass,debug;
39 int exec_out;
40 int chklabels;
41 int warn_unalloc_ini_dat;
42 int listena,listformfeed=1,listlinesperpage=40,listnosyms;
43 listing *first_listing,*last_listing,*cur_listing;
44 struct stabdef *first_nlist,*last_nlist;
45 char *output_format="test";
46 unsigned long long taddrmask;
47 char emptystr[]="";
48 char vasmsym_name[]="__VASM";
49
50 static int produce_listing;
51 static char **listtitles;
52 static int *listtitlelines;
53 static int listtitlecnt;
54
55 static FILE *outfile=NULL;
56
57 static int depend,depend_all;
58 #define DEPEND_LIST 1
59 #define DEPEND_MAKE 2
60 struct deplist {
61 struct deplist *next;
62 char *filename;
63 };
64 static struct deplist *first_depend,*last_depend;
65
66 static section *first_section,*last_section;
67 #if NOT_NEEDED
68 static section *prev_sec=NULL,*prev_org=NULL;
69 #endif
70
71 /* MNEMOHTABSIZE should be defined by cpu module */
72 #ifndef MNEMOHTABSIZE
73 #define MNEMOHTABSIZE 0x1000
74 #endif
75 hashtable *mnemohash;
76
77 static int verbose=1,auto_import=1;
78 static struct include_path *first_incpath=NULL;
79 static struct include_path *first_source=NULL;
80
81 static char *output_copyright;
82 static void (*write_object)(FILE *,section *,symbol *);
83 static int (*output_args)(char *);
84
85
leave(void)86 void leave(void)
87 {
88 section *sec;
89 symbol *sym;
90
91 if(outfile){
92 fclose(outfile);
93 if (errors)
94 remove(outname);
95 }
96
97 if(debug){
98 fprintf(stdout,"Sections:\n");
99 for(sec=first_section;sec;sec=sec->next)
100 print_section(stdout,sec);
101
102 fprintf(stdout,"Symbols:\n");
103 for(sym=first_symbol;sym;sym=sym->next){
104 print_symbol(stdout,sym);
105 fprintf(stdout,"\n");
106 }
107 }
108
109 if(errors)
110 exit(EXIT_FAILURE);
111 else
112 exit(EXIT_SUCCESS);
113 }
114
115 /* Convert all labels from an offset-section into absolute expressions. */
convert_offset_labels(void)116 static void convert_offset_labels(void)
117 {
118 symbol *sym;
119
120 for (sym=first_symbol; sym; sym=sym->next) {
121 if (sym->type==LABSYM && sym->sec!=NULL && (sym->sec->flags&UNALLOCATED)) {
122 sym->type = EXPRESSION;
123 sym->expr = number_expr(sym->pc);
124 sym->sec = NULL;
125 }
126 }
127 }
128
129 /* Removes all unallocated (offset) sections from the list. */
remove_unalloc_sects(void)130 static void remove_unalloc_sects(void)
131 {
132 section *prev,*sec;
133
134 for (sec=first_section,prev=NULL; sec; sec=sec->next) {
135 if (sec->flags&UNALLOCATED) {
136 if (prev)
137 prev->next = sec->next;
138 else
139 first_section = sec->next;
140 }
141 else
142 prev = sec;
143 }
144 }
145
146 /* append a new stabs (nlist) symbol/debugging definition */
new_stabdef(aoutnlist * nlist,section * sec)147 static void new_stabdef(aoutnlist *nlist,section *sec)
148 {
149 struct stabdef *new = mymalloc(sizeof(struct stabdef));
150
151 new->next = NULL;
152 new->name.ptr = nlist->name;
153 new->type = nlist->type;
154 new->other = nlist->other;
155 new->desc = nlist->desc;
156 new->base = NULL;
157 if (nlist->value == NULL)
158 new->value = 0;
159 else if (!eval_expr(nlist->value,&new->value,sec,sec->pc)) {
160 int btype = find_base(nlist->value,&new->base,sec,sec->pc);
161 if (btype==BASE_ILLEGAL || btype==BASE_PCREL) {
162 new->base = NULL;
163 general_error(38); /* illegal relocation */
164 }
165 else if (new->base != NULL)
166 new->base->flags |= REFERENCED;
167 }
168 if (last_nlist)
169 last_nlist = last_nlist->next = new;
170 else
171 first_nlist = last_nlist = new;
172 }
173
174
resolve_section(section * sec)175 static void resolve_section(section *sec)
176 {
177 taddr rorg_pc,org_pc;
178 int fastphase=FASTOPTPHASE;
179 int pass=0;
180 int extrapass,rorg;
181 size_t size;
182 atom *p;
183
184 do{
185 done=1;
186 rorg=0;
187 if (++pass>=MAXPASSES){
188 general_error(7,sec->name);
189 break;
190 }
191 extrapass=pass<=fastphase;
192 if(debug)
193 printf("resolve_section(%s) pass %d%s",sec->name,pass,
194 pass<=fastphase?" (fast)\n":"\n");
195 sec->pc=sec->org;
196 for(p=sec->first;p;p=p->next){
197 sec->pc=pcalign(p,sec->pc);
198 cur_src=p->src;
199 cur_src->line=p->line;
200 #if HAVE_CPU_OPTS
201 if(p->type==OPTS){
202 cpu_opts(p->content.opts);
203 }
204 else
205 #endif
206 if(p->type==RORG){
207 if(rorg)
208 general_error(43); /* reloc org is already set */
209 rorg_pc=*p->content.rorg;
210 org_pc=sec->pc;
211 sec->pc=rorg_pc;
212 sec->flags|=ABSOLUTE;
213 rorg=1;
214 }
215 else if(p->type==RORGEND&&rorg){
216 sec->pc=org_pc+(sec->pc-rorg_pc);
217 rorg_pc=0;
218 sec->flags&=~ABSOLUTE;
219 rorg=0;
220 }
221 else if(p->type==LABEL){
222 symbol *label=p->content.label;
223 if(label->type!=LABSYM)
224 ierror(0);
225 if(label->pc!=sec->pc){
226 if(debug)
227 printf("moving label %s from %lu to %lu\n",label->name,
228 (unsigned long)label->pc,(unsigned long)sec->pc);
229 done=0;
230 label->pc=sec->pc;
231 }
232 }
233 if(pass>fastphase&&!done&&p->type==INSTRUCTION){
234 /* entered safe mode: optimize only one instruction every pass */
235 sec->pc+=p->lastsize;
236 continue;
237 }
238 if(p->changes>MAXSIZECHANGES){
239 /* atom changed size too frequently, set warning flag */
240 if(debug)
241 printf("setting resolve-warning flag for atom type %d at %lu\n",
242 p->type,(unsigned long)sec->pc);
243 sec->flags|=RESOLVE_WARN;
244 size=atom_size(p,sec,sec->pc);
245 sec->flags&=~RESOLVE_WARN;
246 }
247 else
248 size=atom_size(p,sec,sec->pc);
249 if(size!=p->lastsize){
250 if(debug)
251 printf("modify size of atom type %d at %lu from %lu to %lu\n",
252 p->type,(unsigned long)sec->pc,(unsigned long)p->lastsize,
253 (unsigned long)size);
254 done=0;
255 if(pass>fastphase)
256 p->changes++; /* now count size modifications of atoms */
257 else if(size>p->lastsize)
258 extrapass=0; /* no extra pass, when an atom became larger */
259 p->lastsize=size;
260 }
261 sec->pc+=size;
262 }
263 if(rorg){
264 sec->pc=org_pc+(sec->pc-rorg_pc);
265 sec->flags&=~ABSOLUTE; /* workaround for misssing RORGEND */
266 }
267 /* Extend the fast-optimization phase, when there was no atom which
268 became larger than in the previous pass. */
269 if(extrapass) fastphase++;
270 }while(errors==0&&!done);
271 }
272
resolve(void)273 static void resolve(void)
274 {
275 section *sec;
276 final_pass=0;
277 if(debug)
278 printf("resolve()\n");
279 for(sec=first_section;sec;sec=sec->next)
280 resolve_section(sec);
281 }
282
assemble(void)283 static void assemble(void)
284 {
285 section *sec;
286 taddr basepc,rorg_pc,org_pc;
287 atom *p;
288 int bss,rorg;
289
290 convert_offset_labels();
291 final_pass=1;
292 rorg=0;
293 for(sec=first_section;sec;sec=sec->next){
294 source *lasterrsrc=NULL;
295 utaddr oldpc;
296 int lasterrline=0,ovflw=0;
297 sec->pc=sec->org;
298 bss=strchr(sec->attr,'u')!=NULL;
299 for(p=sec->first;p;p=p->next){
300 basepc=sec->pc;
301 sec->pc=pcalign(p,sec->pc);
302 cur_src=p->src;
303 cur_src->line=p->line;
304 if(p->list&&p->list->atom==p){
305 p->list->sec=sec;
306 p->list->pc=sec->pc;
307 }
308 if(p->changes>MAXSIZECHANGES)
309 sec->flags|=RESOLVE_WARN;
310 /* print a warning on auto-aligned instructions or data */
311 if(sec->pc!=basepc){
312 atom *aa;
313 if (p->type==LABEL&&p->next!=NULL&&p->next->line==p->line)
314 aa=p->next; /* next atom in same line, look at it instead of label */
315 else
316 aa=p;
317 if (aa->type==INSTRUCTION)
318 general_error(50); /* instruction has been auto-aligned */
319 else if (aa->type==DATA||aa->type==DATADEF)
320 general_error(57); /* data has been auto-aligned */
321 }
322 if(p->type==RORG){
323 rorg_pc=*p->content.rorg;
324 org_pc=sec->pc;
325 sec->pc=rorg_pc;
326 sec->flags|=ABSOLUTE;
327 rorg=1;
328 }
329 else if(p->type==RORGEND){
330 if(rorg){
331 sec->pc=org_pc+(sec->pc-rorg_pc);
332 rorg_pc=0;
333 sec->flags&=~ABSOLUTE;
334 rorg=0;
335 }
336 else
337 general_error(44); /* reloc org was not set */
338 }
339 else if(p->type==INSTRUCTION){
340 dblock *db;
341 cur_listing=p->list;
342 db=eval_instruction(p->content.inst,sec,sec->pc);
343 if(pic_check)
344 do_pic_check(db->relocs);
345 cur_listing=0;
346 if(debug){
347 if(db->size!=(p->content.inst->code>=0?
348 instruction_size(p->content.inst,sec,sec->pc):0))
349 ierror(0);
350 }
351 /*FIXME: sauber freigeben */
352 myfree(p->content.inst);
353 p->content.db=db;
354 p->type=DATA;
355 }
356 else if(p->type==DATADEF){
357 dblock *db;
358 cur_listing=p->list;
359 db=eval_data(p->content.defb->op,p->content.defb->bitsize,sec,sec->pc);
360 if(pic_check)
361 do_pic_check(db->relocs);
362 cur_listing=0;
363 /*FIXME: sauber freigeben */
364 myfree(p->content.defb);
365 p->content.db=db;
366 p->type=DATA;
367 }
368 else if(p->type==ROFFS){
369 sblock *sb;
370 taddr space;
371 if(eval_expr(p->content.roffs,&space,sec,sec->pc)){
372 space=sec->org+space-sec->pc;
373 if (space>=0){
374 sb=new_sblock(number_expr(space),1,0);
375 p->content.sb=sb;
376 p->type=SPACE;
377 }
378 else
379 general_error(20); /* rorg is lower than current pc */
380 }
381 else
382 general_error(30); /* expression must be constant */
383 }
384 #if HAVE_CPU_OPTS
385 else if(p->type==OPTS)
386 cpu_opts(p->content.opts);
387 #endif
388 else if(p->type==PRINTTEXT&&!depend)
389 printf("%s",p->content.ptext);
390 else if(p->type==PRINTEXPR&&!depend)
391 atom_printexpr(p->content.pexpr,sec,sec->pc);
392 else if(p->type==ASSERT){
393 assertion *ast=p->content.assert;
394 taddr val;
395 if(ast->assert_exp!=NULL) {
396 eval_expr(ast->assert_exp,&val,sec,sec->pc);
397 if(val==0)
398 general_error(47,ast->expstr,ast->msgstr?ast->msgstr:emptystr);
399 }
400 else /* ASSERT without expression, used for user-FAIL directives */
401 general_error(19,ast->msgstr?ast->msgstr:emptystr);
402 }
403 else if(p->type==NLIST)
404 new_stabdef(p->content.nlist,sec);
405 if(p->type==DATA&&bss){
406 if(lasterrsrc!=p->src||lasterrline!=p->line){
407 if(sec->flags&UNALLOCATED){
408 if(warn_unalloc_ini_dat)
409 general_error(54); /* initialized data in offset section */
410 }
411 else
412 general_error(31); /* initialized data in bss */
413 lasterrsrc=p->src;
414 lasterrline=p->line;
415 }
416 }
417 oldpc=sec->pc;
418 sec->pc+=atom_size(p,sec,sec->pc);
419 if((utaddr)sec->pc!=oldpc){
420 if((utaddr)(sec->pc-1)<oldpc||ovflw)
421 general_error(45); /* address space overflow */
422 ovflw=sec->pc==0;
423 }
424 sec->flags&=~RESOLVE_WARN;
425 }
426 /* leave RORG-mode, when section ends */
427 if(rorg){
428 sec->pc=org_pc+(sec->pc-rorg_pc);
429 rorg_pc=0;
430 sec->flags&=~ABSOLUTE;
431 rorg=0;
432 }
433 }
434 remove_unalloc_sects();
435 }
436
undef_syms(void)437 static void undef_syms(void)
438 {
439 symbol *sym;
440
441 for(sym=first_symbol;sym;sym=sym->next){
442 if (!auto_import&&sym->type==IMPORT&&!(sym->flags&(EXPORT|COMMON|WEAK)))
443 general_error(22,sym->name);
444 else if (sym->type==IMPORT&&!(sym->flags&REFERENCED))
445 general_error(61,sym->name);
446 }
447 }
448
fix_labels(void)449 static void fix_labels(void)
450 {
451 symbol *sym,*base;
452 taddr val;
453
454 for(sym=first_symbol;sym;sym=sym->next){
455 /* turn all absolute mode labels into absolute symbols */
456 if((sym->flags&ABSLABEL)&&sym->type==LABSYM){
457 sym->type=EXPRESSION;
458 sym->flags&=~(TYPE_MASK|COMMON);
459 sym->sec=NULL;
460 sym->size=NULL;
461 sym->align=0;
462 sym->expr=number_expr(sym->pc);
463 }
464 /* expressions which are based on a label are turned into a new label */
465 else if(sym->type==EXPRESSION){
466 if(!eval_expr(sym->expr,&val,NULL,0)){
467 if(find_base(sym->expr,&base,NULL,0)==BASE_OK){
468 /* turn into an offseted label symbol from the base's section */
469 sym->type=base->type;
470 sym->sec=base->sec;
471 sym->pc=val;
472 sym->align=1;
473 }else
474 general_error(53,sym->name); /* non-relocatable expr. in equate */
475 }
476 }
477 }
478 }
479
statistics(void)480 static void statistics(void)
481 {
482 section *sec;
483 unsigned long long size;
484
485 printf("\n");
486 for(sec=first_section;sec;sec=sec->next){
487 size=ULLTADDR(ULLTADDR(sec->pc)-ULLTADDR(sec->org));
488 printf("%s(%s%lu):\t%12llu byte%c\n",sec->name,sec->attr,
489 (unsigned long)sec->align,size,size==1?' ':'s');
490 }
491 }
492
init_output(char * fmt)493 static int init_output(char *fmt)
494 {
495 if(!strcmp(fmt,"test"))
496 return init_output_test(&output_copyright,&write_object,&output_args);
497 if(!strcmp(fmt,"elf"))
498 return init_output_elf(&output_copyright,&write_object,&output_args);
499 if(!strcmp(fmt,"bin"))
500 return init_output_bin(&output_copyright,&write_object,&output_args);
501 if(!strcmp(fmt,"srec"))
502 return init_output_srec(&output_copyright,&write_object,&output_args);
503 if(!strcmp(fmt,"vobj"))
504 return init_output_vobj(&output_copyright,&write_object,&output_args);
505 if(!strcmp(fmt,"hunk"))
506 return init_output_hunk(&output_copyright,&write_object,&output_args);
507 if(!strcmp(fmt,"aout"))
508 return init_output_aout(&output_copyright,&write_object,&output_args);
509 if(!strcmp(fmt,"hunkexe")){
510 exec_out=1; /* executable format */
511 return init_output_hunk(&output_copyright,&write_object,&output_args);
512 }
513 if(!strcmp(fmt,"tos")){
514 exec_out=1; /* executable format */
515 return init_output_tos(&output_copyright,&write_object,&output_args);
516 }
517 return 0;
518 }
519
init_main(void)520 static int init_main(void)
521 {
522 size_t i;
523 char *last;
524 hashdata data;
525 mnemohash=new_hashtable(MNEMOHTABSIZE);
526 i=0;
527 while(i<mnemonic_cnt){
528 data.idx=i;
529 last=mnemonics[i].name;
530 add_hashentry(mnemohash,mnemonics[i].name,data);
531 do{
532 i++;
533 }while(i<mnemonic_cnt&&!strcmp(last,mnemonics[i].name));
534 }
535 if(debug){
536 if(mnemohash->collisions)
537 printf("*** %d mnemonic collisions!!\n",mnemohash->collisions);
538 }
539 new_include_path(".");
540 taddrmask=MAKEMASK(bytespertaddr<<3);
541 inst_alignment=INST_ALIGN;
542 return 1;
543 }
544
set_default_output_format(char * fmt)545 void set_default_output_format(char *fmt)
546 {
547 output_format=fmt;
548 }
549
set_input_name(void)550 static void set_input_name(void)
551 {
552 if(inname){
553 char *p,c;
554 if((p=strrchr(inname,'/'))!=NULL||
555 (p=strrchr(inname,'\\'))!=NULL||
556 (p=strrchr(inname,':'))!=NULL){
557 /* source text not in current dir., add an include path for it */
558 p++;
559 c=*p;
560 *p='\0';
561 new_include_path(inname);
562 *p=c;
563 }
564 setfilename(inname);
565 setdebugname(inname);
566 include_source(inname);
567 }else
568 general_error(15);
569 }
570
write_depends(FILE * f)571 static void write_depends(FILE *f)
572 {
573 struct deplist *d = first_depend;
574
575 if (depend==DEPEND_MAKE && d!=NULL && outname!=NULL)
576 fprintf(f,"%s:",outname);
577
578 while (d != NULL) {
579 switch (depend) {
580 case DEPEND_LIST:
581 fprintf(f,"%s\n",d->filename);
582 break;
583 case DEPEND_MAKE:
584 if (str_is_graph(d->filename))
585 fprintf(f," %s",d->filename);
586 else
587 fprintf(f," \"%s\"",d->filename);
588 break;
589 default:
590 ierror(0);
591 }
592 d = d->next;
593 }
594
595 if (depend == DEPEND_MAKE)
596 fputc('\n',f);
597 }
598
main(int argc,char ** argv)599 int main(int argc,char **argv)
600 {
601 int i;
602 for(i=1;i<argc;i++){
603 if(argv[i][0]=='-'&&argv[i][1]=='F'){
604 output_format=argv[i]+2;
605 argv[i][0]=0;
606 }
607 if(!strcmp("-quiet",argv[i])){
608 verbose=0;
609 argv[i][0]=0;
610 }
611 if(!strcmp("-debug",argv[i])){
612 debug=1;
613 argv[i][0]=0;
614 }
615 }
616 if(!init_output(output_format))
617 general_error(16,output_format);
618 if(!init_main())
619 general_error(10,"main");
620 if(!init_symbol())
621 general_error(10,"symbol");
622 if(verbose)
623 printf("%s\n%s\n%s\n%s\n",copyright,cpu_copyright,syntax_copyright,output_copyright);
624 for(i=1;i<argc;i++){
625 if(argv[i][0]==0)
626 continue;
627 if(argv[i][0]!='-'){
628 if(inname)
629 general_error(11);
630 inname=argv[i];
631 continue;
632 }
633 if(!strcmp("-o",argv[i])&&i<argc-1){
634 if(outname)
635 general_error(28,'o');
636 outname=argv[++i];
637 continue;
638 }
639 if(!strcmp("-L",argv[i])&&i<argc-1){
640 if(listname)
641 general_error(28,'L');
642 listname=argv[++i];
643 produce_listing=1;
644 set_listing(1);
645 continue;
646 }
647 if(!strcmp("-Lnf",argv[i])){
648 listformfeed=0;
649 continue;
650 }
651 if(!strcmp("-Lns",argv[i])){
652 listnosyms=1;
653 continue;
654 }
655 if(!strncmp("-Ll",argv[i],3)){
656 sscanf(argv[i]+3,"%i",&listlinesperpage);
657 continue;
658 }
659 if(!strncmp("-D",argv[i],2)){
660 char *def=NULL;
661 expr *val;
662 if(argv[i][2])
663 def=&argv[i][2];
664 else if (i<argc-1)
665 def=argv[++i];
666 if(def){
667 char *s=def;
668 if(ISIDSTART(*s)){
669 s++;
670 while(ISIDCHAR(*s))
671 s++;
672 def=cnvstr(def,s-def);
673 if(*s=='='){
674 s++;
675 val=parse_expr(&s);
676 }
677 else
678 val=number_expr(1);
679 if(*s)
680 general_error(23,'D'); /* trailing garbage after option */
681 new_abs(def,val);
682 myfree(def);
683 continue;
684 }
685 }
686 }
687 if(!strncmp("-I",argv[i],2)){
688 char *path=NULL;
689 if(argv[i][2])
690 path=&argv[i][2];
691 else if (i<argc-1)
692 path=argv[++i];
693 if(path){
694 new_include_path(path);
695 continue;
696 }
697 }
698 if(!strncmp("-depend=",argv[i],8) || !strncmp("-dependall=",argv[i],11)){
699 depend_all=argv[i][7]!='=';
700 if(!strcmp("list",&argv[i][depend_all?11:8])){
701 depend=DEPEND_LIST;
702 continue;
703 }
704 else if(!strcmp("make",&argv[i][depend_all?11:8])){
705 depend=DEPEND_MAKE;
706 continue;
707 }
708 }
709 if(!strcmp("-unnamed-sections",argv[i])){
710 unnamed_sections=1;
711
712 continue;
713 }
714 if(!strcmp("-ignore-mult-inc",argv[i])){
715 ignore_multinc=1;
716 continue;
717 }
718 if(!strcmp("-nocase",argv[i])){
719 nocase=1;
720 continue;
721 }
722 if(!strcmp("-nosym",argv[i])){
723 no_symbols=1;
724 continue;
725 }
726 if(!strncmp("-nowarn=",argv[i],8)){
727 int wno;
728 sscanf(argv[i]+8,"%i",&wno);
729 disable_warning(wno);
730 continue;
731 }
732 else if(!strcmp("-w",argv[i])){
733 no_warn=1;
734 continue;
735 }
736 if(!strncmp("-maxerrors=",argv[i],11)){
737 sscanf(argv[i]+11,"%i",&max_errors);
738 continue;
739 }
740 else if(!strcmp("-pic",argv[i])){
741 pic_check=1;
742 continue;
743 }
744 else if(!strncmp("-maxmacrecurs=",argv[i],14)) {
745 sscanf(argv[i]+14,"%i",&maxmacrecurs);
746 continue;
747 }
748 else if(!strcmp("-unsshift",argv[i])){
749 unsigned_shift=1;
750 continue;
751 }
752 else if(!strcmp("-chklabels",argv[i])){
753 chklabels=1;
754 continue;
755 }
756 else if(!strcmp("-noialign",argv[i])) {
757 inst_alignment=1;
758 continue;
759 }
760 if(cpu_args(argv[i]))
761 continue;
762 if(syntax_args(argv[i]))
763 continue;
764 if(output_args(argv[i]))
765 continue;
766 if(!strcmp("-esc",argv[i])){
767 esc_sequences=1;
768 continue;
769 }
770 if(!strcmp("-noesc",argv[i])){
771 esc_sequences=0;
772 continue;
773 }
774 if (!strncmp("-x",argv[i],2)){
775 auto_import=0;
776 continue;
777 }
778 general_error(14,argv[i]);
779 }
780 set_input_name();
781 internal_abs(vasmsym_name);
782 if(!init_parse())
783 general_error(10,"parse");
784 if(!init_syntax())
785 general_error(10,"syntax");
786 if(!init_cpu())
787 general_error(10,"cpu");
788 parse();
789 if(errors==0||produce_listing)
790 resolve();
791 if(errors==0||produce_listing)
792 assemble();
793 cur_src=NULL;
794 if(errors==0)
795 undef_syms();
796 fix_labels();
797 if(produce_listing){
798 if(!listname)
799 listname="a.lst";
800 write_listing(listname);
801 }
802 if(errors==0){
803 if(!depend){
804 if(verbose)
805 statistics();
806 if(!outname)
807 outname="a.out";
808 outfile=fopen(outname,"wb");
809 if(!outfile)
810 general_error(13,outname);
811 else
812 write_object(outfile,first_section,first_symbol);
813 }else
814 write_depends(stdout);
815 }
816 leave();
817 return 0; /* not reached */
818 }
819
add_depend(char * name)820 static void add_depend(char *name)
821 {
822 if (depend) {
823 struct deplist *d = first_depend;
824
825 /* check if an entry with the same file name already exists */
826 while (d != NULL) {
827 if (!strcmp(d->filename,name))
828 return;
829 d = d->next;
830 }
831
832 /* append new dependency record */
833 d = mymalloc(sizeof(struct deplist));
834 d->next = NULL;
835 if (name[0]=='.'&&(name[1]=='/'||name[1]=='\\'))
836 name += 2; /* skip "./" in paths */
837 d->filename = mystrdup(name);
838 if (last_depend)
839 last_depend = last_depend->next = d;
840 else
841 first_depend = last_depend = d;
842 }
843 }
844
locate_file(char * filename,char * mode)845 FILE *locate_file(char *filename,char *mode)
846 {
847 char pathbuf[MAXPATHLEN];
848 struct include_path *ipath;
849 FILE *f;
850
851 if (*filename=='.' || abs_path(filename)) {
852 /* file name is absolute, then don't use any include paths */
853 /* @@@ FIXME: '.' is currently stripped by convert_path() */
854 if (f = fopen(filename,mode)) {
855 if (depend_all)
856 add_depend(pathbuf);
857 return f;
858 }
859 }
860 else {
861 /* locate file name in all known include paths */
862 for (ipath=first_incpath; ipath; ipath=ipath->next) {
863 if (strlen(ipath->path) + strlen(filename) + 1 <= MAXPATHLEN) {
864 strcpy(pathbuf,ipath->path);
865 strcat(pathbuf,filename);
866 if (f = fopen(pathbuf,mode)) {
867 if (depend_all || !abs_path(pathbuf))
868 add_depend(pathbuf);
869 return f;
870 }
871 }
872 }
873 }
874 general_error(12,filename);
875 return NULL;
876 }
877
include_source(char * inname)878 void include_source(char *inname)
879 {
880 char *filename;
881 struct include_path **nptr = &first_source;
882 struct include_path *name;
883 FILE *f;
884
885 filename = convert_path(inname);
886
887 /* check whether this source was already included */
888 while (name = *nptr) {
889 #if defined(AMIGA) || defined(MSDOS) || defined(ATARI) || defined(_WIN32)
890 if (!stricmp(name->path,filename)) {
891 #else
892 if (!strcmp(name->path,filename)) {
893 #endif
894 myfree(filename);
895 if (!ignore_multinc) {
896 filename = name->path;
897 /* reuse already read file from cache? */
898 }
899 nptr = NULL; /* ignore including this source */
900 break;
901 }
902 nptr = &name->next;
903 }
904 if (nptr) {
905 name = mymalloc(sizeof(struct include_path));
906 name->next = NULL;
907 name->path = filename;
908 *nptr = name;
909 }
910 else if (ignore_multinc)
911 return; /* ignore multiple inclusion of this source completely */
912
913 if (f = locate_file(filename,"r")) {
914 char *text;
915 size_t size;
916
917 for (text=NULL,size=0; ; size+=SRCREADINC) {
918 size_t nchar;
919 text = myrealloc(text,size+SRCREADINC);
920 nchar = fread(text+size,1,SRCREADINC,f);
921 if (nchar < SRCREADINC) {
922 size += nchar;
923 break;
924 }
925 }
926 if (feof(f)) {
927 if (size > 0) {
928 cur_src = new_source(filename,myrealloc(text,size+2),size+1);
929 *(cur_src->text+size) = '\n';
930 *(cur_src->text+size+1) = '\0';
931 }
932 else {
933 myfree(text);
934 cur_src = new_source(filename,"\n",1);
935 }
936 }
937 else
938 general_error(29,filename);
939 fclose(f);
940 }
941 }
942
943 /* searches a section by name and attr (if secname_attr set) */
944 section *find_section(char *name,char *attr)
945 {
946 section *p;
947 if(secname_attr){
948 for(p=first_section;p;p=p->next){
949 if(!strcmp(name,p->name) && !strcmp(attr,p->attr))
950 return p;
951 }
952 }
953 else{
954 for(p=first_section;p;p=p->next){
955 if(!strcmp(name,p->name))
956 return p;
957 }
958 }
959 return 0;
960 }
961
962 /* create a new source text instance, which has cur_src as parent */
963 source *new_source(char *filename,char *text,size_t size)
964 {
965 static unsigned long id = 0;
966 source *s = mymalloc(sizeof(source));
967 char *p;
968 size_t i;
969
970 /* scan source for strange characters */
971 for (p=text,i=0; i<size; i++,p++) {
972 if (*p == 0x1a) {
973 /* EOF character - replace by newline and ignore rest of source */
974 *p = '\n';
975 size = i + 1;
976 break;
977 }
978 }
979
980 s->parent = cur_src;
981 s->parent_line = cur_src ? cur_src->line : 0;
982 s->name = mystrdup(filename);
983 s->text = text;
984 s->size = size;
985 s->macro = NULL;
986 s->repeat = 1; /* read just once */
987 s->irpname = NULL;
988 s->cond_level = clev; /* remember level of conditional nesting */
989 s->num_params = -1; /* not a macro, no parameters */
990 s->param[0] = emptystr;
991 s->param_len[0] = 0;
992 s->id = id++; /* every source has unique id - important for macros */
993 s->srcptr = text;
994 s->line = 0;
995 s->bufsize = INITLINELEN;
996 s->linebuf = mymalloc(INITLINELEN);
997 #ifdef CARGSYM
998 s->cargexp = NULL;
999 #endif
1000 #ifdef REPTNSYM
1001 /* -1 outside of a repetition block */
1002 s->reptn = cur_src ? cur_src->reptn : -1;
1003 #endif
1004 return s;
1005 }
1006
1007 /* quit parsing the current source instance, leave macros, repeat loops
1008 and restore the conditional assembly level */
1009 void end_source(source *s)
1010 {
1011 if(s){
1012 s->srcptr=s->text+s->size;
1013 s->repeat=1;
1014 clev=s->cond_level;
1015 }
1016 }
1017
1018 /* set current section, remember last */
1019 void set_section(section *s)
1020 {
1021 #if NOT_NEEDED
1022 if (current_section!=NULL && !(current_section->flags & UNALLOCATED)) {
1023 if (current_section->flags & ABSOLUTE)
1024 prev_org = current_section;
1025 else
1026 prev_sec = current_section;
1027 }
1028 #endif
1029 #if HAVE_CPU_OPTS
1030 if (!(s->flags & UNALLOCATED))
1031 cpu_opts_init(s); /* set initial cpu opts before the first atom */
1032 #endif
1033 current_section = s;
1034 }
1035
1036 /* creates a new section with given attributes and alignment;
1037 does not switch to this section automatically */
1038 section *new_section(char *name,char *attr,int align)
1039 {
1040 section *p;
1041 if(unnamed_sections)
1042 name=emptystr;
1043 if(p=find_section(name,attr))
1044 return p;
1045 p=mymalloc(sizeof(*p));
1046 p->next=0;
1047 p->name=mystrdup(name);
1048 p->attr=mystrdup(attr);
1049 p->first=p->last=0;
1050 p->align=align;
1051 p->org=p->pc=0;
1052 p->flags=0;
1053 p->memattr=0;
1054 memset(p->pad,0,MAXPADBYTES);
1055 p->padbytes=1;
1056 if(last_section)
1057 last_section=last_section->next=p;
1058 else
1059 first_section=last_section=p;
1060 return p;
1061 }
1062
1063 /* create a dummy code section for each new ORG directive */
1064 section *new_org(taddr org)
1065 {
1066 char buf[16];
1067 section *sec;
1068
1069 sprintf(buf,"seg%llx",ULLTADDR(org));
1070 sec = new_section(buf,"acrwx",1);
1071 sec->org = sec->pc = org;
1072 sec->flags |= ABSOLUTE; /* absolute destination address */
1073 return sec;
1074 }
1075
1076 /* switches current section to the section with the specified name */
1077 void switch_section(char *name,char *attr)
1078 {
1079 section *p;
1080 if(unnamed_sections)
1081 name=emptystr;
1082 p=find_section(name,attr);
1083 if(!p)
1084 general_error(2,name);
1085 else
1086 set_section(p);
1087 }
1088
1089 /* Switches current section to an offset section. Create a new section when
1090 it doesn't exist yet or needs a different offset. */
1091 void switch_offset_section(char *name,taddr offs)
1092 {
1093 static unsigned long id;
1094 char unique_name[14];
1095 section *sec;
1096
1097 if (!name) {
1098 if (offs != -1)
1099 ++id;
1100 sprintf(unique_name,"OFFSET%06lu",id);
1101 name = unique_name;
1102 }
1103 sec = new_section(name,"u",1);
1104 sec->flags |= UNALLOCATED;
1105 if (offs != -1)
1106 sec->org = sec->pc = offs;
1107 set_section(sec);
1108 }
1109
1110 /* returns current_section or the syntax module's default section,
1111 when undefined */
1112 section *default_section(void)
1113 {
1114 section *sec = current_section;
1115
1116 if (!sec && defsectname && defsecttype) {
1117 sec = new_section(defsectname,defsecttype,1);
1118 switch_section(defsectname,defsecttype);
1119 }
1120 return sec;
1121 }
1122
1123 #if NOT_NEEDED
1124 /* restore last relocatable section */
1125 section *restore_section(void)
1126 {
1127 if (prev_sec)
1128 return prev_sec;
1129 if (defsectname && defsecttype)
1130 return new_section(defsectname,defsecttype,1);
1131 return NULL; /* no previous section or default section defined */
1132 }
1133
1134 /* restore last absolute section */
1135 section *restore_org(void)
1136 {
1137 if (prev_org)
1138 return prev_org;
1139 return new_org(0); /* no previous org: default to ORG 0 */
1140 }
1141 #endif /* NOT_NEEDED */
1142
1143 /* end a relocated ORG block */
1144 int end_rorg(void)
1145 {
1146 section *s = default_section();
1147
1148 if (s == NULL) {
1149 general_error(3);
1150 return 0;
1151 }
1152 if (s->flags & IN_RORG) {
1153 add_atom(s,new_rorgend_atom());
1154 if (s->flags & PREVABS)
1155 s->flags |= ABSOLUTE;
1156 else
1157 s->flags &= ~ABSOLUTE;
1158 s->flags &= ~IN_RORG;
1159 return 1;
1160 }
1161 general_error(44); /* no Rorg block to end */
1162 return 0;
1163 }
1164
1165 /* end a relocated ORG block when currently active */
1166 void try_end_rorg(void)
1167 {
1168 if (current_section!=NULL && (current_section->flags&IN_RORG))
1169 end_rorg();
1170 }
1171
1172 /* start a relocated ORG block */
1173 void start_rorg(taddr rorg)
1174 {
1175 section *s = default_section();
1176
1177 if (s == NULL) {
1178 general_error(3);
1179 return;
1180 }
1181 if (s->flags & IN_RORG)
1182 end_rorg(); /* we are already in a ROrg-block, so close it first */
1183 add_atom(s,new_rorg_atom(rorg));
1184 s->flags |= IN_RORG;
1185 if (!(s->flags & ABSOLUTE)) {
1186 s->flags &= ~PREVABS;
1187 s->flags |= ABSOLUTE; /* make section absolute during the ROrg-block */
1188 }
1189 else
1190 s->flags |= PREVABS;
1191 }
1192
1193 void print_section(FILE *f,section *sec)
1194 {
1195 atom *p;
1196 taddr pc=sec->org;
1197 fprintf(f,"section %s (attr=<%s> align=%llu):\n",
1198 sec->name,sec->attr,ULLTADDR(sec->align));
1199 for(p=sec->first;p;p=p->next){
1200 pc=pcalign(p,pc);
1201 fprintf(f,"%8llx: ",ULLTADDR(pc));
1202 print_atom(f,p);
1203 fprintf(f,"\n");
1204 pc+=atom_size(p,sec,pc);
1205 }
1206 }
1207
1208 void new_include_path(char *pathname)
1209 {
1210 struct include_path *new = mymalloc(sizeof(struct include_path));
1211 struct include_path *ipath;
1212 char *newpath = convert_path(pathname);
1213 int len = strlen(newpath);
1214
1215 #if defined(AMIGA)
1216 if (len>0 && newpath[len-1]!='/' && newpath[len-1]!=':') {
1217 pathname = mymalloc(len+2);
1218 strcpy(pathname,newpath);
1219 pathname[len] = '/';
1220 pathname[len+1] = '\0';
1221 }
1222 #elif defined(MSDOS) || defined(ATARI) || defined(_WIN32)
1223 if (len>0 && newpath[len-1]!='\\' && newpath[len-1]!=':') {
1224 pathname = mymalloc(len+2);
1225 strcpy(pathname,newpath);
1226 pathname[len] = '\\';
1227 pathname[len+1] = '\0';
1228 }
1229 #else
1230 if (len>0 && newpath[len-1] != '/') {
1231 pathname = mymalloc(len+2);
1232 strcpy(pathname,newpath);
1233 pathname[len] = '/';
1234 pathname[len+1] = '\0';
1235 }
1236 #endif
1237 else
1238 pathname = mystrdup(newpath);
1239 myfree(newpath);
1240 new->next = NULL;
1241 new->path = pathname;
1242
1243 if (ipath = first_incpath) {
1244 while (ipath->next)
1245 ipath = ipath->next;
1246 ipath->next = new;
1247 }
1248 else
1249 first_incpath = new;
1250 }
1251
1252 void set_listing(int on)
1253 {
1254 listena = on && produce_listing;
1255 }
1256
1257 void set_list_title(char *p,int len)
1258 {
1259 listtitlecnt++;
1260 listtitles=myrealloc(listtitles,listtitlecnt*sizeof(*listtitles));
1261 listtitles[listtitlecnt-1]=mymalloc(len+1);
1262 strncpy(listtitles[listtitlecnt-1],p,len);
1263 listtitles[listtitlecnt-1][len]=0;
1264 listtitlelines=myrealloc(listtitlelines,listtitlecnt*sizeof(*listtitlelines));
1265 listtitlelines[listtitlecnt-1]=cur_src->line;
1266 }
1267
1268 static void print_list_header(FILE *f,int cnt)
1269 {
1270 if(cnt%listlinesperpage==0){
1271 if(cnt!=0&&listformfeed)
1272 fprintf(f,"\f");
1273 if(listtitlecnt>0){
1274 int i,t;
1275 for(i=0,t=-1;i<listtitlecnt;i++){
1276 if(listtitlelines[i]<=cnt+listlinesperpage)
1277 t=i;
1278 }
1279 if(t>=0){
1280 int sp=(120-strlen(listtitles[t]))/2;
1281 while(--sp)
1282 fprintf(f," ");
1283 fprintf(f,"%s\n",listtitles[t]);
1284 }
1285 cnt++;
1286 }
1287 fprintf(f,"Err Line Loc. S Object1 Object2 M Source\n");
1288 }
1289 }
1290
1291 #if VASM_CPU_OIL
1292 void write_listing(char *listname)
1293 {
1294 FILE *f;
1295 int nsecs,i,cnt=0,nl;
1296 section *secp;
1297 listing *p;
1298 atom *a;
1299 symbol *sym;
1300 taddr pc;
1301 char rel;
1302
1303 if(!(f=fopen(listname,"w"))){
1304 general_error(13,listname);
1305 return;
1306 }
1307 for(nsecs=0,secp=first_section;secp;secp=secp->next)
1308 secp->idx=nsecs++;
1309 for(p=first_listing;p;p=p->next){
1310 if(!p->src||p->src->id!=0)
1311 continue;
1312 print_list_header(f,cnt++);
1313 if(p->error!=0)
1314 fprintf(f,"%04d ",p->error);
1315 else
1316 fprintf(f," ");
1317 fprintf(f,"%4d ",p->line);
1318 a=p->atom;
1319 while(a&&a->type!=DATA&&a->next&&a->next->line==a->line&&a->next->src==a->src)
1320 a=a->next;
1321 if(a&&a->type==DATA){
1322 int size=a->content.db->size;
1323 char *dp=a->content.db->data;
1324 pc=p->pc;
1325 fprintf(f,"%05lX %d ",(unsigned long)pc,(int)(p->sec?p->sec->idx:0));
1326 for(i=0;i<8;i++){
1327 if(i==4)
1328 fprintf(f," ");
1329 if(i<size){
1330 fprintf(f,"%02X",(unsigned char)*dp++);
1331 pc++;
1332 }else
1333 fprintf(f," ");
1334 /* append following atoms with align 1 directly */
1335 if(i==size-1&&i<7&&a->next&&a->next->align<=a->align&&a->next->type==DATA&&a->next->line==a->line&&a->next->src==a->src){
1336 a=a->next;
1337 size+=a->content.db->size;
1338 dp=a->content.db->data;
1339 }
1340 }
1341 fprintf(f," ");
1342 if(a->content.db->relocs){
1343 symbol *s=((nreloc *)(a->content.db->relocs->reloc))->sym;
1344 if(s->type==IMPORT)
1345 rel='X';
1346 else
1347 rel='0'+p->sec->idx;
1348 }else
1349 rel='A';
1350 fprintf(f,"%c ",rel);
1351 }else
1352 fprintf(f," ");
1353
1354 fprintf(f," %-.77s",p->txt);
1355
1356 /* bei laengeren Daten den Rest ueberspringen */
1357 /* Block entfernen, wenn alles ausgegeben werden soll */
1358 if(a&&a->type==DATA&&i<a->content.db->size){
1359 pc+=a->content.db->size-i;
1360 i=a->content.db->size;
1361 }
1362
1363 /* restliche DATA-Zeilen, wenn noetig */
1364 while(a){
1365 if(a->type==DATA){
1366 int size=a->content.db->size;
1367 char *dp=a->content.db->data+i;
1368
1369 if(i<size){
1370 for(;i<size;i++){
1371 if((i&7)==0){
1372 fprintf(f,"\n");
1373 print_list_header(f,cnt++);
1374 fprintf(f," %05lX %d ",(unsigned long)pc,(int)(p->sec?p->sec->idx:0));
1375 }else if((i&3)==0)
1376 fprintf(f," ");
1377 fprintf(f,"%02X",(unsigned char)*dp++);
1378 pc++;
1379 /* append following atoms with align 1 directly */
1380 if(i==size-1&&a->next&&a->next->align<=a->align&&a->next->type==DATA&&a->next->line==a->line&&a->next->src==a->src){
1381 a=a->next;
1382 size+=a->content.db->size;
1383 dp=a->content.db->data;
1384 }
1385 }
1386 i=8-(i&7);
1387 if(i>=4)
1388 fprintf(f," ");
1389 while(i--){
1390 fprintf(f," ");
1391 }
1392 fprintf(f," %c",rel);
1393 }
1394 i=0;
1395 }
1396 if(a->next&&a->next->line==a->line&&a->next->src==a->src){
1397 a=a->next;
1398 pc=pcalign(a,pc);
1399 if(a->type==DATA&&a->content.db->relocs){
1400 symbol *s=((nreloc *)(a->content.db->relocs->reloc))->sym;
1401 if(s->type==IMPORT)
1402 rel='X';
1403 else
1404 rel='0'+p->sec->idx;
1405 }else
1406 rel='A';
1407 }else
1408 a=0;
1409 }
1410 fprintf(f,"\n");
1411 }
1412 fprintf(f,"\n\nSections:\n");
1413 for(secp=first_section;secp;secp=secp->next)
1414 fprintf(f,"%d %s\n",(int)secp->idx,secp->name);
1415 if(!listnosyms){
1416 fprintf(f,"\n\nSymbols:\n");
1417 {
1418 symbol *last=0,*cur,*symo;
1419 for(symo=first_symbol;symo;symo=symo->next){
1420 cur=0;
1421 for(sym=first_symbol;sym;sym=sym->next){
1422 if(!last||stricmp(sym->name,last->name)>0)
1423 if(!cur||stricmp(sym->name,cur->name)<0)
1424 cur=sym;
1425 }
1426 if(cur){
1427 print_symbol(f,cur);
1428 fprintf(f,"\n");
1429 last=cur;
1430 }
1431 }
1432 }
1433 }
1434 if(errors==0)
1435 fprintf(f,"\nThere have been no errors.\n");
1436 else
1437 fprintf(f,"\nThere have been %d errors!\n",errors);
1438 fclose(f);
1439 for(p=first_listing;p;){
1440 listing *m=p->next;
1441 myfree(p);
1442 p=m;
1443 }
1444 }
1445 #else
1446 void write_listing(char *listname)
1447 {
1448 FILE *f;
1449 int nsecs,i,maxsrc=0;
1450 section *secp;
1451 listing *p;
1452 atom *a;
1453 symbol *sym;
1454 taddr pc;
1455
1456 if(!(f=fopen(listname,"w"))){
1457 general_error(13,listname);
1458 return;
1459 }
1460 for(nsecs=1,secp=first_section;secp;secp=secp->next)
1461 secp->idx=nsecs++;
1462 for(p=first_listing;p;p=p->next){
1463 char err[6];
1464 if(p->error!=0)
1465 sprintf(err,"E%04d",p->error);
1466 else
1467 sprintf(err," ");
1468 if(p->src&&p->src->id>maxsrc)
1469 maxsrc=p->src->id;
1470 fprintf(f,"F%02d:%04d %s %s",(int)(p->src?p->src->id:0),p->line,err,p->txt);
1471 a=p->atom;
1472 pc=p->pc;
1473 while(a){
1474 if(a->type==DATA){
1475 int size=a->content.db->size;
1476 for(i=0;i<size&&i<32;i++){
1477 if((i&15)==0)
1478 fprintf(f,"\n S%02d:%08lX: ",(int)(p->sec?p->sec->idx:0),(unsigned long)(pc));
1479 fprintf(f," %02X",(unsigned char)a->content.db->data[i]);
1480 pc++;
1481 }
1482 if(a->content.db->relocs)
1483 fprintf(f," [R]");
1484 }
1485 if(a->next&&a->next->line==a->line&&a->next->src==a->src){
1486 a=a->next;
1487 pc=pcalign(a,pc);
1488 }else
1489 a=0;
1490 }
1491 fprintf(f,"\n");
1492 }
1493 fprintf(f,"\n\nSections:\n");
1494 for(secp=first_section;secp;secp=secp->next)
1495 fprintf(f,"S%02d %s\n",(int)secp->idx,secp->name);
1496 fprintf(f,"\n\nSources:\n");
1497 for(i=0;i<=maxsrc;i++){
1498 for(p=first_listing;p;p=p->next){
1499 if(p->src&&p->src->id==i){
1500 fprintf(f,"F%02d %s\n",i,p->src->name);
1501 break;
1502 }
1503 }
1504 }
1505 fprintf(f,"\n\nSymbols:\n");
1506 for(sym=first_symbol;sym;sym=sym->next){
1507 print_symbol(f,sym);
1508 fprintf(f,"\n");
1509 }
1510 if(errors==0)
1511 fprintf(f,"\nThere have been no errors.\n");
1512 else
1513 fprintf(f,"\nThere have been %d errors!\n",errors);
1514 fclose(f);
1515 for(p=first_listing;p;){
1516 listing *m=p->next;
1517 myfree(p);
1518 p=m;
1519 }
1520 }
1521 #endif
1522