|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: F T
Length: 10163 (0x27b3)
Types: TextFile
Names: »Findprim.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/gnu-31mar87/scheme/microcode/Findprim.c«
/* Emacs, please use -*-C-*- mode */
/****************************************************************
* *
* Copyright (c) 1985 *
* Massachusetts Institute of Technology *
* *
* This material was developed by the Scheme project at the *
* Massachusetts Institute of Technology, Department of *
* Electrical Engineering and Computer Science. Permission to *
* copy this software, to redistribute it, and to use it for any *
* purpose is granted, subject to the following restrictions and *
* understandings. *
* *
* 1. Any copy made of this software must include this copyright *
* notice in full. *
* *
* 2. Users of this software agree to make their best efforts (a)*
* to return to the MIT Scheme project any improvements or *
* extensions that they make, so that these may be included in *
* future releases; and (b) to inform MIT of noteworthy uses of *
* this software. *
* *
* 3. All materials developed as a consequence of the use of *
* this software shall duly acknowledge such use, in accordance *
* with the usual standards of acknowledging credit in academic *
* research. *
* *
* 4. MIT has made no warrantee or representation that the *
* operation of this software will be error-free, and MIT is *
* under no obligation to provide any services, by way of *
* maintenance, update, or otherwise. *
* *
* 5. In conjunction with products arising from the use of this *
* material, there shall be no use of the name of the *
* Massachusetts Institute of Technology nor of any adaptation *
* thereof in any advertising, promotional, or sales literature *
* without prior written consent from MIT in each case. *
* *
****************************************************************/
/* File: Findprim.c
*
* Preprocessor to find and declare user defined primitives.
*
* Searches for a token which is a macro defined in primitive.h.
* For each macro invocation it creates an entry in the External
* Primitives descriptor used by Scheme. The entry consists of
* the C routine implementing the primitive, the (fixed) number of
* arguments it requires, and the name Scheme uses to refer to it.
*
* The output is a C source file (on stdout, must be redirected)
* to be compiled and linked with the Scheme microcode.
*/
\f
/* In the following some output lines are done in a strange fashion
* because some C compilers (the vms C compiler, for example) remove
* comments even from within string quotes!!
*/
static char The_Token[] = "Define_Primitive";
/* Maximum number of primitives that can be handled. */
#ifndef BUFFER_SIZE
#define BUFFER_SIZE 200
#endif
\f
#include <stdio.h>
/* For macros toupper, isalpha, etc, supposedly on the standard library */
#include <ctype.h>
#ifdef vax
#ifdef vms
#define normal_exit() return
#else /* Vax, but not a VMS */
#define normal_exit() exit(0)
#include <strings.h>
#endif
#else /* Not a Vax */
#define normal_exit() exit(0)
#endif
#define TRUE 1
#define FALSE 0
typedef int boolean;
#ifdef DEBUGGING
#define dprintf(one, two) fprintf(stderr, one, two)
#else
#define dprintf(one, two)
#endif
static FILE *input, *output;
static char *name;
static char *file_name;
#define error_exit(do_it) { if (do_it) dump(TRUE); exit(1); }
main(argc, argv)
int argc;
char *argv[];
{ FILE *fopen();
name = argv[0];
/* Check for specified output file */
if ((argc >= 2) && (strcmp("-o", argv[1])==0))
{ if ((output = fopen(argv[2], "w")) == NULL)
{ fprintf(stderr, "Error: %s can't open %s\n", name, argv[2]);
error_exit(FALSE);
}
argv += 2;
argc -= 2;
}
else output = stdout;
if (argc == 1)
{ dump(FALSE);
normal_exit();
}
while (--argc > 0)
{ file_name = *++argv;
if (strcmp("-", file_name)==0)
{ input = stdin;
file_name = "stdin";
dprintf("About to process %s\n", "STDIN");
process();
}
else if ((input = fopen(file_name, "r")) == NULL)
{ fprintf(stderr, "Error: %s can't open %s\n", name, file_name);
error_exit(TRUE);
}
else
{ dprintf("About to process %s\n", file_name);
process();
fclose(input);
}
}
dprintf("About to sort %s\n", "");
sort();
dprintf("About to dump %s\n", "");
dump(TRUE);
if (output != stdout) fclose(output);
normal_exit();
}
\f
#define DONE 0
#define FOUND 1
/* Search for tokens and when found, create primitive entries. */
process()
{ while ((scan() != DONE))
{ dprintf("Process: place found.%s\n", "");
create_entry();
}
}
/* Search for token and stop when found. If you hit open comment
* character, read until you hit close comment character.
* FIX: It is not a complete C parser, thus it may be fooled,
* currently the token must always begin a line.
*/
scan()
{ register char c, *temp;
c = '\n';
while(c != EOF)
{
switch(c)
{ case '/':
if ((c = getc(input)) == '*')
{ c = getc(input);
while (TRUE)
{ while (c != '*')
{ if (c == EOF)
{ fprintf(stderr,
"Error: EOF in comment in file %s, or %s confused\n",
file_name, name);
error_exit(TRUE);
}
c = getc(input);
}
if ((c = getc(input)) == '/') break;
}
}
else if (c != '\n') break;
case '\n':
temp = &The_Token[0];
while ((c = getc(input)) == *temp++) {}
if (temp[-1] == '\0') return FOUND;
ungetc(c, input);
break;
default: {}
}
c = getc(input);
}
return DONE;
}
\f
#define STRING_SIZE 80
#define ARITY_SIZE 6
typedef struct dsc
{ char C_Name[STRING_SIZE]; /* The C name of the function */
char Arity[ARITY_SIZE]; /* Number of arguments */
char Scheme_Name[STRING_SIZE]; /* Scheme name of the primitive */
} descriptor;
/* FIX: This should really be malloced incrementally,
* but for the time being ... */
descriptor Data_Buffer[BUFFER_SIZE]; /* New Primitives Allowed */
static int buffer_index = 0;
static int C_Size = 0;
static int A_Size = 0;
static int S_Size = 0;
#define DONT_CAP FALSE
#define DO_CAP TRUE
create_entry()
{ if (buffer_index >= BUFFER_SIZE)
{ fprintf(stderr, "Error: %s cannot handle so many primitives.\n", name);
fprintf(stderr, "Recompile %s with BUFFER_SIZE larger than %d.\n",
name, BUFFER_SIZE);
error_exit(FALSE);
}
scan_to_token_start();
copy_token((Data_Buffer[buffer_index]).C_Name, DONT_CAP, &C_Size);
scan_to_token_start();
copy_token((Data_Buffer[buffer_index]).Arity, DONT_CAP, &A_Size);
scan_to_token_start();
copy_token((Data_Buffer[buffer_index]).Scheme_Name, DO_CAP, &S_Size);
buffer_index++;
}
scan_to_token_start()
{ char c;
while (whitespace(c = getc(input))) {};
ungetc(c, input);
}
/* FIX: This should check for field overflow (n too small) */
copy_token(s, cap, Size)
char s[];
boolean cap;
int *Size;
{ register char c;
register int n = 0;
while (!(whitespace(c = getc(input))))
s[n++] = ((cap && isalpha(c) && islower(c))? toupper(c) : c);
s[n] = '\0';
if (n > *Size) *Size = n;
}
whitespace(c)
char c;
{ switch(c)
{ case ' ':
case '(':
case ')':
case ',': return TRUE;
default: return FALSE;
}
}
\f
/* FIX: No-op for now */
sort()
{ return FALSE;
}
\f
print_spaces(how_many)
register int how_many;
{ for(; --how_many >= 0;) putc(' ', output);
}
#define print_entry(index) \
fprintf(output, " %s,", (Data_Buffer[index].C_Name)); \
print_spaces(1+ \
(C_Size-(strlen(Data_Buffer[index].C_Name)))+ \
(A_Size-(strlen(Data_Buffer[index].Arity)))); \
fprintf(output, "%s", (Data_Buffer[index]).Arity); \
fprintf(output, ", %s", (Data_Buffer[index]).Scheme_Name); \
print_spaces(S_Size-(strlen(Data_Buffer[index].Scheme_Name))); \
fprintf(output, " /%c External %d %c/", '*', index, '*')
/* Produce C source. */
dump(check)
boolean check;
{ register int count;
int max = buffer_index-1;
/* Print header. */
fprintf(output, "/%c User defined primitive declarations %c/\n\n",
'*', '*');
fprintf(output, "#include \"scheme.h\"\n\n");
if (max < 0)
{
if (check) fprintf(stderr, "No User primitives found!\n");
/* C does not understand the empty array, thus it must be faked. */
fprintf(output, "/%c C does not understand the empty array, ", '*');
fprintf(output, "thus it must be faked. %c/\n\n", '*');
/* Dummy entry */
fprintf(output, "Pointer Dummy_Primitive()\n");
fprintf(output, "{ /%c This should NEVER be called. %c/\n", '*', '*');
fprintf(output, " Microcode_Termination(TERM_BAD_PRIMITIVE);\n");
fprintf(output, "}\n\n");
/* Array with Dummy entry */
fprintf(output, "External_Descriptor Ext_Prim_Desc[] = {\n");
fprintf(output, " Dummy_Primitive, 0, \"DUMMY-PRIMITIVE\"\n");
fprintf(output, "};\n\n");
}
else
{
/* Print extern declarations. */
fprintf(output, "extern Pointer\n");
for (count = 0; count < max; count++)
fprintf(output, " %s(),\n", Data_Buffer[count].C_Name);
fprintf(output, " %s();\n\n", Data_Buffer[max].C_Name);
/* Print structure. */
fprintf(output, "External_Descriptor Ext_Prim_Desc[] = {\n");
for (count = 0; count < max; count++)
{ print_entry(count);
fprintf(output, ",\n");
}
print_entry(max);
fprintf(output, "\n};\n\n");
}
fprintf(output, "long MAX_EXTERNAL_PRIMITIVE = %d;\n\n", max);
return;
}