! General utility procedures

%option "-nocheck-nostack-low"

!%include "Config.Inc"
!
!%include "System:Common"
!%include "System:Errors.Inc"
!%include "System:Schedule.Inc"
!
!%include "Inc:Util.Imp"
!%include "Inc:FS.Imp"


! Unpack filenames.  Radix-40 used throughout the
! file system, both for filenames and for usernames.

%constbytearray pchar(0 : 39) =
   '#', 'A', 'B', 'C',  'D', 'E', 'F', 'G',
   'H', 'I', 'J', 'K',  'L', 'M', 'N', 'O',
   'P', 'Q', 'R', 'S',  'T', 'U', 'V', 'W',
   'X', 'Y', 'Z', '_',  '0', '1', '2', '3',
   '4', '5', '6', '7',  '8', '9', '.', '$'

%constinteger dollars = 16_F9FF

%externalstring(31)%fn unpack(%integer p1, p2)

   %string(3)%fn unpack3(%integer p, z1, z2, z3)
      ! unpack one 16-bit portion
      %bytearray u(1 : 3)
      %string(3) s = ""
      %integer i, q, r, last, it
         %result = "" %if p = 0 %and z1 = 0 %and z2 = 0 %and z3 = 0
         %result = "***" %unless 0 <= p <= dollars
         %for i = 3, -1, 1 %cycle
            q = p // 40
            r = p - 40 * q
            u(i) = r
            p = q
         %repeat
         last = z1 ! z2 ! z3
         %for i = 3, -1, 1 %cycle
            it = u(i)
            s = to string(pchar(it)) . s %if it # 0 %or last # 0
            last = it %if last = 0
         %repeat
         %result = s
   %end

   %integer x1, x2, x3, x4
      %result = "*bad*" %if p1 = -1
      %result = "?zero?" %if p1 = 0 %and p2 = 0
      x1 = p1 >> 16;  x2 = p1 & 16_FFFF
      x3 = p2 >> 16;  x4 = p2 & 16_FFFF
      %result = unpack3(x1, x2, x3, x4) . %c
                unpack3(x2, x3, x4,  0) . %c
                unpack3(x3, x4,  0,  0) . %c
                unpack3(x4,  0,  0,  0)
%end


! Convert the date into a printable form.
! (This %must surely be a well-known algorithm??)

%externalstring(15)%fn unpack date(%short date)
   %owninteger last unpacked = -1
   %ownbytearray s(0 : 8)
   %integer d, m, y
      %if date # last unpacked %start
         last unpacked = date
         d = (date + 21000) << 2 - 1
         y = d // 1461 + 1
         d = rem(d, 1461)
         d = ((d + 4) >> 2) * 5 - 3
         m = d // 153 - 9
         %if m <= 0 %start
            m = m + 12;  y = y - 1
         %finish
         d = (rem(d, 153) + 5) // 5
         s(0) = 8
         s(1) = d // 10 + '0'
         s(2) = rem(d, 10) + '0'
         s(3) = '/'
         s(4) = m // 10 + '0'
         s(5) = rem(m, 10) + '0'
         s(6) = '/'
         s(7) = y // 10 + '0'
         s(8) = rem(y, 10) + '0'
      %finish
      %result = string(addr(s(0)))
%end


! This one is easy -- just converts minutes to hours and minutes.

%externalstring(7)%fn unpack time(%short time)
   %bytearray b(0 : 5)
   %integer h, m
      h = time // 60
      m = rem(time, 60)
      b(0) = 5
      b(1) = h // 10 + '0'
      b(2) = rem(h, 10) + '0'
      b(3) = '.'
      b(4) = m // 10 + '0'
      b(5) = rem(m, 10) + '0'
      %result = string(addr(b(0)))
%end


! Dummy

%externalroutine pdate
%end

%end %of %file
