Npt documentation.
Reference: ANSI Common Lisp npt
Prev: 6. Escape Operations
Next: 8. Paper Object
This chapter explains how to start npt in C.
In normal C, the main
function is the start of execution, and in Windows, it is the WinMain
function.
Here’s how npt is initialized in both cases.
To start npt, first execute the following function
void lisp_init(void);
This function initializes a static variable used by the C language in npt and declares it ready to be used.
The corresponding release process is the following functions.
void lisp_free(void);
After the initialization process is executed, the function pointer can be registered. The function pointer registration is a process using the following functions, for example.
void lisp_compiled_rest(int index, lisp_calltype_rest call);
Once the function pointer is executed, it persists until it is released with lisp_free
.
The command argument is the argc
, argv
, and env
of the main
function.
The function used for reading is as follows.
struct lispargv *lispargv_main(int argc, char *argv[], char *env[]);
In case of an error, null is returned.
Since the memory is dynamically allocated, the following release process is required at the time of exit.
void lispargv_free(struct lispargv *ptr);
An example is shown below.
int main(int argc, char *argv[], char *env[])
{
struct lispargv *args;
();
lisp_init= lispargv_main(argc, argv, env);
args if (args == NULL) {
(stderr, "argv error\n");
fprintfreturn 1;
}
/* Here's the code for npt. */
/* free */
(args);
lispargv_free();
lisp_free
return 0;
}
The function lispargv_main
ignores argc
, argv
, and env
on Windows, and forces the following functions to be executed instead.
struct lispargv *lispargv_windows(void);
This function is equivalent to the lispargv_main
, but it gets the arguments and environment variables from the WIN32API.
If the function WinMain
is used, the above function should be used because there is no argument like argc
.
However, it is possible to start the program from the main
function even on Windows.
Even in such a case, it forces the lispargv_windows
function to be used to process the character code correctly.
If you want to run the function from the main
function instead of lispargv_windows
, use the following function.
struct lispargv *lispargv_main_force(int argc, char *argv[], char *env[]);
This function forces reading of arguments, even on Windows.
If argc
, argv
, and env
are not present or you do not want to specify them, perform as follows.
= lispargv_main_force(0, NULL, NULL); args
This section explains how to set up Npt manually instead of from arguments.
Here’s an example of a typical --standalone
mode configuration
->mode_core = 0;
args->mode_degrade = 0;
args->mode_standalone = 1;
args->nocore = 1;
args->noinit = 1;
args->debugger = 1;
args->debuggerp = 0;
args->quit = 1; args
To change the size of the memory, do the following
->heap = 1024UL * 1024UL*1024UL; /* 1G */
args->local = 256UL * 1024UL*1024UL; /* 256M */ args
heap
is the size of the heap area.
local
is the size of the stack region.
Both are allocated by malloc
in the initial stage of npt execution.
To summarize the above, the following is a typical main
function.
int main(int argc, char *argv[], char *env[])
{
int result;
struct lispargv *args;
/* initialize */
();
lisp_init= lispargv_main(argc, argv, env);
args if (args == NULL) {
(stderr, "argv error\n");
fprintfreturn 1;
}
/* main_argv */
->mode_core = 0;
args->mode_degrade = 0;
args->mode_standalone = 1;
args->nocore = 1;
args->noinit = 1;
args->debugger = 1;
args->debuggerp = 0;
args->quit = 1;
args= main_argv(args);
result
/* free */
(args);
lispargv_free();
lisp_free
return result;
}
Next, the function main_argv
is created.
If the argument is something about the display, such as --help
, it prints the information and exits the execution.
static int main_argv(struct lispargv *args)
{
if (args->mode_help)
return lisp_main_help(stdout);
if (args->mode_version)
return lisp_main_version(args, stdout);
if (args->mode_degrade)
return lisp_main_degrade(args);
/* Create the content here in the next chapter. */
return 0
}
The following arguments are now supported
--help
--version
--version-script
--degrade
main_lisp
The next step is to build the npt environment.
The following functions are used.
int lisp_argv_init(struct lispargv *ptr);
int lisp_argv_run(struct lispargv *ptr);
The lisp_argv_init
function is used to prepare and run Lisp by the lisp_argv_run
function.
As shown in the previous examples, set the main_lisp
function to args->call
.
The following is an example.
int main_lisp(void *call_ptr)
{
return 0;
}
static int main_argv(struct lispargv *args)
{
/* mode */
if (args->mode_help)
return lisp_main_help(stdout);
if (args->mode_version)
return lisp_main_version(args, stdout);
if (args->mode_degrade)
return lisp_main_degrade(args);
/* execute */
->call = main_lisp;
args->call_ptr = NULL;
args(args);
lisp_argv_init(args);
lisp_argv_run
return lisp_code? 1: lisp_result;
}
The return value of lisp_argv_init
and lisp_argv_run
is returned whether an error occurred or not. However, since the variable lisp_code
is set to show whether an error occurred or not, you only have to check this value.
The main_lisp
function registered at args->call
is called with args->call_ptr
as an argument.
The reason why you need to register them with function pointers is that you need to set various settings before executing them in order for them to work properly as Common Lisp.
One example is the handling of handler-bind
used in the warn
function.
The main_lisp
function is an escape function, which is a little different from the usual escape function. If the function returns a non-zero value on non-escape, it assumes an abnormal exit and ignores all subsequent operations and exits with the exit code 1
.
To summarize the content, here’s the first example sentence 1. Using Npt in C.
int main_lisp(void *call_ptr)
{
return lisp_format8_(NULL, "Hello~%", NULL);
}
static int main_argv(struct lispargv *args)
{
/* mode */
if (args->mode_help)
return lisp_main_help(stdout);
if (args->mode_version)
return lisp_main_version(args, stdout);
if (args->mode_degrade)
return lisp_main_degrade(args);
/* execute */
->call = main_lisp;
args->call_ptr = NULL;
args(args);
lisp_argv_init(args);
lisp_argv_run
return lisp_code? 1: lisp_result;
}
int main(int argc, char *argv[], char *env[])
{
int result;
struct lispargv *args;
/* initialize */
();
lisp_init= lispargv_main(argc, argv, env);
args if (args == NULL) {
(stderr, "argv error\n");
fprintfreturn 1;
}
/* main_argv */
->mode_core = 0;
args->mode_degrade = 0;
args->mode_standalone = 1;
args->nocore = 1;
args->noinit = 1;
args->debugger = 1;
args->debuggerp = 0;
args->quit = 1;
args= main_argv(args);
result
/* free */
(args);
lispargv_free();
lisp_free
return result;
}
The results are as follows.
Hello