home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / oct93 / develop / umbscheme.lha / UMBScheme / src / primitive.c < prev    next >
C/C++ Source or Header  |  1992-08-04  |  49KB  |  2,123 lines

  1. /* primitive.c -- UMB Scheme, (non-numeric) primitive procedures.
  2.  
  3. UMB Scheme Interpreter                  $Revision: 2.5 $
  4. Copyright (C) 1988, 1991 William R Campbell
  5.  
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20. UMB Scheme was written by Bill Campbell with help from Karl Berry,
  21. Barbara Dixey, Ira Gerstein, Mary Glaser, Kathy Hargreaves, Bill McCabe,
  22. Long Nguyen, Susan Quina, Jeyashree Sivasubram, Bela Sohoni and Thang Quoc Tran.
  23.  
  24. For additional information about UMB Scheme, contact the author:
  25.  
  26.     Bill Campbell
  27.     Department of Mathematics and Computer Science
  28.     University of Massachusetts at Boston
  29.     Harbor Campus
  30.     Boston, MA 02125
  31.  
  32.     Telephone: 617-287-6449        Internet: bill@cs.umb.edu
  33.  
  34. */
  35.  
  36. #include "portable.h"
  37. #include "eval.h"
  38. #include "object.h"
  39. #include "architecture.h"
  40. #include "number.h"
  41. #include "steering.h"
  42. #include "primitive.h"
  43. #include "io.h"
  44.  
  45.  
  46. /* Local routines. */
  47.  
  48. Private void Equal();
  49. Private void Pair_Equal();
  50. Private void Character_Equal();
  51. Private void String_Equal();
  52. Private void Vector_Equal();
  53.  
  54. /* ANSI toupper and tolower */
  55.  
  56. #define To_Lower(x) (isupper(x) ? ((x)-'A'+'a') : (x))
  57. #define To_Upper(x) (islower(x) ? ((x)-'a'+'A') : (x))
  58.  
  59.  
  60. /* Essential procedures for booleans. */
  61.  
  62. Private void Not()
  63. {
  64.     Value_Register = (Top(1) == The_False_Object) ? The_True_Object : 
  65.                         The_False_Object;
  66. }
  67.  
  68.  
  69. Private void Boolean_Predicate()
  70. {
  71.     Value_Register = Is_Boolean(Top(1)) ? The_True_Object : 
  72.                           The_False_Object;
  73. }
  74.  
  75.  
  76.  
  77. /* The various kinds of equivalence. */
  78.  
  79. /* Two object are eq is they're the same pointers. */
  80. Private void Eq()
  81. {
  82.     Value_Register = (Top(1) == Top(2)) ? The_True_Object : 
  83.                           The_False_Object;
  84. }
  85.  
  86. /* Eqv is eq with immutable objects (such as numbers) eqv. */
  87. Private void Eqv()
  88. {
  89.     if (Get_Type(Top(1)) != Get_Type(Top(2))) 
  90.     {
  91.         Value_Register = The_False_Object;
  92.     } 
  93.     else if (Is_Number(Top(1))) 
  94.     {
  95.         Number_Equal();
  96.     } 
  97.     else if (Is_Character(Top(1))) 
  98.     {
  99.         Character_Equal();
  100.     } 
  101.     else if (Is_Vector(Top(1))
  102.         && Get_Vector_Length(Top(1)) == 0
  103.         && Get_Vector_Length(Top(2)) == 0) 
  104.         {
  105.         Value_Register = The_True_Object;
  106.  
  107.     } 
  108.     else if (Is_String(Top(1))
  109.         && Get_String_Length(Top(1)) == 0
  110.         && Get_String_Length(Top(2)) == 0) 
  111.     {
  112.         Value_Register = The_True_Object;
  113.     } 
  114.     else 
  115.     {
  116.         Eq();
  117.     }
  118. }
  119.  
  120. /* Equal is eqv and it looks inside structures. */
  121. Private void Equal()
  122. {
  123.     if (Get_Type(Top(1)) != Get_Type(Top(2)) )
  124.     {
  125.         Value_Register = The_False_Object;
  126.  
  127.     } 
  128.     else if (Is_Pair(Top(1)))
  129.     {
  130.         Pair_Equal();
  131.  
  132.     } 
  133.     else if (Is_String(Top(1)))
  134.     {
  135.         String_Equal();
  136.  
  137.     } 
  138.     else if (Is_Vector(Top(1)))
  139.     {
  140.         Vector_Equal();
  141.  
  142.     }
  143.     else
  144.     {
  145.         Eqv();
  146.     }
  147. }
  148.  
  149.  
  150.  
  151. /* Essential procedures for pairs, a.k.a. lists. */
  152.  
  153. Private void Pair_Predicate()
  154. {
  155.     Value_Register = Is_Pair(Top(1)) ? The_True_Object : The_False_Object;
  156. }
  157.  
  158. Private void Cons()
  159. {
  160.     Push(Top(2));    /* Car */
  161.     Push(Top(2));    /* Cdr */
  162.     Make_Pair();
  163. }
  164.  
  165.  
  166.  
  167. Private void Car()
  168. {
  169.     Value_Register = Get_Pair_Car(Top(1));
  170. }
  171.  
  172.  
  173. Private void Cdr()
  174. {
  175.     Value_Register = Get_Pair_Cdr(Top(1));
  176. }
  177.  
  178.  
  179. Private void Set_Car()
  180. {
  181.     Get_Pair_Car(Top(2)) = Value_Register = Top(1);
  182. }
  183.  
  184. Private void Set_Cdr()
  185. {
  186.     Get_Pair_Cdr(Top(2)) = Value_Register = Top(1);
  187. }
  188.  
  189.  
  190.  
  191. /* The empty list and eof. */
  192.  
  193. Private void Empty_List_Predicate()
  194. {
  195.     Value_Register = Is_Empty_List(Top(1))
  196.         ? The_True_Object : The_False_Object;
  197. }
  198.  
  199.  
  200. Private void Get_Pair_Length()
  201. {
  202.     Integer_To_Number(Length(Top(1)));
  203. }
  204.  
  205.  
  206.  
  207. Private void Append()  /* (append obj ...)  */
  208. {
  209.     Integer arg_count = Get_Apply_Numargs( Expression_Register );
  210.     Integer arg_index;
  211.     Integer length;
  212.     Object  list;
  213.  
  214.     if (arg_count == 0)
  215.     {
  216.         Value_Register = Nil;
  217.     }
  218.     else
  219.     {
  220.         Value_Register = Top(1);
  221.         arg_index = 2;
  222.  
  223.         while ( arg_index <= arg_count )
  224.         {
  225.             list = Top( arg_index );
  226.             length = 0;
  227.             
  228.             while ( Is_Pair( list ) )
  229.             {
  230.                 Push( Get_Pair_Car( list ) );
  231.                 list = Get_Pair_Cdr( list );
  232.                 length++;
  233.             }
  234.  
  235.             if ( list != Nil )
  236.                 Display_Error( "Bad list argument to append: ",
  237.                             Expression_Register );
  238.             while ( length-- )
  239.             {
  240.                 Push( Value_Register );
  241.                 Make_Pair();
  242.             }
  243.             arg_index++;
  244.         }
  245.     }
  246. }
  247.  
  248.  
  249. /* reverse lists */
  250.  
  251. Private void Reverse()
  252. {
  253.     Integer length = Length(Top(1));
  254.     
  255.     if (! Is_List(Top(1)))
  256.         Display_Error("Argument to reverse not a list", Top(1));
  257.  
  258.     Value_Register = Nil;    /* the empty list */
  259.  
  260.     while (length--)
  261.     {
  262.         Push(Get_Pair_Car(Top(1)));    /* car on stack first */
  263.         Push(Value_Register);       /* cdr on stack second */
  264.         Make_Pair(); /* pair in value register; stack restored */
  265.         Replace(1, Get_Pair_Cdr(Top(1)));
  266.     }
  267. }
  268.  
  269.  
  270.  
  271. /* List_Tail....*/
  272.  
  273. Private void List_Tail()
  274. {
  275.     Integer position = 0;
  276.  
  277.     if ( ! Is_Exact_Number( Top(1) ) )
  278.     {
  279.         Error( "(list-tail list k) requires exact 2nd argument" );
  280.     }
  281.     else position = Number_To_Integer(Top(1));
  282.         
  283.     if (!Is_List(Top(2)))
  284.              Display_Error("First argument to list->tail not a list",
  285.                          Top(2));
  286.  
  287.         if (position < 0 || position >= Length(Top(2)))
  288.          Display_Error("List reference out of bounds",
  289.                           Expression_Register);
  290.         else 
  291.     {
  292.             while (position--) /* The while loop is executed as many times
  293.                       to filter the list containing the tail  
  294.                       elements in top(2). */
  295.             {
  296.                Replace(2,Get_Pair_Cdr(Top(2))); /* cdr below */
  297.                 }
  298.         }  
  299.     Value_Register = Top(2);
  300. }
  301.  
  302.   
  303. /* List_Ref....*/
  304.  
  305. Private void List_Ref()
  306. {
  307.     Integer position = 0;
  308.  
  309.     if ( ! Is_Exact_Number( Top(1) ) )
  310.     {
  311.         Error( "(list-ref list k) requires exact 2nd argument" );
  312.     }
  313.     else position = Number_To_Integer(Top(1));
  314.         
  315.     if (!Is_List(Top(2)))
  316.              Display_Error("First argument to list->tail not a list",
  317.                          Top(2));
  318.  
  319.         if (position < 0 || position > Length(Top(2)))
  320.          Display_Error("List reference out of bounds",
  321.                           Expression_Register);
  322.         else 
  323.     {
  324.             while (position--) /* The while loop is executed as many times
  325.                       to filter kth element in car of top(2).*/
  326.             {
  327.                Replace(2,Get_Pair_Cdr(Top(2))); /* cdr below */
  328.                 }
  329.         }  
  330.     Value_Register = Get_Pair_Car(Top(2));
  331. }
  332.  
  333.  
  334.  
  335.  
  336.  
  337. Private void Pair_Equal()
  338. {
  339.     Value_Register = The_True_Object;
  340.  
  341.     /* For efficieny's sake, use a while loop instead of recursion. 
  342.        (Most  pairs are lists, after all. */
  343.     while (Value_Register == The_True_Object
  344.         && Is_Pair(Top(1)) && Is_Pair(Top(2)) )
  345.     {
  346.         Push(Get_Pair_Car(Top(1)));
  347.         Push(Get_Pair_Car(Top(3)));
  348.         Equal();
  349.         Pop(2);
  350.  
  351.         Top(1) = Get_Pair_Cdr(Top(1));
  352.         Top(2) = Get_Pair_Cdr(Top(2));
  353.     }
  354.  
  355.     if (Value_Register == The_True_Object)
  356.     {
  357.         Push(Top(1));
  358.         Push(Top(3));
  359.         Equal();
  360.         Pop(2);
  361.     }
  362. }
  363.  
  364. /* Essential procedures for symbols. */
  365.  
  366. Private void Symbol_Predicate()
  367. {
  368.     Value_Register = Is_Symbol(Top(1))
  369.         ? The_True_Object : The_False_Object;
  370. }
  371. /* (string->symbol str). This can make symbols of both case, unlike
  372.    the reader, but that is according to the definition. */
  373.  
  374. Private void String_To_Symbol()
  375. {
  376.     Value_Register = Intern_Name(Get_String_Value(Top(1)));
  377. }
  378.  
  379.  
  380.  
  381. /* (symbol->string sym). */
  382.  
  383. Private void Symbol_To_String()
  384. {
  385.     Make_Constant_String(Get_Symbol_Name(Top(1)));
  386. }
  387.  
  388. /* Essential procedures for characters. */
  389.  
  390. Private void Character_Predicate()
  391. {
  392.     Value_Register = Is_Character(Top(1)) ? The_True_Object : 
  393.                         The_False_Object;
  394. }
  395.  
  396.  
  397.  
  398.  
  399. /* Actually, this isn't an essential procedure, but it's essential for 
  400. implementing the comparison procedures! */
  401.  
  402. Private Compare_Type Character_Compare(c1, c2)
  403.     Object c1, c2;
  404. {
  405.     Compare_Type answer;
  406.  
  407.     answer = Get_Character_Value(c1) < Get_Character_Value(c2)
  408.         ? LESS_THAN : GREATER_THAN;
  409.  
  410.     if (Get_Character_Value(c1) == Get_Character_Value(c2))
  411.     {
  412.         answer = EQUAL_TO;
  413.     };
  414.  
  415.     return answer;
  416. }
  417.  
  418. Private Compare_Type Character_CI_Compare (c1, c2)
  419.     Object c1, c2;
  420. {
  421.     Compare_Type answer;
  422.  
  423.     answer = To_Lower(Get_Character_Value(c1)) <
  424.         To_Lower(Get_Character_Value(c2))
  425.         ? LESS_THAN : GREATER_THAN;
  426.  
  427.     if(To_Lower(Get_Character_Value(c1)) == 
  428.        To_Lower(Get_Character_Value(c2)))
  429.         answer = EQUAL_TO;
  430.  
  431.     return answer;
  432. }
  433.  
  434.  
  435. Private void Character_Equal()
  436. {
  437.     Value_Register = Character_Compare(Top(2), Top(1)) == EQUAL_TO
  438.         ? The_True_Object : The_False_Object;
  439. }
  440.  
  441.  
  442. Private void Character_Less()
  443. {
  444.     Value_Register = Character_Compare(Top(2), Top(1)) == LESS_THAN
  445.         ? The_True_Object : The_False_Object;
  446. }
  447.  
  448. Private void Character_Greater()
  449. {
  450.     Value_Register = Character_Compare(Top(2), Top(1)) == GREATER_THAN
  451.         ? The_True_Object : The_False_Object;
  452. }
  453.  
  454. Private void Character_Less_Or_Equal()
  455. {
  456.     Value_Register = Character_Compare(Top(2), Top(1)) != GREATER_THAN
  457.         ? The_True_Object : The_False_Object;
  458. }
  459.  
  460. Private void Character_Greater_Or_Equal()
  461. {
  462.     Value_Register = Character_Compare(Top(2), Top(1)) != LESS_THAN
  463.         ? The_True_Object : The_False_Object;
  464. }
  465.  
  466. Private void Character_CI_Equal()
  467. {
  468.     Value_Register = Character_CI_Compare(Top(2), Top(1)) == EQUAL_TO
  469.         ? The_True_Object : The_False_Object;
  470. }
  471.  
  472.  
  473. Private void Character_CI_Less()
  474. {
  475.     Value_Register = Character_CI_Compare(Top(2), Top(1)) == LESS_THAN
  476.         ? The_True_Object : The_False_Object;
  477. }
  478.  
  479. Private void Character_CI_Greater()
  480. {
  481.     Value_Register = Character_CI_Compare(Top(2), Top(1)) == GREATER_THAN
  482.         ? The_True_Object : The_False_Object;
  483. }
  484.  
  485. Private void Character_CI_Less_Or_Equal()
  486. {
  487.     Value_Register = Character_CI_Compare(Top(2), Top(1)) != GREATER_THAN
  488.         ? The_True_Object : The_False_Object;
  489. }
  490.  
  491. Private void Character_CI_Greater_Or_Equal()
  492. {
  493.     Value_Register = Character_CI_Compare(Top(2), Top(1)) != LESS_THAN
  494.         ? The_True_Object : The_False_Object;
  495. }
  496.  
  497. Private void Character_Alpha ()
  498. {
  499.     Value_Register = isalpha(Get_Character_Value(Top(1))) ? 
  500.         The_True_Object : The_False_Object;
  501. }
  502.  
  503.  
  504. Private void Character_Numeric ()
  505. {
  506.     Value_Register = isdigit(Get_Character_Value(Top(1))) ? 
  507.         The_True_Object : The_False_Object;
  508. }
  509.  
  510. Private void Character_WhiteSpace ()
  511. {
  512.     Value_Register = isspace(Get_Character_Value(Top(1))) ? 
  513.         The_True_Object : The_False_Object;
  514. }
  515.  
  516. Private void Character_Upper_Case ()
  517. {
  518.     Value_Register = isupper(Get_Character_Value(Top(1))) ? 
  519.         The_True_Object : The_False_Object;
  520. }
  521.  
  522. Private void Character_Lower_Case ()
  523. {
  524.     Value_Register = islower(Get_Character_Value(Top(1))) ? 
  525.         The_True_Object : The_False_Object;
  526.                              
  527. }
  528.  
  529.  
  530. Private void Character_To_Integer()
  531. {
  532.     Make_Bignum_Number(1); /* All characters will fit in one digit. */
  533.     Get_Number_Digits(Value_Register)[0] = (Number_Digit_Type)
  534.         Get_Character_Value(Top(1));
  535. }
  536.  
  537. /* (integer->char number)return character.Strictly speaking,this takes
  538.     any kind of number as an argument,but only a small integer is reasonable. */
  539.  
  540. Private void Integer_To_Character()
  541. {
  542.      Integer n = Number_To_Integer(Top(1));
  543.      if (n < 0 || n >255)
  544.      {
  545.         Error("Integer value out of range to be a character");
  546.         return;
  547.          };
  548.  
  549.  
  550.      Make_Character((Character) n);
  551. }
  552.  
  553.  
  554. Private void Character_To_Lower_Case ()
  555. {
  556.     Character c;
  557.     c = To_Lower(Get_Character_Value(Top(1)));
  558.     Make_Character(c);
  559. }
  560.  
  561. Private void Character_To_Upper_Case ()
  562. {
  563.     Character c;
  564.     c = To_Upper(Get_Character_Value(Top(1)));
  565.     Make_Character(c);
  566. }
  567.  
  568.  
  569.  
  570.  
  571. /* Scheme strings. */
  572.  
  573. Private void String_Predicate()
  574. {
  575.     Value_Register = Is_String(Top(1)) ? The_True_Object : The_False_Object;
  576. }
  577.  
  578. /* (make-string str-length fill-char) */
  579.  
  580. Private void MakeString()
  581. {
  582.     Character fill_char = Get_Character_Value (Top(1));
  583.     Integer str_length = 0;
  584.     Integer index;
  585.  
  586.     if ( ! Is_Exact_Number( Top(2) ) )
  587.     {
  588.         Error( "(make-string k char) requires exact 1st argument" );
  589.     }
  590.     else str_length = Number_To_Integer(Top(2));
  591.         
  592.     Make_String(str_length);    /* uninitialized string in Value_Reg */
  593.     
  594.     for (index = 0; index < str_length; index++)
  595.         Get_String_Value(Value_Register)[index] = fill_char;
  596.     
  597.     Get_String_Value(Value_Register)[str_length] ='\0';
  598. }
  599.  
  600.  
  601. /* (string-null str). */
  602.  
  603. Private void Is_String_Null()
  604. {
  605.     Value_Register = Get_String_Length(Top(1)) == 0
  606.         ? The_True_Object : The_False_Object;
  607. }
  608.  
  609.  
  610. /* (string-length str). */
  611.  
  612. Private void String_Length()
  613. {
  614.     Integer_To_Number(Get_String_Length(Top(1)));
  615. }
  616.  
  617.  
  618. /* (string-ref str position). Scheme strings are zero-origin, as in C. */
  619.  
  620. Private void String_Ref()
  621. {
  622.     Integer position = 0;
  623.  
  624.     if ( ! Is_Exact_Number( Top(1) ) )
  625.     {
  626.         Error( "(string-ref str k) requires exact 2nd argument" );
  627.     }
  628.     else position = Number_To_Integer(Top(1));
  629.         
  630.     if (position < 0 || position >= Get_String_Length(Top(2)))
  631.         Display_Error("String reference out of bounds", 
  632.                       Expression_Register);
  633.     else
  634.         Make_Character(Get_String_Value(Top(2))[position]);
  635. }
  636.  
  637. /* (string-set! str pos c) change characters at pos to c */
  638.  
  639. Private void String_Set()
  640. {
  641.     Integer pos = 0; 
  642.  
  643.     if ( ! Is_Exact_Number( Top(2) ) )
  644.     {
  645.         Error( "(string-set! str k char) requires exact 2nd argument" );
  646.     }
  647.     else pos = Number_To_Integer(Top(2));
  648.         
  649.     if (pos < 0 || pos >= Get_String_Length(Top(3)))
  650.         Display_Error("String reference out of bounds", pos);
  651.     
  652.     Get_String_Value(Top(3))[pos] = 
  653.         Get_Character_Value(Top(1)); /* this changes the string */
  654.     Value_Register = Top(1);
  655.  
  656. }
  657.  
  658. /* Comparisons. */
  659.  
  660. Private Compare_Type String_Compare(s1, s2)
  661.     Object s1, s2;
  662. {
  663.     Integer len1 = Get_String_Length(s1);
  664.     Integer len2 = Get_String_Length(s2);
  665.     String  str1 = Get_String_Value(s1);
  666.     String  str2 = Get_String_Value(s2);
  667.     Integer shorter;
  668.  
  669.     shorter = len1 < len2 ? len1 : len2;
  670.  
  671.     while (shorter--)
  672.     {
  673.         if (*str1 > *str2) return GREATER_THAN;
  674.         if (*str1 < *str2) return LESS_THAN;
  675.  
  676.         str1++;
  677.         str2++;
  678.     }
  679.  
  680.     return (len1 > len2) ? GREATER_THAN :
  681.         (len1 < len2) ? LESS_THAN :
  682.         EQUAL_TO;
  683. }
  684.  
  685. Private Compare_Type String_Compare_Case_Independent(s1, s2)
  686.     Object s1, s2;
  687.     
  688. {
  689.     Integer len1 = Get_String_Length(s1);
  690.     Integer len2 = Get_String_Length(s2);
  691.     String  str1 = Get_String_Value(s1);
  692.     String  str2 = Get_String_Value(s2);
  693.     Integer shorter;
  694.  
  695.     shorter = len1 < len2 ? len1 : len2;
  696.  
  697.     while (shorter--)
  698.     {
  699.         if (To_Lower(*str1) > To_Lower(*str2)) return GREATER_THAN;
  700.         if (To_Lower(*str1) < To_Lower(*str2)) return LESS_THAN;
  701.  
  702.         str1++;
  703.         str2++;
  704.     }
  705.  
  706.     return (len1 > len2) ? GREATER_THAN :
  707.         (len1 < len2) ? LESS_THAN : EQUAL_TO;
  708. }
  709.  
  710. Private void String_Equal()
  711. {
  712.     Value_Register = String_Compare(Top(2), Top(1)) == EQUAL_TO
  713.         ? The_True_Object : The_False_Object;
  714. }
  715.  
  716. Private void String_Equal_Case_Independent()
  717. {
  718.     Value_Register = String_Compare_Case_Independent(Top(2), Top(1)) == 
  719.         EQUAL_TO ? The_True_Object : The_False_Object;
  720. }
  721.  
  722. Private void String_Less()
  723. {
  724.     Value_Register = String_Compare(Top(2), Top(1)) == LESS_THAN
  725.         ? The_True_Object : The_False_Object;
  726. }
  727.  
  728. Private void String_Greater()
  729. {
  730.     Value_Register = String_Compare(Top(2), Top(1)) == GREATER_THAN
  731.         ? The_True_Object : The_False_Object;
  732. }
  733.  
  734. Private void String_Less_Or_Equal()
  735. {
  736.     Value_Register = String_Compare(Top(2), Top(1)) != GREATER_THAN
  737.         ? The_True_Object : The_False_Object;
  738. }
  739.  
  740. Private void String_Greater_Or_Equal()
  741. {
  742.     Value_Register = String_Compare(Top(2), Top(1)) != LESS_THAN
  743.         ? The_True_Object : The_False_Object;
  744. }
  745.  
  746. Private void String_Less_Case_Independent()
  747. {
  748.     Value_Register = String_Compare_Case_Independent(Top(2), Top(1)) == 
  749.         LESS_THAN ? The_True_Object : The_False_Object;
  750. }
  751.  
  752. Private void String_Greater_Case_Independent()
  753. {
  754.     Value_Register = String_Compare_Case_Independent(Top(2), Top(1)) == 
  755.         GREATER_THAN ? The_True_Object : The_False_Object;
  756. }
  757.  
  758. Private void String_Less_Or_Equal_Case_Independent()
  759. {
  760.     Value_Register = String_Compare_Case_Independent(Top(2), Top(1)) != 
  761.         GREATER_THAN ? The_True_Object : The_False_Object;
  762. }
  763.  
  764. Private void String_Greater_Or_Equal_Case_Independent()
  765. {
  766.     Value_Register = String_Compare_Case_Independent(Top(2), Top(1)) != 
  767.         LESS_THAN ? The_True_Object : The_False_Object;
  768. }
  769.  
  770.  
  771. /* (substring str start end). Note |start| can equal |end|, |end| just
  772.    can't be as long as |str|. */
  773.  
  774. Private void Substring()
  775. {
  776.     Integer start = 0; 
  777.     Integer end = 0; 
  778.     Integer this_char;
  779.  
  780.     if ( ! Is_Exact_Number( Top(2) ) )
  781.     {
  782.         Error( "(substring str k1 k2) requires exact 2nd argument" );
  783.     }
  784.     else start = Number_To_Integer(Top(2));
  785.         
  786.     if ( ! Is_Exact_Number( Top(1) ) )
  787.     {
  788.         Error( "(substring str k1 k2) requires exact 3rd argument" );
  789.     }
  790.     else end = Number_To_Integer(Top(1));
  791.         
  792.     if (start < 0 || start > end)
  793.     {
  794.         Display_Error("Starting position for substring out of bounds",
  795.             Expression_Register);
  796.     }
  797.  
  798.     if (end > Get_String_Length(Top(3)) )
  799.     {
  800.         Display_Error("Ending position for substring out of bounds",
  801.             Expression_Register);
  802.     }
  803.  
  804.     Make_String(end - start);
  805.  
  806.     for (this_char = start; this_char < end ; this_char++)
  807.     {
  808.         Get_String_Value(Value_Register)[this_char - start] =
  809.             Get_String_Value(Top(3))[this_char];
  810.     }
  811.  
  812.     Get_String_Value(Value_Register)[end - start] = '\0';
  813. }
  814.  
  815.  
  816. /* (string-append str ...). */
  817.  
  818. Private void Varying_String_Append( Argnum )
  819.  
  820.     Integer Argnum;
  821. {
  822.     Integer count;
  823.     Integer totlength = 0;
  824.     Integer this_string_length;
  825.     Boolean firstcopy = TRUE;
  826.  
  827.  
  828.     count = Argnum;
  829.  
  830.     while ( count )
  831.     {
  832.         totlength += Get_String_Length( Top( count ) );
  833.         count--;
  834.     }
  835.  
  836.     Make_String( totlength );
  837.     totlength = 0;
  838.  
  839.     while ( Argnum )
  840.     {
  841.         this_string_length = Get_String_Length( Top( Argnum ) );
  842.  
  843.         if ( firstcopy )
  844.         {
  845.             memcpy( Get_String_Value( Value_Register ),
  846.                    Get_String_Value( Top( Argnum ) ), 
  847.                    this_string_length );
  848.             firstcopy = FALSE;
  849.         }
  850.         else
  851.         {
  852.             memcpy( &(Get_String_Value(Value_Register)[totlength]),
  853.                    Get_String_Value( Top(Argnum) ), 
  854.                    this_string_length );
  855.         }
  856.         totlength += this_string_length;
  857.         Argnum--;
  858.     }
  859.     Get_String_Value( Value_Register )[totlength] = '\0';
  860. }
  861.  
  862.  
  863. Private void Scheme_String_Append()
  864. {
  865.     Varying_String_Append( Get_Apply_Numargs( Expression_Register ) );
  866. }
  867.  
  868.  
  869. Public void String_Append()  /* Append just 2 strings; used in Numbers */
  870. {
  871.     Varying_String_Append( 2 );
  872. }
  873.  
  874.  
  875. /* (string->list str). */
  876.  
  877. #define Top_and_Pop(x) {x = Top(1); Pop(1);}
  878.  
  879. Private void String_To_List()
  880. {
  881.     Integer size = Get_String_Length(Top(1));
  882.     Object head;
  883.  
  884.     Value_Register = Nil;
  885.  
  886.     while (size--)
  887.     {
  888.         Push(Value_Register);
  889.         Make_Character(Get_String_Value(Top(2))[size]);
  890.         head = Value_Register;
  891.         Top_and_Pop(Value_Register);
  892.         Push(head);
  893.         Push(Value_Register);
  894.         Make_Pair();
  895.     }
  896. }
  897.  
  898.  
  899.  
  900. Private void List_To_String()
  901. {
  902.     Integer list_length = Length(Top(1));
  903.     Integer this_element;
  904.  
  905.     if (! Is_List(Top(1)))
  906.         Display_Error("Expected a list as parameter to list->string",
  907.                             Top(1));
  908.  
  909.     Make_String(list_length);
  910.  
  911.     for (this_element = 0; this_element < list_length; this_element++)
  912.     {
  913.         if (! Is_Character(First(Top(1))))
  914.             Display_Error("Expected a character in list->string", 
  915.                              Top(1));
  916.  
  917.         /* The |First| above will fail if Top(1) is not a list, 
  918.               so now |Get_Pair_Car| and |Get_Pair_Cdr| are safe. */
  919.         Get_String_Value(Value_Register)[this_element] =
  920.             Get_Character_Value(Get_Pair_Car(Top(1)));
  921.         Top(1) = Get_Pair_Cdr(Top(1));
  922.     }
  923.  
  924.     Get_String_Value(Value_Register)[list_length] = '\0';
  925. }
  926.  
  927. /* (string_copy string) returns a newly allocated copy of the original */
  928.  
  929. Private void String_Copy()
  930. {
  931.     Integer length = Get_String_Length(Top(1));
  932.     
  933.     Make_String(length);
  934.     memcpy(Get_String_Value(Value_Register),
  935.            Get_String_Value(Top(1)), ++length);
  936. }
  937.  
  938. /* (string_fill! string char) stores char in every element of string */
  939. /* return value is unspecified in report */
  940. Private void String_Fill()
  941. {
  942.     Integer this_char;
  943.     Integer length = Get_String_Length(Top(2));
  944.     Character fill = Get_Character_Value(Top(1));
  945.  
  946.     for(this_char = 0; this_char < length; this_char++)
  947.     {
  948.         Get_String_Value(Top(2))[this_char] = fill;
  949.     }
  950.     Get_String_Value(Top(2))[length] = '\0';
  951.     Value_Register = Top(2); /* return the new string */
  952. }
  953.  
  954.  
  955.  
  956. /* Vectors, a.k.a. arrays. */
  957.  
  958. Private void Vector_Predicate()
  959. {
  960.     Value_Register = Is_Vector(Top(1)) ? The_True_Object : The_False_Object;
  961. }
  962.  
  963.  
  964.  
  965. /* (make-vector length fill) */
  966.  
  967. Private void Scheme_Make_Vector()
  968. {
  969.     Object fill;
  970.     Integer length = 0;
  971.  
  972.     if ( ! Is_Exact_Number( Top(2) ) )
  973.     {
  974.         Error( "(make-vector k obj) requires exact 1st argument" );
  975.     }
  976.     else length = Number_To_Integer(Top(2));
  977.  
  978.     Make_Vector(length);
  979.     fill = Top(1);
  980.     while (length--)
  981.     {
  982.         Get_Vector_Elem( Value_Register, length ) = fill;
  983.     }
  984. }
  985.  
  986.    
  987. #define check_vector_index(v, k) \
  988.     if (k < 0 || k >= Get_Vector_Length(v)) \
  989.       { \
  990.       Error("Vector index is too big or too small"); \
  991.       return; \
  992.       } 
  993.  
  994.  
  995. /* (vector-ref vec k). */
  996.  
  997. Private void Vector_Ref()
  998. {
  999.     Integer k = 0;
  1000.  
  1001.     if ( ! Is_Exact_Number( Top(1) ) )
  1002.     {
  1003.         Error( "(vector-ref vec k) requires exact 2nd argument" );
  1004.     }
  1005.     else k = Number_To_Integer(Top(1));
  1006.         
  1007.     check_vector_index(Top(2), k);
  1008.     Value_Register = Get_Vector_Elem(Top(2), k);
  1009. }
  1010.  
  1011.  
  1012. /* (vector-set! vec k elem). */
  1013.  
  1014. Private void Vector_Set()
  1015. {
  1016.     Integer k = 0; 
  1017.  
  1018.     if ( ! Is_Exact_Number( Top(2) ) )
  1019.     {
  1020.         Error( "(vector-set! vec k elem) requires exact 2nd argument" );
  1021.     }
  1022.     else k = Number_To_Integer(Top(2));
  1023.         
  1024.     check_vector_index(Top(3), k);
  1025.     Get_Vector_Elem(Top(3), k) = Value_Register = Top(1);
  1026. }
  1027.  
  1028.  
  1029. /* (vector-length vector). */
  1030.  
  1031. Private void Vector_Length()
  1032. {
  1033.     Integer_To_Number(Get_Vector_Length(Top(1)));
  1034. }
  1035.  
  1036.  
  1037. /* (vector-equal vec1 vec2). */
  1038.  
  1039. Private void Vector_Equal()
  1040. {
  1041.     if (Get_Vector_Length(Top(2)) != Get_Vector_Length(Top(1)))
  1042.     {
  1043.         Value_Register = The_False_Object;
  1044.     } 
  1045.     else
  1046.     {
  1047.         Integer this_element;
  1048.  
  1049.         Value_Register = The_True_Object;
  1050.         for (this_element = 0; 
  1051.             Value_Register == The_True_Object
  1052.             && this_element < Get_Vector_Length(Top(1));
  1053.             this_element++)
  1054.         {
  1055.             Push(Get_Vector_Elem(Top(1), this_element));
  1056.             Push(Get_Vector_Elem(Top(3), this_element));
  1057.             Equal();
  1058.             Pop(2);
  1059.         }
  1060.     }
  1061. }
  1062.  
  1063.  
  1064. /* (vector->list vec). */
  1065.  
  1066. Private void Vector_To_List()
  1067. {
  1068.     Integer size = Get_Vector_Length(Top(1));
  1069.  
  1070.     Value_Register = Nil;
  1071.  
  1072.     while (size--)
  1073.     {
  1074.         Push(Get_Vector_Elem(Top(1), size));
  1075.         Push(Value_Register);
  1076.         Make_Pair();
  1077.     }
  1078. }
  1079.  
  1080. Public void List_To_Vector()
  1081. {
  1082.     Integer list_length = Length(Top(1));
  1083.     Integer this_element;
  1084.  
  1085.     if (! Is_List(Top(1)))
  1086.           Display_Error("Expected a list as argument to list->vector",
  1087.                             Top(1));
  1088.  
  1089.     Make_Vector(list_length);
  1090.  
  1091.     for (this_element = 0; this_element < list_length; this_element++)
  1092.     {
  1093.         Get_Vector_Elem(Value_Register, this_element) = First(Top(1));
  1094.         Top(1) = Get_Pair_Cdr(Top(1));
  1095.     }
  1096. }
  1097.  
  1098. /* (vector-fill! vector fill) stores fill in every element of vector */
  1099. /* return value is unspecified */
  1100.  
  1101. Private void Vector_Fill()
  1102. {
  1103.     Integer length = Get_Vector_Length(Top(2));
  1104.         Object fill = Top(1);
  1105.  
  1106.     while(length--)
  1107.     {
  1108.         Get_Vector_Elem(Top(2), length) = fill;
  1109.     }
  1110.     Value_Register = Top(2); /* return new vector */
  1111. }
  1112.  
  1113.  
  1114. /* Essential procedures for procedures. */
  1115.  
  1116. /* The ``procedure'' object is actually not the only kind of procedure. */
  1117.  
  1118. Private void Procedure_Predicate()
  1119. {
  1120.     Value_Register = Is_Function(Top(1)) ? The_True_Object : 
  1121.                            The_False_Object;
  1122. }
  1123.  
  1124.  
  1125. /* (apply proc arglist). Construct an application and pass it back 
  1126. to evaluator. */
  1127.  
  1128. Private void Apply()
  1129. {
  1130.     if (! Is_Function(Top(2)))
  1131.     {
  1132.         Display_Error("Apply requires a function as its 1st argument",
  1133.                                 Top(2));
  1134.     }
  1135.  
  1136.     if (! Is_List(Top(1)))
  1137.     {
  1138.         Display_Error("Apply requires a list as its 2nd argument", 
  1139.                                 Top(1));
  1140.     }
  1141.  
  1142.     Make_Apply();
  1143.     Expression_Register = Value_Register;
  1144.     PC_Register = EVAL_EXPRESSION;
  1145.     Save();
  1146.  
  1147.     Push(Nil);    /* To be popped off later by Call_Primitive(). */
  1148.     Push(Nil);
  1149. }
  1150.  
  1151. /* (force promise). Force evaluation of promised expression,
  1152.    (built by a delay). */
  1153.  
  1154. Private void Force()
  1155. {
  1156.     if ( Is_Promise(Top(1)) )
  1157.     {
  1158.     if (Get_Promise_Forced(Top(1)) )
  1159.     {
  1160.         Value_Register = Get_Promise_Expression(Top(1));
  1161.     }
  1162.     else
  1163.     {
  1164.         Expression_Register = Top(1);
  1165.         PC_Register = OVERWRITE_PROMISE;
  1166.         Save();
  1167.  
  1168.         Expression_Register = Get_Promise_Expression(Top(1));
  1169.         Environment_Register = Get_Promise_Environment(Top(1));
  1170.         PC_Register = EVAL_EXPRESSION;
  1171.         Save();
  1172.     }
  1173.     }
  1174.     else
  1175.     {
  1176.     Value_Register = Top(1);
  1177.     }
  1178.  
  1179. }
  1180.  
  1181.  
  1182. /* Ports, a.k.a. input and output. */
  1183.  
  1184. Private void Input_Port_Predicate()
  1185. {
  1186.     Value_Register = Is_Port(Top(1)) && Is_Input_Port(Top(1))
  1187.         ? The_True_Object : The_False_Object;
  1188. }
  1189.  
  1190.  
  1191. Private void Output_Port_Predicate()
  1192. {
  1193.     Value_Register = Is_Port(Top(1)) && Is_Output_Port(Top(1))
  1194.         ? The_True_Object : The_False_Object;
  1195. }
  1196.  
  1197.  
  1198. /* (set-current-input-port port) */
  1199.  
  1200. Private void Set_Current_Input()
  1201. {
  1202.      Input_Port_Predicate();
  1203.  
  1204.      if (Value_Register == The_False_Object)
  1205.      {
  1206.         Display_Error("Attempt to set an output port as input: ",
  1207.                             Top(1));
  1208.      }
  1209.      Current_Input_Port = Value_Register = Top(1);
  1210. }
  1211.  
  1212.  
  1213. /* (set-current-output-port port) */
  1214.  
  1215. Private void Set_Current_Output()
  1216. {
  1217.      Output_Port_Predicate();
  1218.  
  1219.      if (Value_Register == The_False_Object)
  1220.      {
  1221.         Display_Error("Attempt to set an input port as output: ",
  1222.                             Top(1));
  1223.      }
  1224.      Current_Output_Port = Value_Register = Top(1);
  1225. }
  1226.  
  1227.  
  1228.  
  1229. /* (open-input-file filename). */
  1230.  
  1231. Private void Open_Input_File()
  1232. {
  1233.     String filename = Get_String_Value(Top(1));
  1234.     FILE *new_file;
  1235.  
  1236.     new_file = fopen(filename, "r");
  1237.  
  1238.     if (new_file == NULL)
  1239.     {
  1240.         Error1("I can't open the file `%s' for reading", filename);
  1241.     }
  1242.  
  1243.     Make_Port(TRUE, new_file, filename);
  1244. }
  1245.  
  1246.  
  1247. /* (open-output-file filename). */
  1248.  
  1249. Private void Open_Output_File()
  1250. {
  1251.     String filename = Get_String_Value(Top(1));
  1252.     FILE *new_file;
  1253.  
  1254.     new_file = fopen(filename, "w");
  1255.  
  1256.     if (new_file == NULL)
  1257.     {
  1258.         Error1("I can't open the file `%s' for writing", filename);
  1259.     }
  1260.  
  1261.     Make_Port(FALSE, new_file, filename);
  1262. }
  1263.  
  1264.  
  1265. /* (current-input-port). */
  1266.  
  1267. Private void Get_Current_Input_Port()
  1268. {
  1269.     Value_Register = Current_Input_Port;
  1270. }
  1271.  
  1272.  
  1273. /* (current-output-port). */
  1274.  
  1275. Private void Get_Current_Output_Port()
  1276. {
  1277.     Value_Register = Current_Output_Port;
  1278. }
  1279.  
  1280.  
  1281. /* (close-xx-port port). We don't bother to check for input vs. output for
  1282.    closing. */
  1283.  
  1284. Private void Close_Port()
  1285. {
  1286.     fclose(Get_Port_File(Top(1)));
  1287. }
  1288.  
  1289.  
  1290. /* (read port). */
  1291.  
  1292. Private void Read_From_Port()
  1293. {
  1294.     Input_Port_Predicate();
  1295.  
  1296.     if (Value_Register == The_False_Object)
  1297.     {
  1298.         Display_Error("Attempt to read from an output port:", Top(1));
  1299.     }
  1300.  
  1301.     Push(Current_Input_Port);
  1302.     Current_Input_Port = Top(1);
  1303.  
  1304.     Read(Get_Port_File(Top(2))); /* The argument is at |Top(2)| now. */
  1305.  
  1306.     Current_Input_Port = Top(1);
  1307.     Pop(1);
  1308. }
  1309.  
  1310.  
  1311. /* (read-char port). */
  1312.  
  1313. Private void Read_Char()
  1314. {
  1315.     Character new_char;
  1316.  
  1317.     Input_Port_Predicate();
  1318.  
  1319.     if (Value_Register == The_False_Object)
  1320.         Display_Error("You're trying to read from a output port:", 
  1321.                                 Top(1) );
  1322.     else
  1323.     {
  1324.         new_char = getc(Get_Port_File(Top(1)));
  1325.         if (new_char == EOF)
  1326.         {
  1327.             Value_Register = The_Eof_Object;
  1328.         }
  1329.         else
  1330.         {
  1331.             Make_Character(new_char);
  1332.         }
  1333.     }
  1334. }
  1335.  
  1336. Private void Char_Ready()
  1337. {
  1338.  
  1339.     Input_Port_Predicate();
  1340.  
  1341.     if (Value_Register == The_False_Object)
  1342.         Display_Error("Attempt to apply char-ready? to an output port:", 
  1343.                                 Top(1) );
  1344.     else
  1345.     {
  1346.         Value_Register = The_True_Object;  /* all ports buffered */
  1347.     }
  1348. }
  1349.  
  1350. /* (peek-char port). */
  1351.  
  1352. Private void Scheme_Peek_Char()
  1353. {
  1354.     Character new_char;
  1355.  
  1356.     Input_Port_Predicate();
  1357.  
  1358.     if (Value_Register == The_False_Object)
  1359.         Display_Error("You're trying to peek from a output port:", 
  1360.                                 Top(1) );
  1361.     else
  1362.     {
  1363.         new_char = Peek_Char(Get_Port_File(Top(1)));
  1364.  
  1365.         if (new_char == EOF)
  1366.         {
  1367.             Value_Register = The_Eof_Object;
  1368.         }
  1369.         else
  1370.         {
  1371.             Make_Character(new_char);
  1372.         }
  1373.     }
  1374. }
  1375.  
  1376. Private void Eof_Predicate()
  1377. {
  1378.     Value_Register = Is_Eof(Top(1)) ? The_True_Object : The_False_Object;
  1379. }
  1380.  
  1381.  
  1382.  
  1383. /* (write obj port). Having a ``current output port'' makes the output routines
  1384.    simpler. But that means we have to save the old current one here. */
  1385.  
  1386. Public void Write_To_Port()
  1387. {
  1388.     Integer    dummy = 0;
  1389.  
  1390.     Output_Port_Predicate(); /* Fortunately, the port is Top(1). */
  1391.  
  1392.     if (Value_Register == The_False_Object)
  1393.     {
  1394.         Display_Error("Attempt to write to an input port:", Top(1));
  1395.     }
  1396.  
  1397.     Push(Current_Output_Port);
  1398.  
  1399.     /* Arguments are |Top(2)| and Top(3) now. */
  1400.     Current_Output_Port = Top(2); 
  1401.  
  1402.     dummy = Write_Object( Top(3) , dummy );
  1403.  
  1404.     Current_Output_Port = Top(1); /* Restore the old value. */
  1405.     Pop(1); /* And pop it. */
  1406.     Value_Register = Nil;
  1407. }
  1408.  
  1409.  
  1410. /* (display obj port). Similar considerations apply here. */
  1411.  
  1412. Private void Display_To_Port()
  1413. {
  1414.     Integer    dummy = 0;
  1415.  
  1416.     Output_Port_Predicate(); /* Fortunately, the port is Top(1). */
  1417.  
  1418.     if (Value_Register == The_False_Object)
  1419.     {
  1420.         Display_Error("Attempt to display on an input port:", Top(1));
  1421.     }
  1422.  
  1423.     Push(Current_Output_Port);
  1424.  
  1425.     Current_Output_Port = Top(2); /* The arguments moved. */
  1426.     dummy = Display_Object( Top(3) , dummy );
  1427.  
  1428.     Current_Output_Port = Top(1);
  1429.     Pop(1);
  1430.     Value_Register = Nil;
  1431. }
  1432.  
  1433.  
  1434. /* (write-char ch port). This just puts out the ASCII value, not
  1435. the representation of the character. */
  1436.  
  1437. Private void Write_Char_To_Port()
  1438. {
  1439.     Output_Port_Predicate(); /* Fortunately, the port is Top(1). */
  1440.  
  1441.     if (Value_Register == The_False_Object)
  1442.     {
  1443.         Display_Error("Attempt to write to an input port:", Top(1));
  1444.     }
  1445.  
  1446.     /* Don't need to save and restore |Current_Output_Port| here, since it's
  1447.            just a single character. */
  1448.  
  1449.     putc(Get_Character_Value(Top(2)), Get_Port_File(Top(1)));
  1450.     Value_Register = Nil;
  1451. }
  1452.  
  1453. /* (load filename). Used to load the standard prelude, hence is public. */
  1454.  
  1455. Public void Load()
  1456. {
  1457.     FILE *load_file;
  1458.     String load_file_name;
  1459.     Boolean save_printing_state = Get_Printing_State();
  1460.  
  1461.     load_file_name = Copy_String(Get_String_Value(Top(1)));
  1462.     load_file = fopen(load_file_name, "r");
  1463.  
  1464.     if (load_file == NULL)
  1465.     {
  1466.         Error1("I can't open `%s' for loading", load_file_name);
  1467.     }
  1468.  
  1469.     Output("Loading "); 
  1470.     Output(load_file_name); 
  1471.     Output("...\n");
  1472.     Set_Printing(FALSE);
  1473.  
  1474.     Environment_Register = The_Global_Environment; /* restored in eval.c */
  1475.     Read_Eval_Print(load_file);
  1476.  
  1477.     Set_Printing(save_printing_state);
  1478.     Value_Register = Nil;
  1479. }
  1480.  
  1481. Public void Load_Verbose()
  1482. {
  1483.     FILE *load_file;
  1484.     String load_file_name;
  1485.     Boolean save_printing_state = Get_Printing_State();
  1486.  
  1487.     load_file_name = Copy_String(Get_String_Value(Top(1)));
  1488.     load_file = fopen(load_file_name, "r");
  1489.  
  1490.     if (load_file == NULL)
  1491.     {
  1492.         Error1("I can't open `%s' for loading", load_file_name);
  1493.     }
  1494.  
  1495.     Output("Loading "); 
  1496.     Output(load_file_name); 
  1497.     Output("...\n");
  1498.     Set_Printing(TRUE);
  1499.  
  1500.     Environment_Register = The_Global_Environment; /* restored in eval.c */
  1501.     Read_Eval_Print(load_file);
  1502.  
  1503.     Set_Printing(save_printing_state);
  1504.     Value_Register = Nil;
  1505. }
  1506.  
  1507.  
  1508.  
  1509. /* Copy all input and output to a transcript file. */
  1510.  
  1511. /* (transcript-on filename). */
  1512.  
  1513. Private void Transcript_On()
  1514. {
  1515.     if (Is_Port(The_Transcript_Port))
  1516.     {
  1517.         Error("You are already making a transcript");
  1518.     } 
  1519.     else
  1520.     {
  1521.         FILE *transcript_file = fopen(Get_String_Value(Top(1)), "w");
  1522.         if (transcript_file == NULL)
  1523.         {
  1524.             Error1("I couldn't open the transcript file `%s'", 
  1525.                 Get_String_Value(Top(1)) );
  1526.         }
  1527.         Make_Port(FALSE, transcript_file, Get_String_Value(Top(1)));
  1528.         The_Transcript_Port = Value_Register;
  1529.     }
  1530.     Value_Register = Nil;
  1531. }
  1532.  
  1533. /* Finish up making a transcript. */
  1534. Private void Transcript_Off()
  1535. {
  1536.     if (! Is_Port(The_Transcript_Port))
  1537.     {
  1538.         Error("You're not making a transcript");
  1539.     } 
  1540.     else
  1541.     {
  1542.         fclose(Get_Port_File(The_Transcript_Port));
  1543.         The_Transcript_Port = Nil;
  1544.     }
  1545.     Value_Register = Nil;
  1546. }
  1547.  
  1548. /* (the-undefined-symbol) */
  1549.  
  1550. Private void Get_The_Undefined_Symbol()
  1551. {
  1552.     Value_Register = The_Undefined_Symbol;
  1553. }
  1554.  
  1555. /* (put symbol property-symbol obj) */
  1556.  
  1557. Private void Put()
  1558. {
  1559.     Object plist = Get_Property_List( Top(3) );
  1560.     Object prop_name = Top( 2 );
  1561.     Object obj = Top( 1 );
  1562.  
  1563.     while ( plist != Nil &&  Get_Pair_Car(Get_Pair_Car(plist)) != prop_name)
  1564.     {
  1565.         plist = Get_Pair_Cdr( plist );
  1566.     }
  1567.  
  1568.     if ( plist == Nil )
  1569.     {
  1570.         Push( prop_name );
  1571.         Push(  obj );
  1572.         Make_Pair();
  1573.         Push( Value_Register )
  1574.             Push( Get_Property_List( Top(4) ) );
  1575.         Make_Pair();
  1576.         Get_Property_List( Top(3) ) = Value_Register;
  1577.     }
  1578.     else
  1579.     {
  1580.         Get_Pair_Cdr( Get_Pair_Car( plist ) ) = obj;
  1581.     }
  1582.     Value_Register = Top(2);
  1583. }
  1584.  
  1585.  
  1586. /* (get symbol prop-name) */
  1587.  
  1588.  
  1589. Private void Get()
  1590. {
  1591.     Object    plist = Get_Property_List( Top(2) );
  1592.     Object  prop_name = Top( 1 );
  1593.  
  1594.     while ( plist != Nil && Get_Pair_Car(Get_Pair_Car(plist)) != prop_name )
  1595.     {
  1596.         plist = Get_Pair_Cdr( plist );
  1597.     }
  1598.  
  1599.     Value_Register = plist == Nil
  1600.         ? Nil
  1601.         : Get_Pair_Cdr( Get_Pair_Car( plist ) );
  1602. }
  1603.  
  1604.  
  1605. /* (gensym "prefix"). */
  1606.  
  1607. #define DECIMAL_NUMERALS_IN_INTEGER 10
  1608.  
  1609. Private void Gensym()
  1610. {
  1611.     Object prefix = Top(1);
  1612.     static Integer gensym_count = 0;
  1613.     String gen_name;
  1614.     Character count_string[DECIMAL_NUMERALS_IN_INTEGER];
  1615.  
  1616.     gen_name = (String) malloc(Get_String_Length(prefix)+
  1617.                          sizeof(count_string));
  1618.     if (gen_name == NULL)
  1619.     {
  1620.         Panic("Not enough memory to generate a name for gensym");
  1621.     }
  1622.  
  1623.     /* |prefix| might include nulls; hence, |strcpy| is not appropriate. */
  1624.     memcpy(gen_name, Get_String_Value(prefix), Get_String_Length(prefix));
  1625.  
  1626.     sprintf(count_string, Integer_Format, gensym_count++);
  1627.  
  1628.     /* This is ``memcat''. */
  1629.     memcpy(&(gen_name[Get_String_Length(prefix)]), count_string, 
  1630.         strlen(count_string));
  1631.     gen_name[Get_String_Length(prefix)+strlen(count_string)] = '\0';
  1632.  
  1633.     Make_Symbol(gen_name);
  1634.     free(gen_name);
  1635. }
  1636.  
  1637. /* (call/cc proc). Wrap up the current continuation and call the procedure
  1638. on stack with this continuation as its single argument. */
  1639.  
  1640. Private void Call_CC()
  1641. {
  1642.     if (! Is_Function(Top(1)))
  1643.     {
  1644.         Display_Error("call/cc not given a function", Top(1));
  1645.     }
  1646.  
  1647.     Function_Register = Top(1);
  1648.     Pop(1); /* Pop here so |proc| won't be on stack of the continuation. */
  1649.  
  1650.     Make_Continuation();    /* Saves stack and State_Register. */
  1651.  
  1652.     Push(Function_Register);
  1653.  
  1654.     Push(Value_Register);    /* Continuation as sole argument. */
  1655.     Push(Nil);
  1656.     Make_Pair();
  1657.     Push(Value_Register);
  1658.  
  1659.     Make_Apply();
  1660.     Expression_Register = Value_Register;
  1661.     PC_Register = EVAL_EXPRESSION;
  1662.     Save();
  1663.  
  1664.     Push(Nil);    /* To be popped off later by Call_Primitive(). */
  1665. }
  1666.  
  1667.  
  1668.  
  1669. Private void Expand_Quoted_Macro_Call()
  1670. {
  1671.     Object    call = Top( 1 );
  1672.  
  1673.     if ( ! Is_Symbol( First( call ) ) )
  1674.     {
  1675.         Display_Error( 
  1676.         "Non-macro name in call passed to expand-macro-call", 
  1677.                 First( call ) );
  1678.     }
  1679.  
  1680.     Value_Register = Get_Global_Binding(  First( call ) );
  1681.  
  1682.     if (! Is_Macro( Value_Register ) )
  1683.     {
  1684.         Display_Error( 
  1685.         "Non-macro name in call passed to expand-macro-call", 
  1686.                 First( call ) );
  1687.     }
  1688.  
  1689.     Push( Get_Macro_Transformer( Value_Register ) );
  1690.     Push( call );
  1691.     Push( Nil );
  1692.     Make_Pair();
  1693.     Push( Value_Register );
  1694.     Make_Apply();
  1695.     Expression_Register = Value_Register;
  1696.     PC_Register = EVAL_EXPRESSION;
  1697.     Save();
  1698. }
  1699.  
  1700. /* Error raising routines */
  1701.  
  1702. Private void Scheme_Break()  /* (break) */
  1703. {
  1704.     Restore();
  1705.     Break();
  1706. }
  1707.  
  1708. Private void Scheme_Reset()  /* (reset) */
  1709. {
  1710.     Reset();
  1711. }
  1712.  
  1713. /* (edit filename). Invokes the editor specified by the EDITOR environment
  1714.    variable, else ed. */
  1715.  
  1716. Private void Edit()
  1717. {
  1718.     String ed = getenv("EDITOR");
  1719.     String editor;
  1720.     String command;
  1721.  
  1722.     editor = (ed == NULL) ? "/usr/ucb/vi" : Copy_String( ed );
  1723.  
  1724.     command = (String) malloc(strlen(editor)+1 + 
  1725.                     Get_String_Length(Top(1))+1);
  1726.  
  1727.     if (command == NULL)
  1728.     {
  1729.         Panic( 
  1730.         "Unable to allocate space for command in Edit() - primitive.c" );
  1731.     }
  1732.  
  1733.     sprintf(command, "%s %s", editor, Get_String_Value(Top(1)));
  1734.  
  1735.     if (system(command) != 0)
  1736.     {
  1737.         Error1("Edit on %s didn't succeed; not reloading file", 
  1738.             Get_String_Value(Top(1)) );
  1739.     } 
  1740.     else
  1741.     {
  1742.         Load_Verbose(); /* The filename to load is still on top of the
  1743.                    stack. Default loading is verbose mode */
  1744.     }
  1745. }
  1746.  
  1747. Private void Edit_Silent()
  1748. {
  1749.     String ed = getenv("EDITOR");
  1750.     String editor;
  1751.     String command;
  1752.  
  1753.     editor = (ed == NULL) ? "/usr/ucb/vi" : Copy_String( ed );
  1754.  
  1755.     command = (String) malloc(strlen(editor)+1 + 
  1756.                     Get_String_Length(Top(1))+1);
  1757.  
  1758.     if (command == NULL)
  1759.     {
  1760.         Panic( 
  1761.         "Unable to allocate space for command in Edit() - primitive.c" );
  1762.     }
  1763.  
  1764.     sprintf(command, "%s %s", editor, Get_String_Value(Top(1)));
  1765.  
  1766.     if (system(command) != 0)
  1767.     {
  1768.         Error1("Edit on %s didn't succeed; not reloading file", 
  1769.             Get_String_Value(Top(1)) );
  1770.     } 
  1771.     else
  1772.     {
  1773.         Load(); /* The filename to load is still on top of the
  1774.                stack.*/
  1775.     }
  1776. }
  1777.  
  1778. Private    void GC_Messages()     /* (gc-messages boolean)  */
  1779. {
  1780.     Show_GC_Messages = Top(1) == The_True_Object;
  1781. }
  1782.  
  1783. /* Associate Scheme symbols with all those C procedures, for all the
  1784.    essential procedures except numbers. */
  1785.  
  1786. Public void Initialize_Primitive()
  1787. {
  1788.     /* These are listed in the order they appear in the Scheme report. */
  1789.     Make_Primitive("not", Not, 1, Any_Type, The_Undefined_Type, 
  1790.         The_Undefined_Type);
  1791.  
  1792.     Make_Primitive("boolean?", Boolean_Predicate, 1, Any_Type, 
  1793.         The_Undefined_Type, The_Undefined_Type);
  1794.  
  1795.     Make_Primitive("eqv?", Eqv, 2, Any_Type, Any_Type, The_Undefined_Type);
  1796.     Make_Primitive("eq?", Eq, 2, Any_Type, Any_Type, The_Undefined_Type);
  1797.     Make_Primitive("equal?", Equal, 2, Any_Type, Any_Type, 
  1798.         The_Undefined_Type);
  1799.  
  1800.     Make_Primitive("pair?", Pair_Predicate, 1, Any_Type, The_Undefined_Type,
  1801.         The_Undefined_Type);
  1802.  
  1803.     Make_Primitive("cons", Cons, 2, Any_Type, Any_Type, The_Undefined_Type);
  1804.  
  1805.     Make_Primitive("car", Car, 1, Pair_Type, The_Undefined_Type, 
  1806.         The_Undefined_Type);
  1807.  
  1808.     Make_Primitive("cdr", Cdr, 1, Pair_Type, The_Undefined_Type, 
  1809.         The_Undefined_Type);
  1810.  
  1811.     Make_Primitive("set-car!", Set_Car, 2, Pair_Type, Any_Type, 
  1812.         The_Undefined_Type);
  1813.  
  1814.     Make_Primitive("set-cdr!", Set_Cdr, 2, Pair_Type, Any_Type, 
  1815.         The_Undefined_Type);
  1816.  
  1817.     Make_Primitive("null?", Empty_List_Predicate, 1, Any_Type, 
  1818.         The_Undefined_Type, The_Undefined_Type);
  1819.  
  1820.  
  1821.     Make_Primitive("length", Get_Pair_Length, 1, Any_Type, 
  1822.         The_Undefined_Type, The_Undefined_Type);
  1823.  
  1824.     Make_Primitive("append", Append, VARYING, Any_Type, The_Undefined_Type,
  1825.                The_Undefined_Type);
  1826.  
  1827.     Make_Primitive("reverse", Reverse, 1, Any_Type, The_Undefined_Type,
  1828.                The_Undefined_Type);
  1829.  
  1830.         Make_Primitive("list-tail",List_Tail ,2 ,Any_Type, Number_Type,
  1831.               The_Undefined_Type);
  1832.  
  1833.         Make_Primitive("list-ref",List_Ref ,2 ,Any_Type, Number_Type,
  1834.               The_Undefined_Type);
  1835.  
  1836.     Make_Primitive("symbol?", Symbol_Predicate, 1, Any_Type, 
  1837.         The_Undefined_Type, The_Undefined_Type);
  1838.  
  1839.     Make_Primitive("symbol->string", Symbol_To_String, 1, Symbol_Type,
  1840.         The_Undefined_Type, The_Undefined_Type);
  1841.  
  1842.     Make_Primitive("string->symbol", String_To_Symbol, 1, String_Type,
  1843.         The_Undefined_Type, The_Undefined_Type);
  1844.  
  1845.     Make_Primitive("char?", Character_Predicate, 1, Any_Type, 
  1846.         The_Undefined_Type, The_Undefined_Type);
  1847.  
  1848.     Make_Primitive("char=?", Character_Equal, 2, Character_Type, 
  1849.         Character_Type, The_Undefined_Type);
  1850.  
  1851.     Make_Primitive("char<?", Character_Less, 2, Character_Type, 
  1852.         Character_Type, The_Undefined_Type);
  1853.  
  1854.     Make_Primitive("char>?", Character_Greater, 2, Character_Type, 
  1855.         Character_Type, The_Undefined_Type);
  1856.  
  1857.     Make_Primitive("char<=?", Character_Less_Or_Equal, 2, Character_Type, 
  1858.         Character_Type, The_Undefined_Type);
  1859.  
  1860.     Make_Primitive("char>=?", Character_Greater_Or_Equal, 2, Character_Type, 
  1861.         Character_Type, The_Undefined_Type);
  1862.  
  1863.     Make_Primitive("char-ci=?", Character_CI_Equal, 2, Character_Type, 
  1864.         Character_Type, The_Undefined_Type);
  1865.  
  1866.     Make_Primitive("char-ci<?", Character_CI_Less, 2, Character_Type, 
  1867.         Character_Type, The_Undefined_Type);
  1868.  
  1869.     Make_Primitive("char-ci>?", Character_CI_Greater, 2, Character_Type, 
  1870.         Character_Type, The_Undefined_Type);
  1871.  
  1872.     Make_Primitive("char-ci<=?", Character_CI_Less_Or_Equal, 2, 
  1873.         Character_Type, Character_Type, The_Undefined_Type);
  1874.  
  1875.     Make_Primitive("char-ci>=?", Character_CI_Greater_Or_Equal, 2, 
  1876.         Character_Type, Character_Type, The_Undefined_Type);
  1877.  
  1878.     Make_Primitive("char-alphabetic?", Character_Alpha, 1, Character_Type,
  1879.             The_Undefined_Type, The_Undefined_Type);
  1880.  
  1881.     Make_Primitive("char-numeric?", Character_Numeric, 1, Character_Type,
  1882.             The_Undefined_Type, The_Undefined_Type);
  1883.  
  1884.     Make_Primitive("char-whitespace?", Character_WhiteSpace, 1, 
  1885.         Character_Type,The_Undefined_Type, The_Undefined_Type);
  1886.  
  1887.     Make_Primitive("char-upper-case?", Character_Upper_Case, 1, 
  1888.            Character_Type,The_Undefined_Type, The_Undefined_Type);
  1889.  
  1890.     Make_Primitive("char-lower-case?", Character_Lower_Case, 1, 
  1891.            Character_Type, The_Undefined_Type, The_Undefined_Type);
  1892.  
  1893.         Make_Primitive("char->integer",Character_To_Integer, 1 ,
  1894.            Character_Type, The_Undefined_Type, The_Undefined_Type);
  1895.  
  1896.         Make_Primitive("integer->char",Integer_To_Character ,1 , 
  1897.            Number_Type, The_Undefined_Type,The_Undefined_Type);
  1898.            
  1899.  
  1900.     Make_Primitive("char-upcase", Character_To_Upper_Case, 1, 
  1901.            Character_Type, The_Undefined_Type, The_Undefined_Type);
  1902.  
  1903.  
  1904.     Make_Primitive("char-downcase", Character_To_Lower_Case, 1, 
  1905.            Character_Type, The_Undefined_Type, The_Undefined_Type);
  1906.  
  1907.  
  1908.     Make_Primitive("string?", String_Predicate, 1, Any_Type, 
  1909.         The_Undefined_Type, The_Undefined_Type);
  1910.  
  1911.     Make_Primitive ("#_make-string", MakeString, 2, Number_Type, 
  1912.          Character_Type, The_Undefined_Type);
  1913.  
  1914.     Make_Primitive("string-null?", Is_String_Null, 1, String_Type, 
  1915.         The_Undefined_Type, The_Undefined_Type);
  1916.  
  1917.     Make_Primitive("string-length", String_Length, 1, String_Type, 
  1918.         The_Undefined_Type, The_Undefined_Type);
  1919.  
  1920.     Make_Primitive("string-ref", String_Ref, 2, String_Type, Number_Type,
  1921.         The_Undefined_Type);
  1922.  
  1923.     Make_Primitive ("string-set!", String_Set, 3, String_Type, Number_Type,
  1924.         Character_Type);
  1925.  
  1926.     Make_Primitive("string=?", String_Equal, 2, String_Type, String_Type,
  1927.         The_Undefined_Type);
  1928.  
  1929.     Make_Primitive("string-ci=?", String_Equal_Case_Independent, 2, 
  1930.         String_Type, String_Type, The_Undefined_Type);
  1931.  
  1932.     Make_Primitive("string<?", String_Less, 2, String_Type, String_Type, 
  1933.         The_Undefined_Type);
  1934.  
  1935.     Make_Primitive("string>?", String_Greater, 2, String_Type, String_Type, 
  1936.         The_Undefined_Type);
  1937.  
  1938.     Make_Primitive("string<=?", String_Less_Or_Equal, 2, String_Type, 
  1939.         String_Type, The_Undefined_Type);
  1940.  
  1941.     Make_Primitive("string>=?", String_Greater_Or_Equal, 2, String_Type, 
  1942.         String_Type, The_Undefined_Type);
  1943.  
  1944.     Make_Primitive("string-ci<?", String_Less_Case_Independent, 2, 
  1945.         String_Type, String_Type, The_Undefined_Type);
  1946.  
  1947.     Make_Primitive("string-ci>?", String_Greater_Case_Independent, 2, 
  1948.         String_Type, String_Type, The_Undefined_Type);
  1949.  
  1950.     Make_Primitive("string-ci<=?", String_Less_Or_Equal_Case_Independent, 
  1951.         2, String_Type, String_Type, The_Undefined_Type);
  1952.  
  1953.     Make_Primitive("string-ci>=?", String_Greater_Or_Equal_Case_Independent
  1954.         , 2, String_Type, String_Type, The_Undefined_Type);
  1955.  
  1956.     Make_Primitive("substring", Substring, 3, String_Type, Number_Type,
  1957.         Number_Type);
  1958.  
  1959.     Make_Primitive("string-append", Scheme_String_Append, VARYING, 
  1960.                String_Type, The_Undefined_Type, The_Undefined_Type);
  1961.  
  1962.     Make_Primitive("string->list", String_To_List, 1, String_Type, 
  1963.         The_Undefined_Type, The_Undefined_Type);
  1964.  
  1965.     Make_Primitive("list->string", List_To_String, 1, Any_Type, 
  1966.         The_Undefined_Type, The_Undefined_Type);
  1967.  
  1968.     Make_Primitive("string-copy", String_Copy, 1, String_Type,
  1969.         The_Undefined_Type, The_Undefined_Type);
  1970.  
  1971.     Make_Primitive("string-fill!", String_Fill, 2, String_Type,
  1972.             Character_Type, The_Undefined_Type);
  1973.  
  1974.     Make_Primitive("vector?", Vector_Predicate, 1, Any_Type, 
  1975.         The_Undefined_Type, The_Undefined_Type);
  1976.  
  1977.     Make_Primitive("#_make-vector", Scheme_Make_Vector, 2, Number_Type,
  1978.         Any_Type, The_Undefined_Type);
  1979.  
  1980.     Make_Primitive("vector-length", Vector_Length, 1, Vector_Type, 
  1981.         The_Undefined_Type, The_Undefined_Type);
  1982.  
  1983.     Make_Primitive("vector-ref", Vector_Ref, 2, Vector_Type, Number_Type, 
  1984.         The_Undefined_Type);
  1985.  
  1986.     Make_Primitive("vector-set!", Vector_Set, 3, Vector_Type, Number_Type, 
  1987.         Any_Type);
  1988.  
  1989.     Make_Primitive("vector->list", Vector_To_List, 1, Vector_Type, 
  1990.         The_Undefined_Type, The_Undefined_Type);
  1991.  
  1992.     Make_Primitive("list->vector", List_To_Vector, 1, Any_Type, 
  1993.         The_Undefined_Type, The_Undefined_Type);
  1994.     
  1995.     Make_Primitive("vector-fill!", Vector_Fill, 2, Vector_Type,
  1996.             Any_Type, The_Undefined_Type);
  1997.  
  1998.     Make_Primitive("procedure?", Procedure_Predicate, 1, Any_Type, 
  1999.         The_Undefined_Type, The_Undefined_Type);
  2000.  
  2001.     /* apply does its own type checking. */
  2002.  
  2003.     Make_Primitive("#_apply", Apply, 2, Any_Type, Any_Type, 
  2004.         The_Undefined_Type);
  2005.  
  2006.     Make_Primitive("force", Force, 1, Any_Type, The_Undefined_Type, 
  2007.         The_Undefined_Type);
  2008.  
  2009.     Make_Primitive("call-with-current-continuation", Call_CC, 1, Any_Type,
  2010.         The_Undefined_Type, The_Undefined_Type);
  2011.  
  2012.     Make_Primitive("input-port?", Input_Port_Predicate, 1, Any_Type, 
  2013.         The_Undefined_Type, The_Undefined_Type);
  2014.  
  2015.     Make_Primitive("output-port?", Output_Port_Predicate, 1, Any_Type,
  2016.         The_Undefined_Type, The_Undefined_Type);
  2017.  
  2018.     Make_Primitive("current-input-port", Get_Current_Input_Port, 0,
  2019.         The_Undefined_Type, The_Undefined_Type, The_Undefined_Type);
  2020.  
  2021.     Make_Primitive("current-output-port", Get_Current_Output_Port, 0,
  2022.         The_Undefined_Type, The_Undefined_Type, The_Undefined_Type);
  2023.  
  2024.     Make_Primitive("set-current-input-port!" , Set_Current_Input, 1 ,
  2025.         Port_Type, The_Undefined_Type, The_Undefined_Type);
  2026.  
  2027.     Make_Primitive("set-current-output-port!" , Set_Current_Output, 1 ,
  2028.         Port_Type, The_Undefined_Type, The_Undefined_Type);
  2029.  
  2030.     Make_Primitive("open-input-file", Open_Input_File, 1, String_Type, 
  2031.         The_Undefined_Type, The_Undefined_Type);
  2032.  
  2033.     Make_Primitive("open-output-file", Open_Output_File, 1, String_Type,
  2034.         The_Undefined_Type, The_Undefined_Type);
  2035.  
  2036.     Make_Primitive("close-input-port", Close_Port, 1, Port_Type,
  2037.         The_Undefined_Type, The_Undefined_Type);
  2038.  
  2039.     Make_Primitive("close-output-port", Close_Port, 1, Port_Type,
  2040.         The_Undefined_Type, The_Undefined_Type);
  2041.  
  2042.     Make_Primitive("#_read", Read_From_Port, 1, Port_Type, 
  2043.         The_Undefined_Type, The_Undefined_Type);
  2044.  
  2045.     Make_Primitive("#_read-char", Read_Char, 1, Port_Type, 
  2046.         The_Undefined_Type, The_Undefined_Type);
  2047.  
  2048.     Make_Primitive("#_char-ready?", Char_Ready, 1, Port_Type, 
  2049.         The_Undefined_Type, The_Undefined_Type);
  2050.  
  2051.     Make_Primitive("#_peek-char", Scheme_Peek_Char, 1, Port_Type, 
  2052.         The_Undefined_Type, The_Undefined_Type);
  2053.  
  2054.     Make_Primitive("eof-object?", Eof_Predicate, 1, Any_Type, 
  2055.         The_Undefined_Type, The_Undefined_Type);
  2056.  
  2057.     Make_Primitive("#_write", Write_To_Port, 2, Any_Type, Port_Type, 
  2058.         The_Undefined_Type);
  2059.  
  2060.     Make_Primitive("#_display", Display_To_Port, 2, Any_Type, Port_Type,
  2061.         The_Undefined_Type);
  2062.  
  2063.     Make_Primitive("#_write-char", Write_Char_To_Port, 2, Character_Type,
  2064.         Port_Type, The_Undefined_Type);
  2065.  
  2066.         Make_Primitive("set-current-input-port!",Set_Current_Input, 1,
  2067.         Port_Type, The_Undefined_Type, The_Undefined_Type);
  2068.  
  2069.     Make_Primitive("load", Load, 1, String_Type, The_Undefined_Type, 
  2070.         The_Undefined_Type);
  2071.  
  2072.     Make_Primitive("loadv", Load_Verbose, 1, String_Type, 
  2073.         The_Undefined_Type, The_Undefined_Type);
  2074.  
  2075.     Make_Primitive("transcript-on", Transcript_On, 1, String_Type, 
  2076.         The_Undefined_Type, The_Undefined_Type);
  2077.  
  2078.     Make_Primitive("transcript-off", Transcript_Off, 0, The_Undefined_Type, 
  2079.         The_Undefined_Type, The_Undefined_Type);
  2080.  
  2081.     Make_Primitive("the-undefined-symbol", Get_The_Undefined_Symbol, 0, 
  2082.         The_Undefined_Type, The_Undefined_Type, The_Undefined_Type);
  2083.  
  2084.     Make_Primitive( "put", Put, 3, Symbol_Type, Symbol_Type, Any_Type );
  2085.  
  2086.     Make_Primitive( "get", Get, 2, Symbol_Type, Symbol_Type, 
  2087.         The_Undefined_Type);
  2088.  
  2089.     Make_Primitive("gensym", Gensym, 1, String_Type, The_Undefined_Type, 
  2090.         The_Undefined_Type);
  2091.  
  2092.     /* call/cc does its own type checking. */
  2093.  
  2094.     Make_Primitive("call/cc", Call_CC, 1, Any_Type, The_Undefined_Type,
  2095.         The_Undefined_Type);
  2096.  
  2097.     Make_Primitive("expand-quoted-macro-call", Expand_Quoted_Macro_Call, 1, 
  2098.         Pair_Type, The_Undefined_Type, The_Undefined_Type);
  2099.  
  2100.     Make_Primitive("#_break", Scheme_Break, 0, The_Undefined_Type, 
  2101.         The_Undefined_Type, The_Undefined_Type);
  2102.  
  2103.     Make_Primitive("reset", Scheme_Reset, 0, The_Undefined_Type, 
  2104.         The_Undefined_Type, The_Undefined_Type);
  2105.  
  2106.     Make_Primitive("#_edit", Edit, 1, String_Type, The_Undefined_Type,
  2107.         The_Undefined_Type);
  2108.  
  2109.     Make_Primitive("#_edits", Edit_Silent, 1, String_Type, 
  2110.             The_Undefined_Type, The_Undefined_Type);
  2111.  
  2112.     Make_Primitive("gc-messages", GC_Messages, 1, Boolean_Type, 
  2113.             The_Undefined_Type, The_Undefined_Type);
  2114.  
  2115.  
  2116.     /* Defined in architecture.c. */
  2117.     Make_Primitive("heap-size", Get_Heap_Size, 0, The_Undefined_Type,
  2118.         The_Undefined_Type, The_Undefined_Type);
  2119.  
  2120.     Make_Primitive("arg-stack-ptr" , Get_Arg_Stack_Ptr, 0, 
  2121.         The_Undefined_Type, The_Undefined_Type, The_Undefined_Type);
  2122. }
  2123.