29 #include "../base/base_uses.f90"
34 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'cp_parser_inpp_methods'
35 LOGICAL,
PARAMETER,
PRIVATE :: debug_this_module = .false.
36 INTEGER,
PARAMETER,
PRIVATE :: max_message_length = 400
39 PRIVATE :: inpp_find_variable, inpp_list_variables
48 LOGICAL PURE FUNCTION is_valid_varname(str)
49 CHARACTER(LEN=*),
INTENT(IN) :: str
50 CHARACTER(LEN=*),
PARAMETER :: alpha =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"
51 CHARACTER(LEN=*),
PARAMETER :: alphanum = alpha//
"0123456789"
54 is_valid_varname = .false.
59 IF (index(alpha, str(1:1)) == 0) &
63 IF (index(alphanum, str(idx:idx)) == 0) &
67 is_valid_varname = .true.
68 END FUNCTION is_valid_varname
85 TYPE(inpp_type),
POINTER :: inpp
86 CHARACTER(LEN=*),
INTENT(INOUT) :: input_line, input_file_name
87 INTEGER,
INTENT(INOUT) :: input_line_number, input_unit
89 CHARACTER(LEN=default_path_length) :: cond1, cond2, filename, mytag,
value, &
91 CHARACTER(LEN=max_message_length) :: message
92 INTEGER :: i, indf, indi, istat, output_unit, pos1, &
96 output_unit = cp_logger_get_default_io_unit()
98 cpassert(
ASSOCIATED(inpp))
101 indi = index(input_line,
"@")
102 pos1 = index(input_line,
"!")
103 pos2 = index(input_line,
"#")
104 IF (((pos1 > 0) .AND. (pos1 < indi)) .OR. ((pos2 > 0) .AND. (pos2 < indi)))
THEN
111 DO WHILE (.NOT. is_whitespace(input_line(indf:indf)))
114 mytag = input_line(indi:indf - 1)
121 filename = trim(input_line(indf:))
122 IF (len_trim(filename) == 0)
THEN
123 WRITE (unit=message, fmt=
"(A,I0)") &
124 "No filename argument found for "//trim(mytag)// &
125 " directive in file <"//trim(input_file_name)// &
126 "> Line:", input_line_number
127 cpabort(trim(message))
130 DO WHILE (is_whitespace(filename(indi:indi)))
133 filename = trim(filename(indi:))
136 pos1 = index(filename,
'"')
137 pos2 = index(filename(pos1 + 1:),
'"')
138 IF ((pos1 /= 0) .AND. (pos2 /= 0))
THEN
139 filename = filename(pos1 + 1:pos1 + pos2 - 1)
141 pos1 = index(filename,
"'")
142 pos2 = index(filename(pos1 + 1:),
"'")
143 IF ((pos1 /= 0) .AND. (pos2 /= 0))
THEN
144 filename = filename(pos1 + 1:pos1 + pos2 - 1)
147 pos2 = index(filename,
'"')
148 IF ((pos1 /= 0) .OR. (pos2 /= 0))
THEN
149 WRITE (unit=message, fmt=
"(A,I0)") &
150 "Incorrect quoting of the included filename in file <", &
151 trim(input_file_name)//
"> Line:", input_line_number
152 cpabort(trim(message))
158 DO i = 1, inpp%io_stack_level
159 check = trim(filename) /= trim(inpp%io_stack_filename(i))
163 CALL open_file(file_name=trim(filename), &
165 file_form=
"FORMATTED", &
166 file_action=
"READ", &
170 inpp%io_stack_level = inpp%io_stack_level + 1
171 CALL reallocate(inpp%io_stack_channel, 1, inpp%io_stack_level)
172 CALL reallocate(inpp%io_stack_lineno, 1, inpp%io_stack_level)
173 CALL reallocate(inpp%io_stack_filename, 1, inpp%io_stack_level)
175 inpp%io_stack_channel(inpp%io_stack_level) = input_unit
176 inpp%io_stack_lineno(inpp%io_stack_level) = input_line_number
177 inpp%io_stack_filename(inpp%io_stack_level) = input_file_name
179 input_file_name = trim(filename)
180 input_line_number = 0
183 CASE (
"@FFTYPE",
"@XCTYPE")
187 filename = trim(input_line(indf:))
188 IF (len_trim(filename) == 0)
THEN
189 WRITE (unit=message, fmt=
"(A,I0)") &
190 "No filename argument found for "//trim(mytag)// &
191 " directive in file <"//trim(input_file_name)// &
192 "> Line:", input_line_number
193 cpabort(trim(message))
196 DO WHILE (is_whitespace(filename(indi:indi)))
199 filename = trim(filename(indi:))
202 pos1 = index(filename,
'"')
203 pos2 = index(filename(pos1 + 1:),
'"')
204 IF ((pos1 /= 0) .AND. (pos2 /= 0))
THEN
205 filename = filename(pos1 + 1:pos1 + pos2 - 1)
207 pos1 = index(filename,
"'")
208 pos2 = index(filename(pos1 + 1:),
"'")
209 IF ((pos1 /= 0) .AND. (pos2 /= 0))
THEN
210 filename = filename(pos1 + 1:pos1 + pos2 - 1)
213 pos2 = index(filename,
'"')
214 IF ((pos1 /= 0) .OR. (pos2 /= 0))
THEN
215 WRITE (unit=message, fmt=
"(A,I0)") &
216 "Incorrect quoting of the filename argument in file <", &
217 trim(input_file_name)//
"> Line:", input_line_number
218 cpabort(trim(message))
224 filename = trim(filename)//
".sec"
226 IF (.NOT. file_exists(trim(filename)))
THEN
227 IF (filename(1:1) ==
"/")
THEN
232 filename =
"forcefield_section/"//trim(filename)
234 filename =
"xc_section/"//trim(filename)
238 IF (.NOT. file_exists(trim(filename)))
THEN
239 WRITE (unit=message, fmt=
"(A,I0)") &
240 trim(mytag)//
": Could not find the file <"// &
241 trim(filename)//
"> with the input section given in the file <"// &
242 trim(input_file_name)//
"> Line: ", input_line_number
243 cpabort(trim(message))
247 DO i = 1, inpp%io_stack_level
248 check = trim(filename) /= trim(inpp%io_stack_filename(i))
253 CALL open_file(file_name=trim(filename), &
255 file_form=
"FORMATTED", &
256 file_action=
"READ", &
260 inpp%io_stack_level = inpp%io_stack_level + 1
261 CALL reallocate(inpp%io_stack_channel, 1, inpp%io_stack_level)
262 CALL reallocate(inpp%io_stack_lineno, 1, inpp%io_stack_level)
263 CALL reallocate(inpp%io_stack_filename, 1, inpp%io_stack_level)
265 inpp%io_stack_channel(inpp%io_stack_level) = input_unit
266 inpp%io_stack_lineno(inpp%io_stack_level) = input_line_number
267 inpp%io_stack_filename(inpp%io_stack_level) = input_file_name
269 input_file_name = trim(filename)
270 input_line_number = 0
275 varname = trim(input_line(indf:))
276 IF (len_trim(varname) == 0)
THEN
277 WRITE (unit=message, fmt=
"(A,I0)") &
278 "No variable name found for "//trim(mytag)//
" directive in file <"// &
279 trim(input_file_name)//
"> Line:", input_line_number
280 cpabort(trim(message))
284 DO WHILE (is_whitespace(varname(indi:indi)))
288 DO WHILE (.NOT. is_whitespace(varname(indf:indf)))
291 value = trim(varname(indf:))
292 varname = trim(varname(indi:indf - 1))
294 IF (.NOT. is_valid_varname(trim(varname)))
THEN
295 WRITE (unit=message, fmt=
"(A,I0)") &
296 "Invalid variable name for "//trim(mytag)//
" directive in file <"// &
297 trim(input_file_name)//
"> Line:", input_line_number
298 cpabort(trim(message))
302 DO WHILE (is_whitespace(value(indi:indi)))
305 value = trim(value(indi:))
307 IF (len_trim(
value) == 0)
THEN
308 WRITE (unit=message, fmt=
"(A,I0)") &
309 "Incomplete "//trim(mytag)//
" directive: "// &
310 "No value found for variable <"//trim(varname)//
"> in file <"// &
311 trim(input_file_name)//
"> Line:", input_line_number
312 cpabort(trim(message))
316 indi = inpp_find_variable(inpp, varname)
319 inpp%num_variables = inpp%num_variables + 1
320 CALL reallocate(inpp%variable_name, 1, inpp%num_variables)
321 CALL reallocate(inpp%variable_value, 1, inpp%num_variables)
322 inpp%variable_name(inpp%num_variables) = varname
323 inpp%variable_value(inpp%num_variables) =
value
324 IF (debug_this_module .AND. output_unit > 0)
THEN
325 WRITE (unit=message, fmt=
"(3A,I6,4A)")
"INPP_@SET: in file: ", &
326 trim(input_file_name),
" Line:", input_line_number, &
327 " Set new variable ", trim(varname),
" to value: ", trim(
value)
328 WRITE (output_unit, *) trim(message)
332 IF (debug_this_module .AND. output_unit > 0)
THEN
333 WRITE (unit=message, fmt=
"(3A,I6,6A)")
"INPP_@SET: in file: ", &
334 trim(input_file_name),
" Line:", input_line_number, &
335 " Change variable ", trim(varname),
" from value: ", &
336 trim(inpp%variable_value(indi)),
" to value: ", trim(
value)
337 WRITE (output_unit, *) trim(message)
339 inpp%variable_value(indi) =
value
342 IF (debug_this_module)
CALL inpp_list_variables(inpp, 6)
350 pos1 = index(input_line,
"==")
351 pos2 = index(input_line,
"/=")
353 DO WHILE (is_whitespace(input_line(indi:indi)))
355 IF (indi > len_trim(input_line))
EXIT
359 cond1 = input_line(indi:pos1 - 1)
360 cond2 = input_line(pos1 + 2:)
362 IF ((pos2 > 0) .OR. (index(cond2,
"==") > 0))
THEN
363 WRITE (unit=message, fmt=
"(A,I0)") &
364 "Incorrect "//trim(mytag)//
" directive found in file <", &
365 trim(input_file_name)//
"> Line:", input_line_number
366 cpabort(trim(message))
368 ELSE IF (pos2 > 0)
THEN
369 cond1 = input_line(indi:pos2 - 1)
370 cond2 = input_line(pos2 + 2:)
372 IF ((pos1 > 0) .OR. (index(cond2,
"/=") > 0))
THEN
373 WRITE (unit=message, fmt=
"(A,I0)") &
374 "Incorrect "//trim(mytag)//
" directive found in file <", &
375 trim(input_file_name)//
"> Line:", input_line_number
376 cpabort(trim(message))
379 IF (len_trim(input_line(indi:)) > 0)
THEN
380 IF (trim(input_line(indi:)) ==
'0')
THEN
397 IF (index(cond1,
"(") /= 0) cond1 = cond1(index(cond1,
"(") + 1:)
398 IF (index(cond2,
")") /= 0) cond2 = cond2(1:index(cond2,
")") - 1)
402 DO WHILE (is_whitespace(cond1(indi:indi)))
409 DO WHILE (is_whitespace(cond2(indi:indi)))
414 IF (len_trim(cond2) == 0)
THEN
415 WRITE (unit=message, fmt=
"(3A,I6)") &
416 "INPP_@IF: Incorrect @IF directive in file: ", &
417 trim(input_file_name),
" Line:", input_line_number
418 cpabort(trim(message))
421 IF ((trim(cond1) == trim(cond2)) .EQV. check)
THEN
422 IF (debug_this_module .AND. output_unit > 0)
THEN
423 WRITE (unit=message, fmt=
"(3A,I6,A)")
"INPP_@IF: in file: ", &
424 trim(input_file_name),
" Line:", input_line_number, &
425 " Conditional ("//trim(cond1)//
","//trim(cond2)// &
426 ") resolves to true. Continuing parsing."
427 WRITE (output_unit, *) trim(message)
432 IF (debug_this_module .AND. output_unit > 0)
THEN
433 WRITE (unit=message, fmt=
"(3A,I6,A)")
"INPP_@IF: in file: ", &
434 trim(input_file_name),
" Line:", input_line_number, &
435 " Conditional ("//trim(cond1)//
","//trim(cond2)// &
436 ") resolves to false. Skipping Lines."
437 WRITE (output_unit, *) trim(message)
440 DO WHILE (istat == 0)
441 input_line_number = input_line_number + 1
442 READ (unit=input_unit, fmt=
"(A)", iostat=istat) input_line
443 IF (debug_this_module .AND. output_unit > 0)
THEN
444 WRITE (unit=message, fmt=
"(1A,I6,2A)")
"INPP_@IF: skipping line ", &
445 input_line_number,
": ", trim(input_line)
446 WRITE (output_unit, *) trim(message)
449 indi = index(input_line,
"@")
450 pos1 = index(input_line,
"!")
451 pos2 = index(input_line,
"#")
452 IF (((pos1 > 0) .AND. (pos1 < indi)) .OR. ((pos2 > 0) .AND. (pos2 < indi)))
THEN
460 DO WHILE (input_line(indf:indf) /=
" ")
463 cpassert((indf - indi) <= default_string_length)
464 mytag = input_line(indi:indf - 1)
466 IF (index(mytag,
"@ENDIF") > 0)
THEN
468 IF (debug_this_module .AND. output_unit > 0)
THEN
469 WRITE (output_unit, *)
"INPP_@IF: found @ENDIF. End of skipping."
475 WRITE (unit=message, fmt=
"(A,I0)") &
476 "Error while searching for matching @ENDIF directive in file <"// &
477 trim(input_file_name)//
"> Line:", input_line_number
478 cpabort(trim(message))
484 IF (debug_this_module .AND. output_unit > 0)
THEN
485 WRITE (unit=message, fmt=
"(A,I0)") &
486 trim(mytag)//
" directive found and ignored in file <"// &
487 trim(input_file_name)//
"> Line: ", input_line_number
492 IF (output_unit > 0)
THEN
493 WRITE (unit=output_unit, fmt=
"(T2,A,I0,A)") &
494 trim(mytag)//
" directive in file <"// &
495 trim(input_file_name)//
"> Line: ", input_line_number, &
496 " ->"//trim(input_line(indf:))
515 TYPE(inpp_type),
POINTER :: inpp
516 CHARACTER(LEN=*),
INTENT(INOUT) :: input_file_name
517 INTEGER,
INTENT(INOUT) :: input_line_number, input_unit
519 cpassert(
ASSOCIATED(inpp))
520 IF (inpp%io_stack_level > 0)
THEN
521 CALL close_file(input_unit)
522 input_unit = inpp%io_stack_channel(inpp%io_stack_level)
523 input_line_number = inpp%io_stack_lineno(inpp%io_stack_level)
524 input_file_name = trim(inpp%io_stack_filename(inpp%io_stack_level))
525 inpp%io_stack_level = inpp%io_stack_level - 1
526 CALL reallocate(inpp%io_stack_channel, 1, inpp%io_stack_level)
527 CALL reallocate(inpp%io_stack_lineno, 1, inpp%io_stack_level)
528 CALL reallocate(inpp%io_stack_filename, 1, inpp%io_stack_level)
545 TYPE(inpp_type),
POINTER :: inpp
546 CHARACTER(LEN=*),
INTENT(INOUT) :: input_line, input_file_name
547 INTEGER,
INTENT(IN) :: input_line_number
549 CHARACTER(LEN=default_path_length) :: newline
550 CHARACTER(LEN=max_message_length) :: message
551 CHARACTER(LEN=:),
ALLOCATABLE :: var_value, var_name
552 INTEGER ::
idx, pos1, pos2, default_val_sep_idx
554 cpassert(
ASSOCIATED(inpp))
557 DO WHILE (index(input_line,
'${') > 0)
558 pos1 = index(input_line,
'${')
560 pos2 = index(input_line(pos1:),
'}')
563 WRITE (unit=message, fmt=
"(3A,I6)") &
564 "Missing '}' in file: ", &
565 trim(input_file_name),
" Line:", input_line_number
566 cpabort(trim(message))
569 pos2 = pos1 + pos2 - 2
570 var_name = input_line(pos1:pos2)
572 default_val_sep_idx = index(var_name,
'-')
574 IF (default_val_sep_idx > 0)
THEN
575 var_value = var_name(default_val_sep_idx + 1:)
576 var_name = var_name(:default_val_sep_idx - 1)
579 IF (.NOT. is_valid_varname(var_name))
THEN
580 WRITE (unit=message, fmt=
"(5A,I6)") &
581 "Invalid variable name ${", var_name,
"} in file: ", &
582 trim(input_file_name),
" Line:", input_line_number
583 cpabort(trim(message))
586 idx = inpp_find_variable(inpp, var_name)
588 IF (
idx == 0 .AND. default_val_sep_idx == 0)
THEN
589 WRITE (unit=message, fmt=
"(5A,I6)") &
590 "Variable ${", var_name,
"} not defined in file: ", &
591 trim(input_file_name),
" Line:", input_line_number
592 cpabort(trim(message))
596 var_value = trim(inpp%variable_value(
idx))
598 newline = input_line(1:pos1 - 3)//var_value//input_line(pos2 + 2:)
603 DO WHILE (index(input_line,
'$') > 0)
604 pos1 = index(input_line,
'$')
606 pos2 = index(input_line(pos1:),
' ')
609 pos2 = len_trim(input_line(pos1:)) + 1
611 pos2 = pos1 + pos2 - 2
612 var_name = input_line(pos1:pos2)
613 idx = inpp_find_variable(inpp, var_name)
615 IF (.NOT. is_valid_varname(var_name))
THEN
616 WRITE (unit=message, fmt=
"(5A,I6)") &
617 "Invalid variable name ${", var_name,
"} in file: ", &
618 trim(input_file_name),
" Line:", input_line_number
619 cpabort(trim(message))
623 WRITE (unit=message, fmt=
"(5A,I6)") &
624 "Variable $", var_name,
" not defined in file: ", &
625 trim(input_file_name),
" Line:", input_line_number
626 cpabort(trim(message))
629 newline = input_line(1:pos1 - 2)//trim(inpp%variable_value(
idx))//input_line(pos2 + 1:)
645 FUNCTION inpp_find_variable(inpp, varname)
RESULT(idx)
646 TYPE(inpp_type),
POINTER :: inpp
647 CHARACTER(len=*),
INTENT(IN) :: varname
653 DO i = 1, inpp%num_variables
654 IF (trim(varname) == trim(inpp%variable_name(i)))
THEN
660 END FUNCTION inpp_find_variable
671 SUBROUTINE inpp_list_variables(inpp, iochan)
672 TYPE(inpp_type),
POINTER :: inpp
673 INTEGER,
INTENT(IN) :: iochan
677 WRITE (iochan,
'(A)')
' # NAME VALUE'
678 DO i = 1, inpp%num_variables
679 WRITE (iochan,
'(I4," | ",A,T30," | ",A," |")') &
680 i, trim(inpp%variable_name(i)), trim(inpp%variable_value(i))
682 END SUBROUTINE inpp_list_variables
subroutine uppercase(string)
...
static GRID_HOST_DEVICE int idx(const orbital a)
Return coset index of given orbital angular momentum.
Utility routines to open and close files. Tracking of preconnections.
subroutine, public open_file(file_name, file_status, file_form, file_action, file_position, file_pad, unit_number, debug, skip_get_unit_number, file_access)
Opens the requested file using a free unit number.
subroutine, public close_file(unit_number, file_status, keep_preconnection)
Close an open file given by its logical unit number. Optionally, keep the file and unit preconnected.
logical function, public file_exists(file_name)
Checks if file exists, considering also the file discovery mechanism.
various routines to log and control the output. The idea is that decisions about where to log should ...
integer function, public cp_logger_get_default_io_unit(logger)
returns the unit nr for the ionode (-1 on all other processors) skips as well checks if the procs cal...
a module to allow simple internal preprocessing in input files.
subroutine, public inpp_expand_variables(inpp, input_line, input_file_name, input_line_number)
expand all ${VAR} or $VAR variable entries on the input string (LTR, no nested vars)
subroutine, public inpp_end_include(inpp, input_file_name, input_line_number, input_unit)
Restore older file status from stack after EOF on include file.
subroutine, public inpp_process_directive(inpp, input_line, input_file_name, input_line_number, input_unit)
process internal preprocessor directives like @INCLUDE, @SET, @IF/@ENDIF
a module to allow simple internal preprocessing in input files.
Defines the basic variable types.
integer, parameter, public default_string_length
integer, parameter, public default_path_length
Utility routines for the memory handling.
Utilities for string manipulations.
elemental logical function, public is_whitespace(testchar)
returns .true. if the character passed is a whitespace char.
elemental subroutine, public uppercase(string)
Convert all lower case characters in a string to upper case.