Imported Upstream version 2.3.1
[debian/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
43         uid_t uid; 
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         uid = geteuid();
99         sprintf(tmpName,"/tmp/as31-%i-%ld.asm",uid,random());
100         fin = fopen(tmpName, "w");
101         if (fin == NULL) {
102                 mesg_f("Cannot open temp file: %s\n",tmpName);
103                 if (outfile) free(outfile);
104                 if (lstfile) free(lstfile);
105                 return -1;
106         }
107
108         while (!feof(finPre)) {
109                 getline(&lineBuffer,&sizeBuf,finPre);
110                 if ((includePtr=strstr(lineBuffer,INC_CMD))) {
111                         includePtr=includePtr+strlen(INC_CMD);
112                         while ((*includePtr==' ')||             //move includePtr to filename
113                                (*includePtr==9)  ||
114                                (*includePtr=='\"')||
115                                (*includePtr=='\''))
116                                 {
117                                 includePtr++;
118                         }
119                         i=0;
120                         while ((includePtr[i]!=0) &&
121                                (includePtr[i]!=10) &&
122                                (includePtr[i]!=13) &&
123                                (includePtr[i]!='\"') &&
124                                (includePtr[i]!='\'')) {
125                                 i++;
126                         }
127                         includePtr[i]=0;
128                         includeFile=fopen(includePtr,"r");
129                         mesg_f("including file: %s\n",includePtr);
130                         if (!includeFile) {
131                                 mesg_f("Cannot open include file: %s\n",includePtr);
132                         } else {
133                                 while (!feof(includeFile)) {
134                                         getline(&incLineBuffer,&incSizeBuf,includeFile);
135                                         fprintf(fin,"%s",incLineBuffer);
136                                         if (strlen(incLineBuffer)) {
137                                                 incLineCount++;
138                                         }
139                                 }
140                                 fclose(includeFile);
141                                 if (incLineCount) {
142                                         incLineCount--;
143                                 }
144                         }
145                 } else {
146                         fprintf(fin,"%s",lineBuffer);
147                 }
148         }                                               //.inc -files are now inserted
149         free(lineBuffer);
150         free(incLineBuffer);
151
152         fclose(fin);
153         fin = freopen(tmpName, "r", stdin);
154
155         if (dashl) {
156                 listing = fopen(lstfile,"w");
157                 if( listing == NULL ) {
158                         mesg_f("Cannot open file: %s for writing.\n",
159                                 lstfile);
160                         fclose(fin);
161                         free(asmfile);
162                         if (outfile) free(outfile);
163                         if (lstfile) free(lstfile);
164                         return -1;
165                 }
166         }
167
168         /* what happens if this doesn't work */
169         emitopen(outfile, fmt, arg);
170
171         syminit();
172         clear_location_counter();
173         fatal = abort_asap = 0;
174         lineno = 1;
175         pass=0;
176         lc = 0;
177
178         /*
179         ** P A S S    1
180         */
181
182         if (!use_stdout) mesg_f("Begin Pass #1\n");
183         yyparse();
184         if (fatal) {
185                 mesg_f("Errors in pass1, assembly aborted\n");
186         } else {
187
188                 rewind(fin);
189                 lineno = 1;
190                 pass++;
191                 lc = 0;
192                 emitaddr(lc);
193
194                 /*
195                 ** P A S S    2
196                 */
197                 if (!use_stdout) mesg_f("Begin Pass #2\n");
198                 yyparse();
199         }
200         if (fatal) {
201                 mesg_f("Errors in pass2, assembly aborted\n");
202         }
203
204         emitclose();
205         fclose(fin);
206         unlink(tmpName);                                        //delete tmpName
207         if (dashl) fclose(listing);
208         free(asmfile);
209         if (outfile) free(outfile);
210         if (lstfile) free(lstfile);
211         freesym();
212         if (fatal) return -1;
213         return 0;
214 }       
215
216
217 /* the parser, lexer and other stuff that actually do the */
218 /* assembly will call to these two functions to report any */
219 /* errors or warning.  error() calls exit() in the command */
220 /* line version, but the abort_asap flag was added, and the */
221 /* parser check it at the end of every line */
222
223 void error(const char *fmt, ...)
224 {
225         va_list args;
226         char buf[2048];
227         int len;
228
229         abort_asap++;
230         fatal++;
231         va_start(args, fmt);
232
233         // fixme: negative line no for includes...
234         len = snprintf(buf, sizeof(buf), "Error, line %d, ", lineno-incLineCount);
235         len += vsnprintf(buf + len, sizeof(buf) - len, fmt, args);
236         snprintf(buf + len, sizeof(buf) - len, ".\n");
237         mesg(buf);
238 }
239
240
241 void warn(const char *fmt, ...)
242 {
243         va_list args;
244         char buf[2048];
245         int len;
246
247         fatal++;
248         va_start(args, fmt);
249
250         printf("incLineCount=%d\n",incLineCount);
251         len = snprintf(buf, sizeof(buf), "Warning, line %d, ", lineno-incLineCount);
252         len += vsnprintf(buf + len, sizeof(buf) - len, fmt, args);
253         snprintf(buf + len, sizeof(buf) - len, ".\n");
254         mesg(buf);
255 }
256
257
258 void mesg_f(const char *fmt, ...)
259 {
260         va_list args;
261         char buf[2048];
262
263         va_start(args, fmt);
264
265         vsnprintf(buf, sizeof(buf), fmt, args);
266         mesg(buf);
267 }
268