1 using System;
  2 using System.IO;
  3 using System.Collections;
  4 using cmsx.object;
  5 
  6 public nothrow const char* Version()
  7 {
  8     return "4.0.0";
  9 }
 10 
 11 void PrintHelp()
 12 {
 13     Console.Out() << "Cmajor System X Linker version " << Version() << endl();
 14     Console.Out() << "Usage: cmsxlink [options] { file.o | file.a }" << endl();
 15     Console.Out() << "Options:" << endl();
 16     Console.Out() << "--help (-h)" << endl();
 17     Console.Out() << "  Print help." << endl();
 18     Console.Out() << "--verbose (-v)" << endl();
 19     Console.Out() << "  Be verbose." << endl();
 20     Console.Out() << "--out=FILE (-o=FILE)" << endl();
 21     Console.Out() << "  Set output file name to FILE." << endl();
 22     Console.Out() << "  Default is 'a.out'." << endl();
 23     Console.Out() << "--clsid=FILE (-c=FILE)" << endl();
 24     Console.Out() << "  Read class id's from FILE." << endl();
 25     Console.Out() << "--min-stack-size=MINSTACKSIZE (-m=MINSTACKSIZE)" << endl();
 26     Console.Out() << "  Set minimum size stack size to MINSTACKSIZE bytes." << endl();
 27     Console.Out() << "  Default minimum stack size is 64 kilobytes." << endl();
 28     Console.Out() << "--max-stack-size=MAXSTACKSIZE (-s=MAXSTACKSIZE)" << endl();
 29     Console.Out() << "  Set maximum size stack size to MAXSTACKSIZE bytes." << endl();
 30     Console.Out() << "  Default maximum stack size is 4 megabytes." << endl();
 31     Console.Out() << "--stack-size-increment=INCREMENT (-i=INCREMENT)" << endl();
 32     Console.Out() << "  Set stack size increment to INCREMENT bytes." << endl();
 33     Console.Out() << "  Default stack size increment is 64 kilobytes." << endl();
 34     Console.Out() << "--debug (-d)" << endl();
 35     Console.Out() << "  Debug linking." << endl();
 36 }
 37 
 38 int main(int argcconst char** argv)
 39 {
 40     try
 41     {
 42         string cmajorRootDir = RtGetEnvironmentVariable("CMAJOR_ROOT");
 43         if (cmajorRootDir.IsEmpty())
 44         {
 45             throw Exception("please set CMAJOR_ROOT environment variable to /path/to/cmajor directory");
 46         }
 47         string mainPath = Path.Combine(cmajorRootDir"projects/cmsx/build/main/lib/Main.o");
 48         List<string> fileNames;
 49         fileNames.Add(GetFullPath(mainPath));
 50         bool verbose = false;
 51         bool debug = false;
 52         ulong minStackSize = 64u * cast<ulong>(1024u);
 53         ulong maxStackSize = 4u * cast<ulong>(1024u) * cast<ulong>(1024u);
 54         ulong stackSizeIncrement = 64u * cast<ulong>(1024u);
 55         ulong initialPoolSize = 4u * cast<ulong>(1024u);
 56         string executableFileName = GetFullPath("a.out");
 57         string clsIdFileName;
 58         bool userFilesGiven = false;
 59         bool removeUnusedCode = true;
 60         for (int i = 1; i < argc; ++i;)
 61         {
 62             string arg = argv[i];
 63             if (arg.StartsWith("--"))
 64             {
 65                 if (arg == "--help")
 66                 {
 67                     PrintHelp();
 68                     return 1;
 69                 }
 70                 else if (arg == "--verbose")
 71                 {
 72                     verbose = true;
 73                 }
 74                 else if (arg == "--debug")
 75                 {
 76                     debug = true;
 77                 }
 78                 else if (arg.StartsWith("--out="))
 79                 {
 80                     executableFileName = GetFullPath(arg.Substring(6));;
 81                 }
 82                 else if (arg.StartsWith("--clsid="))
 83                 {
 84                     clsIdFileName = GetFullPath(arg.Substring(8));
 85                 }
 86                 else if (arg.StartsWith("--min-stack-size="))
 87                 {
 88                     minStackSize = ParseULong(arg.Substring(17));
 89                 }
 90                 else if (arg.StartsWith("--max-stack-size="))
 91                 {
 92                     maxStackSize = ParseULong(arg.Substring(17));
 93                 }
 94                 else if (arg.StartsWith("--stack-size-increment="))
 95                 {
 96                     stackSizeIncrement = ParseULong(arg.Substring(23));
 97                 }
 98                 else
 99                 {
100                     throw Exception("unknown option '" + arg + "'");
101                 }
102             }
103             else if (arg.StartsWith("-"))
104             {
105                 if (arg.StartsWith("-o="))
106                 {
107                     executableFileName = GetFullPath(arg.Substring(3));
108                 }
109                 else if (arg.StartsWith("-c="))
110                 {
111                     clsIdFileName = GetFullPath(arg.Substring(3));
112                 }
113                 else if (arg.StartsWith("-m="))
114                 {
115                     minStackSize = ParseULong(arg.Substring(3));
116                 }
117                 else if (arg.StartsWith("-s="))
118                 {
119                     maxStackSize = ParseULong(arg.Substring(3));
120                 }
121                 else if (arg.StartsWith("-i="))
122                 {
123                     stackSizeIncrement = ParseULong(arg.Substring(3));
124                 }
125                 else
126                 {
127                     string options = arg.Substring(1);
128                     if (options.IsEmpty())
129                     {
130                         throw Exception("unknown option '" + arg + "'");
131                     }
132                     else
133                     {
134                         for (char o : options)
135                         {
136                             if (o == 'h')
137                             {
138                                 PrintHelp();
139                                 return 1;
140                             }
141                             else if (o == 'v')
142                             {
143                                 verbose = true;
144                             }
145                             else if (o == 'd')
146                             {
147                                 debug = true;
148                             }
149                             else
150                             {
151                                 throw Exception("unknown option '-" + string(o) + "'");
152                             }
153                         }
154                     }
155                 }
156             }
157             else
158             {
159                 fileNames.Add(GetFullPath(arg));
160                 userFilesGiven = true;
161             }
162         }
163         if (executableFileName.IsEmpty())
164         {
165             PrintHelp();
166             throw Exception("output executable file name missing");
167         }
168         if (!userFilesGiven)
169         {
170             PrintHelp();
171             throw Exception("no object or library files given");
172         }
173         if (verbose)
174         {
175             Console.Out() << "Cmajor System X Linker version " << Version() << endl();
176         }
177         ClassIdMap classIdMap;
178         if (!clsIdFileName.IsEmpty())
179         {
180             classIdMap.Read(clsIdFileName);
181         }
182         List<UniquePtr<BinaryFile>> binaryFiles;
183         for (const string& fileName : fileNames)
184         {
185             if (verbose)
186             {
187                 Console.Out() << "> " << fileName << endl();
188             }
189             UniquePtr<BinaryFile> binaryFile = ReadBinaryFile(fileName);
190             binaryFile->AddSymbolsToAddressMap();
191             binaryFiles.Add(Rvalue(binaryFile));
192         }
193         if (minStackSize > maxStackSize)
194         {
195             throw Exception("error: minimum stack size (" + ToString(minStackSize) + ") is greater than maximum stack size (" + ToString(maxStackSize) + ")");
196         }
197         if (stackSizeIncrement > maxStackSize - minStackSize)
198         {
199             throw Exception("error: stack size increment (" + ToString(stackSizeIncrement) + ") is greater than difference of maximum stack size (" + ToString(maxStackSize) + 
200                 ") and minimum stack size (" + ToString(minStackSize) + ")");
201         }
202         ExecutableFile executable(executableFileNametrueminStackSizemaxStackSizestackSizeIncrementinitialPoolSize);
203         Link(executablebinaryFilesclassIdMapremoveUnusedCodedebug);
204         if (verbose)
205         {
206             Console.Out() << "==> " << executableFileName << endl();
207         }
208     }
209     catch (const Exception& ex)
210     {
211         Console.Error() << ex.Message() << endl();
212         return 1;
213     }
214     return 0;
215 }