1/* BEGIN LICENSE BLOCK 2 * Version: CMPL 1.1 3 * 4 * The contents of this file are subject to the Cisco-style Mozilla Public 5 * License Version 1.1 (the "License"); you may not use this file except 6 * in compliance with the License. You may obtain a copy of the License 7 * at www.eclipse-clp.org/license. 8 * 9 * Software distributed under the License is distributed on an "AS IS" 10 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 11 * the License for the specific language governing rights and limitations 12 * under the License. 13 * 14 * The Original Code is The ECLiPSe Constraint Logic Programming System. 15 * The Initial Developer of the Original Code is Cisco Systems, Inc. 16 * Portions created by the Initial Developer are 17 * Copyright (C) 1989-2006 Cisco Systems, Inc. All Rights Reserved. 18 * 19 * Contributor(s): 20 * 21 * END LICENSE BLOCK */ 22 23#ifndef _WIN32 24 25/* 26 * SEPIA C SOURCE MODULE 27 * 28 * VERSION $Id: main.c,v 1.6 2011/04/10 14:11:38 jschimpf Exp $ 29 */ 30 31/* 32 * 33 * SEPIA main() procedure. 34 * 35 * It initialises the system, interprets the command line options, 36 * allocates heap and stacks, and eventually 37 * calls the Prolog emulator with an appropriate goal. 38 */ 39 40#include "config.h" 41#include "os_support.h" 42 43#include "sepia.h" 44#include "types.h" 45#include "embed.h" 46#include "error.h" 47#include "mem.h" 48#include "dict.h" 49#include "emu_export.h" 50#include "module.h" 51#include "property.h" 52 53#include <stdio.h> 54#include <errno.h> 55 56#ifdef STDC_HEADERS 57#include <stdlib.h> 58#endif 59 60#ifdef HAVE_STRING_H 61#include <string.h> 62#else 63extern char * strcpy(); 64extern char * strcat(); 65#endif 66 67#ifndef ACCESS_IN_UNISTD 68#include <sys/file.h> 69#endif 70 71#if defined(BARRELFISH) 72#include <vfs/vfs.h> 73#endif 74 75#ifdef STRTOL_UNDEF 76extern long strtol(const char *, char **, int); 77#endif 78 79#define KB 1024 80#define MIN_LOCAL 100*KB 81#define MIN_GLOBAL 210*KB 82#define MIN_PRIVATE 210*KB 83#define MIN_SHARED 210*KB 84 85#define MAX_MEMORY (SIGN_BIT/8*15) /* 15/16 of the address space */ 86 87#define BOOTFILES 20 88 89 90/* 91 * EXTERN declarations 92 */ 93 94extern int eclipse_global_init(int init_flags); 95extern int eclipse_boot(char *initfile); 96extern void msg_trigger(); 97extern int it_emulc(value v_sig, type t_sig); 98 99/* 100 * LOCAL declarations 101 */ 102 103static void main_panic(const char *what, const char *where), 104 usage(char *opt); 105 106 107/* 108 * GLOBAL variable definitions 109 */ 110 111/* 112 * To avoid infinite loops when the memory is corrupted, this flag 113 * is set when SEPIA did not manage it to print the prompt and start user query 114 * after a reset. 0 means ok, 1 is after a reset and before a query. 115 */ 116static int memory_corrupted = 0; 117 118jmp_buf reset; 119 120static uword 121sizearg(char *arg) 122{ 123 int last = strlen(arg) -1; 124 uword multiple = 0; 125 uword size; 126 127 switch(arg[last]) 128 { 129 case 'k': 130 case 'K': 131 multiple = KB; 132 arg[last] = '\000'; 133 break; 134 case 'm': 135 case 'M': 136 multiple = KB * KB; 137 arg[last] = '\000'; 138 break; 139 case 'g': 140 case 'G': 141 multiple = KB * KB * KB; 142 arg[last] = '\000'; 143 break; 144 case '0': case '1': case '2': case '3': case '4': 145 case '5': case '6': case '7': case '8': case '9': 146 multiple = KB; 147 break; 148 default: 149 usage(arg); 150 } 151 size = (uword) atol(arg); 152 return (size > MAX_MEMORY/multiple) ? 0 : size * multiple; 153} 154 155int 156main(int argc, char **argv) 157{ 158 char bootfile_buf[MAX_PATH_LEN]; 159 char * initfile = (char *) 0; 160 char * eclipsedir = (char *) 0; 161 int c, new_argc; 162 pword goal, module; 163 int err; 164 int init_flags = INIT_SHARED|INIT_PRIVATE|INIT_ENGINE|INIT_PROCESS; 165 unsigned startup_delay = 0; 166 int vm_options = 0; 167 char * session, * nsrv_hostname; 168 unsigned nsrv_port_number; 169 170#if defined(BARRELFISH) 171 vfs_init(); 172#endif 173 174#ifdef PROFILE 175 moncontrol(0); /* disable profiling by default */ 176#endif 177 178 /* 179 * collect information from the command line 180 * remove some internally used arguments from the command line 181 */ 182 for (c = new_argc = 1; c < argc; ) 183 { 184 if (argv[c][0] == '-' && argv[c][2] == 0) /* single char opt */ 185 { 186 switch (argv[c][1]) 187 { 188 case 'a': /* -a <worker> <session> 189 <nsrv_hostname> <nsrv_port_no> */ 190 if (++c + 4 > argc) usage(argv[c-1]); 191 ec_options.parallel_worker = atoi(argv[c++]); 192 session = argv[c++]; 193 nsrv_hostname = argv[c++]; 194 nsrv_port_number = atoi(argv[c++]); 195 break; 196 197 case 'c': /* -c <shared_map_file> */ 198 if (++c + 1 > argc) usage(argv[c-1]); 199 ec_options.mapfile = argv[c++]; 200 ec_options.allocation = ALLOC_FIXED; 201 init_flags &= ~INIT_SHARED; 202 break; 203 204 case 'm': /* -m <shared_map_file> */ 205 if (++c + 1 > argc) usage(argv[c-1]); 206 ec_options.mapfile = argv[c++]; 207 ec_options.allocation = ALLOC_FIXED; 208 break; 209 210 case 'g': /* -g <size> */ 211 argv[new_argc++] = argv[c]; /* shift */ 212 if (++c + 1 > argc) usage(argv[c-1]); 213 argv[new_argc++] = argv[c]; /* shift */ 214 ec_options.globalsize = sizearg(argv[c++]); 215 if (ec_options.globalsize < MIN_GLOBAL) { 216 ec_bad_exit("ECLiPSe: Global stack size out of range."); 217 } 218 break; 219 220 case 'd': /* -d <n> */ 221 /* delay worker startup by <n> seconds */ 222 if (++c + 1 > argc) usage(argv[c-1]); 223 startup_delay = atoi(argv[c++]); 224 if (startup_delay == 0) 225 ec_options.io_option = OWN_IO; /* every worker has its own i/o */ 226 else 227 sleep(startup_delay); 228 break; 229 230 case 'D': /* -D <eclipsedir> */ 231 if (++c + 1 > argc) usage(argv[c-1]); 232 eclipsedir = argv[c++]; 233 break; 234 235 case 'l': /* -l <size> */ 236 argv[new_argc++] = argv[c]; /* shift */ 237 if (++c + 1 > argc) usage(argv[c-1]); 238 argv[new_argc++] = argv[c]; /* shift */ 239 ec_options.localsize = sizearg(argv[c++]); 240 if (ec_options.localsize < MIN_LOCAL) { 241 ec_bad_exit("ECLiPSe: local stack size out of range."); 242 } 243 break; 244 245 case 'h': /* -h <size> */ 246 argv[new_argc++] = argv[c]; /* shift */ 247 if (++c + 1 > argc) usage(argv[c-1]); 248 argv[new_argc++] = argv[c]; /* shift */ 249 ec_options.privatesize = sizearg(argv[c++]); 250 if (ec_options.privatesize < MIN_PRIVATE) { 251 ec_bad_exit("ECLiPSe: Private heap size out of range."); 252 } 253 break; 254 255 case 's': /* -s <size> */ 256 argv[new_argc++] = argv[c]; /* shift */ 257 if (++c + 1 > argc) usage(argv[c-1]); 258 argv[new_argc++] = argv[c]; /* shift */ 259 ec_options.sharedsize = sizearg(argv[c++]); 260 if (ec_options.sharedsize < MIN_SHARED) { 261 ec_bad_exit("ECLiPSe: Shared heap size out of range."); 262 } 263 break; 264 265 case 'o': /* enable oracles */ 266 c += 1; 267 vm_options = ORACLES_ENABLED; 268 break; 269 270 case 'p': 271 argv[new_argc++] = argv[c]; /* shift */ 272 if (++c + 1 > argc) usage(argv[c-2]); 273 argv[new_argc++] = argv[c]; /* shift */ 274 ec_options.option_p = atoi(argv[c++]); 275 break; 276 277 /* Options processed by Prolog-level code */ 278 case 'b': /* -b <bootfile> */ 279 case 'f': /* -f <file> */ 280 case 'e': /* -e <goal> */ 281 case 'L': /* -L <language> */ 282 case 't': /* -t <module> */ 283 argv[new_argc++] = argv[c]; /* shift */ 284 if (++c + 1 > argc) usage(argv[c-1]); 285 argv[new_argc++] = argv[c++]; /* shift */ 286 break; 287 288 case '-': /* -- give the rest to Prolog */ 289 for (; c < argc;) 290 argv[new_argc++] = argv[c++]; 291 break; 292 293 default: /* unknown: error */ 294 usage(argv[c]); 295 break; 296 } 297 } 298 else if (!strcmp(argv[c], "-debug_level")) 299 { 300 if (++c + 1 > argc) usage(argv[c-1]); 301 ec_options.debug_level = atoi(argv[c++]); 302 } 303 else if (!strcmp(argv[c], "-layout")) 304 { 305 int lflags = 0; 306 char *from = 0; 307 char *to = 0; 308 long increment = 0; 309 310 if (++c + 1 <= argc) 311 lflags = (int) strtol(argv[c++], (char **) 0, 16); 312 if (c + 1 <= argc) 313 increment = strtol(argv[c++], (char **) 0, 16); 314 if (c + 1 <= argc) 315 from = (char *) strtol(argv[c++], (char **) 0, 16); 316 if (c + 1 <= argc) 317 to = (char *) strtol(argv[c++], (char **) 0, 16); 318 319 if (ec_options.allocation == ALLOC_FIXED) 320 mem_layout(); 321#ifdef HAVE_MMAP 322 ec_layout(lflags, from, to, increment); 323#else 324 ec_bad_exit("ECLiPSe: The -layout scan is not supported without\nmemory mapping."); 325#endif 326 } 327 else if (!strcmp(argv[c], "-norl")) 328 { 329 argv[new_argc++] = argv[c++]; /* shift */ 330 ec_options.rl = 0; 331 } 332 else /* raise error unless preceeded by a -- option */ 333 { 334 usage(argv[c]); 335 } 336 } 337 338 /*---------------------------------------------------------------- 339 * Initialize private heap as early as possible 340 * (must be before setup_mps()) 341 *----------------------------------------------------------------*/ 342 malloc_init(); 343 irq_lock_init(delayed_break); 344 345 /*---------------------------------------------------------------- 346 * Init message passing system 347 *----------------------------------------------------------------*/ 348 if (ec_options.parallel_worker) 349 { 350 setup_mps(ec_options.parallel_worker, session, nsrv_hostname, 351 nsrv_port_number, init_flags & INIT_SHARED); 352 } 353 354 /*---------------------------------------------------------------- 355 * Make the connection to the shared heap, if any. 356 * Because of mmap problems on some machines this should 357 * happen AFTER initializing the message passing system. 358 *----------------------------------------------------------------*/ 359 mem_init(init_flags); /* depends on -c and -m options */ 360 361 362 /*---------------------------------------------------------------- 363 * Init parallel scheduler etc. 364 *----------------------------------------------------------------*/ 365 if (ec_options.parallel_worker) 366 { 367 parallel_init(init_flags); 368 } 369 370 /*---------------------------------------------------------------- 371 * Init the low-level I/O stuff, ie the part which should 372 * really not be done by eclipse itself... 373 *----------------------------------------------------------------*/ 374 /* char_io_init(); does not yet exist */ 375 376 377 /*---------------------------------------------------------------- 378 * Entry point after longjmp(reset) 379 *----------------------------------------------------------------*/ 380 381 switch (setjmp(reset)) 382 { 383 case 0: /* raw boot or -r from above */ 384 break; 385 case 3: /* restore program state */ 386 case 2: 387 init_flags = REINIT_SHARED|INIT_ENGINE|INIT_PRIVATE; 388 break; 389 case 4: /* restore execution state */ 390 init_flags = REINIT_SHARED|INIT_PRIVATE; 391 break; 392 case 1: /* reset after fatal error */ 393 default: 394 if (!(GlobalFlags & HEAP_READY) || ec_options.parallel_worker) 395 { 396 (void) ec_cleanup(); 397 exit(-1); 398 } 399 init_flags = INIT_ENGINE; 400 switch (memory_corrupted++) 401 { 402 case 0: 403 break; 404 405 case 1: 406 /* try to print a message */ 407 memory_corrupted = 2; 408 ec_bad_exit("ECLiPSe: Fatal error, memory corrupted."); 409 /* fall to */ 410 case 2: 411 /* we couldn't even print the message */ 412 exit(-1); 413 } 414 break; 415 } 416 417 418 /* 419 * set up our own panic function which longjumps back to reset 420 * To access command line through global variabes 421 */ 422 ec_options.user_panic = main_panic; 423 ec_options.Argc = new_argc; 424 ec_options.Argv = argv; 425 ec_options.eclipse_home = (char *) 0; 426 ec_options.init_flags = init_flags; 427 if (eclipsedir) 428 ec_options.eclipse_home = eclipsedir; 429 430 431 /* 432 * Init the global (shared) eclipse structures, dictionary, code... 433 * Maybe load a saved state. 434 * Note that we don't have an engine yet! 435 */ 436 437 eclipse_global_init(init_flags); 438 439 440 /*---------------------------------------------------------------- 441 * Setup the Prolog engine 442 *----------------------------------------------------------------*/ 443 444 /* 445 * If we have a PROG_AND_DATA saved state (execution state saved) 446 * we are finished and enter the emulator. 447 */ 448 if (!(init_flags & INIT_ENGINE)) 449 { 450 err = restart_emulc(); 451 (void) ec_cleanup(); 452 exit(err); 453 } 454 455 /* 456 * Initialize the Prolog engine 457 */ 458 emu_init(init_flags, vm_options); 459 460 /* 461 * If we are not running an already booted eclipse, 462 * compile $ECLIPSEDIR/lib/kernel.eco 463 */ 464 if (init_flags & INIT_SHARED) 465 { 466 char msg[1024]; 467 468 initfile = strcat(strcpy(bootfile_buf, ec_eclipse_home), "/lib/kernel.eco"); 469 if (ec_access(initfile, R_OK) < 0) 470 { 471 sprintf(msg, 472 "ECLiPSe: Can't find boot file %s!\nPlease check the setting of your ECLIPSEDIR environment variable\nor use the -D <dir> command line option.", 473 initfile); 474 ec_bad_exit(msg); 475 } 476 477 err = eclipse_boot(initfile); 478 if (err != PSUCCEED) 479 { 480 (void) ec_cleanup(); 481 exit(err); 482 } 483 } 484 485 if (init_flags & (INIT_SHARED|REINIT_SHARED)) 486 GlobalFlags |= HEAP_READY; /* for the other workers */ 487 488 goal = ec_term(ec_did("main",1), ec_long(init_flags & INIT_SHARED ? 0 : 1)); 489 module.val.did = d_.kernel_sepia; 490 module.tag.kernel = ModuleTag(d_.kernel_sepia); 491 492 if (ec_options.parallel_worker <= 1) /* only or first worker */ 493 { 494 err = main_emulc_noexit(goal.val, goal.tag, module.val, module.tag); 495 if (err == PYIELD) 496 { 497 memory_corrupted = 0; /* assume it's ok */ 498 ec_post_goal(ec_term(ec_did(":",2), ec_atom(ec_did("sepia_kernel",0)), 499 ec_atom(ec_did("standalone_toplevel",0)))); 500 do { 501 err = ec_resume(); 502 } while (err == PYIELD); 503 } 504 } 505 else 506 { 507 err = slave_emulc(); 508 } 509 ec_cleanup(); 510 exit(err); 511 /*NOTREACHED*/ 512} 513 514 515/* 516 * Print the warning about wrong usage and bad_exit. 517 * The argument is the bad option string. 518 */ 519/*ARGSUSED*/ 520static void 521usage(char *opt) 522{ 523 ec_bad_exit( 524"Usage:\n\ 525 -b <file> compile or load a file on startup (deprecated, same as -f)\n\ 526 -f <file> compile or load a file on startup (.ecl or .eco)\n\ 527 -e <goal> goal to execute (in Prolog syntax)\n\ 528 -g <kbytes> global+trail stack size\n\ 529 -l <kbytes> local+control stack size\n\ 530 -L <language> default language dialect\n\ 531 -h <kbytes> private heap size\n\ 532 -s <kbytes> shared heap size\n\ 533 -t <module> name of initial toplevel module\n\ 534 -d <seconds> delayed startup\n\ 535 -D <dir> installation directory\n\ 536 -- end of ECLiPSe options\n\ 537Parallel system only:\n\ 538 -w <num> number of parallel workers\n\ 539 -wmi popup worker manager interface\n\ 540 -wv verbose worker startup\n\ 541 -wx <exec> use specified worker executable\n\ 542Reserved:\n\ 543 -a <><><><>\n\ 544 -c <>\n\ 545 -m <>\n\ 546 -o \n\ 547 -r <>\n" 548 ); 549} 550 551static void 552main_panic(const char *what, const char *where) 553{ 554 fprintf(stderr, "\n*** ECLiPSe fatal error: %s",what); 555 556 if (where) 557 fprintf(stderr, " in %s",where); 558 559 fprintf(stderr, "\n"); 560 fflush(stderr); 561 562 longjmp(reset, 1); 563} 564 565 566#else /* _WIN32 */ 567 568/* 569 * ECLiPSe C SOURCE MODULE 570 * 571 * 572 * Simplified standalone main() for Windows 573 * 574 */ 575 576#include <windows.h> 577#include "eclipse.h" 578#include "os_support.h" 579 580 581#include <stdio.h> 582#include <errno.h> 583#include <setjmp.h> 584 585#ifdef STDC_HEADERS 586#include <stdlib.h> 587#include <string.h> 588#endif 589 590#ifndef ACCESS_IN_UNISTD 591#include <sys/file.h> 592#endif 593 594#ifdef STRTOL_UNDEF 595extern long strtol(); 596#endif 597 598#define KB 1024 599#define MIN_LOCAL 100*KB 600#define MIN_GLOBAL 210*KB 601#define MIN_PRIVATE 210*KB 602#define MIN_SHARED 210*KB 603 604#define MAX_MEMORY (SIGN_BIT/8*15) /* 15/16 of the address space */ 605 606/* 607 * LOCAL declarations 608 */ 609 610static void main_panic(char *, char *); 611static void usage(char *); 612 613 614/* 615 * GLOBAL variable definitions 616 */ 617 618/* 619 * To avoid infinite loops when the memory is corrupted, this flag 620 * is set when SEPIA did not manage it to print the prompt and start user query 621 * after a reset. 0 means ok, 1 is after a reset and before a query. 622 */ 623static int memory_corrupted = 0; 624 625jmp_buf reset; 626 627static uword 628sizearg(char *arg) 629{ 630 int last = strlen(arg) -1; 631 uword multiple = 0; 632 uword size; 633 634 switch(arg[last]) 635 { 636 case 'k': 637 case 'K': 638 multiple = KB; 639 arg[last] = '\000'; 640 break; 641 case 'm': 642 case 'M': 643 multiple = KB * KB; 644 arg[last] = '\000'; 645 break; 646 case 'g': 647 case 'G': 648 multiple = KB * KB * KB; 649 arg[last] = '\000'; 650 break; 651 case '0': case '1': case '2': case '3': case '4': 652 case '5': case '6': case '7': case '8': case '9': 653 multiple = KB; 654 break; 655 default: 656 usage(arg); 657 } 658 size = (uword) atol(arg); 659 return (size > MAX_MEMORY/multiple) ? 0 : size * multiple; 660} 661 662main(int argc, char **argv) 663{ 664 char * eclipsedir = (char *) 0; 665 int c, new_argc, err; 666 int init_flags = INIT_SHARED|INIT_PRIVATE|INIT_ENGINE|INIT_PROCESS; 667 char * session, * nsrv_hostname; 668 unsigned nsrv_port_number; 669 uword size; 670 671 /* 672 * If stdio is not a tty, get rid of the console window. This is not ideal 673 * since the window flashes up briefly, but no better solution yet. 674 * (The correct way would be not to build eclipse.exe as a "console 675 * application" and have a WinMain() instead of main(). But then we have 676 * to do all the setup of stdin/out/err, argc/argv, environment etc 677 * ourselves) 678 */ 679 if (!isatty(_fileno(stdin)) 680 && !isatty(_fileno(stdout)) 681 && !isatty(_fileno(stderr))) 682 { 683 FreeConsole(); 684 } 685 686 /* 687 * collect information from the command line 688 * remove some internally used arguments from the command line 689 */ 690 for (c = new_argc = 1; c < argc; ) 691 { 692 if (argv[c][0] == '-' && argv[c][2] == 0) /* single char opt */ 693 { 694 switch (argv[c][1]) 695 { 696 case 'a': /* -a <worker> <session> 697 <nsrv_hostname> <nsrv_port_no> */ 698 if (++c + 4 > argc) usage(argv[c-1]); 699 ec_set_option_int(EC_OPTION_PARALLEL_WORKER, atoi(argv[c++])); 700 session = argv[c++]; 701 nsrv_hostname = argv[c++]; 702 nsrv_port_number = atoi(argv[c++]); 703 break; 704 705 case 'c': /* -c <shared_map_file> */ 706 if (++c + 1 > argc) usage(argv[c-1]); 707 ec_set_option_ptr(EC_OPTION_MAPFILE, argv[c++]); 708 ec_set_option_int(EC_OPTION_ALLOCATION, ALLOC_FIXED); 709 init_flags &= ~INIT_SHARED; 710 break; 711 712 case 'm': /* -m <shared_map_file> */ 713 if (++c + 1 > argc) usage(argv[c-1]); 714 ec_set_option_ptr(EC_OPTION_MAPFILE, argv[c++]); 715 ec_set_option_int(EC_OPTION_ALLOCATION, ALLOC_FIXED); 716 break; 717 718 case 'g': /* -g <size> */ 719 argv[new_argc++] = argv[c]; /* shift */ 720 if (++c + 1 > argc) usage(argv[c-1]); 721 argv[new_argc++] = argv[c]; /* shift */ 722 size = sizearg(argv[c++]); 723 ec_set_option_long(EC_OPTION_GLOBALSIZE, size); 724 if (size < MIN_GLOBAL) { 725 fprintf(stderr,"Global stack size out of range\n"); 726 exit(-1); 727 } 728 break; 729 730 case 'd': /* -d <n> */ 731 /* delay worker startup by <n> seconds */ 732 if (++c + 1 > argc) usage(argv[c-1]); 733 Sleep(1000 * atoi(argv[c++])); 734 break; 735 736 case 'D': /* -D <eclipsedir> */ 737 if (++c + 1 > argc) usage(argv[c-1]); 738 eclipsedir = argv[c++]; 739 break; 740 741 case 'l': /* -l <size> */ 742 argv[new_argc++] = argv[c]; /* shift */ 743 if (++c + 1 > argc) usage(argv[c-1]); 744 argv[new_argc++] = argv[c]; /* shift */ 745 size = sizearg(argv[c++]); 746 ec_set_option_long(EC_OPTION_LOCALSIZE, size); 747 if (size < MIN_LOCAL) { 748 fprintf(stderr,"Local stack size out of range\n"); 749 exit(-1); 750 } 751 break; 752 753 case 'h': /* -h <size> */ 754 argv[new_argc++] = argv[c]; /* shift */ 755 if (++c + 1 > argc) usage(argv[c-1]); 756 argv[new_argc++] = argv[c]; /* shift */ 757 size = sizearg(argv[c++]); 758 ec_set_option_long(EC_OPTION_PRIVATESIZE, size); 759 if (size < MIN_PRIVATE) { 760 fprintf(stderr,"Private heap size out of range\n"); 761 exit(-1); 762 } 763 break; 764 765 case 's': /* -s <size> */ 766 argv[new_argc++] = argv[c]; /* shift */ 767 if (++c + 1 > argc) usage(argv[c-1]); 768 argv[new_argc++] = argv[c]; /* shift */ 769 size = sizearg(argv[c++]); 770 ec_set_option_long(EC_OPTION_SHAREDSIZE, size); 771 if (size < MIN_SHARED) { 772 fprintf(stderr,"Shared heap size out of range\n"); 773 exit(-1); 774 } 775 break; 776 777 case 'o': /* enable oracles */ 778 c += 1; 779 /* vm_options = ORACLES_ENABLED; */ 780 break; 781 782 /* Options processed by Prolog-level code */ 783 case 'b': /* -b <bootfile> */ 784 case 'f': /* -f <file> */ 785 case 'e': /* -e <goal> */ 786 case 'L': /* -L <language> */ 787 case 't': /* -t <module> */ 788 argv[new_argc++] = argv[c]; /* shift */ 789 if (++c + 1 > argc) usage(argv[c-1]); 790 argv[new_argc++] = argv[c++]; /* shift */ 791 break; 792 793 case '-': /* -- give the rest to Prolog */ 794 for (; c < argc; ) 795 argv[new_argc++] = argv[c++]; 796 break; 797 798 default: /* unknown: error */ 799 usage(argv[c]); 800 break; 801 } 802 } 803 else if (!strcmp(argv[c], "-debug_level")) 804 { 805 if (++c + 1 > argc) usage(argv[c-1]); 806 ec_set_option_int(EC_OPTION_DEBUG_LEVEL, atoi(argv[c++])); 807 } 808 else /* raise error unless preceeded by a -- option */ 809 { 810 usage(argv[c]); 811 } 812 } 813 814 /*---------------------------------------------------------------- 815 * Entry point after longjmp(reset) 816 *----------------------------------------------------------------*/ 817 818 switch (setjmp(reset)) 819 { 820 case 0: /* raw boot or -r from above */ 821 break; 822 case 3: /* restore program state */ 823 case 2: 824 init_flags = REINIT_SHARED|INIT_ENGINE|INIT_PRIVATE; 825 break; 826 case 4: /* restore execution state */ 827 init_flags = REINIT_SHARED|INIT_PRIVATE; 828 break; 829 case 1: /* reset after fatal error */ 830 default: 831 init_flags = INIT_ENGINE; 832 switch (memory_corrupted++) 833 { 834 case 0: 835 break; 836 837 case 1: 838 /* try to print a message */ 839 memory_corrupted = 2; 840 fprintf(stderr,"\n*** SEPIA Fatal error: memory corrupted\n"); 841 /* fall to */ 842 case 2: 843 /* we couldn't even print the message */ 844 exit(-1); 845 } 846 break; 847 } 848 849 /* 850 * set up our own panic function which longjumps back to reset 851 */ 852 ec_set_option_ptr(EC_OPTION_PANIC, main_panic); 853 854 ec_set_option_int(EC_OPTION_INIT, init_flags); 855 ec_set_option_int(EC_OPTION_ARGC, new_argc); 856 ec_set_option_ptr(EC_OPTION_ARGV, argv); 857 if (eclipsedir) 858 ec_set_option_ptr(EC_OPTION_ECLIPSEDIR, eclipsedir); 859 860 ec_init(); 861 ec_post_goal(ec_term(ec_did(":",2), ec_atom(ec_did("sepia_kernel",0)), 862 ec_atom(ec_did("standalone_toplevel",0)))); 863 do { 864 err = ec_resume(); 865 } while (err == PYIELD); 866 ec_cleanup(); 867 return err; 868} 869 870 871/* 872 * Print the warning about wrong usage and bad_exit. 873 * The argument is the bad option string. 874 */ 875/*ARGSUSED*/ 876static void 877usage(char *opt) 878{ 879 fprintf(stderr,"Bad option: %s\n",opt); 880 fprintf(stderr,"Usage:\n"); 881 fprintf(stderr,"-b <file> compile or load file on startup (deprecated, same as -f)\n"); 882 fprintf(stderr,"-f <file> compile or load file on startup (.ecl or .eco)\n"); 883 fprintf(stderr,"-e <goal> goal to execute (in Prolog syntax)\n"); 884 fprintf(stderr,"-g <kbytes> global+trail stack size\n"); 885 fprintf(stderr,"-l <kbytes> local+control stack size\n"); 886 fprintf(stderr,"-L <language> default language dialect\n"); 887 fprintf(stderr,"-h <kbytes> private heap size\n"); 888 fprintf(stderr,"-s <kbytes> shared heap size\n"); 889 fprintf(stderr,"-t <module> name of initial toplevel module\n"); 890 fprintf(stderr,"-d <seconds> delayed startup\n"); 891 fprintf(stderr,"-D <dir> installation directory\n"); 892 fprintf(stderr,"-- end of ECLiPSe options\n"); 893 fprintf(stderr,"Parallel system only:\n"); 894 fprintf(stderr,"-w <num> number of parallel workers\n"); 895 fprintf(stderr,"-wmi popup worker manager interface\n"); 896 fprintf(stderr,"-wv verbose worker startup\n"); 897 fprintf(stderr,"-wx <exec> use specified worker executable\n"); 898 fprintf(stderr,"Reserved:\n"); 899 fprintf(stderr,"-a <><><><>\n"); 900 fprintf(stderr,"-c <>\n"); 901 fprintf(stderr,"-m <>\n"); 902 fprintf(stderr,"-o \n"); 903 fprintf(stderr,"-r <>\n"); 904 exit(-1); 905} 906 907static void 908main_panic(char *what, char *where) 909{ 910 fprintf(stderr, "\n*** ECLiPSe fatal error: %s",what); 911 912 if (where) 913 fprintf(stderr, " in %s",where); 914 915 fprintf(stderr, "\n"); 916 fflush(stderr); 917 918 longjmp(reset, 1); 919} 920 921#endif 922