1 #include <stdio.h>
2 #include <strings.h>
3 #include <string.h>
4 #include <ctype.h>
5 #include "defs.h"
6 #include "externs.h"
7 #include "protos.h"
8
9 /* pseudo instructions section flag */
10 char pseudo_flag[] = {
11 0x0C, 0x0C, 0x0F, 0x0F, 0x0F, 0x0C, 0x0C, 0x0C, 0x0F, 0x0C,
12 0x0C, 0x0C, 0x0C, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
13 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0C,
14 0x0F, 0x0F, 0x0F, 0x0C, 0x0C, 0x0C, 0x0C, 0x0F, 0x0F, 0x0F,
15 0x0F, 0x0F, 0x0C, 0x0C, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x04
16 };
17
18
19 /* ----
20 * do_pseudo()
21 * ----
22 * pseudo instruction processor
23 */
24
25 void
do_pseudo(int * ip)26 do_pseudo(int *ip)
27 {
28 char str[80];
29 int old_bank;
30 int size;
31
32 /* check if the directive is allowed in the current section */
33 if (!(pseudo_flag[opval] & (1 << section)))
34 fatal_error("Directive not allowed in the current section!");
35
36 /* save current location */
37 old_bank = bank;
38
39 /* execute directive */
40 opproc(ip);
41
42 /* reset last label pointer */
43 switch (opval) {
44 case P_VRAM:
45 case P_PAL:
46 break;
47
48 case P_DB:
49 case P_DW:
50 if (lastlabl) {
51 if(lastlabl->data_type != P_DB)
52 lastlabl = NULL;
53 }
54 break;
55
56 default:
57 if (lastlabl) {
58 if(lastlabl->data_type != opval)
59 lastlabl = NULL;
60 }
61 break;
62 }
63
64 /* bank overflow warning */
65 if (pass == LAST_PASS) {
66 if (asm_opt[OPT_WARNING]) {
67 switch (opval) {
68 case P_INCBIN:
69 case P_INCCHR:
70 case P_INCSPR:
71 case P_INCPAL:
72 case P_INCBAT:
73 case P_INCTILE:
74 case P_INCMAP:
75 if (bank != old_bank) {
76 size = ((bank - old_bank - 1) * 8192) + loccnt;
77 if (size) {
78 sprintf(str, "Warning, bank overflow by %i bytes!\n", size);
79 warning(str);
80 }
81 }
82 break;
83 }
84 }
85 }
86 }
87
88
89 /* ----
90 * do_list()
91 * ----
92 * .list pseudo
93 */
94
95 void
do_list(int * ip)96 do_list(int *ip)
97 {
98 /* check end of line */
99 if (!check_eol(ip))
100 return;
101
102 asm_opt[OPT_LIST] = 1;
103 xlist = 1;
104 }
105
106
107 /* ----
108 * do_mlist()
109 * ----
110 * .mlist pseudo
111 */
112
113 void
do_mlist(int * ip)114 do_mlist(int *ip)
115 {
116 /* check end of line */
117 if (!check_eol(ip))
118 return;
119
120 asm_opt[OPT_MACRO] = 1;
121 }
122
123
124 /* ----
125 * do_nolist()
126 * ----
127 * .nolist pseudo
128 */
129
130 void
do_nolist(int * ip)131 do_nolist(int *ip)
132 {
133 /* check end of line */
134 if (!check_eol(ip))
135 return;
136
137 asm_opt[OPT_LIST] = 0;
138 }
139
140
141 /* ----
142 * do_nomlist()
143 * ----
144 * .nomlist pseudo
145 */
146
147 void
do_nomlist(int * ip)148 do_nomlist(int *ip)
149 {
150 /* check end of line */
151 if (!check_eol(ip))
152 return;
153
154 asm_opt[OPT_MACRO] = mlist_opt;
155 }
156
157
158 /* ----
159 * do_db()
160 * ----
161 * .db pseudo
162 */
163
164 void
do_db(int * ip)165 do_db(int *ip)
166 {
167 unsigned char c;
168
169 /* define label */
170 labldef(loccnt, 1);
171
172 /* output infos */
173 data_loccnt = loccnt;
174 data_level = 2;
175
176 /* skip spaces */
177 while (isspace(prlnbuf[++(*ip)]));
178
179 /* get bytes */
180 for (;;) {
181 /* ASCII string */
182 if (prlnbuf[*ip] == '\"') {
183 for (;;) {
184 c = prlnbuf[++(*ip)];
185 if (c == '\"')
186 break;
187 if (c == '\0') {
188 error("Unterminated ASCII string!");
189 return;
190 }
191 if (c == '\\') {
192 c = prlnbuf[++(*ip)];
193 switch(c) {
194 case 'r':
195 c = '\r';
196 break;
197 case 'n':
198 c = '\n';
199 break;
200 case 't':
201 c = '\t';
202 break;
203 }
204 }
205 /* store char on last pass */
206 if (pass == LAST_PASS)
207 putbyte(loccnt, c);
208
209 /* update location counter */
210 loccnt++;
211 }
212 (*ip)++;
213 }
214 /* bytes */
215 else {
216 /* get a byte */
217 if (!evaluate(ip, 0))
218 return;
219
220 /* update location counter */
221 loccnt++;
222
223 /* store byte on last pass */
224 if (pass == LAST_PASS) {
225 /* check for overflow */
226 if ((value > 0xFF) && (value < 0xFFFFFF80)) {
227 error("Overflow error!");
228 return;
229 }
230
231 /* store byte */
232 putbyte(loccnt - 1, value);
233 }
234 }
235
236 /* check if there's another byte */
237 c = prlnbuf[(*ip)++];
238
239 if (c != ',')
240 break;
241 }
242
243 /* check error */
244 if (c != ';' && c != '\0') {
245 error("Syntax error!");
246 return;
247 }
248
249 /* size */
250 if (lablptr) {
251 lablptr->data_type = P_DB;
252 lablptr->data_size = loccnt - data_loccnt;
253 }
254 else {
255 if (lastlabl) {
256 if (lastlabl->data_type == P_DB)
257 lastlabl->data_size += loccnt - data_loccnt;
258 }
259 }
260
261 /* output line */
262 if (pass == LAST_PASS)
263 println();
264 }
265
266
267 /* ----
268 * do_dw()
269 * ----
270 * .dw pseudo
271 */
272
273 void
do_dw(int * ip)274 do_dw(int *ip)
275 {
276 char c;
277
278 /* define label */
279 labldef(loccnt, 1);
280
281 /* output infos */
282 data_loccnt = loccnt;
283 data_size = 2;
284 data_level = 2;
285
286 /* get data */
287 for (;;) {
288 /* get a word */
289 if (!evaluate(ip, 0))
290 return;
291
292 /* update location counter */
293 loccnt += 2;
294
295 /* store word on last pass */
296 if (pass == LAST_PASS) {
297 /* check for overflow */
298 if ((value > 0xFFFF) && (value < 0xFFFF8000)) {
299 error("Overflow error!");
300 return;
301 }
302
303 /* store word */
304 putword(loccnt-2, value);
305 }
306
307 /* check if there's another word */
308 c = prlnbuf[(*ip)++];
309
310 if (c != ',')
311 break;
312 }
313
314 /* check error */
315 if (c != ';' && c != '\0') {
316 error("Syntax error!");
317 return;
318 }
319
320 /* size */
321 if (lablptr) {
322 lablptr->data_type = P_DB;
323 lablptr->data_size = loccnt - data_loccnt;
324 }
325 else {
326 if (lastlabl) {
327 if (lastlabl->data_type == P_DB)
328 lastlabl->data_size += loccnt - data_loccnt;
329 }
330 }
331
332 /* output line */
333 if (pass == LAST_PASS)
334 println();
335 }
336
337
338 /* ----
339 * do_equ()
340 * ----
341 * .equ pseudo
342 */
343
344 void
do_equ(int * ip)345 do_equ(int *ip)
346 {
347 /* get value */
348 if (!evaluate(ip, ';'))
349 return;
350
351 /* assign value to the label */
352 labldef(value, 0);
353
354 /* output line */
355 if (pass == LAST_PASS) {
356 loadlc(value, 1);
357 println();
358 }
359 }
360
361
362 /* ----
363 * do_page()
364 * ----
365 * .page pseudo
366 */
367
368 void
do_page(int * ip)369 do_page(int *ip)
370 {
371 /* not allowed in procs */
372 if (proc_ptr) {
373 fatal_error("PAGE can not be changed in procs!");
374 return;
375 }
376
377 /* define label */
378 labldef(loccnt, 1);
379
380 /* get page index */
381 if (!evaluate(ip, ';'))
382 return;
383 if (value > 7) {
384 error("Invalid page index!");
385 return;
386 }
387 page = value;
388
389 /* output line */
390 if (pass == LAST_PASS) {
391 loadlc(value << 13, 1);
392 println();
393 }
394 }
395
396
397 /* ----
398 * do_org()
399 * ----
400 * .org pseudo
401 */
402
403 void
do_org(int * ip)404 do_org(int *ip)
405 {
406 /* get the .org value */
407 if (!evaluate(ip, ';'))
408 return;
409
410 /* check for undefined symbol - they are not allowed in .org */
411 if (undef != 0) {
412 error("Undefined symbol in operand field!");
413 return;
414 }
415
416 /* section switch */
417 switch (section) {
418 case S_ZP:
419 /* zero page section */
420 if ((value & 0xFFFFFF00) && ((value & 0xFFFFFF00) != machine->ram_base)) {
421 error("Invalid address!");
422 return;
423 }
424 break;
425
426 case S_BSS:
427 /* ram section */
428 if ((value < machine->ram_base) || (value >= (machine->ram_base + machine->ram_limit))) {
429 error("Invalid address!");
430 return;
431 }
432 break;
433
434 case S_CODE:
435 case S_DATA:
436 /* not allowed in procs */
437 if (proc_ptr) {
438 fatal_error("ORG can not be changed in procs!");
439 return;
440 }
441
442 /* code and data section */
443 if (value & 0xFFFF0000) {
444 error("Invalid address!");
445 return;
446 }
447 page = (value >> 13) & 0x07;
448 break;
449 }
450
451 /* set location counter */
452 loccnt = (value & 0x1FFF);
453
454 /* set label value if there was one */
455 labldef(loccnt, 1);
456
457 /* output line on last pass */
458 if (pass == LAST_PASS) {
459 loadlc(value, 1);
460 println();
461 }
462 }
463
464
465 /* ----
466 * do_bank()
467 * ----
468 * .bank pseudo
469 */
470
471 void
do_bank(int * ip)472 do_bank(int *ip)
473 {
474 char name[128];
475
476 /* not allowed in procs */
477 if (proc_ptr) {
478 fatal_error("Bank can not be changed in procs!");
479 return;
480 }
481
482 /* define label */
483 labldef(loccnt, 1);
484
485 /* get bank index */
486 if (!evaluate(ip, 0))
487 return;
488 if (value > bank_limit) {
489 error("Bank index out of range!");
490 return;
491 }
492
493 /* check if there's a bank name */
494 switch (prlnbuf[*ip]) {
495 case ';':
496 case '\0':
497 break;
498
499 case ',':
500 /* get name */
501 (*ip)++;
502 if (!getstring(ip, name, 63))
503 return;
504
505 /* check name validity */
506 if (strlen(bank_name[value])) {
507 if (strcasecmp(bank_name[value], name)) {
508 error("Different bank names not allowed!");
509 return;
510 }
511 }
512
513 /* copy name */
514 strcpy(bank_name[value], name);
515
516 /* check end of line */
517 if (!check_eol(ip))
518 return;
519
520 /* ok */
521 break;
522
523 default:
524 error("Syntax error!");
525 return;
526 }
527
528 /* backup current bank infos */
529 bank_glabl[section][bank] = glablptr;
530 bank_loccnt[section][bank] = loccnt;
531 bank_page[section][bank] = page;
532
533 /* get new bank infos */
534 bank = value;
535 page = bank_page[section][bank];
536 loccnt = bank_loccnt[section][bank];
537 glablptr = bank_glabl[section][bank];
538
539 /* update the max bank counter */
540 if (max_bank < bank)
541 max_bank = bank;
542
543 /* output on last pass */
544 if (pass == LAST_PASS) {
545 loadlc(bank, 1);
546 println();
547 }
548 }
549
550
551 /* ----
552 * do_incbin()
553 * ----
554 * .incbin pseudo
555 */
556
557 void
do_incbin(int * ip)558 do_incbin(int *ip)
559 {
560 FILE *fp;
561 char *p;
562 char fname[128];
563 int size;
564
565 /* get file name */
566 if (!getstring(ip, fname, 127))
567 return;
568
569 /* get file extension */
570 if ((p = strrchr(fname, '.')) != NULL) {
571 if (!strchr(p, PATH_SEPARATOR)) {
572 /* check if it's a mx file */
573 if (!strcasecmp(p, ".mx")) {
574 do_mx(fname);
575 return;
576 }
577 /* check if it's a map file */
578 if (!strcasecmp(p, ".fmp")) {
579 if (pce_load_map(fname, 0))
580 return;
581 }
582 }
583 }
584
585 /* define label */
586 labldef(loccnt, 1);
587
588 /* output */
589 if (pass == LAST_PASS)
590 loadlc(loccnt, 0);
591
592 /* open file */
593 if ((fp = open_file(fname, "rb")) == NULL) {
594 fatal_error("Can not open file!");
595 return;
596 }
597
598 /* get file size */
599 fseek(fp, 0, SEEK_END);
600 size = ftell(fp);
601 fseek(fp, 0, SEEK_SET);
602
603 /* check if it will fit in the rom */
604 if (((bank << 13) + loccnt + size) > rom_limit) {
605 fclose(fp);
606 error("ROM overflow!");
607 return;
608 }
609
610 /* load data on last pass */
611 if (pass == LAST_PASS) {
612 fread(&rom[bank][loccnt], 1, size, fp);
613 memset(&map[bank][loccnt], section + (page << 5), size);
614
615 /* output line */
616 println();
617 }
618
619 /* close file */
620 fclose(fp);
621
622 /* update bank and location counters */
623 bank += (loccnt + size) >> 13;
624 loccnt = (loccnt + size) & 0x1FFF;
625 if (bank > max_bank) {
626 if (loccnt)
627 max_bank = bank;
628 else
629 max_bank = bank - 1;
630 }
631
632 /* size */
633 if (lablptr) {
634 lablptr->data_type = P_INCBIN;
635 lablptr->data_size = size;
636 }
637 else {
638 if (lastlabl) {
639 if (lastlabl->data_type == P_INCBIN)
640 lastlabl->data_size += size;
641 }
642 }
643 }
644
645
646 /* ----
647 * do_mx()
648 * ----
649 * load a mx file
650 */
651
652 void
do_mx(char * fname)653 do_mx(char *fname)
654 {
655 FILE *fp;
656 char *ptr;
657 char type;
658 char line[256];
659 unsigned char buffer[128];
660 int data;
661 int flag = 0;
662 int size = 0;
663 int cnt, addr, chksum;
664 int i;
665
666 /* open the file */
667 if ((fp = open_file(fname, "r")) == NULL) {
668 fatal_error("Can not open file!");
669 return;
670 }
671
672 /* read loop */
673 while (fgets(line, 254, fp) != NULL) {
674 if (line[0] == 'S') {
675 /* get record type */
676 type = line[1];
677
678 /* error on unsupported records */
679 if ((type != '2') && (type != '8')) {
680 error("Unsupported S-record type!");
681 return;
682 }
683
684 /* get count and address */
685 cnt = htoi(&line[2], 2);
686 addr = htoi(&line[4], 6);
687
688 if ((strlen(line) < 12) || (cnt < 4) || (addr == -1)) {
689 error("Incorrect S-record line!");
690 return;
691 }
692
693 /* adjust count */
694 cnt -= 4;
695
696 /* checksum */
697 chksum = cnt + ((addr >> 16) & 0xFF) +
698 ((addr >> 8) & 0xFF) +
699 ((addr) & 0xFF) + 4;
700
701 /* get data */
702 ptr = &line[10];
703
704 for (i = 0; i < cnt; i++) {
705 data = htoi(ptr, 2);
706 buffer[i] = data;
707 chksum += data;
708 ptr += 2;
709
710 if (data == -1) {
711 error("Syntax error in a S-record line!");
712 return;
713 }
714 }
715
716 /* checksum test */
717 data = htoi(ptr, 2);
718 chksum = (~chksum) & 0xFF;
719
720 if (data != chksum) {
721 error("Checksum error!");
722 return;
723 }
724
725 /* end record */
726 if (type == '8')
727 break;
728
729 /* data record */
730 if (type == '2') {
731 /* set the location counter */
732 if (addr & 0xFFFF0000) {
733 error("Invalid address!");
734 return;
735 }
736 page = (addr >> 13) & 0x07;
737 loccnt = (addr & 0x1FFF);
738
739 /* define label */
740 if (flag == 0) {
741 flag = 1;
742 labldef(loccnt, 1);
743
744 /* output */
745 if (pass == LAST_PASS)
746 loadlc(loccnt, 0);
747 }
748
749 /* copy data */
750 if (pass == LAST_PASS) {
751 for (i = 0; i < cnt; i++)
752 putbyte(loccnt + i, buffer[i]);
753 }
754
755 /* update location counter */
756 loccnt += cnt;
757 size += cnt;
758 }
759 }
760 }
761
762 /* close file */
763 fclose(fp);
764
765 /* define label */
766 if (flag == 0) {
767 labldef(loccnt, 1);
768
769 /* output */
770 if (pass == LAST_PASS)
771 loadlc(loccnt, 0);
772 }
773
774 /* size */
775 if (lablptr) {
776 lablptr->data_type = P_INCBIN;
777 lablptr->data_size = size;
778 }
779 else {
780 if (lastlabl) {
781 if (lastlabl->data_type == P_INCBIN)
782 lastlabl->data_size += size;
783 }
784 }
785
786 /* output line */
787 if (pass == LAST_PASS)
788 println();
789 }
790
791
792 /* ----
793 * do_include()
794 * ----
795 * .include pseudo
796 */
797
798 void
do_include(int * ip)799 do_include(int *ip)
800 {
801 char fname[128];
802
803 /* define label */
804 labldef(loccnt, 1);
805
806 /* get file name */
807 if (!getstring(ip, fname, 127))
808 return;
809
810 /* open file */
811 if (open_input(fname) == -1) {
812 fatal_error("Can not open file!");
813 return;
814 }
815
816 /* output line */
817 if (pass == LAST_PASS)
818 println();
819 }
820
821
822 /* ----
823 * do_rsset()
824 * ----
825 * .rsset pseudo
826 */
827
828 void
do_rsset(int * ip)829 do_rsset(int *ip)
830 {
831 /* define label */
832 labldef(loccnt, 1);
833
834 /* get value */
835 if (!evaluate(ip, ';'))
836 return;
837 if (value & 0xFFFF0000) {
838 error("Address out of range!");
839 return;
840 }
841
842 /* set 'rs' base */
843 rsbase = value;
844
845 /* output line */
846 if (pass == LAST_PASS) {
847 loadlc(rsbase, 1);
848 println();
849 }
850 }
851
852
853 /* ----
854 * do_rs()
855 * ----
856 * .rs pseudo
857 */
858
859 void
do_rs(int * ip)860 do_rs(int *ip)
861 {
862 /* define label */
863 labldef(rsbase, 0);
864
865 /* get the number of bytes to reserve */
866 if (!evaluate(ip, ';'))
867 return;
868
869 /* ouput line */
870 if (pass == LAST_PASS) {
871 loadlc(rsbase, 1);
872 println();
873 }
874
875 /* update 'rs' base */
876 rsbase += value;
877 if (rsbase & 0xFFFF0000)
878 error("Address out of range!");
879 }
880
881
882 /* ----
883 * do_ds()
884 * ----
885 * .ds pseudo
886 */
887
888 void
do_ds(int * ip)889 do_ds(int *ip)
890 {
891 int limit = 0;
892 int addr;
893
894 /* define label */
895 labldef(loccnt, 1);
896
897 /* get the number of bytes to reserve */
898 if (!evaluate(ip, ';'))
899 return;
900
901 /* section switch */
902 switch (section) {
903 case S_ZP:
904 /* zero page section */
905 limit = machine->zp_limit;
906 break;
907
908 case S_BSS:
909 /* ram section */
910 limit = machine->ram_limit;
911 break;
912
913 case S_CODE:
914 case S_DATA:
915 /* code and data sections */
916 limit = 0x2000;
917 break;
918 }
919
920 /* check range */
921 if ((loccnt + value) > limit) {
922 error("Out of range!");
923 return;
924 }
925
926 /* update max counter for zp and bss sections */
927 addr = loccnt + value;
928
929 switch (section) {
930 case S_ZP:
931 /* zero page */
932 if (addr > max_zp)
933 max_zp = addr;
934 break;
935
936 case S_BSS:
937 /* ram page */
938 if (addr > max_bss)
939 max_bss = addr;
940 break;
941 }
942
943 /* output line on last pass */
944 if (pass == LAST_PASS) {
945 switch (section) {
946 case S_CODE:
947 case S_DATA:
948 memset(&rom[bank][loccnt], 0, value);
949 memset(&map[bank][loccnt], section + (page << 5), value);
950 if (bank > max_bank)
951 max_bank = bank;
952 break;
953 }
954 loadlc(loccnt, 0);
955 println();
956 }
957
958 /* update location counter */
959 loccnt += value;
960 }
961
962
963 /* ----
964 * do_fail()
965 * ----
966 * .fail pseudo
967 */
968
969 void
do_fail(int * ip)970 do_fail(int *ip)
971 {
972 fatal_error("Compilation failed!");
973 }
974
975
976 /* ----
977 * do_section()
978 * ----
979 * .zp/.bss/.code/.data pseudo
980 */
981
982 void
do_section(int * ip)983 do_section(int *ip)
984 {
985 if (proc_ptr) {
986 if (optype == S_DATA) {
987 fatal_error("No data segment in procs!");
988 return;
989 }
990 }
991 if (section != optype) {
992 /* backup current section data */
993 section_bank[section] = bank;
994 bank_glabl[section][bank] = glablptr;
995 bank_loccnt[section][bank] = loccnt;
996 bank_page[section][bank] = page;
997
998 /* change section */
999 section = optype;
1000
1001 /* switch to the new section */
1002 bank = section_bank[section];
1003 page = bank_page[section][bank];
1004 loccnt = bank_loccnt[section][bank];
1005 glablptr = bank_glabl[section][bank];
1006 }
1007
1008 /* output line */
1009 if (pass == LAST_PASS) {
1010 loadlc(loccnt + (page << 13), 1);
1011 println();
1012 }
1013 }
1014
1015
1016 /* ----
1017 * do_incchr()
1018 * ----
1019 * .inchr pseudo - convert a PCX to 8x8 character tiles
1020 */
1021
1022 void
do_incchr(int * ip)1023 do_incchr(int *ip)
1024 {
1025 unsigned char buffer[32];
1026 unsigned int i, j;
1027 unsigned int x, y, w, h;
1028 unsigned int tx, ty;
1029 int total = 0;
1030 int size;
1031
1032 /* define label */
1033 labldef(loccnt, 1);
1034
1035 /* output */
1036 if (pass == LAST_PASS)
1037 loadlc(loccnt, 0);
1038
1039 /* get args */
1040 if (!pcx_get_args(ip))
1041 return;
1042 if (!pcx_parse_args(0, pcx_nb_args, &x, &y, &w, &h, 8))
1043 return;
1044
1045 /* pack data */
1046 for (i = 0; i < h; i++) {
1047 for (j = 0; j < w; j++) {
1048 /* tile coordinates */
1049 tx = x + (j << 3);
1050 ty = y + (i << 3);
1051
1052 /* get tile */
1053 size = pcx_pack_8x8_tile(buffer, tx, ty);
1054 total += size;
1055
1056 /* store tile */
1057 putbuffer(buffer, size);
1058 }
1059 }
1060
1061 /* size */
1062 if (lablptr) {
1063 lablptr->data_type = P_INCCHR;
1064 lablptr->data_size = total;
1065 }
1066 else {
1067 if (lastlabl) {
1068 if (lastlabl->data_type == P_INCCHR)
1069 lastlabl->data_size += total;
1070 }
1071 }
1072
1073 /* output */
1074 if (pass == LAST_PASS)
1075 println();
1076 }
1077
1078
1079 /* ----
1080 * do_opt()
1081 * ----
1082 * .opt pseudo - compilation options
1083 */
1084
1085 void
do_opt(int * ip)1086 do_opt(int *ip)
1087 {
1088 char c;
1089 char flag;
1090 char name[32];
1091 int opt;
1092 int i;
1093
1094 for (;;) {
1095 /* skip spaces */
1096 while (isspace(prlnbuf[*ip]))
1097 (*ip)++;
1098
1099 /* get char */
1100 c = prlnbuf[(*ip)++];
1101
1102 /* no option */
1103 if (c == ',')
1104 continue;
1105
1106 /* end of line */
1107 if (c == ';' || c == '\0')
1108 break;
1109
1110 /* extract option */
1111 i = 0;
1112 for (;;) {
1113 if (c == ' ')
1114 continue;
1115 if (c == ',' || c == ';' || c == '\0')
1116 break;
1117 if (i > 31) {
1118 error("Syntax error!");
1119 return;
1120 }
1121 name[i++] = c;
1122 c = prlnbuf[(*ip)++];
1123 }
1124
1125 /* get option flag */
1126 name[i] = '\0';
1127 flag = name[--i];
1128 name[i] = '\0';
1129
1130 /* search option */
1131 if (!strcasecmp(name, "l"))
1132 opt = OPT_LIST;
1133 else if (!strcasecmp(name, "m"))
1134 opt = OPT_MACRO;
1135 else if (!strcasecmp(name, "w"))
1136 opt = OPT_WARNING;
1137 else if (!strcasecmp(name, "o"))
1138 opt = OPT_OPTIMIZE;
1139 else {
1140 error("Unknown option!");
1141 return;
1142 }
1143
1144 /* set option */
1145 if (flag == '+')
1146 asm_opt[opt] = 1;
1147 if (flag == '-')
1148 asm_opt[opt] = 0;
1149 }
1150
1151 /* output */
1152 if (pass == LAST_PASS)
1153 println();
1154 }
1155
1156
1157 /* ----
1158 * htoi()
1159 * ----
1160 */
1161
1162 int
htoi(char * str,int nb)1163 htoi(char *str, int nb)
1164 {
1165 char c;
1166 int val;
1167 int i;
1168
1169 val = 0;
1170
1171 for (i = 0; i < nb; i++) {
1172 c = toupper(str[i]);
1173
1174 if ((c >= '0') && (c <= '9'))
1175 val = (val << 4) + (c - '0');
1176 else if ((c >= 'A') && (c <= 'F'))
1177 val = (val << 4) + (c - 'A' + 10);
1178 else
1179 return (-1);
1180 }
1181
1182 /* ok */
1183 return (val);
1184 }
1185
1186