1 // Copyright (C) 1999-2012 Core Technologies.
2 //
3 // This file is part of tpasm.
4 //
5 // tpasm is free software; you can redistribute it and/or modify
6 // it under the terms of the tpasm LICENSE AGREEMENT.
7 //
8 // tpasm is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // tpasm LICENSE AGREEMENT for more details.
12 //
13 // You should have received a copy of the tpasm LICENSE AGREEMENT
14 // along with tpasm; see the file "LICENSE.TXT".
15
16
17 #include "include.h"
18
vReportDiagnostic(const char * format,va_list args)19 static void vReportDiagnostic(const char *format,va_list args)
20 // Display diagnostic messages
21 {
22 if(displayDiagnostics)
23 {
24 vfprintf(stderr,format,args);
25 }
26 }
27
ReportDiagnostic(const char * format,...)28 void ReportDiagnostic(const char *format,...)
29 // Display diagnostic messages
30 {
31 va_list
32 args;
33
34 va_start(args,format);
35 vReportDiagnostic(format,args); // do actual reporting
36 va_end(args);
37 }
38
vReportMessage(const char * fileName,unsigned int lineNumber,const char * type,const char * format,va_list args)39 static void vReportMessage(const char *fileName,unsigned int lineNumber,const char *type,const char *format,va_list args)
40 // report messages (errors, warnings, etc...)
41 // type is a string which is descriptive of the message type
42 // This will report to the stderr.
43 // NOTE: this will report during any pass of assembly
44 {
45 unsigned int
46 length;
47
48 if(fileName)
49 {
50 length=strlen(fileName);
51 if(length<16) // work out how much to space over to the error message
52 {
53 length=16-length;
54 }
55 else
56 {
57 length=0;
58 }
59 fprintf(stderr,"%s:%-6d%*s:",fileName,lineNumber,length,"");
60 }
61 else
62 {
63 fprintf(stderr,"<command line> :");
64 }
65 fprintf(stderr,"%s: ",type);
66 vfprintf(stderr,format,args);
67 }
68
ReportMessage(const char * fileName,unsigned int lineNumber,const char * type,const char * format,...)69 static void ReportMessage(const char *fileName,unsigned int lineNumber,const char *type,const char *format,...)
70 // report messages (errors, warnings, etc...)
71 // type is a string which is descriptive of the message type
72 // This will report to the stderr.
73 // NOTE: this will report during any pass of assembly
74 {
75 va_list
76 args;
77
78 va_start(args,format);
79 vReportMessage(fileName,lineNumber,type,format,args);
80 va_end(args);
81 }
82
ReportVirtualPosition()83 static void ReportVirtualPosition()
84 // If the current file location and virtual position do not match up, report
85 // the virtual position
86 {
87 if(currentVirtualFile&&(currentFile!=currentVirtualFile||currentFileLine!=currentVirtualFileLine))
88 {
89 ReportMessage(STNodeName(currentVirtualFile),currentVirtualFileLine,"^ ","Previous message generated indirectly from here\n");
90 }
91 }
92
vReportComplaint(WHERE_FROM * whereFrom,bool isError,const char * format,va_list args)93 static void vReportComplaint(WHERE_FROM *whereFrom,bool isError,const char *format,va_list args)
94 // This will report to the stderr.
95 // NOTE: this will report during any pass of assembly
96 // NOTE: whereFrom can be passed as NULL, in which case, the current
97 // location will be reported
98 // if isError is true, the comlpaint will be reported as an error,
99 // otherwise as a warning
100 {
101 if(isError||displayWarnings)
102 {
103 if(whereFrom)
104 {
105 vReportMessage(whereFrom->file?STNodeName(whereFrom->file):NULL,whereFrom->fileLineNumber,isError?"error ":"warning",format,args);
106 }
107 else
108 {
109 vReportMessage(currentFile?STNodeName(currentFile):NULL,currentFileLine,isError?"error ":"warning",format,args);
110 ReportVirtualPosition();
111 }
112 if(listFile&&outputListing)
113 {
114 if(isError)
115 {
116 fprintf(listFile,"**** ERROR: ");
117 }
118 else
119 {
120 fprintf(listFile,"**** WARNING: ");
121 }
122 vfprintf(listFile,format,args);
123 }
124 if(isError)
125 {
126 errorCount++;
127 }
128 else
129 {
130 warningCount++;
131 }
132 }
133 }
134
vReportSupplement(WHERE_FROM * whereFrom,const char * format,va_list args)135 static void vReportSupplement(WHERE_FROM *whereFrom,const char *format,va_list args)
136 // This will report to the stderr.
137 // NOTE: this will report during any pass of assembly
138 // NOTE: whereFrom can be passed as NULL, in which case, the current
139 // location will be reported
140 {
141 if(whereFrom)
142 {
143 vReportMessage(whereFrom->file?STNodeName(whereFrom->file):NULL,whereFrom->fileLineNumber," ",format,args);
144 }
145 else
146 {
147 vReportMessage(currentFile?STNodeName(currentFile):NULL,currentFileLine," ",format,args);
148 ReportVirtualPosition();
149 }
150 }
151
ReportComplaint(bool isError,const char * format,...)152 void ReportComplaint(bool isError,const char *format,...)
153 // if a hard error (failed to allocate memory, or open file, etc), or warning occurs while
154 // assembling, report it immediately with this function
155 // This will report to the stderr.
156 // NOTE: this will report during any pass of assembly
157 {
158 va_list
159 args;
160
161 va_start(args,format);
162 vReportComplaint(NULL,isError,format,args);
163 va_end(args);
164 }
165
AssemblyComplaint(WHERE_FROM * whereFrom,bool isError,const char * format,...)166 void AssemblyComplaint(WHERE_FROM *whereFrom,bool isError,const char *format,...)
167 // Report assembly errors or warnings
168 // This will report to the stderr, as well as to the listing file if there is one
169 // NOTE: this only reports during the final pass of assembly
170 {
171 va_list
172 args;
173
174 if(!intermediatePass)
175 {
176 va_start(args,format);
177 vReportComplaint(whereFrom,isError,format,args);
178 va_end(args);
179 }
180 }
181
AssemblySupplement(WHERE_FROM * whereFrom,const char * format,...)182 void AssemblySupplement(WHERE_FROM *whereFrom,const char *format,...)
183 // Report supplementary information about an error or warning
184 // This will report to the stderr, as well as to the listing file if there is one
185 // NOTE: this only reports during the final pass of assembly
186 {
187 va_list
188 args;
189
190 if(!intermediatePass)
191 {
192 va_start(args,format);
193 vReportSupplement(whereFrom,format,args);
194 va_end(args);
195 }
196 }
197
CreateListStringValue(LISTING_RECORD * listingRecord,int value,bool unresolved)198 void CreateListStringValue(LISTING_RECORD *listingRecord,int value,bool unresolved)
199 // Create the listing output string for a value
200 {
201 if(!unresolved)
202 {
203 sprintf(listingRecord->listObjectString,"(%08X)",value);
204 }
205 else
206 {
207 sprintf(listingRecord->listObjectString,"(???????\?)"); // see that '\'?? It's there because of the brilliant individual who invented trigraphs
208 }
209 }
210
OutputListFileHeader(time_t timeVal)211 void OutputListFileHeader(time_t timeVal)
212 // Dump the header information to the list file
213 {
214 if(listFile)
215 {
216 timeVal=time(NULL);
217 fprintf(listFile,"tpasm %s Assembling on %s",VERSION,ctime(&timeVal));
218 fprintf(listFile,"\n");
219 fprintf(listFile,"Source File: %s\n",sourceFileName);
220 fprintf(listFile,"\n");
221 fprintf(listFile,"Line Loc Object/(Value) T Source\n");
222 fprintf(listFile,"----- -------- -------------- - ------\n");
223 }
224 }
225
GetNextWrapIndex(char * listObjectString,unsigned int * startIndex,unsigned int * endIndex)226 static void GetNextWrapIndex(char *listObjectString,unsigned int *startIndex,unsigned int *endIndex)
227 // look through the listObjectString, try to find good wrap points, return them
228 // NOTE: startIndex is passed in as the place to start working
229 // both startIndex and endIndex are modified
230 // startIndex will point to the end of the string when there is nothing
231 // more to print
232 {
233 unsigned int
234 bestEndIndex;
235
236 while(listObjectString[*startIndex]&&listObjectString[*startIndex]==' ') // move through all the white at the start
237 {
238 (*startIndex)++;
239 }
240 bestEndIndex=(*endIndex)=(*startIndex);
241 while(listObjectString[*endIndex]&&((*endIndex)-(*startIndex))<14)
242 {
243 if(listObjectString[*endIndex]==' ')
244 {
245 bestEndIndex=*endIndex;
246 }
247 (*endIndex)++;
248 }
249 if(listObjectString[*endIndex]==' ') // check for space at the very end
250 {
251 bestEndIndex=*endIndex;
252 }
253 if(bestEndIndex==(*startIndex)||!listObjectString[*endIndex]) // if nothing good found, or at end, then set best to the end
254 {
255 bestEndIndex=(*endIndex);
256 }
257 (*endIndex)=bestEndIndex; // this is the end
258 }
259
OutputListFileLine(LISTING_RECORD * listingRecord,const char * sourceLine)260 void OutputListFileLine(LISTING_RECORD *listingRecord,const char *sourceLine)
261 // Output the listing line
262 // NOTE: this may generate more than one line if listingRecord->listObjectString is long
263 // the string will be wrapped (preferably on space boundaries) and written on
264 // subsequent lines
265 {
266 unsigned int
267 startIndex,
268 endIndex;
269
270 if(!intermediatePass&&listFile&&outputListing&&listingRecord->wantList)
271 {
272 startIndex=0;
273 GetNextWrapIndex(listingRecord->listObjectString,&startIndex,&endIndex);
274 fprintf(listFile,"%-5d %08X %-14.*s %c %s\n",listingRecord->lineNumber,listingRecord->listPC,endIndex-startIndex,&listingRecord->listObjectString[startIndex],listingRecord->sourceType,sourceLine);
275
276 startIndex=endIndex;
277 GetNextWrapIndex(listingRecord->listObjectString,&startIndex,&endIndex); // move to the next spot
278 while(listingRecord->listObjectString[startIndex]) // if more to print, then do it
279 {
280 fprintf(listFile," %-14.*s %c\n",endIndex-startIndex,&listingRecord->listObjectString[startIndex],listingRecord->sourceType);
281 startIndex=endIndex;
282 GetNextWrapIndex(listingRecord->listObjectString,&startIndex,&endIndex);
283 }
284 }
285 }
286
OutputListFileStats(unsigned int totalTime)287 void OutputListFileStats(unsigned int totalTime)
288 // Dump stats information to the list file
289 {
290 unsigned int
291 hours,minutes,seconds;
292
293 hours=totalTime/3600;
294 totalTime-=(hours*3600);
295 minutes=totalTime/60;
296 totalTime-=(minutes*60);
297 seconds=totalTime;
298 ReportDiagnostic("\n");
299 ReportDiagnostic("Assembled in %d passes\n",passCount+1);
300 ReportDiagnostic("\n");
301 ReportDiagnostic("Total assembly time %02d:%02d:%02d\n",hours,minutes,seconds);
302 ReportDiagnostic("Total Errors: %d\n",errorCount);
303 ReportDiagnostic("Total Warnings: %d\n",warningCount);
304
305 if(listFile)
306 {
307 fprintf(listFile,"\n");
308 fprintf(listFile,"Assembled in %d passes\n",passCount+1);
309 fprintf(listFile,"\n");
310 fprintf(listFile,"Total assembly time %02d:%02d:%02d\n",hours,minutes,seconds);
311 fprintf(listFile,"Total Errors: %d\n",errorCount);
312 fprintf(listFile,"Total Warnings: %d\n",warningCount);
313 }
314 }
315
OutputListFileSegments()316 void OutputListFileSegments()
317 // Dump segment information to the list file
318 {
319 if(listFile)
320 {
321 fprintf(listFile,"\n");
322 DumpSegmentsListing(listFile);
323 }
324 }
325
CompareLabels(const void * i,const void * j)326 static int CompareLabels(const void *i,const void *j)
327 // compare the labels given by the entries i and j
328 // This is called by qsort
329 {
330 LABEL_RECORD
331 **recordA,
332 **recordB;
333
334 recordA=(LABEL_RECORD **)i;
335 recordB=(LABEL_RECORD **)j;
336 return(strcmp(STNodeName((*recordA)->symbol),STNodeName((*recordB)->symbol)));
337 }
338
OutputTextSymbols(FILE * file)339 bool OutputTextSymbols(FILE *file)
340 // Dump symbol information in a textual way to file
341 {
342 LABEL_RECORD
343 *label;
344 unsigned int
345 i,
346 numLabels;
347 LABEL_RECORD
348 **sortArray;
349
350 numLabels=NumLabels();
351 if((sortArray=(LABEL_RECORD **)NewPtr(sizeof(LABEL_RECORD *)*numLabels)))
352 {
353 label=labelsHead;
354 for(i=0;i<numLabels;i++) // make array of pointers to labels
355 {
356 sortArray[i]=label;
357 label=label->next;
358 }
359
360 qsort(sortArray,numLabels,sizeof(LABEL_RECORD *),CompareLabels); // sort the array
361
362 fprintf(file,"Symbol Table Listing\n");
363 fprintf(file,"Value U Name\n");
364 fprintf(file,"-------- - ----\n");
365
366 for(i=0;i<numLabels;i++) // make array of pointers to labels
367 {
368 label=sortArray[i];
369 if(label->resolved)
370 {
371 fprintf(file,"%08X %c %s\n",label->value,(label->refCount==0)?'*':' ',STNodeName(label->symbol));
372 }
373 else
374 {
375 fprintf(file,"???????? %s\n",STNodeName(label->symbol));
376 }
377 }
378
379 DisposePtr(sortArray);
380 }
381 return(true);
382 }
383
OutputListFileLabels()384 void OutputListFileLabels()
385 // Dump symbol information to the list file
386 {
387 if(listFile)
388 {
389 fprintf(listFile,"\n");
390 OutputTextSymbols(listFile);
391 }
392 }
393