📄 intgen.c
字号:
/* 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 "switches.h"#include "stdlib.h"#include "cext.h"#include <string.h>#ifndef booleantypedef 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#endifstatic 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 1struct { 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}, /* look out! event_type is treated as void to eliminate * warning messages ... */ {"event_type", 'C', "", "v", 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)].initializerstatic 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 */{ *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; return true;}/* error() -- print source file and line *//**/void 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); return 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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -