! Utility routines to obtain the information in the $UserData file.  This
! file is assumed to be sorted by username, so that a binary search can be
! used for speed.  For now we don't use the standard Imp RTL.

%include "GDMR_H:IO_F.Inc"

%systemroutinespec phex(%integer x)

%owninteger token1 = 0, token2 = 0, size = 0, flags = 0

%recordformat buffer fm(%bytearray x(0 : 511))
%ownrecord(buffer fm) buffer
%owninteger pos = -1, buffer start = 0, buffer end = -1

%predicate open database
   %string(255) textual response
   %integer status
      %true %if token1 # 0;  ! Already open
      {} printstring("Open $UserData");  newline
      ! Database isn't open yet
      status = F open file(nil, "$UserData", read file mode, read file mode, 0,
                           token1, token2, size, flags, textual response)
      %if status # 0 %start
         printstring("Open $UserData fails: ");  printstring(textual response)
         newline
         %false
      %finish
      {} printstring("Opened: ");  phex(token1);  space
      {} phex(token2);  newline
      buffer start = 0;  buffer end = -1
      pos = 0
      %true
%end

%integerfn next sym
   %string(255) textual response
   %integer status, start, bytes, x
      %unless buffer start <= pos <= buffer end %start
         ! Wrong block, so we'll have to fetch it
         {} printstring("Fetch: ");  write(pos, 0);  space
         {} write(buffer start, 0);  space;  write(buffer end, 0)
         {} space;  write(size, 0);  newline
         %signal 9, 9, pos %if pos >= size;  ! EOF
         start = pos & (\ 511);  ! Lose offset
         status = F read block(nil, token1, token2, start, bytes, buffer,
                               textual response)
         %if status # 0 %start
            printstring("Read $UserData at ");  write(start, 0)
            printstring(" fails: ");  printstring(textual response);  newline
            %signal 9, 9, pos
         %finish
         buffer start = start
         buffer end = start + bytes - 1
      %finish
      x = buffer_x(pos - buffer start)
      {} write(pos, 0);  space;  print symbol(x);  newline
      pos = pos + 1
      %result = x
%end

%routine close database
   %string(255) textual response
   %integer status
      %return %if token1 = 0;  ! Not open
      {} printstring("Close $UserData");  newline
      status = F close file(nil, token1, token2, 0, textual response)
      %if status # 0 %start
         printstring("Close $UserData fails: ");  printstring(textual response)
         newline
      %finish
      token1 = 0;  token2 = 0
%end

%routine get user data(%string(15) user, %string(*)%name home, full name)
   ! Eventually we'll use a binary search here....
   %string(255) current user
   %bytename x
   %integer sym, i, quoted = 0
      %on 9 %start
         close database
         %return
      %finish
      {} printstring("Get for ");  printstring(user);  newline
      home = "";  full name = ""
      %return %if user = ""
      %return %unless open database
      %for i = 1, 1, length(user) %cycle
         x == charno(user, i)
         x = x - 'a' + 'A' %if 'a' <= x <= 'z'
      %repeat
      %cycle
         current user = ""
         sym = next sym %until sym > ' ';  ! Blank lines, leading white space
         %while sym = '!' %cycle
            ! Skip comments: first the rest of this line
            sym = next sym %while sym # NL
            ! Then the white space at the start of the next
            sym = next sym %until sym > ' '
         %repeat
         %while sym > ' ' %cycle
            sym = sym - 'a' + 'A' %if 'a' <= sym <= 'z'
            current user = current user . to string(sym)
            sym = next sym
         %repeat
         {} printstring("Current user: ");  printstring(current user);  newline
         %if current user = user %start
            sym = next sym %while sym <= ' '
            %while sym > ' ' %cycle
               home = home . to string(sym)
               sym = next sym
            %repeat
            {} printstring("Home: ");  printstring(home);  newline
            sym = next sym %while sym # '"'
            sym = next sym
            %while sym # '"' %cycle
               full name = full name . to string(sym)
               sym = next sym
            %repeat
            close database
            %return
         %else
            ! Not this one, so skip the rest of the line
            sym = next sym %while sym # NL
         %finish
      %repeat
%end

%begin
   %string(255) user, home, name
      %on 9 %start;  %stop;  %finish
      %cycle
         read(user)
         get user data(user, home, name)
         printstring(home);  space;  printstring(name);  newline
      %repeat
%end

%end %of %file
