escript.c
来自「OTP是开放电信平台的简称」· C语言 代码 · 共 410 行
C
410 行
/* ``The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' * * $Id$ *//* * Purpose: escript front-end. */#ifdef HAVE_CONFIG_H# include "config.h"#endif#include "sys.h"#ifdef __WIN32__#include <winbase.h>#endif#include <ctype.h>#define NO 0#define YES 1#define ASIZE(a) (sizeof(a)/sizeof(a[0]))static int debug = 0; /* Bit flags for debug printouts. */static char** eargv_base; /* Base of vector. */static char** eargv; /* First argument for erl. */static int eargc; /* Number of arguments in eargv. */#ifdef __WIN32__# define QUOTE(s) possibly_quote(s)# define IS_DIRSEP(c) ((c) == '/' || (c) == '\\')# define ERL_NAME "erl.exe"#else# define QUOTE(s) s# define IS_DIRSEP(c) ((c) == '/')# define ERL_NAME "erl"#endif#define UNSHIFT(s) eargc++, eargv--; eargv[0] = QUOTE(s)#define UNSHIFT3(s, t, u) UNSHIFT(u); UNSHIFT(t); UNSHIFT(s)#define PUSH(s) eargv[eargc++] = QUOTE(s)#define PUSH2(s, t) PUSH(s); PUSH(t)#define PUSH3(s, t, u) PUSH2(s, t); PUSH(u)/* * Local functions. */static void error(char* format, ...);static char* emalloc(size_t size);static char* strsave(char* string);static void push_words(char* src);static int run_erlang(char* name, char** argv);static char* get_default_emulator(char* progname);#ifdef __WIN32__static char* possibly_quote(char* arg);#endif/* * Supply a strerror() function if libc doesn't. */#ifndef HAVE_STRERRORextern int sys_nerr;#ifndef SYS_ERRLIST_DECLAREDextern const char * const sys_errlist[];#endif /* !SYS_ERRLIST_DECLARED */char *strerror(int errnum){ static char *emsg[1024]; if (errnum != 0) { if (errnum > 0 && errnum < sys_nerr) sprintf((char *) &emsg[0], "(%s)", sys_errlist[errnum]); else sprintf((char *) &emsg[0], "errnum = %d ", errnum); } else { emsg[0] = '\0'; } return (char *) &emsg[0];}#endif /* !HAVE_STRERROR */intmain(int argc, char** argv){ int eargv_size; int eargc_base; /* How many arguments in the base of eargv. */ char* emulator; emulator = getenv("ESCRIPT_EMULATOR"); if (emulator == NULL) { emulator = get_default_emulator(argv[0]); } /* * Allocate the argv vector to be used for arguments to Erlang. * Arrange for starting to pushing information in the middle of * the array, to allow easy addition of commands in the beginning. */ eargv_size = argc*4+100; eargv_base = (char **) emalloc(eargv_size*sizeof(char*)); eargv = eargv_base; eargc = 0; push_words(emulator); eargc_base = eargc; eargv = eargv + eargv_size/2; eargc = 0; /* * Push initial arguments. */ PUSH("+B"); PUSH2("-boot", "start_clean"); PUSH("-noshell"); PUSH3("-run", "escript", "start"); /* * Push all options (without the hyphen) before the script name. */ while(argc > 1 && argv[1][0] == '-') { PUSH(argv[1]+1); argc--, argv++; } /* * Push the script name and everything following it as extra arguments. */ PUSH("-extra"); while (argc > 1) { PUSH(argv[1]); argc--, argv++; } /* * Move up the commands for invoking the emulator and adjust eargv * accordingly. */ while (--eargc_base >= 0) { UNSHIFT(eargv_base[eargc_base]); } /* * Invoke Erlang with the collected options. */ PUSH(NULL); return run_erlang(eargv[0], eargv);}static voidpush_words(char* src){ char sbuf[1024]; char* dst; dst = sbuf; while ((*dst++ = *src++) != '\0') { if (isspace((int)*src)) { *dst = '\0'; PUSH(strsave(sbuf)); dst = sbuf; do { src++; } while (isspace((int)*src)); } } if (sbuf[0]) PUSH(strsave(sbuf));}#ifdef __WIN32__char *make_commandline(char **argv){ static char *buff = NULL; static int siz = 0; int num = 0; char **arg, *p; if (*argv == NULL) { return ""; } for (arg = argv; *arg != NULL; ++arg) { num += strlen(*arg)+1; } if (!siz) { siz = num; buff = malloc(siz*sizeof(char)); } else if (siz < num) { siz = num; buff = realloc(buff,siz*sizeof(char)); } p = buff; for (arg = argv; *arg != NULL; ++arg) { strcpy(p,*arg); p+=strlen(*arg); *p++=' '; } *(--p) = '\0'; if (debug) { printf("Processed commandline:%s\n",buff); } return buff;}int my_spawnvp(char **argv){ STARTUPINFO siStartInfo; PROCESS_INFORMATION piProcInfo; DWORD ec; memset(&siStartInfo,0,sizeof(STARTUPINFO)); siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.dwFlags = STARTF_USESTDHANDLES; siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); siStartInfo.wShowWindow = SW_HIDE; siStartInfo.dwFlags |= STARTF_USESHOWWINDOW; if (!CreateProcess(NULL, make_commandline(argv), NULL, NULL, TRUE, 0, NULL, NULL, &siStartInfo, &piProcInfo)) { return -1; } CloseHandle(piProcInfo.hThread); WaitForSingleObject(piProcInfo.hProcess,INFINITE); if (!GetExitCodeProcess(piProcInfo.hProcess,&ec)) { return 0; } return (int) ec;} #endif /* __WIN32__ */static intrun_erlang(char* progname, char** argv){#ifdef __WIN32__ int status;#endif if (debug) { int i = 0; while (argv[i] != NULL) printf(" %s", argv[i++]); printf("\n"); }#ifdef __WIN32__ /* * Alas, we must wait here for the program to finish. * Otherwise, the shell from which we was executed will think * we are finished and print a prompt and read keyboard input. */ status = my_spawnvp(argv)/*_spawnvp(_P_WAIT,progname,argv)*/; if (status == -1) { fprintf(stderr, "erlc: Error executing '%s': %d", progname, GetLastError()); } return status;#else execvp(progname, argv); error("Error %d executing \'%s\'.", errno, progname); return 2;#endif}static voiderror(char* format, ...){ char sbuf[1024]; va_list ap; va_start(ap, format); vsprintf(sbuf, format, ap); va_end(ap); fprintf(stderr, "erlc: %s\n", sbuf); exit(1);}static char*emalloc(size_t size){ char *p = malloc(size); if (p == NULL) error("Insufficient memory"); return p;}static char*strsave(char* string){ char* p = emalloc(strlen(string)+1); strcpy(p, string); return p;}static char*get_default_emulator(char* progname){ char sbuf[MAXPATHLEN]; char* s; strcpy(sbuf, progname); for (s = sbuf+strlen(sbuf); s >= sbuf; s--) { if (IS_DIRSEP(*s)) { strcpy(s+1, ERL_NAME); if (access(sbuf, 1) != -1) { return strsave(sbuf); } break; } } return ERL_NAME;}#ifdef __WIN32__static char*possibly_quote(char* arg){ int mustQuote = NO; int n = 0; char* s; char* narg; if (arg == NULL) { return arg; } /* * Scan the string to find out if it needs quoting and return * the original argument if not. */ for (s = arg; *s; s++, n++) { switch(*s) { case ' ': mustQuote = YES; continue; case '"': mustQuote = YES; n++; continue; case '\\': if(s[1] == '"') n++; continue; default: continue; } } if (!mustQuote) { return arg; } /* * Insert the quotes and put a backslash in front of every quote * inside the string. */ s = narg = emalloc(n+2+1); for (*s++ = '"'; *arg; arg++, s++) { if (*arg == '"' || (*arg == '\\' && arg[1] == '"')) { *s++ = '\\'; } *s = *arg; } if (s[-1] == '\\') { *s++ ='\\'; } *s++ = '"'; *s = '\0'; return narg;}#endif /* __WIN32__ */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?