/* * Some boilerplate code for reading and writing integers in C. */ #include #include int read(void) { int input; fputs(">>> ", stdout); fflush(stdout); if (0 == scanf("%d", &input)) { perror("read"); exit(1); } return input; } void write(int output) { if (0 >= printf("%d\n", output)) { perror("write"); exit(1); } } /* * Define the structure of a cell: an integer "car" followed by a * pointer to a cell "cdr". Such a cell represents a non-empty list of * integers that begins with "car" and continues with "cdr". */ struct cell { int car; struct cell *cdr; }; /* The null pointer to a cell represents the empty list. */ struct cell *const nil = 0; /* * Define the structure of (lambda (lst) (if (null? lst) #f #t)) * It must start with void *jump */ struct anonymous_function_1 { void *jump; }; /* * Define the structure of (lambda (lst) (member? target2 lst)) * It must start with void *jump */ struct anonymous_function_2 { void *jump; int target2; }; /* The main program. */ int main() { /* * Declare local variables. These local variables roughly * correspond to the registers in find.slim. However, local * variables in C and C++ (unlike those in SLIM and Java) have * addresses and can be pointed to by pointers. For example, we * make end point to lst initially below. */ struct cell *lst; struct cell **end; struct cell *cell; int element; int target; int target1; int target2; void **c; /* * The memory location containing lst is the initial end of the list. */ end = &lst; /* * Read a list of integers from the user. */ while (read() != 0) { element = read(); /* * Allocate a new cell and put the new list element in it. * As in print.slim, we assume that there is enough memory * and do not check if the malloc function returns a null * pointer to signal that we have run out of memory. Also as in * print.slim, we ignore the issue of how to reclaim allocated * memory. */ cell = malloc(sizeof(struct cell)); cell->car = element; /* cell->car is shorthand for (*cell).car */ *end = cell; end = &(cell->cdr); /* cell->cdr is shorthand for (*cell).cdr */ /* The parentheses just above are superfluous but clarifying */ } /* * Terminate the list: the rest of the list is the empty list */ *end = nil; /* * Find out from the user what we are looking for */ target1 = read(); target2 = read(); member_twice: /* * Construct (lambda (lst) (member? target2 lst)) and put it into c */ c = malloc(sizeof(struct anonymous_function_2)); ((struct anonymous_function_2 *)c)->jump = &&anonymous_function_2; ((struct anonymous_function_2 *)c)->target2 = target2; /* * Invoke find-c, with our target1 as their target */ target = target1; goto find_c; anonymous_function_2: target = ((struct anonymous_function_2 *)c)->target2; /* fall through */ member: /* * Construct (lambda (lst) (if (null? lst) #f #t)) and put it into c */ c = malloc(sizeof(struct anonymous_function_1)); ((struct anonymous_function_1 *)c)->jump = &&anonymous_function_1; /* * Invoke find-c, with our target as their target */ goto find_c; anonymous_function_1: write(lst != nil); return 0; find_c: if (lst == nil || /* If the list is empty, or */ lst->car == target) /* if the first element in the list is the target */ goto **c; /* then invoke the procedure represented by c */ lst = lst->cdr; /* Advance lst to the rest of the list */ goto find_c; /* Continue with the rest of the list */ }