#include "scheme.h"

#ifdef CAN_DUMP

#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>

extern int errno;

Object Dump_Control_Point;

Init_Dump () {
    Global_GC_Link (Dump_Control_Point);
}

#define Dump_Prolog \
    Object ret;\
    int ofd, afd;\
    FILE *fp;\
    char *ofn;\
    Declare_C_Strings;\
    GC_Node;\
\
    if (!EQ (Curr_Input_Port, Standard_Input_Port) ||\
	    !EQ (Curr_Output_Port, Standard_Output_Port))\
	Primitive_Error ("cannot dump with current ports redirected");\
    Flush_Output (Curr_Output_Port);\
    Close_All_Files ();\
\
    GC_Link (ofile);\
    ret = Internal_Call_CC (1, Null);\
    if (Truep (ret))\
	return ret;\
    GC_Unlink;\
\
    Disable_Interrupts;\
\
    Make_C_String (ofile, ofn);\
    if ((fp = fopen (ofn, "w+")) == 0) {\
	Saved_Errno = errno;\
	Primitive_Error ("cannot open ~s: ~E", ofile);\
    }\
    ofd = dup (fileno (fp));\
    (void)fclose (fp);\
    if (ofd == -1)\
	Primitive_Error ("out of file descriptors");\
    if ((afd = open (A_Out_Name, 0)) == -1) {\
	Saved_Errno = errno;\
	close (ofd);\
	Primitive_Error ("cannot open a.out file: ~E");\
    }

#define Dump_Finalize    Saved_Errno = errno; close (afd); close (ofd)
    

#define Dump_Epilog {\
    close (afd);\
    Set_File_Executable (ofd, ofn);\
    close (ofd);\
    Enable_Interrupts;\
    Dispose_C_Strings;\
    return False;\
}

#ifdef ELF
#  include "dump.elf.c"
#else
#ifdef ECOFF
#  include "dump.ecoff.c"
#else
#  include "dump.vanilla.c"
#endif
#endif

/*ARGSUSED1*/
Set_File_Executable (fd, fn) int fd; char *fn; {
    struct stat st;

    if (fstat (fd, &st) != -1) {
	int omask = umask (0);
	(void)umask (omask);
#ifdef FCHMOD_BROKEN
	(void)chmod (fn, st.st_mode & 0777 | 0111 & ~omask);
#else
	(void)fchmod (fd, st.st_mode & 0777 | 0111 & ~omask);
#endif
    }
}

#endif /* CAN_DUMP */
