summaryrefslogtreecommitdiff
path: root/stdlib/headernt.c
blob: 288e2ae1b0ad2acc97aacb31040aa3f8d4a5986d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/***********************************************************************/
/*                                                                     */
/*                           Objective Caml                            */
/*                                                                     */
/*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         */
/*                                                                     */
/*  Copyright 1998 Institut National de Recherche en Informatique et   */
/*  Automatique.  Distributed only by permission.                      */
/*                                                                     */
/***********************************************************************/

/* $Id$ */

#include <string.h>
#include <wtypes.h>
#include <winbase.h>
#include <process.h>
#include "../byterun/exec.h"

char * default_runtime_name = "ocamlrun";

static unsigned long read_size(char * ptr)
{
  unsigned char * p = (unsigned char *) ptr;
  return ((unsigned long) p[0] << 24) + ((unsigned long) p[1] << 16) +
         ((unsigned long) p[2] << 8) + p[3];
}

static char * read_runtime_path(HANDLE h)
{
  char buffer[TRAILER_SIZE];
  static char runtime_path[MAX_PATH];
  DWORD nread;
  struct exec_trailer tr;
  long size;

  if (SetFilePointer(h, -TRAILER_SIZE, NULL, FILE_END) == -1) return NULL;
  if (! ReadFile(h, buffer, TRAILER_SIZE, &nread, NULL)) return NULL;
  if (nread != TRAILER_SIZE) return NULL;
  tr.path_size = read_size(buffer);
  tr.code_size = read_size(buffer + 4);
  tr.prim_size = read_size(buffer + 8);
  tr.data_size = read_size(buffer + 12);
  tr.symbol_size = read_size(buffer + 16);
  tr.debug_size = read_size(buffer + 20);
  if (tr.path_size >= MAX_PATH) return NULL;
  if (tr.path_size == 0) return default_runtime_name;
  size = tr.path_size + tr.code_size + tr.prim_size +
         tr.data_size + tr.symbol_size + tr.debug_size + TRAILER_SIZE;
  if (SetFilePointer(h, -size, NULL, FILE_END) == -1) return NULL;
  if (! ReadFile(h, runtime_path, tr.path_size, &nread, NULL)) return NULL;
  if (nread != tr.path_size) return NULL;
  runtime_path[tr.path_size - 1] = 0;
  return runtime_path;
}

static void errwrite(char * msg)
{
  DWORD numwritten;
  WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, strlen(msg),
            &numwritten, NULL);
}

int main(int argc, char ** argv)
{
  char truename[MAX_PATH];
  char * cmdline = GetCommandLine();
  char * runtime_path;
  HANDLE h;
  int retcode;

  GetModuleFileName(NULL, truename, sizeof(truename));
  h = CreateFile(truename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
                 NULL, OPEN_EXISTING, 0, NULL);
  if (h == INVALID_HANDLE_VALUE ||
      (runtime_path = read_runtime_path(h)) == NULL) {
    errwrite(truename);
    errwrite(" not found or is not a bytecode executable file\r\n");
    return 2;
  }
  CloseHandle(h);
  retcode = spawnlp(P_WAIT, runtime_path, cmdline, NULL);
  /* We use P_WAIT instead of P_OVERLAY here because under NT,
     P_OVERLAY returns to the command interpreter, displaying the prompt
     before executing the command. */
  if (retcode == -1) {
    errwrite("Cannot exec ");
    errwrite(runtime_path);
    errwrite("\r\n");
    return 2;
  }
  return retcode;
}

/* Prevent VC++ from linking its own _setargv function, which
   performs command-line processing (we don't need it) */

static void _setargv() { }