Changeset 1897 for trunk/LMDZ.TITAN/libf/muphytitan/cfgparse.F90
- Timestamp:
- Jan 24, 2018, 10:24:24 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LMDZ.TITAN/libf/muphytitan/cfgparse.F90
r1814 r1897 1 ! Copyright Jérémie Burgalat (2010-2015 )2 ! 3 ! burgalat.jeremie@gmail.com4 ! 5 ! This software is a computer program whose purpose is to provide configuration 1 ! Copyright Jérémie Burgalat (2010-2015,2017) 2 ! 3 ! jeremie.burgalat@univ-reims.fr 4 ! 5 ! This software is a computer program whose purpose is to provide configuration 6 6 ! file and command line arguments parsing features to Fortran programs. 7 ! 7 ! 8 8 ! This software is governed by the CeCILL-B license under French law and 9 ! abiding by the rules of distribution of free software. You can use, 9 ! abiding by the rules of distribution of free software. You can use, 10 10 ! modify and/ or redistribute the software under the terms of the CeCILL-B 11 11 ! license as circulated by CEA, CNRS and INRIA at the following URL 12 ! "http://www.cecill.info". 13 ! 12 ! "http://www.cecill.info". 13 ! 14 14 ! As a counterpart to the access to the source code and rights to copy, 15 15 ! modify and redistribute granted by the license, users are provided only 16 16 ! with a limited warranty and the software's author, the holder of the 17 17 ! economic rights, and the successive licensors have only limited 18 ! liability. 19 ! 18 ! liability. 19 ! 20 20 ! In this respect, the user's attention is drawn to the risks associated 21 21 ! with loading, using, modifying and/or developing or reproducing the … … 25 25 ! professionals having in-depth computer knowledge. Users are therefore 26 26 ! encouraged to load and test the software's suitability as regards their 27 ! requirements in conditions enabling the security of their systems and/or 28 ! data to be ensured and, more generally, to use and operate it in the 29 ! same conditions as regards security. 30 ! 27 ! requirements in conditions enabling the security of their systems and/or 28 ! data to be ensured and, more generally, to use and operate it in the 29 ! same conditions as regards security. 30 ! 31 31 ! The fact that you are presently reading this means that you have had 32 32 ! knowledge of the CeCILL-B license and that you accept its terms. 33 33 34 34 !! file: cfgparse.F90 35 !! summary: Configuration file parser source file 36 !! author: burgalat37 !! date: 2013-2015, 35 !! summary: Configuration file parser source file. 36 !! author: J. Burgalat 37 !! date: 2013-2015,2017 38 38 39 39 #include "defined.h" … … 41 41 MODULE CFGPARSE 42 42 !! Configuration file parsing module 43 !! 44 !! This module defines a set of derived types as well as methods to parse configuration files. 43 !! 44 !! This module defines a set of derived types as well as methods to parse configuration files. 45 !! 46 !! If you only wish to have an overview of cfgparse usage, you'd better go 47 !! [here](|url|/page/swift/p02_cfgparse.html). 45 48 !! @todo 46 !! Add interpolation from environment and/or parser options 49 !! Add interpolation from environment and/or parser options. 47 50 USE, INTRINSIC :: ISO_FORTRAN_ENV 48 51 USE ERRORS 49 USE STRING S52 USE STRING_OP 50 53 USE FSYSTEM 51 54 IMPLICIT NONE … … 56 59 cfg_get_value, cfg_set_value, cfg_count, cfg_check_name, & 57 60 cfg_has_option, cfg_has_section, & 61 cfg_option_names,cfg_section_names, & 58 62 cfg_remove_option, cfg_remove_section, & 59 63 cfg_sort_options … … 63 67 ! some public definitions from other modules 64 68 ! from strings 65 PUBLIC :: str_to_lower,st_slen, st_llen69 PUBLIC :: to_lower,st_slen, st_llen 66 70 67 71 PUBLIC :: OPERATOR(==), OPERATOR(/=), ASSIGNMENT(=) … … 76 80 TYPE, PUBLIC :: cfgparser 77 81 !! Define a parser of options 78 !! 79 !! A [[cfgparser(type)]] stores [[option(type)]] objects. 82 !! 83 !! A [[cfgparser(type)]] stores [[option(type)]] objects. 80 84 TYPE(option), DIMENSION(:), ALLOCATABLE :: options !! list of options. 81 85 #if HAVE_FTNPROC … … 124 128 PROCEDURE, PUBLIC :: remove_option => cfg_remove_option 125 129 !> Remove a section (and all the associated options) from the parser. 126 PROCEDURE, PUBLIC :: remove_section => cfg_remove_section 127 !> Get value(s) of an option in the parser by name 128 !! 130 PROCEDURE, PUBLIC :: remove_section => cfg_remove_section 131 !> Get value(s) of an option in the parser by name 132 !! 129 133 !! ``` 130 134 !! FUNCTION cfg_get_value(this,name,output) RESULT(error) … … 135 139 !! On error, __output__ argument is undefined (that is, left unchanged 136 140 !! for scalar versions, **unallocated** for vector version). 137 !! 141 !! 138 142 !! Errors occur in the following situations: 139 143 !! - The option has no value (-6) 140 !! - The option does not exist (-7) 144 !! - The option does not exist (-7) 141 145 !! - The option's value cannot be cast in the desired type (-10) 142 146 GENERIC, PUBLIC :: get_value => cp_get_rv_sc,cp_get_dv_sc,cp_get_iv_sc, & … … 144 148 cp_get_rv_ve,cp_get_dv_ve,cp_get_iv_ve, & 145 149 cp_get_lv_ve,cp_get_cv_ve,cp_get_sv_ve 146 !> Set value(s) of an option in the parser by name 147 !! 150 !> Set value(s) of an option in the parser by name 151 !! 148 152 !! ``` 149 153 !! FUNCTION cfg_set_value(this,name,input,create) RESULT(error) … … 167 171 END TYPE cfgparser 168 172 169 !> Get value(s) of an option in the parser by name. 170 !! 173 !> Get value(s) of an option in the parser by name. 174 !! 171 175 !! ``` 172 176 !! FUNCTION cfg_get_value(parser,name,output) RESULT(error) … … 177 181 !! On error, __output__ argument is undefined (that is, left unchanged 178 182 !! for scalar versions, **unallocated** for vector version). 179 !! 183 !! 180 184 !! Errors occur in the following situations: 181 185 !! - The option has no value (-6) 182 !! - The option does not exist (-7) 186 !! - The option does not exist (-7) 183 187 !! - The option's value cannot be cast in the desired type (-10) 184 188 INTERFACE cfg_get_value … … 189 193 END INTERFACE 190 194 191 !> Set value(s) of an option in the parser by name 192 !! 195 !> Set value(s) of an option in the parser by name 196 !! 193 197 !! ``` 194 198 !! FUNCTION set_value(this,name,input,create) RESULT(error) … … 201 205 !! exist in _this_ parser. 202 206 !! @warning 203 !! In such case, if the given is not valid, an assertionis raised !207 !! In such case, if the given __name__ is not valid, an error is raised ! 204 208 !! 205 209 !! On error (i.e. no option matches the given _name_), no values are set. 206 INTERFACE cfg_set_value 210 INTERFACE cfg_set_value 207 211 MODULE PROCEDURE :: cp_set_rv_sc,cp_set_dv_sc,cp_set_iv_sc, & 208 212 cp_set_lv_sc,cp_set_cv_sc,cp_set_sv_sc, & 209 213 cp_set_rv_ve,cp_set_dv_ve,cp_set_iv_ve, & 210 214 cp_set_lv_ve,cp_set_cv_ve,cp_set_sv_ve 211 END INTERFACE 215 END INTERFACE 212 216 213 217 !> Derived type assignment operator … … 230 234 this%section = other%section 231 235 this%values = other%values 232 END SUBROUTINE op_affect_sc 233 236 END SUBROUTINE op_affect_sc 237 234 238 FUNCTION op_valid(opt) RESULT(ok) 235 239 !! Check whether or not the option is valid (i.e. has name) 236 TYPE(option), INTENT(in) :: opt !! An option object 240 TYPE(option), INTENT(in) :: opt !! An option object 237 241 LOGICAL :: ok !! True if the option is valid, false otherwise. 238 242 ok = LEN_TRIM(opt%name) > 0 239 243 END FUNCTION op_valid 240 244 241 SUBROUTINE op_clear(opt) 245 SUBROUTINE op_clear(opt) 242 246 !! Clear and invalid the given option. 243 TYPE(option), INTENT(inout) :: opt !! An option object 247 TYPE(option), INTENT(inout) :: opt !! An option object 244 248 opt%name = '' 245 249 opt%section = '' … … 261 265 ENDIF 262 266 END FUNCTION op_full_name 263 267 264 268 FUNCTION op_split_name(fname,sname,pname) RESULT(err) 265 269 !> Split a full name in section and option names 266 !! 267 !! The method splits a full name into (section,option) names. Output names (if any) are always 268 !! set to lower case. 270 !! 271 !! The method splits a full name into (section,option) names: 272 !! 273 !! - Option basename is always set in lower-case. 274 !! - If any, section name case is left unmodified. 269 275 !! 270 276 !! A full name simply consists in a section name and an option name separated by a single "/". 271 277 !! 272 !! The method never checks the validity of the output names. Consider using [[cfg_check_name(function)]] 273 !! to do so. 274 !! @note 275 !! If _fname_ does not contains any "/", the method set the special name "\_\_default\_\_" for the output 276 !! section name. 278 !! The method never checks the validity of the output names. Consider using [[cfg_check_name(function)]] 279 !! to do so. 277 280 !! @note 278 !! On success, option and section names are set to lower case. Otherwise they are set to empty strings. 281 !! If _fname_ does not contains any "/", the method sets the special name "\_\_default\_\_" for the output 282 !! section name. 283 !! @note 284 !! On failure, output arguments are set to empty strings. 279 285 !! @warning 280 !! If _fname_ ends with a "/", an error (- 6, invalid name) is raised: the method always assumes it can286 !! If _fname_ ends with a "/", an error (-9, invalid name) is raised: the method always assumes it can 281 287 !! find an option part in the name. 282 288 CHARACTER(len=*), INTENT(in) :: fname !! A name to split 283 289 CHARACTER(len=:), INTENT(out), ALLOCATABLE :: sname, & !! Section part of the name 284 290 pname !! Option part of the name 285 TYPE(error) :: err !! Error status of the method 286 INTEGER :: idx 291 TYPE(error) :: err !! Error status of the method 292 INTEGER :: idx 293 CHARACTER(len=:), ALLOCATABLE :: tfname 287 294 err = noerror ; pname = "" ; sname = "" 295 tfname = op_format(fname,sname,pname) 296 IF (LEN_TRIM(tfname) == 0) err = error("Invalid option name ("//TRIM(fname)//")",-9) 297 END FUNCTION op_split_name 298 299 FUNCTION op_format(name,sname,pname) RESULT(oname) 300 !! Format the input name to be consistent with character case requirements. 301 !! 302 !! Given a **name**, the method tries to split in section/option names. 303 !! Then it converts the option part in lower-case. 304 !! 305 !! If no section part is found (not '/' or set as first character of **name**), the 306 !! special section name `__default__` is set. 307 !! 308 !! If **name** ends with a '/', it is an error and the method returns an empty string. 309 CHARACTER(len=*), INTENT(in) :: name !! Name to format. 310 CHARACTER(len=:), ALLOCATABLE, INTENT(out), OPTIONAL :: sname !! Section part of the name (optional output) 311 CHARACTER(len=:), ALLOCATABLE, INTENT(out), OPTIONAL :: pname !! Option part of the name (optional output) 312 CHARACTER(len=:), ALLOCATABLE :: oname !! Formatted full option name. 313 INTEGER :: idx 314 CHARACTER(len=:), ALLOCATABLE :: zsname,zpname 315 zpname = "" ; zsname = "" 288 316 ! splits input name in sname, pname 289 idx = INDEX(fname,'/') 290 IF (idx == LEN_TRIM(fname)) THEN 291 err = error("Invalid option name ("//TRIM(fname)//")",-9) 317 idx = INDEX(name,'/') 318 IF (idx == LEN_TRIM(name)) THEN 319 oname = '' 320 IF (PRESENT(sname)) sname = '' 321 IF (PRESENT(pname)) pname = '' 292 322 RETURN 293 323 ELSE IF (idx <= 1) THEN 294 sname = "__default__" ; pname = TRIM(fname)295 IF (idx == 1) pname=pname(2:)296 ELSE 297 sname = fname(:idx-1)298 pname = fname(idx+1:LEN_TRIM(fname))299 ENDIF 300 ! 17/12/2014: set option name to lower301 pname = str_to_lower(pname)302 sname = str_to_lower(sname)303 END FUNCTION op_ split_name324 zsname = "__default__" ; zpname = to_lower(TRIM(name)) 325 IF (idx == 1) zpname=zpname(2:) 326 ELSE 327 zsname = name(:idx-1) 328 zpname = to_lower(name(idx+1:LEN_TRIM(name))) 329 ENDIF 330 oname = zsname//"/"//zpname 331 IF (PRESENT(sname)) sname = zsname 332 IF (PRESENT(pname)) pname = zpname 333 END FUNCTION op_format 304 334 305 335 FUNCTION op_greater_than(left,right) RESULT(ret) … … 309 339 TYPE(option), INTENT(in) :: left !! LHS option. 310 340 TYPE(option), INTENT(in) :: right !! RHS option. 311 LOGICAL :: ret 341 LOGICAL :: ret 312 342 !! .true. if LHS is _greater_ than RHS (based on section and option name) 313 343 ret = LGT(op_full_name(left),op_full_name(right)) … … 320 350 TYPE(option), INTENT(in) :: left !! LHS option. 321 351 TYPE(option), INTENT(in) :: right !! RHS option. 322 LOGICAL :: ret 352 LOGICAL :: ret 323 353 !! .true. if LHS is _less_ than RHS (based on section and option name) 324 354 ret = LLT(op_full_name(left),op_full_name(right)) … … 327 357 FUNCTION op_to_str(opt,num_values) RESULT(str) 328 358 !! Get the string representation of a option object 329 !! @note 359 !! @note 330 360 !! If the object is not valid an empty string is returned. 331 TYPE(option), INTENT(in) :: opt 361 TYPE(option), INTENT(in) :: opt 332 362 !! A option object 333 363 INTEGER, INTENT(in), OPTIONAL :: num_values … … 343 373 str = TRIM(opt%name)//" = " ; np = LEN(str) 344 374 ALLOCATE(CHARACTER(len=np) :: nspcs) ; nspcs(1:) = " " 345 ! stores the error but do not check... 375 ! stores the error but do not check... 346 376 ret = words_to_vector(opt%values,vec) 347 377 IF (.NOT.ALLOCATED(vec)) RETURN … … 382 412 383 413 FUNCTION cfg_check_name(name) RESULT(valid) 384 !! Check if a name is valid 385 !! 386 !! A valid option/section name begins with a letter and is followed by any 387 !! number of alphanumeric characters and underscore (`[A-Za-z][A-Za-z0-9\_]\*`). 414 !! Check if a name is valid. 415 !! 416 !! If **name** contains a '/' it is assumed to be a full option name. In such case 417 !! both parts of the name are checked against section/option names requirements (see below). 418 !! 419 !! Otherwise it is assumed to be the basename of the option. 420 !! 421 !! A valid option (base) name is an alphanumeric sequence in lower-case that always begin by 422 !! a letter. 423 !! 424 !! A valid section name is and alphanumeric sequence (in any case) that always begins by 425 !! by a letter. 388 426 CHARACTER(len=*), INTENT(in) :: name !! A string with the name to check. 389 427 LOGICAL :: valid !! .true. if the name is valid, .false. otherwise 390 428 INTEGER :: i 391 CHARACTER(len=26), PARAMETER :: alpha = "abcdefghijklmnopqrstuvwxyz" 392 CHARACTER(len=12), PARAMETER :: num = "0123456789_" 429 CHARACTER(len=26), PARAMETER :: alpha = "abcdefghijklmnopqrstuvwxyz" 430 CHARACTER(len=26), PARAMETER :: ualpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 431 CHARACTER(len=12), PARAMETER :: num = "0123456789_" 393 432 CHARACTER(len=:), ALLOCATABLE :: pname,sname 394 433 TYPE(error) :: err … … 401 440 ENDIF 402 441 ELSE 403 pname = str_to_lower(TRIM(name))442 pname = to_lower(TRIM(name)) 404 443 sname = "__default__" 405 444 ENDIF … … 416 455 i = INDEX(sname,CHAR(32)) 417 456 IF (i /= 0.OR.LEN_TRIM(sname) <= 0) RETURN 418 valid = (VERIFY(sname(1:1), alpha) == 0 .AND.VERIFY(TRIM(sname),alpha//"/"//num) == 0)457 valid = (VERIFY(sname(1:1),ualpha//alpha) == 0 .AND.VERIFY(TRIM(sname),ualpha//alpha//num) == 0) 419 458 ENDIF 420 459 END FUNCTION cfg_check_name 421 460 422 FUNCTION cfg_count(this ) RESULT(num)461 FUNCTION cfg_count(this,section) RESULT(num) 423 462 !! Get the total number of option in the parser. 424 463 !! 464 !! If a section name is given in argument, the method returns the count for the given section only. 465 !! 466 !! To get the number of top-level options (i.e. that belongs to the default section) the keyword \_\_default\_\_ 467 !! should be set for the section argument. 468 !! 469 !! If __section__ is not defined in the parser, the method returns 0. 470 !! 425 471 !! @internal 426 !! If no options are defined, then it implies that the internal vector of options is 472 !! If no options are defined, then it implies that the internal vector of options is 427 473 !! not allocated. 428 OBJECT(cfgparser), INTENT(in) :: this !! A cfgparser object to search in 429 INTEGER :: num !! Number of current options registered in the parser. 474 OBJECT(cfgparser), INTENT(in) :: this !! A cfgparser object to search in 475 CHARACTER(len=*), INTENT(in), OPTIONAL :: section !! Optional section name to search in. 476 INTEGER :: num !! Number of current options registered in the parser. 477 INTEGER :: i 430 478 num = 0 431 479 IF(.NOT.ALLOCATED(this%options)) RETURN 432 num = SIZE(this%options) 480 IF (.NOT.PRESENT(section)) THEN 481 num = SIZE(this%options) 482 ELSE 483 DO i=1, SIZE(this%options) 484 IF (this%options(i)%section == section) num = num+1 485 ENDDO 486 ENDIF 433 487 END FUNCTION cfg_count 434 488 … … 469 523 ! Found a match so start looking again 470 524 found = (tmp(j) == this%options(i)%section .OR. & 471 this%options(i)%section == "__default__") 525 this%options(i)%section == "__default__") 472 526 IF (found) EXIT 473 527 ENDDO … … 482 536 END FUNCTION cfg_section_names 483 537 484 FUNCTION cfg_option_names(this ) RESULT(list)538 FUNCTION cfg_option_names(this,secname) RESULT(list) 485 539 !! Get the list of option names. 486 540 !! 487 541 !! @note 488 542 !! If the parser does not have options, the vector is still allocated but with 0 elements. 489 OBJECT(cfgparser), INTENT(in) :: this !! A cfgparser object to process. 490 CHARACTER(len=st_slen), DIMENSION(:), ALLOCATABLE :: list !! List of option names. 491 INTEGER :: i,no 543 OBJECT(cfgparser), INTENT(in) :: this !! A cfgparser object to process. 544 CHARACTER(len=*), INTENT(in), OPTIONAL :: secname !! Optional section name to search in. 545 CHARACTER(len=st_slen), DIMENSION(:), ALLOCATABLE :: list !! List of option names. 546 INTEGER :: j,i,no,nso 492 547 no = cfg_count(this) 493 ALLOCATE(list(no)) 494 IF (no == 0) RETURN 495 DO i=1,no 496 IF (this%options(i)%section == "__default__") THEN 497 list(i) = TRIM(this%options(i)%name) 498 ELSE 499 list(i) = TRIM(this%options(i)%section)//"/"//TRIM(this%options(i)%name) 500 ENDIF 501 ENDDO 548 IF (no == 0) THEN 549 ALLOCATE(list(no)) ; RETURN 550 ENDIF 551 IF (PRESENT(secname)) THEN 552 IF (.NOT.cfg_has_section(this,TRIM(secname))) THEN 553 ALLOCATE(list(no)) ; RETURN 554 ELSE 555 nso = 0 556 DO i=1,no ; IF (this%options(i)%section == TRIM(secname)) nso = nso + 1 ; ENDDO 557 ALLOCATE(list(nso)) 558 IF (nso == 0) RETURN 559 j = 1 560 DO i=1,no 561 IF (this%options(i)%section == TRIM(secname)) THEN 562 list(j) = TRIM(this%options(i)%section)//"/"//TRIM(this%options(i)%name) ; j=j+1 563 ENDIF 564 ENDDO 565 ENDIF 566 ELSE 567 ALLOCATE(list(no)) 568 DO i=1,no 569 IF (this%options(i)%section == "__default__") THEN 570 list(i) = TRIM(this%options(i)%name) 571 ELSE 572 list(i) = TRIM(this%options(i)%section)//"/"//TRIM(this%options(i)%name) 573 ENDIF 574 ENDDO 575 ENDIF 502 576 END FUNCTION cfg_option_names 503 577 504 578 FUNCTION cfg_has_section(this,name) RESULT(yes) 505 579 !! Check if parser has section by name 580 !! 581 !! @note 582 !! Keep in mind that section name in the configuration are case-sensitive. 506 583 OBJECT(cfgparser), INTENT(in) :: this !! cfgparser object 507 584 CHARACTER(len=*), INTENT(in) :: name !! Name of the section to search 508 585 LOGICAL :: yes !! .true. if the section exists, .false. otherwise 509 CHARACTER(len=:), ALLOCATABLE :: zname510 586 INTEGER :: i,no 511 587 yes = .false. 512 588 no = cfg_count(this) 513 589 IF (no == 0) RETURN 514 zname = str_to_lower(name)515 590 DO i = 1,no 516 IF (this%options(i)%section == zname) THEN591 IF (this%options(i)%section == name) THEN 517 592 yes = .true. 518 593 RETURN … … 527 602 LOGICAL :: yes !! .true. if the option is found, .false. otherwise 528 603 CHARACTER(len=:), ALLOCATABLE :: pname,zname 529 INTEGER :: i,no 604 INTEGER :: i,no,iscan 530 605 yes = .false. 531 606 no = cfg_count(this) 532 607 IF (no == 0) RETURN 533 IF (SCAN(name,"/") <= 0) THEN 534 zname = "__default__"//"/"//str_to_lower(TRIM(name)) 535 ELSE 536 zname = str_to_lower(TRIM(name)) 537 ENDIF 608 zname = op_format(name) 609 IF (LEN_TRIM(zname) == 0) RETURN 538 610 DO i = 1,no 539 pname = op_full_name(this%options(i)) 611 pname = op_full_name(this%options(i)) 540 612 IF (pname == zname) THEN 541 613 yes = .true. … … 545 617 END FUNCTION cfg_has_option 546 618 547 SUBROUTINE cfg_sort_options(this) 619 SUBROUTINE cfg_sort_options(this) 548 620 !! Sort the options in the parser (alphabetiCALLy). 549 621 OBJECT(cfgparser), INTENT(inout) :: this !! A cfgparser object … … 552 624 IF (no == 0) RETURN 553 625 CALL insertionSort(this%options) 554 END SUBROUTINE cfg_sort_options 626 END SUBROUTINE cfg_sort_options 555 627 556 628 SUBROUTINE cfg_remove_option(this,name) 557 629 !! Remove an option from parser by name. 558 OBJECT(cfgparser), INTENT(inout) :: this !! A cfgparser object to search in 630 OBJECT(cfgparser), INTENT(inout) :: this !! A cfgparser object to search in 559 631 CHARACTER(len=*), INTENT(in) :: name !! The name of the option to remove 560 CHARACTER(len=:), ALLOCATABLE :: zname,pname561 632 INTEGER :: no,idx,i,j 562 633 TYPE(option), DIMENSION(:), ALLOCATABLE :: tmp 563 IF (SCAN(name,"/") <= 0) THEN 564 zname = "__default__"//"/"//str_to_lower(TRIM(name)) 565 ELSE 566 zname = str_to_lower(TRIM(name)) 567 ENDIF 568 idx = cp_get_opt_idx(this,zname) 634 idx = cp_get_opt_idx(this,name) 635 IF (idx == -1) RETURN 569 636 no = cfg_count(this) 570 IF (idx == -1) RETURN571 637 ! only one opt 572 638 IF (no == 1) THEN … … 589 655 this%options(i) = tmp(i) 590 656 CALL op_clear(tmp(i)) 591 ENDDO 657 ENDDO 592 658 DEALLOCATE(tmp) 593 659 END SUBROUTINE cfg_remove_option … … 597 663 !! 598 664 !! The method removes all the options that belong to the given section name. 599 OBJECT(cfgparser), INTENT(inout) :: this 600 !! A cfgparser object to search in 665 OBJECT(cfgparser), INTENT(inout) :: this 666 !! A cfgparser object to search in 601 667 CHARACTER(len=*), INTENT(in) :: name 602 668 !! The name of the section to remove 603 CHARACTER(len=:), ALLOCATABLE :: zname604 669 INTEGER :: no,i,j,icount 605 670 INTEGER, DIMENSION(:), ALLOCATABLE :: idxs,itmp 606 671 TYPE(option), DIMENSION(:), ALLOCATABLE :: tmp 607 608 672 no = cfg_count(this) 609 673 IF (no == 0) RETURN 610 zname = str_to_lower(TRIM(name))611 674 ALLOCATE(itmp(no)) 612 675 itmp(:) = -1 613 676 icount = 0 614 677 DO i=1,no 615 IF (TRIM(this%options(i)%section) == zname) THEN678 IF (TRIM(this%options(i)%section) == TRIM(name)) THEN 616 679 itmp(icount+1) = i 617 680 icount = icount + 1 … … 627 690 DEALLOCATE(this%options) 628 691 RETURN 629 ENDIF 692 ENDIF 630 693 ALLOCATE(tmp(icount)) 631 694 j = 1 … … 650 713 !! Read configuration file 651 714 !! 652 !! @note 715 !! @note 653 716 !! If the library support C bindings, the method can read included files which are defined 654 717 !! by the __#include <...>__ directive (see [p_cfgparse](here) from more details). … … 662 725 !! An error with the first error encountered 663 726 INTEGER :: i 664 LOGICAL :: zoverride,ok 665 TYPE(words) :: incfiles 727 LOGICAL :: zoverride,ok 728 TYPE(words) :: incfiles 666 729 CHARACTER(len=:), ALLOCATABLE :: name 667 730 CHARACTER(len=st_slen) :: isec 668 err = noerror 731 err = noerror 669 732 zoverride = .false. ; IF (PRESENT(override)) zoverride = override 670 733 isec = "__default__" 671 734 name = TRIM(path) 672 i = INDEX(name,'/',.true.) ; IF (i /= 0) name = name(i+1:) 735 i = INDEX(name,'/',.true.) ; IF (i /= 0) name = name(i+1:) 673 736 IF (i == 0) THEN 674 737 name = fs_realpath("./"//path) … … 710 773 no = cfg_count(this) 711 774 IF (no == 0) THEN 712 err = error("No options to write",-7) 775 err = error("No options to write",-7) 713 776 RETURN 714 777 ENDIF … … 728 791 WRITE(lu,'(a)') op_to_str(this%options(i),nv) 729 792 ENDDO 730 END FUNCTION cfg_write_config 793 END FUNCTION cfg_write_config 731 794 732 795 ! internal (private methods) … … 751 814 FUNCTION cp_get_opt_idx(this,name) RESULT(idx) 752 815 !! Get the index of an option by name in the parser. 753 !! 816 !! 754 817 !! The method searches in the parser for the option with the given (full) __name__. 755 818 !! If found, it returns the index of the option in the internal vector of options. Otherwise … … 763 826 no = cfg_count(this) 764 827 IF (no == 0) RETURN 765 IF (SCAN(name,"/") <= 0) THEN 766 zname = "__default__"//"/"//str_to_lower(TRIM(name)) 767 ELSE 768 zname = str_to_lower(TRIM(name)) 769 ENDIF 828 zname = op_format(name) ! prepare the name to search. 829 IF (LEN_TRIM(zname) == 0) RETURN 770 830 DO i=1,no 771 831 pname = op_full_name(this%options(i)) … … 780 840 !! Update an option in the parser. 781 841 !! 782 !! The attempts to update the option in the parser that matches __opt__ name. 783 !! 784 !! If __name__ is given it is used instead of __opt__ name. 785 !! 786 !! If no option is found, __opt__ is appended in the parser. Otherwise the matched 787 !! option is updated (i.e. its values are set to __opt__ values). 788 !! 789 !! If the option is not valid, the method does nothing and -X error status is returned. 842 !! The method attempts to update the option in the parser. 843 !! 844 !! If __sname__ is set to empty string, the method searches for the option 845 !! in the default section. 846 !! 847 !! If no option is found, The the option is appended in the parser. Otherwise it is updated 848 !! with the content of __values__. 849 !! 850 !! If the option name is not valid, the method does nothing and -9 error status is returned. 790 851 !! 791 852 !! @internal 792 853 !! The method performs the same kind of operations than the setters except that it 793 !! expects raw data ([[string s(module):words(type)]]).854 !! expects raw data ([[string_op(module):words(type)]]). 794 855 OBJECT(cfgparser), INTENT(inout) :: this !! cfgparser object to process. 795 856 CHARACTER(len=*), INTENT(in) :: sname !! Name of the section. 796 CHARACTER(len=*), INTENT(in) :: pname !! Name of the option.857 CHARACTER(len=*), INTENT(in) :: pname !! Basename of the option. 797 858 TYPE(words), INTENT(in) :: values !! Raw values. 798 TYPE(error) :: err!! Error status.859 TYPE(error) :: err !! Error status. 799 860 CHARACTER(len=:), ALLOCATABLE :: zsname,fname 800 861 INTEGER :: i 801 862 err = noerror 802 zsname = str_to_lower(TRIM(sname))803 IF (LEN_TRIM( zsname) == 0) zsname = "__default__"804 fname = zsname//"/"// str_to_lower(TRIM(pname))863 zsname = TRIM(sname) 864 IF (LEN_TRIM(sname) == 0) zsname = "__default__" 865 fname = zsname//"/"//to_lower(TRIM(pname)) 805 866 IF (.NOT.cfg_check_name(fname)) THEN 806 867 err = error("Invalid option (no name)",-9) … … 816 877 END FUNCTION cp_update_opt 817 878 818 819 FUNCTION cp_add_opt(this,sname,pname,values) RESULT(err) 879 FUNCTION cp_add_opt(this,sname,pname,values) RESULT(err) 820 880 !! Add an option to the parser. 821 881 !! 822 882 !! In order to add an option to the default section, _sname_ should be left empty or set to "\_\_default\_\_". 823 !!824 !! If given, _opt_ points to the new option on output. If an error occured the pointer is null.825 883 !! 826 884 !! The following error code can be returned: … … 828 886 !! - -8, the option already exists. 829 887 !! - -9, option name is not valid. 830 OBJECT(cfgparser), INTENT(inout) :: this 888 OBJECT(cfgparser), INTENT(inout) :: this 831 889 !! A cfgparser object to process. 832 890 CHARACTER(len=*), INTENT(in) :: sname 833 891 !! Section name. 834 892 CHARACTER(len=*), INTENT(in) :: pname 835 !! Option name.893 !! Option basename. 836 894 TYPE(words), INTENT(in) :: values 837 895 !! Values to set. … … 839 897 !! Return error status. 840 898 CHARACTER(len=:), ALLOCATABLE :: zsname,fname 841 TYPE(option), DIMENSION(:), ALLOCATABLE :: tmp 899 TYPE(option), DIMENSION(:), ALLOCATABLE :: tmp 842 900 INTEGER :: no,i 843 844 TYPE(option) :: sca 901 TYPE(option) :: sca 845 902 846 903 err = noerror … … 848 905 no = cfg_count(this) 849 906 IF (LEN_TRIM(zsname) == 0) zsname = "__default__" 850 fname = TRIM(zsname)//"/"// TRIM(pname)907 fname = TRIM(zsname)//"/"//to_lower(TRIM(pname)) 851 908 ! check name 852 909 IF (.NOT.cfg_check_name(fname)) THEN … … 864 921 ! build option 865 922 CALL op_clear(sca) 866 sca%name = pname923 sca%name = to_lower(TRIM(pname)) 867 924 sca%section = zsname 868 925 sca%values = values … … 874 931 ! parser has options: increase this%options size (ugly copy). 875 932 ALLOCATE(tmp(no)) 876 DO i =1,no 877 tmp(i) = this%options(i) 933 DO i =1,no 934 tmp(i) = this%options(i) 878 935 CALL op_clear(this%options(i)) 879 936 ENDDO 880 937 DEALLOCATE(this%options) 881 938 ALLOCATE(this%options(no+1)) 882 DO i =1,no 883 this%options(i) = tmp(i) 939 DO i =1,no 940 this%options(i) = tmp(i) 884 941 CALL op_clear(tmp(i)) 885 942 ENDDO … … 898 955 !! - -6, the option does not have value(s). 899 956 !! - -10, the value cannot be converted in the output type. 900 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 957 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 901 958 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to get 902 959 REAL(kind=4), INTENT(out) :: output !! Output value 903 TYPE(error) :: err 960 TYPE(error) :: err 904 961 !! Error status 905 INTEGER :: idx 962 INTEGER :: idx 906 963 CHARACTER(len=:), ALLOCATABLE :: tmp 907 964 err = noerror … … 918 975 err = error("Option "//TRIM(name)//" has no value",-6) 919 976 ELSE 920 IF(.NOT.from_string(tmp,output)) & 977 IF(.NOT.from_string(tmp,output)) & 921 978 err = error(TRIM(name)//": Cannot convert "//tmp//" to real.",-10) 922 979 ENDIF … … 931 988 !! - -6, the option does not have value(s). 932 989 !! - -10, the value cannot be converted in the output type. 933 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 990 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 934 991 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to get 935 992 REAL(kind=8), INTENT(out) :: output !! Output value 936 TYPE(error) :: err 993 TYPE(error) :: err 937 994 !! Error status 938 INTEGER :: idx 995 INTEGER :: idx 939 996 CHARACTER(len=:), ALLOCATABLE :: tmp 940 997 err = noerror … … 951 1008 err = error("Option "//TRIM(name)//" has no value",-6) 952 1009 ELSE 953 IF(.NOT.from_string(tmp,output)) & 1010 IF(.NOT.from_string(tmp,output)) & 954 1011 err = error(TRIM(name)//": Cannot convert "//tmp//" to double.",-10) 955 1012 ENDIF … … 964 1021 !! - -6, the option does not have value(s). 965 1022 !! - -10, the value cannot be converted in the output type. 966 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 1023 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 967 1024 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to get 968 1025 INTEGER, INTENT(out) :: output !! Output value 969 TYPE(error) :: err 1026 TYPE(error) :: err 970 1027 !! Error status 971 INTEGER :: idx 1028 INTEGER :: idx 972 1029 CHARACTER(len=:), ALLOCATABLE :: tmp 973 1030 err = noerror … … 984 1041 err = error("Option "//TRIM(name)//" has no value",-6) 985 1042 ELSE 986 IF(.NOT.from_string(tmp,output)) & 1043 IF(.NOT.from_string(tmp,output)) & 987 1044 err = error(TRIM(name)//": Cannot convert "//tmp//" to integer.",-10) 988 1045 ENDIF … … 997 1054 !! - -6, the option does not have value(s). 998 1055 !! - -10, the value cannot be converted in the output type. 999 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 1056 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 1000 1057 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to get 1001 1058 LOGICAL, INTENT(out) :: output !! Output value 1002 TYPE(error) :: err 1059 TYPE(error) :: err 1003 1060 !! Error status 1004 INTEGER :: idx 1061 INTEGER :: idx 1005 1062 CHARACTER(len=:), ALLOCATABLE :: tmp 1006 1063 err = noerror … … 1017 1074 err = error("Option "//TRIM(name)//" has no value",-6) 1018 1075 ELSE 1019 IF(.NOT.from_string(tmp,output)) & 1076 IF(.NOT.from_string(tmp,output)) & 1020 1077 err = error(TRIM(name)//": Cannot convert "//tmp//" to logical.",-10) 1021 1078 ENDIF … … 1030 1087 !! - -6, the option does not have value(s). 1031 1088 !! - -10, the value cannot be converted in the output type. 1032 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 1089 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 1033 1090 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to get 1034 1091 COMPLEX, INTENT(out) :: output !! Output value 1035 TYPE(error) :: err 1092 TYPE(error) :: err 1036 1093 !! Error status 1037 INTEGER :: idx 1094 INTEGER :: idx 1038 1095 CHARACTER(len=:), ALLOCATABLE :: tmp 1039 1096 err = noerror … … 1050 1107 err = error("Option "//TRIM(name)//" has no value",-6) 1051 1108 ELSE 1052 IF(.NOT.from_string(tmp,output)) & 1109 IF(.NOT.from_string(tmp,output)) & 1053 1110 err = error(TRIM(name)//": Cannot convert "//tmp//" to complex.",-10) 1054 1111 ENDIF … … 1062 1119 !! - -7, no option matches the given name. 1063 1120 !! - -6, the option does not have value(s). 1064 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 1121 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 1065 1122 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to get 1066 1123 CHARACTER(len=*), INTENT(out) :: output !! Output value 1067 TYPE(error) :: err 1124 TYPE(error) :: err 1068 1125 !! Error status 1069 INTEGER :: idx 1126 INTEGER :: idx 1070 1127 !CHARACTER(len=:), ALLOCATABLE :: tmp 1071 1128 err = noerror … … 1087 1144 !! 1088 1145 !! On error, the output vector is not allocated. 1089 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 1146 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 1090 1147 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to get 1091 1148 REAL(kind=4), INTENT(out), DIMENSION(:), ALLOCATABLE :: output !! Output values 1092 TYPE(error) :: err 1149 TYPE(error) :: err 1093 1150 !! Error status of the method (see [[cfgparser(type):get_value(bound)]] documentation) 1094 1151 CHARACTER(len=st_slen), DIMENSION(:), ALLOCATABLE :: tmp … … 1114 1171 ELSE IF (.NOT.from_string(tmp(i), output(i))) THEN 1115 1172 err = error("Cannot convert value #"//TRIM(i2s)//" from option "//TRIM(name),-10) 1116 DEALLOCATE(output) ; EXIT 1173 DEALLOCATE(output) ; EXIT 1117 1174 ENDIF 1118 1175 ENDDO 1119 1176 ENDIF 1120 1177 DEALLOCATE(tmp) 1121 RETURN 1178 RETURN 1122 1179 END FUNCTION cp_get_rv_ve 1123 1180 … … 1126 1183 !! 1127 1184 !! On error, the output vector is not allocated. 1128 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 1185 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 1129 1186 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to get 1130 1187 REAL(kind=8), INTENT(out), DIMENSION(:), ALLOCATABLE :: output !! Output values 1131 TYPE(error) :: err 1188 TYPE(error) :: err 1132 1189 !! Error status of the method (see [[cfgparser(type):get_value(bound)]] documentation) 1133 1190 CHARACTER(len=st_slen), DIMENSION(:), ALLOCATABLE :: tmp … … 1153 1210 ELSE IF (.NOT.from_string(tmp(i), output(i))) THEN 1154 1211 err = error("Cannot convert value #"//TRIM(i2s)//" from option "//TRIM(name),-10) 1155 DEALLOCATE(output) ; EXIT 1212 DEALLOCATE(output) ; EXIT 1156 1213 ENDIF 1157 1214 ENDDO 1158 1215 ENDIF 1159 1216 DEALLOCATE(tmp) 1160 RETURN 1217 RETURN 1161 1218 END FUNCTION cp_get_dv_ve 1162 1219 … … 1165 1222 !! 1166 1223 !! On error, the output vector is not allocated. 1167 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 1224 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 1168 1225 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to get 1169 1226 INTEGER, INTENT(out), DIMENSION(:), ALLOCATABLE :: output !! Output values 1170 TYPE(error) :: err 1227 TYPE(error) :: err 1171 1228 !! Error status of the method (see [[cfgparser(type):get_value(bound)]] documentation) 1172 1229 CHARACTER(len=st_slen), DIMENSION(:), ALLOCATABLE :: tmp … … 1192 1249 ELSE IF (.NOT.from_string(tmp(i), output(i))) THEN 1193 1250 err = error("Cannot convert value #"//TRIM(i2s)//" from option "//TRIM(name),-10) 1194 DEALLOCATE(output) ; EXIT 1251 DEALLOCATE(output) ; EXIT 1195 1252 ENDIF 1196 1253 ENDDO 1197 1254 ENDIF 1198 1255 DEALLOCATE(tmp) 1199 RETURN 1256 RETURN 1200 1257 END FUNCTION cp_get_iv_ve 1201 1258 … … 1204 1261 !! 1205 1262 !! On error, the output vector is not allocated. 1206 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 1263 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 1207 1264 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to get 1208 1265 LOGICAL, INTENT(out), DIMENSION(:), ALLOCATABLE :: output !! Output values 1209 TYPE(error) :: err 1266 TYPE(error) :: err 1210 1267 !! Error status of the method (see [[cfgparser(type):get_value(bound)]] documentation) 1211 1268 CHARACTER(len=st_slen), DIMENSION(:), ALLOCATABLE :: tmp … … 1231 1288 ELSE IF (.NOT.from_string(tmp(i), output(i))) THEN 1232 1289 err = error("Cannot convert value #"//TRIM(i2s)//" from option "//TRIM(name),-10) 1233 DEALLOCATE(output) ; EXIT 1290 DEALLOCATE(output) ; EXIT 1234 1291 ENDIF 1235 1292 ENDDO 1236 1293 ENDIF 1237 1294 DEALLOCATE(tmp) 1238 RETURN 1295 RETURN 1239 1296 END FUNCTION cp_get_lv_ve 1240 1297 … … 1243 1300 !! 1244 1301 !! On error, the output vector is not allocated. 1245 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 1302 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 1246 1303 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to get 1247 1304 COMPLEX, INTENT(out), DIMENSION(:), ALLOCATABLE :: output !! Output values 1248 TYPE(error) :: err 1305 TYPE(error) :: err 1249 1306 !! Error status of the method (see [[cfgparser(type):get_value(bound)]] documentation) 1250 1307 CHARACTER(len=st_slen), DIMENSION(:), ALLOCATABLE :: tmp … … 1270 1327 ELSE IF (.NOT.from_string(tmp(i), output(i))) THEN 1271 1328 err = error("Cannot convert value #"//TRIM(i2s)//" from option "//TRIM(name),-10) 1272 DEALLOCATE(output) ; EXIT 1329 DEALLOCATE(output) ; EXIT 1273 1330 ENDIF 1274 1331 ENDDO 1275 1332 ENDIF 1276 1333 DEALLOCATE(tmp) 1277 RETURN 1334 RETURN 1278 1335 END FUNCTION cp_get_cv_ve 1279 1336 … … 1282 1339 !! 1283 1340 !! On error, the output vector is not allocated. 1284 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 1341 OBJECT(cfgparser), INTENT(in) :: this !! Cfgparser object 1285 1342 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to get 1286 1343 CHARACTER(len=*), INTENT(out), DIMENSION(:), ALLOCATABLE :: output !! Output values 1287 TYPE(error) :: err 1288 !! Error status of the method (see [[cfgparser(type):get_value(bound)]] documentation) 1344 TYPE(error) :: err !! Error status of the method (see [[cfgparser(type):get_value(bound)]] documentation) 1289 1345 LOGICAL :: ok 1290 1346 INTEGER :: idx … … 1307 1363 !! 1308 1364 !! If _create_ is given to .true., the method will add a new option if it does not exist in 1309 !! the parser. 1310 !! In such case, an error ( -6, invalid name) is raised if the option name is not valid.1365 !! the parser. 1366 !! In such case, an error ((-9, invalid name)) is raised if the option name is not valid. 1311 1367 !! 1312 1368 !! In other case, if the option is not defined in the parser the error status is set to -7. 1313 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1369 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1314 1370 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to set 1315 1371 REAL(kind=4), INTENT(in) :: input !! Input value 1316 LOGICAL, INTENT(in), OPTIONAL :: create !! .true. to create option if it does not exist (default to false). 1372 LOGICAL, INTENT(in), OPTIONAL :: create !! .true. to create option if it does not exist (default to false). 1317 1373 TYPE(error) :: err !! Error status 1318 1374 LOGICAL :: zcreate 1319 INTEGER :: idx 1375 INTEGER :: idx 1320 1376 CHARACTER(len=:), ALLOCATABLE :: sname,pname 1321 1377 TYPE(words) :: values … … 1332 1388 ENDIF 1333 1389 ELSE 1334 this%options(idx)%values = values 1390 this%options(idx)%values = values 1335 1391 ENDIF 1336 1392 CALL words_clear(values) … … 1341 1397 !! 1342 1398 !! If _create_ is given to .true., the method will add a new option if it does not exist in 1343 !! the parser. 1344 !! In such case, an error ( -6, invalid name) is raised if the option name is not valid.1399 !! the parser. 1400 !! In such case, an error ((-9, invalid name)) is raised if the option name is not valid. 1345 1401 !! 1346 1402 !! In other case, if the option is not defined in the parser the error status is set to -7. 1347 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1403 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1348 1404 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to set 1349 1405 REAL(kind=8), INTENT(in) :: input !! Input value 1350 LOGICAL, INTENT(in), OPTIONAL :: create !! .true. to create option if it does not exist (default to false). 1406 LOGICAL, INTENT(in), OPTIONAL :: create !! .true. to create option if it does not exist (default to false). 1351 1407 TYPE(error) :: err !! Error status 1352 1408 LOGICAL :: zcreate 1353 INTEGER :: idx 1409 INTEGER :: idx 1354 1410 CHARACTER(len=:), ALLOCATABLE :: sname,pname 1355 1411 TYPE(words) :: values … … 1366 1422 ENDIF 1367 1423 ELSE 1368 this%options(idx)%values = values 1424 this%options(idx)%values = values 1369 1425 ENDIF 1370 1426 CALL words_clear(values) … … 1376 1432 !! If _create_ is given to .true., the method will add a new option if it does not exist in 1377 1433 !! the parser. 1378 !! In such case, an error ( -6, invalid name) is raised if the option name is not valid.1434 !! In such case, an error ((-9, invalid name)) is raised if the option name is not valid. 1379 1435 !! 1380 1436 !! In other case, if the option is not defined in the parser the error status is set to -7. 1381 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1437 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1382 1438 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to set 1383 1439 INTEGER, INTENT(in) :: input !! Input value 1384 LOGICAL, INTENT(in), OPTIONAL :: create !! .true. to create option if it does not exist (default to false). 1440 LOGICAL, INTENT(in), OPTIONAL :: create !! .true. to create option if it does not exist (default to false). 1385 1441 TYPE(error) :: err !! Error status 1386 1442 LOGICAL :: zcreate 1387 INTEGER :: idx 1443 INTEGER :: idx 1388 1444 CHARACTER(len=:), ALLOCATABLE :: sname,pname 1389 1445 TYPE(words) :: values … … 1395 1451 IF (zcreate) THEN 1396 1452 err = op_split_name(name,sname,pname) 1397 !IF (err == 0) err = cp_add_opt(this,sname,pname,values) 1398 err = cp_add_opt(this,sname,pname,values) 1453 IF (err == 0) err = cp_add_opt(this,sname,pname,values) 1399 1454 ELSE 1400 1455 err = error("Option "//TRIM(name)//" does not exist",-7) 1401 1456 ENDIF 1402 1457 ELSE 1403 this%options(idx)%values = values 1458 this%options(idx)%values = values 1404 1459 ENDIF 1405 1460 CALL words_clear(values) … … 1411 1466 !! If _create_ is given to .true., the method will add a new option if it does not exist in 1412 1467 !! the parser. 1413 !! In such case, an error ( -6, invalid name) is raised if the option name is not valid.1468 !! In such case, an error ((-9, invalid name)) is raised if the option name is not valid. 1414 1469 !! 1415 1470 !! In other case, if the option is not defined in the parser the error status is set to -7. 1416 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1471 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1417 1472 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to set 1418 1473 LOGICAL, INTENT(in) :: input !! Input value 1419 LOGICAL, INTENT(in), OPTIONAL :: create !! .true. to create option if it does not exist (default to false). 1474 LOGICAL, INTENT(in), OPTIONAL :: create !! .true. to create option if it does not exist (default to false). 1420 1475 TYPE(error) :: err !! Error status 1421 1476 LOGICAL :: zcreate 1422 INTEGER :: idx 1477 INTEGER :: idx 1423 1478 CHARACTER(len=:), ALLOCATABLE :: sname,pname 1424 1479 TYPE(words) :: values … … 1435 1490 ENDIF 1436 1491 ELSE 1437 this%options(idx)%values = values 1492 this%options(idx)%values = values 1438 1493 ENDIF 1439 1494 CALL words_clear(values) … … 1445 1500 !! If _create_ is given to .true., the method will add a new option if it does not exist in 1446 1501 !! the parser. 1447 !! In such case, an error ( -6, invalid name) is raised if the option name is not valid.1502 !! In such case, an error ((-9, invalid name)) is raised if the option name is not valid. 1448 1503 !! 1449 1504 !! In other case, if the option is not defined in the parser the error status is set to -7. 1450 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1505 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1451 1506 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to set 1452 1507 COMPLEX, INTENT(in) :: input !! Input value 1453 LOGICAL, INTENT(in), OPTIONAL :: create !! .true. to create option if it does not exist (default to false). 1508 LOGICAL, INTENT(in), OPTIONAL :: create !! .true. to create option if it does not exist (default to false). 1454 1509 TYPE(error) :: err !! Error status 1455 1510 LOGICAL :: zcreate 1456 INTEGER :: idx 1511 INTEGER :: idx 1457 1512 CHARACTER(len=:), ALLOCATABLE :: sname,pname 1458 1513 TYPE(words) :: values … … 1469 1524 ENDIF 1470 1525 ELSE 1471 this%options(idx)%values = values 1526 this%options(idx)%values = values 1472 1527 ENDIF 1473 1528 CALL words_clear(values) … … 1479 1534 !! If _create_ is given to .true., the method will add a new option if it does not exist in 1480 1535 !! the parser. 1481 !! In such case, an error ( -6, invalid name) is raised if the option name is not valid.1536 !! In such case, an error ((-9, invalid name)) is raised if the option name is not valid. 1482 1537 !! 1483 1538 !! In other case, if the option is not defined in the parser the error status is set to -7. 1484 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1539 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1485 1540 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to set 1486 1541 CHARACTER(len=*), INTENT(in) :: input !! Input value 1487 LOGICAL, INTENT(in), OPTIONAL :: create !! .true. to create option if it does not exist (default to false). 1542 LOGICAL, INTENT(in), OPTIONAL :: create !! .true. to create option if it does not exist (default to false). 1488 1543 TYPE(error) :: err !! Error status 1489 1544 LOGICAL :: zcreate 1490 INTEGER :: idx 1545 INTEGER :: idx 1491 1546 CHARACTER(len=:), ALLOCATABLE :: sname,pname 1492 1547 TYPE(words) :: values … … 1503 1558 ENDIF 1504 1559 ELSE 1505 this%options(idx)%values = values 1560 this%options(idx)%values = values 1506 1561 ENDIF 1507 1562 CALL words_clear(values) … … 1512 1567 !! 1513 1568 !! If _create_ is given to .true., the method will add a new option if it does not exist in 1514 !! the parser. 1515 !! In such case, an error ( -6, invalid name) is raised if the option name is not valid.1569 !! the parser. 1570 !! In such case, an error ((-9, invalid name)) is raised if the option name is not valid. 1516 1571 !! 1517 1572 !! In other case, if the option is not defined in the parser the error status is set to -7. 1518 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1573 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1519 1574 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to get 1520 1575 REAL(kind=4), INTENT(in), DIMENSION(:) :: input !! Input values … … 1537 1592 ENDIF 1538 1593 ELSE 1539 this%options(idx)%values = values 1594 this%options(idx)%values = values 1540 1595 ENDIF 1541 1596 CALL words_clear(values) … … 1547 1602 !! If _create_ is given to .true., the method will add a new option if it does not exist in 1548 1603 !! the parser. 1549 !! In such case, an error ( -6, invalid name) is raised if the option name is not valid.1604 !! In such case, an error ((-9, invalid name)) is raised if the option name is not valid. 1550 1605 !! 1551 1606 !! In other case, if the option is not defined in the parser the error status is set to -7. 1552 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1607 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1553 1608 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to get 1554 1609 REAL(kind=8), INTENT(in), DIMENSION(:) :: input !! Input values … … 1571 1626 ENDIF 1572 1627 ELSE 1573 this%options(idx)%values = values 1628 this%options(idx)%values = values 1574 1629 ENDIF 1575 1630 CALL words_clear(values) … … 1580 1635 !! 1581 1636 !! If _create_ is given to .true., the method will add a new option if it does not exist in 1582 !! the parser. 1583 !! In such case, an error ( -6, invalid name) is raised if the option name is not valid.1637 !! the parser. 1638 !! In such case, an error ((-9, invalid name)) is raised if the option name is not valid. 1584 1639 !! 1585 1640 !! In other case, if the option is not defined in the parser the error status is set to -7. 1586 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1641 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1587 1642 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to get 1588 1643 INTEGER, INTENT(in), DIMENSION(:) :: input !! Input values … … 1605 1660 ENDIF 1606 1661 ELSE 1607 this%options(idx)%values = values 1662 this%options(idx)%values = values 1608 1663 ENDIF 1609 1664 CALL words_clear(values) … … 1615 1670 !! If _create_ is given to .true., the method will add a new option if it does not exist in 1616 1671 !! the parser. 1617 !! In such case, an error ( -6, invalid name) is raised if the option name is not valid.1672 !! In such case, an error ((-9, invalid name)) is raised if the option name is not valid. 1618 1673 !! 1619 1674 !! In other case, if the option is not defined in the parser the error status is set to -7. 1620 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1675 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1621 1676 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to get 1622 1677 LOGICAL, INTENT(in), DIMENSION(:) :: input !! Input values … … 1639 1694 ENDIF 1640 1695 ELSE 1641 this%options(idx)%values = values 1696 this%options(idx)%values = values 1642 1697 ENDIF 1643 1698 CALL words_clear(values) … … 1648 1703 !! 1649 1704 !! If _create_ is given to .true., the method will add a new option if it does not exist in 1650 !! the parser. 1651 !! In such case, an error ( -6, invalid name) is raised if the option name is not valid.1705 !! the parser. 1706 !! In such case, an error ((-9, invalid name)) is raised if the option name is not valid. 1652 1707 !! 1653 1708 !! In other case, if the option is not defined in the parser the error status is set to -7. 1654 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1709 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1655 1710 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to get 1656 1711 COMPLEX, INTENT(in), DIMENSION(:) :: input !! Input values … … 1673 1728 ENDIF 1674 1729 ELSE 1675 this%options(idx)%values = values 1730 this%options(idx)%values = values 1676 1731 ENDIF 1677 1732 CALL words_clear(values) … … 1683 1738 !! If _create_ is given to .true., the method will add a new option if it does not exist in 1684 1739 !! the parser. 1685 !! In such case, an error ( -6, invalid name) is raised if the option name is not valid.1740 !! In such case, an error ((-9, invalid name)) is raised if the option name is not valid. 1686 1741 !! 1687 1742 !! In other case, if the option is not defined in the parser the error status is set to -7. 1688 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1743 OBJECT(cfgparser), INTENT(inout) :: this !! Cfgparser object 1689 1744 CHARACTER(len=*), INTENT(in) :: name !! (Full) Name of the option to get 1690 1745 CHARACTER(len=*), INTENT(in), DIMENSION(:) :: input !! Input values … … 1707 1762 ENDIF 1708 1763 ELSE 1709 this%options(idx)%values = values 1764 this%options(idx)%values = values 1710 1765 ENDIF 1711 1766 CALL words_clear(values) … … 1734 1789 LOGICAL :: zoverride,ok,has_opt 1735 1790 INTEGER :: lineno,lu,i 1736 CHARACTER(len=2), PARAMETER :: space = CHAR(32)//"," ! check if , is really wanted.. 1791 CHARACTER(len=2), PARAMETER :: space = CHAR(32)//"," ! check if , is really wanted... A: YES space are the delimiter of the words internal object ! 1737 1792 CHARACTER(len=2), PARAMETER :: blanks = CHAR(9)//CHAR(32) ! currently not used because blanks truncate. 1738 1793 CHARACTER(len=15) :: sln … … 1746 1801 zoverride = .false. ; IF (PRESENT(override)) zoverride = override 1747 1802 ! initialize local variables 1748 curval = '' ; line = '' ; name = '' ; value = '' 1749 lineno = 0 ; lu = free_lun() 1803 curval = '' ; line = '' ; name = '' ; value = '' 1804 lineno = 0 ; lu = free_lun() 1750 1805 IF (LEN_TRIM(isec) == 0) isec = "__default__" 1751 1806 i = INDEX(TRIM(path),"/",.true.) 1752 IF (i == 0) THEN 1807 IF (i == 0) THEN 1753 1808 fulp = fs_realpath("./"//TRIM(ADJUSTL(path))) 1754 1809 ELSE … … 1763 1818 RETURN 1764 1819 ENDIF 1765 ! check for lun 1820 ! check for lun 1766 1821 IF (lu == -1) THEN ; err = error("No available logical unit",-12) ; RETURN ; ENDIF 1767 1822 OPEN(lu,FILE=TRIM(path),STATUS='old',ACTION='READ') … … 1775 1830 ! 1) get relative path 1776 1831 ipath = fs_relpath(ipath,dirp) 1777 ! 2) compute asbolute path )1832 ! 2) compute asbolute path 1778 1833 ipath = TRIM(dirp)//"/"//TRIM(ipath) 1779 1834 ipath = fs_realpath(ipath) … … 1793 1848 CALL op_clear(curopt); curval = '' 1794 1849 ENDIF 1795 err = read_include(parser,ipath,isec,ipaths,zoverride) 1850 err = read_include(parser,ipath,isec,ipaths,zoverride) 1796 1851 IF (err /= 0) EXIT 1797 1852 ENDIF … … 1799 1854 ENDIF 1800 1855 ! continuation line ? 1801 IF (SCAN(line(1:1),blanks) /= 0 .AND. op_valid(curopt)) THEN 1856 IF (SCAN(line(1:1),blanks) /= 0 .AND. op_valid(curopt)) THEN 1802 1857 IF (LEN(curval) == 0) THEN 1803 1858 curval = strip_comment(line) … … 1806 1861 ENDIF 1807 1862 ELSE 1808 ! 1. Remove comment part and left adjust line 1863 ! 1. Remove comment part and left adjust line 1809 1864 line = strip_comment(line) 1810 1865 ! a section header or option header? … … 1837 1892 ! 3. curval is set to value 1838 1893 ! 4. update curval 1839 IF (op_valid(curopt)) THEN 1894 IF (op_valid(curopt)) THEN 1840 1895 IF (LEN(curval) > 0) & 1841 1896 CALL words_extend(curopt%values,TRIM(ADJUSTL(curval)),space,.true.,.true.) … … 1847 1902 ENDIF 1848 1903 CALL op_clear(curopt) ; curval = '' 1849 has_opt = cfg_has_option(parser,TRIM(isec)//"/"//TRIM(name)) 1904 has_opt = cfg_has_option(parser,TRIM(isec)//"/"//TRIM(name)) 1850 1905 1851 1906 IF (has_opt.AND..NOT.zoverride) THEN 1852 ! it is an error: no duplicate allowed 1907 ! it is an error: no duplicate allowed 1853 1908 err = error(basp//'(L'//TRIM(sln)//"): Duplicate option '"//TRIM(name)//"' in "//isec,-8) 1854 1909 EXIT … … 1859 1914 curval = value 1860 1915 CASE(cfg_UNKNOWN) 1861 ! unknown handles also invalid name: it is a critical error 1916 ! unknown handles also invalid name: it is a critical error 1862 1917 IF (err == -9) EXIT 1863 END SELECT 1918 END SELECT 1864 1919 ENDIF 1865 1920 ENDDO 1866 IF (op_valid(curopt)) THEN 1921 IF (op_valid(curopt)) THEN 1867 1922 IF (LEN(curval) > 0) & 1868 1923 CALL words_extend(curopt%values,TRIM(ADJUSTL(curval)),space,.true.,.true.) … … 1886 1941 !! it is a section header. 1887 1942 !! - Otherwise, if line has '=', without '#' before '=', it is an option. 1888 !! 1889 !! Then the method returns an integer with the kind flag of the statement which is one of 1943 !! 1944 !! Then the method returns an integer with the kind flag of the statement which is one of 1890 1945 !! -1 (cfg_UNKNOWN), 0 (cfg_SECTION) or 1 (cfg_OPTION). 1891 1946 CHARACTER(len=*), INTENT(in) :: string !! Input string to process … … 1898 1953 kind = cfg_UNKNOWN 1899 1954 ! get a trimmed (and left adjusted) copy 1900 copy = TRIM(string) 1955 copy = TRIM(string) 1901 1956 ! Is it a section ? 1902 1957 ! ---> search for subscripts of '[' and ']' 1903 1958 ! ---> check that '[' is 1st char and ']' is last char 1904 bi = INDEX(copy,'[') ; ei = INDEX(copy,']') 1959 bi = INDEX(copy,'[') ; ei = INDEX(copy,']') 1905 1960 IF (bi == 1 .AND. ei == LEN(copy) .AND. bi < ei) THEN 1906 1961 ! it is a section header 1907 1962 kind = cfg_SECTION 1908 1963 ! get section name: adjust and trim to remove extra blank spaces 1909 name = str_to_lower(TRIM(ADJUSTL(copy(bi+1:ei-1)))) 1910 IF (TRIM(name) /= "__default__" .AND. .NOT.cfg_check_name(name)) THEN 1964 name = TRIM(ADJUSTL(copy(bi+1:ei-1))) 1965 ! hack cfg_check_name: append '/a' to get a valid option part to test 1966 IF (TRIM(name) /= "__default__" .AND. .NOT.cfg_check_name(name//"/a")) THEN 1911 1967 kind = cfg_UNKNOWN 1912 1968 err = error("Invalid section name ("//name//")",-9) … … 1916 1972 ELSE 1917 1973 ! Is it an option ? 1918 ! --> search for '=' and check if it is set before 1974 ! --> search for '=' and check if it is set before 1919 1975 ! 1st quote (if any) 1920 bi = INDEX(copy,"=") 1976 bi = INDEX(copy,"=") 1921 1977 ! search for quotes 1922 1978 ei = SCAN(copy,quotes) ; IF (ei==0) ei = LEN(copy)+1 1923 1979 IF (bi /= 0 .AND. bi < ei) THEN 1924 1980 kind = cfg_OPTION 1925 name = str_to_lower(TRIM(copy(1:bi-1)))1926 IF (.NOT.cfg_check_name(name)) THEN 1981 name = to_lower(TRIM(copy(1:bi-1))) 1982 IF (.NOT.cfg_check_name(name)) THEN 1927 1983 kind = cfg_UNKNOWN 1928 1984 err = error("Invalid option name ("//TRIM(name)//")",-9) … … 1944 2000 FUNCTION strip_comment(line) RESULT(stripped) 1945 2001 !! Replace comments part of a string by blank spaces 1946 !! The method replaces every characters after '#' (included) by spaces. 1947 !! @note 2002 !! The method replaces every characters after '#' (included) by spaces. 2003 !! @note 1948 2004 !! Output string is also left adjusted, thus only trailing blank can be present. 1949 2005 CHARACTER(len=*), INTENT(in) :: line !! A string to process 1950 2006 CHARACTER(len=LEN(line)) :: stripped !! A string of same length than 'line' but without comment(s) 1951 2007 1952 2008 INTEGER :: idx 1953 2009 stripped = ADJUSTL(line) … … 1960 2016 !! Read a complete line 1961 2017 !! 1962 !! Each time it is CALLed, the function reads a complete of the file opened in 'lun' logical 2018 !! Each time it is CALLed, the function reads a complete of the file opened in 'lun' logical 1963 2019 !! unit and returns .false. if EOF has been reached, .true. otherwise. 1964 2020 !! 1965 2021 !! The function is intended to read a file line by line: 1966 !! 1967 !! ``` fortran2022 !! 2023 !! ``` 1968 2024 !! lu = 1 1969 2025 !! open(lu,file="path/to/the/file/to/read") … … 1975 2031 !! CLOSE(1) 1976 2032 !! ``` 1977 INTEGER, INTENT(in) :: lun !! Logical unit with the opened file to read. 1978 CHARACTER(len=:), INTENT(out), ALLOCATABLE :: string !! Output processed line 2033 INTEGER, INTENT(in) :: lun !! Logical unit with the opened file to read. 2034 CHARACTER(len=:), INTENT(out), ALLOCATABLE :: string !! Output processed line 1979 2035 LOGICAL :: not_eof !! .true. if EOF has NOT been reached yet, .false. otherwise 1980 2036 CHARACTER(len=50) :: buf 1981 2037 INTEGER :: e,sz 1982 not_eof = .true. ; string = '' 2038 not_eof = .true. ; string = '' 1983 2039 DO 1984 2040 READ(lun,'(a)',ADVANCE="no",SIZE=sz,IOSTAT=e) buf … … 2006 2062 CHARACTER(len=:), INTENT(out), ALLOCATABLE :: incpath 2007 2063 !! A string with the filepath to be included if '#include' statement is found, empty string otherwise 2008 LOGICAL :: res 2064 LOGICAL :: res 2009 2065 !! .true. if line is a comment or an empty string, .false. otherwise 2010 2066 CHARACTER(len=:), ALLOCATABLE :: copy … … 2017 2073 ! search for include statement 2018 2074 ! IMPORTANT: assume that there is only a path after include statement 2019 IF (INDEX(copy,"#include ") == 1) incpath = TRIM(ADJUSTL(copy(10:)))2075 IF (INDEX(copy,"#include ") == 1) incpath = remove_quotes(TRIM(ADJUSTL(copy(10:)))) 2020 2076 ENDIF 2021 2077 RETURN … … 2046 2102 SUBROUTINE insertionSort(opts) 2047 2103 !! Sort an array of Options using insertion sort algorithm 2048 TYPE(option), INTENT(inout), DIMENSION(:) :: opts !! Array to sort. 2104 TYPE(option), INTENT(inout), DIMENSION(:) :: opts !! Array to sort. 2049 2105 TYPE(option) :: temp 2050 2106 INTEGER :: i, j … … 2058 2114 ELSE 2059 2115 EXIT 2060 ENDIF 2116 ENDIF 2061 2117 ENDDO 2062 2118 opts(j+1) = temp … … 2065 2121 END SUBROUTINE insertionSort 2066 2122 2067 FUNCTION free_lun() RESULT(lu)2068 !> Get the first free logical unit2069 !!2070 !! The function loops from 7 to 9999 and returns the first free logical unit.2071 !! @note2072 !! According to Fortran standard, the maximum value for a lun is processor2073 !! dependent. I just assume that [7,9999] is a valid range and I believe that2074 !! 9992 files to be opened is far enough for any program !2075 !! @note2076 !! If you intend to use loggers object from this library, you should keep in2077 !! mind that loggers open files with the first free logical unit. Consequently2078 !! if you need to perform I/O operations you should use this function to get a2079 !! free lun instead of just randomly set a lun !2080 INTEGER :: lu2081 !! First free logical unit in the range [7,999] or -1 if no lun is available2082 INTEGER, PARAMETER :: mxlu = 99992083 LOGICAL :: notfree2084 lu = 6 ; notfree = .true.2085 DO WHILE(notfree.AND.lu<=mxlu)2086 lu=lu+1 ; INQUIRE(unit=lu,OPENED=notfree)2087 ENDDO2088 IF (lu >= mxlu) lu = -12089 END FUNCTION free_lun2090 2091 2123 END MODULE CFGPARSE 2092 2124
Note: See TracChangeset
for help on using the changeset viewer.