summaryrefslogtreecommitdiff
path: root/scripts/context/stubs/source/mtxrun_dll.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/context/stubs/source/mtxrun_dll.c')
-rw-r--r--scripts/context/stubs/source/mtxrun_dll.c347
1 files changed, 170 insertions, 177 deletions
diff --git a/scripts/context/stubs/source/mtxrun_dll.c b/scripts/context/stubs/source/mtxrun_dll.c
index 6cac18c9b..9836c2ac5 100644
--- a/scripts/context/stubs/source/mtxrun_dll.c
+++ b/scripts/context/stubs/source/mtxrun_dll.c
@@ -1,214 +1,207 @@
-/*
+/************************************************************************
-Copyright:
+ Copyright:
-The originally 'runscript' program was written by in 2009 by
-T.M.Trzeciak and is public domain. This derived mtxrun program
-is an adapted version by Hans Hagen.
+ Public Domain
+ Originally written in 2010 by Tomasz M. Trzeciak and Hans Hagen
-Comment:
+ This program is derived from the 'runscript' program originally
+ written in 2009 by T.M. Trzeciak. It has been adapted for use in
+ ConTeXt MkIV.
-In ConTeXt MkIV we have two core scripts: luatools.lua and
-mtxrun.lua where the second one is used to launch other scripts.
-Normally a user will use a call like:
+ Comment:
-mtxrun --script font --reload
+ In ConTeXt MkIV we have two core scripts: luatools.lua and
+ mtxrun.lua where the second one is used to launch other scripts.
+ Normally a user will use a call like:
-Here mtxrun is a lua script. In order to avoid the usage of a cmd
-file on windows this runner will start texlua directly. In TeXlive
-a runner is added for each cmd file but we don't want that overhead
-(and extra files). By using an exe we can call these scripts in
-batch files without the need for using call.
+ mtxrun --script font --reload
-We also don't want to use other runners, like those that use kpse
-to locate the script as this is exactly what mtxrun itself is doing
-already. Therefore the runscript program is adapted to a more direct
-approach suitable for mtxrun.
+ Here mtxrun is a lua script. In order to avoid the usage of a cmd
+ file on windows this runner will start texlua directly. If the
+ shared library luatex.dll is available, texlua will be started in
+ the same process avoiding thus any additional overhead. Otherwise
+ it will be spawned in a new proces.
-Compilation:
+ We also don't want to use other runners, like those that use kpse
+ to locate the script as this is exactly what mtxrun itself is doing
+ already. Therefore the runscript program is adapted to a more direct
+ approach suitable for mtxrun.
-with gcc (size optimized):
+ Compilation:
-gcc -Os -s -shared -o mtxrun.dll mtxrun_dll.c
-gcc -Os -s -o mtxrun.exe mtxrun_exe.c -L./ -lmtxrun
+ with gcc (size optimized):
-with tcc (ver. 0.9.24), extra small size
+ gcc -Os -s -shared -o mtxrun.dll mtxrun_dll.c
+ gcc -Os -s -o mtxrun.exe mtxrun_exe.c
-tcc -shared -o runscript.dll runscript_dll.c
-tcc -o runscript.exe runscript_exe.c runscript.def
+ with tcc (extra small size):
-*/
+ tcc -shared -o mtxrun.dll mtxrun_dll.c
+ tcc -o mtxrun.exe mtxrun_exe.c mtxrun.def
+
+************************************************************************/
-#include <windows.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <windows.h>
+//#define STATIC
#define IS_WHITESPACE(c) ((c == ' ') || (c == '\t'))
#define MAX_CMD 32768
-//~ #define DRYRUN
+#define DIE(...) { \
+ fprintf( stderr, "mtxrun: " ); \
+ fprintf( stderr, __VA_ARGS__ ); \
+ return 1; \
+}
-static char dirname [MAX_PATH];
-static char basename[MAX_PATH];
+char texlua_name[] = "texlua"; // just a bare name, luatex strips the rest anyway
+static char cmdline[MAX_CMD];
+static char dirpath[MAX_PATH];
static char progname[MAX_PATH];
-static char cmdline [MAX_CMD];
-
-__declspec(dllexport) int dllrunscript( int argc, char *argv[] ) {
-
- int i;
-
- static char path[MAX_PATH];
-
- // get file name of this executable and split it into parts
-
- DWORD nchars = GetModuleFileNameA(NULL, path, MAX_PATH);
- if ( !nchars || (nchars == MAX_PATH) ) {
- fprintf(stderr, "mtxrun: unable to determine a valid own name\n");
- return -1;
- }
-
- // file extension part
-
- i = strlen(path);
-
- while ( i && (path[i] != '.') && (path[i] != '\\') ) i--;
-
- strcpy(basename, path);
-
- if ( basename[i] == '.' ) basename[i] = '\0'; //remove file extension
-
- // file name part
-
- while ( i && (path[i] != '\\') ) i--;
-
- if ( path[i] != '\\' ) {
- fprintf(stderr, "mtxrun: the runner has no directory part in its name: %s\n", path);
- return -1;
- }
-
- strcpy(dirname, path);
- dirname[i+1] = '\0'; //remove file name, leave trailing backslash
- strcpy(progname, &basename[i+1]);
-
- // find program to execute
-
- if ( (strlen(basename)+100 >= MAX_PATH) ) {
- fprintf(stderr, "mtxrun: the runners path is too long: %s\n", path);
- return -1;
- }
-
- // check .lua
-
- strcpy(path, dirname);
- strcat(path, "mtxrun.lua");
-
- if ( GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES ) {
- goto PROGRAM_FOUND;
- } else {
- fprintf(stderr, "mtxrun: the mtxrun.lua file is not in the same path\n");
- return -1;
- }
-
-PROGRAM_FOUND:
-
- strcpy(cmdline,"texlua.exe ");
-
- if ( ( strcmp(progname,"mtxrun") == 0 ) || ( strcmp(progname,"luatools") == 0 ) ) {
- strcat(cmdline, dirname);
- strcat(cmdline,progname);
- strcat(cmdline, ".lua");
- } else if ( ( strcmp(progname,"texmfstart") == 0 ) ) {
- strcat(cmdline, dirname);
- strcat(cmdline,"mtxrun.lua");
- } else {
- strcat(cmdline, dirname);
- strcat(cmdline, "mtxrun.lua --script ");
- strcat(cmdline,progname);
- }
-
- // get the command line for this process
-
- char *argstr;
- argstr = GetCommandLineA();
- if ( argstr == NULL ) {
- fprintf(stderr, "mtxrun: fetching the command line string fails\n");
- return -1;
+static char scriptpath[MAX_PATH];
+HMODULE dllluatex = NULL;
+typedef int ( *mainlikeproc )( int, char ** );
+
+#ifdef STATIC
+int main( int argc, char *argv[] )
+#else
+__declspec(dllexport) int dllrunscript( int argc, char *argv[] )
+#endif
+{
+ char *s, *argstr, **lua_argv;
+ int k, quoted, lua_argc;
+ int passprogname = 0;
+
+ // directory of this module/executable
+
+ HMODULE module_handle = GetModuleHandle( "mtxrun.dll" );
+ // if ( module_handle == NULL ) exe path will be used, which is OK too
+ k = (int) GetModuleFileName( module_handle, dirpath, MAX_PATH );
+ if ( !k || ( k == MAX_PATH ) )
+ DIE( "unable to determine a valid module name\n" );
+ s = strrchr(dirpath, '\\');
+ if ( s == NULL ) DIE( "no directory part in module path: %s\n", dirpath );
+ *(++s) = '\0'; //remove file name, leave trailing backslash
+
+ // program name
+
+ k = strlen(argv[0]);
+ while ( k && (argv[0][k] != '/') && (argv[0][k] != '\\') ) k--;
+ strcpy(progname, &argv[0][k]);
+ s = progname;
+ if ( s = strrchr(s, '.') ) *s = '\0'; // remove file extension part
+
+ // script path
+
+ strcpy( scriptpath, dirpath );
+ k = strlen(progname);
+ if ( k < 6 ) k = 6; // in case the program name is shorter than "mtxrun"
+ if ( strlen(dirpath) + k + 4 >= MAX_PATH )
+ DIE( "path too long: %s%s\n", dirpath, progname );
+ if ( ( strcmpi(progname,"mtxrun") == 0 ) || ( strcmpi(progname,"luatools") == 0 ) ) {
+ strcat( scriptpath, progname );
+ strcat( scriptpath, ".lua" );
+ } else {
+ strcat( scriptpath, "mtxrun.lua" );
+ if ( strcmpi(progname,"texmfstart") != 0 ) passprogname = 1;
+ }
+ if ( GetFileAttributes(scriptpath) == INVALID_FILE_ATTRIBUTES )
+ DIE( "file not found: %s\n", scriptpath );
+
+ // link with luatex.dll if available
+
+ if ( dllluatex = LoadLibrary("luatex.dll") )
+ {
+ mainlikeproc dllluatexmain = (mainlikeproc) GetProcAddress( dllluatex, "dllluatexmain" );
+ if ( dllluatexmain == NULL )
+ DIE( "unable to locate dllluatexmain procedure in luatex.dll" );
+
+ // set up argument list for texlua script
+
+ lua_argv = (char **)malloc( (argc + 4) * sizeof(char *) );
+ if ( lua_argv == NULL ) DIE( "out of memory\n" );
+ lua_argv[lua_argc=0] = texlua_name;
+ lua_argv[++lua_argc] = scriptpath; // script to execute
+ if (passprogname) {
+ lua_argv[++lua_argc] = "--script";
+ lua_argv[++lua_argc] = progname;
}
+ for ( k = 1; k < argc; k++ ) lua_argv[++lua_argc] = argv[k];
+ lua_argv[++lua_argc] = NULL;
- // skip over argv[0] (it can contain embedded double quotes if launched from cmd.exe!)
+ // call texlua interpreter
+ // dllluatexmain never returns, but we pretend that it does
- int argstrlen = strlen(argstr);
- int quoted = 0;
- for ( i = 0; ( i < argstrlen) && ( !IS_WHITESPACE(argstr[i]) || quoted ); i++ )
+ k = dllluatexmain( lua_argc, lua_argv );
+ if (lua_argv) free( lua_argv );
+ return k;
+ }
- if (argstr[i] == '"') quoted = !quoted;
+ // we are still here, so no luatex.dll; spawn texlua.exe instead
- // while ( IS_WHITESPACE(argstr[i]) ) i++; // arguments leading whitespace
+ strcpy( cmdline, "\"" );
+// strcat( cmdline, dirpath );
+ strcat( cmdline, "texlua.exe\" \"" );
+ strcat( cmdline, scriptpath );
+ strcat( cmdline, "\"" );
+ if (passprogname) {
+ strcat( cmdline, " --script " );
+ strcat( cmdline, progname );
+ }
- argstr = &argstr[i];
+ argstr = GetCommandLine(); // get the command line of this process
+ if ( argstr == NULL ) DIE( "unable to retrieve the command line string\n" );
- if ( strlen(cmdline) + strlen(argstr) >= MAX_CMD ) {
- fprintf(stderr, "mtxrun: the command line string is too long:\n%s%s\n", cmdline, argstr);
- return -1;
- }
+ // skip over argv[0] in the argument string
+ // (it can contain embedded double quotes if launched from cmd.exe!)
- // pass through all the arguments
+ for ( quoted = 0; (*argstr) && ( !IS_WHITESPACE(*argstr) || quoted ); argstr++ )
+ if (*argstr == '"') quoted = !quoted;
- strcat(cmdline, argstr);
+ // pass through all the arguments
-#ifdef DRYRUN
- printf("progname : %s\n", progname);
- printf("dirname : %s\n", dirname);
- printf("arguments : %s\n", &argstr[-i]);
- for (i = 0; i < argc; i++) {
- printf("argv[%d] : %s\n", i, argv[i]);
- }
- printf("commandline : %s\n", cmdline);
- return;
-#endif
+ if ( strlen(cmdline) + strlen(argstr) >= MAX_CMD )
+ DIE( "command line string too long:\n%s%s\n", cmdline, argstr );
+ strcat( cmdline, argstr );
- // create child process
+ // create child process
- STARTUPINFOA si; // ANSI variant
- PROCESS_INFORMATION pi;
- ZeroMemory( &si, sizeof(si) );
- si.cb = sizeof(si);
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;// | STARTF_USESHOWWINDOW;
-
//si.dwFlags = STARTF_USESHOWWINDOW;
//si.wShowWindow = SW_HIDE ; // can be used to hide console window (requires STARTF_USESHOWWINDOW flag)
-
- si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
- si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
- si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
-
- ZeroMemory( &pi, sizeof(pi) );
- if( !CreateProcessA(
- NULL, // module name (uses command line if NULL)
- cmdline, // command line
- NULL, // process security attributes
- NULL, // thread security attributes
- TRUE, // handle inheritance
- 0, // creation flags, e.g. CREATE_NEW_CONSOLE, CREATE_NO_WINDOW, DETACHED_PROCESS
- NULL, // pointer to environment block (uses parent if NULL)
- NULL, // starting directory (uses parent if NULL)
- &si, // STARTUPINFO structure
- &pi ) // PROCESS_INFORMATION structure
- ) {
- fprintf(stderr, "mtxrun: unable to create a process for: %s\n", cmdline);
- return -1;
- }
- CloseHandle( pi.hThread ); // thread handle is not needed
- DWORD ret = 0;
- if ( WaitForSingleObject( pi.hProcess, INFINITE ) == WAIT_OBJECT_0 ) {
- if ( !GetExitCodeProcess( pi.hProcess, &ret) ) {
- fprintf(stderr, "mtxrun: unable to fetch the exit code for process: %s\n", cmdline);
- return -1;
- }
- } else {
- fprintf(stderr, "mtxrun: the script has been terminated unexpectedly: %s\n", cmdline);
- return -1;
- }
- CloseHandle( pi.hProcess );
-
- return ret;
+ si.hStdInput = GetStdHandle( STD_INPUT_HANDLE );
+ si.hStdOutput = GetStdHandle( STD_OUTPUT_HANDLE );
+ si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
+ ZeroMemory( &pi, sizeof(pi) );
+
+ if( !CreateProcess(
+ NULL, // module name (uses command line if NULL)
+ cmdline, // command line
+ NULL, // process security atrributes
+ NULL, // thread security atrributes
+ TRUE, // handle inheritance
+ 0, // creation flags, e.g. CREATE_NEW_CONSOLE, CREATE_NO_WINDOW, DETACHED_PROCESS
+ NULL, // pointer to environment block (uses parent if NULL)
+ NULL, // starting directory (uses parent if NULL)
+ &si, // STARTUPINFO structure
+ &pi ) // PROCESS_INFORMATION structure
+ ) DIE( "command execution failed: %s\n", cmdline );
+
+ DWORD ret = 0;
+ CloseHandle( pi.hThread ); // thread handle is not needed
+ if ( WaitForSingleObject( pi.hProcess, INFINITE ) == WAIT_OBJECT_0 ) {
+ if ( !GetExitCodeProcess( pi.hProcess, &ret) )
+ DIE( "unable to retrieve process exit code: %s\n", cmdline );
+ } else DIE( "failed to wait for process termination: %s\n", cmdline );
+ CloseHandle( pi.hProcess );
+
+ // propagate exit code from the child process
+
+ return ret;
}