!***************************************************************************
!*                                                                         *
!* Program to generate an inventory of APM bits & pieces from MANAGR:NS.DAT*
!* Takes managr:ns.dat as input.  Single optional parameter is output file *
!*                                                                         *
!*                  Version 1.2    8 Dec 1987                              *
!*                                                                         *
!***************************************************************************

!1.2: uses modified NS recordformat (inon and room merged, new bootfs field)

include  "managr:nsdefs.inc"
include  "inc:fs.imp"
include  "inc:util.imp"
include  "managr:ns.inc"

conststring  (31) data file = "managr:ns.dat"
constinteger  locn = 1, peripherals = 2, shortname=4, longname=8,all = 255
constinteger  ff=12

conststring  (31) array  peripheral(0:25) = c 
{A} "0.5Mb memory board",       {B} "68010 processor board",
{C} "8MHz processor board",     {D} "10MHz processor board",
{E} "2MHz Ethernet board",      {F} "10MHz Ethernet board",
{G} "Level 1 graphics board",   {H} "Level 1.5 graphics board",
{I} "?MHz processor board",     {J} "level 2 graphics board",
{K} "K???",                     {L} "2.0Mb memory board",
{M} "Mouse controller",         {N} "N???",
{O} "O???",                     {P} "Laser printer controller",
{Q} "QSART board",              {R} "RTS interface board",
{S} "Special board",            {T} "T???",
{U} "U???",                     {V} "V???",
{W} "W???",                     {X} "MIT graphics monitor",
{Y} "Unknown monitor",          {Z} "Twin 3 inch Floppy-Disks"

begin 
integer  size,start,dte,i,j, k
record  (ns lfm) name  data
record  (ns fm) name  file
ownintegerarray  list(0:127) = 0(*)
ownintegerarray  boardtot(0:127) = 0(*)
ownintegerarray  boardlist(0:25, 0:127) = 0(*)
ownintegerarray  freelist(0:127) = 0(*)
owninteger  cases=0, lastcase=-1, freestns = 0
string  (255) outfile
bytearray  sname(0:8)

integerfn  hex(string  (*) name  s)
   integer  i,no,a
   no=0
   for  i=1,1,length(s) cycle 
      a=charno(s,i); a=a-' ' if  'a'<=a<='z'; a=a-'0'
      a=a-7 if  a>9
      exit  unless  0<=a<=15
      no=no<<4+a
   repeat 
   result =no
end 

routine  dump location(integer  dte, qualifier)
   integer  i, j, tag
   record  (ns lfm) name  data
   phex2(dte); spaces(2)
   data == file_l(dte)

   if  qualifier & shortname # 0 start 
      for  i=1,1,7 cycle 
         printsymbol(file_s(dte)_d(i))
      repeat 
      space
   finish 

   if  qualifier & locn # 0 start 
      for  i=1,1,4 cycle ; printsymbol(data_add(i)); repeat 
      space
   finish 

   if  qualifier & peripherals # 0 start 
      for  i=1,1,18 cycle 
         printsymbol(data_bpmap(i))
      repeat 
      space
   finish 

   if  qualifier & longname # 0 start 
      tag = data_inonrm>>4
      if  tag = ns in start 
         printstring("In ")
      elseif  tag = ns on
         printstring("On ")
      elseif  tag = ns at
         printstring("At ")
      finish 
      
      tag = data_inonrm & 15
      printstring("the ") if  tag = ns the
      
      for  j=31,-1,1 cycle ; exit  if  data_lname(j) > ' '; repeat 
      for  i=1,1,j cycle ; printsymbol(data_lname(i)); repeat 
      printstring("'s room") if  data_inonrm = ns room
   finish 

   newline
end 

routine  casesort(integerarrayname  data, integer  entries)
   !Sort integer array data, throughout its length
    integer  i,j,k,l,n1, temp

      integerfn  s(integer  dte)
         result  = file_l(data(dte))_case
      end 

      n1 = 1
      l = entries - 2
      n1 = 2*n1 while  n1<l
      l = 0
       while  n1 > 1 cycle 
         n1 = n1 // 2
         i = l
          cycle 
            i = i+1
            j = i+n1
             exitif  j > entries
            k = i
             cycle 
                exitif  s(j) > s(k)
                temp = data(j); data(j) = data(k); data(k)= temp
               j = k
               k = k - n1
             repeatuntil  k < 1
          repeat 
       repeat 
    end                  ; ! of routine CASESORT

routine  locnsort(integerarrayname  data, integer  entries)
   !Sort integer array data, throughout its length
    integer  i,j,k,l,n1, temp

      integerfn  s(integer  dte)
         integer  i, no
         no=0
         for  i=1,1,4 cycle 
            no = no<<8+file_l(data(dte))_add(i)
         repeat 
         result =no
      end 

      n1 = 1
      l = entries - 2
      n1 = 2*n1 while  n1<l
      l = 0
       while  n1 > 1 cycle 
         n1 = n1 // 2
         i = l
          cycle 
            i = i+1
            j = i+n1
             exitif  j > entries
            k = i
             cycle 
                exitif  s(j) > s(k)
                temp = data(j); data(j) = data(k); data(k)= temp
               j = k
               k = k - n1
             repeatuntil  k < 1
          repeat 
       repeat 
    end                  ; ! of routine LOCNSORT

predicate  assigned(integer  dte)
   integer  i
   true  if  file_l(dte)_case # 0
   for  i=1,1,16 cycle 
     true  if  file_l(dte)_bpmap(i) # '.'
   repeat 
   true  if  file_l(dte)_bpmap(17) # '*' or  file_l(dte)_bpmap(18) # '*'
   false 
end 


outfile = cliparam
if  outfile # "" and  outfile # ":" start 
   open output(1, outfile); selectoutput(1)
finish 
printline("APM inventory on ".date." at ".time.".  Source file: ".data file)

connect file(data file, 0, start, size)
file == record(start)
printline("""".file_comment.""""); newlines(2)

printsymbol(ff); printline("APMs by Station number"); newlines(2)

for  dte=1,1,max addr cycle 
   if  assigned(dte) start 
      dump location(dte, all)
   else 
      freestns=freestns+1
      freelist(freestns) = dte
   finish 
repeat 

printsymbol(ff); printline("APMs by location"); newlines(2)

for  dte=0,1,max addr cycle 
   list(dte) = dte
repeat 
locnsort(list, max addr)
for  i=1,1,max addr cycle 
   dump location(list(i), all) if  assigned(list(i))
repeat 
newline

write(freestns, -1); printline(" Unallocated Stations:"); newline
for  i=0,1,7 cycle 
   for  j=0,1,15 cycle 
      phex2(freelist(i*16+j+1)); space
      -> finished if  i*16+j+1 = freestns
   repeat 
   newline
repeat 
finished:
newlines(2)

for  dte=0,1,max addr cycle 
   data == file_l(dte)
   if  data_case#0 start 
      cases=cases+1; list(cases)=dte
   finish 
   for  i=1,1,18 cycle 
      j = data_bpmap(i); j=j-'a'+'A' if  'a'<=j<='z'
      if  'A'<=j<='Z' start 
         j=j-'A'
         boardtot(j)=boardtot(j)+1
         boardlist(j, boardtot(j)) = dte
      finish 
   repeat 
repeat 

newline; write(cases, -1); printline(" cases:"); newline

casesort(list, cases)
lastcase=-1

for  i=1,1,cases cycle 
   dte = list(i)
   write(file_l(dte)_case, 3); spaces(2); dump location(dte, locn ! longname)
   if  file_l(dte)_case = lastcase start 
      printline("*** This case assigned twice ***")
   finish 
   lastcase = file_l(dte)_case
repeat 
newline

for  j=0,1,25 cycle 
   k = boardtot(j)
   if  k # 0 start 
      write(k, 3); space
      printstring(peripheral(j))
      printsymbol('s') if  k>1
      newline
      for  i=1,1,k cycle 
         dte = boardlist(j, i)
         dump location(dte, locn ! longname)
      repeat 
      newline
   finish 
repeat 

printsymbol(ff); printstring("Peripherals listed by APM"); newlines(2)

for  dte=1,1,127 cycle 
   printstring("Station "); dump location(dte, ¬peripherals)
   
   if  file_l(dte)_case # 0 or  file_l(dte)_bpmap(1) # '.' start 
      printstring("   Recorded Peripherals for case")
      write(file_l(dte)_case,3); printline(":")
      for  i=1,1,18 cycle 
         if  file_l(dte)_bpmap(i) # '.' and  file_l(dte)_bpmap(i) # '*' then  C 
         printline("      ".peripheral(file_l(dte)_bpmap(i)-'A'))
      repeat 
   finish 
   newline
repeat 

endofprogram