/[projet1]/public/pc/tools/osdk/main/link65/sources/Link65.cpp
Defence Force logotype

Contents of /public/pc/tools/osdk/main/link65/sources/Link65.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1045 - (show annotations)
Fri Dec 20 17:42:53 2013 UTC (5 years, 10 months ago) by dbug
File size: 25328 byte(s)
Floppy Builder 0.11
- Added support for metadata that can be used later on by the programmer
Also modified Link65 to handle #include correctly in assembler source files
The SlideShow now correctly displays the name of the pictures and their authors from the exported metadata (Still need transitions)

1 /*
2
3 The 6502 Linker, for the lcc or similar, that produce .s files
4 to be processed later by a cross assembler
5
6 List of modifications:
7
8 Originaly created by Vagelis Blathras
9
10 2009-02-14 [Mike] Version 0.63
11 (WIP) The old linked filtered out comments, need to implement this feature as well
12
13 Fixed a number of issues in the linker:
14 - removed some test code
15 - fixed the loading of symbols from the library index file
16
17 Fixed a problem of text file parsings. Mixed unix/dos cariage return would result in very long lines (containing many lines), leading to some crashes later on.
18 Also fixed a problem in reporting the parsed files.
19
20 2003-05-27 [Mike] Handling of lines that have more than 180 characters
21
22 2003-09-13 [Mike] Version 0.59
23 Corrected a bug that made it impossible to "link" only one source file
24
25 2003-09-13 [Mike] Version 0.57
26 Added '-B' option to suppress inclusion of HEADER and TAIL
27
28 2004-01-18 [Mike] Version 0.58
29 Added filtering of all '#' directives
30 Added an icon to the executable file to make it more 'OSDK' integrated :)
31 Added '-F' option to enable #file directive (requires modified XA assembler)
32 Modified the handling of comments to avoid crashes on C and C++ comments
33
34 2006-06-02 [Mike] Version 0.59
35 Corrected a bug that made it impossible to "link" only one source file
36
37 */
38
39
40
41 #include "infos.h"
42
43 #include <assert.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <memory.h>
48 #include <ctype.h>
49 #include <direct.h>
50
51 #include "common.h"
52
53 // Disable the warning C4706 -> assignment within conditional expression
54 // Allow us to use Warning level 4 instead of level 3
55 #pragma warning( disable : 4706)
56 #pragma warning( disable : 4786) // Debug symbols thing
57
58 #include <vector>
59 #include <string>
60 #include <set>
61
62 #define NB_ARG 2
63
64
65 #define MAX_LINE_SIZE 4096 // XA is limited to 2048
66
67
68
69 // Structure for labels in a pair of : label_name/resolved_flag
70 struct ReferencedLabelEntry_c
71 {
72 bool m_bIsResolved;
73 std::string label_name;
74 };
75
76 // Lib index structure in pair of : label_name/file_containing_label
77 struct LabelEntry_c
78 {
79 std::string label_name;
80 std::string file_name;
81 };
82
83 class FileEntry_c
84 {
85 public:
86 FileEntry_c() :
87 m_nSortPriority(0)
88 {}
89
90 public:
91 std::string m_cFileName;
92 int m_nSortPriority;
93 };
94
95
96 bool gFlagKeepComments=false; // Use -C option to control
97 bool gFlagIncludeHeader=true; // Use -B option to force to 0
98 bool gFlagEnableFileDirective=false; // Use -F option to enable (force to one)
99 bool gFlagVerbose=false; // Use -V option to enable
100 bool gFlagQuiet=false; // Use -Q option to enable (note: seems to work the other way arround !)
101 bool gFlagLibrarian=false; // Use -L option to enable
102
103 char *label;
104
105
106
107
108 // gInputFileList contains filenames to be linked.
109 // nflist is 1 for file given in command line or 0 for files given from lib file index, 2 for tail. It's used for sort...
110 std::vector<FileEntry_c> gInputFileList;
111 std::vector<LabelEntry_c> gLibraryReferencesList;
112 std::vector<ReferencedLabelEntry_c> gReferencedLabelsList;
113 std::set<std::string> gDefinedLabelsList;
114
115
116 //
117 // Some pre-declarations...
118 //
119 bool ParseFile(const std::string& filename);
120
121
122
123 std::string FilterLine(const std::string& cSourceLine)
124 {
125 static bool flag_in_comment_bloc=false; // Used by the parser to know that we are currently parsing a bloc of comments
126
127 std::string outline;
128 outline.reserve(MAX_LINE_SIZE);
129
130 const char* source_line=cSourceLine.c_str();
131 while (char car=*source_line++)
132 {
133 if (flag_in_comment_bloc) // In a C block comment - that one may have been started on another line
134 {
135 if ( (car=='*') && (*source_line=='/') )
136 {
137 // Found end of C block comment
138 source_line++;
139 flag_in_comment_bloc=false;
140 }
141 }
142 else
143 {
144 if (car=='\"')
145 {
146 // Found start of quoted string
147 do
148 {
149 outline+=car;
150 car=*source_line++;
151 }
152 while (car && (car!='\"'));
153 if (car)
154 {
155 outline+=car;
156 }
157 }
158 else
159 if (car==';')
160 {
161 // Found start of assembler line comment - just stop here
162 return outline;
163 }
164 else
165 if ( (car=='/') && (*source_line=='*') )
166 {
167 // Found start of C block comment
168 source_line++;
169 flag_in_comment_bloc=true;
170 }
171 else
172 if ( (car=='/') && (*source_line=='/') )
173 {
174 // Found start of C++ line comment - just stop here
175 return outline;
176 }
177 else
178 {
179 // Any other character
180 outline+=car;
181 }
182 }
183 }
184 return outline;
185 }
186
187 #if 0
188 std::string FilterLine(const std::string& cSourceLine)
189 {
190 static bool flag_in_comment_bloc=false; // Used by the parser to know that we are currently parsing a bloc of comments
191
192 char inpline[MAX_LINE_SIZE+1];
193 assert(sizeof(inpline)>cSourceLine.size());
194 strcpy(inpline,cSourceLine.c_str());
195
196 //
197 // Checking for a end of C bloc comment
198 //
199 if (flag_in_comment_bloc)
200 {
201 char *ptr_line=strstr(inpline,"*/");
202 if (ptr_line)
203 {
204 //
205 // Finalize the comment
206 //
207 *ptr_line=0;
208 strcpy(inpline+2,ptr_line);
209 flag_in_comment_bloc=false;
210 }
211 else
212 {
213 //
214 // We are still in the bloc
215 //
216 inpline[0]=0;
217 }
218 }
219
220 //
221 // Filtering of C++ like comments
222 //
223 {
224 char *ptr_line=strstr(inpline,"//");
225 if (ptr_line)
226 {
227 *ptr_line=0;
228 }
229 }
230
231 //
232 // Filtering of assembly comments
233 //
234 {
235 char *ptr_line=strchr(inpline,';');
236 if (ptr_line)
237 {
238 *ptr_line=0;
239 }
240 }
241
242 //
243 // Checking for a beginning of C bloc comment
244 //
245 if (!flag_in_comment_bloc)
246 {
247 char *ptr_line=strstr(inpline,"/*");
248 if (ptr_line)
249 {
250 *ptr_line=0;
251 flag_in_comment_bloc=true;
252 }
253 }
254
255 return std::string(inpline);
256 }
257 #endif
258
259
260 /*
261 C:\OSDK\BIN\link65.exe -d C:\OSDK\lib/ -o C:\OSDK\TMP\linked.s -s C:\OSDK\TMP\ -q main
262 */
263
264 //
265 // Parse a line. Mask out comment lines and null lines.
266 // Clear ending comments.
267 // Return defined labels in label var, with return value of 1
268 // Return labels used by JSR, JMP, LDA, STA in label var, with ret value of 2
269 //
270 int parseline(const std::string cInputLine,bool parseIncludeFiles)
271 {
272 char *tmp;
273
274 char inpline[MAX_LINE_SIZE+1];
275 assert(sizeof(inpline)>cInputLine.size());
276 strcpy(inpline,cInputLine.c_str());
277
278 int len=strlen(inpline);
279
280 //
281 // Return if comment line or too small line
282 //
283 if (inpline[0] ==';') return 0;
284 if (len < 2) return 0;
285
286 //
287 // Is a label defined..? (first char in line is what we want)
288 //
289 if ((inpline[0] !=' ') && (inpline[0] != 9))
290 {
291 label=strtok(inpline," *+-;\\\n/\t,");
292 if (!label)
293 {
294 //
295 // No token was found
296 //
297 return 0;
298 }
299
300 if (label[0]=='#')
301 {
302 //
303 // It's a preprocessor directive
304 //
305 if (!stricmp(label,"#define")) // MIKE: Do not need problems with #define (for XA equates)
306 {
307 //
308 // #define is always followed by something that can be considered as a label.
309 // For the linker that means that we have to add this 'label' in the list of
310 // things to consider as internal linkage. (no need to lookup in the librarie)
311 //
312 // Read define name
313 label=strtok(NULL," *+-;\\\n/\t,()");
314 return 1;
315 }
316 else if (!stricmp(label,"#include"))
317 {
318 //
319 // Problem with #include is that they may contain labels,
320 // but we do not want to insert the content of the file,
321 // so basically we should just recurse on the name without
322 // including the content.
323 // A kind of "label eater", really.
324 //
325 // Read define name
326 const char* pcFilename=strtok(NULL," \"*+-;\\\n/\t,()");
327 if (parseIncludeFiles)
328 {
329 ParseFile(pcFilename);
330 }
331 /*
332 if (!stricmp(pcFilename,"GenericEditorRoutines.s"))
333 {
334 printf("toto");
335 }
336 ParseFile(pcFilename);
337 */
338 return 0;
339 }
340 //
341 // Other '#' directives are not considered as labels.
342 //
343 return 0;
344 }
345 else
346 if ((label[0]=='.') && ((label[1]=='(') || (label[1]==')')) )
347 {
348 // Opening or closing a local scope, not considered as label
349 return 0;
350 }
351 else
352 {
353 //
354 // Something else (probably a label)
355 //
356 return 1;
357 }
358 }
359
360 //
361 // Check for JMP or JSR and for the following label
362 //
363 int status = 0;
364 tmp=strtok(inpline," *+-;\\\n/\t,()");
365 while (tmp != NULL)
366 {
367 if (status == 1)
368 break;
369
370 if (!stricmp(tmp,"JSR")) status = 1;
371 else
372 if (!stricmp(tmp,"JMP")) status = 1;
373 else
374 if (!stricmp(tmp,"LDA")) status = 1;
375 else
376 if (!stricmp(tmp,"STA")) status = 1;
377 else
378 if (!stricmp(tmp,"LDX")) status = 1;
379 else
380 if (!stricmp(tmp,"STX")) status = 1;
381 else
382 if (!stricmp(tmp,"LDY")) status = 1;
383 else
384 if (!stricmp(tmp,"STY")) status = 1;
385
386 //
387 // Get next token in same line. This is the way strtok works
388 //
389 tmp=strtok(NULL," *+-;\\\n/\t,()");
390 }
391 if (tmp)
392 {
393 if ((status == 1) && tmp[0] != '$' && tmp[0] != '(' && tmp[0] != '#' && !isdigit(tmp[0]))
394 {
395 label = tmp;
396 return(2);
397 }
398 if ((status == 1) && (tmp[0] == '#') )
399 {
400 if (tmp[1] == 'H' || tmp[1] == 'L')
401 {
402 //
403 // HIGH / LOW syntax
404 //
405 tmp=strtok(NULL," *+-;\\\n/\t,()<>");
406 if (tmp != NULL && tmp[0] != '$' && tmp[0] != '(' && tmp[0] != '#' && !isdigit(tmp[0]))
407 {
408 label=tmp;
409 return 2;
410 }
411 }
412 else
413 if (tmp[1]=='<' || tmp[1]=='>')
414 {
415 // < / > syntax
416 if (tmp[2])
417 {
418 tmp+=2;
419 }
420 else
421 {
422 tmp=strtok(NULL," *+-;\\\n/\t,()<>");
423 }
424
425 if (tmp != NULL && tmp[0] != '$' && tmp[0] != '(' && tmp[0] != '#' && !isdigit(tmp[0]))
426 {
427 label=tmp;
428 return 2;
429 }
430 }
431 }
432 }
433 return 0;
434 }
435
436
437
438 void outall()
439 {
440 flushall();
441 fcloseall();
442 }
443
444 //
445 // Simple function that prints error message/calls outall.
446 // Simplifies the look of the main program
447 //
448 void linkerror(char *msg)
449 {
450 printf(msg);
451 outall();
452 }
453
454
455
456
457 bool ParseFile(const std::string& filename)
458 {
459 std::vector<std::string> cTextData;
460 if (!LoadText(filename.c_str(),cTextData))
461 {
462 printf("\nCannot open %s \n",filename.c_str());
463 outall();
464 exit(1);
465 }
466
467 if (gFlagVerbose)
468 printf("\nScanning file %s " ,filename.c_str());
469
470 bool parseIncludeFiles=false;
471 if (*filename.rbegin()=='s') // Quick hack, we parse the includes in the assembler files, need proper detection of format
472 {
473 parseIncludeFiles=true;
474 }
475
476
477 unsigned int i;
478
479 // Scanning the file
480 std::vector<std::string>::const_iterator cItText=cTextData.begin();
481 while (cItText!=cTextData.end())
482 {
483 // Get line file and parse it
484 const std::string& cCurrentLine=*cItText;
485
486 std::string cFilteredLine=FilterLine(cCurrentLine);
487 int state=parseline(cFilteredLine,parseIncludeFiles);
488
489 std::string cFoundLabel;
490 if (state && label)
491 {
492 cFoundLabel=label;
493 }
494
495 // Oh, a label defined. Stuff it in storage
496 if (state==1)
497 {
498 std::set<std::string>::iterator cIt=gDefinedLabelsList.find(cFoundLabel);
499 if (cIt!=gDefinedLabelsList.end())
500 {
501 // Found the label in the list.
502 // It's a duplicate definition... does not mean it's an error, because XA handles allows local labels !
503 //printf("\nError ! Duplicate label : %s\n",label);
504 //outall();
505 //exit(1);
506 //break;
507 }
508 else
509 {
510 // Insert new label in the set
511 gDefinedLabelsList.insert(cFoundLabel);
512 }
513 }
514 else
515 if (state == 2)
516 {
517 // A label reference.
518 // Store it if not already in list.
519 bool bUndefinedLabel=true;
520 for (i=0;i<gReferencedLabelsList.size();i++)
521 {
522 if (gReferencedLabelsList[i].label_name==label)
523 {
524 bUndefinedLabel=false;
525 break;
526 }
527 }
528
529 if (bUndefinedLabel)
530 {
531 // Allocate memory for label name and store it
532 ReferencedLabelEntry_c cLabelEntry;
533 cLabelEntry.label_name =label;
534 cLabelEntry.m_bIsResolved =false;
535
536 gReferencedLabelsList.push_back(cLabelEntry);
537 }
538 }
539 ++cItText;
540 }
541
542 return true;
543 }
544
545
546
547
548 bool LoadLibrary(const std::string& path_library_files)
549 {
550 std::string ndxstr=path_library_files+"library.ndx";
551
552 std::vector<std::string> cTextData;
553 if (!LoadText(ndxstr.c_str(),cTextData))
554 {
555 printf("Cannot open Index file : %s \n",ndxstr.c_str());
556 exit(1);
557 }
558
559 if (gFlagVerbose)
560 printf("Reading lib index file\n");
561
562 LabelEntry_c cLabelEntry;
563 cLabelEntry.file_name ="";
564 cLabelEntry.label_name ="";
565
566 std::vector<std::string>::const_iterator cItText=cTextData.begin();
567 while (cItText!=cTextData.end())
568 {
569 // Get line file and parse it
570 std::string cCurrentLine=StringTrim(*cItText);
571
572 // Lines that indicate files start with -
573 //if (cCurrentLine[0] < 32)
574 // break;
575
576 if (!cCurrentLine.empty())
577 {
578 if (cCurrentLine[0] == '-')
579 {
580 // Found a file indicator. Check if already used, if not start using it in table
581 cLabelEntry.file_name=path_library_files+(cCurrentLine.c_str()+1);
582 // check for duplicate
583 for (unsigned int i=0;i<gLibraryReferencesList.size();i++)
584 {
585 if (cLabelEntry.file_name==gLibraryReferencesList[i].file_name)
586 {
587 printf("Duplicate file %s in lib index\n",cLabelEntry.file_name.c_str());
588 outall();
589 exit(1);
590 }
591 }
592 }
593 else
594 {
595 // Found a label. Check if already used, if not put it in table
596 if (cLabelEntry.file_name.size()<2)
597 {
598 linkerror("Error with file line indicator\n");
599 exit(1);
600 }
601
602 cLabelEntry.label_name=cCurrentLine;
603
604 // Check if label is duplicate
605 for (unsigned int i=0;i<gLibraryReferencesList.size();i++)
606 {
607 if (cLabelEntry.label_name==gLibraryReferencesList[i].label_name)
608 {
609 printf("Duplicate label %s in lib index file\n",cLabelEntry.label_name.c_str());
610 outall();
611 exit(1);
612 }
613 }
614
615 // One more entry in the table
616 gLibraryReferencesList.push_back(cLabelEntry);
617 }
618 }
619 ++cItText;
620 }
621
622 return true;
623 }
624
625
626
627
628
629 int main(int argc,char **argv)
630 {
631 //
632 // Some initialization for the common library
633 //
634 SetApplicationParameters(
635 "Link65",
636 TOOL_VERSION_MAJOR,
637 TOOL_VERSION_MINOR,
638 "{ApplicationName} - Version {ApplicationVersion} - This program is a part of the OSDK\r\n"
639 "\r\n"
640 "Author:\r\n"
641 " Vagelis Blathras\r\n"
642 "Maintainer:\r\n"
643 " Mickael Pointier (aka Dbug)\r\n"
644 " dbug@defence-force.org\r\n"
645 " http://www.defence-force.org\r\n"
646 "\r\n"
647 "Purpose:\r\n"
648 " Gluing together a set of 6502 assembly source codes, and solve the external\r\n"
649 " references by looking up missing ones in the library files.\r\n"
650 "\r\n"
651 "Usage : {ApplicationName} [options] file1 file2 ...\n"
652 "Options:\r\n"
653 " -d : Directory to find library files.Next arg in line is the dir name.\r\n"
654 " e.g : link65 -d /usr/oric/lib/ test.s\r\n"
655 " -s : Directory to find source files.Next arg in line is the dir name.\r\n"
656 " -o : Output file. Default is go.s . Next arg in line is the file name.\r\n"
657 " e.g : link65 -o out.s test.s\r\n"
658 " -l : Print out defined labels.Usefull when building lib index files.\r\n"
659 " -v : Verbose output.\r\n"
660 " -q : Quiet mode.\r\n"
661 " -b : Bare linking (don't include header and tail).\r\n"
662 " -f : Insert #file directives (require expanded XA assembler).\r\n"
663 " -cn: Defines if comments should be kept (-c1) or removed (-c0) [Default]. \r\n"
664 );
665
666
667 // Init the path_library_files variable with default library directory and the output_file_name var with the default go.s
668 std::string path_library_files("lib6502\\");
669 std::string path_source_files("");
670 std::string output_file_name("go.s");
671
672 ArgumentParser cArgumentParser(argc,argv);
673
674 while (cArgumentParser.ProcessNextArgument())
675 {
676 if (cArgumentParser.IsSwitch("-q") || cArgumentParser.IsSwitch("-Q"))
677 {
678 // Quiet mode.
679 gFlagQuiet=true;
680 }
681 else
682 if (cArgumentParser.IsSwitch("-l") || cArgumentParser.IsSwitch("-L"))
683 {
684 // Print out defined labels (Useful when building lib index files)
685 gFlagLibrarian=true;
686 }
687 else
688 if (cArgumentParser.IsSwitch("-v") || cArgumentParser.IsSwitch("-V"))
689 {
690 // Verbose output.
691 gFlagVerbose=true;
692 }
693 else
694 if (cArgumentParser.IsSwitch("-d") || cArgumentParser.IsSwitch("-D"))
695 {
696 // Directory to find library files.Next arg in line is the dir name. e.g : link65 -d /usr/oric/lib/ test.s
697 if (!cArgumentParser.ProcessNextArgument() || !cArgumentParser.IsParameter())
698 {
699 printf(" Must have dir name after -d option\n");
700 exit(1);
701 }
702 path_library_files=cArgumentParser.GetStringValue();
703 }
704 else
705 if (cArgumentParser.IsSwitch("-s") || cArgumentParser.IsSwitch("-S"))
706 {
707 // Directory to find source files.Next arg in line is the dir name
708 if (!cArgumentParser.ProcessNextArgument() || !cArgumentParser.IsParameter())
709 {
710 printf(" Must have dir name after -s option\n");
711 exit(1);
712 }
713 path_source_files=cArgumentParser.GetStringValue();
714 }
715 else
716 if (cArgumentParser.IsSwitch("-o") || cArgumentParser.IsSwitch("-O"))
717 {
718 // Output file. Default is go.s . Next arg in line is the file name. e.g : link65 -o out.s test.s
719 if (!cArgumentParser.ProcessNextArgument() || !cArgumentParser.IsParameter())
720 {
721 printf(" Must have file name after -o option\n");
722 exit(1);
723 }
724 output_file_name=cArgumentParser.GetStringValue();
725 }
726 else
727 if (cArgumentParser.IsSwitch("-b") || cArgumentParser.IsSwitch("-B"))
728 {
729 // Bare linking, does not add "header" and "tail" to the list
730 gFlagIncludeHeader=false;
731 }
732 else
733 if (cArgumentParser.IsSwitch("-f") || cArgumentParser.IsSwitch("-F"))
734 {
735 // Enable the #file directive (require expanded XA assembler)
736 gFlagEnableFileDirective=true;
737 }
738 else
739 if (cArgumentParser.IsParameter())
740 {
741 // Not a switch
742 FileEntry_c cFileEntry;
743
744 if (gFlagIncludeHeader && gInputFileList.empty())
745 {
746 // header.s is the first file used.
747 // So reserve the 0 place in array for after option scanning, to put there the dir name too if needed.
748 cFileEntry.m_cFileName =path_library_files;
749 cFileEntry.m_cFileName +="header.s";
750 cFileEntry.m_nSortPriority=0;
751 gInputFileList.push_back(cFileEntry);
752 }
753
754 //
755 // Then we add the new file
756 //
757 cFileEntry.m_cFileName =path_source_files;
758 cFileEntry.m_cFileName +=cArgumentParser.GetStringValue();
759 cFileEntry.m_nSortPriority=1;
760 gInputFileList.push_back(cFileEntry);
761 }
762 else
763 if (cArgumentParser.IsSwitch("-c"))
764 {
765 //comments: [-c]
766 // 0 => remove comments
767 // 1 => keep comments
768 gFlagKeepComments=cArgumentParser.GetBooleanValue(false);
769 }
770 else
771 {
772 // Unknown argument
773 printf("Invalid option %s \n",cArgumentParser.GetRemainingStuff());
774 exit(1);
775 }
776 }
777
778 if (cArgumentParser.GetParameterCount())
779 {
780 ShowError(0);
781 }
782
783
784 if (!gFlagQuiet)
785 {
786 printf("\nLink65: 6502 Linker, by Vagelis Blathras. Version %d.%3d\n\n",TOOL_VERSION_MAJOR,TOOL_VERSION_MINOR);
787 }
788
789
790 if (gFlagIncludeHeader)
791 {
792 // Now put the tail.s .
793 // Give it nflist of 2 to put it last in file list after the sort
794 FileEntry_c cFileEntry;
795 cFileEntry.m_cFileName =path_library_files;
796 cFileEntry.m_cFileName +="tail.s";
797 cFileEntry.m_nSortPriority=2;
798 gInputFileList.push_back(cFileEntry);
799 }
800
801
802 // Open and scan Index file for labels - file pair list
803 LoadLibrary(path_library_files);
804
805 int state;
806 unsigned int i,j;
807 unsigned int k,l;
808
809 // Scanning files loop
810 for (k=0;k<gInputFileList.size();k++)
811 {
812 // Skip header.s file if gFlagLibrarian option is on
813 if (gFlagLibrarian && k == 0)
814 {
815 k=1;
816 }
817
818 //char filename[255];
819 //strcpy(filename,gInputFileList[k].m_cFileName.c_str());
820 ParseFile(gInputFileList[k].m_cFileName);
821
822 //
823 // Check if used labels are defined inside the files
824 //
825 std::vector<ReferencedLabelEntry_c>::iterator cItReferenced=gReferencedLabelsList.begin();
826 while (cItReferenced!=gReferencedLabelsList.end())
827 {
828 ReferencedLabelEntry_c& cLabelEntry=*cItReferenced;
829 std::set<std::string>::iterator cIt=gDefinedLabelsList.find(cLabelEntry.label_name);
830 if (cIt!=gDefinedLabelsList.end())
831 {
832 // Found the label in the definition list
833 cLabelEntry.m_bIsResolved=true;
834 }
835 ++cItReferenced;
836 }
837
838 if (!gFlagLibrarian)
839 {
840 // Check for not resolved labels.
841 // If defined in lib file index then insert their file right after in the list
842 for (i=0;i<gReferencedLabelsList.size();i++)
843 {
844 // Unresolved label and -l option off. If -l option is on don't care
845 ReferencedLabelEntry_c& cReferencedLabelEntry=gReferencedLabelsList[i];
846 if (!cReferencedLabelEntry.m_bIsResolved)
847 {
848 // Act for unresolved label
849 for (j=0;j<gLibraryReferencesList.size();j++)
850 {
851 LabelEntry_c& cLabelEntry=gLibraryReferencesList[j];
852 // If in lib file index, take file and put it in gInputFileList if not already there
853 if (cReferencedLabelEntry.label_name==cLabelEntry.label_name)
854 {
855 bool labstate=true;
856 for (l=0;l<gInputFileList.size();l++)
857 {
858 FileEntry_c& cFileEntry=gInputFileList[l];
859 if (cFileEntry.m_cFileName==cLabelEntry.file_name)
860 {
861 labstate=false;
862 break;
863 }
864 }
865
866 // Not present : labstate == 1 , insert file in list
867 if (labstate)
868 {
869 FileEntry_c cNewEntry;
870 gInputFileList.push_back(cNewEntry);
871
872 // NICE TRICK : Insert lib file in file list to be processed immediately.
873 // With this labels used by the lib file will be resolved, without the need for multiple passes
874 for (l=gInputFileList.size()-1;l>k+1;l--)
875 {
876 gInputFileList[l]=gInputFileList[l-1];
877 }
878 FileEntry_c& cFileEntry=gInputFileList[k+1];
879 cFileEntry.m_cFileName =cLabelEntry.file_name;
880 cFileEntry.m_nSortPriority =1;
881 }
882 else
883 {
884 break;
885 }
886 }
887 }
888 }
889 }
890 }
891 }
892
893 if (gFlagVerbose)
894 printf("\nend scanning files \n\n");
895
896 state=0;
897
898 if (gFlagLibrarian)
899 {
900 // If -l option just print labels and then exit
901 printf("\nDefined Labels : \n");
902
903 std::set<std::string>::iterator cIt=gDefinedLabelsList.begin();
904 while (cIt!=gDefinedLabelsList.end())
905 {
906 const std::string& cLabelName=*cIt;
907 printf("%s\n",cLabelName.c_str());
908 ++cIt;
909 }
910 outall();
911 return(0);
912 }
913 else
914 {
915 // Check for Unresolved external references.
916 // Print them all before exiting
917 for (i=0;i<gReferencedLabelsList.size();i++)
918 {
919 ReferencedLabelEntry_c& cReferencedLabelEntry=gReferencedLabelsList[i];
920 if (!cReferencedLabelEntry.m_bIsResolved)
921 {
922 printf("Unresolved external: %s\n",cReferencedLabelEntry.label_name.c_str());
923 state=1;
924 }
925 }
926 }
927
928 if (state == 1)
929 {
930 linkerror("Errors durink link.\n");
931 exit(1);
932 }
933
934
935 // Combine all files in list in a nice big juicy go.s or file selected
936 FILE *gofile=fopen(output_file_name.c_str(),"wb");
937 if (!gofile)
938 {
939 linkerror("Cannot open output file for writing\n");
940 exit(1);
941 }
942
943 //
944 // Add a simple header to the linked file
945 //
946 fprintf(gofile,
947 "//\r\n"
948 "// This file was generated by Link65 version %d.%03d \r\n"
949 "// Do not edit by hand\r\n"
950 "//\r\n"
951 ,TOOL_VERSION_MAJOR,TOOL_VERSION_MINOR);
952
953
954 // Get lines from all files and put them in go.s
955 for (k=0;k<gInputFileList.size();k++)
956 {
957 if (gFlagVerbose)
958 {
959 printf("Linking %s\n",gInputFileList[k].m_cFileName.c_str());
960 }
961
962 //
963 // Then insert the name of the included file
964 //
965 if (gFlagEnableFileDirective)
966 {
967 char current_directory[_MAX_PATH+1];
968 char filename[_MAX_PATH];
969
970 getcwd(current_directory,_MAX_PATH);
971 _splitpath(gInputFileList[k].m_cFileName.c_str(),0,0,filename,0);
972
973 fprintf(gofile,"#file \"%s\\%s.s\"\r\n",current_directory,filename);
974 }
975
976 // Mike: The code should really reuse the previously loaded/parsed files
977 std::vector<std::string> cTextData;
978 if (!LoadText(gInputFileList[k].m_cFileName.c_str(),cTextData))
979 {
980 printf("\nCannot open %s \n",gInputFileList[k].m_cFileName.c_str());
981 outall();
982 exit(1);
983 }
984
985 std::vector<std::string>::const_iterator cItText=cTextData.begin();
986 while (cItText!=cTextData.end())
987 {
988 // Get line file and parse it
989 const std::string& cCurrentLine=*cItText;
990 if (gFlagKeepComments)
991 {
992 fprintf(gofile,"%s\r\n",cCurrentLine.c_str());
993 }
994 else
995 {
996 std::string cFilteredLine=FilterLine(cCurrentLine);
997 fprintf(gofile,"%s\r\n",cFilteredLine.c_str());
998 }
999 ++cItText;
1000 }
1001 }
1002
1003 outall();
1004 return(0);
1005 }

  ViewVC Help
Powered by ViewVC 1.1.26