-Licenses
[www.jankratochvil.net.git] / project / mot2as / mot2as.c
1 /*
2  * Motorola to AT&T/GNU ASsembler syntax convertor
3  */
4 #ifndef lint
5 static char rcsid[] = "$Id$";
6 #endif
7
8 static char helptext[] =
9   "Motorola to AT&T/GNU ASsembler syntax convertor\n"
10         "Version: %s\n"
11         "Written in 1999 by Jan Kratochvil for Princip, a.s.\n"
12         " - released under GPL version 2 license, see http://www.gnu.org for details\n"
13         "\n"
14   "for compilation of foo.s use the following command:\n"
15   "./mot2as <foo.s|as --bitwise-or --register-prefix-optional -o foo.o\n"
16   "\n";
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <assert.h>
21 #include <limits.h>
22 #include <stdarg.h>
23 #include <string.h>
24 #include <ctype.h>
25
26 typedef unsigned char muchar;
27
28 enum fatality { WARN,ERR,FATAL };
29
30 #ifndef LINE_MAX
31 #define LINE_MAX 16384
32 #endif
33
34 char buf[LINE_MAX];
35 unsigned lino=0;
36 char waserror;
37
38 static void log(enum fatality fat,const char *fmt,...) __attribute__((format(printf,2,3)));
39 static void log(enum fatality fat,const char *fmt,...)
40 {
41 va_list ap;
42         va_start(ap,fmt);
43         fprintf(stderr,"mot2as: %u: ",lino);
44         switch (fat) {
45                 case WARN : fputs("Warning: ",stderr); break;
46                 case ERR  : fputs("Error  : ",stderr); waserror=1; break;
47                 case FATAL: fputs("Fatal  : ",stderr); break;
48                 default   : assert(0);
49                 }
50         vfprintf(stderr,fmt,ap);
51         va_end(ap);
52         fputs("!\n",stderr);
53         if (fat==FATAL) exit(EXIT_FAILURE);
54 }
55
56 int main(int argc,char **argv)
57 {
58 char fld,defbyte,*s;
59 int i;
60
61         if (argc!=1) {
62                 fprintf(stderr,helptext,rcsid);
63                 return(EXIT_FAILURE);
64                 }
65         while (lino++,fgets(buf,sizeof(buf),stdin)) {
66                 if (!(s=strchr(buf,'\n')))
67                         log(ERR,"Line too long (>%u), cut",sizeof(buf)-2);
68                 else {
69                         assert(!s[1]);
70                         *s='\0';
71                         }
72                 fld=0;
73                 defbyte=0;
74                 if (buf[0]=='l' && buf[1]=='b') buf[0]='L';
75                 else if (buf[0]=='L') buf[0]='l';
76                 for (s=buf;*s;s++)
77                         switch (*s) {
78                                 case ' ':
79                                 case '\t': {
80 char *s2=s,eq=0;
81 skip:
82                                         fld++;
83                                         while (s[1]==' ' || s[1]=='\t') s++;
84                                         *s2='\0';
85                                         if (fld==1 && !strncasecmp(s+1,"equ",3) && (s[1+3]==' ' || s[1+3]=='\t')) {
86                                                 fputs("\t.equ\t",stdout);
87                                                 fputs(buf,stdout); putchar(',');
88                                                 s+=4;
89                                                 eq=1;
90                                                 goto skip;
91                                                 }
92                                         if (fld==1) fputs(buf,stdout);
93                                         if (s2>buf && fld==1) putchar(':'); //label
94                                         if (!eq) putchar('\t');
95                                         defbyte|=(fld==1 && !strncasecmp(s+1,"dc.b",4) && (s[1+4]==' ' || s[1+4]=='\t'));
96                                         if (fld==1 && !strncasecmp(s+1,"opt",3) && (s[1+3]==' ' || s[1+3]=='\t')) putchar('|');
97                                         break; }
98                                 case ';': //comment
99 #ifdef PASS_THRU_COMMENTS
100                                         putchar('|');
101                                         fputs(s+1,stdout);
102 #endif PASS_THRU_COMMENTS
103                                         s+=strlen(s)-1;
104                                         fld=1;
105                                         break;
106                                 case '"':
107                                         do {
108                                                 if (s[0]=='\\' && s[1]) putchar(*s++);
109                                                 putchar(*s++);
110                                                 } while (*s && *s!='"');
111                                         putchar(*s);
112                                         break;
113                                 case '\'': { //string
114 char *d,*str;
115                                         for (str=d=++s;*s;*d++=*s++) {
116                                                 if (s[0]=='\'') {
117                                                         if (s[1]=='\'') s++;
118                                                         else break;
119                                                         }
120                                                 }
121                                         if (!*s) {
122                                                 log(ERR,"String ('...) not terminated on this line");
123                                                 s--;
124                                                 }
125                                         if (!defbyte) {
126                                                 if (d-str!=1 && d-str!=2 && d-str!=4)
127                                                         log(ERR,"String ('...') in NOT-defbyte instruction is not of length 1, 2 or 4");
128                                                 else {
129                                                         fputs("0x",stdout);
130                                                         while (str<d) printf("%02X",(muchar)*str++);
131                                                         }
132                                                 break;
133                                                 }
134                                         while (str<d) {
135                                                 printf("%u",(muchar)*str++);
136                                                 if (str<d) putchar(',');
137                                                 }
138                                         break; }
139                                 case '$':
140                                         fputs("0x",stdout);
141                                         break;
142                                 case '%':
143                                         fputs("0b",stdout);
144                                         break;
145                                 case 'l':
146                                         if (s>buf && !isalnum(s[-1]) && s[-1]!='_' && s[1]=='b' && s[2]!='_') *s='L';
147                                         goto out;
148                                 case 'L':
149                                         if (s>buf && !isalnum(s[-1]) && s[-1]!='_') *s='l';
150                                         goto out;
151                                 case '!':
152                                         *s='|';
153                                         /* FALLTHRU */
154                                 default:
155 out:
156                                         if (fld) putchar(*s);
157                                 }
158                 if (!fld && *buf) { fputs(buf,stdout); putchar(':'); }
159                 putchar('\n');
160                 }
161         return(waserror);
162 }