Browse Source

adding passdb_slim

* needed to alter some header files to accomodate
* added some binaries to .gitignore so we can compile without getting
  cruft on git events
* old style libraries '-l' command line option position causes gcc problems. Put
  at end of line to fix
clementinecomputing 6 years ago
parent
commit
4bf1da5b58
38 changed files with 16595 additions and 2 deletions
  1. 9 0
      .gitignore
  2. 1 1
      busunit/billdb/buildit.sh
  3. 4 0
      busunit/commhub/commhub.h
  4. 36 0
      busunit/common/common_defs.h
  5. 78 0
      busunit/common/log_local.c
  6. 17 0
      busunit/common/log_local.h
  7. 1 1
      busunit/paddlemgr/buildit.sh
  8. 134 0
      busunit/passdb_slim/aux/fpeek.c
  9. 62 0
      busunit/passdb_slim/aux/send_magstripe.c
  10. 28 0
      busunit/passdb_slim/buildit.sh
  11. 8 0
      busunit/passdb_slim/buildit_native.sh
  12. 8 0
      busunit/passdb_slim/buildit_viper.sh
  13. 150 0
      busunit/passdb_slim/byte_access.c
  14. 45 0
      busunit/passdb_slim/byte_access.h
  15. 1533 0
      busunit/passdb_slim/pass_communication.c
  16. 3647 0
      busunit/passdb_slim/passdb_slim.c
  17. 290 0
      busunit/passdb_slim/passdb_slim.h
  18. 560 0
      busunit/passdb_slim/passdb_slim_config.c
  19. 161 0
      busunit/passdb_slim/rfid_decoder.c
  20. 6 0
      busunit/passdb_slim/rfid_decoder.h
  21. 954 0
      busunit/passdb_slim/ruleparam_db.c
  22. 90 0
      busunit/passdb_slim/ruleparam_db.h
  23. 1623 0
      busunit/passdb_slim/rules.c
  24. 45 0
      busunit/passdb_slim/rules.h
  25. 139 0
      busunit/passdb_slim/tinyscheme1.39/BUILDING
  26. 208 0
      busunit/passdb_slim/tinyscheme1.39/CHANGES
  27. 31 0
      busunit/passdb_slim/tinyscheme1.39/COPYING
  28. 449 0
      busunit/passdb_slim/tinyscheme1.39/Manual.txt
  29. 88 0
      busunit/passdb_slim/tinyscheme1.39/MiniSCHEMETribute.txt
  30. 145 0
      busunit/passdb_slim/tinyscheme1.39/dynload.c
  31. 12 0
      busunit/passdb_slim/tinyscheme1.39/dynload.h
  32. 236 0
      busunit/passdb_slim/tinyscheme1.39/hack.txt
  33. 576 0
      busunit/passdb_slim/tinyscheme1.39/init.scm
  34. 87 0
      busunit/passdb_slim/tinyscheme1.39/makefile
  35. 191 0
      busunit/passdb_slim/tinyscheme1.39/opdefines.h
  36. 187 0
      busunit/passdb_slim/tinyscheme1.39/scheme-private.h
  37. 4540 0
      busunit/passdb_slim/tinyscheme1.39/scheme.c
  38. 216 0
      busunit/passdb_slim/tinyscheme1.39/scheme.h

+ 9 - 0
.gitignore

@@ -2,8 +2,13 @@
 *.swp
 .bak
 
+avls
 diu_minder
+client_supervisor
+
 piu_minder
+showmessage
+
 billdb
 debug_client
 ipc_server
@@ -11,6 +16,10 @@ paddlemgr
 passdb
 diuhttpd
 
+passdb_slim
+fpeek
+send_magstripe
+
 *.o
 *.a
 *.so

+ 1 - 1
busunit/billdb/buildit.sh

@@ -2,7 +2,7 @@
 
 rm -f billdb send_billing_record
 
-$target_cc $target_ccopts -lcrypto -o billdb billdb.c bill_communication.c ../commhub/commhub.c ../commhub/client_utils.c ../common/common_defs.c
+$target_cc $target_ccopts -o billdb billdb.c bill_communication.c ../commhub/commhub.c ../commhub/client_utils.c ../common/common_defs.c -lcrypto
 
 $target_cc $target_ccopts -o send_billing_record send_billing_record.c ../commhub/commhub.c ../common/common_defs.c
 

+ 4 - 0
busunit/commhub/commhub.h

@@ -185,6 +185,10 @@ long long int get_usec_time();
 #define MAILBOX_RULE_CALL	"RULE_CALL"		//Request the passdb module to execute a rule.  Payload is driver_rulecall_struct
 #define MAILBOX_VAULT_DROP	"VAULT_DROP"		//Request the cash vault drop
 
+#define MAILBOX_PASSDB_CONSISTENCY    "PASSDB_CONSIST"  //Have the passdb do a consistency check
+#define MAILBOX_PASSDB_PULSE            "PASSDB_PULSE"          //Generate a 'pulse' string to stderr
+
+
 //------------------------------------------------ MESSAGE BODY DATA STRUCTURES
 
 typedef struct gps_status_struct

+ 36 - 0
busunit/common/common_defs.h

@@ -25,6 +25,42 @@
 
 //#define COMMON_PRINT_WARNING
 
+//------------------------------- PASSDB_SLIM ----------------------------------
+
+#define CHECK_ALLOC_FAIL( x ) if (!(x)) { fprintf(stderr, "CHECK_ALLOC_FAIL: %s, line %i: (%s is null)\n", __FILE__, __LINE__, #x ); return FAIL_MEM; }
+
+#define INDEX_MIDPOINT 1000000
+
+#ifdef TARGET_DEVEL_DESKTOP
+  #define PASSDB_SLIM_CONFIG_FILE "./examples/passdb.conf"
+#else
+  #define PASSDB_SLIM_CONFIG_FILE "/mnt/data2/config/passdb.conf"
+#endif
+
+#define CREDENTIAL_LEN  (32)
+#define RULENAME_LEN    (24)
+#define PARAM_LEN       (24)
+
+//#define RIDER_TWO_CRED_SIZE ( sizeof(seq_t) + sizeof(logical_card_id_t) + sizeof(unsigned char) + sizeof(unsigned long long) + sizeof(unsigned char) + sizeof (unsigned long) + sizeof(unsigned long) + sizeof(unsigned short int) )
+//#define RIDER_ONE_CRED_SIZE ( sizeof(seq_t) + sizeof(logical_card_id_t) + sizeof(unsigned char) + sizeof(unsigned long long) + sizeof (unsigned short int) )
+//#define RIDER_SPILLOVER_SIZE ( sizeof(seq_t) + sizeof(logical_card_id_t) + (sizeof(char)*CREDENTIAL_LEN) + (sizeof(char)*CREDENTIAL_LEN) + (sizeof(char)*RULENAME_LEN) + (sizeof(char)*PARAM_LEN) )
+
+// 8 + 8 + 1 + 8 + 1 + 4 + 4 + 2
+//
+#define RIDER_TWO_CRED_SIZE ( 36 )
+
+// 8 + 8 + 1 + 8 + 2
+//
+#define RIDER_ONE_CRED_SIZE ( 27 )
+
+// old style rider db format
+//
+#define RIDER_SPILLOVER_SIZE ( 8 + 8 + CREDENTIAL_LEN + CREDENTIAL_LEN + RULENAME_LEN + PARAM_LEN )
+
+#define ID_INVALID      (0)
+
+
+
 //------------------------------- PROCESS DEATH MANAGEMENT ----------------------
 
 #ifdef USE_WATCHDOG_ALARM

+ 78 - 0
busunit/common/log_local.c

@@ -0,0 +1,78 @@
+#include "log_local.h"
+
+int log_local(char *log_fn, char *msg)
+{
+  FILE *log_fp;
+
+  if (log_fn)
+    log_fp = fopen(log_fn, "a+");
+  else
+    log_fp = fopen(LOG_LOCAL_DEFAULT_LOGFILE, "a+");
+
+  if (!log_fp)
+    return -1;
+
+
+  fprintf(log_fp, msg);
+  fclose(log_fp);
+
+  return 0;
+  
+}
+
+int log_local_message_record(char *log_fn, char *prefix, struct message_record *msg)
+{
+  int i;
+  static char *buf = NULL;
+  if (!buf)
+    buf = malloc(sizeof(char)*8*8192);
+  memset(buf, 0, sizeof(char)*8*8192);
+
+  sprintf(buf, "%s: header usec_time: %lli,", prefix ? prefix : " ", msg->header.usec_time);
+  if (log_local(log_fn, buf)<0) 
+    return -1;
+
+  sprintf(buf, "%s: header mailbox_name: %s,", prefix ? prefix : " ", msg->header.mailbox_name);
+  if (log_local(log_fn, buf)<0) 
+    return -1;
+
+  sprintf(buf, "%s: header payload_length: %i,", prefix ? prefix : " ", msg->header.payload_length);
+  if (log_local(log_fn, buf)<0) 
+    return -1;
+
+  sprintf(buf, "%s: header sender(pid_t): %i,", prefix ? prefix : " ", (int)msg->header.sender);
+  if (log_local(log_fn, buf)<0) 
+    return -1;
+
+  sprintf(buf, "%s: header from_fd: %i,", prefix ? prefix : " ", (int)msg->header.from_fd);
+  if (log_local(log_fn, buf)<0) 
+    return -1;
+
+  sprintf(buf, "%s: payload(ascii): ", prefix ? prefix : " ");
+  if (log_local(log_fn, buf)<0) 
+    return -1;
+
+  buf[0] = '\0';
+  for (i=0; i < msg->header.payload_length; i++)
+    buf[i] = ( isprint(msg->payload[i]) ? msg->payload[i] : '.' );
+  buf[i] = '\n';
+  if (log_local(log_fn, buf)<0) 
+    return -1;
+
+  sprintf(buf, "%s: payload(hex): ", prefix ? prefix : " ");
+  if (log_local(log_fn, buf)<0) 
+    return -1;
+
+  buf[0] = '\0';
+  for (i=0; i < msg->header.payload_length; i++)
+  {
+    buf[3*i] = ' ';
+    sprintf(buf + 3*i + 1, "%02x", (unsigned char)(msg->payload[i]) );
+  }
+  buf[3*i] = '\n';
+  if (log_local(log_fn, buf)<0) 
+    return -1;
+
+  return 0;
+}
+

+ 17 - 0
busunit/common/log_local.h

@@ -0,0 +1,17 @@
+#ifndef LOCAL_LOG_H
+#define LOCAL_LOG_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+//#include "common_defs.h"
+#include "../commhub/commhub.h"
+
+#define LOG_LOCAL_DEFAULT_LOGFILE "/tmp/local.log"
+
+int log_local(char *log_fn, char *msg);
+int log_local_message_record(char *log_fn, char *prefix, struct message_record *msg);
+
+#endif

+ 1 - 1
busunit/paddlemgr/buildit.sh

@@ -2,5 +2,5 @@
 
 rm -f paddlemgr 
 
-$target_cc $target_ccopts -lm -o paddlemgr paddlemgr.c ../common/common_defs.c ../common/gpsmath.c ../commhub/commhub.c ../commhub/client_utils.c 
+$target_cc $target_ccopts -o paddlemgr paddlemgr.c ../common/common_defs.c ../common/gpsmath.c ../commhub/commhub.c ../commhub/client_utils.c  -lm
 

+ 134 - 0
busunit/passdb_slim/aux/fpeek.c

@@ -0,0 +1,134 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+//extern char *optarg;
+
+int g_start_pos = 0;
+int g_end_pos = -1;
+int g_modulus = 16;
+char *g_fn = NULL;
+
+int g_verbose_flag = 0;
+int g_cononical_flag = 0;
+
+void print_usage_and_exit(void)
+{
+  printf("simple utility to look at raw data of files\n");
+  printf("usage:\n");
+  printf("  -f fn           filename\n");
+  printf("  [-s start]      start byte (default start)\n");
+  printf("  [-e end]        end byte (default end)\n");
+  printf("  [-m mod]        newline every 'mod' entries (default 16)\n");
+  printf("  [-C]            'cononical' view.  Print printable ascii next alongsize value\n");
+  printf("  [-h]            help\n");
+  printf("  [-v]            verbose flag\n");
+
+  exit(0);
+}
+
+
+
+int main(int argc, char **argv)
+{
+  int i, k;
+  int fd = -1;
+  struct stat st;
+
+  int r;
+
+  int read_end = -1;
+  char buf[16] = {0};
+  int c;
+
+  while ((c = getopt(argc, argv, "hvs:e:m:f:C")) != -1) 
+    switch (c)
+    {
+      case 'f': g_fn = strdup(optarg); break;
+      case 'C': g_cononical_flag = 1; break;
+      case 'h': print_usage_and_exit(); exit(0); break;
+      case 'v': g_verbose_flag = 1; break;
+      case 's': g_start_pos = atoi(optarg); break;
+      case 'e': g_end_pos = atoi(optarg); break;
+      case 'm': g_modulus = atoi(optarg); break;
+      default: print_usage_and_exit(); exit(0); break;
+    }
+
+  if ( !g_fn )
+  {
+    printf("provide filename\n");
+    print_usage_and_exit();
+  }
+
+  if ((g_start_pos < 0) ||
+      (g_modulus < 1) )
+  {
+    printf("start byte must be non-negative and modulus must be greater than 0\n");
+    print_usage_and_exit();
+  }
+
+  r = stat( g_fn, &st );
+  if (r < 0)
+  {
+    perror(g_fn);
+    exit(-1);
+  }
+
+  fd = open( g_fn, O_RDONLY );
+  if (fd < 0)
+  {
+    perror(g_fn);
+    exit(-1);
+  }
+
+  read_end = st.st_size;
+  if ( (g_end_pos >= 0) && (g_end_pos < st.st_size) )
+    read_end = g_end_pos+1;
+
+  if (g_start_pos>0)
+    lseek( fd, g_start_pos, SEEK_SET );
+
+  printf("start %i end %i\n", g_start_pos, read_end);
+
+  printf("#output in hex\n");
+  for (k=0, i=g_start_pos; i < read_end ; i++, k++)
+  {
+    if ((k % g_modulus)==0)
+    {
+      if (k>0)
+        printf("\n");
+
+      if (g_cononical_flag)
+      {
+        printf("[%4x]", i);
+      }
+ 
+    }
+
+    r = read( fd, buf, 1 );
+    if (r < 0)
+    {
+      perror("read error");
+      exit(-1);
+    }
+
+    printf(" %02x", buf[0] );
+    if (g_cononical_flag)
+    {
+      printf(" %c  ", isprint(buf[0]) ? buf[0] : '.' );
+    }
+  }
+
+  close(fd);
+
+
+  printf("\n");
+
+  return 0;
+
+}

+ 62 - 0
busunit/passdb_slim/aux/send_magstripe.c

@@ -0,0 +1,62 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "common_defs.h"
+#include "commhub.h"
+
+
+
+int main(int argc, char **argv)
+{
+
+    int fd;
+    char foo[1024];
+    char *bar;
+    struct message_record msg;
+    int retval, i;
+
+    fd = connect_to_message_server(argv[0]);
+
+    if(fd < 0)
+    {
+        fprintf(stderr,"Cannot connect to IPC server!\n");
+        exit(1);
+    }
+
+    while(!feof(stdin))
+    {
+        bar = fgets(foo, sizeof(foo), stdin);
+        
+        if(bar == NULL)
+            break;
+    
+                
+        for(i = 0; i < 1024; i++)
+        {
+            if(foo[i] == '\0')
+                break;
+        
+            if( (foo[i] == '\r') ||(foo[i] == '\n') )
+            {
+                foo[i] = '\0';
+                break;
+            }
+        }
+        
+        prepare_message(&msg, MAILBOX_TOKEN_MAG, foo, i);
+        retval = send_message(fd, &msg);
+        
+        if(retval < 0)
+        {
+            fprintf(stderr, "Error attempting to send message!\n");
+            exit(2);
+        }
+        
+    }    
+
+    return 0;
+}
+
+

+ 28 - 0
busunit/passdb_slim/buildit.sh

@@ -0,0 +1,28 @@
+#!/bin/sh
+
+tinyscheme_opts="-fpic  -I. -c -g -Wno-char-subscripts -O -DUSE_STRLWR=1 -DSTANDALONE=0 -DUSE_DL=0 -DUSE_MATH=0 -DUSE_ASCII_NAMES=0 -DUSE_ERROR_HOOK=1 -DUSE_TRACING=1"
+
+
+rm -f passdb_slim scheme.o
+
+$target_cc $tinyscheme_opts tinyscheme1.39/scheme.c
+$target_cc $target_ccopts -o passdb_slim \
+  passdb_slim.c \
+  ruleparam_db.c \
+  byte_access.c \
+  passdb_slim_config.c \
+  passdb_slim_debug.c \
+  rfid_decoder.c \
+  pass_communication.c \
+  rules.c \
+  ../common/common_defs.c \
+  ../common/gpsmath.c \
+  ../commhub/commhub.c \
+  ../commhub/client_utils.c \
+  scheme.o \
+  ../common/log_local.c -lm -lz
+
+$target_cc $target_ccopts -o aux/fpeek aux/fpeek.c -lz -lm 
+
+rm -f send_magstripe
+$target_cc $target_ccopts -I../common -I../commhub -o aux/send_magstripe aux/send_magstripe.c ../commhub/commhub.c ../common/common_defs.c

+ 8 - 0
busunit/passdb_slim/buildit_native.sh

@@ -0,0 +1,8 @@
+#!/bin/sh
+
+target="native"
+
+. ../configure_target.sh.include
+
+./buildit.sh
+

+ 8 - 0
busunit/passdb_slim/buildit_viper.sh

@@ -0,0 +1,8 @@
+#!/bin/sh
+
+target="viper"
+
+. ../configure_target.sh.include
+
+./buildit.sh
+

+ 150 - 0
busunit/passdb_slim/byte_access.c

@@ -0,0 +1,150 @@
+#include "byte_access.h"
+
+// LSB first!
+//
+unsigned short int _usi(void *p)
+{
+  unsigned short int usi = 0;
+  unsigned char c;
+
+  c = (unsigned char)(*((unsigned char *)p));
+  usi |= c;
+
+  c = (unsigned char)(*((unsigned char *)(p+1)));
+  usi |= (c<<8);
+
+  return usi;
+}
+
+unsigned long int _uli(void *p)
+{
+  unsigned long int uli = 0;
+  unsigned char c;
+
+  c = (unsigned char)(*((unsigned char *)p));
+  uli |= c;
+
+  c = (unsigned char)(*((unsigned char *)(p+1)));
+  uli |= (c<<8);
+
+  c = (unsigned char)(*((unsigned char *)(p+2)));
+  uli |= (c<<16);
+
+  c = (unsigned char)(*((unsigned char *)(p+3)));
+  uli |= (c<<24);
+
+  return uli;
+}
+
+unsigned long long int _ulli(void *p)
+{
+  unsigned long long int ulli = 0;
+  unsigned long long int t;
+  unsigned char c;
+
+  c = (unsigned char)(*((unsigned char *)p));
+  ulli |= c;
+
+  c = (unsigned char)(*((unsigned char *)(p+1)));
+  t = c;
+  ulli |= (t<<8);
+
+  c = (unsigned char)(*((unsigned char *)(p+2)));
+  t = c;
+  ulli |= (t<<16);
+
+  c = (unsigned char)(*((unsigned char *)(p+3)));
+  t = c;
+  ulli |= (t<<24);
+
+  c = (unsigned char)(*((unsigned char *)(p+4)));
+  t = c;
+  ulli |= (t<<32);
+
+  c = (unsigned char)(*((unsigned char *)(p+5)));
+  t = c;
+  ulli |= (t<<40);
+
+  c = (unsigned char)(*((unsigned char *)(p+6)));
+  t = c;
+  ulli |= (t<<48);
+
+  c = (unsigned char)(*((unsigned char *)(p+7)));
+  t = c;
+  ulli |= (t<<56);
+
+  return ulli;
+}
+
+
+void _usiw(void *p, unsigned short int usi)
+{
+  unsigned char c;
+  unsigned char *chp;
+
+  chp = p;
+
+  c = usi & 0xff;
+  *chp++ = c;
+
+  c = (usi >> 8) & 0xff;
+  *chp++ = c;
+
+}
+
+void _uliw(void *p, unsigned long int uli)
+{
+  unsigned char c;
+  unsigned char *chp;
+
+  chp = p;
+
+  c = uli & 0xff;
+  *chp++ = c;
+
+  c = (uli >> 8) & 0xff;
+  *chp++ = c;
+
+  c = (uli >> 16) & 0xff;
+  *chp++ = c;
+
+  c = (uli >> 24) & 0xff;
+  *chp++ = c;
+
+}
+
+void _ulliw(void *p, unsigned long long int ulli)
+{
+  unsigned char c;
+  unsigned char *chp;
+
+  chp = p;
+
+  c = ulli & 0xff;
+  *chp++ = c;
+
+  c = (ulli >> 8) & 0xff;
+  *chp++ = c;
+
+  c = (ulli >> 16) & 0xff;
+  *chp++ = c;
+
+  c = (ulli >> 24) & 0xff;
+  *chp++ = c;
+
+  c = (ulli >> 32) & 0xff;
+  *chp++ = c;
+
+  c = (ulli >> 40) & 0xff;
+  *chp++ = c;
+
+  c = (ulli >> 48) & 0xff;
+  *chp++ = c;
+
+  c = (ulli >> 56) & 0xff;
+  *chp++ = c;
+
+}
+
+
+

+ 45 - 0
busunit/passdb_slim/byte_access.h

@@ -0,0 +1,45 @@
+#ifndef BYTE_ACCESS_H
+#define BYTE_ACCESS_H
+
+/* Conversion routines for accessing
+ * integers (short, long, long long)
+ * from a byte array.
+ *
+ * The viper (gcc I assume) does not
+ * allow for non frame aligned access.
+ * From what I can tell, it clamps
+ * the address to the nearest frame
+ * depending on the type you're accessing
+ * and reads starting from this position.
+ * This leads to misframed data being
+ * read if you dereference it from a
+ * non framed position.  I would
+ * also assume writing has the same problem.
+ *
+ * These functions will read or write
+ * short, long or long long (unsigned)
+ * integers starting at the pointer location.
+ *
+ * Storage is least significant byte first.
+ * For example:
+ *    _uliw(p, 67305985) would write:
+ *
+ *    p[0] = 0x01
+ *    p[1] = 0x02
+ *    p[2] = 0x03
+ *    p[3] = 0x04
+ *
+ *    _uli(p) would return 67305985
+ *
+ */
+
+unsigned short int _usi(void *p);
+unsigned long int _uli(void *p);
+unsigned long long int _ulli(void *p);
+
+void _usiw(void *p, unsigned short int usi);
+void _uliw(void *p, unsigned long int uli);
+void _ulliw(void *p, unsigned long long int ulli);
+
+
+#endif 

File diff suppressed because it is too large
+ 1533 - 0
busunit/passdb_slim/pass_communication.c


File diff suppressed because it is too large
+ 3647 - 0
busunit/passdb_slim/passdb_slim.c


+ 290 - 0
busunit/passdb_slim/passdb_slim.h

@@ -0,0 +1,290 @@
+
+#ifndef _PASSDB_H
+#define _PASSDB_H
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "../common/common_defs.h"
+#include "ruleparam_db.h"
+#include "byte_access.h"
+
+typedef unsigned long long seq_t;
+typedef unsigned long long logical_card_id_t;
+
+//#define PASSDB_CONSISTENCY_CHECK
+#define FN_SZ 1024
+
+//#define RIDER_ONE_CRED_SIZE 27
+//#define RIDER_TWO_CRED_SIZE ( sizeof(seq_t) + sizeof(logical_card_id_t) + 
+// sizeof(unsigned char) + sizeof(unsigned long long) + 
+// sizeof(unsigned char) + sizeof (unsigned long) + sizeof(unsigned long) +
+// sizeof(unsigned short int) )
+
+// This record is only used for transport
+// of information.  On disk storage needs to be 
+// done through the helper functions.
+//
+typedef struct rider_record_slim_two_cred_struct
+{
+    seq_t               seq;
+    logical_card_id_t   id;
+
+
+    unsigned long long  magstripe;
+
+    unsigned long       rfid_site;
+    unsigned long       rfid_val;
+
+    unsigned short int  rule_param_bucket_id;
+    unsigned char       rfid_code;
+    unsigned char       magstripe_code;
+
+} rider_record_slim_two_cred;
+
+//#define RIDER_TWO_CRED_SIZE 36
+//#define RIDER_ONE_CRED_SIZE ( sizeof(seq_t) + sizeof(logical_card_id_t) +
+// sizeof(unsigned char) + sizeof(unsigned long long) + 
+// sizeof (unsigned short int) )
+
+
+// This record is only used for transport
+// of information.  On disk storage needs to be 
+// done through the helper functions.
+//
+typedef struct rider_record_slim_one_cred
+{
+    seq_t               seq;
+    logical_card_id_t   id;
+
+    unsigned long long  credential;
+
+    unsigned short int  rule_param_bucket_id;
+    unsigned char       code;
+
+} rider_record_slim_one_cred;
+
+
+//THIS STRUCTURE MUST BE A POWER OF 2 BYTES IN SIZE
+//NOTE: this was the old entry format for the old database.
+// rider_records are still used, but serve only as transport
+// structures to hold information and for the 'spillover'
+// records.  The main on-disk storage now is the rider one
+// cred and rider two cred structures above, which are not
+// powers of two in size.  
+// This rider_record struct is also used to transport
+// information about the card and provide a consistent
+// interface to the rest of the ecosystem.
+//
+typedef struct rider_record_struct
+{
+    seq_t seq;				//sequence number
+    logical_card_id_t  id;			//rider ID
+      
+    char magstripe_value[CREDENTIAL_LEN];
+    char rfid_value[CREDENTIAL_LEN];
+    
+    char rule_name[RULENAME_LEN];
+    char rule_param[PARAM_LEN];    
+
+} rider_record;
+
+
+typedef struct rule_pass_param_bucket_struct
+{
+
+    unsigned int rule_param_bucket_id;
+
+    char rule_name[RULENAME_LEN];
+    char rule_param[PARAM_LEN];    
+
+} rule_pass_param_bucket;
+
+
+// 0              <= idx < INDEX_MIDPOINT    -> single credential (either rfid or mag only)
+// INDEX_MIDPOINT <= idx < 2*INDEX_MIDPOINT  -> double credential (both rfid + mag)
+//
+// idx >= 2*INDEX_MIDPOINT in spillover
+//
+// Each 'bank' is a block of X one credential, two credential or spillover packed
+// structures.  X is read from the passdb.conf file (see passdb_slim_config.[ch]).
+//
+typedef struct rider_node_struct
+{
+  int idx;
+  struct rider_node_struct *next;
+
+} rider_node;
+
+typedef struct passdb_slim_context_struct
+{
+  void **rider_one_cred_bank;
+  void **rider_two_cred_bank;
+  void **rider_spillover_bank;
+
+  // Helper vairables to keep count of number of one and two credit
+  // credentials in all of the banks.
+  //
+
+  // heap of active and free rider indexes 
+  // (indexed into rider_one_cred and rider_two_cred)
+  // simple linear linked lists
+  //
+  rider_node *activelist;
+
+  rider_node *freelist_one_cred;
+  rider_node *freelist_two_cred;
+  rider_node *freelist_spillover;
+
+  char **one_cred_db_bank_fn;
+  char **two_cred_db_bank_fn;
+  char **spillover_db_bank_fn;
+
+  // current number of banks for each database type
+  //
+  int n_one_cred;
+  int n_two_cred;
+  int n_spillover;
+
+  int n_one_cred_bank;
+  int n_two_cred_bank;
+  int n_spillover_bank;
+
+  int n_one_cred_bank_size;
+  int n_two_cred_bank_size;
+  int n_spillover_bank_size;
+
+  int n_one_cred_max_bank;
+  int n_two_cred_max_bank;
+  int n_spillover_max_bank;
+
+  int hash_modulus;
+
+  // hashes of logical_card_id, mag and rf
+  // for quick lookup
+  //
+  rider_node **logical_card_id_hash;
+  rider_node **rider_mag_hash;
+  rider_node **rider_rf_hash;
+
+  seq_t seq;
+
+  // THESE ARE USED IF MMAP IS DETERMINED TO BE BROKEN...
+  // it's broken...
+  int mmap_broken;
+
+  int num_free;
+  int num_active;
+
+  int *passes_one_cred_bank_fd;
+  int *passes_two_cred_bank_fd;
+  int *passes_spillover_bank_fd;
+
+  size_t rider_one_file_size;
+  size_t rider_two_file_size;
+  size_t rider_spillover_file_size;
+
+  size_t rider_one_file_bank_size;
+  size_t rider_two_file_bank_size;
+  size_t rider_spillover_file_bank_size;
+
+  char diagnostic_str[128];
+
+  ruleparam_db_ctx *ruleparam_db;
+  char *ruleparam_db_fn;
+
+  char *one_cred_db_base_fn;
+  char *two_cred_db_base_fn;
+  char *spillover_db_base_fn;
+
+  char *db_fn_suffix;
+
+  float high_watermark_threshold;
+  float low_watermark_threshold;
+
+} passdb_slim_context;
+
+
+typedef struct passdb_slim_config_t {
+
+  int hash_modulus;
+
+  int n_one_cred_bank;
+  int n_two_cred_bank;
+  int n_spillover_bank;
+
+  int n_one_cred_bank_size;
+  int n_two_cred_bank_size;
+  int n_spillover_bank_size;
+
+  int n_one_cred_max_bank;
+  int n_two_cred_max_bank;
+  int n_spillover_max_bank;
+
+  char *one_cred_db_base_fn;
+  char *two_cred_db_base_fn;
+  char *spillover_db_base_fn;
+
+  char *db_fn_suffix;
+
+  char *ruleparam_db_fn;
+
+  size_t rider_one_file_bank_size;
+  size_t rider_two_file_bank_size;
+  size_t rider_spillover_file_bank_size;
+
+  float high_watermark_threshold;
+  float low_watermark_threshold;
+
+} passdb_slim_config;
+
+//--------------------------
+
+int format_new_passdb( char *, int, long );
+int format_new_passdbs();
+
+
+int attach_to_passdb(passdb_slim_context *ctx);
+int detach_from_passdb(passdb_slim_context *ctx);
+
+int delete_rider(passdb_slim_context *ctx, rider_record *rec, int sync);
+int update_rider(passdb_slim_context *ctx, rider_record *rec, int sync);
+
+void sync_all_riders(passdb_slim_context *ctx);
+
+void dump_hashes(passdb_slim_context *ctx);
+
+int find_mag_in_hash(passdb_slim_context *ctx, char *mag);
+int find_rf_in_hash(passdb_slim_context *ctx, char *rfid);
+
+void populate_one_cred_rider_record( rider_record_slim_one_cred *, int, void *);
+void populate_two_cred_rider_record( rider_record_slim_two_cred *, int, void *);
+void populate_spillover_rider_record( rider_record *, int, void *);
+
+int make_rider_record_from_rider_one_cred( passdb_slim_context *ctx, rider_record *rr, rider_record_slim_one_cred *rr1 );
+int make_rider_record_from_rider_two_cred( passdb_slim_context *ctx, rider_record *rr, rider_record_slim_two_cred *rr2 );
+int make_rider_record_from_rider_spillover( passdb_slim_context *, rider_record *, rider_record *);
+void make_rider_record( passdb_slim_context *ctx, rider_record *rr, int idx );
+
+int passdb_slim_get_cred_bank_and_pos( passdb_slim_context *ctx, int *bank, int *pos, int idx );
+
+int passdb_slim_consistency_check( passdb_slim_context *ctx );
+
+// config file functions 
+//
+void passdb_slim_copy_config( passdb_slim_config *, passdb_slim_context *);
+int save_config( passdb_slim_config *, char *);
+int read_config( passdb_slim_config *, char *);
+int init_context_from_config( passdb_slim_context *, char *);
+  
+int make_default_config( char *);
+
+
+// DEBUGGING
+//
+void passdb_slim_dump( passdb_slim_context * );
+
+
+
+#endif
+

+ 560 - 0
busunit/passdb_slim/passdb_slim_config.c

@@ -0,0 +1,560 @@
+#include "passdb_slim.h"
+
+// SHALLOW COPY
+// passdb_slim_config is a shallow container.  All memory management
+// should be done from ctx.
+//
+void passdb_slim_copy_config( passdb_slim_config *cfg, passdb_slim_context *ctx )
+{
+    cfg->hash_modulus             = ctx->hash_modulus;
+    cfg->n_one_cred_bank          = ctx->n_one_cred_bank;
+    cfg->n_two_cred_bank          = ctx->n_two_cred_bank;
+    cfg->n_spillover_bank          = ctx->n_spillover_bank;
+
+    cfg->n_one_cred_bank_size     = ctx->n_one_cred_bank_size;
+    cfg->n_two_cred_bank_size     = ctx->n_two_cred_bank_size;
+    cfg->n_spillover_bank_size     = ctx->n_spillover_bank_size;
+
+    cfg->n_one_cred_max_bank      = ctx->n_one_cred_max_bank;
+    cfg->n_two_cred_max_bank      = ctx->n_two_cred_max_bank;
+    cfg->n_spillover_max_bank      = ctx->n_spillover_max_bank;
+
+    cfg->one_cred_db_base_fn      = ctx->one_cred_db_base_fn;
+    cfg->two_cred_db_base_fn      = ctx->two_cred_db_base_fn;
+    cfg->spillover_db_base_fn      = ctx->spillover_db_base_fn;
+
+    cfg->db_fn_suffix             = ctx->db_fn_suffix;
+    cfg->ruleparam_db_fn          = ctx->ruleparam_db_fn;
+    cfg->high_watermark_threshold = ctx->high_watermark_threshold;
+    cfg->low_watermark_threshold  = ctx->low_watermark_threshold;
+}
+
+#define DEFAULT_HASH_MODULUS 131101
+
+#define DEFAULT_ONE_CRED_MAX_BANK 25
+#define DEFAULT_TWO_CRED_MAX_BANK 25
+#define DEFAULT_SPILLOVER_MAX_BANK 25
+
+#define DEFAULT_ONE_CRED_BANK_SIZE 10012
+#define DEFAULT_TWO_CRED_BANK_SIZE 10012
+#define DEFAULT_SPILLOVER_BANK_SIZE 32
+
+#define DEFAULT_ONE_CRED_BANK 1
+#define DEFAULT_TWO_CRED_BANK 1
+#define DEFAULT_SPILLOVER_BANK 1
+
+#define DEFAULT_ONE_CRED_DB_BASE DATABASE_FILE_PATH "passes_one_bank"
+#define DEFAULT_TWO_CRED_DB_BASE DATABASE_FILE_PATH "passes_two_bank"
+#define DEFAULT_SPILLOVER_DB_BASE DATABASE_FILE_PATH "passes_spillover_bank"
+
+#define DEFAULT_DB_SUFFIX ".mem"
+
+#define DEFAULT_RULEPARAM_DB DATABASE_FILE_PATH "ruleparam.db"
+
+#define DEFAULT_HIGH_WATERMARK 0.95
+
+//unused
+//
+#define DEFAULT_LOW_WATERMARK 0.25
+
+
+int make_default_config( char *config_fn )
+{
+  FILE *fp;
+
+  struct tm tm_tim;
+  struct timeval timval;
+  char str_tim[FN_SZ];
+
+  gettimeofday(&timval, NULL);
+  localtime_r(&(timval.tv_sec), &tm_tim);
+  asctime_r(&tm_tim, str_tim);
+
+
+  fp = fopen(config_fn, "w");
+  if (!fp)
+    return -1;
+
+  fprintf(fp, "# %s", str_tim );
+  fprintf(fp, "#\n");
+  fprintf(fp, "#\n");
+
+  fprintf(fp, "hash_modulus %i\n", DEFAULT_HASH_MODULUS);
+  fprintf(fp, "\n");
+
+  fprintf(fp, "n_one_cred_max_bank %i\n", DEFAULT_ONE_CRED_MAX_BANK );
+  fprintf(fp, "n_two_cred_max_bank %i\n", DEFAULT_TWO_CRED_MAX_BANK );
+  fprintf(fp, "n_spillover_max_bank %i\n", DEFAULT_SPILLOVER_MAX_BANK );
+  fprintf(fp, "\n");
+
+  fprintf(fp, "n_one_cred_bank_size %i\n", DEFAULT_ONE_CRED_BANK_SIZE );
+  fprintf(fp, "n_two_cred_bank_size %i\n", DEFAULT_TWO_CRED_BANK_SIZE );
+  fprintf(fp, "n_spillover_bank_size %i\n", DEFAULT_SPILLOVER_BANK_SIZE );
+  fprintf(fp, "\n");
+
+  fprintf(fp, "n_one_cred_bank %i\n", DEFAULT_ONE_CRED_BANK );
+  fprintf(fp, "n_two_cred_bank %i\n", DEFAULT_TWO_CRED_BANK );
+  fprintf(fp, "n_spillover_bank %i\n", DEFAULT_SPILLOVER_BANK );
+  fprintf(fp, "\n");
+
+  fprintf(fp, "one_cred_db_base %s\n", DEFAULT_ONE_CRED_DB_BASE );
+  fprintf(fp, "two_cred_db_base %s\n", DEFAULT_TWO_CRED_DB_BASE );
+  fprintf(fp, "spillover_db_base %s\n", DEFAULT_SPILLOVER_DB_BASE );
+  fprintf(fp, "\n");
+
+  fprintf(fp, "db_suffix %s\n", DEFAULT_DB_SUFFIX );
+  fprintf(fp, "\n");
+
+  fprintf(fp, "ruleparam_db %s\n", DEFAULT_RULEPARAM_DB );
+  fprintf(fp, "\n");
+
+  fprintf(fp, "high_watermark_threshold %f\n", DEFAULT_HIGH_WATERMARK );
+  fprintf(fp, "low_watermark_threshold %f\n", DEFAULT_LOW_WATERMARK );
+  fprintf(fp, "\n");
+
+  fclose(fp);
+
+  return 0;
+}
+
+int save_config( passdb_slim_config *cfg, char *config_fn )
+{
+  FILE *fp;
+
+  struct tm tm_tim;
+  struct timeval timval;
+  char str_tim[FN_SZ];
+
+  gettimeofday(&timval, NULL);
+  localtime_r(&(timval.tv_sec), &tm_tim);
+  asctime_r(&tm_tim, str_tim);
+
+
+  fp = fopen( config_fn, "w" );
+  if (!fp)
+  {
+    //DEBUG
+    //fprintf(stderr, "ERROR: passdb.save_config: could not open file %s\n", config_fn);
+    //exit(1);
+
+    perror(config_fn);
+    return -1;
+  }
+
+  fprintf(fp, "# %s", str_tim );
+  fprintf(fp, "#\n");
+  fprintf(fp, "#\n");
+
+  fprintf(fp, "hash_modulus %i\n", cfg->hash_modulus);
+  fprintf(fp, "\n");
+
+  fprintf(fp, "n_one_cred_max_bank %i\n", cfg->n_one_cred_max_bank);
+  fprintf(fp, "n_two_cred_max_bank %i\n", cfg->n_two_cred_max_bank);
+  fprintf(fp, "n_spillover_max_bank %i\n", cfg->n_spillover_max_bank);
+  fprintf(fp, "\n");
+
+  fprintf(fp, "n_one_cred_bank_size %i\n", cfg->n_one_cred_bank_size);
+  fprintf(fp, "n_two_cred_bank_size %i\n", cfg->n_two_cred_bank_size);
+  fprintf(fp, "n_spillover_bank_size %i\n", cfg->n_spillover_bank_size);
+  fprintf(fp, "\n");
+
+  fprintf(fp, "n_one_cred_bank %i\n", cfg->n_one_cred_bank);
+  fprintf(fp, "n_two_cred_bank %i\n", cfg->n_two_cred_bank);
+  fprintf(fp, "n_spillover_bank %i\n", cfg->n_spillover_bank);
+  fprintf(fp, "\n");
+
+  fprintf(fp, "one_cred_db_base %s\n", cfg->one_cred_db_base_fn);
+  fprintf(fp, "two_cred_db_base %s\n", cfg->two_cred_db_base_fn);
+  fprintf(fp, "spillover_db_base %s\n", cfg->spillover_db_base_fn);
+  fprintf(fp, "\n");
+
+  fprintf(fp, "db_suffix %s\n", cfg->db_fn_suffix);
+  fprintf(fp, "\n");
+
+  fprintf(fp, "ruleparam_db %s\n", cfg->ruleparam_db_fn);
+  fprintf(fp, "\n");
+
+  fprintf(fp, "high_watermark_threshold %f\n", (double)cfg->high_watermark_threshold );
+  fprintf(fp, "low_watermark_threshold %f\n", (double)cfg->low_watermark_threshold );
+  fprintf(fp, "\n");
+
+  fclose(fp);
+
+  return 0;
+
+}
+
+
+
+
+int read_config( passdb_slim_config *cfg, char *config_fn )
+{
+  FILE *fp;
+  char buf[FN_SZ];
+  char keyword[FN_SZ], rvalue[FN_SZ];
+  int r;
+
+  cfg->hash_modulus = -1;
+
+  cfg->n_one_cred_bank_size = -1;
+  cfg->n_two_cred_bank_size = -1;
+  cfg->n_spillover_bank_size = -1;
+
+  cfg->n_one_cred_bank = -1;
+  cfg->n_two_cred_bank = -1;
+  cfg->n_spillover_bank = -1;
+
+  cfg->one_cred_db_base_fn = NULL;
+  cfg->two_cred_db_base_fn = NULL;
+  cfg->spillover_db_base_fn = NULL;
+  cfg->db_fn_suffix = NULL;
+
+  cfg->high_watermark_threshold = 0.99;
+  cfg->low_watermark_threshold = 0.1;
+
+  cfg->ruleparam_db_fn = NULL;
+
+  fp = fopen(config_fn, "r");
+  if (!fp)
+    return -1;
+
+  while ( fgets(buf, FN_SZ-1, fp) )
+  {
+    if (buf[0] == '#')
+      continue;
+    r = sscanf(buf, "%s %s", keyword, rvalue);
+
+    if (keyword[0] == '#')
+      continue;
+
+    if (r!=2)
+      continue;
+
+    if ( strncmp(keyword, "hash_modulus", FN_SZ-1) == 0 )
+    {
+      cfg->hash_modulus = atoi(rvalue);
+    }
+
+    else if (strncmp(keyword, "n_one_cred_bank_size", FN_SZ-1) == 0 )
+    {
+      cfg->n_one_cred_bank_size = atoi(rvalue);
+    }
+    else if (strncmp(keyword, "n_two_cred_bank_size", FN_SZ-1) == 0 )
+    {
+      cfg->n_two_cred_bank_size = atoi(rvalue);
+    }
+    else if (strncmp(keyword, "n_spillover_bank_size", FN_SZ-1) == 0 )
+    {
+      cfg->n_spillover_bank_size = atoi(rvalue);
+    }
+
+
+    else if (strncmp(keyword, "n_one_cred_bank", FN_SZ-1) == 0 )
+    {
+      cfg->n_one_cred_bank = atoi(rvalue);
+    }
+    else if (strncmp(keyword, "n_two_cred_bank", FN_SZ-1) == 0 )
+    {
+      cfg->n_two_cred_bank = atoi(rvalue);
+    }
+    else if (strncmp(keyword, "n_spillover_bank", FN_SZ-1) == 0 )
+    {
+      cfg->n_spillover_bank = atoi(rvalue);
+    }
+
+    else if (strncmp(keyword, "n_one_cred_max_bank", FN_SZ-1) == 0 )
+    {
+      cfg->n_one_cred_max_bank = atoi(rvalue);
+    }
+    else if (strncmp(keyword, "n_two_cred_max_bank", FN_SZ-1) == 0 )
+    {
+      cfg->n_two_cred_max_bank = atoi(rvalue);
+    }
+    else if (strncmp(keyword, "n_spillover_max_bank", FN_SZ-1) == 0 )
+    {
+      cfg->n_spillover_max_bank = atoi(rvalue);
+    }
+
+    else if (strncmp(keyword, "one_cred_db_base", FN_SZ-1) == 0)
+    {
+      cfg->one_cred_db_base_fn = strdup(rvalue);
+    }
+    else if (strncmp(keyword, "two_cred_db_base", FN_SZ-1) == 0)
+    {
+      cfg->two_cred_db_base_fn = strdup(rvalue);
+    }
+    else if (strncmp(keyword, "spillover_db_base", FN_SZ-1) == 0)
+    {
+      cfg->spillover_db_base_fn = strdup(rvalue);
+    }
+
+    else if (strncmp(keyword, "db_suffix", FN_SZ-1) == 0)
+    {
+      cfg->db_fn_suffix = strdup(rvalue);
+    }
+    else if (strncmp(keyword, "ruleparam_db", FN_SZ-1) == 0)
+    {
+      cfg->ruleparam_db_fn = strdup(rvalue);
+    }
+
+    else if (strncmp(keyword, "high_watermark_threshold", FN_SZ-1) == 0)
+    {
+      cfg->high_watermark_threshold = atof(rvalue);
+    }
+    else if (strncmp(keyword, "low_watermark_threshold", FN_SZ-1) == 0)
+    {
+      cfg->low_watermark_threshold = atof(rvalue);
+    }
+
+  }
+  fclose(fp);
+
+
+  if (!cfg->ruleparam_db_fn)
+    cfg->ruleparam_db_fn = strdup( RULEPARAM_DB_FILE );
+
+
+  // If there were any errors, bail out
+  //
+  if ( (cfg->hash_modulus <= 0) ||
+
+       (cfg->n_one_cred_max_bank <= 0) ||
+       (cfg->n_two_cred_max_bank <= 0) ||
+       (cfg->n_spillover_max_bank <= 0) ||
+
+       (cfg->n_one_cred_bank_size <= 0) ||
+       (cfg->n_two_cred_bank_size <= 0) ||
+       (cfg->n_spillover_bank_size <= 0) ||
+
+       (cfg->n_one_cred_bank <= 0) ||
+       (cfg->n_two_cred_bank <= 0) ||
+       (cfg->n_spillover_bank <= 0) ||
+
+       (cfg->high_watermark_threshold <= 0.0) ||
+       (cfg->high_watermark_threshold >= 1.0) ||
+
+       (cfg->low_watermark_threshold <= 0.0) ||
+       (cfg->low_watermark_threshold >= cfg->high_watermark_threshold) ||
+
+       (!cfg->one_cred_db_base_fn) ||
+       (!cfg->two_cred_db_base_fn) ||
+       (!cfg->spillover_db_base_fn) ||
+       (!cfg->db_fn_suffix) ||
+
+       (!cfg->ruleparam_db_fn)
+       )
+  {
+
+    if (cfg->one_cred_db_base_fn) free(cfg->one_cred_db_base_fn);
+    if (cfg->two_cred_db_base_fn) free(cfg->two_cred_db_base_fn);
+    if (cfg->spillover_db_base_fn) free(cfg->spillover_db_base_fn);
+    if (cfg->db_fn_suffix)        free(cfg->db_fn_suffix);
+
+    if (cfg->ruleparam_db_fn) free(cfg->ruleparam_db_fn);
+    return -1;
+  }
+
+
+  return 0;
+}
+
+
+// Dead simple config file parsing
+//
+int init_context_from_config( passdb_slim_context *ctx, char *config_fn )
+{
+
+  int i, r;
+
+  // Don't copy new values over until we're sure config file read
+  // was successful.  Store in local variables and copy over
+  // afterwards.
+  //
+  passdb_slim_config cfg;
+
+  r = read_config(&cfg, config_fn);
+  if (r<0)
+    return r;
+
+  ctx->n_one_cred_bank = cfg.n_one_cred_bank;
+  ctx->n_two_cred_bank = cfg.n_two_cred_bank;
+  ctx->n_spillover_bank = cfg.n_spillover_bank;
+
+  ctx->n_one_cred_max_bank = cfg.n_one_cred_max_bank;
+  ctx->n_two_cred_max_bank = cfg.n_two_cred_max_bank;
+  ctx->n_spillover_max_bank = cfg.n_spillover_max_bank;
+
+  ctx->n_one_cred_bank_size = cfg.n_one_cred_bank_size;
+  ctx->n_two_cred_bank_size = cfg.n_two_cred_bank_size;
+  ctx->n_spillover_bank_size = cfg.n_spillover_bank_size;
+
+  ctx->hash_modulus = cfg.hash_modulus;
+
+  // Get rid of stale filenames
+  //
+  if (ctx->one_cred_db_bank_fn)
+  {
+    for (i=0; i<ctx->n_one_cred_max_bank; i++)
+      if (ctx->one_cred_db_bank_fn[i])
+        free(ctx->one_cred_db_bank_fn[i]);
+    free(ctx->one_cred_db_bank_fn);
+  }
+
+  if (ctx->two_cred_db_bank_fn)
+  {
+    for (i=0; i<ctx->n_two_cred_max_bank; i++)
+      if (ctx->two_cred_db_bank_fn[i])
+        free(ctx->two_cred_db_bank_fn[i]);
+    free(ctx->two_cred_db_bank_fn);
+  }
+
+  if (ctx->spillover_db_bank_fn)
+  {
+    for (i=0; i<ctx->n_spillover_max_bank; i++)
+      if (ctx->spillover_db_bank_fn[i])
+        free(ctx->spillover_db_bank_fn[i]);
+    free(ctx->spillover_db_bank_fn);
+  }
+
+  if (ctx->one_cred_db_base_fn) free(ctx->one_cred_db_base_fn);
+  if (ctx->two_cred_db_base_fn) free(ctx->two_cred_db_base_fn);
+  if (ctx->spillover_db_base_fn) free(ctx->spillover_db_base_fn);
+  if (ctx->db_fn_suffix) free(ctx->db_fn_suffix);
+
+  if (ctx->ruleparam_db_fn) free(ctx->ruleparam_db_fn);
+
+  if (ctx->logical_card_id_hash) free(ctx->logical_card_id_hash);
+  if (ctx->rider_mag_hash) free(ctx->rider_mag_hash);
+  if (ctx->rider_rf_hash) free(ctx->rider_rf_hash);
+
+  ctx->one_cred_db_base_fn = cfg.one_cred_db_base_fn;
+  ctx->two_cred_db_base_fn = cfg.two_cred_db_base_fn;
+  ctx->spillover_db_base_fn = cfg.spillover_db_base_fn;
+  ctx->db_fn_suffix = cfg.db_fn_suffix;
+
+  ctx->ruleparam_db_fn = cfg.ruleparam_db_fn;
+
+  ctx->high_watermark_threshold = cfg.high_watermark_threshold;
+  ctx->low_watermark_threshold = cfg.low_watermark_threshold;
+
+
+  //---------------------------------------
+  // ONE CREDENTIAL bank
+  //  - filenames
+  //  - file descriptors
+  //  - bank (memory)
+  //
+
+
+  // allocate all filenames, even if we don't create the actual DB files
+  //
+  ctx->one_cred_db_bank_fn = (char **)malloc(sizeof(char *) * (ctx->n_one_cred_max_bank));
+  CHECK_ALLOC_FAIL( (ctx->one_cred_db_bank_fn) );
+
+  for (i=0; i<ctx->n_one_cred_max_bank; i++)
+  {
+    ctx->one_cred_db_bank_fn[i] = (char *)malloc(sizeof(char)*FN_SZ);
+    CHECK_ALLOC_FAIL( (ctx->one_cred_db_bank_fn[i]) );
+
+    snprintf(ctx->one_cred_db_bank_fn[i], FN_SZ, "%s%i%s", ctx->one_cred_db_base_fn, i, ctx->db_fn_suffix );
+  }
+
+  ctx->passes_one_cred_bank_fd = (int *)malloc(sizeof(int) * ctx->n_one_cred_max_bank );
+  CHECK_ALLOC_FAIL( (ctx->passes_one_cred_bank_fd) );
+
+  for (i=0; i<ctx->n_one_cred_max_bank; i++)
+    ctx->passes_one_cred_bank_fd[i] = -1;
+
+  ctx->rider_one_cred_bank = (void **)malloc(sizeof(void *) * ctx->n_one_cred_max_bank );
+  CHECK_ALLOC_FAIL( (ctx->rider_one_cred_bank) );
+
+  for (i=0; i<ctx->n_one_cred_max_bank; i++)
+    ctx->rider_one_cred_bank[i] = NULL;
+
+
+  //---------------------------------------
+  // TWO CREDENTIAL bank
+  //  - filenames
+  //  - file descriptors
+  //  - bank (memory)
+  //
+
+  // allocate all filenames, even if we don't create the actual DB files
+  //
+  ctx->two_cred_db_bank_fn = (char **)malloc(sizeof(char *) * (ctx->n_two_cred_max_bank));
+  CHECK_ALLOC_FAIL( (ctx->two_cred_db_bank_fn) );
+
+  for (i=0; i<ctx->n_two_cred_max_bank; i++)
+  {
+    ctx->two_cred_db_bank_fn[i] = (char *)malloc(sizeof(char)*FN_SZ);
+    CHECK_ALLOC_FAIL( (ctx->two_cred_db_bank_fn[i]) );
+
+    snprintf(ctx->two_cred_db_bank_fn[i], FN_SZ, "%s%i%s", ctx->two_cred_db_base_fn, i, ctx->db_fn_suffix );
+  }
+
+  ctx->passes_two_cred_bank_fd = (int *)malloc(sizeof(int) * ctx->n_two_cred_max_bank );
+  CHECK_ALLOC_FAIL( (ctx->passes_two_cred_bank_fd) );
+
+  for (i=0; i<ctx->n_two_cred_max_bank; i++)
+    ctx->passes_two_cred_bank_fd[i] = -1;
+
+  ctx->rider_two_cred_bank = (void **)malloc(sizeof(void *) * ctx->n_two_cred_max_bank );
+  CHECK_ALLOC_FAIL( (ctx->rider_two_cred_bank) );
+
+  for (i=0; i<ctx->n_two_cred_max_bank; i++)
+    ctx->rider_two_cred_bank[i] = NULL;
+
+
+  //---------------------------------------
+  // SPILLOVER 
+  //  - filenames
+  //  - file descriptors
+  //  - bank (memory)
+  //
+
+  // allocate all filenames, even if we don't create the actual DB files
+  //
+  ctx->spillover_db_bank_fn = (char **)malloc(sizeof(char *) * (ctx->n_spillover_max_bank));
+  CHECK_ALLOC_FAIL( (ctx->spillover_db_bank_fn) );
+
+  for (i=0; i<ctx->n_spillover_max_bank; i++)
+  {
+    ctx->spillover_db_bank_fn[i] = (char *)malloc(sizeof(char)*FN_SZ);
+    CHECK_ALLOC_FAIL( (ctx->spillover_db_bank_fn[i]) );
+
+    snprintf(ctx->spillover_db_bank_fn[i], FN_SZ, "%s%i%s", ctx->spillover_db_base_fn, i, ctx->db_fn_suffix );
+  }
+
+  ctx->passes_spillover_bank_fd = (int *)malloc(sizeof(int) * ctx->n_spillover_max_bank );
+  CHECK_ALLOC_FAIL( (ctx->passes_spillover_bank_fd) );
+
+  for (i=0; i<ctx->n_spillover_max_bank; i++)
+    ctx->passes_spillover_bank_fd[i] = -1;
+
+  ctx->rider_spillover_bank = (void **)malloc(sizeof(void *) * ctx->n_spillover_max_bank );
+  CHECK_ALLOC_FAIL( (ctx->rider_spillover_bank) );
+
+  for (i=0; i<ctx->n_spillover_max_bank; i++)
+    ctx->rider_spillover_bank[i] = NULL;
+
+
+  ctx->logical_card_id_hash = (rider_node **)malloc(sizeof(rider_node *) * ctx->hash_modulus );
+  CHECK_ALLOC_FAIL( (ctx->logical_card_id_hash) );
+
+  ctx->rider_mag_hash       = (rider_node **)malloc(sizeof(rider_node *) * ctx->hash_modulus );
+  CHECK_ALLOC_FAIL( (ctx->rider_mag_hash) );
+
+  ctx->rider_rf_hash        = (rider_node **)malloc(sizeof(rider_node *) * ctx->hash_modulus );
+  CHECK_ALLOC_FAIL( (ctx->rider_rf_hash) );
+
+
+  for (i=0; i<ctx->hash_modulus; i++)
+  {
+    ctx->logical_card_id_hash[i] = NULL;
+    ctx->rider_mag_hash[i] = NULL;
+    ctx->rider_rf_hash[i] = NULL;
+  }
+
+  return 0;
+}
+

+ 161 - 0
busunit/passdb_slim/rfid_decoder.c

@@ -0,0 +1,161 @@
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "../common/common_defs.h"
+
+typedef struct rfid_decode_pattern_struct
+{
+    unsigned int bits;
+
+    unsigned int shift;
+    unsigned long long mask;
+    unsigned long long match;
+
+    unsigned int site_shift;
+    unsigned long long site_mask;
+    
+    unsigned int id_shift;
+    unsigned long long id_mask;
+    
+} rfid_decode_pattern;
+
+static rfid_decode_pattern rfid_pattern_buffer[NUM_RFID_PATTERNS] = {{0}};
+static int rfid_pattern_used = -1;
+
+int rfid_pattern_loaded()
+{
+    return rfid_pattern_used;
+}
+
+int load_rfid_decode_patterns(char *filename)
+{
+    char line[LINE_BUFFER_SIZE];
+    int i, retval;
+    FILE *f;
+    char *c;
+    
+    if(!filename)
+    {
+        fprintf(stderr, "Cannot open RFID Pattern Match file %s", "(null)");
+        rfid_pattern_used = -1;
+        return -1;
+    }
+    
+    i = 0;
+    f = fopen(filename, "rb");
+    
+    if(!f)
+    {
+        fprintf(stderr, "Cannot open RFID Pattern Match file %s", filename);
+        rfid_pattern_used = -1;
+        return -1;
+    }
+    
+    while(i < NUM_RFID_PATTERNS)
+    {
+        fgets(line, LINE_BUFFER_SIZE, f);
+
+        if(feof(f))
+        {
+            break;
+        }
+        
+        c = line;
+        
+        //skip any blank lines, or comment lines starting with a # as their first non-whitespace character
+        while( (*c == ' ') || (*c == '\t') || (*c == '\r') || (*c == '\n') ) c++;
+        if( (*c == '#') || (*c == '\0') ) continue;
+        
+        retval = sscanf(c, "%x %x %llx %llx %x %llx %x %llx", &rfid_pattern_buffer[i].bits, &rfid_pattern_buffer[i].shift, 
+                                                             &rfid_pattern_buffer[i].mask, &rfid_pattern_buffer[i].match, 
+                                                             &rfid_pattern_buffer[i].site_shift, &rfid_pattern_buffer[i].site_mask, 
+                                                             &rfid_pattern_buffer[i].id_shift, &rfid_pattern_buffer[i].id_mask
+                                                            );
+        
+        if(retval == 8)
+        {
+            i++;
+        }
+        else
+        {
+            memset(&rfid_pattern_buffer[i], 0, sizeof(rfid_decode_pattern));
+            fprintf(stderr, "Cannot parse RFID Pattern Match line \"%s\"\n", line);
+        }
+    }
+
+    fclose(f);
+
+    if(i >= NUM_RFID_PATTERNS)
+    {
+        fprintf(stderr, "RFID Pattern Match file %s contains more than %d records!", filename, NUM_RFID_PATTERNS);
+        rfid_pattern_used = -1;
+        return -1;
+    }
+    
+     memset(&rfid_pattern_buffer[i], 0, sizeof(rfid_decode_pattern));
+    
+     rfid_pattern_used = i;
+     return i;   
+}
+
+
+int decode_rfid_string(char *raw_rfid, unsigned long long *site, unsigned long long *id, unsigned int *bits)
+{
+    unsigned long long raw;
+    unsigned int nbits;
+    char *rest;
+    
+    int i;
+    
+    if(!raw_rfid)
+    {
+        fprintf(stderr, "NULL RFID String!\n");
+        return -1;
+    }
+
+    if(rfid_pattern_used < 1)
+    {
+        fprintf(stderr, "rfid_pattern_used < 1!\n");
+    }
+
+    nbits = strtol(raw_rfid, &rest, 16);
+    
+    if(*rest++ != '|')
+    {
+        fprintf(stderr, "Malformed RFID String!\n");
+        return -1;
+    }
+
+    raw = strtoll(rest, NULL, 16);
+
+    for(i = 0; i < rfid_pattern_used; i++)
+    {
+        //If this RFID string has the right number of bits AND matches our shift-and-mask criteria
+        if( (nbits == rfid_pattern_buffer[i].bits) && 	
+            (((raw >> rfid_pattern_buffer[i].shift) & rfid_pattern_buffer[i].mask) == rfid_pattern_buffer[i].match) 
+          )
+        {
+            if(bits)
+            {
+                *bits = nbits;
+            }
+            
+            if(site)
+            {
+                *site = (raw >> rfid_pattern_buffer[i].site_shift) & rfid_pattern_buffer[i].site_mask;
+            }
+
+            if(id)
+            {
+                *id = (raw >> rfid_pattern_buffer[i].id_shift) & rfid_pattern_buffer[i].id_mask;
+            }
+            
+            return 0;
+        }
+    }
+
+    return -1;
+}
+
+

+ 6 - 0
busunit/passdb_slim/rfid_decoder.h

@@ -0,0 +1,6 @@
+
+int rfid_pattern_loaded();
+int load_rfid_decode_patterns(char *filename);
+int decode_rfid_string(char *raw_rfid, unsigned long long *site, unsigned long long *id, unsigned int *bits);
+
+

+ 954 - 0
busunit/passdb_slim/ruleparam_db.c

@@ -0,0 +1,954 @@
+#include "ruleparam_db.h"
+
+extern int commhub_fd;
+struct message_record log_msg;
+
+int ruleparam_db_init( ruleparam_db_ctx *ctx )
+{
+  ctx->n = 0;
+  ctx->head = NULL;
+
+  ctx->sync_counter = 0;
+  ctx->sync_every_n = 100;
+
+  ctx->n_filename_history = 4;
+  ctx->pos_filename_history = 0;
+
+  ctx->seq = 0;
+
+  return 0;
+}
+
+static int _chomp(char *s)
+{
+  int n;
+
+  if (!s) 
+  {
+    return -1;
+  }
+
+  n = strlen(s);
+
+  if (n==0)
+    return 0;
+
+  if (s[n-1] == '\n')
+  {
+    s[n-1] = '\0';
+    return n-1;
+  }
+
+  return n;
+}
+
+// In the consistency check, we allocate our own ruleparam_db, so we needed to expose
+// this function.
+// 
+passdb_slim_ruleparam *_alloc_ruleparam_db_nod(int id, char *name, char *param)
+{
+  passdb_slim_ruleparam *nod;
+  nod = (passdb_slim_ruleparam *)malloc(sizeof(passdb_slim_ruleparam));
+  if (!nod)
+  {
+    fprintf(stderr, "_alloc_ruelparam_db_nod malloc failed: %s line %i\n", __FILE__, __LINE__ );
+    return NULL;
+  }
+
+  nod->id = id;
+  strncpy( nod->name, name, RULENAME_LEN);
+  strncpy( nod->param, param, PARAM_LEN);
+  nod->name[RULENAME_LEN-1] = '\0';
+  nod->param[PARAM_LEN-1] = '\0';
+  nod->reference_count = 0;
+  nod->next = NULL;
+  return nod;
+}
+
+
+ruleparam_db_ctx * ruleparam_db_alloc(void)
+{
+  ruleparam_db_ctx *ctx;
+  ctx = (ruleparam_db_ctx *)malloc(sizeof(ruleparam_db_ctx));
+  if (!ctx)
+  {
+    fprintf(stderr, "ruleparam_db_alloc: malloc failed: %s line %i\n", __FILE__, __LINE__ );
+    return NULL;
+  }
+
+  ctx->n_filename_history = 4;
+  ctx->pos_filename_history = 0;
+
+
+  ruleparam_db_init(ctx);
+  return ctx;
+}
+
+
+int ruleparam_db_load( ruleparam_db_ctx **ctx, char *db_fn )
+{
+  FILE *fp;
+  passdb_slim_ruleparam *nod, *prev=NULL;
+  ruleparam_db_ctx *tctx = NULL;
+
+
+  FILE *seq_fp;
+  char db_seq_fn[1024];
+
+  char buf[1024];
+  char name[RULENAME_LEN];
+  char param[PARAM_LEN];
+  char *chp, *chp_next;
+  char *token;
+  int r = -1;
+  int id;
+
+  int line_no = 0;
+  int k;
+
+  unsigned long long seq=0;
+  long long int tseq;
+  int rulecount=-1;
+
+
+  tctx = (ruleparam_db_ctx *)malloc(sizeof(ruleparam_db_ctx));
+  CHECK_ALLOC_FAIL( (tctx) );
+
+  ruleparam_db_init( tctx );
+
+
+  // Read in sequence number from file.
+  // Keep going if file does not exist.
+  //
+  snprintf(db_seq_fn, 128, "%s.seq", db_fn );
+  seq_fp = fopen( db_seq_fn, "r");
+  if (!seq_fp)
+  {
+    perror( db_seq_fn );
+  }
+  else
+  {
+    fgets( buf, 1024, seq_fp );
+    tseq = atoll( buf );
+    if (tseq > 0)
+    {
+      seq = (unsigned long long)tseq;
+    }
+    fclose(seq_fp);
+  }
+
+
+  fp = fopen(db_fn, "r");
+  if (!fp)
+  {
+    perror(db_fn);
+    if (tctx) 
+      free(tctx);
+    return -1;
+  }
+
+  while (fgets(buf, 1024, fp ))
+  {
+
+    line_no++;
+
+    chp = buf;
+    if (!chp)
+      break;
+
+    if (!(*chp))
+      continue;
+
+    token = chp;
+
+    // skip initial whitespace
+    //
+    while ( (*token) && (*token == ' ') )
+      token++;
+
+    // skip comment
+    //
+    if (token[0] == '#') 
+    {
+
+      /*
+      if (strncmp( token, "#seq: ", strlen("#seq: ")) == 0)
+      {
+        tseq = atoll( token + strlen("#seq: ") );
+        if (tseq > 0)
+        {
+          seq = (unsigned long long)tseq;
+        }
+      }
+      else 
+      */
+
+      if (strncmp( token, "#rulecount: ", strlen("#rulecount: ")) == 0)
+      {
+        rulecount = atoi( token + strlen("#rulecount: ") );
+      }
+      continue;
+    }
+
+    // skip if empty line
+    //
+    if (*token == '\n') continue;
+
+    // FIRST TOKEN (id)
+    //find next token (tab)
+    chp_next = strchr( chp, '\t' );
+    if (!chp_next) { goto _cleanup; }
+    *chp_next = '\0';
+
+    // and process
+    k = _chomp(token);
+    if (k<0) { goto _cleanup; }
+    if (k==0) continue;
+
+    id = atoi(token);
+
+
+    // SECOND TOKEN (rule)
+    // find next token (tab)
+    token = chp_next+1;
+    chp_next = strchr( token, '\t' );
+    if ( !chp_next ) { goto _cleanup; }
+    *chp_next = '\0';
+    _chomp(token);
+
+    // and process
+    strncpy(name, token, RULENAME_LEN);
+    name[RULENAME_LEN-1] = '\0';
+
+
+    // THIRD TOKEN (param)
+    // NOTE: fourth token assummed to exist, even though we don't read it
+    // in.  By convention, the fourth token is the reference count.
+    //
+    // find next token (tab)
+    token = chp_next+1;
+    chp_next = strchr( token, '\t' );
+    if ( !chp_next ) { goto _cleanup; }
+    *chp_next = '\0';
+    _chomp(token);
+
+    // and process
+    strncpy(param, token, PARAM_LEN);
+    param[PARAM_LEN-1] = '\0';
+
+    nod = _alloc_ruleparam_db_nod( id, name, param );
+
+    if (tctx->head) prev->next = nod;
+    else            tctx->head = nod;
+    prev = nod;
+
+    tctx->n++;
+
+  }
+
+  if (tctx->n != rulecount)
+  {
+    fprintf(stderr, "WARNING: ruleparam_db_load: read rule count (%i) != reported rule count (%i)\n", tctx->n, rulecount);
+  }
+
+  r = 0;
+  tctx->db_filename = strdup( db_fn );
+  tctx->seq = seq;
+  *ctx = tctx;
+
+  return 0;
+
+_cleanup:
+
+  fprintf(stderr, "ERROR: ruleparam_db_load: FAIL on line %i\n", line_no);
+
+  if (tctx) 
+  {
+    nod = tctx->head;
+    while (nod)
+    {
+      prev = nod;
+      nod = nod->next;
+      free(prev);
+    }
+    free(tctx);
+  }
+
+  fclose(fp);
+  return -1;
+
+}
+
+int _copy_file( char *src_fn, char *dst_fn )
+{
+  FILE *src_fp, *dst_fp;
+  char buf[1024];
+  int read_len=0, write_len=0;
+  int ret=0;
+
+  if ( !(src_fp = fopen(src_fn, "r")) )
+  {
+    perror(src_fn);
+    return errno;
+  }
+
+  if ( !(dst_fp = fopen(dst_fn, "w")) )
+  {
+
+    fclose(src_fp);
+    perror(dst_fn);
+    return errno;
+  }
+
+  while (!feof(src_fp))
+  {
+    read_len = fread(buf, 1, sizeof(buf), src_fp);
+
+    if (read_len <= 0) 
+    {
+      if (ferror(src_fp) != 0)
+      {
+        perror(src_fn);
+        ret = errno;
+        goto _copy_file_cleanup;
+      }
+      continue;
+    }
+
+
+    while ( (write_len = fwrite(buf, 1, read_len, dst_fp)) != read_len )
+    {
+      perror(dst_fn);
+      ret = errno;
+      goto _copy_file_cleanup;
+    }
+
+  }
+
+
+_copy_file_cleanup:
+  fclose(src_fp);
+  fclose(dst_fp);
+
+  return ret;
+}
+
+int ruleparam_db_seq_save( ruleparam_db_ctx *ctx )
+{
+  FILE *seq_fp;
+  char tmp_fn[512];
+  char seq_fn[512];
+
+
+  // After ruleparam.db has been synchronized, finally
+  // write out sequence number in 'ruleparam.db.seq' file.
+  //
+  snprintf(tmp_fn, 512, "%s.seq.tmp", ctx->db_filename );
+  snprintf(seq_fn, 512, "%s.seq", ctx->db_filename );
+  seq_fp = fopen( tmp_fn, "w" );
+  if (seq_fp)
+  {
+    fprintf(seq_fp, "%llu", ctx->seq);
+    fclose(seq_fp);
+    sync();
+
+    rename( tmp_fn, seq_fn );
+    sync();
+
+  }
+  else
+  {
+    perror( tmp_fn );
+    return -1;
+  }
+
+  return 0;
+}
+
+int ruleparam_db_save( ruleparam_db_ctx *ctx )
+{
+  FILE *fp;
+  passdb_slim_ruleparam *nod;
+  struct tm tm_tim;
+  struct timeval timval;
+  char str_tim[64];
+
+  char tmp_fn[1024];
+  char log_fn[1024];
+  int fn_num = 0;
+
+  int rule_count=0;
+
+  if ( ctx->n_filename_history > 1 )
+  {
+    if (ctx->pos_filename_history < 0)
+    {
+      ctx->pos_filename_history = 0;
+    }
+    else
+    {
+      ctx->pos_filename_history++;
+      ctx->pos_filename_history %= ctx->n_filename_history;
+    }
+
+    fn_num = ctx->pos_filename_history;
+
+  }
+
+  sprintf(tmp_fn, "%s.%i.tmp", ctx->db_filename, fn_num);
+  sprintf(log_fn, "%s.%i", ctx->db_filename, fn_num);
+
+  gettimeofday(&timval, NULL);
+  localtime_r(&(timval.tv_sec), &tm_tim);
+  asctime_r(&tm_tim, str_tim);
+
+
+  fp = fopen(tmp_fn, "w");
+  if (!fp)
+  {
+    perror(tmp_fn);
+
+    format_log_message(&log_msg, LOGLEVEL_ERROR, "Ruleparam dabase open error (%s)", tmp_fn);
+    if (commhub_fd >= 0)
+    {
+      send_message(commhub_fd, &log_msg);
+    }
+
+    return -1;
+  }
+
+  fprintf(fp, "# %s", str_tim);
+  fprintf(fp, "# Tabs are a necessary field delimiter.\n");
+  fprintf(fp, "#\n# InternalID,RuleName,RuleParam,ReferenceCount\n");
+  fprintf(fp, "# Note: The reference count in this file is only used for debugging purposes.\n");
+  fprintf(fp, "#seq: %llu\n", ctx->seq);
+  fprintf(fp, "#\n#\n");
+
+  nod = ctx->head;
+  while (nod)
+  {
+    fprintf(fp, "%i\t%s\t%s\t%i\n", nod->id, nod->name, nod->param, nod->reference_count);
+    nod = nod->next;
+
+    rule_count++;
+  }
+
+  fprintf(fp, "#rulecount: %i\n", rule_count);
+
+  fclose(fp);
+  sync();
+
+  if (_copy_file( tmp_fn, log_fn ) < 0)
+  {
+    format_log_message(&log_msg, LOGLEVEL_ERROR, "Ruleparam dabase copy error (%s -> %s)", tmp_fn, log_fn);
+    if (commhub_fd >= 0)
+    {
+      send_message(commhub_fd, &log_msg);
+    }
+
+    return errno;
+  }
+  sync();
+
+  rename( tmp_fn, ctx->db_filename );
+  sync();
+
+  ruleparam_db_seq_save( ctx );
+  
+
+  return 0;
+}
+
+int format_new_ruleparamdb( char *fn )
+{
+  ruleparam_db_ctx ctx;
+  ruleparam_db_init(&ctx);
+
+  //return ruleparam_db_save( &ctx, fn );
+  return ruleparam_db_save( &ctx );
+}
+
+
+int ruleparam_db_add( ruleparam_db_ctx *ctx, char *name, char *param)
+{
+  int id;
+  passdb_slim_ruleparam *prev = NULL, *nod ;
+
+  if (ctx->n == RULEPARAM_DB_MAX)
+    return RULEPARAM_DB_FULL;
+
+  id = ruleparam_db_find( ctx, name, param );
+  if (id >= 0)
+    return RULEPARAM_DB_DUP;
+
+  id = ruleparam_db_find_free_id( ctx );
+  if (id < 0)
+    return id;
+
+  nod = _alloc_ruleparam_db_nod( id, name, param);
+
+  ctx->n++;
+
+  if (!(ctx->head))
+  {
+    ctx->head = nod;
+    return 0;
+  }
+
+  prev = ctx->head;
+  while(prev->next) prev = prev->next;
+
+  prev->next = nod;
+  return id;
+}
+
+int ruleparam_db_remove( ruleparam_db_ctx *ctx, int id)
+{
+  passdb_slim_ruleparam *prev = NULL, *nod ;
+
+  nod = ctx->head;
+  while (nod)
+  {
+
+    if (nod->id == id)
+    {
+      if (prev) prev->next = nod->next;
+      else      ctx->head = nod->next;
+
+      free(nod);
+      ctx->n--;
+
+      return 0;
+    }
+
+    prev = nod;
+    nod = nod->next;
+  }
+
+  return RULEPARAM_DB_NOT_FOUND;
+
+}
+
+
+// Return id of found rule record.
+// RULEPARAM_DB_NOT_FOUND if none found.
+//
+int ruleparam_db_find( ruleparam_db_ctx *ctx, char *name, char *param )
+{
+  passdb_slim_ruleparam *nod;
+
+  nod = ctx->head;
+  while (nod)
+  {
+    if ( (strncmp( nod->name, name, RULENAME_LEN ) == 0) &&
+         (strncmp( nod->param, param, PARAM_LEN ) == 0) )
+      return nod->id;
+    nod = nod->next;
+  }
+
+  return RULEPARAM_DB_NOT_FOUND;
+}
+
+// Return reference count of rule give as (name,param) string pair
+//
+int ruleparam_db_reference_count( ruleparam_db_ctx *ctx, char *name, char *param )
+{
+  passdb_slim_ruleparam *nod;
+
+  nod = ctx->head;
+  while (nod)
+  {
+    if ( (strncmp( nod->name, name, RULENAME_LEN ) == 0) &&
+         (strncmp( nod->param, param, PARAM_LEN ) == 0) )
+      return nod->reference_count;
+    nod = nod->next;
+  }
+
+  return RULEPARAM_DB_NOT_FOUND;
+}
+
+
+// Populate name and param from rule id, if found
+//
+int ruleparam_db_get( char *name, char *param, ruleparam_db_ctx *ctx, int id )
+{
+  passdb_slim_ruleparam *nod;
+
+  nod = ctx->head;
+
+  while (nod)
+  {
+    if (nod->id == id)
+    {
+      memcpy( name, nod->name, RULENAME_LEN );
+      memcpy( param, nod->param, PARAM_LEN );
+      name[RULENAME_LEN-1] = '\0';
+      name[PARAM_LEN-1] = '\0';
+      return 0;
+    }
+
+    nod = nod->next;
+  }
+
+  return RULEPARAM_DB_NOT_FOUND;
+
+}
+
+
+static int _icmp( const void *a, const void *b)
+{
+  return (*((int *)a)) - (*((int *)b)) ;
+}
+
+//  Take all id's, put them into an array.
+//  Sort it.
+//  Find the first non colliding entry starting
+//  at 0.
+//
+int ruleparam_db_find_free_id( ruleparam_db_ctx *ctx )
+{
+  int i, n, pos=0;
+  int *p;
+  passdb_slim_ruleparam *nod;
+
+  n = ctx->n;
+
+  if (n == RULEPARAM_DB_MAX)
+    return RULEPARAM_DB_FULL;
+
+  if (n == 0)
+    return 0;
+
+  p = (int *)malloc(sizeof(int)*n);
+  CHECK_ALLOC_FAIL( (p) );
+
+  nod = ctx->head;
+  while (nod)
+  {
+    p[pos++] = nod->id;
+    nod = nod->next;
+  }
+
+  qsort(p, n, sizeof(int), _icmp);
+
+  i=0;
+  pos=0;
+  while ( (i<n) && (pos < RULEPARAM_DB_MAX) )
+  {
+    if (p[i] == pos)
+    {
+      i++;
+      pos++;
+    }
+    else break;
+  }
+
+  free(p);
+
+  return pos;
+}
+
+void ruleparam_db_dump(ruleparam_db_ctx *ctx)
+{
+  passdb_slim_ruleparam *nod;
+  printf("n %i\n", ctx->n);
+
+  nod = ctx->head;
+  while (nod)
+  {
+    printf(" (%i) '%s' '%s'\n", nod->id, nod->name, nod->param );
+    nod = nod->next;
+  }
+
+  printf("\n");
+
+}
+
+passdb_slim_ruleparam *ruleparam_db_get_node( ruleparam_db_ctx *ctx, int id )
+{
+  passdb_slim_ruleparam *nod;
+  nod = ctx->head;
+  while (nod)
+  {
+    if (nod->id == id )
+      return nod;
+    nod = nod->next;
+  }
+  return NULL;
+}
+
+int ruleparam_db_update( ruleparam_db_ctx *ctx, char *name, char *param, int delta_ref_count )
+{
+  int id;
+  int r;
+  passdb_slim_ruleparam *nod = NULL;
+
+  id = ruleparam_db_find( ctx, name, param );
+
+  // If it's not found, create it and update reference count
+  //
+  if ( id == RULEPARAM_DB_NOT_FOUND )
+  {
+
+    if (delta_ref_count < 0)
+    {
+      goto _ruleparam_db_update_sanity_error;
+    }
+
+    id = ruleparam_db_add( ctx, name, param );
+
+    if (id < 0)
+      return id;
+
+    nod = ruleparam_db_get_node( ctx, id );
+    nod->reference_count += delta_ref_count;
+
+    //ruleparam_db_save( ctx, ctx->db_filename );
+    ruleparam_db_save( ctx );
+
+    return id;
+  }
+
+  // Rule record was found, update reference count
+  //
+  nod = ruleparam_db_get_node( ctx, id );
+  nod->reference_count += delta_ref_count;
+
+  // check for sanity
+  // 
+  if (nod->reference_count < 0)
+  {
+    goto _ruleparam_db_update_sanity_error;
+  }
+
+  // simply return if there are more references to this record
+  //
+  if (nod->reference_count > 0)
+  {
+    return id;
+  }
+
+  // otherwise we need to remove this rule record
+  //
+  r = ruleparam_db_remove( ctx, id );
+
+  if (r < 0)
+    goto _ruleparam_db_update_sanity_error;
+
+
+  //ruleparam_db_save( ctx, ctx->db_filename );
+  ruleparam_db_save( ctx );
+
+  return r;
+
+_ruleparam_db_update_sanity_error:
+    fprintf(stderr, "ERROR: sanity! ruleparam_db_update: id %i (%s,%s), delta_ref_count: %i, [ nod(%p).reference_count:%i ] \n",
+        id, name, param, delta_ref_count,
+        nod, nod ? nod->reference_count : 0 );
+    fprintf(stdout, "ERROR: sanity! ruleparam_db_update: id %i (%s,%s), delta_ref_count: %i, [ nod(%p).reference_count:%i ] \n",
+        id, name, param, delta_ref_count,
+        nod, nod ? nod->reference_count : 0 );
+    return RULEPARAM_DB_SANITY;
+
+}
+
+// Remove entries that have zero references
+//
+int ruleparam_db_clean (ruleparam_db_ctx *ctx)
+{
+  passdb_slim_ruleparam *nod;
+  passdb_slim_ruleparam *prv = NULL;
+  passdb_slim_ruleparam *nex ;
+
+  nod = ctx->head;
+  while (nod)
+  {
+    nex = nod->next;
+
+    if (nod->reference_count == 0)
+    {
+
+      if (prv) prv->next = nex;
+      else     ctx->head = nex;
+
+      free(nod);
+      ctx->n--;
+
+    }
+    else
+    {
+      prv = nod;
+    }
+
+    nod = nex;
+  }
+
+  if (ctx->n == 0)
+    ctx->head = NULL;
+
+  return 0;
+}
+
+int ruleparam_db_consistency_check( ruleparam_db_ctx *ctx )
+{
+  int n=0;
+  passdb_slim_ruleparam *nod;
+
+  if (!ctx)
+  {
+    printf("ruleparam_db_consistenc_check: error, ctx is null\n");
+    return 0;
+  }
+
+  if ((ctx->n > 0) && (!(ctx->head)))
+  {
+    printf("ruleparam_db_consistenc_check: error, ctx->n > 0 (%i) but ctx->head is null \n", ctx->n);
+  }
+
+  nod = ctx->head;
+  while(nod)
+  {
+
+    if (nod->name[0] == '\0')
+    {
+      printf("ruleparam_db_consistenc_check: error, node id %i (pos %i) name is empty\n", nod->id, n);
+      return 0;
+    }
+
+    if (nod->reference_count <= 0)
+    {
+      printf("ruleparam_db_consistenc_check: error, node id %i (pos %i) (%s,%s) reference count (%i) <= 0 \n", nod->id, n, nod->name, nod->param, nod->reference_count);
+      return 0;
+    }
+
+    n++;
+    nod = nod->next;
+  }
+
+  if (n != ctx->n)
+  {
+    printf("ruleparam_db_consistenc_check: error, ctx->n (%i) != list length (%i) \n", ctx->n, n);
+    return 0;
+  }
+
+  return 1;
+}
+
+int ruleparam_db_debug_dump( ruleparam_db_ctx *ctx) 
+{
+  int count=0;
+  passdb_slim_ruleparam *nod;
+
+  printf("ruleparam_db_ctx:\n");
+  printf("  n: %i\n", ctx->n);
+  printf("  db_filename: %s\n", ctx->db_filename);
+
+  nod = ctx->head;
+  while (nod)
+  {
+    printf("    {%i} id: %i, reference_count: %i, name: %s, param: %s\n", 
+        count++, nod->id, nod->reference_count, nod->name, nod->param );
+    nod = nod->next;
+  }
+  printf("\n");
+
+  return 0;
+}
+
+int ruleparam_db_free( ruleparam_db_ctx *ctx )
+{
+  passdb_slim_ruleparam *nod, *prev = NULL;
+
+  nod = ctx->head;
+  while (nod)
+  {
+    prev = nod;
+    nod = nod->next;
+    free(prev);
+  }
+
+  if (ctx->db_filename)
+    free(ctx->db_filename);
+
+  free(ctx);
+
+  return 0;
+}
+
+// Periodically refresh ruleparam_db, mostly for debugging purposes
+// so we can see a somewhat recent snapshot of reference counts.
+//
+// ruleparam updates through the 'ruleparam_db_update' function
+// will automatically write to the ruleparam_db file if a deletion
+// or insertion happened.
+//
+int ruleparam_db_rate_limited_sync( ruleparam_db_ctx *ctx )
+{
+  int retval = 0;
+
+  if (ctx->sync_every_n < 1)
+  {
+    ctx->sync_counter++;
+    return retval;
+  }
+
+  if ((ctx->sync_counter % ctx->sync_every_n) == 0)
+  {
+    ruleparam_db_save( ctx );
+    retval = 1;
+  }
+
+  // Else do a sequence number save regardless
+  //
+  else
+  {
+    ruleparam_db_seq_save( ctx );
+    sync();
+  }
+
+
+  ctx->sync_counter++;
+
+  return retval;
+}
+
+/*
+int main(int argc, char **argv)
+{
+  int id=-1, k;
+  char name[64], param[64];
+
+  name[0] = '\0';
+  param[0] = '\0';
+
+  ruleparam_db_ctx *ctx;
+
+  ruleparam_db_load(&ctx, RULEPARAM_DB_FILE);
+
+  ruleparam_db_dump(ctx);
+
+  ruleparam_db_add( ctx, "myrule", "myparam" );
+  id = ruleparam_db_add( ctx, "myrule0", "myparam" );
+  ruleparam_db_add( ctx, "myrule", "myparam0" );
+  ruleparam_db_add( ctx, "myrule0", "myparam0" );
+
+  ruleparam_db_dump(ctx);
+
+  printf("removing %i\n", id);
+  printf("\n\n");
+
+  ruleparam_db_remove( ctx, id );
+  ruleparam_db_dump(ctx);
+
+
+  ruleparam_db_save(ctx, RULEPARAM_DB_FILE);
+
+  id = ruleparam_db_find(ctx, "myrule0", "myparam");
+  printf("got %i\n", id);
+
+
+  k = ruleparam_db_get(name, param, ctx, id);
+  printf("  (%i) %s %s\n", k, name, param);
+
+}
+*/

+ 90 - 0
busunit/passdb_slim/ruleparam_db.h

@@ -0,0 +1,90 @@
+#ifndef PASSDB_SLIM_RULEPARAM_DB_H
+#define PASSDB_SLIM_RULEPARAM_DB_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <time.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "../common/common_defs.h"
+#include "../commhub/commhub.h"
+#include "../commhub/client_utils.h"
+
+
+#define RULEPARAM_DB_FILE DATABASE_FILE_PATH "ruleparam.db"
+
+
+#define RULEPARAM_DB_NOT_FOUND  (-1)
+#define RULEPARAM_DB_FULL       (-2)
+#define RULEPARAM_DB_EMPTY      (-3)
+#define RULEPARAM_DB_DUP        (-4)
+#define RULEPARAM_DB_SANITY     (-5)
+
+#define RULEPARAM_DB_MAX ( 2048 )
+
+typedef struct passdb_slim_ruleparam_t {
+  int id;
+  int reference_count;
+  char name[RULENAME_LEN];
+  char param[PARAM_LEN];
+  struct passdb_slim_ruleparam_t *next;
+} passdb_slim_ruleparam;
+
+
+typedef struct passdb_slim_ruleparam_db_context_t {
+  int n;
+  passdb_slim_ruleparam *head;
+  char *db_filename;
+
+  int sync_counter;
+  int sync_every_n;
+
+  int n_filename_history;     // We want to store some historic ruleparams, which we 
+  int pos_filename_history;   // rotate through.
+  unsigned long long seq;
+} ruleparam_db_ctx;
+
+
+passdb_slim_ruleparam *_alloc_ruleparam_db_nod(int id, char *name, char *param);
+
+
+int ruleparam_db_init( ruleparam_db_ctx * );
+ruleparam_db_ctx * ruleparam_db_alloc( );
+int ruleparam_db_load( ruleparam_db_ctx **, char * );
+int ruleparam_db_free( ruleparam_db_ctx * );
+
+int ruleparam_db_debug_dump( ruleparam_db_ctx *);
+
+//int ruleparam_db_save( ruleparam_db_ctx *, char * );
+int ruleparam_db_save( ruleparam_db_ctx * );
+//int ruleparam_db_rate_limited_sync( ruleparam_db_ctx *, char * );
+int ruleparam_db_rate_limited_sync( ruleparam_db_ctx * );
+
+int ruleparam_db_add( ruleparam_db_ctx *, char *, char *);
+int ruleparam_db_remove( ruleparam_db_ctx *, int );
+int ruleparam_db_find( ruleparam_db_ctx *, char *, char *);
+int ruleparam_db_reference_count( ruleparam_db_ctx *, char *, char *);
+
+int ruleparam_db_get( char *, char *, ruleparam_db_ctx *, int );
+
+int ruleparam_db_find_free_id( ruleparam_db_ctx * );
+
+int ruleparam_db_update( ruleparam_db_ctx *ctx, char *name, char *param, int delta_ref_count );
+
+int ruleparam_db_clean( ruleparam_db_ctx *ctx );
+
+
+int ruleparam_db_consistency_check( ruleparam_db_ctx *ctx );
+
+passdb_slim_ruleparam *ruleparam_db_get_node( ruleparam_db_ctx *ctx, int id );
+
+int format_new_ruleparamdb(char *);
+
+void ruleparam_db_dump(ruleparam_db_ctx *ctx);
+
+#endif
+

File diff suppressed because it is too large
+ 1623 - 0
busunit/passdb_slim/rules.c


+ 45 - 0
busunit/passdb_slim/rules.h

@@ -0,0 +1,45 @@
+
+
+//This function clears the entire anti-passback cache
+int apb_clear();
+
+//    This function examines the state of the gps_stat and stop_stat structures and clears the anti-passback cache if the bus has
+//either moved at least APB_DIST_EXPIRE meters since the last accept, or if the route, trip, or stop have changed.
+//    If the cache is cleared as the result of this function call, the cache state is updated so that it reflects the location
+//data as they stood when the flush was completed.  If there is nothing in the cache, the location is simply updated.
+int apb_flush_if_needed();
+
+//Add a rider to the anti-passback cache...
+int apb_add(logical_card_id_t id);
+
+//    Look up a rider in the anti-passback cache.  If the rider is not present, this function returns zero.
+//If the rider is present, this function returns the number of seconds since they last rode this bus.
+int apb_lookup(logical_card_id_t id);
+
+//    This function does a "smart" magstripe lookup by looking up the token found
+//on track1, then track2, then track3 individually (ignoring tracks 1 and 2 if they
+//contain credit-card style field-delimiters), returning the index of the rider
+//in the riders database attached to ctx, or -1 if not found.
+//    If the return is -1 (not found) final_token is filled with the whole list of
+//tracks that were attempted (with credit-card looking tracks blanked out).
+//    If the return is >= 0 (record found) final_token is filled with the token that
+//was used to generate the match.
+int smart_find_mag(passdb_slim_context *ctx, char *token, char *final_token);
+
+//    This function does a "smart" RFID lookup by translating the raw RFID format (NN|XXXX...)
+//where NN is the number of bits in hex, and XXXX... is the bitstring in hex (right justified
+//to the nearest nibble boundary) and processing it based on the number of bits and a list of
+//known formats until it either matches a known format or is determined not to match any of them.
+//    If a match is found, the return value will be >= 0 and indicate the index of the rider in
+//the database that ctx is attached to.  If no match is found, -1 is returned.  In either case
+//final_token is filled with the string representing the decoded decimal RFID value "nbits:site:id"
+//or if the token was not in a known format, "nbits:rawval?".
+int smart_find_rf(passdb_slim_context *ctx, char *token, char *final_token);
+
+int rules_loaded();
+int load_rules(char *filename);
+int unload_rules();
+
+int process_rider(passdb_slim_context *ctx, int rider_index, char *credential);
+
+int process_driver_rulecall(struct driver_rulecall_struct *drc);

+ 139 - 0
busunit/passdb_slim/tinyscheme1.39/BUILDING

@@ -0,0 +1,139 @@
+	Building TinyScheme
+	-------------------
+
+The included makefile includes logic for Linux, Solaris and Win32, and can
+readily serve as an example for other OSes, especially Unixes. There are
+a lot of compile-time flags in TinyScheme (preprocessor defines) that can trim
+unwanted features. See next section. 'make all' and 'make clean' function as
+expected.
+
+Autoconfing TinyScheme was once proposed, but the distribution would not be
+so small anymore. There are few platform dependencies in TinyScheme, and in
+general compiles out of the box.
+
+	 Customizing
+     -----------
+
+     The following symbols are defined to default values in scheme.h.
+     Use the -D flag of cc to set to either 1 or 0.
+
+     STANDALONE
+     Define this to produce a standalone interpreter.
+
+     USE_MATH
+     Includes math routines.
+
+     USE_CHAR_CLASSIFIERS
+     Includes character classifier procedures.
+
+     USE_ASCII_NAMES
+     Enable extended character notation based on ASCII names.
+
+     USE_STRING_PORTS
+     Enables string ports.
+
+     USE_ERROR_HOOK
+     To force system errors through user-defined error handling.
+     (see "Error handling")
+
+     USE_TRACING
+     To enable use of TRACING.
+
+     USE_COLON_HOOK
+     Enable use of qualified identifiers. (see "Colon Qualifiers - Packages")
+     Defining this as 0 has the rather drastic consequence that any code using
+     packages will stop working, and will have to be modified. It should only
+     be used if you *absolutely* need to use '::' in identifiers.
+
+     USE_STRCASECMP
+     Defines stricmp as strcasecmp, for Unix.
+
+     STDIO_ADDS_CR
+     Informs TinyScheme that stdio translates "\n" to "\r\n". For DOS/Windows.
+
+     USE_DL
+     Enables dynamically loaded routines. If you define this symbol, you
+     should also include dynload.c in your compile.
+
+     USE_PLIST
+     Enables property lists (not Standard Scheme stuff). Off by default.
+     
+     USE_NO_FEATURES
+     Shortcut to disable USE_MATH, USE_CHAR_CLASSIFIERS, USE_ASCII_NAMES,
+     USE_STRING_PORTS, USE_ERROR_HOOK, USE_TRACING, USE_COLON_HOOK,
+     USE_DL.
+
+	 USE_SCHEME_STACK
+	 Enables 'cons' stack (the alternative is a faster calling scheme, which 
+	 breaks continuations). Undefine it if you don't care about strict compatibility
+	 but you do care about faster execution.
+
+
+     OS-X tip
+     --------
+	 I don't have access to OS-X, but Brian Maher submitted the following tip:
+
+[1] Download and install fink (I installed fink in
+/usr/local/fink)
+[2] Install the 'dlcompat' package using fink as such:
+> fink install dlcompat
+[3] Make the following changes to the
+tinyscheme-1.32.tar.gz
+
+diff -r tinyscheme-1.32/dynload.c
+tinyscheme-1.32-new/dynload.c
+24c24
+< #define SUN_DL
+---
+> 
+Only in tinyscheme-1.32-new/: dynload.o
+Only in tinyscheme-1.32-new/: libtinyscheme.a Only in tinyscheme-1.32-new/: libtinyscheme.so diff -r tinyscheme-1.32/makefile tinyscheme-1.32-new/makefile
+33,34c33,43
+< LD = gcc
+< LDFLAGS = -shared
+---
+> #LD = gcc
+> #LDFLAGS = -shared
+> #DEBUG=-g -Wno-char-subscripts -O
+> #SYS_LIBS= -ldl
+> #PLATFORM_FEATURES= -DSUN_DL=1
+> 
+> # Mac OS X
+> CC = gcc
+> CFLAGS = -I/usr/local/fink/include
+> LD = gcc
+> LDFLAGS = -L/usr/local/fink/lib
+37c46
+< PLATFORM_FEATURES= -DSUN_DL=1
+---
+> PLATFORM_FEATURES= -DSUN_DL=1 -DOSX
+60c69
+<       $(CC) -I. -c $(DEBUG) $(FEATURES)
+$(DL_FLAGS) $<
+---
+>       $(CC) $(CFLAGS) -I. -c $(DEBUG)
+$(FEATURES) $(DL_FLAGS) $<
+66c75
+<       $(CC) -o $@ $(DEBUG) $(OBJS) $(SYS_LIBS) 
+---
+>       $(CC) $(LDFLAGS) -o $@ $(DEBUG) $(OBJS)
+$(SYS_LIBS)
+Only in tinyscheme-1.32-new/: scheme
+diff -r tinyscheme-1.32/scheme.c
+tinyscheme-1.32-new/scheme.c
+60,61c60,61
+< #ifndef macintosh
+< # include <malloc.h>
+---
+> #ifdef OSX
+> /* Do nothing */
+62a63,65
+> # ifndef macintosh
+> #  include <malloc.h>
+> # else
+77c80,81
+< #endif /* macintosh */
+---
+> # endif /* macintosh */
+> #endif /* !OSX */
+Only in tinyscheme-1.32-new/: scheme.o

+ 208 - 0
busunit/passdb_slim/tinyscheme1.39/CHANGES

@@ -0,0 +1,208 @@
+     Change Log
+     ----------
+     Version 1.39
+          Drew Yao fixed buffer overflow problems in mk_sharp_const.
+     Version 1.38
+          Interim release until the rewrite, mostly incorporating modifications from 
+          Kevin Cozens. Small addition for Cygwin in the makefile, and modifications
+          by Andrew Guenther for Apple platforms.
+     Version 1.37
+          Joe Buehler submitted reserve_cells.
+     Version 1.36
+	  Joe Buehler fixed a patch in the allocator.
+	  Alexander Shendi moved the comment handling in the scanner, which 
+	  fixed an obscure bug for which Mike E had provided a patch as well.
+	  Kevin Cozens has submitted some fixes and modifications which have not
+	  been incorporated yet in their entirety.
+     Version 1.35
+	  Todd Showalter discovered that the number of free cells reported 
+	  after GC was incorrect, which could also cause unnecessary allocations.
+	 Version 1.34
+	  Long missing version. Lots of bugfixes have accumulated in my email, so
+	  I had to start using them. In this version, Keenan Pepper has submitted
+	  a bugfix for the string comparison library procedure, Wouter Boeke 
+	  modified some code that was casting to the wrong type and crashed on
+	  some machines, "SheppardCo" submitted a replacement "modulo" code and
+	  Scott Fenton submitted lots of corrections that shut up some compiler
+	  warnings. Brian Maher submitted instructions on how to build on OS-X.
+	  I have to dig deeper into my mailbox and find earlier emails, too.
+     Version 1.33
+	  Charles Hayden fixed a nasty GC bug of the new stack frame, while in
+	  the process of porting TinyScheme to C++. He also submitted other 
+	  changes, and other people also had comments or requests, but the GC
+	  bug was so important that this version is put through the door to 
+	  correct it.
+     Version 1.32
+	  Stephen Gildea put some quality time on TinyScheme again, and made
+	  a whole lot of changes to the interpreter that made it noticeably 
+	  faster.
+     Version 1.31
+          Patches to the hastily-done version 1.30. Stephen Gildea fixed
+	  some things done wrongly, and Richard Russo fixed the makefile
+	  for building on Windows. Property lists (heritage from MiniScheme)
+	  are now optional and have dissappeared from the interface. They
+	  should be considered as deprecated.
+     Version 1.30
+	  After many months, I followed Preston Bannister's advice of
+	  using macros and a single source text to keep the enums and the
+	  dispatch table in sync, and I used his contributed "opdefines.h".
+	  Timothy Downs contributed a helpful function, "scheme_call".
+	  Stephen Gildea contributed new versions of the makefile and 
+	  practically all other sources. He created a built-in STRING-APPEND,
+	  and fixed a lot of other bugs.
+	  Ruhi Bloodworth reported fixes necessary for OS X and a small
+	  bug in dynload.c.
+     Version 1.29
+	  The previous version contained a lot of corrections, but there
+	  were a lot more that still wait on a sheet of paper lost in a
+	  carton someplace after my house move... Manuel Heras-Gilsanz
+	  noticed this and resent his own contribution, which relies on
+	  another bugfix that v.1.28 was missing: a problem with string
+	  output, that this version fixes. I hope other people will take
+	  the time to resend their contributions, if they didn't make it
+	  to v.1.28.
+     Version 1.28
+	  Many people have contacted me with bugfixes or remarks in
+	  the three months I was inactive. A lot of them spotted that 
+	  scheme_deinit crashed while reporting gc results. They suggested
+	  that sc->outport be set to NIL in scheme_deinit, which I did.
+	  Dennis Taylor remarked that OP_VALUEPRINT reset sc->value instead
+	  of preserving it. He submitted a modification which I adopted 
+	  partially. David Hovemeyer sent me many little changes, that you
+	  will find in version 1.28, and Partice Stoessel modified the 
+	  float reader to conform to R5RS.
+     Version 1.27
+          Version 1.27 is the successor of 1.25. Bug fixes only, but I had to
+          release them so that everybody can profit. 'Backchar' tried to write
+          back to the string, which obviously didn't work for const strings.
+          'Substring' didn't check for crossed start and end indices. Defines
+          changed to restore the ability to compile under MSVC.
+     Version 1.26
+          Version 1.26 was never released. I changed a lot of things, in fact
+          too much, even the garbage collector, and hell broke loose. I'll
+          try a more gradual approach next time.
+     Version 1.25
+          Types have been homogenized to be able to accomodate a different
+	  representation. Plus, promises are no longer closures. Unfortunately,
+	  I discovered that continuations and force/delay do not pass the SCM
+	  test (and never did)... However, on the bright side, what little
+	  modifications I did had a large impact on the footprint: 
+	  USE_NO_FEATURES now produces an object file of 63960 bytes on Linux!
+     Version 1.24
+	  SCM tests now pass again after change in atom2str.
+     Version 1.23
+          Finally I managed to mess it up with my version control. Version
+	  1.22 actually lacked some of the things I have been fixing in the
+	  meantime. This should be considered as a complete replacement for
+	  1.22.
+     Version 1.22
+          The new ports had a bug in LOAD. MK_CLOSURE is introduced.
+	  Shawn Wagner inquired about string->number and number->string.
+	  I added string->atom and atom->string and defined the number
+	  functions from them. Doing that, I fixed WRITE applied to symbols
+	  (it didn't quote them). Unfortunately, minimum build is now
+	  slightly larger than 64k... I postpone action because Jason's idea
+	  might solve it elegantly.
+     Version 1.21
+          Jason Felice submitted a radically different datatype representation
+	  which he had implemented. While discussing its pros and cons, it
+	  became apparent that the current implementation of ports suffered
+	  from a grave fault: ports were not garbage-collected. I changed the
+	  ports to be heap-allocated, which enabled the use of string ports
+	  for loading. Jason also fixed errors in the garbage collection of 
+	  vectors. USE_VERBATIM is gone. "ssp_compiler.c" has a better solution
+	  on HTML generation. A bug involving backslash notation in strings
+	  has been fixed. '-c' flag now executes next argument as a stream of
+	  Scheme commands. Foreign functions are now also heap allocated,
+          and scheme_define is used to define everything.
+     Version 1.20
+          Tracing has been added. The toplevel loop has been slightly
+	  rearranged. Backquote reading for vector templates has been
+	  sanitized. Symbol interning is now correct. Arithmetic functions
+	  have been corrected. APPLY, MAP, FOR-EACH, numeric comparison
+	  functions fixed. String reader/writer understands \xAA notation.
+     Version 1.19
+          Carriage Return now delimits identifiers. DOS-formatted Scheme files
+          can be used by Unix. Random number generator added to library.
+          Fixed some glitches of the new type-checking scheme. Fixed erroneous
+          (append '() 'a) behavior. Will continue with r4rstest.scm to
+          fix errors.
+     Version 1.18
+          The FFI has been extended. USE_VERBOSE_GC has gone. Anyone wanting
+          the same functionality can put (gcverbose #t) in init.scm.
+          print-width was removed, along with three corresponding op-codes.
+     	  Extended character constants with ASCII names were added.
+          mk_counted_string paves the way for full support of binary strings.
+          As much as possible of the type-checking chores were delegated
+          to the inner loop, thus reducing the code size to less than 4200 loc!
+     Version 1.17
+          Dynamically-loaded extensions are more fully integrated.
+          TinyScheme is now distributed under the BSD open-source license.
+     Version 1.16
+          Dynamically-loaded extensions introduced (USE_DL).
+          Santeri Paavolainen found a race condition: When a cons is executed,
+          and each of the two arguments is a constructing function,  GC could
+          happen before all arguments are evaluated and cons() is called, and
+          the evaluated arguments would all be reclaimed!
+          Fortunately, such a case was rare in the code, although it is
+          a pitfall in new code and code in foreign functions. Currently, only
+          one such case remains, when COLON_HOOK is defined.
+     Version 1.15
+          David Gould also contributed some changes that speed up operation.
+          Kirk Zurell fixed HASPROP.
+          The Garbage Collection didn't collect all the garbage...fixed.
+     Version 1.14
+          Unfortunately, after Andre fixed the GC it became obvious that the
+          algorithm was too slow... Fortunately, David Gould found a way to
+          speed it up.
+     Version 1.13
+          Silly bug involving division by zero resolved by Roland Kaufman.
+          Macintoch support from Shmulik Regev.
+          Float parser bug fixed by Alexander Shendi.
+          GC bug from Andru Luvisi.
+     Version 1.12
+          Cis* incorrectly called isalpha() instead of isascii()
+          Added USE_CHAR_CLASSIFIERS, USE_STRING_PORTS.
+     Version 1.11
+          BSDI defines isnumber... changed all similar functions to is_*
+          EXPT now has correct definition. Added FLOOR,CEILING,TRUNCATE
+          and ROUND, courtesy of Bengt Kleberg. Preprocessor symbols now
+          have values 1 or 0, and can be set as compiler defines (proposed
+          by Andy Ganor *months* ago). 'prompt' and 'InitFile' can now be
+          defined during compilation, too.
+     Version 1.10
+          Another bug when file ends with comment!
+          Added DEFINE-MACRO in init.scm, courtesy of Andy Gaynor.
+     Version 1.09
+          Removed bug when READ met EOF. lcm.
+     Version 1.08
+          quotient,remainder and modulo. gcd.
+     Version 1.07
+          '=>' in cond now exists
+          list? now checks for circularity
+          some reader bugs removed
+          Reader is more consistent wrt vectors
+          Quote and Quasiquote work with vectors
+     Version 1.06
+          #! is now skipped
+          generic-assoc bug removed
+          strings are now managed differently, hack.txt is removed
+          various delicate points fixed
+     Version 1.05
+          Support for scripts, *args*, "-1" option.
+          Various R5RS procedures.
+          *sharp-hook*
+          Handles unmatched parentheses.
+          New architecture for procedures.
+     Version 1.04
+          Added missing T_ATOM bits...
+          Added vectors
+          Free-list is sorted by address, since vectors need consecutive cells.
+          (quit <exitcode>) for use with scripts
+     Version 1.03 (26 Aug 1998):
+          Extended .h with useful functions for FFI
+          Library: with-input-* etc.
+          Finished R5RS I/O, added string ports.
+     Version 1.02 (25 Aug 1998):
+          First part of R5RS I/O.
+	

+ 31 - 0
busunit/passdb_slim/tinyscheme1.39/COPYING

@@ -0,0 +1,31 @@
+                         LICENSE TERMS
+
+Copyright (c) 2000, Dimitrios Souflis
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+Neither the name of Dimitrios Souflis nor the names of the
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR 
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 449 - 0
busunit/passdb_slim/tinyscheme1.39/Manual.txt

@@ -0,0 +1,449 @@
+
+
+                       TinySCHEME Version 1.38
+
+                    "Safe if used as prescribed"
+                    -- Philip K. Dick, "Ubik"
+
+This software is open source, covered by a BSD-style license.
+Please read accompanying file COPYING.                                   
+-------------------------------------------------------------------------------
+
+     This Scheme interpreter is based on MiniSCHEME version 0.85k4
+     (see miniscm.tar.gz in the Scheme Repository)
+     Original credits in file MiniSCHEMETribute.txt.
+
+     D. Souflis (dsouflis@acm.org)
+
+-------------------------------------------------------------------------------
+     What is TinyScheme?
+     -------------------
+
+     TinyScheme is a lightweight Scheme interpreter that implements as large
+     a subset of R5RS as was possible without getting very large and
+     complicated. It is meant to be used as an embedded scripting interpreter
+     for other programs. As such, it does not offer IDEs or extensive toolkits
+     although it does sport a small top-level loop, included conditionally.
+     A lot of functionality in TinyScheme is included conditionally, to allow
+     developers freedom in balancing features and footprint.
+
+     As an embedded interpreter, it allows multiple interpreter states to
+     coexist in the same program, without any interference between them.
+     Programmatically, foreign functions in C can be added and values
+     can be defined in the Scheme environment. Being a quite small program,
+     it is easy to comprehend, get to grips with, and use. 
+
+     Known bugs
+     ----------
+
+     TinyScheme is known to misbehave when memory is exhausted.
+
+
+     Things that keep missing, or that need fixing
+     ---------------------------------------------
+
+     There are no hygienic macros. No rational or
+     complex numbers. No unwind-protect and call-with-values.
+
+     Maybe (a subset of) SLIB will work with TinySCHEME...
+
+     Decent debugging facilities are missing. Only tracing is supported 
+     natively.
+
+
+     Scheme Reference
+     ----------------
+
+     If something seems to be missing, please refer to the code and
+     "init.scm", since some are library functions.  Refer to the MiniSCHEME
+     readme as a last resort.
+
+          Environments
+     (interaction-environment)
+     See R5RS. In TinySCHEME, immutable list of association lists.
+
+     (current-environment)
+     The environment in effect at the time of the call. An example of its
+     use and its utility can be found in the sample code that implements
+     packages in "init.scm":
+
+          (macro (package form)
+               `(apply (lambda ()
+                         ,@(cdr form)
+                         (current-environment))))
+
+     The environment containing the (local) definitions inside the closure
+     is returned as an immutable value.
+
+     (defined? <symbol>) (defined? <symbol> <environment>)
+     Checks whether the given symbol is defined in the current (or given)
+     environment.
+
+          Symbols
+     (gensym)
+     Returns a new interned symbol each time. Will probably move to the
+     library when string->symbol is implemented.
+
+          Directives
+     (gc)
+     Performs garbage collection immediatelly.
+
+     (gcverbose) (gcverbose <bool>)
+     The argument (defaulting to #t) controls whether GC produces
+     visible outcome.
+
+     (quit) (quit <num>)
+     Stops the interpreter and sets the 'retcode' internal field (defaults
+     to 0). When standalone, 'retcode' is returned as exit code to the OS.
+
+     (tracing <num>)
+     1, turns on tracing. 0 turns it off. (Only when USE_TRACING is 1).
+
+          Mathematical functions
+     Since rationals and complexes are absent, the respective functions
+     are also missing.
+     Supported: exp, log, sin, cos, tan, asin, acos, atan, floor, ceiling,
+     trunc, round and also sqrt and expt when USE_MATH=1.
+     Number-theoretical quotient, remainder and modulo, gcd, lcm.
+     Library: exact?, inexact?, odd?, even?, zero?, positive?, negative?,
+     exact->inexact. inexact->exact is a core function.
+
+          Type predicates
+     boolean?,eof-object?,symbol?,number?,string?,integer?,real?,list?,null?,
+     char?,port?,input-port?,output-port?,procedure?,pair?,environment?',
+     vector?. Also closure?, macro?.
+
+          Types
+     Types supported:
+
+          Numbers (integers and reals)
+          Symbols
+          Pairs
+          Strings
+          Characters
+          Ports
+          Eof object
+          Environments
+          Vectors
+
+          Literals
+     String literals can contain escaped quotes \" as usual, but also
+     \n, \r, \t, \xDD (hex representations) and \DDD (octal representations).
+     Note also that it is possible to include literal newlines in string
+     literals, e.g.
+
+          (define s "String with newline here
+          and here
+          that can function like a HERE-string")
+
+     Character literals contain #\space and #\newline and are supplemented
+     with #\return and #\tab, with obvious meanings. Hex character
+     representations are allowed (e.g. #\x20 is #\space).
+     When USE_ASCII_NAMES is defined, various control characters can be
+     refered to by their ASCII name.
+     0	     #\nul	       17       #\dc1
+     1	     #\soh             18       #\dc2
+     2	     #\stx             19       #\dc3
+     3	     #\etx             20       #\dc4
+     4	     #\eot             21       #\nak
+     5	     #\enq             22       #\syn
+     6	     #\ack             23       #\etv
+     7	     #\bel             24       #\can
+     8	     #\bs              25       #\em
+     9	     #\ht              26       #\sub
+     10	     #\lf              27       #\esc
+     11	     #\vt              28       #\fs
+     12	     #\ff              29       #\gs
+     13	     #\cr              30       #\rs
+     14	     #\so              31       #\us
+     15	     #\si
+     16	     #\dle             127      #\del 		
+     
+     Numeric literals support #x #o #b and #d. Flonums are currently read only
+     in decimal notation. Full grammar will be supported soon.
+
+          Quote, quasiquote etc.
+     As usual.
+
+          Immutable values
+     Immutable pairs cannot be modified by set-car! and set-cdr!.
+     Immutable strings cannot be modified via string-set!
+
+          I/O
+     As per R5RS, plus String Ports (see below).
+     current-input-port, current-output-port,
+     close-input-port, close-output-port, input-port?, output-port?,
+     open-input-file, open-output-file.
+     read, write, display, newline, write-char, read-char, peek-char.
+     char-ready? returns #t only for string ports, because there is no
+     portable way in stdio to determine if a character is available.
+     Also open-input-output-file, set-input-port, set-output-port (not R5RS)
+     Library: call-with-input-file, call-with-output-file,
+     with-input-from-file, with-output-from-file and
+     with-input-output-from-to-files, close-port and input-output-port? 
+     (not R5RS).
+     String Ports: open-input-string, open-output-string,
+     open-input-output-string. Strings can be used with I/O routines.
+
+          Vectors
+     make-vector, vector, vector-length, vector-ref, vector-set!, list->vector,
+     vector-fill!, vector->list, vector-equal? (auxiliary function, not R5RS)
+
+          Strings
+     string, make-string, list->string, string-length, string-ref, string-set!,
+     substring, string->list, string-fill!, string-append, string-copy.
+     string=?, string<?, string>?, string>?, string<=?, string>=?.
+     (No string-ci*? yet). string->number, number->string. Also atom->string,
+     string->atom (not R5RS).
+
+          Symbols
+     symbol->string, string->symbol
+
+          Characters
+     integer->char, char->integer.
+     char=?, char<?, char>?, char<=?, char>=?.
+     (No char-ci*?)
+
+          Pairs & Lists
+     cons, car, cdr, list, length, map, for-each, foldr, list-tail,
+     list-ref, last-pair, reverse, append.
+     Also member, memq, memv, based on generic-member, assoc, assq, assv
+     based on generic-assoc.
+
+          Streams
+     head, tail, cons-stream
+
+          Control features
+     Apart from procedure?, also macro? and closure?
+     map, for-each, force, delay, call-with-current-continuation (or call/cc),
+     eval, apply. 'Forcing' a value that is not a promise produces the value.
+     There is no call-with-values, values, nor dynamic-wind. Dynamic-wind in
+     the presence of continuations would require support from the abstract
+     machine itself.
+
+          Property lists
+     TinyScheme inherited from MiniScheme property lists for symbols.
+     put, get.
+
+          Dynamically-loaded extensions
+     (load-extension <filename without extension>)
+     Loads a DLL declaring foreign procedures.          
+     
+          Esoteric procedures
+     (oblist)
+     Returns the oblist, an immutable list of all the symbols.
+
+     (macro-expand <form>)
+     Returns the expanded form of the macro call denoted by the argument
+
+     (define-with-return (<procname> <args>...) <body>)
+     Like plain 'define', but makes the continuation available as 'return'
+     inside the procedure. Handy for imperative programs.
+
+     (new-segment <num>)
+     Allocates more memory segments.
+
+     defined?
+     See "Environments"
+
+     (get-closure-code <closure>)
+     Gets the code as scheme data.
+
+     (make-closure <code> <environment>)
+     Makes a new closure in the given environment.
+
+          Obsolete procedures
+     (print-width <object>)          
+     
+     Programmer's Reference
+     ----------------------
+
+     The interpreter state is initialized with "scheme_init".
+     Custom memory allocation routines can be installed with an alternate
+     initialization function: "scheme_init_custom_alloc". 
+     Files can be loaded with "scheme_load_file". Strings containing Scheme
+     code can be loaded with "scheme_load_string". It is a good idea to 
+     "scheme_load" init.scm before anything else.
+
+     External data for keeping external state (of use to foreign functions)
+     can be installed with "scheme_set_external_data".
+     Foreign functions are installed with "assign_foreign". Additional 
+     definitions can be added to the interpreter state, with "scheme_define" 
+     (this is the way HTTP header data and HTML form data are passed to the 
+     Scheme script in the Altera SQL Server). If you wish to define the
+     foreign function in a specific environment (to enhance modularity),
+     use "assign_foreign_env".
+
+     The procedure "scheme_apply0" has been added with persistent scripts in
+     mind. Persistent scripts are loaded once, and every time they are needed
+     to produce HTTP output, appropriate data are passed through global
+     definitions and function "main" is called to do the job. One could
+     add easily "scheme_apply1" etc.
+
+     The interpreter state should be deinitialized with "scheme_deinit".
+
+     DLLs containing foreign functions should define a function named
+     init_<base-name>. E.g. foo.dll should define init_foo, and bar.so
+     should define init_bar. This function should assign_foreign any foreign
+     function contained in the DLL.
+
+     The first dynamically loaded extension available for TinyScheme is
+     a regular expression library. Although it's by no means an
+     established standard, this library is supposed to be installed in
+     a directory mirroring its name under the TinyScheme location.
+
+     
+     Foreign Functions
+     -----------------
+
+     The user can add foreign functions in C. For example, a function
+     that squares its argument:
+
+          pointer square(scheme *sc, pointer args) {
+           if(args!=sc->NIL) {
+               if(sc->isnumber(sc->pair_car(args))) {
+                    double v=sc->rvalue(sc->pair_car(args));
+                    return sc->mk_real(sc,v*v);
+               }
+           }
+           return sc->NIL;
+          }
+
+   Foreign functions are now defined as closures: 
+
+   sc->interface->scheme_define( 
+        sc, 
+        sc->global_env, 
+        sc->interface->mk_symbol(sc,"square"), 
+        sc->interface->mk_foreign_func(sc, square)); 
+
+
+     Foreign functions can use the external data in the "scheme" struct
+     to implement any kind of external state.
+
+     External data are set with the following function:
+          void scheme_set_external_data(scheme *sc, void *p);
+
+     As of v.1.17, the canonical way for a foreign function in a DLL to
+     manipulate Scheme data is using the function pointers in sc->interface.
+
+     Standalone
+     ----------
+
+     Usage: tinyscheme -? 
+     or:    tinyscheme [<file1> <file2> ...] 
+     followed by
+	       -1 <file> [<arg1> <arg2> ...]
+	       -c <Scheme commands> [<arg1> <arg2> ...]
+     assuming that the executable is named tinyscheme.
+
+     Use - in the place of a filename to denote stdin.
+     The -1 flag is meant for #! usage in shell scripts. If you specify
+          #! /somewhere/tinyscheme -1
+     then tinyscheme will be called to process the file. For example, the
+     following script echoes the Scheme list of its arguments.
+
+	       #! /somewhere/tinyscheme -1
+	       (display *args*)
+
+     The -c flag permits execution of arbitrary Scheme code.
+
+
+     Error Handling
+     --------------
+
+     Errors are recovered from without damage. The user can install his
+     own handler for system errors, by defining *error-hook*. Defining
+     to '() gives the default behavior, which is equivalent to "error".
+     USE_ERROR_HOOK must be defined.
+
+     A simple exception handling mechanism can be found in "init.scm".
+     A new syntactic form is introduced:
+
+          (catch <expr returned exceptionally>
+               <expr1> <expr2> ... <exprN>)
+
+     "Catch" establishes a scope spanning multiple call-frames
+     until another "catch" is encountered.
+
+     Exceptions are thrown with:
+
+          (throw "message")
+
+     If used outside a (catch ...), reverts to (error "message").
+
+     Example of use:
+
+          (define (foo x) (write x) (newline) (/ x 0))
+
+          (catch (begin (display "Error!\n") 0)
+               (write "Before foo ... ")
+               (foo 5)
+               (write "After foo"))
+
+     The exception mechanism can be used even by system errors, by
+
+          (define *error-hook* throw)
+
+     which makes use of the error hook described above.
+
+     If necessary, the user can devise his own exception mechanism with
+     tagged exceptions etc.
+
+
+     Reader extensions
+     -----------------
+
+     When encountering an unknown character after '#', the user-specified
+     procedure *sharp-hook* (if any), is called to read the expression.
+     This can be used to extend the reader to handle user-defined constants
+     or whatever. It should be a procedure without arguments, reading from
+     the current input port (which will be the load-port).
+
+
+     Colon Qualifiers - Packages
+     ---------------------------
+
+     When USE_COLON_HOOK=1:
+     The lexer now recognizes the construction <qualifier>::<symbol> and
+     transforms it in the following manner (T is the transformation function):
+
+          T(<qualifier>::<symbol>) = (*colon-hook* 'T(<symbol>) <qualifier>)
+
+     where <qualifier> is a symbol not containing any double-colons.
+
+     As the definition is recursive, qualifiers can be nested.
+     The user can define his own *colon-hook*, to handle qualified names.
+     By default, "init.scm" defines *colon-hook* as EVAL. Consequently,
+     the qualifier must denote a Scheme environment, such as one returned
+     by (interaction-environment). "Init.scm" defines a new syntantic form,
+     PACKAGE, as a simple example. It is used like this:
+
+          (define toto
+               (package
+                    (define foo 1)
+                    (define bar +)))
+
+          foo                                     ==>  Error, "foo" undefined
+          (eval 'foo)                             ==>  Error, "foo" undefined
+          (eval 'foo toto)                        ==>  1
+          toto::foo                               ==>  1
+          ((eval 'bar toto) 2 (eval 'foo toto))   ==>  3
+          (toto::bar 2 toto::foo)                 ==>  3
+          (eval (bar 2 foo) toto)                 ==>  3
+
+     If the user installs another package infrastructure, he must define
+     a new 'package' procedure or macro to retain compatibility with supplied
+     code.
+
+     Note: Older versions used ':' as a qualifier. Unfortunately, the use
+     of ':' as a pseudo-qualifier in existing code (i.e. SLIB) essentially
+     precludes its use as a real qualifier.
+
+
+
+
+
+
+
+

+ 88 - 0
busunit/passdb_slim/tinyscheme1.39/MiniSCHEMETribute.txt

@@ -0,0 +1,88 @@
+     TinyScheme would not exist if it wasn't for MiniScheme. I had just
+     written the HTTP server for Ovrimos SQL Server, and I was lamenting the
+     lack of a scripting language. Server-side Javascript would have been the
+     preferred solution, had there been a Javascript interpreter I could
+     lay my hands on. But there weren't. Perl would have been another solution,
+     but it was probably ten times bigger that the program it was supposed to
+     be embedded in. There would also be thorny licencing issues. 
+     
+     So, the obvious thing to do was find a trully small interpreter. Forth
+     was a language I had once quasi-implemented, but the difficulty of
+     handling dynamic data and the weirdness of the language put me off. I then
+     looked around for a LISP interpreter, the next thing I knew was easy to
+     implement. Alas, the LeLisp I knew from my days in UPMC (Universite Pierre
+     et Marie Curie) had given way to Common Lisp, a megalith of a language!
+     Then my search lead me to Scheme, a language I knew was very orthogonal
+     and clean. When I found Mini-Scheme, a single C file of some 2400 loc, I 
+     fell in love with it! What if it lacked floating-point numbers and 
+     strings! The rest, as they say, is history.
+     
+     Below  are the original credits. Don't email Akira KIDA, the address has
+     changed.
+     
+     ---------- Mini-Scheme Interpreter Version 0.85 ----------
+
+                coded by Atsushi Moriwaki (11/5/1989)
+
+            E-MAIL :  moriwaki@kurims.kurims.kyoto-u.ac.jp
+
+               THIS SOFTWARE IS IN THE PUBLIC DOMAIN
+               ------------------------------------
+ This software is completely free to copy, modify and/or re-distribute.
+ But I would appreciate it if you left my name on the code as the author.
+
+  This version has been modified by R.C. Secrist.
+
+  Mini-Scheme is now maintained by Akira KIDA.
+
+  This is a revised and modified version by Akira KIDA.
+   current version is 0.85k4 (15 May 1994)
+
+  Please send suggestions, bug reports and/or requests to:
+        <SDI00379@niftyserve.or.jp>
+
+
+     Features compared to MiniSCHEME
+     -------------------------------
+
+     All code is now reentrant. Interpreter state is held in a 'scheme'
+     struct, and many interpreters can coexist in the same program, possibly
+     in different threads. The user can specify user-defined memory allocation
+     primitives. (see "Programmer's Reference")
+
+     The reader is more consistent.
+
+     Strings, characters and flonums are supported. (see "Types")
+
+     Files being loaded can be nested up to some depth.
+
+     R5RS I/O is there, plus String Ports. (see "Scheme Reference","I/O")
+
+     Vectors exist.
+
+     As a standalone application, it supports command-line arguments.
+     (see "Standalone")
+
+     Running out of memory is now handled.
+
+     The user can add foreign functions in C. (see "Foreign Functions")
+
+     The code has been changed slightly, core functions have been moved
+     to the library, behavior has been aligned with R5RS etc.
+
+     Support has been added for user-defined error recovery.
+     (see "Error Handling")
+
+     Support has been added for modular programming.
+     (see "Colon Qualifiers - Packages")
+
+     To enable this, EVAL has changed internally, and can
+     now take two arguments, as per R5RS. Environments are supported.
+     (see "Colon Qualifiers - Packages")
+
+     Promises are now evaluated once only.
+
+     (macro (foo form) ...) is now equivalent to (macro foo (lambda(form) ...))
+
+     The reader can be extended using new #-expressions
+     (see "Reader extensions")

+ 145 - 0
busunit/passdb_slim/tinyscheme1.39/dynload.c

@@ -0,0 +1,145 @@
+/* dynload.c Dynamic Loader for TinyScheme */
+/* Original Copyright (c) 1999 Alexander Shendi     */
+/* Modifications for NT and dl_* interface, scm_load_ext: D. Souflis */
+/* Refurbished by Stephen Gildea */
+
+#define _SCHEME_SOURCE
+#include "dynload.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef MAXPATHLEN
+# define MAXPATHLEN 1024
+#endif
+
+static void make_filename(const char *name, char *filename); 
+static void make_init_fn(const char *name, char *init_fn); 
+
+#ifdef _WIN32
+# include <windows.h>
+#else
+typedef void *HMODULE;
+typedef void (*FARPROC)();
+#define SUN_DL
+#include <dlfcn.h>
+#endif
+
+#ifdef _WIN32
+
+#define PREFIX ""
+#define SUFFIX ".dll"
+
+ static void display_w32_error_msg(const char *additional_message) 
+ { 
+   LPVOID msg_buf; 
+ 
+   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, 
+		 NULL, GetLastError(), 0, 
+		 (LPTSTR)&msg_buf, 0, NULL); 
+   fprintf(stderr, "scheme load-extension: %s: %s", additional_message, msg_buf); 
+   LocalFree(msg_buf); 
+ } 
+
+static HMODULE dl_attach(const char *module) {
+  HMODULE dll = LoadLibrary(module);
+  if (!dll) display_w32_error_msg(module); 
+  return dll; 
+}
+
+static FARPROC dl_proc(HMODULE mo, const char *proc) {
+  FARPROC procedure = GetProcAddress(mo,proc); 
+  if (!procedure) display_w32_error_msg(proc); 
+  return procedure; 
+}
+
+static void dl_detach(HMODULE mo) {
+ (void)FreeLibrary(mo);
+}
+
+#elif defined(SUN_DL)
+
+#include <dlfcn.h>
+
+#define PREFIX "lib"
+#define SUFFIX ".so"
+
+static HMODULE dl_attach(const char *module) {
+  HMODULE so=dlopen(module,RTLD_LAZY);
+  if(!so) {
+    fprintf(stderr, "Error loading scheme extension \"%s\": %s\n", module, dlerror()); 
+  }
+  return so;
+}
+
+static FARPROC dl_proc(HMODULE mo, const char *proc) {
+  const char *errmsg;
+  FARPROC fp=(FARPROC)dlsym(mo,proc);
+  if ((errmsg = dlerror()) == 0) {
+    return fp;
+  }
+  fprintf(stderr, "Error initializing scheme module \"%s\": %s\n", proc, errmsg);
+ return 0;
+}
+
+static void dl_detach(HMODULE mo) {
+ (void)dlclose(mo);
+}
+#endif
+
+pointer scm_load_ext(scheme *sc, pointer args)
+{
+   pointer first_arg;
+   pointer retval;
+   char filename[MAXPATHLEN], init_fn[MAXPATHLEN+6];
+   char *name;
+   HMODULE dll_handle;
+   void (*module_init)(scheme *sc);
+   
+   if ((args != sc->NIL) && is_string((first_arg = pair_car(args)))) {
+      name = string_value(first_arg);
+      make_filename(name,filename);     
+      make_init_fn(name,init_fn);     
+      dll_handle = dl_attach(filename);
+      if (dll_handle == 0) {
+         retval = sc -> F;
+      }
+      else {
+         module_init = (void(*)(scheme *))dl_proc(dll_handle, init_fn);
+         if (module_init != 0) {
+            (*module_init)(sc);
+            retval = sc -> T;
+         }
+         else {
+            retval = sc->F;
+         }
+      }
+   }
+   else {
+      retval = sc -> F;
+   }
+   
+  return(retval);
+}
+
+static void make_filename(const char *name, char *filename) {
+ strcpy(filename,name);
+ strcat(filename,SUFFIX);
+}         
+
+static void make_init_fn(const char *name, char *init_fn) {
+ const char *p=strrchr(name,'/');
+ if(p==0) {
+     p=name;
+ } else {
+     p++;
+ }
+ strcpy(init_fn,"init_");
+ strcat(init_fn,p);
+}
+
+
+
+
+
+

+ 12 - 0
busunit/passdb_slim/tinyscheme1.39/dynload.h

@@ -0,0 +1,12 @@
+/* dynload.h */
+/* Original Copyright (c) 1999 Alexander Shendi     */
+/* Modifications for NT and dl_* interface: D. Souflis */
+
+#ifndef DYNLOAD_H
+#define DYNLOAD_H
+
+#include "scheme-private.h"
+
+SCHEME_EXPORT pointer scm_load_ext(scheme *sc, pointer arglist);
+
+#endif

+ 236 - 0
busunit/passdb_slim/tinyscheme1.39/hack.txt

@@ -0,0 +1,236 @@
+
+                              How to hack TinyScheme
+                              ----------------------
+
+     TinyScheme is easy to learn and modify. It is structured like a
+     meta-interpreter, only it is written in C. All data are Scheme
+     objects, which facilitates both understanding/modifying the
+     code and reifying the interpreter workings.
+
+     In place of a dry description, we will pace through the addition
+     of a useful new datatype: garbage-collected memory blocks.
+     The interface will be:
+
+          (make-block <n> [<fill>]) makes a new block of the specified size
+               optionally filling it with a specified byte
+          (block? <obj>)
+          (block-length <block>)
+          (block-ref <block> <index>) retrieves byte at location
+          (block-set! <block> <index> <byte>) modifies byte at location
+     
+     In the sequel, lines that begin with '>' denote lines to add to the
+     code. Lines that begin with '|' are just citations of existing code.
+
+     First of all, we need to assign a typeid to our new type. Typeids
+     in TinyScheme are small integers declared in an enum, very close to
+     the top; it begins with T_STRING. Add a new one at the end, say
+     T_MEMBLOCK. There can be at most 31 types, but you don't have to
+     worry about that limit yet.
+
+|    ...
+|      T_PORT,
+|      T_VECTOR,          /* remember to add a comma to the preceding item! */
+|      T_MEMBLOCK
+}     };
+
+     Then, some helper macros would be useful. Go to where isstring() and
+     the rest are defined and define:
+
+>    int ismemblock(pointer p)      { return (type(p)==T_MEMBLOCK); }
+
+     This actually is a function, because it is meant to be exported by
+     scheme.h. If no foreign function will ever manipulate a memory block,
+     you can instead define it as a macro
+
+>     #define ismemblock(p) (type(p)==T_MEMBLOCK)
+
+     Then we make space for the new type in the main data structure:
+     struct cell. As it happens, the _string part of the union _object
+     (that is used to hold character strings) has two fields that suit us:
+
+|         struct {
+|              char   *_svalue;
+|              int   _keynum;
+|         } _string;
+
+     We can use _svalue to hold the actual pointer and _keynum to hold its
+     length. If we couln't reuse existing fields, we could always add other
+     alternatives in union _object.
+
+     We then procede to write the function that actually makes a new block.
+     For conformance reasons, we name it mk_memblock
+
+>     static pointer mk_memblock(scheme *sc, int len, char fill) {
+>          pointer x;
+>          char *p=(char*)sc->malloc(len);
+>
+>          if(p==0) {
+>               return sc->NIL;
+>          }
+>          x = get_cell(sc, sc->NIL, sc->NIL);
+>
+>          typeflag(x) = T_MEMBLOCK|T_ATOM;
+>          strvalue(x)=p;
+>          keynum(x)=len;
+>          memset(p,fill,len);
+>          return (x);
+>     }
+
+     The memory used by the MEMBLOCK will have to be freed when the cell
+     is reclaimed during garbage collection. There is a placeholder for
+     that staff, function finalize_cell(), currently handling strings only.
+
+|     static void finalize_cell(scheme *sc, pointer a) {
+|          if(isstring(a)) {
+|               sc->free(strvalue(a));
+|          }
+>          else if(ismemblock(a)) {
+>               sc->free(strvalue(x));
+>          }
+|     }
+
+     There are no MEMBLOCK literals, so we don't concern ourselfs with
+     the READER part (yet!). We must cater to the PRINTER, though. We
+     add one case more in printatom().
+
+|     } else if (iscontinuation(l)) {
+|          p = "#<CONTINUATION>";
+>     } else if (ismemblock(l)) {
+>          p = "#<MEMORY BLOCK>";
+|     }
+
+     Whenever a MEMBLOCK is displayed, it will look like that.
+     Now, we must add the interface functions: constructor, predicate,
+     accessor, modifier. We must in fact create new op-codes for the virtual
+     machine underlying TinyScheme. There is a huge enum with OP_XXX values.
+     That's where the op-codes are declared. For reasons of cohesion, we add
+     the new op-codes right after those for vectors:
+
+|   OP_VECSET,
+>   OP_MKBLOCK,
+>   OP_MEMBLOCKP,
+>   OP_BLOCKLEN,
+>   OP_BLOCKREF,
+>   OP_BLOCKSET,
+|   OP_NOT,
+
+     We add the predicate along the other predicates:
+
+|   OP_VECTORP,
+>   OP_BLOCKP,
+|   OP_EQ,
+
+     Op-codes are really just tags for a huge C switch, only this switch
+     is broke up in a number of different opexe_X functions. The
+     correspondence is made in table "dispatch_table". There, we assign
+     the new op-codes to opexe_2, where the equivalent ones for vectors
+     are situated. We also assign a name for them, and specify the minimum
+     and maximum arity. INF_ARG as a maximum arity means "unlimited".
+
+|     {opexe_2, "vector-set!", 3, 3},    /* OP_VECSET */
+>     {opexe_2, "make-block", 1, 2},     /* OP_MKBLOCK */
+>     {opexe_2, "block-length", 1, 1},   /* OP_BLOCKLEN */
+>     {opexe_2, "block-ref", 2, 2},      /* OP_BLOCKREF */
+>     {opexe_2, "block-set!",3 ,3},      /* OP_BLOCKSET */
+
+     The predicate goes with the other predicates, in opexe_3.
+
+|     {opexe_3, "vector?", 1, 1},  /* OP_VECTORP, */
+>     {opexe_3, "block?", 1, 1},   /* OP_BLOCKP, */
+
+     All that remains is to write the actual processing in opexe_2, right
+     after OP_VECSET.
+
+>     case OP_MKBLOCK: { /* make-block */
+>          int fill=0;
+>          int len;
+>
+>          if(!isnumber(car(sc->args))) {
+>               Error_1(sc,"make-block: not a number:",car(sc->args));
+>          }
+>          len=ivalue(car(sc->args));
+>          if(len<=0) {
+>               Error_1(sc,"make-block: not positive:",car(sc->args));
+>          }
+>
+>          if(cdr(sc->args)!=sc->NIL) {
+>               if(!isnumber(cadr(sc->args)) || ivalue(cadr(sc->args))<0) {
+>                    Error_1(sc,"make-block: not a positive number:",cadr(sc->args));
+>               }
+>               fill=charvalue(cadr(sc->args))%255;
+>          }
+>          s_return(sc,mk_memblock(sc,len,(char)fill));
+>     }
+>
+>     case OP_BLOCKLEN:  /* block-length */
+>          if(!ismemblock(car(sc->args))) {
+>               Error_1(sc,"block-length: not a memory block:",car(sc->args));
+>          }
+>          s_return(sc,mk_integer(sc,keynum(car(sc->args))));
+>
+>     case OP_BLOCKREF: { /* block-ref */
+>          char *str;
+>          int index;
+>
+>          if(!ismemblock(car(sc->args))) {
+>               Error_1(sc,"block-ref: not a memory block:",car(sc->args));
+>          }
+>          str=strvalue(car(sc->args));
+>
+>          if(cdr(sc->args)==sc->NIL) {
+>               Error_0(sc,"block-ref: needs two arguments");
+>          }
+>          if(!isnumber(cadr(sc->args))) {
+>               Error_1(sc,"block-ref: not a number:",cadr(sc->args));
+>          }
+>          index=ivalue(cadr(sc->args));
+>
+>          if(index<0 || index>=keynum(car(sc->args))) {
+>               Error_1(sc,"block-ref: out of bounds:",cadr(sc->args));
+>          }
+>
+>          s_return(sc,mk_integer(sc,str[index]));
+>     }
+>
+>     case OP_BLOCKSET: { /* block-set! */
+>          char *str;
+>          int index;
+>          int c;
+>
+>          if(!ismemblock(car(sc->args))) {
+>               Error_1(sc,"block-set!: not a memory block:",car(sc->args));
+>          }
+>          if(isimmutable(car(sc->args))) {
+>               Error_1(sc,"block-set!: unable to alter immutable memory block:",car(sc->args));
+>          }
+>          str=strvalue(car(sc->args));
+>
+>          if(cdr(sc->args)==sc->NIL) {
+>               Error_0(sc,"block-set!: needs three arguments");
+>          }
+>          if(!isnumber(cadr(sc->args))) {
+>               Error_1(sc,"block-set!: not a number:",cadr(sc->args));
+>          }
+>          index=ivalue(cadr(sc->args));
+>          if(index<0 || index>=keynum(car(sc->args))) {
+>               Error_1(sc,"block-set!: out of bounds:",cadr(sc->args));
+>          }
+>
+>          if(cddr(sc->args)==sc->NIL) {
+>               Error_0(sc,"block-set!: needs three arguments");
+>          }
+>          if(!isinteger(caddr(sc->args))) {
+>               Error_1(sc,"block-set!: not an integer:",caddr(sc->args));
+>          }
+>          c=ivalue(caddr(sc->args))%255;
+>
+>          str[index]=(char)c;
+>          s_return(sc,car(sc->args));
+>     }
+
+     Same for the predicate in opexe_3.
+
+|     case OP_VECTORP:     /* vector? */
+|          s_retbool(isvector(car(sc->args)));
+>     case OP_BLOCKP:     /* block? */
+>          s_retbool(ismemblock(car(sc->args)));

+ 576 - 0
busunit/passdb_slim/tinyscheme1.39/init.scm

@@ -0,0 +1,576 @@
+;    Initialization file for TinySCHEME 1.39
+
+; Per R5RS, up to four deep compositions should be defined
+(define (caar x) (car (car x)))
+(define (cadr x) (car (cdr x)))
+(define (cdar x) (cdr (car x)))
+(define (cddr x) (cdr (cdr x)))
+(define (caaar x) (car (car (car x))))
+(define (caadr x) (car (car (cdr x))))
+(define (cadar x) (car (cdr (car x))))
+(define (caddr x) (car (cdr (cdr x))))
+(define (cdaar x) (cdr (car (car x))))
+(define (cdadr x) (cdr (car (cdr x))))
+(define (cddar x) (cdr (cdr (car x))))
+(define (cdddr x) (cdr (cdr (cdr x))))
+(define (caaaar x) (car (car (car (car x)))))
+(define (caaadr x) (car (car (car (cdr x)))))
+(define (caadar x) (car (car (cdr (car x)))))
+(define (caaddr x) (car (car (cdr (cdr x)))))
+(define (cadaar x) (car (cdr (car (car x)))))
+(define (cadadr x) (car (cdr (car (cdr x)))))
+(define (caddar x) (car (cdr (cdr (car x)))))
+(define (cadddr x) (car (cdr (cdr (cdr x)))))
+(define (cdaaar x) (cdr (car (car (car x)))))
+(define (cdaadr x) (cdr (car (car (cdr x)))))
+(define (cdadar x) (cdr (car (cdr (car x)))))
+(define (cdaddr x) (cdr (car (cdr (cdr x)))))
+(define (cddaar x) (cdr (cdr (car (car x)))))
+(define (cddadr x) (cdr (cdr (car (cdr x)))))
+(define (cdddar x) (cdr (cdr (cdr (car x)))))
+(define (cddddr x) (cdr (cdr (cdr (cdr x)))))
+
+(macro (unless form)
+     `(if (not ,(cadr form)) (begin ,@(cddr form))))
+
+(macro (when form)
+     `(if ,(cadr form) (begin ,@(cddr form))))
+
+; DEFINE-MACRO Contributed by Andy Gaynor
+(macro (define-macro dform)
+  (if (symbol? (cadr dform))
+    `(macro ,@(cdr dform))
+    (let ((form (gensym)))
+      `(macro (,(caadr dform) ,form)
+         (apply (lambda ,(cdadr dform) ,@(cddr dform)) (cdr ,form))))))
+
+; Utilities for math. Notice that inexact->exact is primitive,
+; but exact->inexact is not.
+(define exact? integer?)
+(define (inexact? x) (and (real? x) (not (integer? x))))
+(define (even? n) (= (remainder n 2) 0))
+(define (odd? n) (not (= (remainder n 2) 0)))
+(define (zero? n) (= n 0))
+(define (positive? n) (> n 0))
+(define (negative? n) (< n 0))
+(define complex? number?)
+(define rational? real?)
+(define (abs n) (if (>= n 0) n (- n)))
+(define (exact->inexact n) (* n 1.0))
+(define (<> n1 n2) (not (= n1 n2)))
+(define (max . lst)
+     (foldr (lambda (a b) (if (> a b) a b)) (car lst) (cdr lst)))
+(define (min . lst)
+     (foldr (lambda (a b) (if (< a b) a b)) (car lst) (cdr lst)))
+(define (succ x) (+ x 1))
+(define (pred x) (- x 1))
+(define (gcd a b)
+  (let ((aa (abs a))
+	(bb (abs b)))
+     (if (= bb 0)
+          aa
+          (gcd bb (remainder aa bb)))))
+(define (lcm a b)
+     (if (or (= a 0) (= b 0))
+          0
+          (abs (* (quotient a (gcd a b)) b))))
+
+(define call/cc call-with-current-continuation)
+
+(define (string . charlist)
+     (list->string charlist))
+
+(define (list->string charlist)
+     (let* ((len (length charlist))
+            (newstr (make-string len))
+            (fill-string!
+               (lambda (str i len charlist)
+                    (if (= i len)
+                         str
+                         (begin (string-set! str i (car charlist))
+                         (fill-string! str (+ i 1) len (cdr charlist)))))))
+          (fill-string! newstr 0 len charlist)))
+
+(define (string-fill! s e)
+     (let ((n (string-length s)))
+          (let loop ((i 0))
+               (if (= i n)
+                    s
+                    (begin (string-set! s i e) (loop (succ i)))))))
+
+(define (string->list s)
+     (let loop ((n (pred (string-length s))) (l '()))
+          (if (= n -1)
+               l
+               (loop (pred n) (cons (string-ref s n) l)))))
+
+(define (string-copy str)
+     (string-append str))
+
+(define (string->anyatom str pred)
+     (let* ((a (string->atom str)))
+       (if (pred a) a
+	   (error "string->xxx: not a xxx" a))))
+
+(define (string->number str) (string->anyatom str number?))
+
+(define (anyatom->string n pred)
+  (if (pred n)
+      (atom->string n)
+      (error "xxx->string: not a xxx" n)))
+  
+
+(define (number->string n) (anyatom->string n number?))    
+
+(define (char-cmp? cmp a b)
+     (cmp (char->integer a) (char->integer b)))
+(define (char-ci-cmp? cmp a b)
+     (cmp (char->integer (char-downcase a)) (char->integer (char-downcase b))))
+
+(define (char=? a b) (char-cmp? = a b))
+(define (char<? a b) (char-cmp? < a b))
+(define (char>? a b) (char-cmp? > a b))
+(define (char<=? a b) (char-cmp? <= a b))
+(define (char>=? a b) (char-cmp? >= a b))
+
+(define (char-ci=? a b) (char-ci-cmp? = a b))
+(define (char-ci<? a b) (char-ci-cmp? < a b))
+(define (char-ci>? a b) (char-ci-cmp? > a b))
+(define (char-ci<=? a b) (char-ci-cmp? <= a b))
+(define (char-ci>=? a b) (char-ci-cmp? >= a b))
+
+; Note the trick of returning (cmp x y)
+(define (string-cmp? chcmp cmp a b)
+     (let ((na (string-length a)) (nb (string-length b)))
+          (let loop ((i 0))
+               (cond
+                    ((= i na)
+                         (if (= i nb) (cmp 0 0) (cmp 0 1)))
+                    ((= i nb)
+                         (cmp 1 0))
+                    ((chcmp = (string-ref a i) (string-ref b i))
+                         (loop (succ i)))
+                    (else
+                         (chcmp cmp (string-ref a i) (string-ref b i)))))))
+
+
+(define (string=? a b) (string-cmp? char-cmp? = a b))
+(define (string<? a b) (string-cmp? char-cmp? < a b))
+(define (string>? a b) (string-cmp? char-cmp? > a b))
+(define (string<=? a b) (string-cmp? char-cmp? <= a b))
+(define (string>=? a b) (string-cmp? char-cmp? >= a b))
+
+(define (string-ci=? a b) (string-cmp? char-ci-cmp? = a b))
+(define (string-ci<? a b) (string-cmp? char-ci-cmp? < a b))
+(define (string-ci>? a b) (string-cmp? char-ci-cmp? > a b))
+(define (string-ci<=? a b) (string-cmp? char-ci-cmp? <= a b))
+(define (string-ci>=? a b) (string-cmp? char-ci-cmp? >= a b))
+
+(define (list . x) x)
+
+(define (foldr f x lst)
+     (if (null? lst)
+          x
+          (foldr f (f x (car lst)) (cdr lst))))
+
+(define (unzip1-with-cdr . lists)
+  (unzip1-with-cdr-iterative lists '() '()))
+
+(define (unzip1-with-cdr-iterative lists cars cdrs)
+  (if (null? lists)
+      (cons cars cdrs)
+      (let ((car1 (caar lists))
+	    (cdr1 (cdar lists)))
+	(unzip1-with-cdr-iterative 
+	 (cdr lists) 
+	 (append cars (list car1))
+	 (append cdrs (list cdr1))))))
+
+(define (map proc . lists)
+  (if (null? lists)
+      (apply proc)
+      (if (null? (car lists))
+	  '()
+	  (let* ((unz (apply unzip1-with-cdr lists))
+		 (cars (car unz))
+		 (cdrs (cdr unz)))
+	    (cons (apply proc cars) (apply map (cons proc cdrs)))))))
+
+(define (for-each proc . lists)
+  (if (null? lists)
+      (apply proc)
+      (if (null? (car lists))
+	  #t
+	  (let* ((unz (apply unzip1-with-cdr lists))
+		 (cars (car unz))
+		 (cdrs (cdr unz)))
+	    (apply proc cars) (apply map (cons proc cdrs))))))
+
+(define (list-tail x k)
+    (if (zero? k)
+        x
+        (list-tail (cdr x) (- k 1))))
+
+(define (list-ref x k)
+    (car (list-tail x k)))
+
+(define (last-pair x)
+    (if (pair? (cdr x))
+        (last-pair (cdr x))
+        x))
+
+(define (head stream) (car stream))
+
+(define (tail stream) (force (cdr stream)))
+
+(define (vector-equal? x y)
+     (and (vector? x) (vector? y) (= (vector-length x) (vector-length y))
+          (let ((n (vector-length x)))
+               (let loop ((i 0))
+                    (if (= i n)
+                         #t
+                         (and (equal? (vector-ref x i) (vector-ref y i))
+                              (loop (succ i))))))))
+
+(define (list->vector x)
+     (apply vector x))
+
+(define (vector-fill! v e)
+     (let ((n (vector-length v)))
+          (let loop ((i 0))
+               (if (= i n)
+                    v
+                    (begin (vector-set! v i e) (loop (succ i)))))))
+
+(define (vector->list v)
+     (let loop ((n (pred (vector-length v))) (l '()))
+          (if (= n -1)
+               l
+               (loop (pred n) (cons (vector-ref v n) l)))))
+
+;; The following quasiquote macro is due to Eric S. Tiedemann.
+;;   Copyright 1988 by Eric S. Tiedemann; all rights reserved.
+;;
+;; Subsequently modified to handle vectors: D. Souflis
+
+(macro
+ quasiquote
+ (lambda (l)
+   (define (mcons f l r)
+     (if (and (pair? r)
+              (eq? (car r) 'quote)
+              (eq? (car (cdr r)) (cdr f))
+              (pair? l)
+              (eq? (car l) 'quote)
+              (eq? (car (cdr l)) (car f)))
+         (if (or (procedure? f) (number? f) (string? f))
+               f
+               (list 'quote f))
+         (if (eqv? l vector)
+               (apply l (eval r))
+               (list 'cons l r)
+               )))
+   (define (mappend f l r)
+     (if (or (null? (cdr f))
+             (and (pair? r)
+                  (eq? (car r) 'quote)
+                  (eq? (car (cdr r)) '())))
+         l
+         (list 'append l r)))
+   (define (foo level form)
+     (cond ((not (pair? form))
+               (if (or (procedure? form) (number? form) (string? form))
+                    form
+                    (list 'quote form))
+               )
+           ((eq? 'quasiquote (car form))
+            (mcons form ''quasiquote (foo (+ level 1) (cdr form))))
+           (#t (if (zero? level)
+                   (cond ((eq? (car form) 'unquote) (car (cdr form)))
+                         ((eq? (car form) 'unquote-splicing)
+                          (error "Unquote-splicing wasn't in a list:"
+                                 form))
+                         ((and (pair? (car form))
+                               (eq? (car (car form)) 'unquote-splicing))
+                          (mappend form (car (cdr (car form)))
+                                   (foo level (cdr form))))
+                         (#t (mcons form (foo level (car form))
+                                         (foo level (cdr form)))))
+                   (cond ((eq? (car form) 'unquote)
+                          (mcons form ''unquote (foo (- level 1)
+                                                     (cdr form))))
+                         ((eq? (car form) 'unquote-splicing)
+                          (mcons form ''unquote-splicing
+                                      (foo (- level 1) (cdr form))))
+                         (#t (mcons form (foo level (car form))
+                                         (foo level (cdr form)))))))))
+   (foo 0 (car (cdr l)))))
+
+
+;;;;; atom? and equal? written by a.k
+
+;;;; atom?
+(define (atom? x)
+  (not (pair? x)))
+
+;;;;    equal?
+(define (equal? x y)
+     (cond
+          ((pair? x)
+               (and (pair? y)
+                    (equal? (car x) (car y))
+                    (equal? (cdr x) (cdr y))))
+          ((vector? x)
+               (and (vector? y) (vector-equal? x y)))
+          ((string? x)
+               (and (string? y) (string=? x y)))
+          (else (eqv? x y))))
+
+;;;; (do ((var init inc) ...) (endtest result ...) body ...)
+;;
+(macro do
+  (lambda (do-macro)
+    (apply (lambda (do vars endtest . body)
+             (let ((do-loop (gensym)))
+               `(letrec ((,do-loop
+                           (lambda ,(map (lambda (x)
+                                           (if (pair? x) (car x) x))
+                                      `,vars)
+                             (if ,(car endtest)
+                               (begin ,@(cdr endtest))
+                               (begin
+                                 ,@body
+                                 (,do-loop
+                                   ,@(map (lambda (x)
+                                            (cond
+                                              ((not (pair? x)) x)
+                                              ((< (length x) 3) (car x))
+                                              (else (car (cdr (cdr x))))))
+                                       `,vars)))))))
+                  (,do-loop
+                    ,@(map (lambda (x)
+                             (if (and (pair? x) (cdr x))
+                               (car (cdr x))
+                               '()))
+                        `,vars)))))
+      do-macro)))
+
+;;;; generic-member
+(define (generic-member cmp obj lst)
+  (cond
+    ((null? lst) #f)
+    ((cmp obj (car lst)) lst)
+    (else (generic-member cmp obj (cdr lst)))))
+
+(define (memq obj lst)
+     (generic-member eq? obj lst))
+(define (memv obj lst)
+     (generic-member eqv? obj lst))
+(define (member obj lst)
+     (generic-member equal? obj lst))
+
+;;;; generic-assoc
+(define (generic-assoc cmp obj alst)
+     (cond
+          ((null? alst) #f)
+          ((cmp obj (caar alst)) (car alst))
+          (else (generic-assoc cmp obj (cdr alst)))))
+
+(define (assq obj alst)
+     (generic-assoc eq? obj alst))
+(define (assv obj alst)
+     (generic-assoc eqv? obj alst))
+(define (assoc obj alst)
+     (generic-assoc equal? obj alst))
+
+(define (acons x y z) (cons (cons x y) z))
+
+;;;; Utility to ease macro creation
+(define (macro-expand form)
+     ((eval (get-closure-code (eval (car form)))) form))
+
+;;;; Handy for imperative programs
+;;;; Used as: (define-with-return (foo x y) .... (return z) ...)
+(macro (define-with-return form)
+     `(define ,(cadr form)
+          (call/cc (lambda (return) ,@(cddr form)))))
+
+;;;; Simple exception handling
+;
+;    Exceptions are caught as follows:
+;
+;         (catch (do-something to-recover and-return meaningful-value)
+;              (if-something goes-wrong)
+;              (with-these calls))
+;
+;    "Catch" establishes a scope spanning multiple call-frames
+;    until another "catch" is encountered.
+;
+;    Exceptions are thrown with:
+;
+;         (throw "message")
+;
+;    If used outside a (catch ...), reverts to (error "message)
+
+(define *handlers* (list))
+
+(define (push-handler proc)
+     (set! *handlers* (cons proc *handlers*)))
+
+(define (pop-handler)
+     (let ((h (car *handlers*)))
+          (set! *handlers* (cdr *handlers*))
+          h))
+
+(define (more-handlers?)
+     (pair? *handlers*))
+
+(define (throw . x)
+     (if (more-handlers?)
+          (apply (pop-handler))
+          (apply error x)))
+
+(macro (catch form)
+     (let ((label (gensym)))
+          `(call/cc (lambda (exit)
+               (push-handler (lambda () (exit ,(cadr form))))
+               (let ((,label (begin ,@(cddr form))))
+                    (pop-handler)
+                    ,label)))))
+
+(define *error-hook* throw)
+
+
+;;;;; Definition of MAKE-ENVIRONMENT, to be used with two-argument EVAL
+
+(macro (make-environment form)
+     `(apply (lambda ()
+               ,@(cdr form)
+               (current-environment))))
+
+(define-macro (eval-polymorphic x . envl)
+  (display envl)
+  (let* ((env (if (null? envl) (current-environment) (eval (car envl))))
+         (xval (eval x env)))
+    (if (closure? xval)
+	(make-closure (get-closure-code xval) env)
+	xval)))
+
+; Redefine this if you install another package infrastructure
+; Also redefine 'package'
+(define *colon-hook* eval)
+
+;;;;; I/O
+
+(define (input-output-port? p)
+     (and (input-port? p) (output-port? p)))
+
+(define (close-port p)
+     (cond 
+          ((input-output-port? p) (close-input-port (close-output-port p)))
+          ((input-port? p) (close-input-port p))
+          ((output-port? p) (close-output-port p))
+          (else (throw "Not a port" p))))
+
+(define (call-with-input-file s p)
+     (let ((inport (open-input-file s)))
+          (if (eq? inport #f)
+               #f
+               (let ((res (p inport)))
+                    (close-input-port inport)
+                    res))))
+
+(define (call-with-output-file s p)
+     (let ((outport (open-output-file s)))
+          (if (eq? outport #f)
+               #f
+               (let ((res (p outport)))
+                    (close-output-port outport)
+                    res))))
+
+(define (with-input-from-file s p)
+     (let ((inport (open-input-file s)))
+          (if (eq? inport #f)
+               #f
+               (let ((prev-inport (current-input-port)))
+                    (set-input-port inport)
+                    (let ((res (p)))
+                         (close-input-port inport)
+                         (set-input-port prev-inport)
+                         res)))))
+
+(define (with-output-to-file s p)
+     (let ((outport (open-output-file s)))
+          (if (eq? outport #f)
+               #f
+               (let ((prev-outport (current-output-port)))
+                    (set-output-port outport)
+                    (let ((res (p)))
+                         (close-output-port outport)
+                         (set-output-port prev-outport)
+                         res)))))
+
+(define (with-input-output-from-to-files si so p)
+     (let ((inport (open-input-file si))
+           (outport (open-input-file so)))
+          (if (not (and inport outport))
+               (begin
+                    (close-input-port inport)
+                    (close-output-port outport)
+                    #f)
+               (let ((prev-inport (current-input-port))
+                     (prev-outport (current-output-port)))
+                    (set-input-port inport)
+                    (set-output-port outport)
+                    (let ((res (p)))
+                         (close-input-port inport)
+                         (close-output-port outport)
+                         (set-input-port prev-inport)
+                         (set-output-port prev-outport)
+                         res)))))
+
+; Random number generator (maximum cycle)
+(define *seed* 1)
+(define (random-next)
+     (let* ((a 16807) (m 2147483647) (q (quotient m a)) (r (modulo m a)))
+          (set! *seed*
+               (-   (* a (- *seed*
+                         (* (quotient *seed* q) q)))
+                    (* (quotient *seed* q) r)))
+          (if (< *seed* 0) (set! *seed* (+ *seed* m)))
+          *seed*))
+;; SRFI-0 
+;; COND-EXPAND
+;; Implemented as a macro
+(define *features* '(srfi-0))
+
+(define-macro (cond-expand . cond-action-list)
+  (cond-expand-runtime cond-action-list))
+
+(define (cond-expand-runtime cond-action-list)
+  (if (null? cond-action-list)
+      #t
+      (if (cond-eval (caar cond-action-list))
+          `(begin ,@(cdar cond-action-list))
+          (cond-expand-runtime (cdr cond-action-list)))))
+
+(define (cond-eval-and cond-list)
+  (foldr (lambda (x y) (and (cond-eval x) (cond-eval y))) #t cond-list))
+
+(define (cond-eval-or cond-list)
+  (foldr (lambda (x y) (or (cond-eval x) (cond-eval y))) #f cond-list))
+
+(define (cond-eval condition)
+  (cond ((symbol? condition)
+	 (if (member condition *features*) #t #f))
+	((eq? condition #t) #t)
+	((eq? condition #f) #f)
+	(else (case (car condition)
+		((and) (cond-eval-and (cdr condition)))
+		((or) (cond-eval-or (cdr condition)))
+		((not) (if (not (null? (cddr condition)))
+			   (error "cond-expand : 'not' takes 1 argument")
+			   (not (cond-eval (cadr condition)))))
+		(else (error "cond-expand : unknown operator" (car condition)))))))
+
+(gc-verbose #f)

+ 87 - 0
busunit/passdb_slim/tinyscheme1.39/makefile

@@ -0,0 +1,87 @@
+# Makefile for TinyScheme 
+# Time-stamp: <2002-06-24 14:13:27 gildea> 
+  
+# Windows/2000 
+#CC = cl -nologo 
+#DEBUG= -W3 -Z7 -MD 
+#DL_FLAGS= 
+#SYS_LIBS= 
+#Osuf=obj 
+#SOsuf=dll 
+#LIBsuf=.lib
+#EXE_EXT=.exe 
+#LD = link -nologo 
+#LDFLAGS = -debug -map -dll -incremental:no 
+#LIBPREFIX = 
+#OUT = -out:$@ 
+#RM= -del
+#AR= echo
+
+# Unix, generally 
+CC = gcc -fpic 
+DEBUG=-g -Wall -Wno-char-subscripts -O 
+Osuf=o 
+SOsuf=so 
+LIBsuf=a
+EXE_EXT=
+LIBPREFIX=lib
+OUT = -o $@ 
+RM= -rm -f
+AR= ar crs
+ 
+# Linux 
+LD = gcc 
+LDFLAGS = -shared 
+DEBUG=-g -Wno-char-subscripts -O
+SYS_LIBS= -ldl
+PLATFORM_FEATURES= -DUSE_STRLWR=1
+
+# Cygwin
+#PLATFORM_FEATURES = -DUSE_STRLWR=0
+
+ 
+# Solaris 
+#SYS_LIBS= -ldl -lc 
+#Osuf=o 
+#SOsuf=so 
+#EXE_EXT= 
+#LD = ld 
+#LDFLAGS = -G -Bsymbolic -z text 
+#LIBPREFIX = lib 
+#OUT = -o $@ 
+ 
+FEATURES = $(PLATFORM_FEATURES) -DUSE_DL=0 -DUSE_MATH=0 -DUSE_ASCII_NAMES=0
+ 
+OBJS = scheme.$(Osuf) dynload.$(Osuf) 
+ 
+LIBTARGET = $(LIBPREFIX)tinyscheme.$(SOsuf) 
+STATICLIBTARGET = $(LIBPREFIX)tinyscheme.$(LIBsuf)
+
+all: $(LIBTARGET) $(STATICLIBTARGET) scheme$(EXE_EXT)
+
+%.$(Osuf): %.c 
+	$(CC) -I. -c $(DEBUG) $(FEATURES) $(DL_FLAGS) $< 
+
+$(LIBTARGET): $(OBJS) 
+	$(LD) $(LDFLAGS) $(OUT) $(OBJS) $(SYS_LIBS) 
+
+scheme$(EXE_EXT): $(OBJS) 
+	$(CC) -o $@ $(DEBUG) $(OBJS) $(SYS_LIBS) 
+
+$(STATICLIBTARGET): $(OBJS)
+	$(AR) $@ $(OBJS)
+
+$(OBJS): scheme.h scheme-private.h opdefines.h
+dynload.$(Osuf): dynload.h 
+
+clean: 
+	$(RM) $(OBJS) $(LIBTARGET) $(STATICLIBTARGET) scheme$(EXE_EXT)
+	$(RM) tinyscheme.ilk tinyscheme.map tinyscheme.pdb tinyscheme.exp
+	$(RM) scheme.ilk scheme.map scheme.pdb scheme.lib scheme.exp
+	$(RM) *~
+
+TAGS_SRCS = scheme.h scheme.c dynload.h dynload.c
+
+tags: TAGS 
+TAGS: $(TAGS_SRCS) 
+	etags $(TAGS_SRCS) 

+ 191 - 0
busunit/passdb_slim/tinyscheme1.39/opdefines.h

@@ -0,0 +1,191 @@
+    _OP_DEF(opexe_0, "load",                           1,  1,       TST_STRING,                      OP_LOAD             )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_T0LVL            )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_T1LVL            )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_READ_INTERNAL    )
+    _OP_DEF(opexe_0, "gensym",                         0,  0,       0,                               OP_GENSYM           )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_VALUEPRINT       )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_EVAL             )
+#if USE_TRACING
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_REAL_EVAL        )
+#endif
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_E0ARGS           )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_E1ARGS           )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_APPLY            )
+#if USE_TRACING
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_REAL_APPLY       )
+    _OP_DEF(opexe_0, "tracing",                        1,  1,       TST_NATURAL,                     OP_TRACING          )
+#endif
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_DOMACRO          )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_LAMBDA           )
+    _OP_DEF(opexe_0, "make-closure",                   1,  2,       TST_PAIR TST_ENVIRONMENT,        OP_MKCLOSURE        )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_QUOTE            )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_DEF0             )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_DEF1             )
+    _OP_DEF(opexe_0, "defined?",                       1,  2,       TST_SYMBOL TST_ENVIRONMENT,      OP_DEFP             )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_BEGIN            )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_IF0              )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_IF1              )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_SET0             )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_SET1             )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_LET0             )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_LET1             )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_LET2             )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_LET0AST          )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_LET1AST          )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_LET2AST          )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_LET0REC          )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_LET1REC          )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_LET2REC          )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_COND0            )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_COND1            )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_DELAY            )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_AND0             )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_AND1             )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_OR0              )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_OR1              )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_C0STREAM         )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_C1STREAM         )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_MACRO0           )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_MACRO1           )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_CASE0            )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_CASE1            )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_CASE2            )
+    _OP_DEF(opexe_1, "eval",                           1,  2,       TST_ANY TST_ENVIRONMENT,         OP_PEVAL            )
+    _OP_DEF(opexe_1, "apply",                          1,  INF_ARG, TST_NONE,                        OP_PAPPLY           )
+    _OP_DEF(opexe_1, "call-with-current-continuation", 1,  1,       TST_NONE,                        OP_CONTINUATION     )
+#if USE_MATH
+    _OP_DEF(opexe_2, "inexact->exact",                 1,  1,       TST_NUMBER,                      OP_INEX2EX          )
+    _OP_DEF(opexe_2, "exp",                            1,  1,       TST_NUMBER,                      OP_EXP              )
+    _OP_DEF(opexe_2, "log",                            1,  1,       TST_NUMBER,                      OP_LOG              )
+    _OP_DEF(opexe_2, "sin",                            1,  1,       TST_NUMBER,                      OP_SIN              )
+    _OP_DEF(opexe_2, "cos",                            1,  1,       TST_NUMBER,                      OP_COS              )
+    _OP_DEF(opexe_2, "tan",                            1,  1,       TST_NUMBER,                      OP_TAN              )
+    _OP_DEF(opexe_2, "asin",                           1,  1,       TST_NUMBER,                      OP_ASIN             )
+    _OP_DEF(opexe_2, "acos",                           1,  1,       TST_NUMBER,                      OP_ACOS             )
+    _OP_DEF(opexe_2, "atan",                           1,  2,       TST_NUMBER,                      OP_ATAN             )
+    _OP_DEF(opexe_2, "sqrt",                           1,  1,       TST_NUMBER,                      OP_SQRT             )
+    _OP_DEF(opexe_2, "expt",                           2,  2,       TST_NUMBER,                      OP_EXPT             )
+    _OP_DEF(opexe_2, "floor",                          1,  1,       TST_NUMBER,                      OP_FLOOR            )
+    _OP_DEF(opexe_2, "ceiling",                        1,  1,       TST_NUMBER,                      OP_CEILING          )
+    _OP_DEF(opexe_2, "truncate",                       1,  1,       TST_NUMBER,                      OP_TRUNCATE         )
+    _OP_DEF(opexe_2, "round",                          1,  1,       TST_NUMBER,                      OP_ROUND            )
+#endif
+    _OP_DEF(opexe_2, "+",                              0,  INF_ARG, TST_NUMBER,                      OP_ADD              )
+    _OP_DEF(opexe_2, "-",                              1,  INF_ARG, TST_NUMBER,                      OP_SUB              )
+    _OP_DEF(opexe_2, "*",                              0,  INF_ARG, TST_NUMBER,                      OP_MUL              )
+    _OP_DEF(opexe_2, "/",                              1,  INF_ARG, TST_NUMBER,                      OP_DIV              )
+    _OP_DEF(opexe_2, "quotient",                       1,  INF_ARG, TST_INTEGER,                     OP_INTDIV           )
+    _OP_DEF(opexe_2, "remainder",                      2,  2,       TST_INTEGER,                     OP_REM              )
+    _OP_DEF(opexe_2, "modulo",                         2,  2,       TST_INTEGER,                     OP_MOD              )
+    _OP_DEF(opexe_2, "car",                            1,  1,       TST_PAIR,                        OP_CAR              )
+    _OP_DEF(opexe_2, "cdr",                            1,  1,       TST_PAIR,                        OP_CDR              )
+    _OP_DEF(opexe_2, "cons",                           2,  2,       TST_NONE,                        OP_CONS             )
+    _OP_DEF(opexe_2, "set-car!",                       2,  2,       TST_PAIR TST_ANY,                OP_SETCAR           )
+    _OP_DEF(opexe_2, "set-cdr!",                       2,  2,       TST_PAIR TST_ANY,                OP_SETCDR           )
+    _OP_DEF(opexe_2, "char->integer",                  1,  1,       TST_CHAR,                        OP_CHAR2INT         )
+    _OP_DEF(opexe_2, "integer->char",                  1,  1,       TST_NATURAL,                     OP_INT2CHAR         )
+    _OP_DEF(opexe_2, "char-upcase",                    1,  1,       TST_CHAR,                        OP_CHARUPCASE       )
+    _OP_DEF(opexe_2, "char-downcase",                  1,  1,       TST_CHAR,                        OP_CHARDNCASE       )
+    _OP_DEF(opexe_2, "symbol->string",                 1,  1,       TST_SYMBOL,                      OP_SYM2STR          )
+    _OP_DEF(opexe_2, "atom->string",                   1,  1,       TST_ANY,                         OP_ATOM2STR         )
+    _OP_DEF(opexe_2, "string->symbol",                 1,  1,       TST_STRING,                      OP_STR2SYM          )
+    _OP_DEF(opexe_2, "string->atom",                   1,  1,       TST_STRING,                      OP_STR2ATOM         )
+    _OP_DEF(opexe_2, "make-string",                    1,  2,       TST_NATURAL TST_CHAR,            OP_MKSTRING         )
+    _OP_DEF(opexe_2, "string-length",                  1,  1,       TST_STRING,                      OP_STRLEN           )
+    _OP_DEF(opexe_2, "string-ref",                     2,  2,       TST_STRING TST_NATURAL,          OP_STRREF           )
+    _OP_DEF(opexe_2, "string-set!",                    3,  3,       TST_STRING TST_NATURAL TST_CHAR, OP_STRSET           )
+    _OP_DEF(opexe_2, "string-append",                  0,  INF_ARG, TST_STRING,                      OP_STRAPPEND        )
+    _OP_DEF(opexe_2, "substring",                      2,  3,       TST_STRING TST_NATURAL,          OP_SUBSTR           )
+    _OP_DEF(opexe_2, "vector",                         0,  INF_ARG, TST_NONE,                        OP_VECTOR           )
+    _OP_DEF(opexe_2, "make-vector",                    1,  2,       TST_NATURAL TST_ANY,             OP_MKVECTOR         )
+    _OP_DEF(opexe_2, "vector-length",                  1,  1,       TST_VECTOR,                      OP_VECLEN           )
+    _OP_DEF(opexe_2, "vector-ref",                     2,  2,       TST_VECTOR TST_NATURAL,          OP_VECREF           )
+    _OP_DEF(opexe_2, "vector-set!",                    3,  3,       TST_VECTOR TST_NATURAL TST_ANY,        OP_VECSET     )
+    _OP_DEF(opexe_3, "not",                            1,  1,       TST_NONE,                        OP_NOT              )
+    _OP_DEF(opexe_3, "boolean?",                       1,  1,       TST_NONE,                        OP_BOOLP            )
+    _OP_DEF(opexe_3, "eof-object?",                    1,  1,       TST_NONE,                        OP_EOFOBJP          )
+    _OP_DEF(opexe_3, "null?",                          1,  1,       TST_NONE,                        OP_NULLP            )
+    _OP_DEF(opexe_3, "=",                              2,  INF_ARG, TST_NUMBER,                      OP_NUMEQ            )
+    _OP_DEF(opexe_3, "<",                              2,  INF_ARG, TST_NUMBER,                      OP_LESS             )
+    _OP_DEF(opexe_3, ">",                              2,  INF_ARG, TST_NUMBER,                      OP_GRE              )
+    _OP_DEF(opexe_3, "<=",                             2,  INF_ARG, TST_NUMBER,                      OP_LEQ              )
+    _OP_DEF(opexe_3, ">=",                             2,  INF_ARG, TST_NUMBER,                      OP_GEQ              )
+    _OP_DEF(opexe_3, "symbol?",                        1,  1,       TST_ANY,                         OP_SYMBOLP          )
+    _OP_DEF(opexe_3, "number?",                        1,  1,       TST_ANY,                         OP_NUMBERP          )
+    _OP_DEF(opexe_3, "string?",                        1,  1,       TST_ANY,                         OP_STRINGP          )
+    _OP_DEF(opexe_3, "integer?",                       1,  1,       TST_ANY,                         OP_INTEGERP         )
+    _OP_DEF(opexe_3, "real?",                          1,  1,       TST_ANY,                         OP_REALP            )
+    _OP_DEF(opexe_3, "char?",                          1,  1,       TST_ANY,                         OP_CHARP            )
+#if USE_CHAR_CLASSIFIERS
+    _OP_DEF(opexe_3, "char-alphabetic?",               1,  1,       TST_CHAR,                        OP_CHARAP           )
+    _OP_DEF(opexe_3, "char-numeric?",                  1,  1,       TST_CHAR,                        OP_CHARNP           )
+    _OP_DEF(opexe_3, "char-whitespace?",               1,  1,       TST_CHAR,                        OP_CHARWP           )
+    _OP_DEF(opexe_3, "char-upper-case?",               1,  1,       TST_CHAR,                        OP_CHARUP           )
+    _OP_DEF(opexe_3, "char-lower-case?",               1,  1,       TST_CHAR,                        OP_CHARLP           )
+#endif
+    _OP_DEF(opexe_3, "port?",                          1,  1,       TST_ANY,                         OP_PORTP            )
+    _OP_DEF(opexe_3, "input-port?",                    1,  1,       TST_ANY,                         OP_INPORTP          )
+    _OP_DEF(opexe_3, "output-port?",                   1,  1,       TST_ANY,                         OP_OUTPORTP         )
+    _OP_DEF(opexe_3, "procedure?",                     1,  1,       TST_ANY,                         OP_PROCP            )
+    _OP_DEF(opexe_3, "pair?",                          1,  1,       TST_ANY,                         OP_PAIRP            )
+    _OP_DEF(opexe_3, "list?",                          1,  1,       TST_ANY,                         OP_LISTP            )
+    _OP_DEF(opexe_3, "environment?",                   1,  1,       TST_ANY,                         OP_ENVP             )
+    _OP_DEF(opexe_3, "vector?",                        1,  1,       TST_ANY,                         OP_VECTORP          )
+    _OP_DEF(opexe_3, "eq?",                            2,  2,       TST_ANY,                         OP_EQ               )
+    _OP_DEF(opexe_3, "eqv?",                           2,  2,       TST_ANY,                         OP_EQV              )
+    _OP_DEF(opexe_4, "force",                          1,  1,       TST_ANY,                         OP_FORCE            )
+    _OP_DEF(opexe_4, 0,                                0,  0,       0,                               OP_SAVE_FORCED      )
+    _OP_DEF(opexe_4, "write",                          1,  2,       TST_ANY TST_OUTPORT,             OP_WRITE            )
+    _OP_DEF(opexe_4, "write-char",                     1,  2,       TST_CHAR TST_OUTPORT,            OP_WRITE_CHAR       )
+    _OP_DEF(opexe_4, "display",                        1,  2,       TST_ANY TST_OUTPORT,             OP_DISPLAY          )
+    _OP_DEF(opexe_4, "newline",                        0,  1,       TST_OUTPORT,                     OP_NEWLINE          )
+    _OP_DEF(opexe_4, "error",                          1,  INF_ARG, TST_NONE,                        OP_ERR0             )
+    _OP_DEF(opexe_4, 0,                                0,  0,       0,                               OP_ERR1             )
+    _OP_DEF(opexe_4, "reverse",                        1,  1,       TST_PAIR,                        OP_REVERSE          )
+    _OP_DEF(opexe_4, "list*",                          1,  INF_ARG, TST_NONE,                        OP_LIST_STAR        )
+    _OP_DEF(opexe_4, "append",                         0,  INF_ARG, TST_NONE,                        OP_APPEND           )
+    _OP_DEF(opexe_4, "put",                            3,  3,       TST_NONE,                        OP_PUT              )
+    _OP_DEF(opexe_4, "get",                            2,  2,       TST_NONE,                        OP_GET              )
+    _OP_DEF(opexe_4, "quit",                           0,  1,       TST_NUMBER,                      OP_QUIT             )
+    _OP_DEF(opexe_4, "gc",                             0,  0,       0,                               OP_GC               )
+    _OP_DEF(opexe_4, "gc-verbose",                     0,  1,       TST_NONE,                        OP_GCVERB           )
+    _OP_DEF(opexe_4, "new-segment",                    0,  1,       TST_NUMBER,                      OP_NEWSEGMENT       )
+    _OP_DEF(opexe_4, "oblist",                         0,  0,       0,                               OP_OBLIST           )
+    _OP_DEF(opexe_4, "current-input-port",             0,  0,       0,                               OP_CURR_INPORT      )
+    _OP_DEF(opexe_4, "current-output-port",            0,  0,       0,                               OP_CURR_OUTPORT     )
+    _OP_DEF(opexe_4, "open-input-file",                1,  1,       TST_STRING,                      OP_OPEN_INFILE      )
+    _OP_DEF(opexe_4, "open-output-file",               1,  1,       TST_STRING,                      OP_OPEN_OUTFILE     )
+    _OP_DEF(opexe_4, "open-input-output-file",         1,  1,       TST_STRING,                      OP_OPEN_INOUTFILE   )
+#if USE_STRING_PORTS
+    _OP_DEF(opexe_4, "open-input-string",              1,  1,       TST_STRING,                      OP_OPEN_INSTRING    )
+    _OP_DEF(opexe_4, "open-output-string",             1,  1,       TST_STRING,                      OP_OPEN_OUTSTRING   )
+    _OP_DEF(opexe_4, "open-input-output-string",       1,  1,       TST_STRING,                      OP_OPEN_INOUTSTRING )
+#endif
+    _OP_DEF(opexe_4, "close-input-port",               1,  1,       TST_INPORT,                      OP_CLOSE_INPORT     )
+    _OP_DEF(opexe_4, "close-output-port",              1,  1,       TST_OUTPORT,                     OP_CLOSE_OUTPORT    )
+    _OP_DEF(opexe_4, "interaction-environment",        0,  0,       0,                               OP_INT_ENV          )
+    _OP_DEF(opexe_4, "current-environment",            0,  0,       0,                               OP_CURR_ENV         )
+    _OP_DEF(opexe_5, "read",                           0,  1,       TST_INPORT,                      OP_READ             )
+    _OP_DEF(opexe_5, "read-char",                      0,  1,       TST_INPORT,                      OP_READ_CHAR        )
+    _OP_DEF(opexe_5, "peek-char",                      0,  1,       TST_INPORT,                      OP_PEEK_CHAR        )
+    _OP_DEF(opexe_5, "char-ready?",                    0,  1,       TST_INPORT,                      OP_CHAR_READY       )
+    _OP_DEF(opexe_5, "set-input-port",                 1,  1,       TST_INPORT,                      OP_SET_INPORT       )
+    _OP_DEF(opexe_5, "set-output-port",                1,  1,       TST_OUTPORT,                     OP_SET_OUTPORT      )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_RDSEXPR          )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_RDLIST           )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_RDDOT            )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_RDQUOTE          )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_RDQQUOTE         )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_RDQQUOTEVEC      )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_RDUNQUOTE        )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_RDUQTSP          )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_RDVEC            )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_P0LIST           )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_P1LIST           )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_PVECFROM         )
+    _OP_DEF(opexe_6, "length",                         1,  1,       TST_LIST,                        OP_LIST_LENGTH      )
+    _OP_DEF(opexe_6, "assq",                           2,  2,       TST_NONE,                        OP_ASSQ             )
+    _OP_DEF(opexe_6, "get-closure-code",               1,  1,       TST_NONE,                        OP_GET_CLOSURE      )
+    _OP_DEF(opexe_6, "closure?",                       1,  1,       TST_NONE,                        OP_CLOSUREP         )
+    _OP_DEF(opexe_6, "macro?",                         1,  1,       TST_NONE,                        OP_MACROP           )
+#undef _OP_DEF

+ 187 - 0
busunit/passdb_slim/tinyscheme1.39/scheme-private.h

@@ -0,0 +1,187 @@
+/* scheme-private.h */
+
+#ifndef _SCHEME_PRIVATE_H
+#define _SCHEME_PRIVATE_H
+
+#include "scheme.h"
+/*------------------ Ugly internals -----------------------------------*/
+/*------------------ Of interest only to FFI users --------------------*/
+
+
+enum scheme_port_kind { 
+  port_free=0, 
+  port_file=1, 
+  port_string=2, 
+  port_input=16, 
+  port_output=32 
+};
+
+typedef struct port {
+  unsigned char kind;
+  union {
+    struct {
+      FILE *file;
+      int closeit;
+    } stdio;
+    struct {
+      char *start;
+      char *past_the_end;
+      char *curr;
+    } string;
+  } rep;
+} port;
+
+/* cell structure */
+struct cell {
+  unsigned int _flag;
+  union {
+    struct {
+      char   *_svalue;
+      int   _length;
+    } _string;
+    num _number;
+    port *_port;
+    foreign_func _ff;
+    struct {
+      struct cell *_car;
+      struct cell *_cdr;
+    } _cons;
+  } _object;
+};
+
+struct scheme {
+/* arrays for segments */
+func_alloc malloc;
+func_dealloc free;
+
+/* return code */
+int retcode;
+int tracing;
+
+#define CELL_SEGSIZE    5000  /* # of cells in one segment */
+#define CELL_NSEGMENT   10    /* # of segments for cells */
+char *alloc_seg[CELL_NSEGMENT];
+pointer cell_seg[CELL_NSEGMENT];
+int     last_cell_seg;
+
+/* We use 4 registers. */
+pointer args;            /* register for arguments of function */
+pointer envir;           /* stack register for current environment */
+pointer code;            /* register for current code */
+pointer dump;            /* stack register for next evaluation */
+
+int interactive_repl;    /* are we in an interactive REPL? */
+
+struct cell _sink;
+pointer sink;            /* when mem. alloc. fails */
+struct cell _NIL;
+pointer NIL;             /* special cell representing empty cell */
+struct cell _HASHT;
+pointer T;               /* special cell representing #t */
+struct cell _HASHF;
+pointer F;               /* special cell representing #f */
+struct cell _EOF_OBJ;
+pointer EOF_OBJ;         /* special cell representing end-of-file object */
+pointer oblist;          /* pointer to symbol table */
+pointer global_env;      /* pointer to global environment */
+
+/* global pointers to special symbols */
+pointer LAMBDA;               /* pointer to syntax lambda */
+pointer QUOTE;           /* pointer to syntax quote */
+
+pointer QQUOTE;               /* pointer to symbol quasiquote */
+pointer UNQUOTE;         /* pointer to symbol unquote */
+pointer UNQUOTESP;       /* pointer to symbol unquote-splicing */
+pointer FEED_TO;         /* => */
+pointer COLON_HOOK;      /* *colon-hook* */
+pointer ERROR_HOOK;      /* *error-hook* */
+pointer SHARP_HOOK;  /* *sharp-hook* */
+
+pointer free_cell;       /* pointer to top of free cells */
+long    fcells;          /* # of free cells */
+
+pointer inport;
+pointer outport;
+pointer save_inport;
+pointer loadport;
+
+#define MAXFIL 64
+port load_stack[MAXFIL];     /* Stack of open files for port -1 (LOADing) */
+int nesting_stack[MAXFIL];
+int file_i;
+int nesting;
+
+char    gc_verbose;      /* if gc_verbose is not zero, print gc status */
+char    no_memory;       /* Whether mem. alloc. has failed */
+
+#define LINESIZE 1024
+char    linebuff[LINESIZE];
+char    strbuff[256];
+
+FILE *tmpfp;
+int tok;
+int print_flag;
+pointer value;
+int op;
+
+void *ext_data;     /* For the benefit of foreign functions */
+long gensym_cnt;
+
+struct scheme_interface *vptr;
+void *dump_base;	 /* pointer to base of allocated dump stack */
+int dump_size;		 /* number of frames allocated for dump stack */
+};
+
+/* operator code */
+enum scheme_opcodes { 
+#define _OP_DEF(A,B,C,D,E,OP) OP, 
+#include "opdefines.h" 
+  OP_MAXDEFINED 
+}; 
+
+
+#define cons(sc,a,b) _cons(sc,a,b,0)
+#define immutable_cons(sc,a,b) _cons(sc,a,b,1)
+
+int is_string(pointer p);
+char *string_value(pointer p);
+int is_number(pointer p);
+num nvalue(pointer p);
+long ivalue(pointer p);
+double rvalue(pointer p);
+int is_integer(pointer p);
+int is_real(pointer p);
+int is_character(pointer p);
+long charvalue(pointer p);
+int is_vector(pointer p);
+
+int is_port(pointer p);
+
+int is_pair(pointer p);
+pointer pair_car(pointer p);
+pointer pair_cdr(pointer p);
+pointer set_car(pointer p, pointer q);
+pointer set_cdr(pointer p, pointer q);
+
+int is_symbol(pointer p);
+char *symname(pointer p);
+int hasprop(pointer p);
+
+int is_syntax(pointer p);
+int is_proc(pointer p);
+int is_foreign(pointer p);
+char *syntaxname(pointer p);
+int is_closure(pointer p);
+#ifdef USE_MACRO
+int is_macro(pointer p);
+#endif
+pointer closure_code(pointer p);
+pointer closure_env(pointer p);
+
+int is_continuation(pointer p);
+int is_promise(pointer p);
+int is_environment(pointer p);
+int is_immutable(pointer p);
+void setimmutable(pointer p);
+
+#endif

File diff suppressed because it is too large
+ 4540 - 0
busunit/passdb_slim/tinyscheme1.39/scheme.c


+ 216 - 0
busunit/passdb_slim/tinyscheme1.39/scheme.h

@@ -0,0 +1,216 @@
+/* SCHEME.H */
+
+#ifndef _SCHEME_H
+#define _SCHEME_H
+
+#include <stdio.h>
+
+/*
+ * Default values for #define'd symbols
+ */
+#ifndef STANDALONE       /* If used as standalone interpreter */
+# define STANDALONE 1
+#endif
+
+#ifndef _MSC_VER 
+# define USE_STRCASECMP 1 
+# ifndef USE_STRLWR
+#   define USE_STRLWR 1 
+# endif
+# define SCHEME_EXPORT
+#else 
+# define USE_STRCASECMP 0 
+# define USE_STRLWR 0 
+# ifdef _SCHEME_SOURCE
+#  define SCHEME_EXPORT __declspec(dllexport)
+# else
+#  define SCHEME_EXPORT __declspec(dllimport)
+# endif
+#endif
+
+#if USE_NO_FEATURES
+# define USE_MATH 0
+# define USE_CHAR_CLASSIFIERS 0
+# define USE_ASCII_NAMES 0
+# define USE_STRING_PORTS 0
+# define USE_ERROR_HOOK 0
+# define USE_TRACING 0
+# define USE_COLON_HOOK 0
+# define USE_DL 0
+# define USE_PLIST 0
+#endif
+
+/*
+ * Leave it defined if you want continuations, and also for the Sharp Zaurus.
+ * Undefine it if you only care about faster speed and not strict Scheme compatibility.
+ */
+#define USE_SCHEME_STACK
+
+#if USE_DL
+# define USE_INTERFACE 1
+#endif
+
+
+#ifndef USE_MATH         /* If math support is needed */
+# define USE_MATH 1
+#endif
+
+#ifndef USE_CHAR_CLASSIFIERS  /* If char classifiers are needed */
+# define USE_CHAR_CLASSIFIERS 1
+#endif
+
+#ifndef USE_ASCII_NAMES  /* If extended escaped characters are needed */
+# define USE_ASCII_NAMES 1
+#endif
+
+#ifndef USE_STRING_PORTS      /* Enable string ports */
+# define USE_STRING_PORTS 1
+#endif
+
+#ifndef USE_TRACING
+# define USE_TRACING 1
+#endif
+
+#ifndef USE_PLIST
+# define USE_PLIST 0
+#endif
+
+/* To force system errors through user-defined error handling (see *error-hook*) */
+#ifndef USE_ERROR_HOOK
+# define USE_ERROR_HOOK 1
+#endif
+
+#ifndef USE_COLON_HOOK   /* Enable qualified qualifier */
+# define USE_COLON_HOOK 1
+#endif
+
+#ifndef USE_STRCASECMP   /* stricmp for Unix */
+# define USE_STRCASECMP 0
+#endif
+
+#ifndef USE_STRLWR
+# define USE_STRLWR 1
+#endif
+
+#ifndef STDIO_ADDS_CR    /* Define if DOS/Windows */
+# define STDIO_ADDS_CR 0
+#endif
+
+#ifndef INLINE
+# define INLINE
+#endif
+
+#ifndef USE_INTERFACE
+# define USE_INTERFACE 0
+#endif
+
+typedef struct scheme scheme;
+typedef struct cell *pointer;
+
+typedef void * (*func_alloc)(size_t);
+typedef void (*func_dealloc)(void *);
+
+/* num, for generic arithmetic */
+typedef struct num {
+     char is_fixnum;
+     union {
+          long ivalue;
+          double rvalue;
+     } value;
+} num;
+
+SCHEME_EXPORT scheme *scheme_init_new();
+SCHEME_EXPORT scheme *scheme_init_new_custom_alloc(func_alloc malloc, func_dealloc free);
+SCHEME_EXPORT int scheme_init(scheme *sc);
+SCHEME_EXPORT int scheme_init_custom_alloc(scheme *sc, func_alloc, func_dealloc);
+SCHEME_EXPORT void scheme_deinit(scheme *sc);
+void scheme_set_input_port_file(scheme *sc, FILE *fin);
+void scheme_set_input_port_string(scheme *sc, char *start, char *past_the_end);
+SCHEME_EXPORT void scheme_set_output_port_file(scheme *sc, FILE *fin);
+void scheme_set_output_port_string(scheme *sc, char *start, char *past_the_end);
+SCHEME_EXPORT void scheme_load_file(scheme *sc, FILE *fin);
+SCHEME_EXPORT void scheme_load_string(scheme *sc, const char *cmd);
+void scheme_apply0(scheme *sc, const char *procname);
+SCHEME_EXPORT pointer scheme_apply1(scheme *sc, const char *procname, pointer);
+void scheme_set_external_data(scheme *sc, void *p);
+SCHEME_EXPORT void scheme_define(scheme *sc, pointer env, pointer symbol, pointer value);
+
+typedef pointer (*foreign_func)(scheme *, pointer);
+
+pointer _cons(scheme *sc, pointer a, pointer b, int immutable);
+pointer mk_integer(scheme *sc, long num);
+pointer mk_real(scheme *sc, double num);
+pointer mk_symbol(scheme *sc, const char *name);
+pointer gensym(scheme *sc);
+pointer mk_string(scheme *sc, const char *str);
+pointer mk_counted_string(scheme *sc, const char *str, int len);
+pointer mk_character(scheme *sc, int c);
+pointer mk_foreign_func(scheme *sc, foreign_func f);
+void putstr(scheme *sc, const char *s);
+
+
+#if USE_INTERFACE
+struct scheme_interface {
+  void (*scheme_define)(scheme *sc, pointer env, pointer symbol, pointer value);
+  pointer (*cons)(scheme *sc, pointer a, pointer b);
+  pointer (*immutable_cons)(scheme *sc, pointer a, pointer b);
+  pointer (*reserve_cells)(scheme *sc, int n);
+  pointer (*mk_integer)(scheme *sc, long num);
+  pointer (*mk_real)(scheme *sc, double num);
+  pointer (*mk_symbol)(scheme *sc, const char *name);
+  pointer (*gensym)(scheme *sc);
+  pointer (*mk_string)(scheme *sc, const char *str);
+  pointer (*mk_counted_string)(scheme *sc, const char *str, int len);
+  pointer (*mk_character)(scheme *sc, int c);
+  pointer (*mk_vector)(scheme *sc, int len);
+  pointer (*mk_foreign_func)(scheme *sc, foreign_func f);
+  void (*putstr)(scheme *sc, const char *s);
+  void (*putcharacter)(scheme *sc, int c);
+  
+  int (*is_string)(pointer p);
+  char *(*string_value)(pointer p);
+  int (*is_number)(pointer p);
+  num (*nvalue)(pointer p);
+  long (*ivalue)(pointer p);
+  double (*rvalue)(pointer p);
+  int (*is_integer)(pointer p);
+  int (*is_real)(pointer p);
+  int (*is_character)(pointer p);
+  long (*charvalue)(pointer p);
+  int (*is_vector)(pointer p);
+  long (*vector_length)(pointer vec);
+  void (*fill_vector)(pointer vec, pointer elem);
+  pointer (*vector_elem)(pointer vec, int ielem);
+  pointer (*set_vector_elem)(pointer vec, int ielem, pointer newel);
+  int (*is_port)(pointer p);
+  
+  int (*is_pair)(pointer p);
+  pointer (*pair_car)(pointer p);
+  pointer (*pair_cdr)(pointer p);
+  pointer (*set_car)(pointer p, pointer q);
+  pointer (*set_cdr)(pointer p, pointer q);
+
+  int (*is_symbol)(pointer p);
+  char *(*symname)(pointer p);
+  
+  int (*is_syntax)(pointer p);
+  int (*is_proc)(pointer p);
+  int (*is_foreign)(pointer p);
+  char *(*syntaxname)(pointer p);
+  int (*is_closure)(pointer p);
+  int (*is_macro)(pointer p);
+  pointer (*closure_code)(pointer p);
+  pointer (*closure_env)(pointer p);
+
+  int (*is_continuation)(pointer p);
+  int (*is_promise)(pointer p);
+  int (*is_environment)(pointer p);
+  int (*is_immutable)(pointer p);
+  void (*setimmutable)(pointer p);
+  void (*load_file)(scheme *sc, FILE *fin);
+  void (*load_string)(scheme *sc, const char *input);
+};
+#endif
+
+#endif
+