home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v92.tgz / v92.tar / v92 / src / runtime / ocat.r < prev    next >
Text File  |  1996-03-22  |  3KB  |  118 lines

  1. /*
  2.  * File: ocat.r -- caterr, lconcat
  3.  */
  4. "x || y - concatenate strings x and y." 
  5.  
  6. operator{1} || cater(x, y)
  7.  
  8.    if !cnv:string(x) then
  9.       runerr(103, x)
  10.    if !cnv:string(y) then
  11.       runerr(103, y)
  12.  
  13.    abstract {
  14.       return string
  15.       }
  16.  
  17.    body {
  18.       char *s, *s2;
  19.       word len, i;
  20.  
  21.       /*
  22.        *  Optimization 1:  The strings to be concatenated are already
  23.        *   adjacent in memory; no allocation is required.
  24.        */
  25.       if (StrLoc(x) + StrLen(x) == StrLoc(y)) {
  26.          StrLoc(result) = StrLoc(x);
  27.          StrLen(result) = StrLen(x) + StrLen(y);
  28.          return result;
  29.          }
  30.       else if ((StrLoc(x) + StrLen(x) == strfree)
  31.       && (DiffPtrs(strend,strfree) > StrLen(y))) {
  32.          /*
  33.           * Optimization 2: The end of x is at the end of the string space.
  34.           *  Hence, x was the last string allocated and need not be
  35.           *  re-allocated. y is appended to the string space and the
  36.           *  result is pointed to the start of x.
  37.           */
  38.      result = x;
  39.      /*
  40.       * Append y to the end of the string space.
  41.       */
  42.      Protect(alcstr(StrLoc(y),StrLen(y)), runerr(0));
  43.      /*
  44.       *  Set the length of the result and return.
  45.       */
  46.      StrLen(result) = StrLen(x) + StrLen(y);
  47.      return result;
  48.          }
  49.  
  50.       /*
  51.        * Otherwise, allocate space for x and y, and copy them
  52.        *  to the end of the string space.
  53.        */
  54.       Protect(StrLoc(result) = alcstr(NULL, StrLen(x) + StrLen(y)), runerr(0));
  55.       s = StrLoc(result);
  56.       s2 = StrLoc(x);
  57.       len = StrLen(x);
  58.       for(i = 0; i < len; i++)
  59.      *s++ = *s2++;
  60.       s2 = StrLoc(y);
  61.       len = StrLen(y);
  62.       for(i = 0; i < len; i++)
  63.      *s++ = *s2++;
  64.  
  65.       /*
  66.        *  Set the length of the result and return.
  67.        */
  68.       StrLen(result) = StrLen(x) + StrLen(y);
  69.       return result;
  70.       }
  71. end
  72.  
  73.  
  74. "x ||| y - concatenate lists x and y."
  75.  
  76. operator{1} ||| lconcat(x, y)
  77.    /*
  78.     * x and y must be lists.
  79.     */
  80.    if !is:list(x) then
  81.       runerr(108, x)
  82.    if !is:list(y) then
  83.       runerr(108, y)
  84.  
  85.    abstract {
  86.       return new list(store[(type(x) ++ type(y)).lst_elem])
  87.       }
  88.  
  89.    body {
  90.       register struct b_list *bp1, *bp2;
  91.       register struct b_lelem *lp1, *lp2;
  92.       word size1, size2, size3;
  93.  
  94.       /*
  95.        * Get the size of both lists.
  96.        */
  97.       size1 = BlkLoc(x)->list.size;
  98.       size2 = BlkLoc(y)->list.size;
  99.       size3 = size1 + size2;
  100.  
  101.       Protect(bp1 = (struct b_list *)alclist(size3), runerr(0));
  102.       Protect(lp1 = (struct b_lelem *)alclstb(size3,(word)0,size3), runerr(0));
  103.       bp1->listhead = bp1->listtail = (union block *)lp1;
  104.  
  105.       /*
  106.        * Make a copy of both lists in adjacent slots.
  107.        */
  108.       cpslots(&x, lp1->lslots, (word)1, size1 + 1);
  109.       cpslots(&y, lp1->lslots + size1, (word)1, size2 + 1);
  110.  
  111.       BlkLoc(x) = (union block *)bp1;
  112.  
  113.       EVValD(&x, E_Lcreate);
  114.  
  115.       return x;
  116.       }
  117. end
  118.