Merge lp:~albertog/xmlf90/wxml-upgrade into lp:xmlf90

Proposed by Alberto Garcia
Status: Merged
Approved by: Alberto Garcia
Approved revision: 10
Merged at revision: 9
Proposed branch: lp:~albertog/xmlf90/wxml-upgrade
Merge into: lp:xmlf90
Diff against target: 1492 lines (+745/-201)
11 files modified
Examples/wxml/m_pseudo_utils.f90 (+12/-11)
Examples/wxml/simple.f90 (+8/-4)
wxml/m_wxml_array_str.f90 (+77/-0)
wxml/m_wxml_buffer.f90 (+41/-12)
wxml/m_wxml_core.f90 (+220/-61)
wxml/m_wxml_dictionary.f90 (+131/-62)
wxml/m_wxml_elstack.f90 (+53/-23)
wxml/m_wxml_overloads.f90 (+143/-0)
wxml/m_wxml_text.F90 (+47/-23)
wxml/makefile (+12/-2)
wxml/xmlf90_wxml.f90 (+1/-3)
To merge this branch: bzr merge lp:~albertog/xmlf90/wxml-upgrade
Reviewer Review Type Date Requested Status
Alberto Garcia Approve
Review via email: mp+284429@code.launchpad.net

Description of the change

Updated wxml code, brought from the libpsml distribution.

To post a comment you must log in.
Revision history for this message
Alberto Garcia (albertog) wrote :

The wxml test shows that there has been a regression: "real" attribute values are not trimmed.

review: Needs Fixing
lp:~albertog/xmlf90/wxml-upgrade updated
10. By Alberto Garcia

Trim attribute values when using the overloaded interface

Attribute values can be written in the form

pi = 3.1416
call xml_AddAttribute(xf,"key",pi [,fmt="(f6.2)"])

which internally calls the str() function to convert
the real (or integer, etc) to a string, which is now
trimmed.

Revision history for this message
Alberto Garcia (albertog) wrote :

OK. I will merge it now.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Examples/wxml/m_pseudo_utils.f90'
2--- Examples/wxml/m_pseudo_utils.f90 2016-01-15 15:49:14 +0000
3+++ Examples/wxml/m_pseudo_utils.f90 2016-01-30 12:34:50 +0000
4@@ -183,7 +183,8 @@
5 call xml_AddAttribute(xf,"version","0.5")
6 call xml_NewElement(xf,"header")
7 call xml_AddAttribute(xf,"symbol",trim(p%name))
8-call xml_AddAttribute(xf,"zval",trim(str(p%zval)))
9+!call xml_AddAttribute(xf,"zval",trim(str(p%zval)))
10+call xml_AddAttribute(xf,"zval",p%zval) ! Overloaded
11 call xml_AddAttribute(xf,"creator",trim(p%creator))
12 call xml_AddAttribute(xf,"date",trim(p%date))
13 call xml_AddAttribute(xf,"flavor",trim(p%flavor))
14@@ -206,27 +207,27 @@
15 call xml_NewElement(xf,"grid")
16 call xml_AddAttribute(xf,"type","log")
17 call xml_AddAttribute(xf,"units","bohr")
18- call xml_AddAttribute(xf,"scale",trim(str(p%grid_scale)))
19- call xml_AddAttribute(xf,"step",trim(str(p%grid_step)))
20- call xml_AddAttribute(xf,"npts",trim(str(p%nr-1)))
21-call xml_EndElement(xf,"grid")
22+ call xml_AddAttribute(xf,"scale",p%grid_scale)
23+ call xml_AddAttribute(xf,"step",p%grid_step)
24+ call xml_AddAttribute(xf,"npts",p%nr-1)
25+ call xml_EndElement(xf,"grid")
26
27 call xml_NewElement(xf,"semilocal")
28
29 call xml_AddAttribute(xf,"units","rydberg")
30 call xml_AddAttribute(xf,"format","r*V")
31- call xml_AddAttribute(xf,"npots-down",trim(str(p%npotd)))
32- call xml_AddAttribute(xf,"npots-up",trim(str(p%npotu)))
33+ call xml_AddAttribute(xf,"npots-down",p%npotd)
34+ call xml_AddAttribute(xf,"npots-up",p%npotu)
35
36 do i=1,p%npotd
37 call xml_NewElement(xf,"vps")
38 call xml_AddAttribute(xf,"principal-n", &
39- trim(str(p%principal_n(p%ldown(i)))))
40- call xml_AddAttribute(xf,"l",trim(str(p%ldown(i))))
41+ p%principal_n(p%ldown(i)))
42+ call xml_AddAttribute(xf,"l",p%ldown(i))
43 call xml_AddAttribute(xf,"cutoff", &
44- trim(str(p%cutoff(p%ldown(i)))))
45+ p%cutoff(p%ldown(i)))
46 call xml_AddAttribute(xf,"occupation", &
47- trim(str(p%occupation(p%ldown(i)))))
48+ p%occupation(p%ldown(i)))
49 call xml_AddAttribute(xf,"spin","-1")
50
51 call xml_NewElement(xf,"radfunc")
52
53=== modified file 'Examples/wxml/simple.f90'
54--- Examples/wxml/simple.f90 2016-01-15 15:49:14 +0000
55+++ Examples/wxml/simple.f90 2016-01-30 12:34:50 +0000
56@@ -2,6 +2,8 @@
57
58 use xmlf90_wxml
59
60+integer, parameter :: dp = selected_real_kind(15,100)
61+
62 type(xmlf_t) :: xf
63
64 integer :: age = 34
65@@ -12,12 +14,14 @@
66
67 call xml_AddXMLDeclaration(xf,"UTF-8")
68 call xml_NewElement(xf,"john")
69-call xml_AddAttribute(xf,"age",str(age))
70+call xml_AddAttribute(xf,"age",age) ! Overloaded int, with trimming
71 call xml_NewElement(xf,"peter")
72+call xml_AddAttribute(xf,"with-blanks"," ..Ha.. ") ! String, no trimming
73 call xml_NewElement(xf,"tim")
74-call xml_AddAttribute(xf,"age","37")
75-call xml_AddAttribute(xf,"weight",str(123.45,"(f7.3)"))
76-call xml_AddAttribute(xf,"cholesterol",str(167.0,format="(f8.0)"))
77+call xml_AddAttribute(xf,"age","37") ! String, no trimming
78+call xml_AddAttribute(xf,"weight",123.45_dp,fmt="(f7.3)") ! Overloaded, trimming
79+call xml_AddAttribute(xf,"cholesterol",167.0,fmt="(f8.0)") ! Overloaded, trimming
80+call xml_AddAttribute(xf,"realdefault",137.01) ! Overloaded, default fmt, trimming
81 call xml_EndElement(xf,"tim")
82 call xml_AddPcdata(xf,"Ping-pong")
83 call xml_AddPcdata(xf,"champion", line_feed=.false.)
84
85=== added file 'wxml/m_wxml_array_str.f90'
86--- wxml/m_wxml_array_str.f90 1970-01-01 00:00:00 +0000
87+++ wxml/m_wxml_array_str.f90 2016-01-30 12:34:50 +0000
88@@ -0,0 +1,77 @@
89+module m_wxml_array_str
90+!
91+! Utilities for character to character array
92+! conversions and tests of equality.
93+!
94+interface operator (.equal.)
95+ module procedure compare_array_str
96+end interface
97+!
98+! Not supported by all compilers...
99+! interface assignment (=)
100+! module procedure assign_array_to_str !!!! , assign_str_to_array
101+! end interface
102+
103+public :: operator(.equal.) !!!! , assignment(=)
104+public :: assign_array_to_str , assign_str_to_array
105+private
106+
107+CONTAINS
108+!-------------------------------------------------------------
109+subroutine assign_array_to_str(str,s)
110+implicit none
111+character(len=1), dimension(:), intent(in) :: s
112+character(len=*), intent(out) :: str
113+
114+integer :: i, lstr
115+
116+lstr = len(str)
117+do i = 1, min(size(s),lstr)
118+ str(i:i) = s(i)
119+enddo
120+do i = size(s)+1, lstr
121+ str(i:i) = " "
122+enddo
123+end subroutine assign_array_to_str
124+
125+!-------------------------------------------------------------
126+! The NAG and Intel compilers cannot distinguish this from the
127+! intrinsic assignment... so we resort to using an explicit
128+! subroutine call.
129+!
130+subroutine assign_str_to_array(s,str)
131+implicit none
132+character(len=1), dimension(:), intent(out) :: s
133+character(len=*), intent(in) :: str
134+
135+integer :: i, lstr
136+
137+lstr = len(str)
138+do i = 1, min(size(s),lstr)
139+ s(i) = str(i:i)
140+enddo
141+
142+end subroutine assign_str_to_array
143+
144+!-------------------------------------------------------------
145+function compare_array_str(s,str) result(equal) ! .equal. generic
146+implicit none
147+character(len=1), dimension(:), intent(in) :: s
148+character(len=*), intent(in) :: str
149+logical :: equal
150+integer :: lens, lenstr, i
151+
152+
153+equal = .false.
154+lens = size(s)
155+lenstr = len(str)
156+if (lens .ne. lenstr) return
157+
158+do i = 1, lens
159+ if (s(i) .ne. str(i:i)) return
160+enddo
161+equal = .true.
162+
163+end function compare_array_str
164+
165+end module m_wxml_array_str
166
167=== modified file 'wxml/m_wxml_buffer.f90'
168--- wxml/m_wxml_buffer.f90 2014-09-04 09:28:10 +0000
169+++ wxml/m_wxml_buffer.f90 2016-01-30 12:34:50 +0000
170@@ -1,5 +1,9 @@
171 module m_wxml_buffer
172
173+use m_wxml_error
174+
175+implicit none
176+
177 !
178 ! At this point we use a fixed-size buffer.
179 ! Note however that buffer overflows will only be
180@@ -9,13 +13,13 @@
181 ! There is code in the parser module m_fsm to avoid buffer overflows
182 ! caused by pcdata values.
183 !
184-! This module is re-used from the parser package.
185+! This module is re-used from the parser package, except the size.
186 ! Most of the routines are superfluous at this point.
187 !
188 ! In a forthcoming implementation it could be made dynamical...
189 !
190-integer, parameter, public :: MAX_BUFF_SIZE = 2000
191-integer, parameter, private :: BUFF_SIZE_WARNING = 1750
192+integer, parameter, public :: MAX_BUFF_SIZE = 10000
193+integer, parameter, private :: BUFF_SIZE_WARNING = 9500
194 !
195 type, public :: buffer_t
196 private
197@@ -23,12 +27,12 @@
198 character(len=MAX_BUFF_SIZE) :: str
199 end type buffer_t
200
201-public :: add_to_buffer
202+public :: add_to_buffer, add_to_buffer_escaping_markup
203 public :: print_buffer, str, char, len
204 public :: operator (.equal.)
205 public :: buffer_nearly_full, reset_buffer
206
207-
208+private
209 !----------------------------------------------------------------
210 interface add_to_buffer
211 module procedure add_str_to_buffer
212@@ -97,9 +101,7 @@
213 n = buffer%size
214
215 if (n> MAX_BUFF_SIZE) then
216- stop "Buffer overflow: long unbroken string of pcdata or attribute value..."
217-! RETURN
218-!
219+ call wxml_error("Buffer overflow: long unbroken string of pcdata or attribute value...")
220 endif
221
222 buffer%str(n:n) = c
223@@ -110,7 +112,7 @@
224 character(len=*), intent(in) :: s
225 type(buffer_t), intent(inout) :: buffer
226
227-integer :: n, len_s, last_pos
228+integer :: i, n, len_s, last_pos
229
230 len_s = len(s)
231 last_pos = buffer%size
232@@ -118,13 +120,40 @@
233 n = buffer%size
234
235 if (n> MAX_BUFF_SIZE) then
236- stop "Buffer overflow: long unbroken string of pcdata or attribute value..."
237-! RETURN
238+ call wxml_error("Buffer overflow: long unbroken string of pcdata or attribute value...")
239 endif
240
241-buffer%str(last_pos+1:n) = s
242+if (len_s.gt.0) buffer%str(last_pos+1:n) = s
243 end subroutine add_str_to_buffer
244
245+subroutine add_to_buffer_escaping_markup(s,buf)
246+character(len=*), intent(in) :: s
247+type(buffer_t), intent(inout) :: buf
248+
249+integer :: len_s, i
250+character(len=1) :: c
251+
252+len_s = len(s)
253+i = 0
254+do
255+ if (i==len_s) exit
256+ i = i + 1
257+ c = s(i:i)
258+ if (c == "<") then
259+ call add_to_buffer("&lt;",buf)
260+ else if (c == "&") then
261+ call add_to_buffer("&amp;",buf)
262+ else if (c == "'") then
263+ call add_to_buffer("&apos;",buf)
264+ else if (c == '"') then
265+ call add_to_buffer("&quot;",buf)
266+ else
267+ call add_to_buffer(c,buf)
268+ endif
269+enddo
270+
271+end subroutine add_to_buffer_escaping_markup
272+
273 !----------------------------------------------------------------
274 subroutine reset_buffer(buffer)
275 type(buffer_t), intent(inout) :: buffer
276
277=== modified file 'wxml/m_wxml_core.f90'
278--- wxml/m_wxml_core.f90 2014-09-04 09:28:10 +0000
279+++ wxml/m_wxml_core.f90 2016-01-30 12:34:50 +0000
280@@ -1,9 +1,14 @@
281 module m_wxml_core
282
283 use m_wxml_buffer
284+use m_wxml_array_str, only: assign_array_to_str
285+use m_wxml_array_str, only: assign_str_to_array
286+use m_wxml_escape, only: check_Name
287 use m_wxml_elstack
288 use m_wxml_dictionary
289
290+implicit none
291+
292 logical, private, save :: pcdata_advance_line_default = .false.
293 logical, private, save :: pcdata_advance_space_default = .false.
294
295@@ -13,19 +18,31 @@
296 private
297
298 type, public :: xmlf_t
299- integer :: lun
300- type(buffer_t) :: buffer
301- type(elstack_t) :: stack
302+ character, pointer :: filename(:)
303+ integer :: lun
304+ type(buffer_t) :: buffer
305+ type(elstack_t) :: stack
306 type(wxml_dictionary_t) :: dict
307- logical :: start_tag_closed
308- logical :: root_element_output
309- logical :: indenting_requested
310+ logical :: start_tag_closed
311+ logical :: root_element_output
312+ logical :: indenting_requested
313+ logical :: inhibit_lf
314 end type xmlf_t
315
316 public :: xml_OpenFile, xml_NewElement, xml_EndElement, xml_Close
317-public :: xml_AddPcdata, xml_AddAttribute, xml_AddXMLDeclaration
318+public :: xml_AddXMLDeclaration
319+public :: xml_AddXMLStylesheet
320+public :: xml_AddXMLPI
321 public :: xml_AddComment, xml_AddCdataSection
322-
323+public :: xml_AddPcdata, xml_AddAttribute
324+interface xml_AddPcdata
325+ module procedure xml_AddPcdata_Ch
326+end interface
327+!
328+interface xml_AddAttribute
329+ module procedure xml_AddAttribute_Ch
330+end interface
331+!
332 public :: xml_AddArray
333 interface xml_AddArray
334 module procedure xml_AddArray_integer, &
335@@ -37,9 +54,28 @@
336 private :: add_eol
337 private :: write_attributes
338
339+!overload error handlers to allow file info
340+interface wxml_warning
341+ module procedure wxml_warning_xf
342+end interface
343+interface wxml_error
344+ module procedure wxml_error_xf
345+end interface
346+interface wxml_fatal
347+ module procedure wxml_fatal_xf
348+end interface
349
350+!
351+! Heuristic (approximate) target for justification of output
352+! Large unbroken pcdatas will go beyond this limit
353+!
354 integer, private, parameter :: COLUMNS = 80
355
356+! TOHW - This is the longest string that may be output without
357+! a newline. The buffer must not be larger than this, but its size
358+! can be tuned for performance.
359+integer, private, parameter :: xml_recl = 4096
360+
361 CONTAINS
362
363 !-------------------------------------------------------------------
364@@ -50,17 +86,30 @@
365
366 integer :: iostat
367
368+allocate(xf%filename(len(filename)))
369+call assign_str_to_array(xf%filename,filename)
370+
371 call get_unit(xf%lun,iostat)
372-if (iostat /= 0) stop "cannot open file"
373+if (iostat /= 0) call wxml_fatal(xf, "cannot open file")
374+!
375+! Use large I/O buffer in case the O.S./Compiler combination
376+! has hard-limits by default (i.e., NAGWare f95's 1024 byte limit)
377+! This is related to the maximum size of the buffer.
378+! TOHW - This is the longest string that may be output without
379+! a newline. The buffer must not be larger than this, but its size
380+! can be tuned for performance.
381+
382 open(unit=xf%lun, file=filename, form="formatted", status="replace", &
383- action="write", position="rewind") ! , recl=65536)
384-
385-call reset_elstack(xf%stack)
386-call reset_dict(xf%dict)
387+ action="write", position="rewind", recl=xml_recl)
388+
389+call init_elstack(xf%stack)
390+
391+call init_dict(xf%dict)
392 call reset_buffer(xf%buffer)
393
394 xf%start_tag_closed = .true.
395 xf%root_element_output = .false.
396+xf%inhibit_lf = .false.
397
398 xf%indenting_requested = .false.
399 if (present(indent)) then
400@@ -82,6 +131,48 @@
401 end subroutine xml_AddXMLDeclaration
402
403 !-------------------------------------------------------------------
404+subroutine xml_AddXMLStylesheet(xf, href, type, title, media, charset, alternate)
405+type(xmlf_t), intent(inout) :: xf
406+character(len=*), intent(in) :: href
407+character(len=*), intent(in) :: type
408+character(len=*), intent(in), optional :: title
409+character(len=*), intent(in), optional :: media
410+character(len=*), intent(in), optional :: charset
411+logical, intent(in), optional :: alternate
412+
413+call add_eol(xf)
414+call add_to_buffer("<?xml-stylesheet href=""" //trim(href)// &
415+ """ type=""" //trim(type)// """", xf%buffer)
416+
417+if (present(title)) call add_to_buffer(" title="""//trim(title)// """", xf%buffer)
418+if (present(media)) call add_to_buffer(" media="""//trim(media)// """", xf%buffer)
419+if (present(charset)) call add_to_buffer(" charset="""//trim(charset)// """", xf%buffer)
420+if (present(alternate)) then
421+ if (alternate) then
422+ call add_to_buffer(" alternate=""yes""", xf%buffer)
423+ else
424+ call add_to_buffer(" alternate=""no""", xf%buffer)
425+ endif
426+endif
427+call add_to_buffer(" ?>", xf%buffer)
428+
429+end subroutine xml_AddXMLStylesheet
430+
431+!-------------------------------------------------------------------
432+subroutine xml_AddXMLPI(xf, name, data)
433+type(xmlf_t), intent(inout) :: xf
434+character(len=*), intent(in) :: name
435+character(len=*), intent(in), optional :: data
436+
437+call add_eol(xf)
438+call add_to_buffer("<?" // trim(name) // " ", xf%buffer)
439+if(present(data)) call add_to_buffer(data, xf%buffer)
440+call add_to_buffer(" ?>", xf%buffer)
441+
442+end subroutine xml_AddXMLPI
443+
444+
445+!-------------------------------------------------------------------
446 subroutine xml_AddComment(xf,comment)
447 type(xmlf_t), intent(inout) :: xf
448 character(len=*), intent(in) :: comment
449@@ -94,14 +185,20 @@
450 end subroutine xml_AddComment
451
452 !-------------------------------------------------------------------
453-subroutine xml_AddCdataSection(xf,cdata)
454+subroutine xml_AddCdataSection(xf,cdata,line_feed)
455 type(xmlf_t), intent(inout) :: xf
456 character(len=*), intent(in) :: cdata
457+logical, intent(in), optional :: line_feed
458
459 call close_start_tag(xf,">")
460+call dump_buffer(xf,line_feed)
461 call add_to_buffer("<![CDATA[", xf%buffer)
462 call add_to_buffer(cdata, xf%buffer)
463 call add_to_buffer("]]>", xf%buffer)
464+call dump_buffer(xf,line_feed)
465+if (present(line_feed)) then
466+ if (line_feed) xf%inhibit_lf = .true.
467+endif
468 end subroutine xml_AddCdataSection
469
470 !-------------------------------------------------------------------
471@@ -110,10 +207,15 @@
472 character(len=*), intent(in) :: name
473
474 if (is_empty(xf%stack)) then
475- if (xf%root_element_output) stop "two root elements"
476+ if (xf%root_element_output) call wxml_error(xf, "two root elements")
477 xf%root_element_output = .true.
478 endif
479
480+if (.not.check_Name(name)) then
481+ call wxml_warning(xf, 'attribute name '//name//' is not valid')
482+endif
483+
484+
485 call close_start_tag(xf,">")
486 call push_elstack(name,xf%stack)
487 call add_eol(xf)
488@@ -123,15 +225,13 @@
489
490 end subroutine xml_NewElement
491 !-------------------------------------------------------------------
492-subroutine xml_AddPcdata(xf,pcdata,space,line_feed)
493+subroutine xml_AddPcdata_Ch(xf,pcdata,space,line_feed)
494 type(xmlf_t), intent(inout) :: xf
495 character(len=*), intent(in) :: pcdata
496 logical, intent(in), optional :: space
497 logical, intent(in), optional :: line_feed
498
499 logical :: advance_line , advance_space
500-integer :: n, i, jmax
501-integer, parameter :: chunk_size = 128
502
503 advance_line = pcdata_advance_line_default
504 if (present(line_feed)) then
505@@ -144,7 +244,7 @@
506 endif
507
508 if (is_empty(xf%stack)) then
509- stop "pcdata outside element content"
510+ call wxml_error(xf, "pcdata outside element content")
511 endif
512
513 call close_start_tag(xf,">")
514@@ -161,43 +261,32 @@
515 endif
516 endif
517 if (advance_space) call add_to_buffer(" ",xf%buffer)
518-if (len(xf%buffer) > 0) call dump_buffer(xf,lf=.false.)
519-!
520-! We bypass the buffer for the bulk of the dump
521-!
522-n = len(pcdata)
523-!print *, "writing pcdata of length: ", n
524-i = 1
525-do
526- jmax = min(i+chunk_size-1,n)
527-! print *, "writing chunk: ", i, jmax
528- write(unit=xf%lun,fmt="(a)",advance="no") pcdata(i:jmax)
529- if (jmax == n) exit
530- i = jmax + 1
531-enddo
532-end subroutine xml_AddPcdata
533+
534+call add_to_buffer_escaping_markup(pcdata, xf%buffer)
535+
536+end subroutine xml_AddPcdata_Ch
537
538 !-------------------------------------------------------------------
539-subroutine xml_AddAttribute(xf,name,value)
540+subroutine xml_AddAttribute_Ch(xf,name,value)
541 type(xmlf_t), intent(inout) :: xf
542 character(len=*), intent(in) :: name
543 character(len=*), intent(in) :: value
544
545 if (is_empty(xf%stack)) then
546- stop "attributes outside element content"
547+ call wxml_error(xf, "attributes outside element content")
548 endif
549
550 if (xf%start_tag_closed) then
551- stop "attributes outside start tag"
552+ call wxml_error(xf, "attributes outside start tag")
553 endif
554+
555 if (has_key(xf%dict,name)) then
556- stop "duplicate att name"
557+ call wxml_error(xf, "duplicate att name")
558 endif
559
560-call add_key_to_dict(trim(name),xf%dict)
561-call add_value_to_dict(trim(value),xf%dict)
562+call add_item_to_dict(xf%dict, name, value)
563
564-end subroutine xml_AddAttribute
565+end subroutine xml_AddAttribute_Ch
566
567 !-----------------------------------------------------------
568 subroutine xml_EndElement(xf,name)
569@@ -207,19 +296,19 @@
570 character(len=100) :: current
571
572 if (is_empty(xf%stack)) then
573- stop "Out of elements to close"
574+ call wxml_fatal(xf, "Out of elements to close")
575 endif
576
577 call get_top_elstack(xf%stack,current)
578 if (current /= name) then
579- print *, "current, name: ", trim(current), " ", trim(name)
580- stop
581+ call wxml_fatal(xf, 'Trying to close '//Trim(name)//' but '//Trim(current)//' is open.')
582 endif
583 if (.not. xf%start_tag_closed) then ! Empty element
584 if (len(xf%dict) > 0) call write_attributes(xf)
585 call add_to_buffer(" />",xf%buffer)
586 xf%start_tag_closed = .true.
587 else
588+ ! This statement will introduce a newline after array data...
589 call add_eol(xf)
590 call add_to_buffer("</" // trim(name) // ">", xf%buffer)
591 endif
592@@ -230,11 +319,21 @@
593 !----------------------------------------------------------------
594
595 subroutine xml_Close(xf)
596-type(xmlf_t), intent(in) :: xf
597+type(xmlf_t), intent(inout) :: xf
598+
599+character(len=200) :: name
600+
601+do
602+ if (is_empty(xf%stack)) exit
603+ call get_top_elstack(xf%stack,name)
604+ call xml_EndElement(xf,trim(name))
605+enddo
606
607 write(unit=xf%lun,fmt="(a)") char(xf%buffer)
608 close(unit=xf%lun)
609
610+deallocate(xf%filename)
611+
612 end subroutine xml_Close
613
614 !==================================================================
615@@ -266,14 +365,24 @@
616 type(xmlf_t), intent(inout) :: xf
617
618 integer :: indent_level
619-character(len=100), parameter :: blanks = ""
620-
621-indent_level = len(xf%stack) - 1
622-write(unit=xf%lun,fmt="(a)") char(xf%buffer)
623-call reset_buffer(xf%buffer)
624-
625+
626+
627+! Flush with a linefeed except if a previous operation has raised
628+! the inhibit_lf flag
629+
630+if (xf%inhibit_lf) then
631+ call dump_buffer(xf,lf=.false.)
632+ xf%inhibit_lf = .false.
633+else
634+ call dump_buffer(xf,lf=.true.)
635+endif
636+
637+! In case we still have a zero-length stack, we must make
638+! sure indent_level is not less than zero.
639+
640+indent_level = max(len(xf%stack) - 1, 0)
641 if (xf%indenting_requested) &
642- call add_to_buffer(blanks(1:indent_level),xf%buffer)
643+ call add_to_buffer(repeat(' ',indent_level),xf%buffer)
644
645 end subroutine add_eol
646 !------------------------------------------------------------
647@@ -311,21 +420,19 @@
648 subroutine write_attributes(xf)
649 type(xmlf_t), intent(inout) :: xf
650
651-integer :: i, status, size
652-character(len=100) :: key, value
653+integer :: i, status, size, key_len, value_len
654+character(len=200) :: key, value
655
656 do i = 1, len(xf%dict)
657- call get_key(xf%dict,i,key,status)
658- call get_value(xf%dict,key,value,status)
659- key = adjustl(key)
660- value = adjustl(value)
661- size = len_trim(key) + len_trim(value) + 4
662+ call get_key(xf%dict,i,key,key_len,status)
663+ call get_value(xf%dict,i,value,value_len,status)
664+ size = key_len + value_len + 4
665 if ((len(xf%buffer) + size) > COLUMNS) call add_eol(xf)
666 call add_to_buffer(" ", xf%buffer)
667- call add_to_buffer(trim(key), xf%buffer)
668+ call add_to_buffer(key(:key_len), xf%buffer)
669 call add_to_buffer("=", xf%buffer)
670 call add_to_buffer("""",xf%buffer)
671- call add_to_buffer(trim(value), xf%buffer)
672+ call add_to_buffer_escaping_markup(value(:value_len), xf%buffer)
673 call add_to_buffer("""", xf%buffer)
674 enddo
675
676@@ -343,6 +450,7 @@
677 write(xf%lun,format) a
678 else
679 write(xf%lun,"(6(i12))") a
680+ xf%inhibit_lf = .true.
681 endif
682 end subroutine xml_AddArray_integer
683
684@@ -359,6 +467,7 @@
685 else
686 write(xf%lun,"(4(es20.12))") a
687 endif
688+ xf%inhibit_lf = .true.
689 end subroutine xml_AddArray_real_dp
690
691 !------------------------------------------------------------------
692@@ -374,7 +483,57 @@
693 else
694 write(xf%lun,"(4(es20.12))") a
695 endif
696+ xf%inhibit_lf = .true.
697 end subroutine xml_AddArray_real_sp
698
699+!---------------------------------------------------------
700+! Error handling/trapping routines:
701+
702+ subroutine wxml_warning_xf(xf, msg)
703+ ! Emit warning, but carry on.
704+ type(xmlf_t), intent(in) :: xf
705+ character(len=*), intent(in) :: msg
706+
707+ write(6,'(a)') 'WARNING(wxml) in writing to file ', xmlf_name(xf)
708+ write(6,'(a)') msg
709+
710+ end subroutine wxml_warning_xf
711+
712+ subroutine wxml_error_xf(xf, msg)
713+ ! Emit error message, clean up file and stop.
714+ type(xmlf_t), intent(inout) :: xf
715+ character(len=*), intent(in) :: msg
716+
717+ write(6,'(a)') 'ERROR(wxml) in writing to file ', xmlf_name(xf)
718+ write(6,'(a)') msg
719+
720+ call xml_Close(xf)
721+ stop
722+
723+ end subroutine wxml_error_xf
724+
725+ subroutine wxml_fatal_xf(xf, msg)
726+ !Emit error message and abort with coredump. Does not try to
727+ !close file, so should be used from anything xml_Close might
728+ !itself call (to avoid infinite recursion!)
729+
730+ type(xmlf_t), intent(in) :: xf
731+ character(len=*), intent(in) :: msg
732+
733+ write(6,'(a)') 'ERROR(wxml) in writing to file ', xmlf_name(xf)
734+ write(6,'(a)') msg
735+
736+ !call pxfabort
737+ stop
738+
739+ end subroutine wxml_fatal_xf
740+
741+ function xmlf_name(xf) result(fn)
742+ Type (xmlf_t), intent(in) :: xf
743+ character(len=size(xf%filename)) :: fn
744+ call assign_array_to_str(fn,xf%filename)
745+ end function xmlf_name
746+
747+
748 end module m_wxml_core
749
750
751=== modified file 'wxml/m_wxml_dictionary.f90'
752--- wxml/m_wxml_dictionary.f90 2014-09-04 09:28:10 +0000
753+++ wxml/m_wxml_dictionary.f90 2016-01-30 12:34:50 +0000
754@@ -1,24 +1,32 @@
755 module m_wxml_dictionary
756
757+ use m_wxml_escape, only : check_Name
758+ use m_wxml_error, only : wxml_fatal
759+ use m_wxml_array_str
760+
761+ implicit none
762+
763 private
764 !
765-! A very rough implementation for now
766-! It uses fixed-length buffers for key/value pairs,
767-! and the maximum number of dictionary items is hardwired.
768-
769 integer, parameter, private :: MAX_ITEMS = 30
770+
771+type, private :: dict_item
772+ character(len=1), pointer, dimension(:) :: key
773+ character(len=1), pointer, dimension(:) :: value
774+end type dict_item
775+
776 type, public :: wxml_dictionary_t
777 private
778 integer :: number_of_items ! = 0
779- character(len=100), dimension(MAX_ITEMS) :: key
780- character(len=100), dimension(MAX_ITEMS) :: value
781+ type(dict_item), dimension(MAX_ITEMS) :: items
782 end type wxml_dictionary_t
783
784 !
785 ! Building procedures
786 !
787-public :: add_key_to_dict, add_value_to_dict, reset_dict
788-
789+public :: init_dict
790+public :: reset_dict
791+public :: add_item_to_dict
792 !
793 ! Query and extraction procedures
794 !
795@@ -27,13 +35,13 @@
796 module procedure number_of_entries
797 end interface
798 public :: number_of_entries
799-public :: get_key
800+public :: get_key
801 public :: get_value
802 public :: has_key
803 public :: print_dict
804 !
805 interface get_value
806- module procedure wxml_get_value
807+ module procedure wxml_get_value, wxml_get_value_i
808 end interface
809
810 CONTAINS
811@@ -53,14 +61,13 @@
812 character(len=*), intent(in) :: key
813 logical :: found
814
815-integer :: n, i
816+integer :: i
817 found = .false.
818-n = dict%number_of_items
819-do i = 1, n
820- if (dict%key(i) == key) then
821- found = .true.
822- exit
823- endif
824+do i = 1, dict%number_of_items
825+ if (dict%items(i)%key .equal. key) then
826+ found = .true.
827+ exit
828+ endif
829 enddo
830 end function has_key
831
832@@ -71,79 +78,141 @@
833 character(len=*), intent(out) :: value
834 integer, intent(out) :: status
835 !
836-integer :: n, i
837+integer :: i
838
839 status = -1
840-n = dict%number_of_items
841-do i = 1, n
842- if (dict%key(i) == key) then
843- value = dict%value(i)
844- status = 0
845- RETURN
846- endif
847+do i = 1, dict%number_of_items
848+ if (dict%items(i)%key .equal. key) then
849+ call assign_array_to_str(value,dict%items(i)%value)
850+ status = 0
851+ exit
852+ endif
853 enddo
854
855 end subroutine wxml_get_value
856
857+function get_value_len(dict, key) result(value_len)
858+ type(wxml_dictionary_t), intent(in) :: dict
859+ character(len=*), intent(in) :: key
860+ integer :: value_len
861+
862+ integer :: i
863+
864+ value_len = 0
865+ do i = 1, dict%number_of_items
866+ if (dict%items(i)%key .equal. key) then
867+ value_len = size(dict%items(i)%value)
868+ exit
869+ endif
870+ enddo
871+
872+end function get_value_len
873+
874+
875 !------------------------------------------------------
876-subroutine get_key(dict,i,key,status)
877+subroutine get_key(dict,i,key,key_len,status)
878 !
879 ! Get the i'th key
880 !
881 type(wxml_dictionary_t), intent(in) :: dict
882 integer, intent(in) :: i
883 character(len=*), intent(out) :: key
884+integer, intent(out) :: key_len
885 integer, intent(out) :: status
886
887-if (i <= dict%number_of_items) then
888- key = dict%key(i)
889+if (i>0 .and. i<=dict%number_of_items) then
890+ call assign_array_to_str(key,dict%items(i)%key)
891+ key_len = size(dict%items(i)%key)
892 status = 0
893 else
894- key = ""
895+ key = ' '
896+ key_len = 0
897 status = -1
898 endif
899
900 end subroutine get_key
901-
902 !------------------------------------------------------
903-subroutine add_key_to_dict(key,dict)
904-character(len=*), intent(in) :: key
905-type(wxml_dictionary_t), intent(inout) :: dict
906-
907-integer :: n
908-
909-n = dict%number_of_items
910-if (n == MAX_ITEMS) then
911- write(unit=0,fmt=*) "Dictionary capacity exceeded !"
912- RETURN
913+subroutine wxml_get_value_i(dict,i,value,value_len,status)
914+!
915+! Get the i'th value
916+!
917+type(wxml_dictionary_t), intent(in) :: dict
918+integer, intent(in) :: i
919+character(len=*), intent(out) :: value
920+integer, intent(out) :: value_len
921+integer, intent(out) :: status
922+
923+if (i>0 .and. i<=dict%number_of_items) then
924+ call assign_array_to_str(value,dict%items(i)%value)
925+ value_len = size(dict%items(i)%value)
926+ status = 0
927+else
928+ value = ' '
929+ value_len = 0
930+ status = -1
931 endif
932
933-n = n + 1
934-dict%key(n) = key
935-dict%number_of_items = n
936-
937-end subroutine add_key_to_dict
938+end subroutine wxml_get_value_i
939+
940+subroutine add_item_to_dict(dict, key, value)
941+
942+ type(wxml_dictionary_t), intent(inout) :: dict
943+ character(len=*), intent(in) :: key
944+ character(len=*), intent(in) :: value
945+
946+ character(len=len(key)) :: check_key
947+ integer :: n, lenstr
948+
949+ n = dict%number_of_items
950+ if (n == MAX_ITEMS) then
951+ write(unit=0,fmt=*) "Dictionary capacity exceeded !"
952+ RETURN
953+ endif
954+
955+! keys may not have initial (or trailing; thus trim below) blanks:
956+!TOHW remove this check? shouldn't be passing blank-prefixed strings anyway.
957+ check_key=adjustl(key)
958+ if (.not.check_Name(trim(check_key))) then
959+ call wxml_fatal('attribute name is invalid')
960+ endif
961+
962+ n = n + 1
963+ lenstr=len_trim(check_key)
964+ allocate(dict%items(n)%key(lenstr))
965+ call assign_str_to_array(dict%items(n)%key,check_key)
966+ allocate(dict%items(n)%value(len(value)))
967+ call assign_str_to_array(dict%items(n)%value,value)
968+
969+ dict%number_of_items = n
970+
971+end subroutine add_item_to_dict
972
973 !------------------------------------------------------
974-! Assumes we build the dictionary in an orderly fashion,
975-! so one adds first the key and then immediately afterwards the value.
976-!
977-subroutine add_value_to_dict(value,dict)
978-character(len=*), intent(in) :: value
979-type(wxml_dictionary_t), intent(inout) :: dict
980-
981-integer :: n
982-
983-n = dict%number_of_items
984-dict%value(n) = value
985-
986-end subroutine add_value_to_dict
987-
988+subroutine init_dict(dict)
989+ type(wxml_dictionary_t), intent(out) :: dict
990+
991+ integer :: i
992+
993+ do i = 1, MAX_ITEMS
994+ nullify(dict%items(i)%key)
995+ nullify(dict%items(i)%key)
996+ enddo
997+
998+ dict % number_of_items = 0
999+
1000+end subroutine init_dict
1001+
1002 !------------------------------------------------------
1003 subroutine reset_dict(dict)
1004-type(wxml_dictionary_t), intent(inout) :: dict
1005+ type(wxml_dictionary_t), intent(inout) :: dict
1006+
1007+ integer :: i
1008+ do i = 1, dict%number_of_items
1009+ deallocate(dict%items(i)%key)
1010+ deallocate(dict%items(i)%value)
1011+ enddo
1012
1013-dict%number_of_items = 0
1014+ dict%number_of_items = 0
1015
1016 end subroutine reset_dict
1017
1018@@ -154,7 +223,7 @@
1019 integer :: i
1020
1021 do i = 1, dict%number_of_items
1022- print *, trim(dict%key(i)), " = ", trim(dict%value(i))
1023+ print *, dict%items(i)%key, " = ", dict%items(i)%value
1024 enddo
1025
1026 end subroutine print_dict
1027
1028=== modified file 'wxml/m_wxml_elstack.f90'
1029--- wxml/m_wxml_elstack.f90 2014-09-04 09:28:10 +0000
1030+++ wxml/m_wxml_elstack.f90 2016-01-30 12:34:50 +0000
1031@@ -1,19 +1,30 @@
1032 module m_wxml_elstack
1033
1034+use m_wxml_error
1035+
1036+implicit none
1037+
1038 private
1039
1040 !
1041 ! Simple stack to keep track of which elements have appeared so far
1042 !
1043-integer, parameter, private :: STACK_SIZE = 20
1044+! Initial stack size:
1045+integer, parameter, private :: STACK_SIZE_INIT = 10
1046+! Multiplier when stack is exceeded:
1047+real, parameter, private :: STACK_SIZE_MULT = 1.5
1048+
1049+type, private :: elstack_item
1050+ character(len=100) :: data
1051+end type
1052
1053 type, public :: elstack_t
1054 private
1055- integer :: n_items
1056- character(len=100), dimension(STACK_SIZE) :: data
1057+ integer :: n_items
1058+ type(elstack_item), pointer, dimension(:) :: stack
1059 end type elstack_t
1060
1061-public :: push_elstack, pop_elstack, reset_elstack, print_elstack
1062+public :: push_elstack, pop_elstack, init_elstack, reset_elstack, print_elstack
1063 public :: get_top_elstack, is_empty, get_elstack_signature
1064 public :: len
1065
1066@@ -30,14 +41,39 @@
1067 CONTAINS
1068
1069 !-----------------------------------------------------------------
1070+subroutine init_elstack(elstack)
1071+ type(elstack_t), intent(inout) :: elstack
1072+
1073+ allocate(elstack%stack(STACK_SIZE_INIT))
1074+ elstack%n_items = 0
1075+
1076+end subroutine init_elstack
1077+
1078+!-----------------------------------------------------------------
1079 subroutine reset_elstack(elstack)
1080-type(elstack_t), intent(inout) :: elstack
1081+ type(elstack_t), intent(inout) :: elstack
1082
1083-elstack%n_items = 0
1084+ deallocate(elstack%stack)
1085+ call init_elstack(elstack)
1086
1087 end subroutine reset_elstack
1088
1089 !-----------------------------------------------------------------
1090+subroutine resize_elstack(elstack)
1091+ type(elstack_t), intent(inout) :: elstack
1092+ type(elstack_item), pointer, dimension(:) :: temp
1093+ integer :: s
1094+
1095+ s = size(elstack%stack)
1096+
1097+ temp=>elstack%stack
1098+ allocate(elstack%stack(nint(s*STACK_SIZE_MULT)))
1099+ elstack%stack(:s) = temp
1100+ deallocate(temp)
1101+
1102+end subroutine resize_elstack
1103+
1104+!-----------------------------------------------------------------
1105 function is_empty_elstack(elstack) result(answer)
1106 type(elstack_t), intent(in) :: elstack
1107 logical :: answer
1108@@ -61,11 +97,11 @@
1109 integer :: n
1110
1111 n = elstack%n_items
1112-if (n == STACK_SIZE) then
1113- stop "*Element stack full"
1114+if (n == size(elstack%stack)) then
1115+ call resize_elstack(elstack)
1116 endif
1117 n = n + 1
1118-elstack%data(n) = item
1119+elstack%stack(n)%data = item
1120 elstack%n_items = n
1121
1122 end subroutine push_elstack
1123@@ -75,16 +111,13 @@
1124 type(elstack_t), intent(inout) :: elstack
1125 character(len=*), intent(out) :: item
1126
1127-!
1128-! We assume the elstack is not empty... (the user has called is_empty first)
1129-!
1130 integer :: n
1131
1132 n = elstack%n_items
1133 if (n == 0) then
1134- stop "*********Element stack empty"
1135+ call wxml_error("Element stack empty")
1136 endif
1137-item = elstack%data(n)
1138+item = elstack%stack(n)%data
1139 elstack%n_items = n - 1
1140
1141 end subroutine pop_elstack
1142@@ -97,16 +130,13 @@
1143 type(elstack_t), intent(in) :: elstack
1144 character(len=*), intent(out) :: item
1145
1146-!
1147-! We assume the elstack is not empty... (the user has called is_empty first)
1148-!
1149 integer :: n
1150
1151 n = elstack%n_items
1152 if (n == 0) then
1153- stop "*********Element stack empty"
1154+ call wxml_error("Element stack empty")
1155 endif
1156-item = elstack%data(n)
1157+item = elstack%stack(n)%data
1158
1159 end subroutine get_top_elstack
1160
1161@@ -117,7 +147,7 @@
1162 integer :: i
1163
1164 do i = elstack%n_items, 1, -1
1165- write(unit=unit,fmt=*) trim(elstack%data(i))
1166+ write(unit=unit,fmt=*) trim(elstack%stack(i)%data)
1167 enddo
1168
1169 end subroutine print_elstack
1170@@ -128,13 +158,13 @@
1171 character(len=*), intent(out) :: string
1172 integer :: i, length, j
1173
1174-string = ""
1175+string = ' '
1176 j = 0
1177 do i = 1, elstack%n_items
1178- length = len_trim(elstack%data(i))
1179+ length = len_trim(elstack%stack(i)%data)
1180 string(j+1:j+1) = "/"
1181 j = j+1
1182- string(j+1:j+length) = trim(elstack%data(i))
1183+ string(j+1:j+length) = trim(elstack%stack(i)%data)
1184 j = j + length
1185 enddo
1186
1187
1188=== added file 'wxml/m_wxml_overloads.f90'
1189--- wxml/m_wxml_overloads.f90 1970-01-01 00:00:00 +0000
1190+++ wxml/m_wxml_overloads.f90 2016-01-30 12:34:50 +0000
1191@@ -0,0 +1,143 @@
1192+module m_wxml_overloads
1193+
1194+ use m_wxml_text, only: str
1195+ use m_wxml_core, only: xmlf_t
1196+ use m_wxml_core, only: xml_AddPcData_Ch => xml_AddPcData
1197+ use m_wxml_core, only: xml_AddAttribute_Ch => xml_AddAttribute
1198+
1199+ implicit none
1200+
1201+ integer, parameter :: sp = selected_real_kind(6,30)
1202+ integer, parameter :: dp = selected_real_kind(14,100)
1203+
1204+ private
1205+
1206+ public :: xml_AddPcdata
1207+ public :: xml_AddAttribute
1208+
1209+ interface xml_AddPcData
1210+ module procedure xml_AddPcdata_SP
1211+ module procedure xml_AddPcdata_DP
1212+ module procedure xml_AddPcdata_Int
1213+ module procedure xml_AddPcdata_Log
1214+ end interface
1215+
1216+ interface xml_AddAttribute
1217+ module procedure xml_AddAttribute_SP
1218+ module procedure xml_AddAttribute_DP
1219+ module procedure xml_AddAttribute_Int
1220+ module procedure xml_AddAttribute_Log
1221+ end interface
1222+
1223+CONTAINS
1224+
1225+ !-------------------------------------------------------------------
1226+
1227+ subroutine xml_AddPcdata_SP(xf,pcdata,fmt, space,line_feed)
1228+ type(xmlf_t), intent(inout) :: xf
1229+ real(kind=sp), intent(in) :: pcdata
1230+ logical, intent(in), optional :: space
1231+ logical, intent(in), optional :: line_feed
1232+ character(len=*), intent(in), optional :: fmt
1233+
1234+ call xml_AddPcdata_Ch(xf,trim(str(pcdata,fmt)),space,line_feed)
1235+
1236+ end subroutine xml_AddPcdata_SP
1237+
1238+
1239+ subroutine xml_AddPcdata_DP(xf,pcdata,fmt,space,line_feed)
1240+ type(xmlf_t), intent(inout) :: xf
1241+ real(kind=dp), intent(in) :: pcdata
1242+ character(len=*), optional :: fmt
1243+ logical, intent(in), optional :: space
1244+ logical, intent(in), optional :: line_feed
1245+
1246+ call xml_AddPcdata_Ch(xf,trim(str(pcdata,fmt)),space,line_feed)
1247+
1248+ end subroutine xml_AddPcdata_DP
1249+
1250+
1251+ subroutine xml_AddPcdata_log(xf,pcdata,fmt,space,line_feed)
1252+ type(xmlf_t), intent(inout) :: xf
1253+ logical, intent(in) :: pcdata
1254+ character(len=*), intent(in), optional :: fmt
1255+ logical, intent(in), optional :: space
1256+ logical, intent(in), optional :: line_feed
1257+
1258+ if (present(fmt)) then
1259+ call xml_AddPcdata_Ch(xf,trim(str(pcdata,fmt)),space,line_feed)
1260+ else
1261+ call xml_AddPcdata_Ch(xf,trim(str(pcdata)),space,line_feed)
1262+ endif
1263+
1264+ end subroutine xml_AddPcdata_log
1265+
1266+
1267+ subroutine xml_AddPcdata_int(xf,pcdata,fmt,space,line_feed)
1268+ type(xmlf_t), intent(inout) :: xf
1269+ integer, intent(in) :: pcdata
1270+ character(len=*), intent(in), optional :: fmt
1271+ logical, intent(in), optional :: space
1272+ logical, intent(in), optional :: line_feed
1273+
1274+ if (present(fmt)) then
1275+ call xml_AddPcdata_Ch(xf,trim(str(pcdata,fmt)),space,line_feed)
1276+ else
1277+ call xml_AddPcdata_Ch(xf,trim(str(pcdata)),space,line_feed)
1278+ endif
1279+
1280+ end subroutine xml_AddPcdata_int
1281+
1282+
1283+ !-------------------------------------------------------------------
1284+
1285+ subroutine xml_AddAttribute_SP(xf,name,value,fmt)
1286+ type(xmlf_t), intent(inout) :: xf
1287+ character(len=*), intent(in) :: name
1288+ real(kind=sp), intent(in) :: value
1289+ character(len=*), intent(in), optional :: fmt
1290+
1291+ call xml_AddAttribute_Ch(xf,name,trim(str(value,fmt)))
1292+
1293+ end subroutine xml_AddAttribute_SP
1294+
1295+ subroutine xml_AddAttribute_DP(xf,name,value,fmt)
1296+ type(xmlf_t), intent(inout) :: xf
1297+ character(len=*), intent(in) :: name
1298+ real(kind=dp), intent(in) :: value
1299+ character(len=*), intent(in), optional :: fmt
1300+
1301+ call xml_AddAttribute_Ch(xf,name,trim(str(value,fmt)))
1302+
1303+ end subroutine xml_AddAttribute_DP
1304+
1305+ subroutine xml_AddAttribute_log(xf,name,value,fmt)
1306+ type(xmlf_t), intent(inout) :: xf
1307+ character(len=*), intent(in) :: name
1308+ logical, intent(in) :: value
1309+ character(len=*), intent(in), optional :: fmt
1310+
1311+ if (present(fmt)) then
1312+ call xml_AddAttribute_Ch(xf,name,trim(str(value,fmt)))
1313+ else
1314+ call xml_AddAttribute_Ch(xf,name,trim(str(value)))
1315+ endif
1316+
1317+ end subroutine xml_AddAttribute_log
1318+
1319+ subroutine xml_AddAttribute_int(xf,name,value,fmt)
1320+ type(xmlf_t), intent(inout) :: xf
1321+ character(len=*), intent(in) :: name
1322+ integer, intent(in) :: value
1323+ character(len=*), intent(in), optional :: fmt
1324+
1325+ if (present(fmt)) then
1326+ call xml_AddAttribute_Ch(xf,name,trim(str(value,fmt)))
1327+ else
1328+ call xml_AddAttribute_Ch(xf,name,trim(str(value)))
1329+ endif
1330+
1331+ end subroutine xml_AddAttribute_int
1332+
1333+end module m_wxml_overloads
1334+
1335
1336=== renamed file 'wxml/m_wxml_text.f90' => 'wxml/m_wxml_text.F90'
1337--- wxml/m_wxml_text.f90 2014-09-04 14:11:50 +0000
1338+++ wxml/m_wxml_text.F90 2016-01-30 12:34:50 +0000
1339@@ -1,44 +1,68 @@
1340 module m_wxml_text
1341+
1342+implicit none
1343 !
1344 integer, private, parameter :: sp = selected_real_kind(6,30)
1345 integer, private, parameter :: dp = selected_real_kind(14,100)
1346 !
1347 private
1348-
1349 public :: str
1350
1351 interface str
1352- module procedure str_integer, str_real_dp, str_real_sp, &
1353- str_logical
1354+ module procedure str_integer_fmt, str_integer, &
1355+ str_logical_fmt, str_logical, &
1356+ str_real_dp, str_real_sp
1357 end interface
1358-private :: str_integer, str_real_dp, str_real_sp, str_logical
1359
1360 CONTAINS
1361
1362- function str_integer(int,format) result(s)
1363- integer, intent(in) :: int
1364- character(len=*), intent(in), optional :: format
1365+ function str_integer_fmt(i,format) result(s)
1366+ integer, intent(in) :: i
1367+ character(len=*), intent(in) :: format
1368 character(len=100) :: s
1369
1370- if (present(format)) then
1371- write(s,format) int
1372- else
1373- write(s,"(i25)") int
1374- endif
1375+ write(s,format) i
1376 s = adjustl(s)
1377+ end function str_integer_fmt
1378+
1379+ function str_integer(i) result(s)
1380+ ! This will work correctly (return an appropriately-sized
1381+ ! string) for integers i s.t. -99999999<=i<=999999999
1382+ integer, intent(in) :: i
1383+#ifndef WXML_INIT_FIX
1384+ character(len=int(merge(log10(real(max(abs(i),1)))+1, &
1385+ log10(real(max(abs(i),1)))+2, &
1386+ sign(1,i)>0))) :: s
1387+#else
1388+! Some compilers have trouble with the above
1389+ character(len=int(log10(real(max(abs(i),1)))+2)) :: s
1390+#endif
1391+ character(len=4) :: form
1392+
1393+ write(form,'(a,i1,a)') '(i',len(s),')'
1394+ write(s, form) i
1395+
1396 end function str_integer
1397
1398- function str_logical(log,format) result(s)
1399- logical, intent(in) :: log
1400- character(len=*), intent(in), optional :: format
1401+ function str_logical_fmt(l,format) result(s)
1402+ logical, intent(in) :: l
1403+ character(len=*), intent(in) :: format
1404 character(len=100) :: s
1405
1406- if (present(format)) then
1407- write(s,format) log
1408- else
1409- write(s,"(l1)") log
1410- endif
1411+ write(s,format) l
1412 s = adjustl(s)
1413+
1414+ end function str_logical_fmt
1415+
1416+ function str_logical(l) result(s)
1417+ logical, intent(in) :: l
1418+ character(len=merge(4,5,l)) :: s
1419+
1420+ if (l) then
1421+ s='true'
1422+ else
1423+ s='false'
1424+ endif
1425 end function str_logical
1426
1427 function str_real_dp(x,format) result(s)
1428@@ -47,10 +71,10 @@
1429 character(len=100) :: s
1430
1431 if (present(format)) then
1432- write(s,format) x
1433+ write(s,format) x
1434 else
1435 if (abs(nint(x)-x) .lt. epsilon(x)) then
1436- write(s,"(f20.0)") x
1437+ write(s,"(i0)") nint(x)
1438 else
1439 write(s,"(g22.12)") x
1440 endif
1441@@ -67,7 +91,7 @@
1442 write(s,format) x
1443 else
1444 if (abs(nint(x)-x) .lt. epsilon(x)) then
1445- write(s,"(f20.0)") x
1446+ write(s,"(i0)") nint(x)
1447 else
1448 write(s,"(g22.12)") x
1449 endif
1450
1451=== modified file 'wxml/makefile'
1452--- wxml/makefile 2016-01-15 15:49:14 +0000
1453+++ wxml/makefile 2016-01-30 12:34:50 +0000
1454@@ -1,6 +1,8 @@
1455 #
1456-OBJFILES= m_wxml_buffer.o m_wxml_dictionary.o m_wxml_elstack.o \
1457- m_wxml_text.o m_wxml_core.o xmlf90_wxml.o
1458+OBJFILES= m_wxml_buffer.o m_wxml_array_str.o m_wxml_dictionary.o\
1459+ m_wxml_elstack.o \
1460+ m_wxml_text.o m_wxml_escape.o m_wxml_core.o \
1461+ m_wxml_overloads.o xmlf90_wxml.o m_wxml_error.o
1462 MODFILES=$(OBJFILES:.o=)
1463
1464 #------------------------------
1465@@ -10,4 +12,12 @@
1466
1467 clean:
1468 rm -f *.o *.$(MOD_EXT)
1469+# DO NOT DELETE THIS LINE - used by make depend
1470+xmlf90_wxml.o: m_wxml_core.o m_wxml_overloads.o m_wxml_text.o
1471+m_wxml_buffer.o: m_wxml_error.o m_wxml_escape.o
1472+m_wxml_core.o: m_wxml_buffer.o m_wxml_dictionary.o m_wxml_elstack.o
1473+m_wxml_core.o: m_wxml_escape.o m_wxml_array_str.o
1474+m_wxml_dictionary.o: m_wxml_array_str.o m_wxml_escape.o
1475+m_wxml_elstack.o: m_wxml_error.o
1476+m_wxml_overloads.o: m_wxml_core.o m_wxml_text.o
1477
1478
1479=== modified file 'wxml/xmlf90_wxml.f90'
1480--- wxml/xmlf90_wxml.f90 2016-01-15 15:49:14 +0000
1481+++ wxml/xmlf90_wxml.f90 2016-01-30 12:34:50 +0000
1482@@ -1,10 +1,8 @@
1483 module xmlf90_wxml
1484
1485-!use m_wxml_buffer
1486-!use m_wxml_dictionary
1487-!use m_wxml_elstack
1488 use m_wxml_text
1489 use m_wxml_core
1490+use m_wxml_overloads
1491
1492 public
1493

Subscribers

People subscribed via source and target branches

to all changes: