1
/* ``The contents of this file are subject to the Erlang Public License,
2
* Version 1.1, (the "License"); you may not use this file except in
3
* compliance with the License. You should have received a copy of the
4
* Erlang Public License along with this software. If not, it can be
5
* retrieved via the world wide web at http://www.erlang.org/.
7
* Software distributed under the License is distributed on an "AS IS"
8
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9
* the License for the specific language governing rights and limitations
12
* The Initial Developer of the Original Code is Ericsson Utvecklings AB.
13
* Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
14
* AB. All Rights Reserved.''
19
* Purpose: escript front-end.
35
#define ASIZE(a) (sizeof(a)/sizeof(a[0]))
37
static int debug = 0; /* Bit flags for debug printouts. */
39
static char** eargv_base; /* Base of vector. */
40
static char** eargv; /* First argument for erl. */
42
static int eargc; /* Number of arguments in eargv. */
45
# define QUOTE(s) possibly_quote(s)
46
# define IS_DIRSEP(c) ((c) == '/' || (c) == '\\')
47
# define ERL_NAME "erl.exe"
50
# define IS_DIRSEP(c) ((c) == '/')
51
# define ERL_NAME "erl"
54
#define UNSHIFT(s) eargc++, eargv--; eargv[0] = QUOTE(s)
55
#define UNSHIFT3(s, t, u) UNSHIFT(u); UNSHIFT(t); UNSHIFT(s)
56
#define PUSH(s) eargv[eargc++] = QUOTE(s)
57
#define PUSH2(s, t) PUSH(s); PUSH(t)
58
#define PUSH3(s, t, u) PUSH2(s, t); PUSH(u)
64
static void error(char* format, ...);
65
static char* emalloc(size_t size);
66
static char* strsave(char* string);
67
static void push_words(char* src);
68
static int run_erlang(char* name, char** argv);
69
static char* get_default_emulator(char* progname);
71
static char* possibly_quote(char* arg);
75
* Supply a strerror() function if libc doesn't.
81
#ifndef SYS_ERRLIST_DECLARED
82
extern const char * const sys_errlist[];
83
#endif /* !SYS_ERRLIST_DECLARED */
85
char *strerror(int errnum)
87
static char *emsg[1024];
90
if (errnum > 0 && errnum < sys_nerr)
91
sprintf((char *) &emsg[0], "(%s)", sys_errlist[errnum]);
93
sprintf((char *) &emsg[0], "errnum = %d ", errnum);
98
return (char *) &emsg[0];
100
#endif /* !HAVE_STRERROR */
103
main(int argc, char** argv)
106
int eargc_base; /* How many arguments in the base of eargv. */
109
emulator = getenv("ESCRIPT_EMULATOR");
110
if (emulator == NULL) {
111
emulator = get_default_emulator(argv[0]);
115
* Allocate the argv vector to be used for arguments to Erlang.
116
* Arrange for starting to pushing information in the middle of
117
* the array, to allow easy addition of commands in the beginning.
120
eargv_size = argc*4+100;
121
eargv_base = (char **) emalloc(eargv_size*sizeof(char*));
124
push_words(emulator);
126
eargv = eargv + eargv_size/2;
130
* Push initial arguments.
134
PUSH2("-boot", "start_clean");
136
PUSH3("-run", "escript", "start");
139
* Push all options (without the hyphen) before the script name.
142
while(argc > 1 && argv[1][0] == '-') {
148
* Push the script name and everything following it as extra arguments.
158
* Move up the commands for invoking the emulator and adjust eargv
162
while (--eargc_base >= 0) {
163
UNSHIFT(eargv_base[eargc_base]);
167
* Invoke Erlang with the collected options.
171
return run_erlang(eargv[0], eargv);
175
push_words(char* src)
181
while ((*dst++ = *src++) != '\0') {
182
if (isspace((int)*src)) {
188
} while (isspace((int)*src));
195
char *make_commandline(char **argv)
197
static char *buff = NULL;
205
for (arg = argv; *arg != NULL; ++arg) {
206
num += strlen(*arg)+1;
210
buff = malloc(siz*sizeof(char));
211
} else if (siz < num) {
213
buff = realloc(buff,siz*sizeof(char));
216
for (arg = argv; *arg != NULL; ++arg) {
224
printf("Processed commandline:%s\n",buff);
229
int my_spawnvp(char **argv)
231
STARTUPINFO siStartInfo;
232
PROCESS_INFORMATION piProcInfo;
235
memset(&siStartInfo,0,sizeof(STARTUPINFO));
236
siStartInfo.cb = sizeof(STARTUPINFO);
237
siStartInfo.dwFlags = STARTF_USESTDHANDLES;
238
siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
239
siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
240
siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
241
siStartInfo.wShowWindow = SW_HIDE;
242
siStartInfo.dwFlags |= STARTF_USESHOWWINDOW;
245
if (!CreateProcess(NULL,
246
make_commandline(argv),
257
CloseHandle(piProcInfo.hThread);
259
WaitForSingleObject(piProcInfo.hProcess,INFINITE);
260
if (!GetExitCodeProcess(piProcInfo.hProcess,&ec)) {
265
#endif /* __WIN32__ */
269
run_erlang(char* progname, char** argv)
277
while (argv[i] != NULL)
278
printf(" %s", argv[i++]);
284
* Alas, we must wait here for the program to finish.
285
* Otherwise, the shell from which we was executed will think
286
* we are finished and print a prompt and read keyboard input.
289
status = my_spawnvp(argv)/*_spawnvp(_P_WAIT,progname,argv)*/;
291
fprintf(stderr, "erlc: Error executing '%s': %d", progname,
296
execvp(progname, argv);
297
error("Error %d executing \'%s\'.", errno, progname);
303
error(char* format, ...)
308
va_start(ap, format);
309
vsprintf(sbuf, format, ap);
311
fprintf(stderr, "erlc: %s\n", sbuf);
318
char *p = malloc(size);
320
error("Insufficient memory");
325
strsave(char* string)
327
char* p = emalloc(strlen(string)+1);
333
get_default_emulator(char* progname)
335
char sbuf[MAXPATHLEN];
338
strcpy(sbuf, progname);
339
for (s = sbuf+strlen(sbuf); s >= sbuf; s--) {
341
strcpy(s+1, ERL_NAME);
342
if (access(sbuf, 1) != -1) {
343
return strsave(sbuf);
353
possibly_quote(char* arg)
365
* Scan the string to find out if it needs quoting and return
366
* the original argument if not.
369
for (s = arg; *s; s++, n++) {
391
* Insert the quotes and put a backslash in front of every quote
395
s = narg = emalloc(n+2+1);
396
for (*s++ = '"'; *arg; arg++, s++) {
397
if (*arg == '"' || (*arg == '\\' && arg[1] == '"')) {
409
#endif /* __WIN32__ */