]> Shamusworld >> Repos - rmac/blob - error.c
Version bump for last commit. :-)
[rmac] / error.c
1 //
2 // RMAC - Renamed Macro Assembler for all Atari computers
3 // ERROR.C - Error Handling
4 // Copyright (C) 199x Landon Dyer, 2011-2021 Reboot and Friends
5 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
6 // Source utilised with the kind permission of Landon Dyer
7 //
8
9 #include "error.h"
10 #include <stdarg.h>
11 #include "token.h"
12 #include "listing.h"
13 char * interror_msg[] = {
14         "Unknown internal error",       // Error not referenced, should not be displayed
15         "Unknown internal error",       // Error not referenced, should not be displayed
16         "Bad MULTX entry in chrtab",                            // Error #2
17         "Unknown internal error",       // Error not referenced, should not be displayed
18         "Bad fixup type",                                                       // Error #4
19         "Bad operator in expression stream",            // Error #5
20         "Can't find generated code in section",         // Error #6
21         "Fixup (loc) out of range",                                     // Error #7
22         "Absolute top filename found",                          // Error #8
23         "The RISC expression evaluator blew up, sorry" // Error #9
24 };
25
26 // Exported variables
27 int errcnt;                                             // Error count
28 char * err_fname;                               // Name of error message file
29
30 // Internal variables
31 static long unused;                             // For supressing 'write' warnings
32
33 //
34 // Report error if not at EOL
35 //
36 // N.B.: Since this should *never* happen, we can feel free to add whatever
37 //       diagnostics that will help in tracking down a problem to this function.
38 //
39 int ErrorIfNotAtEOL(void)
40 {
41         if (*tok != EOL)
42         {
43                 error("syntax error. expected EOL, found $%X ('%c')", *tok, *tok);
44                 printf("Token = ");
45                 DumpToken(*tok);
46                 printf("\n");
47                 DumpTokenBuffer();
48         }
49
50         return 0;
51 }
52
53 //
54 // Cannot create a file
55 //
56 void CantCreateFile(const char * fn)
57 {
58         printf("Cannot create file: '%s'\n", fn);
59         exit(1);
60 }
61
62 //
63 // Setup for error message
64 //  o  Create error listing file (if necessary)
65 //  o  Set current filename
66 //
67 void err_setup(void)
68 {
69         char fnbuf[FNSIZ];
70
71         if (err_fname != NULL)
72         {
73                 strcpy(fnbuf, err_fname);
74
75                 if (*fnbuf == EOS)
76                         strcpy(fnbuf, firstfname);
77
78                 err_fname = NULL;
79
80                 if ((err_fd = open(fnbuf, _OPEN_FLAGS, _PERM_MODE)) < 0)
81                         CantCreateFile(fnbuf);
82
83                 err_flag = 1;
84         }
85 }
86
87 //
88 // Display error message (uses printf() style variable arguments)
89 //
90 int error(const char * text, ...)
91 {
92         char buf[EBUFSIZ];
93         char buf1[EBUFSIZ];
94
95         err_setup();
96
97         va_list arg;
98         va_start(arg, text);
99         vsprintf(buf, text, arg);
100         va_end(arg);
101
102         if (listing > 0)
103                 ship_ln(buf);
104
105         if (cur_inobj)
106         {
107                 switch (cur_inobj->in_type)
108                 {
109                 case SRC_IFILE:
110                         sprintf(buf1, "%s %d: Error: %s\n", curfname, curlineno, buf);
111                         break;
112                 case SRC_IMACRO:
113                 {
114                         // This is basically SetFilenameForErrorReporting() but we don't
115                         // call it here as it will clobber curfname. That function is used
116                         // during fixups only so it really doesn't matter at that point...
117                         char * filename;
118                         FILEREC * fr;
119                         uint16_t fnum = cur_inobj->inobj.imacro->im_macro->cfileno;
120
121                         // Check for absolute top filename (this should never happen)
122                         if (fnum == -1)
123                                 interror(8);
124                         else
125                         {
126                                 fr = filerec;
127
128                                 // Advance to the correct record...
129                                 while (fr != NULL && fnum != 0)
130                                 {
131                                         fr = fr->frec_next;
132                                         fnum--;
133                                 }
134                         }
135                         // Check for file # record not found (this should never happen either)
136                         if (fr == NULL)
137                                 interror(8);
138
139                         filename = fr->frec_name;
140
141                         sprintf(buf1, "%s %d: Error: %s\nCalled from: %s %d\n", filename, cur_inobj->inobj.imacro->im_macro->lineList->lineno, buf,
142                         curfname, curlineno);
143                 }
144                         break;
145                 case SRC_IREPT:
146                         sprintf(buf1, "%s %d: Error: %s\n", curfname, cur_inobj->inobj.irept->lineno, buf);
147                         break;
148                 }
149         }
150         else
151                 // No current file so cur_inobj is NULL
152                 sprintf(buf1, "%s %d: Error: %s\n", curfname, curlineno, buf);
153
154         if (err_flag)
155                 unused = write(err_fd, buf1, (LONG)strlen(buf1));
156         else
157                 printf("%s", buf1);
158
159         taglist('E');
160         errcnt++;
161
162         return ERROR;
163 }
164
165 //
166 // Display warning message (uses printf() style variable arguments)
167 //
168 int warn(const char * text, ...)
169 {
170         char buf[EBUFSIZ];
171         char buf1[EBUFSIZ];
172
173         err_setup();
174         va_list arg;
175         va_start(arg, text);
176         vsprintf(buf, text, arg);
177         va_end(arg);
178
179         if (listing > 0)
180                 ship_ln(buf);
181
182         sprintf(buf1, "%s %d: Warning: %s\n", curfname, curlineno, buf);
183
184         if (err_flag)
185                 unused = write(err_fd, buf1, (LONG)strlen(buf1));
186         else
187                 printf("%s", buf1);
188
189         taglist('W');
190
191         return OK;
192 }
193
194 int fatal(const char * s)
195 {
196         char buf[EBUFSIZ];
197
198         err_setup();
199
200         if (listing > 0)
201                 ship_ln(s);
202
203         sprintf(buf, "%s %d: Fatal: %s\n", curfname, curlineno, s);
204
205         if (err_flag)
206                 unused = write(err_fd, buf, (LONG)strlen(buf));
207         else
208                 printf("%s", buf);
209
210         exit(1);
211 }
212
213 int interror(int n)
214 {
215         char buf[EBUFSIZ];
216
217         err_setup();
218         sprintf(buf, "%s %d: Internal error #%d: %s\n", curfname, curlineno, n, interror_msg[n]);
219
220         if (listing > 0)
221                 ship_ln(buf);
222
223         if (err_flag)
224                 unused = write(err_fd, buf, (LONG)strlen(buf));
225         else
226                 printf("%s", buf);
227
228         exit(1);
229 }