2018-03-04 23:13:08 +03:00
|
|
|
/* Runtime library */
|
|
|
|
|
|
|
|
|
|
# include <stdio.h>
|
2018-04-30 17:18:41 +03:00
|
|
|
# include <stdio.h>
|
|
|
|
|
# include <malloc.h>
|
|
|
|
|
# include <string.h>
|
|
|
|
|
# include <stdarg.h>
|
|
|
|
|
# include <alloca.h>
|
|
|
|
|
|
|
|
|
|
# define STRING_TAG 0x00000000
|
2018-05-16 09:24:40 +03:00
|
|
|
# define ARRAY_TAG 0x01000000
|
|
|
|
|
# define SEXP_TAG 0x02000000
|
2018-04-30 17:18:41 +03:00
|
|
|
|
|
|
|
|
# define LEN(x) (x & 0x00FFFFFF)
|
|
|
|
|
# define TAG(x) (x & 0xFF000000)
|
|
|
|
|
|
|
|
|
|
# define TO_DATA(x) ((data*)((char*)(x)-sizeof(int)))
|
2018-05-16 09:24:40 +03:00
|
|
|
# define TO_SEXP(x) ((sexp*)((char*)(x)-2*sizeof(int)))
|
2018-04-30 17:18:41 +03:00
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
int tag;
|
|
|
|
|
char contents[0];
|
|
|
|
|
} data;
|
|
|
|
|
|
2018-05-16 09:24:40 +03:00
|
|
|
typedef struct {
|
|
|
|
|
int tag;
|
|
|
|
|
data contents;
|
|
|
|
|
} sexp;
|
|
|
|
|
|
2018-04-30 17:18:41 +03:00
|
|
|
extern int Blength (void *p) {
|
|
|
|
|
data *a = TO_DATA(p);
|
|
|
|
|
return LEN(a->tag);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern void* Belem (void *p, int i) {
|
|
|
|
|
data *a = TO_DATA(p);
|
|
|
|
|
|
|
|
|
|
if (TAG(a->tag) == STRING_TAG) return (void*)(int)(a->contents[i]);
|
2018-05-16 09:24:40 +03:00
|
|
|
|
|
|
|
|
//printf ("elem %d = %p\n", i, (void*) ((int*) a->contents)[i]);
|
|
|
|
|
|
2018-04-30 17:18:41 +03:00
|
|
|
return (void*) ((int*) a->contents)[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern void* Bstring (void *p) {
|
|
|
|
|
int n = strlen (p);
|
|
|
|
|
data *r = (data*) malloc (n + 1 + sizeof (int));
|
|
|
|
|
|
|
|
|
|
r->tag = n;
|
|
|
|
|
strncpy (r->contents, p, n + 1);
|
|
|
|
|
|
|
|
|
|
return r->contents;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern void* Barray (int n, ...) {
|
|
|
|
|
va_list args;
|
|
|
|
|
int i;
|
|
|
|
|
data *r = (data*) malloc (sizeof(int) * (n+1));
|
|
|
|
|
|
2018-05-16 09:24:40 +03:00
|
|
|
r->tag = ARRAY_TAG | n;
|
2018-04-30 17:18:41 +03:00
|
|
|
|
|
|
|
|
va_start(args, n);
|
|
|
|
|
|
|
|
|
|
for (i=0; i<n; i++) {
|
|
|
|
|
int ai = va_arg(args, int);
|
|
|
|
|
((int*)r->contents)[i] = ai;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
|
|
return r->contents;
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-16 09:24:40 +03:00
|
|
|
extern void* Bsexp (int n, ...) {
|
2018-04-30 17:18:41 +03:00
|
|
|
va_list args;
|
2018-05-16 09:24:40 +03:00
|
|
|
int i;
|
|
|
|
|
sexp *r = (sexp*) malloc (sizeof(int) * (n+2));
|
|
|
|
|
data *d = &(r->contents);
|
2018-04-30 17:18:41 +03:00
|
|
|
|
2018-05-16 09:24:40 +03:00
|
|
|
d->tag = SEXP_TAG | (n-1);
|
|
|
|
|
|
|
|
|
|
va_start(args, n);
|
|
|
|
|
|
2018-04-30 17:18:41 +03:00
|
|
|
for (i=0; i<n-1; i++) {
|
2018-05-16 09:24:40 +03:00
|
|
|
int ai = va_arg(args, int);
|
|
|
|
|
//printf ("arg %d = %x\n", i, ai);
|
|
|
|
|
((int*)d->contents)[i] = ai;
|
2018-04-30 17:18:41 +03:00
|
|
|
}
|
|
|
|
|
|
2018-05-16 09:24:40 +03:00
|
|
|
r->tag = va_arg(args, int);
|
|
|
|
|
va_end(args);
|
2018-04-30 17:18:41 +03:00
|
|
|
|
2018-05-16 09:24:40 +03:00
|
|
|
//printf ("tag %d\n", r->tag);
|
|
|
|
|
//printf ("returning %p\n", d->contents);
|
|
|
|
|
|
|
|
|
|
return d->contents;
|
2018-04-30 17:18:41 +03:00
|
|
|
}
|
|
|
|
|
|
2018-05-16 09:24:40 +03:00
|
|
|
extern int Btag (void *d, int t) {
|
|
|
|
|
data *r = TO_DATA(d);
|
|
|
|
|
return TAG(r->tag) == SEXP_TAG && TO_SEXP(d)->tag == t;
|
2018-04-30 17:18:41 +03:00
|
|
|
}
|
2018-05-16 09:24:40 +03:00
|
|
|
|
|
|
|
|
extern void Bsta (int n, int v, void *s, ...) {
|
2018-04-30 17:18:41 +03:00
|
|
|
va_list args;
|
2018-05-16 09:24:40 +03:00
|
|
|
int i, k;
|
|
|
|
|
data *a;
|
|
|
|
|
|
|
|
|
|
va_start(args, s);
|
2018-04-30 17:18:41 +03:00
|
|
|
|
|
|
|
|
for (i=0; i<n-1; i++) {
|
|
|
|
|
k = va_arg(args, int);
|
2018-05-16 09:24:40 +03:00
|
|
|
s = ((int**) s) [k];
|
2018-04-30 17:18:41 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
k = va_arg(args, int);
|
2018-05-16 09:24:40 +03:00
|
|
|
a = TO_DATA(s);
|
2018-04-30 17:18:41 +03:00
|
|
|
|
2018-05-16 09:24:40 +03:00
|
|
|
if (TAG(a->tag) == STRING_TAG)((char*) s)[k] = (char) v;
|
|
|
|
|
else ((int*) s)[k] = v;
|
2018-04-30 17:18:41 +03:00
|
|
|
}
|
|
|
|
|
|
2018-05-16 09:24:40 +03:00
|
|
|
void Lprintf (char *s, ...) {
|
2018-04-30 17:18:41 +03:00
|
|
|
va_list args;
|
|
|
|
|
|
2018-05-16 09:24:40 +03:00
|
|
|
va_start (args, s);
|
|
|
|
|
vprintf (s, args);
|
|
|
|
|
va_end (args);
|
2018-04-30 17:18:41 +03:00
|
|
|
}
|
|
|
|
|
|
2018-05-16 09:24:40 +03:00
|
|
|
void Lfprintf (FILE *f, char *s, ...) {
|
2018-04-30 17:18:41 +03:00
|
|
|
va_list args;
|
|
|
|
|
|
2018-05-16 09:24:40 +03:00
|
|
|
va_start (args, s);
|
|
|
|
|
vfprintf (f, s, args);
|
2018-04-30 17:18:41 +03:00
|
|
|
va_end (args);
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-16 09:24:40 +03:00
|
|
|
FILE* Lfopen (char *f, char *m) {
|
|
|
|
|
return fopen (f, m);
|
2018-04-30 17:18:41 +03:00
|
|
|
}
|
|
|
|
|
|
2018-05-16 09:24:40 +03:00
|
|
|
void Lfclose (FILE *f) {
|
|
|
|
|
fclose (f);
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-04 23:13:08 +03:00
|
|
|
/* Lread is an implementation of the "read" construct */
|
|
|
|
|
extern int Lread () {
|
|
|
|
|
int result;
|
|
|
|
|
|
|
|
|
|
printf ("> ");
|
|
|
|
|
fflush (stdout);
|
|
|
|
|
scanf ("%d", &result);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Lwrite is an implementation of the "write" construct */
|
|
|
|
|
extern int Lwrite (int n) {
|
|
|
|
|
printf ("%d\n", n);
|
|
|
|
|
fflush (stdout);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2018-04-30 17:18:41 +03:00
|
|
|
|