stk/Src/argv.c

329 lines
8.2 KiB
C

/*
*
* a r g v . c -- Argc/Argv management
*
* Copyright © 1993-1997 Erick Gallesio - I3S-CNRS/ESSI <eg@unice.fr>
*
*
* Permission to use, copy, and/or distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that both the above copyright notice and this permission notice appear in
* all copies and derived works. Fees for distribution or use of this
* software or derived works may only be charged with express written
* permission of the copyright holder.
* This software is provided ``as is'' without express or implied warranty.
*
* This software is a derivative work of other copyrighted softwares; the
* copyright notices of these softwares are placed in the file COPYRIGHTS
*
*
* Author: Erick Gallesio [eg@kaolin.unice.fr]
* Creation date: 30-Aug-1994 15:38
* Last file update: 30-Dec-1997 14:34
*/
#include "stk.h"
#ifdef WIN32
#include <process.h>
#include <io.h>
#include <stdlib.h>
#endif
/* Previous versions of Stk use the TkArgv mechanism for managing argc/argv.
* Here is an ad hoc version for argc/argv hich is simpler than the original
* one and which can be used when NO_TK is defined
*/
#ifdef USE_TK
char *STk_arg_Xdisplay = NULL;
char *STk_arg_geometry = NULL;
char *STk_arg_name = NULL;
char *STk_arg_visual = NULL;
int STk_arg_colormap = 0;
int STk_arg_sync = 0;
int STk_arg_no_tk = 0;
#endif
char *STk_arg_file = NULL;
char *STk_arg_load = NULL;
char *STk_arg_image = NULL;
char *STk_arg_cells = NULL;
int STk_arg_interactive = 0;
static struct arguments {
char *key;
char **flag;
char need_argument;
char *init;
char *help;
} Table[] = {
#ifdef USE_TK
{"-colormap", (char **) &STk_arg_colormap, 0, (char *) 0,
"Use a private colormap"},
{"-display", &STk_arg_Xdisplay, 1, NULL,
"Display to use"},
{"-geometry", &STk_arg_geometry, 1, NULL,
"Initial geometry for window"},
{"-name", &STk_arg_name, 1, NULL,
"\tName to use for application"},
{"-sync", (char **) &STk_arg_sync, 0, (char *) 0,
"\tUse synchronous mode for display server"},
{"-visual", &STk_arg_visual, 1, NULL,
"Visual for main window"},
{"-no-tk", (char **) &STk_arg_no_tk, 0, (char *) 0,
"\tDon't initialize Tk"},
#endif
{"-file", &STk_arg_file, 1, NULL,
"\tFile from which to read commands"},
{"-load", &STk_arg_load, 1, NULL,
"\tFile to load after all the initializations are done"},
{"-cells", &STk_arg_cells, 1, (char *) 0L,
"\tDefault size for heap"},
{"-image", &STk_arg_image, 1, NULL,
"\tUse previously created image"},
{"-interactive", (char **) &STk_arg_interactive, 0, (char *) 0,
"Interactive mode"},
{"-help", NULL, 0, NULL,
"\tPrint summary of command-line options and abort"},
{"", NULL, 0, NULL, ""}};
static void usage(void)
{
struct arguments *p;
for (p = Table; *(p->key); p++)
fprintf(STk_stderr, "%s\t%s\n", p->key, p->help);
exit(1);
}
char **STk_process_argc_argv(int argc, char **argv)
{
struct arguments *p;
char **new_argv;
int i;
/* Reset arguments to their default value */
for (p = Table; *(p->key); p++)
if (p->flag)
*(p->flag) = p->init;
/* Set the program name */
STk_whence(*argv, STk_Argv0);
/* Option analysis */
while (--argc) {
char *arg = *++argv;
int found = FALSE;
if (!*arg) break;
if (strcmp(arg, "--") == 0) { /* Special delimiter */
argv += 1;
argc -= 1;
break;
}
/* Try to find the option in table */
for (p = Table; *(p->key); p++) {
if (strlen(arg) >= 2) {
if (strstr(p->key, arg)== p->key) {
found = TRUE;
if (p->need_argument) {
argc -= 1;
argv += 1;
if (*argv)
*(p->flag) = *argv;
else {
fprintf(STk_stderr,
"\"%s\" option requires an additional argument\n",
p->key);
exit(1);
}
}
else
if (p->flag)
*(p->flag) = (char *) TRUE;
else
usage();
}
}
}
if (!found) {
/* Special convention: if we have an argument before "--" alone
* consider it as the name of a script file
*/
if (!STk_arg_file) {
STk_arg_file = arg;
argv += 1;
argc -= 1;
}
break;
}
}
/* Option have been analysed. Parse program arguments */
new_argv = (char**) must_malloc((argc + 1) * sizeof(char*));
for (i = 0; argc; argc--) {
new_argv[i++] = *argv++;
}
new_argv[i] = NULL;
return new_argv;
}
/******************************************************************************
*
* Unix environment saving
*
* The two following function permit to save/restore the argc/argv/envp
* in a file. They are used upon image restauration.
*
******************************************************************************/
void STk_save_unix_args_and_environment(int argc, char **argv)
{
FILE *f;
char **env;
char filename[50];
extern char **environ;
/* Open a file in which we will save argc/argv/envp */
sprintf(filename, "/usr/tmp/STktmp%d", getpid());
if ((f = fopen(filename, "w")) == NULL) {
STk_panic("Cannot save environment in %s.", filename);
exit(1);
}
/* print argc */
fprintf(f, "%d\n", argc);
/* print argv */
for ( ; argc; argc-=1, argv+=1) {
fprintf(f, "%d %s\n", strlen(*argv), *argv);
}
/* print environment */
for (env=environ; *env; env++) {};
fprintf(f, "%d\n", env-environ);
for (env=environ; *env; env++) {
fprintf(f, "%d %s\n", strlen(*env), *env);
}
/* Close file */
fclose(f);
}
void STk_restore_unix_args_and_environment(int *argc, char ***argv)
{
FILE *f;
int i, l, Argc, env_len;
char **Argv, **Env;
char filename[50];
extern char **environ;
/* Open a file in which we have saved argc/argv/envp */
sprintf(filename, "/usr/tmp/STktmp%d", getpid());
if ((f = fopen(filename, "r")) == NULL) {
STk_panic("Cannot re-open environment in %s.", filename);
exit(1);
}
/* Read argc */
fscanf(f, "%d", &Argc); getc(f);
/* Read argv */
Argv = must_malloc((Argc+1) * sizeof(char *));
for (i=0; i<Argc; i++) {
fscanf(f, "%d", &l); getc(f);
Argv[i] = must_malloc(l+1);
fread(Argv[i], 1, l, f);
Argv[i][l] = '\0';
}
Argv[Argc] = NULL;
/* Read environment */
fscanf(f, "%d", &env_len); getc(f);
Env = must_malloc((env_len+1) * sizeof(char *));
for (i=0; i<env_len; i++) {
fscanf(f, "%d", &l); getc(f);
Env[i] = must_malloc(l+1);
fread(Env[i], 1, l, f);
Env[i][l] = '\0';
}
Env[i]= NULL;
/* Save read values in global variables */
*argc = Argc;
*argv = Argv;
environ = Env;
/* close & delete temporary file */
fclose(f);
unlink(filename);
}
void STk_initialize_scheme_args(char **argv)
{
SCM l;
char *progname;
progname = (STk_arg_file) ? STk_arg_file : STk_Argv0;
for (l = NIL; *argv; argv++)
l = Cons(STk_makestring(*argv), l);
STk_define_variable(ARGV, Reverse(l), NIL);
STk_define_variable(PROG_NAME, STk_makestring(progname), NIL);
}
#ifdef WIN32
#include <dos.h>
char **STk_Win32_make_argc_argv(char *lpszCmdLine, int *argc)
{
int size, i, code;
char **argv, **argvlist, *p, *tmp, *prog= "STk.exe";
/*
* First get an upper bound on the size of the argv array by counting the
* number of whitespace characters in the string.
*/
for (size=1, p=lpszCmdLine; *p != '\0'; p++) {
if (isspace(UCHAR(*p))) size++;
}
size+=2; /* Leave space for program name final NULL pointer. */
argvlist = (char **) ckalloc((unsigned) (size * sizeof(char *)));
argv = argvlist;
p = getenv("STK_LIBRARY");
if (p == NULL)
panic("You must set the STK_LIBRARY variable");
tmp = must_malloc(strlen(p) + strlen(prog) + 2);
sprintf(tmp, "%s/%s", p, prog);
argv[0] = tmp; /* FIXME */
/*
* Split the command line into words, and store pointers to the start of
* each word into the argv array. Skips leading whitespace on each word.
*/
for (i=1, p=lpszCmdLine; *p != '\0'; i++) {
while (isspace(UCHAR(*p))) p++;
if (*p == '\0') break;
argv[i] = p;
while (*p != '\0' && !isspace(UCHAR(*p)))
p++;
if (*p) *p++ = '\0';
}
argv[i] = NULL;
*argc = i;
return argv;
}
#endif