summaryrefslogtreecommitdiff
path: root/misc/intgen2.c
diff options
context:
space:
mode:
Diffstat (limited to 'misc/intgen2.c')
-rw-r--r--misc/intgen2.c910
1 files changed, 910 insertions, 0 deletions
diff --git a/misc/intgen2.c b/misc/intgen2.c
new file mode 100644
index 0000000..f462815
--- /dev/null
+++ b/misc/intgen2.c
@@ -0,0 +1,910 @@
+/* intgen.c -- an interface generator for xlisp */
+
+/* (c) Copyright Carnegie Mellon University 1991
+ * For a statement of limited permission to use, see Permission.doc
+ *
+ * HISTORY
+ *
+ * 5-Jul-95 Roger Dannenberg
+ * strip directory prefixes from files before writing include statements
+ * 24-Oct-88 Roger Dannenberg at CMU
+ * Changed so that if C routine returns void and has result parameters,
+ * then result parameters are returned by the lisp subr as well as
+ * assigned to *RSLT*.
+ *
+ * 13-Apr-88 Roger Dannenberg at CMU
+ * Modified for xlisp version 2.0
+ *
+ * 22-Dec-87 Roger Dannenberg at NeXT
+ * Added FILE type.
+ *
+ * 21-May-87 Dale Amon at CMU CSD
+ * Included use of NODE *s_true under SCORE_EDITOR conditional. Standard
+ * xlisp code use NODE *true instead.
+ *
+ * 13-May-87 Dale Amon at CMU CSD
+ * Added conditional compilation switch SCORE_EDITOR so that this
+ * program will work with both standard XLISP sources and with Roger's
+ * (ahem) modified version. Also put in error checking for case where
+ * user does not specifiy an output file so program will exit instead
+ * of coredump.
+ */
+
+
+/* Summary and Design: (NOTE THAT AN INTGEN MANUAL IS AVAILABLE)
+ * The first command line argument gives the name of
+ * the .c file to generate. All following arguments are
+ * .h files to read and use as interface specifications.
+ *
+ * The main program opens the output file, calls
+ * write_prelude, and then process_file for each input
+ * file. Then call write_postlude and close the file.
+ *
+ * process_file opens an input file and reads each line
+ * into current_line.
+ * if the first characters of the file are "ih", then
+ * the rest of the file is processed as normal, except the
+ * .h extension of the file is replaced by .ih before the
+ * filename is written into an include statement in the
+ * output file. This is done to handle ".ih" files generated
+ * by the Andrew Toolkit Class processor.
+ * In any case, the first line of EVERY .h file is discarded.
+ * If #define is found, save the following identifier as
+ * macro_name.
+ * If "LISP:" is found, then see if it is preceded by one
+ * or two identifiers and an open paren.
+ * If yes, call routine_call,
+ * else call macro_call.
+ *
+ * routine_call gets the first one or two identifiers off the
+ * line into type_name and routine_name. If there is just one id,
+ * assign it to routine_name and make type_name = "void".
+ * If the routine_name starts with *, remove the * from
+ * routine_name and append "*" to type_name.
+ * Call write_interface with type_name, routine_name, and location
+ * of parameter type description after "LISP:".
+ *
+ * macro_call gets a type_name from the input line after
+ * "LISP:".
+ * Then call write_interface with type_name, macro_name, and
+ * location of parameter type description.
+ *
+ * lisp function names are saved in a table, and an
+ * initialization routine is written to install the new
+ * SUBRs into the xlisp symbol table, as well as to lookup
+ * RSLT_sym, the atom on which results are placed
+ *
+ *
+ */
+
+/* Turn on special handling for Roger's Score Editor if the following #define
+ * is uncommented:
+ */
+/* #define SCORE_EDITOR */
+
+/* Turn on special handling for Chris's Sound Editor if the following #define
+ * is uncommented:
+ */
+/* #define SOUND_EDITOR */
+
+/* Turn on special handling for Nyquist if the following #define
+ * is uncommented:
+ */
+#define NYQUIST
+
+/* atom 't is named s_true if this is defined, o.w. named true: */
+#define S_TRUE 1
+
+/* Turn on special handling for CMU MIDI Toolkit seq_type:
+ */
+#define SEQ_TYPE
+
+#define errfile stdout
+
+#define ident_max 100
+#define line_max 200
+#define subr_max 500
+
+/* prefix for include files not to be included in interface module */
+#define no_include_prefix '~'
+
+#define false 0
+#define true 1
+
+#include "stdlib.h"
+#include "switches.h"
+#include "cext.h"
+#include <string.h>
+#ifndef boolean
+typedef int boolean;
+#endif
+#include "stdio.h"
+#include "ctype.h"
+#include "cmdline.h"
+#ifdef MACINTOSH
+#include "console.h"
+#endif
+
+#ifdef MACINTOSH
+#define FILESEP ':'
+#else
+#ifdef WINDOWS
+#define FILESEP '\\'
+#else
+#define FILESEP '/'
+#endif
+#endif
+
+static char *sindex();
+
+#define whitep(c) ((c) == ' ' || (c) == '\t')
+#define symbolp(c) (isalpha(c) || (c) == '*' || (c) == '_' || (c) == '-' ||\
+ (c) == ':' || isdigit(c) || (c) == '^' || (c) == '*')
+
+/* c and Lisp parameters are encoded in the same table.
+ * Field type_id is the string name of the type.
+ * For c types (return types of C routines), code is 'C',
+ * convert gives the routine for making a lisp node from
+ * the c datum.
+ * listtype_or_special is "v" for types that should be
+ * returned as LISP NIL (e.g. "void"), "s" for types
+ * that when NULL should be returned as NIL, "r"
+ * for normal types, and "" to raise an error.
+ * ctype is not used and should be NULL.
+ * For Lisp types (from parameter specs), code is 'L'.
+ * convert gives the routine that extracts a C value
+ * from a lisp node whose type is given by the field
+ * getarg_or_special.
+ * c_type is the type of the local C variable which is
+ * passed as a parameter to the C routine.
+ * initializer is the initial value for result only parameters
+ *
+ * End of table is marked by a NULL type_id.
+ *
+ * Location 0 is reserved to indicate errors.
+ * Location 1 MUST BE type ANY
+ *
+ */
+
+#define any_index 1
+struct {
+ char *type_id;
+ char code;
+ char *convert;
+ char *getarg_or_special;
+ char *ctype;
+ char *makenode;
+ char *initializer;
+} type_table[] = {
+ {" ", ' ', NULL, NULL, NULL, NULL, NULL},
+ {"ANY", 'L', "", "", "LVAL", "", "NIL"},
+ {"ATOM", 'L', "", "xlgasymbol", "LVAL", "", "NIL"},
+ {"FILE", 'L', "getfile", "xlgastream", "FILE *", "cvfile", "NULL"},
+ {"FIXNUM", 'L', "getfixnum", "xlgafixnum", "long", "cvfixnum", "0"},
+ {"FIXNUM", 'L', "getfixnum", "xlgafixnum", "int", "cvfixnum", "0"},
+ {"FLOAT", 'L', "getflonum", "xlgaflonum", "float", "cvflonum", "0.0"},
+ {"FLONUM", 'L', "getflonum", "xlgaflonum", "double", "cvflonum", "0.0"},
+ {"ANYNUM", 'L', "testarg2", "xlgaanynum", "double", "cvflonum", "0.0"},
+ {"STRING", 'L', "getstring", "xlgastring", "unsigned char *", "cvstring", "NULL"},
+ {"BOOLEAN", 'L', "getboolean", "xlgetarg", "int", "cvboolean", "0"},
+ {"atom_type", 'C', "", "r", NULL, NULL, NULL},
+ {"LVAL", 'C', "", "r", NULL, NULL, "NIL"},
+
+#ifdef SOUND_EDITOR
+ /* Extensions for Sound Type: */
+ {"SOUND", 'L', "getsound", "xlgasound", "SoundPtr", "cvsound", "NULL"},
+ {"SoundPtr", 'C', "cvsound", "r", NULL, NULL, NULL},
+#endif
+
+#ifdef NYQUIST
+ {"SOUND", 'L', "getsound", "xlgasound", "sound_type", "cvsound", "NULL"},
+ {"sound_type", 'C', "cvsound", "r", NULL, NULL, NULL},
+#endif
+#ifdef SEQ_TYPE
+ {"SEQ", 'L', "getseq", "xlgaseq", "seq_type", "cvseq", "NULL"},
+ {"seq_type", 'C', "cvseq", "r", NULL, NULL, NULL},
+#endif
+#ifdef SCORE_EDITOR
+ {"VALUE", 'L', "getval", "xlgaval", "value_type", "cvval", "NULL"},
+ {"value_type", 'C', "cvval", "r", NULL, NULL, NULL},
+ {"EVENT", 'L', "getevent", "xlgaevent", "event_type", "cvevent", "NULL"},
+ {"event_type", 'C', "cvevent", "r", NULL, NULL, NULL},
+ {"score_type", 'C', "cvevent", "r", NULL, NULL, NULL},
+#endif
+#ifdef DMA_EXTENSIONS
+ /* begin DMA entries */
+ {"DEXT", 'L', "getdext", "xlgadext", "ext_type", "cvdext", "NULL"},
+ {"DEXT", 'C', "cvdext", "r", NULL, NULL, NULL},
+ {"SEXT", 'L', "getsext", "xlgasext", "ext_type", "cvsext", "NULL"},
+ {"SEXT", 'C', "cvsext", "r", NULL, NULL, NULL},
+ /* end DMA entries */
+#endif
+ {"int", 'C', "cvfixnum", "r", NULL, NULL, NULL},
+ {"long", 'C', "cvfixnum", "r", NULL, NULL, NULL},
+ {"boolean", 'C', "cvboolean", "r", NULL, NULL, NULL},
+ {"float", 'C', "cvflonum", "r", NULL, NULL, NULL},
+ {"double", 'C', "cvflonum", "r", NULL, NULL, NULL},
+ {"string", 'C', "cvstring", "s", NULL, NULL, NULL},
+ {"char*", 'C', "cvstring", "s", NULL, NULL, NULL},
+ {"char", 'C', "cvfixnum", "r", NULL, NULL, NULL},
+ {"string_type", 'C', "cvstring", "s", NULL, NULL, NULL},
+ {"FILE*", 'C', "cvfile", "s", NULL, NULL, NULL},
+ {"void", 'C', "", "v", NULL, NULL, NULL},
+/*eot*/ {NULL, ' ', NULL, NULL, NULL, NULL, NULL}};
+
+/* subr names get saved here: */
+char *subr_table[subr_max];
+int subr_table_x;
+
+#define get_c_special(i) type_table[(i)].getarg_or_special[0]
+#define get_c_conversion(i) type_table[(i)].convert
+#define get_lisp_extract(i) type_table[(i)].convert
+#define get_lisp_getarg(i) type_table[(i)].getarg_or_special
+#define get_lisp_ctype(i) type_table[(i)].ctype
+#define get_lisp_makenode(i) type_table[(i)].makenode
+#define get_lisp_initializer(i) type_table[(i)].initializer
+
+static void lisp_code();
+static int lookup();
+static void process_file();
+static void routine_call();
+static void write_interface();
+static void write_postlude();
+static void write_prelude();
+static void write_ptrfile();
+
+char source_file[ident_max]; /* source file */
+char current_line[4 * line_max]; /* current line in source file */
+char out_file[ident_max]; /* output file name */
+char ptr_file[ident_max]; /* ptr.h file name */
+char def_file[ident_max]; /* def.h file name */
+
+FILE *lispout = NULL; /* output for lisp source code (if any) */
+
+#define EOS '\000'
+
+/* getarg -- get an identifier from a string */
+/**/
+int getarg(start, result, pos)
+ char *start; /* where to start scanning */
+ char *result; /* where to put the identifier */
+ char **pos; /* ptr to char after identifier in source */
+{
+ char *save = result;
+ *result = EOS;
+ while (whitep(*start) && *start != EOS) start++;
+ if (*start == EOS) return false;
+ if (!symbolp(*start)) return false;
+
+ while (symbolp(*start) && *start != EOS) {
+ *result = *start;
+ result++;
+ start++;
+ }
+ *result = EOS;
+ *pos = start;
+ printf("getarg got %s\n", save);
+ return true;
+}
+
+
+/* error() -- print source file and line */
+/**/
+error()
+{
+ fprintf(errfile, "\n%s: |%s|\n", source_file, current_line);
+}
+
+
+/* lisp_code -- write lisp code to file */
+/*
+ * read from inp if necessary until close comment found
+ */
+static void lisp_code(inp, s)
+ FILE *inp;
+ char *s;
+{
+ char lisp[line_max];
+ char *endcomment;
+ char *inputline; /* for end of file detection */
+
+ if (lispout == NULL) {
+ char lisp_file_name[ident_max];
+ char *extension;
+ strcpy(lisp_file_name, out_file);
+ extension = sindex(lisp_file_name, ".c");
+ strcpy(extension, ".lsp"); /* overwrite .c with .lsp */
+ lispout = fopen(lisp_file_name, "w");
+ if (lispout == NULL) {
+ fprintf(stdout, "Error: couldn't open %s\n", lisp_file_name);
+ exit(1);
+ }
+ printf("writing %s ...\n", lisp_file_name);
+ }
+
+ strcpy(lisp, s); /* don't modify s */
+ inputline = lisp;
+ while (inputline != NULL &&
+ (endcomment = sindex(lisp, "*/")) == NULL) {
+ fputs(lisp, lispout);
+ inputline = fgets(lisp, line_max, inp);
+ }
+ strcpy(endcomment, "\n\n");
+ fputs(lisp, lispout);
+}
+
+
+/* lookup -- find type data */
+/**/
+static int lookup(s, t)
+ char *s;
+ char t;
+{
+ int i = 1;
+ while (type_table[i].type_id != NULL) {
+ if (type_table[i].code == t &&
+ strcmp(type_table[i].type_id, s) == 0)
+ return i;
+ i++;
+ }
+ return 0;
+}
+
+/* macro_call -- generate xlisp interface for C routine */
+/**/
+void macro_call(in, out, curline, macro_name, arg_loc)
+ FILE *in; /* input file */
+ FILE *out; /* output file */
+ char *curline; /* input line */
+ char *macro_name; /* name of the macro to call */
+ char *arg_loc; /* location after "LISP:" */
+{
+ char type_name[ident_max];
+ if (!getarg(arg_loc, type_name, &arg_loc)) {
+ error();
+ fprintf(errfile, "no type given for macro.\n");
+ } else {
+ write_interface(in, out, type_name, macro_name, arg_loc, true);
+ }
+}
+
+
+
+/* main -- generate an xlisp to c interface file */
+/**/
+int main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ char *s;
+ FILE *out;
+ FILE *ptrfile;
+ FILE *deffile;
+ int n;
+
+#ifdef MACINTOSH
+ argc = ccommand(&argv);
+#endif
+
+ for (n = 0; n < subr_max; n++)
+ {
+ subr_table[n] = (char *) malloc(ident_max);
+ subr_table[n][0] = EOS;
+ }
+ subr_table_x = 0;
+
+ cl_init(NULL, 0, NULL, 0, argv, argc);
+ if ((s = cl_arg(1)) != NULL) {
+ strcpy(out_file, s);
+ if (sindex(out_file, ".") == 0)
+ strcat(out_file, ".c");
+ else fprintf(stderr,
+ "1st command line argument should be a legal c identifier\n");
+ out = fopen(out_file, "w");
+ if (out == NULL) {
+ fprintf(stdout, "Error: couldn't open %s\n", out_file);
+ exit(1);
+ }
+ strcpy(ptr_file, s);
+ strcat(ptr_file, "ptrs.h");
+ ptrfile = fopen(ptr_file, "w");
+ if (ptrfile == NULL) {
+ fprintf(stdout, "Error: couldn't open %s\n", ptr_file);
+ exit(1);
+ }
+ strcpy(def_file, s);
+ strcat(def_file, "defs.h");
+ deffile = fopen(def_file, "w");
+ if (deffile == NULL) {
+ fprintf(stdout, "Error: couldn't open %s\n", def_file);
+ exit(1);
+ }
+ } else {
+ fprintf(stdout, "Error: no output file specified\n");
+ exit(1);
+ }
+
+ printf("writing %s ...\n", out_file);
+
+ write_prelude(out, out_file);
+ n = 2;
+ while ((s = cl_arg(n)) != NULL) {
+ printf(" %s\n", s);
+ process_file(s, out);
+ n++;
+ }
+ write_postlude(out);
+ fclose(out);
+ write_ptrfile(ptrfile, deffile);
+ fclose(ptrfile);
+ fclose(deffile);
+ if (lispout != NULL) fclose(lispout);
+ exit(0);
+}
+
+
+static void process_file(fname, out)
+ char *fname;
+ FILE *out;
+{
+ FILE *in;
+ char *cp;
+ char *pos;
+ char incl_file[ident_max]; /* name of file to include */
+ char type_name[ident_max]; /* the type of the routine */
+ char routine_name[ident_max]; /* the name of the routine or macro */
+ char flag = fname[0];
+ boolean reading_parameters = false; /* says we've got a routine, and
+ we're skipping over parameter declarations */
+
+ if (flag == no_include_prefix) fname++;
+
+ strcpy(source_file, fname); /* for error reporting */
+ in = fopen(fname, "r");
+ if (in == NULL) {
+ fprintf(errfile, "couldn't open %s\n", fname);
+ return;
+ }
+
+ /* first check out the first line: if the first two characters are
+ "ih", then replace fname with file.ih so that the CLASS ".ih"
+ file will be included instead of this ".h" file. This is a
+ hack to allow calls into Andrew Tool Kit objects.
+ */
+
+ strcpy(incl_file, fname);
+ if (fgets(current_line, line_max, in) != NULL) {
+ if (current_line[0] == 'i' && current_line[1] == 'h') {
+ cp = sindex(incl_file, ".h");
+ if (cp != NULL) {
+ strcpy(cp, ".ih");
+ }
+ }
+ }
+
+ /* strip off leading directory prefix, if any */
+ cp = strrchr(incl_file, FILESEP); /* find the last slash */
+ if (cp) {
+ strcpy(incl_file, cp + 1 /* skip the slash */);
+ }
+
+ if (flag != no_include_prefix) fprintf(out, "#include \"%s\"\n\n", incl_file);
+
+ while (fgets(current_line, line_max, in) != NULL) {
+ cp = sindex(current_line, "#define");
+ if (cp != NULL) {
+ cp += strlen("#define");
+ if (!getarg(cp, routine_name, &cp)) {
+ error();
+ fprintf(errfile, "#define not followed by identifier\n");
+ }
+ /* watch out for multi-line macros: */
+ while (sindex(current_line, "\\\n")) {
+ if (fgets(current_line, line_max, in) == NULL) return;
+ }
+ } else if ((cp = sindex(current_line, "LISP:")) != NULL) {
+ char type_str[ident_max];
+ char routine_str[ident_max];
+ if (!reading_parameters &&
+ getarg(current_line, type_str, &pos) &&
+ getarg(pos, routine_str, &pos) &&
+ pos < cp) {
+ routine_call(in, out, current_line, type_str, routine_str,
+ cp + strlen("LISP:"));
+ } else if (getarg(cp + strlen("LISP:"), type_str, &pos)) {
+ macro_call(in, out, current_line, routine_name,
+ cp + strlen("LISP:"));
+ } else routine_call(in, out, current_line, type_name, routine_name,
+ cp + strlen("LISP:"));
+ } else if ((cp = sindex(current_line, "LISP-SRC:")) != NULL) {
+ lisp_code(in, cp + strlen("LISP-SRC:"));
+ } else if (reading_parameters && sindex(current_line, ")")) {
+ reading_parameters = false;
+ } else if (reading_parameters) { /* skip */ ;
+ } else if (getarg(current_line, type_name, &pos) &&
+ getarg(pos, routine_name, &pos)) {
+ /* we grabbed the type and routine name. Check to see if the
+ * parameter list is open but not closed on this line: */
+ printf("type_name %s, routine_name %s\n", type_name, routine_name);
+ if (sindex(current_line, "(") && !sindex(current_line, ")")) {
+ reading_parameters = true;
+ }
+ /* printf("saw %s %s\n", type_name, routine_name);*/
+ } else { /* wipe out names for safety: */
+ type_name[0] = EOS;
+ routine_name[0] = EOS;
+ }
+ }
+
+ fclose(in);
+}
+
+
+/* routine_call -- generate xlisp interface for C routine */
+/**/
+static void routine_call(in, out, curline, type_name, routine_name, arg_loc)
+ FILE *in; /* input file */
+ FILE *out; /* output file */
+ char *curline; /* input line */
+ char *type_name; /* type id */
+ char *routine_name; /* routine id */
+ char *arg_loc; /* location after "LISP:" */
+{
+
+ if (*routine_name == EOS) {
+ routine_name = type_name;
+ type_name = "void";
+ }
+ if (*routine_name == '*') {
+ char *r = routine_name;
+ while (*r != EOS) { /* shift left */
+ *r = *(r+1);
+ r++;
+ }
+ strcat(type_name, "*");
+ }
+ write_interface(in, out, type_name, routine_name, arg_loc, false);
+}
+
+
+/* sindex -- find substring */
+/**/
+static char *sindex(sup, sub)
+ char *sup; /* the containing string */
+ char *sub; /* the substring */
+{
+ int i;
+ for ( ; *sup != EOS; sup++) {
+ for (i = 0; true; i++) {
+ if (*(sub+i) == EOS) return sup;
+ if (*(sup+i) != *(sub+i)) break;
+ }
+ }
+ return EOS;
+}
+
+
+/* write_interface -- write SUBR for xlisp */
+/*
+ * NOTE: if is_macro and there are no arguments, then
+ * do not write parens: e.g. "foo" instead of "foo()"
+ */
+static void write_interface(in, out, type_name, fn_name, arg_loc, is_macro)
+ FILE *in; /* input file */
+ FILE *out; /* output file */
+ char *type_name; /* c type for return value */
+ char *fn_name; /* c function to be called */
+ char *arg_loc; /* LISP arg type are described here */
+ int is_macro; /* true if this is a macro */
+{
+ char lispfn[ident_max]; /* lisp fn name */
+ char *cp; /* a temporary */
+ int len; /* a string length */
+#define args_max 20
+ struct {
+ int index; /* table location for this type */
+ int res_flag; /* is a result returned? */
+ } args[args_max];
+ char arg_type[ident_max]; /* the original type spec */
+ char *c_type; /* c type for an argument */
+ char *c_str; /* temp for a c code line */
+ int argcnt = 0; /* counts arguments */
+ int i; /* argument index */
+ int result_flag = false; /* true if there are result parameters */
+ int result_x; /* index of result type */
+ char newline[line_max]; /* place to read continuation lines */
+
+
+/* printf("write_interface: %s %s %s", type_name, fn_name, arg_loc);*/
+ if (*type_name == EOS || *fn_name == EOS) {
+ error();
+ fprintf(errfile, "Error: bad syntax, maybe missing type\n");
+ return;
+ }
+
+ while (*arg_loc != '(' && *arg_loc != EOS) arg_loc++;
+ if (*arg_loc == EOS) {
+ error();
+ fprintf(errfile, "Error: '(' expected after 'LISP:'\n");
+ return;
+ } else arg_loc++;
+ if (!getarg(arg_loc, lispfn, &arg_loc)) {
+ error();
+ fprintf(stdout, "Error: lisp function name expected\n");
+ return;
+ }
+ /* make it upper case: */
+ for (cp = lispfn; *cp != EOS; cp++) {
+ if (islower(*cp)) *cp = toupper(*cp);
+ }
+
+ /* save SUBR name */
+ strcpy(subr_table[subr_table_x], lispfn);
+ subr_table_x++;
+
+ /* make lispfn lower case, dash, colon -> underscore: */
+ for (cp = lispfn; *cp != EOS; cp++) {
+ if (isupper(*cp)) *cp = tolower(*cp);
+ if (*cp == '-' || *cp == ':') *cp = '_';
+ }
+
+ /* append continuation lines to arg_loc to handle multi-line specs */
+ while (sindex(arg_loc, "*/") == NULL) {
+ /* remove newline */
+ if (strlen(arg_loc) > 0)
+ arg_loc[strlen(arg_loc) - 1] = EOS;
+ if (fgets(newline, line_max, in) == NULL) {
+ error();
+ fprintf(stdout, "Error: end of file unexpected\n");
+ exit(1);
+ }
+ if ((strlen(arg_loc) + strlen(newline)) > (3 * line_max)) {
+ error();
+ fprintf(stdout,
+ "Error: specification too long or missing end of comment.\n");
+ exit(1);
+ }
+ strcat(arg_loc, newline);
+ }
+
+ fprintf(out, "/%c xlc_%s -- interface to C routine %s */\n/**/\n",
+ '*', lispfn, fn_name);
+
+ fprintf(out, "LVAL xlc_%s(void)\n{\n", lispfn);
+ while (getarg(arg_loc, arg_type, &arg_loc)) {
+ int result_only_flag = false;
+
+ if (argcnt >= args_max) {
+ error();
+ fprintf(errfile,
+ "Internal error: too many args, increase args_max\n");
+ }
+ len = strlen(arg_type);
+ if (arg_type[len-1] == '*') {
+ arg_type[len-1] = EOS;
+ args[argcnt].res_flag = true;
+ result_flag = true;
+ } else if (arg_type[len-1] == '^') {
+ arg_type[len-1] = EOS;
+ args[argcnt].res_flag = true;
+ result_flag = true;
+ result_only_flag = true;
+ } else args[argcnt].res_flag = false;
+
+ args[argcnt].index = lookup(arg_type, 'L');
+ c_type = get_lisp_ctype(args[argcnt].index);
+
+ if (c_type == NULL) {
+ error();
+ fprintf(errfile, "Error: %s undefined, using int.\n",
+ arg_type);
+ c_type = "int";
+ args[argcnt].index = lookup("FIXNUM", 'L');
+ }
+ fprintf(out, " %s arg%d = ", c_type, argcnt+1);
+ if (result_only_flag) {
+ fprintf(out, "%s;\n",
+ get_lisp_initializer(args[argcnt].index));
+ } else if (args[argcnt].index == any_index) {
+ fprintf(out, "xlgetarg();\n");
+ } else {
+ c_str = "%s(%s());\n";
+ fprintf(out,c_str,
+ get_lisp_extract(args[argcnt].index),
+ get_lisp_getarg(args[argcnt].index));
+ }
+ argcnt++;
+ }
+
+ if (*arg_loc != ')') {
+ fprintf(errfile,
+ "Warning: paren expected immediately after last arg of %s\n",
+ lispfn);
+ }
+
+ /* check for close paren and close comment: */
+ cp = sindex(arg_loc, ")");
+ if (cp == NULL || sindex(cp+1, "*/") == NULL) {
+ error();
+ fprintf(errfile, "Warning: close paren and close comment expected\n");
+ }
+
+ /* lookup result type */
+ result_x = lookup(type_name, 'C');
+ if (result_x == 0) {
+ fprintf(errfile, "Error: unknown type: %s, assuming void\n",
+ type_name);
+ result_x = lookup("void", 'C');
+ }
+
+ /* if there are result parameters then return them rather than NIL
+ * when the type is void
+ */
+ if (get_c_special(result_x) == 'v' && result_flag) {
+ fprintf(out, " LVAL result;\n");
+ }
+
+ if (get_c_special(result_x) != 'v') {
+ /* declare result: */
+ fprintf(out, " %s result;\n", type_name);
+ }
+
+ /* check for end of argument list: */
+ fprintf(out, "\n xllastarg();\n");
+
+ /* if there are results, we'll call cons, so
+ * protect the result from garbage collection
+ * if necessary
+ */
+ if (result_flag && strcmp(type_name, "LVAL") == 0) {
+ fprintf(out, " xlprot1(result);\n");
+ }
+
+ /* call the c routine */
+ if (get_c_special(result_x) != 'v') {
+ fprintf(out, " result = ");
+ } else fprintf(out, " ");
+ fprintf(out, "%s", fn_name);
+ if (!is_macro || argcnt > 0) fprintf(out, "(");
+
+ /* pass arguments: */
+ for (i = 0; i < argcnt; i++) {
+ if (i > 0) fprintf(out, ", ");
+ if (args[i].res_flag) fprintf(out, "&");
+ fprintf(out, "arg%d", i+1);
+ }
+ if (!is_macro || argcnt > 0) fprintf(out, ")");
+ fprintf(out, ";\n");
+
+ /* put results (if any) on *RSLT* */
+ if (result_flag) {
+ int wrote_one_flag = false;
+ fprintf(out, " {\tLVAL *next = &getvalue(RSLT_sym);\n");
+ for (i = 0; i < argcnt; i++) {
+ if (args[i].res_flag) {
+ if (wrote_one_flag)
+ fprintf(out, "\tnext = &cdr(*next);\n");
+ wrote_one_flag = true;
+ fprintf(out, "\t*next = cons(NIL, NIL);\n");
+ fprintf(out, "\tcar(*next) = %s(arg%d);",
+ get_lisp_makenode(args[i].index), i+1);
+ }
+ }
+ fprintf(out, "\n }\n");
+
+ /* copy *RSLT* to result if appropriate */
+ if (get_c_special(result_x) == 'v') {
+ fprintf(out, " result = getvalue(RSLT_sym);\n");
+ }
+ }
+
+
+ /* generate xlpop() if there was an xlprot1() */
+ if (result_flag && strcmp(type_name, "LVAL") == 0) {
+ fprintf(out, " xlpop();\n");
+ }
+
+
+ /* now return actual return value */
+ if (get_c_special(result_x) == EOS) {
+ error();
+ fprintf(errfile, "Warning: unknown type from C, coercing to int.\n");
+ fprintf(out, " return cvfixnum((int) result);\n");
+ } else if (get_c_special(result_x) == 'v' && !result_flag) {
+ fprintf(out, " return NIL;\n");
+ } else if (get_c_special(result_x) == 'v' && result_flag) {
+ fprintf(out, " return result;\n");
+ } else if (get_c_special(result_x) == 's') {
+ fprintf(out, " if (result == NULL) return NIL;\n");
+ fprintf(out, " else return %s(result);\n",
+ get_c_conversion(result_x));
+ } else {
+ fprintf(out, " return %s(result);\n",
+ get_c_conversion(result_x));
+ }
+ fprintf(out, "}\n\n\n");
+}
+
+
+/* write_postlude -- write stuff at end of file */
+/**/
+static void write_postlude(out)
+ FILE *out;
+{
+ /* nothing to do for version 2 */
+}
+
+
+/* write_ptrfile -- write function definition table */
+/**/
+static void write_ptrfile(pf, df)
+ FILE *pf;
+ FILE *df;
+{
+ int n;
+ char *cp;
+ char cname[ident_max];
+
+ for (n = 0; n < subr_table_x; n++) {
+ strcpy(cname, subr_table[n]);
+ /* make cname lower case, dash,colon -> underscore: */
+ for (cp = cname; *cp != EOS; cp++) {
+ if (isupper(*cp)) *cp = tolower(*cp);
+ if (*cp == '-' || *cp == ':') *cp = '_';
+ }
+ fprintf(df, "extern LVAL xlc_%s(void);\n", cname);
+ fprintf(pf, " { \"%s\", S, xlc_%s}, \n", subr_table[n], cname);
+ }
+ printf(" Add %s to localdefs.h and add %s to localptrs.h\n",
+ def_file, ptr_file);
+}
+
+
+/* write_prelude -- write stuff at head of file */
+/**/
+static void write_prelude(out, out_file)
+ FILE *out;
+ char *out_file;
+{
+ int i = 2;
+ int col = strlen(out_file) + 21;
+ char *s;
+ fprintf(out, "/%c %s -- interface to ",
+ '*', out_file);
+ while ((s = cl_arg(i)) != NULL) {
+ if (i > 2) {
+ fprintf(out, ", ");
+ col += 2;
+ }
+ col += strlen(s) + 2;
+ if (col > 65) {
+ fprintf(out, "\n * ");
+ col = 4 + strlen(s) + 2;
+ }
+ fprintf(out, "%s", s);
+ i++;
+ }
+ fprintf(out, " */\n\n%cifndef mips\n%cinclude \"stdlib.h\"\n", '#', '#');
+ fprintf(out, "%cendif\n%cinclude \"xlisp.h\"\n\n", '#', '#');
+#ifdef S_TRUE
+ fprintf(out, "extern LVAL s_true;\n");
+ fprintf(out, "%cdefine cvboolean(i) ((i) ? s_true : NIL)\n", '#');
+#else
+ fprintf(out, "extern LVAL true;\n");
+ fprintf(out, "%cdefine cvboolean(i) ((i) ? true : NIL)\n", '#');
+#endif
+
+ fprintf(out, "%c%s\n",
+ '#',
+ "define testarg2(e) (moreargs() ? (e) : (getflonum(xltoofew())))");
+
+ fprintf(out, "%c%s\n%s\n%s\n",
+ '#',
+ "define xlgaanynum() (floatp(*xlargv) ? getflonum(nextarg()) : \\",
+ " (fixp(*xlargv) ? (double) getfixnum(nextarg()) : \\",
+/* note: getflonum never gets called here, but this makes typechecking happy */
+ " getflonum(xlbadtype(*xlargv))))");
+
+ fprintf(out, "%cdefine getboolean(lval) ((lval) != NIL)\n\n", '#');
+ fprintf(out, "extern LVAL RSLT_sym;\n\n\n");
+}