	function dix_lbr_open(control,lbr_index,readonly,where)
	implicit none
c
c Open a library and return a lbr_index
c
	include 'dix_def.inc'
	record /control/ control	!:i: control structure
	integer*4 lbr_index		!:o: lbr index
	logical readonly		!:i: open readonly or readwrite
	integer*4 where			!:i: the location
	integer*4 dix_lbr_open
c#
	include '($lbrdef)'
c
	integer*4 open_option,istat
	integer*4 lbr$open
	integer*4 lbr$ini_control
c
	open_option = lbr$c_read
	if(.not. readonly) open_option = lbr$c_update
c
	istat = lbr$ini_control(lbr_index,open_option,lbr$c_typ_txt)
	if(istat) then 
	  if(where .eq. des_in_userlib) then
	    istat = lbr$open(lbr_index,
     1        control.userlib_name(1:control.nk_userlib))
	  else
	    istat = lbr$open(lbr_index,
     1        control.syslib_name(1:control.nk_syslib))
	  endif
	endif
	dix_lbr_open = istat
	return
	end	
	function dix_lbr_close(control,lbr_index)
	implicit none
c
	include 'dix_def.inc'
	record /control/ control	!:i: control structure
	integer*4 lbr_index		!:i: lbr_index
	integer*4 dix_lbr_close
c#
	integer*4 istat
	integer*4 lbr$close
c
	istat = lbr$close(lbr_index)
	if(.not. istat) call dix_message(control,%val(istat))
	dix_lbr_close = istat
	return
	end
c
	function dix_lbr_read_module(control,modname,p_memtab,nlines)
	implicit none
c
c Try to load amouel from 
c 1. userlibrary
c 2. system library
c
	include 'dix_def.inc'
	record /control/ control
	character*(*) modname		!:i: the modulename
	integer*4 p_memtab              !:o: the lun for the scratch file
	integer*4 nlines		!:o: #lines read
	integer*4 dix_lbr_read_module	!:f: result
c#
	integer*4 istat
	integer*4 dix_lbr_get_module
c
c First try to read from userlibrary
c
	istat = dix_lbr_get_module(control,modname,p_memtab,nlines,
     1                des_in_userlib)
	if(.not. istat) then
c
c If not successfull, try userlib
c
	  istat = dix_lbr_get_module(control,modname,p_memtab,nlines,
     1                des_in_syslib)
	endif
	dix_lbr_read_module = istat
	return
	end
c	
	function dix_lbr_get_module(control,modname,p_memtab,nlines,where)
	implicit none
c
c Try to get a module from a TLB file, and write result to the memtab-file
c
	include 'dix_def.inc'
	record /control/ control
	character*(*) modname		!:i: the modulename
	integer*4 p_memtab              !:o: the lun for the scratch file
	integer*4 nlines		!:o: #lines read
	integer*4 where			!:i: in syslib or userlib
	logical*4 dix_lbr_get_module    !:f: Function result, 
c#
	integer*4 rfa(2),istat,lbr_index
	integer*4 lbr$lookup_key
	integer*4 dix_lbr_open
c
10	istat = dix_lbr_open(control,lbr_index,.true.,where)
c
c Try to lookup the module
c
	if(istat) then
	  istat = lbr$lookup_key(lbr_index,modname,rfa)
	  if(istat) then
c
c Copy the module to the scratch-file
c
	    call memtab_open_lbr(control,lbr_index,
     1                           p_memtab,modname,nlines)
	  endif
	  call dix_lbr_close(control,lbr_index)
	endif
	dix_lbr_get_module = istat
	return
	end
	function dix_lbr_replace_module(control,lun,modname,where)
	implicit none
c
c Put the contents of memtab_file in lun to the library
c
	include 'dix_def.inc'
	record /control/ control	!:i: control block
	integer*4 lun                   !:i: memtab file
	character*(*) modname		!:i: module name
	integer*4 where			!:i: where to put it (system/userlib)
	integer*4 dix_lbr_replace_module
c#
	include '($jpidef)'
c
	integer*4 lbr_index
	integer*4 rfa(2),rfaidx(2),rfahdr(2),nk,istat
	character*(max_line_length) line
	logical*4 first
c
	integer*4 lbr$put_record
	integer*4 lbr$put_end
	integer*4 lbr$replace_key
	integer*4 lbr$lookup_key
	integer*4 dix_lbr_open
	integer*4 memtab_read
c
	external dix_msg_noupdate
c
	istat = dix_lbr_open(control,lbr_index,.false.,where)
	if(istat)then
	  istat = lbr$lookup_key(lbr_index,modname,rfa)
	  if(istat) then
	    call memtab_rewind(lun)
	    first = .true.
10	    do while(istat .and. memtab_read(lun,nk,line)) 
	      istat = lbr$put_record(lbr_index,line(1:nk),rfaidx)
	      if(.not. istat) call lib$signal(%val(istat))
	      if(first) then
	        rfahdr(1) = rfaidx(1)
	        rfahdr(2) = rfaidx(2)
	        first = .false.
	      endif
	    end do
	    istat = lbr$put_end(lbr_index)
	    if(.not. istat) call lib$signal(%val(istat))
	    istat = lbr$replace_key(lbr_index,modname,rfa,rfahdr)
	    if(.not. istat) call lib$signal(%val(istat))
	  endif
	  call dix_lbr_close(control,lbr_index)
	endif
	dix_lbr_replace_module = istat
	if(.not. istat) then
	  if(where .eq. des_in_syslib) then
	    call dix_message(control,dix_msg_noupdate,
     1          control.syslib_name(1:control.nk_syslib))
	  else
	    call dix_message(control,dix_msg_noupdate,
     1          control.userlib_name(1:control.nk_userlib))
	  endif
	endif
	return
	end
	function dix_lbr_insert_module(control,lun,modname,where)
	implicit none
c
	include 'dix_def.inc'
	record /control/ control		!:i: control module
	integer*4 lun				!:i:L lun on which memtab open
	character*(*) modname			!:i: module name
	integer*4 where				!:i: where (user/system)
	logical*4 dix_lbr_insert_module		!:f: function result
c#
	integer*4 lbr_index
	integer*4 rfa(2),rfaidx(2),rfahdr(2),nk
	character*(max_line_length) line
	logical*4 first
c
	integer*4 istat
	integer*4 lbr$put_record
	integer*4 lbr$put_end
	integer*4 lbr$insert_key
	integer*4 lbr$lookup_key
	integer*4 dix_lbr_open
	integer*4 memtab_read
c
	external dix_msg_noupdate
	external dix_msg_dupkey
c
	istat = dix_lbr_open(control,lbr_index,.false.,where)
	if(istat) then
	  if(lbr$lookup_key(lbr_index,modname,rfa)) then
	    call dix_message(control,dix_msg_dupkey,modname)
	    istat = %loc(dix_msg_dupkey)
	  else
	    call memtab_rewind(lun)
	    first = .true.
	    do while(istat .and. memtab_read(lun,nk,line)) 
	      istat = lbr$put_record(lbr_index,line(1:nk),rfaidx)
	      if(.not. istat) call lib$signal(%val(istat))
	      if(first) then
	        rfahdr(1) = rfaidx(1)
	        rfahdr(2) = rfaidx(2)
	        first = .false.
	      endif
	    end do
	    istat = lbr$put_end(lbr_index)
	    if(.not. istat) call lib$signal(%val(istat))
	    istat = lbr$insert_key(lbr_index,modname,rfahdr)
	    if(.not. istat) call lib$signal(%val(istat))
	  endif
	  call dix_lbr_close(control,lbr_index)
	endif
	if(.not. istat) then
	  if(where .eq. des_in_syslib) then
	    call dix_message(control,dix_msg_noupdate,
     1          control.syslib_name(1:control.nk_syslib))
	  else
	    call dix_message(control,dix_msg_noupdate,
     1          control.userlib_name(1:control.nk_userlib))
	  endif
	endif
	dix_lbr_insert_module = istat
	return
	end
	function dix_lbr_add_des(control,file,des_mask,signal,all)
	implicit none
c
	include 'dix_def.inc'
c
	record /control/ control	!:i: control structure
	record /file_info/ file		!:i: file info
	character*(*) des_mask		!:i: description name
	logical signal			!:i: signal found modules
	logical*4 all			!:i: include all matches
	integer*4 dix_lbr_add_des
c#
	record /des_info/ des_info
	pointer (p_des_info,des_info)
c
	integer*4 istat,k,nk,p_memtab,ptr,where
	logical master_link
	character*(max_line_length) line
c
	integer*4 dix_lbr_get_list
	integer*4 dix_lbr_get_module
	integer*4 dix_des_read_it
	integer*4 memtab_read
	logical dix_des_find_des
	logical dix_des_find_des_file
	external dix_msg_alrload
	external dix_msg_desadd
c
	dix_lbr_add_des = .false.
c
	where = des_in_userlib
c
10	istat = dix_lbr_get_list(control,p_memtab,des_mask,where,.false.)
	if(istat) then
c
c Got a list
c
	  do while(memtab_read(p_memtab,nk,line))
c
c See if module already in file chan
c
	    if(dix_des_find_des_file(file,line(1:nk),where)) then
	      call dix_message(control,dix_msg_alrload,line(1:nk))
	    else
c
c No, now see if in open des list
c	    
	      if(dix_des_find_des(control,line(1:nk),
     1                          where,ptr)) then
c
c Yes so only link in
c
	        p_Des_info = ptr
	        master_link = .false.
	        istat = 1
	      else
c
c Need a new des_record
c
	        call get_vm(control,sizeof(des_info),p_des_info,
     1                      control.zone_descr,.false.,'DES_INFO')
	        des_info.magic = magic_des_info
	        call dix_des_init_des(des_info)	  
	        des_info.in_library = where
	        des_info.fnam    = line(1:nk)
	        des_info.nk_fnam = nk
c
c now read in the descriptions in a memtab file
c
	        istat = dix_lbr_get_module(control,
     1                  des_info.fnam(1:des_info.nk_fnam),
     1                  des_info.lun_memtab,k,where)
	        if(istat) then
	          istat = dix_des_read_it(control,des_info.lun_memtab,
     1                          des_info,k)
	          call memtab_close(control,des_info.lun_memtab)
	        endif
	        master_link = .true.
	      endif
	      if(istat) then
c
c Link in the chain (at the end)
c
	        if(signal) then
	          call dix_des_display(control,des_info,line,nk,.true.)
	          call dix_message(control,dix_msg_desadd,line(1:nk))
	        endif
	        call dix_des_link_in(control,file,des_info,master_link,.true.)
	        dix_lbr_add_des = .true.
	      else
	        call free_vm(control,sizeof(des_info),p_des_info,
     1                              control.zone_descr)
	      endif
	    endif	!already in file linked list
	  enddo		!loop over all modules
c
c And free table with list of modules
c
	  call memtab_close(control,p_memtab)
	endif
	if(where .eq. des_in_userlib) then
	  if(.not. dix_lbr_add_des .or. all) then
	    where = des_in_syslib
	    goto 10
	  endif
	endif
	return
	end
	function dix_lbr_get_list(control,p_memtab,mask,where,index)
	implicit none
c
c Get a list of the library, matching "mask"
c
	include 'dix_def.inc'
	record /control/ control	!:i: control block
	integer*4 p_memtab		!:i: "lun" to write to
	character*(*) mask		!:i: mask for module names
	integer*4 where			!:i: in which library
	logical*4 index			!:i: in which index
	integer*4 dix_lbr_get_list
c#
	integer*4 istat,lbr_index
c
	integer*4 dix_lbr_open
	integer*4 lbr$get_index
	external dix_lbr_get_index
	integer*4 dix_util_get_len_fu
c
	character*(max_line_length) c_mask
	integer*4 lun_memtab,nk_mask,c_index,c_p_control
	common /dix_lbr_get/ lun_memtab,c_index,c_p_control,
     1                       nk_mask,c_mask
c
	c_index = index
	c_p_control = %loc(control)
	call str$upcase(c_mask,mask)
	nk_mask = dix_util_get_len_fu(mask)
c
	call memtab_init(control,lun_memtab,'LBR_LIST')
	istat = dix_lbr_open(control,lbr_index,.true.,where)
	if(istat) then
	  istat = lbr$get_index(lbr_index,1,dix_lbr_get_index)
	  call dix_lbr_close(control,lbr_index)
	endif
	if(.not. istat) then
	  call memtab_close(control,lun_memtab)
	else
	  p_memtab = lun_memtab
	  call memtab_rewind(p_memtab)
	endif
	dix_lbr_get_list = istat
	return
	end
	function dix_lbr_get_index(key)    !,rfa)
	implicit none
c
c Got through all keys, and create a linked list of empty des records
c than match the given name
c
	include 'dix_def.inc'
c
	character*(*) key		!:I: found key name
c	integer*4 rfa(2)		!:i: rfa name
	integer*4 dix_lbr_get_index	!:f: function result
c#
	character*(max_line_length) c_mask
	integer*4 lun_memtab,nk_mask,c_index,c_p_control
	common /dix_lbr_get/ lun_memtab,c_index,c_p_control,
     1                       nk_mask,c_mask
c
	record /control/ control
	pointer (p_control,control)
c
	integer*4 istat
c
	logical dix_lbr_match_module
	integer*4 memtab_add_record
c
	p_control = c_p_control
	if(dix_lbr_match_module(c_mask(1:nk_mask),key,c_index)) then
	  istat = memtab_add_record(control,lun_memtab,key)
 	else
	  istat = 1
	endif
	dix_lbr_get_index = istat
	return
	end
	function dix_lbr_match_module(mask,key,index)
	implicit none
c
c match the name to a modulename
c
	character*(*) mask	!:i: mask given by nuser
	character*(*) key	!:i: library module name
	logical index		!:i: how to match
	logical dix_lbr_match_module !:f: return value
c#
	integer*4 bposm,eposm,bposk,eposk
	logical dix_lbr_match_name
c
	dix_lbr_match_module = .false.
c
	call dix_util_file_parse(mask,'X',bposm,eposm)
	call dix_util_file_parse(key ,'X',bposk,eposk)
	if(.not. dix_lbr_match_name(index,mask,bposm,eposm,
     1                                    key ,bposk,eposk)) goto 90
c
	call dix_util_file_parse(mask,'D',bposm,eposm)
	call dix_util_file_parse(key ,'D',bposk,eposk)
	if(.not. dix_lbr_match_name(index,mask,bposm,eposm,
     1                                    key ,bposk,eposk)) goto 90
c
	call dix_util_file_parse(mask,'N',bposm,eposm)
	call dix_util_file_parse(key ,'N',bposk,eposk)
	if(.not. dix_lbr_match_name(index,mask,bposm,eposm,
     1                                    key ,bposk,eposk)) goto 90
c
	call dix_util_file_parse(mask,'T',bposm,eposm)
	call dix_util_file_parse(key ,'T',bposk,eposk)
	if(.not. dix_lbr_match_name(index,mask,bposm,eposm,
     1                                    key ,bposk,eposk)) goto 90
	dix_lbr_match_module = .true.
90	return
	end
	function dix_lbr_match_name(idx,mask,bposm,eposm,key,bposk,eposk)
	implicit none
c
c Match a part of the module name
c
	logical idx		!:i: if true revers mask/key
	character*(*) mask	!:i: filename
	integer*4 bposm         !:i: beg-position of part in filename
	integer*4 eposm         !:i: end-position of part in filename
	character*(*) key       !:i: module from library
	integer*4 bposk         !:i: beg_position of part in key 
	integer*4 eposk         !:i: end_position of part in key
	logical dix_lbr_match_name	!:f: function value
c#
	logical str$match_wild
c
	if(bposm .eq. 0) bposm = 1
c
	if(bposk .eq. 0 .or. eposk .lt. bposk) then
c
c  Part not present in key from library, so match always
c
	  dix_lbr_match_name = .true.
	else
c
c Now match part from filename with part from key
c
	  if(idx) then
	    dix_lbr_match_name = str$match_wild(
     1                          key(bposk:eposk),
     1                          mask(bposm:eposm))
	  else
	    dix_lbr_match_name = str$match_wild(
     1                          mask(bposm:eposm),
     1                          key(bposk:eposk))
	  endif
	endif
	return
	end
