Index: LMDZ6/branches/LMDZ-tracers/libf/misc/strings_mod.F90
===================================================================
--- LMDZ6/branches/LMDZ-tracers/libf/misc/strings_mod.F90	(revision 3891)
+++ LMDZ6/branches/LMDZ-tracers/libf/misc/strings_mod.F90	(revision 3892)
@@ -17,5 +17,4 @@
   INTERFACE strHead;    MODULE PROCEDURE    strHead_1,                strHead_m; END INTERFACE strHead
   INTERFACE strTail;    MODULE PROCEDURE    strTail_1,                strTail_m; END INTERFACE strTail
-  INTERFACE strStack;   MODULE PROCEDURE   strStack_1,               strStack_2; END INTERFACE strStack
   INTERFACE strClean;   MODULE PROCEDURE   strClean_1,               strClean_m; END INTERFACE strClean
   INTERFACE strReduce;  MODULE PROCEDURE  strReduce_1,              strReduce_2; END INTERFACE strReduce
@@ -66,5 +65,5 @@
   CHARACTER(LEN=*), INTENT(IN)    :: def
   val = def; CALL getin(nam, val)
-  WRITE(lunout,*)TRIM(nam)//' = '//TRIM(val)
+  IF(val/=def) WRITE(lunout,*)TRIM(nam)//' = '//TRIM(val)
 END SUBROUTINE getin_s
 !==============================================================================================================================
@@ -75,5 +74,5 @@
   INTEGER,          INTENT(IN)    :: def
   val = def; CALL getin(nam, val)
-  WRITE(lunout,*)TRIM(nam)//' = '//TRIM(int2str(val))
+  IF(val/=def) WRITE(lunout,*)TRIM(nam)//' = '//TRIM(int2str(val))
 END SUBROUTINE getin_i
 !==============================================================================================================================
@@ -84,5 +83,5 @@
   REAL,             INTENT(IN)    :: def
   val = def; CALL getin(nam, val)
-  WRITE(lunout,*)TRIM(nam)//' = '//TRIM(real2str(val))
+  IF(val/=def) WRITE(lunout,*)TRIM(nam)//' = '//TRIM(real2str(val))
 END SUBROUTINE getin_r
 !==============================================================================================================================
@@ -93,5 +92,5 @@
   LOGICAL,          INTENT(IN)    :: def
   val = def; CALL getin(nam, val)
-  WRITE(lunout,*)TRIM(nam)//' = '//TRIM(bool2str(val))
+  IF(val/=def) WRITE(lunout,*)TRIM(nam)//' = '//TRIM(bool2str(val))
 END SUBROUTINE getin_l
 !==============================================================================================================================
@@ -190,25 +189,48 @@
 !==============================================================================================================================
 CHARACTER(LEN=256) FUNCTION strHead_1(str,sep) RESULT(out)
-  CHARACTER(LEN=*), INTENT(IN) :: str, sep
-  out = str(1:INDEX(str,sep)-1); IF(out=='') out=str
+  CHARACTER(LEN=*),           INTENT(IN) :: str
+  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep
+  IF(PRESENT(sep)) THEN
+    out = str(1:INDEX(str,sep,.TRUE.)-1)
+  ELSE
+    out = str(1:INDEX(str,'/',.TRUE.)-1)
+  END IF
+  IF(out == '') out = str
 END FUNCTION strHead_1
 !==============================================================================================================================
 CHARACTER(LEN=256) FUNCTION strTail_1(str,sep) RESULT(out)
-  CHARACTER(LEN=*), INTENT(IN) :: str, sep
-  out = str(INDEX(str,sep,.TRUE.)+LEN(sep):LEN_TRIM(str)); IF(out=='') out=str
+  CHARACTER(LEN=*),           INTENT(IN) :: str
+  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep
+  IF(PRESENT(sep)) THEN
+    out = str(INDEX(str,sep,.TRUE.)+LEN(sep):LEN_TRIM(str))
+  ELSE
+    out = str(INDEX(str,'/',.TRUE.)+1:LEN_TRIM(str))
+  END IF
+  IF(out == '') out = str
 END FUNCTION strTail_1
 !==============================================================================================================================
 FUNCTION strHead_m(str,sep) RESULT(out)
-  CHARACTER(LEN=256), ALLOCATABLE :: out(:)
-  CHARACTER(LEN=*),    INTENT(IN) :: str(:), sep
+  CHARACTER(LEN=256),        ALLOCATABLE :: out(:)
+  CHARACTER(LEN=*),           INTENT(IN) :: str(:)
+  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep
   INTEGER :: k
-  out = [(strHead_1(str(k),sep), k=1, SIZE(str))]
+  IF(PRESENT(sep)) THEN
+    out = [(strHead_1(str(k),sep), k=1, SIZE(str))]
+  ELSE
+    out = [(strHead_1(str(k)),     k=1, SIZE(str))]
+  END IF
+
 END FUNCTION strHead_m
 !==============================================================================================================================
 FUNCTION strTail_m(str,sep) RESULT(out)
-  CHARACTER(LEN=256), ALLOCATABLE :: out(:)
-  CHARACTER(LEN=*),    INTENT(IN) :: str(:), sep
+  CHARACTER(LEN=256),        ALLOCATABLE :: out(:)
+  CHARACTER(LEN=*),           INTENT(IN) :: str(:)
+  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep
   INTEGER :: k
-  out = [(strTail_1(str(k),sep), k=1, SIZE(str))]
+  IF(PRESENT(sep)) THEN
+    out = [(strTail_1(str(k),sep), k=1, SIZE(str))]
+  ELSE
+    out = [(strTail_1(str(k)),     k=1, SIZE(str))]
+  END IF
 END FUNCTION strTail_m
 !==============================================================================================================================
@@ -218,5 +240,5 @@
 !=== Concatenates the strings "str(:)" with separator "sep" into a single string using a separator (',' by default). ==========
 !==============================================================================================================================
-FUNCTION strStack_1(str, sep) RESULT(out)
+FUNCTION strStack(str, sep) RESULT(out)
   CHARACTER(LEN=:),          ALLOCATABLE :: out
   CHARACTER(LEN=*),           INTENT(IN) :: str(:)
@@ -225,19 +247,7 @@
   INTEGER :: is
   IF(SIZE(str) == 0) THEN; out = ''; RETURN; END IF
-  ALLOCATE(s, SOURCE=','); IF(PRESENT(sep)) s=sep
-  out = TRIM(str(1)); DO is=2,SIZE(str, DIM=1); out = TRIM(out)//s//' '//TRIM(str(is)); END DO
-END FUNCTION strStack_1
-!==============================================================================================================================
-FUNCTION strStack_2(str1, str2, sep) RESULT(out)
-  CHARACTER(LEN=:),          ALLOCATABLE :: out
-  CHARACTER(LEN=*),           INTENT(IN) :: str1(:), str2(:)
-  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep
-  CHARACTER(LEN=:), ALLOCATABLE :: s
-  INTEGER :: is
-  IF(SIZE(str1) == 0) THEN; out = ''; RETURN; END IF
-  ALLOCATE(s, SOURCE=','); IF(PRESENT(sep)) s=sep
-  out = TRIM(str1(1))//'='//TRIM(str2(1))
-  DO is=2,SIZE(str1); out = TRIM(out)//s//' '//TRIM(str1(is))//'='//TRIM(str2(is)); END DO
-END FUNCTION strStack_2
+  ALLOCATE(s, SOURCE=', '); IF(PRESENT(sep)) s=sep
+  out = str(1); DO is=2,SIZE(str, DIM=1); out = TRIM(out)//s//TRIM(str(is)); END DO
+END FUNCTION strStack
 !==============================================================================================================================
 !=== Concatenate the strings "str(:)" with separator "sep" into one or several lines of "nmax" characters max (for display) ===
@@ -304,4 +314,5 @@
   CHARACTER(LEN=256), ALLOCATABLE :: s1(:)
   INTEGER :: k, n, n1
+  IF(PRESENT(nb)) nb = 0
   CALL MOVE_ALLOC(FROM = str1, TO = s1); CALL strClean(s1)
   n1 = SIZE(s1, DIM=1)                                     !--- Total nb of  elements in "s1"
@@ -406,22 +417,28 @@
 
   INTEGER, ALLOCATABLE :: ii(:)
-  LOGICAL              :: ll
+  LOGICAL              :: ll, ls
   CHARACTER(LEN=256)   :: d
-
+!  modname = 'strIdx'
   lerr = .FALSE.
   idx = strIdx1(rawList, del, ibeg, idel)
-  IF(idx == 0)                  RETURN                               !--- No separator found                      => finished
-  IF(.NOT.PRESENT(lSc))         RETURN; IF(.NOT.lSc ) RETURN         !--- No need to check exceptions for numbers => finished
-  IF(INDEX('+-',del(idel))==0)  RETURN                               !--- No possible sign ambiguity              => finished
-  ll = idx == 1                                                      !--- This is a front sign of a number
-  IF(idx /= 1) ll = INDEX('^*/+-',rawList(idx-1:idx-1)) /= 0         !--- This is a front sign of a number after an operator
-  IF(ll)       idx = strIdx1(rawList, del,idx+1,idel)                !---   => TO THE NEXT DELIMITER
-  IF(idx /= 0) THEN
-    IF(idx /= 1) ll = INDEX('eE' ,rawList(idx-1:idx-1)) /= 0         !--- Exponent sign of a number in scientific notation ?
-    IF(ll)     idx = strIdx1(rawList, del,idx+1,idel)                !--- Identify the next delimiter
-  END IF
-  IF(idx /= 0) lerr = is_numeric(rawList(ibeg:idx              -1))  !--- Check whether the previous word was a number
-  IF(idx == 0) lerr = is_numeric(rawList(ibeg:LEN_TRIM(rawList)-1))  !--- Check whether the previous word was a number
-  IF(idx == 0) idel = 0
+  IF(.NOT.PRESENT(lSc))                     RETURN                  !--- No need to check exceptions for numbers => finished
+  IF(.NOT.        lSc )                     RETURN                  !--- No need to check exceptions for numbers => finished
+  IF(idx == 0) THEN
+    lerr = .NOT.is_numeric(rawList(ibeg:)); RETURN                  !--- No separator detected: string must be a number
+  END IF
+  IF(test(idx==1.AND.INDEX('+-',del(idel))/=0, lerr)) RETURN        !--- Front separator different from +/-: error
+  IF(is_numeric(rawList(ibeg:idx-1)))                 RETURN        !--- The input string tail is a valid number
+  idx = strIdx1(rawList, del, idx+1, idel)                          !---   => TO THE NEXT DELIMITER
+  IF(idx == 0) THEN
+    lerr = .NOT.is_numeric(rawList(ibeg:)); RETURN                  !--- No separator detected: string must be a number
+  END IF
+  IF(is_numeric(rawList(ibeg:idx-1)))                 RETURN        !--- The input string tail is a valid number
+  IF(test(          INDEX('eE',rawList(idx-1:idx-1)) /= 0  &        !--- Sole possible exception: scientific notation: E+/-
+               .OR. INDEX('+-',del(idel)) /=0, lerr)) RETURN
+  idx = strIdx1(rawList, del, idx+1, idel)                          !---   => TO THE NEXT DELIMITER
+  IF(idx == 0) THEN
+    lerr = .NOT.is_numeric(rawList(ibeg:)); RETURN                  !--- No separator detected: string must be a number
+  END IF
+  lerr = .NOT.is_numeric(rawList(ibeg:idx-1))
 
 CONTAINS
@@ -446,4 +463,16 @@
 
 END FUNCTION strIdx_prv
+!==============================================================================================================================
+
+
+!==============================================================================================================================
+!=== Return the index of first appearance of "del" in "str" starting from index "ib"
+!==============================================================================================================================
+INTEGER FUNCTION strIndex(str, del, ib) RESULT(idx)
+  CHARACTER(LEN=*),  INTENT(IN)  :: str
+  CHARACTER(LEN=*),  INTENT(IN)  :: del
+  INTEGER,           INTENT(IN)  :: ib
+  idx  = INDEX( str(ib:LEN_TRIM(str)), del ) + ib -1
+END FUNCTION strIndex
 !==============================================================================================================================
 
@@ -484,10 +513,8 @@
   INTEGER,           INTENT(OUT) :: nb
   LOGICAL, OPTIONAL, INTENT(IN)  :: lSc
-
   INTEGER              :: ib, ie, jd, nr
   LOGICAL              :: ll
   CHARACTER(LEN=1024)  :: r
-
-  modname = 'strCount'
+!  modname = 'strCount'
   lerr = .FALSE.
   ll   = .FALSE.; IF(PRESENT(lSc)) ll = lSc
@@ -518,5 +545,5 @@
   INTEGER,                         OPTIONAL, INTENT(OUT) :: n
   LOGICAL :: ll
-  modname = 'strParse'
+!  modname = 'strParse'
   ll = .FALSE.; IF(PRESENT(lSc)) ll = lSc
   IF(.NOT.PRESENT(vals)) lerr = strParse_m(rawList, [delimiter], keys, ll)
@@ -527,9 +554,9 @@
 LOGICAL FUNCTION strParse_m(rawList, delimiter, keys, lSc, vals, n, id) RESULT(lerr)
   CHARACTER(LEN=*),                          INTENT(IN)  :: rawList, delimiter(:)
-  CHARACTER(LEN=256),           ALLOCATABLE, INTENT(OUT) :: keys(:)
+  CHARACTER(LEN=256),           ALLOCATABLE, INTENT(OUT) :: keys(:)  !--- Parsed keys vector
   LOGICAL,            OPTIONAL,              INTENT(IN)  :: lSc      !--- Take care about numbers in scientific notation
-  CHARACTER(LEN=256), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: vals(:)
-  INTEGER,            OPTIONAL,              INTENT(OUT) :: n
-  INTEGER,            OPTIONAL, ALLOCATABLE, INTENT(OUT) :: id(:)
+  CHARACTER(LEN=256), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: vals(:)  !--- Values for <name>=<value> keys
+  INTEGER,            OPTIONAL,              INTENT(OUT) :: n        !--- Length of the parsed vector
+  INTEGER,            OPTIONAL, ALLOCATABLE, INTENT(OUT) :: id(:)    !--- Indexes of the separators in "delimiter(:)" vector
 
   CHARACTER(LEN=1024) :: r
@@ -537,5 +564,5 @@
   LOGICAL :: ll
 
-  modname = 'strParse'
+!  modname = 'strParse'
   ll = .FALSE.; IF(PRESENT(lSc)) ll = lSc
   IF(test(fmsg(strCount_1m(rawList, delimiter, nk, ll), "Couldn't parse list: non-numerical strings were found"),lerr)) RETURN
@@ -813,5 +840,5 @@
   LOGICAL :: ls, li, lr
 
-  modname = 'dispTable'
+!  modname = 'dispTable'
   rFm = '*';    IF(PRESENT(rFmt)) rFm = rFmt               !--- Specified format for reals
   unt = lunout; IF(PRESENT(unit)) unt = unit               !--- Specified output unit
@@ -892,5 +919,5 @@
   LOGICAL :: ls, li, lr, la
 
-  modname = 'dispNamelist'
+!  modname = 'dispNamelist'
   rFm = '*';    IF(PRESENT(rFmt)) rFm = rFmt               !--- Specified format for reals
   ls = PRESENT(s); li = PRESENT(i); lr = PRESENT(r)
@@ -1077,14 +1104,14 @@
 !==============================================================================================================================
 LOGICAL FUNCTION reduceExpr_1(str, val) RESULT(out)
-  CHARACTER(LEN=*),   INTENT(IN)  :: str
-  CHARACTER(LEN=256), INTENT(OUT) :: val
+  CHARACTER(LEN=*),    INTENT(IN)  :: str
+  CHARACTER(LEN=256),  INTENT(OUT) :: val
+
+  CHARACTER(LEN=256)               :: v
   CHARACTER(LEN=1024)              :: s, vv
-  CHARACTER(LEN=256) :: v
-!  CHARACTER(LEN=:),    ALLOCATABLE :: v
   CHARACTER(LEN=1024), ALLOCATABLE :: vl(:)
   INTEGER,             ALLOCATABLE :: ip(:)
   INTEGER :: nl, nn, i, j, im, ix
   LOGICAL :: ll
-  modname = 'reduceExpr_1'
+!  modname = 'reduceExpr_1'
   s = str
 
@@ -1128,5 +1155,5 @@
 LOGICAL FUNCTION reduceExpr_basic(str, val) RESULT(out)
   CHARACTER(LEN=*),   INTENT(IN)  :: str
-  CHARACTER(LEN=256), INTENT(OUT) :: val
+  CHARACTER(LEN=*),   INTENT(OUT) :: val
   DOUBLE PRECISION,   ALLOCATABLE :: vl(:)
   INTEGER,            ALLOCATABLE :: id(:)
@@ -1139,11 +1166,7 @@
   LOGICAL :: ll
 
-  modname = 'reduceExpr_basic'
+!  modname = 'reduceExpr_basic'
   out = .TRUE.
-  print*,TRIM(str),is_numeric(str)
-!  val =''
-print*,"coincoin 1",len(str),len_trim(str)
-  IF(is_numeric(str)) THEN; val = TRIM(str); RETURN; END IF
-print*,"coincoin 2"
+  IF(is_numeric(str)) THEN; val=TRIM(str); RETURN; END IF
   op = ['^','/','*','+','-']                                                   !--- List of recognized operations
   s = str
@@ -1157,10 +1180,10 @@
       IF(id(i) /= io) CYCLE                                                    !--- Current found operator is not op(io)
       vm = vl(i); vp = vl(i+1)                                                 !--- Couple of values used for current operation
-      SELECT CASE(op(io))                                                      !--- Perform operation on the two values
-        CASE('^'); v = vm**vp
-        CASE('/'); v = vm/vp
-        CASE('*'); v = vm*vp
-        CASE('+'); v = vm+vp
-        CASE('-'); v = vm-vp
+      SELECT CASE(io)                                                          !--- Perform operation on the two values
+        CASE(1); v = vm**vp  !--- ^
+        CASE(2); v = vm/vp   !--- /
+        CASE(3); v = vm*vp   !--- *
+        CASE(4); v = vm+vp   !--- +
+        CASE(5); v = vm-vp   !--- +
       END SELECT
       IF(i == ni) THEN; vl = [vl(1:ni-1), v]; ELSE; vl = [vl(1:i-1), v, vl(i+2:ni+1)]; END IF
@@ -1175,9 +1198,10 @@
 !==============================================================================================================================
 FUNCTION reduceExpr_m(str, val) RESULT(out)
-  CHARACTER(LEN=*),    INTENT(IN)  :: str(:)
-  CHARACTER(LEN=256),  INTENT(OUT) :: val(SIZE(str))
-  LOGICAL                          :: out(SIZE(str))
+  LOGICAL,            ALLOCATABLE              :: out(:)
+  CHARACTER(LEN=*),                INTENT(IN)  :: str(:)
+  CHARACTER(LEN=256), ALLOCATABLE, INTENT(OUT) :: val(:)
   INTEGER :: i
-  out = [(reduceExpr_1(str(i), val(i)), i=1, SIZE(str))]
+  ALLOCATE(out(SIZE(str)),val(SIZE(str)))
+  out(:) = [(reduceExpr_1(str(i), val(i)), i=1, SIZE(str))]
 END FUNCTION reduceExpr_m
 !==============================================================================================================================
@@ -1194,5 +1218,6 @@
   WRITE(fmt,'("(f",i0,".0)")') LEN_TRIM(str)
   READ(str,fmt,IOSTAT=e) x
-  out = e==0
+  out = e==0 .AND. INDEX('Ee',str(LEN_TRIM(str):LEN_TRIM(str)))==0
+  IF(str == '') out = .FALSE.
 END FUNCTION is_numeric
 !==============================================================================================================================
@@ -1237,8 +1262,11 @@
 END FUNCTION bool2str
 !==============================================================================================================================
-ELEMENTAL CHARACTER(LEN=256) FUNCTION int2str(i) RESULT(out)
-  INTEGER, INTENT(IN) :: i
+ELEMENTAL CHARACTER(LEN=256) FUNCTION int2str(i, nDigits) RESULT(out)
+  INTEGER,           INTENT(IN) :: i
+  INTEGER, OPTIONAL, INTENT(IN) :: nDigits
   WRITE(out,*)i
   out = ADJUSTL(out)
+  IF(.NOT.PRESENT(nDigits)) RETURN
+  IF(nDigits > LEN_TRIM(out)) out = REPEAT('0', nDigits - LEN_TRIM(out))//TRIM(out)
 END FUNCTION int2str
 !==============================================================================================================================
