9e5263b08ffc4794c921ac964b0f5187825f80a8
[linux-libre-firmware.git] / as31 / as31 / run.c
1 #define _GNU_SOURCE
2 #include <stdio.h>
3 #include <setjmp.h>
4 #include <stdarg.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8
9 #include <unistd.h>             //for user stuff
10
11 #include "as31.h"
12
13
14 // added ".inc" command to include header files. B.Porr
15
16 /* global variables */
17 unsigned long lc;
18 char *asmfile;
19 int fatal=0, abort_asap=0;
20 int pass=0;
21 int dashl=0;
22 FILE *listing=NULL, *fin=NULL;
23 int incLineCount=0;
24
25
26
27 int run_as31(const char *infile, int lst, int use_stdout,
28              const char *fmt, const char *arg, const char *customoutfile)
29 {
30         char *outfile=NULL, *lstfile=NULL;
31         const char *extension;
32         int has_dot_asm=0;
33         int i,len, baselen, extlen;
34         FILE* finPre;
35         char tmpName[256];
36         char *lineBuffer=NULL;
37         int sizeBuf=0;
38         char *includePtr=NULL;
39         char *incLineBuffer=NULL;
40         int incSizeBuf=0;
41         FILE* includeFile=NULL;
42         int fd;
43
44         /* first, figure out all the file names */
45
46         dashl = lst;
47         extension = emit_extension(fmt);
48         extlen = strlen(extension);
49
50         len = baselen = strlen(infile);
51         if (len >= 4 && strcasecmp(infile + len - 4, ".asm") == 0) {
52                 has_dot_asm = 1;
53                 baselen -= 4;
54         }
55         
56         asmfile = (char *)malloc(baselen + 5);
57         strcpy(asmfile, infile);
58
59         if (dashl) {
60                 lstfile = (char *)malloc(baselen + 5);
61                 strncpy(lstfile, infile, baselen);
62                 strcpy(lstfile + baselen, ".lst");
63         }
64
65         if (use_stdout) {
66                 outfile = NULL;
67         } else {
68                 if (customoutfile==NULL) {
69                         outfile = (char *)malloc(baselen + extlen + 2);
70                         strncpy(outfile, infile, baselen);
71                         *(outfile + baselen) = '.';
72                         strcpy(outfile + baselen + 1, extension);
73                 } else {
74                         len = strlen(customoutfile);
75                         outfile = (char *)malloc(len + 1);
76                         strncpy(outfile, customoutfile, len);
77                 }
78         }
79
80         /* now open the files */
81
82         // "preprocessor"
83         finPre = freopen(asmfile, "r", stdin);
84         if (finPre == NULL) {
85                 if (!has_dot_asm) {
86                         strcpy(asmfile + baselen, ".asm");
87                         finPre = freopen(asmfile, "r", stdin);
88                 }
89                 if (finPre == NULL) {
90                         mesg_f("Cannot open input file: %s\n", asmfile);
91                         free(asmfile);
92                         if (outfile) free(outfile);
93                         if (lstfile) free(lstfile);
94                         return -1;
95                 }
96         }
97         
98         sprintf(tmpName,"/tmp/as31-XXXXXX.asm");
99         fd = mkstemps(tmpName, 4);
100         if (fd == -1) {
101                 mesg_f("Cannot create temp file\n");
102                 if (outfile) free(outfile);
103                 if (lstfile) free(lstfile);
104                 return -1;
105         }
106         fin = fdopen(fd, "w");
107         if (fin == NULL) {
108                 mesg_f("Cannot open temp file: %s\n",tmpName);
109                 close(fd);
110                 if (outfile) free(outfile);
111                 if (lstfile) free(lstfile);
112                 return -1;
113         }
114
115         while (!feof(finPre)) {
116                 if (getline(&lineBuffer,&sizeBuf,finPre) == -1)
117                         break;
118                 if ((includePtr=strstr(lineBuffer,INC_CMD))) {
119                         includePtr=includePtr+strlen(INC_CMD);
120                         while ((*includePtr==' ')||             //move includePtr to filename
121                                (*includePtr==9)  ||
122                                (*includePtr=='\"')||
123                                (*includePtr=='\''))
124                                 {
125                                 includePtr++;
126                         }
127                         i=0;
128                         while ((includePtr[i]!=0) &&
129                                (includePtr[i]!=10) &&
130                                (includePtr[i]!=13) &&
131                                (includePtr[i]!='\"') &&
132                                (includePtr[i]!='\'')) {
133                                 i++;
134                         }
135                         includePtr[i]=0;
136                         includeFile=fopen(includePtr,"r");
137                         mesg_f("including file: %s\n",includePtr);
138                         if (!includeFile) {
139                                 mesg_f("Cannot open include file: %s\n",includePtr);
140                         } else {
141                                 while (!feof(includeFile)) {
142                                         if (getline(&incLineBuffer,&incSizeBuf,includeFile) == -1)
143                                                 break;
144                                         fprintf(fin,"%s",incLineBuffer);
145                                         if (strlen(incLineBuffer)) {
146                                                 incLineCount++;
147                                         }
148                                 }
149                                 fclose(includeFile);
150                                 if (incLineCount) {
151                                         incLineCount--;
152                                 }
153                         }
154                 } else {
155                         fprintf(fin,"%s",lineBuffer);
156                 }
157         }                                               //.inc -files are now inserted
158         free(lineBuffer);
159         free(incLineBuffer);
160
161         fclose(fin);
162         fin = freopen(tmpName, "r", stdin);
163
164         if (dashl) {
165                 listing = fopen(lstfile,"w");
166                 if( listing == NULL ) {
167                         mesg_f("Cannot open file: %s for writing.\n",
168                                 lstfile);
169                         fclose(fin);
170                         free(asmfile);
171                         if (outfile) free(outfile);
172                         if (lstfile) free(lstfile);
173                         return -1;
174                 }
175         }
176
177         /* what happens if this doesn't work */
178         emitopen(outfile, fmt, arg);
179
180         syminit();
181         clear_location_counter();
182         fatal = abort_asap = 0;
183         lineno = 1;
184         pass=0;
185         lc = 0;
186
187         /*
188         ** P A S S    1
189         */
190
191         if (!use_stdout) mesg_f("Begin Pass #1\n");
192         yyparse();
193         if (fatal) {
194                 mesg_f("Errors in pass1, assembly aborted\n");
195         } else {
196
197                 rewind(fin);
198                 lineno = 1;
199                 pass++;
200                 lc = 0;
201                 emitaddr(lc);
202
203                 /*
204                 ** P A S S    2
205                 */
206                 if (!use_stdout) mesg_f("Begin Pass #2\n");
207                 yyparse();
208         }
209         if (fatal) {
210                 mesg_f("Errors in pass2, assembly aborted\n");
211         }
212
213         emitclose();
214         fclose(fin);
215         unlink(tmpName);                                        //delete tmpName
216         if (dashl) fclose(listing);
217         free(asmfile);
218         if (outfile) free(outfile);
219         if (lstfile) free(lstfile);
220         freesym();
221         if (fatal) return -1;
222         return 0;
223 }       
224
225
226 /* the parser, lexer and other stuff that actually do the */
227 /* assembly will call to these two functions to report any */
228 /* errors or warning.  error() calls exit() in the command */
229 /* line version, but the abort_asap flag was added, and the */
230 /* parser check it at the end of every line */
231
232 void error(const char *fmt, ...)
233 {
234         va_list args;
235         char buf[2048];
236         int len;
237
238         abort_asap++;
239         fatal++;
240         va_start(args, fmt);
241
242         // fixme: negative line no for includes...
243         len = snprintf(buf, sizeof(buf), "Error, line %d, ", lineno-incLineCount);
244         len += vsnprintf(buf + len, sizeof(buf) - len, fmt, args);
245         snprintf(buf + len, sizeof(buf) - len, ".\n");
246         mesg(buf);
247 }
248
249
250 void warn(const char *fmt, ...)
251 {
252         va_list args;
253         char buf[2048];
254         int len;
255
256         fatal++;
257         va_start(args, fmt);
258
259         printf("incLineCount=%d\n",incLineCount);
260         len = snprintf(buf, sizeof(buf), "Warning, line %d, ", lineno-incLineCount);
261         len += vsnprintf(buf + len, sizeof(buf) - len, fmt, args);
262         snprintf(buf + len, sizeof(buf) - len, ".\n");
263         mesg(buf);
264 }
265
266
267 void mesg_f(const char *fmt, ...)
268 {
269         va_list args;
270         char buf[2048];
271
272         va_start(args, fmt);
273
274         vsnprintf(buf, sizeof(buf), fmt, args);
275         mesg(buf);
276 }
277