Fparser.f90 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. PROGRAM fparser
  2. !-
  3. !$Id: Fparser.f90 2281 2010-10-15 14:21:13Z smasson $
  4. !-
  5. ! This software is governed by the CeCILL license
  6. ! See IOIPSL/IOIPSL_License_CeCILL.txt
  7. USE stringop
  8. IMPLICIT NONE
  9. !
  10. !
  11. ! Parses the code to create the Config.in Config.default and Config.help
  12. ! which are used by the tk shell.
  13. !
  14. !
  15. INTEGER nbkeymax, nbhelpmax, nbcasemax, nbsourmax, nbelmax
  16. PARAMETER (nbkeymax=100, nbhelpmax=50, nbcasemax=50, nbsourmax=20,nbelmax=nbhelpmax+10)
  17. INTEGER nbfilesmax
  18. PARAMETER (nbfilesmax=150)
  19. !
  20. CHARACTER*120 :: configs(nbkeymax,nbelmax)
  21. CHARACTER*120 :: tmp_help, tmp_key, tmp_desc, tmp_def
  22. INTEGER :: keylen(nbkeymax), nbkeys
  23. INTEGER :: key_pos(nbkeymax), help_pos(nbkeymax,2), def_pos(nbkeymax,2)
  24. INTEGER :: des_pos(nbkeymax), IF_pos(nbkeymax)
  25. CHARACTER*6 TYPE_op(nbkeymax)
  26. !
  27. CHARACTER*120 :: def_out(nbkeymax, nbhelpmax)
  28. INTEGER :: nbdef_out(nbkeymax)
  29. !
  30. CHARACTER*120 :: tke
  31. !
  32. CHARACTER*2 :: nbstr
  33. !
  34. CHARACTER*80 :: files(nbfilesmax), source(nbsourmax), filetmp
  35. CHARACTER*80 :: tmp, main_name
  36. CHARACTER*120 :: keycase(nbcasemax), tmp_CASE
  37. INTEGER :: nbcase, ii, find, nbsource
  38. LOGICAL :: next_source, next_name, last_or
  39. LOGICAL :: is_main, cont
  40. CHARACTER*1 :: backslash, simplequote, doublequote
  41. INTEGER :: ia, iread, iret, IFF, ih, nb_line, iv, id
  42. INTEGER :: ind_space, ind_comma, ind_USE
  43. INTEGER :: nbfiles, nb_key, nb_key_file
  44. !
  45. INTEGER, EXTERNAL :: iargc, getarg
  46. !
  47. !
  48. next_source = .FALSE.
  49. next_name = .FALSE.
  50. is_main = .FALSE.
  51. nbsource = 0
  52. nbfiles = 0
  53. main_name = 'IPSL'
  54. !
  55. backslash = ACHAR(92)
  56. simplequote = ACHAR(39)
  57. doublequote = ACHAR(34)
  58. !
  59. !
  60. !
  61. ! Analyse command line
  62. !
  63. !
  64. ! Get the number of arguments, that is the options and the
  65. ! files to be parsed.
  66. !
  67. !
  68. iread = iargc()
  69. !
  70. DO ia=1,iread
  71. !
  72. iret = getarg(ia,tmp)
  73. !
  74. IF (next_source) THEN
  75. nbsource = nbsource + 1
  76. IF ( nbsource .GT. nbsourmax) THEN
  77. WRITE(*,*) 'Too many files to source in the arguments.'
  78. WRITE(*,*) 'Increase nbsourmax'
  79. STOP
  80. ELSE
  81. source(nbsource) = tmp(1:LEN_TRIM(tmp))
  82. ENDIF
  83. next_source = .FALSE.
  84. ELSE IF (next_name) THEN
  85. main_name = tmp(1:LEN_TRIM(tmp))
  86. next_name = .FALSE.
  87. ELSE
  88. !
  89. IF ( INDEX(tmp,'-m') .GT. 0) THEN
  90. is_main = .TRUE.
  91. ELSE IF ( INDEX(tmp,'-n') .GT. 0) THEN
  92. next_name = .TRUE.
  93. ELSE IF ( INDEX(tmp,'-s') .GT. 0) THEN
  94. next_source = .TRUE.
  95. ELSE IF ( INDEX(tmp,'-h') .GT. 0) THEN
  96. WRITE(*,*) 'USAGE : Fparse [-name NAME] '
  97. WRITE(*,*) ' [-source file_to_source]'
  98. WRITE(*,*) ' [-main] FORTAN_files'
  99. ELSE
  100. nbfiles = nbfiles + 1
  101. IF ( nbfiles .GT. nbfilesmax) THEN
  102. WRITE(*,*) 'Too many files to include in &
  103. & the arguments.'
  104. WRITE(*,*) 'Increase nbfilesmax'
  105. STOP
  106. ELSE
  107. files(nbfiles) = tmp(1:LEN_TRIM(tmp))
  108. ENDIF
  109. ENDIF
  110. ENDIF
  111. ENDDO
  112. !
  113. IF ( nbfiles .LT. 1 ) THEN
  114. WRITE(*,*) 'No files provided'
  115. STOP
  116. ENDIF
  117. !
  118. !
  119. ! 1.0 Read files and extract the lines which we need
  120. !
  121. !
  122. nb_key = 0
  123. !
  124. DO IFF=1,nbfiles
  125. !
  126. filetmp = files(IFF)
  127. CALL READ_from_file(filetmp, nbkeymax, nbelmax, configs, nb_key, keylen)
  128. !
  129. ENDDO
  130. !
  131. ! 2.0 Scan the information we have extracted from the file for the elements we need
  132. !
  133. !
  134. CALL analyse_configs(nbkeymax, nb_key, nbelmax, keylen, configs, key_pos, help_pos, def_pos, des_pos, IF_pos, TYPE_op)
  135. !
  136. !
  137. ! 3.0 Prepare the default values to put them in an array
  138. !
  139. !
  140. DO ia = 1,nb_key
  141. !
  142. ! 3.1 Go to blank delimited lines
  143. !
  144. nbdef_out(ia) = 0
  145. !
  146. DO ii=def_pos(ia,1), def_pos(ia,2)
  147. !
  148. tmp_help = configs(ia,ii)
  149. ind_comma = INDEX(tmp_help(1:len_TRIM(tmp_help)),',')
  150. DO WHILE (ind_comma .GT. 0)
  151. tmp_help(ind_comma:ind_comma) = ' '
  152. ind_comma = INDEX(tmp_help,',')
  153. ENDDO
  154. CALL cmpblank(tmp_help)
  155. configs(ia,ii) = tmp_help
  156. !
  157. ! 3.2 extract the values
  158. !
  159. tmp_help = TRIM(ADJUSTL(configs(ia,ii)))
  160. ind_space= INDEX(tmp_help(1:LEN_TRIM(tmp_help)),' ')
  161. ! Get the first one (there is no space in between)
  162. IF ( ind_space .EQ. 0) THEN
  163. nbdef_out(ia) = nbdef_out(ia) + 1
  164. def_out(ia, nbdef_out(ia)) = tmp_help(1:LEN_TRIM(tmp_help))
  165. ELSE
  166. ! Get all those which are before spaces
  167. DO WHILE (ind_space .GT. 0)
  168. nbdef_out(ia) = nbdef_out(ia) + 1
  169. def_out(ia, nbdef_out(ia)) = tmp_help(1:ind_space)
  170. tmp_help = ADJUSTL(tmp_help(ind_space+1:LEN_TRIM(tmp_help)))
  171. ind_space= INDEX(tmp_help(1:LEN_TRIM(tmp_help)),' ')
  172. ENDDO
  173. ! Get the last one which does not have a space behind
  174. IF ( LEN_TRIM(tmp_help) .GT. 0) THEN
  175. nbdef_out(ia) = nbdef_out(ia) + 1
  176. def_out(ia, nbdef_out(ia)) = tmp_help(1:LEN_TRIM(tmp_help))
  177. ENDIF
  178. !
  179. ENDIF
  180. ENDDO
  181. !
  182. ENDDO
  183. !
  184. !
  185. !
  186. ! 4.0 OPEN Config.in Defaults and Help files
  187. !
  188. !
  189. OPEN (16, FILE='Config.in')
  190. OPEN (17, FILE='Config.help')
  191. OPEN (18, FILE='Config.defaults')
  192. !
  193. ! Some explantation
  194. !
  195. DO IFF=16,18
  196. WRITE(IFF,'(1a)') '# '
  197. WRITE(IFF,'(1a)') '# File created by Fparser, DO NOT EDIT'
  198. WRITE(IFF,'(2a)') '# ', main_name(1:LEN_TRIM(main_name))
  199. WRITE(IFF,'(1a)') '# '
  200. WRITE(IFF,'(1a)') '# '
  201. ENDDO
  202. !
  203. WRITE(17,'(2a)') '# Format of this file: description<nl>', &
  204. & ' variable<nl>helptext<nl><nl>.'
  205. WRITE(17,'(2a)') '# If the question being documented is of', &
  206. & ' type "choice", we list'
  207. WRITE(17,'(2a)') '# only the first occurring config variable.', &
  208. & ' The help texts'
  209. WRITE(17,'(2a)') '# must not contain empty lines. No variable', &
  210. & ' should occur twice; if it'
  211. WRITE(17,'(2a)') '# does, only the first occurrence will be', &
  212. & ' used by Configure. The lines'
  213. WRITE(17,'(2a)') '# in a help text should be indented two', &
  214. & ' positions. Lines starting with'
  215. WRITE(17,'(2a)') '# "#" are ignored. To be nice to menuconfig,', &
  216. & ' limit your lines to 70'
  217. WRITE(17,'(2a)') '# characters. Use emacs" kfill.el to edit', &
  218. & ' this file or you lose.'
  219. WRITE(17,'(2a)') '#'
  220. !
  221. IF ( is_main ) THEN
  222. WRITE(16,'(3a)') 'mainmenu_name "Configuration of model ', &
  223. & main_name(1:LEN_TRIM(main_name)), '"'
  224. WRITE(16,'(1a)') '# '
  225. ENDIF
  226. !
  227. WRITE(16,'(1a)') 'mainmenu_option next_comment'
  228. WRITE(16,'(3a)') 'comment "', main_name(1:LEN_TRIM(main_name)), '"'
  229. WRITE(16,'(1a)') '# '
  230. !
  231. ! 5.0 Loop through the KEYWORDS to prepare the output
  232. !
  233. DO IFF =1,nb_key
  234. !
  235. ! Config.in file
  236. !
  237. !
  238. ! Is it a conditional option ?
  239. !
  240. IF ( IF_pos(IFF) .GE. 0) THEN
  241. tmp_help = configs(IFF,IF_pos(IFF))
  242. !
  243. IF ( (index(tmp_help,'||') .LE. 0) .AND. (index(tmp_help,'&&') .LE. 0) ) THEN
  244. IF ( tmp_help(1:1) .EQ. '!') THEN
  245. WRITE(16,'(3a)') 'if [ "$', tmp_help(2:LEN_TRIM(tmp_help)), '" = "n" ]; then'
  246. ELSE
  247. WRITE(16,'(3a)') 'if [ "$', tmp_help(1:LEN_TRIM(tmp_help)), '" = "y" ]; then'
  248. ENDIF
  249. ELSE
  250. !
  251. last_or = .TRUE.
  252. nbcase = 0
  253. !
  254. DO WHILE( INDEX(tmp_help,'||') .GT. 0)
  255. ii = INDEX(tmp_help,'||')
  256. nbcase = nbcase + 1
  257. if ( nbcase .EQ. 1 ) THEN
  258. IF ( tmp_help(1:1) .EQ. '!') THEN
  259. WRITE(16,'(3a)') 'if [ "$', tmp_help(2:ii-1), '" = "n" \\'
  260. ELSE
  261. WRITE(16,'(3a)') 'if [ "$', tmp_help(1:ii-1), '" = "y" \\'
  262. ENDIF
  263. ELSE
  264. IF ( tmp_help(1:1) .EQ. '!') THEN
  265. WRITE(16,'(3a)') '-o "$', tmp_help(2:ii-1), '" = "n" \\'
  266. ELSE
  267. WRITE(16,'(3a)') '-o "$', tmp_help(1:ii-1), '" = "y" \\'
  268. ENDIF
  269. ENDIF
  270. tmp_help = TRIM(ADJUSTL(tmp_help(ii+2:LEN_TRIM(tmp_help))))
  271. ENDDO
  272. !
  273. DO WHILE( INDEX(tmp_help,'&&') .GT. 0)
  274. ii = INDEX(tmp_help,'&&')
  275. nbcase = nbcase + 1
  276. if ( nbcase .EQ. 1 ) THEN
  277. IF ( tmp_help(1:1) .EQ. '!') THEN
  278. WRITE(16,'(3a)') 'if [ "$', tmp_help(2:ii-1), '" = "n" \\'
  279. ELSE
  280. WRITE(16,'(3a)') 'if [ "$', tmp_help(1:ii-1), '" = "y" \\'
  281. ENDIF
  282. ELSE
  283. IF ( tmp_help(1:1) .EQ. '!') THEN
  284. WRITE(16,'(3a)') '-a "$', tmp_help(2:ii-1), '" = "n" \\'
  285. ELSE
  286. WRITE(16,'(3a)') '-a "$', tmp_help(1:ii-1), '" = "y" \\'
  287. ENDIF
  288. ENDIF
  289. tmp_help = TRIM(ADJUSTL(tmp_help(ii+2:LEN_TRIM(tmp_help))))
  290. last_or = .FALSE.
  291. ENDDO
  292. !
  293. IF ( last_or ) THEN
  294. IF ( tmp_help(1:1) .EQ. '!') THEN
  295. WRITE(16,'(3a)') '-o "$', tmp_help(2:LEN_TRIM(tmp_help)), '" = "n" ]; then'
  296. ELSE
  297. WRITE(16,'(3a)') '-o "$', tmp_help(1:LEN_TRIM(tmp_help)), '" = "y" ]; then'
  298. ENDIF
  299. ELSE
  300. IF ( tmp_help(1:1) .EQ. '!') THEN
  301. WRITE(16,'(3a)') '-a "$', tmp_help(2:LEN_TRIM(tmp_help)), '" = "n" ]; then'
  302. ELSE
  303. WRITE(16,'(3a)') '-a "$', tmp_help(1:LEN_TRIM(tmp_help)), '" = "y" ]; then'
  304. ENDIF
  305. ENDIF
  306. ENDIF
  307. WRITE(16,'(1a)') ' '
  308. ENDIF
  309. !
  310. ! Extract the information from configs
  311. !
  312. DO iv = 1,nbdef_out(IFF)
  313. IF (nbdef_out(IFF) .EQ. 1) THEN
  314. tmp_key = configs(IFF,key_pos(IFF))
  315. tmp_desc = configs(IFF,des_pos(IFF))
  316. tmp_def = def_out(IFF,iv)
  317. ELSE
  318. tmp_key = configs(IFF,key_pos(IFF))
  319. WRITE(nbstr,'(I2.2)') iv
  320. tmp_key = tmp_key(1:LEN_TRIM(tmp_key))//'__'//nbstr
  321. tmp_desc = configs(IFF,des_pos(IFF))
  322. IF ( iv .EQ. 1) THEN
  323. tmp_desc = tmp_desc(1:LEN_TRIM(tmp_desc))//' (Vector)'
  324. ELSE
  325. tmp_desc = 'Cont... '//tmp_key(1:LEN_TRIM(tmp_key))
  326. ENDIF
  327. tmp_def = def_out(IFF,iv)
  328. ENDIF
  329. !
  330. !
  331. !
  332. IF (INDEX(TYPE_op(IFF),'bool') .GT. 0) THEN
  333. !
  334. WRITE(16,'(4a)') 'bool "', tmp_desc(1:LEN_TRIM(tmp_desc)), &
  335. & '" ',tmp_key(1:LEN_TRIM(tmp_key))
  336. !
  337. ELSE IF (INDEX(TYPE_op(IFF),'hex') .GT. 0) THEN
  338. !
  339. WRITE(16,'(6a)') 'hex "', tmp_desc(1:LEN_TRIM(tmp_desc)) &
  340. & ,'" ',tmp_key(1:LEN_TRIM(tmp_key)) &
  341. & ,' ',tmp_def(1:LEN_TRIM(tmp_def))
  342. !
  343. ELSE IF (INDEX(TYPE_op(IFF),'choice') .GT. 0) THEN
  344. !
  345. ! Get number of options
  346. !
  347. nbcase = 0
  348. DO WHILE( INDEX(tmp_key,'||') .GT. 0)
  349. ii = INDEX(tmp_key,'||')
  350. nbcase = nbcase + 1
  351. keycase(nbcase) = tmp_key(1:ii-1)
  352. tmp_key=tmp_key(ii+2:LEN_TRIM(tmp_key))
  353. ENDDO
  354. nbcase = nbcase + 1
  355. keycase(nbcase) = tmp_key(1:LEN_TRIM(tmp_key))
  356. WRITE(16,'(4a)') "choice '", tmp_desc(1:LEN_TRIM(tmp_desc))," '",backslash
  357. !
  358. ! List options
  359. !
  360. tmp_CASE = keycase(1)
  361. WRITE(16,'(5a)') ' "', tmp_CASE(1:LEN_TRIM(tmp_CASE)), " "&
  362. &,tmp_CASE(1:LEN_TRIM(tmp_CASE)), backslash
  363. !
  364. DO ii=2,nbcase-1
  365. tmp_CASE = keycase(ii)
  366. WRITE(16,'(5a)') ' ', tmp_CASE(1:LEN_TRIM(tmp_CASE)), ' ',&
  367. & tmp_CASE(1:LEN_TRIM(tmp_CASE)), backslash
  368. ENDDO
  369. !
  370. tmp_CASE = keycase(nbcase)
  371. WRITE(16,'(6a)') ' ', &
  372. & tmp_CASE(1:LEN_TRIM(tmp_CASE)), &
  373. & ' ', tmp_CASE(1:LEN_TRIM(tmp_CASE)), &
  374. & '" ',tmp_def(1:LEN_TRIM(tmp_def))
  375. !
  376. ELSE
  377. WRITE(*,'(2a)') 'Uniplemented operation : ', TYPE_op(IFF)
  378. STOP
  379. ENDIF
  380. !
  381. ! Config.help file
  382. !
  383. tmp_key = configs(IFF,key_pos(IFF))
  384. IF (INDEX(TYPE_op(IFF),'choice') .GT. 0) THEN
  385. ii = INDEX(tmp_key,'||')-1
  386. ELSE
  387. ii = LEN_TRIM(tmp_key)
  388. ENDIF
  389. IF ( nbdef_out(IFF) .GT. 1) THEN
  390. WRITE(17,'(1a)') tmp_desc(1:LEN_TRIM(tmp_desc))
  391. WRITE(nbstr,'(I2.2)') iv
  392. tke = tmp_key(1:ii)//'__'//nbstr
  393. WRITE(17,'(1a)') tke(1:LEN_TRIM(tke))
  394. WRITE(17,'(1a)') ' (Vector)'
  395. ELSE
  396. WRITE(17,'(1a)') tmp_desc(1:LEN_TRIM(tmp_desc))
  397. WRITE(17,'(1a)') tmp_key(1:ii)
  398. ENDIF
  399. !
  400. DO ih=help_pos(IFF,1),help_pos(IFF,2)
  401. tmp_help = configs(IFF,ih)
  402. WRITE(17,'(" ",1a)') tmp_help(1:LEN_TRIM(tmp_help))
  403. ENDDO
  404. !
  405. ! Config.default file
  406. !
  407. IF (INDEX(TYPE_op(IFF),'choice') .GT. 0) THEN
  408. WRITE(18,'(2a)') tmp_def(1:LEN_TRIM(tmp_def)),'=y'
  409. ELSE
  410. WRITE(18,'(3a)') tmp_key(1:LEN_TRIM(tmp_key)),'=', &
  411. & tmp_def(1:LEN_TRIM(tmp_def))
  412. ENDIF
  413. !
  414. ! Add some empty line to all files
  415. !
  416. WRITE(16,'(1a)') ' '
  417. WRITE(17,'(1a)') ' '
  418. WRITE(17,'(1a)') ' '
  419. ENDDO
  420. !
  421. !
  422. ! Close the IF if needed
  423. !
  424. IF ( IF_pos(IFF) .GT. 0) THEN
  425. WRITE(16,'(1a)') 'fi'
  426. WRITE(16,'(1a)') ' '
  427. ENDIF
  428. !
  429. ENDDO
  430. !
  431. WRITE(16,'(1a)') 'endmenu'
  432. WRITE(16,'(1a)') ' '
  433. IF ( nbsource .GT. 0) THEN
  434. DO ih=1,nbsource
  435. tmp = source(ih)
  436. WRITE(16,'(1a)') ' '
  437. WRITE(16,'(3a)') 'source ',tmp(1:LEN_TRIM(tmp)), &
  438. & '/Config.in'
  439. ENDDO
  440. ENDIF
  441. !
  442. !
  443. CLOSE(16)
  444. CLOSE(17)
  445. CLOSE(18)
  446. !
  447. !
  448. !
  449. STOP
  450. END PROGRAM fparser
  451. !
  452. !
  453. !==========================================================
  454. !
  455. !
  456. SUBROUTINE READ_from_file(file, nbkeymax, nbelmax, configs, nbitems, itemlen)
  457. !
  458. USE stringop
  459. !
  460. IMPLICIT NONE
  461. !
  462. !
  463. ! This routine reads the file and adds the config info it finds to the configs array.
  464. ! Thus the nbitems is an imput variable as it can be increased as we go through the files.
  465. !
  466. !
  467. CHARACTER*(*) :: file
  468. INTEGER :: nbkeymax, nbelmax
  469. CHARACTER*120 :: configs(nbkeymax, nbelmax)
  470. INTEGER :: nbitems, itemlen(nbkeymax)
  471. !
  472. INTEGER :: conf_pos, ip
  473. CHARACTER*250 line
  474. LOGICAL :: cont, conf_END
  475. !
  476. cont = .TRUE.
  477. conf_END = .TRUE.
  478. !
  479. OPEN (12, file=file)
  480. !
  481. ! 1.0 Loop over all the lines of a given file to extract all the configuration line
  482. !
  483. DO WHILE (cont)
  484. READ(12,'(a)',END=9999) line
  485. !
  486. ! 1.0 A configuration line is detected by the line below.
  487. !
  488. IF ( INDEX(line,'Config') .EQ. 1 .OR. INDEX(line,'!'//'Config') .GE. 1 ) THEN
  489. !
  490. IF ( conf_END ) THEN
  491. nbitems = nbitems + 1
  492. IF ( nbitems .GT. nbkeymax) THEN
  493. WRITE(*,*) 'read_from_file : The number of keys in the input array is too small for this file'
  494. STOP
  495. ENDIF
  496. itemlen(nbitems) = 0
  497. conf_END = .FALSE.
  498. ENDIF
  499. !
  500. itemlen(nbitems) = itemlen(nbitems) + 1
  501. IF ( itemlen(nbitems) .GT. nbelmax ) THEN
  502. WRITE(*,*) 'read_from_file : The number of elements per key in the input array is too small'
  503. STOP
  504. ENDIF
  505. !
  506. ! The detected line is shaved !
  507. !
  508. IF ( INDEX(line,'Config') .EQ. 1) THEN
  509. conf_pos = 7
  510. ELSE
  511. conf_pos = INDEX(line,'!'//'Config') +7
  512. ENDIF
  513. line = line(conf_pos:LEN_TRIM(line))
  514. line = TRIM(ADJUSTL(line))
  515. CALL cmpblank(line)
  516. !
  517. configs(nbitems,itemlen(nbitems)) = line
  518. !
  519. ELSE
  520. !
  521. ! Look for the end of a configuration structure.
  522. ! It is determined by a call to the getin subroutine
  523. !
  524. CALL strlowercase(line)
  525. CALL cmpblank(line)
  526. ip = INDEX(line,' (')
  527. DO WHILE (ip .GT. 0)
  528. line = line(1:ip-1)//line(ip+1:LEN_TRIM(line))
  529. ip = INDEX(line,' (')
  530. ENDDO
  531. IF ( INDEX(line, 'call getin(') .GT. 0 .OR. INDEX(line, 'call setvar(') .GT. 0) THEN
  532. conf_END = .TRUE.
  533. ENDIF
  534. !
  535. ENDIF
  536. !
  537. cont = .TRUE.
  538. GOTO 8888
  539. 9999 cont = .FALSE.
  540. 8888 CONTINUE
  541. ENDDO
  542. !
  543. CLOSE(12)
  544. !
  545. END SUBROUTINE READ_from_file
  546. !
  547. !==========================================================
  548. !
  549. !
  550. SUBROUTINE analyse_configs(nbkmax, nb_key, nbelmax, keylen, configs, key_pos, help_pos, def_pos, des_pos, IF_pos, TYPE_op)
  551. !
  552. USE stringop
  553. !
  554. IMPLICIT NONE
  555. !
  556. !
  557. ! This subroutine will localize the KEYWORDS in the configs array
  558. ! and extract all their arguments. For the moment 5 arguments are recognized :
  559. ! KEY : The keyword by which the all is identified
  560. ! HELP : This identifies the help text
  561. ! DEF : The default value of for this KEYWORD
  562. ! DESC : A short description, not more than one line
  563. ! IF : Specifies the other Keyword it depend on. This is a nice features for the menus as it can hide
  564. ! things we do not need
  565. !
  566. ! The DEF and HELP keywords can be multi line
  567. !
  568. INTEGER :: nbkmax, nb_key, nbelmax
  569. INTEGER :: keylen(nbkmax)
  570. INTEGER :: key_pos(nbkmax), help_pos(nbkmax,2), def_pos(nbkmax,2), des_pos(nbkmax), IF_pos(nbkmax)
  571. CHARACTER*120 :: configs(nbkmax,nbelmax)
  572. CHARACTER*6 :: TYPE_op(nbkmax)
  573. !
  574. ! This is the number of arguments we need to find an end for and the total number of arguments we can have.
  575. ! Thus these parameters needs to be updated when the list of arguments to the routine is changed
  576. !
  577. INTEGER, PARAMETER :: toendlen=2, indexlen=5
  578. !
  579. INTEGER :: toend(toendlen), foundend(toendlen), kindex(indexlen)
  580. INTEGER :: ik, il, ieq
  581. CHARACTER*120 :: tmp_str, tmp_str2
  582. !
  583. !
  584. key_pos(1:nb_key)=-1
  585. help_pos(1:nb_key,1:2)=-1
  586. def_pos(1:nb_key,1:2)=-1
  587. des_pos(1:nb_key)=-1
  588. IF_pos(1:nb_key)=-1
  589. TYPE_op(1:nb_key)='hex'
  590. !
  591. DO ik=1,nb_key
  592. !
  593. !
  594. DO il=1,keylen(ik)
  595. !
  596. ieq = INDEX(configs(ik,il),'=')
  597. tmp_str = configs(ik,il)
  598. tmp_str = tmp_str(1:ieq)
  599. CALL struppercase(tmp_str)
  600. !
  601. ! Decide if this is a reserved name and where it fits
  602. !
  603. ! At the same time we clean up the configs array
  604. !
  605. IF ( INDEX(tmp_str,'KEY') .GT. 0) THEN
  606. IF ( key_pos(ik) .GT. 0) THEN
  607. WRITE(*,*) 'analyse_config : Already have a KEYWORD, check that you have a call to getin'
  608. WRITE(*,*) 'analyse_config : ', configs(ik,il)
  609. STOP
  610. ENDIF
  611. key_pos(ik) = il
  612. tmp_str2 = configs(ik,il)
  613. tmp_str2 = tmp_str2(ieq+1:LEN_TRIM(tmp_str2))
  614. configs(ik,il) = TRIM(ADJUSTL(tmp_str2))
  615. !
  616. ! Here we have to check that we are not in an 'choice' case
  617. !
  618. IF ( INDEX(tmp_str2,'||') .GT. 0) THEN
  619. TYPE_op(ik) = 'choice'
  620. ENDIF
  621. !
  622. ENDIF
  623. !
  624. IF ( INDEX(tmp_str,'DEF') .GT. 0) THEN
  625. IF ( def_pos(ik,1) .GT. 0) THEN
  626. WRITE(*,*) 'analyse_config : Already have a DEF, check that you have a call to getin'
  627. WRITE(*,*) 'analyse_config : ', configs(ik,il)
  628. STOP
  629. ENDIF
  630. def_pos(ik,1) = il
  631. tmp_str2 = configs(ik,il)
  632. tmp_str2 = tmp_str2(ieq+1:LEN_TRIM(tmp_str2))
  633. tmp_str2 = TRIM(ADJUSTL(tmp_str2))
  634. configs(ik,il) = tmp_str2
  635. !
  636. ! Here we can check if we have a boolean operation
  637. ! We also wish to standardise the value of booleans
  638. !
  639. CALL struppercase(tmp_str2)
  640. IF (INDEX(tmp_str2,'Y') .EQ. 1 .AND. LEN_TRIM(tmp_str2) .EQ. 1 .OR.&
  641. & INDEX(tmp_str2,'T') .EQ. 1 .AND. LEN_TRIM(tmp_str2) .EQ. 1 .OR.&
  642. & INDEX(tmp_str2,'YES') .EQ. 1 .AND. LEN_TRIM(tmp_str2) .EQ. 3 .OR.&
  643. & INDEX(tmp_str2,'TRUE') .EQ. 1 .AND. LEN_TRIM(tmp_str2) .EQ. 4 .OR.&
  644. & INDEX(tmp_str2,'.TRUE.') .EQ. 1) THEN
  645. configs(ik,il) = 'y'
  646. TYPE_op(ik) = 'bool'
  647. ENDIF
  648. !
  649. IF (INDEX(tmp_str2,'N') .EQ. 1 .AND. LEN_TRIM(tmp_str2) .EQ. 1 .OR.&
  650. & INDEX(tmp_str2,'F') .EQ. 1 .AND. LEN_TRIM(tmp_str2) .EQ. 1 .OR.&
  651. & INDEX(tmp_str2,'NO') .EQ. 1 .AND. LEN_TRIM(tmp_str2) .EQ. 2 .OR.&
  652. & INDEX(tmp_str2,'FALSE') .EQ. 1 .AND. LEN_TRIM(tmp_str2) .EQ. 5 .OR.&
  653. & INDEX(tmp_str2,'.FALSE.') .EQ. 1) THEN
  654. configs(ik,il) = 'n'
  655. TYPE_op(ik) = 'bool'
  656. ENDIF
  657. !
  658. ! Here we check if we have a default behavior and put a standard name
  659. !
  660. IF (INDEX(tmp_str2,'DEF') .EQ. 1 .OR. INDEX(tmp_str2,'NONE') .EQ. 1) THEN
  661. configs(ik,il) = 'default'
  662. ENDIF
  663. !
  664. ENDIF
  665. !
  666. IF ( INDEX(tmp_str,'DESC') .GT. 0) THEN
  667. IF ( des_pos(ik) .GT. 0) THEN
  668. WRITE(*,*) 'analyse_config : Already have a DESC, check that you have a call to getin'
  669. WRITE(*,*) 'analyse_config : ', configs(ik,il)
  670. STOP
  671. ENDIF
  672. des_pos(ik) = il
  673. tmp_str2 = configs(ik,il)
  674. tmp_str2 = tmp_str2(ieq+1:LEN_TRIM(tmp_str2))
  675. configs(ik,il) = TRIM(ADJUSTL(tmp_str2))
  676. ENDIF
  677. !
  678. IF ( INDEX(tmp_str,'IF') .GT. 0) THEN
  679. IF ( IF_pos(ik) .GT. 0) THEN
  680. WRITE(*,*) 'analyse_config : Already have a IF, check that you have a call to getin'
  681. WRITE(*,*) 'analyse_config : ', configs(ik,il)
  682. STOP
  683. ENDIF
  684. IF_pos(ik) = il
  685. tmp_str2 = configs(ik,il)
  686. tmp_str2 = tmp_str2(ieq+1:LEN_TRIM(tmp_str2))
  687. configs(ik,il) = TRIM(ADJUSTL(tmp_str2))
  688. ENDIF
  689. !
  690. IF ( INDEX(tmp_str,'HELP') .GT. 0) THEN
  691. help_pos(ik,1) = il
  692. tmp_str2 = configs(ik,il)
  693. tmp_str2 = tmp_str2(ieq+1:LEN_TRIM(tmp_str2))
  694. configs(ik,il) = TRIM(ADJUSTL(tmp_str2))
  695. ENDIF
  696. !
  697. ENDDO
  698. !
  699. ! Check if we not missing some important informations as for instance
  700. !
  701. ! THE KEYWORD
  702. !
  703. IF ( key_pos(ik) .LT. 1) THEN
  704. WRITE(*,*) 'analyse_configs : Could not find a keyword in the following entry :'
  705. DO il=1,keylen(ik)
  706. WRITE(*,'(a70)') configs(ik,il)
  707. ENDDO
  708. STOP
  709. ENDIF
  710. !
  711. ! THE DEFAULT VALUE
  712. !
  713. IF ( def_pos(ik,1) .LT. 1) THEN
  714. WRITE(*,*) 'analyse_configs : Could not find a default value in the following entry :'
  715. DO il=1,keylen(ik)
  716. WRITE(*,'(a70)') configs(ik,il)
  717. ENDDO
  718. STOP
  719. ENDIF
  720. !
  721. ! Get the end of all the multi line arguments
  722. !
  723. toend(1) = MAX(def_pos(ik,1),1)
  724. toend(2) = MAX(help_pos(ik,1),1)
  725. foundend(:) = keylen(ik)
  726. kindex(1) = MAX(key_pos(ik),1)
  727. kindex(2) = MAX(des_pos(ik),1)
  728. kindex(3) = MAX(def_pos(ik,1),1)
  729. kindex(4) = MAX(IF_pos(ik),1)
  730. kindex(5) = MAX(help_pos(ik,1),1)
  731. CALL find_ends(toendlen, toend, indexlen, kindex, foundend)
  732. def_pos(ik,2) = foundend(1)
  733. help_pos(ik,2) = foundend(2)
  734. !
  735. ENDDO
  736. !
  737. END SUBROUTINE analyse_configs
  738. !
  739. SUBROUTINE find_ends(toendlen, toend, indexlen, kindex, foundend)
  740. !
  741. IMPLICIT NONE
  742. !
  743. !
  744. ! We find the end of the text for all the elements in the key which are multi line
  745. ! This subroutine aims at providing a flexible way to determine this so that other
  746. ! elements in the Keyword can be multi line. For the moment it is only the Help and Ded
  747. ! which are allowed to be multi line.
  748. !
  749. ! Foundend need to be initialized to the maximum value of the elements
  750. !
  751. !
  752. INTEGER :: toendlen, toend(toendlen), indexlen, kindex(indexlen), foundend(toendlen)
  753. !
  754. INTEGER :: whmin(1), ie, ii
  755. !
  756. DO ie=1,toendlen
  757. !
  758. whmin = MINLOC(toend(1:toendlen))
  759. !
  760. DO ii=1,indexlen
  761. IF ( kindex(ii) .GT. toend(whmin(1)) .AND. foundend(whmin(1)) .GE. kindex(ii)) THEN
  762. foundend(whmin(1)) = kindex(ii)-1
  763. toend(whmin(1)) = 100000
  764. ENDIF
  765. ENDDO
  766. !
  767. ENDDO
  768. !
  769. END SUBROUTINE find_ends