	function memtab_init(control,block_pointer,name)
	implicit none
c
	include 'dix_memtab.inc'
c
	record /control/ control
	integer*4 block_pointer
	character*(*) name
	integer memtab_init
c#
	record /memtab/ memtab
	pointer (p_memtab,memtab)
c
	record /vm_zone/ zone_mem
c
	integer*4 istat
c
	block_pointer = 0
	call init_vm(control,zone_mem,0,'MMT_'//name,.false.)
c
c Get a control block and init
c
	call get_vm(control,sizeof(memtab),p_memtab,
     1              zone_mem,.false.,'MEMTAB_CONTROL')
	block_pointer   = p_memtab
	memtab.zone_mem = zone_mem
c
	control.n_memfiles_opened = control.n_memfiles_opened + 1
c
c Now correct the link pointers
c  link out the old one
c
	call dix_util_link_out(zone_mem.link,control.top_vm_zones)
c
c And link in the new one
c
	call dix_util_link_in(memtab.zone_mem.link,control.top_vm_zones)
c
	memtab.magic    = memtab_magic
        memtab.p_first  = 0
	memtab.n_lines  = 0
	memtab.max_width= 0
	memtab.p_last   = 0
	memtab.n_labels = 0
	memtab.p_labels = 0
c
	istat = 1
	memtab_init = istat
	return
	end
	function memtab_open(control,filename,block_pointer,nlines)
	implicit none
c
	include 'dix_memtab.inc'
	record /control/ control	!:i: control block
	character*(*) filename		!:i: the file to readin
	integer*4 block_pointer		!:o: the pointer to a control block
	integer*4 nlines		!:o: #lines read
	integer*4 memtab_open		!:f: the function result
c#
        integer*4 lun,istat
c
	integer*4 memtab_open_lun
c	
	call lib$get_lun(lun)
c
        block_pointer = 0	!make sure 0
	nlines = 0
	open(lun,file=filename,status='old',
     1           defaultfile='.dix',readonly,err=85)
	istat = memtab_open_lun(control,lun,block_pointer,nlines)
	close(lun)
	goto 90
c
c here for file open error
c
85	call errsns(,istat)
c
c General exit
c
90	call lib$free_lun(lun)
	memtab_open = istat
	return
	end
	function memtab_open_lun(control,lun,block_pointer,nlines)
	implicit none
c
	include 'dix_memtab.inc'
	record /control/ control	!:i: control  block
	integer*4 lun			!:i: the lun on which the file is open
	integer*4 block_pointer		!:o: the pointer to a control block
	integer*4 nlines		!:o: #lines read
	integer*4 memtab_open_lun	!:f: the function result
c#
	record /memtab/ memtab
	pointer (p_memtab,memtab)
c
        integer*4 istat,nk
	character*(max_line_length) line
c
	integer*4 memtab_init
	integer*4 memtab_add_record
	integer*4 dix_util_get_len_fu
c
c	
        block_pointer = 0	!make sure 0
	nlines = 0
c
	inquire (lun,name=line)
	nk = dix_util_get_len_fu(line)
	istat = memtab_init(control,block_pointer,line(1:nk))
	if(.not. istat) goto 90
	p_memtab = block_pointer
c
c We have a valid block, start reading
c
	memtab.filename = line(1:nk)
	memtab.nk_filename = nk
c
c Start reading lines,
c
	istat = 1
	do while(istat)
	  read(lun,2000,end=50,err=70) nk,line
2000	  format(q,a)
	  istat = memtab_add_record(control,block_pointer,line(1:nk))
	end do
c
c add_record went wrong, kill vm_zone and exit
c
	call memtab_close(control,block_pointer)
	goto 90
c
c Here for successfull EOF
c
50	istat = 1	
	memtab.p_current = memtab.p_first		!begin of file
	nlines = memtab.n_lines
	goto 90
c
c Read error, get rms status
c
70	call errsns(,istat)
c
c General exit
c
90	memtab_open_lun = istat
	return
	end
	function memtab_open_lbr(control,libidx,block_pointer,modnam,nlines)
	implicit none
c
	include 'dix_memtab.inc'
	record /control/ control	!:i: control block
	integer*4 libidx		!:i: the file to readin
	integer*4 block_pointer		!:o: the pointer to a control block
	character*(*) modnam		!:i: the module name
	integer*4 nlines		!:o: #lines read
	integer*4 memtab_open_lbr		!:f: the function result
c#
	record /memtab/ memtab
	pointer (p_memtab,memtab)
c
	character*(max_line_length) line
        integer*4 istat,descr(2),nk
c
	integer*4 memtab_init
	integer*4 memtab_add_record
	integer*4 lbr$get_record
c	
	nlines = 0
	istat = memtab_init(control,block_pointer,modnam)
	if(.not. istat) goto 90
	p_memtab = block_pointer
c
c We have a valid block, start reading
c
	memtab.filename = modnam
	memtab.nk_filename = len(modnam)
c
c Start reading lines,
c first get a line block
c
	do while(lbr$get_record(libidx,line,descr))
	  nk = descr(1)
	  istat = memtab_add_record(control,block_pointer,line(1:nk))
	  if(.not. istat) goto 80
	end do
c
c Here for successfull EOF
c
	istat = 1	
	memtab.p_current = memtab.p_first
	nlines = memtab.n_lines
	goto 90
c
c add_record went wrong, kill vm_zone and exit
c
80	call memtab_close(control,block_pointer)
c
c General exit
c
90	memtab_open_lbr = istat
	return
	end
	function memtab_add_record(control,block_pointer,line)
	implicit none
c
c Append record to end of file
c
	include 'dix_memtab.inc'
	record /control/ control	!:i: control blocl
	integer*4 block_pointer
	character*(*) line
	integer*4 memtab_add_record
c#
	integer*4 memtab_add_record_level
c
	memtab_add_record = memtab_add_record_level(control,
     1              block_pointer,line,0)
	return
	end
c
	function memtab_add_record_level(control,block_pointer,line,level)
	implicit none
c
c Append record to end of file
c
	include 'dix_memtab.inc'
	record /control/ control	!:i: control block
	integer*4 block_pointer
	character*(*) line
	integer*4 level
	integer*4 memtab_add_record_level
c#
	record /memtab/ memtab
	pointer (p_memtab,memtab)
c
	record /memtab_line/ memtab_line
	pointer (p_memtab_line,memtab_line)
c
	integer*4 istat,k,nb_needed
c
	istat = 0
	if(block_pointer .ne. 0) then
	  p_memtab = block_pointer
	  if(memtab.magic .eq. memtab_magic) then
c
	    nb_needed = len(line) + sizeof(memtab_line.ovhd)
	    call get_vm(control,nb_needed,p_memtab_line,
     1                  memtab.zone_mem,.false.,'MEMTAB_LINE')
c
c Fill in the data
c
	    memtab_line.ovhd.nk = len(line)
	    memtab_line.line(1:memtab_line.ovhd.nk) = line
	    memtab.max_width    = max(memtab.max_width,len(line))
c
	    memtab.n_lines = memtab.n_lines + 1
c
c Now link in
c
	    memtab_line.ovhd.magic   = memtab_magic	!Signature
	    memtab_line.ovhd.p_next  = 0		!no next yet
	    memtab_line.ovhd.p_prev  = memtab.p_last	!point to prev
	    memtab_line.ovhd.line_nr = memtab.n_lines !Set line number
	    memtab_line.ovhd.p_pointers = 0
	    memtab_line.ovhd.level   = level
	    memtab_line.ovhd.labelptr= 0
c
c We have a line, now link in the chain
c
	    if(memtab.p_last .eq. 0) then
c
c First record, just record this one to be the first
c
	      memtab.p_first = p_memtab_line
	    else
c
c Now we must let the prev record point to the new record
c
	      k = p_memtab_line		!save this pointer
	      p_memtab_line = memtab.p_last	!point to prev
	      memtab_line.ovhd.p_next = k     !let it point to me
	      p_memtab_line = k               !and restore pointer
	    endif
	    memtab.p_current = p_memtab_line	!set current
	    memtab.p_last    = p_memtab_line  !and last
	    istat = 1
	  endif
	endif	!block_pointer <>0
c
	memtab_add_record_level = istat
	return
	end

	function memtab_add_label(control,block_pointer,
     1                        ptr_line,label,labelptr)
	implicit none
c
	include 'dix_memtab.inc'
	record /control/ control	!:i: the control block
	integer*4 block_pointer	
	integer*4 ptr_line		!the line where
	character*(*) label
	integer*4 labelptr
	integer*4 memtab_add_label
c#
	integer*4 istat
c
	record /memtab/ memtab
	pointer (p_memtab,memtab)
c
	record /memtab_line/ memtab_line
	pointer (p_memtab_line,memtab_line)
c
	record /memtab_label/ memtab_label
	pointer (p_memtab_label,memtab_label)
c
	istat = 0
	if(block_pointer .ne. 0) then
	  p_memtab = block_pointer
	  if(memtab.magic .ne. memtab_magic) goto 90
	endif
	if(ptr_line .ne. 0) then
	  p_memtab_line = ptr_line
	  if(memtab_line.ovhd.magic .ne. memtab_magic) goto 90
	endif
c
c  All pointers were ok, now fill in
c
	call get_vm(control,sizeof(memtab_label),
     1               p_memtab_label,memtab.zone_mem,.false.,
     1              'MEMTAB_LABEL')
c
c Fill and link in
c
	memtab_label.ptr_line = ptr_line
	memtab_label.label = label
	memtab_label.p_next = memtab.p_labels
	memtab.p_labels = p_memtab_label
c
	memtab_line.ovhd.labelptr = labelptr
90	memtab_add_label = istat
	return
	end

	function memtab_add_pointers(control,block_pointer,nb,ptrs,p_line)
	implicit none
c
	include 'dix_memtab.inc'
	record /control/ control
	integer*4 block_pointer
	byte ptrs(*)
	integer*4 nb
	integer*4 p_line
	integer*4 memtab_add_pointers
c#
	integer*4 istat
c
	record /memtab_line/ memtab_line
	pointer (p_memtab_line,memtab_line)
c
	record /memtab/ memtab
	pointer (p_memtab,memtab)
c
	integer*4 p_pointers
c
	istat = 0
	if(block_pointer .ne. 0) then
	  p_memtab = block_pointer
	  if(memtab.magic .eq. memtab_magic) then
	    if(p_line .ne. 0) then
	      p_memtab_line = p_line
	      if(memtab_line.ovhd.magic .eq. memtab_magic) then
	        if(memtab_line.ovhd.p_pointers .ne. 0) then
	          p_pointers = memtab_line.ovhd.p_pointers
	        else
	          call get_vm(control,nb,p_pointers,memtab.zone_mem,.false.,
     1                        'MEMTAB_POINTERS')
	        endif
	        call lib$movc3(nb,ptrs,%val(p_pointers))
	        memtab_line.ovhd.p_pointers = p_pointers
	      endif
	    endif	   
	  end if
	end if
	memtab_add_pointers = istat
	return
	end
	function memtab_read(block_pointer,nk,line)
	implicit none
c
	include 'dix_memtab.inc'
	integer*4 block_pointer
	integer*4 nk
	character*(*) line
	integer*4 memtab_read
c#
	integer*4 level,labelptr,k
c
	integer*4 memtab_read_level
c
	memtab_read = memtab_read_level(block_pointer,nk,line,
     1          level,labelptr,0,k)
	return
	end
	function memtab_read_level(block_pointer,nk,line,
     1                 level,labelptr,nb_ptrs,ptrs)
	implicit none
c
	include 'dix_memtab.inc'
	integer*4 block_pointer
	integer*4 nk
	character*(*) line
	integer*4 level
	integer*4 labelptr
	integer*4 nb_ptrs
	byte ptrs(*)
	integer*4 memtab_read_level
c#
	record /memtab_line/ memtab_line
	pointer (p_memtab_line,memtab_line)
c
	record /memtab/ memtab
	pointer (p_memtab,memtab)
c
	integer*4 istat
c
	istat = 0
	if(block_pointer .ne. 0) then
	  p_memtab = block_pointer
	  if(memtab.magic .eq. memtab_magic) then
	    if(memtab.p_current .ne. 0) then
	      p_memtab_line = memtab.p_current
	      istat = 1
	      nk = min(len(line),memtab_line.ovhd.nk)
	      line = memtab_line.line(1:nk)
	      memtab.p_current = memtab_line.ovhd.p_next
	      level    = memtab_line.ovhd.level
	      labelptr = memtab_line.ovhd.labelptr
	      if(memtab_line.ovhd.p_pointers .eq. 0) then
	        call lib$movc5(0,0,0,nb_ptrs,ptrs)
	      else
	        call lib$movc3(nb_ptrs,%val(memtab_line.ovhd.p_pointers),ptrs)
	      endif
	    endif
	  endif
	endif
90	memtab_read_level = istat
	return
	end
c
	function memtab_rewind(block_pointer)
	implicit none
c
	include 'dix_memtab.inc'
	integer*4 block_pointer
	integer*4 memtab_rewind
c#
	record /memtab/ memtab
	pointer (p_memtab,memtab)
c
	integer*4 istat
c
	istat = 0
	if(block_pointer .ne. 0) then
	  p_memtab = block_pointer
	  if(memtab.magic .eq. memtab_magic) then
	    memtab.p_current = memtab.p_first
	    istat = 1
	  endif
	endif
	memtab_rewind = istat
	return
	end
	
	function memtab_close(control,block_pointer)
	implicit none
c
	include 'dix_memtab.inc'
c
	record /control/ control
	integer*4 block_pointer
	integer*4 memtab_close
c#
	record /memtab/ memtab
	pointer (p_memtab,memtab)
c
	integer*4 istat
c
	istat = 0
	if(block_pointer .ne. 0) then
	  p_memtab = block_pointer
	  if(memtab.magic .eq. memtab_magic) then
	    call delete_vm(control,memtab.zone_mem)
	    block_pointer = 0
	  endif
	  control.n_memfiles_closed = control.n_memfiles_closed + 1
	endif
	memtab_close = istat
	return
	end
	function memtab_get_nlines(block_pointer,nlines)
	implicit none
c
	include 'dix_memtab.inc'
c#
	integer*4 block_pointer
	integer*4 nlines
	integer*4 memtab_get_nlines
c
	record /memtab/ memtab
	pointer (p_memtab,memtab)
c
	integer*4 istat
c
	istat = 0
	if(block_pointer .ne. 0) then
	  p_memtab = block_pointer
	  if(memtab.magic .eq. memtab_magic) then
	    nlines =  memtab.n_lines
	    istat = 1
	  endif
	endif
	memtab_get_nlines = istat
	return
	end
	function memtab_get_max_width(block_pointer,width)
	implicit none
c
	include 'dix_memtab.inc'
c
	integer*4 block_pointer
	integer*4 width
	integer*4 memtab_get_max_width
c#
	record /memtab/ memtab
	pointer (p_memtab,memtab)
c
	integer*4 istat
c
	istat = 0
	if(block_pointer .ne. 0) then
	  p_memtab = block_pointer
	  if(memtab.magic .eq. memtab_magic) then
	    width =  memtab.max_width
	    istat = 1
	  endif
	endif
	memtab_get_max_width = istat
	return
	end
	function memtab_get_line_ptr(block_pointer,line_ptr)
	implicit none
c
	include 'dix_memtab.inc'
c
	integer*4 block_pointer
	integer*4 line_ptr
	integer*4 memtab_get_line_ptr
c#
	record /memtab/ memtab
	pointer (p_memtab,memtab)
c
	integer*4 istat
c
	istat = 0
	if(block_pointer .ne. 0) then
	  p_memtab = block_pointer
	  if(memtab.magic .eq. memtab_magic) then
	    line_ptr = memtab.p_current
	    istat = 1
	  endif
	endif
	memtab_get_line_ptr = istat
	return
	end
	function memtab_set_line_ptr(block_pointer,line_ptr)
	implicit none
c
	include 'dix_memtab.inc'
c
	integer*4 block_pointer
	integer*4 line_ptr
	integer*4 memtab_set_line_ptr
c#
	record /memtab/ memtab
	pointer (p_memtab,memtab)
c
	record /memtab_line/ memtab_line
	pointer (p_memtab_line,memtab_line)
c
	integer*4 istat
c
	istat = 0
	if(block_pointer .ne. 0) then
	  p_memtab = block_pointer
	  if(memtab.magic .eq. memtab_magic) then
	    if(line_ptr .eq. 0) then
	      memtab.p_current = 0
	      istat = 1
	    else
	      p_memtab_line = line_ptr
	      if(memtab_line.ovhd.magic .eq. memtab_magic) then
	        memtab.p_current = line_ptr
	        istat = 1
	      end if
	    end if
	  endif
	endif
90	memtab_set_line_ptr = istat
	return
	end
	function memtab_find_label(block_pointer,label,ptr_line,level)
	implicit none
	include 'dix_memtab.inc'
c
	integer*4 block_pointer
	character*(*) label
	integer*4 ptr_line
	integer*4 level
	integer*4 memtab_find_label
c#
	record /memtab/ memtab
	pointer (p_memtab,memtab)
c
	record /memtab_label/ memtab_label
	pointer (p_memtab_label,memtab_label)
c
	record /memtab_line/ memtab_line
	pointer (p_memtab_line,memtab_line)
c
c
	integer*4 istat
c
	istat = 0
	if(block_pointer .ne. 0) then
	  p_memtab = block_pointer
	  if(memtab.magic .eq. memtab_magic) then
	    p_memtab_label = memtab.p_labels
	    do while(p_memtab_label .ne. 0)
	      if(label .eq. memtab_label.label)then
	        istat = 1
	        ptr_line = memtab_label.ptr_line
	        p_memtab_line = ptr_line
	        level = memtab_line.ovhd.level
	        goto 90
	      endif
	      p_memtab_label = memtab_label.p_next
	    end do
	  end if
	end if
90	memtab_find_label = istat
	return
	end
