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