Index: LMDZ5/branches/testing/DefLists/config.def_IPSLCM5B_AGCM
===================================================================
--- LMDZ5/branches/testing/DefLists/config.def_IPSLCM5B_AGCM	(revision 1665)
+++ LMDZ5/branches/testing/DefLists/config.def_IPSLCM5B_AGCM	(revision 1665)
@@ -0,0 +1,130 @@
+##############################################################################
+# PARAMETRES ET CLES DE CONFIGURATION LMDZ
+##############################################################################
+# D: Valeur par default
+#
+# Controle des sorties
+#*********************
+#ok_regdyn : y/n calcul/non des regymes dynamiques sur regions pre-definies
+ok_regdyn=y
+phys_out_filekeys=       y       n       n       n       n
+phys_out_filenames=      histmth histday histhf  histins histLES
+phys_out_filelevels=     5      2       2       4       4
+phys_out_filetypes=      ave(X)  ave(X)  ave(X) inst(X) inst(X)
+phys_out_filetimesteps=  _ecrit-mth_   1day    6hr     3hr     6hr
+### parametres pour hist*NMC.nc
+#lev_histdayNMC: nombre de niveaux sur la verticale dans le fichier
+#                histdayNMC: 8 ou 17
+lev_histdayNMC=8
+### - ok_histNMC = y/n, y/n, y/n pour avoir les sorties NMC mensuelles, journalieres et haute frequence
+ok_histNMC = y, n, n
+#
+#Couplage avec autres modules
+#******************************
+#option de couplage pour ocean (D:force)
+##type_ocean=couple
+##version_ocean=nemo
+#avec ou sans orchidee (D:n)
+##VEGET=y
+#type_run=AMIP, ENSP, clim (D:AMIP)
+type_run=CLIM
+##  Soil Model  ou non               
+soil_model=y
+##  Cycle diurne  ou non                 
+cycle_diurne=y
+
+#Code de transfert radiatif
+#**************************
+# ajout de ce flag pour activer/desactiver le rayonnement (MPL)
+# 0 : pas de rayonnement. 1: on active le rayonnement (D=1)
+iflag_radia=1
+## Nombre appels des routines de rayonnements ( par jour)                 
+nbapp_rad=24
+
+# Parametres "orbitaux/ ere geologique"
+#######################################
+#Parametres orbitaux
+#excentricite
+R_ecc=0.016715
+#equinoxe
+R_peri=102.7
+#inclinaison
+R_incl=23.441
+#constante solaire
+solaire=1365.6537
+##  Facteur additif pour l albedo
+pmagic=0.00
+#
+# Taux gaz a effet de serre
+#######################################
+#concentration des gaz (co2 ch4   n2o  cfc11 cfc12)
+#                  (D: 348. 1650. 306.  280.  484.)
+co2_ppm=0.28472500E+03
+#RCO2=co2_ppm * 1.0e-06  * 44.011/28.97= 5.286789092164308E-04
+CH4_ppb=0.79097924E+03
+#RCH4=1.65E-06* 16.043/28.97= 9.137366240938903E-07
+N2O_ppb=0.27542506E+03
+#RN2O=306.E-09* 44.013/28.97= 4.648939592682085E-07
+CFC11_ppt=0.
+#RCFC11=280.E-12* 137.3686/28.97= 1.327690990680013E-09
+CFC12_ppt=0.
+#RCFC12=484.E-12* 120.9140/28.97= 2.020102726958923E-09
+#
+# Parametres effets directs/indirects des "aerosols"
+#######################################
+### ok_ade=y/n   flag Aerosol direct effect
+ok_ade=y
+### ok_aie=y/n   flag Aerosol indirect effect
+ok_aie=y
+### aer_type =   Aerosol variation type : actuel / preind / scenario / annuel
+aer_type=preind
+###  type of coupled aerosol =1 (default) =2 => bc  only =3 => pom only =4 => seasalt only =5 => dust only =6 => all aerosol
+flag_aerosol=6 
+### bl95_b0 =    Parameter in CDNC-maer link (Boucher&Lohmann 1995)
+bl95_b0=1.7
+### bl95_b1 =    Parameter in CDNC-maer link (Boucher&Lohmann 1995)
+bl95_b1=0.2
+#
+# Parametre de lecture de l'ozone
+#######################################
+# Allowed values are 0, 1 and 2
+# 0: do not read an ozone climatology
+# 1: read a single ozone climatology that will be used day and night
+# 2: read two ozone climatologies, the average day and night climatology and the daylight climatology
+read_climoz=2
+#
+# Parametres simulateur COSP (CFMIP Observational Simulator Package)
+#######################################
+### ok_cosp=y/n flag simulateur COSP
+ok_cosp=n
+### freq_COSP = frequence d'appel de COSP en secondes
+freq_COSP=10800.
+### ok_mensuelCOSP=y/n sortir fichier mensuel COSP histmthCOSP.nc, =n pas de fichier histmthCOSP.nc
+ok_mensuelCOSP=y
+### ok_journeCOSP=y/n sortir fichier journalier histdayCOSP.nc, =n pas de fichier histdayCOSP.nc
+ok_journeCOSP=y
+### ok_hfCOSP=y/n, ecrire sorties  haute frequence histhfCOSP.nc, =n pas de fichier histhfCOSP.nc
+ok_hfCOSP=n
+#
+# Parametres simulateur ISCCP
+#######################################
+### ok_isccp=y/n flag simulateur ISCCP
+ok_isccp=n
+### freqin_isccp = frequence input en secondes du simulateur ISCCP
+freq_ISCCP=10800.
+### top_height = flag choix calcul nuages par le simulateur en utilisant 
+# -              les donnees IR et/ou VIS et l algorithme ISCCP-D1
+# - top_height = 1 -> algo IR-VIS
+# - top_height = 2 -> identique a 1, mais "ptop(ibox)=pfull(ilev)"
+# - top_height = 3 -> algo IR
+top_height = 1
+### overlap =    Hypothese de Recouvrement (HR) utilisee pour le simulateur ISCCP
+# - overlap=1    Max overlap
+# - overlap=2    Random overlap
+# - overlap=3    Max/Random overlap
+overlap = 3
+#
+
+# Specifique aquaplanete
+########################
+#qsol0=100.
Index: LMDZ5/branches/testing/DefLists/physiq.def_L39_NPv3.0
===================================================================
--- LMDZ5/branches/testing/DefLists/physiq.def_L39_NPv3.0	(revision 1665)
+++ LMDZ5/branches/testing/DefLists/physiq.def_L39_NPv3.0	(revision 1665)
@@ -0,0 +1,123 @@
+##############################################################################
+# PARAMETRES ET CLES DE LA PHYSIQUE LMDZ
+##############################################################################
+# D: Valeur par default
+#
+#Parametres Orographiques et cdrags
+#**********************************
+##   Si=.T. ,  lecture du fichier limit avec la bonne annee 
+ok_limitvrai=n
+#Cdrags 
+f_cdrag_stable=1.
+f_cdrag_ter=1.
+f_cdrag_oce=0.7
+#cdmmax
+cdmmax=2.5E-3
+#cdhmax
+cdhmax=2.0E-3
+##  Orodr  ou  non   pour l orographie
+ok_orodr=y
+##  Orolf  ou  non   pour l orographie              
+ok_orolf=y
+#Rugoro
+f_rugoro=0.
+#
+# Rayonnement
+#*********************
+# activation du nouveau code de rayonnement RRTM
+# 0 : Ancien code et 1 : RRTM (D=0)
+iflag_rrtm=0
+#
+##  Activation ou non de la parametrisation de Hines pour la strato
+#******************************************************************
+ok_hines=y
+#
+# Parametres nuages
+#******************
+#seuils de la precipitation des nuages strateformes (D: 2.6e-4 2.6e-4)
+cld_lc_lsc=6.e-4
+cld_lc_con=6.e-4
+#constante de temps pour eleminer eau lsc et convective (D: 3600. 3600.)
+cld_tau_lsc=1800.
+cld_tau_con=1800.
+#facteurs correctifs sur la vitesse de chute des cristaux de glace (D: 1 1)
+ffallv_lsc=1.35
+ffallv_con=1.35
+#coefficient sur la reevaporation de la pluie (D: 2.e-5 n)
+coef_eva=1e-4
+reevap_ice=y
+#calcul des proprietes des nuages convectifs (D:1 0.375 1.e-4) 
+iflag_cldcon=6
+fact_cldcon=1.
+facttemps=0.
+#calcul eau condensee et fraction nuageuse a partir des PDF (D:0, 0:version avec ratqs sinon nouvelles PDFs)  
+iflag_pdf=1
+#calcul epaisseur optique et emmissivite des nuages (D: y 1 0.01 0.3)
+ok_newmicro=y
+iflag_ratqs=2
+ratqsbas=0.002
+ratqshaut=0.25
+#rayon effectif pour les nuages de glace (D:35)
+rad_froid=35
+#rayons effectifs pour les nuages eau liq (tailles des gouttes d eau nuageuse, D: 13 9)
+rad_chau1=12
+rad_chau2=11
+##  Choix ou non  de  New oliq               
+new_oliq=y
+#
+rei_min=20.
+rei_max=61.29
+#
+t_glace_min=258.
+t_glace_max=273.13
+#
+# Flags Convection 
+#*****************
+#flag  pour la convection (D:2, 1:LMD, 2:Tiedtke, 3:KE nouvelle physique, 30:KE IPCC)
+iflag_con=3
+#niveau de sorties des diagnos sur la conservation energie
+if_ebil=0
+#efficacite de precepitation maxim (D:.993)
+epmax=0.997
+#ajustement convectif sec au debut de la convection (D: n 0)
+ok_adj_ema=n
+iflag_clw=0
+#fermeture convective (D:1, 0:AR4, 2:ALE and ALP)
+iflag_clos=2
+#loi de melange a l entrainement  (D:1, 0:AR4=PDF plate, 1=PDF)
+iflag_mix=1
+#poids des PDFs plate et en cloche (D: 1 0)
+qqa1=1.
+qqa2=0.
+# Facteur multiplication des precip convectives dans KE
+cvl_corr=1.0
+#
+Fmax=0.65
+#
+# Flags Couche limite
+#********************
+#shema de CL des thermiques (D:0, 0:ajustement sec,=>1:versions thermiques) 
+iflag_thermals=15
+#pas de temps du spliting pour les thermiques
+nsplit_thermals=1
+tau_thermals=0.
+iflag_thermals_ed=10
+iflag_thermals_optflux=0
+#shema de la couche de surface (D:1, 1:LMD, 8:Mellor-Yamada) 
+iflag_pbl=8
+#diffusion turbulente
+ksta_ter=1.e-7
+ksta=1.e-10
+#ok_kzmin : calcul Kzmin dans la CL de surface
+ok_kzmin=y
+#couplage ou non avec la convection
+iflag_coupl=5 (0:AR4 et 1:nouvelle physique)
+seuil_inversion=-0.08
+#rendement sur la puissance fournie par les thermiques a la convection
+alp_bl_k=0.5
+#
+# Flags wakes
+#************
+#activation ou non des wakes (D:0, 0:AR4, 1:nouvelle physique) 
+iflag_wake=1
+alp_offset=0.
Index: LMDZ5/branches/testing/arch/arch-X64_CURIE.fcm
===================================================================
--- LMDZ5/branches/testing/arch/arch-X64_CURIE.fcm	(revision 1665)
+++ LMDZ5/branches/testing/arch/arch-X64_CURIE.fcm	(revision 1665)
@@ -0,0 +1,15 @@
+%COMPILER            mpif90
+%LINK                mpif90
+%AR                  ar
+%MAKE                gmake
+%FPP_FLAGS           -P -traditional
+%FPP_DEF             NC_DOUBLE BLAS SGEMV=DGEMV SGEMM=DGEMM FFT_MKL
+%BASE_FFLAGS         -i4 -r8 -auto -align all -I${MKLROOT}/include
+%PROD_FFLAGS         -O3
+%DEV_FFLAGS          -p -g -O2 -traceback -fp-stack-check -ftrapuv
+%DEBUG_FFLAGS        -p -g -traceback -fp-stack-check -ftrapuv
+%MPI_FFLAGS
+%OMP_FFLAGS          -openmp
+%BASE_LD             -i4 -r8 -auto $MKL_LIBS
+%MPI_LD
+%OMP_LD              -openmp
Index: LMDZ5/branches/testing/arch/arch-X64_CURIE.path
===================================================================
--- LMDZ5/branches/testing/arch/arch-X64_CURIE.path	(revision 1665)
+++ LMDZ5/branches/testing/arch/arch-X64_CURIE.path	(revision 1665)
@@ -0,0 +1,11 @@
+NETCDF_LIBDIR="-L$NETCDF_LIB_DIR -lnetcdff -lnetcdf"
+NETCDF_INCDIR=-I$NETCDF_INC_DIR
+IOIPSL_INCDIR=$LMDGCM/../../lib
+IOIPSL_LIBDIR=$LMDGCM/../../lib
+ORCH_INCDIR=$LMDGCM/../../lib
+ORCH_LIBDIR=$LMDGCM/../../lib
+OASIS_INCDIR=$LMDGCM/../../prism/X64/build/lib/psmile.$couple
+OASIS_LIBDIR=$LMDGCM/../../prism/X64/lib
+INCA_LIBDIR=$LMDGCM/../INCA3/config/lib
+INCA_INCDIR=$LMDGCM/../INCA3/config/lib
+
Index: LMDZ5/branches/testing/libf/bibio/initdynav.F
===================================================================
--- LMDZ5/branches/testing/libf/bibio/initdynav.F	(revision 1664)
+++ 	(revision )
@@ -1,200 +1,0 @@
-!
-! $Id$
-!
-      subroutine initdynav(day0,anne0,tstep,t_ops,t_wrt)
-
-#ifdef CPP_IOIPSL
-       USE IOIPSL
-#endif
-       USE infotrac, ONLY : nqtot, ttext
-      use com_io_dyn_mod, only : histaveid,histvaveid,histuaveid,       &
-     &        dynhistave_file,dynhistvave_file,dynhistuave_file
-      implicit none
-
-C
-C   Routine d'initialisation des ecritures des fichiers histoires LMDZ
-C   au format IOIPSL. Initialisation du fichier histoire moyenne.
-C
-C   Appels succesifs des routines: histbeg
-C                                  histhori
-C                                  histver
-C                                  histdef
-C                                  histend
-C
-C   Entree:
-C
-C      infile: nom du fichier histoire a creer
-C      day0,anne0: date de reference
-C      tstep : frequence d'ecriture
-C      t_ops: frequence de l'operation pour IOIPSL
-C      t_wrt: frequence d'ecriture sur le fichier
-C
-C
-C   L. Fairhead, LMD, 03/99
-C
-C =====================================================================
-C
-C   Declarations
-#include "dimensions.h"
-#include "paramet.h"
-#include "comconst.h"
-#include "comvert.h"
-#include "comgeom.h"
-#include "temps.h"
-#include "ener.h"
-#include "logic.h"
-#include "description.h"
-#include "serre.h"
-#include "iniprint.h"
-
-C   Arguments
-C
-      integer day0, anne0
-      real tstep, t_ops, t_wrt
-
-#ifdef CPP_IOIPSL
-! This routine needs IOIPSL to work
-C   Variables locales
-C
-      integer tau0
-      real zjulian
-      integer iq
-      real rlong(iip1,jjp1), rlat(iip1,jjp1)
-      integer uhoriid, vhoriid, thoriid, zvertiid
-      integer ii,jj
-      integer zan, dayref
-C
-C  Initialisations
-C
-      pi = 4. * atan (1.)
-C
-C  Appel a histbeg: creation du fichier netcdf et initialisations diverses
-C         
-
-      zan = anne0
-      dayref = day0
-      CALL ymds2ju(zan, 1, dayref, 0.0, zjulian)
-      tau0 = itau_dyn
-      
-      do jj = 1, jjp1
-        do ii = 1, iip1
-          rlong(ii,jj) = rlonv(ii) * 180. / pi
-          rlat(ii,jj)  = rlatu(jj) * 180. / pi
-        enddo
-      enddo
-       
-! Creation de 3 fichiers pour les differentes grilles horizontales
-! Restriction de IOIPSL: seulement 2 coordonnees dans le meme fichier
-! Grille Scalaire       
-      call histbeg(dynhistave_file, iip1, rlong(:,1), jjp1, rlat(1,:),
-     .             1, iip1, 1, jjp1,
-     .             tau0, zjulian, tstep, thoriid,histaveid)
-
-C  Creation du fichier histoire pour les grilles en V et U (oblige pour l'instant,
-C  IOIPSL ne permet pas de grilles avec des nombres de point differents dans
-C  un meme fichier)
-! Grille V
-      do jj = 1, jjm
-        do ii = 1, iip1
-          rlong(ii,jj) = rlonv(ii) * 180. / pi
-          rlat(ii,jj) = rlatv(jj) * 180. / pi
-        enddo
-      enddo
-
-      call histbeg(dynhistvave_file, iip1, rlong(:,1), jjm, rlat(1,:),
-     .             1, iip1, 1, jjm,
-     .             tau0, zjulian, tstep, vhoriid,histvaveid)
-! Grille U
-      do jj = 1, jjp1
-        do ii = 1, iip1
-          rlong(ii,jj) = rlonu(ii) * 180. / pi
-          rlat(ii,jj) = rlatu(jj) * 180. / pi
-        enddo
-      enddo
-
-      call histbeg(dynhistuave_file, iip1, rlong(:,1),jjp1, rlat(1,:),
-     .             1, iip1, 1, jjp1,
-     .             tau0, zjulian, tstep, uhoriid,histuaveid)
-C
-C  Appel a histvert pour la grille verticale
-C
-      call histvert(histaveid,'presnivs','Niveaux Pression
-     &     approximatifs','mb',llm, presnivs/100., zvertiid,'down')
-      call histvert(histuaveid,'presnivs','Niveaux Pression
-     &     approximatifs','mb',llm, presnivs/100., zvertiid,'down')
-      call histvert(histvaveid,'presnivs','Niveaux Pression
-     &     approximatifs','mb',llm, presnivs/100., zvertiid,'down')
-C
-C  Appels a histdef pour la definition des variables a sauvegarder
-C
-C  Vents U
-C
-!      write(6,*)'inithistave',tstep
-      call histdef(histuaveid, 'u', 'vent u moyen ',
-     .             'm/s', iip1, jjp1, uhoriid, llm, 1, llm, zvertiid,
-     .             32, 'ave(X)', t_ops, t_wrt)
-
-C  Vents V
-C
-      call histdef(histvaveid, 'v', 'vent v moyen',
-     .             'm/s', iip1, jjm, vhoriid, llm, 1, llm, zvertiid,
-     .             32, 'ave(X)', t_ops, t_wrt)
-
-C
-C  Temperature
-C
-      call histdef(histaveid, 'temp', 'temperature moyenne', 'K',
-     .             iip1, jjp1, thoriid, llm, 1, llm, zvertiid,
-     .             32, 'ave(X)', t_ops, t_wrt)
-C
-C  Temperature potentielle
-C
-      call histdef(histaveid, 'theta', 'temperature potentielle', 'K',
-     .             iip1, jjp1, thoriid, llm, 1, llm, zvertiid,
-     .             32, 'ave(X)', t_ops, t_wrt)
-C
-C  Geopotentiel
-C
-      call histdef(histaveid, 'phi', 'geopotentiel moyen', '-',
-     .             iip1, jjp1, thoriid, llm, 1, llm, zvertiid,
-     .             32, 'ave(X)', t_ops, t_wrt)
-C
-C  Traceurs
-C
-!        DO iq=1,nqtot
-!          call histdef(histaveid, ttext(iq), ttext(iq), '-',
-!     .             iip1, jjp1, thoriid, llm, 1, llm, zvertiid,
-!     .             32, 'ave(X)', t_ops, t_wrt)
-!        enddo
-C
-C  Masse
-C
-      call histdef(histaveid, 'masse', 'masse', 'kg',
-     .             iip1, jjp1, thoriid, llm, 1, llm, zvertiid,
-     .             32, 'ave(X)', t_ops, t_wrt)
-C
-C  Pression au sol
-C
-      call histdef(histaveid, 'ps', 'pression naturelle au sol', 'Pa',
-     .             iip1, jjp1, thoriid, 1, 1, 1, -99,
-     .             32, 'ave(X)', t_ops, t_wrt)
-C
-C  Geopotentiel au sol
-C
-!      call histdef(histaveid, 'phis', 'geopotentiel au sol', '-',
-!     .             iip1, jjp1, thoriid, 1, 1, 1, -99,
-!     .             32, 'ave(X)', t_ops, t_wrt)
-!C
-C  Fin
-C
-      call histend(histaveid)
-      call histend(histuaveid)
-      call histend(histvaveid)
-#else
-! tell the user this routine should be run with ioipsl
-      write(lunout,*)"initdynav: Warning this routine should not be",
-     &               " used without ioipsl"
-#endif
-! of #ifdef CPP_IOIPSL
-      return
-      end
Index: LMDZ5/branches/testing/libf/bibio/initdynav.F90
===================================================================
--- LMDZ5/branches/testing/libf/bibio/initdynav.F90	(revision 1665)
+++ LMDZ5/branches/testing/libf/bibio/initdynav.F90	(revision 1665)
@@ -0,0 +1,194 @@
+! $Id$
+
+subroutine initdynav(day0,anne0,tstep,t_ops,t_wrt)
+
+#ifdef CPP_IOIPSL
+  USE IOIPSL
+#endif
+  USE infotrac, ONLY : nqtot, ttext
+  use com_io_dyn_mod, only : histaveid,histvaveid,histuaveid, &
+       dynhistave_file,dynhistvave_file,dynhistuave_file
+  implicit none
+
+
+  !   Routine d'initialisation des ecritures des fichiers histoires LMDZ
+  !   au format IOIPSL. Initialisation du fichier histoire moyenne.
+
+  !   Appels succesifs des routines: histbeg
+  !                                  histhori
+  !                                  histver
+  !                                  histdef
+  !                                  histend
+
+  !   Entree:
+
+  !      infile: nom du fichier histoire a creer
+  !      day0,anne0: date de reference
+  !      tstep : frequence d'ecriture
+  !      t_ops: frequence de l'operation pour IOIPSL
+  !      t_wrt: frequence d'ecriture sur le fichier
+
+
+  !   L. Fairhead, LMD, 03/99
+
+  include "dimensions.h"
+  include "paramet.h"
+  include "comconst.h"
+  include "comvert.h"
+  include "comgeom.h"
+  include "temps.h"
+  include "ener.h"
+  include "logic.h"
+  include "description.h"
+  include "serre.h"
+  include "iniprint.h"
+
+  !   Arguments
+
+  integer day0, anne0
+  real tstep, t_ops, t_wrt
+
+#ifdef CPP_IOIPSL
+  ! This routine needs IOIPSL to work
+  !   Variables locales
+
+  integer tau0
+  real zjulian
+  integer iq
+  real rlong(iip1,jjp1), rlat(iip1,jjp1)
+  integer uhoriid, vhoriid, thoriid, zvertiid
+  integer ii,jj
+  integer zan, dayref
+
+  !--------------------------------------------------------------------
+
+  !  Initialisations
+
+  pi = 4. * atan (1.)
+
+  !  Appel a histbeg: creation du fichier netcdf et initialisations diverses
+
+
+  zan = anne0
+  dayref = day0
+  CALL ymds2ju(zan, 1, dayref, 0.0, zjulian)
+  tau0 = itau_dyn
+
+  do jj = 1, jjp1
+     do ii = 1, iip1
+        rlong(ii,jj) = rlonv(ii) * 180. / pi
+        rlat(ii,jj)  = rlatu(jj) * 180. / pi
+     enddo
+  enddo
+
+  ! Creation de 3 fichiers pour les differentes grilles horizontales
+  ! Restriction de IOIPSL: seulement 2 coordonnees dans le meme fichier
+  ! Grille Scalaire       
+  call histbeg(dynhistave_file, iip1, rlong(:,1), jjp1, rlat(1,:), &
+       1, iip1, 1, jjp1, &
+       tau0, zjulian, tstep, thoriid,histaveid)
+
+  ! Creation du fichier histoire pour les grilles en V et U (oblige
+  ! pour l'instant, IOIPSL ne permet pas de grilles avec des nombres
+  ! de point differents dans  un meme fichier)
+  ! Grille V
+  do jj = 1, jjm
+     do ii = 1, iip1
+        rlong(ii,jj) = rlonv(ii) * 180. / pi
+        rlat(ii,jj) = rlatv(jj) * 180. / pi
+     enddo
+  enddo
+
+  call histbeg(dynhistvave_file, iip1, rlong(:,1), jjm, rlat(1,:), &
+       1, iip1, 1, jjm, &
+       tau0, zjulian, tstep, vhoriid,histvaveid)
+  ! Grille U
+  do jj = 1, jjp1
+     do ii = 1, iip1
+        rlong(ii,jj) = rlonu(ii) * 180. / pi
+        rlat(ii,jj) = rlatu(jj) * 180. / pi
+     enddo
+  enddo
+
+  call histbeg(dynhistuave_file, iip1, rlong(:,1),jjp1, rlat(1,:), &
+       1, iip1, 1, jjp1, &
+       tau0, zjulian, tstep, uhoriid,histuaveid)
+
+  !  Appel a histvert pour la grille verticale
+
+  call histvert(histaveid,'presnivs','Niveaux Pression approximatifs','mb', &
+       llm, presnivs/100., zvertiid,'down')
+  call histvert(histuaveid,'presnivs','Niveaux Pression approximatifs','mb', &
+       llm, presnivs/100., zvertiid,'down')
+  call histvert(histvaveid,'presnivs','Niveaux Pression approximatifs','mb', &
+       llm, presnivs/100., zvertiid,'down')
+
+  !  Appels a histdef pour la definition des variables a sauvegarder
+
+  !  Vents U
+
+  call histdef(histuaveid, 'u', 'vent u moyen ', &
+       'm/s', iip1, jjp1, uhoriid, llm, 1, llm, zvertiid, &
+       32, 'ave(X)', t_ops, t_wrt)
+
+  !  Vents V
+
+  call histdef(histvaveid, 'v', 'vent v moyen', &
+       'm/s', iip1, jjm, vhoriid, llm, 1, llm, zvertiid, &
+       32, 'ave(X)', t_ops, t_wrt)
+
+
+  !  Temperature
+
+  call histdef(histaveid, 'temp', 'temperature moyenne', 'K', &
+       iip1, jjp1, thoriid, llm, 1, llm, zvertiid, &
+       32, 'ave(X)', t_ops, t_wrt)
+
+  !  Temperature potentielle
+
+  call histdef(histaveid, 'theta', 'temperature potentielle', 'K', &
+       iip1, jjp1, thoriid, llm, 1, llm, zvertiid, &
+       32, 'ave(X)', t_ops, t_wrt)
+
+  !  Geopotentiel
+
+  call histdef(histaveid, 'phi', 'geopotentiel moyen', '-', &
+       iip1, jjp1, thoriid, llm, 1, llm, zvertiid, &
+       32, 'ave(X)', t_ops, t_wrt)
+
+  !  Traceurs
+
+  !        DO iq=1,nqtot
+  !          call histdef(histaveid, ttext(iq), ttext(iq), '-', &
+  !                  iip1, jjp1, thoriid, llm, 1, llm, zvertiid, &
+  !                  32, 'ave(X)', t_ops, t_wrt)
+  !        enddo
+
+  !  Masse
+
+  call histdef(histaveid, 'masse', 'masse', 'kg', &
+       iip1, jjp1, thoriid, llm, 1, llm, zvertiid, &
+       32, 'ave(X)', t_ops, t_wrt)
+
+  !  Pression au sol
+
+  call histdef(histaveid, 'ps', 'pression naturelle au sol', 'Pa', &
+       iip1, jjp1, thoriid, 1, 1, 1, -99, &
+       32, 'ave(X)', t_ops, t_wrt)
+
+  !  Geopotentiel au sol
+
+  !      call histdef(histaveid, 'phis', 'geopotentiel au sol', '-', &
+  !                  iip1, jjp1, thoriid, 1, 1, 1, -99, &
+  !                  32, 'ave(X)', t_ops, t_wrt)
+
+  call histend(histaveid)
+  call histend(histuaveid)
+  call histend(histvaveid)
+#else
+  write(lunout,*)"initdynav: Warning this routine should not be", &
+       " used without ioipsl"
+#endif
+  ! of #ifdef CPP_IOIPSL
+
+end subroutine initdynav
Index: LMDZ5/branches/testing/libf/bibio/lnblnk.F
===================================================================
--- LMDZ5/branches/testing/libf/bibio/lnblnk.F	(revision 1664)
+++ 	(revision )
@@ -1,39 +1,0 @@
-!
-! $Header$
-!
-      INTEGER FUNCTION lnblnk (letter)
-
-C--------------------------------------------------------
-C Fonction qui determine la longeur d'un string sans les
-C blancs qui suivent. Le critere pour determiner la fin du
-C string est, trois blancs de suite
-C---------------------------------------------------------
-C     ARGUMENTS
-C     +++++++++
-C     letter: CHARACTER*xxx (xxx < imax)
-C             le string dont on determine la longuer
-C     lnblnk: INTEGER
-C             le nombre de characteres
-C
-C     PARAMETER
-C     +++++++++
-C     imax : INTEGER
-C            le nombre maximale de character que peut contenir le string
-C            a traiter
-
-      IMPLICIT NONE
-      INTEGER i,imax
-      PARAMETER (imax = 256)
-      CHARACTER(*) letter
-
-      i=0
-
-10    i=i+1
-      IF (letter(i:i+3) . EQ . '   ') GOTO 20
-      GOTO 10
-
-20    lnblnk=i-1
-
-      RETURN
-      END
-
Index: LMDZ5/branches/testing/libf/bibio/new_unit.F90
===================================================================
--- LMDZ5/branches/testing/libf/bibio/new_unit.F90	(revision 1665)
+++ LMDZ5/branches/testing/libf/bibio/new_unit.F90	(revision 1665)
@@ -0,0 +1,25 @@
+module new_unit_m
+
+  implicit none
+
+contains
+
+  subroutine new_unit(unit)
+
+    integer, intent(out):: unit
+
+    ! Variables local to the procedure:
+    logical opened, exist
+
+    !------------------------------------------------------
+
+    unit = 0
+    do
+       inquire(unit=unit, opened=opened, exist=exist)
+       if (exist .and. .not. opened) exit
+       unit = unit + 1
+    end do
+
+  end subroutine new_unit
+
+end module new_unit_m
Index: LMDZ5/branches/testing/libf/bibio/writedynav.F
===================================================================
--- LMDZ5/branches/testing/libf/bibio/writedynav.F	(revision 1664)
+++ 	(revision )
@@ -1,152 +1,0 @@
-!
-! $Id$
-!
-      subroutine writedynav(time, vcov, 
-     ,                ucov,teta,ppk,phi,q,masse,ps,phis)
-
-#ifdef CPP_IOIPSL
-      USE ioipsl
-#endif
-      USE infotrac, ONLY : nqtot, ttext
-      use com_io_dyn_mod, only : histaveid,histvaveid,histuaveid
-      implicit none
-
-C
-C   Ecriture du fichier histoire au format IOIPSL
-C
-C   Appels succesifs des routines: histwrite
-C
-C   Entree:
-C      time: temps de l'ecriture
-C      vcov: vents v covariants
-C      ucov: vents u covariants
-C      teta: temperature potentielle
-C      phi : geopotentiel instantane
-C      q   : traceurs
-C      masse: masse
-C      ps   :pression au sol
-C      phis : geopotentiel au sol
-C      
-C
-C
-C   L. Fairhead, LMD, 03/99
-C
-C =====================================================================
-C
-C   Declarations
-#include "dimensions.h"
-#include "paramet.h"
-#include "comconst.h"
-#include "comvert.h"
-#include "comgeom.h"
-#include "temps.h"
-#include "ener.h"
-#include "logic.h"
-#include "description.h"
-#include "serre.h"
-#include "iniprint.h"
-
-C
-C   Arguments
-C
-
-      REAL vcov(ip1jm,llm),ucov(ip1jmp1,llm) 
-      REAL teta(ip1jmp1*llm),phi(ip1jmp1,llm),ppk(ip1jmp1*llm)     
-      REAL ps(ip1jmp1),masse(ip1jmp1,llm)                   
-      REAL phis(ip1jmp1)                  
-      REAL q(ip1jmp1,llm,nqtot)
-      integer time
-
-
-#ifdef CPP_IOIPSL
-! This routine needs IOIPSL to work
-C   Variables locales
-C
-      integer ndex2d(ip1jmp1),ndexu(ip1jmp1*llm),ndexv(ip1jm*llm)
-      INTEGER iq, ii, ll
-      real tm(ip1jmp1*llm)
-      REAL vnat(ip1jm,llm),unat(ip1jmp1,llm) 
-      logical ok_sync
-      integer itau_w
-C
-C  Initialisations
-C
-      ndexu = 0
-      ndexv = 0
-      ndex2d = 0
-      ok_sync = .TRUE.
-      tm = 999.999
-      vnat = 999.999
-      unat = 999.999
-      itau_w = itau_dyn + time
-
-C Passage aux composantes naturelles du vent
-      call covnat(llm, ucov, vcov, unat, vnat)
-
-C
-C  Appels a histwrite pour l'ecriture des variables a sauvegarder
-C
-C  Vents U 
-C
-      call histwrite(histuaveid, 'u', itau_w, unat, 
-     .               iip1*jjp1*llm, ndexu)
-C
-C  Vents V
-C
-      call histwrite(histvaveid, 'v', itau_w, vnat, 
-     .               iip1*jjm*llm, ndexv)
-C
-C  Temperature potentielle moyennee
-C
-      call histwrite(histaveid, 'theta', itau_w, teta, 
-     .                iip1*jjp1*llm, ndexu)
-C
-C  Temperature moyennee
-C
-      do ii = 1, ijp1llm
-        tm(ii) = teta(ii) * ppk(ii)/cpp
-      enddo
-      call histwrite(histaveid, 'temp', itau_w, tm, 
-     .                iip1*jjp1*llm, ndexu)
-C
-C  Geopotentiel
-C
-      call histwrite(histaveid, 'phi', itau_w, phi, 
-     .                iip1*jjp1*llm, ndexu)
-C
-C  Traceurs
-C
-!        DO iq=1,nqtot
-!          call histwrite(histaveid, ttext(iq), itau_w, q(:,:,iq), 
-!     .                   iip1*jjp1*llm, ndexu)
-!        enddo
-C
-C  Masse
-C
-       call histwrite(histaveid, 'masse', itau_w, masse, 
-     $                   iip1*jjp1*llm, ndexu)
-C
-C  Pression au sol
-C
-       call histwrite(histaveid, 'ps', itau_w, ps, iip1*jjp1, ndex2d)
-C
-C  Geopotentiel au sol
-C
-!       call histwrite(histaveid,'phis',itau_w, phis,iip1*jjp1, ndex2d)
-C
-C  Fin
-C
-      if (ok_sync) then
-          call histsync(histaveid)
-          call histsync(histvaveid)
-          call histsync(histuaveid)
-      ENDIF
-
-#else
-! tell the user this routine should be run with ioipsl
-      write(lunout,*)"writedynav: Warning this routine should not be",
-     &               " used without ioipsl"
-#endif
-! of #ifdef CPP_IOIPSL
-      return
-      end
Index: LMDZ5/branches/testing/libf/bibio/writedynav.F90
===================================================================
--- LMDZ5/branches/testing/libf/bibio/writedynav.F90	(revision 1665)
+++ LMDZ5/branches/testing/libf/bibio/writedynav.F90	(revision 1665)
@@ -0,0 +1,141 @@
+! $Id$
+
+subroutine writedynav(time, vcov, ucov, teta, ppk, phi, q, masse, ps, phis)
+
+#ifdef CPP_IOIPSL
+  USE ioipsl
+#endif
+  USE infotrac, ONLY : nqtot, ttext
+  use com_io_dyn_mod, only : histaveid, histvaveid, histuaveid
+
+  implicit none
+
+  !   Ecriture du fichier histoire au format IOIPSL
+
+  !   Appels succesifs des routines: histwrite
+
+  !   Entree:
+  !      time: temps de l'ecriture
+  !      vcov: vents v covariants
+  !      ucov: vents u covariants
+  !      teta: temperature potentielle
+  !      phi : geopotentiel instantane
+  !      q   : traceurs
+  !      masse: masse
+  !      ps   :pression au sol
+  !      phis : geopotentiel au sol
+
+  !   L. Fairhead, LMD, 03/99
+
+  !   Declarations
+  include "dimensions.h"
+  include "paramet.h"
+  include "comconst.h"
+  include "comvert.h"
+  include "comgeom.h"
+  include "temps.h"
+  include "ener.h"
+  include "logic.h"
+  include "description.h"
+  include "serre.h"
+  include "iniprint.h"
+
+  !   Arguments
+
+  REAL vcov(ip1jm, llm), ucov(ip1jmp1, llm) 
+  REAL teta(ip1jmp1*llm), phi(ip1jmp1, llm), ppk(ip1jmp1*llm)     
+  REAL ps(ip1jmp1), masse(ip1jmp1, llm)                   
+  REAL phis(ip1jmp1)                  
+  REAL q(ip1jmp1, llm, nqtot)
+  integer time
+
+#ifdef CPP_IOIPSL
+  ! This routine needs IOIPSL to work
+  !   Variables locales
+
+  integer ndex2d(ip1jmp1), ndexu(ip1jmp1*llm), ndexv(ip1jm*llm)
+  INTEGER iq, ii, ll
+  real tm(ip1jmp1*llm)
+  REAL vnat(ip1jm, llm), unat(ip1jmp1, llm) 
+  logical ok_sync
+  integer itau_w
+
+  !-----------------------------------------------------------------
+
+  !  Initialisations
+
+  ndexu = 0
+  ndexv = 0
+  ndex2d = 0
+  ok_sync = .TRUE.
+  tm = 999.999
+  vnat = 999.999
+  unat = 999.999
+  itau_w = itau_dyn + time
+
+  ! Passage aux composantes naturelles du vent
+  call covnat(llm, ucov, vcov, unat, vnat)
+
+  !  Appels a histwrite pour l'ecriture des variables a sauvegarder
+
+  !  Vents U 
+
+  call histwrite(histuaveid, 'u', itau_w, unat,  &
+       iip1*jjp1*llm, ndexu)
+
+  !  Vents V
+
+  call histwrite(histvaveid, 'v', itau_w, vnat,  &
+       iip1*jjm*llm, ndexv)
+
+  !  Temperature potentielle moyennee
+
+  call histwrite(histaveid, 'theta', itau_w, teta,  &
+       iip1*jjp1*llm, ndexu)
+
+  !  Temperature moyennee
+
+  do ii = 1, ijp1llm
+     tm(ii) = teta(ii) * ppk(ii)/cpp
+  enddo
+  call histwrite(histaveid, 'temp', itau_w, tm,  &
+       iip1*jjp1*llm, ndexu)
+
+  !  Geopotentiel
+
+  call histwrite(histaveid, 'phi', itau_w, phi,  &
+       iip1*jjp1*llm, ndexu)
+
+  !  Traceurs
+
+  !  DO iq=1, nqtot
+  !       call histwrite(histaveid, ttext(iq), itau_w, q(:, :, iq), &
+  !                   iip1*jjp1*llm, ndexu)
+  ! enddo
+
+  !  Masse
+
+  call histwrite(histaveid, 'masse', itau_w, masse,  &
+       iip1*jjp1*llm, ndexu)
+
+  !  Pression au sol
+
+  call histwrite(histaveid, 'ps', itau_w, ps, iip1*jjp1, ndex2d)
+
+  ! Geopotentiel au sol
+
+  ! call histwrite(histaveid, 'phis', itau_w, phis, iip1*jjp1, ndex2d)
+
+  if (ok_sync) then
+     call histsync(histaveid)
+     call histsync(histvaveid)
+     call histsync(histuaveid)
+  ENDIF
+
+#else
+  write(lunout, *) "writedynav: Warning this routine should not be", &
+       " used without ioipsl"
+#endif
+  ! of #ifdef CPP_IOIPSL
+
+end subroutine writedynav
Index: LMDZ5/branches/testing/libf/dyn3d/calfis.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/calfis.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3d/calfis.F	(revision 1665)
@@ -165,5 +165,5 @@
       PARAMETER(ntetaSTD=3)
       REAL rtetaSTD(ntetaSTD)
-      DATA rtetaSTD/350., 380., 405./
+      DATA rtetaSTD/350., 380., 405./ ! Earth-specific values, beware !!
       REAL PVteta(ngridmx,ntetaSTD)
 c
@@ -434,5 +434,6 @@
 c
       if (planet_type=="earth") then
-#ifdef CPP_EARTH
+#ifdef CPP_PHYS
+! PVtheta calls tetalevel, which is in the physics
 cIM calcul PV a teta=350, 380, 405K
       CALL PVtheta(ngridmx,llm,pucov,pvcov,pteta,
@@ -450,6 +451,4 @@
 
 
-      if (planet_type=="earth") then
-#ifdef CPP_EARTH
 
 !      write(lunout,*) 'PHYSIQUE AVEC NSPLIT_PHYS=',nsplit_phys
@@ -460,5 +459,8 @@
       zdqfic(:,:,:)=0.
 
-      do isplit=1,nsplit_phys
+      if (planet_type=="earth") then
+#ifdef CPP_PHYS
+
+       do isplit=1,nsplit_phys
 
          jH_cur_split=jH_cur+(isplit-1) * dtvr / (daysec *nsplit_phys)
@@ -503,5 +505,10 @@
          zdqfic(:,:,:)=zdqfic(:,:,:)+zdqfi(:,:,:)
 
-      enddo
+       enddo ! of do isplit=1,nsplit_phys
+
+#endif
+! of #ifdef CPP_PHYS
+      endif ! of if (planet_type=="earth")
+
       zdufi(:,:)=zdufic(:,:)/nsplit_phys
       zdvfi(:,:)=zdvfic(:,:)/nsplit_phys
@@ -509,6 +516,4 @@
       zdqfi(:,:,:)=zdqfic(:,:,:)/nsplit_phys
 
-#endif
-      endif !of if (planet_type=="earth")
 
 500   CONTINUE
Index: LMDZ5/branches/testing/libf/dyn3d/ce0l.F90
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/ce0l.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3d/ce0l.F90	(revision 1665)
@@ -28,4 +28,5 @@
   IMPLICIT NONE
 #ifndef CPP_EARTH
+#include "iniprint.h"
   WRITE(lunout,*)'limit_netcdf: Earth-specific routine, needs Earth physics'
 #else
Index: LMDZ5/branches/testing/libf/dyn3d/comvert.h
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/comvert.h	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3d/comvert.h	(revision 1665)
@@ -9,5 +9,5 @@
      &               aps(llm),bps(llm),scaleheight
 
-      common/comverti/disvert_type
+      common/comverti/disvert_type, pressure_exner
 
       real ap     ! hybrid pressure contribution at interlayers
@@ -30,3 +30,7 @@
                            !     using 'z2sig.def' (or 'esasig.def) file
 
+      logical pressure_exner
+!     compute pressure inside layers using Exner function, else use mean
+!     of pressure values at interfaces
+
  !-----------------------------------------------------------------------
Index: LMDZ5/branches/testing/libf/dyn3d/conf_gcm.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/conf_gcm.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3d/conf_gcm.F	(revision 1665)
@@ -155,4 +155,12 @@
       nday = 10
       CALL getin('nday',nday)
+
+!Config  Key  = starttime
+!Config  Desc = Heure de depart de la simulation
+!Config  Def  = 0
+!Config  Help = Heure de depart de la simulation
+!Config         en jour
+      starttime = 0
+      CALL getin('starttime',starttime)
 
 !Config  Key  = day_step
Index: LMDZ5/branches/testing/libf/dyn3d/control_mod.F90
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/control_mod.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3d/control_mod.F90	(revision 1665)
@@ -10,5 +10,5 @@
   IMPLICIT NONE
 
-  REAL    :: periodav
+  REAL    :: periodav, starttime
   INTEGER :: nday,day_step,iperiod,iapp_tracvl,nsplit_phys
   INTEGER :: iconser,iecri,dissip_period,iphysiq,iecrimoy
Index: LMDZ5/branches/testing/libf/dyn3d/disvert.F90
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/disvert.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3d/disvert.F90	(revision 1665)
@@ -4,4 +4,7 @@
 
   ! Auteur : P. Le Van
+
+  use new_unit_m, only: new_unit
+  use ioipsl, only: getin
 
   IMPLICIT NONE
@@ -26,20 +29,28 @@
   real zk, zkm1, dzk1, dzk2, k0, k1
 
-  INTEGER l
+  INTEGER l, unit
   REAL dsigmin
   REAL alpha, beta, deltaz
-  INTEGER iostat
   REAL x
   character(len=*),parameter :: modname="disvert"
 
+  character(len=6):: vert_sampling
+  ! (allowed values are "param", "tropo", "strato" and "read")
+
   !-----------------------------------------------------------------------
+
+  print *, "Call sequence information: disvert"
 
   ! default scaleheight is 8km for earth
   scaleheight=8.
 
-  OPEN(99, file='sigma.def', status='old', form='formatted', iostat=iostat)
+  vert_sampling = merge("strato", "tropo ", ok_strato) ! default value
+  call getin('vert_sampling', vert_sampling)
+  print *, 'vert_sampling = ' // vert_sampling
 
-  IF (iostat == 0) THEN
-     ! cas 1 on lit les options dans sigma.def:
+  select case (vert_sampling)
+  case ("param")
+     ! On lit les options dans sigma.def:
+     OPEN(99, file='sigma.def', status='old', form='formatted')
      READ(99, *) scaleheight ! hauteur d'echelle 8.
      READ(99, *) deltaz ! epaiseur de la premiere couche 0.04
@@ -68,32 +79,8 @@
 
      sig(llm+1)=0.
-
-     DO l = 1, llm
-        dsig(l) = sig(l)-sig(l+1)
-     end DO
-  ELSE
-     if (ok_strato) then
-        if (llm==39) then
-           dsigmin=0.3
-        else if (llm==50) then
-           dsigmin=1.
-        else
-           write(lunout,*) trim(modname), &
-           ' ATTENTION discretisation z a ajuster'
-           dsigmin=1.
-        endif
-        write(lunout,*) trim(modname), &
-        ' Discretisation verticale DSIGMIN=',dsigmin
-     endif
-
+  case("tropo")
      DO l = 1, llm
         x = 2*asin(1.) * (l - 0.5) / (llm + 1)
-
-        IF (ok_strato) THEN
-           dsig(l) =(dsigmin + 7. * SIN(x)**2) &
-                *(0.5*(1.-tanh(1.*(x-asin(1.))/asin(1.))))**2
-        ELSE
-           dsig(l) = 1.0 + 7.0 * SIN(x)**2
-        ENDIF
+        dsig(l) = 1.0 + 7.0 * SIN(x)**2
      ENDDO
      dsig = dsig / sum(dsig)
@@ -102,5 +89,37 @@
         sig(l) = sig(l+1) + dsig(l)
      ENDDO
-  ENDIF
+  case("strato")
+     if (llm==39) then
+        dsigmin=0.3
+     else if (llm==50) then
+        dsigmin=1.
+     else
+        write(lunout,*) trim(modname), ' ATTENTION discretisation z a ajuster'
+        dsigmin=1.
+     endif
+     WRITE(LUNOUT,*) trim(modname), 'Discretisation verticale DSIGMIN=',dsigmin
+
+     DO l = 1, llm
+        x = 2*asin(1.) * (l - 0.5) / (llm + 1)
+        dsig(l) =(dsigmin + 7. * SIN(x)**2) &
+             *(0.5*(1.-tanh(1.*(x-asin(1.))/asin(1.))))**2
+     ENDDO
+     dsig = dsig / sum(dsig)
+     sig(llm+1) = 0.
+     DO l = llm, 1, -1
+        sig(l) = sig(l+1) + dsig(l)
+     ENDDO
+  case("read")
+     call new_unit(unit)
+     open(unit, file="hybrid.txt", status="old", action="read", &
+          position="rewind")
+     read(unit, fmt=*) ! skip title line
+     do l = 1, llm + 1
+        read(unit, fmt=*) sig(l)
+     end do
+     close(unit)
+  case default
+     call abort_gcm("disvert", 'Wrong value for "vert_sampling"', 1)
+  END select
 
   DO l=1, llm
Index: LMDZ5/branches/testing/libf/dyn3d/dynetat0.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/dynetat0.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3d/dynetat0.F	(revision 1665)
@@ -119,4 +119,5 @@
       day_ini = tab_cntrl(30)
       itau_dyn = tab_cntrl(31)
+      start_time = tab_cntrl(32)
 c   .................................................................
 c
Index: LMDZ5/branches/testing/libf/dyn3d/dynredem.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/dynredem.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3d/dynredem.F	(revision 1665)
@@ -120,4 +120,6 @@
        tab_cntrl(30) = REAL(iday_end)
        tab_cntrl(31) = REAL(itau_dyn + itaufin)
+c start_time: start_time of simulation (not necessarily 0.)
+       tab_cntrl(32) = start_time
 c
 c    .........................................................
Index: LMDZ5/branches/testing/libf/dyn3d/etat0_netcdf.F90
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/etat0_netcdf.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3d/etat0_netcdf.F90	(revision 1665)
@@ -251,7 +251,7 @@
 !*******************************************************************************
   CALL pression(ip1jmp1, ap, bp, psol, p3d)
-  if (disvert_type.eq.1) then
+  if (pressure_exner) then
     CALL exner_hyb(ip1jmp1, psol, p3d, alpha, beta, pks, pk, y)
-  else ! we assume that we are in the disvert_type==2 case
+  else
     CALL exner_milieu(ip1jmp1,psol,p3d,beta,pks,pk,y)
   endif
Index: LMDZ5/branches/testing/libf/dyn3d/exner_hyb.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/exner_hyb.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3d/exner_hyb.F	(revision 1665)
@@ -56,11 +56,4 @@
       ! Sanity check
       if (firstcall) then
-        ! check that vertical discretization is compatible
-        ! with this routine
-        if (disvert_type.ne.1) then
-          call abort_gcm(modname,
-     &     "this routine should only be called if disvert_type==1",42)
-        endif
-        
         ! sanity checks for Shallow Water case (1 vertical layer)
         if (llm.eq.1) then
Index: LMDZ5/branches/testing/libf/dyn3d/exner_milieu.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/exner_milieu.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3d/exner_milieu.F	(revision 1665)
@@ -53,11 +53,4 @@
       ! Sanity check
       if (firstcall) then
-        ! check that vertical discretization is compatible
-        ! with this routine
-        if (disvert_type.ne.2) then
-          call abort_gcm(modname,
-     &     "this routine should only be called if disvert_type==2",42)
-        endif
-        
         ! sanity checks for Shallow Water case (1 vertical layer)
         if (llm.eq.1) then
Index: LMDZ5/branches/testing/libf/dyn3d/gcm.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/gcm.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3d/gcm.F	(revision 1665)
@@ -21,6 +21,5 @@
 ! A nettoyer. On ne veut qu'une ou deux routines d'interface 
 ! dynamique -> physique pour l'initialisation
-! Ehouarn: for now these only apply to Earth:
-#ifdef CPP_EARTH
+#ifdef CPP_PHYS
       USE dimphy
       USE comgeomphy
@@ -88,5 +87,4 @@
 
       REAL zdtvr
-      INTEGER nbetatmoy, nbetatdem,nbetat
 
 c   variables dynamiques
@@ -181,11 +179,8 @@
 ! A nettoyer. On ne veut qu'une ou deux routines d'interface 
 ! dynamique -> physique pour l'initialisation
-! Ehouarn : temporarily (?) keep this only for Earth
-      if (planet_type.eq."earth") then
-#ifdef CPP_EARTH
+#ifdef CPP_PHYS
       CALL Init_Phys_lmdz(iim,jjp1,llm,1,(/(jjm-1)*iim+2/))
       call InitComgeomphy
 #endif
-      endif
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 c-----------------------------------------------------------------------
@@ -305,4 +300,15 @@
 C on remet le calendrier à zero si demande
 c
+      IF (start_time /= starttime) then
+        WRITE(lunout,*)' GCM: Attention l''heure de depart lue dans le'
+     &,' fichier restart ne correspond pas à celle lue dans le run.def'
+        IF (raz_date == 1) then
+          WRITE(lunout,*)'Je prends l''heure lue dans run.def'
+          start_time = starttime
+        ELSE
+          WRITE(lunout,*)'Je m''arrete'
+          CALL abort
+        ENDIF
+      ENDIF
       IF (raz_date == 1) THEN
         annee_ref = anneeref
@@ -373,7 +379,4 @@
 #endif
 
-c  nombre d'etats dans les fichiers demarrage et histoire
-      nbetatdem = nday / iecri
-      nbetatmoy = nday / periodav + 1
 
       if (iflag_phys.eq.1) then
@@ -428,14 +431,11 @@
          WRITE(lunout,*)
      .       'GCM: WARNING!!! vitesse verticale nulle dans la physique'
-! Earth:
-         if (planet_type.eq."earth") then
-#ifdef CPP_EARTH
+! Physics:
+#ifdef CPP_PHYS
          CALL iniphysiq(ngridmx,llm,daysec,day_ini,dtphys/nsplit_phys ,
      ,                latfi,lonfi,airefi,zcufi,zcvfi,rad,g,r,cpp     )
 #endif
-         endif ! of if (planet_type.eq."earth")
          call_iniphys=.false.
       ENDIF ! of IF (call_iniphys.and.(iflag_phys.eq.1))
-!#endif
 
 c  numero de stockage pour les fichiers de redemarrage:
@@ -459,5 +459,5 @@
 #endif
 
-#ifdef CPP_EARTH
+#ifdef CPP_PHYS
 ! Create start file (startphy.nc) and boundary conditions (limit.nc) 
 ! for the Earth verstion
Index: LMDZ5/branches/testing/libf/dyn3d/guide_mod.F90
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/guide_mod.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3d/guide_mod.F90	(revision 1665)
@@ -644,7 +644,7 @@
 ! -----------------------------------------------------------------
     CALL pression( ip1jmp1, ap, bp, psi, p )
-    if (disvert_type==1) then
+    if (pressure_exner) then
       CALL exner_hyb(ip1jmp1,psi,p,alpha,beta,pks,pk,pkf)
-    else ! we assume that we are in the disvert_type==2 case
+    else
       CALL exner_milieu(ip1jmp1,psi,p,beta,pks,pk,pkf)
     endif
Index: LMDZ5/branches/testing/libf/dyn3d/iniacademic.F90
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/iniacademic.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3d/iniacademic.F90	(revision 1665)
@@ -222,12 +222,8 @@
 
         CALL pression ( ip1jmp1, ap, bp, ps, p       )
-        if (disvert_type.eq.1) then
+        if (pressure_exner) then
           CALL exner_hyb( ip1jmp1, ps, p,alpha,beta, pks, pk, pkf )
-        elseif (disvert_type.eq.2) then
+        else
           call exner_milieu(ip1jmp1,ps,p,beta,pks,pk,pkf)
-        else
-          write(abort_message,*) "Wrong value for disvert_type: ", &
-                              disvert_type
-          call abort_gcm(modname,abort_message,0)
         endif
         CALL massdair(p,masse)
Index: LMDZ5/branches/testing/libf/dyn3d/iniconst.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/iniconst.F	(revision 1664)
+++ 	(revision )
@@ -1,84 +1,0 @@
-!
-! $Id$
-!
-      SUBROUTINE iniconst
-
-      USE control_mod
-#ifdef CPP_IOIPSL
-      use IOIPSL
-#else
-! if not using IOIPSL, we still need to use (a local version of) getin
-      use ioipsl_getincom
-#endif
-
-      IMPLICIT NONE
-c
-c      P. Le Van
-c
-c-----------------------------------------------------------------------
-c   Declarations:
-c   -------------
-c
-#include "dimensions.h"
-#include "paramet.h"
-#include "comconst.h"
-#include "temps.h"
-#include "comvert.h"
-#include "iniprint.h"
-
-      character(len=*),parameter :: modname="iniconst"
-      character(len=80) :: abort_message
-c
-c
-c
-c-----------------------------------------------------------------------
-c   dimension des boucles:
-c   ----------------------
-
-      im      = iim
-      jm      = jjm
-      lllm    = llm
-      imp1    = iim 
-      jmp1    = jjm + 1
-      lllmm1  = llm - 1
-      lllmp1  = llm + 1
-
-c-----------------------------------------------------------------------
-
-      dtphys  = iphysiq * dtvr
-      unsim   = 1./iim
-      pi      = 2.*ASIN( 1. )
-
-c-----------------------------------------------------------------------
-c
-
-      r       = cpp * kappa
-
-      write(lunout,*) trim(modname),': R  CP  Kappa ',r,cpp,kappa
-c
-c-----------------------------------------------------------------------
-
-! vertical discretization: default behavior depends on planet_type flag
-      if (planet_type=="earth") then
-        disvert_type=1
-      else
-        disvert_type=2
-      endif
-      ! but user can also specify using one or the other in run.def:
-      call getin('disvert_type',disvert_type)
-      write(lunout,*) trim(modname),': disvert_type=',disvert_type
-      
-      if (disvert_type==1) then
-       ! standard case for Earth (automatic generation of levels)
-       call disvert(pa,preff,ap,bp,dpres,presnivs,nivsigs,nivsig,
-     &              scaleheight)
-      else if (disvert_type==2) then
-        ! standard case for planets (levels generated using z2sig.def file)
-        call disvert_noterre
-      else
-        write(abort_message,*) "Wrong value for disvert_type: ",
-     &                        disvert_type
-        call abort_gcm(modname,abort_message,0)
-      endif
-
-      END
Index: LMDZ5/branches/testing/libf/dyn3d/iniconst.F90
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/iniconst.F90	(revision 1665)
+++ LMDZ5/branches/testing/libf/dyn3d/iniconst.F90	(revision 1665)
@@ -0,0 +1,84 @@
+!
+! $Id$
+!
+SUBROUTINE iniconst
+
+  USE control_mod
+#ifdef CPP_IOIPSL
+  use IOIPSL
+#else
+  ! if not using IOIPSL, we still need to use (a local version of) getin
+  use ioipsl_getincom
+#endif
+
+  IMPLICIT NONE
+  !
+  !      P. Le Van
+  !
+  !   Declarations:
+  !   -------------
+  !
+  include "dimensions.h"
+  include "paramet.h"
+  include "comconst.h"
+  include "temps.h"
+  include "comvert.h"
+  include "iniprint.h"
+
+  character(len=*),parameter :: modname="iniconst"
+  character(len=80) :: abort_message
+  !
+  !
+  !
+  !-----------------------------------------------------------------------
+  !   dimension des boucles:
+  !   ----------------------
+
+  im      = iim
+  jm      = jjm
+  lllm    = llm
+  imp1    = iim 
+  jmp1    = jjm + 1
+  lllmm1  = llm - 1
+  lllmp1  = llm + 1
+
+  !-----------------------------------------------------------------------
+
+  dtphys  = iphysiq * dtvr
+  unsim   = 1./iim
+  pi      = 2.*ASIN( 1. )
+
+  !-----------------------------------------------------------------------
+  !
+
+  r       = cpp * kappa
+
+  write(lunout,*) trim(modname),': R  CP  Kappa ',r,cpp,kappa
+  !
+  !-----------------------------------------------------------------------
+
+  ! vertical discretization: default behavior depends on planet_type flag
+  if (planet_type=="earth") then
+     disvert_type=1
+  else
+     disvert_type=2
+  endif
+  ! but user can also specify using one or the other in run.def:
+  call getin('disvert_type',disvert_type)
+  write(lunout,*) trim(modname),': disvert_type=',disvert_type
+
+  pressure_exner = disvert_type == 1 ! default value
+  call getin('pressure_exner', pressure_exner)
+
+  if (disvert_type==1) then
+     ! standard case for Earth (automatic generation of levels)
+     call disvert(pa,preff,ap,bp,dpres,presnivs,nivsigs,nivsig, scaleheight)
+  else if (disvert_type==2) then
+     ! standard case for planets (levels generated using z2sig.def file)
+     call disvert_noterre
+  else
+     write(abort_message,*) "Wrong value for disvert_type: ", disvert_type
+     call abort_gcm(modname,abort_message,0)
+  endif
+
+END SUBROUTINE iniconst
Index: LMDZ5/branches/testing/libf/dyn3d/inidissip.F90
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/inidissip.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3d/inidissip.F90	(revision 1665)
@@ -28,7 +28,8 @@
 ! Local variables:
   REAL fact,zvert(llm),zz
-  REAL zh(ip1jmp1),zu(ip1jmp1),zv(ip1jm),deltap(ip1jmp1,llm)
+  REAL zh(ip1jmp1),zu(ip1jmp1), gx(ip1jmp1), divgra(ip1jmp1)
+  real zv(ip1jm), gy(ip1jm), deltap(ip1jmp1,llm)
   REAL ullm,vllm,umin,vmin,zhmin,zhmax
-  REAL zllm,z1llm
+  REAL zllm
 
   INTEGER l,ij,idum,ii
@@ -78,16 +79,11 @@
   DO l = 1,50
      IF(lstardis) THEN
-        CALL divgrad2(1,zh,deltap,niterh,zh)
+        CALL divgrad2(1,zh,deltap,niterh,divgra)
      ELSE
-        CALL divgrad (1,zh,niterh,zh)
+        CALL divgrad (1,zh,niterh,divgra)
      ENDIF
 
-     CALL minmax(iip1*jjp1,zh,zhmin,zhmax )
-
-     zllm  = ABS( zhmax )
-     z1llm = 1./zllm
-     DO ij = 1,ip1jmp1
-        zh(ij) = zh(ij)* z1llm
-     ENDDO
+     zllm  = ABS(maxval(divgra))
+     zh = divgra / zllm
   ENDDO
 
@@ -123,30 +119,19 @@
            !cccc             CALL covcont( 1,zu,zv,zu,zv )
            IF(lstardis) THEN
-              CALL gradiv2( 1,zu,zv,nitergdiv,zu,zv )
+              CALL gradiv2( 1,zu,zv,nitergdiv,gx,gy )
            ELSE
-              CALL gradiv ( 1,zu,zv,nitergdiv,zu,zv )
+              CALL gradiv ( 1,zu,zv,nitergdiv,gx,gy )
            ENDIF
         ELSE
            IF(lstardis) THEN
-              CALL nxgraro2( 1,zu,zv,nitergrot,zu,zv )
+              CALL nxgraro2( 1,zu,zv,nitergrot,gx,gy )
            ELSE
-              CALL nxgrarot( 1,zu,zv,nitergrot,zu,zv )
+              CALL nxgrarot( 1,zu,zv,nitergrot,gx,gy )
            ENDIF
         ENDIF
 
-        CALL minmax(iip1*jjp1,zu,umin,ullm )
-        CALL minmax(iip1*jjm, zv,vmin,vllm )
-
-        ullm = ABS  ( ullm )
-        vllm = ABS  ( vllm )
-
-        zllm  = MAX( ullm,vllm )
-        z1llm = 1./ zllm
-        DO ij = 1, ip1jmp1
-           zu(ij) = zu(ij)* z1llm
-        ENDDO
-        DO ij = 1, ip1jm
-           zv(ij) = zv(ij)* z1llm
-        ENDDO
+        zllm = max(abs(maxval(gx)), abs(maxval(gy)))
+        zu = gx / zllm
+        zv = gy / zllm
      end DO
 
Index: LMDZ5/branches/testing/libf/dyn3d/inigrads.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/inigrads.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3d/inigrads.F	(revision 1665)
@@ -9,5 +9,5 @@
       implicit none
 
-      integer if,im,jm,lm,i,j,l,lnblnk
+      integer if,im,jm,lm,i,j,l
       real x(im),y(jm),z(lm),fx,fy,fz,dt
       real xmin,xmax,ymin,ymax
@@ -40,5 +40,5 @@
       ivar(if)=0
 
-      fichier(if)=file(1:lnblnk(file))
+      fichier(if)=trim(file)
 
       firsttime(if)=.true.
@@ -70,7 +70,7 @@
 
       print*,4*(ifd(if)-iid(if))*(jfd(if)-jid(if))
-      print*,file(1:lnblnk(file))//'.dat'
+      print*,trim(file)//'.dat'
 
-      OPEN (unit(if)+1,FILE=file(1:lnblnk(file))//'.dat'
+      OPEN (unit(if)+1,FILE=trim(file)//'.dat'
      s   ,FORM='unformatted',
      s   ACCESS='direct'
Index: LMDZ5/branches/testing/libf/dyn3d/integrd.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/integrd.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3d/integrd.F	(revision 1665)
@@ -4,5 +4,6 @@
       SUBROUTINE integrd
      $  (  nq,vcovm1,ucovm1,tetam1,psm1,massem1,
-     $     dv,du,dteta,dq,dp,vcov,ucov,teta,q,ps,masse,phis,finvmaold )
+     $     dv,du,dteta,dq,dp,vcov,ucov,teta,q,ps,masse,phis !,finvmaold
+     &  )
 
       use control_mod, only : planet_type
@@ -34,20 +35,30 @@
 #include "temps.h"
 #include "serre.h"
+#include "iniprint.h"
 
 c   Arguments:
 c   ----------
 
-      INTEGER nq
-
-      REAL vcov(ip1jm,llm),ucov(ip1jmp1,llm),teta(ip1jmp1,llm)
-      REAL q(ip1jmp1,llm,nq)
-      REAL ps(ip1jmp1),masse(ip1jmp1,llm),phis(ip1jmp1)
-
-      REAL vcovm1(ip1jm,llm),ucovm1(ip1jmp1,llm)
-      REAL tetam1(ip1jmp1,llm),psm1(ip1jmp1),massem1(ip1jmp1,llm)
-
-      REAL dv(ip1jm,llm),du(ip1jmp1,llm)
-      REAL dteta(ip1jmp1,llm),dp(ip1jmp1)
-      REAL dq(ip1jmp1,llm,nq), finvmaold(ip1jmp1,llm)
+      integer,intent(in) :: nq ! number of tracers to handle in this routine
+      real,intent(inout) :: vcov(ip1jm,llm) ! covariant meridional wind
+      real,intent(inout) :: ucov(ip1jmp1,llm) ! covariant zonal wind
+      real,intent(inout) :: teta(ip1jmp1,llm) ! potential temperature
+      real,intent(inout) :: q(ip1jmp1,llm,nq) ! advected tracers
+      real,intent(inout) :: ps(ip1jmp1) ! surface pressure
+      real,intent(inout) :: masse(ip1jmp1,llm) ! atmospheric mass
+      real,intent(in) :: phis(ip1jmp1) ! ground geopotential !!! unused
+      ! values at previous time step
+      real,intent(inout) :: vcovm1(ip1jm,llm)
+      real,intent(inout) :: ucovm1(ip1jmp1,llm)
+      real,intent(inout) :: tetam1(ip1jmp1,llm)
+      real,intent(inout) :: psm1(ip1jmp1)
+      real,intent(inout) :: massem1(ip1jmp1,llm)
+      ! the tendencies to add
+      real,intent(in) :: dv(ip1jm,llm)
+      real,intent(in) :: du(ip1jmp1,llm)
+      real,intent(in) :: dteta(ip1jmp1,llm)
+      real,intent(in) :: dp(ip1jmp1)
+      real,intent(in) :: dq(ip1jmp1,llm,nq) !!! unused
+!      real,intent(out) :: finvmaold(ip1jmp1,llm) !!! unused
 
 c   Local:
@@ -55,5 +66,6 @@
 
       REAL vscr( ip1jm ),uscr( ip1jmp1 ),hscr( ip1jmp1 ),pscr(ip1jmp1)
-      REAL massescr( ip1jmp1,llm ), finvmasse(ip1jmp1,llm)
+      REAL massescr( ip1jmp1,llm )
+!      REAL finvmasse(ip1jmp1,llm)
       REAL p(ip1jmp1,llmp1)
       REAL tpn,tps,tppn(iim),tpps(iim)
@@ -61,5 +73,5 @@
       REAL deltap( ip1jmp1,llm )
 
-      INTEGER  l,ij,iq
+      INTEGER  l,ij,iq,i,j
 
       REAL SSUM
@@ -88,7 +100,12 @@
       DO ij = 1,ip1jmp1
         IF( ps(ij).LT.0. ) THEN
-         PRINT*,' Au point ij = ',ij, ' , pression sol neg. ', ps(ij)
-         print *, ' dans integrd'
-         stop 1
+         write(lunout,*) "integrd: negative surface pressure ",ps(ij)
+         write(lunout,*) " at node ij =", ij
+         ! since ij=j+(i-1)*jjp1 , we have
+         j=modulo(ij,jjp1)
+         i=1+(ij-j)/jjp1
+         write(lunout,*) " lon = ",rlonv(i)*180./pi, " deg",
+     &                   " lat = ",rlatu(j)*180./pi, " deg"
+         stop
         ENDIF
       ENDDO
@@ -110,6 +127,8 @@
       CALL massdair (     p  , masse         )
 
-      CALL   SCOPY( ijp1llm  , masse, 1, finvmasse,  1      )
-      CALL filtreg( finvmasse, jjp1, llm, -2, 2, .TRUE., 1  )
+! Ehouarn : we don't use/need finvmaold and finvmasse,
+!           so might as well not compute them
+!      CALL   SCOPY( ijp1llm  , masse, 1, finvmasse,  1      )
+!      CALL filtreg( finvmasse, jjp1, llm, -2, 2, .TRUE., 1  )
 c
 
@@ -218,6 +237,6 @@
        ENDDO
 
-
-      CALL  SCOPY( ijp1llm , finvmasse, 1, finvmaold, 1 )
+! Ehouarn: forget about finvmaold
+!      CALL  SCOPY( ijp1llm , finvmasse, 1, finvmaold, 1 )
 
       endif ! of if (planet_type.eq."earth")
Index: LMDZ5/branches/testing/libf/dyn3d/leapfrog.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/leapfrog.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3d/leapfrog.F	(revision 1665)
@@ -72,5 +72,4 @@
 
       real zqmin,zqmax
-      INTEGER nbetatmoy, nbetatdem,nbetat
 
 c   variables dynamiques
@@ -118,5 +117,6 @@
 
       REAL  SSUM
-      REAL time_0 , finvmaold(ip1jmp1,llm)
+      REAL time_0
+!     REAL finvmaold(ip1jmp1,llm)
 
 cym      LOGICAL  lafin
@@ -212,7 +212,7 @@
       dq(:,:,:)=0.
       CALL pression ( ip1jmp1, ap, bp, ps, p       )
-      if (disvert_type==1) then
+      if (pressure_exner) then
         CALL exner_hyb( ip1jmp1, ps, p,alpha,beta, pks, pk, pkf )
-      else ! we assume that we are in the disvert_type==2 case
+      else
         CALL exner_milieu( ip1jmp1, ps, p, beta, pks, pk, pkf )
       endif
@@ -222,9 +222,12 @@
 c   ----------------------------------
 
-   1  CONTINUE
-
-      jD_cur = jD_ref + day_ini - day_ref + int (itau * dtvr / daysec) 
-      jH_cur = jH_ref +                                                 &
-     &          (itau * dtvr / daysec - int(itau * dtvr / daysec)) 
+   1  CONTINUE ! Matsuno Forward step begins here
+
+      jD_cur = jD_ref + day_ini - day_ref +                             &
+     &          itau/day_step
+      jH_cur = jH_ref + start_time +                                    &
+     &          mod(itau,day_step)/float(day_step) 
+      jD_cur = jD_cur + int(jH_cur)
+      jH_cur = jH_cur - int(jH_cur)
 
 
@@ -255,9 +258,9 @@
 
 c   ...    P.Le Van .26/04/94  ....
-
-      CALL SCOPY   ( ijp1llm,   masse, 1, finvmaold,     1 )
-      CALL filtreg ( finvmaold ,jjp1, llm, -2,2, .TRUE., 1 )
-
-   2  CONTINUE
+! Ehouarn: finvmaold is actually not used
+!      CALL SCOPY   ( ijp1llm,   masse, 1, finvmaold,     1 )
+!      CALL filtreg ( finvmaold ,jjp1, llm, -2,2, .TRUE., 1 )
+
+   2  CONTINUE ! Matsuno backward or leapfrog step begins here
 
 c-----------------------------------------------------------------------
@@ -302,4 +305,5 @@
 c   --------------------------------
 
+      ! compute geopotential phi()
       CALL geopot  ( ip1jmp1, teta  , pk , pks,  phis  , phi   )
 
@@ -315,5 +319,6 @@
 
       IF( forward. OR . leapf )  THEN
-
+! Ehouarn: NB: at this point p with ps are not synchronized
+!              (whereas mass and ps are...)
          CALL caladvtrac(q,pbaru,pbarv,
      *        p, masse, dq,  teta,
@@ -340,6 +345,6 @@
 
        CALL integrd ( 2,vcovm1,ucovm1,tetam1,psm1,massem1 ,
-     $         dv,du,dteta,dq,dp,vcov,ucov,teta,q,ps,masse,phis ,
-     $              finvmaold                                    )
+     $         dv,du,dteta,dq,dp,vcov,ucov,teta,q,ps,masse,phis )
+!     $              finvmaold                                    )
 
 
@@ -364,7 +369,7 @@
 
          CALL pression (  ip1jmp1, ap, bp, ps,  p      )
-         if (disvert_type==1) then
+         if (pressure_exner) then
            CALL exner_hyb(  ip1jmp1, ps, p,alpha,beta,pks, pk, pkf )
-         else ! we assume that we are in the disvert_type==2 case
+         else
            CALL exner_milieu( ip1jmp1, ps, p, beta, pks, pk, pkf )
          endif
@@ -372,8 +377,14 @@
 !           rdaym_ini  = itau * dtvr / daysec
 !           rdayvrai   = rdaym_ini  + day_ini
-           jD_cur = jD_ref + day_ini - day_ref
-     $        + int (itau * dtvr / daysec) 
-           jH_cur = jH_ref +                                            &
-     &              (itau * dtvr / daysec - int(itau * dtvr / daysec)) 
+!           jD_cur = jD_ref + day_ini - day_ref
+!     $        + int (itau * dtvr / daysec) 
+!           jH_cur = jH_ref +                                            &
+!     &              (itau * dtvr / daysec - int(itau * dtvr / daysec)) 
+           jD_cur = jD_ref + day_ini - day_ref +                        &
+     &          itau/day_step
+           jH_cur = jH_ref + start_time +                               &
+     &              mod(itau,day_step)/float(day_step) 
+           jD_cur = jD_cur + int(jH_cur)
+           jH_cur = jH_cur - int(jH_cur)
 !         write(lunout,*)'itau, jD_cur = ', itau, jD_cur, jH_cur
 !         call ju2ymds(jD_cur+jH_cur, an, mois, jour, secondes)
@@ -394,6 +405,8 @@
 ! Ehouarn: be careful, diagedyn is Earth-specific (includes ../phylmd/..)!
            IF (planet_type.eq."earth") THEN
+#ifdef CPP_EARTH
             CALL diagedyn(ztit,2,1,1,dtphys
      &    , ucov    , vcov , ps, p ,pk , teta , q(:,:,1), q(:,:,2))
+#endif
            ENDIF
          ENDIF ! of IF (ip_ebil_dyn.ge.1 )
@@ -472,7 +485,7 @@
 
         CALL pression ( ip1jmp1, ap, bp, ps, p                  )
-        if (disvert_type==1) then
+        if (pressure_exner) then
           CALL exner_hyb( ip1jmp1, ps, p,alpha,beta, pks, pk, pkf )
-        else ! we assume that we are in the disvert_type==2 case
+        else
           CALL exner_milieu( ip1jmp1, ps, p, beta, pks, pk, pkf )
         endif
@@ -529,16 +542,20 @@
         ENDDO
 
-        DO ij =  1,iim
-          tppn(ij)  = aire(  ij    ) * ps (  ij    )
-          tpps(ij)  = aire(ij+ip1jm) * ps (ij+ip1jm)
-        ENDDO
-          tpn  = SSUM(iim,tppn,1)/apoln
-          tps  = SSUM(iim,tpps,1)/apols
-
-        DO ij = 1, iip1
-          ps(  ij    ) = tpn
-          ps(ij+ip1jm) = tps
-        ENDDO
-
+        if (1 == 0) then
+!!! Ehouarn: lines here 1) kill 1+1=2 in the dynamics
+!!!                     2) should probably not be here anyway
+!!! but are kept for those who would want to revert to previous behaviour
+           DO ij =  1,iim
+             tppn(ij)  = aire(  ij    ) * ps (  ij    )
+             tpps(ij)  = aire(ij+ip1jm) * ps (ij+ip1jm)
+           ENDDO
+             tpn  = SSUM(iim,tppn,1)/apoln
+             tps  = SSUM(iim,tpps,1)/apols
+
+           DO ij = 1, iip1
+             ps(  ij    ) = tpn
+             ps(ij+ip1jm) = tps
+           ENDDO
+        endif ! of if (1 == 0)
 
       END IF ! of IF(apdiss)
@@ -622,5 +639,4 @@
              ! Ehouarn: output only during LF or Backward Matsuno
 	     if (leapf.or.(.not.leapf.and.(.not.forward))) then
-              nbetat = nbetatdem
               CALL geopot(ip1jmp1,teta,pk,pks,phis,phi)
               unat=0.
@@ -652,9 +668,10 @@
 !              if (planet_type.eq."earth") then
 ! Write an Earth-format restart file
-                CALL dynredem1("restart.nc",0.0,
+                CALL dynredem1("restart.nc",start_time,
      &                         vcov,ucov,teta,q,masse,ps)
 !              endif ! of if (planet_type.eq."earth")
 
               CLOSE(99)
+              !!! Ehouarn: Why not stop here and now?
             ENDIF ! of IF (itau.EQ.itaufin)
 
@@ -740,5 +757,4 @@
               IF(MOD(itau,iecri         ).EQ.0) THEN
 c              IF(MOD(itau,iecri*day_step).EQ.0) THEN
-                nbetat = nbetatdem
                 CALL geopot(ip1jmp1,teta,pk,pks,phis,phi)
                 unat=0.
@@ -763,5 +779,5 @@
               IF(itau.EQ.itaufin) THEN
 !                if (planet_type.eq."earth") then
-                  CALL dynredem1("restart.nc",0.0,
+                  CALL dynredem1("restart.nc",start_time,
      &                           vcov,ucov,teta,q,masse,ps)
 !                endif ! of if (planet_type.eq."earth")
Index: LMDZ5/branches/testing/libf/dyn3d/temps.h
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/temps.h	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3d/temps.h	(revision 1665)
@@ -14,10 +14,12 @@
 
       COMMON/temps/itaufin, dt, day_ini, day_end, annee_ref, day_ref,   &
-     &             itau_dyn, itau_phy, jD_ref, jH_ref, calend
+     &             itau_dyn, itau_phy, jD_ref, jH_ref, calend,          &
+     &             start_time
+
 
       INTEGER   itaufin
       INTEGER itau_dyn, itau_phy
       INTEGER day_ini, day_end, annee_ref, day_ref
-      REAL      dt, jD_ref, jH_ref
+      REAL      dt, jD_ref, jH_ref, start_time
       CHARACTER (len=10) :: calend
 
Index: LMDZ5/branches/testing/libf/dyn3d/wrgrads.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3d/wrgrads.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3d/wrgrads.F	(revision 1665)
@@ -26,5 +26,5 @@
 c   local
 
-      integer im,jm,lm,i,j,l,lnblnk,iv,iii,iji,iif,ijf
+      integer im,jm,lm,i,j,l,iv,iii,iji,iif,ijf
 
       logical writectl
@@ -59,5 +59,5 @@
             nvar(if)=ivar(if)
             var(ivar(if),if)=name
-            tvar(ivar(if),if)=titlevar(1:lnblnk(titlevar))
+            tvar(ivar(if),if)=trim(titlevar)
             nld(ivar(if),if)=nl
 c           print*,'initialisation ecriture de ',var(ivar(if),if)
@@ -101,8 +101,8 @@
       file=fichier(if)
 c   WARNING! on reecrase le fichier .ctl a chaque ecriture
-      open(unit(if),file=file(1:lnblnk(file))//'.ctl'
+      open(unit(if),file=trim(file)//'.ctl'
      &         ,form='formatted',status='unknown')
       write(unit(if),'(a5,1x,a40)')
-     &       'DSET ','^'//file(1:lnblnk(file))//'.dat'
+     &       'DSET ','^'//trim(file)//'.dat'
 
       write(unit(if),'(a12)') 'UNDEF 1.0E30'
Index: LMDZ5/branches/testing/libf/dyn3dpar/bands.F90
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/bands.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/bands.F90	(revision 1665)
@@ -93,6 +93,6 @@
    SUBROUTINE  Set_Bands 
      USE parallel
-#ifdef CPP_EARTH
-! Ehouarn: what follows is only related to // physics; for now only for Earth 
+#ifdef CPP_PHYS
+! Ehouarn: what follows is only related to // physics
      USE mod_phys_lmdz_para, ONLY : jj_para_begin,jj_para_end
 #endif
@@ -106,6 +106,5 @@
       enddo
           
-#ifdef CPP_EARTH
-! Ehouarn: what follows is only related to // physics; for now only for Earth          
+#ifdef CPP_PHYS
       do i=0,MPI_Size-1
         jj_Nb_physic(i)=jj_para_end(i)-jj_para_begin(i)+1
@@ -332,6 +331,6 @@
     subroutine AdjustBands_physic
       use times
-#ifdef CPP_EARTH
-! Ehouarn: what follows is only related to // physics; for now only for Earth 
+#ifdef CPP_PHYS
+! Ehouarn: what follows is only related to // physics
       USE mod_phys_lmdz_para, only : klon_mpi_para_nb
 #endif
@@ -359,6 +358,5 @@
       medium=medium/mpi_size      
       NbTot=0
-#ifdef CPP_EARTH
-! Ehouarn: what follows is only related to // physics; for now only for Earth 
+#ifdef CPP_PHYS
       do i=0,mpi_size-1
         Inc(i)=nint(klon_mpi_para_nb(i)*(medium-value(i))/value(i))
Index: LMDZ5/branches/testing/libf/dyn3dpar/calfis_p.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/calfis_p.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/calfis_p.F	(revision 1665)
@@ -27,9 +27,6 @@
      $                  pdqfi,
      $                  pdpsfi)
-#ifdef CPP_EARTH
-! Ehouarn: For now, calfis_p needs Earth physics
-c
-c    Auteur :  P. Le Van, F. Hourdin 
-c   .........
+#ifdef CPP_PHYS
+! If using physics
       USE dimphy
       USE mod_phys_lmdz_para, mpi_root_xx=>mpi_root 
@@ -146,5 +143,6 @@
       REAL clesphy0( longcles )
 
-#ifdef CPP_EARTH
+#ifdef CPP_PHYS
+! Ehouarn: for now calfis_p needs some informations from physics to compile
 c    Local variables :
 c    -----------------
@@ -222,5 +220,5 @@
       PARAMETER(ntetaSTD=3)
       REAL rtetaSTD(ntetaSTD)
-      DATA rtetaSTD/350., 380., 405./
+      DATA rtetaSTD/350., 380., 405./ ! Earth-specific values, beware !!
       REAL PVteta(klon,ntetaSTD)
       
@@ -489,6 +487,7 @@
 
 
-      IF (is_sequential) THEN
-c
+      IF (is_sequential.and.(planet_type=="earth")) THEN
+#ifdef CPP_PHYS
+! PVtheta calls tetalevel, which is in the physics
 cIM calcul PV a teta=350, 380, 405K
         CALL PVtheta(ngridmx,llm,pucov,pvcov,pteta,
@@ -496,4 +495,5 @@
      $           ntetaSTD,rtetaSTD,PVteta)
 c
+#endif
       ENDIF
 
@@ -627,7 +627,4 @@
 c$OMP BARRIER
       
-      if (planet_type=="earth") then
-#ifdef CPP_EARTH
-
 !$OMP MASTER
 !      write(lunout,*) 'PHYSIQUE AVEC NSPLIT_PHYS=',nsplit_phys
@@ -639,4 +636,6 @@
       zdqfic_omp(:,:,:)=0.
 
+      if (planet_type=="earth") then
+#ifdef CPP_PHYS
       do isplit=1,nsplit_phys
 
@@ -687,11 +686,12 @@
       enddo
 
+#endif
+! of #ifdef CPP_PHYS
+      endif !of if (planet_type=="earth")
+
       zdufi_omp(:,:)=zdufic_omp(:,:)/nsplit_phys
       zdvfi_omp(:,:)=zdvfic_omp(:,:)/nsplit_phys
       zdtfi_omp(:,:)=zdtfic_omp(:,:)/nsplit_phys
       zdqfi_omp(:,:,:)=zdqfic_omp(:,:,:)/nsplit_phys
-
-#endif
-      endif !of if (planet_type=="earth")
 c$OMP BARRIER
 
@@ -1110,10 +1110,10 @@
       firstcal = .FALSE.
 
-#else
-      write(lunout,*)
-     & "calfis_p: for now can only work with parallel physics"
-      stop
-#endif
-! of #ifdef CPP_EARTH
+#else 
+      write(lunout,*) 
+     & "calfis_p: for now can only work with parallel physics" 
+      stop 
+#endif 
+! of #ifdef CPP_PHYS
       RETURN
       END
Index: LMDZ5/branches/testing/libf/dyn3dpar/ce0l.F90
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/ce0l.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/ce0l.F90	(revision 1665)
@@ -19,5 +19,5 @@
   USE dimphy
   USE comgeomphy
-  USE mod_phys_lmdz_para
+  USE mod_phys_lmdz_para, mpi_root_xx=>mpi_root
   USE mod_const_mpi
   USE infotrac
@@ -31,4 +31,5 @@
   IMPLICIT NONE
 #ifndef CPP_EARTH
+#include "iniprint.h"
   WRITE(lunout,*)'limit_netcdf: Earth-specific routine, needs Earth physics'
 #else
@@ -42,5 +43,10 @@
 #include "temps.h"
 #include "logic.h"
+#ifdef CPP_MPI
+      include 'mpif.h'
+#endif
+
   INTEGER, PARAMETER            :: longcles=20
+  INTEGER                       :: ierr
   REAL,    DIMENSION(longcles)  :: clesphy0
   REAL,    DIMENSION(iip1,jjp1) :: masque
@@ -50,5 +56,7 @@
   CALL conf_gcm( 99, .TRUE. , clesphy0 )
 
+#ifdef CPP_MPI
   CALL init_mpi
+#endif
 
   CALL Init_Phys_lmdz(iim,jjp1,llm,1,(/(jjm-1)*iim+2/))
@@ -115,7 +123,10 @@
   END IF
   
+#ifdef CPP_MPI
 !$OMP MASTER
-  CALL finalize_parallel
+  CALL MPI_FINALIZE(ierr)
+  IF (ierr /= 0) CALL abort_gcm('ce0l','Error in MPI_FINALIZE',1)
 !$OMP END MASTER
+#endif
 
 #endif
Index: LMDZ5/branches/testing/libf/dyn3dpar/comvert.h
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/comvert.h	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/comvert.h	(revision 1665)
@@ -9,5 +9,5 @@
      &               aps(llm),bps(llm),scaleheight
 
-      common/comverti/disvert_type
+      common/comverti/disvert_type, pressure_exner
 
       real ap     ! hybrid pressure contribution at interlayers
@@ -30,3 +30,7 @@
                            !     using 'z2sig.def' (or 'esasig.def) file
 
+      logical pressure_exner
+!     compute pressure inside layers using Exner function, else use mean
+!     of pressure values at interfaces
+
  !-----------------------------------------------------------------------
Index: LMDZ5/branches/testing/libf/dyn3dpar/conf_gcm.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/conf_gcm.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/conf_gcm.F	(revision 1665)
@@ -167,4 +167,12 @@
       nday = 10
       CALL getin('nday',nday)
+
+!Config  Key  = starttime
+!Config  Desc = Heure de depart de la simulation
+!Config  Def  = 0
+!Config  Help = Heure de depart de la simulation
+!Config         en jour
+      starttime = 0
+      CALL getin('starttime',starttime)
 
 !Config  Key  = day_step
Index: LMDZ5/branches/testing/libf/dyn3dpar/control_mod.F90
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/control_mod.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/control_mod.F90	(revision 1665)
@@ -10,5 +10,5 @@
   IMPLICIT NONE
 
-  REAL    :: periodav
+  REAL    :: periodav, starttime
   INTEGER :: nday,day_step,iperiod,iapp_tracvl,nsplit_phys
   INTEGER :: iconser,iecri,dissip_period,iphysiq,iecrimoy
Index: LMDZ5/branches/testing/libf/dyn3dpar/disvert.F90
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/disvert.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/disvert.F90	(revision 1665)
@@ -4,4 +4,7 @@
 
   ! Auteur : P. Le Van
+
+  use new_unit_m, only: new_unit
+  use ioipsl, only: getin
 
   IMPLICIT NONE
@@ -26,20 +29,28 @@
   real zk, zkm1, dzk1, dzk2, k0, k1
 
-  INTEGER l
+  INTEGER l, unit
   REAL dsigmin
   REAL alpha, beta, deltaz
-  INTEGER iostat
   REAL x
   character(len=*),parameter :: modname="disvert"
 
+  character(len=6):: vert_sampling
+  ! (allowed values are "param", "tropo", "strato" and "read")
+
   !-----------------------------------------------------------------------
+
+  print *, "Call sequence information: disvert"
 
   ! default scaleheight is 8km for earth
   scaleheight=8.
 
-  OPEN(99, file='sigma.def', status='old', form='formatted', iostat=iostat)
+  vert_sampling = merge("strato", "tropo ", ok_strato) ! default value
+  call getin('vert_sampling', vert_sampling)
+  print *, 'vert_sampling = ' // vert_sampling
 
-  IF (iostat == 0) THEN
-     ! cas 1 on lit les options dans sigma.def:
+  select case (vert_sampling)
+  case ("param")
+     ! On lit les options dans sigma.def:
+     OPEN(99, file='sigma.def', status='old', form='formatted')
      READ(99, *) scaleheight ! hauteur d'echelle 8.
      READ(99, *) deltaz ! epaiseur de la premiere couche 0.04
@@ -68,32 +79,8 @@
 
      sig(llm+1)=0.
-
-     DO l = 1, llm
-        dsig(l) = sig(l)-sig(l+1)
-     end DO
-  ELSE
-     if (ok_strato) then
-        if (llm==39) then
-           dsigmin=0.3
-        else if (llm==50) then
-           dsigmin=1.
-        else
-           write(lunout,*) trim(modname), &
-           ' ATTENTION discretisation z a ajuster'
-           dsigmin=1.
-        endif
-        write(lunout,*) trim(modname), &
-        ' Discretisation verticale DSIGMIN=',dsigmin
-     endif
-
+  case("tropo")
      DO l = 1, llm
         x = 2*asin(1.) * (l - 0.5) / (llm + 1)
-
-        IF (ok_strato) THEN
-           dsig(l) =(dsigmin + 7. * SIN(x)**2) &
-                *(0.5*(1.-tanh(1.*(x-asin(1.))/asin(1.))))**2
-        ELSE
-           dsig(l) = 1.0 + 7.0 * SIN(x)**2
-        ENDIF
+        dsig(l) = 1.0 + 7.0 * SIN(x)**2
      ENDDO
      dsig = dsig / sum(dsig)
@@ -102,5 +89,37 @@
         sig(l) = sig(l+1) + dsig(l)
      ENDDO
-  ENDIF
+  case("strato")
+     if (llm==39) then
+        dsigmin=0.3
+     else if (llm==50) then
+        dsigmin=1.
+     else
+        write(lunout,*) trim(modname), ' ATTENTION discretisation z a ajuster'
+        dsigmin=1.
+     endif
+     WRITE(LUNOUT,*) trim(modname), 'Discretisation verticale DSIGMIN=',dsigmin
+
+     DO l = 1, llm
+        x = 2*asin(1.) * (l - 0.5) / (llm + 1)
+        dsig(l) =(dsigmin + 7. * SIN(x)**2) &
+             *(0.5*(1.-tanh(1.*(x-asin(1.))/asin(1.))))**2
+     ENDDO
+     dsig = dsig / sum(dsig)
+     sig(llm+1) = 0.
+     DO l = llm, 1, -1
+        sig(l) = sig(l+1) + dsig(l)
+     ENDDO
+  case("read")
+     call new_unit(unit)
+     open(unit, file="hybrid.txt", status="old", action="read", &
+          position="rewind")
+     read(unit, fmt=*) ! skip title line
+     do l = 1, llm + 1
+        read(unit, fmt=*) sig(l)
+     end do
+     close(unit)
+  case default
+     call abort_gcm("disvert", 'Wrong value for "vert_sampling"', 1)
+  END select
 
   DO l=1, llm
Index: LMDZ5/branches/testing/libf/dyn3dpar/dynetat0.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/dynetat0.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/dynetat0.F	(revision 1665)
@@ -119,4 +119,5 @@
       day_ini = tab_cntrl(30)
       itau_dyn = tab_cntrl(31)
+      start_time = tab_cntrl(32)
 c   .................................................................
 c
Index: LMDZ5/branches/testing/libf/dyn3dpar/dynredem.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/dynredem.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/dynredem.F	(revision 1665)
@@ -120,4 +120,6 @@
        tab_cntrl(30) = REAL(iday_end)
        tab_cntrl(31) = REAL(itau_dyn + itaufin)
+c start_time: start_time of simulation (not necessarily 0.)
+       tab_cntrl(32) = start_time
 c
 c    .........................................................
Index: LMDZ5/branches/testing/libf/dyn3dpar/dynredem_p.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/dynredem_p.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/dynredem_p.F	(revision 1665)
@@ -120,4 +120,6 @@
        tab_cntrl(30) =  REAL(iday_end)
        tab_cntrl(31) =  REAL(itau_dyn + itaufin)
+c start_time: start_time of simulation (not necessarily 0.)
+       tab_cntrl(32) = start_time
 c
 c    .........................................................
Index: LMDZ5/branches/testing/libf/dyn3dpar/etat0_netcdf.F90
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/etat0_netcdf.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/etat0_netcdf.F90	(revision 1665)
@@ -251,7 +251,7 @@
 !*******************************************************************************
   CALL pression(ip1jmp1, ap, bp, psol, p3d)
-  if (disvert_type.eq.1) then
+  if (pressure_exner) then
     CALL exner_hyb(ip1jmp1, psol, p3d, alpha, beta, pks, pk, y)
-  else ! we assume that we are in the disvert_type==2 case
+  else
     CALL exner_milieu(ip1jmp1,psol,p3d,beta,pks,pk,y)
   endif
Index: LMDZ5/branches/testing/libf/dyn3dpar/exner_hyb.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/exner_hyb.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/exner_hyb.F	(revision 1665)
@@ -56,11 +56,4 @@
       ! Sanity check
       if (firstcall) then
-        ! check that vertical discretization is compatible
-        ! with this routine
-        if (disvert_type.ne.1) then
-          call abort_gcm(modname,
-     &     "this routine should only be called if disvert_type==1",42)
-        endif
-        
         ! sanity checks for Shallow Water case (1 vertical layer)
         if (llm.eq.1) then
Index: LMDZ5/branches/testing/libf/dyn3dpar/exner_hyb_p.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/exner_hyb_p.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/exner_hyb_p.F	(revision 1665)
@@ -60,11 +60,4 @@
       ! Sanity check
       if (firstcall) then
-        ! check that vertical discretization is compatible
-        ! with this routine
-        if (disvert_type.ne.1) then
-          call abort_gcm(modname,
-     &     "this routine should only be called if disvert_type==1",42)
-        endif
-        
         ! sanity checks for Shallow Water case (1 vertical layer)
         if (llm.eq.1) then
Index: LMDZ5/branches/testing/libf/dyn3dpar/exner_milieu.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/exner_milieu.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/exner_milieu.F	(revision 1665)
@@ -53,11 +53,4 @@
       ! Sanity check
       if (firstcall) then
-        ! check that vertical discretization is compatible
-        ! with this routine
-        if (disvert_type.ne.2) then
-          call abort_gcm(modname,
-     &     "this routine should only be called if disvert_type==2",42)
-        endif
-        
         ! sanity checks for Shallow Water case (1 vertical layer)
         if (llm.eq.1) then
Index: LMDZ5/branches/testing/libf/dyn3dpar/exner_milieu_p.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/exner_milieu_p.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/exner_milieu_p.F	(revision 1665)
@@ -56,11 +56,4 @@
       ! Sanity check
       if (firstcall) then
-        ! check that vertical discretization is compatible
-        ! with this routine
-        if (disvert_type.ne.2) then
-          call abort_gcm(modname,
-     &     "this routine should only be called if disvert_type==2",42)
-        endif
-        
         ! sanity checks for Shallow Water case (1 vertical layer)
         if (llm.eq.1) then
Index: LMDZ5/branches/testing/libf/dyn3dpar/filtreg_p.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/filtreg_p.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/filtreg_p.F	(revision 1665)
@@ -208,24 +208,39 @@
                IF( ifiltre.EQ.-2 )   THEN
                   DO j = jdfil,jffil
+#ifdef BLAS
                      CALL DGEMM("N", "N", iim, nbniv_loc, iim, 1.0, 
      &                    matrinvn(1,1,j), iim, 
      &                    champ_loc(1,j,1), iip1*nlat, 0.0,
      &                    champ_fft(1,j-jdfil+1,1), iip1*nlat)
+#else
+                     champ_fft(:,j-jdfil+1,:)
+     &                    =matmul(matrinvn(:,:,j),champ_loc(:iim,j,:))
+#endif
                   ENDDO
                   
                ELSE IF ( griscal )     THEN
                   DO j = jdfil,jffil
+#ifdef BLAS
                      CALL DGEMM("N", "N", iim, nbniv_loc, iim, 1.0, 
      &                    matriceun(1,1,j), iim, 
      &                    champ_loc(1,j,1), iip1*nlat, 0.0,
      &                    champ_fft(1,j-jdfil+1,1), iip1*nlat)
+#else
+                     champ_fft(:,j-jdfil+1,:)
+     &                    =matmul(matriceun(:,:,j),champ_loc(:iim,j,:))
+#endif
                   ENDDO
                   
                ELSE 
                   DO j = jdfil,jffil
+#ifdef BLAS
                      CALL DGEMM("N", "N", iim, nbniv_loc, iim, 1.0, 
      &                    matricevn(1,1,j), iim, 
      &                    champ_loc(1,j,1), iip1*nlat, 0.0, 
      &                    champ_fft(1,j-jdfil+1,1), iip1*nlat)
+#else
+                     champ_fft(:,j-jdfil+1,:)
+     &                    =matmul(matricevn(:,:,j),champ_loc(:iim,j,:))
+#endif
                   ENDDO
                   
@@ -236,8 +251,14 @@
                IF( ifiltre.EQ.-2 )   THEN
                   DO j = jdfil,jffil
+#ifdef BLAS
                      CALL DGEMM("N", "N", iim, nbniv_loc, iim, 1.0, 
      &                    matrinvs(1,1,j-jfiltsu+1), iim, 
      &                    champ_loc(1,j,1), iip1*nlat, 0.0, 
      &                    champ_fft(1,j-jdfil+1,1), iip1*nlat)
+#else
+                     champ_fft(:,j-jdfil+1,:)
+     &                    =matmul(matrinvs(:,:,j-jfiltsu+1),
+     &                            champ_loc(:iim,j,:))
+#endif
                   ENDDO
                   
@@ -245,8 +266,14 @@
                   
                   DO j = jdfil,jffil
+#ifdef BLAS
                      CALL DGEMM("N", "N", iim, nbniv_loc, iim, 1.0, 
      &                    matriceus(1,1,j-jfiltsu+1), iim, 
      &                    champ_loc(1,j,1), iip1*nlat, 0.0, 
      &                    champ_fft(1,j-jdfil+1,1), iip1*nlat)
+#else
+                     champ_fft(:,j-jdfil+1,:)
+     &                    =matmul(matriceus(:,:,j-jfiltsu+1),
+     &                            champ_loc(:iim,j,:))
+#endif
                   ENDDO
                   
@@ -254,8 +281,14 @@
                   
                   DO j = jdfil,jffil
+#ifdef BLAS
                      CALL DGEMM("N", "N", iim, nbniv_loc, iim, 1.0, 
      &                    matricevs(1,1,j-jfiltsv+1), iim, 
      &                    champ_loc(1,j,1), iip1*nlat, 0.0, 
      &                    champ_fft(1,j-jdfil+1,1), iip1*nlat)
+#else
+                     champ_fft(:,j-jdfil+1,:)
+     &                    =matmul(matricevs(:,:,j-jfiltsv+1),
+     &                            champ_loc(:iim,j,:))
+#endif
                   ENDDO
                   
Index: LMDZ5/branches/testing/libf/dyn3dpar/gcm.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/gcm.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/gcm.F	(revision 1665)
@@ -20,6 +20,5 @@
       USE control_mod
 
-! Ehouarn: for now these only apply to Earth:
-#ifdef CPP_EARTH
+#ifdef CPP_PHYS
       USE mod_grid_phy_lmdz
       USE mod_phys_lmdz_para, ONLY : klon_mpi_para_nb
@@ -87,6 +86,4 @@
 
       REAL zdtvr
-c      INTEGER nbetatmoy, nbetatdem,nbetat
-      INTEGER nbetatmoy, nbetatdem
 
 c   variables dynamiques
@@ -189,13 +186,10 @@
       call ini_getparam("out.def")
       call Read_Distrib
-! Ehouarn : temporarily (?) keep this only for Earth
-      if (planet_type.eq."earth") then
-#ifdef CPP_EARTH
+
+#ifdef CPP_PHYS
         CALL Init_Phys_lmdz(iim,jjp1,llm,mpi_size,distrib_phys)
 #endif
-      endif ! of if (planet_type.eq."earth")
       CALL set_bands
-#ifdef CPP_EARTH
-! Ehouarn: For now only Earth physics is parallel
+#ifdef CPP_PHYS
       CALL Init_interface_dyn_phys
 #endif
@@ -209,12 +203,9 @@
 c$OMP END PARALLEL
 
-! Ehouarn : temporarily (?) keep this only for Earth
-      if (planet_type.eq."earth") then
-#ifdef CPP_EARTH
+#ifdef CPP_PHYS
 c$OMP PARALLEL
       call InitComgeomphy
 c$OMP END PARALLEL 
 #endif
-      endif ! of if (planet_type.eq."earth")
 
 c-----------------------------------------------------------------------
@@ -323,4 +314,15 @@
 C on remet le calendrier à zero si demande
 c
+      IF (start_time /= starttime) then
+        WRITE(lunout,*)' GCM: Attention l''heure de depart lue dans le'
+     &,' fichier restart ne correspond pas à celle lue dans le run.def'
+        IF (raz_date == 1) then
+          WRITE(lunout,*)'Je prends l''heure lue dans run.def'
+          start_time = starttime
+        ELSE
+          WRITE(lunout,*)'Je m''arrete'
+          CALL abort
+        ENDIF
+      ENDIF
       IF (raz_date == 1) THEN
         annee_ref = anneeref
@@ -390,7 +392,4 @@
 #endif
 
-c  nombre d'etats dans les fichiers demarrage et histoire
-      nbetatdem = nday / iecri
-      nbetatmoy = nday / periodav + 1
 
       if (iflag_phys.eq.1) then
@@ -445,11 +444,9 @@
          WRITE(lunout,*)
      .       'GCM: WARNING!!! vitesse verticale nulle dans la physique'
-! Earth:
-         if (planet_type.eq."earth") then
-#ifdef CPP_EARTH
+! Physics:
+#ifdef CPP_PHYS
          CALL iniphysiq(ngridmx,llm,daysec,day_ini,dtphys/nsplit_phys ,
      ,                latfi,lonfi,airefi,zcufi,zcvfi,rad,g,r,cpp     )
 #endif
-         endif ! of if (planet_type.eq."earth")
          call_iniphys=.false.
       ENDIF ! of IF (call_iniphys.and.(iflag_phys.eq.1))
@@ -484,4 +481,12 @@
  301  FORMAT('1'/,15x,'run du ', i2,'/',i2,'/',i4)
  302  FORMAT('1'/,15x,'    au ', i2,'/',i2,'/',i4)
+#endif
+
+#ifdef CPP_PHYS
+! Create start file (startphy.nc) and boundary conditions (limit.nc) 
+! for the Earth verstion
+       if (iflag_phys>=100) then
+          call iniaqua(ngridmx,latfi,lonfi,iflag_phys)
+       endif
 #endif
 
Index: LMDZ5/branches/testing/libf/dyn3dpar/gr_dyn_fi_p.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/gr_dyn_fi_p.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/gr_dyn_fi_p.F	(revision 1665)
@@ -3,7 +3,6 @@
 !
       SUBROUTINE gr_dyn_fi_p(nfield,im,jm,ngrid,pdyn,pfi)
-#ifdef CPP_EARTH
+#ifdef CPP_PHYS
 ! Interface with parallel physics,
-! for now this routine only works with Earth physics
       USE mod_interface_dyn_phys
       USE dimphy
@@ -40,10 +39,6 @@
       ENDDO
 c$OMP END DO NOWAIT
-#else
-      write(lunout,*) "gr_fi_dyn_p : This routine should not be called",
-     &   "without parallelized physics"
-      stop
 #endif
-! of #ifdef CPP_EARTH
+! of #ifdef CPP_PHYS
       RETURN
       END
Index: LMDZ5/branches/testing/libf/dyn3dpar/gr_fi_dyn_p.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/gr_fi_dyn_p.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/gr_fi_dyn_p.F	(revision 1665)
@@ -3,7 +3,6 @@
 !
       SUBROUTINE gr_fi_dyn_p(nfield,ngrid,im,jm,pfi,pdyn)
-#ifdef CPP_EARTH
+#ifdef CPP_PHYS
 ! Interface with parallel physics,
-! for now this routine only works with Earth physics
       USE mod_interface_dyn_phys
       USE dimphy
@@ -52,10 +51,6 @@
       ENDDO
 c$OMP END DO NOWAIT
-#else
-      write(lunout,*) "gr_fi_dyn_p : This routine should not be called",
-     &   "without parallelized physics"
-      stop
 #endif
-! of #ifdef CPP_EARTH
+! of #ifdef CPP_PHYS
       RETURN
       END
Index: LMDZ5/branches/testing/libf/dyn3dpar/guide_p_mod.F90
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/guide_p_mod.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/guide_p_mod.F90	(revision 1665)
@@ -455,5 +455,5 @@
 !       Calcul niveaux pression milieu de couches 
 	CALL pression_p( ip1jmp1, ap, bp, ps, p )
-	if (disvert_type==1) then
+	if (pressure_exner) then
           CALL exner_hyb_p(ip1jmp1,ps,p,alpha,beta,pks,pk,pkf)
 	else
@@ -755,7 +755,7 @@
     ELSE
 	CALL pression_p( ip1jmp1, ap, bp, psi, p )
-	if (disvert_type==1) then
+	if (pressure_exner) then
           CALL exner_hyb_p(ip1jmp1,psi,p,alpha,beta,pks,pk,pkf)
-        else ! we assume that we are in the disvert_type==2 case
+        else
           CALL exner_milieu_p(ip1jmp1,psi,p,beta,pks,pk,pkf)
         endif
Index: LMDZ5/branches/testing/libf/dyn3dpar/iniacademic.F90
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/iniacademic.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/iniacademic.F90	(revision 1665)
@@ -222,12 +222,8 @@
 
         CALL pression ( ip1jmp1, ap, bp, ps, p       )
-        if (disvert_type.eq.1) then
+        if (pressure_exner) then
           CALL exner_hyb( ip1jmp1, ps, p,alpha,beta, pks, pk, pkf )
-        elseif (disvert_type.eq.2) then
+        else
           call exner_milieu(ip1jmp1,ps,p,beta,pks,pk,pkf)
-        else
-          write(abort_message,*) "Wrong value for disvert_type: ", &
-                              disvert_type
-          call abort_gcm(modname,abort_message,0)
         endif
         CALL massdair(p,masse)
Index: LMDZ5/branches/testing/libf/dyn3dpar/iniconst.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/iniconst.F	(revision 1664)
+++ 	(revision )
@@ -1,84 +1,0 @@
-!
-! $Id$
-!
-      SUBROUTINE iniconst
-
-      USE control_mod
-#ifdef CPP_IOIPSL
-      use IOIPSL
-#else
-! if not using IOIPSL, we still need to use (a local version of) getin
-      use ioipsl_getincom
-#endif
-
-      IMPLICIT NONE
-c
-c      P. Le Van
-c
-c-----------------------------------------------------------------------
-c   Declarations:
-c   -------------
-c
-#include "dimensions.h"
-#include "paramet.h"
-#include "comconst.h"
-#include "temps.h"
-#include "comvert.h"
-#include "iniprint.h"
-
-      character(len=*),parameter :: modname="iniconst"
-      character(len=80) :: abort_message
-c
-c
-c
-c-----------------------------------------------------------------------
-c   dimension des boucles:
-c   ----------------------
-
-      im      = iim
-      jm      = jjm
-      lllm    = llm
-      imp1    = iim 
-      jmp1    = jjm + 1
-      lllmm1  = llm - 1
-      lllmp1  = llm + 1
-
-c-----------------------------------------------------------------------
-
-      dtphys  = iphysiq * dtvr
-      unsim   = 1./iim
-      pi      = 2.*ASIN( 1. )
-
-c-----------------------------------------------------------------------
-c
-
-      r       = cpp * kappa
-
-      write(lunout,*) trim(modname),': R  CP  Kappa ',r,cpp,kappa
-c
-c-----------------------------------------------------------------------
-
-! vertical discretization: default behavior depends on planet_type flag
-      if (planet_type=="earth") then
-        disvert_type=1
-      else
-        disvert_type=2
-      endif
-      ! but user can also specify using one or the other in run.def:
-      call getin('disvert_type',disvert_type)
-      write(lunout,*) trim(modname),': disvert_type=',disvert_type
-      
-      if (disvert_type==1) then
-       ! standard case for Earth (automatic generation of levels)
-       call disvert(pa,preff,ap,bp,dpres,presnivs,nivsigs,nivsig,
-     &              scaleheight)
-      else if (disvert_type==2) then
-        ! standard case for planets (levels generated using z2sig.def file)
-        call disvert_noterre
-      else
-        write(abort_message,*) "Wrong value for disvert_type: ",
-     &                        disvert_type
-        call abort_gcm(modname,abort_message,0)
-      endif
-
-      END
Index: LMDZ5/branches/testing/libf/dyn3dpar/iniconst.F90
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/iniconst.F90	(revision 1665)
+++ LMDZ5/branches/testing/libf/dyn3dpar/iniconst.F90	(revision 1665)
@@ -0,0 +1,84 @@
+!
+! $Id$
+!
+SUBROUTINE iniconst
+
+  USE control_mod
+#ifdef CPP_IOIPSL
+  use IOIPSL
+#else
+  ! if not using IOIPSL, we still need to use (a local version of) getin
+  use ioipsl_getincom
+#endif
+
+  IMPLICIT NONE
+  !
+  !      P. Le Van
+  !
+  !   Declarations:
+  !   -------------
+  !
+  include "dimensions.h"
+  include "paramet.h"
+  include "comconst.h"
+  include "temps.h"
+  include "comvert.h"
+  include "iniprint.h"
+
+  character(len=*),parameter :: modname="iniconst"
+  character(len=80) :: abort_message
+  !
+  !
+  !
+  !-----------------------------------------------------------------------
+  !   dimension des boucles:
+  !   ----------------------
+
+  im      = iim
+  jm      = jjm
+  lllm    = llm
+  imp1    = iim 
+  jmp1    = jjm + 1
+  lllmm1  = llm - 1
+  lllmp1  = llm + 1
+
+  !-----------------------------------------------------------------------
+
+  dtphys  = iphysiq * dtvr
+  unsim   = 1./iim
+  pi      = 2.*ASIN( 1. )
+
+  !-----------------------------------------------------------------------
+  !
+
+  r       = cpp * kappa
+
+  write(lunout,*) trim(modname),': R  CP  Kappa ',r,cpp,kappa
+  !
+  !-----------------------------------------------------------------------
+
+  ! vertical discretization: default behavior depends on planet_type flag
+  if (planet_type=="earth") then
+     disvert_type=1
+  else
+     disvert_type=2
+  endif
+  ! but user can also specify using one or the other in run.def:
+  call getin('disvert_type',disvert_type)
+  write(lunout,*) trim(modname),': disvert_type=',disvert_type
+
+  pressure_exner = disvert_type == 1 ! default value
+  call getin('pressure_exner', pressure_exner)
+
+  if (disvert_type==1) then
+     ! standard case for Earth (automatic generation of levels)
+     call disvert(pa,preff,ap,bp,dpres,presnivs,nivsigs,nivsig, scaleheight)
+  else if (disvert_type==2) then
+     ! standard case for planets (levels generated using z2sig.def file)
+     call disvert_noterre
+  else
+     write(abort_message,*) "Wrong value for disvert_type: ", disvert_type
+     call abort_gcm(modname,abort_message,0)
+  endif
+
+END SUBROUTINE iniconst
Index: LMDZ5/branches/testing/libf/dyn3dpar/inidissip.F90
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/inidissip.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/inidissip.F90	(revision 1665)
@@ -28,7 +28,8 @@
 ! Local variables:
   REAL fact,zvert(llm),zz
-  REAL zh(ip1jmp1),zu(ip1jmp1),zv(ip1jm),deltap(ip1jmp1,llm)
+  REAL zh(ip1jmp1),zu(ip1jmp1), gx(ip1jmp1), divgra(ip1jmp1)
+  real zv(ip1jm), gy(ip1jm), deltap(ip1jmp1,llm)
   REAL ullm,vllm,umin,vmin,zhmin,zhmax
-  REAL zllm,z1llm
+  REAL zllm
 
   INTEGER l,ij,idum,ii
@@ -78,16 +79,11 @@
   DO l = 1,50
      IF(lstardis) THEN
-        CALL divgrad2(1,zh,deltap,niterh,zh)
+        CALL divgrad2(1,zh,deltap,niterh,divgra)
      ELSE
-        CALL divgrad (1,zh,niterh,zh)
+        CALL divgrad (1,zh,niterh,divgra)
      ENDIF
 
-     CALL minmax(iip1*jjp1,zh,zhmin,zhmax )
-
-     zllm  = ABS( zhmax )
-     z1llm = 1./zllm
-     DO ij = 1,ip1jmp1
-        zh(ij) = zh(ij)* z1llm
-     ENDDO
+     zllm  = ABS(maxval(divgra))
+     zh = divgra / zllm
   ENDDO
 
@@ -123,30 +119,19 @@
            !cccc             CALL covcont( 1,zu,zv,zu,zv )
            IF(lstardis) THEN
-              CALL gradiv2( 1,zu,zv,nitergdiv,zu,zv )
+              CALL gradiv2( 1,zu,zv,nitergdiv,gx,gy )
            ELSE
-              CALL gradiv ( 1,zu,zv,nitergdiv,zu,zv )
+              CALL gradiv ( 1,zu,zv,nitergdiv,gx,gy )
            ENDIF
         ELSE
            IF(lstardis) THEN
-              CALL nxgraro2( 1,zu,zv,nitergrot,zu,zv )
+              CALL nxgraro2( 1,zu,zv,nitergrot,gx,gy )
            ELSE
-              CALL nxgrarot( 1,zu,zv,nitergrot,zu,zv )
+              CALL nxgrarot( 1,zu,zv,nitergrot,gx,gy )
            ENDIF
         ENDIF
 
-        CALL minmax(iip1*jjp1,zu,umin,ullm )
-        CALL minmax(iip1*jjm, zv,vmin,vllm )
-
-        ullm = ABS  ( ullm )
-        vllm = ABS  ( vllm )
-
-        zllm  = MAX( ullm,vllm )
-        z1llm = 1./ zllm
-        DO ij = 1, ip1jmp1
-           zu(ij) = zu(ij)* z1llm
-        ENDDO
-        DO ij = 1, ip1jm
-           zv(ij) = zv(ij)* z1llm
-        ENDDO
+        zllm = max(abs(maxval(gx)), abs(maxval(gy)))
+        zu = gx / zllm
+        zv = gy / zllm
      end DO
 
Index: LMDZ5/branches/testing/libf/dyn3dpar/inigrads.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/inigrads.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/inigrads.F	(revision 1665)
@@ -9,5 +9,5 @@
       implicit none
 
-      integer if,im,jm,lm,i,j,l,lnblnk
+      integer if,im,jm,lm,i,j,l
       real x(im),y(jm),z(lm),fx,fy,fz,dt
       real xmin,xmax,ymin,ymax
@@ -40,5 +40,5 @@
       ivar(if)=0
 
-      fichier(if)=file(1:lnblnk(file))
+      fichier(if)=trim(file)
 
       firsttime(if)=.true.
@@ -70,7 +70,7 @@
 
       print*,4*(ifd(if)-iid(if))*(jfd(if)-jid(if))
-      print*,file(1:lnblnk(file))//'.dat'
+      print*,trim(file)//'.dat'
 
-      OPEN (unit(if)+1,FILE=file(1:lnblnk(file))//'.dat'
+      OPEN (unit(if)+1,FILE=trim(file)//'.dat'
      s   ,FORM='unformatted',
      s   ACCESS='direct'
Index: LMDZ5/branches/testing/libf/dyn3dpar/integrd_p.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/integrd_p.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/integrd_p.F	(revision 1665)
@@ -4,5 +4,5 @@
       SUBROUTINE integrd_p
      $  (  nq,vcovm1,ucovm1,tetam1,psm1,massem1,
-     $     dv,du,dteta,dq,dp,vcov,ucov,teta,q,ps0,masse,phis,finvmaold)
+     $     dv,du,dteta,dq,dp,vcov,ucov,teta,q,ps0,masse,phis) !,finvmaold)
       USE parallel
       USE control_mod, only : planet_type
@@ -33,20 +33,30 @@
 #include "temps.h"
 #include "serre.h"
+#include "iniprint.h"
 
 c   Arguments:
 c   ----------
 
-      INTEGER nq
-
-      REAL vcov(ip1jm,llm),ucov(ip1jmp1,llm),teta(ip1jmp1,llm)
-      REAL q(ip1jmp1,llm,nq)
-      REAL ps0(ip1jmp1),masse(ip1jmp1,llm),phis(ip1jmp1)
-
-      REAL vcovm1(ip1jm,llm),ucovm1(ip1jmp1,llm)
-      REAL tetam1(ip1jmp1,llm),psm1(ip1jmp1),massem1(ip1jmp1,llm)
-
-      REAL dv(ip1jm,llm),du(ip1jmp1,llm)
-      REAL dteta(ip1jmp1,llm),dp(ip1jmp1)
-      REAL dq(ip1jmp1,llm,nq), finvmaold(ip1jmp1,llm)
+      integer,intent(in) :: nq ! number of tracers to handle in this routine
+      real,intent(inout) :: vcov(ip1jm,llm) ! covariant meridional wind
+      real,intent(inout) :: ucov(ip1jmp1,llm) ! covariant zonal wind
+      real,intent(inout) :: teta(ip1jmp1,llm) ! potential temperature
+      real,intent(inout) :: q(ip1jmp1,llm,nq) ! advected tracers
+      real,intent(inout) :: ps0(ip1jmp1) ! surface pressure
+      real,intent(inout) :: masse(ip1jmp1,llm) ! atmospheric mass
+      real,intent(in) :: phis(ip1jmp1) ! ground geopotential !!! unused
+      ! values at previous time step
+      real,intent(inout) :: vcovm1(ip1jm,llm)
+      real,intent(inout) :: ucovm1(ip1jmp1,llm)
+      real,intent(inout) :: tetam1(ip1jmp1,llm)
+      real,intent(inout) :: psm1(ip1jmp1)
+      real,intent(inout) :: massem1(ip1jmp1,llm)
+      ! the tendencies to add
+      real,intent(in) :: dv(ip1jm,llm)
+      real,intent(in) :: du(ip1jmp1,llm)
+      real,intent(in) :: dteta(ip1jmp1,llm)
+      real,intent(in) :: dp(ip1jmp1)
+      real,intent(in) :: dq(ip1jmp1,llm,nq) !!! unused
+!      real,intent(out) :: finvmaold(ip1jmp1,llm) !!! unused
 
 c   Local:
@@ -54,5 +64,6 @@
 
       REAL vscr( ip1jm ),uscr( ip1jmp1 ),hscr( ip1jmp1 ),pscr(ip1jmp1)
-      REAL massescr( ip1jmp1,llm ), finvmasse(ip1jmp1,llm)
+      REAL massescr( ip1jmp1,llm )
+!      REAL finvmasse(ip1jmp1,llm)
       REAL,SAVE :: p(ip1jmp1,llmp1)
       REAL tpn,tps,tppn(iim),tpps(iim)
@@ -60,5 +71,5 @@
       REAL,SAVE :: deltap( ip1jmp1,llm )
 
-      INTEGER  l,ij,iq
+      INTEGER  l,ij,iq,i,j
 
       REAL SSUM
@@ -126,8 +137,12 @@
        
         IF( .NOT. checksum ) THEN
-         PRINT*,' Au point ij = ',stop_it, ' , pression sol neg. '
-     &         , ps(stop_it)
-         print *, ' dans integrd'
-         stop 1
+         write(lunout,*) "integrd: negative surface pressure ",
+     &                                                ps(stop_it)
+         write(lunout,*) " at node ij =", stop_it
+         ! since ij=j+(i-1)*jjp1 , we have
+         j=modulo(stop_it,jjp1)
+         i=1+(stop_it-j)/jjp1
+         write(lunout,*) " lon = ",rlonv(i)*180./pi, " deg",
+     &                   " lat = ",rlatu(j)*180./pi, " deg"
         ENDIF
 
@@ -167,17 +182,19 @@
       CALL massdair_p (     p  , masse         )
 
-c      CALL   SCOPY( ijp1llm  , masse, 1, finvmasse,  1      )
-      ijb=ij_begin
-      ije=ij_end
-      
-c$OMP DO SCHEDULE(STATIC,OMP_CHUNK) 
-      DO  l = 1,llm
-        finvmasse(ijb:ije,l)=masse(ijb:ije,l)
-      ENDDO
-c$OMP END DO NOWAIT
-
-      jjb=jj_begin
-      jje=jj_end
-      CALL filtreg_p( finvmasse,jjb,jje, jjp1, llm, -2, 2, .TRUE., 1  )
+! Ehouarn : we don't use/need finvmaold and finvmasse,
+!           so might as well not compute them
+!c      CALL   SCOPY( ijp1llm  , masse, 1, finvmasse,  1      )
+!      ijb=ij_begin
+!      ije=ij_end
+!      
+!c$OMP DO SCHEDULE(STATIC,OMP_CHUNK) 
+!      DO  l = 1,llm
+!        finvmasse(ijb:ije,l)=masse(ijb:ije,l)
+!      ENDDO
+!c$OMP END DO NOWAIT
+!
+!      jjb=jj_begin
+!      jje=jj_end
+!      CALL filtreg_p( finvmasse,jjb,jje, jjp1, llm, -2, 2, .TRUE., 1  )
 c
 
@@ -330,11 +347,12 @@
       ENDIF
       
-c         CALL  SCOPY( ijp1llm , finvmasse, 1, finvmaold, 1 )
-
-c$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
-      DO l = 1, llm      
-        finvmaold(ijb:ije,l)=finvmasse(ijb:ije,l)        
-      ENDDO
-c$OMP END DO NOWAIT
+! Ehouarn: forget about finvmaold
+!c         CALL  SCOPY( ijp1llm , finvmasse, 1, finvmaold, 1 )
+!
+!c$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
+!      DO l = 1, llm      
+!        finvmaold(ijb:ije,l)=finvmasse(ijb:ije,l)        
+!      ENDDO
+!c$OMP END DO NOWAIT
 
       endif ! of if (planet_type.eq."earth")
Index: LMDZ5/branches/testing/libf/dyn3dpar/leapfrog_p.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/leapfrog_p.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/leapfrog_p.F	(revision 1665)
@@ -75,5 +75,4 @@
 
       real zqmin,zqmax
-      INTEGER nbetatmoy, nbetatdem,nbetat
 
 c   variables dynamiques
@@ -125,5 +124,5 @@
       REAL  SSUM
       REAL time_0 
-      REAL,SAVE :: finvmaold(ip1jmp1,llm)
+!      REAL,SAVE :: finvmaold(ip1jmp1,llm)
 
 cym      LOGICAL  lafin
@@ -234,7 +233,7 @@
       dq(:,:,:)=0.
       CALL pression ( ip1jmp1, ap, bp, ps, p       )
-      if (disvert_type==1) then
+      if (pressure_exner) then
         CALL exner_hyb( ip1jmp1, ps, p,alpha,beta, pks, pk, pkf )
-      else ! we assume that we are in the disvert_type==2 case
+      else
         CALL exner_milieu( ip1jmp1, ps, p, beta, pks, pk, pkf )
       endif
@@ -245,9 +244,14 @@
 c et du parallelisme !!
 
-   1  CONTINUE
-
-      jD_cur = jD_ref + day_ini - day_ref + int (itau * dtvr / daysec) 
-      jH_cur = jH_ref +                                                 &
-     &          (itau * dtvr / daysec - int(itau * dtvr / daysec)) 
+   1  CONTINUE ! Matsuno Forward step begins here
+
+      jD_cur = jD_ref + day_ini - day_ref +                             &
+     &          itau/day_step
+      jH_cur = jH_ref + start_time +                                    &
+     &         mod(itau,day_step)/float(day_step) 
+      if (jH_cur > 1.0 ) then
+        jD_cur = jD_cur +1.
+        jH_cur = jH_cur -1.
+      endif
 
 
@@ -280,7 +284,8 @@
          massem1= masse
          psm1= ps
-         
-         finvmaold = masse
-         CALL filtreg ( finvmaold ,jjp1, llm, -2,2, .TRUE., 1 )
+
+! Ehouarn: finvmaold is actually not used       
+!         finvmaold = masse
+!         CALL filtreg ( finvmaold ,jjp1, llm, -2,2, .TRUE., 1 )
 c$OMP END MASTER
 c$OMP BARRIER
@@ -300,5 +305,5 @@
            tetam1   (ijb:ije,l) = teta  (ijb:ije,l)
            massem1  (ijb:ije,l) = masse (ijb:ije,l)
-           finvmaold(ijb:ije,l)=masse(ijb:ije,l)
+!           finvmaold(ijb:ije,l)=masse(ijb:ije,l)
                  
            if (pole_sud) ije=ij_end-iip1
@@ -309,7 +314,7 @@
 c$OMP ENDDO  
 
-
-          CALL filtreg_p ( finvmaold ,jj_begin,jj_end,jjp1, 
-     .                    llm, -2,2, .TRUE., 1 )
+! Ehouarn: finvmaold not used
+!          CALL filtreg_p ( finvmaold ,jj_begin,jj_end,jjp1, 
+!     .                    llm, -2,2, .TRUE., 1 )
 
        endif ! of if (FirstCaldyn)
@@ -327,5 +332,5 @@
 cym      call minmax(ijp1llm,q(:,:,3),zqmin,zqmax)
 
-   2  CONTINUE
+   2  CONTINUE ! Matsuno backward or leapfrog step begins here
 
 c$OMP MASTER
@@ -472,6 +477,6 @@
          call Register_SwapFieldHallo(phi,phi,ip1jmp1,llm,
      &                                jj_Nb_caldyn,0,0,TestRequest)
-         call Register_SwapFieldHallo(finvmaold,finvmaold,ip1jmp1,llm,
-     &                                jj_Nb_caldyn,0,0,TestRequest)
+!         call Register_SwapFieldHallo(finvmaold,finvmaold,ip1jmp1,llm,
+!     &                                jj_Nb_caldyn,0,0,TestRequest)
  
         do j=1,nqtot
@@ -555,4 +560,5 @@
       call start_timer(timer_caldyn)
 
+      ! compute geopotential phi()
       CALL geopot_p  ( ip1jmp1, teta  , pk , pks,  phis  , phi   )
 
@@ -629,6 +635,6 @@
 
        CALL integrd_p ( 2,vcovm1,ucovm1,tetam1,psm1,massem1 ,
-     $         dv,du,dteta,dq,dp,vcov,ucov,teta,q,ps,masse,phis ,
-     $              finvmaold                                    )
+     $         dv,du,dteta,dq,dp,vcov,ucov,teta,q,ps,masse,phis )
+!     $              finvmaold                                    )
 
 !       CALL FTRACE_REGION_END("integrd")
@@ -693,15 +699,19 @@
 
 c$OMP BARRIER
-         if (disvert_type==1) then
+         if (pressure_exner) then
            CALL exner_hyb_p(  ip1jmp1, ps, p,alpha,beta,pks, pk, pkf )
-         else ! we assume that we are in the disvert_type==2 case
+         else
            CALL exner_milieu_p( ip1jmp1, ps, p, beta, pks, pk, pkf )
          endif
 c$OMP BARRIER
            jD_cur = jD_ref + day_ini - day_ref
-     $        + int (itau * dtvr / daysec) 
-           jH_cur = jH_ref +                                            &
-     &              (itau * dtvr / daysec - int(itau * dtvr / daysec)) 
+     $        + itau/day_step
+           jH_cur = jH_ref + start_time +                                &
+     &              mod(itau,day_step)/float(day_step) 
 !         call ju2ymds(jD_cur+jH_cur, an, mois, jour, secondes)
+           if (jH_cur > 1.0 ) then
+             jD_cur = jD_cur +1.
+             jH_cur = jH_cur -1.
+           endif
 
 c rajout debug
@@ -719,6 +729,8 @@
 ! Ehouarn: be careful, diagedyn is Earth-specific (includes ../phylmd/..)!
            IF (planet_type.eq."earth") THEN
+#ifdef CPP_EARTH
             CALL diagedyn(ztit,2,1,1,dtphys
      &    , ucov    , vcov , ps, p ,pk , teta , q(:,:,1), q(:,:,2))
+#endif
            ENDIF
       ENDIF 
@@ -1036,7 +1048,7 @@
         CALL pression_p ( ip1jmp1, ap, bp, ps, p                  )
 c$OMP BARRIER
-        if (disvert_type==1) then
+        if (pressure_exner) then
           CALL exner_hyb_p( ip1jmp1, ps, p,alpha,beta, pks, pk, pkf )
-        else ! we assume that we are in the disvert_type==2 case
+        else
           CALL exner_milieu_p( ip1jmp1, ps, p, beta, pks, pk, pkf )
         endif
@@ -1185,4 +1197,8 @@
 c$OMP END DO NOWAIT
 
+         if (1 == 0) then
+!!! Ehouarn: lines here 1) kill 1+1=2 in the dynamics
+!!!                     2) should probably not be here anyway
+!!! but are kept for those who would want to revert to previous behaviour
 c$OMP MASTER               
           DO ij =  1,iim
@@ -1195,5 +1211,6 @@
           ENDDO
 c$OMP END MASTER
-        endif
+         endif ! of if (1 == 0)
+        endif ! of of (pole_nord)
         
         if (pole_sud) then
@@ -1211,4 +1228,8 @@
 c$OMP END DO NOWAIT
 
+         if (1 == 0) then
+!!! Ehouarn: lines here 1) kill 1+1=2 in the dynamics
+!!!                     2) should probably not be here anyway
+!!! but are kept for those who would want to revert to previous behaviour
 c$OMP MASTER               
           DO ij =  1,iim
@@ -1221,5 +1242,6 @@
           ENDDO
 c$OMP END MASTER
-        endif
+         endif ! of if (1 == 0)
+        endif ! of if (pole_sud)
 
 
@@ -1431,5 +1453,4 @@
 c$OMP BARRIER
 c$OMP MASTER
-              nbetat = nbetatdem
               CALL geopot_p(ip1jmp1,teta,pk,pks,phis,phi)
        
@@ -1634,5 +1655,4 @@
 c$OMP BARRIER
 c$OMP MASTER
-                nbetat = nbetatdem
                 CALL geopot_p(ip1jmp1,teta,pk,pks,phis,phi)
 
Index: LMDZ5/branches/testing/libf/dyn3dpar/mod_interface_dyn_phys.F90
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/mod_interface_dyn_phys.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/mod_interface_dyn_phys.F90	(revision 1665)
@@ -7,7 +7,6 @@
   
   
-#ifdef CPP_EARTH
+#ifdef CPP_PHYS
 ! Interface with parallel physics,
-! for now this routine only works with Earth physics
 CONTAINS
   
@@ -56,4 +55,4 @@
   END SUBROUTINE Init_interface_dyn_phys 
 #endif
-! of #ifdef CPP_EARTH
+! of #ifdef CPP_PHYS
 END MODULE mod_interface_dyn_phys
Index: LMDZ5/branches/testing/libf/dyn3dpar/temps.h
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/temps.h	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/temps.h	(revision 1665)
@@ -14,10 +14,12 @@
 
       COMMON/temps/itaufin, dt, day_ini, day_end, annee_ref, day_ref,   &
-     &             itau_dyn, itau_phy, jD_ref, jH_ref, calend
+     &             itau_dyn, itau_phy, jD_ref, jH_ref, calend,          &
+     &             start_time
+
 
       INTEGER   itaufin
       INTEGER itau_dyn, itau_phy
       INTEGER day_ini, day_end, annee_ref, day_ref
-      REAL      dt, jD_ref, jH_ref
+      REAL      dt, jD_ref, jH_ref, start_time
       CHARACTER (len=10) :: calend
 
Index: LMDZ5/branches/testing/libf/dyn3dpar/wrgrads.F
===================================================================
--- LMDZ5/branches/testing/libf/dyn3dpar/wrgrads.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/dyn3dpar/wrgrads.F	(revision 1665)
@@ -22,5 +22,5 @@
 c   local
 
-      integer im,jm,lm,i,j,l,lnblnk,iv,iii,iji,iif,ijf
+      integer im,jm,lm,i,j,l,iv,iii,iji,iif,ijf
 
       logical writectl
@@ -55,5 +55,5 @@
             nvar(if)=ivar(if)
             var(ivar(if),if)=name
-            tvar(ivar(if),if)=titlevar(1:lnblnk(titlevar))
+            tvar(ivar(if),if)=trim(titlevar)
             nld(ivar(if),if)=nl
             print*,'initialisation ecriture de ',var(ivar(if),if)
@@ -96,8 +96,8 @@
       file=fichier(if)
 c   WARNING! on reecrase le fichier .ctl a chaque ecriture
-      open(unit(if),file=file(1:lnblnk(file))//'.ctl'
+      open(unit(if),file=trim(file)//'.ctl'
      &         ,form='formatted',status='unknown')
       write(unit(if),'(a5,1x,a40)')
-     &       'DSET ','^'//file(1:lnblnk(file))//'.dat'
+     &       'DSET ','^'//trim(file)//'.dat'
 
       write(unit(if),'(a12)') 'UNDEF 1.0E30'
Index: LMDZ5/branches/testing/libf/filtrez/coefils.h
===================================================================
--- LMDZ5/branches/testing/libf/filtrez/coefils.h	(revision 1664)
+++ LMDZ5/branches/testing/libf/filtrez/coefils.h	(revision 1665)
@@ -1,4 +1,4 @@
 !
-! $Header$
+! $Id $
 !
       COMMON/coefils/jfiltnu,jfiltsu,jfiltnv,jfiltsv,sddu(iim),sddv(iim)&
@@ -7,5 +7,10 @@
      & ,coefilu2(iim,jjm),coefilv2(iim,jjm)
 !c
-      INTEGER jfiltnu,jfiltsu,jfiltnv,jfiltsv,modfrstu,modfrstv
+      INTEGER jfiltnu ! index of the last lat line filtered in NH (U grid)
+      INTEGER jfiltsu ! index of the first lat line filtered in SH (U grid)
+      INTEGER jfiltnv ! index of the last lat line filtered in NH (V grid)
+      INTEGER jfiltsv ! index of the first lat line filtered in SH (V grid)
+      INTEGER modfrstu ! number of retained (ie: unfiltered) modes on U grid
+      INTEGER modfrstv ! number of retained (ie: unfiltered) modes on V grid
       REAL    sddu,sddv,unsddu,unsddv,coefilu,coefilv,eignfnu,eignfnv
       REAL    coefilu2,coefilv2
Index: LMDZ5/branches/testing/libf/filtrez/filtreg_mod.F90
===================================================================
--- LMDZ5/branches/testing/libf/filtrez/filtreg_mod.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/filtrez/filtreg_mod.F90	(revision 1665)
@@ -1,2 +1,5 @@
+!
+! $Id $
+!
 MODULE filtreg_mod
 
@@ -42,5 +45,4 @@
     INTEGER ixmineq
 #endif
-    EXTERNAL  inifgn
     !
     ! ------------------------------------------------------------
@@ -71,7 +73,7 @@
     CALL inifgn(eignvl)
     !
-    PRINT *,' EIGNVL '
+    PRINT *,'inifilr: EIGNVL '
     PRINT 250,eignvl
-250 FORMAT( 1x,5e13.6)
+250 FORMAT( 1x,5e14.6)
     !
     ! compute eigenvalues and eigenfunctions
@@ -113,4 +115,10 @@
 #endif
     !
+    ! For a regular grid, we want the filter to start at latitudes
+    ! corresponding to lengths dx of the same size as dy (in terms
+    ! of angles: dx=2*dy) => at colat0=0.5 (i.e. colatitude=30 degrees
+    !  <=> latitude=60 degrees).
+    ! Same idea for the zoomed grid: start filtering polewards as soon
+    ! as length dx becomes of the same size as dy 
     !
     colat0  =  MIN( 0.5, dymin/dxmin )
@@ -158,16 +166,25 @@
     imx  = iim
     !
-    PRINT *,' TRUNCATION AT ',imx
-    !
+    PRINT *,'inifilr: TRUNCATION AT ',imx
+    !
+! Ehouarn: set up some defaults
+    jfiltnu=2 ! avoid north pole
+    jfiltsu=jjm ! avoid south pole (which is at jjm+1)
+    jfiltnv=1 ! NB: no poles on the V grid
+    jfiltsv=jjm
+
     DO j = 2, jjm/2+1
        cof = COS( rlatu(j) )/ colat0
        IF ( cof .LT. 1. ) THEN
-          IF( rlamda(imx) * COS(rlatu(j) ).LT.1. ) jfiltnu= j
+          IF( rlamda(imx) * COS(rlatu(j) ).LT.1. ) THEN
+            jfiltnu= j
+          ENDIF
        ENDIF
 
        cof = COS( rlatu(jjp1-j+1) )/ colat0
        IF ( cof .LT. 1. ) THEN
-          IF( rlamda(imx) * COS(rlatu(jjp1-j+1) ).LT.1. ) &
+          IF( rlamda(imx) * COS(rlatu(jjp1-j+1) ).LT.1. ) THEN
                jfiltsu= jjp1-j+1
+          ENDIF
        ENDIF
     ENDDO
@@ -176,16 +193,18 @@
        cof = COS( rlatv(j) )/ colat0
        IF ( cof .LT. 1. ) THEN
-          IF( rlamda(imx) * COS(rlatv(j) ).LT.1. ) jfiltnv= j
+          IF( rlamda(imx) * COS(rlatv(j) ).LT.1. ) THEN
+            jfiltnv= j
+          ENDIF
        ENDIF
 
        cof = COS( rlatv(jjm-j+1) )/ colat0
        IF ( cof .LT. 1. ) THEN
-          IF( rlamda(imx) * COS(rlatv(jjm-j+1) ).LT.1. ) &
+          IF( rlamda(imx) * COS(rlatv(jjm-j+1) ).LT.1. ) THEN
                jfiltsv= jjm-j+1
+          ENDIF
        ENDIF
     ENDDO
     !                                 
 
-    IF ( jfiltnu.LE.0 ) jfiltnu=1
     IF( jfiltnu.GT. jjm/2 +1 )  THEN
        PRINT *,' jfiltnu en dehors des valeurs acceptables ' ,jfiltnu
@@ -193,5 +212,4 @@
     ENDIF
 
-    IF( jfiltsu.LE.0) jfiltsu=1
     IF( jfiltsu.GT.  jjm  +1 )  THEN
        PRINT *,' jfiltsu en dehors des valeurs acceptables ' ,jfiltsu
@@ -199,5 +217,4 @@
     ENDIF
 
-    IF( jfiltnv.LE.0) jfiltnv=1
     IF( jfiltnv.GT. jjm/2    )  THEN
        PRINT *,' jfiltnv en dehors des valeurs acceptables ' ,jfiltnv
@@ -205,5 +222,4 @@
     ENDIF
 
-    IF( jfiltsv.LE.0) jfiltsv=1
     IF( jfiltsv.GT.     jjm  )  THEN
        PRINT *,' jfiltsv en dehors des valeurs acceptables ' ,jfiltsv
@@ -211,14 +227,14 @@
     ENDIF
 
-    PRINT *,' jfiltnv jfiltsv jfiltnu jfiltsu ' , &
+    PRINT *,'inifilr: jfiltnv jfiltsv jfiltnu jfiltsu ' , &
          jfiltnv,jfiltsv,jfiltnu,jfiltsu
 
     IF(first_call_inifilr) THEN
        ALLOCATE(matriceun(iim,iim,jfiltnu))
-       ALLOCATE(matriceus(iim,iim,jfiltsu))
+       ALLOCATE(matriceus(iim,iim,jjm-jfiltsu+1))
        ALLOCATE(matricevn(iim,iim,jfiltnv))
-       ALLOCATE(matricevs(iim,iim,jfiltsv))
+       ALLOCATE(matricevs(iim,iim,jjm-jfiltsv+1))
        ALLOCATE( matrinvn(iim,iim,jfiltnu))
-       ALLOCATE( matrinvs(iim,iim,jfiltsu))
+       ALLOCATE( matrinvs(iim,iim,jjm-jfiltsu+1))
        first_call_inifilr = .FALSE.
     ENDIF
@@ -230,4 +246,5 @@
     !
     DO j = 1,jjm
+    !default initialization: all modes are retained (i.e. no filtering)
        modfrstu( j ) = iim
        modfrstv( j ) = iim
@@ -306,5 +323,6 @@
 
     IF(jfiltnv.GE.jjm/2 .OR. jfiltnu.GE.jjm/2)THEN
-
+! Ehouarn: and what are these for??? Trying to handle a limit case
+!          where filters extend to and meet at the equator?
        IF(jfiltnv.EQ.jfiltsv)jfiltsv=1+jfiltnv
        IF(jfiltnu.EQ.jfiltsu)jfiltsu=1+jfiltnu
@@ -334,5 +352,5 @@
              eignft(i,k) = eignfnv(k,i) * coff
           ENDDO
-       ENDDO
+       ENDDO ! of DO i=1,iim
 #ifdef CRAY
        CALL MXM( eignfnv,iim,eignft,iim,matriceun(1,1,j),iim )
@@ -350,9 +368,9 @@
              ENDDO
           ENDDO
-       ENDDO
-#endif
-#endif
-
-    ENDDO
+       ENDDO ! of DO k = 1, iim
+#endif
+#endif
+
+    ENDDO ! of DO j = 2, jfiltnu
 
     DO j = jfiltsu, jjm
@@ -364,5 +382,5 @@
              eignft(i,k) = eignfnv(k,i) * coff
           ENDDO
-       ENDDO
+       ENDDO ! of DO i=1,iim
 #ifdef CRAY
        CALL MXM(eignfnv,iim,eignft,iim,matriceus(1,1,j-jfiltsu+1),iim)
@@ -381,9 +399,9 @@
              ENDDO
           ENDDO
-       ENDDO
-#endif
-#endif
-
-    ENDDO
+       ENDDO ! of DO k = 1, iim
+#endif
+#endif
+
+    ENDDO ! of DO j = jfiltsu, jjm
 
     !   ...................................................................
@@ -421,5 +439,5 @@
 #endif
 
-    ENDDO
+    ENDDO ! of DO j = 1, jfiltnv
 
     DO j = jfiltsv, jjm
@@ -452,5 +470,5 @@
 #endif
 
-    ENDDO
+    ENDDO ! of DO j = jfiltsv, jjm
 
     !   ...................................................................
@@ -488,5 +506,5 @@
 #endif
 
-    ENDDO
+    ENDDO ! of DO j = 2, jfiltnu
 
     DO j = jfiltsu, jjm
@@ -518,5 +536,5 @@
 #endif
 
-    ENDDO
+    ENDDO ! of DO j = jfiltsu, jjm
 
     IF (use_filtre_fft) THEN
Index: LMDZ5/branches/testing/libf/grid/dimension/makdim
===================================================================
--- LMDZ5/branches/testing/libf/grid/dimension/makdim	(revision 1664)
+++ LMDZ5/branches/testing/libf/grid/dimension/makdim	(revision 1665)
@@ -1,48 +1,48 @@
-for i in $* ; do
-   list=$list.$i
+#!/bin/bash
+#set -xv
+
+# sanity check: do we have the required argument ?
+if (( $# < 1 )) || (( $# > 3 ))
+then
+ echo "Wrong number of parameters in $0 !!!"
+ echo " Usage:"
+ echo "  $0 [im] [jm] lm"
+ echo " where im, jm and lm are the dimensions"
+ exit
+fi
+
+# build "fichnom", the relevant 'dimensions.im.jm.lm' file name
+for i in $*
+  do
+  list=$list.$i
 done
 fichdim=dimensions${list}
 
-if [ ! -f $fichdim ] ; then
-# si le fichier de dimensions n'existe pas, on le cree
+if [ ! -f $fichdim ]
+    then
+#    echo "$fichdim does not exist"
 
-  if [ $# -ge 3 ] ; then
-     im=$1
-     jm=$2
-     lm=$3
-     n2=$1
-     ndm=1
+    # assign values of im, jm and lm
+    if [ $# -ge 3 ]
+        then
+        im=$1
+        jm=$2
+        lm=$3
+        ndm=1
+    elif [ $# -ge 2 ]
+        then
+        im=1
+        jm=$1
+        lm=$2
+        ndm=1
+    elif [ $# -ge 1 ]
+        then
+        im=1
+        jm=1
+        lm=$1
+        ndm=1
+    fi
 
-# Le test suivant est commente car il est inutile avec le nouveau 
-# filtre filtrez. Attention avec le "vieux" filtre (F. Forget,11/1994)
-#
-#     while [ "$n2" -gt 2 ]; do
-#       n2=`expr $n2 / 2`
-#       ndm=`expr $ndm + 1`
-#       echo $n2
-#    done
-#    if [ "$n2" != 2 ] ; then
-#       echo le nombre de longitude doit etre une puissance de 2
-#       exit
-#    fi
-
-
-  else if [ $# -ge 2 ] ; then
-      im=1
-      jm=$1
-      lm=$2
-      ndm=1
-  else if [ $# -ge 1 ] ; then
-      im=1
-      jm=1
-      lm=$1
-      ndm=1
-  else
-         echo il faut au moins une dimension
-         exit
-  fi
-fi
-fi
-
+# since the file doesn't exist, we create it
 cat << EOF > $fichdim
 !-----------------------------------------------------------------------
@@ -62,4 +62,8 @@
 fi
 
+# remove 'old' dimensions.h file (if any) and replace it with new one
+if [ -f ../dimensions.h ] ; then
 \rm ../dimensions.h
+fi
 tar cf - $fichdim | ( cd .. ; tar xf - ; mv $fichdim dimensions.h )
+# line above is a trick to preserve time of creation of dimensions.h files
Index: LMDZ5/branches/testing/libf/phy1d/1DUTILS.h_no_writelim
===================================================================
--- LMDZ5/branches/testing/libf/phy1d/1DUTILS.h_no_writelim	(revision 1665)
+++ LMDZ5/branches/testing/libf/phy1d/1DUTILS.h_no_writelim	(revision 1665)
@@ -0,0 +1,2582 @@
+!
+! $Id: conf_unicol.F 1279 2010-08-04 17:20:56Z lahellec $
+!
+c
+c
+      SUBROUTINE conf_unicol( tapedef )
+c
+#ifdef CPP_IOIPSL
+      use IOIPSL
+#else
+! if not using IOIPSL, we still need to use (a local version of) getin
+      use ioipsl_getincom
+#endif
+      IMPLICIT NONE
+c-----------------------------------------------------------------------
+c     Auteurs :   A. Lahellec  .
+c
+c     Arguments :
+c
+c     tapedef   :
+
+       INTEGER tapedef
+c
+c   Declarations :
+c   --------------
+
+#include "compar1d.h"
+#include "flux_arp.h"
+#include "fcg_gcssold.h"
+#include "fcg_racmo.h"
+#include "iniprint.h"
+c
+c
+c   local:
+c   ------
+
+c      CHARACTER ch1*72,ch2*72,ch3*72,ch4*12
+      
+c
+c  -------------------------------------------------------------------
+c
+c      .........    Initilisation parametres du lmdz1D      ..........
+c
+c---------------------------------------------------------------------
+c   initialisations:
+c   ----------------
+
+!Config  Key  = lunout
+!Config  Desc = unite de fichier pour les impressions
+!Config  Def  = 6
+!Config  Help = unite de fichier pour les impressions 
+!Config         (defaut sortie standard = 6)
+      lunout=6
+      CALL getin('lunout', lunout)
+      IF (lunout /= 5 .and. lunout /= 6) THEN
+        OPEN(lunout,FILE='lmdz.out')
+      ENDIF
+
+!Config  Key  = prt_level
+!Config  Desc = niveau d'impressions de débogage
+!Config  Def  = 0
+!Config  Help = Niveau d'impression pour le débogage
+!Config         (0 = minimum d'impression)
+c      prt_level = 0
+c      CALL getin('prt_level',prt_level)
+
+c-----------------------------------------------------------------------
+c  Parametres de controle du run:
+c-----------------------------------------------------------------------
+
+!Config  Key  = restart
+!Config  Desc = on repart des startphy et start1dyn
+!Config  Def  = false
+!Config  Help = les fichiers restart doivent etre renomme en start
+       restart = .FALSE.
+       CALL getin('restart',restart)
+
+!Config  Key  = forcing_type
+!Config  Desc = defines the way the SCM is forced:
+!Config  Def  = 0
+!!Config  Help = 0 ==> forcing_les = .true.
+!             initial profiles from file prof.inp.001
+!             no forcing by LS convergence ; 
+!             surface temperature imposed ;
+!             radiative cooling may be imposed (iflag_radia=0 in physiq.def)
+!         = 1 ==> forcing_radconv = .true.
+!             idem forcing_type = 0, but the imposed radiative cooling 
+!             is set to 0 (hence, if iflag_radia=0 in physiq.def, 
+!             then there is no radiative cooling at all)
+!         = 2 ==> forcing_toga = .true.
+!             initial profiles from TOGA-COARE IFA files 
+!             LS convergence and SST imposed from TOGA-COARE IFA files 
+!         = 3 ==> forcing_GCM2SCM = .true.
+!             initial profiles from the GCM output
+!             LS convergence imposed from the GCM output
+!         = 4 ==> forcing_twpi = .true.
+!             initial profiles from TWPICE nc files 
+!             LS convergence and SST imposed from TWPICE nc files 
+!         = 5 ==> forcing_rico = .true.
+!             initial profiles from RICO idealized
+!             LS convergence imposed from  RICO (cst) 
+!         = 40 ==> forcing_GCSSold = .true.
+!             initial profile from GCSS file
+!             LS convergence imposed from GCSS file
+!
+       forcing_type = 0
+       CALL getin('forcing_type',forcing_type)
+         imp_fcg_gcssold   = .false.
+         ts_fcg_gcssold    = .false.  
+         Tp_fcg_gcssold    = .false.  
+         Tp_ini_gcssold    = .false.  
+         xTurb_fcg_gcssold = .false. 
+        IF (forcing_type .eq.40) THEN
+          CALL getin('imp_fcg',imp_fcg_gcssold)
+          CALL getin('ts_fcg',ts_fcg_gcssold)
+          CALL getin('tp_fcg',Tp_fcg_gcssold)
+          CALL getin('tp_ini',Tp_ini_gcssold)
+          CALL getin('turb_fcg',xTurb_fcg_gcssold)
+        ENDIF
+
+!Config  Key  = ok_flux_surf
+!Config  Desc = forcage ou non par les flux de surface
+!Config  Def  = false
+!Config  Help = forcage ou non par les flux de surface
+       ok_flux_surf = .FALSE.
+       CALL getin('ok_flux_surf',ok_flux_surf)
+
+!Config  Key  = time_ini
+!Config  Desc = meaningless in this  case
+!Config  Def  = 0.
+!Config  Help = 
+       tsurf = 0.
+       CALL getin('time_ini',time_ini)
+
+!Config  Key  = rlat et rlon
+!Config  Desc = latitude et longitude
+!Config  Def  = 0.0  0.0
+!Config  Help = fixe la position de la colonne
+       xlat = 0.
+       xlon = 0.
+       CALL getin('rlat',xlat)
+       CALL getin('rlon',xlon)
+
+!Config  Key  = airephy
+!Config  Desc = Grid cell area
+!Config  Def  = 1.e11
+!Config  Help = 
+       airefi = 1.e11
+       CALL getin('airephy',airefi)
+
+!Config  Key  = nat_surf
+!Config  Desc = surface type
+!Config  Def  = 0 (ocean)
+!Config  Help = 0=ocean,1=land,2=glacier,3=banquise
+       nat_surf = 0.
+       CALL getin('nat_surf',nat_surf)
+
+!Config  Key  = tsurf
+!Config  Desc = surface temperature
+!Config  Def  = 290.
+!Config  Help = not used if type_ts_forcing=1 in lmdz1d.F
+       tsurf = 290.
+       CALL getin('tsurf',tsurf)
+
+!Config  Key  = psurf
+!Config  Desc = surface pressure
+!Config  Def  = 102400.
+!Config  Help = 
+       psurf = 102400.
+       CALL getin('psurf',psurf)
+
+!Config  Key  = zsurf
+!Config  Desc = surface altitude
+!Config  Def  = 0.
+!Config  Help = 
+       zsurf = 0.
+       CALL getin('zsurf',zsurf)
+
+!Config  Key  = rugos
+!Config  Desc = coefficient de frottement
+!Config  Def  = 0.0001
+!Config  Help = calcul du Cdrag
+       rugos = 0.0001
+       CALL getin('rugos',rugos)
+
+!Config  Key  = wtsurf et wqsurf
+!Config  Desc = ???
+!Config  Def  = 0.0 0.0
+!Config  Help = 
+       wtsurf = 0.0
+       wqsurf = 0.0
+       CALL getin('wtsurf',wtsurf)
+       CALL getin('wqsurf',wqsurf)
+
+!Config  Key  = albedo
+!Config  Desc = albedo
+!Config  Def  = 0.09
+!Config  Help = 
+       albedo = 0.09
+       CALL getin('albedo',albedo)
+
+!Config  Key  = agesno
+!Config  Desc = age de la neige
+!Config  Def  = 30.0
+!Config  Help = 
+       xagesno = 30.0
+       CALL getin('agesno',xagesno)
+
+!Config  Key  = restart_runoff
+!Config  Desc = age de la neige
+!Config  Def  = 30.0
+!Config  Help = 
+       restart_runoff = 0.0
+       CALL getin('restart_runoff',restart_runoff)
+
+!Config  Key  = qsolinp
+!Config  Desc = initial bucket water content (kg/m2) when land (5std)
+!Config  Def  = 30.0
+!Config  Help = 
+       qsolinp = 1.
+       CALL getin('qsolinp',qsolinp)
+
+!Config  Key  = zpicinp
+!Config  Desc = denivellation orographie
+!Config  Def  = 300.
+!Config  Help =  input brise
+       zpicinp = 300.
+       CALL getin('zpicinp',zpicinp)
+
+
+      write(lunout,*)' +++++++++++++++++++++++++++++++++++++++'
+      write(lunout,*)' Configuration des parametres du gcm1D: '
+      write(lunout,*)' +++++++++++++++++++++++++++++++++++++++'
+      write(lunout,*)' restart = ', restart
+      write(lunout,*)' forcing_type = ', forcing_type
+      write(lunout,*)' time_ini = ', time_ini
+      write(lunout,*)' rlat = ', xlat
+      write(lunout,*)' rlon = ', xlon
+      write(lunout,*)' airephy = ', airefi
+      write(lunout,*)' nat_surf = ', nat_surf
+      write(lunout,*)' tsurf = ', tsurf
+      write(lunout,*)' psurf = ', psurf
+      write(lunout,*)' zsurf = ', zsurf
+      write(lunout,*)' rugos = ', rugos
+      write(lunout,*)' wtsurf = ', wtsurf
+      write(lunout,*)' wqsurf = ', wqsurf
+      write(lunout,*)' albedo = ', albedo
+      write(lunout,*)' xagesno = ', xagesno
+      write(lunout,*)' restart_runoff = ', restart_runoff
+      write(lunout,*)' qsolinp = ', qsolinp
+      write(lunout,*)' zpicinp = ', zpicinp
+      IF (forcing_type .eq.40) THEN
+        write(lunout,*) '--- Forcing type GCSS Old --- with:'
+        write(lunout,*)'imp_fcg',imp_fcg_gcssold
+        write(lunout,*)'ts_fcg',ts_fcg_gcssold
+        write(lunout,*)'tp_fcg',Tp_fcg_gcssold
+        write(lunout,*)'tp_ini',Tp_ini_gcssold
+        write(lunout,*)'xturb_fcg',xTurb_fcg_gcssold
+      ENDIF
+
+      write(lunout,*)' +++++++++++++++++++++++++++++++++++++++'
+      write(lunout,*)
+c
+      RETURN
+      END
+!
+! $Id: dyn1deta0.F 1279 2010/07/30 A Lahellec$
+!
+c
+      SUBROUTINE dyn1deta0(fichnom,plev,play,phi,phis,presnivs,
+     &                          ucov,vcov,temp,q,omega2)
+      USE dimphy
+      USE mod_grid_phy_lmdz
+      USE mod_phys_lmdz_para
+      USE iophy
+      USE phys_state_var_mod
+      USE iostart
+      USE write_field_phy
+      USE infotrac
+      use control_mod
+
+      IMPLICIT NONE
+c=======================================================
+c Ecriture du fichier de redemarrage sous format NetCDF
+c=======================================================
+c   Declarations:
+c   -------------
+#include "dimensions.h"
+#include "comconst.h"
+#include "temps.h"
+!!#include "control.h"
+#include "logic.h"
+#include "netcdf.inc"
+
+c   Arguments:
+c   ----------
+      CHARACTER*(*) fichnom
+cAl1 plev tronque pour .nc mais plev(klev+1):=0
+      real :: plev(klon,klev),play (klon,klev),phi(klon,klev)
+      real :: presnivs(klon,klev)
+      real :: ucov(klon,klev),vcov(klon,klev),temp(klon,klev)
+      real :: q(klon,klev,nqtot),omega2(klon,klev)
+c      real :: ug(klev),vg(klev),fcoriolis
+      real :: phis(klon) 
+
+c   Variables locales pour NetCDF:
+c   ------------------------------
+      INTEGER nid, nvarid
+      INTEGER idim_s
+      INTEGER ierr, ierr_file 
+      INTEGER iq
+      INTEGER length
+      PARAMETER (length = 100)
+      REAL tab_cntrl(length) ! tableau des parametres du run
+      character*4 nmq(nqtot)
+      character*12 modname
+      character*80 abort_message
+      LOGICAL found
+c
+      INTEGER nb
+
+      modname = 'dyn1deta0 : '
+      nmq(1)="vap"
+      nmq(2)="cond"
+      do iq=3,nqtot
+        write(nmq(iq),'("tra",i1)') iq-2
+      enddo
+      print*,'in dyn1deta0 ',fichnom,klon,klev,nqtot
+      CALL open_startphy(fichnom)
+      print*,'after open startphy ',fichnom,nmq
+
+c
+c Lecture des parametres de controle:
+c
+      CALL get_var("controle",tab_cntrl)
+       
+
+      im         = tab_cntrl(1)
+      jm         = tab_cntrl(2)
+      lllm       = tab_cntrl(3)
+      day_ref    = tab_cntrl(4)
+      annee_ref  = tab_cntrl(5)
+c      rad        = tab_cntrl(6)
+c      omeg       = tab_cntrl(7)
+c      g          = tab_cntrl(8)
+c      cpp        = tab_cntrl(9)
+c      kappa      = tab_cntrl(10)
+c      daysec     = tab_cntrl(11)
+c      dtvr       = tab_cntrl(12)
+c      etot0      = tab_cntrl(13)
+c      ptot0      = tab_cntrl(14)
+c      ztot0      = tab_cntrl(15)
+c      stot0      = tab_cntrl(16)
+c      ang0       = tab_cntrl(17)
+c      pa         = tab_cntrl(18)
+c      preff      = tab_cntrl(19)
+c
+c      clon       = tab_cntrl(20)
+c      clat       = tab_cntrl(21)
+c      grossismx  = tab_cntrl(22)
+c      grossismy  = tab_cntrl(23)
+c
+      IF ( tab_cntrl(24).EQ.1. )  THEN
+        fxyhypb  = . TRUE .
+c        dzoomx   = tab_cntrl(25)
+c        dzoomy   = tab_cntrl(26)
+c        taux     = tab_cntrl(28)
+c        tauy     = tab_cntrl(29)
+      ELSE
+        fxyhypb = . FALSE .
+        ysinus  = . FALSE .
+        IF( tab_cntrl(27).EQ.1. ) ysinus = . TRUE. 
+      ENDIF
+
+      day_ini = tab_cntrl(30)
+      itau_dyn = tab_cntrl(31)
+c   .................................................................
+c
+c
+c      PRINT*,'rad,omeg,g,cpp,kappa',rad,omeg,g,cpp,kappa
+cAl1
+       Print*,'day_ref,annee_ref,day_ini,itau_dyn',
+     &              day_ref,annee_ref,day_ini,itau_dyn
+
+c  Lecture des champs
+c
+      plev(1,klev+1)=0.
+      CALL get_field("plev",plev,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <Plev> est absent'
+      CALL get_field("play",play,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <Play> est absent'
+      CALL get_field("phi",phi,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <Phi> est absent'
+      CALL get_field("phis",phis,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <Phis> est absent'
+      CALL get_field("presnivs",presnivs,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <Presnivs> est absent'
+      CALL get_field("ucov",ucov,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <ucov> est absent'
+      CALL get_field("vcov",vcov,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <vcov> est absent'
+      CALL get_field("temp",temp,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <temp> est absent'
+      CALL get_field("omega2",omega2,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <omega2> est absent'
+
+      Do iq=1,nqtot
+        CALL get_field("q"//nmq(iq),q(:,:,iq),found)
+        IF (.NOT. found)
+     &  PRINT*, modname//'Le champ <q'//nmq//'> est absent'
+      EndDo
+
+      CALL close_startphy
+      print*,' close startphy'
+     .      ,fichnom,play(1,1),play(1,klev),temp(1,klev)
+c
+      RETURN
+      END
+!
+! $Id: dyn1dredem.F 1279 2010/07/29 A Lahellec$
+!
+c
+      SUBROUTINE dyn1dredem(fichnom,plev,play,phi,phis,presnivs,
+     &                          ucov,vcov,temp,q,omega2)
+      USE dimphy
+      USE mod_grid_phy_lmdz
+      USE mod_phys_lmdz_para
+      USE phys_state_var_mod
+      USE iostart
+      USE infotrac
+      use control_mod
+
+      IMPLICIT NONE
+c=======================================================
+c Ecriture du fichier de redemarrage sous format NetCDF
+c=======================================================
+c   Declarations:
+c   -------------
+#include "dimensions.h"
+#include "comconst.h"
+#include "temps.h"
+!!#include "control.h"
+#include "logic.h"
+#include "netcdf.inc"
+
+c   Arguments:
+c   ----------
+      CHARACTER*(*) fichnom
+      REAL time
+cAl1 plev tronque pour .nc mais plev(klev+1):=0
+      real :: plev(klon,klev),play (klon,klev),phi(klon,klev)
+      real :: presnivs(klon,klev)
+      real :: ucov(klon,klev),vcov(klon,klev),temp(klon,klev)
+      real :: q(klon,klev,nqtot)
+      real :: omega2(klon,klev),rho(klon,klev+1)
+c      real :: ug(klev),vg(klev),fcoriolis
+      real :: phis(klon) 
+
+c   Variables locales pour NetCDF:
+c   ------------------------------
+      INTEGER nid, nvarid
+      INTEGER idim_s
+      INTEGER ierr, ierr_file 
+      INTEGER iq,l
+      INTEGER length
+      PARAMETER (length = 100)
+      REAL tab_cntrl(length) ! tableau des parametres du run
+      character*4 nmq(nqtot)
+      character*20 modname
+      character*80 abort_message
+c
+      INTEGER nb
+      SAVE nb
+      DATA nb / 0 /
+
+      REAL zan0,zjulian,hours
+      INTEGER yyears0,jjour0, mmois0
+      character*30 unites
+
+cDbg
+      CALL open_restartphy(fichnom)
+      print*,'redm1 ',fichnom,klon,klev,nqtot
+      nmq(1)="vap"
+      nmq(2)="cond"
+      nmq(3)="tra1"
+      nmq(4)="tra2"
+
+      modname = 'dyn1dredem'
+      ierr = NF_OPEN(fichnom, NF_WRITE, nid)
+      IF (ierr .NE. NF_NOERR) THEN
+         PRINT*, "Pb. d ouverture "//fichnom
+         CALL abort
+      ENDIF
+
+      DO l=1,length
+       tab_cntrl(l) = 0.
+      ENDDO
+       tab_cntrl(1)  = FLOAT(iim)
+       tab_cntrl(2)  = FLOAT(jjm)
+       tab_cntrl(3)  = FLOAT(llm)
+       tab_cntrl(4)  = FLOAT(day_ref)
+       tab_cntrl(5)  = FLOAT(annee_ref)
+       tab_cntrl(6)  = rad
+       tab_cntrl(7)  = omeg
+       tab_cntrl(8)  = g
+       tab_cntrl(9)  = cpp
+       tab_cntrl(10) = kappa
+       tab_cntrl(11) = daysec
+       tab_cntrl(12) = dtvr
+c       tab_cntrl(13) = etot0
+c       tab_cntrl(14) = ptot0
+c       tab_cntrl(15) = ztot0
+c       tab_cntrl(16) = stot0
+c       tab_cntrl(17) = ang0
+c       tab_cntrl(18) = pa
+c       tab_cntrl(19) = preff
+c
+c    .....    parametres  pour le zoom      ......   
+
+c       tab_cntrl(20)  = clon
+c       tab_cntrl(21)  = clat
+c       tab_cntrl(22)  = grossismx
+c       tab_cntrl(23)  = grossismy
+c
+      IF ( fxyhypb )   THEN
+       tab_cntrl(24) = 1.
+c       tab_cntrl(25) = dzoomx
+c       tab_cntrl(26) = dzoomy
+       tab_cntrl(27) = 0.
+c       tab_cntrl(28) = taux
+c       tab_cntrl(29) = tauy
+      ELSE
+       tab_cntrl(24) = 0.
+c       tab_cntrl(25) = dzoomx
+c       tab_cntrl(26) = dzoomy
+       tab_cntrl(27) = 0.
+       tab_cntrl(28) = 0.
+       tab_cntrl(29) = 0.
+       IF( ysinus )  tab_cntrl(27) = 1.
+      ENDIF
+CAl1 iday_end -> day_end
+       tab_cntrl(30) = FLOAT(day_end)
+       tab_cntrl(31) = FLOAT(itau_dyn + itaufin)
+c
+      CALL put_var("controle","Param. de controle Dyn1D",tab_cntrl)
+c
+
+c  Ecriture/extension de la coordonnee temps
+
+      nb = nb + 1
+
+c  Ecriture des champs
+c
+      CALL put_field("plev","p interfaces sauf la nulle",plev)
+      CALL put_field("play","",play)
+      CALL put_field("phi","geopotentielle",phi)
+      CALL put_field("phis","geopotentiell de surface",phis)
+      CALL put_field("presnivs","",presnivs)
+      CALL put_field("ucov","",ucov)
+      CALL put_field("vcov","",vcov)
+      CALL put_field("temp","",temp)
+      CALL put_field("omega2","",omega2)
+
+      Do iq=1,nqtot
+        CALL put_field("q"//nmq(iq),"eau vap ou condens et traceurs",
+     .                                                      q(:,:,iq))
+      EndDo
+      CALL close_restartphy
+
+c
+      RETURN
+      END
+      SUBROUTINE gr_fi_dyn(nfield,ngrid,im,jm,pfi,pdyn)
+      IMPLICIT NONE
+!=======================================================================
+!   passage d'un champ de la grille scalaire a la grille physique
+!=======================================================================
+ 
+!-----------------------------------------------------------------------
+!   declarations:
+!   -------------
+ 
+      INTEGER im,jm,ngrid,nfield
+      REAL pdyn(im,jm,nfield)
+      REAL pfi(ngrid,nfield)
+ 
+      INTEGER i,j,ifield,ig
+ 
+!-----------------------------------------------------------------------
+!   calcul:
+!   -------
+ 
+      DO ifield=1,nfield
+!   traitement des poles
+         DO i=1,im
+            pdyn(i,1,ifield)=pfi(1,ifield)
+            pdyn(i,jm,ifield)=pfi(ngrid,ifield)
+         ENDDO
+ 
+!   traitement des point normaux
+         DO j=2,jm-1
+	    ig=2+(j-2)*(im-1)
+            CALL SCOPY(im-1,pfi(ig,ifield),1,pdyn(1,j,ifield),1)
+	    pdyn(im,j,ifield)=pdyn(1,j,ifield)
+         ENDDO
+      ENDDO
+ 
+      RETURN
+      END
+ 
+ 
+
+      SUBROUTINE abort_gcm(modname, message, ierr)
+ 
+      USE IOIPSL
+!
+! Stops the simulation cleanly, closing files and printing various
+! comments
+!
+!  Input: modname = name of calling program
+!         message = stuff to print
+!         ierr    = severity of situation ( = 0 normal )
+ 
+      character*20 modname
+      integer ierr
+      character*80 message
+ 
+      write(*,*) 'in abort_gcm'
+      call histclo
+!     call histclo(2)
+!     call histclo(3)
+!     call histclo(4)
+!     call histclo(5)
+      write(*,*) 'out of histclo'
+      write(*,*) 'Stopping in ', modname
+      write(*,*) 'Reason = ',message
+      call getin_dump
+!
+      if (ierr .eq. 0) then
+        write(*,*) 'Everything is cool'
+      else
+        write(*,*) 'Houston, we have a problem ', ierr
+      endif
+      STOP
+      END
+      REAL FUNCTION fq_sat(kelvin, millibar)
+!
+      IMPLICIT none
+!======================================================================
+! Autheur(s): Z.X. Li (LMD/CNRS)
+! Objet: calculer la vapeur d'eau saturante (formule Centre Euro.)
+!======================================================================
+! Arguments:
+! kelvin---input-R: temperature en Kelvin
+! millibar--input-R: pression en mb
+!
+! fq_sat----output-R: vapeur d'eau saturante en kg/kg
+!======================================================================
+!
+      REAL kelvin, millibar
+!
+      REAL r2es
+      PARAMETER (r2es=611.14 *18.0153/28.9644)
+!
+      REAL r3les, r3ies, r3es
+      PARAMETER (R3LES=17.269)
+      PARAMETER (R3IES=21.875)
+!
+      REAL r4les, r4ies, r4es
+      PARAMETER (R4LES=35.86)
+      PARAMETER (R4IES=7.66)
+!
+      REAL rtt
+      PARAMETER (rtt=273.16)
+!
+      REAL retv
+      PARAMETER (retv=28.9644/18.0153 - 1.0)
+!
+      REAL zqsat
+      REAL temp, pres
+!     ------------------------------------------------------------------
+!
+!
+      temp = kelvin
+      pres = millibar * 100.0
+!      write(*,*)'kelvin,millibar=',kelvin,millibar
+!      write(*,*)'temp,pres=',temp,pres
+!
+      IF (temp .LE. rtt) THEN
+         r3es = r3ies
+         r4es = r4ies
+      ELSE
+         r3es = r3les
+         r4es = r4les
+      ENDIF
+!
+      zqsat=r2es/pres * EXP ( r3es*(temp-rtt) / (temp-r4es) )
+      zqsat=MIN(0.5,ZQSAT)
+      zqsat=zqsat/(1.-retv  *zqsat)
+!
+      fq_sat = zqsat
+!
+      RETURN
+      END
+      subroutine scopy(n,sx,incx,sy,incy)
+!
+      IMPLICIT NONE
+!
+      integer n,incx,incy,ix,iy,i
+      real sx((n-1)*incx+1),sy((n-1)*incy+1)
+!
+      iy=1
+      ix=1
+      do 10 i=1,n
+	 sy(iy)=sx(ix)
+         ix=ix+incx
+         iy=iy+incy
+10    continue
+!
+      return
+      end
+      subroutine wrgradsfi(if,nl,field,name,titlevar)
+      implicit none
+ 
+!   Declarations
+ 
+#include "gradsdef.h"
+ 
+!   arguments
+      integer if,nl
+      real field(imx*jmx*lmx)
+      character*10 name,file
+      character*10 titlevar
+ 
+!   local
+ 
+      integer im,jm,lm,i,j,l,iv,iii,iji,iif,ijf
+ 
+      logical writectl
+ 
+ 
+      writectl=.false.
+ 
+!     print*,if,iid(if),jid(if),ifd(if),jfd(if)
+      iii=iid(if)
+      iji=jid(if)
+      iif=ifd(if)
+      ijf=jfd(if)
+      im=iif-iii+1
+      jm=ijf-iji+1
+      lm=lmd(if)
+
+
+!     print*,'im,jm,lm,name,firsttime(if)'
+!     print*,im,jm,lm,name,firsttime(if)
+ 
+      if(firsttime(if)) then
+         if(name.eq.var(1,if)) then
+            firsttime(if)=.false.
+            ivar(if)=1
+         print*,'fin de l initialiation de l ecriture du fichier'
+         print*,file
+           print*,'fichier no: ',if
+           print*,'unit ',unit(if)
+           print*,'nvar  ',nvar(if)
+           print*,'vars ',(var(iv,if),iv=1,nvar(if))
+         else
+            ivar(if)=ivar(if)+1
+            nvar(if)=ivar(if)
+            var(ivar(if),if)=name
+            tvar(ivar(if),if)=trim(titlevar)
+            nld(ivar(if),if)=nl
+            print*,'initialisation ecriture de ',var(ivar(if),if)
+            print*,'if ivar(if) nld ',if,ivar(if),nld(ivar(if),if)
+         endif
+         writectl=.true.
+         itime(if)=1
+      else
+         ivar(if)=mod(ivar(if),nvar(if))+1
+         if (ivar(if).eq.nvar(if)) then
+            writectl=.true.
+            itime(if)=itime(if)+1
+         endif
+ 
+         if(var(ivar(if),if).ne.name) then
+           print*,'Il faut stoker la meme succession de champs a chaque'
+           print*,'pas de temps'
+           print*,'fichier no: ',if
+           print*,'unit ',unit(if)
+           print*,'nvar  ',nvar(if)
+           print*,'vars ',(var(iv,if),iv=1,nvar(if))
+ 
+           stop
+         endif
+      endif
+ 
+!     print*,'ivar(if),nvar(if),var(ivar(if),if),writectl'
+!     print*,ivar(if),nvar(if),var(ivar(if),if),writectl
+      do l=1,nl
+         irec(if)=irec(if)+1
+!        print*,'Ecrit rec=',irec(if),iii,iif,iji,ijf,
+!    s (l-1)*imd(if)*jmd(if)+(iji-1)*imd(if)+iii
+!    s ,(l-1)*imd(if)*jmd(if)+(ijf-1)*imd(if)+iif
+         write(unit(if)+1,rec=irec(if))
+     s   ((field((l-1)*imd(if)*jmd(if)+(j-1)*imd(if)+i)
+     s   ,i=iii,iif),j=iji,ijf)
+      enddo
+      if (writectl) then
+ 
+      file=fichier(if)
+!   WARNING! on reecrase le fichier .ctl a chaque ecriture
+      open(unit(if),file=trim(file)//'.ctl',
+     &         form='formatted',status='unknown')
+      write(unit(if),'(a5,1x,a40)')
+     &       'DSET ','^'//trim(file)//'.dat'
+ 
+      write(unit(if),'(a12)') 'UNDEF 1.0E30'
+      write(unit(if),'(a5,1x,a40)') 'TITLE ',title(if)
+      call formcoord(unit(if),im,xd(iii,if),1.,.false.,'XDEF')
+      call formcoord(unit(if),jm,yd(iji,if),1.,.true.,'YDEF')
+      call formcoord(unit(if),lm,zd(1,if),1.,.false.,'ZDEF')
+      write(unit(if),'(a4,i10,a30)')
+     &       'TDEF ',itime(if),' LINEAR 07AUG1998 30MN '
+      write(unit(if),'(a4,2x,i5)') 'VARS',nvar(if)
+      do iv=1,nvar(if)
+!        print*,'if,var(iv,if),nld(iv,if),nld(iv,if)-1/nld(iv,if)'
+!        print*,if,var(iv,if),nld(iv,if),nld(iv,if)-1/nld(iv,if)
+         write(unit(if),1000) var(iv,if),nld(iv,if)-1/nld(iv,if)
+     &     ,99,tvar(iv,if)
+      enddo
+      write(unit(if),'(a7)') 'ENDVARS'
+!
+1000  format(a5,3x,i4,i3,1x,a39)
+ 
+      close(unit(if))
+ 
+      endif ! writectl
+ 
+      return
+ 
+      END
+ 
+      subroutine inigrads(if,im
+     s  ,x,fx,xmin,xmax,jm,y,ymin,ymax,fy,lm,z,fz
+     s  ,dt,file,titlel)
+ 
+ 
+      implicit none
+ 
+      integer if,im,jm,lm,i,j,l
+      real x(im),y(jm),z(lm),fx,fy,fz,dt
+      real xmin,xmax,ymin,ymax
+      integer nf
+ 
+      character file*10,titlel*40
+ 
+#include "gradsdef.h"
+ 
+      data unit/24,32,34,36,38,40,42,44,46,48/
+      data nf/0/
+ 
+      if (if.le.nf) stop'verifier les appels a inigrads'
+ 
+      print*,'Entree dans inigrads'
+ 
+      nf=if
+      title(if)=titlel
+      ivar(if)=0
+ 
+      fichier(if)=trim(file)
+ 
+      firsttime(if)=.true.
+      dtime(if)=dt
+ 
+      iid(if)=1
+      ifd(if)=im
+      imd(if)=im
+      do i=1,im
+         xd(i,if)=x(i)*fx
+         if(xd(i,if).lt.xmin) iid(if)=i+1
+         if(xd(i,if).le.xmax) ifd(if)=i
+      enddo
+      print*,'On stoke du point ',iid(if),'  a ',ifd(if),' en x'
+ 
+      jid(if)=1
+      jfd(if)=jm
+      jmd(if)=jm
+      do j=1,jm
+         yd(j,if)=y(j)*fy
+         if(yd(j,if).gt.ymax) jid(if)=j+1
+         if(yd(j,if).ge.ymin) jfd(if)=j
+      enddo
+      print*,'On stoke du point ',jid(if),'  a ',jfd(if),' en y'
+
+      print*,'Open de dat'
+      print*,'file=',file
+      print*,'fichier(if)=',fichier(if)
+ 
+      print*,4*(ifd(if)-iid(if))*(jfd(if)-jid(if))
+      print*,trim(file)//'.dat'
+ 
+      OPEN (unit(if)+1,FILE=trim(file)//'.dat',
+     s   FORM='UNFORMATTED',
+     s   ACCESS='DIRECT'
+     s  ,RECL=4*(ifd(if)-iid(if)+1)*(jfd(if)-jid(if)+1))
+ 
+      print*,'Open de dat ok'
+ 
+      lmd(if)=lm
+      do l=1,lm
+         zd(l,if)=z(l)*fz
+      enddo
+ 
+      irec(if)=0
+!CR 
+!      print*,if,imd(if),jmd(if),lmd(if)
+!      print*,'if,imd(if),jmd(if),lmd(if)'
+ 
+      return
+      end
+      SUBROUTINE gr_dyn_fi(nfield,im,jm,ngrid,pdyn,pfi)
+      IMPLICIT NONE
+!=======================================================================
+!   passage d'un champ de la grille scalaire a la grille physique
+!=======================================================================
+ 
+!-----------------------------------------------------------------------
+!   declarations:
+!   -------------
+ 
+      INTEGER im,jm,ngrid,nfield
+      REAL pdyn(im,jm,nfield)
+      REAL pfi(ngrid,nfield)
+ 
+      INTEGER j,ifield,ig
+ 
+!-----------------------------------------------------------------------
+!   calcul:
+!   -------
+ 
+      IF(ngrid.NE.2+(jm-2)*(im-1).AND.ngrid.NE.1)
+     s    STOP 'probleme de dim'
+!   traitement des poles
+      CALL SCOPY(nfield,pdyn,im*jm,pfi,ngrid)
+      CALL SCOPY(nfield,pdyn(1,jm,1),im*jm,pfi(ngrid,1),ngrid)
+ 
+!   traitement des point normaux
+      DO ifield=1,nfield
+         DO j=2,jm-1
+	    ig=2+(j-2)*(im-1)
+            CALL SCOPY(im-1,pdyn(1,j,ifield),1,pfi(ig,ifield),1)
+         ENDDO
+      ENDDO
+ 
+      RETURN
+      END
+ 
+      SUBROUTINE disvert(pa,preff,ap,bp,dpres,presnivs,nivsigs,nivsig)
+ 
+!    Auteur :  P. Le Van .
+!
+      IMPLICIT NONE
+ 
+#include "dimensions.h"
+#include "paramet.h"
+!
+!=======================================================================
+!
+!
+!    s = sigma ** kappa   :  coordonnee  verticale
+!    dsig(l)            : epaisseur de la couche l ds la coord.  s
+!    sig(l)             : sigma a l'interface des couches l et l-1
+!    ds(l)              : distance entre les couches l et l-1 en coord.s
+!
+!=======================================================================
+!
+      REAL pa,preff
+      REAL ap(llmp1),bp(llmp1),dpres(llm),nivsigs(llm),nivsig(llmp1)
+      REAL presnivs(llm)
+!
+!   declarations:
+!   -------------
+!
+      REAL sig(llm+1),dsig(llm)
+!
+      INTEGER l
+      REAL snorm
+      REAL alpha,beta,gama,delta,deltaz,h
+      INTEGER np,ierr
+      REAL pi,x
+ 
+!-----------------------------------------------------------------------
+!
+      pi=2.*ASIN(1.)
+ 
+      OPEN(99,file='sigma.def',status='old',form='formatted',
+     s   iostat=ierr)
+ 
+!-----------------------------------------------------------------------
+!   cas 1 on lit les options dans sigma.def:
+!   ----------------------------------------
+ 
+      IF (ierr.eq.0) THEN
+ 
+      print*,'WARNING!!! on lit les options dans sigma.def'
+      READ(99,*) deltaz
+      READ(99,*) h
+      READ(99,*) beta
+      READ(99,*) gama
+      READ(99,*) delta
+      READ(99,*) np
+      CLOSE(99)
+      alpha=deltaz/(llm*h)
+!
+ 
+       DO 1  l = 1, llm
+       dsig(l) = (alpha+(1.-alpha)*exp(-beta*(llm-l)))*
+     $          ( (tanh(gama*l)/tanh(gama*llm))**np +
+     $            (1.-l/FLOAT(llm))*delta )
+   1   CONTINUE
+ 
+       sig(1)=1.
+       DO 101 l=1,llm-1
+          sig(l+1)=sig(l)*(1.-dsig(l))/(1.+dsig(l))
+101    CONTINUE
+       sig(llm+1)=0.
+ 
+       DO 2  l = 1, llm
+       dsig(l) = sig(l)-sig(l+1)
+   2   CONTINUE
+!
+ 
+      ELSE
+!-----------------------------------------------------------------------
+!   cas 2 ancienne discretisation (LMD5...):
+!   ----------------------------------------
+ 
+      PRINT*,'WARNING!!! Ancienne discretisation verticale'
+ 
+      h=7.
+      snorm  = 0.
+      DO l = 1, llm
+         x = 2.*asin(1.) * (FLOAT(l)-0.5) / float(llm+1)
+         dsig(l) = 1.0 + 7.0 * SIN(x)**2
+         snorm = snorm + dsig(l)
+      ENDDO
+      snorm = 1./snorm
+      DO l = 1, llm
+         dsig(l) = dsig(l)*snorm
+      ENDDO
+      sig(llm+1) = 0.
+      DO l = llm, 1, -1
+         sig(l) = sig(l+1) + dsig(l)
+      ENDDO
+ 
+      ENDIF
+ 
+ 
+      DO l=1,llm
+        nivsigs(l) = FLOAT(l)
+      ENDDO
+ 
+      DO l=1,llmp1
+        nivsig(l)= FLOAT(l)
+      ENDDO
+ 
+!
+!    ....  Calculs  de ap(l) et de bp(l)  ....
+!    .........................................
+!
+!
+!   .....  pa et preff sont lus  sur les fichiers start par lectba  .....
+!
+ 
+      bp(llmp1) =   0.
+ 
+      DO l = 1, llm
+!c
+!cc    ap(l) = 0.
+!cc    bp(l) = sig(l)
+ 
+      bp(l) = EXP( 1. -1./( sig(l)*sig(l)) )
+      ap(l) = pa * ( sig(l) - bp(l) )
+!
+      ENDDO
+      ap(llmp1) = pa * ( sig(llmp1) - bp(llmp1) )
+ 
+      PRINT *,' BP '
+      PRINT *,  bp
+      PRINT *,' AP '
+      PRINT *,  ap
+ 
+      DO l = 1, llm
+       dpres(l) = bp(l) - bp(l+1)
+       presnivs(l) = 0.5 *( ap(l)+bp(l)*preff + ap(l+1)+bp(l+1)*preff )
+      ENDDO
+ 
+      PRINT *,' PRESNIVS '
+      PRINT *,presnivs
+ 
+      RETURN
+      END
+
+!======================================================================
+       SUBROUTINE read_tsurf1d(knon,knindex,sst_out)
+
+! This subroutine specifies the surface temperature to be used in 1D simulations
+
+      USE dimphy, ONLY : klon
+
+      INTEGER, INTENT(IN)                  :: knon     ! nomber of points on compressed grid
+      INTEGER, DIMENSION(klon), INTENT(IN) :: knindex  ! grid point number for compressed grid
+      REAL, DIMENSION(klon), INTENT(OUT)   :: sst_out  ! tsurf used to force the single-column model
+
+       INTEGER :: i
+! COMMON defined in lmdz1d.F:
+       real ts_cur
+       common /sst_forcing/ts_cur
+
+       DO i = 1, knon
+        sst_out(i) = ts_cur
+       ENDDO
+
+      END SUBROUTINE read_tsurf1d
+
+!===============================================================
+      subroutine advect_vert(llm,w,dt,q,plev)
+!===============================================================
+!   Schema amont pour l'advection verticale en 1D
+!   w est la vitesse verticale dp/dt en Pa/s
+!   Traitement en volumes finis 
+!   d / dt ( zm q ) = delta_z ( omega q )
+!   d / dt ( zm ) = delta_z ( omega )
+!   avec zm = delta_z ( p )
+!   si * designe la valeur au pas de temps t+dt
+!   zm*(l) q*(l) - zm(l) q(l) = w(l+1) q(l+1) - w(l) q(l)
+!   zm*(l) -zm(l) = w(l+1) - w(l)
+!   avec w=omega * dt
+!---------------------------------------------------------------
+      implicit none
+! arguments
+      integer llm
+      real w(llm+1),q(llm),plev(llm+1),dt
+
+! local
+      integer l
+      real zwq(llm+1),zm(llm+1),zw(llm+1)
+      real qold
+
+!---------------------------------------------------------------
+
+      do l=1,llm
+         zw(l)=dt*w(l)
+         zm(l)=plev(l)-plev(l+1)
+         zwq(l)=q(l)*zw(l)
+      enddo
+      zwq(llm+1)=0.
+      zw(llm+1)=0.
+ 
+      do l=1,llm
+         qold=q(l)
+         q(l)=(q(l)*zm(l)+zwq(l+1)-zwq(l))/(zm(l)+zw(l+1)-zw(l))
+         print*,'ADV Q ',zm(l),zw(l),zwq(l),qold,q(l)
+      enddo
+
+ 
+      return
+      end
+
+!===============================================================
+
+
+       SUBROUTINE advect_va(llm,omega,d_t_va,d_q_va,d_u_va,d_v_va,
+     !                q,temp,u,v,
+     !            play,plev)
+!itlmd 
+!----------------------------------------------------------------------
+!   Calcul de l'advection verticale (ascendance et subsidence) de 
+!   température et d'humidité. Hypothèse : ce qui rentre de l'extérieur
+!   a les mêmes caractéristiques que l'air de la colonne 1D (WTG) ou 
+!   sans WTG rajouter une advection horizontale 
+!----------------------------------------------------------------------  
+        implicit none
+#include "YOMCST.h"
+!        argument
+        integer llm
+        real  omega(llm+1),d_t_va(llm), d_q_va(llm,3)
+        real  d_u_va(llm), d_v_va(llm)
+        real  q(llm,3),temp(llm)
+        real  u(llm),v(llm)
+        real  play(llm),plev(llm+1)
+! interne
+        integer l
+        real alpha,omgdown,omgup
+
+      do l= 1,llm
+       if(l.eq.1) then
+!si omgup pour la couche 1, alors tendance nulle
+        omgdown=max(omega(2),0.0)
+        alpha = rkappa*temp(l)*(1.+q(l,1)*rv/rd)/(play(l)*
+     &           (1.+q(l,1)))
+        d_t_va(l)= alpha*(omgdown)- 
+     &              omgdown*(temp(l)-temp(l+1))
+     &              /(play(l)-play(l+1))              
+
+        d_q_va(l,:)= -omgdown*(q(l,:)-q(l+1,:))
+     &              /(play(l)-play(l+1))              
+
+        d_u_va(l)= -omgdown*(u(l)-u(l+1))
+     &              /(play(l)-play(l+1))              
+        d_v_va(l)= -omgdown*(v(l)-v(l+1))
+     &              /(play(l)-play(l+1))              
+
+        
+       elseif(l.eq.llm) then
+        omgup=min(omega(l),0.0)
+        alpha = rkappa*temp(l)*(1.+q(l,1)*rv/rd)/(play(l)*
+     &           (1.+q(l,1)))
+        d_t_va(l)= alpha*(omgup)- 
+!bug?     &              omgup*(temp(l-1)-temp(l))/(play(l-1)-plev(l))
+     &              omgup*(temp(l-1)-temp(l))/(play(l-1)-play(l))
+        d_q_va(l,:)= -omgup*(q(l-1,:)-q(l,:))/(play(l-1)-play(l))
+        d_u_va(l)= -omgup*(u(l-1)-u(l))/(play(l-1)-play(l))
+        d_v_va(l)= -omgup*(v(l-1)-v(l))/(play(l-1)-play(l))
+       
+       else
+        omgup=min(omega(l),0.0)
+        omgdown=max(omega(l+1),0.0)
+        alpha = rkappa*temp(l)*(1.+q(l,1)*rv/rd)/(play(l)*
+     &           (1.+q(l,1)))
+        d_t_va(l)= alpha*(omgup+omgdown)- 
+     &              omgdown*(temp(l)-temp(l+1))
+     &              /(play(l)-play(l+1))-              
+!bug?     &              omgup*(temp(l-1)-temp(l))/(play(l-1)-plev(l))
+     &              omgup*(temp(l-1)-temp(l))/(play(l-1)-play(l))
+!      print*, '  ??? '
+
+        d_q_va(l,:)= -omgdown*(q(l,:)-q(l+1,:))
+     &              /(play(l)-play(l+1))-              
+     &              omgup*(q(l-1,:)-q(l,:))/(play(l-1)-play(l))
+        d_u_va(l)= -omgdown*(u(l)-u(l+1))
+     &              /(play(l)-play(l+1))-              
+     &              omgup*(u(l-1)-u(l))/(play(l-1)-play(l))
+        d_v_va(l)= -omgdown*(v(l)-v(l+1))
+     &              /(play(l)-play(l+1))-              
+     &              omgup*(v(l-1)-v(l))/(play(l-1)-play(l))
+       
+      endif
+         
+      enddo
+!fin itlmd
+        return
+        end
+!       SUBROUTINE lstendH(llm,omega,d_t_va,d_q_va,d_u_va,d_v_va,
+       SUBROUTINE lstendH(llm,nqtot,omega,d_t_va,d_q_va,
+     !                q,temp,u,v,play)
+!itlmd 
+!----------------------------------------------------------------------
+!   Calcul de l'advection verticale (ascendance et subsidence) de 
+!   température et d'humidité. Hypothèse : ce qui rentre de l'extérieur
+!   a les mêmes caractéristiques que l'air de la colonne 1D (WTG) ou 
+!   sans WTG rajouter une advection horizontale 
+!----------------------------------------------------------------------  
+        implicit none
+#include "YOMCST.h"
+!        argument
+        integer llm,nqtot
+        real  omega(llm+1),d_t_va(llm), d_q_va(llm,nqtot)
+!        real  d_u_va(llm), d_v_va(llm)
+        real  q(llm,nqtot),temp(llm)
+        real  u(llm),v(llm)
+        real  play(llm)
+        real cor(llm)
+!        real dph(llm),dudp(llm),dvdp(llm),dqdp(llm),dtdp(llm)
+        real dph(llm),dqdp(llm),dtdp(llm)
+! interne
+        integer l,k
+        real alpha,omdn,omup
+
+!        dudp=0.
+!        dvdp=0.
+        dqdp=0.
+        dtdp=0.
+!        d_u_va=0.
+!        d_v_va=0.
+
+      cor(:) = rkappa*temp*(1.+q(:,1)*rv/rd)/(play*(1.+q(:,1)))
+
+
+      do k=2,llm-1
+
+       dph  (k-1) = (play(k  )- play(k-1  ))
+!       dudp (k-1) = (u   (k  )- u   (k-1  ))/dph(k-1)
+!       dvdp (k-1) = (v   (k  )- v   (k-1  ))/dph(k-1)
+       dqdp (k-1) = (q   (k,1)- q   (k-1,1))/dph(k-1)
+       dtdp (k-1) = (temp(k  )- temp(k-1  ))/dph(k-1)
+
+      enddo
+
+!      dudp (  llm  ) = dudp ( llm-1 )
+!      dvdp (  llm  ) = dvdp ( llm-1 )
+      dqdp (  llm  ) = dqdp ( llm-1 )
+      dtdp (  llm  ) = dtdp ( llm-1 )
+
+      do k=2,llm-1
+      omdn=max(0.0,omega(k+1))
+      omup=min(0.0,omega( k ))
+
+!      d_u_va(k)  = -omdn*dudp(k)-omup*dudp(k-1)
+!      d_v_va(k)  = -omdn*dvdp(k)-omup*dvdp(k-1)
+      d_q_va(k,1)= -omdn*dqdp(k)-omup*dqdp(k-1)
+      d_t_va(k)  = -omdn*dtdp(k)-omup*dtdp(k-1)
+     :              +(omup+omdn)*cor(k)
+      enddo
+
+      omdn=max(0.0,omega( 2 ))
+      omup=min(0.0,omega(llm))
+!      d_u_va( 1 )   = -omdn*dudp( 1 )
+!      d_u_va(llm)   = -omup*dudp(llm)
+!      d_v_va( 1 )   = -omdn*dvdp( 1 )
+!      d_v_va(llm)   = -omup*dvdp(llm)
+      d_q_va( 1 ,1) = -omdn*dqdp( 1 )
+      d_q_va(llm,1) = -omup*dqdp(llm)
+      d_t_va( 1 )   = -omdn*dtdp( 1 )+omdn*cor( 1 )
+      d_t_va(llm)   = -omup*dtdp(llm)!+omup*cor(llm)
+
+!      if(abs(rlat(1))>10.) then
+!     Calculate the tendency due agestrophic motions
+!      du_age = fcoriolis*(v-vg)
+!      dv_age = fcoriolis*(ug-u)
+!      endif
+
+!       call writefield_phy('d_t_va',d_t_va,llm)
+
+          return
+         end
+
+!======================================================================
+      SUBROUTINE read_togacoare(fich_toga,nlev_toga,nt_toga
+     :             ,ts_toga,plev_toga,t_toga,q_toga,u_toga,v_toga,w_toga
+     :             ,ht_toga,vt_toga,hq_toga,vq_toga)
+      implicit none
+
+c-------------------------------------------------------------------------
+c Read TOGA-COARE forcing data 
+c-------------------------------------------------------------------------
+
+      integer nlev_toga,nt_toga
+      real ts_toga(nt_toga),plev_toga(nlev_toga,nt_toga)
+      real t_toga(nlev_toga,nt_toga),q_toga(nlev_toga,nt_toga)
+      real u_toga(nlev_toga,nt_toga),v_toga(nlev_toga,nt_toga)
+      real w_toga(nlev_toga,nt_toga)
+      real ht_toga(nlev_toga,nt_toga),vt_toga(nlev_toga,nt_toga)
+      real hq_toga(nlev_toga,nt_toga),vq_toga(nlev_toga,nt_toga)
+      character*80 fich_toga
+
+      integer no,l,k,ip
+      real riy,rim,rid,rih,bid
+
+      integer iy,im,id,ih
+      
+       real plev_min
+
+       plev_min = 55.  ! pas de tendance de vap. d eau au-dessus de 55 hPa
+
+      open(21,file=trim(fich_toga),form='formatted')
+      read(21,'(a)') 
+      do ip = 1, nt_toga
+      read(21,'(a)') 
+      read(21,'(a)') 
+      read(21,223) iy, im, id, ih, bid, ts_toga(ip), bid,bid,bid,bid
+      read(21,'(a)') 
+      read(21,'(a)') 
+
+       do k = 1, nlev_toga
+         read(21,230) plev_toga(k,ip), t_toga(k,ip), q_toga(k,ip) 
+     :       ,u_toga(k,ip), v_toga(k,ip), w_toga(k,ip)
+     :       ,ht_toga(k,ip), vt_toga(k,ip), hq_toga(k,ip), vq_toga(k,ip)
+
+! conversion in SI units:
+         t_toga(k,ip)=t_toga(k,ip)+273.15     ! K
+         q_toga(k,ip)=q_toga(k,ip)*0.001      ! kg/kg
+         w_toga(k,ip)=w_toga(k,ip)*100./3600. ! Pa/s
+! no water vapour tendency above 55 hPa
+         if (plev_toga(k,ip) .lt. plev_min) then
+          q_toga(k,ip) = 0.
+          hq_toga(k,ip) = 0.
+          vq_toga(k,ip) =0.
+         endif
+       enddo
+
+         ts_toga(ip)=ts_toga(ip)+273.15       ! K
+       enddo
+       close(21)
+
+  223 format(4i3,6f8.2)
+  226 format(f7.1,1x,10f8.2)
+  227 format(f7.1,1x,1p,4e11.3)
+  230 format(6f9.3,4e11.3)
+
+          return
+          end
+
+!=====================================================================
+      subroutine read_twpice(fich_twpice,nlevel,ntime
+     :     ,T_srf,plev,T,q,u,v,omega
+     :     ,T_adv_h,T_adv_v,q_adv_h,q_adv_v)
+
+!program reading forcings of the TWP-ICE experiment
+
+!      use netcdf
+
+      implicit none
+
+#include "netcdf.inc"
+
+      integer ntime,nlevel
+      integer l,k
+      character*80 :: fich_twpice
+      real*8 time(ntime)
+      real*8 lat, lon, alt, phis	
+      real*8 lev(nlevel)
+      real*8 plev(nlevel,ntime)
+
+      real*8 T(nlevel,ntime)
+      real*8 q(nlevel,ntime),u(nlevel,ntime)
+      real*8 v(nlevel,ntime)
+      real*8 omega(nlevel,ntime), div(nlevel,ntime)
+      real*8 T_adv_h(nlevel,ntime)
+      real*8 T_adv_v(nlevel,ntime), q_adv_h(nlevel,ntime)
+      real*8 q_adv_v(nlevel,ntime)	
+      real*8 s(nlevel,ntime), s_adv_h(nlevel,ntime)
+      real*8 s_adv_v(nlevel,ntime)
+      real*8 p_srf_aver(ntime), p_srf_center(ntime)
+      real*8 T_srf(ntime)
+
+      integer nid, ierr
+      integer nbvar3d
+      parameter(nbvar3d=20)
+      integer var3didin(nbvar3d)
+
+      ierr = NF_OPEN(fich_twpice,NF_NOWRITE,nid)
+      if (ierr.NE.NF_NOERR) then
+         write(*,*) 'ERROR: Pb opening forcings cdf file '
+         write(*,*) NF_STRERROR(ierr)
+         stop ""
+      endif
+
+      ierr=NF_INQ_VARID(nid,"lat",var3didin(1))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'lat'
+         endif
+      
+       ierr=NF_INQ_VARID(nid,"lon",var3didin(2))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'lon'
+         endif
+
+       ierr=NF_INQ_VARID(nid,"alt",var3didin(3))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'alt'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"phis",var3didin(4))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'phis'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"T",var3didin(5))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'T'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"q",var3didin(6))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'q'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"u",var3didin(7))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'u'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"v",var3didin(8))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'v'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"omega",var3didin(9))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'omega'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"div",var3didin(10))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'div'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"T_adv_h",var3didin(11))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'T_adv_h'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"T_adv_v",var3didin(12))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'T_adv_v'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"q_adv_h",var3didin(13))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'q_adv_h'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"q_adv_v",var3didin(14))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'q_adv_v'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"s",var3didin(15))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 's'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"s_adv_h",var3didin(16))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 's_adv_h'
+         endif
+    
+      ierr=NF_INQ_VARID(nid,"s_adv_v",var3didin(17))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 's_adv_v'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"p_srf_aver",var3didin(18))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'p_srf_aver'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"p_srf_center",var3didin(19))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'p_srf_center'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"T_srf",var3didin(20))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'T_srf'
+         endif
+
+!dimensions lecture
+      call catchaxis(nid,ntime,nlevel,time,lev,ierr)
+
+!pressure 
+       do l=1,ntime
+       do k=1,nlevel
+          plev(k,l)=lev(k)
+       enddo
+       enddo
+          
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(1),lat)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(1),lat)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture lat ok',lat
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(2),lon)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(2),lon)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture lon ok',lon
+ 
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(3),alt)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(3),alt)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!          write(*,*)'lecture alt ok',alt
+ 
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(4),phis)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(4),phis)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!          write(*,*)'lecture phis ok',phis
+          
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(5),T)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(5),T)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture T ok'
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(6),q)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(6),q)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture q ok'
+!q in kg/kg
+       do l=1,ntime
+       do k=1,nlevel
+          q(k,l)=q(k,l)/1000.
+       enddo
+       enddo
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(7),u)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(7),u)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture u ok'
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(8),v)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(8),v)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture v ok'
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(9),omega)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(9),omega)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture omega ok'
+!omega in mb/hour
+       do l=1,ntime
+       do k=1,nlevel
+          omega(k,l)=omega(k,l)*100./3600.
+       enddo
+       enddo
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(10),div)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(10),div)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture div ok'
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(11),T_adv_h)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(11),T_adv_h)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture T_adv_h ok'
+!T adv in K/s
+       do l=1,ntime
+       do k=1,nlevel
+          T_adv_h(k,l)=T_adv_h(k,l)/3600.
+       enddo
+       enddo
+
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(12),T_adv_v)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(12),T_adv_v)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture T_adv_v ok'
+!T adv in K/s
+       do l=1,ntime
+       do k=1,nlevel
+          T_adv_v(k,l)=T_adv_v(k,l)/3600.
+       enddo
+       enddo
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(13),q_adv_h)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(13),q_adv_h)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture q_adv_h ok'
+!q adv in kg/kg/s
+       do l=1,ntime
+       do k=1,nlevel
+          q_adv_h(k,l)=q_adv_h(k,l)/1000./3600.
+       enddo
+       enddo
+
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(14),q_adv_v)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(14),q_adv_v)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture q_adv_v ok'
+!q adv in kg/kg/s
+       do l=1,ntime
+       do k=1,nlevel
+          q_adv_v(k,l)=q_adv_v(k,l)/1000./3600.
+       enddo
+       enddo
+
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(15),s)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(15),s)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(16),s_adv_h)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(16),s_adv_h)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(17),s_adv_v)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(17),s_adv_v)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(18),p_srf_aver)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(18),p_srf_aver)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(19),p_srf_center)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(19),p_srf_center)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(20),T_srf)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(20),T_srf)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture T_srf ok', T_srf
+
+         return 
+         end subroutine read_twpice
+!=====================================================================
+         subroutine catchaxis(nid,ttm,llm,time,lev,ierr)
+
+!         use netcdf
+
+         implicit none
+#include "netcdf.inc"
+         integer nid,ttm,llm
+         real*8 time(ttm)
+         real*8 lev(llm)
+         integer ierr
+
+         integer i
+         integer timevar,levvar
+         integer timelen,levlen
+         integer timedimin,levdimin
+
+! Control & lecture on dimensions
+! ===============================
+         ierr=NF_INQ_DIMID(nid,"time",timedimin)
+         ierr=NF_INQ_VARID(nid,"time",timevar)
+         if (ierr.NE.NF_NOERR) then
+            write(*,*) 'ERROR: Field <time> is missing'
+            stop ""  
+         endif
+         ierr=NF_INQ_DIMLEN(nid,timedimin,timelen)
+
+         ierr=NF_INQ_DIMID(nid,"lev",levdimin)
+         ierr=NF_INQ_VARID(nid,"lev",levvar)
+         if (ierr.NE.NF_NOERR) then
+             write(*,*) 'ERROR: Field <lev> is lacking'
+             stop "" 
+         endif
+         ierr=NF_INQ_DIMLEN(nid,levdimin,levlen)
+
+         if((timelen/=ttm).or.(levlen/=llm)) then
+            write(*,*) 'ERROR: Not the good lenght for axis'
+            write(*,*) 'longitude: ',timelen,ttm+1
+            write(*,*) 'latitude: ',levlen,llm
+            stop ""  
+         endif
+
+!#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,timevar,time)
+         ierr = NF_GET_VAR_DOUBLE(nid,levvar,lev)
+!#else
+!        ierr = NF_GET_VAR_REAL(nid,timevar,time)
+!        ierr = NF_GET_VAR_REAL(nid,levvar,lev)
+!#endif
+
+       return
+       end
+
+!======================================================================
+      SUBROUTINE read_rico(fich_rico,nlev_rico,ps_rico,play
+     :             ,ts_rico,t_rico,q_rico,u_rico,v_rico,w_rico
+     :             ,dth_dyn,dqh_dyn)
+      implicit none
+
+c-------------------------------------------------------------------------
+c Read RICO forcing data 
+c-------------------------------------------------------------------------
+#include "dimensions.h"
+
+
+      integer nlev_rico
+      real ts_rico,ps_rico
+      real t_rico(llm),q_rico(llm)
+      real u_rico(llm),v_rico(llm)
+      real w_rico(llm)
+      real dth_dyn(llm)
+      real dqh_dyn(llm)
+      
+
+      real play(llm),zlay(llm)
+     
+
+      real prico(nlev_rico),zrico(nlev_rico)
+
+      character*80 fich_rico
+
+      integer k,l
+
+      
+      print*,fich_rico
+      open(21,file=trim(fich_rico),form='formatted')
+        do k=1,llm
+      zlay(k)=0.
+         enddo
+      
+        read(21,*) ps_rico,ts_rico
+        prico(1)=ps_rico
+        zrico(1)=0.0
+      do l=2,nlev_rico
+        read(21,*) k,prico(l),zrico(l)
+      enddo
+       close(21)
+
+      do k=1,llm
+        do l=1,80
+          if(prico(l)>play(k)) then
+              if(play(k)>prico(l+1)) then
+                zlay(k)=zrico(l)+(play(k)-prico(l)) * 
+     &              (zrico(l+1)-zrico(l))/(prico(l+1)-prico(l))
+              else
+                zlay(k)=zrico(l)+(play(k)-prico(80))* 
+     &              (zrico(81)-zrico(80))/(prico(81)-prico(80))
+              endif
+          endif
+        enddo
+        print*,k,zlay(k)
+        ! U
+        if(0 < zlay(k) .and. zlay(k) < 4000) then
+          u_rico(k)=-9.9 + (-1.9 + 9.9)*zlay(k)/4000
+        elseif(4000 < zlay(k) .and. zlay(k) < 12000) then
+       u_rico(k)=  -1.9 + (30.0 + 1.9) / 
+     :          (12000 - 4000) * (zlay(k) - 4000)
+        elseif(12000 < zlay(k) .and. zlay(k) < 13000) then
+          u_rico(k)=30.0
+        elseif(13000 < zlay(k) .and. zlay(k) < 20000) then
+          u_rico(k)=30.0 - (30.0) / 
+     : (20000 - 13000) * (zlay(k) - 13000)
+        else
+          u_rico(k)=0.0
+        endif
+
+!Q_v
+        if(0 < zlay(k) .and. zlay(k) < 740) then
+          q_rico(k)=16.0 + (13.8 - 16.0) / (740) * zlay(k)
+        elseif(740 < zlay(k) .and. zlay(k) < 3260) then
+          q_rico(k)=13.8 + (2.4 - 13.8) / 
+     :          (3260 - 740) * (zlay(k) - 740)
+        elseif(3260 < zlay(k) .and. zlay(k) < 4000) then
+          q_rico(k)=2.4 + (1.8 - 2.4) / 
+     :               (4000 - 3260) * (zlay(k) - 3260)
+        elseif(4000 < zlay(k) .and. zlay(k) < 9000) then
+          q_rico(k)=1.8 + (0 - 1.8) / 
+     :             (10000 - 4000) * (zlay(k) - 4000)
+        else
+          q_rico(k)=0.0
+        endif
+
+!T
+        if(0 < zlay(k) .and. zlay(k) < 740) then
+          t_rico(k)=299.2 + (292.0 - 299.2) / (740) * zlay(k)
+        elseif(740 < zlay(k) .and. zlay(k) < 4000) then
+          t_rico(k)=292.0 + (278.0 - 292.0) /
+     :       (4000 - 740) * (zlay(k) - 740)
+        elseif(4000 < zlay(k) .and. zlay(k) < 15000) then
+          t_rico(k)=278.0 + (203.0 - 278.0) /
+     :       (15000 - 4000) * (zlay(k) - 4000)
+        elseif(15000 < zlay(k) .and. zlay(k) < 17500) then
+          t_rico(k)=203.0 + (194.0 - 203.0) / 
+     :       (17500 - 15000)* (zlay(k) - 15000)
+        elseif(17500 < zlay(k) .and. zlay(k) < 20000) then
+          t_rico(k)=194.0 + (206.0 - 194.0) /
+     :       (20000 - 17500)* (zlay(k) - 17500)
+        elseif(20000 < zlay(k) .and. zlay(k) < 60000) then
+          t_rico(k)=206.0 + (270.0 - 206.0) / 
+     :        (60000 - 20000)* (zlay(k) - 20000)
+        endif
+
+! W
+        if(0 < zlay(k) .and. zlay(k) < 2260 ) then
+          w_rico(k)=- (0.005/2260) * zlay(k)
+        elseif(2260 < zlay(k) .and. zlay(k) < 4000 ) then
+          w_rico(k)=- 0.005
+        elseif(4000 < zlay(k) .and. zlay(k) < 5000 ) then
+       w_rico(k)=- 0.005 + (0.005/ (5000 - 4000)) * (zlay(k) - 4000)
+        else
+          w_rico(k)=0.0
+        endif
+
+! dThrz+dTsw0+dTlw0
+        if(0 < zlay(k) .and. zlay(k) < 4000) then
+          dth_dyn(k)=- 2.51 / 86400 + (-2.18 + 2.51 )/ 
+     :               (86400*4000) * zlay(k)
+        elseif(4000 < zlay(k) .and. zlay(k) < 5000) then
+          dth_dyn(k)=- 2.18 / 86400 + ( 2.18 ) /
+     :           (86400*(5000 - 4000)) * (zlay(k) - 4000)
+        else
+          dth_dyn(k)=0.0
+        endif
+! dQhrz
+        if(0 < zlay(k) .and. zlay(k) < 3000) then
+          dqh_dyn(k)=-1.0 / 86400 + (0.345 + 1.0)/
+     :                    (86400*3000) * (zlay(k))
+        elseif(3000 < zlay(k) .and. zlay(k) < 4000) then
+          dqh_dyn(k)=0.345 / 86400
+        elseif(4000 < zlay(k) .and. zlay(k) < 5000) then
+          dqh_dyn(k)=0.345 / 86400 + 
+     +   (-0.345)/(86400 * (5000 - 4000)) * (zlay(k)-4000)
+        else
+          dqh_dyn(k)=0.0
+        endif
+
+!?        if(play(k)>6e4) then
+!?          ratqs0(1,k)=ratqsbas*(plev(1)-play(k))/(plev(1)-6e4)
+!?        elseif((play(k)>3e4).and.(play(k)<6e4)) then
+!?          ratqs0(1,k)=ratqsbas+(ratqshaut-ratqsbas)&
+!?                          *(6e4-play(k))/(6e4-3e4)
+!?        else
+!?          ratqs0(1,k)=ratqshaut
+!?        endif
+
+      enddo
+
+      do k=1,llm
+      q_rico(k)=q_rico(k)/1e3 
+      dqh_dyn(k)=dqh_dyn(k)/1e3
+      v_rico(k)=-3.8
+      enddo
+
+          return
+          end
+
+!=====================================================================
+c-------------------------------------------------------------------------
+      SUBROUTINE read_armcu(fich_armcu,nlev_armcu,nt_armcu,
+     : sens,flat,adv_theta,rad_theta,adv_qt)
+      implicit none
+
+c-------------------------------------------------------------------------
+c Read ARM_CU case forcing data
+c-------------------------------------------------------------------------
+
+      integer nlev_armcu,nt_armcu
+      real sens(nt_armcu),flat(nt_armcu)
+      real adv_theta(nt_armcu),rad_theta(nt_armcu),adv_qt(nt_armcu)
+      character*80 fich_armcu
+
+      integer no,l,k,ip
+      real riy,rim,rid,rih,bid
+
+      integer iy,im,id,ih,in
+
+      open(21,file=trim(fich_armcu),form='formatted')
+      read(21,'(a)')
+      do ip = 1, nt_armcu
+      read(21,'(a)')
+      read(21,'(a)')
+      read(21,223) iy, im, id, ih, in, sens(ip),flat(ip),
+     :             adv_theta(ip),rad_theta(ip),adv_qt(ip)
+      print *,'forcages=',iy,im,id,ih,in, sens(ip),flat(ip),
+     :             adv_theta(ip),rad_theta(ip),adv_qt(ip)
+      enddo
+      close(21)
+
+  223 format(5i3,5f8.3)
+  226 format(f7.1,1x,10f8.2)
+  227 format(f7.1,1x,1p,4e11.3)
+  230 format(6f9.3,4e11.3)
+
+          return
+          end
+
+!=====================================================================
+       SUBROUTINE interp_toga_vertical(play,nlev_toga,plev_prof
+     :         ,t_prof,q_prof,u_prof,v_prof,w_prof
+     :         ,ht_prof,vt_prof,hq_prof,vq_prof
+     :         ,t_mod,q_mod,u_mod,v_mod,w_mod
+     :         ,ht_mod,vt_mod,hq_mod,vq_mod,mxcalc)
+ 
+       implicit none
+ 
+#include "dimensions.h"
+
+c-------------------------------------------------------------------------
+c Vertical interpolation of TOGA-COARE forcing data onto model levels
+c-------------------------------------------------------------------------
+ 
+       integer nlevmax
+       parameter (nlevmax=41)
+       integer nlev_toga,mxcalc
+!       real play(llm), plev_prof(nlevmax) 
+!       real t_prof(nlevmax),q_prof(nlevmax)
+!       real u_prof(nlevmax),v_prof(nlevmax), w_prof(nlevmax)
+!       real ht_prof(nlevmax),vt_prof(nlevmax)
+!       real hq_prof(nlevmax),vq_prof(nlevmax)
+ 
+       real play(llm), plev_prof(nlev_toga) 
+       real t_prof(nlev_toga),q_prof(nlev_toga)
+       real u_prof(nlev_toga),v_prof(nlev_toga), w_prof(nlev_toga)
+       real ht_prof(nlev_toga),vt_prof(nlev_toga)
+       real hq_prof(nlev_toga),vq_prof(nlev_toga)
+ 
+       real t_mod(llm),q_mod(llm)
+       real u_mod(llm),v_mod(llm), w_mod(llm)
+       real ht_mod(llm),vt_mod(llm)
+       real hq_mod(llm),vq_mod(llm)
+ 
+       integer l,k,k1,k2,kp
+       real aa,frac,frac1,frac2,fact
+ 
+       do l = 1, llm
+
+        if (play(l).ge.plev_prof(nlev_toga)) then
+ 
+        mxcalc=l
+         k1=0
+         k2=0
+
+         if (play(l).le.plev_prof(1)) then
+
+         do k = 1, nlev_toga-1
+          if (play(l).le.plev_prof(k) 
+     :       .and. play(l).gt.plev_prof(k+1)) then
+            k1=k
+            k2=k+1
+          endif
+         enddo
+
+         if (k1.eq.0 .or. k2.eq.0) then
+          write(*,*) 'PB! k1, k2 = ',k1,k2
+          write(*,*) 'l,play(l) = ',l,play(l)/100
+         do k = 1, nlev_toga-1
+          write(*,*) 'k,plev_prof(k) = ',k,plev_prof(k)/100
+         enddo
+         endif
+
+         frac = (plev_prof(k2)-play(l))/(plev_prof(k2)-plev_prof(k1))
+         t_mod(l)= t_prof(k2) - frac*(t_prof(k2)-t_prof(k1))
+         q_mod(l)= q_prof(k2) - frac*(q_prof(k2)-q_prof(k1))
+         u_mod(l)= u_prof(k2) - frac*(u_prof(k2)-u_prof(k1))
+         v_mod(l)= v_prof(k2) - frac*(v_prof(k2)-v_prof(k1))
+         w_mod(l)= w_prof(k2) - frac*(w_prof(k2)-w_prof(k1))
+         ht_mod(l)= ht_prof(k2) - frac*(ht_prof(k2)-ht_prof(k1))
+         vt_mod(l)= vt_prof(k2) - frac*(vt_prof(k2)-vt_prof(k1))
+         hq_mod(l)= hq_prof(k2) - frac*(hq_prof(k2)-hq_prof(k1))
+         vq_mod(l)= vq_prof(k2) - frac*(vq_prof(k2)-vq_prof(k1))
+     
+         else !play>plev_prof(1)
+
+         k1=1
+         k2=2
+         frac1 = (play(l)-plev_prof(k2))/(plev_prof(k1)-plev_prof(k2))
+         frac2 = (play(l)-plev_prof(k1))/(plev_prof(k1)-plev_prof(k2))
+         t_mod(l)= frac1*t_prof(k1) - frac2*t_prof(k2)
+         q_mod(l)= frac1*q_prof(k1) - frac2*q_prof(k2)
+         u_mod(l)= frac1*u_prof(k1) - frac2*u_prof(k2)
+         v_mod(l)= frac1*v_prof(k1) - frac2*v_prof(k2)
+         w_mod(l)= frac1*w_prof(k1) - frac2*w_prof(k2)
+         ht_mod(l)= frac1*ht_prof(k1) - frac2*ht_prof(k2)
+         vt_mod(l)= frac1*vt_prof(k1) - frac2*vt_prof(k2)
+         hq_mod(l)= frac1*hq_prof(k1) - frac2*hq_prof(k2)
+         vq_mod(l)= frac1*vq_prof(k1) - frac2*vq_prof(k2)
+
+         endif ! play.le.plev_prof(1)
+
+        else ! above max altitude of forcing file
+ 
+cjyg
+         fact=20.*(plev_prof(nlev_toga)-play(l))/plev_prof(nlev_toga) !jyg
+         fact = max(fact,0.)                                           !jyg
+         fact = exp(-fact)                                             !jyg
+         t_mod(l)= t_prof(nlev_toga)                                   !jyg
+         q_mod(l)= q_prof(nlev_toga)*fact                              !jyg
+         u_mod(l)= u_prof(nlev_toga)*fact                              !jyg
+         v_mod(l)= v_prof(nlev_toga)*fact                              !jyg
+         w_mod(l)= 0.0                                                 !jyg
+         ht_mod(l)= ht_prof(nlev_toga)                                 !jyg
+         vt_mod(l)= vt_prof(nlev_toga)                                 !jyg
+         hq_mod(l)= hq_prof(nlev_toga)*fact                            !jyg
+         vq_mod(l)= vq_prof(nlev_toga)*fact                            !jyg
+ 
+        endif ! play
+ 
+       enddo ! l
+
+!       do l = 1,llm
+!       print *,'t_mod(l),q_mod(l),ht_mod(l),hq_mod(l) ',
+!     $        l,t_mod(l),q_mod(l),ht_mod(l),hq_mod(l)
+!       enddo
+ 
+          return
+          end
+ 
+!======================================================================
+        SUBROUTINE interp_toga_time(day,day1,annee_ref
+     i             ,year_ini_toga,day_ini_toga,nt_toga,dt_toga,nlev_toga
+     i             ,ts_toga,plev_toga,t_toga,q_toga,u_toga,v_toga,w_toga
+     i             ,ht_toga,vt_toga,hq_toga,vq_toga
+     o             ,ts_prof,plev_prof,t_prof,q_prof,u_prof,v_prof,w_prof
+     o             ,ht_prof,vt_prof,hq_prof,vq_prof)
+        implicit none
+
+!---------------------------------------------------------------------------------------
+! Time interpolation of a 2D field to the timestep corresponding to day
+!
+! day: current julian day (e.g. 717538.2)
+! day1: first day of the simulation
+! nt_toga: total nb of data in the forcing (e.g. 480 for TOGA-COARE)
+! dt_toga: total time interval (in sec) between 2 forcing data (e.g. 6h for TOGA-COARE)
+!---------------------------------------------------------------------------------------
+
+#include "compar1d.h"
+
+! inputs:
+        integer annee_ref
+        integer nt_toga,nlev_toga
+        integer year_ini_toga
+        real day, day1,day_ini_toga,dt_toga
+        real ts_toga(nt_toga)
+        real plev_toga(nlev_toga,nt_toga),t_toga(nlev_toga,nt_toga)
+        real q_toga(nlev_toga,nt_toga),u_toga(nlev_toga,nt_toga)
+        real v_toga(nlev_toga,nt_toga),w_toga(nlev_toga,nt_toga)
+        real ht_toga(nlev_toga,nt_toga),vt_toga(nlev_toga,nt_toga)
+        real hq_toga(nlev_toga,nt_toga),vq_toga(nlev_toga,nt_toga)
+! outputs:
+        real ts_prof
+        real plev_prof(nlev_toga),t_prof(nlev_toga)
+        real q_prof(nlev_toga),u_prof(nlev_toga)
+        real v_prof(nlev_toga),w_prof(nlev_toga)
+        real ht_prof(nlev_toga),vt_prof(nlev_toga)
+        real hq_prof(nlev_toga),vq_prof(nlev_toga)
+! local:
+        integer it_toga1, it_toga2,k
+        real timeit,time_toga1,time_toga2,frac
+
+
+        if (forcing_type.eq.2) then
+! Check that initial day of the simulation consistent with TOGA-COARE period:
+       if (annee_ref.ne.1992 .and. annee_ref.ne.1993) then
+        print*,'Pour TOGA-COARE, annee_ref doit etre 1992 ou 1993'
+        print*,'Changer annee_ref dans run.def'
+        stop
+       endif
+       if (annee_ref.eq.1992 .and. day1.lt.day_ini_toga) then
+        print*,'TOGA-COARE a débuté le 1er Nov 1992 (jour julien=306)'
+        print*,'Changer dayref dans run.def'
+        stop
+       endif
+       if (annee_ref.eq.1993 .and. day1.gt.day_ini_toga+119) then
+        print*,'TOGA-COARE a fini le 28 Feb 1993 (jour julien=59)'
+        print*,'Changer dayref ou nday dans run.def'
+        stop
+       endif
+
+       else if (forcing_type.eq.4) then
+
+! Check that initial day of the simulation consistent with TWP-ICE period:
+       if (annee_ref.ne.2006) then
+        print*,'Pour TWP-ICE, annee_ref doit etre 2006'
+        print*,'Changer annee_ref dans run.def'
+        stop
+       endif
+       if (annee_ref.eq.2006 .and. day1.lt.day_ini_toga) then
+        print*,'TWP-ICE a debute le 17 Jan 2006 (jour julien=17)'
+        print*,'Changer dayref dans run.def'
+        stop
+       endif
+       if (annee_ref.eq.2006 .and. day1.gt.day_ini_toga+26) then
+        print*,'TWP-ICE a fini le 12 Feb 2006 (jour julien=43)'
+        print*,'Changer dayref ou nday dans run.def'
+        stop
+       endif
+
+       endif
+
+! Determine timestep relative to the 1st day of TOGA-COARE:
+!       timeit=(day-day1)*86400.
+!       if (annee_ref.eq.1992) then
+!        timeit=(day-day_ini_toga)*86400.
+!       else
+!        timeit=(day+61.-1.)*86400. ! 61 days between Nov01 and Dec31 1992
+!       endif
+      timeit=(day-day_ini_toga)*86400
+
+! Determine the closest observation times:
+       it_toga1=INT(timeit/dt_toga)+1
+       it_toga2=it_toga1 + 1
+       time_toga1=(it_toga1-1)*dt_toga
+       time_toga2=(it_toga2-1)*dt_toga
+
+       if (it_toga1 .ge. nt_toga) then
+        write(*,*) 'PB-stop: day, it_toga1, it_toga2, timeit: '
+     :        ,day,it_toga1,it_toga2,timeit/86400.
+        stop
+       endif
+
+! time interpolation:
+       frac=(time_toga2-timeit)/(time_toga2-time_toga1)
+       frac=max(frac,0.0)
+
+       ts_prof = ts_toga(it_toga2)
+     :          -frac*(ts_toga(it_toga2)-ts_toga(it_toga1))
+
+!        print*,
+!     :'day,annee_ref,day_ini_toga,timeit,it_toga1,it_toga2,SST:',
+!     :day,annee_ref,day_ini_toga,timeit/86400.,it_toga1,it_toga2,ts_prof
+
+       do k=1,nlev_toga
+        plev_prof(k) = 100.*(plev_toga(k,it_toga2)
+     :          -frac*(plev_toga(k,it_toga2)-plev_toga(k,it_toga1)))
+        t_prof(k) = t_toga(k,it_toga2)
+     :          -frac*(t_toga(k,it_toga2)-t_toga(k,it_toga1))
+        q_prof(k) = q_toga(k,it_toga2)
+     :          -frac*(q_toga(k,it_toga2)-q_toga(k,it_toga1))
+        u_prof(k) = u_toga(k,it_toga2)
+     :          -frac*(u_toga(k,it_toga2)-u_toga(k,it_toga1))
+        v_prof(k) = v_toga(k,it_toga2)
+     :          -frac*(v_toga(k,it_toga2)-v_toga(k,it_toga1))
+        w_prof(k) = w_toga(k,it_toga2)
+     :          -frac*(w_toga(k,it_toga2)-w_toga(k,it_toga1))
+        ht_prof(k) = ht_toga(k,it_toga2)
+     :          -frac*(ht_toga(k,it_toga2)-ht_toga(k,it_toga1))
+        vt_prof(k) = vt_toga(k,it_toga2)
+     :          -frac*(vt_toga(k,it_toga2)-vt_toga(k,it_toga1))
+        hq_prof(k) = hq_toga(k,it_toga2)
+     :          -frac*(hq_toga(k,it_toga2)-hq_toga(k,it_toga1))
+        vq_prof(k) = vq_toga(k,it_toga2)
+     :          -frac*(vq_toga(k,it_toga2)-vq_toga(k,it_toga1))
+        enddo
+
+        return
+        END
+
+!======================================================================
+        SUBROUTINE interp_armcu_time(day,day1,annee_ref
+     i             ,year_ini_armcu,day_ini_armcu,nt_armcu,dt_armcu
+     i             ,nlev_armcu,fs_armcu,fl_armcu,at_armcu,rt_armcu
+     i             ,aqt_armcu,fs_prof,fl_prof,at_prof,rt_prof,aqt_prof)
+        implicit none
+
+!---------------------------------------------------------------------------------------
+! Time interpolation of a 2D field to the timestep corresponding to day
+!
+! day: current julian day (e.g. 717538.2)
+! day1: first day of the simulation
+! nt_armcu: total nb of data in the forcing (e.g. 31 for armcu)
+! dt_armcu: total time interval (in sec) between 2 forcing data (e.g. 1/2h for armcu)
+! fs= sensible flux
+! fl= latent flux
+! at,rt,aqt= advective and radiative tendencies
+!---------------------------------------------------------------------------------------
+
+! inputs:
+        integer annee_ref
+        integer nt_armcu,nlev_armcu
+        integer year_ini_armcu
+        real day, day1,day_ini_armcu,dt_armcu
+        real fs_armcu(nt_armcu),fl_armcu(nt_armcu),at_armcu(nt_armcu)
+        real rt_armcu(nt_armcu),aqt_armcu(nt_armcu)
+! outputs:
+        real fs_prof,fl_prof,at_prof,rt_prof,aqt_prof
+! local:
+        integer it_armcu1, it_armcu2,k
+        real timeit,time_armcu1,time_armcu2,frac
+
+! Check that initial day of the simulation consistent with ARMCU period:
+       if (annee_ref.ne.1997 ) then
+        print*,'Pour ARMCU, annee_ref doit etre 1997 '
+        print*,'Changer annee_ref dans run.def'
+        stop
+       endif
+
+      timeit=(day-day_ini_armcu)*86400
+
+! Determine the closest observation times:
+       it_armcu1=INT(timeit/dt_armcu)+1
+       it_armcu2=it_armcu1 + 1
+       time_armcu1=(it_armcu1-1)*dt_armcu
+       time_armcu2=(it_armcu2-1)*dt_armcu
+       print *,'timeit day day_ini_armcu',timeit,day,day_ini_armcu
+       print *,'it_armcu1,it_armcu2,time_armcu1,time_armcu2',
+     .          it_armcu1,it_armcu2,time_armcu1,time_armcu2
+
+       if (it_armcu1 .ge. nt_armcu) then
+        write(*,*) 'PB-stop: day, it_armcu1, it_armcu2, timeit: '
+     :        ,day,it_armcu1,it_armcu2,timeit/86400.
+        stop
+       endif
+
+! time interpolation:
+       frac=(time_armcu2-timeit)/(time_armcu2-time_armcu1)
+       frac=max(frac,0.0)
+
+       fs_prof = fs_armcu(it_armcu2)
+     :          -frac*(fs_armcu(it_armcu2)-fs_armcu(it_armcu1))
+       fl_prof = fl_armcu(it_armcu2)
+     :          -frac*(fl_armcu(it_armcu2)-fl_armcu(it_armcu1))
+       at_prof = at_armcu(it_armcu2)
+     :          -frac*(at_armcu(it_armcu2)-at_armcu(it_armcu1))
+       rt_prof = rt_armcu(it_armcu2)
+     :          -frac*(rt_armcu(it_armcu2)-rt_armcu(it_armcu1))
+       aqt_prof = aqt_armcu(it_armcu2)
+     :          -frac*(aqt_armcu(it_armcu2)-aqt_armcu(it_armcu1))
+
+         print*,
+     :'day,annee_ref,day_ini_armcu,timeit,it_armcu1,it_armcu2,SST:',
+     :day,annee_ref,day_ini_armcu,timeit/86400.,it_armcu1,
+     :it_armcu2,fs_prof,fl_prof,at_prof,rt_prof,aqt_prof
+
+        return
+        END
+
+!=====================================================================
+      subroutine readprofiles(nlev_max,kmax,height,
+     .           thlprof,qtprof,uprof,
+     .           vprof,e12prof,ugprof,vgprof,
+     .           wfls,dqtdxls,dqtdyls,dqtdtls,
+     .           thlpcar)
+      implicit none
+
+        integer nlev_max,kmax,kmax2
+        logical :: llesread = .true.
+
+        real height(nlev_max),thlprof(nlev_max),qtprof(nlev_max),
+     .       uprof(nlev_max),vprof(nlev_max),e12prof(nlev_max),
+     .       ugprof(nlev_max),vgprof(nlev_max),wfls(nlev_max),
+     .       dqtdxls(nlev_max),dqtdyls(nlev_max),dqtdtls(nlev_max),
+     .           thlpcar(nlev_max)
+
+        integer, parameter :: ilesfile=1
+        integer :: ierr,irad,imax,jtot,k
+        logical :: lmoist,lcoriol,ltimedep
+        real :: xsize,ysize
+        real :: ustin,wsvsurf,timerad
+        character(80) :: chmess
+
+        if(.not.(llesread)) return
+
+       open (ilesfile,file='prof.inp.001',status='old',iostat=ierr)
+        if (ierr /= 0) stop 'ERROR:Prof.inp does not exist'
+        read (ilesfile,*) kmax
+        do k=1,kmax
+          read (ilesfile,*) height(k),thlprof(k),qtprof (k),
+     .                      uprof (k),vprof  (k),e12prof(k)
+        enddo
+        close(ilesfile)
+
+       open(ilesfile,file='lscale.inp.001',status='old',iostat=ierr)
+        if (ierr /= 0) stop 'ERROR:Lscale.inp does not exist'
+        read (ilesfile,*) kmax2
+        if (kmax .ne. kmax2) then
+          print *, 'fichiers prof.inp et lscale.inp incompatibles :'
+          print *, 'nbre de niveaux : ',kmax,' et ',kmax2
+          stop 'lecture profiles'
+        endif
+        do k=1,kmax
+          read (ilesfile,*) height(k),ugprof(k),vgprof(k),wfls(k),
+     .                      dqtdxls(k),dqtdyls(k),dqtdtls(k),thlpcar(k)
+        end do
+        close(ilesfile)
+
+        return
+        end
+
+
+!======================================================================
+      subroutine readprofile_armcu(nlev_max,kmax,height,pprof,uprof,
+     .       vprof,thetaprof,tprof,qvprof,rvprof,aprof,bprof)
+!======================================================================
+      implicit none
+
+        integer nlev_max,kmax,kmax2
+        logical :: llesread = .true.
+
+        real height(nlev_max),pprof(nlev_max),tprof(nlev_max),
+     .  thetaprof(nlev_max),rvprof(nlev_max),
+     .  qvprof(nlev_max),uprof(nlev_max),vprof(nlev_max),
+     .  aprof(nlev_max+1),bprof(nlev_max+1)
+
+        integer, parameter :: ilesfile=1
+        integer, parameter :: ifile=2
+        integer :: ierr,irad,imax,jtot,k
+        logical :: lmoist,lcoriol,ltimedep
+        real :: xsize,ysize
+        real :: ustin,wsvsurf,timerad
+        character(80) :: chmess
+
+        if(.not.(llesread)) return
+
+! Read profiles at full levels
+       IF(nlev_max.EQ.19) THEN
+       open (ilesfile,file='prof.inp.19',status='old',iostat=ierr)
+       print *,'On ouvre prof.inp.19'
+       ELSE
+       open (ilesfile,file='prof.inp.40',status='old',iostat=ierr)
+       print *,'On ouvre prof.inp.40'
+       ENDIF
+        if (ierr /= 0) stop 'ERROR:Prof.inp does not exist'
+        read (ilesfile,*) kmax
+        do k=1,kmax
+          read (ilesfile,*) height(k)    ,pprof(k),  uprof(k), vprof(k),
+     .                      thetaprof(k) ,tprof(k), qvprof(k),rvprof(k)
+        enddo
+        close(ilesfile)
+
+! Vertical coordinates half levels for eta-coordinates (plev = alpha + beta * psurf) 
+       IF(nlev_max.EQ.19) THEN
+       open (ifile,file='proh.inp.19',status='old',iostat=ierr)
+       print *,'On ouvre proh.inp.19'
+       if (ierr /= 0) stop 'ERROR:Proh.inp.19 does not exist'
+       ELSE
+       open (ifile,file='proh.inp.40',status='old',iostat=ierr)
+       print *,'On ouvre proh.inp.40'
+       if (ierr /= 0) stop 'ERROR:Proh.inp.40 does not exist'
+       ENDIF
+        read (ifile,*) kmax
+        do k=1,kmax
+          read (ifile,*) jtot,aprof(k),bprof(k)
+        enddo
+        close(ifile)
+
+        return
+        end
+!===============================================================
+      function ismin(n,sx,incx)
+
+      implicit none
+      integer n,i,incx,ismin,ix
+      real sx((n-1)*incx+1),sxmin
+
+      ix=1
+      ismin=1
+      sxmin=sx(1)
+      do i=1,n-1
+         ix=ix+incx
+         if(sx(ix).lt.sxmin) then
+             sxmin=sx(ix)
+             ismin=i+1
+         endif
+      enddo
+
+      return
+      end
+
+!===============================================================
+      function ismax(n,sx,incx)
+
+      implicit none
+      integer n,i,incx,ismax,ix
+      real sx((n-1)*incx+1),sxmax
+
+      ix=1
+      ismax=1
+      sxmax=sx(1)
+      do i=1,n-1
+         ix=ix+incx
+         if(sx(ix).gt.sxmax) then
+             sxmax=sx(ix)
+             ismax=i+1
+         endif
+      enddo
+
+      return
+      end
+
Index: LMDZ5/branches/testing/libf/phy1d/1DUTILS.h_with_writelim
===================================================================
--- LMDZ5/branches/testing/libf/phy1d/1DUTILS.h_with_writelim	(revision 1665)
+++ LMDZ5/branches/testing/libf/phy1d/1DUTILS.h_with_writelim	(revision 1665)
@@ -0,0 +1,2705 @@
+!
+! $Id: conf_unicol.F 1279 2010-08-04 17:20:56Z lahellec $
+!
+c
+c
+      SUBROUTINE conf_unicol( tapedef )
+c
+#ifdef CPP_IOIPSL
+      use IOIPSL
+#else
+! if not using IOIPSL, we still need to use (a local version of) getin
+      use ioipsl_getincom
+#endif
+      IMPLICIT NONE
+c-----------------------------------------------------------------------
+c     Auteurs :   A. Lahellec  .
+c
+c     Arguments :
+c
+c     tapedef   :
+
+       INTEGER tapedef
+c
+c   Declarations :
+c   --------------
+
+#include "compar1d.h"
+#include "flux_arp.h"
+#include "fcg_gcssold.h"
+#include "fcg_racmo.h"
+#include "iniprint.h"
+c
+c
+c   local:
+c   ------
+
+c      CHARACTER ch1*72,ch2*72,ch3*72,ch4*12
+      
+c
+c  -------------------------------------------------------------------
+c
+c      .........    Initilisation parametres du lmdz1D      ..........
+c
+c---------------------------------------------------------------------
+c   initialisations:
+c   ----------------
+
+!Config  Key  = lunout
+!Config  Desc = unite de fichier pour les impressions
+!Config  Def  = 6
+!Config  Help = unite de fichier pour les impressions 
+!Config         (defaut sortie standard = 6)
+      lunout=6
+      CALL getin('lunout', lunout)
+      IF (lunout /= 5 .and. lunout /= 6) THEN
+        OPEN(lunout,FILE='lmdz.out')
+      ENDIF
+
+!Config  Key  = prt_level
+!Config  Desc = niveau d'impressions de débogage
+!Config  Def  = 0
+!Config  Help = Niveau d'impression pour le débogage
+!Config         (0 = minimum d'impression)
+c      prt_level = 0
+c      CALL getin('prt_level',prt_level)
+
+c-----------------------------------------------------------------------
+c  Parametres de controle du run:
+c-----------------------------------------------------------------------
+
+!Config  Key  = restart
+!Config  Desc = on repart des startphy et start1dyn
+!Config  Def  = false
+!Config  Help = les fichiers restart doivent etre renomme en start
+       restart = .FALSE.
+       CALL getin('restart',restart)
+
+!Config  Key  = forcing_type
+!Config  Desc = defines the way the SCM is forced:
+!Config  Def  = 0
+!!Config  Help = 0 ==> forcing_les = .true.
+!             initial profiles from file prof.inp.001
+!             no forcing by LS convergence ; 
+!             surface temperature imposed ;
+!             radiative cooling may be imposed (iflag_radia=0 in physiq.def)
+!         = 1 ==> forcing_radconv = .true.
+!             idem forcing_type = 0, but the imposed radiative cooling 
+!             is set to 0 (hence, if iflag_radia=0 in physiq.def, 
+!             then there is no radiative cooling at all)
+!         = 2 ==> forcing_toga = .true.
+!             initial profiles from TOGA-COARE IFA files 
+!             LS convergence and SST imposed from TOGA-COARE IFA files 
+!         = 3 ==> forcing_GCM2SCM = .true.
+!             initial profiles from the GCM output
+!             LS convergence imposed from the GCM output
+!         = 4 ==> forcing_twpi = .true.
+!             initial profiles from TWPICE nc files 
+!             LS convergence and SST imposed from TWPICE nc files 
+!         = 5 ==> forcing_rico = .true.
+!             initial profiles from RICO idealized
+!             LS convergence imposed from  RICO (cst) 
+!         = 40 ==> forcing_GCSSold = .true.
+!             initial profile from GCSS file
+!             LS convergence imposed from GCSS file
+!
+       forcing_type = 0
+       CALL getin('forcing_type',forcing_type)
+         imp_fcg_gcssold   = .false.
+         ts_fcg_gcssold    = .false.  
+         Tp_fcg_gcssold    = .false.  
+         Tp_ini_gcssold    = .false.  
+         xTurb_fcg_gcssold = .false. 
+        IF (forcing_type .eq.40) THEN
+          CALL getin('imp_fcg',imp_fcg_gcssold)
+          CALL getin('ts_fcg',ts_fcg_gcssold)
+          CALL getin('tp_fcg',Tp_fcg_gcssold)
+          CALL getin('tp_ini',Tp_ini_gcssold)
+          CALL getin('turb_fcg',xTurb_fcg_gcssold)
+        ENDIF
+
+!Config  Key  = ok_flux_surf
+!Config  Desc = forcage ou non par les flux de surface
+!Config  Def  = false
+!Config  Help = forcage ou non par les flux de surface
+       ok_flux_surf = .FALSE.
+       CALL getin('ok_flux_surf',ok_flux_surf)
+
+!Config  Key  = time_ini
+!Config  Desc = meaningless in this  case
+!Config  Def  = 0.
+!Config  Help = 
+       tsurf = 0.
+       CALL getin('time_ini',time_ini)
+
+!Config  Key  = rlat et rlon
+!Config  Desc = latitude et longitude
+!Config  Def  = 0.0  0.0
+!Config  Help = fixe la position de la colonne
+       xlat = 0.
+       xlon = 0.
+       CALL getin('rlat',xlat)
+       CALL getin('rlon',xlon)
+
+!Config  Key  = airephy
+!Config  Desc = Grid cell area
+!Config  Def  = 1.e11
+!Config  Help = 
+       airefi = 1.e11
+       CALL getin('airephy',airefi)
+
+!Config  Key  = nat_surf
+!Config  Desc = surface type
+!Config  Def  = 0 (ocean)
+!Config  Help = 0=ocean,1=land,2=glacier,3=banquise
+       nat_surf = 0.
+       CALL getin('nat_surf',nat_surf)
+
+!Config  Key  = tsurf
+!Config  Desc = surface temperature
+!Config  Def  = 290.
+!Config  Help = not used if type_ts_forcing=1 in lmdz1d.F
+       tsurf = 290.
+       CALL getin('tsurf',tsurf)
+
+!Config  Key  = psurf
+!Config  Desc = surface pressure
+!Config  Def  = 102400.
+!Config  Help = 
+       psurf = 102400.
+       CALL getin('psurf',psurf)
+
+!Config  Key  = zsurf
+!Config  Desc = surface altitude
+!Config  Def  = 0.
+!Config  Help = 
+       zsurf = 0.
+       CALL getin('zsurf',zsurf)
+
+!Config  Key  = rugos
+!Config  Desc = coefficient de frottement
+!Config  Def  = 0.0001
+!Config  Help = calcul du Cdrag
+       rugos = 0.0001
+       CALL getin('rugos',rugos)
+
+!Config  Key  = wtsurf et wqsurf
+!Config  Desc = ???
+!Config  Def  = 0.0 0.0
+!Config  Help = 
+       wtsurf = 0.0
+       wqsurf = 0.0
+       CALL getin('wtsurf',wtsurf)
+       CALL getin('wqsurf',wqsurf)
+
+!Config  Key  = albedo
+!Config  Desc = albedo
+!Config  Def  = 0.09
+!Config  Help = 
+       albedo = 0.09
+       CALL getin('albedo',albedo)
+
+!Config  Key  = agesno
+!Config  Desc = age de la neige
+!Config  Def  = 30.0
+!Config  Help = 
+       xagesno = 30.0
+       CALL getin('agesno',xagesno)
+
+!Config  Key  = restart_runoff
+!Config  Desc = age de la neige
+!Config  Def  = 30.0
+!Config  Help = 
+       restart_runoff = 0.0
+       CALL getin('restart_runoff',restart_runoff)
+
+!Config  Key  = qsolinp
+!Config  Desc = initial bucket water content (kg/m2) when land (5std)
+!Config  Def  = 30.0
+!Config  Help = 
+       qsolinp = 1.
+       CALL getin('qsolinp',qsolinp)
+
+!Config  Key  = zpicinp
+!Config  Desc = denivellation orographie
+!Config  Def  = 300.
+!Config  Help =  input brise
+       zpicinp = 300.
+       CALL getin('zpicinp',zpicinp)
+
+
+      write(lunout,*)' +++++++++++++++++++++++++++++++++++++++'
+      write(lunout,*)' Configuration des parametres du gcm1D: '
+      write(lunout,*)' +++++++++++++++++++++++++++++++++++++++'
+      write(lunout,*)' restart = ', restart
+      write(lunout,*)' forcing_type = ', forcing_type
+      write(lunout,*)' time_ini = ', time_ini
+      write(lunout,*)' rlat = ', xlat
+      write(lunout,*)' rlon = ', xlon
+      write(lunout,*)' airephy = ', airefi
+      write(lunout,*)' nat_surf = ', nat_surf
+      write(lunout,*)' tsurf = ', tsurf
+      write(lunout,*)' psurf = ', psurf
+      write(lunout,*)' zsurf = ', zsurf
+      write(lunout,*)' rugos = ', rugos
+      write(lunout,*)' wtsurf = ', wtsurf
+      write(lunout,*)' wqsurf = ', wqsurf
+      write(lunout,*)' albedo = ', albedo
+      write(lunout,*)' xagesno = ', xagesno
+      write(lunout,*)' restart_runoff = ', restart_runoff
+      write(lunout,*)' qsolinp = ', qsolinp
+      write(lunout,*)' zpicinp = ', zpicinp
+      IF (forcing_type .eq.40) THEN
+        write(lunout,*) '--- Forcing type GCSS Old --- with:'
+        write(lunout,*)'imp_fcg',imp_fcg_gcssold
+        write(lunout,*)'ts_fcg',ts_fcg_gcssold
+        write(lunout,*)'tp_fcg',Tp_fcg_gcssold
+        write(lunout,*)'tp_ini',Tp_ini_gcssold
+        write(lunout,*)'xturb_fcg',xTurb_fcg_gcssold
+      ENDIF
+
+      write(lunout,*)' +++++++++++++++++++++++++++++++++++++++'
+      write(lunout,*)
+c
+      RETURN
+      END
+!
+! $Id: dyn1deta0.F 1279 2010/07/30 A Lahellec$
+!
+c
+      SUBROUTINE dyn1deta0(fichnom,plev,play,phi,phis,presnivs,
+     &                          ucov,vcov,temp,q,omega2)
+      USE dimphy
+      USE mod_grid_phy_lmdz
+      USE mod_phys_lmdz_para
+      USE iophy
+      USE phys_state_var_mod
+      USE iostart
+      USE write_field_phy
+      USE infotrac
+      use control_mod
+
+      IMPLICIT NONE
+c=======================================================
+c Ecriture du fichier de redemarrage sous format NetCDF
+c=======================================================
+c   Declarations:
+c   -------------
+#include "dimensions.h"
+#include "comconst.h"
+#include "temps.h"
+!!#include "control.h"
+#include "logic.h"
+#include "netcdf.inc"
+
+c   Arguments:
+c   ----------
+      CHARACTER*(*) fichnom
+cAl1 plev tronque pour .nc mais plev(klev+1):=0
+      real :: plev(klon,klev),play (klon,klev),phi(klon,klev)
+      real :: presnivs(klon,klev)
+      real :: ucov(klon,klev),vcov(klon,klev),temp(klon,klev)
+      real :: q(klon,klev,nqtot),omega2(klon,klev)
+c      real :: ug(klev),vg(klev),fcoriolis
+      real :: phis(klon) 
+
+c   Variables locales pour NetCDF:
+c   ------------------------------
+      INTEGER nid, nvarid
+      INTEGER idim_s
+      INTEGER ierr, ierr_file 
+      INTEGER iq
+      INTEGER length
+      PARAMETER (length = 100)
+      REAL tab_cntrl(length) ! tableau des parametres du run
+      character*4 nmq(nqtot)
+      character*12 modname
+      character*80 abort_message
+      LOGICAL found
+c
+      INTEGER nb
+
+      modname = 'dyn1deta0 : '
+      nmq(1)="vap"
+      nmq(2)="cond"
+      do iq=3,nqtot
+        write(nmq(iq),'("tra",i1)') iq-2
+      enddo
+      print*,'in dyn1deta0 ',fichnom,klon,klev,nqtot
+      CALL open_startphy(fichnom)
+      print*,'after open startphy ',fichnom,nmq
+
+c
+c Lecture des parametres de controle:
+c
+      CALL get_var("controle",tab_cntrl)
+       
+
+      im         = tab_cntrl(1)
+      jm         = tab_cntrl(2)
+      lllm       = tab_cntrl(3)
+      day_ref    = tab_cntrl(4)
+      annee_ref  = tab_cntrl(5)
+c      rad        = tab_cntrl(6)
+c      omeg       = tab_cntrl(7)
+c      g          = tab_cntrl(8)
+c      cpp        = tab_cntrl(9)
+c      kappa      = tab_cntrl(10)
+c      daysec     = tab_cntrl(11)
+c      dtvr       = tab_cntrl(12)
+c      etot0      = tab_cntrl(13)
+c      ptot0      = tab_cntrl(14)
+c      ztot0      = tab_cntrl(15)
+c      stot0      = tab_cntrl(16)
+c      ang0       = tab_cntrl(17)
+c      pa         = tab_cntrl(18)
+c      preff      = tab_cntrl(19)
+c
+c      clon       = tab_cntrl(20)
+c      clat       = tab_cntrl(21)
+c      grossismx  = tab_cntrl(22)
+c      grossismy  = tab_cntrl(23)
+c
+      IF ( tab_cntrl(24).EQ.1. )  THEN
+        fxyhypb  = . TRUE .
+c        dzoomx   = tab_cntrl(25)
+c        dzoomy   = tab_cntrl(26)
+c        taux     = tab_cntrl(28)
+c        tauy     = tab_cntrl(29)
+      ELSE
+        fxyhypb = . FALSE .
+        ysinus  = . FALSE .
+        IF( tab_cntrl(27).EQ.1. ) ysinus = . TRUE. 
+      ENDIF
+
+      day_ini = tab_cntrl(30)
+      itau_dyn = tab_cntrl(31)
+c   .................................................................
+c
+c
+c      PRINT*,'rad,omeg,g,cpp,kappa',rad,omeg,g,cpp,kappa
+cAl1
+       Print*,'day_ref,annee_ref,day_ini,itau_dyn',
+     &              day_ref,annee_ref,day_ini,itau_dyn
+
+c  Lecture des champs
+c
+      plev(1,klev+1)=0.
+      CALL get_field("plev",plev,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <Plev> est absent'
+      CALL get_field("play",play,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <Play> est absent'
+      CALL get_field("phi",phi,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <Phi> est absent'
+      CALL get_field("phis",phis,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <Phis> est absent'
+      CALL get_field("presnivs",presnivs,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <Presnivs> est absent'
+      CALL get_field("ucov",ucov,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <ucov> est absent'
+      CALL get_field("vcov",vcov,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <vcov> est absent'
+      CALL get_field("temp",temp,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <temp> est absent'
+      CALL get_field("omega2",omega2,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <omega2> est absent'
+
+      Do iq=1,nqtot
+        CALL get_field("q"//nmq(iq),q(:,:,iq),found)
+        IF (.NOT. found)
+     &  PRINT*, modname//'Le champ <q'//nmq//'> est absent'
+      EndDo
+
+      CALL close_startphy
+      print*,' close startphy'
+     .      ,fichnom,play(1,1),play(1,klev),temp(1,klev)
+c
+      RETURN
+      END
+!
+! $Id: dyn1dredem.F 1279 2010/07/29 A Lahellec$
+!
+c
+      SUBROUTINE dyn1dredem(fichnom,plev,play,phi,phis,presnivs,
+     &                          ucov,vcov,temp,q,omega2)
+      USE dimphy
+      USE mod_grid_phy_lmdz
+      USE mod_phys_lmdz_para
+      USE phys_state_var_mod
+      USE iostart
+      USE infotrac
+      use control_mod
+
+      IMPLICIT NONE
+c=======================================================
+c Ecriture du fichier de redemarrage sous format NetCDF
+c=======================================================
+c   Declarations:
+c   -------------
+#include "dimensions.h"
+#include "comconst.h"
+#include "temps.h"
+!!#include "control.h"
+#include "logic.h"
+#include "netcdf.inc"
+
+c   Arguments:
+c   ----------
+      CHARACTER*(*) fichnom
+      REAL time
+cAl1 plev tronque pour .nc mais plev(klev+1):=0
+      real :: plev(klon,klev),play (klon,klev),phi(klon,klev)
+      real :: presnivs(klon,klev)
+      real :: ucov(klon,klev),vcov(klon,klev),temp(klon,klev)
+      real :: q(klon,klev,nqtot)
+      real :: omega2(klon,klev),rho(klon,klev+1)
+c      real :: ug(klev),vg(klev),fcoriolis
+      real :: phis(klon) 
+
+c   Variables locales pour NetCDF:
+c   ------------------------------
+      INTEGER nid, nvarid
+      INTEGER idim_s
+      INTEGER ierr, ierr_file 
+      INTEGER iq,l
+      INTEGER length
+      PARAMETER (length = 100)
+      REAL tab_cntrl(length) ! tableau des parametres du run
+      character*4 nmq(nqtot)
+      character*20 modname
+      character*80 abort_message
+c
+      INTEGER nb
+      SAVE nb
+      DATA nb / 0 /
+
+      REAL zan0,zjulian,hours
+      INTEGER yyears0,jjour0, mmois0
+      character*30 unites
+
+cDbg
+      CALL open_restartphy(fichnom)
+      print*,'redm1 ',fichnom,klon,klev,nqtot
+      nmq(1)="vap"
+      nmq(2)="cond"
+      nmq(3)="tra1"
+      nmq(4)="tra2"
+
+      modname = 'dyn1dredem'
+      ierr = NF_OPEN(fichnom, NF_WRITE, nid)
+      IF (ierr .NE. NF_NOERR) THEN
+         PRINT*, "Pb. d ouverture "//fichnom
+         CALL abort
+      ENDIF
+
+      DO l=1,length
+       tab_cntrl(l) = 0.
+      ENDDO
+       tab_cntrl(1)  = FLOAT(iim)
+       tab_cntrl(2)  = FLOAT(jjm)
+       tab_cntrl(3)  = FLOAT(llm)
+       tab_cntrl(4)  = FLOAT(day_ref)
+       tab_cntrl(5)  = FLOAT(annee_ref)
+       tab_cntrl(6)  = rad
+       tab_cntrl(7)  = omeg
+       tab_cntrl(8)  = g
+       tab_cntrl(9)  = cpp
+       tab_cntrl(10) = kappa
+       tab_cntrl(11) = daysec
+       tab_cntrl(12) = dtvr
+c       tab_cntrl(13) = etot0
+c       tab_cntrl(14) = ptot0
+c       tab_cntrl(15) = ztot0
+c       tab_cntrl(16) = stot0
+c       tab_cntrl(17) = ang0
+c       tab_cntrl(18) = pa
+c       tab_cntrl(19) = preff
+c
+c    .....    parametres  pour le zoom      ......   
+
+c       tab_cntrl(20)  = clon
+c       tab_cntrl(21)  = clat
+c       tab_cntrl(22)  = grossismx
+c       tab_cntrl(23)  = grossismy
+c
+      IF ( fxyhypb )   THEN
+       tab_cntrl(24) = 1.
+c       tab_cntrl(25) = dzoomx
+c       tab_cntrl(26) = dzoomy
+       tab_cntrl(27) = 0.
+c       tab_cntrl(28) = taux
+c       tab_cntrl(29) = tauy
+      ELSE
+       tab_cntrl(24) = 0.
+c       tab_cntrl(25) = dzoomx
+c       tab_cntrl(26) = dzoomy
+       tab_cntrl(27) = 0.
+       tab_cntrl(28) = 0.
+       tab_cntrl(29) = 0.
+       IF( ysinus )  tab_cntrl(27) = 1.
+      ENDIF
+CAl1 iday_end -> day_end
+       tab_cntrl(30) = FLOAT(day_end)
+       tab_cntrl(31) = FLOAT(itau_dyn + itaufin)
+c
+      CALL put_var("controle","Param. de controle Dyn1D",tab_cntrl)
+c
+
+c  Ecriture/extension de la coordonnee temps
+
+      nb = nb + 1
+
+c  Ecriture des champs
+c
+      CALL put_field("plev","p interfaces sauf la nulle",plev)
+      CALL put_field("play","",play)
+      CALL put_field("phi","geopotentielle",phi)
+      CALL put_field("phis","geopotentiell de surface",phis)
+      CALL put_field("presnivs","",presnivs)
+      CALL put_field("ucov","",ucov)
+      CALL put_field("vcov","",vcov)
+      CALL put_field("temp","",temp)
+      CALL put_field("omega2","",omega2)
+
+      Do iq=1,nqtot
+        CALL put_field("q"//nmq(iq),"eau vap ou condens et traceurs",
+     .                                                      q(:,:,iq))
+      EndDo
+      CALL close_restartphy
+
+c
+      RETURN
+      END
+      SUBROUTINE gr_fi_dyn(nfield,ngrid,im,jm,pfi,pdyn)
+      IMPLICIT NONE
+!=======================================================================
+!   passage d'un champ de la grille scalaire a la grille physique
+!=======================================================================
+ 
+!-----------------------------------------------------------------------
+!   declarations:
+!   -------------
+ 
+      INTEGER im,jm,ngrid,nfield
+      REAL pdyn(im,jm,nfield)
+      REAL pfi(ngrid,nfield)
+ 
+      INTEGER i,j,ifield,ig
+ 
+!-----------------------------------------------------------------------
+!   calcul:
+!   -------
+ 
+      DO ifield=1,nfield
+!   traitement des poles
+         DO i=1,im
+            pdyn(i,1,ifield)=pfi(1,ifield)
+            pdyn(i,jm,ifield)=pfi(ngrid,ifield)
+         ENDDO
+ 
+!   traitement des point normaux
+         DO j=2,jm-1
+	    ig=2+(j-2)*(im-1)
+            CALL SCOPY(im-1,pfi(ig,ifield),1,pdyn(1,j,ifield),1)
+	    pdyn(im,j,ifield)=pdyn(1,j,ifield)
+         ENDDO
+      ENDDO
+ 
+      RETURN
+      END
+ 
+ 
+
+      SUBROUTINE abort_gcm(modname, message, ierr)
+ 
+      USE IOIPSL
+!
+! Stops the simulation cleanly, closing files and printing various
+! comments
+!
+!  Input: modname = name of calling program
+!         message = stuff to print
+!         ierr    = severity of situation ( = 0 normal )
+ 
+      character*20 modname
+      integer ierr
+      character*80 message
+ 
+      write(*,*) 'in abort_gcm'
+      call histclo
+!     call histclo(2)
+!     call histclo(3)
+!     call histclo(4)
+!     call histclo(5)
+      write(*,*) 'out of histclo'
+      write(*,*) 'Stopping in ', modname
+      write(*,*) 'Reason = ',message
+      call getin_dump
+!
+      if (ierr .eq. 0) then
+        write(*,*) 'Everything is cool'
+      else
+        write(*,*) 'Houston, we have a problem ', ierr
+      endif
+      STOP
+      END
+      REAL FUNCTION fq_sat(kelvin, millibar)
+!
+      IMPLICIT none
+!======================================================================
+! Autheur(s): Z.X. Li (LMD/CNRS)
+! Objet: calculer la vapeur d'eau saturante (formule Centre Euro.)
+!======================================================================
+! Arguments:
+! kelvin---input-R: temperature en Kelvin
+! millibar--input-R: pression en mb
+!
+! fq_sat----output-R: vapeur d'eau saturante en kg/kg
+!======================================================================
+!
+      REAL kelvin, millibar
+!
+      REAL r2es
+      PARAMETER (r2es=611.14 *18.0153/28.9644)
+!
+      REAL r3les, r3ies, r3es
+      PARAMETER (R3LES=17.269)
+      PARAMETER (R3IES=21.875)
+!
+      REAL r4les, r4ies, r4es
+      PARAMETER (R4LES=35.86)
+      PARAMETER (R4IES=7.66)
+!
+      REAL rtt
+      PARAMETER (rtt=273.16)
+!
+      REAL retv
+      PARAMETER (retv=28.9644/18.0153 - 1.0)
+!
+      REAL zqsat
+      REAL temp, pres
+!     ------------------------------------------------------------------
+!
+!
+      temp = kelvin
+      pres = millibar * 100.0
+!      write(*,*)'kelvin,millibar=',kelvin,millibar
+!      write(*,*)'temp,pres=',temp,pres
+!
+      IF (temp .LE. rtt) THEN
+         r3es = r3ies
+         r4es = r4ies
+      ELSE
+         r3es = r3les
+         r4es = r4les
+      ENDIF
+!
+      zqsat=r2es/pres * EXP ( r3es*(temp-rtt) / (temp-r4es) )
+      zqsat=MIN(0.5,ZQSAT)
+      zqsat=zqsat/(1.-retv  *zqsat)
+!
+      fq_sat = zqsat
+!
+      RETURN
+      END
+      subroutine scopy(n,sx,incx,sy,incy)
+!
+      IMPLICIT NONE
+!
+      integer n,incx,incy,ix,iy,i
+      real sx((n-1)*incx+1),sy((n-1)*incy+1)
+!
+      iy=1
+      ix=1
+      do 10 i=1,n
+	 sy(iy)=sx(ix)
+         ix=ix+incx
+         iy=iy+incy
+10    continue
+!
+      return
+      end
+      subroutine wrgradsfi(if,nl,field,name,titlevar)
+      implicit none
+ 
+!   Declarations
+ 
+#include "gradsdef.h"
+ 
+!   arguments
+      integer if,nl
+      real field(imx*jmx*lmx)
+      character*10 name,file
+      character*10 titlevar
+ 
+!   local
+ 
+      integer im,jm,lm,i,j,l,iv,iii,iji,iif,ijf
+ 
+      logical writectl
+ 
+ 
+      writectl=.false.
+ 
+!     print*,if,iid(if),jid(if),ifd(if),jfd(if)
+      iii=iid(if)
+      iji=jid(if)
+      iif=ifd(if)
+      ijf=jfd(if)
+      im=iif-iii+1
+      jm=ijf-iji+1
+      lm=lmd(if)
+
+
+!     print*,'im,jm,lm,name,firsttime(if)'
+!     print*,im,jm,lm,name,firsttime(if)
+ 
+      if(firsttime(if)) then
+         if(name.eq.var(1,if)) then
+            firsttime(if)=.false.
+            ivar(if)=1
+         print*,'fin de l initialiation de l ecriture du fichier'
+         print*,file
+           print*,'fichier no: ',if
+           print*,'unit ',unit(if)
+           print*,'nvar  ',nvar(if)
+           print*,'vars ',(var(iv,if),iv=1,nvar(if))
+         else
+            ivar(if)=ivar(if)+1
+            nvar(if)=ivar(if)
+            var(ivar(if),if)=name
+            tvar(ivar(if),if)=trim(titlevar)
+            nld(ivar(if),if)=nl
+            print*,'initialisation ecriture de ',var(ivar(if),if)
+            print*,'if ivar(if) nld ',if,ivar(if),nld(ivar(if),if)
+         endif
+         writectl=.true.
+         itime(if)=1
+      else
+         ivar(if)=mod(ivar(if),nvar(if))+1
+         if (ivar(if).eq.nvar(if)) then
+            writectl=.true.
+            itime(if)=itime(if)+1
+         endif
+ 
+         if(var(ivar(if),if).ne.name) then
+           print*,'Il faut stoker la meme succession de champs a chaque'
+           print*,'pas de temps'
+           print*,'fichier no: ',if
+           print*,'unit ',unit(if)
+           print*,'nvar  ',nvar(if)
+           print*,'vars ',(var(iv,if),iv=1,nvar(if))
+ 
+           stop
+         endif
+      endif
+ 
+!     print*,'ivar(if),nvar(if),var(ivar(if),if),writectl'
+!     print*,ivar(if),nvar(if),var(ivar(if),if),writectl
+      do l=1,nl
+         irec(if)=irec(if)+1
+!        print*,'Ecrit rec=',irec(if),iii,iif,iji,ijf,
+!    s (l-1)*imd(if)*jmd(if)+(iji-1)*imd(if)+iii
+!    s ,(l-1)*imd(if)*jmd(if)+(ijf-1)*imd(if)+iif
+         write(unit(if)+1,rec=irec(if))
+     s   ((field((l-1)*imd(if)*jmd(if)+(j-1)*imd(if)+i)
+     s   ,i=iii,iif),j=iji,ijf)
+      enddo
+      if (writectl) then
+ 
+      file=fichier(if)
+!   WARNING! on reecrase le fichier .ctl a chaque ecriture
+      open(unit(if),file=trim(file)//'.ctl',
+     &         form='formatted',status='unknown')
+      write(unit(if),'(a5,1x,a40)')
+     &       'DSET ','^'//trim(file)//'.dat'
+ 
+      write(unit(if),'(a12)') 'UNDEF 1.0E30'
+      write(unit(if),'(a5,1x,a40)') 'TITLE ',title(if)
+      call formcoord(unit(if),im,xd(iii,if),1.,.false.,'XDEF')
+      call formcoord(unit(if),jm,yd(iji,if),1.,.true.,'YDEF')
+      call formcoord(unit(if),lm,zd(1,if),1.,.false.,'ZDEF')
+      write(unit(if),'(a4,i10,a30)')
+     &       'TDEF ',itime(if),' LINEAR 07AUG1998 30MN '
+      write(unit(if),'(a4,2x,i5)') 'VARS',nvar(if)
+      do iv=1,nvar(if)
+!        print*,'if,var(iv,if),nld(iv,if),nld(iv,if)-1/nld(iv,if)'
+!        print*,if,var(iv,if),nld(iv,if),nld(iv,if)-1/nld(iv,if)
+         write(unit(if),1000) var(iv,if),nld(iv,if)-1/nld(iv,if)
+     &     ,99,tvar(iv,if)
+      enddo
+      write(unit(if),'(a7)') 'ENDVARS'
+!
+1000  format(a5,3x,i4,i3,1x,a39)
+ 
+      close(unit(if))
+ 
+      endif ! writectl
+ 
+      return
+ 
+      END
+ 
+      subroutine inigrads(if,im
+     s  ,x,fx,xmin,xmax,jm,y,ymin,ymax,fy,lm,z,fz
+     s  ,dt,file,titlel)
+ 
+ 
+      implicit none
+ 
+      integer if,im,jm,lm,i,j,l
+      real x(im),y(jm),z(lm),fx,fy,fz,dt
+      real xmin,xmax,ymin,ymax
+      integer nf
+ 
+      character file*10,titlel*40
+ 
+#include "gradsdef.h"
+ 
+      data unit/24,32,34,36,38,40,42,44,46,48/
+      data nf/0/
+ 
+      if (if.le.nf) stop'verifier les appels a inigrads'
+ 
+      print*,'Entree dans inigrads'
+ 
+      nf=if
+      title(if)=titlel
+      ivar(if)=0
+ 
+      fichier(if)=trim(file)
+ 
+      firsttime(if)=.true.
+      dtime(if)=dt
+ 
+      iid(if)=1
+      ifd(if)=im
+      imd(if)=im
+      do i=1,im
+         xd(i,if)=x(i)*fx
+         if(xd(i,if).lt.xmin) iid(if)=i+1
+         if(xd(i,if).le.xmax) ifd(if)=i
+      enddo
+      print*,'On stoke du point ',iid(if),'  a ',ifd(if),' en x'
+ 
+      jid(if)=1
+      jfd(if)=jm
+      jmd(if)=jm
+      do j=1,jm
+         yd(j,if)=y(j)*fy
+         if(yd(j,if).gt.ymax) jid(if)=j+1
+         if(yd(j,if).ge.ymin) jfd(if)=j
+      enddo
+      print*,'On stoke du point ',jid(if),'  a ',jfd(if),' en y'
+
+      print*,'Open de dat'
+      print*,'file=',file
+      print*,'fichier(if)=',fichier(if)
+ 
+      print*,4*(ifd(if)-iid(if))*(jfd(if)-jid(if))
+      print*,trim(file)//'.dat'
+ 
+      OPEN (unit(if)+1,FILE=trim(file)//'.dat',
+     s   FORM='UNFORMATTED',
+     s   ACCESS='DIRECT'
+     s  ,RECL=4*(ifd(if)-iid(if)+1)*(jfd(if)-jid(if)+1))
+ 
+      print*,'Open de dat ok'
+ 
+      lmd(if)=lm
+      do l=1,lm
+         zd(l,if)=z(l)*fz
+      enddo
+ 
+      irec(if)=0
+!CR 
+!      print*,if,imd(if),jmd(if),lmd(if)
+!      print*,'if,imd(if),jmd(if),lmd(if)'
+ 
+      return
+      end
+      SUBROUTINE gr_dyn_fi(nfield,im,jm,ngrid,pdyn,pfi)
+      IMPLICIT NONE
+!=======================================================================
+!   passage d'un champ de la grille scalaire a la grille physique
+!=======================================================================
+ 
+!-----------------------------------------------------------------------
+!   declarations:
+!   -------------
+ 
+      INTEGER im,jm,ngrid,nfield
+      REAL pdyn(im,jm,nfield)
+      REAL pfi(ngrid,nfield)
+ 
+      INTEGER j,ifield,ig
+ 
+!-----------------------------------------------------------------------
+!   calcul:
+!   -------
+ 
+      IF(ngrid.NE.2+(jm-2)*(im-1).AND.ngrid.NE.1)
+     s    STOP 'probleme de dim'
+!   traitement des poles
+      CALL SCOPY(nfield,pdyn,im*jm,pfi,ngrid)
+      CALL SCOPY(nfield,pdyn(1,jm,1),im*jm,pfi(ngrid,1),ngrid)
+ 
+!   traitement des point normaux
+      DO ifield=1,nfield
+         DO j=2,jm-1
+	    ig=2+(j-2)*(im-1)
+            CALL SCOPY(im-1,pdyn(1,j,ifield),1,pfi(ig,ifield),1)
+         ENDDO
+      ENDDO
+ 
+      RETURN
+      END
+ 
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      subroutine writelim
+     s   (phy_nat,phy_alb,phy_sst,phy_bil,phy_rug,phy_ice,
+     s    phy_fter,phy_foce,phy_flic,phy_fsic)
+
+      use dimphy
+      implicit none
+!
+#include "dimensions.h"
+#include "netcdf.inc"
+ 
+      integer klon1d
+      integer k
+      parameter (klon1d=1)
+      REAL phy_nat(klon1d,360)
+      REAL phy_alb(klon1d,360)
+      REAL phy_sst(klon1d,360)
+      REAL phy_bil(klon1d,360)
+      REAL phy_rug(klon1d,360)
+      REAL phy_ice(klon1d,360)
+      REAL phy_fter(klon1d,360)
+      REAL phy_foce(klon1d,360)
+      REAL phy_flic(klon1d,360)
+      REAL phy_fsic(klon1d,360)
+ 
+      INTEGER ierr
+      INTEGER dimfirst(3)
+      INTEGER dimlast(3)
+!
+      INTEGER nid, ndim, ntim
+      INTEGER dims(2), debut(2), epais(2)
+      INTEGER id_tim
+      INTEGER id_NAT, id_SST, id_BILS, id_RUG, id_ALB
+      INTEGER id_FTER,id_FOCE,id_FSIC,id_FLIC
+ 
+      PRINT*, 'Ecriture du fichier limit'
+!
+      ierr = NF_CREATE ("limit.nc", NF_CLOBBER, nid)
+!
+      ierr = NF_PUT_ATT_TEXT (nid, NF_GLOBAL, "title", 30,
+     .                       "Fichier conditions aux limites")
+      ierr = NF_DEF_DIM (nid, "points_physiques", klon1d, ndim)
+      ierr = NF_DEF_DIM (nid, "time", NF_UNLIMITED, ntim)
+!
+      dims(1) = ndim
+      dims(2) = ntim
+!
+!cc      ierr = NF_DEF_VAR (nid, "TEMPS", NF_DOUBLE, 1,ntim, id_tim)
+      ierr = NF_DEF_VAR (nid, "TEMPS", NF_FLOAT, 1,ntim, id_tim)
+      ierr = NF_PUT_ATT_TEXT (nid, id_tim, "title", 17,
+     .                        "Jour dans l annee")
+!cc      ierr = NF_DEF_VAR (nid, "NAT", NF_DOUBLE, 2,dims, id_NAT)
+      ierr = NF_DEF_VAR (nid, "NAT", NF_FLOAT, 2,dims, id_NAT)
+      ierr = NF_PUT_ATT_TEXT (nid, id_NAT, "title", 23,
+     .                        "Nature du sol (0,1,2,3)")
+!cc      ierr = NF_DEF_VAR (nid, "SST", NF_DOUBLE, 2,dims, id_SST)
+      ierr = NF_DEF_VAR (nid, "SST", NF_FLOAT, 2,dims, id_SST)
+      ierr = NF_PUT_ATT_TEXT (nid, id_SST, "title", 35,
+     .                        "Temperature superficielle de la mer")
+!cc      ierr = NF_DEF_VAR (nid, "BILS", NF_DOUBLE, 2,dims, id_BILS)
+      ierr = NF_DEF_VAR (nid, "BILS", NF_FLOAT, 2,dims, id_BILS)
+      ierr = NF_PUT_ATT_TEXT (nid, id_BILS, "title", 32,
+     .                        "Reference flux de chaleur au sol")
+!cc      ierr = NF_DEF_VAR (nid, "ALB", NF_DOUBLE, 2,dims, id_ALB)
+      ierr = NF_DEF_VAR (nid, "ALB", NF_FLOAT, 2,dims, id_ALB)
+      ierr = NF_PUT_ATT_TEXT (nid, id_ALB, "title", 19,
+     .                        "Albedo a la surface")
+!cc      ierr = NF_DEF_VAR (nid, "RUG", NF_DOUBLE, 2,dims, id_RUG)
+      ierr = NF_DEF_VAR (nid, "RUG", NF_FLOAT, 2,dims, id_RUG)
+      ierr = NF_PUT_ATT_TEXT (nid, id_RUG, "title", 8,
+     .                        "Rugosite")
+
+      ierr = NF_DEF_VAR (nid, "FTER", NF_FLOAT, 2,dims, id_FTER)
+      ierr = NF_PUT_ATT_TEXT (nid, id_FTER, "title", 8,"Frac. Terre")
+      ierr = NF_DEF_VAR (nid, "FOCE", NF_FLOAT, 2,dims, id_FOCE)
+      ierr = NF_PUT_ATT_TEXT (nid, id_FOCE, "title", 8,"Frac. Terre")
+      ierr = NF_DEF_VAR (nid, "FSIC", NF_FLOAT, 2,dims, id_FSIC)
+      ierr = NF_PUT_ATT_TEXT (nid, id_FSIC, "title", 8,"Frac. Terre")
+      ierr = NF_DEF_VAR (nid, "FLIC", NF_FLOAT, 2,dims, id_FLIC)
+      ierr = NF_PUT_ATT_TEXT (nid, id_FLIC, "title", 8,"Frac. Terre")
+!
+      ierr = NF_ENDDEF(nid)
+!
+      DO k = 1, 360
+!
+      debut(1) = 1
+      debut(2) = k
+      epais(1) = klon1d
+      epais(2) = 1
+!
+#ifdef NC_DOUBLE
+      ierr = NF_PUT_VAR1_DOUBLE (nid,id_tim,k,DBLE(k))
+      ierr = NF_PUT_VARA_DOUBLE (nid,id_NAT,debut,epais,phy_nat(1,k))
+      ierr = NF_PUT_VARA_DOUBLE (nid,id_SST,debut,epais,phy_sst(1,k))
+      ierr = NF_PUT_VARA_DOUBLE (nid,id_BILS,debut,epais,phy_bil(1,k))
+      ierr = NF_PUT_VARA_DOUBLE (nid,id_ALB,debut,epais,phy_alb(1,k))
+      ierr = NF_PUT_VARA_DOUBLE (nid,id_RUG,debut,epais,phy_rug(1,k))
+      ierr = NF_PUT_VARA_DOUBLE (nid,id_FTER,debut,epais,phy_fter(1,k))
+      ierr = NF_PUT_VARA_DOUBLE (nid,id_FOCE,debut,epais,phy_foce(1,k))
+      ierr = NF_PUT_VARA_DOUBLE (nid,id_FSIC,debut,epais,phy_fsic(1,k))
+      ierr = NF_PUT_VARA_DOUBLE (nid,id_FLIC,debut,epais,phy_flic(1,k))
+#else
+      ierr = NF_PUT_VAR1_REAL (nid,id_tim,k,FLOAT(k))
+      ierr = NF_PUT_VARA_REAL (nid,id_NAT,debut,epais,phy_nat(1,k))
+      ierr = NF_PUT_VARA_REAL (nid,id_SST,debut,epais,phy_sst(1,k))
+      ierr = NF_PUT_VARA_REAL (nid,id_BILS,debut,epais,phy_bil(1,k))
+      ierr = NF_PUT_VARA_REAL (nid,id_ALB,debut,epais,phy_alb(1,k))
+      ierr = NF_PUT_VARA_REAL (nid,id_RUG,debut,epais,phy_rug(1,k))
+      ierr = NF_PUT_VARA_REAL (nid,id_FTER,debut,epais,phy_fter(1,k))
+      ierr = NF_PUT_VARA_REAL (nid,id_FOCE,debut,epais,phy_foce(1,k))
+      ierr = NF_PUT_VARA_REAL (nid,id_FSIC,debut,epais,phy_fsic(1,k))
+      ierr = NF_PUT_VARA_REAL (nid,id_FLIC,debut,epais,phy_flic(1,k))
+
+#endif
+!
+      ENDDO
+!
+      ierr = NF_CLOSE(nid)
+!
+      return
+      end
+ 
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      SUBROUTINE disvert(pa,preff,ap,bp,dpres,presnivs,nivsigs,nivsig)
+ 
+!    Auteur :  P. Le Van .
+!
+      IMPLICIT NONE
+ 
+#include "dimensions.h"
+#include "paramet.h"
+!
+!=======================================================================
+!
+!
+!    s = sigma ** kappa   :  coordonnee  verticale
+!    dsig(l)            : epaisseur de la couche l ds la coord.  s
+!    sig(l)             : sigma a l'interface des couches l et l-1
+!    ds(l)              : distance entre les couches l et l-1 en coord.s
+!
+!=======================================================================
+!
+      REAL pa,preff
+      REAL ap(llmp1),bp(llmp1),dpres(llm),nivsigs(llm),nivsig(llmp1)
+      REAL presnivs(llm)
+!
+!   declarations:
+!   -------------
+!
+      REAL sig(llm+1),dsig(llm)
+!
+      INTEGER l
+      REAL snorm
+      REAL alpha,beta,gama,delta,deltaz,h
+      INTEGER np,ierr
+      REAL pi,x
+ 
+!-----------------------------------------------------------------------
+!
+      pi=2.*ASIN(1.)
+ 
+      OPEN(99,file='sigma.def',status='old',form='formatted',
+     s   iostat=ierr)
+ 
+!-----------------------------------------------------------------------
+!   cas 1 on lit les options dans sigma.def:
+!   ----------------------------------------
+ 
+      IF (ierr.eq.0) THEN
+ 
+      print*,'WARNING!!! on lit les options dans sigma.def'
+      READ(99,*) deltaz
+      READ(99,*) h
+      READ(99,*) beta
+      READ(99,*) gama
+      READ(99,*) delta
+      READ(99,*) np
+      CLOSE(99)
+      alpha=deltaz/(llm*h)
+!
+ 
+       DO 1  l = 1, llm
+       dsig(l) = (alpha+(1.-alpha)*exp(-beta*(llm-l)))*
+     $          ( (tanh(gama*l)/tanh(gama*llm))**np +
+     $            (1.-l/FLOAT(llm))*delta )
+   1   CONTINUE
+ 
+       sig(1)=1.
+       DO 101 l=1,llm-1
+          sig(l+1)=sig(l)*(1.-dsig(l))/(1.+dsig(l))
+101    CONTINUE
+       sig(llm+1)=0.
+ 
+       DO 2  l = 1, llm
+       dsig(l) = sig(l)-sig(l+1)
+   2   CONTINUE
+!
+ 
+      ELSE
+!-----------------------------------------------------------------------
+!   cas 2 ancienne discretisation (LMD5...):
+!   ----------------------------------------
+ 
+      PRINT*,'WARNING!!! Ancienne discretisation verticale'
+ 
+      h=7.
+      snorm  = 0.
+      DO l = 1, llm
+         x = 2.*asin(1.) * (FLOAT(l)-0.5) / float(llm+1)
+         dsig(l) = 1.0 + 7.0 * SIN(x)**2
+         snorm = snorm + dsig(l)
+      ENDDO
+      snorm = 1./snorm
+      DO l = 1, llm
+         dsig(l) = dsig(l)*snorm
+      ENDDO
+      sig(llm+1) = 0.
+      DO l = llm, 1, -1
+         sig(l) = sig(l+1) + dsig(l)
+      ENDDO
+ 
+      ENDIF
+ 
+ 
+      DO l=1,llm
+        nivsigs(l) = FLOAT(l)
+      ENDDO
+ 
+      DO l=1,llmp1
+        nivsig(l)= FLOAT(l)
+      ENDDO
+ 
+!
+!    ....  Calculs  de ap(l) et de bp(l)  ....
+!    .........................................
+!
+!
+!   .....  pa et preff sont lus  sur les fichiers start par lectba  .....
+!
+ 
+      bp(llmp1) =   0.
+ 
+      DO l = 1, llm
+!c
+!cc    ap(l) = 0.
+!cc    bp(l) = sig(l)
+ 
+      bp(l) = EXP( 1. -1./( sig(l)*sig(l)) )
+      ap(l) = pa * ( sig(l) - bp(l) )
+!
+      ENDDO
+      ap(llmp1) = pa * ( sig(llmp1) - bp(llmp1) )
+ 
+      PRINT *,' BP '
+      PRINT *,  bp
+      PRINT *,' AP '
+      PRINT *,  ap
+ 
+      DO l = 1, llm
+       dpres(l) = bp(l) - bp(l+1)
+       presnivs(l) = 0.5 *( ap(l)+bp(l)*preff + ap(l+1)+bp(l+1)*preff )
+      ENDDO
+ 
+      PRINT *,' PRESNIVS '
+      PRINT *,presnivs
+ 
+      RETURN
+      END
+
+!======================================================================
+       SUBROUTINE read_tsurf1d(knon,knindex,sst_out)
+
+! This subroutine specifies the surface temperature to be used in 1D simulations
+
+      USE dimphy, ONLY : klon
+
+      INTEGER, INTENT(IN)                  :: knon     ! nomber of points on compressed grid
+      INTEGER, DIMENSION(klon), INTENT(IN) :: knindex  ! grid point number for compressed grid
+      REAL, DIMENSION(klon), INTENT(OUT)   :: sst_out  ! tsurf used to force the single-column model
+
+       INTEGER :: i
+! COMMON defined in lmdz1d.F:
+       real ts_cur
+       common /sst_forcing/ts_cur
+
+       DO i = 1, knon
+        sst_out(i) = ts_cur
+       ENDDO
+
+      END SUBROUTINE read_tsurf1d
+
+!===============================================================
+      subroutine advect_vert(llm,w,dt,q,plev)
+!===============================================================
+!   Schema amont pour l'advection verticale en 1D
+!   w est la vitesse verticale dp/dt en Pa/s
+!   Traitement en volumes finis 
+!   d / dt ( zm q ) = delta_z ( omega q )
+!   d / dt ( zm ) = delta_z ( omega )
+!   avec zm = delta_z ( p )
+!   si * designe la valeur au pas de temps t+dt
+!   zm*(l) q*(l) - zm(l) q(l) = w(l+1) q(l+1) - w(l) q(l)
+!   zm*(l) -zm(l) = w(l+1) - w(l)
+!   avec w=omega * dt
+!---------------------------------------------------------------
+      implicit none
+! arguments
+      integer llm
+      real w(llm+1),q(llm),plev(llm+1),dt
+
+! local
+      integer l
+      real zwq(llm+1),zm(llm+1),zw(llm+1)
+      real qold
+
+!---------------------------------------------------------------
+
+      do l=1,llm
+         zw(l)=dt*w(l)
+         zm(l)=plev(l)-plev(l+1)
+         zwq(l)=q(l)*zw(l)
+      enddo
+      zwq(llm+1)=0.
+      zw(llm+1)=0.
+ 
+      do l=1,llm
+         qold=q(l)
+         q(l)=(q(l)*zm(l)+zwq(l+1)-zwq(l))/(zm(l)+zw(l+1)-zw(l))
+         print*,'ADV Q ',zm(l),zw(l),zwq(l),qold,q(l)
+      enddo
+
+ 
+      return
+      end
+
+!===============================================================
+
+
+       SUBROUTINE advect_va(llm,omega,d_t_va,d_q_va,d_u_va,d_v_va,
+     !                q,temp,u,v,
+     !            play,plev)
+!itlmd 
+!----------------------------------------------------------------------
+!   Calcul de l'advection verticale (ascendance et subsidence) de 
+!   température et d'humidité. Hypothèse : ce qui rentre de l'extérieur
+!   a les mêmes caractéristiques que l'air de la colonne 1D (WTG) ou 
+!   sans WTG rajouter une advection horizontale 
+!----------------------------------------------------------------------  
+        implicit none
+#include "YOMCST.h"
+!        argument
+        integer llm
+        real  omega(llm+1),d_t_va(llm), d_q_va(llm,3)
+        real  d_u_va(llm), d_v_va(llm)
+        real  q(llm,3),temp(llm)
+        real  u(llm),v(llm)
+        real  play(llm),plev(llm+1)
+! interne
+        integer l
+        real alpha,omgdown,omgup
+
+      do l= 1,llm
+       if(l.eq.1) then
+!si omgup pour la couche 1, alors tendance nulle
+        omgdown=max(omega(2),0.0)
+        alpha = rkappa*temp(l)*(1.+q(l,1)*rv/rd)/(play(l)*
+     &           (1.+q(l,1)))
+        d_t_va(l)= alpha*(omgdown)- 
+     &              omgdown*(temp(l)-temp(l+1))
+     &              /(play(l)-play(l+1))              
+
+        d_q_va(l,:)= -omgdown*(q(l,:)-q(l+1,:))
+     &              /(play(l)-play(l+1))              
+
+        d_u_va(l)= -omgdown*(u(l)-u(l+1))
+     &              /(play(l)-play(l+1))              
+        d_v_va(l)= -omgdown*(v(l)-v(l+1))
+     &              /(play(l)-play(l+1))              
+
+        
+       elseif(l.eq.llm) then
+        omgup=min(omega(l),0.0)
+        alpha = rkappa*temp(l)*(1.+q(l,1)*rv/rd)/(play(l)*
+     &           (1.+q(l,1)))
+        d_t_va(l)= alpha*(omgup)- 
+!bug?     &              omgup*(temp(l-1)-temp(l))/(play(l-1)-plev(l))
+     &              omgup*(temp(l-1)-temp(l))/(play(l-1)-play(l))
+        d_q_va(l,:)= -omgup*(q(l-1,:)-q(l,:))/(play(l-1)-play(l))
+        d_u_va(l)= -omgup*(u(l-1)-u(l))/(play(l-1)-play(l))
+        d_v_va(l)= -omgup*(v(l-1)-v(l))/(play(l-1)-play(l))
+       
+       else
+        omgup=min(omega(l),0.0)
+        omgdown=max(omega(l+1),0.0)
+        alpha = rkappa*temp(l)*(1.+q(l,1)*rv/rd)/(play(l)*
+     &           (1.+q(l,1)))
+        d_t_va(l)= alpha*(omgup+omgdown)- 
+     &              omgdown*(temp(l)-temp(l+1))
+     &              /(play(l)-play(l+1))-              
+!bug?     &              omgup*(temp(l-1)-temp(l))/(play(l-1)-plev(l))
+     &              omgup*(temp(l-1)-temp(l))/(play(l-1)-play(l))
+!      print*, '  ??? '
+
+        d_q_va(l,:)= -omgdown*(q(l,:)-q(l+1,:))
+     &              /(play(l)-play(l+1))-              
+     &              omgup*(q(l-1,:)-q(l,:))/(play(l-1)-play(l))
+        d_u_va(l)= -omgdown*(u(l)-u(l+1))
+     &              /(play(l)-play(l+1))-              
+     &              omgup*(u(l-1)-u(l))/(play(l-1)-play(l))
+        d_v_va(l)= -omgdown*(v(l)-v(l+1))
+     &              /(play(l)-play(l+1))-              
+     &              omgup*(v(l-1)-v(l))/(play(l-1)-play(l))
+       
+      endif
+         
+      enddo
+!fin itlmd
+        return
+        end
+!       SUBROUTINE lstendH(llm,omega,d_t_va,d_q_va,d_u_va,d_v_va,
+       SUBROUTINE lstendH(llm,nqtot,omega,d_t_va,d_q_va,
+     !                q,temp,u,v,play)
+!itlmd 
+!----------------------------------------------------------------------
+!   Calcul de l'advection verticale (ascendance et subsidence) de 
+!   température et d'humidité. Hypothèse : ce qui rentre de l'extérieur
+!   a les mêmes caractéristiques que l'air de la colonne 1D (WTG) ou 
+!   sans WTG rajouter une advection horizontale 
+!----------------------------------------------------------------------  
+        implicit none
+#include "YOMCST.h"
+!        argument
+        integer llm,nqtot
+        real  omega(llm+1),d_t_va(llm), d_q_va(llm,nqtot)
+!        real  d_u_va(llm), d_v_va(llm)
+        real  q(llm,nqtot),temp(llm)
+        real  u(llm),v(llm)
+        real  play(llm)
+        real cor(llm)
+!        real dph(llm),dudp(llm),dvdp(llm),dqdp(llm),dtdp(llm)
+        real dph(llm),dqdp(llm),dtdp(llm)
+! interne
+        integer l,k
+        real alpha,omdn,omup
+
+!        dudp=0.
+!        dvdp=0.
+        dqdp=0.
+        dtdp=0.
+!        d_u_va=0.
+!        d_v_va=0.
+
+      cor(:) = rkappa*temp*(1.+q(:,1)*rv/rd)/(play*(1.+q(:,1)))
+
+
+      do k=2,llm-1
+
+       dph  (k-1) = (play(k  )- play(k-1  ))
+!       dudp (k-1) = (u   (k  )- u   (k-1  ))/dph(k-1)
+!       dvdp (k-1) = (v   (k  )- v   (k-1  ))/dph(k-1)
+       dqdp (k-1) = (q   (k,1)- q   (k-1,1))/dph(k-1)
+       dtdp (k-1) = (temp(k  )- temp(k-1  ))/dph(k-1)
+
+      enddo
+
+!      dudp (  llm  ) = dudp ( llm-1 )
+!      dvdp (  llm  ) = dvdp ( llm-1 )
+      dqdp (  llm  ) = dqdp ( llm-1 )
+      dtdp (  llm  ) = dtdp ( llm-1 )
+
+      do k=2,llm-1
+      omdn=max(0.0,omega(k+1))
+      omup=min(0.0,omega( k ))
+
+!      d_u_va(k)  = -omdn*dudp(k)-omup*dudp(k-1)
+!      d_v_va(k)  = -omdn*dvdp(k)-omup*dvdp(k-1)
+      d_q_va(k,1)= -omdn*dqdp(k)-omup*dqdp(k-1)
+      d_t_va(k)  = -omdn*dtdp(k)-omup*dtdp(k-1)
+     :              +(omup+omdn)*cor(k)
+      enddo
+
+      omdn=max(0.0,omega( 2 ))
+      omup=min(0.0,omega(llm))
+!      d_u_va( 1 )   = -omdn*dudp( 1 )
+!      d_u_va(llm)   = -omup*dudp(llm)
+!      d_v_va( 1 )   = -omdn*dvdp( 1 )
+!      d_v_va(llm)   = -omup*dvdp(llm)
+      d_q_va( 1 ,1) = -omdn*dqdp( 1 )
+      d_q_va(llm,1) = -omup*dqdp(llm)
+      d_t_va( 1 )   = -omdn*dtdp( 1 )+omdn*cor( 1 )
+      d_t_va(llm)   = -omup*dtdp(llm)!+omup*cor(llm)
+
+!      if(abs(rlat(1))>10.) then
+!     Calculate the tendency due agestrophic motions
+!      du_age = fcoriolis*(v-vg)
+!      dv_age = fcoriolis*(ug-u)
+!      endif
+
+!       call writefield_phy('d_t_va',d_t_va,llm)
+
+          return
+         end
+
+!======================================================================
+      SUBROUTINE read_togacoare(fich_toga,nlev_toga,nt_toga
+     :             ,ts_toga,plev_toga,t_toga,q_toga,u_toga,v_toga,w_toga
+     :             ,ht_toga,vt_toga,hq_toga,vq_toga)
+      implicit none
+
+c-------------------------------------------------------------------------
+c Read TOGA-COARE forcing data 
+c-------------------------------------------------------------------------
+
+      integer nlev_toga,nt_toga
+      real ts_toga(nt_toga),plev_toga(nlev_toga,nt_toga)
+      real t_toga(nlev_toga,nt_toga),q_toga(nlev_toga,nt_toga)
+      real u_toga(nlev_toga,nt_toga),v_toga(nlev_toga,nt_toga)
+      real w_toga(nlev_toga,nt_toga)
+      real ht_toga(nlev_toga,nt_toga),vt_toga(nlev_toga,nt_toga)
+      real hq_toga(nlev_toga,nt_toga),vq_toga(nlev_toga,nt_toga)
+      character*80 fich_toga
+
+      integer no,l,k,ip
+      real riy,rim,rid,rih,bid
+
+      integer iy,im,id,ih
+      
+       real plev_min
+
+       plev_min = 55.  ! pas de tendance de vap. d eau au-dessus de 55 hPa
+
+      open(21,file=trim(fich_toga),form='formatted')
+      read(21,'(a)') 
+      do ip = 1, nt_toga
+      read(21,'(a)') 
+      read(21,'(a)') 
+      read(21,223) iy, im, id, ih, bid, ts_toga(ip), bid,bid,bid,bid
+      read(21,'(a)') 
+      read(21,'(a)') 
+
+       do k = 1, nlev_toga
+         read(21,230) plev_toga(k,ip), t_toga(k,ip), q_toga(k,ip) 
+     :       ,u_toga(k,ip), v_toga(k,ip), w_toga(k,ip)
+     :       ,ht_toga(k,ip), vt_toga(k,ip), hq_toga(k,ip), vq_toga(k,ip)
+
+! conversion in SI units:
+         t_toga(k,ip)=t_toga(k,ip)+273.15     ! K
+         q_toga(k,ip)=q_toga(k,ip)*0.001      ! kg/kg
+         w_toga(k,ip)=w_toga(k,ip)*100./3600. ! Pa/s
+! no water vapour tendency above 55 hPa
+         if (plev_toga(k,ip) .lt. plev_min) then
+          q_toga(k,ip) = 0.
+          hq_toga(k,ip) = 0.
+          vq_toga(k,ip) =0.
+         endif
+       enddo
+
+         ts_toga(ip)=ts_toga(ip)+273.15       ! K
+       enddo
+       close(21)
+
+  223 format(4i3,6f8.2)
+  226 format(f7.1,1x,10f8.2)
+  227 format(f7.1,1x,1p,4e11.3)
+  230 format(6f9.3,4e11.3)
+
+          return
+          end
+
+!=====================================================================
+      subroutine read_twpice(fich_twpice,nlevel,ntime
+     :     ,T_srf,plev,T,q,u,v,omega
+     :     ,T_adv_h,T_adv_v,q_adv_h,q_adv_v)
+
+!program reading forcings of the TWP-ICE experiment
+
+!      use netcdf
+
+      implicit none
+
+#include "netcdf.inc"
+
+      integer ntime,nlevel
+      integer l,k
+      character*80 :: fich_twpice
+      real*8 time(ntime)
+      real*8 lat, lon, alt, phis	
+      real*8 lev(nlevel)
+      real*8 plev(nlevel,ntime)
+
+      real*8 T(nlevel,ntime)
+      real*8 q(nlevel,ntime),u(nlevel,ntime)
+      real*8 v(nlevel,ntime)
+      real*8 omega(nlevel,ntime), div(nlevel,ntime)
+      real*8 T_adv_h(nlevel,ntime)
+      real*8 T_adv_v(nlevel,ntime), q_adv_h(nlevel,ntime)
+      real*8 q_adv_v(nlevel,ntime)	
+      real*8 s(nlevel,ntime), s_adv_h(nlevel,ntime)
+      real*8 s_adv_v(nlevel,ntime)
+      real*8 p_srf_aver(ntime), p_srf_center(ntime)
+      real*8 T_srf(ntime)
+
+      integer nid, ierr
+      integer nbvar3d
+      parameter(nbvar3d=20)
+      integer var3didin(nbvar3d)
+
+      ierr = NF_OPEN(fich_twpice,NF_NOWRITE,nid)
+      if (ierr.NE.NF_NOERR) then
+         write(*,*) 'ERROR: Pb opening forcings cdf file '
+         write(*,*) NF_STRERROR(ierr)
+         stop ""
+      endif
+
+      ierr=NF_INQ_VARID(nid,"lat",var3didin(1))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'lat'
+         endif
+      
+       ierr=NF_INQ_VARID(nid,"lon",var3didin(2))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'lon'
+         endif
+
+       ierr=NF_INQ_VARID(nid,"alt",var3didin(3))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'alt'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"phis",var3didin(4))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'phis'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"T",var3didin(5))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'T'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"q",var3didin(6))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'q'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"u",var3didin(7))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'u'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"v",var3didin(8))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'v'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"omega",var3didin(9))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'omega'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"div",var3didin(10))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'div'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"T_adv_h",var3didin(11))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'T_adv_h'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"T_adv_v",var3didin(12))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'T_adv_v'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"q_adv_h",var3didin(13))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'q_adv_h'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"q_adv_v",var3didin(14))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'q_adv_v'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"s",var3didin(15))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 's'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"s_adv_h",var3didin(16))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 's_adv_h'
+         endif
+    
+      ierr=NF_INQ_VARID(nid,"s_adv_v",var3didin(17))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 's_adv_v'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"p_srf_aver",var3didin(18))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'p_srf_aver'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"p_srf_center",var3didin(19))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'p_srf_center'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"T_srf",var3didin(20))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'T_srf'
+         endif
+
+!dimensions lecture
+      call catchaxis(nid,ntime,nlevel,time,lev,ierr)
+
+!pressure 
+       do l=1,ntime
+       do k=1,nlevel
+          plev(k,l)=lev(k)
+       enddo
+       enddo
+          
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(1),lat)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(1),lat)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture lat ok',lat
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(2),lon)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(2),lon)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture lon ok',lon
+ 
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(3),alt)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(3),alt)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!          write(*,*)'lecture alt ok',alt
+ 
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(4),phis)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(4),phis)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!          write(*,*)'lecture phis ok',phis
+          
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(5),T)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(5),T)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture T ok'
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(6),q)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(6),q)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture q ok'
+!q in kg/kg
+       do l=1,ntime
+       do k=1,nlevel
+          q(k,l)=q(k,l)/1000.
+       enddo
+       enddo
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(7),u)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(7),u)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture u ok'
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(8),v)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(8),v)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture v ok'
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(9),omega)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(9),omega)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture omega ok'
+!omega in mb/hour
+       do l=1,ntime
+       do k=1,nlevel
+          omega(k,l)=omega(k,l)*100./3600.
+       enddo
+       enddo
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(10),div)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(10),div)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture div ok'
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(11),T_adv_h)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(11),T_adv_h)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture T_adv_h ok'
+!T adv in K/s
+       do l=1,ntime
+       do k=1,nlevel
+          T_adv_h(k,l)=T_adv_h(k,l)/3600.
+       enddo
+       enddo
+
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(12),T_adv_v)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(12),T_adv_v)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture T_adv_v ok'
+!T adv in K/s
+       do l=1,ntime
+       do k=1,nlevel
+          T_adv_v(k,l)=T_adv_v(k,l)/3600.
+       enddo
+       enddo
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(13),q_adv_h)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(13),q_adv_h)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture q_adv_h ok'
+!q adv in kg/kg/s
+       do l=1,ntime
+       do k=1,nlevel
+          q_adv_h(k,l)=q_adv_h(k,l)/1000./3600.
+       enddo
+       enddo
+
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(14),q_adv_v)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(14),q_adv_v)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture q_adv_v ok'
+!q adv in kg/kg/s
+       do l=1,ntime
+       do k=1,nlevel
+          q_adv_v(k,l)=q_adv_v(k,l)/1000./3600.
+       enddo
+       enddo
+
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(15),s)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(15),s)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(16),s_adv_h)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(16),s_adv_h)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(17),s_adv_v)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(17),s_adv_v)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(18),p_srf_aver)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(18),p_srf_aver)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(19),p_srf_center)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(19),p_srf_center)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(20),T_srf)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(20),T_srf)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture T_srf ok', T_srf
+
+         return 
+         end subroutine read_twpice
+!=====================================================================
+         subroutine catchaxis(nid,ttm,llm,time,lev,ierr)
+
+!         use netcdf
+
+         implicit none
+#include "netcdf.inc"
+         integer nid,ttm,llm
+         real*8 time(ttm)
+         real*8 lev(llm)
+         integer ierr
+
+         integer i
+         integer timevar,levvar
+         integer timelen,levlen
+         integer timedimin,levdimin
+
+! Control & lecture on dimensions
+! ===============================
+         ierr=NF_INQ_DIMID(nid,"time",timedimin)
+         ierr=NF_INQ_VARID(nid,"time",timevar)
+         if (ierr.NE.NF_NOERR) then
+            write(*,*) 'ERROR: Field <time> is missing'
+            stop ""  
+         endif
+         ierr=NF_INQ_DIMLEN(nid,timedimin,timelen)
+
+         ierr=NF_INQ_DIMID(nid,"lev",levdimin)
+         ierr=NF_INQ_VARID(nid,"lev",levvar)
+         if (ierr.NE.NF_NOERR) then
+             write(*,*) 'ERROR: Field <lev> is lacking'
+             stop "" 
+         endif
+         ierr=NF_INQ_DIMLEN(nid,levdimin,levlen)
+
+         if((timelen/=ttm).or.(levlen/=llm)) then
+            write(*,*) 'ERROR: Not the good lenght for axis'
+            write(*,*) 'longitude: ',timelen,ttm+1
+            write(*,*) 'latitude: ',levlen,llm
+            stop ""  
+         endif
+
+!#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,timevar,time)
+         ierr = NF_GET_VAR_DOUBLE(nid,levvar,lev)
+!#else
+!        ierr = NF_GET_VAR_REAL(nid,timevar,time)
+!        ierr = NF_GET_VAR_REAL(nid,levvar,lev)
+!#endif
+
+       return
+       end
+
+!======================================================================
+      SUBROUTINE read_rico(fich_rico,nlev_rico,ps_rico,play
+     :             ,ts_rico,t_rico,q_rico,u_rico,v_rico,w_rico
+     :             ,dth_dyn,dqh_dyn)
+      implicit none
+
+c-------------------------------------------------------------------------
+c Read RICO forcing data 
+c-------------------------------------------------------------------------
+#include "dimensions.h"
+
+
+      integer nlev_rico
+      real ts_rico,ps_rico
+      real t_rico(llm),q_rico(llm)
+      real u_rico(llm),v_rico(llm)
+      real w_rico(llm)
+      real dth_dyn(llm)
+      real dqh_dyn(llm)
+      
+
+      real play(llm),zlay(llm)
+     
+
+      real prico(nlev_rico),zrico(nlev_rico)
+
+      character*80 fich_rico
+
+      integer k,l
+
+      
+      print*,fich_rico
+      open(21,file=trim(fich_rico),form='formatted')
+        do k=1,llm
+      zlay(k)=0.
+         enddo
+      
+        read(21,*) ps_rico,ts_rico
+        prico(1)=ps_rico
+        zrico(1)=0.0
+      do l=2,nlev_rico
+        read(21,*) k,prico(l),zrico(l)
+      enddo
+       close(21)
+
+      do k=1,llm
+        do l=1,80
+          if(prico(l)>play(k)) then
+              if(play(k)>prico(l+1)) then
+                zlay(k)=zrico(l)+(play(k)-prico(l)) * 
+     &              (zrico(l+1)-zrico(l))/(prico(l+1)-prico(l))
+              else
+                zlay(k)=zrico(l)+(play(k)-prico(80))* 
+     &              (zrico(81)-zrico(80))/(prico(81)-prico(80))
+              endif
+          endif
+        enddo
+        print*,k,zlay(k)
+        ! U
+        if(0 < zlay(k) .and. zlay(k) < 4000) then
+          u_rico(k)=-9.9 + (-1.9 + 9.9)*zlay(k)/4000
+        elseif(4000 < zlay(k) .and. zlay(k) < 12000) then
+       u_rico(k)=  -1.9 + (30.0 + 1.9) / 
+     :          (12000 - 4000) * (zlay(k) - 4000)
+        elseif(12000 < zlay(k) .and. zlay(k) < 13000) then
+          u_rico(k)=30.0
+        elseif(13000 < zlay(k) .and. zlay(k) < 20000) then
+          u_rico(k)=30.0 - (30.0) / 
+     : (20000 - 13000) * (zlay(k) - 13000)
+        else
+          u_rico(k)=0.0
+        endif
+
+!Q_v
+        if(0 < zlay(k) .and. zlay(k) < 740) then
+          q_rico(k)=16.0 + (13.8 - 16.0) / (740) * zlay(k)
+        elseif(740 < zlay(k) .and. zlay(k) < 3260) then
+          q_rico(k)=13.8 + (2.4 - 13.8) / 
+     :          (3260 - 740) * (zlay(k) - 740)
+        elseif(3260 < zlay(k) .and. zlay(k) < 4000) then
+          q_rico(k)=2.4 + (1.8 - 2.4) / 
+     :               (4000 - 3260) * (zlay(k) - 3260)
+        elseif(4000 < zlay(k) .and. zlay(k) < 9000) then
+          q_rico(k)=1.8 + (0 - 1.8) / 
+     :             (10000 - 4000) * (zlay(k) - 4000)
+        else
+          q_rico(k)=0.0
+        endif
+
+!T
+        if(0 < zlay(k) .and. zlay(k) < 740) then
+          t_rico(k)=299.2 + (292.0 - 299.2) / (740) * zlay(k)
+        elseif(740 < zlay(k) .and. zlay(k) < 4000) then
+          t_rico(k)=292.0 + (278.0 - 292.0) /
+     :       (4000 - 740) * (zlay(k) - 740)
+        elseif(4000 < zlay(k) .and. zlay(k) < 15000) then
+          t_rico(k)=278.0 + (203.0 - 278.0) /
+     :       (15000 - 4000) * (zlay(k) - 4000)
+        elseif(15000 < zlay(k) .and. zlay(k) < 17500) then
+          t_rico(k)=203.0 + (194.0 - 203.0) / 
+     :       (17500 - 15000)* (zlay(k) - 15000)
+        elseif(17500 < zlay(k) .and. zlay(k) < 20000) then
+          t_rico(k)=194.0 + (206.0 - 194.0) /
+     :       (20000 - 17500)* (zlay(k) - 17500)
+        elseif(20000 < zlay(k) .and. zlay(k) < 60000) then
+          t_rico(k)=206.0 + (270.0 - 206.0) / 
+     :        (60000 - 20000)* (zlay(k) - 20000)
+        endif
+
+! W
+        if(0 < zlay(k) .and. zlay(k) < 2260 ) then
+          w_rico(k)=- (0.005/2260) * zlay(k)
+        elseif(2260 < zlay(k) .and. zlay(k) < 4000 ) then
+          w_rico(k)=- 0.005
+        elseif(4000 < zlay(k) .and. zlay(k) < 5000 ) then
+       w_rico(k)=- 0.005 + (0.005/ (5000 - 4000)) * (zlay(k) - 4000)
+        else
+          w_rico(k)=0.0
+        endif
+
+! dThrz+dTsw0+dTlw0
+        if(0 < zlay(k) .and. zlay(k) < 4000) then
+          dth_dyn(k)=- 2.51 / 86400 + (-2.18 + 2.51 )/ 
+     :               (86400*4000) * zlay(k)
+        elseif(4000 < zlay(k) .and. zlay(k) < 5000) then
+          dth_dyn(k)=- 2.18 / 86400 + ( 2.18 ) /
+     :           (86400*(5000 - 4000)) * (zlay(k) - 4000)
+        else
+          dth_dyn(k)=0.0
+        endif
+! dQhrz
+        if(0 < zlay(k) .and. zlay(k) < 3000) then
+          dqh_dyn(k)=-1.0 / 86400 + (0.345 + 1.0)/
+     :                    (86400*3000) * (zlay(k))
+        elseif(3000 < zlay(k) .and. zlay(k) < 4000) then
+          dqh_dyn(k)=0.345 / 86400
+        elseif(4000 < zlay(k) .and. zlay(k) < 5000) then
+          dqh_dyn(k)=0.345 / 86400 + 
+     +   (-0.345)/(86400 * (5000 - 4000)) * (zlay(k)-4000)
+        else
+          dqh_dyn(k)=0.0
+        endif
+
+!?        if(play(k)>6e4) then
+!?          ratqs0(1,k)=ratqsbas*(plev(1)-play(k))/(plev(1)-6e4)
+!?        elseif((play(k)>3e4).and.(play(k)<6e4)) then
+!?          ratqs0(1,k)=ratqsbas+(ratqshaut-ratqsbas)&
+!?                          *(6e4-play(k))/(6e4-3e4)
+!?        else
+!?          ratqs0(1,k)=ratqshaut
+!?        endif
+
+      enddo
+
+      do k=1,llm
+      q_rico(k)=q_rico(k)/1e3 
+      dqh_dyn(k)=dqh_dyn(k)/1e3
+      v_rico(k)=-3.8
+      enddo
+
+          return
+          end
+
+!=====================================================================
+c-------------------------------------------------------------------------
+      SUBROUTINE read_armcu(fich_armcu,nlev_armcu,nt_armcu,
+     : sens,flat,adv_theta,rad_theta,adv_qt)
+      implicit none
+
+c-------------------------------------------------------------------------
+c Read ARM_CU case forcing data
+c-------------------------------------------------------------------------
+
+      integer nlev_armcu,nt_armcu
+      real sens(nt_armcu),flat(nt_armcu)
+      real adv_theta(nt_armcu),rad_theta(nt_armcu),adv_qt(nt_armcu)
+      character*80 fich_armcu
+
+      integer no,l,k,ip
+      real riy,rim,rid,rih,bid
+
+      integer iy,im,id,ih,in
+
+      open(21,file=trim(fich_armcu),form='formatted')
+      read(21,'(a)')
+      do ip = 1, nt_armcu
+      read(21,'(a)')
+      read(21,'(a)')
+      read(21,223) iy, im, id, ih, in, sens(ip),flat(ip),
+     :             adv_theta(ip),rad_theta(ip),adv_qt(ip)
+      print *,'forcages=',iy,im,id,ih,in, sens(ip),flat(ip),
+     :             adv_theta(ip),rad_theta(ip),adv_qt(ip)
+      enddo
+      close(21)
+
+  223 format(5i3,5f8.3)
+  226 format(f7.1,1x,10f8.2)
+  227 format(f7.1,1x,1p,4e11.3)
+  230 format(6f9.3,4e11.3)
+
+          return
+          end
+
+!=====================================================================
+       SUBROUTINE interp_toga_vertical(play,nlev_toga,plev_prof
+     :         ,t_prof,q_prof,u_prof,v_prof,w_prof
+     :         ,ht_prof,vt_prof,hq_prof,vq_prof
+     :         ,t_mod,q_mod,u_mod,v_mod,w_mod
+     :         ,ht_mod,vt_mod,hq_mod,vq_mod,mxcalc)
+ 
+       implicit none
+ 
+#include "dimensions.h"
+
+c-------------------------------------------------------------------------
+c Vertical interpolation of TOGA-COARE forcing data onto model levels
+c-------------------------------------------------------------------------
+ 
+       integer nlevmax
+       parameter (nlevmax=41)
+       integer nlev_toga,mxcalc
+!       real play(llm), plev_prof(nlevmax) 
+!       real t_prof(nlevmax),q_prof(nlevmax)
+!       real u_prof(nlevmax),v_prof(nlevmax), w_prof(nlevmax)
+!       real ht_prof(nlevmax),vt_prof(nlevmax)
+!       real hq_prof(nlevmax),vq_prof(nlevmax)
+ 
+       real play(llm), plev_prof(nlev_toga) 
+       real t_prof(nlev_toga),q_prof(nlev_toga)
+       real u_prof(nlev_toga),v_prof(nlev_toga), w_prof(nlev_toga)
+       real ht_prof(nlev_toga),vt_prof(nlev_toga)
+       real hq_prof(nlev_toga),vq_prof(nlev_toga)
+ 
+       real t_mod(llm),q_mod(llm)
+       real u_mod(llm),v_mod(llm), w_mod(llm)
+       real ht_mod(llm),vt_mod(llm)
+       real hq_mod(llm),vq_mod(llm)
+ 
+       integer l,k,k1,k2,kp
+       real aa,frac,frac1,frac2,fact
+ 
+       do l = 1, llm
+
+        if (play(l).ge.plev_prof(nlev_toga)) then
+ 
+        mxcalc=l
+         k1=0
+         k2=0
+
+         if (play(l).le.plev_prof(1)) then
+
+         do k = 1, nlev_toga-1
+          if (play(l).le.plev_prof(k) 
+     :       .and. play(l).gt.plev_prof(k+1)) then
+            k1=k
+            k2=k+1
+          endif
+         enddo
+
+         if (k1.eq.0 .or. k2.eq.0) then
+          write(*,*) 'PB! k1, k2 = ',k1,k2
+          write(*,*) 'l,play(l) = ',l,play(l)/100
+         do k = 1, nlev_toga-1
+          write(*,*) 'k,plev_prof(k) = ',k,plev_prof(k)/100
+         enddo
+         endif
+
+         frac = (plev_prof(k2)-play(l))/(plev_prof(k2)-plev_prof(k1))
+         t_mod(l)= t_prof(k2) - frac*(t_prof(k2)-t_prof(k1))
+         q_mod(l)= q_prof(k2) - frac*(q_prof(k2)-q_prof(k1))
+         u_mod(l)= u_prof(k2) - frac*(u_prof(k2)-u_prof(k1))
+         v_mod(l)= v_prof(k2) - frac*(v_prof(k2)-v_prof(k1))
+         w_mod(l)= w_prof(k2) - frac*(w_prof(k2)-w_prof(k1))
+         ht_mod(l)= ht_prof(k2) - frac*(ht_prof(k2)-ht_prof(k1))
+         vt_mod(l)= vt_prof(k2) - frac*(vt_prof(k2)-vt_prof(k1))
+         hq_mod(l)= hq_prof(k2) - frac*(hq_prof(k2)-hq_prof(k1))
+         vq_mod(l)= vq_prof(k2) - frac*(vq_prof(k2)-vq_prof(k1))
+     
+         else !play>plev_prof(1)
+
+         k1=1
+         k2=2
+         frac1 = (play(l)-plev_prof(k2))/(plev_prof(k1)-plev_prof(k2))
+         frac2 = (play(l)-plev_prof(k1))/(plev_prof(k1)-plev_prof(k2))
+         t_mod(l)= frac1*t_prof(k1) - frac2*t_prof(k2)
+         q_mod(l)= frac1*q_prof(k1) - frac2*q_prof(k2)
+         u_mod(l)= frac1*u_prof(k1) - frac2*u_prof(k2)
+         v_mod(l)= frac1*v_prof(k1) - frac2*v_prof(k2)
+         w_mod(l)= frac1*w_prof(k1) - frac2*w_prof(k2)
+         ht_mod(l)= frac1*ht_prof(k1) - frac2*ht_prof(k2)
+         vt_mod(l)= frac1*vt_prof(k1) - frac2*vt_prof(k2)
+         hq_mod(l)= frac1*hq_prof(k1) - frac2*hq_prof(k2)
+         vq_mod(l)= frac1*vq_prof(k1) - frac2*vq_prof(k2)
+
+         endif ! play.le.plev_prof(1)
+
+        else ! above max altitude of forcing file
+ 
+cjyg
+         fact=20.*(plev_prof(nlev_toga)-play(l))/plev_prof(nlev_toga) !jyg
+         fact = max(fact,0.)                                           !jyg
+         fact = exp(-fact)                                             !jyg
+         t_mod(l)= t_prof(nlev_toga)                                   !jyg
+         q_mod(l)= q_prof(nlev_toga)*fact                              !jyg
+         u_mod(l)= u_prof(nlev_toga)*fact                              !jyg
+         v_mod(l)= v_prof(nlev_toga)*fact                              !jyg
+         w_mod(l)= 0.0                                                 !jyg
+         ht_mod(l)= ht_prof(nlev_toga)                                 !jyg
+         vt_mod(l)= vt_prof(nlev_toga)                                 !jyg
+         hq_mod(l)= hq_prof(nlev_toga)*fact                            !jyg
+         vq_mod(l)= vq_prof(nlev_toga)*fact                            !jyg
+ 
+        endif ! play
+ 
+       enddo ! l
+
+!       do l = 1,llm
+!       print *,'t_mod(l),q_mod(l),ht_mod(l),hq_mod(l) ',
+!     $        l,t_mod(l),q_mod(l),ht_mod(l),hq_mod(l)
+!       enddo
+ 
+          return
+          end
+ 
+!======================================================================
+        SUBROUTINE interp_toga_time(day,day1,annee_ref
+     i             ,year_ini_toga,day_ini_toga,nt_toga,dt_toga,nlev_toga
+     i             ,ts_toga,plev_toga,t_toga,q_toga,u_toga,v_toga,w_toga
+     i             ,ht_toga,vt_toga,hq_toga,vq_toga
+     o             ,ts_prof,plev_prof,t_prof,q_prof,u_prof,v_prof,w_prof
+     o             ,ht_prof,vt_prof,hq_prof,vq_prof)
+        implicit none
+
+!---------------------------------------------------------------------------------------
+! Time interpolation of a 2D field to the timestep corresponding to day
+!
+! day: current julian day (e.g. 717538.2)
+! day1: first day of the simulation
+! nt_toga: total nb of data in the forcing (e.g. 480 for TOGA-COARE)
+! dt_toga: total time interval (in sec) between 2 forcing data (e.g. 6h for TOGA-COARE)
+!---------------------------------------------------------------------------------------
+
+#include "compar1d.h"
+
+! inputs:
+        integer annee_ref
+        integer nt_toga,nlev_toga
+        integer year_ini_toga
+        real day, day1,day_ini_toga,dt_toga
+        real ts_toga(nt_toga)
+        real plev_toga(nlev_toga,nt_toga),t_toga(nlev_toga,nt_toga)
+        real q_toga(nlev_toga,nt_toga),u_toga(nlev_toga,nt_toga)
+        real v_toga(nlev_toga,nt_toga),w_toga(nlev_toga,nt_toga)
+        real ht_toga(nlev_toga,nt_toga),vt_toga(nlev_toga,nt_toga)
+        real hq_toga(nlev_toga,nt_toga),vq_toga(nlev_toga,nt_toga)
+! outputs:
+        real ts_prof
+        real plev_prof(nlev_toga),t_prof(nlev_toga)
+        real q_prof(nlev_toga),u_prof(nlev_toga)
+        real v_prof(nlev_toga),w_prof(nlev_toga)
+        real ht_prof(nlev_toga),vt_prof(nlev_toga)
+        real hq_prof(nlev_toga),vq_prof(nlev_toga)
+! local:
+        integer it_toga1, it_toga2,k
+        real timeit,time_toga1,time_toga2,frac
+
+
+        if (forcing_type.eq.2) then
+! Check that initial day of the simulation consistent with TOGA-COARE period:
+       if (annee_ref.ne.1992 .and. annee_ref.ne.1993) then
+        print*,'Pour TOGA-COARE, annee_ref doit etre 1992 ou 1993'
+        print*,'Changer annee_ref dans run.def'
+        stop
+       endif
+       if (annee_ref.eq.1992 .and. day1.lt.day_ini_toga) then
+        print*,'TOGA-COARE a débuté le 1er Nov 1992 (jour julien=306)'
+        print*,'Changer dayref dans run.def'
+        stop
+       endif
+       if (annee_ref.eq.1993 .and. day1.gt.day_ini_toga+119) then
+        print*,'TOGA-COARE a fini le 28 Feb 1993 (jour julien=59)'
+        print*,'Changer dayref ou nday dans run.def'
+        stop
+       endif
+
+       else if (forcing_type.eq.4) then
+
+! Check that initial day of the simulation consistent with TWP-ICE period:
+       if (annee_ref.ne.2006) then
+        print*,'Pour TWP-ICE, annee_ref doit etre 2006'
+        print*,'Changer annee_ref dans run.def'
+        stop
+       endif
+       if (annee_ref.eq.2006 .and. day1.lt.day_ini_toga) then
+        print*,'TWP-ICE a debute le 17 Jan 2006 (jour julien=17)'
+        print*,'Changer dayref dans run.def'
+        stop
+       endif
+       if (annee_ref.eq.2006 .and. day1.gt.day_ini_toga+26) then
+        print*,'TWP-ICE a fini le 12 Feb 2006 (jour julien=43)'
+        print*,'Changer dayref ou nday dans run.def'
+        stop
+       endif
+
+       endif
+
+! Determine timestep relative to the 1st day of TOGA-COARE:
+!       timeit=(day-day1)*86400.
+!       if (annee_ref.eq.1992) then
+!        timeit=(day-day_ini_toga)*86400.
+!       else
+!        timeit=(day+61.-1.)*86400. ! 61 days between Nov01 and Dec31 1992
+!       endif
+      timeit=(day-day_ini_toga)*86400
+
+! Determine the closest observation times:
+       it_toga1=INT(timeit/dt_toga)+1
+       it_toga2=it_toga1 + 1
+       time_toga1=(it_toga1-1)*dt_toga
+       time_toga2=(it_toga2-1)*dt_toga
+
+       if (it_toga1 .ge. nt_toga) then
+        write(*,*) 'PB-stop: day, it_toga1, it_toga2, timeit: '
+     :        ,day,it_toga1,it_toga2,timeit/86400.
+        stop
+       endif
+
+! time interpolation:
+       frac=(time_toga2-timeit)/(time_toga2-time_toga1)
+       frac=max(frac,0.0)
+
+       ts_prof = ts_toga(it_toga2)
+     :          -frac*(ts_toga(it_toga2)-ts_toga(it_toga1))
+
+!        print*,
+!     :'day,annee_ref,day_ini_toga,timeit,it_toga1,it_toga2,SST:',
+!     :day,annee_ref,day_ini_toga,timeit/86400.,it_toga1,it_toga2,ts_prof
+
+       do k=1,nlev_toga
+        plev_prof(k) = 100.*(plev_toga(k,it_toga2)
+     :          -frac*(plev_toga(k,it_toga2)-plev_toga(k,it_toga1)))
+        t_prof(k) = t_toga(k,it_toga2)
+     :          -frac*(t_toga(k,it_toga2)-t_toga(k,it_toga1))
+        q_prof(k) = q_toga(k,it_toga2)
+     :          -frac*(q_toga(k,it_toga2)-q_toga(k,it_toga1))
+        u_prof(k) = u_toga(k,it_toga2)
+     :          -frac*(u_toga(k,it_toga2)-u_toga(k,it_toga1))
+        v_prof(k) = v_toga(k,it_toga2)
+     :          -frac*(v_toga(k,it_toga2)-v_toga(k,it_toga1))
+        w_prof(k) = w_toga(k,it_toga2)
+     :          -frac*(w_toga(k,it_toga2)-w_toga(k,it_toga1))
+        ht_prof(k) = ht_toga(k,it_toga2)
+     :          -frac*(ht_toga(k,it_toga2)-ht_toga(k,it_toga1))
+        vt_prof(k) = vt_toga(k,it_toga2)
+     :          -frac*(vt_toga(k,it_toga2)-vt_toga(k,it_toga1))
+        hq_prof(k) = hq_toga(k,it_toga2)
+     :          -frac*(hq_toga(k,it_toga2)-hq_toga(k,it_toga1))
+        vq_prof(k) = vq_toga(k,it_toga2)
+     :          -frac*(vq_toga(k,it_toga2)-vq_toga(k,it_toga1))
+        enddo
+
+        return
+        END
+
+!======================================================================
+        SUBROUTINE interp_armcu_time(day,day1,annee_ref
+     i             ,year_ini_armcu,day_ini_armcu,nt_armcu,dt_armcu
+     i             ,nlev_armcu,fs_armcu,fl_armcu,at_armcu,rt_armcu
+     i             ,aqt_armcu,fs_prof,fl_prof,at_prof,rt_prof,aqt_prof)
+        implicit none
+
+!---------------------------------------------------------------------------------------
+! Time interpolation of a 2D field to the timestep corresponding to day
+!
+! day: current julian day (e.g. 717538.2)
+! day1: first day of the simulation
+! nt_armcu: total nb of data in the forcing (e.g. 31 for armcu)
+! dt_armcu: total time interval (in sec) between 2 forcing data (e.g. 1/2h for armcu)
+! fs= sensible flux
+! fl= latent flux
+! at,rt,aqt= advective and radiative tendencies
+!---------------------------------------------------------------------------------------
+
+! inputs:
+        integer annee_ref
+        integer nt_armcu,nlev_armcu
+        integer year_ini_armcu
+        real day, day1,day_ini_armcu,dt_armcu
+        real fs_armcu(nt_armcu),fl_armcu(nt_armcu),at_armcu(nt_armcu)
+        real rt_armcu(nt_armcu),aqt_armcu(nt_armcu)
+! outputs:
+        real fs_prof,fl_prof,at_prof,rt_prof,aqt_prof
+! local:
+        integer it_armcu1, it_armcu2,k
+        real timeit,time_armcu1,time_armcu2,frac
+
+! Check that initial day of the simulation consistent with ARMCU period:
+       if (annee_ref.ne.1997 ) then
+        print*,'Pour ARMCU, annee_ref doit etre 1997 '
+        print*,'Changer annee_ref dans run.def'
+        stop
+       endif
+
+      timeit=(day-day_ini_armcu)*86400
+
+! Determine the closest observation times:
+       it_armcu1=INT(timeit/dt_armcu)+1
+       it_armcu2=it_armcu1 + 1
+       time_armcu1=(it_armcu1-1)*dt_armcu
+       time_armcu2=(it_armcu2-1)*dt_armcu
+       print *,'timeit day day_ini_armcu',timeit,day,day_ini_armcu
+       print *,'it_armcu1,it_armcu2,time_armcu1,time_armcu2',
+     .          it_armcu1,it_armcu2,time_armcu1,time_armcu2
+
+       if (it_armcu1 .ge. nt_armcu) then
+        write(*,*) 'PB-stop: day, it_armcu1, it_armcu2, timeit: '
+     :        ,day,it_armcu1,it_armcu2,timeit/86400.
+        stop
+       endif
+
+! time interpolation:
+       frac=(time_armcu2-timeit)/(time_armcu2-time_armcu1)
+       frac=max(frac,0.0)
+
+       fs_prof = fs_armcu(it_armcu2)
+     :          -frac*(fs_armcu(it_armcu2)-fs_armcu(it_armcu1))
+       fl_prof = fl_armcu(it_armcu2)
+     :          -frac*(fl_armcu(it_armcu2)-fl_armcu(it_armcu1))
+       at_prof = at_armcu(it_armcu2)
+     :          -frac*(at_armcu(it_armcu2)-at_armcu(it_armcu1))
+       rt_prof = rt_armcu(it_armcu2)
+     :          -frac*(rt_armcu(it_armcu2)-rt_armcu(it_armcu1))
+       aqt_prof = aqt_armcu(it_armcu2)
+     :          -frac*(aqt_armcu(it_armcu2)-aqt_armcu(it_armcu1))
+
+         print*,
+     :'day,annee_ref,day_ini_armcu,timeit,it_armcu1,it_armcu2,SST:',
+     :day,annee_ref,day_ini_armcu,timeit/86400.,it_armcu1,
+     :it_armcu2,fs_prof,fl_prof,at_prof,rt_prof,aqt_prof
+
+        return
+        END
+
+!=====================================================================
+      subroutine readprofiles(nlev_max,kmax,height,
+     .           thlprof,qtprof,uprof,
+     .           vprof,e12prof,ugprof,vgprof,
+     .           wfls,dqtdxls,dqtdyls,dqtdtls,
+     .           thlpcar)
+      implicit none
+
+        integer nlev_max,kmax,kmax2
+        logical :: llesread = .true.
+
+        real height(nlev_max),thlprof(nlev_max),qtprof(nlev_max),
+     .       uprof(nlev_max),vprof(nlev_max),e12prof(nlev_max),
+     .       ugprof(nlev_max),vgprof(nlev_max),wfls(nlev_max),
+     .       dqtdxls(nlev_max),dqtdyls(nlev_max),dqtdtls(nlev_max),
+     .           thlpcar(nlev_max)
+
+        integer, parameter :: ilesfile=1
+        integer :: ierr,irad,imax,jtot,k
+        logical :: lmoist,lcoriol,ltimedep
+        real :: xsize,ysize
+        real :: ustin,wsvsurf,timerad
+        character(80) :: chmess
+
+        if(.not.(llesread)) return
+
+       open (ilesfile,file='prof.inp.001',status='old',iostat=ierr)
+        if (ierr /= 0) stop 'ERROR:Prof.inp does not exist'
+        read (ilesfile,*) kmax
+        do k=1,kmax
+          read (ilesfile,*) height(k),thlprof(k),qtprof (k),
+     .                      uprof (k),vprof  (k),e12prof(k)
+        enddo
+        close(ilesfile)
+
+       open(ilesfile,file='lscale.inp.001',status='old',iostat=ierr)
+        if (ierr /= 0) stop 'ERROR:Lscale.inp does not exist'
+        read (ilesfile,*) kmax2
+        if (kmax .ne. kmax2) then
+          print *, 'fichiers prof.inp et lscale.inp incompatibles :'
+          print *, 'nbre de niveaux : ',kmax,' et ',kmax2
+          stop 'lecture profiles'
+        endif
+        do k=1,kmax
+          read (ilesfile,*) height(k),ugprof(k),vgprof(k),wfls(k),
+     .                      dqtdxls(k),dqtdyls(k),dqtdtls(k),thlpcar(k)
+        end do
+        close(ilesfile)
+
+        return
+        end
+
+
+!======================================================================
+      subroutine readprofile_armcu(nlev_max,kmax,height,pprof,uprof,
+     .       vprof,thetaprof,tprof,qvprof,rvprof,aprof,bprof)
+!======================================================================
+      implicit none
+
+        integer nlev_max,kmax,kmax2
+        logical :: llesread = .true.
+
+        real height(nlev_max),pprof(nlev_max),tprof(nlev_max),
+     .  thetaprof(nlev_max),rvprof(nlev_max),
+     .  qvprof(nlev_max),uprof(nlev_max),vprof(nlev_max),
+     .  aprof(nlev_max+1),bprof(nlev_max+1)
+
+        integer, parameter :: ilesfile=1
+        integer, parameter :: ifile=2
+        integer :: ierr,irad,imax,jtot,k
+        logical :: lmoist,lcoriol,ltimedep
+        real :: xsize,ysize
+        real :: ustin,wsvsurf,timerad
+        character(80) :: chmess
+
+        if(.not.(llesread)) return
+
+! Read profiles at full levels
+       IF(nlev_max.EQ.19) THEN
+       open (ilesfile,file='prof.inp.19',status='old',iostat=ierr)
+       print *,'On ouvre prof.inp.19'
+       ELSE
+       open (ilesfile,file='prof.inp.40',status='old',iostat=ierr)
+       print *,'On ouvre prof.inp.40'
+       ENDIF
+        if (ierr /= 0) stop 'ERROR:Prof.inp does not exist'
+        read (ilesfile,*) kmax
+        do k=1,kmax
+          read (ilesfile,*) height(k)    ,pprof(k),  uprof(k), vprof(k),
+     .                      thetaprof(k) ,tprof(k), qvprof(k),rvprof(k)
+        enddo
+        close(ilesfile)
+
+! Vertical coordinates half levels for eta-coordinates (plev = alpha + beta * psurf) 
+       IF(nlev_max.EQ.19) THEN
+       open (ifile,file='proh.inp.19',status='old',iostat=ierr)
+       print *,'On ouvre proh.inp.19'
+       if (ierr /= 0) stop 'ERROR:Proh.inp.19 does not exist'
+       ELSE
+       open (ifile,file='proh.inp.40',status='old',iostat=ierr)
+       print *,'On ouvre proh.inp.40'
+       if (ierr /= 0) stop 'ERROR:Proh.inp.40 does not exist'
+       ENDIF
+        read (ifile,*) kmax
+        do k=1,kmax
+          read (ifile,*) jtot,aprof(k),bprof(k)
+        enddo
+        close(ifile)
+
+        return
+        end
+!===============================================================
+      function ismin(n,sx,incx)
+
+      implicit none
+      integer n,i,incx,ismin,ix
+      real sx((n-1)*incx+1),sxmin
+
+      ix=1
+      ismin=1
+      sxmin=sx(1)
+      do i=1,n-1
+         ix=ix+incx
+         if(sx(ix).lt.sxmin) then
+             sxmin=sx(ix)
+             ismin=i+1
+         endif
+      enddo
+
+      return
+      end
+
+!===============================================================
+      function ismax(n,sx,incx)
+
+      implicit none
+      integer n,i,incx,ismax,ix
+      real sx((n-1)*incx+1),sxmax
+
+      ix=1
+      ismax=1
+      sxmax=sx(1)
+      do i=1,n-1
+         ix=ix+incx
+         if(sx(ix).gt.sxmax) then
+             sxmax=sx(ix)
+             ismax=i+1
+         endif
+      enddo
+
+      return
+      end
+
Index: LMDZ5/branches/testing/libf/phy1d/1DUTILS.h_with_writelim_old
===================================================================
--- LMDZ5/branches/testing/libf/phy1d/1DUTILS.h_with_writelim_old	(revision 1665)
+++ LMDZ5/branches/testing/libf/phy1d/1DUTILS.h_with_writelim_old	(revision 1665)
@@ -0,0 +1,2647 @@
+!
+! $Id: conf_unicol.F 1279 2010-08-04 17:20:56Z lahellec $
+!
+c
+c
+      SUBROUTINE conf_unicol( tapedef )
+c
+#ifdef CPP_IOIPSL
+      use IOIPSL
+#else
+! if not using IOIPSL, we still need to use (a local version of) getin
+      use ioipsl_getincom
+#endif
+      IMPLICIT NONE
+c-----------------------------------------------------------------------
+c     Auteurs :   A. Lahellec  .
+c
+c     Arguments :
+c
+c     tapedef   :
+
+       INTEGER tapedef
+c
+c   Declarations :
+c   --------------
+
+#include "compar1d.h"
+#include "flux_arp.h"
+#include "fcg_gcssold.h"
+#include "fcg_racmo.h"
+#include "iniprint.h"
+c
+c
+c   local:
+c   ------
+
+c      CHARACTER ch1*72,ch2*72,ch3*72,ch4*12
+      
+c
+c  -------------------------------------------------------------------
+c
+c      .........    Initilisation parametres du lmdz1D      ..........
+c
+c---------------------------------------------------------------------
+c   initialisations:
+c   ----------------
+
+!Config  Key  = lunout
+!Config  Desc = unite de fichier pour les impressions
+!Config  Def  = 6
+!Config  Help = unite de fichier pour les impressions 
+!Config         (defaut sortie standard = 6)
+      lunout=6
+      CALL getin('lunout', lunout)
+      IF (lunout /= 5 .and. lunout /= 6) THEN
+        OPEN(lunout,FILE='lmdz.out')
+      ENDIF
+
+!Config  Key  = prt_level
+!Config  Desc = niveau d'impressions de débogage
+!Config  Def  = 0
+!Config  Help = Niveau d'impression pour le débogage
+!Config         (0 = minimum d'impression)
+c      prt_level = 0
+c      CALL getin('prt_level',prt_level)
+
+c-----------------------------------------------------------------------
+c  Parametres de controle du run:
+c-----------------------------------------------------------------------
+
+!Config  Key  = restart
+!Config  Desc = on repart des startphy et start1dyn
+!Config  Def  = false
+!Config  Help = les fichiers restart doivent etre renomme en start
+       restart = .FALSE.
+       CALL getin('restart',restart)
+
+!Config  Key  = forcing_type
+!Config  Desc = defines the way the SCM is forced:
+!Config  Def  = 0
+!!Config  Help = 0 ==> forcing_les = .true.
+!             initial profiles from file prof.inp.001
+!             no forcing by LS convergence ; 
+!             surface temperature imposed ;
+!             radiative cooling may be imposed (iflag_radia=0 in physiq.def)
+!         = 1 ==> forcing_radconv = .true.
+!             idem forcing_type = 0, but the imposed radiative cooling 
+!             is set to 0 (hence, if iflag_radia=0 in physiq.def, 
+!             then there is no radiative cooling at all)
+!         = 2 ==> forcing_toga = .true.
+!             initial profiles from TOGA-COARE IFA files 
+!             LS convergence and SST imposed from TOGA-COARE IFA files 
+!         = 3 ==> forcing_GCM2SCM = .true.
+!             initial profiles from the GCM output
+!             LS convergence imposed from the GCM output
+!         = 4 ==> forcing_twpi = .true.
+!             initial profiles from TWPICE nc files 
+!             LS convergence and SST imposed from TWPICE nc files 
+!         = 5 ==> forcing_rico = .true.
+!             initial profiles from RICO idealized
+!             LS convergence imposed from  RICO (cst) 
+!         = 40 ==> forcing_GCSSold = .true.
+!             initial profile from GCSS file
+!             LS convergence imposed from GCSS file
+!
+       forcing_type = 0
+       CALL getin('forcing_type',forcing_type)
+         imp_fcg_gcssold   = .false.
+         ts_fcg_gcssold    = .false.  
+         Tp_fcg_gcssold    = .false.  
+         Tp_ini_gcssold    = .false.  
+         xTurb_fcg_gcssold = .false. 
+        IF (forcing_type .eq.40) THEN
+          CALL getin('imp_fcg',imp_fcg_gcssold)
+          CALL getin('ts_fcg',ts_fcg_gcssold)
+          CALL getin('tp_fcg',Tp_fcg_gcssold)
+          CALL getin('tp_ini',Tp_ini_gcssold)
+          CALL getin('turb_fcg',xTurb_fcg_gcssold)
+        ENDIF
+
+!Config  Key  = ok_flux_surf
+!Config  Desc = forcage ou non par les flux de surface
+!Config  Def  = false
+!Config  Help = forcage ou non par les flux de surface
+       ok_flux_surf = .FALSE.
+       CALL getin('ok_flux_surf',ok_flux_surf)
+
+!Config  Key  = time_ini
+!Config  Desc = meaningless in this  case
+!Config  Def  = 0.
+!Config  Help = 
+       tsurf = 0.
+       CALL getin('time_ini',time_ini)
+
+!Config  Key  = rlat et rlon
+!Config  Desc = latitude et longitude
+!Config  Def  = 0.0  0.0
+!Config  Help = fixe la position de la colonne
+       xlat = 0.
+       xlon = 0.
+       CALL getin('rlat',xlat)
+       CALL getin('rlon',xlon)
+
+!Config  Key  = airephy
+!Config  Desc = Grid cell area
+!Config  Def  = 1.e11
+!Config  Help = 
+       airefi = 1.e11
+       CALL getin('airephy',airefi)
+
+!Config  Key  = nat_surf
+!Config  Desc = surface type
+!Config  Def  = 0 (ocean)
+!Config  Help = 0=ocean,1=land,2=glacier,3=banquise
+       nat_surf = 0.
+       CALL getin('nat_surf',nat_surf)
+
+!Config  Key  = tsurf
+!Config  Desc = surface temperature
+!Config  Def  = 290.
+!Config  Help = not used if type_ts_forcing=1 in lmdz1d.F
+       tsurf = 290.
+       CALL getin('tsurf',tsurf)
+
+!Config  Key  = psurf
+!Config  Desc = surface pressure
+!Config  Def  = 102400.
+!Config  Help = 
+       psurf = 102400.
+       CALL getin('psurf',psurf)
+
+!Config  Key  = zsurf
+!Config  Desc = surface altitude
+!Config  Def  = 0.
+!Config  Help = 
+       zsurf = 0.
+       CALL getin('zsurf',zsurf)
+
+!Config  Key  = rugos
+!Config  Desc = coefficient de frottement
+!Config  Def  = 0.0001
+!Config  Help = calcul du Cdrag
+       rugos = 0.0001
+       CALL getin('rugos',rugos)
+
+!Config  Key  = wtsurf et wqsurf
+!Config  Desc = ???
+!Config  Def  = 0.0 0.0
+!Config  Help = 
+       wtsurf = 0.0
+       wqsurf = 0.0
+       CALL getin('wtsurf',wtsurf)
+       CALL getin('wqsurf',wqsurf)
+
+!Config  Key  = albedo
+!Config  Desc = albedo
+!Config  Def  = 0.09
+!Config  Help = 
+       albedo = 0.09
+       CALL getin('albedo',albedo)
+
+!Config  Key  = agesno
+!Config  Desc = age de la neige
+!Config  Def  = 30.0
+!Config  Help = 
+       xagesno = 30.0
+       CALL getin('agesno',xagesno)
+
+!Config  Key  = restart_runoff
+!Config  Desc = age de la neige
+!Config  Def  = 30.0
+!Config  Help = 
+       restart_runoff = 0.0
+       CALL getin('restart_runoff',restart_runoff)
+
+!Config  Key  = qsolinp
+!Config  Desc = initial bucket water content (kg/m2) when land (5std)
+!Config  Def  = 30.0
+!Config  Help = 
+       qsolinp = 1.
+       CALL getin('qsolinp',qsolinp)
+
+!Config  Key  = zpicinp
+!Config  Desc = denivellation orographie
+!Config  Def  = 300.
+!Config  Help =  input brise
+       zpicinp = 300.
+       CALL getin('zpicinp',zpicinp)
+
+
+      write(lunout,*)' +++++++++++++++++++++++++++++++++++++++'
+      write(lunout,*)' Configuration des parametres du gcm1D: '
+      write(lunout,*)' +++++++++++++++++++++++++++++++++++++++'
+      write(lunout,*)' restart = ', restart
+      write(lunout,*)' forcing_type = ', forcing_type
+      write(lunout,*)' time_ini = ', time_ini
+      write(lunout,*)' rlat = ', xlat
+      write(lunout,*)' rlon = ', xlon
+      write(lunout,*)' airephy = ', airefi
+      write(lunout,*)' nat_surf = ', nat_surf
+      write(lunout,*)' tsurf = ', tsurf
+      write(lunout,*)' psurf = ', psurf
+      write(lunout,*)' zsurf = ', zsurf
+      write(lunout,*)' rugos = ', rugos
+      write(lunout,*)' wtsurf = ', wtsurf
+      write(lunout,*)' wqsurf = ', wqsurf
+      write(lunout,*)' albedo = ', albedo
+      write(lunout,*)' xagesno = ', xagesno
+      write(lunout,*)' restart_runoff = ', restart_runoff
+      write(lunout,*)' qsolinp = ', qsolinp
+      write(lunout,*)' zpicinp = ', zpicinp
+      IF (forcing_type .eq.40) THEN
+        write(lunout,*) '--- Forcing type GCSS Old --- with:'
+        write(lunout,*)'imp_fcg',imp_fcg_gcssold
+        write(lunout,*)'ts_fcg',ts_fcg_gcssold
+        write(lunout,*)'tp_fcg',Tp_fcg_gcssold
+        write(lunout,*)'tp_ini',Tp_ini_gcssold
+        write(lunout,*)'xturb_fcg',xTurb_fcg_gcssold
+      ENDIF
+
+      write(lunout,*)' +++++++++++++++++++++++++++++++++++++++'
+      write(lunout,*)
+c
+      RETURN
+      END
+!
+! $Id: dyn1deta0.F 1279 2010/07/30 A Lahellec$
+!
+c
+      SUBROUTINE dyn1deta0(fichnom,plev,play,phi,phis,presnivs,
+     &                          ucov,vcov,temp,q,omega2)
+      USE dimphy
+      USE mod_grid_phy_lmdz
+      USE mod_phys_lmdz_para
+      USE iophy
+      USE phys_state_var_mod
+      USE iostart
+      USE write_field_phy
+      USE infotrac
+      use control_mod
+
+      IMPLICIT NONE
+c=======================================================
+c Ecriture du fichier de redemarrage sous format NetCDF
+c=======================================================
+c   Declarations:
+c   -------------
+#include "dimensions.h"
+#include "comconst.h"
+#include "temps.h"
+!!#include "control.h"
+#include "logic.h"
+#include "netcdf.inc"
+
+c   Arguments:
+c   ----------
+      CHARACTER*(*) fichnom
+cAl1 plev tronque pour .nc mais plev(klev+1):=0
+      real :: plev(klon,klev),play (klon,klev),phi(klon,klev)
+      real :: presnivs(klon,klev)
+      real :: ucov(klon,klev),vcov(klon,klev),temp(klon,klev)
+      real :: q(klon,klev,nqtot),omega2(klon,klev)
+c      real :: ug(klev),vg(klev),fcoriolis
+      real :: phis(klon) 
+
+c   Variables locales pour NetCDF:
+c   ------------------------------
+      INTEGER nid, nvarid
+      INTEGER idim_s
+      INTEGER ierr, ierr_file 
+      INTEGER iq
+      INTEGER length
+      PARAMETER (length = 100)
+      REAL tab_cntrl(length) ! tableau des parametres du run
+      character*4 nmq(nqtot)
+      character*12 modname
+      character*80 abort_message
+      LOGICAL found
+c
+      INTEGER nb
+
+      modname = 'dyn1deta0 : '
+      nmq(1)="vap"
+      nmq(2)="cond"
+      do iq=3,nqtot
+        write(nmq(iq),'("tra",i1)') iq-2
+      enddo
+      print*,'in dyn1deta0 ',fichnom,klon,klev,nqtot
+      CALL open_startphy(fichnom)
+      print*,'after open startphy ',fichnom,nmq
+
+c
+c Lecture des parametres de controle:
+c
+      CALL get_var("controle",tab_cntrl)
+       
+
+      im         = tab_cntrl(1)
+      jm         = tab_cntrl(2)
+      lllm       = tab_cntrl(3)
+      day_ref    = tab_cntrl(4)
+      annee_ref  = tab_cntrl(5)
+c      rad        = tab_cntrl(6)
+c      omeg       = tab_cntrl(7)
+c      g          = tab_cntrl(8)
+c      cpp        = tab_cntrl(9)
+c      kappa      = tab_cntrl(10)
+c      daysec     = tab_cntrl(11)
+c      dtvr       = tab_cntrl(12)
+c      etot0      = tab_cntrl(13)
+c      ptot0      = tab_cntrl(14)
+c      ztot0      = tab_cntrl(15)
+c      stot0      = tab_cntrl(16)
+c      ang0       = tab_cntrl(17)
+c      pa         = tab_cntrl(18)
+c      preff      = tab_cntrl(19)
+c
+c      clon       = tab_cntrl(20)
+c      clat       = tab_cntrl(21)
+c      grossismx  = tab_cntrl(22)
+c      grossismy  = tab_cntrl(23)
+c
+      IF ( tab_cntrl(24).EQ.1. )  THEN
+        fxyhypb  = . TRUE .
+c        dzoomx   = tab_cntrl(25)
+c        dzoomy   = tab_cntrl(26)
+c        taux     = tab_cntrl(28)
+c        tauy     = tab_cntrl(29)
+      ELSE
+        fxyhypb = . FALSE .
+        ysinus  = . FALSE .
+        IF( tab_cntrl(27).EQ.1. ) ysinus = . TRUE. 
+      ENDIF
+
+      day_ini = tab_cntrl(30)
+      itau_dyn = tab_cntrl(31)
+c   .................................................................
+c
+c
+c      PRINT*,'rad,omeg,g,cpp,kappa',rad,omeg,g,cpp,kappa
+cAl1
+       Print*,'day_ref,annee_ref,day_ini,itau_dyn',
+     &              day_ref,annee_ref,day_ini,itau_dyn
+
+c  Lecture des champs
+c
+      plev(1,klev+1)=0.
+      CALL get_field("plev",plev,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <Plev> est absent'
+      CALL get_field("play",play,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <Play> est absent'
+      CALL get_field("phi",phi,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <Phi> est absent'
+      CALL get_field("phis",phis,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <Phis> est absent'
+      CALL get_field("presnivs",presnivs,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <Presnivs> est absent'
+      CALL get_field("ucov",ucov,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <ucov> est absent'
+      CALL get_field("vcov",vcov,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <vcov> est absent'
+      CALL get_field("temp",temp,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <temp> est absent'
+      CALL get_field("omega2",omega2,found)
+      IF (.NOT. found) PRINT*, modname//'Le champ <omega2> est absent'
+
+      Do iq=1,nqtot
+        CALL get_field("q"//nmq(iq),q(:,:,iq),found)
+        IF (.NOT. found)
+     &  PRINT*, modname//'Le champ <q'//nmq//'> est absent'
+      EndDo
+
+      CALL close_startphy
+      print*,' close startphy'
+     .      ,fichnom,play(1,1),play(1,klev),temp(1,klev)
+c
+      RETURN
+      END
+!
+! $Id: dyn1dredem.F 1279 2010/07/29 A Lahellec$
+!
+c
+      SUBROUTINE dyn1dredem(fichnom,plev,play,phi,phis,presnivs,
+     &                          ucov,vcov,temp,q,omega2)
+      USE dimphy
+      USE mod_grid_phy_lmdz
+      USE mod_phys_lmdz_para
+      USE phys_state_var_mod
+      USE iostart
+      USE infotrac
+      use control_mod
+
+      IMPLICIT NONE
+c=======================================================
+c Ecriture du fichier de redemarrage sous format NetCDF
+c=======================================================
+c   Declarations:
+c   -------------
+#include "dimensions.h"
+#include "comconst.h"
+#include "temps.h"
+!!#include "control.h"
+#include "logic.h"
+#include "netcdf.inc"
+
+c   Arguments:
+c   ----------
+      CHARACTER*(*) fichnom
+      REAL time
+cAl1 plev tronque pour .nc mais plev(klev+1):=0
+      real :: plev(klon,klev),play (klon,klev),phi(klon,klev)
+      real :: presnivs(klon,klev)
+      real :: ucov(klon,klev),vcov(klon,klev),temp(klon,klev)
+      real :: q(klon,klev,nqtot)
+      real :: omega2(klon,klev),rho(klon,klev+1)
+c      real :: ug(klev),vg(klev),fcoriolis
+      real :: phis(klon) 
+
+c   Variables locales pour NetCDF:
+c   ------------------------------
+      INTEGER nid, nvarid
+      INTEGER idim_s
+      INTEGER ierr, ierr_file 
+      INTEGER iq,l
+      INTEGER length
+      PARAMETER (length = 100)
+      REAL tab_cntrl(length) ! tableau des parametres du run
+      character*4 nmq(nqtot)
+      character*20 modname
+      character*80 abort_message
+c
+      INTEGER nb
+      SAVE nb
+      DATA nb / 0 /
+
+      REAL zan0,zjulian,hours
+      INTEGER yyears0,jjour0, mmois0
+      character*30 unites
+
+cDbg
+      CALL open_restartphy(fichnom)
+      print*,'redm1 ',fichnom,klon,klev,nqtot
+      nmq(1)="vap"
+      nmq(2)="cond"
+      nmq(3)="tra1"
+      nmq(4)="tra2"
+
+      modname = 'dyn1dredem'
+      ierr = NF_OPEN(fichnom, NF_WRITE, nid)
+      IF (ierr .NE. NF_NOERR) THEN
+         PRINT*, "Pb. d ouverture "//fichnom
+         CALL abort
+      ENDIF
+
+      DO l=1,length
+       tab_cntrl(l) = 0.
+      ENDDO
+       tab_cntrl(1)  = FLOAT(iim)
+       tab_cntrl(2)  = FLOAT(jjm)
+       tab_cntrl(3)  = FLOAT(llm)
+       tab_cntrl(4)  = FLOAT(day_ref)
+       tab_cntrl(5)  = FLOAT(annee_ref)
+       tab_cntrl(6)  = rad
+       tab_cntrl(7)  = omeg
+       tab_cntrl(8)  = g
+       tab_cntrl(9)  = cpp
+       tab_cntrl(10) = kappa
+       tab_cntrl(11) = daysec
+       tab_cntrl(12) = dtvr
+c       tab_cntrl(13) = etot0
+c       tab_cntrl(14) = ptot0
+c       tab_cntrl(15) = ztot0
+c       tab_cntrl(16) = stot0
+c       tab_cntrl(17) = ang0
+c       tab_cntrl(18) = pa
+c       tab_cntrl(19) = preff
+c
+c    .....    parametres  pour le zoom      ......   
+
+c       tab_cntrl(20)  = clon
+c       tab_cntrl(21)  = clat
+c       tab_cntrl(22)  = grossismx
+c       tab_cntrl(23)  = grossismy
+c
+      IF ( fxyhypb )   THEN
+       tab_cntrl(24) = 1.
+c       tab_cntrl(25) = dzoomx
+c       tab_cntrl(26) = dzoomy
+       tab_cntrl(27) = 0.
+c       tab_cntrl(28) = taux
+c       tab_cntrl(29) = tauy
+      ELSE
+       tab_cntrl(24) = 0.
+c       tab_cntrl(25) = dzoomx
+c       tab_cntrl(26) = dzoomy
+       tab_cntrl(27) = 0.
+       tab_cntrl(28) = 0.
+       tab_cntrl(29) = 0.
+       IF( ysinus )  tab_cntrl(27) = 1.
+      ENDIF
+CAl1 iday_end -> day_end
+       tab_cntrl(30) = FLOAT(day_end)
+       tab_cntrl(31) = FLOAT(itau_dyn + itaufin)
+c
+      CALL put_var("controle","Param. de controle Dyn1D",tab_cntrl)
+c
+
+c  Ecriture/extension de la coordonnee temps
+
+      nb = nb + 1
+
+c  Ecriture des champs
+c
+      CALL put_field("plev","p interfaces sauf la nulle",plev)
+      CALL put_field("play","",play)
+      CALL put_field("phi","geopotentielle",phi)
+      CALL put_field("phis","geopotentiell de surface",phis)
+      CALL put_field("presnivs","",presnivs)
+      CALL put_field("ucov","",ucov)
+      CALL put_field("vcov","",vcov)
+      CALL put_field("temp","",temp)
+      CALL put_field("omega2","",omega2)
+
+      Do iq=1,nqtot
+        CALL put_field("q"//nmq(iq),"eau vap ou condens et traceurs",
+     .                                                      q(:,:,iq))
+      EndDo
+      CALL close_restartphy
+
+c
+      RETURN
+      END
+      SUBROUTINE gr_fi_dyn(nfield,ngrid,im,jm,pfi,pdyn)
+      IMPLICIT NONE
+!=======================================================================
+!   passage d'un champ de la grille scalaire a la grille physique
+!=======================================================================
+ 
+!-----------------------------------------------------------------------
+!   declarations:
+!   -------------
+ 
+      INTEGER im,jm,ngrid,nfield
+      REAL pdyn(im,jm,nfield)
+      REAL pfi(ngrid,nfield)
+ 
+      INTEGER i,j,ifield,ig
+ 
+!-----------------------------------------------------------------------
+!   calcul:
+!   -------
+ 
+      DO ifield=1,nfield
+!   traitement des poles
+         DO i=1,im
+            pdyn(i,1,ifield)=pfi(1,ifield)
+            pdyn(i,jm,ifield)=pfi(ngrid,ifield)
+         ENDDO
+ 
+!   traitement des point normaux
+         DO j=2,jm-1
+	    ig=2+(j-2)*(im-1)
+            CALL SCOPY(im-1,pfi(ig,ifield),1,pdyn(1,j,ifield),1)
+	    pdyn(im,j,ifield)=pdyn(1,j,ifield)
+         ENDDO
+      ENDDO
+ 
+      RETURN
+      END
+ 
+ 
+
+      SUBROUTINE abort_gcm(modname, message, ierr)
+ 
+      USE IOIPSL
+!
+! Stops the simulation cleanly, closing files and printing various
+! comments
+!
+!  Input: modname = name of calling program
+!         message = stuff to print
+!         ierr    = severity of situation ( = 0 normal )
+ 
+      character*20 modname
+      integer ierr
+      character*80 message
+ 
+      write(*,*) 'in abort_gcm'
+      call histclo
+!     call histclo(2)
+!     call histclo(3)
+!     call histclo(4)
+!     call histclo(5)
+      write(*,*) 'out of histclo'
+      write(*,*) 'Stopping in ', modname
+      write(*,*) 'Reason = ',message
+      call getin_dump
+!
+      if (ierr .eq. 0) then
+        write(*,*) 'Everything is cool'
+      else
+        write(*,*) 'Houston, we have a problem ', ierr
+      endif
+      STOP
+      END
+      REAL FUNCTION q_sat(kelvin, millibar)
+!
+      IMPLICIT none
+!======================================================================
+! Autheur(s): Z.X. Li (LMD/CNRS)
+! Objet: calculer la vapeur d'eau saturante (formule Centre Euro.)
+!======================================================================
+! Arguments:
+! kelvin---input-R: temperature en Kelvin
+! millibar--input-R: pression en mb
+!
+! q_sat----output-R: vapeur d'eau saturante en kg/kg
+!======================================================================
+!
+      REAL kelvin, millibar
+!
+      REAL r2es
+      PARAMETER (r2es=611.14 *18.0153/28.9644)
+!
+      REAL r3les, r3ies, r3es
+      PARAMETER (R3LES=17.269)
+      PARAMETER (R3IES=21.875)
+!
+      REAL r4les, r4ies, r4es
+      PARAMETER (R4LES=35.86)
+      PARAMETER (R4IES=7.66)
+!
+      REAL rtt
+      PARAMETER (rtt=273.16)
+!
+      REAL retv
+      PARAMETER (retv=28.9644/18.0153 - 1.0)
+!
+      REAL zqsat
+      REAL temp, pres
+!     ------------------------------------------------------------------
+!
+!
+      temp = kelvin
+      pres = millibar * 100.0
+!      write(*,*)'kelvin,millibar=',kelvin,millibar
+!      write(*,*)'temp,pres=',temp,pres
+!
+      IF (temp .LE. rtt) THEN
+         r3es = r3ies
+         r4es = r4ies
+      ELSE
+         r3es = r3les
+         r4es = r4les
+      ENDIF
+!
+      zqsat=r2es/pres * EXP ( r3es*(temp-rtt) / (temp-r4es) )
+      zqsat=MIN(0.5,ZQSAT)
+      zqsat=zqsat/(1.-retv  *zqsat)
+!
+      q_sat = zqsat
+!
+      RETURN
+      END
+      subroutine scopy(n,sx,incx,sy,incy)
+!
+      IMPLICIT NONE
+!
+      integer n,incx,incy,ix,iy,i
+      real sx((n-1)*incx+1),sy((n-1)*incy+1)
+!
+      iy=1
+      ix=1
+      do 10 i=1,n
+	 sy(iy)=sx(ix)
+         ix=ix+incx
+         iy=iy+incy
+10    continue
+!
+      return
+      end
+      subroutine wrgradsfi(if,nl,field,name,titlevar)
+      implicit none
+ 
+!   Declarations
+ 
+#include "gradsdef.h"
+ 
+!   arguments
+      integer if,nl
+      real field(imx*jmx*lmx)
+      character*10 name,file
+      character*10 titlevar
+ 
+!   local
+ 
+      integer im,jm,lm,i,j,l,iv,iii,iji,iif,ijf
+ 
+      logical writectl
+ 
+ 
+      writectl=.false.
+ 
+!     print*,if,iid(if),jid(if),ifd(if),jfd(if)
+      iii=iid(if)
+      iji=jid(if)
+      iif=ifd(if)
+      ijf=jfd(if)
+      im=iif-iii+1
+      jm=ijf-iji+1
+      lm=lmd(if)
+
+
+!     print*,'im,jm,lm,name,firsttime(if)'
+!     print*,im,jm,lm,name,firsttime(if)
+ 
+      if(firsttime(if)) then
+         if(name.eq.var(1,if)) then
+            firsttime(if)=.false.
+            ivar(if)=1
+         print*,'fin de l initialiation de l ecriture du fichier'
+         print*,file
+           print*,'fichier no: ',if
+           print*,'unit ',unit(if)
+           print*,'nvar  ',nvar(if)
+           print*,'vars ',(var(iv,if),iv=1,nvar(if))
+         else
+            ivar(if)=ivar(if)+1
+            nvar(if)=ivar(if)
+            var(ivar(if),if)=name
+            tvar(ivar(if),if)=trim(titlevar)
+            nld(ivar(if),if)=nl
+            print*,'initialisation ecriture de ',var(ivar(if),if)
+            print*,'if ivar(if) nld ',if,ivar(if),nld(ivar(if),if)
+         endif
+         writectl=.true.
+         itime(if)=1
+      else
+         ivar(if)=mod(ivar(if),nvar(if))+1
+         if (ivar(if).eq.nvar(if)) then
+            writectl=.true.
+            itime(if)=itime(if)+1
+         endif
+ 
+         if(var(ivar(if),if).ne.name) then
+           print*,'Il faut stoker la meme succession de champs a chaque'
+           print*,'pas de temps'
+           print*,'fichier no: ',if
+           print*,'unit ',unit(if)
+           print*,'nvar  ',nvar(if)
+           print*,'vars ',(var(iv,if),iv=1,nvar(if))
+ 
+           stop
+         endif
+      endif
+ 
+!     print*,'ivar(if),nvar(if),var(ivar(if),if),writectl'
+!     print*,ivar(if),nvar(if),var(ivar(if),if),writectl
+      do l=1,nl
+         irec(if)=irec(if)+1
+!        print*,'Ecrit rec=',irec(if),iii,iif,iji,ijf,
+!    s (l-1)*imd(if)*jmd(if)+(iji-1)*imd(if)+iii
+!    s ,(l-1)*imd(if)*jmd(if)+(ijf-1)*imd(if)+iif
+         write(unit(if)+1,rec=irec(if))
+     s   ((field((l-1)*imd(if)*jmd(if)+(j-1)*imd(if)+i)
+     s   ,i=iii,iif),j=iji,ijf)
+      enddo
+      if (writectl) then
+ 
+      file=fichier(if)
+!   WARNING! on reecrase le fichier .ctl a chaque ecriture
+      open(unit(if),file=trim(file)//'.ctl',
+     &         form='formatted',status='unknown')
+      write(unit(if),'(a5,1x,a40)')
+     &       'DSET ','^'//trim(file)//'.dat'
+ 
+      write(unit(if),'(a12)') 'UNDEF 1.0E30'
+      write(unit(if),'(a5,1x,a40)') 'TITLE ',title(if)
+      call formcoord(unit(if),im,xd(iii,if),1.,.false.,'XDEF')
+      call formcoord(unit(if),jm,yd(iji,if),1.,.true.,'YDEF')
+      call formcoord(unit(if),lm,zd(1,if),1.,.false.,'ZDEF')
+      write(unit(if),'(a4,i10,a30)')
+     &       'TDEF ',itime(if),' LINEAR 07AUG1998 30MN '
+      write(unit(if),'(a4,2x,i5)') 'VARS',nvar(if)
+      do iv=1,nvar(if)
+!        print*,'if,var(iv,if),nld(iv,if),nld(iv,if)-1/nld(iv,if)'
+!        print*,if,var(iv,if),nld(iv,if),nld(iv,if)-1/nld(iv,if)
+         write(unit(if),1000) var(iv,if),nld(iv,if)-1/nld(iv,if)
+     &     ,99,tvar(iv,if)
+      enddo
+      write(unit(if),'(a7)') 'ENDVARS'
+!
+1000  format(a5,3x,i4,i3,1x,a39)
+ 
+      close(unit(if))
+ 
+      endif ! writectl
+ 
+      return
+ 
+      END
+ 
+      subroutine inigrads(if,im
+     s  ,x,fx,xmin,xmax,jm,y,ymin,ymax,fy,lm,z,fz
+     s  ,dt,file,titlel)
+ 
+ 
+      implicit none
+ 
+      integer if,im,jm,lm,i,j,l
+      real x(im),y(jm),z(lm),fx,fy,fz,dt
+      real xmin,xmax,ymin,ymax
+      integer nf
+ 
+      character file*10,titlel*40
+ 
+#include "gradsdef.h"
+ 
+      data unit/24,32,34,36,38,40,42,44,46,48/
+      data nf/0/
+ 
+      if (if.le.nf) stop'verifier les appels a inigrads'
+ 
+      print*,'Entree dans inigrads'
+ 
+      nf=if
+      title(if)=titlel
+      ivar(if)=0
+ 
+      fichier(if)=trim(file)
+ 
+      firsttime(if)=.true.
+      dtime(if)=dt
+ 
+      iid(if)=1
+      ifd(if)=im
+      imd(if)=im
+      do i=1,im
+         xd(i,if)=x(i)*fx
+         if(xd(i,if).lt.xmin) iid(if)=i+1
+         if(xd(i,if).le.xmax) ifd(if)=i
+      enddo
+      print*,'On stoke du point ',iid(if),'  a ',ifd(if),' en x'
+ 
+      jid(if)=1
+      jfd(if)=jm
+      jmd(if)=jm
+      do j=1,jm
+         yd(j,if)=y(j)*fy
+         if(yd(j,if).gt.ymax) jid(if)=j+1
+         if(yd(j,if).ge.ymin) jfd(if)=j
+      enddo
+      print*,'On stoke du point ',jid(if),'  a ',jfd(if),' en y'
+
+      print*,'Open de dat'
+      print*,'file=',file
+      print*,'fichier(if)=',fichier(if)
+ 
+      print*,4*(ifd(if)-iid(if))*(jfd(if)-jid(if))
+      print*,trim(file)//'.dat'
+ 
+      OPEN (unit(if)+1,FILE=trim(file)//'.dat',
+     s   FORM='UNFORMATTED',
+     s   ACCESS='DIRECT'
+     s  ,RECL=4*(ifd(if)-iid(if)+1)*(jfd(if)-jid(if)+1))
+ 
+      print*,'Open de dat ok'
+ 
+      lmd(if)=lm
+      do l=1,lm
+         zd(l,if)=z(l)*fz
+      enddo
+ 
+      irec(if)=0
+!CR 
+!      print*,if,imd(if),jmd(if),lmd(if)
+!      print*,'if,imd(if),jmd(if),lmd(if)'
+ 
+      return
+      end
+      SUBROUTINE gr_dyn_fi(nfield,im,jm,ngrid,pdyn,pfi)
+      IMPLICIT NONE
+!=======================================================================
+!   passage d'un champ de la grille scalaire a la grille physique
+!=======================================================================
+ 
+!-----------------------------------------------------------------------
+!   declarations:
+!   -------------
+ 
+      INTEGER im,jm,ngrid,nfield
+      REAL pdyn(im,jm,nfield)
+      REAL pfi(ngrid,nfield)
+ 
+      INTEGER j,ifield,ig
+ 
+!-----------------------------------------------------------------------
+!   calcul:
+!   -------
+ 
+      IF(ngrid.NE.2+(jm-2)*(im-1).AND.ngrid.NE.1)
+     s    STOP 'probleme de dim'
+!   traitement des poles
+      CALL SCOPY(nfield,pdyn,im*jm,pfi,ngrid)
+      CALL SCOPY(nfield,pdyn(1,jm,1),im*jm,pfi(ngrid,1),ngrid)
+ 
+!   traitement des point normaux
+      DO ifield=1,nfield
+         DO j=2,jm-1
+	    ig=2+(j-2)*(im-1)
+            CALL SCOPY(im-1,pdyn(1,j,ifield),1,pfi(ig,ifield),1)
+         ENDDO
+      ENDDO
+ 
+      RETURN
+      END
+ 
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      subroutine writelim
+     s   (phy_nat,phy_alb,phy_sst,phy_bil,phy_rug,phy_ice,
+     s    phy_fter,phy_foce,phy_flic,phy_fsic)
+
+      use dimphy
+      implicit none
+!
+#include "dimensions.h"
+#include "netcdf.inc"
+ 
+      integer klon1d
+      integer k
+      parameter (klon1d=1)
+      REAL phy_nat(klon1d,360)
+      REAL phy_alb(klon1d,360)
+      REAL phy_sst(klon1d,360)
+      REAL phy_bil(klon1d,360)
+      REAL phy_rug(klon1d,360)
+      REAL phy_ice(klon1d,360)
+      REAL phy_fter(klon1d,360)
+      REAL phy_foce(klon1d,360)
+      REAL phy_flic(klon1d,360)
+      REAL phy_fsic(klon1d,360)
+ 
+      INTEGER ierr
+      INTEGER dimfirst(3)
+      INTEGER dimlast(3)
+!
+      INTEGER nid, ndim, ntim
+      INTEGER dims(2), debut(2), epais(2)
+      INTEGER id_tim
+      INTEGER id_NAT, id_SST, id_BILS, id_RUG, id_ALB
+      INTEGER id_FTER,id_FOCE,id_FSIC,id_FLIC
+ 
+      PRINT*, 'Ecriture du fichier limit'
+!
+      ierr = NF_CREATE ("limit.nc", NF_CLOBBER, nid)
+!
+      ierr = NF_PUT_ATT_TEXT (nid, NF_GLOBAL, "title", 30,
+     .                       "Fichier conditions aux limites")
+      ierr = NF_DEF_DIM (nid, "points_physiques", klon1d, ndim)
+      ierr = NF_DEF_DIM (nid, "time", NF_UNLIMITED, ntim)
+!
+      dims(1) = ndim
+      dims(2) = ntim
+!
+!cc      ierr = NF_DEF_VAR (nid, "TEMPS", NF_DOUBLE, 1,ntim, id_tim)
+      ierr = NF_DEF_VAR (nid, "TEMPS", NF_FLOAT, 1,ntim, id_tim)
+      ierr = NF_PUT_ATT_TEXT (nid, id_tim, "title", 17,
+     .                        "Jour dans l annee")
+!cc      ierr = NF_DEF_VAR (nid, "NAT", NF_DOUBLE, 2,dims, id_NAT)
+      ierr = NF_DEF_VAR (nid, "NAT", NF_FLOAT, 2,dims, id_NAT)
+      ierr = NF_PUT_ATT_TEXT (nid, id_NAT, "title", 23,
+     .                        "Nature du sol (0,1,2,3)")
+!cc      ierr = NF_DEF_VAR (nid, "SST", NF_DOUBLE, 2,dims, id_SST)
+      ierr = NF_DEF_VAR (nid, "SST", NF_FLOAT, 2,dims, id_SST)
+      ierr = NF_PUT_ATT_TEXT (nid, id_SST, "title", 35,
+     .                        "Temperature superficielle de la mer")
+!cc      ierr = NF_DEF_VAR (nid, "BILS", NF_DOUBLE, 2,dims, id_BILS)
+      ierr = NF_DEF_VAR (nid, "BILS", NF_FLOAT, 2,dims, id_BILS)
+      ierr = NF_PUT_ATT_TEXT (nid, id_BILS, "title", 32,
+     .                        "Reference flux de chaleur au sol")
+!cc      ierr = NF_DEF_VAR (nid, "ALB", NF_DOUBLE, 2,dims, id_ALB)
+      ierr = NF_DEF_VAR (nid, "ALB", NF_FLOAT, 2,dims, id_ALB)
+      ierr = NF_PUT_ATT_TEXT (nid, id_ALB, "title", 19,
+     .                        "Albedo a la surface")
+!cc      ierr = NF_DEF_VAR (nid, "RUG", NF_DOUBLE, 2,dims, id_RUG)
+      ierr = NF_DEF_VAR (nid, "RUG", NF_FLOAT, 2,dims, id_RUG)
+      ierr = NF_PUT_ATT_TEXT (nid, id_RUG, "title", 8,
+     .                        "Rugosite")
+
+      ierr = NF_DEF_VAR (nid, "FTER", NF_FLOAT, 2,dims, id_FTER)
+      ierr = NF_PUT_ATT_TEXT (nid, id_FTER, "title", 8,"Frac. Terre")
+      ierr = NF_DEF_VAR (nid, "FOCE", NF_FLOAT, 2,dims, id_FOCE)
+      ierr = NF_PUT_ATT_TEXT (nid, id_FOCE, "title", 8,"Frac. Terre")
+      ierr = NF_DEF_VAR (nid, "FSIC", NF_FLOAT, 2,dims, id_FSIC)
+      ierr = NF_PUT_ATT_TEXT (nid, id_FSIC, "title", 8,"Frac. Terre")
+      ierr = NF_DEF_VAR (nid, "FLIC", NF_FLOAT, 2,dims, id_FLIC)
+      ierr = NF_PUT_ATT_TEXT (nid, id_FLIC, "title", 8,"Frac. Terre")
+!
+      ierr = NF_ENDDEF(nid)
+!
+      DO k = 1, 360
+!
+      debut(1) = 1
+      debut(2) = k
+      epais(1) = klon1d
+      epais(2) = 1
+!
+#ifdef NC_DOUBLE
+      ierr = NF_PUT_VAR1_DOUBLE (nid,id_tim,k,DBLE(k))
+      ierr = NF_PUT_VARA_DOUBLE (nid,id_NAT,debut,epais,phy_nat(1,k))
+      ierr = NF_PUT_VARA_DOUBLE (nid,id_SST,debut,epais,phy_sst(1,k))
+      ierr = NF_PUT_VARA_DOUBLE (nid,id_BILS,debut,epais,phy_bil(1,k))
+      ierr = NF_PUT_VARA_DOUBLE (nid,id_ALB,debut,epais,phy_alb(1,k))
+      ierr = NF_PUT_VARA_DOUBLE (nid,id_RUG,debut,epais,phy_rug(1,k))
+      ierr = NF_PUT_VARA_DOUBLE (nid,id_FTER,debut,epais,phy_fter(1,k))
+      ierr = NF_PUT_VARA_DOUBLE (nid,id_FOCE,debut,epais,phy_foce(1,k))
+      ierr = NF_PUT_VARA_DOUBLE (nid,id_FSIC,debut,epais,phy_fsic(1,k))
+      ierr = NF_PUT_VARA_DOUBLE (nid,id_FLIC,debut,epais,phy_flic(1,k))
+#else
+      ierr = NF_PUT_VAR1_REAL (nid,id_tim,k,FLOAT(k))
+      ierr = NF_PUT_VARA_REAL (nid,id_NAT,debut,epais,phy_nat(1,k))
+      ierr = NF_PUT_VARA_REAL (nid,id_SST,debut,epais,phy_sst(1,k))
+      ierr = NF_PUT_VARA_REAL (nid,id_BILS,debut,epais,phy_bil(1,k))
+      ierr = NF_PUT_VARA_REAL (nid,id_ALB,debut,epais,phy_alb(1,k))
+      ierr = NF_PUT_VARA_REAL (nid,id_RUG,debut,epais,phy_rug(1,k))
+      ierr = NF_PUT_VARA_REAL (nid,id_FTER,debut,epais,phy_fter(1,k))
+      ierr = NF_PUT_VARA_REAL (nid,id_FOCE,debut,epais,phy_foce(1,k))
+      ierr = NF_PUT_VARA_REAL (nid,id_FSIC,debut,epais,phy_fsic(1,k))
+      ierr = NF_PUT_VARA_REAL (nid,id_FLIC,debut,epais,phy_flic(1,k))
+
+#endif
+!
+      ENDDO
+!
+      ierr = NF_CLOSE(nid)
+!
+      return
+      end
+ 
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      SUBROUTINE disvert(pa,preff,ap,bp,dpres,presnivs,nivsigs,nivsig)
+ 
+!    Auteur :  P. Le Van .
+!
+      IMPLICIT NONE
+ 
+#include "dimensions.h"
+#include "paramet.h"
+!
+!=======================================================================
+!
+!
+!    s = sigma ** kappa   :  coordonnee  verticale
+!    dsig(l)            : epaisseur de la couche l ds la coord.  s
+!    sig(l)             : sigma a l'interface des couches l et l-1
+!    ds(l)              : distance entre les couches l et l-1 en coord.s
+!
+!=======================================================================
+!
+      REAL pa,preff
+      REAL ap(llmp1),bp(llmp1),dpres(llm),nivsigs(llm),nivsig(llmp1)
+      REAL presnivs(llm)
+!
+!   declarations:
+!   -------------
+!
+      REAL sig(llm+1),dsig(llm)
+!
+      INTEGER l
+      REAL snorm
+      REAL alpha,beta,gama,delta,deltaz,h
+      INTEGER np,ierr
+      REAL pi,x
+ 
+!-----------------------------------------------------------------------
+!
+      pi=2.*ASIN(1.)
+ 
+      OPEN(99,file='sigma.def',status='old',form='formatted',
+     s   iostat=ierr)
+ 
+!-----------------------------------------------------------------------
+!   cas 1 on lit les options dans sigma.def:
+!   ----------------------------------------
+ 
+      IF (ierr.eq.0) THEN
+ 
+      print*,'WARNING!!! on lit les options dans sigma.def'
+      READ(99,*) deltaz
+      READ(99,*) h
+      READ(99,*) beta
+      READ(99,*) gama
+      READ(99,*) delta
+      READ(99,*) np
+      CLOSE(99)
+      alpha=deltaz/(llm*h)
+!
+ 
+       DO 1  l = 1, llm
+       dsig(l) = (alpha+(1.-alpha)*exp(-beta*(llm-l)))*
+     $          ( (tanh(gama*l)/tanh(gama*llm))**np +
+     $            (1.-l/FLOAT(llm))*delta )
+   1   CONTINUE
+ 
+       sig(1)=1.
+       DO 101 l=1,llm-1
+          sig(l+1)=sig(l)*(1.-dsig(l))/(1.+dsig(l))
+101    CONTINUE
+       sig(llm+1)=0.
+ 
+       DO 2  l = 1, llm
+       dsig(l) = sig(l)-sig(l+1)
+   2   CONTINUE
+!
+ 
+      ELSE
+!-----------------------------------------------------------------------
+!   cas 2 ancienne discretisation (LMD5...):
+!   ----------------------------------------
+ 
+      PRINT*,'WARNING!!! Ancienne discretisation verticale'
+ 
+      h=7.
+      snorm  = 0.
+      DO l = 1, llm
+         x = 2.*asin(1.) * (FLOAT(l)-0.5) / float(llm+1)
+         dsig(l) = 1.0 + 7.0 * SIN(x)**2
+         snorm = snorm + dsig(l)
+      ENDDO
+      snorm = 1./snorm
+      DO l = 1, llm
+         dsig(l) = dsig(l)*snorm
+      ENDDO
+      sig(llm+1) = 0.
+      DO l = llm, 1, -1
+         sig(l) = sig(l+1) + dsig(l)
+      ENDDO
+ 
+      ENDIF
+ 
+ 
+      DO l=1,llm
+        nivsigs(l) = FLOAT(l)
+      ENDDO
+ 
+      DO l=1,llmp1
+        nivsig(l)= FLOAT(l)
+      ENDDO
+ 
+!
+!    ....  Calculs  de ap(l) et de bp(l)  ....
+!    .........................................
+!
+!
+!   .....  pa et preff sont lus  sur les fichiers start par lectba  .....
+!
+ 
+      bp(llmp1) =   0.
+ 
+      DO l = 1, llm
+!c
+!cc    ap(l) = 0.
+!cc    bp(l) = sig(l)
+ 
+      bp(l) = EXP( 1. -1./( sig(l)*sig(l)) )
+      ap(l) = pa * ( sig(l) - bp(l) )
+!
+      ENDDO
+      ap(llmp1) = pa * ( sig(llmp1) - bp(llmp1) )
+ 
+      PRINT *,' BP '
+      PRINT *,  bp
+      PRINT *,' AP '
+      PRINT *,  ap
+ 
+      DO l = 1, llm
+       dpres(l) = bp(l) - bp(l+1)
+       presnivs(l) = 0.5 *( ap(l)+bp(l)*preff + ap(l+1)+bp(l+1)*preff )
+      ENDDO
+ 
+      PRINT *,' PRESNIVS '
+      PRINT *,presnivs
+ 
+      RETURN
+      END
+
+!======================================================================
+       SUBROUTINE read_tsurf1d(knon,knindex,sst_out)
+
+! This subroutine specifies the surface temperature to be used in 1D simulations
+
+      USE dimphy, ONLY : klon
+
+      INTEGER, INTENT(IN)                  :: knon     ! nomber of points on compressed grid
+      INTEGER, DIMENSION(klon), INTENT(IN) :: knindex  ! grid point number for compressed grid
+      REAL, DIMENSION(klon), INTENT(OUT)   :: sst_out  ! tsurf used to force the single-column model
+
+       INTEGER :: i
+! COMMON defined in lmdz1d.F:
+       real ts_cur
+       common /sst_forcing/ts_cur
+
+       DO i = 1, knon
+        sst_out(i) = ts_cur
+       ENDDO
+
+      END SUBROUTINE read_tsurf1d
+
+!===============================================================
+      subroutine advect_vert(llm,w,dt,q,plev)
+!===============================================================
+!   Schema amont pour l'advection verticale en 1D
+!   w est la vitesse verticale dp/dt en Pa/s
+!   Traitement en volumes finis 
+!   d / dt ( zm q ) = delta_z ( omega q )
+!   d / dt ( zm ) = delta_z ( omega )
+!   avec zm = delta_z ( p )
+!   si * designe la valeur au pas de temps t+dt
+!   zm*(l) q*(l) - zm(l) q(l) = w(l+1) q(l+1) - w(l) q(l)
+!   zm*(l) -zm(l) = w(l+1) - w(l)
+!   avec w=omega * dt
+!---------------------------------------------------------------
+      implicit none
+! arguments
+      integer llm
+      real w(llm+1),q(llm),plev(llm+1),dt
+
+! local
+      integer l
+      real zwq(llm+1),zm(llm+1),zw(llm+1)
+      real qold
+
+!---------------------------------------------------------------
+
+      do l=1,llm
+         zw(l)=dt*w(l)
+         zm(l)=plev(l)-plev(l+1)
+         zwq(l)=q(l)*zw(l)
+/      enddo
+      zwq(llm+1)=0.
+      zw(llm+1)=0.
+ 
+      do l=1,llm
+         qold=q(l)
+         q(l)=(q(l)*zm(l)+zwq(l+1)-zwq(l))/(zm(l)+zw(l+1)-zw(l))
+         print*,'ADV Q ',zm(l),zw(l),zwq(l),qold,q(l)
+      enddo
+
+ 
+      return
+      end
+
+!===============================================================
+
+
+       SUBROUTINE advect_va(llm,omega,d_t_va,d_q_va,d_u_va,d_v_va,
+     !                q,temp,u,v,
+     !            play,plev)
+!itlmd 
+!----------------------------------------------------------------------
+!   Calcul de l'advection verticale (ascendance et subsidence) de 
+!   température et d'humidité. Hypothèse : ce qui rentre de l'extérieur
+!   a les mêmes caractéristiques que l'air de la colonne 1D (WTG) ou 
+!   sans WTG rajouter une advection horizontale 
+!----------------------------------------------------------------------  
+        implicit none
+#include "YOMCST.h"
+!        argument
+        integer llm
+        real  omega(llm+1),d_t_va(llm), d_q_va(llm,3)
+        real  d_u_va(llm), d_v_va(llm)
+        real  q(llm,3),temp(llm)
+        real  u(llm),v(llm)
+        real  play(llm),plev(llm+1)
+! interne
+        integer l
+        real alpha,omgdown,omgup
+
+      do l= 1,llm
+       if(l.eq.1) then
+!si omgup pour la couche 1, alors tendance nulle
+        omgdown=max(omega(2),0.0)
+        alpha = rkappa*temp(l)*(1.+q(l,1)*rv/rd)/(play(l)*
+     &           (1.+q(l,1)))
+        d_t_va(l)= alpha*(omgdown)- 
+     &              omgdown*(temp(l)-temp(l+1))
+     &              /(play(l)-play(l+1))              
+
+        d_q_va(l,:)= -omgdown*(q(l,:)-q(l+1,:))
+     &              /(play(l)-play(l+1))              
+
+        d_u_va(l)= -omgdown*(u(l)-u(l+1))
+     &              /(play(l)-play(l+1))              
+        d_v_va(l)= -omgdown*(v(l)-v(l+1))
+     &              /(play(l)-play(l+1))              
+
+        
+       elseif(l.eq.llm) then
+        omgup=min(omega(l),0.0)
+        alpha = rkappa*temp(l)*(1.+q(l,1)*rv/rd)/(play(l)*
+     &           (1.+q(l,1)))
+        d_t_va(l)= alpha*(omgup)- 
+!bug?     &              omgup*(temp(l-1)-temp(l))/(play(l-1)-plev(l))
+     &              omgup*(temp(l-1)-temp(l))/(play(l-1)-play(l))
+        d_q_va(l,:)= -omgup*(q(l-1,:)-q(l,:))/(play(l-1)-play(l))
+        d_u_va(l)= -omgup*(u(l-1)-u(l))/(play(l-1)-play(l))
+        d_v_va(l)= -omgup*(v(l-1)-v(l))/(play(l-1)-play(l))
+       
+       else
+        omgup=min(omega(l),0.0)
+        omgdown=max(omega(l+1),0.0)
+        alpha = rkappa*temp(l)*(1.+q(l,1)*rv/rd)/(play(l)*
+     &           (1.+q(l,1)))
+        d_t_va(l)= alpha*(omgup+omgdown)- 
+     &              omgdown*(temp(l)-temp(l+1))
+     &              /(play(l)-play(l+1))-              
+!bug?     &              omgup*(temp(l-1)-temp(l))/(play(l-1)-plev(l))
+     &              omgup*(temp(l-1)-temp(l))/(play(l-1)-play(l))
+!      print*, '  ??? '
+
+        d_q_va(l,:)= -omgdown*(q(l,:)-q(l+1,:))
+     &              /(play(l)-play(l+1))-              
+     &              omgup*(q(l-1,:)-q(l,:))/(play(l-1)-play(l))
+        d_u_va(l)= -omgdown*(u(l)-u(l+1))
+     &              /(play(l)-play(l+1))-              
+     &              omgup*(u(l-1)-u(l))/(play(l-1)-play(l))
+        d_v_va(l)= -omgdown*(v(l)-v(l+1))
+     &              /(play(l)-play(l+1))-              
+     &              omgup*(v(l-1)-v(l))/(play(l-1)-play(l))
+       
+      endif
+         
+      enddo
+!fin itlmd
+        return
+        end
+!       SUBROUTINE lstendH(llm,omega,d_t_va,d_q_va,d_u_va,d_v_va,
+       SUBROUTINE lstendH(llm,nqtot,omega,d_t_va,d_q_va,
+     !                q,temp,u,v,play)
+!itlmd 
+!----------------------------------------------------------------------
+!   Calcul de l'advection verticale (ascendance et subsidence) de 
+!   température et d'humidité. Hypothèse : ce qui rentre de l'extérieur
+!   a les mêmes caractéristiques que l'air de la colonne 1D (WTG) ou 
+!   sans WTG rajouter une advection horizontale 
+!----------------------------------------------------------------------  
+        implicit none
+#include "YOMCST.h"
+!        argument
+        integer llm,nqtot
+        real  omega(llm+1),d_t_va(llm), d_q_va(llm,nqtot)
+!        real  d_u_va(llm), d_v_va(llm)
+        real  q(llm,nqtot),temp(llm)
+        real  u(llm),v(llm)
+        real  play(llm)
+        real cor(llm)
+!        real dph(llm),dudp(llm),dvdp(llm),dqdp(llm),dtdp(llm)
+        real dph(llm),dqdp(llm),dtdp(llm)
+! interne
+        integer l,k
+        real alpha,omdn,omup
+
+!        dudp=0.
+!        dvdp=0.
+        dqdp=0.
+        dtdp=0.
+!        d_u_va=0.
+!        d_v_va=0.
+
+      cor(:) = rkappa*temp*(1.+q(:,1)*rv/rd)/(play*(1.+q(:,1)))
+
+
+      do k=2,llm-1
+
+       dph  (k-1) = (play(k  )- play(k-1  ))
+!       dudp (k-1) = (u   (k  )- u   (k-1  ))/dph(k-1)
+!       dvdp (k-1) = (v   (k  )- v   (k-1  ))/dph(k-1)
+       dqdp (k-1) = (q   (k,1)- q   (k-1,1))/dph(k-1)
+       dtdp (k-1) = (temp(k  )- temp(k-1  ))/dph(k-1)
+
+      enddo
+
+!      dudp (  llm  ) = dudp ( llm-1 )
+!      dvdp (  llm  ) = dvdp ( llm-1 )
+      dqdp (  llm  ) = dqdp ( llm-1 )
+      dtdp (  llm  ) = dtdp ( llm-1 )
+
+      do k=2,llm-1
+      omdn=max(0.0,omega(k+1))
+      omup=min(0.0,omega( k ))
+
+!      d_u_va(k)  = -omdn*dudp(k)-omup*dudp(k-1)
+!      d_v_va(k)  = -omdn*dvdp(k)-omup*dvdp(k-1)
+      d_q_va(k,1)= -omdn*dqdp(k)-omup*dqdp(k-1)
+      d_t_va(k)  = -omdn*dtdp(k)-omup*dtdp(k-1)
+     :              +(omup+omdn)*cor(k)
+      enddo
+
+      omdn=max(0.0,omega( 2 ))
+      omup=min(0.0,omega(llm))
+!      d_u_va( 1 )   = -omdn*dudp( 1 )
+!      d_u_va(llm)   = -omup*dudp(llm)
+!      d_v_va( 1 )   = -omdn*dvdp( 1 )
+!      d_v_va(llm)   = -omup*dvdp(llm)
+      d_q_va( 1 ,1) = -omdn*dqdp( 1 )
+      d_q_va(llm,1) = -omup*dqdp(llm)
+      d_t_va( 1 )   = -omdn*dtdp( 1 )+omdn*cor( 1 )
+      d_t_va(llm)   = -omup*dtdp(llm)!+omup*cor(llm)
+
+!      if(abs(rlat(1))>10.) then
+!     Calculate the tendency due agestrophic motions
+!      du_age = fcoriolis*(v-vg)
+!      dv_age = fcoriolis*(ug-u)
+!      endif
+
+!       call writefield_phy('d_t_va',d_t_va,llm)
+
+          return
+         end
+
+!======================================================================
+      SUBROUTINE read_togacoare(fich_toga,nlev_toga,nt_toga
+     :             ,ts_toga,plev_toga,t_toga,q_toga,u_toga,v_toga,w_toga
+     :             ,ht_toga,vt_toga,hq_toga,vq_toga)
+      implicit none
+
+c-------------------------------------------------------------------------
+c Read TOGA-COARE forcing data 
+c-------------------------------------------------------------------------
+
+      integer nlev_toga,nt_toga
+      real ts_toga(nt_toga),plev_toga(nlev_toga,nt_toga)
+      real t_toga(nlev_toga,nt_toga),q_toga(nlev_toga,nt_toga)
+      real u_toga(nlev_toga,nt_toga),v_toga(nlev_toga,nt_toga)
+      real w_toga(nlev_toga,nt_toga)
+      real ht_toga(nlev_toga,nt_toga),vt_toga(nlev_toga,nt_toga)
+      real hq_toga(nlev_toga,nt_toga),vq_toga(nlev_toga,nt_toga)
+      character*80 fich_toga
+
+      integer no,l,k,ip
+      real riy,rim,rid,rih,bid
+
+      integer iy,im,id,ih
+      
+
+       real plev_min
+
+       plev_min = 55.  ! pas de tendance de vap. d eau au-dessus de 55 hPa
+
+      open(21,file=trim(fich_toga),form='formatted')
+      read(21,'(a)') 
+      do ip = 1, nt_toga
+      read(21,'(a)') 
+      read(21,'(a)') 
+      read(21,223) iy, im, id, ih, bid, ts_toga(ip), bid,bid,bid,bid
+      read(21,'(a)') 
+      read(21,'(a)') 
+
+       do k = 1, nlev_toga
+         read(21,230) plev_toga(k,ip), t_toga(k,ip), q_toga(k,ip) 
+     :       ,u_toga(k,ip), v_toga(k,ip), w_toga(k,ip)
+     :       ,ht_toga(k,ip), vt_toga(k,ip), hq_toga(k,ip), vq_toga(k,ip)
+
+! conversion in SI units:
+         t_toga(k,ip)=t_toga(k,ip)+273.15     ! K
+         q_toga(k,ip)=q_toga(k,ip)*0.001      ! kg/kg
+         w_toga(k,ip)=w_toga(k,ip)*100./3600. ! Pa/s
+! no water vapour tendency above 55 hPa
+         if (plev_toga(k,ip) .lt. plev_min) then
+          q_toga(k,ip) = 0.
+          hq_toga(k,ip) = 0.
+          vq_toga(k,ip) =0.
+         endif
+       enddo
+
+         ts_toga(ip)=ts_toga(ip)+273.15       ! K
+       enddo
+       close(21)
+
+  223 format(4i3,6f8.2)
+  226 format(f7.1,1x,10f8.2)
+  227 format(f7.1,1x,1p,4e11.3)
+  230 format(6f9.3,4e11.3)
+
+          return
+          end
+       end
+
+!=====================================================================
+      subroutine read_twpice(fich_twpice,nlevel,ntime
+     :     ,T_srf,plev,T,q,u,v,omega
+     :     ,T_adv_h,T_adv_v,q_adv_h,q_adv_v)
+
+!program reading forcings of the TWP-ICE experiment
+
+!      use netcdf
+
+      implicit none
+
+#include "netcdf.inc"
+
+      integer ntime,nlevel
+      integer l,k
+      character*80 :: fich_twpice
+      real*8 time(ntime)
+      real*8 lat, lon, alt, phis	
+      real*8 lev(nlevel)
+      real*8 plev(nlevel,ntime)
+
+      real*8 T(nlevel,ntime)
+      real*8 q(nlevel,ntime),u(nlevel,ntime)
+      real*8 v(nlevel,ntime)
+      real*8 omega(nlevel,ntime), div(nlevel,ntime)
+      real*8 T_adv_h(nlevel,ntime)
+      real*8 T_adv_v(nlevel,ntime), q_adv_h(nlevel,ntime)
+      real*8 q_adv_v(nlevel,ntime)	
+      real*8 s(nlevel,ntime), s_adv_h(nlevel,ntime)
+      real*8 s_adv_v(nlevel,ntime)
+      real*8 p_srf_aver(ntime), p_srf_center(ntime)
+      real*8 T_srf(ntime)
+
+      integer nid, ierr
+      integer nbvar3d
+      parameter(nbvar3d=20)
+      integer var3didin(nbvar3d)
+
+      ierr = NF_OPEN(fich_twpice,NF_NOWRITE,nid)
+      if (ierr.NE.NF_NOERR) then
+         write(*,*) 'ERROR: Pb opening forcings cdf file '
+         write(*,*) NF_STRERROR(ierr)
+         stop ""
+      endif
+
+      ierr=NF_INQ_VARID(nid,"lat",var3didin(1))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'lat'
+         endif
+      
+       ierr=NF_INQ_VARID(nid,"lon",var3didin(2))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'lon'
+         endif
+
+       ierr=NF_INQ_VARID(nid,"alt",var3didin(3))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'alt'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"phis",var3didin(4))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'phis'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"T",var3didin(5))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'T'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"q",var3didin(6))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'q'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"u",var3didin(7))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'u'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"v",var3didin(8))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'v'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"omega",var3didin(9))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'omega'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"div",var3didin(10))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'div'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"T_adv_h",var3didin(11))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'T_adv_h'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"T_adv_v",var3didin(12))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'T_adv_v'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"q_adv_h",var3didin(13))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'q_adv_h'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"q_adv_v",var3didin(14))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'q_adv_v'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"s",var3didin(15))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 's'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"s_adv_h",var3didin(16))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 's_adv_h'
+         endif
+    
+      ierr=NF_INQ_VARID(nid,"s_adv_v",var3didin(17))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 's_adv_v'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"p_srf_aver",var3didin(18))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'p_srf_aver'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"p_srf_center",var3didin(19))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'p_srf_center'
+         endif
+
+      ierr=NF_INQ_VARID(nid,"T_srf",var3didin(20))
+         if(ierr/=NF_NOERR) then
+           write(*,*) NF_STRERROR(ierr)
+           stop 'T_srf'
+         endif
+
+!dimensions lecture
+      call catchaxis(nid,ntime,nlevel,time,lev,ierr)
+
+!pressure 
+       do l=1,ntime
+       do k=1,nlevel
+          plev(k,l)=lev(k)
+       enddo
+       enddo
+          
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(1),lat)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(1),lat)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture lat ok',lat
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(2),lon)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(2),lon)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture lon ok',lon
+ 
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(3),alt)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(3),alt)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!          write(*,*)'lecture alt ok',alt
+ 
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(4),phis)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(4),phis)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!          write(*,*)'lecture phis ok',phis
+          
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(5),T)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(5),T)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture T ok'
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(6),q)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(6),q)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture q ok'
+!q in kg/kg
+       do l=1,ntime
+       do k=1,nlevel
+          q(k,l)=q(k,l)/1000.
+       enddo
+       enddo
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(7),u)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(7),u)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture u ok'
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(8),v)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(8),v)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture v ok'
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(9),omega)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(9),omega)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture omega ok'
+!omega in mb/hour
+       do l=1,ntime
+       do k=1,nlevel
+          omega(k,l)=omega(k,l)*100./3600.
+       enddo
+       enddo
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(10),div)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(10),div)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture div ok'
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(11),T_adv_h)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(11),T_adv_h)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture T_adv_h ok'
+!T adv in K/s
+       do l=1,ntime
+       do k=1,nlevel
+          T_adv_h(k,l)=T_adv_h(k,l)/3600.
+       enddo
+       enddo
+
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(12),T_adv_v)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(12),T_adv_v)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture T_adv_v ok'
+!T adv in K/s
+       do l=1,ntime
+       do k=1,nlevel
+          T_adv_v(k,l)=T_adv_v(k,l)/3600.
+       enddo
+       enddo
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(13),q_adv_h)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(13),q_adv_h)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture q_adv_h ok'
+!q adv in kg/kg/s
+       do l=1,ntime
+       do k=1,nlevel
+          q_adv_h(k,l)=q_adv_h(k,l)/1000./3600.
+       enddo
+       enddo
+
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(14),q_adv_v)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(14),q_adv_v)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture q_adv_v ok'
+!q adv in kg/kg/s
+       do l=1,ntime
+       do k=1,nlevel
+          q_adv_v(k,l)=q_adv_v(k,l)/1000./3600.
+       enddo
+       enddo
+
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(15),s)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(15),s)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(16),s_adv_h)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(16),s_adv_h)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(17),s_adv_v)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(17),s_adv_v)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(18),p_srf_aver)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(18),p_srf_aver)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(19),p_srf_center)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(19),p_srf_center)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+
+#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,var3didin(20),T_srf)
+#else
+         ierr = NF_GET_VAR_REAL(nid,var3didin(20),T_srf)
+#endif
+         if(ierr/=NF_NOERR) then
+            write(*,*) NF_STRERROR(ierr)
+            stop "getvarup"
+         endif
+!         write(*,*)'lecture T_srf ok', T_srf
+
+         return 
+         end subroutine read_twpice
+!=====================================================================
+         subroutine catchaxis(nid,ttm,llm,time,lev,ierr)
+
+!         use netcdf
+
+         implicit none
+#include "netcdf.inc"
+         integer nid,ttm,llm
+         real*8 time(ttm)
+         real*8 lev(llm)
+         integer ierr
+
+         integer i
+         integer timevar,levvar
+         integer timelen,levlen
+         integer timedimin,levdimin
+
+! Control & lecture on dimensions
+! ===============================
+         ierr=NF_INQ_DIMID(nid,"time",timedimin)
+         ierr=NF_INQ_VARID(nid,"time",timevar)
+         if (ierr.NE.NF_NOERR) then
+            write(*,*) 'ERROR: Field <time> is missing'
+            stop ""  
+         endif
+         ierr=NF_INQ_DIMLEN(nid,timedimin,timelen)
+
+         ierr=NF_INQ_DIMID(nid,"lev",levdimin)
+         ierr=NF_INQ_VARID(nid,"lev",levvar)
+         if (ierr.NE.NF_NOERR) then
+             write(*,*) 'ERROR: Field <lev> is lacking'
+             stop "" 
+         endif
+         ierr=NF_INQ_DIMLEN(nid,levdimin,levlen)
+
+         if((timelen/=ttm).or.(levlen/=llm)) then
+            write(*,*) 'ERROR: Not the good lenght for axis'
+            write(*,*) 'longitude: ',timelen,ttm+1
+            write(*,*) 'latitude: ',levlen,llm
+            stop ""  
+         endif
+
+!#ifdef NC_DOUBLE
+         ierr = NF_GET_VAR_DOUBLE(nid,timevar,time)
+         ierr = NF_GET_VAR_DOUBLE(nid,levvar,lev)
+!#else
+!        ierr = NF_GET_VAR_REAL(nid,timevar,time)
+!        ierr = NF_GET_VAR_REAL(nid,levvar,lev)
+!#endif
+
+       return
+
+!======================================================================
+      SUBROUTINE read_rico(fich_rico,nlev_rico,ps_rico,play
+     :             ,ts_rico,t_rico,q_rico,u_rico,v_rico,w_rico
+     :             ,dth_dyn,dqh_dyn)
+      implicit none
+
+c-------------------------------------------------------------------------
+c Read RICO forcing data 
+c-------------------------------------------------------------------------
+#include "dimensions.h"
+
+
+      integer nlev_rico
+      real ts_rico,ps_rico
+      real t_rico(llm),q_rico(llm)
+      real u_rico(llm),v_rico(llm)
+      real w_rico(llm)
+      real dth_dyn(llm)
+      real dqh_dyn(llm)
+      
+
+      real play(llm),zlay(llm)
+     
+
+      real prico(nlev_rico),zrico(nlev_rico)
+
+      character*80 fich_rico
+
+      integer k,l
+
+      
+      print*,fich_rico
+      open(21,file=trim(fich_rico),form='formatted')
+        do k=1,llm
+      zlay(k)=0.
+         enddo
+      
+        read(21,*) ps_rico,ts_rico
+        prico(1)=ps_rico
+        zrico(1)=0.0
+      do l=2,nlev_rico
+        read(21,*) k,prico(l),zrico(l)
+      enddo
+       close(21)
+
+      do k=1,llm
+        do l=1,80
+          if(prico(l)>play(k)) then
+              if(play(k)>prico(l+1)) then
+                zlay(k)=zrico(l)+(play(k)-prico(l)) * 
+     &              (zrico(l+1)-zrico(l))/(prico(l+1)-prico(l))
+              else
+                zlay(k)=zrico(l)+(play(k)-prico(80))* 
+     &              (zrico(81)-zrico(80))/(prico(81)-prico(80))
+              endif
+          endif
+        enddo
+        print*,k,zlay(k)
+        ! U
+        if(0 < zlay(k) .and. zlay(k) < 4000) then
+          u_rico(k)=-9.9 + (-1.9 + 9.9)*zlay(k)/4000
+        elseif(4000 < zlay(k) .and. zlay(k) < 12000) then
+       u_rico(k)=  -1.9 + (30.0 + 1.9) / 
+     :          (12000 - 4000) * (zlay(k) - 4000)
+        elseif(12000 < zlay(k) .and. zlay(k) < 13000) then
+          u_rico(k)=30.0
+        elseif(13000 < zlay(k) .and. zlay(k) < 20000) then
+          u_rico(k)=30.0 - (30.0) / 
+     : (20000 - 13000) * (zlay(k) - 13000)
+        else
+          u_rico(k)=0.0
+        endif
+
+!Q_v
+        if(0 < zlay(k) .and. zlay(k) < 740) then
+          q_rico(k)=16.0 + (13.8 - 16.0) / (740) * zlay(k)
+        elseif(740 < zlay(k) .and. zlay(k) < 3260) then
+          q_rico(k)=13.8 + (2.4 - 13.8) / 
+     :          (3260 - 740) * (zlay(k) - 740)
+        elseif(3260 < zlay(k) .and. zlay(k) < 4000) then
+          q_rico(k)=2.4 + (1.8 - 2.4) / 
+     :               (4000 - 3260) * (zlay(k) - 3260)
+        elseif(4000 < zlay(k) .and. zlay(k) < 9000) then
+          q_rico(k)=1.8 + (0 - 1.8) / 
+     :             (10000 - 4000) * (zlay(k) - 4000)
+        else
+          q_rico(k)=0.0
+        endif
+
+!T
+        if(0 < zlay(k) .and. zlay(k) < 740) then
+          t_rico(k)=299.2 + (292.0 - 299.2) / (740) * zlay(k)
+        elseif(740 < zlay(k) .and. zlay(k) < 4000) then
+          t_rico(k)=292.0 + (278.0 - 292.0) /
+     :       (4000 - 740) * (zlay(k) - 740)
+        elseif(4000 < zlay(k) .and. zlay(k) < 15000) then
+          t_rico(k)=278.0 + (203.0 - 278.0) /
+     :       (15000 - 4000) * (zlay(k) - 4000)
+        elseif(15000 < zlay(k) .and. zlay(k) < 17500) then
+          t_rico(k)=203.0 + (194.0 - 203.0) / 
+     :       (17500 - 15000)* (zlay(k) - 15000)
+        elseif(17500 < zlay(k) .and. zlay(k) < 20000) then
+          t_rico(k)=194.0 + (206.0 - 194.0) /
+     :       (20000 - 17500)* (zlay(k) - 17500)
+        elseif(20000 < zlay(k) .and. zlay(k) < 60000) then
+          t_rico(k)=206.0 + (270.0 - 206.0) / 
+     :        (60000 - 20000)* (zlay(k) - 20000)
+        endif
+
+! W
+        if(0 < zlay(k) .and. zlay(k) < 2260 ) then
+          w_rico(k)=- (0.005/2260) * zlay(k)
+        elseif(2260 < zlay(k) .and. zlay(k) < 4000 ) then
+          w_rico(k)=- 0.005
+        elseif(4000 < zlay(k) .and. zlay(k) < 5000 ) then
+       w_rico(k)=- 0.005 + (0.005/ (5000 - 4000)) * (zlay(k) - 4000)
+        else
+          w_rico(k)=0.0
+        endif
+
+! dThrz+dTsw0+dTlw0
+        if(0 < zlay(k) .and. zlay(k) < 4000) then
+          dth_dyn(k)=- 2.51 / 86400 + (-2.18 + 2.51 )/ 
+     :               (86400*4000) * zlay(k)
+        elseif(4000 < zlay(k) .and. zlay(k) < 5000) then
+          dth_dyn(k)=- 2.18 / 86400 + ( 2.18 ) /
+     :           (86400*(5000 - 4000)) * (zlay(k) - 4000)
+        else
+          dth_dyn(k)=0.0
+        endif
+! dQhrz
+        if(0 < zlay(k) .and. zlay(k) < 3000) then
+          dqh_dyn(k)=-1.0 / 86400 + (0.345 + 1.0)/
+     :                    (86400*3000) * (zlay(k))
+        elseif(3000 < zlay(k) .and. zlay(k) < 4000) then
+          dqh_dyn(k)=0.345 / 86400
+        elseif(4000 < zlay(k) .and. zlay(k) < 5000) then
+          dqh_dyn(k)=0.345 / 86400 + 
+     +   (-0.345)/(86400 * (5000 - 4000)) * (zlay(k)-4000)
+        else
+          dqh_dyn(k)=0.0
+        endif
+
+!?        if(play(k)>6e4) then
+!?          ratqs0(1,k)=ratqsbas*(plev(1)-play(k))/(plev(1)-6e4)
+!?        elseif((play(k)>3e4).and.(play(k)<6e4)) then
+!?          ratqs0(1,k)=ratqsbas+(ratqshaut-ratqsbas)&
+!?                          *(6e4-play(k))/(6e4-3e4)
+!?        else
+!?          ratqs0(1,k)=ratqshaut
+!?        endif
+
+      enddo
+
+      do k=1,llm
+      q_rico(k)=q_rico(k)/1e3 
+      dqh_dyn(k)=dqh_dyn(k)/1e3
+      v_rico(k)=-3.8
+      enddo
+
+          return
+          end
+
+!=====================================================================
+c-------------------------------------------------------------------------
+      SUBROUTINE read_armcu(fich_armcu,nlev_armcu,nt_armcu,
+     : sens,flat,adv_theta,rad_theta,adv_qt)
+      implicit none
+
+c-------------------------------------------------------------------------
+c Read ARM_CU case forcing data
+c-------------------------------------------------------------------------
+
+      integer nlev_armcu,nt_armcu
+      real sens(nt_armcu),flat(nt_armcu)
+      real adv_theta(nt_armcu),rad_theta(nt_armcu),adv_qt(nt_armcu)
+      character*80 fich_armcu
+
+      integer no,l,k,ip
+      real riy,rim,rid,rih,bid
+
+      integer iy,im,id,ih,in
+
+      open(21,file=trim(fich_armcu),form='formatted')
+      read(21,'(a)')
+      do ip = 1, nt_armcu
+      read(21,'(a)')
+      read(21,'(a)')
+      read(21,223) iy, im, id, ih, in, sens(ip),flat(ip),
+     :             adv_theta(ip),rad_theta(ip),adv_qt(ip)
+      print *,'forcages=',iy,im,id,ih,in, sens(ip),flat(ip),
+     :             adv_theta(ip),rad_theta(ip),adv_qt(ip)
+      enddo
+      close(21)
+
+  223 format(5i3,5f8.3)
+  226 format(f7.1,1x,10f8.2)
+  227 format(f7.1,1x,1p,4e11.3)
+  230 format(6f9.3,4e11.3)
+
+          return
+          end
+
+!=====================================================================
+       SUBROUTINE interp_toga_vertical(play,nlev_toga,plev_prof
+     :         ,t_prof,q_prof,u_prof,v_prof,w_prof
+     :         ,ht_prof,vt_prof,hq_prof,vq_prof
+     :         ,t_mod,q_mod,u_mod,v_mod,w_mod
+     :         ,ht_mod,vt_mod,hq_mod,vq_mod,mxcalc)
+ 
+       implicit none
+ 
+#include "dimensions.h"
+
+c-------------------------------------------------------------------------
+c Vertical interpolation of TOGA-COARE forcing data onto model levels
+c-------------------------------------------------------------------------
+ 
+       integer nlevmax
+       parameter (nlevmax=41)
+       integer nlev_toga,mxcalc
+!       real play(llm), plev_prof(nlevmax) 
+!       real t_prof(nlevmax),q_prof(nlevmax)
+!       real u_prof(nlevmax),v_prof(nlevmax), w_prof(nlevmax)
+!       real ht_prof(nlevmax),vt_prof(nlevmax)
+!       real hq_prof(nlevmax),vq_prof(nlevmax)
+ 
+       real play(llm), plev_prof(nlev_toga) 
+       real t_prof(nlev_toga),q_prof(nlev_toga)
+       real u_prof(nlev_toga),v_prof(nlev_toga), w_prof(nlev_toga)
+       real ht_prof(nlev_toga),vt_prof(nlev_toga)
+       real hq_prof(nlev_toga),vq_prof(nlev_toga)
+ 
+       real t_mod(llm),q_mod(llm)
+       real u_mod(llm),v_mod(llm), w_mod(llm)
+       real ht_mod(llm),vt_mod(llm)
+       real hq_mod(llm),vq_mod(llm)
+ 
+       integer l,k,k1,k2,kp
+       real aa,frac,frac1,frac2,fact
+ 
+       do l = 1, llm
+
+        if (play(l).ge.plev_prof(nlev_toga)) then
+ 
+        mxcalc=l
+         k1=0
+         k2=0
+
+         if (play(l).le.plev_prof(1)) then
+
+         do k = 1, nlev_toga-1
+          if (play(l).le.plev_prof(k) 
+     :       .and. play(l).gt.plev_prof(k+1)) then
+            k1=k
+            k2=k+1
+          endif
+         enddo
+
+         if (k1.eq.0 .or. k2.eq.0) then
+          write(*,*) 'PB! k1, k2 = ',k1,k2
+          write(*,*) 'l,play(l) = ',l,play(l)/100
+         do k = 1, nlev_toga-1
+          write(*,*) 'k,plev_prof(k) = ',k,plev_prof(k)/100
+         enddo
+         endif
+
+         frac = (plev_prof(k2)-play(l))/(plev_prof(k2)-plev_prof(k1))
+         t_mod(l)= t_prof(k2) - frac*(t_prof(k2)-t_prof(k1))
+         q_mod(l)= q_prof(k2) - frac*(q_prof(k2)-q_prof(k1))
+         u_mod(l)= u_prof(k2) - frac*(u_prof(k2)-u_prof(k1))
+         v_mod(l)= v_prof(k2) - frac*(v_prof(k2)-v_prof(k1))
+         w_mod(l)= w_prof(k2) - frac*(w_prof(k2)-w_prof(k1))
+         ht_mod(l)= ht_prof(k2) - frac*(ht_prof(k2)-ht_prof(k1))
+         vt_mod(l)= vt_prof(k2) - frac*(vt_prof(k2)-vt_prof(k1))
+         hq_mod(l)= hq_prof(k2) - frac*(hq_prof(k2)-hq_prof(k1))
+         vq_mod(l)= vq_prof(k2) - frac*(vq_prof(k2)-vq_prof(k1))
+     
+         else !play>plev_prof(1)
+
+         k1=1
+         k2=2
+         frac1 = (play(l)-plev_prof(k2))/(plev_prof(k1)-plev_prof(k2))
+         frac2 = (play(l)-plev_prof(k1))/(plev_prof(k1)-plev_prof(k2))
+         t_mod(l)= frac1*t_prof(k1) - frac2*t_prof(k2)
+         q_mod(l)= frac1*q_prof(k1) - frac2*q_prof(k2)
+         u_mod(l)= frac1*u_prof(k1) - frac2*u_prof(k2)
+         v_mod(l)= frac1*v_prof(k1) - frac2*v_prof(k2)
+         w_mod(l)= frac1*w_prof(k1) - frac2*w_prof(k2)
+         ht_mod(l)= frac1*ht_prof(k1) - frac2*ht_prof(k2)
+         vt_mod(l)= frac1*vt_prof(k1) - frac2*vt_prof(k2)
+         hq_mod(l)= frac1*hq_prof(k1) - frac2*hq_prof(k2)
+         vq_mod(l)= frac1*vq_prof(k1) - frac2*vq_prof(k2)
+
+         endif ! play.le.plev_prof(1)
+
+        else ! above max altitude of forcing file
+ 
+cjyg
+         fact=20.*(plev_prof(nlev_toga)-play(l))/plev_prof(nlev_toga) !jyg
+         fact = max(fact,0.)                                           !jyg
+         fact = exp(-fact)                                             !jyg
+         t_mod(l)= t_prof(nlev_toga)                                   !jyg
+         q_mod(l)= q_prof(nlev_toga)*fact                              !jyg
+         u_mod(l)= u_prof(nlev_toga)*fact                              !jyg
+         v_mod(l)= v_prof(nlev_toga)*fact                              !jyg
+         w_mod(l)= 0.0                                                 !jyg
+         ht_mod(l)= ht_prof(nlev_toga)                                 !jyg
+         vt_mod(l)= vt_prof(nlev_toga)                                 !jyg
+         hq_mod(l)= hq_prof(nlev_toga)*fact                            !jyg
+         vq_mod(l)= vq_prof(nlev_toga)*fact                            !jyg
+ 
+        endif ! play
+ 
+       enddo ! l
+
+!       do l = 1,llm
+!       print *,'t_mod(l),q_mod(l),ht_mod(l),hq_mod(l) ',
+!     $        l,t_mod(l),q_mod(l),ht_mod(l),hq_mod(l)
+!       enddo
+ 
+          return
+          end
+ 
+!======================================================================
+        SUBROUTINE interp_toga_time(day,day1,annee_ref
+     i             ,year_ini_toga,day_ini_toga,nt_toga,dt_toga,nlev_toga
+     i             ,ts_toga,plev_toga,t_toga,q_toga,u_toga,v_toga,w_toga
+     i             ,ht_toga,vt_toga,hq_toga,vq_toga
+     o             ,ts_prof,plev_prof,t_prof,q_prof,u_prof,v_prof,w_prof
+     o             ,ht_prof,vt_prof,hq_prof,vq_prof)
+        implicit none
+
+!---------------------------------------------------------------------------------------
+! Time interpolation of a 2D field to the timestep corresponding to day
+!
+! day: current julian day (e.g. 717538.2)
+! day1: first day of the simulation
+! nt_toga: total nb of data in the forcing (e.g. 480 for TOGA-COARE)
+! dt_toga: total time interval (in sec) between 2 forcing data (e.g. 6h for TOGA-COARE)
+!---------------------------------------------------------------------------------------
+
+#include "compar1d.h"
+
+! inputs:
+        integer annee_ref
+        integer nt_toga,nlev_toga
+        integer year_ini_toga
+        real day, day1,day_ini_toga,dt_toga
+        real ts_toga(nt_toga)
+        real plev_toga(nlev_toga,nt_toga),t_toga(nlev_toga,nt_toga)
+        real q_toga(nlev_toga,nt_toga),u_toga(nlev_toga,nt_toga)
+        real v_toga(nlev_toga,nt_toga),w_toga(nlev_toga,nt_toga)
+        real ht_toga(nlev_toga,nt_toga),vt_toga(nlev_toga,nt_toga)
+        real hq_toga(nlev_toga,nt_toga),vq_toga(nlev_toga,nt_toga)
+! outputs:
+        real ts_prof
+        real plev_prof(nlev_toga),t_prof(nlev_toga)
+        real q_prof(nlev_toga),u_prof(nlev_toga)
+        real v_prof(nlev_toga),w_prof(nlev_toga)
+        real ht_prof(nlev_toga),vt_prof(nlev_toga)
+        real hq_prof(nlev_toga),vq_prof(nlev_toga)
+! local:
+        integer it_toga1, it_toga2,k
+        real timeit,time_toga1,time_toga2,frac
+
+
+        if (forcing_type.eq.2) then
+! Check that initial day of the simulation consistent with TOGA-COARE period:
+       if (annee_ref.ne.1992 .and. annee_ref.ne.1993) then
+        print*,'Pour TOGA-COARE, annee_ref doit etre 1992 ou 1993'
+        print*,'Changer annee_ref dans run.def'
+        stop
+       endif
+       if (annee_ref.eq.1992 .and. day1.lt.day_ini_toga) then
+        print*,'TOGA-COARE a débuté le 1er Nov 1992 (jour julien=306)'
+        print*,'Changer dayref dans run.def'
+        stop
+       endif
+       if (annee_ref.eq.1993 .and. day1.gt.day_ini_toga+119) then
+        print*,'TOGA-COARE a fini le 28 Feb 1993 (jour julien=59)'
+        print*,'Changer dayref ou nday dans run.def'
+        stop
+       endif
+
+       else if (forcing_type.eq.4) then
+
+! Check that initial day of the simulation consistent with TWP-ICE period:
+       if (annee_ref.ne.2006) then
+        print*,'Pour TWP-ICE, annee_ref doit etre 2006'
+        print*,'Changer annee_ref dans run.def'
+        stop
+       endif
+       if (annee_ref.eq.2006 .and. day1.lt.day_ini_toga) then
+        print*,'TWP-ICE a debute le 17 Jan 2006 (jour julien=17)'
+        print*,'Changer dayref dans run.def'
+        stop
+       endif
+       if (annee_ref.eq.2006 .and. day1.gt.day_ini_toga+26) then
+        print*,'TWP-ICE a fini le 12 Feb 2006 (jour julien=43)'
+        print*,'Changer dayref ou nday dans run.def'
+        stop
+       endif
+
+       endif
+
+! Determine timestep relative to the 1st day of TOGA-COARE:
+!       timeit=(day-day1)*86400.
+!       if (annee_ref.eq.1992) then
+!        timeit=(day-day_ini_toga)*86400.
+!       else
+!        timeit=(day+61.-1.)*86400. ! 61 days between Nov01 and Dec31 1992
+!       endif
+      timeit=(day-day_ini_toga)*86400
+
+! Determine the closest observation times:
+       it_toga1=INT(timeit/dt_toga)+1
+       it_toga2=it_toga1 + 1
+       time_toga1=(it_toga1-1)*dt_toga
+       time_toga2=(it_toga2-1)*dt_toga
+
+       if (it_toga1 .ge. nt_toga) then
+        write(*,*) 'PB-stop: day, it_toga1, it_toga2, timeit: '
+     :        ,day,it_toga1,it_toga2,timeit/86400.
+        stop
+       endif
+
+! time interpolation:
+       frac=(time_toga2-timeit)/(time_toga2-time_toga1)
+       frac=max(frac,0.0)
+
+       ts_prof = ts_toga(it_toga2)
+     :          -frac*(ts_toga(it_toga2)-ts_toga(it_toga1))
+
+!        print*,
+!     :'day,annee_ref,day_ini_toga,timeit,it_toga1,it_toga2,SST:',
+!     :day,annee_ref,day_ini_toga,timeit/86400.,it_toga1,it_toga2,ts_prof
+
+       do k=1,nlev_toga
+        plev_prof(k) = 100.*(plev_toga(k,it_toga2)
+     :          -frac*(plev_toga(k,it_toga2)-plev_toga(k,it_toga1)))
+        t_prof(k) = t_toga(k,it_toga2)
+     :          -frac*(t_toga(k,it_toga2)-t_toga(k,it_toga1))
+        q_prof(k) = q_toga(k,it_toga2)
+     :          -frac*(q_toga(k,it_toga2)-q_toga(k,it_toga1))
+        u_prof(k) = u_toga(k,it_toga2)
+     :          -frac*(u_toga(k,it_toga2)-u_toga(k,it_toga1))
+        v_prof(k) = v_toga(k,it_toga2)
+     :          -frac*(v_toga(k,it_toga2)-v_toga(k,it_toga1))
+        w_prof(k) = w_toga(k,it_toga2)
+     :          -frac*(w_toga(k,it_toga2)-w_toga(k,it_toga1))
+        ht_prof(k) = ht_toga(k,it_toga2)
+     :          -frac*(ht_toga(k,it_toga2)-ht_toga(k,it_toga1))
+        vt_prof(k) = vt_toga(k,it_toga2)
+     :          -frac*(vt_toga(k,it_toga2)-vt_toga(k,it_toga1))
+        hq_prof(k) = hq_toga(k,it_toga2)
+     :          -frac*(hq_toga(k,it_toga2)-hq_toga(k,it_toga1))
+        vq_prof(k) = vq_toga(k,it_toga2)
+     :          -frac*(vq_toga(k,it_toga2)-vq_toga(k,it_toga1))
+        enddo
+
+        return
+        END
+
+!======================================================================
+        SUBROUTINE interp_armcu_time(day,day1,annee_ref
+     i             ,year_ini_armcu,day_ini_armcu,nt_armcu,dt_armcu
+     i             ,nlev_armcu,fs_armcu,fl_armcu,at_armcu,rt_armcu
+     i             ,aqt_armcu,fs_prof,fl_prof,at_prof,rt_prof,aqt_prof)
+        implicit none
+
+!---------------------------------------------------------------------------------------
+! Time interpolation of a 2D field to the timestep corresponding to day
+!
+! day: current julian day (e.g. 717538.2)
+! day1: first day of the simulation
+! nt_armcu: total nb of data in the forcing (e.g. 31 for armcu)
+! dt_armcu: total time interval (in sec) between 2 forcing data (e.g. 1/2h for armcu)
+! fs= sensible flux
+! fl= latent flux
+! at,rt,aqt= advective and radiative tendencies
+!---------------------------------------------------------------------------------------
+
+! inputs:
+        integer annee_ref
+        integer nt_armcu,nlev_armcu
+        integer year_ini_armcu
+        real day, day1,day_ini_armcu,dt_armcu
+        real fs_armcu(nt_armcu),fl_armcu(nt_armcu),at_armcu(nt_armcu)
+        real rt_armcu(nt_armcu),aqt_armcu(nt_armcu)
+! outputs:
+        real fs_prof,fl_prof,at_prof,rt_prof,aqt_prof
+! local:
+        integer it_armcu1, it_armcu2,k
+        real timeit,time_armcu1,time_armcu2,frac
+
+! Check that initial day of the simulation consistent with ARMCU period:
+       if (annee_ref.ne.1997 ) then
+        print*,'Pour ARMCU, annee_ref doit etre 1997 '
+        print*,'Changer annee_ref dans run.def'
+        stop
+       endif
+
+      timeit=(day-day_ini_armcu)*86400
+
+! Determine the closest observation times:
+       it_armcu1=INT(timeit/dt_armcu)+1
+       it_armcu2=it_armcu1 + 1
+       time_armcu1=(it_armcu1-1)*dt_armcu
+       time_armcu2=(it_armcu2-1)*dt_armcu
+       print *,'timeit day day_ini_armcu',timeit,day,day_ini_armcu
+       print *,'it_armcu1,it_armcu2,time_armcu1,time_armcu2',
+     .          it_armcu1,it_armcu2,time_armcu1,time_armcu2
+
+       if (it_armcu1 .ge. nt_armcu) then
+        write(*,*) 'PB-stop: day, it_armcu1, it_armcu2, timeit: '
+     :        ,day,it_armcu1,it_armcu2,timeit/86400.
+        stop
+       endif
+
+! time interpolation:
+       frac=(time_armcu2-timeit)/(time_armcu2-time_armcu1)
+       frac=max(frac,0.0)
+
+       fs_prof = fs_armcu(it_armcu2)
+     :          -frac*(fs_armcu(it_armcu2)-fs_armcu(it_armcu1))
+       fl_prof = fl_armcu(it_armcu2)
+     :          -frac*(fl_armcu(it_armcu2)-fl_armcu(it_armcu1))
+       at_prof = at_armcu(it_armcu2)
+     :          -frac*(at_armcu(it_armcu2)-at_armcu(it_armcu1))
+       rt_prof = rt_armcu(it_armcu2)
+     :          -frac*(rt_armcu(it_armcu2)-rt_armcu(it_armcu1))
+       aqt_prof = aqt_armcu(it_armcu2)
+     :          -frac*(aqt_armcu(it_armcu2)-aqt_armcu(it_armcu1))
+
+         print*,
+     :'day,annee_ref,day_ini_armcu,timeit,it_armcu1,it_armcu2,SST:',
+     :day,annee_ref,day_ini_armcu,timeit/86400.,it_armcu1,
+     :it_armcu2,fs_prof,fl_prof,at_prof,rt_prof,aqt_prof
+
+        return
+        END
+
+!=====================================================================
+      subroutine readprofiles(nlev_max,kmax,height,
+     .           thlprof,qtprof,uprof,
+     .           vprof,e12prof,ugprof,vgprof,
+     .           wfls,dqtdxls,dqtdyls,dqtdtls,
+     .           thlpcar)
+      implicit none
+
+        integer nlev_max,kmax,kmax2
+        logical :: llesread = .true.
+
+        real height(nlev_max),thlprof(nlev_max),qtprof(nlev_max),
+     .       uprof(nlev_max),vprof(nlev_max),e12prof(nlev_max),
+     .       ugprof(nlev_max),vgprof(nlev_max),wfls(nlev_max),
+     .       dqtdxls(nlev_max),dqtdyls(nlev_max),dqtdtls(nlev_max),
+     .           thlpcar(nlev_max)
+
+        integer, parameter :: ilesfile=1
+        integer :: ierr,irad,imax,jtot,k
+        logical :: lmoist,lcoriol,ltimedep
+        real :: xsize,ysize
+        real :: ustin,wsvsurf,timerad
+        character(80) :: chmess
+
+        if(.not.(llesread)) return
+
+       open (ilesfile,file='prof.inp.001',status='old',iostat=ierr)
+        if (ierr /= 0) stop 'ERROR:Prof.inp does not exist'
+        read (ilesfile,*) kmax
+        do k=1,kmax
+          read (ilesfile,*) height(k),thlprof(k),qtprof (k),
+     .                      uprof (k),vprof  (k),e12prof(k)
+        enddo
+        close(ilesfile)
+
+       open(ilesfile,file='lscale.inp.001',status='old',iostat=ierr)
+        if (ierr /= 0) stop 'ERROR:Lscale.inp does not exist'
+        read (ilesfile,*) kmax2
+        if (kmax .ne. kmax2) then
+          print *, 'fichiers prof.inp et lscale.inp incompatibles :'
+          print *, 'nbre de niveaux : ',kmax,' et ',kmax2
+          stop 'lecture profiles'
+        endif
+        do k=1,kmax
+          read (ilesfile,*) height(k),ugprof(k),vgprof(k),wfls(k),
+     .                      dqtdxls(k),dqtdyls(k),dqtdtls(k),thlpcar(k)
+        end do
+        close(ilesfile)
+
+        return
+        end
+
+!===============================================================
+      function ismin(n,sx,incx)
+
+      implicit none
+      integer n,i,incx,ismin,ix
+      real sx((n-1)*incx+1),sxmin
+
+      ix=1
+      ismin=1
+      sxmin=sx(1)
+      do i=1,n-1
+         ix=ix+incx
+         if(sx(ix).lt.sxmin) then
+             sxmin=sx(ix)
+             ismin=i+1
+         endif
+      enddo
+
+      return
+      end
+
+!===============================================================
+      function ismax(n,sx,incx)
+
+      implicit none
+      integer n,i,incx,ismax,ix
+      real sx((n-1)*incx+1),sxmax
+
+      ix=1
+      ismax=1
+      sxmax=sx(1)
+      do i=1,n-1
+         ix=ix+incx
+         if(sx(ix).gt.sxmax) then
+             sxmax=sx(ix)
+             ismax=i+1
+         endif
+      enddo
+
+      return
+      end
+
Index: LMDZ5/branches/testing/libf/phy1d/1D_decl_cases.h
===================================================================
--- LMDZ5/branches/testing/libf/phy1d/1D_decl_cases.h	(revision 1665)
+++ LMDZ5/branches/testing/libf/phy1d/1D_decl_cases.h	(revision 1665)
@@ -0,0 +1,129 @@
+! Declarations specifiques au cas Toga
+        character*80 :: fich_toga
+!        integer nlev_prof
+!        parameter (nlev_prof = 41)
+        integer nlev_toga, nt_toga
+        parameter (nlev_toga=41, nt_toga=480)
+        integer year_ini_toga, day_ini_toga, mth_ini_toga
+        real day_ju_ini_toga   ! Julian day of toga coare first day
+        parameter (year_ini_toga=1992) 
+        parameter (mth_ini_toga=11)
+        parameter (day_ini_toga=1)  !  1erNov1992
+        real dt_toga
+        parameter (dt_toga=6.*3600.)
+!!
+        integer year_print, month_print, day_print
+        real    sec_print
+!!
+        integer nn
+        integer it_toga1, it_toga2
+        real time_toga1,time_toga2
+
+        real ts_toga(nt_toga)
+        real plev_toga(nlev_toga,nt_toga),w_toga(nlev_toga,nt_toga)
+        real t_toga(nlev_toga,nt_toga),q_toga(nlev_toga,nt_toga)
+        real u_toga(nlev_toga,nt_toga),v_toga(nlev_toga,nt_toga)
+        real ht_toga(nlev_toga,nt_toga),vt_toga(nlev_toga,nt_toga)
+        real hq_toga(nlev_toga,nt_toga),vq_toga(nlev_toga,nt_toga)
+
+        real ts_prof
+        real plev_prof(nlev_toga),w_prof(nlev_toga)
+        real t_prof(nlev_toga),q_prof(nlev_toga)
+        real u_prof(nlev_toga),v_prof(nlev_toga)
+        real ht_prof(nlev_toga),vt_prof(nlev_toga)
+        real hq_prof(nlev_toga),vq_prof(nlev_toga)
+
+        real plev_mod(llm),w_mod(llm), t_mod(llm),q_mod(llm)
+        real u_mod(llm),v_mod(llm), ht_mod(llm),vt_mod(llm)
+        real hq_mod(llm),vq_mod(llm),qv_mod(llm),ql_mod(llm),qt_mod(llm)
+
+        real ts_cur
+        common /sst_forcing/ts_cur ! also in read_tsurf1d.F
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+! Declarations specifiques au cas RICO
+        character*80 :: fich_rico
+        integer nlev_rico
+
+        parameter (nlev_rico=81)
+        real ts_rico,ps_rico
+        real w_rico(llm)
+        real t_rico(llm),q_rico(llm)
+        real u_rico(llm),v_rico(llm)
+        real dth_rico(llm)
+        real dqh_rico(llm)
+        real du_age(llm),dv_age(llm)
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+! Declarations specifiques au cas TWPice
+        character*80 :: fich_twpice
+        integer nlev_twpi, nt_twpi
+        parameter (nlev_twpi=40, nt_twpi=215)
+        integer year_ini_twpi, day_ini_twpi, mth_ini_twpi
+        real heure_ini_twpi
+        real day_ju_ini_twpi   ! Julian day of twpice first day
+        parameter (year_ini_twpi=2006) 
+        parameter (mth_ini_twpi=1)
+        parameter (day_ini_twpi=17)  ! 17 = 17Jan2006
+        parameter (heure_ini_twpi=10800.) !3h en secondes
+        real dt_twpi
+        parameter (dt_twpi=3.*3600.)
+
+        real ts_twpi(nt_twpi)
+        real plev_twpi(nlev_twpi,nt_twpi),w_twpi(nlev_twpi,nt_twpi)
+        real t_twpi(nlev_twpi,nt_twpi),q_twpi(nlev_twpi,nt_twpi)
+        real u_twpi(nlev_twpi,nt_twpi),v_twpi(nlev_twpi,nt_twpi)
+        real ht_twpi(nlev_twpi,nt_twpi),vt_twpi(nlev_twpi,nt_twpi)
+        real hq_twpi(nlev_twpi,nt_twpi),vq_twpi(nlev_twpi,nt_twpi)
+
+        real ts_proftwp
+        real plev_proftwp(nlev_twpi),w_proftwp(nlev_twpi)
+        real t_proftwp(nlev_twpi),q_proftwp(nlev_twpi)
+        real u_proftwp(nlev_twpi),v_proftwp(nlev_twpi)
+        real ht_proftwp(nlev_twpi),vt_proftwp(nlev_twpi)
+        real hq_proftwp(nlev_twpi),vq_proftwp(nlev_twpi)
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+! Declarations specifiques au cas GCSSold
+        character*80 :: fich_gcssold_ctl
+        character*80 :: fich_gcssold_dat
+        real  ht_gcssold(llm),hq_gcssold(llm),hw_gcssold(llm)
+        real  hu_gcssold(llm)
+        real  hv_gcssold(llm)
+        real  hthturb_gcssold(llm)
+        real  hqturb_gcssold(llm)
+        real  Ts_gcssold
+        real  dtime_frcg
+cAl1     logical :: imp_fcg_gcssold
+c        logical :: ts_fcg_gcssold 
+c        logical :: Tp_fcg_gcssold 
+        logical :: Turb_fcg_gcssold
+        common /turb_forcing/ dtime_frcg,
+     $      Turb_fcg_gcssold, hthturb_gcssold, hqturb_gcssold
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+! Declarations specifiques au cas Arm_cu
+        character*80 :: fich_armcu
+
+
+        integer nlev_armcu, nt_armcu
+        parameter (nlev_armcu=40, nt_armcu=31)
+        integer year_ini_armcu, day_ini_armcu, mth_ini_armcu
+        real  heure_ini_armcu
+        real day_ju_ini_armcu                                ! Julian day of armcu case first day
+        parameter (year_ini_armcu=1997) 
+        parameter (mth_ini_armcu=6)
+        parameter (day_ini_armcu=21)  ! 172 = 21 juin 1997
+        parameter (heure_ini_armcu=41400)   ! 11:30 en secondes
+        real dt_armcu
+        parameter (dt_armcu=1.*1800.)   ! forcages donnes ttes les demi-heures par ifa_armcu.txt
+        real sens_armcu(nt_armcu),flat_armcu(nt_armcu)
+        real adv_theta_armcu(nt_armcu),rad_theta_armcu(nt_armcu)
+        real adv_qt_armcu(nt_armcu)
+        real theta_mod(llm),rv_mod(llm),play_mod(llm)
+        real d_t_dyn_ls(llm),d_q_dyn_ls(llm)
+! profc comme "profil armcu"
+        real h_profc,play_profc,t_profc,th_profc,plev_profc
+        real u_profc,v_profc,qv_profc,rv_profc
+        
+! forcages interpoles dans le temps
+        real adv_theta_prof,rad_theta_prof,adv_qt_prof
+        real sens_prof,flat_prof,fact
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
Index: LMDZ5/branches/testing/libf/phy1d/1D_interp_cases.h
===================================================================
--- LMDZ5/branches/testing/libf/phy1d/1D_interp_cases.h	(revision 1665)
+++ LMDZ5/branches/testing/libf/phy1d/1D_interp_cases.h	(revision 1665)
@@ -0,0 +1,256 @@
+!---------------------------------------------------------------------
+! Interpolation forcing in time and onto model levels
+!---------------------------------------------------------------------
+      if (forcing_GCSSold) then
+
+       call get_uvd(it,timestep,fich_gcssold_ctl,fich_gcssold_dat,
+     :               ht_gcssold,hq_gcssold,hw_gcssold,
+     :               hu_gcssold,hv_gcssold,
+     :               hthturb_gcssold,hqturb_gcssold,Ts_gcssold,
+     :               imp_fcg_gcssold,ts_fcg_gcssold,
+     :               Tp_fcg_gcssold,Turb_fcg_gcssold)
+       if (prt_level.ge.1) then
+         print *,' get_uvd -> hqturb_gcssold ',it,hqturb_gcssold
+       endif
+! large-scale forcing :
+!!!      tsurf = ts_gcssold
+      do l = 1, llm
+!       u(l) = hu_gcssold(l) !  on prescrit le vent
+!       v(l) = hv_gcssold(l)    !  on prescrit le vent
+!       omega(l) = hw_gcssold(l)
+!       rho(l)  = play(l)/(rd*temp(l)*(1.+(rv/rd-1.)*q(l,1)))
+!       omega2(l)=-rho(l)*omega(l)
+       omega(l) = hw_gcssold(l)
+       omega2(l)= omega(l)/rg*airefi ! flxmass_w calcule comme ds physiq
+
+       alpha = rd*temp(l)*(1.+(rv/rd-1.)*q(l,1))/play(l)
+       d_th_adv(l) = ht_gcssold(l)
+       d_q_adv(l,1) = hq_gcssold(l)
+       dt_cooling(l) = 0.0
+      enddo
+
+      endif ! forcing_GCSSold
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!---------------------------------------------------------------------
+! Interpolation Toga forcing 
+!---------------------------------------------------------------------
+      if (forcing_toga) then
+
+       if (prt_level.ge.1) then
+        print*,
+     : '#### ITAP,day,day1,(day-day1)*86400,(day-day1)*86400/dt_toga=',
+     :    day,day1,(day-day1)*86400.,(day-day1)*86400/dt_toga
+       endif
+
+! time interpolation:
+        CALL interp_toga_time(daytime,day1,annee_ref
+     i             ,year_ini_toga,day_ju_ini_toga,nt_toga,dt_toga
+     i             ,nlev_toga,ts_toga,plev_toga,t_toga,q_toga,u_toga
+     i             ,v_toga,w_toga,ht_toga,vt_toga,hq_toga,vq_toga
+     o             ,ts_prof,plev_prof,t_prof,q_prof,u_prof,v_prof,w_prof
+     o             ,ht_prof,vt_prof,hq_prof,vq_prof)
+
+        if (type_ts_forcing.eq.1) ts_cur = ts_prof ! SST used in read_tsurf1d
+
+! vertical interpolation:
+      CALL interp_toga_vertical(play,nlev_toga,plev_prof
+     :         ,t_prof,q_prof,u_prof,v_prof,w_prof
+     :         ,ht_prof,vt_prof,hq_prof,vq_prof
+     :         ,t_mod,q_mod,u_mod,v_mod,w_mod
+     :         ,ht_mod,vt_mod,hq_mod,vq_mod,mxcalc)
+
+! large-scale forcing :
+      tsurf = ts_prof
+      do l = 1, llm
+       u(l) = u_mod(l) ! sb: on prescrit le vent
+       v(l) = v_mod(l) ! sb: on prescrit le vent
+!       omega(l) = w_prof(l)
+!       rho(l)  = play(l)/(rd*temp(l)*(1.+(rv/rd-1.)*q(l,1)))
+!       omega2(l)=-rho(l)*omega(l)
+       omega(l) = w_mod(l)
+       omega2(l)= omega(l)/rg*airefi ! flxmass_w calcule comme ds physiq
+
+       alpha = rd*temp(l)*(1.+(rv/rd-1.)*q(l,1))/play(l)
+       d_th_adv(l) = alpha*omega(l)/rcpd-(ht_mod(l)+vt_mod(l))
+       d_q_adv(l,1) = -(hq_mod(l)+vq_mod(l))
+       dt_cooling(l) = 0.0
+      enddo
+
+      endif ! forcing_toga
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!---------------------------------------------------------------------
+! Interpolation forcing TWPice
+!---------------------------------------------------------------------
+      if (forcing_twpice) then
+
+        print*,
+     : '#### ITAP,day,day1,(day-day1)*86400,(day-day1)*86400/dt_twpi=',
+     :    daytime,day1,(daytime-day1)*86400.,
+     :    (daytime-day1)*86400/dt_twpi
+
+! time interpolation:
+        CALL interp_toga_time(daytime,day1,annee_ref
+     i       ,year_ini_twpi,day_ju_ini_twpi,nt_twpi,dt_twpi,nlev_twpi
+     i       ,ts_twpi,plev_twpi,t_twpi,q_twpi,u_twpi,v_twpi,w_twpi
+     i       ,ht_twpi,vt_twpi,hq_twpi,vq_twpi
+     o       ,ts_proftwp,plev_proftwp,t_proftwp,q_proftwp,u_proftwp
+     o       ,v_proftwp,w_proftwp
+     o       ,ht_proftwp,vt_proftwp,hq_proftwp,vq_proftwp)
+
+! vertical interpolation:
+      CALL interp_toga_vertical(play,nlev_twpi,plev_proftwp
+     :         ,t_proftwp,q_proftwp,u_proftwp,v_proftwp,w_proftwp
+     :         ,ht_proftwp,vt_proftwp,hq_proftwp,vq_proftwp
+     :         ,t_mod,q_mod,u_mod,v_mod,w_mod
+     :         ,ht_mod,vt_mod,hq_mod,vq_mod,mxcalc)
+
+
+!calcul de l'advection verticale a partir du omega
+cCalcul des gradients verticaux
+cinitialisation
+      d_t_z(:)=0.
+      d_q_z(:)=0.
+      d_t_dyn_z(:)=0.
+      d_q_dyn_z(:)=0.
+      DO l=2,llm-1
+       d_t_z(l)=(temp(l+1)-temp(l-1))
+     &          /(play(l+1)-play(l-1))
+       d_q_z(l)=(q(l+1,1)-q(l-1,1))
+     &          /(play(l+1)-play(l-1))
+      ENDDO
+      d_t_z(1)=d_t_z(2)
+      d_q_z(1)=d_q_z(2)
+      d_t_z(llm)=d_t_z(llm-1)
+      d_q_z(llm)=d_q_z(llm-1)
+
+cCalcul de l advection verticale
+      d_t_dyn_z(:)=w_mod(:)*d_t_z(:)
+      d_q_dyn_z(:)=w_mod(:)*d_q_z(:)
+
+!wind nudging above 500m with a 2h time scale
+        do l=1,llm
+        if (nudge_wind) then
+!           if (phi(l).gt.5000.) then
+        if (phi(l).gt.0.) then
+        u(l)=u(l)
+     .      +timestep*(u_mod(l)-u(l))/(2.*3600.)
+        v(l)=v(l) 
+     .      +timestep*(v_mod(l)-v(l))/(2.*3600.)
+           endif    
+        else
+        u(l) = u_mod(l) 
+        v(l) = v_mod(l)
+        endif
+        enddo
+
+!CR:nudging of q and theta with a 6h time scale above 15km
+        if (nudge_thermo) then
+        do l=1,llm
+           zz(l)=phi(l)/9.8
+           if ((zz(l).le.16000.).and.(zz(l).gt.15000.)) then
+             zfact=(zz(l)-15000.)/1000.
+        q(l,1)=q(l,1)
+     .      +timestep*(q_mod(l)-q(l,1))/(6.*3600.)*zfact
+        temp(l)=temp(l) 
+     .      +timestep*(t_mod(l)-temp(l))/(6.*3600.)*zfact
+           else if (zz(l).gt.16000.) then 
+        q(l,1)=q(l,1)
+     .      +timestep*(q_mod(l)-q(l,1))/(6.*3600.)
+        temp(l)=temp(l) 
+     .      +timestep*(t_mod(l)-temp(l))/(6.*3600.)
+           endif
+        enddo    
+        endif
+
+      do l = 1, llm
+       omega(l) = w_mod(l)
+       omega2(l)= omega(l)/rg*airefi ! flxmass_w calcule comme ds physiq
+       alpha = rd*temp(l)*(1.+(rv/rd-1.)*q(l,1))/play(l)
+!calcul de l'advection totale
+        if (cptadvw) then
+        d_th_adv(l) = alpha*omega(l)/rcpd+ht_mod(l)-d_t_dyn_z(l)
+!        print*,'temp vert adv',l,ht_mod(l),vt_mod(l),-d_t_dyn_z(l)
+        d_q_adv(l,1) = hq_mod(l)-d_q_dyn_z(l)
+!        print*,'q vert adv',l,hq_mod(l),vq_mod(l),-d_q_dyn_z(l)
+        else
+        d_th_adv(l) = alpha*omega(l)/rcpd+(ht_mod(l)+vt_mod(l))
+        d_q_adv(l,1) = (hq_mod(l)+vq_mod(l))
+        endif
+       dt_cooling(l) = 0.0
+      enddo
+
+      endif ! forcing_twpice
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!---------------------------------------------------------------------
+! Interpolation forcing Rico
+!---------------------------------------------------------------------
+      if (forcing_rico) then
+!       call lstendH(llm,omega,dt_dyn,dq_dyn,du_dyn, dv_dyn,
+!     :  q,temp,u,v,play)
+       call lstendH(llm,nqtot,omega,dt_dyn,dq_dyn,
+     :  q,temp,u,v,play)
+
+        do l=1,llm
+       d_th_adv(l) =  (dth_rico(l) +  dt_dyn(l))
+       d_q_adv(l,1) = (dqh_rico(l) +  dq_dyn(l,1))
+       d_q_adv(l,2) = 0.
+        enddo
+      endif  ! forcing_rico
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!---------------------------------------------------------------------
+! Interpolation forcing Arm_cu
+!---------------------------------------------------------------------
+      if (forcing_armcu) then
+
+        print*,
+     : '#### ITAP,day,day1,(day-day1)*86400,(day-day1)*86400/dt_armcu=',
+     :    day,day1,(day-day1)*86400.,(day-day1)*86400/dt_armcu
+
+! time interpolation:
+! ATTENTION, cet appel ne convient pas pour TOGA !!
+! revoir 1DUTILS.h et les arguments
+      CALL interp_armcu_time(daytime,day1,annee_ref
+     i            ,year_ini_armcu,day_ju_ini_armcu,nt_armcu,dt_armcu
+     i            ,nlev_armcu,sens_armcu,flat_armcu,adv_theta_armcu
+     i            ,rad_theta_armcu,adv_qt_armcu,sens_prof,flat_prof
+     i            ,adv_theta_prof,rad_theta_prof,adv_qt_prof)
+
+! vertical interpolation:
+! No vertical interpolation if nlev imposed to 19 or 40
+
+! For this case, fluxes are imposed
+       fsens=-1*sens_prof
+       flat=-1*flat_prof
+
+! Advective forcings are given in K or g/kg ... BY HOUR
+      do l = 1, llm
+       ug(l)= u_mod(l)
+       vg(l)= v_mod(l)
+       IF((phi(l)/RG).LT.1000) THEN
+         d_th_adv(l) = (adv_theta_prof + rad_theta_prof)/3600.
+         d_q_adv(l,1) = adv_qt_prof/1000./3600.
+         d_q_adv(l,2) = 0.0
+!        print *,'INF1000: phi dth dq1 dq2',
+!    :  phi(l)/RG,d_th_adv(l),d_q_adv(l,1),d_q_adv(l,2)
+       ELSEIF ((phi(l)/RG).GE.1000.AND.(phi(l)/RG).lt.3000) THEN
+         fact=((phi(l)/RG)-1000.)/2000.
+         fact=1-fact
+         d_th_adv(l) = (adv_theta_prof + rad_theta_prof)*fact/3600.
+         d_q_adv(l,1) = adv_qt_prof*fact/1000./3600.
+         d_q_adv(l,2) = 0.0
+!        print *,'SUP1000: phi fact dth dq1 dq2',
+!    :  phi(l)/RG,fact,d_th_adv(l),d_q_adv(l,1),d_q_adv(l,2)
+       ELSE
+         d_th_adv(l) = 0.0
+         d_q_adv(l,1) = 0.0
+         d_q_adv(l,2) = 0.0
+!        print *,'SUP3000: phi dth dq1 dq2',
+!    :  phi(l)/RG,d_th_adv(l),d_q_adv(l,1),d_q_adv(l,2)
+       ENDIF
+      dt_cooling(l) = 0.0  
+!     print *,'Interp armcu: phi dth dq1 dq2',
+!    :  l,phi(l),d_th_adv(l),d_q_adv(l,1),d_q_adv(l,2)
+      enddo
+      endif ! forcing_armcu
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
Index: LMDZ5/branches/testing/libf/phy1d/1D_read_forc_cases.h
===================================================================
--- LMDZ5/branches/testing/libf/phy1d/1D_read_forc_cases.h	(revision 1665)
+++ LMDZ5/branches/testing/libf/phy1d/1D_read_forc_cases.h	(revision 1665)
@@ -0,0 +1,368 @@
+!----------------------------------------------------------------------
+! forcing_les = .T. : Impose a constant cooling 
+! forcing_radconv = .T. : Pure radiative-convective equilibrium:
+!----------------------------------------------------------------------
+
+      if (forcing_les .or. forcing_radconv .or. forcing_GCSSold ) then
+
+!----------------------------------------------------------------------
+! Read profiles from files: prof.inp.001 and lscale.inp.001
+! (repris de readlesfiles)
+!----------------------------------------------------------------------
+
+      call readprofiles(nlev_max,kmax,height,
+     .           tttprof,qtprof,uprof,vprof,
+     .           e12prof,ugprof,vgprof,
+     .           wfls,dqtdxls,dqtdyls,dqtdtls,
+     .           thlpcar) 
+
+! compute altitudes of play levels.
+      zlay(1) =zsurf +  rd*tsurf*(psurf-play(1))/(rg*psurf)
+      do l = 2,llm
+        zlay(l) = zlay(l-1)+rd*tsurf*(psurf-play(1))/(rg*psurf)
+      enddo
+
+!----------------------------------------------------------------------
+! Interpolation of the profiles given on the input file to
+! model levels
+!----------------------------------------------------------------------
+      zlay(1) = zsurf +  rd*tsurf*(psurf-play(1))/(rg*psurf)
+      do l=1,llm
+        ! Above the max altutide of the input file
+
+        if (zlay(l)<height(kmax)) mxcalc=l
+
+        frac = (height(kmax)-zlay(l))/(height (kmax)-height(kmax-1))
+        ttt =tttprof(kmax)-frac*(tttprof(kmax)-tttprof(kmax-1))
+        if (forcing_GCSSold .AND. tp_ini_GCSSold) then ! pot. temp. in initial profile
+          temp(l) = ttt*(play(l)/pzero)**rkappa
+          teta(l) = ttt
+        else
+          temp(l) = ttt
+          teta(l) = ttt*(pzero/play(l))**rkappa
+        endif
+          print *,' temp,teta ',l,temp(l),teta(l)
+        q(l,1)  = qtprof(kmax)-frac*( qtprof(kmax)- qtprof(kmax-1))
+        u(l)    =  uprof(kmax)-frac*(  uprof(kmax)-  uprof(kmax-1))
+        v(l)    =  vprof(kmax)-frac*(  vprof(kmax)-  vprof(kmax-1))
+        ug(l)   = ugprof(kmax)-frac*( ugprof(kmax)- ugprof(kmax-1))
+        vg(l)   = vgprof(kmax)-frac*( vgprof(kmax)- vgprof(kmax-1))
+        omega(l)=   wfls(kmax)-frac*(   wfls(kmax)-   wfls(kmax-1))
+
+        dq_dyn(l,1) = dqtdtls(kmax)-frac*(dqtdtls(kmax)-dqtdtls(kmax-1))
+        dt_cooling(l)
+     .          =thlpcar(kmax)-frac*(thlpcar(kmax)-thlpcar(kmax-1))
+        do k=2,kmax
+          frac = (height(k)-zlay(l))/(height(k)-height(k-1))
+          if(l==1) print*,'k, height, tttprof',k,height(k),tttprof(k)
+          if(zlay(l)>height(k-1).and.zlay(l)<height(k)) then
+            ttt =tttprof(k)-frac*(tttprof(k)-tttprof(k-1))
+        if (forcing_GCSSold .AND. tp_ini_GCSSold) then ! pot. temp. in initial profile
+          temp(l) = ttt*(play(l)/pzero)**rkappa
+          teta(l) = ttt
+        else
+          temp(l) = ttt
+          teta(l) = ttt*(pzero/play(l))**rkappa
+        endif
+          print *,' temp,teta ',l,temp(l),teta(l)
+            q(l,1)  = qtprof(k)-frac*( qtprof(k)- qtprof(k-1))
+            u(l)    =  uprof(k)-frac*(  uprof(k)-  uprof(k-1))
+            v(l)    =  vprof(k)-frac*(  vprof(k)-  vprof(k-1))
+            ug(l)   = ugprof(k)-frac*( ugprof(k)- ugprof(k-1))
+            vg(l)   = vgprof(k)-frac*( vgprof(k)- vgprof(k-1))
+            omega(l)=   wfls(k)-frac*(   wfls(k)-   wfls(k-1))
+            dq_dyn(l,1)=dqtdtls(k)-frac*(dqtdtls(k)-dqtdtls(k-1))
+            dt_cooling(l)
+     .              =thlpcar(k)-frac*(thlpcar(k)-thlpcar(k-1))
+          elseif(zlay(l)<height(1)) then ! profils uniformes pour z<height(1)
+            ttt =tttprof(1)
+        if (forcing_GCSSold .AND. tp_ini_GCSSold) then ! pot. temp. in initial profile
+          temp(l) = ttt*(play(l)/pzero)**rkappa
+          teta(l) = ttt
+        else
+          temp(l) = ttt
+          teta(l) = ttt*(pzero/play(l))**rkappa
+        endif
+            q(l,1)  = qtprof(1)
+            u(l)    =  uprof(1)
+            v(l)    =  vprof(1)
+            ug(l)   = ugprof(1)
+            vg(l)   = vgprof(1)
+            omega(l)=   wfls(1)
+            dq_dyn(l,1)  =dqtdtls(1)
+            dt_cooling(l)=thlpcar(1)
+          endif
+        enddo 
+
+        temp(l)=max(min(temp(l),350.),150.)
+        rho(l)  = play(l)/(rd*temp(l)*(1.+(rv/rd-1.)*q(l,1)))
+        if (l .lt. llm) then
+          zlay(l+1) = zlay(l) + (play(l)-play(l+1))/(rg*rho(l))
+        endif
+        omega2(l)=-rho(l)*omega(l)
+        omega(l)= omega(l)*(-rg*rho(l)) !en Pa/s
+        if (l>1) then
+        if(zlay(l-1)>height(kmax)) then
+           omega(l)=0.0
+           omega2(l)=0.0
+        endif   
+        endif
+        if(q(l,1)<0.) q(l,1)=0.0
+        q(l,2)  = 0.0
+      enddo
+
+      endif ! forcing_les .or. forcing_GCSSold
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!---------------------------------------------------------------------
+! Forcing for GCSSold:
+!---------------------------------------------------------------------
+      if (forcing_GCSSold) then
+       fich_gcssold_ctl = './forcing.ctl'
+       fich_gcssold_dat = './forcing8.dat'
+       call copie(llm,play,psurf,fich_gcssold_ctl)
+       call get_uvd2(it,timestep,fich_gcssold_ctl,fich_gcssold_dat,
+     :               ht_gcssold,hq_gcssold,hw_gcssold,
+     :               hu_gcssold,hv_gcssold,
+     :               hthturb_gcssold,hqturb_gcssold,Ts_gcssold,
+     :               imp_fcg_gcssold,ts_fcg_gcssold,
+     :               Tp_fcg_gcssold,Turb_fcg_gcssold)
+       print *,' get_uvd2 -> hqturb_gcssold ',hqturb_gcssold
+      endif ! forcing_GCSSold
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!---------------------------------------------------------------------
+! Forcing for RICO:
+!---------------------------------------------------------------------
+      if (forcing_rico) then
+
+!       call writefield_phy('omega', omega,llm+1)
+      fich_rico = 'rico.txt'
+       call read_rico(fich_rico,nlev_rico,ps_rico,play
+     :             ,ts_rico,t_rico,q_rico,u_rico,v_rico,w_rico
+     :             ,dth_rico,dqh_rico)
+        print*, ' on a lu et prepare RICO'
+
+       mxcalc=llm
+       print *, airefi, ' airefi '
+       do l = 1, llm
+       rho(l)  = play(l)/(rd*t_rico(l)*(1.+(rv/rd-1.)*q_rico(l)))
+       temp(l) = t_rico(l)
+       q(l,1) = q_rico(l)
+       q(l,2) = 0.0
+       u(l) = u_rico(l)
+       v(l) = v_rico(l)
+       ug(l)=u_rico(l)
+       vg(l)=v_rico(l)
+       omega(l) = -w_rico(l)*rg
+       omega2(l) = omega(l)/rg*airefi
+       enddo
+      endif
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!---------------------------------------------------------------------
+! Forcing from TOGA-COARE experiment (Ciesielski et al. 2002) :
+!---------------------------------------------------------------------
+
+      if (forcing_toga) then
+
+! read TOGA-COARE forcing (native vertical grid, nt_toga timesteps):
+      fich_toga = './d_toga/ifa_toga_coare_v21_dime.txt'
+      CALL read_togacoare(fich_toga,nlev_toga,nt_toga
+     :         ,ts_toga,plev_toga,t_toga,q_toga,u_toga,v_toga,w_toga
+     :         ,ht_toga,vt_toga,hq_toga,vq_toga)
+
+       write(*,*) 'Forcing TOGA lu'
+
+! time interpolation for initial conditions:
+      write(*,*) 'AVT 1ere INTERPOLATION: day,day1 = ',day,day1
+      CALL interp_toga_time(daytime,day1,annee_ref
+     i             ,year_ini_toga,day_ju_ini_toga,nt_toga,dt_toga
+     i             ,nlev_toga,ts_toga,plev_toga,t_toga,q_toga,u_toga
+     i             ,v_toga,w_toga,ht_toga,vt_toga,hq_toga,vq_toga
+     o             ,ts_prof,plev_prof,t_prof,q_prof,u_prof,v_prof,w_prof
+     o             ,ht_prof,vt_prof,hq_prof,vq_prof)
+
+! vertical interpolation:
+      CALL interp_toga_vertical(play,nlev_toga,plev_prof
+     :         ,t_prof,q_prof,u_prof,v_prof,w_prof
+     :         ,ht_prof,vt_prof,hq_prof,vq_prof
+     :         ,t_mod,q_mod,u_mod,v_mod,w_mod
+     :         ,ht_mod,vt_mod,hq_mod,vq_mod,mxcalc)
+       write(*,*) 'Profil initial forcing TOGA interpole'
+
+! initial and boundary conditions :
+      tsurf = ts_prof
+      write(*,*) 'SST initiale: ',tsurf
+      do l = 1, llm
+       temp(l) = t_mod(l)
+       q(l,1) = q_mod(l)
+       q(l,2) = 0.0
+       u(l) = u_mod(l)
+       v(l) = v_mod(l)
+       omega(l) = w_mod(l)
+       omega2(l)=omega(l)/rg*airefi ! flxmass_w calcule comme ds physiq
+!?       rho(l)  = play(l)/(rd*temp(l)*(1.+(rv/rd-1.)*q(l,1)))
+!?       omega2(l)=-rho(l)*omega(l)
+       alpha = rd*temp(l)*(1.+(rv/rd-1.)*q(l,1))/play(l)
+       d_th_adv(l) = alpha*omega(l)/rcpd-(ht_mod(l)+vt_mod(l))
+       d_q_adv(l,1) = -(hq_mod(l)+vq_mod(l))
+       d_q_adv(l,2) = 0.0
+      enddo
+
+      endif ! forcing_toga
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!---------------------------------------------------------------------
+! Forcing from TWPICE experiment (Shaocheng et al. 2010) :
+!---------------------------------------------------------------------
+
+      if (forcing_twpice) then
+!read TWP-ICE forcings
+      fich_twpice=
+     : 'd_twpi/twp180iopsndgvarana_v2.1_C3.c1.20060117.000000.cdf'
+      call read_twpice(fich_twpice,nlev_twpi,nt_twpi
+     :     ,ts_twpi,plev_twpi,t_twpi,q_twpi,u_twpi,v_twpi,w_twpi
+     :     ,ht_twpi,vt_twpi,hq_twpi,vq_twpi)
+
+      write(*,*) 'Forcing TWP-ICE lu'
+!Time interpolation for initial conditions using TOGA interpolation routine
+         write(*,*) 'AVT 1ere INTERPOLATION: day,day1 = ',daytime,day1   
+      CALL interp_toga_time(daytime,day1,annee_ref
+     i          ,year_ini_twpi,day_ju_ini_twpi,nt_twpi,dt_twpi,nlev_twpi
+     i             ,ts_twpi,plev_twpi,t_twpi,q_twpi,u_twpi,v_twpi,w_twpi
+     i             ,ht_twpi,vt_twpi,hq_twpi,vq_twpi
+     o             ,ts_proftwp,plev_proftwp,t_proftwp,q_proftwp
+     o             ,u_proftwp,v_proftwp,w_proftwp
+     o             ,ht_proftwp,vt_proftwp,hq_proftwp,vq_proftwp)
+
+! vertical interpolation using TOGA interpolation routine:
+!      write(*,*)'avant interp vert', t_proftwp
+      CALL interp_toga_vertical(play,nlev_twpi,plev_proftwp
+     :         ,t_proftwp,q_proftwp,u_proftwp,v_proftwp,w_proftwp
+     :         ,ht_proftwp,vt_proftwp,hq_proftwp,vq_proftwp
+     :         ,t_mod,q_mod,u_mod,v_mod,w_mod
+     :         ,ht_mod,vt_mod,hq_mod,vq_mod,mxcalc)
+!       write(*,*) 'Profil initial forcing TWP-ICE interpole',t_mod
+
+! initial and boundary conditions :
+!      tsurf = ts_proftwp
+      write(*,*) 'SST initiale: ',tsurf
+      do l = 1, llm
+       temp(l) = t_mod(l)
+       q(l,1) = q_mod(l)
+       q(l,2) = 0.0
+       u(l) = u_mod(l)
+       v(l) = v_mod(l)
+       omega(l) = w_mod(l)
+       omega2(l)=omega(l)/rg*airefi ! flxmass_w calcule comme ds physiq
+
+       alpha = rd*temp(l)*(1.+(rv/rd-1.)*q(l,1))/play(l)
+!on applique le forcage total au premier pas de temps
+!attention: signe different de toga
+       d_th_adv(l) = alpha*omega(l)/rcpd+(ht_mod(l)+vt_mod(l))
+       d_q_adv(l,1) = (hq_mod(l)+vq_mod(l))
+       d_q_adv(l,2) = 0.0
+      enddo     
+       
+      endif !forcing_twpice
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!---------------------------------------------------------------------
+! Forcing from Arm_Cu case                   
+! For this case, ifa_armcu.txt contains sensible, latent heat fluxes
+! large scale advective forcing,radiative forcing 
+! and advective tendency of theta and qt to be applied 
+!---------------------------------------------------------------------
+
+      if (forcing_armcu) then
+! read armcu forcing :
+       write(*,*) 'Avant lecture Forcing Arm_Cu'
+      fich_armcu = './ifa_armcu.txt'
+      CALL read_armcu(fich_armcu,nlev_armcu,nt_armcu,
+     : sens_armcu,flat_armcu,adv_theta_armcu,
+     : rad_theta_armcu,adv_qt_armcu)
+       write(*,*) 'Forcing Arm_Cu lu'
+
+!----------------------------------------------------------------------
+! Read profiles from file: prof.inp.19 or prof.inp.40 
+! For this case, profiles are given for two vertical resolution
+! 19 or 40 levels
+!
+! Comment from: http://www.knmi.nl/samenw/eurocs/ARM/profiles.html
+! Note that the initial profiles contain no liquid water! 
+! (so potential temperature can be interpreted as liquid water 
+! potential temperature and water vapor as total water)
+! profiles are given at full levels
+!----------------------------------------------------------------------
+
+      call readprofile_armcu(nlev_max,kmax,height,play_mod,u_mod,
+     .           v_mod,theta_mod,t_mod,qv_mod,rv_mod,ap,bp)
+
+! time interpolation for initial conditions:
+      write(*,*) 'AVT 1ere INTERPOLATION: day,day1 = ',day,day1
+
+      print *,'Avant interp_armcu_time'
+      print *,'daytime=',daytime
+      print *,'day1=',day1
+      print *,'annee_ref=',annee_ref
+      print *,'year_ini_armcu=',year_ini_armcu
+      print *,'day_ju_ini_armcu=',day_ju_ini_armcu
+      print *,'nt_armcu=',nt_armcu
+      print *,'dt_armcu=',dt_armcu
+      print *,'nlev_armcu=',nlev_armcu
+      CALL interp_armcu_time(daytime,day1,annee_ref
+     i            ,year_ini_armcu,day_ju_ini_armcu,nt_armcu,dt_armcu
+     i            ,nlev_armcu,sens_armcu,flat_armcu,adv_theta_armcu
+     i            ,rad_theta_armcu,adv_qt_armcu,sens_prof,flat_prof
+     i            ,adv_theta_prof,rad_theta_prof,adv_qt_prof)
+       write(*,*) 'Forcages interpoles dans temps'
+
+! No vertical interpolation if nlev imposed to 19 or 40
+! The vertical grid stops at 4000m # 600hPa
+      mxcalc=llm
+
+! initial and boundary conditions :
+!     tsurf = ts_prof
+! tsurf read in lmdz1d.def
+      write(*,*) 'Tsurf initiale: ',tsurf
+      do l = 1, llm
+       play(l)=play_mod(l)*100.
+       presnivs(l)=play(l)
+       zlay(l)=height(l)
+       temp(l) = t_mod(l)
+       teta(l)=theta_mod(l)
+       q(l,1) = qv_mod(l)/1000.
+! No liquid water in the initial profil
+       q(l,2) = 0.
+       u(l) = u_mod(l)
+       ug(l)= u_mod(l)
+       v(l) = v_mod(l)
+       vg(l)= v_mod(l)
+! Advective forcings are given in K or g/kg ... per HOUR
+!      IF(height(l).LT.1000) THEN
+!        d_th_adv(l) = (adv_theta_prof + rad_theta_prof)/3600.
+!        d_q_adv(l,1) = adv_qt_prof/1000./3600.
+!        d_q_adv(l,2) = 0.0
+!      ELSEIF (height(l).GE.1000.AND.height(l).LT.3000) THEN
+!        d_th_adv(l) = (adv_theta_prof + rad_theta_prof)*
+!    :               (1-(height(l)-1000.)/2000.)
+!        d_th_adv(l) = d_th_adv(l)/3600.
+!        d_q_adv(l,1) = adv_qt_prof*(1-(height(l)-1000.)/2000.)
+!        d_q_adv(l,1) = d_q_adv(l,1)/1000./3600.
+!        d_q_adv(l,2) = 0.0
+!      ELSE
+!        d_th_adv(l) = 0.0
+!        d_q_adv(l,1) = 0.0
+!        d_q_adv(l,2) = 0.0
+!      ENDIF
+      enddo
+! plev at half levels is given in proh.inp.19 or proh.inp.40 files
+      plev(1)= ap(llm+1)+bp(llm+1)*psurf
+      do l = 1, llm
+      plev(l+1) = ap(llm-l+1)+bp(llm-l+1)*psurf
+      print *,'Read_forc: l height play plev zlay temp',
+     :   l,height(l),play(l),plev(l),zlay(l),temp(l)
+      enddo
+! For this case, fluxes are imposed
+       fsens=-1*sens_prof
+       flat=-1*flat_prof
+
+      endif ! forcing_armcu
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
Index: LMDZ5/branches/testing/libf/phy1d/1Dconv.h
===================================================================
--- LMDZ5/branches/testing/libf/phy1d/1Dconv.h	(revision 1665)
+++ LMDZ5/branches/testing/libf/phy1d/1Dconv.h	(revision 1665)
@@ -0,0 +1,880 @@
+        subroutine get_uvd(itap,dtime,file_forctl,file_fordat,
+     :       ht,hq,hw,hu,hv,hthturb,hqturb,
+     :       Ts,imp_fcg,ts_fcg,Tp_fcg,Turb_fcg)
+c
+        implicit none
+ 
+cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+c cette routine permet d obtenir u_convg,v_convg,ht,hq et ainsi de
+c pouvoir calculer la convergence et le cisaillement dans la physiq
+ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+
+#include "YOMCST.h"
+
+      INTEGER klev
+      REAL play(100)  !pression en Pa au milieu de chaque couche GCM
+      INTEGER JM(100) !pression en Pa au milieu de chaque couche GCM
+      REAL coef1(100) !coefficient d interpolation
+      REAL coef2(100) !coefficient d interpolation
+
+      INTEGER nblvlm !nombre de niveau de pression du mesoNH
+      REAL playm(100)  !pression en Pa au milieu de chaque couche Meso-NH
+      REAL hplaym(100) !pression en hPa milieux des couches Meso-NH
+
+      integer i,j,k,ii,ll,in
+      REAL tsol,qsol
+
+      CHARACTER*80 file_forctl,file_fordat
+
+      COMMON/com1_phys_gcss/klev,play,JM,coef1,coef2
+      COMMON/com2_phys_gcss/nblvlm,playm,hplaym
+
+c======================================================================
+c methode: on va chercher les donnees du mesoNH de meteo france, on y
+c          a acces a tout pas detemps grace a la routine rdgrads qui
+c          est une boucle lisant dans ces fichiers.
+c          Puis on interpole ces donnes sur les 11 niveaux du gcm et
+c          et sur les pas de temps de ce meme gcm
+c----------------------------------------------------------------------
+c input:
+c       pasmax     :nombre de pas de temps maximum du mesoNH
+c       dt         :pas de temps du meso_NH (en secondes)
+c----------------------------------------------------------------------
+      integer pasmax,dt
+      save pasmax,dt
+c----------------------------------------------------------------------
+c arguments:
+c           itap   :compteur de la physique(le nombre de ces pas est
+c                   fixe dans la subroutine calcul_ini_gcm de interpo
+c                   -lation
+c           dtime  :pas detemps du gcm (en secondes)
+c           ht     :convergence horizontale de temperature(K/s)
+c           hq     :    "         "       d humidite (kg/kg/s)
+c           hw     :vitesse verticale moyenne (m/s**2)
+c           hu     :convergence horizontale d impulsion le long de x
+c                  (kg/(m^2 s^2)
+c           hv     : idem le long de y.
+c           Ts     : Temperature de surface (K)
+c           imp_fcg: var. logical .eq. T si forcage en impulsion
+c           ts_fcg: var. logical .eq. T si forcage en Ts present dans fichier
+c           Tp_fcg: var. logical .eq. T si forcage donne en Temp potentielle
+c           Turb_fcg: var. logical .eq. T si forcage turbulent present dans fichier
+c----------------------------------------------------------------------
+        integer itap
+        real dtime
+        real ht(100)
+        real hq(100)
+        real hu(100)
+        real hv(100)
+        real hw(100)
+        real hthturb(100)
+        real hqturb(100)
+        real Ts, Ts_subr
+        logical imp_fcg
+        logical ts_fcg
+        logical Tp_fcg
+        logical Turb_fcg
+c----------------------------------------------------------------------
+c Variables internes de get_uvd (note : l interpolation temporelle
+c est faite entre les pas de temps before et after, sur les variables
+c definies sur la grille du SCM; on atteint exactement les valeurs Meso
+c aux milieux des pas de temps Meso)
+c     time0     :date initiale en secondes
+c     time      :temps associe a chaque pas du SCM
+c     pas       :numero du pas du meso_NH (on lit en pas : le premier pas
+c                 des donnees est duplique)
+c     pasprev   :numero du pas de lecture precedent
+c     htaft     :advection horizontale de temp. au pas de temps after
+c     hqaft     :    "         "      d humidite        "
+c     hwaft     :vitesse verticalle moyenne  au pas de temps after
+c     huaft,hvaft :advection horizontale d impulsion au pas de temps after
+c     tsaft     : surface temperature 'after time step'
+c     htbef     :idem htaft, mais pour le pas de temps before
+c     hqbef     :voir hqaft
+c     hwbef     :voir hwaft
+c     hubef,hvbef : idem huaft,hvaft, mais pour before
+c     tsbef     : surface temperature 'before time step'
+c----------------------------------------------------------------------
+        integer time0,pas,pasprev
+        save time0,pas,pasprev
+        real time
+        real htaft(100),hqaft(100),hwaft(100),huaft(100),hvaft(100)
+        real hthturbaft(100),hqturbaft(100)
+        real Tsaft
+        save htaft,hqaft,hwaft,huaft,hvaft,hthturbaft,hqturbaft
+        real htbef(100),hqbef(100),hwbef(100),hubef(100),hvbef(100)
+        real hthturbbef(100),hqturbbef(100)
+        real Tsbef
+        save htbef,hqbef,hwbef,hubef,hvbef,hthturbbef,hqturbbef
+c
+        real timeaft,timebef
+        save timeaft,timebef
+        integer temps
+        character*4 string
+c----------------------------------------------------------------------
+c variables arguments de la subroutine rdgrads
+c---------------------------------------------------------------------
+        integer icompt,icomp1 !compteurs de rdgrads
+        real z(100)         ! altitude (grille Meso)
+        real ht_mes(100)    !convergence horizontale de temperature
+                            !-(grille Meso)
+        real hq_mes(100)    !convergence horizontale d humidite
+                            !(grille Meso)
+        real hw_mes(100)    !vitesse verticale moyenne
+                            !(grille Meso)
+        real hu_mes(100),hv_mes(100)    !convergence horizontale d impulsion
+                                        !(grille Meso)
+        real hthturb_mes(100) !tendance horizontale de T_pot, due aux
+                              !flux turbulents
+        real hqturb_mes(100) !tendance horizontale d humidite, due aux
+                              !flux turbulents
+c
+c---------------------------------------------------------------------
+c variable argument de la subroutine copie
+c---------------------------------------------------------------------
+c SB        real pplay(100)    !pression en milieu de couche du gcm
+c SB                            !argument de la physique
+c---------------------------------------------------------------------
+c variables destinees a la lecture du pas de temps du fichier de donnees
+c---------------------------------------------------------------------
+       character*80 aaa,atemps,spaces,apasmax
+       integer nch,imn,ipa
+c---------------------------------------------------------------------
+c  procedures appelees
+        external rdgrads    !lire en iterant dans forcing.dat
+c---------------------------------------------------------------------
+               print*,'le pas itap est:',itap
+c*** on determine le pas du meso_NH correspondant au nouvel itap ***
+c*** pour aller chercher les champs dans rdgrads                 ***
+c
+        time=time0+itap*dtime
+cc        temps=int(time/dt+1)
+cc        pas=min(temps,pasmax)
+        temps = 1 + int((dt + 2*time)/(2*dt))
+        pas=min(temps,pasmax-1)
+             print*,'le pas Meso est:',pas
+c
+c
+c===================================================================
+c
+c*** on remplit les champs before avec les champs after du pas   ***
+c*** precedent en format gcm                                     ***
+        if(pas.gt.pasprev)then
+          do i=1,klev
+             htbef(i)=htaft(i)
+             hqbef(i)=hqaft(i)
+             hwbef(i)=hwaft(i)
+             hubef(i)=huaft(i)
+             hvbef(i)=hvaft(i)
+             hThTurbbef(i)=hThTurbaft(i)
+             hqTurbbef(i)=hqTurbaft(i)
+          enddo
+	       tsbef = tsaft
+          timebef=pasprev*dt
+          timeaft=timebef+dt
+          icomp1 = nblvlm*4
+          IF (ts_fcg) icomp1 = icomp1 + 1
+          IF (imp_fcg) icomp1 = icomp1 + nblvlm*2
+          IF (Turb_fcg) icomp1 = icomp1 + nblvlm*2
+          icompt = icomp1*pas
+         print *, 'imp_fcg,ts_fcg,Turb_fcg,pas,nblvlm,icompt'
+         print *, imp_fcg,ts_fcg,Turb_fcg,pas,nblvlm,icompt
+                       print*,'le pas pas est:',pas
+c*** on va chercher les nouveaux champs after dans toga.dat     ***
+c*** champs en format meso_NH                                   ***
+          open(99,FILE=file_fordat,FORM='UNFORMATTED',
+     .             ACCESS='DIRECT',RECL=8)
+          call rdgrads(99,icompt,nblvlm,z,ht_mes,hq_mes,hw_mes
+     .                  ,hu_mes,hv_mes,hthturb_mes,hqturb_mes
+     .                  ,ts_fcg,ts_subr,imp_fcg,Turb_fcg)
+c
+
+               if(Tp_fcg) then
+c     (le forcage est donne en temperature potentielle)
+         do i = 1,nblvlm
+           ht_mes(i) = ht_mes(i)*(hplaym(i)/1000.)**rkappa
+         enddo
+               endif ! Tp_fcg
+        if(Turb_fcg) then
+         do i = 1,nblvlm
+           hThTurb_mes(i) = hThTurb_mes(i)*(hplaym(i)/1000.)**rkappa
+         enddo
+        endif  ! Turb_fcg
+c
+               print*,'ht_mes ',(ht_mes(i),i=1,nblvlm)
+               print*,'hq_mes ',(hq_mes(i),i=1,nblvlm)
+               print*,'hw_mes ',(hw_mes(i),i=1,nblvlm)
+                  if(imp_fcg) then
+               print*,'hu_mes ',(hu_mes(i),i=1,nblvlm)
+               print*,'hv_mes ',(hv_mes(i),i=1,nblvlm)
+                  endif
+                  if(Turb_fcg) then
+               print*,'hThTurb_mes ',(hThTurb_mes(i),i=1,nblvlm)
+               print*,'hqTurb_mes ',(hqTurb_mes(i),i=1,nblvlm)
+                  endif
+	       IF (ts_fcg) print*,'ts_subr', ts_subr
+c*** on interpole les champs meso_NH sur les niveaux de pression***
+c*** gcm . on obtient le nouveau champ after                    ***
+            do k=1,klev
+             if (JM(k) .eq. 0) then
+         htaft(k)=              ht_mes(jm(k)+1)
+         hqaft(k)=              hq_mes(jm(k)+1)
+         hwaft(k)=              hw_mes(jm(k)+1)
+               if(imp_fcg) then
+           huaft(k)=              hu_mes(jm(k)+1)
+           hvaft(k)=              hv_mes(jm(k)+1)
+               endif ! imp_fcg
+               if(Turb_fcg) then
+           hThTurbaft(k)=         hThTurb_mes(jm(k)+1)
+           hqTurbaft(k)=          hqTurb_mes(jm(k)+1)
+               endif ! Turb_fcg
+             else ! JM(k) .eq. 0
+           htaft(k)=coef1(k)*ht_mes(jm(k))+coef2(k)*ht_mes(jm(k)+1)
+           hqaft(k)=coef1(k)*hq_mes(jm(k))+coef2(k)*hq_mes(jm(k)+1)
+           hwaft(k)=coef1(k)*hw_mes(jm(k))+coef2(k)*hw_mes(jm(k)+1)
+               if(imp_fcg) then
+           huaft(k)=coef1(k)*hu_mes(jm(k))+coef2(k)*hu_mes(jm(k)+1)
+           hvaft(k)=coef1(k)*hv_mes(jm(k))+coef2(k)*hv_mes(jm(k)+1)
+               endif ! imp_fcg
+               if(Turb_fcg) then
+           hThTurbaft(k)=coef1(k)*hThTurb_mes(jm(k))
+     $               +coef2(k)*hThTurb_mes(jm(k)+1)
+           hqTurbaft(k) =coef1(k)*hqTurb_mes(jm(k))
+     $               +coef2(k)*hqTurb_mes(jm(k)+1)
+               endif ! Turb_fcg
+             endif ! JM(k) .eq. 0
+            enddo
+            tsaft = ts_subr
+            pasprev=pas
+         else ! pas.gt.pasprev
+            print*,'timebef est:',timebef
+         endif ! pas.gt.pasprev    fin du bloc relatif au passage au pas
+                                  !de temps (meso) suivant
+c*** si on atteint le pas max des donnees experimentales ,on     ***
+c*** on conserve les derniers champs calcules                    ***
+      if(temps.ge.pasmax)then
+          do ll=1,klev
+               ht(ll)=htaft(ll)
+               hq(ll)=hqaft(ll)
+               hw(ll)=hwaft(ll)
+               hu(ll)=huaft(ll)
+               hv(ll)=hvaft(ll)
+               hThTurb(ll)=hThTurbaft(ll)
+               hqTurb(ll)=hqTurbaft(ll)
+          enddo
+	       ts_subr = tsaft
+      else ! temps.ge.pasmax
+c*** on interpole sur les pas de temps de 10mn du gcm a partir   ***
+c** des pas de temps de 1h du meso_NH                            ***
+         do j=1,klev
+         ht(j)=((timeaft-time)*htbef(j)+(time-timebef)*htaft(j))/dt
+         hq(j)=((timeaft-time)*hqbef(j)+(time-timebef)*hqaft(j))/dt
+         hw(j)=((timeaft-time)*hwbef(j)+(time-timebef)*hwaft(j))/dt
+             if(imp_fcg) then
+         hu(j)=((timeaft-time)*hubef(j)+(time-timebef)*huaft(j))/dt
+         hv(j)=((timeaft-time)*hvbef(j)+(time-timebef)*hvaft(j))/dt
+             endif ! imp_fcg
+             if(Turb_fcg) then
+         hThTurb(j)=((timeaft-time)*hThTurbbef(j)
+     $           +(time-timebef)*hThTurbaft(j))/dt
+         hqTurb(j)= ((timeaft-time)*hqTurbbef(j)
+     $           +(time-timebef)*hqTurbaft(j))/dt
+             endif ! Turb_fcg
+         enddo
+	      ts_subr = ((timeaft-time)*tsbef + (time-timebef)*tsaft)/dt
+       endif ! temps.ge.pasmax
+c
+        print *,' time,timebef,timeaft',time,timebef,timeaft
+        print *,' ht,htbef,htaft,hthturb,hthturbbef,hthturbaft'
+        do j= 1,klev
+           print *, j,ht(j),htbef(j),htaft(j),
+     $             hthturb(j),hthturbbef(j),hthturbaft(j)
+        enddo
+        print *,' hq,hqbef,hqaft,hqturb,hqturbbef,hqturbaft'
+        do j= 1,klev
+           print *, j,hq(j),hqbef(j),hqaft(j),
+     $             hqturb(j),hqturbbef(j),hqturbaft(j)
+        enddo
+c
+c-------------------------------------------------------------------
+c
+         IF (Ts_fcg) Ts = Ts_subr
+         return
+c
+c-----------------------------------------------------------------------
+c on sort les champs de "convergence" pour l instant initial 'in'
+c ceci se passe au pas temps itap=0 de la physique
+c-----------------------------------------------------------------------
+        entry get_uvd2(itap,dtime,file_forctl,file_fordat,
+     .           ht,hq,hw,hu,hv,hThTurb,hqTurb,ts,
+     .           imp_fcg,ts_fcg,Tp_fcg,Turb_fcg)
+             print*,'le pas itap est:',itap
+c
+c===================================================================
+c
+       write(*,'(a)') 'OPEN '//file_forctl
+       open(97,FILE=file_forctl,FORM='FORMATTED')
+c
+c------------------
+      do i=1,1000
+      read(97,1000,end=999) string
+ 1000 format (a4)
+      if (string .eq. 'TDEF') go to 50
+      enddo
+ 50   backspace(97)
+c-------------------------------------------------------------------
+c   *** on lit le pas de temps dans le fichier de donnees ***
+c   *** "forcing.ctl" et pasmax                           ***
+c-------------------------------------------------------------------
+      read(97,2000) aaa
+ 2000  format (a80)
+         print*,'aaa est',aaa
+      aaa=spaces(aaa,1)
+         print*,'aaa',aaa
+      call getsch(aaa,' ',' ',5,atemps,nch)
+         print*,'atemps est',atemps
+        atemps=atemps(1:nch-2)
+         print*,'atemps',atemps
+        read(atemps,*) imn
+        dt=imn*60
+         print*,'le pas de temps dt',dt
+      call getsch(aaa,' ',' ',2,apasmax,nch)
+        apasmax=apasmax(1:nch)
+        read(apasmax,*) ipa
+        pasmax=ipa
+         print*,'pasmax est',pasmax
+      CLOSE(97)
+c------------------------------------------------------------------
+c *** on lit le pas de temps initial de la simulation ***
+c------------------------------------------------------------------
+                  in=itap
+cc                  pasprev=in
+cc                  time0=dt*(pasprev-1)
+                  pasprev=in-1
+                  time0=dt*pasprev
+C
+          close(98)
+c
+      write(*,'(a)') 'OPEN '//file_fordat
+      open(99,FILE=file_fordat,FORM='UNFORMATTED',
+     .          ACCESS='DIRECT',RECL=8)
+          icomp1 = nblvlm*4
+          IF (ts_fcg) icomp1 = icomp1 + 1
+          IF (imp_fcg) icomp1 = icomp1 + nblvlm*2
+          IF (Turb_fcg) icomp1 = icomp1 + nblvlm*2
+          icompt = icomp1*(in-1)
+          call rdgrads(99,icompt,nblvlm,z,ht_mes,hq_mes,hw_mes
+     .                   ,hu_mes,hv_mes,hthturb_mes,hqturb_mes
+     .                   ,ts_fcg,ts_subr,imp_fcg,Turb_fcg)
+          print *, 'get_uvd : rdgrads ->'
+          print *, tp_fcg
+c
+c following commented out because we have temperature already in ARM case
+c   (otherwise this is the potential temperature )
+c------------------------------------------------------------------------
+               if(Tp_fcg) then
+          do i = 1,nblvlm
+            ht_mes(i) = ht_mes(i)*(hplaym(i)/1000.)**rkappa
+          enddo
+               endif ! Tp_fcg
+           print*,'ht_mes ',(ht_mes(i),i=1,nblvlm)
+           print*,'hq_mes ',(hq_mes(i),i=1,nblvlm)
+           print*,'hw_mes ',(hw_mes(i),i=1,nblvlm)
+              if(imp_fcg) then
+           print*,'hu_mes ',(hu_mes(i),i=1,nblvlm)
+           print*,'hv_mes ',(hv_mes(i),i=1,nblvlm)
+           print*,'t',ts_subr
+              endif ! imp_fcg
+              if(Turb_fcg) then
+                 print*,'hThTurb_mes ',(hThTurb_mes(i),i=1,nblvlm)
+                 print*,'hqTurb ',     (hqTurb_mes(i),i=1,nblvlm)
+              endif ! Turb_fcg
+c----------------------------------------------------------------------
+c on a obtenu des champs initiaux sur les niveaux du meso_NH
+c on interpole sur les niveaux du gcm(niveau pression bien sur!)
+c-----------------------------------------------------------------------
+            do k=1,klev
+             if (JM(k) .eq. 0) then
+cFKC bug? ne faut il pas convertir tsol en tendance ????
+cRT bug taken care of by removing the stuff
+           htaft(k)=              ht_mes(jm(k)+1)
+           hqaft(k)=              hq_mes(jm(k)+1)
+           hwaft(k)=              hw_mes(jm(k)+1)
+               if(imp_fcg) then
+           huaft(k)=              hu_mes(jm(k)+1)
+           hvaft(k)=              hv_mes(jm(k)+1)
+               endif ! imp_fcg
+               if(Turb_fcg) then
+           hThTurbaft(k)=         hThTurb_mes(jm(k)+1)
+           hqTurbaft(k)=          hqTurb_mes(jm(k)+1)
+               endif ! Turb_fcg
+             else ! JM(k) .eq. 0
+           htaft(k)=coef1(k)*ht_mes(jm(k))+coef2(k)*ht_mes(jm(k)+1)
+           hqaft(k)=coef1(k)*hq_mes(jm(k))+coef2(k)*hq_mes(jm(k)+1)
+           hwaft(k)=coef1(k)*hw_mes(jm(k))+coef2(k)*hw_mes(jm(k)+1)
+               if(imp_fcg) then
+           huaft(k)=coef1(k)*hu_mes(jm(k))+coef2(k)*hu_mes(jm(k)+1)
+           hvaft(k)=coef1(k)*hv_mes(jm(k))+coef2(k)*hv_mes(jm(k)+1)
+               endif ! imp_fcg
+               if(Turb_fcg) then
+           hThTurbaft(k)=coef1(k)*hThTurb_mes(jm(k))
+     $                  +coef2(k)*hThTurb_mes(jm(k)+1)
+           hqTurbaft(k) =coef1(k)*hqTurb_mes(jm(k))
+     $                  +coef2(k)*hqTurb_mes(jm(k)+1)
+               endif ! Turb_fcg
+             endif ! JM(k) .eq. 0
+            enddo
+            tsaft = ts_subr
+c valeurs initiales des champs de convergence
+          do k=1,klev
+             ht(k)=htaft(k)
+             hq(k)=hqaft(k)
+             hw(k)=hwaft(k)
+                if(imp_fcg) then
+             hu(k)=huaft(k)
+             hv(k)=hvaft(k)
+                endif ! imp_fcg
+                if(Turb_fcg) then
+             hThTurb(k)=hThTurbaft(k)
+             hqTurb(k) =hqTurbaft(k)
+                endif ! Turb_fcg
+          enddo
+	       ts_subr = tsaft
+          close(99)
+          close(98)
+c
+c-------------------------------------------------------------------
+c
+c
+ 100      IF (Ts_fcg) Ts = Ts_subr
+        return
+c
+999     continue
+        stop 'erreur lecture, file forcing.ctl'
+        end
+
+      SUBROUTINE advect_tvl(dtime,zt,zq,vu_f,vv_f,t_f,q_f
+     :                     ,d_t_adv,d_q_adv)
+      use dimphy
+      implicit none
+
+#include "dimensions.h"
+ccccc#include "dimphy.h"
+
+      integer k
+      real dtime, fact, du, dv, cx, cy, alx, aly
+      real zt(klev), zq(klev,3)
+     :   , vu_f(klev), vv_f(klev), t_f(klev), q_f(klev,3)
+
+      real d_t_adv(klev), d_q_adv(klev,3)
+
+c Velocity of moving cell
+      data cx,cy /12., -2./
+
+c Dimensions of moving cell
+      data alx,aly /100 000.,150 000./
+
+      do k = 1, klev
+            du = abs(vu_f(k)-cx)/alx
+            dv = abs(vv_f(k)-cy)/aly
+            fact = dtime *(du+dv-du*dv*dtime)
+            d_t_adv(k) = fact * (t_f(k)-zt(k))
+            d_q_adv(k,1) = fact * (q_f(k,1)-zq(k,1))
+            d_q_adv(k,2) = fact * (q_f(k,2)-zq(k,2))
+            d_q_adv(k,3) = fact * (q_f(k,3)-zq(k,3))
+      enddo
+
+      return
+      end
+
+      SUBROUTINE copie(klevgcm,playgcm,psolgcm,file_forctl)
+      implicit none
+
+ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+c cette routine remplit les COMMON com1_phys_gcss et com2_phys_gcss.h
+cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+
+      INTEGER klev !nombre de niveau de pression du GCM
+      REAL play(100)  !pression en Pa au milieu de chaque couche GCM
+      INTEGER JM(100)
+      REAL coef1(100)   !coefficient d interpolation
+      REAL coef2(100)   !coefficient d interpolation
+
+      INTEGER nblvlm !nombre de niveau de pression du mesoNH
+      REAL playm(100) !pression en Pa au milieu de chaque couche Meso-NH
+      REAL hplaym(100)!pression en hecto-Pa des milieux de couche Meso-NH
+
+      COMMON/com1_phys_gcss/klev,play,JM,coef1,coef2
+      COMMON/com2_phys_gcss/nblvlm,playm,hplaym
+
+      integer i,k,klevgcm
+      real playgcm(klevgcm) ! pression en milieu de couche du gcm
+      real psolgcm
+      character*80 file_forctl
+
+      klev = klevgcm
+
+c---------------------------------------------------------------------
+c pression au milieu des couches du gcm dans la physiq
+c (SB: remplace le call conv_lipress_gcm(playgcm) )
+c---------------------------------------------------------------------
+
+       do k = 1, klev
+        play(k) = playgcm(k)
+        print*,'la pression gcm est:',play(k)
+       enddo
+
+c----------------------------------------------------------------------
+c lecture du descripteur des donnees Meso-NH (forcing.ctl):
+c  -> nb niveaux du meso.NH (nblvlm) + pressions meso.NH
+c (on remplit le COMMON com2_phys_gcss)
+c----------------------------------------------------------------------
+
+      call mesolupbis(file_forctl)
+
+      print*,'la valeur de nblvlm est:',nblvlm
+
+c----------------------------------------------------------------------
+c etude de la correspondance entre les niveaux meso.NH et GCM;
+c calcul des coefficients d interpolation coef1 et coef2
+c (on remplit le COMMON com1_phys_gcss)
+c----------------------------------------------------------------------
+
+      call corresbis(psolgcm)
+
+c---------------------------------------------------------
+c TEST sur le remplissage de com1_phys_gcss et com2_phys_gcss:
+c---------------------------------------------------------
+ 
+      write(*,*) ' '
+      write(*,*) 'TESTS com1_phys_gcss et com2_phys_gcss dans copie.F'
+      write(*,*) '--------------------------------------'
+      write(*,*) 'GCM: nb niveaux:',klev,' et pression, coeffs:'
+      do k = 1, klev
+      write(*,*) play(k), coef1(k), coef2(k)
+      enddo
+      write(*,*) 'MESO-NH: nb niveaux:',nblvlm,' et pression:'
+      do k = 1, nblvlm
+      write(*,*) playm(k), hplaym(k)
+      enddo
+      write(*,*) ' '
+
+      end
+      SUBROUTINE mesolupbis(file_forctl)
+      implicit none 
+c
+cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+c
+c Lecture descripteur des donnees MESO-NH (forcing.ctl):
+c -------------------------------------------------------
+c
+c     Cette subroutine lit dans le fichier de controle "essai.ctl"
+c     et affiche le nombre de niveaux du Meso-NH ainsi que les valeurs
+c     des pressions en milieu de couche du Meso-NH (en Pa puis en hPa).
+cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+c
+      INTEGER nblvlm !nombre de niveau de pression du mesoNH
+      REAL playm(100)  !pression en Pa milieu de chaque couche Meso-NH
+      REAL hplaym(100) !pression en hPa des milieux de couche Meso-NH
+      COMMON/com2_phys_gcss/nblvlm,playm,hplaym
+
+      INTEGER i,lu,k,mlz,mlzh,j
+ 
+      character*80 file_forctl
+
+      character*4 a
+      character*80 aaa,anblvl,spaces
+      integer nch
+
+      lu=9
+      open(lu,file=file_forctl,form='formatted')
+c
+      do i=1,1000
+      read(lu,1000,end=999) a
+      if (a .eq. 'ZDEF') go to 100
+      enddo
+c
+ 100  backspace(lu)
+      print*,'  DESCRIPTION DES 2 MODELES : '
+      print*,' '
+c
+      read(lu,2000) aaa
+ 2000  format (a80)
+       aaa=spaces(aaa,1)
+       call getsch(aaa,' ',' ',2,anblvl,nch)
+         read(anblvl,*) nblvlm
+
+c
+      print*,'nbre de niveaux de pression Meso-NH :',nblvlm
+      print*,' '
+      print*,'pression en Pa de chaque couche du meso-NH :'
+c
+      read(lu,*) (playm(mlz),mlz=1,nblvlm)
+c      Si la pression est en HPa, la multiplier par 100
+      if (playm(1) .lt. 10000.) then
+        do mlz = 1,nblvlm
+         playm(mlz) = playm(mlz)*100.
+        enddo
+      endif
+      print*,(playm(mlz),mlz=1,nblvlm)
+c
+ 1000 format (a4)
+ 1001 format(5x,i2)
+c
+      print*,' '
+      do mlzh=1,nblvlm
+      hplaym(mlzh)=playm(mlzh)/100.
+      enddo
+c
+      print*,'pression en hPa de chaque couche du meso-NH: '
+      print*,(hplaym(mlzh),mlzh=1,nblvlm)
+c
+      close (lu)
+      return
+c
+ 999  stop 'erreur lecture des niveaux pression des donnees'
+      end
+
+      SUBROUTINE rdgrads(itape,icount,nl,z,ht,hq,hw,hu,hv,hthtur,hqtur,
+     :  ts_fcg,ts,imp_fcg,Turb_fcg)
+      IMPLICIT none
+      INTEGER itape,icount,icomp, nl
+      real z(nl),ht(nl),hq(nl),hw(nl),hu(nl),hv(nl)
+      real hthtur(nl),hqtur(nl)
+      real ts
+c
+      INTEGER i, k
+c
+      LOGICAL imp_fcg,ts_fcg,Turb_fcg
+c
+      icomp = icount
+c
+c
+         do k=1,nl
+            icomp=icomp+1
+            read(itape,rec=icomp)z(k)
+            print *,'icomp,k,z(k) ',icomp,k,z(k)
+         enddo
+         do k=1,nl
+            icomp=icomp+1
+            read(itape,rec=icomp)hT(k)
+             print*, hT(k), k
+         enddo
+         do k=1,nl
+            icomp=icomp+1
+            read(itape,rec=icomp)hQ(k)
+         enddo
+c
+             if(turb_fcg) then
+         do k=1,nl
+            icomp=icomp+1
+           read(itape,rec=icomp)hThTur(k)
+         enddo
+         do k=1,nl
+            icomp=icomp+1
+           read(itape,rec=icomp)hqTur(k)
+         enddo
+             endif
+         print *,' apres lecture hthtur, hqtur'
+c
+          if(imp_fcg) then
+
+         do k=1,nl
+            icomp=icomp+1
+           read(itape,rec=icomp)hu(k)
+         enddo
+         do k=1,nl
+            icomp=icomp+1
+            read(itape,rec=icomp)hv(k)
+         enddo
+
+          endif
+c
+         do k=1,nl
+            icomp=icomp+1
+            read(itape,rec=icomp)hw(k)
+         enddo
+c
+              if(ts_fcg) then
+         icomp=icomp+1
+         read(itape,rec=icomp)ts
+              endif
+c
+      print *,' rdgrads ->'
+
+      RETURN
+      END
+
+      SUBROUTINE corresbis(psol)
+      implicit none
+
+ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+c Cette subroutine calcule et affiche les valeurs des coefficients
+c d interpolation qui serviront dans la formule d interpolation elle-
+c meme.
+cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+
+      INTEGER klev    !nombre de niveau de pression du GCM
+      REAL play(100)  !pression en Pa au milieu de chaque couche GCM
+      INTEGER JM(100)
+      REAL coef1(100) !coefficient d interpolation
+      REAL coef2(100) !coefficient d interpolation
+
+      INTEGER nblvlm !nombre de niveau de pression du mesoNH
+      REAL playm(100) !pression en Pa milieu de chaque couche Meso-NH
+      REAL hplaym(100)!pression en hPa des milieux de couche Meso-NH
+
+      COMMON/com1_phys_gcss/klev,play,JM,coef1,coef2
+      COMMON/com2_phys_gcss/nblvlm,playm,hplaym
+
+      REAL psol
+      REAL val
+      INTEGER k, mlz, mlzh
+
+
+      do k=1,klev
+         val=play(k)
+       if (val .gt. playm(1)) then
+          mlz = 0
+          JM(1) = mlz
+          coef1(1)=(playm(mlz+1)-val)
+     *             /(playm(mlz+1)-psol)
+          coef2(1)=(val-psol)
+     *             /(playm(mlz+1)-psol)
+       else if (val .gt. playm(nblvlm)) then
+         do mlz=1,nblvlm
+          if (     val .le. playm(mlz)
+     *       .and. val .gt. playm(mlz+1))then
+           JM(k)=mlz
+           coef1(k)=(playm(mlz+1)-val)
+     *              /(playm(mlz+1)-playm(mlz))
+           coef2(k)=(val-playm(mlz))
+     *              /(playm(mlz+1)-playm(mlz))
+          endif
+         enddo
+       else
+         JM(k) = nblvlm-1
+         coef1(k) = 0.
+         coef2(k) = 0.
+       endif
+      enddo
+c
+cc      if (play(klev) .le. playm(nblvlm)) then
+cc         mlz=nblvlm-1
+cc         JM(klev)=mlz
+cc         coef1(klev)=(playm(mlz+1)-val)
+cc     *            /(playm(mlz+1)-playm(mlz))
+cc         coef2(klev)=(val-playm(mlz))
+cc     *            /(playm(mlz+1)-playm(mlz))
+cc      endif
+c
+      print*,' '
+      print*,'         INTERPOLATION  : '
+      print*,' '
+      print*,'correspondance de 9 niveaux du GCM sur les 53 du meso-NH:'
+      print*,(JM(k),k=1,klev)
+      print*,'correspondance de 9 niveaux du GCM sur les 53 du meso-NH:'
+      print*,(JM(k),k=1,klev)
+      print*,' '
+      print*,'valeurs du premier coef d"interpolation pour les 9 niveaux
+     *: '
+      print*,(coef1(k),k=1,klev)
+      print*,' '
+      print*,'valeurs du deuxieme coef d"interpolation pour les 9 niveau
+     *x: '
+      print*,(coef2(k),k=1,klev)
+c
+      return
+      end
+      SUBROUTINE GETSCH(STR,DEL,TRM,NTH,SST,NCH)
+C***************************************************************
+C*                                                             *
+C*                                                             *
+C* GETSCH                                                      *
+C*                                                             *
+C*                                                             *
+C* modified by :                                               *
+C***************************************************************
+C*   Return in SST the character string found between the NTH-1 and NTH
+C*   occurence of the delimiter 'DEL' but before the terminator 'TRM' in
+C*   the input string 'STR'. If TRM=DEL then STR is considered unlimited.
+C*   NCH=Length of the string returned in SST or =-1 if NTH is <1 or if
+C*   NTH is greater than the number of delimiters in STR.
+      IMPLICIT INTEGER (A-Z)
+      CHARACTER STR*(*),DEL*1,TRM*1,SST*(*)
+      NCH=-1
+      SST=' '
+      IF(NTH.GT.0) THEN
+        IF(TRM.EQ.DEL) THEN
+          LENGTH=LEN(STR)
+        ELSE
+          LENGTH=INDEX(STR,TRM)-1
+          IF(LENGTH.LT.0) LENGTH=LEN(STR)
+        ENDIF
+C*     Find beginning and end of the NTH DEL-limited substring in STR
+        END=-1
+        DO 1,N=1,NTH
+        IF(END.EQ.LENGTH) RETURN
+        BEG=END+2
+        END=BEG+INDEX(STR(BEG:LENGTH),DEL)-2
+        IF(END.EQ.BEG-2) END=LENGTH
+C*        PRINT *,'NTH,LENGTH,N,BEG,END=',NTH,LENGTH,N,BEG,END
+    1   CONTINUE
+        NCH=END-BEG+1
+        IF(NCH.GT.0) SST=STR(BEG:END)
+      ENDIF
+      END
+      CHARACTER*(*) FUNCTION SPACES(STR,NSPACE)
+C
+C CERN PROGLIB# M433    SPACES          .VERSION KERNFOR  4.14  860211
+C ORIG.  6/05/86 M.GOOSSENS/DD
+C
+C-    The function value SPACES returns the character string STR with
+C-    leading blanks removed and each occurence of one or more blanks
+C-    replaced by NSPACE blanks inside the string STR
+C
+      CHARACTER*(*) STR
+C
+      LENSPA = LEN(SPACES)
+      SPACES = ' '
+      IF (NSPACE.LT.0) NSPACE = 0
+      IBLANK = 1
+      ISPACE = 1
+  100 INONBL = INDEXC(STR(IBLANK:),' ')
+      IF (INONBL.EQ.0) THEN
+          SPACES(ISPACE:) = STR(IBLANK:)
+                                                    GO TO 999
+      ENDIF
+      INONBL = INONBL + IBLANK - 1
+      IBLANK = INDEX(STR(INONBL:),' ')
+      IF (IBLANK.EQ.0) THEN
+          SPACES(ISPACE:) = STR(INONBL:)
+                                                    GO TO 999
+      ENDIF
+      IBLANK = IBLANK + INONBL - 1
+      SPACES(ISPACE:) = STR(INONBL:IBLANK-1)
+      ISPACE = ISPACE + IBLANK - INONBL + NSPACE
+      IF (ISPACE.LE.LENSPA)                         GO TO 100
+  999 END
+      FUNCTION INDEXC(STR,SSTR)
+C
+C CERN PROGLIB# M433    INDEXC          .VERSION KERNFOR  4.14  860211
+C ORIG. 26/03/86 M.GOOSSENS/DD
+C
+C-    Find the leftmost position where substring SSTR does not match
+C-    string STR scanning forward
+C
+      CHARACTER*(*) STR,SSTR
+C
+      LENS   = LEN(STR)
+      LENSS  = LEN(SSTR)
+C
+      DO 10 I=1,LENS-LENSS+1
+          IF (STR(I:I+LENSS-1).NE.SSTR) THEN
+              INDEXC = I
+                                         GO TO 999
+          ENDIF
+   10 CONTINUE
+      INDEXC = 0
+C
+  999 END
Index: LMDZ5/branches/testing/libf/phy1d/add_pbl_tend.F
===================================================================
--- LMDZ5/branches/testing/libf/phy1d/add_pbl_tend.F	(revision 1665)
+++ LMDZ5/branches/testing/libf/phy1d/add_pbl_tend.F	(revision 1665)
@@ -0,0 +1,51 @@
+      SUBROUTINE add_pbl_tend (zdu,zdv,zdt,zdq,zdql,text)
+!======================================================================
+! Ajoute les tendances de couche limite, soit determinees par la parametrisation
+! physique, soit forcees,  aux variables d etat de la dynamique t_seri, q_seri ...
+!======================================================================
+
+
+!======================================================================
+! Declarations
+!======================================================================
+
+      use dimphy
+      use phys_local_var_mod
+      use phys_state_var_mod
+      IMPLICIT none
+#include "dimensions.h"
+        real  hthturb_gcssold(llm)
+        real  hqturb_gcssold(llm)
+        real dtime_frcg
+        logical  Turb_fcg_gcssold
+        common /turb_forcing/ dtime_frcg,
+     $           Turb_fcg_gcssold, hthturb_gcssold, hqturb_gcssold
+! Arguments :
+!------------
+      REAL zdu(klon,klev),zdv(klon,klev)
+      REAL zdt(klon,klev),zdq(klon,klev),zdql(klon,klev)
+      CHARACTER*(*) text
+
+! Local :
+!--------
+      REAL zzdt(klon,klev),zzdq(klon,klev)
+      INTEGER i,k
+!
+      IF (Turb_fcg_gcssold) THEN
+       DO k = 1,klev
+        DO i = 1,klon
+         zzdt(i,k) = hthturb_gcssold(k)*dtime_frcg
+         zzdq(i,k) = hqturb_gcssold(k)*dtime_frcg
+        ENDDO
+       ENDDO
+       print *,' add_pbl_tend, dtime_frcg ', dtime_frcg
+       print *,' add_pbl_tend, zzdt ', zzdt
+       print *,' add_pbl_tend, zzdq ', zzdq
+       CALL add_phys_tend (zdu,zdv,zzdt,zzdq,zdql,text)
+      ELSE
+       CALL add_phys_tend (zdu,zdv, zdt, zdq,zdql,text)
+      ENDIF
+!
+
+      RETURN
+      END
Index: LMDZ5/branches/testing/libf/phy1d/compar1d.h
===================================================================
--- LMDZ5/branches/testing/libf/phy1d/compar1d.h	(revision 1665)
+++ LMDZ5/branches/testing/libf/phy1d/compar1d.h	(revision 1665)
@@ -0,0 +1,43 @@
+!
+! $Id: compar1d.h 2010-08-04 17:02:56Z lahellec $
+!
+      integer :: forcing_type
+      real :: nat_surf
+      real :: tsurf
+      real :: rugos
+      real :: qsol(1:2)
+      real :: qsurf
+      real :: psurf
+      real :: zsurf
+      real :: albedo
+
+      real :: time
+      real :: time_ini
+      real :: xlat 
+      real :: xlon 
+      real :: airefi
+      real :: wtsurf 
+      real :: wqsurf 
+      real :: restart_runoff 
+      real :: xagesno 
+      real :: qsolinp 
+      real :: zpicinp 
+
+      logical :: restart
+
+      common/com_par1d/forcing_type,nat_surf,tsurf,rugos,               &
+     & qsol,qsurf,psurf,zsurf,albedo,time,time_ini,xlat,xlon,airefi,    &
+     & wtsurf,wqsurf,restart_runoff,xagesno,qsolinp,zpicinp,            &
+     & restart
+
+!$OMP THREADPRIVATE(/com_par1d/)
+
+
+
+
+
+
+
+
+
+
Index: LMDZ5/branches/testing/libf/phy1d/fcg_gcssold.h
===================================================================
--- LMDZ5/branches/testing/libf/phy1d/fcg_gcssold.h	(revision 1665)
+++ LMDZ5/branches/testing/libf/phy1d/fcg_gcssold.h	(revision 1665)
@@ -0,0 +1,46 @@
+!
+! $Id: fcg_gcssold.h 2010-08-10 17:02:56Z lahellec $
+!
+      logical :: imp_fcg_gcssold,ts_fcg_gcssold,Tp_fcg_gcssold,
+     $ Tp_ini_gcssold,
+     $ xTurb_fcg_gcssold
+
+      common /fcg_gcssold/imp_fcg_gcssold,ts_fcg_gcssold,Tp_fcg_gcssold,
+     $ Tp_ini_gcssold,
+     $ xTurb_fcg_gcssold
+
+!$OMP THREADPRIVATE(/fcg_gcssold/)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: LMDZ5/branches/testing/libf/phy1d/fcg_racmo.h
===================================================================
--- LMDZ5/branches/testing/libf/phy1d/fcg_racmo.h	(revision 1665)
+++ LMDZ5/branches/testing/libf/phy1d/fcg_racmo.h	(revision 1665)
@@ -0,0 +1,45 @@
+!
+! $Id: fcg_racmo.h 2011-02-16 17:02:56Z cheruy $
+!
+      real   :: a_guide 
+      logical :: ok_invertp 
+      integer :: forc_trb
+      character*31 :: fich_racmo
+
+      common /fcg_racmo/forc_trb,ok_invertp,a_guide,fich_racmo
+
+!$OMP THREADPRIVATE(/fcg_racmo/)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: LMDZ5/branches/testing/libf/phy1d/flux_arp.h
===================================================================
--- LMDZ5/branches/testing/libf/phy1d/flux_arp.h	(revision 1665)
+++ LMDZ5/branches/testing/libf/phy1d/flux_arp.h	(revision 1665)
@@ -0,0 +1,14 @@
+!
+! $Id: flux_arp.h 2010-08-04 17:02:56Z lahellec $
+!
+      logical :: ok_flux_surf
+      real :: fsens
+      real :: flat
+
+      common /flux_arp/fsens,flat,ok_flux_surf
+
+!$OMP THREADPRIVATE(/flux_arp/)
+
+
+
+
Index: LMDZ5/branches/testing/libf/phy1d/lmdz1d.F
===================================================================
--- LMDZ5/branches/testing/libf/phy1d/lmdz1d.F	(revision 1665)
+++ LMDZ5/branches/testing/libf/phy1d/lmdz1d.F	(revision 1665)
@@ -0,0 +1,811 @@
+      PROGRAM lmdz1d
+
+      USE ioipsl, only: ju2ymds, ymds2ju, ioconf_calendar
+      use phys_state_var_mod
+      use comgeomphy
+      use dimphy
+      use surface_data, only : type_ocean,ok_veget
+      use pbl_surface_mod, only : pbl_surface_init, pbl_surface_final
+      use fonte_neige_mod, only : fonte_neige_init, fonte_neige_final 
+
+      use infotrac ! new
+      use control_mod
+
+      implicit none
+#include "dimensions.h"
+#include "YOMCST.h"
+#include "temps.h"
+!!#include "control.h"
+#include "iniprint.h"
+#include "clesphys.h"
+#include "dimsoil.h"
+#include "indicesol.h"
+
+#include "comvert.h"
+#include "compar1d.h"
+#include "flux_arp.h"
+#include "fcg_gcssold.h"
+!!!#include "fbforcing.h"
+
+!=====================================================================
+! DECLARATIONS
+!=====================================================================
+
+!---------------------------------------------------------------------
+!  Externals
+!---------------------------------------------------------------------
+      external fq_sat
+      real fq_sat
+
+!---------------------------------------------------------------------
+!  Arguments d' initialisations de la physique (USER DEFINE)
+!---------------------------------------------------------------------
+
+      integer, parameter :: ngrid=1
+      real :: zcufi    = 1.
+      real :: zcvfi    = 1.
+
+!-      real :: nat_surf
+!-      logical :: ok_flux_surf
+!-      real :: fsens
+!-      real :: flat
+!-      real :: tsurf
+!-      real :: rugos
+!-      real :: qsol(1:2)
+!-      real :: qsurf
+!-      real :: psurf
+!-      real :: zsurf
+!-      real :: albedo
+!-
+!-      real :: time     = 0.
+!-      real :: time_ini
+!-      real :: xlat 
+!-      real :: xlon 
+!-      real :: wtsurf 
+!-      real :: wqsurf 
+!-      real :: restart_runoff 
+!-      real :: xagesno 
+!-      real :: qsolinp 
+!-      real :: zpicinp 
+!-
+      real :: fnday 
+      real :: day, daytime 
+      real :: day1
+      real :: heure
+      integer :: jour
+      integer :: mois
+      integer :: an
+ 
+!
+      real :: paire    = 1.     ! aire de la maille
+!**      common /flux_arp/fsens,flat,ok_flux_surf
+
+!---------------------------------------------------------------------
+!  Declarations related to forcing and initial profiles 
+!---------------------------------------------------------------------
+
+        integer :: kmax = llm
+        integer nlev_max
+        parameter (nlev_max = 100)
+        real timestep, frac, timeit
+        real height(nlev_max),tttprof(nlev_max),qtprof(nlev_max),
+     .              uprof(nlev_max),vprof(nlev_max),e12prof(nlev_max),
+     .              ugprof(nlev_max),vgprof(nlev_max),wfls(nlev_max),
+     .              dqtdxls(nlev_max),dqtdyls(nlev_max),
+     .              dqtdtls(nlev_max),thlpcar(nlev_max)
+
+        real    :: fff
+c        integer :: forcing_type
+        logical :: forcing_les     = .false.
+        logical :: forcing_armcu  = .false.
+        logical :: forcing_rico    = .false.
+        logical :: forcing_radconv = .false.
+        logical :: forcing_toga    = .false.
+        logical :: forcing_twpice  = .false.
+        logical :: forcing_GCM2SCM = .false.
+        logical :: forcing_GCSSold = .false.
+        integer :: type_ts_forcing ! 0 = SST constant; 1 = SST read from a file
+!                                                            (cf read_tsurf1d.F)
+
+!vertical advection computation
+        real d_t_z(llm), d_q_z(llm)
+        real d_t_dyn_z(llm), d_q_dyn_z(llm)
+        real zz(llm)
+        real zfact
+
+!flag forcings
+        logical :: nudge_wind=.true.
+        logical :: nudge_thermo=.false.
+        logical :: cptadvw=.true.
+!=====================================================================
+! DECLARATIONS FOR EACH CASE
+!=====================================================================
+!
+#include "1D_decl_cases.h"
+!
+!---------------------------------------------------------------------
+!  Declarations related to vertical discretization:
+!---------------------------------------------------------------------
+      real :: pzero=1.e5
+      real :: play (llm),zlay (llm),sig_s(llm),plev(llm+1)
+      real :: playd(llm),zlayd(llm)
+
+!---------------------------------------------------------------------
+!  Declarations related to variables
+!---------------------------------------------------------------------
+
+      integer :: iq
+      real :: phi(llm)
+      real :: teta(llm),temp(llm),u(llm),v(llm)
+      real :: omega(llm+1),omega2(llm),rho(llm+1)
+      real :: ug(llm),vg(llm),fcoriolis
+      real :: du_phys(llm),dv_phys(llm),dt_phys(llm)
+      real :: du_dyn(llm),dv_dyn(llm),dt_dyn(llm)
+      real :: dt_cooling(llm),d_t_cool(llm),d_th_adv(llm)
+      real :: dq_cooling(llm),d_q_cool(llm)
+      real :: tmpvar(llm)
+      real :: alpha
+
+      REAL, ALLOCATABLE, DIMENSION(:,:):: q
+      REAL, ALLOCATABLE, DIMENSION(:,:):: dq
+      REAL, ALLOCATABLE, DIMENSION(:,:):: dq_dyn
+      REAL, ALLOCATABLE, DIMENSION(:,:):: d_q_adv
+
+!---------------------------------------------------------------------
+!  Initialization of surface variables
+!---------------------------------------------------------------------
+      real :: run_off_lic_0(1)
+      real :: fder(1),snsrf(1,nbsrf),qsurfsrf(1,nbsrf)
+      real :: evap(1,nbsrf),frugs(1,nbsrf)
+      real :: tsoil(1,nsoilmx,nbsrf)
+      real :: agesno(1,nbsrf)
+
+!---------------------------------------------------------------------
+!  Call to phyredem
+!---------------------------------------------------------------------
+      logical :: ok_writedem =.true.
+      
+!---------------------------------------------------------------------
+!  Call to physiq
+!---------------------------------------------------------------------
+      integer, parameter :: longcles=20
+      logical :: firstcall=.true.
+      logical :: lastcall=.false.
+      real :: phis    = 0.0
+      real :: clesphy0(longcles) = 0.0
+      real :: dpsrf 
+
+!---------------------------------------------------------------------
+!  Initializations of boundary conditions 
+!---------------------------------------------------------------------
+      integer, parameter :: yd = 360
+      real :: phy_nat (yd) = 0.0 ! 0=ocean libre,1=land,2=glacier,3=banquise
+      real :: phy_alb (yd)  ! Albedo land only (old value condsurf_jyg=0.3)
+      real :: phy_sst (yd)  ! SST (will not be used; cf read_tsurf1d.F)
+      real :: phy_bil (yd) = 1.0 ! Ne sert que pour les slab_ocean
+      real :: phy_rug (yd) ! Longueur rugosite utilisee sur land only
+      real :: phy_ice (yd) = 0.0 ! Fraction de glace
+      real :: phy_fter(yd) = 0.0 ! Fraction de terre
+      real :: phy_foce(yd) = 0.0 ! Fraction de ocean
+      real :: phy_fsic(yd) = 0.0 ! Fraction de glace
+      real :: phy_flic(yd) = 0.0 ! Fraction de glace
+
+!---------------------------------------------------------------------
+!  Fichiers et d'autres variables
+!---------------------------------------------------------------------
+      real ttt
+      integer :: ierr,k,l,i,it=1,mxcalc
+      integer jjmp1
+      parameter (jjmp1=jjm+1-1/jjm)
+      INTEGER nbteta
+      PARAMETER(nbteta=3)
+      REAL dudyn(iim+1,jjmp1,llm)
+      REAL PVteta(1,nbteta)
+      INTEGER read_climoz 
+!Al1
+      integer ecrit_slab_oc !1=ecrit,-1=lit,0=no file
+      data ecrit_slab_oc/-1/
+
+!=====================================================================
+! INITIALIZATIONS 
+!=====================================================================
+! Initialization of Common turb_forcing
+       dtime_frcg = 0.
+       Turb_fcg_gcssold=.false.
+       hthturb_gcssold = 0.
+       hqturb_gcssold = 0.
+
+!---------------------------------------------------------------------
+! OPTIONS OF THE 1D SIMULATION (lmdz1d.def => unicol.def)
+!---------------------------------------------------------------------
+cAl1
+        call conf_unicol(99)
+cAl1 moves this gcssold var from common fcg_gcssold to 
+        Turb_fcg_gcssold = xTurb_fcg_gcssold
+c --------------------------------------------------------------------
+        close(1)
+cAl1
+        write(*,*) 'lmdz1d.def lu => unicol.def'
+
+! forcing_type defines the way the SCM is forced:
+!forcing_type = 0 ==> forcing_les = .true.
+!             initial profiles from file prof.inp.001
+!             no forcing by LS convergence ; 
+!             surface temperature imposed ;
+!             radiative cooling may be imposed (iflag_radia=0 in physiq.def)
+!forcing_type = 1 ==> forcing_radconv = .true.
+!             idem forcing_type = 0, but the imposed radiative cooling 
+!             is set to 0 (hence, if iflag_radia=0 in physiq.def, 
+!             then there is no radiative cooling at all)
+!forcing_type = 2 ==> forcing_toga = .true.
+!             initial profiles from TOGA-COARE IFA files 
+!             LS convergence and SST imposed from TOGA-COARE IFA files 
+!forcing_type = 3 ==> forcing_GCM2SCM = .true.
+!             initial profiles from the GCM output
+!             LS convergence imposed from the GCM output
+!forcing_type = 4 ==> forcing_twpice = .true.
+!             initial profiles from TWP-ICE cdf file 
+!             LS convergence, omega and SST imposed from TWP-ICE files 
+!forcing_type = 5 ==> forcing_rico = .true.
+!             initial profiles from RICO files 
+!             LS convergence imposed from RICO files 
+!forcing_type = 40 ==> forcing_GCSSold = .true.
+!             initial profile from GCSS file
+!             LS convergence imposed from GCSS file
+!forcing_type = 61 ==> forcing_armcu = .true.
+!             initial profile from arm_cu file
+!             LS convergence imposed from arm_cu file
+!
+      if (forcing_type .eq.0) THEN
+       forcing_les = .true.
+      elseif (forcing_type .eq.1) THEN
+       forcing_radconv = .true.
+      elseif (forcing_type .eq.2) THEN
+       forcing_toga    = .true.
+      elseif (forcing_type .eq.3) THEN
+       forcing_GCM2SCM = .true.
+      elseif (forcing_type .eq.4) THEN
+       forcing_twpice = .true.
+      elseif (forcing_type .eq.5) THEN
+       forcing_rico = .true.
+      elseif (forcing_type .eq.40) THEN
+       forcing_GCSSold = .true.
+      elseif (forcing_type .eq.61) THEN
+       forcing_armcu = .true.
+      else
+       write (*,*) 'ERROR : unknown forcing_type ', forcing_type
+       stop 'Forcing_type should be 0,1,2,3 or 40'
+      ENDIF
+      print*,"forcing type=",forcing_type
+
+! if type_ts_forcing=0, the surface temp of 1D simulation is constant in time
+! (specified by tsurf in lmdz1d.def); if type_ts_forcing=1, the surface temperature
+! varies in time according to a forcing (e.g. forcing_toga) and is passed to read_tsurf1d.F
+! through the common sst_forcing.
+
+        type_ts_forcing = 0
+        if (forcing_toga) type_ts_forcing = 1
+
+!---------------------------------------------------------------------
+!  Definition of the run
+!---------------------------------------------------------------------
+
+      call conf_gcm( 99, .TRUE. , clesphy0 )
+c-----------------------------------------------------------------------
+c   Choix du calendrier
+c   -------------------
+
+c      calend = 'earth_365d'
+      if (calend == 'earth_360d') then
+        call ioconf_calendar('360d')
+        write(*,*)'CALENDRIER CHOISI: Terrestre a 360 jours/an'
+      else if (calend == 'earth_365d') then
+        call ioconf_calendar('noleap')
+        write(*,*)'CALENDRIER CHOISI: Terrestre a 365 jours/an'
+      else if (calend == 'earth_366d') then
+        call ioconf_calendar('all_leap')
+        write(*,*)'CALENDRIER CHOISI: Terrestre bissextile'
+      else if (calend == 'gregorian') then
+        call ioconf_calendar('gregorian') ! not to be used by normal users
+        write(*,*)'CALENDRIER CHOISI: Gregorien'
+      else
+        write (*,*) 'ERROR : unknown calendar ', calend
+        stop 'calend should be 360d,earth_365d,earth_366d,gregorian'
+      endif
+c-----------------------------------------------------------------------
+c
+cc Date :
+c      La date est supposee donnee sous la forme [annee, numero du jour dans 
+c      l annee] ; l heure est donnee dans time_ini, lu dans lmdz1d.def.
+c      On appelle ymds2ju pour convertir [annee, jour] en [jour Julien].
+c      Le numero du jour est dans "day". L heure est traitee separement.
+c      La date complete est dans "daytime" (l'unite est le jour).
+      fnday=nday
+c Special case for arm_cu which lasts less than one day : 53100s !! (MPL 20111026)
+      IF(forcing_type .EQ. 61) fnday=53100./86400.
+      annee_ref = anneeref
+      mois = 1
+      day_ref = dayref
+      heure = 0.
+      itau_dyn = 0
+      itau_phy = 0
+      call ymds2ju(annee_ref,mois,day_ref,heure,day)
+      day_ini = day
+      day_end = day_ini + nday
+! Convert the initial date of Toga-Coare to Julian day
+      call ymds2ju
+     $ (year_ini_toga,mth_ini_toga,day_ini_toga,heure,day_ju_ini_toga)
+
+! Convert the initial date of TWPICE to Julian day
+      call ymds2ju
+     $ (year_ini_twpi,mth_ini_twpi,day_ini_twpi,heure_ini_twpi
+     $ ,day_ju_ini_twpi)
+
+! Convert the initial date of Arm_cu to Julian day
+      call ymds2ju
+     $ (year_ini_armcu,mth_ini_armcu,day_ini_armcu,heure_ini_armcu
+     $ ,day_ju_ini_armcu)
+
+      daytime = day + time_ini/24. ! 1st day and initial time of the simulation 
+! Print out the actual date of the beginning of the simulation :
+      call ju2ymds(daytime,year_print, month_print,day_print,sec_print)
+      print *,' Time of beginning : ',
+     $        year_print, month_print, day_print, sec_print
+
+!---------------------------------------------------------------------
+! Initialization of dimensions, geometry and initial state
+!---------------------------------------------------------------------
+      call init_phys_lmdz(1,1,llm,1,(/1/))
+      call suphel
+      call initcomgeomphy
+      call infotrac_init 
+
+      allocate(q(llm,nqtot)) 
+      allocate(dq(llm,nqtot)) 
+      allocate(dq_dyn(llm,nqtot)) 
+      allocate(d_q_adv(llm,nqtot)) 
+
+c
+c   No ozone climatology need be read in this pre-initialization
+c          (phys_state_var_init is called again in physiq)
+      read_climoz = 0
+c
+      call phys_state_var_init(read_climoz)
+
+      if (ngrid.ne.klon) then
+         print*,'stop in inifis'
+         print*,'Probleme de dimensions :'
+         print*,'ngrid = ',ngrid
+         print*,'klon  = ',klon
+         stop
+      endif
+!!!=====================================================================
+!!! Feedback forcing values for Gateaux differentiation (al1)
+!!!=====================================================================
+!!! Surface Planck forcing bracketing call radiation
+!!      surf_Planck = 0.
+!!      surf_Conv   = 0.
+!!      write(*,*) 'Gateaux-dif Planck,Conv:',surf_Planck,surf_Conv
+!!! a mettre dans le lmdz1d.def ou autre
+!!
+!!
+      qsol = qsolinp
+      qsurf = fq_sat(tsurf,psurf/100.)
+      rlat=xlat
+      rlon=xlon
+      day1= day_ini
+      time=daytime-day
+      ts_toga(1)=tsurf ! needed by read_tsurf1d.F
+      rho(1)=psurf/(rd*tsurf*(1.+(rv/rd-1.)*qsurf)) 
+
+      ok_flux_surf=.false.
+      fsens=-wtsurf*rcpd*rho(1)
+      flat=-wqsurf*rlvtt*rho(1)
+
+! Vertical discretization and pressure levels at half and mid levels:
+
+      pa   = 5e4
+!!      preff= 1.01325e5
+      preff = psurf
+      call disvert(pa,preff,ap,bp,dpres,presnivs,nivsigs,nivsig)
+      sig_s=presnivs/preff
+      plev =ap+bp*psurf
+      play = 0.5*(plev(1:llm)+plev(2:llm+1))
+ccc      zlay=-rd*300.*log(play/psurf)/rg ! moved after reading profiles
+
+      write(*,*) '***********************'
+      do l = 1, llm
+       write(*,*) 'l,play(l),presnivs(l): ',l,play(l),presnivs(l)
+      enddo
+      write(*,*) '***********************'
+
+c
+!=====================================================================
+! EVENTUALLY, READ FORCING DATA :
+!=====================================================================
+
+#include "1D_read_forc_cases.h"
+
+      if (forcing_GCM2SCM) then
+        write (*,*) 'forcing_GCM2SCM not yet implemented'
+        stop 'in initialization'
+      endif ! forcing_GCM2SCM
+
+      print*,'mxcalc=',mxcalc
+      print*,'zlay=',zlay(mxcalc)
+      print*,'play=',play(mxcalc)
+
+cAl1 pour SST forced, appellé depuis ocean_forced_noice
+      ts_cur = tsurf ! SST used in read_tsurf1d
+!=====================================================================
+! Initialisation de la physique : 
+!=====================================================================
+
+!  Rq: conf_phys.F90 lit tous les flags de physiq.def; conf_phys appele depuis physiq.F
+!
+! day_step, iphysiq lus dans gcm.def ci-dessus
+! timestep: calcule ci-dessous from rday et day_step
+! ngrid=1
+! llm: defini dans .../modipsl/modeles/LMDZ4/libf/grid/dimension
+! rday: defini dans suphel.F (86400.)
+! day_ini: lu dans run.def (dayref)
+! rlat,rlon lus dans lmdz1d.def
+! airefi,zcufi,zcvfi initialises au debut de ce programme
+! rday,ra,rg,rd,rcpd declares dans YOMCST.h et calcules dans suphel.F
+      day_step = float(nsplit_phys)*day_step/float(iphysiq)
+      write (*,*) 'Time step divided by nsplit_phys (=',nsplit_phys,')'
+      timestep =rday/day_step
+      dtime_frcg = timestep
+!
+      zcufi=airefi
+      zcvfi=airefi
+
+      call iniphysiq(ngrid,llm,rday,day_ini,timestep,
+     .     rlat,rlon,airefi,zcufi,zcvfi,ra,rg,rd,rcpd)
+      print*,'apres iniphysiq'
+
+! 2 PARAMETRES QUI DEVRAIENT ETRE LUS DANS run.def MAIS NE LE SONT PAS ICI:
+      co2_ppm= 330.0
+      solaire=1370.0
+
+! Ecriture du startphy avant le premier appel a la physique.
+! On le met juste avant pour avoir acces a tous les champs
+! NB: les clesphy0 seront remplies dans phyredem d'apres les flags lus dans gcm.def
+
+      if (ok_writedem) then
+
+!--------------------------------------------------------------------------
+! pbl_surface_init (called here) and pbl_surface_final (called by phyredem)
+! need : qsol fder snow qsurf evap rugos agesno ftsoil
+!--------------------------------------------------------------------------
+
+        type_ocean = "force"
+        run_off_lic_0(1) = restart_runoff 
+        call fonte_neige_init(run_off_lic_0)
+
+        fder=0.
+        snsrf(1,:)=0.        ! couverture de neige des sous surface
+        qsurfsrf(1,:)=qsurf ! humidite de l'air des sous surface
+        evap=0.
+        frugs(1,:)=rugos     ! couverture de neige des sous surface
+        agesno  = xagesno
+        tsoil(:,:,:)=tsurf
+        call pbl_surface_init(qsol, fder, snsrf, qsurfsrf,
+     &                                    evap, frugs, agesno, tsoil)
+
+!------------------ prepare limit conditions for limit.nc -----------------
+!--   Ocean force
+
+        print*,'avant phyredem'
+        pctsrf(1,:)=0.
+        if (nat_surf.eq.0.) then
+          pctsrf(1,is_oce)=1.
+          pctsrf(1,is_ter)=0.
+        else
+          pctsrf(1,is_oce)=0.
+          pctsrf(1,is_ter)=1.
+        end if
+
+        print*,'nat_surf,pctsrf(1,is_oce),pctsrf(1,is_ter)',nat_surf
+     $        ,pctsrf(1,is_oce),pctsrf(1,is_ter)
+
+        zmasq=pctsrf(1,is_ter)+pctsrf(1,is_lic)
+        zpic = zpicinp
+        ftsol=tsurf
+        falb1 = albedo                            
+        falb2 = albedo                            
+        rugoro=rugos 
+        t_ancien(1,:)=temp(:)
+        q_ancien(1,:)=q(:,1)
+        pbl_tke=1.e-8
+
+        rain_fall=0.
+        snow_fall=0.
+        solsw=0.
+        sollw=0.
+        radsol=0.
+        rnebcon=0.
+        ratqs=0.
+        clwcon=0.
+        zmea=0.
+        zstd=0.
+        zsig=0.
+        zgam=0.
+        zval=0. 
+        zthe=0. 
+        ema_work1=0.
+        ema_work2=0.
+ 
+!------------------------------------------------------------------------
+! Make file containing restart for the physics (startphy.nc)
+!
+! NB: List of the variables to be written by phyredem (via put_field):
+! rlon,rlat,zmasq,pctsrf(:,is_ter),pctsrf(:,is_lic),pctsrf(:,is_oce)
+! pctsrf(:,is_sic),ftsol(:,nsrf),tsoil(:,isoil,nsrf),qsurf(:,nsrf)
+! qsol,falb1(:,nsrf),falb2(:,nsrf),evap(:,nsrf),snow(:,nsrf)
+! radsol,solsw,sollw,fder,rain_fall,snow_fall,frugs(:,nsrf)
+! agesno(:,nsrf),zmea,zstd,zsig,zgam,zthe,zpic,zval,rugoro
+! t_ancien,q_ancien,frugs(:,is_oce),clwcon(:,1),rnebcon(:,1),ratqs(:,1)
+! run_off_lic_0,pbl_tke(:,1:klev,nsrf),zmax0,f0,ema_work1,ema_work2
+! wake_deltat,wake_deltaq,wake_s,wake_cstar,wake_fip
+!------------------------------------------------------------------------
+CAl1 =============== restart option ==========================
+        if (.not.restart) then
+          call phyredem ("startphy.nc")
+        else
+c (desallocations)
+        print*,'callin surf final'
+          call pbl_surface_final(qsol, fder, snsrf, qsurfsrf,
+     &                                    evap, frugs, agesno, tsoil)
+        print*,'after surf final'
+          CALL fonte_neige_final(run_off_lic_0)
+        endif
+
+        ok_writedem=.false.
+        print*,'apres phyredem'
+
+      endif ! ok_writedem
+      
+!------------------------------------------------------------------------
+! Make file containing boundary conditions (limit.nc) **Al1->restartdyn***
+! --------------------------------------------------
+! NB: List of the variables to be written in limit.nc 
+!     (by writelim.F, subroutine of 1DUTILS.h):
+!        phy_nat,phy_alb,phy_sst,phy_bil,phy_rug,phy_ice,
+!        phy_fter,phy_foce,phy_flic,phy_fsic)
+!------------------------------------------------------------------------
+      do i=1,yd
+        phy_nat(i)  = nat_surf
+        phy_alb(i)  = albedo
+        phy_sst(i)  = tsurf ! read_tsurf1d will be used instead
+        phy_rug(i)  = rugos
+        phy_fter(i) = pctsrf(1,is_ter)
+        phy_foce(i) = pctsrf(1,is_oce)
+        phy_fsic(i) = pctsrf(1,is_sic)
+        phy_flic(i) = pctsrf(1,is_lic)
+      enddo
+
+C fabrication de limit.nc
+      call writelim (1,phy_nat,phy_alb,phy_sst,phy_bil,phy_rug,
+     &               phy_ice,phy_fter,phy_foce,phy_flic,phy_fsic)
+
+
+      call phys_state_var_end
+cAl1
+      if (restart) then
+        print*,'call to restart dyn 1d'
+        Call dyn1deta0("start1dyn.nc",
+     &              plev,play,phi,phis,presnivs,
+     &              u,v,temp,q,omega2)
+
+       print*,'fnday,annee_ref,day_ref,day_ini',
+     &     fnday,annee_ref,day_ref,day_ini
+c**      call ymds2ju(annee_ref,mois,day_ini,heure,day)
+       day = day_ini
+       day_end = day_ini + nday
+       daytime = day + time_ini/24. ! 1st day and initial time of the simulation 
+
+! Print out the actual date of the beginning of the simulation :
+       call ju2ymds(daytime, an, mois, jour, heure)
+       print *,' Time of beginning : y m d h',an, mois,jour,heure/3600.
+
+       day = int(daytime)
+       time=daytime-day
+  
+       print*,'****** intialised fields from restart1dyn *******'
+       print*,'plev,play,phi,phis,presnivs,u,v,temp,q,omega2'
+       print*,'temp(1),q(1,1),u(1),v(1),plev(1),phis :'
+       print*,temp(1),q(1,1),u(1),v(1),plev(1),phis
+c raz for safety
+       do l=1,llm
+         dq_dyn(l,1) = 0.
+       enddo
+      endif
+!Al1 ================  end restart =================================
+      IF (ecrit_slab_oc.eq.1) then
+         open(97,file='div_slab.dat',STATUS='UNKNOWN')
+       elseif (ecrit_slab_oc.eq.0) then
+         open(97,file='div_slab.dat',STATUS='OLD')
+       endif
+!=====================================================================
+! START OF THE TEMPORAL LOOP :
+!=====================================================================
+           
+      do while(it.le.nint(fnday*day_step))
+
+       if (prt_level.ge.1) then
+         print*,'XXXXXXXXXXXXXXXXXXX ITAP,day,time=',
+     .                                it,day,time,nint(fnday*day_step)
+         print*,'PAS DE TEMPS ',timestep
+       endif
+!Al1 demande de restartphy.nc
+       if (it.eq.nint(fnday*day_step)) lastcall=.True.
+
+!---------------------------------------------------------------------
+! Interpolation of forcings in time and onto model levels
+!---------------------------------------------------------------------
+
+#include "1D_interp_cases.h"
+
+      if (forcing_GCM2SCM) then
+        write (*,*) 'forcing_GCM2SCM not yet implemented'
+        stop 'in time loop'
+      endif ! forcing_GCM2SCM
+
+!---------------------------------------------------------------------
+!  Geopotential :
+!---------------------------------------------------------------------
+
+        phi(1)=RD*temp(1)*(plev(1)-play(1))/(.5*(plev(1)+play(1)))
+        do l = 1, llm-1
+          phi(l+1)=phi(l)+RD*(temp(l)+temp(l+1))*
+     .    (play(l)-play(l+1))/(play(l)+play(l+1))
+        enddo
+
+!---------------------------------------------------------------------
+!   Call physiq :
+!---------------------------------------------------------------------
+
+       if (prt_level.ge.1) then
+         print *,' avant physiq : -------- day time ',day,time
+         print *,' temp ',temp
+         print *,' u ',u
+         print *,' q ',q
+         print *,' omega2 ',omega2
+       endif
+!       call writefield_phy('u', u,llm)
+
+        call physiq(ngrid,llm,
+     :              firstcall,lastcall,
+     :              day,time,timestep,
+     :              plev,play,phi,phis,presnivs,clesphy0,
+     :              u,v,temp,q,omega2,
+     :              du_phys,dv_phys,dt_phys,dq,dpsrf,
+     :              dudyn,PVteta)
+!       call writefield_phy('u', u,llm)
+
+        firstcall=.false.
+        if (prt_level.ge.1) then
+          print*,'APRES PHYS'
+          print *,' temp ',temp
+          print *,' q ',q
+          print *,' dq ',dq
+          print*,'dq_dyn',dq_dyn
+          print *,' dt_phys ',dt_phys
+          print *,' dpsrf ',dpsrf
+          print *,' dudyn ',dudyn
+          print *,' PVteta',PVteta
+        endif
+!---------------------------------------------------------------------
+!   Add physical tendencies :
+!---------------------------------------------------------------------
+
+      fcoriolis=2.*sin(rpi*rlat(1)/180.)*romega
+
+       if (forcing_radconv) then
+         fcoriolis=0.0
+         dt_cooling=0.0
+         d_th_adv=0.0
+         d_q_adv=0.0
+       endif
+
+       if (forcing_toga .or. forcing_GCSSold .or. forcing_twpice) then
+         fcoriolis=0.0
+       endif
+         if(forcing_rico) then
+          dt_cooling=0.
+        endif
+
+      print*, 'fcoriolis ', fcoriolis, rlat(1)
+
+        du_age(1:mxcalc)=
+     : fcoriolis*(v(1:mxcalc)-vg(1:mxcalc))
+       dv_age(1:mxcalc)=
+     : -fcoriolis*(u(1:mxcalc)-ug(1:mxcalc))
+!         call  writefield_phy('dv_age' ,dv_age,llm)
+!         call  writefield_phy('du_age' ,du_age,llm)
+!         call  writefield_phy('du_phys' ,du_phys,llm)
+!         call  writefield_phy('u_tend' ,u,llm)
+!         call  writefield_phy('u_g' ,ug,llm)
+        u(1:mxcalc)=u(1:mxcalc) + timestep*(
+     :              du_phys(1:mxcalc)
+     :             +du_age(1:mxcalc) )            
+        v(1:mxcalc)=v(1:mxcalc) + timestep*(
+     :	             dv_phys(1:mxcalc)
+     :             +dv_age(1:mxcalc) )
+        q(1:mxcalc,:)=q(1:mxcalc,:)+timestep*(
+     :                dq(1:mxcalc,:)
+     :               +d_q_adv(1:mxcalc,:) )
+
+        if (prt_level.ge.1) then
+          print *,
+     :    'physiq-> temp(1),dt_phys(1),d_th_adv(1),dt_cooling(1) ',
+     :              temp(1),dt_phys(1),d_th_adv(1),dt_cooling(1)
+           print*,du_phys
+           print*, v
+           print*, vg
+        endif
+
+        temp(1:mxcalc)=temp(1:mxcalc)+timestep*(
+     .              dt_phys(1:mxcalc)
+     .             +d_th_adv(1:mxcalc)
+     .             +dt_cooling(1:mxcalc))  ! Taux de chauffage ou refroid.
+
+        teta=temp*(pzero/play)**rkappa
+
+!---------------------------------------------------------------------
+!   Add large-scale tendencies (advection, etc) :
+!---------------------------------------------------------------------
+
+ccc nrlmd
+ccc        tmpvar=teta
+ccc        call advect_vert(llm,omega,timestep,tmpvar,plev)
+ccc
+ccc        teta(1:mxcalc)=tmpvar(1:mxcalc)
+ccc        tmpvar(:)=q(:,1)
+ccc        call advect_vert(llm,omega,timestep,tmpvar,plev)
+ccc        q(1:mxcalc,1)=tmpvar(1:mxcalc)
+ccc        tmpvar(:)=q(:,2)
+ccc        call advect_vert(llm,omega,timestep,tmpvar,plev)
+ccc        q(1:mxcalc,2)=tmpvar(1:mxcalc)
+
+!---------------------------------------------------------------------
+!   Air temperature :
+!---------------------------------------------------------------------        
+        if (lastcall) then
+          print*,'Pas de temps final ',it
+          call ju2ymds(daytime, an, mois, jour, heure)
+          print*,'a la date : a m j h',an, mois, jour ,heure/3600.
+        endif
+
+c  incremente day time
+c        print*,'daytime bef',daytime,1./day_step
+        daytime = daytime+1./day_step
+!Al1dbg
+        day = int(daytime+0.1/day_step)
+c        time = max(daytime-day,0.0)
+cAl1&jyg: correction de bug
+ccc        time = real(mod(it,day_step))/day_step
+        time = time_ini/24.+real(mod(it,day_step))/day_step
+c        print*,'daytime nxt time',daytime,time
+        it=it+1
+
+      enddo
+
+!Al1
+      if (ecrit_slab_oc.ne.-1) close(97)
+
+!Al1 Call to 1D equivalent of dynredem (an,mois,jour,heure ?)
+! -------------------------------------
+       call dyn1dredem("restart1dyn.nc",
+     :              plev,play,phi,phis,presnivs,
+     :              u,v,temp,q,omega2)
+
+        CALL abort_gcm ('lmdz1d   ','The End  ',0)
+
+      end
+
+#include "1DUTILS.h"
+#include "1Dconv.h"
+
+
Index: LMDZ5/branches/testing/libf/phy1d/ocean_forced_mod.F90
===================================================================
--- LMDZ5/branches/testing/libf/phy1d/ocean_forced_mod.F90	(revision 1665)
+++ LMDZ5/branches/testing/libf/phy1d/ocean_forced_mod.F90	(revision 1665)
@@ -0,0 +1,278 @@
+!
+MODULE ocean_forced_mod
+!
+! This module is used for both the sub-surfaces ocean and sea-ice for the case of a 
+! forced ocean,  "ocean=force".
+!
+  IMPLICIT NONE
+
+CONTAINS
+!
+!****************************************************************************************
+!
+  SUBROUTINE ocean_forced_noice( &
+       itime, dtime, jour, knon, knindex, &
+       p1lay, cdragh, cdragm, precip_rain, precip_snow, &
+       temp_air, spechum, &
+       AcoefH, AcoefQ, BcoefH, BcoefQ, &
+       AcoefU, AcoefV, BcoefU, BcoefV, &
+       ps, u1, v1, &
+       radsol, snow, agesno, & 
+       qsurf, evap, fluxsens, fluxlat, flux_u1, flux_v1, &
+       tsurf_new, dflux_s, dflux_l)
+!
+! This subroutine treats the "open ocean", all grid points that are not entierly covered
+! by ice.
+! The routine receives data from climatologie file limit.nc and does some calculations at the 
+! surface. 
+!
+    USE dimphy
+    USE calcul_fluxs_mod
+    USE limit_read_mod
+    USE mod_grid_phy_lmdz
+    INCLUDE "indicesol.h"
+    INCLUDE "YOMCST.h"
+
+! Input arguments
+!****************************************************************************************
+    INTEGER, INTENT(IN)                      :: itime, jour, knon
+    INTEGER, DIMENSION(klon), INTENT(IN)     :: knindex
+    REAL, INTENT(IN)                         :: dtime
+    REAL, DIMENSION(klon), INTENT(IN)        :: p1lay
+    REAL, DIMENSION(klon), INTENT(IN)        :: cdragh, cdragm
+    REAL, DIMENSION(klon), INTENT(IN)        :: precip_rain, precip_snow
+    REAL, DIMENSION(klon), INTENT(IN)        :: temp_air, spechum
+    REAL, DIMENSION(klon), INTENT(IN)        :: AcoefH, AcoefQ, BcoefH, BcoefQ
+    REAL, DIMENSION(klon), INTENT(IN)        :: AcoefU, AcoefV, BcoefU, BcoefV
+    REAL, DIMENSION(klon), INTENT(IN)        :: ps
+    REAL, DIMENSION(klon), INTENT(IN)        :: u1, v1
+
+! In/Output arguments
+!****************************************************************************************
+    REAL, DIMENSION(klon), INTENT(INOUT)     :: radsol
+    REAL, DIMENSION(klon), INTENT(INOUT)     :: snow
+    REAL, DIMENSION(klon), INTENT(INOUT)     :: agesno !? put to 0 in ocean
+  
+! Output arguments
+!****************************************************************************************
+    REAL, DIMENSION(klon), INTENT(OUT)       :: qsurf
+    REAL, DIMENSION(klon), INTENT(OUT)       :: evap, fluxsens, fluxlat
+    REAL, DIMENSION(klon), INTENT(OUT)       :: flux_u1, flux_v1
+    REAL, DIMENSION(klon), INTENT(OUT)       :: tsurf_new
+    REAL, DIMENSION(klon), INTENT(OUT)       :: dflux_s, dflux_l
+
+! Local variables
+!****************************************************************************************
+    INTEGER                     :: i
+    REAL, DIMENSION(klon)       :: cal, beta, dif_grnd
+    REAL, DIMENSION(klon)       :: alb_neig, tsurf_lim, zx_sl
+    REAL, DIMENSION(klon)       :: u0, v0
+    REAL, DIMENSION(klon)       :: u1_lay, v1_lay
+    LOGICAL                     :: check=.FALSE.
+
+!****************************************************************************************
+! Start calculation
+!****************************************************************************************
+    IF (check) WRITE(*,*)' Entering ocean_forced_noice'
+    
+!****************************************************************************************
+! 1)    
+! Read sea-surface temperature from file limit.nc
+!
+!****************************************************************************************
+!--sb:
+!!jyg    if (knon.eq.1) then ! single-column model
+    if (klon_glo.eq.1) then ! single-column model
+      CALL read_tsurf1d(knon,knindex,tsurf_lim) ! new
+    else ! GCM
+      CALL limit_read_sst(knon,knindex,tsurf_lim)
+    endif ! knon
+!sb--
+
+!****************************************************************************************
+! 2)
+! Flux calculation
+!
+!****************************************************************************************
+! Set some variables for calcul_fluxs
+    cal = 0.
+    beta = 1.
+    dif_grnd = 0.
+    alb_neig(:) = 0.
+    agesno(:) = 0.
+! Suppose zero surface speed
+    u0(:)=0.0
+    v0(:)=0.0
+    u1_lay(:) = u1(:) - u0(:)
+    v1_lay(:) = v1(:) - v0(:)
+
+! Calcul de tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l and qsurf
+    CALL calcul_fluxs(knon, is_oce, dtime, &
+         tsurf_lim, p1lay, cal, beta, cdragh, ps, &
+         precip_rain, precip_snow, snow, qsurf,  &
+         radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, &
+         AcoefH, AcoefQ, BcoefH, BcoefQ, &
+         tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
+
+! - Flux calculation at first modele level for U and V
+    CALL calcul_flux_wind(knon, dtime, &
+         u0, v0, u1, v1, cdragm, &
+         AcoefU, AcoefV, BcoefU, BcoefV, &
+         p1lay, temp_air, &
+         flux_u1, flux_v1)  
+
+  END SUBROUTINE ocean_forced_noice
+!
+!***************************************************************************************
+!
+  SUBROUTINE ocean_forced_ice( &
+       itime, dtime, jour, knon, knindex, &
+       tsurf_in, p1lay, cdragh, cdragm, precip_rain, precip_snow, temp_air, spechum, &
+       AcoefH, AcoefQ, BcoefH, BcoefQ, &
+       AcoefU, AcoefV, BcoefU, BcoefV, &
+       ps, u1, v1, &
+       radsol, snow, qsol, agesno, tsoil, &
+       qsurf, alb1_new, alb2_new, evap, fluxsens, fluxlat, flux_u1, flux_v1, &
+       tsurf_new, dflux_s, dflux_l)
+!
+! This subroutine treats the ocean where there is ice. 
+! The routine reads data from climatologie file and does flux calculations at the 
+! surface.
+!
+    USE dimphy
+    USE calcul_fluxs_mod
+    USE surface_data,     ONLY : calice, calsno, tau_gl
+    USE limit_read_mod
+    USE fonte_neige_mod,  ONLY : fonte_neige
+
+    INCLUDE "indicesol.h"
+    INCLUDE "dimsoil.h"
+    INCLUDE "YOMCST.h"
+    INCLUDE "clesphys.h"
+
+! Input arguments
+!****************************************************************************************
+    INTEGER, INTENT(IN)                  :: itime, jour, knon
+    INTEGER, DIMENSION(klon), INTENT(IN) :: knindex
+    REAL, INTENT(IN)                     :: dtime
+    REAL, DIMENSION(klon), INTENT(IN)    :: tsurf_in
+    REAL, DIMENSION(klon), INTENT(IN)    :: p1lay
+    REAL, DIMENSION(klon), INTENT(IN)    :: cdragh, cdragm
+    REAL, DIMENSION(klon), INTENT(IN)    :: precip_rain, precip_snow
+    REAL, DIMENSION(klon), INTENT(IN)    :: temp_air, spechum
+    REAL, DIMENSION(klon), INTENT(IN)    :: AcoefH, AcoefQ, BcoefH, BcoefQ
+    REAL, DIMENSION(klon), INTENT(IN)    :: AcoefU, AcoefV, BcoefU, BcoefV
+    REAL, DIMENSION(klon), INTENT(IN)    :: ps
+    REAL, DIMENSION(klon), INTENT(IN)    :: u1, v1
+
+! In/Output arguments
+!****************************************************************************************
+    REAL, DIMENSION(klon), INTENT(INOUT)          :: radsol
+    REAL, DIMENSION(klon), INTENT(INOUT)          :: snow, qsol
+    REAL, DIMENSION(klon), INTENT(INOUT)          :: agesno
+    REAL, DIMENSION(klon, nsoilmx), INTENT(INOUT) :: tsoil
+
+! Output arguments
+!****************************************************************************************
+    REAL, DIMENSION(klon), INTENT(OUT)            :: qsurf
+    REAL, DIMENSION(klon), INTENT(OUT)            :: alb1_new  ! new albedo in visible SW interval
+    REAL, DIMENSION(klon), INTENT(OUT)            :: alb2_new  ! new albedo in near IR interval
+    REAL, DIMENSION(klon), INTENT(OUT)            :: evap, fluxsens, fluxlat
+    REAL, DIMENSION(klon), INTENT(OUT)            :: flux_u1, flux_v1
+    REAL, DIMENSION(klon), INTENT(OUT)            :: tsurf_new
+    REAL, DIMENSION(klon), INTENT(OUT)            :: dflux_s, dflux_l      
+
+! Local variables
+!****************************************************************************************
+    LOGICAL                     :: check=.FALSE.
+    INTEGER                     :: i
+    REAL                        :: zfra
+    REAL, PARAMETER             :: t_grnd=271.35
+    REAL, DIMENSION(klon)       :: cal, beta, dif_grnd, capsol
+    REAL, DIMENSION(klon)       :: alb_neig, tsurf_tmp
+    REAL, DIMENSION(klon)       :: soilcap, soilflux
+    REAL, DIMENSION(klon)       :: u0, v0
+    REAL, DIMENSION(klon)       :: u1_lay, v1_lay
+
+!****************************************************************************************
+! Start calculation
+!****************************************************************************************
+    IF (check) WRITE(*,*)'Entering surface_seaice, knon=',knon 
+
+!****************************************************************************************
+! 1) 
+! Flux calculation : tsurf_new, evap, fluxlat, fluxsens, flux_u1, flux_v1
+!                    dflux_s, dflux_l and qsurf
+!****************************************************************************************
+    tsurf_tmp(:) = tsurf_in(:)
+
+! calculate the parameters cal, beta, capsol and dif_grnd
+    CALL calbeta(dtime, is_sic, knon, snow, qsol, beta, capsol, dif_grnd)
+
+    
+    IF (soil_model) THEN 
+! update tsoil and calculate soilcap and soilflux
+       CALL soil(dtime, is_sic, knon, snow, tsurf_tmp, tsoil,soilcap, soilflux)
+       cal(1:knon) = RCPD / soilcap(1:knon)
+       radsol(1:knon) = radsol(1:knon)  + soilflux(1:knon)
+       dif_grnd = 1.0 / tau_gl
+    ELSE 
+       dif_grnd = 1.0 / tau_gl
+       cal = RCPD * calice
+       WHERE (snow > 0.0) cal = RCPD * calsno 
+    ENDIF
+
+    beta = 1.0
+! Suppose zero surface speed
+    u0(:)=0.0
+    v0(:)=0.0
+    u1_lay(:) = u1(:) - u0(:)
+    v1_lay(:) = v1(:) - v0(:)
+    CALL calcul_fluxs(knon, is_sic, dtime, &
+         tsurf_tmp, p1lay, cal, beta, cdragh, ps, &
+         precip_rain, precip_snow, snow, qsurf,  &
+         radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, &
+         AcoefH, AcoefQ, BcoefH, BcoefQ, &
+         tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
+
+! - Flux calculation at first modele level for U and V
+    CALL calcul_flux_wind(knon, dtime, &
+         u0, v0, u1, v1, cdragm, &
+         AcoefU, AcoefV, BcoefU, BcoefV, &
+         p1lay, temp_air, &
+         flux_u1, flux_v1)  
+
+!****************************************************************************************
+! 2)
+! Calculations due to snow and runoff
+!
+!****************************************************************************************
+    CALL fonte_neige( knon, is_sic, knindex, dtime, &
+         tsurf_tmp, precip_rain, precip_snow, &
+         snow, qsol, tsurf_new, evap)
+    
+! Calculation of albedo at snow (alb_neig) and update the age of snow (agesno)
+! 
+    CALL albsno(klon, knon, dtime, agesno(:), alb_neig(:), precip_snow(:))  
+
+    WHERE (snow(1:knon) .LT. 0.0001) agesno(1:knon) = 0.
+
+    alb1_new(:) = 0.0
+    DO i=1, knon
+       zfra = MAX(0.0,MIN(1.0,snow(i)/(snow(i)+10.0)))
+       alb1_new(i) = alb_neig(i) * zfra +  0.6 * (1.0-zfra)
+    ENDDO
+
+    alb2_new(:) = alb1_new(:)
+
+  END SUBROUTINE ocean_forced_ice
+!
+!****************************************************************************************
+!
+END MODULE ocean_forced_mod
+
+
+
+
+
+
Index: LMDZ5/branches/testing/libf/phy1d/orografi_strato.F
===================================================================
--- LMDZ5/branches/testing/libf/phy1d/orografi_strato.F	(revision 1665)
+++ LMDZ5/branches/testing/libf/phy1d/orografi_strato.F	(revision 1665)
@@ -0,0 +1,2060 @@
+      SUBROUTINE drag_noro_strato (nlon,nlev,dtime,paprs,pplay,
+     e                   pmea,pstd, psig, pgam, pthe,ppic,pval,
+     e                   kgwd,kdx,ktest,
+     e                   t, u, v,
+     s                   pulow, pvlow, pustr, pvstr,
+     s                   d_t, d_u, d_v)
+c
+      USE dimphy
+      IMPLICIT none
+c======================================================================
+c Auteur(s): F.Lott (LMD/CNRS) date: 19950201
+c Object: Mountain drag interface. Made necessary because:
+C 1. in the LMD-GCM Layers are from bottom to top,
+C    contrary to most European GCM.
+c 2. the altitude above ground of each model layers
+c    needs to be known (variable zgeom)
+c======================================================================
+c Explicit Arguments:
+c ==================
+c nlon----input-I-Total number of horizontal points that get into physics
+c nlev----input-I-Number of vertical levels
+c dtime---input-R-Time-step (s)
+c paprs---input-R-Pressure in semi layers    (Pa)
+c pplay---input-R-Pressure model-layers      (Pa)
+c t-------input-R-temperature (K)
+c u-------input-R-Horizontal wind (m/s)
+c v-------input-R-Meridional wind (m/s)
+c pmea----input-R-Mean Orography (m)
+C pstd----input-R-SSO standard deviation (m)
+c psig----input-R-SSO slope
+c pgam----input-R-SSO Anisotropy
+c pthe----input-R-SSO Angle
+c ppic----input-R-SSO Peacks elevation (m)
+c pval----input-R-SSO Valleys elevation (m)
+c
+c kgwd- -input-I: Total nb of points where the orography schemes are active
+c ktest--input-I: Flags to indicate active points
+c kdx----input-I: Locate the physical location of an active point.
+
+c pulow, pvlow -output-R: Low-level wind
+c pustr, pvstr -output-R: Surface stress due to SSO drag      (Pa)
+c
+c d_t-----output-R: T increment            
+c d_u-----output-R: U increment              
+c d_v-----output-R: V increment              
+c
+c Implicit Arguments:
+c ===================
+c
+c iim--common-I: Number of longitude intervals
+c jjm--common-I: Number of latitude intervals
+c klon-common-I: Number of points seen by the physics
+c                (iim+1)*(jjm+1) for instance
+c klev-common-I: Number of vertical layers
+c======================================================================
+c Local Variables:
+c ================
+c
+c zgeom-----R: Altitude of layer above ground
+c pt, pu, pv --R: t u v from top to bottom
+c pdtdt, pdudt, pdvdt --R: t u v tendencies (from top to bottom) 
+c papmf: pressure at model layer (from top to bottom)
+c papmh: pressure at model 1/2 layer (from top to bottom)
+c 
+c======================================================================
+cym#include "dimensions.h"
+cym#include "dimphy.h"
+#include "YOMCST.h"
+#include "YOEGWD.h"
+c
+c  ARGUMENTS
+c
+      INTEGER nlon,nlev
+      REAL dtime
+      REAL paprs(nlon,nlev+1)
+      REAL pplay(nlon,nlev)
+      REAL pmea(nlon),pstd(nlon),psig(nlon),pgam(nlon),pthe(nlon)
+      REAL ppic(nlon),pval(nlon)
+      REAL pulow(nlon),pvlow(nlon),pustr(nlon),pvstr(nlon)
+      REAL t(nlon,nlev), u(nlon,nlev), v(nlon,nlev)
+      REAL d_t(nlon,nlev), d_u(nlon,nlev), d_v(nlon,nlev)
+c
+      INTEGER i, k, kgwd,  kdx(nlon), ktest(nlon)
+c
+c LOCAL VARIABLES:
+c
+      REAL zgeom(klon,klev)
+      REAL pdtdt(klon,klev), pdudt(klon,klev), pdvdt(klon,klev)
+      REAL pt(klon,klev), pu(klon,klev), pv(klon,klev)
+      REAL papmf(klon,klev),papmh(klon,klev+1)
+      CHARACTER (LEN=20) :: modname='orografi_strato'
+      CHARACTER (LEN=80) :: abort_message
+c
+c INITIALIZE OUTPUT VARIABLES 
+c
+      DO i = 1,klon
+         pulow(i) = 0.0
+         pvlow(i) = 0.0
+         pustr(i) = 0.0
+         pvstr(i) = 0.0
+      ENDDO
+      DO k = 1, klev
+      DO i = 1, klon
+         d_t(i,k) = 0.0
+         d_u(i,k) = 0.0
+         d_v(i,k) = 0.0
+         pdudt(i,k)=0.0
+         pdvdt(i,k)=0.0
+         pdtdt(i,k)=0.0
+      ENDDO
+      ENDDO
+c
+c PREPARE INPUT VARIABLES FOR ORODRAG (i.e., ORDERED FROM TOP TO BOTTOM)
+C CALCULATE LAYERS HEIGHT ABOVE GROUND)
+c
+      DO k = 1, klev
+      DO i = 1, klon
+         pt(i,k) = t(i,klev-k+1) 
+         pu(i,k) = u(i,klev-k+1)
+         pv(i,k) = v(i,klev-k+1)
+         papmf(i,k) = pplay(i,klev-k+1)
+      ENDDO
+      ENDDO
+      DO k = 1, klev+1
+      DO i = 1, klon
+         papmh(i,k) = paprs(i,klev-k+2)
+      ENDDO
+      ENDDO
+      DO i = 1, klon
+         zgeom(i,klev) = RD * pt(i,klev)
+     .                  * LOG(papmh(i,klev+1)/papmf(i,klev))
+      ENDDO
+      DO k = klev-1, 1, -1
+      DO i = 1, klon
+         zgeom(i,k) = zgeom(i,k+1) + RD * (pt(i,k)+pt(i,k+1))/2.0
+     .               * LOG(papmf(i,k+1)/papmf(i,k))
+      ENDDO
+      ENDDO
+c
+c CALL SSO DRAG ROUTINES        
+c
+      CALL orodrag_strato(klon,klev,kgwd,kdx,ktest,
+     .            dtime,
+     .            papmh, papmf, zgeom,
+     .            pt, pu, pv,
+     .            pmea, pstd, psig, pgam, pthe, ppic,pval,
+     .            pulow,pvlow,
+     .            pdudt,pdvdt,pdtdt)
+C
+C COMPUTE INCREMENTS AND STRESS FROM TENDENCIES
+
+      DO k = 1, klev
+      DO i = 1, klon
+         d_u(i,klev+1-k) = dtime*pdudt(i,k)
+         d_v(i,klev+1-k) = dtime*pdvdt(i,k)
+         d_t(i,klev+1-k) = dtime*pdtdt(i,k)
+         pustr(i)        = pustr(i)
+     .                    +pdudt(i,k)*(papmh(i,k+1)-papmh(i,k))/rg
+         pvstr(i)        = pvstr(i)
+     .                    +pdvdt(i,k)*(papmh(i,k+1)-papmh(i,k))/rg
+      ENDDO
+      ENDDO
+c
+      RETURN
+      END
+
+      SUBROUTINE orodrag_strato( nlon,nlev 
+     i                 , kgwd,  kdx, ktest
+     r                 , ptsphy
+     r                 , paphm1,papm1,pgeom1,ptm1,pum1,pvm1
+     r                 , pmea, pstd, psig, pgam, pthe, ppic, pval
+c outputs
+     r                 , pulow,pvlow
+     r                 , pvom,pvol,pte )
+      
+      USE dimphy
+      IMPLICIT NONE
+c
+c
+c**** *orodrag* - does the SSO drag  parametrization.
+c
+c     purpose.
+c     --------
+c
+c     this routine computes the physical tendencies of the
+c     prognostic variables u,v  and t due to  vertical transports by
+c     subgridscale orographically excited gravity waves, and to
+c     low level blocked flow drag.
+c
+c**   interface.
+c     ----------
+c          called from *drag_noro*.
+c
+c          the routine takes its input from the long-term storage:
+c          u,v,t and p at t-1.
+c
+c        explicit arguments :
+c        --------------------
+c     ==== inputs ===
+c nlon----input-I-Total number of horizontal points that get into physics
+c nlev----input-I-Number of vertical levels
+c
+c kgwd- -input-I: Total nb of points where the orography schemes are active
+c ktest--input-I: Flags to indicate active points
+c kdx----input-I: Locate the physical location of an active point.
+c ptsphy--input-R-Time-step (s)
+c paphm1--input-R: pressure at model 1/2 layer
+c papm1---input-R: pressure at model layer
+c pgeom1--input-R: Altitude of layer above ground
+c ptm1, pum1, pvm1--R-: t, u and v
+c pmea----input-R-Mean Orography (m)
+C pstd----input-R-SSO standard deviation (m)
+c psig----input-R-SSO slope
+c pgam----input-R-SSO Anisotropy
+c pthe----input-R-SSO Angle
+c ppic----input-R-SSO Peacks elevation (m)
+c pval----input-R-SSO Valleys elevation (m)
+
+      integer nlon,nlev,kgwd
+      real ptsphy
+
+c     ==== outputs ===
+c pulow, pvlow -output-R: Low-level wind
+c
+c pte -----output-R: T tendency
+c pvom-----output-R: U tendency
+c pvol-----output-R: V tendency
+c
+c
+c Implicit Arguments:
+c ===================
+c
+c klon-common-I: Number of points seen by the physics
+c klev-common-I: Number of vertical layers
+c
+c     method.
+c     -------
+c
+c     externals.
+c     ----------
+      integer ismin, ismax
+      external ismin, ismax
+c
+c     reference.
+c     ----------
+c
+c     author.
+c     -------
+c     m.miller + b.ritter   e.c.m.w.f.     15/06/86.
+c
+c     f.lott + m. miller    e.c.m.w.f.     22/11/94
+c-----------------------------------------------------------------------
+c
+c
+cym#include "dimensions.h"
+cym#include "dimphy.h"
+#include "YOMCST.h"
+#include "YOEGWD.h"
+c-----------------------------------------------------------------------
+c
+c*       0.1   arguments
+c              ---------
+c
+c
+      real  pte(nlon,nlev),
+     *      pvol(nlon,nlev),
+     *      pvom(nlon,nlev),
+     *      pulow(nlon),
+     *      pvlow(nlon)
+      real  pum1(nlon,nlev),
+     *      pvm1(nlon,nlev),
+     *      ptm1(nlon,nlev),
+     *      pmea(nlon),pstd(nlon),psig(nlon),
+     *      pgam(nlon),pthe(nlon),ppic(nlon),pval(nlon),
+     *      pgeom1(nlon,nlev),
+     *      papm1(nlon,nlev),
+     *      paphm1(nlon,nlev+1)
+c
+      integer  kdx(nlon),ktest(nlon)
+c-----------------------------------------------------------------------
+c
+c*       0.2   local arrays
+c              ------------
+      integer  isect(klon),
+     *         icrit(klon),
+     *         ikcrith(klon),
+     *         ikenvh(klon),
+     *         iknu(klon),
+     *         iknu2(klon),
+     *         ikcrit(klon),
+     *         ikhlim(klon)
+c
+      real   ztau(klon,klev+1),
+     *       zstab(klon,klev+1),
+     *       zvph(klon,klev+1),
+     *       zrho(klon,klev+1),
+     *       zri(klon,klev+1),
+     *       zpsi(klon,klev+1),
+     *       zzdep(klon,klev)
+      real   zdudt(klon),
+     *       zdvdt(klon),
+     *       zdtdt(klon),
+     *       zdedt(klon),
+     *       zvidis(klon),
+     *       ztfr(klon),
+     *       znu(klon),
+     *       zd1(klon),
+     *       zd2(klon),
+     *       zdmod(klon)
+
+
+c local quantities:
+
+      integer jl,jk,ji
+      real ztmst,zdelp,ztemp,zforc,ztend,rover                
+      real zb,zc,zconb,zabsv,zzd1,ratio,zbet,zust,zvst,zdis
+   
+c
+c------------------------------------------------------------------
+c
+c*         1.    initialization
+c                --------------
+c
+c        print *,' in orodrag'
+ 100  continue
+c
+c     ------------------------------------------------------------------
+c
+c*         1.1   computational constants
+c                -----------------------
+c
+ 110  continue
+c
+c     ztmst=twodt
+c     if(nstep.eq.nstart) ztmst=0.5*twodt
+      ztmst=ptsphy
+c     ------------------------------------------------------------------
+c
+ 120  continue
+c
+c     ------------------------------------------------------------------
+c
+c*         1.3   check whether row contains point for printing
+c                ---------------------------------------------
+c
+ 130  continue
+c
+c     ------------------------------------------------------------------
+c
+c*         2.     precompute basic state variables.
+c*                ---------- ----- ----- ----------
+c*                define low level wind, project winds in plane of
+c*                low level wind, determine sector in which to take
+c*                the variance and set indicator for critical levels.
+c
+
+  200 continue
+c
+c
+c
+      call orosetup_strato
+     *     ( nlon, nlev , ktest 
+     *     , ikcrit, ikcrith, icrit, isect, ikhlim, ikenvh,iknu,iknu2
+     *     , paphm1, papm1 , pum1   , pvm1 , ptm1 , pgeom1, pstd
+     *     , zrho  , zri   , zstab  , ztau , zvph , zpsi, zzdep
+     *     , pulow, pvlow 
+     *     , pthe,pgam,pmea,ppic,pval,znu  ,zd1,  zd2,  zdmod )
+
+
+c
+c
+c
+c***********************************************************
+c
+c
+c*         3.      compute low level stresses using subcritical and
+c*                 supercritical forms.computes anisotropy coefficient
+c*                 as measure of orographic twodimensionality.
+c
+  300 continue
+c
+      call gwstress_strato
+     *    ( nlon  , nlev
+     *    , ikcrit, isect, ikhlim, ktest, ikcrith, icrit, ikenvh, iknu
+     *    , zrho  , zstab, zvph  , pstd,  psig, pmea, ppic, pval
+     *    , ztfr   , ztau 
+     *    , pgeom1,pgam,zd1,zd2,zdmod,znu)
+
+c
+c
+c*         4.      compute stress profile including
+c                  trapped waves, wave breaking,
+c                  linear decay in stratosphere.
+c
+  400 continue
+c
+c
+
+      call gwprofil_strato
+     *       (  nlon , nlev
+     *       , kgwd   , kdx  , ktest
+     *       , ikcrit, ikcrith, icrit  , ikenvh, iknu
+     *       ,iknu2 , paphm1, zrho   , zstab , ztfr   , zvph
+     *       , zri   , ztau 
+ 
+     *       , zdmod , znu    , psig  , pgam , pstd , ppic , pval)
+
+c
+c*         5.      Compute tendencies from waves stress profile.
+c                  Compute low level blocked flow drag. 
+c*                 --------------------------------------------
+c
+  500 continue
+
+      
+c
+c  explicit solution at all levels for the gravity wave
+c  implicit solution for the blocked levels
+
+      do 510 jl=kidia,kfdia
+      zvidis(jl)=0.0
+      zdudt(jl)=0.0
+      zdvdt(jl)=0.0
+      zdtdt(jl)=0.0
+  510 continue
+c
+
+      do 524 jk=1,klev
+c
+
+C  WAVE STRESS 
+C-------------
+c
+c
+      do 523 ji=kidia,kfdia
+
+      if(ktest(ji).eq.1) then
+
+      zdelp=paphm1(ji,jk+1)-paphm1(ji,jk)
+      ztemp=-rg*(ztau(ji,jk+1)-ztau(ji,jk))/(zvph(ji,klev+1)*zdelp)
+
+      zdudt(ji)=(pulow(ji)*zd1(ji)-pvlow(ji)*zd2(ji))*ztemp/zdmod(ji)
+      zdvdt(ji)=(pvlow(ji)*zd1(ji)+pulow(ji)*zd2(ji))*ztemp/zdmod(ji)
+c
+c Control Overshoots
+c
+
+      if(jk.ge.nstra)then
+        rover=0.10
+        if(abs(zdudt(ji)).gt.rover*abs(pum1(ji,jk))/ztmst)
+     C    zdudt(ji)=rover*abs(pum1(ji,jk))/ztmst*
+     C              zdudt(ji)/(abs(zdudt(ji))+1.E-10)
+        if(abs(zdvdt(ji)).gt.rover*abs(pvm1(ji,jk))/ztmst)
+     C    zdvdt(ji)=rover*abs(pvm1(ji,jk))/ztmst*
+     C              zdvdt(ji)/(abs(zdvdt(ji))+1.E-10)
+      endif 
+
+      rover=0.25
+      zforc=sqrt(zdudt(ji)**2+zdvdt(ji)**2)        
+      ztend=sqrt(pum1(ji,jk)**2+pvm1(ji,jk)**2)/ztmst                      
+
+      if(zforc.ge.rover*ztend)then
+        zdudt(ji)=rover*ztend/zforc*zdudt(ji)
+        zdvdt(ji)=rover*ztend/zforc*zdvdt(ji)
+      endif
+c
+c BLOCKED FLOW DRAG:
+C -----------------
+c
+      if(jk.gt.ikenvh(ji)) then
+         zb=1.0-0.18*pgam(ji)-0.04*pgam(ji)**2
+         zc=0.48*pgam(ji)+0.3*pgam(ji)**2
+         zconb=2.*ztmst*gkwake*psig(ji)/(4.*pstd(ji))
+         zabsv=sqrt(pum1(ji,jk)**2+pvm1(ji,jk)**2)/2.
+         zzd1=zb*cos(zpsi(ji,jk))**2+zc*sin(zpsi(ji,jk))**2
+         ratio=(cos(zpsi(ji,jk))**2+pgam(ji)*sin(zpsi(ji,jk))**2)/
+     *   (pgam(ji)*cos(zpsi(ji,jk))**2+sin(zpsi(ji,jk))**2)
+         zbet=max(0.,2.-1./ratio)*zconb*zzdep(ji,jk)*zzd1*zabsv
+c
+c OPPOSED TO THE WIND
+c
+         zdudt(ji)=-pum1(ji,jk)/ztmst
+         zdvdt(ji)=-pvm1(ji,jk)/ztmst
+c
+c PERPENDICULAR TO THE SSO MAIN AXIS:
+C                            
+cmod     zdudt(ji)=-(pum1(ji,jk)*cos(pthe(ji)*rpi/180.)
+cmod *              +pvm1(ji,jk)*sin(pthe(ji)*rpi/180.))
+cmod *              *cos(pthe(ji)*rpi/180.)/ztmst
+cmod     zdvdt(ji)=-(pum1(ji,jk)*cos(pthe(ji)*rpi/180.)
+cmod *              +pvm1(ji,jk)*sin(pthe(ji)*rpi/180.))
+cmod *              *sin(pthe(ji)*rpi/180.)/ztmst
+C
+         zdudt(ji)=zdudt(ji)*(zbet/(1.+zbet))
+         zdvdt(ji)=zdvdt(ji)*(zbet/(1.+zbet))
+      end if
+      pvom(ji,jk)=zdudt(ji)
+      pvol(ji,jk)=zdvdt(ji)
+      zust=pum1(ji,jk)+ztmst*zdudt(ji)
+      zvst=pvm1(ji,jk)+ztmst*zdvdt(ji)
+      zdis=0.5*(pum1(ji,jk)**2+pvm1(ji,jk)**2-zust**2-zvst**2)
+      zdedt(ji)=zdis/ztmst
+      zvidis(ji)=zvidis(ji)+zdis*zdelp
+      zdtdt(ji)=zdedt(ji)/rcpd
+c
+c  NO TENDENCIES ON TEMPERATURE .....
+c
+c  Instead of, pte(ji,jk)=zdtdt(ji), due to mechanical dissipation
+c
+      pte(ji,jk)=0.0
+
+      endif
+
+  523 continue
+  524 continue
+c
+c
+  501 continue
+
+      return
+      end
+      SUBROUTINE orosetup_strato
+     *         ( nlon   , nlev  , ktest
+     *         , kkcrit, kkcrith, kcrit, ksect , kkhlim
+     *         , kkenvh, kknu  , kknu2
+     *         , paphm1, papm1 , pum1   , pvm1 , ptm1  , pgeom1, pstd
+     *         , prho  , pri   , pstab  , ptau , pvph  ,ppsi, pzdep
+     *         , pulow , pvlow  
+     *         , ptheta, pgam, pmea, ppic, pval
+     *         , pnu  ,  pd1  ,  pd2  ,pdmod  )
+C
+c**** *gwsetup*
+c
+c     purpose.
+c     --------
+c     SET-UP THE ESSENTIAL PARAMETERS OF THE SSO DRAG SCHEME:
+C     DEPTH OF LOW WBLOCKED LAYER, LOW-LEVEL FLOW, BACKGROUND
+C     STRATIFICATION.....
+c
+c**   interface.
+c     ----------
+c          from *orodrag*
+c
+c        explicit arguments :
+c        --------------------
+c     ==== inputs ===
+c 
+c nlon----input-I-Total number of horizontal points that get into physics
+c nlev----input-I-Number of vertical levels
+c ktest--input-I: Flags to indicate active points
+c
+c ptsphy--input-R-Time-step (s)
+c paphm1--input-R: pressure at model 1/2 layer
+c papm1---input-R: pressure at model layer
+c pgeom1--input-R: Altitude of layer above ground
+c ptm1, pum1, pvm1--R-: t, u and v
+c pmea----input-R-Mean Orography (m)
+C pstd----input-R-SSO standard deviation (m)
+c psig----input-R-SSO slope
+c pgam----input-R-SSO Anisotropy
+c pthe----input-R-SSO Angle
+c ppic----input-R-SSO Peacks elevation (m)
+c pval----input-R-SSO Valleys elevation (m)
+
+c     ==== outputs ===
+c pulow, pvlow -output-R: Low-level wind
+c kkcrit----I-: Security value for top of low level flow
+c kcrit-----I-: Critical level 
+c ksect-----I-: Not used
+c kkhlim----I-: Not used
+c kkenvh----I-: Top of blocked flow layer
+c kknu------I-: Layer that sees mountain peacks
+c kknu2-----I-: Layer that sees mountain peacks above mountain mean
+c kknub-----I-: Layer that sees mountain mean above valleys
+c prho------R-: Density at 1/2 layers
+c pri-------R-: Background Richardson Number, Wind shear measured along GW stress
+c pstab-----R-: Brunt-Vaisala freq. at 1/2 layers
+c pvph------R-: Wind in  plan of GW stress, Half levels.
+c ppsi------R-: Angle between low level wind and SS0 main axis.
+c pd1-------R-| Compared the ratio of the stress
+c pd2-------R-| that is along the wind to that Normal to it.
+c               pdi define the plane of low level stress
+c               compared to the low level wind.
+c see p. 108 Lott & Miller (1997).                      
+c pdmod-----R-: Norme of pdi
+
+c     === local arrays ===
+c
+c zvpf------R-: Wind projected in the plan of the low-level stress.
+
+c     ==== outputs ===
+c
+c        implicit arguments :   none
+c        --------------------
+c
+c     method.
+c     -------
+c
+c
+c     externals.
+c     ----------
+c
+c
+c     reference.
+c     ----------
+c
+c        see ecmwf research department documentation of the "i.f.s."
+c
+c     author.
+c     -------
+c
+c     modifications.
+c     --------------
+c     f.lott  for the new-gwdrag scheme november 1993
+c
+c-----------------------------------------------------------------------
+      USE dimphy
+      implicit none
+c
+
+cym#include "dimensions.h"
+cym#include "dimphy.h"
+#include "YOMCST.h"
+#include "YOEGWD.h"
+
+c-----------------------------------------------------------------------
+c
+c*       0.1   arguments
+c              ---------
+c
+      integer nlon,nlev
+      integer kkcrit(nlon),kkcrith(nlon),kcrit(nlon),ksect(nlon),
+     *        kkhlim(nlon),ktest(nlon),kkenvh(nlon)
+
+c
+      real paphm1(nlon,klev+1),papm1(nlon,klev),pum1(nlon,klev),
+     *     pvm1(nlon,klev),ptm1(nlon,klev),pgeom1(nlon,klev),
+     *     prho(nlon,klev+1),pri(nlon,klev+1),pstab(nlon,klev+1),
+     *     ptau(nlon,klev+1),pvph(nlon,klev+1),ppsi(nlon,klev+1),
+     *     pzdep(nlon,klev)
+       real pulow(nlon),pvlow(nlon),ptheta(nlon),pgam(nlon),pnu(nlon),
+     *     pd1(nlon),pd2(nlon),pdmod(nlon)
+      real pstd(nlon),pmea(nlon),ppic(nlon),pval(nlon)
+c
+c-----------------------------------------------------------------------
+c
+c*       0.2   local arrays
+c              ------------
+c
+c
+      integer ilevh ,jl,jk
+      real zcons1,zcons2,zhgeo,zu,zphi
+      real zvt1,zvt2,zdwind,zwind,zdelp
+      real zstabm,zstabp,zrhom,zrhop
+      logical lo 
+      logical ll1(klon,klev+1)
+      integer kknu(klon),kknu2(klon),kknub(klon),kknul(klon),
+     *        kentp(klon),ncount(klon)  
+c
+      real zhcrit(klon,klev),zvpf(klon,klev),
+     *     zdp(klon,klev)
+      real znorm(klon),zb(klon),zc(klon),
+     *      zulow(klon),zvlow(klon),znup(klon),znum(klon)
+c       
+c     ------------------------------------------------------------------
+c
+c*         1.    initialization
+c                --------------
+c
+c       PRINT *,' in orosetup'
+ 100  continue
+c
+c     ------------------------------------------------------------------
+c
+c*         1.1   computational constants
+c                -----------------------
+c
+ 110  continue
+c
+      ilevh =klev/3
+c
+      zcons1=1./rd
+      zcons2=rg**2/rcpd
+c
+c
+c     ------------------------------------------------------------------
+c
+c*         2.
+c                --------------
+c
+ 200  continue
+c
+c     ------------------------------------------------------------------
+c
+c*         2.1     define low level wind, project winds in plane of
+c*                 low level wind, determine sector in which to take
+c*                 the variance and set indicator for critical levels.
+c
+c
+c
+      do 2001 jl=kidia,kfdia
+      kknu(jl)    =klev
+      kknu2(jl)   =klev
+      kknub(jl)   =klev
+      kknul(jl)   =klev
+      pgam(jl) =max(pgam(jl),gtsec)
+      ll1(jl,klev+1)=.false.
+ 2001 continue
+c
+c Ajouter une initialisation (L. Li, le 23fev99):
+c
+      do jk=klev,ilevh,-1
+      do jl=kidia,kfdia
+      ll1(jl,jk)= .false.
+      ENDDO
+      ENDDO
+c
+c*      define top of low level flow
+c       ----------------------------
+      do 2002 jk=klev,ilevh,-1
+      do 2003 jl=kidia,kfdia
+      if(ktest(jl).eq.1) then
+      lo=(paphm1(jl,jk)/paphm1(jl,klev+1)).ge.gsigcr
+      if(lo) then
+        kkcrit(jl)=jk
+      endif
+      zhcrit(jl,jk)=ppic(jl)-pval(jl)           
+      zhgeo=pgeom1(jl,jk)/rg
+      ll1(jl,jk)=(zhgeo.gt.zhcrit(jl,jk))
+      if(ll1(jl,jk).neqv.ll1(jl,jk+1)) then
+        kknu(jl)=jk
+      endif
+      if(.not.ll1(jl,ilevh))kknu(jl)=ilevh
+      endif
+ 2003 continue
+ 2002 continue
+      do 2004 jk=klev,ilevh,-1
+      do 2005 jl=kidia,kfdia
+      if(ktest(jl).eq.1) then
+      zhcrit(jl,jk)=ppic(jl)-pmea(jl)
+      zhgeo=pgeom1(jl,jk)/rg
+      ll1(jl,jk)=(zhgeo.gt.zhcrit(jl,jk))
+      if(ll1(jl,jk).neqv.ll1(jl,jk+1)) then
+        kknu2(jl)=jk
+      endif
+      if(.not.ll1(jl,ilevh))kknu2(jl)=ilevh
+      endif
+ 2005 continue
+ 2004 continue
+      do 2006 jk=klev,ilevh,-1
+      do 2007 jl=kidia,kfdia
+      if(ktest(jl).eq.1) then
+      zhcrit(jl,jk)=amin1(ppic(jl)-pmea(jl),pmea(jl)-pval(jl))
+      zhgeo=pgeom1(jl,jk)/rg
+      ll1(jl,jk)=(zhgeo.gt.zhcrit(jl,jk))
+      if(ll1(jl,jk).neqv.ll1(jl,jk+1)) then
+        kknub(jl)=jk
+      endif
+      if(.not.ll1(jl,ilevh))kknub(jl)=ilevh
+      endif
+ 2007 continue
+ 2006 continue
+c
+      do 2010 jl=kidia,kfdia  
+      if(ktest(jl).eq.1) then
+      kknu(jl)=min(kknu(jl),nktopg)
+      kknu2(jl)=min(kknu2(jl),nktopg)
+      kknub(jl)=min(kknub(jl),nktopg)
+      kknul(jl)=klev
+      endif
+ 2010 continue      
+c
+ 210  continue
+c
+cc*     initialize various arrays
+c
+      do 2107 jl=kidia,kfdia
+      prho(jl,klev+1)  =0.0
+cym correction en attendant mieux
+      prho(jl,1)  =0.0      
+      pstab(jl,klev+1) =0.0
+      pstab(jl,1)      =0.0
+      pri(jl,klev+1)   =9999.0
+      ppsi(jl,klev+1)  =0.0
+      pri(jl,1)        =0.0
+      pvph(jl,1)       =0.0
+      pvph(jl,klev+1)  =0.0
+cym correction en attendant mieux
+cym      pvph(jl,klev)    =0.0
+      pulow(jl)        =0.0
+      pvlow(jl)        =0.0
+      zulow(jl)        =0.0
+      zvlow(jl)        =0.0
+      kkcrith(jl)      =klev
+      kkenvh(jl)       =klev
+      kentp(jl)        =klev
+      kcrit(jl)        =1
+      ncount(jl)       =0
+      ll1(jl,klev+1)   =.false.
+ 2107 continue
+c
+c*     define flow density and stratification (rho and N2)
+c      at semi layers.
+c      -------------------------------------------------------
+c
+      do 223 jk=klev,2,-1
+      do 222 jl=kidia,kfdia
+      if(ktest(jl).eq.1) then
+        zdp(jl,jk)=papm1(jl,jk)-papm1(jl,jk-1)
+        prho(jl,jk)=2.*paphm1(jl,jk)*zcons1/(ptm1(jl,jk)+ptm1(jl,jk-1))
+        pstab(jl,jk)=2.*zcons2/(ptm1(jl,jk)+ptm1(jl,jk-1))*
+     *  (1.-rcpd*prho(jl,jk)*(ptm1(jl,jk)-ptm1(jl,jk-1))/zdp(jl,jk))
+        pstab(jl,jk)=max(pstab(jl,jk),gssec)
+      endif
+  222 continue
+  223 continue
+c
+c********************************************************************
+c
+c*     define Low level flow (between ground and peacks-valleys)
+c      ---------------------------------------------------------
+      do 2115 jk=klev,ilevh,-1
+      do 2116 jl=kidia,kfdia
+      if(ktest(jl).eq.1)  then
+      if(jk.ge.kknu2(jl).and.jk.le.kknul(jl)) then
+        pulow(jl)=pulow(jl)+pum1(jl,jk)*(paphm1(jl,jk+1)-paphm1(jl,jk))
+        pvlow(jl)=pvlow(jl)+pvm1(jl,jk)*(paphm1(jl,jk+1)-paphm1(jl,jk))
+        pstab(jl,klev+1)=pstab(jl,klev+1)
+     c                   +pstab(jl,jk)*(paphm1(jl,jk+1)-paphm1(jl,jk))
+        prho(jl,klev+1)=prho(jl,klev+1)
+     c                   +prho(jl,jk)*(paphm1(jl,jk+1)-paphm1(jl,jk))
+      end if
+      endif
+ 2116 continue
+ 2115 continue
+      do 2110 jl=kidia,kfdia
+      if(ktest(jl).eq.1)  then
+      pulow(jl)=pulow(jl)/(paphm1(jl,kknul(jl)+1)-paphm1(jl,kknu2(jl)))
+      pvlow(jl)=pvlow(jl)/(paphm1(jl,kknul(jl)+1)-paphm1(jl,kknu2(jl)))
+      znorm(jl)=max(sqrt(pulow(jl)**2+pvlow(jl)**2),gvsec)
+      pvph(jl,klev+1)=znorm(jl)
+      pstab(jl,klev+1)=pstab(jl,klev+1)
+     c                /(paphm1(jl,kknul(jl)+1)-paphm1(jl,kknu2(jl)))
+      prho(jl,klev+1)=prho(jl,klev+1)
+     c                /(paphm1(jl,kknul(jl)+1)-paphm1(jl,kknu2(jl)))
+      endif
+ 2110 continue
+
+c
+c*******  setup orography orientation relative to the low level
+C       wind and define parameters of the Anisotropic wave stress.
+c
+      do 2112 jl=kidia,kfdia
+      if(ktest(jl).eq.1)  then
+        lo=(pulow(jl).lt.gvsec).and.(pulow(jl).ge.-gvsec)
+        if(lo) then
+          zu=pulow(jl)+2.*gvsec
+        else
+          zu=pulow(jl)
+        endif
+        zphi=atan(pvlow(jl)/zu)
+        ppsi(jl,klev+1)=ptheta(jl)*rpi/180.-zphi
+        zb(jl)=1.-0.18*pgam(jl)-0.04*pgam(jl)**2
+        zc(jl)=0.48*pgam(jl)+0.3*pgam(jl)**2
+        pd1(jl)=zb(jl)-(zb(jl)-zc(jl))*(sin(ppsi(jl,klev+1))**2)
+        pd2(jl)=(zb(jl)-zc(jl))*sin(ppsi(jl,klev+1))
+     *                         *cos(ppsi(jl,klev+1))
+        pdmod(jl)=sqrt(pd1(jl)**2+pd2(jl)**2)
+      endif
+ 2112 continue
+c
+c  ************ projet flow in plane of lowlevel stress *************
+C  ************ Find critical levels...                 *************
+c
+      do 213 jk=1,klev
+      do 212 jl=kidia,kfdia
+      if(ktest(jl).eq.1)  then
+        zvt1       =pulow(jl)*pum1(jl,jk)+pvlow(jl)*pvm1(jl,jk)
+        zvt2       =-pvlow(jl)*pum1(jl,jk)+pulow(jl)*pvm1(jl,jk)
+        zvpf(jl,jk)=(zvt1*pd1(jl)+zvt2*pd2(jl))/(znorm(jl)*pdmod(jl))
+      endif
+      ptau(jl,jk)  =0.0
+      pzdep(jl,jk) =0.0
+      ppsi(jl,jk)  =0.0
+      ll1(jl,jk)   =.false.
+  212 continue
+  213 continue
+      do 215 jk=2,klev
+      do 214 jl=kidia,kfdia
+      if(ktest(jl).eq.1) then
+        zdp(jl,jk)=papm1(jl,jk)-papm1(jl,jk-1)
+        pvph(jl,jk)=((paphm1(jl,jk)-papm1(jl,jk-1))*zvpf(jl,jk)+
+     *            (papm1(jl,jk)-paphm1(jl,jk))*zvpf(jl,jk-1))
+     *            /zdp(jl,jk)
+        if(pvph(jl,jk).lt.gvsec) then
+          pvph(jl,jk)=gvsec
+          kcrit(jl)=jk
+        endif
+      endif
+  214 continue
+  215 continue
+c
+c*         2.3     mean flow richardson number.
+c
+  230 continue
+c
+      do 232 jk=2,klev
+      do 231 jl=kidia,kfdia
+      if(ktest(jl).eq.1) then
+        zdwind=max(abs(zvpf(jl,jk)-zvpf(jl,jk-1)),gvsec)
+        pri(jl,jk)=pstab(jl,jk)*(zdp(jl,jk)
+     *          /(rg*prho(jl,jk)*zdwind))**2
+        pri(jl,jk)=max(pri(jl,jk),grcrit)
+      endif
+  231 continue
+  232 continue
+  
+c
+c
+c*      define top of 'envelope' layer
+c       ----------------------------
+
+      do 233 jl=kidia,kfdia
+      pnu (jl)=0.0
+      znum(jl)=0.0
+ 233  continue
+      
+      do 234 jk=2,klev-1
+      do 234 jl=kidia,kfdia
+      
+      if(ktest(jl).eq.1) then
+       
+      if (jk.ge.kknu2(jl)) then
+          
+            znum(jl)=pnu(jl)
+            zwind=(pulow(jl)*pum1(jl,jk)+pvlow(jl)*pvm1(jl,jk))/
+     *            max(sqrt(pulow(jl)**2+pvlow(jl)**2),gvsec)
+            zwind=max(sqrt(zwind**2),gvsec)
+            zdelp=paphm1(jl,jk+1)-paphm1(jl,jk)
+            zstabm=sqrt(max(pstab(jl,jk  ),gssec))
+            zstabp=sqrt(max(pstab(jl,jk+1),gssec))
+            zrhom=prho(jl,jk  )
+            zrhop=prho(jl,jk+1)
+            pnu(jl) = pnu(jl) + (zdelp/rg)*
+     *            ((zstabp/zrhop+zstabm/zrhom)/2.)/zwind     
+            if((znum(jl).le.gfrcrit).and.(pnu(jl).gt.gfrcrit)
+     *                          .and.(kkenvh(jl).eq.klev))
+     *      kkenvh(jl)=jk
+     
+      endif    
+
+      endif
+      
+ 234  continue
+      
+c  calculation of a dynamical mixing height for when the waves
+C  BREAK AT LOW LEVEL: The drag will be repartited over
+C  a depths that depends on waves vertical wavelength,
+C  not just between two adjacent model layers.
+c  of gravity waves:
+
+      do 235 jl=kidia,kfdia
+      znup(jl)=0.0
+      znum(jl)=0.0
+ 235  continue
+
+      do 236 jk=klev-1,2,-1
+      do 236 jl=kidia,kfdia
+      
+      if(ktest(jl).eq.1) then
+
+            znum(jl)=znup(jl)
+            zwind=(pulow(jl)*pum1(jl,jk)+pvlow(jl)*pvm1(jl,jk))/
+     *            max(sqrt(pulow(jl)**2+pvlow(jl)**2),gvsec)
+            zwind=max(sqrt(zwind**2),gvsec)
+            zdelp=paphm1(jl,jk+1)-paphm1(jl,jk)
+            zstabm=sqrt(max(pstab(jl,jk  ),gssec))
+            zstabp=sqrt(max(pstab(jl,jk+1),gssec))
+            zrhom=prho(jl,jk  )
+            zrhop=prho(jl,jk+1)
+            znup(jl) = znup(jl) + (zdelp/rg)*
+     *            ((zstabp/zrhop+zstabm/zrhom)/2.)/zwind     
+            if((znum(jl).le.rpi/4.).and.(znup(jl).gt.rpi/4.)
+     *                          .and.(kkcrith(jl).eq.klev))
+     *      kkcrith(jl)=jk
+     
+      endif
+      
+ 236  continue
+ 
+      do 237 jl=kidia,kfdia
+      if(ktest(jl).eq.1) then
+      kkcrith(jl)=max0(kkcrith(jl),ilevh*2)
+      kkcrith(jl)=max0(kkcrith(jl),kknu(jl))
+      if(kcrit(jl).ge.kkcrith(jl))kcrit(jl)=1
+      endif
+ 237  continue         
+c
+c     directional info for flow blocking ************************* 
+c
+      do 251 jk=1,klev    
+      do 252 jl=kidia,kfdia
+      if(ktest(jl).eq.1) then
+      lo=(pum1(jl,jk).lt.gvsec).and.(pum1(jl,jk).ge.-gvsec)
+      if(lo) then
+        zu=pum1(jl,jk)+2.*gvsec
+      else
+        zu=pum1(jl,jk)
+      endif
+       zphi=atan(pvm1(jl,jk)/zu)
+       ppsi(jl,jk)=ptheta(jl)*rpi/180.-zphi
+      endif
+ 252  continue
+ 251  continue
+
+c      forms the vertical 'leakiness' **************************
+
+      do 254  jk=ilevh,klev
+      do 253  jl=kidia,kfdia
+      if(ktest(jl).eq.1) then
+      pzdep(jl,jk)=0
+      if(jk.ge.kkenvh(jl).and.kkenvh(jl).ne.klev) then
+        pzdep(jl,jk)=(pgeom1(jl,kkenvh(jl)  )-pgeom1(jl,  jk))/
+     *               (pgeom1(jl,kkenvh(jl)  )-pgeom1(jl,klev))
+      end if
+      endif
+ 253  continue
+ 254  continue
+
+      return
+      end
+      SUBROUTINE gwstress_strato
+     *         (  nlon  , nlev
+     *         , kkcrit, ksect, kkhlim, ktest, kkcrith, kcrit, kkenvh
+     *         , kknu
+     *         , prho  , pstab , pvph  , pstd, psig
+     *         , pmea , ppic , pval  , ptfr  , ptau  
+     *         , pgeom1 , pgamma , pd1  , pd2   , pdmod , pnu )
+c
+c**** *gwstress*
+c
+c     purpose.
+c     --------
+c  Compute the surface stress due to Gravity Waves, according
+c  to the Phillips (1979) theory of 3-D flow above 
+c  anisotropic elliptic ridges.
+
+C  The stress is reduced two account for cut-off flow over
+C  hill.  The flow only see that part of the ridge located
+c  above the blocked layer (see zeff).
+c
+c**   interface.
+c     ----------
+c     call *gwstress*  from *gwdrag*
+c
+c        explicit arguments :
+c        --------------------
+c     ==== inputs ===
+c     ==== outputs ===
+c
+c        implicit arguments :   none
+c        --------------------
+c
+c     method.
+c     -------
+c
+c
+c     externals.
+c     ----------
+c
+c
+c     reference.
+c     ----------
+c
+c   LOTT and MILLER (1997)  &  LOTT (1999)
+c
+c     author.
+c     -------
+c
+c     modifications.
+c     --------------
+c     f. lott put the new gwd on ifs      22/11/93
+c
+c-----------------------------------------------------------------------
+      USE dimphy
+      implicit none
+
+cym#include "dimensions.h"
+cym#include "dimphy.h"
+#include "YOMCST.h"
+#include "YOEGWD.h"
+
+c-----------------------------------------------------------------------
+c
+c*       0.1   arguments
+c              ---------
+c
+      integer nlon,nlev
+      integer kkcrit(nlon),kkcrith(nlon),kcrit(nlon),ksect(nlon),
+     *        kkhlim(nlon),ktest(nlon),kkenvh(nlon),kknu(nlon)
+c
+      real prho(nlon,nlev+1),pstab(nlon,nlev+1),ptau(nlon,nlev+1),
+     *     pvph(nlon,nlev+1),ptfr(nlon),
+     *     pgeom1(nlon,nlev),pstd(nlon)
+c
+      real pd1(nlon),pd2(nlon),pnu(nlon),psig(nlon),pgamma(nlon)
+      real pmea(nlon),ppic(nlon),pval(nlon)
+      real pdmod(nlon)
+c
+c-----------------------------------------------------------------------
+c
+c*       0.2   local arrays
+c              ------------
+c  zeff--real: effective height seen by the flow when there is blocking
+
+      integer jl
+      real zeff  
+c
+c-----------------------------------------------------------------------
+c
+c*       0.3   functions
+c              ---------
+c     ------------------------------------------------------------------
+c
+c*         1.    initialization
+c                --------------
+c
+c      PRINT *,' in gwstress'
+ 100  continue
+c
+c*         3.1     gravity wave stress.
+c
+  300 continue
+c
+c
+      do 301 jl=kidia,kfdia
+      if(ktest(jl).eq.1) then
+      
+c  effective mountain height above the blocked flow
+  
+         zeff=ppic(jl)-pval(jl)
+         if(kkenvh(jl).lt.klev)then
+         zeff=amin1(GFRCRIT*pvph(jl,klev+1)/sqrt(pstab(jl,klev+1))
+     c              ,zeff)
+         endif
+
+      
+        ptau(jl,klev+1)=gkdrag*prho(jl,klev+1)
+     *     *psig(jl)*pdmod(jl)/4./pstd(jl)
+     *     *pvph(jl,klev+1)*sqrt(pstab(jl,klev+1))
+     *     *zeff**2
+
+
+c  too small value of stress or  low level flow include critical level
+c  or low level flow:  gravity wave stress nul.
+                
+c       lo=(ptau(jl,klev+1).lt.gtsec).or.(kcrit(jl).ge.kknu(jl))
+c    *      .or.(pvph(jl,klev+1).lt.gvcrit)
+c       if(lo) ptau(jl,klev+1)=0.0
+      
+c      print *,jl,ptau(jl,klev+1)
+
+      else
+      
+          ptau(jl,klev+1)=0.0
+          
+      endif
+
+  301 continue
+
+c      write(21)(ptau(jl,klev+1),jl=kidia,kfdia)
+ 
+      return
+      end
+
+      subroutine gwprofil_strato
+     *         ( nlon, nlev
+     *         , kgwd ,kdx  , ktest
+     *         , kkcrit, kkcrith, kcrit ,  kkenvh, kknu,kknu2
+     *         , paphm1, prho   , pstab , ptfr , pvph , pri , ptau
+     *         , pdmod   , pnu   , psig ,pgamma, pstd, ppic,pval)
+
+C**** *gwprofil*
+C
+C     purpose.
+C     --------
+C
+C**   interface.
+C     ----------
+C          from *gwdrag*
+C
+C        explicit arguments :
+C        --------------------
+C     ==== inputs ===
+C
+C     ==== outputs ===
+C
+C        implicit arguments :   none
+C        --------------------
+C
+C     method:
+C     -------
+C     the stress profile for gravity waves is computed as follows:
+C     it decreases linearly with heights from the ground 
+C     to the low-level indicated by kkcrith,
+C     to simulates lee waves or 
+C     low-level gravity wave breaking.
+C     above it is constant, except when the waves encounter a critical
+C     level (kcrit) or when they break.
+C     The stress is also uniformly distributed above the level
+C     nstra.                                          
+C
+      USE dimphy
+      IMPLICIT NONE
+
+cym#include "dimensions.h"
+cym#include "dimphy.h"
+#include "YOMCST.h"
+#include "YOEGWD.h"
+
+C-----------------------------------------------------------------------
+C
+C*       0.1   ARGUMENTS
+C              ---------
+C
+      integer nlon,nlev,kgwd
+      integer kkcrit(nlon),kkcrith(nlon),kcrit(nlon)
+     *       ,kdx(nlon),ktest(nlon)
+     *       ,kkenvh(nlon),kknu(nlon),kknu2(nlon)
+C
+      real paphm1(nlon,nlev+1), pstab(nlon,nlev+1),
+     *     prho  (nlon,nlev+1), pvph (nlon,nlev+1),
+     *     pri   (nlon,nlev+1), ptfr (nlon), ptau(nlon,nlev+1)
+     
+      real pdmod (nlon) , pnu (nlon) , psig(nlon),
+     *     pgamma(nlon) , pstd(nlon) , ppic(nlon), pval(nlon)
+     
+C-----------------------------------------------------------------------
+C
+C*       0.2   local arrays
+C              ------------
+C
+      integer jl,jk
+      real zsqr,zalfa,zriw,zdel,zb,zalpha,zdz2n,zdelp,zdelpt
+
+      real zdz2 (klon,klev) , znorm(klon) , zoro(klon)
+      real ztau (klon,klev+1)
+C
+C-----------------------------------------------------------------------
+C
+C*         1.    INITIALIZATION
+C                --------------
+C
+C      print *,' entree gwprofil' 
+ 100  CONTINUE
+C
+C
+C*    COMPUTATIONAL CONSTANTS.
+C     ------------- ----------
+C
+      do 400 jl=kidia,kfdia
+      if(ktest(jl).eq.1)then
+      zoro(jl)=psig(jl)*pdmod(jl)/4./pstd(jl)
+      ztau(jl,klev+1)=ptau(jl,klev+1)
+c     print *,jl,ptau(jl,klev+1)
+      ztau(jl,kkcrith(jl))=grahilo*ptau(jl,klev+1)
+      endif
+  400 continue
+  
+C
+      do 430 jk=klev+1,1,-1
+C
+C
+C*         4.1    constant shear stress until top of the
+C                 low-level breaking/trapped layer
+  410 CONTINUE
+C
+      do 411 jl=kidia,kfdia
+      if(ktest(jl).eq.1)then
+           if(jk.gt.kkcrith(jl)) then
+           zdelp=paphm1(jl,jk)-paphm1(jl,klev+1) 
+           zdelpt=paphm1(jl,kkcrith(jl))-paphm1(jl,klev+1) 
+           ptau(jl,jk)=ztau(jl,klev+1)+zdelp/zdelpt*
+     c                 (ztau(jl,kkcrith(jl))-ztau(jl,klev+1))
+           else                    
+           ptau(jl,jk)=ztau(jl,kkcrith(jl))
+           endif
+       endif
+ 411  continue             
+C
+C*         4.15   constant shear stress until the top of the
+C                 low level flow layer.
+ 415  continue
+C        
+C
+C*         4.2    wave displacement at next level.
+C
+  420 continue
+C
+  430 continue
+
+C
+C*         4.4    wave richardson number, new wave displacement
+C*                and stress:  breaking evaluation and critical 
+C                 level
+C
+                          
+      do 440 jk=klev,1,-1
+
+      do 441 jl=kidia,kfdia
+      if(ktest(jl).eq.1)then
+      znorm(jl)=prho(jl,jk)*sqrt(pstab(jl,jk))*pvph(jl,jk)
+      zdz2(jl,jk)=ptau(jl,jk)/amax1(znorm(jl),gssec)/zoro(jl)
+      endif
+  441 continue
+
+      do 442 jl=kidia,kfdia
+      if(ktest(jl).eq.1)then
+          if(jk.lt.kkcrith(jl)) then
+          if((ptau(jl,jk+1).lt.gtsec).or.(jk.le.kcrit(jl))) then
+             ptau(jl,jk)=0.0
+          else
+               zsqr=sqrt(pri(jl,jk))
+               zalfa=sqrt(pstab(jl,jk)*zdz2(jl,jk))/pvph(jl,jk)
+               zriw=pri(jl,jk)*(1.-zalfa)/(1+zalfa*zsqr)**2
+               if(zriw.lt.grcrit) then
+C                 print *,' breaking!!!',ptau(jl,jk)
+                  zdel=4./zsqr/grcrit+1./grcrit**2+4./grcrit
+                  zb=1./grcrit+2./zsqr
+                  zalpha=0.5*(-zb+sqrt(zdel))
+                  zdz2n=(pvph(jl,jk)*zalpha)**2/pstab(jl,jk)
+                  ptau(jl,jk)=znorm(jl)*zdz2n*zoro(jl)
+               endif
+                
+               ptau(jl,jk)=amin1(ptau(jl,jk),ptau(jl,jk+1))
+                  
+          endif
+          endif
+      endif
+  442 continue
+  440 continue
+
+C  REORGANISATION OF THE STRESS PROFILE AT LOW LEVEL
+
+      do 530 jl=kidia,kfdia
+      if(ktest(jl).eq.1)then
+         ztau(jl,kkcrith(jl)-1)=ptau(jl,kkcrith(jl)-1)
+         ztau(jl,nstra)=ptau(jl,nstra)
+      endif
+ 530  continue      
+
+      do 531 jk=1,klev
+      
+      do 532 jl=kidia,kfdia
+      if(ktest(jl).eq.1)then
+                
+         if(jk.gt.kkcrith(jl)-1)then
+
+          zdelp=paphm1(jl,jk)-paphm1(jl,klev+1    )
+          zdelpt=paphm1(jl,kkcrith(jl)-1)-paphm1(jl,klev+1    )
+          ptau(jl,jk)=ztau(jl,klev+1    ) +
+     .                (ztau(jl,kkcrith(jl)-1)-ztau(jl,klev+1    ) )*
+     .                zdelp/zdelpt
+     
+        endif
+      endif
+            
+ 532  continue    
+ 
+C  REORGANISATION AT THE MODEL TOP....
+
+      do 533 jl=kidia,kfdia
+      if(ktest(jl).eq.1)then
+
+         if(jk.lt.nstra)then
+
+          zdelp =paphm1(jl,nstra)
+          zdelpt=paphm1(jl,jk)
+          ptau(jl,jk)=ztau(jl,nstra)*zdelpt/zdelp 
+c         ptau(jl,jk)=ztau(jl,nstra)                
+
+        endif
+
+      endif
+
+ 533  continue
+
+ 
+ 531  continue        
+
+
+ 123   format(i4,1x,20(f6.3,1x))
+
+
+      return
+      end
+      subroutine lift_noro_strato (nlon,nlev,dtime,paprs,pplay,      
+     i                   plat,pmea,pstd, psig, pgam, pthe, ppic,pval,
+     i                   kgwd,kdx,ktest,
+     i                   t, u, v,
+     o                   pulow, pvlow, pustr, pvstr,
+     o                   d_t, d_u, d_v)
+c
+      USE dimphy
+      implicit none
+c======================================================================
+c Auteur(s): F.Lott (LMD/CNRS) date: 19950201
+c Object: Mountain lift interface (enhanced vortex stretching).
+c         Made necessary because:
+C 1. in the LMD-GCM Layers are from bottom to top,
+C    contrary to most European GCM.
+c 2. the altitude above ground of each model layers
+c    needs to be known (variable zgeom)
+c======================================================================
+c Explicit Arguments:
+c ==================
+c nlon----input-I-Total number of horizontal points that get into physics
+c nlev----input-I-Number of vertical levels
+c dtime---input-R-Time-step (s)
+c paprs---input-R-Pressure in semi layers    (Pa)
+c pplay---input-R-Pressure model-layers      (Pa)
+c t-------input-R-temperature (K)
+c u-------input-R-Horizontal wind (m/s)
+c v-------input-R-Meridional wind (m/s)
+c pmea----input-R-Mean Orography (m)
+C pstd----input-R-SSO standard deviation (m)
+c psig----input-R-SSO slope
+c pgam----input-R-SSO Anisotropy
+c pthe----input-R-SSO Angle
+c ppic----input-R-SSO Peacks elevation (m)
+c pval----input-R-SSO Valleys elevation (m)
+c
+c kgwd- -input-I: Total nb of points where the orography schemes are active
+c ktest--input-I: Flags to indicate active points
+c kdx----input-I: Locate the physical location of an active point.
+
+c pulow, pvlow -output-R: Low-level wind
+c pustr, pvstr -output-R: Surface stress due to SSO drag      (Pa)
+c
+c d_t-----output-R: T increment
+c d_u-----output-R: U increment
+c d_v-----output-R: V increment
+c
+c Implicit Arguments:
+c ===================
+c
+c iim--common-I: Number of longitude intervals
+c jjm--common-I: Number of latitude intervals
+c klon-common-I: Number of points seen by the physics
+c                (iim+1)*(jjm+1) for instance
+c klev-common-I: Number of vertical layers
+c======================================================================
+c Local Variables:
+c ================
+c
+c zgeom-----R: Altitude of layer above ground
+c pt, pu, pv --R: t u v from top to bottom
+c pdtdt, pdudt, pdvdt --R: t u v tendencies (from top to bottom)
+c papmf: pressure at model layer (from top to bottom)
+c papmh: pressure at model 1/2 layer (from top to bottom)
+c
+c======================================================================
+
+cym#include "dimensions.h"
+cym#include "dimphy.h"
+#include "YOMCST.h"
+#include "YOEGWD.h"
+c
+c ARGUMENTS
+c
+      INTEGER nlon,nlev
+      REAL dtime
+      REAL paprs(klon,klev+1)
+      REAL pplay(klon,klev)
+      REAL plat(nlon),pmea(nlon)
+      REAL pstd(nlon),psig(nlon),pgam(nlon),pthe(nlon)
+      REAL ppic(nlon),pval(nlon)
+      REAL pulow(nlon),pvlow(nlon),pustr(nlon),pvstr(nlon)
+      REAL t(nlon,nlev), u(nlon,nlev), v(nlon,nlev)
+      REAL d_t(nlon,nlev), d_u(nlon,nlev), d_v(nlon,nlev)
+c
+      INTEGER i, k, kgwd,  kdx(nlon), ktest(nlon)
+c
+c Variables locales:
+c
+      REAL zgeom(klon,klev)
+      REAL pdtdt(klon,klev), pdudt(klon,klev), pdvdt(klon,klev)
+      REAL pt(klon,klev), pu(klon,klev), pv(klon,klev)
+      REAL papmf(klon,klev),papmh(klon,klev+1)
+c
+c initialiser les variables de sortie (pour securite)
+c
+
+c     print *,'in lift_noro'
+      DO i = 1,klon
+         pulow(i) = 0.0
+         pvlow(i) = 0.0
+         pustr(i) = 0.0
+         pvstr(i) = 0.0
+      ENDDO
+      DO k = 1, klev
+      DO i = 1, klon
+         d_t(i,k) = 0.0
+         d_u(i,k) = 0.0
+         d_v(i,k) = 0.0
+         pdudt(i,k)=0.0
+         pdvdt(i,k)=0.0
+         pdtdt(i,k)=0.0
+      ENDDO
+      ENDDO
+c
+c preparer les variables d'entree (attention: l'ordre des niveaux 
+c verticaux augmente du haut vers le bas)
+c
+      DO k = 1, klev
+      DO i = 1, klon
+         pt(i,k) = t(i,klev-k+1) 
+         pu(i,k) = u(i,klev-k+1)
+         pv(i,k) = v(i,klev-k+1)
+         papmf(i,k) = pplay(i,klev-k+1)
+      ENDDO
+      ENDDO
+      DO k = 1, klev+1
+      DO i = 1, klon
+         papmh(i,k) = paprs(i,klev-k+2)
+      ENDDO
+      ENDDO
+      DO i = 1, klon
+         zgeom(i,klev) = RD * pt(i,klev)
+     .                  * LOG(papmh(i,klev+1)/papmf(i,klev))
+      ENDDO
+      DO k = klev-1, 1, -1
+      DO i = 1, klon
+         zgeom(i,k) = zgeom(i,k+1) + RD * (pt(i,k)+pt(i,k+1))/2.0
+     .               * LOG(papmf(i,k+1)/papmf(i,k))
+      ENDDO
+      ENDDO
+c
+c appeler la routine principale
+c
+
+      CALL OROLIFT_strato(klon,klev,kgwd,kdx,ktest,
+     .            dtime,
+     .            papmh, papmf, zgeom,
+     .            pt, pu, pv,
+     .            plat,pmea, pstd, psig, pgam, pthe, ppic,pval,
+     .            pulow,pvlow,
+     .            pdudt,pdvdt,pdtdt)
+C
+      DO k = 1, klev
+      DO i = 1, klon
+         d_u(i,klev+1-k) = dtime*pdudt(i,k)
+         d_v(i,klev+1-k) = dtime*pdvdt(i,k)
+         d_t(i,klev+1-k) = dtime*pdtdt(i,k)
+         pustr(i)        = pustr(i)
+     .                    +pdudt(i,k)*(papmh(i,k+1)-papmh(i,k))/rg
+         pvstr(i)        = pvstr(i)
+     .                    +pdvdt(i,k)*(papmh(i,k+1)-papmh(i,k))/rg
+      ENDDO
+      ENDDO
+
+c     print *,' out lift_noro'
+c
+      RETURN
+      END
+      subroutine orolift_strato( nlon,nlev
+     I                 , kgwd, kdx, ktest
+     R                 , ptsphy
+     R                 , paphm1,papm1,pgeom1,ptm1,pum1,pvm1
+     R                 , plat
+     R                 , pmea, pstd, psig, pgam, pthe,ppic,pval
+C OUTPUTS
+     R                 , pulow,pvlow
+     R                 , pvom,pvol,pte )
+
+C
+C**** *OROLIFT: SIMULATE THE GEOSTROPHIC LIFT.
+C
+C     PURPOSE.
+C     --------
+C this routine computes the physical tendencies of the
+C prognostic variables u,v  when enhanced vortex stretching
+C is needed.
+C
+C**   INTERFACE.
+C     ----------
+C          CALLED FROM *lift_noro
+c        explicit arguments :
+c        --------------------
+c     ==== inputs ===
+c nlon----input-I-Total number of horizontal points that get into physics
+c nlev----input-I-Number of vertical levels
+c
+c kgwd- -input-I: Total nb of points where the orography schemes are active
+c ktest--input-I: Flags to indicate active points
+c kdx----input-I: Locate the physical location of an active point.
+c ptsphy--input-R-Time-step (s)
+c paphm1--input-R: pressure at model 1/2 layer
+c papm1---input-R: pressure at model layer
+c pgeom1--input-R: Altitude of layer above ground
+c ptm1, pum1, pvm1--R-: t, u and v
+c pmea----input-R-Mean Orography (m)
+C pstd----input-R-SSO standard deviation (m)
+c psig----input-R-SSO slope
+c pgam----input-R-SSO Anisotropy
+c pthe----input-R-SSO Angle
+c ppic----input-R-SSO Peacks elevation (m)
+c pval----input-R-SSO Valleys elevation (m)
+c plat----input-R-Latitude (degree)
+c
+c     ==== outputs ===
+c pulow, pvlow -output-R: Low-level wind
+c
+c pte -----output-R: T tendency
+c pvom-----output-R: U tendency
+c pvol-----output-R: V tendency
+c
+c
+c Implicit Arguments:
+c ===================
+c
+c klon-common-I: Number of points seen by the physics
+c klev-common-I: Number of vertical layers
+c
+
+C     ----------
+C
+C     AUTHOR.
+C     -------
+C     F.LOTT  LMD 22/11/95
+C
+       USE dimphy
+       implicit none
+C
+C
+cym#include "dimensions.h"
+cym#include "dimphy.h"
+#include "YOMCST.h"
+#include "YOEGWD.h"
+C-----------------------------------------------------------------------
+C
+C*       0.1   ARGUMENTS
+C              ---------
+C
+C
+      integer nlon,nlev,kgwd
+      real ptsphy
+      real  pte(nlon,nlev),
+     *      pvol(nlon,nlev),
+     *      pvom(nlon,nlev),
+     *      pulow(nlon),
+     *      pvlow(nlon)
+      real  pum1(nlon,nlev),
+     *      pvm1(nlon,nlev),
+     *      ptm1(nlon,nlev),
+     *      plat(nlon),pmea(nlon),
+     *      pstd(nlon),psig(nlon),pgam(nlon),
+     *      pthe(nlon),ppic(nlon),pval(nlon),
+     *      pgeom1(nlon,nlev),
+     *      papm1(nlon,nlev),
+     *      paphm1(nlon,nlev+1)
+C
+      INTEGER  KDX(NLON),KTEST(NLON)
+C-----------------------------------------------------------------------
+C
+C*       0.2   local arrays
+
+      integer jl,ilevh,jk
+      real zhgeo,zdelp,zslow,zsqua,zscav,zbet
+C              ------------
+      integer  iknub(klon),
+     *         iknul(klon)
+      logical ll1(klon,klev+1)
+C
+      real   ztau(klon,klev+1),
+     *       ztav(klon,klev+1),
+     *       zrho(klon,klev+1)
+      real   zdudt(klon),
+     *       zdvdt(klon)
+      real zhcrit(klon,klev)
+
+      logical lifthigh
+      real zcons1,ztmst
+      CHARACTER (LEN=20) :: modname='orolift_strato'
+      CHARACTER (LEN=80) :: abort_message
+
+
+C-----------------------------------------------------------------------
+C
+C*         1.1  initialisations
+C               ---------------
+
+      lifthigh=.false.
+
+      if(nlon.ne.klon.or.nlev.ne.klev) then
+        abort_message = 'pb dimension'
+        CALL abort_gcm (modname,abort_message,1)
+      ENDIF
+      zcons1=1./rd
+      ztmst=ptsphy
+C
+      do 1001 jl=kidia,kfdia
+      zrho(jl,klev+1)  =0.0
+      pulow(jl)        =0.0
+      pvlow(jl)        =0.0
+      iknub(JL)   =klev
+      iknul(JL)   =klev
+      ilevh=klev/3
+      ll1(jl,klev+1)=.false.
+      do 1000 jk=1,klev
+      pvom(jl,jk)=0.0
+      pvol(jl,jk)=0.0
+      pte (jl,jk)=0.0
+ 1000 continue
+ 1001 continue
+
+C
+C*         2.1     DEFINE LOW LEVEL WIND, PROJECT WINDS IN PLANE OF
+C*                 LOW LEVEL WIND, DETERMINE SECTOR IN WHICH TO TAKE
+C*                 THE VARIANCE AND SET INDICATOR FOR CRITICAL LEVELS.
+C
+C
+C
+      do 2006 jk=klev,1,-1
+      do 2007 jl=kidia,kfdia
+      if(ktest(jl).eq.1) then
+      zhcrit(jl,jk)=amax1(ppic(jl)-pval(jl),100.)
+      zhgeo=pgeom1(jl,jk)/rg
+      ll1(jl,jk)=(zhgeo.gt.zhcrit(jl,jk))
+      if(ll1(jl,jk).neqv.ll1(jl,jk+1)) then
+        iknub(jl)=jk
+      endif
+      endif
+ 2007 continue
+ 2006 continue
+C
+
+      do 2010 jl=kidia,kfdia
+      if(ktest(jl).eq.1) then
+      iknub(jl)=max(iknub(jl),klev/2)
+      iknul(jl)=max(iknul(jl),2*klev/3)
+      if(iknub(jl).gt.nktopg) iknub(jl)=nktopg
+      if(iknub(jl).eq.nktopg) iknul(jl)=klev
+      if(iknub(jl).eq.iknul(jl)) iknub(jl)=iknul(jl)-1
+      endif
+ 2010 continue
+
+      do 223 jk=klev,2,-1
+      do 222 jl=kidia,kfdia
+        zrho(jl,jk)=2.*paphm1(jl,jk)*zcons1/(ptm1(jl,jk)+ptm1(jl,jk-1))
+  222 continue
+  223 continue
+c     print *,'  dans orolift: 223'
+
+C********************************************************************
+C
+c*     define low level flow
+C      -------------------
+      do 2115 jk=klev,1,-1
+      do 2116 jl=kidia,kfdia
+      if(ktest(jl).eq.1) THEN
+      if(jk.ge.iknub(jl).and.jk.le.iknul(jl)) then
+        pulow(JL)=pulow(JL)+pum1(jl,jk)*(paphm1(jl,jk+1)-paphm1(jl,jk))
+        pvlow(JL)=pvlow(JL)+pvm1(jl,jk)*(paphm1(jl,jk+1)-paphm1(jl,jk))
+        zrho(JL,klev+1)=zrho(JL,klev+1)
+     *                 +zrho(JL,JK)*(paphm1(jl,jk+1)-paphm1(jl,jk))
+      endif
+      endif
+ 2116 continue
+ 2115 continue
+      do 2110 jl=kidia,kfdia
+      if(ktest(jl).eq.1) then
+      pulow(JL)=pulow(JL)/(paphm1(jl,iknul(jl)+1)-paphm1(jl,iknub(jl)))
+      pvlow(JL)=pvlow(JL)/(paphm1(jl,iknul(jl)+1)-paphm1(jl,iknub(jl)))
+      zrho(JL,klev+1)=zrho(Jl,klev+1)
+     *               /(paphm1(jl,iknul(jl)+1)-paphm1(jl,iknub(jl)))
+      endif
+ 2110 continue
+
+
+200   continue
+
+C***********************************************************
+C
+C*         3.      COMPUTE MOUNTAIN LIFT
+C
+  300 continue
+C
+      do 301 jl=kidia,kfdia
+      if(ktest(jl).eq.1) then
+       ztau(jl,klev+1)= - gklift*zrho(jl,klev+1)*2.*romega*
+c    *                 (2*pstd(jl)+pmea(jl))*
+     *                 2*pstd(jl)*
+     *                 sin(rpi/180.*plat(jl))*pvlow(jl)
+       ztav(jl,klev+1)=   gklift*zrho(jl,klev+1)*2.*romega*
+c    *                 (2*pstd(jl)+pmea(jl))*
+     *                 2*pstd(jl)*
+     *                 sin(rpi/180.*plat(jl))*pulow(jl)
+      else
+       ztau(jl,klev+1)=0.0
+       ztav(jl,klev+1)=0.0
+      endif
+301   continue
+
+C
+C*         4.      COMPUTE LIFT PROFILE         
+C*                 --------------------   
+C
+
+  400 continue
+
+      do 401 jk=1,klev
+      do 401 jl=kidia,kfdia
+      if(ktest(jl).eq.1) then
+      ztau(jl,jk)=ztau(jl,klev+1)*paphm1(jl,jk)/paphm1(jl,klev+1)
+      ztav(jl,jk)=ztav(jl,klev+1)*paphm1(jl,jk)/paphm1(jl,klev+1)
+      else
+      ztau(jl,jk)=0.0
+      ztav(jl,jk)=0.0
+      endif
+401   continue
+C
+C
+C*         5.      COMPUTE TENDENCIES.
+C*                 -------------------
+      if(lifthigh)then
+C
+  500 continue
+C
+C  EXPLICIT SOLUTION AT ALL LEVELS
+C
+      do 524 jk=1,klev
+      do 523 jl=kidia,kfdia
+      if(ktest(jl).eq.1) then
+      zdelp=paphm1(jl,jk+1)-paphm1(jl,jk)
+      zdudt(jl)=-rg*(ztau(jl,jk+1)-ztau(jl,jk))/zdelp
+      zdvdt(jl)=-rg*(ztav(jl,jk+1)-ztav(jl,jk))/zdelp
+      endif  
+  523 continue
+  524 continue
+C
+C  PROJECT PERPENDICULARLY TO U NOT TO DESTROY ENERGY
+C
+      do 530 jk=1,klev
+      do 530 jl=kidia,kfdia
+      if(ktest(jl).eq.1) then
+
+        zslow=sqrt(pulow(jl)**2+pvlow(jl)**2)
+        zsqua=amax1(sqrt(pum1(jl,jk)**2+pvm1(jl,jk)**2),gvsec)
+        zscav=-zdudt(jl)*pvm1(jl,jk)+zdvdt(jl)*pum1(jl,jk)
+        if(zsqua.gt.gvsec)then
+          pvom(jl,jk)=-zscav*pvm1(jl,jk)/zsqua**2
+          pvol(jl,jk)= zscav*pum1(jl,jk)/zsqua**2
+        else
+          pvom(jl,jk)=0.0
+          pvol(jl,jk)=0.0      
+        endif  
+        zsqua=sqrt(pum1(jl,jk)**2+pum1(jl,jk)**2)               
+        if(zsqua.lt.zslow)then
+          pvom(jl,jk)=zsqua/zslow*pvom(jl,jk)
+          pvol(jl,jk)=zsqua/zslow*pvol(jl,jk)
+        endif 
+
+      endif  
+530   continue
+C
+C  6.  LOW LEVEL LIFT, SEMI IMPLICIT:
+C  ----------------------------------
+
+      else
+
+        do 601 jl=kidia,kfdia
+        if(ktest(jl).eq.1) then
+          do jk=klev,iknub(jl),-1
+          zbet=gklift*2.*romega*sin(rpi/180.*plat(jl))*ztmst*
+     *        (pgeom1(jl,iknub(jl)-1)-pgeom1(jl,  jk))/
+     *        (pgeom1(jl,iknub(jl)-1)-pgeom1(jl,klev))
+          zdudt(jl)=-pum1(jl,jk)/ztmst/(1+zbet**2)
+          zdvdt(jl)=-pvm1(jl,jk)/ztmst/(1+zbet**2)
+          pvom(jl,jk)= zbet**2*zdudt(jl) - zbet   *zdvdt(jl)
+          pvol(jl,jk)= zbet   *zdudt(jl) + zbet**2*zdvdt(jl)    
+          enddo
+        endif
+ 601    continue
+
+      endif
+
+c     print *,' out orolift'
+
+      return
+      end
+      SUBROUTINE SUGWD_strato(NLON,NLEV,paprs,pplay)
+C     
+C
+C**** *SUGWD* INITIALIZE COMMON YOEGWD CONTROLLING GRAVITY WAVE DRAG
+C
+C     PURPOSE.
+C     --------
+C           INITIALIZE YOEGWD, THE COMMON THAT CONTROLS THE
+C           GRAVITY WAVE DRAG PARAMETRIZATION.
+C    VERY IMPORTANT:
+C    ______________
+C           THIS ROUTINE SET_UP THE "TUNABLE PARAMETERS" OF THE
+C           VARIOUS SSO SCHEMES
+C
+C**   INTERFACE.
+C     ----------
+C        CALL *SUGWD* FROM *SUPHEC*
+C              -----        ------
+C
+C        EXPLICIT ARGUMENTS :
+C        --------------------
+C        PAPRS,PPLAY : Pressure at semi and full model levels
+C        NLEV        : number of model levels
+c        NLON        : number of points treated in the physics
+C
+C        IMPLICIT ARGUMENTS :
+C        --------------------
+C        COMMON YOEGWD
+C-GFRCRIT-R:  Critical Non-dimensional mountain Height
+C             (HNC in (1),    LOTT 1999)
+C-GKWAKE--R:  Bluff-body drag coefficient for low level wake
+C             (Cd in (2),     LOTT 1999)
+C-GRCRIT--R:  Critical Richardson Number 
+C             (Ric, End of first column p791 of LOTT 1999) 
+C-GKDRAG--R:  Gravity wave drag coefficient
+C             (G in (3),      LOTT 1999)
+C-GKLIFT--R:  Mountain Lift coefficient
+C             (Cl in (4),     LOTT 1999)
+C-GHMAX---R:  Not used
+C-GRAHILO-R:  Set-up the trapped waves fraction
+C             (Beta , End of first column,  LOTT 1999)
+C
+C-GSIGCR--R:  Security value for blocked flow depth
+C-NKTOPG--I:  Security value for blocked flow level
+C-nstra----I:  An estimate to qualify the upper levels of
+C             the model where one wants to impose strees
+C             profiles
+C-GSSECC--R:  Security min value for low-level B-V frequency
+C-GTSEC---R:  Security min value for anisotropy and GW stress.
+C-GVSEC---R:  Security min value for ulow
+C         
+C
+C     METHOD.
+C     -------
+C        SEE DOCUMENTATION
+C
+C     EXTERNALS.
+C     ----------
+C        NONE
+C
+C     REFERENCE.
+C     ----------
+C     Lott, 1999: Alleviation of stationary biases in a GCM through...
+C                 Monthly Weather Review, 127, pp 788-801.
+C
+C     AUTHOR.
+C     -------
+C        FRANCOIS LOTT        *LMD*
+C
+C     MODIFICATIONS.
+C     --------------
+C        ORIGINAL : 90-01-01 (MARTIN MILLER, ECMWF)
+C        LAST:  99-07-09     (FRANCOIS LOTT,LMD)
+C     ------------------------------------------------------------------
+      USE dimphy
+      USE mod_phys_lmdz_para
+      USE mod_grid_phy_lmdz
+      IMPLICIT NONE
+C
+C     -----------------------------------------------------------------
+#include "YOEGWD.h"
+C      ----------------------------------------------------------------
+C
+C  ARGUMENTS
+      integer nlon,nlev
+      REAL paprs(nlon,nlev+1)
+      REAL pplay(nlon,nlev)
+C
+      INTEGER JK
+      REAL ZPR,ZTOP,ZSIGT,ZPM1R
+      REAL :: pplay_glo(klon_glo,nlev)
+      REAL :: paprs_glo(klon_glo,nlev+1)
+
+C
+C*       1.    SET THE VALUES OF THE PARAMETERS
+C              --------------------------------
+C
+ 100  CONTINUE
+C
+      PRINT *,' DANS SUGWD NLEV=',NLEV
+      GHMAX=10000.
+C
+      ZPR=100000.
+      ZTOP=0.001 
+      ZSIGT=0.94
+cold  ZPR=80000.
+cold  ZSIGT=0.85
+C
+      CALL gather(pplay,pplay_glo)
+      CALL bcast(pplay_glo)
+      CALL gather(paprs,paprs_glo)
+      CALL bcast(paprs_glo)
+
+      DO 110 JK=1,NLEV
+      ZPM1R=pplay_glo(klon_glo/2+1,jk)/paprs_glo(klon_glo/2+1,1) 
+      IF(ZPM1R.GE.ZSIGT)THEN
+         nktopg=JK
+      ENDIF
+      ZPM1R=pplay_glo(klon_glo/2+1,jk)/paprs_glo(klon_glo/2+1,1) 
+      IF(ZPM1R.GE.ZTOP)THEN
+         nstra=JK
+      ENDIF
+  110 CONTINUE
+c
+c  inversion car dans orodrag on compte les niveaux a l'envers
+      nktopg=nlev-nktopg+1
+      nstra=nlev-nstra
+      print *,' DANS SUGWD nktopg=', nktopg
+      print *,' DANS SUGWD nstra=', nstra
+C
+      GSIGCR=0.80
+C
+      GKDRAG=0.1875
+      GRAHILO=0.1   
+      GRCRIT=1.00 
+      GFRCRIT=1.00
+      GKWAKE=0.50
+C
+      GKLIFT=0.25
+      GVCRIT =0.1
+
+      WRITE(UNIT=6,FMT='('' *** SSO essential constants ***'')')
+      WRITE(UNIT=6,FMT='('' *** SPECIFIED IN SUGWD ***'')')
+      WRITE(UNIT=6,FMT='('' Gravity wave ct '',E13.7,'' '')')GKDRAG
+      WRITE(UNIT=6,FMT='('' Trapped/total wave dag '',E13.7,'' '')')
+     S      GRAHILO
+      WRITE(UNIT=6,FMT='('' Critical Richardson   = '',E13.7,'' '')')
+     S                  GRCRIT
+      WRITE(UNIT=6,FMT='('' Critical Froude'',e13.7)') GFRCRIT
+      WRITE(UNIT=6,FMT='('' Low level Wake bluff cte'',e13.7)') GKWAKE
+      WRITE(UNIT=6,FMT='('' Low level lift  cte'',e13.7)') GKLIFT
+
+C
+C
+C      ----------------------------------------------------------------
+C
+C*       2.    SET VALUES OF SECURITY PARAMETERS
+C              ---------------------------------
+C
+ 200  CONTINUE
+C
+      GVSEC=0.10
+      GSSEC=0.0001
+C
+      GTSEC=0.00001
+C
+      RETURN
+      END
+
Index: LMDZ5/branches/testing/libf/phy1d/surf_land_bucket_mod.F90
===================================================================
--- LMDZ5/branches/testing/libf/phy1d/surf_land_bucket_mod.F90	(revision 1665)
+++ LMDZ5/branches/testing/libf/phy1d/surf_land_bucket_mod.F90	(revision 1665)
@@ -0,0 +1,178 @@
+!
+MODULE surf_land_bucket_mod
+!
+! Surface land bucket module
+!
+! This module is used when no external land model is choosen.
+!
+  IMPLICIT NONE
+
+CONTAINS
+
+  SUBROUTINE surf_land_bucket(itime, jour, knon, knindex, debut, dtime,&
+       tsurf, p1lay, tq_cdrag, precip_rain, precip_snow, temp_air, &
+       spechum, petAcoef, peqAcoef, petBcoef, peqBcoef, pref, &
+       u1, v1, rugoro, swnet, lwnet, &
+       snow, qsol, agesno, tsoil, &
+       qsurf, z0_new, alb1_new, alb2_new, evap, &
+       fluxsens, fluxlat, tsurf_new, dflux_s, dflux_l)
+
+    USE limit_read_mod
+    USE surface_data
+    USE fonte_neige_mod
+    USE calcul_fluxs_mod
+    USE cpl_mod
+    USE dimphy
+    USE mod_grid_phy_lmdz
+    USE mod_phys_lmdz_para
+!****************************************************************************************
+! Bucket calculations for surface. 
+!
+    INCLUDE "clesphys.h"
+    INCLUDE "indicesol.h"
+    INCLUDE "dimsoil.h"
+    INCLUDE "YOMCST.h"
+
+! Input variables  
+!****************************************************************************************
+    INTEGER, INTENT(IN)                     :: itime, jour, knon
+    INTEGER, DIMENSION(klon), INTENT(IN)    :: knindex
+    LOGICAL, INTENT(IN)                     :: debut
+    REAL, INTENT(IN)                        :: dtime
+    REAL, DIMENSION(klon), INTENT(IN)       :: tsurf
+    REAL, DIMENSION(klon), INTENT(IN)       :: p1lay
+    REAL, DIMENSION(klon), INTENT(IN)       :: tq_cdrag
+    REAL, DIMENSION(klon), INTENT(IN)       :: precip_rain, precip_snow
+    REAL, DIMENSION(klon), INTENT(IN)       :: temp_air, spechum
+    REAL, DIMENSION(klon), INTENT(IN)       :: petAcoef, peqAcoef
+    REAL, DIMENSION(klon), INTENT(IN)       :: petBcoef, peqBcoef
+    REAL, DIMENSION(klon), INTENT(IN)       :: pref
+    REAL, DIMENSION(klon), INTENT(IN)       :: u1, v1
+    REAL, DIMENSION(klon), INTENT(IN)       :: rugoro
+    REAL, DIMENSION(klon), INTENT(IN)       :: swnet, lwnet
+
+! In/Output variables
+!****************************************************************************************
+    REAL, DIMENSION(klon), INTENT(INOUT)          :: snow, qsol
+    REAL, DIMENSION(klon), INTENT(INOUT)          :: agesno
+    REAL, DIMENSION(klon, nsoilmx), INTENT(INOUT) :: tsoil
+
+! Output variables
+!****************************************************************************************
+    REAL, DIMENSION(klon), INTENT(OUT)       :: qsurf
+    REAL, DIMENSION(klon), INTENT(OUT)       :: z0_new
+    REAL, DIMENSION(klon), INTENT(OUT)       :: alb1_new, alb2_new
+    REAL, DIMENSION(klon), INTENT(OUT)       :: evap, fluxsens, fluxlat
+    REAL, DIMENSION(klon), INTENT(OUT)       :: tsurf_new
+    REAL, DIMENSION(klon), INTENT(OUT)       :: dflux_s, dflux_l      
+
+! Local variables
+!****************************************************************************************
+    REAL, DIMENSION(klon) :: soilcap, soilflux
+    REAL, DIMENSION(klon) :: cal, beta, dif_grnd, capsol
+    REAL, DIMENSION(klon) :: alb_neig, alb_lim
+    REAL, DIMENSION(klon) :: zfra
+    REAL, DIMENSION(klon) :: radsol       ! total net radiance at surface
+    REAL, DIMENSION(klon) :: u0, v0, u1_lay, v1_lay
+    REAL, DIMENSION(klon) :: dummy_riverflow,dummy_coastalflow 
+    INTEGER               :: i
+!
+!****************************************************************************************
+
+
+!
+!* Read from limit.nc : albedo(alb_lim), length of rugosity(z0_new)
+!
+    CALL limit_read_rug_alb(itime, dtime, jour,&
+         knon, knindex, &
+         z0_new, alb_lim)
+!
+!* Calcultaion of fluxes 
+!
+
+! calculate total absorbed radiance at surface
+       radsol(:) = 0.0
+       radsol(1:knon) = swnet(1:knon) + lwnet(1:knon)
+
+! calculate constants
+    CALL calbeta(dtime, is_ter, knon, snow, qsol, beta, capsol, dif_grnd)
+       
+! calculate temperature, heat capacity and conduction flux in soil
+    IF (soil_model) THEN 
+       CALL soil(dtime, is_ter, knon, snow, tsurf, tsoil, soilcap, soilflux)
+       DO i=1, knon
+          cal(i) = RCPD / soilcap(i)
+          radsol(i) = radsol(i)  + soilflux(i)
+       END DO
+    ELSE 
+       cal(:) = RCPD * capsol(:)
+       IF (klon_glo .EQ. 1) THEN
+         cal(:) = 0.
+       ENDIF
+    ENDIF
+    
+! Suppose zero surface speed
+    u0(:)=0.0
+    v0(:)=0.0
+    u1_lay(:) = u1(:) - u0(:)
+    v1_lay(:) = v1(:) - v0(:)
+
+    CALL calcul_fluxs(knon, is_ter, dtime, &
+         tsurf, p1lay, cal, beta, tq_cdrag, pref, &
+         precip_rain, precip_snow, snow, qsurf,  &
+         radsol, dif_grnd, temp_air, spechum, u1_lay, v1_lay, &
+         petAcoef, peqAcoef, petBcoef, peqBcoef, &
+         tsurf_new, evap, fluxlat, fluxsens, dflux_s, dflux_l)
+    
+!
+!* Calculate snow height, run_off, age of snow
+!      
+    CALL fonte_neige( knon, is_ter, knindex, dtime, &
+         tsurf, precip_rain, precip_snow, &
+         snow, qsol, tsurf_new, evap)
+!
+!* Calculate the age of snow
+!
+    CALL albsno(klon,knon,dtime,agesno(:),alb_neig(:), precip_snow(:))  
+    
+    WHERE (snow(1 : knon) .LT. 0.0001) agesno(1 : knon) = 0.
+    
+    DO i=1, knon
+       zfra(i) = MAX(0.0,MIN(1.0, snow(i)/(snow(i)+10.0)))
+       alb_lim(i)  = alb_neig(i) *zfra(i) + alb_lim(i)*(1.0-zfra(i))
+    END DO
+
+!
+!* Return albedo : 
+!    alb1_new and alb2_new are here given the same values
+!
+    alb1_new(:) = 0.0
+    alb2_new(:) = 0.0
+    alb1_new(1:knon) = alb_lim(1:knon)
+    alb2_new(1:knon) = alb_lim(1:knon)
+       
+!
+!* Calculate the rugosity
+!
+    DO i = 1, knon
+       z0_new(i) = MAX(1.5e-05,SQRT(z0_new(i)**2 + rugoro(i)**2))
+    END DO
+
+!* Send to coupler
+!  The run-off from river and coast are not calculated in the bucket modele.
+!  For testing purpose of the coupled modele we put the run-off to zero.
+    IF (type_ocean=='couple') THEN
+       dummy_riverflow(:)   = 0.0
+       dummy_coastalflow(:) = 0.0
+       CALL cpl_send_land_fields(itime, knon, knindex, &
+            dummy_riverflow, dummy_coastalflow)
+    ENDIF
+
+!
+!* End
+!
+  END SUBROUTINE surf_land_bucket
+!
+!****************************************************************************************
+!
+END MODULE surf_land_bucket_mod
Index: LMDZ5/branches/testing/libf/phy1d/ttt/pbl_surface_mod.F90
===================================================================
--- LMDZ5/branches/testing/libf/phy1d/ttt/pbl_surface_mod.F90	(revision 1665)
+++ LMDZ5/branches/testing/libf/phy1d/ttt/pbl_surface_mod.F90	(revision 1665)
@@ -0,0 +1,1400 @@
+!
+! $Id: pbl_surface_mod.F90 1413 2010-07-13 07:55:22Z idelkadi $
+!
+MODULE pbl_surface_mod
+!
+! Planetary Boundary Layer and Surface module
+!
+! This module manage the calculation of turbulent diffusion in the boundary layer 
+! and all interactions towards the differents sub-surfaces.
+!
+!
+  USE dimphy
+  USE mod_phys_lmdz_para,  ONLY : mpi_size
+  USE ioipsl
+  USE surface_data,        ONLY : type_ocean, ok_veget
+  USE surf_land_mod,       ONLY : surf_land
+  USE surf_landice_mod,    ONLY : surf_landice
+  USE surf_ocean_mod,      ONLY : surf_ocean
+  USE surf_seaice_mod,     ONLY : surf_seaice
+  USE cpl_mod,             ONLY : gath2cpl
+  USE climb_hq_mod,        ONLY : climb_hq_down, climb_hq_up
+  USE climb_wind_mod,      ONLY : climb_wind_down, climb_wind_up
+  USE coef_diff_turb_mod,  ONLY : coef_diff_turb
+  USE control_mod
+
+
+  IMPLICIT NONE
+
+! Declaration of variables saved in restart file
+  REAL, ALLOCATABLE, DIMENSION(:), PRIVATE, SAVE     :: qsol   ! water height in the soil (mm)
+  !$OMP THREADPRIVATE(qsol)
+  REAL, ALLOCATABLE, DIMENSION(:), PRIVATE, SAVE     :: fder   ! flux drift
+  !$OMP THREADPRIVATE(fder)
+  REAL, ALLOCATABLE, DIMENSION(:,:), PRIVATE, SAVE   :: snow   ! snow at surface
+  !$OMP THREADPRIVATE(snow)
+  REAL, ALLOCATABLE, DIMENSION(:,:), PRIVATE, SAVE   :: qsurf  ! humidity at surface
+  !$OMP THREADPRIVATE(qsurf)
+  REAL, ALLOCATABLE, DIMENSION(:,:), PRIVATE, SAVE   :: evap   ! evaporation at surface
+  !$OMP THREADPRIVATE(evap)
+  REAL, ALLOCATABLE, DIMENSION(:,:), PRIVATE, SAVE   :: rugos  ! rugosity at surface (m)
+  !$OMP THREADPRIVATE(rugos)
+  REAL, ALLOCATABLE, DIMENSION(:,:), PRIVATE, SAVE   :: agesno ! age of snow at surface
+  !$OMP THREADPRIVATE(agesno)
+  REAL, ALLOCATABLE, DIMENSION(:,:,:), PRIVATE, SAVE :: ftsoil ! soil temperature
+  !$OMP THREADPRIVATE(ftsoil)
+
+CONTAINS
+!
+!****************************************************************************************
+!
+  SUBROUTINE pbl_surface_init(qsol_rst, fder_rst, snow_rst, qsurf_rst,&
+       evap_rst, rugos_rst, agesno_rst, ftsoil_rst)
+
+! This routine should be called after the restart file has been read.
+! This routine initialize the restart variables and does some validation tests
+! for the index of the different surfaces and tests the choice of type of ocean.
+
+    INCLUDE "indicesol.h"
+    INCLUDE "dimsoil.h"
+    INCLUDE "iniprint.h"
+ 
+! Input variables
+!****************************************************************************************
+    REAL, DIMENSION(klon), INTENT(IN)                 :: qsol_rst
+    REAL, DIMENSION(klon), INTENT(IN)                 :: fder_rst
+    REAL, DIMENSION(klon, nbsrf), INTENT(IN)          :: snow_rst
+    REAL, DIMENSION(klon, nbsrf), INTENT(IN)          :: qsurf_rst
+    REAL, DIMENSION(klon, nbsrf), INTENT(IN)          :: evap_rst
+    REAL, DIMENSION(klon, nbsrf), INTENT(IN)          :: rugos_rst
+    REAL, DIMENSION(klon, nbsrf), INTENT(IN)          :: agesno_rst
+    REAL, DIMENSION(klon, nsoilmx, nbsrf), INTENT(IN) :: ftsoil_rst
+
+  
+! Local variables
+!****************************************************************************************
+    INTEGER                       :: ierr
+    CHARACTER(len=80)             :: abort_message
+    CHARACTER(len = 20)           :: modname = 'pbl_surface_init'
+    
+
+!****************************************************************************************
+! Allocate and initialize module variables with fields read from restart file.
+!
+!****************************************************************************************    
+    ALLOCATE(qsol(klon), stat=ierr)
+    IF (ierr /= 0) CALL abort_gcm('pbl_surface_init', 'pb in allocation',1)
+
+    ALLOCATE(fder(klon), stat=ierr)
+    IF (ierr /= 0) CALL abort_gcm('pbl_surface_init', 'pb in allocation',1)
+
+    ALLOCATE(snow(klon,nbsrf), stat=ierr)
+    IF (ierr /= 0) CALL abort_gcm('pbl_surface_init', 'pb in allocation',1)
+
+    ALLOCATE(qsurf(klon,nbsrf), stat=ierr)
+    IF (ierr /= 0) CALL abort_gcm('pbl_surface_init', 'pb in allocation',1)
+
+    ALLOCATE(evap(klon,nbsrf), stat=ierr)
+    IF (ierr /= 0) CALL abort_gcm('pbl_surface_init', 'pb in allocation',1)
+
+    ALLOCATE(rugos(klon,nbsrf), stat=ierr)
+    IF (ierr /= 0) CALL abort_gcm('pbl_surface_init', 'pb in allocation',1)
+
+    ALLOCATE(agesno(klon,nbsrf), stat=ierr)
+    IF (ierr /= 0) CALL abort_gcm('pbl_surface_init', 'pb in allocation',1)
+
+    ALLOCATE(ftsoil(klon,nsoilmx,nbsrf), stat=ierr)
+    IF (ierr /= 0) CALL abort_gcm('pbl_surface_init', 'pb in allocation',1)
+
+
+    qsol(:)       = qsol_rst(:)
+    fder(:)       = fder_rst(:)
+    snow(:,:)     = snow_rst(:,:)
+    qsurf(:,:)    = qsurf_rst(:,:)
+    evap(:,:)     = evap_rst(:,:)
+    rugos(:,:)    = rugos_rst(:,:)
+    agesno(:,:)   = agesno_rst(:,:)
+    ftsoil(:,:,:) = ftsoil_rst(:,:,:)
+
+
+!****************************************************************************************
+! Test for sub-surface indices
+!
+!****************************************************************************************
+    IF (is_ter /= 1) THEN 
+      WRITE(lunout,*)" *** Warning ***"
+      WRITE(lunout,*)" is_ter n'est pas le premier surface, is_ter = ",is_ter
+      WRITE(lunout,*)"or on doit commencer par les surfaces continentales"
+      abort_message="voir ci-dessus"
+      CALL abort_gcm(modname,abort_message,1)
+    ENDIF
+
+    IF ( is_oce > is_sic ) THEN
+      WRITE(lunout,*)' *** Warning ***'
+      WRITE(lunout,*)' Pour des raisons de sequencement dans le code'
+      WRITE(lunout,*)' l''ocean doit etre traite avant la banquise'
+      WRITE(lunout,*)' or is_oce = ',is_oce, '> is_sic = ',is_sic
+      abort_message='voir ci-dessus'
+      CALL abort_gcm(modname,abort_message,1)
+    ENDIF
+
+    IF ( is_lic > is_sic ) THEN
+      WRITE(lunout,*)' *** Warning ***'
+      WRITE(lunout,*)' Pour des raisons de sequencement dans le code'
+      WRITE(lunout,*)' la glace contineltalle doit etre traite avant la glace de mer'
+      WRITE(lunout,*)' or is_lic = ',is_lic, '> is_sic = ',is_sic
+      abort_message='voir ci-dessus'
+      CALL abort_gcm(modname,abort_message,1)
+    ENDIF
+
+!****************************************************************************************
+! Validation of ocean mode
+!
+!****************************************************************************************
+
+    IF (type_ocean /= 'slab  ' .AND. type_ocean /= 'force ' .AND. type_ocean /= 'couple') THEN
+       WRITE(lunout,*)' *** Warning ***'
+       WRITE(lunout,*)'Option couplage pour l''ocean = ', type_ocean
+       abort_message='option pour l''ocean non valable'
+       CALL abort_gcm(modname,abort_message,1)
+    ENDIF
+
+  END SUBROUTINE pbl_surface_init
+!  
+!****************************************************************************************
+!  
+
+  SUBROUTINE pbl_surface( &
+       dtime,     date0,     itap,     jour,          &
+       debut,     lafin,                              &
+       rlon,      rlat,      rugoro,   rmu0,          &
+       rain_f,    snow_f,    solsw_m,  sollw_m,       &
+       t,         q,         u,        v,             &
+       pplay,     paprs,     pctsrf,                  &
+       ts,        alb1,      alb2,     u10m,   v10m,  &
+       lwdown_m,  cdragh,    cdragm,   zu1,    zv1,   &
+       alb1_m,    alb2_m,    zxsens,   zxevap,        &
+       zxtsol,    zxfluxlat, zt2m,     qsat2m,        &
+       d_t,       d_q,       d_u,      d_v,           & 
+       zcoefh,    slab_wfbils,                        &
+       qsol_d,    zq2m,      s_pblh,   s_plcl,        &
+       s_capCL,   s_oliqCL,  s_cteiCL, s_pblT,        &
+       s_therm,   s_trmb1,   s_trmb2,  s_trmb3,       &
+       zxrugs,    zu10m,     zv10m,    fder_print,    &
+       zxqsurf,   rh2m,      zxfluxu,  zxfluxv,       &
+       rugos_d,   agesno_d,  sollw,    solsw,         &
+       d_ts,      evap_d,    fluxlat,  t2m,           &
+       wfbils,    wfbilo,    flux_t,   flux_u, flux_v,&
+       dflux_t,   dflux_q,   zxsnow,                  &
+       zxfluxt,   zxfluxq,   q2m,      flux_q, tke    )
+!****************************************************************************************
+! Auteur(s) Z.X. Li (LMD/CNRS) date: 19930818
+! Objet: interface de "couche limite" (diffusion verticale)
+!
+!AA REM:
+!AA-----
+!AA Tout ce qui a trait au traceurs est dans phytrac maintenant
+!AA pour l'instant le calcul de la couche limite pour les traceurs
+!AA se fait avec cltrac et ne tient pas compte de la differentiation
+!AA des sous-fraction de sol.
+!AA REM bis :
+!AA----------
+!AA Pour pouvoir extraire les coefficient d'echanges et le vent 
+!AA dans la premiere couche, 3 champs supplementaires ont ete crees
+!AA zcoefh, zu1 et zv1. Pour l'instant nous avons moyenne les valeurs
+!AA de ces trois champs sur les 4 subsurfaces du modele. Dans l'avenir 
+!AA si les informations des subsurfaces doivent etre prises en compte
+!AA il faudra sortir ces memes champs en leur ajoutant une dimension, 
+!AA c'est a dire nbsrf (nbre de subsurface).
+!
+! Arguments:
+!
+! dtime----input-R- interval du temps (secondes)
+! itap-----input-I- numero du pas de temps
+! date0----input-R- jour initial
+! t--------input-R- temperature (K)
+! q--------input-R- vapeur d'eau (kg/kg)
+! u--------input-R- vitesse u
+! v--------input-R- vitesse v
+! ts-------input-R- temperature du sol (en Kelvin)
+! paprs----input-R- pression a intercouche (Pa)
+! pplay----input-R- pression au milieu de couche (Pa)
+! rlat-----input-R- latitude en degree
+! rugos----input-R- longeur de rugosite (en m)
+!
+! d_t------output-R- le changement pour "t"
+! d_q------output-R- le changement pour "q"
+! d_u------output-R- le changement pour "u"
+! d_v------output-R- le changement pour "v"
+! d_ts-----output-R- le changement pour "ts"
+! flux_t---output-R- flux de chaleur sensible (CpT) J/m**2/s (W/m**2)
+!                    (orientation positive vers le bas)
+! tke---input/output-R- tke (kg/m**2/s)
+! flux_q---output-R- flux de vapeur d'eau (kg/m**2/s)
+! flux_u---output-R- tension du vent X: (kg m/s)/(m**2 s) ou Pascal
+! flux_v---output-R- tension du vent Y: (kg m/s)/(m**2 s) ou Pascal
+! dflux_t--output-R- derive du flux sensible
+! dflux_q--output-R- derive du flux latent
+! zu1------output-R- le vent dans la premiere couche
+! zv1------output-R- le vent dans la premiere couche
+! trmb1----output-R- deep_cape
+! trmb2----output-R- inhibition 
+! trmb3----output-R- Point Omega
+! cteiCL---output-R- Critere d'instab d'entrainmt des nuages de CL
+! plcl-----output-R- Niveau de condensation
+! pblh-----output-R- HCL
+! pblT-----output-R- T au nveau HCL
+!
+    USE carbon_cycle_mod, ONLY : carbon_cycle_cpl, co2_send
+    IMPLICIT NONE
+
+    INCLUDE "indicesol.h"
+    INCLUDE "dimsoil.h"
+    INCLUDE "YOMCST.h"
+    INCLUDE "iniprint.h"
+    INCLUDE "FCTTRE.h"
+    INCLUDE "clesphys.h"
+    INCLUDE "compbl.h"
+    INCLUDE "dimensions.h"
+    INCLUDE "YOETHF.h"
+    INCLUDE "temps.h"
+!****************************************************************************************
+! Declarations specifiques pour le 1D. A reprendre 
+    INCLUDE flux_arp.h
+! Input variables
+!****************************************************************************************
+    REAL,                         INTENT(IN)        :: dtime   ! time interval (s)
+    REAL,                         INTENT(IN)        :: date0   ! initial day
+    INTEGER,                      INTENT(IN)        :: itap    ! time step
+    INTEGER,                      INTENT(IN)        :: jour    ! current day of the year
+    LOGICAL,                      INTENT(IN)        :: debut   ! true if first run step
+    LOGICAL,                      INTENT(IN)        :: lafin   ! true if last run step
+    REAL, DIMENSION(klon),        INTENT(IN)        :: rlon    ! longitudes in degrees
+    REAL, DIMENSION(klon),        INTENT(IN)        :: rlat    ! latitudes in degrees
+    REAL, DIMENSION(klon),        INTENT(IN)        :: rugoro  ! rugosity length
+    REAL, DIMENSION(klon),        INTENT(IN)        :: rmu0    ! cosine of solar zenith angle
+    REAL, DIMENSION(klon),        INTENT(IN)        :: rain_f  ! rain fall
+    REAL, DIMENSION(klon),        INTENT(IN)        :: snow_f  ! snow fall
+    REAL, DIMENSION(klon),        INTENT(IN)        :: solsw_m ! net shortwave radiation at mean surface
+    REAL, DIMENSION(klon),        INTENT(IN)        :: sollw_m ! net longwave radiation at mean surface
+    REAL, DIMENSION(klon,klev),   INTENT(IN)        :: t       ! temperature (K)
+    REAL, DIMENSION(klon,klev),   INTENT(IN)        :: q       ! water vapour (kg/kg)
+    REAL, DIMENSION(klon,klev),   INTENT(IN)        :: u       ! u speed
+    REAL, DIMENSION(klon,klev),   INTENT(IN)        :: v       ! v speed
+    REAL, DIMENSION(klon,klev),   INTENT(IN)        :: pplay   ! mid-layer pression (Pa)
+    REAL, DIMENSION(klon,klev+1), INTENT(IN)        :: paprs   ! pression between layers (Pa) 
+    REAL, DIMENSION(klon, nbsrf), INTENT(IN)        :: pctsrf  ! sub-surface fraction
+
+! Input/Output variables
+!****************************************************************************************
+    REAL, DIMENSION(klon, nbsrf), INTENT(INOUT)     :: ts      ! temperature at surface (K)
+    REAL, DIMENSION(klon, nbsrf), INTENT(INOUT)     :: alb1    ! albedo in visible SW interval
+    REAL, DIMENSION(klon, nbsrf), INTENT(INOUT)     :: alb2    ! albedo in near infra-red SW interval
+    REAL, DIMENSION(klon, nbsrf), INTENT(INOUT)     :: u10m    ! u speed at 10m
+    REAL, DIMENSION(klon, nbsrf), INTENT(INOUT)     :: v10m    ! v speed at 10m
+    REAL, DIMENSION(klon, klev+1, nbsrf), INTENT(INOUT) :: tke 
+
+! Output variables
+!****************************************************************************************
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: lwdown_m   ! Downcoming longwave radiation
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: cdragh     ! drag coefficient for T and Q
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: cdragm     ! drag coefficient for wind
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: zu1        ! u wind speed in first layer
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: zv1        ! v wind speed in first layer
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: alb1_m     ! mean albedo in visible SW interval
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: alb2_m     ! mean albedo in near IR SW interval
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: zxsens     ! sensible heat flux at surface with inversed sign 
+                                                                  ! (=> positive sign upwards)
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: zxevap     ! water vapour flux at surface, positiv upwards
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: zxtsol     ! temperature at surface, mean for each grid point
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: zxfluxlat  ! latent flux, mean for each grid point
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: zt2m       ! temperature at 2m, mean for each grid point
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: qsat2m
+    REAL, DIMENSION(klon, klev),  INTENT(OUT)       :: d_t        ! change in temperature 
+    REAL, DIMENSION(klon, klev),  INTENT(OUT)       :: d_q        ! change in water vapour
+    REAL, DIMENSION(klon, klev),  INTENT(OUT)       :: d_u        ! change in u speed
+    REAL, DIMENSION(klon, klev),  INTENT(OUT)       :: d_v        ! change in v speed
+    REAL, DIMENSION(klon, klev),  INTENT(OUT)       :: zcoefh     ! coef for turbulent diffusion of T and Q, mean for each grid point
+
+! Output only for diagnostics
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: slab_wfbils! heat balance at surface only for slab at ocean points
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: qsol_d     ! water height in the soil (mm)
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: zq2m       ! water vapour at 2m, mean for each grid point
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: s_pblh     ! height of the planetary boundary layer(HPBL)
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: s_plcl     ! condensation level
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: s_capCL    ! CAPE of PBL
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: s_oliqCL   ! liquid water intergral of PBL
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: s_cteiCL   ! cloud top instab. crit. of PBL
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: s_pblT     ! temperature at PBLH
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: s_therm    ! thermal virtual temperature excess
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: s_trmb1    ! deep cape, mean for each grid point
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: s_trmb2    ! inhibition, mean for each grid point
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: s_trmb3    ! point Omega, mean for each grid point
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: zxrugs     ! rugosity at surface (m), mean for each grid point
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: zu10m      ! u speed at 10m, mean for each grid point
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: zv10m      ! v speed at 10m, mean for each grid point
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: fder_print ! fder for printing (=fder(i) + dflux_t(i) + dflux_q(i))
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: zxqsurf    ! humidity at surface, mean for each grid point
+    REAL, DIMENSION(klon),        INTENT(OUT)       :: rh2m       ! relative humidity at 2m
+    REAL, DIMENSION(klon, klev),  INTENT(OUT)       :: zxfluxu    ! u wind tension, mean for each grid point
+    REAL, DIMENSION(klon, klev),  INTENT(OUT)       :: zxfluxv    ! v wind tension, mean for each grid point
+    REAL, DIMENSION(klon, nbsrf), INTENT(OUT)       :: rugos_d    ! rugosity length (m)
+    REAL, DIMENSION(klon, nbsrf), INTENT(OUT)       :: agesno_d   ! age of snow at surface
+    REAL, DIMENSION(klon, nbsrf), INTENT(OUT)       :: solsw      ! net shortwave radiation at surface 
+    REAL, DIMENSION(klon, nbsrf), INTENT(OUT)       :: sollw      ! net longwave radiation at surface
+    REAL, DIMENSION(klon, nbsrf), INTENT(OUT)       :: d_ts       ! change in temperature at surface
+    REAL, DIMENSION(klon, nbsrf), INTENT(OUT)       :: evap_d     ! evaporation at surface
+    REAL, DIMENSION(klon, nbsrf), INTENT(OUT)       :: fluxlat    ! latent flux
+    REAL, DIMENSION(klon, nbsrf), INTENT(OUT)       :: t2m        ! temperature at 2 meter height
+    REAL, DIMENSION(klon, nbsrf), INTENT(OUT)       :: wfbils     ! heat balance at surface
+    REAL, DIMENSION(klon, nbsrf), INTENT(OUT)       :: wfbilo     ! water balance at surface
+    REAL, DIMENSION(klon, klev, nbsrf), INTENT(OUT) :: flux_t     ! sensible heat flux (CpT) J/m**2/s (W/m**2)
+                                                                  ! positve orientation downwards
+    REAL, DIMENSION(klon, klev, nbsrf), INTENT(OUT) :: flux_u     ! u wind tension (kg m/s)/(m**2 s) or Pascal
+    REAL, DIMENSION(klon, klev, nbsrf), INTENT(OUT) :: flux_v     ! v wind tension (kg m/s)/(m**2 s) or Pascal
+
+! Output not needed
+    REAL, DIMENSION(klon),       INTENT(OUT)        :: dflux_t    ! change of sensible heat flux 
+    REAL, DIMENSION(klon),       INTENT(OUT)        :: dflux_q    ! change of water vapour flux
+    REAL, DIMENSION(klon),       INTENT(OUT)        :: zxsnow     ! snow at surface, mean for each grid point
+    REAL, DIMENSION(klon, klev), INTENT(OUT)        :: zxfluxt    ! sensible heat flux, mean for each grid point
+    REAL, DIMENSION(klon, klev), INTENT(OUT)        :: zxfluxq    ! water vapour flux, mean for each grid point
+    REAL, DIMENSION(klon, nbsrf),INTENT(OUT)        :: q2m        ! water vapour at 2 meter height
+    REAL, DIMENSION(klon, klev, nbsrf), INTENT(OUT) :: flux_q     ! water vapour flux(latent flux) (kg/m**2/s)
+
+
+! Local variables with attribute SAVE
+!****************************************************************************************
+    INTEGER, SAVE                            :: nhoridbg, nidbg   ! variables for IOIPSL
+!$OMP THREADPRIVATE(nhoridbg, nidbg)
+    LOGICAL, SAVE                            :: debugindex=.FALSE.
+!$OMP THREADPRIVATE(debugindex)
+    LOGICAL, SAVE                            :: first_call=.TRUE.
+!$OMP THREADPRIVATE(first_call)
+    CHARACTER(len=8), DIMENSION(nbsrf), SAVE :: cl_surf
+!$OMP THREADPRIVATE(cl_surf)
+
+! Other local variables
+!****************************************************************************************
+    INTEGER                            :: i, k, nsrf 
+    INTEGER                            :: knon, j
+    INTEGER                            :: idayref
+    INTEGER , DIMENSION(klon)          :: ni
+    REAL                               :: zx_alf1, zx_alf2 !valeur ambiante par extrapola
+    REAL                               :: amn, amx
+    REAL                               :: f1 ! fraction de longeurs visibles parmi tout SW intervalle
+    REAL, DIMENSION(klon)              :: r_co2_ppm     ! taux CO2 atmosphere
+    REAL, DIMENSION(klon)              :: yts, yrugos, ypct, yz0_new
+    REAL, DIMENSION(klon)              :: yalb, yalb1, yalb2
+    REAL, DIMENSION(klon)              :: yu1, yv1
+    REAL, DIMENSION(klon)              :: ysnow, yqsurf, yagesno, yqsol
+    REAL, DIMENSION(klon)              :: yrain_f, ysnow_f
+    REAL, DIMENSION(klon)              :: ysolsw, ysollw
+    REAL, DIMENSION(klon)              :: yfder
+    REAL, DIMENSION(klon)              :: yrugoro
+    REAL, DIMENSION(klon)              :: yfluxlat
+    REAL, DIMENSION(klon)              :: y_d_ts
+    REAL, DIMENSION(klon)              :: y_flux_t1, y_flux_q1
+    REAL, DIMENSION(klon)              :: y_dflux_t, y_dflux_q
+    REAL, DIMENSION(klon)              :: y_flux_u1, y_flux_v1
+    REAL, DIMENSION(klon)              :: yt2m, yq2m, yu10m
+    REAL, DIMENSION(klon)              :: yustar
+    REAL, DIMENSION(klon)              :: ywindsp
+    REAL, DIMENSION(klon)              :: yt10m, yq10m
+    REAL, DIMENSION(klon)              :: ypblh
+    REAL, DIMENSION(klon)              :: ylcl
+    REAL, DIMENSION(klon)              :: ycapCL
+    REAL, DIMENSION(klon)              :: yoliqCL
+    REAL, DIMENSION(klon)              :: ycteiCL
+    REAL, DIMENSION(klon)              :: ypblT
+    REAL, DIMENSION(klon)              :: ytherm
+    REAL, DIMENSION(klon)              :: ytrmb1
+    REAL, DIMENSION(klon)              :: ytrmb2
+    REAL, DIMENSION(klon)              :: ytrmb3
+    REAL, DIMENSION(klon)              :: uzon, vmer
+    REAL, DIMENSION(klon)              :: tair1, qair1, tairsol
+    REAL, DIMENSION(klon)              :: psfce, patm
+    REAL, DIMENSION(klon)              :: qairsol, zgeo1
+    REAL, DIMENSION(klon)              :: rugo1
+    REAL, DIMENSION(klon)              :: yfluxsens
+    REAL, DIMENSION(klon)              :: AcoefH, AcoefQ, BcoefH, BcoefQ
+    REAL, DIMENSION(klon)              :: AcoefU, AcoefV, BcoefU, BcoefV
+    REAL, DIMENSION(klon)              :: ypsref
+    REAL, DIMENSION(klon)              :: yevap, ytsurf_new, yalb1_new, yalb2_new
+    REAL, DIMENSION(klon)              :: ztsol
+    REAL, DIMENSION(klon)              :: alb_m  ! mean albedo for whole SW interval
+    REAL, DIMENSION(klon,klev)         :: y_d_t, y_d_q
+    REAL, DIMENSION(klon,klev)         :: y_d_u, y_d_v
+    REAL, DIMENSION(klon,klev)         :: y_flux_t, y_flux_q
+    REAL, DIMENSION(klon,klev)         :: y_flux_u, y_flux_v
+    REAL, DIMENSION(klon,klev)         :: ycoefh, ycoefm
+    REAL, DIMENSION(klon)              :: ycdragh, ycdragm
+    REAL, DIMENSION(klon,klev)         :: yu, yv
+    REAL, DIMENSION(klon,klev)         :: yt, yq
+    REAL, DIMENSION(klon,klev)         :: ypplay, ydelp
+    REAL, DIMENSION(klon,klev)         :: delp
+    REAL, DIMENSION(klon,klev+1)       :: ypaprs
+    REAL, DIMENSION(klon,klev+1)       :: ytke
+    REAL, DIMENSION(klon,nsoilmx)      :: ytsoil
+    CHARACTER(len=80)                  :: abort_message
+    CHARACTER(len=20)                  :: modname = 'pbl_surface'
+    LOGICAL, PARAMETER                 :: zxli=.FALSE. ! utiliser un jeu de fonctions simples
+    LOGICAL, PARAMETER                 :: check=.FALSE.
+
+! For debugging with IOIPSL
+    INTEGER, DIMENSION(iim*(jjm+1))    :: ndexbg
+    REAL                               :: zjulian
+    REAL, DIMENSION(klon)              :: tabindx
+    REAL, DIMENSION(iim,jjm+1)         :: zx_lon, zx_lat
+    REAL, DIMENSION(iim,jjm+1)         :: debugtab
+
+
+    REAL, DIMENSION(klon,nbsrf)        :: pblh         ! height of the planetary boundary layer
+    REAL, DIMENSION(klon,nbsrf)        :: plcl         ! condensation level
+    REAL, DIMENSION(klon,nbsrf)        :: capCL
+    REAL, DIMENSION(klon,nbsrf)        :: oliqCL
+    REAL, DIMENSION(klon,nbsrf)        :: cteiCL
+    REAL, DIMENSION(klon,nbsrf)        :: pblT
+    REAL, DIMENSION(klon,nbsrf)        :: therm
+    REAL, DIMENSION(klon,nbsrf)        :: trmb1        ! deep cape
+    REAL, DIMENSION(klon,nbsrf)        :: trmb2        ! inhibition
+    REAL, DIMENSION(klon,nbsrf)        :: trmb3        ! point Omega
+    REAL, DIMENSION(klon,nbsrf)        :: zx_rh2m, zx_qsat2m
+    REAL, DIMENSION(klon,nbsrf)        :: zx_t1
+    REAL, DIMENSION(klon, nbsrf)       :: alb          ! mean albedo for whole SW interval
+    REAL, DIMENSION(klon)              :: ylwdown      ! jg : temporary (ysollwdown)
+
+    REAL                               :: zx_qs1, zcor1, zdelta1 
+
+!****************************************************************************************
+! Declarations specifiques pour le 1D. A reprendre 
+!****************************************************************************************
+! End of declarations
+!****************************************************************************************
+
+
+!****************************************************************************************
+! 1) Initialisation and validation tests 
+!    Only done first time entering this subroutine
+!
+!****************************************************************************************
+
+    IF (first_call) THEN
+       first_call=.FALSE.
+      
+       ! Initialize ok_flux_surf (for 1D model)
+       if (klon>1) ok_flux_surf=.FALSE.
+       
+       ! Initilize debug IO
+       IF (debugindex .AND. mpi_size==1) THEN 
+          ! initialize IOIPSL output
+          idayref = day_ini
+          CALL ymds2ju(annee_ref, 1, idayref, 0.0, zjulian)
+          CALL gr_fi_ecrit(1,klon,iim,jjm+1,rlon,zx_lon)
+          DO i = 1, iim
+             zx_lon(i,1) = rlon(i+1)
+             zx_lon(i,jjm+1) = rlon(i+1)
+          ENDDO
+          CALL gr_fi_ecrit(1,klon,iim,jjm+1,rlat,zx_lat)
+          CALL histbeg("sous_index", iim,zx_lon(:,1),jjm+1,zx_lat(1,:), &
+               1,iim,1,jjm+1, &
+               itau_phy,zjulian,dtime,nhoridbg,nidbg) 
+          ! no vertical axis
+          cl_surf(1)='ter'
+          cl_surf(2)='lic'
+          cl_surf(3)='oce'
+          cl_surf(4)='sic'
+          DO nsrf=1,nbsrf
+             CALL histdef(nidbg, cl_surf(nsrf),cl_surf(nsrf), "-",iim, &
+                  jjm+1,nhoridbg, 1, 1, 1, -99, 32, "inst", dtime,dtime) 
+          END DO
+
+          CALL histend(nidbg)
+          CALL histsync(nidbg)
+
+       END IF
+       
+    ENDIF
+          
+!****************************************************************************************
+! Force soil water content to qsol0 if qsol0>0 and VEGET=F (use bucket
+! instead of ORCHIDEE)
+    IF (qsol0>0.) THEN
+      PRINT*,'WARNING : On impose qsol=',qsol0
+      qsol(:)=qsol0
+    ENDIF
+!****************************************************************************************
+
+!****************************************************************************************
+! 2) Initialization to zero 
+!    Done for all local variables that will be compressed later
+!    and argument with INTENT(OUT)
+!****************************************************************************************
+    cdragh = 0.0  ; cdragm = 0.0     ; dflux_t = 0.0   ; dflux_q = 0.0
+    ypct = 0.0    ; yts = 0.0        ; ysnow = 0.0
+    zv1 = 0.0     ; yqsurf = 0.0     ; yalb1 = 0.0     ; yalb2 = 0.0    
+    yrain_f = 0.0 ; ysnow_f = 0.0    ; yfder = 0.0     ; ysolsw = 0.0    
+    ysollw = 0.0  ; yrugos = 0.0     ; yu1 = 0.0    
+    yv1 = 0.0     ; ypaprs = 0.0     ; ypplay = 0.0
+    ydelp = 0.0   ; yu = 0.0         ; yv = 0.0        ; yt = 0.0         
+    yq = 0.0      ; y_dflux_t = 0.0  ; y_dflux_q = 0.0 
+    yrugoro = 0.0 ; ywindsp = 0.0   
+    d_ts = 0.0    ; yfluxlat=0.0     ; flux_t = 0.0    ; flux_q = 0.0     
+    flux_u = 0.0  ; flux_v = 0.0     ; d_t = 0.0       ; d_q = 0.0      
+    d_u = 0.0     ; d_v = 0.0        ; yqsol = 0.0    
+    ytherm = 0.0  ; ytke=0.
+    
+    zcoefh(:,:) = 0.0
+    zcoefh(:,1) = 999999. ! zcoefh(:,k=1) should never be used
+    ytsoil = 999999. 
+
+    rh2m(:)        = 0.
+    qsat2m(:)      = 0.
+!****************************************************************************************
+! 3) - Calculate pressure thickness of each layer
+!    - Calculate the wind at first layer
+!    - Mean calculations of albedo
+!    - Calculate net radiance at sub-surface
+!****************************************************************************************
+    DO k = 1, klev
+       DO i = 1, klon
+          delp(i,k) = paprs(i,k)-paprs(i,k+1)
+       ENDDO
+    ENDDO
+
+!****************************************************************************************
+! Test for rugos........ from physiq.. A la fin plutot???
+!
+!****************************************************************************************
+
+    zxrugs(:) = 0.0
+    DO nsrf = 1, nbsrf
+       DO i = 1, klon
+          rugos(i,nsrf) = MAX(rugos(i,nsrf),0.000015)
+          zxrugs(i) = zxrugs(i) + rugos(i,nsrf)*pctsrf(i,nsrf)
+       ENDDO
+    ENDDO
+
+! Mean calculations of albedo
+!
+! Albedo at sub-surface
+! * alb1 : albedo in visible SW interval
+! * alb2 : albedo in near infrared SW interval
+! * alb  : mean albedo for whole SW interval
+!
+! Mean albedo for grid point
+! * alb1_m : albedo in visible SW interval
+! * alb2_m : albedo in near infrared SW interval
+! * alb_m  : mean albedo at whole SW interval
+
+    alb1_m(:) = 0.0
+    alb2_m(:) = 0.0
+    DO nsrf = 1, nbsrf
+       DO i = 1, klon
+          alb1_m(i) = alb1_m(i) + alb1(i,nsrf) * pctsrf(i,nsrf)
+          alb2_m(i) = alb2_m(i) + alb2(i,nsrf) * pctsrf(i,nsrf)
+       ENDDO
+    ENDDO
+
+! We here suppose the fraction f1 of incoming radiance of visible radiance 
+! as a fraction of all shortwave radiance 
+    f1 = 0.5 
+!    f1 = 1    ! put f1=1 to recreate old calculations
+
+    DO nsrf = 1, nbsrf
+       DO i = 1, klon
+          alb(i,nsrf) = f1*alb1(i,nsrf) + (1-f1)*alb2(i,nsrf)
+       ENDDO
+    ENDDO
+
+    DO i = 1, klon
+       alb_m(i) = f1*alb1_m(i) + (1-f1)*alb2_m(i)
+    END DO
+
+! Calculation of mean temperature at surface grid points
+    ztsol(:) = 0.0
+    DO nsrf = 1, nbsrf
+       DO i = 1, klon
+          ztsol(i) = ztsol(i) + ts(i,nsrf)*pctsrf(i,nsrf)
+       ENDDO
+    ENDDO
+
+! Linear distrubution on sub-surface of long- and shortwave net radiance
+    DO nsrf = 1, nbsrf
+       DO i = 1, klon
+          sollw(i,nsrf) = sollw_m(i) + 4.0*RSIGMA*ztsol(i)**3 * (ztsol(i)-ts(i,nsrf))
+          solsw(i,nsrf) = solsw_m(i) * (1.-alb(i,nsrf)) / (1.-alb_m(i))
+       ENDDO
+    ENDDO
+
+
+! Downwelling longwave radiation at mean surface
+    lwdown_m(:) = 0.0
+    DO i = 1, klon
+       lwdown_m(i) = sollw_m(i) + RSIGMA*ztsol(i)**4
+    ENDDO
+
+!****************************************************************************************
+! 4) Loop over different surfaces
+!
+! Only points containing a fraction of the sub surface will be threated.
+! 
+!****************************************************************************************
+   
+    loop_nbsrf: DO nsrf = 1, nbsrf
+
+! Search for index(ni) and size(knon) of domaine to treat
+       ni(:) = 0
+       knon  = 0
+       DO i = 1, klon
+          IF (pctsrf(i,nsrf) > 0.) THEN
+             knon = knon + 1
+             ni(knon) = i
+          ENDIF
+       ENDDO
+
+       ! write index, with IOIPSL
+       IF (debugindex .AND. mpi_size==1) THEN 
+          tabindx(:)=0.
+          DO i=1,knon
+             tabindx(i)=REAL(i)
+          END DO
+          debugtab(:,:) = 0.
+          ndexbg(:) = 0
+          CALL gath2cpl(tabindx,debugtab,knon,ni)
+          CALL histwrite(nidbg,cl_surf(nsrf),itap,debugtab,iim*(jjm+1), ndexbg)
+       ENDIF
+       
+!****************************************************************************************
+! 5) Compress variables 
+!
+!****************************************************************************************
+
+       DO j = 1, knon
+          i = ni(j)
+          ypct(j)    = pctsrf(i,nsrf)
+          yts(j)     = ts(i,nsrf)
+          ysnow(j)   = snow(i,nsrf)
+          yqsurf(j)  = qsurf(i,nsrf)
+          yalb(j)    = alb(i,nsrf)
+          yalb1(j)   = alb1(i,nsrf)
+          yalb2(j)   = alb2(i,nsrf)
+          yrain_f(j) = rain_f(i)
+          ysnow_f(j) = snow_f(i)
+          yagesno(j) = agesno(i,nsrf)
+          yfder(j)   = fder(i)
+          ysolsw(j)  = solsw(i,nsrf)
+          ysollw(j)  = sollw(i,nsrf)
+          yrugos(j)  = rugos(i,nsrf)
+          yrugoro(j) = rugoro(i)
+          yu1(j)     = u(i,1)
+          yv1(j)     = v(i,1)
+          ypaprs(j,klev+1) = paprs(i,klev+1)
+          ywindsp(j) = SQRT(u10m(i,nsrf)**2 + v10m(i,nsrf)**2 )
+       END DO
+
+       DO k = 1, klev
+          DO j = 1, knon
+             i = ni(j)
+             ypaprs(j,k) = paprs(i,k)
+             ypplay(j,k) = pplay(i,k)
+             ydelp(j,k)  = delp(i,k)
+             ytke(j,k)   = tke(i,k,nsrf)
+             yu(j,k) = u(i,k)
+             yv(j,k) = v(i,k)
+             yt(j,k) = t(i,k)
+             yq(j,k) = q(i,k)
+          ENDDO
+       ENDDO
+       
+       DO k = 1, nsoilmx
+          DO j = 1, knon
+             i = ni(j)
+             ytsoil(j,k) = ftsoil(i,k,nsrf)
+          END DO
+       END DO
+       
+       ! qsol(water height in soil) only for bucket continental model
+       IF ( nsrf .EQ. is_ter .AND. .NOT. ok_veget ) THEN 
+          DO j = 1, knon
+             i = ni(j)
+             yqsol(j) = qsol(i)
+          END DO
+       ENDIF
+       
+!****************************************************************************************
+! 6a) Calculate coefficients for turbulent diffusion at surface, cdragh et cdragm.
+!
+!****************************************************************************************
+
+       CALL clcdrag( knon, nsrf, ypaprs, ypplay, &
+            yu(:,1), yv(:,1), yt(:,1), yq(:,1), &
+            yts, yqsurf, yrugos, &
+            ycdragm, ycdragh )
+
+!****************************************************************************************
+! 6b) Calculate coefficients for turbulent diffusion in the atmosphere, ycoefm et ycoefm.
+!
+!****************************************************************************************
+
+       CALL coef_diff_turb(dtime, nsrf, knon, ni,  &
+            ypaprs, ypplay, yu, yv, yq, yt, yts, yrugos, yqsurf, ycdragm, &
+            ycoefm, ycoefh, ytke)
+       
+!****************************************************************************************
+! 
+! 8) "La descente" - "The downhill"
+!  
+!  climb_hq_down and climb_wind_down calculate the coefficients
+!  Ccoef_X et Dcoef_X for X=[H, Q, U, V].
+!  Only the coefficients at surface for H and Q are returned.
+!
+!****************************************************************************************
+
+! - Calculate the coefficients Ccoef_H, Ccoef_Q, Dcoef_H and Dcoef_Q 
+       CALL climb_hq_down(knon, ycoefh, ypaprs, ypplay, &
+            ydelp, yt, yq, dtime, &
+            AcoefH, AcoefQ, BcoefH, BcoefQ)
+
+! - Calculate the coefficients Ccoef_U, Ccoef_V, Dcoef_U and Dcoef_V
+       CALL climb_wind_down(knon, dtime, ycoefm, ypplay, ypaprs, yt, ydelp, yu, yv, &
+            AcoefU, AcoefV, BcoefU, BcoefV)
+      
+
+!****************************************************************************************
+! 9) Small calculations
+!
+!****************************************************************************************
+
+! - Reference pressure is given the values at surface level          
+       ypsref(:) = ypaprs(:,1)  
+
+! - CO2 field on 2D grid to be sent to ORCHIDEE
+!   Transform to compressed field
+       IF (carbon_cycle_cpl) THEN
+          DO i=1,knon
+             r_co2_ppm(i) = co2_send(ni(i))
+          END DO
+       ELSE
+          r_co2_ppm(:) = co2_ppm     ! Constant field
+       END IF
+
+!****************************************************************************************
+!
+! Calulate t2m and q2m for the case of calculation at land grid points 
+! t2m and q2m are needed as input to ORCHIDEE
+!
+!****************************************************************************************
+       IF (nsrf == is_ter) THEN
+
+          DO i = 1, knon
+             zgeo1(i) = RD * yt(i,1) / (0.5*(ypaprs(i,1)+ypplay(i,1))) &
+                  * (ypaprs(i,1)-ypplay(i,1))
+          END DO
+
+          ! Calculate the temperature et relative humidity at 2m and the wind at 10m 
+          CALL stdlevvar(klon, knon, is_ter, zxli, &
+               yu(:,1), yv(:,1), yt(:,1), yq(:,1), zgeo1, &
+               yts, yqsurf, yrugos, ypaprs(:,1), ypplay(:,1), &
+               yt2m, yq2m, yt10m, yq10m, yu10m, yustar)
+          
+       END IF
+
+!****************************************************************************************
+!
+! 10) Switch selon current surface
+!     It is necessary to start with the continental surfaces because the ocean
+!     needs their run-off.
+!
+!****************************************************************************************
+       SELECT CASE(nsrf)
+     
+       CASE(is_ter)
+          ! ylwdown : to be removed, calculation is now done at land surface in surf_land
+          ylwdown(:)=0.0
+          DO i=1,knon
+             ylwdown(i)=lwdown_m(ni(i))
+          END DO
+          CALL surf_land(itap, dtime, date0, jour, knon, ni,&
+               rlon, rlat, &
+               debut, lafin, ydelp(:,1), r_co2_ppm, ysolsw, ysollw, yalb, &
+               yts, ypplay(:,1), ycdragh, ycdragm, yrain_f, ysnow_f, yt(:,1), yq(:,1),&
+               AcoefH, AcoefQ, BcoefH, BcoefQ, & 
+               AcoefU, AcoefV, BcoefU, BcoefV, & 
+               ypsref, yu1, yv1, yrugoro, pctsrf, &
+               ylwdown, yq2m, yt2m, &
+               ysnow, yqsol, yagesno, ytsoil, &
+               yz0_new, yalb1_new, yalb2_new, yevap, yfluxsens, yfluxlat, &
+               yqsurf, ytsurf_new, y_dflux_t, y_dflux_q, &
+               y_flux_u1, y_flux_v1 )
+               
+     
+       CASE(is_lic)
+          CALL surf_landice(itap, dtime, knon, ni, &
+               ysolsw, ysollw, yts, ypplay(:,1), &
+               ycdragh, ycdragm, yrain_f, ysnow_f, yt(:,1), yq(:,1),&
+               AcoefH, AcoefQ, BcoefH, BcoefQ, &
+               AcoefU, AcoefV, BcoefU, BcoefV, &
+               ypsref, yu1, yv1, yrugoro, pctsrf, &
+               ysnow, yqsurf, yqsol, yagesno, &
+               ytsoil, yz0_new, yalb1_new, yalb2_new, yevap, yfluxsens, yfluxlat, &
+               ytsurf_new, y_dflux_t, y_dflux_q, &
+               y_flux_u1, y_flux_v1)
+          
+       CASE(is_oce)
+          CALL surf_ocean(rlon, rlat, ysolsw, ysollw, yalb1, &
+               yrugos, ywindsp, rmu0, yfder, yts, &
+               itap, dtime, jour, knon, ni, &
+               ypplay(:,1), ycdragh, ycdragm, yrain_f, ysnow_f, yt(:,1), yq(:,1),&
+               AcoefH, AcoefQ, BcoefH, BcoefQ, &
+               AcoefU, AcoefV, BcoefU, BcoefV, &
+               ypsref, yu1, yv1, yrugoro, pctsrf, &
+               ysnow, yqsurf, yagesno, &
+               yz0_new, yalb1_new, yalb2_new, yevap, yfluxsens, yfluxlat, &
+               ytsurf_new, y_dflux_t, y_dflux_q, slab_wfbils, &
+               y_flux_u1, y_flux_v1)
+          
+       CASE(is_sic)
+          CALL surf_seaice( &
+               rlon, rlat, ysolsw, ysollw, yalb1, yfder, &
+               itap, dtime, jour, knon, ni, &
+               lafin, &
+               yts, ypplay(:,1), ycdragh, ycdragm, yrain_f, ysnow_f, yt(:,1), yq(:,1),&
+               AcoefH, AcoefQ, BcoefH, BcoefQ, &
+               AcoefU, AcoefV, BcoefU, BcoefV, &
+               ypsref, yu1, yv1, yrugoro, pctsrf, &
+               ysnow, yqsurf, yqsol, yagesno, ytsoil, &
+               yz0_new, yalb1_new, yalb2_new, yevap, yfluxsens, yfluxlat, &
+               ytsurf_new, y_dflux_t, y_dflux_q, &
+               y_flux_u1, y_flux_v1)
+          
+
+       CASE DEFAULT
+          WRITE(lunout,*) 'Surface index = ', nsrf
+          abort_message = 'Surface index not valid'
+          CALL abort_gcm(modname,abort_message,1)
+       END SELECT
+
+
+!****************************************************************************************
+! 11) - Calcul the increment of surface temperature
+!
+!****************************************************************************************
+       y_d_ts(1:knon)   = ytsurf_new(1:knon) - yts(1:knon)
+ 
+!****************************************************************************************
+!
+! 12) "La remontee" - "The uphill"
+!
+!  The fluxes (y_flux_X) and tendancy (y_d_X) are calculated 
+!  for X=H, Q, U and V, for all vertical levels.
+!
+!****************************************************************************************
+! H and Q
+       IF (ok_flux_surf) THEN
+          PRINT *,'pbl_surface: fsens flat RLVTT=',fsens,flat,RLVTT
+          y_flux_t1(:) =  fsens
+          y_flux_q1(:) =  flat/RLVTT
+          yfluxlat(:) =  flat
+       ELSE
+          y_flux_t1(:) =  yfluxsens(:)
+          y_flux_q1(:) = -yevap(:)
+       ENDIF
+
+       CALL climb_hq_up(knon, dtime, yt, yq, &
+            y_flux_q1, y_flux_t1, ypaprs, ypplay, &
+            y_flux_q(:,:), y_flux_t(:,:), y_d_q(:,:), y_d_t(:,:))    
+       
+
+       CALL climb_wind_up(knon, dtime, yu, yv, y_flux_u1, y_flux_v1, &
+            y_flux_u, y_flux_v, y_d_u, y_d_v)
+
+
+       DO j = 1, knon
+          y_dflux_t(j) = y_dflux_t(j) * ypct(j)
+          y_dflux_q(j) = y_dflux_q(j) * ypct(j)
+       ENDDO
+
+!****************************************************************************************
+! 13) Transform variables for output format : 
+!     - Decompress
+!     - Multiply with pourcentage of current surface
+!     - Cumulate in global variable
+!
+!****************************************************************************************
+
+       tke(:,:,nsrf) = 0.
+       DO k = 1, klev
+          DO j = 1, knon
+             i = ni(j)
+             y_d_t(j,k)  = y_d_t(j,k) * ypct(j)
+             y_d_q(j,k)  = y_d_q(j,k) * ypct(j)
+             y_d_u(j,k)  = y_d_u(j,k) * ypct(j)
+             y_d_v(j,k)  = y_d_v(j,k) * ypct(j)
+
+             flux_t(i,k,nsrf) = y_flux_t(j,k)
+             flux_q(i,k,nsrf) = y_flux_q(j,k)
+             flux_u(i,k,nsrf) = y_flux_u(j,k)
+             flux_v(i,k,nsrf) = y_flux_v(j,k)
+
+             tke(i,k,nsrf)    = ytke(j,k)
+
+          ENDDO
+       ENDDO
+
+       evap(:,nsrf) = - flux_q(:,1,nsrf)
+       
+       alb1(:, nsrf) = 0.
+       alb2(:, nsrf) = 0.
+       snow(:, nsrf) = 0.
+       qsurf(:, nsrf) = 0.
+       rugos(:, nsrf) = 0.
+       fluxlat(:,nsrf) = 0.
+       DO j = 1, knon
+          i = ni(j)
+          d_ts(i,nsrf) = y_d_ts(j)
+          alb1(i,nsrf) = yalb1_new(j)  
+          alb2(i,nsrf) = yalb2_new(j)
+          snow(i,nsrf) = ysnow(j)  
+          qsurf(i,nsrf) = yqsurf(j)
+          rugos(i,nsrf) = yz0_new(j)
+          fluxlat(i,nsrf) = yfluxlat(j)
+          agesno(i,nsrf) = yagesno(j)  
+          cdragh(i) = cdragh(i) + ycdragh(j)*ypct(j)
+          cdragm(i) = cdragm(i) + ycdragm(j)*ypct(j)
+          dflux_t(i) = dflux_t(i) + y_dflux_t(j)
+          dflux_q(i) = dflux_q(i) + y_dflux_q(j)
+       END DO
+
+       DO k = 2, klev
+          DO j = 1, knon
+             i = ni(j)
+             zcoefh(i,k) = zcoefh(i,k) + ycoefh(j,k)*ypct(j)
+          END DO
+       END DO
+
+       IF ( nsrf .EQ. is_ter ) THEN 
+          DO j = 1, knon
+             i = ni(j)
+             qsol(i) = yqsol(j)
+          END DO
+       END IF
+       
+       ftsoil(:,:,nsrf) = 0.
+       DO k = 1, nsoilmx
+          DO j = 1, knon
+             i = ni(j)
+             ftsoil(i, k, nsrf) = ytsoil(j,k)
+          END DO
+       END DO
+       
+       
+       DO k = 1, klev
+          DO j = 1, knon
+             i = ni(j)
+             d_t(i,k) = d_t(i,k) + y_d_t(j,k)
+             d_q(i,k) = d_q(i,k) + y_d_q(j,k)
+             d_u(i,k) = d_u(i,k) + y_d_u(j,k)
+             d_v(i,k) = d_v(i,k) + y_d_v(j,k)
+          END DO
+       END DO
+
+!****************************************************************************************
+! 14) Calculate the temperature et relative humidity at 2m and the wind at 10m 
+!     Call HBTM
+!
+!****************************************************************************************
+       t2m(:,nsrf)    = 0.
+       q2m(:,nsrf)    = 0.
+       u10m(:,nsrf)   = 0.
+       v10m(:,nsrf)   = 0.
+
+       pblh(:,nsrf)   = 0.        ! Hauteur de couche limite
+       plcl(:,nsrf)   = 0.        ! Niveau de condensation de la CLA
+       capCL(:,nsrf)  = 0.        ! CAPE de couche limite
+       oliqCL(:,nsrf) = 0.        ! eau_liqu integree de couche limite
+       cteiCL(:,nsrf) = 0.        ! cloud top instab. crit. couche limite
+       pblt(:,nsrf)   = 0.        ! T a la Hauteur de couche limite
+       therm(:,nsrf)  = 0.
+       trmb1(:,nsrf)  = 0.        ! deep_cape
+       trmb2(:,nsrf)  = 0.        ! inhibition 
+       trmb3(:,nsrf)  = 0.        ! Point Omega
+
+#undef T2m     
+#define T2m     
+#ifdef T2m
+! Calculations of diagnostic t,q at 2m and u, v at 10m
+
+       DO j=1, knon
+          i = ni(j)
+          uzon(j) = yu(j,1) + y_d_u(j,1)
+          vmer(j) = yv(j,1) + y_d_v(j,1)
+          tair1(j) = yt(j,1) + y_d_t(j,1)
+          qair1(j) = yq(j,1) + y_d_q(j,1)
+          zgeo1(j) = RD * tair1(j) / (0.5*(ypaprs(j,1)+ypplay(j,1))) &
+               * (ypaprs(j,1)-ypplay(j,1))
+          tairsol(j) = yts(j) + y_d_ts(j)
+          rugo1(j) = yrugos(j)
+          IF(nsrf.EQ.is_oce) THEN
+             rugo1(j) = rugos(i,nsrf)
+          ENDIF
+          psfce(j)=ypaprs(j,1)
+          patm(j)=ypplay(j,1)
+          qairsol(j) = yqsurf(j)
+       END DO
+       
+
+! Calculate the temperature et relative humidity at 2m and the wind at 10m 
+       CALL stdlevvar(klon, knon, nsrf, zxli, &
+            uzon, vmer, tair1, qair1, zgeo1, &
+            tairsol, qairsol, rugo1, psfce, patm, &
+            yt2m, yq2m, yt10m, yq10m, yu10m, yustar)
+
+       DO j=1, knon
+          i = ni(j)
+          t2m(i,nsrf)=yt2m(j)
+          q2m(i,nsrf)=yq2m(j)
+          
+          ! u10m, v10m : composantes du vent a 10m sans spirale de Ekman
+          u10m(i,nsrf)=(yu10m(j) * uzon(j))/SQRT(uzon(j)**2+vmer(j)**2)
+          v10m(i,nsrf)=(yu10m(j) * vmer(j))/SQRT(uzon(j)**2+vmer(j)**2)
+       END DO
+
+!IM Calcule de l'humidite relative a 2m (rh2m) pour diagnostique
+!IM Ajoute dependance type surface
+       IF (thermcep) THEN
+          DO j = 1, knon
+             i=ni(j)
+             zdelta1 = MAX(0.,SIGN(1., rtt-yt2m(j) ))
+             zx_qs1  = r2es * FOEEW(yt2m(j),zdelta1)/paprs(i,1)
+             zx_qs1  = MIN(0.5,zx_qs1)
+             zcor1   = 1./(1.-RETV*zx_qs1)
+             zx_qs1  = zx_qs1*zcor1
+             
+             rh2m(i)   = rh2m(i)   + yq2m(j)/zx_qs1 * pctsrf(i,nsrf)
+             qsat2m(i) = qsat2m(i) + zx_qs1  * pctsrf(i,nsrf)
+          END DO
+       END IF
+
+       CALL HBTM(knon, ypaprs, ypplay, &
+            yt2m,yt10m,yq2m,yq10m,yustar, &
+            y_flux_t,y_flux_q,yu,yv,yt,yq, &
+            ypblh,ycapCL,yoliqCL,ycteiCL,ypblT, &
+            ytherm,ytrmb1,ytrmb2,ytrmb3,ylcl)
+       
+       DO j=1, knon
+          i = ni(j)
+          pblh(i,nsrf)   = ypblh(j)
+          plcl(i,nsrf)   = ylcl(j)
+          capCL(i,nsrf)  = ycapCL(j)
+          oliqCL(i,nsrf) = yoliqCL(j)
+          cteiCL(i,nsrf) = ycteiCL(j)
+          pblT(i,nsrf)   = ypblT(j)
+          therm(i,nsrf)  = ytherm(j)
+          trmb1(i,nsrf)  = ytrmb1(j)
+          trmb2(i,nsrf)  = ytrmb2(j)
+          trmb3(i,nsrf)  = ytrmb3(j)
+       END DO
+       
+#else 
+! T2m not defined
+! No calculation
+       PRINT*,' Warning !!! No T2m calculation. Output is set to zero.'
+#endif
+
+!****************************************************************************************
+! 15) End of loop over different surfaces
+!
+!****************************************************************************************
+    END DO loop_nbsrf
+
+!****************************************************************************************
+! 16) Calculate the mean value over all sub-surfaces for som variables
+!
+!****************************************************************************************
+    
+    zxfluxt(:,:) = 0.0 ; zxfluxq(:,:) = 0.0
+    zxfluxu(:,:) = 0.0 ; zxfluxv(:,:) = 0.0
+    DO nsrf = 1, nbsrf
+       DO k = 1, klev
+          DO i = 1, klon
+             zxfluxt(i,k) = zxfluxt(i,k) + flux_t(i,k,nsrf) * pctsrf(i,nsrf)
+             zxfluxq(i,k) = zxfluxq(i,k) + flux_q(i,k,nsrf) * pctsrf(i,nsrf)
+             zxfluxu(i,k) = zxfluxu(i,k) + flux_u(i,k,nsrf) * pctsrf(i,nsrf)
+             zxfluxv(i,k) = zxfluxv(i,k) + flux_v(i,k,nsrf) * pctsrf(i,nsrf)
+          END DO
+       END DO
+    END DO
+
+    DO i = 1, klon
+       zxsens(i)     = - zxfluxt(i,1) ! flux de chaleur sensible au sol
+       zxevap(i)     = - zxfluxq(i,1) ! flux d'evaporation au sol
+       fder_print(i) = fder(i) + dflux_t(i) + dflux_q(i)
+    ENDDO
+   
+!
+! Incrementer la temperature du sol
+!
+    zxtsol(:) = 0.0  ; zxfluxlat(:) = 0.0
+    zt2m(:) = 0.0    ; zq2m(:) = 0.0 
+    zu10m(:) = 0.0   ; zv10m(:) = 0.0
+    s_pblh(:) = 0.0  ; s_plcl(:) = 0.0 
+    s_capCL(:) = 0.0 ; s_oliqCL(:) = 0.0
+    s_cteiCL(:) = 0.0; s_pblT(:) = 0.0
+    s_therm(:) = 0.0 ; s_trmb1(:) = 0.0
+    s_trmb2(:) = 0.0 ; s_trmb3(:) = 0.0
+    
+    
+    DO nsrf = 1, nbsrf
+       DO i = 1, klon          
+          ts(i,nsrf) = ts(i,nsrf) + d_ts(i,nsrf)
+          
+          wfbils(i,nsrf) = ( solsw(i,nsrf) + sollw(i,nsrf) &
+               + flux_t(i,1,nsrf) + fluxlat(i,nsrf) ) * pctsrf(i,nsrf)
+          wfbilo(i,nsrf) = (evap(i,nsrf) - (rain_f(i) + snow_f(i))) * &
+               pctsrf(i,nsrf)
+
+          zxtsol(i)    = zxtsol(i)    + ts(i,nsrf)      * pctsrf(i,nsrf)
+          zxfluxlat(i) = zxfluxlat(i) + fluxlat(i,nsrf) * pctsrf(i,nsrf)
+          
+          zt2m(i)  = zt2m(i)  + t2m(i,nsrf)  * pctsrf(i,nsrf)
+          zq2m(i)  = zq2m(i)  + q2m(i,nsrf)  * pctsrf(i,nsrf)
+          zu10m(i) = zu10m(i) + u10m(i,nsrf) * pctsrf(i,nsrf)
+          zv10m(i) = zv10m(i) + v10m(i,nsrf) * pctsrf(i,nsrf)
+
+          s_pblh(i)   = s_pblh(i)   + pblh(i,nsrf)  * pctsrf(i,nsrf)
+          s_plcl(i)   = s_plcl(i)   + plcl(i,nsrf)  * pctsrf(i,nsrf)
+          s_capCL(i)  = s_capCL(i)  + capCL(i,nsrf) * pctsrf(i,nsrf)
+          s_oliqCL(i) = s_oliqCL(i) + oliqCL(i,nsrf)* pctsrf(i,nsrf)
+          s_cteiCL(i) = s_cteiCL(i) + cteiCL(i,nsrf)* pctsrf(i,nsrf)
+          s_pblT(i)   = s_pblT(i)   + pblT(i,nsrf)  * pctsrf(i,nsrf)
+          s_therm(i)  = s_therm(i)  + therm(i,nsrf) * pctsrf(i,nsrf)
+          s_trmb1(i)  = s_trmb1(i)  + trmb1(i,nsrf) * pctsrf(i,nsrf)
+          s_trmb2(i)  = s_trmb2(i)  + trmb2(i,nsrf) * pctsrf(i,nsrf)
+          s_trmb3(i)  = s_trmb3(i)  + trmb3(i,nsrf) * pctsrf(i,nsrf)
+       END DO
+    END DO
+
+    IF (check) THEN
+       amn=MIN(ts(1,is_ter),1000.)
+       amx=MAX(ts(1,is_ter),-1000.)
+       DO i=2, klon
+          amn=MIN(ts(i,is_ter),amn)
+          amx=MAX(ts(i,is_ter),amx)
+       ENDDO
+       PRINT*,' debut apres d_ts min max ftsol(ts)',itap,amn,amx
+    ENDIF
+
+!jg ?
+!!$!
+!!$! If a sub-surface does not exsist for a grid point, the mean value for all 
+!!$! sub-surfaces is distributed.
+!!$!
+!!$    DO nsrf = 1, nbsrf
+!!$       DO i = 1, klon
+!!$          IF ((pctsrf_new(i,nsrf) .LT. epsfra) .OR. (t2m(i,nsrf).EQ.0.)) THEN
+!!$             ts(i,nsrf)     = zxtsol(i)
+!!$             t2m(i,nsrf)    = zt2m(i)
+!!$             q2m(i,nsrf)    = zq2m(i)
+!!$             u10m(i,nsrf)   = zu10m(i)
+!!$             v10m(i,nsrf)   = zv10m(i)
+!!$
+!!$! Les variables qui suivent sont plus utilise, donc peut-etre pas la peine a les mettre ajour
+!!$             pblh(i,nsrf)   = s_pblh(i)
+!!$             plcl(i,nsrf)   = s_plcl(i)
+!!$             capCL(i,nsrf)  = s_capCL(i)
+!!$             oliqCL(i,nsrf) = s_oliqCL(i) 
+!!$             cteiCL(i,nsrf) = s_cteiCL(i)
+!!$             pblT(i,nsrf)   = s_pblT(i)
+!!$             therm(i,nsrf)  = s_therm(i)
+!!$             trmb1(i,nsrf)  = s_trmb1(i)
+!!$             trmb2(i,nsrf)  = s_trmb2(i)
+!!$             trmb3(i,nsrf)  = s_trmb3(i)
+!!$          ENDIF
+!!$       ENDDO
+!!$    ENDDO
+
+
+    DO i = 1, klon
+       fder(i) = - 4.0*RSIGMA*zxtsol(i)**3 
+    ENDDO
+    
+    zxqsurf(:) = 0.0
+    zxsnow(:)  = 0.0
+    DO nsrf = 1, nbsrf
+       DO i = 1, klon
+          zxqsurf(i) = zxqsurf(i) + qsurf(i,nsrf) * pctsrf(i,nsrf)
+          zxsnow(i)  = zxsnow(i)  + snow(i,nsrf)  * pctsrf(i,nsrf)
+       END DO
+    END DO
+
+! Premier niveau de vent sortie dans physiq.F
+    zu1(:) = u(:,1)
+    zv1(:) = v(:,1)
+
+! Some of the module declared variables are returned for printing in physiq.F
+    qsol_d(:)     = qsol(:)
+    evap_d(:,:)   = evap(:,:)
+    rugos_d(:,:)  = rugos(:,:) 
+    agesno_d(:,:) = agesno(:,:)
+
+
+  END SUBROUTINE pbl_surface
+!
+!****************************************************************************************
+!
+  SUBROUTINE pbl_surface_final(qsol_rst, fder_rst, snow_rst, qsurf_rst, &
+       evap_rst, rugos_rst, agesno_rst, ftsoil_rst)
+
+    INCLUDE "indicesol.h"
+    INCLUDE "dimsoil.h"
+
+! Ouput variables
+!****************************************************************************************
+    REAL, DIMENSION(klon), INTENT(OUT)                 :: qsol_rst
+    REAL, DIMENSION(klon), INTENT(OUT)                 :: fder_rst
+    REAL, DIMENSION(klon, nbsrf), INTENT(OUT)          :: snow_rst
+    REAL, DIMENSION(klon, nbsrf), INTENT(OUT)          :: qsurf_rst
+    REAL, DIMENSION(klon, nbsrf), INTENT(OUT)          :: evap_rst
+    REAL, DIMENSION(klon, nbsrf), INTENT(OUT)          :: rugos_rst
+    REAL, DIMENSION(klon, nbsrf), INTENT(OUT)          :: agesno_rst
+    REAL, DIMENSION(klon, nsoilmx, nbsrf), INTENT(OUT) :: ftsoil_rst
+
+ 
+!****************************************************************************************
+! Return module variables for writing to restart file
+!
+!****************************************************************************************    
+    qsol_rst(:)       = qsol(:)
+    fder_rst(:)       = fder(:)
+    snow_rst(:,:)     = snow(:,:)
+    qsurf_rst(:,:)    = qsurf(:,:)
+    evap_rst(:,:)     = evap(:,:)
+    rugos_rst(:,:)    = rugos(:,:)
+    agesno_rst(:,:)   = agesno(:,:)
+    ftsoil_rst(:,:,:) = ftsoil(:,:,:)
+
+!****************************************************************************************
+! Deallocate module variables
+!
+!****************************************************************************************
+!   DEALLOCATE(qsol, fder, snow, qsurf, evap, rugos, agesno, ftsoil)
+    IF (ALLOCATED(qsol)) DEALLOCATE(qsol)
+    IF (ALLOCATED(fder)) DEALLOCATE(fder)
+    IF (ALLOCATED(snow)) DEALLOCATE(snow)
+    IF (ALLOCATED(qsurf)) DEALLOCATE(qsurf)
+    IF (ALLOCATED(evap)) DEALLOCATE(evap)
+    IF (ALLOCATED(rugos)) DEALLOCATE(rugos)
+    IF (ALLOCATED(agesno)) DEALLOCATE(agesno)
+    IF (ALLOCATED(ftsoil)) DEALLOCATE(ftsoil)
+
+  END SUBROUTINE pbl_surface_final
+!  
+!****************************************************************************************
+! 
+  SUBROUTINE pbl_surface_newfrac(itime, pctsrf_new, pctsrf_old, tsurf, alb1, alb2, u10m, v10m, tke)
+
+    ! Give default values where new fraction has appread
+
+    INCLUDE "indicesol.h"
+    INCLUDE "dimsoil.h"
+    INCLUDE "clesphys.h"
+    INCLUDE "compbl.h"
+
+! Input variables
+!****************************************************************************************
+    INTEGER, INTENT(IN)                     :: itime
+    REAL, DIMENSION(klon,nbsrf), INTENT(IN) :: pctsrf_new, pctsrf_old
+
+! InOutput variables
+!****************************************************************************************
+    REAL, DIMENSION(klon,nbsrf), INTENT(INOUT)        :: tsurf
+    REAL, DIMENSION(klon,nbsrf), INTENT(INOUT)        :: alb1, alb2
+    REAL, DIMENSION(klon,nbsrf), INTENT(INOUT)        :: u10m, v10m
+    REAL, DIMENSION(klon,klev+1,nbsrf), INTENT(INOUT) :: tke
+
+! Local variables
+!****************************************************************************************
+    INTEGER           :: nsrf, nsrf_comp1, nsrf_comp2, nsrf_comp3, i
+    CHARACTER(len=80) :: abort_message
+    CHARACTER(len=20) :: modname = 'pbl_surface_newfrac'
+    INTEGER, DIMENSION(nbsrf) :: nfois=0, mfois=0, pfois=0
+!
+! All at once !! 
+!****************************************************************************************
+    
+    DO nsrf = 1, nbsrf
+       ! First decide complement sub-surfaces
+       SELECT CASE (nsrf)
+       CASE(is_oce)
+          nsrf_comp1=is_sic
+          nsrf_comp2=is_ter
+          nsrf_comp3=is_lic
+       CASE(is_sic)
+          nsrf_comp1=is_oce
+          nsrf_comp2=is_ter
+          nsrf_comp3=is_lic
+       CASE(is_ter)
+          nsrf_comp1=is_lic
+          nsrf_comp2=is_oce
+          nsrf_comp3=is_sic
+       CASE(is_lic)
+          nsrf_comp1=is_ter
+          nsrf_comp2=is_oce
+          nsrf_comp3=is_sic
+       END SELECT
+
+       ! Initialize all new fractions
+       DO i=1, klon
+          IF (pctsrf_new(i,nsrf) > 0. .AND. pctsrf_old(i,nsrf) == 0.) THEN
+             
+             IF (pctsrf_old(i,nsrf_comp1) > 0.) THEN
+                ! Use the complement sub-surface, keeping the continents unchanged
+                qsurf(i,nsrf) = qsurf(i,nsrf_comp1)
+                evap(i,nsrf)  = evap(i,nsrf_comp1)
+                rugos(i,nsrf) = rugos(i,nsrf_comp1)
+                tsurf(i,nsrf) = tsurf(i,nsrf_comp1)
+                alb1(i,nsrf)  = alb1(i,nsrf_comp1)
+                alb2(i,nsrf)  = alb2(i,nsrf_comp1)
+                u10m(i,nsrf)  = u10m(i,nsrf_comp1)
+                v10m(i,nsrf)  = v10m(i,nsrf_comp1)
+                if (iflag_pbl > 1) then
+                 tke(i,:,nsrf) = tke(i,:,nsrf_comp1)
+                endif
+                mfois(nsrf) = mfois(nsrf) + 1
+             ELSE
+                ! The continents have changed. The new fraction receives the mean sum of the existent fractions
+                qsurf(i,nsrf) = qsurf(i,nsrf_comp2)*pctsrf_old(i,nsrf_comp2) + qsurf(i,nsrf_comp3)*pctsrf_old(i,nsrf_comp3)
+                evap(i,nsrf)  = evap(i,nsrf_comp2) *pctsrf_old(i,nsrf_comp2) + evap(i,nsrf_comp3) *pctsrf_old(i,nsrf_comp3)
+                rugos(i,nsrf) = rugos(i,nsrf_comp2)*pctsrf_old(i,nsrf_comp2) + rugos(i,nsrf_comp3)*pctsrf_old(i,nsrf_comp3)
+                tsurf(i,nsrf) = tsurf(i,nsrf_comp2)*pctsrf_old(i,nsrf_comp2) + tsurf(i,nsrf_comp3)*pctsrf_old(i,nsrf_comp3)
+                alb1(i,nsrf)  = alb1(i,nsrf_comp2) *pctsrf_old(i,nsrf_comp2) + alb1(i,nsrf_comp3) *pctsrf_old(i,nsrf_comp3)
+                alb2(i,nsrf)  = alb2(i,nsrf_comp2) *pctsrf_old(i,nsrf_comp2) + alb2(i,nsrf_comp3) *pctsrf_old(i,nsrf_comp3)
+                u10m(i,nsrf)  = u10m(i,nsrf_comp2) *pctsrf_old(i,nsrf_comp2) + u10m(i,nsrf_comp3) *pctsrf_old(i,nsrf_comp3)
+                v10m(i,nsrf)  = v10m(i,nsrf_comp2) *pctsrf_old(i,nsrf_comp2) + v10m(i,nsrf_comp3) *pctsrf_old(i,nsrf_comp3)
+                if (iflag_pbl > 1) then
+                 tke(i,:,nsrf) = tke(i,:,nsrf_comp2)*pctsrf_old(i,nsrf_comp2) + tke(i,:,nsrf_comp3)*pctsrf_old(i,nsrf_comp3)
+                endif
+            
+                ! Security abort. This option has never been tested. To test, comment the following line.
+!                abort_message='The fraction of the continents have changed!'
+!                CALL abort_gcm(modname,abort_message,1)
+                nfois(nsrf) = nfois(nsrf) + 1
+             END IF
+             snow(i,nsrf)     = 0.
+             agesno(i,nsrf)   = 0.
+             ftsoil(i,:,nsrf) = tsurf(i,nsrf)
+          ELSE
+             pfois(nsrf) = pfois(nsrf)+ 1
+          END IF
+       END DO
+       
+    END DO
+
+  END SUBROUTINE pbl_surface_newfrac
+
+!  
+!****************************************************************************************
+!  
+
+END MODULE pbl_surface_mod
Index: LMDZ5/branches/testing/libf/phy1d/ttt/ttt.x
===================================================================
--- LMDZ5/branches/testing/libf/phy1d/ttt/ttt.x	(revision 1665)
+++ LMDZ5/branches/testing/libf/phy1d/ttt/ttt.x	(revision 1665)
@@ -0,0 +1,8 @@
+ echo Update pbl_surface_mod.F90
+ sed -e "/^ *INCLUDE *\"temps.h\"/{
+ a\\
+!****************************************************************************************\\
+! Declarations specifiques pour le 1D. A reprendre \\
+    INCLUDE "flux_arp.h"
+ }; /^.*REAL *::.*fsens *, *flat/d; /^.*LOGICAL *::.*ok_flux_surf/d; /^.*COMMON.*flux_arp.*/d " /home/jygz/LMDZ/TLMDZ/test_int_20110531/LMDZ5/modipsl/modeles/LMDZ5/libf/phylmd/pbl_surface_mod.F90 >pbl_surface_mod.F90
+
Index: LMDZ5/branches/testing/libf/phydev/comcstphy.h
===================================================================
--- LMDZ5/branches/testing/libf/phydev/comcstphy.h	(revision 1665)
+++ LMDZ5/branches/testing/libf/phydev/comcstphy.h	(revision 1665)
@@ -0,0 +1,2 @@
+      real rradius,rr,rg,rcpp
+      common/comcstphy/rradius,rr,rg,rcpp
Index: LMDZ5/branches/testing/libf/phydev/comgeomphy.F90
===================================================================
--- LMDZ5/branches/testing/libf/phydev/comgeomphy.F90	(revision 1665)
+++ LMDZ5/branches/testing/libf/phydev/comgeomphy.F90	(revision 1665)
@@ -0,0 +1,1 @@
+link ../phylmd/comgeomphy.F90
Index: LMDZ5/branches/testing/libf/phydev/dimphy.F90
===================================================================
--- LMDZ5/branches/testing/libf/phydev/dimphy.F90	(revision 1665)
+++ LMDZ5/branches/testing/libf/phydev/dimphy.F90	(revision 1665)
@@ -0,0 +1,1 @@
+link ../phylmd/dimphy.F90
Index: LMDZ5/branches/testing/libf/phydev/iniphysiq.F
===================================================================
--- LMDZ5/branches/testing/libf/phydev/iniphysiq.F	(revision 1665)
+++ LMDZ5/branches/testing/libf/phydev/iniphysiq.F	(revision 1665)
@@ -0,0 +1,114 @@
+!
+! $Id: iniphysiq.F 1403 2010-07-01 09:02:53Z fairhead $
+!
+c
+c
+      SUBROUTINE iniphysiq(ngrid,nlayer,
+     $           punjours,
+     $           pdayref,ptimestep,
+     $           plat,plon,parea,pcu,pcv,
+     $           prad,pg,pr,pcpp)
+      USE dimphy
+      USE mod_grid_phy_lmdz
+      USE mod_phys_lmdz_para
+      USE comgeomphy
+
+      IMPLICIT NONE
+c
+c=======================================================================
+c
+c   subject:
+c   --------
+c
+c   Initialisation for the physical parametrisations of the LMD 
+c   martian atmospheric general circulation modele.
+c
+c   author: Frederic Hourdin 15 / 10 /93
+c   -------
+c
+c   arguments:
+c   ----------
+c
+c   input:
+c   ------
+c
+c    ngrid                 Size of the horizontal grid.
+c                          All internal loops are performed on that grid.
+c    nlayer                Number of vertical layers.
+c    pdayref               Day of reference for the simulation
+c    firstcall             True at the first call
+c    lastcall              True at the last call
+c    pday                  Number of days counted from the North. Spring
+c                          equinoxe.
+c
+c=======================================================================
+c
+c-----------------------------------------------------------------------
+c   declarations:
+c   -------------
+ 
+cym#include "dimensions.h"
+cym#include "dimphy.h"
+cym#include "comgeomphy.h"
+#include "comcstphy.h"
+      REAL prad,pg,pr,pcpp,punjours
+ 
+      INTEGER ngrid,nlayer
+      REAL plat(ngrid),plon(ngrid),parea(klon_glo)
+      REAL pcu(klon_glo),pcv(klon_glo)
+      INTEGER pdayref
+      INTEGER :: ibegin,iend,offset
+ 
+      REAL ptimestep
+      CHARACTER (LEN=20) :: modname='iniphysiq'
+      CHARACTER (LEN=80) :: abort_message
+ 
+      IF (nlayer.NE.klev) THEN
+         PRINT*,'STOP in inifis'
+         PRINT*,'Probleme de dimensions :'
+         PRINT*,'nlayer     = ',nlayer
+         PRINT*,'klev   = ',klev
+         abort_message = ''
+         CALL abort_gcm (modname,abort_message,1)
+      ENDIF
+
+      IF (ngrid.NE.klon_glo) THEN
+         PRINT*,'STOP in inifis'
+         PRINT*,'Probleme de dimensions :'
+         PRINT*,'ngrid     = ',ngrid
+         PRINT*,'klon   = ',klon_glo
+         abort_message = ''
+         CALL abort_gcm (modname,abort_message,1)
+      ENDIF
+c$OMP PARALLEL PRIVATE(ibegin,iend) 
+c$OMP+         SHARED(parea,pcu,pcv,plon,plat)
+      
+      offset=klon_mpi_begin-1
+      airephy(1:klon_omp)=parea(offset+klon_omp_begin:
+     &                          offset+klon_omp_end)
+      cuphy(1:klon_omp)=pcu(offset+klon_omp_begin:offset+klon_omp_end)
+      cvphy(1:klon_omp)=pcv(offset+klon_omp_begin:offset+klon_omp_end)
+      rlond(1:klon_omp)=plon(offset+klon_omp_begin:offset+klon_omp_end)
+      rlatd(1:klon_omp)=plat(offset+klon_omp_begin:offset+klon_omp_end)
+
+!     call suphel
+!     prad,pg,pr,pcpp
+      rradius=prad
+      rg=pg
+      rr=pr
+      rcpp=pcpp
+
+      
+
+c$OMP END PARALLEL
+
+      print*,'ATTENTION !!! TRAVAILLER SUR INIPHYSIQ'
+      print*,'CONTROLE DES LATITUDES, LONGITUDES, PARAMETRES ...'
+
+      RETURN
+9999  CONTINUE
+      abort_message ='Cette version demande les fichier rnatur.dat
+     & et surf.def'
+      CALL abort_gcm (modname,abort_message,1)
+
+      END
Index: LMDZ5/branches/testing/libf/phydev/init_phys_lmdz.F90
===================================================================
--- LMDZ5/branches/testing/libf/phydev/init_phys_lmdz.F90	(revision 1665)
+++ LMDZ5/branches/testing/libf/phydev/init_phys_lmdz.F90	(revision 1665)
@@ -0,0 +1,1 @@
+link ../phylmd/init_phys_lmdz.F90
Index: LMDZ5/branches/testing/libf/phydev/iophy.F90
===================================================================
--- LMDZ5/branches/testing/libf/phydev/iophy.F90	(revision 1665)
+++ LMDZ5/branches/testing/libf/phydev/iophy.F90	(revision 1665)
@@ -0,0 +1,1 @@
+link ../phylmd/iophy.F90
Index: LMDZ5/branches/testing/libf/phydev/mod_grid_phy_lmdz.F90
===================================================================
--- LMDZ5/branches/testing/libf/phydev/mod_grid_phy_lmdz.F90	(revision 1665)
+++ LMDZ5/branches/testing/libf/phydev/mod_grid_phy_lmdz.F90	(revision 1665)
@@ -0,0 +1,1 @@
+link ../phylmd/mod_grid_phy_lmdz.F90
Index: LMDZ5/branches/testing/libf/phydev/mod_phys_lmdz_mpi_data.F90
===================================================================
--- LMDZ5/branches/testing/libf/phydev/mod_phys_lmdz_mpi_data.F90	(revision 1665)
+++ LMDZ5/branches/testing/libf/phydev/mod_phys_lmdz_mpi_data.F90	(revision 1665)
@@ -0,0 +1,1 @@
+link ../phylmd/mod_phys_lmdz_mpi_data.F90
Index: LMDZ5/branches/testing/libf/phydev/mod_phys_lmdz_mpi_transfert.F90
===================================================================
--- LMDZ5/branches/testing/libf/phydev/mod_phys_lmdz_mpi_transfert.F90	(revision 1665)
+++ LMDZ5/branches/testing/libf/phydev/mod_phys_lmdz_mpi_transfert.F90	(revision 1665)
@@ -0,0 +1,1 @@
+link ../phylmd/mod_phys_lmdz_mpi_transfert.F90
Index: LMDZ5/branches/testing/libf/phydev/mod_phys_lmdz_omp_data.F90
===================================================================
--- LMDZ5/branches/testing/libf/phydev/mod_phys_lmdz_omp_data.F90	(revision 1665)
+++ LMDZ5/branches/testing/libf/phydev/mod_phys_lmdz_omp_data.F90	(revision 1665)
@@ -0,0 +1,1 @@
+link ../phylmd/mod_phys_lmdz_omp_data.F90
Index: LMDZ5/branches/testing/libf/phydev/mod_phys_lmdz_omp_transfert.F90
===================================================================
--- LMDZ5/branches/testing/libf/phydev/mod_phys_lmdz_omp_transfert.F90	(revision 1665)
+++ LMDZ5/branches/testing/libf/phydev/mod_phys_lmdz_omp_transfert.F90	(revision 1665)
@@ -0,0 +1,1 @@
+link ../phylmd/mod_phys_lmdz_omp_transfert.F90
Index: LMDZ5/branches/testing/libf/phydev/mod_phys_lmdz_para.F90
===================================================================
--- LMDZ5/branches/testing/libf/phydev/mod_phys_lmdz_para.F90	(revision 1665)
+++ LMDZ5/branches/testing/libf/phydev/mod_phys_lmdz_para.F90	(revision 1665)
@@ -0,0 +1,1 @@
+link ../phylmd/mod_phys_lmdz_para.F90
Index: LMDZ5/branches/testing/libf/phydev/mod_phys_lmdz_transfert_para.F90
===================================================================
--- LMDZ5/branches/testing/libf/phydev/mod_phys_lmdz_transfert_para.F90	(revision 1665)
+++ LMDZ5/branches/testing/libf/phydev/mod_phys_lmdz_transfert_para.F90	(revision 1665)
@@ -0,0 +1,1 @@
+link ../phylmd/mod_phys_lmdz_transfert_para.F90
Index: LMDZ5/branches/testing/libf/phydev/phyaqua.F
===================================================================
--- LMDZ5/branches/testing/libf/phydev/phyaqua.F	(revision 1665)
+++ LMDZ5/branches/testing/libf/phydev/phyaqua.F	(revision 1665)
@@ -0,0 +1,26 @@
+! Routines complementaires pour la physique planetaire.
+
+
+      subroutine iniaqua(nlon,latfi,lonfi,iflag_phys)
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!  Creation d'un etat initial et de conditions aux limites 
+!  (resp startphy.nc et limit.nc) pour des configurations idealisees 
+! du modele LMDZ dans sa version terrestre.
+!  iflag_phys est un parametre qui controle
+!  iflag_phys = N  
+!    de 100 a 199 : aqua planetes avec SST forcees
+!                 N-100 determine le type de SSTs
+!    de 200 a 299 : terra planetes avec Ts calcule
+!        
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+
+      integer nlon,iflag_phys
+cIM ajout latfi, lonfi
+      REAL, DIMENSION (nlon) :: lonfi, latfi
+
+
+      return
+      end
+
Index: LMDZ5/branches/testing/libf/phydev/physiq.F90
===================================================================
--- LMDZ5/branches/testing/libf/phydev/physiq.F90	(revision 1665)
+++ LMDZ5/branches/testing/libf/phydev/physiq.F90	(revision 1665)
@@ -0,0 +1,124 @@
+! $Id: physiq.F 1565 2011-08-31 12:53:29Z jghattas $
+!#define IO_DEBUG
+
+      SUBROUTINE physiq (nlon,nlev, &
+     &            debut,lafin,jD_cur, jH_cur,pdtphys, &
+     &            paprs,pplay,pphi,pphis,presnivs,clesphy0, &
+     &            u,v,t,qx, &
+     &            flxmass_w, &
+     &            d_u, d_v, d_t, d_qx, d_ps &
+     &            , dudyn &
+     &            , PVteta)
+
+      USE dimphy
+      USE infotrac
+      USE comgeomphy
+
+      IMPLICIT none
+!======================================================================
+! Objet: Moniteur general de la physique du modele
+!======================================================================
+!
+!  Arguments:
+!
+! nlon----input-I-nombre de points horizontaux
+! nlev----input-I-nombre de couches verticales, doit etre egale a klev
+! debut---input-L-variable logique indiquant le premier passage
+! lafin---input-L-variable logique indiquant le dernier passage
+! jD_cur       -R-jour courant a l'appel de la physique (jour julien)
+! jH_cur       -R-heure courante a l'appel de la physique (jour julien)
+! pdtphys-input-R-pas d'integration pour la physique (seconde)
+! paprs---input-R-pression pour chaque inter-couche (en Pa)
+! pplay---input-R-pression pour le mileu de chaque couche (en Pa)
+! pphi----input-R-geopotentiel de chaque couche (g z) (reference sol)
+! pphis---input-R-geopotentiel du sol
+! presnivs-input_R_pressions approximat. des milieux couches ( en PA)
+! u-------input-R-vitesse dans la direction X (de O a E) en m/s
+! v-------input-R-vitesse Y (de S a N) en m/s
+! t-------input-R-temperature (K)
+! qx------input-R-humidite specifique (kg/kg) et d'autres traceurs
+! d_t_dyn-input-R-tendance dynamique pour "t" (K/s)
+! d_q_dyn-input-R-tendance dynamique pour "q" (kg/kg/s)
+! flxmass_w -input-R- flux de masse verticale
+! d_u-----output-R-tendance physique de "u" (m/s/s)
+! d_v-----output-R-tendance physique de "v" (m/s/s)
+! d_t-----output-R-tendance physique de "t" (K/s)
+! d_qx----output-R-tendance physique de "qx" (kg/kg/s)
+! d_ps----output-R-tendance physique de la pression au sol
+!IM
+! PVteta--output-R-vorticite potentielle a des thetas constantes
+!======================================================================
+#include "dimensions.h"
+#include "comcstphy.h"
+
+      integer jjmp1
+      parameter (jjmp1=jjm+1-1/jjm)
+      integer iip1
+      parameter (iip1=iim+1)
+
+      INTEGER ivap          ! indice de traceurs pour vapeur d'eau
+      PARAMETER (ivap=1)
+      INTEGER iliq          ! indice de traceurs pour eau liquide
+      PARAMETER (iliq=2)
+
+!
+!
+! Variables argument:
+!
+      INTEGER nlon
+      INTEGER nlev
+      REAL, intent(in):: jD_cur, jH_cur
+
+      REAL pdtphys
+      LOGICAL debut, lafin
+      REAL paprs(klon,klev+1)
+      REAL pplay(klon,klev)
+      REAL pphi(klon,klev)
+      REAL pphis(klon)
+      REAL presnivs(klev)
+      REAL znivsig(klev)
+      real pir
+
+      REAL u(klon,klev)
+      REAL v(klon,klev)
+      REAL t(klon,klev),theta(klon,klev)
+      REAL qx(klon,klev,nqtot)
+      REAL flxmass_w(klon,klev)
+      REAL omega(klon,klev) ! vitesse verticale en Pa/s
+      REAL d_u(klon,klev)
+      REAL d_v(klon,klev)
+      REAL d_t(klon,klev)
+      REAL d_qx(klon,klev,nqtot)
+      REAL d_ps(klon)
+      real da(klon,klev),phi(klon,klev,klev),mp(klon,klev)
+!IM definition dynamique o_trac dans phys_output_open
+!      type(ctrl_out) :: o_trac(nqtot)
+!FH! REAL PVteta(klon,nbteta)
+      REAL PVteta(klon,1)
+      REAL dudyn(iim+1,jjmp1,klev)
+
+    INTEGER        longcles
+    PARAMETER    ( longcles = 20 )
+
+real temp_newton(klon,klev)
+integer k
+logical, save :: first=.true.
+
+      REAL clesphy0( longcles      )
+
+d_u=0.
+d_v=0.
+d_t=0.
+d_qx=0.
+d_ps=0.
+
+     d_u(:,1)=-u(:,1)/86400.
+     do k=1,klev
+        temp_newton(:,k)=280.+cos(rlatd(:))*40.-pphi(:,k)/rg*6.e-3
+        d_t(:,k)=(temp_newton(:,k)-t(:,k))/1.e5
+     enddo
+
+
+      print*,'COUCOU PHYDEV'
+      return
+      end
Index: LMDZ5/branches/testing/libf/phydev/tetalevel.F
===================================================================
--- LMDZ5/branches/testing/libf/phydev/tetalevel.F	(revision 1665)
+++ LMDZ5/branches/testing/libf/phydev/tetalevel.F	(revision 1665)
@@ -0,0 +1,1 @@
+link ../phylmd/tetalevel.F
Index: LMDZ5/branches/testing/libf/phylmd/calwake.F
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/calwake.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/calwake.F	(revision 1665)
@@ -60,5 +60,5 @@
       REAL wake_dtKE(klon,klev),wake_dqKE(klon,klev)
       REAL wake_dtPBL(klon,klev),wake_dqPBL(klon,klev)
-      REAL wake_omg(klon,klev+1),wake_dp_deltomg(klon,klev)
+      REAL wake_omg(klon,klev),wake_dp_deltomg(klon,klev)
       REAL wake_spread(klon,klev),wake_Cstar(klon)
       REAL wake_ddeltat(klon,klev),wake_ddeltaq(klon,klev)
@@ -84,5 +84,5 @@
       REAL tu(klon,klev),qu(klon,klev)
       REAL hw(klon),sigmaw(klon),wape(klon),fip(klon),gfl(klon)
-      REAL omgbdth(klon,klev),dp_omgb(klon,klev)
+      REAL omgbdth(klon,klev+1),dp_omgb(klon,klev)
       REAL dtKE(klon,klev),dqKE(klon,klev)
       REAL dtPBL(klon,klev),dqPBL(klon,klev)
Index: LMDZ5/branches/testing/libf/phylmd/climb_hq_mod.F90
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/climb_hq_mod.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/climb_hq_mod.F90	(revision 1665)
@@ -252,4 +252,6 @@
        Bcoef(i) = -1. * RG / buf
     END DO
+    acoef(knon+1: klon) = 0.
+    bcoef(knon+1: klon) = 0.
 
   END SUBROUTINE calc_coef
Index: LMDZ5/branches/testing/libf/phylmd/climb_wind_mod.F90
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/climb_wind_mod.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/climb_wind_mod.F90	(revision 1665)
@@ -209,4 +209,6 @@
        Bcoef(i) = -RG/buf
     END DO
+    acoef(knon+1: klon) = 0.
+    bcoef(knon+1: klon) = 0.
 
   END SUBROUTINE calc_coef
Index: LMDZ5/branches/testing/libf/phylmd/coef_diff_turb_mod.F90
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/coef_diff_turb_mod.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/coef_diff_turb_mod.F90	(revision 1665)
@@ -389,5 +389,9 @@
 !           calculer la fraction nuageuse (processus humide):
 !
-          zfr = (zq+ratqs*zq-zqs) / (2.0*ratqs*zq)
+          if (zq /= 0.) then
+             zfr = (zq+ratqs*zq-zqs) / (2.0*ratqs*zq)
+          else
+             zfr = 0.
+          end if
           zfr = MAX(0.0,MIN(1.0,zfr))
           IF (.NOT.richum) zfr = 0.0
Index: LMDZ5/branches/testing/libf/phylmd/concvl.F
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/concvl.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/concvl.F	(revision 1665)
@@ -248,5 +248,5 @@
          DO i = 1, klon
           cbmf(i) = 0.
-          plcl(i) = 0.
+!          plcl(i) = 0.
           sigd(i) = 0.
          ENDDO
@@ -256,4 +256,5 @@
       plfc(:)  = 0.
       wbeff(:) = 100.
+      plcl(:) = 0.
 
       DO k = 1, klev+1
Index: LMDZ5/branches/testing/libf/phylmd/cpl_mod.F90
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/cpl_mod.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/cpl_mod.F90	(revision 1665)
@@ -345,5 +345,5 @@
        IF (is_sequential) THEN
           ndexcs(:) = 0
-          itau_w = itau_phy + itime
+          itau_w = itau_phy + itime + start_time * day_step / iphysiq
           DO i = 1, maxrecv
             IF (inforecv(i)%action) THEN
@@ -1232,5 +1232,5 @@
     IF (is_sequential) THEN
        ndexct(:) = 0
-       itau_w = itau_phy + itime
+       itau_w = itau_phy + itime + start_time * day_step / iphysiq
        CALL histwrite(nidct,'tauxe',itau_w,tmp_taux,iim*(jjm+1),ndexct)
        CALL histwrite(nidct,'tauyn',itau_w,tmp_tauy,iim*(jjm+1),ndexct)
Index: LMDZ5/branches/testing/libf/phylmd/iostart.F90
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/iostart.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/iostart.F90	(revision 1665)
@@ -177,6 +177,20 @@
          ierr=NF90_GET_VAR(nid_start,varid,field_glo)
          IF (ierr/=NF90_NOERR) THEN
+           ! La variable exist dans le fichier mais la lecture a echouee. 
            PRINT*, 'phyetat0: Lecture echouee pour <'//field_name//'>'
-           CALL abort
+
+           IF (field_name=='CLWCON' .OR. field_name=='RNEBCON' .OR. field_name=='RATQS') THEN
+              ! Essaye de lire le variable sur surface uniqument, comme fait avant
+              field_glo(:)=0.
+              ierr=NF90_GET_VAR(nid_start,varid,field_glo(1:klon_glo))
+              IF (ierr/=NF90_NOERR) THEN
+                 PRINT*, 'phyetat0: Lecture echouee aussi en 2D pour <'//field_name//'>'
+                 CALL abort
+              ELSE
+                 PRINT*, 'phyetat0: La variable <'//field_name//'> lu sur surface seulement'!, selon ancien format, le reste mis a zero'
+              END IF
+           ELSE
+              CALL abort
+           ENDIF
          ENDIF
 
Index: LMDZ5/branches/testing/libf/phylmd/limit_read_mod.F90
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/limit_read_mod.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/limit_read_mod.F90	(revision 1665)
@@ -150,4 +150,5 @@
     
     INCLUDE "indicesol.h"
+    INCLUDE "iniprint.h"
 
 ! In- and ouput arguments
@@ -165,5 +166,7 @@
 !$OMP THREADPRIVATE(lmt_pas) 
     LOGICAL, SAVE                             :: first_call=.TRUE.
-!$OMP THREADPRIVATE(first_call)    
+!$OMP THREADPRIVATE(first_call)  
+    INTEGER, SAVE                             :: jour_lu = -1
+!$OMP THREADPRIVATE(jour_lu)  
 ! Locals variables
 !****************************************************************************************
@@ -209,5 +212,6 @@
 
     is_modified = .FALSE.
-    IF (MOD(itime-1, lmt_pas) == 0) THEN   ! time to read
+    IF (MOD(itime-1, lmt_pas) == 0 .OR. jour_lu /= jour ) THEN   ! time to read
+       jour_lu = jour
        is_modified = .TRUE.
 !$OMP MASTER  ! Only master thread
Index: LMDZ5/branches/testing/libf/phylmd/lnblnk1.F
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/lnblnk1.F	(revision 1664)
+++ 	(revision )
@@ -1,47 +1,0 @@
-!
-! $Header$
-!
-      INTEGER FUNCTION lnblnk1 (letter)
-
-C--------------------------------------------------------
-C Fonction qui determine la longeur d'un string sans les
-C blancs qui suivent. Le critere pour determiner la fin du
-C string est, trois blancs de suite
-C---------------------------------------------------------
-C     ARGUMENTS
-C     +++++++++
-C     letter: CHARACTER*xxx (xxx < imax)
-C             le string dont on determine la longuer
-C     lnblnk1: INTEGER
-C             le nombre de characteres
-C
-C     PARAMETER
-C     +++++++++
-C     imax : INTEGER
-C            le nombre maximale de character que peut contenir le string
-C            a traiter
-
-      IMPLICIT NONE
-      INTEGER i,imax
-      PARAMETER (imax = 256)
-c     CHARACTER*256 letter
-      CHARACTER*4 letter
-
-      i=0
-
-10    i=i+1
-c     IF (letter(i:i+1) . EQ . ' ') THEN
-      IF (letter(i:i) . EQ . ' ') THEN
-c      print*,'i=',i,'letter(i:i+1)=',letter(i:i+1)
-c      print*,'i=',i
-       GOTO 20
-      ELSE
-       GOTO 10
-      ENDIF
-
-20    lnblnk1=i-1
-c     PRINT*,'lnblnk1=',lnblnk1
-
-      RETURN
-      END
-
Index: LMDZ5/branches/testing/libf/phylmd/phyetat0.F
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/phyetat0.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/phyetat0.F	(revision 1665)
@@ -749,10 +749,20 @@
       ENDIF
 
-      u_ancien = 0.0   !AXC: We don't have u_ancien and v_ancien in the start
-      v_ancien = 0.0   !AXC: files, therefore they have to be initialized.
-c
+      CALL get_field("UANCIEN",u_ancien,found)
+      IF (.NOT. found) THEN
+         PRINT*, "phyetat0: Le champ <UANCIEN> est absent"
+         PRINT*, "Depart legerement fausse. Mais je continue"
+         ancien_ok = .FALSE.
+      ENDIF
+
+      CALL get_field("VANCIEN",v_ancien,found)
+      IF (.NOT. found) THEN
+         PRINT*, "phyetat0: Le champ <VANCIEN> est absent"
+         PRINT*, "Depart legerement fausse. Mais je continue"
+         ancien_ok = .FALSE.
+      ENDIF
 
       clwcon=0.
-      CALL get_field("CLWCON",clwcon(:,1),found)
+      CALL get_field("CLWCON",clwcon,found)
       IF (.NOT. found) THEN
          PRINT*, "phyetat0: Le champ CLWCON est absent"
@@ -766,5 +776,5 @@
 c
       rnebcon = 0.
-      CALL get_field("RNEBCON",rnebcon(:,1),found)
+      CALL get_field("RNEBCON",rnebcon,found)
       IF (.NOT. found) THEN
          PRINT*, "phyetat0: Le champ RNEBCON est absent"
@@ -781,5 +791,5 @@
 c
       ratqs=0.
-      CALL get_field("RATQS",ratqs(:,1),found)
+      CALL get_field("RATQS",ratqs,found)
       IF (.NOT. found) THEN
          PRINT*, "phyetat0: Le champ <RATQS> est absent"
Index: LMDZ5/branches/testing/libf/phylmd/phyredem.F
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/phyredem.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/phyredem.F	(revision 1665)
@@ -267,13 +267,17 @@
       
       CALL put_field("QANCIEN","QANCIEN",q_ancien)
-      
+
+      CALL put_field("UANCIEN","",u_ancien)
+
+      CALL put_field("VANCIEN","",v_ancien)
+
       CALL put_field("RUGMER","Longueur de rugosite sur mer",
      .               frugs(:,is_oce))
       
-      CALL put_field("CLWCON","Eau liquide convective",clwcon(:,1))
-      
-      CALL put_field("RNEBCON","Nebulosite convective",rnebcon(:,1))
-      
-      CALL put_field("RATQS", "Ratqs",ratqs(:,1))
+      CALL put_field("CLWCON","Eau liquide convective",clwcon)
+      
+      CALL put_field("RNEBCON","Nebulosite convective",rnebcon)
+      
+      CALL put_field("RATQS", "Ratqs",ratqs)
 c
 c run_off_lic_0
Index: LMDZ5/branches/testing/libf/phylmd/phys_output_mod.F90
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/phys_output_mod.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/phys_output_mod.F90	(revision 1665)
@@ -1318,10 +1318,8 @@
           ! Couplage conv-CL
           IF (iflag_con.GE.3) THEN
-             IF (iflag_coupl>=1) THEN
                 CALL histdef2d(iff,clef_stations(iff), &
                      o_ale_bl%flag,o_ale_bl%name, "ALE BL", "m2/s2") 
                 CALL histdef2d(iff,clef_stations(iff), &
                      o_alp_bl%flag,o_alp_bl%name, "ALP BL", "m2/s2") 
-             ENDIF
           ENDIF !(iflag_con.GE.3)
 
@@ -1491,10 +1489,4 @@
                 CALL histdef2d(iff,clef_stations(iff), &
                      o_alp_wk%flag,o_alp_wk%name, "ALP WK", "m2/s2")
-                CALL histdef2d(iff,clef_stations(iff), &
-                     o_ale%flag,o_ale%name, "ALE", "m2/s2")
-                CALL histdef2d(iff,clef_stations(iff), &
-                     o_alp%flag,o_alp%name, "ALP", "W/m2")
-                CALL histdef2d(iff,clef_stations(iff),o_cin%flag,o_cin%name, "Convective INhibition", "m2/s2")
-                CALL histdef2d(iff,clef_stations(iff),o_wape%flag,o_WAPE%name, "WAPE", "m2/s2")
                 CALL histdef2d(iff,clef_stations(iff),o_wake_h%flag,o_wake_h%name, "wake_h", "-")
                 CALL histdef2d(iff,clef_stations(iff),o_wake_s%flag,o_wake_s%name, "wake_s", "-")
@@ -1504,5 +1496,11 @@
                 CALL histdef3d(iff,clef_stations(iff),o_wake_deltaq%flag,o_wake_deltaq%name, "wake_deltaq", " ")
                 CALL histdef3d(iff,clef_stations(iff),o_wake_omg%flag,o_wake_omg%name, "wake_omg", " ")
+                CALL histdef2d(iff,clef_stations(iff),o_wape%flag,o_WAPE%name, "WAPE", "m2/s2")
              ENDIF
+             CALL histdef2d(iff,clef_stations(iff), &
+                     o_ale%flag,o_ale%name, "ALE", "m2/s2")
+             CALL histdef2d(iff,clef_stations(iff), &
+                     o_alp%flag,o_alp%name, "ALP", "W/m2")
+             CALL histdef2d(iff,clef_stations(iff),o_cin%flag,o_cin%name, "Convective INhibition", "m2/s2")
              CALL histdef3d(iff,clef_stations(iff),o_Vprecip%flag,o_Vprecip%name, "precipitation vertical profile", "-")
              CALL histdef3d(iff,clef_stations(iff),o_ftd%flag,o_ftd%name, "tend temp due aux descentes precip", "-")
@@ -1859,5 +1857,5 @@
     if ( type == 'day'.or.type == 'days'.or.type == 'jours'.or.type == 'jour' ) timestep = ttt * dayseconde
     if ( type == 'mounths'.or.type == 'mth'.or.type == 'mois' ) then
-       write(lunout,*)'annee_ref,day_ref mon_len',annee_ref,day_ref,ioget_mon_len(annee_ref,day_ref)
+       write(lunout,*)'annee_ref,day_ref mon_len',annee_ref,day_ref,mth_len
        timestep = ttt * dayseconde * mth_len
     endif
Index: LMDZ5/branches/testing/libf/phylmd/phys_output_write.h
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/phys_output_write.h	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/phys_output_write.h	(revision 1665)
@@ -1,3 +1,3 @@
-      itau_w = itau_phy + itap
+      itau_w = itau_phy + itap + start_time * day_step / iphysiq
 
       DO iff=1,nfiles
@@ -801,5 +801,4 @@
 ! Couplage convection-couche limite
       IF (iflag_con.GE.3) THEN
-      IF (iflag_coupl>=1) THEN
        IF (o_ale_bl%flag(iff)<=lev_files(iff)) THEN
        CALL histwrite_phy(nid_files(iff),clef_stations(iff),
@@ -810,5 +809,4 @@
      $o_alp_bl%name,itau_w,alp_bl)
        ENDIF
-      ENDIF !iflag_coupl>=1
       ENDIF !(iflag_con.GE.3)
 
@@ -825,16 +823,4 @@
        ENDIF
 
-       IF (o_ale%flag(iff)<=lev_files(iff)) THEN
-       CALL histwrite_phy(nid_files(iff),clef_stations(iff),
-     $o_ale%name,itau_w,ale)
-       ENDIF
-       IF (o_alp%flag(iff)<=lev_files(iff)) THEN
-       CALL histwrite_phy(nid_files(iff),clef_stations(iff),
-     $o_alp%name,itau_w,alp)
-       ENDIF
-       IF (o_cin%flag(iff)<=lev_files(iff)) THEN
-       CALL histwrite_phy(nid_files(iff),clef_stations(iff),
-     $o_cin%name,itau_w,cin)
-       ENDIF
        IF (o_wape%flag(iff)<=lev_files(iff)) THEN
        CALL histwrite_phy(nid_files(iff),clef_stations(iff),
@@ -883,4 +869,16 @@
       ENDIF ! iflag_wake>=1
 
+       IF (o_ale%flag(iff)<=lev_files(iff)) THEN
+       CALL histwrite_phy(nid_files(iff),clef_stations(iff),
+     $o_ale%name,itau_w,ale)
+       ENDIF
+       IF (o_alp%flag(iff)<=lev_files(iff)) THEN
+       CALL histwrite_phy(nid_files(iff),clef_stations(iff),
+     $o_alp%name,itau_w,alp)
+       ENDIF
+       IF (o_cin%flag(iff)<=lev_files(iff)) THEN
+       CALL histwrite_phy(nid_files(iff),clef_stations(iff),
+     $o_cin%name,itau_w,cin)
+       ENDIF
         IF (o_Vprecip%flag(iff)<=lev_files(iff)) THEN
        CALL histwrite_phy(nid_files(iff),clef_stations(iff),
Index: LMDZ5/branches/testing/libf/phylmd/physiq.F
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/physiq.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/physiq.F	(revision 1665)
@@ -614,6 +614,6 @@
       REAL dd_t(klon,klev),dd_q(klon,klev)
 
-      real, save :: alp_bl_prescr=0.
-      real, save :: ale_bl_prescr=0.
+      real, save :: alp_bl_prescr=0.1
+      real, save :: ale_bl_prescr=4.
 
       real, save :: ale_max=1000.
@@ -791,7 +791,4 @@
 cIM
       EXTERNAL haut2bas  !variables de haut en bas
-      INTEGER lnblnk1
-      EXTERNAL lnblnk1   !enleve les blancs a la fin d'une variable de type
-                         !caracter
       EXTERNAL ini_undefSTD  !initialise a 0 une variable a 1 niveau de pression
       EXTERNAL undefSTD      !somme les valeurs definies d'1 var a 1 niveau de pression
@@ -1220,4 +1217,5 @@
       INTEGER :: nbtr_tmp ! Number of tracer inside concvl
       REAL, dimension(klon,klev) :: sh_in ! Specific humidity entering in phytrac
+      integer iostat
 
 cIM for NMC files
@@ -1492,10 +1490,8 @@
 cCR:04.12.07: initialisations poches froides
 c Controle de ALE et ALP pour la fermeture convective (jyg)
-          if (iflag_wake>=1) then
-            CALL ini_wake(0.,0.,it_wape_prescr,wape_prescr,fip_prescr
+         CALL ini_wake(0.,0.,it_wape_prescr,wape_prescr,fip_prescr
      s                  ,alp_bl_prescr, ale_bl_prescr)
 c 11/09/06 rajout initialisation ALE et ALP du wake et PBL(YU)
 c        print*,'apres ini_wake iflag_cldcon=', iflag_cldcon
-          endif
 
         do i = 1,klon
@@ -1508,5 +1504,6 @@
       nCFMIP=npCFMIP
       OPEN(98,file='npCFMIP_param.data',status='old',
-     $          form='formatted',err=999)
+     $          form='formatted',iostat=iostat)
+            if (iostat == 0) then
       READ(98,*,end=998) nCFMIP
 998   CONTINUE
@@ -1540,5 +1537,9 @@
      $tabijGCM, lonGCM, latGCM, iGCM, jGCM)
 c
-999      CONTINUE
+            else
+               ALLOCATE(tabijGCM(0))
+               ALLOCATE(lonGCM(0), latGCM(0))
+               ALLOCATE(iGCM(0), jGCM(0))
+            end if
          ENDIF !debut
  
@@ -2041,53 +2042,57 @@
 c
 
-      CALL pbl_surface( 
-     e     dtime,     date0,     itap,    days_elapsed+1,
-     e     debut,     lafin,
-     e     rlon,      rlat,      rugoro,  rmu0,     
-     e     rain_fall, snow_fall, solsw,   sollw,    
-     e     t_seri,    q_seri,    u_seri,  v_seri,   
-     e     pplay,     paprs,     pctsrf,            
-     +     ftsol,     falb1,     falb2,   u10m,   v10m,
-     s     sollwdown, cdragh,    cdragm,  u1,    v1,
-     s     albsol1,   albsol2,   sens,    evap,  
-     s     zxtsol,    zxfluxlat, zt2m,    qsat2m, 
-     s     d_t_vdf,   d_q_vdf,   d_u_vdf, d_v_vdf,
-     s     coefh,     coefm,     slab_wfbils,                
-     d     qsol,      zq2m,      s_pblh,  s_lcl,
-     d     s_capCL,   s_oliqCL,  s_cteiCL,s_pblT,
-     d     s_therm,   s_trmb1,   s_trmb2, s_trmb3,
-     d     zxrugs,    zu10m,     zv10m,   fder,
-     d     zxqsurf,   rh2m,      zxfluxu, zxfluxv,
-     d     frugs,     agesno,    fsollw,  fsolsw,
-     d     d_ts,      fevap,     fluxlat, t2m,
-     d     wfbils,    wfbilo,    fluxt,   fluxu,  fluxv,
-     -     dsens,     devap,     zxsnow,
-     -     zxfluxt,   zxfluxq,   q2m,     fluxq, pbl_tke )
+      if (iflag_pbl/=0) then 
+
+        CALL pbl_surface( 
+     e       dtime,     date0,     itap,    days_elapsed+1,
+     e       debut,     lafin,
+     e       rlon,      rlat,      rugoro,  rmu0,     
+     e       rain_fall, snow_fall, solsw,   sollw,    
+     e       t_seri,    q_seri,    u_seri,  v_seri,   
+     e       pplay,     paprs,     pctsrf,            
+     +       ftsol,     falb1,     falb2,   u10m,   v10m,
+     s       sollwdown, cdragh,    cdragm,  u1,    v1,
+     s       albsol1,   albsol2,   sens,    evap,  
+     s       zxtsol,    zxfluxlat, zt2m,    qsat2m, 
+     s       d_t_vdf,   d_q_vdf,   d_u_vdf, d_v_vdf,
+     s       coefh,     coefm,     slab_wfbils,                
+     d       qsol,      zq2m,      s_pblh,  s_lcl,
+     d       s_capCL,   s_oliqCL,  s_cteiCL,s_pblT,
+     d       s_therm,   s_trmb1,   s_trmb2, s_trmb3,
+     d       zxrugs,    zu10m,     zv10m,   fder,
+     d       zxqsurf,   rh2m,      zxfluxu, zxfluxv,
+     d       frugs,     agesno,    fsollw,  fsolsw,
+     d       d_ts,      fevap,     fluxlat, t2m,
+     d       wfbils,    wfbilo,    fluxt,   fluxu,  fluxv,
+     -       dsens,     devap,     zxsnow,
+     -       zxfluxt,   zxfluxq,   q2m,     fluxq, pbl_tke )
 
 
 !-----------------------------------------------------------------------------------------
 ! ajout des tendances de la diffusion turbulente
-      CALL add_phys_tend(d_u_vdf,d_v_vdf,d_t_vdf,d_q_vdf,dql0,'vdf')
+        CALL add_phys_tend(d_u_vdf,d_v_vdf,d_t_vdf,d_q_vdf,dql0,'vdf')
 !-----------------------------------------------------------------------------------------
 
-      if (mydebug) then
-        call writefield_phy('u_seri',u_seri,llm)
-        call writefield_phy('v_seri',v_seri,llm)
-        call writefield_phy('t_seri',t_seri,llm)
-        call writefield_phy('q_seri',q_seri,llm)
-      endif
-
-
-      IF (ip_ebil_phy.ge.2) THEN 
-        ztit='after surface_main'
-        CALL diagetpq(airephy,ztit,ip_ebil_phy,2,2,dtime
+        if (mydebug) then
+          call writefield_phy('u_seri',u_seri,llm)
+          call writefield_phy('v_seri',v_seri,llm)
+          call writefield_phy('t_seri',t_seri,llm)
+          call writefield_phy('q_seri',q_seri,llm)
+        endif
+
+
+        IF (ip_ebil_phy.ge.2) THEN 
+          ztit='after surface_main'
+          CALL diagetpq(airephy,ztit,ip_ebil_phy,2,2,dtime
      e      , t_seri,q_seri,ql_seri,qs_seri,u_seri,v_seri,paprs,pplay
      s      , d_h_vcol, d_qt, d_qw, d_ql, d_qs, d_ec)
-         call diagphy(airephy,ztit,ip_ebil_phy
+          call diagphy(airephy,ztit,ip_ebil_phy
      e      , zero_v, zero_v, zero_v, zero_v, sens
      e      , evap  , zero_v, zero_v, ztsol
      e      , d_h_vcol, d_qt, d_ec
      s      , fs_bound, fq_bound )
-      END IF 
+        END IF 
+
+      ENDIF
 
 c =================================================================== c
@@ -2239,23 +2244,10 @@
 cdans le thermique sinon
        if (iflag_coupl.eq.0) then
-          if (debut.and.prt_level.gt.9)
-     $                     WRITE(lunout,*)'ALE et ALP imposes'
-          do i = 1,klon
-con ne couple que ale
-c           ALE(i) = max(ale_wake(i),Ale_bl(i))
-            ALE(i) = max(ale_wake(i),ale_bl_prescr)
-con ne couple que alp
-c           ALP(i) = alp_wake(i) + Alp_bl(i)
-            ALP(i) = alp_wake(i) + alp_bl_prescr
-          enddo
+          if (debut.and.prt_level.gt.9)WRITE(lunout,*) 'ALE&ALP imposes'
+          Ale_bl(1:klon) = ale_bl_prescr
+          Alp_bl(1:klon) = alp_bl_prescr
        else
          IF(prt_level>9)WRITE(lunout,*)'ALE et ALP couples au thermique'
-!         do i = 1,klon
-!             ALE(i) = max(ale_wake(i),Ale_bl(i))
-! avant        ALP(i) = alp_wake(i) + Alp_bl(i)
-!             ALP(i) = alp_wake(i) + Alp_bl(i) + alp_offset ! modif sb
-!         write(20,*)'ALE',ALE(i),Ale_bl(i),ale_wake(i)
-!         write(21,*)'ALP',ALP(i),Alp_bl(i),alp_wake(i)
-!         enddo
+       endif
 
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -2264,4 +2256,5 @@
 ! w si <0
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
        do i = 1,klon
           ALE(i) = max(ale_wake(i),Ale_bl(i))
@@ -2276,7 +2269,7 @@
           endif
        enddo
+
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-       endif
        do i=1,klon
           if (alp(i)>alp_max) then
@@ -2634,5 +2627,5 @@
 c  ==============
 
-! Dans le cas oÃ¹ on active les thermiques, on fait partir l'ajustement
+! Dans le cas o\`u on active les thermiques, on fait partir l'ajustement
 ! a partir du sommet des thermiques.
 ! Dans le cas contraire, on demarre au niveau 1.
@@ -2821,5 +2814,5 @@
 ! FH 22/09/2009
 ! La ligne ci-dessous faisait osciller le modele et donnait une solution
-! assymptotique bidon et dÃ©pendant fortement du pas de temps.
+! asymptotique bidon et d\'ependant fortement du pas de temps.
 !        ratqs(:,:)=sqrt(ratqs(:,:)**2+ratqss(:,:)**2)
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -3576,5 +3569,4 @@
 
        IF (ok_hines) then
-
          CALL hines_gwd(klon,klev,dtime,paprs,pplay,
      i                  rlat,t_seri,u_seri,v_seri,
@@ -3584,10 +3576,6 @@
 c  ajout des tendances
         CALL add_phys_tend(d_u_hin,d_v_hin,d_t_hin,dq0,dql0,'hin')
-
       ENDIF
-c
-
-c
-cIM cf. FLott BEG
+
 C STRESS NECESSAIRES: TOUTE LA PHYSIQUE
 
@@ -3614,5 +3602,5 @@
 cIM calcul composantes axiales du moment angulaire et couple des montagnes
 c
-      IF (is_sequential) THEN
+      IF (is_sequential .and. ok_orodr) THEN
       
         CALL aaam_bud (27,klon,klev,jD_cur-jD_ref,jH_cur,
Index: LMDZ5/branches/testing/libf/phylmd/phytrac.F90
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/phytrac.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/phytrac.F90	(revision 1665)
@@ -214,5 +214,5 @@
      SELECT CASE(type_trac)
      CASE('lmdz')
-        CALL traclmdz_init(pctsrf, ftsol, tr_seri, t_seri, pplay, sh, pdtphys, aerosol, lessivage)
+        CALL traclmdz_init(pctsrf, xlat, xlon, ftsol, tr_seri, t_seri, pplay, sh, pdtphys, aerosol, lessivage)
      CASE('inca')
         source(:,:)=0.
Index: LMDZ5/branches/testing/libf/phylmd/readaerosol.F90
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/readaerosol.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/readaerosol.F90	(revision 1665)
@@ -247,11 +247,11 @@
   
        WRITE(lunout,*) 'reading variable ',TRIM(varname),' in file ', TRIM(fname)
-       CALL check_err( nf90_open(TRIM(fname), NF90_NOWRITE, ncid) )
+       CALL check_err( nf90_open(TRIM(fname), NF90_NOWRITE, ncid), "pb open "//trim(varname) )
 
 ! Test for equal longitudes and latitudes in file and model
 !****************************************************************************************
        ! Read and test longitudes
-       CALL check_err( nf90_inq_varid(ncid, 'lon', varid) )
-       CALL check_err( nf90_get_var(ncid, varid, lon_src(:)) )
+       CALL check_err( nf90_inq_varid(ncid, 'lon', varid),"pb inq lon" )
+       CALL check_err( nf90_get_var(ncid, varid, lon_src(:)),"pb get lon" )
        
        IF (maxval(ABS(lon_src - io_lon)) > 0.001) THEN
@@ -264,6 +264,6 @@
 
        ! Read and test latitudes
-       CALL check_err( nf90_inq_varid(ncid, 'lat', varid) )
-       CALL check_err( nf90_get_var(ncid, varid, lat_src(:)) )
+       CALL check_err( nf90_inq_varid(ncid, 'lat', varid),"pb inq lat" )
+       CALL check_err( nf90_get_var(ncid, varid, lat_src(:)),"pb get lat" )
 
        ! Invert source latitudes
@@ -311,5 +311,5 @@
 ! 2) Find vertical dimension klev_src
 !****************************************************************************************
-       CALL check_err( nf90_inquire_dimension(ncid, dimid, len = klev_src) )
+       CALL check_err( nf90_inquire_dimension(ncid, dimid, len = klev_src),"pb inq dim for PRESNIVS or lev" )
        
      ! Allocate variables depending on the number of vertical levels
@@ -330,5 +330,5 @@
 !**************************************************************************************************
        ierr = nf90_inq_dimid(ncid, 'TIME',dimid)
-       CALL check_err( nf90_inquire_dimension(ncid, dimid, len = nbr_tsteps) )
+       CALL check_err( nf90_inquire_dimension(ncid, dimid, len = nbr_tsteps),"pb inq dim TIME" )
 !       IF (nbr_tsteps /= 12 .AND. nbr_tsteps /= 14) THEN
        IF (nbr_tsteps /= 12 ) THEN
@@ -339,43 +339,43 @@
 !****************************************************************************************
           ! Get variable id
-          CALL check_err( nf90_inq_varid(ncid, TRIM(varname), varid) )
+          CALL check_err( nf90_inq_varid(ncid, TRIM(varname), varid),"pb inq var "//TRIM(varname) )
           
           ! Get the variable
-          CALL check_err( nf90_get_var(ncid, varid, varyear(:,:,:,:)) )
+          CALL check_err( nf90_get_var(ncid, varid, varyear(:,:,:,:)),"pb get var "//TRIM(varname) )
           
 ! ++) Read surface pression, 12 month in one variable
 !****************************************************************************************
           ! Get variable id
-          CALL check_err( nf90_inq_varid(ncid, "ps", varid) )
+          CALL check_err( nf90_inq_varid(ncid, "ps", varid),"pb inq var ps" )
           ! Get the variable
-          CALL check_err( nf90_get_var(ncid, varid, psurf_glo2D) )
+          CALL check_err( nf90_get_var(ncid, varid, psurf_glo2D),"pb get var ps" )
           
 ! ++) Read mass load, 12 month in one variable
 !****************************************************************************************
           ! Get variable id
-          CALL check_err( nf90_inq_varid(ncid, "load_"//TRIM(varname), varid) )
+          CALL check_err( nf90_inq_varid(ncid, "load_"//TRIM(varname), varid) ,"pb inq var load_"//TRIM(varname))
           ! Get the variable
-          CALL check_err( nf90_get_var(ncid, varid, load_glo2D) )
+          CALL check_err( nf90_get_var(ncid, varid, load_glo2D),"pb get var load_"//TRIM(varname) )
           
 ! ++) Read ap
 !****************************************************************************************
           ! Get variable id
-          CALL check_err( nf90_inq_varid(ncid, "ap", varid) )
+          CALL check_err( nf90_inq_varid(ncid, "ap", varid),"pb inq var ap" )
           ! Get the variable
-          CALL check_err( nf90_get_var(ncid, varid, pt_ap) )
+          CALL check_err( nf90_get_var(ncid, varid, pt_ap),"pb get var ap" )
 
 ! ++) Read b
 !****************************************************************************************
           ! Get variable id
-          CALL check_err( nf90_inq_varid(ncid, "b", varid) )
+          CALL check_err( nf90_inq_varid(ncid, "b", varid),"pb inq var b" )
           ! Get the variable
-          CALL check_err( nf90_get_var(ncid, varid, pt_b) )
+          CALL check_err( nf90_get_var(ncid, varid, pt_b),"pb get var b" )
 
 ! ++) Read p0 : reference pressure
 !****************************************************************************************
           ! Get variable id
-          CALL check_err( nf90_inq_varid(ncid, "p0", varid) )
+          CALL check_err( nf90_inq_varid(ncid, "p0", varid),"pb inq var p0" )
           ! Get the variable
-          CALL check_err( nf90_get_var(ncid, varid, p0) )
+          CALL check_err( nf90_get_var(ncid, varid, p0),"pb get var p0" )
           
 
@@ -412,8 +412,8 @@
              
              ! Get variable id
-             CALL check_err( nf90_inq_varid(ncid, TRIM(cvar), varid) )
+             CALL check_err( nf90_inq_varid(ncid, TRIM(cvar), varid),"pb inq var "//TRIM(cvar) )
              
              ! Get the variable
-             CALL check_err( nf90_get_var(ncid, varid, varmth) )
+             CALL check_err( nf90_get_var(ncid, varid, varmth),"pb get var "//TRIM(cvar) )
              
              ! Store in variable for the whole year
@@ -432,5 +432,5 @@
 ! 4) Close file  
 !****************************************************************************************
-       CALL check_err( nf90_close(ncid) )
+       CALL check_err( nf90_close(ncid),"pb in close" )
      
 
@@ -570,5 +570,5 @@
 
 
-  SUBROUTINE check_err(status)
+  SUBROUTINE check_err(status,text)
     USE netcdf
     IMPLICIT NONE
@@ -576,7 +576,11 @@
     INCLUDE "iniprint.h"
     INTEGER, INTENT (IN) :: status
+    CHARACTER(len=*), INTENT (IN), OPTIONAL :: text
 
     IF (status /= NF90_NOERR) THEN
-       WRITE(lunout,*) 'Error in get_aero_fromfile ',status
+       WRITE(lunout,*) 'Error in get_aero_fromfile, netcdf error code = ',status
+       IF (PRESENT(text)) THEN
+          WRITE(lunout,*) 'Error in get_aero_fromfile : ',text
+       END IF
        CALL abort_gcm('get_aero_fromfile',trim(nf90_strerror(status)),1)
     END IF
Index: LMDZ5/branches/testing/libf/phylmd/readaerosol_interp.F90
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/readaerosol_interp.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/readaerosol_interp.F90	(revision 1665)
@@ -175,5 +175,5 @@
      ! Reading values corresponding to the closest year taking into count the choice of aer_type. 
      ! For aer_type=scenario interpolation between 2 data sets is done in readaerosol.
-     ! If aer_type=mix1 or mix2, the run type and file name depends on the aerosol.
+     ! If aer_type=mix1, mix2 or mix3, the run type and file name depends on the aerosol.
      IF (aer_type=='preind' .OR. aer_type=='actuel' .OR. aer_type=='annuel' .OR. aer_type=='scenario') THEN
         ! Standard case
@@ -196,4 +196,13 @@
         ELSE
            filename='aerosols'
+           type='preind'
+        END IF
+     ELSE  IF (aer_type == 'mix3') THEN
+        ! Special case using a mix of annual sulfate file and natrual aerosols
+        IF (name_aero(id_aero) == 'SO4') THEN
+           filename='aerosols'
+           type='annuel'
+        ELSE
+           filename='aerosols' 
            type='preind'
         END IF
Index: LMDZ5/branches/testing/libf/phylmd/traclmdz_mod.F90
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/traclmdz_mod.F90	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/traclmdz_mod.F90	(revision 1665)
@@ -84,5 +84,5 @@
 
 
-  SUBROUTINE traclmdz_init(pctsrf, ftsol, tr_seri, t_seri, pplay, sh, pdtphys, aerosol, lessivage)
+  SUBROUTINE traclmdz_init(pctsrf, xlat, xlon, ftsol, tr_seri, t_seri, pplay, sh, pdtphys, aerosol, lessivage)
     ! This subroutine allocates and initialize module variables and control variables.
     ! Initialization of the tracers should be done here only for those not found in the restart file.
@@ -99,4 +99,6 @@
 ! Input variables
     REAL,DIMENSION(klon,nbsrf),INTENT(IN)     :: pctsrf ! Pourcentage de sol f(nature du sol)
+    REAL,DIMENSION(klon),INTENT(IN)           :: xlat   ! latitudes en degres pour chaque point 
+    REAL,DIMENSION(klon),INTENT(IN)           :: xlon   ! longitudes en degres pour chaque point 
     REAL,DIMENSION(klon,nbsrf),INTENT(IN)     :: ftsol  ! Temperature du sol (surf)(Kelvin)
     REAL,DIMENSION(klon,klev,nbtr),INTENT(INOUT) :: tr_seri! Concentration Traceur [U/KgA]  
Index: LMDZ5/branches/testing/libf/phylmd/wrgradsfi.F
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/wrgradsfi.F	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/wrgradsfi.F	(revision 1665)
@@ -23,5 +23,5 @@
 c   local
 
-      integer lm,l,lnblnk
+      integer lm,l
 
 
Index: LMDZ5/branches/testing/libf/phylmd/write_bilKP_ave.h
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/write_bilKP_ave.h	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/write_bilKP_ave.h	(revision 1665)
@@ -9,5 +9,5 @@
 c Champs 2D:
 c
-      itau_w = itau_phy + itap
+      itau_w = itau_phy + itap + start_time * day_step / iphysiq
 c
 cym      CALL gr_fi_ecrit(klev, klon,iim,jjmp1, ue_lay,zx_tmp_3d)
Index: LMDZ5/branches/testing/libf/phylmd/write_bilKP_ins.h
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/write_bilKP_ins.h	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/write_bilKP_ins.h	(revision 1665)
@@ -7,5 +7,5 @@
       ndex3d = 0
 c
-      itau_w = itau_phy + itap
+      itau_w = itau_phy + itap + start_time * day_step / iphysiq
 c
 c Champs 3D:
Index: LMDZ5/branches/testing/libf/phylmd/write_histISCCP.h
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/write_histISCCP.h	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/write_histISCCP.h	(revision 1665)
@@ -9,5 +9,5 @@
        ndex3d = 0
 c
-       itau_w = itau_phy + itap
+       itau_w = itau_phy + itap + start_time * day_step / iphysiq
 c
        IF(type_run.EQ."ENSP".OR.type_run.EQ."CLIM") THEN
Index: LMDZ5/branches/testing/libf/phylmd/write_histREGDYN.h
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/write_histREGDYN.h	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/write_histREGDYN.h	(revision 1665)
@@ -8,5 +8,5 @@
 
       ndex3d = 0
-      itau_w = itau_phy + itap
+      itau_w = itau_phy + itap + start_time * day_step / iphysiq
 c
        CALL histwrite(nid_regdyn,"hw1",itau_w,histoW(:,:,:,1),
Index: LMDZ5/branches/testing/libf/phylmd/write_histdayNMC.h
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/write_histdayNMC.h	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/write_histdayNMC.h	(revision 1665)
@@ -5,5 +5,5 @@
 c
        ndex3d = 0
-       itau_w = itau_phy + itap
+       itau_w = itau_phy + itap + start_time * day_step / iphysiq
 ccc
 c  Champs interpolles sur des niveaux de pression du NMC
Index: LMDZ5/branches/testing/libf/phylmd/write_histday_seri.h
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/write_histday_seri.h	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/write_histday_seri.h	(revision 1665)
@@ -7,5 +7,5 @@
 c
       ndex2d = 0
-      itau_w = itau_phy + itap
+      itau_w = itau_phy + itap + start_time * day_step / iphysiq
 c
 c Champs 2D:
Index: LMDZ5/branches/testing/libf/phylmd/write_histhf3d.h
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/write_histhf3d.h	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/write_histhf3d.h	(revision 1665)
@@ -7,5 +7,5 @@
       ndex3d = 0
 c
-      itau_w = itau_phy + itap
+      itau_w = itau_phy + itap + start_time * day_step / iphysiq
 c
 c Champs 3D:
Index: LMDZ5/branches/testing/libf/phylmd/write_histhfNMC.h
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/write_histhfNMC.h	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/write_histhfNMC.h	(revision 1665)
@@ -5,5 +5,5 @@
 c
        ndex3d = 0
-       itau_w = itau_phy + itap
+       itau_w = itau_phy + itap + start_time * day_step / iphysiq
 ccc
 c  Champs interpolles sur des niveaux de pression du NMC
Index: LMDZ5/branches/testing/libf/phylmd/write_histmthNMC.h
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/write_histmthNMC.h	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/write_histmthNMC.h	(revision 1665)
@@ -5,5 +5,5 @@
 c
        ndex3d = 0
-       itau_w = itau_phy + itap
+       itau_w = itau_phy + itap + start_time * day_step / iphysiq
 ccc
 c  Champs interpolles sur des niveaux de pression du NMC
Index: LMDZ5/branches/testing/libf/phylmd/write_histrac.h
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/write_histrac.h	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/write_histrac.h	(revision 1665)
@@ -5,5 +5,5 @@
   IF (ecrit_tra > 0.) THEN
      
-     itau_w = itau_phy + nstep
+     itau_w = itau_phy + nstep + start_time * day_step / iphysiq
      
      CALL histwrite_phy(nid_tra,.FALSE.,"phis",itau_w,pphis)
Index: LMDZ5/branches/testing/libf/phylmd/write_paramLMDZ_phy.h
===================================================================
--- LMDZ5/branches/testing/libf/phylmd/write_paramLMDZ_phy.h	(revision 1664)
+++ LMDZ5/branches/testing/libf/phylmd/write_paramLMDZ_phy.h	(revision 1665)
@@ -27,5 +27,5 @@
 c
       ndex2d = 0
-      itau_w = itau_phy + itap
+      itau_w = itau_phy + itap + start_time * day_step / iphysiq
 c
 c Variables globales
Index: LMDZ5/branches/testing/makegcm
===================================================================
--- LMDZ5/branches/testing/makegcm	(revision 1664)
+++ LMDZ5/branches/testing/makegcm	(revision 1665)
@@ -568,6 +568,10 @@
    set phys="L_PHY= LIBPHY="
 else
-   #Default planet type is Earth
-   set cppflags="$cppflags -DCPP_EARTH"
+   #We'll use some physics
+   set cppflags="$cppflags -DCPP_PHYS"
+   if ( `echo $physique | grep -i "^lmd"` != "" ) then
+     #For lmd physics, default planet type is Earth
+     set cppflags="$cppflags -DCPP_EARTH"
+   endif
 endif
 
Index: LMDZ5/branches/testing/makelmdz_fcm
===================================================================
--- LMDZ5/branches/testing/makelmdz_fcm	(revision 1664)
+++ LMDZ5/branches/testing/makelmdz_fcm	(revision 1665)
@@ -27,5 +27,4 @@
 io=ioipsl
 LIBPREFIX=""
-fcm_path=none
 cosp=false
 
@@ -34,4 +33,5 @@
 LIBFGCM=$LMDGCM/libf
 COSP_PATH=$LMDGCM/.void_dir
+fcm_path=$LMDGCM/tools/fcm/bin
 
 ########################################################################
@@ -74,5 +74,5 @@
 [-filtre NOMFILTRE]        : prend le filtre dans libf/NOMFILTRE (def: filtrez)
 [-link LINKS]              : liens optionels avec d'autres librairies
-[-fcm_path path]           : chemin pour fcm (def: le chemin est suppose deja exister dans le PATH)
+[-fcm_path path]           : chemin pour fcm (def: tools/fcm/bin)
 [-ext_src path]            : chemin d'un repertoire source avec des sources externe a compiler avec le modele
  -arch nom_arch            : nom de l'architecture cible
@@ -156,8 +156,5 @@
 # mettre le chemin du fcm dans le path
 ###############################################################
-if  [[ "$fcm_path" != "none" ]]
-then
-    export PATH=${fcm_path}:${PATH}
-fi
+export PATH=${fcm_path}:${PATH}
 
 echo "Chemin du fcm utlise :" 
@@ -193,6 +190,11 @@
 if [[ "$physique" != "nophys" ]]
 then
-   #Default planet type is Earth
+   #We'll use some physics
+   CPP_KEY="$CPP_KEY CPP_PHYS"
+   if [[ "${physique:0:3}" == "lmd" ]]
+   then
+   #For lmd physics, default planet type is Earth
    CPP_KEY="$CPP_KEY CPP_EARTH"
+   fi
 fi
 
Index: LMDZ5/branches/testing/tools/fcm/COPYRIGHT.txt
===================================================================
--- LMDZ5/branches/testing/tools/fcm/COPYRIGHT.txt	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/COPYRIGHT.txt	(revision 1665)
@@ -0,0 +1,109 @@
+!------------------------------------------------------------------------------!
+!              Flexible Configuration Management Software License              !
+!                                                                              !
+!     Please read this Software Licence as you will be bound by its terms      !
+!                           if you use the Software                            !
+!------------------------------------------------------------------------------!
+
+The Licensor:
+-------------
+
+The Met Office of FitzRoy Road, Exeter EX1 3PB, United Kingdom
+--------------------------------------------------------------------------------
+
+1. Licence.
+-----------
+
+The Met Office grants you a non-exclusive, royalty free; world-wide,
+transferable Licence to use, modify, copy and distribute the Flexible
+Configuration Management software ("the software") accompanying this License
+providing:
+
+a. you undertake to provide to the Met Office a copy of any modifications made
+   by you on the same terms contained within this licence agreement;
+
+b. modified files carry prominent notices stating that you changed the files
+   and the date of change;
+
+c. distribution of original or modified files is made free of charge under the
+   terms of this Licence;
+
+d. the appropriate copyright notices, the above copyright notice and a
+   disclaimer of warranty is included with the distribution.
+
+2. Ownership.
+-------------
+
+The Flexible Configuration Management software is Crown copyright and is
+reproduced with the permission of Met Office under delegated authority from
+the Controller of HMSO. The software and documentation are provided to you to
+allow you to exercise your rights under this License, which is granted to you.
+
+3. Duration.
+------------
+
+This license will remain in effect until terminated.
+ 
+4. Termination.
+---------------
+
+You may terminate this license at any time by removing all copies of the
+software from your system.  This License will terminate immediately without
+notice from us if you fail to comply with any of the provisions of this
+License or in the event of your breaching the terms of this licence you are
+given notice that the license has been terminated.  Upon termination you will
+delete all copies of the software and any related documentation.
+
+5. Disclaimer of Warranty.
+--------------------------
+
+a. THE MET OFFICE DISCLAIMS ALL WARRANTIES, REPRESENTATIONS AND PROMISES,
+   INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF SATISFACTORY QUALITY
+   AND FIT FOR THE PURPOSE.  NEITHER DOES THE MET OFFICE MAKE ANY
+   REPRESENTATIONS AS TO COMPATABILITY WITH YOUR OPERATING SYSTEMS AND
+   PLATFORMS.
+
+b. In no event does the Met Office warrant that the software or related
+   documentation will satisfy your requirements, that the software and
+   documentation will be without errors or defects or that the operation of
+   the software will be uninterrupted.
+
+c. IN NO EVENT WILL THE MET OFFICE BE LIABLE FOR ANY OTHER DAMAGES, INCLUDING
+   BUT NOT LIMITED TO DAMAGES FOR LOSS OF PROFITS DATA OR USE OF THE SOFTWARE
+   OR FOR ANY INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES, EVEN IF THE MET
+   OFFICE HAS BEEN SPECIFICALLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+6. General Provisions.
+----------------------
+
+a. You will not do anything, relating to this software that will bring the Met
+   Office into disrepute.
+
+b. You will not use the name of the Met Office or any other contributor to
+   endorse or promote any products derived from the software without the
+   written permission of the Met Office.
+
+7. Acknowledgements.
+--------------------
+
+The Fortran 9X Interface Generator found in file
+./src/lib/Ecmwf/Fortran90_stuff.pm is adapted from a script developed at ECMWF
+and is provided by kind permission of ECMWF under the same terms of this
+Licence.
+
+8. Entire Agreement.
+--------------------
+
+This License constitutes the entire agreement between us with respect to your
+rights or warranties for using the software and related documentation.  If any
+provision of this agreement is determined to be invalid or unenforceable the
+remaining provisions shall continue in full force.
+
+9. Governing Law.
+-----------------
+
+This Agreement is governed by and construed in accordance with the Laws of
+England.
+
+--------------------------------------------------------------------------------
+                                               © British Crown copyright 2006-7.
Index: LMDZ5/branches/testing/tools/fcm/LICENSE.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/LICENSE.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/LICENSE.html	(revision 1665)
@@ -0,0 +1,150 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>Flexible Configuration Management Software License</title>
+  <meta name="copyright" content="&copy; British Crown Copyright">
+  <style type="text/css">
+  <!--
+  body {
+    font: normal normal 10pt Arial, sans-serif;
+  }
+
+  h1 {
+    text-align: center;
+    text-decoration: underline;
+    font: normal bold 14pt Arial, sans-serif;
+  }
+
+  h2 {
+    text-align: left;
+    text-decoration: none;
+    font: normal normal 14pt Arial, sans-serif;
+  }
+
+  h3 {
+    text-align: left;
+    text-decoration: none;
+    font: normal bold 10pt Arial, sans-serif;
+  }
+
+  .copyright {
+    text-align: right;
+    font: normal bold 11pt Arial, sans-serif;
+  }
+
+  ol li {
+    list-style: lower-alpha;
+  }
+  //-->
+  </style>
+</head>
+
+<body>
+  <h1>Flexible Configuration Management Software License</h1>
+
+  <h1>Please read this Software Licence as you will be bound by its terms if
+  you use the Software</h1>
+
+  <h2>The Licensor:</h2>
+
+  <h2>The Met Office of FitzRoy Road, Exeter EX1 3PB, United Kingdom</h2>
+
+  <h3>1. Licence.</h3>
+
+  <p>The Met Office grants you a non-exclusive, royalty free; world-wide,
+  transferable Licence to use, modify, copy and distribute the Flexible
+  Configuration Management software ("the software") accompanying this License
+  providing:</p>
+
+  <ol>
+    <li>you undertake to provide to the Met Office a copy of any modifications
+    made by you on the same terms contained within this licence agreement;</li>
+
+    <li>modified files carry prominent notices stating that you changed the
+    files and the date of change;</li>
+
+    <li>distribution of original or modified files is made free of charge under
+    the terms of this Licence;</li>
+
+    <li>the appropriate copyright notices, the above copyright notice and a
+    disclaimer of warranty is included with the distribution.</li>
+  </ol>
+
+  <h3>2. Ownership.</h3>
+
+  <p>The Flexible Configuration Management software is Crown copyright and is
+  reproduced with the permission of Met Office under delegated authority from
+  the Controller of HMSO. The software and documentation are provided to you to
+  allow you to exercise your rights under this License, which is granted to
+  you.</p>
+
+  <h3>3. Duration.</h3>
+
+  <p>This license will remain in effect until terminated.</p>
+
+  <h3>4. Termination.</h3>
+
+  <p>You may terminate this license at any time by removing all copies of the
+  software from your system. This License will terminate immediately without
+  notice from us if you fail to comply with any of the provisions of this
+  License or in the event of your breaching the terms of this licence you are
+  given notice that the license has been terminated. Upon termination you will
+  delete all copies of the software and any related documentation.</p>
+
+  <h3>5. Disclaimer of Warranty.</h3>
+
+  <ol>
+    <li>THE MET OFFICE DISCLAIMS ALL WARRANTIES, REPRESENTATIONS AND PROMISES,
+    INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF SATISFACTORY QUALITY
+    AND FIT FOR THE PURPOSE. NEITHER DOES THE MET OFFICE MAKE ANY
+    REPRESENTATIONS AS TO COMPATABILITY WITH YOUR OPERATING SYSTEMS AND
+    PLATFORMS.</li>
+
+    <li>In no event does the Met Office warrant that the software or related
+    documentation will satisfy your requirements, that the software and
+    documentation will be without errors or defects or that the operation of
+    the software will be uninterrupted.</li>
+
+    <li>IN NO EVENT WILL THE MET OFFICE BE LIABLE FOR ANY OTHER DAMAGES,
+    INCLUDING BUT NOT LIMITED TO DAMAGES FOR LOSS OF PROFITS DATA OR USE OF THE
+    SOFTWARE OR FOR ANY INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES, EVEN IF
+    THE MET OFFICE HAS BEEN SPECIFICALLY ADVISED OF THE POSSIBILITY OF SUCH
+    DAMAGES.</li>
+  </ol>
+
+  <h3>6. General Provisions.</h3>
+
+  <ol>
+    <li>You will not do anything, relating to this software that will bring the
+    Met Office into disrepute.</li>
+
+    <li>You will not use the name of the Met Office or any other contributor to
+    endorse or promote any products derived from the software without the
+    written permission of the Met Office.</li>
+  </ol>
+
+  <h3>7. Acknowledgements.</h3>
+
+  <p>The Fortran 9X Interface Generator found in file
+  ./src/lib/Ecmwf/Fortran90_stuff.pm is adapted from a script developed at
+  ECMWF and is provided by kind permission of ECMWF under the same terms of
+  this Licence.</p>
+
+  <h3>8. Entire Agreement.</h3>
+
+  <p>This License constitutes the entire agreement between us with respect to
+  your rights or warranties for using the software and related documentation.
+  If any provision of this agreement is determined to be invalid or
+  unenforceable the remaining provisions shall continue in full force.</p>
+
+  <h3>9. Governing Law.</h3>
+
+  <p>This Agreement is governed by and construed in accordance with the Laws of
+  England.</p>
+
+  <div class="copyright">
+    <p>&copy; British Crown copyright 2006-7.</p>
+  </div>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/README
===================================================================
--- LMDZ5/branches/testing/tools/fcm/README	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/README	(revision 1665)
@@ -0,0 +1,4 @@
+FCM release 1-2 created from revision 2131
+
+For further details please refer to the release notes
+which can be found in the directory doc/release_notes.
Index: LMDZ5/branches/testing/tools/fcm/bin/fcm
===================================================================
--- LMDZ5/branches/testing/tools/fcm/bin/fcm	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/bin/fcm	(revision 1665)
@@ -0,0 +1,794 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   fcm
+#
+# SYNOPSIS
+#   fcm SUBCOMMAND [OPTIONS...] ARGS...
+#
+# DESCRIPTION
+#   The fcm command is the frontend of the FCM system. The first argument to the
+#   command must be a recognised subcommand. See "fcm help" for a full list of
+#   functionalities.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard pragmas:
+use warnings;
+use strict;
+
+# Standard modules:
+use File::Basename;
+use File::Spec;
+use Getopt::Long;
+use Cwd;
+
+# FCM component modules:
+use lib File::Spec->catfile (dirname (dirname ($0)), 'lib');
+use Fcm::Config;
+use Fcm::Extract;
+use Fcm::Build;
+use Fcm::Util;
+
+BEGIN {
+  eval {
+    require Fcm::Cm;
+    import Fcm::Cm;
+
+    require Fcm::CmUrl;
+    import Fcm::CmUrl;
+  }
+}
+
+# Function declaration:
+sub cmp_ext_cfg;
+sub invoke_build_system;
+sub invoke_extract_system;
+sub invoke_cfg_printer;
+sub invoke_cm_system;
+sub invoke_www_browser;
+sub invoke_help;
+
+# ------------------------------------------------------------------------------
+
+my $prog      = basename $0;
+my $year      = (localtime)[5] + 1900;
+my $copyright = <<EOF;
+
+(C) Crown copyright $year Met Office. All rights reserved.
+EOF
+
+# List of sub-commands recognised by FCM
+my %subcommand = (
+  HLP => [qw/help ? h/],
+  BLD => [qw/build bld/],
+  EXT => [qw/extract ext/],
+  CFG => [qw/cfg/],
+  GUI => [qw/gui/],
+  CM  => [qw/
+    branch    br
+    conflicts cf
+    add
+    blame     praise annotate ann
+    cat
+    checkout  co
+    cleanup
+    commit    ci
+    copy      cp
+    delete    del    remove   rm
+    diff      di
+    export
+    import
+    info
+    list      ls
+    lock
+    log
+    merge
+    mkdir
+    mkpatch
+    move      mv     rename   ren
+    propdel   pdel   pd
+    propedit  pedit  pe
+    propget   pget   pg
+    proplist  plist  pl
+    propset   pset   ps
+    resolved
+    revert
+    status    stat   st
+    switch    sw
+    unlock
+    update    up
+  /],
+  CMP => [qw/cmp-ext-cfg/],
+  WWW => [qw/www trac/],
+);
+
+# Get configuration settings
+my $config = Fcm::Config->new ();
+$config->get_config ();
+
+# Determine the functionality of this invocation of the command
+my $function = @ARGV ? shift @ARGV : '';
+
+# Run command accordingly
+if (grep {$_ eq $function} @{ $subcommand{BLD} }) {
+  invoke_build_system;
+
+} elsif (grep {$_ eq $function} @{ $subcommand{EXT} }) {
+  invoke_extract_system;
+
+} elsif (grep {$_ eq $function} @{ $subcommand{CFG} }) {
+  invoke_cfg_printer;
+
+} elsif (grep {$_ eq $function} @{ $subcommand{GUI} }) {
+  &run_command (['fcm_gui', @ARGV], METHOD => 'exec');
+
+} elsif (grep {$_ eq $function} @{ $subcommand{CM} }) {
+  invoke_cm_system;
+
+} elsif (grep {$_ eq $function} @{ $subcommand{CMP} }) {
+  cmp_ext_cfg;
+
+} elsif (grep {$_ eq $function} @{ $subcommand{WWW} }) {
+  invoke_www_browser;
+
+} elsif ($function =~ /^\s*$/ or grep {$_ eq $function} @{ $subcommand{HLP} }) {
+  invoke_help;
+
+} else {
+  w_report 'Unknown command: ', $function;
+  e_report 'Type "', $prog, ' help" for usage';
+}
+
+exit;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfg = &main::cfg ();
+#
+# DESCRIPTION
+#   Return the $config variable.
+# ------------------------------------------------------------------------------
+
+sub cfg {
+  return $config;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &cmp_ext_cfg ();
+#
+# DESCRIPTION
+#   Compare two similar extract configuration files.
+# ------------------------------------------------------------------------------
+
+sub cmp_ext_cfg {
+  # Check options
+  # ----------------------------------------------------------------------------
+  my ($wiki, $verbose);
+
+  GetOptions ('wiki|w=s' => \$wiki, 'verbose|v' => \$verbose);
+
+  # Check arguments
+  # ----------------------------------------------------------------------------
+  e_report $prog, ' ', $function,
+           ': 2 extract config files must be specified, abort.'
+    if @ARGV < 2;
+
+  # Invoke 2 new instances of the Fcm::Extract class
+  # ----------------------------------------------------------------------------
+  my (@cfg, $rc);
+  for my $i (0 .. 1) {
+    $cfg[$i] = Fcm::Extract->new (CFG_SRC => $ARGV[$i]);
+
+    # Read the extract configuration file
+    $rc = $cfg[$i]->decipher_cfg;
+    $rc = $cfg[$i]->expand_cfg if $rc;
+
+    last if not $rc;
+  }
+
+  # Throw error if command has failed
+  # ----------------------------------------------------------------------------
+  e_report $prog, ' ', $function,
+           ': cannot read extract configuration file, abort' if not $rc;
+
+  # Get list of URLs
+  # ----------------------------------------------------------------------------
+  my @urls = ();
+  for my $i (0 .. 1) {
+    # List of branches in each extract configuration file
+    my @branches = $cfg[$i]->branches;
+
+    for my $branch (@branches) {
+      # Ignore declarations of local directories
+      next if $branch->type eq 'user';
+
+      # List of SRC declarations in each branch
+      my %dirs = $branch->dirs;
+
+      for my $dir (values %dirs) {
+        # Set up a new instance of Fcm::CmUrl object for each SRC declaration
+        my $cm_url = Fcm::CmUrl->new (
+          URL => $dir . ($branch->version ? '@' . $branch->version : ''),
+        );
+
+        $urls[$i]{$cm_url->branch_url}{$dir} = $cm_url;
+      }
+    }
+  }
+
+  # Compare
+  # ----------------------------------------------------------------------------
+  my %log;
+  for my $i (0 .. 1) {
+    # Compare the first file with the second one and then vice versa
+    my $j = ($i == 0) ? 1 : 0;
+
+    for my $branch (sort keys %{ $urls[$i] }) {
+      if (exists $urls[$j]{$branch}) {
+        # Same REPOS declarations in both files
+        for my $dir (sort keys %{ $urls[$i]{$branch} }) {
+          if (exists $urls[$j]{$branch}{$dir}) {
+            # Same SRC declarations in both files, only need to compare once
+            next if $i == 1;
+
+            my $this_url = $urls[$i]{$branch}{$dir};
+            my $that_url = $urls[$j]{$branch}{$dir};
+
+            # Check whether their last changed revisions are the same
+            my $this_rev = $this_url->svninfo (FLAG => 'Last Changed Rev');
+            my $that_rev = $that_url->svninfo (FLAG => 'Last Changed Rev');
+
+            # Make sure last changed revisions differ
+            next if $this_rev eq $that_rev;
+
+            # Not interested in the log before the minimum revision
+            my $min_rev = ($this_url->pegrev > $that_url->pegrev)
+                          ? $that_url->pegrev : $this_url->pegrev;
+
+            $this_rev = $min_rev if $this_rev < $min_rev;
+            $that_rev = $min_rev if $that_rev < $min_rev;
+
+            # Get list of changed revisions using the commit log
+            my $u   = ($this_rev > $that_rev) ? $this_url : $that_url;
+            my %revs = $u->svnlog (REV => [$this_rev, $that_rev]);
+
+            for my $rev (keys %revs) {
+              # Check if revision is already in the list
+              next if exists $log{$branch}{$rev};
+
+              # Not interested in the minimum revision
+              next if $rev == $min_rev;
+
+              # Get list of changed paths. Accept this revision only if it
+              # contains changes in the current branch
+              my %paths  = %{ $revs{$rev}{paths} };
+
+              for my $path (keys %paths) {
+                my $change_url = Fcm::CmUrl->new (URL => $u->root . $path);
+
+                if ($change_url->branch eq $u->branch) {
+                  $log{$branch}{$rev} = $u;
+                  last;
+                }
+              }
+            }
+
+          } else {
+            # Report SRC declaration in one file but not in another
+            print $urls[$i]{$branch}{$dir}->url_peg, ':', "\n";
+            print '  in    : ', $ARGV[$i], "\n";
+            print '  not in: ', $ARGV[$j], "\n\n";
+          }
+        }
+
+      } else {
+        # Report REPOS declaration in one file but not in another
+        print $branch, ':', "\n";
+        print '  in    : ', $ARGV[$i], "\n";
+        print '  not in: ', $ARGV[$j], "\n\n";
+      }
+    }
+  }
+
+  # Report modifications
+  # ----------------------------------------------------------------------------
+  print 'Revisions at which declared source directories are modified:', "\n\n"
+    if keys %log;
+
+  if (defined $wiki) {
+    # Output in wiki format
+    my $wiki_url  = Fcm::CmUrl->new (URL => &expand_url_keyword (URL => $wiki));
+    my $base_trac = $wiki
+                    ? &get_browser_url (URL => $wiki_url->project_url)
+                    : $wiki_url;
+    $base_trac    = $wiki_url if not $base_trac;
+
+    for my $branch (sort keys %log) {
+      # Name of the branch
+      my $branch_trac = &get_browser_url (URL => $branch);
+      $branch_trac =~ s#^$base_trac(?:/*|$)#source:#;
+
+      print '[', $branch_trac, ']:', "\n";
+
+      # Revision table
+      for my $rev (sort {$b <=> $a} keys %{ $log{$branch} }) {
+        print $log{$branch}{$rev}->display_svnlog ($rev, $base_trac), "\n";
+      }
+
+      print "\n";
+    }
+
+  } else {
+    my $separator = '-' x 80 . "\n";
+
+    for my $branch (sort keys %log) {
+      # Output in plain text format
+      print $branch, ':', "\n";
+
+      if ($verbose or &cfg->verbose > 1) {
+        # Verbose mode, print revision log
+        for my $rev (sort {$b <=> $a} keys %{ $log{$branch} }) {
+          print $separator, $log{$branch}{$rev}->display_svnlog ($rev), "\n";
+        }
+
+      } else {
+        # Normal mode, print list of revisions
+        print join (' ', sort {$b <=> $a} keys %{ $log{$branch} }), "\n";
+      }
+
+      print $separator, "\n";
+    }
+  }
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &invoke_build_system ();
+#
+# DESCRIPTION
+#   Invoke the build system.
+# ------------------------------------------------------------------------------
+
+sub invoke_build_system {
+  my ($archive, $full, $ignore_lock, $jobs, $stage, @targets, $verbose);
+
+  GetOptions (
+    'archive|a'   => \$archive,     # switch on archive mode?
+    'full|f'      => \$full,        # full build?
+    'ignore-lock' => \$ignore_lock, # ignore lock file?
+    'jobs|j=i'    => \$jobs,        # number of parallel jobs in make
+    'stage|s=s'   => \$stage,       # build up to and including this stage
+    'targets|t=s' => \@targets,     # make targets
+    'verbose|v=i' => \$verbose,     # verbose level
+  );
+
+  # Verbose level
+  $config->verbose ($verbose) if defined $verbose;
+
+  # Invoke a new instance of the Fcm::Build class
+  my $bld = Fcm::Build->new (CFG_SRC  => @ARGV ? join (' ', @ARGV) : cwd ());
+
+  # Perform build
+  $bld->build (
+    ARCHIVE     => $archive,
+    FULL        => $full,
+    IGNORE_LOCK => $ignore_lock,
+    JOBS        => $jobs ? $jobs : 1,
+    STAGE       => $stage ? $stage : 5,
+    TARGETS     => (@targets ? [split (/:/, join (':', @targets))] : [qw/all/]),
+  );
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &invoke_extract_system ();
+#
+# DESCRIPTION
+#   Invoke the extract system.
+# ------------------------------------------------------------------------------
+
+sub invoke_extract_system {
+  my ($full, $ignore_lock, $verbose);
+
+  GetOptions (
+    'full|f'      => \$full,        # full extract?
+    'ignore-lock' => \$ignore_lock, # ignore lock file?
+    'verbose|v=i' => \$verbose,     # verbose level
+  );
+
+  $config->verbose ($verbose) if defined $verbose;
+
+  # Invoke a new instance of the Fcm::Extract class
+  my $ext = Fcm::Extract->new (CFG_SRC => @ARGV ? join (' ', @ARGV) : cwd ());
+
+  # Perform extract
+  $ext->extract (FULL => $full, IGNORE_LOCK => $ignore_lock);
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &invoke_cfg_printer ();
+#
+# DESCRIPTION
+#   Invoke the CFG file pretty printer.
+# ------------------------------------------------------------------------------
+
+sub invoke_cfg_printer {
+
+  use Fcm::CfgFile;
+
+  my $out_file;
+  GetOptions (
+    'output|o=s'  => \$out_file,  # output file for print
+  );
+
+  my $file = join (' ', @ARGV);
+  e_report $prog, ' ', $function, ': file not specified, abort.' if ! $file;
+
+  # Invoke a new Fcm::CfgFile instance
+  my $cfg = Fcm::CfgFile->new (SRC => $file);
+
+  # Read the cfg file
+  my $read = $cfg->read_cfg;
+  e_report if not $read;
+
+  # Pretty print CFG file
+  $cfg->print_cfg ($out_file);
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &invoke_cm_system ();
+#
+# DESCRIPTION
+#   Invoke a code management system command.
+# ------------------------------------------------------------------------------
+
+sub invoke_cm_system {
+
+  &cm_command ($function);
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &invoke_www_browser ();
+#
+# DESCRIPTION
+#   Invoke a web browser on the specified PATH.
+# ------------------------------------------------------------------------------
+
+sub invoke_www_browser {
+
+  # Options
+  my ($browser);
+  GetOptions (
+    'browser|b=s' => \$browser, # browser command
+  );
+
+  $browser = &cfg->setting (qw/MISC WEB_BROWSER/) unless $browser;
+
+  # Arguments
+  my ($arg) = @ARGV ? $ARGV[0] : (&is_wc () ? '.' : '');
+  e_report $prog, ' ', $function,
+           ': input URL not specified and . not a working copy, abort.'
+    if not $arg;
+
+  # Local PATH?
+  $arg = &expand_tilde ($arg);
+  $arg = &get_url_of_wc ($arg) if -e $arg;
+
+  # Expand URL and revision keywords
+  my $www_url = &expand_url_keyword (URL => $arg);
+  my $rev     = 'HEAD';
+
+  if ($www_url =~ m#^(\w+://\S+)@(\S+)$#) {
+    $www_url = $1;
+    $rev     = $2;
+  }
+
+  $rev = &expand_rev_keyword (URL => $www_url, REV => $rev, HEAD => 1)
+    unless uc ($rev) eq 'HEAD';
+
+  # Get web browser URL
+  $www_url = &get_browser_url (URL => $www_url);
+  die 'WWW URL not defined for "', $arg, '", abort' unless $www_url;
+
+  $www_url = $www_url . '?rev=' . $rev;
+
+  # Execute command
+  my @command = (split (/\s+/, $browser), $www_url);
+  &run_command (\@command, METHOD => 'exec', PRINT => 1);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &invoke_help ();
+#
+# DESCRIPTION
+#   Invoke help.
+# ------------------------------------------------------------------------------
+
+sub invoke_help {
+
+  my $cmd = @ARGV ? shift @ARGV : undef;
+
+  if ($cmd) {
+    if (grep {$_ eq $cmd} @{ $subcommand{BLD} }) {
+      print <<EOF;
+$prog $cmd: invoke the build system.
+usage: $prog $cmd [OPTIONS...] [CFGFILE]
+
+  The path to a CFG file may be provided. Otherwise, the build system
+  searches the default locations for a bld cfg file.
+
+  If no option is specified, the options "-s 5 -t all -j 1 -v 1" are assumed.
+
+  If the option for full build is specified, the sub-directories created by
+  previous builds will be removed, so that the current build can start cleanly.
+
+  The -s option can be used to limit the actions performed by the build system
+  up to a named stage. The stages are:
+    "1", "s" or "setup"                - stage 1, setup
+    "2", "pp" or "pre_process"         - stage 2, pre-process
+    "3", "gd" or "generate_dependency" - stage 3, generate dependency
+    "4", "gi" or "generate_interface"  - stage 4, generate Fortran 9X interface
+    "5", "m", "make"                   - stage 5, make
+
+  If a colon separated list of targets is specified using the -t option, the
+  default targets specified in the configuration file will not be used.
+
+  If archive mode is switched on, build sub-directories that are only used
+  in the build process will be archived to TAR files. The default is off.
+
+  If specified, the verbose level must be an integer greater than 0. Verbose
+  level 0 is the quiet mode. Increasing the verbose level will increase the
+  amount of diagnostic output.
+
+  When a build is invoked, it sets up a lock file in the build root directory.
+  The lock is normally removed at the end of the build. While the lock file is
+  in place, othe build commands invoked in the same root directory will fail.
+  If you need to bypass this check for whatever reason, you can invoke the
+  build system with the --ignore-lock option.
+
+Valid options:
+  -a [--archive]     : archive build sub-directories?
+  -f [--full]        : full build
+  --ignore-lock      : ignore lock files in build root directory
+  -j [--jobs] arg    : number of parallel jobs that "make" can handle
+  -s [--stage] arg   : perform build up to a named stage
+  -t [--targets] arg : build a colon (:) separated list of targets
+  -v [--verbose] arg : verbose level
+$copyright
+EOF
+
+    } elsif (grep {$_ eq $cmd} @{ $subcommand{EXT} }) {
+      print <<EOF;
+$prog $cmd: invoke the extract system.
+usage: $prog $cmd [OPTIONS...] [CFGFILE]
+
+  The path to a CFG file may be provided. Otherwise, the extract system
+  searches the default locations for an ext cfg file.
+
+  If no option is specified, the system will attempt an incremental extract
+  where appropriate.
+
+  If specified, the verbose level must be an integer greater than 0. Verbose
+  level 0 is the quiet mode. Increasing the verbose level will increase the
+  amount of diagnostic output.
+
+  When an extract is invoked, it sets up a lock file in the extract destination
+  root directory. The lock is normally removed at the end of the extract. While
+  the lock file is in place, othe extract commands invoked in the same
+  destination root directory will fail. If you need to bypass this check for
+  whatever reason, you can invoke the extract system with the --ignore-lock
+  option.
+
+Valid options:
+  -f [--full]        : perform a full/clean extract
+  --ignore-lock      : ignore lock files in build root directory
+  -v [--verbose] arg : verbose level
+$copyright
+EOF
+
+    } elsif (grep {$_ eq $cmd} @{ $subcommand{CFG} }) {
+      print <<EOF;
+$prog $cmd: invoke the CFG file pretty printer.
+usage: $prog $cmd [OPTIONS...] FILE
+
+  If no option is specified, the output will be sent to standard output.
+
+Valid options:
+  -o [--output] arg : send output to a file as specified by arg.
+$copyright
+EOF
+
+    } elsif (grep {$_ eq $cmd} @{ $subcommand{GUI} }) {
+      print <<EOF;
+$prog $cmd: invoke the GUI wrapper for CM commands.
+usage: $prog $cmd DIR
+
+  The optional argument DIR modifies the initial working directory.
+$copyright
+EOF
+
+    } elsif (grep {$_ eq $cmd} @{ $subcommand{CM} }) {
+      @ARGV = qw(--help);
+      cm_command ($cmd);
+
+    } elsif (grep {$_ eq $cmd} @{ $subcommand{CMP} }) {
+      print <<EOF;
+$prog $cmd: compare two similar extract configuration files.
+usage: $prog $cmd [OPTIONS...] CFG1 CFG2
+
+  Compares the extract configurations of two similar extract configuration
+  files CFG1 and CFG2.
+
+Valid options:
+  -v [--verbose]  : print revision tables in verbose mode. In particular,
+                    display the change log of each revision.
+  -w [--wiki] arg : print revision tables in wiki format. The argument to this
+                    option must be the Subversion URL or FCM URL keyword of a
+                    FCM project associated with the intended Trac system. This
+                    option overrides the -v option.
+$copyright
+EOF
+
+    } elsif (grep {$_ eq $cmd} @{ $subcommand{WWW} }) {
+      print <<EOF;
+$prog $cmd: invoke the web repository browser on a Subversion URL.
+usage: $prog $cmd [OPTIONS...] [PATH]
+
+  If PATH is specified, it must be a FCM URL keyword, a Subversion URL or the
+  PATH to a local working copy. If not specified, the current working directory
+  is assumed to be a working copy. If the --browser option is specified, the
+  specified web browser command is used to launch the repository browser.
+  Otherwise, it attempts to use the default browser from the configuration
+  setting.
+
+Valid options:
+  -b [--browser] arg : specify a command arg for the web browser.
+$copyright
+EOF
+
+    } elsif (grep {$_ eq $cmd} @{ $subcommand{HLP} }) {
+      print <<EOF;
+help (?, h): Describe the usage of $prog or its subcommands.
+usage: $prog help [SUBCOMMAND...]
+$copyright
+EOF
+
+      &run_command ([qw/svn help/, $cmd, @ARGV], PRINT => 1);
+
+    } else {
+      warn $prog, ' help: "', $cmd, '" not recognised';
+      $cmd = undef;
+    }
+  }
+
+  if (not $cmd) {
+    # Get output from "svn help"
+    my @lines = &run_command (
+      [qw/svn help/], DEVNULL => 1, METHOD => 'qx', ERROR => 'ignore',
+    );
+
+    # Get release number, (and revision number from revision number file)
+    my $release  = &cfg->setting ('RELEASE');
+    my $rev_file = &cfg->setting ('REV_FILE');
+
+    if (-r $rev_file) {
+      open FILE, '<', $rev_file;
+      my $rev = readline 'FILE';
+      close FILE;
+
+      chomp $rev;
+      $release .= '-dev (r' . $rev . ')' if $rev;
+    }
+
+    # Print common help
+    print <<EOF;
+usage: $prog <subcommand> [options] [args]
+Flexible configuration management system, release $release.
+Type "$prog help <subcommand>" for help on a specific subcommand.
+
+Available subcommands:
+  help       (h, ?) - help
+  build      (bld)  - build system
+EOF
+
+    # The following are only available on platforms with "svn" installed
+    if (@lines) {
+      print <<EOF;
+  branch     (br)   - cm system: branch info & creation
+  cfg               - CFG file pretty printer
+  cmp-ext-cfg       - compare two similar extract configuration files
+  conflicts  (cf)   - cm system: resolve conflicts
+  extract    (ext)  - extract system
+  mkpatch           - create patches from specified revisions of a URL
+  trac       (www)  - cm system: browse a path using the web browser
+  <SVN COMMANDS>    - any Subversion sub-commands
+EOF
+    }
+
+    # Print FCM copyright notice
+    print $copyright;
+
+    # Print output from "svn help"
+    if (@lines) {
+      print "\n";
+      &print_command ([qw/svn help/]);
+      print @lines;
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ans = &main::get_input (MESSAGE => $mesg, TYPE => $type, DEFAULT => $def);
+#
+# DESCRIPTION
+#   Get an input string from the user and return it as $ans. MESSAGE is the
+#   main message printed on screen to prompt the user for an input.  If TYPE is
+#   'YN', print message to prompt user to enter either 'y' or 'n'. If TYPE is
+#   'YNA', then 'a' is given as a third option. If DEFAULT is set, print message
+#   to inform user that the return value will be set to the $def (if nothing is
+#   entered).
+# ------------------------------------------------------------------------------
+
+sub get_input {
+  my %args = @_;
+  my $type  = exists $args{TYPE}    ? $args{TYPE}    : '';
+  my $mesg  = exists $args{MESSAGE} ? $args{MESSAGE} : '';
+  my $def   = exists $args{DEFAULT} ? $args{DEFAULT} : '';
+
+  my $ans;
+
+  while (1) {
+    # Print the prompt
+    print $mesg;
+    print "\n", 'Enter "y" or "n"' if uc ($type) eq 'YN';
+    print "\n", 'Enter "y", "n" or "a"' if uc ($type) eq 'YNA';
+    print ' (or just press <return> for "', $def, '")' if $def;
+    print ': ';
+
+    # Get answer from STDIN
+    $ans = <STDIN>;
+    chomp $ans;
+
+    # Set answer to default, if necessary
+    $ans = $def if ($def and not $ans);
+
+    if ($type =~ /^yna?$/i) {
+      # For YN and YNA type dialog boxes,
+      # check that the answer is in the correct form
+      my $pat = (uc ($type) eq 'YN' ? 'y|n' : 'y|n|a');
+      last if $ans =~ /^(?:$pat)/i;
+
+    } else {
+      last;
+    }
+  }
+
+  return $ans;
+}
+
+# ------------------------------------------------------------------------------
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/bin/fcm_graphic_diff
===================================================================
--- LMDZ5/branches/testing/tools/fcm/bin/fcm_graphic_diff	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/bin/fcm_graphic_diff	(revision 1665)
@@ -0,0 +1,90 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   fcm_graphic_diff
+#
+# SYNOPSIS
+#   fcm_graphic_diff [-u] [-L OLD_DESC] [-L NEW_DESC] OLD NEW
+#
+# DESCRIPTION
+#   Wrapper script which invokes a graphical diff tool. Its interface is
+#   compatible with the "svn diff" command and can be used in combination with
+#   its "--diff-cmd" option. The command prints the OLD_DESC and NEW_DESC if
+#   they are both set. The two arguments OLD and NEW must be set and are the
+#   files to compare. The graphical diff tool invoked depends on the value of
+#   the FCM_GRAPHIC_DIFF environment variable. The command exits if the
+#   environment variable is not set.
+#
+# COPYRIGHT
+#   This program is part of the FCM system.
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard pragmas:
+use warnings;
+use strict;
+
+use Getopt::Long;
+
+# ------------------------------------------------------------------------------
+
+my ($u, @label);
+GetOptions ('u' => \$u, 'L=s' => \@label);
+
+# Check existence of files
+for my $i (0 .. 1) {
+  die $ARGV[$i], ': not found, abort' unless $ARGV[$i] and -f $ARGV[$i];
+}
+
+my ($old, $new) = @ARGV;
+
+if ($old =~ m#.svn/empty-file$#) {
+  print 'Skipping new file', "\n\n";
+
+} elsif ($new =~ m#.svn/empty-file$#) {
+  print 'Skipping deleted file', "\n\n";
+
+} elsif (-z $old) {
+  print 'Skipping as old file is empty (or does not exist)', "\n\n";
+
+} elsif (-z $new) {
+  print 'Skipping as new file is empty (or deleted)', "\n\n";
+
+} elsif (-B $new) {
+  print 'Skipping binary file', "\n\n";
+
+} else {
+  # Print descriptions of files
+  if (@label >= 2) {
+    print '--- ', $label[0], "\n", '+++ ', $label[1], "\n\n";
+  }
+
+  # FCM_GRAPHIC_DIFF is the graphical diff tool command
+  my $cmd = (exists $ENV{FCM_GRAPHIC_DIFF} ? $ENV{FCM_GRAPHIC_DIFF} : 'xxdiff');
+
+  if ($cmd) {
+    my @options = ();
+
+    # Set options for labels if appropriate
+    if (@label >= 2) {
+      if ($cmd eq 'tkdiff') {
+        # Use tkdiff
+        @options = ('-L', $label[0], '-L', $label[1]);
+
+      } elsif ($cmd eq 'xxdiff') {
+        # Use xxdiff
+        @options = ('--title1', $label[0], '--title2', $label[1]);
+      }
+    }
+
+    # Execute the command
+    my @command = ($cmd, @options, $old, $new);
+    exec (@command) or die 'Cannot execute: ', join (' ', @command);
+  }
+
+  exit;
+}
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/bin/fcm_gui
===================================================================
--- LMDZ5/branches/testing/tools/fcm/bin/fcm_gui	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/bin/fcm_gui	(revision 1665)
@@ -0,0 +1,1321 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   fcm_gui
+#
+# SYNOPSIS
+#   fcm_gui [DIR]
+#
+# DESCRIPTION
+#   The fcm_gui command is a simple graphical user interface for some of the
+#   commands of the FCM system. The optional argument DIR modifies the initial
+#   working directory.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard pragmas
+use warnings;
+use strict;
+
+# Standard modules
+use File::Basename;
+use File::Spec::Functions;
+use Cwd;
+use Tk;
+use Tk::ROText;
+
+# FCM component modules:
+use lib catfile (dirname (dirname ($0)), 'lib');
+use Fcm::Config;
+use Fcm::Util;
+use Fcm::Timer;
+
+# ------------------------------------------------------------------------------
+
+# Argument
+if (@ARGV) {
+  my $dir = shift @ARGV;
+  chdir $dir if -d $dir;
+}
+
+# Get configuration settings
+my $config = Fcm::Config->new ();
+$config->get_config ();
+
+# ------------------------------------------------------------------------------
+
+# FCM subcommands
+my @subcmds = qw/CHECKOUT BRANCH STATUS DIFF ADD DELETE MERGE CONFLICTS COMMIT
+                 UPDATE SWITCH/;
+
+# Subcommands allowed when CWD is not a WC
+my @nwc_subcmds = qw/CHECKOUT BRANCH/;
+
+# Subcommands allowed, when CWD is a WC
+my @wc_subcmds = qw/STATUS BRANCH DIFF ADD DELETE MERGE CONFLICTS COMMIT UPDATE
+                    SWITCH/;
+
+# Subcommands that apply to WC only
+my @wco_subcmds = qw/BRANCH STATUS DIFF ADD DELETE MERGE CONFLICTS COMMIT UPDATE
+                     SWITCH/;
+
+# Subcommands that apply to top level WC only
+my @wcto_subcmds = qw/BRANCH MERGE COMMIT UPDATE SWITCH/;
+
+# Selected subcommand
+my $selsubcmd = '';
+
+# Selected subcommand is running?
+my $cmdrunning = 0;
+
+# PID of running subcommand
+my $cmdpid = undef;
+
+# List of subcommand frames
+my %subcmd_f;
+
+# List of subcommand buttons
+my %subcmd_b;
+
+# List of subcommand button help strings
+my %subcmd_help = (
+  BRANCH    => 'list information about, create or delete a branch.',
+  CHECKOUT  => 'check out a working copy from a repository.',
+  STATUS    => 'print the status of working copy files and directories.',
+  DIFF      => 'display the differences in modified files.',
+  ADD       => 'put files and directories under version control.',
+  DELETE    => 'remove files and directories from version control.',
+  MERGE     => 'merge changes into your working copy.',
+  CONFLICTS => 'use "xxdiff" to resolve any conflicts within your working copy.',
+  COMMIT    => 'send changes from your working copy to the repository.',
+  UPDATE    => 'bring changes from the repository into your working copy.',
+  SWITCH    => 'update your working copy to a different URL.',
+);
+
+for (keys %subcmd_help) {
+  $subcmd_help{$_} = 'Select the "' . lc ($_) . '" sub-command - ' .
+                     $subcmd_help{$_};
+}
+
+# List of subcommand button bindings (key name and underline position)
+my %subcmd_bind = (
+  BRANCH    => {KEY => '<Alt-Key-b>', U => 0},
+  CHECKOUT  => {KEY => '<Alt-Key-o>', U => 5},
+  STATUS    => {KEY => '<Alt-Key-s>', U => 0},
+  DIFF      => {KEY => '<Alt-Key-d>', U => 0},
+  ADD       => {KEY => '<Alt-Key-a>', U => 0},
+  DELETE    => {KEY => '<Alt-Key-t>', U => 4},
+  MERGE     => {KEY => '<Alt-Key-m>', U => 0},
+  CONFLICTS => {KEY => '<Alt-Key-f>', U => 3},
+  COMMIT    => {KEY => '<Alt-Key-c>', U => 0},
+  UPDATE    => {KEY => '<Alt-Key-u>', U => 0},
+  SWITCH    => {KEY => '<Alt-Key-w>', U => 1},
+);
+
+# List of subcommand variables
+my %subcmdvar = (
+  CWD       => cwd (),
+  WCT       => '',
+  CWD_URL   => '',
+  WCT_URL   => '',
+
+  BRANCH    => {
+    OPT     => 'info',
+    URL     => '',
+    NAME    => '',
+    TYPE    => 'DEV',
+    REVFLAG => 'NORMAL',
+    REV     => '',
+    TICKET  => '',
+    SRCTYPE => 'trunk',
+    S_CHD   => 0,
+    S_SIB   => 0,
+    S_OTH   => 0,
+    VERBOSE => 0,
+    OTHER   => '',
+  },
+
+  CHECKOUT  => {
+    URL     => '',
+    REV     => 'HEAD',
+    PATH    => '',
+    OTHER   => '',
+  },
+
+  STATUS    => {
+    USEWCT  => 0,
+    UPDATE  => 0,
+    VERBOSE => 0,
+    OTHER   => '',
+  },
+
+  DIFF      => {
+    USEWCT  => 0,
+    GRAPHIC => 1,
+    BRANCH  => 0,
+    URL     => '',
+    OTHER   => '',
+  },
+
+  ADD       => {
+    USEWCT  => 0,
+    CHECK   => 1,
+    OTHER   => '',
+  },
+
+  DELETE    => {
+    USEWCT  => 0,
+    CHECK   => 1,
+    OTHER   => '',
+  },
+
+  MERGE     => {
+    USEWCT  => 1,
+    SRC     => '',
+    MODE    => 'automatic',
+    DRYRUN  => 0,
+    VERBOSE => 0,
+    REV     => '',
+    OTHER   => '',
+  },
+
+  CONFLICTS => {
+    USEWCT  => 0,
+    OTHER   => '',
+  },
+
+  COMMIT    => {
+    USEWCT  => 1,
+    DRYRUN  => 0,
+    OTHER   => '',
+  },
+
+  UPDATE    => {
+    USEWCT  => 1,
+    OTHER   => '',
+  },
+
+  SWITCH    => {
+    USEWCT  => 1,
+    URL     => '',
+    OTHER   => '',
+  },
+);
+
+# List of action buttons
+my %action_b;
+
+# List of action button help strings
+my %action_help = (
+  QUIT  => 'Quit fcm gui',
+  HELP  => 'Print help to the output text box for the selected sub-command',
+  CLEAR => 'Clear the output text box',
+  RUN   => 'Run the selected sub-command',
+);
+
+# List of action button bindings
+my %action_bind = (
+  QUIT  => {KEY => '<Control-Key-q>', U => undef},
+  HELP  => {KEY => '<F1>'           , U => undef},
+  CLEAR => {KEY => '<Alt-Key-l>'    , U => 1},
+  RUN   => {KEY => '<Alt-Key-r>'    , U => 0},
+);
+
+# List of branch subcommand options
+my %branch_opt = (
+  INFO   => undef,
+  CREATE => undef,
+  DELETE => undef,
+  LIST   => undef,
+);
+
+# List of branch create types
+my %branch_type = (
+  'DEV'         => undef,
+  'DEV::SHARE'  => undef,
+  'TEST'        => undef,
+  'TEST::SHARE' => undef,
+  'PKG'         => undef,
+  'PKG::SHARE'  => undef,
+  'PKG::CONFIG' => undef,
+  'PKG::REL'    => undef,
+);
+
+# List of branch create source type
+my %branch_srctype = (
+  TRUNK  => undef,
+  BRANCH => undef,
+);
+
+# List of branch create revision prefix option
+my %branch_revflag = (
+  NORMAL => undef,
+  NUMBER => undef,
+  NONE   => undef,
+);
+
+# List of branch info/delete options
+my %branch_info_opt = (
+  S_CHD   => 'Show children',
+  S_SIB   => 'Show siblings',
+  S_OTH   => 'Show other',
+  VERBOSE => 'Print extra information',
+);
+
+# Text in the status bar
+my $statustext = '';
+
+# ------------------------------------------------------------------------------
+
+my $mw = MainWindow->new ();
+
+my $mw_title = 'FCM GUI';
+$mw->title ($mw_title);
+
+# Frame containing subcommand selection buttons
+my $top_f = $mw->Frame ()->grid (
+  '-row'    => 0,
+  '-column' => 0,
+  '-sticky' => 'w',
+);
+
+# Frame containing subcommand options
+my $mid_f = $mw->Frame ()->grid (
+  '-row'    => 1,
+  '-column' => 0,
+  '-sticky' => 'ew',
+);
+
+# Frame containing action buttons
+my $bot_f = $mw->Frame ()->grid (
+  '-row'    => 2,
+  '-column' => 0,
+  '-sticky' => 'ew',
+);
+
+# Text box to display output
+my $out_t  = $mw->Scrolled ('ROText', '-scrollbars' => 'osow')->grid (
+  '-row'    => 3,
+  '-column' => 0,
+  '-sticky' => 'news',
+);
+
+# Text box - allow scroll with mouse wheel
+$out_t->bind (
+  '<4>' => sub {
+    $_[0]->yview ('scroll', -1, 'units') unless $Tk::strictMotif;
+  },
+);
+
+$out_t->bind (
+  '<5>' => sub {
+    $_[0]->yview ('scroll', +1, 'units') unless $Tk::strictMotif;
+  },
+);
+
+# Status bar
+$mw->Label (
+  '-textvariable' => \$statustext,
+  '-relief'       => 'groove',
+)->grid (
+  '-row'    => 4,
+  '-column' => 0,
+  '-sticky' => 'ews',
+);
+
+# Main window grid configure
+{
+  my ($cols, $rows) = $mw->gridSize ();
+  $mw->gridColumnconfigure ($_, '-weight' => 1) for (0 .. $cols - 1);
+  $mw->gridRowconfigure    ( 3, '-weight' => 1);
+}
+
+# Frame grid configure
+{
+  my ($cols, $rows) = $mid_f->gridSize ();
+  $bot_f->gridColumnconfigure (3, '-weight' => 1);
+}
+
+$mid_f->gridRowconfigure    (0, '-weight' => 1);
+$mid_f->gridColumnconfigure (0, '-weight' => 1);
+
+# ------------------------------------------------------------------------------
+
+# Buttons to select subcommands
+{
+  my $col = 0;
+  for my $name (@subcmds) {
+    $subcmd_b{$name} = $top_f->Button (
+      '-text'    => uc (substr ($name, 0, 1)) . lc (substr ($name, 1)),
+      '-command' => [\&button_clicked, $name],
+      '-width'   => 8,
+    )->grid (
+      '-row'    => 0,
+      '-column' => $col++,
+      '-sticky' => 'w',
+    );
+
+    $subcmd_b{$name}->bind ('<Enter>', sub {$statustext = $subcmd_help{$name}});
+    $subcmd_b{$name}->bind ('<Leave>', sub {$statustext = ''});
+
+    $subcmd_b{$name}->configure ('-underline' => $subcmd_bind{$name}{U})
+      if defined $subcmd_bind{$name}{U};
+
+    $mw->bind ($subcmd_bind{$name}{KEY}, sub {$subcmd_b{$name}->invoke});
+  }
+}
+
+# ------------------------------------------------------------------------------
+
+# Frames to contain subcommands options
+{
+  my %row = ();
+
+  for my $name (@subcmds) {
+    $subcmd_f{$name} = $mid_f->Frame ();
+    $subcmd_f{$name}->gridColumnconfigure (1, '-weight' => 1);
+
+    $row{$name} = 0;
+
+    # Widgets common to all sub-commands
+    $subcmd_f{$name}->Label ('-text' => 'Current working directory: ')->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+    $subcmd_f{$name}->Label ('-textvariable' => \($subcmdvar{CWD}))->grid (
+      '-row'    => $row{$name}++,
+      '-column' => 1,
+      '-sticky' => 'w',
+    );
+  }
+
+  # Widgets common to all sub-commands that apply to working copies
+  for my $name (@wco_subcmds) {
+    my @labtxts = (
+      'Corresponding URL: ',
+      'Working copy top: ',
+      'Corresponding URL: ',
+    );
+    my @varrefs = \(
+      $subcmdvar{URL_CWD},
+      $subcmdvar{WCT},
+      $subcmdvar{URL_WCT},
+    );
+
+    for my $i (0 .. $#varrefs) {
+      $subcmd_f{$name}->Label ('-text' => $labtxts[$i])->grid (
+        '-row'    => $row{$name},
+        '-column' => 0,
+        '-sticky' => 'w',
+      );
+      $subcmd_f{$name}->Label ('-textvariable' => $varrefs[$i])->grid (
+        '-row'    => $row{$name}++,
+        '-column' => 1,
+        '-sticky' => 'w',
+      );
+    }
+
+    $subcmd_f{$name}->Checkbutton (
+      '-text'     => 'Apply sub-command to working copy top',
+      '-variable' => \($subcmdvar{$name}{USEWCT}),
+      '-state'    => (grep ({$_ eq $name} @wcto_subcmds) ? 'disabled' : 'normal'),
+    )->grid (
+      '-row'        => $row{$name}++,
+      '-column'     => 0,
+      '-columnspan' => 2,
+      '-sticky'     => 'w',
+    );
+  }
+
+  # Widget for the Branch sub-command
+  {
+    my $name = 'BRANCH';
+
+    # Radio buttons to select the sub-option of the branch sub-command
+    my $opt_f = $subcmd_f{$name}->Frame ()->grid (
+      '-row'        => $row{$name}++,
+      '-column'     => 0,
+      '-columnspan' => 2,
+      '-sticky'     => 'w',
+    );
+
+    my $col = 0;
+    for my $key (sort keys %branch_opt) {
+      my $opt = lc $key;
+
+      $branch_opt{$key} = $opt_f->Radiobutton (
+        '-text'     => $opt,
+        '-value'    => $opt,
+        '-variable' => \($subcmdvar{$name}{OPT}),
+        '-state'    => 'normal',
+      )->grid (
+        '-row'      => 0,
+        '-column'   => $col++,
+        '-sticky'   => 'w',
+      );
+    }
+
+    # Label and entry box for specifying URL
+    $subcmd_f{$name}->Label ('-text' => 'URL: ')->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+    $subcmd_f{$name}->Entry (
+      '-textvariable' => \($subcmdvar{$name}{URL}),
+    )->grid (
+      '-row'    => $row{$name}++,
+      '-column' => 1,
+      '-sticky' => 'ew',
+    );
+
+    # Label and entry box for specifying create branch name
+    $subcmd_f{$name}->Label (
+      '-text' => 'Branch name (create only): ',
+    )->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+    $subcmd_f{$name}->Entry (
+      '-textvariable' => \($subcmdvar{$name}{NAME}),
+    )->grid (
+      '-row'    => $row{$name}++,
+      '-column' => 1,
+      '-sticky' => 'ew',
+    );
+
+    # Label and entry box for specifying create branch source revision
+    $subcmd_f{$name}->Label (
+      '-text' => 'Source revision (create/list only): ',
+    )->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+    $subcmd_f{$name}->Entry (
+      '-textvariable' => \($subcmdvar{$name}{REV}),
+    )->grid (
+      '-row'    => $row{$name}++,
+      '-column' => 1,
+      '-sticky' => 'ew',
+    );
+
+    # Label and radio buttons box for specifying create branch type
+    $subcmd_f{$name}->Label (
+      '-text' => 'Branch type (create only): ',
+    )->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+
+    {
+      my $opt_f = $subcmd_f{$name}->Frame ()->grid (
+        '-row'    => $row{$name}++,
+        '-column' => 1,
+        '-sticky' => 'w',
+      );
+
+      my $col = 0;
+      for my $key (sort keys %branch_type) {
+        my $txt = lc $key;
+        my $opt = $key;
+
+        $branch_opt{$key} = $opt_f->Radiobutton (
+          '-text'     => $txt,
+          '-value'    => $opt,
+          '-variable' => \($subcmdvar{$name}{TYPE}),
+          '-state'    => 'normal',
+        )->grid (
+          '-row'      => 0,
+          '-column'   => $col++,
+          '-sticky'   => 'w',
+        );
+      }
+    }
+
+    # Label and radio buttons box for specifying create source type
+    $subcmd_f{$name}->Label (
+      '-text' => 'Source type (create only): ',
+    )->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+
+    {
+      my $opt_f = $subcmd_f{$name}->Frame ()->grid (
+        '-row'    => $row{$name}++,
+        '-column' => 1,
+        '-sticky' => 'w',
+      );
+
+      my $col = 0;
+      for my $key (sort keys %branch_srctype) {
+        my $txt = lc $key;
+        my $opt = lc $key;
+
+        $branch_opt{$key} = $opt_f->Radiobutton (
+          '-text'     => $txt,
+          '-value'    => $opt,
+          '-variable' => \($subcmdvar{$name}{SRCTYPE}),
+          '-state'    => 'normal',
+        )->grid (
+          '-row'      => 0,
+          '-column'   => $col++,
+          '-sticky'   => 'w',
+        );
+      }
+    }
+
+    # Label and radio buttons box for specifying create prefix option
+    $subcmd_f{$name}->Label (
+      '-text' => 'Prefix option (create only): ',
+    )->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+
+    {
+      my $opt_f = $subcmd_f{$name}->Frame ()->grid (
+        '-row'    => $row{$name}++,
+        '-column' => 1,
+        '-sticky' => 'w',
+      );
+
+      my $col = 0;
+      for my $key (sort keys %branch_revflag) {
+        my $txt = lc $key;
+        my $opt = $key;
+
+        $branch_opt{$key} = $opt_f->Radiobutton (
+          '-text'     => $txt,
+          '-value'    => $opt,
+          '-variable' => \($subcmdvar{$name}{REVFLAG}),
+          '-state'    => 'normal',
+        )->grid (
+          '-row'      => 0,
+          '-column'   => $col++,
+          '-sticky'   => 'w',
+        );
+      }
+    }
+
+    # Label and entry box for specifying ticket number
+    $subcmd_f{$name}->Label (
+      '-text' => 'Related Trac ticket(s) (create only): ',
+    )->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+    $subcmd_f{$name}->Entry (
+      '-textvariable' => \($subcmdvar{$name}{TICKET}),
+    )->grid (
+      '-row'    => $row{$name}++,
+      '-column' => 1,
+      '-sticky' => 'ew',
+    );
+
+    # Check button for info/delete
+    # --show-children, --show-siblings, --show-other, --verbose
+    $subcmd_f{$name}->Label (
+      '-text' => 'Options for info/delete only: ',
+    )->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+
+    {
+      my $opt_f = $subcmd_f{$name}->Frame ()->grid (
+        '-row'    => $row{$name}++,
+        '-column' => 1,
+        '-sticky' => 'w',
+      );
+
+      my $col = 0;
+
+      for my $key (sort keys %branch_info_opt) {
+        $opt_f->Checkbutton (
+          '-text'     => $branch_info_opt{$key},
+          '-variable' => \($subcmdvar{$name}{$key}),
+        )->grid (
+          '-row'    => 0,
+          '-column' => $col++,
+          '-sticky' => 'w',
+        );
+      }
+    }
+  }
+
+  # Widget for the Checkout sub-command
+  {
+    my $name = 'CHECKOUT';
+
+    # Label and entry boxes for specifying URL and revision
+    my @labtxts = (
+      'URL: ',
+      'Revision: ',
+      'Path: ',
+    );
+    my @varrefs = \(
+      $subcmdvar{$name}{URL},
+      $subcmdvar{$name}{REV},
+      $subcmdvar{$name}{PATH},
+    );
+
+    for my $i (0 .. $#varrefs) {
+      $subcmd_f{$name}->Label ('-text' => $labtxts[$i])->grid (
+        '-row'    => $row{$name},
+        '-column' => 0,
+        '-sticky' => 'w',
+      );
+      $subcmd_f{$name}->Entry (
+        '-textvariable' => $varrefs[$i],
+      )->grid (
+        '-row'    => $row{$name}++,
+        '-column' => 1,
+        '-sticky' => 'ew',
+      );
+    }
+  }
+
+  # Widget for the Status sub-command
+  {
+    my $name = 'STATUS';
+
+    # Checkbuttons for various options
+    my @labtxts = (
+      'Display update information',
+      'Print extra information',
+    );
+    my @varrefs = \(
+      $subcmdvar{$name}{UPDATE},
+      $subcmdvar{$name}{VERBOSE},
+    );
+
+    for my $i (0 .. $#varrefs) {
+      $subcmd_f{$name}->Checkbutton (
+        '-text'     => $labtxts[$i],
+        '-variable' => $varrefs[$i],
+      )->grid (
+        '-row'        => $row{$name}++,
+        '-column'     => 0,
+        '-columnspan' => 2,
+        '-sticky'     => 'w',
+      );
+    }
+  }
+
+  # Widget for the Diff sub-command
+  {
+    my $name = 'DIFF';
+
+    # Checkbuttons for various options
+    $subcmd_f{$name}->Checkbutton (
+      '-text'     => 'Use xxdiff to display differences',
+      '-variable' => \($subcmdvar{$name}{GRAPHIC}),
+    )->grid (
+      '-row'        => $row{$name}++,
+      '-column'     => 0,
+      '-columnspan' => 2,
+      '-sticky'     => 'w',
+    );
+
+    my $entry;
+    $subcmd_f{$name}->Checkbutton (
+      '-text'     => 'Show differences relative to the base of the branch',
+      '-variable' => \($subcmdvar{$name}{BRANCH}),
+      '-command'  => sub {
+        $entry->configure (
+          '-state' => ($subcmdvar{$name}{BRANCH} ? 'normal' : 'disabled'),
+        );
+      },
+    )->grid (
+      '-row'        => $row{$name}++,
+      '-column'     => 0,
+      '-columnspan' => 2,
+      '-sticky'     => 'w',
+    );
+
+    $subcmd_f{$name}->Label ('-text' => 'Branch URL')->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+
+    $entry = $subcmd_f{$name}->Entry (
+      '-textvariable' => \($subcmdvar{$name}{URL}),
+      '-state'        => ($subcmdvar{$name}{BRANCH} ? 'normal' : 'disabled'),
+    )->grid (
+      '-row'    => $row{$name}++,
+      '-column' => 1,
+      '-sticky' => 'ew',
+    );
+  }
+
+  # Widget for the Add/Delete sub-command
+  for my $name (qw/ADD DELETE/) {
+
+    # Checkbuttons for various options
+    $subcmd_f{$name}->Checkbutton (
+      '-text'     => 'Check for files or directories not under version control',
+      '-variable' => \($subcmdvar{$name}{CHECK}),
+    )->grid (
+      '-row'        => $row{$name}++,
+      '-column'     => 0,
+      '-columnspan' => 2,
+      '-sticky'     => 'w',
+    );
+  }
+
+  # Widget for the Merge sub-command
+  {
+    my $name = 'MERGE';
+
+    # Label and radio buttons box for specifying merge mode
+    $subcmd_f{$name}->Label (
+      '-text' => 'Mode: ',
+    )->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+
+    {
+      my $opt_f = $subcmd_f{$name}->Frame ()->grid (
+        '-row'    => $row{$name}++,
+        '-column' => 1,
+        '-sticky' => 'w',
+      );
+
+      my $col = 0;
+      for my $key (qw/automatic custom reverse/) {
+        my $txt = lc $key;
+        my $opt = $key;
+
+        $branch_opt{$key} = $opt_f->Radiobutton (
+          '-text'     => $txt,
+          '-value'    => $opt,
+          '-variable' => \($subcmdvar{$name}{MODE}),
+          '-state'    => 'normal',
+        )->grid (
+          '-row'      => 0,
+          '-column'   => $col++,
+          '-sticky'   => 'w',
+        );
+      }
+    }
+
+    # Check buttons for dry-run
+    $subcmd_f{$name}->Checkbutton (
+      '-text'     => 'Dry run',
+      '-variable' => \($subcmdvar{$name}{DRYRUN}),
+    )->grid (
+      '-row'        => $row{$name}++,
+      '-column'     => 0,
+      '-columnspan' => 2,
+      '-sticky'     => 'w',
+    );
+
+    # Check buttons for verbose mode
+    $subcmd_f{$name}->Checkbutton (
+      '-text'     => 'Print extra information',
+      '-variable' => \($subcmdvar{$name}{VERBOSE}),
+    )->grid (
+      '-row'        => $row{$name}++,
+      '-column'     => 0,
+      '-columnspan' => 2,
+      '-sticky'     => 'w',
+    );
+
+    # Label and entry boxes for specifying merge source
+    $subcmd_f{$name}->Label (
+      '-text' => 'Source (automatic/custom only): ',
+    )->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+    $subcmd_f{$name}->Entry (
+      '-textvariable' => \($subcmdvar{$name}{SRC}),
+    )->grid (
+      '-row'    => $row{$name}++,
+      '-column' => 1,
+      '-sticky' => 'ew',
+    );
+
+    # Label and entry boxes for specifying merge revision (range)
+    $subcmd_f{$name}->Label (
+      '-text' => 'Revision (custom/reverse only): ',
+    )->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+    $subcmd_f{$name}->Entry (
+      '-textvariable' => \($subcmdvar{$name}{REV}),
+    )->grid (
+      '-row'    => $row{$name}++,
+      '-column' => 1,
+      '-sticky' => 'ew',
+    );
+  }
+
+  # Widget for the Commit sub-command
+  {
+    my $name = 'COMMIT';
+
+    # Checkbuttons for various options
+    $subcmd_f{$name}->Checkbutton (
+      '-text'     => 'Dry run',
+      '-variable' => \($subcmdvar{$name}{DRYRUN}),
+    )->grid (
+      '-row'        => $row{$name}++,
+      '-column'     => 0,
+      '-columnspan' => 2,
+      '-sticky'     => 'w',
+    );
+  }
+
+  # Widget for the Switch sub-command
+  {
+    my $name = 'SWITCH';
+
+    # Label and entry boxes for specifying switch URL
+    $subcmd_f{$name}->Label ('-text' => 'URL: ')->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+    $subcmd_f{$name}->Entry (
+      '-textvariable' => \($subcmdvar{$name}{URL}),
+    )->grid (
+      '-row'    => $row{$name}++,
+      '-column' => 1,
+      '-sticky' => 'ew',
+    );
+  }
+
+  # Widgets common to all sub-commands
+  for my $name (@subcmds) {
+    $subcmd_f{$name}->Label ('-text' => 'Other options: ')->grid (
+      '-row'    => $row{$name},
+      '-column' => 0,
+      '-sticky' => 'w',
+    );
+    $subcmd_f{$name}->Entry (
+      '-textvariable' => \($subcmdvar{$name}{OTHER}),
+    )->grid (
+      '-row'    => $row{$name}++,
+      '-column' => 1,
+      '-sticky' => 'ew',
+    );
+  }
+}
+
+# ------------------------------------------------------------------------------
+
+# Buttons to perform main actions
+{
+  my $col = 0;
+  for my $name (qw/QUIT HELP CLEAR RUN/) {
+    $action_b{$name} = $bot_f->Button (
+      '-text'    => uc (substr ($name, 0, 1)) . lc (substr ($name, 1)),
+      '-command' => [\&button_clicked, $name],
+      '-width'   => 8,
+    )->grid (
+      '-row'    => 0,
+      '-column' => $col++,
+      '-sticky' => ($name eq 'RUN' ? 'ew' : 'w'),
+    );
+
+    $action_b{$name}->bind ('<Enter>', sub {$statustext = $action_help{$name}});
+    $action_b{$name}->bind ('<Leave>', sub {$statustext = ''});
+
+    $action_b{$name}->configure ('-underline' => $action_bind{$name}{U})
+      if defined $action_bind{$name}{U};
+
+    $mw->bind ($action_bind{$name}{KEY}, sub {$action_b{$name}->invoke});
+  }
+}
+
+&change_cwd ($subcmdvar{CWD});
+
+# ------------------------------------------------------------------------------
+
+# Handle the situation when the user attempts to quit the window while a
+# sub-command is running
+
+$mw->protocol ('WM_DELETE_WINDOW', sub {
+  if (defined $cmdpid) {
+    my $ans = $mw->messageBox (
+      '-title'   => $mw_title,
+      '-message' => $selsubcmd . ' is still running. Really quit?',
+      '-type'    => 'YesNo',
+      '-default' => 'No',
+    );
+
+    if ($ans eq 'Yes') {
+      kill 9, $cmdpid; # Need to kill the sub-process before quitting
+
+    } else {
+      return; # Do not quit
+    }
+  }
+
+  exit;
+});
+
+MainLoop;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfg = &main::cfg ();
+#
+# DESCRIPTION
+#   Return the $config variable.
+# ------------------------------------------------------------------------------
+
+sub cfg {
+  return $config;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &change_cwd ($dir);
+#
+# DESCRIPTION
+#   Change current working directory to $dir
+# ------------------------------------------------------------------------------
+
+sub change_cwd {
+  my $dir = $_[0];
+  my @allowed_subcmds = (&is_wc ($dir) ? @wc_subcmds : @nwc_subcmds);
+
+  for my $subcmd (@subcmds) {
+    if (grep {$_ eq $subcmd} @allowed_subcmds) {
+      $subcmd_b{$subcmd}->configure ('-state' => 'normal');
+
+    } else {
+      $subcmd_b{$subcmd}->configure ('-state' => 'disabled');
+    }
+  }
+
+  &display_subcmd_frame ($allowed_subcmds[0])
+    if not grep {$_ eq $selsubcmd} @allowed_subcmds;
+
+  chdir $dir;
+  $subcmdvar{CWD} = $dir;
+
+  if (&is_wc ($dir)) {
+    $subcmdvar{WCT}     = &get_wct ($dir);
+    $subcmdvar{URL_CWD} = &get_url_of_wc ($dir);
+    $subcmdvar{URL_WCT} = &get_url_of_wc ($subcmdvar{WCT});
+
+    $branch_opt{INFO}  ->configure ('-state' => 'normal');
+    $branch_opt{DELETE}->configure ('-state' => 'normal');
+    $subcmdvar{BRANCH}{OPT} = 'info';
+
+  } else {
+    $branch_opt{INFO}  ->configure ('-state' => 'disabled');
+    $branch_opt{DELETE}->configure ('-state' => 'disabled');
+    $subcmdvar{BRANCH}{OPT} = 'create';
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &button_clicked ($name);
+#
+# DESCRIPTION
+#   Call back function to handle a click on a command button named $name.
+# ------------------------------------------------------------------------------
+
+sub button_clicked {
+  my $name = $_[0];
+
+  if (grep {$_ eq $name} keys %subcmd_b) {
+    &display_subcmd_frame ($name);
+
+  } elsif ($name eq 'CLEAR') {
+    $out_t->delete ('1.0', 'end');
+
+  } elsif ($name eq 'QUIT') {
+    exit;
+
+  } elsif ($name eq 'HELP') {
+    &invoke_cmd ('help ' . lc ($selsubcmd));
+
+  } elsif ($name eq 'RUN') {
+    &invoke_cmd (&setup_cmd ($selsubcmd));
+
+  } else {
+    $out_t->insert ('end', $name . ': function to be implemented' . "\n");
+    $out_t->yviewMoveto (1);
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &display_subcmd_frame ($name);
+#
+# DESCRIPTION
+#   Change selected subcommand to $name, and display the frame containing the
+#   widgets for configuring the options and arguments of that subcommand.
+# ------------------------------------------------------------------------------
+
+sub display_subcmd_frame {
+  my $name = $_[0];
+
+  if ($selsubcmd ne $name and not $cmdrunning) {
+    $subcmd_b{$name     }->configure ('-relief' => 'sunken');
+    $subcmd_b{$selsubcmd}->configure ('-relief' => 'raised') if $selsubcmd;
+
+    $subcmd_f{$name     }->grid ('-sticky' => 'new');
+    $subcmd_f{$selsubcmd}->gridForget if $selsubcmd;
+
+    $selsubcmd = $name;
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $pos = &get_wm_pos ();
+#
+# DESCRIPTION
+#   Returns the position part of the geometry string of the main window.
+# ------------------------------------------------------------------------------
+
+sub get_wm_pos {
+  my $geometry = $mw->geometry ();
+  $geometry =~ /^=?(?:\d+x\d+)?([+-]\d+[+-]\d+)$/;
+  return $1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $command = &setup_cmd ($name);
+#
+# DESCRIPTION
+#   Setup the the system command for the sub-command $name.
+# ------------------------------------------------------------------------------
+
+sub setup_cmd {
+  my $name = $_[0];
+  my $cmd  = '';
+
+  if ($name eq 'BRANCH') {
+    $cmd .= lc ($name);
+    if ($subcmdvar{$name}{OPT} eq 'create') {
+      $cmd .= ' -c --svn-non-interactive';
+      $cmd .= ' -n '     . $subcmdvar{$name}{NAME} if $subcmdvar{$name}{NAME};
+      $cmd .= ' -t '     . $subcmdvar{$name}{TYPE};
+      $cmd .= ' --rev-flag ' . $subcmdvar{$name}{REVFLAG};
+      $cmd .= ' -r ' . $subcmdvar{$name}{REV} if $subcmdvar{$name}{REV};
+      $cmd .= ' -k ' . $subcmdvar{$name}{TICKET} if $subcmdvar{$name}{TICKET};
+      $cmd .= ' --branch-of-branch ' if $subcmdvar{$name}{SRCTYPE} eq 'branch';
+
+    } elsif ($subcmdvar{$name}{OPT} eq 'delete') {
+      $cmd .= ' -v' if $subcmdvar{$name}{VERBOSE};
+      $cmd .= ' -d --svn-non-interactive';
+
+    } elsif ($subcmdvar{$name}{OPT} eq 'list') {
+      $cmd .= ' -l';
+      $cmd .= ' -r ' . $subcmdvar{$name}{REV} if $subcmdvar{$name}{REV};
+
+    } else {
+      $cmd .= ' -i';
+      $cmd .= ' --show-children' if $subcmdvar{$name}{S_CHD};
+      $cmd .= ' --show-siblings' if $subcmdvar{$name}{S_SIB};
+      $cmd .= ' --show-other'    if $subcmdvar{$name}{S_OTH};
+      $cmd .= ' -v' if $subcmdvar{$name}{VERBOSE};
+    }
+    $cmd .= ' ' . $subcmdvar{$name}{URL}   if $subcmdvar{$name}{URL};
+    $cmd .= ' ' . $subcmdvar{$name}{OTHER} if $subcmdvar{$name}{OTHER};
+
+  } elsif ($name eq 'CHECKOUT') {
+    $cmd .= lc ($name);
+    $cmd .= ' -r' . $subcmdvar{$name}{REV} if $subcmdvar{$name}{REV};
+    $cmd .= ' ' . $subcmdvar{$name}{OTHER} if $subcmdvar{$name}{OTHER};
+    $cmd .= ' ' . $subcmdvar{$name}{URL};
+    $cmd .= ' ' . $subcmdvar{$name}{PATH} if $subcmdvar{$name}{PATH};
+
+  } elsif ($name eq 'STATUS') {
+    $cmd .= lc ($name);
+    $cmd .= ' -u' if $subcmdvar{$name}{UPDATE};
+    $cmd .= ' -v' if $subcmdvar{$name}{VERBOSE};
+    $cmd .= ' ' . $subcmdvar{$name}{OTHER} if $subcmdvar{$name}{OTHER};
+
+  } elsif ($name eq 'DIFF') {
+    $cmd .= lc ($name);
+    $cmd .= ' -g' if $subcmdvar{$name}{GRAPHIC};
+
+    if ($subcmdvar{$name}{BRANCH}) {
+      $cmd .= ' -b';
+      $cmd .= ' ' . $subcmdvar{$name}{URL} if $subcmdvar{$name}{URL};
+    }
+
+    $cmd .= ' ' . $subcmdvar{$name}{OTHER} if $subcmdvar{$name}{OTHER};
+
+  } elsif ($name eq 'ADD' or $name eq 'DELETE') {
+    $cmd .= lc ($name);
+    $cmd .= ' -c' if $subcmdvar{$name}{CHECK};
+    $cmd .= ' --non-interactive'
+      if $name eq 'DELETE' and not $subcmdvar{$name}{CHECK};
+    $cmd .= ' ' . $subcmdvar{$name}{OTHER} if $subcmdvar{$name}{OTHER};
+
+  } elsif ($name eq 'MERGE') {
+    $cmd .= lc ($name);
+
+    if ($subcmdvar{$name}{MODE} ne 'automatic') {
+      $cmd .= ' --' . $subcmdvar{$name}{MODE};
+      $cmd .= ' --revision ' . $subcmdvar{$name}{REV} if $subcmdvar{$name}{REV};
+    }
+
+    $cmd .= ' --dry-run' if $subcmdvar{$name}{DRYRUN};
+    $cmd .= ' -v'        if $subcmdvar{$name}{VERBOSE};
+    $cmd .= ' ' . $subcmdvar{$name}{SRC}   if $subcmdvar{$name}{SRC};
+    $cmd .= ' ' . $subcmdvar{$name}{OTHER} if $subcmdvar{$name}{OTHER};
+
+  } elsif ($name eq 'CONFLICTS') {
+    $cmd .= lc ($name);
+    $cmd .= ' ' . $subcmdvar{$name}{OTHER} if $subcmdvar{$name}{OTHER};
+
+  } elsif ($name eq 'COMMIT') {
+    $cmd .= lc ($name);
+    $cmd .= ' --dry-run' if $subcmdvar{$name}{DRYRUN};
+    $cmd .= ' --svn-non-interactive';
+    $cmd .= ' ' . $subcmdvar{$name}{OTHER} if $subcmdvar{$name}{OTHER};
+
+  } elsif ($name eq 'SWITCH') {
+    $cmd .= lc ($name);
+    $cmd .= ' ' . $subcmdvar{$name}{URL}   if $subcmdvar{$name}{URL};
+    $cmd .= ' ' . $subcmdvar{$name}{OTHER} if $subcmdvar{$name}{OTHER};
+
+  } elsif ($name eq 'UPDATE') {
+    $cmd .= lc ($name);
+    $cmd .= ' ' . $subcmdvar{$name}{OTHER} if $subcmdvar{$name}{OTHER};
+
+  }
+
+  return $cmd;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &invoke_cmd ($cmd);
+#
+# DESCRIPTION
+#   Invoke the command $cmd.
+# ------------------------------------------------------------------------------
+
+sub invoke_cmd {
+  my $cmd      = $_[0];
+  return unless $cmd;
+
+  my $disp_cmd = 'fcm ' . $cmd;
+  $cmd         = (index ($cmd, 'help ') == 0)
+                 ? $disp_cmd
+                 : ('fcm_gui_internal ' . &get_wm_pos () . ' ' . $cmd);
+
+  # Change directory to working copy top if necessary
+  if ($subcmdvar{$selsubcmd}{USEWCT} and $subcmdvar{WCT} ne $subcmdvar{CWD}) {
+    chdir $subcmdvar{WCT};
+    $out_t->insert ('end', 'cd ' . $subcmdvar{WCT} . "\n");
+    $out_t->yviewMoveto (1);
+  }
+
+  # Report start of command
+  $out_t->insert ('end', timestamp_command ($disp_cmd, 'Start'));
+  $out_t->yviewMoveto (1);
+
+  # Open the command as a pipe
+  if ($cmdpid = open CMD, '-|', $cmd . ' 2>&1') {
+    # Disable all action buttons
+    $action_b{$_}->configure ('-state' => 'disabled') for (keys %action_b);
+    $cmdrunning = 1;
+
+    # Set up a file event to read output from the command
+    $mw->fileevent (\*CMD, readable => sub {
+      if (sysread CMD, my ($buf), 1024) {
+        # Insert text into the output text box as it becomes available
+        $out_t->insert ('end', $buf);
+        $out_t->yviewMoveto (1);
+
+      } else {
+        # Delete the file event and close the file when the command finishes
+        $mw->fileevent(\*CMD, readable => '');
+        close CMD;
+        $cmdpid = undef;
+
+        # Check return status
+        if ($?) {
+          $out_t->insert (
+            'end', '"' . $disp_cmd . '" failed (' . $? . ')' . "\n",
+          );
+          $out_t->yviewMoveto (1);
+        }
+
+        # Report end of command
+        $out_t->insert ('end', timestamp_command ($disp_cmd, 'End'));
+        $out_t->yviewMoveto (1);
+
+        # Change back to CWD if necessary
+        if ($subcmdvar{$selsubcmd}{USEWCT} and
+            $subcmdvar{WCT} ne $subcmdvar{CWD}) {
+          chdir $subcmdvar{CWD};
+          $out_t->insert ('end', 'cd ' . $subcmdvar{CWD} . "\n");
+          $out_t->yviewMoveto (1);
+        }
+
+        # Enable all action buttons again
+        $action_b{$_}->configure ('-state' => 'normal') for (keys %action_b);
+        $cmdrunning = 0;
+
+        # If the command is "checkout", change directory to working copy
+        if (lc ($selsubcmd) eq 'checkout') {
+          my $url = expand_url_keyword (URL => $subcmdvar{CHECKOUT}{URL});
+          my $dir = $subcmdvar{CHECKOUT}{PATH}
+                  ? $subcmdvar{CHECKOUT}{PATH}
+                  : basename $url;
+          $dir    = File::Spec->rel2abs ($dir);
+          &change_cwd ($dir);
+
+        # If the command is "switch", change URL
+        } elsif (lc ($selsubcmd) eq 'switch') {
+          $subcmdvar{URL_CWD} = &get_url_of_wc ($subcmdvar{CWD}, 1);
+          $subcmdvar{URL_WCT} = &get_url_of_wc ($subcmdvar{WCT}, 1);
+        }
+      }
+      1;
+    });
+
+  } else {
+    $mw->messageBox (
+      '-title'   => 'Error',
+      '-message' => 'Error running "' . $cmd . '"',
+      '-icon'    => 'error',
+    );
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/bin/fcm_gui_internal
===================================================================
--- LMDZ5/branches/testing/tools/fcm/bin/fcm_gui_internal	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/bin/fcm_gui_internal	(revision 1665)
@@ -0,0 +1,272 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   fcm_gui_internal
+#
+# SYNOPSIS
+#   fcm_gui_internal POS FUNCTION
+#
+# DESCRIPTION
+#   The fcm_gui_internal command is part of a simple graphical user interface
+#   for some of the commands of the FCM system. The argument POS is a geometry
+#   string used by the &Main::get_input method to determine the location of the
+#   pop up window. The argument FUNCTION must be a keyword recognised by the
+#   &Fcm::Cm::cm_command function.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard pragmas
+use warnings;
+use strict;
+
+# Standard modules
+use Tk;
+use File::Basename;
+use File::Spec::Functions;
+
+# FCM component modules:
+use lib catfile (dirname (dirname ($0)), 'lib');
+use Fcm::Cm;
+use Fcm::Config;
+
+# ------------------------------------------------------------------------------
+
+# Get configuration settings
+my $config = Fcm::Config->new ();
+$config->get_config ();
+
+my $pos      = shift @ARGV;
+my $function = shift @ARGV;
+cm_command $function;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfg = &main::cfg ();
+#
+# DESCRIPTION
+#   Return the $config variable.
+# ------------------------------------------------------------------------------
+
+sub cfg {
+  return $config;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ans = &main::get_input (
+#     TITLE   => $title,
+#     MESSAGE => $mesg,
+#     TYPE    => $type,
+#     DEFAULT => $def,
+#   );
+#
+# DESCRIPTION
+#   Get an input string from the user and return it as $ans. If TYPE is 'YN', a
+#   'YesNo' type message box will be displayed to prompt the user to click
+#   either the 'yes' or 'no' button. If TYPE is 'YNA', then an 'all' button is
+#   provided as a third option. Otherwise, a dialog box with an entry box for
+#   the user to type in a string will be displayed. TITLE is the title of the
+#   dialog box, and MESSAGE is the main message of the dialog box. If DEFAULT is
+#   set, $ans is set to the default value when the dialog box is invoked.
+# ------------------------------------------------------------------------------
+
+sub get_input {
+  my %args  = @_;
+  my $title = exists $args{TITLE}   ? $args{TITLE}   : '';
+  my $mesg  = exists $args{MESSAGE} ? $args{MESSAGE} : '';
+  my $type  = exists $args{TYPE}    ? $args{TYPE}    : '';
+  my $def   = exists $args{DEFAULT} ? $args{DEFAULT} : '';
+  my $ans   = '';
+
+  # Create a main window
+  my $mw = MainWindow->new;
+  $mw->title ($title);
+
+  # Define the default which applies if the dialog box is just closed or
+  # the user selects 'cancel'
+  $ans = $def ? $def : '';
+
+  if ($type =~ /^yn/i) {
+    # Create a yes-no(-all) dialog box
+
+    # If TYPE is YNA then add a third button: 'all'
+    my $buttons;
+    if ($type =~ /a$/i) {
+      $buttons = 3;
+
+    } else {
+      $buttons = 2;
+    }
+
+    # Message of the dialog box
+    $mw->Label ('-text' => $mesg)->grid (
+      '-row'        => 0,
+      '-column'     => 0,
+      '-columnspan' => $buttons,
+      '-padx'       => 10,
+      '-pady'       => 10,
+    );
+
+    # The "yes" button
+    my $y_b = $mw->Button (
+      '-text'      => 'Yes',
+      '-underline' => 0,
+      '-command'   => sub {$ans = 'y'; $mw->destroy},
+    )->grid (
+      '-row'    => 1,
+      '-column' => 0,
+      '-padx'   => 5,
+      '-pady'   => 5,
+    );
+
+    # The "no" button
+    my $n_b = $mw->Button (
+      '-text'      => 'No',
+      '-underline' => 0,
+      '-command'   => sub {$ans = 'n'; $mw->destroy},
+    )->grid (
+      '-row'    => 1,
+      '-column' => 1,
+      '-padx'   => 5,
+      '-pady'   => 5,
+    );
+
+    # The "all" button
+    my $a_b;
+    if ($buttons == 3) {
+      $a_b = $mw->Button (
+        '-text'      => 'All',
+        '-underline' => 0,
+        '-command'   => sub {$ans = 'a'; $mw->destroy},
+      )->grid (
+        '-row'    => 1,
+        '-column' => 2,
+        '-padx'   => 5,
+        '-pady'   => 5,
+      );
+    }
+
+    # Keyboard binding
+    if ($buttons == 3) {
+      $mw->bind ('<Key>' => sub {
+	if ($Tk::event->K eq 'Y' or $Tk::event->K eq 'y') {
+	  $y_b->invoke;
+
+	} elsif ($Tk::event->K eq 'N' or $Tk::event->K eq 'n') {
+	  $n_b->invoke;
+
+	} elsif ($Tk::event->K eq 'A' or $Tk::event->K eq 'a') {
+	  $a_b->invoke;
+	}
+      });
+
+    } else {
+      $mw->bind ('<Key>' => sub {
+	if ($Tk::event->K eq 'Y' or $Tk::event->K eq 'y') {
+	  $y_b->invoke;
+
+	} elsif ($Tk::event->K eq 'N' or $Tk::event->K eq 'n') {
+	  $n_b->invoke;
+	}
+      });
+    }
+
+    # Handle the situation when the user attempts to quit the window
+    $mw->protocol ('WM_DELETE_WINDOW', sub {
+      $ans = $def if $def;
+      $mw->destroy;
+    });
+
+  } else {
+    # Create a dialog box to obtain an input string
+
+    # Message of the dialog box
+    $mw->Label ('-text' => $mesg)->grid (
+      '-row'    => 0,
+      '-column' => 0,
+      '-padx'   => 5,
+      '-pady'   => 5,
+    );
+
+    # Entry box for the user to type in the input string
+    my $entry   = $ans;
+    my $input_e = $mw->Entry (
+      '-textvariable'    => \$entry,
+      '-width'           => 40,
+    )->grid (
+      '-row'    => 0,
+      '-column' => 1,
+      '-sticky' => 'ew',
+      '-padx'   => 5,
+      '-pady'   => 5,
+    );
+
+    my $b_f = $mw->Frame->grid (
+      '-row'        => 1,
+      '-column'     => 0,
+      '-columnspan' => 2,
+      '-sticky'     => 'e',
+    );
+
+    # An OK button to accept the input string
+    my $ok_b = $b_f->Button (
+      '-text' => 'OK',
+      '-command' => sub {$ans = $entry; $mw->destroy},
+    )->grid (
+      '-row'        => 0,
+      '-column'     => 0,
+      '-padx'       => 5,
+      '-pady'       => 5,
+    );
+
+    # A Cancel button to reject the input string
+    my $cancel_b = $b_f->Button (
+      '-text' => 'Cancel',
+      '-command' => sub {$ans = undef; $mw->destroy},
+    )->grid (
+      '-row'        => 0,
+      '-column'     => 1,
+      '-padx'       => 5,
+      '-pady'       => 5,
+    );
+
+    # Keyboard binding
+    $mw->bind ('<Key>' => sub {
+      if ($Tk::event->K eq 'Return' or $Tk::event->K eq 'KP_Enter') {
+        $ok_b->invoke;
+
+      } elsif ($Tk::event->K eq 'Escape') {
+        $cancel_b->invoke;
+      }
+    });
+
+    # Allow the entry box to expand
+    $mw->gridColumnconfigure (1, '-weight' => 1);
+
+    # Set initial focus on the entry box
+    $input_e->focus;
+    $input_e->icursor ('end');
+  }
+
+  $mw->geometry ($pos);
+
+  # Switch on "always on top" property for $mw
+  $mw->property (
+    qw/set _NET_WM_STATE ATOM/,
+    32,
+    ['_NET_WM_STATE_STAYS_ON_TOP'],
+    ($mw->toplevel->wrapper)[0],
+  );
+
+  MainLoop;
+
+  return $ans;
+}
+
+# ------------------------------------------------------------------------------
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/bin/fcm_internal
===================================================================
--- LMDZ5/branches/testing/tools/fcm/bin/fcm_internal	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/bin/fcm_internal	(revision 1665)
@@ -0,0 +1,581 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   fcm_internal
+#
+# SYNOPSIS
+#   fcm_internal SUBCOMMAND ARGS
+#
+# DESCRIPTION
+#   The fcm_internal command is a frontend for some of the internal commands of
+#   the FCM build system. The subcommand can be "compile", "load" or "archive"
+#   for invoking the compiler, loader and library archiver respectively. If
+#   "compile" is specified, it can be suffixed with ":TYPE" to specify the
+#   nature of the source file. If TYPE is not specified, it is set to F by
+#   default (for Fortran source). For compile and load, the other arguments are
+#   the 1) name of the container package of the source file, 2) the path to the
+#   source file and 3) the target name after compiling or loading the source
+#   file. For compile, the 4th argument is a flag to indicate whether
+#   pre-processing is required for compiling the source file. For load, the 4th
+#   and the rest of the arguments is a list of object files that cannot be
+#   archived into the temporary load library and must be linked into the target
+#   through the linker command. (E.g. Fortran BLOCKDATA program units must be
+#   linked this way.) If archive is specified, the first argument should be the
+#   name of the library archive target and the rest should be the object files
+#   to be included in the archive. This command is invoked via the build system
+#   and should never be called directly by the user.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard pragmas:
+use warnings;
+use strict;
+
+# FCM component modules
+use Fcm::Timer;
+
+# Function declarations
+sub catfile;
+sub basename;
+sub dirname;
+
+# ------------------------------------------------------------------------------
+
+# Module level variables
+my %unusual_tool_name = ();
+
+# ------------------------------------------------------------------------------
+
+MAIN: {
+  # Name of program
+  my $this = basename $0;
+
+  # Arguments
+  my $subcommand = shift @ARGV;
+  my ($function, $type) = split /:/, $subcommand; 
+  my ($srcpackage, $src, $target, $requirepp, @objects, @blockdata);
+  
+  if ($subcommand eq 'archive') {
+    ($target, @objects) = @ARGV;
+
+  } elsif ($subcommand eq 'load') {
+    ($srcpackage, $src, $target, @blockdata) = @ARGV;
+
+  } else {
+    ($srcpackage, $src, $target, $requirepp) = @ARGV;
+  }
+
+  # Set up hash reference for all the required information
+  my %info = (
+    SRCPACKAGE => $srcpackage,
+    SRC        => $src,
+    TYPE       => $type,
+    TARGET     => $target,
+    REQUIREPP  => $requirepp,
+    OBJECTS    => \@objects,
+    BLOCKDATA  => \@blockdata,
+  );
+
+  # Get list of unusual tools
+  my $i = 0;
+  while (my $label = &get_env ('FCM_UNUSUAL_TOOL_LABEL' . $i)) {
+    my $value = &get_env ('FCM_UNUSUAL_TOOL_VALUE' . $i);
+    $unusual_tool_name{$label} = $value;
+    $i++;
+  }
+
+  # Invoke the action
+  my $rc = 0;
+  if ($function eq 'compile') {
+    $rc = &compile (\%info);
+
+  } elsif ($function eq 'load') {
+    $rc = &load (\%info);
+
+  } elsif ($function eq 'archive') {
+    $rc = &archive (\%info);
+
+  } else {
+    print STDERR $this, ': incorrect usage, abort';
+    $rc = 1;
+  }
+
+  # Throw error if action failed
+  if ($rc) {
+    print STDERR $this, ' ', $function, ' failed (', $rc, ')', "\n";
+    exit 1;
+
+  } else {
+    exit;
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = &compile (\%info);
+#
+# DESCRIPTION
+#   This method invokes the correct compiler with the correct options to
+#   compile the source file into the required target. The argument $info is a
+#   hash reference set up in MAIN. The following environment variables are
+#   used, where * is the source file type (F for Fortran, and C for C/C++):
+# 
+#   *C          - compiler command
+#   *C_OUTPUT   - *C option to specify the name of the output file
+#   *C_DEFINE   - *C option to declare a pre-processor def
+#   *C_INCLUDE  - *C option to declare an include directory
+#   *C_COMPILE  - *C option to ask the compiler to perform compile only
+#   *CFLAGS     - *C user options
+#   *PPKEYS     - list of pre-processor defs (may have sub-package suffix)
+#   FCM_VERBOSE - verbose level
+#   FCM_OBJDIR  - destination directory of object file
+#   FCM_TMPDIR  - temporary destination directory of object file
+# ------------------------------------------------------------------------------
+
+sub compile {
+  my $info = shift;
+
+  # Verbose mode
+  my $verbose = &get_env ('FCM_VERBOSE');
+  $verbose    = 1 unless defined ($verbose);
+
+  my @command = ();
+
+  # Only support C and Fortran source files at the moment
+  my $type = $info->{TYPE};
+  $type    = ($info->{SRC} =~ /\.c(\w+)?$/i) ? 'C' : 'F' if not $type;
+
+  # Compiler
+  push @command, &get_env ($type . 'C', 1);
+
+  # Compile output target (typical -o option)
+  push @command, &get_env ($type . 'C_OUTPUT', 1), $info->{TARGET};
+
+  # Pre-processor definition macros
+  if ($info->{REQUIREPP}) {
+    my @ppkeys = split /\s+/, &select_flags ($info, $type . 'PPKEYS');
+    my $defopt = &get_env ($type . 'C_DEFINE', 1);
+
+    push @command, (map {$defopt . $_} @ppkeys);
+  }
+
+  # Include search path
+  my $incopt  = &get_env ($type . 'C_INCLUDE', 1);
+  my @incpath = split /:/, &get_env ('FCM_INCPATH');
+  push @command, (map {$incopt . $_} @incpath);
+
+  # Other compiler flags
+  my $flags = &select_flags ($info, $type . 'FLAGS');
+  push @command, $flags if $flags;
+
+  my $compile_only = &get_env ($type . 'C_COMPILE');
+  if ($flags !~ /(?:^|\s)$compile_only\b/) {
+    push @command, &get_env ($type . 'C_COMPILE');
+  }
+
+  # Name of source file
+  push @command, $info->{SRC};
+
+  # Execute command
+  my $objdir = &get_env ('FCM_OBJDIR', 1);
+  my $tmpdir = &get_env ('FCM_TMPDIR', 1);
+  chdir $tmpdir;
+
+  my $command = join ' ', @command;
+  if ($verbose > 1) {
+    print 'cd ', $tmpdir, "\n";
+    print &timestamp_command ($command, 'Start');
+
+  } elsif ($verbose) {
+    print $command, "\n";
+  }
+
+  my $rc = system $command;
+
+  print &timestamp_command ($command, 'End  ') if $verbose > 1;
+
+  # Move temporary output to correct location on success
+  # Otherwise, remove temporary output
+  if ($rc) { # error
+    unlink $info->{TARGET};
+
+  } else {   # success
+    print 'mv ', $info->{TARGET}, ' ', $objdir, "\n" if $verbose > 1;
+    rename $info->{TARGET}, &catfile ($objdir, $info->{TARGET});
+  }
+
+  # Move any Fortran module definition files to the INC directory
+  my @modfiles = <*.mod *.MOD>;
+  for my $file (@modfiles) {
+    rename $file, &catfile ($incpath[0], $file);
+  }
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = &load (\%info);
+#
+# DESCRIPTION
+#   This method invokes the correct loader with the correct options to link
+#   the main program object into an executable. The argument $info is a hash
+#   reference set up in MAIN. The following environment variables are used:
+# 
+#   LD           - linker command
+#   LD_OUTPUT    - LD option to specify the name of the output file
+#   LD_LIBSEARCH - LD option to declare a directory in the library search path
+#   LD_LIBLINK   - LD option to declare an object library
+#   LDFLAGS      - LD user options
+#   FCM_VERBOSE  - verbose level
+#   FCM_LIBDIR   - destination directory of object libraries
+#   FCM_OBJDIR   - destination directory of object files
+#   FCM_BINDIR   - destination directory of executable file
+#   FCM_TMPDIR   - temporary destination directory of executable file
+# ------------------------------------------------------------------------------
+
+sub load {
+  my $info = shift;
+
+  my $rc = 0;
+
+  # Verbose mode
+  my $verbose = &get_env ('FCM_VERBOSE');
+  $verbose    = 1 unless defined ($verbose);
+
+  # Create temporary object library
+  (my $name   = $info->{TARGET}) =~ s/\.\S+$//;
+  my $libname = '__fcm__' . $name;
+  my $lib     = 'lib' . $libname . '.a';
+  my $libfile = catfile (&get_env ('FCM_LIBDIR', 1), $lib);
+  $rc = &archive ({TARGET => $lib});
+
+  unless ($rc) {
+    my @command = ();
+
+    # Linker
+    push @command, &select_flags ($info, 'LD');
+
+    # Linker output target (typical -o option)
+    push @command, &get_env ('LD_OUTPUT', 1), $info->{TARGET};
+
+    # Name of main object file
+    my $mainobj = (basename ($info->{SRC}) eq $info->{SRC})
+                  ? catfile (&get_env ('FCM_OBJDIR'), $info->{SRC})
+                  : $info->{SRC};
+    push @command, $mainobj;
+
+    # Link with Fortran BLOCKDATA objects if necessary
+    if (@{ $info->{BLOCKDATA} }) {
+      my @blockdata = @{ $info->{BLOCKDATA} };
+      my @objpath   = split /:/, &get_env ('FCM_OBJPATH');
+
+      # Search each BLOCKDATA object file from the object search path
+      for my $file (@blockdata) {
+        for my $dir (@objpath) {
+          my $full = catfile ($dir, $file);
+
+          if (-r $full) {
+            $file = $full;
+            last;
+          }
+        }
+
+        push @command, $file;
+      }
+    }
+
+    # Library search path
+    my $libopt  = &get_env ('LD_LIBSEARCH', 1);
+    my @libpath = split /:/, &get_env ('FCM_LIBPATH');
+    push @command, (map {$libopt . $_} @libpath);
+
+    # Link with temporary object library if it exists
+    push @command, &get_env ('LD_LIBLINK', 1) . $libname if -f $libfile;
+
+    # Other linker flags
+    my $flags = &select_flags ($info, 'LDFLAGS');
+    push @command, $flags;
+
+    # Execute command
+    my $tmpdir = &get_env ('FCM_TMPDIR', 1);
+    my $bindir = &get_env ('FCM_BINDIR', 1);
+    chdir $tmpdir;
+
+    my $command = join ' ', @command;
+    if ($verbose > 1) {
+      print 'cd ', $tmpdir, "\n";
+      print &timestamp_command ($command, 'Start');
+
+    } elsif ($verbose) {
+      print $command, "\n";
+    }
+
+    $rc = system $command;
+
+    print &timestamp_command ($command, 'End  ') if $verbose > 1;
+
+    # Move temporary output to correct location on success
+    # Otherwise, remove temporary output
+    if ($rc) { # error
+      unlink $info->{TARGET};
+
+    } else {   # success
+      print 'mv ', $info->{TARGET}, ' ', $bindir, "\n" if $verbose > 1;
+      rename $info->{TARGET}, &catfile ($bindir, $info->{TARGET});
+    }
+  }
+
+  # Remove the temporary object library
+  unlink $libfile if -f $libfile;
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = &archive (\%info);
+#
+# DESCRIPTION
+#   This method invokes the library archiver to create an object library. The
+#   argument $info is a hash reference set up in MAIN. The following
+#   environment variables are used:
+# 
+#   AR           - archiver command
+#   ARFLAGS      - AR options to update/create an object library
+#   FCM_VERBOSE  - verbose level
+#   FCM_LIBDIR   - destination directory of object libraries
+#   FCM_OBJPATH  - search path of object files
+#   FCM_OBJDIR   - destination directory of object files
+#   FCM_TMPDIR   - temporary destination directory of executable file
+# ------------------------------------------------------------------------------
+
+sub archive {
+  my $info = shift;
+
+  my $rc = 0;
+
+  # Verbose mode
+  my $verbose = &get_env ('FCM_VERBOSE');
+  $verbose    = 1 unless defined ($verbose);
+
+  # Set up the archive command
+  my $lib     = &basename ($info->{TARGET});
+  my $tmplib  = &catfile (&get_env ('FCM_TMPDIR', 1), $lib);
+  my @ar_cmd  = ();
+  push @ar_cmd, (&get_env ('AR', 1), &get_env ('ARFLAGS', 1));
+  push @ar_cmd, $tmplib;
+
+  # Get object directories and their files
+  my %objdir;
+  if (exists $info->{OBJECTS}) {
+    # List of objects set in the argument, sort into directory/file list
+    for my $name (@{ $info->{OBJECTS} }) {
+      my $dir = (&dirname ($name) eq '.')
+                ? &get_env ('FCM_OBJDIR', 1) : &dirname ($name);
+      $objdir{$dir}{&basename ($name)} = 1;
+    }
+
+  } else {
+    # Objects not listed in argument, search object path for all files
+    my @objpath  = split /:/, &get_env ('FCM_OBJPATH', 1);
+    my %objbase  = ();
+
+    # Get registered objects into a hash (keys = objects, values = 1)
+    my %objects = map {($_, 1)} split (/\s+/, &get_env ('OBJECTS'));
+
+    # Seach object path for all files
+    for my $dir (@objpath) {
+      next unless -d $dir;
+
+      chdir $dir;
+
+      # Use all files from each directory in the object search path
+      for ((glob ('*'))) {
+        next unless exists $objects{$_}; # consider registered objects only
+        $objdir{$dir}{$_} = 1 unless exists $objbase{$_};
+        $objbase{$_} = 1;
+      }
+    }
+  }
+
+  for my $dir (keys %objdir) {
+    next unless -d $dir;
+
+    # Go to each object directory and executes the library archive command 
+    chdir $dir;
+    my $command = join ' ', (@ar_cmd, sort keys %{ $objdir{$dir} });
+
+    if ($verbose > 1) {
+      print 'cd ', $dir, "\n";
+      print &timestamp_command ($command, 'Start');
+
+    } else {
+      print $command, "\n" if exists $info->{OBJECTS};
+    }
+
+    $rc = system $command;
+
+    print &timestamp_command ($command, 'End  ')
+      if $verbose > 1;
+    last if $rc;
+  }
+
+  # Move temporary output to correct location on success
+  # Otherwise, remove temporary output
+  if ($rc) { # error
+    unlink $tmplib;
+
+  } else {   # success
+    my $libdir = &get_env ('FCM_LIBDIR', 1);
+
+    print 'mv ', $tmplib, ' ', $libdir, "\n" if $verbose > 1;
+    rename $tmplib, &catfile ($libdir, $lib);
+  }
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flags = &select_flags (\%info, $set);
+#
+# DESCRIPTION
+#   This function selects the correct compiler/linker flags for the current
+#   sub-package from the environment variable prefix $set. The argument $info
+#   is a hash reference set up in MAIN.
+# ------------------------------------------------------------------------------
+
+sub select_flags {
+  my ($info, $set) = @_;
+
+  (my $srcroot = &basename ($info->{SRC})) =~ s/\.\S+$//;
+  my @names    = ($set);
+  push @names, split (/__/, $info->{SRCPACKAGE} . '__' . $srcroot);
+
+  my $string   = '';
+  while (@names) {
+    my $name = join '__', @names;
+    my $var  = &get_env ($name);
+
+    if (defined $var) {
+      $string = $var;
+      last;
+
+    } else {
+      pop @names;
+    }
+  }
+
+  return $string;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $variable = &get_env ($name);
+#   $variable = &get_env ($name, $compulsory);
+#
+# DESCRIPTION
+#   This internal method gets a variable from $ENV{$name}. If $compulsory is
+#   set to true, it throws an error if the variable is a not set or is an empty
+#   string. Otherwise, it returns C<undef> if the variable is not set.
+# ------------------------------------------------------------------------------
+
+sub get_env {
+  (my $name, my $compulsory) = @_;
+  my $string;
+
+  if ($name =~ /^\w+$/) {
+    # $name contains only word characters, variable is exported normally
+    die 'The environment variable "', $name, '" must be set, abort'
+      if $compulsory and not exists $ENV{$name};
+
+    $string = exists $ENV{$name} ? $ENV{$name} : undef;
+
+  } else {
+    # $name contains unusual characters
+    die 'The environment variable "', $name, '" must be set, abort'
+      if $compulsory and not exists $unusual_tool_name{$name};
+
+    $string = exists $unusual_tool_name{$name}
+              ? $unusual_tool_name{$name} : undef;
+  }
+
+  return $string;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $path = &catfile (@paths);
+#
+# DESCRIPTION
+#   This is a local implementation of what is in the File::Spec module.
+# ------------------------------------------------------------------------------
+
+sub catfile {
+  my @names = split (m!/!, join ('/', @_));
+  my $path  = shift @names;
+
+  for my $name (@names) {
+    $path .= '/' . $name if $name;
+  }
+
+  return $path;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $basename = &basename ($path);
+#
+# DESCRIPTION
+#   This is a local implementation of what is in the File::Basename module.
+# ------------------------------------------------------------------------------
+
+sub basename {
+  my $name = $_[0];
+
+  $name =~ s{/*$}{}; # remove trailing slashes
+
+  if ($name =~ m#.*/([^/]+)$#) {
+    return $1;
+
+  } else {
+    return $name;
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $dirname = &dirname ($path);
+#
+# DESCRIPTION
+#   This is a local implementation of what is in the File::Basename module.
+# ------------------------------------------------------------------------------
+
+sub dirname {
+  my $name = $_[0];
+
+  if ($name =~ m#^/+$#) {
+    return '/'; # dirname of root is root
+
+  } else {
+    $name =~ s{/*$}{}; # remove trailing slashes
+
+    if ($name =~ m#^(.*)/[^/]+$#) {
+      my $dir = $1;
+      $dir =~ s{/*$}{}; # remove trailing slashes
+      return $dir;
+
+    } else {
+      return '.';
+    }
+  }
+}
+
+# ------------------------------------------------------------------------------
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/bin/fcm_setup_konqueror
===================================================================
--- LMDZ5/branches/testing/tools/fcm/bin/fcm_setup_konqueror	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/bin/fcm_setup_konqueror	(revision 1665)
@@ -0,0 +1,44 @@
+#!/usr/bin/ksh
+# ------------------------------------------------------------------------------
+# NAME
+#   fcm_setup_konqueror
+#
+# SYNOPSIS
+#   fcm_setup_konqueror
+#
+# DESCRIPTION
+#   Set up Konqueror to use "fcm gui".
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Check number of arguments
+script=$(basename $0)
+usage="$script: no argument required"
+if (( $# != 0 )); then
+  echo "$usage, abort..." >&2
+  exit 1
+fi
+
+filename=fcm_gui.desktop
+
+file=$(dirname $0)
+file=${file%/bin}/etc/$filename
+
+if [[ ! -f $file ]]; then
+  echo "$script: $file not found, abort..." >&2
+  exit 1
+fi
+
+dir=$HOME/.kde/share/applnk/.hidden
+mkdir -p $dir
+cd $dir
+rm -f $filename             # Always remove.
+ln -s $file .
+
+echo "$script: finished"
+
+#EOF
Index: LMDZ5/branches/testing/tools/fcm/bin/fcm_update_version_dir.pl
===================================================================
--- LMDZ5/branches/testing/tools/fcm/bin/fcm_update_version_dir.pl	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/bin/fcm_update_version_dir.pl	(revision 1665)
@@ -0,0 +1,302 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   fcm_update_version_dir.pl
+#
+# SYNOPSIS
+#   fcm_update_version_dir.pl [OPTIONS] [CFGFILE]
+#
+# DESCRIPTION
+#   See $usage for detail.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard pragmas
+use strict;
+use warnings;
+
+# Standard modules
+use Getopt::Long;
+use Cwd;
+use File::Basename;
+use File::Path;
+use File::Spec;
+
+# FCM component modules:
+use lib File::Spec->catfile (dirname (dirname ($0)), 'lib');
+use Fcm::Config;
+use Fcm::Util;
+
+# Usage
+# ------------------------------------------------------------------------------
+my $this  = basename $0;
+my $usage = <<EOF;
+NAME
+  $this
+
+SYNOPSIS
+  $this [OPTIONS] [CFGFILE]
+
+DESCRIPTION
+  Update the version directories for a list of relative paths in the source
+  repository URL.
+
+OPTIONS
+  -d [--dest] arg: Specify a destination for the extraction. If not specified,
+                   the command extracts to the current working directory.
+  -h [--help]    : Print help and exit.
+  -f [--full]    : Specify the full mode. If not specified, the command runs
+                   in incremental mode.
+  -u [--url]  arg: Specify the source repository URL. No default.
+
+ARGUMENTS
+  A configuration file may be given to this command, or it will attempt to
+  read from the standard input. Each line in the configuration must contain
+  a relative path that resides under the given source repository URL. (Empty
+  lines and lines beginning with a "#" are ignored.) Optionally, each
+  relative path may be followed by a list of space separated "conditions".
+  Each condition is a conditional operator (>, >=, <, <=, == or !=) followed
+  by a revision number or the keyword HEAD. The command uses the revision
+  log to determine the revisions at which the relative path has been updated
+  in the source repository URL. If these revisions also satisfy the
+  "conditions" set by the user, they will be considered in the extraction.
+  In full mode, everything is re-extracted. In incremental mode, the version
+  directories are only updated if they do not already exist.
+
+COPYRIGHT
+  This program is part of the FCM system.
+  (C) Crown copyright Met Office. All rights reserved.
+  For further details please refer to the file COPYRIGHT.txt
+  which you should have received as part of this distribution.
+EOF
+
+# Options
+# ------------------------------------------------------------------------------
+my ($dest, $full, $help, $url);
+GetOptions (
+  'dest|d=s' => \$dest,
+  'full|f'   => \$full,
+  'help'     => \$help,
+  'url|u=s'  => \$url,
+);
+
+if ($help) {
+  print $usage;
+  exit;
+}
+
+$dest = cwd () unless $dest;
+
+die 'An URL must be specified with the --url option, abort' unless $url;
+
+# Arguments
+# ------------------------------------------------------------------------------
+if (@ARGV) {
+  die 'Cannot read: ', $ARGV[0], ', abort' unless -f $ARGV[0] and -r $ARGV[0];
+}
+
+# Get configuration settings
+# ------------------------------------------------------------------------------
+my $config = Fcm::Config->new ();
+$config->get_config ();
+
+# Expand URL keyword
+$url = &expand_url_keyword (URL => $url);
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfg = &main::cfg ();
+#
+# DESCRIPTION
+#   Return the $config variable.
+# ------------------------------------------------------------------------------
+
+sub cfg {
+  return $config;
+}
+
+# ------------------------------------------------------------------------------
+
+MAIN: {
+  my $date = localtime;
+  print $this, ': started on ', $date, "\n";
+
+  my %dirs;
+
+  # Read input (file) for a list directories and update conditions
+  while (<>) {
+    chomp;
+
+    # Ignore empty and comment lines
+    next if /^\s*(?:#|$)/;
+
+    # Each line must contain a relative path, and optionally a list of
+    # space delimited conditions
+    my @words = split /\s+/;
+    my $dir   = shift @words;
+
+    # Check that the conditions are valid
+    my @conditions;
+    for my $word (@words) {
+      if ($word =~ /^([<>]=?|[!=]=)(.+)$/i) {
+        # Condition must be a conditional operator followed by a revision
+        my ($operator, $rev) = ($1, $2);
+        $rev = &expand_rev_keyword (REV => $rev, URL => $url, HEAD => 1);
+        push @conditions, $operator . $rev;
+
+      } else {
+        print STDERR 'Warning: ignore unknown syntax for update condition: ',
+                     $word, "\n";
+      }
+    }
+
+    # Add directory and its conditions to a hash
+    if ($dir =~ s#/\*$##) { # Directory finishes with wildcard
+
+      # Run "svn ls" in recursive mode
+      my $dirurl  = join ('/', ($url, $dir));
+      my @files   = &run_command ([qw/svn ls -R/, $dirurl], METHOD => 'qx');
+
+      # Find directories containing regular files
+      while (my $file = shift @files) {
+	# Skip directories
+	next if $file =~ m#/$#;
+
+	# Get "dirname" of regular file and add to hash
+	my $subdir = join ('/', ($dir, dirname ($file)));
+	$dirs{$subdir} = \@conditions;
+      }
+
+    } else {
+      $dirs{$dir} = \@conditions;
+    }
+
+  }
+
+  # Update each directory, if required
+  for my $dir (sort keys %dirs) {
+    # Use "svn log" to determine the revisions that need to be updated
+    my %allversions;
+    {
+      my $command = 'svn log -q ' . join ('/', ($url, $dir));
+      my @log     = &run_command (
+        [qw/svn log -q/, join ('/', ($url, $dir))], METHOD => 'qx',
+      );
+      @log        = grep /^r\d+/, @log;
+
+      # Assign a sequential "version" number to each sub-directory
+      my $version = scalar @log;
+      for (@log) {
+        m/^r(\d+)/;
+        $allversions{$1} = 'v' . $version--;
+      }
+    }
+    my %versions = %allversions;
+
+    # Extract only revisions matching the conditions
+    if (@{ $dirs{$dir} }) {
+      my @conditions = @{ $dirs{$dir} };
+
+      for my $condition (@conditions) {
+        for my $rev (keys %versions) {
+          delete $versions{$rev} unless eval ($rev . $condition);
+        }
+      }
+    }
+
+    # Destination directory
+    my $dirpath = File::Spec->catfile ($dest, $dir);
+
+    if (-d $dirpath) {
+      if ($full or not keys %versions) {
+        # Remove destination directory top, in full mode
+        # or if there are no matching revisions
+        &run_command ([qw/rm -rf/, $dirpath], PRINT => 1);
+
+      } else {
+        # Delete excluded revisions if they exist, in incremental mode
+        if (opendir DIR, $dirpath) {
+          while (my $rev = readdir 'DIR') {
+            next unless $rev =~ /^\d+$/;
+
+            if (not grep {$_ eq $rev} keys %versions) {
+              my @command = (qw/rm -rf/, File::Spec->catfile ($dirpath, $rev));
+              &run_command (\@command, PRINT => 1);
+
+              # Remove "version" symlink
+              my $verlink = File::Spec->catfile ($dirpath, $allversions{$rev});
+              unlink $verlink if -l $verlink;
+            }
+          }
+          closedir DIR;
+        }
+      }
+    }
+
+    # Create container directory of destination if it does not already exist
+    if (keys %versions and not -d $dirpath) {
+      print '-> mkdir -p ', $dirpath, "\n";
+      my $rc = mkpath $dirpath;
+      die 'mkdir -p ', $dirpath, ' failed' unless $rc;
+    }
+
+    # Update each version directory that needs updating
+    for my $rev (keys %versions) {
+      my $revpath = File::Spec->catfile ($dest, $dir, $rev);
+
+      # Create version directory if it does not exist
+      if (not -e $revpath) {
+        # Use "svn export" to create the version directory
+        my @command = (
+          qw/svn export -q -r/,
+          $rev,
+          join ('/', ($url, $dir)),
+          $revpath,
+        );
+
+        &run_command (\@command, PRINT => 1);
+
+        # Run GenScr_GenRule on any component directories
+        # This can be removed once old versions of the SCSUI are no longer used
+	if ($dir =~ m#(?:^|/)components/#) {
+          my @command = (
+            "GenScr_GenRule",
+            File::Spec->catfile ($revpath, join ('.', (basename ($dir), "rule")))
+          );
+
+          &run_command (\@command, PRINT => 1);
+	}
+      }
+
+      # Create "version" symlink if necessary
+      my $verlink = File::Spec->catfile ($dest, $dir, $versions{$rev});
+      symlink $rev, $verlink unless -l $verlink;
+    }
+
+    # Symbolic link to the "latest" version directory
+    my $headlink = File::Spec->catfile ($dest, $dir, 'latest');
+    my $headrev  = 0;
+    for my $rev (keys %versions) {
+      $headrev = $rev if $rev > $headrev;
+    }
+
+    if (-l $headlink) {
+      # Remove old symbolic link if there is no revision to update or if it
+      # does not point to the correct version directory
+      my $org = readlink $headlink;
+      unlink $headlink if (! $headrev or $org ne $headrev);
+    }
+
+    # (Re-)create the "latest" symbolic link, if necessary
+    symlink $headrev, $headlink if ($headrev and not -l $headlink);
+  }
+
+  $date = localtime;
+  print $this, ': finished normally on ', $date, "\n";
+}
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/doc/collaboration/index.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/collaboration/index.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/collaboration/index.html	(revision 1665)
@@ -0,0 +1,369 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>External Distribution &amp; Collaboration for FCM Projects</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content=
+  "External Distribution &amp; Collaboration">
+  <meta name="keywords" content="FCM, distribution, collaboration">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <p align="right"><img src="logo.png" alt="Met Office logo" width="85" height=
+  "85"></p>
+
+  <h1>External Distribution &amp; Collaboration for FCM Projects</h1>
+
+  <p align="center">Last updated: 28 November 2006</a>
+
+  <p align="center">Met Office<br>
+  FitzRoy Road, Exeter<br>
+  Devon, EX1 3PB<br>
+  United Kingdom</p>
+
+  <p align="center">&copy; Crown Copyright 2006</p>
+
+  <p align="center">Questions regarding this document or permissions to quote
+  from it should be directed to the <a href=
+  "mailto:iprmanager@metoffice.gov.uk">IPR Manager</a>.</p>
+  
+  <script type="text/javascript">
+  <!--
+  var out = 'For printing, please use the '
+  out    += '<a href="fcm-collaboration.pdf">PDF<\/a> version of the document.'
+  document.write ('<p align="center">')
+  document.write (out)
+  document.write ('<\/p>')
+  //-->
+  </script>
+
+  <h2><a name="introduction" id="introduction">Introduction</a></h2>
+
+  <p>This document describes how projects configured under FCM can be
+  distributed externally. Particular attention is given to collaborative
+  distributions - where the external user regularly returns code for
+  consolidation into the central repositories which hold the master copies of the
+  code.</p>
+
+  <p><b>Note:</b> This document assumes that the repositories are inaccessible to
+  the external user, due to issues of security and practicality.</p>
+
+  <h2><a name="distribution" id="distribution">Creating a Distribution</a></h2>
+
+  <p>A system configured under FCM can be distributed by packaging a known
+  revision (usually corresponding to a stable release) into an archive (e.g. a
+  tarball) of directories and files. Various issues need to be considered:</p>
+
+  <ul>
+    <li>A distribution may contain a variety of different files including
+    source code, scripts, benchmark and validation tests, documentation,
+    etc.</li>
+
+    <li>A system may consist of several different <em>projects</em> which
+    should be put into separate directories in the distribution. Please refer
+    to the section <a href=
+    "../user_guide/system_admin.html#svn_design">Repository design</a> in the
+    FCM user guide for an explanation of what is meant by a project in this
+    context.</li>
+
+    <li>Some files in a project may not be included in the distribution. This
+    may be because they are of no interest to external users or because of
+    license restrictions. Such files will need to be filtered out when creating
+    the distribution.</li>
+
+    <li>The distribution may also contain some files which are not maintained
+    under FCM version control (test results for instance).</li>
+
+    <li>Some systems share code with other systems.
+
+      <ul>
+        <li>If a distribution is intended to be used standalone then the
+        necessary files from these other systems will need to be included. e.g.
+        The VAR system requires code from the OPS and GEN systems.</li>
+
+        <li>If the distribution is part of a wider collaboration then it is
+        likely that the files from the other systems will be distributed
+        separately. It is best if stable releases of the various systems can be
+        synchronised so that, for example, a VAR stable release uses code from
+        an OPS stable release which both use code from the same GEN release.</li>
+      </ul>
+    </li>
+
+    <li>Release notes should be prepared to accompany a distribution which
+    explain, among other things, how the distribution is structured.</li>
+
+    <li>The distribution should contain a file which identifies the repository
+    revision(s) contained in the distribution.</li>
+
+    <li>System managers will probably wish to maintain a script which automates
+    the generation of these distributions.</li>
+  </ul>
+
+  <h2><a name="feedback" id="feedback">Feeding Back Changes</a></h2>
+
+  <p>Although we would encourage all collaborators to make use of the FCM
+  system for version control, we recognise that they may already have their own
+  preferred systems in place. There is no particular problem with this. The
+  main requirement is that any proposed changes are provided as a modification
+  relative to the provided distribution. The changeset could be provided in
+  the form of a modified project tree or as a patchfile (refer to the man page
+  for the Unix command <em>patch</em> for details). If the change involves any
+  renaming or removal of files or directories then special instructions should be
+  provided plus a script to perform the changes.</p>
+
+  <p>At the central repository, the changeset should be applied to a branch
+  created from the repository revision which formed the basis of the changeset
+  (possibly making use of the Subversion utility
+  <a href="http://svnbook.red-bean.com/en/1.2/svn.advanced.vendorbr.html#svn.advanced.vendorbr.svn_load_dirs">
+  svn_load_dirs.pl</a>). Note that extra care is needed with changesets
+  provided as modified project trees if there are any files in the project which
+  are excluded from the distribution. Once imported, the changeset should then
+  undergo any necessary testing or review before being merged into the trunk.</p>
+
+  <h2><a name="usingfcm" id="usingfcm">Collaborating Using FCM for Version
+  Control</a></h2>
+
+  <p>There are a number of advantages if the FCM system is used for version
+  control by the collaborator. In particular it means that:</p>
+
+  <ul>
+    <li>Collaborators will be able to see all of the individual changesets
+    which went in to a new release rather than only being able to view each new
+    release as one big change.</li>
+
+    <li>The process of sending a proposed change to the central repository can be
+    standardised through the use of an "FCM patch" (explained later).</li>
+
+    <li>The FCM Extract system can be fully utilised.</li>
+
+    <li>Common tools will help to ease communication. We will all use technical
+    terms to mean the same thing.</li>
+  </ul>
+
+  <p>This section explains the recommended way of using FCM in a
+  collaboration.</p>
+
+  <h3><a name="initsvn" id="initsvn">Initialising the Subversion
+  Repositories</a></h3>
+
+  <p>The collaborator needs to set up a repository and import each of the
+  projects. Please see the section <a href=
+  "../user_guide/system_admin.html#svn_create">Creating a repository</a> in the
+  FCM user guide for advice. Collaborators may wish to use separate repositories
+  and Trac systems for each project or they may prefer to use a single
+  repository for all projects and use a single Trac system. Either option
+  should be fine so long as the same set of projects is retained.</p>
+
+  <p>After completing the initial import, the collaborator should have the
+  required set of projects available in Subversion where the initial version of
+  the trunk of each project corresponds with the initial stable release provided
+  in the distribution.</p>
+
+  <h3><a name="prepchanges" id="prepchanges">Preparing Changes at the
+  Collaborator's Site</a></h3>
+
+  <p>The recommended way of preparing changes is illustrated in Figure 1a:</p>
+
+  <p class="image"><img src="working-as-collaborator.png" alt=
+  "Figure 1a: working at the collaborator's site"><br>
+  Figure 1a: working at the collaborator's site</p>
+
+  <p>The collaborator will create a shared package branch from the latest
+  stable release on the trunk. This branch will contain all the changes that
+  will eventually be fed back to the central repository. Developers will also
+  create their own development branches. These may be branched from the latest
+  stable release on the trunk. Alternatively, if the change needs to build on
+  other changes then a branch can be created from the shared package branch. When
+  the changes are ready (i.e. tested, documented, reviewed, etc) then they are
+  merged into the shared package branch. The trunk is not used for the shared
+  changes as it is reserved for changes received from the central repository.</p>
+
+  <p>Should it be required, a second shared package branch can be created from
+  the same point to contain any local modifications that will not be fed back
+  to the central repository. A configuration branch can then be used to combine
+  the local changes with those destined to be fed back. This is illustrated in
+  Figure 1b:</p>
+
+  <p class="image"><img src="managing-local-changes.png" alt=
+  "Figure 1b: managing local changes"><br>
+  Figure 1b: managing local changes</p>
+
+  <h3><a name="feedbackfcm" id="feedbackfcm">Feeding Back Changes Using
+  FCM</a></h3>
+
+  <p>Eventually, a series of changesets will exist on the first package branch.
+  These changes will be fed back to the central repository via an "FCM patch".
+  This contains a series of differences associated with changesets in a given
+  branch of development, created by the <tt>fcm mkpatch</tt> command. For further
+  information about the command, please refer to its <a href=
+  "../user_guide/command_ref.html#fcm_svn_mkpatch">command reference</a> in the
+  FCM user guide.</p>
+
+  <p>At the central repository, the changeset will be applied to a branch
+  created from the repository revision which formed the basis of the changeset.
+  This is illustrated in Figure 2:</p>
+
+  <p class="image"><img src="feeding-back-patch.png" alt=
+  "Figure 2: feeding back changes"><br>
+  Figure 2: feeding back changes</p>
+
+  <p>Patches will usually be exchanged in the form of a tarball. To apply the
+  patch it must first be extracted to a directory. In this directory there
+  should be a shell script called <tt>fcm-import-patch</tt>. A TARGET needs to
+  be specified when invoking the script. The TARGET must either be a URL or a
+  working copy of a valid project tree that can accept the import of the
+  patches. It is essential that this target matches the version of the project
+  from which the patch was created (usually this means a particular stable
+  release). The script contains a series of <tt>cp</tt> and <tt>svn</tt>
+  commands to import the changesets one by one. Note that the changesets are
+  committed automatically with no user interaction. It is worth ensuring that
+  an up to date backup of the repository is available in case of problems.</p>
+
+  <h3><a name="changescentral" id="changescentral">Incorporating Changes into
+  the Trunk of the Central Repository</a></h3>
+
+  <p>Once the changes have undergone any necessary testing or review they can
+  be merged into the trunk. There are three ways of approaching this:</p>
+
+  <ol>
+    <li>As one changeset: all changes in the branch will be merged into the
+    trunk as a single changeset. This approach is the easiest and has the
+    advantage that any conflicts only need to be resolved once. However, the
+    drawback of this approach is that the logical changesets as fed back by the
+    collaborator will be combined into a large single changeset on the trunk,
+    which may not be the most desirable (although the logical changesets will
+    still be available to examine on the import branch). This is illustrated in
+    Figure 3a:
+
+      <p class="image"><img src="merging-patch-one.png" alt=
+      "Figure 3a: merging a patch in a single changeset"><br>
+      Figure 3a: merging a patch in a single changeset</p>
+    </li>
+
+    <li>As multiple changesets: each changeset in the branch will be merged
+    into the trunk in order. This can be quite complicated and time consuming,
+    especially if you have a large number of changesets and there are a lot of
+    clashes. The advantage is that each logical changeset will retain its
+    logical identity, which may be more desirable in the long run, when you
+    come to inspect the history. This is illustrated in Figure 3b:
+
+      <p class="image"><img src="merging-patch-multi.png" alt=
+      "Figure 3b: merging a patch in multiple changesets"><br>
+      Figure 3b: merging a patch in multiple changesets</p>
+    </li>
+
+    <li>As a mixture of the above: you may want to combine the above two
+    approaches when it makes sense to do so. For example, there may be a series
+    of small changesets that can be combined logically, or there may be a
+    changeset that fixes a bug introduced in the previous one. The bottom line
+    is that the project/system manager should use his/her own judgement in the
+    matter for what is best for the future of the project.</li>
+  </ol>
+
+  <h3><a name="changescollab" id="changescollab">Incorporating Updates at the
+  Collaborator's Site</a></h3>
+
+  <p>Once a new stable release is available it will be supplied in the form of
+  a distribution tarball as described earlier. However, collaborators will also
+  be supplied with an "FCM patch" (as described earlier) for each project
+  containing all the changes made since the previous stable release. Note that
+  this assumes that stable releases are prepared on the trunk and not in
+  branches.</p>
+
+  <p>Each patch should be applied to the trunk of the collaborator's
+  repository. This means that the collaborator's trunk will always be mirroring
+  that of the central repository. This is illustrated in Figure&nbsp;4:</p>
+
+  <p class="image"><img src="mirroring-trunk.png" alt=
+  "Figure 4: mirroring the trunk at the collaborator's site"><br>
+  Figure 4: mirroring the trunk at the collaborator's site</p>
+
+  <p>In order to be certain that the patch has worked correctly, we recommend
+  that a check is performed to ensure that the new stable release on the trunk
+  matches the files provided in the distribution.</p>
+
+  <h3><a name="updatebranches" id="updatebranches">Updating Existing
+  Branches</a></h3>
+
+  <p>Old branches that are still active at the collaborators site should be
+  updated to the latest stable release when it becomes available. Developers
+  should create a new branch from the latest stable release and then merge the
+  changes from the old branch to the new branch. The old branch should be
+  deleted once it is no longer required. This is illustrated in Figure 5a:</p>
+
+  <p class="image"><img src="updating-branch.png" alt=
+  "Figure 5a: updating a branch to the latest stable release"><br>
+  Figure 5a: updating a branch to the latest stable release</p>
+
+  <p>Note that the merge will be easiest if the old branch was created from the
+  previous stable release. If it was created from the shared package branch
+  then a custom merge will be required to achieve the desired result. This is
+  illustrated in Figure 5b:</p>
+
+  <p class="image"><img src="updating-shared-branch.png" alt=
+  "Figure 5b: updating a branch of the shared package branch"><br>
+  Figure 5b: updating a branch of the shared package branch</p>
+
+  <h3><a name="other" id="other">Other Scenarios</a></h3>
+
+  <p>The previous sections have only considered how developments on the trunk of
+  a central repository can be shared with a single collaborator. However, the
+  same techniques can be applied to more complex situations.</p>
+
+  <ul>
+    <li>If there are multiple external collaborators each working with their own
+    repository then hopefully it is clear that this does not alter things in any
+    way. Inevitably there will be an increased workload on the maintainers of the
+    central repository. There will also be an increased need for coordination of
+    planned code changes. However, the method of code exchange is unaltered.</li>
+
+    <li>Sometimes there may be the need to collaborate on development of a branch
+    (i.e. to exchange code which is not yet ready to be incorporated onto the
+    trunk). The collaborator would maintain the trunk of their repository as
+    before, importing patches to keep their trunk alligned with the stable
+    releases from the central repository. In addition, they would receive an FCM
+    patch from the central repository representing the changes on the shared
+    branch relative to the stable release. The collaborator should create a
+    branch from the stable release and the patch should then be imported onto
+    this branch. They should then create a branch from this branch on which to
+    prepare their changes. When ready the changes would be returned in the form
+    of an FCM patch, and so on. Hopefully it can be seen that the same process
+    can be applied to this shared branch as we have previously described for
+    trunk developments.</li>
+  </ul>
+
+  <h2><a name="further" id="other">Further Considerations</a></h2>
+
+  <p>The previous sections have only considered the version control aspects of a
+  collaboration. This section lists some other aspects of the collaboration which
+  will need to be considered.</p>
+
+  <ul>
+    <li>The FCM build system can be used regardless of what version control
+    system is used. This avoids effort being wasted trying to maintain
+    compatibility with an alternate build system. It also ensures that any code
+    changes prepared by the collaborator are compatible with the coding standards
+    which the FCM build system requires. Even if there are good reasons for the
+    collaborator not to use FCM for version control, it is highly recommended
+    that the FCM build system is used (assuming that is what is used at the
+    central repository).</li>
+
+    <li>Coding standards should be agreed by all collaborators.</li>
+
+    <li>Working practises should be agreed which should define, amongst other
+    things, what level of testing, review and documentation is expected to
+    accompany any proposed change.</li>
+
+    <li>All parties in the collaboration should note the advice given in the
+    <a href="../user_guide/code_management.html#svn_problems">FCM user guide</a>
+    to avoid renaming files or directories unless you can ensure that no-one is
+    working in parallel on the affected areas of the project.</li>
+
+    <li>IPR, copyright and license issues should be agreed by all collaborators.</li>
+  </ul>
+
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/collaboration/logo.png
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/collaboration/logo.png	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/collaboration/logo.png	(revision 1665)
@@ -0,0 +1,1 @@
+link ../etc/logo.png
Index: LMDZ5/branches/testing/tools/fcm/doc/collaboration/maintain.js
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/collaboration/maintain.js	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/collaboration/maintain.js	(revision 1665)
@@ -0,0 +1,1 @@
+link ../etc/maintain.js
Index: LMDZ5/branches/testing/tools/fcm/doc/collaboration/style.css
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/collaboration/style.css	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/collaboration/style.css	(revision 1665)
@@ -0,0 +1,1 @@
+link ../etc/style.css
Index: LMDZ5/branches/testing/tools/fcm/doc/collaboration/style.html2ps.css
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/collaboration/style.html2ps.css	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/collaboration/style.html2ps.css	(revision 1665)
@@ -0,0 +1,1 @@
+link ../etc/style.html2ps.css
Index: LMDZ5/branches/testing/tools/fcm/doc/design/build.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/design/build.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/design/build.html	(revision 1665)
@@ -0,0 +1,812 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM Detailed Design: Build System</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="FCM Detailed Design: Build System">
+  <meta name="keywords" content="FCM, design">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM Detailed Design</a> &gt; Build System
+  </address>
+
+  <h1>Build System</h1>
+  
+  <p>In this chapter, we shall discuss in detail the design of the build
+  system. For information of how to use the build system, please see: <a
+  href="../user_guide/build.html">FCM System User Guide &gt; The Build
+  System</a>.</p>
+
+  <p>The build system analyses the directory tree containing a set of source
+  code, processes the configuration, and invokes <em>make</em> to compile/build
+  the source code into the project executables. The system is written in a set
+  of Perl modules. It is designed to work with GNU <em>make</em>. It creates
+  the <em>Makefile</em> and many other dependent files automcatically. The
+  build system uses a similar interface to the extract system. Its
+  configuration file can be produced through the extract system. It also
+  shares the same command line interface and many other utilities with the
+  code management system and the extract system.</p>
+
+  <h2><a name="io">Input and Output</a></h2>
+
+  <p>The build system has the following input:</p>
+
+  <ul class="pad">
+    <li>a directory tree populated with a set of Fortran and C source files,
+    and scripts written in Perl, Python, TCL, PVWave or a Unix shell.</li>
+
+    <li>the location of the root directory of the build.</li>
+
+    <li>the tools/commands (and their options) to be used for the build.</li>
+
+    <li>the locations of previous builds, if the current build is to base on
+    them.</li>
+
+    <li>other build options.</li>
+  </ul>
+
+  <p>Output from the build system includes:</p>
+
+  <ul class="pad">
+    <li>the targets of the build and their dependencies.</li>
+
+    <li>other files used by the system to build the targets.</li>
+  </ul>
+
+  <h2><a name="component">Components</a></h2>
+
+  <p>The build system uses the following commands, modules and tools:</p>
+
+  <table class="pad" summary="build system components" border="1">
+    <tr>
+      <th>Name</th>
+
+      <th>Category</th>
+
+      <th>Description</th>
+    </tr>
+
+    <tr>
+      <th>fcm</th>
+
+      <td>Perl executable</td>
+
+      <td>Top level command line interface of the FCM system.</td>
+    </tr>
+
+    <tr>
+      <th>fcm_internal</th>
+
+      <td>Perl executable</td>
+
+      <td>Command wrapper for the compiler and linker.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::Build</th>
+
+      <td>Perl module</td>
+
+      <td>Main class that controls the running of the build system.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::BuildTask</th>
+
+      <td>Perl module</td>
+
+      <td>A class that performs various "tasks" (such as pre-process and
+      generate interface) for the build system.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::CfgFile</th>
+
+      <td>Perl module</td>
+
+      <td>A class for reading from and writing to configuration files.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::Compiler</th>
+
+      <td>Perl module</td>
+
+      <td>A class for wrapping the compiler and linker commands.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::Config</th>
+
+      <td>Perl module</td>
+
+      <td>A class that contains the configuration settings shared by all
+      FCM components.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::SrcFile</th>
+
+      <td>Perl module</td>
+
+      <td>A class that controls the actions on a source file.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::SrcPackage</th>
+
+      <td>Perl module</td>
+
+      <td>A class that deals with the actions on a source directory
+      sub-package.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::Util</th>
+
+      <td>Perl module</td>
+
+      <td>A collection of utilities shared by all FCM components.</td>
+    </tr>
+
+    <tr>
+      <th>Ecmwf::Fortran90_stuff</th>
+
+      <td>Perl module</td>
+
+      <td>A utility originally developed by the ECMWF for generating interface
+      blocks for Fortran 9X source files. Modified for adoptation by the FCM
+      system.</td>
+    </tr>
+
+    <tr>
+      <th>make</th>
+
+      <td>Unix utility</td>
+
+      <td>The <em>make</em> build utility. FCM is designed to work with the
+      GNU version of <em>make</em>.</td>
+    </tr>
+
+    <tr>
+      <th>ksh</th>
+
+      <td>Unix shell</td>
+
+      <td>The following shell commands are used: "cp", "rm", "mv", "cd" and
+      "touch".</td>
+    </tr>
+
+    <tr>
+      <th>f90aib</th>
+
+      <td>Fortran utility</td>
+
+      <td>Formerly used by the GEN system as the generator for Fortran 9X
+      interface blocks. It is a freeware developed by Michel Olagnon at the
+      French Research Institute for Exploitation of the Sea. Its use is still
+      supported by FCM, but the ECMWF interface generator is now
+      preferred.</td>
+    </tr>
+  </table>
+
+  <h2><a name="command">The Build Command</a></h2>
+
+  <p>There are several options that can be supplied to the build command.
+  These options are implemented as follows:</p>
+
+  <ul>
+    <li><strong>Archive mode</strong>: the build system generates many files,
+    which are placed in various sub-directories according to their categories.
+    Most of these files are not used in the runtime environment. To prevent a
+    clutter up of disk space, it may be desirable to archive these
+    sub-directories. The system implements this by using the "tar" command to
+    archive each sub-directory. For an incremental build in the same
+    directory, the archived "tar" files are extracted back into the
+    sub-directories so that they can be re-used. It is worth noting that the
+    archive mode should not be used if a build is going to be re-used as a
+    pre-compiled build, as it will not be possible to extract the "tar" archives
+    back to their original forms. The default is not to archive
+    sub-directories.</li>
+
+    <li><strong>Full mode</strong>: on an incremental build, the system removes
+    all sub-directories created by the previous build, so that a new build can
+    be performed. The default is to perform an incremental build.</li>
+
+    <li><strong>Parallel jobs</strong>: this is implemented via the option in
+    GNU <em>make</em>. The generated <em>Makefile</em> is written with
+    parallel <em>make</em> in mind. The default is to perform a serial
+    build.</li>
+
+    <li><strong>Stage</strong>: this is implemented by running the build
+    system up to and including a named or a numbered stage. The default is to
+    go through all the stages.</li>
+
+    <li><strong>Targets</strong>: if targets are specified in the build
+    command, overrides the default targets supplied to the <em>make</em>
+    command. The default is to build the "all" target.</li>
+
+    <li><strong>Verbose</strong>: the verbose setting is a variable in the
+    Fcm::Config module. If the option is specified in the build command, it
+    sets this variable to the value supplied to the option. At various places
+    in the build process, it may be useful to print out diagnostic
+    information. This variable contols whether the information will get
+    printed.</li>
+  </ul>
+
+  <h2><a name="fcm-cfg">The Central/User Configuration File</a></h2>
+
+  <p>When we invoke the FCM command, it creates a new instance of Fcm::Config,
+  which reads, processes and stores information from the central and user
+  configuration file. The default settings in Fcm::Config is overwritten by
+  the information provided by the central configuration file. If a user
+  configuration file is found, its settings will take overall precedence.
+  These settings are stored in the Fcm::Config instance, which are parsed to
+  all other modules used by the build system. By convention, the reference to
+  the Fcm::Config instance can normally be fetched by the "config" method for
+  all OO "Fcm::" modules.</p>
+
+  <h2><a name="bld-cfg">The Build Configuration File</a></h2>
+
+  <p>When we invoke the build command, it creates a new instance of Fcm::Build,
+  which automatically creates a new instance of Fcm::CfgFile. If an argument
+  is specified in the build command, it is used as the build configuration
+  file if it is a regular file. Otherwise, it is used to search for the build
+  configuration file. If no argument is specified, the current working directory
+  is searched. Fcm::CfgFile will attempt to locate a file called "bld.cfg"
+  under this directory. If such a file is not found, it will attempt to locate
+  it under "cfg/bld.cfg".</p>
+  
+  <p>Once a file is located, Fcm::CfgFile will attempt to parse it. This is
+  done by reading and processing each line of the configuration file into
+  separate label, value and comment fields. Each line is then pushed into an
+  array that can be fetched using the "lines" method of the Fcm::CfgFile
+  instance. Internally, each line is recorded as a reference to a hash table
+  with the following keys:</p>
+
+  <ul class="pad">
+    <li>LABEL: the label of a declaration.</li>
+
+    <li>VALUE: the value of a declaration.</li>
+
+    <li>COMMENT: the comment following a declaration or the comment in a
+    comment line.</li>
+
+    <li>NUMBER: the line number of the current line in the source file.</li>
+
+    <li>SRC: the name of the source file.</li>
+  </ul>
+  
+  <p>The information given by each line is "deciphered" by Fcm::Build. The
+  information is processed in the following ways:</p>
+
+  <ul class="pad">
+    <li>The configuration file type "CFG::TYPE" and version "CFG::VERSION"
+    declarations are stored as properties of the Fcm::CfgFile instance.
+    Fcm::Build uses the information to ensure that it is reading a build
+    configuration file.</li>
+
+    <li>Build target(s) declarations "TARGET" are delimited by space
+    characters. Each target is pushed into the array reference "TARGET".</li>
+
+    <li>The location of the build root directory "DIR::ROOT" and its
+    sub-directories are stored in the "DIR" hash reference in the Fcm::Build
+    instance.  The keys of the hash table are the internal names of the
+    sub-directories, and the values are the locations of the
+    sub-directories.</li>
+
+    <li>The source directories "SRC::&lt;pcks&gt;" are stored in the "SRCDIR"
+    hash reference under the Fcm::Build instance. The keys of the hash table
+    are the names of the sub-packages. (If package names are delimited by the
+    double colons "::", they are turned into the double underscores "__" at
+    this stage.) The values of the "SRCDIR" hash reference are new instances
+    of Fcm::SrcPackage. When initialised, Each Fcm::SrcPackage creates a list
+    of source files in its source directory. For each source file in the list,
+    a new instance of Fcm::SrcFile is created, and pushed into the the
+    "SRCFILE" array reference under the Fcm::SrcPackage instance. When
+    initialised, each Fcm::SrcFile instance will attempt to determine the type
+    associated with the source file. This information can be fetched using the
+    "type" method of the Fcm::SrcFile instance.</li>
+
+    <li>Pre-processor switches "PP[::&lt;pcks&gt;]" declarations are stored in
+    the "PP" hash reference under the Fcm::Build instance. The keys of this hash
+    table are the names of the sub-packages, prefix with PP and a pair of
+    underscores, i.e. "PP__&lt;pcks&gt;". The declaration to switch on/off
+    pre-processing globally is stored using the key "PP". The values in the
+    hash table is either true (1) or false (0).</li>
+
+    <li>A tool declaration "TOOL::&lt;name&gt;[::&lt;pcks&gt;]" is stored as
+    a setting in Fcm::Config as ("TOOL", &lt;name&gt;[__&lt;pcks&gt;]. The
+    value of the declaration can then be fetched using the "setting" method of
+    the Fcm::Config instance.</li>
+
+    <li>An exclude dependency declaration "EXCL_DEP[::&lt;pcks&gt;]" is stored
+    as a setting in Fcm::Config as ("EXCL_DEP", &lt;value&gt;, &lt;pcks&gt;,
+    where &lt;value&gt; is the value of the declaration. For an exclude
+    dependency declaration that applies globally, &lt;pcks&gt; is set to a
+    null string "".) The value of an exclude dependency setting is always set
+    to 1.</li>
+
+    <li>Input file extension declaration "INFILE_EXT::&lt;ext&gt;" is stored
+    as a setting in Fcm::Config as ("INFILE_EXT", &lt;ext&gt;). The value of
+    the setting can then be fetched using the "setting" method of the
+    Fcm::Config instance.</li>
+
+    <li>Output file extension declaration "OUTFILE_EXT::&lt;type&gt;" is
+    stored as a in Fcm::Config as ("OUTFILE_EXT", &lt;type&gt;). The value of
+    the setting can then be fetched using the "setting" method of the
+    Fcm::Config instance.</li>
+
+    <li>For each "USE" declaration to use a pre-compiled build, a new instance of
+    Fcm::Build is created. The instance Fcm::Build for the previous build
+    creates a new instance of Fcm::CfgFile for its configuration file. The
+    configuration of the previous build is read and processed as described
+    above. The current instance of Fcm::Build will then attempt to inherit the
+    settings of the previous build where appropriate. The Fcm::Build instance
+    for the pre-compiled build is pushed into the "USE" array reference under
+    the current Fcm::Build.</li>
+
+    <li>The inherit flags for targets "INHERIT::TARGET", source directories
+    "INHERIT::SRC[::&lt;pcks&gt;]" and pre-processor switches
+    "INHERIT::PP[::&lt;pcks&gt;]" are stored in the "INHERIT" hash reference
+    under the Fcm::Build instance. For declarations that apply globally, the
+    keys to the hash table are "TARGET", "SRCDIR" or "PP". If the declarations
+    apply to &lt;pcks&gt;, the keys are "SRCDIR__&lt;pcks&gt;" or
+    "PP__&lt;pcks&gt;". (The inherit target flag always applies globally.)</li>
+  </ul>
+
+  <p>Unless the search source flag "SEARCH_SRC" is switched off (0) in the build
+  configuration, Fcm::Build will attempt to search the source sub-directory
+  "src/" of the build root recursively for source directory sub-packages. The
+  source directories obtained in the search are treated as if they are
+  declared using "SRC::&lt;pcks&gt;" in the build configuration file.</p>
+
+  <h2><a name="flags">Compiler Flags</a></h2>
+
+  <p>As discussed in the user guide, if you declare the Fortran compiler flags
+  without specifying a sub-package, the declaration applies globally.
+  Otherwise, it only applies to the Fortran source files within the
+  sub-package. This is implemented via a simple "tool selection" mechanism. You
+  may have noticed that all TOOL declarations (and TOOL settings in
+  Fcm::Config) are turned into an environemnt variable declaration in the
+  generated <em>Makefile</em>. For example, if we have a
+  "FFLAGS__bar__egg__ham__foo" declaration, it will be declared as an
+  environment variable in the generated <em>Makefile</em>. Suppose we have a
+  source file "foo.f90" under the sub-package "bar::egg::ham". When we invoke
+  the compiler wrapper (i.e. "fcm_internal" and "Fcm::Compile") to compile the
+  source file, the system will first attempt to select from the FFLAGS
+  environment variable that matches the sub-package of the source file, which
+  is "FFLAGS__bar__egg__ham__foo" in this case. If the environment variable
+  does not exist, it will attempt to go one sub-package up, i.e.
+  "FFLAGS__bar__egg__ham", and so on until it reaches the global "FFLAGS"
+  declaration, (which should always exists).</p>
+
+  <p>For changes in compiler flags declaration, the build system should
+  trigger re-compilation of required targets only. This is implemented using a
+  "flags" file system. These "flags" files are dummy files created in the
+  "flags/" sub-directory of the build root. They are updated by the "touch"
+  command.  The following dependencies are followed:</p>
+
+  <ul>
+    <li>Source files are dependent on its own "flags" file. E.g. the file
+    Ops_Switch in sub-package ":ops::code::OpsMod_Control" is dependent
+    on "FFLAGS__ops__code__OpsMod_Control__Ops_Switch.flags".</li>
+
+    <li>The "flags" file of a source file is dependent on the "flags" file
+    of its container sub-package. E.g. the above flags file is dependent
+    on "FFLAGS__ops__code__OpsMod_Control.flags".</li>
+
+    <li>The "flags" file of a sub-package is dependent on the "flags"
+    file of its container sub-package. E.g. the above is dependent on
+    "FFLAGS__ops__code.flags", which is dependent on
+    "FFLAGS__ops.flags".</li>
+
+    <li>The "flags" file of a top-level package is dependent on the
+    "flags" file of the global flags. E.g. "FFLAGS__ops.flags" is
+    dependent on "FFLAGS.flags".</li>
+
+    <li>The "flags" file of the global "flags" file is dependent on the
+    "flags" file of the compiler command. E.g. "FFLAGS.flags" is
+    dependent on "FC.flags".</li>
+  </ul>
+  
+  <p>The system records changes in declared tools using a cache file, (called
+  ".bld_tool", located at the ".cache/" sub-directory of the built root). It
+  is basically a list of "TOOL::" declarations for the latest build.  When an
+  incremental build is invoked, the list is compared against the current set.
+  If there are changes (modification, addition and deletion) in any
+  declarations, the timestamp of the corresponding "flags" files will be
+  updated. Files depending on the updated "flags" file will then be considered
+  out of date by <em>make</em>, triggering a re-build of those files.</p>
+
+  <h2><a name="interface">Fortran 9X Interface Block Generator</a></h2>
+
+  <p>The build system generates an interface block file for each Fortran 9X
+  source file. If the original source file has been pre-processed, the system
+  uses the pre-processed source file. Otherwise, the system uses the original
+  source file. For each source file containing standalone subroutines and
+  functions, the system will generate an interface file containing the
+  interfaces for the subroutines and functions. The interface files for other
+  Fortran 9X source files are empty.</p>
+
+  <p>Fcm::Build controls the creation of interface files by searching for a
+  list of Fcm::SrcFile instances containing Fortran 9X source files, by
+  calling the "is_type ('FORTRAN9X')" method of each Fcm::SrcFile instance.
+  For each of Fortran 9X source file, a Fcm::BuildTask is created to "build"
+  the interface file. The build task is dependent on the interface
+  generator. The interface files will be re-generated if we change the
+  interface generator. The generated interface is held in an array initially.
+  If an old file exists, it is read into an array so that it can be compared
+  with the current one. The current interface is written to the interface file
+  if it is not the same as the old one, or if an old one does not already
+  exist.</p>
+
+  <p>FCM supports the use of <em>f90aib</em> and the ECMWF interface
+  generator. The latter is the default.</p>
+
+  <h2><a name="dependency">Depdendency Scanner</a></h2>
+
+  <p>For each source directory sub-package, the build system scans its source
+  files for dependency information. The dependency scanner uses a pre-defined
+  set of patterns and rules in Fcm::Config to determine whether a line in a
+  source file contains a dependency. Only source files of supported types are
+  scanned. The dependency information of a sub-package is stored in the memory
+  as well as a cache file. The latter can be re-used by subsequent incremental
+  builds. In an incremntal build, only those source files newer than the cache
+  file is re-scanned for dependency. The cache file is read/written using
+  temporary instances of Fcm::CfgFile.</p>
+
+  <p>The control of the source file selection process is handled by the
+  Fcm::SrcPackage instances, while the actual dependency scans are performed
+  via the scan_dependency method of the Fcm::SrcFile instances.</p>
+
+  <p>A dependency has a type. For example, it can be a Fortran module or an
+  include file. The type of a dependency determines how it will be used by the
+  source file during the <em>make</em> stage, and so it affects how the
+  <em>make</em> rule will be written for the source file. In memory, the
+  dependency information is stored in a hash table, which can be retrieved as
+  a property of the Fcm::SrcFile instance. The keys of the hash table are the
+  dependency items, and the values are their types.</p>
+
+  <p>A dependency is not added to the hash table if it matches with an exclude
+  dependency declaration for the current sub-package.</p>
+
+  <p>While the dependency scanner is scanning through each line of a Fortran
+  source file, the system also attempt to determine its internal name. This is
+  normally the name of the first compilable program unit defined in the
+  Fortran source file. The internal name is converted into lowercase (bearing
+  in mind that Fortran is case insensitive), and will be used to name the
+  compiled object file of the source file.</p>
+
+  <p>The package configuration file is a system to bypass the automatic
+  dependency scanner. It can also be used to add extra dependencies to a
+  source file in the package. The configuration file is a special file in a
+  source package. The lines in the file is read using a temporary instance of
+  Fcm::CfgFile created by Fcm::SrcPackage. All declarations in a package
+  configuration file apply to named source files. The declarations set the
+  properties of the Fcm::SrcFile instance associated with the source file. It
+  can be used to add dependencies to a source file, and to tell the system to
+  bypass automatic dependency scanning of the source file. Other modifications
+  such as the internal name (object file name) of a source file, or the target
+  name of the executable can also be set using the package configuration file
+  in the package containing the source file.</p>
+
+  <h2><a name="rule">Make Rule Generator</a></h2>
+
+  <p>The dependency information is used to create the <em>Makefile</em>
+  fragments for the source directory sub-packages. A <em>Makefile</em> fragment
+  is updated if it is older than its corresponding dependency cache file.</p>
+
+  <p>The following is a list of file types and their <em>make</em> rule
+  targets:</p>
+
+  <table class="pad" summary="list of file types and thier make rules"
+  border="1">
+    <tr>
+      <th colspan="2">File type</th>
+
+      <th>Targets</th>
+    </tr>
+
+    <tr>
+      <th rowspan="5">SOURCE</th>
+
+      <th>all</th>
+
+      <td>
+        <ul>
+          <li>compile: object file</li>
+
+          <li>touch: flags file for compiler flags</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>FPP and C</th>
+
+      <td>
+        <p>If the original source has not been pre-processed:</p>
+
+        <ul>
+          <li>touch: flags file for pre-processor definition macros</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>PROGRAM</th>
+
+      <td>
+        <ul>
+          <li>load: executable binary file</li>
+
+          <li>touch: flags file for loader (linker) flags</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>all except PROGRAM</th>
+
+      <td>
+        <ul>
+          <li>touch: "done" file to denote the resolution of all external
+          objects.</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>all FORTRAN except PROGRAM and MODULE</th>
+
+      <td>
+        <ul>
+          <li>interface: "interface" file to denote that all dependent module
+          information files are up to date.</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th colspan="2">INCLUDE</th>
+
+      <td>
+        <ul>
+          <li>cp: "include" file to "inc/" sub-directory</li>
+
+          <li>touch: "idone" file to denote the resolution of all external
+          objects.</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th colspan="2">EXE and SCRIPT</th>
+
+      <td>
+        <ul>
+          <li>cp: executable file to "bin/" sub-directory</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th colspan="2">LIB</th>
+
+      <td>
+        <ul>
+          <li>ar: archive object library file</li>
+        </ul>
+      </td>
+    </tr>
+  </table>
+
+  <p>The resulting <em>Makefile</em> is made up of a top level
+  <em>Makefile</em> and a list of include ".mk" files, (one for each
+  sub-package). The toplevel <em>Makefile</em> consists of useful environment
+  variables, including the search path of each sub-directory, the build tools,
+  the verbose mode and the VPATH directives for different file types. It has
+  two top level build targets, "all" and "clean". The "all" target is the
+  default target, and the "clean" target is for removing the previous build
+  from the current build root. It also has a list of targets for building the
+  top level and the container sub-package "flags" files. At the end of the
+  file is a list of "include" statements to include the ".mk" files.</p>
+
+  <p>A the top of each of ".mk" files are local variables for locating the
+  source directories of the sub-package. Below that are the rules for building
+  source files in the sub-package.</p>
+
+  <h2><a name="pp">Pre-processing</a></h2>
+
+  <p>As discussed in the user guide, the PP switch can be used to switch on
+  pre-processing. The PP switch can be specified globally or for individual
+  sub-packages. (However, it does not go down to the level of individual
+  source files.) The "inheritance" relationship is similar to that of the
+  compiler flags.</p>
+
+  <p>Currently, only Fortran source files with uppercase file extensions and C
+  source files are considered to be source files requiring pre-processing. If
+  a sub-package source directory contains such files and has its PP switch set
+  to ON, the system will attempt to pre-process these files.</p>
+
+  <p>The system allows header files to be located anywhere in the source tree.
+  Therefore, a dependency scan is performed on all files requiring
+  pre-processing as well as all header files to obtain a list of "#include"
+  header file dependencies. For each header file or source file requiring
+  pre-processing, a new instance of Fcm::BuildTask is created to represent a
+  "target". Similar to the logic in <em>make</em>, a "target" is only up to
+  date if all its dependencies are up to date. The Fcm::BuildTask instance
+  uses this logic to pre-process its files. Dependent header files are updated
+  by copying them to the "inc/" sub-directory of the build root. The "inc/"
+  sub-directory is automatically placed in the search path of the
+  pre-processor command, usually by the "-I" option. Pre-processing is
+  performed by a method of the Fcm::SrcFile instance. The method builds the
+  command by selecting the correct set of pre-processor definition macros and
+  pre-processor flags, using an inheritance relationship similar to that used
+  by the compiler flags. Unlike <em>make</em>, however, Fcm::BuildTask only
+  updates the target if both the timestamp and the content are out of date.
+  Therefore, if the target already exists, the pre-processing command is only
+  invoked if the timestamp of the target is out of date. The output from the
+  pre-processor will then be compared with the content in the target. The
+  target is only updated if the content has changed.</p>
+
+  <p>Once a source file is pre-processed, subsequent build system operations
+  such as Fortran 9X interface block generation and dependency scan (for
+  creating the <em>Makefile</em>) will be based on the pre-processed source,
+  and not the original source file. If a source file requires pre-processing
+  and is not pre-processed at the pre-processing stage, it will be left to the
+  compiler to perform the task.</p>
+
+  <h2><a name="file-type">File Type Register</a></h2>
+
+  <p>The build system file type register is a simple interface for modifying
+  the default settings in the Fcm::Config module. There are two registers, one
+  for output file type and one for input file type.</p>
+
+  <p>The output file register is the simpler of the two. It is implemented as
+  a hash table, with the keys being the names of the file types as known by the
+  system internally, and the values being the suffices that will be added to
+  those output files. Therefore, the output file register allows us to modify
+  the suffix added to an output file of a particular type.</p>
+
+  <p>The input file register allows us to modify the type flags of a file
+  named with a particular extension. The type flags are keywords used by the
+  build system to determine what type of input files it is dealing with. It is
+  implemented as a list of uppercase keywords delimited by a pair of colons.
+  The order of the keywords in the string is insignificant. Internally, the
+  build system determines the action on a file by looking at whether it
+  belongs to a type that is tied with that particular action. For example, a
+  file that has the keyword "SOURCE" in its type flag will be treated as a
+  compilable source file, and so it will be written to the <em>Makefile</em>
+  with a rule to compile it.</p>
+
+  <h2><a name="makefile">The <em>Makefile</em></a></h2>
+
+  <p>The following items are automatically written to the <em>Makefile</em>:</p>
+
+  <ul>
+    <li>The root directory and sub-directories of the current build, as
+    environment variables FCM_ROOTDIR, etc.</li>
+
+    <li>The search path of the different types of output file, using a set of
+    "vpath" directives.</li>
+
+    <li>TOOL declarations in the build configuration file are exported as
+    environment variables.</li>
+
+    <li>The diagnostic verbose mode information.</li>
+
+    <li>The default build targets.</li>
+
+    <li>The rules for building the targets for all the source files.</li>
+  </ul>
+
+  <h2><a name="wrapper">The Compiler/Linker Wrapper</a></h2>
+
+  <p>Compile and link are handled by the <em>fcm_internal</em> wrapper script.
+  The wrapper script uses the environment variables exported by the
+  <em>Makefile</em> to generate the correct compiler (or linker) command for the
+  current source (or object) file. Depending on the diagnistic verbose level,
+  it also prints out various amount of diagnostic output.</p>
+
+  <p>For compilation, the wrapper does the following:</p>
+
+  <ol>
+    <li>Select the correct compiler for the current source file.</li>
+
+    <li>Specify the output file name for the current source file.</li>
+
+    <li>If pre-processing is left to the compiler, specify the definition
+    macros, if any, for the pre-processor.</li>
+
+    <li>Specify the "include" path, in case the source file has dependencies
+    on include files.</li>
+
+    <li>Specify the "compile only" option, if it is not already set.</li>
+
+    <li>Add any other user defined flags to the compiler command.</li>
+
+    <li>Run the command, sending the output to a temporary directory.</li>
+
+    <li>If the compile succeeded, move the output from the temporary directory
+    to the output object directory.</li>
+
+    <li>Otherwise, delete the output from the temporary directory.</li>
+
+    <li>If there are Fortran module definition files (*.mod, *.MOD, etc), move
+    them to the "inc/" sub-directory.</li>
+  </ol>
+
+  <p>For linking, the wrapper does the following:</p>
+
+  <ol>
+    <li>Create a temporary object archive library with all the object files
+    currently residing in the output object sub-directory.</li>
+
+    <li>Select the correct linker for the current main program object
+    file.</li>
+
+    <li>Specify the output file name for the main program.</li>
+
+    <li>Specify the main program object file.</li>
+
+    <li>Specify the link library search path and the temporary link
+    library.</li>
+
+    <li>Add any other user defined flags to the linker command.</li>
+
+    <li>Run the command, sending the output to a temporary directory.</li>
+
+    <li>If the link succeeded, move the output from the temporary directory to
+    the "bin/" sub-directory of the build root.</li>
+
+    <li>Otherwise, delete the output from the temporary directory.</li>
+
+    <li>Remove the temporary object archive library.</li>
+  </ol>
+
+  <h2><a name="inheritance">Inheriting from a Pre-compiled Build</a></h2>
+
+  <p>A build can inherit configurations, source files and other items from a
+  previous build. At the Perl source code level, this is implemented via hash
+  tables and search paths. At the <em>Makefile</em> level, this is implemented
+  using the "vpath" directives. The following is a summary:</p>
+
+  <ul>
+    <li>Build targets are stored in a list. Targets that are specified in the
+    configuration file in the previous build are pushed into the list first.
+    A target that is specified in the current configuration file is pushed
+    into the list if it has not already been specified.</li>
+
+    <li>Each source directory has a unique sub-package identifier and a path
+    location. If a source directory in the previous build has the same
+    sub-package identifier, its location as specified in the previous build
+    will be placed in the search path of the source directory. The directory
+    specified in the current build is searched for files before the directory
+    specified in the previous build.</li>
+
+    <li>Tool settings such as compiler flags are set via the configuration
+    hash table. Settings declared in the previous build overrides those of the
+    default, and settings declared in the current build overrides those
+    declared in the previous build.</li>
+
+    <li>Ditto for exclude dependency, input file extension and output file
+    extension declarations.</li>
+
+    <li>Build items such as object files, executable files and other dummy
+    files are inherited via search path (and/or "vpath"). For example, the
+    system searches the "obj/" sub-directory of the current build for object
+    files before looking at that of the previous build. The system does not
+    re-build an item that exists in the previous build and is up to date.</li>
+  </ul>
+  
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/design/code_management.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/design/code_management.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/design/code_management.html	(revision 1665)
@@ -0,0 +1,56 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM Detailed Design: Code Management System</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content=
+  "FCM Detailed Design: Code Management System">
+  <meta name="keywords" content="FCM, design">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM Detailed Design</a> &gt; Code Management System
+  </address>
+
+  <h1>Code Management System</h1>
+
+  <p>The code management commands provided by FCM are generally wrappers around
+  the underlying Subversion commands intended to add functionality or make the
+  system easier to use. Most of the wrappers are very simple and you can find
+  all the information you need from the <a href=
+  "../user_guide/command_ref.html">command reference section</a> of the FCM
+  User Guide and from the source code (which all resides within the Perl
+  package <a href=
+  "http://www-nwp/~fcm/FCM/src/lib/Fcm/Cm.pm"><em>Fcm::Cm</em></a>.
+  This section describes the few areas which merit further discussion.</p>
+
+  <h2><a name="prompts">Interactive Prompts</a></h2>
+
+  <p>Several of the commands prompt for further information interactively. This
+  is done using the function "&amp;main::get_input". This allows a different
+  version of the function to be used depending on the calling program. When
+  called by the main <tt>fcm</tt> script this function simply prompts for
+  information on the command line. However, when called from
+  <tt>fcm_gui_internal</tt> (which runs commands within the GUI) this function
+  uses a dialog box generated using Perl-Tk.</p>
+
+  <p>This design ensures that the main <tt>fcm</tt> command has no dependency
+  on the Perl <em>Tk</em> module.</p>
+
+  <h2><a name="merge">Merging</a></h2>
+
+  <p><em>Explain the logic used in determining the base path and
+  revision.</em></p>
+
+  <h2><a name="gui">GUI</a></h2>
+
+  <p><em>Anything needed here?</em></p>
+  
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/design/extract.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/design/extract.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/design/extract.html	(revision 1665)
@@ -0,0 +1,388 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM Detailed Design: Extract System</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="FCM Detailed Design: Extract System">
+  <meta name="keywords" content="FCM, design">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM Detailed Design</a> &gt; Extract System
+  </address>
+
+  <h1>Extract System</h1>
+  
+  <p>In this chapter, we shall discuss in detail the design of the extract
+  system. For information of how to use the extract system, please see: <a
+  href="../user_guide/extract.html">FCM System User Guide &gt; The Extract
+  System</a>.</p>
+
+  <p>The extract system extracts source directories from different branches of
+  Subversion repositories, combining them with source directories from the
+  local file system to give a source directory tree suitable for feeding into
+  the build system. The system is written in a set of Perl modules. The extract
+  system uses a similar interface to the build system. It shares the same
+  command line interface and many other utilities with the code management
+  system and the build system.</p>
+
+  <h2><a name="io">Input and Output</a></h2>
+
+  <p>The extract system should provide the following outputs:</p>
+
+  <ul class="pad">
+    <li>a directory tree with the extracted source code suitable for feeding
+    into the build system.</li>
+
+    <li>a configuration file for the build system.</li>
+
+    <li>an expanded version of the current configuration file, so that the
+    current extraction can be re-used.</li>
+  </ul>
+
+  <p>The following inputs are required by the extract system:</p>
+
+  <ul class="pad">
+    <li>the location of the destination.</li>
+
+    <li>the location of the source, e.g a repository URL or a local file
+    system path.</li>
+
+    <li>the revision of the source, if applicable.</li>
+
+    <li>extra configuration settings to be exported to the build system.</li>
+
+    <li>the location of previous extractions, if the current extract is to be
+    based on them.</li>
+  </ul>
+
+  <h2><a name="component">Components</a></h2>
+
+  <p>The extract system uses the following commands, modules and tools:</p>
+
+  <table class="pad" summary="build system components" border="1">
+    <tr>
+      <th>Name</th>
+
+      <th>Category</th>
+
+      <th>Description</th>
+    </tr>
+
+    <tr>
+      <th>fcm</th>
+
+      <td>Perl executable</td>
+
+      <td>Top level command line interface of the FCM system.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::CfgFile</th>
+
+      <td>Perl module</td>
+
+      <td>A class for reading from and writing to configuration files.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::Config</th>
+
+      <td>Perl module</td>
+
+      <td>A class that contains the configuration settings shared by all
+      FCM components.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::Extract</th>
+
+      <td>Perl module</td>
+
+      <td>Main class that controls the running of the extract system.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::ReposBranch</th>
+
+      <td>Perl module</td>
+
+      <td>A class that stores and processes information of a repository
+      branch.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::SrcDirLayer</th>
+
+      <td>Perl module</td>
+
+      <td>A class that stores and processes information of a "layer" in the
+      extraction sequence of a source directory.</td>
+    </tr>
+
+    <tr>
+      <th>Fcm::Util</th>
+
+      <td>Perl module</td>
+
+      <td>A collection of utilities shared by all FCM components.</td>
+    </tr>
+
+    <tr>
+      <th>svn</th>
+
+      <td>Subversion client</td>
+
+      <td>The following sub-commands are used: "info", "list", "export" and
+      "cat".</td>
+    </tr>
+
+    <tr>
+      <th>ksh</th>
+
+      <td>Unix shell</td>
+
+      <td>The following shell commands are used: "cp", "rm" and "mkdir".</td>
+    </tr>
+
+    <tr>
+      <th>rdist</th>
+
+      <td>Unix utility</td>
+
+      <td>A remote distribution tool for mirror the extracted source
+      directory to a remote host.</td>
+    </tr>
+
+    <tr>
+      <th>rsync</th>
+
+      <td>Unix utility</td>
+
+      <td>A remote synchronisation tool for mirror the extracted source
+      directory to a remote host.</td>
+    </tr>
+
+    <tr>
+      <th>remsh</th>
+
+      <td>Unix command</td>
+
+      <td>A command to invoke a shell on a remote host.</td>
+    </tr>
+  </table>
+
+  <h2><a name="task">Task</a></h2>
+  
+  <p>To do its job, the extract system executes the following tasks in
+  order:</p>
+
+  <ul class="pad">
+    <li>parse/decipher the extract configuration file.</li>
+
+    <li>establish the extraction sequence when dealing with extraction of
+    multiple branches of the same package.</li>
+
+    <li>extract or copy individual files from the source to the
+    destination.</li>
+
+    <li>generate of an expanded extraction configuration file to allow another
+    extraction to be based on the current one.</li>
+
+    <li>generate of a build configuration file.</li>
+
+    <li>mirror extracted source code and configuration files to a remote build
+    machine.</li>
+  </ul>
+
+  <h3><a name="task_cfg">The extract configuration</a></h3>
+
+  <p>When we invoke the FCM command, it creates a new instance of Fcm::Config,
+  which reads, processes and stores information from the central and user
+  configuration file. Configuration settings in Fcm::Config are then
+  accessible by all other modules used by the extract system.</p> 
+
+  <p>When we invoke the extract command, it creates a new instance of
+  Fcm::Extract, which automatically creates a new instance of the
+  Fcm::CfgFile. If an argument is specified in the command line, the argument
+  is used as the "basis". Otherwise, the current working directory is taken as
+  the basis. If the basis is a directory, Fcm::CfgFile will attempt to locate
+  a file called "ext.cfg" under this directory. If such a file is not found,
+  it will attempt to locate it under "cfg/ext.cfg". If the basis is a regular
+  file, the file itself is used.</p>
+  
+  <p>Once a file is located, Fcm::CfgFile will attempt to parse it. This is
+  done by reading and processing each line of the configuration file into
+  separate label, value and comment fields. If an INC declaration is
+  encountered, a new instance of Fcm::CfgFile is created to read the included
+  file as specified. The included lines are then added to the current array.
+  Each line is then pushed into an array that can be fetched as a property of
+  Fcm::CfgFile. Internally, each line is recorded as a reference to a hash
+  table with the following keys:</p>
+
+  <ul class="pad">
+    <li>LABEL: the label of a declaration.</li>
+
+    <li>VALUE: the value of a declaration.</li>
+
+    <li>COMMENT: the comment following a declaration or the comment in a
+    comment line.</li>
+
+    <li>NUMBER: the line number of the current line in the source file.</li>
+
+    <li>SRC: the name of the source file.</li>
+  </ul>
+  
+  <p>The information given by each line is "deciphered" by Fcm::Extract. The
+  information is processed in the following ways:</p>
+
+  <ul class="pad">
+    <li>The configuration file type and version declarations are stored as
+    properties of the Fcm::CfgFile instance. Fcm::Extract uses the
+    information to ensure that it is reading an extract configuration
+    file.</li>
+
+    <li>The destination directory declarations are stored in a hash table,
+    which is a property of the Fcm::Extract instance.</li>
+
+    <li>The remote destionation machine, logname and directory declarations
+    are stored in a hash table, which is another property of the Fcm::Extract
+    instance.</li>
+
+    <li>Build configuration declarations are stored in a hash table, which is
+    yet another property of the Fcm::Extract instance.</li>
+
+    <li>For each declaration of a repository branch, a new instance of
+    Fcm::ReposBranch is created, if it does not already exist. (A
+    Fcm::ReposBranch instance is identified by a "tag" property, which is the
+    combination of its package name and its branch name.) The REPOS, VERSION,
+    SRC and EXPSRC declarations set the "repos", "version", "dir" and "expdir"
+    properties of the Fcm::ReposBranch instance.</li>
+
+    <li>The override mode flag is stored as a property of the Fcm::Extract
+    instance.</li>
+
+    <li>For each declaration to USE a previous extract, a new instance of
+    Fcm::Extract is created, with its "extracted" property set to true. The
+    instance Fcm::Extract for the previous extraction creates a new instance of
+    Fcm::CfgFile for its configuration file. The configuration of the previous
+    extract is read and processed similarly to what was described above. The
+    current instance of Fcm::Extract will then attempt to inherit the settings
+    of the previous extraction where appropriate. The instances of the
+    previous extractions are stored in an array, which can be fetched as a
+    property of the current Fcm::Extract instance.</li>
+
+    <li>The INC declaration is ignored, as it is already processed by
+    Fcm::CfgFile.</li>
+
+    <li>The MIRROR declaration changes the setting (TOOL, MIRROR) in the
+    Fcm::Config instance.</li>
+  </ul>
+
+  <p>If a full extraction is required, Fcm::Extract will attempt to remove any
+  sub-directories created by previous extractions in the same location.
+  Destination directories are (re-)created as they are required.</p>
+
+  <p>For each repository branch, if the REPOS declaration is a file system
+  path, the VERSION declaration will be set automatically to the word "USER".
+  If the REPOS declaration matches a FCM URL keyword pattern, it is expanded
+  to the full URL. If REPOS is not in the local file system and the VERSION
+  declaration is not a number, the system will attempt to convert the keyword
+  back to a number. If the keyword is "HEAD", the system will use <tt>"svn
+  info"</tt> to determine the revision number. Otherwise, it will attempt to
+  match the keyword with a pre-defined FCM revision keyword. If there are any
+  expanded source directory (EXPSRC) declarations, the system will use
+  <tt>"svn ls -R"</tt> to search recursively for all normal source directories
+  containing regular files. These directories are then added to the "dir"
+  property of the Fcm::ReposBranch instance.</p>
+
+  <h3><a name="task_seq">The extraction sequence</a></h3>
+
+  <p>In the next step, the extract system converts the information given in
+  the list of repository branches into a list of source directory sub-package.
+  Each source directory sub-package will have a destination and a "stack" of
+  extraction sequence. The sequence is basically a list for locating the
+  source directories in the repository branches. The order of the sequence is
+  based on the order in which a repository branch is declared. The logic has
+  already been discussed in the user guide.</p>
+
+  <p>The sequence is implemented by a list of Fcm::SrcDirLayer instances. For
+  each Fcm::SrcDirLayer instance in an extraction sequence of a source
+  directory, the system will attempt to find out its "last commit" revision,
+  using the <tt>"svn info"</tt> command on the particular revision on the
+  given URL. This information is normally cached in a file called ".config" in
+  the cache sub-directory of the extraction destination root. For an
+  incremental extraction, the system will consult the cache to obtain the list
+  of "last commit" revisions for the source directories, instead of having to
+  go through a large number of <tt>"svn info"</tt> commands again. The cache
+  file is read/written using a temporary instance of Fcm::CfgFile. The label
+  in each line consists of the package name of the sub-package, its URL and a
+  revision number. The corresponding value is the "last commit" revision at
+  the given revision number.</p>
+
+  <h3><a name="task_ext">The extraction</a></h3>
+
+  <p>With the extraction sequence in place for each source directory, the
+  extraction itself can now take place. There are two steps in this
+  process.</p>
+
+  <p>For each "layer" in the extraction sequence of each source directory, if
+  the "layer" contains a repository URL, the system extracts from that URL the
+  source directory and place the resulting source files in a cache. From the
+  cache sub-directory of the destination root, the cache for each source
+  directory is placed under a relative path that reflects the sub-package name
+  of the source directory. Underneath this path is a list of directories
+  with names reflecting the name of the branch and the "last commit"
+  revision, (separated by double underscore "__"). These are where the cache of
+  the source files for the "layers" of the source directory are placed.</p>
+
+  <p>It is also worth noting that source files from the local file system are
+  not cached. They will be taken directly from their locations.</p>
+
+  <p>Once we have the cached "layers" (or branches) of the source directories,
+  the system will select the source files from the correct cache before
+  updating the destinations. The logic of which has already been discussed in
+  the user guide.</p>
+
+  <p>At the end of this stage, we should have a directory tree in the
+  destination source sub-directory, with the relative paths to the extracted
+  files reflecting the sub-package names of those files.</p>
+
+  <h3><a name="task_gen">The extract/build configuration generator</a></h3>
+
+  <p>If extraction completes without any error, the system will attempt to
+  write an expanded extract configuration file, where all revision keywords
+  are expanded into numbers, and all source directory packages are declared.
+  Subsequent dependent extractions will be able to re-use this configuration
+  without having to invoke the Subversion client for repository and revision
+  information.</p>
+
+  <p>The system will also attempt to produce a build configuration file for
+  feeding to the build system. The following "conversions" are performed:</p>
+
+  <ul>
+    <li>The destination root becomes the build root.</li>
+
+    <li>The destination directories are all are declared as the source
+    directories.</li>
+
+    <li>All BLD declarations are unchanged, except that the BLD prefixes are
+    removed from the label.</li>
+
+    <li>All USE extract configuration statements are converted to USE build
+    configuration statements.</li>
+  </ul>
+
+  <h3><a name="task_mir">The mirror interface</a></h3>
+
+  <p>The system uses "rdist" or "rsync" to mirror the extracted source code
+  and the generated configuration files to a remote machine.</p>
+  
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/design/index.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/design/index.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/design/index.html	(revision 1665)
@@ -0,0 +1,52 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM Detailed Design</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="FCM Detailed Design">
+  <meta name="keywords" content="FCM, design">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+  <img src="logo.png" alt="Met Office logo" align="right">
+  <br clear="right">
+
+  <h1>FCM Detailed Design</h1>
+
+  <p align="center">Last updated: 28 November 2006</a>
+
+  <p align="center">Met Office<br>
+  FitzRoy Road, Exeter<br>
+  Devon, EX1 3PB<br>
+  United Kingdom</p>
+
+  <p align="center">&copy; Crown Copyright 2005-6</p>
+
+  <p align="center">Questions regarding this document or permissions to quote
+  from it should be directed to the <a href=
+  "mailto:iprmanager@metoffice.gov.uk">IPR Manager</a>.</p>
+
+  <h2 align="center">Contents</h2>
+
+  <ol>
+    <li><a href="introduction.html">Introduction</a></li>
+
+    <li>
+      <a href="code_management.html">Code Management System</a>
+    </li>
+
+    <li>
+      <a href="extract.html">Extract System</a>
+    </li>
+
+    <li>
+      <a href="build.html">Build System</a>
+    </li>
+
+  </ol>
+
+  <script type="text/javascript" src="maintain.js"></script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/design/introduction.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/design/introduction.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/design/introduction.html	(revision 1665)
@@ -0,0 +1,52 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM Detailed Design: Introduction</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="FCM Detailed Design: Introduction">
+  <meta name="keywords" content="FCM, design">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM Detailed Design</a> &gt; Introduction
+  </address>
+
+  <h1>Introduction</h1>
+
+  <p>This document contains the Detailed Design for the <em>Flexible
+  Configuration Management</em> system which is known as <em>FCM</em>.</p>
+
+  <p>A lot of information about the design of FCM can be found within:</p>
+
+  <ul class="pad">
+    <li>The <a href="../user_guide">FCM User Guide</a>. This contains all the
+    information which a user needs to know about FCM, including relevant
+    aspects of the design.</li>
+
+    <li>The FCM source code which is, we hope, well commented.</li>
+  </ul>
+
+  <p>Everything else which you might need to know about the design should be
+  described in the following sections. It includes higher level design
+  information not suited for inclusion in the source code but too detailed to
+  be included in the User Guide. It is intended for those who need to maintain
+  or develop the FCM system or simply for those who wish to obtain a deeper
+  understanding of how the system works. This document consists of the following
+  sections:</p>
+
+  <ul class="pad">
+    <li><a href="code_management.html">Code Management System</a></li>
+
+    <li><a href="extract.html">Extract System</a></li>
+
+    <li><a href="build.html">Build System</a></li>
+  </ul>
+  
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/design/logo.png
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/design/logo.png	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/design/logo.png	(revision 1665)
@@ -0,0 +1,1 @@
+link ../etc/logo.png
Index: LMDZ5/branches/testing/tools/fcm/doc/design/maintain.js
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/design/maintain.js	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/design/maintain.js	(revision 1665)
@@ -0,0 +1,1 @@
+link ../etc/maintain.js
Index: LMDZ5/branches/testing/tools/fcm/doc/design/style.css
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/design/style.css	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/design/style.css	(revision 1665)
@@ -0,0 +1,1 @@
+link ../etc/style.css
Index: LMDZ5/branches/testing/tools/fcm/doc/etc/maintain.js
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/etc/maintain.js	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/etc/maintain.js	(revision 1665)
@@ -0,0 +1,11 @@
+// Display info about maintenance team
+
+// FCM contact URL
+var url     = 'http://www.metoffice.gov.uk/research/nwp/external/fcm/'
+var contact = '<a href="' + url + '">the FCM team</a>'
+
+// Output string 
+var out     = '<p></p><hr><address>Maintained by ' + contact + '.</address>'
+
+// Write to document
+document.write (out)
Index: LMDZ5/branches/testing/tools/fcm/doc/etc/style.css
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/etc/style.css	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/etc/style.css	(revision 1665)
@@ -0,0 +1,146 @@
+/* New stylesheet for FCM - created by Jim Bolton, 18 April 2005
+   Needs to be reviewed. */
+
+body {
+  background-color: #ffffcc;
+  color: black;
+  font-family: Arial, Helvetica, sans-serif;
+  font-size: 12pt;
+}
+h1 {
+  background-color: #ccccff;
+  color: navy;
+  font-size: 200%;
+  font-weight: bold;
+  text-align: center;
+  padding: 20px;
+}
+h2 {
+  background-color: #ccccff;
+  color: navy;
+  font-size: 175%;
+  font-weight: bold;
+  padding: 15px;
+}
+h3 {
+  background-color: #ccccff;
+  color: #40668c;
+  font-size: 150%;
+  font-weight: bold;
+  padding: 10px;
+}
+h4 {
+  color: #40668c;
+  font-size: medium;
+  font-weight: bold;
+}
+h5 {
+  background-color: #ccccff;
+  color: #40668c;
+  font-size: medium;
+  font-weight: bold;
+}
+table {
+  margin-top: 5px;
+  margin-bottom: 10px;
+}
+
+table.head {
+  background-color: #ccccff;
+  color: navy;
+  font-size: 200%;
+  font-weight: bold;
+  text-align: center;
+  padding: 20px;
+}
+
+table.foot {
+  background-color: #ccccff;
+  padding: 5px;
+}
+
+th {
+  background-color: #ccccff;
+}
+
+td {
+  background-color: transparent;
+}
+
+ol li {
+  margin: 5px;
+}
+
+ul.contents {
+  margin-bottom: 5px;
+  list-style-type: none;
+}
+
+img {
+  margin: 5px;
+}
+
+:link {
+  color: blue;
+  text-decoration: underline;
+}
+
+:visited {
+  color: purple;
+  text-decoration: none;
+}
+
+:active, :hover {
+  color: blue;
+  text-decoration: underline;
+}
+
+address {
+  text-align: right;
+  font-size: small;
+  font-style: normal;
+}
+
+em {
+  font-style: italic;
+}
+
+strong {
+  font-weight: bold;
+}
+
+code {
+  font-family: "Courier New", Courier, monospace;
+}
+
+pre {
+  background-color: #ffffcc;
+  font-family: "Courier New", Courier, monospace;
+  padding: 10px;
+}
+
+div.yell {
+  background-color: #ffffcc;
+  padding: 5px;
+}
+
+p.image {
+  text-align: center;
+  font-weight: bold;
+}
+
+div.yell td {
+  background-color: #ffffcc;
+}
+
+.pad th, .pad td, .pad li {
+  padding: 5px;
+}
+
+.gray {
+  color: gray;
+}
+
+.mono {
+  font-family: "Courier New", Courier, monospace;
+}
Index: LMDZ5/branches/testing/tools/fcm/doc/etc/style.html2ps.css
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/etc/style.html2ps.css	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/etc/style.html2ps.css	(revision 1665)
@@ -0,0 +1,29 @@
+/* Configuration file for html2ps on the FCM user guide */
+
+h1 {
+  color: navy;
+  text-align: center;
+}
+
+h2 {
+  color: navy;
+}
+
+h3 {
+  color: #40668c;
+}
+
+h4 {
+  font-size: 12pt;
+}
+
+a:link {
+  color: blue;
+}
+
+@page {
+  margin-left: 2cm;
+  margin-right: 2cm;
+  margin-top: 2cm;
+  margin-bottom: 2cm;
+}
Index: LMDZ5/branches/testing/tools/fcm/doc/release_notes/1-1.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/release_notes/1-1.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/release_notes/1-1.html	(revision 1665)
@@ -0,0 +1,488 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM 1.1 Release Notes</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="FCM Release Notes">
+  <meta name="keywords" content="FCM, release">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <h1>FCM 1.1 Release Notes<br>
+  06 November 2006</h1>
+
+  <p>These are the release notes for FCM release 1.1. You can use this release
+  of FCM freely under the terms of the <a href="../../LICENSE.html">FCM
+  LICENSE</a>, which you should receive with this distribution. Release 1.1 is
+  the first external release of FCM. (Release 1.0, 30 November 2005, was an
+  internal Met Office release which marked the start of the main migration of
+  systems into FCM.)</p>
+
+  <p>FCM is maintained by the FCM team at the Met Office. Please feedback any
+  bug reports or feature requests to us by <a href=
+  "mailto:fcm-team@metoffice.gov.uk">e-mail</a>.</p>
+
+  <h2>Contents</h2>
+
+  <ul>
+    <li><a href="#new">What's New?</a></li>
+
+    <li><a href="#fix">Minor Enhancements &amp; Bug Fixes</a></li>
+
+    <li><a href="#req">System Requirements</a></li>
+
+    <li><a href="#ins">Installation</a></li>
+  </ul>
+
+  <h2><a name="new" id="new">What's New?</a></h2>
+
+  <p>Build system:</p>
+
+  <ul>
+    <li>Support building of Fortran <span class="mono">BLOCKDATA</span> program
+    units.</li>
+
+    <li>Option to generate Fortran interface files in lower case names after
+    their program units.</li>
+
+    <li>Allow renaming of main program targets using the build configuration
+    file.</li>
+
+    <li>The <span class="mono">fcm_env.ksh</span> file now provides an
+    environment variable for the <span class="mono">etc/</span> sub-directory
+    of the build which can be used if you are "building" data files.</li>
+
+    <li>The build root directory is now locked while a build is running. This
+    prevents multiple instances of build running in the same directory.
+    However, you can bypass the lock if you specify the new <span class=
+    "mono">--ignore-lock</span> option with <span class="mono">fcm
+    build</span>.</li>
+  </ul>
+
+  <p>Extract system:</p>
+
+  <ul>
+    <li>The destination root directory is now locked while an extract is
+    running. This prevents multiple instances of extract running in the same
+    directory. However, you can bypass the lock if you specify the new
+    <span class="mono">--ignore-lock</span> option with <span class="mono">fcm
+    extract</span>.</li>
+  </ul>
+
+  <p>Code management commands:</p>
+
+  <ul>
+    <li><span class="mono">fcm merge</span> now supports custom and reverse
+    modes.</li>
+
+    <li><span class="mono">fcm merge</span> now allows automatic merges in
+    sub-trees if it is safe.</li>
+
+    <li><span class="mono">fcm merge</span> now handles automatic merges from
+    sibling branches that are created at different revisions of the
+    parent.</li>
+
+    <li><span class="mono">fcm branch, fcm diff --branch</span> and
+    <span class="mono">fcm merge</span> can now handle creation, diff and
+    automatic merge of a branch of a branch.</li>
+
+    <li><span class="mono">fcm switch</span> is improved to allow safer
+    switches of your working copy to point to different branches in your
+    project.</li>
+
+    <li><span class="mono">fcm commit</span> now displays your location in the
+    branch, and extra warning when you are committing to the trunk of a
+    project.</li>
+
+    <li>New <span class="mono">fcm mkpatch</span> command.</li>
+  </ul>
+
+  <p>General:</p>
+
+  <ul>
+    <li>Error handling is improved.</li>
+
+    <li>The User Guide is now complete, with a much improved tutorial.</li>
+
+    <li>New document: Fortran coding standard for FCM.</li>
+  </ul>
+
+  <h2><a name="fix" id="fix">Minor Enhancements &amp; Bug Fixes</a></h2>
+
+  <p>Build system:</p>
+
+  <ul>
+    <li>Ignore empty Fortran source files, so that alternate sections can be
+    handled correctly.</li>
+
+    <li>Handle recursive header file dependency correctly in pre-processing
+    stage.</li>
+
+    <li>Identify changes in pre-processed source file, the pre-processor
+    options and "keys" correctly in incremental builds.</li>
+
+    <li>Improve speed of pre-processing in incremental builds by not performing
+    any unnecessary null-action pre-processing.</li>
+
+    <li>Load archiver no longer includes main program objects.</li>
+
+    <li>It is now possible for a sub-package to exclude particular types of
+    dependencies.</li>
+  </ul>
+
+  <p>Extract system:</p>
+
+  <ul>
+    <li>Sub-directories are now extracted with the non-recursive mode of
+    <span class="mono">svn export</span>.</li>
+
+    <li>Peg revisions should now be handled correctly in <span class=
+    "mono">INC</span> extract declarations.</li>
+
+    <li>The command should now fail if a declared source directory does not
+    exist or if the update of an extract destination fails.</li>
+  </ul>
+
+  <p>Code management commands:</p>
+
+  <ul>
+    <li><span class="mono">fcm branch --info</span> and <span class="mono">fcm
+    diff</span> can now take a <span class="mono">PATH</span> as an
+    argument.</li>
+
+    <li>The <span class="mono">--ticket</span> option of <span class="mono">fcm
+    branch --create</span> can now accept multiple tickets.</li>
+
+    <li><span class="mono">fcm branch --info</span> and <span class="mono">fcm
+    diff --branch</span> should now work correctly in a sub-tree of a
+    branch.</li>
+
+    <li><span class="mono">fcm branch --create</span> no longer offers to
+    checkout the branch.</li>
+
+    <li><span class="mono">fcm commit</span> no longer fails when adding a new
+    symbolic link.</li>
+
+    <li>The <span class="mono">--password</span> option is now supported by the
+    <span class="mono">fcm branch --create, fcm branch --delete, fcm
+    commit</span> and <span class="mono">fcm delete</span> commands.</li>
+
+    <li>Empty arguments to code management commands are now parsed
+    correctly.</li>
+
+    <li>The <span class="mono">fcm diff --graphical</span> option no longer
+    fails with binary files.</li>
+
+    <li>FCM will always set the environment variable <span class=
+    "mono">LANG=en_GB</span> before running Subversion commands. This prevents
+    failure of FCM when it attempts to parse output from Subversion commands
+    when a different <span class="mono">LANG</span> setting is used.</li>
+  </ul>
+
+  <p>General:</p>
+
+  <ul>
+    <li>Various other very minor enhancements and bug fixes.</li>
+  </ul>
+
+  <h2><a name="req" id="req">System Requirements</a></h2>
+
+  <h3><a name="req_perl" id="req_perl">Perl</a></h3>
+
+  <p>The core part of FCM is a set of Perl scripts and modules. For the build
+  system to work, you need the following modules installed:</p>
+
+  <ul>
+    <li class="mono">Carp</li>
+
+    <li class="mono">Cwd</li>
+
+    <li class="mono">File::Basename</li>
+
+    <li class="mono">File::Compare</li>
+
+    <li class="mono">File::Find</li>
+
+    <li class="mono">File::Path</li>
+
+    <li class="mono">File::Spec::Functions</li>
+
+    <li class="mono">File::Spec</li>
+
+    <li class="mono">FindBin</li>
+
+    <li class="mono">Getopt::Long</li>
+
+    <li class="mono">POSIX</li>
+  </ul>
+
+  <p>The code management commands and extract system need the following
+  additional modules installed:</p>
+
+  <ul>
+    <li class="mono">File::Temp</li>
+
+    <li class="mono">Getopt::Long</li>
+
+    <li class="mono">HTTP::Date</li>
+
+    <li class="mono">XML::DOM</li>
+  </ul>
+
+  <p>To use the simple GUI for some of the code management commands, you also
+  need the following modules:</p>
+
+  <ul>
+    <li class="mono">Tk::ROText</li>
+
+    <li class="mono">Tk</li>
+  </ul>
+
+  <p>At the Met Office we are currently using the complete FCM system with Perl
+  5.8.x. In addition the build system is being used with Perl 5.6.x.</p>
+
+  <h3><a name="req_svn" id="req_svn">Subversion</a></h3>
+
+  <p>To use the code management commands (and relevant parts of the extract
+  system) you need to have <a href=
+  "http://subversion.tigris.org/">Subversion</a> installed.</p>
+
+  <ul>
+    <li>FCM makes extensive use of peg revisions in both the code management
+    and extract systems. This requires Subversion 1.2.0.</li>
+
+    <li>At the Met Office we are currently using Subversion 1.3.2 (although
+    1.2.3 was used until very recently).</li>
+  </ul>
+
+  <p>Note that the extract system can mirror extracted code to a remote
+  platform for building. Therefore it is only necessary to have Subversion
+  installed on the platform where you do your code development. If you use
+  other platforms purely for building and running then you do not need to have
+  Subversion installed on these platforms.</p>
+
+  <h3><a name="req_trac" id="req_trac">Trac</a></h3>
+
+  <p>The use of <a href="http://projects.edgewall.com/trac/">Trac</a> is
+  entirely optional (although highly recommended if you are using Subversion).
+  At the Met Office we are currently using version 0.9.6.</p>
+
+  <h3><a name="req_other" id="req_other">Other Requirements</a></h3>
+
+  <p>The <tt>fcm diff --graphical</tt> and <tt>fcm conflicts</tt> commands
+  require <a href="http://furius.ca/xxdiff/">xxdiff</a>. At the Met Office we
+  are currently using version 3.1.</p>
+
+  <p>The build system requires <a href=
+  "http://www.gnu.org/software/make/make.html">GNU make</a>. At the Met Office
+  we are currently using version 3.79.x and 3.80.</p>
+
+  <p>Optionally, the build system can use <a href=
+  "http://www.ifremer.fr/ditigo/molagnon/fortran90">f90aib</a> to generate
+  interface files. However, there is also a built in Perl based interface file
+  generator which is quicker and better in most cases so you are unlikely to
+  need f90aib unless you hit a problem with some particular code.</p>
+
+  <p>FCM is intended to run on a Unix/Linux system. It is currently used at the
+  Met Office on Linux (Red Hat 9 and Red Hat Enterprise 2.1 and 4.4) and HP-UX
+  11.00.</p>
+
+  <h2><a name="ins" id="ins">Installation</a></h2>
+
+  <p>FCM is distributed in the form of a compressed tar file. Un-pack the tar
+  file into an appropriate location on your system. Then add the <tt>bin</tt>
+  directory into your PATH. Once you have done this you should now have full
+  access to the FCM system, assuming that you have met the requirements
+  described in the previous section.</p>
+
+  <p>If you wish to define keywords for your systems you will need to create a
+  file <tt>etc/fcm.cfg</tt>. An example file, <tt>fcm.cfg.eg</tt>, is provided
+  which is a copy of the file currently used at the Met Office. For further
+  details please refer to the section <a href=
+  "../user_guide/system_admin.html#fcm-keywords">FCM keywords</a> in the System
+  Admin chapter of the User Guide.</p>
+
+  <p>The <tt>doc</tt> directory contains all the system documentation.</p>
+
+  <ul>
+    <li><tt>doc/release_notes</tt> contains these release notes. It also
+    contains the release notes for all previous versions which may be useful if
+    you have skipped any versions.</li>
+
+    <li><tt>doc/user_guide</tt> contains the FCM User Guide in both <a href=
+    "../user_guide/index.html">HTML</a> and <a href=
+    "../user_guide/fcm-user-guide.pdf">PDF</a> form.</li>
+
+    <li><tt>doc/design</tt> contains the <a href="../design/index.html">FCM
+    Detailed Design</a> document (currently in draft form).</li>
+
+    <li><tt>doc/standards</tt> contains the FCM <a href=
+    "../standards/perl_standard.html">Perl</a> and <a href=
+    "../standards/fortran_standard.html">Fortran</a> coding standards. The Perl
+    standard describes the standards followed by the FCM code. The Fortran
+    standard contains some <a href=
+    "../standards/fortran_standard.html#fcm">specific advice</a> on the best
+    way of writing Fortran code for use with FCM as well as more general advice
+    on good practise.</li>
+  </ul>
+
+  <p>The <tt>tutorial</tt> directory contains the files necessary to set up a
+  tutorial repository. This will allow you to follow the <a href=
+  "../user_guide/getting_started.html#tutorial">tutorial section</a> in the
+  User Guide.</p>
+
+  <ul>
+    <li>The file <tt>tutorial/repos/tutorial.dump</tt> should be loaded into an
+    empty repository using the <tt>svnadmin load</tt> command.</li>
+
+    <li>The hook scripts in <tt>tutorial/hook</tt> should then be installed in
+    this repository in order to prevent any commits to the trunk. Note that the
+    configuration file <tt>svnperms.conf</tt> assumes that the tutorial
+    repository is called <tt>tutorial_svn</tt>. Please edit this file if you
+    use a different name.</li>
+
+    <li>The repository should be configured to allow users write access. You
+    may find it easiest to simply allow anonymous access.</li>
+
+    <li>A Trac system should be configured associated with the Tutorial
+    repository. You then need to allow users write access. You may find it
+    easiest to set up a number of guest accounts for this purpose.</li>
+  </ul>
+
+  <p>The <tt>templates</tt> directory contains various example scripts which
+  you may find useful. Note that these scripts are all specific to the Met
+  Office and may contain hard coded paths and email addresses. They are
+  provided in the hope that you may find them useful as templates for setting
+  up similar scripts of your own. However, they should only be used after
+  careful review to adapt them to your environment. The contents are as
+  follows:</p>
+
+  <table summary="list of template scripts" border="1" width="100%">
+    <tr>
+      <th>Script</th>
+
+      <th>Description</th>
+    </tr>
+
+    <tr>
+      <th>templates/hook/pre-commit</th>
+
+      <td>
+        This script restricts write-access to the repository by checking the
+        following:
+
+        <ul>
+          <li>It executes the Subversion utility <tt>svnperms.py</tt> if it
+          exists. This utility checks whether the author of the current
+          transaction has enough permission to write to particular paths in the
+          repository.</li>
+
+          <li>It checks the disk space required by the current transaction. It
+          fails the commit if it requires more than 5Mb of disk space.</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>templates/hook/post-commit</th>
+
+      <td>A simple post-commit hook script which runs the script
+      <tt>post-commit-background</tt> in the background.</td>
+    </tr>
+
+    <tr>
+      <th>templates/hook/post-commit-background</th>
+
+      <td>
+        This script runs in the background after each commit
+
+        <ul>
+          <li>It updates a <tt>&lt;repos&gt;.latest</tt> file with the latest
+          revision number.</li>
+
+          <li>It creates a dump of the new revision.</li>
+
+          <li>It calls the script <tt>background_updates.pl</tt> if it
+          exists.</li>
+        </ul>This script is installed as standard in all our repositories.
+      </td>
+    </tr>
+
+    <tr>
+      <th>templates/hook/background_updates.pl</th>
+
+      <td>An example of how you may want to set up a
+      <tt>background_updates.pl</tt> script to perform post-commit tasks for a
+      specific repository. This script uses a lock file to prevent multiple
+      commits in quick succession from causing problems.</td>
+    </tr>
+
+    <tr>
+      <th>templates/hook/pre-revprop-change</th>
+
+      <td>A simple pre-revprop-change hook script which runs the script
+      <tt>pre-revprop-change.pl</tt>.</td>
+    </tr>
+
+    <tr>
+      <th>templates/hook/pre-revprop-change.pl</th>
+
+      <td>If a user attempts to modify the log message of a changeset and
+      he/she is not the original author of the changeset, this script will
+      e-mail the original author. You can also set up a watch facility to
+      monitor changes of log messages that affect particular paths in the
+      repository. For further details please refer to the section <a href=
+      "../user_guide/system_admin.html#svn_watch">Watching changes in log
+      messages</a> in the System Admin chapter of the User Guide.</td>
+    </tr>
+
+    <tr>
+      <th>templates/hook/post-revprop-change</th>
+
+      <td>A simple post-revprop-change hook script which runs the script
+      <tt>post-revprop-change.py</tt>.</td>
+    </tr>
+
+    <tr>
+      <th>templates/hook/post-revprop-change.py</th>
+
+      <td>This hook script updates the Trac SQLite database following a
+      successful change in the log message.</td>
+    </tr>
+
+    <tr>
+      <th>templates/utils/cron_template.ksh</th>
+
+      <td>An example of how you might set up a cron job to make use of the
+      <tt>&lt;repos&gt;.latest</tt> file.</td>
+    </tr>
+
+    <tr>
+      <th>templates/utils/daily_cron</th>
+
+      <td>The cron job which we run each night. It verifies and backs up each
+      of our repositories, housekeeps the revision dumps created by
+      <tt>post-commit-background</tt> and backs up each of our Trac systems. It
+      also handles the distribution of FCM to various platforms at the Met
+      Office.</td>
+    </tr>
+
+    <tr>
+      <th>templates/utils/fcm_add_trac.pl</th>
+
+      <td>This script sets up a new Trac system and applies some configuration
+      options which we use by default at the Met Office.</td>
+    </tr>
+
+    <tr>
+      <th>templates/utils/recover_svn.pl</th>
+
+      <td>This script allows us to recover all of our Subversion repositories
+      by using the nightly backups and the repository dumps.</td>
+    </tr>
+  </table>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/release_notes/1-2.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/release_notes/1-2.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/release_notes/1-2.html	(revision 1665)
@@ -0,0 +1,402 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM 1.2 Release Notes</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="FCM Release Notes">
+  <meta name="keywords" content="FCM, release">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <h1>FCM 1.2 Release Notes<br>
+  22 March 2007</h1>
+
+  <p>These are the release notes for FCM release 1.2. You can use this release
+  of FCM freely under the terms of the <a href="../../LICENSE.html">FCM
+  LICENSE</a>, which you should receive with this distribution.</p>
+
+  <p>FCM is maintained by the FCM team at the Met Office. Please feedback any
+  bug reports or feature requests to us by <a href=
+  "mailto:fcm-team@metoffice.gov.uk">e-mail</a>.</p>
+
+  <h2>Contents</h2>
+
+  <ul>
+    <li><a href="#new">What's New?</a></li>
+
+    <li><a href="#fix">Minor enhancements &amp; Bug Fixes</a></li>
+
+    <li><a href="#req">System Requirements</a></li>
+
+    <li><a href="#ins">Installation</a></li>
+  </ul>
+
+  <h2><a name="new" id="new">What's New?</a></h2>
+
+  <p>Code management commands:</p>
+
+  <ul>
+    <li>New options <tt>--trac</tt> and <tt>--wiki</tt> for <tt>fcm diff
+    --branch</tt>.</li>
+
+    <li>Allow other graphical diff tools to be used in place of <em>xxdiff</em>.
+    </li>
+  </ul>
+
+  <p>General:</p>
+
+  <ul>
+    <li>New document <em>External Distribution &amp; Collaboration for FCM
+    Projects</em>.</li>
+  </ul>
+
+  <h2><a name="fix" id="fix">Minor enhancements &amp; Bug Fixes</a></h2>
+
+  <p>Build system:</p>
+
+  <ul>
+    <li>Extra warnings when multiple targets are detected in the source
+    tree.</li>
+
+    <li>Improved the patterns for detecting <em>recursive</em>, <em>pure</em>
+    and <em>elemental</em> Fortran subroutines and functions.</li>
+  </ul>
+
+  <p>Code management commands:</p>
+
+  <ul>
+    <li><tt>fcm branch --list</tt> now prints the branches using FCM URL
+    keywords by default. Use the <tt>--verbose</tt> option to print branches
+    in full Subversion URLs.</li>
+  </ul>
+
+  <p>General:</p>
+
+  <ul>
+    <li>Enhanced <tt>fcm cmp-ext-cfg</tt> to link to tickets.</li>
+
+    <li>Improved handling of FCM URL keywords. The <tt>SET::REPOS</tt>
+    declaration in the central/user configuration file is deprecated in favour
+    of <tt>SET::URL</tt>. The keyword of the project with the standard suffices
+    (<tt>_tr</tt> or <tt>-tr</tt> for "trunk", <tt>_br</tt> or <tt>-br</tt> for
+    "branches", and <tt>_tg</tt> or <tt>-tg</tt> for "tags") are recognised
+    automatically.</li>
+
+    <li>Fix: full extract/build should no longer delete one another's cache if
+    they are run in the same directory.</li>
+
+    <li>Various other very minor enhancements and bug fixes.</li>
+  </ul>
+
+  <h2><a name="req" id="req">System Requirements</a></h2>
+
+  <h3><a name="req_perl" id="req_perl">Perl</a></h3>
+
+  <p>The core part of FCM is a set of Perl scripts and modules. For the build
+  system to work, you need the following modules installed:</p>
+
+  <ul>
+    <li class="mono">Carp</li>
+
+    <li class="mono">Cwd</li>
+
+    <li class="mono">File::Basename</li>
+
+    <li class="mono">File::Compare</li>
+
+    <li class="mono">File::Find</li>
+
+    <li class="mono">File::Path</li>
+
+    <li class="mono">File::Spec::Functions</li>
+
+    <li class="mono">File::Spec</li>
+
+    <li class="mono">FindBin</li>
+
+    <li class="mono">Getopt::Long</li>
+
+    <li class="mono">POSIX</li>
+  </ul>
+
+  <p>The code management commands and extract system need the following
+  additional modules installed:</p>
+
+  <ul>
+    <li class="mono">File::Temp</li>
+
+    <li class="mono">Getopt::Long</li>
+
+    <li class="mono">HTTP::Date</li>
+
+    <li class="mono">XML::DOM</li>
+  </ul>
+
+  <p>To use the simple GUI for some of the code management commands, you also
+  need the following modules:</p>
+
+  <ul>
+    <li class="mono">Tk::ROText</li>
+
+    <li class="mono">Tk</li>
+  </ul>
+
+  <p>At the Met Office we are currently using the complete FCM system with Perl
+  5.8.x. In addition the build system is being used with Perl 5.6.x.</p>
+
+  <h3><a name="req_svn" id="req_svn">Subversion</a></h3>
+
+  <p>To use the code management commands (and relevant parts of the extract
+  system) you need to have <a href=
+  "http://subversion.tigris.org/">Subversion</a> installed.</p>
+
+  <ul>
+    <li>FCM makes extensive use of peg revisions in both the code management
+    and extract systems. This requires Subversion 1.2.0.</li>
+
+    <li>At the Met Office we are currently using Subversion 1.3.2.</li>
+  </ul>
+
+  <p>Note that the extract system can mirror extracted code to a remote
+  platform for building. Therefore it is only necessary to have Subversion
+  installed on the platform where you do your code development. If you use
+  other platforms purely for building and running then you do not need to have
+  Subversion installed on these platforms.</p>
+
+  <h3><a name="req_trac" id="req_trac">Trac</a></h3>
+
+  <p>The use of <a href="http://projects.edgewall.com/trac/">Trac</a> is
+  entirely optional (although highly recommended if you are using Subversion).
+  </p>
+
+  <ul>
+    <li>The <tt>--trac</tt> and <tt>--wiki</tt> options to the <tt>fcm diff
+    --branch</tt> command allow you to view branch differences using Trac. This
+    requires Trac 0.10.</li>
+
+    <li>At the Met Office we are currently using Trac 0.10.3.</li>
+  </ul>
+
+  <h3><a name="req_other" id="req_other">Other Requirements</a></h3>
+
+  <p>The <tt>fcm conflicts</tt> command requires <a href=
+  "http://furius.ca/xxdiff/">xxdiff</a>. At the Met Office we are currently
+  using version 3.1. The <tt>fcm diff --graphical</tt> command also uses xxdiff
+  by default although other graphical diff tools can also be used.</p>
+
+  <p>The build system requires <a href=
+  "http://www.gnu.org/software/make/make.html">GNU make</a>. At the Met Office
+  we are currently using version 3.79.x and 3.80.</p>
+
+  <p>Optionally, the build system can use <a href=
+  "http://www.ifremer.fr/ditigo/molagnon/fortran90">f90aib</a> to generate
+  interface files. However, there is also a built in Perl based interface file
+  generator which is quicker and better in most cases so you are unlikely to
+  need f90aib unless you hit a problem with some particular code.</p>
+
+  <p>FCM is intended to run on a Unix/Linux system. It is currently used at the
+  Met Office on Linux (Red Hat Enterprise 2.1 and 4.4) and HP-UX 11.00.</p>
+
+  <h2><a name="ins" id="ins">Installation</a></h2>
+
+  <p>FCM is distributed in the form of a compressed tar file. Un-pack the tar
+  file into an appropriate location on your system. Then add the <tt>bin</tt>
+  directory into your PATH. Once you have done this you should now have full
+  access to the FCM system, assuming that you have met the requirements
+  described in the previous section.</p>
+
+  <p>If you wish to define keywords for your systems you will need to create a
+  file <tt>etc/fcm.cfg</tt>. An example file, <tt>fcm.cfg.eg</tt>, is provided
+  which is a copy of the file currently used at the Met Office. For further
+  details please refer to the section <a href=
+  "../user_guide/system_admin.html#fcm-keywords">FCM keywords</a> in the System
+  Admin chapter of the User Guide.</p>
+
+  <p>The <tt>doc</tt> directory contains all the system documentation.</p>
+
+  <ul>
+    <li><tt>doc/release_notes</tt> contains these release notes. It also
+    contains the release notes for all previous versions which may be useful if
+    you have skipped any versions.</li>
+
+    <li><tt>doc/user_guide</tt> contains the <a href="../user_guide/index.html">
+    FCM User Guide</a>.</li>
+
+    <li><tt>doc/design</tt> contains the <a href="../design/index.html">FCM
+    Detailed Design</a> document (currently in draft form).</li>
+
+    <li><tt>doc/standards</tt> contains the FCM <a href=
+    "../standards/perl_standard.html">Perl</a> and <a href=
+    "../standards/fortran_standard.html">Fortran</a> coding standards. The Perl
+    standard describes the standards followed by the FCM code. The Fortran
+    standard contains some <a href=
+    "../standards/fortran_standard.html#fcm">specific advice</a> on the best
+    way of writing Fortran code for use with FCM as well as more general advice
+    on good practise.</li>
+
+    <li><tt>doc/collaboration</tt> contains the <a href=
+    "../collaboration/index.html">External Distribution &amp; Collaboration for
+    FCM Projects</a> document which discusses how projects configured under FCM
+    can be distributed externally.</li>
+  </ul>
+
+  <p>The <tt>tutorial</tt> directory contains the files necessary to set up a
+  tutorial repository. This will allow you to follow the <a href=
+  "../user_guide/getting_started.html#tutorial">tutorial section</a> in the
+  User Guide.</p>
+
+  <ul>
+    <li>The file <tt>tutorial/repos/tutorial.dump</tt> should be loaded into an
+    empty repository using the <tt>svnadmin load</tt> command.</li>
+
+    <li>The hook scripts in <tt>tutorial/hook</tt> should then be installed in
+    this repository in order to prevent any commits to the trunk. Note that the
+    configuration file <tt>svnperms.conf</tt> assumes that the tutorial
+    repository is called <tt>tutorial_svn</tt>. Please edit this file if you
+    use a different name.</li>
+
+    <li>The repository should be configured to allow users write access. You
+    may find it easiest to simply allow anonymous access.</li>
+
+    <li>A Trac system should be configured associated with the Tutorial
+    repository. You then need to allow users write access. You may find it
+    easiest to set up a number of guest accounts for this purpose.</li>
+  </ul>
+
+  <p>The <tt>templates</tt> directory contains various example scripts which
+  you may find useful. Note that these scripts are all specific to the Met
+  Office and may contain hard coded paths and email addresses. They are
+  provided in the hope that you may find them useful as templates for setting
+  up similar scripts of your own. However, they should only be used after
+  careful review to adapt them to your environment. The contents are as
+  follows:</p>
+
+  <table summary="list of template scripts" border="1" width="100%">
+    <tr>
+      <th>Script</th>
+
+      <th>Description</th>
+    </tr>
+
+    <tr>
+      <th>templates/hook/pre-commit</th>
+
+      <td>
+        This script restricts write-access to the repository by checking the
+        following:
+
+        <ul>
+          <li>It executes the Subversion utility <tt>svnperms.py</tt> if it
+          exists. This utility checks whether the author of the current
+          transaction has enough permission to write to particular paths in the
+          repository.</li>
+
+          <li>It checks the disk space required by the current transaction. It
+          fails the commit if it requires more than 5Mb of disk space.</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>templates/hook/post-commit</th>
+
+      <td>A simple post-commit hook script which runs the script
+      <tt>post-commit-background</tt> in the background.</td>
+    </tr>
+
+    <tr>
+      <th>templates/hook/post-commit-background</th>
+
+      <td>
+        This script runs in the background after each commit
+
+        <ul>
+          <li>It updates a <tt>&lt;repos&gt;.latest</tt> file with the latest
+          revision number.</li>
+
+          <li>It creates a dump of the new revision.</li>
+
+          <li>It calls the script <tt>background_updates.pl</tt> if it
+          exists.</li>
+        </ul>This script is installed as standard in all our repositories.
+      </td>
+    </tr>
+
+    <tr>
+      <th>templates/hook/background_updates.pl</th>
+
+      <td>An example of how you may want to set up a
+      <tt>background_updates.pl</tt> script to perform post-commit tasks for a
+      specific repository. This script uses a lock file to prevent multiple
+      commits in quick succession from causing problems.</td>
+    </tr>
+
+    <tr>
+      <th>templates/hook/pre-revprop-change</th>
+
+      <td>A simple pre-revprop-change hook script which runs the script
+      <tt>pre-revprop-change.pl</tt>.</td>
+    </tr>
+
+    <tr>
+      <th>templates/hook/pre-revprop-change.pl</th>
+
+      <td>If a user attempts to modify the log message of a changeset and
+      he/she is not the original author of the changeset, this script will
+      e-mail the original author. You can also set up a watch facility to
+      monitor changes of log messages that affect particular paths in the
+      repository. For further details please refer to the section <a href=
+      "../user_guide/system_admin.html#svn_watch">Watching changes in log
+      messages</a> in the System Admin chapter of the User Guide.</td>
+    </tr>
+
+    <tr>
+      <th>templates/hook/post-revprop-change</th>
+
+      <td>A simple post-revprop-change hook script which runs the script
+      <tt>post-revprop-change.py</tt>.</td>
+    </tr>
+
+    <tr>
+      <th>templates/hook/post-revprop-change.py</th>
+
+      <td>This hook script updates the Trac SQLite database following a
+      successful change in the log message.</td>
+    </tr>
+
+    <tr>
+      <th>templates/utils/cron_template.ksh</th>
+
+      <td>An example of how you might set up a cron job to make use of the
+      <tt>&lt;repos&gt;.latest</tt> file.</td>
+    </tr>
+
+    <tr>
+      <th>templates/utils/daily_cron</th>
+
+      <td>The cron job which we run each night. It verifies and backs up each
+      of our repositories, housekeeps the revision dumps created by
+      <tt>post-commit-background</tt> and backs up each of our Trac systems. It
+      also handles the distribution of FCM to various platforms at the Met
+      Office.</td>
+    </tr>
+
+    <tr>
+      <th>templates/utils/fcm_add_trac.pl</th>
+
+      <td>This script sets up a new Trac system and applies some configuration
+      options which we use by default at the Met Office.</td>
+    </tr>
+
+    <tr>
+      <th>templates/utils/recover_svn.pl</th>
+
+      <td>This script allows us to recover all of our Subversion repositories
+      by using the nightly backups and the repository dumps.</td>
+    </tr>
+  </table>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/release_notes/maintain.js
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/release_notes/maintain.js	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/release_notes/maintain.js	(revision 1665)
@@ -0,0 +1,1 @@
+link ../etc/maintain.js
Index: LMDZ5/branches/testing/tools/fcm/doc/release_notes/style.css
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/release_notes/style.css	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/release_notes/style.css	(revision 1665)
@@ -0,0 +1,1 @@
+link ../etc/style.css
Index: LMDZ5/branches/testing/tools/fcm/doc/standards/fortran_standard.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/standards/fortran_standard.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/standards/fortran_standard.html	(revision 1665)
@@ -0,0 +1,1169 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>Fortran coding standard for FCM</title>
+  <meta name="author" content="FCM team">
+  <meta name="descriptions" content="Fortran coding standard for FCM">
+  <meta name="keywords" content="Fortran, coding standard, FCM">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="StyleSheet" type="text/css" href="style.css">
+  <style type="text/css">
+  <!--
+  li, th, td {
+    padding: 3px;
+  }
+  td {
+    vertical-align: top;
+  }
+  mono {
+    font-family: monospace;
+  }
+  -->
+  </style>
+</head>
+
+<body>
+  <p align="right"><img src="logo.png" alt="Met Office logo" width="85"
+  height="85"></p>
+
+  <h1>Fortran coding standard for FCM</h1>
+
+  <p align="center">Last updated: 28 November 2006</a>
+
+  <p align="center">Met Office<br>
+  FitzRoy Road, Exeter<br>
+  Devon, EX1 3PB<br>
+  United Kingdom</p>
+
+  <p align="center">&copy; Crown copyright 2006. All rights reserved.</p>
+
+  <p align="center">Questions regarding this document or permissions to quote
+  from it should be directed to the <a href=
+  "mailto:iprmanager@metoffice.gov.uk">IPR Manager</a>.</p>
+  
+  <script type="text/javascript">
+  <!--
+  var out = 'For printing, please use the '
+  out    += '<a href="fcm-fortran-standard.pdf">PDF<\/a> version of the document.'
+  document.write ('<p align="center">')
+  document.write (out)
+  document.write ('<\/p>')
+  //-->
+  </script>
+
+  <h2>Contents</h2>
+
+  <p>Main contents:</p>
+
+  <ol>
+    <li><a href="#intro">Introduction</a></li>
+
+    <li>
+      <a href="#fcm">Programming Fortran for the FCM build system</a>
+
+      <ul>
+        <li><a href="#fcm-general">General</a></li>
+
+        <li><a href="#fcm-cpp">Use of C pre-processor</a></li>
+      </ul>
+    </li>
+
+    <li>
+      <a href="#fortran">Programming Fortran in general</a>
+
+      <ul>
+        <li><a href="#fortran-layout">Layout and formatting</a></li>
+
+        <li><a href="#fortran-style">Style</a></li>
+
+        <li><a href="#fortran-feature">Fortran features</a></li>
+      </ul>
+    </li>
+
+    <li><a href="#template">Program templates</a></li>
+  </ol>
+
+  <h2><a name="intro"></a>1. Introduction</h2>
+
+  <p>Fortran is the standard programming language at the Met Office for
+  developing scientific and research applications, in particular, for programs
+  running on the supercomputers. This document describes some guidelines that
+  should be followed by developers when writing Fortran code, especially for
+  code in systems hosted by FCM.</p>
+
+  <h2><a name="fcm"></a>2. Programming Fortran for the FCM build system</h2>
+
+  <h3><a name="fcm-general"></a>2.1 General</h3>
+
+  <p>To get the most out of the FCM build system, you should follow these
+  guidelines when you develop your code:</p>
+
+  <ol>
+    <li>Each source file should contain one and no more than one top level
+    program unit, (such as a PROGRAM, a standalone SUBROUTINE/FUNCTION or a
+    MODULE). All top level standalone program units in a source tree should be
+    uniquely named. ("Top level" means a standalone program unit that is
+    compilable independently, i.e. this rule does not restrict the naming and
+    placements of sub-programs in a CONTAINS section.) FCM may fail to set up
+    the dependency tree of your source correctly if you do not follow this rule.
+
+      <p>A clash of program unit names happens most often when you have multiple
+      versions of the same program unit in the same source tree. You should
+      design your code to avoid this situation. If it is not possible to do so,
+      you may have to use a pre-processor to ensure that there is only one copy
+      of each program unit in the source tree. Another situation where clashes
+      of program unit names may occur is when you are developing code that is
+      shared between several projects. In this case, you may want to agree with
+      the other projects a naming convention to define a unique namespace for
+      program units in each project. (E.g. some projects at the Met Office have
+      adopted a naming convention such that all shared program units in a
+      project are named with a unique prefix.)</p>
+    </li>
+
+    <li>All code should be written using the free source form. (At Fortran 95,
+    the free source form can have a maximum of 132 characters per line, and up
+    to 39 continuations in a Fortran statement.) The fixed source form is
+    obsolete, and is not supported by the interface file generators used by
+    FCM.</li>
+
+    <li>An interface should be provided when calling a SUBROUTINE or a FUNCTION.
+    Not only is this considered good practice, it also allows FCM to determine
+    the dependency relationship of your source files. An interface can be
+    provided in these ways:
+
+      <table summary="interface - internal procedures" width="100%" border="1">
+        <tr>
+          <th colspan="2">Internal sub-program</th>
+        </tr>
+
+        <tr>
+          <td colspan="2">Place sub-programs in the CONTAINS section of a
+          standalone program unit. There are two advantages for this approach.
+          Firstly, the sub-programs will get an automatic interface when the
+          container program unit is compiled. Secondly, it should be easier for
+          the compiler to provide optimisation when the sub-programs are
+          internal to the caller.  The disadvantage of this approach is that the
+          sub-programs are local to the caller, and so they cannot be called by
+          other program units.  Therefore, this approach is only suitable for
+          small sub-programs local to a particular program unit.
+        
+            <p>Note: One way to share a sub-program unit between several top
+            level program units is to make use of the Fortran INCLUDE statement.
+            You can write the sub-program unit in a separate file and place it
+            in the CONTAINS section of different program units using INCLUDE
+            statements.  The disadvantage of this approach is that when the
+            program is compiled, a copy of the sub-program unit will be embedded
+            within each of the top level program units. This may lead to an
+            increase in size of the executable, and so this approach is still
+            only suitable for small sub-programs local to a small number of
+            program units.</p>
+
+            <p>Example:</p>
+          </td>
+        </tr>
+
+        <tr>
+          <td width="50%">In the file "sub_prog.inc":
+
+            <pre>
+SUBROUTINE sub_prog (some, arg)
+! Some declarations ...
+! Some executable statements ...
+END SUBROUTINE sub_prog
+</pre>
+          </td>
+
+          <td>In the file "bar.f90":
+
+            <pre>
+SUBROUTINE bar (more, arg)
+! Some declarations ...
+! Some executable statements ...
+CALL sub_prog (some, arg)
+! More executable statements ...
+CONTAINS
+  INCLUDE 'sub_prog.inc'
+END SUBROUTINE bar
+</pre>
+          </td>
+        </tr>
+      </table>
+
+      <table summary="interface - module procedures" width="100%" border="1">
+        <tr>
+          <th colspan="2">Module procedures</th>
+        </tr>
+
+        <tr>
+          <td colspan="2">Place sub-programs in the CONTAINS section of a
+          MODULE. Again, the sub-programs will have automatic interfaces when
+          the MODULE is compiled.  If you give the sub-programs the PUBLIC
+          attribute (which is the default), you will be able to call them from
+          anywhere using the current MODULE. You will also gain all the
+          advantages offered by a MODULE. (E.g. a MODULE will allow you to
+          design your code in a more object-oriented manner.) However, MODULE
+          dependency can have an impact on the efficiency of incremental
+          compilations. For example, if you modify items that are local to the
+          MODULE, it is very difficult for the build system to detect that your
+          change does not affect program units using the MODULE, so the build
+          system will end up compiling the MODULE and all the program units that
+          use it.
+
+            <p>Example:</p>
+          </td>
+        </tr>
+
+        <tr>
+          <td width="50%">In the file "my_mod.f90":
+
+            <pre>
+MODULE my_mod
+! Some module declarations
+CONTAINS
+  SUBROUTINE sub_prog (some, arg)
+  ! Some declarations ...
+  ! Some executable statements ...
+  END SUBROUTINE sub_prog
+END MODULE my_mod
+</pre>
+          </td>
+
+          <td>In the file "foo.f90":
+
+            <pre>
+SUBROUTINE foo (some, arg)
+USE my_mod, ONLY: sub_prog
+! Some declarations ...
+! Some executable statements ...
+CALL sub_prog (some, arg)
+! More executable statements ...
+END SUBROUTINE foo
+</pre>
+          </td>
+        </tr>
+      </table>
+
+      <table summary="interface - interface files" width="100%" border="1">
+        <tr>
+          <th colspan="2">Interface files</th>
+        </tr>
+
+        <tr>
+          <td colspan="2">For each source file containing a standalone
+          SUBROUTINE or FUNCTION, FCM generates a file containing the interface
+          of the SUBROUTINE or FUNCTION. By default, the generated file is named
+          after the original source file, but with the file extension replaced
+          by "*.interface". In the specification section of the caller routine,
+          you will then be able to declare the interface using a Fortran INCLUDE
+          statement to include the interface file. This type of INCLUDE
+          statement is detected automatically by FCM, which will use it to set
+          up the dependency tree.
+        
+            <p>The advantage of using an interface file is that the caller is
+            now dependent on the interface file, rather than the SUBROUTINE or
+            FUNCTION itself. If you change the SUBROUTINE or FUNCTION without
+            modifying its interface, the build system will not re-compile the
+            caller in incremental build, (but it will be intelligent enough to
+            re-link the executable with the updated object).</p>
+
+            <p>Note: By default, an interface file is named after the original
+            source file. Bearing this in mind, it is worth noting that file
+            names in a Unix/Linux system are case-sensitive, and so the
+            interface file name declared by your INCLUDE statement is also case
+            sensitive. If you use an incorrect case in the INCLUDE statement,
+            the dependency tree will be set up incorrectly and the compilation
+            will fail. Another problem is that if you do not name your file
+            after the program unit, the dependency tree will be wrong. To avoid
+            this problem, it is recommended that all source files are named in
+            lower case after the program units they contain. (Alternatively, you
+            can use the TOOL::INTERFACE option in the FCM build configuration
+            file to allow you to alter the default behaviour so that the
+            interface file is named after the "program" unit in lowercase. We
+            may alter FCM in the future so that this will become the default. In
+            the mean time, it is highly recommended that you use this option and
+            design your new code accordingly.)</p>
+
+            <p>Example:</p>
+          </td>
+        </tr>
+
+        <tr>
+          <td width="50%">In the file "sub_prog.f90":
+
+            <pre>
+SUBROUTINE sub_prog (some, arg)
+! Some declarations ...
+! Some executable statements ...
+END SUBROUTINE sub_prog
+</pre>
+          </td>
+
+          <td>In the file "egg.f90":
+
+            <pre>
+SUBROUTINE egg (some, arg)
+! Some declarations ...
+INCLUDE 'sub_prog.interface'
+! More declarations ...
+! Some executable statements ...
+CALL sub_prog (some, arg)
+! More executable statements ...
+END SUBROUTINE egg
+</pre>
+          </td>
+        </tr>
+      </table>
+
+      <table summary="interface - interfaces in a module" width="100%" border="1">
+        <tr>
+          <th colspan="2">Interfaces in a module</th>
+        </tr>
+
+        <tr>
+          <td colspan="2">There is also a half-way house approach between the
+          second and the third options. You can have a dedicated MODULE where a
+          large number of INCLUDE interface file statements are placed. Other
+          program units get their interfaces by importing from this MODULE. A
+          major disadvantage of this approach is that the sub-programs with
+          their interfaces declared within this MODULE will not be able to call
+          any other sub-programs declared within the same MODULE, as it will run
+          into a cyclic dependency problem. Another disadvantage is that if an
+          interface changes, the MODULE and all program units depending on the
+          MODULE will have to be re-compiled, even though the change may be
+          unrelated to some or all of these program units. For these reasons,
+          this approach is only good if you have a bundle of sub-programs that
+          have relatively stable interfaces and are very much independent of one
+          another.
+
+            <p>Note: a similar approach can be useful when you have a library of
+            legacy or external code. In this situation, you will simply declare
+            the interfaces for all the library sub-programs in the MODULE. Any
+            programs that call sub-programs within the library can then import
+            their interfaces by using the MODULE.</p>
+
+            <p>Example:</p>
+          </td>
+        </tr>
+
+        <tr>
+          <td width="50%">In the file "my_i_mod.f90":
+
+            <pre>
+MODULE my_i_mod
+! Some declarations
+INCLUDE 'sub_prog.interface'
+! More declarations
+END MODULE my_i_mod
+</pre>
+          </td>
+
+          <td>In the file "ham.f90":
+
+            <pre>
+SUBROUTINE ham (some, arguments)
+USE my_i_mod, ONLY: sub_prog
+! Some declarations ...
+! Some executable statements ...
+CALL sub_prog (some, arguments)
+! More executable statements ...
+END SUBROUTINE ham
+</pre>
+          </td>
+        </tr>
+      </table>
+
+      <p>FCM also supports the use of a <tt>"! DEPENDS ON"</tt> directive for
+      users to specify a dependency from within a source file. This feature is
+      documented in the <a href=
+      "../user_guide/build.html#advanced_dependency">Further dependency
+      features</a> sub-section of the <a href="../user_guide/">FCM user
+      guide</a>. However, it is worth noting that this method is only included
+      in FCM to support legacy code. It is not a feature recommended for new
+      code, and its use should be gradually phased out from existing code.</p>
+    </li>
+
+    <li>Arguments and local variables should be declared in different
+    statements. It makes your declaration clearer, and it is friendlier to the
+    interface file generator.
+
+      <table summary="declaration example" border="1" width="100%">
+        <tr>
+          <th width="50%">Common practice</th>
+
+          <th>Better approach</th>
+        </tr>
+
+        <tr>
+          <td>
+            <pre>
+SUBROUTINE foo (a, b, c)
+
+INTEGER :: a, b, c, i, j, k
+
+! ...
+
+END SUBROUTINE foo
+</pre>
+          </td>
+
+          <td>
+            <pre>
+SUBROUTINE foo (a, b, c)
+
+INTEGER :: a, b, c
+
+INTEGER :: i, j, k
+
+! ...
+
+END SUBROUTINE foo
+</pre>
+          </td>
+        </tr>
+      </table>
+    </li>
+
+    <li>Use the ONLY clause in a USE &lt;module&gt; statement to declare all
+    imported symbols (i.e. parameters, variables, functions, subroutines, etc).
+    This makes it easier to locate the source of each symbol, and avoids
+    unintentional access to other PUBLIC symbols within the MODULE. It is also
+    friendlier to the compiler and the interface file generator, as they will
+    not have to import modules and symbols that are unnecessary.</li>
+
+    <li>In its default settings, FCM recognises the following file extensions
+    as Fortran free format source files:
+
+      <ul>
+        <li>*.f90, *.f95: regular Fortran free format source files</li>
+
+        <li>*.F90, *.F95: Fortran free format source files that require
+        pre-processing</li>
+
+        <li>*.inc: INCLUDE files that can be added to a regular Fortran free
+        format source file with a Fortran INCLUDE statement</li>
+      </ul>
+    </li>
+  </ol>
+
+  <h3><a name="fcm-cpp"></a>2.2 Use of C pre-processor with Fortran</h3>
+
+  <p>We do not recommend the use of C pre-processor with Fortran. However, it is
+  acknowledged that there are some situations when it is necessary to
+  pre-process Fortran code. FCM supports pre-processing in two ways.
+  Pre-processing can be left to the compiler or it can be done in a separate
+  early stage of the build process. A separate pre-process stage can be useful
+  if pre-processing changes any of the following in a program unit:</p>
+
+  <ul>
+    <li>its name</li>
+
+    <li>its calling interface</li>
+
+    <li>its dependencies</li>
+  </ul>
+
+  <p>However, using a separate pre-process stage is not the best way of working,
+  as it adds an overhead to the build process. If your code requires
+  pre-processing, you should try to design it to avoid changes in the above.</p>
+
+  <p>In practice, the only reasonable use of C pre-processor with Fortran is for
+  code selection. For example, pre-processing is useful for isolating machine
+  specific libraries or instructions, where it may be appropriate to use inline
+  alternatives for small sections of code. Another example is when multiple
+  versions of the same procedure exist in the source tree and you need to use
+  the pre-processor to select the correct version for your build.</p>
+
+  <p>Avoid using the C pre-processor for code inclusion, as you should be able
+  to do the same via the Fortran INCLUDE statement. You should also avoid
+  embedding pre-processor macros within the continuations of a Fortran
+  statement, as it can make your code very confusing.</p>
+
+  <h2><a name="fortran"></a>3. Programming Fortran in general</h2>
+
+  <p>The guidelines in this section are recommended practices for programming
+  Fortran in general. These are guidelines you should try to adhere to when you
+  are developing new code. If you are modifying existing code, you should adhere
+  to its existing standard and style where possible. If you want to change its
+  standard and style, you should seek prior agreements with the owner and the
+  usual developers of the code. Where possible, you should try to maintain the
+  same layout and style within a source file, and preferably, within all the
+  source code in a particular project.</p>
+
+  <p>When reading these guidelines, it is assumed that you already have a good
+  understanding of modern Fortran terminology. It is understood that these
+  guidelines may not cover every aspect of your work. In such cases, you will
+  be a winner if you use a bit of common sense, and always bearing in mind that
+  some other people may have to maintain the code in the future.</p>
+
+  <p>Always test your code before releasing it. Do not ignore compiler warnings,
+  as they may point you to potential problems.</p>
+
+  <h3><a name="fortran-layout"></a>3.1 Layout and formatting</h3>
+
+  <p>The following is a list of recommended practices for layout and formatting
+  when you write code in Fortran.</p>
+
+  <ul>
+    <li>Indent blocks by 2 characters. Where possible, comments should be
+    indented with the code within a block.</li>
+
+    <li>Use space and blank lines where appropriate to format your code to
+    improve readability. (Use genuine spaces but avoid using tabs, as the "tab"
+    character is not in the Fortran character set.) In the following example,
+    the code on the right hand side is preferred:
+
+      <table summary="space example" border="1" width="100%">
+        <tr>
+          <th width="50%">Common practice</th>
+
+          <th>Better approach</th>
+        </tr>
+
+        <tr>
+          <td>
+            <pre>
+DO i=1,n
+  a(i)%c=10*i/n
+  b(i)%d=20+i
+ENDDO
+IF(this==that)THEN
+  distance=0
+  time=0
+ENDIF
+</pre>
+          </td>
+
+          <td>
+            <pre>
+DO i = 1, n
+  a(i) % c = 10 * i / n
+  b(i) % d = 20 + i
+END DO
+
+IF (this == that) THEN
+  distance = 0
+  time     = 0
+END IF
+</pre>
+          </td>
+        </tr>
+      </table>
+    </li>
+
+    <li>Try to confine your line width to 80 characters, so that your code can
+    be printed easily on A4 paper.</li>
+
+    <li>Line up your statements, where appropriate, to improve readability. For
+    example:
+
+      <table summary="line up example" border="1" width="100%">
+        <tr>
+          <th width="50%">Common practice</th>
+
+          <th>Better approach</th>
+        </tr>
+
+        <tr>
+          <td>
+            <pre>
+REAL, INTENT (OUT) :: my_out (:)
+REAL, INTENT (INOUT) :: my_inout (:)
+REAL, INTENT (IN) :: my_in  (:)
+
+! ...
+
+CHARACTER (LEN = 256) :: my_char
+
+my_char = 'This is a very very' // &amp;
+  ' very very very long' // &amp;
+  ' character assignment'.
+</pre>
+          </td>
+
+          <td>
+            <pre>
+REAL, INTENT (  OUT) :: my_out   (:)
+REAL, INTENT (INOUT) :: my_inout (:)
+REAL, INTENT (IN   ) :: my_in    (:)
+
+! ...
+
+CHARACTER (LEN = 256) :: my_char
+
+my_char = 'This is a very very'  // &amp;
+          ' very very very long' // &amp;
+          ' character assignment'.
+</pre>
+          </td>
+        </tr>
+      </table>
+    </li>
+
+    <li>Short and simple Fortran statements are easier to read and understand
+    than long and complex ones. Where possible, avoid using continuation lines
+    in a statement.</li>
+
+    <li>Avoid putting multiple statements on the same line. It is not good for
+    readability.</li>
+  </ul>
+
+  <h3><a name="fortran-style"></a>3.2 Style</h3>
+
+  <p>The following is a list of recommended styles when you write code in
+  Fortran.</p>
+
+  <ul>
+    <li>New code should be written using Fortran 95 syntax. Avoid unportable
+    vendor/compiler extensions. Avoid Fortran 2003 features for the moment, as
+    they will not become widely available in the near future. (Having said that,
+    there is no harm in designing your code with the future in mind. For
+    example, if there is a feature that is not in Fortran 95 and you know that
+    it is in Fortran 2003, you may want to write your Fortran 95 code to make it
+    easier for the future upgrade.)</li>
+
+    <li>Write your program in UK English, unless you have a very good reason for
+    not doing so. Write your comments in simple UK English and name your program
+    units and variables based on sensible UK English words, bearing in mind that
+    your code may be read by people who are not proficient English
+    speakers.</li>
+
+    <li>When naming your variables and program units, always bear in mind that
+    Fortran is a case-insensitive language. (E.g. EditOrExit is the same as
+    EditorExit.)</li>
+
+    <li>Use only characters in the Fortran character set. In particular, accent
+    characters and tabs are not allowed in code, although they are usually OK
+    in comments. If your editor inserts tabs automatically, you should
+    configure it to switch off the functionality when you are editing Fortran
+    source files.</li>
+
+    <li>Although Fortran has no reserved keywords, you should avoid naming your
+    program units and variables with names that match an intrinsic FUNCTION or
+    SUBROUTINE. Similarly, you should avoid naming your program units and
+    variables with names that match a "keyword" in a Fortran statement.</li>
+
+    <li>Be generous with comments. State the reason for doing something,
+    instead of repeating the Fortran logic in words.</li>
+
+    <li>To improve readability, write your program in mainly lower case
+    characters. Writing a program in mainly lower case also means that you will
+    not have to use the Shift/Caps Lock keys often. There is a lot of debate on
+    using upper/lower cases in a case insensitive language such as Fortran.
+    There is no right or wrong, but people have adopted the different approaches
+    over time, each has its own merit. If you are starting a new project, you
+    should choose a suitable option and stick to it. Otherwise, you should stick
+    with the style in the existing code. Some options are listed here:
+
+      <ul>
+        <li>The ALL CAPS Fortran keywords approach, like most of the examples in
+        this document, where all Fortran keywords and intrinsic procedures are
+        written in ALL CAPS. This approach has the advantage that Fortran
+        keywords stand out, but it does increase how often the Shift/Caps Lock
+        key is used. Programmers who are used to some other programming
+        languages may also find it difficult to read a program with a lot of
+        upper case characters.</li>
+
+        <li>The Title Case Fortran keywords approach, where all Fortran keywords
+        are written with an initial capital case letter.</li>
+
+        <li>The sentence case approach, where only the initial character in a
+        Fortran statements is written in capital case letter, like a normal
+        sentence.</li>
+
+        <li>The all lower case approach, where all Fortran keywords are written
+        in lower case letters.</li>
+
+        <li>Some people have also proposed a variable naming convention where
+        local variables start with an initial lower case letter, private
+        module level variables with an initial capital case letter and public
+        module variables written in all caps. However, this approach has been
+        seen by many as too restrictive, and so its use has not been widely
+        spread.</li>
+      </ul>
+    </li>
+
+    <li>Use the new and clearer syntax for LOGICAL comparisons, i.e.:
+
+      <ul>
+        <li>== instead of .EQ.</li>
+
+        <li>/= instead of .NE.</li>
+
+        <li>&gt; instead of .GT.</li>
+
+        <li>&lt; instead of .LT.</li>
+
+        <li>&gt;= instead of .GE.</li>
+
+        <li>&lt;= instead of .LE.</li>
+      </ul>
+    </li>
+
+    <li>Where appropriate, simplify your LOGICAL assignments, for example:
+
+      <table summary="logic assignment example" border="1" width="100%">
+        <tr>
+          <th width="50%">Common practice</th>
+
+          <th>Better approach</th>
+        </tr>
+
+        <tr>
+          <td>
+            <pre>
+IF (my_var == some_value) THEN
+  something      = .TRUE.
+  something_else = .FALSE.
+
+ELSE
+  something      = .FALSE.
+  something_else = .TRUE.
+END IF
+
+IF (something .EQV. .TRUE.) THEN
+  CALL do_something ()
+  ! ...
+END IF
+</pre>
+          </td>
+
+          <td>
+            <pre>
+something      = (my_var == some_value)
+something_else = (my_var /= some_value)
+
+IF (something) THEN
+  CALL do_something ()
+  ! ...
+END IF
+</pre>
+          </td>
+        </tr>
+      </table>
+    </li>
+
+    <li>Positive logic is usually easier to understand. When you have an
+    IF-ELSE-END IF construct, you should use positive logic in the IF test,
+    provided that the positive and the negative blocks are about the same size.
+    (However, it may be more appropriate to use negative logic if the negative
+    block is significantly bigger than the positive block.) For example:
+
+      <table summary="positive logic example" border="1" width="100%">
+        <tr>
+          <th width="50%">Common practice</th>
+
+          <th>Better approach</th>
+        </tr>
+
+        <tr>
+          <td>
+            <pre>
+IF (my_var != some_value) THEN
+  CALL do_this ()
+
+ELSE
+  CALL do_that ()
+END IF
+</pre>
+          </td>
+
+          <td>
+            <pre>
+IF (my_var == some_value) THEN
+  CALL do_that ()
+
+ELSE
+  CALL do_this ()
+END IF
+</pre>
+          </td>
+        </tr>
+      </table>
+    </li>
+
+    <li>To improve readability, you should always use the optional space to
+    separate the following Fortran keywords:
+
+      <table summary="space in Fortran keywords" width="100%">
+        <tr class="mono">
+          <td width="25%">else if</td>
+
+          <td width="25%">end do</td>
+
+          <td width="25%">end forall</td>
+
+          <td width="25%">end function</td>
+        </tr>
+
+        <tr class="mono">
+          <td width="25%">end if</td>
+
+          <td width="25%">end interface</td>
+
+          <td width="25%">end module</td>
+
+          <td width="25%">end program</td>
+        </tr>
+
+        <tr class="mono">
+          <td width="25%">end select</td>
+
+          <td width="25%">end subroutine</td>
+
+          <td width="25%">end type</td>
+
+          <td width="25%">end where</td>
+        </tr>
+
+        <tr class="mono">
+          <td width="25%">select case</td>
+
+          <td width="25%">-</td>
+
+          <td width="25%">-</td>
+
+          <td width="25%">-</td>
+        </tr>
+      </table>
+    </li>
+
+    <li>If you have a large or complex code block embedding other code blocks,
+    you may consider naming some or all of them to improve readability.</li>
+
+    <li>If you have a large or complex interface block or if you have one or
+    more sub-program units in the CONTAINS section, you can improve readability
+    by using the full version of the END statement (i.e. END SUBROUTINE
+    &lt;name&gt; or END FUNCTION &lt;name&gt; instead of just END) at the end of
+    each sub-program unit. For readability in general, the full version of the
+    END statement is recommended over the simple END.</li>
+
+    <li>Where possible, consider using CYCLE, EXIT or a WHERE-construct to
+    simplify complicated DO-loops.</li>
+
+    <li>When writing a REAL literal with an integer value, put a 0 after the
+    decimal point (i.e. 1.0 as opposed to 1.) to improve readability.</li>
+
+    <li>Where reasonable and sensible to do so, you should try to match the
+    names of dummy and actual arguments to a SUBROUTINE/FUNCTION.</li>
+
+    <li>In an array assignment, it is recommended that you use array notations
+    to improve readability. E.g.:
+
+      <table summary="array notation example" border="1" width="100%">
+        <tr>
+          <th width="50%">Common practice</th>
+
+          <th>Better approach</th>
+        </tr>
+
+        <tr>
+          <td>
+            <pre>
+INTEGER :: array1(10, 20), array2(10, 20)
+INTEGER :: scalar
+
+array1 = 1
+array2 = array1 * scalar
+</pre>
+          </td>
+
+          <td>
+            <pre>
+INTEGER :: array1(10, 20), array2(10, 20)
+INTEGER :: scalar
+
+array1(:, :) = 1
+array2(:, :) = array1(:, :) * scalar
+</pre>
+          </td>
+        </tr>
+      </table>
+    </li>
+
+    <li>Where appropriate, use parentheses to improve readability. E.g.:
+
+      <table summary="parentheses example" border="1" width="100%">
+        <tr>
+          <th width="50%">Common practice</th>
+
+          <th>Better approach</th>
+        </tr>
+
+        <tr>
+          <td>
+            <pre>
+a = b * i + c / n
+</pre>
+          </td>
+
+          <td>
+            <pre>
+a = (b * i) + (c / n)
+</pre>
+          </td>
+        </tr>
+      </table>
+    </li>
+  </ul>
+
+  <h3><a name="fortran-feature"></a>3.3 Fortran features</h3>
+
+  <p>The following is a list of Fortran features that you should use or
+  avoid.</p>
+
+  <ul>
+    <li>Use IMPLICIT NONE in all program units. It means that you have declare
+    all your variables explicitly. This helps to reduce bugs in your program
+    that will otherwise be difficult to track.</li>
+
+    <li>Design your derived data types carefully and use them to group related
+    variables. Appropriate use of derived data types will allow you to design
+    modules and procedures with simpler and cleaner interfaces.</li>
+
+    <li>Where possible, module variables and procedures should be declared
+    PRIVATE. This avoids unnecessary export of symbols, promotes data hiding and
+    may also help the compiler to optimise the code.</li>
+
+    <li>When you are passing an array argument to a SUBROUTINE/FUNCTION, and the
+    SUBROUTINE/FUNCTION does not change the SIZE/DIMENSION of the array, you
+    should pass it as an assumed shape array. Memory management of such an array
+    is automatically handled by the SUBROUTINE/FUNCTION, and you do not have to
+    worry about having to ALLOCATE or DEALLOCATE your array. It also helps the
+    compiler to optimise the code.</li>
+
+    <li>Use an array POINTER when you are passing an array argument to a
+    SUBROUTINE, and the SUBROUTINE has to alter the SIZE/DIMENSION of the array.
+    You should also use an array POINTER when you need a dynamic array in a
+    component of a derived data type. (Note: Fortran 2003 allows passing
+    ALLOCATABLE arrays as arguments as well as using ALLOCATABLE arrays as
+    components of a derived data type. Therefore, the need for using an array
+    POINTER should be reduced once Fortran 2003 becomes more widely
+    accepted.)</li>
+
+    <li>Where possible, an ALLOCATE statement for an ALLOCATABLE array (or a
+    POINTER used as a dynamic array) should be coupled with a DEALLOCATE within
+    the same scope. If an ALLOCATABLE array is a PUBLIC MODULE variable, it is
+    highly desirable if its memory allocation and deallocation are only
+    performed in procedures within the MODULE in which it is declared. You may
+    consider writing specific SUBROUTINEs within the MODULE to handle these
+    memory managements.</li>
+
+    <li>To avoid memory fragmentation, it is desirable to DEALLOCATE in reverse
+    order of ALLOCATE.
+
+      <table summary="ALLOCATE example" border="1" width="100%">
+        <tr>
+          <th width="50%">Common practice</th>
+
+          <th>Better approach</th>
+        </tr>
+
+        <tr>
+          <td>
+            <pre>
+ALLOCATE (a(n))
+ALLOCATE (b(n))
+ALLOCATE (c(n))
+! ... do something ...
+DEALLOCATE (a)
+DEALLOCATE (b)
+DEALLOCATE (c)
+</pre>
+          </td>
+
+          <td>
+            <pre>
+ALLOCATE (a(n))
+ALLOCATE (b(n))
+ALLOCATE (c(n))
+! ... do something ...
+DEALLOCATE (c)
+DEALLOCATE (b)
+DEALLOCATE (a)
+</pre>
+          </td>
+        </tr>
+      </table>
+    </li>
+
+    <li>Always define a POINTER before using it. You can define a POINTER in its
+    declaration by pointing it to the intrinsic function NULL (). Alternatively,
+    you can make sure that your POINTER is defined or nullified early on in the
+    program unit. Similarly, NULLIFY a POINTER when it is no longer in use,
+    either by using the NULLIFY statement or by pointing your POINTER to NULL
+    ().</li>
+
+    <li>Avoid the DIMENSION attribute or statement. Declare the DIMENSION with
+    the declared variables. E.g.:
+
+      <table summary="dimension attribute example" border="1" width="100%">
+        <tr>
+          <th width="50%">Common practice</th>
+
+          <th>Better approach</th>
+        </tr>
+
+        <tr>
+          <td>
+            <pre>
+INTEGER, DIMENSION(10) :: array1
+INTEGER                :: array2
+DIMENSION              :: array2(20)
+</pre>
+          </td>
+
+          <td>
+            <pre>
+INTEGER :: array1(10), array2(20)
+</pre>
+          </td>
+        </tr>
+      </table>
+    </li>
+
+    <li>Avoid COMMON blocks and BLOCK DATA program units. Use PUBLIC MODULE
+    variables.</li>
+
+    <li>Avoid the EQUIVALENCE statament. Use a POINTER or a derived data type,
+    and the TRANSFER intrinsic function to convert between types.</li>
+
+    <li>Avoid the PAUSE statement, as your program will hang in a batch
+    environment. If you need to halt your program for interactive use, consider
+    using a READ* statement instead.</li>
+
+    <li>Avoid the ENTRY statement. Use a MODULE or internal SUBROUTINE.</li>
+
+    <li>Avoid the GOTO statement. The only commonly acceptable usage of GOTO is
+    for error trapping. In such case, the jump should be to a commented 9999
+    CONTINUE statement near the end of the program unit. Typically, you will
+    only find error handlers beyond the 9999 CONTINUE statement.</li>
+
+    <li>Avoid assigned GOTO, arithmetic IF, etc. Use the appropriate modern
+    constructs such as IF, WHERE, SELECT CASE, etc..</li>
+
+    <li>Avoid numbered statement labels. DO ... <em>label</em> CONTINUE
+    constructs should be replaced by DO ... END DO constructs. FORMAT statements
+    should be replaced by format strings. (Tip: a format string can be a
+    CHARACTER variable.)</li>
+
+    <li>A FUNCTION should be PURE, i.e. it should have no side effects (e.g.
+    altering an argument or module variable, or performing I/O). If you need to
+    perform a task with side effects, you should use a SUBROUTINE instead.</li>
+
+    <li>Avoid using a statement FUNCTION. Use an internal FUNCTION instead.</li>
+
+    <li>Avoid RECURSIVE procedures if possible. RECURSIVE procedures are usually
+    difficult to understand, and are always difficult to optimise in a
+    supercomputer environment.</li>
+
+    <li>Avoid using the specific names of intrinsic procedures. Use the generic
+    names of intrinsic procedures where possible.</li>
+  </ul>
+
+  <h2><a name="template"></a>4. Program templates</h2>
+
+  <p>The following is a basic template for a SUBROUTINE:</p>
+  <pre>
+SUBROUTINE &lt;subroutine_name&gt; (&lt;arguments&gt;, ...)
+
+! Description:
+!   &lt;Explain the usage of the subroutine and what it does.&gt;
+!
+! (c) Crown copyright Met Office. All rights reserved.
+! For further details please refer to the file COPYRIGHT.txt
+! which you should have received as part of this distribution.
+! ------------------------------------------------------------------------------
+
+! Modules
+&lt;module declarations, each with a list of imported symbols&gt;
+
+IMPLICIT NONE
+
+! Arguments:
+&lt;arguments with INTENT (  OUT)&gt;
+&lt;arguments with INTENT (INOUT)&gt;
+&lt;arguments with INTENT (IN   )&gt;
+
+! Local declarations:
+&lt;parameters, derived data types, variables, etc&gt;
+
+! INTERFACE blocks
+&lt;INCLUDE interface blocks for external procedures&gt;
+&lt;interface blocks for procedure and operator overloading&gt;
+
+!-------------------------------------------------------------------------------
+
+&lt;... subroutine executable statements&gt;
+
+!-------------------------------------------------------------------------------
+
+CONTAINS
+
+  &lt;sub-programs&gt;
+
+END SUBROUTINE &lt;subroutine_name&gt;
+</pre>
+
+  <p>Note:</p>
+
+  <ul>
+    <li>The basic templates for other types of program units are similar to
+    that of a SUBROUTINE, with the following exceptions:
+
+      <ul>
+        <li>A PROGRAM does not have arguments, so the "arguments" list in the
+        header and the "Arguments" section in the declaration section should be
+        removed. All declarations are local to a PROGRAM, so the "Local
+        Declarations" section should be replaced by a simple "Declarations"
+        section.</li>
+
+        <li>A FUNCTION should have no INTENT (OUT) and INTENT (INOUT) arguments.
+        You will also need to declare the type returned by the FUNCTION. This
+        can be in the FUNCTION header, declared separately or declared using a
+        RESULT clause. For the latters, make your declaration at the beginning
+        of the "Local declarations" section.</li>
+
+        <li>A MODULE does not have arguments, so the "arguments" list in the
+        header and the "Arguments" section in the declaration section should be
+        removed. Where appropriate, the "Local Declarations" section should be
+        replaced by a "PUBLIC declarations" section and a "PRIVATE declarations"
+        section.</li>
+      </ul>
+    </li>
+
+    <li>When you are distributing your code, you should include a COPYRIGHT.txt
+    file at a top level directory in your source tree. The file should contain
+    the detailed copyright information:
+
+      <ul>
+        <li>the copyright year, ranging from the year the code is first
+        distributed to the year the code is last distributed</li>
+
+        <li>the copyright statement</li>
+
+        <li>the owner of the code and his/her address</li>
+      </ul>
+
+      <p>For example:</p>
+      <pre>
+!------------------------------------------------------------------------------!
+!                                                                              !
+! (C) Crown copyright 2005-6 Met Office. All rights reserved.                  !
+!                                                                              !
+! Use, duplication or disclosure of this code is subject to the restrictions   !
+! as set forth in the contract. If no contract has been raised with this copy  !
+! of the code, the use, duplication or disclosure of it is strictly            !
+! prohibited. Permission to do so must first be obtained in writing from the   !
+! Head of Numerical Modelling at the following address:                        !
+!                                                                              !
+! Met Office, FitzRoy Road, Exeter, Devon, EX1 3PB, United Kingdom             !
+!                                                                              !
+!------------------------------------------------------------------------------!
+</pre>
+    </li>
+  </ul>
+  
+  <script type="text/javascript" src="maintain.js"></script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/standards/logo.png
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/standards/logo.png	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/standards/logo.png	(revision 1665)
@@ -0,0 +1,1 @@
+link ../etc/logo.png
Index: LMDZ5/branches/testing/tools/fcm/doc/standards/maintain.js
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/standards/maintain.js	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/standards/maintain.js	(revision 1665)
@@ -0,0 +1,1 @@
+link ../etc/maintain.js
Index: LMDZ5/branches/testing/tools/fcm/doc/standards/perl_standard.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/standards/perl_standard.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/standards/perl_standard.html	(revision 1665)
@@ -0,0 +1,396 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>Perl coding standard for FCM</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="Perl coding standard for FCM">
+  <meta name="keywords" content="Perl, coding standard, FCM">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="StyleSheet" type="text/css" href="style.css">
+  <style type="text/css">
+  <!--
+  li, th, td {
+    padding: 3px;
+  }
+  td {
+    vertical-align: top;
+  }
+  th.r {
+    text-align: right;
+    background-color: transparent;
+    padding-right: 5px;
+  }
+  th.l {
+    text-align: left;
+    background-color: transparent;
+  }
+  -->
+  </style>
+</head>
+
+<body>
+  <p align="right"><img src="logo.png" alt="Met Office logo" width="85"
+  height="85"></p>
+
+  <h1>Perl coding standard for FCM</h1>
+
+  <p align="center">Last updated: 28 November 2006</a>
+
+  <p align="center">Met Office<br>
+  FitzRoy Road, Exeter<br>
+  Devon, EX1 3PB<br>
+  United Kingdom</p>
+
+  <p align="center">&copy; Crown copyright 2005-6. All rights reserved.</p>
+
+  <p align="center">Questions regarding this document or permissions to quote
+  from it should be directed to the <a href=
+  "mailto:iprmanager@metoffice.gov.uk">IPR Manager</a>.</p>
+  
+  <script type="text/javascript">
+  <!--
+  var out = 'For printing, please use the '
+  out    += '<a href="fcm-perl-standard.pdf">PDF<\/a> version of the document.'
+  document.write ('<p align="center">')
+  document.write (out)
+  document.write ('<\/p>')
+  //-->
+  </script>
+
+  <h2>Contents</h2>
+
+  <ul>
+    <li>Main contents:
+
+      <ol>
+        <li><a href="#1">Introduction</a></li>
+
+        <li><a href="#2">Online Perl style guides</a></li>
+
+        <li><a href="#3">Coding standard</a></li>
+      </ol>
+    </li>
+  </ul><a name="1"></a>
+
+  <h2>1. Introduction</h2>
+
+  <p>Perl (Practical Extraction and Report Language) is gaining a lot of
+  popularity at the Met Office for developing applications that are
+  traditionally programmed using shell script. For example, it is currently our
+  choice of language for developing the in-house components of the FCM
+  system.</p>
+ 
+  <p>Perl is a very powerful general purpose scripting tool that is free and
+  portable across a huge variety of platforms including many non-Unix systems.
+  Replacing a shell script with an equivalent Perl program often results in a
+  massive reduction in runtime - using cleaner syntax and algorithm.</p>
+
+  <p>Perl is a language with a rich set of "grammar". To most people, the first
+  impression of a piece of code written in Perl is that it is very ugly. Its
+  lines are full of punctuation junks that nobody can hope to understand. This
+  is often caused by poorly written programs coupled with little and often
+  inadequte documentations. To improve readability and to reduce the overheads
+  of maintenance, it is important for Perl programmers to write their code in a
+  nice and consistent way.</p>
+
+  <p>The aim of this document is to propose ideas on how the Perl programming
+  language should be used with FCM.</p>
+
+  <a name="2"></a><h2>2. Online Perl style guides</h2>
+
+  <p>There are many Perl style guides available online. Some are listed
+  below:</p>
+
+  <ul>
+    <li>the manpages <code>perlstyle</code> and <code>perlmodstyle</code></li>
+
+    <li><a href=
+    "http://www.kulnet.kuleuven.ac.be/perlcourse/perlingo.html">Perlingo</a></li>
+
+    <li><a href="http://ali.as/devel/code.html">Perl Style Guide for Large Scale
+    Object Oriented Development</a></li>
+
+    <li><a href="http://perltidy.sourceforge.net/">Perltidy</a></li>
+
+    <li><a href=
+    "http://perl.apache.org/docs/2.0/devel/core/coding_style.pdf">mod_perl
+    Coding Style Guide</a> (PDF)</li>
+  </ul>
+
+  <p>It is worth noting that the ideas in some of the Perl style guides may
+  conflict with each other - as they are targeted to different people. However,
+  there is a common theme to most of the best practices. The following is a
+  summary:</p>
+
+  <ul>
+    <li>A source file, whether it is a top-level script or a module, should
+    contain a header block with information of the source file,
+    some general description of the code as well as standard pragmas or
+    options for running the Perl interpreter.</li>
+
+    <li>Each function should be preceded by a comment block or a block of
+    POD to specify a synopsis for the defined function.</li>
+
+    <li>Avoid using names of built-in functions to name your new functions.</li>
+
+    <li>If the parameter list of a function is becoming too long, e.g. more
+    than 3 arguments, you may want to implement the argument list with a hash,
+    so that all the arguments are named.</li>
+
+    <li>Indent to an appropriate number of spaces/tabs for code blocks.</li>
+
+    <li>Open curly brackets should be on the same line as the keyword.</li>
+
+    <li>Close curly brackets should line up with the keywords that started
+    the block.</li>
+
+    <li>Insert a blank line between chunks of code that do different
+    things.</li>
+
+    <li>Use space between tokens and operators to improve readability.
+    Use space after commas. No space before commas and semi-colons.</li>
+
+    <li>Line up corresponding items vertically.</li>
+
+    <li>Use parentheses only if necessary.</li>
+
+    <li>Restrict line length to e.g. 80 characters.</li>
+
+    <li>Be consistent with style.</li>
+
+    <li>Use the "strict" and "warnings" pragmas.</li>
+
+    <li>options and arguments should be processed as "soon" as possible,
+    preferably at the beginning of a source file or a function.</li>
+
+    <li>Use the "__END__" directive at the end of a Perl script.</li>
+
+    <li>-more later-</li>
+  </ul>
+
+  <a name="3"></a><h2>3. Coding standard</h2>
+
+  <p>The main question is: what should we include in our coding standard?
+  Although we would like to recommend using the best practices described in
+  the last section, we would not want to impose any restriction, as Perl is a
+  language designed to do things in many different ways. The only thing we
+  would like to impose is a header block in each source file, and a header
+  comment block for each function in a source file.</p>
+
+  <p>For a Perl executable, the header block of the source file should contain
+  the following:</p>
+  
+  <ul>
+    <li>the first line should be <tt>"#!/usr/bin/perl"</tt></li>
+
+    <li>the name of the executable</li>
+    
+    <li>a synopsis and/or a description or what the executable does</li>
+
+    <li>an explanation of the options and arguments (either in separate
+    sections or described within the "description" section)</li>
+
+    <li>copyright and owner information</li>
+
+    <li>no history or revision information, (as we would prefer using the
+    Subversion log message to record such information)</li>
+
+    <li>use "strict" and use "warnings" statements</li>
+
+    <li>use the "__END__" directive at the end of a Perl script.</li>
+  </ul>
+
+  <table summary="executable header block example" border="1" width="100%">
+    <tr>
+      <th>Executable header block example</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   example.pl
+#
+# SYNOPSIS
+#   example.pl [options] args
+#
+# DESCRIPTION
+#   This is a header example, and so on and so forth.
+#
+# OPTIONS
+#   -b [--bar] - this option does what "bar" does.
+#   -f [--foo] - this option does what "foo" does.
+#
+# ARGUMENTS
+#   args       - description of each argument.
+#
+# SEE ALSO
+#   list of relevant commands, modules and documents
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard pragmas
+use strict;
+use warnings;
+
+# Standard modules
+use Getopt::Long;
+
+# ------------------------------------------------------------------------------
+
+# Process options
+my ($foo, $bar);
+GetOptions (
+  'foo|f' =&gt; \$foo,
+  'bar|b' =&gt; \$bar,
+);
+
+# Process arguments
+my $arg = shift @ARGV;
+
+# Do something...
+print 'This is an example: ', $arg, "\n";
+print 'FOO', "\n" if $foo;
+print 'BAR', "\n" if $bar;
+
+__END__
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>For a Perl module, the header block of the source file should contain
+  the following:</p>
+  
+  <ul>
+    <li>the first line should be <tt>"#!/usr/bin/perl"</tt></li>
+
+    <li>the name of the module</li>
+    
+    <li>a synopsis and/or a description or what the module does</li>
+
+    <li>copyright and owner information</li>
+
+    <li>no history or revision information</li>
+
+    <li>use "strict" and use "warnings" statements</li>
+
+    <li>a list of exports (do not export if you are writing an OO module)</li>
+
+    <li>use the "__END__" directive at the end of a Perl script, and remember
+    to put 1 before the end of the module, so that it will return true.</li>
+  </ul>
+
+  <table summary="module header block example" border="1" width="100%">
+    <tr>
+      <th>Module header block example</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Metoffice::Example
+#
+# DESCRIPTION
+#   This is a header example, and so on and so forth.
+#
+# SEE ALSO
+#   list of relevant commands, modules and documents
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Metoffice::Example;
+
+# Standard pragmas
+use strict;
+use warnings;
+
+# Exports
+our (@ISA, @EXPORT, @EXPORT_OK);
+require Exporter;
+@ISA    = qw(Exporter);
+@EXPORT = qw(
+  foo
+  bar
+);
+
+# ------------------------------------------------------------------------------
+# ... some more Perl ...
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>The header of a function (or "method" for OO code) should have the
+  following:</p>
+
+  <ul>
+    <li>a synopsis of the function's calling interfaces.</li>
+
+    <li>a description of what the function does and what it returns, and if
+    appropriate, what each argument represents</li>
+  </ul>
+
+  <table summary="function header block example" border="1" width="100%">
+    <tr>
+      <th>Function header block example</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+# ... Something before the function ...
+#
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $result = &amp;print_hello;
+#   $result = &amp;print_hello ($arg);
+#
+# DESCRIPTION
+#   Print the word "hello" to standard output. If no argument is specified,
+#   the word "world" will be printed after the word "hello". Otherwise, the
+#   word specified by the argument $arg will follow "hello". The function
+#   returns true on success.
+#
+# ARGUMENTS
+#   $arg - optional, describe $arg if it has not been done in the above section
+# ------------------------------------------------------------------------------
+
+sub print_hello {
+  my ($arg) = @_;
+  $arg = defined ($arg) ? $arg : 'world';
+  my $result = print 'hello ', $arg, "\n";
+  return $result;
+}
+
+# ------------------------------------------------------------------------------
+#
+# ... Something after the function ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/standards/style.css
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/standards/style.css	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/standards/style.css	(revision 1665)
@@ -0,0 +1,1 @@
+link ../etc/style.css
Index: LMDZ5/branches/testing/tools/fcm/doc/standards/style.html2ps.css
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/standards/style.html2ps.css	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/standards/style.html2ps.css	(revision 1665)
@@ -0,0 +1,1 @@
+link ../etc/style.html2ps.css
Index: LMDZ5/branches/testing/tools/fcm/doc/user_guide/annex_bld_cfg.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/user_guide/annex_bld_cfg.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/user_guide/annex_bld_cfg.html	(revision 1665)
@@ -0,0 +1,1533 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide Annex: Declarations in FCM build
+  configuration file</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide Annex">
+  <meta name="keywords" content="FCM, user guide, annex">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; Annex: Declarations in
+    FCM build configuration file
+  </address>
+
+  <h1>Annex:<br>
+  Declarations in FCM build configuration file</h1>
+
+  <p>The following is a list of supported declarations for the configuration
+  file used by the FCM build system. Unless otherwise stated, the fields in
+  all declaration labels are not case sensitive. Build declarations can be
+  made either in a build configuration file or in an extract configuration
+  file. In the latter case, the prefix "BLD::" must be added at the beginning
+  of each label to inform the extract system that the declaration is a build
+  system declaration. (In a build configuration file, the prefix "BLD::" is
+  optional.)</p>
+
+  <table class="pad" summary="Declarations in build configuration file"
+  width="100%" border="1">
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">CFG::TYPE</th>
+
+      <th>Description</th>
+
+      <td>The configuration file type, the value should always be "bld" for a
+      build configuration file. This declaration is compulsory for all
+      build configuration files. (This declaration is automatic when the
+      extract system creates a build configuration file.)</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+cfg::type  bld
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">CFG::VERSION</th>
+
+      <th>Description</th>
+
+      <td>The file format version, currently "1.0" - a version is included so
+      that we shall be able to read the configuration file correctly should we
+      decide to change its format in the future. (This declaration is automatic
+      when the extract system creates a build configuration file.)</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+cfg::version  1.0
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">TARGET</th>
+
+      <th>Description</th>
+
+      <td>Specify the targets for the build. Multiple targets can be declared in
+      one or more declarations. These targets become the dependencies of the
+      default "all" target in the <em>Makefile</em>.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+target  VarScr_AnalysePF VarScr_CovAccStats
+target  VarScr_CovPFstats
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">DIR::ROOT</th>
+
+      <th>Description</th>
+
+      <td>The root directory of the build. It must be declared for each build.
+      (This declaration is automatic when the extract system creates a build
+      configuration file. The value is normally the root path of the
+      extraction destination.)</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::root  $HOME/my_build
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">SRC::&lt;pcks&gt;</th>
+
+      <th>Description</th>
+
+      <td>This declares a source directory in the sub-package &lt;pcks&gt;.
+      The name of the sub-package &lt;pcks&gt; must be unique. Package names
+      are delimited by double colons "::" or double underscores "__". (This
+      declaration is automatic when the extract system creates the build
+      configuration file. The list of declared source directories will be the
+      list of extracted source directories.)</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+src::var::code::VarMod_PF  $HOME/my_build/src/var/code/VarMod_PF
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">SEARCH_SRC</th>
+
+      <th>Description</th>
+
+      <td>This declares a flag to determine whether the build system should
+      search the source sub-directory of the build root for a list of source
+      directories. The automatic search is useful if the build system is
+      invoked standalone and the source sub-directory contains the full source
+      tree of the build. The default is to search (1). Set the flag to 0 to
+      switch off the behaviour. (When the extract system creates a build
+      configuration file, it declares all source directories. Searching of the
+      source sub-directory should not be required, and so this flag is
+      automatically set to 0.)</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+search_src  0
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">EXE_DEP[::&lt;target&gt;]</th>
+
+      <th>Description</th>
+
+      <td>This declares an extra dependency for either all main program targets
+      or only &lt;target&gt; if it is specified. If &lt;target&gt; is specified,
+      it must be the name of a main program target. The value of the declaration
+      is a space delimited list. Each item in the list can either be a valid
+      name of a sub-package or the name of a valid object target. If a
+      sub-package name is used, the <em>make</em> rule for the main program will
+      be set to depend on all (non-program) object files within the
+      sub-package.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+# Only foo.exe to depend on the package foo::bar and egg.o
+exe_dep::foo.exe  foo::bar egg.o
+
+# All executables to depend on the package foo::bar and egg.o
+exe_dep  foo::bar egg.o
+
+# Only foo.exe to depend on all objects
+exe_dep::foo.exe
+
+# All executables to depend on all objects
+exe_dep
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">BLOCKDATA[::&lt;target&gt;]</th>
+
+      <th>Description</th>
+
+      <td>This declares a BLOCKDATA dependency for either all main program targets
+      or only &lt;target&gt; if it is specified. If &lt;target&gt; is specified,
+      it must be the name of a main program target. The value of the declaration
+      is a space delimited list. Each item in the list must be the name of a
+      valid object target containing a Fortran BLOCKDATA program unit.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+# Only foo.exe to depend on blkdata.o
+blockdata::foo.exe  blkdata.o
+
+# All executables to depend on fbd.o
+blockdata  fbd.o
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">EXE_NAME::&lt;name&gt;</th>
+
+      <th>Description</th>
+
+      <td>This renames the executable target of a main program source file
+      &lt;name&gt; to the specified value.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+# Rename the executable target name of foo.f90 from "foo.exe" to "bar"
+exe_name::foo  bar
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">LIB[::&lt;pcks&gt;]</th>
+
+      <th>Description</th>
+
+      <td>This declares the name of a library archive target. If &lt;pcks&gt; is
+      specified in the label, the declaration applies to the library archive
+      target for that sub-package only. If set, the name of the library archive
+      target will be named "lib&lt;value&gt;.a", where &lt;value&gt; is the
+      value of the declaration. If not specified, the default is to name the
+      global library "libfcm_default.a". For a library archive of a sub-package,
+      the default is to name its library after the name of the sub-package.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+# Rename the top level library "libfoo.a"
+lib  foo
+
+# Rename the library for the sub-package "egg::ham"
+# from "libegg__ham.a" to "libegg-ham.a"
+lib::egg::ham  egg-ham
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">PP[::&lt;pcks&gt;]</th>
+
+      <th>Description</th>
+
+      <td>This declares whether a pre-processing stage is required. To switch on
+      pre-processing, set the value to 1. If &lt;pcks&gt; is specified
+      in the label, the flag applies to the files within that sub-package
+      only. Otherwise, the flag affects source directories in all packages.
+      The pre-processing stage is useful if the pre-processor changes the
+      dependency and/or the argument list of the source files. The default
+      behaviour is skip the pre-processing stage for all source
+      directories.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+pp::gen 1  # switch on pre-processing for sub-packages in "gen"
+pp      1  # switch on pre-processing globally
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">TOOL::&lt;label&gt;[::&lt;pcks&gt;]</th>
+
+      <th>Description</th>
+
+      <td>This declaration is used to specify a build "tool" such as the Fortran
+      compiler or its flags. The &lt;label&gt; determines the "tool" you are
+      declaring. A TOOL declaration normally applies globally. However, where it
+      is sensible to do so, a sub-package &lt;pcks&gt; can be specified. In
+      which case, the declaration applies only to the files and directories
+      under the sub-package. A list of &lt;label&gt; fields is available <a
+      href="#tools-list">later in this section</a>.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+tool::fc      sxmpif90
+tool::fflags  -Chopt -Pstack
+
+tool::cc      sxmpic++
+tool::cflags  -O nomsg -pvctl nomsg
+
+tool::ar      sxar
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">EXCL_DEP[::&lt;pcks&gt;]</th>
+
+      <th>Description</th>
+
+      <td>
+        This declaration is used to specify whether a particular dependency
+        should be ignored during the automatic dependency scan. If a sub-package
+        &lt;pcks&gt; is specified, the declaration applies only to the files and
+        directories under the sub-package. Otherwise, the declaration applies
+        globally. It is worth noting that the build system is not yet clever
+        enough to recognise changes in this declaration in incremental builds.
+        Therefore, users should manually trigger a full build if these
+        statements are modified. The value of this declaration must contain one
+        or two fields (separated by the double colon "::"). The first field
+        denotes the dependency type, and the second field is the dependency
+        target. If the second field is specified, it will only exclude the
+        dependency to the specified target. Otherwise, it will exclude all
+        dependency to the specified type. The following dependency types are
+        supported:
+
+        <a name="dependency-types"></a>
+
+        <table summary="dependency types" border="1">
+          <tr>
+            <th>Dependency type</th>
+
+            <th>Description</th>
+          </tr>
+
+          <tr>
+            <th>USE</th>
+
+            <td>The dependency target is a Fortran module.</td>
+          </tr>
+
+          <tr>
+            <th>INTERFACE</th>
+
+            <td>The dependency target is a Fortran 9X interface block file.</td>
+          </tr>
+
+          <tr>
+            <th>INC</th>
+
+            <td>The dependency target is a Fortran INCLUDE file.</td>
+          </tr>
+
+          <tr>
+            <th>H</th>
+
+            <td>The dependency target is a pre-processor #include header
+            file.</td>
+          </tr>
+
+          <tr>
+            <th>OBJ</th>
+
+            <td>The dependency target is a compiled binary object file.</td>
+          </tr>
+
+          <tr>
+            <th>EXE</th>
+
+            <td>The dependency target is an executable binary or script.</td>
+          </tr>
+        </table>
+
+        <p>N.B. The following dependency targets are in the default list of
+        excluded dependencies:</p>
+
+        <ul>
+          <li>
+            Intrinsic Fortran modules:
+
+            <ul>
+              <li>USE::ISO_C_BINDING</li>
+
+              <li>USE::IEEE_EXCEPTIONS</li>
+
+              <li>USE::IEEE_ARITHMETIC</li>
+
+              <li>USE::IEEE_FEATURES</li>
+            </ul>
+          </li>
+
+          <li>
+            Intrinsic Fortran subroutines:
+
+            <ul>
+              <li>OBJ::CPU_TIME</li>
+
+              <li>OBJ::GET_COMMAND</li>
+
+              <li>OBJ::GET_COMMAND_ARGUMENT</li>
+
+              <li>OBJ::GET_ENVIRONMENT_VARIABLE</li>
+
+              <li>OBJ::MOVE_ALLOC</li>
+
+              <li>OBJ::MVBITS</li>
+
+              <li>OBJ::RANDOM_NUMBER</li>
+
+              <li>OBJ::RANDOM_SEED</li>
+
+              <li>OBJ::SYSTEM_CLOCK</li>
+            </ul>
+          </li>
+
+          <li>
+            Dummy declarations:
+
+            <ul>
+              <li>OBJ::NONE</li>
+
+              <li>EXE::NONE</li>
+            </ul>
+          </li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+excl_dep  USE::YourFortranMod
+excl_dep  INTERFACE::HerFortran.interface
+excl_dep  INC::HisFortranInc.inc
+excl_dep  H::TheirHeader.h
+excl_dep  OBJ
+excl_dep  EXE
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">INFILE_EXT::&lt;ext&gt;</th>
+
+      <th>Description</th>
+
+      <td>
+        This declaration is used to re-register particular file name
+        extensions &lt;ext&gt; to associate with different file types. The
+        value of the declaration is a list of type flags delimited by the
+        double colon "::". Each type flag is used internally to describe the
+        nature of the file. For example, a Fortran free source form containing
+        a main program is registered as
+        <tt>"FORTRAN::FORTRAN9X::SOURCE::PROGRAM"</tt>. The following is a
+        list of type flags that are currently in-use (or <span class="gray">*
+        reserved</span>) by the build system:
+
+        <a name="infile-ext-types"></a>
+
+        <table summary="input file extension type flags" border="1">
+          <tr>
+            <th>Flag</th>
+
+            <th>Description</th>
+          </tr>
+
+          <tr>
+            <td class="mono">SOURCE</td>
+
+            <td>a source file containing program code of a supported language
+            (currently Fortran, FPP, C and CPP).</td>
+          </tr>
+
+          <tr>
+            <td class="mono">INCLUDE</td>
+
+            <td>an include file containing program code of a supported language
+            (currently Fortran, FPP, C and CPP).</td>
+          </tr>
+
+          <tr>
+            <td class="mono">FORTRAN</td>
+
+            <td>a file containing Fortran code.</td>
+          </tr>
+
+          <tr>
+            <td class="mono">FORTRAN9X</td>
+
+            <td>a file containing the Fortran free source form. This word must be
+            used in conjunction with the word "FORTRAN".</td>
+          </tr>
+
+          <tr>
+            <td class="mono">FPP</td>
+
+            <td>a file containing Fortran code requiring pre-processing.</td>
+          </tr>
+
+          <tr>
+            <td class="mono">FPP9X</td>
+
+            <td>a file containing Fortran free source form requiring
+            pre-processing. This word must be used in conjunction with the word
+            "FPP".</td>
+          </tr>
+
+          <tr>
+            <td class="mono">C</td>
+
+            <td>a file containing C code.</td>
+          </tr>
+
+          <tr>
+            <td class="mono">CPP</td>
+
+            <td>a file containing CPP include header.</td>
+          </tr>
+
+          <tr>
+            <td class="mono">INTERFACE</td>
+
+            <td>a file containing a Fortran 9X interface block.</td>
+          </tr>
+
+          <tr>
+            <td class="mono">PROGRAM</td>
+
+            <td>a file containing a main program.</td>
+          </tr>
+
+          <tr>
+            <td class="mono">MODULE</td>
+
+            <td>a file containing a Fortran 9X module.</td>
+          </tr>
+
+          <tr>
+            <td class="mono">BINARY</td>
+
+            <td>a binary file.</td>
+          </tr>
+
+          <tr>
+            <td class="mono">EXE</td>
+
+            <td>an executable file. This word must be used in conjunction with
+            the word "BINARY".</td>
+          </tr>
+
+          <tr>
+            <td class="mono">LIB</td>
+
+            <td>an archive library. This word must be used in conjunction with
+            the word "BINARY".</td>
+          </tr>
+
+          <tr>
+            <td class="mono">SCRIPT</td>
+
+            <td>a file containing source code of a scripting language.</td>
+          </tr>
+
+          <tr>
+            <td class="mono">PVWAVE</td>
+
+            <td>a file containing executable PVWAVE scripts. This word must be
+            used in conjunction with the word "SCRIPT".</td>
+          </tr>
+
+          <tr>
+            <td class="mono">SQL</td>
+
+            <td>a file containing SQL scripts. This word must be used in
+            conjunction with the word "SCRIPT".</td>
+          </tr>
+
+          <tr>
+            <td class="mono">GENLIST</td>
+
+            <td>a GEN List file.</td>
+          </tr>
+
+          <tr class="gray">
+            <td class="mono">OBJ</td>
+
+            <td>(* reserved) an object file. This word must be used in
+            conjunction with the word "BINARY".</td>
+          </tr>
+
+          <tr class="gray">
+            <td class="mono">SHELL</td>
+
+            <td>(* reserved) a file containing executable shell scripts. This
+            word must be used in conjunction with the word "SCRIPT".</td>
+          </tr>
+
+          <tr class="gray">
+            <td class="mono">PERL</td>
+
+            <td>(* reserved) a file containing executable Perl scripts. This
+            word must be used in conjunction with the word "SCRIPT".</td>
+          </tr>
+
+          <tr class="gray">
+            <td class="mono">PYTHON</td>
+
+            <td>(* reserved) a file containing executable Python scripts. This
+            word must be used in conjunction with the word "SCRIPT".</td>
+          </tr>
+
+          <tr class="gray">
+            <td class="mono">TCL</td>
+
+            <td>(* reserved) a file containing executable TCL scripts. This
+            word must be used in conjunction with the word "SCRIPT".</td>
+          </tr>
+        </table>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+infile_ext::h90  CPP::INCLUDE
+infile_ext::inc  FORTRAN::FORTRAN9X::INCLUDE
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">OUTFILE_EXT::&lt;type&gt;</th>
+
+      <th>Description</th>
+
+      <td>
+        This declaration is used to re-register the output file extension
+        for a particular &lt;type&gt; of output files. The value must be a
+        valid file extension. The following is a list of output file types
+        in-use by the build system:
+
+        <a name="outfile-ext-types"></a>
+
+        <table summary="output file extension types" border="1">
+          <tr>
+            <th>Type</th>
+
+            <th>Description</th>
+
+            <th>Default</th>
+          </tr>
+
+          <tr>
+            <td class="mono">MK</td>
+
+            <td>dependency files, <em>Makefile</em> fragments</td>
+
+            <td class="mono">.mk</td>
+          </tr>
+
+          <tr>
+            <td class="mono">OBJ</td>
+
+            <td>compiled object files</td>
+
+            <td class="mono">.o</td>
+          </tr>
+
+          <tr>
+            <td class="mono">MOD</td>
+
+            <td>compiled Fortran module information files</td>
+
+            <td class="mono">.mod</td>
+          </tr>
+
+          <tr>
+            <td class="mono">EXE</td>
+
+            <td>binary executables</td>
+
+            <td class="mono">.exe</td>
+          </tr>
+
+          <tr>
+            <td class="mono">DONE</td>
+
+            <td>"done" files for compiled source</td>
+
+            <td class="mono">.done</td>
+          </tr>
+
+          <tr>
+            <td class="mono">IDONE</td>
+
+            <td>"done" files for included source</td>
+
+            <td class="mono">.idone</td>
+          </tr>
+
+          <tr>
+            <td class="mono">FLAGS</td>
+
+            <td>"flags" files, compiler flags config</td>
+
+            <td class="mono">.flags</td>
+          </tr>
+
+          <tr>
+            <td class="mono">INTERFACE</td>
+
+            <td>interface files for F9X standalone subroutines/functions</td>
+
+            <td class="mono">.interface</td>
+          </tr>
+
+          <tr>
+            <td class="mono">LIB</td>
+
+            <td>archive object library</td>
+
+            <td class="mono">.a</td>
+          </tr>
+
+          <tr>
+            <td class="mono">TAR</td>
+
+            <td>TAR archive</td>
+
+            <td class="mono">.tar</td>
+          </tr>
+        </table>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+# Output F9X interface files will now have ".foo" extension
+outfile_ext::interface  .foo
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">INC</th>
+
+      <th>Description</th>
+
+      <td>This declares the name of a file containing build configuration. The
+      lines in the declared file will be included inline to the current build
+      configuration file.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+inc  ~frva/var_stable_22.0/cfg/bld.cfg
+# ... and then your changes ...
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">USE</th>
+
+      <th>Description</th>
+
+      <td>This declares a pre-compiled build, which the current build is
+      dependent on. The value must be must be either the configuration file or
+      the root directory of a successful build. Output of the pre-compiled
+      build, the build tools, the exclude dependency declarations, the file
+      type registers declarations are automatically inherited from the
+      pre-compiled build. Source directories, build targets and pre-processing
+      stage declarations may be inherited depending on the INHERIT
+      declarations. (If you have a USE declaration in an extraction, the
+      resulting build configuration file will contain an automatic USE
+      declaration, which expects a pre-compiled build at the destination of
+      the extraction.)</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+# Use VAR build 22.0
+USE  ~frva/var_22.0
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">INHERIT::&lt;name&gt;[::&lt;pcks&gt;]</th>
+
+      <th>Description</th>
+
+      <td>This declares whether build targets (&lt;name&gt; = "target"),
+      source directories (&lt;name&gt; = "src") and pre-processing stage
+      declarations (&lt;name&gt; = "pp") are inherited from pre-compiled builds
+      declared by the USE statement. By default, source directories and
+      pre-processing stage declarations are inherited from pre-compiled
+      builds, while build targets are not. Use the value 1 to switch on
+      inheritance, or 0 to switch off. For source directories and
+      pre-processing stage declarations, the name of a sub-package
+      &lt;pcks&gt; can be specified. If a sub-package pcks is specified, the
+      declaration applies only to the files and directories under the
+      sub-package. Otherwise, the declaration applies globally.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+inherit::target   1
+inherit::src      0
+inherit::pp::gen  0
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">%&lt;name&gt;</th>
+
+      <th>Description</th>
+
+      <td>%&lt;name&gt; declares an internal variable &lt;name&gt; that
+      can later be re-used.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+%my_variable  foo
+src::bar      %my_variable
+src::egg      %my_variable
+src::ham      %my_variable
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+  </table>
+
+  <p><a name="tools-list"></a>The following is a list of &lt;label&gt; fields
+  that can be used with a TOOL declaration. Those marked with an asterisk (*)
+  accept declarations at sub-package levels.</p>
+
+  <table class="pad" summary="list of tools" width="100%" border="1">
+    <tr>
+      <th>Label</th>
+
+      <th>Description</th>
+
+      <th>Default</th>
+    </tr>
+
+    <tr>
+      <th>FC</th>
+
+      <td>The Fortran compiler.</td>
+
+      <td class="mono">"f90"</td>
+    </tr>
+
+    <tr>
+      <th>FFLAGS *</th>
+
+      <td>Options used by the Fortran compiler.</td>
+
+      <td class="mono">""</td>
+    </tr>
+
+    <tr>
+      <th>FC_COMPILE</th>
+
+      <td>The option used by the Fortran compiler to suppress the
+      linking stage.</td>
+
+      <td class="mono">"-c"</td>
+    </tr>
+
+    <tr>
+      <th>FC_INCLUDE</th>
+
+      <td>The option used by the Fortran compiler to specify the
+      "include" search path.</td>
+
+      <td class="mono">"-I"</td>
+    </tr>
+
+    <tr>
+      <th>FC_DEFINE</th>
+
+      <td>The option used by the Fortran compiler to define a
+      pre-processor definition macro.</td>
+
+      <td class="mono">"-D"</td>
+    </tr>
+
+    <tr>
+      <th>FC_OUTPUT</th>
+
+      <td>The option used by the Fortran compiler to specify the output
+      file name.</td>
+
+      <td class="mono">"-o"</td>
+    </tr>
+
+    <tr>
+      <th>CC</th>
+
+      <td>The C compiler.</td>
+
+      <td class="mono">"cc"</td>
+    </tr>
+
+    <tr>
+      <th>CFLAGS *</th>
+
+      <td>Options used by the C compiler.</td>
+
+      <td class="mono">""</td>
+    </tr>
+
+    <tr>
+      <th>CC_COMPILE</th>
+
+      <td>The option used by the C compiler to suppress the
+      linking stage.</td>
+
+      <td class="mono">"-c"</td>
+    </tr>
+
+    <tr>
+      <th>CC_INCLUDE</th>
+
+      <td>The option used by the C compiler to specify the
+      "include" search path.</td>
+
+      <td class="mono">"-I"</td>
+    </tr>
+
+    <tr>
+      <th>CC_DEFINE</th>
+
+      <td>The option used by the C compiler to define a
+      pre-processor definition macro.</td>
+
+      <td class="mono">"-D"</td>
+    </tr>
+
+    <tr>
+      <th>CC_OUTPUT</th>
+
+      <td>The option used by the C compiler to specify the output
+      file name.</td>
+
+      <td class="mono">"-o"</td>
+    </tr>
+
+    <tr>
+      <th>LD *</th>
+
+      <td>Name of the linker or loader for linking object files into an
+      executable.</td>
+
+      <td class="mono">"ld"</td>
+    </tr>
+
+    <tr>
+      <th>LDFLAGS *</th>
+
+      <td>The flags used by the linker or loader.</td>
+
+      <td class="mono">""</td>
+    </tr>
+
+    <tr>
+      <th>LD_OUTPUT</th>
+
+      <td>The option used by the linker or loader for the output file name
+      (other than the default "a.out").</td>
+
+      <td class="mono">"-o"</td>
+    </tr>
+
+    <tr>
+      <th>LD_LIBSEARCH</th>
+
+      <td>The option used by the linker or loader for specifying the
+      search path for link libraries.</td>
+
+      <td class="mono">"-L"</td>
+    </tr>
+
+    <tr>
+      <th>LD_LIBLINK</th>
+
+      <td>The option used by the linker or loader command for linking
+      with a library.</td>
+
+      <td class="mono">"-l"</td>
+    </tr>
+
+    <tr>
+      <th>AR</th>
+
+      <td>The archive command.</td>
+
+      <td class="mono">"ar"</td>
+    </tr>
+
+    <tr>
+      <th>ARFLAGS</th>
+
+      <td>The options used for the archive command to create a
+      library.</td>
+
+      <td class="mono">"rs"</td>
+    </tr>
+
+    <tr>
+      <th>FPP</th>
+
+      <td>The Fortran pre-processor command.</td>
+
+      <td class="mono">"cpp"</td>
+    </tr>
+
+    <tr>
+      <th>FPPKEYS *</th>
+
+      <td>The Fortran pre-processor will pre-define each word in this
+      setting as a macro.</td>
+
+      <td class="mono">""</td>
+    </tr>
+
+    <tr>
+      <th>FPPFLAGS *</th>
+
+      <td>The options used by the Fortran pre-processor.</td>
+
+      <td class="mono">"-P -traditional"</td>
+    </tr>
+
+    <tr>
+      <th>FPP_DEFINE</th>
+
+      <td>The option used by the Fortran pre-processor to define a
+      macro.</td>
+
+      <td class="mono">"-D"</td>
+    </tr>
+
+    <tr>
+      <th>FPP_INCLUDE</th>
+
+      <td>The option used by the Fortran pre-processor to specify the
+      "include" search path.</td>
+
+      <td class="mono">"-I"</td>
+    </tr>
+
+    <tr>
+      <th>CPP</th>
+
+      <td>The C pre-processor command.</td>
+
+      <td class="mono">"cpp"</td>
+    </tr>
+
+    <tr>
+      <th>CPPKEYS *</th>
+
+      <td>The C pre-processor will pre-define each word in this
+      setting as a macro.</td>
+
+      <td class="mono">""</td>
+    </tr>
+
+    <tr>
+      <th>CPPFLAGS *</th>
+
+      <td>The options used by the C pre-processor.</td>
+
+      <td class="mono">"-C"</td>
+    </tr>
+
+    <tr>
+      <th>CPP_DEFINE</th>
+
+      <td>The option used by the C pre-processor to define a
+      macro.</td>
+
+      <td class="mono">"-D"</td>
+    </tr>
+
+    <tr>
+      <th>CPP_INCLUDE</th>
+
+      <td>The option used by the C pre-processor to specify the
+      "include" search path.</td>
+
+      <td class="mono">"-I"</td>
+    </tr>
+
+    <tr>
+      <th>MAKE</th>
+
+      <td>The "make" command.</td>
+
+      <td class="mono">"make"</td>
+    </tr>
+
+    <tr>
+      <th>MAKEFLAGS</th>
+
+      <td>The options used by the "make" command</td>
+
+      <td class="mono">""</td>
+    </tr>
+
+    <tr>
+      <th>MAKE_SILENT</th>
+
+      <td>The option used by the "make" command to specify silent
+      operation.</td>
+
+      <td class="mono">"-s"</td>
+    </tr>
+
+    <tr>
+      <th>MAKE_JOB</th>
+
+      <td>The option used by the "make" command to specify the number
+      jobs to run simultaneously.</td>
+
+      <td class="mono">"-j"</td>
+    </tr>
+
+    <tr>
+      <th>GENINTERFACE *</th>
+
+      <td>The command/method for generating interface for Fortran 9X
+      standalone subroutines/functions. Supported values are "ECMWF",
+      "f90aib" and "none". (The keyword "none" is used to switch off
+      interface generation.)</td>
+
+      <td class="mono">"ECMWF"</td>
+    </tr>
+
+    <tr>
+      <th>INTERFACE *</th>
+
+      <td>Generate Fortran 9X interface files with root names according to
+      either the root name of the source "file" or the name of the "program"
+      unit.</td>
+
+      <td class="mono">"file"</td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th>Description</th>
+
+      <th>Default</th>
+    </tr>
+  </table>
+
+  <p class="gray">The following declarations are for reference only. They
+  should not be used in normal operations of the FCM build system:</p>
+
+  <table class="pad" summary="Unused declarations in build configuration file"
+  width="100%" border="1">
+    <tr class="gray">
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::BIN</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      "bin" directory, container of executable files created by the build.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::bin  $HOME/my_build/bin
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::BLD</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      build directory, container of the <em>Makefile</em> and its fragments
+      created by the build system.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::bld  $HOME/my_build/bld
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::CACHE</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      cache directory, container of internal cache files used by the build
+      system.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::cache $HOME/my_build/.cache
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::CFG</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      configuration directory, container of the build configuration file. Not
+      created by the build system.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::cfg $HOME/my_build/cfg
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::DONE</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      "done" file directory, container of dummy "done" files created by the
+      build process. A "done" file is used to indicate that all the external
+      objects of an object files are compiled and ready to be used by the link
+      process.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::done $HOME/my_build/done
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::ETC</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      miscellaneous file directory, container of "data" files. "Data" files
+      are files in the source sub-package without a registered type. It is
+      possible for the user to tell the build system to copy all "data" files
+      in a sub-package to this directory by "building" a dummy sub-package
+      data file target.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::etc $HOME/my_build/etc
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::FLAGS</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      "flags" file directory, container of dummy "flags" files created by the
+      build process. A "flags" file is used to indicate to <em>make</em> that
+      the compiler flags for a source file or a container package has
+      changed.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::flags $HOME/my_build/flags
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::INC</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      include directory, container of "include" files such as pre-processor
+      header files, Fortran INCLUDE files, Fortran 9X interface files, and
+      Fortran compiled module information files.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::inc $HOME/my_build/inc
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::LIB</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      library directory, container of object library achive files created by
+      the build.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::lib $HOME/my_build/lib
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::OBJ</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      object directory, container of compiled object files created by the
+      build process.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::obj $HOME/my_build/obj
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::PPSRC</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      pre-processed source directory, container of pre-processed source files
+      created by the build process.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::ppsrc $HOME/my_build/ppsrc
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::SRC</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      source directory, container of the source tree. Not created by the build
+      system.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::src $HOME/my_build/src
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DIR::TMP</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      temporary directory, container of temporary files used by the wrapper to
+      the compiler and linker.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dir::tmp $HOME/my_build/tmp
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+  </table>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/user_guide/annex_ext_cfg.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/user_guide/annex_ext_cfg.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/user_guide/annex_ext_cfg.html	(revision 1665)
@@ -0,0 +1,643 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide Annex: Declarations in FCM extract configuration
+  file</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide Annex">
+  <meta name="keywords" content="FCM, user guide, annex">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; Annex: Declarations in
+    FCM extract configuration file
+  </address>
+
+  <h1>Annex:<br>
+  Declarations in FCM extract configuration file</h1>
+
+  <p>The following is a list of supported declarations for the configuration
+  file used by the FCM extract system. Unless otherwise stated, the fields in
+  all declaration labels are not case sensitive.</p>
+
+  <table class="pad" summary="Declarations in extract configuration file"
+  width="100%" border="1">
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">CFG::TYPE</th>
+
+      <th>Description</th>
+
+      <td>The configuration file type, the value should always be "ext" for an
+      extract configuration file. This declaration is compulsory for all
+      extract configuration files.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+cfg::type  ext
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">CFG::VERSION</th>
+
+      <th>Description</th>
+
+      <td>The file format version, currently "1.0" - a version is included so
+      that we shall be able to read the configuration file correctly should we
+      decide to change its format in the future.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+cfg::version  1.0
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">DEST::ROOTDIR</th>
+
+      <th>Description</th>
+
+      <td>The "root" path of the destination of this extraction. This
+      declaration is compulsory for all extract configuration files.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+dest::rootdir  $HOME/project/my_project
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">RDEST::MACHINE</th>
+
+      <th>Description</th>
+
+      <td>The destination machine for this extraction. If set, the extraction
+      will be mirrored to a location on this machine.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+rdest::machine  tx01
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">RDEST::LOGNAME</th>
+
+      <th>Description</th>
+
+      <td>The login name of the user on the remote destination machine. If not
+      specified, the current login name of the user on the local platform is
+      assumed.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+rdest::logname  frva
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">RDEST::ROOTDIR</th>
+
+      <th>Description</th>
+
+      <td>The "root" path of the remote destination of this extraction. This
+      declaration is compulsory if this extraction requires mirroring to a
+      remote machine.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+rdest::rootdir  /home/nwp/da/frva/project/my_project
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">REPOS::&lt;pck&gt;::&lt;branch&gt;</th>
+
+      <th>Description</th>
+
+      <td>This declares a URL or a local file system path for the container
+      "repository" of a branch named &lt;branch&gt; in a package named
+      &lt;pck&gt;. The package name &lt;pck&gt; must be the name of a
+      top-level package (i.e. it must not contain the double colon "::"
+      delimiter). The name &lt;branch&gt; is used internally within the
+      extract system, and so is independent of the branch name of the code
+      management system. However, it is usually desirable to use the same name
+      of the actual branch in the code management system. For declaration of a
+      local file system path, the convention is to name the branch "user".
+      Please note that both &lt;pck&gt; and &lt;branch&gt; fields are case
+      sensitive. The declared URL must be a valid Subversion URL or a valid
+      FCM URL keyword.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+repos::var::trunk        fcm:var_tr
+repos::var::r4790_foobar fcm:var_br/frsn/r4790_foobar
+repos::var::user         $HOME/var
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">VERSION::&lt;pck&gt;::&lt;branch&gt;</th>
+
+      <th>Description</th>
+
+      <td>The revision to be used for the URL of &lt;branch&gt; in the package
+      &lt;pck&gt;. If not specified, the revision defaults to "HEAD". Please
+      note that if the delcared "repository" is in the local file system, this
+      declaration must not be used. The value of the declaration can be a FCM
+      revision keyword or any revision argument acceptable by Subversion. You
+      can use a valid revision number, a date between a pair of curly brackets
+      (e.g. {"2005-05-01 12:00"}) or the keyword "HEAD". However, please do
+      not use the keywords "BASE", "COMMITTED" or "PREV" as these are reserved
+      for working copy only. Again, please note that both &lt;pck&gt; and
+      &lt;branch&gt; fields are case sensitive. </td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+# Declare the revision with the FCM revision keyword "vn22.0"
+version::var::trunk        vn22.0
+# Declare the revision with a {date}
+version::var::r4790_foobar {2006-01-01}
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">SRC::&lt;pcks&gt;::&lt;branch&gt;</th>
+
+      <th>Description</th>
+
+      <td>This declares a source directory for the sub-package &lt;pcks&gt;
+      of &lt;branch&gt;. If the repository is declared as a URL, the source
+      directory must be quoted as a relative path to the URL. If the
+      repository is declared as a path in the local file system, the source
+      directory can be declared as either a relative path to the "repository"
+      or a full path. If the source directory is a relative path and
+      &lt;pcks&gt; is a top-level package, the full name of the sub-package
+      will be determined automatically using the directory names of the
+      relative path as the name of the sub-packages. If the source directory
+      is a full path, the full sub-package name must be specified. The name of
+      the sub-package determines the destination path of the source directory
+      in the extraction.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+src::var::trunk                   code/VarMod_PF
+src::var::code::VarMod_PF::user   $HOME/var/code/VarMod_PF 
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">EXPSRC::&lt;pcks&gt;::&lt;branch&gt;</th>
+
+      <th>Description</th>
+
+      <td>This declares an expandable source directory for the sub-package
+      &lt;pcks&gt; of &lt;branch&gt;. This declaration is essentially the
+      same as the SRC declaration, except that the system will attempt to
+      search recursively for sub-directories within the declared source
+      directory.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+expsrc::var::trunk code
+expsrc::var::user  code
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">BLD::&lt;fields&gt;</th>
+
+      <th>Description</th>
+
+      <td>Declare a build configuration file declaration. The label
+      &lt;fields&gt; is the label of the declaration. On a successful
+      extraction, &lt;fields&gt; will be added to the build configuration
+      file. Please note that some of the &lt;fields&gt; may be case
+      sensitive.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+bld::name     var_stable_22.0
+bld::target   VarScr_AnalysePF
+bld::tool::fc sxmpif90
+bld::tool::cc sxmpic++
+# ... and so on ...
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">USE</th>
+
+      <th>Description</th>
+
+      <td>The declares the location of a previous successful extraction, which
+      the current extraction will base on. If the previous extraction is also
+      a build, the subsequent invocation of the build system on the current
+      extraction will automatically trigger an inherited incremental build
+      based on that build.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+use  ~frva/var_stable_22.0
+# ... and then the settings for your current extraction ...
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">INC</th>
+
+      <th>Description</th>
+
+      <td>This declares the name of a file containing extract configuration.
+      The lines in the declared file will be included inline to the current
+      extract configuration file.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+inc  ~frva/var_stable_22.0/cfg/ext.cfg
+# ... and then your changes ...
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">OVERRIDE</th>
+
+      <th>Description</th>
+
+      <td>If a file is modified by two different branches, this flag can be
+      used to specify either to allow the later branch to override (1) the
+      earlier one or to fail (0) the extraction. If not specified, the default
+      is to fail (0).</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+override  1
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">MIRROR</th>
+
+      <th>Description</th>
+
+      <td>The extract system can mirror the extracted source to a remote
+      machine. Currently, it does this using either the <em>rdist</em> or the
+      <em>rsync</em> command. The default is <em>rsync</em>. This declaration
+      can be used to switch to using <em>rdist</em>.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+mirror  rdist
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">%&lt;name&gt;</th>
+
+      <th>Description</th>
+
+      <td>%&lt;name&gt; declares an internal variable &lt;name&gt; that
+      can later be re-used.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+%my_variable      foo
+src::bar::trunk   %my_variable
+src::egg::trunk   %my_variable
+src::ham::trunk   %my_variable
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+  </table>
+
+  <p class="gray">The following declarations are for reference only. They
+  should not be used in normal operations of the FCM extract system:</p>
+
+  <table class="pad" summary="Unused declarations in extract configuration file"
+  width="100%" border="1">
+    <tr class="gray">
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DEST::SRCDIR</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      "source" path of the desintation of this extraction. Source directories
+      will be extracted to this directory. The default is to extract source
+      directories to the "src/" sub-directory under the root path of the
+      destination.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dest::srcdir  $HOME/project/my_project/src
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DEST::CFGDIR</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      "configuration" path of the destination of this extraction.
+      Configuration files such as the expanded extraction configuration file
+      and the build configuration file will be written in this location. The
+      default is to send the configuration files to the "cfg/" sub-directory
+      under the root path of the destination.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dest::cfgdir  $HOME/project/my_project/cfg
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DEST::CACHEDIR</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      cache directory used by this extraction. Source directories and other
+      configuration files will normally be extracted and written to the cache
+      directory before being copied to the destination. This ensures fast
+      subsequent incremental extractions. It also reduces the load on the
+      repository server. The default is use the ".cache/" sub-directory under
+      the root path of the destination.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dest::cachedir  $HOME/project/my_project/.cache
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DEST::BLD_CFG</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      destination path of the build configuration file. By default, this file
+      will be named "bld.cfg" and will be placed under the configuration
+      directory, i.e. "cfg/bld.cfg" under the root path of the
+      destination.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dest::bld_cfg  $HOME/project/my_project/cfg/bld.cfg
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">DEST::EXT_CFG</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      destination path of the output expanded extract configuration file. By
+      default, this file will be named "ext.cfg" and will be placed under the
+      configuration directory, i.e. "cfg/ext.cfg" under the root path of the
+      destination.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+dest::ext_cfg  $HOME/project/my_project/cfg/ext.cfg
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">RDEST::SRCDIR</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      "source" path of the remote desintation of this extraction. Source
+      directories will be mirrored to this directory. The default is to mirror
+      source directories to the "src/" sub-directory under the root path of the
+      remote destination.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+rdest::srcdir  /home/nwp/da/frva/project/my_project/src
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">RDEST::CFGDIR</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      "configuration" path of the remote destination of this extraction.
+      Configuration files such as the expanded extraction configuration file
+      and the build configuration file are mirrored in this location. The
+      default is to send the configuration files to the "cfg/" sub-directory
+      under the root path of the remote destination.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+rdest::cfgdir  /home/nwp/da/frva/project/my_project/cfg
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">RDEST::BLD_CFG</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      remote destination path of the build configuration file. By default, this
+      file will be named "bld.cfg" and will be placed under the configuration
+      directory, i.e. "cfg/bld.cfg" under the root path of the remote
+      destination.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+rdest::bld_cfg  /home/nwp/da/frva/project/my_project/cfg/bld.cfg
+</pre>
+      </td>
+    </tr>
+
+    <tr class="gray">
+      <th rowspan="2">RDEST::EXT_CFG</th>
+
+      <th>Description</th>
+
+      <td>This declaration is optional and is not normally required. It is the
+      remote destination path of the output expanded extract configuration file.
+      By default, this file will be named "ext.cfg" and will be placed under the
+      configuration directory, i.e. "cfg/ext.cfg" under the root path of the
+      remote destination.</td>
+    </tr>
+
+    <tr class="gray">
+      <th>Example</th>
+
+      <td>
+        <pre>
+rdest::ext_cfg  /home/nwp/da/frva/project/my_project/cfg/ext.cfg
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/user_guide/annex_fcm_cfg.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/user_guide/annex_fcm_cfg.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/user_guide/annex_fcm_cfg.html	(revision 1665)
@@ -0,0 +1,187 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide Annex: Declarations in FCM central/user
+  configuration file</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide Annex">
+  <meta name="keywords" content="FCM, user guide, annex">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; Annex: Declarations in
+    FCM central/user configuration file
+  </address>
+
+  <h1>Annex:<br>
+  Declarations in FCM central/user configuration file</h1>
+
+  <p>Please note that setting labels in both the central and the user
+  configuration files are case insensitive.</p>
+
+  <table class="pad" summary="Declarations in FCM configuration file"
+  width="100%" border="1">
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">SET::URL::&lt;pck&gt;<br>
+      <span class="gray">SET::REPOS::&lt;pck&gt;</span>
+      </th>
+
+      <th>Description</th>
+
+      <td>This declares a URL keyword for the package &lt;pck&gt;. The value of
+      the declaration must be a valid Subversion &lt;URL&gt;. Once declared, the
+      URL keyword &lt;pck&gt; will be associated with the specified URL. In
+      subsequent invocations of the "fcm" command, the following expansion may
+      take place:
+
+        <ul>
+          <li>"fcm:&lt;pck&gt;": replaced by "&lt;URL&gt;".</li>
+
+          <li>"fcm:&lt;pck&gt;_tr" or "fcm:&lt;pck&gt;-tr": replaced by
+          "&lt;URL&gt;/trunk"
+
+          <li>"fcm:&lt;pck&gt;_br" or "fcm:&lt;pck&gt;-br": replaced by
+          "&lt;URL&gt;/branches"
+
+          <li>"fcm:&lt;pck&gt;_tg" or "fcm:&lt;pck&gt;-tg": replaced by
+          "&lt;URL&gt;/tags"
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+# Associate "var" with "svn://server/VAR_svn/var"
+set::url::var  svn://server/VAR_svn/var
+
+# "fcm:var" is now the same as "svn://server/VAR_svn/var"
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">SET::REVISION::&lt;pck&gt;::&lt;keyword&gt;</th>
+
+      <th>Description</th>
+
+      <td>This declares &lt;keyword&gt; to be the revision number for the
+      package &lt;pck&gt;. The &lt;keyword&gt; string can contain any
+      characters except spaces. It must not contain only digits (as digits are
+      treated as revision numbers). It must not be the Subversion revision
+      keywords "HEAD", "BASE", "COMMITTED" and "PREV". It cannot begin and end
+      with a pair of curly brackets (as this will be parsed as a revision
+      date). The package &lt;pck&gt; must be associated with a URL using the
+      SET::URL::&lt;pck&gt; declaration described above before this
+      declaration can make sense. Once defined, &lt;keyword&gt; can be used
+      anywhere in place the defined revision number.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+set::revision::var::v22.0  8410
+
+# E.g. "fcm list -r v22.0 fcm:var" is now the same as
+#      "fcm list -r 8410 fcm:var".
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">SET::TRAC::&lt;pck&gt;</th>
+
+      <th>Description</th>
+
+      <td>This declares a Trac browser URL that corresponds to the Subversion
+      URL declared using SET::URL::&lt;pck&gt;.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+set::trac::var  http://server/Trac/VAR/browser/VAR
+
+# E.g. "fcm trac fcm:var" will launch the web browser to view above.
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">SET::MISC::WEB_BROWSER</th>
+
+      <th>Description</th>
+
+      <td>This declares a default web browser that can be used by some FCM
+      commands to browse files and documents online. The default is
+      "firefox".</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+# Use Netscape instead of Firefox
+set::misc::web_browser  netscape
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">INC</th>
+
+      <th>Description</th>
+
+      <td>This declares the name of a file containing user configuration. The
+      lines in the declared file will be included inline.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+inc  ~fred/etc/fcm.cfg
+# ... and then your changes ...
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+  </table>
+
+  <p>N.B. almost all settings in the Fcm::Config module can be modified using
+  the central/user configuration file. However, most users should only ever
+  need to use the above.</p>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/user_guide/annex_pck_cfg.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/user_guide/annex_pck_cfg.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/user_guide/annex_pck_cfg.html	(revision 1665)
@@ -0,0 +1,183 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide Annex: Declarations in FCM build package
+  configuration file</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide Annex">
+  <meta name="keywords" content="FCM, user guide, annex">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; Annex: Declarations in
+    FCM build package configuration file
+  </address>
+
+  <h1>Annex:<br>
+  Declarations in FCM build package configuration file</h1>
+
+  <p>The following is a list of supported declarations for package
+  configuration files. The package configuration is used by the build system.
+  It must be stored in a file called <tt>@PACKAGE.cfg</tt> in a source
+  directory. The labels in all declarations in a package configuration file
+  contain two fields delimited by the double colon "::". The first field is the
+  name of the label, which is case insensitive. The second field is the name
+  of a file, which the declaration is associated with.</p>
+
+  <table class="pad" summary="Declarations in build package configuration file"
+  width="100%" border="1">
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+
+    <tr>
+      <th rowspan="2">TYPE::<em>file</em></th>
+
+      <th>Description</th>
+
+      <td>This declares the type of <em>file</em>. The value of this
+      declaration is a list of type flags delimited by the double colon "::".
+      Each type flag is used internally to describe the nature of the file.
+      Supported flags are the same as those used in the INFILE_EXT
+      declarations in the build configuration file. For a list of these flags,
+      please see the <a href="annex_bld_cfg.html#infile-ext-types">Input file
+      extension type flags table</a> of the <a href="annex_bld_cfg.html">FCM
+      System User Guide &gt; Annex: Declarations in FCM build configuration
+      file</a> document.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+# Declare a Fortran 9X program source file
+type::MyFortranProg.f90  FORTRAN::FORTRAN9X::SOURCE::PROGRAM
+
+# Declare a target to build a shared object library
+type::libbooks.a         BINARY::LIB
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">SCAN::<em>file</em></th>
+
+      <th>Description</th>
+
+      <td>This declares a flag to determine whether <em>file</em> needs to be
+      scanned for dependency. Set the value to 1 to switch on, and 0 to switch
+      off. If <em>file</em> is declared a shared library, this flag is
+      automatically set to 0. For all other files, this flag is automatically
+      set to 1.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+scan::MyFortranProg.f90  0
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">TARGET::<em>file</em></th>
+
+      <th>Description</th>
+
+      <td>This declares the executable name of <em>file</em> if it is a C or
+      Fortran program. If not set, the default executable name of a program is
+      the root name (i.e. base name without the file extension) of
+      <em>file</em> suffixed with the file extension ".exe".</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+target::MyFortranProg.f90  hello_world
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">INTNAME::<em>file</em></th>
+
+      <th>Description</th>
+
+      <td>This declares the internal name of <em>file</em> if it contains a
+      Fortran subroutine, function or module. The internal name determines the
+      name of the compiled object file of <em>file</em>. If not set, the
+      default depends on whether the <em>file</em> will be scanned for
+      dependencies. If so, the name of the first program unit will be used as
+      the internal name. Otherwise, the root name of <em>file</em> will be
+      used.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+intname::YourFortranMod.f90  hello_mod
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th rowspan="2">DEP::<em>file</em></th>
+
+      <th>Description</th>
+
+      <td>This declares a dependency target for <em>file</em>. The value of this
+      declaration must contain two fields separated by the double colon "::".
+      The first field denotes the dependency type, and the second field is the
+      dependency target. Supported dependency types are the same as those used
+      in the EXCL_DEP declarations in the build configuration file. For a list
+      of these flags, please see the <a
+      href="annex_bld_cfg.html#dependency-types">dependency types table</a> of
+      the <a href="annex_bld_cfg.html">FCM System User Guide &gt; Annex:
+      Declarations in FCM build configuration file</a> document.</td>
+    </tr>
+
+    <tr>
+      <th>Example</th>
+
+      <td>
+        <pre>
+dep::MyFortranProg.f90  USE::YourFortranMod
+dep::MyFortranProg.f90  INTERFACE::HerFortran.interface
+dep::MyFortranProg.f90  INC::HisFortranInc.inc
+dep::MyFortranProg.f90  H::TheirHeader.h
+dep::MyFortranProg.f90  OBJ::ItsObject.o
+
+dep::libbooks.a         OBJ::MyObject.o
+dep::libbooks.a         OBJ::YourObject.o
+dep::libbooks.a         OBJ::HisObject.o
+dep::libbooks.a         OBJ::HerObject.o
+dep::libbooks.a         OBJ::TheirObject.o
+dep::libbooks.a         OBJ::ItsObject.o
+</pre>
+      </td>
+    </tr>
+
+    <tr>
+      <th>Label</th>
+
+      <th colspan="2">Content</th>
+    </tr>
+  </table>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/user_guide/annex_quick_ref.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/user_guide/annex_quick_ref.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/user_guide/annex_quick_ref.html	(revision 1665)
@@ -0,0 +1,316 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide Annex: Quick reference</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide Annex">
+  <meta name="keywords" content="FCM, user guide, annex">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <script type="text/javascript">
+  <!--
+    document.write ('<address>')
+    document.write ('<a href="index.html">FCM System User Guide</a>')
+    document.write (' &gt; ')
+    document.write ('Annex: Quick reference')
+    document.write ('<\/address>')
+  //-->
+  </script>
+
+  <h1>Annex:<br>
+  Quick reference</h1>
+
+  <p>Note: some sub-commands can be invoked with alternate names. For example,
+  "fcm help" is the same as "fcm ?". In this annex, some favourite alternate
+  names are listed, separated by a pipe, i.e. the above example will be given as
+  "fcm help|?".</p>
+
+  <a name="help"></a><h2>Getting help</h2>
+
+  <table summary="help" width="100%" border="0">
+    <tr>
+      <td>fcm help|?</td>
+
+      <td width="70%">get list of subcommands</td>
+    </tr>
+
+    <tr>
+      <td>fcm help|? SUBCOMMAND</td>
+
+      <td width="70%">get help on SUBCOMMAND</td>
+    </tr>
+  </table>
+
+  <a name="maintaining-wc"></a><h2>Maintaining the working copy</h2>
+
+  <table summary="maintaining-wc" width="100%" border="0">
+    <tr>
+      <td colspan="2">fcm&nbsp;checkout|co&nbsp;[OPTIONS]&nbsp;URL&nbsp;[DEST]</td>
+
+      <td width="70%">Checkout URL (and create a working copy at DEST)</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-r N</td>
+
+      <td width="70%">Checkout revision N of URL</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm info</td>
+
+      <td width="70%">Print working copy information</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm status|st [OPTIONS]</td>
+
+      <td width="70%">Print status of working copy</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-u</td>
+
+      <td width="70%">Show update information</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-v</td>
+
+      <td width="70%">Show verbose information</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm update|up</td>
+
+      <td width="70%">Update working copy with repository changes</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm switch|sw URL</td>
+
+      <td width="70%">Switch your working copy to point to a branch specified by
+      URL</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm commit|ci</td>
+
+      <td width="70%">Commit local changes back into the repository</td>
+    </tr>
+  </table>
+
+  <a name="preparing-changes"></a><h2>Preparing changes</h2>
+
+  <table summary="preparing-changes" width="100%" border="0">
+    <tr>
+      <td colspan="2">fcm diff|di [OPTIONS]</td>
+
+      <td width="70%">Display working copy changes in unified diff format</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-b</td>
+
+      <td width="70%">Show differences relative to the base of the branch</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-g</td>
+
+      <td width="70%">Display working copy changes with a graphical diff
+      tool</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-r N</td>
+
+      <td width="70%">Display working copy changes against revision N</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-t</td>
+
+      <td width="70%">Display differences in Trac, (with -b only)</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm revert [OPTIONS] PATH</td>
+
+      <td width="70%">Restore the file PATH to the pristine copy</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td>-R</td>
+
+      <td width="70%">Descend PATH recursively, restoring any modified files to
+      the pristine copy</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm mkdir [PATH]</td>
+
+      <td width="70%">Add a directory PATH under revision control</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm add [OPTIONS] [PATH]</td>
+
+      <td width="70%">Add PATH under revision control</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-c</td>
+
+      <td width="70%">Check for items not under revision control and add
+      them</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm&nbsp;delete|del|rm&nbsp;[OPTIONS]&nbsp;[PATH]</td>
+
+      <td width="70%">Remove PATH from revision control</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-c</td>
+
+      <td width="70%">Check for missing items and remove them</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm copy|cp SRC DST</td>
+
+      <td width="70%">Duplicate SRC to DST, remembering history</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm&nbsp;move|mv&nbsp;SRC&nbsp;DST</td>
+
+      <td width="70%">Move or rename SRC to DST, remembering history</td>
+    </tr>
+  </table>
+
+  <a name="browse"></a><h2>Browsing</h2>
+
+  <table summary="browse" width="100%" border="0">
+    <tr>
+      <td colspan="2">fcm&nbsp;log&nbsp;[OPTIONS]&nbsp;[TARGET]</td>
+
+      <td width="70%">Show the log message of a TARGET that can either be
+      working copy or URL</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-r N[:M]</td>
+
+      <td width="70%">Show the log message of a range of reivsions</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm list|ls [OPTIONS] [TARGET]</td>
+
+      <td width="70%">List directory entries in TARGET</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-r N</td>
+
+      <td width="70%">List directory entries of revision N</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-v</td>
+
+      <td width="70%">List directory entries in verbose mode</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-R</td>
+
+      <td width="70%">List directory entries recursively down the
+      directories</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm trac [TARGET]</td>
+
+      <td width="70%">Open a WWW browser to browse TARGET with Trac</td>
+    </tr>
+  </table>
+
+  <a name="branch"></a><h2>Branching</h2>
+
+  <table summary="browse" width="100%" border="0">
+    <tr>
+      <td colspan="2">fcm branch|br [OPTIONS] [URL]</td>
+
+      <td width="70%">Show branch information of URL or local working
+      copy</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-d</td>
+
+      <td width="70%">Show branch information and delete the branch</td>
+    </tr>
+
+    <tr>
+      <td>&nbsp;</td>
+
+      <td width="18%">-c -n NAME</td>
+
+      <td width="70%">Create a branch</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm merge [SOURCE]</td>
+
+      <td width="70%">Merge changes from SOURCE to your working copy</td>
+    </tr>
+
+    <tr>
+      <td colspan="2">fcm conflicts|cf</td>
+
+      <td width="70%">Use xxdiff to resolve conflicts in your working copy</td>
+    </tr>
+  </table>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/user_guide/build.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/user_guide/build.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/user_guide/build.html	(revision 1665)
@@ -0,0 +1,1976 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide: The Build System</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide - The Build System">
+  <meta name="keywords" content="FCM, user guide, extract, build">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; The Build System
+  </address>
+
+  <h1>The Build System</h1>
+
+  <p>The build system analyses the directory tree containing a set of source
+  code, processes the configuration, and invokes <em>make</em> to compile/build
+  the source code into the project executables. In this chapter, we shall use
+  many examples to explain how to use the build system. At the end of this
+  chapter, you should be able to use the build system, either by defining the
+  build configuration file directly or by using the extract system to generate
+  a suitable build configuration file.</p>
+
+  <h2><a name="command">The Build Command</a></h2>
+
+  <p>To invoke the build system, simply issue the command:</p>
+  <pre>
+fcm build
+</pre>
+
+  <p>By default, the build system searches for a build configuration file
+  "bld.cfg" in "$PWD" and then "$PWD/cfg". If a build configuration file is
+  not found in these directories, the command fails with an error. If a build
+  configuration file is found, the system will use the configuration specified
+  in the file to perform the build. If you use the extract system to extract
+  your source tree, a build configuration should be written for you
+  automatically at the "cfg/" sub-directory of the destination root
+  directory.</p>
+
+  <p>If the root directory of the build does not exist, the system performs a
+  new full build at this directory. If a previous build already exists at this
+  directory, the system performs an incremental build. If a full (fresh) build
+  is required for whatever reason, you can invoke the build system using the
+  "-f" option, (i.e. the command becomes "fcm build -f").</p>
+
+  <p>The build system uses GNU <em>make</em> to perform the majority of the
+  build. GNU <em>make</em> has a "-j &lt;jobs&gt;" option to specify the
+  number of &lt;jobs&gt; to run simultaneously. Invoking the build system with
+  the same option triggers this option when the build system invokes the
+  <em>make</em> command. The argument to the option &lt;jobs&gt; must be an
+  integer. The default is 1. For example, the command "fcm build -j 4"
+  will allow <em>make</em> to perform 4 jobs simultaneously.</p>
+
+  <p>For further information on the build command, please see <a href=
+  "command_ref.html#fcm_bld">FCM Command Reference &gt; fcm build</a>.</p>
+
+  <h2><a name="basic">Basic Features</a></h2>
+
+  <p>The build configuration file is the user interface of the build system. It
+  is a line based text file. You can create your own build configuration file
+  or you can use the extract system to create one for you.  For a complete set
+  of build configuration file declarations, please refer to the <a
+  href="annex_bld_cfg.html">Annex: Declarations in FCM build configuration
+  file</a>.</p>
+
+  <h3><a name="basic_build">Basic build configuration</a></h3>
+
+  <p>Suppose we have a directory at "$HOME/example". Its sub-directory
+  at "$HOME/example/src" contains a source tree to be built. You may
+  want to have a build configuration file "$HOME/example/cfg/bld.cfg",
+  which may contain:</p>
+
+  <table class="pad" summary="build_example1" border="1" width="100%">
+    <tr>
+      <th>Build configuration example 1 - basic build configuration</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type     bld                           # line 1
+cfg::version  1.0                           # line 2
+
+dir::root     $HOME/example                 # line 4
+
+target        foo.exe bar.exe               # line 6
+
+tool::fc      ifc                           # line 8
+tool::fflags  -O3                           # line 9
+tool::cc      gcc                           # line 10
+tool::cflags  -O3                           # line 11
+tool::ld      ifc                           # line 12
+tool::ldflags -O3 -L$(HOME)/lib -legg -lham # line 13
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 1: the label CFG::TYPE declares the type of the configuration
+    file. The value "bld" tells the system that it is a build configuration
+    file.</li>
+
+    <li>line 2: the label CFG::VERSION declares the version of the build
+    configuration file. The current default is "1.0". Although it is not
+    currently used, if we have to change the format of the configuration file
+    at a later stage, we shall be able to use this number to determine whether
+    we are reading a file with an older format or one with a newer
+    format.</li>
+
+    <li>line 4: the label DIR::ROOT declares the root directory of the current
+    build.</li>
+
+    <li>line 6: the label TARGET declares a list of "default" targets. The
+    default targets of the current build will be "foo.exe" and "bar.exe".</li>
+
+    <li>line 8: the label TOOL::FC declares the Fortran compiler command.</li>
+
+    <li>line 9: the label TOOL::FFLAGS declares the options to be used when
+    invoking the Fortran compiler command.</li>
+
+    <li>line 10: the label TOOL::CC declares the C compiler command.</li>
+
+    <li>line 11: the label TOOL::CFLAGS declares the options to be used when
+    invoking the C compiler command.</li>
+
+    <li>line 12: the label TOOL::LD declares the linker command.</li>
+
+    <li>line 13: the label TOOL::LDFLAGS declares the options to be used when
+    invoking the linker command.</li>
+  </ul>
+
+  <p>When we invoke the build system, it reads the above configuration file.  It
+  will go through various internal processes, such as dependency generations, to
+  obtain the required information to prepare the <em>Makefile</em> of the build.
+  (All of which will be described in later sections.) The <em>Makefile</em> of
+  the build will be placed at "$HOME/example/bld". The system will then invoke
+  <em>make</em> to build the targets specified in line 6, i.e. "foo.exe" and
+  "bar.exe" using the build tools specified between line 8 to line 13. On a
+  successful build, the target executables will be sent to "$HOME/example/bin/".
+  The build system also creates a shell script called "fcm_env.ksh" in
+  "$HOME/example/". If you source the shell script, it will export your PATH
+  environment variable to search the "$HOME/example/bin/" directory for
+  executables.</p>
+
+  <p>N.B. You may have noticed that the "-c" (compile to object file only)
+  option is missing from the compiler flags declarations. This is because the
+  option is inserted automatically by the build system, unless it is already
+  declared.</p>
+
+  <table class="pad" summary=
+  "note - declaration of source directories for build" border="1" width="100%">
+    <tr>
+      <th>Note - declaration of source directories for build</th>
+    </tr>
+
+    <tr>
+      <td>
+        Source directories do not have to reside in the source sub-directory
+        of the build root directory. They can be anywhere, but you will have to
+        declare them individually, using the label SRC::&lt;pcks&gt;, where
+        &lt;pcks&gt; is the sub-package name in which the source directory
+        belongs. E.g.
+
+        <pre>
+# Declare a source directory in the sub-package "foo::bar"
+src::foo::bar  $HOME/foo/bar
+</pre>
+
+        <p>By default, the build system searches the "src/"
+        sub-directory of the build root directory for sub-package source
+        directories. If all source directories are already declared
+        explicitly, you can switch off the automatic directory search by
+        setting the SEARCH_SRC flag to 0. E.g.</p>
+
+        <pre>
+search_src  0
+</pre>
+
+        <p>As mentioned in the previous chapter, the name of a sub-package
+        &lt;pcks&gt; provides a unique namespace for a file container. The
+        name of a sub-package is a list of words delimited by the double
+        colons "::", which is turned into the double underscores "__" by
+        the build system internally. Please avoid using "::" and "__" for
+        naming your files and directories.</p>
+        
+        <p>In the build system, the sub-package name also provides an
+        "inheritance" relationship for sub-packages. For instance, we may
+        have a sub-package called "foo::bar::egg", which belongs to the
+        sub-package "foo::bar", which belongs to the package "foo".</p>
+        
+        <ul>
+          <li>If we declare a global build tool, it applies to all
+          packages.</li>
+          
+          <li>If we declare a build tool for "foo", it applies also to the
+          sub-package "foo::bar" and "foo::bar::egg".</li>
+          
+          <li>If we declare a build tool for "foo::bar", it applies also to
+          "foo::bar::egg", but not to other sub-packages in "foo".</li>
+        </ul>
+      </td>
+    </tr>
+  </table>
+
+  <h3><a name="basic_extract">Build configuration via the extract
+  system</a></h3>
+
+  <p>As mentioned earlier, you can obtain a build configuration file through
+  the extract system. The following example is what you may have in your
+  extract configuration in order to obtain a similar configuration as example
+  1:</p>
+
+  <table class="pad" summary="build_example2" border="1" width="100%">
+    <tr>
+      <th>Build configuration example 2 - created by the extract system</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type          ext                           # line 1
+cfg::version       1.0                           # line 2
+
+dest::rootdir      $HOME/example                 # line 4
+
+bld::target        foo.exe bar.exe               # line 6
+
+bld::tool::fc      ifc                           # line 8
+bld::tool::fflags  -O3                           # line 9
+bld::tool::cc      gcc                           # line 10
+bld::tool::cflags  -O3                           # line 11
+bld::tool::ld      ifc                           # line 12
+bld::tool::ldflags -O3 -L$(HOME)/lib -legg -lham # line 13
+
+# ... and other declarations for repositories and source directories ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>It is easy to note the similarities and differences between example 1 and
+  example 2. Example 2 is an extract configuration file. It extracts to a
+  destination root directory that will become the root directory of the build.
+  Line 6 to line 13 are the same declarations, except that they are now
+  prefixed with "BLD::". In an extract configuration file, any lines prefixed
+  with "BLD::" means that they are build configuration setting. These lines
+  are "ignored" by the extract system but are parsed down to the output build
+  configuration file, with the "BLD::" prefix removed. (Note: the "BLD::" prefix
+  is optional for declarations in a build configuration file.)</p>
+
+  <p>N.B. If you use the extract system to mirror an extraction to a remote
+  machine, the extract system will assume that the root directory of the
+  remote destination is the root directory of the build, and that the build
+  will be carried out in the remote machine.</p>
+
+  <h3><a name="basic_exename">Naming of executables</a></h3>
+
+  <p>If a source file called "foo.f90" contains a main program, the default
+  behaviour of the system is to name its executable "foo.exe". The root name of
+  the executable is the same as the original file name, but its file extension
+  is replaced with ".exe". The output extension can be altered by re-registering
+  the extension for output EXE files. How this can be done will be discussed
+  later in the sub-section <a href="#advanced_file-type">File Type</a>.</p>
+  
+  <p>If you need to alter the full name of the executable, you can use the
+  "EXE_NAME::" declaration. For example, the declaration:</p>
+
+  <pre>
+bld::exe_name::foo  bar
+</pre>
+
+  <p>will rename the executable of "foo.f90" from "foo.exe" to "bar".</p>
+
+  <p>Note: the declaration label is "bld::exe_name::foo" (not
+  "bld::exe_name::foo.exe") and the executable will be named "bar" (not
+  "bar.exe").</p>
+  
+  <p>Another way to alter the full name of the executable is to use the package
+  configuration file, which will be discussed later in the sub-section <a
+  href="#other_pckcfg">Using a package configuration file</a>.</p>
+
+  <h3><a name="basic_flags">Setting the compiler flags</a></h3>
+
+  <p>As discussed in the first example, the compiler commands and their flags
+  can be set via the "TOOL::" declarations. A simple "TOOL::FFLAGS"
+  declaration, for example, alters the compiler options for compiling all
+  Fortran source files in the build. If you need to alter the compiler options
+  only for the source files in a particular sub-package, it is possible to do so
+  by adding the sub-package name to the declaration label. For example, the
+  declaration label "TOOL::FFLAGS::ops::code::OpsMod_Control" will ensure that
+  the declaration only applies to the code in the sub-package
+  "ops::code::OpsMod_Control". You can even make declarations down to the
+  individual source file level. For example, the declaration label
+  "TOOL::FFLAGS::ops::code::OpsMod_Control::Ops_Switch" will ensure that the
+  declaration applies only for the file "Ops_Switch.f90".</p>
+  
+  <p>N.B. Although the prefix "TOOL::" and the tool names are
+  case-insensitive, sub-package names are case sensitive in the declarations.
+  Internally, tool names are turned into uppercase, and the sub-package
+  delimiters are changed from the double colons "::" to the double underscores
+  "__". When the system generates the <em>Makefile</em> for the build, each
+  "TOOL" declaration will be exported as an environment variable. For example,
+  the declaration "tool::fflags::ops::code::OpsMod_Control" will be exported
+  as "FFLAGS__ops__code__OpsMod_Control".</p>
+
+  <p>N.B. TOOL declarations for sub-packages are only accepted by the system
+  when it is sensible to do so. For example, it allows you to declare different
+  compiler flags, linker commands and linker flags for different sub-packages,
+  but it does not accept different compilers for different sub-packages.</p>
+
+  <!--table class="pad" summary="note - TOOL declarations" border="1"
+  width="100%">
+    <tr>
+      <th>Note - TOOL declarations</th>
+    </tr>
+
+    <tr>
+      <td>The system does not stop you from making TOOL declarations that are
+      not supported, but it will only use the ones that are supported. For
+      example, you can define a compiler command for a sub-package, but it
+      will be ignored.</td>
+    </tr>
+  </table-->
+
+  <p>The following is an example setting in an extract configuration file
+  based on example 2:</p>
+
+  <table class="pad" summary="build_example3" border="1" width="100%">
+    <tr>
+      <th>Build configuration example 3 - compiler flags for different
+      sub-packages</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type              ext
+cfg::version           1.0
+
+dest::rootdir          $HOME/example
+
+bld::target            foo.exe bar.exe
+
+bld::tool::fc          ifc
+bld::tool::fflags      -O3    # line 9
+bld::tool::cc          gcc
+bld::tool::cflags      -O3
+bld::tool::ld          ifc
+bld::tool::ldflags     -L$(HOME)/lib -legg -lham
+
+bld::tool::fflags::ops -O1 -C # line 15
+bld::tool::fflags::gen -O2    # line 16
+
+# ... and other declarations for repositories and source directories ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>In the example above, line 15 alters the Fortran compiler flags for "ops",
+  so that all source files in "ops" will be compiled with optimisation level
+  1 and will have runtime error checking switched on. Line 16, alters the
+  Fortran compiler flags for "gen", so that all source files in "gen" will be
+  compiled with optimisation level 2. All other Fortran source files will use
+  the global setting declared at line 9, so they they will all be compiled
+  with optimisation level 3.</p>
+
+  <table class="pad" summary=
+  "note - changing compiler flags in incremental builds" border="1"
+  width="100%">
+    <tr>
+      <th>Note - changing compiler flags in incremental builds</th>
+    </tr>
+
+    <tr>
+      <td>
+        Suppose you have performed a successful build using the configuration
+        in example 3, and you have decided to change some of the compiler
+        flags, you can do so by altering the appropriate flags in the build
+        configuration file.  When you trigger an incremental build, the system
+        will detect changes in compiler flags automatically, and update only
+        the required targets. The following hierarchy is followed:
+
+        <ul>
+          <li>If the compiler flags for a particular source file change, only
+          that source file and any targets depending on that source file are
+          re-built.</li>
+
+          <li>If the compiler flags for a particular sub-package change, only
+          source files within that sub-package and any targets depending on
+          those source files are re-built.</li>
+
+          <li>If the global compiler flags change, all source files are
+          re-built.</li>
+
+          <li>If the compiler command changes, all source files are
+          re-built.</li>
+        </ul>
+
+        <!--p>The build system implements the above hierarchy using a "flags"
+        file system, which are dummy files created in the "flags/"
+        sub-directory of the build root. They are updated by the "touch"
+        command. The following dependencies are followed:</p>
+
+        <ul>
+          <li>Source files are dependent on its own "flags" file. E.g. the file
+          Ops_Switch in sub-package ":ops::code::OpsMod_Control" is dependent
+          on "FFLAGS__ops__code__OpsMod_Control__Ops_Switch.flags".</li>
+
+          <li>The "flags" file of a source file is dependent on the "flags" file
+          of its container sub-package. E.g. the above flags file is dependent
+          on "FFLAGS__ops__code__OpsMod_Control.flags".</li>
+
+          <li>The "flags" file of a sub-package is dependent on the "flags"
+          file of its container sub-package. E.g. the above is dependent on
+          "FFLAGS__ops__code.flags", which is dependent on
+          "FFLAGS__ops.flags".</li>
+
+          <li>The "flags" file of a top-level package is dependent on the
+          "flags" file of the global flags. E.g. "FFLAGS__ops.flags" is
+          dependent on "FFLAGS.flags".</li>
+
+          <li>The "flags" file of the global "flags" file is dependent on the
+          "flags" file of the compiler command. E.g. "FFLAGS.flags" is
+          dependent on "FC.flags".</li>
+        </ul>
+        
+        <p>The system records changes in declared tools using a cache file,
+        (called ".bld_tool", located at the ".cache/" sub-directory of the
+        built root). It is basically a list of "TOOL::" declarations for the
+        latest build.  When an incremental build is invoked, the list is
+        compared against the current set. If there are changes (modification,
+        addition and deletion) in any declarations, the timestamp of the
+        corresponding "flags" files will be updated. Files depending on the
+        updated "flags" file will then be considered out of date by
+        <em>make</em>, triggering a re-build of those files.</p-->
+      </td>
+    </tr>
+  </table>
+
+  <p>N.B. For a full list of build tools declarations, please see <a
+  href="annex_bld_cfg.html#tools-list">Annex: Declarations in FCM build
+  configuration file &gt; list of tools</a>.</p>
+
+  <h3><a name="basic_interface">Automatic Fortran 9X interface block</a></h3>
+
+  <p>For each Fortran 9X source file containing standalone subroutines and/or
+  functions, the system generates an interface file and sends it to the "inc/"
+  sub-directory of the build root. An interface file contains the interface
+  blocks for the subroutines and functions in the original source file. In an
+  incremental build, if you have modified a Fortran 9X source file, its
+  interface file will only be re-generated if the content of the interface has
+  changed.</p>
+  
+  <p>Consider a source file "foo.f90" containing a subroutine called "foo". In a
+  normal operation, the system writes the interface file to "foo.interface" in
+  the "inc/" sub-directory of the build root. By default, the root name of the
+  interface file is the same as that of the source file, and is case sensitive.
+  You can change this behaviour using a "TOOL::INTERFACE" declaration. E.g.:</p>
+
+  <pre>
+bld::tool::interface  program # The default is "file"
+</pre>
+
+  <p>In such case, the root name of the interface file will be named in lower
+  case after the first program unit in the file.</p>
+  
+  <p>The default extension for an interface file is ".interface". This can be
+  modified through the input and output file type register, which will be
+  discussed in a later section on <a href="#advanced_file-type">File
+  Type</a>.</p>
+  
+  <p>In most cases, we modify procedures without altering their calling
+  interfaces. Consider another source file "bar.f90" containing a subroutine
+  "bar". If "bar" calls "foo", it is good practice for "bar" to have an explicit
+  interface for "foo". This can be achieved if the subroutine "bar" has the
+  following within its declaration section:</p>
+
+  <pre>
+INCLUDE 'foo.interface'
+</pre>
+
+  <p>The source file "bar.f90" is now dependent on the interface file
+  "foo.interface". This can make incremental build very efficient, as changes
+  in the "foo.f90" file will not normally trigger the re-compilation of
+  "bar.f90", provided that the interface of the subroutine "foo" remains
+  unchanged. (However, the system is clever enough to know that it needs to
+  re-link any executables that are dependent on the object file for the
+  subroutine "bar".)</p>
+
+  <p>The default interface block generator is a piece of "plugged-in" Perl
+  code originally developed by the ECMWF. It has been modified at the Met
+  Office to work with FCM. Currently, the system can also work with the
+  interface generator <em>f90aib</em>, which is a freeware obtained from <a
+  href="http://www.ifremer.fr/ditigo/molagnon/fortran90/contenu.html">Fortran
+  90 texts and programs, assembled by Michel Olagnon</a> at the French
+  Research Institute for Exploitation of the Sea. To do so, you need to make a
+  declaration in the build configuration file using the label
+  "TOOL::GENINTERFACE". As for any other TOOL declarations, you can attach a
+  sub-package name to the label. The change will then apply only to source
+  files within that sub-package. If "TOOL::GENINTERFACE" is declared to have
+  the value "NONE", interface generation will be switched off. The following
+  are some examples:</p>
+
+  <table class="pad" summary="build_example4" border="1" width="100%">
+    <tr>
+      <th>Build configuration example 4 - Fortran 9X interface block
+      generator</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+# This is an EXTRACT configuration file ...
+
+# ... some other declarations ...
+
+bld::tool::geninterface       f90aib # line 5
+bld::tool::geninterface::foo  ECMWF  # line 6
+bld::tool::geninterface::bar  none   # line 7
+
+# ... some other declarations ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>In line 5, the global interface generator is now set to <em>f90aib</em>.
+  In line 6, the interface generator for the package "foo" is set to the ECMWF
+  one. In line 7, by setting the interface generator for the package "bar" to
+  the "none" keyword, no interface file will be generated for source files
+  under the package "bar".</p>
+
+  <p>Switching off the interface block generator can be useful in many
+  circumstances. For example, if the interface block is already provided
+  manually within the source tree, or if the interface block is never used by
+  other program units, it is worth switching off the interface generator for
+  the source file to speed up the build process.</p>
+
+  <h3><a name="basic_dependency">Automatic dependency</a></h3>
+
+  <p>The build system has a built-in dependency scanner, which works out the
+  dependency relationship between source files, so that they can be built in
+  the correct order. The system scans all source files of known types for all
+  supported dependency patterns. Dependencies of source files in a sub-package
+  are written in a cache, which can be retrieved for incremental builds. (In
+  an incremental build, only changed source files need to be re-scanned for
+  dependency information. Dependency information for other files are retrieved
+  from the cache.) The dependency information is parsed to the <em>make</em>
+  rule generator, which writes the <em>Makefile</em> fragment for building the
+  source files in the sub-package. In an incremental build, a
+  <em>Makefile</em> fragment for a sub-package is only re-generated if a
+  source file in the sub-package has changed.</p>
+
+  <p>The <em>make</em> rule generator generates different <em>make</em> rules
+  for different dependency types. The following dependency patterns are
+  automatically detected by the current system:</p>
+
+  <ul>
+    <li>The [USE &lt;module&gt;] statement in a Fortran source file is the first
+    pattern. The statement has two implications: 1) The current file compiles
+    only if the module has been successfully compiled, and needs to be
+    re-compiled if the module has changed. 2) The executable depending on the
+    current file can only resolve all its externals by linking with the object
+    file of the compiled module. The executable needs to be re-linked if the
+    module and its dependencies has changed.</li>
+
+    <li>The [INCLUDE '&lt;name&gt;.interface'] statement in a Fortran source
+    file is the second pattern. (The default extension for an interface file is
+    ".interface". This can be modified through the input and output file type
+    register, which will be discussed in a later section on <a href=
+    "#advanced_file-type">File Type</a>.) It has two implications: 1) The
+    current file compiles only if the included interface file is in the INCLUDE
+    search path, and needs to be re-compiled if the interface file changes. 2)
+    The executable depending on the current file can only resolve all its
+    externals by linking with the object file of the source file that generates
+    the interface file. The executable needs to be re-linked if the source file
+    (and its dependencies) associated with the interface file has changed. It is
+    worth noting that for this dependency to work, the root &lt;name&gt; of the
+    interface file should match with that of the source file associated with the
+    interface file. (Please note that you can use pre-processor [#include
+    "&lt;name&gt;.interface] instead of Fortran INCLUDE, but it will not work
+    if you switch on the <a href="#advanced_pp">pre-processing</a> stage, which
+    will be discussed in a later section.)</li>
+
+    <li>The [INCLUDE '&lt;file&gt;'] statement (excluding the INCLUDE
+    interface file statement) in a Fortran source file is the third pattern.
+    It has two implications: 1) The current file compiles only if the included
+    file is in the INCLUDE search path, and needs to be re-compiled if the
+    include file changes. 2) The executable needs to be linked with any
+    objects the include file is dependent on. It needs to be re-linked if
+    these objects have changed.</li>
+
+    <li>The [#include '&lt;file&gt;'] statement in a Fortran/C source or header
+    file is the fourth pattern. It has similar implications as the Fortran
+    INCLUDE statement. However, they have to be handled differently because
+    "#include" statements are processed by the pre-processor, which may be
+    performed in a separate stage of the FCM build process. This will be
+    further discussed in a later sub-section on <a
+    href="#advanced_pp">Pre-processing</a>.</li>
+  </ul>
+
+  <p>If you want your code to be built automatically by the FCM build system,
+  you should also design your code to conform to the following rules:</p>
+
+  <ol>
+    <li>Single compilable program unit, (i.e. program, subroutine, function or
+    module), per file.</li>
+
+    <li>Unique name for each compilable program unit.</li>
+
+    <li>Always supply an interface for subroutines and functions, i.e.:
+      <ul>
+        <li>Put them in modules.</li>
+
+        <li>Put them in the CONTAINS section within the main program unit.</li>
+
+        <li>Use interface files.</li>
+      </ul>
+    </li>
+
+    <li>If interface files are used, it is good practise to name each source
+    file after the program unit it contains. It will make life a lot simpler
+    when using the <a href="#basic_interface">Automatic Fortran 9X interface
+    block</a> feature, which has already been discussed in the previous
+    section.
+      <ul>
+        <li>The problem is that, by default, the root name of the interface file
+	    is the same as that of the source file rather than the program unit.
+	    If they differ then the build system will create a dependency on the
+	    wrong object file (since the object files are named according to the
+	    program unit).</li>
+	<li>This problem can be avoided by changing the behaviour of the interface
+	    file generator to use the name of the program unit instead (using a
+	    "TOOL::INTERFACE" declaration).</li>
+      </ul>
+    </li>
+  </ol>
+
+  <table class="pad" summary=
+  "note - setting build targets" border="1" width="100%">
+    <tr>
+      <th>Note - setting build targets</th>
+    </tr>
+
+    <tr>
+      <td>
+        The <em>Makefile</em> (and its include fragments) generated by the
+        build system contains a list of targets that can be built. The build
+        system allows you to build (or perform the actions of) any targets that
+        are present in the generated <em>Makefile</em>. There are two ways to
+        specify the targets to be built. Firstly, you can use the TARGET
+        declarations in your build configuration file to specify the default
+        targets to be built.  These targets will be set as dependencies of the
+        "all" target in the generated <em>Makefile</em>, which is the default
+        target to be built when <em>make</em> is invoked by FCM. Alternatively,
+        you can use the "-t" option when you invoke the "fcm build" command. The
+        option takes an argument, which should be a colon ":" separated list of
+        targets to be built. When the "-t" option is set, FCM invokes
+        <em>make</em> to build these targets instead. (E.g. if we invoke the
+        build system with the command "fcm build -t foo.exe:bar.exe", it will
+        invoke <em>make</em> to build "foo.exe" and "bar.exe".)
+
+        <p>If you do not specify any explicit targets, the system will search
+        your source tree for main programs:</p>
+        
+        <ul>
+          <li>If there are main programs in your source tree, they will be set
+          as the default targets automatically.</li>
+
+          <li>Otherwise, the default is to build the top level library archive
+          containing objects compiled from the source files in the current
+          source tree. (For more information on building library archives,
+          please see the section on <a href="#advanced_library">Creating
+          library archives</a>.)</li>
+        </ul>
+      </td>
+    </tr>
+  </table>
+
+  <h2><a name="advanced">Advanced Features</a></h2>
+
+  <h3><a name="advanced_dependency">Further dependency features</a></h3>
+
+  <p>Apart from the usual dependency patterns described in the previous
+  sub-section, the automatic dependency scanner also recognises two special
+  directives when they are inserted into a source file:</p>
+
+  <ul>
+    <li>The directive [DEPENDS ON: &lt;object&gt;] in a comment line of a
+    Fortran/C source file: It states that the current file is dependent on the
+    declared external object. The executable depending on the current file
+    needs to link with this external object in order to resolve all its
+    external references. It needs to be re-linked if the declared external
+    object (and its dependencies) has changed.</li>
+
+    <li>The directive [CALLS: &lt;executable&gt;] in a comment line of a
+    script: It states that the current script is dependent on the declared
+    executable file, which can be another script or a binary executable. The
+    current script can only function correctly if the declared executable is
+    found in the search path. This directive is useful to ensure that all
+    dependent executables are built or copied to the correct path.</li>
+  </ul>
+
+  <p>There are situations when you need to bypass the automatic dependency
+  scanner. In such case, you may need to use a package configuration file. For
+  further information, please refer to the sub-section on <a href=
+  "#advanced_pckcfg">Using a package configuration file</a>.</p>
+
+  <p>Another way to specify external dependency is to use the EXE_DEP
+  declaration to declare extra dependencies. The declaration normally applies to
+  all main programs, but if the the form EXE_DEP::&lt;target&gt; is used, it
+  will only apply to &lt;target&gt;, (which must be the name of a main program
+  target). If the declaration is made without a value, the main programs will be
+  set to depend on all object files. Otherwise, the value can be supplied as a
+  space delimited list of items. Each item can be either the name of a
+  sub-package or an object target. For the former, the main programs will be set
+  to depend on all object files within the sub-package. For the latter, the main
+  programs will be set to depend on the object target. The following are some
+  examples:</p>
+
+  <table class="pad" summary="build_example5" border="1" width="100%">
+    <tr>
+      <th>Build configuration example 5 - extra executable dependency</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type          ext
+cfg::version       1.0
+
+bld::exe_dep::foo.exe  foo::bar egg.o # line 4
+bld::exe_dep                          # line 5
+# ... some other declarations ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 4: this line declares the dependency on the sub-package "foo::bar"
+    and the object target "egg.o" for building the main program target
+    "foo.exe". The target "foo.exe" will now depends on all object files in the
+    "foo::bar" sub-package as well as the object target "egg.o".</li>
+
+    <li>line 5: this line declares that all other main program targets will
+    depend on all (non-program) object files in the build.</li>
+  </ul>
+
+  <table class="pad" summary="note - naming of object files" border="1"
+  width="100%">
+    <tr>
+      <th>Note - naming of object files</th>
+    </tr>
+
+    <tr>
+      <td>By default, object files are named with the suffix ".o". For a
+      Fortran source file, the build system uses the lower case name of the
+      first program unit within the file to name its object file. For example,
+      if the first program unit in the Fortran source file "foo.f90" is
+      "PROGRAM Bar", the object file will be "bar.o". For a C source file, the
+      build system uses the lower case root name of the source file to name
+      its object file. For example, a C source file called "egg.c" will have
+      its object file named "egg.o".
+      
+        <p>The reason for using lower case to name the object files is because
+        Fortran is a case insensitive language. Its symbols can either be in
+        lower or upper case. E.g. the SUBROUTINE "Foo" is the same as the
+        SUBROUTINE "foo". It can be rather confusing if the subroutines are
+        stored in different files. When they are compiled and archived into a
+        library, there will be a clash of namespace, as the Fortran compiler
+        thinks they are the same. However, this type of error does not normally
+        get reported. If "Foo" and "foo" are very different code, the user may
+        end up using the wrong subroutine, which may lead to a very long
+        debugging session. By naming all object files in lower case, this type
+        of situation can be avoided. If there is a clash in names due to the use
+        of upper/lower cases, it will be reported as warnings by <em>make</em>,
+        (as "duplicated targets" for building "foo.o").</p>
+      </td>
+    </tr>
+  </table>
+  
+  <p>It is realised that there are situations when an automatically detected
+  dependency should not be written into the <em>Makefile</em>. For example,
+  the dependency may be a standard module provided by the Fortran compiler,
+  and does not need to be built in the usual way. In such case, we need to
+  have a way to exclude this module during an automatic dependency scan.</p>
+
+  <p>The EXCL_DEP declaration can be used to do just that. The following
+  extract configuration contains some examples of the basic usage of the
+  EXCL_DEP declaration:</p>
+
+  <table class="pad" summary="build_example6" border="1" width="100%">
+    <tr>
+      <th>Build configuration example 6 - exclude dependency</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type          ext
+cfg::version       1.0
+
+bld::excl_dep  USE::YourFortranMod             # line 4
+bld::excl_dep  INTERFACE::HerFortran.interface # line 5
+bld::excl_dep  INC::HisFortranInc.inc          # line 6
+bld::excl_dep  H::TheirHeader.h                # line 7
+bld::excl_dep  OBJ::ItsObject.o                # line 8
+
+# ... some other declarations ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 4: this line declares that the Fortran module "YourFortranMod"
+    should be excluded. The value of each EXCL_DEP declaration has two parts.
+    The first part is a label that is used to define the type of dependency to
+    be excluded. For a full list of these labels, please see the <a
+    href="annex_bld_cfg.html#dependency-types">dependency types table</a> in
+    the <a href="annex_bld_cfg.html">Annex:
+    Declarations in FCM build configuration file</a>. The label "USE"
+    denotes a Fortran module. The second part of the label is the dependency
+    itself. For instance, if a Fortran source file contains the line: "USE
+    YourFortranMod", the dependency scanner will ignore it.</li>
+
+    <li>line 5: this line declares that the include statement for the Fortran
+    9X interface file "HerFortran.interface" should be excluded. The label
+    "INTERFACE" denotes a Fortran INCLUDE statement for a Fortran 9X interface
+    block file. For example, if a Fortran source file contains the line:
+    "INCLUDE 'HerFortran.interface'", the dependency scanner will
+    ignore it.</li>
+
+    <li>line 6: this line declares that the include statement for
+    "HisFortranInc.inc" should be excluded. The label "INC" denotes a Fortran
+    INCLUDE statement other than an INCLUDE statement for an interface block
+    file. For example, if a Fortran source file contains the line:
+    "INCLUDE 'HisFortranInc.inc'", the dependency scanner will ignore
+    it.</li>
+
+    <li>line 7: this line declares that the header include statement
+    "TheirHeader.h" should be excluded. The label "H" denotes a pre-processing
+    #include statement. For example, if a source file contains the line:
+    "#include 'TheirHeader.h'", the dependency scanner will ignore
+    it.</li>
+
+    <li>line 8: this line declares that the external dependency for
+    "ItsObject.o" should be excluded. The label "OBJ" denotes a compiled
+    binary object. These dependencies are normally inserted into the source
+    files as special comments. For example, if a source file contains the line:
+    "! depends on: ItsObject.o", the dependency scanner will ignore
+    it.</li>
+  </ul>
+
+  <p>An EXCL_DEP declaration normally applies to all files in the build.
+  However, you can suffix it with the name of a sub-package, i.e.
+  EXCL_DEP::&lt;pcks&gt;. In such case, the declaration will only apply while
+  scanning for dependencies in the source files in the sub-package named
+  &lt;pcks&gt;.</p>
+
+  <p>You can also exclude all dependency scan of a particular type. To do so,
+  simply declare the type in the value. For example, if you do not want the
+  build system to scan for the [CALLS: &lt;executable&gt;] directive in the
+  comment lines of your scripts, you can make the following declaration:</p>
+
+  <pre>
+bld::excl_dep  EXE
+</pre>
+
+  <p>N.B. Currently, the build system is unable to detect changes in EXCL_DEP
+  declarations. Therefore, you will need to invoke the build system in full
+  build mode if you have changed these settings.</p>
+
+  <h3><a name="advanced_blockdata">Linking a Fortran executable with a BLOCKDATA
+  program unit</a></h3>
+
+  <p>If it is required to link Fortran executables with BLOCKDATA program units,
+  you must declare the executable targets and the objects containing the
+  BLOCKDATA program units using the BLOCKDATA::&lt;target&gt; declarations. For
+  example, if "foo.exe" is an executable target depending on the objects of the
+  BLOCKDATA program units "blkdata.o" and "fbk.o", you will make the following
+  declarations:</p>
+
+  <pre>
+bld::blockdata::foo.exe  blkdata fbk
+</pre>
+
+  <p>If all your executables are dependent on "blkdata.o" and "fbk.o", you will
+  make the following declarations:</p>
+
+  <pre>
+bld::blockdata  blkdata fbk
+</pre>
+
+  <h3><a name="advanced_library">Creating library archives</a></h3>
+
+  <p>If you are interested in building library archives, the build system allows
+  you to do it in a relatively simple way. For each sub-package in the source
+  tree, there is a target to build a library containing all the objects compiled
+  from the source files (that are not main programs) within the sub-package. If
+  the sub-package contains children sub-packages, the object files of the
+  children will also be included recursively. By default, the library archive is
+  named after the sub-package, in the format "lib&lt;pcks&gt;.a". (For example,
+  the library archive for the package "foo::bar::egg" will be named
+  "libfoo__bar__egg.a" by default.) If you do not like the default name for the
+  sub-package library, you can use the LIB::&lt;pcks&gt; declaration to rename
+  it, as long as the new name does not clash with other targets. For example, to
+  rename "libfoo__bar__egg.a" to "libham.a", you will make the following
+  declaration in your extract configuration file:</p>
+
+  <pre>
+bld::lib::foo::bar::egg  ham
+</pre>
+
+  <p>In addition to sub-package libraries, you can also build a global library
+  archive for the whole source tree. By default, the library is named
+  "libfcm_default.a", but you can rename it using the LIB declaration as above.
+  For example, to rename the library to "libmy-lib.a", you will make the
+  following declaration in your extract configuration file:</p>
+
+  <pre>
+bld::lib  my-lib
+</pre>
+
+  <p>When a library archive is created successfully, the build system will
+  automatically generate the relevant exclude dependency configurations in the
+  "etc/" sub-directory of the build root. You will be able to include these
+  configurations in subsequent builds that utilise the library. The root names
+  of the configuration files match those of the library archives that you can
+  create in the current build, but the extension "*.a" is replaced with "*.cfg".
+  For example, the exclude dependency configuration for "libmy-lib.a"
+  is "libmy-lib.cfg".</p>
+
+  <h3><a name="advanced_pp">Pre-processing</a></h3>
+
+  <p>As most modern compilers can handle pre-processing, the build system
+  leaves pre-processing to the compiler by default. However, it is recognised
+  that there are code written with pre-processor directives that can alter the
+  argument list of procedures and/or their dependencies. If a source file
+  requires pre-processing in such a way, we have to pre-process before running
+  the interface block generator and the dependency scanner. The PP declaration
+  can be used to switch on this pre-processing stage. The pre-processing stage
+  can be switched on globally or for individual sub-packages only. The
+  following is an example, using an extract configuration file:</p>
+
+  <table class="pad" summary="build_example7" border="1" width="100%">
+    <tr>
+      <th>Build configuration example 7 - pre-processing switch</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type          ext
+cfg::version       1.0
+
+bld::pp::gen       1                     # line 4
+bld::pp::var::foo  1                     # line 5
+
+bld::tool::cppkeys GOOD WEATHER FORECAST # line 7
+bld::tool::fppkeys FOO BAR EGG HAM       # line 8
+
+# ... some other declarations ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 4 to 5: these switches on the pre-processing stage for all
+    sub-packages under "gen" and "var::foo".</li>
+
+    <li>line 7: this declares a list of pre-defined macros "GOOD", "WEATHER"
+    and "FORECAST" for pre-processing all C files.</li>
+
+    <li>line 8: this declares a list of pre-defined macros "FOO", "BAR",
+    "EGG" and "HAM" for pre-processing all Fortran files that require
+    processing.</li>
+  </ul>
+
+  <p>Source files requiring pre-processing may contain "#include" statements to
+  include header files. For including a local file, its name should be embedded
+  within a pair of quotes, i.e. 'file.h' or "file.h". If the header file is
+  embedded within a pair of "&lt;file.h&gt;" angle brackets, the system will
+  assume that the file can be found in a standard location.</p>
+
+  <p>The build system allows header files to be placed anywhere within the
+  declared source tree. The system uses the dependency scanner, as described
+  in the previous sub-section to scan for any header file dependencies. All
+  source files requiring pre-processing and all header files are scanned. Header
+  files that are required are copied to the "inc/" subdirectory of the build
+  root, which is automatically added to the pre-processor search path via the
+  "-I&lt;dir&gt;" option. The build system uses an internal logic similar to
+  <em>make</em> to perform pre-processing. Header files are only copied to the
+  "inc/" sub-directory if they are used in "#include" statements.</p>
+  
+  <p>Unlike <em>make</em>, which only uses the timestamp to determine whether an
+  item is out of date, the internal logic of the build system does this by
+  inspecting the content of the file as well. In an incremental build, the
+  pre-processed file is only updated if its content has changed. This avoids
+  unnecessary updates (and hence unnecessary re-compilation) in an incremental
+  build if the changed section of the code does not affect the output file.</p>
+
+  <p>Pre-processed code generated during the pre-processing stage are sent to
+  the "ppsrc/" sub-directory of the build root. It will have a relative path
+  that reflects the name of the declared sub-package. The pre-processed source
+  file will have the same root name as the original source file. For C files,
+  the same extension ".c" will be used. For Fortran files, the case of the
+  extension will normally be dropped, e.g. from ".F90" to ".f90".</p>
+  
+  <p>Following pre-processing, the system will use the pre-processed source
+  file as if it is the original source file. The interface generator will
+  generate the interface file using the pre-processed file, the dependency
+  scanner will scan the pre-processed file for dependencies, and the compiler
+  will compile the pre-processed source.</p>
+
+  <p>The TOOL::CPPKEYS and TOOL::FPPKEYS declarations are used to pre-define
+  macros in the C and Fortran pre-processor respectively. This is implemented
+  by the build system using the pre-processor "-D" option on each word in the
+  list. The use of these declarations are not confined to the pre-process
+  stage. If any source files requiring pre-processing are left to the compiler,
+  the declarations will be used to set up the commands for compiling these
+  source files.</p>
+
+  <p>The TOOL::CPPKEYS and TOOL::FPPKEYS declarations normally applies
+  globally, but like any other TOOL declarations, they can be suffixed with
+  sub-package names. In such cases, the declarations will apply only to the
+  specified sub-packages.</p>
+
+  <table class="pad" summary="note - changing pre-processor flags" border="1"
+  width="100%">
+    <tr>
+      <th>Note - changing pre-processor flags</th>
+    </tr>
+
+    <tr>
+      <td>
+        As for compiler flags, the build system detects changes in
+        pre-processor flags (TOOL::CPPFLAGS and TOOL::FPPFLAGS) and macro
+        definitions (TOOL::CPPKEYS and TOOL::FPPKEYS). If the pre-processor
+        flags or the macro definitions have changed in an incremental build,
+        the system will re-do all the necessary pre-processing. The following
+        hierarchy is followed:
+
+        <ul>
+          <li>If the pre-processor flags or macro definitions for a particular
+          source file change, only that source file will be pre-processed
+          again.</li>
+
+          <li>If the pre-processor flags or macro definitions for a particular
+          sub-package change, only source files within that sub-package will
+          be pre-processed again.</li>
+
+          <li>If the global pre-processor flags or macro definitions change,
+          all source files will be pre-processed again.</li>
+
+          <li>If the pre-processor command changes, all source files are
+          pre-processed again.</li>
+        </ul>
+      </td>
+    </tr>
+  </table>
+
+  <h3><a name="advanced_file-type">File type</a></h3>
+
+  <p>The build system only knows what to do with an input source file if it
+  knows what type of file it is. The type of a source file is normally
+  determined automatically using one of the following three methods (in
+  order):</p>
+
+  <ol>
+    <li>If the file is named with an extension, its extension will be matched
+    against a set of registered file extensions. If a match is found, the file
+    type will be set according to the register.</li>
+
+    <li>If a file does not have an extension or does not match with a
+    registered extension, its name is compared with a set of pre-defined
+    patterns. If a match is found, the file type will be set according to the
+    file type associated with the pattern.</li>
+
+    <li>If the above two methods failed and if the file is a text file, the
+    system will attempt to read the first line of the file. If the first line
+    begins with a "#!" pattern, the line will be compared with a set of
+    pre-defined patterns. If a match is found, the file type will be set
+    according to the file type associated with the pattern.</li>
+  </ol>
+
+  <p>In addition to the above, if a file is a Fortran or C source file, the
+  system will attempt to open the source file to determine whether it contains
+  a main program, module (Fortran only) or just standalone procedures. All
+  these information will be used later by the build system to process the
+  source file.</p>
+
+  <p>The build system registers a file type with a set of type flags
+  delimited by the double colons "::". For example, a Fortran 9X source file is
+  registered as "FORTRAN::FORTRAN9X::SOURCE". (Please note that the
+  order of the type flags in the list is insignificant. For example,
+  "FORTRAN::SOURCE" is the same as "SOURCE::FORTRAN".) For a list of all the
+  type flags used by the build system, please see the <a
+  href="annex_bld_cfg.html#infile-ext-types">input file extension type
+  flags table</a> in the <a href="annex_bld_cfg.html">
+  Annex: Declarations in FCM build configuration file</a>.</p>
+  
+  <p>The following is a list of default input file extensions and their
+  associated types:</p>
+
+  <table class="pad" summary="list of known file extensions" border="1">
+    <tr>
+      <th>Extensions</th>
+
+      <th>Type flags</th>
+
+      <th>Description</th>
+    </tr>
+
+    <tr>
+      <td class="mono">.f .for .ftn .f77</td>
+
+      <td class="mono">FORTRAN::SOURCE</td>
+
+      <td>Fortran 77 source file (assumed to be fixed format)</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.f90 .f95</td>
+
+      <td class="mono">FORTRAN::FORTRAN9X::SOURCE</td>
+
+      <td>Fortran 9X source file (assumed to be free format)</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.F .FOR .FTN .F77</td>
+
+      <td class="mono">FPP::SOURCE</td>
+
+      <td>Fortran 77 source file (assumed to be fixed format) that requires
+      pre-processing</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.F90 .F95</td>
+
+      <td class="mono">FPP::FPP9X::SOURCE</td>
+
+      <td>Fortran 9X source file (assumed to be free format) that requires
+      pre-processing</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.c</td>
+
+      <td class="mono">C::SOURCE</td>
+
+      <td>C source file</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.h .h90</td>
+
+      <td class="mono">CPP::INCLUDE</td>
+
+      <td>Pre-processor "#include" header file</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.o .obj</td>
+
+      <td class="mono">BINARY::OBJ</td>
+
+      <td>Compiled binary object</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.exe</td>
+
+      <td class="mono">BINARY::EXE</td>
+
+      <td>Binary executable</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.a</td>
+
+      <td class="mono">BINARY::LIB</td>
+
+      <td>Binary object library archive</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.sh .ksh .bash .csh</td>
+
+      <td class="mono">SHELL::SCRIPT</td>
+
+      <td>Unix shell script</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.pl .pm</td>
+
+      <td class="mono">PERL::SCRIPT</td>
+
+      <td>Perl script</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.py</td>
+
+      <td class="mono">PYTHON::SCRIPT</td>
+
+      <td>Python script</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.tcl</td>
+
+      <td class="mono">TCL::SCRIPT</td>
+
+      <td>Tcl/Tk script</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.pro</td>
+
+      <td class="mono">PVWAVE::SCRIPT</td>
+
+      <td>PVWave program</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.cfg</td>
+
+      <td class="mono">CFGFILE</td>
+
+      <td>FCM configuration file</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.inc</td>
+
+      <td class="mono">FORTRAN::FORTRAN9X::INCLUDE</td>
+
+      <td>Fortran INCLUDE file</td>
+    </tr>
+
+    <tr>
+      <td class="mono">.interface</td>
+
+      <td class="mono">FORTRAN::FORTRAN9X::INCLUDE::INTERFACE</td>
+
+      <td>Fortran 9X INCLUDE interface block file</td>
+    </tr>
+  </table>
+
+  <p>N.B. The extension must be unique. For example, the system does not
+  support the use of ".inc" files for both "#include" and Fortran
+  "INCLUDE".</p>
+
+  <p>The following is a list of supported file name patterns and their
+  associated types:</p>
+
+  <table class="pad" summary="list of known file name patterns" border="1">
+    <tr>
+      <th>Patterns</th>
+
+      <th>Type flags</th>
+
+      <th>Description</th>
+    </tr>
+
+    <tr>
+      <td class="mono">*Scr_* *Comp_* *IF_* *Suite_* *Interface_*</td>
+
+      <td class="mono">SHELL::SCRIPT</td>
+
+      <td>Unix shell script, GEN-based project naming conventions</td>
+    </tr>
+
+    <tr>
+      <td class="mono">*List_*</td>
+
+      <td class="mono">SHELL::SCRIPT::GENLIST</td>
+
+      <td>Unix shell script, GEN "list" file</td>
+    </tr>
+
+    <tr>
+      <td class="mono">*Sql_*</td>
+
+      <td class="mono">SCRIPT::SQL</td>
+
+      <td>SQL script, GEN-based project naming conventions</td>
+    </tr>
+  </table>
+
+  <p>The following is a list of supported "#!" line patterns and their
+  associated types:</p>
+
+  <table class="pad" summary="list of known file name patterns" border="1">
+    <tr>
+      <th>Patterns</th>
+
+      <th>Type flags</th>
+
+      <th>Description</th>
+    </tr>
+
+    <tr>
+      <td class="mono">*sh* *ksh* *bash* *csh*</td>
+
+      <td class="mono">SHELL::SCRIPT</td>
+
+      <td>Unix shell script</td>
+    </tr>
+
+    <tr>
+      <td class="mono">*perl*</td>
+
+      <td class="mono">PERL::SCRIPT</td>
+
+      <td>Perl script</td>
+    </tr>
+
+    <tr>
+      <td class="mono">*python*</td>
+
+      <td class="mono">PYTHON::SCRIPT</td>
+
+      <td>Python script</td>
+    </tr>
+
+    <tr>
+      <td class="mono">*tclsh* *wish*</td>
+
+      <td class="mono">TCL::SCRIPT</td>
+
+      <td>Tcl/Tk script</td>
+    </tr>
+  </table>
+
+  <p>The build system allows you to add or modify the register for input file
+  extensions and their associated type using the INFILE_EXT::&lt;ext&gt;
+  declaration, where &lt;ext&gt; is a file name extension without the leading
+  dot. For example, in an extract configuration file, you may have:</p>
+
+  <table class="pad" summary="build_example8" border="1" width="100%">
+    <tr>
+      <th>Build configuration example 8 - add/modify input file extension
+      types</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type             ext
+cfg::version          1.0
+
+bld::infile_ext::foo  CPP::INCLUDE                # line 4
+bld::infile_ext::bar  FORTRAN::FORTRAN9X::INCLUDE # line 5
+
+# ... some other declarations ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 4: this line registers the extension ".foo" to be of type
+    "CPP::INCLUDE". This means that any input files with ".foo"
+    extension will be treated as if they are pre-processor header files.</li>
+
+    <li>line 5: this line registers the extension ".bar" to be of type
+    "FORTRAN::FORTRAN9X::INCLUDE". This means that any input file
+    with ".bar" extension will be treated as if they are Fortran 9X INCLUDE
+    files.</li>
+  </ul>
+
+  <p>The INFILE_EXT declarations deal with extensions of input files. There is
+  also a OUTFILE_EXT::&lt;type&gt; declaration that deals with extensions of
+  output files. The declaration is opposite that of INFILE_EXT. The file
+  &lt;type&gt; is now declared with the label, and the extension is declared
+  as the value. It is worth noting that OUTFILE_EXT declarations use very
+  different syntax for &lt;type&gt;, and the declared extension must include
+  the leading dot. For a list of output types used by the build system,
+  please see the <a href="annex_bld_cfg.html#outfile-ext-types">output file
+  extension types table</a> in the <a href="annex_bld_cfg.html">
+  Annex: Declarations in FCM build configuration file</a>.
+  An example is given below:</p>
+
+  <table class="pad" summary="build_example9" border="1" width="100%">
+    <tr>
+      <th>Build configuration example 9 - modify output file extensions</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type                   ext
+cfg::version                1.0
+
+bld::outfile_ext::mk        .rule  # line 4
+bld::outfile_ext::mod       .MOD   # line 5
+bld::outfile_ext::interface .intfb # line 6
+
+# ... some other declarations ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 4: this line modifies the extension of output <em>Makefile</em>
+    fragments, output of the dependency scanner, from the default ".mk" to
+    ".rule".</li>
+
+    <li>line 5: this line modifies the extension of compiled Fortran 9X module
+    information files from the default ".mod" to ".MOD".</li>
+
+    <li>line 6: this line modifies the extension of INCLUDE Fortran 9X
+    interface block files from the default ".interface" to ".intfb".</li>
+  </ul>
+
+  <p>N.B. If you have made changes to the file type registers, whether it is
+  for input files or output files, it is always worth re-building your code in
+  full-build mode to avoid unexpected behaviour.</p>
+
+  <h3><a name="advanced_incremental">Incremental build based on a pre-compiled
+  build</a></h3>
+
+  <p>As you can perform incremental extractions against pre-extracted source
+  code, you can perform incremental builds against pre-compiled builds. The
+  very same USE statement can be used to declare a build, which the current
+  build will depend on. The only difference is that the declared location must
+  contain a valid build configuration file. In fact, if you use the extract
+  system to obtain your build configuration file, any USE declarations in the
+  extract configuration file will also be USE declarations in the output
+  build configuration file.</p>
+
+  <p>By declaring a USE statement, the current build automatically inherits
+  settings from the pre-compiled build. The following points are worth
+  noting:</p>
+
+  <ul>
+    <li>
+      Build targets are not normally inherited. However, you can switch on
+      inheritance of build targets using an INHERIT::TARGET declaration, such
+      as:
+      <pre>
+inherit::target  1
+</pre>
+    </li>
+
+    <li> The build root directory and its sub-directories of the pre-compiled
+    build are placed into the search paths. For example, if we have a
+    pre-compiled build at "/path/to/pre/compiled", and it is used by an
+    incremental build at "/path/to/incremental", the search path of executable
+    files will become "/path/to/incremental/bin:/path/to/pre/compiled/bin", so
+    that the "bin/" sub-directory of the incremental build is searched before
+    the "bin/" sub-directory of the pre-compiled build. If two or more USE
+    statements are declared, the USE statement declared last will have higher
+    priority. For example, if the current build is "C", and it USEs build "A"
+    before build "B", the search path will be "C:B:A".</li>
+
+    <li>
+      Sub-package source directories are inherited by default. If a source
+      directory is declared in the current build that has the same sub-package
+      name as a source directory of the pre-compiled build, any source files in
+      the source directory of the current build will override those in the
+      source directory of the pre-compiled build. Any source files missing
+      from the source directory of the current build will be taken from the
+      source directory of the pre-compiled build.
+
+      <p>For example, if build "B" USEs build "A", and both of them have a
+      sub-package called "basic::element". In build "A", the sub-package
+      contains the source files "earth.f90", "wind.f90" and "water.f90". In
+      build "B", the sub-package contains "earth.f90" and "fire.f90". When the
+      system searches for source files, it will look for source files in "B"
+      before "A". Therefore, the source file "earth.f90" in "B" will override
+      that of "A", and the files used for the build will be "earth.f90" and
+      "fire.f90" from "B" and "wind.f90" and "water.f90" from "A".</p>
+      
+      <p>You can switch off inheritance of source directories using an
+      INHERIT::SRC declaration.  This declaration can be suffixed with the
+      name of a sub-package. In such case, the declaration applies only to the
+      inheritance of the sub-package. Otherwise, it applies to all source
+      directories. For example:</p>
+
+      <pre>
+# Switch off inheritance of source directories in the "gen" sub-package
+inherit::src::gen  0
+</pre>
+    </li>
+
+    <li>All build tools are automatically inherited. If the same tool is
+    declared in the current incremental build, it overrides the declaration in
+    the pre-compiled build.</li>
+
+    <li>"PP", "EXCL_DEP", "INFILE_EXT" and "OUTFILE_EXT" declarations are
+    inherited using a similar mechanism as build tool declarations.</li>
+  </ul>
+
+  <p>As an example, suppose we have already performed an extract and build based
+  on the configuration in example 2, we can set up an extract configuration
+  file as follows:</p>
+
+  <table class="pad" summary="build_example10" border="1" width="100%">
+    <tr>
+      <th>Build configuration example 10 - "USE" a pre-compiled
+      build</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type            ext
+cfg::version         1.0
+
+use                  $HOME/example               # line 4
+
+dest::rootdir        $HOME/example9              # line 6
+
+bld::inherit::target 1                           # line 8 
+bld::target          ham.exe egg.exe             # line 9
+
+bld::tool::fflags    -O2 -w                      # line 11
+bld::tool::cflags    -O2                         # line 12
+
+# ... and other declarations for repositories and source directories ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 4: this line declares a previous extraction at
+    "$HOME/example" which the current extraction will be based on. The
+    same line will be written to the output build configuration file at
+    "$HOME/example9/cfg/bld.cfg". The subsequent build will then be
+    based on the build at "$HOME/example".</li>
+
+    <li>line 6: this declares the destination root directory of the current
+    extraction, which will become the root directory of the current build.
+    Search paths of the build sub-directories will be set automatically. For
+    example, the search path for executable files created by the current build
+    will be "$HOME/example9/bin:$HOME/example/bin".</li>
+
+    <li>line 8: this line switches on inheritance of build targets. The build
+    targets in example 1, i.e. "foo.exe" and "bar.exe" will be built as part
+    of the current build.</li>
+
+    <li>line 9: this declares two new build targets "ham.exe" and "egg.exe" to
+    be added to the inherited ones. The default build targets of the current
+    build will now be "foo.exe", "bar.exe", "ham.exe" and "egg.exe".</li>
+
+    <li>line 11-12: these lines modify options used by the Fortran and the C
+    compilers, overriding those inherited from example 1.</li>
+  </ul>
+
+  <h3><a name="advanced_pckcfg">Using a package configuration file</a></h3>
+
+  <p>It is recognised that the build system needs to be able to work with code
+  that is not designed to work with the automatic dependency scanner. There are
+  various techniques which can be used to achieve this, some of which are
+  already described. However, it should be noted that these techniques are
+  simply designed to allow code to be successfully built. They will not
+  necessarily result in a good environment for developing such code, since for
+  example, dependencies need to be manually maintained by the developer.</p>
+
+  <p>The final technique is the package configuration file. The package
+  configuration file is a special source file to inform the build system about
+  any additional information of the source files in the package. It must be a
+  file called "@PACKAGE.cfg" in a source directory. For a full list of available
+  declarations in the package configuration file, please refer to the <a
+  href="annex_pck_cfg.html">Annex: Declarations in FCM build package
+  configuration file</a>.</p>
+
+  <p>The following is an example of how a package configuration file can be
+  used to provide additional information to the build system for a source
+  file:</p>
+
+  <table class="pad" summary="package_example1" border="1" width="100%">
+    <tr>
+      <th>Package configuration example 1 - dependency information for a
+      source file</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+type::MyFortranProg.f90    FORTRAN::FORTRAN9X::SOURCE::PROGRAM # line 1
+scan::MyFortranProg.f90    0                                   # line 2
+intname::MyFortranProg.f90 myprog                              # line 3
+target::MyFortranProg.f90  hello_world                         # line 4
+
+dep::MyFortranProg.f90     USE::YourFortranMod                 # line 6
+dep::MyFortranProg.f90     INTERFACE::HerFortran.interface     # line 7
+dep::MyFortranProg.f90     INC::HisFortranInc.inc              # line 8
+dep::MyFortranProg.f90     H::TheirHeader.h                    # line 9
+dep::MyFortranProg.f90     OBJ::ItsObject.o                    # line 10
+
+# ... some other declarations ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 1: this declares a source file "MyFortranProg.f90" in the package
+    of type "FORTRAN::FORTRAN9X::SOURCE::PROGRAM", i.e. a Fortran 9X source
+    file containing a main program. The list of type flags used in the value
+    is the same list of type flags used in the INFILE_EXT declaration of a
+    build configuration file. For a list of  these flags, please see the <a
+    href="annex_bld_cfg.html#infile-ext-types">Input file extension type flags
+    table</a> in the <a href="annex_bld_cfg.html">
+    Annex: Declarations in FCM build configuration file</a>.</li>
+
+    <li>line 2: this declaration switches off (0) automatic dependency scan for
+    this source file. If this switch is not declared, it is automatically set
+    to on (1) for a source file. If the switch is on, the dependency scanner
+    will scan the source file for further dependencies. Otherwise, dependency
+    information for this source file will only be read from this configuration
+    file.</li>
+
+    <li>line 3: this declares the internal name of the source file to be
+    "myprog". If this is not set and the dependency scanner is switched on,
+    the internal name of the source file will be taken from the first program
+    unit of the source file. The resulting object file will be named after
+    the internal name, plus the ".o" extension. If internal name is not set
+    and cannot be determined automatically, the default is to use the root
+    name of the source file to name the object file.</li>
+
+    <li>line 4: this declares the executable target name of a main program.
+    This declaration is only used when the source file contains a main
+    program. If the target name is not set, the name of the executable will be
+    named after the root name of the source file plus the ".exe" extension. In
+    the above example, the executable will be named "hello_world".</li>
+
+    <li>line 6-10: these lines declare the dependencies of the source file.
+    The syntax of the values are exactly the same as those used in the
+    EXCL_DEP declarations in the build configuration file. For a list of these
+    flags, please see the <a
+    href="annex_bld_cfg.html#dependency-types">dependency types table</a> in
+    the <a href="annex_bld_cfg.html">Annex:
+    Declarations in FCM build configuration file</a>. In the example,
+    the source file is dependent on a Fortran module called "YourFortranMod",
+    a Fortran INCLUDE interface block file called "HerFortran.interface", a
+    Fortran INCLUDE file called "HistFortran.inc, a pre-processor header file
+    called "TheirHeader.h", and an object file called "ItsObject.o".</li>
+  </ul>
+
+  <h3><a name="advanced_data">Building data files</a></h3>
+
+  <p>While the usual targets to be built are the executables associated with
+  source files containing main programs, libraries or scripts, the build system
+  also allows you to build "data" files. All files with no registered type are
+  considered to be "data" files.  For each sub-package, there is an automatic
+  target for copying all "data" files to the "etc/" sub-directory of the build
+  root. The name of the target has the form "&lt;pcks&gt;.etc", where
+  &lt;pcks&gt; is the name of the sub-package (with package names delimited by
+  the double underscore "__"). For example, the target name for sub-package
+  "foo::bar" is "foo__bar.etc". This target is particularly useful for copying,
+  say, all namelists in a sub-package to the "etc/" sub-directory of the build
+  root.</p>
+
+  <p>At the end of a successful build, if the "etc/" sub-directory is not empty,
+  the "fcm_env.ksh" script will export the environment variable FCM_ETCDIR to
+  point to the "etc/" sub-directory. You should be able to use this environment
+  variable to locate your data files.</p>
+
+  <h2><a name="verbose">Diagnostic verbose level</a></h2>
+
+  <p>The amount of diagnostic messages generated by the build system is
+  normally set to a level suitable for normal everyday operation. This is the
+  default diagnostic verbose level 1. If you want a minimum amount of
+  diagnostic messages, you should set the verbose level to 0. If you want more
+  diagnostic messages, you can set the verbose level to 2 or 3. You can modify
+  the verbose level in two ways. The first way is to set the environment
+  variable FCM_VERBOSE to the desired verbose level. The second way is to
+  invoke the build system with the "-v &lt;level&gt;" option. (If set, the
+  command line option overrides the environment variable.)</p>
+
+  <p>The following is a list of diagnostic output at each verbose level:</p>
+
+  <table class="pad" summary="List of diagnostic verbose output" border="1">
+    <tr>
+      <th>Verbose level</th>
+
+      <th>Possible output</th>
+    </tr>
+
+    <tr>
+      <th>0</th>
+
+      <td>
+        <ul>
+          <li>Report the time taken at the end of each stage of the build
+          process.</li>
+
+          <li>Run the <em>make</em> command in silent mode.</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>1</th>
+
+      <td>
+        <ul>
+          <li>Everything at verbose level 0.</li>
+
+          <li>Report the name of the build configuration file.</li>
+
+          <li>Report date/time at the beginning of each stage of the build
+          process.</li>
+
+          <li>Report removed directories.</li>
+
+          <li>Report number of pre-processed files.</li>
+
+          <li>Report number of generated F9X interface files.</li>
+
+          <li>Report number of sub-packages that have source files scanned
+          for dependencies.</li>
+
+          <li>Report number of generated/updated sub-package <em>make</em>
+          rule fragment files.</li>
+
+          <li>Report name of updated <em>Makefile</em>.</li>
+
+          <li>Print compiler/linker commands.</li>
+
+          <li>Report total time.</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>2</th>
+
+      <td>
+        <ul>
+          <li>Everything at verbose level 1.</li>
+
+          <li>For incremental build in archive mode, report the commands used
+          to extract the archives.</li>
+
+          <li>Report creation and removal of directories.</li>
+
+          <li>Report pre-processor commands.</li>
+
+          <li>Report number of files scanned for dependency in each
+          sub-package.</li>
+
+          <li>Report names of generated/updated sub-package <em>make</em> rule
+          fragment files.</li>
+
+          <li>Print compiler/linker commands with timestamps.</li>
+
+          <li>Print usage of the runtime environment set up script.</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>3</th>
+
+      <td>
+        <ul>
+          <li>Everything at verbose level 2.</li>
+
+          <li>Report update of dummy files.</li>
+
+          <li>Report all shell commands.</li>
+
+          <li>Report pre-processor commands with timestamps.</li>
+
+          <li>If F9X interface is generated by <em>f90aib</em>, print commands
+          with timestamps.</li>
+
+          <li>If F9X interface is generated by ECMWF code, report start
+          date/time and time taken to generate each interface file.</li>
+
+          <li>Report start date/time and time taken of dependency scan for each
+          source file.</li>
+
+          <li>Run <em>make</em> on normal mode (as opposed to silent mode).</li>
+
+          <li>Report start date/time and time taken of <em>make</em>
+          commands.</li>
+        </ul>
+      </td>
+    </tr>
+  </table>
+
+  <h2><a name="overview">Overview of the build process</a></h2>
+
+  <p>The FCM build process can be summarised in five stages. Here is a summary
+  of what is done in each stage:</p>
+
+  <ol>
+    <li><strong>Setup</strong>: in this first stage, the build system reads
+    and processes the configuration file. The source sub-directory is searched
+    recursively for source directories. For full builds, it ensures that the
+    sub-directories created by the build system are removed. For inherited
+    (i.e. pre-compiled) builds, it sets up the search paths for the
+    sub-directories, inherits the targets, source directories, etc. For
+    incremental builds, the system also works out whether the current list of
+    build tools have changed.</li>
+
+    <li><strong>Pre-process</strong>: if any files in any source directories
+    require pre-processing, they will be pre-processed at this stage. The
+    resulting pre-processed source files will be sent to the "ppsrc/"
+    sub-directory of the build root.</li>
+
+    <li><strong>Generate dependency</strong>: the system scans source files of
+    registered types for dependency information. For an incremental build, the
+    information is only updated if a source file is changed. The system then
+    uses the information to write a <em>Makefile</em> for the main build. The
+    <em>Makefile</em> and any of its included fragments are generated in the
+    "bld/" sub-directory of the build root.</li>
+
+    <li><strong>Generate interface</strong>: if there are Fortran 9X source
+    files with standalone subroutines and functions, the build system
+    generates interface blocks for them. The result of which will be written
+    to the interface files in the "inc/" sub-directory of the build root.</li>
+
+    <li>
+      <strong>Make</strong>: the system invokes <em>make</em> on the
+      <em>Makefile</em> generated in the previous stage to perform the main
+      build. Following a build, the "root" directory of the build may contain
+      the following sub-directories (empty ones are removed automatically at the
+      end of the build process):
+
+      <table summary="list of build sub-directories" border="1" width="100%">
+        <tr>
+          <th>Sub-directory</th>
+
+          <th>Contents</th>
+
+          <th>Note</th>
+        </tr>
+
+        <tr>
+          <th>.cache/</th>
+
+          <td>&lt;cache files&gt;</td>
+
+          <td>used internally by FCM</td>
+        </tr>
+
+        <tr>
+          <th>bin/</th>
+
+          <td>&lt;executable binaries and scripts&gt;</td>
+
+          <td>-</td>
+        </tr>
+
+        <tr>
+          <th>bld/</th>
+
+          <td>Makefile and &lt;Makefile include files&gt;</td>
+
+          <td>-</td>
+        </tr>
+
+        <tr>
+          <th>cfg/</th>
+
+          <td>bld.cfg</td>
+
+          <td>this directory is not changed by the build system</td>
+        </tr>
+
+        <tr>
+          <th>done/</th>
+
+          <td>&lt;dummy "done" files&gt;</td>
+
+          <td>used internally by the Makefile generated by FCM</td>
+        </tr>
+
+        <tr>
+          <th>etc/</th>
+
+          <td>&lt;miscellaneous data files&gt;</td>
+
+          <td>-</td>
+        </tr>
+
+        <tr>
+          <th>flags/</th>
+
+          <td>&lt;dummy "flags" files&gt;</td>
+
+          <td>used internally by the Makefile generated by FCM</td>
+        </tr>
+
+        <tr>
+          <th>inc/</th>
+
+          <td>&lt;include files&gt;</td>
+
+          <td>such as *.h, *.inc, *.interface and *.mod files</td>
+        </tr>
+
+        <tr>
+          <th>lib/</th>
+
+          <td>&lt;object library archives&gt;</td>
+
+          <td>-</td>
+        </tr>
+
+        <tr>
+          <th>obj/</th>
+
+          <td>&lt;compiled object files&gt;</td>
+
+          <td>-</td>
+        </tr>
+
+        <tr>
+          <th>ppsrc/</th>
+
+          <td>&lt;source directories with pre-processed files&gt;</td>
+
+          <td>-</td>
+        </tr>
+
+
+        <tr>
+          <th>src/</th>
+
+          <td>&lt;source directories&gt;</td>
+
+          <td>this directory is not changed by the build system</td>
+        </tr>
+        <tr>
+          <th>tmp/</th>
+
+          <td>&lt;temporary objects and binaries&gt;</td>
+
+          <td>files generated by the compiler/linker may be left here</td>
+        </tr>
+      </table>
+    </li>
+  </ol>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/user_guide/code_management.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/user_guide/code_management.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/user_guide/code_management.html	(revision 1665)
@@ -0,0 +1,1262 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide: Code Management</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide - Code Management">
+  <meta name="keywords" content="FCM, user guide">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; Code Management System
+  </address>
+
+  <h1>Code Management System</h1>
+
+  <h2><a name="svn">Using Subversion</a></h2>
+
+  <p>One of the key strengths of Subversion
+  is its documentation. <a href="http://svnbook.red-bean.com/en/1.2">Version
+  Control with Subversion</a> (which we'll just refer to as the "Subversion
+  book" from now on) is an excellent book which explains in detail how to use
+  Subversion and also provides a good introduction to all the basic concepts of
+  version control. Rather than trying to write our own explanations (and not
+  doing as good a job) we will simply refer you to the Subversion book, where
+  appropriate, for the relevant information.</p>
+
+  <p>In general, the approach taken in this section is to make sure that you
+  first understand how to perform a particular action using the Subversion
+  tools and then describe how this differs using FCM.</p>
+
+  <h3><a name="svn_concepts">Basic Concepts</a></h3>
+
+  <p>In order to use FCM you need to have a basic understanding of version
+  control. If you're not already familiar with Subversion or CVS then please
+  read the chapter <a href=
+  "http://svnbook.red-bean.com/en/1.2/svn.basic.html">Basic Concepts</a> from
+  the Subversion book. In particular, make sure that you understand:</p>
+
+  <ul>
+    <li>The <em>Copy-Modify-Merge</em> approach to file sharing.</li>
+
+    <li>Global Revision Numbers.</li>
+  </ul>
+
+  <p>Note that this chapter states that <em>"working copies do not always
+  correspond to any single revision in the repository"</em>. However, the FCM
+  working practises do not encourage this and the wrapper scripts provided by
+  FCM should ensure that your working copy (a local copy of the repository's
+  files and directories where you can prepare changes) always corresponds to
+  exactly one revision.</p>
+
+  <p>CVS users should already be familiar with all the basic concepts. This is
+  not surprising since Subversion was designed as a replacement for CVS and it
+  uses the same development model. However, there are some important
+  differences which may confuse those more familiar with CVS. Fortunately,
+  <a href="http://svnbook.red-bean.com/en/1.2/svn.forcvs.html">Appendix A</a> of
+  the Subversion book is specifically written for those moving from CVS to
+  Subversion and you should read this if you are a CVS user.</p>
+
+  <h3><a name="svn_basic">Basic Command Line Usage</a></h3>
+
+  <p>Before we discuss the FCM system you need to have a good understanding of
+  how to perform most of the normal day-to-day tasks using Subversion.
+  Therefore, unless you are already familiar with Subversion, please read the
+  chapter <a href="http://svnbook.red-bean.com/en/1.2/svn.tour.html">Guided
+  Tour</a> from the Subversion book.</p>
+
+  <p>So, now you have an understanding of how to do basic tasks using
+  Subversion (you did read the <em>Guided Tour</em> didn't you?), how is using
+  FCM different? Well, the key thing to remember is that, instead of using the
+  command <tt>svn</tt> you need to use the command <tt>fcm</tt>. The advantages
+  of this are as follows:</p>
+
+  <ul>
+    <li><tt>fcm</tt> implements all of the commands that <tt>svn</tt> does
+    (including all the command abbreviations).</li>
+
+    <li>In some cases <tt>fcm</tt> does very little and basically passes on the
+    command to <tt>svn</tt>.</li>
+
+    <li>In other cases <tt>fcm</tt> has a lot of additional functionality
+    compared with the equivalent <tt>svn</tt> command.</li>
+
+    <li><tt>fcm</tt> also implements several commands not provided by
+    <tt>svn</tt>.</li>
+
+    <li><tt>fcm</tt> provides support for URL and revision keywords.</li>
+
+    <li>Most of the additional features and commands are discussed later in
+    this section or in the following sections.</li>
+  </ul>
+
+  <p>Full details of all the <tt>fcm</tt> commands available are provided in
+  the <a href="command_ref.html">FCM Command Reference</a> section.</p>
+
+  <h4><a name="svn_basic_keywords">URL &amp; Revision Keywords</a></h4>
+
+  <p>URL keywords can be used to specify URLs in <tt>fcm</tt> commands.
+  The syntax is <tt>fcm:&lt;keyword&gt;</tt>. Keywords can be defined globally
+  (see the file <a href=
+  "http://www-nwp/~fcm/FCM/src/etc/fcm.cfg"><tt>../etc/fcm.cfg</tt></a>
+  where-ever the <tt>fcm</tt> command has been installed) or individually in a
+  user configuration file (<tt>$HOME/.fcm</tt>). See the <a href=
+  "command_ref.html#fcm_config">FCM Command Reference</a> for further details
+  about configuration files.</p>
+
+  <p>For example, if you define a keyword in your configuration file as
+  follows:</p>
+  <pre>
+set::url::fcm      svn://fcm1/FCM_svn/FCM
+</pre>
+
+  <p>then you can abbreviate the URL as in the following examples:</p>
+
+  <pre>
+# fcm ls svn://fcm1/FCM_svn/FCM
+fcm ls fcm:fcm
+
+# fcm ls svn://fcm1/FCM_svn/FCM/trunk
+fcm ls fcm:fcm_tr  # OR: fcm ls fcm:fcm-tr
+
+# fcm ls svn://fcm1/FCM_svn/FCM/branches
+fcm ls fcm:fcm_br  # OR: fcm ls fcm:fcm-br
+
+# fcm ls svn://fcm1/FCM_svn/FCM/tags
+fcm ls fcm:fcm_tg  # OR: fcm ls fcm:fcm-tg
+</pre>
+
+  <p>Using URL keywords has two advantages.</p>
+
+  <ul>
+    <li>They are shorter and easier to remember.</li>
+
+    <li>If the repository needs to be moved then only the keyword definitions
+    need to be updated (although any working copies you have will still need to
+    be <em>relocated</em> by issuing a <a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.switch.html"><tt>fcm
+    switch --relocate</tt></a> command).</li>
+  </ul>
+
+  <p>In a similar way, revision keywords can be used to specify revision
+  numbers in <tt>fcm</tt> commands. The keyword can be used anywhere a revision
+  number can be used. Each keyword is associated with a repository keyword and
+  can only be used when referring to that repository.</p>
+
+  <p>For example, if you define a keyword in your configuration file as
+  follows:</p>
+  <pre>
+set::revision::fcm::vn1.0  112
+</pre>
+
+  <p>then the following commands are equivalent:<br>
+  <tt>fcm log -r 112 svn://fcm1/FCM_svn/trunk</tt><br>
+  <tt>fcm log -r vn1.0 fcm:fcm_tr</tt></p>
+
+  <h4><a name="svn_basic_diff">Examining Changes</a></h4>
+
+  <p>Code differences can be displayed graphically using <em>xxdiff</em> by
+  using the <tt>--graphical</tt> (or <tt>-g</tt>) option to <tt>fcm diff</tt>.
+  This option can be used in combination with any other options which are
+  accepted by <tt>svn diff</tt>.</p>
+
+  <p>An example display from xxdiff is shown below.</p>
+
+  <p class="image"><img src="xxdiff1.png" alt="xxdiff 2-way display"></p>
+
+  <p align="center"><em>xxdiff</em> 2-way display</p>
+
+  <p>Points to note:</p>
+
+  <ul>
+    <li>By default <em>xxdiff</em> is configured to show horizontal
+    differences. This means that the parts of the line which have changed are
+    highlighted (e.g. the text "useful" is highlighted in the example
+    above).</li>
+
+    <li>The number shown to the right of each file name shows the current line
+    number. The number on the far right is the number of differences found (2
+    in the example above).</li>
+
+    <li>You may find the following keyboard shortcuts useful.
+
+      <ul>
+        <li><em>N</em> - move to the next difference</li>
+
+        <li><em>P</em> - move to the previous difference</li>
+
+        <li><em>Ctrl-Q</em> - exit</li>
+      </ul>
+    </li>
+
+    <li>If you want to use another diff tool instead of <em>xxdiff</em> to
+    examine changes, you can either set the <tt>FCM_GRAPHIC_DIFF</tt>
+    environment variable or define the <tt>set::tool::graphic_diff</tt> setting
+    in your <tt>$HOME/.fcm</tt> file. For example, to use <em>tkdiff</em>, you
+    will do:
+
+    <pre>
+# EITHER: in the Korn shell:
+(SHELL PROMPT)$ export FCM_GRAPHIC_DIFF=tkdiff
+
+# OR: in your $HOME/.fcm:
+set::tool::graphic_diff  tkdiff
+</pre>
+
+    </li>
+  </ul>
+
+  <h4><a name="svn_basic_conflicts">Resolving Conflicts</a></h4>
+
+  <p>Your working copy may contain files <em>in conflict</em> as a result of an
+  update or a merge (covered later). Conflicts arise from the situation where
+  two changes being applied to a file <em>overlap</em>. For conflicts in text
+  files, the command <tt>fcm conflicts</tt> can be used to help resolve them.
+  (A discussion on binary files is given in the section
+  <a href="working_practices.html#binary">Working with Binary Files</a> later in
+  this document.) The <tt>fcm conflicts</tt> command calls <em>xxdiff</em> which
+  then displays a 3-way diff for each of the files in conflict.</p>
+
+  <p class="image"><img src="xxdiff2.png" alt="xxdiff 3-way display"></p>
+
+  <p align="center"><em>xxdiff</em> 3-way display</p>
+
+  <p>Points to note:</p>
+
+  <ul>
+    <li>The file in the middle is the common ancestor from the merge. The file
+    on the left is your original file and the file on the right is the file
+    containing the changes which you are merging in.</li>
+
+    <li><em>xxdiff</em> is configured to automatically select regions that
+    would end up being selected by an automatic merge (e.g. there are only
+    changes in one of the files). Any difference "hunks" which cannot be
+    resolved automatically are left "unselected".</li>
+
+    <li>Before you can save a merged version you need to go through each
+    unselected difference hunk and decide which text you wish to use.
+
+      <ul>
+        <li>Selecting a diff hunk can be carried out by clicking on it with the
+        left mouse button (or refer to the keyboard shortcuts shown under the
+        <em>Region</em> menu). The colours update to display which side is
+        selected for output. You can select individual lines with the middle
+        mouse button.</li>
+
+        <li>If you want to select more than one side, you have to invoke the
+        <em>Region-&gt;Split/swap/join</em> command (keyboard shortcut:
+        <em>S</em>). This will split the current diff hunk so you can select
+        the pieces you want from both sides. Further invocations of this
+        command will cause swapping of the regions, looping through all the
+        different ordering possibilities, and finally joining the regions again
+        (preserving selections where it is possible).</li>
+      </ul>
+    </li>
+
+    <li>The number on the far right is the number of unselected difference
+    hunks (1 in the example above). Once this number is 0 then you are ready to
+    save the merged file.</li>
+
+    <li>If you want to see how the merged file will look with the current
+    selections then select <em>Windows-&gt;Toggle Merged View</em> (keyboard
+    shortcut: <em>Alt+Y</em>). An extra window then appears showing the merged
+    output that updates interactively as you make selections.</li>
+
+    <li>You may find the following keyboard shortcuts useful.
+
+      <ul>
+        <li><em>B</em> - move to the next unselected hunk</li>
+
+        <li><em>O</em> - move to the previous unselected hunk</li>
+      </ul>
+    </li>
+
+    <li>There are several different ways to exit the 3-way diff (available from
+    the <em>file</em> menu):
+
+      <ul>
+        <li>Exit with MERGE (keyboard shortcut: <em>M</em>) - This saves the
+        merge result. If there are any unselected difference hunks remaining
+        then you will be warned and given the option of saving the file with
+        conflict markers.</li>
+
+        <li>Exit with ACCEPT (keyboard shortcut: <em>A</em>) - This saves the
+        file you are merging in (i.e. the middle one) as the merge result
+        (i.e. you have <em>accepted</em> all the changes).</li>
+
+        <li>Exit with REJECT (keyboard shortcut: <em>R</em>) - This saves the
+        original working copy file (i.e. the left one) as the merge result
+        (i.e. you have <em>rejected</em> all the changes).</li>
+      </ul>
+      
+      <p>If you just want to exit without making any decisions you can also just
+      close the window.</p>
+    </li>
+
+    <li>For further details please read the <a href=
+    "http://furius.ca/xxdiff/doc/xxdiff-doc.html"><em>xxdiff</em> users
+    manual</a> (available from the <em>Help</em> menu). In particular, read the
+    section <a href=
+    "http://furius.ca/xxdiff/doc/xxdiff-doc.html#merging-files-and-resolving-conflicts">
+    <em>Merging files and resolving conflicts</em></a>.</li>
+  </ul>
+
+  <p>If you have resolved all the conflicts in a file then you will be prompted
+  on whether to run <tt>svn resolved</tt> on the file to signal that the file
+  is no longer in conflict.</p>
+
+  <table class="pad" summary="fcm conflicts example output" border="1" width=
+  "100%">
+    <tr>
+      <th>Example output from <tt>fcm conflicts</tt></th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm conflicts
+Conflicts in file: Gen_setup_local1.proc
+You have chosen to ACCEPT all the changes
+Would you like to run "svn resolved"?
+Enter "y" or "n" (or just press &lt;return&gt; for "n"): y
+Resolved conflicted state of 'Gen_setup_local1.proc'
+Conflicts in file: Gen_setup_remote2.proc
+Merge conflicts were not all resolved
+Conflicts in file: Gen_setup_remote3.proc
+All merge conflicts resolved
+Would you like to run "svn resolved"?
+Enter "y" or "n" (or just press &lt;return&gt; for "n"): y
+Resolved conflicted state of 'Gen_setup_remote3.proc'
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>It is important to realise that there are some types of merge that
+  <em>xxdiff</em> will not be able to help you with.</p>
+
+  <ul>
+    <li>It you have 2 versions of a file, both with substantial changes to the
+    same piece of code, then the <em>xxdiff</em> display will be extremely
+    colourful and not very helpful.</li>
+
+    <li>In these cases it is often easier to start with one version of the file
+    and manually re-apply the changes from the other version. It might not be
+    obvious how to do this and you may need to speak to the author of the other
+    change to agree how this can be done. Fortunately this situation should be
+    very rare.</li>
+
+    <li>For a more detailed discussion please refer to <a href=
+    "http://software.ericsink.com/scm/scm_file_merge.html">Chapter 3: File
+    Merge</a> in the online book called <a href=
+    "http://software.ericsink.com/scm/source_control.html">Source Control
+    HOWTO</a>.</li>
+  </ul>
+
+  <h4><a name="svn_basic_check">Adding and Removing Files</a></h4>
+
+  <p>If your working copy contains files which are not under version control
+  then you can use the command <tt>fcm add --check</tt> to add them. This will
+  go through each of the files and prompt to see if you wish to put that file
+  under version control using <tt>svn add</tt>. For each file you can enter "y"
+  for yes, "n" for no or "a" to assume yes for all following files.</p>
+
+  <table class="pad" summary="fcm add --check example output" border="1" width=
+  "100%">
+    <tr>
+      <th>Example output from <tt>fcm add --check</tt></th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm add -c
+?      xxdiff1.png
+?      xxdiff2.png
+?      xxdiff3.png
+?      xxdiff4.png
+Add file 'xxdiff1.png'?
+Enter "y", "n" or "a" (or just press &lt;return&gt; for "n"): y
+A         xxdiff1.png
+Add file 'xxdiff2.png'?
+Enter "y", "n" or "a" (or just press &lt;return&gt; for "n"): n
+Add file 'xxdiff3.png'?
+Enter "y", "n" or "a" (or just press &lt;return&gt; for "n"): a
+A         xxdiff3.png
+A         xxdiff4.png
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Similarly, if your working copy contains files which are missing (i.e. you
+  have deleted them without using <tt>svn delete</tt>) then you can use the
+  command <tt>fcm delete --check</tt> to delete them. This will go through each
+  of the files and prompt to see if you wish to remove that file from version
+  control using <tt>svn delete</tt>.</p>
+
+  <p>As noted in the <a href=
+  "http://subversion.tigris.org/faq.html#wc-change-detection">Subversion
+  FAQ</a>, it can be dangerous using these commands. If you have moved or
+  copied a file then simply adding them would cause the history to be lost.
+  Therefore take care to only use these commands on files which really are new
+  or deleted.</p>
+
+  <h4><a name="svn_basic_commit">Committing Changes</a></h4>
+
+  <p>The command <tt>fcm commit</tt> should be used for committing changes back
+  to the repository. It differs from the <tt>svn commit</tt> command in a
+  number of important ways:</p>
+
+  <ul>
+    <li>Your working copy <em>must</em> be up to date. <tt>fcm commit</tt> will
+    abort if it finds that any files are out of date with respect to the
+    repository. This ensures that your working copy reflects how the repository
+    will be after you have committed your changes.
+
+      <ul>
+        <li>This helps to ensure that any tests you have done prior to
+        committing are valid.</li>
+
+        <li><tt>fcm commit</tt> is not suitable if you need to commit changes
+        from a working copy containing mixed revisions. However, you are very
+        unlikely to need to do this.</li>
+
+        <li>Actually there is a small chance that your working copy might not
+        be up to date when you commit if someone else is committing some
+        changes at the same time. However, this should very seldom happen and,
+        even if it does, the commit would fail if any of the files being
+        changed became out of date (i.e. it is not possible to lose any
+        changes).</li>
+      </ul>
+    </li>
+
+    <li>If it discovers a file named <tt>#commit_message#</tt> in the top level
+    of your working copy it uses this to provide a template commit message
+    (which you can then edit).
+
+      <ul>
+        <li>If you have performed a merge then a message describing the merge
+        will have been added to this file. It is important that you leave this
+        included in the commit message and do not change its format, as it is
+        used by the <tt>fcm branch</tt> command.</li>
+
+        <li>You can, if you wish, add entries to this file as you go along to
+        record what changes you have prepared in your working copy. You can
+        also use the command <tt>fcm commit --dry-run</tt> to allow you to edit
+        the commit message without committing any changes.</li>
+
+        <li><tt>#commit_message#</tt> is ignored by Subversion (so you won't
+        see it show up as an unversioned files when you run <tt>fcm
+        status</tt>).</li>
+      </ul>
+    </li>
+
+    <li>It always operates from the top of your working copy. If you issue the
+    <tt>fcm commit</tt> command from a sub-directory of your working copy then
+    it will automatically work out the top directory and work from there.
+
+      <ul>
+        <li>This ensures that any template commit message gets picked up and
+        that you do not, for example, accidently commit a partial set of
+        changes from a merge.</li>
+      </ul>
+    </li>
+
+    <li>It always commits <em>all</em> the changes in your working copy (it
+    does not accept a list of files to commit).
+
+      <ul>
+        <li>Once again, this avoids any danger of accidently committing a
+        partial set of changes.</li>
+
+        <li>You should only work on one change within a working copy. If you
+        need to prepare another, unrelated change then use a separate working
+        copy.</li>
+      </ul>
+    </li>
+
+    <li>It runs <tt>svn update</tt> after the commit to ensure that your
+    working copy is at the latest revision and to avoid any confusion caused by
+    your working copy containing mixed revisions.</li>
+  </ul>
+
+  <table class="pad" summary="fcm commit example output" border="1" width=
+  "100%">
+    <tr>
+      <th>Example output from <tt>fcm commit</tt></th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm commit
+Starting editor to create commit message ...
+Commit message is as follows:
+------------------------------------------------------------------------
+An example commit.
+--This line, and those below, will be ignored--
+[Project: GEN]
+[Branch : branches/test/frsn/r123_foo_bar]
+[Sub-dir: &lt;top&gt;]
+
+M      src/code/GenMod_Control/GenMod_Control.f90
+M      src/code/GenMod_Control/Gen_SetupControl.f90
+------------------------------------------------------------------------
+Would you like to commit this change?
+Enter "y" or "n" (or just press &lt;return&gt; for "n"): y
+Sending        src/code/GenMod_Control/GenMod_Control.f90
+Sending        src/code/GenMod_Control/Gen_SetupControl.f90
+Transmitting file data ..
+Committed revision 170.
+Performing update to make sure your working copy is at this new revision ...
+At revision 170.
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <h3><a name="svn_branching">Branching &amp; Merging</a></h3>
+
+  <p>Branching is a fundamental concept common to most version control systems.
+  For a good introduction please read the chapter <a href=
+  "http://svnbook.red-bean.com/en/1.2/svn.branchmerge.html">Branching &amp;
+  Merging</a> from the Subversion book. Even if you are already familiar with
+  branching using other version control systems you should still read this
+  chapter to see how branching is implemented in Subversion.</p>
+
+  <p>Having read this chapter from the Subversion book you should understand:</p>
+
+  <ul>
+    <li>Why each project directory has sub-directories called <em>trunk</em>,
+    <em>branches</em> and <em>tags</em>. This structure is assumed by
+    <tt>fcm</tt> (Subversion recommends it but doesn't insist on it).</li>
+
+    <li>That when you make a branch you are taking a copy of the entire project
+    file tree. Fortunately, the design of the Subversion repository means that
+    these copies are "cheap" - they are quick to create and take very little
+    space.</li>
+
+    <li>That Subversion doesn't (currently) track merge information for you -
+    this has to be done manually.</li>
+
+    <li>That each revision of your repository can also be thought of as a
+    <em>changeset</em>.</li>
+
+    <li>That once a change is committed to a repository it cannot be removed
+    (only reversed). Therefore you must take care not to committ a sensitive
+    document or a large data file unintentionally.</li>
+  </ul>
+
+  <p>FCM provides various commands which make working with branches easier (as
+  described in the following sections).</p>
+
+  <h4><a name="svn_branching_create">Creating Branches</a></h4>
+
+  <p>The command <tt>fcm branch --create</tt> should be used for creating new
+  branches. It provides a number of features:</p>
+
+  <ul>
+    <li>It applies a standard naming convention for branches. The branch name
+    is automatically constructed for you depending on the option(s) supplied to
+    the command. The full detail of these options are described in the <a href=
+    "command_ref.html#fcm_svn_br">FCM Command Reference &gt; fcm branch</a>
+    section.</li>
+
+    <li>By default, it assumes that you are branching from the last changed
+    revision of the <em>trunk</em>.
+
+      <ul>
+        <li>You can use the <tt>--branch-of-branch</tt> option if you need to
+        create a branch of a branch. A branch of a branch can be useful in many
+        situations. For example, consider a shared branch used by several
+        members of your team to develop, say, a new science scheme, and you have
+        come up with some different ideas of implementing the scheme. You may
+        want to create a branch of the shared branch to develop your idea before
+        merging it back to the shared branch. Note that you can only merge a
+        branch of a branch with it's parent or with another branch created from
+        the same parent. You can't, for example, merge it with the trunk.</li>
+
+        <li>You can use the <tt>--revision &lt;rev&gt;</tt> option if you need
+        to create a branch from an earlier revision of the source.</li>
+      </ul>
+    </li>
+
+    <li>Each branch always contains a full copy of the trunk (or its parent
+    branch) - you cannot create a branch from a sub-tree.
+
+      <ul>
+        <li>There would be no reason to only include a sub-tree in a
+        branch.</li>
+      </ul>
+    </li>
+
+    <li>It applies a standard commit message which defines how the branch has
+    been created. If a Trac ticket is specified using the <tt>--ticket
+    &lt;number&gt;</tt> option, it is added to the commit log message. If you need to
+    add anything to the commit log message, please do so <strong>above</strong>
+    the line that says "--This line will be ignored and those below will be
+    inserted automatically--".</li>
+  </ul>
+  
+  <p>The following is a list of the different types of branches available:</p>
+
+  <table class="pad" summary="list of available branch types" border="1">
+    <tr>
+      <th>Type</th>
+
+      <th>Branch Name</th>
+
+      <th>Description</th>
+    </tr>
+
+    <tr>
+      <td rowspan="2">Development<br>
+      Branches</td>
+
+      <td class="mono">branches/dev/&lt;Userid&gt;/&lt;Branch_Name&gt;</td>
+
+      <td>These are for changes which are intended to be merged back to the
+      trunk once they are complete. Most branches will belong to this type.
+      e.g. branches/dev/frdm/vn6.1_ImprovedDeepConvection,
+      branches/dev/frdm/r2134_NewBranchNamingConvention.</td>
+    </tr>
+
+    <tr>
+      <td class="mono">branches/dev/Share/&lt;Branch_Name&gt;</td>
+
+      <td>Shared development branches not owned by one specific user.</td>
+    </tr>
+
+    <tr>
+      <td rowspan="2">Test<br>
+      Branches</td>
+
+      <td class="mono">branches/test/&lt;Userid&gt;/&lt;Branch_Name&gt;</td>
+
+      <td>These are for changes which are <em>not</em> intended for the trunk.
+      e.g. Proof of concept work, temporary code written for dealing with a
+      one-off problem, etc.</td>
+    </tr>
+
+    <tr>
+      <td class="mono">branches/test/Share/&lt;Branch_Name&gt;</td>
+
+      <td>Shared test branches.</td>
+    </tr>
+
+    <tr>
+      <td rowspan="2">Packages</td>
+
+      <td class="mono">branches/pkg/&lt;Userid&gt;/&lt;Branch_Name&gt;</td>
+
+      <td>These are branches which combine together a number of different
+      development branches. Sometimes this will simply be for testing purposes
+      (i.e. for testing a branch in combination with other branches). Other
+      times it may be the package which eventually gets merged to the trunk
+      (rather than the development branches). e.g.
+      branches/pkg/frdm/vn6.1_TestImprovedDeepConvection</td>
+    </tr>
+
+    <tr>
+      <td class="mono">branches/pkg/Share/&lt;Branch_Name&gt;</td>
+
+      <td>Shared packages. e.g.
+      branches/pkg/Share/vn6.1_NewConvectionScheme.</td>
+    </tr>
+
+    <tr>
+      <td>Configurations</td>
+
+      <td class="mono">branches/pkg/Config/&lt;Branch_Name&gt;</td>
+
+      <td>These are major packages which combine together a number of different
+      packages and development branches. e.g.
+      branches/pkg/Config/vn6.1_HadGEM1a.</td>
+    </tr>
+
+    <tr>
+      <td>Releases</td>
+
+      <td class="mono">branches/pkg/Rel/&lt;Branch_Name&gt;</td>
+
+      <td>These may be bug-fix branches for system releases, if required. They
+      can also be branches on which stable releases are prepared if you don't
+      do this on the trunk (although you lose the ability to branch from stable
+      releases if you work this way). e.g.
+      branches/pkg/Rel/vn6.1_BugFixes.</td>
+    </tr>
+  </table>
+
+  <table class="pad" summary="fcm branch --create example output" border="1"
+  width="100%">
+    <tr>
+      <th>Example output from <tt>fcm branch --create</tt></th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm br -c -n my_test_branch -k 23 fcm:test
+Starting nedit to create commit message ...
+Commit message is as follows:
+------------------------------------------------------------------------
+Create an example branch to demonstrate branch creation for the user guide.
+Created /OPS/branches/dev/frsn/r118_my_test_branch from /OPS/trunk@118.
+Relates to ticket #23.
+--This line, and those below, will be ignored--
+
+A    svn://fcm1/repos/OPS/branches/dev/frsn/r118_my_test_branch
+------------------------------------------------------------------------
+Would you like to go ahead and create this branch?
+Enter "y" or "n" (or just press &lt;return&gt; for "n"): y
+Creating branch svn://fcm1/repos/OPS/branches/dev/frsn/r118_my_test_branch ...
+
+Committed revision 169.
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <h4><a name="svn_branching_list">Listing Branches Created by You or Other
+  Users</a></h4>
+
+  <p>The command <tt>fcm branch --list</tt> can be used to list the branches
+  you have created at the HEAD of a repository. If you specify the <tt>--user
+  &lt;userid&gt;</tt> option, the branches created by &lt;userid&gt; are listed
+  instead. You can specify multiple users with multiple <tt>--user
+  &lt;userid&gt;</tt> options, or with a colon (:) separated list to a single
+  <tt>--user &lt;userid:list&gt;</tt> option. The command returns 0 (success)
+  if one or more branches is found for the specified users, or 1 (failure) if
+  no branch is found.</p>
+
+  <table class="pad" summary="fcm branch --list example output" border="1"
+  width="100%">
+    <tr>
+      <th>Example output from <tt>fcm branch --list</tt></th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm branch --list fcm:gen
+1 branch found for frsn in svn://fcm1/GEN_svn/GEN
+fcm:GEN-br/dev/frsn/r1191_clean_up/
+(SHELL PROMPT)$ echo $?
+0
+(SHELL PROMPT)$ fcm branch --list --user frbj --user frsn fcm:gen
+2 branches found for frbj, frsn in svn://fcm1/GEN_svn/GEN
+fcm:GEN-br/dev/frbj/r1177_gen_ui_for_scs/
+fcm:GEN-br/dev/frsn/r1191_clean_up/
+(SHELL PROMPT)$ echo $?
+0
+(SHELL PROMPT)$ fcm branch --list --user frva fcm:gen
+0 branch found for frva in svn://fcm1/GEN_svn/GEN
+(SHELL PROMPT)$ echo $?
+1
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <h4><a name="svn_branching_info">Getting Information About Branches</a></h4>
+
+  <p>The command <tt>fcm branch --info</tt> can be used to get various
+  information about a branch. In particular, it summarises information about
+  merges to and from the branch and its parent.</p>
+
+  <table class="pad" summary="fcm branch --info example output" border="1"
+  width="100%">
+    <tr>
+      <th>Example output from <tt>fcm branch --info</tt></th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm branch --info
+URL: svn://fcm1/FCM_svn/FCM/branches/dev/frsn/r1346_merge
+Repository Root: svn://fcm1/FCM_svn
+Revision: 1385
+Last Changed Author: frsn
+Last Changed Rev: 1385
+Last Changed Date: 2006-04-20 11:08:45 +0100 (Thu, 20 Apr 2006)
+--------------------------------------------------------------------------------
+Branch Create Author: frsn
+Branch Create Rev: 1354
+Branch Create Date: 2006-04-04 14:27:47 +0100 (Tue, 04 Apr 2006)
+Branch Parent: svn://fcm1/FCM_svn/FCM/trunk@1346
+Last Merge From Parent, Revision: 1444
+Last Merge From Parent, Delta: /FCM/trunk@1439 cf. /FCM/trunk@1395
+Merges Avail From Parent: 1445
+Merges Avail Into Parent: 1453 1452 1449 1446 1444 1443 1441 1434 1397 1396 ...
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>If you need information on the current children of the branch, use the
+  <tt>--show-children</tt> option of the <tt>fcm branch --info</tt> command. If
+  you need information on recent merges to and from the branch and its siblings,
+  use the <tt>--show-siblings</tt> option of the <tt>fcm branch --info</tt>
+  command.</p>
+
+  <p>To find out what changes have been made on a branch relative to its parent
+  you can use the command <tt>fcm diff --branch</tt>.</p>
+
+  <ul>
+    <li>You can combine this with the options:
+    
+      <table summary="options for fcm diff --branch">
+        <tr>
+          <td class="mono">--graphical</td>
+
+          <td>to display the differences using a graphical <em>diff</em>
+          tool</td>
+        </tr>
+
+        <tr>
+          <td class="mono">--trac</td>
+
+          <td>to display the differences using Trac</td>
+        </tr>
+
+        <tr>
+          <td class="mono">--wiki</td>
+
+          <td>to print a wiki syntax suitable for inserting into Trac</td>
+        </tr>
+      </table>
+    </li>
+
+    <li>The base of the difference is adjusted to account for any merges from
+    the branch to its parent or vice-versa.</li>
+  </ul>
+
+  <h4><a name="svn_branching_switch">Switching your working copy to point to
+  another branch</a></h4>
+
+  <p>The command <tt>fcm switch</tt> can be used to switch your working copy to
+  point to another branch. For example, if you have a working copy at
+  <tt>$HOME/work</tt>, currently pointing to the trunk or a branch of a project
+  at <tt>svn://fcm1/FCM_svn/FCM/trunk</tt>, you can switch the working copy to
+  point to another branch of same project:</p>
+
+  <table class="pad" summary="fcm switch" border="1" width="100%">
+    <tr>
+      <th>Example output from <tt>fcm switch</tt></th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(Shell prompt)$ cd $HOME/work
+(Shell prompt)$ fcm sw dev/frsn/r959_blockdata
+-&gt; svn switch --revision HEAD svn://fcm1/FCM_svn/FCM/branches/dev/frsn/r959_blockdata
+U    doc/user_guide/getting_started.html
+U    doc/user_guide/code_management.html
+U    doc/user_guide/command_ref.html
+U    src/lib/Fcm/SrcFile.pm
+U    src/lib/Fcm/Util.pm
+U    src/lib/Fcm/Build.pm
+U    src/lib/Fcm/Cm.pm
+U    src/lib/Fcm/SrcPackage.pm
+U    src/bin/fcm_internal
+U    src/bin/fcm_gui
+Updated to revision 1009.
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Unlike <tt>svn switch</tt>, <tt>fcm switch</tt> does extra checking to
+  ensure that your whole working copy is switched to the new branch at the
+  correct level of sub-directory. In addition, you can specify only the "branch"
+  part of the URL, such as "trunk", "branches/dev/fred/r1234_bob" or even
+  "dev/fred/r1234_bob" and the command will work out the full URL for you.</p>
+
+  <h4><a name="svn_branching_delete">Deleting Branches</a></h4>
+
+  <p>The command <tt>fcm branch --delete</tt> can be used to delete branches
+  which are no longer required. Before being asked to confirm that you want to
+  delete the branch, you will first see the same output as from <tt>fcm branch
+  --info</tt>. This allows you to check, for example, whether your branch is
+  being used anywhere else or whether the latest changes on your branch have
+  been merged to the trunk. You will be prompted to edit your commit log
+  message. If you need to add anything to the commit log message, please do so
+  <strong>above</strong> the line that says "--This line will be ignored and
+  those below will be inserted automatically--".</p>
+
+  <h4><a name="svn_branching_merge">Merging</a></h4>
+
+  <p>As mentioned earlier, Subversion doesn't track merge information
+  (although, in the longer term, there are plans to add this feature). However,
+  <tt>fcm</tt> <em>does</em> track a limited amount of merge information. It
+  does this by making a number of assumptions:</p>
+
+  <ul>
+    <li>That all merges are performed using FCM and are identified using a
+    standard template in the commit log message.</li>
+
+    <li>That you only ever merge all the changes available on the source branch
+    up to a chosen point (i.e. you can't only include a subset of the
+    changes made to the branch).</li>
+
+    <li>That the source and target are both branches (or the trunk) in the
+    same FCM project.</li>
+
+    <li>That the source and target are directly related, i.e. they must either
+    have a parent/child relationship or they are siblings from the same parent
+    branch.</li>
+  </ul>
+
+  <p>Note that the term "source branch" and "target branch" referred to above
+  can also mean the trunk.</p>
+
+  <p>To perform a merge, use the command <tt>fcm merge &lt;source&gt;</tt>. This
+  includes a number of important features:</p>
+
+  <ul>
+    <li>If it finds any local modifications in your working copy then it checks
+    whether you wish to continue (in most cases you won't want to mix a merge
+    with other changes).</li>
+
+    <li>It determines the base revision and path of the <em>common
+    ancestor</em> to be used for the merge, taking into account any merges from
+    the <em>source</em> to the <em>target</em> or vice-versa.</li>
+
+    <li>Before doing the merge, (unless you specify the
+    <tt>--non-interactive</tt> option), it reports what changes will result from
+    performing the merge and checks that you wish to continue.</li>
+
+    <li>It adds details of the merge, using a standard template, into the commit
+    message file (<tt>#commit_message#</tt>). If you need to add any extra
+    comment, you should do so <strong>above</strong> the line that says "--This
+    line will be ignored and those below will be inserted automatically--".
+
+      <ul>
+        <li>If you decide to revert the merge, you should remove the template
+        line manually from the commit message file, making sure that you do not
+        alter the standard template by accident.</li>
+      </ul>
+    </li>
+  </ul>
+
+  <table class="pad" summary="fcm merge example output" border="1" width=
+  "100%">
+    <tr>
+      <th>Example output from <tt>fcm merge</tt></th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm merge trunk # merge changes from the trunk into the branch
+Available Merges From /FCM/trunk: 1383 1375
+Please enter the revision you wish to merge from
+  (or just press <return> for "1383"):
+About to merge in changes from /FCM/trunk@1383 compared with /FCM/trunk@1371
+This merge will result in the following changes:
+--------------------------------------------------------------------------------
+A    doc/standards/fortran_standard.html
+U    src/lib/Fcm/ReposBranch.pm
+--------------------------------------------------------------------------------
+Would you like to go ahead with the merge?
+Enter "y" or "n" (or just press <return> for "n"): y
+Performing merge ...
+A    doc/standards/fortran_standard.html
+U    src/lib/Fcm/ReposBranch.pm
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <h3><a name="svn_gui">Using the GUI</a></h3>
+
+  <p>So far, all the tools described have been command line tools. Many people
+  will be happy with these but, for those who prefer it, there is also a simple
+  Graphical User Interface (GUI).</p>
+
+  <h4><a name="svn_gui_start">Starting the GUI</a></h4>
+
+  <p>To run the GUI simply issue the command <tt>fcm gui</tt> from the
+  directory you want as your working directory. You can also start the GUI from
+  within Konqueror (see <a href="#svn_gui_konqueror">Accessing the GUI from
+  Konqueror</a>).</p>
+
+  <p>The GUI consists of several sections:</p>
+
+  <ul>
+    <li>The top section contains a row of buttons to allow you to select which
+    command you want to run.</li>
+
+    <li>Beneath this is shown the current working directory and the top level
+    directory of your working copy (these may be the same).</li>
+
+    <li>Beneath this come various buttons and entry boxes to allow you to
+    configure the command you have selected. These vary according to the
+    command.</li>
+
+    <li>Beneath this comes a further row of buttons
+
+      <ul>
+        <li><em>Quit</em> - this exits the GUI.</li>
+
+        <li><em>Help</em> - this displays the help message for the selected
+        command.</li>
+
+        <li><em>Clear</em> - this empties the text window.</li>
+
+        <li><em>Run</em> - this allows you to run your command.</li>
+      </ul>
+    </li>
+
+    <li>Beneath this comes a scrolling text window where the output from the
+    commands is displayed.</li>
+
+    <li>The bottom section displays help information when you position the
+    cursor over various parts of the GUI.</li>
+  </ul>
+
+  <p class="image"><img src="gui1.png" alt=
+  "Example GUI screen with the Status commands selected"></p>
+
+  <p align="center">Example GUI screen with the <em>Status</em> commands
+  selected</p>
+
+  <p>If you run a more complicated command, like <tt>fcm branch</tt>, which
+  prompts for input then extra entry windows will pop up.</p>
+
+  <p class="image"><img src="gui2.png" alt="Example GUI pop-up window"></p>
+
+  <p align="center">Example GUI pop-up window</p>
+
+  <h4><a name="svn_gui_commands">GUI Commands</a></h4>
+
+  <p>The commands available from the GUI should be self explanatory. A few
+  points to note:</p>
+
+  <ul>
+    <li>If the current directory is not a working copy, you will only be able to
+    Checkout a working copy or create a branch from the GUI.</li>
+
+    <li>The <em>Checkout</em> command is only available if you start the GUI in
+    a directory which is not already a working copy. After successfully running
+    a checkout the GUI automatically sets the working directory to the top of
+    this new working copy.</li>
+
+    <li>With some commands (Status, Diff, Add, Delete, Conflicts) you can
+    choose whether to run from the top level of your working copy or from your
+    working directory. With the remaining commands this would not make sense
+    and they can only be run from the top level.</li>
+
+    <li>You can only issue commands from the GUI if they do not need to prompt
+    you for authentication (i.e. the Subversion command can be run with the
+    <em>--non-interactive</em> option).  
+
+      <ul>
+        <li>If authentication is required then the command issued by the GUI
+        will fail. For the "branch --create", "branch --delete" and "commit"
+        commands, which support the "--password" option, you should specify your
+        password in "Other options" and click "Run" again. For other commands,
+        you should run the command in interactive mode on the command line. Use
+        the command displayed in the GUI text window but remove the
+        <em>--non-interactive</em> option.</li>
+
+        <li>Most repositories will be configured so that you only need
+        authentication for writing (not reading). Therefore, the first command
+        requiring authentication will probably be creating a branch or commiting
+        to the trunk.</li>
+
+        <li>You should only need to do this the first time you ever issue such
+        a command on a each repository (unless the repository is moved to a new
+        location) since the Subversion client caches this information for future
+        comamnds .</li>
+      </ul>
+    </li>
+  </ul>
+
+  <h4><a name="svn_gui_konqueror">Accessing the GUI from Konqueror</a></h4>
+
+  <p>To enable access from Konqueror run the script
+  <tt>fcm_setup_konqueror</tt>. You can then use the Konqueror file manager to
+  select the directory which you want as your working directory. To run the GUI
+  click the right mouse button and select <em>Open With =&gt; FCM GUI</em>.</p>
+
+  <ul>
+    <li>Make sure that your current selection is the directory and not a file
+    within that directory.</li>
+  </ul>
+
+  <p class="image"><img src="konqueror.png" alt=
+  "Running the GUI from within Konqueror"></p>
+
+  <p align="center">Running the GUI from within Konqueror</p>
+
+  <h3><a name="svn_problems">Known Problems with Subversion</a></h3>
+
+  <p>There are some limitations with Subversion v1.3 which you should be aware
+  of:</p>
+
+  <ul>
+    <li>The <em>svn rename</em> command is not a true rename/move operation,
+    but is implemented as a copy and delete. As a result, if you rename an item
+    in a branch, and later attempt to merge it back to the trunk, the operation
+    may not be handled correctly by <em>svn merge</em> (see <a href=
+    "http://subversion.tigris.org/issues/show_bug.cgi?id=1864">subversion issue
+    1864</a> for further details). Support for a "true move" will hopefully be
+    available in Subversion in the near future. Until this is implemented, you
+    should avoid renaming of files or directories unless you can ensure that
+    no-one is working in parallel on the affected areas of the project.</li>
+  </ul>
+
+  <h2><a name="trac">Using Trac</a></h2>
+
+  <p><em>Trac</em> has a simple and intuitive web interface which is relatively
+  easy to pick up. It also includes a <a href=
+  "http://trac.edgewall.org/wiki/TracGuide">User and Administration Guide</a>
+  which is full of helpful information (and is referred to extensively in this
+  section).</p>
+
+  <p>Trac contains a menu bar at the top of each page (which we will refer to
+  as the <em>Trac menu</em>). This provides access to all the main
+  features.</p>
+
+  <h3><a name="trac_login">Logging In</a></h3>
+
+  <p>Although different projects may choose their own rules, we expect that
+  most systems will have Trac configured so that all the information is
+  viewable by anyone. However, in order to make any changes you will need to
+  login. This ensures that any changes are identified with the appropriate
+  userid.</p>
+
+  <p>In the rest of this section it is assumed that you have logged in to Trac
+  and are therefore able to make changes.</p>
+
+  <p>If you haven't yet got a Trac userid (which should be the same as the
+  userid you use for committing changes to Subversion) then please contact your
+  system manager.</p>
+
+  <h3><a name="trac_wiki">Using the Wiki Pages</a></h3>
+
+  <p>A wiki enables documents to be written in a simple markup language using a
+  web browser. See the Trac Guide for information on the <a href=
+  "http://trac.edgewall.org/wiki/TracWiki">Trac Wiki Engine</a>. Make sure that
+  you read the information provided on:</p>
+
+  <ul>
+    <li><a href="http://trac.edgewall.org/wiki/WikiFormatting">Wiki
+    Formatting</a> which explains how to format your wiki pages.</li>
+
+    <li><a href="http://trac.edgewall.org/wiki/WikiPageNames">Wiki Page
+    Names</a> which explains how <em>CamelCase</em> is used to create <a href=
+    "http://trac.edgewall.org/wiki/WikiNewPage">New Wiki Pages</a>.</li>
+
+    <li><a href="http://trac.edgewall.org/wiki/TracLinks">Trac Links</a> which
+    allow hyperlinking between Trac entities (tickets, reports, changesets,
+    Wiki pages, milestones and source files). This is a fundamental feature of
+    Trac which makes it easy, for example, to link a bug report (ticket) to the
+    changeset which fixed the bug (and vice-versa).</li>
+  </ul>
+
+  <p>Whenever you are viewing a wiki page in Trac you should see several
+  buttons at the bottom of the page:</p>
+
+  <ul>
+    <li><em>Edit This Page</em> - Clicking this will bring up a page where you
+    can edit the page contents. Before saving your changes you can preview how
+    the modified page will appear. You can also leave a comment explaining what
+    changes you made.</li>
+
+    <li><em>Attach File</em> - Allows you to attach files to a page, e.g. an
+    image.</li>
+
+    <li>If you have admin rights then you will also see
+
+      <ul>
+        <li><em>Delete This Version</em> - Delete the particular version of the
+        page you are viewing.</li>
+
+        <li><em>Delete Page</em> - Delete the page and all its history.</li>
+      </ul>Use with care - these operations are irreversible!
+    </li>
+  </ul>
+
+  <p>At the top of each wiki page at the right hand side you can select
+  <em>Page History</em>. This shows you the full history of each page with
+  details of when each change was made, who made the change and what the
+  changes were.</p>
+
+  <h3><a name="trac_browser">Using the Repository Browser</a></h3>
+
+  <p>The <a href="http://trac.edgewall.org/wiki/TracBrowser">Trac Browser</a>
+  is used to view the contents of your repository. To get to it just select
+  <em>Browse Source</em> from the Trac menu. You can view directories and files
+  at any version, see their revision histories and view <a href=
+  "http://trac.edgewall.org/wiki/TracChangeset">changesets</a>. Any wiki
+  formatting in log messages is recognised and interpreted so you can easily
+  link a changeset to a Trac ticket by using <a href=
+  "http://trac.edgewall.org/wiki/TracLinks">Trac Links</a>.</p>
+
+  <h3><a name="trac_tickets">Using the Issue Tracker</a></h3>
+
+  <p>The Trac issue database provides a way of tracking issues within a project
+  (e.g. bug reports, feature requests, software support issues, project tasks).
+  Within Trac an issue is often referred to as a <em>Ticket</em>.</p>
+
+  <p>Please refer to the Trac Guide for the following information:</p>
+
+  <ul>
+    <li>
+      <a href="http://trac.edgewall.org/wiki/TracTickets">The Trac Ticket
+      System</a> - Creating and modifying tickets.
+
+      <ul>
+        <li>Only Trac accounts with admin rights can modify ticket
+        descriptions.</li>
+      </ul>
+    </li>
+
+    <li><a href="http://trac.edgewall.org/wiki/TracQuery">Trac Ticket
+    Queries</a> - List tickets matching your chosen criterion.</li>
+  </ul>
+
+  <h3><a name="trac_roadmap">Using the Roadmap</a></h3>
+
+  <p>Each ticket can be assigned to a milestone. The Trac Roadmap can then be
+  used to provide a view on the ticket system. This can useful to see what
+  changes went into a particular system release or what changes are outstanding
+  before a milestone can be reached.</p>
+
+  <p>Please refer to the Trac Guide for further information on the <a href=
+  "http://trac.edgewall.org/wiki/TracRoadmap">Trac Roadmap</a>.</p>
+
+  <ul>
+    <li>Only Trac accounts with admin rights can add, modify and remove
+    milestones using the web interface.</li>
+  </ul>
+
+  <h3><a name="trac_timeline">Using the Timeline</a></h3>
+
+  <p>The <a href="http://trac.edgewall.org/wiki/TracTimeline">Trac Timeline</a>
+  allows you to list all the acitivity on a project over any given period. It
+  can list:</p>
+
+  <ul>
+    <li>Creation and changes to wiki pages.</li>
+
+    <li>Creation, closure and changes to tickets.</li>
+
+    <li>Commits to the Subversion repository.</li>
+
+    <li>Milestones reached.</li>
+  </ul>
+  
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/user_guide/command_ref.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/user_guide/command_ref.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/user_guide/command_ref.html	(revision 1665)
@@ -0,0 +1,1270 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide: FCM Command Reference</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide - FCM Command Reference">
+  <meta name="keywords" content="FCM, user guide, command reference">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; FCM Command Reference
+  </address>
+
+  <h1>FCM Command Reference</h1>
+
+  <h2><a name="fcm_config">fcm Configuration File</a></h2>
+
+  <p>The FCM system uses simple line based text files to store configuration
+  settings. All configuration files used by FCM are based on the same
+  principles:</p>
+
+  <ul>
+    <li>All configurations are stored in plain text files.</li>
+
+    <li>A line in a file may contain a configuration setting or a comment.</li>
+
+    <li>Blank lines are ignored.</li>
+
+    <li>A line that begins with a <tt>#</tt> is a <em>comment</em> line.</li>
+
+    <li>Each configuration line has a <em>label</em>, a <em>value</em> and
+    optionally a trailing <em>comment</em>. For example:
+      <pre>
+my::label  this is the value  # some comment
+</pre>
+    </li>
+
+    <li>A <em>label</em> in a configuration line may contain any non-space
+    character. A space character marks the end of the <em>label</em>.</li>
+
+    <li>Words or fields in the <em>label</em> are normally delimited by the
+    double colon (<tt>::</tt>).</li>
+
+    <li>The first non-space character after the <em>label</em> is the beginning
+    of the <em>value</em>. The <em>value</em> may contain space characters. The
+    newline character or the character sequence <tt>" # "</tt> marks the end of
+    the <em>value</em>.</li>
+
+    <li>The first non-space character after the character sequence <tt>" #
+    "</tt> at the end of the <em>value</em> is the <em>comment</em>. The
+    <em>comment</em> is normally ignored by the parser of the configuration
+    file.</li>
+
+    <li>If the last character of the <em>value</em> is a backslash "\", the
+    next non-comment line will be the continuation of the current line. Please
+    note that trailing spaces before the continuation mark are preserved, and
+    leading spaces are removed from the beginning of a continuation. If you
+    want to have leading spaces in a continued line, start the line with a
+    backslash "\" before the leading spaces. It is also worth bearing in mind
+    that the backslash "\" character is only significant if it appears at the
+    end of a value or the beginning of a continuation line. It is not a special
+    character if it appears elsewhere. For example:
+      <pre>
+foo bar\
+    egg\
+    ham
+# will become:
+foo bareggham
+
+foo bar \
+    egg \
+    ham
+# will become:
+foo bar egg ham
+
+foo bar\
+    \ egg\
+    \ ham
+# will become:
+foo bar egg ham
+
+foo bar\
+    \ egg\ham
+# will become:
+foo bar egg\ham
+</pre>
+    </li>
+  </ul>
+
+  <p>The FCM central and user configuration files can be used to add or modify
+  some of the default settings of FCM. When the <em>fcm</em> command is
+  invoked, it normally attempts to search for a central configuration file at
+  <tt>$BINDIR/../etc/fcm.cfg</tt> and then <tt>$BINDIR/fcm.cfg</tt>, where
+  <tt>$BINDIR</tt> is the container directory of the <em>fcm</em> command. If a
+  central configuration file can be located, the settings in the file will
+  replace the pre-defined ones. After searching/reading the central
+  configuration file, the system will attempt to search for a user
+  configuration file located at <tt>$HOME/.fcm</tt> of the current user. If
+  such a file can be found, its settings will replace the pre-defined ones as
+  well as those defined in the central configuration file.</p>
+
+  <p>For information on the valid entries in the central and user configuration
+  files, please refer to the <a href="annex_fcm_cfg.html">Annex: Declarations
+  in FCM central/user configuration file</a>.</p>
+
+  <h2><a name="fcm_bld">fcm build</a></h2>
+
+  <h4>Usage</h4>
+
+  <p>fcm build [OPTIONS...] [CFGFILE]</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm build</tt> invokes the FCM build system.</p>
+
+  <p>The path to a valid build configuration file <tt>CFGFILE</tt> may be
+  provided as either a URL or a pathname. Otherwise, the build system
+  searches the default locations for a build configuration file.</p>
+
+  <p>If no option is specified, the system uses the "<tt>-s 5 -t all -j 1 -v
+  1</tt>" by default.</p>
+
+  <ul>
+    <li>The "<tt>-a [--archive]</tt>" option can be specified to switch on the
+    archive mode. In archive mode, sub-directories produced by the build will
+    be archived in <em>tar</em> format at the end of a successful build. This
+    option should not be used if the current build is intended to be re-used as
+    a pre-compiled build.</li>
+
+    <li>If the "<tt>-f [--full]</tt>" option is specified, the build system
+    will attempt to perform a full/clean build by removing any previous build
+    files. Otherwise, the build system will attempt to perform an incremental
+    build where appropriate.</li>
+
+    <li>When the build system is invoked, it sets a lock file in the build root
+    directory to prevent other extracts/builds taking place in the same
+    location. The lock file is normally removed when the build system exits.
+    (However, a lock file may be left behind if the user interrupts the command,
+    e.g. by typing <tt>Ctrl-C</tt>.) You can bypass the check for lock files by
+    using the "<tt>--ignore-lock</tt>" option.</li>
+
+    <li>The "<tt>-j [--jobs] arg</tt>" option can be used to specify the number
+    of parallel jobs that can be handled by the <em>make</em> command. The
+    argument <tt>arg</tt> must be a natural integer to represent the number of
+    jobs. If not specified, the default is to perform serial <em>make</em>
+    (i.e. 1 job).</li>
+
+    <li>The "<tt>-s [--stage] arg</tt>" option can be used to limit the actions
+    performed by the build system, up to a named stage determined by the
+    argument <tt>arg</tt>. If not specified, the default is 5. The stages are:
+
+      <ul>
+        <li>"1", "s" or "setup": stage 1, read configuration and set up the
+        build</li>
+
+        <li>"2", "pp" or "pre_process": stage 2, perform pre-processing for
+        source files that require pre-processing</li>
+
+        <li>"3", "gd" or "generate_dependency": stage 3, scan source files for
+        dependency information and generate <em>make</em> rules for them</li>
+
+        <li>"4", "gi" or "generate_interface": stage 4, generate interface
+        files for Fortran 9X source files</li>
+
+        <li>"5", "m", "make": stage 5, invoke the <em>make</em> command to
+        build the project</li>
+      </ul>
+    </li>
+
+    <li>The "<tt>-t [--targets] arg</tt>" can be used to specify the targets to
+    be built. The argument <tt>arg</tt> must be a colon-separated list of valid
+    targets. If not specified, the default target to be built is the "all"
+    target.</li>
+
+    <li>The "<tt>-v [--verbose] arg</tt>" option can be specified to alter the
+    level of diagnostic output. The argument <tt>arg</tt> to this option must
+    be an integer greater than or equal to 0. The verbose level increases with
+    this number. If not specified, the default verbose level is 1.</li>
+  </ul>
+
+  <p>For further details, please refer to the chapter on <a href=
+  "build.html">The Build System</a>.</p>
+
+  <h4>Alternate Names</h4>
+
+  <p>bld</p>
+
+  <h2><a name="fcm_ext">fcm extract</a></h2>
+
+  <h4>Usage</h4>
+
+  <p>fcm extract [OPTIONS...] [CFGFILE]</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm extract</tt> invokes the FCM extract system.</p>
+
+  <p>The path to a valid extract configuration file <tt>CFGFILE</tt> may be
+  provided as either a URL or a pathname. Otherwise, the extract system
+  searches the default locations for an extract configuration file.</p>
+
+  <ul>
+    <li>If the "<tt>-f [--full]</tt>" option is specified, the extract system
+    will attempt to perform a full/clean extraction by removing any previous
+    extracted files. Otherwise, the extract system will attempt to perform an
+    incremental extraction where appropriate.</li>
+
+    <li>When the extract system is invoked, it sets a lock file in the extract
+    destination root directory to prevent other extracts/builds taking place in
+    the same location. The lock file is normally removed when the extract system
+    exits.  (However, a lock file may be left behind if the user interrupts the
+    command, e.g. by typing <tt>Ctrl-C</tt>.) You can bypass the check for lock
+    files by using the "<tt>--ignore-lock</tt>" option.</li>
+
+    <li>The "<tt>-v [--verbose] arg</tt>" option can be specified to alter the
+    level of diagnostic output. The argument <tt>arg</tt> to this option must
+    be an integer greater than or equal to 0. The verbose level increases with
+    this number. If not specified, the default verbose level is 1.</li>
+  </ul>
+
+  <p>For further details, please refer to the chapter on <a href=
+  "extract.html">The Extract System</a>.</p>
+
+  <h4>Alternate Names</h4>
+
+  <p>ext</p>
+
+  <h2><a name="fcm_cmp-ext-cfg">fcm cmp-ext-cfg</a></h2>
+
+  <h4>Usage</h4>
+
+  <p>fcm cmp-ext-cfg [--verbose (-v)] [--wiki (-w) arg] CFG1 CFG2</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm cmp-ext-cfg</tt> compares the extract configurations of two similar
+  extract configuration files CFG1 and CFG2. It reports repository branches and
+  source directories that are declared in one file but not another. If a source
+  directory is declared in both files, it compares their versions. If they
+  differ, it uses <tt>svn log</tt> to obtain a list of revision numbers at which
+  changes are made to the source directory. It then reports, for each declared
+  repository branch, the revisions at which changes occur in their declared
+  source directories.</p>
+
+  <p>The list of revisions for each declared repository branch is normally
+  printed out as a simple list in plain text.</p>
+  
+  <ul>
+    <li>You can use the <tt>--verbose</tt> option to print also the log of each
+    revision.</li>
+
+    <li>Alternatively, you can use the <tt>--wiki</tt> option to change that
+    into an tabular output suitable for inserting into a Trac wiki page. The
+    <tt>--wiki</tt> option must be specified with an argument, which must be the
+    Subversion URL or FCM URL keyword of a FCM project associated with the
+    intended Trac system. The URL allows the command to work out the correct
+    wiki syntax to use.</li>
+  </ul>
+
+  <h2><a name="fcm_gui">fcm gui</a></h2>
+
+  <h4>Usage</h4>
+
+  <p>fcm gui [DIR]</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm gui</tt> starts up the FCM GUI. If DIR is specified then this is
+  used as the working directory.</p>
+
+  <p>For further details, please refer to the section <a href=
+  "code_management.html#svn_gui">Using the GUI</a>.</p>
+
+  <h2><a name="fcm_svn">fcm Subversion Subcommands</a></h2>
+
+  <p>This section describes all of the Subversion related commands supported by
+  <tt>fcm</tt>.</p>
+
+  <ul>
+    <li>In some cases <tt>fcm</tt> simply passes the command directly on to
+    <tt>svn</tt> (after expanding any URL keywords). These commands are
+    listed in the <a href="#fcm_svn_other">Other Subversion Commands</a>
+    section.</li>
+
+    <li>Where <tt>fcm</tt> adds functionality these commands are discussed
+    individually.</li>
+
+    <li>In all cases, all the command abbreviations supported by <tt>svn</tt>
+    work with <tt>fcm</tt>.</li>
+  </ul>
+
+  <h3><a name="fcm_svn_add">fcm add</a></h3>
+
+  <h4>Usage</h4>
+
+  <p>fcm add --check (-c)</p>
+ 
+  <p>fcm add &lt;any valid <em>svn add</em> options&gt;</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm add</tt> supports all of the switches and arguments supported by
+  <tt>svn add</tt> (refer to the <a href=
+  "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.add.html">Subversion
+  book</a> for details).</p>
+
+  <p>In addition, <tt>fcm add</tt> supports a <tt>--check</tt> switch (no
+  other switches or arguments). When this is specified then <tt>fcm</tt>
+  checks for any files which are not currently under version control (i.e. those
+  marked with a "?" by <tt>svn status</tt>) and prompts to see if you wish to
+  schedule them for addition at the next commit (using <tt>svn add</tt>).</p>
+
+  <p>For further details refer to the section <a href=
+  "code_management.html#svn_basic_check">Adding and Removing
+  Files</a>.</p>
+
+  <h3><a name="fcm_svn_br">fcm branch</a></h3>
+
+  <h4>Usage</h4>
+
+  <p>fcm branch [--info (-i)] [--verbose (-v)] [--show-children]
+  [--show-siblings] [--show-other] [--show-all (-a)] [TARGET]</p>
+
+  <p>fcm branch --delete (-d) [--verbose (-v)] [--show-children]
+  [--show-siblings] [--show-other] [--show-all (-a)] [--svn-non-interactive]
+  [--non-interactive] [--password arg] [TARGET]</p>
+
+  <p>fcm branch --create (-c) --name (-n) arg [--type (-t) arg] [--rev-flag arg]
+  [--ticket (-k) arg] [--branch-of-branch] [--svn-non-interactive]
+  [--non-interactive] [--password arg] [--revision arg] [TARGET]</p>
+
+  <p>fcm branch --list (-l) [--user (-u) arg] [--verbose (-v)] [--revision arg]
+  [TARGET]</p>
+
+  <h4>Description</h4>
+
+  <p>If TARGET is specified, it must either be a URL or a path to a local
+  working copy. Otherwise, the current working directory must be a working copy.
+  For <tt>--info</tt> and <tt>--delete</tt>, the specified URL or that of the
+  working copy must be a valid branch (including the trunk) in a standard FCM
+  project. For <tt>--create</tt> and <tt>--list</tt>, it must be a valid URL of
+  a standard FCM project.</p>
+
+  <p><tt>fcm branch --info</tt> displays information about a branch.</p>
+
+  <ul>
+    <li>This is the default if no options are specified (e.g. if you just
+    issue the command <tt>fcm br</tt>).</li>
+
+    <li>This command performs the following actions:
+
+      <ul>
+        <li>It reports the basic information of the branch URL, as returned
+        by "svn info".</li>
+
+        <li>If <tt>--verbose</tt> is set, it also prints the log message of
+        the last change revision.</li>
+
+        <li>If the URL is not the trunk:
+        
+          <ul>
+            <li>It reports the branch creation information, including the
+            revision, author and date. It also reports the parent URL@REV of the
+            branch.  If <tt>--verbose</tt> is set, it prints the log message of
+            the branch creation revision.</li>
+
+            <li>If the branch does not exist at the HEAD, it reports the
+            revision at which it is deleted.</li>
+
+            <li>It reports the last merges into and from the parent branch. If
+            <tt>--verbose</tt> is set, it also prints the log message of
+            these merges.</li>
+
+            <li>It reports the revisions available for merging into and from the
+            parent branch. If <tt>--verbose</tt> is set, it also prints the log
+            message of these revisions.</li>
+          </ul>
+        </li>
+
+        <li>If <tt>--show-children</tt> is specified, it lists the current
+        children of the branch and their create revisions. Where appropriate, it
+        reports the revision of each child, which is last merged from/into the
+        current branch. It also reports the available merges from/into each
+        child into the current branch.</li>
+
+        <li>If <tt>--show-siblings</tt> is specified, it reports recent merges
+        from/into sibling branches. It also reports the available merges
+        from/into sibling branches where recent merges are detected. If
+        <tt>--verbose</tt> is set, it also prints the log message of these
+        merges.</li>
+
+        <li>If <tt>--show-other</tt> is specified, it reports all custom and
+        reverse merges into the current branch.</li>
+
+        <li>You can turn on <tt>--show-children</tt>, <tt>--show-siblings</tt>
+        and <tt>--show-other</tt> simultaneously by specifying
+        <tt>--show-all</tt>.</li>
+      </ul>
+    </li>
+
+    <li>For further details refer to the section <a href=
+    "code_management.html#svn_branching_info">Getting Information About
+    Branches</a>.</li>
+  </ul>
+
+  <p><tt>fcm branch --delete</tt> deletes a branch.</p>
+
+  <ul>
+    <li>This command performs the following actions:
+
+      <ul>
+        <li>Firstly, it provides exactly the same output as <tt>fcm branch
+        --info</tt>.</li>
+
+        <li>If you do not specify the <tt>--non-interactive</tt> option, it starts an
+        editor (using a similar convention as <a href= "#fcm_svn_ci">commit</a>)
+        to allow you to add further comment to the commit log message. A
+        standard commit log template is provided for you below the line that
+        says "--This line will be ignored and those below will be inserted
+        automatically--". If you need to add any extra message to the log,
+        please do so <strong>above</strong> this line. When you exit the editor,
+        the command will report the commit log before prompting for confirmation
+        that you wish to proceed with deleting the branch (it aborts if
+        not).</li>
+      </ul>
+    </li>
+
+    <li>If you specify the <tt>--non-interactive</tt> option, the command will not prompt
+    you for anything. (The <tt>--svn-non-interactive</tt> option is set automatically
+    when you specify <tt>--non-interactive</tt>.)</li>
+
+    <li>Subversion may prompt you for authentication if it is the first time
+    you access the repository. The command fails if the authentication
+    fails. If you specify the <tt>--svn-non-interactive</tt> option, Subversion will not
+    prompt you for authentication. In such case, the command will simply
+    fail if authentication is required. You can use the <tt>--password</tt> option to
+    specify a password. Please note that the <tt>--svn-non-interactive</tt> option is
+    always specified if you are running <tt>branch --delete</tt> from the FCM GUI.
+    If authentication is required, you should specify your password using
+    the <tt>--password</tt> option in "Other options".</li>
+
+    <li>For further details refer to the section <a href=
+    "code_management.html#svn_branching_delete">Deleting Branches</a>.</li>
+  </ul>
+
+  <p><tt>fcm branch --create</tt> creates a new branch.</p>
+
+  <ul>
+    <li>You have to choose a name for your branch. This must be specified
+    as the argument of the <tt>--name (-n)</tt> option. The name of the branch must
+    contain only word characters, i.e. [A-Za-z0-9_].</li>
+
+    <li>You can specify the type of branch you are creating using the
+    <tt>--type (-t)</tt> option. The argument to the option must be one of the
+    following:
+
+      <ul>
+        <li>DEV::USER - a development branch for the current user (e.g.
+        branches/dev/&lt;user_id&gt;/&lt;branch_name&gt;)</li>
+
+        <li>DEV::SHARE - a shared development branch (e.g.
+        branches/dev/Share/&lt;branch_name&gt;)</li>
+
+        <li>DEV - same as DEV::USER</li>
+
+        <li>TEST::USER - a test branch for the current user (e.g.
+        branches/test/&lt;user_id&gt;/&lt;branch_name&gt;)</li>
+
+        <li>TEST::SHARE - a shared test branch (e.g.
+        branches/test/Share/&lt;branch_name&gt;)</li>
+
+        <li>TEST - same as TEST::USER</li>
+
+        <li>PKG::USER - a package branch for the current user (e.g.
+        branches/pkg/&lt;user_id&gt;/&lt;branch_name&gt;)</li>
+
+        <li>PKG::SHARE - a shared package branch (e.g.
+        branches/pkg/Share/&lt;branch_name&gt;)</li>
+
+        <li>PKG::CONFIG - a configuration branch (e.g.
+        branches/pkg/Config/&lt;branch_name&gt;)</li>
+
+        <li>PKG::REL - a release branch (e.g.
+        branches/pkg/Rel/&lt;branch_name&gt;)</li>
+
+        <li>PKG - same as PKG::USER</li>
+
+        <li>CONFIG - same as PKG::CONFIG</li>
+
+        <li>REL - same as PKG::REL</li>
+
+        <li>SHARE - same as DEV::SHARE</li>
+
+        <li>USER - same as DEV::USER</li>
+      </ul>
+
+      <p>If the <tt>--type</tt> option is not specified, it defaults to
+      DEV::USER.</p>
+    </li>
+
+    <li>Your branch name will normally be prefixed by the revision number
+    from which it is branched. (E.g. if the branch name is "my_branch" and
+    you are branching from revision 123 of the trunk, the final name will
+    be "r123_my_branch".) If this revision number is associated with a
+    revision keyword, the keyword will be used in place of the revision
+    number. (E.g. if revision 123 is associated with the keyword vn6.1,
+    "r123_my_branch" will become "vn6.1_my_branch".) You can alter this
+    behaviour using the argument to the <tt>--rev-flag</tt> option. If NORMAL is
+    specified, it uses the default behaviour. If NUMBER is specified, it
+    will always use the revision number as the prefix, regardless of
+    whether the revision number is defined as a keyword or not. If NONE is
+    specified, it will not add a prefix to your branch name.</li>
+
+    <li>The command will normally create your branch from the last changed
+    revision of the trunk of the specified project.
+      
+      <ul>
+        <li>You can use the <tt>--revision</tt> option to specify an earlier revision of
+        the source.</li>
+
+        <li>If the source URL is a valid URL of a branch in a standard FCM
+        project, you can use the <tt>--branch-of-branch</tt> option to create
+        a branch of the source branch.</li>
+      </ul>
+    </li>
+
+    <li>The <tt>--ticket</tt> option can be used to specify one or more Trac ticket
+    numbers, which the branch relates to. Multiple ticket numbers can be set
+    by specifying this option multiple times, or by using a comma-separated
+    list of ticket numbers as the argument to the option. If set, the line
+    "Relates to ticket #&lt;number&gt;[, #&lt;number&gt;...]" will be added
+    to the template commit log.</li>
+
+    <li>If you specify the <tt>--non-interactive</tt> option, the command will not prompt
+    you for anything. (The <tt>--svn-non-interactive</tt> option is set automatically
+    when you specify <tt>--non-interactive</tt>.)</li>
+
+    <li>Subversion may prompt you for authentication if it is the first time
+    you access the repository. The command fails if the authentication
+    fails. If you specify the <tt>--svn-non-interactive</tt> option, Subversion will not
+    prompt you for authentication. In such case, the command will simply
+    fail if authentication is required. You can use the <tt>--password</tt> option to
+    specify a password. Please note that the <tt>--svn-non-interactive</tt> option is
+    always specified if you are running <tt>branch --create</tt> from the FCM GUI.
+    If authentication is required, you should specify your password using
+    the <tt>--password</tt> option in "Other options".</li>
+
+    <li>This command performs the following actions:
+
+      <ul>
+        <li>It determines the last changed revision of the trunk/source branch
+        at the HEAD (or the specified) revision.</li>
+
+        <li>It constructs the branch name from the option you have
+        specified and reports it.</li>
+
+        <li>It checks that the chosen branch name does not currently exist.
+        If so, the command aborts with an error.</li>
+
+        <li>If you do not specify the <tt>--non-interactive</tt> option, it starts an
+        editor (using a similar convention as <a href= "#fcm_svn_ci">commit</a>)
+        to allow you to add further comment to the commit log message. A
+        standard commit log template is provided for you below the line that
+        says "--This line will be ignored and those below will be inserted
+        automatically--". If you need to add any extra message to the log,
+        please do so <strong>above</strong> this line. When you exit the editor,
+        the command will report the commit log before prompting for confirmation
+        that you wish to proceed (it aborts if not).</li>
+
+        <li>It uses <tt>svn mkdir</tt> to create any sub-directories
+        required for the copy to succeed.</li>
+
+        <li>It uses <tt>svn copy</tt> to create the branch.</li>
+      </ul>
+    </li>
+
+    <li>For further details refer to the section <a href=
+    "code_management.html#svn_branching_create">Creating Branches</a>.</li>
+  </ul>
+
+  <p><tt>fcm branch --list</tt> lists the branches created by you (and/or other
+  users) at the HEAD revision of a standard FCM project.</p>
+
+  <ul>
+    <li>By default, it lists the branches created by you at the HEAD revision.
+    To display the branches at a different revision, you can use the
+    <tt>--revision arg</tt> option.</li>
+
+    <li>You can specify a list of users with the <tt>--user arg</tt>
+    option, where "arg" is a colon separated list of users. (Alternatively,
+    you can specify this option multiple times.) When this option is set,
+    the command lists the branches created by the specified list of users
+    instead.</li>
+
+    <li>By default, it lists the branches in the FCM URL keyword format. If you
+    want to print the full Subversion URL of the branches, you can use the
+    <tt>--verbose</tt> option.</li>
+
+    <li>The command returns 0 (success) if one or more branches is found
+    for the specified users, or 1 (failure) if no branch is found.</li>
+  </ul>
+
+  <h4>Alternate Names</h4>
+
+  <p>br</p>
+
+  <h3><a name="fcm_svn_ci">fcm commit</a></h3>
+
+  <h4>Usage</h4>
+
+  <p>fcm commit [--dry-run] [--svn-non-interactive] [--password arg] [PATH]</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm commit</tt> sends changes from your working copy in the current
+  working directory (or from PATH if it is specified) to the repository.</p>
+
+  <ul>
+    <li>This command performs the following actions:
+
+      <ul>
+        <li>It checks that the current working directory (or PATH if it is
+        specified) is a working copy. (If not, it aborts with an error).</li>
+
+        <li>It always commits from the top level of the working copy.</li>
+
+        <li>It checks that there are no files in conflict, missing or out of
+        date (it aborts if there are).</li>
+
+        <li>It checks that any files which have been added have the
+        <em>svn:executable</em> property set correctly (in case a script was
+        added before the execute bit was set correctly).</li>
+
+        <li>It reads in any existing commit message and strips out any previous
+        status info (it starts with an empty file if there is none).
+
+          <ul>
+            <li>The commit message is stored in the file
+            <tt>#commit_message#</tt> in the top level of your working
+            copy.</li>
+          </ul>
+        </li>
+
+        <li>If you have run the <a href="fcm_svn_merge">merge</a> command
+        before the commit, you will get a standard commit log template below
+        the line that says "--This line will be ignored and those below will be
+        inserted automatically--". If you need to add any extra message to the
+        log, please do so <strong>above</strong> this line.</li>
+
+        <li>It adds the following line to the commit message:<br>
+        <tt>--This line, and those below, will be ignored--</tt><br>
+        This line, and anything below it, is automatically ignored by <tt>svn
+        commit</tt>.</li>
+
+        <li>It adds current status information to the commit message showing
+        the list of modifications.</li>
+
+        <li>It starts an editor to allow you to edit the commit message.
+
+          <ul>
+            <li>If defined, the environment variable SVN_EDITOR specifies the
+            editor.</li>
+
+            <li>Otherwise the environment variable VISUAL specifies the
+            editor.</li>
+
+            <li>Otherwise the environment variable EDITOR specifies the
+            editor.</li>
+
+            <li>Otherwise the editor <em>nedit</em> is used.</li>
+          </ul>
+        </li>
+
+        <li>It reports the commit message and then asks if you want to proceed
+        (it aborts if not).</li>
+
+        <li>It calls <tt>svn commit</tt> to send the changes to the
+        repository.</li>
+
+        <li>It calls <tt>svn update</tt> to bring your working copy up to the
+        new revision.</li>
+      </ul>
+    </li>
+
+    <li>Subversion may prompt you for authentication if it is the first time you
+    access the repository. The command fails if the authentication fails. If you
+    specify the <tt>--non-interactive</tt> option, Subversion will not prompt you for
+    authentication. In such case, the command will simply fail if authentication
+    is required. You can use the <tt>--password</tt> option to specify a password. Please
+    note that the <tt>--svn-non-interactive</tt> option is always specified if you are
+    running "commit" from the FCM GUI. If authentication is required, you should
+    specify your password using the <tt>--password</tt> option in "Other options".</li>
+
+    <li>The <tt>--dry-run</tt> switch prevents the command from committing any
+    changes. This can be used to allow you to add notes to your commit message
+    whilst you are still preparing your change.</li>
+  </ul>
+
+  <p>For further details refer to the section <a href=
+  "code_management.html#svn_basic_commit">Committing Changes</a>.</p>
+
+  <h4>Alternate Names</h4>
+
+  <p>ci</p>
+
+  <h3><a name="fcm_svn_cf">fcm conflicts</a></h3>
+
+  <h4>Usage</h4>
+
+  <p>fcm conflicts [PATH]</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm conflicts</tt> helps you to resolve any text files in your working
+  copy which have conflicts by using the graphical merge tool <em>xxdiff</em>.
+  If PATH is set, it must be a working copy, and the command will operate in
+  it. If PATH is not set, the command will operate in your current working
+  directory.</p>
+
+  <li>This command performs the following actions:
+
+    <ul>
+      <li>For each text file reported as being in conflict (i.e. marked with a
+      "C" by <tt>svn status</tt>) it calls <tt>xxdiff</tt>.</li>
+
+      <li>If <tt>xxdiff</tt> reports all conflicts resolved then if asks if
+      you wish to run <tt>svn resolved</tt> on that file.</li>
+    </ul>
+  </li>
+
+  <p>For further details refer to the section <a href=
+  "code_management.html#svn_basic_conflicts">Resolving Conflicts</a>.</p>
+
+  <h4>Alternate Names</h4>
+
+  <p>cf</p>
+
+  <h3><a name="fcm_svn_rm">fcm delete</a></h3>
+
+  <h4>Usage</h4>
+
+  <p>fcm delete --check (-c)</p>
+
+  <p>fcm delete &lt;any valid <em>svn delete</em> options&gt;</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm delete</tt> supports all of the switches, arguments and alternate
+  names supported by <tt>svn delete</tt> (refer to the <a href=
+  "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.delete.html">Subversion
+  book</a> for details).</p>
+
+  <ul>
+    <li>In addition, <tt>fcm delete</tt> supports a <tt>--check</tt> switch (no
+    other switches or arguments). When this is specified then <tt>fcm</tt>
+    checks for any files which are missing (i.e. marked with a "!" by <tt>svn
+    status</tt>) and prompts to see if you wish to schedule them for deletion
+    at the next commit (using <tt>svn delete</tt>).
+
+    <li>Subversion may prompt you for authentication if it is the first time
+    you access the repository. The command fails if the authentication fails.
+    If you specify the <tt>--non-interactive</tt> option, Subversion will not prompt
+    you for authentication. In such case, the command will simply fail if
+    authentication is required. Please note that the <tt>--non-interactive</tt> option
+    is automatically specified if you are running "delete" from the FCM GUI and
+    you have not checked the box "Check for files and directories...". If
+    authentication is required, you should run "delete" in interactive mode on
+    a command line.</li>
+  </ul>
+
+  <p>For further details refer to the section <a href=
+  "code_management.html#svn_basic_check">Adding and Removing Files</a>.</p>
+
+  <h3><a name="fcm_svn_diff">fcm diff</a></h3>
+
+  <h4>Usage</h4>
+
+  <p>fcm diff --branch (-b) [--graphical (-g) | --diff-cmd arg [--extensions
+  (-x) arg] | --wiki | --trac (-t)] [TARGET]</p>
+
+  <p>fcm diff [--graphical (-g) | --diff-cmd arg [--extensions (-x) arg]]
+  &lt;any valid <em>svn diff</em> options&gt;</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm diff</tt> supports all of the switches, arguments and alternate
+  names supported by <tt>svn diff</tt> (refer to the <a href=
+  "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.diff.html">Subversion
+  book</a> for details). In addition, <tt>fcm diff</tt> supports the following
+  switches:</p>
+
+  <ul>
+    <li>If <tt>--graphical</tt> is specified, the command uses a graphical tool
+    to display the differences. (The default graphical <em>diff</em> tool is
+    <em>xxdiff</em>, but you can alter the behaviour by following the
+    instruction discussed in the sub-section on <a href=
+    "code_management.html#svn_basic_diff">Examining Changes</a>.) This
+    switch can be used in combination with all other valid switch (including
+    <tt>--branch</tt>) except <tt>--diff-cmd</tt>, <tt>--extensions</tt>,
+    <tt>--trac</tt> and <tt>--wiki</tt>.</li>
+
+    <li>If <tt>--branch</tt> is specified, the command displays the differences
+    between the target branch and its parent. This should show you the
+    differences which you would get if you tried to merge the changes in the
+    branch into its parent. It performs the following actions:
+
+      <ul>
+        <li>If TARGET is specified, it must either be a URL or a path to a
+        local working copy. Otherwise, the current working directory must be a
+        working copy. The specified URL or that of the working copy must be a
+        valid branch in a standard FCM project.</li>
+
+        <li>It determines the base of the branch relative to its parent. This is
+        adjusted to account for any merges from the branch to its parent or
+        vice-versa.</li>
+
+        <li>It reports what path and revision it is comparing against.</li>
+
+        <li>If <tt>--trac</tt> is specified, it launches Trac with your default
+        web browser to display it. Note: if TARGET is a working copy, local
+        changes in it will not be displayed by Trac.</li>
+
+        <li>If <tt>--wiki</tt> is specified, it prints a Trac wiki syntax for
+        the differences between the base and the specified branch.</li>
+
+        <li>Otherwise, it calls <tt>svn diff</tt> to report the differences
+        between the base and the specified branch (or working copy).</li>
+      </ul>
+    </li>
+  </ul>
+
+  <p>For further details refer to the section <a href=
+  "code_management.html#svn_basic_diff">Examining Changes</a>.</p>
+
+  <h3><a name="fcm_svn_merge">fcm merge</a></h3>
+
+  <h4>Usage</h4>
+
+  <p>fcm merge [--dry-run] [--non-interactive] [--verbose (-v)] SOURCE</p>
+
+  <p>fcm merge --custom --revision N[:M] [--dry-run] [--non-interactive]
+  [--verbose (-v)] SOURCE</p>
+
+  <p>fcm merge --custom [--dry-run] [--non-interactive] [--verbose (-v)]
+  URL1[@REV1] URL2[@REV2]</p>
+
+  <p>fcm merge --reverse --revision [M:]N [--dry-run] [--non-interactive]
+  [--verbose (-v)]</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm merge</tt> allows you to merge changes from a source into your
+  working copy.</p>
+
+  <p>Before it begins, the command does the following:</p>
+
+  <ul>
+    <li>If a SOURCE/URL is specified, it can be a full URL or a partial URL
+    starting at the branches, trunk or tags level.
+
+      <ul>
+        <li>If a partial URL is given, and the path name does not begin with
+        "trunk", "tags" or "branches" then "branches/" is automatically
+        added to the beginning of your path.</li>
+      </ul>
+    </li>
+
+    <li>It determines the TARGET URL by examining your working copy.</li>
+
+    <li>If the current directory is not the top of your working copy, it
+    changes the current directory to the top of your working copy.</li>
+
+    <li>If your working copy is not pointing to a branch of a project
+    managed by FCM, the command aborts with an error.</li>
+
+    <li>If you do not specify the <tt>--non-interactive</tt> option, it checks for any
+    local modifications in your working copy. If it finds any it reports them
+    and asks you to confirm that you wish to continue (it aborts if not).</li>
+  </ul>
+
+  <p>If neither <tt>--custom</tt> nor <tt>--reverse</tt> is specified, the command defaults to the
+  automatic mode. Automatic merges are used to merge changes between two
+  directly related branches, (i.e. the branches must either be created from the
+  same parent or have a parent/child relationship). These merges are tracked by
+  FCM and can be used by subsequent FCM commands. The merge delta is calculated
+  by doing the following:</p>
+
+  <ul>
+    <li>It checks that the SOURCE and TARGET are directly related.</li>
+
+    <li>It determines the base revision and path of the <em>common
+    ancestor</em> of the SOURCE and TARGET.</li>
+
+    <li>The base revision and path are adjusted to account for any merges
+    from the SOURCE to the TARGET or vice-versa.</li>
+
+    <li>It reports the revisions from SOURCE available for merging into
+    TARGET. If the <tt>--verbose</tt> option is set, it prints the log for these
+    revisions. It aborts if no revision is available for merging.</li>
+
+    <li>If there are 2 or more revisions available for merging and you do not
+    specify the <tt>--non-interactive</tt> target, it asks you which revision of the
+    SOURCE you wish to merge from. The default is the last changed revision of
+    the SOURCE. The merge delta is between the base and the specified revision
+    of the SOURCE.</li>
+
+    <li>If your working copy is a sub-tree of the TARGET, it ensures that the
+    SOURCE contains only changes in the same sub-tree. Otherwise, the merge is
+    unsafe, and the command will abort with an error.
+
+     <p>N.B.: The command looks for changes in the SOURCE by going through the
+     list of changed files since the the SOURCE was last merged into the TARGET.
+     (If there is no previous merge from SOURCE to TARGET, the common ancestor
+     is used.) It is worth noting that there are situations when the command
+     will regard your merge as "unsafe" (and so will fail incorrectly) even if
+     the changes in the SOURCE outside of the current sub-tree will result in a
+     null merge. This can happen if the changes are the results of a previous
+     merge from the TARGET to the SOURCE or if these changes have been
+     reversed. In such case, you will have to perform your merge in a working
+     copy of a full tree.</p>
+    </li>
+  </ul>
+
+  <p>The <tt>--custom</tt> mode is useful if you need to merge changes selectively from
+  another branch. The custom mode can be used in two forms:
+  
+  <ul>
+    <li>In the first form, you must specify a SOURCE as well as a revision
+    (range) using the <tt>--revision</tt> option. If you specify a single revision N, the
+    merge delta is between revision N - 1 and revision N of the SOURCE.
+    Otherwise, the merge delta is between revision N and revision M, where N
+    &lt; M.</li>
+  
+    <li>In the second form, you must specify two URLs. The merge delta is simply
+    between the two URLs. (For each URL, if you do not specify a peg revision,
+    the command will peg the URL with its last changed revision.)</li>
+  </ul>
+  
+  <p>N.B. Unlike automatic merges, custom merges are not tracked or used by
+  subsequent FCM <tt>diff</tt> or <tt>merge</tt> commands, (although <tt>branch
+  --info</tt> can be set to report them). Custom merges are always allowed, even
+  if your working copy is pointing to a sub-tree of a branch. However, there is no
+  checking mechanism to ensure the safety of your sub-tree custom merge so you
+  should only do this if you are confident it is what you want.
+  Therefore, it is recommended that you use automatic merges where possible, and
+  use custom merges only if you know what you are doing.</p>
+
+  <p>The <tt>--reverse</tt> mode is useful if you need to reverse a changeset (or a range
+  of changesets) in the current branch of the working copy. In this mode, you
+  must specify a revision (range) using the <tt>--revision</tt> option. If you specify a
+  single revision N, the merge delta is between revision N and revision N - 1 of
+  the current branch. Otherwise, the merge delta is between revision M and
+  revision N, where M &gt; N.</p>
+
+  <p>N.B. Like custom merges, reverse merges are not tracked or used by
+  subsequent FCM <tt>diff</tt> or <tt>merge</tt> commands, (although <tt>branch
+  --info</tt> can be set to report them). Likewise, reverse merges in sub-trees
+  are always allowed, although there is no checking mechanism to ensure the safety of
+  your sub-tree reverse merge.</p>
+
+  <p>Once the merge delta is determined, the command performs the following:</p>
+
+  <ul>
+    <li>If you set the <tt>--dry-run</tt> option or if you are running in the interactive
+    mode, it reports what changes will result from performing this merge by
+    calling <tt>svn merge --dry-run</tt>.
+
+      <ul>
+        <li>It prints the actual <tt>svn merge --dry-run</tt> command if the
+        <tt>--verbose</tt> option is specified.</li>
+
+        <li>If you specify the <tt>--dry-run</tt> option, it exits after reporting what
+        changes will result from performing the merge.</li>
+      </ul>
+    </li>
+
+    <li>If you are running in the interactive mode, it asks if you want to go
+    ahead with the merge (it aborts if not).</li>
+
+    <li>It performs the merge by calling <tt>svn merge</tt> to apply the delta
+    between the base and the SOURCE on your working copy.
+
+      <ul>
+        <li>It prints the actual <tt>svn merge</tt> command if the <tt>--verbose</tt>
+        option is specified.</li>
+      </ul>
+    </li>
+
+    <li>It adds a standard template into the commit message to provide
+    details of the merge. The template is written below the line that says
+    "--This line will be ignored and those below will be inserted
+    automatically--". The <a href="fcm_svn_commit">fcm commit</a> command
+    will detect the existence of the template, so that you will not be able
+    to alter it by accident.
+
+      <ul>
+        <li>The commit message is stored in the file
+        <tt>#commit_message#</tt> in the top level of your working copy. It
+        is created by the merge command if it does not already exist.</li>
+      </ul>
+    </li>
+  </ul>
+
+  <p>For further details refer to the section <a href=
+  "code_management.html#svn_branching_merge">Merging</a>.</p>
+
+  <h3><a name="fcm_svn_mkpatch">fcm mkpatch</a></h3>
+
+  <h4>Usage</h4>
+
+  <p>fcm mkpatch [OPTIONS] URL [OUTDIR]</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm mkpatch</tt> creates patches from the specified revisions of the
+  specified URL, which must be a branch URL of a valid FCM project. If the URL
+  is a sub-directory of a branch, it will use the root of the branch.</p>
+  
+  <p>If OUTDIR is specified, the output is sent to OUTDIR.  Otherwise, the
+  output will be sent to a default location in the current directory
+  (<tt>$PWD/fcm-mkpatch-out/</tt>). The output directory will contain the patch
+  for each revision as well as a script for importing the patch.</p>
+
+  <p>If a revision is specified using the <tt>--revision</tt> option, it will
+  attempt to create a patch based on the changes at that revision. If a revision
+  is not specified, it will attempt to create a patch based on the changes at
+  the HEAD revision. If a revision range is specified, it will attempt to create
+  a patch for each revision in that range (including the change in the lower
+  range) where changes have taken place in the URL. No output will be written if
+  there is no change in the given revision (range).</p>
+
+  <p>The <tt>--exclude</tt> option can be used to exclude a path in the URL. The
+  specified path must be a relative path of the URL. Glob patterns such as
+  <tt>*</tt> and <tt>?</tt> are acceptable. Changes in an excluded path will not
+  be considered in the patch. A changeset containing changes only in the
+  excluded path will not be considered at all.</p>
+
+  <p>The <tt>--organisation</tt> option can be used to specify the name of your
+  organisation. The command will attempt to parse the commit log message for
+  each revision in the patch. It will remove all merge templates, replace links
+  to Trac tickets with a simple string, and add information about the original
+  changeset. If you specify the name of your organisation, it will replace Trac
+  ticket links such as <tt>"ticket:123"</tt> to <tt>"$organisation ticket
+  123"</tt>, and report the orginal changeset with a message such as
+  <tt>"$organisation changeset 1000"</tt>. Otherwise, it will report without the
+  organisation name, e.g. <tt>"Original ticket 123"</tt> and <tt>"Original
+  changeset 1000"</tt>.</p>
+
+  <p>Within the output directory are the "patches" and the log message file for
+  each revision. It also contains a generated script <tt>fcm-import-patch</tt>
+  for importing the patches. The user of the script can invoke the script with
+  either a URL or a working copy argument, and the script will attempt to import
+  the patches into the given URL or working copy.</p>
+
+  <p>It is worth noting that changes in Subversion properties, including changes
+  in executable permissions, are not handled by the import script.</p>
+
+  <h3><a name="fcm_svn_switch">fcm switch</a></h3>
+
+  <h4>Usage</h4>
+
+  <p>fcm switch [OPTIONS] URL [PATH]</p>
+
+  <p>fcm switch --relocate [OPTIONS] FROM TO [PATH]</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm switch</tt> supports the arguments and alternate names supported by
+  <tt>svn switch</tt>. If <tt>--relocate</tt> is specified, it supports all
+  options supported by <tt>svn switch</tt>. Otherwise, it supports
+  <tt>--non-interactive</tt>, <tt>-r [--revision]</tt> and <tt>-q [--quiet]</tt>
+  only. (Please refer to the <a href=
+  "http://svnbook.red-bean.com/en/1.2/svn.branchmerge.switchwc.html">Subversion
+  book</a> for details).</p>
+
+  <p>If <tt>--relocate</tt> is specified, FCM will pass the options and
+  arguments directly to the corresponding Subversion command. Otherwise, FCM
+  will ensure that your working copy switches safely through the following
+  actions:</p>
+
+  <ul>
+    <li>If PATH (or the current working directory if PATH is not specified)
+    is not at the top of a working copy, the command will automatically
+    search for the top of the working copy, and the switch command will
+    always apply recursively from that level.</li>
+
+    <li>You can specify only the "branch" part of the URL, such as "trunk",
+    "branches/dev/fred/r1234_bob" or even "dev/fred/r1234_bob" and the
+    command will work out the full URL for you.</li>
+
+    <li>If you do not specify the <tt>--non-interactive</tt> option, it checks for any
+    local modifications in your working copy. If it finds any it reports them
+    and asks you to confirm that you wish to continue (it aborts if not).</li>
+
+    <li>If you have some template messages in the <tt>#commit_message#</tt> file
+    in the top level of your working copy, (e.g. after you have performed a
+    merge), the command will report an error. You should remove the template
+    message manually from the <tt>#commit_message#</tt> file before re-running
+    <tt>switch</tt>.</li>
+
+    <li>The command will analyse the current working copy URL and the
+    specified URL to ensure that they are in the same project. If your
+    working copy is a sub-tree of a project, the command will assume that
+    you want the same sub-tree in the new URL.</li>
+  </ul>
+
+  <p>For further details refer to the section <a href=
+  "code_management.html#svn_branching_switch">Switching your working copy to
+  point to another branch</a>.</p>
+
+  <h3><a name="fcm_svn_trac">fcm trac</a></h3>
+
+  <h4>Usage</h4>
+
+  <p>fcm trac [--browser (-b) ARG] [PATH]</p>
+
+  <h4>Description</h4>
+
+  <p><tt>fcm trac</tt> invokes the web-browser to launch the corresponding
+  URL of the web-based repository browser (currently Trac browser) to view
+  the Subversion repository specified by PATH.</p>
+
+  <ul>
+    <li>If the <tt>--browser</tt> option is specified, ARG must be a valid command
+    to a web browser. If this option is not specified, the default is to use
+    "firefox", or whatever setting you have declared in the user configuration
+    file (<tt>$HOME/.fcm</tt>) using the label "SET::MISC::WEB_BROWSER". For
+    example:
+
+      <pre>
+set::misc::web_browser  mozilla
+</pre>
+    </li>
+
+    <li>If PATH is specified, it must be a path to a local working copying, a
+    Subversion URL or a FCM URL keyword. If PATH is not specified, it is set to
+    ".", the current working directory. If PATH is a directory in the local
+    file system, the command will determine whether it is a working copy. If
+    so, its associated Subversion URL will be used. The command fails if the
+    directory is not a working copy. If PATH is a Subversion URL or a FCM URL
+    keyword, the URL can be "pegged" with a revision number using the "@"
+    symbol. For example, to view the trunk of the FCM repository at revision
+    400, you can use "fcm:fcm_tr@400". The URL declared by or associated with
+    PATH must also be associated with a Trac browser URL, which is declared
+    using the "SET::TRAC::&lt;pck&gt;" label in the FCM central/user
+    configuration file. The command fails if an associated Trac browser URL is
+    not found.</li>
+  </ul>
+
+  <h4>Alternate Names</h4>
+
+  <p>www</p>
+
+  <h3><a name="fcm_svn_other">Other Subversion Commands</a></h3>
+
+  <p>Other <tt>svn</tt> commands are supported by <tt>fcm</tt> without
+  any change in functionality, with the following minor enhancements:</p>
+
+  <ul>
+    <li>Where appropriate, FCM performs repository and revision keywords
+    expansion.</li>
+
+    <li>The <tt>fcm checkout</tt> command fails if you attempt to checkout into
+    an existing working copy.</li>
+
+    <li>FCM prints the corresponding <tt>svn</tt> command, except for
+    <tt>cat</tt> and any commands with the <tt>--xml</tt> option specified.</li>
+  </ul>
+  
+  <p>The following is a list of the commands:</p>
+
+  <ul>
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.blame.html">svn
+    blame</a></li>
+
+    <li><a href="http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.cat.html">svn
+    cat</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.checkout.html">svn
+    checkout</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.cleanup.html">svn
+    cleanup</a></li>
+
+    <li><a href="http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.copy.html">svn
+    copy</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.export.html">svn
+    export</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.import.html">svn
+    import</a></li>
+
+    <li><a href="http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.info.html">svn
+    info</a></li>
+
+    <li><a href="http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.list.html">svn
+    list</a></li>
+
+    <li><a href="http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.log.html">svn
+    log</a></li>
+
+    <li><a href="http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.lock.html">svn
+    lock</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.mkdir.html">svn
+    mkdir</a></li>
+
+    <li><a href="http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.move.html">svn
+    move</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.propdel.html">svn
+    propdel</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.propedit.html">svn
+    propedit</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.propget.html">svn
+    propget</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.proplist.html">svn
+    proplist</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.propset.html">svn
+    propset</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.resolved.html">svn
+    resolved</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.revert.html">svn
+    revert</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.status.html">svn
+    status</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.unlock.html">svn
+    unlock</a></li>
+
+    <li><a href=
+    "http://svnbook.red-bean.com/en/1.2/svn.ref.svn.c.update.html">svn
+    update</a></li>
+  </ul>
+
+  <p>Please refer to the <a href=
+  "http://svnbook.red-bean.com/en/1.2/svn.ref.html">Subversion book</a> for
+  details of these commands.</p>
+  
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/user_guide/extract.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/user_guide/extract.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/user_guide/extract.html	(revision 1665)
@@ -0,0 +1,1118 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide: The Extract System</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide - The Extract System">
+  <meta name="keywords" content="FCM, user guide, extract, build">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; The Extract System
+  </address>
+
+  <h1>The Extract System</h1>
+
+  <p>The extract system provides an interface between the revision control
+  system (currently Subversion) and the build system. Where appropriate, it
+  extracts code from the repository and other user-defined locations to a
+  directory tree suitable for feeding into the build system. In this chapter,
+  we shall use many examples to explain how to use the extract system. At the
+  end of this chapter, you will be able to extract code from the local file system
+  as well as from different branches of different repository URLs. You will
+  also learn how to mirror code to a remote machine. Finally, you will be given
+  an introduction on how to specify configurations for the build system via the
+  extract configuration file. (For further information on the build system,
+  please see the next chapter <a href="build.html">The Build System</a>.) The
+  last section of the chapter tells you what you can do in the case when
+  Subversion is not available.</p>
+
+  <h2><a name="command">The Extract Command</a></h2>
+
+  <p>To invoke the extract system, simply issue the command:</p>
+  <pre>
+fcm extract
+</pre>
+
+  <p>By default, the extract system searches for an extract configuration file
+  "ext.cfg" in "$PWD" and then "$PWD/cfg". If an extract configuration file is
+  not found in these directories, the command fails with an error. If an
+  extract configuration file is found, the system will use the configuration
+  specified in the file to perform the current extraction.</p>
+
+  <p>If the destination of the extraction does not exist, the system performs a
+  new full extraction to the destination. If a previous extraction already
+  exists at the destination, the system performs an incremental extraction,
+  updating any modifications if necessary. If a full (fresh) extraction is
+  required for whatever reason, you can invoke the extract system using the
+  "-f" option, (i.e. the command becomes "fcm extract -f"). For further
+  information on the extract command, please see <a href=
+  "command_ref.html#fcm_ext">FCM Command Reference &gt; fcm extract</a>.</p>
+
+  <h2><a name="simple">Simple Usage</a></h2>
+
+  <p>The extract configuration file is the main user interface of the extract
+  system. It is a line based text file. For a complete set of extract
+  configuration file declarations, please refer to the <a href=
+  "annex_ext_cfg.html">Annex: Declarations in FCM extract configuration
+  file</a>.</p>
+
+  <h3><a name="simple_local">Extract from a local path</a></h3>
+
+  <p>A simple example of a basic extract configuration file is given below:</p>
+
+  <table class="pad" summary="extract_example1" border="1" width="100%">
+    <tr>
+      <th>Extract configuration example 1 - extract from a local path</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type         ext       # line 1
+cfg::version      1.0       # line 2
+                            # line 3
+dest::rootdir     $PWD      # line 4
+                            # line 5
+repos::var::user  $HOME/var # line 6
+                            # line 7
+expsrc::var::user code      # line 8
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>The above demonstrates how to use the extract system to extract code from
+  a local user directory. Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 1: the label "CFG::TYPE" declares the type of the configuration
+    file. The value "ext" tells the system that it is an extract configuration
+    file.</li>
+
+    <li>line 2: the label "CFG::VERSION" declares the version of the extract
+    configuration file. The current default is "1.0". Although it is not
+    currently used, if we have to change the format of the configuration file
+    at a later stage, we shall be able to use this number to determine whether
+    we are reading a file with an older format or one with a newer format.</li>
+
+    <li>line 3: a blank line or a line beginning with a "#" is a comment, and
+    is ignored by the interpreter.</li>
+
+    <li>line 4: the label "DEST::ROOTDIR" declares the destination root
+    directory of this extraction. The value "$PWD" expands to the current
+    working directory.</li>
+
+    <li>line 5: comment line, ignored.</li>
+
+    <li>line 6: the label "REPOS::&lt;pck&gt;::&lt;branch&gt;" declares the top
+    level URL or path of a repository. The package name of the repository is
+    given by &lt;pck&gt;. In our example, we choose "var" as the name of the
+    package. (You can choose any name you like, however, it is usually sensible
+    to use a package name that matches the name of the project or system you are
+    working with.) The branch name in the repository is given by &lt;branch&gt;.
+    (Again, you can choose any name you like, however, it is usually sensible to
+    use a name such as "trunk", "user" or something that matches your branch
+    name.) In our example, the word "user" is normally used to denote a local
+    user directory. Hence the statement declares that the repository path for
+    the "var" package in the "user" branch can be found at "$HOME/var".</li>
+
+    <li>line 7: comment line, ignored.</li>
+
+    <li>line 8: the label "EXPSRC::&lt;pck&gt;::&lt;branch&gt;" declares an
+    "expandable" source directory for the package &lt;pck&gt; in the branch
+    &lt;branch&gt;. In our example, the package name is "var", and the branch
+    name is "user". These match the package and the branch names of the
+    repository declaration in line 6. It means that the source directory
+    declaration is associated with the path "$HOME/var". The value of the
+    declaration "code" is therefore a sub-directory under "$HOME/var". By
+    declaring a source directory using an "expsrc" label, the system
+    automatically searches for all sub-directories (recursively) under the
+    declared source directory.</li>
+  </ul>
+
+  <p>Invoking the extract system using the above configuration file will
+  "extract" all sub-directories under "$HOME/var/code" to "$PWD/src/var/code".
+  Note: the extract system ignores all hidden files, (i.e. directories and
+  files beginning with a "."). It will write a build configuration file to
+  "$PWD/cfg/bld.cfg". The configuration used for this extraction will be
+  written to the configuration file at "$PWD/cfg/ext.cfg".</p>
+
+  <table class="pad" summary="note - incremental extraction" border="1" width=
+  "100%">
+    <tr>
+      <th>Note - incremental extraction</th>
+    </tr>
+
+    <tr>
+      <td>Suppose you have already performed an extraction using the above
+      configuration file. At a later time, you have made some changes to some
+      of the files in the source directory. Re-running the extract system on
+      the same configuration will trigger an incremental extraction. In an
+      incremental extraction, the system will update only those files that are
+      modified. In exact words, the system checks the modification time of each
+      file in the source and destination. If a source file is newer than its
+      corresponding destination file, it checks whether the content differs.
+      The destination is only updated if its content differs from the
+      source.</td>
+    </tr>
+  </table>
+
+  <h3><a name="simple_url">Extract from a Subversion URL</a></h3>
+
+  <p>The next example demonstrates how to extract from a Subversion repository
+  URL:</p>
+
+  <table class="pad" summary="extract_example2" border="1" width="100%">
+    <tr>
+      <th>Extract configuration example 2 - extract from a Subversion URL</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type           ext                    # line 1
+cfg::version        1.0                    # line 2
+                                           # line 3
+dest::rootdir       $PWD                   # line 4
+                                           # line 5
+repos::var::trunk   svn://server/var/trunk # line 6
+version::var::trunk 1234                   # line 7
+                                           # line 8
+expsrc::var::trunk  code                   # line 9
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <ul>
+    <li>line 1 to 5: same as example 1.</li>
+
+    <li>line 6: the line declares the repository location of the "trunk" branch
+    of the "var" package to be the Subversion URL
+    "svn://server/var/trunk".</li>
+
+    <li>line 7: the label "VERSION::&lt;pck&gt;::&lt;branch&gt;" declares the
+    revision of the repository associated with the package &lt;pck&gt; in the
+    branch &lt;branch&gt;. The current line tells the extract system to use
+    revision 1234 of "svn://server/var/trunk". If the revision is not declared,
+    the default revision "HEAD" will be assumed.</li>
+
+    <li>line 8: comment line, ignored.</li>
+
+    <li>line 9: the line declares an expandable source directory in the
+    repository "svn://server/var/trunk".</li>
+  </ul>
+
+  <p>Invoking the extract system using the above configuration file will
+  extract all sub-directories under "svn://server/var/trunk/code" to
+  "$PWD/src/var/code". It will write a build configuration file to
+  "$PWD/cfg/bld.cfg". The configuration used for this extraction will be
+  written to the configuration file at "$PWD/cfg/ext.cfg".</p>
+
+  <table class="pad" summary=
+  "note - declaration of source directories for extraction" border="1" width=
+  "100%">
+    <tr>
+      <th>Note - declaration of source directories for extraction</th>
+    </tr>
+
+    <tr>
+      <td>
+        <strong>EXPSRC or SRC?</strong>
+
+        <p>So far, we have only declared source directories using the "EXPSRC"
+        statement, which stands for "expandable source directory". A source
+        directory declared using this statement will trigger the system to
+        search recursively for any sub-directories under the declared one. Any
+        sub-directories containing regular source files will be included in the
+        extraction. Empty directories, hidden directories and directories
+        containing only hidden files are ignored.</p>
+
+        <p>If you do not want the system to search for sub-directories
+        underneath your declared source directory, you can declare your source
+        directory using the "SRC" statement. The "SRC" statement is essentially
+        the same as "EXPSRC" except that it does not trigger the automatic
+        recursive search for source directories. In fact, the system implements
+        the "EXPSRC" statement by expanding it into a list of "SRC"
+        statements.</p>
+
+        <p><strong>Package and sub-package</strong></p>
+
+        <p>The second field of a repository, revision or source directory
+        declaration label is the name of the container package. It is a name
+        selected by the user to identify the system or project he/she is
+        working on. (Therefore, it is often sensible to choose an identifier
+        that matches the name of the project or system.) The package name
+        provides a unique namespace for a file container. Source directories
+        are automatically arranged into sub-packages, using the names of the
+        sub-directories as the names of the sub-packages. For example, the
+        declaration at line 9 in example 2 will put the source directory in the
+        "var::code" sub-package automatically.</p>
+
+        <p>The double colon "::" and the double underscore "__" (internal only)
+        are delimiters for package names in the extract system. Please avoid
+        using "::" and "__" for naming your files and directories.</p>
+
+        <p>You can declare a sub-package name explicitly in your source
+        directory statement. For example, the following two lines are
+        equivalent:</p>
+        <pre>
+src::var::trunk                        code/VarMod_Surface
+src::var::code::VarMod_Surface::trunk  code/VarMod_Surface
+</pre>
+
+        <p>Explicit sub-package declaration should not be used normally, as it
+        requires a lot more typing (although there are some situations where it
+        can be useful).</p>
+      </td>
+    </tr>
+  </table>
+
+  <table class="pad" summary="note - the expanded extract configuration file"
+  border="1" width="100%">
+    <tr>
+      <th>Note - the expanded extract configuration file</th>
+    </tr>
+
+    <tr>
+      <td>
+        At the end of a successful extraction, the configuration used by the
+        current extraction is written in "cfg/ext.cfg" under the extract
+        destination root. This file is an "expanded" version of the original,
+        with changes in the following declarations:
+
+        <ul>
+          <li>All revision keywords are converted into revision numbers.</li>
+
+          <li>If a revision is not defined for a repository, it is set to the
+          corresponding revision number of the HEAD revision.</li>
+
+          <li>All URL keywords are converted into the full URLs.</li>
+
+          <li>All EXPSRC declarations are expanded into SRC declarations.</li>
+
+          <li>All other variables are expanded.</li>
+        </ul>
+
+        <p>With this file, it should be possible for later extraction to
+        re-create the current configuration even if the contents of the
+        repository have changed. (This applies only to code stored in the
+        repository.)</p>
+      </td>
+    </tr>
+  </table>
+
+  <h3><a name="simple_mirror">Mirror code to a remote machine</a></h3>
+
+  <p>The next example demonstrates how to extract from a repository and mirror
+  the code to a remote machine. It is essentially the same as example 2,
+  except that it has three new lines to describe how the system can mirror the
+  extracted code to a remote machine.</p>
+
+  <table class="pad" summary="extract_example3" border="1" width="100%">
+    <tr>
+      <th>Extract configuration example 3 - mirror code to remote machine</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type           ext
+cfg::version        1.0
+
+dest::rootdir       $PWD
+
+rdest::machine      tx01                           # line 6
+rdest::logname      frva                           # line 7
+rdest::rootdir      /scratch/frva/extract/example3 # line 8
+
+repos::var::trunk   svn://server/var/trunk
+version::var::trunk 1234
+
+expsrc::var::trunk  code
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 6: "RDEST::MACHINE" declares the target machine to which the code
+    will be mirrored. The example mirrors the code to the machine named
+    "tx01".</li>
+
+    <li>line 7: "RDEST::LOGNAME" declares the remote user name of the target
+    machine, to which the user has remote login access. If this is not
+    declared, the system uses the login name of the current user on the local
+    machine.</li>
+
+    <li>line 8: "RDEST::ROOTDIR" declares the root directory of the extraction
+    on the remote target machine. This is where the mirror version of the
+    extraction will be sent.</li>
+  </ul>
+
+  <p>Invoking the extract system on the above configuration will trigger an
+  extraction similar to that given in example 2, but it will also attempt to
+  mirror the contents at "$PWD/src/var/code" to
+  "/scratch/frva/extract/example3/src" on the remote machine. It will also
+  mirror the expanded extract configuration file "$PWD/cfg/ext.cfg" to
+  "/scratch/frva/extract/example3/cfg/ext.cfg" and "$PWD/cfg/bld.cfg" to
+  "/scratch/frva/extract/example3/cfg/bld.cfg". It is also worth noting that
+  the content of the build configuration file will be slightly different, since
+  it will include directory names appropriate for the remote system.</p>
+
+  <table class="pad" summary="note - mirroring command" border="1" width=
+  "100%">
+    <tr>
+      <th>Note - mirroring command</th>
+    </tr>
+
+    <tr>
+      <td>
+        The extract system currently supports "rdist" and "rsync" as its
+        mirroring tool. The default is "rsync". To use "rdist" instead of
+        "rsync", add the following line to your "$HOME/.fcm" file:
+        <pre>
+set::tool::mirror  rdist
+</pre>
+
+        <p>N.B. If you are going to mirror code to another machine, you need to
+        ensure that your account on the remote machine is set up correctly to
+        accept commands from the local machine. In our current settings of both
+        "rdist" and "rsync", all you need to do is set up your "$HOME/.rhosts"
+        file on the remote machine. For example, if you are "fred" working on
+        the local machine "eld001", you will need to have the following entry
+        in your "$HOME/.rhosts" on the remote machine:</p>
+        <pre>
+eld001  fred
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <h2><a name="advanced">Advanced Usage</a></h2>
+
+  <h3><a name="advanced_multi">Extract from multiple repositories</a></h3>
+
+  <p>So far, we have only extracted from a single location. The extract system
+  is not much use if that is the only thing it can do. In fact, the extract
+  system supports extraction of multiple source directories from multiple
+  branches in multiple repositories. The following configuration file is an
+  example of how to extract from multiple repositories:</p>
+
+  <table class="pad" summary="extract_example4" border="1" width="100%">
+    <tr>
+      <th>Extract configuration example 4 - extract from multiple
+      repositories</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type           ext
+cfg::version        1.0
+
+dest::rootdir       $PWD
+
+repos::var::trunk   fcm:var_tr              # line 6
+repos::ops::trunk   fcm:ops_tr              # line 7
+repos::gen::trunk   fcm:gen_tr              # line 8
+
+version::gen::trunk 2468                    # line 10
+
+expsrc::var::trunk  code                    # line 12
+expsrc::var::trunk  scripts                 # line 13
+expsrc::ops::trunk  code                    # line 14
+src::gen::trunk     code/GenMod_Constants   # line 15
+src::gen::trunk     code/GenMod_Control     # line 16
+src::gen::trunk     code/GenMod_FortranIO   # line 17
+src::gen::trunk     code/GenMod_GetEnv      # line 18
+src::gen::trunk     code/GenMod_ModelIO     # line 19
+src::gen::trunk     code/GenMod_ObsInfo     # line 20
+src::gen::trunk     code/GenMod_Platform    # line 21
+src::gen::trunk     code/GenMod_Reporting   # line 22
+src::gen::trunk     code/GenMod_Trace       # line 23
+src::gen::trunk     code/GenMod_UMConstants # line 24
+src::gen::trunk     code/GenMod_Utilities   # line 25
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Here is an explanation of what each line does:</p>
+
+  <ul>
+    <li>line 6 to 8: these lines declare the repositories for the "trunk"
+    branches of the "var", "ops" and "gen" packages respectively. It is worth
+    noting that the values of the declarations are no longer Subversion URLs
+    but are FCM URL keywords. These keywords are normally declared in the
+    central configuration file of the FCM system, and will be expanded into the
+    corresponding Subversion URLs by the FCM system. For further information on
+    URL keywords, please see <a href=
+    "code_management.html#svn_basic_keywords">Code Management System &gt; Using
+    Subversion &gt; Basic Command Line Usage &gt; Repository &amp; Revision
+    Keywords</a>.</li>
+
+    <li>line 10: this line declares the revision number for the "trunk" branch
+    of the "gen" package, i.e. for the "fcm:gen_tr" repository. It is worth
+    noting that the revision numbers for the "var" and "ops" packages have not
+    been declared. By default, their revision numbers will be set to
+    "HEAD".</li>
+
+    <li>line 12 to 14: these line declares the source directories for the
+    "trunk" branches of the "var" and "ops" packages. For the "var" package, we
+    are extracting everything from the "code" and the "scripts" sub-directory.
+    For the "ops" package, we are extracting everything from the "code"
+    directory.</li>
+
+    <li>line 15 to 25: these line declares the source directories for the
+    "trunk" branch of the "gen" package. The source directories declared will
+    not be searched for sub-directories underneath the declared
+    directories.</li>
+  </ul>
+
+  <p>We shall end up with a directory tree such as:</p>
+  <pre>
+$PWD
+   |
+   |--- cfg
+   |      |
+   |      |--- bld.cfg
+   |      |--- ext.cfg
+   |
+   |--- src
+          |
+          |--- gen
+          |      |
+          |      |--- code
+          |              |
+          |              |--- GenMod_Constants
+          |              |--- GenMod_Control
+          |              |--- GenMod_FortranIO
+          |              |--- GenMod_GetEnv
+          |              |--- GenMod_ModelIO
+          |              |--- GenMod_ObsInfo
+          |              |--- GenMod_Platform
+          |              |--- GenMod_Reporting
+          |              |--- GenMod_Trace
+          |              |--- GenMod_UMConstants
+          |              |--- GenMod_Utilities
+          |
+          |--- ops
+          |      |
+          |      |--- code
+          |              |
+          |              |--- ...
+          |
+          |--- var
+                 |
+                 |--- code
+                 |       |
+                 |       |--- ...
+                 |
+                 |--- scripts
+                         |
+                         |--- ...
+</pre>
+
+  <table class="pad" summary="note - revision number" border="1" width="100%">
+    <tr>
+      <th>Note - revision number</th>
+    </tr>
+
+    <tr>
+      <td>
+        As seen in the above example, if a revision number is not specified for
+        a repository URL, it defaults to the "HEAD" revision. The revision
+        number can also be declared in other ways:
+
+        <ul>
+          <li>Any revision arguments acceptable by Subversion are allowed. You
+          can use a valid revision number, a date between a pair of curly
+          brackets (e.g. {"2005-05-01 12:00"}) or the keyword "HEAD". However,
+          please do not use the keywords "BASE", "COMMITTED" or "PREV" as these
+          are reserved for working copy only.</li>
+
+          <li>FCM revision keywords are allowed. These must be defined for the
+          corresponding repository URLs in either the central or the user FCM
+          configuration file. For further information on revision keywords,
+          please see <a href="code_management.html#svn_basic_keywords">Code
+          Management &gt; Using Subversion &gt; Basic Command Line Usage &gt;
+          Repository &amp; Revision Keywords</a>.</li>
+
+          <li>Do not use the keyword "USER", as it is used internally by the
+          extract system.</li>
+        </ul>
+      </td>
+    </tr>
+  </table>
+
+  <h3><a name="advanced_branches">Extract from multiple branches</a></h3>
+
+  <p>We have so far dealt with extraction from a single branch in any package.
+  The extract system can be used to "combine" changes from different branches
+  of a package. An example is given below:</p>
+
+  <table class="pad" summary="extract_example5" border="1" width="100%">
+    <tr>
+      <th>Extract configuration example 5 - extract from multiple branches</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type               ext
+cfg::version            1.0
+ 
+dest::rootdir           $PWD
+ 
+repos::var::trunk       fcm:var_tr
+repos::ops::trunk       fcm:ops_tr
+repos::gen::trunk       fcm:gen_tr
+ 
+version::gen::trunk     2468
+ 
+expsrc::var::trunk      code
+expsrc::var::trunk      scripts
+expsrc::ops::trunk      code
+src::gen::trunk         code/GenMod_Constants
+src::gen::trunk         code/GenMod_Control
+src::gen::trunk         code/GenMod_FortranIO
+src::gen::trunk         code/GenMod_GetEnv
+src::gen::trunk         code/GenMod_ModelIO
+src::gen::trunk         code/GenMod_ObsInfo
+src::gen::trunk         code/GenMod_Platform
+src::gen::trunk         code/GenMod_Reporting
+src::gen::trunk         code/GenMod_Trace
+src::gen::trunk         code/GenMod_UMConstants
+src::gen::trunk         code/GenMod_Utilities
+
+repos::var::new_stuff   fcm:var_br/frva/r1234_new_stuff   # line 27
+repos::var::bug_fix     fcm:var_br/frva/r1516_bug_fix     # line 28
+repos::ops::good_stuff  fcm:ops_br/opsrc/r3188_good_stuff # line 29
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>The configuration file in example 5 is similar to that of example 4 except
+  for the last three lines. Here is an explanation of what they do:</p>
+
+  <ul>
+    <li>line 27: this line declares a repository URL for the "new_stuff" branch
+    of the "var" package. From the URL of the branch, we know that the branch
+    was created by the user "frva" based on the trunk at revision at 1234. The
+    description of the branch is "new_stuff". The following points are worth
+    noting:
+
+      <ul>
+        <li>By declaring a new branch with the same package name to a
+        previously declared branch, it is assumed that both branches reside in
+        the same Subversion repository.</li>
+
+        <li>It is only by convention that the branch name "new_stuff" declared
+        using the "REPOS::var::new_stuff" label should correspond to the branch
+        description of the URL. It is not a requirement by the extract system.
+        It is perfectly valid to use "REPOS::var::ham_egg" as the label of line
+        27. In such case, the extract system will use "ham_egg" instead of
+        "new_stuff" as the internal label of the URL.</li>
+
+        <li>No revision is declared for this URL, so the default "HEAD"
+        revision is used.</li>
+
+        <li>No source directory is declared for this URL. By default, if no
+        source directory is declared for a branch repository, it will attempt
+        to use the same set of source directories as the first declared branch
+        of the package. In this case, the source directories declared for the
+        "trunk" branch of the "var" package will be used.</li>
+      </ul>
+    </li>
+
+    <li>line 28: this line declares another branch called "bug_fix" for the
+    "var" package. No source directory is declared for this URL either, so it
+    will use the same set of source directories declared for the "trunk"
+    branch.</li>
+
+    <li>line 29: this line declares a branch called "good_stuff" for the "ops"
+    package. It will use the same set of source directories declared for the
+    "ops" package "trunk" branch.</li>
+  </ul>
+
+  <p>When we invoke the extract system, it will attempt to extract from the
+  first declared branch of a package, if the last commit revision of the source
+  directory is the same in all the branches. However, if the last commit
+  revision of the source directory differs for different branches, the system
+  will attempt to obtain an extract priority list for each source directory,
+  using the following logic:</p>
+
+  <ol>
+    <li>The system looks for source directory packages from the first declared
+    branch to the last declared branch.</li>
+
+    <li>The branch in which a source directory package is first declared is
+    the "base" branch of the source directory package.</li>
+
+    <li>The commit revision of a source directory package in a subsequently
+    declared repository branch is compared with that of the base branch. If
+    the commit revision is the same as that of the base branch, the source
+    directory of this branch is discarded. Otherwise, it is placed at the end
+    of the extract priority list.</li>
+  </ol>
+
+  <p>For the "var" package in the above example, let us assume that we have
+  three source directory packages X, Y and Z under "code", and their commit
+  revisions under "trunk" are 100. Let's say we have committed some changes to
+  X and Z in the "new_stuff" branch at revision 102, and other changes to Y
+  and Z in the "bug_fix" branch at revision 104, the extract priority lists
+  for X, Y and Z will look like:</p>
+
+  <ul>
+    <li>X: trunk (100, base), new_stuff (102), bug_fix (100, discarded)</li>
+
+    <li>Y: trunk (100, base), new_stuff (100, discarded), bug_fix (104)</li>
+
+    <li>Z: trunk (100, base), new_stuff (102), bug_fix (104)</li>
+  </ul>
+
+  <p>Once we have an extract priority list for a source directory, we can
+  begin the extraction of source files in the source directory. The source
+  directory of the base branch is extracted first, followed by that in the
+  subsequent branches. If a source file in a subsequent branch has the same
+  content as the that in the base branch, it is discarded. Otherwise, the
+  following logic determines the branch to use:</p>
+
+  <ol>
+    <li>If a source file is modified in only one subsequent branch, the source
+    file in that branch is extracted.</li>
+
+    <li>If a source file is modified in two or more subsequent branches, but
+    their modifications are the same, then the source file in the first
+    modification is used.</li>
+
+    <li>If a source file is modified in two or more subsequent branches and
+    their modifications differ, then the behaviour depends on the override
+    mode setting. If override mode is false, the extraction fails. Otherwise,
+    the file in the latest declared branch takes precedence. The default
+    override mode is false, which is the safe behaviour - conflicting changes
+    should be resolved manually. However, this behaviour may not be the most
+    efficient way for development. Therefore, an override mode is provided,
+    which should be used with care. To switch on the override mode, make the
+    following declaration in the extract configuration file:
+      <pre>
+override  1
+</pre>
+    </li>
+  </ol>
+  
+  <p>Once the system has established which source files to use, it determines
+  whether the destination is out of date or not. The destination is out of
+  date if the source file does not exist or if its content differs from the
+  version of the source file we are using. The system only updates the
+  destination if it is considered to be out of date.</p>
+
+  <p>The extract system can also combine changes from branches in the Subversion
+  repository and the local file system. The limitation is that there can only
+  be one branch from the local file system. (By convention, the branch is named
+  "user".)</p>
+
+  <p>It is also worth bearing in mind that the "user" branch always takes
+  precedence over branches residing in Subversion repositories. Hence, source
+  directories from a "user" branch are always placed at the end of the extract
+  priority list.</p>
+
+  <p>Extracting from a mixture of Subversion repository and local file system
+  is demonstrated in the next example.</p>
+
+  <table class="pad" summary="extract_example6" border="1" width="100%">
+    <tr>
+      <th>Extract configuration example 6 - extract from multiple branches +
+      user paths</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type               ext
+cfg::version            1.0
+ 
+dest::rootdir           $PWD
+  
+repos::var::trunk       fcm:var_tr
+repos::ops::trunk       fcm:ops_tr
+repos::gen::trunk       fcm:gen_tr
+ 
+version::gen::trunk     2468
+ 
+expsrc::var::trunk      code
+expsrc::var::trunk      scripts
+expsrc::ops::trunk      code
+src::gen::trunk         code/GenMod_Constants
+src::gen::trunk         code/GenMod_Control
+src::gen::trunk         code/GenMod_FortranIO
+src::gen::trunk         code/GenMod_GetEnv
+src::gen::trunk         code/GenMod_ModelIO
+src::gen::trunk         code/GenMod_ObsInfo
+src::gen::trunk         code/GenMod_Platform
+src::gen::trunk         code/GenMod_Reporting
+src::gen::trunk         code/GenMod_Trace
+src::gen::trunk         code/GenMod_UMConstants
+src::gen::trunk         code/GenMod_Utilities
+
+repos::var::new_stuff   fcm:var_br/frva/r1234_new_stuff
+repos::var::bug_fix     fcm:var_br/frva/r1516_bug_fix
+repos::ops::good_stuff  fcm:ops_br/opsrc/r3188_good_stuff
+
+repos::var::user        $HOME/var/src                     # line 31
+repos::gen::user        $HOME/gen/src                     # line 32
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Example 6 is similar to example 5 except that it is also extracting from
+  local directories. Here is an explanation of the lines:</p>
+
+  <ul>
+    <li>line 31 to 32: these line declare the "repositories" for the "user"
+    branches of the "var" and "gen" packages respectively. Both are local paths
+    at the local file system. There are no declarations for source directories
+    for the "user" branches, so they use the same set of source directories of
+    the first declared branches, the "trunk" branches in both cases.</li>
+  </ul>
+
+  <table class="pad" summary="note - the inc statement" border="1" width=
+  "100%">
+    <tr>
+      <th>Note - the INC declaration</th>
+    </tr>
+
+    <tr>
+      <td>
+        You have probably realised that the above examples have many repeated
+        lines. To avoid having repeated lines in multiple extract configuration
+        files, you can use INC declarations to "include" other extract
+        configuration files. For example, if the configuration file of example 5
+        is stored in the file "$HOME/var/example5/ext.cfg", line 1 to 29 of
+        example 6 can be replaced with an INC declaration. Example 6 can then be
+        written as:
+        <pre>
+inc                     $HOME/var/example5/ext.cfg
+
+repos::var::user        $HOME/var/src
+repos::gen::user        $HOME/gen/src
+</pre>
+
+        <p>Note: the INC declaration supports the special "environment variable"
+        $HERE. If this variable is already set in the environment, it acts as a
+        normal environment variable. However, if it is not set, it will be
+        expanded into the container directory of the current extract
+        configuration file. This feature is particularly useful if you are
+        including a hierarchy of extract configurations from files in the same
+        container directory in a repository.</p>
+      </td>
+    </tr>
+  </table>
+
+  <h3><a name="advanced_incremental">Incremental extract based on a previous
+  extraction</a></h3>
+
+  <p>All the examples above dealt with standalone extraction, that is, the
+  current extraction is independent of any other extraction. If a previous
+  extraction exists in another location, the extract system can "USE" this
+  previous extraction in your current extraction. This works like a normal
+  incremental extraction, except that your extraction will only contain the
+  changes you have specified (compared with the USEd extraction) instead of the
+  full source directory tree. This type of incremental extraction is useful in
+  several ways. For instance:</p>
+
+  <ul>
+    <li>The extraction is fast, because you only have to extract and mirror
+    files that you have changed.</li>
+
+    <li>The subsequent build will also be fast, since it will use incremental
+    build.</li>
+
+    <li>You do not need write access to the original extraction. A system
+    administrator can set up a stable version in a central account, which
+    developers can then reuse.</li>
+
+    <li>You want an incremental extraction, but you need to leave the original
+    extraction unmodified.</li>
+  </ul>
+
+  <p>The following example is based on example 4 and 6. The assumption is that
+  an extraction has already been performed at the directory "~frva/var/vn22.0"
+  based on the configuration file in example 4.</p>
+
+  <table class="pad" summary="extract_example7" border="1" width="100%">
+    <tr>
+      <th>Extract configuration example 7 - incremental extract based on a
+      previous extraction</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type               ext
+cfg::version            1.0
+ 
+dest::rootdir           $PWD
+
+use                     ~frva/var/vn22.0                  # line 6
+
+repos::var::new_stuff   fcm:var_br/frva/r1234_new_stuff   # line 8
+repos::var::bug_fix     fcm:var_br/frva/r1516_bug_fix     # line 9
+repos::ops::good_stuff  fcm:ops_br/opsrc/r3188_good_stuff # line 10
+
+repos::var::user        $HOME/var/src                     # line 12
+repos::gen::user        $HOME/gen/src                     # line 13
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <ul>
+    <li>line 6: this line replaces line 1 to 25 of example 6. It declares that
+    the current extraction should be based on the previous extraction located
+    at "~frva/var/vn22.0".</li>
+  </ul>
+
+  <p>Running the extract system using the above configuration will trigger an
+  incremental extraction, as if you are running an incremental extraction
+  having modified the configuration file in example 4 to that of example 6. The
+  only difference is that the original extraction using the example 4
+  configuration will be left untouched at "~frva/var/vn22.0", and the new
+  extraction will contain only the changes in the branches declared from line 8
+  to 13.</p>
+
+  <p>If you are setting up an extraction to be reused, you do not have to
+  perform a build. If you don't you will still gain the benefit of incremental
+  file extraction, but you will be performing a full build of the code.</p>
+
+  <h3><a name="advanced_build">Extract - Build Configuration</a></h3>
+
+  <p>Configuration settings for feeding into the build system can be declared
+  through the extract configuration file using the "BLD::" prefix. Any line in
+  an extract configuration containing a label with such a prefix will be
+  considered a build system variable. At the end of a successful extraction,
+  the system strips out the "BLD::" prefix before writing these variables to
+  the build configuration file. Some example entries are given between line 17
+  and 22 in the following configuration file:</p>
+
+  <table class="pad" summary="extract_example8" border="1" width="100%">
+    <tr>
+      <th>Extract configuration example 8 - setting build configuration</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+cfg::type           ext
+cfg::version        1.0
+
+dest::rootdir       $PWD
+
+repos::var::trunk   fcm:var_tr
+repos::ops::trunk   fcm:ops_tr
+repos::gen::trunk   fcm:gen_tr
+
+version::gen::trunk 2468
+
+expsrc::var::trunk  code
+expsrc::var::trunk  scripts
+expsrc::ops::trunk  code
+src::gen::trunk     code/GenMod_Constants
+src::gen::trunk     code/GenMod_Control
+src::gen::trunk     code/GenMod_FortranIO
+src::gen::trunk     code/GenMod_GetEnv
+src::gen::trunk     code/GenMod_ModelIO
+src::gen::trunk     code/GenMod_ObsInfo
+src::gen::trunk     code/GenMod_Platform
+src::gen::trunk     code/GenMod_Reporting
+src::gen::trunk     code/GenMod_Trace
+src::gen::trunk     code/GenMod_UMConstants
+src::gen::trunk     code/GenMod_Utilities
+
+bld::target         VarProg_AnalysePF.exe   # line 27
+
+bld::tool::fc       sxmpif90                # line 29
+bld::tool::cc       sxmpic++                # line 30
+bld::tool::ld       sxmpif90                # line 31
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>The above example is essentially the same as example 4, apart from the
+  additional build configuration. The following is a simple explanation of what
+  the lines represent: (For detail of the build system, please see the next
+  chapter on <a href="build.html">The Build System</a>.)</p>
+
+  <ul>
+    <li>Line 27: the line declares a default target of the build.</li>
+
+    <li>Line 29-31: the lines declare the Fortran compiler, the C compiler and
+    the linker respectively.</li>
+  </ul>
+
+  <table class="pad" summary="note - user variable" border="1" width=
+  "100%">
+    <tr>
+      <th>Note - user variable</th>
+    </tr>
+
+    <tr>
+      <td>When you start using the extract system to define compiler flags for
+      the build system, you may end up having to make a lot of long and
+      repetitive declarations. In such case, you may want to define variables to
+      replace the repetitive parts of the declarations. In the extract system,
+      you can define a local variable by making a declaration with a label that
+      begins with a percent sign "%". For example:
+
+        <pre>
+# Declare a variable %fred
+%fred                     -Cdebug -eC -Wf,-init heap=nan stack=nan
+
+bld::tool::fflags         %fred
+# bld::tool::fflags       -Cdebug -eC -Wf,-init heap=nan stack=nan
+
+bld::tool::fflags::foo    %fred -f0
+# bld::tool::fflags::foo  -Cdebug -eC -Wf,-init heap=nan stack=nan -f0
+
+bld::tool::fflags::bar    -w %fred
+# bld::tool::fflags::bar  -w -Cdebug -eC -Wf,-init heap=nan stack=nan
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <h2><a name="verbose">Diagnostic verbose level</a></h2>
+
+  <p>The amount of diagnostic messages generated by the extract system is
+  normally set to a level suitable for normal everyday operation. This is the
+  default diagnostic verbose level 1. If you want a minimum amount of
+  diagnostic messages, you should set the verbose level to 0. If you want more
+  diagnostic messages, you can set the verbose level to 2 or 3. You can modify
+  the verbose level in two ways. The first way is to set the environment
+  variable FCM_VERBOSE to the desired verbose level. The second way is to
+  invoke the extract system with the "-v &lt;level&gt;" option. (If set, the
+  command line option overrides the environment variable.)</p>
+
+  <p>The following is a list of diagnostic output at each verbose level:</p>
+
+  <table class="pad" summary="List of diagnostic verbose output" border="1">
+    <tr>
+      <th>Verbose level</th>
+
+      <th>Possible output</th>
+    </tr>
+
+    <tr>
+      <th>0</th>
+
+      <td>
+        <ul>
+          <li>Report the time taken to extract the code.</li>
+
+          <li>Report the time taken to mirror the code.</li>
+
+          <li>If "rdist" is used to mirror the code, run the command with the
+          "-q" option.</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>1</th>
+
+      <td>
+        <ul>
+          <li>Everything at verbose level 0.</li>
+
+          <li>Report the name of the extract configuration file.</li>
+
+          <li>Report date/time at the beginning of the extract step.</li>
+
+          <li>Report the number of directories created, number of ignored
+          sub-directories, number of files updated and number of removed
+          files.</li>
+
+          <li>In override mode, report any files that are modified in two or
+          more branches.</li>
+
+          <li>Report date/time at the beginning of the mirror step.</li>
+
+          <li>Report total time.</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>2</th>
+
+      <td>
+        <ul>
+          <li>Everything at verbose level 1.</li>
+
+          <li>If the revision specified for a repository branch is not current
+          (i.e. the specified revision number is less than the revision number
+          of the last commit revision), print an information statement to
+          inform the user of the last commit revision of the branch.</li>
+
+          <li>Report details of created directories, ignored sub-directories,
+          removed files and updated files.</li>
+
+          <li>Report any files that have the same modifications in two or more
+          branches.</li>
+
+          <li>If "rdist" is used to mirror the code, run the command without the
+          "-q" option.</li>
+        </ul>
+      </td>
+    </tr>
+
+    <tr>
+      <th>3</th>
+
+      <td>
+        <ul>
+          <li>Everything at verbose level 2.</li>
+
+          <li>Report all shell commands invoked by the extract system with
+          timestamp.</li>
+
+          <li>If "rdist" is used to mirror the code, print the "distfile"
+          supplied to the command.</li>
+
+          <li>If "rsync" is used to mirror the code, invoke the command with
+          the "-v" option.</li>
+        </ul>
+      </td>
+    </tr>
+  </table>
+
+  <h2><a name="nosvn">When Subversion Is Not Available</a></h2>
+
+  <p>The extract system can still be used if Subversion is not available.
+  Clearly, you can only use local repositories. However, you can still do
+  incremental extraction, mirror an extraction to another machine, or combine
+  code from multiple local repositories.</p>
+
+  <p>If you are using Subversion but your server is down then clearly there is
+  little you can do. However, if you already have an extraction then you can
+  re-run <tt>fcm extract</tt> as long as the extract configuration file only
+  refers to fixed revisions. If this is not the case then you can always use the
+  expanded extract configuration file which can be found in "cfg/ext.cfg" under
+  the extract destination root. This means that you can continue to makes changes
+  to local code and do incremental extractions even whilst your Subversion server
+  is down.</p>
+
+  <script type="text/javascript" src="maintain.js"></script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/user_guide/further_info.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/user_guide/further_info.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/user_guide/further_info.html	(revision 1665)
@@ -0,0 +1,93 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide: Further Information</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide - Further Information">
+  <meta name="keywords" content="FCM, user guide">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; Further Information
+  </address>
+
+  <h1>Further Information</h1>
+
+  <ul>
+    <li>Project documents
+
+      <ul>
+        <li>
+          <a href="../../../FCM_Admin/doc/project/HighLevelDesign.html">High Level Design</a>
+
+          <ul>
+            <li>Gives the original reasons behind the choice of tools used in
+            the FCM system (e.g. Subversion &amp; Trac).</li>
+
+            <li>Some of the issues discussed are no longer relevant.</li>
+          </ul>
+        </li>
+
+        <li>
+          <a href="../design">FCM Detailed Design</a>
+
+          <ul>
+            <li>Information about the internal workings of the FCM system.</li>
+
+            <li>Intended mainly for people maintaining or developing the FCM
+            system.</li>
+          </ul>
+        </li>
+
+        <li>
+          <a href="../../../FCM_Admin/doc/project/scmUsecaseSolutions.html">Use-Case
+          Solution</a>
+
+          <ul>
+            <li>Discusses how FCM meets its requirements.</li>
+
+            <li>Some of the working practices discussed may not match current
+            advice. This User Guide takes precedence where there are any
+            differences.</li>
+          </ul>
+        </li>
+      </ul>
+    </li>
+
+    <li>Subversion
+
+      <ul>
+        <li><a href="http://subversion.tigris.org/">Subversion Home
+        Page</a></li>
+
+        <li><a href="http://svnbook.red-bean.com/en/1.2/">Subversion
+        Book</a></li>
+
+        <li><a href="http://subversion.tigris.org/faq.html">Subversion
+        FAQ</a></li>
+      </ul>
+    </li>
+
+    <li>Other links
+
+      <ul>
+        <li><a href="http://projects.edgewall.com/trac/">Trac Home
+        Page</a></li>
+
+        <li><a href="http://furius.ca/xxdiff/">xxdiff Home Page</a></li>
+
+        <li><a href="http://subversion.tigris.org/hacking.html">Hacker's
+        Guide to Subversion</a>: Contains some useful guidelines on log
+        message, filing issues, etc.</li>
+      </ul>
+    </li>
+  </ul>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/user_guide/getting_started.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/user_guide/getting_started.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/user_guide/getting_started.html	(revision 1665)
@@ -0,0 +1,1667 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide: Getting Started</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide - Getting Started">
+  <meta name="keywords" content="FCM, user guide, getting started, tutorial">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; Getting Started
+  </address>
+
+  <h1>Getting Started</h1>
+
+  <p><em>Getting Started</em> is a "hands-on" approach to help you set up your
+  FCM session, and familiarise yourself with some of the system's basic
+  concepts and working practices. It is designed to complement other sections
+  of the User Guide.</p>
+
+  <p>You may also find it useful to refer to the <a href=
+  "annex_quick_ref.html">Annex: Quick reference</a>.</p>
+
+  <h2><a name="setup">How to set yourself up to run FCM</a></h2>
+
+  <p>It is easy to set yourself up to run FCM. Simply follow the steps
+  below:</p>
+
+  <p><strong>Setting up your PATH</strong></p>
+
+  <p>The full FCM system is already available for you to use on the Met Office
+  Linux desktop systems. On other Met Office systems (currently NEC &amp;
+  HP-UX) only the build component is functional.</p>
+
+  <p>On Linux &amp; HP-UX systems FCM is automatically available in the
+  standard PATH. It is also automatically added to your PATH when you run UI
+  jobs on the NEC computers. However, if you intend to run FCM from the command
+  line on the NEC then you will need to add the following to your
+  <tt>$HOME/.profile</tt> script on that platform:</p>
+  <pre>
+. ~fcm/FCM/bin/env.sh  # Add FCM environment
+</pre>
+
+  <p><strong>Setting up the FCM GUI to work with Konqueror</strong></p>
+
+  <p>If you like to use a graphical user interface for some common code
+  management commands, you can set it up for launching from your desktop
+  Konqueror file manager by typing:</p>
+  <pre>
+(SHELL PROMPT)$ fcm_setup_konqueror
+</pre>
+
+  <p>See the section on <a href=
+  "code_management.html#svn_gui_konqueror">Accessing the GUI from Konqueror</a>
+  for further information.</p>
+
+  <p>Note that the first time you issue a command which requires authentication
+  you may need to supply a password or run it from the command line. See the
+  section on <a href="code_management.html#svn_gui_commands">GUI Commands</a>
+  for further information.</p>
+
+  <p><strong>Configure your editor for Subversion</strong></p>
+
+  <p>When you attempt to create a branch or commit changes to the repository,
+  you will normally be prompted to edit your commit log message using a text
+  editor. The system chooses its editor by searching for a non-empty string
+  through a hierarchy of environment variables in this order: SVN_EDITOR,
+  VISUAL, and EDITOR. If none of these environment variables are set, the
+  default is to use <em>nedit</em>. If you set your editor with an environment
+  variable, it is worth bearing in mind that it must be able to run in the
+  foreground. For example, you can add one of the followings in your
+  <tt>$HOME/.kshrc</tt> (Korn) or <tt>$HOME/.bashrc</tt> (Bash):</p>
+  <pre>
+# GVim
+export SVN_EDITOR='gvim -f'
+
+# Emacs
+export SVN_EDITOR=emacs
+
+# NEdit client "nc"
+export SVN_EDITOR='nc -wait'
+</pre>
+
+  <p><strong>Register your user name</strong></p>
+
+  <p>At the Met Office, most projects managed by FCM grant write accesses to
+  their Subversion repositories and Trac ticket create/modify privileges to
+  authorised users only. If you are developing code for a project for the first
+  time, please contact the system manager of the project, who will arrange with
+  the FCM team to put your user name in the register.</p>
+
+  <p><strong>Configure your e-mail address in Trac</strong></p>
+
+  <p>Trac can be configured to send automatic e-mail notifications to authors of
+  any ticket whenever there are changes to that ticket (and we would expect most
+  systems to be configured in this way). You should check that the settings for
+  your name and e-mail address are correct. To do this you need to go to the
+  Settings page once you are logged into Trac. (Click on &lt;Settings&gt; just
+  above the menu bar). Check that your settings are entered correctly. Note: at
+  the Met Office, these settings are set up and maintained automatically, and so
+  you should report any errors to the FCM team.</p>
+
+  <p><strong>Configure your web browser</strong></p>
+
+  <p>FCM assumes that you are using Firefox as your default web browser. If you
+  use another web browser such as Mozilla, you should configure it in your
+  <tt>$HOME/.fcm</tt> file. See the section on <a href=
+  "command_ref.html#fcm_svn_trac">fcm trac</a> for further information.</p>
+
+  <h2><a name="tutorial">Tutorial</a></h2>
+
+  <h3><a name="tutorial_intro">Introduction</a></h3>
+
+  <p>This tutorial leads you through the basics of using FCM to make changes to
+  your source code, and demonstrates the recommended practices for working with
+  it. A tutorial Subversion repository, with its own Trac system, is available
+  for you to practice for working with the FCM system. You will work through
+  the following activities:</p>
+
+  <ul>
+    <li><a href="#tutorial_create-ticket">Create a new ticket</a></li>
+
+    <li><a href="#tutorial_launch-gui">Launch the GUI</a></li>
+
+    <li><a href="#tutorial_create-branch">Create a branch</a></li>
+
+    <li><a href="#tutorial_checkout">Checkout a working copy</a></li>
+
+    <li><a href="#tutorial_change">Make changes to files in your working
+    copy</a></li>
+
+    <li><a href="#tutorial_commit">Commit your changes to the
+    repository</a></li>
+
+    <li><a href="#tutorial_extract">Test your changes</a></li>
+
+    <li><a href="#tutorial_merge">Merge changes from the trunk and resolve
+    conflicts</a></li>
+
+    <li><a href="#tutorial_review-ticket">Review changes</a></li>
+
+    <li><a href="#tutorial_merge-back">Commit to the trunk</a></li>
+
+    <li><a href="#tutorial_extra-extract">Extra activities on the extract and
+    build systems</a></li>
+
+    <li><a href="#tutorial_delete-branch">Delete your branch</a></li>
+
+    <li><a href="#tutorial_delete-final-comments">Final comments</a></li>
+  </ul>
+
+  <p>We recommend that you create a work area in your filespace, for example,
+  <tt>$HOME/tutorial/work</tt> for your working copy, and
+  <tt>$HOME/tutorial/build</tt> for your build.</p>
+
+  <p>If you have not already done so, you should set up your desktop environment
+  as described above in the <a href="#setup">How to set yourself up to run
+  FCM</a> section.</p>
+
+  <p>It is also worth knowing that the <a href=
+  "http://svnbook.red-bean.com/en/1.2/">Subversion Book</a> is a great source
+  of reference of Subversion features. In particular, the <a href=
+  "http://svnbook.red-bean.com/en/1.2/svn.basic.html">Basic Concepts</a> and
+  <a href="http://svnbook.red-bean.com/en/1.2/svn.tour.html">Guided Tour</a>
+  chapters are well worth reading.</p>
+
+  <h3><a name="tutorial_create-ticket">Create a new ticket</a></h3>
+
+  <p><em>Trac is an integrated web-based issue tracker and wiki system. You
+  will use it to manage and keep track of changes in your project. The issue
+  tracker is called the ticket system. When you want to report a problem or
+  submit a change request, you will create a new ticket. In a typical
+  situation, you and/or your colleagues will make changes to your system in
+  order to resolve the problem or change request, and you will monitor these
+  changes via the ticket.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>launch a Trac system,</li>
+
+    <li>create a new Trac ticket,</li>
+
+    <li>search for a Trac ticket, and</li>
+
+    <li>accept a Trac ticket.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li><a href="overview.html">System Overview</a></li>
+
+    <li>Code Management System &gt; <a href=
+    "code_management.html#svn_basic">Basic Command Line Usage</a></li>
+
+    <li>Code Management System &gt; <a href="code_management.html#trac">Using
+    Trac</a></li>
+
+    <li>FCM Command Reference &gt; <a href="command_ref.html#fcm_svn_trac">fcm
+    trac</a></li>
+  </ul>
+
+  <h4>Launch a Trac system</h4>
+
+  <p>To launch the Trac system for the tutorial: type and <span class=
+  "mono">&lt;Enter&gt;</span> the following command:</p>
+  <pre>
+(SHELL PROMPT)$ fcm trac fcm:tutorial
+</pre>
+
+  <p>This is probably the first time you have used the <tt>fcm</tt> command.
+  The command has the general syntax:</p>
+  <pre>
+fcm &lt;sub-command&gt; [&lt;options...&gt;] &lt;arguments&gt;
+</pre>
+
+  <p>For example, if you type <tt>fcm help</tt>, it will display a listing of
+  what sub-commands are available, and if you type <tt>fcm help
+  &lt;sub-command&gt;</tt>, it will display help for that particular
+  sub-command.</p>
+
+  <p>The <tt>trac</tt> sub-command launches the corresponding Trac system
+  browser for a Subversion URL specified in your argument. In this case, we are
+  asking it to display the Trac system browser for the tutorial. The argument
+  <tt>fcm:tutorial</tt> is a FCM URL keyword and will be expanded by FCM into a
+  real Subversion URL (e.g. <tt>svn://fcm1/tutorial_svn/tutorial</tt>). You are
+  encouraged to use FCM URL keywords throughout the tutorial, as it will save
+  you a lot of typing.</p>
+
+  <p>Note: Although we use the Trac system as a browser for a Subversion
+  repository, they do not interact in any other ways. Having access to a Trac
+  system does not guarantee the same privilege to a Subversion repository. In
+  particular, you should note the differences between the URLs of a Subversion
+  repository path and its equivalence in a Trac browser.</p>
+
+  <p>There are other ways to launch the Trac system for a project. If you know
+  its URL, you can launch the Trac system by entering it in the address box of
+  your favourite browser. If you often access a Trac system for a particular
+  project, you should bookmark it in your favourite browser.</p>
+
+  <h4>Create a new Trac ticket</h4>
+
+  <p>Click on <span class="mono">&lt;Login&gt;</span> just above the menu bar,
+  enter your Unix/Linux user ID as your user name and leave the password empty.
+  Then click on <span class="mono">&lt;OK&gt;</span> to proceed.</p>
+
+  <p>Once you have logged in, the <span class="mono">&lt;New Ticket&gt;</span>
+  link will become available on the menu bar. Click on it to display a new
+  ticket form, where you can enter details about your problem or change
+  request. In the tutorial, it does not matter what you enter, but you should
+  feel free to play around with wiki formatting when entering the "Full
+  description". (Click on <span class="mono">&lt;WikiFormatting&gt;</span> to
+  see how you can use it.) For example:</p>
+
+  <ul>
+    <li>Short summary:
+      <pre>
+Tutorial to change repository files and resolve conflicts with the trunk
+</pre>
+    </li>
+
+    <li>Full description:
+      <pre>
+In this tutorial, I shall:
+ 1. try out the FCM GUI and its functions
+ 2. play with WikiFormatting in Trac tickets     
+ 3. create a branch and checkout a working copy
+ 4. make changes to files in it
+ 5. commit my changes and assign the ticket for review
+ 6. record the review and assign the ticket back to the author
+ 7. merge in the trunk, and resolve any conflicts 
+ 8. merge my changes back to the trunk
+ 9. close the ticket
+ 10. delete my branch
+</pre>
+    </li>
+
+    <li>Feel free to select an option you desire for each of the other ticket
+    properties: Type, Component, Priority, Version, Milestone and
+    Severity.</li>
+  </ul>
+
+  <p>At the bottom of the page, click the <span class=
+  "mono">&lt;Preview&gt;</span> button to see what the description would look
+  like. When you are happy, click the <span class="mono">&lt;Submit
+  changes&gt;</span> button. Trac will create the new ticket and return it in a
+  state where you can append to it.</p>
+
+  <p>When the ticket is created, you should get an automatic e-mail notication
+  from the Trac system. In real life, depending on the setting, the owner of
+  your Trac system may also get a similar e-mail notification. It is worth
+  noting that each time the ticket is modified, the Trac system will send out an
+  e-mail notification to you (the reporter) and anyone who modified the ticket
+  subsequently.</p>
+
+  <h4>Search for a Trac ticket</h4>
+
+  <p>You should remember the number of your new ticket, as you will have to
+  revisit it later.</p>
+
+  <p>In real work, it is often not practical to have to remember the numbers of
+  all the tickets you have created. Trac provides a powerful custom query for
+  searching a ticket. You can search for the ticket you have just created by
+  clicking the <span class="mono">&lt;View Tickets&gt;</span> link. Feel free
+  to play with the custom query tool. Add or remove filters and try grouping
+  your results by different categories.</p>
+
+  <p>In addition, you can search your ticket using the keyword <span class=
+  "mono">&lt;Search&gt;</span> utility at the top right hand corner of each
+  Trac page. (If you enter <tt>#&lt;number&gt;</tt> in the search box, it will
+  take you directly to that ticket.) In the tutorial, however, it may be
+  easiest if you simply leave the tutorial Trac system open, so that you do not
+  have to login again when you come back to your ticket.</p>
+
+  <h4>Accept Trac ticket</h4>
+
+  <p>The status of the ticket is <em>new</em>. When you start working on a
+  problem reported in a ticket or when you are reviewing changes for a
+  colleague, it is often good practice to "accept" the ticket to indicate that
+  you are working on it. For the purpose of the tutorial, however, it is
+  entirely optional whether you accept the ticket or not, since you know you
+  will be doing all the work any way.</p>
+
+  <p>To accept a ticket, click on <span class="mono">&lt;accept
+  ticket&gt;</span> in the <em>Action</em> box at the bottom of the page, and
+  then click on <span class="mono">&lt;Submit changes&gt;</span>.</p>
+
+  <h3><a name="tutorial_launch-gui">Launch the GUI</a></h3>
+
+  <p><em>The FCM GUI is a basic graphical wrapper for some of the common code
+  management commands. Most examples in this tutorial can be done via the GUI.
+  You can skip this section and use only the command line if that is what you
+  prefer. Where appropriate, usage examples will be given for both the command
+  line and the FCM GUI.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>launch the GUI from the command line, and</li>
+
+    <li>launch the GUI from Konqueror.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li>Code Management System &gt; <a href=
+    "code_management.html#svn_gui">Using the GUI</a></li>
+
+    <li>FCM Command Reference &gt; <a href="command_ref.html#fcm_gui">fcm
+    gui</a></li>
+  </ul>
+
+  <h4>Launch the GUI from the command line</h4>
+
+  <p>You can launch the GUI from the command line. Change directory to your
+  work area and then type <tt>fcm gui</tt>.</p>
+
+  <h4>Launch the GUI from Konqueror</h4>
+
+  <p>Alternatively, open Konqueror and navigate to your work area. Right-click
+  in the file-manager window to bring up a menu. Select <em>Open with</em> &gt;
+  <em>FCM GUI</em>.</p>
+
+  <h3><a name="tutorial_create-branch">Create a branch</a></h3>
+
+  <p><em>You create a branch by making a copy of your project at a particular
+  revision. Most often, this will be a particular revision of the trunk, i.e.
+  the main branch/development line in your project.  A branch resides in the
+  repository. It allows you to work in parallel with your colleagues without
+  affecting one another, while keeping your changes under version
+  control.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>create a branch in a Subversion repository, and</li>
+
+    <li>update a ticket with a link to a branch.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li>Code Management System &gt; Branching &amp; Merging &gt; <a href=
+    "code_management.html#svn_branching_create">Creating Branches</a></li>
+
+    <li>Code Management Working Practices &gt; <a href=
+    "working_practices.html#branching">Branching &amp; Merging</a></li>
+
+    <li>FCM Command Reference &gt; <a href="command_ref.html#fcm_svn_br">fcm
+    branch</a></li>
+  </ul>
+
+  <h4>Create a branch in a Subversion repository</h4>
+
+  <p><em>Command line</em>: issue the <tt>fcm branch --create</tt> (or simply
+  <tt>fcm br -c</tt>) command. E.g.:</p>
+  <pre>
+(SHELL PROMPT)$ fcm br -c -n tutorial -r 1 --type test -k 2 fcm:tutorial
+</pre>
+
+  <p><em>FCM GUI</em>: click on <span class="mono">&lt;Branch&gt;</span> on the
+  top menu bar of the GUI. Check the <span class="mono">&lt;create&gt;</span>
+  radio button and configure your branch details as follow:</p>
+
+  <ul>
+    <li>Enter <tt>fcm:tutorial</tt> for the URL of the tutorial
+    repository.</li>
+
+    <li>Enter the short branch name. This must contain only alpha-numeric
+    characters and/or underscores, e.g. <tt>tutorial</tt>.</li>
+
+    <li>Enter <tt>1</tt> for the source revision. The trunk was last changed at
+    revision 2. To facilitate the generation of conflicts when you merge with
+    it, you will branch from revision 1 of the trunk.</li>
+
+    <li>Set the branch type. In this case click on <span class=
+    "mono">&lt;test::user&gt;</span>. This will ensure the branch you create is
+    a user test branch.</li>
+
+    <li>Leave the source type as <span class="mono">&lt;trunk&gt;</span> and
+    the prefix option as <span class="mono">&lt;normal&gt;</span>.</li>
+
+    <li>Enter the related Trac ticket number for the ticket you created
+    earlier.</li>
+
+    <li>As this is probably the first time you access the tutorial repository,
+    you should also enter <tt>--password ""</tt> (i.e. <tt>--password</tt>
+    followed by a pair of quotes) in the "Other Options" entry box.</li>
+  </ul>
+
+  <p>Click on <span class="mono">&lt;Run&gt;</span> when you are ready.</p>
+
+  <p class="image"><img src="create_branch.png" border="0" alt=
+  "create my branch"></p>
+
+  <p>You will be prompted to edit the message log file. A standard template is
+  automatically supplied for the commit. However, if you want to add extra
+  comment for the branch, please do so <strong>above</strong> the line that
+  says "<tt>--This line will be ignored and those below will be inserted
+  automatically--</tt>". When you are ready, save your change and exit the
+  editor. Answer <span class="mono">&lt;Yes&gt;</span> when you are prompted to
+  go ahead and create the branch.</p>
+
+  <p>Note: If you are on the command line, the Subversion command will prompt
+  you for a password the first time you access a repository. The password will
+  normally be cached by the client, and you will not have to specify a password
+  on subsequent access. If you are using the GUI, please refer to the section on
+  <a href="code_management.html#svn_gui_commands">GUI Commands</a> in the next
+  chapter for further information.</p>
+
+  <p>When creating branches for the first time, you will notice that FCM will
+  create and commit any missing sub-directories it needs to set up your branch
+  inside the repository, before creating your branch and commiting it.</p>
+
+  <p>Take a note of the revision number the branch was created at, and its
+  branch name. (The revision number is the number following the last output
+  that says "Committed revision". In the example above, the branch created at
+  <tt>[5]</tt> is called <tt>branches/test/frsn/r1_tutorial</tt>, which is a
+  branch of the <tt>tutorial</tt> project in the
+  <tt>svn://fcm1/tutorial_svn</tt> repository.)</p>
+
+  <h4>Update your ticket with a link to your branch</h4>
+
+  <p>If you wish, you can update your ticket with details of the branch. Note
+  that this step is entirely optional. It is useful for developments which will
+  take a long time to complete. For short lived branches, this step is probably
+  unnecessary.</p>
+
+  <p>In the ticket you have created, refer to the revision number in the
+  <em>Add/Change</em> box, for example:</p>
+  <pre>
+Created the branch [source:tutorial/branches/test/frsn/r1_tutorial@5] at [5].
+</pre>
+
+  <p>Note:</p>
+
+  <ul>
+    <li><tt>[source:tutorial/branches/test/frsn/r1_tutorial@5]</tt> is a Trac
+    wiki link. In this syntax, you do not have to put in the root URL, (e.g.
+    <tt>svn://fcm1/tutorial_svn/</tt>), but you should specify your branch
+    using the project name (<tt>tutorial</tt>), the branch name
+    (<tt>branches/test/frsn/r1_tutorial</tt>), and a revision number. Trac will
+    translate this into a link to that branch.</li>
+
+    <li>Trac will translate the syntax <tt>[&lt;number&gt;]</tt> into a link to
+    the numbered changeset.</li>
+  </ul>
+
+  <p>Click on &lt;Preview&gt; and check that the links work correctly, and on
+  <span class="mono">&lt;Submit changes&gt;</span> when you are ready.</p>
+
+  <h3><a name="tutorial_checkout">Checkout a working copy</a></h3>
+
+  <p><em>A Subversion working copy is an ordinary directory tree on your local
+  system, containing a collection of files. It is your private working area in
+  which you can make changes before publishing them back to the repository. You
+  create a working copy by using the checkout command on some subtree of the
+  repository.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>checkout a Subversion working copy.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li>Code Management System &gt; <a href=
+    "code_management.html#svn_concepts">Basic Concepts</a></li>
+
+    <li>FCM Command Reference &gt; <a href=
+    "command_ref.html#fcm_svn_other">Other Subversion Commands</a></li>
+  </ul>
+
+  <h4>Checkout a Subversion working copy</h4>
+
+  <p><em>Command line</em>: issue the <tt>fcm checkout</tt> (or simply
+  <tt>fcm co</tt>) command. E.g.:</p>
+  <pre>
+(SHELL PROMPT)$ fcm co fcm:tutorial_br/test/frsn/r1_tutorial
+</pre>
+
+  <p><em>FCM GUI</em>: click on <span class="mono">&lt;Checkout&gt;</span> in
+  the GUI, and enter the URL of your branch, e.g.
+  <tt>fcm:tutorial_br/test/frsn/r1_tutorial</tt>. Note:</p>
+
+  <ul>
+    <li>In the example, we have replaced the leading part of the Subversion URL
+    <tt>svn://fcm1/tutorial_svn/tutorial/branches</tt> with the FCM URL
+    keyword <tt>fcm:tutorial_br</tt>. This is mainly to save you from having to
+    type in the full URL. However, you may find it easier to copy-and-paste the
+    full Subversion URL from the output generated when you created the
+    branch.</li>
+
+    <li>If you do not specify a local directory PATH in the <tt>checkout</tt>
+    command, it will create a working copy in your current working directory,
+    using the basename of the URL you are checking out. For example, when you
+    checkout the branch you have just created, the command should create the
+    working copy in <tt>$PWD/r1_tutorial</tt>. Make a note of the location of
+    your working copy, in case you forget where you have put it.</li>
+
+    <li>If you do not specify a revision to checkout, it will checkout the
+    HEAD, i.e. the latest, revision.</li>
+  </ul>
+
+  <p>Click on <span class="mono">&lt;Run&gt;</span> - a working copy pointing
+  to your branch will be created. The GUI will automatically change directory
+  to the top of your new working copy.</p>
+
+  <table class="pad" summary="branch checkout example" border="1" width="100%">
+    <tr>
+      <th>Example output, checking out the branch</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+=&gt; svn co --revision HEAD svn://fcm1/tutorial_svn/tutorial/branches/test/frsn/r1_tutorial
+A    r1_tutorial/cfg
+A    r1_tutorial/cfg/ext.cfg
+A    r1_tutorial/doc
+A    r1_tutorial/doc/hello.html
+A    r1_tutorial/src
+A    r1_tutorial/src/subroutine
+A    r1_tutorial/src/subroutine/hello_c.c
+A    r1_tutorial/src/subroutine/hello_sub.f90
+A    r1_tutorial/src/module
+A    r1_tutorial/src/module/hello_constants.f90
+A    r1_tutorial/src/program
+A    r1_tutorial/src/program/hello.f90
+Checked out revision 5.
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <h3><a name="tutorial_change">Make changes to files in your working
+  copy</a></h3>
+
+  <p><em>Subversion provides various useful commands to help you monitor your
+  working copy. The most useful ones are "diff", "revert" and "status". You
+  will also find "add", "copy", "delete" and "move" useful when you are
+  rearranging your files and directories.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>make and revert changes,</li>
+
+    <li>add and remove files,</li>
+
+    <li>inspect the status of a working copy, and</li>
+
+    <li>display changes in a working copy.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li>Code Management System &gt; <a href=
+    "code_management.html#svn_basic">Basic Command Line Usage</a></li>
+
+    <li>FCM Command Reference &gt; <a href="command_ref.html#fcm_svn_add">fcm
+    add</a>, <a href="command_ref.html#fcm_svn_diff">fcm diff</a>, <a href=
+    "command_ref.html#fcm_svn_delete">fcm delete</a>, <a href=
+    "command_ref.html#fcm_svn_other">Other Subversion Commands</a></li>
+  </ul>
+
+  <h4>Make and revert changes</h4>
+
+  <p>For the later part of the tutorial to work, you must make the following
+  modification:</p>
+
+  <ul>
+    <li>Change to the "<tt>src/module/</tt>" sub-directory in your working
+    copy.</li>
+
+    <li>Edit <b>hello_constants.f90</b>, using your favourite editor, and
+    change: <em>"Hello World!"</em> to <em>"Hello Earthlings!"</em>. Save your
+    change and exit the editor.</li>
+  </ul>
+
+  <p>Try the following so that you know how to restore a changed file:</p>
+
+  <ul>
+    <li>Change to the "<tt>src/subroutine/</tt>" directory of your working
+    copy.</li>
+
+    <li>Make a change in file <b>hello_c.c</b>, using your favourite
+    editor.</li>
+
+    <li>To see that you have <u>M</u>odified this file: <em>command line</em>:
+    issue the "<tt>fcm status</tt>"command; <em>FCM GUI</em>: click on <span
+    class="mono">&lt;Status&gt;</span> and then on <span
+    class="mono">&lt;Run&gt;</span></li>
+
+    <li>Run the <em>revert</em> command to get the file back unmodified:
+      <pre>
+(SHELL PROMPT)$ fcm revert hello_c.c
+</pre>
+    </li>
+  </ul>
+
+  <h4>Add and remove files</h4>
+
+  <p>You may also want to try the following FCM commands in your <tt>doc/</tt>
+  sub-directory. You can safely make changes here since they will not interfere
+  with your code changes.</p>
+
+  <ul>
+    <li>change to the "doc/" directory of your working copy.</li>
+
+    <li>Echo some text into a new file and then run the <em>add</em> command,
+    which lets the repository know you're adding a new file at the next commit.
+    For example:
+      <pre>
+(SHELL PROMPT)$ echo 'Some text' &gt;new_file.txt
+(SHELL PROMPT)$ fcm add new_file.txt
+</pre>
+    </li>
+
+    <li>Make a copy of <em>hello.html</em> and remove the original, using the
+    <em>copy</em> and <em>delete</em> commands. For example:
+      <pre>
+(SHELL PROMPT)$ fcm copy hello.html add.html
+(SHELL PROMPT)$ fcm delete hello.html
+</pre>
+    </li>
+
+    <li>You can use a simple <em>move</em> sub-command for the above
+    <em>copy</em> and <em>delete</em>.</li>
+  </ul>
+
+  <h4>Inspect the status of a working copy</h4>
+
+  <p><em>Command line</em>: issue the <tt>fcm status</tt> (or simply <tt>fcm
+  st</tt>) command.</p>
+
+  <p><em>FCM GUI</em>: click on <span class="mono">&lt;Status&gt;</span> and
+  then on <span class="mono">&lt;Run&gt;</span> to see what has changed:</p>
+
+  <table class="pad" summary="status example 1" border="1" width="100%">
+    <tr>
+      <th>Example output, status in a working copy</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+=&gt; svn status
+D      doc/hello.html
+A      doc/new_file.txt
+A  +   doc/add.html
+M      src/module/hello_constants.f90
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>This confirms the actions you have taken. You have <u>D</u>eleted a file,
+  <u>A</u>dded a new file, <u>A</u>dded a file with history (<tt>+</tt>) and
+  <u>M</u>odified another. It also confirms the action of the <em>revert</em>
+  command.</p>
+
+  <h4>Display changes in a working copy</h4>
+
+  <p>You can view the changes you have made to your working copy.</p>
+
+  <p><em>Command line</em>: issue the <tt>fcm diff --graphical</tt>
+  (or simply <tt>fcm di -g</tt>) command.</p>
+
+  <p><em>FCM GUI</em>: click on <span class="mono">&lt;Diff&gt;</span> and then
+  on <span class= "mono">&lt;Run&gt;</span>.</p>
+
+  <p>A listing of the files you have changed will be displayed, and a graphical
+  diff tool will open up for each modified file.</p>
+
+  <h3><a name="tutorial_commit">Commit your changes to the repository</a></h3>
+
+  <p><em>The change in your working copy remains local until you commit it to
+  the repository where it becomes permanent. If you are planning to make a
+  large number of changes, you are encouraged to commit regularly to your
+  branch at appropriate intervals.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>commit your changes, and</li>
+
+    <li>inspect your changes using Trac.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li>Code Management System &gt; <a href=
+    "code_management.html#svn_basic">Basic Command Line Usage</a></li>
+
+    <li>FCM Command Reference &gt; <a href="command_ref.html#fcm_svn_ci">fcm
+    commit</a></li>
+  </ul>
+
+  <h4>Commit changes</h4>
+
+  <p><em>Command line</em>: issue the <tt>fcm commit</tt> (or simply <tt>fcm
+  ci</tt>) command.</p>
+
+  <p><em>FCM GUI</em>: click on <span class="mono">&lt;Commit&gt;</span> and
+  then on <span class="mono">&lt;Run&gt;</span>.</p>
+
+  <p>A text editor will appear to allow you to edit the commit message. You
+  must add a commit message to describe your change <strong>above</strong> the
+  line that says "<tt>--This line, and those below, will be ignored--</tt>". (A
+  suggestion is given as the highlighted text in the example below.) Your
+  commit will fail if you do not enter a commit message.</p>
+
+  <p>Save your change and exit the editor. Answer <span class=
+  "mono">&lt;Yes&gt;</span> when you are prompted to confirm the commit. For
+  example:</p>
+
+  <table class="pad" summary="status example 1" border="1" width="100%">
+    <tr>
+      <th>Example output, commit my changes to the repository</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+Starting nedit to create commit message ...
+Commit message is as follows:
+------------------------------------------------------------------------
+<font color="purple">In my tutorial branch, for #2:
+  1. Moved hello.html to add.html, and created a new document '''new_file.txt'''
+  2. Changed greeting in hello_constants.f90 to ''Hello Earthlings!''</font>
+--This line, and those below, will be ignored--
+[Project: tutorial]
+[Branch : branches/test/frsn/r1_tutorial]
+[Sub-dir: &lt;top&gt;]
+
+D      doc/hello.html
+A      doc/new_file.txt
+A  +   doc/add.html
+M      src/module/hello_constants.f90
+------------------------------------------------------------------------
+Adding         doc/add.html
+Deleting       doc/hello.html
+Adding         doc/new_file.txt
+Sending        src/module/hello_constants.f90
+Transmitting file data ..
+Committed revision 6.
+Performing update to make sure your working copy is at this new revision ...
+At revision 6.
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <h4>Inspect changes using Trac</h4>
+
+  <p>Click on <span class="mono">&lt;Timeline&gt;</span> in Trac. Drill down to
+  your changeset and see how it appears. (Alternatively, if you enter
+  "<tt>[&lt;number&gt;]</tt>" into the search box at the top right, it will
+  take you directly to the numbered changeset.) For example:</p>
+
+  <p class="image"><img src="changeset.png" border="0" alt=
+  "commit my changes"></p>
+
+  <p>Note:</p>
+
+  <ul>
+    <li>Wiki Formatting, used in the commit message, has customised the
+    changeset message.</li>
+
+    <li>All your changes are listed.</li>
+  </ul>
+
+  <h3><a name="tutorial_extract">Test your changes</a></h3>
+
+  <p><em>You should test the changes in your branch before asking a colleague
+  to review them. FCM features a build system that allows you to build your
+  code easily. As your changes may be located in a repository branch and/or a
+  working copy, you should work with the extract system to extract the correct
+  code to build. The extract system allows you to extract code from the
+  repository, combining changes in different branches and your working copy,
+  before generating a configuration file and a suitable source tree for feeding
+  into the build system.</em></p>
+
+  <p><em>In this sub-section of the tutorial, you will be shown how to extract
+  and build the code from your branch. (There are some <a href=
+  "#tutorial_extra-extract">extra activities on the extract and build
+  systems</a> in a later sub-section of the tutorial should you want to explore
+  the extract and build systems in more depth.) In the example here, the
+  extract and build systems will be shown to you in their simplest form. In
+  real life, the managers of the systems you are developing code for will
+  provide you with more information on how to extract and build their
+  systems.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>set up a simple extract configuration file, and</li>
+
+    <li>perform simple extracts and builds.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li><a href="extract.html">The Extract System</a></li>
+
+    <li><a href="build.html">The Build System</a></li>
+  </ul>
+
+  <p>You should extract and build your code in a different directory to your
+  working copy. For example, you may want to create a sub-directory
+  <tt>tutorial/build/</tt> in <tt>$HOME</tt> and change to it:</p>
+  <pre>
+(SHELL PROMPT)$ mkdir -p $HOME/tutorial/build
+(SHELL PROMPT)$ cd $HOME/tutorial/build
+</pre>
+
+  <h4>Set up an extract configuration file</h4>
+
+  <p>To set up an extract configuration file from scratch, launch your
+  favourite editor and add the following lines:</p>
+
+  <table class="pad" summary="extract config example, branch" border="1" width=
+  "100%">
+    <tr>
+      <th>Example extract configuration, extract from a branch</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+# Extract configuration, format version 1.0
+cfg::type              ext
+cfg::version           1.0
+
+# Extract destination root directory
+dest::rootdir          $HOME/tutorial/build
+
+# Location of the source in the "r1_tutorial" branch
+repos::tutorial::base  fcm:tutorial_br/test/$LOGNAME/r1_tutorial
+
+# Extract all sub-directories under the above URL
+expsrc::tutorial::base src
+
+# Fortran compiler, C compiler and linker commands respectively
+# You may need to redefine these for different platforms
+bld::tool::fc          ifc
+bld::tool::cc          gcc
+bld::tool::ld          ifc
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Note:</p>
+
+  <ul>
+    <li>The "<tt>dest::rootdir</tt>" declaration is set to
+    <tt>$HOME/tutorial/build</tt>. If you decide to extract to a different
+    directory, you should modify its value.</li>
+
+    <li>Similarly, the "<tt>repos::tutorial::base</tt>" declaration is set to
+    <tt>fcm:tutorial_br/test/$LOGNAME/r1_tutorial</tt>. If you have named your
+    branch differently, you should modify its value.</li>
+  </ul>
+
+  <p>Save the file as "<tt>ext.cfg</tt>" and exit your editor.</p>
+
+  <h4>Perform an extract and a build</h4>
+
+  <p>Issue the command "<tt>fcm extract</tt>" and you should get an output
+  similar to the following:</p>
+
+  <table class="pad" summary="extract example, branch" border="1" width="100%">
+    <tr>
+      <th>Example output, extract from a branch</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm extract
+Extraction started on Thu Oct 27 13:54:06 2005.
+Config file (ext): /net/home/h01/frsn/tutorial/build/ext.cfg
+-&gt;Extract: start
+Number of directories created    : 4
+Number of updated files          : 4
+-&gt;Extract: 1 second
+-&gt;TOTAL  : 1 second
+Extraction finished on Thu Oct 27 13:54:07 2005.
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>If nothing goes wrong, you should end up with the sub-direcories
+  "<tt>src/</tt>" and "<tt>cfg/</tt>" in your working directory. The
+  "<tt>src/</tt>" contains a source tree to be built, and "<tt>cfg/</tt>" should
+  contain two configuration files: "<tt>ext.cfg</tt>" and "<tt>bld.cfg</tt>".
+  The former is an expanded version of your extract configuration file and the
+  latter is a build configuration file. You can now build your code by running
+  the "<tt>fcm build</tt>" command:</p>
+
+  <table class="pad" summary="build example, branch" border="1" width="100%">
+    <tr>
+      <th>Example output, build</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm build 2&gt;err
+Build command started on Fri Oct 14 09:15:38 2005.
+-&gt;gt;Setup              : start
+Config file (bld): /net/home/h01/frsn/tutorial/build/cfg/bld.cfg
+-&gt;Setup              : 0 second
+-&gt;Pre-process        : start
+-&gt;Pre-process        : 0 second
+-&gt;Scan dependency    : start
+Scanned files in 3 package(s) for dependency
+Updated make rules for 3 package(s).
+Updated Makefile: /net/home/h01/frsn/tutorial/build/bld/Makefile
+-&gt;Scan dependency    : 1 second
+-&gt;Generate interface : start
+Number of generated interfaces: 1
+-&gt;Generate interface : 0 second
+-&gt;Make               : start
+ifc -o hello_constants.o -I/home/h01/frsn/tutorial/build/inc -c
+  /home/h01/frsn/tutorial/build/src/tutorial/src/module/hello_constants.f90
+ifc -o hello.o -I/home/h01/frsn/tutorial/build/inc -c
+  /home/h01/frsn/tutorial/build/src/tutorial/src/program/hello.f90
+ifc -o hello_sub.o -I/home/h01/frsn/tutorial/build/inc -c
+  /home/h01/frsn/tutorial/build/src/tutorial/src/subroutine/hello_sub.f90
+gcc -o hello_c.o -I/home/h01/frsn/tutorial/build/inc -c
+  /home/h01/frsn/tutorial/build/src/tutorial/src/subroutine/hello_c.c
+ifc -o hello.exe /home/h01/frsn/tutorial/build/obj/hello.o
+  -L/home/h01/frsn/tutorial/build/lib -l__fcm__hello
+-&gt;Make               : 3 seconds
+-&gt;TOTAL              : 4 second
+Build command finished on Fri Oct 14 09:15:42 2005.
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>The executable you have built is "<tt>hello.exe</tt>", which is located in
+  the "<tt>bin/</tt>" sub-directory. You can test your executable by running
+  it. You should get an output similar to the following:</p>
+
+  <table class="pad" summary="build example run, working copy" border="1"
+  width="100%">
+    <tr>
+      <th>Example output, running the build</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ bin/hello.exe 
+Hello: Hello Earthlings!
+Hello_Sub: Hello Earthlings!
+Hello_Sub: maximum integer: 2147483647
+Hello_C: Hello World!
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <h3><a name="tutorial_merge">Merge changes from the trunk and resolve
+  conflicts</a></h3>
+
+  <p><em>Your branch is normally isolated from other development lines in your
+  project. However, at some point during your development, you may need to merge
+  your changes with those of your colleagues. In some cases, it is desirable to
+  merge changes regularly from the trunk to keep your branch up to date with the
+  latest development. The automatic merge provided by FCM allows you to do this
+  easily.</em></p>
+
+  <p><em>A merge results in a conflict if changes being applied to a file
+  overlap. FCM uses a graphical merge tool to help you resolve conflicts in text
+  files.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>merge changes from the trunk into your working copy, and</li>
+
+    <li>resolve conflicts in your working copy.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li>Code Management System &gt; Basic Command Line Usage &gt; <a href=
+    "code_management.html#svn_basic_conflicts">Resolving Conflicts</a></li>
+
+    <li>Code Management System &gt; <a href=
+    "code_management.html#svn_branching">Branching &amp; Merging</a></li>
+
+    <li>Code Management Working Practices &gt; <a href=
+    "working_practices.html#branching">Branching &amp; Merging</a></li>
+
+    <li>FCM Command Reference &gt; <a href="command_ref.html#fcm_svn_cf">fcm
+    conflicts</a></li>
+
+    <li>FCM Command Reference &gt; <a href="command_ref.html#fcm_svn_merge">fcm
+    merge</a></li>
+  </ul>
+
+  <h4>Merge changes from the trunk into a working copy</h4>
+
+  <p>Perform the merge in your working copy.</p>
+
+  <p><em>Command line</em>: issue the <tt>fcm merge</tt> command. E.g.</p>
+  <pre>
+(SHELL PROMPT)$ fcm merge trunk
+</pre>
+
+  <p><em>FCM GUI</em>: click on <span class="mono">&lt;Merge&gt;</span>. Enter
+  "<tt>trunk</tt>" into the Source entry box and click on <span class=
+  "mono">&lt;Run&gt;</span> to proceed.</p>
+
+  <p>If there is more than one revision of the source that you can merge with,
+  you will be prompted for the revision number you wish to merge from. You will
+  not be prompted in this case, because there is only one revision of the
+  source that you can merge with.</p>
+
+  <p>Answer <span class="mono">&lt;Yes&gt;</span> when you are prompted to go
+  ahead with the merge.</p>
+
+  <table class="pad" summary="merge from trunk example" border="1" width=
+  "100%">
+    <tr>
+      <th>Example output, merging changes from the trunk</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+Available Merges From /tutorial/trunk: 2
+About to merge in changes from tutorial/trunk@2 compared with tutorial/trunk@1
+This merge will result in the following changes:
+------------------------------------------------------------------------
+U    src/subroutine/hello_c.c
+C    src/module/hello_constants.f90
+------------------------------------------------------------------------
+Performing merge ...
+U    src/subroutine/hello_c.c
+C    src/module/hello_constants.f90
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <h4>Resolve conflicts in a working copy</h4>
+
+  <p>The "C" status indicates that the file you changed is now in conflict. If
+  you run <tt>status</tt>, you will see extra files created by the merge, which
+  enable you to resolve the conflict using the 3-way difference tool
+  <em>xxdiff</em>:</p>
+
+  <table class="pad" summary="conflict status example" border="1" width="100%">
+    <tr>
+      <th>Example output, status in conflict</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+=&gt; svn status
+M      src/subroutine/hello_c.c
+?      src/module/hello_constants.f90.merge-left.r1
+?      src/module/hello_constants.f90.merge-right.r2
+?      src/module/hello_constants.f90.working
+C      src/module/hello_constants.f90
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>You will now have to resolve the conflicts.</p>
+
+  <p><em>Command line</em>: issue the <tt>fcm conflicts</tt> (or simply <tt>fcm
+  cf</tt>) command.</p>
+
+  <p><em>FCM GUI</em>: click on <span class="mono">&lt;Conflicts&gt;</span> and
+  then on <span class="mono">&lt;Run&gt;</span>.</p>
+
+  <p><em>xxdiff</em> comes into play:</p>
+
+  <p class="image"><img src="xxdiff_tutorial.png" border="0" alt=
+  "3-way diff"></p>
+
+  <p>See the sub-section on <a href=
+  "code_management.html#svn_basic_conflicts">resolving conflicts</a>, or the
+  <em>xxdiff User's Manual (click on <span class=
+  "mono">&lt;Help&gt;</span>)</em> to guide you through this process. (If you
+  do not want to learn how to use <em>xxdiff</em> now, you can just select
+  <em>Exit with ACCEPT</em> from the <em>File</em> menu. This saves the file
+  you are merging in as the result of the merge, i.e. you have
+  <em>accepted</em> all the changes).</p>
+
+  <p>On resolving the conflict, you will be asked to run "<tt>svn
+  resolved</tt>". Answer <span class="mono">&lt;Yes&gt;</span>.</p>
+
+  <p>If you now run <tt>status</tt>, you will notice that these extra conflict
+  files have disappeared.</p>
+
+  <table class="pad" summary="resolve conflicts example" border="1" width=
+  "100%">
+    <tr>
+      <th>Example output, resolving conflicts</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+Conflicts in file: src/module/hello_constants.f90
+All merge conflicts resolved
+Resolved conflicted state of 'hello_constants.f90'
+=&gt; svn status
+M      src/subroutine/hello_c.c
+M      src/module/hello_constants.f90
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>It is important to remember that the <tt>merge</tt> command only applies
+  changes to your working copy. Therefore, you must now commit the change in
+  order for it to become permanent in the repository. Similar to other changes,
+  it is a good practice to use <tt>diff</tt> to inspect the changes before
+  committing.</p>
+
+  <p>When you run <tt>commit</tt>, you will be prompted to edit the commit log
+  as usual. However, you may notice that a standard template is already
+  provided for you by the <tt>merge</tt> command. In most cases, the standard
+  message should be sufficient. However, if you want to add extra comment to
+  the commit, please do so <strong>above</strong> the line that says
+  "<tt>--This line will be ignored and those below will be inserted
+  automatically--</tt>". This is useful, for example, if there were significant
+  issues addressed in the merge.</p>
+
+  <h3><a name="tutorial_review-ticket">Review changes</a></h3>
+
+  <p><em>For the purpose of this tutorial, we assume that your changes are
+  complete, have been tested and committed to the repository, and are now ready
+  for review. You should assign the ticket to the reviewer and inform him/her
+  where to find the changes you wish him/her to review. The reviewer will
+  record any issues in the ticket, perhaps linking to other documents as
+  required. Once completed, he/she will record the outcome in the ticket and
+  assign it back to the you.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>display changes in a branch, and</li>
+
+    <li>re-assign a ticket.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li>Code Management System &gt; Branching &amp; Merging &gt; <a href=
+    "code_management.html#svn_branching_info">Getting Information About
+    Branches</a></li>
+
+    <li>Code Management System &gt; <a href="code_management.html#trac">Using
+    Trac</a></li>
+
+    <li>Code Management Working Practices &gt; <a href=
+    "working_practices.html#tickets">Using Tickets</a></li>
+
+    <li>FCM Command Reference &gt; <a href="command_ref.html#fcm_svn_diff">fcm
+    diff</a></li>
+  </ul>
+
+  <h4>Display changes in a branch</h4>
+
+  <p>Before you ask someone to review your code, it is often a good idea to have
+  a look at the changes one more time. To view the changes in a branch, you can
+  look at all the changes relative to its base.</p>
+
+  <p><em>Command line</em>: issue the <tt>fcm diff --branch --graphical</tt> (or
+  simply <tt>fcm di -b -g</tt>) command.</p>
+
+  <p><em>FCM GUI</em>: click on <span class="mono">&lt;Diff&gt;</span>. Check the
+  box <span class="mono">&lt;Show differences relative to the base of the
+  branch&gt;</span>, and click on <span class="mono">&lt;Run&gt;</span>.</p>
+
+  <p>You should be presented with the differences between the branch and the
+  trunk (since the last merge).</p>
+  
+  <p>Note: you can also use the <tt>--trac</tt> (<tt>-t</tt>) option instead of
+  <tt>--graphical</tt> (<tt>-g</tt>) to view the changes in a branch using Trac
+  rather than using a graphical diff tool. Take note of the Trac URL for
+  displaying the differences. The part that begins with <tt>"diff:"</tt> is of
+  particular interest to you, as it is a Trac link that can be inserted into a
+  Trac wiki/ticket. In the above example, the Trac link would look like:
+  <tt>diff:/tutorial/trunk@2///tutorial/branches/test/frsn/r1_tutorial@7</tt>.
+
+  <h4>Re-assign a ticket to a reviewer</h4>
+
+  <p>Back in your ticket, add an appropriate comment showing where to find your
+  changes, in the <em>Add/Change</em> box. Include a link to your branch and a
+  diff link (see above) in the comment. For example:</p>
+
+  <table summary="review ticket example" border="1">
+    <tr>
+      <td>
+        <pre>
+The [log:tutorial/branches/test/frsn/r1_tutorial@5:7] branch proposes changes to
+the greeting in hello_constants.f90. It also contains some new documents. See
+[diff:/tutorial/trunk@2///tutorial/branches/test/frsn/r1_tutorial@7] for the
+changes.
+
+Fred, could you review the change, please?
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Note: the syntax <tt>[log:tutorial/branches/test/frsn/r1_tutorial@5:7]</tt>
+  will be translated by Trac into a link to the revision log browser to display
+  the log between revision 5 and 7 of the
+  <tt>branches/test/frsn/r1_tutorial</tt> branch in the <tt>tutorial</tt>
+  project; and the syntax
+  <tt>[diff:/tutorial/trunk@2///tutorial/branches/test/frsn/r1_tutorial@7]</tt>
+  will be translated into a link to display the differences between the trunk at
+  revision 2 and the branch at revision 7. Click on &lt;Preview&gt; and check
+  that the links work correctly.</p>
+
+  <p>To re-assign a ticket to your reviewer, click on the <span class=
+  "mono">&lt;reassign to&gt;</span> button in the <em>Action</em> box section
+  and enter the reviewer's User ID.</p>
+
+  <p>When you are ready, click on <span class="mono">&lt;Submit
+  changes&gt;</span>.</p>
+
+  <h4>Reassign the ticket back to the author</h4>
+
+  <p>For the purpose of this tutorial, you will act as the reviewer of the
+  changes you have made. Following the review, you should record its outcome and
+  re-assign the ticket back to the author. Enter the comment "<tt>No issues were
+  found during the review</tt>". Click on the <span class="mono">&lt;reassign
+  to&gt;</span> button in the <em>Action</em> box section, and enter your guest
+  account name. Click on <span class="mono">&lt;Submit changes&gt;</span> when
+  you are ready.</p>
+
+  <h3><a name="tutorial_merge-back">Commit to the trunk</a></h3>
+
+  <p><em>Your changes in the branch have been tested and reviewed. It is now
+  time to merge and commit it to the trunk. Once you have committed your
+  change, you will close your ticket to complete the work cycle.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>use the <tt>switch</tt> command,</li>
+
+    <li><tt>merge</tt> and <tt>commit</tt> your changes into the trunk,
+    and</li>
+
+    <li>close a ticket</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li>Code Management System &gt; <a href=
+    "code_management.html#svn_branching">Branching &amp; Merging</a></li>
+
+    <li>Code Management Working Practices &gt; <a href=
+    "working_practices.html#branching">Branching &amp; Merging</a></li>
+
+    <li>FCM Command Reference &gt; <a href=
+    "command_ref.html#fcm_svn_switch">fcm switch</a></li>
+  </ul>
+
+  <h4>Switch a working copy to point to the trunk</h4>
+
+  <p><em>Command line</em>: issue the <tt>fcm switch</tt> (or simply <tt>fcm
+  sw</tt>) command. E.g.:</p>
+  <pre>
+(SHELL PROMPT)$ fcm sw trunk
+</pre>
+
+  <p><em>FCM GUI</em>: click on <span class="mono">&lt;Switch&gt;</span>. Enter
+  "<tt>trunk</tt>" as the URL and then click on <span class=
+  "mono">&lt;Run&gt;</span>.</p>
+
+  <p>To check that your working copy is pointing to the trunk, you should:
+  <em>command line</em>: issue the <tt>fcm info</tt> command; <em>FCM GUI</em>:
+  inspect the "corresponding URL" of your working copy.</p>
+
+  <h4>Merge and commit your changes into the trunk</h4>
+
+  <p><em>Command line</em>: issue the <tt>fcm merge</tt> command.  E.g.</p>
+  <pre>
+(SHELL PROMPT)$ fcm merge branches/test/frsn/r1_tutorial
+</pre>
+
+  <p><em>FCM GUI</em>: click on <span class="mono">&lt;Merge&gt;</span>. Enter
+  the name of your branch in the Source entry box, (e.g.
+  "<tt>branches/test/frsn/r1_tutorial</tt>"). Click on <span class=
+  "mono">&lt;Run&gt;</span> to proceed.</p>
+
+  <table class="pad" summary="merge back to trunk example" border="1" width=
+  "100%">
+    <tr>
+      <th>Example output, merging changes back to the trunk</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+Available Merges From /tutorial/branches/test/frsn/r1_tutorial: 7 6
+About to merge in changes from /tutorial/branches/test/frsn/r1_tutorial@7
+  compared with /tutorial/trunk@2
+This merge will result in the following changes:
+------------------------------------------------------------------------
+D    doc/hello.html
+A    doc/new_file.txt
+U    src/module/hello_constants.f90
+A    add.html
+------------------------------------------------------------------------
+Performing merge ...
+D    doc/hello.html
+A    doc/new_file.txt
+U    src/module/hello_constants.f90
+A    add.html
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Since there is more than one revision available for merging, you will be
+  prompted for the revision number you wish to merge from. The default is the
+  last changed revision of your branch. which is the revision you want to merge
+  with, so you should just proceed with the default.</p>
+
+  <p>Answer <span class="mono">&lt;Yes&gt;</span> when you are prompted to go
+  ahead with the merge.</p>
+
+  <p>Since we merged in the latest changes from the trunk into the branch,
+  there should be no conflicts from this merge.</p>
+
+  <p>Once again, please remember that the merge command only changes your
+  working copy. You need to commit the change before it becomes permanent in
+  the repository. Before you commit to the trunk, however, it is often sensible
+  to have a last look at what you are going to change using the <tt>diff</tt>
+  command.</p>
+
+  <p>Note: We have set up the repository to prevent any commits to the trunk to
+  preserve the tutorial for other users, so your commit to the trunk will fail.
+  However, you should try doing it any way to complete the exercise.</p>
+
+  <p><em>Command line</em>: issue the <tt>fcm commit</tt> (or simply <tt>fcm
+  ci</tt>) command.</p>
+
+  <p><em>FCM GUI</em>: click on <span class="mono">&lt;Commit&gt;</span> and
+  then on <span class="mono">&lt;Run&gt;</span>.</p>
+
+  <p>A text editor will appear to allow you to edit the commit message. You
+  must add a commit message to describe your change <strong>above</strong> the
+  line that says "<tt>--This line will be ignored and those below will be
+  inserted automatically--</tt>". Since you are going to commit changes to the
+  trunk, you should provide a useful message, including a link to your ticket.
+  For example:</p>
+
+  <table summary="" border="1">
+    <tr>
+      <td>
+        <pre>
+For #2: complete the tutorial:
+  1. Changed greeting in hello_constants.f90 to "Hello Earthlings!"
+  2. Moved hello.html to add.html, and created a new document ''new_file.txt''
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>When you are ready, save your change and exit the editor.</p>
+
+  <p>As we have said before, the command will fail when you try to proceed with
+  the commit.</p>
+
+  <h4>Close your ticket</h4>
+
+  <p>As you have completed your work, you should now update and close your
+  ticket. In real life, you will typically include a closing comment with an
+  appropriate Trac wiki link to the changeset in the trunk that fixes the
+  ticket.</p>
+
+  <p>Since you cannot commit to the trunk in the tutorial, you can include a
+  Trac link to the latest changeset in your branch. For example, you can put
+  "<tt>Fixed at changeset [7].</tt>" in the comment. To mark the ticket as
+  "fixed", move down to the <em>Action</em> box section, click on <span class=
+  "mono">&lt;resolve as&gt;</span> and choose <em>fixed</em>. Use <span class=
+  "mono">&lt;Preview&gt;</span> to ensure that your links work correctly. When
+  you are happy, click on <span class="mono">&lt;Submit changes&gt;</span>.</p>
+
+  <h3><a name="tutorial_extra-extract">Extra activities on the extract and
+  build systems</a></h3>
+
+  <p><em>The extract and build systems are very flexible. If you have time, you
+  may want to explore their uses in more depth.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>extract from a working copy,</li>
+
+    <li>change a compiler flag, and</li>
+
+    <li>extract from a particular branch and/or revision from the
+    repository.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li><a href="extract.html">The Extract System</a></li>
+
+    <li><a href="build.html">The Build System</a></li>
+  </ul>
+
+  <h4>Extract from a working copy</h4>
+
+  <p>Modify the source files in your working copy and commit the changes back
+  to your branch in the repository. Re-run <tt>"fcm extract"</tt> and <tt>"fcm
+  build"</tt> and see the results of the changes. [The file(s) you have changed
+  should be updated by "extract", and "build" should only re-build the
+  necessary code.]</p>
+
+  <p>In fact, you can test changes in your working copy directly using a
+  similar "extract" and "build" mechanism. In such case, you need to modify the
+  REPOS declaration. For example:</p>
+  <pre>
+repos::tutorial::base  $HOME/fcm/work/r1_tutorial
+</pre>
+
+  <h4>Change a compiler flag</h4>
+
+  <p>Modify the compiler flags, and re-run <tt>"fcm extract"</tt> and <tt>"fcm
+  build"</tt> and see the results of the changes. To modify the compiler flags,
+  edit your extract configuration file, and add the declarations for changing
+  compiler flags. For example:</p>
+  <pre>
+# Declare extra options for Fortran compiler
+bld::tool::fflags  -i8 -O3
+</pre>
+
+  <p>For further information on how to set your compiler flags, please refer to
+  the sub-section on <a href="build.html#basic_flags">Setting the compiler
+  flags</a>.</p>
+
+  <h4>Extract from a particular branch and/or revision</h4>
+
+  <p>Try extracting from an earlier revision of your branch. Suppose the HEAD
+  of your branch is revision 7, and the branch was created at an earlier
+  revision. You can extract your branch at, say, revision 5 by adding a
+  declaration in your extract configuration file:</p>
+  <pre>
+version::tutorial::base  5
+</pre>
+
+  <p>You can also try extracting from the trunk. In such case, you will need to
+  modify the REPOS declaration in your extract configuration file. For
+  example:</p>
+  <pre>
+repos::tutorial::base  fcm:tutorial_tr/src
+
+# Extract with and without the following line and note the difference!
+version::tutorial::base  1
+</pre>
+
+  <h3><a name="tutorial_delete-branch">Delete your branch</a></h3>
+
+  <p><em>You should remove your branch when it is no longer required. When you
+  remove it, it becomes invisible from the HEAD revision, but will continue to
+  exist in the repository, should you want to refer to it in the
+  future.</em></p>
+
+  <p>After completing this sub-section, you will learn how to:</p>
+
+  <ul>
+    <li>list branches owned by you, and</li>
+
+    <li>delete a branch.</li>
+  </ul>
+
+  <p>Further reading:</p>
+
+  <ul>
+    <li>Code Management System &gt; Branching &amp; Merging &gt; <a href=
+    "code_management.html#svn_branching_list">Listing Branches Created by You
+    or Other Users</a></li>
+
+    <li>Code Management System &gt; Branching &amp; Merging &gt; <a href=
+    "code_management.html#svn_branching_delete">Deleting Branches</a></li>
+  </ul>
+
+  <h4>List branches owned by you</h4>
+
+  <p>If you forget what your branch is called and/or what other branches you
+  have created, you can get a listing of all the branches you have created in a
+  project.</p>
+
+  <p><em>Command line</em>: issue the <tt>fcm branch --list</tt> (or simply
+  <tt>fcm br -l</tt>) command</p>
+  
+  <p><em>FCM GUI</em>: click on <span class= "mono">&lt;Branch&gt;</span>, and
+  then on the <span class= "mono">&lt;list&gt;</span> radio button. Click on
+  <span class= "mono">&lt;Run&gt;</span>.</p>
+
+  <h4>Delete a branch</h4>
+
+  <p>Switch your working copy to point back to your branch.</p>
+  
+  <p><em>Command line</em>: issue the <tt>fcm switch &lt;URL&gt;</tt> (or simply
+  <tt>fcm sw &lt;URL&gt;</tt>) command.</p>
+  
+  <p><em>FCM GUI</em>: click on <span class="mono">&lt;Switch&gt;</span>. Enter
+  the name of your branch as the URL and click on <span
+  class="mono">&lt;Run&gt;</span> to proceed.</p>
+
+  <p>You can continue your work in the branch if you wish, but once you have
+  finished all the work, you should delete it. <em>Command line</em>: issue the
+  <tt>fcm branch --delete</tt> (or simply <tt>fcm br -d</tt>) command. <em>FCM
+  GUI</em>: click on <span class="mono">&lt;Branch&gt;</span> in the GUI. Check
+  the <span class= "mono">&lt;delete&gt;</span> radio button, and click <span
+  class= "mono">&lt;Run&gt;</span> to proceed.</p>
+
+  <table class="pad" summary="branch delete example" border="1" width="100%">
+    <tr>
+      <th>Example output, deleting a branch</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+URL: svn://fcm1/tutorial_svn/tutorial/branches/test/frsn/r1_tutorial
+Repository Root: svn://fcm1/tutorial_svn
+Repository UUID: cb858ce8-0f05-0410-9e64-efa98b760b62
+Revision: 7
+Node Kind: directory
+Last Changed Author:
+Last Changed Rev: 7
+Last Changed Date: 2005-11-09 09:11:57 +0000 (Wed, 09 Nov 2005)
+--------------------------------------------------------------------------------
+Branch Create Rev: 5
+Branch Create Date: 2005-11-09 08:34:22 +0000 (Wed, 09 Nov 2005)
+Branch Parent: svn://fcm1/tutorial_svn/tutorial/trunk@1
+--------------------------------------------------------------------------------
+Last Merge From Trunk: /tutorial/branches/test/frsn/r1_tutorial@7
+                       /tutorial/trunk@2
+Avail Merges Into Trunk: 7 6
+Starting nedit to create commit message ...
+Commit message is as follows:
+------------------------------------------------------------------------
+Deleted tutorial/branches/test/frsn/r1_tutorial.
+--This line, and those below, will be ignored--
+D    svn://fcm1/tutorial_svn/tutorial/branches/test/frsn/r1_tutorial
+------------------------------------------------------------------------
+Deleting branch
+  svn://fcm1/tutorial_svn/tutorial/branches/test/frsn/r1_tutorial ...
+
+Committed revision 8.
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>You will be prompted to edit the commit message file. A standard template
+  is automatically supplied for the commit. However, if you want to add extra
+  comment for the branch, please do so <strong>above</strong> the line that
+  says "<tt>--This line will be ignored and those below will be inserted
+  automatically--</tt>". Save your change and exit the editor.</p>
+
+  <p>Answer <span class="mono">&lt;Yes&gt;</span> when you are prompted to go
+  ahead and delete this branch.</p>
+
+  <p>Your working copy is now pointing to a branch that no longer exists at the
+  HEAD revision of the repository. If you want to try the tutorial again, you
+  may want to create another branch, and switch your working copy to point to
+  the new branch. Otherwise, you can remove your working copy by issuing a
+  careful <tt>rm -rf</tt> command.</p>
+
+  <h3><a name="tutorial_delete-final-comments">Final comments</a></h3>
+
+  <p>We have guided you through the basics of the complete change process,
+  using recommended ways of working. Most of the basic and important commands
+  have been covered by the tutorial. (The exceptions are <strong>fcm
+  log</strong> and <strong>fcm update</strong>,
+  which you may have to use regularly. For information on these commands, please
+  refer to the section on <a href=
+  "http://svnbook.red-bean.com/en/1.2/svn.tour.history.html#svn.tour.history.log">svn
+  log </a> and <a href=
+  "http://svnbook.red-bean.com/en/1.2/svn.tour.cycle.html#svn.tour.cycle.update">
+  Update Your Working Copy</a> in the <a href=
+  "http://svnbook.red-bean.com/en/1.2/">Subversion book</a>.) You should now be
+  in a position to continue with your development work with FCM. However, if at
+  any time you are unsure about any aspect of using FCM, please consult the
+  relevant section of the <a href="index.html">FCM User Guide</a>.</p>
+
+  <p>Feel free to use the tutorial, at any time, for testing out any aspect of
+  the system. You may wish to do this rather than use your own repository and
+  ticket system, to avoid cluttering them with unwanted junk.</p>
+  
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/user_guide/index.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/user_guide/index.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/user_guide/index.html	(revision 1665)
@@ -0,0 +1,465 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="FCM User Guide">
+  <meta name="keywords" content="FCM, user guide">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <p align="right"><img src="logo.png" alt="Met Office logo" width="85" height=
+  "85"></p>
+
+  <h1>FCM System<br>
+  User Guide</h1>
+
+  <p align="center">Release: 1.2</p>
+
+  <p align="center">Last updated: 22 March 2007</p>
+
+  <p align="center">Met Office<br>
+  FitzRoy Road, Exeter<br>
+  Devon, EX1 3PB<br>
+  United Kingdom</p>
+
+  <p align="center">&copy; Crown copyright 2005-7. All rights reserved.</p>
+
+  <p align="center">Questions regarding this document or permissions to quote
+  from it should be directed to the <a href=
+  "mailto:iprmanager@metoffice.gov.uk">IPR Manager</a>.</p>
+  
+  <script type="text/javascript">
+  <!--
+  var out = 'For printing, please use the '
+  out    += '<a href="fcm-user-guide.pdf">PDF<\/a> version of the document.'
+  document.write ('<p align="center">')
+  document.write (out)
+  document.write ('<\/p>')
+  //-->
+  </script>
+
+  <h2 align="center">Contents</h2>
+
+  <ol>
+    <li><a href="introduction.html">Introduction</a></li>
+
+    <li><a href="overview.html">System Overview</a></li>
+
+    <li>
+      <a href="getting_started.html">Getting Started</a>
+
+      <ul>
+        <li><a href="getting_started.html#setup">How to set yourself up to run
+        FCM</a></li>
+
+        <li><a href="getting_started.html#tutorial">Tutorial</a></li>
+      </ul>
+    </li>
+
+    <li>
+      <a href="code_management.html">Code Management System</a>
+
+      <ul>
+        <li>
+          <a href="code_management.html#svn">Using Subversion</a>
+
+          <ul>
+            <li><a href="code_management.html#svn_concepts">Basic
+            Concepts</a></li>
+
+            <li>
+              <a href="code_management.html#svn_basic">Basic Command Line
+              Usage</a>
+
+              <ul>
+                <li><a href=
+                "code_management.html#svn_basic_keywords">URL &amp;
+                Revision Keywords</a></li>
+
+                <li><a href="code_management.html#svn_basic_diff">Examining
+                Changes</a></li>
+
+                <li><a href=
+                "code_management.html#svn_basic_conflicts">Resolving
+                Conflicts</a></li>
+
+                <li><a href="code_management.html#svn_basic_check">Adding and
+                Removing Files</a></li>
+
+                <li><a href="code_management.html#svn_basic_commit">Committing
+                Changes</a></li>
+              </ul>
+            </li>
+
+            <li>
+              <a href="code_management.html#svn_branching">Branching &amp;
+              Merging</a>
+
+              <ul>
+                <li><a href=
+                "code_management.html#svn_branching_create">Creating
+                Branches</a></li>
+
+                <li><a href="code_management.html#svn_branching_list">Listing
+                Branches Created by You or Other Users</a></li>
+
+                <li><a href="code_management.html#svn_branching_info">Getting
+                Information About Branches</a></li>
+
+                <li><a href=
+                "code_management.html#svn_branching_switch">Switching your
+                working copy to point to another branch</a></li>
+
+                <li><a href=
+                "code_management.html#svn_branching_delete">Deleting
+                Branches</a></li>
+
+                <li><a href=
+                "code_management.html#svn_branching_merge">Merging</a></li>
+              </ul>
+            </li>
+
+            <li>
+              <a href="code_management.html#svn_gui">Using the GUI</a>
+
+              <ul>
+                <li><a href="code_management.html#svn_gui_start">Starting the
+                GUI</a></li>
+
+                <li><a href="code_management.html#svn_gui_commands">GUI
+                Commands</a></li>
+
+                <li><a href="code_management.html#svn_gui_konqueror">Accessing
+                the GUI from Konqueror</a></li>
+              </ul>
+            </li>
+
+            <li><a href="code_management.html#svn_problems">Known Problems with
+            Subversion</a></li>
+          </ul>
+        </li>
+
+        <li>
+          <a href="code_management.html#trac">Using Trac</a>
+
+          <ul>
+            <li><a href="code_management.html#trac_login">Logging In</a></li>
+
+            <li><a href="code_management.html#trac_wiki">Using the Wiki
+            Pages</a></li>
+
+            <li><a href="code_management.html#trac_browser">Using the
+            Repository Browser</a></li>
+
+            <li><a href="code_management.html#trac_tickets">Using the Issue
+            Tracker</a></li>
+
+            <li><a href="code_management.html#trac_roadmap">Using the
+            Roadmap</a></li>
+
+            <li><a href="code_management.html#trac_timeline">Using the
+            Timeline</a></li>
+          </ul>
+        </li>
+      </ul>
+    </li>
+
+    <li>
+      <a href="working_practices.html">Code Management Working Practices</a>
+
+      <ul>
+        <li><a href="working_practices.html#changes">Making Changes</a></li>
+
+        <li><a href="working_practices.html#wc">Working Copies</a></li>
+
+        <li>
+          <a href="working_practices.html#branching">Branching &amp;
+          Merging</a>
+
+          <ul>
+            <li><a href="working_practices.html#branching_when">When to
+            Branch</a></li>
+
+            <li><a href="working_practices.html#branching_where">Where to
+            Branch From</a></li>
+
+            <li><a href="working_practices.html#branching_update">Merging From
+            the Trunk</a></li>
+
+            <li><a href="working_practices.html#branching_commit">Merging Back
+            to the Trunk</a></li>
+
+            <li><a href="working_practices.html#branching_delete">When to
+            Delete Branches</a></li>
+          </ul>
+        </li>
+
+        <li><a href="working_practices.html#binary">Working with Binary Files</a>
+
+          <ul>
+            <li><a href="working_practices.html#binary_conflicts">Resolving
+            Conflicts in Binary Files</a></li>
+
+            <li><a href="working_practices.html#binary_locking">Using
+            Locking</a></li>
+          </ul>
+        </li>
+
+        <li><a href="working_practices.html#messages">Commit Log
+        Messages</a></li>
+
+        <li>
+          <a href="working_practices.html#tickets">Trac Tickets</a>
+
+          <ul>
+            <li><a href="working_practices.html#tickets_create">Creating
+            Tickets</a></li>
+
+            <li><a href="working_practices.html#tickets_use">Using
+            Tickets</a></li>
+          </ul>
+        </li>
+
+        <li><a href="working_practices.html#packages">Creating
+        Packages</a></li>
+
+        <li><a href="working_practices.html#releases">Preparing System
+        Releases</a></li>
+
+        <li><a href="working_practices.html#rapid">Rapid vs Staged Development
+        Practises</a></li>
+      </ul>
+    </li>
+
+    <li>
+      <a href="extract.html">The Extract System</a>
+
+      <ul>
+        <li><a href="extract.html#command">The Extract Command</a></li>
+
+        <li>
+          <a href="extract.html#simple">Simple Usage</a>
+
+          <ul>
+            <li><a href="extract.html#simple_local">Extract from a local
+            path</a></li>
+
+            <li><a href="extract.html#simple_url">Extract from a Subversion
+            URL</a></li>
+
+            <li><a href="extract.html#simple_mirror">Mirror code to a remote
+            machine</a></li>
+          </ul>
+        </li>
+
+        <li>
+          <a href="extract.html#advanced">Advanced Usage</a>
+
+          <ul>
+            <li><a href="extract.html#advanced_multi">Extract from multiple
+            repositories</a></li>
+
+            <li><a href="extract.html#advanced_branches">Extract from multiple
+            branches</a></li>
+
+            <li><a href="extract.html#advanced_incremental">Incremental extract
+            based on a previous extraction</a></li>
+
+            <li><a href="extract.html#advanced_build">Extract - Build
+            Configuration</a></li>
+          </ul>
+        </li>
+
+        <li><a href="extract.html#verbose">Diagnostic verbose level</a></li>
+
+        <li><a href="extract.html#nosvn">When Subversion Is Not
+        Available</a></li>
+      </ul>
+    </li>
+
+    <li>
+      <a href="build.html">The Build System</a>
+
+      <ul>
+        <li><a href="build.html#command">The Build Command</a></li>
+
+        <li>
+          <a href="build.html#basic">Basic Features</a>
+
+          <ul>
+            <li><a href="build.html#basic_build">Basic build
+            configuration</a></li>
+
+            <li><a href="build.html#basic_extract">Build configuration via the
+            extract system</a></li>
+
+            <li><a href="build.html#basic_exename">Naming of executables</a></li>
+
+            <li><a href="build.html#basic_flags">Setting the compiler
+            flags</a></li>
+
+            <li><a href="build.html#basic_interface">Automatic Fortran 9X
+            interface block</a></li>
+
+            <li><a href="build.html#basic_dependency">Automatic
+            dependency</a></li>
+          </ul>
+        </li>
+
+        <li>
+          <a href="build.html#advanced">Advanced Features</a>
+
+          <ul>
+            <li><a href="build.html#advanced_dependency">Further dependency
+            features</a></li>
+
+            <li><a href="build.html#advanced_blockdata">Linking a Fortran
+            executable with a BLOCKDATA program unit</a></li>
+
+            <li><a href="build.html#advanced_library">Creating library
+            archives</a></li>
+
+            <li><a href="build.html#advanced_pp">Pre-processing</a></li>
+
+            <li><a href="build.html#advanced_file-type">File type</a></li>
+
+            <li><a href="build.html#advanced_incremental">Incremental build
+            based on a pre-compiled build</a></li>
+
+            <li><a href="build.html#advanced_pckcfg">Using a package
+            configuration file</a></li>
+
+            <li><a href="build.html#advanced_data">Building data files</a></li>
+          </ul>
+        </li>
+
+        <li><a href="build.html#verbose">Diagnostic verbose level</a></li>
+
+        <li><a href="build.html#overview">Overview of the build
+        process</a></li>
+      </ul>
+    </li>
+
+    <li>
+      <a href="system_admin.html">System Administration</a>
+
+      <ul>
+        <li>
+          <a href="system_admin.html#svn">Subversion</a>
+
+          <ul>
+            <li><a href="system_admin.html#svn_design">Repository
+            design</a></li>
+
+            <li><a href="system_admin.html#svn_create">Creating a
+            repository</a></li>
+
+            <li><a href="system_admin.html#svn_access">Access control</a></li>
+
+            <li><a href="system_admin.html#svn_hosting">Repository
+	    hosting</a></li>
+
+            <li><a href="system_admin.html#svn_watch">Watching changes in log
+            messages</a></li>
+          </ul>
+        </li>
+
+        <li>
+          <a href="system_admin.html#trac">Trac</a>
+
+          <ul>
+            <li><a href="system_admin.html#trac_config">Trac
+            configuration</a></li>
+
+            <li><a href="system_admin.html#trac_hosting">Trac hosting</a></li>
+          </ul>
+        </li>
+
+        <li><a href="system_admin.html#fcm-keywords">FCM keywords</a></li>
+
+        <li><a href="system_admin.html#ext-bld-cfg">Extract and build
+        configuration</a></li>
+
+        <li><a href="system_admin.html#alternate_versions">Maintaining
+        alternate versions of namelists and data files</a></li>
+
+        <li><a href="system_admin.html#work-practise">Defining working
+        practises and policies</a></li>
+
+      </ul>
+    </li>
+
+    <li>
+      <a href="command_ref.html">FCM Command Reference</a>
+
+      <ul>
+        <li><a href="command_ref.html#fcm_config">fcm Configuration
+        File</a></li>
+
+        <li><a href="command_ref.html#fcm_bld">fcm build</a></li>
+
+        <li><a href="command_ref.html#fcm_ext">fcm extract</a></li>
+
+        <li><a href="command_ref.html#fcm_cmp-ext-cfg">fcm cmp-ext-cfg</a></li>
+
+        <li><a href="command_ref.html#fcm_gui">fcm gui</a></li>
+
+        <li>
+          <a href="command_ref.html#fcm_svn">fcm Subversion Subcommands</a>
+
+          <ul>
+            <li><a href="command_ref.html#fcm_svn_add">fcm add</a></li>
+
+            <li><a href="command_ref.html#fcm_svn_br">fcm branch</a></li>
+
+            <li><a href="command_ref.html#fcm_svn_ci">fcm commit</a></li>
+
+            <li><a href="command_ref.html#fcm_svn_cf">fcm conflicts</a></li>
+
+            <li><a href="command_ref.html#fcm_svn_rm">fcm delete</a></li>
+
+            <li><a href="command_ref.html#fcm_svn_diff">fcm diff</a></li>
+
+            <li><a href="command_ref.html#fcm_svn_merge">fcm merge</a></li>
+
+            <li><a href="command_ref.html#fcm_svn_mkpatch">fcm mkpatch</a></li>
+
+            <li><a href="command_ref.html#fcm_svn_switch">fcm switch</a></li>
+
+            <li><a href="command_ref.html#fcm_svn_trac">fcm trac</a></li>
+
+            <li><a href="command_ref.html#fcm_svn_other">Other Subversion
+            Commands</a></li>
+          </ul>
+        </li>
+      </ul>
+    </li>
+
+    <li><a href="further_info.html">Further Information</a></li>
+  </ol>
+
+  <p>Annex:</p>
+
+  <ul>
+    <li><a href="annex_quick_ref.html">Quick reference</a></li>
+
+    <li><a href="annex_fcm_cfg.html">Declarations in FCM central/user
+    configuration file</a></li>
+
+    <li><a href="annex_ext_cfg.html">Declarations in FCM extract configuration
+    file</a></li>
+
+    <li><a href="annex_bld_cfg.html">Declarations in FCM build configuration
+    file</a></li>
+
+    <li><a href="annex_pck_cfg.html">Declarations in FCM build package
+    configuration file</a></li>
+  </ul>
+  
+  <script type="text/javascript" src="maintain.js"></script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/user_guide/introduction.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/user_guide/introduction.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/user_guide/introduction.html	(revision 1665)
@@ -0,0 +1,83 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide: Introduction</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide - Introduction">
+  <meta name="keywords" content="FCM, user guide">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; Introduction
+  </address>
+
+  <h1>Introduction</h1>
+
+  <p>This is the User Guide for the <em>Flexible Configuration Management</em>
+  system which is known as <em>FCM</em>. It is designed to tell you everything
+  you need to know if you want to develop code which has been configured within
+  FCM. In addition it also provides the extra information you will need if you
+  are system manager of a project within FCM.</p>
+
+  <p>Note: some hyperlinks in this document lead to pages that are internal to
+  the Met Office, and so will generally not work when this document is viewed
+  externally. Please accept our apologies if this causes you any
+  inconvenience.</p>
+
+  <p>This guide consists of the following sections:</p>
+
+  <ul>
+    <li><a href="overview.html">System Overview</a>: A brief description of the
+    main features of FCM.</li>
+
+    <li><a href="getting_started.html">Getting Started</a>: How to start using
+    FCM. It includes a tutorial for you to work through and
+    familiarise yourself with some FCM activities.</li>
+
+    <li><a href="code_management.html">Code Management System</a>: How to use
+    the code management system to manage code changes.</li>
+
+    <li><a href="working_practices.html">Code Management Working Practices</a>:
+    Recommended ways of working with the code management system.</li>
+
+    <li><a href="extract.html">The Extract System</a>: How to extract code from
+    the repository ready for building.</li>
+
+    <li><a href="build.html">The Build System</a>: How to compile code using
+    the build system.</li>
+
+    <li><a href="system_admin.html">System Administration</a>: How to configure
+    and maintain a new system within FCM.</li>
+
+    <li><a href="command_ref.html">FCM Command Reference</a>: Detailed
+    information about each of the <em>fcm</em> commands.</li>
+
+    <li><a href="further_info.html">Further Information</a>: Where to find
+    further information about FCM and about configuration management in
+    general.</li>
+
+    <li>Annex: <a href="annex_quick_ref.html">Quick reference</a>: A quick
+    reference to many useful FCM code management system commands.</li>
+
+    <li>Annex: Detailed definitions of what declarations are allowed in the
+    following configuration files:
+
+      <ul>
+        <li><a href="annex_fcm_cfg.html">central/user</a></li>
+
+        <li><a href="annex_ext_cfg.html">extract</a></li>
+
+        <li><a href="annex_bld_cfg.html">build</a></li>
+
+        <li><a href="annex_pck_cfg.html">build package</a></li>
+      </ul>
+    </li>
+  </ul>
+
+  <script type="text/javascript" src="maintain.js"></script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/user_guide/logo.png
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/user_guide/logo.png	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/user_guide/logo.png	(revision 1665)
@@ -0,0 +1,1 @@
+link ../etc/logo.png
Index: LMDZ5/branches/testing/tools/fcm/doc/user_guide/maintain.js
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/user_guide/maintain.js	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/user_guide/maintain.js	(revision 1665)
@@ -0,0 +1,1 @@
+link ../etc/maintain.js
Index: LMDZ5/branches/testing/tools/fcm/doc/user_guide/overview.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/user_guide/overview.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/user_guide/overview.html	(revision 1665)
@@ -0,0 +1,192 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide: System Overview</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide - System Overview">
+  <meta name="keywords" content="FCM, user guide">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; System Overview
+  </address>
+
+  <h1>System Overview</h1>
+
+  <p>The FCM system is designed to simplify the task of managing and building
+  source code. It consists of three main components.</p>
+
+  <ul>
+    <li>Code Management (CM) System
+
+      <ul>
+        <li>This system provides facilities for making changes to source code in
+        a controlled and straightforward manner.</li>
+
+	<li>Version control is provided by the open source tool
+        <a href="http://subversion.tigris.org/"><em>Subversion</em></a>. The
+        source code and its history are stored in a central database which is
+        called the repository. Support for parallel working is provided through
+        the use of branches.</li>
+
+	<li>The open source web-based tool <a href="http://trac.edgewall.org/">
+        <em>Trac</em></a> allows changes to be examined and documented. It
+        provides an integrated issue tracker, wiki and repository browser.</li>
+      </ul>
+    </li>
+
+    <li>Build System
+
+      <ul>
+        <li>This system allows source code to be compiled with a minimal amount
+        of configuration. Compilation time can be minimised through the use of
+        pre-compiled code and by using the parallel make facilities provided by
+        the open source tool <a href="http://www.gnu.org/software/make/"><em>GNU
+        Make</em></a>.</li>
+
+        <li>It provides a number of powerful features aimed primarily at building
+        Fortran 9x code.</li>
+      </ul>
+    </li>
+
+    <li>Extract System
+
+      <ul>
+        <li>This system provides the interface between the CM and build systems.
+        Code is extracted and presented in a suitable form for the build system.
+	Code can be mirrored to a different build platform if necessary.</li>
+      </ul>
+    </li>
+  </ul>
+
+  <p>The diagram below illustrates how these components fit together.</p>
+
+  <p class="image"><img src="fcm_overview.png" alt="FCM system overview"></p>
+
+  <p>The following sections discuss these components in more detail.</p>
+
+  <h2>Code Management System</h2>
+
+  <p>The CM system is built using a number of open source tools, in particular
+  <em>Subversion</em> and <em>Trac</em>.</p>
+
+  <p><em>Subversion</em> is a modern version control tool with a large and
+  rapidly expanding user base. For a summary of its main features please refer
+  to chapter 1 of the book
+  <a href="http://svnbook.red-bean.com/en/1.2/svn.intro.html">Version Control
+  with Subversion</a>.</p>
+
+  <p>Subversion is a generalised tool which can be used in lots of different
+  ways. This makes some day-to-day tasks more complex than they need be. FCM
+  defines a simplified process and appropriate naming conventions. It then adds
+  a layer on top of Subversion to provide a natural interface which is
+  specifically tailored to this process. Where appropriate it simply makes use of
+  the command line tools provided by Subversion. However, in other cases it
+  provides significant additional functionality, for example:</p>
+
+  <ul>
+    <li>By making some assumptions about the repository layout (i.e. by
+    imposing a standard working practise) FCM simplifies the task of
+    creating branches and enforces a standard branch naming convention.</li>
+
+    <li>Having defined working practises and standard log messages allows FCM to
+    greatly simplify the process of merging changes between branches.</li>
+
+    <li>FCM makes use of <a href="http://furius.ca/xxdiff/"><em>xxdiff</em></a>
+    (a graphical merge tool) to simplify the process of resolving any conflicts
+    which result from a merge.</li>
+
+    <li>Code changes can be examined in graphical form using <em>xxdiff</em>.
+    FCM also allows you to easily examine the changes made on a branch.</li>
+
+    <li>FCM allows you to check where any particular branch has been used and
+    which version is being used.</li>
+  </ul>
+
+  <p>FCM also provides a simple GUI which allows easy access to most of the
+  common commands which you will need.</p>
+
+  <p><em>Trac</em> is the other main component of the CM system. It is a
+  powerful web based tool which helps you to manage your software project. It
+  includes the following features:</p>
+
+  <ul>
+    <li>A flexible issue tracker which can be used to keep track of bugs, feature
+    requests, etc. Each issue (known as a "ticket" within Trac) can be given a
+    priority and assigned to a particular person. Changes made to your Subversion
+    repository can easily be traced to the relevant ticket. Where appropriate,
+    tickets can be used to record information about who has reviewed each change.
+    </li>
+
+    <li>A roadmap feature which helps you to plan and manage project releases.
+    Each ticket can be associated with a particular milestone. Trac can then
+    easily show you what features or fixes went into a particular release or
+    what work remains before a particular milestone is reached.</li>
+
+    <li>A "wiki" which can be used for project documentation.</li>
+
+    <li>A browser for viewing your Subversion repository which allows you to
+    browse the project tree / files and examine revision logs and changesets.
+    </li>
+
+    <li>A timeline view which summarises all the activity on a project (changes
+    to the tickets, wiki pages or the Subversion repository).</li>
+  </ul>
+
+  <h2>Build System</h2>
+
+  <p>The build system provides the following features:</p>
+
+  <ul>
+    <li>Automatic generation of Makefile's at build time based on a simple
+    configuration file.</li>
+
+    <li>Full dependency analysis at build time.</li>
+
+    <li>Automatic generation of Fortran 9x interface files at build time.</li>
+
+    <li>Support for non-standard source code. You can override automatic
+    dependency and compile rules in order to deal with code which does not
+    conform to the necessary coding standards.</li>
+
+    <li>Flexible control over compiler flags. Changes to compiler flags trigger
+    the appropriate re-compilation.</li>
+
+    <li>Support for Pre-processor directives. Changes to Pre-processor flags
+    trigger the appropriate re-compilation.</li>
+
+    <li>Support for pre-compiled object code to speed compilation time.</li>
+
+    <li><em>GNU make</em> is used to perform the build. Build times on
+    multi-processor systems can be reduced using <em>parallel make</em>.</li>
+  </ul>
+
+  <h2>Extract System</h2>
+
+  <p>The extract system provides the following features:</p>
+
+  <ul>
+    <li>Extraction of code to a directory tree suitable for feeding into the
+    build system. Code can be combined from multiple repositories and branches.
+    Local user code can also be included.</li>
+
+    <li>Either a complete set of source code may be extracted or just a set of
+    changes relative to pre-compiled code.</li>
+
+    <li>A simple configuration file defines what code is required (and what
+    compile options are required). Typically, standard versions of these
+    configuration files are maintained within the repository. Users can then
+    define changes relative to these standard versions.</li>
+
+    <li>If necessary, code can be transferred to a different platform ready for
+    building.</li>
+  </ul>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/user_guide/style.css
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/user_guide/style.css	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/user_guide/style.css	(revision 1665)
@@ -0,0 +1,128 @@
+/* New stylesheet for FCM - created by Jim Bolton, 18 April 2005
+   Needs to be reviewed. */
+
+@media screen {
+  body {
+    background-color: #ffffcc;
+    color: black;
+    font-family: Arial, Helvetica, sans-serif;
+    font-size: 12pt;
+  }
+}
+@media print {
+  body {
+    color: black;
+    font-family: Arial, Helvetica, sans-serif;
+    font-size: 12pt;
+  }
+}
+h1 {
+  background-color: #ccccff;
+  color: navy;
+  font-size: 200%;
+  font-weight: bold;
+  text-align: center;
+  padding: 20px;
+}
+h2 {
+  background-color: #ccccff;
+  color: navy;
+  font-size: 175%;
+  font-weight: bold;
+  padding: 15px;
+}
+h3 {
+  background-color: #ccccff;
+  color: #40668c;
+  font-size: 150%;
+  font-weight: bold;
+  padding: 10px;
+}
+h4 {
+  color: #40668c;
+  font-size: medium;
+  font-weight: bold;
+}
+h5 {
+  background-color: #ccccff;
+  color: #40668c;
+  font-size: medium;
+  font-weight: bold;
+}
+table {
+  margin-top: 5px;
+  margin-bottom: 10px;
+}
+
+th {
+  background-color: #ccccff;
+}
+
+td {
+  background-color: transparent;
+}
+
+li {
+  padding: 5px;
+}
+
+img {
+  margin: 5px;
+}
+
+:link {
+  color: blue;
+  text-decoration: underline;
+}
+
+:visited {
+  color: purple;
+  text-decoration: none;
+}
+
+:active, :hover {
+  color: blue;
+  text-decoration: underline;
+}
+
+address {
+  text-align: right;
+  font-size: small;
+  font-style: normal;
+}
+
+code {
+  font-family: "Courier New", Courier, monospace;
+}
+
+pre {
+  background-color: #ffffcc;
+  font-family: "Courier New", Courier, monospace;
+  padding: 10px;
+}
+
+.yell {
+  background-color: #ffffcc;
+  padding: 5px;
+}
+
+.yell td {
+  background-color: transparent;
+}
+
+.image {
+  text-align: center;
+  font-weight: bold;
+}
+
+.gray {
+  color: gray;
+}
+
+.mono {
+  font-family: "Courier New", Courier, monospace;
+}
+
+.pad th, .pad td {
+  padding: 5px;
+}
Index: LMDZ5/branches/testing/tools/fcm/doc/user_guide/style.html2ps.css
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/user_guide/style.html2ps.css	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/user_guide/style.html2ps.css	(revision 1665)
@@ -0,0 +1,1 @@
+link ../etc/style.html2ps.css
Index: LMDZ5/branches/testing/tools/fcm/doc/user_guide/system_admin.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/user_guide/system_admin.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/user_guide/system_admin.html	(revision 1665)
@@ -0,0 +1,558 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide: System Administration</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide - System Administration">
+  <meta name="keywords" content="FCM, user guide">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; System Administration
+  </address>
+
+  <h1>System Administration</h1>
+
+  <p>This chapter provides an administration guide for managers of projects or
+  systems which are using FCM.</p>
+
+  <p>Note that, where this section refers to the "FCM team" this applies only to
+  Met Office users. External users will either need to refer to the equivalent
+  team within their organisation or will need to perfom these tasks themselves.
+  </p>
+
+  <h2><a name="svn">Subversion</a></h2>
+
+  <h3><a name="svn_design">Repository design</a></h3>
+
+  <p>The FCM system assumes that each project directory has sub-directories called
+  <em>trunk</em>, <em>branches</em> and <em>tags</em> (Subversion recommends it but
+  doesn't insist on it). We recommend that each project within a Subversion
+  repository is in a sub-directory of the repository root.</p>
+      <pre>
+&lt;root&gt;
+    |
+    |-- &lt;project 1&gt;
+    |       |
+    |       |-- trunk
+    |       |-- branches
+    |       |-- tags
+    |
+    |-- &lt;project 2&gt;
+    |       |
+    |       |-- trunk
+    |       |-- branches
+    |       |-- tags
+    |
+    |-- ...
+</pre>
+  <p>In theory you could also have the project as the root directory or several levels
+  below the root directory. However, this is not tested and could cause problems with
+  some <tt>fcm</tt> commands so is best avoided.</p>
+
+  <p>You will need to decide whether to use a single project tree for your system or
+  whether to use multiple projects.</p>
+
+  <p>Advantages of a single project tree:</p>
+
+  <ul>
+    <li>Changes to any part of the system can always be committed as a single logical
+    changeset. If you split your system into multiple projects then you may have
+    occasions when a logical change involves more than one project and hence requires
+    multiple commits (and branches).</li>
+  </ul>
+
+  <p>Disadvantages of a single project tree:</p>
+
+  <ul>
+    <li>If you have a large system then your working copies may become very large
+    and unwieldy. Basic commands such as <tt>checkout</tt> and <tt>status</tt>
+    can become frustratingly slow if your working copy is too large.</li>
+        
+    <li>Depending on how you work, you may end up doing lots more merges of files
+    that are unrelated to your work.</li>
+  </ul>
+
+  <p>One common approach is to split the admin type files (things that only the
+  system manager should need to touch) into a separate project from the core
+  system files (which all the developers need access to). If you include any
+  large data files under version control you may also want to use a separate
+  project for them to avoid making your working copies very large when editing
+  code.</p>
+  
+  <p>Note that there is often no obvious right or wrong answer so you just have
+  to make a decision and see how it works out. You can always re-arrange your
+  repository in the future (although be aware that this will break any changes
+  being prepared on branches at the time).</p>
+
+  <p>You also need to decide whether your system requires its own repository (or
+  multiple repositories) or whether it can share with another system.</p>
+  
+  <ul>
+    <li>The main disadvantage of having separate repositories for each system is
+    the maintenance overhead (although this is almost all automated by the FCM
+    team so is not a big deal).</li>
+        
+    <li>We normally configure a single Trac system per repository. If the
+    repository contains multiple systems then it makes it difficult to use the
+    Trac milestones to handle system releases. However, Trac now supports
+    restricting itself to a sub-directory within a repository so, again, this is
+    not a big deal.</li>
+        
+    <li>If you share a repository with other systems then your revision numbers
+    can increase even when there are no changes to your system. This doesn't
+    matter but some people don't like it.</li>
+  </ul>
+  
+  <p>For simplicity, in most cases you will probably want your own repository for
+  your system.</p>
+
+  <p>You will not normally want to have multiple repositories for a system. One
+  exception may be if you are storing large data files where you might not want
+  to keep all the old versions for ever. Removing old versions can't be done
+  without changing all the revision numbers which would mess up all your code
+  history and Trac tickets. Storing the large data files in a separate
+  repository reduces the impact if you do decide to remove old versions in the
+  future. One disadvantage of this approach is that, for the moment at least,
+  Trac only handles one repository so you will need a separate Trac system for
+  the data files.</p>
+
+  <p>For further details please see the section
+  <a href="http://svnbook.red-bean.com/en/1.2/svn.reposadmin.projects.html#svn.reposadmin.projects.chooselayout">
+  Choosing a Repository Layout</a> from the Subversion book.</p>
+
+  <h3><a name="svn_create">Creating a repository</a></h3>
+
+  <p>Normally the FCM team will help you to set up your initial repository.
+  However, it is quite simple if you need to do it yourself. First you need to
+  issue the command <tt>svnadmin create /path/to/repos</tt>. This creates an
+  empty repository which is now ready to accept an initial import. To do so,
+  you should create a directory tree in a suitable location, and issue the
+  <tt>svn import</tt> command. At the top level of your directory tree should be
+  the project directories. Each project should then contain three directories
+  "trunk", "branches" and "tags". The directories "branches" and "tags" should be
+  empty.  The directory "trunk" should contain your source files in a directory
+  structure you have chosen.  For example, if your directory tree is located
+  at "$HOME/foo", you will do the following to import it to a new repository:</p>
+
+  <table class="pad" summary="creating a repository and importing a project tree" border="1" width="100%">
+    <tr>
+      <th>Creating a repository and importing a project tree</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ svnadmin create FOO_svn
+(SHELL PROMPT)$ svn import $HOME/foo file://$PWD/FOO_svn -m 'Initial import'
+Adding         FOO
+Adding         FOO/trunk
+Adding         FOO/trunk/doc
+Adding         FOO/trunk/doc/hello.html
+Adding         FOO/trunk/doc/world.html
+Adding         FOO/trunk/src
+Adding         FOO/trunk/src/bar
+Adding         FOO/trunk/src/bar/egg.f90
+Adding         FOO/trunk/src/bar/ham.f90
+Adding         FOO/branches
+Adding         FOO/tags
+
+Committed revision 1.
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Note that the <tt>svnadmin</tt> command takes a PATH as an argument, as
+  opposed to a URL for the <tt>svn</tt> command.</p>
+
+  <p>For further details please see the section
+  <a href="http://svnbook.red-bean.com/en/1.2/svn.reposadmin.projects.html#svn.reposadmin.projects.import">
+  Creating the Layout, and Importing Initial Data</a> from the Subversion book.</p>  
+
+  <h3><a name="svn_access">Access control</a></h3>
+
+  <p>You will not normally want to allow anonymous write access to your repository
+  since this means that changes do not get identified with a userid. Therefore
+  system managers need to provide the FCM team with a list of users who should
+  have write access to their repositories. You may also want to arrange passwords
+  for these users although this is only necessary if you need to prevent
+  malicious access. Further restrictions such as preventing anonymous read access
+  or restricting write access to the trunk to a limited set of users can be
+  arranged if necessary.</p>
+
+  <h3><a name="svn_hosting">Repository hosting</a></h3>
+
+  <p>The FCM team will organise the hosting of your repository. A number of
+  facilities will be set up for you as standard.</p>
+  
+  <ul>
+    <li>Your repository will be set up on a central FCM server and access will be
+    provided via <em>svnserve</em> (which we use in preference to <em>Apache</em>
+    for performance reasons). The FCM team will advise you of the URL.</li>
+        
+    <li>Each night a full backup of your repository will be taken. An integrity
+    check will also be performed using the <tt>svnadmin verify</tt> command.</li>
+        
+    <li>Standard hook scripts will be set up to handle the following post-commit
+    tasks:
+
+      <ul>
+        <li>Each time a changeset is successfully committed an incremental dump
+        of the new revision is taken. This would allow the repository to be
+        recovered should the live repository become corrupted for whatever
+        reason.</li>
+            
+        <li>A file is updated which records the latest revision of your
+        repository. This can be used by system managers to regularly check for
+        new commits in a cron job and perform any required actions (updating
+        files on a remote platform for instance). The FCM team can advise you
+        of the location of this file and show you some example scripts which
+        make use of it.</li>
+      </ul>
+    </li>
+
+    <li>Standard hook scripts will be set up to handle the following tasks for
+    changes in revision properties (pre-revprop-change/post-revprop-change):
+
+      <ul>
+        <li>If a user attempts to modify the log message of a changeset and
+        he/she is not the original author of the changeset, the
+        pre-revprop-change hook script will e-mail the original author. You can
+        also set up a watch facility to monitor changes of log messages that
+        affect particular paths in the repository. (See the <a href=
+        "#svn_watch">next sub-section</a> for details.)</li>
+
+        <li>The post-revprop-change hook script updates the Trac SQLite database
+        following a successful change in the log message.</li>
+      </ul>
+    </li>
+  </ul>
+
+  <p>Additional hook scripts can be put in place if you have a requirement. The
+  use of hook scripts is discussed in the section <a href=
+  "http://svnbook.red-bean.com/en/1.2/svn.reposadmin.create.html#svn.reposadmin.create.hooks">
+  Repository Creation and Configuration</a> from the Subversion book.</p>
+
+  <p>Note that if you want to use a Subversion repository for your own individual
+  use there is no need to get the FCM team to host it. You can simply create your
+  repository and then use a <tt>file://</tt> URL to access it.</p>
+
+  <h3><a name="svn_watch">Watching changes in log messages</a></h3>
+
+  <p>You can set up a watch facility to monitor changes in revision log messages
+  in your repository. An obvious use of this facility is for system managers to
+  monitor changes of log messages affecting the trunks of their projects. To set
+  up the facility, you will need to add a <tt>watch.cfg</tt> file to the root of
+  your repository. (To avoid checking out the whole repository, including every
+  branch, make sure that you checkout the root of your repository
+  non-recursively, i.e. <tt>fcm checkout -N URL</tt>.) The <tt>watch.cfg</tt>
+  file is an INI-type file, with the basic format:</p>
+
+  <pre>
+[repos_base]
+
+path/in/repos = list,of,watchers
+</pre>
+
+  <p>For example, if your repository is <tt>svn://fcm1/FCM_svn/</tt>, and you
+  want set up particular users to monitor changes of the log messages affecting
+  several areas within the repository, you may have something like this:</p>
+
+  <pre>
+[FCM_svn]
+
+FCM/trunk/src            = fred,bob
+FCM/trunk/doc            = fred,bob,alice
+FCM/branches/dev/*/*/src = fred
+</pre>
+
+  <p>Later on, if "dave" attempts to modify the log message of a changeset that
+  affects the path <tt>FCM/trunk/src</tt>, "fred" and "bob" will both be
+  notified by e-mail.</p>
+    
+  <h2><a name="trac">Trac</a></h2>
+
+  <h3><a name="trac_config">Trac configuration</a></h3>
+
+  <p>Normally the FCM team will set up your Trac system for you (using a script
+  which helps automate the configuration). This section describes some things you
+  may wish to be configured. This can be done when the Trac system is set up or
+  later if you are unsure what you will require at first.</p>
+
+  <h4><a name="trac_access">Access control</a></h4>
+
+  <p>You will not normally want to allow anonymous users to make changes to your
+  Trac system since this means that changes may not get identified with a userid.
+  The FCM team will set up your Trac system with accounts for all users who have
+  write access to your Subversion repository. You may also want to arrange
+  passwords for these users although this is only necessary if you need to prevent
+  malicious access. Further restrictions such as preventing anonymous read access
+  can be arranged if necessary.</p>
+
+  <p>An additional admin account will be set up for the system manager which will
+  be given TRAC_ADMIN privileges. This allows this account to do additional
+  things which normal users cannot do such as:</p>
+
+  <ul>
+    <li>Delete wiki pages (particular versions or the entire page).</li>
+        
+    <li>Add or modify milestones.</li>
+        
+    <li>Modify ticket descriptions and delete ticket attachments.</li>
+        
+    <li>Make wiki pages read-only.</li>
+  </ul>
+  
+  <p>We recommend that the system manager uses a normal account most of the time
+  and only uses their admin account when they require the additional privileges.
+  </p>
+
+  <p>For further details please see the section
+  <a href="http://projects.edgewall.com/trac/wiki/TracPermissions">
+  Trac Permissions</a> from the Trac documentation.</p>  
+
+  <h4><a name="trac_email">Email notification</a></h4>
+
+  <p>By default, each Trac system is configured such that the owner and reporter
+  and anyone on the "CC" list are notified whenever a change is made to a
+  ticket. If system mangers wish to be notified of all ticket changes then this
+  can also be configured. Alternatively, email notifications can be disabled if
+  they are not wanted.</p>
+
+  <h4><a name="trac_milestones">Milestones</a></h4>
+
+  <p>Milestones are useful for identifying when tickets need to be resolved.
+  Typically, milestones may be particular system releases or time periods. The
+  FCM team can configure milestones for you when they set up your Trac system.
+  However, this is not strictly necessary since milestones can be set up via the
+  web interface using the admin account (go to the <em>Roadmap</em> page).</p>
+
+  <h4><a name="trac_misc">Other configurable items</a></h4>
+
+  <p>There are lots of other things that can be configured in your Trac system
+  such as:</p>
+  
+  <ul>
+    <li>Components</li>
+        
+    <li>Versions</li>
+        
+    <li>Custom fields</li>
+        
+    <li>System icon</li>
+        
+    <li>Stylesheets</li>
+  </ul>
+
+  <p>For further details please see the sections
+  <a href="http://projects.edgewall.com/trac/wiki/TracIni">
+  The Trac Configuration File</a> and
+  <a href="http://projects.edgewall.com/trac/wiki/TracTickets">
+  The Trac Ticket System</a> from the Trac documentation.</p>  
+  
+  <h3><a name="trac_hosting">Trac hosting</a></h3>
+
+  <p>The FCM team will organise the hosting of your Trac system. It will be set
+  up on the same server that hosts your Subversion repository and access will be
+  provided via a web server. The FCM team will advise you of the URL. Each night
+  a backup of your Trac system will be taken in case the live system should
+  become corrupted for whatever reason.</p>
+  
+  <h2><a name="fcm-keywords">FCM keywords</a></h2>
+
+  <p>When you set up a repository for a new project, you will normally want the
+  FCM team to set up a set of URL keywords for it in the FCM central
+  configuration file. The name of the project should be a short string containing
+  only word characters. If your project is called "PROJ", the recommended set of
+  keywords are:</p>
+
+  <ul>
+    <li>fcm:proj - for the top level URL of the PROJ repository.</li>
+
+    <li>fcm:proj_tr - for the "trunk" sub-directory of PROJ repository.</li>
+
+    <li>fcm:proj_br - for the "branches" sub-directory of PROJ repository.</li>
+
+    <li>fcm:proj_tg - for the "tags" sub-directory of PROJ repository.</li>
+  </ul>
+
+  <p>If your project has an associated Trac browser, you should also declare the
+  Trac browser URL (that corresponds to the Subversion URL) in the central
+  configuration file. This allows FCM to associate the URL to the Trac browser
+  with a Subversion URL.</p>
+
+  <p>For more information on how to set up the keywords, please refer to <a
+  href="code_management.html#svn_basic_keywords">Repository &amp; Revision
+  Keywords</a> and the <a href="annex_fcm_cfg.html">Annex: Declarations in FCM
+  central/user configuration file</a>.</p>
+
+  <h2><a name="ext-bld-cfg">Extract and build configuration</a></h2>
+
+  <p>The extract and build systems are very flexibile and can be used in lots of
+  different ways. It is therefore difficult to give specific advice explaining
+  how to configure them. However, based on experience with a number of systems,
+  the following general advice can be offered.</p>
+
+  <ul>
+    <li>Standard extract configuration files should be defined and stored within
+    the repository. Users then include these files into their configurations,
+    before applying their local changes.</li>
+    <li>The files should be designed to include one another in a hierarchy. For
+    example, you may have one core file which defines all the repository and
+    source locations plus a series of platform/compiler specific files which
+    include the core file. More complex setups are also possible if you need to
+    cater for other options such as different optimisation levels, 32/64 bit,
+    etc.</li>
+    <li>When including other configuration files, always make use of the special
+    <tt>$HERE</tt> variable
+    (rather than, for instance, referring to a fixed repository location). When
+    your configuration file is parsed, this special variable is normally
+    expanded into the container directory of the current configuration file. This
+    means that the include statements should work correctly whether you are
+    referring to configuration files in the repository trunk, in a branch or in
+    a local working copy.</li>
+    <li>Make good use of user variables (e.g. <tt>%fred</tt>) to simplify
+    repetitive declarations and make your configuration files easier to
+    maintain.</li>
+    <li>Use continuation lines to split long lines and make them easier to read
+    (see the <a href="command_ref.html#fcm_config">FCM Command Reference</a>
+    section for further details about configuration files).</li>
+  </ul>
+
+  <p>Probably the best advice is to look at what has already been set up for
+  other systems. The FCM team can advise on the best systems to examine.</p>
+
+  <p>When you create a stable build you should keep an extract configuration file
+  that can reproduce the build. One easy way to do this is to create your build
+  using the standard configuration files and the latest versions of the code. You
+  can then save the expanded extract configuration file which is created when you
+  run the extraction. To help document your stable build you can use the command
+  <tt>fcm cmp-ext-cfg</tt> to show what has changed.</p>
+
+  <h2><a name="alternate_versions">Maintaining alternate versions of namelists
+  and data files</a></h2>
+
+  <p>Sometimes it is useful to be able to access particular revisions of some
+  directories from a FCM repository without having to go via Subversion. Typical
+  examples are namelist or data files used as inputs to a program. The script
+  <tt>fcm_update_version_dir.pl</tt> is designed to help with this. It can be
+  used to maintain a set of extracted version directories from a FCM repository.
+  The script has the following options and arguments:</p>
+
+  <ul>
+    <li>-f [--full]: specify the full mode, in which the versioned directories
+    of each specified item will be removed before being re-extracted.</li>
+
+    <li>-d [--dest] &lt;arg&gt;: specify a destination &lt;arg&gt; for the
+    extraction. If not specified, the current working directory will be used as
+    the base path.</li>
+
+    <li>-u [--url] &lt;arg&gt;: specify the source repository URL. This option
+    is compulsory.</li>
+  </ul>
+
+  <p>If an argument is specified, it must be the location of a configuration
+  file. Otherwise, the command reads its configuration from the standard input.
+  The configuration file is a line-based text file. Blank lines and lines
+  beginning with a "#" are ignored.</p>
+
+  <p>Each configuration line must contain the relative path of a sub-directory
+  under the specified source repository URL. If the path ends in "<tt>*</tt>"
+  then the path is expanded recursively and any sub-directories containing
+  regular files are added to the list of relative paths to extract.</p>
+
+  <p>Optionally, each relative path may be followed by a list of space separated
+  "conditions". Each condition is a conditional operator (&gt;, &gt;=, &lt;,
+  &lt;=, == or !=) followed by a revision number or the keyword HEAD.</p>
+
+  <p>The command uses the revision log to determine the revisions at which the
+  relative path has been updated in the source repository URL. If these
+  revisions also satisfy the "conditions" set by the user, they will be
+  considered in the extraction. In full mode, everything is re-extracted. In
+  incremental mode, the version directories are only updated if they do not
+  already exist.</p>
+
+  <p>Example:</p>
+
+  <table class="pad" summary="fcm_update_version_dir.pl example" border="1"
+  width="100%">
+    <tr>
+      <th>fcm_update_version_dir.pl example</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm_update_version_dir.pl -u fcm:ver_tr &lt;&lt;EOF
+namelists/VerNL_AreaDefinition   &gt;1000 !=1234
+namelists/VerNL_GRIBToPPCode     &gt;=600 &lt;3000
+namelists/VerNL_StationList      
+elements/*                       &gt;1000
+EOF
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>N.B.</p>
+
+  <ol>
+    <li>Each time a sub-directory is revised, the script assigns a sequential
+    "v" number for the item. Each "v" number for a sub-directory, therefore, is
+    associated with a revision number. For each extracted revision directory,
+    there is a corresponding "v" number symbolic link pointing to it.</li>
+
+    <li>The system also creates a symbolic link "latest" to point to the latest
+    extracted revision directory.</li>
+  </ol>
+
+  <h2><a name="work-practise">Defining working practises and policies</a></h2>
+
+  <p>Some options on working practises and policies are defined in the chapter
+  on <a href="working_practices.html">Code Management Working Practices</a>.
+  Individual projects should document the approach they have adopted. In
+  addition, each project may also need to define its own working practices and
+  policies to suit its local need. For example each project may need to
+  specify:</p>
+
+  <ul>
+    <li>Whether changes are allowed directly on the trunk or whether branches
+    have to be used in all cases.</li>
+
+    <li>Whether all users are allowed to make changes to the trunk.</li>
+
+    <li>Whether Trac tickets have to be raised for all changes to the trunk.</li>
+        
+    <li>Whether Trac tickets should be raised for all support queries or whether
+    a Trac ticket should only be raised once there is an agreed "issue".</li>
+
+    <li>Whether branches should normally be made from the latest code or from a
+    stable release.</li>
+
+    <li>Whether a user is allowed to resolve conflicts directly when merging a
+    branch into the trunk or whether he/she should merge the trunk into the
+    branch and resolve the conflicts in the branch first.</li>
+
+    <li>Whether all code changes to the trunk need to be reviewed.</li>
+
+    <li>What testing is required before changes can be merged to the trunk.</li>
+
+    <li>Whether history entries are maintained in source files or whether
+    individual source files changes need to be described in the Subversion log
+    message.</li>
+
+    <li>Branch deletion policy.</li>
+
+    <li>Whether any files in the project require locking before being changed.
+    </li>
+  </ul>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/doc/user_guide/working_practices.html
===================================================================
--- LMDZ5/branches/testing/tools/fcm/doc/user_guide/working_practices.html	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/doc/user_guide/working_practices.html	(revision 1665)
@@ -0,0 +1,825 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>FCM System User Guide: Working Practices</title>
+  <meta name="author" content="FCM development team">
+  <meta name="descriptions" content="User Guide - Working Practices">
+  <meta name="keywords" content="FCM, user guide">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+
+<body>
+  <address>
+    <a href="index.html">FCM System User Guide</a> &gt; Code Management
+    Working Practices
+  </address>
+
+  <h1>Code Management Working Practices</h1>
+
+  <p>The previous chapter described how to use the various parts of the FCM
+  code management system. They also described aspects of working practises
+  which are enforced by the system. This section discusses other recommended
+  working practises.  They are optional in the sense that you don't have to
+  follow them to use FCM.  It is a matter for individual projects to decide
+  which working practises to adopt (although we expect most projects/systems
+  at the Met Office to adopt similar practises).</p>
+
+  <h2><a name="changes">Making Changes</a></h2>
+
+  <p>This sub-section gives an overview of the recommended approach for
+  preparing changes. Particular topics are discussed in more detail
+  in later sub-sections where appropriate.</p>
+
+  <p>The recommended process for making a change is as follows:</p>
+
+  <ol>
+    <li>Before work starts on any coding you should make sure that
+	there is a Trac ticket open which explains the purpose of the change.
+	<ul>
+	  <li>Make sure that you set the ticket milestone to indicate
+	      which release of the system you are aiming to include
+	      your change in.
+	  <li>Accept the ticket to indicate that you are working on the change.
+	  <li>For further advice on using tickets see
+	      <a href="#tickets">Trac Tickets</a> later in this section.
+	</ul>
+    <li>Create a branch
+	<ul>
+	  <li>For very simple changes you may be happy to prepare your changes
+	      directly on the trunk. For further details see
+	      <a href="#branching_when">When to Branch</a> later in this section.
+	  <li>Create your branch either from the latest version or from a stable
+	      release (see <a href="#branching_where">Where to Branch From</a>
+	      later in this section).
+	</ul>
+    <li>Prepare your code changes on the branch
+	<ul>
+	  <li>Commit interim versions to your branch on a regular basis as you
+	      develop your change. This makes it much easier to keep track of
+	      what you're changing and to revert changes if necessary.
+	  <li>You may wish to merge in changes from the trunk. For further details see
+	      <a href="#branching_update">Merging From the Trunk</a> later in this section.
+	      <ul>
+		<li>Make sure that you always commit any local changes to your branch
+		    before doing a merge. Otherwise it becomes impossible to distinguish
+		    your changes from those you have merged in. It is also impossible to
+		    revert the merge without losing your local changes.
+		<li>Likewise, always commit the merge to your branch (after resolving any
+		    conflicts) before making any further changes.
+	      </ul>
+	  <li>Don't include unrelated changes. If you want to make some changes which
+	      aren't really associated with your other changes then use a separate ticket and
+	      branch for these changes.
+	</ul>
+    <li>Once your changes are ready for review, update the Trac ticket to record
+	which version of the branch is to be reviewed and assign the ticket to your reviewer.
+    <li>If the reviewer is happy with the change then he/she should update the ticket
+	to record that the change is approved and assign the ticket back to you.
+	<ul>
+	  <li>The reviewer can use the command
+	      <tt>fcm&nbsp;diff&nbsp;--branch &lt;branch_name&gt;</tt> to examine all of the
+	      changes on the branch.
+	  <li>If changes are necessary then these should be prepared and then the
+	      ticket updated to refer to the new version under review.
+	</ul>
+    <li>Once the change is approved it can be merged back to the trunk
+	<ul>
+	  <li>If you have been merging the latest changes from the trunk onto your
+	      branch then the merge should be automatic. If not you may have
+	      conflicts to resolve.
+	  <li>Make sure that each merge is a separate commit to the trunk.
+	      i.e. Don't combine changes from several branches in one commit.
+	      This makes it easier to reverse changes if necessary. It also
+	      makes the changeset easier to understand.
+	  <li>Make sure that you use a good log message to describe your change.
+	      For further details see <a href="#messages">Commit Log Messages</a>
+	      later in this section.	      
+	  <li>Once the changes are commited, update the ticket to refer to the
+	      changeset. Then the ticket can be closed.
+	</ul>
+    <li>Once you are finished with the branch it should be deleted.
+  </ol>
+
+  <h2><a name="wc">Working Copies</a></h2>
+
+  Some points to consider regarding working copies:
+
+  <ol>
+    <li>In general we recommend that you keep your working copies in your home directory.
+	This ensures that any local changes which you accidently delete can be recovered
+	via the snapshot facility (on Met Office Exeter and Reading based systems).
+    <li>If the size of your project is small then you will probably find it easiest to
+	work with a complete copy of the project (either the trunk or your branch).
+	This means that you always have immediate access to all the files and that you
+	are always able to perform merges using your normal working copy.
+    <li>If you have a large project then you may prefer to work on a sub-tree of your
+	project.
+	<ul>
+	  <li><em>Pros:</em>
+	      <ul>
+		<li>Subversion operations on your working copy are faster.
+		<li>Your working copies use up less disk space. Remember that
+		    you may be working on several changes at once on separate branches
+		    so you may wish to have several working copies.
+	      </ul>
+	  <li><em>Cons:</em>
+	      <ul>
+		<li>You cannot always perform merge operations in sub-trees (if
+		    the changes which need to be merged include files outside of
+		    your sub-tree). To handle this we suggest that if you need to
+		    perform a merge using a complete copy of your project you
+		    check it out in your $LOCALDATA area (local disk space which
+		    is not backed up) to be used purely for doing the merge.
+		<li>You may find that your change involves more files than you originally
+		    thought and that some of the files to be changed lie outside of your
+		    working copy. You then have to make sure that you have committed any
+		    changes before checking out a larger working copy.
+	      </ul>
+	</ul>
+
+  </ol>
+  
+  <h2><a name="branching">Branching &amp; Merging</a></h2>
+
+  <h3><a name="branching_when">When to Branch</a></h3>
+
+  <p>If you are making a reasonably large change which will take more than a
+  hour or two to prepare then there are clear advantages to doing this work on a
+  branch.</p>
+
+  <ul>
+    <li>You can commit intermediate versions to the branch.</li>
+
+    <li>If you need to merge in changes from the trunk then you have a record
+    of your files prior to the merge.</li>
+
+    <li>The version of the code which gets reviewed is recorded. If subsequent
+    changes are required then only those changes will need reviewing.</li>
+  </ul>
+
+  <p>However, if you are only making a small change (maybe only one line)
+  should you create a branch for this? There are two possible approaches:</p>
+
+  <ol>
+    <li>The <em>Always Branch</em> system
+
+      <ul>
+        <li>ALL coding changes are prepared on branches.</li>
+
+        <li><em>Pros:</em> Same process is followed in all cases.</li>
+
+        <li><em>Cons:</em> The extra work required to create the branch and
+        merge it back to the trunk may seem unnecessary for a very small
+        change.</li>
+      </ul>
+    </li>
+
+    <li>The <em>Branch When Needed</em> system
+
+      <ul>
+        <li>Small changes can be committed directly to the trunk (after testing
+        and code review).</li>
+
+        <li><em>Pros:</em> Avoids the overhead of using branches.</li>
+
+        <li><em>Cons:</em> Danger of underestimating the size of a change. What
+        you thought was a small change may turn out to be larger than you
+        thought (although you can always move it onto a branch if this
+        happens).</li>
+      </ul>
+    </li>
+  </ol>
+
+  <p>This is a matter for project policy although, in general, we would
+  recommend the <em>Branch When Needed</em> approach.</p>
+
+  <h3><a name="branching_where">Where to Branch From</a></h3>
+
+  <p>When you create a new branch you have two choices for which revision to
+  create the branch from:</p>
+
+  <ol>
+    <li>The latest version of the trunk.
+
+      <ul>
+        <li>This is the preferred choice where possible. It minimised the
+        chances of conflicts when you need to incorporate your changes back
+        onto the trunk.</li>
+      </ul>
+    </li>
+
+    <li>An older version of the trunk. There are a number of reasons why you
+    may need to do this. For example:
+
+      <ul>
+        <li>You are using a stable version to act as your "control" data.</li>
+
+        <li>You need to know that your baseline is well tested (e.g. scientific
+        changes).</li>
+
+        <li>Your change may need to be merged with other changes relative to a
+        stable version for testing purposes or for use in a package (see
+        <a href="#packages">Creating Packages</a> later in this section).</li>
+      </ul>
+    </li>
+  </ol>
+
+  <h3><a name="branching_update">Merging From the Trunk</a></h3>
+
+  <p>Once you've created your branch you need to decide whether you now work in
+  isolation or whether you periodically merge in the latest changes from the
+  trunk.</p>
+
+  <ul>
+    <li>Regularly merging from the trunk minimises the work involved when you
+    are ready to merge back to the trunk. You deal with any merge issues as you
+    go along rather than all at the end (by which time your branch and the
+    trunk could have diverged significantly).</li>
+
+    <li>One downside of merging from the trunk is that the baseline for your
+    changes is a moving target. This may not be what you want if you have some
+    "control" results that you have generated.</li>
+
+    <li>Another downside of merging from the trunk is that it may introduce
+    bugs. Although any code on the trunk should have been tested and reviewed
+    it is unlikely to be as well tested as code from a stable release.</li>
+
+    <li>Unless you originally created your branch from the latest version of
+    the trunk it is unlikely that you are going to want to merge in changes
+    from the trunk. The exception to this is once your change is complete when
+    it may make sense to merge all the changes on the trunk into your branch as
+    a final step. This is discussed in
+    <a href="#branching_commit">Merging Back to the Trunk</a> below.</li>
+  </ul>
+
+  <p>So, there are basically three methods of working:</p>
+
+  <ol>
+    <li>Branch from a stable version and prepare all your changes in isolation.
+
+      <ul>
+        <li>Necessary if you need to make your change relative to a well tested
+        release.</li>
+      </ul>
+    </li>
+
+    <li>Branch from the latest code but then prepare all your changes in
+    isolation.
+
+      <ul>
+        <li>Necessary if you need a stable baseline for your "control"
+        data.</li>
+      </ul>
+    </li>
+
+    <li>Branch from the latest code and then update your branch from the trunk
+    on a regular basis.
+
+      <ul>
+        <li>This is considered "best practise" for parallel working and should
+        be used where possible.</li>
+      </ul>
+    </li>
+  </ol>
+
+  <h3><a name="branching_commit">Merging Back to the Trunk</a></h3>
+
+  <p>Before merging your change back to the trunk you will need to test your
+  change and get it reviewed. There are two options for what code to test and
+  review:</p>
+
+  <ol>
+    <li>Test and review your changes in isolation. Then merge to the trunk and
+    deal with any conflicts at this stage. This may be the best method if:
+
+      <ul>
+        <li>Your changes have already been tested against a stable baseline and
+        re-testing after merging would be impracticable.</li>
+
+        <li>Your branch needs to be available for others to merge in its
+        changes in isolation.</li>
+      </ul>
+    </li>
+
+    <li>Merge in the latest code from the trunk before your final test and
+    review. This has the advantage that you are testing and reviewing the
+    actual code which will be committed to the trunk. However, it is possible
+    that other changes could get committed to the trunk whilst you are
+    completing your testing and review. There are several ways of dealing with
+    this:
+
+      <ul>
+        <li>Use locking to prevent it happening. The danger with this is that
+        you may prevent others from being able to get their change tested and
+        reviewed, hence inhibiting parallel devlopment.</li>
+
+        <li>Insist that the change is re-tested and reviewed. The problem with
+        this is that there is no guarantee that the same thing won't happen
+        again.</li>
+
+        <li>Merge in the new changes but don't insist on further testing or
+        review.
+
+          <ul>
+            <li>In most cases any changes won't clash so there is little to
+            worry about.</li>
+
+            <li>Where there are clashes then, in most cases, they will be
+            trivial with little danger of any side-effects.</li>
+
+            <li>Where the clashes are significant then, in most cases, this
+            will be very obvious whilst you are resolving the conflicts. In
+            this case you should repeat the testing and get the updates
+            reviewed.</li>
+          </ul>This is the recommended approach since it doesn't inhibit
+          parallel development and yet the chances of a bad change being
+          committed to the trunk are still very small.
+        </li>
+      </ul>
+
+      You should also consider what can be done to minimise the time taken
+      for testing and review.
+      <ul>
+	<li>Try to keep your changes small by breaking them down where possible.
+	    Smaller changes are easier and quicker to review. This also
+	    helps to minimise merge problems by getting changes back onto the
+	    trunk earlier.
+	<li>Automate your testing as far as possible to speed up the process.
+      </ul>
+    </li>
+  </ol>
+
+  <p>Most projects will require the developer who prepared the change to merge
+  it back to the trunk once it is complete. However, larger projects may wish
+  to consider restricting this to a number of experienced / trusted
+  developers.</p>
+
+  <ul>
+    <li>This makes it easier to control and prioritise the merges.</li>
+
+    <li>It applies an extra level of quality control.</li>
+
+    <li>It minimises the risk of mistakes being merged back on to the trunk by
+    less experienced developers</li>
+
+    <li>Scientific developers can concentrate on the scientific work.</li>
+
+    <li>One issue is that the person doing the merge to the trunk may need help
+    from the original developer to prepare a suitable log message.</li>
+  </ul>
+
+  <h3><a name="branching_delete">When to Delete Branches</a></h3>
+
+  <p>Once you are finished with your branch it is best to delete it to avoid
+  cluttering up the directory tree (remember that the branch and all its
+  history will still be available). There are two obvious approaches to
+  deleting branches.</p>
+
+  <ol>
+    <li>Delete the branch as soon as it has been merged back to the trunk
+    (prior to closing any associated Trac ticket).
+
+      <ul>
+        <li>This is the tidiest approach which minimises the chances of old
+        branches being left around.</li>
+      </ul>
+    </li>
+
+    <li>Delete the branch once a stable version of the system has been released
+    which incorporates your change.
+
+      <ul>
+        <li>If a bug is found in your change during integration testing then
+        you can prepare the fix on the original branch (without having to do
+        any additional work to restore the branch).</li>
+      </ul>
+    </li>
+  </ol>
+
+  <h2><a name="binary">Working with Binary Files</a></h2>
+
+  <p>The <tt>fcm conflicts</tt> command and <tt>xxdiff</tt> can only help you
+  resolve conflicts in text files. If you have binary files in your repository
+  you need to consider whether conflicts in these files would cause a problem.</p>
+
+  <h3><a name="binary_conflicts">Resolving Conflicts in Binary Files</a></h3>
+
+  <p>Conflicts in some types of binary files can be resolved manually. When you
+  are satisfied that the conflicts are resolved, issue the <tt>fcm resolved</tt>
+  command on the file to remove the conflict status. (You will be prevented from
+  committing if you have a conflicting file in your working copy.)</p>
+
+  <p>If you have a conflicting MS Office 2003 document, you may be able to take
+  advantage of the "Compare and Merge Documents" facility under the "Tools" menu
+  in a MS Office application. Consider a working copy, which you have just
+  updated from revision 100 to revision 101, and someone else has committed some
+  changes to a file <tt>doument.doc</tt> you are editing, you will get:</p>
+
+  <table class="pad" summary="Conflicts in a binary file" border="1"
+  width="100%">
+    <tr>
+      <th>Conflicts in a binary file</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm conflicts
+Conflicts in file: document.doc
+document.doc: ignoring binary file, please resolve conflicts manually.
+(SHELL PROMPT)$ fcm status
+=&gt; svn st
+?      document.doc.r100
+?      document.doc.r101
+C      document.doc
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Open <tt>document.doc.r101</tt> with MS Word. In <em>Tools &gt; Compare
+  and Merge Documents...</em>, open <tt>document.doc</tt>. You will be in Track
+  Changes mode automatically. Go through the document to accept, reject or merge
+  any changes. Save the document and exit MS Word when you are ready. Finally,
+  issue the <tt>fcm resolved</tt> command to remove the conflict status:</p>
+
+  <table class="pad" summary="Resolved conflicts in a binary file" border="1"
+  width="100%">
+    <tr>
+      <th>Resolved conflicts in a binary file</th>
+    </tr>
+
+    <tr>
+      <td>
+        <pre>
+(SHELL PROMPT)$ fcm resolved document.doc
+=&gt; svn resolved document.doc
+Resolved conflicted state of 'document.doc'
+(SHELL PROMPT)$ fcm status
+=&gt; svn st
+M      document.doc
+</pre>
+      </td>
+    </tr>
+  </table>
+
+  <p>Another type of conflict that you may be able to resolve manually is where
+  the binary file is generated from another file which can be merged. For
+  instance, some people who use LaTeX also store a PDF version of the document in
+  the repository. In such cases it is easy to resolve the conflict by
+  re-generating the PDF file from the merged LaTeX file and then issuing the
+  <tt>fcm resolved</tt> command to remove the conflict status. Note that, in this
+  particular case, a better approach might be to automate the generation of the
+  PDF file outside of the repository.</p>
+
+  <h3><a name="binary_locking">Using Locking</a></h3>
+
+  <p>For files with binary formats, such as artwork or sound, it is often
+  impossible to merge conflicting changes. In these situations, it is necessary
+  for users to take strict turns when changing the file in order to prevent time
+  wasted on changes that are ultimately discarded.</p>
+
+  <p>Subversion supports <em>locking</em> to allow you to prevent other users
+  from modifying a file while you are preparing changes. For details please refer
+  to the chapter
+  <a href="http://svnbook.red-bean.com/en/1.2/svn.advanced.locking.html">
+  Locking</a> from the Subversion book. Note that:</p>
+
+  <ul>
+    <li>FCM does not add any functionality to the locking commands provided by
+    Subversion.</li>
+
+    <li>If you need to lock a file you must do this in a working copy of the
+    trunk. There is nothing to stop you preparing the changes in a branch (maybe
+    you want to prepare the change in combination with a number of other changes
+    which do not require locking). However, you must always remember to lock the
+    file in the trunk first to prevent other users from preparing changes to the
+    file in parallel.</li> 
+
+    <li>Locking isn't the only way of preventing conflicts with binary files. If
+    you only have a small project team and a small number of binary files you may
+    find it easier to use other methods of communication such as emails or
+    just talking to each other. Alternatively, you may have a working practise
+    that particular files are only modified by particular users.</li>
+  </ul>
+  
+  <h2><a name="messages">Commit Log Messages</a></h2>
+
+  <p>Certain guidelines should be adhered to when writing log messages for code
+  changes when committing to the trunk:</p>
+
+  <ul>
+    <li>Try to start off the log message with one line indicating the general
+    nature of the change. This helps developers to tell whether a change is
+    important to them when viewing the Trac timeline view.</li>
+
+    <li>If you want to use bullets in your message then make them compatible
+    with <a href="http://trac.edgewall.org/wiki/WikiFormatting">Wiki
+    Formatting</a>. For example:
+
+      <table class="pad" summary="Example bullets using wiki formatting"
+      border="1" width="100%">
+        <tr>
+          <td>
+            <pre>
+No bullet
+ * First level bullet (single space at beginning)
+   * Second level bullet (three spaces at beginning)
+ 1. Numbered item instead of a bullet
+</pre>
+          </td>
+        </tr>
+      </table>This will ensure that the log message is displayed with proper
+      bullets in the Trac changeset view. You can also include other types of
+      wiki formatting but please be aware that the message still needs to be
+      readable when simply viewed as text (e.g. via <tt>fcm&nbsp;log</tt>).
+    </li>
+
+    <li>If your changes close a Trac ticket, make sure that your log message
+    refers to this using <a href="http://trac.edgewall.org/wiki/TracLinks">Trac
+    Links</a>, e.g. <tt>Closes issue #26.</tt></li>
+
+    <li>Don't leave blank lines at the end of your log message since they get
+    included in the message and, therefore, get included in the ouptut from
+    <tt>fcm log</tt>.</li>
+
+    <li>Take care to avoid making mistakes in your log messages since
+    correcting them involves additional work. However, if you realise that that
+    you've made a mistake don't leave it - get it corrected.
+
+      <ul>
+        <li>A log message can be corrected using the <em>propedit</em>
+        command,<br>
+        e.g. <tt>fcm propedit svn:log --revprop -r REV</tt><br>
+        Take care since this is an <em>unversioned</em> property so you run the
+        risk of losing information if you aren't careful with your edits.</li>
+
+        <li>By default, FCM repositories are configured such that all users can
+        update log messages. If you are not the original author of the changeset
+        then the original author will be sent an e-mail informing them of the
+        change. Other users can also be informed of log message changes if they
+        wish (see the section <a href="system_admin.html#svn_watch">Watching
+        changes in log messages</a> for details).</li>
+      </ul>
+    </li>
+  </ul>
+
+  <p>There are two possible approaches to recording the changes to individual
+  files:</p>
+
+  <ol>
+    <li>Maintain history entries in file headers.
+
+      <ul>
+        <li>
+          <em>Pros:</em>
+
+          <ul>
+            <li>You don't need access to the Subversion repository in order to
+            be able to view a files change history (e.g. external
+            collaborators).</li>
+          </ul>
+        </li>
+
+        <li>
+          <em>Cons:</em>
+
+          <ul>
+            <li>History entries will produce clashes whenever files are changed
+            in parallel (although these conflicts are trivial to resolve).</li>
+
+            <li>Source files which are changed regularly can become cluttered
+            with very long history entries.</li>
+
+            <li>It is not possible to include history entries in some types of
+            file.</li>
+          </ul>
+        </li>
+      </ul>
+    </li>
+
+    <li>Record which files have changed in the commit log message.
+
+      <ul>
+        <li>The log message should name every modified file and explain why it
+        was changed. For example:
+
+          <table class="pad" summary="Example log message" border="1" width=
+          "100%">
+            <tr>
+              <td>
+                <pre>
+ * working_practices.html:
+   Added guidelines for writing log messages.
+</pre>
+              </td>
+            </tr>
+          </table>
+
+	  Make sure that the log message includes some sort of description for
+	  every change. The value of the log becomes much less if developers cannot
+	  rely on its completeness. Even if you've only changed comments, note this
+	  in the message.</li>
+
+        <li>If you make exactly the same change in several files, list all the
+        changed files in one entry. For example:
+
+          <table class="pad" summary="Example log message" border="1" width=
+          "100%">
+            <tr>
+              <td>
+                <pre>
+ * code_management.html, system_admin.html, index.html:
+   Ran pages through tidy to fix HTML errors.
+</pre>
+              </td>
+            </tr>
+          </table>
+        </li>
+
+        <li>It shouldn't normally be necessary to include the full path in the
+	    file name - just make sure it is clear which of the changed files
+	    you are referring to. You can get a full list of the files changed using
+	    <tt>fcm&nbsp;log&nbsp;-v</tt>.
+        </li>
+      </ul>
+    </li>
+  </ol>
+
+  <p>When you're committing to your own branch then you can be much more
+  relaxed about log messages. Use whatever level of detail you find helpful.
+  However, if you follow similar guidelines then this will help when it comes
+  to preparing the log message when your change is merged back to the
+  trunk.</p>
+
+  <h2><a name="tickets">Trac Tickets</a></h2>
+
+  <h3><a name="tickets_create">Creating Tickets</a></h3>
+
+  <p>There are two different approaches to using the issue tracker within
+  Trac:</p>
+
+  <ol>
+    <li>All problems should be reported using Trac tickets.
+
+      <ul>
+        <li><em>Pros:</em> The issue tracker contains a full record of all the
+        problems reported and enhancements requested.</li>
+
+        <li>
+          <em>Cons:</em> The issue tracker gets cluttered up with lots of
+          inappropriate tickets.
+
+          <ul>
+            <li>Duplicate tickets.</li>
+
+            <li>Issues already discussed in the documentation.</li>
+
+            <li>Problems which turn out to be unrelated to the system.</li>
+
+            <li>Problems which are poorly described.</li>
+
+            <li>Things which would be better solved by a quick
+            conversation.</li>
+          </ul>This makes it much harder to search the issues and can slow down
+          the response to simple issues.
+        </li>
+      </ul>
+    </li>
+
+    <li>A Trac ticket shouldn't be created until the issue has been agreed.
+
+      <ul>
+        <li>Problems and issues should first be discussed with the project team
+        / system maintainers. Depending on the project, this could be via
+        email, on the newsgroups or through a quick chat over coffee.</li>
+
+        <li>Nothing is lost this way. Issues which are appropriate for the
+        issue tracker still get filed. It just happens slightly later, after
+        initial discussion has helped to clarify the best description for the
+        issue.</li>
+      </ul>
+    </li>
+  </ol>
+
+  <h3><a name="tickets_use">Using Tickets</a></h3>
+
+  <p>This sub-section provides advice on the best way of using tickets:</p>
+
+  <ol>
+    <li>In general, mature systems will require that there is a Trac ticket related
+	to every changeset made to the trunk. However this doesn't mean that there
+	should be a separate ticket for each change.
+	<ul>
+	  <li>If a change is made to the trunk and then a bug is subsequently found then,
+	      if this happens before the next release of the system, the subsequent
+	      change can be recorded on the same ticket.
+	  <li>There can often be changes which don't really affect the system itself since
+	      they are just system administration details. One way of dealing with this
+	      is to open a ticket for each release in which to record all such miscellaneous
+	      changes. It will probably be acceptable to review these changes after they have
+	      been committed, prior to the system release.
+	</ul>
+    <li>Whenever you refer to source files/directories in tickets, make sure that you refer
+	to particular versions of the files. This ensures that the links will work
+	in the future, even if those files are no longer in the latest version.
+	For example:<br>
+	<tt>Changes now ready for review:  source:/OPS/branches/dev/frdm/r123_MyBranch@234</tt>
+    <li>For some types of information, simply appending to the ticket may not be the
+	best way of working. For example, design notes or test results may be best recorded
+	elsewhere, preferably in a wiki page. If using wiki pages we recommend using a naming
+	convention to identify the wiki page with the associated ticket, for example:<br>
+	<tt>Please refer to [wiki:ticket/123/Design design notes]</tt><br>
+	<tt>See separate [wiki:ticket/123/TestResults test results]</tt><br>
+	Note that the square brackets have to be used since a page name containing numbers is
+	not recognised automatically.
+  </ol>
+
+  
+  <h2><a name="packages">Creating Packages</a></h2>
+
+  <p>Sometimes you may need to combine the changes from several different branches.
+  For example:
+  <ul>
+    <li>Your branch is just part of a larger change which needs to be tested in its
+	entirety before committing to the trunk.</li>
+    <li>You have some diagnostic code stored on a branch which you want to combine
+	with another branch for testing purposes.</li>
+  </ul>
+  We refer to this as creating a <em>package</em>.</p>
+
+  <p>To create a package you simply create a new branch as normal. The <em>type</em> should
+  be a <em>package</em> or possibly a <em>configuration</em> branch to help you distinguish
+  it from your other branches. You then simply merge in all of the branches that you want to
+  combine using <tt>fcm merge</tt>.</p>
+  
+  <ul>
+    <li>The chance of conflicts will be reduced if the branches you are combining have been
+	created from the same point on the trunk. Your package branch should also be created
+	from the same point on the trunk.
+	<ul>
+	  <li><em>Currently, <tt>fcm merge</tt> will not work unless this is true.</em></li>
+	</ul></li>
+    <li>If further changes are made on a branch you are using in a package then you can
+	incorporate these changes into your package using <tt>fcm merge</tt>. Note, however,
+	that if you have a branch which is being used in a package then you should avoid merging
+	changes from the trunk into your branch. If you do then it will be very difficult to
+	get updates to your branch merged into the package.</li>
+  </ul>
+
+  <p>The <tt>fcm branch --info</tt> command is very useful for maintaining packages. It tells
+  you all of the branches which have been merged into your package and whether there are any
+  more recent changes on those branches.</p>
+
+  <h2><a name="releases">Preparing System Releases</a></h2>
+
+  There are two ways of preparing system releases:
+  <ol>
+    <li>A system release is simply a particular version of the trunk. In order to do this it
+	will be necessary to restrict changes on the trunk whilst the release is being prepared.
+	<ul>
+	  <li>Users can continue to develop changes not intended for inclusion
+	      in this release on branches.
+	  <li>This may be a problem if preparing the release takes too long.
+	</ul>
+    <li>Create a release branch where the release is finalised.
+	<ul>
+	  <li>You then lose the ability to be able to branch from the release.
+	  <li>It may be harder to identify what changes have been made between releases
+	      (since you can't simply look at all the changesets made between two versions
+	      of the trunk).
+	</ul>
+  </ol>
+
+  <h2><a name="rapid">Rapid vs Staged Development Practises</a></h2>
+
+  <p>Most of this section on working practises has focussed on projects/systems
+  which are quite mature. Such systems are likely to have regular releases and
+  will, for example, insist that all changes to the trunk are reviewed and
+  tested.</p>
+
+  <p>If your system is still undergoing rapid development and has not yet
+  reached any sort of formal release then you will probably want to adopt a
+  much more relaxed set of working practises. For example:</p>
+
+  <ul>
+    <li>Changes don't need to be reviewed.</li>
+
+    <li>More changes will be committed to the trunk. Only very large changes
+    will be prepared on branches.</li>
+
+    <li>No requirement to have a Trac ticket associated with each change.</li>
+  </ul>
+
+  <p>We have tried to avoid building too many assumptions about working
+  practises into the FCM system. This gives projects the flexibility to decide
+  which working practises are appropriate for their system. Hopefully this
+  means that FCM can be used for large or small systems and for rapidly
+  evolving or very stable systems.</p>
+
+  <script type="text/javascript" src="maintain.js">
+  </script>
+</body>
+</html>
Index: LMDZ5/branches/testing/tools/fcm/etc/fcm.cfg.eg
===================================================================
--- LMDZ5/branches/testing/tools/fcm/etc/fcm.cfg.eg	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/etc/fcm.cfg.eg	(revision 1665)
@@ -0,0 +1,266 @@
+# ------------------------------------------------------------------------------
+# FCM central configuration file
+# ------------------------------------------------------------------------------
+
+# ------------------------------------------------------------------------------
+# Standard repository locations
+# ------------------------------------------------------------------------------
+
+# AMV repository
+set::url::amv                svn://fcm7/AMV_svn/AMV
+
+set::trac::amv               http://fcm7/projects/AMV/browser/AMV
+
+# ANCIL repository
+set::url::ancil              svn://fcm8/ANCIL_svn/ANCIL
+
+set::trac::ancil             http://fcm8/projects/ANCIL/browser/ANCIL
+
+# ATSR repository
+set::url::atsr               svn://fcm7/ATSR_svn/ATSR
+
+set::trac::atsr              http://fcm7/projects/ATSR/browser/ATSR
+
+# CICE repository
+set::url::cice               svn://fcm3/CICE_svn/CICE
+
+set::trac::cice              http://fcm3/projects/CICE/browser/CICE
+
+# CVC repository
+set::url::cvc_admin          svn://fcm6/CVC_svn/Admin
+set::url::bullseye           svn://fcm6/CVC_svn/Bullseye
+set::url::cat                svn://fcm6/CVC_svn/CAT
+set::url::deicing            svn://fcm6/CVC_svn/Deicing
+set::url::ea                 svn://fcm6/CVC_svn/EA  
+set::url::ensemble           svn://fcm6/CVC_svn/Ensemble
+set::url::gales              svn://fcm6/CVC_svn/Gales
+set::url::ifv                svn://fcm6/CVC_svn/IFV
+set::url::mogreps            svn://fcm6/CVC_svn/MOGREPS
+set::url::openroad           svn://fcm6/CVC_svn/OpenRoad
+set::url::powertable         svn://fcm6/CVC_svn/PowerTable
+set::url::qnh                svn://fcm6/CVC_svn/QNH
+
+set::trac::cvc_admin         http://fcm6/projects/CVC/browser/Admin
+set::trac::bullseye          http://fcm6/projects/CVC/browser/Bullseye
+set::trac::cat               http://fcm6/projects/CVC/browser/CAT
+set::trac::deicing           http://fcm6/projects/CVC/browser/Deicing
+set::trac::ea                http://fcm6/projects/CVC/browser/EA
+set::trac::ensemble          http://fcm6/projects/CVC/browser/Ensemble
+set::trac::gales             http://fcm6/projects/CVC/browser/Gales
+set::trac::ifv               http://fcm6/projects/CVC/browser/IFV
+set::trac::mogreps           http://fcm6/projects/CVC/browser/MOGREPS
+set::trac::openroad          http://fcm6/projects/CVC/browser/OpenRoad
+set::trac::powertable        http://fcm6/projects/CVC/browser/PowerTable
+set::trac::qnh               http://fcm6/projects/CVC/browser/QNH
+
+# DA repository
+set::url::da                 svn://fcm5/DA_svn/DA
+
+set::trac::da                http://fcm5/projects/DA/browser/DA
+
+# ENS repository
+set::url::ens                svn://fcm9/ENS_svn/ENS
+
+set::trac::ens               http://fcm9/projects/ENS/browser/ENS
+
+# FCM repository
+set::url::fcm                svn://fcm1/FCM_svn/FCM
+set::url::fcm_admin          svn://fcm1/FCM_svn/Admin
+
+set::trac::fcm               http://fcm1/projects/FCM/browser/FCM
+set::trac::fcm_admin         http://fcm1/projects/FCM/browser/Admin
+
+# FLUME repository
+set::url::flume_metadata     svn://fcm2/FLUME_svn/metadata
+
+set::trac::flume_metadata    http://fcm2/projects/FLUME/browser/metadata
+
+# GEN repository
+set::url::gen                svn://fcm1/GEN_svn/GEN
+
+set::trac::gen               http://fcm1/projects/GEN/browser/GEN
+
+# LEM repository
+set::url::lem                svn://fcm2/LEM_svn/LEM
+
+set::trac::lem               http://fcm2/projects/LEM/browser/LEM
+
+# LINK repository
+set::url::link               svn://fcm1/LINK_svn/LINK
+
+set::trac::link              http://fcm1/projects/LINK/browser/LINK
+
+# NEMO repository
+set::url::nemosys            svn://fcm3/NEMO_svn/NEMOSYS
+
+set::trac::nemosys           http://fcm3/projects/NEMO/browser/NEMOSYS
+
+# NWPWEB repository
+set::url::www_nwp            svn://fcm1/NWPWEB_svn/www_nwp
+
+set::trac::www_nwp           http://fcm1/projects/NWPWEB_svn/browser/www_nwp
+
+# obsmon repository
+set::url::obsmon_dc          svn://fcm4/obsmon_svn/DC
+set::url::obsmon_rtm         svn://fcm4/obsmon_svn/RTM
+
+set::trac::obsmon_dc         http://fcm4/projects/obsmon/browser/DC
+set::trac::obsmon_rtm        http://fcm4/projects/obsmon/browser/RTM
+
+# OCN repository
+set::url::polcoms            svn://fcm3/OCN_svn/POLCOMS
+
+set::trac::polcoms           http://fcm3/projects/OCN/browser/POLCOMS
+
+# OPFC repository
+set::url::opfc               svn://fcm9/OPFC_svn/OPFC
+
+set::trac::opfc              http://fcm9/projects/OPFC/browser/OPFC
+
+# OPS repository
+set::url::ops                svn://fcm4/OPS_svn/OPS
+set::url::ops_admin          svn://fcm4/OPS_svn/Admin
+set::url::ops_data           svn://fcm4/OPS_svn/Data
+
+set::trac::ops               http://fcm4/projects/OPS/browser/OPS
+set::trac::ops_admin         http://fcm4/projects/OPS/browser/Admin
+set::trac::ops_data          http://fcm4/projects/OPS/browser/Data
+
+# OSTIA repository
+set::url::ostia              svn://fcm3/OSTIA_svn/OSTIA
+
+set::trac::ostia             http://fcm3/projects/OSTIA/browser/OSTIA
+
+# PF repository
+set::url::pf                 svn://fcm5/PF_svn/PF
+
+set::trac::pf                http://fcm5/projects/PF/browser/PF
+
+# PostProc repository
+set::url::pp                 svn://fcm9/PostProc_svn/PostProc
+set::url::ppancil            svn://fcm9/PostProc_svn/PostProcAncil
+
+set::trac::pp                http://fcm9/projects/PostProc/browser/PostProc
+set::trac::ppancil           http://fcm9/projects/PostProc/browser/PostProcAncil
+
+# PRISM repository
+set::url::oasis4             svn://fcm2/PRISM_svn/oasis4
+
+set::trac::oasis4            http://fcm2/projects/PRISM/browser/oasis4
+
+# radarnet repository
+set::url::radarnet4          svn://fcm9/radarnet_svn/radarnet4
+
+set::trac::radarnet4         http://fcm7/projects/radarnet/browser/radarnet4
+
+# ROPP repository
+set::url::ropp_doc           svn://fcm7/ROPP_svn/ropp_doc
+set::url::ropp_src           svn://fcm7/ROPP_svn/ropp_src
+set::url::ropp_test          svn://fcm7/ROPP_svn/ropp_test
+set::url::ropp_web           svn://fcm7/ROPP_svn/ropp_web
+
+set::trac::ropp_doc          http://fcm7/projects/ROPP/browser/ropp_doc
+set::trac::ropp_src          http://fcm7/projects/ROPP/browser/ropp_src
+set::trac::ropp_test         http://fcm7/projects/ROPP/browser/ropp_test
+set::trac::ropp_web          http://fcm7/projects/ROPP/browser/ropp_web
+
+# RTTOV repository
+set::url::rttov8             svn://fcm7/RTTOV_svn/RTTOV8
+set::url::rttov9             svn://fcm7/RTTOV_svn/RTTOV9
+
+set::trac::rttov8            http://fcm7/projects/RTTOV/browser/RTTOV8
+set::trac::rttov9            http://fcm7/projects/RTTOV/browser/RTTOV9
+
+# SAUtils repository
+set::url::autoscat_global      svn://fcm7/SAUtils_svn/AUTOSCAT_Global
+set::url::autoscat_nae         svn://fcm7/SAUtils_svn/AUTOSCAT_NAE
+set::url::gpsiwv_mon           svn://fcm7/SAUtils_svn/GPSIWV_Mon
+set::url::gpsro_mon            svn://fcm7/SAUtils_svn/GPSRO_Mon
+set::url::iasi_mon             svn://fcm7/SAUtils_svn/IASI_Mon
+set::url::metstrike            svn://fcm7/SAUtils_svn/METSTRIKE
+set::url::scatwind_mon         svn://fcm7/SAUtils_svn/Scatwind_Mon
+
+set::trac::autoscat_global     http://fcm7/projects/SAUtils/browser/AUTOSCAT_Global
+set::trac::autoscat_nae        http://fcm7/projects/SAUtils/browser/AUTOSCAT_NAE
+set::trac::gpsiwv_mon          http://fcm7/projects/SAUtils/browser/GPSIWV_Mon
+set::trac::gpsro_mon           http://fcm7/projects/SAUtils/browser/GPSRO_Mon
+set::trac::iasi_mon            http://fcm7/projects/SAUtils/browser/IASI_Mon
+set::trac::metstrike           http://fcm7/projects/SAUtils/browser/METSTRIKE
+set::trac::scatwind_mon        http://fcm7/projects/SAUtils/browser/Scatwind_Mon
+
+# SBV repository
+set::url::sbv                svn://fcm6/SBV_svn/SBV
+set::url::sbv_admin          svn://fcm6/SBV_svn/Admin
+
+set::trac::sbv               http://fcm6/projects/SBV/browser/SBV
+set::trac::sbv_admin         http://fcm6/projects/SBV/browser/Admin
+
+# SCS repository
+set::url::scs                svn://fcm1/SCS_svn/SCS
+set::url::tik                svn://fcm1/SCS_svn/TIK
+set::url::tt                 svn://fcm1/SCS_svn/TT
+
+set::trac::scs               http://fcm1/projects/SCS/browser/SCS
+set::trac::tik               http://fcm1/projects/SCS/browser/TIK
+set::trac::tt                http://fcm1/projects/SCS/browser/TT
+
+# SPS repository
+set::url::sps                svn://fcm7/SPS_svn/SPS
+set::url::sps_archive        svn://fcm7/SPS_svn/Archive
+
+set::trac::sps               http://fcm7/projects/SPS/browser/SPS
+set::trac::sps_archive       http://fcm7/projects/SPS/browser/Archive
+
+# SURF repository
+set::url::surf               svn://fcm8/SURF_svn/SURF
+
+set::trac::surf              http://fcm8/projects/SURF/browser/SURF
+
+# test repository
+set::url::test               svn://fcm1/test_svn/OPS
+
+set::trac::test              http://fcm1/projects/test/browser/OPS
+
+# tutorial repository
+set::url::tutorial           svn://fcm1/tutorial_svn/tutorial
+
+set::trac::tutorial          http://fcm1/projects/tutorial/browser/tutorial
+
+# TRUI repository
+set::url::trui               svn://fcm1/TRUI_svn/TRUI
+
+set::trac::trui              http://fcm1/projects/TRUI/browser/TRUI
+
+# UM repository
+set::url::um                 svn://fcm2/UM_svn/UM
+set::url::um_admin           svn://fcm2/UM_svn/Admin
+set::url::gcom               svn://fcm2/UM_svn/GCOM
+
+set::trac::um                http://fcm2/projects/UM/browser/UM
+set::trac::um_admin          http://fcm2/projects/UM/browser/Admin
+set::trac::gcom              http://fcm2/projects/UM/browser/GCOM
+
+# UM tutorial repository
+set::url::um_tutorial        svn://fcm2/UM_TUTORIAL_svn/UM
+
+set::trac::um_tutorial       http://fcm2/projects/UM_TUTORIAL/browser/UM
+
+# VAR repository
+set::url::var                svn://fcm5/VAR_svn/VAR
+set::url::var_admin          svn://fcm5/VAR_svn/Admin
+set::url::var_data           svn://fcm5/VAR_svn/Data
+
+set::trac::var               http://fcm5/projects/VAR/browser/VAR
+set::trac::var_admin         http://fcm5/projects/VAR/browser/Admin
+set::trac::var_data          http://fcm5/projects/VAR/browser/Data
+
+# VER repository
+set::url::ver                svn://fcm6/VER_svn/VER
+set::url::ver_admin          svn://fcm6/VER_svn/Admin
+set::url::ver_archive        svn://fcm6/VER_svn/Archive
+
+set::trac::ver               http://fcm6/projects/VER/browser/VER
+set::trac::ver_admin         http://fcm6/projects/VER/browser/Admin
+set::trac::ver_archive       http://fcm6/projects/VER/browser/Archive
+
+# EOF
Index: LMDZ5/branches/testing/tools/fcm/etc/fcm_gui.desktop
===================================================================
--- LMDZ5/branches/testing/tools/fcm/etc/fcm_gui.desktop	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/etc/fcm_gui.desktop	(revision 1665)
@@ -0,0 +1,13 @@
+[Desktop Entry]
+Comment=
+Exec=fcm gui %f
+Hidden=false
+Icon=wizard
+MimeType=inode/directory
+Name=FCM GUI
+Path=
+Terminal=0
+TerminalOptions=
+Type=Application
+X-KDE-SubstituteUID=false
+X-KDE-Username=
Index: LMDZ5/branches/testing/tools/fcm/lib/Ecmwf/Fortran90_stuff.pm
===================================================================
--- LMDZ5/branches/testing/tools/fcm/lib/Ecmwf/Fortran90_stuff.pm	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/lib/Ecmwf/Fortran90_stuff.pm	(revision 1665)
@@ -0,0 +1,2736 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Ecmwf::Fortran90_stuff
+#
+# DESCRIPTION
+#   This is a module for analysing Fortran 9X code. It is used by the FCM
+#   system to generate interface blocks for Fortran 9X free source files.
+#
+# ABOUT THIS MODULE:
+#   The original version of this module was developed by the European Centre
+#   for Medium-Range Weather Forecasts (ECMWF). This version has been modified
+#   by UK Met Office to become part of the FCM system.
+# ------------------------------------------------------------------------------
+
+package Ecmwf::Fortran90_stuff;
+
+# Standard pragmas
+use strict;
+use warnings;
+
+# Standard modules
+require Exporter;
+
+our @ISA      = qw(Exporter);
+our @EXPORT   = qw(study setup_parse pre_tidy remove_macro expcont 
+                   process_include_files tidy tidy_decl getvars 
+		   find_unused_vars remove_unused_vars doctor_viol
+		   fix_doctor_viol various cont_lines f90_indent
+		   writefile readfile create_interface_block
+		   add_interface_blocks change_var_names insert_hook
+		   remake_arg_decl remove_some_comments parse_prog_unit
+		   get_calls_inc);
+
+# ------------------------------------------------------------------------------
+
+# Module variables
+
+my $fname = '';
+
+# ------------------------------------------------------------------------------
+# SYNPOSIS
+#   $file = &Ecmwf::Fortran90_stuff::fname ();
+#   &Ecmwf::Fortran90_stuff::fname ($file);
+#
+# DESCRIPTION
+#   This function returns the value in the module variable $fname, which is the
+#   name of the input Fortran source file from FCM. If an argument exists, the
+#   value of $fname is set to the value of the argument.
+#
+# ------------------------------------------------------------------------------
+
+sub fname {
+  $fname = $_[0] if @_;
+  return $fname;
+}
+
+#==========================================================================
+sub study{
+# Study statements and put attributes into array $statements
+# Attributes assigned:
+# $href->{content}       - What statement it is
+# $href->{decl}       - true if declaration,
+#                       5 means statement function
+#                       4 means USE statement,
+#                       2 means type decleration
+#                       3 means FORMAT statement
+#                       1 means the rest
+# $href->{in_contain} - true while in internal procedure(s)
+# $href->{exec}       - true if executable statement
+#                     - 2 means first executable statement in program unit
+#                     - 3 means last executable statement in program unit
+#                     - 23 means first and last executable statement in program unit
+# $href->{prog_unit}  - program unit number (numbered from 0)
+# $href->{number}     - statement number (numbered from 0)
+ 
+# Further attributes will be assigned later (action attributes)
+
+  my($statements,$prog_info) = @_;
+
+  our ($name,$nest_par);
+  my ($unit_name,@args,$prog_unit,$href,@punit,$current_punit);
+  my ($content,$decl,$exec);
+  my($type_def)=0;
+  my($unit_count)=-1;
+  @punit=();
+  $current_punit='';
+  my $number=-1;
+  my $in_contain=0;
+  my $in_interface=0;
+  my $contain_host='';
+  my $current_unit_name='';
+  our($study_called);
+#  if(! $study_called) {
+#    $$prog_info{has_interface_block}=0;
+#  }
+# Initial "parsing" loop
+
+  foreach $href (@$statements) {
+    $href->{in_contain}=$in_contain;
+    $href->{contain_host}=$contain_host if($in_contain);
+    $number++;
+    $_=$href->{statement};
+    $content='unknown';
+    my $content2='';
+    $decl=0;
+    $exec=0;
+
+    if($type_def) {
+ #     $href->{content}='typedef';
+    }
+    
+# Comment
+CRACK:    {
+      if(/^\s*(?:!|$)/) {
+	$content='comment';
+	last CRACK;
+      }
+
+      $_ = uc unless /^#/;
+      s/^\s*//;
+      s/\!.*\n/\n/g; # Remove trailing comments in all lines
+#      print "AA $_";
+ 
+# Program name statement 
+      if($content eq 'unknown' and ! $in_interface) {
+	$prog_unit=&parse_prog_unit(\$unit_name,\@args);
+	if($prog_unit) {
+          $current_unit_name=$unit_name;
+	  $content=uc($prog_unit);
+	  push(@punit,$prog_unit);
+	  $current_punit=$prog_unit;
+	  $unit_count++;
+	  if(! $study_called) {
+	    $$prog_info{'unit_name'}[$unit_count]=uc($unit_name);
+	    $$prog_info{'unit_name'}[$unit_count]=uc($unit_name);
+#	  $$prog_info{'tokens'}[$unit_count]=[];
+	    if($prog_unit eq 'module') {
+	      $$prog_info{'is_module'}=1;
+	      $$prog_info{'module_name'}=$unit_name;
+	    }
+	  }
+	  last CRACK;
+	}
+      }
+      if($content eq 'unknown') {
+	$decl=0;
+	$exec=1;
+# Executable constructs
+	&study_exec(\$content,$prog_info,\$study_called);
+	if($content eq 'IF') {
+	  s/^IF\s*$nest_par\s*//;
+	  &study_exec(\$content2,$prog_info,\$study_called);
+	}
+      }
+      
+
+      if($content eq 'unknown') {
+# Specification statemnts
+	$exec=0;
+	$decl=1;
+	if(/^USE\b/) {
+	  $content='USE';
+	  $decl=4;
+	}
+	elsif(/^INTEGER\b/) {
+	  $content='INTEGER';
+	  $decl=2;
+	}
+	elsif(/^REAL\b/) {
+	  $content='REAL';
+	  $decl=2;
+	}
+	elsif(/^LOGICAL\b/) {
+	  $content='LOGICAL';
+	  $decl=2;
+	}
+	elsif(/^CHARACTER\b/) {
+	  $content='CHARACTER';
+	  $decl=2;
+	}
+	elsif(/^DOUBLE\s*PRECISION\b/) {
+	  $content='DOUBLE PRECISION';
+	  $decl=2;
+	}
+	elsif(/^COMPLEX\b/) {
+	  $content='COMPLEX';
+	  $decl=2;
+	}
+	elsif(/^TYPE *\(/) {
+	  $content='type_decl';
+	  $decl=2;
+	}
+	elsif(/^ALLOCATABLE\b/) {
+	  $content='ALLOCATABLE';
+	}
+	elsif(/^COMMON\b/) {
+	  $content='COMMON';
+	}
+	elsif(/^DATA\b/) {
+	  $content='DATA';
+	}
+	elsif(/^DIMENSION\b/) {
+	  $content='DIMENSION';
+	}
+	elsif(/^EQUIVALENCE\b/) {
+	  $content='EQUIVALENCE';
+	}
+	elsif(/^EXTERNAL\b/) {
+	  $content='EXTERNAL';
+	}
+	elsif(/^\d+\s+FORMAT\b/) {
+	  $content='FORMAT';
+	  $decl=3;
+	}
+	elsif(/^IMPLICIT\b\s+NONE\b/) {
+	  $content='IMPLICIT NONE';
+	}
+	elsif(/^IMPLICIT\b/) {
+	  $content='IMPLICIT';
+	}
+	elsif(/^INTENT\b/) {
+	  $content='INTENT';
+	}
+	elsif(/^INTRINSIC\b/) {
+	  $content='INTRINSIC';
+	}
+	elsif(/^NAMELIST\b/) {
+	  $content='NAMELIST';
+	}
+	elsif(/^OPTIONAL\b/) {
+	  $content='OPTIONAL';
+	}
+	elsif(/^PARAMETER\b/) {
+	  $content='PARAMETER';
+          $decl = 2;
+	}
+	elsif(/^POINTER\b/) {
+	  $content='POINTER';
+	}
+	elsif(/^PUBLIC\b/) {
+	  $content='PUBLIC';
+	}
+	elsif(/^PRIVATE\b/) {
+	  $content='PRIVATE';
+	}
+	elsif(/^SAVE\b/) {
+	  $content='SAVE';
+	}
+	elsif(/^TARGET\b/) {
+	  $content='TARGET';
+	}
+	elsif(/^SEQUENCE\b/) {
+	  $content='SEQUENCE';
+	}
+	elsif(/^INTERFACE\b/) {
+	  $content='INTERFACE';
+	  if(! $study_called) {
+	    $$prog_info{has_interface_block}=1;
+	    $in_interface=1;
+	  }
+	}
+	elsif(/^END ?INTERFACE\b/) {
+	  $content='END INTERFACE';
+	    $in_interface=0;
+	}
+	elsif(/^TYPE *[^\( ]/i) {
+	  $content='type_def';
+	  $type_def=1;
+	}
+	elsif(/^END\s*TYPE\b/){
+	  $content='type_def';
+	  $type_def=0;
+	}
+        elsif( $in_interface ) {
+          if(/^MODULE PROCEDURE\b/) {
+            $content='MODULE PROCEDURE';
+          }
+        }
+      }
+# Other constructs
+      if($content eq 'unknown') {
+	$decl=0;
+	$exec=0;
+	
+	if(/^CONTAINS\b/) {
+	  $content='CONTAINS';
+	  $in_contain=1;
+          $contain_host=uc($current_unit_name);
+	  if(! $study_called) {
+	    $$prog_info{has_contain}=1;
+	    $$prog_info{containing}=1;
+	  }
+	}
+	elsif(/^(?:INCLUDE|#include)\b/) {
+	  $content='include';
+	  if(! $study_called) {
+	    $$prog_info{has_include}=1;
+	  }
+	}
+	elsif(/^\#/) {
+	  $content='cpp';
+	}
+	elsif(/^\@/) {
+	  $content='compiler_directive';
+	}
+	
+	else{
+	  if(/^END\b/ and ! $in_interface) {
+	    $prog_unit=pop(@punit);
+	    $content='END '.uc($prog_unit);
+	    if($in_contain) {
+	      unless(@punit) {
+		$unit_count=0;
+		$href->{in_contain}=0;
+		$in_contain=0;
+	      }
+	    }
+	  }
+	} 
+      }
+    }
+    
+    if($in_interface and $content ne 'INTERFACE') {
+      $content='in_interface';
+      $exec=0;
+      $decl=1;
+    }
+
+#    print "BB $unit_count $content $_";
+    if($content  eq 'unknown') {
+      print STDERR $fname, ': failed to crack statement starting at line ',
+                   $href->{first_line}, ', - syntax error?', "\n";
+      print STDERR ' ', $_, "\n";
+#      print STDERR "study_called $study_called in_interface $in_interface \n";
+#      print STDERR Dumper($statements);
+      #die "Failed in study";
+    }
+#    unless($content eq 'comment') {
+#      my @tmpvar=/\b$name\b/g;
+#      my $i=0;
+#      foreach my $tmp (@tmpvar){ 
+#	$href->{'tokens'}[$i]=$tmp;
+#	$i++;
+#	if(! $study_called and $unit_count > -1) {
+#	  $$prog_info{'token_hash'}[$unit_count]{$tmp}++;
+#	}
+#      }
+#    }
+               
+    $href->{content}=$content;
+    $href->{content2}=$content2 if($content2);
+    $href->{decl}=$decl;
+    $href->{exec}=$exec;
+#    $href->{type_decl}=$type_decl;
+    $href->{prog_unit}=$unit_count;
+    $href->{number}=$number;
+    unless($content eq 'comment') {
+      $href->{multi_line} = 1 if(tr/\n// > 1);
+    }
+  }
+
+
+# Find first executable statement in each program unit
+# Also repair statement functions wrongly assigned as executable
+  my $prev_unit_count=-2;
+  my $stat_func_suspicion=0;
+  my @lastexec=();
+
+  foreach $href (@$statements) {
+    $exec=$href->{exec};
+    $unit_count=$href->{prog_unit};
+    if($exec) {
+      if($unit_count > $prev_unit_count) {
+	$content=$href->{content};
+	if($content eq 'array_assign') {
+	  $stat_func_suspicion=1;
+	  $_=$href->{statement};
+	  if(/^\s*$name\s*\(\s*:/){
+	    $stat_func_suspicion=0;
+#	    print " A $_";
+	   } 
+	  elsif(/^\s*$name\s*\(\s*$name\s*:/){
+	    $stat_func_suspicion=0;
+#	    print " B $_";
+	  } 
+	  elsif(/^\s*$name\s*\(\s*\d+/){
+	    $stat_func_suspicion=0;
+#	    print " C $_";
+	  }
+	  else {
+	    $href->{exec}=0;
+	    $href->{decl}=5;
+	    $href->{content}='statmf';
+#	    print " D $_";
+	    next;
+	  }
+	}
+	$href->{exec}=2;
+	$prev_unit_count=$unit_count;
+	$content=$href->{content};
+      }
+      $lastexec[$unit_count]=$href->{number}  unless ($unit_count < 0);  
+# No prog_unit assigned, include file?
+    }
+  }
+
+# Assign last executable statement
+  if(@lastexec) {
+    foreach my $last (@lastexec) {
+      if(defined ($last)) {
+	if($$statements[$last]->{exec} == 1) {
+	  $$statements[$last]->{exec}=3;
+	}
+	else{
+	  $$statements[$last]->{exec}=23;
+	}      
+      }
+    }
+  }
+# Consistency checks
+  my $fail=0;
+  my $prev_exec=0;
+  $prev_unit_count=-1;
+  foreach $href (@$statements) {
+    $content=$href->{content};
+    next if($content eq 'comment');
+    $unit_count=$href->{prog_unit};
+    $exec=$href->{exec};
+    $decl=$href->{decl};
+    if($unit_count == $prev_unit_count) {
+      if($decl and $prev_exec) {
+	unless ($content eq 'FORMAT' | $content eq 'DATA' ) {
+          die $fname, ': declaration after executable statement', "\n",
+              $href->{first_line}, ' ', $href->{statement}, "\n";
+	}
+      }
+    }
+    $prev_unit_count=$unit_count;
+    $prev_exec=$exec;
+  }
+
+  $study_called=1;
+}
+
+#==========================================================================
+sub study_exec{
+  my($content,$prog_info,$study_called) = @_;
+  our ($name,$nest_par);
+  if(/^(\w+\s*:\s*)*IF\s*$nest_par\s*THEN/) {
+    $$content='IF_construct';
+  }
+  elsif(/^ELSE\s*IF\s*\(/) {
+    $$content='ELSEIF';
+  }
+  elsif(/^ELSE\b\s*($name)*/) {
+    $$content='ELSE';
+  }
+  elsif(/^END\s*IF\b\s*($name)*/) {
+    $$content='ENDIF';
+  }
+  elsif(/^(?:\d+\s+)?($name\s*:\s*)*DO(\s+WHILE)?\b/) {
+    $$content='DO';
+  }
+  elsif(/^(?:\d+\s+)?END\s*DO\b/) {
+    $$content='ENDDO';
+  }
+  elsif(/^(?:\d+\s+)?ALLOCATE\b/) {
+    $$content='ALLOCATE';
+  }
+  elsif(/^ASSIGN\b/) {
+    $$content='ASIGN';
+  }
+  elsif(/^(?:\d+\s+)?BACKSPACE\b/) {
+    $$content='BACKSPACE';
+  }
+  elsif(/^(?:\d+\s+)?CALL\b/) {
+    $$content='CALL';
+    if(!$$study_called) {
+      $$prog_info{no_calls}++;
+    }
+  }
+  elsif(/^(?:\d+\s+)?CLOSE\b/) {
+    $$content='CLOSE';
+  }
+  elsif(/^(?:\d+\s+)?CONTINUE\b/) {
+    $$content='CONTINUE';
+  }
+  elsif(/^(?:\d+\s+)?CYCLE\b/) {
+    $$content='CYCLE';
+  }
+  elsif(/^(?:\d+\s+)?DEALLOCATE\b/) {
+    $$content='DEALLOCATE';
+  }
+  elsif(/^ENDFILE\b/) {
+    $$content='ENDFILE';
+  }
+  elsif(/^(?:\d+\s+)?EXIT\b/) {
+    $$content='EXIT';
+  }
+  elsif(/^(?:\d+\s+)?GO\s*TO\b/) {
+    $$content='GOTO';
+  }
+  elsif(/^(?:\d+\s+)?IF\s*\(/) {
+    $$content='IF';
+  }
+  elsif(/^(?:\d+\s+)?INQUIRE\b/) {
+    $$content='INQUIRE';
+  }
+  elsif(/^(?:\d+\s+)?NULLIFY\b/) {
+    $$content='NULLIFY';
+  }
+  elsif(/^(?:\d+\s+)?OPEN\b/) {
+    $$content='OPEN';
+  }
+  elsif(/^(?:\d+\s+)?PAUSE\b/) {
+    $$content='PAUSE';
+  }
+  elsif(/^(?:\d+\s+)?PRINT\b/) {
+    $$content='PRINT';
+  }
+  elsif(/^(?:\d+\s+)?(?:READ|BUFFER\s*IN)\b/) {
+    $$content='READ';
+  }
+  elsif(/^(?:\d+\s+)?RETURN\b/) {
+    $$content='RETURN';
+  }
+  elsif(/^(?:\d+\s+)?REWIND\b/) {
+    $$content='REWIND';
+  }
+  elsif(/^(?:\d+\s+)?STOP\b/) {
+    $$content='STOP';
+  }
+  elsif(/^(?:\d+\s+)?(?:WRITE|BUFFER\s*OUT)\s*\(/) {
+    $$content='WRITE';
+  }
+  elsif(/^(?:\d+\s+)?($name\s*:\s*)*SELECT\s*CASE\b/) {
+    $$content='SELECT CASE';
+  }
+  elsif(/^(?:\d+\s+)?CASE\b/) {
+    $$content='CASE';
+  }
+  elsif(/^(?:\d+\s+)?END\s*SELECT\b/) {
+    $$content='END SELECT';
+  }
+  elsif(/^(?:\d+\s+)?WHERE\s*$nest_par\s*$name.*=/) {
+    $$content='WHERE';
+  }
+  elsif(/^(?:\d+\s+)?WHERE\s*\(/) {
+    $$content='WHERE_construct';
+  }
+  elsif(/^ELSE\s*WHERE\b/) {
+    $$content='ELSEWHERE';
+  }
+  elsif(/^END\s*WHERE\b/) {
+    $$content='ENDWHERE';
+  }
+  elsif(/^(?:\d+\s+)?FORALL\s*\(/) {
+    $$content='FORALL';
+  }
+  elsif(/^END\s*FORALL\b/) {
+    $$content='ENDFORALL';
+  }
+  elsif(/^(?:\d+\s+)?$name(?:\s*%\s*$name)*\s*=/o) {
+    $$content='scal_assign';
+  }
+  elsif(/^(?:\d+\s+)?$name(?:\s*$nest_par)*(?:\s*%\s*$name(?:\s*$nest_par)?)*\s*=/o) {
+    $$content='array_assign';
+  }
+}
+#===================================================================================
+sub pre_tidy {
+
+# Initial tidying to make the rest work
+
+  my($lines)=@_;
+  foreach (@$lines) {
+
+# Substitute tab with four blanks
+    s/\t/    /g;
+    s/^ *INTEGER /INTEGER_M /i;
+    s/^ *REAL /REAL_B /i;
+  }
+}
+#==========================================================================
+sub remove_macro {
+
+# Remove INTEGER_M, _ONE_ etc. macros and replace by expanded statement
+
+  my($lines)=@_;
+
+  my($im)=1; # Until I start checking include files
+  my($ia)=0;
+  my($ib)=0;
+  my($rb)=1; # Until I start checking include files
+  my($is)=0;
+  my($rh)=0;
+  my($rm)=0;
+  my(@pars,$string);
+  for (@$lines) {
+    next if(/^ *$/ | /^ *!/);
+# The following two substitutions should be restored at end of processing
+    s/(\'[^!]*)!+(.*\')/$1\£$2/;   # Protect against mischief 
+    s/(["][^!]*)!+(.*["])/$1\£$2/;      # Protect against mischief
+    $im=$im+/JPIM\b/i unless($im);
+    $rb=$rb+/JPRB\b/i unless($rb);
+    $rm=$rm+/JPRM\b/i unless($rm);
+    $im=$im+s/\bINTEGER_M\b/INTEGER(KIND=JPIM)/o;
+    $ia=$ia+s/\bINTEGER_A\b/INTEGER(KIND=JPIA)/o;
+    $ib=$ib+s/\bINTEGER_B\b/INTEGER(KIND=JPIB)/o;
+    $is=$is+s/\bINTEGER_S\b/INTEGER(KIND=JPIS)/o;
+    $rb=$rb+s/\bREAL_B\b/REAL(KIND=JPRB)/o;
+    $rh=$rh+s/\bREAL_H\b/REAL(KIND=JPRH)/o;
+    $rm=$rm+s/\bREAL_M\b/REAL(KIND=JPRM)/o;
+    $rb=$rb+s/\b_ZERO_\b/0.0_JPRB/og;
+    $rb=$rb+s/\b_ONE_\b/1.0_JPRB/og;
+    $rb=$rb+s/\b_TWO_\b/2.0_JPRB/og;
+    $rb=$rb+s/\b_HALF_\b/0.5_JPRB/og;
+  }
+  @pars=();
+  push(@pars,"JPIM") if $im;
+  push(@pars,"JPRB") if $rb;
+  push(@pars,"JPRM") if $rm;
+  push(@pars,"JPIA") if $ia;
+  push(@pars,"JPIB") if $ib;
+  push(@pars,"JPIS") if $is;
+  ($string=join('     ,',@pars))=~s/ *$//;
+  for (@$lines) {
+    next unless (/^\#/);
+    if(@pars) {
+      s/^#include +"tsmbkind.h"/USE PARKIND1  ,ONLY : $string/ ;
+    }
+    else {
+      s/^#include +"tsmbkind.h"//;
+    }
+#    if($rh) {
+      s/^#include +"hugekind.h"/USE PARKIND2  ,ONLY : JPRH/ ;
+#    }
+#    else {
+#      s/^#include +"hugekind.h"// ;
+#    }
+  }
+}
+
+#==========================================================================
+sub readfile  {
+# Read file 
+  my($fname)=@_;
+  my(@lines);
+  if(!open(INFIL,$fname)) {
+    print STDERR "Can't open $fname for reading\n";
+    die("Can't open $fname for reading\n");
+  }
+  @lines=<INFIL>;
+  close INFIL;
+  (@lines);
+}
+
+#==========================================================================
+sub writefile  {
+# Write file
+  my($fname,$lines)=@_;
+  if(!open(OUTFIL,">".$fname)) {
+    print STDERR "Can't open $fname for writing\n";
+    exit;
+  }
+  print OUTFIL @$lines;
+  close OUTFIL;
+}
+
+#==========================================================================
+sub expcont {
+#
+# Expand continuation lines into statements for free-format Fortran while
+# maintaining line-breaking and all comments
+# Put statements onto array of references to anonymous hashes as key 'statement'
+# Also put into the hash the linenumber of first line of statement as key 'first_line'
+  my ($lines, $statements) = @_;
+  my ($statm, $first_line);
+
+  my $prev        = 0;
+  my $line_number = 0;
+
+  for (@$lines) {
+    $line_number++;
+
+    s/^([^'"]*)(?:\s*!.*)$/$1/; # Remove trailing comments
+
+    s/^(\s*)&(.*)$/$1$2/s;
+
+    if (!/^\s*!.*$/ && /^.+?&(?:\s*!.*)*\s*$/) {
+      s/(.+?)&(.+)/$1\n/s;
+
+      $statm     .= $_;
+      $first_line = $line_number unless $prev;
+      $prev       = 1;
+      next;
+
+    } elsif ($prev && /^\s*(?:!|$)/) { # ignore blank/comment lines
+      next;
+
+    } else {
+      s/!.*?$//;
+
+      $statm     .= $_;
+      push @$statements, {
+        'statement'  => $statm,
+        'first_line' => $prev ? $first_line : $line_number,
+      };
+
+      $statm = "";
+      $prev  = 0;
+    }
+  }
+}
+#==========================================================================
+
+sub cont_lines {
+#
+# Put back continuation character in correct place and execute delayed actions
+#
+  my($statements,$lines,$line_hash) = @_;
+  my(@temp,$i,$iup,$href);
+
+
+# Put back continuation characters and split statements into lines as they were
+  @$lines=();
+  @$line_hash=();
+  foreach $href (@$statements) {
+    $_=$href->{statement};
+    if (/\n.*\n/){                      # This is a multi-line statement
+      @temp=split /\n/;                 # Split statement into lines (removes EOL)
+      $iup=scalar(@temp);               # Number of lines in statement
+      for ($i=0;$i < $iup;$i++) {       # Loop through lines
+	$_=$temp[$i];
+	if($i == 0 ){                   # First line
+	  if(/^([^!]+)(!.*)$/) {        # Line has trailing comment
+	    s/^([^!]+)(!.*)$/$1&$2\n/;  # Put back & at end of line before comment
+	  }
+	  else {                        # No trailing comment
+	    s/^([^!]+)$/$1&\n/;         # Put back & and EOL at end of line
+	  }	    
+	}
+	elsif ($i == ($iup-1)) {        # Last line
+	  s/^( *)(.*)$/$1& $2 \n/;      # Put back & at beginning of line
+	}
+	else {                          # Other lines
+	  if (/^ *!/) {                 # Line is comment line
+	    $_=$_."\n";                 # Restore EOL for comments
+	  }
+	  else {
+	    if(/^( *)([^!]*)(!.*)$/) {  # Line has trailing comment
+	      s/^( *)([^!]*)(!.*)*$/$1& $2&$3\n/;  # & at beginning and end of line
+	    }
+	    else {                      # No trailing comment
+	      s/^( *)([^!]*)$/$1& $2&\n/; # & at beggining and end of line
+	    }	 
+	  }  
+	}
+	if($i == 0        && exists $href->{pre_insert}) {
+	  my @templines=split('\n',$href->{pre_insert});
+	  foreach my $tline (@templines) {
+	    my $rec={};
+	    $rec->{'content'}='unknown';
+	    $rec->{'line'}=$tline."\n";
+	    push(@$lines,$rec->{'line'});
+	    push(@$line_hash,$rec);
+	  }
+	}
+	unless(exists $href->{remove}) {
+	  my $rec={};
+	  $rec->{'line'}=$_;
+	  if($i == 0) {
+	    $rec->{'content'}=$href->{content};
+	  }
+	  else {
+	    $rec->{'content'}='cont_line';
+	  }
+	  push(@$lines,$rec->{'line'});
+	  push(@$line_hash,$rec);
+	}
+	if($i == ($iup-1) && exists $href->{post_insert}) {
+	  my @templines=split('\n',$href->{post_insert});
+	  foreach my $tline (@templines) {
+	    my $rec={};
+	    $rec->{'content'}='unknown';
+	    $rec->{'line'}=$tline."\n";
+	    push(@$lines,$rec->{'line'});
+	    push(@$line_hash,$rec);
+	  }
+	}
+      }
+    }
+    else {  # Not multiline statement
+      if(exists $href->{pre_insert}) {
+	my @templines=split('\n',$href->{pre_insert});
+	foreach my $tline (@templines) {
+	  my $rec={};
+	  $rec->{'content'}='unknown';
+	  $rec->{'line'}=$tline."\n";
+	  push(@$lines,$rec->{'line'});
+	  push(@$line_hash,$rec);
+	}
+      }
+      unless(exists $href->{remove}) {
+	my $rec={};
+	$rec->{'line'}=$_;
+	$rec->{'content'}=$href->{content};
+	push(@$lines,$rec->{'line'});
+	push(@$line_hash,$rec);
+#	print $rec;
+      }
+      if(exists $href->{post_insert}) {
+	my @templines=split('\n',$href->{post_insert});
+	foreach my $tline (@templines) {
+	  my $rec={};
+	  $rec->{'content'}='unknown';
+	  $rec->{'line'}=$tline."\n";
+	  push(@$lines,$rec->{'line'});
+	  push(@$line_hash,$rec);
+	}
+      }
+    }
+  }
+}
+#==========================================================================
+sub getvars {
+# Return list of locally declared variables with type and scope information
+# 
+  my($statements,$prog_info,$vars,$use_vars) = @_;
+  my ($test,$type,@vars1,$func,$prog_unit,$dum,$tmp_name,@pu_args);
+  my ($preserve,$rank,$href);
+  our($nest_par,$name);
+
+  %$vars=();
+  $func="";
+  $prog_unit=0;
+  %$use_vars=();
+  foreach $href (@$statements) {
+    next if($href->{content} eq 'comment');           # Skip comments
+    next if($href->{exec});                        # Don't look in executable statements
+    next if($$prog_info{is_module} and ! $href->{in_contain}); # Unless inside CONTAIN skip module 
+    $prog_unit=$href->{prog_unit};
+    if($href->{content} eq 'FUNCTION') {
+      $_=$href->{statement};
+      my $dum=&parse_prog_unit(\$func,\@pu_args);          # Get name of FUNCTION
+#      print "GETVARS FUNCTION $func \n";
+      $func=uc($func);
+    }
+    if($href->{decl} == 2 or $href->{content} eq 'EXTERNAL'){  # Real parse starts
+      $_=$href->{statement};
+      $_=uc($_);                                   # Upcase to avoid /.../i
+      s/^ *//;                                     # remove leading blanks
+      if($href->{decl} == 2) {
+	$type=lc(substr($href->{content},0,1));
+      }
+      else {
+	$type='e';
+      }
+      s/\!.*\n/\n/g;                               # Remove trailing comments in all lines
+      $preserve=$_;
+      s/(.+)::(.+)/$2/s;                           #REAL(KIND=JPRB) :: zsig(:) -> zsig(:),
+      s/^EXTERNAL (.+)$/$1/;
+      s/\s+//g;                                    # Remove all white-space
+      if($href->{content} eq 'CHARACTER') {
+	s/($name)\*\d+/$1/g;
+	s/($name)\*$nest_par/$1/g;
+	s/($name)$nest_par\*\w+/$1/g;
+      }
+      s#=\(/.+/\)##;      # ZVAL(1:2)=(/1.0,2.0/) -> ZVAL(1:2)
+#?      s/=[^,\n]+//g;
+      s/$nest_par//g;     # ISEC3(SIZE(NSEC3)),ISEC4(SIZE(NSEC4)) -> ISEC3,ISEC4
+      s/=\w+//g;          # ZVAL=1.0 -> ZVAL
+      s@/.*/@@;           # What?
+      @vars1=split(',',$_);
+      for(@vars1) {
+	next unless /^$name$/;          # A bit of security
+	if($preserve =~ /\b$_\b *\(/ | $preserve =~ /DIMENSION/) {
+	  $rank=1;        # Variable is array
+	}
+	else {
+	  $rank=0;        # Variable is scalar
+	}
+	if($_ eq $func) {
+	  $$vars{$_}{type_spec}="f";
+	} 
+	else {
+	  if($href->{content} eq 'FUNCTION') {
+	    $$vars{$_}{type_spec}='f';
+	  }
+	  else {
+	    $$vars{$_}{type_spec}=$type;
+	  }
+	}
+	$$vars{$_}{scope}=$prog_unit;
+	$$vars{$_}{rank}=$rank;
+	$$vars{$_}{usage}='local';
+      }
+    }
+# Perhaps the variable is really a statement function?
+    if($href->{decl} == 5) {
+      $_=$href->{statement};
+      s/\s+//g;                                    # Remove all white-space
+      /^($name)\((.+)\)=/i;
+      my $tvar=uc($1);
+      my @stmf_args=split(',',$2);
+      if (exists($$vars{$tvar})) {
+	$$vars{$tvar}{type_spec}='s';
+#	print "STATMF OK $tvar \n ";
+      }
+      for (@stmf_args) {
+	if (exists($$vars{$_})) {
+	  $$vars{$_}{type_spec}='s';
+#	  print "STATMF ARG OK $_ \n ";
+	}
+      }
+    }
+  }
+# Perhaps instead the variable is a declaration of an external function?
+  my @extract=();                  # Extract part of statements for efficiency
+  foreach $href (@$statements) {
+    if($href->{exec}) {                 # Function call must be in executable stat.
+      next if($href->{content} eq 'CALL'); # A call can't contain an undeclared function
+      push(@extract,$href->{statement});
+    }
+  }
+  
+  foreach my $var (keys (%$vars)) {
+    next if($$vars{$var}{rank} > 0);   # Can't be a function if rank > 0
+    next if($$vars{$var}{type_spec} eq 's' | $$vars{$var}{type_spec} eq 'f');
+    my $dec_unit=$$vars{$var}{scope};
+    my $regex1=qr/\b$var\b\s*\(/i;      # As var's rank=0 this could be function call
+    for(@extract) {
+      if(/${regex1}/) {
+	s/\!.*\n/\n/g;                       # Remove trailing comments in all lines
+	s/\s+//g;                            # Remove all white-space
+	if(/${regex1}/) {
+	  if($$vars{$var}{type_spec} eq 'c') {   # Avoid CLVAR(1:3) etc.
+	    next if(/${regex1}\s*(\d+|$name)*\s*:\s*(\d+|$name)*\s*\)/);
+	  }
+#	  print "TYPE changed to function $var $_ \n";
+	  $$vars{$var}{type_spec}='f';
+	  last;
+	}
+      }
+    }
+  }
+# ---------------------------------------------------------------------
+# Assign  "usage" in Doctor sense to variable (default usage is 'local')
+# 
+  foreach $href (@$statements) {
+# Is the varaible a dummy argument
+    if($href->{content} eq 'FUNCTION' or $href->{content} eq 'SUBROUTINE') {
+      $_=$href->{statement};
+      @pu_args=();
+      my $dum=&parse_prog_unit(\$func,\@pu_args);   # Get arguments
+      for(@pu_args) {
+	if( exists $$vars{$_} ) {
+	  if($$vars{$_}{scope} == $href->{prog_unit}) {
+	    $$vars{$_}{usage}='arg';
+	  }
+
+	} else {
+          print STDERR "Argument $_ has not got a corresponding declaration " .
+                       "statement\n";
+          print STDERR "Bailing out at this point\n";
+          die "Bailing out";
+	}
+      }
+    }
+# Does the variable appear in a NAMELIST
+# We want to distinguish this for more lenient Doctor check
+    if($href->{content} eq 'NAMELIST') {
+      $_=$href->{statement};
+      s/\!.*\n/\n/g;     # Remove trailing comments in all lines
+      s/\s+//g;          # Remove all white-space
+      m:NAMELIST/\w+/(.+):;
+      my @namvars=split(',',uc($1));
+      for (@namvars) {
+	if( exists $$vars{$_} ) {
+	  if($$vars{$_}{scope} == $href->{prog_unit}) {
+	    $$vars{$_}{usage}='namvar';
+	  }
+	}
+      }
+    }
+    if(exists $href->{inc_statm}) { # We also have to look in include files
+      my $incs=$href->{inc_statm};
+      foreach my $hrefi (@$incs) {
+	if($hrefi->{content} eq 'NAMELIST') {
+	  $_=$hrefi->{statement};
+	  s/\!.*\n/\n/g;     # Remove trailing comments in all lines
+	  s/\s+//g;          # Remove all white-space
+	m:NAMELIST/\w+/(.+):;
+	  my @namvars=split(',',uc($1));
+	  for (@namvars) {
+	    if( exists $$vars{$_} ) {
+	      if($$vars{$_}{scope} == $href->{prog_unit}) {
+		$$vars{$_}{usage}='namvar';
+	      }
+	    }
+	  }
+	}
+      }
+    }
+  }
+# -----------------------------------------------------------------------------
+# Find use variables
+  my %use_count=();
+  foreach $href (@$statements) {
+    if($href->{content} eq 'USE') {
+      $prog_unit=$href->{prog_unit};
+      $_=$href->{statement};
+      s/\!.*\n/\n/g;                               # Remove trailing comments in all lines
+      s/\s+//g;                                    # Remove all white-space
+      $_=uc($_);                                   # Upcase to avoid /.../i
+      if(/^USE($name),ONLY:(.+)$/){
+	my $modname=$1;
+	if( exists $use_count{$modname}) {
+	  if($prog_unit == $use_count{$modname}) {
+	    print STDERR "-> $href->{statement}";
+            print STDERR "USE $modname appears more than once in program unit $prog_unit \n\n";
+
+	  }
+	}
+	$use_count{$modname} = $prog_unit;
+	my @usevars = split /,/ ,$2;
+	my %usevars=();
+	foreach my $usevar (@usevars) {
+	  $usevars{$usevar}++;
+	  $$use_vars{$usevar}{module}=$modname;
+	  $$use_vars{$usevar}{scope}=$prog_unit;
+	  $$use_vars{$usevar}{count}++;
+	}
+	foreach my $usevar (keys (%usevars)) {
+	  if($usevars{$usevar} >1) {
+	    print STDERR "DUPLICATE USE ONLY VARIABLE ",
+	    "$modname $usevar $prog_unit \n";
+	    $_=$href->{statement};
+	    s/\b$usevar\b//i;
+	    s/,\s*,/,/;
+	    s/,\s*\n$/\n/;
+	    s/\n *\n/\n/;
+	    s/^(.+:\s*),/$1/;
+	    $href->{statement}=$_;
+	  }
+	}
+      }
+      else {
+#	print "WARNING:USE without ONLY \n";
+      }
+    }
+  }
+}
+#==========================================================================
+sub find_unused_vars {
+# Find declared variables not used
+  my($statements,$vars,$unused_vars,$use_vars,$unused_use_vars) = @_;
+  my ($var,@tokens,$href);
+  @tokens=();
+# Find all tokens in file
+  foreach $href (@$statements) {
+    next if($href->{content} eq 'comment');
+    if(exists $href->{inc_statm}) {  # Look also in include files
+      my $incs=$href->{inc_statm};
+      foreach my $hrefi (@$incs) {
+	die "FUV $href->{content} $href->{statement}" unless exists $hrefi->{statement};
+	$_=$hrefi->{statement};
+	if(/\b[a-zA-Z]\w*\b/) {
+	  push(@tokens,/\b[a-zA-Z]\w*\b/g);
+	}
+      }
+    }
+    else {
+      $_=$href->{statement};
+      push(@tokens,/\b[a-zA-Z]\w*\b/g);
+    }
+  }
+  @tokens= map {uc} @tokens; # Upcase array of tokens, the variables are upper-case
+
+# Find out how many times the variable appears in array tokens
+  foreach $var (keys (%$vars)) {
+    $$vars{$var}{uses}=0;
+  }
+  foreach $var (keys (%$use_vars)) {
+    $$use_vars{$var}{uses}=0;
+  }
+  for (@tokens) {
+    if(exists($$vars{$_})){
+      $$vars{$_}{uses}++; 
+    }
+    if(exists($$use_vars{$_})){
+      $$use_vars{$_}{uses}++; 
+    }
+  }
+# If it appears only one time (which must be in a declaration) it is unused
+  @$unused_vars=();
+  foreach $var (keys (%$vars)) {
+    push(@$unused_vars,$var) if($$vars{$var}{uses} < 2);
+  }
+  @$unused_use_vars=();
+  foreach $var (keys (%$use_vars)) {
+    push(@$unused_use_vars,$var) if($$use_vars{$var}{uses} < 2);
+  }
+}
+#==========================================================================
+sub remove_unused_vars {
+# Does what it says on the tin
+  my($statements,$unused_vars,$unused_use_vars) = @_;
+  my ($var,$href);
+  our $nest_par;
+  for (@$unused_vars) {
+    $var=$_;
+    foreach $href (@$statements) {
+      $_=$href->{statement};
+      next unless(($href->{decl}) | ($href->{content} eq 'comment'));
+      if($href->{content} eq 'comment') {
+	next unless(/^ *!\$OMP/);
+      }
+      if(/\b$var\b/i) {
+#	print $_;
+	
+	if(/\b$var\b *\(/i) {
+#	  print "ZYZ $var $_";
+	  s/\b$var\b *$nest_par *(=\s*\(\/.*\/\))*//si;
+#	  print "ZZZ $var $_";
+	}
+	s/\b$var\b\s*=\s*\d+(\.\d*)*//i;
+	s/\b$var\b *(\* *\d+)*//i if($href->{content} eq 'CHARACTER') ;
+	s/\b$var\b//i; 
+#	print $_;
+        s/^.+:: *\n$//;
+        s/^.+:: *\!.*\n$//;
+#	print $_;
+        s/,\s*,/,/;
+#	print $_;
+	s/, *\n$/\n/;
+#	print $_;
+        s/(::\s*),(.+)$/$1$2/s;
+        s/\n *\n/\n/;
+        s/\n *!.*\n/\n/;
+	s/, *\n$/\n/;
+# Remove "empty" lines
+        s/^.+::\s*$//;
+        s/^.+::\s*=.*$//;
+        s/^.+::\s*!.*$//;
+#	print $_;
+        s/^CHARACTER *\*\d+ *\n$//i if($href->{content} eq 'CHARACTER') ;
+	$href->{statement}=$_;
+      }
+    }
+  }
+  for (@$unused_use_vars) {
+    $var=$_;
+    foreach $href (@$statements) {
+      next unless($href->{decl} == 4);
+      $_=$href->{statement};
+      next if(/PARKIND/); #I am sure this could be done betterh
+
+      if(/\b$var\b/i) {
+	s/\b$var\b//i;
+        s/,\s*,/,/;
+        s/,\s*\n$/\n/;
+        s/\n *\n/\n/;
+	s/^(.+:\s*),/$1/;
+	s/^.+:\s*$//;
+	$href->{statement}=$_;
+      }
+    }
+  }
+}
+#==========================================================================
+sub tidy_decl {
+# Tidy up declarions
+  my($statements) = @_;
+  my($href,$content);
+
+  foreach $href (@$statements) {
+    next unless($href->{decl} == 2);
+    $_=$href->{statement};
+    $content=$href->{content};
+    
+    if($content eq 'CHARACTER') {
+      s/CHARACTER *\* *(\w+)/CHARACTER \(LEN = $1\)/i; 
+      s/CHARACTER *\* *\(\*\)/CHARACTER \(LEN = \*\)/i;
+      s/CHARACTER *\* *\( *(\w+) *\)/CHARACTER \(LEN = $1)/i;
+    }
+    if($content eq 'INTEGER') {
+      if(/^ *INTEGER[^\(]/i) {
+	s/INTEGER\b/INTEGER(KIND=JPIM)/;
+      }
+    }
+    unless (/::/) {
+      s/^( *LOGICAL )/$1:: /i;
+      s/^( *INTEGER\(KIND=JPI\w\) )/$1:: /;
+      s/^( *REAL\(KIND=JPR\w\) )/$1:: /;
+      if(/^ *CHARACTER/i) {
+	if( s/^( *CHARACTER *\( *LEN *= *\w+ *\))/$1 :: /i) {
+	  $href->{statement}=$_;
+	  next;
+	}
+	if(s/^( *CHARACTER *\( *LEN *= *\* *\))/$1 :: /i) {
+	  $href->{statement}=$_;
+	  next;
+	}
+	s/^( *CHARACTER )/$1:: /i;
+      }
+    }
+    $href->{statement}=$_;
+  }
+}
+#==========================================================================
+
+sub doctor_viol {
+# Find Doctor violations
+
+  my($vars,$fix_doc) = @_;
+  my ($var,$type,$zz,$prog_unit,$usage);
+  %$fix_doc=();
+
+  foreach $var (keys (%$vars)) {
+    $type=$$vars{$var}{type_spec};
+    $prog_unit=$$vars{$var}{scope};
+    $usage=$$vars{$var}{usage};
+#    print "DOC $var $type $prog_unit $usage \n";
+    if($zz=&doc_char($type,$usage,$var)) {
+#      print "DOCTOR VIOL - ",$var," $type $zz $prog_unit\n";
+      $$fix_doc{$var}=$zz.'_'.$var.','.$prog_unit
+    }
+  }  
+}
+#==========================================================================
+
+sub fix_doctor_viol {
+# Fix Doctor violations
+  my($statements,$fix_doc) = @_;
+  my($doc_viol,$repl,$prog_unit,$cur_prog_unit,@allowed,$href,$content);
+  my($tmp_name,@pu_args);
+
+  @allowed=('NRGRI'); # Hack
+
+  VIOL:foreach $doc_viol (keys (%$fix_doc)) {
+    # Let's allow some violations
+    for (@allowed){ 
+      next VIOL if($doc_viol eq $_);
+    }
+
+    ($repl,$prog_unit)=split(',',$$fix_doc{$doc_viol});
+
+    print "FIX $repl $prog_unit \n";
+    foreach $href (@$statements) {
+      $content=$href->{content};
+      $_=$href->{statement};
+      if($href->{content} eq 'comment') {
+	next unless(/^ *!\$OMP/);
+      }
+      $cur_prog_unit=$href->{prog_unit};
+      if($prog_unit == $cur_prog_unit) {  # Could be fine in other program units
+	if(/\b$doc_viol\b/i) {
+	  s/%$doc_viol\b/_X_$doc_viol/ig; # Protect type-components
+	  s/\b$doc_viol\b/$repl/ig;
+	  s/_X_$doc_viol\b/%$doc_viol/ig; # Restore type-components
+	}
+      }
+      $href->{statement}=$_;
+    }
+  }
+  
+}
+#==========================================================================
+sub various{
+# 
+  my($statements,$prog_info,$vars) = @_;
+  my($punit,@args,$tmp_name,$cont,$statm);
+  my($href,$exec);
+  our $nest_par;
+#------------------------------------------------------------------
+# Remove unneccesary RETURN statement
+  foreach $href (@$statements) {
+    $cont=$href->{content};
+    if($cont eq 'RETURN') {
+      if($href->{exec} == 3) {   # $href->{exec} == 3 means last executable statement
+	$href->{remove} = 1;     # Post remove line for later
+      }
+    }
+  }
+
+
+# Make sure all CALL MPL_... has a CDSTRING argument
+  foreach $href (@$statements) {
+    $cont=$href->{content};
+    if($href->{content} eq 'CALL' ) {
+      $_=$href->{statement};
+      if(/^\s*CALL\s+MPL_/i) {
+	next if(/^\s*CALL\s+MPL_ABORT/i);
+	next if(/^\s*CALL\s+MPL_WRITE/i);
+	next if(/^\s*CALL\s+MPL_READ/i);
+	next if(/^\s*CALL\s+MPL_OPEN/i);
+	next if(/^\s*CALL\s+MPL_CLOSE/i);
+	next if(/^\s*CALL\s+MPL_INIT/i);
+	next if(/^\s*CALL\s+MPL_GROUPS_CREATE/i);
+	next if(/^\s*CALL\s+MPL_BUFFER_METHOD/i);
+	next if(/^\s*CALL\s+MPL_IOINIT/i);
+	next if(/^\s*CALL\s+MPL_CART_COORD/i);
+#	print "CDSTRING=$$prog_info{'unit_name'}[$href->{prog_unit}]: \n";
+	unless(/CDSTRING\s*=/i) {
+	  s/\)(\s)$/,CDSTRING=\'$$prog_info{'unit_name'}[$href->{prog_unit}]:\'\)$1/;
+	  $href->{statement}=$_;
+	}
+      }
+    }
+  }
+	
+
+
+#------------------------------------------------------------------
+# Add Standard Modification Line
+
+  my $start=0;
+  foreach $href (@$statements) {
+    $cont=$href->{content};
+    if($cont eq 'comment') {
+      $_=$href->{statement};
+      if($start) {                        # Found header - look for end of mod lines
+	if(/^ *$/ || /^! *------------------------/) {
+	  $href->{pre_insert} = "!        M.Hamrud      01-Oct-2003 CY28 Cleaning\n";
+	  last;
+	}
+	next;
+      }
+      $start=1 if(/^! +Modifications/i) ;  # This how the header should look
+      next;
+    }
+    last if($href->{exec});                # We have failed - bail out
+  }
+
+# Change subroutine and call multi-line statements so that the comma
+# beetwen variables comes at the end of the line
+  my @lines=();
+  foreach $href (@$statements) {
+    if(exists $href->{multi_line}) {
+      $cont=$href->{content};
+      if($cont eq 'SUBROUTINE' | $cont eq 'CALL' ) {
+	$statm=$href->{statement};
+	@lines=split "\n", $statm;
+	@lines = reverse @lines;
+	my $append_comma=0;
+	for (@lines) {
+#	  print "A $append_comma $_ \n";
+	  next if(/^ *!/);
+	  if($append_comma) {
+	    if(/\S *!.*$/) {
+	      s/(\S)( *!.*)$/$1,$2/;
+	    }
+	    else {
+	      s/(\S) *$/$1,/;
+	    }
+	  }
+	  $append_comma=s/^ *,//;
+#	  print "B $append_comma $_ \n";
+	}
+	@lines = reverse @lines;
+	$statm=join  "\n",@lines;
+	$statm=$statm."\n";
+	$href->{statement}=$statm;
+      }
+    }
+  }
+  our $name;
+  foreach $href (@$statements) {
+    if($href->{content} eq 'USE') {
+      $_=$href->{statement};
+      unless(/^\s*USE\s+$name\s*,\s*ONLY\s*:/i){
+	print $_;
+	print "WARNING:USE without ONLY \n";
+      }
+    }
+  }    
+}
+#==========================================================================
+sub insert_hook{
+# 
+  my($statements,$prog_info,$vars) = @_;
+  my($punit,@args,$tmp_name,$cont,$statm);
+  my($href,$exec);
+  our $nest_par;
+#------------------------------------------------------------------
+# Add HOOK function
+  my $unit_name='';
+  my $last_use=0;
+  my $hook_status=0;
+  my $in_contain=0;
+  my $prev_prog=0;
+  my ($decl,$remember);
+  foreach $href (@$statements) {
+    $cont=$href->{content};
+    next if($cont eq 'comment');
+
+    $decl=$href->{decl};
+    $exec=$href->{exec};
+    $in_contain=$href->{in_contain};
+    if(! $in_contain and $href->{prog_unit} > $prev_prog) {
+      $hook_status=0;
+      $prev_prog=$href->{prog_unit};
+      print "resetting hook status \n";
+    }
+
+    if($cont eq 'FUNCTION' or $cont eq 'SUBROUTINE' or 
+       $cont eq 'PROGRAM'){ # Need name of routine
+      $_=$href->{statement};
+      &parse_prog_unit(\$unit_name,\@args);
+      $unit_name=uc($unit_name);
+# If in module pre-pend module name
+      $unit_name=$$prog_info{module_name}.':'.$unit_name if($$prog_info{is_module}); 
+      $remember=0;
+    }
+
+    if($hook_status == 0) {   # $hook_status == 0 means we have not done anything yet
+      if($cont eq 'USE') {    # Add USE YOMHOOK as second use statement
+	$href->{post_insert}="USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK\n";
+	$hook_status=1;
+      }
+      elsif($cont eq 'IMPLICIT NONE') { # No previous USE, add USE YOMHOOK before IMPLICIT NONE
+	$href->{pre_insert} ="USE PARKIND1  ,ONLY : JPRB\n".
+	  "USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK\n";
+	$hook_status=1;
+      } 
+    }
+    $remember=$href->{number} if($decl == 2); 
+
+#   Use statement added ($hook_status == 1), now insert HOOK switch on statement
+#   before first executable statement in program unit ($exec == 2)
+    if($hook_status == 1 && $exec == 2) {
+      if($remember) {
+	$$statements[$remember]->{post_insert}="REAL(KIND=JPRB) :: ZHOOK_HANDLE\n";
+	$href->{pre_insert}="IF (LHOOK) CALL DR_HOOK(\'${unit_name}\',0,ZHOOK_HANDLE)\n";
+      }
+      else {
+	$href->{pre_insert}="REAL(KIND=JPRB) :: ZHOOK_HANDLE\n".
+	    "IF (LHOOK) CALL DR_HOOK(\'${unit_name}\',0,ZHOOK_HANDLE)\n";
+      }   
+      if($cont eq 'IF') {
+	if($href->{content2} eq 'RETURN') {
+	  $_=$href->{statement};
+	  s/(\s*IF\s*$nest_par).*\n/$1/i;
+	  s/\)$/ .AND. LHOOK\)/;
+	  $href->{pre_insert}=$href->{pre_insert}."$_ CALL DR_HOOK(\'${unit_name}\',1,ZHOOK_HANDLE)\n";
+	}
+      }
+      $hook_status=2;
+    }
+#   Hook switched on($hook_status == 2), switch off after last executable statement
+#   ($exec == 3)
+    elsif($hook_status == 2) {
+      if($exec == 3 or $exec == 23) {
+	$href->{post_insert}="IF (LHOOK) CALL DR_HOOK(\'${unit_name}\',1,ZHOOK_HANDLE)\n";
+	$hook_status=3;
+      }
+      elsif($cont eq 'RETURN') {
+	$href->{pre_insert}="IF (LHOOK) CALL DR_HOOK(\'${unit_name}\',1,ZHOOK_HANDLE)\n";
+      }
+      elsif($cont eq 'IF') {
+	if($href->{content2} eq 'RETURN') {
+	  $_=$href->{statement};
+	  s/(\s*IF\s*$nest_par).*\n/$1/i;
+	  s/\)$/ .AND. LHOOK\)/;
+	  $href->{pre_insert}="$_ CALL DR_HOOK(\'${unit_name}\',1,ZHOOK_HANDLE)\n";
+	}
+      }	
+    }
+    $hook_status=1 if($in_contain && $hook_status==3); # Reset hook status in CONTAIN region
+  }
+  die "Adding HOOK function failed " if($hook_status == 2);
+}
+#==========================================================================
+
+sub doc_char{
+# Returns suggested prefix in case of DOCTOR violation (otherwise null string)
+  my($type,$usage,$var) = @_;
+  my $prefix="";
+# INTEGER variables
+  if( $type eq "i") {
+    if($usage eq "arg") {
+      $prefix="K" unless($var=~/^K/i);
+    }
+    elsif($usage eq "local") {
+      $prefix="I" unless($var=~/^[IJ]/i);
+    }
+    elsif($usage eq "module") {
+      $prefix="N" unless($var=~/^[MN]/i);
+    }
+    elsif($usage eq "namvar") {
+      $prefix="I" unless($var=~/^[MNIJ]/i);
+    }
+    else { 
+      die "Unknown usage";
+    }
+  }
+# REAL variables
+  elsif( $type eq "r") {
+    if($usage eq "arg") {
+      $prefix="P" unless($var=~/^P/i);
+    }
+    elsif($usage eq "local") {
+      $prefix="Z" unless($var=~/^Z|^PP/i);
+    }
+    elsif($usage eq "module") {
+      $prefix="R" if ($var=~/^[ZPIJKLMNCY]/i);
+    }
+    elsif($usage eq "namvar") {
+      $prefix="Z" if ($var=~/^[PIJKLMNCY]/i);
+    }
+    else { 
+      die "Unknown usage";
+    }
+  }
+#LOGICAL variables
+  elsif( $type eq "l") {
+    if($usage eq "arg") {
+      $prefix="LD" unless($var=~/^LD/i);
+    }
+    elsif($usage eq "local") {
+      $prefix="LL" unless($var=~/^LL/i);
+    }
+    elsif($usage eq "module") {
+      $prefix="L" unless($var=~/^L[^LD]/i);
+    }
+    elsif($usage eq "namvar") {
+      $prefix="LL" unless($var=~/^L/i);
+    }
+    else { 
+      die "Unknown usage";
+    }
+  }
+#CHARACTER variables
+  elsif( $type eq "c") {
+    if($usage eq "arg") {
+      $prefix="CD" unless($var=~/^CD/i);
+    }
+    elsif($usage eq "local") {
+      $prefix="CL" unless($var=~/^CL/i);
+    }
+    elsif($usage eq "module") {
+      $prefix="C" unless($var=~/^C[^LD]/i);
+    }
+    elsif($usage eq "namvar") {
+      $prefix="CL" unless($var=~/^C/i);
+    }
+    else { 
+      die "Unknown usage";
+    }
+  }
+# USER DEFINED TYPES
+  elsif( $type eq 't') {
+    if($usage eq "arg") {
+      $prefix="YD" unless($var=~/^YD/i);
+    }
+    elsif($usage eq "local") {
+      $prefix="YL" unless($var=~/^YL/i);
+    }
+    elsif($usage eq "module") {
+      $prefix="Y" unless($var=~/^Y[^LD]/i);
+    }
+    elsif($usage eq "namvar") {
+      $prefix="YL" unless($var=~/^Y/i);
+    }
+    else { 
+      die "Unknown usage";
+    }
+  }
+# FUNCTION/EXTERNAL declarations
+  elsif( $type eq 'f' || $type eq 'e' || $type eq 's') {
+# Everything is OK
+  }
+  else {
+    die "Unknown type $type"
+  }
+  ($prefix);
+}
+#==========================================================================
+     
+sub parse_prog_unit {
+  # Find out type (return), name ($$unit_name) and arguments (@$args)
+  # from a program unit statement ($_)
+  my ($unit_name, $args) = @_;
+  $$unit_name = '';
+  @$args      = ();
+
+  my $type = '';
+
+  our ($name, $type_spec, $attribute);
+
+  if (/^\s*(MODULE|PROGRAM|BLOCK\s*DATA)\s+($name)\s*$/io) {
+    $type       = lc ($1);
+    $$unit_name = $2;
+
+    # Remove space from "block data"
+    $type       =~ s/\s*//;
+
+  } elsif (/^\s*(?:$attribute)?\s*(SUBROUTINE)\s+($name)\b/io or
+           /^\s*(?:$attribute)?\s*(?:$type_spec)?\s*(FUNCTION)\s+($name)\b/io) {
+    $type       = lc ($1);
+    $$unit_name = $2;
+
+    # Get arguments/keywords from SUBROUTINE/FUNCTION
+    if(/^[^\(]+\([^\)]+\)/) {
+      my $tstatm = $_;
+
+      # Remove trailing comment
+      $tstatm =~ s/\!.*\n/\n/g;
+
+      # Remove space characters
+      $tstatm =~ s/\s//g;
+
+      # Add the RESULT clause to the argument/keyword list
+      $tstatm =~ s/\)result\((\w+\))$/,$1/i if $type eq 'function';
+
+      # Remove the parenthesis around the argument list
+      $tstatm =~ s/.+\((.+)\)/$1/;
+
+      @$args = split (',', uc ($tstatm));
+
+      # For FUNCTION, add its name to the list if necessary
+      push @$args, uc ($$unit_name)
+        if $type eq 'function' and not grep {$_ eq uc ($$unit_name)} @$args;
+    }
+  }
+
+  return $type;
+}
+
+#==========================================================================
+
+sub setup_parse {
+  # Set up some "global" variables that helps with parsing statements
+
+  # Pattern for nested parenthesis
+  our $nest_par;
+  $nest_par = qr/\((?:(?>[^()]+)|(??{$nest_par}))*\)/; #Camel p214
+
+  # Patterns for variable name and natural digit
+  our $name='[a-zA-Z]\w*';
+  our $digit_string='\d+';
+  our $type_name=$name;
+
+  # Patterns for specification
+  our $specification_expr='(?:'.$name.'|'.$digit_string.')'; # Simplification
+  our $type_param_value='(?:\*|'.$specification_expr.')';
+
+  # Patterns for length/kind attributes
+  our $char_selector='LEN *= *'.$type_param_value; # Simplification
+  our $kind_selector='\( *KIND *= *'.$name.' *\)';    # Simplification
+
+  # Pattern for type specification
+  our $type_spec='INTEGER *(?:'.$kind_selector.')?|REAL *(?:'.$kind_selector.
+    ')?|DOUBLE PRECISION|COMPLEX *(?:'.$kind_selector.')?|CHARACTER *'.
+    $char_selector.'|LOGICAL *(?:'.$kind_selector.')?|TYPE\s*\(\s*'.$type_name.
+    '\s*\)';
+
+  # Pattern for function/subroutine attribute
+  our $attribute = 'ELEMENTAL|(?:RECURSIVE(?:\s+PURE)?|PURE(?:\s+RECURSIVE)?)';
+
+  return;
+}
+
+#==========================================================================
+
+sub f90_indent {
+# Indent free-format F90 program to our standards
+  my($line_hash,$lines)=@_;
+  my($delta)='  '; 
+  my($cur_indent)='';
+  @$lines=();
+  foreach my $href (@$line_hash) {
+    $_=$href->{line};
+    if($href->{content} eq 'comment') {
+      push(@$lines,$_);
+      next;
+    }
+    s/^ *//; # Remove current indentation
+    my($post_chg)=0;
+    my($pre_chg)=0;
+    my($cont_line)='';
+    exit if (! exists $href->{content});
+    if($href->{content} eq 'DO') {
+      $post_chg=1 unless /^DO\s+\d/;
+    }
+    elsif($href->{content} eq 'ENDDO') {
+      $pre_chg=1;
+    }
+    elsif($href->{content} eq 'IF_construct') {
+      $post_chg=1;
+    }
+    elsif($href->{content} eq 'ELSEIF') {
+      $post_chg=1;
+      $pre_chg=1;
+    }
+    elsif($href->{content} eq 'ELSE') {
+      $post_chg=1;
+      $pre_chg=1;
+    }
+    elsif($href->{content} eq 'ENDIF') {
+      $pre_chg=1;
+    }
+    elsif($href->{content} eq 'ENDIF') {
+      $pre_chg=1;
+    }
+    elsif($href->{content} eq 'WHERE_construct') {
+      $post_chg=1;
+    }
+    elsif($href->{content} eq 'ELSEWHERE') {
+      $post_chg=1;
+      $pre_chg=1;
+    }
+    elsif($href->{content} eq 'ENDWHERE') {
+      $pre_chg=1;
+    }
+    elsif($href->{content} eq 'ENDIF') {
+      $pre_chg=1;
+    }
+    elsif($href->{content} eq 'SELECT CASE') {
+      $post_chg=1;
+    }
+    elsif($href->{content} eq 'CASE') {
+      $post_chg=1;
+      $pre_chg=1;
+    }
+    elsif($href->{content} eq 'END SELECT') {
+      $pre_chg=1;
+    }
+    $cont_line=' ' if($href->{content} eq 'cont_line');
+    if( $pre_chg ) {
+      unless($cur_indent=~s/^$delta//o) {
+	print STDERR $_;
+	die  "f90_indent: something wrong, indent negative\n";;
+      }
+    }
+#    print "$cur_indent$cont_line$_";
+    
+    $_=$cur_indent.$cont_line.$_;
+    push(@$lines,$_);
+    $cur_indent.=$delta if( $post_chg );
+  }
+
+  if(! ($cur_indent eq '')) {
+    die "f90_indent: something wrong, indent=XX${cur_indent}XX\n";
+  }
+}
+
+#==========================================================================
+
+sub tidy {
+# Straigthforward tidiyng of statements
+  my($statements) = @_;
+  my($href,$content);
+  foreach $href (@$statements) {
+    $_=$href->{statement};
+    $content=$href->{content};
+# Substitute tab with four blanks
+    s/\t/    /g;
+    if($content eq 'comment') {
+# Substitute empty comment line with empty line
+      s/^[!] *\n$/\n/;
+      $href->{statement}=$_;
+      next;
+    }
+    if($href->{exec}) {
+      if($content eq 'ENDDO') {
+	s/\bEND DO\b/ENDDO/i;
+	$href->{statement}=$_;
+	next;
+      }
+      if($content eq 'ENDIF') {
+	s/\bEND IF\b/ENDIF/i;
+	$href->{statement}=$_;
+	next;
+      }
+      if($content eq 'ENDWHERE') {
+	s/\bEND WHERE\b/ENDWHERE/i;
+	$href->{statement}=$_;
+	next;
+      }
+
+      s/\bELSE IF\b/ELSEIF/i  if($content eq 'ELSEIF');
+
+      if(/\./) {
+	s/ *\.EQ\. */ == /gi;
+	s/ *\.NE\. */ \/= /gi;
+	s/ *\.LT\. */ < /gi;
+	s/ *\.LE\. */ <= /gi;
+	s/ *\.GT\. */ > /gi;
+	s/ *\.GE\. */ >= /gi;
+      }
+
+#
+      s/\bA?MAX[01]\b/MAX/gi;
+      s/\bA?MIN[01]\b/MIN/gi;
+      s/\bAMOD\b/MOD/gi;
+      s/\bALOG\b/LOG/gi;
+      s/\bALOG10\b/LOG10/gi;
+#      s/\bI(SIGN *\()/$1/gi; # Goes wrong in larcinad etc.
+      s/\bFLOAT\b/REAL/g;
+      s/\bfloat\b/real/g;
+    }
+    
+    $href->{statement}=$_;
+  }
+}
+
+#==========================================================================
+
+sub process_include_files {
+# Read include files and put reference to the anonomys array
+# holding the array of "statement" hashes in $href->{inc_statm}
+  my($statements,$prog_info,$inc_statements) = @_;
+  my ($content,$fname,$href);
+  return unless ($$prog_info{has_include});
+  my @lines=();
+  foreach $href (@$statements) {
+    $content=$href->{content};
+    if($content eq 'include'){
+      $_=$href->{statement};
+      /["](\S+)["]/;
+      $fname=$1;
+      &get_inc_lines($fname,\@lines);
+# Macro-removal
+      &remove_macro(\@lines);
+# Expand lines into statements and put refernce to this
+# array of hashes into $href->{inc_statm}
+      my @inc_statms=();
+      my $dum={};
+      &expcont(\@lines,\@inc_statms);
+      $href->{inc_statm}=[@inc_statms];
+      my $incs=$href->{inc_statm};
+# Study the read in file and add more attributes
+      &study($incs);
+#      print Dumper($incs,$dum);
+      
+    }
+  }
+}
+#==========================================================================
+sub get_inc_lines{
+# Recurcivly get lines from include files, flatten into array of lines
+  my ($fname,$lines) = @_;
+  my ($VPATH,@vpath,@tmp_lines);
+
+  $VPATH=$ENV{VPATH} or die "VPATH not defined ";
+# IFS VPATH /tmp/27/ifs/function:/tmp/27/ifs/common:/tmp/27/ifs/interface:/tmp/27/ifs/namelist:/tmp/27/ifsaux/include:/tmp/27/trans/interface:/tmp/27/obsort/interface:/tmp/27/ifs/ald_inc/function:/tmp/27/ifs/ald_inc/interface:/tmp/27/ifs/ald_inc/namelist
+  @vpath=split(":",$VPATH);
+# Look for include file in VPATH
+  foreach my $path (@vpath) {
+    my $ffname=$path.'/'.$fname;
+    if( -f $ffname) {
+# Read lines from include file
+      @tmp_lines = &readfile($ffname);
+#      print "$ffname \n";
+      for (@tmp_lines) {
+	if(/^\#include\b/){
+	  /["](\S+)["]/;
+	  my $fname2=$1;
+	  &get_inc_lines($fname2,$lines);
+	}
+	else {
+	  push(@$lines,$_);
+	}
+      }
+      last;
+    }
+  }
+  die "Include file $fname not found in VPATH=$VPATH " unless(@$lines);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &create_interface_block (\@statements, \@interface_block);
+#
+# DESCRIPTION
+#   This function analyses the Fortran statements in \@statements and returns
+#   an interface block in \@interface_block.
+# ------------------------------------------------------------------------------
+
+sub create_interface_block {
+  # Create a "minimal" interface block for subroutines
+  my  ($statements, $interface_block) = @_;
+  my  (%pu_args, %tokens);
+  our ($name, $nest_par);
+
+  @$interface_block = ();
+
+  my @tokens_in_lines = (); # List of tokens in each line
+
+  # Gather information needed to create interface block for routine
+  for my $href (@$statements) {
+    last if $href->{exec}; # exit loop at beginning of executable statements
+
+    # Get arguments of subroutine or function
+    if ($href->{content} eq 'SUBROUTINE' or $href->{content} eq 'FUNCTION') {
+      my $func;
+      my @pu_args;
+      $_ = $href->{statement};
+      &parse_prog_unit (\$func, \@pu_args);
+      $pu_args{uc ($_)} = 1 for @pu_args;
+      next;
+    }
+
+    # Get tokens from lines where arguments are present
+    # Inspect only type declaration statements
+    next unless $href->{decl} == 2;
+
+    my $statement = uc $href->{statement};
+    $statement =~ s/!.*$//; # Remove trailing comment
+
+    my @line_tokens = ();
+    if ($statement =~ s/^(.*?):://) {
+      # New style declaration statement contains "::"
+
+      # Tokens in specification part
+      my $spec = $1;
+      my @tokens = ($spec =~ /\b$name\b/g);
+      shift @tokens; # Remove leading token
+
+      for (@tokens) {
+        push @line_tokens, $_
+          unless /^(?:KIND|LEN|ALLOCATABLE|POINTER|TARGET|DIMENSION|OPTIONAL|
+                  SAVE|INTENT|IN|OUT|INOUT|PARAMETER)$/x;
+      }
+
+      # Tokens in declaration part
+      push @line_tokens, ($statement =~ /\b$name\b/g);
+
+    } else {
+      # Old style declaration statement does not contain "::"
+      @line_tokens = ($statement =~ /\b$name\b/g);
+      shift @line_tokens; # Remove leading token
+    }
+
+    push @tokens_in_lines, \@line_tokens;
+
+    # Check whether each token matches an argument
+    for my $token (@line_tokens) {
+      if (exists $pu_args{$token}) {
+        $tokens{$_} = 1 for @line_tokens;
+        last;
+      }
+    }
+  }
+
+  # Parse statements one more time to ensure all required tokens are included
+  for (@tokens_in_lines) {
+    my @line_tokens = @{ $_ };
+
+    # Check whether line contains an essential token
+    for my $token (@line_tokens) {
+      if (exists $tokens{$token}) {
+        $tokens{$_} = 1 for @line_tokens;
+        last;
+      }
+    }
+  }
+
+  # Create the interface block
+  for my $href (@$statements) {
+    my %myhref  = %$href;
+    my $content = $myhref{content};
+
+    # Ignore comment, executable statements and items in CONTAINS block
+    next if $content eq 'comment';
+    next if $myhref{exec};
+    next if $myhref{in_contain};
+
+    # Delete existing pre- and post -inserts
+    delete $myhref{pre_insert}  if exists $myhref{pre_insert};
+    delete $myhref{post_insert} if exists $myhref{post_insert};
+
+    # Put SUBROUTINE/FUNCTION statement into interface block
+    if ($content =~ /^(?:SUBROUTINE|FUNCTION)$/) {
+      $myhref{pre_insert} = 'INTERFACE' . "\n"; # Insert INTERFACE statement
+      push @$interface_block, \%myhref;
+    }
+
+    # Add USE statement in interface block, if necessary
+    if($myhref{decl} == 4) {
+      $_ = uc $myhref{statement};
+      tr/ \n//d;
+
+      if(/^USE$name,ONLY:(.+)$/) {
+        # USE statement with ONLY, check token to see if it is necessary
+	my @line_tokens = /\b$name\b/g;
+
+	for (@line_tokens) {
+	  if (exists $tokens{$_}) {
+	    push @$interface_block, \%myhref;
+	    last;
+	  }
+	}
+
+      } else {
+        # Always add USE statement without ONLY
+	push @$interface_block, \%myhref;
+      }  
+    }
+
+    if ($myhref{decl} == 1 or $myhref{decl} == 2) {
+      $_ = uc ($myhref{statement});
+      s/\s*!.*$//;
+
+      if ($content eq 'INTEGER' or $content eq 'PARAMETER') {
+        # INTEGER and PARAMETER may be used for dimensioning
+	my @line_tokens = /\b$name\b/g;
+
+	for (@line_tokens) {
+	  if (exists $tokens{$_}) {
+	    push @$interface_block, \%myhref;
+	    last;
+	  }
+	}
+      } else {
+        # Add line only if an argument is present
+	s/$nest_par//g;
+	my @line_tokens = /\b$name\b/g;
+
+	for (@line_tokens) {
+	  if (exists $pu_args{$_}) {
+	    push @$interface_block, \%myhref;
+	    last;
+	  }
+	}
+      }
+    }
+
+    # Add END statement to interface block
+    if ($content =~ /^END\s+(?:SUBROUTINE|FUNCTION)/) {
+      $myhref{post_insert} = 'END INTERFACE' . "\n";
+      push @$interface_block, \%myhref;
+    }
+  }
+
+  # Beautify the interface block
+  for my $href (@$interface_block) {
+    $_ = $href->{statement};
+
+    s/\!.*\n/\n/g; # Remove trailing comments
+    s/ +/ /g;      # Only one space
+    s/\n *\n/\n/g; # Remove empty lines
+    s/\n *\n/\n/g; # Remove empty lines again
+    s/ +\n/\n/g;   # No trailing spaces
+
+    $href->{statement} = $_;
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+
+sub change_var_names{
+  my($statements) = @_;
+  foreach my $href (@$statements) {
+    $_=$href->{statement};
+    s/\bVAZX\b/YVAZX/ig;
+    s/\bPVAZX\b/YDVAZX/ig;
+    s/\bVAZG\b/YVAZG/ig;
+    s/\bPVAZG\b/YDVAZG/ig;
+    s/\bSCALP_DV\b/YSCALP/ig;
+    s/\bRSCALP_DV\b/YRSCALP/ig;
+    s/\bSCALPSQRT_DV\b/YSCALPSQRT/ig;
+    s/\bRSCALPSQRT_DV\b/YRSCALPSQRT/ig;
+    s/\bPYBAR\b/YDYBAR/ig;
+    s/\bPSBAR\b/YDSBAR/ig;
+    s/\bVCGLPC\b/YVCGLPC/ig;
+    s/\bVCGLEV\b/YVCGLEV/ig;
+    s/\bSKFROT\b/YSKFROT/ig;
+    s/\bSKFMAT\b/YSKFMAT/ig;
+    s/\bSTATE_VECTOR_4D\b/YSTATE_VECTOR_4D/ig;
+    s/\bVAZX0\b/YVAZX0/ig;
+    s/\bVAZG0\b/YVAZG0/ig;
+    s/\bRSPFORCE\b/YSPFORCE/ig;
+    $href->{statement}=$_;
+  }
+}
+# =========================================================================
+sub remake_arg_decl{
+  my($statements,$prog_info) = @_;
+  my($href,$content,@pu_args,$func,%tokens);
+  my($left,$right,%arghash,$dim);
+  our($nest_par,$name);
+
+  my $dims='';
+# Crack existing dummy declarations, build hash arghash
+  foreach $href (@$statements) {
+    last if($href->{prog_unit} >0);
+    if($href->{content} eq 'SUBROUTINE') {   # Get arguments of subroutine
+      $_=$href->{statement};
+      my $dum=&parse_prog_unit(\$func,\@pu_args);
+#      print Dumper(\@pu_args);
+      for(@pu_args) {
+	$_=uc($_);
+	$arghash{$_}{other}='';
+	$arghash{$_}{dimuse}=0;
+	$arghash{$_}{intent}='';
+	$arghash{$_}{used}=0;
+	$arghash{$_}{set}=0;
+	$arghash{$_}{reallyset}=0;
+	$arghash{$_}{type}='';
+	$arghash{$_}{comment}='';
+	$arghash{$_}{inif}=0;
+      }
+      next;
+    }
+    if($href->{decl} == 2) {
+      $_=$href->{statement};
+      my $comment='';
+      $comment=$1 if(/.*(\!.*)$/);
+      s/\!.*\n/\n/g;                        # Remove trailing comments in all lines
+      $_=uc($_);
+      s/\s//g;
+      if(/^(.+)::(.+)$/){
+	$left=$1;
+	$right=$2;
+	$_=$right;
+	s/$nest_par//g;
+	s/($name)\*\w+/$1/g;
+#	print "XX  $_ \n";
+	foreach my $arg (@pu_args) {
+	  if(/\b$arg\b/) {
+#	    print "ARG $arg $left $_ \n";
+	    $arghash{$arg}{linedec}=$href->{number};
+	    $arghash{$arg}{comment}=$comment;
+	    my @locdec =split ',',$left;
+	    my $i=0;
+	    foreach my $locdec (@locdec) {
+	      if($i == 0) {
+		$arghash{$arg}{type}=$locdec;
+	      }
+	      elsif($locdec=~/\bINTENT/) {
+		$arghash{$arg}{intent}=','.$locdec;
+	      }
+	      else {
+		$arghash{$arg}{other}=$arghash{$arg}{other}.','.$locdec;
+	      }
+	      $i++;
+	    }
+	    if($right=~/\b$arg\b(\*\w+)/) {
+	      $dim=$1;
+	    }
+	    elsif($right=~/\b$arg\b($nest_par\*$nest_par)/) {
+	      $dim=$1;
+	    }
+	    elsif($right=~/\b$arg\b($nest_par\*\w+)/) {
+	      $dim=$1;
+	    }
+	    elsif($right=~/\b$arg\b(\*$nest_par)/) {
+	      $dim=$1;
+	    }
+	    elsif($right=~/\b$arg\b($nest_par)/) {
+	      $dim=$1;
+	    }
+	    else {
+	      $dim='';
+	    }
+	    $arghash{$arg}{dim}=$dim;
+	    $dims=$dims.$dim
+	      }
+	}
+	foreach my $arg (@pu_args) {  # Is arg. used for dimensioning other args?
+	  if($dims=~/\b$arg\b/i) {
+	    $arghash{$arg}{dimuse}=1;
+	  }
+	}  
+      }
+    }
+  }
+  my $insert_line=0;
+  foreach $href (@$statements) {
+    last if($href->{prog_unit} >0);
+    if($href->{decl} == 2 or $href->{content} eq 'PARAMETER') {                 
+      $_=uc($href->{statement});
+      next unless /\bPARAMETER\b/;
+      my @tmpvar=/\b$name\b/g;
+      foreach my $token (@tmpvar) {
+	if($dims=~/\b$token\b/) {
+	  $insert_line=$href->{number};
+	}
+      }
+    }
+  }
+      
+# Gather info to decide INTENT status
+  my $inif=0;
+  my @inif_stack=();
+  my $cur_inif=0;
+  foreach $href (@$statements) {
+    last if($href->{prog_unit} >0);
+    if($href->{exec}) {
+      if($href->{content} eq 'ENDIF') {
+	$inif--;
+	$cur_inif=pop @inif_stack;
+	next;
+      }
+      elsif($href->{content} eq 'ELSEIF' or $href->{content} eq 'ELSE') {
+	$cur_inif=pop @inif_stack;
+	$cur_inif=$href->{number};
+	push @inif_stack,$cur_inif;
+      }
+      my ($left,$right);
+      $_=$href->{statement};
+      s/\!.*\n/\n/g;                        # Remove trailing comments in all lines
+      my %setnow=();
+      foreach my $arg (@pu_args) {
+	$setnow{$arg}=0;
+	$setnow{$arg}=1 if($arghash{$arg}{reallyset});
+	unless ($setnow{$arg}) {
+	  foreach my $xx (@inif_stack) {
+	    $setnow{$arg}=1 if($xx == $arghash{$arg}{inif});
+	  }
+	}
+      }
+      
+      if($href->{content} eq 'scal_assign' or $href->{content} eq 'array_assign') {
+	s/\s//g;
+	($left,$right)=/^(.+)=(.+)$/;
+	$_=$right;
+	foreach my $arg (@pu_args) {
+	  if(/\b$arg\b/i) {
+	    $arghash{$arg}{used}=1 unless $setnow{$arg};
+	  }
+	}
+	$_=$left;
+	if(/($nest_par)/) {
+	  $_=$1;
+	  foreach my $arg (@pu_args) {
+	    if(/\b$arg\b/i) {
+	      $arghash{$arg}{used}=1 unless $setnow{$arg};
+	    }
+	  }
+	}
+	$_=$left;
+	foreach my $arg (@pu_args) {
+	  if(/^$arg\b/i) {
+	    $arghash{$arg}{set}=1;
+	    $arghash{$arg}{inif}=$cur_inif;
+	    $arghash{$arg}{reallyset}=1 unless($inif);
+	  }
+	}
+      }
+      elsif($href->{content} eq 'IF' ) {
+	if($href->{content2} eq 'scal_assign' or $href->{content2} eq 'array_assign' or 
+	   $href->{content2} eq 'CALL') {
+	  s/\n//g;
+	  ($left,$right)=/^\s*(IF\b\s*$nest_par)(.+)/i;
+	  $_=$left;
+	  foreach my $arg (@pu_args) {
+	    if(/\b$arg\b/i) {
+	      $arghash{$arg}{used}=1 unless $setnow{$arg};
+	    }
+	  }
+	  $_=$right;
+	  if($href->{content2} eq 'CALL') {
+	    my $statement=$right;
+	    my $inifx=1;
+	    &propag_arg(\$statement,\%arghash,\$inifx,\%setnow);
+	  }
+	  else {
+	    s/\s//g;
+	    ($left,$right)=/^(.+)=(.+)$/;
+	    $_=$right;
+	    foreach my $arg (@pu_args) {
+	      if(/\b$arg\b/i) {
+		$arghash{$arg}{used}=1 unless $setnow{$arg};
+	      }
+	    }
+	    $_=$left;
+	    if(/($nest_par)/) {
+	      $_=$1;
+	      foreach my $arg (@pu_args) {
+		if(/\b$arg\b/i) {
+		  $arghash{$arg}{used}=1 unless $setnow{$arg};
+		}
+	      }
+	    }
+	    $_=$left;
+	    foreach my $arg (@pu_args) {
+	      if(/^$arg\b/i) {
+		$arghash{$arg}{inif}=$cur_inif;
+		$arghash{$arg}{set}=1;
+	      }
+	    }
+	  }
+	}
+	else {
+	  foreach my $arg (@pu_args) {
+	    if(/\b$arg\b/i) {
+	      $arghash{$arg}{used}=1 unless $setnow{$arg};
+	    }
+	  }
+	}
+      }
+      elsif($href->{content} eq 'WHERE' ) {
+	s/\s//g;
+	($left,$right)=/^(WHERE$nest_par)(.+)/i;
+	$_=$left;
+	foreach my $arg (@pu_args) {
+	  if(/\b$arg\b/i) {
+	    $arghash{$arg}{used}=1 unless $setnow{$arg};
+	  }
+	}
+	$_=$right;
+	($left,$right)=/^(.+)=(.+)$/;
+	$_=$right;
+	foreach my $arg (@pu_args) {
+	  if(/\b$arg\b/i) {
+	    $arghash{$arg}{used}=1 unless $setnow{$arg};
+	  }
+	}
+	$_=$left;
+	foreach my $arg (@pu_args) {
+	  if(/^$arg\b/i) {
+	    $arghash{$arg}{inif}=$cur_inif;
+	    $arghash{$arg}{set}=1;
+	  }
+	}
+      }
+      elsif($href->{content} eq 'CALL') {
+	my $statement=$_;
+	&propag_arg(\$statement,\%arghash,\$inif);
+      }
+      else{
+	foreach my $arg (@pu_args) {
+	  if(/\b$arg\b/i) {
+	    $arghash{$arg}{used}=1 unless $setnow{$arg};
+	  }
+	}
+      }
+      if($href->{content} eq 'IF_construct') {
+	$inif++;
+	$cur_inif=$href->{number};
+	push @inif_stack,$cur_inif;
+      }
+    }	  
+  }
+
+# Create INTENT statemant based on gathered info
+  foreach my $arg (@pu_args) {
+    if($arghash{$arg}{linedec}) {
+      if($arghash{$arg}{nointent}) {
+	unless($arghash{$arg}{intent}) {
+	  $arghash{$arg}{intent}=' ';
+	  $arghash{$arg}{comment}='! UNDETERMINED INTENT';
+	}
+      }
+      else{
+	my $intent='';
+	$intent='IN' if($arghash{$arg}{used} or $arghash{$arg}{dimuse});
+	$intent=$intent.'OUT' if($arghash{$arg}{set});
+	if($intent) {
+	  if($arghash{$arg}{intent} and $intent eq 'OUT') {
+	    $intent='INOUT' if $arghash{$arg}{intent}=~/INOUT/i;
+	  }
+	  $arghash{$arg}{intent}=',INTENT('.$intent.')';
+	}
+	else {
+	  $arghash{$arg}{intent}=' ';
+	  $arghash{$arg}{comment}='! Argument NOT used';
+	}
+      }
+    }
+  }
+
+# Remove existing argument declarations
+  foreach my $arg (@pu_args) {
+    if($arghash{$arg}{linedec}) {
+      $_=$$statements[$arghash{$arg}{linedec}]->{statement};
+      #   print "BEFORE $arg $_";
+      if(/.*::\s*\b$arg\b\s*(\!.*\n)*$/i) {
+	$_='';
+      }
+      elsif(/.*::\s*\b$arg\b\s*$nest_par\s*(\!.*\n)*$/i) {
+	$_='';
+      }
+      elsif(/.*::\s*\b$arg\b\s*\*\s*\w+\s*(\!.*\n)*$/i) {
+	$_='';
+      }
+      elsif(/.*::\s*\b$arg\b\s*\*\s*$nest_par\s*(\!.*\n)*$/i) {
+	$_='';
+      }
+      elsif(/.*::\s*\b$arg\b\s*$nest_par\s*\*\s*\w+\s*(\!.*\n)*$/i) {
+	$_='';
+      }
+      elsif(/.*::\s*\b$arg\b\s*$nest_par\s*\*\s*$nest_par\s*(\!.*\n)*$/i) {
+	$_='';
+      }
+      else{
+	/^(.*::)(.*)$/s;
+	my $left=$1;
+	$_=$2;
+	s/\b$arg\b\s*$nest_par//i;
+	s/\b$arg\b\s*\*\s*\w+//i;
+	s/\b$arg\b\s*\*\s*$nest_par//i;
+	s/\b$arg\b//i;
+	s/,\s*,/,/;
+	s/,(\s*)$/$1/;
+	s/\n\s*\n/\n/g;
+	$_=$left.$_;
+	s/::\s*,/::/;
+      }
+ #   print "AFTER $arg $_\n";
+      $$statements[$arghash{$arg}{linedec}]->{statement}=$_; 
+    }
+  }
+
+ # Write out
+
+  my $newdecl='';
+  my $linedec;
+  foreach my $arg (@pu_args) {
+    if($arghash{$arg}{linedec}) {
+      if($arghash{$arg}{other} and ! $arghash{$arg}{dim}) {
+	$arghash{$arg}{other}=~s/\s//g;
+	if($arghash{$arg}{other}=~/^,DIMENSION($nest_par)$/i) {
+	  $arghash{$arg}{other}='';
+	  $arghash{$arg}{dim}=$1;
+	}
+      }
+      if($arghash{$arg}{dimuse}) { # Put declerations of args first
+	$linedec=sprintf "%-18s%s%-14s%s%s%s%s %s",
+	$arghash{$arg}{type},$arghash{$arg}{other},$arghash{$arg}{intent},
+	    ' :: ',$arg,$arghash{$arg}{dim},$arghash{$arg}{comment},"\n";
+	$newdecl=$newdecl.$linedec;
+      }
+    }
+  }
+  foreach my $arg (@pu_args) {
+    if($arghash{$arg}{linedec}) {
+      unless($arghash{$arg}{dimuse}) {
+	$linedec=sprintf "%-18s%s%-14s%s%s%s %s%s",
+	$arghash{$arg}{type},$arghash{$arg}{other},$arghash{$arg}{intent},
+	    ' :: ',$arg,$arghash{$arg}{dim},$arghash{$arg}{comment},"\n";
+	$newdecl=$newdecl.$linedec;
+      }
+    }
+  }
+#  print "INSERT_LINE $insert_line \n";
+  if($insert_line) {
+    $$statements[$insert_line]->{post_insert}=$newdecl;
+  }
+  else{
+    foreach $href (@$statements) {
+      if($href->{decl} == 2) {                 
+	$href->{pre_insert}=$newdecl;
+	last;
+      }
+    }
+  }
+
+#  print $newdecl;
+#  print Dumper(\%arghash);
+}
+
+sub propag_arg{
+  my ($statement,$arghash,$inif,$setnow) = @_;
+  our ($name,$nest_par);
+  my (%argpos);
+  $_=$$statement;
+  s/^\s*CALL\s+($name)//i;
+  my $called=lc($1);
+  s/\s//g;
+  s/^\((.*)\)$/$1/s;
+  my @inpars=/$nest_par/g;
+  s/$nest_par//g;
+  s/($name)%$name/$1/g;
+  $_=uc($_);
+#  print "PROPAG $called $_ ££ @inpars \n";
+  my @call_args=split ',' , $_;
+  my $i=0;
+  my $interesting=0;
+  %argpos=();
+  foreach my $call (@call_args) {
+    
+#    print "CALL $called $call \n" ;
+    if($call=~/(.+)=(.+)/) {
+      $call=$2; #This just by-passes the problem
+    }
+    if(exists $$arghash{$call}) {
+      if(exists $argpos{$call}) {
+	push @{$argpos{$call}},$i;
+      }
+      else {
+	my @i=($i);
+	$argpos{$call}=[@i];
+      }
+      $interesting=1;
+    }
+    $i++;
+  }
+  if($interesting) {
+    my $fname='/tmp/intblocks/'.$called.'.intfb.h';
+    if( -f $fname ) {
+      my @dumargs=();
+      my $unit_name;
+      print "FILE $fname FOUND \n";
+      my @lines = &readfile($fname);
+      my @loc_statements=(); 
+      &expcont(\@lines,\@loc_statements);
+      foreach my $href (@loc_statements) {
+	$_=$href->{statement};
+	if(/^\s*SUBROUTINE/i) {
+	  my $dum=&parse_prog_unit(\$unit_name,\@dumargs);
+	  next;
+	}
+	if(/::/) {
+	  s/\s//g;
+	  foreach my $arg (keys (%argpos)) {
+	    my $set_before=$$setnow{$arg};
+	    foreach my $i (@{$argpos{$arg}}){
+	      if(/::$dumargs[$i]/) {
+		if(/INTENT\(IN\)/i) {
+		  $$arghash{$arg}{used}=1 unless $set_before;
+		}
+		elsif(/INTENT\(OUT\)/i) {
+		  $$arghash{$arg}{set}=1;
+		  $$setnow{$arg}=1 unless($$inif);
+		}
+		elsif(/INTENT\(INOUT\)/i) {
+		  $$arghash{$arg}{set}=1;
+		  $$arghash{$arg}{used}=1 unless $set_before;;
+		  $$arghash{$arg}{reallyset}=1 unless($$inif);
+		}
+		elsif(/\! UNDETERMINED INTENT/) {
+		  $$arghash{$arg}{nointent}=1;
+		}
+	      }
+	    }
+	  }
+	}
+      }
+    }
+    else {
+      foreach my $arg (keys (%argpos)) {
+	$$arghash{$arg}{nointent}=1;
+      }
+    }
+  }
+  for (@inpars) {
+    foreach my $arg (keys (%$arghash)) {
+      if(exists $$arghash{$arg}) {
+	if(/\b$arg\b/i) {
+	  $$arghash{$arg}{used}=1 unless $$setnow{$arg};
+	}
+      }
+    }
+  }
+}
+  
+sub add_interface_blocks {
+# Add interface block for called routines
+  use File::Find;
+  my($statements,$prog_info) = @_;
+  my($href,$call);
+  our($name,$nest_par);
+  our(@call_names,@call_names_found,%call_names);
+
+  return unless ($$prog_info{no_calls}); # Skip if there are no calls
+  @call_names=();
+  %call_names=();
+
+  my $last_decl=0;
+  my $in_intfblk=0;
+  my %already_in=();
+  ST:foreach $href (@$statements) {
+    last if($href->{prog_unit} > 0);  # Only consider first program unit (no contains)
+    if($href->{content} eq 'INTERFACE') {
+      $in_intfblk=1;
+      next;
+    }
+    if($href->{content} eq 'END INTERFACE') {
+      $in_intfblk=0;
+      next;
+    }
+    if($in_intfblk) {
+      $_=$href->{statement};
+      s/\#include\s*\"(\w+)\.h\"\s*$/$1/;
+      $_=lc($_);
+      $already_in{$_}++;
+      next;
+    }
+    
+# Find last declaration
+    if($href->{decl}) {
+      next if($href->{content} eq 'FORMAT');
+      next if($href->{content} eq 'DATA');
+      $last_decl = $href->{number} ;
+    }
+# Find calls
+    next unless($href->{exec});
+    if($href->{content} eq 'CALL' or 
+       (exists  $href->{content2} and$ href->{content2} eq 'CALL') ) {
+      $_=$href->{statement};
+      /\s*\bCALL\b\s*($name)/i;
+      my $call=lc($1);
+      next if($already_in{$call}); # Exclude already existing interface block
+      next if($call eq 'packmsg'); # A couple of special exceptions
+      next if($call eq 'unpkmsg');
+      $call_names{$call}++;
+    }
+  }
+  
+
+# Check that routine exists in IFS
+  @call_names_found=();
+  find(\&calls_wanted,'/tmp/27/ifs/');
+#  find(\&calls_wanted,'/home/mats/work/cy28/ifs/');
+#  find(\&calls_wanted,'/tmp/27/trans/');
+  @call_names_found=sort(@call_names_found);
+#  print "P2 @call_names_found \n";
+  @call_names=@call_names_found;
+
+# Contruct include block
+  my $block='';
+  for (@call_names) {
+    $block=$block.'#include "'.$_.'.intfb.h"'."\n";
+  }
+#  print $block;
+
+  my $clean=0;
+  if(@call_names) {
+    if($$prog_info{has_interface_block}) {
+      foreach $href (@$statements) {
+# Add interface block to routine that already has INTERFACE statement
+	if($href->{content} eq 'END INTERFACE'){
+	  if($href->{post_insert}) {
+	    $href->{post_insert}=$href->{post_insert}."\n".$block;
+	  }
+	  else {
+	    $href->{post_insert}="\n".$block;
+	  }	    
+	  last;
+	}
+      }
+    }
+# Add interface block to routine that does not have previous INTERFACE statement
+    else {
+      $href=@$statements[$last_decl];
+      if($href->{post_insert}) {
+	$href->{post_insert}=$href->{post_insert}."\n".$block;
+      }
+      else {
+	$href->{post_insert}="\n".$block;
+      }	    
+    }
+# Remove from EXTERNAL statement where interface block has been added
+    foreach $href (@$statements) {
+      if($href->{content} eq 'EXTERNAL') {
+	$_=$href->{statement};
+	foreach my $ext (@call_names) {
+	  s/\b$ext\b//i;
+	}
+	s/,\s*,/,/g;
+	s/^(\s*EXTERNAL\s*),/$1/i;
+	s/^(\s*EXTERNAL.*),\s*$/$1/i;
+	s/^\s*EXTERNAL\s*,*\s*$//i;
+	$href->{statement}=$_;	
+      }
+    }
+  }
+}
+#======================================================================================
+sub calls_wanted {
+  # Used by Find as called from add_interface_blocks
+  our(%call_names,@call_names_found);
+  return unless (/^(\w+)\.F90$/);
+  my $call=$1;
+  if($call_names{$call}) {
+    push(@call_names_found,$call);
+  }    
+}
+sub remove_some_comments{
+  my($statements) = @_;
+  my $prev_empty=0;
+  foreach my $href (@$statements) {
+    if($href->{content} eq 'comment'){
+      $_=$href->{statement};
+      if(/^\s*$/) {
+	if($prev_empty) {
+	  s/\s*//;
+	  $href->{statement}=$_;
+	}
+	else {
+	  $prev_empty=1;
+	} 
+	next;
+      }
+      $prev_empty=0;
+      s/^\s*![\s\*]*\bLOCAL\s+(INTEGER|REAL|LOGICAL|CHARACTER)\s+(SCALARS|ARRAYS).*\n$//i;
+      s/^\s*![\s\*]*\bDUMMY\s+(INTEGER|REAL|LOGICAL|CHARACTER)\s+(SCALARS|ARRAYS).*\n$//i;
+      s/^\s*![\s\*]*\bLOCAL\s+(INTEGER|REAL|LOGICAL|CHARACTER).*\n$//i;
+      s/^\s*![\s\*]*\bDUMMY\b\s*$//i;
+      s/^\s*![\s\*]*\bLOCAL\b\s*$//i;
+      s/^\s*![\s\*]*\bLOCAL\b:\s*$//i;
+      s/^\s*![\s\*]*\bLOCAL ARRAYS\b[\s\*]*$//i;
+      s/^\s*![\s\*]*\bLOCAL SCALARS\b\s*$//i;
+      s/^\s*![\s\*]*\s*\d\.\d+\s*\bLOCAL ARRAYS\b\s*$//i;
+      s/^\s*![\s\*]*\s*=== LOCAL ARRAYS ===\s*$//i;
+      $href->{statement}=$_;
+    }
+    else {
+      $prev_empty=0;
+    }
+  }
+}      
+sub get_calls_inc {
+  my($statements,$calls,$intfb) = @_;
+  foreach my $href (@$statements) {
+    if($href->{content} eq 'CALL') {
+      $_=$href->{statement};
+      /^\s*CALL\s+([A-Z]\w*)/i;
+      $$calls{lc($1)}++;
+    }
+    elsif($href->{content} eq 'IF') {
+      if($href->{content2} eq 'CALL') {
+	$_=$href->{statement};
+	/\bCALL\s+([A-Z]\w*)/i;
+	$$calls{lc($1)}++;
+      }
+    }
+    elsif($href->{content} eq 'include') {
+      $_=$href->{statement};
+      $$intfb{$1}=1 if(/["](\S+)\.intfb\.h["]/);
+      $$intfb{$1}=2 if(/["](\S+)\.h["]/); # For old-style interface blocks
+    }
+  }
+}
+
+1;
+      
+__END__
Index: LMDZ5/branches/testing/tools/fcm/lib/Fcm/Build.pm
===================================================================
--- LMDZ5/branches/testing/tools/fcm/lib/Fcm/Build.pm	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/lib/Fcm/Build.pm	(revision 1665)
@@ -0,0 +1,2428 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::Build
+#
+# DESCRIPTION
+#   The main purpose of this class is to process the build configuration,
+#   generate the required files for the build and invoke make to create the
+#   build.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::Build;
+
+# Standard pragma
+use strict;
+use warnings;
+
+# Standard modules
+use Carp;
+use Cwd;
+use File::Basename;
+use File::Path;
+use File::Spec::Functions;
+
+# FCM component modules
+use Fcm::CfgFile;
+use Fcm::SrcPackage;
+use Fcm::BuildTask;
+use Fcm::Util;
+use Fcm::Timer;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $bld = Fcm::Build->new (
+#     CONFIG  => $config,
+#     CFG_SRC => $cfg_src,
+#   );
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::Build class.
+#
+# ARGUMENTS
+#   CONFIG     - reference to a Fcm::Config instance
+#   CFG_SRC    - source path to the build configuration file
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $cfg    = exists $args{CFG_SRC} ? $args{CFG_SRC} : undef;
+  my $config = exists $args{CONFIG}  ? $args{CONFIG}  : &main::cfg;
+
+  my $self  = {
+    CONFIG   => $config,            # configuration settings
+    CFG      => Fcm::CfgFile->new ( # bld cfg
+      TYPE   => 'bld',              # config file type
+      SRC    => $cfg,               # source path of the bld cfg
+      CONFIG => $config,            # configuration settings
+    ),
+    NAME     => '',                 # name of this build
+    DIR      => {                   # directory tree of this build
+      ROOT    => '',                # root directory of this build
+    },
+    PATH     => {},                 # search paths of this build
+    SEARCH   => 1,                  # search for source directories in src/?
+    SRCDIR   => {},                 # source directories of this build
+    PP       => {},                 # pre-process flags
+    PACKAGE  => {},                 # source directory packages of this build
+    TARGET   => [],                 # targets of this build
+    USE      => [],                 # list of inherited builds
+    INHERIT  => {                   # inheritance flags
+      SRCDIR => 1,                  # inherit source directories?
+      PP     => 1,                  # inherit pre-process flags?
+      TARGET => 0,                  # inherit targets?
+    },
+    LIB      => {'' => ''},         # name of libraries
+    LOCK     => undef,              # lock file
+  };
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->DESTROY;
+#
+# DESCRIPTION
+#   This method is called automatically when a Fcm::Build object is
+#   destroyed.
+# ------------------------------------------------------------------------------
+
+sub DESTROY {
+  my $self = shift;
+
+  # Remove the lock if it is set
+  unlink $self->{LOCK} if $self->{LOCK} and -e $self->{LOCK};
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = $bld->config;
+#
+# DESCRIPTION
+#   This method returns a reference to the Fcm::Config instance.
+# ------------------------------------------------------------------------------
+
+sub config {
+  my $self = shift;
+
+  return $self->{CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfgfile = $bld->cfg;
+#
+# DESCRIPTION
+#   This method returns a reference to a Fcm::CfgFile instance for the build
+#   configuration file.
+# ------------------------------------------------------------------------------
+
+sub cfg {
+  my $self = shift;
+
+  return $self->{CFG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   %allpcks = $bld->allpcks ();
+#
+# DESCRIPTION
+#   This method returns a hash table with keys representing all the packages
+#   declared in the current build. The value of each element in the hash is a
+#   reference to a list of children of the current package.
+# ------------------------------------------------------------------------------
+
+sub allpcks {
+  my $self        = shift;
+  my %allpcks = ();
+
+  for my $pckname (keys %{ $self->{PACKAGE} }) {
+    $allpcks{$pckname} = [];
+  }
+
+  for my $pckname (keys %{ $self->{PACKAGE} }) {
+    my @names = split /__/, $pckname;
+
+    my $cur = $pckname;
+    while ($cur) {
+      pop @names;
+      my $depend = @names ? join '__', @names : '';
+      $allpcks{$depend} = [] unless exists $allpcks{$depend};
+
+      push @{ $allpcks{$depend} }, $cur
+        unless grep {$_ eq $cur} @{ $allpcks{$depend} };
+
+      $cur = $depend;
+    }
+  }
+
+  return %allpcks;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = $bld->build (
+#     [ARCHIVE     => $archive,]
+#     [FULL        => $full,]
+#     [IGNORE_LOCK => $ignore_lock,]
+#     [JOBS        => $jobs,]
+#     [STAGE       => $stage,]
+#     [TARGETS     => \@targets,]
+#   );
+#
+# DESCRIPTION
+#   This method performs a build based on the current configuration. The
+#   method returns 1 on success.
+#
+# ARGUMENTS
+#   ARCHIVE      - If set to "true", invoke the "archive" mode. Most build files
+#                  and directories created by this build will be archived using
+#                  the "tar" command. If not set, the default is not to invoke
+#                  the "archive" mode.
+#   FULL         - If set to "true", invoke the build in "full" mode. Build files
+#                  and directories created by previous builds in the same
+#                  location will be removed before the current build is
+#                  performed. If not set, the default is to perform the build
+#                  in "incremental" mode.
+#   IGNORE_LOCK  - If set to "true", it ignores any lock files that may exist in
+#                  the build root directory. 
+#   JOBS         - Specify number of jobs that can be handled by "make". If set,
+#                  the value must be a natural integer. If not set, the default
+#                  value is 1 (i.e. run "make" in serial mode).
+#   STAGE        - If set, it should be an integer number or a recognised
+#                  keyword or abbreviation. If set, the build is performed up
+#                  to the named stage. If not set, the default is to perform
+#                  all stages of the build. Allowed values are:
+#                  1, setup or s
+#                  2, pre_process or pp
+#                  3, generate_dependency or gd
+#                  4, generate_interface or gi
+#                  5, all, a, make or m
+#   TARGETS      - Specify targets to be built. If set, these targets will be
+#                  built instead of the ones specified in the build
+#                  configuration file.
+# ------------------------------------------------------------------------------
+
+sub build {
+  my $self = shift;
+  my %args = @_;
+
+  # Process arguments
+  my $archive     = exists $args{ARCHIVE}     ? $args{ARCHIVE}     : 0;
+  my $full        = exists $args{FULL}        ? $args{FULL}        : 0;
+  my $ignore_lock = exists $args{IGNORE_LOCK} ? $args{IGNORE_LOCK} : 0;
+  my $jobs        = exists $args{JOBS}        ? $args{JOBS}        : 1;
+  my $stage       = exists $args{STAGE}       ? $args{STAGE}       : 5;
+  my $targets     = exists $args{TARGETS}     ? $args{TARGETS}     : [qw/all/];
+
+  # Resolve named stages
+  $stage = 5 unless $stage;
+  if ($stage !~ /^\d$/) {
+    my %stagenames = (
+      'S(?:ETUP)?'                      => 1,
+      'P(?:RE)?_?P(?:ROCESS)?'          => 2,
+      'G(?:ENERATE)?_?D(?:ENPENDENCY)?' => 3,
+      'G(?:ENERATE)?_?I(?:NTERFACE)?'   => 4,
+      '(?:A(?:LL)|M(?:AKE)?)'           => 5,
+    );
+
+    for my $name (keys %stagenames) {
+      if ($stage =~ /$name/i) {
+        $stage = $stagenames{$name};
+        last;
+      }
+    }
+
+    if ($stage !~ /^\d$/) {
+      w_report 'Warning: invalid build stage: ', $stage, ', default to "5"';
+      $stage = 5;
+    }
+  }
+
+  # Get verbose mode
+  my $verbose = $self->config->verbose;
+
+  # Stage 1: setup
+  my $date = localtime;
+  print 'Build command started on ', $date, '.', "\n" if $verbose;
+  my $otime = time;
+
+  print '->Setup              : start', "\n" if $verbose;
+  my $stime = time;
+
+  # Read configurations
+  my $rc = $self->decipher_cfg;
+
+  # Check directories are set
+  $rc = $self->check_dir if $rc;
+
+  # Check for lock files
+  $rc = $self->check_lock if $rc and not $ignore_lock;
+
+  # Set a lock file
+  $rc = $self->_set_lock if $rc;
+
+  # Create build root directory if necessary
+  $rc = $self->_create_build_dir if $rc;
+
+  # Set up directory inheritance
+  $rc = $self->_setup_dir (FULL => $full) if $rc;
+
+  # Set up source directories, targets, etc
+  $rc = $self->_update_bld_info if $rc;
+
+  # Set up PP flag cache
+  $rc = $self->_update_pp_info if $rc;
+
+  # Set up build tools cache
+  $rc = $self->_update_tool_info if $rc;
+
+  # Set up regenerate make rule cache
+  $rc = $self->_update_regen_rule_info if $rc;
+
+  my $ftime = time;
+  my $s_str = $ftime - $stime > 1 ? 'seconds' : 'second';
+  print '->Setup              : ', $ftime - $stime, ' ', $s_str, "\n";
+
+  # Stage 2: Pre-process
+  if ($rc and $stage >= 2) {
+    print '->Pre-process        : start', "\n" if $verbose;
+    my $stime = time;
+
+    $rc = $self->_pre_process;
+
+    $ftime = time;
+    $s_str = $ftime - $stime > 1 ? 'seconds' : 'second';
+    print '->Pre-process        : ', $ftime - $stime, ' ', $s_str, "\n";
+  }
+
+  # Stage 3: Scan dependency and write make rules
+  if ($rc and $stage >= 3) {
+    print '->Scan dependency    : start', "\n" if $verbose;
+    my $stime = time;
+
+    $rc = $self->_scan_dependency;
+    $rc = $self->_write_make_rules if $rc;
+    $rc = $self->_write_makefile if $rc;
+
+    $ftime = time;
+    $s_str = $ftime - $stime > 1 ? 'seconds' : 'second';
+    print '->Scan dependency    : ', $ftime - $stime, ' ', $s_str, "\n";
+  }
+
+  # Stage 4: Generate Fortran 9x interface block
+  if ($rc and $stage >= 4) {
+    print '->Generate interface : start', "\n" if $verbose;
+    my $stime = time;
+
+    $rc = $self->_generate_f9x_interface;
+
+    $ftime = time;
+    $s_str = $ftime - $stime > 1 ? 'seconds' : 'second';
+    print '->Generate interface : ', $ftime - $stime, ' ', $s_str, "\n";
+  }
+
+  # Stage 5: Make the build
+  if ($rc and $stage >= 5) {
+    print '->Make               : start', "\n" if $verbose;
+    my $stime = time;
+
+    $rc = $self->_invoke_make (
+      TARGETS => $targets,
+      JOBS    => $jobs,
+      ARCHIVE => $archive,
+    );
+
+    # Remove empty build directories
+    $rc = $self->_remove_empty_dirs () if $rc;
+
+    # Create TAR archives if necessary
+    $rc = $self->_tar_build_dirs () if $rc and $archive;
+
+    # Create run time environment script if necessary
+    $rc = $self->_create_runenv_script () if $rc;
+
+    # Create exclude dependency configurations for libraries
+    $rc = $self->_create_lib_excl_dep () if $rc;
+
+    $ftime = time;
+    $s_str = $ftime - $stime > 1 ? 'seconds' : 'second';
+    print '->Make               : ', $ftime - $stime, ' ', $s_str, "\n";
+  }
+
+  if ($verbose) {
+    $s_str = $ftime - $otime > 1 ? 'seconds' : 'second';
+    print '->TOTAL              : ', $ftime - $otime, ' ', $s_str, "\n";
+  }
+
+  $date = localtime;
+  if ($rc) {
+    print 'Build command finished on ', $date, '.', "\n" if $verbose;
+
+  } else {
+    e_report 'Build command failed on ', $date, '.';
+  }
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $bld->decipher_cfg ();
+#
+# DESCRIPTION
+#   This method deciphers the build configuration file and assigns the
+#   configurations to the variables of the current build.
+# ------------------------------------------------------------------------------
+
+sub decipher_cfg {
+  my $self = shift;
+
+  my $read = $self->cfg->read_cfg;
+
+  # Check config file type
+  if ($read) {
+    if ($self->cfg->type ne 'bld') {
+      w_report 'Error: ', $self->cfg->src, ': not a build config file.';
+      return;
+    }
+
+  } else {
+    return;
+  }
+
+  my %cfg_label = %{ $self->config->setting ('CFG_LABEL') };
+  my %tools     = %{ $self->config->setting ('TOOL') };
+
+  # Get lines from cfg file
+  my @cfg_lines  = $self->cfg->lines;
+
+  LINE: for my $line (@cfg_lines) {
+    # Label and value of each line
+    my $label = $line->{LABEL};
+    my $value = $line->{VALUE};
+
+    next LINE unless $label; # ignore blank or comment line
+
+    # Strip out BLD prefix from all labels
+    my $prefix = $cfg_label{BDECLARE} . '::';
+    $label = substr ($label, length ($prefix))
+      if index (uc ($label), $prefix) == 0;
+
+    next LINE unless $label; # ignore blank or comment line
+
+    # Configuration file type/version, ignore
+    next LINE if uc $label eq $cfg_label{CFGFILE}{TYPE};
+    next LINE if uc $label eq $cfg_label{CFGFILE}{VERSION};
+
+    # User variable, ignore
+    next LINE if index (uc ($label), '%') == 0;
+
+    # Build name
+    if (uc $label eq $cfg_label{NAME}) {
+      $self->{NAME} = $value;
+      next LINE;
+    }
+
+    # Build directory tree
+    $prefix = $cfg_label{DIR} . '::';
+    if (index (uc ($label), $prefix) == 0) {
+      my $name = substr uc ($label), length ($prefix);
+      $self->{DIR}{$name} = expand_tilde $value;
+      next LINE;
+    }
+
+    # Source directory
+    $prefix = $cfg_label{SRCDIR} . '::';
+    if (index (uc ($label), $prefix) == 0) {
+      my $name = substr $label, length ($prefix);
+      $name    =~ s/::/__/g;
+      $self->{SRCDIR}{$name} = expand_tilde $value;
+      next LINE;
+    }
+
+    # Automatic source directory search?
+    if (uc $label eq $cfg_label{SEARCH_SRC}) {
+      $self->{SEARCH} = $value;
+      next LINE;
+    }
+
+    # Pre-process flag, directory/file requires pre-processing before all tasks
+    $prefix = $cfg_label{PP};
+    if (index (uc ($label), $prefix) == 0) {
+      my @flds = split /::/, $label;
+      my $name = uc shift @flds;
+      $name    = join '__', ($name, @flds) if @flds;
+      $self->{PP}{$name} = $value;
+      next LINE;
+    }
+
+    # Specify name of top level or package library
+    $prefix = $cfg_label{LIB};
+    if (index (uc ($label), $prefix) == 0) {
+      my @flds = split /::/, $label;
+      shift @flds;
+      my $name = @flds ? join ('__', @flds) : '';
+      $self->{LIB}{$name} = $value;
+
+      next LINE;
+    }
+
+    # Specify extra executable dependencies and BLOCKDATA dependency
+    for my $name (qw/EXE_DEP BLOCKDATA/) {
+      $prefix = $cfg_label{$name};
+
+      if (index (uc ($label), $prefix) == 0) {
+        my @flds = split /::/, $label;
+        shift @flds;
+        my $target = @flds ? $flds[0] : '';
+        my @deps   = split /\s+/, $value;
+
+        # If $value is a null string, set executable to depend on all objects
+        if (not @deps) {
+          if ($name eq 'BLOCKDATA') {
+
+            # Label not recognised
+            w_report 'Warning: ', $line->{SRC}, ': LINE ', $line->{NUMBER},
+                     ': "', $label, '" declaration must have a value';
+            next LINE;
+
+          } else {
+            push @deps, '';
+          }
+        }
+
+        for my $dep (@deps) {
+          $dep =~ s/::/__/g;
+
+          $self->config->assign_setting (
+            LABELS => [$name, $target, $dep],
+            VALUE  => 1,
+          );
+        }
+
+        next LINE;
+      }
+    }
+
+    # Build target
+    if (uc $label eq $cfg_label{TARGET}) {
+      push @{ $self->{TARGET} }, split (/\s+/, $value);
+      next LINE;
+    }
+
+    # Rename a main program target
+    $prefix = $cfg_label{EXE_NAME};
+    if (index (uc ($label), $prefix) == 0) {
+      my @flds = split /::/, $label;
+      shift @flds;
+      my $name = shift @flds;
+
+      if ($name and $value) {
+        $self->config->assign_setting (
+          LABELS => ['EXE_NAME', $name],
+          VALUE  => $value,
+        );
+
+        next LINE;
+      }
+    }
+
+    # Build tool
+    $prefix = $cfg_label{TOOL} . '::';
+    if (index (uc ($label), $prefix) == 0) {
+      my $name = substr $label, length ($prefix);
+      my @flds = split /::/, $name;
+
+      $name = uc (shift @flds);
+
+      if (exists $tools{$name}) {
+        $name = join '__', ($name, @flds) if @flds;
+
+        $self->config->assign_setting (
+          LABELS => ['TOOL', $name],
+          VALUE  => $value,
+        );
+        next LINE;
+      }
+    }
+
+    # File name extension and type
+    for my $name (qw/INFILE_EXT OUTFILE_EXT/) {
+      $prefix = $cfg_label{$name};
+      if (index (uc ($label), $prefix) == 0) {
+        my $key = (split /::/, $label)[1];
+        $key    = uc $key if $name eq 'OUTFILE_EXT';
+
+        my $val = ($name eq 'INFILE_EXT') ? uc $value : $value;
+
+        $self->config->assign_setting (
+          LABELS => [$name, $key],
+          VALUE  => $val,
+        );
+        next LINE;
+      }
+    }
+
+    # Dependency scan exclusion
+    $prefix = $cfg_label{EXCL_DEP};
+    if (index (uc ($label), $prefix) == 0) {
+      my @flds = split /::/, $label;
+      shift @flds;
+
+      my $pk = @flds ? join ('__', @flds) : '';
+      $self->config->assign_setting (
+        LABELS => ['EXCL_DEP', uc ($value), $pk],
+        VALUE  => 1,
+      );
+      next LINE;
+    }
+
+    # Use (inherit from) another build
+    if (uc $label eq $cfg_label{USE}) {
+      my $use = Fcm::Build->new (
+        CONFIG  => $self->config,
+        CFG_SRC => expand_tilde ($value),
+      );
+      $use->decipher_cfg;
+      $use->check_dir;
+      push @{ $self->{USE} }, $use;
+      next LINE;
+    }
+
+    # Inheritance flag
+    $prefix = $cfg_label{INHERIT} . '::';
+    if (index (uc ($label), $prefix) == 0) {
+      my $name = substr $label, length ($prefix);
+      my @flds = split /::/, $name;
+
+      $name = uc (shift @flds);
+
+      for my $flag (qw/SRCDIR PP LIB TARGET/) {
+        if ($name eq $cfg_label{$flag}) {
+          $name = @flds ? join ('__', ($flag, @flds)) : $flag;
+          $self->{INHERIT}{$name} = $value;
+          next LINE;
+        }
+      }
+    }
+
+    # Label not recognised
+    w_report 'ERROR: ', $line->{SRC}, ': LINE ', $line->{NUMBER}, ': label "',
+             $label, '" not recognised';
+    return;
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $bld->check_dir ();
+#
+# DESCRIPTION
+#   This method checks whether the build directories are set correctly.
+# ------------------------------------------------------------------------------
+
+sub check_dir {
+  my $self = shift;
+
+  # Make sure build root directory is set
+  if (not $self->{DIR}{ROOT}) {
+    w_report 'Error: build root directory not set.';
+    return;
+  }
+
+  # Set value of build sub-directories if necessary
+  for my $name (keys %{ $self->config->setting ('DIR') }) {
+    next if $self->{DIR}{$name};
+
+    $self->{DIR}{$name} = catfile (
+      $self->{DIR}{ROOT},
+      $self->config->setting ('DIR', $name),
+    );
+  }
+
+  # Search src/ sub-directory if necessary
+  if ($self->{SEARCH} and -d $self->{DIR}{SRC}) {
+    my %dir = find_srcdir ($self->{DIR}{SRC});
+    for my $name (keys %dir) {
+      $self->{SRCDIR}{$name} = $dir{$name} unless $self->{SRCDIR}{$name};
+    }
+  }
+
+  # Expand source directory paths if necessary
+  for my $name (keys %{ $self->{SRCDIR} }) {
+    if ($self->{SRCDIR}{$name} =~ /^\w/) {
+      my $src_search  = catfile $self->{DIR}{SRC} , $self->{SRCDIR}{$name};
+      my $root_search = catfile $self->{DIR}{ROOT}, $self->{SRCDIR}{$name};
+
+      if ($self->{DIR}{SRC} and -d $src_search) {
+        $self->{SRCDIR}{$name} = $src_search;
+
+      } elsif (-d $root_search) {
+        $self->{SRCDIR}{$name} = $root_search;
+
+      } else {
+        w_report 'Warning: cannot locate declared source directory: ',
+                 $self->{SRCDIR}{$name};
+        next;
+      }
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $bld->check_lock ();
+#
+# DESCRIPTION
+#   This method checks whether a lock is set in the current build.
+# ------------------------------------------------------------------------------
+
+sub check_lock {
+  my $self = shift;
+
+  my $rootdir  = $self->{DIR}{ROOT};
+  my $lock_ext = catfile ($rootdir, $self->config->setting (qw/MISC LOCK_EXT/));
+  my $lock_bld = catfile ($rootdir, $self->config->setting (qw/MISC LOCK_BLD/));
+
+  # Always throw error if extract lock exists
+  if (-e $lock_ext) {
+    w_report 'ERROR: extract lock file exists: ', $lock_ext, ',';
+    w_report '       an extract may be running at ', $rootdir, ', abort.';
+    return;
+  }
+
+  # Always throw error if build lock exists
+  if (-e $lock_bld) {
+    w_report 'ERROR: build lock file exists: ', $lock_bld, ',';
+    w_report '       a build may be running at ', $rootdir, ', abort.';
+    return;
+  }
+
+  # Check locks in inherited build
+  for my $use (@{ $self->{USE} }) {
+    return unless $use->check_lock;
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_set_lock ();
+#
+# DESCRIPTION
+#   This method sets a lock is set in the current build.
+# ------------------------------------------------------------------------------
+
+sub _set_lock {
+  my $self = shift;
+
+  $self->{LOCK} = catfile (
+    $self->{DIR}{ROOT}, $self->config->setting (qw/MISC LOCK_BLD/),
+  );
+
+  &touch_file ($self->{LOCK});
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_setup_dir (FULL => $full);
+#
+# DESCRIPTION
+#   This internal method sets up the build directories.
+# ------------------------------------------------------------------------------
+
+sub _setup_dir {
+  my $self = shift;
+  my %args = @_;
+
+  my $full = exists $args{FULL} ? $args{FULL} : 0;
+
+  my $tar      = $self->config->setting (qw/OUTFILE_EXT TAR/);
+  my @tar_dirs = split /,/, $self->config->setting (qw/TAR_DIRS/);
+  my $verbose  = $self->config->verbose;
+
+  if ($full) {
+    # Remove sub-directories/archives created from previous builds
+    for my $name (qw/BIN BLD DONE ETC FLAGS INC LIB PPSRC OBJ TMP/) {
+      &run_command ([qw/rm -rf/, $self->{DIR}{$name}], PRINT => $verbose)
+        if -d $self->{DIR}{$name};
+
+      &run_command ([qw/rm -f/, $self->{DIR}{$name} . $tar], PRINT => $verbose)
+        if -f $self->{DIR}{$name} . $tar;
+    }
+
+    # Remove cache
+    my @files;
+    if (-d $self->{DIR}{CACHE} and opendir DIR, $self->{DIR}{CACHE}) {
+      @files = grep {$_ ne '.' and $_ ne '..'} readdir 'DIR';
+      closedir DIR;
+    }
+
+    my $extension = '\\' . $self->config->setting (qw/CACHE PCKFILE/) . '|' .
+                    '\\' . $self->config->setting (qw/CACHE PCKPPDEPEND/) . '|' .
+                    '\\' . $self->config->setting (qw/CACHE PCKDEPEND/);
+
+
+    for my $file (@files) {
+      next unless $file eq $self->config->setting (qw/CACHE BLDTOOL/) or
+                  $file eq $self->config->setting (qw/CACHE PPOPTION/) or
+                  $file eq $self->config->setting (qw/CACHE EXE_DEP/) or
+                  $file =~ /$extension$/;
+
+      my $path = File::Spec->catfile ($self->{DIR}{CACHE}, $file);
+      &run_command ([qw/rm -f/, $path], PRINT => $verbose);
+    }
+
+  } else {
+    # Extract archives if necessary
+    for my $name (@tar_dirs) {
+      my $tar_file = $self->{DIR}{$name} . $tar;
+
+      if (-f $tar_file) {
+        &run_command ([qw/tar -x -f/, $tar_file], PRINT => $verbose > 1);
+        &run_command ([qw/rm -f/, $tar_file], PRINT => $verbose > 1);
+      }
+    }
+  }
+
+  # Set up search paths
+  for my $name (keys %{ $self->{DIR} }) {
+    $self->{PATH}{$name} = [$self->_get_inherited_paths ($name)];
+
+    $self->config->assign_setting (
+      LABELS => ['PATH', $name],
+      VALUE  => $self->{PATH}{$name},
+    )
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_update_bld_info ();
+#
+# DESCRIPTION
+#   This internal method sets up the inheritance relationship for source
+#   directories and targets, and other configurations required by the build.
+# ------------------------------------------------------------------------------
+
+sub _update_bld_info {
+  my $self = shift;
+
+  # Set up build targets
+  $self->{TARGET} = [$self->_get_inherited_items ('TARGET')];
+
+  # Set up PP switches
+  $self->{PP} = {$self->_get_inherited_items ('PP')};
+
+  # Set up source directory packages for this build
+  my %srcdir = $self->_get_inherited_items ('SRCDIR');
+  for my $name (keys %srcdir) {
+    my $package = Fcm::SrcPackage->new (
+      CONFIG     => $self->config,
+      NAME       => $name,
+      CURRENT    => exists $self->{SRCDIR}{$name},
+      REQUIREPP  => $self->_require_pp ($name),
+      SEARCHPATH => [$self->_get_inherited_srcdirs ($name)],
+    );
+
+    $package->update_file_info ();
+
+    $self->{PACKAGE}{$name} = $package;
+  }
+
+  # Set up runtime dependency scan patterns
+  my %dep_pattern = %{ $self->config->setting ('DEP_PATTERN') };
+  for my $key (keys %dep_pattern) {
+    my $pattern = $dep_pattern{$key};
+
+    while ($pattern =~ /##([\w:]+)##/g) {
+      my $match = $1;
+      my $val   = $self->config->setting (split (/::/, $match));
+
+      last unless defined $val;
+      $val =~ s/\./\\./;
+
+      $pattern =~ s/##$match##/$val/;
+    }
+
+    $self->config->assign_setting (
+      LABELS => ['DEP_PATTERN', $key],
+      VALUE  => $pattern,
+    ) unless $pattern eq $dep_pattern{$key};
+  }
+
+  # Set up top level library name
+  {
+    $self->{LIB} = {$self->_get_inherited_items ('LIB')};
+
+    my $lib = $self->{LIB}{''};
+    $lib    = ($self->{NAME} ? $self->{NAME} : 'fcm_default') unless $lib;
+    $self->{LIB}{''} = $lib;
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_update_regen_rule_info ();
+#
+# DESCRIPTION
+#   This internal method compares the current EXE_DEP, BLOCKDATA and EXE_NAME
+#   declarations and the previous. If changed, the REGEN_MAKERULE flag will be
+#   set to true and the cache will be updated.
+# ------------------------------------------------------------------------------
+
+sub _update_regen_rule_info {
+  my $self = shift;
+
+  # Look for an extra executable dependency cache file
+  my $cachebase = $self->config->setting (qw/CACHE EXE_DEP/);
+  my $incache   = find_file_in_path $cachebase, $self->{PATH}{CACHE};
+
+  my $uptodate = 0;
+  my @inlines  = ();
+
+  # Read cache if it exists
+  if ($incache and -r $incache) {
+    my $incfg = Fcm::CfgFile->new (CONFIG => $self->config, SRC => $incache);
+    $incfg->read_cfg;
+
+    @inlines  = $incfg->lines;
+    $uptodate = 1;
+  }
+
+  # Prepare output lines
+  my $outcfg = Fcm::CfgFile->new (CONFIG => $self->config);
+  $outcfg->add_line (COMMENT => 'EXE_DEP cache');
+
+  # List of extra executable dependencies
+  my %exe_dep   = %{ $self->config->setting ('EXE_DEP') };
+  for my $target (sort keys %exe_dep) {
+    $outcfg->add_line (
+      LABEL => ($target ? 'OBJECTS__' . $target : 'OBJECTS'),
+      VALUE => join (' ', sort keys %{ $exe_dep{$target} }),
+    );
+  }
+
+  # List of BLOCKDATA dependencies
+  my %blockdata = %{ $self->config->setting ('BLOCKDATA') };
+  for my $target (sort keys %blockdata) {
+    $outcfg->add_line (
+      LABEL => ($target ? 'BLOCKDATA__' . $target : 'BLOCKDATA'),
+      VALUE => join (' ', sort keys %{ $blockdata{$target} }),
+    );
+  }
+
+  # List of EXE_NAME
+  my %exe_name = %{ $self->config->setting ('EXE_NAME') };
+  for my $target (sort keys %exe_name) {
+    $outcfg->add_line (
+      LABEL => 'EXE_NAME__' . $target,
+      VALUE => $exe_name{$target},
+    );
+  }
+
+  # Compare cache with current output
+  my @outlines = $outcfg->lines ();
+
+  $uptodate = 0 if @inlines != @outlines;
+
+  if ($uptodate) {
+    for my $i (0 .. $#outlines) {
+      next unless $inlines[$i]->{LABEL} and $outlines[$i]->{LABEL};
+
+      if ($inlines[$i]->{LABEL} ne $outlines[$i]->{LABEL} or
+          $inlines[$i]->{VALUE} ne $outlines[$i]->{VALUE}) {
+        $uptodate = 0;
+        last;
+      }
+    }
+  }
+
+  # Update cache if it is out of date
+  $outcfg->print_cfg (catfile ($self->{DIR}{CACHE}, $cachebase))
+    unless $uptodate;
+
+  # If out to date, set regenerate make rule flag to true
+  $self->config->assign_setting (
+    LABELS => [qw/REGEN_MAKERULE/],
+    VALUE  => ! $uptodate,
+  );
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_update_pp_info ();
+#
+# DESCRIPTION
+#   This internal method compares the current set of pre-processor options
+#   with that of the previous build using a "cache" file. If some
+#   pre-processor options have changed, the method updates the cache file and
+#   remove the "make" rules for the appropriate source packages.
+# ------------------------------------------------------------------------------
+
+sub _update_pp_info {
+  my $self = shift;
+
+  # Look for a PP option cache file
+  my $cachebase = $self->config->setting (qw/CACHE PPOPTION/);
+  my $incache   = find_file_in_path $cachebase, $self->{PATH}{CACHE};
+
+  my @chgpp = ();
+  my %newpp = %{ $self->{PP} };
+
+  # Read config if exists, otherwise marked all current PP flags as "changed"
+  if ($incache and -r $incache) {
+    my $cfg = Fcm::CfgFile->new (CONFIG => $self->config, SRC => $incache);
+    $cfg->read_cfg;
+
+    my @lines   = $cfg->lines;
+    my %oldpp = ();
+
+    for my $line (@lines) {
+      next unless $line->{LABEL};
+
+      $oldpp{$line->{LABEL}} = $line->{VALUE};
+    }
+
+    # Compare new and old, mark as "changed" if changed or does not exist in old
+    @chgpp = (grep {
+      exists $oldpp{$_} ? $oldpp{$_} ne $newpp{$_} : 1;
+    } keys %newpp);
+
+    # Compare old and new, mark as "changed" if not exist in new
+    push @chgpp, (grep {not exists $newpp{$_}} keys %oldpp);
+
+  } else {
+    @chgpp = keys %newpp;
+  }
+
+  if (@chgpp) {
+    for my $name (@chgpp) {
+      for my $package (values %{ $self->{PACKAGE} }) {
+        next if $package->newpp;
+
+        if (('PP__' . $package->name) =~ /^$name(?:__|$)/) {
+          $package->current (1);
+          $package->newpp   (1);
+        }
+      }
+    }
+
+    # Update the PP cache file if necessary
+    my $cfg = Fcm::CfgFile->new (CONFIG => $self->config);
+
+    for my $name (keys %newpp) {
+      $cfg->add_line (LABEL => $name, VALUE => $newpp{$name});
+    }
+    $cfg->add_line unless $cfg->lines;
+
+    $cfg->print_cfg (catfile ($self->{DIR}{CACHE}, $cachebase));
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_update_tool_info ();
+#
+# DESCRIPTION
+#   This internal method compares the current set of build tools with that of
+#   the previous build using a "cache" file. If some build tools have changed,
+#   the method updates the cache file and (the time stamps of) dummy "flags"
+#   files to denote changes in build tools from the previous build.
+# ------------------------------------------------------------------------------
+
+sub _update_tool_info {
+  my $self = shift;
+
+  # Look for a build tool cache file
+  my $cachebase = $self->config->setting (qw/CACHE BLDTOOL/);
+  my $incache   = find_file_in_path $cachebase, $self->{PATH}{CACHE};
+
+  my @chgtool = ();
+  my %newtool = %{ $self->config->setting ('TOOL') };
+
+  # Read config if exists, otherwise marked all current tools as "changed"
+  if ($incache and -r $incache) {
+    my $cfg = Fcm::CfgFile->new (CONFIG => $self->config, SRC => $incache);
+    $cfg->read_cfg;
+
+    my @lines   = $cfg->lines;
+    my %oldtool = ();
+
+    for my $line (@lines) {
+      next unless $line->{LABEL};
+
+      $oldtool{$line->{LABEL}} = $line->{VALUE};
+    }
+
+    # Compare new and old, mark as "changed" if changed or does not exist in old
+    @chgtool = (grep {
+      exists $oldtool{$_} ? $oldtool{$_} ne $newtool{$_} : 1;
+    } keys %newtool);
+
+    # Compare old and new, mark as "changed" if not exist in new
+    push @chgtool, (grep {not exists $newtool{$_}} keys %oldtool);
+
+  } else {
+    @chgtool = keys %newtool;
+  }
+
+  if (@chgtool) {
+    # Update the time stamps of dummy files for changed tools
+    $self->_create_build_dir ('FLAGS');
+
+    my $ext = $self->config->setting (qw/OUTFILE_EXT FLAGS/);
+    for my $name (@chgtool) {
+      my $file = catfile $self->{DIR}{FLAGS}, $name . $ext;
+
+      # Create/touch the file
+      touch_file $file or croak 'Unable to update: ', $file, ', abort';
+
+      print 'Updated: ', $file, "\n" if $self->config->verbose > 2;
+    }
+
+    # Update the build tool cache file if necessary
+    my $cfg = Fcm::CfgFile->new (CONFIG => $self->config);
+
+    for my $name (keys %newtool) {
+      $cfg->add_line (LABEL => $name, VALUE => $newtool{$name});
+    }
+
+    $cfg->print_cfg (catfile ($self->{PATH}{CACHE}->[0], $cachebase));
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_pre_process ();
+#
+# DESCRIPTION
+#   This internal method obtains a list of source files that require
+#   pre-processing in the source packages of this build, and attempts to
+#   pre-process them. The method returns 1 on success.
+# ------------------------------------------------------------------------------
+
+sub _pre_process {
+  my $self = shift;
+
+  # Go through source packages/files to see if PP is required
+  my @srcfiles = ();
+  for my $package (values %{ $self->{PACKAGE} }) {
+    next unless $package->requirepp;
+
+    $package->scan_dependency (HEADER_ONLY => 1);
+
+    push @srcfiles, grep ({$_->is_type_or (qw/FPP C/)} $package->srcfile);
+  }
+
+  return 1 unless @srcfiles;
+
+  my %task     = ();
+  my $flagsext = $self->config->setting (qw/OUTFILE_EXT FLAGS/);
+  my $pdoneext = $self->config->setting (qw/OUTFILE_EXT PDONE/);
+
+  # Set up tasks for each source file
+  for my $srcfile (@srcfiles) {
+    my $command  = $srcfile->is_type ('FPP') ? 'FPP' : 'CPP';
+    my @pck_list = $srcfile->get_package_list;
+    my @pknames  = split '__', pop (@pck_list);
+
+    # Set up a PP build task for each source file
+    my $target    = $srcfile->base . $pdoneext;
+    my $ppkeyname = join ('__', ($command . 'KEYS' , @pknames)) . $flagsext;
+    my $flagsname = join ('__', ($command . 'FLAGS', @pknames)) . $flagsext;
+
+    # Issue warning for duplicated tasks
+    if (exists $task{$target}) {
+      w_report 'Warning: ', $target, ': unable to create task for: ',
+               $srcfile->src, ': task already exists for: ',
+               $task{$target}->srcfile->src;
+      next;
+    }
+
+    $task{$target} = Fcm::BuildTask->new (
+      CONFIG     => $self->config,
+      TARGET     => $target,
+      TARGETPATH => $self->{PATH}{DONE},
+      SRCFILE    => $srcfile,
+      DEPENDENCY => [$ppkeyname, $flagsname, ($srcfile->dep ('H'))],
+      ACTIONTYPE => 'PP',
+    );
+
+    # Set up update ppkeys/flags build tasks for each source file/package
+    for my $i (0 .. $#pknames) {
+      my $name  = join '__', @pknames [0 .. $i];     # package name
+      my $dname = join '__', @pknames [0 .. $i - 1]; # dependent package name
+
+      for my $flag (qw/KEYS FLAGS/) {
+        my $fullflag = $command . $flag;
+        my $target   = join '__', ($fullflag, $name);
+        my $depend   = $dname ? join '__', ($fullflag, $dname) : $fullflag;
+
+        $target .= $flagsext;
+        $depend .= $flagsext;
+
+        next if exists $task{$target};
+
+        $task{$target} = Fcm::BuildTask->new (
+          CONFIG     => $self->config,
+          TARGET     => $target,
+          TARGETPATH => $self->{PATH}{FLAGS},
+          DEPENDENCY => [$depend],
+          ACTIONTYPE => 'UPDATE',
+        );
+      }
+    }
+  }
+
+  # Set up update global ppkeys/flags build tasks
+  for my $command (qw/CPP FPP/) {
+    for my $flag ('', qw/KEYS FLAGS/) {
+      my $target = $command . $flag . $flagsext;
+
+      $task{$target} = Fcm::BuildTask->new (
+        CONFIG     => $self->config,
+        TARGET     => $target,
+        TARGETPATH => $self->{PATH}{FLAGS},
+        ACTIONTYPE => 'UPDATE',
+      );
+    }
+  }
+
+  # Set up build tasks to copy all header files
+  for my $package (values %{ $self->{PACKAGE} }) {
+    my @files = grep {$_->is_type (qw/CPP INCLUDE/)} $package->srcfile;
+
+    # Author's note: may also want to issue warning for duplicated tasks
+
+    for my $file (@files) {
+      $task{$file->base} = Fcm::BuildTask->new (
+        CONFIG     => $self->config,
+        TARGET     => $file->base,
+        TARGETPATH => $self->{PATH}{INC},
+        SRCFILE    => $file,
+        DEPENDENCY => [$file->dep ('H')],
+        ACTIONTYPE => 'COPY',
+      );
+    }
+  }
+
+  # Build all PP tasks
+  my $count = 0;
+
+  for my $task (values %task) {
+    next unless $task->actiontype eq 'PP';
+
+    my $rc = $task->action (TASKLIST => \%task);
+    $count++ if $rc;
+  }
+
+  print 'Number of pre-processed files: ', $count, "\n"
+    if $self->config->verbose and $count;
+
+  # Change path and file type of pre-processed source files
+  for my $task (values %task) {
+    next unless $task->actiontype eq 'PP';
+
+    # Remove header dependencies from source file
+    my %dep = $task->srcfile->dep ();
+    for my $key (keys %dep) {
+      delete $dep{$key} if $dep{$key} eq 'H';
+    }
+    $task->srcfile->dep (\%dep);
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_generate_f9x_interface ();
+#
+# DESCRIPTION
+#   This internal method obtains a list of Fortran 9X source files in the
+#   source packages of this build, and attempts to generate an interface block
+#   file for each of the Fortran 9X source files. The method returns 1 on
+#   success.
+# ------------------------------------------------------------------------------
+
+sub _generate_f9x_interface {
+  my $self = shift;
+
+  # Go through source packages/files for Fortran 9x source files with
+  # standalone subroutines or functions
+  my @srcfiles = ();
+  for my $package (values %{ $self->{PACKAGE} }) {
+    next unless $package->current;
+
+    push @srcfiles, grep {
+      $_->is_type_or (qw/FORTRAN9X FPP9X/) and
+      uc ($_->select_tool ('GENINTERFACE')) ne 'NONE' and
+      not $_->is_type_or (qw/PROGRAM MODULE INCLUDE/)
+    } $package->srcfile;
+  }
+
+  my $flagsext = $self->config->setting (qw/OUTFILE_EXT FLAGS/);
+  my $pdoneext = $self->config->setting (qw/OUTFILE_EXT PDONE/);
+
+  # Set up build task to generate interface files for all selected Fortran 9x
+  # sources
+  my %task         = ();
+  for my $srcfile (@srcfiles) {
+    my $target  = $srcfile->interfacebase . $pdoneext;
+    my @pknames = split '__', ($srcfile->get_package_list)[-1];
+    my $flag    = join ('__', ('GENINTERFACE', @pknames)) . $flagsext;
+
+    $task{$target} = Fcm::BuildTask->new (
+      CONFIG     => $self->config,
+      TARGET     => $target,
+      TARGETPATH => $self->{PATH}{DONE},
+      SRCFILE    => $srcfile,
+      DEPENDENCY => [$flag],
+      ACTIONTYPE => 'GENINTERFACE',
+    );
+
+    # Set up build tasks for each source file/package flags file for interface
+    # generator tool
+    for my $i (0 .. $#pknames) {
+      my $name   = join '__', @pknames [0 .. $i];     # package name
+      my $dname  = join '__', @pknames [0 .. $i - 1]; # dependent package name
+
+      my $target = join '__', ('GENINTERFACE', $name);
+      my $depend = $dname ? join '__', ('GENINTERFACE', $dname) : 'GENINTERFACE';
+
+      $target .= $flagsext;
+      $depend .= $flagsext;
+
+      next if exists $task{$target};
+
+      $task{$target} = Fcm::BuildTask->new (
+        CONFIG     => $self->config,
+        TARGET     => $target,
+        TARGETPATH => $self->{PATH}{FLAGS},
+        DEPENDENCY => [$depend],
+        ACTIONTYPE => 'UPDATE',
+      );
+    }
+  }
+
+  # Set up build task to update the flags file for interface generator tool
+  {
+    my $target     = 'GENINTERFACE' . $flagsext;
+    $task{$target} = Fcm::BuildTask->new (
+      CONFIG     => $self->config,
+      TARGET     => $target,
+      TARGETPATH => $self->{PATH}{FLAGS},
+      ACTIONTYPE => 'UPDATE',
+    );
+  }
+
+  my $count = 0;
+
+  # Performs task
+  for my $task (values %task) {
+    next unless $task->actiontype eq 'GENINTERFACE';
+
+    my $rc = $task->action (TASKLIST => \%task);
+    $count++ if $rc;
+  }
+
+  print 'Number of generated interfaces: ', $count, "\n"
+    if $self->config->verbose and $count;
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_scan_dependency ();
+#
+# DESCRIPTION
+#   This internal method goes through each source package to obtain dependency
+#   information from their source files. It returns 1 on success.
+# ------------------------------------------------------------------------------
+
+sub _scan_dependency {
+  my $self = shift;
+
+  # Go through source packages/files
+  my $count = 0;
+
+  for my $package (values %{ $self->{PACKAGE} }) {
+    my $rc = $package->scan_dependency;
+    $count++ if $rc;
+  }
+
+  print 'Scanned files in ', $count, ' package(s) for dependency', "\n"
+    if $self->config->verbose and $count;
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_set_targets ();
+#
+# DESCRIPTION
+#   This internal method determines the default targets to be built.
+# ------------------------------------------------------------------------------
+
+sub _set_targets {
+  my $self = shift;
+
+  # Targets of the build
+  if (not @{ $self->{TARGET} }) {
+    # Build targets not specified by user, default to building all main programs
+    my @programs = ();
+
+    # Get all main programs from all packages
+    for my $package (values %{ $self->{PACKAGE} }) {
+      my @srcfiles = grep {$_->exebase} $package->srcfile;
+
+      for (@srcfiles) {
+        push @programs, $_->exebase;
+      }
+    }
+
+    @programs = sort (@programs);
+
+    if (@programs) {
+      # Build main programs, if there are any
+      @{ $self->{TARGET} } = @programs;
+
+    } else {
+      # No main program in source tree, build the default library
+      @{ $self->{TARGET} } = (
+        'lib' . $self->{LIB}{''} . $self->config->setting (qw/OUTFILE_EXT LIB/),
+      );
+    }
+  }
+
+  return @{ $self->{TARGET} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_write_make_rules ();
+#
+# DESCRIPTION
+#   This internal method writes the included make rules if necessary.
+# ------------------------------------------------------------------------------
+
+sub _write_make_rules {
+  my $self   = shift;
+  my $return = 1;
+
+  # Get list of all packages
+  my %allpcks = $self->allpcks;
+
+  # Get list of types that cannot have duplicated targets
+  my @no_duplicated_target_types = split (
+    /,/, $self->config->setting ('NO_DUPLICATED_TARGET_TYPE'),
+  );
+
+  my $unusual = 0;
+  my $count   = 0;
+  my %targets;
+  for my $name (sort keys %allpcks) {
+    # Check whether package is an actual package of the build
+    my $package  = exists $self->{PACKAGE}{$name} ? $self->{PACKAGE}{$name} : '';
+
+    # Regenerate make rules if this flag is set to true
+    my $regen_mk;
+
+    # Register non-word package name
+    if (not $name =~ /^\w*$/) {
+      $self->config->assign_setting (
+        LABELS => ['FCM_PCK_OBJECTS', $name],
+        VALUE  => 'FCM_PCK_OBJECTS' . $unusual++,
+      );
+
+      # Set regenerate make rule flag to true
+      $regen_mk = 1;
+    }
+
+    # Cycle loop if not an actual package of the build
+    next unless $package;
+
+    # Check whether make rule for each source package needs updating. Yes if:
+    # 1. package name contains non-word characters
+    # 2. the config setting REGEN_MAKERULE is set to true
+    # 3. package is current and the make rule for the package is out of date
+    $regen_mk = (
+      $regen_mk or
+      $self->config->setting ('REGEN_MAKERULE') or
+      ($package->current and not $package->makerule_uptodate)
+    );
+
+    # Update make rule for source package, if necessary
+    $count += $package->write_makerule () if $regen_mk;
+
+    # Check for duplicated rules
+    for my $srcfile (sort $package->srcfile) {
+      next unless $srcfile->type;
+
+      my %rules = $srcfile->required_rules;
+
+      for my $key (sort keys %rules) {
+        if (exists $targets{$key}) {
+          # Duplicated target: warning for most file types
+          my $status = 'WARNING';
+
+          # Duplicated target: error for the following file types
+          if (@no_duplicated_target_types and
+              $srcfile->is_type_or (@no_duplicated_target_types) and
+              $targets{$key}->is_type_or (@no_duplicated_target_types)) {
+            $status = 'ERROR';
+            $return = 0;
+          }
+
+          # Report the warning/error
+          w_report $status, ': ', $key, ': duplicated targets for building:';
+          w_report '       ', $targets{$key}->src;
+          w_report '       ', $srcfile->src;
+
+        } else {
+          $targets{$key} = $srcfile;
+        }
+      }
+    }
+  }
+
+  # Diagnostic
+  print 'Updated make rules for ', $count, ' package(s).', "\n"
+    if $count and $self->config->verbose;
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_write_makefile ();
+#
+# DESCRIPTION
+#   This internal method writes the "Makefile" for this build.
+# ------------------------------------------------------------------------------
+
+sub _write_makefile {
+  my $self = shift;
+
+  # Makefile header
+  # ----------------------------------------------------------------------------
+  my $makefile = '# Automatic Makefile' . "\n\n";
+
+  # Name of the build
+  $makefile .= 'FCM_BUILD_NAME = ' . $self->{NAME} . "\n" if $self->{NAME};
+  
+  # Location of FCM config file
+  $makefile .= 'FCM_BLD_CFG = ' . $self->cfg->src . "\n";
+
+  # Targets of the build
+  $makefile .= 'FCM_BLD_TARGETS = ' . join (' ', ($self->_set_targets)) . "\n\n";
+
+  # Perl library
+  # ----------------------------------------------------------------------------
+  {
+    my $libdir  = dirname (dirname ($INC{'Fcm/Build.pm'}));
+    my @libpath = split /:/, ($ENV{PERL5LIB} ? $ENV{PERL5LIB} : '');
+
+    if (not grep (m/$libdir/, @libpath)) {
+      $makefile .= 'export PERL5LIB := ' . $libdir;
+      $makefile .= ':$(PERL5LIB)' if exists $ENV{PERL5LIB};
+      $makefile .= "\n\n";
+    }
+  }
+
+  # Build directories
+  # ----------------------------------------------------------------------------
+  my @keys    = ('ROOT', sort grep {$_ ne 'ROOT'} keys (%{ $self->{DIR} }));
+  my $rootdir = $self->{DIR}{ROOT};
+
+  # Build sub-directories
+  for my $name (@keys) {
+    my $dir = $self->{DIR}{$name};
+    $dir    =~ s/^$rootdir/\$(FCM_ROOTDIR)/ unless $name eq 'ROOT';
+
+    $makefile .= 'export FCM_' . $name . 'DIR = ' . $dir . "\n";
+  }
+
+  $makefile .= "\n";
+
+  # Build sub-directory paths
+  for my $name (@keys) {
+    my @path = @{ $self->{PATH}{$name} };
+    shift @path;
+
+    $makefile .= 'export FCM_' . $name . 'PATH = ' .
+                 join (':', ('$(FCM_' . $name . 'DIR)', @path)) . "\n";
+  }
+
+  $makefile .= "\n";
+
+  # Build tools
+  # ----------------------------------------------------------------------------
+  # List of build tools
+  my $tool          = $self->config->setting ('TOOL');
+
+  # List of tools local to FCM, (will not be exported)
+  my %localtool     = map {($_, 1)} split (    # map into a hash table
+    /,/, $self->config->setting ('LOCALTOOL'), # split comma separated list
+  );
+
+  # Export required tools
+  my $unusual_count = 0;
+  for my $name (sort keys %$tool) {
+    # Ignore local tools
+    my $topname = (split (/__/, $name))[0];
+    next if exists $localtool{$topname};
+
+    if ($name =~ /^\w+$/) {
+      # Tools with normal name, just export it as an environment variable
+      $makefile .= 'export ' . $name . ' = ' . $tool->{$name} . "\n";
+
+    } else {
+      # Tools with unusual characters, export using a label/value pair
+      $makefile .= 'export FCM_UNUSUAL_TOOL_LABEL' . $unusual_count . ' = ' .
+                   $name . "\n";
+      $makefile .= 'export FCM_UNUSUAL_TOOL_VALUE' . $unusual_count . ' = ' .
+                   $tool->{$name} . "\n";
+      $unusual_count++;
+    }
+  }
+
+  $makefile .= "\n";
+
+  # Verbose mode
+  # ----------------------------------------------------------------------------
+  $makefile .= 'export FCM_VERBOSE ?= ' . $self->config->verbose . "\n\n";
+
+  # VPATH
+  # ----------------------------------------------------------------------------
+  # $name is internal name of build sub-directories
+  # $type is the type of files
+  for my $name (sort keys %{ $self->config->setting ('VPATH') }) {
+    my @types = split /,/, $self->config->setting ('VPATH', $name);
+
+    for my $type (sort @types) {
+      # If $type is EMPTY, it is a file with no file name extension
+      if (uc ($type) eq 'EMPTY') {
+        $makefile .= 'vpath % $(FCM_' . $name . 'PATH)' . "\n";
+
+      } elsif ($type =~ s/^(in|out)://i) {
+        if (uc ($1) eq 'IN') {
+          # If $type begins with IN:<type>, it is a list of file extensions that
+          # can be found under the INFILE_EXT hash in the configuration setting,
+          # with <type> matching a keyword in the values of the hash.
+          my %infile_ext = %{ $self->config->setting ('INFILE_EXT') };
+
+          for my $ext (sort keys %infile_ext) {
+            $makefile .= 'vpath %.' . $ext . ' $(FCM_' . $name . 'PATH)' . "\n"
+              if grep {$_ eq $type} split /::/, $infile_ext{$ext};
+          }
+
+        } else {
+          # If $type begins with OUT:<type>, it is the value of a hash element
+          # in the OUTFILE_EXT hash in the configuration setting, with <type>
+          # matching the key.
+          my $ext    = $self->config->setting ('OUTFILE_EXT', $type);
+          $makefile .= 'vpath %' . $ext . ' $(FCM_' . $name . 'PATH)' . "\n";
+        }
+
+      } else {
+        # Otherwise, $type is a VPATH pattern recognised by "make".
+        $makefile .= 'vpath ' . $type . ' $(FCM_' . $name . 'PATH)' . "\n";
+      }
+    }
+  }
+
+  # VPATH for dummy files
+  $makefile .= 'vpath %.dummy $(FCM_DONEDIR)' . "\n";
+  $makefile .= "\n";
+
+  # Default targets
+  # ----------------------------------------------------------------------------
+  $makefile .= '.PHONY : all clean' . "\n\n";
+  $makefile .= 'all : $(FCM_BLD_TARGETS)' . "\n\n";
+  $makefile .= 'clean : ' . "\n";
+  $makefile .= "\t" . 'rm -rf';
+  for my $dir (qw/BIN LIB OBJ DONE/) {
+    $makefile .= ' $(FCM_' . $dir . 'DIR)' if exists $self->{DIR}{$dir};
+  }
+  $makefile .= "\n";
+  $makefile .= "\t" . 'rm -f lib__*' .
+               $self->config->setting (qw/OUTFILE_EXT LIB/) .
+               ' *' . $self->config->setting (qw/OUTFILE_EXT OBJ/) . "\n";
+  $makefile .= "\n";
+
+  # Targets for copy dummy
+  $makefile .= $self->config->setting (qw/MISC CPDUMMY/) . ' :' . "\n";
+  $makefile .= "\t" . 'touch $@' . "\n\n";
+
+  # Targets for all (non-main-program) objects and libraries
+  # ----------------------------------------------------------------------------
+  my %allpcks = $self->allpcks;
+  for my $key (reverse sort keys %allpcks) {
+    # Objects variable
+    my $var;
+    if ($self->config->setting ('FCM_PCK_OBJECTS', $key)) {
+      # Package name contains unusual characters, use predefined variable
+      $var = $self->config->setting ('FCM_PCK_OBJECTS', $key);
+
+    } else {
+      # Normal package name, prefix the package name with "OBJECTS__"
+      # Top level package, simply set to "OBJECTS"
+      $var = $key ? join ('__', ('OBJECTS', $key)) : 'OBJECTS';
+    }
+
+    # Export top level OBJECTS variable
+    # but keep sub-package OBJECTS variables local to the Makefile
+    $makefile .= ($var eq 'OBJECTS' ? 'export ' : '') . $var . ' =';
+
+    # Add objects from children
+    if (@{ $allpcks{$key} }) {
+      # List of sub-packages of current package
+      my @deps   = map {
+        if ($self->config->setting ('FCM_PCK_OBJECTS', $_)) {
+          # Package name contains unusual characters, use predefined variable
+          '$(' . $self->config->setting ('FCM_PCK_OBJECTS', $_) . ')';
+
+        } else {
+          # Normal package name, prefix the package name with "OBJECTS__"
+          '$(OBJECTS__' . $_ . ')';
+        }
+      } @{ $allpcks{$key} };
+
+      $makefile .= ' ' . join (' ', sort @deps);
+    }
+
+    # Add its own objects
+    if (exists $self->{PACKAGE}{$key}) {
+      # List of source files in the current package
+      my @files = sort {$a->base cmp $b->base} $self->{PACKAGE}{$key}->srcfile;
+
+      for my $file (@files) {
+        # Consider compilable source files only
+        next unless $file->objbase;
+
+        # Ignore main programs and Fortran BLOCKDATA program units
+        next if $file->is_type_or (qw/PROGRAM BLOCKDATA/);
+
+        # Add to object list
+        $makefile .= ' ' . $file->objbase;
+      }
+    }
+
+    $makefile .= "\n\n";
+
+    # Library target
+    my $lib = exists ($self->{LIB}{$key}) ? $self->{LIB}{$key} : $key;
+    $lib    = 'lib' . $lib . $self->config->setting (qw/OUTFILE_EXT LIB/);
+
+    $makefile .= $lib . ' : $(' . $var . ')' . "\n";
+    $makefile .= "\t" . 'fcm_internal archive $@ $(^F)' . "\n\n";
+  }
+
+  # Targets for top level and package flags files and dummy dependencies
+  my %src_tool   = %{ $self->config->setting ('SRC_TOOL') };
+  my %flags_tool = (LD => '', LDFLAGS => '');
+
+  for my $key (keys %src_tool) {
+    $flags_tool{$src_tool{$key}{FLAGS}} = $src_tool{$key}{COMPILER}
+      if exists $src_tool{$key}{FLAGS};
+
+    $flags_tool{$src_tool{$key}{PPKEYS}} = ''
+      if exists $src_tool{$key}{PPKEYS};
+  }
+
+  my $ext = $self->config->setting (qw/OUTFILE_EXT FLAGS/);
+  for my $name (sort keys %flags_tool) {
+    # Flags files for tool command
+    if ($flags_tool{$name}) {
+      $makefile .= $flags_tool{$name} . $ext . ' :' . "\n";
+      $makefile .= "\t" . 'touch ' . catfile ('$(FCM_FLAGSDIR)', '$@') . "\n\n";
+    }
+
+    # Top level flags files
+    $makefile .= $name . $ext . ' :';
+    $makefile .= ' ' . $flags_tool{$name} . $ext if $flags_tool{$name};
+    $makefile .= "\n\t" . 'touch ' . catfile ('$(FCM_FLAGSDIR)', '$@') . "\n\n";
+
+    # Package level flags files
+    for my $key (sort keys %allpcks) {
+      next unless @{ $allpcks{$key} }; # ignore packages without children
+
+      my $depend  = $key ? join '__', ($name, $key) : $name;
+      my @targets = sort map {$name . '__' . $_ . $ext} @{ $allpcks{$key} };
+
+      $makefile .= join (' ', @targets) . ' : ' . $depend . $ext . "\n";
+      $makefile .= "\t" . 'touch ' . catfile ('$(FCM_FLAGSDIR)', '$@') .
+                   "\n\n";
+    }
+  }
+
+  # Include source package make rules
+  # ----------------------------------------------------------------------------
+  for my $package (sort {$a->name cmp $b->name} values %{ $self->{PACKAGE} }) {
+    my $mkbase = $package->name . $self->config->setting (qw/OUTFILE_EXT MK/);
+    my $mkfile = find_file_in_path ($mkbase, $self->{PATH}{BLD});
+
+    if ($mkfile) {
+      if (index ($mkfile, $self->{DIR}{BLD}) == 0) {
+        $mkfile = catfile '$(FCM_BLDDIR)',
+                  substr ($mkfile, length ($self->{DIR}{BLD}) + 1);
+
+      } elsif (index ($mkfile, $self->{DIR}{ROOT}) == 0) {
+        $mkfile = catfile '$(FCM_ROOTDIR)',
+                  substr ($mkfile, length ($self->{DIR}{ROOT}) + 1);
+      }
+
+      $makefile .= 'include ' . $mkfile . "\n";
+
+    } else {
+      my $pck = join ('::', split (/__/, $package->name));
+      w_report 'Warning: no make rule file for source package: ', $pck;
+    }
+  }
+
+  $makefile .= "\n" . '# EOF' . "\n";
+
+  # Print Makefile
+  # ----------------------------------------------------------------------------
+  $self->_create_build_dir ('BLD');
+  my $out = catfile (
+    $self->{DIR}{BLD}, $self->config->setting (qw/MISC MAKEFILE/),
+  );
+
+  # Check whether an old file exists, if so compare current contents with it
+  my $old = '';
+
+  if (-r $out) {
+    open OLD, '<', $out or croak 'Cannot open "', $out, '" (', $!, '), abort';
+    my @lines = readline 'OLD';
+    close OLD;
+
+    $old = join ('', @lines);
+  }
+
+  # Update Makefile if changed
+  if ($old ne $makefile) {
+    open OUT, '>', $out or croak 'Cannot open "', $out, '" (', $!, '), abort';
+    print OUT $makefile;
+    close OUT or croak 'Cannot close "', $out, '" (', $!, '), abort';
+
+    print 'Updated Makefile: ', $out, "\n" if $self->config->verbose;
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_invoke_make (
+#     TARGETS => \@targets,
+#     JOBS    => $jobs,
+#     ARCHIVE => $archive,
+#   );
+#
+# DESCRIPTION
+#   This internal method invokes the "make" command to make the build.
+#
+# ARGUMENTS
+#   TARGETS - Specify targets to be built. If set, these targets will be built
+#             instead of the ones specified in the build configuration file.
+#   JOBS    - Specify number of jobs that can be handled by "make". If set,
+#             the value must be a natural integer. If not set, the default
+#             value is 1 (i.e. run "make" in serial mode).
+#   ARCHIVE - If set to "true", invoke the "archive" mode. Most build files and
+#             directories created by this build will be archived using the
+#             "tar" command. If not set, the default is not to invoke the
+#             "archive" mode.
+# ------------------------------------------------------------------------------
+
+sub _invoke_make {
+  my $self = shift;
+  my %args = @_;
+
+  # Build the make command from the specified targets
+  my @targets  = exists $args{TARGETS} ? @{ $args{TARGETS} } : qw/all/;
+  my $jobs     = exists $args{JOBS}    ? $args{JOBS}         : 1;
+  my $archive  = exists $args{ARCHIVE} ? $args{ARCHIVE}      : 0;
+  my $verbose  = $self->config->verbose;
+
+  # Create the required build directories
+  for my $dir (qw/BIN DONE ETC INC FLAGS LIB OBJ TMP/) {
+    $self->_create_build_dir ($dir);
+  }  
+
+  my @commands = ();
+  my @make_cmd = ($self->config->setting (qw/TOOL MAKE/));
+  push @make_cmd, split (/\s+/, $self->config->setting (qw/TOOL MAKEFLAGS/));
+  push @make_cmd, $self->config->setting (qw/TOOL MAKE_SILENT/)
+    unless $verbose > 2;
+
+  if ($jobs > 1) { # multi-process "make"
+    my $make_job = $self->config->setting (qw/TOOL MAKE_JOB/);
+
+    # Setup the "make" commands for each target
+    while (my $target = shift @targets) {
+      if ($target eq 'clean') { # Do not run "clean" in parallel
+        push @commands, [@make_cmd, $target];
+
+      } else {
+        push @commands, [@make_cmd, $make_job, $jobs, $target];
+      }
+    }
+
+  } else { # single process "make"
+
+    # Setup the "make" command
+    push @commands, [@make_cmd, @targets];
+
+  }
+  
+  # Run the make command
+  my $rc  = 0;
+  my $cwd = cwd;
+  print 'cd ', $self->{DIR}{BLD}, "\n" if $verbose > 2;
+  chdir $self->{DIR}{BLD};
+  while (my $cmd = shift @commands) {
+    $| = 1; # flush STDOUT before running "make"
+    print timestamp_command (&get_command_string ($cmd)) if $verbose > 2;
+    $| = 0;
+    &run_command ($cmd, ERROR => 'warn', RC => \$rc);
+    print timestamp_command (&get_command_string ($cmd), 'End') if $verbose > 2;
+    last if $rc;
+  }
+  print 'cd ', $cwd, "\n" if $verbose > 2;
+  chdir $cwd;
+
+  return $rc ? undef : 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = $self->_remove_empty_dirs ();
+#
+# DESCRIPTION
+#   This internal method removes empty build directories.
+# ------------------------------------------------------------------------------
+
+sub _remove_empty_dirs {
+  my $self = shift;
+
+  for my $name (qw/BIN CACHE DONE ETC FLAGS INC LIB PPSRC OBJ TMP/) {
+    opendir DIR, $self->{DIR}{$name};
+    my @files = readdir DIR;
+    @files    = grep !/^\.\.?$/, @files;
+    closedir DIR;
+
+    if (not @files) {
+      print 'Remove directory: ', $self->{DIR}{$name}, "\n"
+        if $self->config->verbose > 1;
+      rmdir $self->{DIR}{$name};
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = $self->_tar_build_dirs ();
+#
+# DESCRIPTION
+#   This internal method creates TAR archives for selected build directories.
+# ------------------------------------------------------------------------------
+
+sub _tar_build_dirs {
+  my $self = shift;
+
+  # Create TAR archives if necessary
+  my $cwd = cwd;
+
+  my $tar      = $self->config->setting (qw/OUTFILE_EXT TAR/);
+  my @tar_dirs = split /,/, $self->config->setting (qw/TAR_DIRS/);
+  my $verbose  = $self->config->verbose;
+
+  for my $name (@tar_dirs) {
+    my $dir = $self->{DIR}{$name};
+
+    if (-d $dir) {
+      my $base = basename ($dir);
+      print 'cd ', dirname ($dir), "\n" if $verbose > 2;
+      chdir dirname ($dir);
+
+      my $rc = &run_command (
+        [qw/tar -c -f/, $base . $tar, $base],
+        PRINT => $verbose > 1, ERROR => 'warn',
+      );
+
+      &run_command ([qw/rm -rf/, $base], PRINT => $verbose > 1) if not $rc;
+    }
+  }
+
+  print 'cd ', $cwd, "\n" if $verbose > 2;
+  chdir $cwd;
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = $self->_create_runenv_script ();
+#
+# DESCRIPTION
+#   This internal method creates the runtime environment script if necessary.
+# ------------------------------------------------------------------------------
+
+sub _create_runenv_script {
+  my $self = shift;
+
+  # More diagnostic on how to use the build
+  my @bin_dirs = grep {-d} @{ $self->{PATH}{BIN} };
+  my $etc_dir  = -d $self->{DIR}{ETC} ? $self->{DIR}{ETC} : undef;
+
+  if (@bin_dirs or $etc_dir) {
+    # Create a runtime environment script if necessary
+    my $run_env_sh_base = $self->config->setting (qw/MISC RUN_ENV_SH/);
+    my $run_env_sh      = catfile $self->{DIR}{ROOT}, $run_env_sh_base;
+
+    open FILE, '>', $run_env_sh
+      or croak $run_env_sh, ': cannot open (', $!, '), abort';
+    print FILE '#!/usr/bin/ksh', "\n";
+    print FILE 'export PATH=', join (':', @bin_dirs), ':$PATH', "\n"
+      if @bin_dirs;
+    print FILE 'export FCM_ETCDIR=', $self->{DIR}{ETC}, "\n" if $etc_dir;
+    close FILE or croak $run_env_sh, ': cannot close (', $!, '), abort';
+
+    # Create symbolic link in bin/ sub-directory for backward compatibility
+    if (-d $self->{DIR}{BIN}) {
+      my $file = catfile ($self->{DIR}{BIN}, $run_env_sh_base);
+      
+      # Remove old link if necessary
+      unlink $file if -l $file and readlink ($file) ne $run_env_sh;
+
+      # Create the new link
+      symlink $run_env_sh, $file if not -l $file;
+    }
+
+    # Information on the location/usage of the runtime environment script
+    if ($self->config->verbose > 1 and $run_env_sh) {
+      print '# ', '-' x 78, "\n";
+      print '# To use this build, source the following shell script:', "\n";
+      print '. ', $run_env_sh, "\n";
+      print '# ', '-' x 78, "\n";
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_create_lib_excl_dep ();
+#
+# DESCRIPTION
+#   This internal method creates a set of exclude dependency configurations for
+#   libraries of this build.
+# ------------------------------------------------------------------------------
+
+sub _create_lib_excl_dep {
+  my $self = shift;
+
+  if (-d $self->{DIR}{LIB}) {
+    $self->_create_build_dir ('ETC');
+    
+    my %allpcks  = $self->allpcks;
+    my $cfgext   = $self->config->setting (qw/OUTFILE_EXT CFG/);
+    my %cfglabel = %{ $self->config->setting ('CFG_LABEL') };
+
+    for my $key (reverse sort keys %allpcks) {
+      my $outcfg = Fcm::CfgFile->new (CONFIG => $self->config);
+
+      # Include configurations from sub-packages
+      for my $subpck (@{ $allpcks{$key} }) {
+        my $base = 'lib' . $subpck . $cfgext;
+        ($base = $self->{LIB}{$subpck}) =~ s/\.\w+$/$cfgext/
+          if exists ($self->{LIB}{$subpck});
+        my $file = catfile ('$HERE', $base);
+
+        $outcfg->add_line (LABEL => $cfglabel{INC}, VALUE => $file)
+          if -r catfile ($self->{DIR}{ETC}, $base);;
+      }
+
+      # Exclude dependency for source files in current package
+      if (exists $self->{PACKAGE}{$key}) {
+        my @srcfiles = $self->{PACKAGE}{$key}->srcfile;
+
+        for my $srcfile (@srcfiles) {
+          if ($srcfile->is_type ('INCLUDE')) {
+            if ($srcfile->is_type ('CPP')) {
+              $outcfg->add_line (
+                LABEL => $cfglabel{EXCL_DEP},
+                VALUE => 'H::' . $srcfile->base,
+              );
+
+            } elsif ($srcfile->is_type ('INTERFACE')) {
+              $outcfg->add_line (
+                LABEL => $cfglabel{EXCL_DEP},
+                VALUE => 'INTERFACE::' . $srcfile->base,
+              );
+
+            } else {
+              $outcfg->add_line (
+                LABEL => $cfglabel{EXCL_DEP},
+                VALUE => 'INC::' . $srcfile->base,
+              );
+            }
+
+          } elsif ($srcfile->is_type ('SOURCE')) {
+            next if $srcfile->is_type_or (qw/PROGRAM BLOCKDATA/);
+
+            if ($srcfile->is_type ('FORTRAN')) {
+              if ($srcfile->is_type (qw/FORTRAN MODULE/)) {
+                $outcfg->add_line (
+                  LABEL => $cfglabel{EXCL_DEP},
+                  VALUE => 'USE::' . $srcfile->root,
+                );
+
+              } else {
+                $outcfg->add_line (
+                  LABEL => $cfglabel{EXCL_DEP},
+                  VALUE => 'INTERFACE::' . $srcfile->interfacebase,
+                ) if $srcfile->interfacebase;
+
+                $outcfg->add_line (
+                  LABEL => $cfglabel{EXCL_DEP},
+                  VALUE => 'OBJ::' . $srcfile->root,
+                );
+              }
+
+            } else {
+              $outcfg->add_line (
+                LABEL => $cfglabel{EXCL_DEP},
+                VALUE => 'OBJ::' . $srcfile->root,
+              );
+            }
+          }
+        }
+      }
+
+      # Name of configuration file, follows the name of library
+      my $outbase ='lib' . $key . $cfgext;
+      ($outbase = $self->{LIB}{$key}) =~ s/\.\w+$/$cfgext/
+        if exists ($self->{LIB}{$key});
+      my $outfile = catfile ($self->{DIR}{ETC}, $outbase);
+
+      # Write to configuration file
+      $outcfg->print_cfg ($outfile);
+    }
+
+    # Information on the location/usage of the exclude dependency configurations
+    if ($self->config->verbose > 1) {
+      my $etcdir = $self->{DIR}{ETC};
+      print '# ', '-' x 78, "\n";
+      print <<EOF;
+# To use a library archive of this build in another FCM build, you need to
+# include in the new build configuration the corresponding configuration file
+# that has the relevant exclude dependency information. These configurations
+# files can be found in $etcdir.
+EOF
+      print '# ', '-' x 78, "\n";
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_create_build_dir ();
+#   $self->_create_build_dir ($label);
+#
+# DESCRIPTION
+#   This internal method creates a build directory. If $label is specified,
+#   the method will attempt to create a named sub-directory according to
+#   $label. Otherwise, the method attempts to create the build root
+#   directory. Returns the name of the directory if it is created successfully
+#   or if it already exists.
+# ------------------------------------------------------------------------------
+
+sub _create_build_dir {
+  my $self  = shift;
+  my $label = $_[0] ? uc $_[0] : 'ROOT';
+
+  my $dir = undef;
+
+  # Make sure the variable is set
+  if ($self->{DIR}{$label}) {
+    $dir = $self->{DIR}{$label};
+
+    # Expand relative path if necessary
+    $dir = catfile $self->{DIR}{ROOT}, $dir if $dir =~ /^\w/;
+
+  } else {
+    if ($label eq 'ROOT') {
+      w_report 'Error: build root directory not set.';
+      return;
+
+    } elsif ($self->config->setting ('DIR', $label)) {
+      $dir = catfile $self->{DIR}{ROOT}, $self->config->setting ('DIR', $label);
+
+    } else {
+      carp 'Directory label "', $label, '" not recognised';
+      return undef;
+    }
+  }
+
+  # Set up the bld directory, if required
+  if (not -d $dir) {
+    print 'Make directory: ', $dir, "\n" if $self->config->verbose > 1;
+    mkpath $dir or croak 'Cannot create directory "', $dir, '"';
+  }
+
+  $self->{DIR}{$label} = $dir unless $self->{DIR}{$label};
+
+  return $dir;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_get_inherited_paths ($name);
+#
+# DESCRIPTION
+#   This recursive internal method returns a list containing the search path
+#   for a build directory named by the internal label $name. (Please note that
+#   a build directory will only be placed into the search path if the
+#   directory exists.)
+# ------------------------------------------------------------------------------
+
+sub _get_inherited_paths {
+  my $self = shift;
+  my $name = shift;
+
+  return () unless $name and exists $self->{DIR}{$name};
+
+  my @path = ();
+
+  # Recursively inherit the search path for a this type of build directory
+  for my $use (@{ $self->{USE} }) {
+    my @cur_path = $use->_get_inherited_paths ($name);
+    unshift @path, @cur_path;
+  }
+
+  # Place the path of the current build in the front
+  unshift @path, $self->{DIR}{$name};
+
+  return @path;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_get_inherited_srcdirs ($name);
+#
+# DESCRIPTION
+#   This recursive internal method returns a list containing the search path
+#   for a source directory named by the internal package label $name. (Please
+#   note that a source directory will only be placed into the search path if
+#   the directory exists.)
+# ------------------------------------------------------------------------------
+
+sub _get_inherited_srcdirs {
+  my $self = shift;
+  my $name = shift;
+
+  return () unless $name;
+
+  my @path = ();
+
+  # Recursively inherit the search path for this source directory
+  my $key = 'SRCDIR__' . $name;
+  if ($self->_inherit_ok ($key)) {
+    for my $use (@{ $self->{USE} }) {
+      my @cur_path = $use->_get_inherited_srcdirs ($name);
+      unshift @path, @cur_path;
+    }
+  }
+
+  # Place the path of the current source in the front
+  unshift @path, $self->{SRCDIR}{$name}
+    if exists $self->{SRCDIR}{$name} and -d $self->{SRCDIR}{$name};
+
+  return @path;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_get_inherited_items ($type);
+#
+# DESCRIPTION
+#   This recursive internal method returns a list containing an inherited
+#   build item of the type $type. (Depending of $type, the returned list can
+#   be an array or a hash.)
+# ------------------------------------------------------------------------------
+
+sub _get_inherited_items {
+  my $self = shift;
+  my $type = shift;
+
+  return () if not exists $self->{$type};
+
+  if (ref $self->{$type} eq 'ARRAY') {
+
+    my @items = ();
+
+    # Recursively inherit from used builds
+    if ($self->{INHERIT}{$type}) {
+      for my $use (@{ $self->{USE} }) {
+        my @cur_items = $use->_get_inherited_items ($type);
+
+        for my $item (@cur_items) {
+          my $type_item = $type . '__' . $item;
+
+          # Check inheritance option of current item
+          next unless $self->_inherit_ok ($type_item);
+
+          # The statement ensures that there is no duplication
+          push @items, $item unless grep {$_ eq $item} @items;
+        }
+      }
+    }
+
+    # Items in current build
+    if (@{ $self->{$type} }) {
+      for my $item (@{ $self->{$type} }) {
+        # The statement ensures that there is no duplication
+        push @items, $item unless grep {$_ eq $item} @items;
+      }
+    }
+
+    return @items;
+
+  } elsif (ref $self->{$type} eq 'HASH') {
+
+    my %items = ();
+
+    # Recursively inherit from used builds
+    if ($self->{INHERIT}{$type}) {
+      for my $use (@{ $self->{USE} }) {
+        my %cur_items = $use->_get_inherited_items ($type);
+
+        for my $name (keys %cur_items) {
+          my $type_name = $type . '__' . $name;
+
+          # Check inheritance option of current item
+          next unless $self->_inherit_ok ($type_name);
+
+          # "Closer" ancestors overrides more "distant" ones
+          $items{$name} = $cur_items{$name};
+        }
+      }
+    }
+
+    # Items in current build
+    if (%{ $self->{$type} }) {
+      for my $name (keys %{ $self->{$type} }) {
+        # Settings in current build override inherited settings
+        $items{$name} = $self->{$type}{$name};
+      }
+    }
+
+    return %items;
+
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_require_pp ($name);
+#
+# DESCRIPTION
+#   This internal method returns true if source package $name requires
+#   pre-processing.
+# ------------------------------------------------------------------------------
+
+sub _require_pp {
+  my $self = shift;
+  my $name = $_[0];
+
+  my $rc    = 0;
+  my @names = 'PP';
+  push @names, (split /__/, $name);
+
+  # Check whether pre-process flag exists, going up the source package hierarchy
+  do {
+    my $cur_name = join '__', @names;
+    if (exists $self->{PP}{$cur_name}) {
+      $rc = $self->{PP}{$cur_name};
+      return $rc;
+    }
+  } while pop @names;
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_inherit_ok ($name);
+#
+# DESCRIPTION
+#   This internal method returns true if it is OK to inherit an item specified
+#   by $name, (where $name is a double underscore "__" delimited positional
+#   list of source package names).
+# ------------------------------------------------------------------------------
+
+sub _inherit_ok {
+  my $self  = shift;
+  my $name  = $_[0];
+
+  my $rc    = 1;
+  my @names = split /__/, $name;
+
+  # Check whether INHERIT flag exists, going up the source package hierarchy
+  do {
+    my $cur_name = join '__', @names;
+    if (exists $self->{INHERIT}{$cur_name}) {
+      $rc = $self->{INHERIT}{$cur_name};
+      return $rc;
+    }
+  } while pop @names;
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/lib/Fcm/BuildTask.pm
===================================================================
--- LMDZ5/branches/testing/tools/fcm/lib/Fcm/BuildTask.pm	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/lib/Fcm/BuildTask.pm	(revision 1665)
@@ -0,0 +1,406 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::BuildTask
+#
+# DESCRIPTION
+#   This class hosts information of a build task in the FCM build system.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::BuildTask;
+
+# Standard pragma
+use strict;
+use warnings;
+
+# Standard modules
+use Carp;
+use File::Compare;
+use File::Basename;
+use File::Path;
+use File::Spec::Functions;
+
+# FCM component modules
+use Fcm::Util;
+use Fcm::Timer;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $task = Fcm::BuildTask->new (
+#     CONFIG     => $config,
+#     TARGET     => $target,
+#     TARGETPATH => \@targetpath,
+#     SRCFILE    => $srcfile,
+#     DEPENDENCY => \@dependency,
+#     TASKTYPE   => $tasktype,
+#   );
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::BuildTask class.
+#
+# ARGUMENTS
+#   CONFIG     - reference to a Fcm::Config instance
+#   TARGET     - target name for this task
+#   TARGETPATH - search path for the target
+#   SRCFILE    - reference to input Fcm::SrcFile instance
+#   DEPENDENCY - list of dependencies for this target
+#   TASKTYPE   - type of task to build the target
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $self  = {
+    CONFIG      => exists $args{CONFIG}     ? $args{CONFIG}     : &main::cfg,
+    TARGET      => exists $args{TARGET}     ? $args{TARGET}     : undef,
+    TARGETPATH  => exists $args{TARGETPATH} ? $args{TARGETPATH} : [],
+    SRCFILE     => exists $args{SRCFILE}    ? $args{SRCFILE}    : undef,
+    DEPENDENCY  => exists $args{DEPENDENCY} ? $args{DEPENDENCY} : [],
+    ACTIONTYPE  => exists $args{ACTIONTYPE} ? $args{ACTIONTYPE} : undef,
+
+    OUTPUT      => undef,
+    OUTPUTMTIME => undef,
+  };
+
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = $task->config;
+#
+# DESCRIPTION
+#   This method returns a reference to the Fcm::Config instance.
+# ------------------------------------------------------------------------------
+
+sub config {
+  my $self = shift;
+
+  return $self->{CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $srcfile = $task->srcfile;
+#   $task->srcfile ($srcfile);
+#
+# DESCRIPTION
+#   This method returns the reference to the input Fcm::SrcFile instance
+#   associated with this task. If an argument is specified, the reference is
+#   modified to the value given by the argument.
+# ------------------------------------------------------------------------------
+
+sub srcfile {
+  my $self = shift;
+
+  if (@_) {
+    $self->{SRCFILE} = $_[0];
+  }
+
+  return $self->{SRCFILE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $actiontype = $task->actiontype;
+#   $task->actiontype ($actiontype);
+#
+# DESCRIPTION
+#   This method returns the action type of this task. If an argument is
+#   specified, the action type of this task is set to the value of the
+#   argument.
+# ------------------------------------------------------------------------------
+
+sub actiontype {
+  my $self = shift;
+
+  if (@_) {
+    $self->{ACTIONTYPE} = $_[0];
+  }
+
+  return $self->{ACTIONTYPE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $output = $task->output;
+#   $task->output ($output);
+#
+# DESCRIPTION
+#   This method returns the name of the output file after the task has been
+#   performed successfully. If an argument is specified, it sets the output
+#   file (and its last modified time) to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub output {
+  my $self = shift;
+
+  if (@_) {
+    $self->{OUTPUT}      = $_[0];
+    $self->{OUTPUTMTIME} = (stat $self->{OUTPUT}) [9];
+  }
+
+  return $self->{OUTPUT};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $time = $task->outputmtime;
+#
+# DESCRIPTION
+#   This method returns the modified time of the output file.
+# ------------------------------------------------------------------------------
+
+sub outputmtime {
+  my $self = shift;
+
+  return $self->{OUTPUTMTIME};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = $task->action (TASKLIST => \%tasklist);
+#
+# DESCRIPTION
+#   This method performs the task action and sets the output accordingly. The
+#   argument TASKLIST must be a reference to a hash containing the other tasks
+#   of the build, which this task may depend on. The keys of the hash must the
+#   name of the target names of the tasks, and the values of the hash must be
+#   the references to the corresponding Fcm::BuildTask instances. The method
+#   returns true if the task has been performed to create a new version of the
+#   target.
+# ------------------------------------------------------------------------------
+
+sub action {
+  my $self     = shift;
+  my %args     = @_;
+  my $tasklist = exists $args{TASKLIST} ? $args{TASKLIST} : {};
+
+  return unless $self->actiontype;
+
+  my $uptodate     = 1;
+  my $dep_uptodate = 1;
+
+  # Check if dependencies are up to date
+  # ----------------------------------------------------------------------------
+  for my $depend (@{ $self->{DEPENDENCY} }) {
+    if (exists $tasklist->{$depend}) {
+      if (not $tasklist->{$depend}->output) {
+        # Dependency task output is not set, performs its task action
+        if ($tasklist->{$depend}->action (TASKLIST => $tasklist)) {
+          $uptodate     = 0;
+          $dep_uptodate = 0;
+        }
+      }
+
+    } elsif ($self->config->verbose > 1) {
+      w_report 'Warning: Task for "', $depend,
+               '" does not exist, may be required by ', $self->{TARGET};
+    }
+  }
+
+  # Check if the target exists in the search path
+  # ----------------------------------------------------------------------------
+  if (@{ $self->{TARGETPATH} }) {
+    my $output = find_file_in_path ($self->{TARGET}, $self->{TARGETPATH});
+    $self->output ($output) if $output;
+  }
+
+  # Target is out of date if it does not exist
+  if ($uptodate) {
+    $uptodate = 0 if not $self->output;
+  }
+
+  # Check if current target is older than its dependencies
+  # ----------------------------------------------------------------------------
+  if ($uptodate) {
+    for my $depend (@{ $self->{DEPENDENCY} }) {
+      next unless exists $tasklist->{$depend};
+
+      if ($tasklist->{$depend}->outputmtime > $self->outputmtime) {
+        $uptodate     = 0;
+        $dep_uptodate = 0;
+      }
+    }
+
+    if ($uptodate and ref $self->srcfile) {
+      $uptodate = 0 if $self->srcfile->mtime > $self->outputmtime;
+    }
+  }
+
+  if ($uptodate) {
+    # Current target and its dependencies are up to date
+    # --------------------------------------------------------------------------
+    if ($self->actiontype eq 'PP') {
+      # "done" file up to date, set name of pre-processed source file
+      # ------------------------------------------------------------------------
+      my $base     = $self->srcfile->root . lc ($self->srcfile->ext);
+      my @pck_list = $self->srcfile->get_package_list;
+      pop @pck_list;
+      my @pknames  = split '__', pop (@pck_list);
+      my @path     = map {
+        catfile ($_, @pknames);
+      } @{ $self->config->setting (qw/PATH PPSRC/) };
+      my $oldfile = find_file_in_path ($base, \@path);
+      $self->srcfile->ppsrc ($oldfile);
+    }
+
+  } else {
+    # Perform action is not up to date
+    # --------------------------------------------------------------------------
+    # (For GENINTERFACE and PP, perform action if "done" file not up to date)
+    my $new_output = @{ $self->{TARGETPATH} }
+                     ? catfile ($self->{TARGETPATH}[0], $self->{TARGET})
+                     : $self->{TARGET};
+
+    # Create destination container directory if necessary
+    my $destdir = dirname $new_output;
+
+    if (not -d $destdir) {
+      print 'Make directory: ', $destdir, "\n" if $self->config->verbose > 2;
+      mkpath $destdir;
+    }
+
+    # List of actions
+    if ($self->actiontype eq 'UPDATE') {
+      # Action is UPDATE: Update file
+      # ------------------------------------------------------------------------
+      print 'Update: ', $new_output, "\n" if $self->config->verbose > 2;
+      touch_file $new_output
+        or croak 'Unable to update "', $new_output, '", abort';
+      $self->output ($new_output);
+
+    } elsif ($self->actiontype eq 'COPY') {
+      # Action is COPY: copy file to destination if necessary
+      # ------------------------------------------------------------------------
+      my $copy_required = ($dep_uptodate and $self->output and -r $self->output)
+                          ? compare ($self->output, $self->srcfile->src)
+                          : 1;
+
+      if ($copy_required) {
+        # Set up copy command
+        &run_command (
+          ['cp', $self->srcfile->src, $destdir],
+          TIME => $self->config->verbose > 2,
+        );
+
+        $self->output ($new_output);
+
+      } else {
+        $uptodate = 1;
+      }
+
+    } elsif ($self->actiontype eq 'PP' or $self->actiontype eq 'GENINTERFACE') {
+      # Action is PP or GENINTERFACE: process file
+      # ------------------------------------------------------------------------
+      my ($newlines, $base, @path);
+
+      if ($self->actiontype eq 'PP') {
+        # Invoke the pre-processor on the source file
+        # ----------------------------------------------------------------------
+        # Get lines in the pre-processed source
+        $newlines = $self->srcfile->pre_process;
+        $base     = $self->srcfile->root . lc ($self->srcfile->ext);
+
+        # Get search path for the existing pre-processed file
+        my @pck_list = $self->srcfile->get_package_list;
+        pop @pck_list;
+        my @pknames  = split '__', pop (@pck_list);
+        @path        = map {
+          catfile ($_, @pknames);
+        } @{ $self->config->setting (qw/PATH PPSRC/) };
+
+      } else { # if ($self->actiontype eq 'GENINTERFACE')
+        # Invoke the interface generator
+        # ----------------------------------------------------------------------
+        # Get new interface lines
+        $newlines = $self->srcfile->gen_interface;
+
+        # Get search path for the existing interface file
+        $base     = $self->srcfile->interfacebase;
+        @path     = @{ $self->config->setting (qw/PATH INC/) },
+      }
+
+
+      # If pre-processed or interface file exists,
+      # compare its content with new lines to see if it has been updated
+      my $update_required = 1;
+      my $oldfile = find_file_in_path ($base, \@path);
+
+      if ($oldfile and -r $oldfile) {
+        # Read old file
+        open FILE, '<', $oldfile;
+        my @oldlines = readline 'FILE';
+        close FILE;
+
+        # Compare old contents and new contents
+        if (@oldlines eq @$newlines) {
+          $update_required = grep {
+            $oldlines[$_] ne $newlines->[$_];
+          } (0 .. $#oldlines);
+        }
+      }
+
+      if ($update_required) {
+        # Update the pre-processed source or interface file
+        # ----------------------------------------------------------------------
+        # Determine container directory of the  pre-processed or interface file
+        my $newfile = @path ? catfile ($path[0], $base) : $base;
+
+        # Create the container directory if necessary
+        if (not -d $path[0]) {
+          print 'Make directory: ', $path[0], "\n"
+            if $self->config->verbose > 1;
+          mkpath $path[0];
+        }
+
+        # Update the pre-processor or interface file
+        open FILE, '>', $newfile
+          or croak 'Cannot write to "', $newfile, '" (', $!, '), abort';
+        print FILE @$newlines;
+        close FILE
+          or croak 'Cannot write to "', $newfile, '" (', $!, '), abort';
+        print 'Generated: ', $newfile, "\n" if $self->config->verbose > 1;
+
+        # Set the name of the pre-processed file
+        $self->srcfile->ppsrc ($newfile) if $self->actiontype eq 'PP';
+
+        # Set the "current" flag of the container source package to "true"
+        $self->srcfile->srcpackage->current (1);
+
+      } else {
+        # Content in pre-processed source or interface file is up to date
+        # ----------------------------------------------------------------------
+        $uptodate = 1;
+
+        # Set the name of the pre-processed file
+        $self->srcfile->ppsrc ($oldfile) if $self->actiontype eq 'PP';
+      }
+
+      # Update the "done" file
+      print 'Update: ', $new_output, "\n" if $self->config->verbose > 2;
+      touch_file $new_output
+        or croak 'Unable to update "', $new_output, '", abort';
+      $self->output ($new_output);
+
+    } else {
+      carp 'Action type "', $self->actiontype, "' not supported";
+    }
+  }
+
+  return not $uptodate;
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/lib/Fcm/CfgFile.pm
===================================================================
--- LMDZ5/branches/testing/tools/fcm/lib/Fcm/CfgFile.pm	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/lib/Fcm/CfgFile.pm	(revision 1665)
@@ -0,0 +1,861 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::CfgFile
+#
+# DESCRIPTION
+#   This class is used for reading and writing FCM config files. A FCM config
+#   file is a line-based text file that provides information on how to perform
+#   a particular task using the FCM system.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::CfgFile;
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Standard modules
+use Carp;
+use File::Basename;
+use File::Path;
+use File::Spec;
+use File::Spec::Functions;
+
+# FCM component modules
+use Fcm::Util;
+
+# Local module variables
+my $expand_type   = 'bld|ext'; # config file type that needs variable expansions
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfgfile = Fcm::CfgFile->new (CONFIG=> $config, SRC => $src, TYPE => $type);
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::CfgFile class.
+#
+# ARGUMENTS
+#   CONFIG - reference to a Fcm::Config instance
+#   SRC    - configuration file source
+#   TYPE   - type of expected configuration file
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $self = {
+    CONFIG     => exists $args{CONFIG} ? $args{CONFIG} : &main::cfg,
+    SRC        => exists $args{SRC}    ? $args{SRC}    : undef,
+    TYPE       => exists $args{TYPE}   ? $args{TYPE}   : undef,
+
+    # Version of the configuration file
+    VERSION    => undef,
+
+    # List of references to hash tables for each line in the file
+    LINES      => [],
+
+    # Actual source of configuration file
+    ACTUAL_SRC => undef,
+    PEGREV     => undef,
+  };
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = $cfgfile->config;
+#
+# DESCRIPTION
+#   This method returns a reference to the Fcm::Config instance.
+# ------------------------------------------------------------------------------
+
+sub config {
+  my $self = shift;
+
+  return $self->{CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $src = $cfgfile->src ();
+#   $cfgfile->src ($src);
+#
+# DESCRIPTION
+#   This method returns the specified source of the configuration file. If an
+#   argument is specified, the source of the configuration file is modified to
+#   the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub src {
+  my $self = shift;
+
+  if (@_) {
+    $self->{SRC} = shift;
+  }
+
+  return $self->{SRC};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $src = $cfgfile->actual_src ();
+#
+# DESCRIPTION
+#   This method returns the actual source of the configuration file. If an
+#   argument is specified, the source of the configuration file is modified to
+#   the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub actual_src {
+  my $self = shift;
+
+  return $self->{ACTUAL_SRC};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rev = $cfgfile->pegrev ();
+#
+# DESCRIPTION
+#   This method returns the peg revision of the configuration file.
+# ------------------------------------------------------------------------------
+
+sub pegrev {
+  my $self = shift;
+
+  return $self->{PEGREV};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $type = $cfgfile->type ();
+#   $cfgfile->type ($type);
+#
+# DESCRIPTION
+#   This method returns the configuration file type. If an argument is
+#   specified, the type is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub type {
+  my $self = shift;
+
+  if (@_) {
+    $self->{TYPE} = shift;
+  }
+
+  return $self->{TYPE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $version = $cfgfile->version ();
+#
+# DESCRIPTION
+#   This method returns the version of the configuration file.
+# ------------------------------------------------------------------------------
+
+sub version {
+  my $self = shift;
+
+  return $self->{VERSION};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @lines = $cfgfile->lines ();
+#
+# DESCRIPTION
+#   This method returns an array containing all "lines" in the configuration
+#   file. Each "line" is a reference to a hash table with the following keys:
+#
+#   SRC     - the source of the configuration file
+#   NUMBER  - the line number in the source
+#   LABEL   - the label of the of the configuration line
+#   VALUE   - the value of the configuration line
+#   COMMENT - comment in the configuration line
+# ------------------------------------------------------------------------------
+
+sub lines {
+  my $self = shift;
+
+  return @{ $self->{LINES} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $line = $cfgfile->line ($line_number);
+#
+# DESCRIPTION
+#   This method return a "line" at $line_number in the configuration file. A
+#   "line" is a reference to a hash table with the following keys:
+#
+#   SRC     - the source of the configuration file
+#   NUMBER  - the line number in the source
+#   LABEL   - the label of the of the configuration line
+#   VALUE   - the value of the configuration line
+#   COMMENT - comment in the configuration line
+# ------------------------------------------------------------------------------
+
+sub line {
+  my $self     = shift;
+  my $line_num = shift;
+
+  if (exists $self->{LINES}[$line_num]) {
+    return $self->{LINES}[$line_num]; # returns a ref to a label:value pair hash
+
+  } else {
+    return undef;
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfgfile->add_line (
+#     LABEL   => $label,
+#     VALUE   => $value,
+#     COMMENT => $comment,
+#     SRC     => $src,
+#     NUMBER  => $line_number
+#   );
+#
+# DESCRIPTION
+#   This method adds a "line" to the configuration file. LABEL is the
+#   configuration line label. VALUE is the configuration line value. COMMENT
+#   is the comment in the line. VALUE should only be specified if LABEL is
+#   specified. COMMENT can be specified without LABEL. In such case, the whole
+#   line is a comment line. A blank line is inserted if no argument is
+#   specified. SRC can be specified to indicate the name of the source file
+#   from which this line is obtained. If not specified, the source file of the
+#   current configuration file is used. NUMBER can be specified to indicate
+#   the line number of the source file from which this line is obtained.
+# ------------------------------------------------------------------------------
+
+sub add_line {
+  my $self = shift;
+  my %args = @_;
+
+  my $line = {
+    SRC     => exists $args{SRC    } ? $args{SRC    } : $self->actual_src,
+    NUMBER  => exists $args{NUMBER } ? $args{NUMBER } : 0,
+    LABEL   => exists $args{LABEL  } ? $args{LABEL  } : '',
+    VALUE   => exists $args{VALUE  } ? $args{VALUE  } : '',
+    COMMENT => exists $args{COMMENT} ? $args{COMMENT} : '',
+  };
+
+  push @{ $self->{LINES} }, $line;
+
+  return $line;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfgfile->add_comment_block ($line1, [$line2, ...]);
+#
+# DESCRIPTION
+#   This method adds a comment block to the configuration file. Each argument
+#   represents a line in the comment block.
+# ------------------------------------------------------------------------------
+
+sub add_comment_block {
+  my $self = shift;
+
+  $self->add_line (COMMENT => '-' x 78,);
+
+  while (my $line = shift @_) {
+    $self->add_line (COMMENT => $line,)
+  }
+
+  $self->add_line (COMMENT => '-' x 78,);
+  $self->add_line;
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfgfile->add_header ();
+#
+# DESCRIPTION
+#   This method adds a header to the configuration file, with its type and
+#   type version. It returns 1 on success.
+# ------------------------------------------------------------------------------
+
+sub add_header {
+  my $self = shift;
+
+  return undef unless $self->{TYPE};
+
+  $self->{VERSION} = $self->config->setting ('CFG_VERSION', uc ($self->{TYPE}))
+    if not $self->{VERSION};
+
+  $self->add_comment_block ('File header');
+
+  $self->add_line (
+    LABEL => $self->config->setting (qw/CFG_LABEL CFGFILE TYPE/),
+    VALUE => $self->{TYPE},
+  );
+
+  $self->add_line (
+    LABEL => $self->config->setting (qw/CFG_LABEL CFGFILE VERSION/),
+    VALUE => $self->{VERSION},
+  );
+
+  $self->add_line;
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $exist = $cfg->label_exists ($label);
+#   @lines = $cfg->label_exists ($label);
+#
+# DESCRIPTION
+#   This method returns the (number of) "lines" with their LABEL matching the
+#   argument $label.
+# ------------------------------------------------------------------------------
+
+sub label_exists {
+  my $self  = shift;
+  my $label = shift;
+
+  return grep {$_->{LABEL} eq $label} @{ $self->{LINES} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $mtime = $cfgfile->mtime ();
+#
+# DESCRIPTION
+#   This method returns the modified time of the configuration file source.
+# ------------------------------------------------------------------------------
+
+sub mtime {
+  my $self  = shift;
+  my $mtime = undef;
+
+  if (-f $self->{SRC}) {
+    $mtime = (stat $self->{SRC})[9];
+  }
+
+  return $mtime;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $read = $cfgfile->read_cfg ();
+#
+# DESCRIPTION
+#   This method reads the current configuration file. It returns the number of
+#   lines read from the config file, or "undef" if it fails. The result is
+#   placed in the LINES array of the current instance, and can be accessed via
+#   the "lines" method.
+# ------------------------------------------------------------------------------
+
+sub read_cfg {
+  my $self = shift;
+
+  my @lines = $self->_get_cfg_lines;
+
+  # List of CFG labels
+  my %cfg_labels = %{ $self->config->setting ('CFG_LABEL') };
+
+  # List of CFG types that need INC declarations expansion
+  my %exp_inc    = ();
+  for (split (/,/, $self->config->setting ('CFG_EXP_INC'))) {
+    $exp_inc{uc ($_)} = 1;
+  }
+
+  # List of CFG labels that are reserved keywords
+  my %cfg_keywords = ();
+  for (split (/,/, $self->config->setting ('CFG_KEYWORD'))) {
+    $cfg_keywords{$cfg_labels{$_}} = 1;
+  }
+
+  # Loop each line, to separate lines into label : value pairs
+  my $cont = undef;
+  my $here = undef;
+  for my $line_num (1 .. @lines) {
+    my $line = $lines[$line_num - 1];
+    chomp $line;
+
+    my $label   = '';
+    my $value   = '';
+    my $comment = '';
+
+    # If this line is a continuation, set $start to point to the line that
+    # starts this continuation. Otherwise, set $start to undef
+    my $start   = defined ($cont) ? $self->line ($cont) : undef;
+
+    if ($line =~ /^(\s*#.*)$/) { # comment line
+      $comment = $1;
+
+    } elsif ($line =~ /\S/) {    # non-blank line
+      if (defined $cont) {
+        # Previous line has a continuation mark
+        $value = $line;
+
+        # Separate value and comment
+        if ($value =~ s/((?:\s+|^)#\s+.*)$//) {
+          $comment = $1;
+        }
+
+        # Remove leading spaces
+        $value =~ s/^\s*\\?//;
+
+        # Expand environment variables
+        $value = $self->_expand_variable ($value, 1) if $value;
+
+        # Expand internal variables
+        $value = $self->_expand_variable ($value) if $value;
+
+        # Get "line" that begins the current continuation
+        ($start->{VALUE} .= $value) =~ s/\\$//;
+
+      } else {
+        # Previous line does not have a continuation mark
+        if ($line =~ /^\s*(\S+)(?:\s+(.*))?$/) {
+          # Check line contains a valid label:value pair
+          $label = $1;
+          $value = defined ($2) ? $2 : '';
+
+          # Separate value and comment
+          if ($value =~ s/((?:\s+|^)#\s+.*)$//) {
+            $comment = $1;
+          }
+
+          # Remove trailing spaces
+          $value =~ s/\s+$//;
+
+          # Value begins with $HERE?
+          $here  = ($value =~ /\$\{?HERE\}?(?:[^A-Z_]|$)/);
+
+          # Expand environment variables
+          $value = $self->_expand_variable ($value, 1) if $value;
+
+          # Expand internal variables
+          $value = $self->_expand_variable ($value) if $value;
+        }
+      }
+
+      # Determine whether current line ends with a continuation mark
+      if ($value =~ s/\\$//) {
+        $cont = scalar ($self->lines) unless $cont;
+
+      } else {
+        $cont = undef;
+      }
+    }
+
+    if (exists $exp_inc{uc ($self->type)} and
+        uc ($start ? $start->{LABEL} : $label) eq $cfg_labels{INC} and
+        not defined $cont) {
+      # Current configuration file requires expansion of INC declarations
+      # The start/current line is an INC declaration
+      # The current line is not a continuation or is the end of the continuation
+
+      # Get lines from an "include" configuration file
+      my $src = ($start ? $start->{VALUE} : $value);
+      $src   .= '@' . $self->pegrev if $here and $self->pegrev;
+
+      if ($src) {
+        # Invoke a new instance to read the source
+        my $cfg = Fcm::CfgFile->new (
+          SRC    => expand_tilde ($src),
+          TYPE   => $self->type,
+          CONFIG => $self->config,
+        );
+
+        $cfg->read_cfg;
+
+        # Add lines to the "LINES" array in the current configuration file
+        $comment = 'INC ' . $src . ' ';
+        $self->add_line (
+          COMMENT => $comment . '# Start',
+          NUMBER  => ($start ? $start->{NUMBER} : $line_num),
+        );
+        $self->add_line (%{ $_ }) for (($cfg->lines));
+        $self->add_line (COMMENT => $comment . '# End');
+
+      } else {
+        $self->add_line (NUMBER  => $line_num);
+        w_report 'Warning: ', $self->actual_src, ': line ', $line_num,
+                 ': empty INC declaration.' if $self->config->verbose > 2;
+      }
+
+    } else {
+      # Push label:value pair into "LINES" array
+      $self->add_line (
+        LABEL   => $label,
+        VALUE   => ($label ? $value : ''),
+        COMMENT => $comment,
+        NUMBER  => $line_num,
+      );
+    }
+
+    next if defined $cont; # current line not a continuation
+
+    my $slabel = ($start ? $start->{LABEL} : $label);
+    my $svalue = ($start ? $start->{VALUE} : $value);
+    next unless $slabel;
+
+    # Check config file type and version
+    if (uc ($slabel) eq $cfg_labels{CFGFILE}{TYPE}) {
+      $self->type ($svalue);
+
+    } elsif (uc ($slabel) eq $cfg_labels{CFGFILE}{VERSION}) {
+      $self->version ($svalue);
+    }
+
+    # Set internal variable
+    $slabel =~ s/^\%//; # Remove leading "%" from label
+
+    $self->config->assign_variable (
+      LABEL => $slabel,
+      VALUE => $svalue,
+    ) unless exists $cfg_keywords{$slabel};
+  }
+
+  return $self->lines;
+
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = $cfgfile->print_cfg ($file);
+#
+# DESCRIPTION
+#   This method prints the content of current configuration file. If no
+#   argument is specified, it prints output to the standard output. If $file
+#   is specified, and is a writable file name, the output is sent to the file.
+#   If the file already exists, its content is compared to the current output.
+#   Nothing will be written if the content is unchanged. Otherwise, for typed
+#   configuration files, the existing file is renamed using a prefix that
+#   contains its last modified time. The method returns 1 if there is no
+#   error.
+# ------------------------------------------------------------------------------
+
+sub print_cfg {
+  my $self = shift;
+  my $file = shift;
+
+  # Count maximum number of characters in the labels, (for pretty printing)
+  my $max_label_len = 0;
+  for my $line (@{ $self->{LINES} }) {
+    next unless $line->{LABEL};
+    my $label_len  = length $line->{LABEL};
+    $max_label_len = $label_len if $label_len > $max_label_len;
+  }
+
+  # Output string
+  my $out = '';
+
+  # Append each line of the config file to the output string
+  for my $line (@{ $self->{LINES} }) {
+    my $label   = $line->{LABEL};
+    my $value   = $line->{VALUE};
+    my $comment = $line->{COMMENT};
+
+    if ($label) {
+      # Line up label/value for pretty printing
+      $label   = $label . ' ' x ($max_label_len - length ($label));
+      $comment =~ s/^\s+/ / if $comment;
+
+      $out .= $label;
+      $out .= ' ' . $value if defined $value;
+
+    } else {
+      # Make sure comments begin with a "#"
+      $comment = '# ' . $comment if $comment and $comment !~ /^\s*($|#)/;
+      $comment =~ s/^\s*//;
+    }
+
+    $out .= $comment if $comment;
+    $out .= "\n";
+  }
+
+  if ($out) {
+
+    my $old_select = select;
+
+    # Open file if necessary
+    if ($file) {
+      # Make sure the host directory exists and is writable
+      my $dirname = dirname $file;
+      if (not -d $dirname) {
+        print 'Make directory: ', $dirname, "\n" if $self->config->verbose;
+        mkpath $dirname;
+      }
+      croak 'Cannot write to config file directory: "', $dirname, '", abort'
+        unless -d $dirname and -w $dirname;
+
+      # If config file already exists, make sure it is writable
+      if (-f $file) {
+        if (-r $file) {
+          # Read old config file to see if content has changed
+          open IN, '<', $file;
+          my $in_lines = '';
+          while (my $line = <IN>) {
+            $in_lines .= $line;
+          }
+          close IN;
+
+          # Return if content is up-to-date
+          if ($in_lines eq $out) {
+            print 'No change in ', lc ($self->{TYPE}), ' cfg: ', $file,
+                  "\n" if $self->config->verbose > 1 and $self->{TYPE};
+            return;
+          }
+        }
+
+        if (-w $file) {
+          if ($self->{TYPE}) {
+            # Existing config file writable, rename it using its time stamp
+            my $mtime = (stat $file)[9];
+            my ($sec, $min, $hour, $mday, $mon, $year) = (gmtime $mtime)[0 .. 5];
+            my $timestamp = sprintf '%4d%2.2d%2.2d_%2.2d%2.2d%2.2d_',
+                            $year + 1900, $mon + 1, $mday, $hour, $min, $sec;
+            my $oldfile   = catfile $dirname, $timestamp . basename ($file);
+            rename $file, $oldfile;
+            print 'Renamed existing ', lc ($self->{TYPE}), ' cfg: ',
+                  $oldfile, "\n" if $self->config->verbose > 1;
+          }
+        } else {
+          # Existing config file not writable, throw an error
+          croak 'Config file "', $file, '" not writable, abort';
+        }
+      }
+
+      # Open file and select file handle
+      open OUT, '>', $file
+        or croak 'Cannot write to config file "', $file, '" (', $!, '), abort';
+      select OUT;
+    }
+
+    # Print output
+    print $out;
+
+    # Close file if necessary
+    if ($file) {
+      select $old_select;
+      close OUT;
+
+      if ($self->{TYPE} and $self->config->verbose > 1) {
+        print 'Generated ', lc ($self->{TYPE}), ' cfg: ', $file, "\n";
+      } elsif ($self->config->verbose > 2) {
+        print 'Generated cfg: ', $file, "\n";
+      }
+    }
+
+  } else {
+
+    # Warn if nothing to print
+    my $warning = 'Empty configuration';
+    $warning   .= ' - nothing written to file: "' . $file . '"' if $file;
+    carp $warning if $self->{TYPE};
+
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @lines = $self->_get_cfg_lines ();
+#
+# DESCRIPTION
+#   This internal method reads from a configuration file residing in a
+#   Subversion repository or in the normal file system.
+# ------------------------------------------------------------------------------
+
+sub _get_cfg_lines {
+  my $self  = shift;
+  my @lines = ();
+
+  my $verbose = $self->config->verbose;
+
+  # Expand URL keywords if necessary
+  {
+    my $src = expand_url_keyword (URL => $self->src, CFG => $self->config);
+    $self->src ($src) if $src ne $self->src;
+  }
+
+  if (&is_url ($self->src)) {
+    # Config file resides in a SVN repository
+    # --------------------------------------------------------------------------
+    # Set URL source and version
+    my $src = $self->src;
+    my $rev = 'HEAD';
+
+    # Extract version from source if it exists
+    if ($src =~ s/@(.+)$//) {
+      $rev = $1;
+    }
+
+    # Expand revision keyword, if required
+    $rev = expand_rev_keyword (REV => $rev, URL => $src, HEAD => 1);
+
+    # Check whether URL is a config file
+    my $rc;
+    my @cmd = (qw/svn cat/, $src . '@' . $rev);
+    @lines = &run_command (
+      \@cmd, METHOD => 'qx', DEVNULL => 1, RC => \$rc, ERROR => 'ignore',
+    );
+
+    # Error in "svn cat" command
+    if ($rc) {
+      # See whether specified config file is a known type
+      my %cfgname = %{ $self->config->setting ('CFG_NAME') };
+      my $key     = uc $self->type;
+      my $file    = exists $cfgname{$key} ? $cfgname{$key} : '';
+
+      # If config file is a known type, specified URL may be a directory
+      if ($file) {
+        # Check whether a config file with a default name exists in the URL
+        my $sep  = $self->config->setting (qw/MISC DIR_SEPARATOR/);
+        my $path = $src . $sep . $file;
+        my @cmd  = (qw/svn cat/, $path . '@' . $rev);
+
+        @lines = &run_command (
+          \@cmd, METHOD => 'qx', DEVNULL => 1, RC => \$rc, ERROR => 'ignore',
+        );
+
+        # Check whether a config file with a default name exists under the "cfg"
+        # sub-directory of the URL
+        if ($rc) {
+          my $cfgdir = $self->config->setting (qw/DIR CFG/);
+          $path   = $src . $sep . $cfgdir . $sep . $file;
+          my @cmd = (qw/svn cat/, $path . '@' . $rev);
+
+          @lines  = &run_command (
+            \@cmd, METHOD => 'qx', DEVNULL => 1, RC => \$rc, ERROR => 'ignore',
+          );
+        }
+
+        $src = $path unless $rc;
+      }
+    }
+
+    if ($rc) {
+      # Error in "svn cat"
+      croak 'Unable to locate config file from "', $self->src, '", abort';
+
+    } else {
+      # Print diagnostic, if necessary
+      if ($verbose and $self->type and $self->type =~ /$expand_type/) {
+        print '# Config file (', $self->type, '): ', $src;
+        print '@', $rev if $rev;
+        print "\n";
+      }
+    }
+
+    # Record the actual source location
+    $self->{PEGREV    } = $rev;
+    $self->{ACTUAL_SRC} = $src;
+
+  } else {
+    # Config file resides in the normal file system
+    # --------------------------------------------------------------------------
+    my $src = $self->src;
+
+    if (-d $src) { # Source is a directory
+      croak 'Config file "', $src, '" is a directory, abort' if not $self->type;
+
+      # Get name of the config file by looking at the type
+      my %cfgname = %{ $self->config->setting ('CFG_NAME') };
+      my $key     = uc $self->type;
+      my $file    = exists $cfgname{$key} ? $cfgname{$key} : '';
+
+      if ($file) {
+        my $cfgdir = $self->config->setting (qw/DIR CFG/);
+
+        # Check whether a config file with a default name exists in the
+        # specified path, then check whether a config file with a default name
+        # exists under the "cfg" sub-directory of the specified path
+        if (-f catfile $self->src, $file) {
+          $src = catfile $self->src, $file;
+
+        } elsif (-f catfile ($self->src, $cfgdir, $file)) {
+          $src = catfile $self->src, $cfgdir, $file;
+
+        } else {
+          croak 'Unable to locate config file from "', $self->src, '", abort';
+        }
+
+      } else {
+        croak 'Unknown config file type "', $self->type, '", abort';
+      }
+    }
+
+    if (-r $src) {
+      open FILE, '<', $src;
+      print '# Config file (', $self->type, '): ', $src, "\n"
+        if $verbose and $self->type and $self->type =~ /$expand_type/;
+
+      @lines = readline 'FILE';
+      close FILE;
+
+    } else {
+      croak 'Unable to read config file "', $src, '", abort';
+    }
+
+    # Record the actual source location
+    $self->{ACTUAL_SRC} = $src;
+  }
+
+  return @lines;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = $self->_expand_variable ($string[, $env]);
+#
+# DESCRIPTION
+#   This internal method expands variables in $string. If $env is specified
+#   and is true, it expands environment variables. Otherwise, it expands
+#   local variables.
+# ------------------------------------------------------------------------------
+
+sub _expand_variable {
+  my ($self, $string, $env) = @_;
+
+  # Pattern for environment/local variable
+  my $pattern = $env ? '\$\{?([A-Z][A-Z0-9_]+)\}?' : '%\{?([\w:]+)\}?';
+
+  while ($string and $string =~ /$pattern/) {
+    my $var_label = $1; # variable label
+
+    # Get variable value from environment or local configuration
+    my $variable = $env
+                   ? (exists $ENV{$var_label} ? $ENV{$var_label} : undef)
+                   : $self->config->variable ($var_label);
+
+    $variable = dirname ($self->actual_src)
+      if $env and $var_label eq 'HERE' and not defined $variable;
+
+    # Substitute match with value of variable
+    if (defined $variable) {
+      $string =~ s/$pattern/$variable/;
+
+    } else {
+      w_report 'Warning: ', $self->actual_src, ': variable "',
+               ($env ? '$' : '%'), $var_label, '" not expanded.';
+      last;
+    }
+  }
+
+  return $string;
+}
+
+1;
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/lib/Fcm/Cm.pm
===================================================================
--- LMDZ5/branches/testing/tools/fcm/lib/Fcm/Cm.pm	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/lib/Fcm/Cm.pm	(revision 1665)
@@ -0,0 +1,2243 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::Cm
+#
+# DESCRIPTION
+#   This module contains the FCM code management functionalities and wrappers
+#   to Subversion commands.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::Cm;
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Standard modules
+our (@ISA, @EXPORT, @EXPORT_OK);
+use Getopt::Long;
+use File::Basename;
+use File::Path;
+use File::Spec;
+use File::Temp qw/tempfile/;
+use Cwd;
+
+# FCM component modules
+use Fcm::CmBranch;
+use Fcm::CmUrl;
+use Fcm::Util;
+
+sub cm_command;
+
+require Exporter;
+@ISA = qw(Exporter);
+@EXPORT = qw(
+  cm_command
+);
+
+# Function declaration:
+sub cm_add;
+sub cm_branch;
+sub cm_commit;
+sub cm_conflicts;
+sub cm_delete;
+sub cm_diff;
+sub cm_merge;
+sub cm_mkpatch;
+sub cm_svn;
+sub cm_switch;
+sub _construct_branch_url;
+
+# ------------------------------------------------------------------------------
+
+my @subcommand_url = qw/
+  blame     praise annotate ann
+  branch    br
+  cat
+  checkout  co
+  copy      cp
+  delete    del    remove   rm
+  diff      di
+  export
+  import
+  info
+  list      ls
+  lock
+  log
+  merge
+  mkdir
+  mkpatch
+  move      mv     rename   ren
+  propdel   pdel   pd
+  propedit  pedit  pe
+  propget   pget   pg
+  proplist  plist  pl
+  propset   pset   ps
+  switch    sw
+  unlock
+/; # List of subcommands that accept URL inputs
+
+my @subcommand_rev = qw/
+  blame     praise annotate ann
+  branch    br
+  cat
+  checkout  co
+  copy      cp
+  diff      di
+  export
+  info
+  list      ls
+  log
+  merge
+  mkpatch
+  move      mv     rename   ren
+  propdel   pdel   pd
+  propedit  pedit  pe
+  propget   pget   pg
+  proplist  plist  pl
+  propset   pset   ps
+  switch    sw
+  update    up
+/; # List of subcommands that accept revision inputs
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &cm_command ($function);
+#
+# DESCRIPTION
+#   This is the generic FCM code management wrapper. It calls the correct FCM
+#   code management function or a wrapper to a Subversion command based on the
+#   value of the argument $function.
+# ------------------------------------------------------------------------------
+
+sub cm_command {
+
+  my ($function) = shift @_;
+
+  # Expand URL keywords if necessary
+  if (grep {$_ eq $function} @subcommand_url) {
+    for my $arg (@ARGV) {
+      my $var = expand_url_keyword (URL => $arg);
+      $arg = $var if $arg ne $var;
+    }
+  }
+
+  # Expand revision keywords (for -r or --revision options) if necessary
+  if (grep {$_ eq $function} @subcommand_rev) {
+    my @new_argv = ();
+
+    while (defined (my $arg = shift @ARGV)) {
+      if ($arg eq '--revision') {
+        # Long --revision option, must be followed by a space before the
+        # revision argument
+        push @new_argv, $arg;
+
+      } elsif ($arg =~ s/^-r//) {
+        # Short -r option, may be followed by the revision argument with or
+        # without a space in between
+        push @new_argv, '--revision';
+        unshift @ARGV, $arg if $arg;
+
+      } else {
+        # Other option or argument
+        push @new_argv, $arg;
+        next;
+      }
+
+      # First revision number/keyword
+      my $rev1 = '';
+
+      # Get the next argument from the list
+      $arg = shift @ARGV;
+
+      if (index ($arg, '{') == 0) {
+        # A revision date argument may contain a space. Therefore, it may need
+        # the next argument(s) from the list
+        while (index ($arg, '}') == -1) {
+          my $shift = shift @ARGV;
+          last unless $shift;
+          $arg     .= ' ' . $shift;
+        }
+
+        $arg  =~ s/^(\{.+?\})//;
+        $rev1 = $1;
+
+      } else {
+        # Other revision argument
+        $arg  =~ s/^(\S+?)(?::|$)//;
+        $rev1 = $1;
+      }
+
+      # The rest of $arg is the second revision number/keyword
+      my $rev2 = $arg;
+      $rev2 =~ s/^:*//;
+
+      # A revision date argument may contain a space. Therefore, it may need
+      # the next argument(s) from the list
+      if (index ($rev2, '{') == 0) {
+        while (index ($rev2, '}') == -1) {
+          my $shift = shift @ARGV;
+          last unless $shift;
+          $rev2    .= ' ' . $shift;
+        }
+      }
+
+      # Expand revision keyword if necessary
+      if ($rev1 !~ /^(?:\d+|HEAD|BASE|COMMITTED|PREV|\{.+\})$/i or
+          $rev2 !~ /^(?:\d+|HEAD|BASE|COMMITTED|PREV|\{.+\})$/i) {
+        # Find out the associated URLs by inspecting the argument list
+        my $url1 = '';
+        my $url2 = '';
+
+        for (@new_argv, @ARGV) {
+          my $arg = Fcm::CmUrl->new (URL => $_);
+          next unless $arg->is_url;
+
+          if ($url1) {
+            $url2 = $arg->url_peg;
+            last;
+
+          } else {
+            $url1 = $arg->url_peg;
+          }
+        }
+
+        # Argument list does not contain a URL, try "svn info" on WC
+        $url1 = &get_url_of_wc () if not $url1;
+        $url2 = $url1 if not $url2;
+
+        # Expand 1st revision keyword if necessary
+        $rev1 = expand_rev_keyword (REV => $rev1, URL => $url1)
+          if $rev1 !~ /^(?:\d+|HEAD|BASE|COMMITTED|PREV|\{.+\})$/i;
+
+        # Expand 2nd revision keyword if necessary
+        $rev2 = expand_rev_keyword (REV => $rev2, URL => $url2)
+          if $rev2 and $rev2 !~ /^(?:\d+|HEAD|BASE|COMMITTED|PREV|\{.+\})$/i;
+      }
+
+      # Append revision argument to argument list
+      push @new_argv, ($rev2 ? $rev1 . ':' . $rev2 : $rev1);
+    }
+
+    @ARGV = @new_argv;
+  }
+
+  # Expand revision keywords (for peg revision TARGET@REVSION) if necessary
+  for (@ARGV) {
+    if (m#^(\w+://\S+)@(\S+)$#) {
+      my $url = $1;
+      my $rev = $2;
+
+      my $new_rev = expand_rev_keyword (URL => $url, REV => $rev, HEAD => 1);
+
+      $_ = $url . '@' . $new_rev if $new_rev ne $rev;
+    }
+  }
+
+  # List of special sub-commands recognised by FCM
+  my %subcommand = (
+    ADD       => [qw/add/],
+    BRANCH    => [qw/branch br/],
+    COMMIT    => [qw/commit ci/],
+    CONFLICTS => [qw/conflicts cf/],
+    CHECKOUT  => [qw/checkout co/],
+    DELETE    => [qw/delete del remove rm/],
+    DIFF      => [qw/diff di/],
+    MERGE     => [qw/merge/],
+    MKPATCH   => [qw/mkpatch/],
+    SWITCH    => [qw/switch sw/],
+  );
+
+  if (grep {$_ eq $function} @{ $subcommand{ADD} }) {
+    cm_add;
+
+  } elsif (grep {$_ eq $function} @{ $subcommand{BRANCH} }) {
+    cm_branch;
+
+  } elsif (grep {$_ eq $function} @{ $subcommand{CHECKOUT} }) {
+    # Check whether the last argument is a PATH.
+    # If so, check whether it is a working copy.
+    # Otherwise, check whether the current directory is a working copy.
+    # If current working direcory (or PATH) is a working copy, fail the command.
+    if (@ARGV) {
+      my $arg  = Fcm::CmUrl->new (URL => $ARGV [-1]);
+      my $path = $arg->is_url ? cwd () : $ARGV [-1];
+
+      e_report $path, ': already a working copy, abort checkout.'
+        if &is_wc ($path);
+    }
+
+    # Invoke checkout
+    cm_svn ('checkout');
+
+  } elsif (grep {$_ eq $function} @{ $subcommand{COMMIT} }) {
+    cm_commit;
+
+  } elsif (grep {$_ eq $function} @{ $subcommand{CONFLICTS} }) {
+    cm_conflicts;
+
+  } elsif (grep {$_ eq $function} @{ $subcommand{DELETE} }) {
+    cm_delete;
+
+  } elsif (grep {$_ eq $function} @{ $subcommand{DIFF} }) {
+    cm_diff;
+
+  } elsif (grep {$_ eq $function} @{ $subcommand{MERGE} }) {
+    cm_merge;
+
+  } elsif (grep {$_ eq $function} @{ $subcommand{MKPATCH} }) {
+    cm_mkpatch;
+
+  } elsif (grep {$_ eq $function} @{ $subcommand{SWITCH} }) {
+    cm_switch;
+
+  } else {
+    cm_svn ($function);
+  }
+
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &Fcm::Cm::cm_add ();
+#
+# DESCRIPTION
+#   This is a wrapper to "svn add". It adds an extra functionality to check
+#   for any files or directories reported by "svn status" as not under version
+#   control, and to prompt the user whether these files or directories should
+#   be added.
+# ------------------------------------------------------------------------------
+
+sub cm_add {
+
+  # Print usage message if requested
+  if (defined ($ARGV[0]) and grep {$_ eq $ARGV[0]} qw(--help -h)) {
+    print <<EOF;
+usage: fcm add [options] [args]
+
+Valid options:
+  -c [--check]  : Check for any files or directories reported by svn status as
+                  not under version control and add them.
+  <SVN options> : Standard options to svn add as described below ...
+
+EOF
+
+    &run_command ([qw/svn add --help/], PRINT => 1, METHOD => 'exec');
+  }
+
+  if (defined ($ARGV[0]) and grep {$_ eq $ARGV[0]} qw(--check -c)) {
+    # The --check option is specified, add any new files
+    # Execute "svn status", print lines starting with a "?"
+    my $pat    = '^\?.{4}\s*';
+    my @status = grep /$pat.*/, &run_command ([qw/svn status/], METHOD => 'qx');
+    print @status if @status;
+
+    # Get list of "?" files
+    my @files  = map {chomp; s/$pat//; $_} @status;
+    my $reply  = '';
+
+    # Execute "add" command depending on user reply
+    for my $file (@files) {
+      # Get a user reply, unless previous reply is "a" for "all"
+      $reply = &main::get_input (
+        TITLE   => 'fcm add',
+        MESSAGE => "Add file '$file'?",
+        TYPE    => 'yna',
+        DEFAULT => 'n',
+      ) unless $reply eq "a";
+
+      # Add current $file if reply is "y" for "yes" or "a" for "all"
+      &run_command ([qw/svn add/, $file]) if $reply =~ /^[ya]$/;
+    }
+
+  } else {
+    # The --check option is not specified, just call "svn add"
+    cm_svn ("add");
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &Fcm::Cm::cm_branch ();
+#
+# DESCRIPTION
+#   This is a FCM command to check information, create or delete a branch in
+#   a Subversion repository.
+# ------------------------------------------------------------------------------
+
+sub cm_branch {
+  my $usage = <<EOF;
+branch: Create, delete or display information of a branch
+usage: 1. fcm branch [--info] [OPTIONS] [TARGET]
+       2. fcm branch --delete [OPTIONS] [TARGET]
+       3. fcm branch --create [OPTIONS] [SOURCE]
+       4. fcm branch --list   [OPTIONS] [SOURCE]
+
+  1. --info or -i: Display information about a branch. This is the default
+     option if --create, --delete and --list are not specified.
+
+  2. --delete or -d: Delete a branch.
+
+  3. --create or -c: Create a new branch from SOURCE. The --name option must be
+     used to specify a short name for the new branch.
+
+  4. --list or -l: List all the branches owned by the current user in SOURCE. If
+     the --user option is specified with a list of users, list all the branches
+     owned by these users instead of the current user.
+
+  TARGET (and SOURCE) can be an URL or a Subversion working copy. Otherwise,
+  the current working directory must be a working copy. For --info and
+  --delete, the specified URL (or the URL of the working copy) must be a URL
+  under a valid branch in a standard FCM project. For --create and --list, it
+  must be a URL under a standard FCM project.
+
+Valid options with --info and --delete:
+  -v [--verbose]        : Print extra information.
+  -a [--show-all]       : Set --show-children, --show-other and --show-siblings.
+  --show-children       : Report children of the current branch.
+  --show-other          : Report custom/ reverse merges into the current branch.
+  --show-siblings       : Report merges with siblings of the current branch.
+
+Valid options with --delete and --create:
+  --non-interactive     : Do no interactive prompting. This option implies
+                          --svn-non-interactive.
+  --password arg        : Specify a password for write access to the repository.
+  --svn-non-interactive : Do no interactive prompting at commit time. This
+                          option is implied by --non-interactive.
+
+Valid options with --create and --list:
+  -r [--revision] arg   : Specify the operative revision of the SOURCE for
+                          creating the branch.
+
+Valid options with --create:
+  --branch-of-branch    : If this option is specified and the SOURCE is a
+                          branch, it will create a new branch from the SOURCE
+                          branch. Otherwise, the branch is created from the
+                          trunk.
+  -k [--ticket] arg     : Specify one (or more) Trac ticket. If specified, the
+                          command will add to the commit log the line "Relates
+                          to ticket #<ticket>". Multiple tickets can be set by
+                          specifying this option multiple times, or by
+                          specifying the tickets in a comma-separated list.
+  -n [--name] arg       : Specify a short name for the branch, which should
+                          contain only word characters, i.e. [A-Za-z0-9_].
+  --rev-flag arg        : Specify a flag for determining the prefix of the
+                          branch name. The flag can be the the string "NORMAL",
+                          "NUMBER" or "NONE".  "NORMAL" is the default
+                          behaviour, in which the branch name will be prefixed
+                          with a Subversion revision number if the revision is
+                          not associated with a registered FCM revision
+                          keyword. If the revision is registered with a FCM
+                          revision keyword, the keyword will be used in place
+                          of the number. If "NUMBER" is specified, the branch
+                          name will always be prefixed with a Subversion
+                          revision number. If "NONE" is specified, the branch
+                          name will not be prefixed by a revision number or
+                          keyword.
+  -t [--type] arg       : Specify the type of the branch to be created. It must
+                          be one of the following:
+                            DEV::USER   - a development branch for the user
+                            DEV::SHARE  - a shared development branch
+                            DEV         - same as DEV::USER
+                            TEST::USER  - a test branch for the user
+                            TEST::SHARE - a shared test branch
+                            TEST        - same as TEST::USER
+                            PKG::USER   - a package branch for the user
+                            PKG::SHARE  - a shared package branch
+                            PKG::CONFIG - a configuration branch
+                            PKG::REL    - a release branch
+                            PKG         - same as PKG::USER
+                            CONFIG      - same as PKG::CONFIG
+                            REL         - same as PKG::REL
+                            SHARE       - same as DEV::SHARE
+                            USER        - same as DEV::USER
+                          If not specified, the default is to create a
+                          development branch for the current user, i.e.
+                          DEV::USER.
+
+Valid options with --list:
+  -u [--user] arg       : Specify a colon-separated list of users. List branches
+                          owned by these users instead of the current user.
+  -v [--verbose]        : Print Subversion URL instead of FCM URL keywords.
+EOF
+
+  # Print usage message if requested
+  if (defined ($ARGV[0]) and grep {$_ eq $ARGV[0]} qw(--help -h)) {
+    print $usage;
+    return 1;
+  }
+
+  # Process command line options
+  # ----------------------------------------------------------------------------
+  my (
+    $info,
+    $delete,
+    $create,
+    $list,
+    $branch_of_branch,
+    $name,
+    $non_interactive,
+    $password,
+    $rev,
+    $rev_flag,
+    $show_all,
+    $show_children,
+    $show_other,
+    $show_siblings,
+    $svn_non_interactive,
+    @tickets,
+    $type,
+    @userlist,
+    $verbose,
+  );
+  GetOptions (
+    'info|i'              => \$info,
+    'delete|d'            => \$delete,
+    'create|c'            => \$create,
+    'list|l'              => \$list,
+    'branch-of-branch'    => \$branch_of_branch,
+    'name|n=s'            => \$name,
+    'non-interactive'     => \$non_interactive,
+    'password=s'          => \$password,
+    'revision|r=s'        => \$rev,
+    'rev-flag=s'          => \$rev_flag,
+    'show-all|a'          => \$show_all,
+    'show-children'       => \$show_children,
+    'show-other'          => \$show_other,
+    'show-siblings'       => \$show_siblings,
+    'svn-non-interactive' => \$svn_non_interactive,
+    'ticket|k=s'          => \@tickets,
+    'type|t=s'            => \$type,
+    'user|u=s'            => \@userlist,
+    'verbose|v'           => \$verbose,
+  );
+
+  my $num_options = 0;
+  $num_options++ if defined $info;
+  $num_options++ if defined $delete;
+  $num_options++ if defined $create;
+  $num_options++ if defined $list;
+
+  # Report invalid usage
+  # ----------------------------------------------------------------------------
+  e_report $usage if $num_options > 1;
+
+  # Get URL of repository or branch
+  # ----------------------------------------------------------------------------
+  my $url;
+  if ($ARGV[0]) {
+    $url = Fcm::CmUrl->new (URL => $ARGV[0]);
+
+    if (not $url->is_url) {
+      # An argument is specified and is not a URL
+      # Assume that it is a path with a working copy
+      if (&is_wc ($ARGV[0])) {
+        $url = Fcm::CmUrl->new (URL => &get_url_of_wc ($ARGV[0]));
+
+      } else {
+        e_report $ARGV[0], ': is not a working copy, abort.';
+      }
+    }
+
+  } else {
+    # An argument is not specified
+    # Assume that the current directory is a working copy
+    if (&is_wc ()) {
+      $url = Fcm::CmUrl->new (URL => &get_url_of_wc ());
+
+    } else {
+      e_report 'The current directory is not a working copy, please specify a ',
+               'URL or a path to a working copy, abort.';
+    }
+  }
+
+  # Ensure $url->url_peg is a URL of a standard FCM project
+  e_report $url->url_peg, ': not a URL of a standard FCM project, abort.'
+    if not $url->project_url;
+
+  if ($create) {
+    # The --create option is specified, create a branch
+    # --------------------------------------------------------------------------
+
+    # Check branch type flags
+    if ($type) {
+      $type = uc ($type);
+
+      if ($type =~ /^(USER|SHARE)$/) {
+        $type = 'DEV::' . $1;
+
+      } elsif ($type =~ /^(CONFIG|REL)$/) {
+        $type = 'PKG::' . $1;
+
+      } elsif ($type =~ /^(DEV|TEST|PKG)$/) {
+        $type = $1 . '::USER';
+
+      } elsif ($type !~ /^(?:DEV|TEST|PKG)::(?:USER|SHARE)$/ and
+               $type !~ /^PKG::(?:CONFIG|REL)/) {
+        e_report $type, ': is not a valid type flag, abort.';
+      }
+
+    } else {
+      $type = 'DEV::USER';
+    }
+
+    # Check branch name
+    e_report 'The option --name must be used to specify a branch name, abort.'
+      if not $name;
+
+    e_report $name, ': invalid characters in name, abort.' if $name !~ /^\w+$/;
+
+    # Check revision flag is valid
+    if ($rev_flag) {
+      $rev_flag = uc ($rev_flag);
+
+      e_report $rev_flag, ': invalid argument to the --rev-flag option, abort.'
+        if $rev_flag !~ /^(?:NORMAL|NUMBER|NONE)$/;
+
+    } else {
+      $rev_flag = 'NORMAL';
+    }
+
+    # Handle multiple tickets
+    @tickets = split (/,/, join (',', @tickets));
+    s/^#// for (@tickets);
+    @tickets = sort {$a <=> $b} @tickets;
+
+    # Determine whether to create a branch of a branch
+    $url->branch ('trunk') unless $branch_of_branch;
+
+    # Create the branch
+    my $branch = Fcm::CmBranch->new;
+    $branch->create (
+      SRC                 => $url,
+      TYPE                => $type,
+      NAME                => $name,
+      PASSWORD            => $password,
+      REV_FLAG            => $rev_flag,
+      TICKET              => \@tickets,
+      REV                 => $rev,
+      NON_INTERACTIVE     => $non_interactive,
+      SVN_NON_INTERACTIVE => $svn_non_interactive,
+    );
+
+  } elsif ($list) {
+    # The option --list is specified
+    # List branches owned by current or specified users
+    # --------------------------------------------------------------------------
+    # Get URL of the project "branches/" sub-directory
+    $url->subdir ('');
+    $url->branch ('');
+    my @list = map {$_, 1} $url->branch_list ($rev);
+
+    if (@userlist) {
+      # Sort list of users
+      @userlist = sort (split /:/, join (':', @userlist));
+
+    } else {
+      # No user specified, add currrent user to list
+      push @userlist, $ENV{LOGNAME} unless @userlist;
+    }
+
+    # Filter branches matching user list
+    my @branches;
+    for my $branch (@list) {
+      next unless $branch =~ m#/([^/]+)/[^/]+/*$#;
+
+      my $user = $1;
+
+      push @branches, $branch if grep {$user eq $_} @userlist;
+    }
+
+    # Output, number of branches found
+    print scalar (@branches), ' ',
+          (scalar (@branches) > 1 ? 'branches' : 'branch'), ' found for ',
+          join (', ', @userlist), ' in ', $url->project_url_peg,
+          ($rev ? (' at r', $rev) : ()), "\n";
+
+    if (@branches) {
+      # Output the URL of each branch
+      if (not $verbose) {
+        my $project = $url->project_url;
+        my $keyword = &get_url_keyword (URL => $project);
+        @branches = map {s#^$project/+branches#$keyword-br#; $_} @branches
+          if defined $keyword;
+      }
+      @branches = map {$_ . "\n"} sort @branches;
+      print @branches;
+
+    } else {
+      # No branch found, exit with an error code
+      exit 1;
+    }
+
+  } else {
+    # The option --info or --delete is specified
+    # Report branch information (and/or delete a branch)
+    # --------------------------------------------------------------------------
+    # Set verbose level
+    &main::cfg->verbose ($verbose ? 1 : 0);
+
+    # Set up the branch, report any error
+    my $branch = Fcm::CmBranch->new (URL => $url->url_peg);
+    e_report $branch->url_peg, ': not a branch, abort.' unless $branch->branch;
+
+    e_report $branch->url_peg, ': does not exist, abort.'
+      unless $branch->url_exists;
+
+    # Remove the sub-directory part of the URL
+    $branch->subdir ('');
+
+    # Report branch info
+    $branch->display_info (
+      SHOW_CHILDREN => ($show_all || $show_children),
+      SHOW_OTHER    => ($show_all || $show_other   ),
+      SHOW_SIBLINGS => ($show_all || $show_siblings),
+    );
+
+    # Delete branch if --delete is specified
+    $branch->del (
+      PASSWORD            => $password,
+      NON_INTERACTIVE     => $non_interactive,
+      SVN_NON_INTERACTIVE => $svn_non_interactive,
+    ) if $delete;
+  }
+
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &Fcm::Cm::cm_commit ();
+#
+# DESCRIPTION
+#   This is a FCM wrapper to the "svn commit" command.
+# ------------------------------------------------------------------------------
+
+sub cm_commit {
+
+  # Print usage message if requested
+  if (defined ($ARGV[0]) and grep {$_ eq $ARGV[0]} qw(--help -h)) {
+    print <<EOF;
+commit (ci): Send changes from your working copy to the repository.
+usage: fcm commit [PATH]
+
+  Invoke your favourite editor to prompt you for a commit log message. Send
+  changes from your working copy to the repository. Update your working copy
+  following the commit.
+
+Valid options:
+  --dry-run             : Allows you to add to the commit message without
+                          committing.
+  --svn-non-interactive : Do no interactive prompting at commit time.
+  --password arg        : Specify a password ARG.
+EOF
+    return 1;
+  }
+
+  my ($dry_run, $svn_non_interactive, $password);
+  GetOptions (
+    'dry-run'             => \$dry_run,
+    'svn-non-interactive' => \$svn_non_interactive,
+    'password'            => \$password,
+  );
+
+  # The remaining argument is the path to a working copy
+  my ($path) = @ARGV;
+
+  if ($path) {
+    # Check that specified path exists
+    e_report $path, ': does not exist, abort.' if not -e $path;
+
+  } else {
+    # No argument specified, use current working directory
+    $path = cwd ();
+  }
+
+  # Make sure we are in a working copy
+  e_report $path, ': not a working copy, abort.' if not &is_wc ($path);
+
+  # Make sure we are at the top level of the working copy
+  # (otherwise we might miss any template commit message)
+  my $dir = &get_wct ($path);
+
+  if ($dir ne cwd ()) {
+    chdir $dir or die 'Cannot change directory to: ', $dir;
+    print 'Committing changes from ', $dir, ' ...', "\n";
+  }
+
+  # Get update status of working copy
+  # Check working copy files are not in conflict, missing, or out of date
+  my @status = &run_command ([qw/svn status --show-updates/], METHOD => 'qx');
+  unless (defined $dry_run) {
+    my (@conflict, @missing, @outdate);
+
+    for (@status) {
+      if (/^C/) {
+        push @conflict, $_;
+        next;
+      }
+
+      if (/^!/) {
+        push @missing, $_;
+        next;
+      }
+
+      if (/^.{7}\*/) {
+        push @outdate, $_;
+        next;
+      }
+
+      # Check that all files which have been added have the svn:executable
+      # property set correctly (in case the developer adds a script before they
+      # remember to set the execute bit)
+      next unless /^A.{7} *\d+ +(.*)/;
+      my $file = $1;
+
+      next unless -f $file;
+      my @command = (-x $file)
+                    ? (qw/svn propset -q svn:executable */, $file)
+                    : (qw/svn propdel -q svn:executable/  , $file);
+      &run_command (\@command);
+    }
+
+    # Abort commit if files are in conflict, missing, or out of date
+    if (@conflict or @missing or @outdate) {
+      w_report 'File(s) in conflict:', "\n", @conflict if @conflict;
+      w_report 'File(s) missing:'    , "\n", @missing  if @missing;
+      w_report 'File(s) out of date:', "\n", @outdate  if @outdate;
+      e_report 'Abort commit.';
+    }
+  }
+
+  # Read in any existing message
+  my $ci_mesg = Fcm::CmCommitMessage->new ();
+  $ci_mesg->read_file;
+
+  # Execute "svn status" for a list of changed items
+  @status = grep !/^\?/, &run_command ([qw/svn status/], METHOD => 'qx');
+
+  # Abort if there is no change in the working copy
+  if (not @status) {
+    print 'No change in working copy, abort.', "\n";
+    return;
+  }
+
+  # Get associated URL of current working copy
+  my $url = Fcm::CmUrl->new (URL => &get_url_of_wc ());
+
+  # Include URL, or project, branch and sub-directory info in @status
+  unshift @status, "\n";
+
+  if ($url->project and $url->branch) {
+    unshift @status, (
+      '[Project: ' . $url->project                           . ']' . "\n",
+      '[Branch : ' . $url->branch                            . ']' . "\n",
+      '[Sub-dir: ' . ($url->subdir ? $url->subdir : '<top>') . ']' . "\n",
+    );
+
+  } else {
+    unshift @status, '[URL: ' . $url->url . ']' . "\n";
+  }
+
+  # Use a temporary file to store the final commit log message
+  $ci_mesg->ignore_mesg (@status);
+  my $logfile = $ci_mesg->edit_file (TEMP => 1);
+
+  # Check with the user to see if he/she wants to go ahead
+  my $reply = 'n';
+  if (not defined $dry_run) {
+    # Add extra warning for trunk commit
+    my $mesg = $url->is_trunk
+      ? "\n" .
+        '*** WARNING: YOU ARE COMMITTING TO THE TRUNK.' . "\n" .
+        '*** Please ensure that your change conforms to your project\'s ' .
+        'working practices.' . "\n\n"
+      : '';
+    $mesg   .= 'Would you like to commit this change?';
+
+    # Prompt the user
+    $reply = &main::get_input (
+      TITLE   => 'fcm commit',
+      MESSAGE => $mesg,
+      TYPE    => 'yn',
+      DEFAULT => 'n',
+    );
+  }
+
+  if ($reply eq 'y') {
+    # Commit the change if user replies "y" for "yes"
+    my @command = (
+      qw/svn commit -F/, $logfile,
+      ($svn_non_interactive  ? '--non-interactive'       : ()),
+      (defined $password     ? ('--password', $password) : ()),
+    );
+    my $rc;
+    &run_command (\@command, RC => \$rc, ERROR => 'warn');
+
+    if ($rc) {
+      # Commit failed
+      # Write temporary commit log content to commit log message file
+      $ci_mesg->write_file;
+
+      # Fail the command
+      e_report;
+    }
+
+    # Remove commit message file
+    unlink $ci_mesg->file;
+
+    # Update the working copy
+    print 'Performing update to make sure your working copy is at this new ',
+          'revision ...', "\n";
+    &run_command ([qw/svn update/]);
+
+  } else {
+    # Abort commit if dry run or user replies "n" for "no"
+    w_report 'Commit aborted by user.' unless $dry_run;
+
+    # Write temporary commit log content to commit log message file
+    $ci_mesg->write_file;
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &Fcm::Cm::cm_conflicts ();
+#
+# DESCRIPTION
+#   This is a FCM command for resolving conflicts within working copy using a
+#   graphical merge tool.
+# ------------------------------------------------------------------------------
+
+sub cm_conflicts {
+
+  # Print usage message if requested
+  if (defined ($ARGV[0]) and grep {$_ eq $ARGV[0]} qw(--help -h)) {
+    print <<EOF;
+conflicts: Use graphical tool to resolve any conflicts within your working copy.
+usage: fcm conflicts [PATH]
+
+  Invoke the xxdiff graphical merge tool to help you resolve conflicts in your
+  working copy. It prompts you to run "svn resolved" each time you have
+  resolved the conflicts in a file.
+EOF
+    return 1;
+  }
+
+  # Path to the working copy
+  my $path = $ARGV[0];
+  $path    = cwd () if not $path;
+
+  # Check for any files with conflicts
+  my @status = grep /^C.{4} *(.*)/, &run_command (
+    [qw/svn st/, ($path eq cwd () ? () : $path)], METHOD => 'qx',
+  );
+  my @files  = map {m/^C.{4} *(.*)/; $1} @status;
+
+  # Save current working directory
+  my $topdir = cwd ();
+
+  for my $file (@files) {
+    # Print name of file in conflicts
+    print "Conflicts in file: $file\n";
+
+    # Determine directory and base name of file in conflicts
+    my $base = basename $file;
+    my $dir  = dirname $file;
+
+    # Change to container directory of file in conflicts
+    chdir File::Spec->catfile ($topdir, $dir) or die "Directory change to $dir failed";
+
+    # Use "svn info" to determine conflict marker files
+    my @info = &run_command ([qw/svn info/, $base], METHOD => 'qx');
+
+    # Ignore if $base is a binary file
+    if (-B $base) {
+      w_report $base,
+               ': ignoring binary file, please resolve conflicts manually.';
+      next;
+    }
+
+    # Get conflicts markers files
+    my ($older, $mine, $yours);
+
+    for (@info) {
+      $older = $1 if (/^Conflict Previous Base File: (.*)/);
+      $mine  = $1 if (/^Conflict Previous Working File: (.*)/);
+      $yours = $1 if (/^Conflict Current Base File: (.*)/);
+    }
+
+    if ((stat $base)[9] > (stat $mine)[9]) {
+      # If $base is newer, it may contain saved changes
+      my $reply = &main::get_input (
+        TITLE   => 'fcm conflicts',
+        MESSAGE => 'Existing changes in ' . $base . ' will be overwritten.' .
+                   "\n" . 'Do you wish to continue?',
+        TYPE    => 'yn',
+        DEFAULT => 'n',
+      );
+
+      next if $reply ne 'y';
+    }
+
+    # Launch "xxdiff" to allow user to perform graphical merging
+    my $xxdiffrc;
+    my @command  = (qw/xxdiff -m -M/, $base, qw/-O -X/, $mine, $older, $yours);
+    my ($decision) = &run_command (
+      \@command, METHOD => 'qx', RC => \$xxdiffrc, ERROR => 'ignore',
+    );
+    die &get_command_string (\@command), ' failed' if $xxdiffrc and ! $decision;
+    chomp $decision;
+
+    # Perform different actions depending on the user's decision
+    if ($decision eq "NODECISION") {
+      print "No decision taken\n";
+
+    } elsif ($decision eq "MERGED" and $xxdiffrc != 0) {
+      print "Merge conflicts were not all resolved\n";
+
+    } else {
+      # User has MERGED, ACCEPTED or REJECTED all changes
+      if ($decision eq "MERGED") {
+        print "All merge conflicts resolved\n";
+
+      } else {
+        print "You have chosen to $decision all the changes\n";
+      }
+
+      # Prompt user to run "svn resolved" on the file
+      my $reply = &main::get_input (
+        TITLE   => 'fcm conflicts',
+        MESSAGE => 'Would you like to run "svn resolved"?',
+        TYPE    => 'yn',
+        DEFAULT => 'n',
+      );
+
+      # If reply is "yes"...
+      &run_command ([qw/svn resolved/, $base]) if $reply eq 'y';
+    }
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &Fcm::Cm::cm_delete ();
+#
+# DESCRIPTION
+#   This is a wrapper to "svn delete". It adds an extra functionality to check
+#   for any files or directories reported by "svn status" as missing, and to
+#   prompt the user whether these files or directories should be deleted.
+# ------------------------------------------------------------------------------
+
+sub cm_delete {
+
+  # Print usage message if requested
+  if (defined ($ARGV[0]) and grep {$_ eq $ARGV[0]} qw(--help -h)) {
+    print <<EOF;
+usage: fcm delete [options] [args]
+
+Valid options:
+  -c [--check]  : Check for any files or directories reported by svn status as
+                  missing and delete them.
+  <SVN options> : Standard options to svn delete as described below ...
+
+EOF
+
+    &run_command ([qw/svn delete --help/], PRINT => 1, METHOD => 'exec');
+  }
+
+  if (defined ($ARGV[0]) and grep {$_ eq $ARGV[0]} qw(--check -c)) {
+    # The --check option is specified, delete any missing files
+    # Execute "svn status", print lines starting with a "!"
+    my $pat    = '^!.{4}\s*';
+    my @status = grep /$pat.*/, &run_command ([qw/svn status/], METHOD => 'qx');
+    print @status if @status;
+
+    # Get list of "!" files
+    my @files  = map {chomp; s/$pat//; $_} @status;
+    my $reply  = '';
+
+    # Execute "delete" command depending on user reply
+    for my $file (@files) {
+      # Get a user reply, unless previous reply is "a" for "all"
+      $reply = &main::get_input (
+        TITLE   => 'fcm delete',
+        MESSAGE => "Delete file '$file'?",
+        TYPE    => 'yna',
+        DEFAULT => 'n',
+      ) unless $reply eq "a";
+
+      # Delete current $file if reply is "y" for "yes" or "a" for "all"
+      &run_command ([qw/svn delete/, $file]) if $reply =~ /^[ya]$/;
+    }
+
+  } else {
+    # The --check option is not specified, just call "svn delete"
+    cm_svn ("delete");
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &Fcm::Cm::cm_diff ();
+#
+# DESCRIPTION
+#   This is a wrapper to "svn diff". It adds two extra functionalities. The
+#   first one allows the command to show differences relative to the base of
+#   the branch. The second one allows differences to be displayed via a
+#   graphical tool.
+# ------------------------------------------------------------------------------
+
+sub cm_diff {
+
+  # Print usage message if requested
+  if (defined ($ARGV[0]) and grep {$_ eq $ARGV[0]} qw(--help -h)) {
+    print <<EOF;
+usage: 1. fcm diff --branch [OPTIONS] [TARGET]
+       2. fcm diff [OPTIONS] [ARGS]
+
+  1. --branch or -b: Show differences relative to the base of the target branch,
+     i.e. the changes available for merging from the target branch into its
+     parent. If TARGET is specified, it must either be a URL or a working copy.
+     Otherwise, the target is the the current directory which must be a working
+     copy. The target URL must be a branch in a standard FCM project.
+
+  2. See description of "svn diff" below.
+
+Valid options:
+  -g [--graphical] : Use a graphical diff tool to display the differences. This
+                     option should not be used in combination with --diff-cmd.
+  <SVN options>    : Standard options to "svn diff" as described below.
+
+Valid options with --branch:
+  --diff-cmd arg        : As described below in the help for "svn diff".
+  -g [--graphical]      : As described above.
+  -t [--trac]           : If TARGET is a URL, use Trac to display the diff.
+  --wiki                : If TARGET is a URL, print Trac link for the diff.
+  -x [--extensions] arg : As described below in the help for "svn diff".
+
+EOF
+
+    &run_command ([qw/svn diff --help/], PRINT => 1, METHOD => 'exec');
+  }
+
+  # Set up environment for graphical diff
+  # Use environment variable if set, otherwise use default setting
+  my $env = 'FCM_GRAPHIC_DIFF';
+  $ENV{$env} = &main::cfg->setting (qw/TOOL GRAPHIC_DIFF/)
+    unless exists $ENV{$env} or not &main::cfg->setting (qw/TOOL GRAPHIC_DIFF/);
+
+  # Check for the --branch options
+  # ----------------------------------------------------------------------------
+  my $branch = grep {$_ eq '-b' or $_ eq '--branch'} @ARGV;
+
+  if (not $branch) {
+    # The --branch option not specified, just call "svn diff"
+    # Convert the --graphical to qw/--diff-cmd fcm_graphical_diff/
+    @ARGV = map {
+      ($_ eq '-g' or $_ eq '--graphical')
+      ? (qw/--diff-cmd fcm_graphic_diff/)
+      : $_
+    } @ARGV;
+
+    # Execute the command
+    cm_svn ('diff');
+  }
+
+  # The --branch option is specified
+  # ----------------------------------------------------------------------------
+
+  # Determine whether the --graphical option is specified,
+  # if so set the appropriate command
+  # ----------------------------------------------------------------------------
+  my ($diff_cmd, $extensions, $graphical, $trac, $wiki);
+  GetOptions (
+    'b|branch'       => \$branch,
+    'diff-cmd=s'     => \$diff_cmd,
+    'x|extensions=s' => \$extensions,
+    'g|graphical'    => \$graphical,
+    't|trac'         => \$trac,
+    'wiki'           => \$wiki,
+  );
+
+  my @diff_cmd = ();
+  
+  if ($graphical) {
+    @diff_cmd = (qw/--diff-cmd fcm_graphic_diff/);
+
+  } elsif ($diff_cmd) {
+    @diff_cmd = ('--diff-cmd', $diff_cmd);
+
+    push @diff_cmd, '--extensions', split (/\s+/, $extensions) if $extensions;
+  }
+
+  # The remaining argument should either be a URL or a PATH
+  my ($url_arg, $path_arg);
+
+  if (@ARGV) {
+    my $arg = Fcm::CmUrl->new (URL => $ARGV[0]);
+
+    if ($arg->is_url) {
+      $url_arg = $ARGV[0];
+
+    } else {
+      $path_arg = $ARGV[0];
+    }
+  }
+
+  # Get repository and branch information
+  # ----------------------------------------------------------------------------
+  my ($url, $path);
+  if (defined $url_arg) {
+    # If a URL is specified, get repository and branch information from it
+    $url = Fcm::CmBranch->new (URL => $url_arg);
+
+  } else {
+    # Get repository and branch information from the specified path or the
+    # current directory if it is a working copy
+    $path = $path_arg ? $path_arg : cwd ();
+    e_report $path, ': not a working copy, abort.' unless &is_wc ($path);
+
+    $url  = Fcm::CmBranch->new (URL => &get_url_of_wc ($path));
+  }
+
+  # Check that URL is a standard FCM branch
+  e_report $url->url_peg, ': not a standard FCM branch, abort.'
+    unless $url->is_branch;
+
+  # Save and remove sub-directory part of the URL
+  my $subdir = $url->subdir ();
+  $url->subdir ('');
+
+  # Check that $url exists
+  e_report $url->url_peg, ': not a valid URL, abort.' unless $url->url_exists;
+
+  # Compare current branch with its parent
+  # ----------------------------------------------------------------------------
+  my $parent = Fcm::CmBranch->new (URL => $url->parent->url);
+  $parent->pegrev ($url->pegrev) if $url->pegrev;
+
+  e_report $parent->url, ': branch parent no longer exists',
+           ($parent->pegrev ? ' at ' . $parent->pegrev : ''), ', abort.'
+    unless $parent->url_exists;
+
+  my $base = $parent->base_of_merge_from ($url);
+
+  # Ensure the correct diff (syntax) is displayed
+  # ----------------------------------------------------------------------------
+  # Reinstate the sub-tree part into the URL
+  $url->subdir ($subdir);
+  $base->subdir ($subdir);
+
+  # Ensure the branch URL has a peg revision
+  $url->pegrev ($url->svninfo (FLAG => 'Last Changed Rev')) if not $url->pegrev;
+
+  if ($trac or $wiki) {
+    # Trac/wiki
+    # --------------------------------------------------------------------------
+    if (not $url_arg) {
+      if (&run_command ([qw/svn status/], METHOD => 'qx')) {
+        w_report 'WARNING: the working copy at "', ($path_arg ? $path_arg : '.'),
+                 '" contains local changes, which cannot be displayed in Trac.';
+      }
+    }
+
+    # Trac wiki syntax
+    my $wiki_syntax = 'diff:' . $base->path_peg . '//' . $url->path_peg;
+
+    if ($wiki) {
+      # Print Trac wiki syntax only
+      print $wiki_syntax, "\n";
+
+    } else { # if $trac
+      # Use Trac to view "diff"
+      my $browser  = &main::cfg->setting (qw/MISC WEB_BROWSER/);
+      die 'ERROR: web browser not set, abort' if not $browser;
+
+      my $trac_url = &get_browser_url (URL => $url->project_url);
+      e_report 'ERROR: ', $url->project_url,
+               ': not associated with a Trac URL, abort.'
+        if not $trac_url;
+
+      $trac_url =~ s#/browser/.*$#/intertrac/$wiki_syntax#;
+
+      &run_command ([$browser, $trac_url], METHOD => 'exec', PRINT => 1);
+    }
+
+  } else {
+    # Execute the "diff" command
+    # --------------------------------------------------------------------------
+    my @command = (
+      qw/svn diff/, @diff_cmd,
+      '--old', $base->url_peg,
+      '--new', ($url_arg ? $url->url_peg : ($path_arg ? $path_arg : '.')),
+    );
+    &run_command (\@command, PRINT => 1);
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &Fcm::Cm::cm_merge ();
+#
+# DESCRIPTION
+#   This is a wrapper to "svn merge".
+# ------------------------------------------------------------------------------
+
+sub cm_merge {
+
+  # Print usage message if requested
+  if (defined ($ARGV[0]) and grep {$_ eq $ARGV[0]} qw(--help -h)) {
+    print <<EOF;
+merge: Merge changes from a source into your working copy.
+usage: 1. fcm merge SOURCE
+       2. fcm merge --custom  --revision N[:M] SOURCE
+          fcm merge --custom  URL[\@REV1] URL[\@REV2]
+       3. fcm merge --reverse --revision [M:]N
+
+  1. If neither --custom nor --reverse is specified, the command merges changes
+     automatically from SOURCE into your working copy. SOURCE must be a valid
+     URL[\@REV] of a branch in a standard FCM project. The base of the merge
+     will be calculated automatically based on the common ancestor and latest
+     merge information between the SOURCE and the branch of the working copy.
+
+  2. If --custom is specified, the command can be used in two forms.
+  
+     In the first form, it performs a custom merge from the specified
+     changeset(s) of SOURCE into your working copy. SOURCE must be a valid
+     URL[\@REV] of a branch in a standard FCM project. If a single revision is
+     specified, the merge delta is (N - 1):N of SOURCE. Otherwise, the merge
+     delta, is N:M of SOURCE, where N < M.
+     
+     In the second form, it performs a custom merge using the delta between the
+     two specified branch URLs. For each URL, if a peg revision is not
+     specified, the command will peg the URL with its last changed revision.
+
+  3. If --reverse is specified, the command performs a reverse merge of the
+     changeset(s) specified by the --revision option. If a single revision is
+     specified, the merge delta is N:(N - 1). Otherwise, the merge delta is
+     M:N, where M > N. Note that you do not have to specify a SOURCE for a
+     reverse merge, because the SOURCE should always be the branch your working
+     copy is pointing to.
+  
+  The command provide a commit log message template following the merge.
+
+Valid options:
+  --dry-run          : Try operation but make no changes.
+  --non-interactive  : Do no interactive prompting.
+  -r [--revision] arg: Specify a (range of) revision number(s).
+  --verbose          : Print extra information.
+EOF
+    return 1;
+  }
+
+  # Options
+  # ----------------------------------------------------------------------------
+  my ($custom, $dry_run, $non_interactive, $reverse, $rev, $verbose);
+  GetOptions (
+    'custom'          => \$custom,
+    'dry-run'         => \$dry_run,
+    'non-interactive' => \$non_interactive,
+    'reverse'         => \$reverse,
+    'revision|r=s'    => \$rev,
+    'verbose|v'       => \$verbose,
+  );
+
+  # Find out the URL of the working copy
+  # ----------------------------------------------------------------------------
+  my ($target, $wct);
+  if (&is_wc ()) {
+    $wct = &get_wct ();
+
+    if ($wct ne cwd ()) {
+      print 'Change directory to top of working copy: ', $wct, "\n";
+      chdir $wct or die 'Cannot change directory to: ', $wct;
+    }
+
+    $target = Fcm::CmBranch->new (URL => &get_url_of_wc ($wct));
+
+  } else {
+    e_report 'The current directory is not a working copy, abort.';
+  }
+
+  e_report 'Your working copy URL does not exist at the HEAD revision, abort.'
+    unless $target->url_exists;
+
+  # The target must be at the top of a branch
+  # $subdir will be used later to determine whether the merge is allowed or not
+  my $subdir = $target->subdir;
+  $target->subdir ('') if $subdir;
+
+  # Check for any local modifications
+  # ----------------------------------------------------------------------------
+  return
+    if ! ($dry_run or $non_interactive) and &_abort_modified_wc ('fcm merge');
+
+  # Determine the SOURCE URL
+  # ----------------------------------------------------------------------------
+  my $source;
+
+  if ($reverse) {
+    # Reverse merge, the SOURCE is the the working copy URL
+    $source = Fcm::CmBranch->new (URL => $target->url);
+
+  } else {
+    # Automatic/custom merge, argument 1 is the SOURCE of the merge
+    my $source_url = shift (@ARGV);
+    e_report 'Error: argument 1 must be the URL/name of a source branch in ',
+             'automatic/custom mode, abort.'
+      if not $source_url;
+
+    $source = &_construct_branch_url ($source_url, $target);
+  }
+
+  # Parse the revision option
+  # ----------------------------------------------------------------------------
+  my @revs;
+  if ($reverse or $custom) {
+    if ($reverse and not $rev) {
+      e_report 'Error: a revision (range) must be specified with ',
+               '--revision in reverse mode, abort.'
+    }
+
+    @revs = split (/:/, $rev) if $rev;
+  }
+
+  # Determine the merge delta and the commit log message
+  # ----------------------------------------------------------------------------
+  my (@delta, $mesg);
+  my $separator = '-' x 80 . "\n";
+
+  if ($reverse) {
+    # Reverse merge
+    # --------------------------------------------------------------------------
+    if (@revs == 1) {
+      $revs[1] = ($revs[0] - 1);
+
+    } else {
+      @revs = sort {$b <=> $a} @revs;
+    }
+
+    $source->pegrev ($source->svninfo (FLAG => 'Last Changed Rev'))
+      unless $source->pegrev;
+    $source->subdir ($subdir);
+
+    # "Delta" of the "svn merge" command
+    @delta = ('-r' . $revs[0] . ':' . $revs[1], $source->url_peg);
+
+    # Template message
+    $mesg = 'Reversed r' . $revs[0] .
+            (($revs[1] < $revs[0] - 1) ? ':' . $revs[1] : '') . ' of ' .
+            $source->path . "\n";
+
+  } elsif ($custom) {
+    # Custom merge
+    # --------------------------------------------------------------------------
+    if (@revs) {
+      # Revision specified
+      # ------------------------------------------------------------------------
+      # Only one revision N specified, use (N - 1):N as the delta
+      unshift @revs, ($revs[0] - 1) if @revs == 1;
+
+      $source->pegrev ($source->svninfo (FLAG => 'Last Changed Rev'))
+        unless $source->pegrev;
+      $source->subdir ($subdir);
+      $target->subdir ($subdir);
+
+      # "Delta" of the "svn merge" command
+      @delta = ('-r' . $revs[0] . ':' . $revs[1], $source->url_peg);
+
+      # Template message
+      $mesg = 'Custom merge into ' . $target->path . ': r' . $revs[1] .
+              ' cf. r' . $revs[0] . ' of ' . $source->path_peg . "\n";
+
+    } else {
+      # Revision not specified
+      # ------------------------------------------------------------------------
+      # Get second source URL
+      my $source2_url = shift (@ARGV);
+      e_report 'Error: argument 2 must be the URL/name of a source branch in ',
+               'custom mode when --revision is not specified, abort.'
+        if not $source2_url;
+
+      my $source2 = &_construct_branch_url ($source2_url, $target);
+
+      $source->pegrev  ($source->svninfo  (FLAG => 'Last Changed Rev'))
+        unless $source->pegrev;
+      $source2->pegrev ($source2->svninfo (FLAG => 'Last Changed Rev'))
+        unless $source2->pegrev;
+      $source->subdir  ($subdir);
+      $source2->subdir ($subdir);
+      $target->subdir  ($subdir);
+
+      # "Delta" of the "svn merge" command
+      @delta = ($source->url_peg, $source2->url_peg);
+
+      # Template message
+      $mesg = 'Custom merge into ' . $target->path . ': ' . $source->path_peg .
+              ' cf. ' . $source2->path_peg . "\n";
+    }
+
+  } else {
+    # Automatic merge
+    # --------------------------------------------------------------------------
+    # Check to ensure source branch is not the same as the target branch
+    e_report 'Error: cannot merge ', $source->branch,
+             ' to its own working copy, abort.'
+      if $source->branch eq $target->branch;
+
+    # Only allow the merge if the source and target are "directly related"
+    # --------------------------------------------------------------------------
+    my $anc = $target->ancestor ($source);
+    e_report 'Error: source and target are not directly related' unless
+      ($anc->url eq $target->url and $anc->url_peg eq $source->parent->url_peg)
+      or
+      ($anc->url eq $source->url and $anc->url_peg eq $target->parent->url_peg)
+      or
+      ($anc->url eq $source->parent->url and $anc->url eq $target->parent->url);
+
+    # Check for available merges from the source
+    # --------------------------------------------------------------------------
+    my @revs = $target->avail_merge_from ($source, 1);
+
+    if (@revs) {
+      print 'Available Merge', (@revs > 1 ? 's' : ''), ' From ',
+            $source->path_peg, ':';
+
+      if ($verbose) {
+        # Verbose mode, print log messages of available merges
+        print "\n";
+
+        for (@revs) {
+          print $separator, $source->display_svnlog ($_);
+        }
+
+        print $separator;
+
+      } else {
+        # Normal mode, list revisions of available merges
+        print ' ', join (' ', @revs), "\n";
+      }
+
+    } else {
+      w_report 'No merge available from ', $source->path_peg, ', abort.';
+      return;
+    }
+
+    # If more than one merge available, prompt user to enter a revision number
+    # to merge from, default to $revs [0]
+    # --------------------------------------------------------------------------
+    my $reply = ($non_interactive or @revs == 1) ? $revs[0] : &main::get_input (
+      TITLE   => 'fcm merge',
+      MESSAGE => 'Please enter the revision you wish to merge from',
+      DEFAULT => $revs [0],
+    );
+
+    if (not defined ($reply)) {
+      w_report 'Merge aborted by user.';
+      return;
+    }
+
+    # Expand revision keyword if necessary
+    if ($reply) {
+      $reply = expand_rev_keyword (REV => $reply, URL => $target->project_url);
+    }
+
+    # Check that the reply is a number in the available merges list
+    e_report $reply, ': not a revision in the list of available merges.'
+      unless (grep {$_ == $reply} @revs);
+
+    $source->pegrev ($1) if ($reply =~ /^(\d+)/);
+
+    # If the working copy top is pointing to a sub-directory of a branch,
+    # we need to check whether the merge will result in losing changes made in
+    # other sub-directories of the source.
+    if ($subdir and not $target->allow_subdir_merge_from ($source, $subdir)) {
+      e_report 'SOURCE contains changes outside the current sub-directory.', "\n",
+               'Please use a full tree for the merge, abort.';
+    }
+
+    # Calculate the base of the merge
+    my $base = $target->base_of_merge_from ($source);
+
+    # $source and $base must take into account the sub-directory
+    my $s = Fcm::CmBranch->new (URL => $source->url_peg);
+    my $b = Fcm::CmBranch->new (URL => $base->url_peg);
+
+    $s->subdir ($subdir) if $subdir;
+    $b->subdir ($subdir) if $subdir;
+
+    # Diagnostic
+    print 'About to merge in changes from ', $s->path_peg, ' compared with ',
+          $b->path_peg, "\n";
+
+    # Delta of the "svn merge" command
+    @delta = ($b->url_peg, $s->url_peg);
+
+    # Template message
+    $mesg = 'Merged into ' . $target->path . ': ' . $source->path_peg .
+            ' cf. ' . $base->path_peg . "\n";
+  }
+
+  # Run "svn merge" in "--dry-run" mode to see the result
+  # ----------------------------------------------------------------------------
+  my @out   = &run_command (
+    [qw/svn merge --dry-run/, @delta],
+    METHOD => 'qx', PRINT => ($dry_run and $verbose),
+  );
+
+  # Abort merge if it will result in no change
+  if (not @out) {
+    print 'This merge will not result in any change, abort.', "\n";
+    return;
+  }
+
+  # Report result of "svn merge --dry-run"
+  if (not $non_interactive) {
+    print 'This merge will result in the following change',
+          (@out > 1 ? 's' : ''), ':', "\n";
+    print $separator, @out, $separator;
+  }
+
+  return if $dry_run;
+
+  # Prompt the user to see if (s)he would like to go ahead
+  # ----------------------------------------------------------------------------
+  my $reply = $non_interactive ? 'y' : &main::get_input (
+    TITLE   => 'fcm merge',
+    MESSAGE => 'Would you like to go ahead with the merge?',
+    TYPE    => 'yn',
+    DEFAULT => 'n',
+  );
+
+  # Go ahead with merge only if user replies "y"
+  if ($reply eq "y") {
+    print "Performing merge ...\n";
+    &run_command ([qw/svn merge/, @delta], PRINT => $verbose);
+
+  } else {
+    w_report 'Merge aborted by user.';
+    return;
+  }
+
+  # Prepare the commit log
+  # ----------------------------------------------------------------------------
+  # Read in any existing message
+  my $ci_mesg = Fcm::CmCommitMessage->new;
+  $ci_mesg->read_file;
+  $ci_mesg->auto_mesg ($mesg, ($ci_mesg->auto_mesg));
+  $ci_mesg->write_file;
+
+  if ($verbose) {
+    print <<EOF;
+${separator}The following line has been added to your commit message file:
+$mesg
+EOF
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &Fcm::Cm::cm_mkpatch ();
+#
+# DESCRIPTION
+#   This is a FCM command to create a patching script from particular revisions
+#   of a URL.
+# ------------------------------------------------------------------------------
+
+sub cm_mkpatch {
+  my $usage = <<EOF;
+mkpatch: Create patches from specified revisions of a URL
+usage: fcm mkpatch [OPTIONS] URL [OUTDIR]
+
+  URL must be the URL of a branch in a FCM project. If the URL is a
+  sub-directory of a branch, it will use the root of the branch.
+
+  Create patches from specified revisions of the specified URL. If OUTDIR is
+  specified, the output is sent to OUTDIR. Otherwise, the output will be sent
+  to a default location in the current directory (\$PWD/fcm-mkpatch-out). The
+  output directory will contain the patch for each revision as well as a script
+  for importing the patch.
+
+  If a revision is specified with the --revision option, it will attempt to
+  create a patch based on the changes at that revision. If a revision is not
+  specified, it will attempt to create a patch based on the changes at the HEAD
+  revision. If a revision range is specified, it will attempt to create a patch
+  for each revision in that range (including the change in the lower range)
+  where changes have taken place in the URL. No output will be written if there
+  is no change in the given revision (range).
+
+  The --exclude option can be used to exclude a path in the URL. The specified
+  path must be a relative path of the URL. Glob patterns such as * and ? are
+  acceptable. Changes in an excluded path will not be considered in the patch.
+  A changeset containing changes only in the excluded path will not be
+  considered at all.
+
+  The --organisation option can be used to specify the name of your
+  organisation. The command will attempt to parse the commit log message for
+  each revision in the patch. It will remove all merge templates, replace links
+  to Trac tickets with a simple string, and add information about the original
+  changeset. If you specify the name of your organisation, it will replace Trac
+  ticket links such as "ticket:123" to "Original \$organisation ticket 123",
+  and report the orginal changeset with a message such as "Original
+  \$organisation changeset 1000". Otherwise, it will report without the
+  organisation name, e.g. "Original ticket 123" and "Original  changeset 1000".
+
+Valid options:
+  --exclude       arg : Exclude a path in the URL. Multiple paths can be
+                        specified by using a colon-separated list of paths, or
+                        by specifying this option multiple times.
+  --organisation  arg : Specify the name of your organisation.
+  -r [--revision] arg : Specify a revision number or a revision number range.
+EOF
+
+  # Print usage message if requested
+  if (defined ($ARGV[0]) and grep {$_ eq $ARGV[0]} qw(--help -h)) {
+    print $usage;
+    return 1;
+  }
+
+  # Process command line options and arguments
+  # ----------------------------------------------------------------------------
+  my (@exclude, $organisation, $revision);
+  GetOptions (
+    'exclude=s'      => \@exclude,
+    'organisation=s' => \$organisation,
+    'r|revision=s'   => \$revision,
+  );
+
+  # Excluded paths, convert glob into regular patterns
+  @exclude = split (/:/, join (':', @exclude));
+  for (@exclude) {
+    s#\*#[^/]*#; # match any number of non-slash character
+    s#\?#[^/]#;  # match a non-slash character
+    s#/*$##;     # remove trailing slash
+  }
+
+  # Organisation prefix
+  $organisation = $organisation ? $organisation : 'original';
+
+  # Make sure revision option is set correctly
+  my @revs = $revision ? split (/:/, $revision) : ();
+  @revs    = @revs [0, 1] if @revs > 2;
+
+  # Arguments
+  my ($u, $outdir) = @ARGV;
+
+  if (not $u) {
+    print $usage;
+    return 1;
+  }
+
+  my $url = Fcm::CmUrl->new (URL => $u);
+  e_report $u, ': URL is not a URL, abort.' if not $url->is_url;
+  e_report $u, ': URL does not exist, abort.' if not $url->url_exists;
+  e_report $u, ': URL is not a valid branch in a FCM project, abort.'
+    if not $url->branch;
+
+  $url->subdir ('');
+
+  if (@revs) {
+    # If HEAD revision is given, convert it into a number
+    # --------------------------------------------------------------------------
+    for my $rev (@revs) {
+      $rev = $url->svninfo (FLAG => 'Revision') if uc ($rev) eq 'HEAD';
+    }
+
+  } else {
+    # If no revision is given, use the HEAD
+    # --------------------------------------------------------------------------
+    $revs[0] = $url->svninfo (FLAG => 'Revision');
+  }
+
+  $revs[1] = $revs[0] if @revs == 1;
+
+  # Check that output directory is set
+  # ----------------------------------------------------------------------------
+  $outdir = File::Spec->catfile (cwd (), 'fcm-mkpatch-out') if not $outdir;
+
+  if (-e $outdir) {
+    # Ask user to confirm removal of old output directory if it exists
+    my $reply = &main::get_input (
+      TITLE   => 'fcm mkpatch',
+      MESSAGE => 'Output location ' . $outdir . ' exists. OK to overwrite?',
+      TYPE    => 'yn',
+      DEFAULT => 'n',
+    );
+
+    if ($reply ne 'y') {
+      w_report 'fcm mkpatch: command aborted by user.';
+      return 1;
+    }
+
+    rmtree $outdir or die $outdir, ': cannot remove';
+  }
+
+  # (Re-)create output directory
+  mkpath $outdir or die $outdir, ': cannot create';
+  print 'Output directory: ', $outdir, "\n";
+
+  # Get and process log of URL
+  # ----------------------------------------------------------------------------
+  my @script     = (); # output script, from the log
+  my %log        = $url->svnlog (REV => \@revs);
+  my $url_path   = $url->path;
+  my $file_count = 0;
+
+  for my $rev (sort {$a <=> $b} keys %log) {
+    # Look at the changed paths for each revision
+    my @paths;
+
+    # Skip excluded paths if necessary
+    PATH: for my $path (sort keys %{ $log{$rev}{paths} }) {
+      for my $exclude (@exclude) {
+        (my $file = $path) =~ s#^$url_path/*##;
+
+        next PATH if $file =~ m#^$exclude(?:/*|$)#;
+      }
+
+      push @paths, $path;
+    }
+
+    next unless @paths;
+
+    # Parse commit log message
+    my @msg = split /\n/, $log{$rev}{msg};
+    for (@msg) {
+      # Re-instate line break
+      $_ .= "\n";
+
+      # Remove line if it matches a merge template
+      $_ = '' if /^Reversed r\d+(?::\d+)? of \S+$/;
+      $_ = '' if /^Custom merge into \S+:.+$/;
+      $_ = '' if /^Merged into \S+: \S+ cf\. \S+$/;
+
+      # Modify Trac ticket link
+      s/(?:#|ticket:)(\d+)/[$organisation ticket $1]/g;
+
+      # Modify Trac changeset link
+      s/(?:r|changeset:)(\d+)/[$organisation changeset $1]/g;
+      s/\[(\d+)\]/[$organisation changeset $1]/g;
+    }
+
+    push @msg, '[' . $organisation . ' changeset ' . $rev . ']' . "\n";
+
+    # Write commit log message in a file
+    my $f_revlog = File::Spec->catfile ($outdir, $rev . '-log');
+    open FILE, '>', $f_revlog or die $f_revlog, ': cannot open (', $!, ')';
+    print FILE @msg;
+    close FILE or die $f_revlog, ': cannot close (', $!, ')';
+
+    # Create a directory for this revision in the output directory
+    my $outdir_rev = File::Spec->catfile ($outdir, $rev);
+    mkpath $outdir_rev or die $outdir_rev, ': cannot create';
+
+    # Handle modified/copy/new path, export the path, + script to copy/add it
+    for my $path (@paths) {
+      next unless $log{$rev}{paths}{$path}{action} =~ /^[AMR]$/;
+
+      (my $file = $path) =~ s#^$url_path/*##;
+
+      # Download the file using "svn export"
+      my $patch    = File::Spec->catfile ($outdir_rev, $file_count++);
+      my $url_file = $url->url . '/' . $file . '@' . $rev;
+      &run_command ([qw/svn export -q -r/, $rev, $url_file, $patch]);
+
+      (my $patch_path = $patch) =~ s#^$outdir/*##;
+
+      # Script to copy the file, if required
+      my $is_newfile = 0;
+      if ($log{$rev}{paths}{$path}{action} eq 'A') {
+        if (exists $log{$rev}{paths}{$path}{'copyfrom-path'}) {
+          # History exists for this file
+          my $copyfrom_path = $log{$rev}{paths}{$path}{'copyfrom-path'};
+          my $copyfrom_rev  = $log{$rev}{paths}{$path}{'copyfrom-rev'};
+
+          # Check whether file is copied from a file under the specified URL
+          # It is likely to be a new file if it is copied from outside of the
+          # specified URL.
+          $is_newfile = not ($copyfrom_path =~ s#^$url_path/*##);
+
+          if ($is_newfile) {
+            # File copied from outside of the specified URL
+            # If it is copied from a branch, follow its history, stop on copy
+            my $cp_url = Fcm::CmUrl->new (
+              URL => $url->root . $copyfrom_path . '@' . $copyfrom_rev,
+            );
+
+            # Log of the copied file
+            my %cp_log = $cp_url->svnlog (STOP_ON_COPY => 1);
+
+            # "First" revision of the copied file
+            my $cp_rev = (sort {$a <=> $b} keys %cp_log) [0];
+            my %attrib = exists $cp_log{$cp_rev}{paths}{$cp_url->path}
+                         ? %{ $cp_log{$cp_rev}{paths}{$cp_url->path} } : ();
+
+            # Check whether the "first" revision is copied from elsewhere.
+            if (exists $attrib{'copyfrom-path'}) {
+              # Check whether source exists in the current branch
+              my $cp_cp_url = Fcm::CmUrl->new (
+                URL => $url->root . $attrib{'copyfrom-path'} . '@' .
+                       $attrib{'copyfrom-rev'},
+              );
+
+              $cp_cp_url->branch ($url->branch);
+
+              # If source exists in current branch, set up copy from the source
+              if ($cp_cp_url->url_exists ($rev - 1)) {
+                $is_newfile     = 0;
+                (my $cp_cp_path = $cp_cp_url->path) =~ s#^$url_path/*##;
+
+                push @script, 'svn copy ' . $cp_cp_path .  ' ' . $file;
+              }
+            }
+
+          } else {
+            # File copied from a location under the specified URL
+            # Script to copy file
+            push @script, 'svn copy ' . $copyfrom_path .  ' ' . $file;
+          }
+
+        } else {
+          # History does not exist, must be a new file
+          $is_newfile = 1;
+        }
+      }
+
+      # Copy the "patch" into the file
+      push @script, 'cp -r ${fcm_patch_dir}/' . $patch_path . ' ' . $file;
+
+      # Script to add the file, if required
+      push @script, 'svn add ' . $file
+        if $log{$rev}{paths}{$path}{action} eq 'A' and $is_newfile;
+    }
+
+    # Handle deleted path, script to delete it
+    for my $path (@paths) {
+      next unless $log{$rev}{paths}{$path}{action} eq 'D';
+
+      (my $file = $path) =~ s#^$url_path/*##;
+
+      push @script, 'svn delete ' . $file;
+    }
+
+    # Script to commit the change
+    push @script, 'svn commit -F ${fcm_patch_dir}/' . $rev . '-log';
+    push @script, '';
+  }
+
+  # Write the script if necessary. Otherwise remove output directory
+  # ----------------------------------------------------------------------------
+  if (@script) {
+    # Add line break to each line in @script
+    @script = map {($_ ? $_ . ' || exit 1' . "\n" : "\n")} @script;
+
+    # Write script to output
+    my $out = File::Spec->catfile ($outdir, 'fcm-import-patch');
+    open FILE, '>', $out or die $out, ': cannot open (', $!, ')';
+
+    # Script header
+    print FILE <<EOF;
+#!/bin/sh
+# ------------------------------------------------------------------------------
+# NAME
+#   fcm-import-patch
+#
+# SYNOPSIS
+#   fcm-import-patch TARGET
+#
+# DESCRIPTION
+#   This script is generated automatically by the "fcm mkpatch" command,
+#   together with the revision "patches" it creates. The script imports the
+#   patches into TARGET, which must either be a URL or a working copy of a
+#   valid project tree that can accept the import of the patches.
+#
+#   Patch created from $organisation URL: $u
+# ------------------------------------------------------------------------------
+
+this=`basename \$0`
+
+# Check argument
+target=\$1
+
+# First argument must be a URL or working copy
+if [[ -z \$target ]]; then
+  echo "\$this: the first argument must be a URL or a working copy, abort." >&2
+  exit 1
+fi
+
+if [[ \$target == svn://*  || \$target == svn+ssh://* || \\
+      \$target == http://* || \$target == https://*   || \\
+      \$target == file://* ]]; then
+  # A URL, checkout a working copy in a temporary location
+  fcm_tmp_dir=`mktemp -d \$TMPDIR/\$0.XXXXXX`
+  fcm_working_copy=\$fcm_tmp_dir
+  svn checkout -q \$target \$fcm_working_copy || exit 1
+
+else
+  # A working copy, check that it does not have local changes
+  status=`svn status \$target`
+
+  if [[ -n \$status ]]; then
+    echo "\$target: working copy contains changes, abort." >&2
+    exit 1
+  fi
+
+  fcm_working_copy=\$target
+fi
+
+# Location of the patches, base on the location of this script
+cd `dirname \$0` || exit 1
+fcm_patch_dir=\$PWD
+
+# Change directory to the working copy
+cd \$fcm_working_copy || exit 1
+
+# Commands to apply patches
+EOF
+
+    # Script content
+    print FILE @script;
+
+    # Script footer
+    print FILE <<EOF;
+# Remove temporary working copy, if necessary
+if [[ -d \$fcm_tmp_dir && -w \$fcm_tmp_dir ]]; then
+  rm -rf \$fcm_tmp_dir
+fi
+
+echo "\$this: finished normally."
+#EOF
+EOF
+
+    close FILE or die $out, ': cannot close (', $!, ')';
+
+    # Add executable permission
+    chmod 0755, $out;
+
+    # Diagnostic
+    print $outdir, ': patch generated.', "\n";
+
+  } else {
+    # Remove output directory
+    rmtree $outdir or die $outdir, ': cannot remove';
+
+    # Diagnostic
+    w_report 'No patch is required, abort.';
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &Fcm::Cm::cm_svn ();
+#
+# DESCRIPTION
+#   This is a generic wrapper for all "other" Subversion commands.
+# ------------------------------------------------------------------------------
+
+sub cm_svn {
+  &run_command (
+    ['svn', @_, @ARGV],
+    PRINT => ($_[0] ne 'cat' and not grep {$_ eq '--xml'} @ARGV),
+    METHOD => 'exec',
+  );
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &Fcm::Cm::cm_switch ();
+#
+# DESCRIPTION
+#   This is a wrapper for the Subversion "switch" command.
+# ------------------------------------------------------------------------------
+
+sub cm_switch {
+  if (grep {$_ eq '-h' or $_ eq '--help'} @ARGV or not @ARGV) {
+    # Print usage message if requested
+    print <<EOF;
+usage: 1. switch URL [PATH]
+       2. switch --relocate FROM TO [PATH...]
+
+Note: if --relocate is not specified, "fcm switch" will only support the
+      options --non-interactive, -r [--revision] and -q [--quiet].
+
+EOF
+
+    &run_command ([qw/svn switch --help/], PRINT => 1, METHOD => 'exec');
+
+  } elsif (grep {$_ eq '--relocate'} @ARGV) {
+    # If "--relocate" is specified, call the command "as is"
+    cm_svn ('switch');
+  }
+
+  # "--help" and "--relocate" not specified, implement custom switch command
+
+  # Get command line options
+  my ($non_interactive, $rev, $quiet);
+  GetOptions (
+    'non-interactive' => \$non_interactive,
+    'revision|r=s'    => \$rev,
+    'quiet|q'         => \$quiet,
+  );
+
+  # The remaining arguments
+  $rev = 'HEAD' if not $rev;
+
+  # The remaining arguments
+  my ($newurl_arg, $path) = @ARGV;
+
+  # Make sure we are in a working copy
+  if ($path) {
+    e_report $path, ': does not exist, abort.' if not -e $path;
+
+  } else {
+    $path = cwd ();
+  }
+
+  e_report $path, ': not a working copy, abort.' if not &is_wc ($path);
+
+  # Make sure we are at the top level of the working copy
+  my $dir = &get_wct ($path);
+
+  # Check for merge template in the commit log file in the working copy
+  my $ci_mesg = Fcm::CmCommitMessage->new (DIR => $dir);
+  $ci_mesg->read_file;
+  e_report (
+    (($path eq $dir) ? $ci_mesg->base : $ci_mesg->file),
+    ': merge template exists, please remove it before running switch, abort.',
+  ) if $ci_mesg->auto_mesg;
+
+  # Check for any local modifications
+  return if ! $non_interactive and &_abort_modified_wc ('fcm switch', $dir);
+
+  # Get current URL information associated with the working copy
+  my $oldurl = Fcm::CmBranch->new (URL => &get_url_of_wc ($dir));
+
+  # Analyse new URL
+  my $newurl = &_construct_branch_url ($newurl_arg, $oldurl);
+
+  # Construct the switch command
+  my @command = (
+    qw/svn switch/,
+    ($non_interactive ? '--non-interactive' : ()),
+    ($rev             ? ('-r', $rev)        : ()),
+    ($quiet           ? '--quiet'           : ()),
+    $newurl->url,
+    ($dir eq cwd () ? () : $dir),
+  );
+
+  # Execute the command
+  &run_command (\@command, METHOD => 'exec', PRINT => 1);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $source = &_construct_branch_url ($src_url, $target);
+#
+# DESCRIPTION
+#   The function takes a string $src_url, which is normally the SOURCE URL
+#   argument for "merge" and "switch", and a target, which is an instance of a
+#   Fcm::CmBranch object with a valid URL of a standard FCM branch. It returns
+#   an instance of a Fcm::CmBranch object that represents a valid URL for
+#   $src_url.
+# ------------------------------------------------------------------------------
+
+sub _construct_branch_url {
+  my ($src_url, $target) = @_;
+
+  my $source = Fcm::CmBranch->new (URL => $src_url);
+
+  if (not $source->is_url) {
+    # Not a full URL, construct full URL based on current URL
+    $source->url_peg ($target->url_peg);
+
+    my $path    = '';
+    my $project = $target->project;
+
+    # Construct the branch URL
+    if ($src_url =~ m#^/*$project/(?:trunk|branches|tags)$#) {
+      # Argument contains the full path under the repository root
+      $path = $src_url;
+
+    } elsif ($src_url =~ m#^/*trunk/*(?:@\d+)?$# or
+             $src_url =~ m#^/*(?:trunk|branches|tags)/+#) {
+      # Argument contains the full branch name
+      $src_url =~ s#^/*##;
+      $path    = $target->project_path . '/' . $src_url;
+
+    } else {
+      # Argument contains the shorter branch name
+      $src_url =~ s#^/*##;
+      $path    = $target->project_path . '/branches/' . $src_url;
+    }
+
+    $source->path_peg ($path);
+  }
+
+  # Replace source sub-directory with the target sub-directory
+  $source->subdir ($target->subdir);
+
+  # Ensure that the branch name exists
+  e_report $src_url, ': not a valid URL, abort.'
+    if not $source->url_exists;
+
+  # Ensure that the branch name is valid
+  e_report $src_url, ': not a standard branch in a FCM project, abort.'
+    if not $source->branch;
+
+  # Ensure that the source and target URLs are in the same project
+  e_report 'Source and target URLs are in different projects, abort.'
+    if $source->project_url ne $target->project_url;
+
+  return $source;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &_abort_modified_wc ($title, [$wc]);
+#
+# DESCRIPTION
+#   The function checks for any local modifications in a working copy and
+#   prompts the user whether he/she wants to continue with the command. $title
+#   is the title of the current command. If $wc is specified, it must be the
+#   path to a working copy. Otherwise, the current working directory is used.
+# ------------------------------------------------------------------------------
+
+sub _abort_modified_wc {
+  my ($title, $wc) = @_;
+
+  my @status = &run_command ([qw/svn status/, ($wc ? $wc : ())], METHOD => 'qx');
+
+  if (@status) {
+    print 'You have local modifications:', "\n", @status;
+    my $reply = &main::get_input (
+      TITLE   => $title,
+      MESSAGE => 'Are you sure you want to continue?',
+      TYPE    => 'yn',
+      DEFAULT => 'n',
+    );
+
+    # Abort if user gives any reply other than "y"
+    if ($reply ne 'y') {
+      w_report $title, ': command aborted by user.';
+      return 1;
+    }
+  }
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/lib/Fcm/CmBranch.pm
===================================================================
--- LMDZ5/branches/testing/tools/fcm/lib/Fcm/CmBranch.pm	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/lib/Fcm/CmBranch.pm	(revision 1665)
@@ -0,0 +1,1199 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::CmBranch
+#
+# DESCRIPTION
+#   This class contains methods for manipulating a branch. It is a sub-class of
+#   Fcm::CmUrl, and inherits all methods from that class.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::CmBranch;
+@ISA = qw(Fcm::CmUrl);
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Standard modules
+use Carp;
+use File::Spec;
+
+# FCM component modules
+use Fcm::CmCommitMessage;
+use Fcm::CmUrl;
+use Fcm::Util qw/run_command e_report w_report get_rev_keyword svn_date/;
+
+my @properties = (
+  'CREATE_REV',  # revision at which the branch is created
+  'DELETE_REV',  # revision at which the branch is deleted
+  'PARENT',      # reference to parent branch Fcm::CmBranch
+  'ANCESTOR',    # list of common ancestors with other branches
+                 # key = URL, value = ancestor Fcm::CmBranch
+  'LAST_MERGE',  # list of last merges from branches
+                 # key = URL@REV, value = [TARGET, UPPER, LOWER]
+  'AVAIL_MERGE', # list of available revisions for merging
+                 # key = URL@REV, value = [REV ...]
+  'CHILDREN',    # list of children of this branch
+  'SIBLINGS',    # list of siblings of this branch
+);
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cm_branch = Fcm::CmBranch->new (
+#     CONFIG  => $config,
+#     URL     => $url,
+#   );
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::CmBranch class.
+#
+# ARGUMENTS
+#   CONFIG - reference to a Fcm::Config instance
+#   URL    - URL of a branch
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $self = Fcm::CmUrl->new (%args);
+
+  $self->{$_} = undef for (@properties);
+
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $url = $cm_branch->url_peg;
+#   $cm_branch->url_peg ($url);
+#
+# DESCRIPTION
+#   This method returns/sets the current URL.
+# ------------------------------------------------------------------------------
+
+sub url_peg {
+  my $self = shift;
+
+  if (@_) {
+    if (! $self->{URL} or $_[0] ne $self->{URL}) {
+      # Re-set URL and other essential variables in the SUPER-class
+      $self->SUPER::url_peg (@_);
+
+      # Re-set essential variables
+      $self->{$_} = undef for (@properties);
+    }
+  }
+
+  return $self->{URL};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rev = $cm_branch->create_rev;
+#
+# DESCRIPTION
+#   This method returns the revision at which the branch was created.
+# ------------------------------------------------------------------------------
+
+sub create_rev {
+  my $self = shift;
+
+  if (not $self->{CREATE_REV}) {
+    return unless $self->url_exists ($self->pegrev);
+
+    # Use "svn log" to find out the first revision of the branch
+    my %log = $self->svnlog (STOP_ON_COPY => 1);
+
+    # Look at log in ascending order
+    my $rev   = (sort {$a <=> $b} keys %log) [0];
+    my $paths = $log{$rev}{paths};
+
+    # Get revision when URL is first added to the repository
+    if (exists $paths->{$self->branch_path}) {
+      $self->{CREATE_REV} = $rev if $paths->{$self->branch_path}{action} eq 'A';
+    }
+  }
+
+  return $self->{CREATE_REV};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $parent = $cm_branch->parent;
+#
+# DESCRIPTION
+#   This method returns the parent (a Fcm::CmBranch object) of the current
+#   branch.
+# ------------------------------------------------------------------------------
+
+sub parent {
+  my $self = shift;
+
+  if (not $self->{PARENT}) {
+    # Use the log to find out the parent revision
+    my %log = $self->svnlog (REV => $self->create_rev);
+
+    if (exists $log{paths}{$self->branch_path}) {
+      my $path = $log{paths}{$self->branch_path};
+
+      if ($path->{action} eq 'A') {
+        if (exists $path->{'copyfrom-path'}) {
+          # Current branch is copied from somewhere, set the source as the parent
+          my $url = $self->root .  $path->{'copyfrom-path'};
+          my $rev = $path->{'copyfrom-rev'};
+          $self->{PARENT} = Fcm::CmBranch->new (URL => $url . '@' . $rev);
+
+        } else {
+          # Current branch is not copied from somewhere
+          $self->{PARENT} = $self;
+        }
+      }
+    }
+  }
+
+  return $self->{PARENT};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rev = $cm_branch->delete_rev;
+#
+# DESCRIPTION
+#   This method returns the revision at which the branch was deleted.
+# ------------------------------------------------------------------------------
+
+sub delete_rev {
+  my $self = shift;
+
+  if (not $self->{DELETE_REV}) {
+    return if $self->url_exists ('HEAD');
+
+    # Container of the current URL
+    (my $dir_url = $self->branch_url) =~ s#/+[^/]+/*$##;
+
+    # Use "svn log" on the container between a revision where the branch exists
+    # and the HEAD
+    my $dir = Fcm::CmUrl->new (URL => $dir_url);
+    my %log = $dir->svnlog (
+      REV => ['HEAD', ($self->pegrev ? $self->pegrev : $self->create_rev)],
+    );
+
+    # Go through the log to see when branch no longer exists
+    for my $rev (sort {$a <=> $b} keys %log) {
+      next unless exists $log{$rev}{paths}{$self->branch_path} and
+                  $log{$rev}{paths}{$self->branch_path}{action} eq 'D';
+
+      $self->{DELETE_REV} = $rev;
+      last;
+    }
+  }
+
+  return $self->{DELETE_REV};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $cm_branch->is_child_of ($branch);
+#
+# DESCRIPTION
+#   This method returns true if the current branch is a child of $branch.
+# ------------------------------------------------------------------------------
+
+sub is_child_of {
+  my ($self, $branch) = @_;
+
+  # The trunk cannot be a child branch
+  return if $self->is_trunk;
+
+  # If $branch is a branch, use name of $self to see when it is created
+  if ($branch->is_branch and $self->url =~ m#/r(\d+)_[^/]+/*$#) {
+    my $rev = $1;
+
+    # $self can only be a child if it is copied from a revision > the create
+    # revision of $branch
+    return if $rev < $branch->create_rev;
+  }
+
+  return if $self->parent->url ne $branch->url;
+
+  # If $branch is a branch, ensure that it is created before $self
+  return if $branch->is_branch and $self->create_rev <= $branch->create_rev;
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $cm_branch->is_sibling_of ($branch);
+#
+# DESCRIPTION
+#   This method returns true if the current branch is a sibling of $branch.
+# ------------------------------------------------------------------------------
+
+sub is_sibling_of {
+  my ($self, $branch) = @_;
+
+  # The trunk cannot be a sibling branch
+  return if $branch->is_trunk;
+
+  return if $self->parent->url ne $branch->parent->url;
+
+  # If the parent is a branch, ensure they are actually the same branch
+  return if $branch->parent->is_branch and
+            $self->parent->create_rev != $branch->parent->create_rev;
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_get_relatives ($relation);
+#
+# DESCRIPTION
+#   This method sets the $self->{$relation} variable by inspecting the list of
+#   branches at the current revision of the current branch. $relation can be
+#   either "CHILDREN" or "SIBLINGS".
+# ------------------------------------------------------------------------------
+
+sub _get_relatives {
+  my ($self, $relation) = @_;
+
+  my @branch_list = $self->branch_list;
+
+  $self->{$relation} = [];
+
+  # If we are searching for CHILDREN, get list of SIBLINGS, and vice versa
+  my $other = ($relation eq 'CHILDREN' ? 'SIBLINGS' : 'CHILDREN');
+  my %other_list;
+  if ($self->{$other}) {
+    %other_list = map {$_->url, 1} @{ $self->{$other} };
+  }
+
+  for my $u (@branch_list) {
+    # Ignore URL of current branch and its parent
+    next if $u eq $self->url;
+    next if $self->is_branch and $u eq $self->parent->url;
+
+    # Ignore if URL is a branch detected to be another type of relative
+    next if exists $other_list{$u};
+
+    # Construct new Fcm::CmBranch object from branch URL
+    my $url = $u . ($self->pegrev ? '@' . $self->pegrev : '');
+    my $branch = Fcm::CmBranch->new (URL => $url);
+
+    # Test whether $branch is a relative we are looking for
+    if ($relation eq 'CHILDREN') {
+      push @{ $self->{$relation} }, $branch if $branch->is_child_of ($self);
+
+    } else {
+      push @{ $self->{$relation} }, $branch if $branch->is_sibling_of ($self);
+    }
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @children = $cm_branch->children;
+#
+# DESCRIPTION
+#   This method returns a list of children (Fcm::CmBranch objects) of the
+#   current branch that exists in the current revision.
+# ------------------------------------------------------------------------------
+
+sub children {
+  my $self = shift;
+
+  $self->_get_relatives ('CHILDREN') if not $self->{CHILDREN};
+
+  return @{ $self->{CHILDREN} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @siblings = $cm_branch->siblings;
+#
+# DESCRIPTION
+#   This method returns a list of siblings (Fcm::CmBranch objects) of the
+#   current branch that exists in the current revision.
+# ------------------------------------------------------------------------------
+
+sub siblings {
+  my $self = shift;
+
+  $self->_get_relatives ('SIBLINGS') if not $self->{SIBLINGS};
+
+  return @{ $self->{SIBLINGS} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ancestor = $cm_branch->ancestor ($branch);
+#
+# DESCRIPTION
+#   This method returns the common ancestor (a Fcm::CmBranch object) of a
+#   specified $branch and the current branch. The argument $branch must be a
+#   Fcm::CmBranch object. Both the current branch and $branch are assumed to be
+#   in the same project.
+# ------------------------------------------------------------------------------
+
+sub ancestor {
+  my ($self, $branch) = @_;
+
+  if (not exists $self->{ANCESTOR}{$branch->url_peg}) {
+    if ($self->url_peg eq $branch->url_peg) {
+      $self->{ANCESTOR}{$branch->url_peg} = $self;
+
+    } else {
+      # Get family tree of current branch, from trunk to current branch
+      my @this_family = ($self);
+      while (not $this_family [0]->is_trunk) {
+        unshift @this_family, $this_family [0]->parent;
+      }
+
+      # Get family tree of $branch, from trunk to $branch
+      my @that_family = ($branch);
+      while (not $that_family [0]->is_trunk) {
+        unshift @that_family, $that_family [0]->parent;
+      }
+
+      # Find common ancestor from list of parents
+      my $ancestor = undef;
+
+      while (not $ancestor) {
+        # $this and $that should both start as some revisions on the trunk.
+        # Walk down a generation each time it loops around.
+        my $this = shift @this_family;
+        my $that = shift @that_family;
+
+        if ($this->url eq $that->url) {
+          if ($this->is_trunk or $this->create_rev eq $that->create_rev) {
+            # $this and $that are the same branch
+            if (@this_family and @that_family) {
+              # More generations in both branches, try comparing the next
+              # generations.
+              next;
+
+            } else {
+              # End of lineage in one of the branches, ancestor is at the lower
+              # revision of the current URL.
+              if ($this->pegrev and $that->pegrev) {
+                $ancestor = $this->pegrev < $that->pegrev ? $this : $that;
+
+              } else {
+                $ancestor = $this->pegrev ? $this : $that;
+              }
+            }
+
+          } else {
+            # Despite the same URL, $this and $that are different branches as
+            # they are created at different revisions. The ancestor must be the
+            # parent with the lower revision. (This should not occur at the
+            # start.)
+            $ancestor = $this->parent->pegrev < $that->parent->pegrev
+                        ? $this->parent : $that->parent;
+          }
+
+        } else {
+          # Different URLs, ancestor must be the parent with the lower revision.
+          # (This should not occur at the start.)
+          $ancestor = $this->parent->pegrev < $that->parent->pegrev
+                      ? $this->parent : $that->parent;
+        }
+      }
+
+      $self->{ANCESTOR}{$branch->url_peg} = $ancestor;
+    }
+  }
+
+  return $self->{ANCESTOR}{$branch->url_peg};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   ($target, $upper, $lower) = $cm_branch->last_merge_from (
+#     $branch, $stop_on_copy,
+#   );
+#
+# DESCRIPTION
+#   This method returns a 3-element list with information of the last merge
+#   into the current branch from a specified $branch. The first element in the
+#   list $target (a Fcm::CmBranch object) is the target at which the merge was
+#   performed. (This can be the current branch or a parent branch up to the
+#   common ancestor with the specified $branch.) The second and third elements,
+#   $upper and $lower, (both Fcm::CmBranch objects), are the upper and lower
+#   ends of the source delta. If there is no merge from $branch into the
+#   current branch from their common ancestor to the current revision, this
+#   method will return an empty list. If $stop_on_copy is specified, it ignores
+#   merges from parents of $branch, and merges into parents of the current
+#   branch.
+# ------------------------------------------------------------------------------
+
+sub last_merge_from {
+  my ($self, $branch, $stop_on_copy) = @_;
+
+  if (not exists $self->{LAST_MERGE}{$branch->url_peg}) {
+    # Get "log" of current branch down to the common ancestor
+    my %log = $self->svnlog (
+      REV => [
+       ($self->pegrev ? $self->pegrev : 'HEAD'),
+       $self->ancestor ($branch)->pegrev,
+      ],
+
+      STOP_ON_COPY => $stop_on_copy,
+    );
+
+    my $cr = $self;
+
+    # Go down the revision log, checking for merge template messages
+    REV: for my $rev (sort {$b <=> $a} keys %log) {
+      # Loop each line of the log message at each revision
+      my @msg = split /\n/, $log{$rev}{msg};
+
+      # Also consider merges into parents of current branch
+      $cr = $cr->parent if ($cr->is_branch and $rev < $cr->create_rev);
+
+      for (@msg) {
+        # Ignore unless log message matches a merge template
+        next unless /Merged into \S+: (\S+) cf\. (\S+)/;
+
+        # Upper $1 and lower $2 ends of the source delta
+        my $u_path = $1;
+        my $l_path = $2;
+
+        # Add the root directory to the paths if necessary
+        $u_path = '/' . $u_path if substr ($u_path, 0, 1) ne '/';
+        $l_path = '/' . $l_path if substr ($l_path, 0, 1) ne '/';
+
+        # Only consider merges with specified branch (and its parent)
+        (my $path = $u_path) =~ s/@(\d+)$//;
+        my $u_rev = $1;
+
+        my $br = $branch;
+        $br    = $br->parent while (
+          $br->is_branch and $u_rev < $br->create_rev and not $stop_on_copy
+        );
+
+        next unless $br->branch_path eq $path;
+
+        # If $br is a parent of branch, ignore those merges with the parent
+        # above the branch point of the current branch
+        next if $br->pegrev and $br->pegrev < $u_rev;
+
+        # Set the return values
+        $self->{LAST_MERGE}{$branch->url_peg} = [
+          Fcm::CmBranch->new (URL => $cr->url . '@' . $rev), # target
+          Fcm::CmBranch->new (URL => $self->root . $u_path), # delta upper
+          Fcm::CmBranch->new (URL => $self->root . $l_path), # delta lower
+        ];
+
+        last REV;
+      }
+    }
+  }
+
+  return (exists $self->{LAST_MERGE}{$branch->url_peg}
+          ? @{ $self->{LAST_MERGE}{$branch->url_peg} } : ());
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @revs = $cm_branch->avail_merge_from ($branch[, $stop_on_copy]);
+#
+# DESCRIPTION
+#   This method returns a list of revisions of a specified $branch, which are
+#   available for merging into the current branch. If $stop_on_copy is
+#   specified, it will not list available merges from the parents of $branch.
+# ------------------------------------------------------------------------------
+
+sub avail_merge_from {
+  my ($self, $branch, $stop_on_copy) = @_;
+
+  if (not exists $self->{AVAIL_MERGE}{$branch->url_peg}) {
+    # Find out the revision of the upper delta at the last merge from $branch
+    # If no merge is found, use revision of common ancestor with $branch
+    my @last_merge = $self->last_merge_from ($branch);
+    my $rev        = $self->ancestor ($branch)->pegrev;
+    $rev           = $last_merge [1]->pegrev
+      if @last_merge and $last_merge [1]->pegrev > $rev;
+
+    # Get the "log" of the $branch down to $rev
+    my %log = $branch->svnlog (
+      REV          => [($branch->pegrev ? $branch->pegrev : 'HEAD'), $rev],
+      STOP_ON_COPY => $stop_on_copy,
+    );
+
+    # No need to include $rev itself, as it has already been merged
+    delete $log{$rev};
+
+    # No need to include the branch create revision
+    delete $log{$branch->create_rev}
+      if $branch->is_branch and exists $log{$branch->create_rev};
+
+    if (keys %log) {
+      # Check whether there is a latest merge from $self into $branch, if so,
+      # all revisions of $branch below that merge should become unavailable
+      my @last_merge_into = $branch->last_merge_from ($self);
+
+      if (@last_merge_into) {
+        for my $rev (keys %log) {
+          delete $log{$rev} if $rev < $last_merge_into [0]->pegrev;
+        }
+      }
+    }
+
+    # Available merges include all revisions above the branch creation revision
+    # or the revision of the last merge
+    $self->{AVAIL_MERGE}{$branch->url_peg} = [sort {$b <=> $a} keys %log];
+  }
+
+  return @{ $self->{AVAIL_MERGE}{$branch->url_peg} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $lower = $cm_branch->base_of_merge_from ($branch);
+#
+# DESCRIPTION
+#   This method returns the lower delta (a Fcm::CmBranch object) for the next
+#   merge from $branch.
+# ------------------------------------------------------------------------------
+
+sub base_of_merge_from {
+  my ($self, $branch) = @_;
+
+  # Base is the ancestor if there is no merge between $self and $branch
+  my $return = $self->ancestor ($branch);
+
+  # Get configuration for the last merge from $branch to $self
+  my @merge_from = $self->last_merge_from ($branch);
+
+  # Use the upper delta of the last merge from $branch, as all revisions below
+  # that have already been merged into the $self
+  $return = $merge_from [1]
+    if @merge_from and $merge_from [1]->pegrev > $return->pegrev;
+
+  # Get configuration for the last merge from $self to $branch
+  my @merge_into = $branch->last_merge_from ($self);
+
+  # Use the upper delta of the last merge from $self, as the current revision
+  # of $branch already contains changes of $self up to the peg revision of the
+  # upper delta
+  $return = $merge_into [1]
+    if @merge_into and $merge_into [0]->pegrev > $return->pegrev;
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $cm_branch->allow_subdir_merge_from ($branch, $subdir);
+#
+# DESCRIPTION
+#   This method returns true if a merge from the sub-directory $subdir in
+#   $branch  is allowed - i.e. it does not result in losing changes made in
+#   $branch outside of $subdir.
+# ------------------------------------------------------------------------------
+
+sub allow_subdir_merge_from {
+  my ($self, $branch, $subdir) = @_;
+
+  # Get revision at last merge from $branch or ancestor
+  my @merge_from = $self->last_merge_from ($branch);
+  my $last       = @merge_from ? $merge_from [1] : $self->ancestor ($branch);
+  my $rev        = $last->pegrev;
+
+  if ($branch->pegrev > $rev) {
+    # Inspect log from revision at last merge/ancestor to current revision
+    my %log = $branch->svnlog (REV => [$branch->pegrev, $rev + 1]);
+    my $br  = $branch;
+
+    # Check whether there are changes outside of $subdir
+    for my $rev (sort {$b <=> $a} keys %log) {
+      $br = $br->parent if $br->is_branch and $rev < $br->create_rev;
+
+      for my $path (keys %{ $log{$rev}{paths} }) {
+        next if $path eq $br->branch_path; # Ignore branch creation
+
+        my $p_subdir = substr ($path, length ($br->branch_path) + 1);
+
+        return if $p_subdir !~ m#^$subdir(?:/|$)#;
+      }
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cm_branch->create (
+#     SRC                  => $src,
+#     TYPE                 => $type,
+#     NAME                 => $name,
+#     [PASSWORD            => $password,]
+#     [REV_FLAG            => $rev_flag,]
+#     [TICKET              => \@tickets,]
+#     [REV                 => $rev,]
+#     [NON_INTERACTIVE     => 1,]
+#     [SVN_NON_INTERACTIVE => 1,]
+#   );
+#
+# DESCRIPTION
+#   This method creates a branch in a Subversion repository.
+#
+# OPTIONS
+#   SRC                 - reference to a Fcm::CmUrl object.
+#   TYPE                - Specify the branch type. See help in "fcm branch" for
+#                         further information.
+#   NAME                - specify the name of the branch.
+#   NON_INTERACTIVE     - Do no interactive prompting, set SVN_NON_INTERACTIVE
+#                         to true automatically.
+#   PASSWORD            - specify the password for commit access.
+#   REV                 - specify the operative revision of the source.
+#   REV_FLAG            - A flag to specify the behaviour of the prefix to the
+#                         branch name. See help in "fcm branch" for further
+#                         information.
+#   SVN_NON_INTERACTIVE - Do no interactive prompting when running svn commit,
+#                         etc. This option is implied by NON_INTERACTIVE.
+#   TICKET              - Specify one or more related tickets for the branch.
+# ------------------------------------------------------------------------------
+
+sub create {
+  my $self = shift;
+  my %args = @_;
+
+  # Options
+  # ----------------------------------------------------------------------------
+  # Compulsory options
+  my $src  = $args{SRC};
+  my $type = $args{TYPE};
+  my $name = $args{NAME};
+
+  # Other options
+  my $rev_flag        = $args{REV_FLAG}        ? $args{REV_FLAG}    : 'NORMAL';
+  my @tickets         = exists $args{TICKET}   ? @{ $args{TICKET} } : ();
+  my $password        = exists $args{PASSWORD} ? $args{PASSWORD}    : undef;
+  my $orev            = exists $args{REV}      ? $args{REV}         : 'HEAD';
+
+  my $non_interactive     = exists $args{NON_INTERACTIVE}
+                            ? $args{NON_INTERACTIVE} : 0;
+  my $svn_non_interactive = exists $args{SVN_NON_INTERACTIVE}
+                            ? $args{SVN_NON_INTERACTIVE} : 0;
+  $svn_non_interactive    = $non_interactive ? 1 : $svn_non_interactive;
+
+  # Analyse the source URL
+  # ----------------------------------------------------------------------------
+  # Create branch from the trunk by default
+  $src->branch ('trunk') if not $src->branch;
+
+  # Remove "sub-directory" part from source URL
+  $src->subdir ('')      if $src->subdir;
+
+  # Remove "peg revision" part because it does not work with "svn copy"
+  $src->pegrev ('')      if $src->pegrev;
+
+  # Find out the URL and the last changed revision of the specified URL at the
+  # specified operative revision
+  my $url = $src->svninfo (FLAG => 'URL', REV => $orev);
+  e_report $src->url, ': cannot determine the operative URL at revision ',
+           $orev, ', abort.' if not $url;
+
+  $src->url ($url) if $url ne $src->url;
+
+  my $rev = $src->svninfo (FLAG => 'Last Changed Rev', REV => $orev);
+  e_report $src->url, ': cannot determine the last changed rev at revision',
+           $orev, ', abort.' if not $rev;
+
+  # Warn user if last changed revision is not the specified revision
+  w_report 'Warning: branch will be created from revision ', $rev,
+           ', i.e. the last changed rev.'
+    unless $orev and $orev eq $rev;
+
+  # Determine the sub-directory names of the branch
+  # ----------------------------------------------------------------------------
+  my @branch_dirs = ('branches');
+
+  # Split branch type flags into a hash table
+  my %type_flags = ();
+  $type_flags{$_} = 1 for ((split /::/, $type));
+
+  # Branch sub-directory 1, development, test or package
+  for my $flag (qw/DEV TEST PKG/) {
+    if (exists $type_flags{$flag}) {
+      push @branch_dirs, lc ($flag);
+      last;
+    }
+  }
+
+  # Branch sub-directory 2, user, share, configuration or release
+  if (exists $type_flags{USER}) {
+    my $userid = getlogin;
+    $userid    = $ENV{LOGNAME} unless $userid;
+    $userid    = $ENV{USER}    unless $userid;
+    die 'Unable to determine your user ID, abort' unless $userid;
+
+    push @branch_dirs, $userid;
+
+  } else {
+    for my $flag (qw/SHARE CONFIG REL/) {
+      if (exists $type_flags{$flag}) {
+        push @branch_dirs, uc (substr $flag, 0, 1) . lc (substr $flag, 1);
+        last;
+      }
+    }
+  }
+
+  # Branch sub-directory 3, branch name
+  # Prefix branch name with revision number/keyword if necessary
+  my $prefix = '';
+  if ($rev_flag ne 'NONE') {
+    $prefix = $rev;
+
+    # Attempt to replace revision number with a revision keyword if necessary
+    $prefix = &get_rev_keyword (
+      REV => $rev,
+      URL => $src->url_peg,
+    ) if $rev_flag eq 'NORMAL';
+
+    # $prefix is still a revision number, add "r" in front of it
+    $prefix = 'r' . $prefix if $prefix eq $rev;
+
+    # Add an underscore before the branch name
+    $prefix.= '_';
+  }
+
+  # Branch name
+  push @branch_dirs, $prefix . $name;
+
+  # Check whether the branch already exists, fail if so
+  # ----------------------------------------------------------------------------
+  # Construct the URL of the branch
+  $self->project_url ($src->project_url);
+  $self->branch  (join ('/', @branch_dirs));
+
+  # Check that branch does not already exists
+  e_report $self->url, ': branch already exists, abort.' if $self->url_exists;
+
+  # Message for the commit log
+  # ----------------------------------------------------------------------------
+  my @message = ('Created ' . $self->branch_path .  ' from ' .
+                 $src->branch_path . '@' . $rev . '.' . "\n");
+
+  # Add related Trac ticket links to commit log if set
+  if (@tickets) {
+    my $ticket_mesg = 'Relates to ticket' . (@tickets > 1 ? 's' : '');
+
+    while (my $ticket = shift @tickets) {
+      $ticket_mesg .= ' #' . $ticket;
+      $ticket_mesg .= (@tickets > 1 ? ',' : ' and') if @tickets >= 1;
+    }
+
+    push @message, $ticket_mesg . ".\n";
+  }
+
+  # Create a temporary file for the commit log message
+  my $ci_mesg = Fcm::CmCommitMessage->new;
+  $ci_mesg->auto_mesg (@message);
+  $ci_mesg->ignore_mesg ('A' . ' ' x 4 . $self->url . "\n");
+  my $logfile = $ci_mesg->edit_file (TEMP => 1, BATCH => $non_interactive);
+
+  # Check with the user to see if he/she wants to go ahead
+  # ----------------------------------------------------------------------------
+  if (not $non_interactive) {
+    my $reply = &main::get_input (
+      TITLE   => 'fcm branch',
+      MESSAGE => 'Would you like to go ahead and create this branch?',
+      TYPE    => 'yn',
+      DEFAULT => 'n',
+    );
+
+    return unless $reply eq 'y';
+  }
+
+  # Ensure existence of container sub-directories of the branch
+  # ----------------------------------------------------------------------------
+  for my $i (0 .. $#branch_dirs - 1) {
+    my $subdir     = join ('/', @branch_dirs[0 .. $i]);
+    my $subdir_url = Fcm::CmUrl->new (URL => $src->project_url . '/' . $subdir);
+
+    # Check whether each sub-directory of the branch already exists,
+    # if sub-directory does not exist, create it
+    next if $subdir_url->url_exists;
+
+    print 'Creating sub-directory: ', $subdir, "\n";
+
+    my @command = (
+      qw/svn mkdir/,
+      '-m', 'Created ' . $subdir . ' directory.',
+      ($svn_non_interactive  ? '--non-interactive'       : ()),
+      (defined $password     ? ('--password', $password) : ()),
+
+      $subdir_url->url,
+    );
+    &run_command (\@command);
+  }
+
+  # Create the branch
+  # ----------------------------------------------------------------------------
+  {
+    print 'Creating branch ', $self->url, ' ...', "\n";
+    my @command = (
+      qw/svn copy/,
+      '-r', $rev,
+      '-F', $logfile,
+      ($svn_non_interactive  ? '--non-interactive'       : ()),
+      (defined $password     ? ('--password', $password) : ()),
+
+      $src->url, $self->url,
+    );
+    &run_command (\@command);
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cm_branch->delete (
+#     [NON_INTERACTIVE     => 1,]
+#     [PASSWORD            => $password,]
+#     [SVN_NON_INTERACTIVE => 1,]
+#   );
+#
+# DESCRIPTION
+#   This method deletes the current branch from the Subversion repository.
+#
+# OPTIONS
+#   NON_INTERACTIVE     - Do no interactive prompting, set SVN_NON_INTERACTIVE
+#                         to true automatically.
+#   PASSWORD            - specify the password for commit access.
+#   SVN_NON_INTERACTIVE - Do no interactive prompting when running svn commit,
+#                         etc. This option is implied by NON_INTERACTIVE.
+# ------------------------------------------------------------------------------
+
+sub del {
+  my $self = shift;
+  my %args = @_;
+
+  # Options
+  # ----------------------------------------------------------------------------
+  my $password            = exists $args{PASSWORD} ? $args{PASSWORD} : undef;
+  my $non_interactive     = exists $args{NON_INTERACTIVE}
+                            ? $args{NON_INTERACTIVE} : 0;
+  my $svn_non_interactive = exists $args{SVN_NON_INTERACTIVE}
+                            ? $args{SVN_NON_INTERACTIVE} : 0;
+  $svn_non_interactive    = $non_interactive ? 1 : $svn_non_interactive;
+
+  # Ensure URL is a branch
+  # ----------------------------------------------------------------------------
+  e_report $self->url_peg, ': not a branch, abort.' if not $self->is_branch;
+
+  # Message for the commit log
+  # ----------------------------------------------------------------------------
+  my @message = ('Deleted ' . $self->branch_path . '.' . "\n");
+
+  # Create a temporary file for the commit log message
+  my $ci_mesg = Fcm::CmCommitMessage->new ();
+  $ci_mesg->auto_mesg (@message);
+  $ci_mesg->ignore_mesg ('D' . ' ' x 4 . $self->url . "\n");
+  my $logfile = $ci_mesg->edit_file (TEMP => 1, BATCH => $non_interactive);
+
+  # Check with the user to see if he/she wants to go ahead
+  # ----------------------------------------------------------------------------
+  if (not $non_interactive) {
+    my $reply = &main::get_input (
+      TITLE   => 'fcm branch',
+      MESSAGE => 'Would you like to go ahead and delete this branch?',
+      TYPE    => 'yn',
+      DEFAULT => 'n',
+    );
+
+    return unless $reply eq 'y';
+  }
+
+  # Delete branch if answer is "y" for "yes"
+  # ----------------------------------------------------------------------------
+  print 'Deleting branch ', $self->url, ' ...', "\n";
+  my @command = (
+    qw/svn delete/,
+    '-F', $logfile,
+    (defined $password    ? ('--password', $password) : ()),
+    ($svn_non_interactive ? '--non-interactive'       : ()),
+
+    $self->url,
+  );
+  &run_command (\@command);
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cm_branch->display_info (
+#     [SHOW_CHILDREN => 1],
+#     [SHOW_OTHER    => 1]
+#     [SHOW_SIBLINGS => 1]
+#   );
+#
+# DESCRIPTION
+#   This method displays information of the current branch. If SHOW_CHILDREN is
+#   set, it shows information of all current children branches of the current
+#   branch. If SHOW_SIBLINGS is set, it shows information of siblings that have
+#   been merged recently with the current branch. If SHOW_OTHER is set, it shows
+#   information of custom/reverse merges.
+# ------------------------------------------------------------------------------
+
+sub display_info {
+  my $self = shift;
+  my %args = @_;
+
+  # Arguments
+  # ----------------------------------------------------------------------------
+  my $show_children = exists $args{SHOW_CHILDREN} ? $args{SHOW_CHILDREN} : 0;
+  my $show_other    = exists $args{SHOW_OTHER   } ? $args{SHOW_OTHER}    : 0;
+  my $show_siblings = exists $args{SHOW_SIBLINGS} ? $args{SHOW_SIBLINGS} : 0;
+
+  # Useful variables
+  # ----------------------------------------------------------------------------
+  my $separator  = '-' x 80 . "\n";
+  my $separator2 = '  ' . '-' x 78 . "\n";
+
+  # Print "info" as returned by "svn info"
+  # ----------------------------------------------------------------------------
+  for my $key ('URL', 'Repository Root', 'Revision', 'Last Changed Author',
+               'Last Changed Rev', 'Last Changed Date') {
+    print $key, ': ', $self->svninfo (FLAG => $key), "\n"
+      if $self->svninfo (FLAG => $key);
+  }
+
+  if ($self->config->verbose) {
+    # Verbose mode, print log message at last changed revision
+    my %log = $self->svnlog (REV => $self->svninfo (FLAG => 'Last Changed Rev'));
+    my @log = split /\n/, $log{msg};
+    print 'Last Changed Log:', "\n\n", map ({'  ' . $_ . "\n"} @log), "\n";
+  }
+
+  if ($self->is_branch) {
+    # Print create information
+    # --------------------------------------------------------------------------
+    my %log = $self->svnlog (REV => $self->create_rev);
+
+    print $separator;
+    print 'Branch Create Author: ', $log{author}, "\n" if $log{author};
+    print 'Branch Create Rev: ', $self->create_rev, "\n";
+    print 'Branch Create Date: ', &svn_date ($log{date}), "\n";
+
+    if ($self->config->verbose) {
+      # Verbose mode, print log message at last create revision
+      my @log = split /\n/, $log{msg};
+      print 'Branch Create Log:', "\n\n", map ({'  ' . $_ . "\n"} @log), "\n";
+    }
+
+    # Print delete information if branch no longer exists
+    # --------------------------------------------------------------------------
+    print 'Branch Delete Rev: ', $self->delete_rev, "\n" if $self->delete_rev;
+
+    # Report merges into/from the parent
+    # --------------------------------------------------------------------------
+    # Print the URL@REV of the parent branch
+    print $separator, 'Branch Parent: ', $self->parent->url_peg, "\n";
+
+    # Set up a new object for the parent at the current revision
+    # --------------------------------------------------------------------------
+    my $p_url  = $self->parent->url;
+    $p_url    .= '@' . $self->pegrev if $self->pegrev;
+    my $parent = Fcm::CmBranch->new (URL => $p_url);
+
+    if (not $parent->url_exists) {
+      print 'Branch parent deleted.', "\n";
+      return;
+    }
+
+    # Report merges into/from the parent
+    # --------------------------------------------------------------------------
+    print $self->_report_merges ($parent, 'Parent');
+  }
+
+  # Report merges with siblings
+  # ----------------------------------------------------------------------------
+  if ($show_siblings) {
+    # Report number of sibling branches found
+    print $separator, 'Seaching for siblings ... ';
+    my @siblings = $self->siblings;
+    print scalar (@siblings), ' ', (@siblings> 1 ? 'siblings' : 'sibling'),
+          ' found.', "\n";
+
+    # Report branch name and merge information only if there are recent merges
+    my $out = '';
+    for my $sibling (@siblings) {
+      my $string = $self->_report_merges ($sibling, 'Sibling');
+
+      $out .= $separator2 . '  ' . $sibling->url . "\n" . $string if $string;
+    }
+
+    if (@siblings) {
+      if ($out) {
+        print 'Merges with existing siblings:', "\n", $out;
+
+      } else {
+        print 'No merges with existing siblings.', "\n";
+      }
+    }
+  }
+
+  # Report children
+  # ----------------------------------------------------------------------------
+  if ($show_children) {
+    # Report number of child branches found
+    print $separator, 'Seaching for children ... ';
+    my @children = $self->children;
+    print scalar (@children), ' ', (@children > 1 ? 'children' : 'child'),
+          ' found.', "\n";
+
+    # Report children if they exist
+    print 'Current children:', "\n" if @children;
+
+    for my $child (@children) {
+      print $separator2, '  ', $child->url, "\n";
+      print '  Child Create Rev: ', $child->create_rev, "\n";
+      print $self->_report_merges ($child, 'Child');
+    }
+  }
+
+  # Report custom/reverse merges into the branch
+  # ----------------------------------------------------------------------------
+  if ($show_other) {
+    my %log = $self->svnlog (STOP_ON_COPY => 1);
+    my @out;
+
+    # Go down the revision log, checking for merge template messages
+    REV: for my $rev (sort {$b <=> $a} keys %log) {
+      # Loop each line of the log message at each revision
+      my @msg = split /\n/, $log{$rev}{msg};
+
+      for (@msg) {
+        # Ignore unless log message matches a merge template
+        if (/^Reversed r\d+(:\d+)? of \S+$/ or
+            s/^(Custom merge) into \S+(:.+)$/$1$2/) {
+          push @out, ('r' . $rev . ': ' . $_) . "\n";
+        }
+      }
+    }
+
+    print $separator, 'Other merges:', "\n", @out if @out;
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = $self->_report_merges ($branch, $relation);
+#
+# DESCRIPTION
+#   This method returns a string for displaying merge information with a
+#   branch, the $relation of which can be a Parent, a Sibling or a Child.
+# ------------------------------------------------------------------------------
+
+sub _report_merges {
+  my ($self, $branch, $relation) = @_;
+
+  my $indent    = ($relation eq 'Parent') ? '' : '  ';
+  my $separator = ($relation eq 'Parent') ? ('-' x 80) : ('  ' . '-' x 78);
+  $separator   .= "\n";
+
+  my $return = '';
+
+  # Report last merges into/from the $branch
+  # ----------------------------------------------------------------------------
+  my %merge  = (
+    'Last Merge From ' . $relation . ':'
+    => [$self->last_merge_from ($branch, 1)],
+    'Last Merge Into ' . $relation . ':'
+    => [$branch->last_merge_from ($self, 1)],
+  );
+
+  if ($self->config->verbose) {
+    # Verbose mode, print the log of the merge
+    for my $key (keys %merge) {
+      next if not @{ $merge{$key} };
+
+      # From: target (0) is self, upper delta (1) is $branch
+      # Into: target (0) is $branch, upper delta (1) is self
+      my $t = ($key =~ /From/) ? $self : $branch;
+
+      $return .= $indent . $key . "\n";
+      $return .= $separator . $t->display_svnlog ($merge{$key}[0]->pegrev);
+    }
+
+  } else {
+    # Normal mode, print in simplified form (rREV Parent@REV)
+    for my $key (keys %merge) {
+      next if not @{ $merge{$key} };
+
+      # From: target (0) is self, upper delta (1) is $branch
+      # Into: target (0) is $branch, upper delta (1) is self
+      $return .= $indent . $key . ' r' . $merge{$key}[0]->pegrev . ' ' .
+                 $merge{$key}[1]->path_peg . ' cf. ' .
+                 $merge{$key}[2]->path_peg . "\n";
+    }
+  }
+
+  if ($relation eq 'Sibling') {
+    # For sibling, do not report further if there is no recent merge
+    my @values = values %merge;
+
+    return $return unless (@{ $values[0] } or @{ $values[1] });
+  }
+
+  # Report available merges into/from the $branch
+  # ----------------------------------------------------------------------------
+  my %avail = (
+    'Merges Avail From ' . $relation . ':'
+    => ($self->delete_rev ? [] : [$self->avail_merge_from ($branch, 1)]),
+    'Merges Avail Into ' . $relation . ':'
+    => [$branch->avail_merge_from ($self, 1)],
+  );
+
+  if ($self->config->verbose) {
+    # Verbose mode, print the log of each revision
+    for my $key (keys %avail) {
+      next unless @{ $avail{$key} };
+
+      $return .= $indent . $key . "\n";
+
+      my $s = ($key =~ /From/) ? $branch: $self;
+
+      for my $rev (@{ $avail{$key} }) {
+        $return .= $separator . $s->display_svnlog ($rev);
+      }
+    }
+
+  } else {
+    # Normal mode, print only the revisions
+    for my $key (keys %avail) {
+      next unless @{ $avail{$key} };
+
+      $return .= $indent . $key . ' ' . join (' ', @{ $avail{$key} }) . "\n";
+    }
+  }
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/lib/Fcm/CmCommitMessage.pm
===================================================================
--- LMDZ5/branches/testing/tools/fcm/lib/Fcm/CmCommitMessage.pm	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/lib/Fcm/CmCommitMessage.pm	(revision 1665)
@@ -0,0 +1,395 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::CmCommitMessage
+#
+# DESCRIPTION
+#   This class contains methods to read, write and edit the commit message file
+#   in a working copy.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::CmCommitMessage;
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Standard modules
+use Carp;
+use Cwd;
+use File::Spec;
+use File::Temp qw/tempfile/;
+
+# FCM component modules
+use Fcm::Util qw/e_report run_command/;
+
+# Commit log delimiter messages
+my $ignore_line = '--This line, and those below, will be ignored--';
+my $auto_line   = '--This line will be ignored and those below will be ' .
+                  'inserted automatically--';
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ci_mesg = Fcm::CmCommitMessage->new (
+#     CONFIG  => $config,
+#     DIR     => $dir,
+#     BASE    => $base,
+#   );
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::CmCommitMessageFile class.
+#
+# ARGUMENTS
+#   CONFIG - reference to a Fcm::Config instance
+#   DIR    - directory containing the commit message file
+#   BASE   - base name of the commit message file
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $self = {
+    CONFIG => (exists $args{CONFIG} ? $args{CONFIG} : &main::cfg),
+    DIR    => (exists $args{DIR}    ? $args{DIR}    : cwd),
+    BASE   => (exists $args{BASE}   ? $args{BASE}   : '#commit_message#'),
+    USER_M => [],
+    AUTO_M => [],
+    IGNORE => [],
+  };
+
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = $ci_mesg->config;
+#
+# DESCRIPTION
+#   This method returns a reference to the Fcm::Config instance.
+# ------------------------------------------------------------------------------
+
+sub config {
+  my $self = shift;
+
+  return $self->{CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $dir = $ci_mesg->dir;
+#   $ci_mesg->dir ($dir);
+#
+# DESCRIPTION
+#   This method returns the directory container of the commit message file. If
+#   an argument is specified, the directory is reset using the value of the
+#   argument. (It does nothing is the directory does not already exist.)
+# ------------------------------------------------------------------------------
+
+sub dir {
+  my $self = shift;
+
+  if (@_) {
+    my $dir = shift;
+    $self->{DIR} = $dir if -d $dir;
+  }
+
+  return $self->{DIR};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $base = $ci_mesg->base;
+#   $ci_mesg->base ($base);
+#
+# DESCRIPTION
+#   This method returns the base name of the commit message file. If an
+#   argument is specified, the file is reset using the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub base {
+  my $self = shift;
+
+  if (@_) {
+    $self->{BASE} = shift;
+  }
+
+  return $self->{BASE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $file = $ci_mesg->file;
+#   $ci_mesg->file ($file);
+#
+# DESCRIPTION
+#   This method returns the full name of the commit message file. If an
+#   argument is specified, the file is reset using the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub file {
+  my $self = shift;
+
+  if (@_) {
+    my $file      = shift;
+    $self->{DIR}  = dirname  ($file);
+    $self->{BASE} = basename ($file);
+  }
+
+  return File::Spec->catfile ($self->{DIR}, $self->{BASE});
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @mesg = $ci_mesg->user_mesg;
+#   $ci_mesg->user_mesg (@mesg);
+#
+# DESCRIPTION
+#   This method returns the user defined commit message. If an argument is
+#   specified, the message is reset using the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub user_mesg {
+  my $self = shift;
+
+  if (@_) {
+    @{ $self->{USER_M} } = @_;
+  }
+
+  return @{ $self->{USER_M} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @mesg = $ci_mesg->auto_mesg;
+#   $ci_mesg->auto_mesg (@mesg);
+#
+# DESCRIPTION
+#   This method returns the automatically inserted commit message. If an
+#   argument is specified, the message is reset using the value of the
+#   argument.
+# ------------------------------------------------------------------------------
+
+sub auto_mesg {
+  my $self = shift;
+
+  if (@_) {
+    @{ $self->{AUTO_M} } = @_;
+  }
+
+  return @{ $self->{AUTO_M} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @mesg = $ci_mesg->ignore_mesg;
+#   $ci_mesg->ignore_mesg (@mesg);
+#
+# DESCRIPTION
+#   This method returns the ignored part of a commit message. If an argument is
+#   specified, the message is reset using the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub ignore_mesg {
+  my $self = shift;
+
+  if (@_) {
+    @{ $self->{IGNORE} } = @_;
+  }
+
+  return @{ $self->{IGNORE} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   ($user, $auto) = $ci_mesg->read_file ();
+#
+# DESCRIPTION
+#   This function reads from the commit log message file. It resets the user
+#   and the automatic messages after reading the file. It returns the message
+#   back in two array references.
+# ------------------------------------------------------------------------------
+
+sub read_file {
+  my $self = shift;
+
+  my @user = ();
+  my @auto = ();
+  my $file = $self->file;
+
+  if (-r $file) {
+    open FILE, '<', $file or croak 'Cannot open ', $file, '(', $!, '), abort';
+
+    my $in_auto = 0;
+    while (<FILE>) {
+      last if index ($_, $ignore_line) == 0; # ignore after the ignore delimiter
+
+      if (index ($_, $auto_line) == 0) {
+        # Beginning of the automatically inserted message delimiter
+        $in_auto = 1;
+        next;
+      }
+
+      if ($in_auto) {
+        push @auto, $_;
+
+      } else {
+        push @user, $_;
+      }
+    }
+
+    close FILE;
+
+    $self->user_mesg (@user);
+    $self->auto_mesg (@auto);
+  }
+
+  return (\@user, \@auto);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ci_mesg->write_file ();
+#
+# DESCRIPTION
+#   This function writes to the commit log message file based on the content of
+#   the user defined message, and the automatically inserted message.
+# ------------------------------------------------------------------------------
+
+sub write_file {
+  my $self = shift;
+  my %args = @_;
+
+  my @user = $self->user_mesg;
+  my @auto = $self->auto_mesg;
+  my $file = $self->file;
+
+  open FILE, '>', $file or die 'Cannot open ', $file, '(', $!, '), abort';
+  print FILE @user;
+  print FILE $auto_line, "\n", @auto if @auto;
+  close FILE or croak 'Cannot close ', $file, '(', $!, '), abort';
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $file = $ci_mesg->edit_file ([TEMP => 1,] [BATCH => 1,]);
+#
+# DESCRIPTION
+#   This function normally triggers an editor for editing the commit message.
+#   If TEMP is set, it edits a temporary file. Otherwise, it edits the current
+#   commit message file. It resets the user defined message on success. Returns
+#   the name of the commit log file. Do not start the editor if BATCH is set.
+# ------------------------------------------------------------------------------
+
+sub edit_file {
+  my $self  = shift;
+  my %args  = @_;
+  my $temp  = exists $args{TEMP}  ? $args{TEMP}  : 0;
+  my $batch = exists $args{BATCH} ? $args{BATCH} : 0;
+
+  my @user   = $self->user_mesg;
+  my @auto   = $self->auto_mesg;
+  my @ignore = $self->ignore_mesg;
+  my $file   = $self->file;
+
+  if ($temp) {
+    my $fh;
+    ($fh, $file) = tempfile (SUFFIX => ".fcm", UNLINK => 1);
+    close $fh;
+  }
+
+  # Add original or code driven message and status information to the file
+  my $select = select;
+  open FILE, '>', $file or croak 'Cannot open ', $file, ' (', $!, '), abort';
+  select FILE;
+
+  print @user;
+  print (@auto || @user ? '' : "\n");
+  print $auto_line, "\n", @auto, "\n" if @auto;
+  print $ignore_line, "\n\n";
+  print @ignore if @ignore;
+
+  close FILE or die 'Cannot close ', $file, ' (', $!, '), abort';
+  select $select;
+
+  if (not $batch) {
+    # Select editor
+    my $editor = 'nedit';
+    
+    if ($ENV{'SVN_EDITOR'}) {
+      $editor = $ENV{'SVN_EDITOR'};
+
+    } elsif ($ENV{'VISUAL'}) {
+      $editor = $ENV{'VISUAL'};
+
+    } elsif ($ENV{'EDITOR'}) {
+      $editor = $ENV{'EDITOR'};
+    }
+
+    # Execute command to start the editor
+    print 'Starting ', $editor, ' to edit commit message ...', "\n";
+    &run_command ([split (/\s+/, $editor), $file]);
+  }
+
+  # Read the edited file, and extract user log message from it
+  open FILE, '<', $file or croak 'Cannot open ', $file, ' (', $!, '), abort';
+  my (@log);
+  my $in_auto    = 0;
+  my $in_ignored = 0;
+
+  while (<FILE>) {
+    if (index ($_, $auto_line) == 0) {
+      $in_auto = 1;
+
+    } elsif (index ($_, $ignore_line) == 0) {
+      $in_ignored = 1;
+      last;
+
+    } else {
+      next if $in_auto;
+      push @log, $_;
+    }
+  }
+
+  close FILE;
+
+  # Ensure auto and ignored lines are not altered
+  e_report 'Error: the line "', $auto_line, '" has been altered, abort.'
+    if @auto and not $in_auto;
+
+  e_report 'Error: the line "', $ignore_line, '" has been altered, abort.'
+    if not $in_ignored;
+
+  # Check for empty commit log
+  e_report 'Error: log message unchanged or not specified, abort.'
+    if join (' ', (@log, @auto)) =~ /^\s*$/;
+
+  # Echo the commit message to standard output
+  my $separator = '-' x 80 . "\n";
+  print 'Commit message is as follows:', "\n";
+  print $separator, @log, @auto, $ignore_line, "\n", @ignore, $separator;
+
+  open FILE, '>', $file or croak 'Cannot open ', $file, ' (', $!, '), abort';
+  print FILE @log, @auto;
+  close FILE or croak 'Cannot close ', $file, ' (', $!, '), abort';
+
+  # Reset the array for the user specified log message
+  $self->user_mesg (@log);
+
+  return $file;
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/lib/Fcm/CmUrl.pm
===================================================================
--- LMDZ5/branches/testing/tools/fcm/lib/Fcm/CmUrl.pm	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/lib/Fcm/CmUrl.pm	(revision 1665)
@@ -0,0 +1,1138 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::CmUrl
+#
+# DESCRIPTION
+#   This class contains methods for manipulating a Subversion URL in a standard
+#   FCM project.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::CmUrl;
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Standard modules
+use Carp;
+use File::Spec;
+use HTTP::Date;
+use XML::DOM;
+
+# FCM component modules
+use Fcm::Util qw/run_command svn_date get_browser_url/;
+
+# Revision pattern
+my $rev_pattern = '\d+|HEAD|BASE|COMMITTED|PREV|\{.+\}';
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cm_url = Fcm::CmUrl->new (
+#     CONFIG  => $config,
+#     URL     => $url,
+#   );
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::CmUrl class.
+#
+# ARGUMENTS
+#   CONFIG - reference to a Fcm::Config instance
+#   URL    - URL of a branch
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $self = {
+    CONFIG      => (exists $args{CONFIG} ? $args{CONFIG} : &main::cfg),
+    URL         => (exists $args{URL}    ? $args{URL}    : ''),
+    ANALYSED    => undef,
+    PROJECT     => undef,
+    BRANCH      => undef,
+    SUBDIR      => undef,
+    PEGREV      => undef,
+    LIST        => undef,
+    RLIST       => undef,
+    LOG         => undef,
+    LOG_RANGE   => undef,
+    INFO        => undef,
+    BRANCH_LIST => undef, # list of branches in current project
+  };
+
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = $cm_url->config;
+#
+# DESCRIPTION
+#   This method returns a reference to the Fcm::Config instance.
+# ------------------------------------------------------------------------------
+
+sub config {
+  my $self = shift;
+
+  return $self->{CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $url = $cm_url->url_peg;
+#   $cm_url->url_peg ($url);
+#
+# DESCRIPTION
+#   This method returns/sets the current URL@PEG.
+# ------------------------------------------------------------------------------
+
+sub url_peg {
+  my $self = shift;
+
+  if (@_) {
+    if (! $self->{URL} or $_[0] ne $self->{URL}) {
+      # Re-set URL
+      $self->{URL} = shift;
+
+      # Re-set essential variables
+      $self->{$_}  = undef for (qw/ANALYSED RLIST LIST INFO LOG LOG_RANGE/);
+    }
+  }
+
+  return $self->{URL};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $cm_url->is_url ();
+#
+# DESCRIPTION
+#   Returns true if current url is a valid Subversion URL.
+# ------------------------------------------------------------------------------
+
+sub is_url {
+  my $self = shift;
+
+  # This should handle URL beginning with svn://, http:// and svn+ssh://
+  return ($self->url_peg =~ m#^[\+\w]+://#);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $cm_url->url_exists ([$rev]);
+#
+# DESCRIPTION
+#   Returns true if current url exists (at operative revision $rev) in a
+#   Subversion repository.
+# ------------------------------------------------------------------------------
+
+sub url_exists {
+  my ($self, $rev) = @_;
+
+  my $exists = $self->svnlist (REV => $rev);
+
+  return defined ($exists);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = $cm_url->svninfo ([FLAG => $flag], [REV => $rev]);
+#
+# DESCRIPTION
+#   Returns the value of $flag, where $flag is a field returned by "svn info".
+#   (If $flag is not set, default to "URL".) Otherwise returns an empty string.
+#   If REV is specified, it will be used as the operative revision.
+# ------------------------------------------------------------------------------
+
+sub svninfo {
+  my $self = shift;
+  my %args = @_;
+
+  my $flag = exists $args{FLAG} ? $args{FLAG} : 'URL';
+  my $rev  = exists $args{REV}  ? $args{REV}  : undef;
+
+  $rev = ($self->pegrev ? $self->pegrev : 'HEAD') if not $rev;
+
+  return if not $self->is_url;
+
+  # Get "info" for the specified revision if necessary
+  if (not exists $self->{INFO}{$rev}) {
+    # Invoke "svn info" command
+    my @info = &run_command (
+      [qw/svn info -r/, $rev, $self->url_peg],
+      PRINT   => $self->config->verbose > 2,
+      METHOD  => 'qx',
+      DEVNULL => 1,
+      ERROR   => 'ignore',
+    );
+
+    # Store selected information
+    for (@info) {
+      chomp;
+
+      if (/^(.+?):\s*(.+)$/) {
+        $self->{INFO}{$rev}{$1} = $2;
+      }
+    }
+  }
+
+  my $return = exists $self->{INFO}{$rev}{$flag}
+               ? $self->{INFO}{$rev}{$flag} : undef;
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   %logs = $cm_url->svnlog (
+#     [REV          => $rev,]
+#     [REV          => \@revs,] # reference to a 2-element array
+#     [STOP_ON_COPY => 1,]
+#   );
+#
+# DESCRIPTION
+#   Returns the logs for the current URL. If REV is a range of revisions or not
+#   specified, return a hash where the keys are revision numbers and the values
+#   are the entries (which are hash references). If a single REV is specified,
+#   return the entry (a hash reference) at the specified REV. Each entry in the
+#   returned list is a hash reference, with the following structure:
+#
+#   $entry = {
+#     author => $author,              # the commit author
+#     date   => $date,                # the commit date (in seconds since epoch)
+#     msg    => $msg,                 # the log message
+#     paths  => {                     # list of changed paths
+#       $path1  => {                  # a changed path
+#         copyfrom-path => $frompath, # copy-from-path
+#         copyfrom-rev  => $fromrev,  # copy-from-revision
+#         action        => $action,   # action status code
+#       },
+#       ...     => { ... },           # ... more changed paths ...
+#     },
+#   }
+# ------------------------------------------------------------------------------
+
+sub svnlog {
+  my $self = shift;
+  my %args = @_;
+
+  my $stop_on_copy  = exists $args{STOP_ON_COPY} ? $args{STOP_ON_COPY} : 0;
+  my $rev_arg       = exists $args{REV}          ? $args{REV}          : 0;
+
+  my @revs;
+
+  # Get revision options
+  # ----------------------------------------------------------------------------
+  if ($rev_arg) {
+    if (ref ($rev_arg)) {
+      # Revsion option is an array, a range of revisions specified?
+      ($revs [0], $revs [1]) = @$rev_arg;
+
+    } else {
+      # A single revision specified
+      $revs [0] = $rev_arg;
+    }
+
+    # Expand 'HEAD' revision
+    for my $rev (@revs) {
+      next unless uc ($rev) eq 'HEAD';
+      $rev = $self->svninfo (FLAG => 'Revision', REV => 'HEAD');
+    }
+
+  } else {
+    # No revision option specified, get log for all revisions
+    $revs [0] = $self->svninfo (FLAG => 'Revision');
+    $revs [1] = 1;
+  }
+
+  $revs [1] = $revs [0] if not $revs [1];
+  @revs     = sort {$b <=> $a} @revs;
+
+  # Check whether a "svn log" run is necessary
+  # ----------------------------------------------------------------------------
+  my $need_update = ! ($revs [0] == $revs [1] and exists $self->{LOG}{$revs [0]});
+  my @ranges      = @revs;
+  if ($need_update and $self->{LOG_RANGE}) {
+    my %log_range = %{ $self->{LOG_RANGE} };
+
+    if ($stop_on_copy) {
+      $ranges [1] = $log_range{UPPER} if $ranges [1] >= $log_range{LOWER_SOC};
+
+    } else {
+      $ranges [1] = $log_range{UPPER} if $ranges [1] >= $log_range{LOWER};
+    }
+  }
+
+  $need_update = 0 if $ranges [0] < $ranges [1];
+
+  if ($need_update) {
+    # Invoke "svn log" command for all revisions of the current branch
+    # --------------------------------------------------------------------------
+    my @command = (
+      qw/svn log --xml -v/, ($stop_on_copy ? '--stop-on-copy' : ()),
+      '-r' . join (':', @ranges),
+      $self->url,
+    );
+
+    my $rc;
+    my @xml = &run_command (
+      \@command,
+      PRINT   => $self->config->verbose > 2,
+      METHOD  => 'qx',
+      DEVNULL => 1,
+      ERROR   => 'ignore',
+      RC      => \$rc,
+    );
+
+    # Parse the XML
+    # --------------------------------------------------------------------------
+    if (not $rc) {
+      my $parser = XML::DOM::Parser->new;
+      my $doc    = $parser->parse (join ('', @xml));
+
+      my $entry_list = $doc->getElementsByTagName ('logentry');
+
+      # Record the author, date, message and path change for each revision
+      for my $i (0 .. $entry_list->getLength - 1) {
+        # Select current entry from node list
+        my $entry = $entry_list->item ($i);
+        my %this = ();
+
+        # Revision is an attribute of the entry node
+        my $rev   = $entry->getAttributeNode ('revision')->getValue;
+
+        # Author, date and log message are children elements of the entry node
+        for my $key (qw/author date msg/) {
+          # Get data of each node, also convert date to seconds since epoch
+          my $node    = $entry->getElementsByTagName ($key)->item (0);
+          my $data    = ($node and $node->getFirstChild)
+                        ? $node->getFirstChild->getData : '';
+          $this{$key} = ($key eq 'date' ? str2time ($data) : $data);
+        }
+
+        # Path nodes are grand children elements of the entry node
+        my $paths = $entry->getElementsByTagName ('path');
+
+        for my $p (0 .. $paths->getLength - 1) {
+          # Select current path node from node list
+          my $node = $paths->item ($p);
+
+          # Get data from the path node
+          my $path = $node->getFirstChild->getData;
+          $this{paths}{$path} = {};
+
+          # Action, copyfrom-path and copyfrom-rev are attributes of path nodes
+          for my $key (qw/action copyfrom-path copyfrom-rev/) {
+            next unless $node->getAttributeNode ($key); # ensure attribute exists
+
+            $this{paths}{$path}{$key} = $node->getAttributeNode ($key)->getValue;
+          }
+        }
+
+        $self->{LOG}{$rev} = \%this;
+      }
+    }
+
+    # Update the range cache
+    # --------------------------------------------------------------------------
+    # Upper end of the range
+    $self->{LOG_RANGE}{UPPER} = $ranges [0]
+      if ! $self->{LOG_RANGE}{UPPER} or $ranges [0] > $self->{LOG_RANGE}{UPPER};
+
+    # Lower end of the range, need to take into account the stop-on-copy option
+    if ($stop_on_copy) {
+      # Lower end of the range with stop-on-copy option
+      $self->{LOG_RANGE}{LOWER_SOC} = $ranges [1]
+        if ! $self->{LOG_RANGE}{LOWER_SOC} or
+           $ranges [1] < $self->{LOG_RANGE}{LOWER_SOC};
+
+      my $low = (sort {$a <=> $b} keys %{ $self->{LOG} }) [0];
+      $self->{LOG_RANGE}{LOWER} = $low
+        if ! $self->{LOG_RANGE}{LOWER} or $low < $self->{LOG_RANGE}{LOWER};
+
+    } else {
+      # Lower end of the range without the stop-on-copy option
+      $self->{LOG_RANGE}{LOWER} = $ranges [1]
+        if ! $self->{LOG_RANGE}{LOWER} or
+           $ranges [1] < $self->{LOG_RANGE}{LOWER};
+
+      $self->{LOG_RANGE}{LOWER_SOC} = $ranges [1]
+        if ! $self->{LOG_RANGE}{LOWER_SOC} or
+           $ranges [1] < $self->{LOG_RANGE}{LOWER_SOC};
+    }
+  }
+
+  my %return = ();
+
+  if (! $rev_arg or ref ($rev_arg)) {
+    # REV is an array, return log entries if they are within range
+    for my $rev (sort {$b <=> $a} keys %{ $self->{LOG} }) {
+      next if $rev > $revs [0] or $revs [1] > $rev;
+
+      $return{$rev} = $self->{LOG}{$rev};
+
+      if ($stop_on_copy) {
+        last if exists $self->{LOG}{$rev}{paths}{$self->branch_path} and
+           $self->{LOG}{$rev}{paths}{$self->branch_path}{action} eq 'A';
+      }
+    }
+
+  } else {
+    # REV is a scalar, return log of the specified revision if it exists
+    %return = %{ $self->{LOG}{$revs [0]} } if exists $self->{LOG}{$revs [0]};
+  }
+
+  return %return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = $cm_branch->display_svnlog ($rev, [$wiki]);
+#
+# DESCRIPTION
+#   This method returns a string for displaying the log of the current branch
+#   at a $rev. If $wiki is set, returns a string for displaying in a Trac wiki
+#   table.  The value of $wiki should be the Subversion URL of a FCM project
+#   associated with the intended Trac system.
+# ------------------------------------------------------------------------------
+
+sub display_svnlog {
+  my ($self, $rev, $wiki) = @_;
+  my $return = '';
+
+  my %log = $self->svnlog (REV => $rev);
+
+  if ($wiki) {
+    # Output in Trac wiki format
+    # --------------------------------------------------------------------------
+    $return .= '|| ' . &svn_date ($log{date}) . ' || ' . $log{author} . ' || ';
+
+    my $trac_url = &get_browser_url (URL => $self->url);
+
+    # Get list of tickets from log
+    my @tickets;
+    while ($log{msg} =~ /(?:#|ticket:)(\d+)/g) {
+      push @tickets, $1;
+    }
+    @tickets = sort {$a <=> $b} @tickets;
+
+    if ($trac_url =~ m#^$wiki(?:/*|$)#) {
+      # URL is in the specified $wiki, use Trac link
+      $return .= '[' . $rev . '] ||';
+
+      for my $ticket (@tickets) {
+        $return .= ' #' . $ticket;
+      }
+
+      $return .= ' ||';
+
+    } else {
+      # URL is not in the specified $wiki, use full URL
+      my $rev_url = $trac_url;
+      $rev_url    =~ s#/browser/.*$##;
+      $rev_url   .= '/changeset/' . $rev;
+      $return    .= '[' . $rev_url . ' ' . $rev . '] ||';
+
+      my $ticket_url = $trac_url;
+      $ticket_url    =~ s#/browser/.*$#/ticket/#;
+
+      for my $ticket (@tickets) {
+        $return .= ' [' . $ticket_url . $ticket . ' ' . $ticket . ']';
+      }
+
+      $return .= ' ||';
+    }
+
+  } else {
+    # Output in plain text format
+    # --------------------------------------------------------------------------
+    my @msg  = split /\n/, $log{msg};
+    my $line = (@msg > 1 ? ' lines' : ' line');
+
+    $return .= join (
+      ' | ',
+      ('r' . $rev, $log{author}, &svn_date ($log{date}), scalar (@msg) . $line),
+    );
+    $return .= "\n\n";
+    $return .= $log{msg};
+  }
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @list = $cm_url->svnlist ([REV => $rev], [RECURSIVE => 1]);
+#
+# DESCRIPTION
+#   The method returns a list of paths as returned by "svn list". If RECURSIVE
+#   is set, "svn list" is invoked with the "-R" option.
+# ------------------------------------------------------------------------------
+
+sub svnlist {
+  my $self = shift;
+  my %args = @_;
+
+  my $recursive = exists $args{RECURSIVE} ? $args{RECURSIVE} : 0;
+  my $rev       = exists $args{REV}       ? $args{REV}       : undef;
+  my $key       = $recursive ? 'RLIST' : 'LIST';
+
+  # Find out last changed revision of the current URL
+  $rev = $self->svninfo (FLAG => 'Last Changed Rev', REV => $rev);
+  return () if not $rev;
+
+  # Get directory listing for the current URL at the last changed revision
+  if (not exists $self->{$key}{$rev}) {
+    my $rc;
+
+    my @list = map {chomp; $_} &run_command (
+      [qw/svn list -r/, $rev, ($recursive ? '-R' : ()), $self->url_peg],
+      METHOD => 'qx', ERROR => 'ignore', DEVNULL => 1, RC => \$rc,
+    );
+
+    $self->{$key}{$rev} = $rc ? undef : \@list;
+  }
+
+  return (defined ($self->{$key}{$rev}) ? @{ $self->{$key}{$rev} } : undef);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @list = $cm_url->branch_list ($rev);
+#
+# DESCRIPTION
+#   The method returns a list of branches in the current project, assuming the
+#   FCM naming convention. If $rev if specified, it returns the list of
+#   branches at $rev.
+# ------------------------------------------------------------------------------
+
+sub branch_list {
+  my ($self, $rev) = @_;
+
+  # Current URL must be a valid FCM project
+  return if not $self->project;
+
+  # Find out last changed revision of the current URL
+  $rev = $self->svninfo (FLAG => 'Revision', REV => $rev);
+  return () if not $rev;
+
+  if (not exists $self->{BRANCH_LIST}{$rev}) {
+    $self->{BRANCH_LIST}{$rev} = [];
+
+    # Get URL of the project "branches/" sub-directory
+    my $url = Fcm::CmUrl->new (URL => $self->project_url . '/branches');
+
+    # List three levels underneath "branches/"
+    # First level, i.e. dev, test, pkg, etc
+    my @list1 = map {$url->url . '/' . $_} $url->svnlist (REV => $rev);
+    @list1    = grep m#/$#, @list1;
+
+    # Second level, i.e. user name, Shared, Rel or Config
+    my @list2;
+    for (@list1) {
+      my $u    = Fcm::CmUrl->new (URL => $_);
+      my @list = $u->svnlist (REV => $rev);
+
+      push @list2, map {$u->url . $_} @list;
+    }
+
+    # Third level, branch name
+    for (@list2) {
+      my $u    = Fcm::CmUrl->new (URL => $_);
+      my @list = map {s#/*$##; $_} $u->svnlist (REV => $rev);
+
+      push @{ $self->{BRANCH_LIST}{$rev} }, map {$u->url . $_} @list;
+    }
+  }
+
+  return @{ $self->{BRANCH_LIST}{$rev} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_analyse_url ();
+#
+# DESCRIPTION
+#   The method analyses the current URL, breaking it up into the project
+#   (substring of URL up to the slash before "trunk", "branches" or "tags"),
+#   branch name ("trunk", "branches/<type>/<id>/<name>" or "tags/<name>") and
+#   the sub-directory below the top of the project sub-tree. It re-sets the
+#   corresponding interal variables.
+# ------------------------------------------------------------------------------
+
+sub _analyse_url {
+  my $self = shift;
+  my ($url, $project, $branch, $subdir, $pegrev);
+
+  # Check that URL is set
+  $url    = $self->url_peg;
+  return if not $url;
+  return if not $self->is_url;
+
+  # Extract from URL the peg revision
+  $pegrev = $1 if $url =~ s/@($rev_pattern)$//i;
+
+  if ($url =~ m#^(.*?)/+(trunk|branches|tags)(?:/+(.*))?/*$#) {
+    # URL is under the "trunk", a branch or a tag
+    $project                 = $1;
+    my ($branch_id, $remain) = ($2, $3);
+
+    $remain = '' if not defined $remain;
+
+    if ($branch_id eq 'trunk') {
+      # URL under the "trunk"
+      $branch = 'trunk';
+
+    } else {
+      # URL under a branch or a tag
+      $branch = $branch_id;
+
+      # Assume "3 sub-directories", FCM branch naming convention
+      for (1 .. 3) {
+        if ($remain =~ s#^([^/]+)(?:/+|$)##) {
+          $branch .=  '/' . $1;
+
+        } else {
+          $branch = undef;
+          last;
+        }
+      }
+    }
+
+    $subdir = $remain ? $remain : '' if $branch;
+
+  } else {
+    # URL is at some level above the "trunk", a branch or a tag
+    # Use "svn ls" to determine whether it is a project URL
+    my @list = $self->svnlist (REV => ($pegrev ? $pegrev : 'HEAD'));
+    my %lines = map {chomp $_; ($_, 1)} @list;
+
+    # A project URL should have the "trunk", "branches" and "tags" directories
+    ($project = $url) =~ s#/*$##
+      if $lines{'trunk/'} and $lines{'branches/'} and $lines{'tags/'};
+  }
+
+  $self->{PROJECT}  = $project;
+  $self->{BRANCH}   = $branch;
+  $self->{SUBDIR}   = $subdir;
+  $self->{PEGREV}   = $pegrev;
+  $self->{ANALYSED} = 1;
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $url = $cm_url->root ();
+#
+# DESCRIPTION
+#   The method returns the repository root of the current URL.
+# ------------------------------------------------------------------------------
+
+sub root {
+  my $self = shift;
+
+  return $self->svninfo (FLAG => 'Repository Root');
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $url = $cm_url->project_url_peg ();
+#   $cm_url->project_url_peg ($url);
+#
+# DESCRIPTION
+#   The method returns the URL@PEG of the "project" part of the current URL. If
+#   an argument is specified, the URL of the "project" part and the peg
+#   revision of the current URL are re-set.
+# ------------------------------------------------------------------------------
+
+sub project_url_peg {
+  my $self = shift;
+
+  if (@_) {
+    my $url = shift;
+
+    # Re-construct URL is necessary
+    if (! $self->project_url_peg or $url ne $self->project_url_peg) {
+      my $pegrev = ($url =~ s/@($rev_pattern)$//i) ? $1 : '';
+
+      $url .= '/' . $self->branch if $self->branch;
+      $url .= '/' . $self->subdir if $self->subdir;
+      $url .= '@' . $pegrev       if $pegrev;
+
+      $self->url_peg ($url);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return $self->{PROJECT} . ($self->pegrev ? '@' . $self->pegrev : '');
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $url = $cm_url->project_url ();
+#   $cm_url->project_url ($url);
+#
+# DESCRIPTION
+#   The method returns the URL of the "project" part of the current URL. If an
+#   argument is specified, the URL of the "project" part of the current URL is
+#   re-set.
+# ------------------------------------------------------------------------------
+
+sub project_url {
+  my $self = shift;
+
+  if (@_) {
+    my $url = shift;
+    $url =~ s/@($rev_pattern)$//i;
+
+    # Re-construct URL is necessary
+    if (! $self->project_url or $url ne $self->project_url) {
+      $url .= '/' . $self->branch if $self->branch;
+      $url .= '/' . $self->subdir if $self->subdir;
+
+      $self->url ($url);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return $self->{PROJECT};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $path = $cm_url->project_path ();
+#   $cm_url->project_path ($path);
+#
+# DESCRIPTION
+#   The method returns the path of the "project" part of the current URL. If an
+#   argument is specified, the path of the "project" part of the current URL is
+#   re-set.
+# ------------------------------------------------------------------------------
+
+sub project_path {
+  my $self = shift;
+
+  # Repository root
+  my $root = $self->root;
+  $root    = substr (
+    $self->project_url,
+    0,
+    length ($self->project_url) - length ($self->project) - 1
+  ) if not $root;
+
+  if (@_) {
+    my $path = shift;
+
+    # Re-construct URL is necessary
+    if (! $self->project_path or $path ne $self->project_path) {
+      $path .= '/' . $self->branch if $self->branch;
+      $path .= '/' . $self->subdir if $self->subdir;
+
+      $self->path ($path);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return substr ($self->{PROJECT}, length ($root));
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $name = $cm_url->project ();
+#   $cm_url->project ($name);
+#
+# DESCRIPTION
+#   The method returns the basename of the "project" part of the current URL.
+#   If an argument is specified, the basename of the "project" part of the
+#   current URL is re-set.
+# ------------------------------------------------------------------------------
+
+sub project {
+  my $self = shift;
+
+  if (@_) {
+    my $name = shift;
+
+    # Re-construct URL is necessary
+    if (! $self->project or $name ne $self->project) {
+      my $url = '';
+      if ($self->project) {
+        $url =  $self->project;
+        $url =~ s#/[^/]+$##;
+
+      } else {
+        $url =  $self->root;
+      }
+
+      $url .=  '/' . $name;
+      $url .=  '/' . $self->branch if $self->branch;
+      $url .=  '/' . $self->subdir if $self->subdir;
+      $url .=  '@' . $self->pegrev if $self->pegrev;
+
+      $self->url_peg ($url);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  my $name = $self->{PROJECT};
+  $name =~ s#^.*/([^/]+)$#$1# if $name;
+
+  return $name;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $url = $cm_url->branch_url_peg ();
+#   $cm_url->branch_url_peg ($url);
+#
+# DESCRIPTION
+#   The method returns the URL@PEG of the "branch" part of the current URL. If
+#   an argument is specified, the URL@PEG of the "branch" part of the current
+#   URL is re-set.
+# ------------------------------------------------------------------------------
+
+sub branch_url_peg {
+  my $self = shift;
+
+  if (@_) {
+    my $url = shift;
+
+    # Re-construct URL is necessary
+    if (! $self->branch_url_peg or $url ne $self->branch_url_peg) {
+      my $pegrev = ($url =~ s/@($rev_pattern)$//i) ? $1 : '';
+
+      $url .= '/' . $self->subdir if $self->subdir;
+      $url .= '@' . $pegrev       if $pegrev;
+
+      $self->url_peg ($url);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return $self->project_url . '/' . $self->branch .
+         ($self->pegrev ? '@' . $self->pegrev : '');
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $url = $cm_url->branch_url ();
+#   $cm_url->branch_url ($url);
+#
+# DESCRIPTION
+#   The method returns the URL of the "branch" part of the current URL. If an
+#   argument is specified, the URL of the "branch" part of the current URL is
+#   re-set.
+# ------------------------------------------------------------------------------
+
+sub branch_url {
+  my $self = shift;
+
+  if (@_) {
+    my $url = shift;
+    $url =~ s/@($rev_pattern)$//i;
+
+    # Re-construct URL is necessary
+    if (! $self->branch_url or $url ne $self->branch_url) {
+      $url .= '/' . $self->subdir if $self->subdir;
+
+      $self->url ($url);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return $self->project_url . '/' . $self->branch;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $path = $cm_url->branch_path ();
+#   $cm_url->branch_path ($path);
+#
+# DESCRIPTION
+#   The method returns the path of the "branch" part of the current URL. If an
+#   argument is specified, the path of the "branch" part of the current URL is
+#   re-set.
+# ------------------------------------------------------------------------------
+
+sub branch_path {
+  my $self = shift;
+
+  if (@_) {
+    my $path = shift;
+
+    # Re-construct URL is necessary
+    if (! $self->branch_path or $path ne $self->branch_path) {
+      $path .= '/' . $self->subdir if $self->subdir;
+
+      $self->path ($path);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return $self->project_path . '/' . $self->branch;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $branch = $cm_url->branch ();
+#   $cm_url->branch ($branch);
+#
+# DESCRIPTION
+#   The method returns the "branch" part of the current URL. If an argument is
+#   specified, the "branch" part of the current URL is re-set.
+# ------------------------------------------------------------------------------
+
+sub branch {
+  my $self = shift;
+
+  if (@_) {
+    my $branch = shift;
+
+    # Re-construct URL is necessary
+    if (! $self->branch or $branch ne $self->branch) {
+      my $url = $self->project_url;
+      $url   .= '/' . $branch;
+      $url   .= '/' . $self->subdir if $self->subdir;
+
+      $self->url ($url);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return $self->{BRANCH};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $cm_url->is_trunk ();
+#
+# DESCRIPTION
+#   The method returns true if the the current URL is (a sub-tree of) the trunk.
+# ------------------------------------------------------------------------------
+
+sub is_trunk {
+  my $self = shift;
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return ($self->branch and $self->branch eq 'trunk');
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $cm_url->is_branch ();
+#
+# DESCRIPTION
+#   The method returns true if the the current URL is (a sub-tree of) a branch.
+# ------------------------------------------------------------------------------
+
+sub is_branch {
+  my $self = shift;
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return ($self->branch and $self->branch =~ m#^branches/#);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $cm_url->is_tag ();
+#
+# DESCRIPTION
+#   The method returns true if the the current URL is (a sub-tree of) a tag.
+# ------------------------------------------------------------------------------
+
+sub is_tag {
+  my $self = shift;
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return ($self->branch and $self->branch =~ m#^tags/#);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $subdir = $cm_url->subdir ();
+#   $cm_url->subdir ($subdir);
+#
+# DESCRIPTION
+#   The method returns the "subdir" part of the current URL. If an argument is
+#   specified, the "subdir" part of the current URL is re-set.
+# ------------------------------------------------------------------------------
+
+sub subdir {
+  my $self = shift;
+
+  if (@_) {
+    my $subdir = shift;
+
+    # Re-construct URL is necessary
+    if (! $self->subdir or $subdir ne $self->subdir) {
+      my $url = $self->project_url;
+      $url   .= '/' . $self->branch if $self->branch;
+      $url   .= '/' . $subdir if $subdir;
+
+      $self->url ($url);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return $self->{SUBDIR};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $url = $cm_url->url ();
+#   $cm_url->url ($url);
+#
+# DESCRIPTION
+#   The method returns the URL without the "peg revision" part. If an argument
+#   is specified, the URL is re-set without modifying the "peg revision" part.
+# ------------------------------------------------------------------------------
+
+sub url {
+  my $self = shift;
+
+  if (@_) {
+    my $url = shift;
+    $url    =~ s/@($rev_pattern)$//i;
+
+    # Re-construct URL if necessary
+    if (! $self->url or $url ne $self->url) {
+      $self->url_peg ($url . ($self->pegrev ? '@' . $self->pegrev : ''));
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  (my $url = $self->url_peg) =~ s/@($rev_pattern)$//i;
+
+  return $url;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $path = $cm_url->path ();
+#   $cm_url->path ($path);
+#
+# DESCRIPTION
+#   The method returns the "path" part of the URL (i.e. URL without the
+#   "root" part). If an argument is specified, the "path" part of the URL is
+#   re-set.
+# ------------------------------------------------------------------------------
+
+sub path {
+  my $self = shift;
+
+  # Repository root
+  my $root = $self->root;
+  $root    = substr (
+    $self->project_url,
+    0,
+    length ($self->project_url) - length ($self->project) - 1
+  ) if not $root;
+
+  if (@_) {
+    my $path = shift;
+    $path    =~ s/@($rev_pattern)$//i;
+
+    # Re-construct URL is necessary
+    if (! $self->path or $path ne $self->path) {
+      my $url = ($root . (substr ($path, 0, 1) eq '/' ? '' : '/') . $path);
+      $self->url ($url);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return substr ($self->url, length ($root));
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $path = $cm_url->path_peg ();
+#   $cm_url->path_peg ($path);
+#
+# DESCRIPTION
+#   The method returns the PATH@PEG part of the URL (i.e. URL without the
+#   "root" part). If an argument is specified, the PATH@PEG part of the URL is
+#   re-set.
+# ------------------------------------------------------------------------------
+
+sub path_peg {
+  my $self = shift;
+
+  # Repository root
+  my $root = $self->root;
+  $root    = substr (
+    $self->project_url,
+    0,
+    length ($self->project_url) - length ($self->project) - 1
+  ) if not $root;
+
+  if (@_) {
+    my $path = shift;
+
+    # Re-construct URL is necessary
+    if (! $self->path_peg or $path ne $self->path_peg) {
+      my $url = ($root . (substr ($path, 0, 1) eq '/' ? '' : '/') . $path);
+      $self->url_peg ($url);
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return substr ($self->url_peg, length ($root));
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rev = $cm_url->pegrev ();
+#   $cm_url->pegrev ($rev);
+#
+# DESCRIPTION
+#   The method returns the "peg revision" part of the current URL. If an
+#   argument is specified, the "peg revision" part of the current URL is
+#   re-set.
+# ------------------------------------------------------------------------------
+
+sub pegrev {
+  my $self = shift;
+
+  if (@_) {
+    my $pegrev = shift;
+
+    # Re-construct URL is necessary
+    if (! $self->pegrev or $pegrev ne $self->pegrev) {
+      $self->url_peg ($self->url . ($pegrev ? '@' . $pegrev : ''));
+    }
+  }
+
+  $self->_analyse_url () if not $self->{ANALYSED};
+
+  return $self->{PEGREV};
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/lib/Fcm/Config.pm
===================================================================
--- LMDZ5/branches/testing/tools/fcm/lib/Fcm/Config.pm	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/lib/Fcm/Config.pm	(revision 1665)
@@ -0,0 +1,735 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::Config
+#
+# DESCRIPTION
+#   This is a class for reading and processing central and user configuration
+#   settings for FCM.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::Config;
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Standard modules
+use File::Basename;
+use File::Spec::Functions;
+use FindBin;
+use POSIX qw/setlocale LC_ALL/;
+
+# FCM component modules
+use Fcm::CfgFile;
+
+# Other declarations:
+sub _get_hash_value;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = Fcm::Config->new (VERBOSE => $verbose);
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::Config class.
+#
+# ARGUMENTS
+#   VERBOSE - Set the verbose level of diagnostic output
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  # Ensure that all subsequent Subversion output is in UK English
+  if (setlocale (LC_ALL, 'en_GB')) {
+    $ENV{LANG} = 'en_GB';
+  }
+
+  # Location of the central/user configuration file
+  my $cntl_config = catfile (dirname ($FindBin::Bin), 'etc', 'fcm.cfg');
+  $cntl_config    = catfile $FindBin::Bin, 'fcm.cfg' unless -r $cntl_config;
+  my $user_config = exists $ENV{HOME} ? catfile $ENV{HOME}, '.fcm' : '';
+
+  # Verbose mode
+  my $verbose     = exists $ENV{FCM_VERBOSE} ? $ENV{FCM_VERBOSE} : 1;
+
+  my $self = {
+    CNTL_CONFIG => -r $cntl_config ? $cntl_config : '',
+    USER_CONFIG => -r $user_config ? $user_config : '',
+    VERBOSE     => exists $args{VERBOSE} ? $args{VERBOSE} : $verbose,
+    VARIABLE    => {},
+
+    # Primary settings
+    SETTING => {
+      # Release identifier/version
+      RELEASE  => '1.2',
+
+      # Location of file with the last changed revision of the FCM trunk
+      REV_FILE => catfile (dirname ($FindBin::Bin), 'etc', 'fcm_rev'),
+
+      # Default names of known FCM configuration files
+      CFG_NAME => {
+        BLD        => 'bld.cfg',      # bld cfg
+        EXT        => 'ext.cfg',      # ext cfg
+        SRCPACKAGE => '@PACKAGE.cfg', # source package cfg
+      },
+
+      # Latest version of known FCM configuration files
+      CFG_VERSION => {
+        BLD        => '1.0', # bld cfg
+        EXT        => '1.0', # ext cfg
+        SRCPACKAGE => '1.0', # source package cfg
+      },
+
+      # Labels for all types of FCM configuration files
+      CFG_LABEL => {
+        CFGFILE => {
+          TYPE    => 'CFG::TYPE',       # config file type
+          VERSION => 'CFG::VERSION',    # version of config file syntax
+        },
+
+        # Labels for central/user internal config setting
+        SETTING    => 'SET',
+
+        # Labels for ext and bld cfg
+        USE        => 'USE',            # use (inherit from) another ext/bld
+        SRCDIR     => 'SRC',            # prefix, source directory
+
+        # Labels for bld and pck cfg
+        TARGET     => 'TARGET',         # BLD: targets of current build
+                                        # PCK: target name of source file
+
+        # Labels for bld cfg
+        NAME        => 'NAME',          # build name
+        DIR         => 'DIR',           # prefix, build directory
+        PP          => 'PP',            # prefix, pre-process?
+        LIB         => 'LIB',           # declare name of a library
+        SEARCH_SRC  => 'SEARCH_SRC',    # search src/ sub-directory?
+        EXE_NAME    => 'EXE_NAME',      # rename a main program target
+        TOOL        => 'TOOL',          # prefix, build tool
+        INHERIT     => 'INHERIT',       # prefix, inheritance flag
+        EXCL_DEP    => 'EXCL_DEP',      # exclude these automatic dependencies
+        INFILE_EXT  => 'INFILE_EXT',    # input file name extension and type
+        OUTFILE_EXT => 'OUTFILE_EXT',   # output file type and name extension
+        EXE_DEP     => 'EXE_DEP',       # extra executable dependencies
+        BLOCKDATA   => 'BLOCKDATA',     # BLOCKDATA dependencies
+
+        # Labels for ext cfg
+        DEST       => {                 # local extract destinations
+          ROOTDIR  => 'DEST::ROOTDIR',  # top directory for this extract
+          SRCDIR   => 'DEST::SRCDIR',   # extracted source directory
+          CFGDIR   => 'DEST::CFGDIR',   # generated configuration directory
+          CACHEDIR => 'DEST::CACHEDIR', # cache directory for fast extract
+          BLD_CFG  => 'DEST::BLD_CFG',  # generated bld cfg file
+          EXT_CFG  => 'DEST::EXT_CFG',  # generated ext cfg file
+        },
+        RDEST      => {                 # remote extract destionations
+          MACHINE  => 'RDEST::MACHINE', # name of remote machine
+          LOGNAME  => 'RDEST::LOGNAME', # user logname on remote machine
+          ROOTDIR  => 'RDEST::ROOTDIR', # top directory for this extract
+          SRCDIR   => 'RDEST::SRCDIR',  # extracted source directory
+          CFGDIR   => 'RDEST::CFGDIR',  # generated configuration directory
+          BLD_CFG  => 'RDEST::BLD_CFG', # generated bld cfg file
+          EXT_CFG  => 'RDEST::EXT_CFG', # generated ext cfg file
+        },
+        INC        => 'INC',            # "include" settings in another cfg file
+        BDECLARE   => 'BLD',            # declare entries for build system
+        OVERRIDE   => 'OVERRIDE',       # set conflict override option
+        REPOS      => 'REPOS',          # set repos loc for a project branch
+        VERSION    => 'VERSION',        # set version for a project branch
+        EXPSRCDIR  => 'EXPSRC',         # prefix, expandable source directory
+        MIRROR     => 'MIRROR',         # mirror tool
+
+        # Labels for pck cfg
+        TYPE       => 'TYPE',           # type of source file/build task
+        SCAN       => 'SCAN',           # scan source file for dependency
+        INTNAME    => 'INTNAME',        # internal name of source file
+        DEP        => 'DEP',            # source file/build task dependencies
+      },
+
+      # Keywords in known FCM configuration files
+      CFG_KEYWORD => 'USE,INC,TARGET,EXCL_DEP',
+
+      # Types of "inc" statements expandable CFG files
+      CFG_EXP_INC => 'BLD,EXT,FCM',
+
+      # Standard sub-directories for extract/build
+      DIR => {
+        BIN    => 'bin',    # executable
+        BLD    => 'bld',    # build
+        CACHE  => '.cache', # cache
+        CFG    => 'cfg',    # configuration
+        DONE   => 'done',   # "done"
+        ETC    => 'etc',    # miscellaneous items
+        FLAGS  => 'flags',  # "flags"
+        INC    => 'inc',    # include
+        LIB    => 'lib',    # library
+        OBJ    => 'obj',    # object
+        PPSRC  => 'ppsrc',  # pre-processed source
+        SRC    => 'src',    # source
+        TMP    => 'tmp',    # temporary directory
+      },
+
+      # Build commands and options (i.e. tools)
+      TOOL => {
+        SHELL        => '/usr/bin/ksh',    # Default shell
+
+        CPP          => 'cpp',             # C pre-processor
+        CPPFLAGS     => '-C',              # CPP flags
+        CPP_INCLUDE  => '-I',              # CPP flag, specify "include" path
+        CPP_DEFINE   => '-D',              # CPP flag, define macro
+        CPPKEYS      => '',                # CPP keys (definition macro)
+
+        CC           => 'cc',              # C compiler
+        CFLAGS       => '',                # CC flags
+        CC_COMPILE   => '-c',              # CC flag, compile only
+        CC_OUTPUT    => '-o',              # CC flag, specify output file name
+        CC_INCLUDE   => '-I',              # CC flag, specify "include" path
+        CC_DEFINE    => '-D',              # CC flag, define macro
+
+        FPP          => 'cpp',             # Fortran pre-processor
+        FPPFLAGS     => '-P -traditional', # FPP flags
+        FPP_INCLUDE  => '-I',              # FPP flag, specify "include" path
+        FPP_DEFINE   => '-D',              # FPP flag, define macro
+        FPPKEYS      => '',                # FPP keys (definition macro)
+
+        FC           => 'f90',             # Fortran compiler
+        FFLAGS       => '',                # FC flags
+        FC_COMPILE   => '-c',              # FC flag, compile only
+        FC_OUTPUT    => '-o',              # FC flag, specify output file name
+        FC_INCLUDE   => '-I',              # FC flag, specify "include" path
+        FC_DEFINE    => '-D',              # FC flag, define macro
+
+        LD           => 'ld',              # linker
+        LDFLAGS      => '',                # LD flags
+        LD_OUTPUT    => '-o',              # LD flag, specify output file name
+        LD_LIBSEARCH => '-L',              # LD flag, specify "library" path
+        LD_LIBLINK   => '-l',              # LD flag, specify link library
+
+        AR           => 'ar',              # library archiver
+        ARFLAGS      => 'rs',              # AR flags
+
+        MAKE         => 'make',            # make command
+        MAKEFLAGS    => '',                # make flags
+        MAKE_SILENT  => '-s',              # make flag, silent diagnostic
+        MAKE_JOB     => '-j',              # make flag, number of jobs
+
+        INTERFACE    => 'file',            # name interface after file/program
+        GENINTERFACE => 'ECMWF',           # Fortran 9x interface generator
+
+        MIRROR       => 'rsync',           # extract mirroring tool
+        REMOTE_SHELL => 'remsh',           # command to invoke the remote shell
+        GRAPHIC_DIFF => 'xxdiff',          # graphical diff tool
+      },
+
+      # List of tools that are local to FCM, (will not be exported to a Makefile)
+      LOCALTOOL => 'CPP,CPPFLAGS,CPP_INCLUDE,CPP_DEFINE,FPP,FPPFLAGS,' .
+                   'FPP_INCLUDE,FPP_DEFINE,GRAPHIC_DIFF,MAKE,MAKEFLAGS,' .
+                   'MAKE_SILENT,MAKE_JOB,INTERFACE,GENINTERFACE,MIRROR,' .
+                   'REMOTE_SHELL',
+
+      # Supported tools for compilable source
+      SRC_TOOL => {
+        FORTRAN => {
+          COMPILER => 'FC',
+          FLAGS    => 'FFLAGS',
+          OUTPUT   => 'FC_OUTPUT',
+          INCLUDE  => 'FC_INCLUDE',
+        },
+
+        FPP     => {
+          COMPILER => 'FC',
+          FLAGS    => 'FFLAGS',
+          PPKEYS   => 'FPPKEYS',
+          OUTPUT   => 'FC_OUTPUT',
+          INCLUDE  => 'FC_INCLUDE',
+          DEFINE   => 'FC_DEFINE',
+        },
+
+        C       => {
+          COMPILER => 'CC',
+          FLAGS    => 'CFLAGS',
+          PPKEYS   => 'CPPKEYS',
+          OUTPUT   => 'CC_OUTPUT',
+          INCLUDE  => 'CC_INCLUDE',
+          DEFINE   => 'CC_DEFINE',
+        },
+      },
+
+      # Cache file names/extensions
+      CACHE => {
+        EXTCONFIG   => '.config',       # ext cache, commit version info
+        PCKFILE     => '.pck_file',     # bld cache, source package list
+        PCKPPDEPEND => '.pck_ppdepend', # bld cache, source package PP dependency
+        PCKDEPEND   => '.pck_depend',   # bld cache, source package dependency
+        BLDTOOL     => '.bld_tool',     # bld cache, build tool list
+        PPOPTION    => '.bld_pp',       # bld cache, PP option
+        EXE_DEP     => '.exe_dep',      # bld cache, executable extra dependency
+      },
+
+      # Input file name extension and type
+      # (may overlap with output and vpath, see below)
+      INFILE_EXT => {
+        # General extensions
+        'f'    => 'FORTRAN::SOURCE',
+        'for'  => 'FORTRAN::SOURCE',
+        'ftn'  => 'FORTRAN::SOURCE',
+        'f77'  => 'FORTRAN::SOURCE',
+        'f90'  => 'FORTRAN::FORTRAN9X::SOURCE',
+        'f95'  => 'FORTRAN::FORTRAN9X::SOURCE',
+        'F'    => 'FPP::SOURCE',
+        'FOR'  => 'FPP::SOURCE',
+        'FTN'  => 'FPP::SOURCE',
+        'F77'  => 'FPP::SOURCE',
+        'F90'  => 'FPP::FPP9X::SOURCE',
+        'F95'  => 'FPP::FPP9X::SOURCE',
+        'c'    => 'C::SOURCE',
+        'cpp'  => 'C::C++::SOURCE',
+        'h'    => 'CPP::INCLUDE',
+        'o'    => 'BINARY::OBJ',
+        'obj'  => 'BINARY::OBJ',
+        'exe'  => 'BINARY::EXE',
+        'a'    => 'BINARY::LIB',
+        'sh'   => 'SHELL::SCRIPT',
+        'ksh'  => 'SHELL::SCRIPT',
+        'bash' => 'SHELL::SCRIPT',
+        'csh'  => 'SHELL::SCRIPT',
+        'pl'   => 'PERL::SCRIPT',
+        'pm'   => 'PERL::SCRIPT',
+        'py'   => 'PYTHON::SCRIPT',
+        'tcl'  => 'TCL::SCRIPT',
+        'pro'  => 'PVWAVE::SCRIPT',
+
+        # Local extensions
+        'cfg'       => 'CFGFILE',
+        'h90'       => 'CPP::INCLUDE',
+        'inc'       => 'FORTRAN::FORTRAN9X::INCLUDE',
+        'interface' => 'FORTRAN::FORTRAN9X::INCLUDE::INTERFACE',
+      },
+
+      # Input file name pattern and type
+      INFILE_PAT => {
+        '\w+Scr_\w+'              => 'SHELL::SCRIPT',
+        '\w+Comp_\w+'             => 'SHELL::SCRIPT::GENTASK',
+        '\w+(?:IF|Interface)_\w+' => 'SHELL::SCRIPT::GENIF',
+        '\w+Suite_\w+'            => 'SHELL::SCRIPT::GENSUITE',
+        '\w+List_\w+'             => 'SHELL::SCRIPT::GENLIST',
+        '\w+Sql_\w+'              => 'SCRIPT::SQL',
+      },
+
+      # Input text file pattern and type
+      INFILE_TXT => {
+        '(?:[ck]|ba)?sh'  => 'SHELL::SCRIPT',
+        'perl'            => 'PERL::SCRIPT',
+        'python'          => 'PYTHON::SCRIPT',
+        'tcl(?:sh)?|wish' => 'TCL::SCRIPT',
+      },
+
+      # Ignore input files matching the following names (comma-separated list)
+      INFILE_IGNORE => 'fcm_env.ksh',
+
+      # Output file type and extension
+      # (may overlap with input (above) and vpath (below))
+      OUTFILE_EXT => {
+        CFG       => '.cfg',       # FCM configuration file
+        DONE      => '.done',      # "done" files for compiled source
+        ETC       => '.etc',       # "etc" dummy file
+        EXE       => '.exe',       # binary executables
+        FLAGS     => '.flags',     # "flags" files, compiler flags config
+        IDONE     => '.idone',     # "done" files for included source
+        INTERFACE => '.interface', # interface for F90 subroutines/functions
+        LIB       => '.a',         # archive object library
+        MK        => '.mk',        # dependency files, Makefile fragments
+        MOD       => '.mod',       # compiled Fortran module information files
+        OBJ       => '.o',         # compiled object files
+        PDONE     => '.pdone',     # "done" files for pre-processed files
+        TAR       => '.tar',       # TAR archive
+      },
+
+      # VPATH, each value must be a comma separate list
+      # EMPTY      translates to %
+      # IN:<FLAG>  translates to any key in {INFILE_EXT} if the value contains
+      #            the word in <FLAG>
+      # OUT:<FLAG> translates to {OUTFILE_EXT}{<FLAG>}
+      VPATH   => {
+        BIN   => 'EMPTY,OUT:EXE,IN:SCRIPT',
+        BLD   => 'OUT:MK',
+        DONE  => 'OUT:DONE,OUT:IDONE,OUT:ETC',
+        FLAGS => 'OUT:FLAGS',
+        INC   => 'IN:INCLUDE',
+        LIB   => 'OUT:LIB',
+        OBJ   => 'OUT:OBJ',
+      },
+
+      # Dependency scan types for pre-processing
+      PP_DEP_TYPE => {
+        FPP => 'H',
+        CPP => 'H',
+        C   => 'H',
+      },
+
+      # Dependency scan types
+      DEP_TYPE => {
+        FORTRAN => 'USE::INTERFACE::INC::OBJ',
+        FPP     => 'USE::INTERFACE::INC::H::OBJ',
+        CPP     => 'H::OBJ',
+        C       => 'H::OBJ',
+        SCRIPT  => 'EXE',
+      },
+
+      # Dependency pattern for each type
+      DEP_PATTERN => {
+        H         => q/^#\s*include\s*['"](\S+)['"]/,
+        USE       => q/^\s*use\s+(\w+)/,
+        INTERFACE => q/^#?\s*include\s+['"](\S+##OUTFILE_EXT::INTERFACE##)['"]/,
+        INC       => q/^\s*include\s+['"](\S+)['"]/,
+        OBJ       => q#^\s*(?:/\*|!)\s*depends\s*on\s*:\s*(\S+)#,
+        EXE       => q/^\s*(?:#|;)\s*(?:calls|list|if|interface)\s*:\s*(\S+)/,
+      },
+
+      # Types that always need to be built
+      ALWAYS_BUILD_TYPE => 'PVWAVE,GENLIST,SQL',
+
+      # Types that cannot have duplicated targets
+      NO_DUPLICATED_TARGET_TYPE => '',
+
+      # Excluded dependency
+      EXCL_DEP => {
+        # Fortran intrinsic modules
+        'USE::ISO_C_BINDING'            => {'' => 1},
+        'USE::IEEE_EXCEPTIONS'          => {'' => 1},
+        'USE::IEEE_ARITHMETIC'          => {'' => 1},
+        'USE::IEEE_FEATURES'            => {'' => 1},
+
+        # Fortran intrinsic subroutines
+        'OBJ::CPU_TIME'                 => {'' => 1},
+        'OBJ::GET_COMMAND'              => {'' => 1},
+        'OBJ::GET_COMMAND_ARGUMENT'     => {'' => 1},
+        'OBJ::GET_ENVIRONMENT_VARIABLE' => {'' => 1},
+        'OBJ::MOVE_ALLOC'               => {'' => 1},
+        'OBJ::MVBITS'                   => {'' => 1},
+        'OBJ::RANDOM_NUMBER'            => {'' => 1},
+        'OBJ::RANDOM_SEED'              => {'' => 1},
+        'OBJ::SYSTEM_CLOCK'             => {'' => 1},
+
+        # Dummy statements
+        'OBJ::NONE'                     => {'' => 1},
+        'EXE::NONE'                     => {'' => 1},
+      },
+
+      # Extra executable dependencies
+      EXE_DEP => {},
+
+      # Fortran BLOCKDATA dependencies
+      BLOCKDATA => {},
+
+      # Rename main program targets
+      EXE_NAME => {},
+
+      # Build sub-directories that can be archived by "tar"
+      TAR_DIRS => 'BLD,CACHE,DONE,FLAGS,INC,PPSRC,OBJ',
+
+      # Misc
+      MISC => {
+        CPDUMMY       => '$(FCM_DONEDIR)/FCM_CP.dummy',
+                                         # build system "copy" dummy target
+        DIR_SEPARATOR => '/',            # repository directory separator
+        EXPURL_PREFIX => 'fcm:',         # expandable URL keyword prefix
+        LOCK_BLD      => 'fcm.bld.lock', # build lock file
+        LOCK_EXT      => 'fcm.ext.lock', # extract lock file
+        MAKEFILE      => 'Makefile',     # name of Makefile
+        RUN_ENV_SH    => 'fcm_env.ksh',  # bld runtime environment shell script
+        WEB_BROWSER   => 'firefox',      # web browser
+      },
+
+      # URL, revision, and Trac URL keywords
+      URL      => {},
+      REVISION => {},
+      TRAC     => {},
+    },
+  };
+
+  # Backward compatibility: the REPOS setting is equivalent to the URL setting
+  $self->{SETTING}{REPOS} = $self->{SETTING}{URL};
+
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $file = $config->central_config ();
+#   $config->central_config ($file);
+#
+# DESCRIPTION
+#   This method returns the path name of the central configuration file. If an
+#   argument $file is specified, the path name of the central configuration
+#   file is set to its value.
+# ------------------------------------------------------------------------------
+
+sub central_config {
+  my $self = shift;
+
+  if (@_) {
+    $self->{CNTL_CONFIG} = $_[0];
+  }
+
+  return $self->{CNTL_CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $file = $config->user_config ();
+#   $config->user_config ($file);
+#
+# DESCRIPTION
+#   This method returns the path name of the user configuration file. If an
+#   argument $file is specified, the path name of the user configuration file
+#   is set to its value.
+# ------------------------------------------------------------------------------
+
+sub user_config {
+  my $self = shift;
+
+  if (@_) {
+    $self->{USER_CONFIG} = $_[0];
+  }
+
+  return $self->{USER_CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $mode = $config->verbose ();
+#   $config->verbose ($mode);
+#
+# DESCRIPTION
+#   This method returns the diagnostic verbose level. If an argument $mode is
+#   specified, the diagnostic verbose level is set to its value.
+# ------------------------------------------------------------------------------
+
+sub verbose {
+  my $self = shift;
+
+  if (@_) {
+    $self->{VERBOSE} = $_[0];
+  }
+
+  return $self->{VERBOSE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $setting = $config->setting (arg, [...]);
+#
+# DESCRIPTION
+#   This method returns an item under the SETTING hash table. The depth within
+#   the hash table is given by the list of arguments, which should match with
+#   the keys in the multi-dimension SETTING hash table.
+# ------------------------------------------------------------------------------
+
+sub setting {
+  my $self = shift;
+
+  if (@_) {
+    my $label   = shift;
+    my $setting = $self->{SETTING};
+    return _get_hash_value ($setting->{$label}, @_) if exists $setting->{$label};
+  }
+
+  return undef;
+
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config->assign_setting (
+#     LABELS => \@labels, # setting labels
+#     VALUE  => $value,   # setting value
+#   );
+#
+# DESCRIPTION
+#   This method assigns a VALUE to a SETTING specified by the names in LABEL.
+# ------------------------------------------------------------------------------
+
+sub assign_setting {
+  my $self = shift;
+  my %args = @_;
+
+  my @labels = exists $args{LABELS} ? @{ $args{LABELS} } : ();
+  my $value  = exists $args{VALUE}  ? $args{VALUE}       : undef;
+
+  my $setting = $self->{SETTING};
+  while (defined (my $label = shift @labels)) {
+    if (exists $setting->{$label}) {
+      if (ref $setting->{$label}) {
+        $setting = $setting->{$label};
+
+      } else {
+        $setting->{$label} = $value;
+        last;
+      }
+
+    } else {
+      if (@labels) {
+        $setting->{$label} = {};
+        $setting           = $setting->{$label};
+
+      } else {
+        $setting->{$label} = $value;
+      }
+    }
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $variable = $config->variable ([arg]);
+#
+# DESCRIPTION
+#   If arg is set, this method returns the value of a variable named arg. If
+#   arg is not set, this method returns the VARIABLE hash.
+# ------------------------------------------------------------------------------
+
+sub variable {
+  my $self     = shift;
+
+  my $variable = $self->{VARIABLE};
+
+  if (@_) {
+    my $label   = shift;
+    return exists $variable->{$label} ? $variable->{$label} : undef;
+
+  } else {
+    return %{ $variable };
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config->assign_variable (
+#     LABEL => $label, # variable label
+#     VALUE => $value, # variable value
+#   );
+#
+# DESCRIPTION
+#   This method assigns a VALUE to a VARIABLE named by LABEL.
+# ------------------------------------------------------------------------------
+
+sub assign_variable {
+  my $self = shift;
+  my %args = @_;
+
+  my $label = exists $args{LABEL} ? $args{LABEL} : undef;
+  my $value = exists $args{VALUE} ? $args{VALUE} : undef;
+
+  if ($label) {
+    $self->{VARIABLE}{$label} = $value;
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config->get_config ();
+#
+# DESCRIPTION
+#   This method reads the configuration settings from the central and the user
+#   configuration files.
+# ------------------------------------------------------------------------------
+
+sub get_config {
+  my $self = shift;
+
+  $self->_read_config_file ($self->{CNTL_CONFIG}) if $self->{CNTL_CONFIG};  
+  $self->_read_config_file ($self->{USER_CONFIG}) if $self->{USER_CONFIG};
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config->_read_config_file ();
+#
+# DESCRIPTION
+#   This internal method reads a configuration file and assign values to the
+#   attributes of the current instance.
+# ------------------------------------------------------------------------------
+
+sub _read_config_file {
+  my $self        = shift;
+  my $config_file = $_[0];
+
+  return undef unless -r $config_file;
+
+  my $cfgfile = Fcm::CfgFile->new (SRC => $config_file, TYPE => 'FCM');
+  $cfgfile->read_cfg ();
+  my @lines = $cfgfile->lines ();
+
+  LINE: for my $line (@lines) {
+    my $label = $line->{LABEL};
+    my $value = $line->{VALUE};
+
+    next unless $label;
+
+    # "Environment variables" start with $
+    if ($label =~ s/^\$([A-Za-z_]\w*)$/$1/) {
+      $ENV{$label} = $value;
+      next LINE;
+    }
+
+    # "Settings variables" start with "set::"
+    my @tags = map {uc $_} split (/::/, $label);
+    if ($tags[0] eq uc $self->{SETTING}{CFG_LABEL}{SETTING}) {
+      shift @tags;
+      $self->assign_setting (LABELS => \@tags, VALUE => $value);
+      next LINE;
+    }
+
+    # Not a standard setting variable, put in internal variable list
+    $label =~ s/^\%//;
+    $self->assign_variable (LABEL => $label, VALUE => $value);
+  }
+
+  1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ref = _get_hash_value (arg1, arg2, ...);
+#
+# DESCRIPTION
+#   This internal method recursively gets a value from a multi-dimensional
+#   hash.
+# ------------------------------------------------------------------------------
+
+sub _get_hash_value {
+  my $value = shift;
+
+  while (defined (my $arg = shift)) {
+    if (exists $value->{$arg}) {
+      $value = $value->{$arg};
+
+    } else {
+      return undef;
+    }
+  }
+
+  return $value;
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/lib/Fcm/Extract.pm
===================================================================
--- LMDZ5/branches/testing/tools/fcm/lib/Fcm/Extract.pm	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/lib/Fcm/Extract.pm	(revision 1665)
@@ -0,0 +1,1768 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::Extract
+#
+# DESCRIPTION
+#   This class contains methods for carrying out the various tasks that are
+#   required to extract code from the FCM Subversion repository for feeding
+#   into the prototype build system. At the end of the extract, it writes a
+#   build configuration file for feeding into the build system.  If the code
+#   is to be built on a remote machine, it is mirrored to the remote machine
+#   using a "rdist" or "rsync" interface.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::Extract;
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Standard modules
+use Carp;
+use File::Spec;
+use File::Spec::Functions;
+use File::Basename;
+use File::Path;
+use File::Compare;
+
+# FCM component modules
+use Fcm::CfgFile;
+use Fcm::ReposBranch;
+use Fcm::SrcDirLayer;
+use Fcm::Util;
+use Fcm::Timer;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ext = Fcm::Extract->new (
+#     CONFIG    => $config,
+#     CFG_SRC   => $cfg_src,
+#     EXTRACTED => $extracted,
+#   );
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::Extract class.
+#
+# ARGUMENTS
+#   CONFIG     - reference to a Fcm::Config instance
+#   CFG_SRC    - source path to the extract configuration file
+#   EXTRACTED  - is it a pre-extracted object?
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $cfg       = exists $args{CFG_SRC}   ? $args{CFG_SRC}   : undef;
+  my $extracted = exists $args{EXTRACTED} ? $args{EXTRACTED} : undef;
+  my $config    = exists $args{CONFIG}    ? $args{CONFIG}    : &main::cfg;
+
+  my $self = {
+    CONFIG     => $config,            # configuration settings
+    CFG        => Fcm::CfgFile->new ( # ext cfg for this extract
+      SRC      => $cfg,               # source path of the config file
+      TYPE     => 'ext',              # config file type
+      CONFIG   => $config,            # configuration settings
+    ),
+    DEST       => {                   # destination info for this extract
+      ROOTDIR  => undef,              # destination root directory
+      CACHEDIR => undef,              # extract cache directory
+      CFGDIR   => undef,              # destination configuration directory
+      SRCDIR   => undef,              # destination source directory
+      BLD_CFG  => undef,              # bld cfg for the build system
+      EXT_CFG  => undef,              # ext cfg for subsequent extract
+    },
+    RDEST      => {                   # remote destination information
+      MACHINE  => undef,              # destination machine
+      LOGNAME  => undef,              # remote login name
+      ROOTDIR  => undef,              # destination root directory
+      CFGDIR   => undef,              # destination configuration directory
+      SRCDIR   => undef,              # destination source directory
+      BLD_CFG  => undef,              # bld cfg for the build system
+      EXT_CFG  => undef,              # ext cfg for subsequent extract
+    },
+    BDECLARE   => [],                 # list of declared bld cfg entries
+    OVERRIDE   => 0,                  # override conflicting patches?
+    EXTRACTED  => $extracted,         # is the current object pre-extracted?
+    USE        => [],                 # list of re-used extracts
+    BRANCHES   => [],                 # list of repository branch info
+    SRCDIRS    => {},                 # list of source directory extract info
+    LOCK       => undef,              # lock file
+  };
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->DESTROY;
+#
+# DESCRIPTION
+#   This method is called automatically when a Fcm::Extract object is
+#   destroyed.
+# ------------------------------------------------------------------------------
+
+sub DESTROY {
+  my $self = shift;
+
+  # Remove the lock if it is set
+  unlink $self->{LOCK} if $self->{LOCK} and -e $self->{LOCK};
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = $ext->config;
+#
+# DESCRIPTION
+#   This method returns a reference to the Fcm::Config instance.
+# ------------------------------------------------------------------------------
+
+sub config {
+  my $self = shift;
+
+  return $self->{CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfgfile = $ext->cfg;
+#   $ext->cfg ($cfgfile);
+#
+# DESCRIPTION
+#   This method returns a reference to a Fcm::CfgFile instance for the extract
+#   configuration file.
+# ------------------------------------------------------------------------------
+
+sub cfg {
+  my $self = shift;
+
+  return $self->{CFG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $dest = $ext->dest ([$name]);
+#
+# DESCRIPTION
+#   This method returns a hash containing the extract destination information
+#   (local) if no argument is specified. If $name is specified, it returns the
+#   named hash element if it exists.
+# ------------------------------------------------------------------------------
+
+sub dest {
+  my $self = shift;
+
+  if (@_) {
+    my $name = shift;
+    $name    = uc $name;
+
+    if (exists $self->{DEST}{$name}) {
+      return $self->{DEST}{$name};
+    }
+  }
+
+  return %{ $self->{DEST} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rdest = $ext->rdest ([$name]);
+#
+# DESCRIPTION
+#   This method returns a hash containing the extract destination information
+#   (remote) if no argument is specified. If $name is specified, it returns the
+#   named hash element if it exists.
+# ------------------------------------------------------------------------------
+
+sub rdest {
+  my $self = shift;
+
+  if (@_) {
+    my $name = shift;
+    $name    = uc $name;
+
+    if (exists $self->{RDEST}{$name}) {
+      return $self->{RDEST}{$name};
+    }
+  }
+
+  return %{ $self->{RDEST} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @bdeclare = $ext->bdeclare ();
+#
+# DESCRIPTION
+#   This method returns a list containing the build configuration file entries.
+# ------------------------------------------------------------------------------
+
+sub bdeclare {
+  my $self = shift;
+
+  return @{ $self->{BDECLARE} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @branches = $ext->branches ([$index]);
+#
+# DESCRIPTION
+#   This method returns a list of references to Fcm::ReposBranch instances. If
+#   $index is specified, it returns the numbered item in the list.
+# ------------------------------------------------------------------------------
+
+sub branches {
+  my $self = shift;
+
+  if (@_) {
+    my $index = $_[0];
+    return exists $self->{BRANCHES}[$index] ? $self->{BRANCHES}[$index] : undef;
+  }
+
+  return @{ $self->{BRANCHES} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   %srcdirs = $ext->srcdirs ([$name]);
+#
+# DESCRIPTION
+#   This method returns a hash of source directories to be processed by this
+#   extract. If $name is specified, a named element of the hash is returned
+#   instead.
+# ------------------------------------------------------------------------------
+
+sub srcdirs {
+  my $self = shift;
+
+  if (@_) {
+    my $name = shift;
+    $name    = uc $name;
+
+    return exists $self->{SRCDIRS}{$name} ? $self->{SRCDIRS}{$name} : undef;
+  }
+
+  return %{ $self->{SRCDIRS} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = $ext->extract ([FULL => 1], [IGNORE_LOCK => 1]);
+#
+# DESCRIPTION
+#   This is the main class method. It performs an extract using the current
+#   configuration. If FULL is set to true, it runs in full mode. Otherwise, it
+#   runs in incremental mode. If IGNORE_LOCK is set to true, it ignores any lock
+#   files that may exist in the extract destination root directory.
+# ------------------------------------------------------------------------------
+
+sub extract {
+  my $self = shift;
+  my %args = @_;
+
+  my $full        = exists $args{FULL}        ? $args{FULL}        : 0;
+  my $ignore_lock = exists $args{IGNORE_LOCK} ? $args{IGNORE_LOCK} : 0;
+
+  my $verbose = $self->config->verbose;
+
+  my $date = localtime;
+  print 'Extract started on ', $date, '.', "\n" if $verbose;
+  my $otime = time;
+
+  my $rc;
+  $rc = $self->decipher_cfg;
+
+  print '->Extract: start', "\n" if $verbose;
+  my $stime = time;
+
+  $rc = $self->check_dest               if $rc;
+  $rc = $self->check_lock               if $rc and not $ignore_lock;
+  $rc = $self->_set_lock                if $rc;
+  $rc = $self->expand_cfg               if $rc;
+  $rc = $self->_create_dest_dir ($full) if $rc;
+  $rc = $self->create_dir_stack         if $rc;
+  $rc = $self->_extract_src             if $rc;
+
+  $rc = $self->_sort_bdeclare if $rc;
+  $rc = $self->_write_ext_cfg if $rc;
+  $rc = $self->_write_bld_cfg if $rc;
+
+  my $ftime = time;
+  my $s_str = $ftime - $stime > 1 ? 'seconds' : 'second';
+  print '->Extract: ', $ftime - $stime, ' ', $s_str, "\n";
+
+  if ($rc and $self->{RDEST}{MACHINE}) {
+    print '->Mirror : start', "\n" if $verbose;
+    $stime = time;
+    $rc = $self->_mirror_extract;
+    $ftime = time;
+    $s_str = $ftime - $stime > 1 ? 'seconds' : 'second';
+    print '->Mirror : ', $ftime - $stime, ' ', $s_str, "\n";
+  }
+
+  if ($verbose) {
+    $s_str = $ftime - $otime > 1 ? 'seconds' : 'second';
+    print '->TOTAL  : ', $ftime - $otime, ' ', $s_str, "\n";
+  }
+
+  $date = localtime;
+  if ($rc) {
+    print 'Extract command finished on ', $date, '.', "\n" if $verbose;
+
+  } else {
+    e_report 'Extract command failed on ', $date, '.';
+  }
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ext->decipher_cfg ();
+#
+# DESCRIPTION
+#   This method deciphers the extract configuration file.
+# ------------------------------------------------------------------------------
+
+sub decipher_cfg {
+  my $self = shift;
+
+  return unless $self->cfg->src;
+
+  # Read config file
+  my $read = $self->cfg->read_cfg;
+
+  # Check config file type
+  if ($read) {
+    if ($self->cfg->type ne 'ext') {
+      w_report 'Error: ', $self->cfg->src, ': not an extract config file';
+      return;
+    }
+
+  } else {
+    return;
+  }
+
+  my %cfg_labels = %{ $self->config->setting ('CFG_LABEL') };
+
+  # Extract information from each line of the config file
+  my @lines    = $self->cfg->lines;
+  LINE: for my $line (@lines) {
+    my $label = $line->{LABEL};
+    my $value = $line->{VALUE};
+
+    next LINE unless $label;
+
+    # Configuration file type/version, ignore
+    for my $my_label (keys %{ $cfg_labels{CFGFILE} }) {
+      next LINE if uc ($label) eq uc ($cfg_labels{CFGFILE}{$my_label});
+    }
+
+    # Include another file, processed already, ignore this line
+    next LINE if uc ($label) eq $cfg_labels{INC};
+
+    # User variable, ignore
+    next LINE if index (uc ($label), '%') == 0;
+
+    # Local destination directories, config file, etc
+    for my $my_label (keys %{ $cfg_labels{DEST} }) {
+      if (uc ($label) eq uc ($cfg_labels{DEST}{$my_label})) {
+        $self->{DEST}{$my_label} = &expand_tilde ($value);
+        next LINE;
+      }
+    }
+
+    # Remote machine, logname, destination directories, config file, etc
+    for my $my_label (keys %{ $cfg_labels{RDEST} }) {
+      if (uc ($label) eq uc ($cfg_labels{RDEST}{$my_label})) {
+        $self->{RDEST}{$my_label} = $value;
+        next LINE;
+      }
+    }
+
+    # "USE" statements
+    if (uc ($label) eq uc ($cfg_labels{USE})) {
+      my $exists = grep {$_->cfg->src eq $value} @{ $self->{USE} };
+
+      # Initialise new Fcm::Extract object if not already exists
+      unless ($exists) {
+        my $extract = Fcm::Extract->new (
+          CONFIG    => $self->config,
+          CFG_SRC   => expand_tilde ($value),
+          EXTRACTED => 1,
+        );
+
+        $extract->decipher_cfg;
+        $extract->check_dest;
+        $extract->expand_cfg ();
+        push @{ $self->{USE} }, $extract;
+      }
+      next LINE;
+    }
+
+    # "Override" setting
+    if (uc ($label) eq uc ($cfg_labels{OVERRIDE})) {
+      $self->{OVERRIDE} = $value;
+      next LINE;
+    }
+
+    # "Mirror" command
+    if (uc ($label) eq uc ($cfg_labels{MIRROR})) {
+      $self->config->assign_setting (
+        LABELS => [qw/TOOL MIRROR/],
+        VALUE  => $value,
+      );
+      next LINE;
+    }
+
+    # Declared bld cfg entries
+    {
+      my $prefix = $cfg_labels{BDECLARE} . '::';
+
+      if (index (uc ($label), $prefix) == 0) {
+        my $name = substr $label, length ($prefix);
+
+        if ($name) {
+          push @{ $self->{BDECLARE} }, {LABEL => $name, VALUE => $value,};
+          next LINE;
+        }
+      }
+    }
+
+    # Repository, version and source directories
+    for my $my_label (qw/REPOS VERSION SRCDIR EXPSRCDIR/) {
+      my $prefix  = $cfg_labels{$my_label} . '::';
+
+      if (index (uc ($label), $prefix) == 0) {
+        my $name    = substr $label, length ($prefix);
+
+        # Detemine package and tag
+        my @names   = split /::/, $name;
+        my $tag     = pop @names;
+        my $pckroot = $names[0];
+        my $pck     = join '::', @names;
+
+        # Check that $tag and $pckroot are defined
+        last if not $tag;
+        last if not $pckroot;
+
+        # Check whether branch already exists
+        my @branches = grep {
+          $_->package eq $pckroot and $_->tag eq $tag
+        } @{ $self->{BRANCHES} };
+
+        my $branch   = undef;
+
+        if (@branches) { # If so, set $branch to point to existing branch
+          $branch = shift @branches;
+
+        } else {         # If not, create new branch
+          $branch = Fcm::ReposBranch->new (
+            CONFIG  => $self->config,
+            PACKAGE => $pckroot,
+            TAG     => $tag,
+          );
+
+          push @{ $self->{BRANCHES} }, $branch;
+        }
+
+        # Check package name for source directory declarations
+        if ($my_label eq 'SRCDIR' or $my_label eq 'EXPSRCDIR') {
+          if ($pck eq $pckroot and $value !~ m#^/#) {
+            # Sub-package name not set and source directory quoted as a relative
+            # path, determine package name from path name
+            my @subpck = File::Spec->splitdir ($value);
+            $pck       = join '::', ($pckroot, @subpck);
+          }
+        }
+
+        # Assign the value accordingly
+        if ($my_label eq 'REPOS') {          # Repository location
+          $branch->repos ($value);
+
+        } elsif ($my_label eq 'VERSION') {   # Version used
+          $branch->version ($value);
+
+        } elsif ($my_label eq 'SRCDIR') {    # Source directory used
+          $branch->dir ($pck, $value);
+
+        } elsif ($my_label eq 'EXPSRCDIR') { # Expandable source directory
+          $branch->expdir ($pck, $value);
+        }
+
+        next LINE;
+      }
+    }
+
+    # Label not recognised
+    w_report 'ERROR: ', $line->{SRC}, ': LINE ', $line->{NUMBER},
+             ': label "', $label, '" not recognised';
+    return;
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ext->check_dest ();
+#
+# DESCRIPTION
+#   This method checks that the extract destionations are set correctly.
+# ------------------------------------------------------------------------------
+
+sub check_dest {
+  my $self = shift;
+
+  my %subdir  = %{ $self->config->setting ('DIR') };
+  my %cfgname = %{ $self->config->setting ('CFG_NAME') };
+
+  # Default destination settings
+  my $dest = $self->{DEST};
+  if ($dest->{ROOTDIR}) {
+    unless ($dest->{SRCDIR}) {   # Location of extracted source
+      $dest->{SRCDIR} = catfile $dest->{ROOTDIR}, $subdir{SRC};
+    }
+    unless ($dest->{CFGDIR}) {   # Location of configuration files
+      $dest->{CFGDIR} = catfile $dest->{ROOTDIR}, $subdir{CFG};
+    }
+    unless ($dest->{CACHEDIR}) { # Location of cache
+      $dest->{CACHEDIR} = catfile $dest->{ROOTDIR}, $subdir{CACHE};
+    }
+    unless ($dest->{BLD_CFG}) {  # Location of (output) bld cfg
+      $dest->{BLD_CFG} = catfile $dest->{CFGDIR}, $cfgname{BLD};
+    }
+    unless ($dest->{EXT_CFG}) {  # Location of (output) ext cfg
+      $dest->{EXT_CFG} = catfile $dest->{CFGDIR}, $cfgname{EXT};
+    }
+  } else {
+    w_report 'Error: ', $self->cfg->src,
+             ': destination root directory not set.';
+    return;
+  }
+
+  # Default remote destination settings
+  if ($self->{RDEST}{MACHINE}) {
+
+    # Use local logname as remote logname if it is not set
+    $self->{RDEST}{LOGNAME} = getlogin      unless $self->{RDEST}{LOGNAME};
+    $self->{RDEST}{LOGNAME} = $ENV{LOGNAME} unless $self->{RDEST}{LOGNAME};
+    $self->{RDEST}{LOGNAME} = $ENV{USER}    unless $self->{RDEST}{LOGNAME};
+
+    unless ($self->{RDEST}{LOGNAME}) {
+      w_report 'Error: ', $self->cfg->src,
+               ': cannot determine your remote logname.';
+      return;
+    }
+
+    # Make sure remote destination root directory is set
+    unless ($self->{RDEST}{ROOTDIR}) {
+      w_report 'Error: ', $self->cfg->src,
+               ': remote destination root directory not set.';
+      return;
+    }
+
+    # Make sure remote destination source directory is set
+    $self->{RDEST}{SRCDIR} = catfile $self->{RDEST}{ROOTDIR}, $subdir{SRC}
+      unless $self->{RDEST}{SRCDIR};
+
+    # Make sure remote destination configuration directory is set
+    $self->{RDEST}{CFGDIR} = catfile $self->{RDEST}{ROOTDIR}, $subdir{CFG}
+      unless $self->{RDEST}{CFGDIR};
+
+    # Make sure remote bld cfg is set
+    $self->{RDEST}{BLD_CFG} = catfile $self->{RDEST}{CFGDIR}, $cfgname{BLD}
+      unless $self->{RDEST}{BLD_CFG};
+
+    # Make sure remote ext cfg is set
+    $self->{RDEST}{EXT_CFG} = catfile $self->{RDEST}{CFGDIR}, $cfgname{EXT}
+      unless $self->{RDEST}{EXT_CFG};
+
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ext->check_lock ();
+#
+# DESCRIPTION
+#   This method checks whether a lock is set in the current extract.
+# ------------------------------------------------------------------------------
+
+sub check_lock {
+  my $self = shift;
+
+  my $rootdir  = $self->{DEST}{ROOTDIR};
+  my $lock_ext = catfile ($rootdir, $self->config->setting (qw/MISC LOCK_EXT/));
+  my $lock_bld = catfile ($rootdir, $self->config->setting (qw/MISC LOCK_BLD/));
+
+  # Always throw error if extract lock exists
+  if (-e $lock_ext) {
+    w_report 'ERROR: extract lock file exists: ', $lock_ext, ',';
+    w_report '       an extract may be running at ', $rootdir, ', abort.';
+    return;
+  }
+
+  # Throw error if current object is not a "used" pre-extracted object and
+  # a build lock exists
+  if ((not $self->{EXTRACTED}) and -e $lock_bld) {
+    w_report 'ERROR: build lock file exists: ', $lock_bld, ',';
+    w_report '       a build may be running at ', $rootdir, ', abort.';
+    return;
+  }
+
+  # Check locks in inherited extract
+  for my $use (@{ $self->{USE} }) {
+    return unless $use->check_lock;
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_set_lock ();
+#
+# DESCRIPTION
+#   This method sets a lock is set in the current extract.
+# ------------------------------------------------------------------------------
+
+sub _set_lock {
+  my $self = shift;
+
+  $self->{LOCK} = catfile (
+    $self->{DEST}{ROOTDIR}, $self->config->setting (qw/MISC LOCK_EXT/),
+  );
+
+  &touch_file ($self->{LOCK});
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ext->expand_cfg ();
+#
+# DESCRIPTION
+#   This method expands the settings of the extract configuration.
+# ------------------------------------------------------------------------------
+
+sub expand_cfg {
+  my $self = shift;
+
+  # Establish a set of source directories from the "base repository"
+  my %base_branches = ();
+
+  # Inherit "base" set of source directories from re-used extracts
+  my @uses = @{ $self->{USE} };
+
+  for my $use (@uses) {
+    my @branches = $use->branches;
+
+    for my $branch (@branches) {
+      my $package              = $branch->package;
+      $base_branches{$package} = $branch unless exists $base_branches{$package};
+    }
+  }
+
+  for my $branch (@{ $self->{BRANCHES} }) {
+    # Expand URL keywords if necessary
+    if ($branch->repos) {
+      my $repos = expand_url_keyword (
+        URL => $branch->repos,
+        CFG => $self->config,
+      );
+      $branch->repos ($repos) if $repos ne $branch->repos;
+    }
+
+    # Check that repository type and version are set
+    if ($branch->repos and &is_url ($branch->repos)) {
+      $branch->type    ('svn')  unless $branch->type;
+      $branch->version ('head') unless $branch->version;
+
+    } else {
+      $branch->type    ('user') unless $branch->type;
+      $branch->version ('user') unless $branch->version;
+    }
+
+    $branch->expand_version_tag; # Work out revision number a version tag
+    $branch->expand_path;        # Expand relative path to full path
+    $branch->expand_all;         # Search sub-directories
+
+    my $package = $branch->package;
+
+    if (exists $base_branches{$package}) {
+      # A base branch for this package exists
+
+      # If current branch has no source directory, use the set provided by the
+      # base branch
+      my %dirs = $branch->dirs;
+      $branch->add_base_dirs ($base_branches{$package}) unless keys %dirs;
+
+    } else {
+      # This package does not yet have a base branch, set this branch as base
+      $base_branches{$package} = $branch;
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_create_dest_dir ($full);
+#
+# DESCRIPTION
+#   This internal method (re-)creates all the destination directories if
+#   necessary. If $full is set to true, it removes existing directories/files
+#   in the destination directories.
+# ------------------------------------------------------------------------------
+
+sub _create_dest_dir {
+  my ($self, $full) = @_;
+
+  my $verbose = $self->config->verbose;
+
+  # Remove previous extract if "FULL" flag is set
+  if ($full) {
+    # Remove extracted source
+    if (-d $self->{DEST}{SRCDIR} and -w $self->{DEST}{SRCDIR}) {
+      print 'Remove directory: ', $self->{DEST}{SRCDIR}, "\n" if $verbose;
+      my $removed = rmtree $self->{DEST}{SRCDIR};
+      w_report 'WARNING: ', $self->{DEST}{SRCDIR}, ': cannot remove.'
+        if not $removed;
+    }
+
+    # Remove cache
+    my @files;
+    if (-d $self->{DEST}{CACHEDIR} and opendir DIR, $self->{DEST}{CACHEDIR}) {
+      @files = grep {$_ ne '.' and $_ ne '..'} readdir 'DIR';
+      closedir DIR;
+    }
+
+    for my $file (@files) {
+      my $path = File::Spec->catfile ($self->{DEST}{CACHEDIR}, $file);
+
+      next unless $file eq $self->config->setting (qw/CACHE EXTCONFIG/) or
+                  -d $path;
+
+      print 'Remove: ', $path, "\n" if $verbose;
+      my $removed = rmtree $path;
+      w_report 'WARNING: ', $path, ': cannot remove.' if not $removed;
+    }
+  }
+
+  # Create extract destinations if necessary
+  for my $my_label (qw/ROOTDIR CACHEDIR CFGDIR SRCDIR/) {
+    my $dirname = $self->{DEST}{$my_label};
+
+    # Create directory if it does not already exist
+    if (not -d $dirname) {
+      print 'Make directory: ', $dirname, "\n" if $verbose > 1;
+      mkpath $dirname;
+    }
+
+    unless (-d $dirname and -w $dirname) {
+      w_report 'ERROR: ', $dirname, ': cannot write to destination.';
+      return;
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ext->create_dir_stack (
+#     USE => $use, # Is this a pre-extracted configuration?
+#   );
+#
+# DESCRIPTION
+#   This method creates a hash of source directories to be processed. If the
+#   flag USE is set to true, the source directories are assumed processed and
+#   extracted.
+# ------------------------------------------------------------------------------
+
+sub create_dir_stack {
+  my $self = shift;
+  my %args = @_;
+  my $extracted = exists $args{USE} ? $args{USE} : undef;
+
+  # Inherit from USE ext cfg
+  if (@{ $self->{USE} } > 0) {
+    for my $use (@{ $self->{USE} }) {
+      $use->create_dir_stack (USE => 1);
+      my %use_srcdirs = $use->srcdirs;
+
+      while (my ($key, $value) = each %use_srcdirs) {
+        $self->{SRCDIRS}{$key} = $value;
+
+        # Re-set destination to current destination
+        my @path = split (/::/, $key);
+        $self->{SRCDIRS}{$key}{DEST} = catfile ($self->{DEST}{SRCDIR}, @path);
+      }
+    }
+  }
+
+  # Build stack from current ext cfg
+  for my $branch (@{ $self->{BRANCHES} }) {
+    my %branch_dirs = $branch->dirs;
+
+    for my $dir (keys %branch_dirs) {
+      # Check whether source directory is already in the list
+      if (not exists $self->{SRCDIRS}{$dir}) { # if not, create it
+        $self->{SRCDIRS}{$dir} = {
+          DEST  => catfile ($self->{DEST}{SRCDIR}, split (/::/, $dir)),
+          STACK => [],
+          FILES => {},
+        };
+      }
+
+      my $stack = $self->{SRCDIRS}{$dir}{STACK}; # copy reference
+
+      # Create a new layer in the input stack
+      my $layer = Fcm::SrcDirLayer->new (
+        CONFIG    => $self->config,
+        NAME      => $dir,
+        PACKAGE   => $branch->package,
+        TAG       => $branch->tag,
+        LOCATION  => $branch->dir ($dir),
+        REPOSROOT => $branch->repos,
+        VERSION   => $branch->version,
+        TYPE      => $branch->type,
+        EXTRACTED => $extracted ? $self->{SRCDIRS}{$dir}{DEST} : undef,
+      );
+
+      # Check whether layer is already in the stack
+      my $exist = grep {
+        $_->location eq $layer->location and $_->version  eq $layer->version;
+      } @{ $stack };
+
+      if (not $exist) {
+        # If not already exist, put layer into stack
+
+        # Note: user stack always comes last
+        if (! $layer->user and exists $stack->[-1] and $stack->[-1]->user) {
+          my $lastlayer = pop @{ $stack };
+          push @{ $stack }, $layer;
+          $layer = $lastlayer;
+        }
+
+        push @{ $stack }, $layer;
+
+      } elsif ($layer->user) {
+
+        # User layer already exists, overwrite it
+        $stack->[-1] = $layer;
+
+      }
+    }
+  }
+
+  # Read content of "commit cache" file if it exists
+  my $cachedir = $self->{DEST}{CACHEDIR};
+  my $cfgbase  = $self->config->setting (qw/CACHE EXTCONFIG/);
+  my $cfgfile  = catfile $cachedir, $cfgbase;
+  my %config_lines = ();
+  if (-r $cfgfile) {
+    my $cfg = Fcm::CfgFile->new (CONFIG => $self->config, SRC => $cfgfile,);
+    $cfg->read_cfg;
+    my @lines = $cfg->lines;
+
+    for my $line (@lines) {
+      $config_lines{$line->{LABEL}} = $line->{VALUE};
+    }
+  }
+
+  my %new_config_lines;
+
+  # Compare each layer to base layer, discard unnecessary layers
+  for my $srcdir (keys %{ $self->{SRCDIRS} }) {
+    my @stack = ();
+
+    while (my $layer = shift @{ $self->{SRCDIRS}{$srcdir}{STACK} }) {
+      if ($layer->user) {
+        # User directory, check that the declared location exists
+        if (not -d $layer->location) {
+          w_report 'Error: declared source directory ', $layer->location,
+                   ' does not exists ';
+          return;
+        }
+
+        # Always override repository code
+        push @stack, $layer;
+
+      } else {
+        unless ($layer->extracted and $layer->commit) {
+
+          my $key = join '::', ($srcdir, $layer->location, $layer->version);
+
+          # See if commit version information is cached
+          if (keys %config_lines) {
+            if (exists $config_lines{$key}) {
+              $layer->commit ($config_lines{$key});
+            }
+          }
+
+          # Check source directory for commit version, if necessary
+          $layer->get_commit unless $layer->commit;
+          if (not $layer->commit) {
+            w_report 'Error: cannot determine the last changed revision of ',
+                     $layer->location;
+            return;
+          }
+
+          # Set cache directory for layer
+          my $tag_ver = $layer->tag . '__' . $layer->commit;
+          $layer->cachedir (catfile $cachedir, split (/::/, $srcdir), $tag_ver);
+
+          # New line in cache config file
+          $new_config_lines{$key} = $layer->commit;
+        }
+
+        # Push this layer in the stack:
+        # 1. it has a different version compared to the top layer
+        # 2. it is the top layer (base line code)
+        if (@stack > 0) {
+          push @stack, $layer if $layer->commit != $stack[0]->commit;
+
+        } else {
+          push @stack, $layer;
+        }
+
+      }
+    }
+
+    $self->{SRCDIRS}{$srcdir}{STACK} = \@stack;
+
+  }
+
+  # Write "commit cache" file
+  if (not $extracted) {
+    mkpath $cachedir if not -d $cachedir;
+    my $cfg = Fcm::CfgFile->new (CONFIG => $self->config,);
+
+    while ((my $label, my $value) = each %new_config_lines) {
+      $cfg->add_line (LABEL => $label, VALUE => $value,);
+    }
+
+    $cfg->print_cfg ($cfgfile);
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_extract_src ();
+#
+# DESCRIPTION
+#   This internal method performs the extract of the source directories and
+#   files if necessary.
+# ------------------------------------------------------------------------------
+
+sub _extract_src {
+  my $self = shift;
+
+  my $verbose = $self->config->verbose;
+  my %v_count = (
+    CREATED_DIRS    => 0,
+    IGNORED_SUBDIRS => 0,
+    UPDATED_FILES   => 0,
+    REMOVED_FILES   => 0,
+  );
+
+  my $cachedir = $self->{DEST}{CACHEDIR};
+
+  # Go through the "stack" of each source directory
+  # Extract the source directories/files if required
+
+  for my $srcdir (values %{ $self->{SRCDIRS} }) {
+
+    # Check if destionation exists and is not a directory
+    if (-f $srcdir->{DEST}) {
+      w_report $srcdir->{DEST},
+               ': destination exists and is not a directory, abort.';
+      return;
+    }
+
+    my %base_files   = (); # list of files in the base layer
+    my %used_files   = (); # keys = file basenames, values = layer reference
+    $srcdir->{FILES} = \%used_files;
+    my @destpath     = (); # search path for source directory destinations
+ 
+    for my $layer (@{ $srcdir->{STACK} }) {
+      # Update the cache for each layer of the stack if necessary
+      $layer->update_cache unless $layer->extracted or -d $layer->localdir;
+
+      # Search path for extract destinations of this source directory
+      unshift @destpath, $layer->extracted
+        if $layer->extracted and not grep {$_ eq $layer->extracted} @destpath;
+ 
+      # Get list of files in the cache or local directory
+      for my $file (($layer->get_files)) {
+        if (exists $base_files{$file}) {
+          # File exists in the base, compare current version with base version,
+          # discard if not changed
+          my $base_file = catfile $base_files{$file}->localdir, $file;
+          my $used_file = catfile $used_files{$file}->localdir, $file;
+          my $this_file = catfile $layer->localdir, $file;
+
+          if (compare ($base_file, $this_file)) { # Differs
+            if ($base_files{$file} eq $used_files{$file}) {
+              # Base and used are the same layer, use current layer
+              $used_files{$file} = $layer;
+
+            } elsif (compare ($used_file, $this_file) == 0) {
+              # Changes in used and this are the same, no update required
+
+              # Print a message at verbose mode 2 or above
+              if ($verbose > 1) {
+                print &_print_override_mesg (
+                  FILE   => $file,
+                  LAYER0 => $base_files{$file},
+                  LAYER1 => $used_files{$file},
+                  LAYER2 => $layer,
+                );
+                print '  Same modifications, use the source in URL 1.', "\n";
+              }
+
+            } elsif ($self->{OVERRIDE}) {
+              # Base and used are different, and used is not the same as this
+              # Override mode, use current layer
+
+              # Print override mode message
+              if ($verbose) {
+                print &_print_override_mesg (
+                  FILE   => $file,
+                  LAYER0 => $base_files{$file},
+                  LAYER1 => $used_files{$file},
+                  LAYER2 => $layer,
+                );
+                print '  ', $file, ' in URL 2 overrides that in URL 1.', "\n";
+              }
+
+              $used_files{$file} = $layer;
+
+            } else {
+              # Base and used are different, and used is not the same as this
+              # Non-override mode, fail the extract
+              w_report &_print_override_mesg (
+                FILE   => $file,
+                LAYER0 => $base_files{$file},
+                LAYER1 => $used_files{$file},
+                LAYER2 => $layer,
+              );
+              w_report '  Override mode is false, file in URL 1 cannot ',
+                       'override file in URL 2, abort.';
+              return;
+            }
+          }
+ 
+        } else {
+          # The first time the file is found
+          $base_files{$file} = $layer;
+          $used_files{$file} = $layer;
+        }
+      }
+    }
+
+    # Add current destination to the beginning of the destination search path
+    unshift @destpath, $srcdir->{DEST} if -d $srcdir->{DEST};
+
+    for my $file (keys %used_files) {
+      # Ignore sub-directories
+      if (-d catfile $used_files{$file}->localdir, $file) {
+        # Print diagnostic
+        if ($verbose > 1) {
+          print 'Ignore subdirectory: ', $file, "\n";
+          print '                Src: ', $used_files{$file}->location;
+          print '@', $used_files{$file}->version unless $used_files{$file}->user;
+          print "\n";
+        }
+        $v_count{IGNORED_SUBDIRS}++;
+        next;
+      }
+
+      # Determine whether file has changed, compared with the destination
+      my $diff = 1;
+      for my $dir (@destpath) {
+        my $old = catfile ($dir, $file);
+
+        if (-f $old) {
+          my $new = catfile ($used_files{$file}->localdir, $file);
+          $diff   = compare $old, $new;
+          last;
+        }
+      }
+
+      if ($diff) { # copy if differs
+        # Create extract destination, if required
+        if (not -d $srcdir->{DEST}) {
+          print 'Create directory: ', $srcdir->{DEST}, "\n" if $verbose > 1;
+          my $mkdirs = mkpath $srcdir->{DEST};
+
+          if (! -d $srcdir->{DEST} or ! -w $srcdir->{DEST}) {
+            w_report $srcdir->{DEST}, ': not a writable directory, abort.';
+            return;
+          }
+
+          $v_count{CREATED_DIRS} += $mkdirs;
+        }
+
+        # Set up the copy command
+        my @cmd = (
+          'cp',
+          catfile ($used_files{$file}->localdir, $file),
+          $srcdir->{DEST},
+        );
+
+        my $dest_file = catfile ($srcdir->{DEST}, $file);
+
+        # Print diagnostic
+        if ($verbose > 1) {
+          print 'Update: ', $dest_file, "\n";
+          print '   Src: ', $used_files{$file}->location;
+          print '@', $used_files{$file}->version unless $used_files{$file}->user;
+          print "\n";
+        }
+
+        # Remove old file if it exists
+        unlink $dest_file if -f $dest_file;
+
+        # Execute the copy command
+        &run_command (\@cmd, TIME => $self->config->verbose > 2);
+
+        $v_count{UPDATED_FILES}++;
+      }
+
+    }
+
+    # Check that the destination directory does not contain any removed files
+    opendir DIR, $srcdir->{DEST};
+    my @dest_files = readdir DIR;
+    closedir DIR;
+
+    while (my $file = shift @dest_files) {
+      next if $file =~ /^\.\.?/;                   # ignore hidden files
+      next if -d catfile ($srcdir->{DEST}, $file); # ignore sub-directories
+
+      # Check if the file exists in any of the versions
+      my $exists = 0;
+      for my $layer (@{ $srcdir->{STACK} }) {
+        if (-f catfile ($layer->localdir, $file)) {
+          $exists = 1;
+          last;
+        }
+      }
+
+      # File exists in destination but not in any versions...
+      if (not $exists) {
+        my @cmd = (
+          qw/rm -f/,
+          catfile ($srcdir->{DEST}, $file),
+        );
+
+        # Print diagnostic
+        print 'Remove: ', catfile ($srcdir->{DEST}, $file), "\n"
+          if $verbose > 1;
+
+        # Execute the command
+        &run_command (\@cmd, TIME => $self->config->verbose > 2);
+
+        $v_count{REMOVED_FILES}++;
+      }
+    }
+  }
+
+  if ($verbose) {
+    my %v_label = (
+      CREATED_DIRS    => 'Number of directories created    : ',
+      IGNORED_SUBDIRS => 'Number of ignored sub-directories: ',
+      UPDATED_FILES   => 'Number of updated files          : ',
+      REMOVED_FILES   => 'Number of removed files          : ',
+    );
+    for my $key (qw/CREATED_DIRS IGNORED_SUBDIRS UPDATED_FILES REMOVED_FILES/) {
+      print $v_label{$key}, $v_count{$key}, "\n" if $v_count{$key};
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = _print_override_mesg (
+#     FILE => $file,
+#     LAYER0 => $layer0,
+#     LAYER1 => $layer1,
+#     LAYER2 => $layer2,
+#   );
+#
+# DESCRIPTION
+#   This internal method returns a string containing an override mode message.
+#
+# ARGUMENTS
+#   FILE   - name of the source file
+#   LAYER0 - base location
+#   LAYER1 - source location overridden by LOC2
+#   LAYER2 - source location overriding LOC1
+# ------------------------------------------------------------------------------
+
+sub _print_override_mesg {
+  my %args = @_;
+
+  my $string = $args{FILE};
+  $string .= ': modified in both URL 1 and URL 2, relative to BASE:';
+  $string .= "\n";
+  $string .= '  BASE : ' . $args{LAYER0}->location;
+  $string .= '@' . $args{LAYER0}->version unless $args{LAYER0}->user;
+  $string .= "\n";
+  $string .= '  URL 1: ' . $args{LAYER1}->location;
+  $string .= '@' . $args{LAYER1}->version unless $args{LAYER1}->user;
+  $string .= "\n";
+  $string .= '  URL 2: ' . $args{LAYER2}->location;
+  $string .= '@' . $args{LAYER2}->version unless $args{LAYER2}->user;
+  $string .= "\n";
+
+  return $string;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_sort_bdeclare ();
+#
+# DESCRIPTION
+#   This internal method sorts the declared build configuration entries,
+#   filtering out repeated entries.
+# ------------------------------------------------------------------------------
+
+sub _sort_bdeclare {
+  my $self = shift;
+
+  # Get list of build configuration labels that can be declared multiple times
+  my %cfg_labels   = %{ $self->config->setting ('CFG_LABEL') };
+  my @cfg_keywords = split /,/, $self->config->setting ('CFG_KEYWORD');
+  @cfg_keywords    = map {$cfg_labels{$_}} @cfg_keywords;
+
+  # Filter out repeated declarations
+  my @bdeclares = ();
+  for my $bdeclare (reverse @{ $self->{BDECLARE} }) {
+    my $label = $bdeclare->{LABEL};
+
+    # Do not filter any declarations that can be declared multiple times
+    my $unshift_ok = grep {
+      uc ($label) eq $_ or index (uc ($label), $_ . '::') == 0;
+    } @cfg_keywords;
+    # @bdeclare contains nothing, last entry
+    $unshift_ok    = 1 unless $unshift_ok or @bdeclares;
+    # Check if a later entry already exists
+    $unshift_ok    = 1
+      unless $unshift_ok or grep {$_->{LABEL} eq $label} @bdeclares;
+
+    # Reconstruct array from bottom up
+    unshift @bdeclares, $bdeclare if $unshift_ok;
+  }
+
+  $self->{BDECLARE} = \@bdeclares;
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_write_ext_cfg ();
+#
+# DESCRIPTION
+#   This internal method writes the expanded extract configuration file.
+# ------------------------------------------------------------------------------
+
+sub _write_ext_cfg {
+  my $self = shift;
+
+  my %cfg_labels = %{ $self->config->setting ('CFG_LABEL') };
+  my %subdir     = %{ $self->config->setting ('DIR') };
+  my %cfgname    = %{ $self->config->setting ('CFG_NAME') };
+
+  # Create new config file object and assign lines to it
+  my $cfg = Fcm::CfgFile->new (CONFIG => $self->config, TYPE => 'ext',);
+
+  # Set up config file header
+  $cfg->add_header ();
+
+  # Re-use pre-extracted expanded ext cfg
+  if (@{ $self->{USE} }) {
+    $cfg->add_comment_block ('Other ext cfg');
+
+    for my $reuse (@{ $self->{USE} }) {
+      my $rootdir = $reuse->dest ('ROOTDIR');
+      my $ext_cfg = $reuse->cfg->src;
+
+      # Default location of build config file
+      my $def_ext_cfg = catfile $rootdir, $subdir{CFG}, $cfgname{EXT};
+
+      $cfg->add_line (
+        LABEL => $cfg_labels{USE},
+        VALUE => $ext_cfg eq $def_ext_cfg ? $rootdir : $ext_cfg,
+      );
+    }
+
+    # Blank line
+    $cfg->add_line;
+  }
+
+  # Destination directories, config file, etc
+  my $dest = $self->{DEST};
+
+  $cfg->add_comment_block ('Destination');
+
+  $cfg->add_line (
+    LABEL => $cfg_labels{DEST}{ROOTDIR},
+    VALUE => $dest->{ROOTDIR},
+  );
+
+  for my $label (qw/CFG SRC CACHE/) {
+    my $dir = $label . 'DIR';
+
+    if ($dest->{$dir} ne catfile $dest->{ROOTDIR}, $subdir{$label}) {
+      $cfg->add_line (
+        LABEL => $cfg_labels{DEST}{$dir},
+        VALUE => $dest->{$dir},
+      );
+    }
+  }
+
+  for my $name (qw/BLD EXT/) {
+    my $label = $name . '_CFG';
+
+    if ($dest->{$label} ne catfile $dest->{CFGDIR}, $cfgname{$name}) {
+      $cfg->add_line (
+        LABEL => $cfg_labels{DEST}{$label},
+        VALUE => $dest->{$label},
+      );
+    }
+  }
+
+  # Blank line
+  $cfg->add_line;
+
+  # Remote destination directories, config file, etc
+  if ($self->{RDEST}{MACHINE}) {
+    my $rdest = $self->{RDEST};
+
+    $cfg->add_comment_block ('Remote destination');
+
+    for my $label (qw/MACHINE LOGNAME ROOTDIR/) {
+      $cfg->add_line (
+        LABEL => $cfg_labels{RDEST}{$label},
+        VALUE => $rdest->{$label},
+      );
+    }
+
+    for my $label (qw/CFG SRC/) {
+      my $dir = $label . 'DIR';
+      if ($rdest->{$dir} ne catfile $rdest->{ROOTDIR}, $subdir{$label}) {
+        $cfg->add_line (
+          LABEL => $cfg_labels{RDEST}{$dir},
+          VALUE => $rdest->{$dir},
+        );
+      }
+    }
+
+    for my $name (qw/BLD EXT/) {
+      my $label = $name . '_CFG';
+
+      if ($rdest->{$label} ne catfile $rdest->{CFGDIR}, $cfgname{$name}) {
+        $cfg->add_line (
+          LABEL => $cfg_labels{RDEST}{$label},
+          VALUE => $rdest->{$label},
+        );
+      }
+    }
+
+    $cfg->add_line (
+      LABEL => $cfg_labels{MIRROR},
+      VALUE => $self->config->setting (qw/TOOL MIRROR/),
+    );
+
+    # Blank line
+    $cfg->add_line;
+  }
+
+  if ($self->{OVERRIDE}) {
+    $cfg->add_line (
+      LABEL => $cfg_labels{OVERRIDE},
+      VALUE => $self->{OVERRIDE} ? 1 : 0,
+    );
+    $cfg->add_line;
+  }
+
+  # Source directories
+  $cfg->add_comment_block ('Source directories');
+
+  # Set up lines in the ext cfg
+  my @lines = ();
+  for my $my_label (keys %{ $self->{SRCDIRS} }) {
+    for my $layer (@{ $self->{SRCDIRS}{$my_label}{STACK} }) {
+      next if $layer->extracted;
+
+      my $tag = $layer->package . '::' . $layer->tag;
+
+      # Repository
+      my $exists = grep {
+        $_->{LABEL} eq $cfg_labels{REPOS} . '::' . $tag;
+      } @lines;
+      push @lines, {
+        LABEL   => $cfg_labels{REPOS} . '::' . $tag,
+        VALUE   => $layer->reposroot,
+      } if not $exists;
+
+      # Version
+      $exists = grep {
+        $_->{LABEL} eq $cfg_labels{VERSION} . '::' . $tag;
+      } @lines;
+      push @lines, {
+        LABEL   => $cfg_labels{VERSION} . '::' . $tag,
+        VALUE   => $layer->version,
+      } unless $layer->user or $exists;
+
+      # Source directory
+      my ($pcks, $path);
+
+      if ($layer->reposroot) {
+        # Repository root declaration exists, print relative path
+        if ($layer->location eq $layer->reposroot) {
+          $path  = '';
+
+        } else {
+          $path  = substr ($layer->location, length ($layer->reposroot) + 1);
+        }
+        my @pcks = split /::/, $my_label;
+        shift @pcks;
+
+        if (join ('::', @pcks) eq join ('::', File::Spec->splitdir ($path))) {
+          # Print top package name if relative path matches sub-package name
+          $pcks = $layer->package;
+
+        } else {
+          # Print full sub-package name otherwise
+          $pcks = $my_label;
+        }
+
+      } else {
+        # No repository root declaration
+        # Print full path and full sub-package name
+        $path = $layer->location;
+        $pcks = $my_label;
+      }
+
+      my $length = $layer->reposroot ? length ($layer->reposroot) + 1 : 0;
+      push @lines, {
+        LABEL   => join ('::', ($cfg_labels{SRCDIR}, $pcks, $layer->tag)),
+        VALUE   => $path,
+      };
+    }
+  }
+
+  # Sort lines for specifying repository, version and source directories
+  @lines = sort {
+    my $rep_label = $cfg_labels{REPOS};
+    my $ver_label = $cfg_labels{VERSION};
+
+    if ($a->{LABEL} =~ /^$rep_label/) {
+
+      # Repository labels
+      if ($b->{LABEL} =~ /^$rep_label/) {
+        $a->{LABEL} cmp $b->{LABEL} or $a->{VALUE} cmp $b->{VALUE};
+      } else {
+        -1;
+      }
+
+    } elsif ($a->{LABEL} =~ /^$ver_label/) {
+
+      # Version labels
+      if ($b->{LABEL} =~ /^$rep_label/) {
+        1;
+      } elsif ($b->{LABEL} =~ /^$ver_label/) {
+        $a->{LABEL} cmp $b->{LABEL} or $a->{VALUE} cmp $b->{VALUE};
+      } else {
+        -1;
+      }
+    } else {
+
+      # Source directories labels
+      if ($b->{LABEL} =~ /^(?:$rep_label|$ver_label)/) {
+        1;
+      } else {
+        $a->{LABEL} cmp $b->{LABEL} or $a->{VALUE} cmp $b->{VALUE};
+      }
+
+    }
+  } @lines;
+
+  # Add lines for specifying repository, version and source directories
+  while (my $line = shift @lines) {
+    $cfg->add_line (
+      LABEL => $line->{LABEL},
+      VALUE => $line->{VALUE},
+    );
+  }
+
+  # Add declared bld cfg entries
+  if (@{ $self->{BDECLARE} }) {
+    # Blank line
+    $cfg->add_line;
+
+    $cfg->add_comment_block ('Declared bld cfg entries');
+    for my $bdeclare (@{ $self->{BDECLARE} }) {
+      $cfg->add_line (
+        LABEL => $cfg_labels{BDECLARE} . '::' . $bdeclare->{LABEL},
+        VALUE => $bdeclare->{VALUE},
+      );
+    }
+  }
+
+  # Print lines to config file
+  $cfg->print_cfg ($self->{DEST}{EXT_CFG});
+
+  return 1;
+
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_write_bld_cfg ();
+#
+# DESCRIPTION
+#   This internal method writes the build configuration file.
+# ------------------------------------------------------------------------------
+
+sub _write_bld_cfg {
+  my $self = shift;
+
+  my %cfg_labels = %{ $self->config->setting ('CFG_LABEL') };
+  my %subdir     = %{ $self->config->setting ('DIR') };
+  my %cfgname    = %{ $self->config->setting ('CFG_NAME') };
+
+  # Create new config file object and assign lines to it
+  my $cfg = Fcm::CfgFile->new (CONFIG => $self->config, TYPE => 'bld');
+
+  # Set up config file header
+  $cfg->add_header ();
+
+  # Pre-compile source
+  if (@{ $self->{USE} }) {
+    $cfg->add_comment_block ('Pre-compile source');
+
+    for my $reuse (@{ $self->{USE} }) {
+      my $rootdir;
+      my $bld_cfg;
+
+      if ($self->{RDEST}{MACHINE}) {
+        $rootdir = $reuse->rdest ('ROOTDIR');
+        $bld_cfg = $reuse->rdest ('BLD_CFG');
+      } else {
+        $rootdir = $reuse->dest ('ROOTDIR');
+        $bld_cfg = $reuse->dest ('BLD_CFG');
+      }
+
+      # Default location of build config file
+      my $def_bld_cfg = catfile $rootdir, $subdir{CFG}, $cfgname{BLD};
+
+      $cfg->add_line (
+        LABEL => $cfg_labels{USE},
+        VALUE => $bld_cfg eq $def_bld_cfg ? $rootdir : $bld_cfg,
+      );
+    }
+
+    # Blank line
+    $cfg->add_line;
+  }
+
+  # Add declared bld cfg entries
+  if (@{ $self->{BDECLARE} }) {
+    $cfg->add_comment_block ('Declared build options...');
+
+    my @bdeclares = sort {$a->{LABEL} cmp $b->{LABEL}} @{ $self->{BDECLARE} };
+    for my $bdeclare (@bdeclares) {
+      $cfg->add_line (
+        LABEL => $bdeclare->{LABEL},
+        VALUE => $bdeclare->{VALUE},
+      );
+    }
+
+    # Blank line
+    $cfg->add_line;
+  }
+
+  # Add source directories to config file
+  $cfg->add_comment_block ('Project directory tree');
+
+  my $dest = $self->{RDEST}{MACHINE} ? $self->{RDEST} : $self->{DEST};
+  $cfg->add_line (
+    LABEL => $cfg_labels{DIR} . '::ROOT',
+    VALUE => $dest->{ROOTDIR},
+  );
+  for my $label (qw/SRC CFG/) {
+    my $dir = $label . 'DIR';
+    if ($dest->{$dir} ne catfile $dest->{ROOTDIR}, $subdir{$label}) {
+      $cfg->add_line (
+        LABEL => $cfg_labels{DIR} . '::' . $label,
+        VALUE => $dest->{$dir},
+      );
+    }
+  }
+
+  # Blank line
+  $cfg->add_line;
+
+  # Add source directories to config file
+  $cfg->add_comment_block ('Source directories');
+
+  $cfg->add_line (LABEL => $cfg_labels{SEARCH_SRC}, VALUE => '0',);
+  $cfg->add_line;
+
+  for my $srcdir (sort keys %{ $self->{SRCDIRS} }) {
+
+    if (-d $self->{SRCDIRS}{$srcdir}{DEST}) {
+      # Check whether pre-extracted source exists
+      my $pre_extracted = grep {
+        $_->extracted;
+      } @{ $self->{SRCDIRS}{$srcdir}{STACK} };
+
+      # Source directory
+      my $dest = undef;
+      if ($self->{RDEST}{MACHINE}) {
+        my $base = substr $self->{SRCDIRS}{$srcdir}{DEST},
+                          length ($self->{DEST}{SRCDIR}) + 1;
+        $dest    = catfile $self->{RDEST}{SRCDIR}, $base;
+      } else {
+        $dest = $self->{SRCDIRS}{$srcdir}{DEST}
+      }
+
+      # Source directory label
+      my $label = join '::', ($cfg_labels{SRCDIR}, $srcdir);
+
+      $cfg->add_line (LABEL => $label, VALUE => $dest,)
+    }
+
+  }
+
+  # Print lines to config file
+  $cfg->print_cfg ($self->{DEST}{BLD_CFG});
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_mirror_extract ();
+#
+# DESCRIPTION
+#   This internal method mirrors the current extract to a remote machine.
+# ------------------------------------------------------------------------------
+
+sub _mirror_extract {
+  my $self = shift;
+
+  # Needs mirroring only if remote machine is set
+  return unless $self->{RDEST}{MACHINE};
+
+  my $verbose = $self->config->verbose;
+
+  my $mirror = $self->config->setting (qw/TOOL MIRROR/);
+
+  if ($mirror eq 'rdist') {
+    # Use "rdist" to mirror extract
+
+    # Variable for "remote_logname@remote_machine"
+    my $rhost = $self->{RDEST}{LOGNAME} . '@' . $self->{RDEST}{MACHINE};
+
+    # Print distfile content to temporary file
+    my @distfile = ();
+    for my $my_label (qw/BLD_CFG EXT_CFG SRCDIR/) {
+      push @distfile, '( ' . $self->{DEST}{$my_label} . ' ) -> ' . $rhost . "\n";
+      push @distfile, '  install ' . $self->{RDEST}{$my_label} . ';' . "\n";
+    }
+
+    # Set up mirroring command (use "rdist" at the moment)
+    my $command = 'rdist -R';
+    $command   .= ' -q' unless $verbose > 1;
+    $command   .= ' -f - 1>/dev/null';
+
+    # Diagnostic
+    my $croak = 'Cannot execute "' . $command . '"';
+    if ($verbose > 2) {
+      print timestamp_command ($command, 'Start');
+      print '  ', $_ for (@distfile);
+    }
+
+    # Execute the mirroring command
+    open COMMAND, '|-', $command or croak $croak, ' (', $!, '), abort';
+    for my $line (@distfile) {
+      print COMMAND $line;
+    }
+    close COMMAND or croak $croak, ' (', $?, '), abort';
+
+    # Diagnostic
+    print timestamp_command ($command, 'End  ') if $verbose > 2;
+
+  } elsif ($mirror eq 'rsync') {
+    # Use "rsync" to mirror extract
+
+    my $rsh = $self->config->setting (qw/TOOL REMOTE_SHELL/);
+
+    # Variable for "remote_logname@remote_machine"
+    my $rhost = $self->{RDEST}{LOGNAME} . '@' . $self->{RDEST}{MACHINE};
+
+    for my $my_label (qw/BLD_CFG EXT_CFG SRCDIR/) {
+      my $rdir = dirname $self->{RDEST}{$my_label}; # remote container directory
+
+      {
+        # Create remote container directory with remote shell command
+        my @command = (
+          $rsh, $self->{RDEST}{MACHINE}, '-n', '-l', $self->{RDEST}{LOGNAME},
+          qw/mkdir -p/, $rdir,
+        );
+
+        # Execute command
+        &run_command (\@command, TIME => $verbose > 2);
+      }
+
+      {
+        # Build the rsync command
+        my @command = qw/rsync -a --exclude='.*' --delete-excluded/;
+        push @command, '-v' if $verbose > 2;
+        push @command, $self->{DEST}{$my_label};
+        push @command, $rhost . ':' . $rdir;
+
+        # Execute command
+        &run_command (\@command, TIME => $verbose > 2);
+      }
+    }
+
+  } else {
+    w_report $mirror, ': unknown mirroring tool, abort.';
+    return;
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/lib/Fcm/ReposBranch.pm
===================================================================
--- LMDZ5/branches/testing/tools/fcm/lib/Fcm/ReposBranch.pm	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/lib/Fcm/ReposBranch.pm	(revision 1665)
@@ -0,0 +1,516 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::ReposBranch
+#
+# DESCRIPTION
+#   This class contains methods for gathering information for a repository
+#   branch. It currently supports Subversion repository and local user
+#   directory.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::ReposBranch;
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Standard modules
+use Carp;
+use File::Spec;
+use File::Spec::Functions;
+use File::Basename;
+use File::Find;
+
+# FCM component modules
+use Fcm::Util;
+use Fcm::Timer;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $branch = Fcm::ReposBranch->new (
+#     CONFIG  => $config,
+#     PACKAGE => $package,
+#     TAG     => $tag,
+#     REPOS   => $repos,
+#     VERSION => $version,
+#     TYPE    => $type,
+#   );
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::ReposBranch class.
+#
+# ARGUMENTS
+#   CONFIG  - reference to a Fcm::Config instance
+#   PACKAGE - package name of which this repository belongs
+#   TAG     - "tag" name of this branch of the repository
+#   REPOS   - repository branch root URL/path
+#   VERSION - this version of the branch is used by the extract
+#   TYPE    - repository type
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $self = {
+    CONFIG  => (exists $args{CONFIG}  ? $args{CONFIG}  : &main::cfg),
+    PACKAGE => (exists $args{PACKAGE} ? $args{PACKAGE} : undef),
+    TAG     => (exists $args{TAG}     ? $args{TAG}     : undef),
+    REPOS   => (exists $args{REPOS}   ? $args{REPOS}   : undef),
+    VERSION => (exists $args{VERSION} ? $args{VERSION} : undef),
+    TYPE    => (exists $args{TYPE}    ? $args{TYPE}    : undef),
+
+    # Use this list of directories in this branch
+    DIRS    => {},
+
+    # Expand this list of directories in this branch
+    EXPDIRS => {},
+  };
+
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = $branch->config;
+#
+# DESCRIPTION
+#   This method returns a reference to the Fcm::Config instance.
+# ------------------------------------------------------------------------------
+
+sub config {
+  my $self = shift;
+
+  return $self->{CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $package = $branch->package;
+#   $branch->package ($package);
+#
+# DESCRIPTION
+#   This method returns the package name of this repository branch. If an
+#   argument is specified, the name is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub package {
+  my $self = shift;
+
+  if (@_) {
+    $self->{PACKAGE} = shift;
+  }
+
+  return $self->{PACKAGE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $tag = $branch->tag;
+#   $branch->tag ($tag);
+#
+# DESCRIPTION
+#   This method returns the tag name of this repository branch. If an
+#   argument is specified, the name is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub tag {
+  my $self = shift;
+
+  if (@_) {
+    $self->{TAG} = shift;
+  }
+
+  return $self->{TAG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $repos = $branch->repos;
+#   $branch->repos ($repos);
+#
+# DESCRIPTION
+#   This method returns the URL/path name of this repository branch. If an
+#   argument is specified, the URL/path is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub repos {
+  my $self = shift;
+
+  if (@_) {
+    $self->{REPOS} = shift;
+  }
+
+  return $self->{REPOS};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $version= $branch->version;
+#   $branch->version ($version);
+#
+# DESCRIPTION
+#   This method returns the revision number of this repository branch. If an
+#   argument is specified, the revision is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub version {
+  my $self = shift;
+
+  if (@_) {
+    $self->{VERSION} = shift;
+  }
+
+  return $self->{VERSION};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $type = $branch->type;
+#   $branch->type ($type);
+#
+# DESCRIPTION
+#   This method returns the repository type ("svn" or "user"). If an
+#   argument is specified, the type is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub type {
+  my $self = shift;
+
+  if (@_) {
+    $self->{TYPE} = shift;
+  }
+
+  return $self->{TYPE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $dir = $branch->dir ($name);
+#   $branch->dir ($name, $dir);
+#
+# DESCRIPTION
+#   This method returns the path to the source directory with sub-package name
+#   $name. If $dir is specified, the path is set to its value.
+# ------------------------------------------------------------------------------
+
+sub dir {
+  my $self = shift;
+  my $name = shift;
+
+  if (@_) {
+    $self->{DIRS}{$name} = $_[0];
+  }
+
+  if (exists $self->{DIRS}{$name}) {
+    return $self->{DIRS}{$name};
+
+  } else {
+    return undef;
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   %dirs = $branch->dirs;
+#
+# DESCRIPTION
+#   This method returns a hash containing the source directories of this
+#   repository. The keys of the hash are the sub-package names, and the values
+#   of the hash are the URL/path to the source directories.
+# ------------------------------------------------------------------------------
+
+sub dirs {
+  my $self = shift;
+
+  return %{ $self->{DIRS} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $dir = $branch->expdir ($name);
+#   $branch->expdir ($name, $dir);
+#
+# DESCRIPTION
+#   This method returns the path to the expandable source directory with
+#   sub-package name $name. If $dir is specified, the path is set to its
+#   value.
+# ------------------------------------------------------------------------------
+
+sub expdir {
+  my $self = shift;
+  my $name = shift;
+
+  if (@_) {
+    $self->{EXPDIRS}{$name} = $_[0];
+  }
+
+  if (exists $self->{EXPDIRS}{$name}) {
+    return $self->{EXPDIRS}{$name};
+
+  } else {
+    return undef;
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   %dirs = $branch->expdirs;
+#
+# DESCRIPTION
+#   This method returns a hash containing the expandable source directories of
+#   this repository. The keys of the hash are the sub-package names, and the
+#   values of the hash are the URL/path to the expandable source directories.
+# ------------------------------------------------------------------------------
+
+sub expdirs {
+  my $self = shift;
+
+  return %{ $self->{EXPDIRS} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $branch->expand_version_tag;
+#
+# DESCRIPTION
+#   This method expands the VERSION of the current repository branch to a
+#   revision number.
+# ------------------------------------------------------------------------------
+
+sub expand_version_tag {
+  my $self = shift;
+
+  if ($self->type eq 'svn') {
+    # Expand revision keyword
+    my $rev = expand_rev_keyword (
+      REV  => $self->version,
+      URL  => $self->repos,
+      HEAD => 1,
+    );
+
+    # Find out whether the specified revision is current or not
+    if (uc ($self->version) ne 'HEAD' and $self->config->verbose > 1) {
+      # Get last commit revision
+      my $lc_rev = expand_rev_keyword (
+        REV => 'HEAD',
+        URL => $self->repos,
+      );
+
+      # Print information if used rev is less than the last commit rev
+      print 'Info: using rev ', $rev, ' of ', $self->repos,
+            ', last commit rev is ', $lc_rev, ".\n"
+        if $rev < $lc_rev;
+    }
+
+    $self->version ($rev) if $rev ne $self->version;
+
+  } elsif ($self->type eq 'user') {
+    return;
+
+  } else {
+    e_report $self->repos, ': repository type "', $self->type,
+             '" not supported.';
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $branch->expand_path;
+#
+# DESCRIPTION
+#   This method expands the relative path names of sub-directories to full
+#   path names. It returns 1 on success.
+# ------------------------------------------------------------------------------
+
+sub expand_path {
+  my $self = shift;
+
+  my $separator = $self->{CONFIG}->setting (qw/MISC DIR_SEPARATOR/);
+
+  if ($self->type eq 'svn') {
+    # SVN repository
+    # Do nothing unless there is a declared repository for this branch
+    return unless $self->{REPOS};
+
+    # Remove trailing /
+    $self->{REPOS} =~ s/$separator+$//;
+
+    # Consider all declared (expandable) sub-directories
+    for my $name (qw/DIRS EXPDIRS/) {
+      for my $dir (keys %{ $self->{$name} }) {
+        # Do nothing if declared sub-directory is quoted as a full URL
+        next if &is_url ($self->{$name}{$dir});
+
+        # Expand sub-directory to full URL
+        $self->{$name}{$dir} = $self->{REPOS} . (
+          $self->{$name}{$dir} ? ($separator . $self->{$name}{$dir}) : ''
+        );
+      }
+    }
+    # Note: "catfile" cannot be used in the above statement because it has
+    #       the tendency of removing a slash from double slashes.
+
+  } elsif ($self->type eq 'user') {
+    # Local user directories
+
+    # Expand leading ~ for all declared (expandable) sub-directories
+    for my $name (qw/DIRS EXPDIRS/) {
+      for my $dir (keys %{ $self->{$name} }) {
+        $self->{$name}{$dir} = expand_tilde $self->{$name}{$dir};
+      }
+    }
+
+    # A top directory for the source is declared
+    if ($self->{REPOS}) {
+      # Expand leading ~ for the top directory
+      $self->{REPOS} = expand_tilde $self->{REPOS};
+
+      # Get the root directory of the file system
+      my $rootdir = File::Spec->rootdir ();
+
+      # Expand top directory to absolute path, if necessary
+      $self->{REPOS} = File::Spec->rel2abs ($self->{REPOS})
+        if $self->{REPOS} !~ m/^$rootdir/;
+
+      # Remove trailing /
+      $self->{REPOS} =~ s/$separator+$//;
+
+      # Consider all declared (expandable) sub-directories
+      for my $name (qw/DIRS EXPDIRS/) {
+        for my $dir (keys %{ $self->{$name} }) {
+          # Do nothing if declared sub-directory is quoted as a full path
+          next if $self->{$name}{$dir} =~ m#^$rootdir#;
+
+          # Expand sub-directory to full path
+          $self->{$name}{$dir} = $self->{$name}{$dir}
+                               ? catfile ($self->{REPOS}, $self->{$name}{$dir})
+                               : $self->{REPOS};
+        }
+      }
+    }
+
+  } else {
+    e_report $self->repos, ': repository type "', $self->type,
+             '" not supported.';
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $branch->expand_all;
+#
+# DESCRIPTION
+#   This method searches the expandable source directories recursively for
+#   source directories containing regular files. These sub-directories are
+#   then added to the source directory list. The method returns total number
+#   of sub-directories to be extracted from the current repository.
+# ------------------------------------------------------------------------------
+
+sub expand_all {
+  my $self = shift;
+
+  my %dirs = ();
+
+  # Directory separator for SVN repository
+  my $separator = $self->{CONFIG}->setting (qw/MISC DIR_SEPARATOR/);
+
+  if ($self->type eq 'user') {
+    for my $rootname (keys %{ $self->{EXPDIRS} }) {
+      my %subdirs = find_srcdir $self->{EXPDIRS}{$rootname}, $rootname, '::';
+
+      for my $key (keys %subdirs) {
+        $dirs{$key} = $subdirs{$key};
+      }
+    }
+
+  } elsif  ($self->type eq 'svn') {
+    for my $rootname (keys %{ $self->{EXPDIRS} }) {
+      # Execute the "svn ls -R" command
+      my @lines   = &run_command (
+        [qw/svn ls -R/, $self->{EXPDIRS}{$rootname} . '@' . $self->{VERSION}],
+        METHOD => 'qx', TIME => $self->config->verbose > 2,
+      );
+
+      # Get list of sub-directories containing source files
+      for my $line (@lines) {
+        chomp $line;
+        next if $line =~ /$separator$/;
+
+        my $dir = dirname $line;
+
+        my @pck = split /::/, $rootname;
+        push @pck, (File::Spec->splitdir ($dir)) unless $dir eq '.';
+        my $pck = join '::', @pck;
+
+        my $val = $self->{EXPDIRS}{$rootname};
+        $val   .= $separator . $dir unless $dir eq '.';
+
+        $dirs{$pck} = $val;
+      }
+    }
+
+  } else {
+    e_report $self->repos, ': repository type "', $self->type,
+             '" not supported.';
+  }
+
+  for my $key (keys %dirs) {
+    $self->{DIRS}{$key} = $dirs{$key};
+  }
+
+  return scalar keys %dirs;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $branch->add_base_dirs ($base);
+#
+# DESCRIPTION
+#   Add a list of source directories to the current branch based on the set
+#   provided by $base, which must be a reference to a Fcm::ReposBranch
+#   instance. It returns the total number of used sub-directories in the
+#   current repositories.
+# ------------------------------------------------------------------------------
+
+sub add_base_dirs {
+  my $self = shift;
+  my $base = shift;
+
+  my %base_dirs = $base->dirs;
+
+  for my $key (keys %base_dirs) {
+    # Remove repository root from base directories
+    if ($base_dirs{$key} eq $base->repos) {
+      $base_dirs{$key} = '';
+
+    } else {
+      $base_dirs{$key} = substr $base_dirs{$key}, length ($base->repos) + 1;
+    }
+
+    # Append base directories to current repository root
+    $self->dir ($key, $base_dirs{$key}); 
+  }
+
+  # Expand relative path names of sub-directories
+  $self->expand_path;
+
+  return scalar keys %{ $self->{DIRS} };
+  
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/lib/Fcm/SrcDirLayer.pm
===================================================================
--- LMDZ5/branches/testing/tools/fcm/lib/Fcm/SrcDirLayer.pm	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/lib/Fcm/SrcDirLayer.pm	(revision 1665)
@@ -0,0 +1,481 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::SrcDirLayer
+#
+# DESCRIPTION
+#   This class contains methods to manipulate the extract of a source
+#   directory from a branch of a (Subversion) repository.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::SrcDirLayer;
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Standard modules
+use Carp;
+use File::Spec;
+use File::Spec::Functions;
+use File::Basename;
+use File::Path;
+use File::Compare;
+
+# FCM component modules
+use Fcm::Util;
+use Fcm::Timer;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $layer = Fcm::SrcDirLayer->new (
+#     CONFIG    => $config,
+#     NAME      => $dir,
+#     PACKAGE   => $package,
+#     TAG       => $tag,
+#     LOCATION  => $loc,
+#     REPOSROOT => $repos,
+#     VERSION   => $ver,
+#     TYPE      => $type,
+#     COMMIT    => $com,
+#     EXTRACTED => $ext,
+#     CACHEDIR  => $cac,
+#   );
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::SrcDirLayer class.
+#
+# ARGUMENTS
+#   CONFIG    - reference to a Fcm::Config instance
+#   NAME      - sub-package name of the source directory
+#   PACKAGE   - top level package name of which the current repository belongs
+#   TAG       - package/revision tag of the current repository branch
+#   LOCATION  - location of the source directory in the branch
+#   REPOSROOT - repository root URL
+#   VERSION   - revision of the repository branch
+#   TYPE      - type of the repository branch ("svn" or "user")
+#   COMMIT    - revision at which the source directory was changed
+#   EXTRACTED - is this branch already extracted?
+#   CACHEDIR  - cache directory for this directory branch
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $self = {
+    CONFIG    => (exists $args{CONFIG}    ? $args{CONFIG}    : &main::cfg),
+    NAME      => (exists $args{NAME}      ? $args{NAME}      : undef),
+    PACKAGE   => (exists $args{PACKAGE}   ? $args{PACKAGE}   : undef),
+    TAG       => (exists $args{TAG}       ? $args{TAG}       : undef),
+    LOCATION  => (exists $args{LOCATION}  ? $args{LOCATION}  : undef),
+    REPOSROOT => (exists $args{REPOSROOT} ? $args{REPOSROOT} : undef),
+    VERSION   => (exists $args{VERSION}   ? $args{VERSION}   : undef),
+    TYPE      => (exists $args{TYPE}      ? $args{TYPE}      : undef),
+    COMMIT    => (exists $args{COMMIT}    ? $args{COMMIT}    : undef),
+    EXTRACTED => (exists $args{EXTRACTED} ? $args{EXTRACTED} : undef),
+    CACHEDIR  => (exists $args{CACHEDIR}  ? $args{CACHEDIR}  : undef),
+
+    # List of source files in this directory branch
+    FILES     => [],
+  };
+
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = $layer->config;
+#
+# DESCRIPTION
+#   This method returns a reference to the Fcm::Config instance.
+# ------------------------------------------------------------------------------
+
+sub config {
+  my $self = shift;
+
+  return $self->{CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $name = $layer->name;
+#   $layer->name ($name);
+#
+# DESCRIPTION
+#   This method returns the sub-package name of the current source directory.
+#   If an argument is specified, the sub-package name is set to the value of
+#   the argument.
+# ------------------------------------------------------------------------------
+
+sub name {
+  my $self = shift;
+
+  if (@_) {
+    $self->{NAME} = shift;
+  }
+
+  return $self->{NAME};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $package = $layer->package;
+#   $layer->package ($package);
+#
+# DESCRIPTION
+#   This method returns the top level package name in which the current source
+#   directory belongs. If an argument is specified, the package name is set to
+#   the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub package {
+  my $self = shift;
+
+  if (@_) {
+    $self->{PACKAGE} = shift;
+  }
+
+  return $self->{PACKAGE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $tag = $layer->tag;
+#   $layer->tag ($tag);
+#
+# DESCRIPTION
+#   This method returns the branch/revision tag of the current repository
+#   branch. If an argument is specified, the tag is set to the value of the
+#   argument.
+# ------------------------------------------------------------------------------
+
+sub tag {
+  my $self = shift;
+
+  if (@_) {
+    $self->{TAG} = shift;
+  }
+
+  return $self->{TAG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $location = $layer->location;
+#   $layer->location ($location);
+#
+# DESCRIPTION
+#   This method returns the URL/location of the source directory in the
+#   branch. If an argument is specified, the location is set to the value of
+#   the argument.
+# ------------------------------------------------------------------------------
+
+sub location {
+  my $self = shift;
+
+  if (@_) {
+    $self->{LOCATION} = shift;
+  }
+
+  return $self->{LOCATION};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $reposroot = $layer->reposroot;
+#   $layer->reposroot ($reposroot);
+#
+# DESCRIPTION
+#   This method returns the URL/location of the repository root of this
+#   branch. If an argument is specified, the location is set to the value of
+#   the argument.
+# ------------------------------------------------------------------------------
+
+sub reposroot {
+  my $self = shift;
+
+  if (@_) {
+    $self->{REPOSROOT} = shift;
+  }
+
+  return $self->{REPOSROOT};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $version = $layer->version;
+#   $layer->version ($version);
+#
+# DESCRIPTION
+#   This method returns the revision number of this branch. If an argument is
+#   specified, the revision number is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub version {
+  my $self = shift;
+
+  if (@_) {
+    $self->{VERSION} = shift;
+  }
+
+  return $self->{VERSION};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $type = $layer->type;
+#   $layer->type ($type);
+#
+# DESCRIPTION
+#   This method returns the repository type ("svn" or "user"). If an argument is
+#   specified, the type is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub type {
+  my $self = shift;
+
+  if (@_) {
+    $self->{TYPE} = shift;
+  }
+
+  return $self->{TYPE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $version = $layer->commit;
+#   $layer->commit ($version);
+#
+# DESCRIPTION
+#   This method returns the last modified revision of the source directory in
+#   the branch. If an argument is specified, this revision is set to the value
+#   of the argument.
+# ------------------------------------------------------------------------------
+
+sub commit {
+  my $self = shift;
+
+  if (@_) {
+    $self->{COMMIT} = shift;
+  }
+
+  return $self->{COMMIT};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $extracted = $layer->extracted;
+#   $layer->extracted ($extracted);
+#
+# DESCRIPTION
+#   This method returns the "extracted flag" of the source directory branch
+#   If an argument is specified, the flag is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub extracted {
+  my $self = shift;
+
+  if (@_) {
+    $self->{EXTRACTED} = shift;
+  }
+
+  return $self->{EXTRACTED};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $dir = $layer->cachedir;
+#   $layer->cachedir ($dir);
+#
+# DESCRIPTION
+#   This method returns the cache directory of the source directory branch
+#   If an argument is specified, the cache directory is set to the value of
+#   the argument.
+# ------------------------------------------------------------------------------
+
+sub cachedir {
+  my $self = shift;
+
+  if (@_) {
+    my $dir = shift;
+    $self->{CACHEDIR} = $dir;
+  }
+
+  return $self->{CACHEDIR};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $dir = $layer->localdir;
+#
+# DESCRIPTION
+#   This method returns the user or cache directory for the current revision
+#   of the repository branch.
+# ------------------------------------------------------------------------------
+
+sub localdir {
+  my $self = shift;
+
+  return $self->user ? $self->{LOCATION} : $self->{CACHEDIR};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @files = $layer->files;
+#
+# DESCRIPTION
+#   This method returns a list of regular files in this directory branch.
+#   This method should only be called after a successful operation of the
+#   get_files method that will be described below.
+# ------------------------------------------------------------------------------
+
+sub files {
+  my $self = shift;
+
+  return @{ $self->{FILES} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $user = $layer->user;
+#
+# DESCRIPTION
+#   This method returns the string "user" if the current source directory
+#   branch is a local directory. Otherwise, it returns "undef".
+# ------------------------------------------------------------------------------
+
+sub user {
+  my $self = shift;
+
+  return $self->{TYPE} eq 'user' ? 'user' : undef;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $version = $layer->get_commit;
+#
+# DESCRIPTION
+#   If the current repository type is "svn", this method attempts to obtain
+#   the revision in which the branch is last committed. On a successful
+#   operation, it returns this revision number. Otherwise, it returns
+#   "undef".
+# ------------------------------------------------------------------------------
+
+sub get_commit {
+  my $self = shift;
+
+  if ($self->type eq 'svn') {
+    # Execute the "svn info" command
+    my @lines   = &run_command (
+      [qw/svn info/, $self->{LOCATION} . '@' . $self->{VERSION}],
+      METHOD => 'qx', TIME => $self->config->verbose > 2,
+    );
+
+    my $rev;
+    for (@lines) {
+      if (/^Last\s+Changed\s+Rev\s*:\s*(\d+)/i) {
+        $rev = $1;
+        last;
+      }
+    }
+
+    # Commit version of this source directory
+    $self->{COMMIT} = $rev;
+
+    return $self->{COMMIT};
+
+  } elsif ($self->type eq 'user') {
+    return;
+
+  } else {
+    e_report 'Repository type "', $self->type, '" not supported.';
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = $layer->update_cache;
+#
+# DESCRIPTION
+#   If the current repository type is "svn", this method attempts to extract
+#   the current version source directory from the current branch from the
+#   repository, sending the output to the cache directory. It returns true on
+#   a successful operation, or false if the repository is not of type "svn".
+# ------------------------------------------------------------------------------
+
+sub update_cache {
+  my $self = shift;
+
+  return unless $self->{CACHEDIR};
+
+  # Create cache extract destination, if necessary
+  my $dirname = dirname $self->{CACHEDIR};
+  mkpath $dirname if not -d $dirname;
+
+  e_report $dirname, ': cannot write to cache, abort.'
+    unless -d $dirname and -w $dirname;
+  
+  if ($self->type eq 'svn') {
+    # Set up the extract command, "svn export --force -q -N"
+    my @command = (
+      qw/svn export --force -q -N/,
+      $self->{LOCATION} . '@' . $self->{VERSION},
+      $self->{CACHEDIR},
+    );
+
+    &run_command (\@command, TIME => $self->config->verbose > 2);
+
+  } elsif ($self->type eq 'user') {
+    return;
+
+  } else {
+    e_report 'Repository type "', $self->type, '" not supported.';
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @files = $layer->get_files;
+#
+# DESCRIPTION
+#   This method returns a list of files in the cache or local user directory
+#   of the current version of the source directory in the current branch.
+# ------------------------------------------------------------------------------
+
+sub get_files {
+  my $self = shift;
+
+  # Get a list of files in the cache (or local user) directory
+  my @files = ();
+
+  opendir (DIR, $self->localdir)
+    or die $self->localdir, ': cannot read directory';
+
+  while (my $file = readdir DIR) {
+    next if $file =~ /^\.\.?/;                   # ignore . and .. and hidden
+    next if $file =~ /~$/;                       # ignore emacs swap files
+    next if -d catfile ($self->localdir, $file); # ignore sub-directories
+    push @files, $file;
+  }
+  closedir DIR;
+
+  # Return the (base name) of the list of files
+  $self->{FILES} = \@files;
+  return @files;
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/lib/Fcm/SrcFile.pm
===================================================================
--- LMDZ5/branches/testing/tools/fcm/lib/Fcm/SrcFile.pm	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/lib/Fcm/SrcFile.pm	(revision 1665)
@@ -0,0 +1,1538 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::SrcFile
+#
+# DESCRIPTION
+#   This class contains methods to manipulate the build process of a source
+#   file of supported type.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::SrcFile;
+
+# Standard pragma
+
+use strict;
+use warnings;
+
+# Standard modules
+use Cwd;
+use Carp;
+use File::Basename;
+use File::Spec;
+use File::Spec::Functions;
+
+# FCM component modules
+use Fcm::Util;
+use Fcm::Timer;
+
+# Other modules
+use Ecmwf::Fortran90_stuff ();
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $srcfile = Fcm::SrcFile->new (
+#     CONFIG     => $config,
+#     SRCPACKAGE => $srcpackage,
+#     SRC        => $src,
+#     PPSRC      => $ppsrc,
+#     TYPE       => $type,
+#     SCAN       => $scan,
+#     EXEBASE    => $exebase,
+#     PCKCFG     => $pckcfg,
+#   );
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::SrcFile class.
+#
+# ARGUMENTS
+#   CONFIG     - reference to a Fcm::Config instance
+#   SRCPACKAGE - reference to the container Fcm::SrcPackage instance
+#   SRC        - source path of this file
+#   PPSRC      - pre-processed source path of this file
+#   TYPE       - type flag of this source file
+#   SCAN       - scan source file for dependency?
+#   EXEBASE    - name of executable
+#   PCKCFG     - this source file is modified by a package cfg?
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $self = {
+    CONFIG     => exists $args{CONFIG}     ? $args{CONFIG}     : &main::cfg,
+    SRCPACKAGE => exists $args{SRCPACKAGE} ? $args{SRCPACKAGE} : undef,
+    SRC        => exists $args{SRC}        ? $args{SRC}        : undef,
+    PPSRC      => exists $args{PPSRC}      ? $args{PPSRC}      : undef,
+    TYPE       => exists $args{TYPE}       ? $args{TYPE}       : undef,
+    SCAN       => exists $args{SCAN}       ? $args{SCAN}       : 1,
+    EXEBASE    => exists $args{EXEBASE}    ? $args{EXEBASE}    : undef,
+    PCKCFG     => exists $args{PCKCFG}     ? $args{PCKCFG}     : undef,
+
+    PROGNAME   => undef,
+    LANG       => undef,
+    DEP        => {}, 
+    RULES      => {},
+  };
+  bless $self, $class;
+
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = $srcfile->config;
+#
+# DESCRIPTION
+#   This method returns a reference to the Fcm::Config instance.
+# ------------------------------------------------------------------------------
+
+sub config {
+  my $self = shift;
+
+  return $self->{CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $srcpackage = $srcfile->srcpackage;
+#   $srcfile->srcpackage ($srcpackage);
+#
+# DESCRIPTION
+#   This method returns the reference to the container Fcm::SrcPackage of this
+#   source file. If an argument is specified, the reference is set to the
+#   value of the argument.
+# ------------------------------------------------------------------------------
+
+sub srcpackage {
+  my $self = shift;
+
+  if (@_) {
+    $self->{SRCPACKAGE} = shift;
+  }
+
+  return $self->{SRCPACKAGE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $src = $srcfile->src;
+#   $srcfile->src ($src);
+#
+# DESCRIPTION
+#   This method returns the reference to the location of this source file. If
+#   an argument is specified, the location is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub src {
+  my $self = shift;
+
+  if (@_) {
+    $self->{SRC} = shift;
+  }
+
+  return $self->{SRC};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ppsrc = $srcfile->ppsrc;
+#   $srcfile->ppsrc ($ppsrc);
+#
+# DESCRIPTION
+#   This method returns the reference to the location of the pre-processed
+#   file of this source file. If an argument is specified, the location is set
+#   to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub ppsrc {
+  my $self = shift;
+
+  if (@_) {
+    $self->{PPSRC} = shift;
+  }
+
+  return $self->{PPSRC};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $time = $srcfile->mtime;
+#
+# DESCRIPTION
+#   This method returns the last modified time of the source file. If a
+#   pre-processed version of the source file exists, it returns the last
+#   modified time of the pre-processed source file instead.
+# ------------------------------------------------------------------------------
+
+sub mtime {
+  my $self = shift;
+
+  return $self->{PPSRC} ? (stat $self->{PPSRC})[9] : (stat $self->{SRC})[9];
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $base = $srcfile->base;
+#
+# DESCRIPTION
+#   This method returns the base name of the source file.
+# ------------------------------------------------------------------------------
+
+sub base {
+  my $self = shift;
+
+  return basename ($self->{SRC});
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ppbase = $srcfile->ppbase;
+#
+# DESCRIPTION
+#   This method returns the base name of the pre-processed source file.
+# ------------------------------------------------------------------------------
+
+sub ppbase {
+  my $self = shift;
+
+  return basename ($self->{PPSRC});
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $interfacebase = $srcfile->interfacebase;
+#
+# DESCRIPTION
+#   This method returns the base name of the F9X interface file.
+# ------------------------------------------------------------------------------
+
+sub interfacebase {
+  my $self   = shift;
+  my $return = undef;
+
+  if ($self->is_type_or (qw/FORTRAN FPP/) and
+      uc ($self->select_tool ('GENINTERFACE')) ne 'NONE' and
+      not $self->is_type_or (qw/PROGRAM MODULE/)) {
+
+    my $flag = lc ($self->select_tool ('INTERFACE'));
+    my $ext  = $self->config->setting (qw/OUTFILE_EXT INTERFACE/);
+
+    $return = ($flag eq 'program' ? $self->intname : $self->root) . $ext;
+  }
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $root = $srcfile->root;
+#
+# DESCRIPTION
+#   This method returns the root name (i.e. base name without file extension)
+#   of the source file.
+# ------------------------------------------------------------------------------
+
+sub root {
+  my $self = shift;
+
+  (my $root = $self->base) =~ s/\.\w+$//;
+
+  return $root;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ext = $srcfile->ext;
+#
+# DESCRIPTION
+#   This method returns the file extension of the source file.
+# ------------------------------------------------------------------------------
+
+sub ext {
+  my $self = shift;
+
+  return substr $self->base, length ($self->root);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ppext = $srcfile->ppext;
+#
+# DESCRIPTION
+#   This method returns the file extension of the pre-processed source file.
+# ------------------------------------------------------------------------------
+
+sub ppext {
+  my $self = shift;
+
+  return substr $self->ppbase, length ($self->root);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $dir = $srcfile->dir;
+#
+# DESCRIPTION
+#   This method returns the dir name of the source file.
+# ------------------------------------------------------------------------------
+
+sub dir {
+  my $self = shift;
+
+  return dirname ($self->{SRC});
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $ppdir = $srcfile->ppdir;
+#
+# DESCRIPTION
+#   This method returns the dir name of the pre-processed source file.
+# ------------------------------------------------------------------------------
+
+sub ppdir {
+  my $self = shift;
+
+  return dirname ($self->{PPSRC});
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $progname = $srcfile->progname();
+#   $srcfile->progname ($progname);
+#
+# DESCRIPTION
+#   This method returns the name of the first program unit in a Fortran source
+#   file. If an argument is specified, the name is set to the value of the
+#   argument.
+# ------------------------------------------------------------------------------
+
+sub progname {
+  my $self = shift;
+
+  if (@_) {
+    $self->{PROGNAME} = $_[0];
+  }
+
+  return $self->{PROGNAME};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $intname = $srcfile->intname ();
+#
+# DESCRIPTION
+#   This method returns the internal name of the source file.
+# ------------------------------------------------------------------------------
+
+sub intname {
+  my $self = shift;
+
+  return $self->progname ? $self->progname : lc ($self->root);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $objbase = $srcfile->objbase ();
+#
+# DESCRIPTION
+#   If the source file contains a compilable procedure, this method returns
+#   the name of the object file.
+# ------------------------------------------------------------------------------
+
+sub objbase {
+  my $self   = shift;
+  my $return = undef;
+
+  if ($self->is_type ('SOURCE')) {
+    my $ext = $self->config->setting (qw/OUTFILE_EXT OBJ/);
+
+    if ($self->is_type_or (qw/FORTRAN FPP/)) {
+      $return = $self->progname . $ext if $self->progname;
+
+    } else {
+      $return = $self->intname . $ext;
+    }
+  }
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $donebase = $srcfile->donebase ();
+#
+# DESCRIPTION
+#   This method returns the DONE file for a source file containing a compilable
+#   procedure, or the IDONE file for an include file.
+# ------------------------------------------------------------------------------
+
+sub donebase {
+  my $self   = shift;
+  my $return = undef;
+
+  if ($self->is_type ('SOURCE')) {
+    if ($self->objbase and not $self->is_type ('PROGRAM')) {
+      $return = $self->intname . $self->config->setting (qw/OUTFILE_EXT DONE/);
+    }
+
+  } elsif ($self->is_type ('INCLUDE')) {
+    $return = $self->base . $self->config->setting (qw/OUTFILE_EXT IDONE/);
+  }
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $exebase = $srcfile->exebase ();
+#   $srcfile->exebase ($exebase);
+#
+# DESCRIPTION
+#   If the source file contains a compilable main program, this method returns
+#   the executable name. If an argument is specified, the executable name is
+#   set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub exebase {
+  my $self = shift;
+
+  if (@_) {
+    $self->{EXEBASE} = $_[0];
+  }
+
+  my $return;
+
+  if ($self->objbase and $self->is_type ('PROGRAM')) {
+    if ($self->config->setting ('EXE_NAME', $self->root)) {
+      $return = $self->config->setting ('EXE_NAME', $self->root);
+
+    } elsif ($self->{EXEBASE}) {
+      $return = $self->{EXEBASE};
+
+    } else {
+      $return = $self->root . $self->config->setting (qw/OUTFILE_EXT EXE/);
+    }
+  }
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $base = $srcfile->flagsbase ([$flag]);
+#
+# DESCRIPTION
+#   If the source file contains a compilable program unit, it returns the base
+#   name of the compiler flags-file. If $flag is set, it returns the base name
+#   of the flags file as specified by $flag. The value of $flag can be:
+#     FLAGS   - compiler flags flags-file (default)
+#     PPKEYS  - pre-processor keys (i.e. macro definitions) flags-file
+#     LD      - linker flags-file
+#     LDFLAGS - linker flags flags-file
+# ------------------------------------------------------------------------------
+
+sub flagsbase {
+  my ($self, $flag) = @_;
+  $flag             = 'FLAGS' if not $flag;
+  my $return        = undef;
+
+  if ($self->is_type ('SOURCE')) {
+    if ($flag eq 'FLAGS' or $flag eq 'PPKEYS') {
+      my %src_tool = %{ $self->config->setting ('SRC_TOOL') };
+
+      if ($self->lang and exists $src_tool{$self->lang}{$flag}) {
+        $return = join ('__', (
+          $src_tool{$self->lang}{$flag}, $self->srcpackage->name, $self->root,
+        )) . $self->config->setting (qw/OUTFILE_EXT FLAGS/);
+      }
+
+    } elsif ($self->is_type ('PROGRAM')) {
+      $return = join ('__', ($flag, $self->srcpackage->name, $self->root)) .
+                $self->config->setting (qw/OUTFILE_EXT FLAGS/);
+    }
+  }
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   %dep   = $srcfile->dep;
+#   @files = $srcfile->dep ($type);
+#   $srcfile->dep (\%dep);
+#
+# DESCRIPTION
+#   This method returns the dependencies of this source file. If no argument
+#   is set, the method returns the dependency hash of this source file. The
+#   keys of the hash are the names of the files this source files depends on
+#   and the values of the hash are the dependency types of the corresponding
+#   files. If an argument is specified and the argument is a normal string,
+#   the method returns the keys of the dependency hash, which have their
+#   corresponding values equal to $type. If an argument is specified and the
+#   argument is a reference to a hash, the reference to the dependency hash of
+#   the current source file is re-set to point to the reference of this new
+#   hash.
+# ------------------------------------------------------------------------------
+
+sub dep {
+  my $self = shift;
+
+  if (@_) {
+    if (ref $_[0] eq 'HASH') {
+      $self->{DEP} = $_[0];
+
+    } else {
+      my $type = $_[0];
+      return grep {
+        $self->{DEP}{$_} eq $type;
+      } keys %{ $self->{DEP} };
+    }
+  }
+
+  return %{ $self->{DEP} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $srcfile->add_dep ($target, $type);
+#
+# DESCRIPTION
+#   This method adds (or modifies) a dependency to the dependency hash of the
+#   source file. The argument $type is the type of the dependency and the
+#   argument $target is the dependency target.
+# ------------------------------------------------------------------------------
+
+sub add_dep {
+  my $self = shift;
+  my ($target, $type) = @_;
+
+  $self->{DEP}{$target} = $type;
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @pklist = $self->get_package_list ();
+#
+# DESCRIPTION
+#   This method returns a list of package names associated with this source
+#   file. The list begins with the top level container package to the
+#   sub-package name of the current source file.
+# ------------------------------------------------------------------------------
+
+sub get_package_list {
+  my $self = shift;
+
+  my @pknames = ();
+
+  my @packages = split /__/, $self->srcpackage->name;
+  push @packages, $self->root;
+
+  for my $i (0 .. $#packages) {
+    push @pknames, join ('__', (@packages[0 .. $i]));
+  }
+
+  return @pknames;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $pckcfg = $srcfile->pckcfg ();
+#   $srcfile->pckcfg ($pckcfg);
+#
+# DESCRIPTION
+#   This method returns the name of the flag to indicate whether this source
+#   file is modified by a package level configuration file. If an argument is
+#   specified, the flag is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub pckcfg {
+  my $self = shift;
+
+  if (@_) {
+    $self->{PCKCFG} = $_[0];
+  }
+
+  return $self->{PCKCFG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $srcfile->scan ();
+#   $srcfile->scan ($flag);
+#
+# DESCRIPTION
+#   This method returns the "scan" flag that determines whether the source
+#   file needs to be scanned for dependency. If an argument is specified, the
+#   flag is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub scan {
+  my $self = shift;
+
+  if (@_) {
+    $self->{SCAN} = $_[0];
+  }
+
+  return $self->{SCAN};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $type = $srcfile->type;
+#   $srcfile->type ($type);
+#
+# DESCRIPTION
+#   This method returns the type flag of the source file. If an argument is
+#   specified, the flag is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub type {
+  my $self = shift;
+
+  if (@_) {
+    $self->{TYPE} = shift;
+  }
+
+  return $self->{TYPE};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $srcfile->is_type ($type1[, $type2, ...]);
+#
+# DESCRIPTION
+#   This method returns true if current file is a known type matching all the
+#   arguments.
+# ------------------------------------------------------------------------------
+
+sub is_type {
+  my $self    = shift;
+  my @intypes = @_;
+  my $rc      = 0;
+
+  if ($self->{TYPE}) {
+    my @types = split /::/, $self->{TYPE};
+
+    for my $intype (@intypes) {
+      $rc = grep {uc $_ eq uc $intype} @types;
+      last unless $rc;
+    }
+
+  }
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $srcfile->is_type_or ($type1[, $type2, ...]);
+#
+# DESCRIPTION
+#   This method returns true if current file is a known type matching any of
+#   the arguments.
+# ------------------------------------------------------------------------------
+
+sub is_type_or {
+  my $self    = shift;
+  my @intypes = @_;
+  my $rc      = 0;
+
+  if ($self->{TYPE}) {
+    my @types = split /::/, $self->{TYPE};
+
+    for my $intype (@intypes) {
+      $rc = grep {uc $_ eq uc $intype} @types;
+      last if $rc;
+    }
+
+  }
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $lang = $srcfile->lang ();
+#
+# DESCRIPTION
+#   This method returns the language name of the source file if it contains
+#   compilable source of a supported language.
+# ------------------------------------------------------------------------------
+
+sub lang {
+  my $self = shift;
+
+  if ((not $self->{LANG}) and $self->is_type ('SOURCE')) {
+    my %src_tool = %{ $self->config->setting ('SRC_TOOL') };
+
+    for my $key (keys %src_tool) {
+      if ($self->is_type ($key)) {
+        $self->{LANG} = $key;
+        last;
+      }
+    }
+  }
+
+  return $self->{LANG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $srcfile->determine_type;
+#
+# DESCRIPTION
+#   This method determines whether the source file is a type known to the
+#   build system. If so, it sets the "type" flag.
+# ------------------------------------------------------------------------------
+
+sub determine_type {
+  my $self = shift;
+
+  if (not $self->{TYPE}) {
+    # Do not set a type if the file name matches the "ignore" list
+    my @ignore = split /,/, $self->config->setting ('INFILE_IGNORE');
+
+    for (@ignore) {
+      return if $self->base eq $_;
+    }
+  }
+
+  if (not $self->{TYPE}) {
+    # Determine file type by comparing its extension with supported ones
+    my %known_ext = %{ $self->config->setting ('INFILE_EXT') };
+    my $ext       = $self->ext ? substr ($self->ext, 1) : 0;
+    $self->{TYPE} = $known_ext{$ext} if $ext and exists $known_ext{$ext};
+  }
+
+  if (not $self->{TYPE}) {
+    # Determine file type by comparing its name with known patterns
+    my %known_pat = %{ $self->config->setting ('INFILE_PAT') };
+    for my $pat (keys %known_pat) {
+      if ($self->base =~ /$pat/) {
+        $self->{TYPE} = $known_pat{$pat};
+        last;
+      }
+    }
+  }
+
+  if (-s $self->{SRC} and -T $self->{SRC} and not $self->{TYPE}) {
+    # Determine file type by inspecting its first line (text file only)
+    if (open SRC, '<', $self->{SRC}) {
+      my $line = <SRC>;
+      close SRC;
+
+      my %known_txt = %{ $self->config->setting ('INFILE_TXT') };
+      for my $txt (keys %known_txt) {
+        if ($line =~ /^#!.*$txt/) {
+          $self->{TYPE} = $known_txt{$txt};
+          last;
+        }
+      }
+    }
+  }
+
+  if ($self->is_type_or (qw/FORTRAN FPP/)) {
+    # Determine whether source file is a main Fortran program or module
+    if (open SRC, '<', $self->{SRC}) {
+      while (my $line = <SRC>) {
+        if ($line =~ /^\s*(PROGRAM|MODULE)\b/i) {
+          $self->{TYPE} = $self->{TYPE} . '::' . uc ($1);
+          last;
+
+        } elsif ($line =~ /^\s*BLOCK\s*DATA\b/i) {
+          $self->{TYPE} = $self->{TYPE} . '::' . 'BLOCKDATA';
+          last;
+        }
+      }
+      close SRC;
+    }
+
+  } elsif ($self->is_type (qw/C/)) {
+    # Determine whether source file is a main C program
+    if (open SRC, '<', $self->{SRC}) {
+      while (my $line = <SRC>) {
+        next unless $line =~ /int\s*main\s*\(/i;
+        $self->{TYPE} = $self->{TYPE} . '::PROGRAM';
+        last;
+      }
+      close SRC;
+    }
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @pp_src = @{ $srcfile->pre_process () };
+#
+# DESCRIPTION
+#   This method invokes the pre-processor on the source file. It returns a
+#   reference to an array containing the lines of the pre-processed source if
+#   the pre-processor command succeeded.
+# ------------------------------------------------------------------------------
+
+sub pre_process {
+  my $self = shift;
+
+  # Support only Fortran and C source files
+  return unless $self->is_type_or (qw/FPP C/);
+
+  # List of include directories
+  my @inc = @{ $self->config->setting (qw/PATH INC/) };
+
+  # Build the pre-processor command according to file type
+  my $name    = $self->is_type ('FPP') ? 'FPP' : 'CPP';
+  my %tool    = %{ $self->config->setting ('TOOL') };
+
+  # The pre-processor command and its options
+  my @command = ($tool{$name});
+  my @ppflags = split /\s+/, $self->select_tool ($name . 'FLAGS');
+
+  # List of defined macros, add "-D" in front of each macro
+  my @ppkeys  = split /\s+/, $self->select_tool ($name . 'KEYS');
+  @ppkeys     = map {($tool{$name . '_DEFINE' }. $_)} @ppkeys;
+
+  # Add "-I" in front of each include directories
+  @inc        = map {($tool{$name . '_INCLUDE'}. $_)} @inc;
+
+  push @command, (@ppflags, @ppkeys, @inc, $self->base);
+
+  my $verbose = $self->config->verbose;
+  my $cwd     = cwd;
+
+  # Change to container directory of source file
+  print 'cd ', $self->dir, "\n" if $verbose > 1;
+  chdir $self->dir;
+
+  # Execute the command, getting the output lines
+  my @outlines = &run_command (
+    \@command, METHOD => 'qx', PRINT => $verbose > 1, TIME => $verbose > 2,
+  );
+
+  # Change back to original directory
+  print 'cd ', $cwd, "\n" if $self->config->verbose > 1;
+  chdir $cwd;
+
+  return \@outlines;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @interface_block = @{ $srcfile->gen_interface () };
+#
+# DESCRIPTION
+#   This method invokes the Fortran 9x interface block generator to generate
+#   an interface block for the current source file. It returns a reference to
+#   an array containing the lines of the interface block.
+# ------------------------------------------------------------------------------
+
+sub gen_interface {
+  my $self = shift;
+
+  my $generator = $self->select_tool ('GENINTERFACE');
+
+  my $src      = $self->{PPSRC} ? $self->{PPSRC} : $self->{SRC};
+  my @outlines = ();
+
+  if ($generator eq 'f90aib') {
+    # Use F90AIB
+
+    # Open pipeline to interface file generator and read its output
+    my $devnull = File::Spec->devnull;
+    my $command = $generator;
+    $command   .= " <'" . $src . "'" . " 2>'" . $devnull . "'";
+    my $croak   = $command . ' failed';
+
+    print timestamp_command ($command, 'Start') if $self->config->verbose > 2;
+    open COMMAND, '-|', $command or croak $croak, ' (', $!, '), abort';
+    @outlines = readline 'COMMAND';
+    close COMMAND or croak $croak, ' (', $?, '), abort';
+    print timestamp_command ($command, 'End  ') if $self->config->verbose > 2;
+
+  } elsif ($generator eq 'ECMWF') {
+    # Use ECMWF interface generator
+  
+    # Read source file into an array
+    open FILE, '<', $src or croak 'Cannot open "', $src, '" (', $!, '), abort';
+    my @src_lines = <FILE>;
+    close FILE;
+  
+    # Process standalone subroutines and functions only
+    if (not grep /^\s*(?:program|module)\b/i, @src_lines) {
+      print timestamp_command ('Analyse: ' . $self->src, 'Start')
+        if $self->config->verbose > 2;
+
+      my @statements = ();
+      my %prog_info  = ();
+  
+      # Set name of source file
+      &Ecmwf::Fortran90_stuff::fname ($src);
+  
+      # Parse lines in source
+      &Ecmwf::Fortran90_stuff::setup_parse ();
+
+      # Expand continuation lines in source
+      &Ecmwf::Fortran90_stuff::expcont (\@src_lines, \@statements);
+  
+      # Analyse statements in source
+      $Ecmwf::Fortran90_stuff::study_called = 0;
+      &Ecmwf::Fortran90_stuff::study (\@statements, \%prog_info);
+  
+      # Source code is not a module
+      if (not $prog_info{is_module}) {
+        my @interface_block = ();
+        my @line_hash       = ();
+  
+        # Create an interface block for the program unit
+        &Ecmwf::Fortran90_stuff::create_interface_block (
+          \@statements,
+          \@interface_block,
+        );
+
+        # Put continuation lines back
+        &Ecmwf::Fortran90_stuff::cont_lines (
+          \@interface_block,
+          \@outlines,
+          \@line_hash,
+        );
+      }
+
+      print timestamp_command ('Analyse: ' . $self->src, 'End')
+        if $self->config->verbose > 2;
+    }
+
+  } elsif (uc ($generator) eq 'NONE') {
+    print $self->root, ': interface generation is switched off', "\n"
+      if $self->config->verbose > 2;
+
+  } else {
+    e_report 'Error: Unknown Fortran 9x interface generator: ', $generator, '.';
+  }
+
+  return \@outlines;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $tool = $self->select_tool ($name);
+#
+# DESCRIPTION
+#   This method selects the correct "tool" for the current source file by
+#   following the name of its container package. The argument $name must be
+#   the generic name of the "tool" to be selected. The method returns the
+#   value of the selected tool.
+# ------------------------------------------------------------------------------
+
+sub select_tool {
+  my $self  = shift;
+  my $name  = shift;
+
+  return undef unless $name;
+
+  my @pknames = $self->get_package_list ();
+
+  my %tool    = %{ $self->config->setting ('TOOL') };
+
+  for my $pkname (reverse @pknames) {
+    my $cur_name = join '__', ($name, $pkname);
+    return $tool{$cur_name} if exists $tool{$cur_name};
+  }
+
+  return exists $tool{$name} ? $tool{$name} : '';
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = $srcfile->scan_dependency ();
+#   $rc = $srcfile->scan_dependency (HEADER_ONLY => 1);
+#
+# DESCRIPTION
+#   This method scans the source file for dependencies. If no argument is
+#   specified, the method scans the pre-processed source file if it exists.
+#   Otherwise, the original source file is scanned. If HEADER_ONLY is
+#   specified, only pre-processing header dependencies are scanned from the
+#   source file. (The HEADER_ONLY flag should only be specified if "ppsrc" is
+#   not already specified.) This method returns the number of 1 on success.
+# ------------------------------------------------------------------------------
+
+sub scan_dependency {
+  my $self = shift;
+  my %args = @_;
+
+  my $header_only = exists $args{HEADER_ONLY} ? $args{HEADER_ONLY} : 0;
+
+  return 0 unless $self->{SCAN};
+  return 0 unless $self->{TYPE};
+
+  my $src = $self->{PPSRC} ? $self->{PPSRC} : $self->{SRC};
+  return 0 unless $src;
+
+  # Determine what dependencies are supported by this known type
+  my %types = $header_only
+              ? %{ $self->config->setting ('PP_DEP_TYPE') }
+              : %{ $self->config->setting ('DEP_TYPE') };
+
+  # List of excluded dependencies
+  my %excl_dep = %{ $self->config->setting ('EXCL_DEP') };
+
+  # Package list
+  my @pknames = $self->get_package_list ();
+
+  my @depends = ();
+  for my $key (keys %types) {
+    # Check if current file is a type of file requiring dependency scan
+    next unless $self->is_type ($key);
+    
+    # Get list of dependency type for this file
+    DEPEND: for my $depend ((split /::/, $types{$key})) {
+      # Ignore a dependency type if the dependency is in the exclude list
+      if (exists $excl_dep{$depend}) {
+        # Global exclude
+        next DEPEND if exists $excl_dep{$depend}{''};
+
+        # Sub-package exclude
+        for my $pkname (@pknames) {
+          next DEPEND if exists $excl_dep{$depend}{$pkname};
+        }
+      }
+
+      # Add to dependency list for current file
+      push @depends, $depend;
+    }
+  }
+
+  # Scan dependencies, if necessary ...
+  if (@depends) {
+    # Print diagnostic
+    print timestamp_command ('scan dependency in file: ' . $src, 'Start')
+      if $self->config->verbose > 2;
+
+    open FILE, '<', $src or croak 'Cannot open "', $src, '" (', $!, ')';
+    my @lines = readline 'FILE';
+    close FILE;
+
+    # List of dependency patterns
+    my %dep_pattern = %{ $self->config->setting ('DEP_PATTERN') };
+
+    LINE: for my $line (@lines) {
+      # Ignore empty lines
+      next LINE if $line =~ /^\s*$/;
+
+      # Fortran source, also scan for program unit name
+      if (! $header_only and ! $self->progname) {
+        if ($self->is_type ('SOURCE') and $self->is_type_or (qw/FPP FORTRAN/)) {
+          my $pfx_pttn = '(?:(?:ELEMENTAL|(?:RECURSIVE(?:\s+PURE)?|' .
+                         'PURE(?:\s+RECURSIVE)?))\s+)?';
+          my $spc_pttn = '(?:(?:CHARACTER|COMPLEX|DOUBLE\s*PRECISION|INTEGER|' .
+                         'LOGICAL|REAL|TYPE)(?:\s*\(.+\)|\s*\*\d+\s*)??\s+)?';
+
+          if ($line =~ /^\s*PROGRAM\s+(\w+)/i) {
+            # Matches the beginning of a named main program
+            $self->progname (lc $1);
+            next LINE;
+
+          } elsif ($line =~ /^\s*MODULE\s+(\w+)/i) {
+            my $keyword = $1;
+
+            if (uc ($keyword) ne 'PROCEDURE') {
+              # Matches the beginning of a module
+              $self->progname (lc $keyword);
+              next LINE;
+            }
+
+          } elsif ($line =~ /^\s*BLOCK\s*DATA\s+(\w+)/i) {
+            # Matches the beginning of a named block data program unit
+            $self->progname (lc $1);
+            next LINE;
+
+          } elsif ($line =~ /^\s*$pfx_pttn SUBROUTINE\s+(\w+)/ix) {
+            # Matches the beginning of a subroutine
+            $self->progname (lc $1);
+            next LINE;
+
+          } elsif ($line =~ /^\s*$pfx_pttn $spc_pttn FUNCTION\s+(\w+)/ix) {
+            # Matches the beginning of a function
+            $self->progname (lc $1);
+            next LINE;
+          }
+        }
+      }
+
+      # Scan known dependencies
+      for my $depend (@depends) {
+        # Check if a pattern exists for the current dependency
+        next unless exists $dep_pattern{$depend};
+
+        # Attempt to match the pattern
+        my $pattern = $dep_pattern{$depend};
+
+        if ($line =~ /$pattern/i) {
+          my $match = $1;
+
+          # $match may contain multiple items delimited by space
+          NAME: for my $name (split /\s+/, $match) {
+            # Skip dependency if it is in the exclusion list
+            my $key = uc ($depend . '::' . $name);
+
+            if (exists $excl_dep{$key}) {
+              # Exclude this dependency, in the global list
+              next NAME if exists $excl_dep{$key}{''};
+
+              # Exclude this dependency, current sub-package
+              for my $pkname (@pknames) {
+                next NAME if exists $excl_dep{$key}{$pkname};
+              }
+            }
+
+            # Add this dependency to the list
+            $self->add_dep ($name, $depend);
+          }
+
+          next LINE;
+        }
+      }
+    }
+
+    # Diagnostic messages
+    if ($self->config->verbose > 2) {
+      my $base = $self->ppsrc ? $self->ppbase : $self->base;
+
+      print $self->srcpackage->name, ': ', $base;
+      print ': scanned ', scalar (@lines), ' lines for ';
+      print 'header ' if $header_only;
+      print 'dependencies: ', scalar (keys %{ $self->{DEP} }), "\n";
+      print timestamp_command ('scan dependency in file: ' . $src, 'End');
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   %rules = $srcfile->required_rules ();
+#
+# DESCRIPTION
+#   This method returns a hash in the following format:
+#     %rules = (
+#       target => {ACTION => action, DEP => [dependencies], ...},
+#       ...    => {...},
+#     );
+#   where the 1st rank keys are the available targets for building this source
+#   file, the second rank keys are ACTION and DEP. The value of ACTION is the
+#   action for building the target, which can be "COMPILE", "LOAD", "TOUCH",
+#   "CP" or "AR". The value of DEP is a refernce to an array containing a list
+#   of dependencies suitable for insertion into the Makefile.
+# ------------------------------------------------------------------------------
+
+sub required_rules {
+  my $self = shift;
+
+  if (not keys %{ $self->{RULES} }) {
+    my %outfile_ext = %{ $self->config->setting ('OUTFILE_EXT') };
+
+    if ($self->is_type (qw/SOURCE/)) {
+      # Source file
+      # ------------------------------------------------------------------------
+      # Determine the whether the language of the source file is supported
+      my %src_tool = %{ $self->config->setting ('SRC_TOOL') };
+
+      return () unless $self->lang;
+
+      # Compile object
+      # ------------------------------------------------------------------------
+      if ($self->objbase) {
+        # Depends on the source file
+        my @dep = ($self->_makerule_srcfile);
+
+        # Depends on the compiler flags flags-file
+        my @flags;
+        push @flags, ('FLAGS' )
+          if $self->flagsbase ('FLAGS' );
+        push @flags, ('PPKEYS')
+          if $self->flagsbase ('PPKEYS') and not $self->ppsrc;
+
+        push @dep, $self->flagsbase ($_) for (@flags);
+
+        # Source file dependencies
+        for my $name (sort keys %{ $self->{DEP} }) {
+          # A Fortran 9X module, lower case object file name
+          if ($self->{DEP}{$name} eq 'USE') {
+            (my $root = $name) =~ s/\.\w+$//;
+            push @dep, lc ($root) . $outfile_ext{OBJ};
+
+          # An include file
+          } elsif ($self->{DEP}{$name} =~ /^(?:INC|H|INTERFACE)$/) {
+            push @dep, $name;
+          }
+        }
+
+        $self->{RULES}{$self->objbase} = {ACTION => 'COMPILE', DEP => \@dep};
+
+        # Touch flags-files
+        # ----------------------------------------------------------------------
+        for my $flag (@flags) {
+          next unless $self->flagsbase ($flag);
+
+          $self->{RULES}{$self->flagsbase ($flag)} = {
+            ACTION => 'TOUCH',
+            DEP    => [
+              $self->srcpackage->flagsbase ($src_tool{$self->lang}{$flag}),
+            ],
+            DEST   => '$(FCM_FLAGSDIR)',
+          };
+        }
+      }
+
+      if ($self->exebase) {
+        # Link into an executable
+        # ----------------------------------------------------------------------
+        my @dep = ();
+        push @dep, $self->objbase               if $self->objbase;
+        push @dep, $self->flagsbase ('LD'     ) if $self->flagsbase ('LD'     );
+        push @dep, $self->flagsbase ('LDFLAGS') if $self->flagsbase ('LDFLAGS');
+
+        # Depends on BLOCKDATA program units, for Fortran programs
+        my %blockdata = %{ $self->config->setting ('BLOCKDATA') };
+        my @blkobj    = ();
+
+        if ($self->is_type_or (qw/FPP FORTRAN/) and keys %blockdata) {
+          # List of BLOCKDATA object files
+          if (exists $blockdata{$self->exebase}) {
+            @blkobj = keys (%{ $blockdata{$self->exebase} });
+
+          } elsif (exists $blockdata{''}) {
+            @blkobj = keys (%{ $blockdata{''} });
+          }
+
+          for my $name (@blkobj) {
+            (my $root = $name) =~ s/\.\w+$//;
+            $name = $root . $outfile_ext{OBJ};
+            push @dep, $root . $outfile_ext{DONE};
+          }
+        }
+
+        # Extra executable dependencies
+        my %exe_dep = %{ $self->config->setting ('EXE_DEP') };
+        if (keys %exe_dep) {
+          my @exe_deps;
+          if (exists $exe_dep{$self->exebase}) {
+            @exe_deps = keys (%{ $exe_dep{$self->exebase} });
+
+          } elsif (exists $exe_dep{''}) {
+            @exe_deps = keys (%{ $exe_dep{''} });
+          }
+
+          my $pattern = '\\' . $outfile_ext{OBJ} . '$';
+
+          for my $name (@exe_deps) {
+            if ($name =~ /$pattern/) {
+              # Extra dependency is an object
+              (my $root = $name) =~ s/\.\w+$//;
+              push @dep, $root . $outfile_ext{DONE};
+
+            } else {
+              # Extra dependency is a sub-package
+              my $var;
+              if ($self->config->setting ('FCM_PCK_OBJECTS', $name)) {
+                # sub-package name contains unusual characters
+                $var = $self->config->setting ('FCM_PCK_OBJECTS', $name);
+
+              } else {
+                # sub-package name contains normal characters
+                $var = $name ? join ('__', ('OBJECTS', $name)) : 'OBJECTS';
+              }
+
+              push @dep, '$(' . $var . ')';
+            }
+          }
+        }
+
+        # Source file dependencies
+        for my $name (sort keys %{ $self->{DEP} }) {
+          (my $root = $name) =~ s/\.\w+$//;
+
+          # Lowercase name for object dependency
+          $root = lc ($root) unless $self->{DEP}{$name} =~ /^(?:INC|H)$/;
+
+          # Select "done" file extension
+          if ($self->{DEP}{$name} =~ /^(?:INC|H)$/) {
+            push @dep, $name . $outfile_ext{IDONE};
+
+          } else {
+            push @dep, $root . $outfile_ext{DONE};
+          }
+        }
+
+        $self->{RULES}{$self->exebase} = {
+          ACTION => 'LOAD', DEP => \@dep, BLOCKDATA => \@blkobj,
+        };
+
+        # Touch Linker flags-file
+        # ----------------------------------------------------------------------
+        for my $flag (qw/LD LDFLAGS/) {
+          $self->{RULES}{$self->flagsbase ($flag)} = {
+            ACTION => 'TOUCH',
+            DEP    => [$self->srcpackage->flagsbase ($flag)],
+            DEST   => '$(FCM_FLAGSDIR)',
+          };
+        }
+
+      }
+
+      if ($self->donebase) {
+        # Touch done file
+        # ----------------------------------------------------------------------
+        my @dep = ($self->objbase);
+
+        for my $name (sort keys %{ $self->{DEP} }) {
+          (my $root = $name) =~ s/\.\w+$//;
+
+          # Lowercase name for object dependency
+          $root = lc ($root) unless $self->{DEP}{$name} =~ /^(?:INC|H)$/;
+
+          # Select "done" file extension
+          if ($self->{DEP}{$name} =~ /^(?:INC|H)$/) {
+            push @dep, $name . $outfile_ext{IDONE};
+
+          } else {
+            push @dep, $root . $outfile_ext{DONE};
+          }
+        }
+
+        $self->{RULES}{$self->donebase} = {
+          ACTION => 'TOUCH', DEP => \@dep, DEST => '$(FCM_DONEDIR)',
+        };
+      }
+      
+      if ($self->interfacebase) {
+        # Interface target
+        # ----------------------------------------------------------------------
+        # Source file dependencies
+        my @dep = ();
+        for my $name (sort keys %{ $self->{DEP} }) {
+          # Depends on Fortran 9X modules
+          push @dep, lc ($name) . $outfile_ext{OBJ}
+            if $self->{DEP}{$name} eq 'USE';
+        }
+
+        $self->{RULES}{$self->interfacebase} = {DEP => \@dep};
+      }
+
+    } elsif ($self->is_type ('INCLUDE')) {
+      # Copy include target
+      # ------------------------------------------------------------------------
+      my @dep = ($self->_makerule_srcfile);
+
+      for my $name (sort keys %{ $self->{DEP} }) {
+        # A Fortran 9X module, lower case object file name
+        if ($self->{DEP}{$name} eq 'USE') {
+          (my $root = $name) =~ s/\.\w+$//;
+          push @dep, lc ($root) . $outfile_ext{OBJ};
+
+        # An include file
+        } elsif ($self->{DEP}{$name} =~ /^(?:INC|H|INTERFACE)$/) {
+          push @dep, $name;
+        }
+      }
+
+      $self->{RULES}{$self->base} = {
+        ACTION => 'CP', DEP => \@dep, DEST => '$(FCM_INCDIR)',
+      };
+
+      # Touch IDONE file
+      # ------------------------------------------------------------------------
+      if ($self->donebase) {
+        my @dep = ($self->_makerule_srcfile);
+
+        for my $name (sort keys %{ $self->{DEP} }) {
+          (my $root = $name) =~ s/\.\w+$//;
+
+          # Lowercase name for object dependency
+          $root   = lc ($root) unless $self->{DEP}{$name} =~ /^(?:INC|H)$/;
+
+          # Select "done" file extension
+          if ($self->{DEP}{$name} =~ /^(?:INC|H)$/) {
+            push @dep, $name . $outfile_ext{IDONE};
+
+          } else {
+            push @dep, $root . $outfile_ext{DONE};
+          }
+        }
+
+        $self->{RULES}{$self->donebase} = {
+          ACTION => 'TOUCH', DEP => \@dep, DEST => '$(FCM_DONEDIR)',
+        };
+      }
+
+    } elsif ($self->is_type_or (qw/EXE SCRIPT/)) {
+      # Copy executable file
+      # ------------------------------------------------------------------------
+      my @dep = ($self->_makerule_srcfile);
+
+      # Depends on dummy copy file, if file is an "always build type"
+      push @dep, $self->config->setting (qw/MISC CPDUMMY/)
+        if $self->is_type_or (
+          split (/,/, $self->config->setting ('ALWAYS_BUILD_TYPE'))
+        );
+
+      # Depends on other executable files
+      for my $name (sort keys %{ $self->{DEP} }) {
+        push @dep, $name if $self->{DEP}{$name} eq 'EXE';
+      }
+
+      $self->{RULES}{$self->base} = {
+        ACTION => 'CP', DEP => \@dep, DEST => '$(FCM_BINDIR)',
+      };
+
+    } elsif ($self->is_type ('LIB')) {
+      # Archive object library
+      # ------------------------------------------------------------------------
+      my @dep;
+      for my $name (sort keys %{ $self->{DEP} }) {
+        next unless $self->{DEP}{$name} eq 'OBJ';
+
+        if ($name =~ /^\$\(\w+\)$/) {
+          # Dependency is a Makefile variable
+          push @dep, $name;
+
+        } else {
+          # Dependency is an object
+          (my $root = $name) =~ s/\.\w+$//;
+          push @dep, lc ($root) . $outfile_ext{OBJ};
+        }
+      }
+
+      $self->{RULES}{$self->base} = {ACTION => 'AR', DEP => \@dep};
+    }
+  }
+
+  return %{ $self->{RULES} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = $srcfile->write_makerules ();
+#
+# DESCRIPTION
+#   This method returns a string containing the "Make" rules for building the
+#   source file.
+# ------------------------------------------------------------------------------
+
+sub write_makerules {
+  my $self  = shift;
+  my $mk    = '';
+  my %rules = $self->required_rules;
+  my $nl    = " \\\n" . ' ' x 10;
+
+  for my $target (sort keys %rules) {
+    $mk .= $target . ':';
+    
+    for my $dep (@{ $rules{$target}{DEP} }) {
+      $mk .= $nl . $dep;
+    }
+
+    $mk .= "\n";
+
+    if (exists $rules{$target}{ACTION}) {
+      if ($rules{$target}{ACTION} eq 'COMPILE') {
+        if ($self->lang) {
+          $mk .= "\t" . 'fcm_internal compile:' . substr ($self->lang, 0, 1) .
+                 ' ' . $self->srcpackage->name . ' $< $@';
+          $mk .= ' 1' if ($self->flagsbase ('PPKEYS') and not $self->ppsrc);
+          $mk .= "\n";
+        }
+
+      } elsif ($rules{$target}{ACTION} eq 'LOAD') {
+        $mk .= "\t" . 'fcm_internal load ' . $self->srcpackage->name . ' $< $@';
+        $mk .= ' ' . join (' ', @{ $rules{$target}{BLOCKDATA} })
+          if @{ $rules{$target}{BLOCKDATA} };
+        $mk .= "\n";
+
+      } elsif ($rules{$target}{ACTION} eq 'TOUCH') {
+        $mk .= "\t" . 'touch ' . catfile ($rules{$target}{DEST}, '$@') . "\n";
+
+      } elsif ($rules{$target}{ACTION} eq 'CP') {
+        $mk .= "\t" . 'cp $< ' . $rules{$target}{DEST} . "\n";
+        $mk .= "\t" . 'chmod u+w ' . catfile ($rules{$target}{DEST}, '$@') . "\n";
+
+      } elsif ($rules{$target}{ACTION} eq 'AR') {
+        $mk .= "\t" . 'fcm_internal archive $@ $(^F)' . "\n";
+      }
+    }
+
+    $mk .= "\n";
+  }
+
+  return $mk;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = $srcfile->_makerule_srcfile ();
+#
+# DESCRIPTION
+#   This internal method returns a string containing the location of the
+#   source file relative to a package source path. This string will be
+#   suitable for use in a "Make" rule file for FCM.
+# ------------------------------------------------------------------------------
+
+sub _makerule_srcfile {
+  my $self = shift;
+
+  my $return;
+  my @searchpath;
+  my $label;
+  my $dir;
+  my $base;
+
+  if ($self->ppsrc) {
+    $return     = $self->ppsrc;
+    @searchpath = $self->srcpackage->ppsearchpath;
+    $label      = 'PPSRCDIR';
+    $dir        = $self->ppdir;
+    $base       = $self->ppbase;
+
+  } else {
+    $return     = $self->src;
+    @searchpath = $self->srcpackage->searchpath;
+    $label      = 'SRCDIR';
+    $dir        = $self->dir;
+    $base       = $self->base;
+  }
+
+  $return = catfile $dir, $base;
+
+  # Use variable for directory name
+  # if container package name contains word characters only
+  if ($self->srcpackage->name =~ /^\w+$/) {
+    for my $i (0 .. $#searchpath) {
+      if ($dir eq $searchpath[$i]) {
+        my $returndir = '$(' . $label . $i . '__' . $self->srcpackage->name .
+                        ')';
+        $return = catfile $returndir, $base;
+        last;
+      }
+    }
+  }
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/lib/Fcm/SrcPackage.pm
===================================================================
--- LMDZ5/branches/testing/tools/fcm/lib/Fcm/SrcPackage.pm	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/lib/Fcm/SrcPackage.pm	(revision 1665)
@@ -0,0 +1,895 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::SrcPackage
+#
+# DESCRIPTION
+#   This is a class to process a source directory package. It uses the
+#   supplied inheritance hierarchy to obtain a list of source files of this
+#   package.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::SrcPackage;
+
+# Standard pragma
+use strict;
+use warnings;
+
+# Standard modules
+use Carp;
+use File::Spec::Functions;
+use File::Basename;
+use File::Path;
+
+# FCM component modules
+use Fcm::Util;
+use Fcm::SrcFile;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $package = Fcm::SrcPackage->new (
+#     CONFIG     => $config,
+#     NAME       => $name,
+#     CURRENT    => $current,
+#     REQUIREPP  => $requirepp,
+#     NEWPP      => $newpp,
+#     SEARCHPATH => \@path,
+#   );
+#
+# DESCRIPTION
+#   This method constructs a new instance of the Fcm::SrcPackage class.
+#
+# ARGUMENTS
+#   CONFIG     - reference to a Fcm::Config instance
+#   NAME       - name of the source directory package
+#   CURRENT    - package declared in current build?
+#   REQUIREPP  - require pre-processing?
+#   NEWPP      - pre-process option has changed?
+#   SEARCHPATH - search path of files in the source package
+# ------------------------------------------------------------------------------
+
+sub new {
+  my $this  = shift;
+  my %args  = @_;
+  my $class = ref $this || $this;
+
+  my $self  = {
+    CONFIG     => exists $args{CONFIG}     ? $args{CONFIG}     : &main::cfg,
+    NAME       => exists $args{NAME}       ? $args{NAME}       : undef,
+    CURRENT    => exists $args{CURRENT}    ? $args{CURRENT}    : undef,
+    REQUIREPP  => exists $args{REQUIREPP}  ? $args{REQUIREPP}  : undef,
+    NEWPP      => exists $args{NEWPP}      ? $args{NEWPP}      : undef,
+    SEARCHPATH => exists $args{SEARCHPATH} ? $args{SEARCHPATH} : [],
+
+    # Reference to Fcm::CfgFile, source package configuration file
+    CFG       => undef,
+
+    # References to Fcm::SrcFile, list of source files
+    SRCFILE   => [],
+  };
+
+  bless $self, $class;
+  return $self;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $config = $package->config;
+#
+# DESCRIPTION
+#   This method returns a reference to the Fcm::Config instance.
+# ------------------------------------------------------------------------------
+
+sub config {
+  my $self = shift;
+
+  return $self->{CONFIG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $name = $package->name;
+#   $package->name ($name);
+#
+# DESCRIPTION
+#   This method returns the name of this package. If an argument is specified,
+#   the name is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub name {
+  my $self = shift;
+
+  if (@_) {
+    $self->{NAME} = shift;
+  }
+
+  return $self->{NAME};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $package->current;
+#   $package->current ($flag);
+#
+# DESCRIPTION
+#   This method returns the "current" flag of the source package. If an
+#   argument is specified, the flag is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub current {
+  my $self = shift;
+
+  if (@_) {
+    $self->{CURRENT} = shift;
+  }
+
+  return $self->{CURRENT};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $package->requirepp;
+#   $package->requirepp ($flag);
+#
+# DESCRIPTION
+#   This method returns the "require PP" flag of the source package. If an
+#   argument is specified, the flag is set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub requirepp {
+  my $self = shift;
+
+  if (@_) {
+    $self->{REQUIREPP} = shift;
+  }
+
+  return $self->{REQUIREPP};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = $package->newpp;
+#   $package->newpp ($flag);
+#
+# DESCRIPTION
+#   This method returns the flag to denote whether pre-processor option for
+#   this source package has changed. If an argument is specified, the flag is
+#   set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub newpp {
+  my $self = shift;
+
+  if (@_) {
+    $self->{NEWPP} = shift;
+  }
+
+  return $self->{NEWPP};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $cfgfile = $package->cfg;
+#   $package->cfg ($cfgfile);
+#
+# DESCRIPTION
+#   This method returns a reference to a Fcm::CfgFile instance for the source
+#   package configuration file. If an argument is specified, the reference is
+#   set to the value of the argument.
+# ------------------------------------------------------------------------------
+
+sub cfg {
+  my $self = shift;
+
+  if (@_) {
+    $self->{CFG} = $_[0];
+  }
+
+  return $self->{CFG};
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @path = $package->searchpath;
+#   $package->searchpath (@path);
+#
+# DESCRIPTION
+#   This method returns the source file search path associated with this
+#   source package in the current build. If arguments are specified, the
+#   search path is replaced by the array in the argument list.
+# ------------------------------------------------------------------------------
+
+sub searchpath {
+  my $self = shift;
+
+  @{ $self->{SEARCHPATH} } = @_ if @_; 
+
+  return @{ $self->{SEARCHPATH} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @path = $package->ppsearchpath;
+#
+# DESCRIPTION
+#   This method returns the pre-processed source file search path associated
+#   with this source package in the current build.
+# ------------------------------------------------------------------------------
+
+sub ppsearchpath {
+  my $self = shift;
+
+  my @path = ();
+  my @name = split /__/, $self->name;
+
+  for my $ppsrcdir (@{ $self->config->setting (qw/PATH PPSRC/) }) {
+    push @path, catfile ($ppsrcdir, @name);
+  }
+
+  return @path;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $base = $package->flagsbase ($flag);
+#
+# DESCRIPTION
+#   Returns the base name of a flags-file, determined by $flag.
+# ------------------------------------------------------------------------------
+
+sub flagsbase {
+  my ($self, $flag) = @_;
+
+  return join ('__', ($flag, $self->name)) .
+         $self->config->setting (qw/OUTFILE_EXT FLAGS/);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @srcfile = $package->srcfile;
+#
+# DESCRIPTION
+#   This method returns a list of references to Fcm::SrcFile instances
+#   associated with this package.
+# ------------------------------------------------------------------------------
+
+sub srcfile {
+  my $self = shift;
+
+  return @{ $self->{SRCFILE} };
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $package->update_file_info ();
+#
+# DESCRIPTION
+#   This method updates the source file information of this package. Please
+#   note that information is only updated if the cache file for this package
+#   does not exist. For a package declared in the current build, the
+#   information is also updated if the cache file is out of date.
+# ------------------------------------------------------------------------------
+
+sub update_file_info {
+  my $self      = shift;
+
+  # Check if the cache file exists and up to date
+  my @cachepath = @{ $self->config->setting (qw/PATH CACHE/) };
+  my $cachefile = find_file_in_path ($self->_cache_basename, \@cachepath);
+
+  my $uptodate  = $cachefile ? 1 : 0;
+  if ($uptodate and $self->{CURRENT}) {
+    # Is cache file up to date compared with directory?
+    $uptodate = (stat $cachefile) [9] > (stat $self->{SEARCHPATH}[0]) [9];
+
+    # Is cache file up to date compared with each file?
+    if ($uptodate) {
+      my $dir = $self->{SEARCHPATH}[0];
+
+      if (opendir DIR, $dir) {
+        my @files = map {catfile $dir, $_} grep {!/^\.\.?/} readdir 'DIR';
+        closedir DIR;
+        $uptodate = (grep {(stat $cachefile) [9] > (stat) [9]} @files) ? 1 : 0;
+      }
+    }
+  }
+
+  # Read package source file information if it appears to be up to date
+  $uptodate = $self->_read_file_list_cache ($cachefile) if ($uptodate);
+
+  # Update package source file information if necessary
+  if (not $uptodate) {
+    # Get list of files by searching through the search path
+    my @files = ();
+    for my $dir (@{ $self->{SEARCHPATH} }) {
+      opendir DIR, $dir;
+      while (my $base = readdir 'DIR') {
+        next if $base =~ /^\./;
+
+        my $file = catfile $dir, $base;
+        next if -d $file;
+
+        push @files, $file unless grep {basename ($_) eq $base} @files;
+      }
+      closedir DIR;
+    }
+
+    # Declare new instances of source file objects
+    my @srcfile = ();
+    for my $file (@files) {
+      if (basename ($file) eq $self->config->setting (qw/CFG_NAME SRCPACKAGE/)) {
+        $self->{CFG} = Fcm::CfgFile->new (CONFIG => $self->config, SRC => $file);
+
+      } else {
+        my $srcfile = Fcm::SrcFile->new (
+          CONFIG     => $self->config,
+          SRC        => $file,
+          SRCPACKAGE => $self,
+        );
+
+        # Determine source file types
+        $srcfile->determine_type;
+
+        # Record files of known types
+        push @srcfile, $srcfile;
+      }
+    }
+
+    # Set each SRCFILE to reference the source file instances
+    $self->{SRCFILE} = \@srcfile;
+
+    # Decipher configuration file if necessary
+    $self->_decipher_cfg if $self->cfg;
+
+    # Write to a new cache file
+    $self->_update_file_list_cache ();
+
+    # Source package info updated. Make sure the "current" flag is set to true
+    $self->current (1);
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $up_to_date = $self->_read_file_list_cache ($file);
+#
+# DESCRIPTION
+#   This internal method reads the cache $file of this package and assigns the
+#   information to the SRCFILE list. It returns true if the cache appears to
+#   be up to date.
+# ------------------------------------------------------------------------------
+
+sub _read_file_list_cache {
+  my $self = shift;
+  my $file = shift;
+
+  my $cfg = Fcm::CfgFile->new (CONFIG => $self->config, SRC => $file);
+
+  # Read from config file
+  $cfg->read_cfg;
+  my @lines = $cfg->lines;
+
+  my %filetype = ();
+  my $uptodate = 1;
+  for my $line (@lines) {
+    next unless $line->{LABEL};
+
+    # On package declared in the current build, check that file is not deleted
+    if (not -f $line->{LABEL}) {
+      $uptodate = 0;
+      last;
+    }
+
+    $filetype{$line->{LABEL}} = $line->{VALUE};
+  }
+
+  # Assign to SRCFILE list if cache file is up to date
+  if ($uptodate) {
+    my @srcfiles = ();
+
+    for my $file (sort keys %filetype) {
+      if ($filetype{$file} eq 'SRCPACKAGECFG') {
+        $self->{CFG} = Fcm::CfgFile->new (CONFIG => $self->config, SRC => $file);
+
+      } else {
+        my $srcfile = Fcm::SrcFile->new (
+          CONFIG     => $self->config,
+          SRC        => $file,
+          TYPE       => $filetype{$file},
+          SRCPACKAGE => $self,
+        );
+
+        push @srcfiles, $srcfile;
+      }
+    }
+
+    $self->{SRCFILE} = [@srcfiles];
+
+    $self->_decipher_cfg if $self->cfg;
+  }
+
+  return $uptodate;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_update_file_list_cache (\@cachepath);
+#
+# DESCRIPTION
+#   This internal method updates the cache file of this package by writing
+#   current SRCFILE information to it. The argument @cachepath must be the
+#   search path of the build cache directory.
+# ------------------------------------------------------------------------------
+
+sub _update_file_list_cache {
+  my $self      = shift;
+  my @cachepath = @{ $self->config->setting (qw/PATH CACHE/) };
+
+  my $cfg = Fcm::CfgFile->new (CONFIG => $self->config);
+
+  if ($self->{CFG}) {
+    $cfg->add_line (LABEL => $self->cfg->src, VALUE => 'SRCPACKAGECFG')
+  }
+
+  for my $file (@{ $self->{SRCFILE} }) {
+    $cfg->add_line (LABEL => $file->src, VALUE => $file->type);
+  }
+
+  my $cachefile = catfile $cachepath[0], $self->_cache_basename;
+  $cfg->print_cfg ($cachefile);
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $basename = $self->_cache_basename ($type);
+#
+# DESCRIPTION
+#   This internal method returns the basename of a cache file for this
+#   package. If no argument is specified, it returns the package file list
+#   cache name. Otherwise, it returns the package file dependency cache name.
+# ------------------------------------------------------------------------------
+
+sub _cache_basename {
+  my $self = shift;
+  my $type = $_[0] ? $_[0] : 'PCKFILE';
+
+  return $self->{NAME} . $self->config->setting ('CACHE', $type);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $self->_decipher_cfg ();
+#
+# DESCRIPTION
+#   This internal method deciphers the CFG file associated with this source
+#   package.
+# ------------------------------------------------------------------------------
+
+sub _decipher_cfg {
+  my $self = shift;
+
+  $self->cfg->read_cfg;
+  my @lines = $self->cfg->lines;
+
+  my %cfg_label = %{ $self->config->setting ('CFG_LABEL') };
+
+  LINE: for my $line (@lines) {
+    my $label = $line->{LABEL};
+    my $value = $line->{VALUE};
+
+    next unless $label;
+    next if uc $label eq $cfg_label{CFGFILE}{TYPE};
+    next if uc $label eq $cfg_label{CFGFILE}{VERSION};
+
+    my ($prefix, $name) = split /::/, $label;
+
+    # Get name of file from the package cfg
+    my $srcfile;
+    if ($name) {
+      ($srcfile) = grep {$_->base eq $name} @{ $self->{SRCFILE} };
+
+      # Create new instance of Fcm::SrcFile if not already in package
+      if (not $srcfile) {
+        my $src    = find_file_in_path ($name, $self->{SEARCHPATH});
+        my $target = $name unless $src;
+
+        $srcfile   = Fcm::SrcFile->new (
+          CONFIG     => $self->config,
+          SRCPACKAGE => $self,
+          SRC        => $src ? $src : $name,
+          TARGET     => $target,
+          PCKCFG     => 1,
+        );
+        push @{ $self->{SRCFILE} }, $srcfile;
+
+      } else {
+        $srcfile->pckcfg (1);
+      }
+
+    } else {
+      w_report 'Warning: ', $line->{SRC}, ': LINE ', $line->{NUMBER},
+               ': label "', $label, '" not recognised.';
+      next LINE;
+    }
+
+    $prefix = uc $prefix;
+    if ($prefix eq $cfg_label{TYPE}) {
+      # Type label of source file
+      $srcfile->type (uc $value);
+      $srcfile->scan (0) if $srcfile->is_type (qw/BINARY LIB/);
+      next LINE;
+
+    } elsif ($prefix eq $cfg_label{SCAN}) {
+      # Scan original file for dependency?
+      $srcfile->scan ($value);
+      next LINE;
+
+    } elsif ($prefix eq $cfg_label{TARGET}) {
+      # Name of build target for this source file
+      $srcfile->exebase ($value);
+      next LINE;
+
+    } elsif ($prefix eq $cfg_label{INTNAME}) {
+      # Program unit name of this source file
+      $srcfile->progname ($value);
+      next LINE;
+
+    } elsif ($prefix eq $cfg_label{DEP}) {
+      # Dependency of this source file
+      my ($type, $target) = split /::/, $value;
+      $srcfile->add_dep ($target, uc $type);
+      next LINE;
+
+    } else {
+      w_report 'Warning: ', $line->{SRC}, ': LINE ', $line->{NUMBER},
+               ': label "', $label, '" not recognised.';
+      next LINE;
+    }
+  }
+
+  return 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $package->scan_dependency ();
+#   $package->scan_dependency (HEADER_ONLY => 1);
+#
+# DESCRIPTION
+#   This method scans the dependency in each source file in this source
+#   package and updates the package dependency cache. If HEADER_ONLY is
+#   specified, it performs dependency scan for pre-processor headers only if
+#   this source package requires pre-processing.
+# ------------------------------------------------------------------------------
+
+sub scan_dependency {
+  my $self = shift;
+  my %args = @_;
+
+  # Search for include header dependencies only
+  my $header_only = exists $args{HEADER_ONLY} ? $args{HEADER_ONLY} : 0;
+
+  # Get list of source files
+  # If header dependencies only, only consider FPP, C and CPP files
+  my @srcfiles = $header_only
+                 ? grep {$_->is_type_or (qw/FPP C CPP/)} $self->srcfile
+                 : grep {$_->type} $self->srcfile;
+  return unless @srcfiles;
+
+  # Location of the cache
+  my @cachepath = @{ $self->config->setting (qw/PATH CACHE/) };
+  my $cachebase = $header_only
+                  ? $self->_cache_basename ('PCKPPDEPEND')
+                  : $self->_cache_basename ('PCKDEPEND');
+  my $cachefile = find_file_in_path ($cachebase, \@cachepath);
+
+  # Obtain old dependency information from cache file if it exists
+  my %dep     = ();
+  my %intname = ();
+
+  if ($cachefile) {
+    # Read the cache
+    my $cfg = Fcm::CfgFile->new (CONFIG => $self->config, SRC => $cachefile);
+    $cfg->read_cfg;
+    my @lines = $cfg->lines;
+
+    # Get list of source file base names
+    my %srcfilebase;
+    for (@srcfiles) {
+      my $base = $_->ppsrc ? $_->ppbase : $_->base;
+      $srcfilebase{$base} = 1;
+    }
+
+    for my $line (@lines) {
+      next unless $line->{LABEL};
+
+      # Label is either INTNAME or a dependency type name
+      # For INTNAME, value is the program unit name
+      # Otherwise, value is file::dependency
+      my $type = $line->{LABEL};
+      (my $file, my $depend) = split /::/, $line->{VALUE};
+
+      # Make sure $file exists in the list of source file base names
+      next unless exists $srcfilebase{$file};
+
+      if ($type eq 'INTNAME') {
+        $intname{$file} = $depend;
+
+      } else {
+        $dep{$file}{$depend} = $type;
+      }
+    }
+  }
+
+  # If a source file is newer than the cache file, re-scan dependency for that
+  # source file.
+  my $uptodate        = $cachefile ? 1 : 0;
+  my $cachefile_mtime = $cachefile ? (stat $cachefile) [9] : undef;
+  my $count           = 0;
+
+  for my $srcfile (@srcfiles) {
+    # Check modified time of source file
+    my $srcfile_mtime = $srcfile->mtime;
+
+    # If a package config file exists and it affects the source file,
+    # compare its timestamp with that of the source file
+    if ($srcfile->pckcfg) {
+      $srcfile_mtime = $self->cfg->mtime if not defined $srcfile_mtime;
+      $srcfile_mtime = ($self->cfg->mtime > $srcfile_mtime) ? $self->cfg->mtime
+                                                            : $srcfile_mtime;
+    }
+
+    # For files requiring PP, must re-scan if PP option has changed
+    my $rescan = ($self->newpp and $srcfile->is_type_or (qw/FPP C/)) ? 1 : 0;
+
+    if ($cachefile_mtime and $cachefile_mtime > $srcfile_mtime and ! $rescan) {
+      # No need to re-scan dependency, read dependency from cache
+      my $base = ($srcfile->ppsrc ? $srcfile->ppbase : $srcfile->base);
+
+      $srcfile->progname ($intname{$base}) if $intname{$base};
+      $srcfile->dep ($dep{$base})          if $dep{$base};
+
+    } else {
+      # Rescan dependency
+      $srcfile->progname (undef);
+      my $rc = $srcfile->scan_dependency (HEADER_ONLY => $header_only);
+      my %dp = $srcfile->dep;
+
+      # Get list of dependencies for updating the cache
+      my $base = ($srcfile->ppsrc ? $srcfile->ppbase : $srcfile->base);
+
+      $intname{$base} = $srcfile->progname;
+      $dep    {$base} = \%dp;
+
+      $uptodate = 0;
+      $count++ if $rc;
+    }
+  }
+
+  # Output diagnostic, if necessary
+  if ($self->config->verbose > 1 and $count) {
+    my $out =  $self->name . ': scanned ' . $count . ' file(s) for';
+    $out   .= ' header' if $header_only;
+    $out   .= ' dependency' . "\n";
+    print $out;
+  }
+
+  # Check whether package config file is newer than the dependency cache
+  if ($uptodate and $self->cfg) {
+    $uptodate = $cachefile_mtime > $self->cfg->mtime ? 1 : 0;
+  }
+
+  if (not $uptodate) {
+    # Update dependency cache file
+    my $cfg = Fcm::CfgFile->new (CONFIG => $self->config);
+
+    # Program unit name of source files
+    for my $file (keys %intname) {
+      next unless $intname{$file};
+
+      $cfg->add_line (
+        LABEL => 'INTNAME',
+        VALUE => $file . '::' . $intname{$file},
+      );
+    }
+
+    # Dependencies of source files
+    for my $file (keys %dep) {
+      for my $depend (keys %{ $dep{$file} }) {
+        $cfg->add_line (
+          LABEL => $dep{$file}{$depend},
+          VALUE => $file . '::' . $depend,
+        );
+      }
+    }
+
+    # Create an empty config file if no dependency in this source package
+    $cfg->add_line unless $cfg->lines;
+
+    # Write to config file
+    my $outfile = catfile $cachepath[0], $cachebase;
+    $cfg->print_cfg ($outfile);
+  }
+
+  return not $uptodate;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = $package->makerule_uptodate ();
+#
+# DESCRIPTION
+#   This method returns true if the make rule file for this source package
+#   is up to date.
+# ------------------------------------------------------------------------------
+
+sub makerule_uptodate {
+  my $self = shift;
+
+  my $return = 0;
+
+  if (not $self->newpp) {
+    # Check whether a Make rule file already exists
+    my $mkbase = $self->name . $self->config->setting (qw/OUTFILE_EXT MK/);
+    my $mkfile = find_file_in_path (
+      $mkbase,
+      $self->config->setting (qw/PATH BLD/),
+    );
+
+    # Check location of source package file type cache
+    my $pckfile = find_file_in_path (
+      $self->_cache_basename ('PCKFILE'),
+      $self->config->setting (qw/PATH CACHE/),
+    );
+
+    # Check location of source package dependency cache
+    my $pckdepend = find_file_in_path (
+      $self->_cache_basename ('PCKDEPEND'),
+      $self->config->setting (qw/PATH CACHE/),
+    );
+
+    # If make rule file exists, determine whether it is out of date
+    if ($pckdepend) {
+      if ($mkfile) {
+        my $pckfile_mt   = (stat $pckfile)  [9];
+        my $pckdepend_mt = (stat $pckdepend)[9];
+        my $mkfile_mt    = (stat $mkfile)   [9];
+
+        $return = 1 if $mkfile_mt >= $pckdepend_mt and $mkfile_mt >= $pckfile_mt;
+      }
+
+    } else {
+      $return = 1; # No cache file, no need to have a make rule
+    }
+  }
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $package->write_makerule ();
+#
+# DESCRIPTION
+#   This method writes to the I<Make> rule file of the current source package.
+# ------------------------------------------------------------------------------
+
+sub write_makerule {
+  my $self = shift;
+
+  # Package Make rule header
+  my $mk = '# Automatic Make rule for ' . $self->name . "\n\n";
+
+  # Set up variable for directory name
+  # if package name contains only word characters
+  my @searchpath   = $self->searchpath;
+  my @ppsearchpath = $self->ppsearchpath;
+
+  if ($self->name =~ /^\w+$/) {
+    # Package search path
+    my %path = (SRCDIR => \@searchpath, PPSRCDIR => \@ppsearchpath);
+
+    for my $key (keys %path) {
+      my $count = 0;
+      my @dirs  = @{ $path{$key} };
+
+      for my $i (0 .. $#dirs) {
+        next unless -d $dirs[$i];
+        $mk .= $key . $i . '__' . $self->name . ' = ' . $dirs[$i] . "\n";
+        $count++;
+      }
+
+      $mk .= "\n" if $count;
+    }
+  }
+
+  my $mk_out;
+
+  # Make rules for copying data files, if necessary
+  {
+    # Get a list of files with no associated type
+    my @files = grep {not $_->type} @{ $self->{SRCFILE} };
+
+    if (@files) {
+      my $target = $self->name . $self->config->setting (qw/OUTFILE_EXT ETC/);
+      $mk_out .= $target . ' :';
+
+      # Depends on all un-typed source files
+      my $nl = " \\\n" . ' ' x 10;
+      for my $file (@files) {
+        my $dir = $file->dir;
+
+        # Use variable for directory name
+        # if package name contains only word characters
+        if ($self->name =~ /^\w+$/) {
+          for my $i (0 .. $#searchpath) {
+            if ($dir eq $searchpath[$i]) {
+              $dir = '$(SRCDIR' . $i . '__' . $self->name . ')';
+              last;
+            }
+          }
+        }
+
+        $mk_out .= $nl . catfile ($dir, $file->base);
+      }
+
+      # Depends on dummy copy file, so there will be no dependency inheritance
+      $mk_out .= $nl . $self->config->setting (qw/MISC CPDUMMY/);
+
+      # Actions for target
+      $mk_out .= "\n";
+      $mk_out .= "\t" . 'cp $^ $(FCM_ETCDIR)' . "\n";
+      $mk_out .= "\t" . 'touch ' . catfile ('$(FCM_DONEDIR)', '$@') . "\n";
+
+      $mk_out .= "\n";
+    }
+  }
+
+  # Make rules for source files
+  my @srcfiles = grep {$_->type} @{ $self->{SRCFILE} };
+  for my $srcfile (@srcfiles) {
+    $mk_out .= $srcfile->write_makerules;
+  }
+
+  # Write make rule file only if necessary
+  if ($mk_out) {
+    $mk .= $mk_out;
+
+    # Write to output file
+    my $mkbase = $self->name . $self->config->setting (qw/OUTFILE_EXT MK/);
+    my $blddir = ${ $self->config->setting (qw/PATH BLD/) }[0];
+    my $mkfile = catfile $blddir, $mkbase;
+
+    if (not -d $blddir) {
+      print 'Make directory: ', $blddir, "\n" if $self->config->verbose > 1;
+      mkpath $blddir or croak $blddir, ': cannot create directory, abort';
+    }
+
+    open OUT, '>', $mkfile
+      or croak 'Cannot open "', $mkfile, '" (', $!, '), abort';
+    print OUT $mk;
+    close OUT or croak 'Cannot close "', $mkfile, '" (', $!, '), abort';
+
+    print 'Generated: ', $mkfile, "\n" if $self->config->verbose > 1;
+
+    return 1;
+
+  } else {
+    return 0;
+  }
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/lib/Fcm/Timer.pm
===================================================================
--- LMDZ5/branches/testing/tools/fcm/lib/Fcm/Timer.pm	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/lib/Fcm/Timer.pm	(revision 1665)
@@ -0,0 +1,73 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::Timer
+#
+# DESCRIPTION
+#   This is a package of timer utility used by the FCM command.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::Timer;
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Exports
+our (@ISA, @EXPORT, @EXPORT_OK);
+
+sub timestamp_command;
+
+require Exporter;
+@ISA = qw(Exporter);
+@EXPORT = qw(timestamp_command);
+
+# ------------------------------------------------------------------------------
+
+# Module level variables
+my %cmd_start_time = (); # Command start time, (key = command, value = time)
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = &Fcm::Timer::timestamp_command ($command[, $status]);
+#
+# DESCRIPTION
+#   This function returns a string adding to $command a prefix according the
+#   value of $status. If $status is not specified or does not match the word
+#   "end", the status is assumed to be "start". At "start", the prefix will
+#   contain the current timestamp. If $status is the word "end", the prefix
+#   will contain the total time taken since this function was called with the
+#   same $command at the "start" status.
+# ------------------------------------------------------------------------------
+
+sub timestamp_command {
+  (my $command, my $status) = @_;
+
+  my $prefix;
+  if ($status and $status =~ /end/i) {
+    # Status is "end", insert time taken
+    my $lapse = time () - $cmd_start_time{$command};
+    $prefix = sprintf "# Time taken: %12d s=> ", $lapse;
+
+  } else {
+    # Status is "start", insert time stamp
+    $cmd_start_time{$command} = time;
+
+    (my $sec, my $min, my $hour, my $mday, my $mon, my $year) = localtime;
+    $prefix = sprintf "# Start: %04d-%02d-%02d %02d:%02d:%02d=> ",
+              $year + 1900, $mon + 1, $mday, $hour, $min, $sec;
+  }
+
+  return $prefix . $command . "\n";
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/lib/Fcm/Util.pm
===================================================================
--- LMDZ5/branches/testing/tools/fcm/lib/Fcm/Util.pm	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/lib/Fcm/Util.pm	(revision 1665)
@@ -0,0 +1,848 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   Fcm::Util
+#
+# DESCRIPTION
+#   This is a package of misc utilities used by the FCM command.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+package Fcm::Util;
+
+# Standard pragma
+use warnings;
+use strict;
+
+# Exports
+our (@ISA, @EXPORT, @EXPORT_OK);
+
+sub expand_rev_keyword;
+sub expand_tilde;
+sub expand_url_keyword;
+sub e_report;
+sub find_srcdir;
+sub find_file_in_path;
+sub get_browser_url;
+sub get_command_string;
+sub get_rev_of_wc;
+sub get_rev_keyword;
+sub get_url_of_wc;
+sub get_url_keyword;
+sub get_wct;
+sub is_url;
+sub is_wc;
+sub print_command;
+sub run_command;
+sub svn_date;
+sub touch_file;
+sub w_report;
+
+require Exporter;
+@ISA = qw(Exporter);
+@EXPORT = qw(
+  expand_rev_keyword
+  expand_tilde
+  expand_url_keyword
+  e_report
+  find_srcdir
+  find_file_in_path
+  get_browser_url
+  get_command_string
+  get_rev_of_wc
+  get_rev_keyword
+  get_url_of_wc
+  get_url_keyword
+  get_wct
+  is_url
+  is_wc
+  print_command
+  run_command
+  svn_date
+  touch_file
+  w_report
+);
+
+# Standard modules
+use Carp;
+use Cwd;
+use File::Basename;
+use File::Find;
+use File::Path;
+use File::Spec;
+use POSIX qw/strftime/;
+
+# FCM component modules
+use Fcm::Timer;
+
+# ------------------------------------------------------------------------------
+
+# Module level variables
+my %svn_info       = (); # "svn info" log, (key1 = path,
+                         # key2 = URL, Revision, Last Changed Rev)
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   %srcdir = &Fcm::Util::find_srcdir ($topdir, $toppck, $join);
+#
+# DESCRIPTION
+#   Search $topdir for sub-directories containing regular files. Returns a hash
+#   with each key/value pair assigned to a unique name of the source directory
+#   and the location of the source directory. If $toppck is set the name of
+#   each source directory will be prefixed with this package name, and the
+#   search may include the $topdir in the result. If $join is set, the name of
+#   the sub-package will use $join as the delimiter of packages. Otherwise, the
+#   default double underscore '__' will be used.  Please note that all
+#   directories beginning with a ".", i.e. hidden directories, are ignored.
+# ------------------------------------------------------------------------------
+
+sub find_srcdir {
+  (my $topdir, my $toppck, my $join) = @_;
+  $join = defined ($join) ? $join : '__';
+
+  my @dirs = ();
+
+  # Locate all source directories containing regular files
+  if (-d $topdir) {
+    find (
+      sub {
+        my $dir = $File::Find::name;
+        return 0 if $dir eq $topdir and not $toppck;
+
+        if (-d $dir) {
+          # Ignore sub-directories with names beginning with .
+          if ($dir ne $topdir) {
+            my $subdir = substr ($dir, length ($topdir) + 1);
+            return 0 if grep {m/^\./} File::Spec->splitdir ($subdir);
+          }
+
+          # Read contents of directory
+          opendir DIR, $dir;
+          my @files = readdir 'DIR';
+          closedir DIR;
+
+          # Check if the directory contains one or more source file
+          my $contain_src;
+          for my $file (@files) {
+            next if $file =~ /^\./; # ignore hidden file
+
+            if (-f File::Spec->catfile ($dir, $file)) {
+              $contain_src = 1;
+              last;
+            }
+          }
+
+          push @dirs, $dir if $contain_src;
+          return 1;
+
+        } else {
+          return 0;
+        }
+      },
+
+      $topdir,
+    );
+  }
+
+  # String length of src directory name
+  my $topdir_len = length $topdir;
+
+  # Assign new source directories to current build
+  my @pck    = $toppck ? split (/$join/, $toppck) : ();
+  my %srcdir = ();
+  for my $dir (@dirs) {
+    my $name = ($dir eq $topdir) ? '' : substr $dir, $topdir_len + 1;
+    my @path = File::Spec->splitdir ($name);
+    my $key  = join $join, (@pck, @path);
+
+    $srcdir{$key} = $dir;
+  }
+
+  return %srcdir;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   %srcdir = &Fcm::Util::find_file_in_path ($file, \@path);
+#
+# DESCRIPTION
+#   Search $file in @path. Returns the full path of the $file if it is found
+#   in @path. Returns "undef" if $file is not found in @path.
+# ------------------------------------------------------------------------------
+
+sub find_file_in_path {
+  my ($file, $path) = @_;
+
+  for my $dir (@$path) {
+    my $full_file = File::Spec->catfile ($dir, $file);
+    return $full_file if -e $full_file;
+  }
+
+  return undef;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $expanded_path = &Fcm::Util::expand_tilde ($path);
+#
+# DESCRIPTION
+#   Returns an expanded path if $path is a path that begins with a tilde (~).
+# ------------------------------------------------------------------------------
+
+sub expand_tilde {
+  my $file = $_[0];
+
+  $file =~ s#^~([^/]*)#$1 ? (getpwnam $1)[7] : ($ENV{HOME} || $ENV{LOGDIR})#ex;
+
+  return $file;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $rc = &Fcm::Util::touch_file ($file);
+#
+# DESCRIPTION
+#   Touch $file if it exists. Create $file if it does not exist. Return 1 for
+#   success or 0 otherwise.
+# ------------------------------------------------------------------------------
+
+sub touch_file {
+  my $file = $_[0];
+  my $rc   = 1;
+
+  if (-e $file) {
+    my $now = time;
+    $rc = utime $now, $now, $file;
+
+  } else {
+    mkpath dirname ($file) unless -d dirname ($file);
+
+    $rc = open FILE, '>', $file;
+    $rc = close FILE if $rc;
+  }
+
+  return $rc;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $new_url = &Fcm::Util::expand_url_keyword (URL => $url[, CFG => $cfg]);
+#
+# DESCRIPTION
+#   Expand URL if its begins with a pre-defined pattern followed by a keyword
+#   that can be found in the setting of CFG. If URL is a genuine URL, the
+#   function also attempts to expand any . or .. in the path. If CFG is not
+#   set, it defaults to &main::cfg.
+# ------------------------------------------------------------------------------
+
+sub expand_url_keyword {
+  my %args = @_;
+  my $url  = $args{URL};
+  my $cfg  = exists $args{CFG} ? $args{CFG} : &main::cfg;
+
+  # Prefix for URL keyword
+  my $prefix = $cfg->setting (qw/MISC EXPURL_PREFIX/);
+
+  # Pattern for URL keyword
+  my $pattern = '^' . $prefix . '([^/]+)';
+
+  # Standard suffix for URL keyword
+  my %suffix_value = (tr => 'trunk', br => 'branches', tg => 'tags');
+
+  # URL matches pattern?
+  if ($url =~ /$pattern/) {
+    my $keyword = $1;
+
+    # Determine whether keyword is registered.
+    my $keyval = $cfg->setting ('URL', uc ($keyword));
+
+    if ((not $keyval) and $keyword =~ s/[-_](tr|br|tg)$//) {
+      # Keyword is not registered, but it matches a standard suffix
+      my $suffix = $suffix_value{$1};
+
+      $keyval = $cfg->setting ('URL', uc ($keyword)) . '/' . $suffix
+        if $cfg->setting ('URL', uc ($keyword));
+    }
+
+    # Expand if keyword is registered
+    $url =~ s/$pattern/$keyval/ if $keyval;
+  }
+
+  # Expand . and ..
+  if (&is_url ($url)) {
+    while ($url =~ s#/+\.(?:/+|$)#/#g) {next}
+    while ($url =~ s#/+[^/]+/+\.\.(?:/+|$)#/#g) {next}
+  }
+
+  return $url;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = &Fcm::Util::get_url_keyword (URL => $url[, CFG => $cfg]);
+#
+# DESCRIPTION
+#   Return a FCM URL keyword if URL matches a registered project URL or undef
+#   otherwise. If CFG is not set, it defaults to &main::cfg.
+# ------------------------------------------------------------------------------
+
+sub get_url_keyword {
+  my %args = @_;
+  my $url  = $args{URL};
+  my $cfg  = exists $args{CFG} ? $args{CFG} : &main::cfg;
+
+  my $return;
+
+  for my $key (%{ $cfg->setting ('URL') }) {
+    my $value = $cfg->setting ('URL', $key);
+    next unless defined $value;
+    next unless $url =~ s#^$value(?:/+|$)##;
+
+    $return = $cfg->setting (qw/MISC EXPURL_PREFIX/) . $key .
+              ($url ? '/' . $url : '');
+    last;
+  }
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $new_rev = &Fcm::Util::expand_rev_keyword (
+#     REV  => $rev,
+#     URL  => $url,
+#    [HEAD => $flag,]
+#    [CFG  => $cfg,]
+#  );
+#
+# DESCRIPTION
+#   Expand REV if URL is a known URL in CFG setting and REV matches a revision
+#   keyword of this URL, or if REV is "HEAD". SVN revision numbers, date and
+#   other keywords are ignored. HEAD should only be specified if REV has the
+#   value "HEAD". If HEAD is specified and is true, the return value of the
+#   function will be the operative revision number of the HEAD revision.
+#   Otherwise, the last commit revision will be returned. If CFG is not set,
+#   it defaults to &main::cfg.
+# ------------------------------------------------------------------------------
+
+sub expand_rev_keyword {
+  my %args = @_;
+  my $rev  = $args{REV};
+  my $url  = $args{URL};
+  my $head = exists $args{HEAD} ? $args{HEAD} : undef;
+  my $cfg  = exists $args{CFG } ? $args{CFG } : &main::cfg;
+
+  if (uc ($rev) eq 'HEAD') {
+    # Expand HEAD revision
+    &_invoke_svn_info (PATH => $url, CFG => $cfg) unless exists $svn_info{$url};
+    my $expanded_rev = $head
+                     ? $svn_info{$url}{Revision}
+                     : $svn_info{$url}{'Last Changed Rev'};
+
+    &w_report ($url, ': cannot determine HEAD revision.')
+      if $cfg->verbose > 1 and not $expanded_rev;
+
+    $rev = $expanded_rev if $expanded_rev;
+
+  } elsif ($rev !~ /^(?:\d+|BASE|COMMITTED|PREV|\{.+\})$/i) {
+    # Expand revision keyword, if required
+
+    # Get configuration settings
+    my %keywords  = %{ $cfg->setting (qw/REVISION/) };
+    my $separator = $cfg->setting (qw/MISC DIR_SEPARATOR/);
+
+    my $name      = '';
+
+    # Find out whether URL matches a registered repository
+    for my $keyword (keys %keywords) {
+      my $repos = $cfg->setting ('URL', uc ($keyword));
+      next unless $repos;
+
+      if ($url =~ m#^$repos(?:$separator|$)#) {
+        $name = $keyword;
+        last;
+      }
+    }
+
+    # If revision keyword exists for the registered repository, expand it
+    if ($name and exists $keywords{$name}{uc ($rev)}) {
+      $rev = $keywords{$name}{uc ($rev)};
+
+    } else {
+      &e_report (
+        $rev, ': revision keyword not found for ', $url,
+        ' in FCM configuration file, abort.',
+      );
+    }
+  }
+
+  return $rev;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $keyword = Fcm::Util::get_rev_keyword (
+#     REV => $rev,
+#     URL => $url,
+#    [CFG => $cfg,]
+#  );
+#
+# DESCRIPTION
+#   Returns a revision keyword if URL is a known URL in CFG setting and REV is
+#   a revision number that matches a revision keyword of this URL. Otherwise,
+#   it returns REV unchanged. If CFG is not set, it defaults to &main::cfg.
+# ------------------------------------------------------------------------------
+
+sub get_rev_keyword {
+  my %args = @_;
+  my $rev  = $args{REV};
+  my $url  = $args{URL};
+  my $cfg  = exists $args{CFG} ? $args{CFG} : &main::cfg;
+
+  if ($rev =~ /^\d+$/) {
+    # Get revision keyword, if REV is a revision number
+
+    # Get configuration settings
+    my %keywords  = %{ $cfg->setting (qw/REVISION/) };
+    my $separator = $cfg->setting (qw/MISC DIR_SEPARATOR/);
+
+    my $name      = '';
+
+    # Find out whether URL matches a registered repository
+    for my $keyword (keys %keywords) {
+      my $repos = $cfg->setting ('URL', uc ($keyword));
+      next unless $repos;
+
+      if ($url =~ m#^$repos(?:$separator|$)#) {
+        $name = $keyword;
+        last;
+      }
+    }
+
+    # If revision keyword for REV exists for the registered repository, get it
+    if ($name and exists $keywords{$name} and ref $keywords{$name} eq 'HASH') {
+      for my $key (keys %{ $keywords{$name} }) {
+        if ($rev eq $keywords{$name}{$key}) {
+          $rev = $key;
+          last;
+        }
+      }
+    }
+  }
+
+  return $rev;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $browser_url = Fcm::Util::get_browser_url (
+#     URL => $url,
+#    [CFG => $cfg,]
+#  );
+#
+# DESCRIPTION
+#   Returns a web address for browsing URL from Trac if URL is a known URL in
+#   CFG setting, and that it is a matching web address. Otherwise, it returns
+#   "undef". If CFG is not set, it defaults to &main::cfg.
+# ------------------------------------------------------------------------------
+
+sub get_browser_url {
+  my %args        = @_;
+  my $url         = $args{URL};
+  my $cfg         = exists $args{CFG} ? $args{CFG} : &main::cfg;
+  my $browser_url = undef;
+
+  # Get configuration settings
+  my %keywords  = %{ $cfg->setting (qw/TRAC/) };
+  my $separator = $cfg->setting (qw/MISC DIR_SEPARATOR/);
+
+  my $name  = '';
+  my $trail = '';
+
+  # Find out whether URL matches a registered repository
+  for my $keyword (keys %keywords) {
+    my $repos = $cfg->setting ('URL', uc ($keyword));
+    next unless $repos;
+
+    if ($url =~ m#^$repos(?:$separator(.*$)|$)#) {
+      $name  = $keyword;
+      $trail = $1 if $1;
+      last;
+    }
+  }
+
+  # If TRAC web address exists for the registered repository, get it
+  if ($name and exists $keywords{$name}) {
+    $browser_url  = $keywords{$name};
+    $browser_url .= $separator . $trail if $trail;
+  }
+
+  return $browser_url;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = &is_wc ([$path]);
+#
+# DESCRIPTION
+#   Returns true if current working directory (or $path) is a Subversion
+#   working copy.
+# ------------------------------------------------------------------------------
+
+sub is_wc {
+  my $path = @_ ? $_[0] : cwd ();
+
+  if (-d $path) {
+    return (-e File::Spec->catfile ($path, qw/.svn format/)) ? 1 : 0;
+
+  } elsif (-f $path) {
+    return (-e File::Spec->catfile (dirname ($path), qw/.svn format/)) ? 1 : 0;
+
+  } else {
+    return 0;
+  }
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $flag = &is_url ($url);
+#
+# DESCRIPTION
+#   Returns true if $url is a URL.
+# ------------------------------------------------------------------------------
+
+sub is_url {
+  # This should handle URL beginning with svn://, http:// and svn+ssh://
+  return ($_[0] =~ m#^[\+\w]+://#);
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = &get_wct ([$dir]);
+#
+# DESCRIPTION
+#   If current working directory (or $dir) is a Subversion working copy,
+#   returns the top directory of this working copy; otherwise returns an empty
+#   string.
+# ------------------------------------------------------------------------------
+
+sub get_wct {
+  my $dir = @_ ? $_[0] : cwd ();
+
+  return '' if not &is_wc ($dir);
+
+  my $updir = dirname $dir;
+  while (&is_wc ($updir)) {
+    $dir   = $updir;
+    $updir = dirname $dir;
+    last if $updir eq $dir;
+  }
+
+  return $dir;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = &get_url_of_wc ([$path[, $refresh]]);
+#
+# DESCRIPTION
+#   If current working directory (or $path) is a Subversion working copy,
+#   returns the URL of the associated Subversion repository; otherwise returns
+#   an empty string. If $refresh is specified, do not use the cached
+#   information.
+# ------------------------------------------------------------------------------
+
+sub get_url_of_wc {
+  my $path    = @_ ? $_[0] : cwd ();
+  my $refresh = exists $_[1] ? $_[1] : 0;
+  my $url  = '';
+
+  if (&is_wc ($path)) {
+    delete $svn_info{$path} if $refresh;
+    &_invoke_svn_info (PATH => $path) unless exists $svn_info{$path};
+    $url = $svn_info{$path}{URL};
+  }
+
+  return $url;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &_invoke_svn_info (PATH => $path, [CFG => $cfg]);
+#
+# DESCRIPTION
+#   The function is internal to this module. It invokes "svn info" on $path to
+#   gather information on URL, Revision and Last Changed Rev. The information
+#   is stored in a hash table at the module level, so that the information can
+#   be re-used. If CFG is not set, it defaults to &main::cfg.
+# ------------------------------------------------------------------------------
+
+sub _invoke_svn_info {
+  my %args = @_;
+  my $path = $args{PATH};
+  my $cfg  = exists $args{CFG} ? $args{CFG} : &main::cfg;
+
+  return if exists $svn_info{$path};
+
+  # Invoke "svn info" command
+  my @info = &run_command (
+    [qw/svn info/, $path],
+    PRINT => $cfg->verbose > 2, METHOD => 'qx', DEVNULL => 1, ERROR => 'ignore',
+  );
+  for (@info) {
+    chomp;
+
+    if (/^(URL|Revision|Last Changed Rev):\s*(.+)$/) {
+      $svn_info{$path}{$1} = $2;
+    }
+  }
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $string = &get_command_string ($cmd);
+#   $string = &get_command_string (\@cmd);
+#
+# DESCRIPTION
+#   The function returns a string by converting the list in @cmd or the scalar
+#   $cmd to a form, where it can be executed as a shell command.
+# ------------------------------------------------------------------------------
+
+sub get_command_string {
+  my $cmd    = $_[0];
+  my $return = '';
+
+  if (ref ($cmd) and ref ($cmd) eq 'ARRAY') {
+    # $cmd is a reference to an array
+
+    # Print each argument
+    for my $i (0 .. @{ $cmd } - 1) {
+      my $arg = $cmd->[$i];
+
+      $arg =~ s/./*/g if $i > 0 and $cmd->[$i - 1] eq '--password';
+
+      if ($arg =~ /[\s'"*?]/) {
+        # Argument contains a space, quote it
+        if (index ($arg, "'") >= 0) {
+          # Argument contains an apostrophe, quote it with double quotes
+          $return .= ($i > 0 ? ' ' : '') . '"' . $arg . '"';
+
+        } else {
+          # Otherwise, quote argument with apostrophes
+          $return .= ($i > 0 ? ' ' : '') . "'" . $arg . "'";
+        }
+
+      } else {
+        # Argument does not contain a space, just print it
+        $return .= ($i > 0 ? ' ' : '') . ($arg eq '' ? "''" : $arg);
+      }
+    }
+
+  } else {
+    # $cmd is a scalar, just print it "as is"
+    $return = $cmd;
+  }
+
+  return $return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &print_command ($cmd);
+#   &print_command (\@cmd);
+#
+# DESCRIPTION
+#   The function prints the list in @cmd or the scalar $cmd, as it would be
+#   executed by the shell.
+# ------------------------------------------------------------------------------
+
+sub print_command {
+  my $cmd = $_[0];
+
+  print '=> ', &get_command_string ($cmd) , "\n";
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   @return = &run_command (\@cmd, <OPTIONS>);
+#   @return = &run_command ($cmd , <OPTIONS>);
+#
+# DESCRIPTION
+#   This function executes the command in the list @cmd or in the scalar $cmd.
+#   The remaining are optional arguments in a hash table. Valid options are
+#   listed below. If the command is run using "qx", the function returns the
+#   standard output from the command. If the command is run using "system", the
+#   function returns true on success. By default, the function dies on failure.
+#
+# OPTIONS
+#   METHOD  => $method - this can be "system", "exec" or "qx". This determines
+#                        how the command will be executed. If not set, the
+#                        default is to run the command with "system".
+#   PRINT   => 1       - if set, print the command before executing it.
+#   ERROR   => $flag   - this should only be set if METHOD is set to "system"
+#                        or "qx". The $flag can be "die" (default), "warn" or
+#                        "ignore". If set to "die", the function dies on error.
+#                        If set to "warn", the function issues a warning on
+#                        error, and the function returns false. If set to
+#                        "ignore", the function returns false on error.
+#   RC      => 1       - if set, must be a reference to a scalar, which will be
+#                        set to the return code of the command.
+#   DEVNULL => 1       - if set, re-direct STDERR to /dev/null before running
+#                        the command.
+#   TIME    => 1       - if set, print the command with a timestamp before
+#                        executing it, and print the time taken when it
+#                        completes. This option supersedes the PRINT option.
+# ------------------------------------------------------------------------------
+
+sub run_command {
+  my $cmd     = shift;
+  my %options = @_;
+  my $method  = exists $options{METHOD}  ? $options{METHOD}  : 'system';
+  my $print   = exists $options{PRINT}   ? $options{PRINT}   : undef;
+  my $error   = exists $options{ERROR}   ? $options{ERROR}   : 'die';
+  my $rc      = exists $options{RC}      ? $options{RC}      : undef;
+  my $devnull = exists $options{DEVNULL} ? $options{DEVNULL} : undef;
+  my $time    = exists $options{TIME}    ? $options{TIME}    : undef;
+  my @return  = ();
+
+  # Check that the $error flag is set correctly
+  $error = 'die' unless $error =~ /^(?:die|warn|ignore)$/i;
+
+  # Print the command before execution, if necessary
+  if ($time) {
+    print &timestamp_command (&get_command_string ($cmd));
+
+  } elsif ($print) {
+    &print_command ($cmd);
+  }
+
+  # Re-direct to /dev/null if necessary
+  if ($devnull) {
+    $devnull = File::Spec->devnull;
+
+    # Save current STDERR
+    no warnings;
+    open OLDERR, ">&STDERR" or croak 'Cannot dup STDERR (', $!, '), abort';
+    use warnings;
+
+    # Redirect STDERR to /dev/null
+    open STDERR, '>', $devnull
+      or croak 'Cannot redirect STDERR (', $!, '), abort';
+
+    # Make sure the channels are unbuffered
+    my $select = select;
+    select STDERR; $| = 1;
+    select $select;
+  }
+
+  if (ref ($cmd) and ref ($cmd) eq 'ARRAY') {
+    # $cmd is an array
+    my @command = @{ $cmd };
+
+    if ($method eq 'qx') {
+      @return = qx(@command);
+
+    } elsif ($method eq 'exec') {
+      exec (@command);
+
+    } else {
+      system (@command);
+      @return = $? ? () : (1);
+    }
+
+  } else {
+    # $cmd is an scalar
+    if ($method eq 'qx') {
+      @return = qx($cmd);
+
+    } elsif ($method eq 'exec') {
+      exec ($cmd);
+
+    } else {
+      system ($cmd);
+      @return = $? ? () : (1);
+    }
+  }
+
+  # Put STDERR back to normal, if redirected previously
+  if ($devnull) {
+    close STDERR;
+
+    open STDERR, ">&OLDERR" or croak 'Cannot dup STDERR (', $!, '), abort';
+  }
+
+  # Print the time taken for command after execution, if necessary
+  print &timestamp_command (&get_command_string ($cmd), 'end') if $time;
+
+  if ($?) {
+    # The command has failed
+    if ($error eq 'die') {
+      # Throw fatal error if ERROR is set to "die"
+      croak &get_command_string ($cmd), ' failed (', $?, ')';
+
+    } elsif ($error eq 'warn') {
+      # Issue warning if ERROR is set to "warn"
+      carp  &get_command_string ($cmd), ' failed (', $?, ')';
+    }
+  }
+
+  # Set the return code if necessary
+  $$rc = $? if $rc;
+
+  return @return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &e_report (@message);
+#
+# DESCRIPTION
+#   The function prints @message to STDERR and aborts with a error.
+# ------------------------------------------------------------------------------
+
+sub e_report {
+  print STDERR @_, "\n" if @_;
+
+  exit 1;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   &w_report (@message);
+#
+# DESCRIPTION
+#   The function prints @message to STDERR and returns.
+# ------------------------------------------------------------------------------
+
+sub w_report {
+  print STDERR @_, "\n" if @_;
+
+  return;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   $date = &svn_date ($time);
+#
+# DESCRIPTION
+#   The function returns a date, formatted as by Subversion. The argument $time
+#   is the number of seconds since epoch.
+# ------------------------------------------------------------------------------
+
+sub svn_date {
+  my $time = shift;
+
+  return strftime ('%Y-%m-%d %H:%M:%S %z (%a, %d %b %Y)', localtime ($time));
+}
+
+# ------------------------------------------------------------------------------
+
+1;
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/templates/hook/background_updates.pl
===================================================================
--- LMDZ5/branches/testing/tools/fcm/templates/hook/background_updates.pl	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/templates/hook/background_updates.pl	(revision 1665)
@@ -0,0 +1,214 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   background_updates.pl
+#
+# SYNOPSIS
+#   background_updates.pl <repos> <logdir>
+#
+# DESCRIPTION
+#   Performs any background tasks required after each commit to the FCM
+#   respository. A lock file is used to prevent mulitple instances of this
+#   program from running.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard pragmas
+use strict;
+use warnings;
+
+# Standard modules
+use File::Basename;
+use File::Spec::Functions;
+use File::Path;
+
+# ------------------------------------------------------------------------------
+
+# Usage
+my $this = basename $0;
+
+# ------------------------------------------------------------------------------
+
+# Arguments
+my ($repos, $logdir) = @ARGV;
+die $this, ': incorrect usage' unless $repos and $logdir;
+
+# ------------------------------------------------------------------------------
+
+# Lock file
+my $lockfile = catfile ($logdir, $repos . '.lock');
+my $locked   = undef;
+
+# Do nothing if lock file exists
+if (-e $lockfile) {
+  print "$this: Found lock file ($lockfile). Exiting.\n";
+  exit;
+}
+
+# Create lock file
+open FILE, '>', $lockfile
+  or die $this, ': unable to create lock file ', $lockfile;
+close FILE;
+$locked = 1;
+
+# ------------------------------------------------------------------------------
+
+my $wc_main      = '/home/h03/fcm/FCM/work/FCM';   # Location of main working copy
+my $wc_admin     = '/home/h03/fcm/FCM/work/Admin'; # Location of admin working copy
+
+my $install_hook = '/home/h03/fcm/FCM/work/Admin/src/utils/install_hook.pl';
+my $hooksrc_top  = '/home/h03/fcm/FCM/work/Admin/src/hook';
+my $hookdest_top = '/data/local/fcm/svn/live';
+
+my $fcm_html2pdf = '/home/h03/fcm/FCM/work/Admin/src/utils/fcm_html2pdf';
+
+my @html2pdf = (
+  {
+    PATTERN => 'doc/user_guide',
+    INPUT   => '/home/h03/fcm/FCM/work/FCM/doc/user_guide/index.html',
+    OUTPUT  => 'fcm-user-guide',
+  },
+  {
+    PATTERN => 'doc/collaboration',
+    INPUT   => '/home/h03/fcm/FCM/work/FCM/doc/collaboration/index.html',
+    OUTPUT  => 'fcm-collaboration',
+  },
+  {
+    PATTERN => 'doc/standards/fortran_standard\.html',
+    INPUT   => '/home/h03/fcm/FCM/work/FCM/doc/standards/fortran_standard.html',
+    OUTPUT  => 'fcm-fortran-standard',
+  },
+  {
+    PATTERN => 'doc/standards/perl_standard\.html',
+    INPUT   => '/home/h03/fcm/FCM/work/FCM/doc/standards/perl_standard.html',
+    OUTPUT  => 'fcm-perl-standard',
+  },
+);
+
+my @remotes      = (   # list of remote machines
+  # 1st remote machine
+  {
+    MACHINE => 'tx01',               # machine name
+    LOGNAME => 'fcm',                # logname
+    WC      => '~/FCM/work',         # working copy location
+    OPTIONS => [qw#-a -v
+                --timeout=1800
+		--exclude='.*'
+		--exclude='FCM/doc'
+		--delete-excluded#], # options to "rsync"
+  },
+
+  # 2nd remote machine, etc
+  #{
+  #  MACHINE => '',     # machine name
+  #  LOGNAME => '',     # logname
+  #  WC      => '',     # working copy location
+  #  OPTIONS => [],     # options to "rsync"
+  #},
+);
+
+$ENV{RSYNC_RSH} = 'rsh'; # Remote shell for "rsync"
+
+while (1) {
+  # Perform "svn update" on working copy of the "trunk" of the main project
+  print "$this: Updating main working copy ...\n";
+  my @update_main = qx(svn update $wc_main);
+  die $this, ': unable to update working copy of FCM/trunk' if $?;
+
+  # Perform "svn update" on working copy of the "trunk" of the Admin project
+  print "$this: Updating admin working copy ...\n";
+  my @update_admin = qx(svn update $wc_admin);
+  die $this, ': unable to update working copy of Admin/trunk' if $?;
+
+  # Remove last line from each output, which should be info of the revision
+  pop @update_main;
+  pop @update_admin;
+
+  # No updates, exit loop
+  if (not @update_main and not @update_admin) {
+    print "$this: No updates detected. Exiting.\n";
+    last;
+  }
+
+  # Set FCM release number, if necessary
+  if (@update_main) {
+    # Get last changed revision
+    my @info = qx(svn info $wc_main);
+    my $rev;
+
+    for (@info) {
+      next unless /^Last Changed Rev: (\d+)$/;
+
+      $rev = $1;
+      last;
+    }
+
+    # Update src/etc/fcm_rev
+    print "$this: updating the FCM release number file ...\n";
+    my $fcm_rev = catfile ($wc_main, 'src/etc/fcm_rev');
+    open FILE, '>', $fcm_rev or die $fcm_rev, ': cannot open';
+    print FILE $rev, "\n";
+    close FILE or die $fcm_rev, ': cannot close';
+  }
+
+  # Re-create PDF files if necessary
+  for (@html2pdf) {
+    my $pattern = $_->{PATTERN};
+    next unless grep m/$pattern/, @update_main;
+
+    print $this, ': Re-creating PDF for ', $_->{OUTPUT}, '...', "\n";
+    my @command = ($fcm_html2pdf, $_->{INPUT}, $_->{OUTPUT});
+    system @command;
+    die $this, ': unable to execute ', join (' ', @command) if $?;
+  }
+
+  # Re-install hook scripts if necessary
+  if (grep m#src/hook#, @update_admin) {
+    print "$this: Re-install hook scripts ...\n";
+    my @command = ($install_hook, $hooksrc_top, $hookdest_top);
+    system @command;
+    die $this, ': unable to execute ', join (' ', @command) if $?;
+  }
+
+  if (@update_main) {
+    # Update remote platforms, if necessary
+    my $rsh = 'rsh';
+    for my $remote (@remotes) {
+      next unless $remote->{MACHINE} and $remote->{WC};
+      print "$this: Updating working copy on $remote->{MACHINE} ...\n";
+
+      # Create the top level directory for the remote working copy (if necessary)
+      {
+        my @command = ($rsh, $remote->{MACHINE});
+        push @command, ('-l', $remote->{LOGNAME}) if $remote->{LOGNAME};
+        push @command, (qw/mkdir -p/, $remote->{WC});
+        system @command;
+        die $this, ': unable to execute ', join (' ', @command) if $?;
+      }
+
+      # Sync the working copy to the remote platform
+      {
+        my @command = ('rsync');
+        push @command, @{ $remote->{OPTIONS} } if @{ $remote->{OPTIONS} };
+        my $rwcpath = $remote->{LOGNAME};
+        $rwcpath   .= '@' . $remote->{MACHINE} . ':' . $remote->{WC};
+        push @command, ($wc_main, $rwcpath);
+        system join (' ', @command);
+        die $this, ': unable to execute ', join (' ', @command) if $?;
+      }
+    }
+  }
+}
+
+# ------------------------------------------------------------------------------
+
+END {
+  # Remove lock file on exit
+  unlink $lockfile if $locked;
+}
+
+# ------------------------------------------------------------------------------
Index: LMDZ5/branches/testing/tools/fcm/templates/hook/post-commit
===================================================================
--- LMDZ5/branches/testing/tools/fcm/templates/hook/post-commit	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/templates/hook/post-commit	(revision 1665)
@@ -0,0 +1,68 @@
+#!/bin/ksh
+
+# POST-COMMIT HOOK
+#
+# The post-commit hook is invoked after a commit.  Subversion runs
+# this hook by invoking a program (script, executable, binary, etc.)
+# named 'post-commit' (for which this file is a template) with the 
+# following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] REV          (the number of the revision just committed)
+#
+# The default working directory for the invocation is undefined, so
+# the program should set one explicitly if it cares.
+#
+# Because the commit has already completed and cannot be undone,
+# the exit code of the hook program is ignored.  The hook program
+# can use the 'svnlook' utility to help it examine the
+# newly-committed tree.
+#
+# On a Unix system, the normal procedure is to have 'post-commit'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'post-commit' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'post-commit.bat' or 'post-commit.exe',
+# but the basic idea is the same.
+# 
+# The hook program typically does not inherit the environment of
+# its parent process.  For example, a common problem is for the
+# PATH environment variable to not be set to its usual value, so
+# that subprograms fail to launch unless invoked via absolute path.
+# If you're having unexpected problems with a hook program, the
+# culprit may be unusual (or missing) environment variables.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter.
+# For more examples and pre-written hooks, see those in
+# the Subversion repository at
+# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
+# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
+
+REPOS=$1
+REV=$2
+
+CMD=${REPOS}/hooks/post-commit-background
+ERR=''
+
+if [[ -x $CMD ]]; then
+  $CMD $REPOS $REV >/dev/null 2>&1 &
+  RC=$?
+
+  if ((RC != 0)); then
+    ERR="$CMD failed ($RC)"
+  fi
+
+else
+  ERR="$CMD does not exist"
+fi
+
+if [[ -n $ERR ]]; then
+  /bin/mail -s "$ERR" my.name@somewhere.org <<EOF
+$(date): $ERR
+EOF
+fi
Index: LMDZ5/branches/testing/tools/fcm/templates/hook/post-commit-background
===================================================================
--- LMDZ5/branches/testing/tools/fcm/templates/hook/post-commit-background	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/templates/hook/post-commit-background	(revision 1665)
@@ -0,0 +1,90 @@
+#!/bin/ksh
+# ------------------------------------------------------------------------------
+# NAME
+#   post-commit-background
+#
+# SYNOPSIS
+#   post-commit-background REPOS REV
+#
+# DESCRIPTION
+#   This script performs the Subversion post-commit tasks in the background. The
+#   first argument must be the path to the current Subversion repository, and
+#   the second argument must be the revision of the current commit. Errors in
+#   the script are automatically e-mailed to the FCM user account.
+#
+#   The script does the following:
+#    1. updates the "latest" file in the log directory with the latest revision
+#       number of the repository.
+#    2. creates an incremental revision dump of the current revision.
+#    3. runs "background_updates.pl" if it exists in the hook script directory.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+REPOS=$1
+REV=$2
+
+REPOS_NAME=${REPOS##*/}
+LOG_DIR=~fcm/svn/post-commit
+LOG_FILE=$LOG_DIR/${REPOS_NAME}.log
+DUMP_DIR=~fcm/svn/dumps/$REPOS_NAME
+DUMP_FILE=$DUMP_DIR/$REV
+ERR=''
+
+{
+  # Update the "latest" file with the latest revision number
+  # ----------------------------------------------------------------------------
+  echo "$(date): Updating ${REPOS_NAME}.latest ..."
+  echo $REV > $LOG_DIR/${REPOS_NAME}.latest
+
+  if (($? != 0)); then
+    ERR="${ERR}Update of ${REPOS_NAME}.latest: failed. "
+  fi
+
+  # Dump the current revision
+  # ----------------------------------------------------------------------------
+  if [[ ! -d $DUMP_DIR ]]; then
+    mkdir -p $DUMP_DIR
+  fi
+
+  svnadmin dump -r $REV --incremental --deltas $REPOS 1>$DUMP_FILE
+
+  if (($? != 0)); then
+    ERR="${ERR}$REPOS_NAME@$REV: svnadmin dump: failed. "
+  fi
+
+  # Warn us of large changesets (>1Mb)
+  dump_size=$(stat -c %s $DUMP_FILE)
+
+  if (($dump_size > 1048576)); then
+    ERR="${ERR}Dump size exceeds 1Mb. "
+    echo "WARNING: large changeset dump, size = ${dump_size}byte">&2 
+  fi
+
+  # Perform background update, if necessary
+  # ----------------------------------------------------------------------------
+  if [[ -e ${REPOS}/hooks/background_updates.pl ]]; then
+    echo "$(date): Running background tasks and exiting ..."
+    ${REPOS}/hooks/background_updates.pl $REPOS_NAME $LOG_DIR
+
+    if (($? != 0)); then
+      ERR="${ERR}background_updates.pl: failed. "
+    fi
+
+  else
+    echo "$(date): No background tasks required - exiting"
+  fi
+
+} 1>$LOG_FILE 2>&1
+
+# If there are errors, e-mail the log message to FCM
+# ------------------------------------------------------------------------------
+if [[ -n $ERR ]]; then
+  ERR=${ERR% *}
+  /bin/mail -s "$REPOS@$REV: $ERR" my.name@somewhere.org <<EOF
+$(<$LOG_FILE)
+EOF
+fi
Index: LMDZ5/branches/testing/tools/fcm/templates/hook/post-revprop-change
===================================================================
--- LMDZ5/branches/testing/tools/fcm/templates/hook/post-revprop-change	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/templates/hook/post-revprop-change	(revision 1665)
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+# POST-REVPROP-CHANGE HOOK
+#
+# The post-revprop-change hook is invoked after a revision property
+# has been added, modified or deleted.  Subversion runs this hook by
+# invoking a program (script, executable, binary, etc.) named
+# 'post-revprop-change' (for which this file is a template), with the
+# following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] REV          (the revision that was tweaked)
+#   [3] USER         (the username of the person tweaking the property)
+#   [4] PROPNAME     (the property that was changed)
+#   [5] ACTION       (the property was 'A'dded, 'M'odified, or 'D'eleted)
+#
+#   [STDIN] PROPVAL  ** the old property value is passed via STDIN.
+#
+# Because the propchange has already completed and cannot be undone,
+# the exit code of the hook program is ignored.  The hook program
+# can use the 'svnlook' utility to help it examine the
+# new property value.
+#
+# On a Unix system, the normal procedure is to have 'post-revprop-change'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'post-revprop-change' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'post-revprop-change.bat' or 'post-revprop-change.exe',
+# but the basic idea is the same.
+# 
+# The hook program typically does not inherit the environment of
+# its parent process.  For example, a common problem is for the
+# PATH environment variable to not be set to its usual value, so
+# that subprograms fail to launch unless invoked via absolute path.
+# If you're having unexpected problems with a hook program, the
+# culprit may be unusual (or missing) environment variables.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter.
+# For more examples and pre-written hooks, see those in
+# the Subversion repository at
+# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
+# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
+
+REPOS="$1"
+REV="$2"
+USER="$3"
+PROPNAME="$4"
+ACTION="$5"
+
+REPOS_NAME=${REPOS##*/}
+LOG_DIR=~fcm/svn/revprop-change
+LOG_FILE=$LOG_DIR/${REPOS_NAME}.post.log
+CMD=${REPOS}/hooks/post-revprop-change.py
+
+$CMD "$@" <&0 1>$LOG_FILE 2>&1
+RC=$?
+
+if ((RC != 0)); then
+  /bin/mail -s "$CMD failed" my.name@somewhere.org <<EOF
+$(<$LOG_FILE)
+EOF
+fi
+
+exit $RC
Index: LMDZ5/branches/testing/tools/fcm/templates/hook/post-revprop-change.py
===================================================================
--- LMDZ5/branches/testing/tools/fcm/templates/hook/post-revprop-change.py	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/templates/hook/post-revprop-change.py	(revision 1665)
@@ -0,0 +1,69 @@
+#!/usr/bin/python
+# ------------------------------------------------------------------------------
+# NAME
+#   post-revprop-change.py
+#
+# SYNOPSIS
+#   post-revprop-change.py REPOS REV USER PROPNAME ACTION <&0
+#
+# DESCRIPTION
+#   This script updates the Trac SQLite database with the new revision log
+#   following a change in svn:log. The old property value is passed via STDIN.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard modules
+import commands
+import os.path
+import sqlite
+import sys
+
+def main ():
+  '''Main program'''
+
+  # Get command line arguments
+  (repos, rev, user, propname, action) = sys.argv [1:6]
+
+  # Handle only log message change
+  if not (propname == 'svn:log' and action == 'M'):
+    return
+
+  # Get new message with "svnlook"
+  message = commands.getoutput ('svnlook log -r ' + rev + ' ' + repos)
+  if not message:
+    return
+
+  # Name of the project
+  project = os.path.basename (repos)
+  project = project.replace ('_svn', '')
+
+  # Path to project Trac system
+  trac    = os.path.join (os.path.expanduser ('~fcm'), 'trac', 'live', project)
+  trac_db = os.path.join (trac, 'db', 'trac.db')
+
+  # Update Trac database
+  db      = sqlite.connect (trac_db)
+  cursor  = db.cursor ()
+  cursor.execute (
+    "UPDATE revision SET message = %s WHERE rev == %s", message, rev
+  )
+
+  try:
+    db.commit ()
+
+  except:
+    raise 'Failed to update log of revision ' + rev + ' in ' + trac_db + '.'
+
+  else:
+    print 'Updated log of revision ' + rev + ' in ' + trac_db + '.'
+
+  return
+
+# ------------------------------------------------------------------------------
+
+if __name__ == '__main__' :
+  main ()
Index: LMDZ5/branches/testing/tools/fcm/templates/hook/pre-commit
===================================================================
--- LMDZ5/branches/testing/tools/fcm/templates/hook/pre-commit	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/templates/hook/pre-commit	(revision 1665)
@@ -0,0 +1,76 @@
+#!/bin/ksh
+
+# PRE-COMMIT HOOK
+#
+# The pre-commit hook is invoked before a Subversion txn is
+# committed.  Subversion runs this hook by invoking a program
+# (script, executable, binary, etc.) named 'pre-commit' (for which
+# this file is a template), with the following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] TXN-NAME     (the name of the txn about to be committed)
+#
+# The default working directory for the invocation is undefined, so
+# the program should set one explicitly if it cares.
+#
+# If the hook program exits with success, the txn is committed; but
+# if it exits with failure (non-zero), the txn is aborted, no commit
+# takes place, and STDERR is returned to the client.   The hook
+# program can use the 'svnlook' utility to help it examine the txn.
+#
+# On a Unix system, the normal procedure is to have 'pre-commit'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+#   ***  NOTE: THE HOOK PROGRAM MUST NOT MODIFY THE TXN, EXCEPT  ***
+#   ***  FOR REVISION PROPERTIES (like svn:log or svn:author).   ***
+#
+#   This is why we recommend using the read-only 'svnlook' utility.
+#   In the future, Subversion may enforce the rule that pre-commit
+#   hooks should not modify the versioned data in txns, or else come
+#   up with a mechanism to make it safe to do so (by informing the
+#   committing client of the changes).  However, right now neither
+#   mechanism is implemented, so hook writers just have to be careful.
+#
+# Note that 'pre-commit' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'pre-commit.bat' or 'pre-commit.exe',
+# but the basic idea is the same.
+#
+# The hook program typically does not inherit the environment of
+# its parent process.  For example, a common problem is for the
+# PATH environment variable to not be set to its usual value, so
+# that subprograms fail to launch unless invoked via absolute path.
+# If you're having unexpected problems with a hook program, the
+# culprit may be unusual (or missing) environment variables.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter.
+# For more examples and pre-written hooks, see those in
+# the Subversion repository at
+# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
+# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
+
+REPOS="$1"
+TXN="$2"
+
+# Check that the author of this commit has the rights to perform
+# the commit on the files and directories being modified.
+script=$REPOS/hooks/svnperms.py
+if [[ -x $script ]]; then
+  $script -r "$REPOS" -t "$TXN" -f ${REPOS}/hooks/svnperms.conf || exit 1
+fi
+
+# Check that the size of the transaction does not exceed 5Mb
+size=$(du -b -s $REPOS/db/transactions/$TXN.txn | cut -f 1)
+if (($size > 5242880)); then
+  echo \
+"Your changeset requires a disk space ($size bytes) exceeding our 5Mb limit.
+Please contact the FCM team if you need to bypass this restriction." >&2
+  exit 1
+fi
+
+# All checks passed, so allow the commit.
+exit 0
Index: LMDZ5/branches/testing/tools/fcm/templates/hook/pre-revprop-change
===================================================================
--- LMDZ5/branches/testing/tools/fcm/templates/hook/pre-revprop-change	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/templates/hook/pre-revprop-change	(revision 1665)
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+# PRE-REVPROP-CHANGE HOOK
+#
+# The pre-revprop-change hook is invoked before a revision property
+# is added, modified or deleted.  Subversion runs this hook by invoking
+# a program (script, executable, binary, etc.) named 'pre-revprop-change'
+# (for which this file is a template), with the following ordered
+# arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] REVISION     (the revision being tweaked)
+#   [3] USER         (the username of the person tweaking the property)
+#   [4] PROPNAME     (the property being set on the revision)
+#   [5] ACTION       (the property is being 'A'dded, 'M'odified, or 'D'eleted)
+#
+#   [STDIN] PROPVAL  ** the new property value is passed via STDIN.
+#
+# If the hook program exits with success, the propchange happens; but
+# if it exits with failure (non-zero), the propchange doesn't happen.
+# The hook program can use the 'svnlook' utility to examine the 
+# existing value of the revision property.
+#
+# WARNING: unlike other hooks, this hook MUST exist for revision
+# properties to be changed.  If the hook does not exist, Subversion 
+# will behave as if the hook were present, but failed.  The reason
+# for this is that revision properties are UNVERSIONED, meaning that
+# a successful propchange is destructive;  the old value is gone
+# forever.  We recommend the hook back up the old value somewhere.
+#
+# On a Unix system, the normal procedure is to have 'pre-revprop-change'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+# Note that 'pre-revprop-change' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'pre-revprop-change.bat' or 'pre-revprop-change.exe',
+# but the basic idea is the same.
+#
+# The hook program typically does not inherit the environment of
+# its parent process.  For example, a common problem is for the
+# PATH environment variable to not be set to its usual value, so
+# that subprograms fail to launch unless invoked via absolute path.
+# If you're having unexpected problems with a hook program, the
+# culprit may be unusual (or missing) environment variables.
+# 
+# Here is an example hook script, for a Unix /bin/sh interpreter.
+# For more examples and pre-written hooks, see those in
+# the Subversion repository at
+# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
+# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
+
+REPOS="$1"
+REV="$2"
+USER="$3"
+PROPNAME="$4"
+ACTION="$5"
+
+REPOS_NAME=${REPOS##*/}
+LOG_DIR=~fcm/svn/revprop-change
+LOG_FILE=$LOG_DIR/${REPOS_NAME}.pre.log
+CMD=${REPOS}/hooks/pre-revprop-change.pl
+
+$CMD "$@" <&0 1>$LOG_FILE 2>&1
+RC=$?
+
+if ((RC != 0)); then
+  /bin/mail -s "$CMD failed" my.name@somewhere.org <<EOF
+$(<$LOG_FILE)
+EOF
+fi
+
+exit $RC
Index: LMDZ5/branches/testing/tools/fcm/templates/hook/pre-revprop-change.pl
===================================================================
--- LMDZ5/branches/testing/tools/fcm/templates/hook/pre-revprop-change.pl	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/templates/hook/pre-revprop-change.pl	(revision 1665)
@@ -0,0 +1,222 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   pre-revprop-change.pl
+#
+# SYNOPSIS
+#   pre-revprop-change.pl REPOS REV USER PROPNAME ACTION <&0
+#
+# DESCRIPTION
+#   This script e-mails authors and watchers when a user attempts to modify the
+#   svn:log of a particular revision. The new property value is passed via
+#   STDIN. Watchers are set in the "watch.cfg" file, which should be located in
+#   the root within the Subversion repository. The watch.cfg file is a standard
+#   INI-type configuration file with the basic format:
+#
+#     [repos_base]
+#     path/in/repos = list,of,watchers
+#
+#   E.g.:
+#
+#     [FCM_svn]
+#
+#     FCM/trunk/src            = fcm,frsn
+#     FCM/trunk/doc            = fcm,frsn,frdm,frbj
+#     FCM/branches/dev/*/*/src = fcm,frsn
+#     FCM/branches/dev/*/*/doc = fcm,frsn,frdm,frbj
+#
+# COPYRIGHT
+#   This program is part of the FCM system.
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+use strict;
+use warnings;
+
+use File::Basename;
+use File::Spec;
+use File::Temp qw/tempfile/;
+use Mail::Mailer;
+use Config::IniFiles;
+
+# Arguments
+# ------------------------------------------------------------------------------
+my ($repos, $rev, $user, $propname, $action) = @ARGV;
+
+# Basename of repository
+my $base = basename $repos;
+
+# Top level variables
+# ------------------------------------------------------------------------------
+# The watch configuration file, at the root of the current repository
+my $watch_config = 'watch.cfg';
+
+# Determine whether change is permitted
+# ------------------------------------------------------------------------------
+# Switch off for most revision properties
+my $return = 1;
+
+# Switch on only for "svn:log"
+$return = 0 if $propname eq 'svn:log' and $action eq 'M';
+
+if ($return == 0) {
+  # Diagnostic
+  print $repos, ': ', $propname, ' at revision ', $rev,
+        ' is being modified by ', $user, '.', "\n";
+
+  my %mail_to = ();
+
+  # Mail original author, if he/she is not the current user
+  # ----------------------------------------------------------------------------
+  # Find out who is the author of the changeset at $rev
+  my @command = (qw/svnlook author -r/, $rev, $repos);
+  my $author  = qx(@command);
+  chomp $author;
+
+  # Add author to mail list, if necessary
+  $mail_to{$author} = 1 if $author ne $user;
+
+  # Mail watchers, if changeset involves files being watched
+  # ----------------------------------------------------------------------------
+  # Find out what files were involved in the changeset
+  @command    = (qw/svnlook changed -r/, $rev, $repos);
+  my @changed = qx(@command);
+
+  # Get list of watchers for current repository
+  my %watch = &get_watchers ();
+
+  for my $file (@changed) {
+    # Remove trailing line break and leading status
+    chomp $file;
+    $file = substr ($file, 4);
+
+    # Find out who are watching this file
+    my @watchers = &who_watch ($file, \%watch);
+
+    # If necessary, add watchers to list, unless he/she is the current user
+    for my $watcher (@watchers) {
+      $mail_to{$watcher} = 1 if $user ne $watcher;
+    }
+  }
+
+  # Send mail if necessary
+  # ----------------------------------------------------------------------------
+  if (keys %mail_to) {
+    # Old value of revision property
+    my @command = (qw/svnlook pg -r/, $rev, '--revprop', $repos, $propname);
+    my $oldval  = qx(@command);
+
+    # Addresses as a comma-separated list
+    my $address = join (',', sort keys %mail_to);
+
+    # Invoke a new Mail::Mailer object
+    my $mailer  = Mail::Mailer->new ();
+    $mailer->open ({
+      From    => 'my.name@somewhere.org',
+      To      => $address,
+      Subject => $base . '@' . $rev . ': ' . $propname . ' modified by ' . $user,
+    }) or die 'Cannot e-mail ', $address, ' (', $!, ')';
+
+    # Write the mail
+    # Old value
+    print $mailer <<EOF;
+Old value:
+----------
+$oldval
+
+New value:
+----------
+EOF
+
+    # New value from STDIN
+    print $mailer $_ while (<STDIN>);
+
+    # Send the mail
+    $mailer->close;
+
+    print 'Mail notification has been sent to ', $address, '.', "\n";
+
+  } else {
+    print 'No mail notification is required for this change.', "\n";
+  }
+}
+
+exit $return;
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   %watch = &get_watchers ();
+#
+# DESCRIPTION
+#   From the list of watch configuration files, get a list of watched files and
+#   their watchers for the current repository. Returns the results in a hash
+#   containing the watched paths (keys) and their corresponding list of
+#   watchers (values, array references).
+# ------------------------------------------------------------------------------
+
+sub get_watchers {
+  my %watch;
+
+  # Get contents in watch file
+  my @command = (qw/svnlook cat/, $repos, $watch_config);
+  my @output  = qx(@command);
+
+  if (@output) {
+    # Write result to temporary file
+    my ($fh, $temp_file) = tempfile (UNLINK => 1);
+    print $fh @output;
+    close $fh;
+
+    # Parse the configuration
+    my $cfg = Config::IniFiles->new ('-file' => $temp_file);
+
+    # Check if current repository name exists in the configuration file
+    if ($cfg and $cfg->SectionExists ($base)) {
+      # The name of the parameter is a sub-path in the repository
+      # The value of the parameter is a comma-delimited list of the watchers
+      my $separator = '/';
+      for my $parameter ($cfg->Parameters ($base)) {
+        # Parameter may contain wildcards * and ?
+        $parameter =~ s#\*#[^$separator]*#g;
+        $parameter =~ s#\?#[^$separator]#g;
+
+        $watch{$parameter} = [split (/,/, $cfg->val ($base, $parameter))];
+      }
+    }
+  }
+
+  return %watch;
+}
+
+# ------------------------------------------------------------------------------
+# SYNOPSIS
+#   my @watchers = &who_watch ($file, \%watch);
+#
+# DESCRIPTION
+#   Using the %watch hash, determine who are the watchers watching $file.
+#   Returns the list of watchers.
+# ------------------------------------------------------------------------------
+
+sub who_watch {
+  my $file  = $_[0];
+  my %watch = %{ $_[1] };
+
+  my %watchers;
+  my $separator = '/';
+
+  for my $watched (keys %watch) {
+    # Test if $file or its parent path is being watched
+    next unless $file =~ m#^$watched(?:$separator+|$)#;
+
+    # Add watchers to the return list
+    $watchers{$_} = 1 for (@{ $watch{$watched} });
+  }
+
+  return keys %watchers;
+}
+
+# ------------------------------------------------------------------------------
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/templates/utils/cron_template.ksh
===================================================================
--- LMDZ5/branches/testing/tools/fcm/templates/utils/cron_template.ksh	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/templates/utils/cron_template.ksh	(revision 1665)
@@ -0,0 +1,50 @@
+#!/usr/bin/ksh
+# ------------------------------------------------------------------------------
+# (C) Crown copyright Met Office. All rights reserved.
+# For further details please refer to the file COPYRIGHT.txt
+# which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+lockfile='lock'
+
+if [[ -f $lockfile ]]; then
+  exit
+fi
+
+touch $lockfile
+
+headrevfile='latest'
+lastrevfile='lastrev'
+
+# Current HEAD revision
+if [[ ! -r $headrevfile ]]; then
+  echo "HEAD revision file $headrevfile cannot be read, abort" >&2
+  rm -f $lockfile
+  exit 1
+fi
+headrev=$(<$headrevfile)
+headrev=$(echo $headrev)
+
+# Revision at which this script is last run
+if [[ -r $lastrevfile ]]; then
+  lastrev=$(<$lastrevfile)
+  lastrev=$(echo $lastrev)
+else
+  lastrev=0
+fi
+
+# Exit if HEAD revision is the same as the last run revision
+if (($lastrev == $headrev)); then
+  rm -f $lockfile
+  exit 0
+fi
+
+# ------------------------------------------------------------------------------
+# Do something...
+# ------------------------------------------------------------------------------
+
+# Update last run revision file
+echo $headrev >$lastrevfile
+rm -f $lockfile
+
+# EOF
Index: LMDZ5/branches/testing/tools/fcm/templates/utils/daily_cron
===================================================================
--- LMDZ5/branches/testing/tools/fcm/templates/utils/daily_cron	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/templates/utils/daily_cron	(revision 1665)
@@ -0,0 +1,277 @@
+#!/bin/ksh
+
+out=~fcm/FCM/daily_cron.out
+svn_live=/data/local/fcm/svn/live
+svn_backup=~fcm/svn/backups
+svn_tmp=/var/tmp/fcm/svn/backups
+svn_dump=~fcm/svn/dumps
+trac_live=~fcm/trac/live
+trac_backup=~fcm/trac/backups
+trac_tmp=/var/tmp/fcm/trac/backups
+err=''
+
+export RSYNC_RSH=rsh # remote shell for "rsync"
+
+{
+
+  # Verify and backup Subversion repository database
+  # ----------------------------------------------------------------------------
+  cd $svn_live
+  tmpfile=/tmp/${USER}.$$
+  now=$(date +%s)
+  for dir in *; do
+    if [[ ! -d $dir ]]; then continue; fi
+
+    # Verify
+    # --------------------------------------------------------------------------
+    echo "$(date): Verifying $dir ..."
+    sed '/^\* Verified revision [0-9][0-9]*\./d'<<EOF
+$(svnadmin verify $dir 2>&1; echo $? > $tmpfile)
+EOF
+    RC=$(cat $tmpfile)
+
+    if ((RC != 0)); then
+      err="${err}Error in $dir repository integrity. "
+      continue
+    fi
+
+    # Backup
+    # --------------------------------------------------------------------------
+    # Create the temporary backup location if it does not exists
+    if [[ ! -d $svn_tmp ]]; then
+      mkdir -p $svn_tmp
+
+      if (($? != 0)); then
+        err="${err}Error creating $svn_tmp. "
+        break
+      fi
+    fi
+
+    # Hotcopy to temporary location
+    tmp_backup_dir=$svn_tmp/$dir
+    echo "$(date): Hotcopying $dir SVN repository to $tmp_backup_dir ..."
+    svnadmin hotcopy $dir $tmp_backup_dir
+
+    if (($? != 0)); then
+      err="${err}Error hotcopying $dir SVN repository to $tmp_backup_dir. "
+      continue
+    fi
+
+    # Create the backup location if it does not exists
+    if [[ ! -d $svn_backup ]]; then
+      mkdir -p $svn_backup
+
+      if (($? != 0)); then
+        err="${err}Error creating $svn_backup. "
+        break
+      fi
+    fi
+
+    # Tar and gzip the backup
+    new_backup=$svn_backup/$dir.$(date +%Y%m%d).tgz
+    echo "$(date): Creating tar archive in $new_backup ..."
+    tar -C $svn_tmp -c -z -f $new_backup $(basename $tmp_backup_dir)
+
+    if (($? != 0)); then
+      err="${err}Error creating tar archive in $new_backup. "
+      continue
+    fi
+
+    # Remove the temporary hotcopy
+    rm -rf $tmp_backup_dir
+
+    if (($? != 0)); then
+      err="${err}Error removing $tmp_backup_dir. "
+    fi
+
+    # Remove the old backup, if necessary
+    backup=$svn_backup/$dir.tgz
+
+    if [[ -f $backup ]]; then
+      rm -f $backup
+
+      if (($? != 0)); then
+        err="${err}Error removing old copy of $backup. "
+        continue
+      fi
+    fi
+
+    # Move today's backup to the final location
+    echo "$(date): Renaming $new_backup to $backup ..."
+    mv $new_backup $backup
+
+    if (($? != 0)); then
+      err="${err}Error renaming $new_backup to $backup. "
+    fi
+
+    # Housekeep the revision dumps
+    # --------------------------------------------------------------------------
+    if [[ -d $svn_dump/$dir ]]; then
+      # Keep dumps created in the last 3 days
+      echo "$(date): Housekeeping dumps in $svn_dump/$dir ..."
+
+      cd $svn_dump/$dir
+      for rev in *; do
+        # Check that $rev is a regular file
+        if [[ ! -f $rev ]]; then
+          continue
+        fi
+
+        # 3 days = 24 * 60 * 60 * 3 = 259200 seconds
+        if (($now - $(stat -c %Y $rev) > 259200)); then
+          echo "$(date): Removing $svn_dump/$dir/$rev ..."
+          rm -f $rev
+          if (($? != 0)); then
+            err="${err}Error removing dump $svn_dump/$dir/$rev. "
+          fi
+        fi
+      done
+
+      cd $OLDPWD
+    fi
+  done
+
+  # Backing up Trac systems
+  # ----------------------------------------------------------------------------
+  cd $trac_live
+  for dir in *; do
+    if [[ ! -d $dir ]]; then continue; fi
+
+    # Backup
+    # --------------------------------------------------------------------------
+    # Create the temporary backup location if it does not exists
+    if [[ ! -d $trac_tmp ]]; then
+      mkdir -p $trac_tmp
+
+      if (($? != 0)); then
+        err="${err}Error creating $trac_tmp. "
+        break
+      fi
+    fi
+
+    # Hotcopy to temporary location
+    tmp_backup_dir=$trac_tmp/$dir
+    echo "$(date): Hotcopying $dir Trac system to $tmp_backup_dir ..."
+    trac-admin $dir hotcopy $tmp_backup_dir
+
+    if (($? != 0)); then
+      err="${err}Error hotcopying $dir Trac system to $tmp_backup_dir. "
+      continue
+    fi
+
+    # Create the backup location if it does not exists
+    if [[ ! -d $trac_backup ]]; then
+      mkdir -p $trac_backup
+
+      if (($? != 0)); then
+        err="${err}Error creating $trac_backup. "
+        break
+      fi
+    fi
+
+    # Tar and gzip the backup
+    new_backup=$trac_backup/$dir.$(date +%Y%m%d).tgz
+    echo "$(date): Creating tar archive in $new_backup ..."
+    tar -C $trac_tmp -c -z -f $new_backup $(basename $tmp_backup_dir)
+
+    if (($? != 0)); then
+      err="${err}Error creating tar archive in $new_backup. "
+      continue
+    fi
+
+    # Remove the temporary hotcopy
+    rm -rf $tmp_backup_dir
+
+    if (($? != 0)); then
+      err="${err}Error removing $tmp_backup_dir. "
+    fi
+
+    # Rename backups on success
+    # --------------------------------------------------------------------------
+    # Shift backup "1" to backup "2", and then backup "0" to backup "1"
+    for i in 1 0; do
+      old_file=$trac_backup/$dir.$i.tgz
+      new_file=$trac_backup/$dir.$((i + 1)).tgz
+
+      # Check if move is necessary
+      if [[ ! -f $old_file ]]; then
+        continue
+      fi
+
+      if [[ -f $new_file ]]; then
+        echo "$(date): Removing $new_file ..."
+        rm -f $new_file
+
+        if (($? != 0)); then
+          err="${err}Error removing $new_file. "
+          break
+        fi
+      fi
+
+      echo "$(date): Renaming $old_file to $new_file ..."
+      mv $old_file $new_file
+      if (($? != 0)); then
+        err="${err}Error renaming $old_file. "
+        break
+      fi
+    done
+
+    # Move today's backup to "0", if possible
+    backup=$trac_backup/$dir.0.tgz
+    if [[ ! -f $backup ]]; then
+      echo "$(date): Renaming $new_backup to $backup ..."
+      mv $new_backup $backup
+      if (($? != 0)); then
+        err="${err}Error renaming $new_backup to $backup. "
+      fi
+    fi
+  done
+
+  # Update the Trac password file and databases with latest login information
+  # ----------------------------------------------------------------------------
+  echo "$(date): Updating password files and Trac databases ..."
+  $(dirname $0)/fcm_manage_login.py
+  if (($? != 0)); then
+    err="${err} Error updating Trac password file and databases. "
+  fi
+
+  # Sync the working copy to the NEC
+  # ----------------------------------------------------------------------------
+  echo "$(date): Updating NEC ..."
+  rsync -a -v --timeout=1800 --exclude='.*' --exclude='FCM/doc' \
+    --delete-excluded ~/FCM/work/FCM fcm@tx01:~/FCM/work
+  if (($? != 0)); then
+    err="${err}Error updating NEC. "
+  fi
+
+  # Update "synch" path from "synch" machine
+  # ----------------------------------------------------------------------------
+  echo "$(date): Updating synch machine ..."
+  for subdir in bin lib etc; do
+    rsync -a -v --timeout=1800 --exclude='.*' ~/FCM/work/FCM/src/$subdir/* \
+      fcm@hc0100:/opt/ukmo/utils/supported/portable/$subdir/
+
+    if (($? != 0)); then
+      err="${err}Error updating $subdir/ on synch machine. "
+    fi
+  done
+
+  # Final report
+  # ----------------------------------------------------------------------------
+  if [[ -n $err ]]; then
+    subject="$(basename $0) finished with errors: $err"
+
+  else
+    subject="$(basename $0) finished normally."
+  fi
+
+  echo "$(date): $subject"
+} 1>$out 2>&1
+
+# Report completion via e-mail
+# ------------------------------------------------------------------------------
+mail -s "$subject" my.name@somewhere.org <<EOF
+$(<$out)
+EOF
+
+# EOF
Index: LMDZ5/branches/testing/tools/fcm/templates/utils/fcm_add_trac.pl
===================================================================
--- LMDZ5/branches/testing/tools/fcm/templates/utils/fcm_add_trac.pl	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/templates/utils/fcm_add_trac.pl	(revision 1665)
@@ -0,0 +1,368 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   fcm_add_trac.pl
+#
+# SYNOPSIS
+#   fcm_add_trac.pl [OPTIONS] <system>
+#   fcm_add_trac.pl -h
+#
+# DESCRIPTION
+#   See $usage for further information.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard pragmas
+use strict;
+use warnings;
+
+# Standard modules
+use Getopt::Long;
+use File::Basename;
+use File::Spec;
+use Config::IniFiles;
+
+# In-house modules
+use lib File::Spec->catfile (
+  dirname (
+    (grep {-x File::Spec->catfile ($_, 'fcm')} split (/:/, $ENV{PATH})) [0]
+  ),
+  'lib',
+);
+use Fcm::Util;
+
+# ------------------------------------------------------------------------------
+
+# Program information
+my $this      = basename ($0);
+my $year      = (localtime)[5] + 1900;
+my $copyright = <<EOF;
+
+(C) Crown copyright $year Met Office. All rights reserved.
+EOF
+my $usage     = <<EOF;
+NAME
+  $this: add a new Trac browser for a FCM project
+
+SYNOPSIS
+  $this [OPTIONS] <project> # normal usage
+  $this [-h]                # print help and exit
+
+DESCRIPTION
+  This script adds a new Trac browser for a project managed by FCM. The name of
+  the project is specified in the first argument.
+  
+  With the except of --authorised and --help, all options to the script take at
+  least one argument. If an option can take more than one argument, the
+  arguments should be specified in a comma-separated list.
+
+OPTIONS
+  -a, --authorised      - specify an "authorised" permission. Only those users
+                          granted this permission will have "_CREATE" and
+                          "_MODIFY" access. The default is to grant all
+                          authenticated users "_CREATE" and "_MODIFY" access.
+
+  -c, --component       - specify one or more components.
+
+  -d, --description     - specify a description of the project.
+
+  -e, --smtp-always-cc  - specify one or more e-mail addresses, where e-mails
+                          will be sent to on ticket changes.
+
+  -h, --help            - prints the usage string and exits.
+
+  -m, --milestone       - specify one or more milestones.
+
+  -s, --svn-repos       - specify the Subversion repository location. Use an
+                          empty string if no Subversion repository is needed.
+
+  -u, --admin-user      - specify one or more admin users.
+
+  -v, --version         - specify one or more versions.
+$copyright
+EOF
+
+# ------------------------------------------------------------------------------
+
+# Options
+my ($authorised, $help, $description, $svn_repos);
+my (@admin_users, @components, @emails, @milestones, @versions);
+
+GetOptions (
+  'a|authorised'       => \$authorised,
+  'c|component=s'      => \@components,
+  'd|description=s'    => \$description,
+  'e|smtp-always-cc=s' => \@emails,
+  'h|help'             => \$help,
+  'm|milestone=s'      => \@milestones,
+  's|svn-repos=s'      => \$svn_repos,
+  'u|admin-user=s'     => \@admin_users,
+  'v|version=s'        => \@versions,
+);
+
+@admin_users = split (/,/, join (',', @admin_users));
+@components  = split (/,/, join (',', @components));
+@emails      = split (/,/, join (',', @emails));
+@milestones  = split (/,/, join (',', @milestones));
+@versions    = split (/,/, join (',', @versions));
+
+if ($help) {
+  print $usage;
+  exit;
+}
+
+# Arguments
+my $project = $ARGV[0];
+if (not $project) {
+  print $usage;
+  exit;
+}
+
+# ------------------------------------------------------------------------------
+
+# Useful variables
+my $svn_root  = '/data/local/fcm/svn/live';
+my $trac_root = File::Spec->catfile ((getpwnam ('fcm'))[7], 'trac', 'live');
+
+# Parse the central configuration file
+my $central_ini = Config::IniFiles->new (
+  '-file' => File::Spec->catfile ($trac_root, 'trac.ini'),
+);
+
+# ------------------------------------------------------------------------------
+
+MAIN: {
+  # Check for the existence of Trac for the current project
+  # ----------------------------------------------------------------------------
+  my $trac_project = File::Spec->catfile ($trac_root, $project);
+  die $this, ': ', $trac_project, ': already exists, abort' if -d $trac_project;
+
+  # Check for the existence of SVN for the current project
+  # ----------------------------------------------------------------------------
+  my $svn_project = defined ($svn_repos)
+                    ? $svn_repos
+                    : File::Spec->catfile ($svn_root, $project . '_svn');
+  die $this, ': ', $svn_project, ': does not exist, abort'
+    if $svn_project and not -d $svn_project;
+
+  # Set up "trac-admin" command for this project
+  # ----------------------------------------------------------------------------
+  my @admin_cmd = ('trac-admin', $trac_project);
+
+  # Create project's Trac
+  my $trac_templates = '/usr/share/trac/templates';
+
+  my @command = (
+    @admin_cmd,
+    'initenv',
+    $project,
+    'sqlite:db/trac.db',
+    ($svn_project ? ('svn', $svn_project) : ('', '')),
+    $trac_templates,
+  );
+
+  &run_command (\@command, PRINT => 1);
+
+  # Ensure the new Trac has the correct group and permissions
+  &run_command ([qw/chgrp -R apache/, $trac_project], PRINT => 1);
+  &run_command ([qw/chmod -R g+w/, $trac_project], PRINT => 1);
+
+  # Components
+  # ----------------------------------------------------------------------------
+  my @cur_cmd = (@admin_cmd, 'component');
+
+  # Remove example components
+  for my $component (qw/component1 component2/) {
+    &run_command ([@cur_cmd, 'remove', $component], PRINT => 1);
+  }
+
+  # Add specified components
+  for my $component (@components) {
+    &run_command ([@cur_cmd, 'add', $component, ''], PRINT => 1);
+  }
+
+  # List components
+  &run_command ([@cur_cmd, 'list'], PRINT => 1);
+
+  # Versions
+  # ----------------------------------------------------------------------------
+  @cur_cmd = (@admin_cmd, 'version');
+
+  # Remove example versions
+  for my $version (qw/1.0 2.0/) {
+    &run_command ([@cur_cmd, 'remove', $version], PRINT => 1);
+  }
+
+  # Add specified versions
+  for my $version (@versions) {
+    &run_command ([@cur_cmd, 'add', $version], PRINT => 1);
+  }
+
+  # List versions
+  &run_command ([@cur_cmd, 'list'], PRINT => 1);
+
+  # Milestones
+  # ----------------------------------------------------------------------------
+  @cur_cmd = (@admin_cmd, 'milestone');
+
+  # Remove example milestones
+  for my $milestone (qw/milestone1 milestone2 milestone3 milestone4/) {
+    &run_command ([@cur_cmd, 'remove', $milestone], PRINT => 1);
+  }
+
+  # Add specified milestones
+  for my $milestone (@milestones) {
+    &run_command ([@cur_cmd, 'add', $milestone], PRINT => 1);
+  }
+
+  # List milestones
+  &run_command ([@cur_cmd, 'list'], PRINT => 1);
+
+  # Priority
+  # ----------------------------------------------------------------------------
+  @cur_cmd = (@admin_cmd, 'priority');
+
+  # Change default priorities
+  my %priorities = (
+    blocker  => 'highest',
+    critical => 'high',
+    major    => 'normal',
+    minor    => 'low',
+    trivial  => 'lowest',
+  );
+  while (my ($old, $new) = each %priorities) {
+    &run_command ([@cur_cmd, 'change', $old, $new], PRINT => 1);
+  }
+
+  # List priorities
+  &run_command ([@cur_cmd, 'list'], PRINT => 1);
+
+  # Severity
+  # ----------------------------------------------------------------------------
+  @cur_cmd = (@admin_cmd, 'severity');
+
+  # Add serverities
+  for my $severity (qw/blocker critical major normal minor trivial/) {
+    &run_command ([@cur_cmd, 'add', $severity], PRINT => 1);
+  }
+
+  # List serverities
+  &run_command ([@cur_cmd, 'list'], PRINT => 1);
+
+  # Permission
+  # ----------------------------------------------------------------------------
+  @cur_cmd = (@admin_cmd, 'permission');
+
+  # Add permissions to admin users
+  for my $user (@admin_users) {
+    &run_command ([@cur_cmd, 'add', $user, 'admin'], PRINT => 1);
+  }
+  &run_command ([@cur_cmd, qw/add admin TRAC_ADMIN/], PRINT => 1);
+
+  # Remove wiki/ticket create/modify permissions from anonymous users
+  for my $per (qw/TICKET_CREATE TICKET_MODIFY WIKI_CREATE WIKI_MODIFY/) {
+    &run_command ([@cur_cmd, qw/remove anonymous/, $per], PRINT => 1);
+  }
+
+  # Add wiki/ticket create/modify permissions to authenticated/authorised users
+  for my $per (qw/TICKET_CREATE TICKET_MODIFY WIKI_CREATE WIKI_MODIFY/) {
+    &run_command (
+      [@cur_cmd, 'add', ($authorised ? 'authorised' : 'authenticated'), $per],
+      PRINT => 1,
+    );
+  }
+
+  # List permissions
+  &run_command ([@cur_cmd, 'list'], PRINT => 1);
+
+  # Misc modifications to "trac.ini"
+  # ----------------------------------------------------------------------------
+  my $local_file = File::Spec->catfile ($trac_project, 'conf', 'trac.ini');
+
+  # Read and parse "trac.ini"
+  my $local_ini = Config::IniFiles->new ('-file' => $local_file);
+
+  # Descriptive name for the current project
+  my $descr          = $description ? $description : $project;
+
+  # Default component
+  my $def_component  = @components ? $components [0] : '';
+
+  # List of e-mail addresses to always cc
+  my $smtp_always_cc = @emails ? join (',', @emails) : '';
+
+  # List of "default" config, in [section, option, value]
+  my @config = (
+    ['notification', 'smtp_always_cc'        , $smtp_always_cc],
+    ['project'     , 'descr'                 , $descr],
+    ['ticket'      , 'default_component'     , $def_component],
+  );
+
+  for (@config) {
+    my ($section, $option, $value) = @{ $_ };
+
+    # Add new section, if necessary
+    $local_ini->AddSection ($section)
+      if not $local_ini->SectionExists ($section);
+
+    if (defined ($local_ini->val ($section, $option))) {
+      # Modify existing option
+      $local_ini->setval ($section, $option, $value);
+
+    } else {
+      # Add new option
+      $local_ini->newval ($section, $option, $value);
+    }
+  }
+
+  # Remove duplicated sections/options in the configuration file
+  for my $section (($local_ini->Sections)) {
+    # Remove comments
+    $local_ini->DeleteSectionComment ($section);
+
+    # Leave section in local configuration file if it does not exist in the
+    # central configuration file
+    next unless $central_ini->SectionExists ($section);
+
+    for my $parameter (($local_ini->Parameters ($section))) {
+      # Remove comments
+      $local_ini->DeleteParameterComment ($section, $parameter);
+
+      # Leave parameter in local configuration file if it does not exist in the
+      # central configuration file
+      my $central_value = $central_ini->val ($section, $parameter);
+      next unless defined $central_value;
+
+      # Remove local parameter if it is the same as the central one
+      if ($central_value eq $local_ini->val ($section, $parameter)) {
+        print 'Remove parameter: ', $parameter, ' in section: ', $section, "\n";
+        $local_ini->delval ($section, $parameter);
+      }
+    }
+
+    # Remove section if it is empty
+    if (not ($local_ini->Parameters ($section))) {
+      print 'Remove section: ', $section, "\n";
+      $local_ini->DeleteSection ($section);
+    }
+  }
+
+  # Rename original "trac.ini" to "trac.ini.orig"
+  rename $local_file, $local_file . '.orig';
+
+  # Output modifications to "trac.ini"
+  $local_ini->WriteConfig ($local_file);
+}
+
+# Finally...
+# ------------------------------------------------------------------------------
+print $this, ': finished normally.', "\n";
+exit;
+
+# ------------------------------------------------------------------------------
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/templates/utils/recover_svn.pl
===================================================================
--- LMDZ5/branches/testing/tools/fcm/templates/utils/recover_svn.pl	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/templates/utils/recover_svn.pl	(revision 1665)
@@ -0,0 +1,170 @@
+#!/usr/bin/perl
+# ------------------------------------------------------------------------------
+# NAME
+#   recover_svn.pl
+#
+# SYNOPSIS
+#   recover_svn.pl [<list of projects>]
+#
+# DESCRIPTION
+#   This command is used to recover live repositories from backups and dumps,
+#   using the following logic:
+#     1. If one or more <projects> are not specified, check the backup directory
+#        for list of projects and available backups.
+#     2. For each available project (or the specified <projects>), check if its
+#        live repository exists. If so, performs an integrity check.
+#     3. If the live repository does not exist or if the integrity check fails,
+#        recover by copying the backup into the live location.
+#     4. Determine the youngest revision of the live repository.
+#     5. Search the dump directory to see if there are dumps for newer
+#        reversions. If so, load them back to the live repository.
+#
+# COPYRIGHT
+#   (C) Crown copyright Met Office. All rights reserved.
+#   For further details please refer to the file COPYRIGHT.txt
+#   which you should have received as part of this distribution.
+# ------------------------------------------------------------------------------
+
+# Standard pragmas:
+use strict;
+use warnings;
+
+# Standard modules:
+use File::Basename;
+use File::Spec;
+use File::Path;
+
+# ------------------------------------------------------------------------------
+
+# Top level locations of live repositories, backups, dumps and hook scripts
+my $logname  = 'fcm';
+my $svn_live = File::Spec->catfile (
+  File::Spec->rootdir (), qw/data local/, $logname, qw/svn live/,
+);
+my $svn_back = File::Spec->catfile ((getpwnam $logname) [7], qw/svn backups/);
+my $svn_dump = File::Spec->catfile ((getpwnam $logname) [7], qw/svn dumps/);
+my $hook_dir = File::Spec->catfile (
+  (getpwnam $logname) [7], qw/FCM work Admin src hook/,
+);
+
+# Arguments
+my %projects = map {$_, 1} @ARGV;
+
+# Search the backup directory to see what are available
+opendir DIR, $svn_back
+  or die $svn_back, ': cannot read directory (', $!, '), abort';
+my %backups = ();
+while (my $file = readdir 'DIR') {
+  next if $file =~ /^\./;
+  next if $file !~ /\.tgz$/;
+  next unless -f File::Spec->catfile ($svn_back, $file);
+
+  (my $project = $file) =~ s/\.tgz$//;
+
+  # If project arguments specified, skip projects that are not in the list
+  next if %projects and not exists $projects{$project};
+
+  # Store project name and its backup location
+  $backups{$project} = File::Spec->catfile ($svn_back, $file);
+}
+closedir DIR;
+
+# Create the live directory if it does not exist
+mkpath $svn_live or die $svn_live, ': cannot create, abort' if not -d $svn_live;
+
+# Exit if no backups found (for list of specified projects)
+if (not keys %backups) {
+  print 'No backup',
+        (keys %projects ? join (' ', (' for', sort keys %projects)) : ''),
+        ' found in ', $svn_back, "\n";
+  exit;
+}
+
+# Search the live directory to see what are available
+for my $project (sort keys %backups) {
+  my $live_dir = File::Spec->catfile ($svn_live, $project);
+
+  # Recovery required if $live_dir does not exist
+  my $recovery = not -d $live_dir;
+
+  # Perform an integrity check if $live_dir exist
+  $recovery = system ('svnadmin', 'verify', $live_dir) unless $recovery;
+
+  if (not $recovery) {
+    print $project, ': live repository appears to be fine.', "\n";
+    next;
+  }
+
+  # Recover to a temporary location first
+  my $temp_dir = $live_dir . '.tmp';
+
+  if (-d $temp_dir) {
+    # Remove $temp_dir if it exists
+    print 'Removing ', $temp_dir, ' ...', "\n";
+    rmtree $temp_dir;
+  }
+
+  # Un-tar the backup
+  print 'Extracting from the backup archive ', $backups{$project}, "\n";
+  ! system (
+    qw/tar -x -z -C/, dirname ($backups{$project}), '-f', $backups{$project},
+  ) or die 'Cannot extract from the backup archive', $backups{$project};
+
+  (my $backup_dir = $backups{$project}) =~ s/\.tgz$//;
+
+  # Recover from backup
+  print 'Copying ', $backup_dir, ' to ', $temp_dir, ' ...', "\n";
+  my @command = ('svnadmin', 'hotcopy', $backup_dir, $temp_dir);
+  system (@command);
+  die join (' ', @command), ' failed (', $?, '), abort' if $?;
+
+  rmtree $backup_dir;
+
+  # Determine the youngest revision of the repository
+  @command     = ('svnlook', 'youngest', $temp_dir);
+  my $youngest = qx(@command)
+    or die $temp_dir, ': cannot determine youngest revision (', $?, ')';
+
+  # Search dump directory to see if there are any later dumps available
+  my $dump_dir = File::Spec->catfile ($svn_dump, $project);
+  
+  if (opendir DIR, $dump_dir) {
+    my @revs = grep {m/^\d+$/ and $_ > $youngest} readdir DIR;
+    closedir DIR;
+
+    # If newer dumps available, load each one back to the repository
+    for my $rev (sort {$a <=> $b} @revs) {
+      print 'Loading dump for revision ', $rev, ' to ', $temp_dir, ' ...', "\n";
+      my $command = 'svnadmin load ' . $temp_dir .
+                    ' <' . File::Spec->catfile ($dump_dir, $rev);
+      system ($command);
+      die $command, ' failed (', $?, '), abort' if $?;
+    }
+
+  } else {
+      warn $project, ': dump directory not available for project';
+  }
+
+  # Move temporary directory to live
+  if (-d $live_dir) {
+    # Remove $live_dir if it exists
+    print 'Removing ', $live_dir, ' ...', "\n";
+    rmtree $live_dir;
+
+    die $live_dir, ': cannot remove' if -d $live_dir;
+  }
+
+  print 'Moving ', $temp_dir, ' to ', $live_dir, ' ...', "\n";
+  rename $temp_dir, $live_dir or die $temp_dir, ': cannot move to: ', $live_dir;
+}
+
+# Reinstate the hook scripts
+my @command = (
+  File::Spec->catfile (dirname ($0), 'install_hook.pl'),
+  $hook_dir,
+  $svn_live,
+);
+
+exec @command or die 'Cannot exec install_hook.pl (', $!, ')';
+
+__END__
Index: LMDZ5/branches/testing/tools/fcm/tutorial/hook/pre-commit
===================================================================
--- LMDZ5/branches/testing/tools/fcm/tutorial/hook/pre-commit	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/tutorial/hook/pre-commit	(revision 1665)
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+# PRE-COMMIT HOOK
+#
+# The pre-commit hook is invoked before a Subversion txn is
+# committed.  Subversion runs this hook by invoking a program
+# (script, executable, binary, etc.) named 'pre-commit' (for which
+# this file is a template), with the following ordered arguments:
+#
+#   [1] REPOS-PATH   (the path to this repository)
+#   [2] TXN-NAME     (the name of the txn about to be committed)
+#
+# The default working directory for the invocation is undefined, so
+# the program should set one explicitly if it cares.
+#
+# If the hook program exits with success, the txn is committed; but
+# if it exits with failure (non-zero), the txn is aborted, no commit
+# takes place, and STDERR is returned to the client.   The hook
+# program can use the 'svnlook' utility to help it examine the txn.
+#
+# On a Unix system, the normal procedure is to have 'pre-commit'
+# invoke other programs to do the real work, though it may do the
+# work itself too.
+#
+#   ***  NOTE: THE HOOK PROGRAM MUST NOT MODIFY THE TXN, EXCEPT  ***
+#   ***  FOR REVISION PROPERTIES (like svn:log or svn:author).   ***
+#
+#   This is why we recommend using the read-only 'svnlook' utility.
+#   In the future, Subversion may enforce the rule that pre-commit
+#   hooks should not modify the versioned data in txns, or else come
+#   up with a mechanism to make it safe to do so (by informing the
+#   committing client of the changes).  However, right now neither
+#   mechanism is implemented, so hook writers just have to be careful.
+#
+# Note that 'pre-commit' must be executable by the user(s) who will
+# invoke it (typically the user httpd runs as), and that user must
+# have filesystem-level permission to access the repository.
+#
+# On a Windows system, you should name the hook program
+# 'pre-commit.bat' or 'pre-commit.exe',
+# but the basic idea is the same.
+#
+# The hook program typically does not inherit the environment of
+# its parent process.  For example, a common problem is for the
+# PATH environment variable to not be set to its usual value, so
+# that subprograms fail to launch unless invoked via absolute path.
+# If you're having unexpected problems with a hook program, the
+# culprit may be unusual (or missing) environment variables.
+
+REPOS="$1"
+TXN="$2"
+
+# Check that the author of this commit has the rights to perform
+# the commit on the files and directories being modified.
+${REPOS}/hooks/svnperms.py -r "$REPOS" -t "$TXN" -f ${REPOS}/hooks/svnperms.conf || exit 1
+
+# All checks passed, so allow the commit.
+exit 0
Index: LMDZ5/branches/testing/tools/fcm/tutorial/hook/svnperms.conf
===================================================================
--- LMDZ5/branches/testing/tools/fcm/tutorial/hook/svnperms.conf	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/tutorial/hook/svnperms.conf	(revision 1665)
@@ -0,0 +1,5 @@
+## Configuration file for svnperms.py. ##
+
+[tutorial_svn]
+tutorial/trunk/.* = *()
+tutorial/branches/[^/]+/.* = *(add,remove,update)
Index: LMDZ5/branches/testing/tools/fcm/tutorial/hook/svnperms.py
===================================================================
--- LMDZ5/branches/testing/tools/fcm/tutorial/hook/svnperms.py	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/tutorial/hook/svnperms.py	(revision 1665)
@@ -0,0 +1,311 @@
+#!/usr/bin/env python
+
+# $HeadURL: https://svn.collab.net/repos/svn/trunk/tools/hook-scripts/svnperms.py $
+# $LastChangedDate: 2005-03-17 04:39:51 -0600 (Thu, 17 Mar 2005) $
+# $LastChangedBy: maxb $
+# $LastChangedRevision: 13456 $
+
+import commands
+import sys, os
+import getopt
+import re
+
+__author__ = "Gustavo Niemeyer <niemeyer@conectiva.com>"
+
+class Error(Exception): pass
+
+SECTION = re.compile(r'\[([^]]+)\]')
+OPTION = re.compile(r'(\S+)\s*=\s*(.*)$')
+
+class Config:
+    def __init__(self, filename):
+        # Options are stored in __sections_list like this:
+        # [(sectname, [(optname, optval), ...]), ...]
+        self._sections_list = []
+        self._sections_dict = {}
+        self._read(filename)
+
+    def _read(self, filename):
+        # Use the same logic as in ConfigParser.__read()
+        file = open(filename)
+        cursectdict = None
+        optname = None
+        lineno = 0
+        for line in file.xreadlines():
+            lineno = lineno + 1
+            if line.isspace() or line[0] == '#':
+                continue
+            if line[0].isspace() and cursectdict is not None and optname:
+                value = line.strip()
+                cursectdict[optname] = "%s %s" % (cursectdict[optname], value)
+                cursectlist[-1][1] = "%s %s" % (cursectlist[-1][1], value)
+            else:
+                m = SECTION.match(line)
+                if m:
+                    sectname = m.group(1)
+                    cursectdict = self._sections_dict.setdefault(sectname, {})
+                    cursectlist = []
+                    self._sections_list.append((sectname, cursectlist))
+                    optname = None
+                elif cursectdict is None:
+                    raise Error, "%s:%d: no section header" % \
+                                 (filename, lineno)
+                else:
+                    m = OPTION.match(line)
+                    if m:
+                        optname, optval = m.groups()
+                        optval = optval.strip()
+                        cursectdict[optname] = optval
+                        cursectlist.append([optname, optval])
+                    else:
+                        raise Error, "%s:%d: parsing error" % \
+                                     (filename, lineno)
+
+    def sections(self):
+        return self._sections_dict.keys()
+
+    def options(self, section):
+        return self._sections_dict.get(section, {}).keys()
+
+    def get(self, section, option, default=None):
+        return self._sections_dict.get(option, default)
+
+    def walk(self, section, option=None):
+        ret = []
+        for sectname, options in self._sections_list:
+            if sectname == section:
+                for optname, value in options:
+                    if not option or optname == option:
+                        ret.append((optname, value))
+        return ret
+
+
+class Permission:
+    def __init__(self):
+        self._group = {}
+        self._permlist = []
+    
+    def parse_groups(self, groupsiter):
+        for option, value in groupsiter:
+            self._group[option] = value.split()
+            
+    def parse_perms(self, permsiter):
+        for option, value in permsiter:
+            # Paths never start with /, so remove it if provided
+            if option[0] == "/":
+                option = option[1:]
+            pattern = re.compile("^%s$" % option)
+            for entry in value.split():
+                openpar, closepar = entry.find("("), entry.find(")")
+                groupsusers = entry[:openpar].split(",")
+                perms = entry[openpar+1:closepar].split(",")
+                users = []
+                for groupuser in groupsusers:
+                    if groupuser[0] == "@":
+                        try:
+                            users.extend(self._group[groupuser[1:]])
+                        except KeyError:
+                            raise Error, "group '%s' not found" % \
+                                         groupuser[1:]
+                    else:
+                        users.append(groupuser)
+                self._permlist.append((pattern, users, perms))
+
+    def get(self, user, path):
+        ret = []
+        for pattern, users, perms in self._permlist:
+            if pattern.match(path) and (user in users or "*" in users):
+                ret = perms
+        return ret
+
+class SVNLook:
+    def __init__(self, repospath, txn=None, rev=None):
+        self.repospath = repospath
+        self.txn = txn
+        self.rev = rev
+
+    def _execcmd(self, *cmd, **kwargs):
+        cmdstr = " ".join(cmd)
+        status, output = commands.getstatusoutput(cmdstr)
+        if status != 0:
+            sys.stderr.write(cmdstr)
+            sys.stderr.write("\n")
+            sys.stderr.write(output)
+            raise Error, "command failed: %s\n%s" % (cmdstr, output)
+        return status, output
+
+    def _execsvnlook(self, cmd, *args, **kwargs):
+        execcmd_args = ["svnlook", cmd, self.repospath]
+        self._add_txnrev(execcmd_args, kwargs)
+        execcmd_args += args
+        execcmd_kwargs = {}
+        keywords = ["show", "noerror"]
+        for key in keywords:
+            if kwargs.has_key(key):
+                execcmd_kwargs[key] = kwargs[key]
+        return self._execcmd(*execcmd_args, **execcmd_kwargs)
+
+    def _add_txnrev(self, cmd_args, received_kwargs):
+        if received_kwargs.has_key("txn"):
+            txn = received_kwargs.get("txn")
+            if txn is not None:
+                cmd_args += ["-t", txn]
+        elif self.txn is not None:
+            cmd_args += ["-t", self.txn]
+        if received_kwargs.has_key("rev"):
+            rev = received_kwargs.get("rev")
+            if rev is not None:
+                cmd_args += ["-r", rev]
+        elif self.rev is not None:
+            cmd_args += ["-r", self.rev]
+
+    def changed(self, **kwargs):
+        status, output = self._execsvnlook("changed", **kwargs)
+        if status != 0:
+            return None
+        changes = []
+        for line in output.splitlines():
+            line = line.rstrip()
+            if not line: continue
+            entry = [None, None, None]
+            changedata, changeprop, path = None, None, None
+            if line[0] != "_":
+                changedata = line[0]
+            if line[1] != " ":
+                changeprop = line[1]
+            path = line[4:]
+            changes.append((changedata, changeprop, path))
+        return changes
+
+    def author(self, **kwargs):
+        status, output = self._execsvnlook("author", **kwargs)
+        if status != 0:
+            return None
+        return output.strip()
+
+
+def check_perms(filename, section, repos, txn=None, rev=None, author=None):
+    svnlook = SVNLook(repos, txn=txn, rev=rev)
+    if author is None:
+        author = svnlook.author()
+    changes = svnlook.changed()
+    try:
+        config = Config(filename)
+    except IOError:
+        raise Error, "can't read config file "+filename
+    if not section in config.sections():
+        raise Error, "section '%s' not found in config file" % section
+    perm = Permission()
+    perm.parse_groups(config.walk("groups"))
+    perm.parse_groups(config.walk(section+" groups"))
+    perm.parse_perms(config.walk(section))
+    permerrors = []
+    for changedata, changeprop, path in changes:
+        pathperms = perm.get(author, path)
+        if changedata == "A" and "add" not in pathperms:
+            permerrors.append("you can't add "+path)
+        elif changedata == "U" and "update" not in pathperms:
+            permerrors.append("you can't update "+path)
+        elif changedata == "D" and "remove" not in pathperms:
+            permerrors.append("you can't remove "+path)
+        elif changeprop == "U" and "update" not in pathperms:
+            permerrors.append("you can't update properties of "+path)
+        #else:
+        #    print "cdata=%s cprop=%s path=%s perms=%s" % \
+        #          (str(changedata), str(changeprop), path, str(pathperms))
+    if permerrors:
+        permerrors.insert(0, "you don't have enough permissions for "
+                             "this transaction:")
+        raise Error, "\n".join(permerrors)
+
+
+# Command:
+
+USAGE = """\
+Usage: svnperms.py OPTIONS
+
+Options:
+    -r PATH    Use repository at PATH to check transactions
+    -t TXN     Query transaction TXN for commit information
+    -f PATH    Use PATH as configuration file (default is repository
+               path + /conf/svnperms.conf)
+    -s NAME    Use section NAME as permission section (default is
+               repository name, extracted from repository path)
+    -R REV     Query revision REV for commit information (for tests)
+    -A AUTHOR  Check commit as if AUTHOR had commited it (for tests)
+    -h         Show this message
+"""
+
+class MissingArgumentsException(Exception):
+    "Thrown when required arguments are missing."
+    pass
+
+def parse_options():
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], "f:s:r:t:R:A:h", ["help"])
+    except getopt.GetoptError, e:
+        raise Error, e.msg
+    class Options: pass
+    obj = Options()
+    obj.filename = None
+    obj.section = None
+    obj.repository = None
+    obj.transaction = None
+    obj.revision = None
+    obj.author = None
+    for opt, val in opts:
+        if opt == "-f":
+            obj.filename = val
+        elif opt == "-s":
+            obj.section = val
+        elif opt == "-r":
+            obj.repository = val
+        elif opt == "-t":
+            obj.transaction = val
+        elif opt == "-R":
+            obj.revision = val
+        elif opt == "-A":
+            obj.author = val
+        elif opt in ["-h", "--help"]:
+            sys.stdout.write(USAGE)
+            sys.exit(0)
+    missingopts = []
+    if not obj.repository:
+        missingopts.append("repository")
+    if not (obj.transaction or obj.revision):
+        missingopts.append("either transaction or a revision")
+    if missingopts:
+        raise MissingArgumentsException, \
+              "missing required option(s): " + ", ".join(missingopts)
+    obj.repository = os.path.abspath(obj.repository)
+    if obj.filename is None:
+        obj.filename = os.path.join(obj.repository, "conf", "svnperms.conf")
+    if obj.section is None:
+        obj.section = os.path.basename(obj.repository)
+    if not (os.path.isdir(obj.repository) and
+            os.path.isdir(os.path.join(obj.repository, "db")) and
+            os.path.isdir(os.path.join(obj.repository, "hooks")) and
+            os.path.isfile(os.path.join(obj.repository, "format"))):
+        raise Error, "path '%s' doesn't look like a repository" % \
+                     obj.repository
+        
+    return obj
+
+def main():
+    try:
+        opts = parse_options()
+        check_perms(opts.filename, opts.section,
+                    opts.repository, opts.transaction, opts.revision,
+                    opts.author)
+    except MissingArgumentsException, e:
+        sys.stderr.write("%s\n" % str(e))
+        sys.stderr.write(USAGE)
+        sys.exit(1)
+    except Error, e:
+        sys.stderr.write("error: %s\n" % str(e))
+        sys.exit(1)
+
+if __name__ == "__main__":
+    main()
+
+# vim:et:ts=4:sw=4
Index: LMDZ5/branches/testing/tools/fcm/tutorial/repos/tutorial.dump
===================================================================
--- LMDZ5/branches/testing/tools/fcm/tutorial/repos/tutorial.dump	(revision 1665)
+++ LMDZ5/branches/testing/tools/fcm/tutorial/repos/tutorial.dump	(revision 1665)
@@ -0,0 +1,305 @@
+SVN-fs-dump-format-version: 3
+
+UUID: cb858ce8-0f05-0410-9e64-efa98b760b62
+
+Revision-number: 1
+Prop-content-length: 112
+Content-length: 112
+
+K 7
+svn:log
+V 14
+Initial import
+K 10
+svn:author
+V 3
+fcm
+K 8
+svn:date
+V 27
+2005-11-08T16:03:11.054362Z
+PROPS-END
+
+Node-path: tutorial
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: tutorial/trunk
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: tutorial/trunk/cfg
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: tutorial/trunk/cfg/ext.cfg
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 491
+Text-content-md5: ee678001bbc0789983e79d365eff2c9d
+Content-length: 501
+
+PROPS-END
+CFG::TYPE                               ext
+CFG::VERSION                            1.0
+
+DEST::ROOTDIR                           $PWD
+
+REPOS::tutorial::trunk                  fcm:tutorial_tr/src
+EXPSRC::tutorial::trunk
+
+BLD::TOOL::FC                           ifc
+BLD::TOOL::FFLAGS                       -O3
+
+BLD::TOOL::CC                           gcc
+BLD::TOOL::CFLAGS                       -O3
+
+BLD::TOOL::FFLAGS::tutorial::subroutine -O3 -i8
+
+BLD::TOOL::LD                           ifc
+
+
+Node-path: tutorial/trunk/doc
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: tutorial/trunk/doc/hello.html
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 691
+Text-content-md5: 1cc3c9a6d7734c3667776d7a5f81162d
+Content-length: 701
+
+PROPS-END
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+  <title>Hello</title>
+  <meta name="author" content="FCM Team">
+  <meta name="descriptions" content="Hello">
+  <meta name="keywords" content="hello">
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <link rel="stylesheet" href="stylesheet.css" type="text/css">
+</head>
+
+<body>
+  <p>Hello from the FCM team!</p>
+  <hr>
+
+  <address>
+    &copy; Crown copyright <script type="text/javascript">
+    <!--
+      var mtime = new Date (document.lastModified)
+      document.write (mtime.getUTCFullYear ())
+    //-->
+    </script> Met Office. All rights reserved.
+  </address>
+</body>
+</html>
+
+
+Node-path: tutorial/trunk/src
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: tutorial/trunk/src/subroutine
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: tutorial/trunk/src/subroutine/hello_c.c
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 85
+Text-content-md5: a4e47e0c187a4e16d107175808ad1699
+Content-length: 95
+
+PROPS-END
+#include <stdio.h>
+
+void hello_c_ () {
+  printf ("%s\n", "Hello_C: Hello World!");
+}
+
+
+Node-path: tutorial/trunk/src/subroutine/hello_sub.f90
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 341
+Text-content-md5: 5e7b7a11e3f94b1885356379d903fd1d
+Content-length: 351
+
+PROPS-END
+SUBROUTINE Hello_Sub
+
+USE Hello_Constants, ONLY: hello_string
+
+IMPLICIT NONE
+
+CHARACTER (LEN=*), PARAMETER :: this = 'Hello_Sub'
+INTEGER :: i
+
+! DEPENDS ON: hello_c.o
+EXTERNAL Hello_C
+
+WRITE (*, '(A)') this // ': ' // TRIM (hello_string)
+WRITE (*, '(A,I0)') this // ': maximum integer: ', HUGE (i)
+
+CALL Hello_C ()
+
+END SUBROUTINE Hello_Sub
+
+
+Node-path: tutorial/trunk/src/module
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: tutorial/trunk/src/module/hello_constants.f90
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 115
+Text-content-md5: c57ebb7151db2032b82eae2f6712bca7
+Content-length: 125
+
+PROPS-END
+MODULE Hello_Constants
+
+CHARACTER (LEN=80), PARAMETER :: hello_string = 'Hello World!'
+
+END MODULE Hello_Constants
+
+
+Node-path: tutorial/trunk/src/program
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: tutorial/trunk/src/program/hello.f90
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 240
+Text-content-md5: bfc42450c107f935b77d50422b85a6e7
+Content-length: 250
+
+PROPS-END
+PROGRAM Hello
+
+USE Hello_Constants, ONLY: hello_string
+
+IMPLICIT NONE
+
+INCLUDE 'hello_sub.interface'
+
+CHARACTER (LEN=*), PARAMETER :: this = 'Hello'
+
+WRITE (*, '(A)') this // ': ' // TRIM (hello_string)
+CALL Hello_Sub ()
+
+END PROGRAM Hello
+
+
+Node-path: tutorial/branches
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: tutorial/tags
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 2
+Prop-content-length: 232
+Content-length: 232
+
+K 7
+svn:log
+V 157
+Change greeting messages from ''Hello World'' to ''Hello Earth'' in C code and Fortran module. Add copyright header to Fortran module. This change fixes #1.
+
+K 8
+svn:date
+V 27
+2005-11-08T16:35:08.365632Z
+PROPS-END
+
+Node-path: tutorial/trunk/src/module/hello_constants.f90
+Node-kind: file
+Node-action: change
+Text-delta: true
+Text-content-length: 106
+Text-content-md5: 2396c2f40dde69b32a036dee9c9e9645
+Content-length: 106
+
+SVNs*[·O¤! (C) Crown copyright Met Office. All rights reserved.
+Earth!'
+
+END MODULE Hello_Constants
+
+
+Node-path: tutorial/trunk/src/subroutine/hello_c.c
+Node-kind: file
+Node-action: change
+Text-delta: true
+Text-content-length: 25
+Text-content-md5: 8c87c7a561710945bd407e9687fdedb3
+Content-length: 25
+
+SVNUU
+IEarth!");
+}
+
+
