@@ -46,7 +46,7 @@ module f90getopt
4646! ------------------ Implicit -----------------------------------------------------------------------------------------------------
4747 IMPLICIT NONE
4848! ------------------ Local declarations -------------------------------------------------------------------------------------------
49- PUBLIC :: getopt, option_s, optarg
49+ PUBLIC :: getopt, option_s, optarg, isnum
5050 PRIVATE ! all other are private (hidden)
5151! ------------------ Constant declarations ----------------------------------------------------------------------------------------
5252
@@ -247,4 +247,101 @@ character function process_short( optstring, arg )
247247 endif
248248 end function process_short
249249
250+ ! ----------------------------------------
251+ ! Utility function(s)
252+ ! ----------------------------------------
253+
254+ integer function isnum (txtval )
255+ ! Verify whether a character string represents a numerical value
256+ !
257+ ! Can be used to check "optarg" for numbers. Can distinguish
258+ ! integer, real/double and character strings:
259+ !
260+ ! isnum = 0 => txtval is a string
261+ ! isnum = 1 => txtval is a integer
262+ ! isnum > 1 => txtval is a real/double
263+
264+ character (len=* ), intent (in ) :: txtval
265+
266+ ! Declaration local constants
267+ integer , parameter :: CINT = 1 ! when txtval contains integer
268+ integer , parameter :: CREAL = 2 ! when txtval contains real
269+ integer , parameter :: CREXP = 3 ! when txtval contains real (exponential)
270+
271+ ! Declaration local variables
272+ integer :: num ! numerical indicator variable, if > 0 (0 >= num >= CREXP)
273+ logical :: isint ! integer indicator, if .true.
274+ logical :: isexp ! real with exponent indicator, if .true.
275+ logical :: issign ! sign (+/-) indicator, if .true.
276+ logical :: issignexp ! sign (+/-) indicator for exponents, if .true.
277+ logical :: isblank ! indicator for blanks between characters
278+ integer :: i ! control variable (index), max. len(txtvar)
279+
280+ ! Initialize local variables
281+ num = 0
282+ isint = .false.
283+ isexp = .false.
284+ issign = .false.
285+ issignexp = .false.
286+ isblank = .false.
287+ i = 0
288+
289+ ! loop over characters
290+ do
291+ if (i >= len (txtval)) then
292+ ! last check
293+ if (isint .eqv. .false. ) exit
294+ if (num >= CREXP .AND. (isexp .eqv. .false. )) exit
295+ isnum = num
296+ return
297+ end if
298+
299+ i = i + 1
300+
301+ select case (txtval(i:i))
302+ ! process blanks
303+ case (' ' )
304+ if (num == 0 .and. (isblank .eqv. .false. )) then ! preceding or trailing blanks
305+ continue
306+ else if (num /= 0 ) then ! blank after sign or number
307+ isblank = .true.
308+ end if
309+ ! process digits
310+ case (' 0' , ' 1' , ' 2' , ' 3' , ' 4' , ' 5' , ' 6' , ' 7' , ' 8' , ' 9' )
311+ if (num == 0 ) num = CINT ! first number
312+ if (num < CREXP) then ! no exponent number
313+ isint = .true.
314+ else ! exponent number
315+ isexp = .true.
316+ end if
317+ if (isblank .eqv. .true. ) exit ! if blanks are in the middle => string
318+ ! process signs
319+ case (' +' , ' -' )
320+ if (num == 0 ) then ! sign of number
321+ if (issign .eqv. .true. ) exit ! second sign without number => string
322+ issign = .true.
323+ num = CINT
324+ else ! sign of exponent
325+ if (num < CREXP) exit
326+ if (issignexp .eqv. .true. ) exit
327+ issignexp = .true.
328+ end if
329+ ! process decimal point
330+ case (' .' )
331+ if (num /= CINT .AND. i /= 1 ) exit
332+ num = CREAL
333+ ! process exponent
334+ case (' e' , ' E' , ' d' , ' D' )
335+ if (num >= CREXP) exit
336+ if (isint .eqv. .false. ) exit
337+ num = CREXP
338+ case DEFAULT ! any other character means the string is non-numeric
339+ exit
340+ end SELECT
341+ end DO
342+
343+ isnum = 0 ! if this point is reached, the string is non-numeric
344+ RETURN
345+ end function isnum
346+
250347end module f90getopt
0 commit comments