PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/polyml.5.4.1/libpolyml/mpoly.cpp

#
C++ | 301 lines | 212 code | 39 blank | 50 comment | 41 complexity | 9de0d0e71d22e86543f6aae5105902f0 MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-2.0
  1. /*
  2. Title: Main program
  3. Copyright (c) 2000-7
  4. Cambridge University Technical Services Limited
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 of the License, or (at your option) any later version.
  9. This library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with this library; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. */
  17. #ifdef HAVE_CONFIG_H
  18. #include "config.h"
  19. #elif defined(WIN32)
  20. #include "winconfig.h"
  21. #else
  22. #error "No configuration file"
  23. #endif
  24. #ifdef HAVE_STDIO_H
  25. #include <stdio.h>
  26. #endif
  27. #ifdef HAVE_STDLIB_H
  28. #include <stdlib.h>
  29. #endif
  30. #ifdef HAVE_STRING_H
  31. #include <string.h>
  32. #endif
  33. #ifdef HAVE_ASSERT_H
  34. #include <assert.h>
  35. #define ASSERT(x) assert(x)
  36. #else
  37. #define ASSERT(x) 0
  38. #endif
  39. #ifdef HAVE_TCHAR_H
  40. #include <tchar.h>
  41. #endif
  42. #include "globals.h"
  43. #include "sys.h"
  44. #include "gc.h"
  45. #include "run_time.h"
  46. #include "machine_dep.h"
  47. #include "version.h"
  48. #include "diagnostics.h"
  49. #include "processes.h"
  50. #include "mpoly.h"
  51. #include "scanaddrs.h"
  52. #include "save_vec.h"
  53. #include "../polyexports.h"
  54. #include "memmgr.h"
  55. #include "pexport.h"
  56. #ifdef WINDOWS_PC
  57. #include "Console.h"
  58. #endif
  59. static void InitHeaderFromExport(exportDescription *exports);
  60. NORETURNFN(static void Usage(const char *message));
  61. // Return the entry in the io vector corresponding to the Poly system call.
  62. PolyWord *IoEntry(unsigned sysOp)
  63. {
  64. MemSpace *space = gMem.IoSpace();
  65. return space->bottom + sysOp * IO_SPACING;
  66. }
  67. struct _userOptions userOptions;
  68. UNSIGNEDADDR exportTimeStamp;
  69. static unsigned hsize, isize, msize;
  70. struct __argtab {
  71. const char *argName, *argHelp;
  72. unsigned scale, *argVal;
  73. } argTable[] =
  74. {
  75. { "-H", "Initial heap size (MB)", 1024, &hsize }, // Leave this for the moment
  76. { "--heap", "Initial heap size (MB)", 1024, &hsize },
  77. { "--immutable", "Initial size of immutable buffer (MB)", 1024, &isize },
  78. { "--mutable", "Initial size of mutable buffer(MB)", 1024, &msize },
  79. { "--debug", "Debug options", 1, &userOptions.debug }
  80. };
  81. /* In the Windows version this is called from WinMain in Console.c */
  82. int polymain(int argc, char **argv, exportDescription *exports)
  83. {
  84. /* Get arguments. */
  85. memset(&userOptions, 0, sizeof(userOptions)); /* Reset it */
  86. // Get the program name for CommandLine.name. This is allowed to be a full path or
  87. // just the last component so we return whatever the system provides.
  88. if (argc > 0)
  89. userOptions.programName = argv[0];
  90. else
  91. userOptions.programName = ""; // Set it to a valid empty string
  92. char *importFileName = 0;
  93. userOptions.debug = 0;
  94. userOptions.noDisplay = false;
  95. userOptions.user_arg_count = 0;
  96. userOptions.user_arg_strings = (char**)malloc(argc * sizeof(char*)); // Enough room for all of them
  97. // Process the argument list removing those recognised by the RTS and adding the
  98. // remainder to the user argument list.
  99. for (int i = 1; i < argc; i++)
  100. {
  101. if (argv[i][0] == '-')
  102. {
  103. bool argUsed = false;
  104. for (unsigned j = 0; j < sizeof(argTable)/sizeof(argTable[0]); j++)
  105. {
  106. unsigned argl = strlen(argTable[j].argName);
  107. if (strncmp(argv[i], argTable[j].argName, argl) == 0)
  108. {
  109. char *p;
  110. if (strlen(argv[i]) == argl)
  111. { // If it has used all the argument pick the next
  112. i++;
  113. p = argv[i];
  114. }
  115. else
  116. {
  117. p = argv[i]+argl;
  118. if (*p == '=') p++; // Skip an equals sign
  119. }
  120. if (i >= argc)
  121. printf("Incomplete %s option\n", argTable[j].argName);
  122. else
  123. *(argTable[j].argVal) = atoi(p) * argTable[j].scale;
  124. argUsed = true;
  125. break;
  126. }
  127. }
  128. if (! argUsed) // Add it to the user args.
  129. userOptions.user_arg_strings[userOptions.user_arg_count++] = argv[i];
  130. }
  131. else if (exports == 0 && importFileName == 0)
  132. importFileName = argv[i];
  133. else
  134. userOptions.user_arg_strings[userOptions.user_arg_count++] = argv[i];
  135. }
  136. if (exports == 0 && importFileName == 0)
  137. Usage("Missing import file name");
  138. /* initialise the run-time system before opening the database */
  139. init_run_time_system();
  140. CreateHeap(hsize, isize, msize);
  141. PolyObject *rootFunction = 0;
  142. if (exports != 0)
  143. {
  144. InitHeaderFromExport(exports);
  145. rootFunction = (PolyObject *)exports->rootFunction;
  146. }
  147. else
  148. {
  149. if (importFileName != 0)
  150. rootFunction = ImportPortable(importFileName);
  151. if (rootFunction == 0)
  152. exit(1);
  153. }
  154. /* Initialise the interface vector. */
  155. machineDependent->InitInterfaceVector(); /* machine dependent entries. */
  156. // This word has a zero value and is used for null strings.
  157. add_word_to_io_area(POLY_SYS_emptystring, PolyWord::FromUnsigned(0));
  158. // This is used to represent zero-sized vectors.
  159. // N.B. This assumes that the word before is zero because it's
  160. // actually the length word we want to be zero here.
  161. add_word_to_io_area(POLY_SYS_nullvector, PolyWord::FromUnsigned(0));
  162. /* The standard input and output streams are persistent i.e. references
  163. to the the standard input in one session will refer to the standard
  164. input in the next. */
  165. add_word_to_io_area(POLY_SYS_stdin, PolyWord::FromUnsigned(0));
  166. add_word_to_io_area(POLY_SYS_stdout, PolyWord::FromUnsigned(1));
  167. add_word_to_io_area(POLY_SYS_stderr, PolyWord::FromUnsigned(2));
  168. re_init_run_time_system();
  169. // Set up the initial process to run the root function.
  170. processes->BeginRootThread(rootFunction);
  171. finish(0);
  172. /*NOTREACHED*/
  173. return 0; /* just to keep lint happy */
  174. }
  175. void Uninitialise(void)
  176. // Close down everything and free all resources. Stop any threads or timers.
  177. {
  178. uninit_run_time_system();
  179. }
  180. void finish (int n)
  181. {
  182. // Make sure we don't get any interrupts once the destructors are
  183. // applied to globals or statics.
  184. Uninitialise();
  185. #if defined(WINDOWS_PC)
  186. ExitThread(n);
  187. #else
  188. exit (n);
  189. #endif
  190. }
  191. // Print a message and exit if an argument is malformed.
  192. void Usage(const char *message)
  193. {
  194. if (message)
  195. printf("%s\n", message);
  196. for (unsigned j = 0; j < sizeof(argTable)/sizeof(argTable[0]); j++)
  197. {
  198. printf("%s <%s>\n", argTable[j].argName, argTable[j].argHelp);
  199. }
  200. fflush(stdout);
  201. #if defined(WINDOWS_PC)
  202. if (useConsole)
  203. {
  204. MessageBox(hMainWindow, _T("Poly/ML has exited"), _T("Poly/ML"), MB_OK);
  205. }
  206. #endif
  207. exit (1);
  208. }
  209. // Return a string containing the argument names. Can be printed out in response
  210. // to a --help argument. It is up to the ML application to do that since it may well
  211. // want to produce information about any arguments it chooses to process.
  212. char *RTSArgHelp(void)
  213. {
  214. static char buff[2000];
  215. char *p = buff;
  216. for (unsigned j = 0; j < sizeof(argTable)/sizeof(argTable[0]); j++)
  217. {
  218. int spaces = sprintf(p, "%s <%s>\n", argTable[j].argName, argTable[j].argHelp);
  219. p += spaces;
  220. }
  221. ASSERT((unsigned)(p - buff) < (unsigned)sizeof(buff));
  222. return buff;
  223. }
  224. void InitHeaderFromExport(exportDescription *exports)
  225. {
  226. // Check the structure sizes stored in the export structure match the versions
  227. // used in this library.
  228. if (exports->structLength != sizeof(exportDescription) ||
  229. exports->memTableSize != sizeof(memoryTableEntry) ||
  230. exports->rtsVersion < FIRST_supported_version ||
  231. exports->rtsVersion > LAST_supported_version)
  232. {
  233. #if (FIRST_supported_version == LAST_supported_version)
  234. Exit("The exported object file has version %0.2f but this library supports %0.2f",
  235. ((float)exports->rtsVersion) / 100.0,
  236. ((float)FIRST_supported_version) / 100.0);
  237. #else
  238. Exit("The exported object file has version %0.2f but this library supports %0.2f-%0.2f",
  239. ((float)exports->rtsVersion) / 100.0,
  240. ((float)FIRST_supported_version) / 100.0,
  241. ((float)LAST_supported_version) / 100.0);
  242. #endif
  243. }
  244. // We could also check the RTS version and the architecture.
  245. exportTimeStamp = exports->timeStamp; // Needed for load and save.
  246. memoryTableEntry *memTable = exports->memTable;
  247. for (unsigned i = 0; i < exports->memTableEntries; i++)
  248. {
  249. // Construct a new space for each of the entries.
  250. if (i == exports->ioIndex)
  251. (void)gMem.InitIOSpace((PolyWord*)memTable[i].mtAddr, memTable[i].mtLength/sizeof(PolyWord));
  252. else
  253. (void)gMem.NewPermanentSpace((PolyWord*)memTable[i].mtAddr,
  254. memTable[i].mtLength/sizeof(PolyWord), (memTable[i].mtFlags & MTF_WRITEABLE) != 0,
  255. (memTable[i].mtFlags & MTF_NO_OVERWRITE) != 0, memTable[i].mtIndex);
  256. }
  257. }