m_StrTemplate.F90 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  3. !-----------------------------------------------------------------------
  4. ! CVS m_StrTemplate.F90,v 1.6 2004-04-21 22:54:46 jacob Exp
  5. ! CVS MCT_2_8_0
  6. !BOP -------------------------------------------------------------------
  7. !
  8. ! !MODULE: m_StrTemplate - A template formatting a string with variables
  9. !
  10. ! !DESCRIPTION:
  11. !
  12. ! A template resolver formatting a string with a string variable
  13. ! and time variables. The format descriptors are similar to those
  14. ! used in the GrADS.
  15. !
  16. ! "%y4" substitute with a 4 digit year
  17. ! "%y2" a 2 digit year
  18. ! "%m1" a 1 or 2 digit month
  19. ! "%m2" a 2 digit month
  20. ! "%mc" a 3 letter month in lower cases
  21. ! "%Mc" a 3 letter month with a leading letter in upper case
  22. ! "%MC" a 3 letter month in upper cases
  23. ! "%d1" a 1 or 2 digit day
  24. ! "%d2" a 2 digit day
  25. ! "%h1" a 1 or 2 digit hour
  26. ! "%h2" a 2 digit hour
  27. ! "%h3" a 3 digit hour (?)
  28. ! "%n2" a 2 digit minute
  29. ! "%s" a string variable
  30. ! "%%" a "%"
  31. !
  32. ! !INTERFACE:
  33. module m_StrTemplate
  34. implicit none
  35. private ! except
  36. public :: StrTemplate ! Substitute variables in a template
  37. interface StrTemplate
  38. module procedure strTemplate_
  39. end interface
  40. ! !REVISION HISTORY:
  41. ! 01Jun99 - Jing Guo <guo@dao.gsfc.nasa.gov>
  42. ! - initial prototype/prolog/code
  43. ! 19Jan01 - Jay Larson <larson@mcs.anl.gov> - removed numerous
  44. ! double-quote characters appearing inside single-quote
  45. ! blocks. This was done to comply with pgf90. Also,
  46. ! numerous double-quote characters were removed from
  47. ! within comment blocks because pgf90 kept trying to
  48. ! interpret them (spooky).
  49. !EOP ___________________________________________________________________
  50. character(len=*),parameter :: myname='MCT(MPEU)::m_StrTemplate'
  51. character(len=3),parameter,dimension(12) :: mon_lc = (/ &
  52. 'jan','feb','mar','apr','may','jun', &
  53. 'jul','aug','sep','oct','nov','dec' /)
  54. character(len=3),parameter,dimension(12) :: mon_wd = (/ &
  55. 'Jan','Feb','Mar','Apr','May','Jun', &
  56. 'Jul','Aug','Sep','Oct','Nov','Dec' /)
  57. character(len=3),parameter,dimension(12) :: mon_uc = (/ &
  58. 'JAN','FEB','MAR','APR','MAY','JUN', &
  59. 'JUL','AUG','SEP','OCT','NOV','DEC' /)
  60. contains
  61. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  62. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  63. !BOP -------------------------------------------------------------------
  64. !
  65. ! !IROUTINE: strTemplate_ - expanding a format template to a string
  66. !
  67. ! !DESCRIPTION:
  68. !
  69. ! !INTERFACE:
  70. subroutine strTemplate_(str,tmpl,class,xid,nymd,nhms,stat)
  71. use m_chars, only : uppercase
  72. use m_stdio, only : stderr
  73. use m_die, only : die
  74. implicit none
  75. character(len=*),intent(out) :: str ! the output
  76. character(len=*),intent(in ) :: tmpl ! a "format"
  77. character(len=*),intent(in ),optional :: class
  78. ! choose a UNIX or a GrADS(defulat) type format
  79. character(len=*),intent(in ),optional :: xid
  80. ! a string substituting a '%s'. Trailing
  81. ! spaces will be ignored
  82. integer,intent(in ),optional :: nymd
  83. ! yyyymmdd, substituting '%y4', '%y2', '%m1',
  84. ! '%m2', '%mc', '%Mc', and '%MC'
  85. integer,intent(in ),optional :: nhms
  86. ! hhmmss, substituting '%h1', '%h2', '%h3',
  87. ! and '%n2'
  88. integer,intent(out),optional :: stat
  89. ! error code
  90. ! !REVISION HISTORY:
  91. ! 03Jun99 - Jing Guo <guo@dao.gsfc.nasa.gov>
  92. ! - initial prototype/prolog/code
  93. ! 08Jan03 - R. Jacob <jacob@mcs.anl.gov> Small change to get
  94. ! around IBM compiler bug. Cant have character valued functions
  95. ! in case statements. Fix found by Everest Ong.
  96. !EOP ___________________________________________________________________
  97. character(len=*),parameter :: myname_=myname//'::strTemplate_'
  98. character(len=16) :: tmpl_class
  99. character(len=16) :: tmp_upper
  100. tmpl_class="GX"
  101. if(present(class)) tmpl_class=class
  102. tmp_upper = uppercase(tmpl_class)
  103. select case(tmp_upper)
  104. case("GX","GRADS")
  105. call GX_(str,tmpl,xid,nymd,nhms,stat)
  106. !case("UX","UNIX") ! yet to be implemented
  107. ! call UX_(str,tmpl,xid,nymd,nhms,stat)
  108. case default
  109. write(stderr,'(4a)') myname_,': unknown class: ', &
  110. trim(tmpl_class),'.'
  111. if(.not.present(stat)) call die(myname_)
  112. stat=-1
  113. return
  114. end select
  115. end subroutine strTemplate_
  116. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  117. ! NASA/GSFC, Data Assimilation Office, Code 910.3, GEOS/DAS !
  118. !BOP -------------------------------------------------------------------
  119. !
  120. ! !IROUTINE: GX_ - evaluate a GrADS style string template
  121. !
  122. ! !DESCRIPTION:
  123. !
  124. ! !INTERFACE:
  125. subroutine GX_(str,tmpl,xid,nymd,nhms,stat)
  126. use m_stdio,only : stderr
  127. use m_die, only : die,perr
  128. implicit none
  129. character(len=*),intent(out) :: str
  130. character(len=*),intent(in ) :: tmpl
  131. character(len=*),optional,intent(in) :: xid
  132. integer,optional,intent(in) :: nymd
  133. integer,optional,intent(in) :: nhms
  134. integer,optional,intent(out) :: stat
  135. ! !REVISION HISTORY:
  136. ! 01Jun99 - Jing Guo <guo@dao.gsfc.nasa.gov>
  137. ! - initial prototype/prolog/code
  138. ! 19Jan01 - Jay Larson <larson@mcs.anl.gov> - added
  139. ! variable c1c2, to store c1//c2, which pgf90
  140. ! would not allow as an argument to the 'select case'
  141. ! statement.
  142. !EOP ___________________________________________________________________
  143. character(len=*),parameter :: myname_=myname//'::GX_'
  144. integer :: iy4,iy2,imo,idy
  145. integer :: ihr,imn
  146. integer :: i,i1,i2,m,k
  147. integer :: ln_tmpl,ln_str
  148. integer :: istp,kstp
  149. character(len=1) :: c0,c1,c2
  150. character(len=2) :: c1c2
  151. character(len=4) :: sbuf
  152. !________________________________________
  153. ! Determine iyr, imo, and idy
  154. iy4=-1
  155. iy2=-1
  156. imo=-1
  157. idy=-1
  158. if(present(nymd)) then
  159. if(nymd < 0) then
  160. call perr(myname_,'nymd < 0',nymd)
  161. if(.not.present(stat)) call die(myname_)
  162. stat=1
  163. return
  164. endif
  165. i=nymd
  166. iy4=i/10000
  167. iy2=mod(iy4,100)
  168. i=mod(i,10000)
  169. imo=i/100
  170. i=mod(i,100)
  171. idy=i
  172. endif
  173. !________________________________________
  174. ! Determine ihr and imn
  175. ihr=-1
  176. imn=-1
  177. if(present(nhms)) then
  178. if(nhms < 0) then
  179. call perr(myname_,'nhms < 0',nhms)
  180. if(.not.present(stat)) call die(myname_)
  181. stat=1
  182. return
  183. endif
  184. i=nhms
  185. ihr=i/10000
  186. i=mod(i,10000)
  187. imn=i/100
  188. endif
  189. !________________________________________
  190. ln_tmpl=len_trim(tmpl) ! size of the format template
  191. ln_str =len(str) ! size of the output string
  192. !________________________________________
  193. if(present(stat)) stat=0
  194. str=""
  195. i=0; istp=1
  196. k=1; kstp=1
  197. do while( i+istp <= ln_tmpl ) ! A loop over all tokens in (tmpl)
  198. if(k>ln_Str) exit ! truncate the output here.
  199. i=i+istp
  200. c0=tmpl(i:i)
  201. select case(c0)
  202. case ("%")
  203. !________________________________________
  204. c1=""
  205. i1=i+1
  206. if(i1 <= ln_Tmpl) c1=tmpl(i1:i1)
  207. !________________________________________
  208. select case(c1)
  209. case("s")
  210. if(.not.present(xid)) then
  211. write(stderr,'(2a)') myname_, &
  212. ': optional argument expected, "xid="'
  213. if(.not.present(stat)) call die(myname_)
  214. stat=1
  215. return
  216. endif
  217. istp=2
  218. m=min(k+len_trim(xid)-1,ln_str)
  219. str(k:m)=xid
  220. k=m+1
  221. cycle
  222. case("%")
  223. istp=2
  224. str(k:k)="%"
  225. k=k+1 ! kstp=1
  226. cycle
  227. case default
  228. c2=""
  229. i2=i+2
  230. if(i2 <= ln_Tmpl) c2=tmpl(i2:i2)
  231. !________________________________________
  232. c1c2 = c1 // c2
  233. select case(c1c2)
  234. case("y4","y2","m1","m2","mc","Mc","MC","d1","d2")
  235. if(.not.present(nymd)) then
  236. write(stderr,'(2a)') myname_, &
  237. ': optional argument expected, "nymd="'
  238. if(.not.present(stat)) call die(myname_)
  239. stat=1
  240. return
  241. endif
  242. istp=3
  243. case("h1","h2","h3","n2")
  244. if(.not.present(nhms)) then
  245. write(stderr,'(2a)') myname_, &
  246. ': optional argument expected, "nhms="'
  247. if(.not.present(stat)) call die(myname_)
  248. stat=1
  249. return
  250. endif
  251. istp=3
  252. case default
  253. write(stderr,'(4a)') myname_, &
  254. ': invalid template entry: ',trim(tmpl(i:)),'.'
  255. if(.not.present(stat)) call die(myname_)
  256. stat=2
  257. return
  258. end select ! case(c1//c2)
  259. end select ! case(c1)
  260. !________________________________________
  261. select case(c1)
  262. case("y")
  263. select case(c2)
  264. case("2")
  265. write(sbuf,'(i2.2)') iy2
  266. kstp=2
  267. case("4")
  268. write(sbuf,'(i4.4)') iy4
  269. kstp=4
  270. case default
  271. write(stderr,'(4a)') myname_, &
  272. ': invalid template entry: ',trim(tmpl(i:)),'.'
  273. if(.not.present(stat)) call die(myname_)
  274. stat=2
  275. return
  276. end select
  277. case("m")
  278. select case(c2)
  279. case("1")
  280. if(imo < 10) then
  281. write(sbuf,'(i1)') imo
  282. kstp=1
  283. else
  284. write(sbuf,'(i2)') imo
  285. kstp=2
  286. endif
  287. case("2")
  288. write(sbuf,'(i2.2)') imo
  289. kstp=2
  290. case("c")
  291. sbuf=mon_lc(imo)
  292. kstp=3
  293. case default
  294. write(stderr,'(4a)') myname_, &
  295. ': invalid template entry: ',trim(tmpl(i:)),'.'
  296. if(.not.present(stat)) call die(myname_)
  297. stat=2
  298. return
  299. end select
  300. case("M")
  301. select case(c2)
  302. case("c")
  303. sbuf=mon_wd(imo)
  304. kstp=3
  305. case("C")
  306. sbuf=mon_uc(imo)
  307. kstp=3
  308. case default
  309. write(stderr,'(4a)') myname_, &
  310. ': invalid template entry: ',trim(tmpl(i:)),'.'
  311. if(.not.present(stat)) call die(myname_)
  312. stat=2
  313. return
  314. end select
  315. case("d")
  316. select case(c2)
  317. case("1")
  318. if(idy < 10) then
  319. write(sbuf,'(i1)') idy
  320. kstp=1
  321. else
  322. write(sbuf,'(i2)') idy
  323. kstp=2
  324. endif
  325. case("2")
  326. write(sbuf,'(i2.2)') idy
  327. kstp=2
  328. case default
  329. write(stderr,'(4a)') myname_, &
  330. ': invalid template entry: ',trim(tmpl(i:)),'.'
  331. if(.not.present(stat)) call die(myname_)
  332. stat=2
  333. return
  334. end select
  335. case("h")
  336. select case(c2)
  337. case("1")
  338. if(ihr < 10) then
  339. write(sbuf,'(i1)') ihr
  340. kstp=1
  341. else
  342. write(sbuf,'(i2)') ihr
  343. kstp=2
  344. endif
  345. case("2")
  346. write(sbuf,'(i2.2)') ihr
  347. kstp=2
  348. case("3")
  349. write(sbuf,'(i3.3)') ihr
  350. kstp=3
  351. case default
  352. write(stderr,'(4a)') myname_, &
  353. ': invalid template entry: ',trim(tmpl(i:)),'.'
  354. if(.not.present(stat)) call die(myname_)
  355. stat=2
  356. return
  357. end select
  358. case("n")
  359. select case(c2)
  360. case("2")
  361. write(sbuf,'(i2.2)') imn
  362. kstp=2
  363. case default
  364. write(stderr,'(4a)') myname_, &
  365. ': invalid template entry: ',trim(tmpl(i:)),'.'
  366. if(.not.present(stat)) call die(myname_)
  367. stat=2
  368. return
  369. end select
  370. case default
  371. write(stderr,'(4a)') myname_, &
  372. ': invalid template entry: ',trim(tmpl(i:)),'.'
  373. if(.not.present(stat)) call die(myname_)
  374. stat=2
  375. return
  376. end select ! case(c1)
  377. m=min(k+kstp-1,ln_Str)
  378. str(k:m)=sbuf
  379. k=m+1
  380. case default
  381. istp=1
  382. str(k:k)=tmpl(i:i)
  383. k=k+1
  384. end select ! case(c0)
  385. end do
  386. end subroutine GX_
  387. end module m_StrTemplate