	program conv

	include 'conv.inc'

	logical init
	integer i,j,l,lin,iostat
	character*128 line
	character*2048 input

	data lun/0/,pos/0/,nlist/0/

	path=' '
	lp=0
	verbose=.false.
	call sys_get_cmdpar(input, l)
	if (input .eq. ' ') then
	  verbose=.true.
	  print '(a,$)',
	1' File(s) (separated with space): '
	  read(*,'(a)',end=99) input
	  if (input .eq. ' ') goto 99
	endif
	i=index(input, '-p')
	if (i .ne. 0) then ! first path option valid from start
	  j=index(input(i+1:), ' ')
	  call str_trim(path, input(i+2:i+j), lp)
	endif
	i=0
	do while (input(i+1:) .ne. ' ')
	  j=index(input(i+1:), ' ')
	  if (j .le. 1) then
	    i=i+1
	  else if (input(i+1:i+2) .eq. '-p') then
	    call str_trim(path, input(i+3:i+j), lp)
	    i=i+j
	  else if (input(i+1:i+1) .eq. '-') then
	    print *,'unknown option: ',input(i+1:i+j)
	    i=i+j
	  else
	    call str_trim(file, input(i+1:i+j), lf)
	    i=i+j
	    if (verbose) print *
	    open(1,name=file(1:lf),status='old',iostat=iostat)
	    if (iostat .ne. 0) then
	      if (verbose) then
	        print *,'can not open ',file(1:lf)
	        print "(x,60('-'))"
	      endif
	      nlist=nlist+1
	      list(nlist)='can not open '//file(1:lf)
	    else
	      lin=0
	      do
	        call lsc_errinit(1) ! 1=lun
	        call lsc_convert_table(lin)
	        if (lin .lt. 0) goto 19
	        if (verbose) print "(x,60('-'))"
	      enddo
19	      continue
	      close(1)
	    endif
	  endif
	enddo

	do i=1,nlist
	  call str_trim(list(i), list(i), l)
	  print *,list(i)(1:l)
	enddo

99	continue
	end


	subroutine pack(line, l, x, y, offset, m)
	character line*(*)
	integer l, offset, m
	real x(m), y(m)

	integer j,p

	p=0
	do j=1,m
	  call str_append(line, p, '#0,')
	  call cvt_real_str(line(p+1:), l, 1.0*(offset+j), 1, 0, 6, 3)
	  p=p+l
	  call str_append(line, p, ':')
	  call cvt_real_str(line(p+1:), l, x(j), 1, 0, 6, 3)
	  p=p+l
	  call str_append(line, p, ',')
	  call cvt_real_str(line(p+1:), l, y(j), 1, 0, 6, 3)
	  p=p+l
	  call str_append(line, p, ';')
	enddo
	line(p:p)=' '
	l=p-1
	end


	subroutine lsc_convert_table(lin)

	implicit none
	include 'conv.inc'

	integer lin

	integer ntypes,nvolts, namps
	parameter (ntypes=12, nvolts=12, namps=12)
	integer np

	real x(200), y(200), ex, ey
	integer i,j,l,p,li,crc,form,iostat

	character name*15, sensor*10, header*64, line*128, old*128, intype*16
	character crcmp*3, filnam*128, cfgdir*128
	character c40*40/'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$+-&'/
	integer unit, stype, excit, irange, coef, iunit, stdcurv
	! codes
	character types(0:ntypes)*12/'Special','Si Diode','GaAlAs Diode'
	1 ,'Pt250 Ohm','Pt500 Ohm','Pt2500 Ohm','RhFe','C-Glass'
	1 ,'Cernox','RuOx','Ge','Cap','Tc'/
	integer nunits
	parameter (nunits=3)
	character units(nunits)*5/'mV','V','Ohm'/
	integer nexcits
	parameter (nexcits=12)
	character excits(0:nexcits)*8/'Off','30nA','100nA','300nA','1uA','3uA'
	1 ,'10uA','30uA','100uA','300uA','1mA','10mV','1mV'/
	integer nforms
	parameter (nforms=5)
	character forms(nforms)*6/'ill','ill','lin','log','loglog'/

	! default values
	integer defu(ntypes)/ 1, 1, 2, 2,2, 2, 2, 2, 2, 2, 3, 1/	! unit
	integer defe(ntypes)/ 6, 6,10,10,8,10,11,11,11,12, 0, 0/	! excit
	integer defr(ntypes)/11,12, 8, 9,8, 8, 4, 4, 4, 1, 1, 6/	! range
	integer defc(ntypes)/ 1, 1, 2, 2,2, 2, 1, 1, 1, 1, 2, 2/	! coef
	real volts(nvolts)/1E-3,2.5E-3,5E-3,1E-2,2.5E-2,5E-2
	1                 ,1E-1,2.5E-1,5E-1,1E-0,2.5E-0,5E-0/
	real amps(namps)/3E-8,1E-7,3E-7,1E-6,3E-6,1E-5,3E-5,1E-4,3E-4,1E-3
	1               ,3E-8,3E-8/	! minimal values are for voltage excitation
	integer stdmax
	parameter (stdmax=10)	
	character*40 stdhdr(stdmax)/
	1 'DT-470    ,Standard  ,2,+475.000E+0,1', 
	1 'DT-500-D  ,Standard  ,2,+365.000E+0,1', 
	1 'DT-500-E1 ,Standard  ,2,+330.000E+0,1', 
	1 'PT-100    ,Standard  ,3,+800.000E+0,2', 
	1 'PT-1000   ,Standard  ,3,+800.000E+0,2', 
	1 'TYPE K ,Standard  ,1,+1645.00E+0,2', 
	1 'TYPE E ,Standard  ,1,+1188.50E+0,2', 
	1 'TYPE T ,Standard  ,1,+673.000E+0,2', 
	1 'CrAuFe.03%,Standard  ,1,+500.000E+0,2', 
	1 'CrAuFe.07%,Standard	,1,+610.000E+0,2'/
	integer stdtype(stdmax)/1,1,1,4,5,12,12,12,12,12/

	real tlim, range, xmax, ymax, curr, rl

	real x1,x2,xi,y1,y2,yi,sum,sum1,sum2,mum,mum1,mum2,d,at,at1,at2
	logical eof, first, inverted
	
	! functions
	integer  lsc_getno
	external lsc_getno, pack

	first=.true.
	eof=.false.
	np=0
	name=' '
	sensor=' '
	unit=0
	tlim=0
	stype=0
	excit=0
	form=0
	range=-1.0
	stdcurv=0
1	read(1,'(a)',err=97,end=97) line
	call str_trim(line, line, l)
	lin=lin+1
	call str_first_nonblank(line, i)
	if (i .eq. 0) goto 1
	if (line(i:i) .eq. '!') goto 1
	first=.false.
	call str_upcase(line(1:l),line(i:l))
	i=index(line(1:l),'!')
	if (i .ne. 0) line=line(1:i-1)
	call str_trim(line(1:l),line(1:l),l)
	if (line(1:4) .ne. 'CURV') then
	  i=index(line,'=')
	  if (i .eq. 0) then
	    call lsc_error(lin, 'missing "="')
	    goto 1
	  endif
	  if (i .eq. l) then
	    call lsc_error(lin, 'missing value')
	    goto 1
	  endif
	  call str_first_nonblank(line(i+1:l), j)
	  i=i+j
	  if (line(1:4) .eq. 'SENS') then
	    sensor=line(i:l)
	    name=sensor
	  elseif (line(1:4) .eq. 'UNIT') then
	    unit=lsc_getno(units, nunits, line(i:l))
	    if (unit .le. 0) call lsc_error(lin, 'illegal unit')
	  elseif (line(1:4) .eq. 'TLIM') then
	    read(line(i:l),*,err=92,end=92) tlim
	  elseif (line(1:4) .eq. 'TYPE') then
	    stype=lsc_getno(types, ntypes+1, line(i:l))-1
	    if (stype .lt. 0) call lsc_error(lin, 'illegal type')
	  elseif (line(1:4) .eq. 'EXCI') then
	    call str_substitute(line(1:8),line(i:l),' ',char(0))
	    excit=lsc_getno(excits, nexcits, line(1:8))-1
	    if (excit .lt. 0) call lsc_error(lin, 'illegal excitation')
	  elseif (line(1:4) .eq. 'RANG') then
	    read(line(i:l),*,err=93,end=93) range
	    if (range .lt. 0) goto 93
	  elseif (line(1:4) .eq. 'FORM') then
	    form=lsc_getno(forms, nforms, line(i:l))
	    if (form .lt. 3) call lsc_error(lin, 'illegal format')
	  else
	    call lsc_error(lin, 'unknown parameter name')
	  endif
	  goto 1
	endif
	if (sensor .eq. ' ') call lsc_error(lin, 'missing sensor name')
	i=index(line,'=')
	if (i .ne. 0) then
	  read(line(i+1:l), *, err=2,end=2) stdcurv
2	 continue
	  if (stdcurv .lt. 0 .or. stdcurv .gt. stdmax) then
	    call lsc_error(lin, 'illegal standard curve no.')
	    goto 101
	  endif
	  if (unit .ne. 0 .or. stype .ne. 0 .or.
	1     excit .ne. 0 .or. tlim .ne. 0) then
	    if (verbose) then
	      print *,'Warning: all parameters except "sens"'
	1       ,', "range" and "curv" are ignored',char(7)
	    endif
	    errstat=max(errstat,1)
	  endif
	  line=stdhdr(stdcurv)
	  i=index(line, ',')
	  if (i .eq. 0) goto 96 ! illegal stdhdr
	  j=index(line(i+1:), ',')
	  if (j .eq. 0) goto 96 ! illegal stdhdr

	  read(line(i+j+1:), *, err=96, end=96) unit, ymax, coef
	  stype=stdtype(stdcurv)
!	  if (range  .lt.  0) then
!	    range=stdrange(stdcurv)
!	  end if
	  xmax=0
	  excit=0
	  tlim=0
	  goto 100
	endif
	if (line(5:)  .ne.  ' ') then
	  call lsc_error(lin, 'missing "="')
	  goto 101
	end if
	 ! user curve
	if (unit .eq. 0) call lsc_error(lin, 'missing unit')
	if (stype .eq. 0) then
	  if (excit .le. 0) call lsc_error(lin, 'missing excitation')
	  if (range .lt. 0) call lsc_error(lin, 'missing range')
	else
	  if (excit .eq. 0) excit=defe(stype)
	endif
3	np=np+1
	read(1,'(a)',err=98,end=98) line
	lin=lin+1
	if (line .eq. ' ') goto 9
	read(line, *, err=94, end=94) x(np), y(np)
	goto 3


92	call lsc_error(lin,'illegal tlim')
	goto 1
93	call lsc_error(lin,'illegal range')
	goto 1
94	call lsc_error(lin,'illegal datapoint')
	goto 101
95	call lsc_error(lin,'illegal table no')
	goto 1
96	stop 'internal error: illegal stdhdr'
97	if (.not. first) then
	  call lsc_error(lin,'unexpected end of file')
	endif
	lin=-1
	RETURN
98	eof=.true.

9	np=np-1 ! point (np) is not valid

	if (np .lt. 2) call lsc_error(lin+np, 'not enough data points')
	if (x(np) .lt. x(1)) then ! inverse order
	  j=np
	  do i=1,np/2
	    ex=x(i)
	    ey=y(i)
	    x(i)=x(j)
	    y(i)=y(j)
	    x(j)=ex
	    y(j)=ey
	    j=j-1
	  enddo
	  inverted=.true.
	else
	  inverted=.false.
	endif
	do i=2,np
	  if (x(i) .le. x(i-1)) then
	    j=i
	    if (inverted) j=np-i+1
	    call lsc_error(lin+j, 'table not ordered')
	    goto 101
	  endif
	enddo
	xmax=x(np)
	if (y(np) .lt. y(1)) then
	  coef=1
	  do i=2,np
	    if (y(i) .ge. y(i-1)) then
	      j=i
	      if (inverted) j=np-i+1
	      call lsc_error(lin+j, 'table not ordered')
	      goto 101
	    endif
	  enddo
	  ymax=y(1)
	else
	  coef=2
	  do i=2,np
	    if (y(i) .le. y(i-1)) then
	      j=i
	      if (inverted) j=np-i+1
	      call lsc_error(lin+j, 'table not ordered')
	      goto 101
	    endif
	  enddo
	  ymax=y(np)
	endif
101	continue
	do i=1,np
	  if (x(i) .eq. 0.0) then
	    j=i
	    if (inverted) j=np-i+1
	    call lsc_error(lin+j, 'illegal sensor value')
	  endif
	  if (y(i) .le. 0.0) then
	    j=i
	    if (inverted) j=np-i+1
	    call lsc_error(lin+j, 'illegal temperature')
	  endif
	enddo
	if (errstat .gt. 1) goto 999

	sum=0
	sum1=0
	sum2=0
	mum=0
	mum1=0
	mum2=0
	do i=2,np-1
	  xi=x(i)
	  x1=x(i-1)
	  x2=x(i+1)
	  yi=log(y(i))
	  y1=y(i-1)
	  y2=y(i+1)
	  d=abs(yi-log(y1+(xi-x1)/(x2-x1)*(y2-y1)))
	  sum=sum+d*d
	  if (d .gt. mum) then
	    mum=d
	    at=y(i)
	  endif
	  xi=log(abs(xi))
	  x1=log(abs(x1))
	  x2=log(abs(x2))
	  d=abs(yi-log(y1+(xi-x1)/(x2-x1)*(y2-y1)))
	  sum1=sum1+d*d
	  if (d .gt. mum1) then
	    mum1=d
	    at1=y(i)
	  endif
	  y1=log(y1)
	  y2=log(y2)
	  d=abs(yi-(y1+(xi-x1)/(x2-x1)*(y2-y1)))
	  sum2=sum2+d*d
	  if (d .gt. mum2) then
	    mum2=d
	    at2=y(i)
	  endif
	enddo
	if (np .gt. 2) then
	  sum=sqrt(sum/(np-1))*25
	  sum1=sqrt(sum1/(np-1))*25
	  sum2=sqrt(sum2/(np-1))*25

	  if (verbose) then
	    print '(x,a)','Interpolation accuracy	 mean	  worst	    at'
	    print '(13x,a,3(f8.2,a))','linear	',sum, '%',mum *25,'%',at,' K'
	    print '(13x,a,3(f8.2,a))','log/lin ',sum1,'%',mum1*25,'%',at1,' K'
	    print '(13x,a,3(f8.2,a))','log/log ',sum2,'%',mum2*25,'%',at2,' K'
	  endif

	  if (unit .eq. 3) then
	    sum1=(sum1/sum)**2+(mum1/mum)**2
	    sum2=(sum2/sum)**2+(mum2/mum)**2
	    if (form .eq. 0 .and. (sum1 .lt. 1.0 .or. sum2 .lt. 1.0)
	1       .or. form .gt. 3) then
	      if (form .eq. 0 .and. sum2 .lt. sum1 .or. form .eq. 5) then
	        unit=5
	        do i=1,np
	          y(i)=log10(y(i))
	        enddo
	      else
	        unit=4
	      endif
	      do i=1,np
	        x(i)=log10(x(i))
	      enddo
	    endif
	  else
	    if (form .gt. 3 .and. verbose)
	1     print *,'FORM ignored (not unit Ohm)'
	  endif
	endif

100	continue

	if (unit .eq. 1) then ! check for mV / V consistency
	  if (xmax .gt. 990) then
	    unit=2
	    do i=1,np
	      x(i)=x(i)/1000.0
	    enddo
	  endif
	  xmax=xmax/1000.0
	  range=range/1000.0
	elseif (unit .eq. 2) then
	  if (xmax .lt. 0.5) then
	    unit=1
	    do i=1,np
	      x(i)=x(i)*1000.0
	    enddo
	  endif
	endif
	if (range .eq. 0) range=xmax
	if (tlim .eq. 0 .or. tlim .gt. ymax) tlim=ymax
	irange=0
	if (range .gt. 0) then
	  if (unit .ge. 3) then ! Ohm
	    curr=amps(excit)
	    rl=range*curr	! convert Ohm to V
	    if (rl .gt. 5.0) then
!	      print *,'Warning: maximum range exceeded: '
!	1       , range,'>',5/curr,' Ohm',char(7)
!	      errstat=max(errstat,1)
	      irange=12
	    endif
	  else
	    rl=range ! V
	  endif
	  if (irange .eq. 0) then
	    if (stype.eq.12) then
	      j=6
	    else
	      j=nvolts
	    end if
	    do i=1,j
	      if (rl .le. volts(i)) then
	        irange=i
	        goto 150
	      endif
	    enddo
!	    print *,'Warning: maximum range exceeded: ', range,' > ',volts(j),' V',char(7)
!	    errstat=max(errstat,1)
	    irange=j
150	    continue
	    if (excit .eq. 11) then ! 10 mV excit -> min. 10 mV range
	      if (irange .lt. 4) irange=4
	    endif
	  endif
	else
	  irange=defr(stype)
	  range=xmax
	endif
	if (stdcurv.eq.0) then
	  if (unit .ge. 3) then
	    if (range*amps(excit) .gt. volts(irange)) then
	      print *,'Warning: max. range exceeded: '
	1      ,range,' > ',volts(irange)/amps(excit),' Ohm',char(7)
	      errstat=max(errstat,1)
	    endif
	  else if (range .gt. volts(irange)) then
	    print *,'Warning: max. range exceeded: '
	1     ,range,' > ',volts(irange), ' V',char(7)
	    errstat=max(errstat,1)
	  endif
	endif

	if (stype .gt. 0) then
	  if (excit .le. 0) excit=defe(stype)
	  if (irange .eq. 0) irange=defr(stype)
	endif
	if (verbose) then
	  print *,'Sensor type:	',types(stype)
	  print *,'Excitation:	 ',excits(excit)
	  if (unit .eq. 1) then
	    print *,'Sensor Range: ',volts(irange)*1000,' mV'
	  elseif (unit .eq. 2) then
	    print *,'Sensor Range: ',volts(irange),' V'
	  else
	    print *,'Sensor Range: ',volts(irange)/amps(excit),' Ohm'
	    if (unit .eq. 5) then
	      print *,'table double logarithmic'
	    elseif (unit .eq. 4) then
	      print *,'table logarithmic'
	    else
	      print *,'table linear'
	    endif
	  endif
	  if (coef .eq. 1) then
	    print *,'negative characteristic'
	  else
	    print *,'positive characteristic'
	  endif
	  print *
	endif

	if (stype .eq. 0) then
	  if (unit .ge. 3) then
	    iunit=2
	  else
	    iunit=1
	  endif
	else
	  if (unit .le. 2) then ! mV / V
	    iunit=1
	  else ! Ohm
	    iunit=2
	  endif
	  if (iunit .ne. defu(stype) .or. 
	1     coef  .ne. defc(stype) .or. 
	1     excit .ne. defe(stype) .or. 
	1     irange.ne. defr(stype)) then
	    if (stype .ne. 12) stype=0
	  endif
	endif


	if (stype .eq. 12) then
	  l=5
	  write (line(1:l), '(a,i1)') ',,,,',max(0,irange-5)
	elseif (stype .eq. 0) then
	  l=14
	  write (line(1:l), '(i2,4(a,i2.0))')
	1   stype,',',iunit,',',coef,',',excit,',',irange
	else
	  l=2
	  write(line(1:l), '(i2)') stype
	endif

	call str_substitute(intype, line(1:l), ' ', char(0))
	call str_trim(intype, intype, li)

	if (tlim .gt. 1500) tlim=1500
	if (tlim .lt. 0) tlim=0

	if (stdcurv.eq.0) then
!	  calculate crc of table
	  crc=0
	  do i=1,np
	    call pack(line, l, x(i), y(i), i-1, 1)
	    call str_crc(crc, line(1:l))
	  enddo
	  call str_crc_comp(crc, crcmp)
	  write (header, "(a,x,a,',',a,',',i1,',',f8.3,',',i1)")
	1   name(1:11), crcmp,sensor,unit,tlim,coef
	else
	  crc=0
	  header=stdhdr(stdcurv)
	endif

	! compare with old file
	call str_trim(filnam, sensor, l)
	call str_lowcase(filnam, filnam)
	filnam(l+1:)='.crv'
	if (path(1:lp) .ne. ' ') then
	  filnam=path(1:lp)//filnam
	endif
	open(unit=2, file=filnam, status='old', iostat=iostat)
	if (iostat .ne. 0) goto 198
	read(2, '(a)',end=199) old
	if (old .ne. header) goto 199
	read(2, '(a)', end=199) old
	if (old .ne. intype) goto 199
	if (stdcurv .ne. 0) then
	  write(line, '(a, i2)') '$',stdcurv
	  read(2, '(a)', end=199) old
	  if (line .ne. old) goto 199
	  read(2, '(a)', end=197) old ! goto end (o.k.) if no more line
	  goto 199
	endif
	do i=1,np,ncolumn
	  read(2, '(a)', end=199) old	
	  call pack(line, l, x(i), y(i), i-1, min(ncolumn,np-i+1))
	  if (line .ne. old) goto 199
	enddo
	read(2, '(a)', end=199) old	
	call pack(line, l, 0.0, 0.0, np, 1)
	if (line .ne. old) goto 199
	read(2, '(a)', end=197) old ! goto end (o.k.) if no more line
	goto 199
197	close(2)
	if (verbose) print *,'curve file has not changed: ',filnam
	goto 200
!	goto 999

198	if (verbose) print *,'create new curve file: ',filnam
	nlist=nlist+1
	list(nlist)='created '//filnam
	goto 200

199	close(2)
	if (verbose) print *,'modify curve file: ',filnam
	nlist=nlist+1
	list(nlist)='modified '//filnam
200	continue
	open(unit=2, file=filnam, status='unknown', iostat=iostat)
	if (iostat .ne. 0) then
	  call str_trim(filnam, filnam, l)
	  print *,'can not open ',filnam(1:l)
	  nlist=nlist-1
	  lin=-1
	  return
	endif
	call str_trim(header, header, l)
	write(2, '(a)') header(1:l)
	write(2, '(a)') intype(1:li)
	if (stdcurv .ne. 0) then
	  write(2, '(a,i2)') '$',stdcurv
	else
	  do i=1,np,ncolumn
	    call pack(line, l, x(i), y(i), i-1, min(ncolumn,np-i+1))
	    write(2,'(a)') line(1:l)
	  enddo
	  call pack(line, l, 0.0, 0.0, np, 1)
	  write(2,'(a)') line(1:l)
	endif
	close(2)
999	continue
	if (errstat .gt. 0) then
	  if (name.eq.' ') name='<unknown>'
	  nlist=nlist+1
	  if (errstat .gt. 1) then
	    list(nlist)='error in '//file(1:lf)//', curve '//name
	    if (verbose) print *,'no curve file written'
	    lin=-1
	  else
	    list(nlist)='warning in '//file(1:lf)//', curve '//name
	  endif
	endif
	if (eof) lin=-1
	return
	end


	integer function lsc_getno(list, n, name)

	integer n
	character list(n)*(*), name*(*)
	character str*32

	integer i,l

	call str_trim(name, name, l)
	l=min(l,len(str))
	do i=1,n
	  call str_upcase(str(1:l), list(i))
	  if (name(1:l) .eq. str(1:l)) then
	    lsc_getno=i
	    RETURN
	  endif
	enddo
	lsc_getno=0
	end


	subroutine lsc_errinit(lunit)

	include 'conv.inc'
	
	integer lunit

	lun=lunit
	pos=0
	errstat=0
	end


	subroutine lsc_error(lin, text)

	include 'conv.inc'
	
	integer lin
	character text*(*)

	integer i,l
	character line*132

	if (pos .eq. 0) then
	  print *
	endif
	if (lin .gt. pos) then
	  rewind lun
	  do i=1,lin-1
	    read(lun, '(a)', end=8) line
	    call str_trim(line, line, l)
	    if (i .gt. max(pos,lin-3)) then
	      print '(5x,a)',line(1:l)
	    endif
	  enddo
	  read(lun, '(a)', end=8) line
	  call str_trim(line, line, l)
	  print '(x,2a)','>>> ',line(1:l)
8	 pos=lin
	  errstat=2
	endif

9	print '(x,a)', text
	end
