home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / MSDOS / WATTCP / DELFT / SAGE.TAR / sage / scheme / schcel.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-14  |  23.2 KB  |  786 lines

  1. /**********************************************************************
  2. ** MODULE INFORMATION*
  3. **********************
  4. **      FILE     NAME:       SCHCEL.C
  5. **      SYSTEM   NAME:       SCHEME
  6. **      ORIGINAL AUTHOR(S):  Alfred Kayser
  7. **      VERSION  NUMBER:     1.5.5
  8. **      CREATION DATE:       88/10/12
  9. **
  10. ** DESCRIPTION: All the Scheme CEL functions are defined here.
  11. **              If the format of the cel is changed only these
  12. **              function need to be changed.
  13. ***********************************************************************
  14. ** CHANGES INFORMATION **
  15. *************************
  16. ** REVISION:    $Revision$
  17. ** CHANGER:     $Author$
  18. ** WORKFILE:    $Workfile$
  19. ** LOGFILE:     $Logfile$
  20. ** LOGINFO:     $Log$
  21. **********************************************************************/
  22. #include "schinc.h"
  23. #include "schdef.h"
  24.  
  25. STATIC int PASCAL DsHash  __((CONST char *str));
  26. STATIC CELP CDECL DsListRef  __((CELP list,CELP num));
  27. STATIC CELP CDECL DsListTail __((CELP list,CELP num));
  28. STATIC CELP CDECL DsAppend   __((CELP list,CELP num));
  29. STATIC CELP CDECL Ds_Append  __((CELP list,CELP num));
  30. STATIC CELP CDECL Ds_length  __((CELP list));
  31. STATIC CELP CDECL Ds_reverse __((CELP list));
  32.  
  33. #define PROTBIT  0x2
  34. #define MARKBIT  0x1
  35. #define SETMARK(cel)  (GCFpart(cel) |= MARKBIT)     /* SET BIT 0 */
  36. #define UNMARK(cel)   (GCFpart(cel) &= 0xfe)        /* RESET BIT 0 */
  37. #define MARKED(cel)   (GCFpart(cel))                /* TEST GC BITS */
  38.  
  39. STATIC
  40. EXTDEF CelFunctions[] =
  41.     {
  42.         {"LIST-REF",  (EXTPROC)DsListRef,  2, TYPE_PAIR, TYPE_INT},
  43.         {"LIST-TAIL", (EXTPROC)DsListTail, 2, TYPE_PAIR, TYPE_INT},
  44.         {"APPEND!",   (EXTPROC)DsAppend,   2, 0, 0},
  45.         {"APPEND",    (EXTPROC)Ds_Append,  2, 0, 0},
  46.         {"LENGTH",    (EXTPROC)Ds_length,  1, 0},
  47.         {"REVERSE",   (EXTPROC)Ds_reverse, 1, 0},
  48.  
  49.         {"CAR",    (EXTPROC)DsCar,    1, 0},
  50.         {"CAR",    (EXTPROC)DsCar,    1, 0},
  51.         {"CDR",    (EXTPROC)DsCdr,    1, 0},
  52.         {"CAAR",   (EXTPROC)DsCaar,   1, 0},
  53.         {"CADR",   (EXTPROC)DsCadr,   1, 0},
  54.         {"CDAR",   (EXTPROC)DsCdar,   1, 0},
  55.         {"CDDR",   (EXTPROC)DsCddr,   1, 0},
  56.         {"CAAAR",  (EXTPROC)DsCaaar,  1, 0},
  57.         {"CAADR",  (EXTPROC)DsCaadr,  1, 0},
  58.         {"CADAR",  (EXTPROC)DsCadar,  1, 0},
  59.         {"CADDR",  (EXTPROC)DsCaddr,  1, 0},
  60.         {"CDAAR",  (EXTPROC)DsCdaar,  1, 0},
  61.         {"CDADR",  (EXTPROC)DsCdadr,  1, 0},
  62.         {"CDDAR",  (EXTPROC)DsCddar,  1, 0},
  63.         {"CDDDR",  (EXTPROC)DsCdddr,  1, 0},
  64.         ENDOFLIST
  65.     };
  66.  
  67. #ifdef MSDOS
  68. void FAR * PASCAL DsFarMalloc(size)
  69. int size;
  70. {
  71.     void FAR *ptr;
  72.     struct SREGS segregs;
  73.  
  74.     ptr=_fmalloc(size);
  75.     if (ISTRUE(ptr))
  76.     {
  77.         segread(&segregs);
  78.         if (segregs.ds==FP_SEG(ptr))        /* don't allocate in data segment */
  79.         {
  80.             _ffree(ptr);
  81.             ptr=NIL;
  82.         }
  83.     }
  84.     return(ptr);
  85. }
  86. #endif
  87.  
  88.  
  89. /*****************************************************************
  90. ** NAME:        DsIniCells
  91. ** SYNOPSIS:    void DsIniCells(numcels)
  92. **              DWORD numcels;
  93. ** DESCRIPTION: Initializes the cell space.
  94. ** RETURNS:     void
  95. *****************************************************************/
  96. void PASCAL DsIniCells(numcels)
  97. DWORD numcels;
  98. {
  99.     GLOB(GCtreshold) = (numcels<25600L) ? 256L : numcels/100L;
  100.     while (numcels>0L)
  101.     {
  102.         DWORD c = min(numcels,6550L);
  103.         DsAllocCells((int)c);
  104.         numcels-=c;
  105.     }
  106.     DsFuncDef(CelFunctions);
  107. }
  108.  
  109.  
  110. /***************************************************************
  111. ** NAME:        DsAllocCells
  112. ** SYNOPSIS:    void DsAllocCells(size)
  113. **              int size;       Number of cells to allocate
  114. ** DESCRIPTION: Allocates an array of new cells. The first cell
  115. **              is used as a link to previously allocated arrays
  116. **              and contains also the array size. The remaining
  117. **              (size less one) cells are linked into the free
  118. **              list. Global variables freecel and GCtreshold
  119. **              are adjusted.
  120. ** RETURNS:     void
  121. ***************************************************************/
  122. void PASCAL DsAllocCells(blocksize)
  123. int blocksize;
  124. {
  125.     CELP p, array;
  126.     int i;
  127.  
  128.     array = FARMALLOC(blocksize,CEL);
  129.     if (ISNIL(array))
  130.         DsMemError("Cell space");
  131.     p = array;                                   /* Address of first new cell */
  132.     TAGpart(p) = TYPE_SPC;                                    /* Default type */
  133.     PROTECT(p);                                    /* set GC flags: protected */
  134.     CARIpart(p) = blocksize;                            /* Remember blocksize */
  135.     CDRpart(p) = GLOB(fblk);                     /* Chain to other cellblocks */
  136.     for (i=1;i<blocksize;i++)                      /* For all cels in a block */
  137.     {                                            /* Except the first and last */
  138.           p++;                                       /* To next cell in block */
  139.           TAGpart(p) = TYPE_FREE;                     /* Free type by default */
  140.           CARpart(p) = NIL;                                  /* Reset to zero */
  141.           CDRpart(p) = p+1;                       /* Point to next free block */
  142.     }                                                   /* Until all is reset */
  143.     CDRpart(p) = GLOB(freel);        /* Modify last cell to point to freelist */
  144.     GLOB(fblk) = array;                             /* Remember pos. of array */
  145.     GLOB(freel) = array+1;                          /* First cell is not free */
  146.     GLOB(freecels) += blocksize-1;                   /* Number of fresh cells */
  147. }
  148.  
  149.  
  150. /***************************************************************
  151. ** NAME:        DsGetCell
  152. ** SYNOPSIS:    CELP DsGetCell()
  153. ** DESCRIPTION: Allocates a new cel. It takes a cel from the
  154. **              free list and returns it. If the freelist is
  155. **              empty the garbage collector is called in. If the
  156. **              garbage collector can't find any free space, an
  157. **              error is raised (ERRMEM).
  158. ** RETURNS:     Pointer to new cel.
  159. ** USES:        DsGarbageCollect, error
  160. ***************************************************************/
  161. CELP PASCAL DsGetCell(typ)
  162. int typ;
  163. {
  164.     register CELP temp;
  165.  
  166.     temp = GLOB(freel);                             /* First free cel in list */
  167.     if (ISNIL(temp))
  168.         DSVERROR(ERRMEM);                         /* No free cells? => error! */
  169.     GLOB(freel) = CDRpart(temp);                /* Remove cell from free list */
  170.     GLOB(freecels)--;
  171.     if (GLOB(freecels)<GLOB(GCtreshold)) GLOB(GCflag)=TRUE;
  172.     TAGpart(temp) = (BYTE)typ;
  173.     GCFpart(temp) = 0;
  174.     CDRpart(temp) = NIL;                          /* unlink from freecel list */
  175.     return(temp);
  176. }
  177.  
  178.  
  179. /***************************************************************
  180. ** NAME:        DsFreeCell
  181. ** SYNOPSIS:    DsFreeCell(item)
  182. **              CELP item       The cel to be released.
  183. ** DESCRIPTION: Releases a cel. In other words the cel is linked
  184. **              into the freelist.
  185. ***************************************************************/
  186. void PASCAL DsFreeCell(temp)
  187. CELP temp;
  188. {
  189.     if (ISTRUE(temp) && TAGpart(temp)!=TYPE_FREE)          /* oke to release? */
  190.     {
  191.         TAGpart(temp) = TYPE_FREE;                              /* Reset type */
  192.         GCFpart(temp) = 0;                                   /* Reset GC flag */
  193.         CARpart(temp) = NIL;                                   /* Reset value */
  194.         CDRpart(temp) = GLOB(freel);            /* Chain in front of freelist */
  195.         GLOB(freel) = temp;
  196.         GLOB(freecels)++;
  197.     }
  198. #ifdef DEBUG
  199.     else
  200.         DsOuts(GLOB(errport),"**** SERIOUS ERROR: Attempted to release free cell\n");
  201. #endif
  202. }
  203.  
  204.  
  205. /***************************************************************
  206. ** NAME:        DsCons
  207. ** SYNOPSIS:    CELP DsCons(A,B);
  208. **              CELP A,B        Pointers to the two pair items
  209. ** DESCRIPTION: Allocates a new cel and initializes it as a pair
  210. **              with the pointers to A and B.
  211. ** RETURNS:     Pointer to the new pair cel.
  212. ***************************************************************/
  213. CELP PASCAL DsCons(a,b)
  214. CELP a,b;
  215. {
  216.     register CELP temp;
  217.  
  218.     temp = GLOB(freel);                             /* First free cel in list */
  219.     if (ISNIL(temp))
  220.         DSVERROR(ERRMEM);                         /* No free cells? => error! */
  221.     GLOB(freel) = CDRpart(temp);                /* Remove cell from free list */
  222.     GLOB(freecels)--;
  223.     if (GLOB(freecels)<GLOB(GCtreshold))
  224.         GLOB(GCflag)=TRUE;
  225.     TAGpart(temp)=TYPE_PAIR;
  226.     GCFpart(temp)=0;
  227.     CARpart(temp)=a;
  228.     CDRpart(temp)=b;
  229.     return(temp);
  230. }
  231.  
  232.  
  233. /***************************************************************
  234. ** NAME:        DsCons1
  235. ** SYNOPSIS:    CELP DsCons1(A);
  236. **              CELP A          Pointer to the car value.
  237. ** DESCRIPTION: Allocates a new cel and initializes it as a pair
  238. **              with the car set to A and the cdr set to NIL.
  239. ** RETURNS:     Pointer to the new pair cel.
  240. ***************************************************************/
  241. CELP PASCAL DsCons1(a)
  242. CELP a;
  243. {
  244.     register CELP temp;
  245.  
  246.     temp = GLOB(freel);                             /* First free cel in list */
  247.     if (ISNIL(temp))
  248.         DSVERROR(ERRMEM);                         /* No free cells? => error! */
  249.     GLOB(freel) = CDRpart(temp);                /* Remove cell from free list */
  250.     GLOB(freecels)--;
  251.     if (GLOB(freecels)<GLOB(GCtreshold))
  252.         GLOB(GCflag)=TRUE;
  253.     TAGpart(temp)=TYPE_PAIR;
  254.     GCFpart(temp)=0;
  255.     CARpart(temp)=a;
  256.     CDRpart(temp)=NIL; 
  257.     return(temp);
  258. }
  259.  
  260.  
  261. CELP PASCAL DsIntCell(l)
  262. LONG l;
  263. {
  264.     CELP p=DsGetCell(TYPE_INT);
  265.     INTpart(p)=l;
  266.     return p;
  267. }
  268.  
  269.  
  270. CELP PASCAL DsFltCell(v)
  271. REAL v;
  272. {
  273.     CELP p=DsGetCell(TYPE_FLT);
  274.     FLTpart(p)=v;
  275.     return p;
  276. }
  277.  
  278.  
  279. CELP PASCAL DsChrCell(c)
  280. int c;
  281. {
  282.     CELP p=DsGetCell(TYPE_CHR);
  283.     CHRpart(p)=c;
  284.     return p;
  285. }
  286.  
  287.  
  288. CELP PASCAL DsPrtCell(prt)
  289. PORT *prt;
  290. {
  291.     CELP p=DsGetCell(TYPE_PRT);
  292.     PRTpart(p)=prt;
  293.     return p;
  294. }
  295.  
  296.  
  297. /***************************************************************
  298. ** NAME:        DsHash
  299. ** SYNOPSIS:    int DsHash(str);
  300. **              CONST char *str;      pointer to input string
  301. ** DESCRIPTION: Hash returns a hash number calculated by hashing
  302. **              the input string and taking the modulo hashsize.
  303. ** RETURNS:     An integer between 0 and glo->hashsize.
  304. ***************************************************************/
  305. STATIC
  306. int PASCAL DsHash(str)
  307. CONST char *str;
  308. {
  309.     register int j=0;
  310.     while (*str)
  311.          j = (j*3 + *str++) % GLOB(hashsize);
  312.     return(j);
  313. }
  314.  
  315.  
  316. /***************************************************************
  317. ** NAME:        DsSymbol
  318. ** SYNOPSIS:    CELP DsSymbol(symstr)
  319. **              char *symbol;   pointer to input string
  320. ** DESCRIPTION: DsSymbol searches for symstr in the symbol
  321. **              table. If it is found the pointer to it is
  322. **              returned, otherwise a new entry is made and
  323. **              filled with the symbol string.
  324. ** RETURNS:     Pointer to existing or new cel containing symbol
  325. ***************************************************************/
  326. CELP PASCAL DsSymbol(symbol)
  327. CONST char *symbol;
  328. {
  329.     int i;
  330.     int symlen;
  331.     CELP p;
  332.  
  333.     i=DsHash(symbol);      /* p points to the first elem of list with symbols */
  334.     symlen=strlen(symbol);                          /* with the same hashcode */
  335.  
  336.     for (p=GLOB(hashtab[i]); ISTRUE(p); p=CDRpart(p))
  337.          if ( (STRLpart(CDARpart(p))==symlen)        /* compare stringlengths */
  338.            && (strncmp(STRPpart(CDARpart(p)),symbol,symlen)==0))   /* compare */
  339.               return(CARpart(p));                                /* Found it! */
  340.     p = DsCons(NIL,DsStrCell(symbol));              /* combine "name" and NIL */
  341.     TAGpart(p) = TYPE_SYM;                             /* default symbol type */
  342.     GLOB(hashtab[i]) = DsCons(p,GLOB(hashtab[i])); /* link to old symbol list */
  343.     return(p);                                    /* return ptr to symbol cel */
  344. }
  345.  
  346.  
  347. /***************************************************************
  348. ** NAME:        DsInsExt
  349. ** SYNOPSIS:    CELP DsInsExt(symstr)
  350. **              char *symbol;   pointer to input string
  351. ** DESCRIPTION: Insertext searches for symstr in the symbol
  352. **              table. If it is found the pointer to it is
  353. **              returned, otherwise a new entry is made and
  354. **              filled with the symbol string.
  355. ** RETURNS:     Pointer to existing or new cel containing symbol
  356. ***************************************************************/
  357. CELP PASCAL DsInsExt(name)
  358. CONST char *name;
  359. {
  360.     int i;
  361.     int symlen;
  362.     CELP p;
  363.  
  364.     i=DsHash(name);          /* p points to the first elem of list with names */
  365.     symlen=strlen(name);                            /* with the same hashcode */
  366.  
  367.     for (p=GLOB(hashtab[i]); ISTRUE(p); p=CDRpart(p))
  368.          if ( (STRLpart(CDARpart(p))==symlen)        /* compare stringlengths */
  369.            && (strncmp(STRPpart(CDARpart(p)),name,symlen)==0))     /* compare */
  370.               return(CARpart(p));                                /* Found it! */
  371.     p = DsGetCell(TYPE_STR);                          /* create a string cell */
  372.     PROTECT(p);
  373.     STRPpart(p) = (char *)name;
  374.     STRLpart(p) = strlen(name);
  375.     p = DsCons(NIL,p);                              /* combine "name" and NIL */
  376.     TAGpart(p)=TYPE_SYM;                                      /* default type */
  377.     GLOB(hashtab[i]) = DsCons(p,GLOB(hashtab[i])); /* link to old symbol list */
  378.     return(p);                                    /* return ptr to symbol cel */
  379. }
  380.  
  381.  
  382. /**************************************************************
  383. ** NAME:        DsListRef
  384. ** SYNOPSIS:    CELP DsListRef(list, num);
  385. **              CELP list;
  386. **              CELP num;
  387. ** DESCRIPTION: Returns the num-th element of the list.
  388. ** RETURNS:     Num-the list element.
  389. **************************************************************/
  390. STATIC
  391. CELP DsListRef(list,num)
  392. CELP list,num;
  393. {
  394.     list=DsListTail(list,num);
  395.     return ISNIL(list) ? NIL : CARpart(list);
  396. }
  397.  
  398.  
  399. /**************************************************************
  400. ** NAME:        DsListTail
  401. ** SYNOPSIS:    CELP DsListTail(list, num);
  402. **              CELP list;
  403. **              CELP num;
  404. ** DESCRIPTION: Returns the tail after the num-th element of
  405. **              the list.
  406. ** RETURNS:     Num-the list element.
  407. **************************************************************/
  408. STATIC
  409. CELP DsListTail(list,num)
  410. CELP list,num;
  411. {
  412.     int n;
  413.  
  414.     for (n=(int)INTpart(num); n>0; n--)
  415.     {
  416.         if (ISNIL(list)) break;
  417.         list=DsCdr(list);
  418.     }
  419.     return list;
  420. }
  421.  
  422.  
  423. /**************************************************************
  424. ** NAME:        DsAppend
  425. ** SYNOPSIS:    CELP DsAppend(list, p);
  426. **              CELP list;
  427. **              CELP p;
  428. ** DESCRIPTION: Appends p to the end of the list.
  429. ** RETURNS:     Same list with p appended.
  430. **************************************************************/
  431. STATIC
  432. CELP DsAppend(list,p)
  433. CELP list,p;
  434. {
  435.     CELP q,pq;
  436.  
  437.     if (ISNIL(list)) return p;
  438.     pq=list;
  439.     q=DsCdr(pq);
  440.     while (ISTRUE(q))
  441.     q=DsCdr(pq=q);
  442.     CDRpart(pq)=p;
  443.     return list;
  444. }
  445.  
  446. STATIC
  447. CELP Ds_Append(list,p)
  448. CELP list,p;
  449. {
  450.     CELP pq,q,np,fp;
  451.  
  452.     pq=list;
  453.     if (ISNIL(list)) return p;
  454.     q=DsCdr(pq);
  455.     np=fp=DsGetCell(TYPE_PAIR);
  456.     CARpart(np)=CARpart(pq);
  457.     while (ISTRUE(q))
  458.     {
  459.     q=DsCdr(pq=q);
  460.     np=CDRpart(np)=DsGetCell(TYPE_PAIR);
  461.     CARpart(np)=CARpart(pq);
  462.     }
  463.     CDRpart(np)=p;
  464.     return fp;
  465. }
  466.  
  467. /***************************************************************
  468. ** NAME:        Ds_length
  469. ** SYNOPSIS:    CELP Ds_length(list)
  470. **              CELP list;      List
  471. ** DESCRIPTION: Calculates the length of the list
  472. ** RETURNS:     The length.
  473. ***************************************************************/
  474. CELP Ds_length(l)
  475. CELP l;
  476. {
  477.     return DSINTCEL(DsLength(l));
  478. }
  479.  
  480.  
  481. /***************************************************************
  482. ** NAME:        Ds_reverse
  483. ** SYNOPSIS:    CELP Ds_reverse(list)
  484. **              CELP list;      list to be reversed
  485. ** DESCRIPTION: Reverses the list.
  486. ** RETURNS:     The reversed list.
  487. ***************************************************************/
  488. STATIC
  489. CELP Ds_reverse(list)
  490. CELP list;
  491. {
  492.     CELP cp=NIL;
  493.     for ( ;ISTRUE(list); list=CDRpart(list))
  494.         cp=DsCons(DsCar(list),cp);
  495.     return(cp);
  496. }
  497.  
  498.  
  499. /***************************************************************
  500. ** NAME:        DsCar, DsCdr, ..., DsCdddr
  501. ** SYNOPSIS:    CELP DsCar(A);
  502. **              CELP A;             Pointers to a list item.
  503. ** DESCRIPTION: These work all like the SCHEME functions CAR,
  504. **              CDR, etc. When the car or cdr is taken from an
  505. **              atom, the error function is called. The
  506. **              arguments of car and cdr may be a pair, lambda
  507. **              procedure or macro definitions.
  508. ** EXAMPLES:    (car (1 2 3))               ==> 1
  509. **              (cdr (1 2 3))               ==> (2 3)
  510. **              (define sum
  511. **                 (lambda (x y) (+ x y)))  ==> #PROC
  512. **              (car sum)                   ==> [(x . y), 2, 0]
  513. **              (cadr sum)                  ==> ((+ x y))
  514. **              (cddr sum)                  ==> proc.environment
  515. ** RETURNS:     Pointer to the car or cdr.
  516. ***************************************************************/
  517. #define getCAR(l)  ISCAR(l)?(l)->dat.pair.car:DSERROR(ERRCAR,l)
  518. #define getCDR(l)  ISCAR(l)?(l)->dat.pair.cdr:DSERROR(ERRCDR,l)
  519. #define testCAR(l) if (!ISCAR(l)) DSERROR(ERRCAR,l)
  520. #define testCDR(l) if (!ISCAR(l)) DSERROR(ERRCDR,l)
  521.  
  522. CELP DsCar(l)
  523. CELP l;
  524. {
  525.     testCAR(l);
  526.     return(CARpart(l));
  527. }
  528.  
  529. CELP DsCdr(l)
  530. CELP l;
  531. {
  532.     testCDR(l);
  533.     return(CDRpart(l));
  534. }
  535.  
  536. CELP DsCaar(l)
  537. CELP l;
  538. {
  539.     testCAR(l);
  540.     l=CARpart(l);
  541.     testCAR(l);
  542.     return(CARpart(l));
  543. }
  544.  
  545. CELP DsCadr(l)
  546. CELP l;
  547. {
  548.     testCDR(l);
  549.     l=CDRpart(l);
  550.     testCAR(l);
  551.     return(CARpart(l));
  552. }
  553.  
  554. CELP DsCdar(l)
  555. CELP l;
  556. {
  557.     testCAR(l);
  558.     l=CARpart(l);
  559.     testCDR(l);
  560.     return(CDRpart(l));
  561. }
  562.  
  563. CELP DsCddr(l)
  564. CELP l;
  565. {
  566.     testCDR(l);
  567.     l=CDRpart(l);
  568.     testCDR(l);
  569.     return(CDRpart(l));
  570. }
  571.  
  572. CELP DsCaaar(l)
  573. CELP l;
  574. {
  575.     return(DsCar(DsCaar(l)));
  576. }
  577.  
  578. CELP DsCaadr(l)
  579. CELP l;
  580. {
  581.     return(DsCar(DsCadr(l)));
  582. }
  583.  
  584. CELP DsCadar(l)
  585. CELP l;
  586. {
  587.     return(DsCar(DsCdar(l)));
  588. }
  589.  
  590. CELP DsCaddr(l)
  591. CELP l;
  592. {
  593.     return(DsCar(DsCddr(l)));
  594. }
  595.  
  596. CELP DsCdaar(l)
  597. CELP l;
  598. {
  599.     return(DsCdr(DsCaar(l)));
  600. }
  601.  
  602. CELP DsCdadr(l)
  603. CELP l;
  604. {
  605.     return(DsCdr(DsCadr(l)));
  606. }
  607.  
  608. CELP DsCddar(l)
  609. CELP l;
  610. {
  611.     return(DsCdr(DsCdar(l)));
  612. }
  613.  
  614. CELP DsCdddr(l)
  615. CELP l;
  616. {
  617.     return(DsCdr(DsCddr(l)));
  618. }
  619.  
  620.  
  621. /***************************************************************
  622. ** NAME:        DsRelease
  623. ** SYNOPSIS:    void DsRelease(p);
  624. **              CELP p;   cells to be release
  625. ** DESCRIPTION: Releases this cell and recursively all cells
  626. **              chained to it.
  627. ** RETURNS:     void
  628. ***************************************************************/
  629. void PASCAL DsRelease(p)
  630. CELP p;
  631. {
  632.     if (ISNIL(p)) return;
  633.     switch(TAGpart(p))
  634.     {
  635.     case TYPE_STR:
  636.     case TYPE_VEC:
  637.         DsFreeBuf(STRPpart(p));
  638.     break;
  639. #ifdef GCPORTS
  640.     case TYPE_PRT:
  641.         DsClosePort(CELPRT(q));         /* close before cell is released */
  642.     break;
  643. #endif
  644.      default:
  645.          if (_ISCAR(p)) DsRelease(CARpart(p));
  646.          if (_ISCDR(p)) DsRelease(CDRpart(p));
  647.      }
  648.      DsFreeCell(p);
  649. }
  650.  
  651.  
  652. /***************************************************************
  653. ** NAME:        DsProtect
  654. ** SYNOPSIS:    void DsProtect(p);
  655. **              CELP p;         cell to be protected
  656. ** DESCRIPTION: Protect this cell and recursively all cells
  657. **              chained to it.
  658. ** RETURNS:     void
  659. ***************************************************************/
  660. void PASCAL DsProtect(p)
  661. CELP p;
  662. {
  663.     while (ISTRUE(p) && !MARKED(p))
  664.     {
  665. #ifdef GCPORTS
  666.         if (TAGpart(p)==TYPE_PRT) CELPRT(p)->dir |= GCMARK; /* port is used */
  667. #endif
  668.         PROTECT(p);
  669.         if (_ISCAR(p)) DsProtect(CARpart(p));
  670.         if (!_ISCDR(p)) return;
  671.         p=CDRpart(p);
  672.     }
  673. }
  674.  
  675.  
  676. /***************************************************************
  677. ** NAME:        DsGarbageCollect
  678. ** SYNOPSIS:    DWORD DsGarbageCollect(p)
  679. **              CELP p;         A cell to be protected.
  680. ** DESCRIPTION: Performs a garbage collect on the DScheme memory
  681. **              All cells not used anymore, or accessible are
  682. **              released. Port not used anymore are closed and
  683. **              strings are released to the string space.
  684. ** RETURNS:     Number of released cells.
  685. ***************************************************************/
  686. DWORD PASCAL DsGarbageCollect(cels)
  687. CELP cels;
  688. {
  689.     CELP p, FAR *sp;
  690.     int i;
  691.     DWORD oldnum=GLOB(freecels);
  692.     void (*oldsig)();
  693.  
  694.     DSGCmessage(GCstart);
  695.     oldsig=signal(SIGINT, SIG_IGN);              /* Disable Control-C handler */
  696.     DsMark(cels);                                            /* mark argument */
  697.     DsMark(GLOB(curargs));
  698.     DsMark(GLOB(curenv));                    /* mark all cells which are used */
  699.     DsMark(GLOB(curexp));
  700.     for (p=GLOB(freel); ISTRUE(p); p=CDRpart(p))
  701.         SETMARK(p);                           /* mark all cells in free list. */
  702.     for (i=0;i<GLOB(hashsize);i++)               /* mark all symbols as used! */
  703.         DsMark(GLOB(hashtab[i]));
  704.     for (sp=GLOB(sstack);sp<GLOB(stkptr);sp++)
  705.         DsMark(*sp);                        /* mark all cells pushed on stack */
  706.     DsCollect();                                /* Collect all unmarked cells */
  707.     if ((GLOB(GCflag)&2) || DsFragmented()) 
  708.         DsBufDefrag();                       /* Defragmatise the string space */
  709.     DSGCmessage(GCstop);
  710.     GLOB(GCflag)=FALSE;
  711.     signal(SIGINT, oldsig);                       /* Enable Control-C handler */
  712.     return(GLOB(freecels)-oldnum);
  713. }
  714.  
  715.  
  716. /***************************************************************
  717. ** NAME:        DsMark
  718. ** SYNOPSIS:    void DsMark(p);
  719. **              CELP p;         cell to be DsMarked.
  720. ** DESCRIPTION: DsMarks this cell and recursively all cells
  721. **              chained to it.
  722. ** RETURNS:     void
  723. ***************************************************************/
  724. void PASCAL DsMark(p)
  725. CELP p;
  726. {
  727.     for (; ISTRUE(p) && (!MARKED(p)); p=CDRpart(p))
  728.     {
  729.         SETMARK(p);
  730. #ifdef GCPORTS
  731.         if (TAGpart(p)==TYPE_PRT) CELPRT(p)->dir |= GCMARK; /* port is used */
  732. #endif
  733.         if (_ISCAR(p)) DsMark(CARpart(p));
  734.         if (!_ISCDR(p)) return;
  735.     }
  736. }
  737.  
  738.  
  739. /***************************************************************
  740. ** NAME:        DsCollect
  741. ** SYNOPSIS:    void DsCollect()
  742. ** DESCRIPTION: Collect all not DsMarked cells and releases them
  743. **              to the free cell space. All DsMarked cells are
  744. **              unDsMarked.
  745. ** RETURNS:     void
  746. ***************************************************************/
  747. void PASCAL DsCollect()
  748. {
  749.     int i;
  750.     CELP p,q;
  751.  
  752.     for (p=GLOB(fblk); ISTRUE(p); p=CDRpart(p))
  753.     {
  754.         DSGCmessage(GCrun);
  755.         q=p;
  756.         for (i=(int)CARIpart(p)-1;i>0;i--)
  757.         {
  758.             if (!MARKED(++q))                      /* Not marked=> release it */
  759.             {
  760.                 switch (TAGpart(q))
  761.                 {
  762.                 case TYPE_VEC:
  763.                 case TYPE_STR:
  764.             DsFreeBuf(STRPpart(q));
  765.                     break;
  766. #ifdef GCPORTS
  767.                 case TYPE_PRT:
  768.                     if (!(CELPRT(q)->dir&GCMARK)) /* close only it isn't used */
  769.                         DsClosePort(CELPRT(q));/*close before cel is released */
  770. #endif
  771.                 }
  772.                 DsFreeCell(q);
  773.             }
  774.         }
  775.     }
  776.     DSGCmessage(GCrun);
  777.     for (p=GLOB(fblk); ISTRUE(p); p=CDRpart(p))
  778.     {
  779.         q=p;
  780.         for (i=(int)CARIpart(p)-1;i>0;i--) UNMARK(++q);
  781.     }
  782. #ifdef GCPORTS
  783.     for (i=GLOB(prtnum);i>0;i--) GLOB(ports)[i].dir &= ~GCMARK;
  784. #endif
  785. }
  786.