module globals integer, parameter :: maxentries=15000 integer, parameter :: maxnamelen=200 integer, parameter :: maxlangs=150 character (len=30) :: filename = 'spice_large.incl' character (len=20) :: langs(maxlangs) logical :: mclass(maxlangs) character (len=3) :: codes(maxlangs) character (len=200):: misslangs = ' ' integer :: nlangs integer :: longestname = 0 end module globals program index use globals !use f90_unix_proc implicit none character (len=maxnamelen) :: names(maxentries,5) integer :: nentries,i,j open (1,file='spice_large.txt',status='old') open (2,file='x.x',status='unknown') open (3,file=filename,status='unknown', recl=500) open (4,file='spice_large.engl',status='unknown') open (5,file='spice_large.germ',status='unknown') open (16,file='langs.txt',status='old') call load_langs (16) close (16) call load_names (names,nentries) call sort_names (names,nentries) call writ_names (names,nentries) ! print*,'Changing character references' ! call system ('./spice_large.csh') end program index subroutine load_names (names,nentries) ! Reads data file and puts its contetnts in _names(i,{1,2,3})_ ! names(i,1) = Anchor (e.g., Myristica_fragrans) ! names(i,2) = Name (e.g., Muskatnuß) ! names(i,3) = Language (e.g., German) ! names(i,4) is unused here, but will later become the ! sort key (e.g., muskatnus) (see routine create_sort_key) ! names(i,5) = Plant identity, normally empty use globals implicit none character (len=maxnamelen) :: names(maxentries,5) integer :: nentries, istat, nspices, pos character (len=maxnamelen) :: anchor, name, language character (len=maxnamelen) :: line nentries=1 nspices=0 do read (1,iostat=istat,fmt='(a)') line if (istat /= 0) exit if (line(1:1) == '*' .or. line ==' ') cycle if (line(1:1) /= ' ') then anchor=line nspices=nspices+1 else pos=index(line,'|') if (pos /= 0) then names(nentries, 5) = line(pos+1:) line=line(:pos-1) else names(nentries, 5) = ' ' endif call get_name_and_lang(line(2:),name,language) names(nentries,1)=anchor names(nentries,2)=name if (len_trim(name) > longestname) longestname = len_trim(name) names(nentries,3)=language nentries=nentries+1 if (nentries > maxentries) then print*,'Memory overflow: Increase MAXENTRIES!' stop endif endif enddo close (1) nentries=nentries-1 print '(tr1,i5,a,i3,a)', nentries,' entries sucessfully read (', & & nspices,' anchors)' return end subroutine load_names subroutine get_name_and_lang (source,name,lang) ! Separates name and language, input _source_, output _name_ and _lang_ ! Separator is either first comma or any semicolon not involved in HTML ! character notation. use globals implicit none character (len=*) :: source,name,lang character (len=maxnamelen) :: lang1,l character (len=100) :: cut_word logical :: semicolon, ampersand, comma, first integer :: pos, i character (len=1) :: char logical :: found ampersand = .false. semicolon = .false. comma = .false. pos = 0 do i=1,len_trim(source) char=source(i:i) if (char == '&') then if (ampersand) then print*,'double ampersand error' print*,source stop else ampersand=.true. endif else if (char == ';') then if (ampersand) then ampersand = .false. else semicolon = .true. pos=i exit endif else if (char == ',') then if (.not.comma) then comma = .true. pos=i endif endif enddo if (pos == 0) then print*,'Unstructured record error:' print*,source stop endif name=source(:pos-1) lang=source(pos+1:) do while (lang(1:1) == ' ') lang=lang(2:) enddo lang1=lang found=.false. do l=cut_word(lang1) if (l==' ') exit do i=1,nlangs found = found .or. (l == langs(i)) if (found) exit enddo if (.not.found) then if (index(misslangs, trim(l)//' ') == 0) then misslangs = trim(misslangs) // ' ' // l print*,'WARNING: Unknown language: ',trim(l) endif endif enddo if (index(lang,',')>0) then lang=trim(lang) // ',' first=.true. do i=1,nlangs if (index(lang,trim(langs(i))//',') >0 ) then if (first) then lang1=langs(i) first=.false. else lang1=trim(lang1) // ', ' // langs(i) endif endif enddo lang=lang1 endif return end subroutine get_name_and_lang subroutine sort_names(names,nentries) ! Creates sort key from _names(i,2)_ to _names(i,4)_ and sorts ascendingly use globals implicit none character (len=maxnamelen) :: names(maxentries,5),foo integer :: nentries,i,j,k,ptr call create_sort_key(names,nentries) do i=1,nentries-1 ! straight selection sort ptr=i do j=i+1,nentries if (names(j,4) < names(ptr,4)) ptr=j enddo do k=1,5 foo=names(i,k) names(i,k)=names(ptr,k) names(ptr,k)=foo enddo enddo if (.false.) then do i=1,nentries if (names(i,4)(1:1) == 'w') then print '(2(tr2,a20))', names(i,2),names(i,4) endif enddo endif print*,'Entries sorted' end subroutine sort_names subroutine create_sort_key(names,nentries) ! names(i,4)= new sort key: lowercase, blanks removed, _&abc;_ resolved to _a_ ! special cases: _ß_ resolved to _ss_ ! _ð_ resolved to _d_ ! _&schwa resolved to _e_ ! _&XYlig;_ resolved to _XY_ ! use globals implicit none character (len=maxnamelen) :: names(maxentries,5) integer :: nentries,i,j,k,inte,ce_start character (len=maxnamelen) :: name,sort character (len=16) :: equiv_char, ce_sequence character (len=1) :: char logical :: ampersand do i=1,nentries name=names(i,2) sort=' ' ampersand=.false. ! inside an html entity do j=1,len_trim(name) char=name(j:j) if (char=='-' .or. char==' ') char=' ' if (char=='''') char=' ' inte=ichar(char) if (inte >= ichar("A") .and. inte <= ichar("Z")) then char=achar(inte - (ichar("A") - ichar("a"))) else if ( sort == ' ' .and. char /= '&' .and. .not. ampersand ) then print*,'Non-capital (',char,'): ', trim(name) endif endif if (ampersand) then if (char == ';') then ampersand=.false. ce_sequence = name(ce_start:j) do k=1, len_trim (ce_sequence) char=ce_sequence(k:k) inte=ichar(char) if (inte >= ichar("A") .and. inte <= ichar("Z")) then ce_sequence(k:k)=achar(inte - (ichar("A") - ichar("a"))) endif enddo if (ce_sequence == 'ß') then equiv_char='ss' else if (ce_sequence == '&schwa;' .or. ce_sequence == '&SCHWA;') then equiv_char='e' else if (ce_sequence == 'ð') then equiv_char='d' else if (ce_sequence == 'þ') then equiv_char='th' else if (ce_sequence(4:) == 'lig;') then equiv_char=ce_sequence(2:3) endif sort = trim(sort) // trim(equiv_char) endif else if (char == '&') then ampersand=.true. ce_start=j equiv_char=name(j+1:j+1) inte=ichar(equiv_char(1:1)) if (inte >= ichar("A") .and. inte <= ichar("Z")) then equiv_char=achar(inte - (ichar("A") - ichar("a"))) else if (sort == ' ') then print*,'Non-capital entity: ', trim(name) endif endif else sort = trim(sort) // char endif endif enddo names(i,4)=sort enddo do i=1,nentries ! print '(i7,tr2,2a35)',i,names(i,2),names(i,4) enddo return end subroutine create_sort_key subroutine writ_names (names,nentries) ! Punches the sorted names use globals implicit none character (len=maxnamelen) :: names(maxentries,5) character (len=maxnamelen) :: last_name, last_anchor character (len=maxnamelen) :: current_anchor, current_name, current_lang, current_bot, current_entry character (len=1) :: init,oldinit(3) character (len=13) :: makelink, link1, link2, link3 character (len=99) :: makelang, langspec character (len=300) :: langhandle integer :: i,nentries,j,k integer :: countla=0, countde=0, counten=0 logical :: first oldinit=achar(ichar("A")-1) last_anchor=' ' last_name=' ' do k=1,3 do i=ichar("A"), ichar("Z") write (2+k,'(5a)') ' ',achar(i),& & ' ' enddo write (2+k,'(tr1,A)') '
' enddo first=.true. do i=1,nentries init=names(i,2)(1:1) if (init == "&") init=names(i,2)(2:2) do k=1,3 if (init /= oldinit(k)) then do j=ichar(oldinit(k))+1,ichar(init) if (.not. first) write (k+2,*) '' write (k+2,'(/,8a,/)') & & '
', &
& trim(current_entry(:longestname+4)) , &
& ' ',trim(langhandle(current_lang))
! write (3,'(20a)') ' ', &
! & trim(current_entry(:longestname+4)) , &
! & ' (',trim(current_lang),')'
if (index(current_lang,'English') /= 0) then
counten=counten+1
write (4,'(5a)') &
& ' ', trim(current_entry)
endif
if (index(current_lang,'German') /= 0) then
countde=countde+1
write (5,'(5a)') &
& ' ', trim(current_entry)
endif
if (current_lang == 'Latin [bot.]') then
do k=4,5
write (k,'(5a)') &
& '