From 32810cbe8bd870d7cd83b257efc6c83c1dcd338a Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 11 Jul 2023 13:16:00 -0400 Subject: [PATCH 1/4] error formatting through function --- src/CLI.f90 | 50 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/src/CLI.f90 b/src/CLI.f90 index f2575657c..d616ae5d2 100644 --- a/src/CLI.f90 +++ b/src/CLI.f90 @@ -158,36 +158,46 @@ subroutine CLI_init() print'(1x,a,/)',' Prints this message and exits' call quit(0) ! normal Termination case ('-g', '--geom', '--geometry') - if (.not. hasArg) print'(/,1x,a)', 'ERROR: Missing argument for --geom' + if (.not. hasArg) print'(/,1x,a)', asError('missing argument for --geom') geomArg = getArg(i+1) case ('-l', '--load', '--loadcase') - if (.not. hasArg) print'(/,1x,a)', 'ERROR: Missing argument for --load' + if (.not. hasArg) print'(/,1x,a)', asError('missing argument for --load') loadArg = getArg(i+1) case ('-m', '--material', '--materialconfig') - if (.not. hasArg) print'(/,1x,a)', 'ERROR: Missing argument for --material' + if (.not. hasArg) print'(/,1x,a)', asError('missing argument for --material') materialArg = getArg(i+1) case ('-n', '--numerics', '--numericsconfig') - if (.not. hasArg) print'(/,1x,a)', 'ERROR: Missing argument for --numerics' + if (.not. hasArg) print'(/,1x,a)', asError('missing argument for --numerics') numericsArg = getArg(i+1) case ('-j', '--job', '--jobname') - if (.not. hasArg) print'(/,1x,a)', 'ERROR: Missing argument for --jobname' + if (.not. hasArg) print'(/,1x,a)', asError('missing argument for --jobname') solverJobname = getArg(i+1) case ('-w', '--wd', '--workingdir', '--workingdirectory') - if (.not. hasArg) print'(/,1x,a)', 'ERROR: Missing argument for --workingdirectory' + if (.not. hasArg) print'(/,1x,a)', asError('missing argument for --workingdirectory') workingDirArg = getArg(i+1) case ('-r', '--rs', '--restart') - if (.not. hasArg) print'(/,1x,a)', 'ERROR: Missing argument for --restart' + if (.not. hasArg) print'(/,1x,a)', asError('missing argument for --restart') arg = getArg(i+1) read(arg,*,iostat=stat) CLI_restartInc if (CLI_restartInc < 0 .or. stat /= 0) then - print'(/,1x,a)', 'ERROR: Could not parse restart increment: '//trim(arg) + print'(/,1x,a)', asError('could not parse restart increment: '//trim(arg)) call quit(1) end if end select end do - if (.not. all([allocated(loadArg),allocated(geomArg),allocated(materialArg)])) then - print'(/,1x,a)', 'ERROR: Please specify geometry AND load case AND material configuration (-h for help)' + if (.not. allocated(loadArg)) then + print'(/,1x,a)', asError('no load case specified (-h for help)') + call quit(1) + end if + + if (.not. allocated(geomArg)) then + print'(/,1x,a)', asError('no geometry specified (-h for help)') + call quit(1) + end if + + if (.not. allocated(materialArg)) then + print'(/,1x,a)', asError('no material configuration specified (-h for help)') call quit(1) end if @@ -201,7 +211,7 @@ subroutine CLI_init() if (.not. allocated(solverJobname)) then solverJobname = jobname(CLI_geomFile,CLI_loadFile,CLI_materialFile,CLI_numericsFile) elseif (scan(solverJobname,'/') > 0) then - print'(/,1x,a)', 'ERROR: JOBNAME must not contain any slashes' + print'(/,1x,a)', asError('JOBNAME must not contain any slashes') call quit(1) endif @@ -276,7 +286,7 @@ subroutine setWorkingDirectory(workingDirectoryArg) workingDirectory = trim(normpath(workingDirectory)) error = setCWD(trim(workingDirectory)) if (error) then - print'(1x,a)', 'ERROR: Invalid Working directory: '//trim(workingDirectory) + print'(1x,a)', asError('invalid Working directory: '//trim(workingDirectory)) call quit(1) end if @@ -343,7 +353,7 @@ function getPathRelCWD(path,fileType) inquire(file=getPathRelCWD, exist=file_exists) if (.not. file_exists) then - print'(/,1x,a)', 'ERROR: '//fileType//' file does not exist: '//trim(getPathRelCWD) + print'(/,1x,a)', asError(fileType//' file does not exist: '//trim(getPathRelCWD)) call quit(1) end if @@ -428,4 +438,18 @@ function relpath(path,start) end function relpath +!-------------------------------------------------------------------------------------------------- +!> @brief Prefix string with 'ERROR: ' and color it red. +!-------------------------------------------------------------------------------------------------- +function asError(str) + + character(len=*), intent(in) :: str + character(len=:), allocatable :: asError + + asError = 'ERROR: '//achar(27)//'[31m'//trim(str)//achar(27)//'[0m' + +end function asError + + + end module CLI From d452a9ce3f99b1eeb3a47963fbff13cd7999a2ff Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 11 Jul 2023 17:15:03 -0400 Subject: [PATCH 2/4] use IO_error in CLI --- src/CLI.f90 | 69 ++++++++++++----------------------------------------- src/IO.f90 | 48 ++++++++++++++++++++++++++++++------- 2 files changed, 54 insertions(+), 63 deletions(-) diff --git a/src/CLI.f90 b/src/CLI.f90 index d616ae5d2..a94cb2e60 100644 --- a/src/CLI.f90 +++ b/src/CLI.f90 @@ -74,7 +74,7 @@ subroutine CLI_init() print'(a)', achar(27)//'[31m' print'(1x,a,/)', 'debug version - debug version - debug version - debug version - debug version' #else - print'(a)', achar(27)//'[94m' + print'(a)', achar(27)//'[1;94m' #endif print'(1x,a)', ' _/_/_/ _/_/ _/ _/ _/_/ _/_/_/ _/ _/ _/_/_/' print'(1x,a)', ' _/ _/ _/ _/ _/_/ _/_/ _/ _/ _/ _/ _/ _/' @@ -158,48 +158,34 @@ subroutine CLI_init() print'(1x,a,/)',' Prints this message and exits' call quit(0) ! normal Termination case ('-g', '--geom', '--geometry') - if (.not. hasArg) print'(/,1x,a)', asError('missing argument for --geom') + if (.not. hasArg) call IO_error(610) geomArg = getArg(i+1) case ('-l', '--load', '--loadcase') - if (.not. hasArg) print'(/,1x,a)', asError('missing argument for --load') + if (.not. hasArg) call IO_error(611) loadArg = getArg(i+1) case ('-m', '--material', '--materialconfig') - if (.not. hasArg) print'(/,1x,a)', asError('missing argument for --material') + if (.not. hasArg) call IO_error(612) materialArg = getArg(i+1) case ('-n', '--numerics', '--numericsconfig') - if (.not. hasArg) print'(/,1x,a)', asError('missing argument for --numerics') + if (.not. hasArg) call IO_error(613) numericsArg = getArg(i+1) case ('-j', '--job', '--jobname') - if (.not. hasArg) print'(/,1x,a)', asError('missing argument for --jobname') + if (.not. hasArg) call IO_error(614) solverJobname = getArg(i+1) case ('-w', '--wd', '--workingdir', '--workingdirectory') - if (.not. hasArg) print'(/,1x,a)', asError('missing argument for --workingdirectory') + if (.not. hasArg) call IO_error(615) workingDirArg = getArg(i+1) case ('-r', '--rs', '--restart') - if (.not. hasArg) print'(/,1x,a)', asError('missing argument for --restart') + if (.not. hasArg) call IO_error(616) arg = getArg(i+1) read(arg,*,iostat=stat) CLI_restartInc - if (CLI_restartInc < 0 .or. stat /= 0) then - print'(/,1x,a)', asError('could not parse restart increment: '//trim(arg)) - call quit(1) - end if + if (CLI_restartInc < 0 .or. stat /= 0) call IO_error(617,ext_msg=arg) end select end do - if (.not. allocated(loadArg)) then - print'(/,1x,a)', asError('no load case specified (-h for help)') - call quit(1) - end if - - if (.not. allocated(geomArg)) then - print'(/,1x,a)', asError('no geometry specified (-h for help)') - call quit(1) - end if - - if (.not. allocated(materialArg)) then - print'(/,1x,a)', asError('no material configuration specified (-h for help)') - call quit(1) - end if + if (.not. allocated(geomArg)) call IO_error(620,ext_msg='-h for help') + if (.not. allocated(loadArg)) call IO_error(621,ext_msg='-h for help') + if (.not. allocated(materialArg)) call IO_error(622,ext_msg='-h for help') call setWorkingDirectory(trim(workingDirArg)) CLI_geomFile = getPathRelCWD(geomArg,'geometry') @@ -211,8 +197,7 @@ subroutine CLI_init() if (.not. allocated(solverJobname)) then solverJobname = jobname(CLI_geomFile,CLI_loadFile,CLI_materialFile,CLI_numericsFile) elseif (scan(solverJobname,'/') > 0) then - print'(/,1x,a)', asError('JOBNAME must not contain any slashes') - call quit(1) + call IO_error(630) endif commandLine = getArg(-1) @@ -272,9 +257,6 @@ subroutine setWorkingDirectory(workingDirectoryArg) character(len=*), intent(in) :: workingDirectoryArg !< working directory argument character(len=:), allocatable :: workingDirectory - logical :: error - external :: quit - absolutePath: if (workingDirectoryArg(1:1) == '/') then workingDirectory = workingDirectoryArg @@ -284,11 +266,7 @@ subroutine setWorkingDirectory(workingDirectoryArg) end if absolutePath workingDirectory = trim(normpath(workingDirectory)) - error = setCWD(trim(workingDirectory)) - if (error) then - print'(1x,a)', asError('invalid Working directory: '//trim(workingDirectory)) - call quit(1) - end if + if (setCWD(trim(workingDirectory))) call IO_error(640,ext_msg=workingDirectory) end subroutine setWorkingDirectory @@ -344,7 +322,6 @@ function getPathRelCWD(path,fileType) character(len=*), intent(in) :: fileType logical :: file_exists - external :: quit getPathRelCWD = trim(path) @@ -352,10 +329,7 @@ function getPathRelCWD(path,fileType) getPathRelCWD = trim(relpath(getPathRelCWD,getCWD())) inquire(file=getPathRelCWD, exist=file_exists) - if (.not. file_exists) then - print'(/,1x,a)', asError(fileType//' file does not exist: '//trim(getPathRelCWD)) - call quit(1) - end if + if (.not. file_exists) call IO_error(100,ext_msg=fileType//' "'//trim(getPathRelCWD)//'"') end function getPathRelCWD @@ -438,18 +412,5 @@ function relpath(path,start) end function relpath -!-------------------------------------------------------------------------------------------------- -!> @brief Prefix string with 'ERROR: ' and color it red. -!-------------------------------------------------------------------------------------------------- -function asError(str) - - character(len=*), intent(in) :: str - character(len=:), allocatable :: asError - - asError = 'ERROR: '//achar(27)//'[31m'//trim(str)//achar(27)//'[0m' - -end function asError - - end module CLI diff --git a/src/IO.f90 b/src/IO.f90 index 39a48e1e5..a0cf850b6 100644 --- a/src/IO.f90 +++ b/src/IO.f90 @@ -555,6 +555,34 @@ subroutine IO_error(error_ID,ext_msg,label1,ID1,label2,ID2) ! user errors case (603) msg = 'invalid data for table' + case (610) + msg = 'missing argument for --geom' + case (611) + msg = 'missing argument for --load' + case (612) + msg = 'missing argument for --material' + case (613) + msg = 'missing argument for --numerics' + case (614) + msg = 'missing argument for --jobname' + case (615) + msg = 'missing argument for --workingdirectory' + case (616) + msg = 'missing argument for --restart' + case (617) + msg = 'could not parse restart increment' + case (620) + msg = 'no geometry specified' + case (621) + msg = 'no load case specified' + case (622) + msg = 'no material configuration specified' + case (630) + msg = 'JOBNAME must not contain any slashes' + case (640) + msg = 'invalid working directory' + + !------------------------------------------------------------------------------------------------ ! errors related to YAML data @@ -622,9 +650,9 @@ subroutine IO_error(error_ID,ext_msg,label1,ID1,label2,ID2) end select call panel('error',error_ID,msg, & - ext_msg=ext_msg, & - label1=label1,ID1=ID1, & - label2=label2,ID2=ID2) + ext_msg=ext_msg, & + label1=label1,ID1=ID1, & + label2=label2,ID2=ID2) call quit(9000+error_ID) end subroutine IO_error @@ -704,6 +732,7 @@ subroutine panel(paneltype,ID,msg,ext_msg,label1,ID1,label2,ID2) character(len=pSTRLEN) :: formatString integer, parameter :: panelwidth = 69 + character(len=:), allocatable :: msg_,ID_ character(len=*), parameter :: DIVIDER = repeat('─',panelwidth) @@ -712,16 +741,17 @@ subroutine panel(paneltype,ID,msg,ext_msg,label1,ID1,label2,ID2) if ( present(label1) .and. .not. present(ID1)) error stop 'missing value for label 1' if ( present(label2) .and. .not. present(ID2)) error stop 'missing value for label 2' + if (paneltype == 'error') msg_ = achar(27)//'[31m'//trim(msg)//achar(27)//'[0m' + if (paneltype == 'warning') msg_ = achar(27)//'[33m'//trim(msg)//achar(27)//'[0m' + ID_ = IO_intAsStr(ID) !$OMP CRITICAL (write2out) write(IO_STDERR,'(/,a)') ' ┌'//DIVIDER//'┐' - write(formatString,'(a,i2,a)') '(a,24x,a,',max(1,panelwidth-24-len_trim(paneltype)),'x,a)' - write(IO_STDERR,formatString) ' │',trim(paneltype), '│' - write(formatString,'(a,i2,a)') '(a,24x,i3,',max(1,panelwidth-24-3),'x,a)' - write(IO_STDERR,formatString) ' │',ID, '│' + write(formatString,'(a,i2,a)') '(a,24x,a,1x,i0,',max(1,panelwidth-24-len_trim(paneltype)-1-len_trim(ID_)),'x,a)' + write(IO_STDERR,formatString) ' │',trim(paneltype),ID, '│' write(IO_STDERR,'(a)') ' ├'//DIVIDER//'┤' - write(formatString,'(a,i3.3,a,i3.3,a)') '(1x,a4,a',max(1,len_trim(msg)),',',& + write(formatString,'(a,i3.3,a,i3.3,a)') '(1x,a4,a',max(1,len_trim(msg_)),',',& max(1,panelwidth+3-len_trim(msg)-4),'x,a)' - write(IO_STDERR,formatString) '│ ',trim(msg), '│' + write(IO_STDERR,formatString) '│ ',trim(msg_), '│' if (present(ext_msg)) then write(formatString,'(a,i3.3,a,i3.3,a)') '(1x,a4,a',max(1,len_trim(ext_msg)),',',& max(1,panelwidth+3-len_trim(ext_msg)-4),'x,a)' From d9cf3983b49fc6a04139b32e79fff6ab44aa1354 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 12 Jul 2023 12:45:39 +0200 Subject: [PATCH 3/4] more generic error codes allow label without ID in IO_error --- src/CLI.f90 | 22 +++++++++++----------- src/IO.f90 | 45 ++++++++++++++++----------------------------- 2 files changed, 27 insertions(+), 40 deletions(-) diff --git a/src/CLI.f90 b/src/CLI.f90 index a94cb2e60..ce2f68ed7 100644 --- a/src/CLI.f90 +++ b/src/CLI.f90 @@ -158,34 +158,34 @@ subroutine CLI_init() print'(1x,a,/)',' Prints this message and exits' call quit(0) ! normal Termination case ('-g', '--geom', '--geometry') - if (.not. hasArg) call IO_error(610) + if (.not. hasArg) call IO_error(610,ext_msg='--geom') geomArg = getArg(i+1) case ('-l', '--load', '--loadcase') - if (.not. hasArg) call IO_error(611) + if (.not. hasArg) call IO_error(610,ext_msg='--load') loadArg = getArg(i+1) case ('-m', '--material', '--materialconfig') - if (.not. hasArg) call IO_error(612) + if (.not. hasArg) call IO_error(610,ext_msg='--material') materialArg = getArg(i+1) case ('-n', '--numerics', '--numericsconfig') - if (.not. hasArg) call IO_error(613) + if (.not. hasArg) call IO_error(610,ext_msg='--numerics') numericsArg = getArg(i+1) case ('-j', '--job', '--jobname') - if (.not. hasArg) call IO_error(614) + if (.not. hasArg) call IO_error(610,ext_msg='--jobname') solverJobname = getArg(i+1) case ('-w', '--wd', '--workingdir', '--workingdirectory') - if (.not. hasArg) call IO_error(615) + if (.not. hasArg) call IO_error(610,ext_msg='--workingdirectory') workingDirArg = getArg(i+1) case ('-r', '--rs', '--restart') - if (.not. hasArg) call IO_error(616) + if (.not. hasArg) call IO_error(610,ext_msg='--jobname') arg = getArg(i+1) read(arg,*,iostat=stat) CLI_restartInc - if (CLI_restartInc < 0 .or. stat /= 0) call IO_error(617,ext_msg=arg) + if (CLI_restartInc < 0 .or. stat /= 0) call IO_error(611,ext_msg=arg) end select end do - if (.not. allocated(geomArg)) call IO_error(620,ext_msg='-h for help') - if (.not. allocated(loadArg)) call IO_error(621,ext_msg='-h for help') - if (.not. allocated(materialArg)) call IO_error(622,ext_msg='-h for help') + if (.not. allocated(geomArg)) call IO_error(612,ext_msg='--help for instructions',label1='--geom') + if (.not. allocated(loadArg)) call IO_error(612,ext_msg='--help for instructions',label1='--load') + if (.not. allocated(materialArg)) call IO_error(612,ext_msg='--help for instructions',label1='--material') call setWorkingDirectory(trim(workingDirArg)) CLI_geomFile = getPathRelCWD(geomArg,'geometry') diff --git a/src/IO.f90 b/src/IO.f90 index a0cf850b6..86eb6558e 100644 --- a/src/IO.f90 +++ b/src/IO.f90 @@ -556,27 +556,11 @@ subroutine IO_error(error_ID,ext_msg,label1,ID1,label2,ID2) case (603) msg = 'invalid data for table' case (610) - msg = 'missing argument for --geom' + msg = 'no argument value specified' case (611) - msg = 'missing argument for --load' - case (612) - msg = 'missing argument for --material' - case (613) - msg = 'missing argument for --numerics' - case (614) - msg = 'missing argument for --jobname' - case (615) - msg = 'missing argument for --workingdirectory' - case (616) - msg = 'missing argument for --restart' - case (617) msg = 'could not parse restart increment' - case (620) - msg = 'no geometry specified' - case (621) - msg = 'no load case specified' - case (622) - msg = 'no material configuration specified' + case (612) + msg = 'missing argument' case (630) msg = 'JOBNAME must not contain any slashes' case (640) @@ -732,18 +716,21 @@ subroutine panel(paneltype,ID,msg,ext_msg,label1,ID1,label2,ID2) character(len=pSTRLEN) :: formatString integer, parameter :: panelwidth = 69 - character(len=:), allocatable :: msg_,ID_ + character(len=:), allocatable :: msg_,ID_,msg1,msg2 character(len=*), parameter :: DIVIDER = repeat('─',panelwidth) if (.not. present(label1) .and. present(ID1)) error stop 'missing label for value 1' if (.not. present(label2) .and. present(ID2)) error stop 'missing label for value 2' - if ( present(label1) .and. .not. present(ID1)) error stop 'missing value for label 1' - if ( present(label2) .and. .not. present(ID2)) error stop 'missing value for label 2' + + ID_ = IO_intAsStr(ID) + if (present(label1)) msg1 = label1 + if (present(label2)) msg2 = label2 + if (present(ID1)) msg1 = msg1//' '//IO_intAsStr(ID1) + if (present(ID2)) msg2 = msg2//' '//IO_intAsStr(ID2) if (paneltype == 'error') msg_ = achar(27)//'[31m'//trim(msg)//achar(27)//'[0m' if (paneltype == 'warning') msg_ = achar(27)//'[33m'//trim(msg)//achar(27)//'[0m' - ID_ = IO_intAsStr(ID) !$OMP CRITICAL (write2out) write(IO_STDERR,'(/,a)') ' ┌'//DIVIDER//'┐' write(formatString,'(a,i2,a)') '(a,24x,a,1x,i0,',max(1,panelwidth-24-len_trim(paneltype)-1-len_trim(ID_)),'x,a)' @@ -758,14 +745,14 @@ subroutine panel(paneltype,ID,msg,ext_msg,label1,ID1,label2,ID2) write(IO_STDERR,formatString) '│ ',trim(ext_msg), '│' end if if (present(label1)) then - write(formatString,'(a,i3.3,a,i3.3,a)') '(1x,a7,a',max(1,len_trim(label1)),',i9,',& - max(1,panelwidth+3-len_trim(label1)-9-7),'x,a)' - write(IO_STDERR,formatString) '│ at ',trim(label1),ID1, '│' + write(formatString,'(a,i3.3,a,i3.3,a)') '(1x,a7,a',max(1,len_trim(msg1)),',',& + max(1,panelwidth+3-len_trim(msg1)-7),'x,a)' + write(IO_STDERR,formatString) '│ at ',trim(msg1), '│' end if if (present(label2)) then - write(formatString,'(a,i3.3,a,i3.3,a)') '(1x,a7,a',max(1,len_trim(label2)),',i9,',& - max(1,panelwidth+3-len_trim(label2)-9-7),'x,a)' - write(IO_STDERR,formatString) '│ at ',trim(label2),ID2, '│' + write(formatString,'(a,i3.3,a,i3.3,a)') '(1x,a7,a',max(1,len_trim(msg2)),',',& + max(1,panelwidth+3-len_trim(msg2)-7),'x,a)' + write(IO_STDERR,formatString) '│ at ',trim(msg2), '│' end if write(formatString,'(a,i2.2,a)') '(a,',max(1,panelwidth),'x,a)' write(IO_STDERR,formatString) ' │', '│' From b235742472c083e7fe97183269f671ac763241ff Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Fri, 14 Jul 2023 10:23:23 -0400 Subject: [PATCH 4/4] clearer error messages --- src/CLI.f90 | 6 +++--- src/IO.f90 | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/CLI.f90 b/src/CLI.f90 index ce2f68ed7..ed7fbcd5e 100644 --- a/src/CLI.f90 +++ b/src/CLI.f90 @@ -183,9 +183,9 @@ subroutine CLI_init() end select end do - if (.not. allocated(geomArg)) call IO_error(612,ext_msg='--help for instructions',label1='--geom') - if (.not. allocated(loadArg)) call IO_error(612,ext_msg='--help for instructions',label1='--load') - if (.not. allocated(materialArg)) call IO_error(612,ext_msg='--help for instructions',label1='--material') + if (.not. allocated(geomArg)) call IO_error(612,ext_msg='--geom') + if (.not. allocated(loadArg)) call IO_error(612,ext_msg='--load') + if (.not. allocated(materialArg)) call IO_error(612,ext_msg='--material') call setWorkingDirectory(trim(workingDirArg)) CLI_geomFile = getPathRelCWD(geomArg,'geometry') diff --git a/src/IO.f90 b/src/IO.f90 index 86eb6558e..0a8f7b07e 100644 --- a/src/IO.f90 +++ b/src/IO.f90 @@ -556,11 +556,11 @@ subroutine IO_error(error_ID,ext_msg,label1,ID1,label2,ID2) case (603) msg = 'invalid data for table' case (610) - msg = 'no argument value specified' + msg = 'missing argument for option' case (611) msg = 'could not parse restart increment' case (612) - msg = 'missing argument' + msg = 'missing option' case (630) msg = 'JOBNAME must not contain any slashes' case (640)