home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / p / plbin.zip / pl / src / pl-dump.c < prev    next >
C/C++ Source or Header  |  1993-02-23  |  9KB  |  371 lines

  1. /*  pl-dump.c,v 1.7 1993/02/23 13:16:28 jan Exp
  2.  
  3.     Copyright (c) 1990 Jan Wielemaker. All rights reserved.
  4.     See ../LICENCE to find out about your rights.
  5.     jan@swi.psy.uva.nl
  6.  
  7.     Purpose: Create a saved state (stand alone executable)
  8. */
  9.  
  10. #include "pl-incl.h"
  11.  
  12. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  13. Creating of saved states of the program (the  stacks  are  lost).   This
  14. module takes the currently running program and generates a complete Unix
  15. executable file from it.  It uses the GNU-Emacs code for unexec(), which
  16. is modified a bit to improve the interaction with SWI-Prolog.
  17.  
  18. Hack hack hack hack ...
  19. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  20.  
  21. #if O_STORE_PROGRAM || O_SAVE
  22.  
  23. #include <sys/param.h>
  24. #if O_STORE_PROGRAM
  25. int    unexec P((char *, char *, char *, unsigned, unsigned, unsigned));
  26. #else
  27. #include "pl-save.h"
  28. #endif
  29.  
  30. word
  31. saveProgram(new)
  32. Word new;
  33. { char *new_name, *sym_name;
  34.   char tmp[MAXPATHLEN];
  35.   char dest[MAXPATHLEN];
  36.   char old_name[MAXPATHLEN];
  37.   
  38.   if ( !isAtom(*new) )
  39.     return warning("save_program/1: instantiation fault");
  40.  
  41.   if ( cannot_save_program != NULL )
  42.     return warning("Cannot save the program: %s", cannot_save_program);
  43.  
  44.   TRY( getSymbols() );
  45.   
  46.   strcpy(old_name,OsPath(stringAtom(loaderstatus.orgsymbolfile)));
  47.   if ( loaderstatus.symbolfile != loaderstatus.orgsymbolfile )
  48.     sym_name = stringAtom(loaderstatus.symbolfile);
  49.   else
  50.     sym_name = NULL;
  51.   
  52.   strcpy(dest,OsPath(stringAtom(*new)));
  53.   sprintf(tmp, "%s#%d", dest, getpid());
  54.   new_name = tmp;
  55.  
  56.   systemDefaults.state = (char *) NULL;        /* does not need this any */
  57.   closeFiles();
  58.  
  59. #if O_SAVE
  60.   TRY(save(dest, old_name, RET_MAIN, 0, NULL));
  61. #else
  62.   Putf("Running program: %s\n", old_name);
  63.   if ( sym_name != NULL )
  64.     Putf("Taking symbol table from %s\n", sym_name);
  65.   Putf("Saving to %s ... ", new_name); pl_flush();
  66.   if ( unexec(new_name, old_name, sym_name, 0, 0, 0) < 0 )
  67.   { DeleteFile(tmp);
  68.     fail;
  69.   }
  70.   Putf("ok.\n");
  71.   Putf("Moving %s to %s ... ", tmp, dest); pl_flush();
  72.   if ( RenameFile(tmp, dest) == FALSE )
  73.   { warning("Failed to install %s: %s", dest, OsError());
  74.     DeleteFile(tmp);
  75.     fail;
  76.   }
  77. #endif
  78.   Putf("Program saved in %s\n", dest);
  79.  
  80.   succeed;
  81. }
  82.  
  83. static
  84. bool
  85. sizeOption(i, v)
  86. int *i;
  87. word v;
  88. { if ( !isInteger(v) )
  89.     return warning("save_program/2: illegal option argument");
  90.   *i = valNum(v);
  91.  
  92.   succeed;
  93. }
  94.  
  95. static
  96. bool
  97. stringOption(s, v)
  98. char **s;
  99. word v;
  100. { if ( !isAtom(v) )
  101.     return warning("save_program/2: illegal option argument");
  102.   *s = stringAtom(v);
  103.  
  104.   succeed;
  105. }
  106.  
  107. static
  108. bool
  109. boolOption(b, v)
  110. bool *b;
  111. word v;
  112. { if ( v == (word) ATOM_on )
  113.     *b = TRUE;
  114.   else if ( v == (word) ATOM_off )
  115.     *b = FALSE;
  116.   else
  117.     return warning("save_program/2: illegal option argument");
  118.  
  119.   succeed;
  120. }
  121.  
  122. word
  123. pl_save_program(new, args)
  124. Word new, args;
  125. { Word a;
  126.   Word Option, Value;
  127.   Atom option;
  128.   word value;
  129.  
  130.   while( isList(*args) )
  131.   { a = HeadList(args);
  132.     deRef(a);
  133.     if ( !isTerm(*a) || functorTerm(*a) != FUNCTOR_equals2 )
  134.       return warning("save_program/2: Illegal option list");
  135.  
  136.     Option = argTermP(*a, 0); deRef(Option);
  137.     Value  = argTermP(*a, 1); deRef(Value);
  138.     if ( !isAtom(*Option) )
  139.       return warning("save_program/2: Illegal option list");
  140.  
  141.     option = (Atom) *Option;
  142.     value = *Value;
  143.     if        ( option == ATOM_local )
  144.     { TRY( sizeOption(&systemDefaults.local, value) );
  145.     } else if ( option == ATOM_global )
  146.     { TRY( sizeOption(&systemDefaults.global, value) );
  147.     } else if ( option == ATOM_trail )
  148.     { TRY( sizeOption(&systemDefaults.trail, value) );
  149.     } else if ( option == ATOM_argument )
  150.     { TRY( sizeOption(&systemDefaults.argument, value) );
  151.     } else if ( option == ATOM_goal )
  152.     { TRY( stringOption(&systemDefaults.goal, value) );
  153.     } else if ( option == ATOM_toplevel )
  154.     { TRY( stringOption(&systemDefaults.toplevel, value) );
  155.     } else if ( option == ATOM_init_file )
  156.     { TRY( stringOption(&systemDefaults.startup, value) );
  157.     } else if ( option == ATOM_tty )
  158.     { TRY( boolOption(&systemDefaults.notty, value) );
  159.       systemDefaults.notty = !systemDefaults.notty;
  160.     } else
  161.     { return warning("save_program/2: Unknown option: %s", stringAtom(option));
  162.     }
  163.  
  164.     args = TailList(args);
  165.     deRef(args);
  166.   }
  167.   if ( !isNil(*args) )
  168.     return warning("save_program/2: Illegal option list");
  169.  
  170.   return saveProgram(new);
  171. }
  172.  
  173. #if O_SAVE
  174.  
  175. word
  176. pl_save(file, restore)
  177. Word file, restore;
  178. { char *state, *interpreter;
  179. #if O_DYNAMIC_STACKS
  180.   struct save_section sections[5];
  181. #endif
  182.  
  183.   if ( (state = primitiveToString(*file, FALSE)) == (char *)NULL )
  184.     return warning("save/2: instantiation fault");
  185.   if ( (state = ExpandOneFile(state)) == (char *)NULL )
  186.     fail;
  187.  
  188.   TRY( getSymbols() );
  189.   interpreter = stringAtom(loaderstatus.orgsymbolfile);
  190.   
  191. #if O_DYNAMIC_STACKS
  192. #define fill_section(sec, stack) \
  193.   { (sec)->start  = (caddr) (stack)->base; \
  194.     (sec)->length = (ulong) (stack)->top - (ulong) (stack)->base; \
  195.     (sec)->type   = S_PLSTACK; \
  196.     (sec)->flags  = 0; \
  197.   }
  198.   fill_section(§ions[0], &stacks.local);
  199.   fill_section(§ions[1], &stacks.global);
  200.   fill_section(§ions[2], &stacks.trail);
  201.   fill_section(§ions[3], &stacks.argument);
  202.   fill_section(§ions[4], &stacks.lock);
  203. #undef fill_section
  204.  
  205.   switch( save(state, interpreter, RET_RETURN, 5, sections) )
  206. #else
  207.   switch( save(state, interpreter, RET_RETURN, 0, NULL) )
  208. #endif
  209.   { case SAVE_SAVE:
  210.       return unifyAtomic(restore, consNum(0));
  211.     case SAVE_RESTORE:
  212. #if unix || EMX
  213.       initSignals();
  214. #endif
  215.       return unifyAtomic(restore, consNum(1));
  216.     case SAVE_FAILURE:
  217.     default:
  218.       fail;
  219.   }
  220. }
  221.  
  222. #if O_DYNAMIC_STACKS
  223. bool
  224. allocateSection(s)
  225. SaveSection s;
  226. { if ( s->type == S_PLSTACK )
  227.   { if ((stacks.local.base    == s->start &&
  228.      restoreStack((Stack) &stacks.local)) ||
  229.     (stacks.global.base   == s->start &&
  230.      restoreStack((Stack) &stacks.global)) ||
  231.     (stacks.trail.base    == s->start &&
  232.      restoreStack((Stack) &stacks.trail)) ||
  233.     (stacks.argument.base == s->start &&
  234.      restoreStack((Stack) &stacks.argument)) ||
  235.     (stacks.lock.base     == s->start &&
  236.      restoreStack((Stack) &stacks.lock)) )
  237.       succeed;
  238.  
  239.     fatalError("Cannot locate stack to restore");
  240.     fail;
  241.   }
  242.  
  243.   succeed;
  244. }
  245. #endif
  246.  
  247. word
  248. pl_restore(file)
  249. Word file;
  250. { char *state;
  251.  
  252.   if ( (state = primitiveToString(*file, FALSE)) == (char *)NULL )
  253.     return warning("restore/1: instantiation fault");
  254.   if ( (state = ExpandOneFile(state)) == (char *)NULL )
  255.     fail;
  256.   if ( ExistsFile(state) == FALSE )
  257.     return warning("restore/1: no such file: %s", state);
  258.  
  259. #if O_DYNAMIC_STACKS
  260.   deallocateStacks();
  261.   restore(state, allocateSection);
  262. #else
  263.   restore(state, NULL);
  264. #endif
  265.   fatalError("restore/1: restore failed");
  266.   fail;
  267. }
  268.  
  269. #endif /* O_SAVE */
  270.  
  271. #if O_STORE_PROGRAM
  272.  
  273. #define NO_REMAP 1            /* Do not change data start */
  274.  
  275. #ifdef UNEXEC_SOURCE
  276.  
  277. #include UNEXEC_SOURCE
  278.  
  279. #else /* ~UNEXEC_SOURCE */
  280.  
  281. #include <a.out.h>
  282.  
  283. #if sun
  284. #define A_TEXT_OFFSET(HDR) sizeof (HDR)
  285. #define TEXT_START    (SEGSIZ + sizeof(struct exec))
  286. #endif
  287.  
  288. #if gould
  289. #define A_TEXT_OFFSET(HDR) sizeof (HDR)
  290. #define ADJUST_EXEC_HEADER unexec_text_start = hdr.a_txbase + sizeof (hdr);
  291. #define GOULD 1
  292. #endif
  293.  
  294. #if AIX                    /* PS2 version; still in use? */
  295. #define COFF        1        /* Coff ld output format */
  296. #define TEXT_START    0x00000000    /* Hope text always starts here */
  297. #define DATA_START    0x00400000    /* Hope data always starts here */
  298. #endif
  299.  
  300. #if hpux
  301. #define HPUX
  302. #define N_TXTOFF(hdr)    TEXT_OFFSET(hdr)
  303. #define N_DATADDR(hdr)    (DATA_OFFSET(hdr) - EXEC_PAGESIZE)
  304. #define N_SYMOFF(hdr)    LESYM_OFFSET(hdr)
  305. #endif
  306.  
  307. #define PERROR(msg) warning("save_program/2: %s: %s", msg, OsError()); \
  308.             return -1
  309.  
  310. char *
  311. start_of_data ()
  312. {
  313. #ifdef DATA_START
  314.   return ((char *) DATA_START);
  315. #else
  316. #  if hpux
  317. {     extern etext;
  318.       return (char *) &etext + EXEC_PAGESIZE; /* Rounded down by unexec() */
  319. }
  320. #  else
  321.       extern char **environ;
  322.       return ((char *)&environ);
  323. #  endif
  324. #endif
  325. }
  326.  
  327.  
  328. char *
  329. start_of_text(hdr)
  330. struct exec *hdr;
  331. {
  332. #ifdef N_TXTADDR
  333. #ifdef A_TEXT_OFFSET
  334.   return (char *) N_TXTADDR(*hdr) + A_TEXT_OFFSET(*hdr);
  335. #else
  336.   return (char *) N_TXTADDR(*hdr);
  337. #endif
  338. #else /* N_TXTADDR */
  339. #ifdef TEXT_START
  340.   return ((char *) TEXT_START);
  341. #else
  342. #if gould                /* GOULD machine */
  343.   extern csrt();
  344.   return ((char *) csrt);
  345. #else /* gould */
  346.   return (char *) hdr->a_entry;
  347. #endif
  348. #endif /* TEXT_START */
  349. #endif /* N_TXTADDR */
  350. }
  351.  
  352. #include "gnu/unexec.c"
  353. #endif /* UNEXEC_SOURCE */
  354. #endif /* O_STORE_PROGRAM */
  355.  
  356. #else /* O_STORE_PROGRAM || O_SAVE */
  357.  
  358. word
  359. saveProgram(new)
  360. Word new;
  361. { return warning("store_program/1: not ported to this machine");
  362. }
  363.  
  364. word
  365. pl_save_program(old, new)
  366. Word old, new;
  367. { return warning("store_program/2: not ported to this machine");
  368. }
  369.  
  370. #endif /* O_STORE_PROGRAM || O_SAVE */
  371.