1module m_wxml_core 2 3#ifndef DUMMYLIB 4 use fox_m_fsys_abort_flush, only: pxfabort 5 use fox_m_fsys_array_str, only: vs_str, str_vs, vs_str_alloc 6 use fox_m_fsys_string, only: toLower 7 use fox_m_utils_uri, only: URI, parseURI, destroyURI 8 use m_common_attrs, only: dictionary_t, getLength, get_key, get_value, & 9 hasKey, add_item_to_dict, init_dict, reset_dict, destroy_dict, & 10 getWhitespaceHandling, sortAttrs 11 use m_common_buffer, only: buffer_t, len, add_to_buffer, reset_buffer, & 12 dump_buffer 13 use m_common_charset, only: XML1_0, XML1_1, checkChars 14 use m_common_element, only: parse_dtd_element, parse_dtd_attlist 15 use m_common_elstack, only: elstack_t, len, get_top_elstack, pop_elstack, & 16 is_empty, init_elstack, push_elstack, destroy_elstack 17 use m_common_entities, only: existing_entity, is_unparsed_entity 18 use m_common_error, only: FoX_warning_base, FoX_error_base, FoX_fatal_base, & 19 error_stack, in_error, FoX_get_fatal_errors, FoX_get_fatal_warnings 20 use m_common_io, only: get_unit 21 use m_common_namecheck, only: checkEncName, checkName, checkQName, & 22 checkCharacterEntityReference, checkPublicId, prefixOfQName, & 23 localpartofQName, checkPEDef, checkPseudoAttValue, checkAttValue, checkNCName, & 24 likeCharacterEntityReference, checkCharacterEntityReference 25 use m_common_namespaces, only: namespaceDictionary, getnamespaceURI, & 26 initnamespaceDictionary, addDefaultNS, destroyNamespaceDictionary, & 27 addPrefixedNS, isPrefixInForce, checkNamespacesWriting, checkEndNamespaces 28 use m_common_notations, only: add_notation, notation_exists 29 use m_common_struct, only: xml_doc_state, init_xml_doc_state, destroy_xml_doc_state, & 30 register_internal_PE, register_external_PE, register_internal_GE, register_external_GE 31 use m_wxml_escape, only: escape_string 32#ifdef PGF90 33 use m_common_element, only : element_t 34#endif 35#endif 36 37 implicit none 38 private 39 40#ifndef DUMMYLIB 41 integer, parameter :: indent_inc = 2 42 ! TOHW should we let this be set? 43 44 !Output State Machines 45 ! status wrt root element: 46 integer, parameter :: WXML_STATE_1_JUST_OPENED = 0 47 !File is just opened, nothing written to it yet. 48 integer, parameter :: WXML_STATE_1_BEFORE_ROOT = 1 49 !File has been opened, something has been written, but no root element yet. 50 integer, parameter :: WXML_STATE_1_DURING_ROOT = 2 51 !The root element has been opened but not closed 52 integer, parameter :: WXML_STATE_1_AFTER_ROOT = 3 53 !The root element has been opened but not closed 54 55 ! status wrt tags: 56 integer, parameter :: WXML_STATE_2_OUTSIDE_TAG = 0 57 !We are not within a tag. 58 integer, parameter :: WXML_STATE_2_INSIDE_PI = 1 59 !We are inside a Processing Instruction tag 60 integer, parameter :: WXML_STATE_2_INSIDE_ELEMENT = 2 61 !We are inside an element tag. 62 integer, parameter :: WXML_STATE_2_IN_CHARDATA = 3 63 !We are inside deliberately-constructed text. (this is only necessary for preserve_whitespace) 64 65 ! status wrt DTD 66 integer, parameter :: WXML_STATE_3_BEFORE_DTD = 0 67 ! No DTD has been encountered yet. 68 integer, parameter :: WXML_STATE_3_DURING_DTD = 1 69 ! Halfway throught outputting a DTD 70 integer, parameter :: WXML_STATE_3_INSIDE_INTSUBSET = 2 71 !We are inside the internal subset definition 72 integer, parameter :: WXML_STATE_3_AFTER_DTD = 3 73 ! Finished outputting a DTD 74#endif 75 76 77 type xmlf_t 78 private 79#ifdef DUMMYLIB 80 integer :: i = 0 81#else 82 type(xml_doc_state) :: xds 83 integer :: lun = -1 84 type(buffer_t) :: buffer 85 type(elstack_t) :: stack 86 type(dictionary_t) :: dict 87 integer :: state_1 = -1 88 integer :: state_2 = -1 89 integer :: state_3 = -1 90 ! Holder for extra information for other writers. See 91 ! table with getter and setter below: 92 integer :: extended_data = 0 93 logical :: minimize_overrun = .true. 94 logical :: pretty_print = .false. 95 logical :: canonical = .false. 96 integer :: indent = 0 97 character, pointer :: name(:) 98 logical :: namespace = .true. 99 type(namespaceDictionary) :: nsDict 100#endif 101 end type xmlf_t 102 103 public :: xmlf_t 104 105 public :: xml_OpenFile 106 public :: xml_NewElement 107 public :: xml_EndElement 108 public :: xml_Close 109 public :: xml_AddXMLDeclaration 110 public :: xml_AddXMLStylesheet 111 public :: xml_AddXMLPI 112 public :: xml_AddComment 113 public :: xml_AddCharacters 114 public :: xml_AddNewline 115 public :: xml_AddEntityReference 116 public :: xml_AddAttribute 117 public :: xml_AddPseudoAttribute 118 public :: xml_DeclareNamespace 119 public :: xml_UnDeclareNamespace 120 public :: xml_AddDOCTYPE 121 public :: xml_AddParameterEntity 122 public :: xml_AddInternalEntity 123 public :: xml_AddExternalEntity 124 public :: xml_AddNotation 125 public :: xml_AddElementToDTD 126 public :: xml_AddAttlistToDTD 127 public :: xml_AddPEreferenceToDTD 128 129 public :: xmlf_Name 130 public :: xmlf_OpenTag 131 132 public :: xmlf_SetPretty_print 133 public :: xmlf_GetPretty_print 134 public :: xmlf_SetExtendedData 135 public :: xmlf_GetExtendedData 136 137 interface xml_AddCharacters 138 module procedure xml_AddCharacters_Ch 139 end interface 140 interface xml_AddAttribute 141 module procedure xml_AddAttribute_Ch 142 end interface 143 interface xml_AddPseudoAttribute 144 module procedure xml_AddPseudoAttribute_Ch 145 end interface 146 147#ifndef DUMMYLIB 148 !overload error handlers to allow file info 149 interface wxml_warning 150 module procedure wxml_warning_xf, FoX_warning_base 151 end interface 152 interface wxml_error 153 module procedure wxml_error_xf, FoX_error_base 154 end interface 155 interface wxml_fatal 156 module procedure wxml_fatal_xf, FoX_fatal_base 157 end interface 158 159 ! Heuristic (approximate) target for justification of output 160 ! only gets used for outputting attributes 161 integer, parameter :: COLUMNS = 80 162 163 ! TOHW - This is the longest string that may be output without 164 ! a newline. The buffer must not be larger than this, but its size 165 ! can be tuned for performance. 166 !lowest value found so far is 4096, for NAG. We use 1024 just in case. 167 integer, parameter :: xml_recl = 1024 168#endif 169 170contains 171 172 subroutine xml_OpenFile(filename, xf, unit, iostat, preserve_whitespace, & 173 pretty_print, minimize_overrun, canonical, replace, addDecl, warning, & 174 validate, namespace) 175 character(len=*), intent(in) :: filename 176 type(xmlf_t), intent(inout) :: xf 177 integer, intent(in), optional :: unit 178 integer, intent(out), optional :: iostat 179 logical, intent(in), optional :: preserve_whitespace 180 logical, intent(in), optional :: pretty_print 181 logical, intent(in), optional :: minimize_overrun 182 logical, intent(in), optional :: canonical 183 logical, intent(in), optional :: replace 184 logical, intent(in), optional :: addDecl 185 logical, intent(in), optional :: warning 186 logical, intent(in), optional :: validate 187 logical, intent(in), optional :: namespace 188 189#ifdef DUMMYLIB 190 if (present(iostat)) iostat = 0 191#else 192 logical :: repl, decl 193 integer :: iostat_ 194 195 if (xf%lun /= -1) & 196 call wxml_fatal("Trying to reopen an already-open XML file") 197 198 if (present(replace)) then 199 repl = replace 200 else 201 repl = .true. 202 endif 203 if (present(addDecl)) then 204 decl = addDecl 205 else 206 decl = .true. 207 endif 208 if (present(iostat)) iostat = 0 209 210 allocate(xf%name(0)) 211 212 if (present(unit)) then 213 if (unit==-1) then 214 call get_unit(xf%lun,iostat_) 215 if (iostat_ /= 0) then 216 if (present(iostat)) iostat = iostat_ 217 return 218 endif 219 else 220 xf%lun = unit 221 endif 222 else 223 call get_unit(xf%lun,iostat_) 224 if (iostat_ /= 0) then 225 if (present(iostat)) iostat = iostat_ 226 return 227 endif 228 endif 229 230 ! Use large I/O buffer in case the O.S./Compiler combination 231 ! has hard-limits by default (i.e., NAGWare f95's 1024 byte limit) 232 ! This is related to the maximum size of the buffer. 233 ! TOHW - This is the longest string that may be output without 234 ! a newline. The buffer must not be larger than this, but its size 235 ! can be tuned for performance. 236 237 if (repl) then 238 ! NAG insists on unnecessary duplication of iostat etc here 239 if (present(iostat)) then 240 open(unit=xf%lun, file=filename, form="formatted", status="replace", & 241 action="write", recl=xml_recl, iostat=iostat) 242 else 243 open(unit=xf%lun, file=filename, form="formatted", status="replace", & 244 action="write", recl=xml_recl) 245 endif 246 else 247 if (present(iostat)) then 248 open(unit=xf%lun, file=filename, form="formatted", status="new", & 249 action="write", recl=xml_recl, iostat=iostat) 250 else 251 open(unit=xf%lun, file=filename, form="formatted", status="new", & 252 action="write", recl=xml_recl) 253 endif 254 endif 255 256 call init_elstack(xf%stack) 257 258 call init_dict(xf%dict) 259 !NB it can make no difference which XML version we are using 260 !until after we output the XML declaration. So we set it to 261 !1.0 for the moment & reset below. 262 ! Actually, this is done automatically in initializing xf%xds 263 call init_xml_doc_state(xf%xds) 264 xf%xds%documentURI => vs_str_alloc(filename) 265 266 if (present(warning)) then 267 xf%xds%warning = warning 268 else 269 xf%xds%warning = .false. 270 endif 271 if (present(validate)) then 272 xf%xds%valid = validate 273 else 274 xf%xds%valid = .false. 275 endif 276 xf%state_1 = WXML_STATE_1_JUST_OPENED 277 xf%state_2 = WXML_STATE_2_OUTSIDE_TAG 278 xf%state_3 = WXML_STATE_3_BEFORE_DTD 279 280 if (present(pretty_print)) then 281 xf%pretty_print = pretty_print 282 else 283 xf%pretty_print = .true. 284 endif 285 if (present(minimize_overrun)) then 286 xf%minimize_overrun = minimize_overrun 287 else 288 xf%minimize_overrun = .false. 289 endif 290 if (present(preserve_whitespace)) then 291 xf%pretty_print = .not.preserve_whitespace 292 xf%minimize_overrun = preserve_whitespace 293 endif 294 if (present(canonical)) then 295 xf%canonical = canonical 296 else 297 xf%canonical = .false. 298 endif 299! FIXME interplay of above options 300 301 xf%indent = 0 302 303 if (decl) then 304 call xml_AddXMLDeclaration(xf,encoding='UTF-8') 305 ! which will reset the buffer itself 306 else 307 call reset_buffer(xf%buffer, xf%lun, xf%xds%xml_version) 308 endif 309 310 if (present(namespace)) then 311 xf%namespace = namespace 312 else 313 xf%namespace = .true. 314 endif 315 if (xf%namespace) & 316 call initNamespaceDictionary(xf%nsDict) 317#endif 318 end subroutine xml_OpenFile 319 320 321 subroutine xml_AddXMLDeclaration(xf, version, encoding, standalone) 322 type(xmlf_t), intent(inout) :: xf 323 character(len=*), intent(in), optional :: version 324 character(len=*), intent(in), optional :: encoding 325 logical, intent(in), optional :: standalone 326 327#ifndef DUMMYLIB 328 call check_xf(xf) 329 ! Don't need to call checkChars on args, everything is checked 330 ! fully below anyway. 331 332 if (xf%state_1 /= WXML_STATE_1_JUST_OPENED) & 333 call wxml_error("Tried to put XML declaration in wrong place") 334 335 call reset_buffer(xf%buffer, xf%lun, xf%xds%xml_version) 336 337 call xml_AddXMLPI(xf, "xml", xml=.true.) 338 if (present(version)) then 339 if (version =="1.0") then 340 xf%xds%xml_version = XML1_0 341 call xml_AddPseudoAttribute(xf, "version", version) 342 elseif (version=="1.1") then 343 xf%xds%xml_version = XML1_1 344 call xml_AddPseudoAttribute(xf, "version", version) 345 else 346 call wxml_error("Invalid XML version.") 347 endif 348 else 349 call xml_AddPseudoAttribute(xf, "version", "1.0") 350 xf%xds%xml_version = XML1_0 351 endif 352 if (present(encoding)) then 353 if (.not.checkEncName(encoding)) & 354 call wxml_error("Invalid encoding name: "//encoding) 355 if (encoding /= 'UTF-8' .and. encoding /= 'utf-8') & 356 call wxml_warning(xf, "Non-default encoding specified: "//encoding) 357 call xml_AddPseudoAttribute(xf, "encoding", encoding) 358 endif 359 if (present(standalone)) then 360 xf%xds%standalone_declared = .true. 361 xf%xds%standalone = standalone 362 if (standalone) then 363 call xml_AddPseudoAttribute(xf, "standalone", "yes") 364 else 365 call xml_AddPseudoAttribute(xf, "standalone", "no") 366 endif 367 endif 368 call close_start_tag(xf) 369 ! We have to close explicitly here to ensure nothing gets tied 370 ! up in the XML declaration 371 xf%state_1 = WXML_STATE_1_BEFORE_ROOT 372#endif 373 end subroutine xml_AddXMLDeclaration 374 375 376 subroutine xml_AddDOCTYPE(xf, name, system, public) 377 type(xmlf_t), intent(inout) :: xf 378 character(len=*), intent(in) :: name 379 character(len=*), intent(in), optional :: system, public 380 381#ifndef DUMMYLIB 382 type(URI), pointer :: URIref 383 384 call check_xf(xf) 385 386 if (xf%namespace) then 387 if (.not.checkQName(name, xf%xds%xml_version)) & 388 call wxml_error("Invalid Name in DTD "//name) 389 else 390 if (.not.checkName(name, xf%xds%xml_version)) & 391 call wxml_error("Invalid Name in DTD "//name) 392 endif 393 394 if (present(system)) then 395 URIref => parseURI(system) 396 if (.not.associated(URIref)) call wxml_error("xml_AddDOCTYPE: Invalid SYSTEM URI") 397 call destroyURI(URIref) 398 endif 399 if (present(public)) then 400 if (.not.checkPublicId(public)) call wxml_error("xml_AddDOCTYPE: Invalid PUBLIC ID") 401 endif 402 403 if (present(public).and..not.present(system)) & 404 call wxml_error('xml_AddDOCTYPE: PUBLIC supplied without SYSTEM for: '//name) 405 406 ! By having an external ID we probably render this non-standalone (unless we've said that it is in the declaration) 407 if (present(system).and..not.xf%xds%standalone_declared) & 408 xf%xds%standalone=.false. 409 410 call close_start_tag(xf) 411 412 if (xf%state_1 /= WXML_STATE_1_BEFORE_ROOT) & 413 call wxml_error("Tried to put XML DOCTYPE in wrong place: "//name) 414 415 if (xf%state_3 /= WXML_STATE_3_BEFORE_DTD) then 416 call wxml_error("Tried to output more than one DOCTYPE declaration: "//name) 417 else 418 xf%state_3 = WXML_STATE_3_DURING_DTD 419 endif 420 421 call add_eol(xf) 422 call add_to_buffer("<!DOCTYPE "//name, xf%buffer, .false.) 423 424 deallocate(xf%name) 425 allocate(xf%name(len(name))) 426 xf%name = vs_str(name) 427 428 if (present(system)) then 429 if (present(public)) then 430 call add_to_buffer(" PUBLIC", xf%buffer, .false.) 431 call add_to_buffer(" """//public//"""", xf%buffer, .true.) 432 else 433 call add_to_buffer(" SYSTEM", xf%buffer, .false.) 434 endif 435 if (scan(system, """")/=0) then 436 call add_to_buffer(" '"//system//"'", xf%buffer, .true.) 437 else 438 call add_to_buffer(" """//system//"""", xf%buffer, .true.) 439 endif 440 endif 441#endif 442 end subroutine xml_AddDOCTYPE 443 444 445 subroutine xml_AddParameterEntity(xf, name, PEdef, system, public) 446 type(xmlf_t), intent(inout) :: xf 447 character(len=*), intent(in) :: name 448 character(len=*), intent(in), optional :: PEDef 449 character(len=*), intent(in), optional :: system 450 character(len=*), intent(in), optional :: public 451 452#ifndef DUMMYLIB 453 type(URI), pointer :: URIref 454#ifdef PGF90 455 type(URI), pointer :: nullURIref 456#endif 457 call check_xf(xf) 458#ifdef PGF90 459 nullURIref => null() 460#endif 461 if (xf%namespace) then 462 if (.not.checkNCName(name, xf%xds%xml_version)) & 463 call wxml_error("Invalid Name in DTD "//name) 464 else 465 if (.not.checkName(name, xf%xds%xml_version)) & 466 call wxml_error("Invalid Name in DTD "//name) 467 endif 468 469 if (present(PEDef)) then 470 if (.not.checkChars(PEDef,xf%xds%xml_version)) call wxml_error("xml_AddParameterEntity: Invalid character in PEDef") 471 endif 472 473 if (present(system)) then 474 URIref => parseURI(system) 475 if (.not.associated(URIref)) call wxml_error("xml_AddParameterEntity: Invalid SYSTEM URI") 476 call destroyURI(URIref) 477 endif 478 if (present(public)) then 479 if (.not.checkPublicId(public)) call wxml_error("xml_AddParameterEntity: Invalid PUBLIC ID") 480 endif 481 482 ! By adding a parameter entity (internal or external) we make this 483 ! a non-standalone document. 484 if (.not.xf%xds%standalone_declared) & 485 xf%xds%standalone = .false. 486 487 if (xf%state_3 == WXML_STATE_3_DURING_DTD) then 488 call add_to_buffer(" [", xf%buffer, .false.) 489 xf%state_3 = WXML_STATE_3_INSIDE_INTSUBSET 490 endif 491 492 if (xf%state_3 /= WXML_STATE_3_INSIDE_INTSUBSET) & 493 call wxml_fatal("Cannot define Parameter Entity here: "//name) 494 495 if (xf%state_2 == WXML_STATE_2_INSIDE_PI) then 496 call close_start_tag(xf) 497 xf%state_2 = WXML_STATE_2_OUTSIDE_TAG 498 endif 499 500 if (present(PEdef)) then 501 if (present(system) .or. present(public)) & 502 call wxml_fatal("Parameter entity "//name//" cannot have both a PEdef and an External ID") 503 else 504 if (.not.present(system)) & 505 call wxml_fatal("Parameter entity "//name//" must have either a PEdef or an External ID") 506 endif 507 if (present(PEdef)) then 508 if (.not.checkPEDef(PEDef, xf%xds%xml_version)) & 509 call wxml_fatal("Parameter entity definition is invalid: "//PEDef) 510 if (xf%xds%standalone) then 511 if (.not.checkExistingRefs()) & 512 call wxml_error("Tried to reference unregistered parameter entity") 513 else 514 if (.not.checkExistingRefs()) & 515 call wxml_warning(xf, "Reference to unknown parameter entity") 516 endif 517#ifdef PGF90 518 call register_internal_PE(xf%xds, name=name, text=PEdef, baseURI=nullURIref, wfc=.false.) 519#else 520 call register_internal_PE(xf%xds, name=name, text=PEdef, baseURI=null(), wfc=.false.) 521#endif 522 523 else 524#ifdef PGF90 525 call register_external_PE(xf%xds, name=name, systemId=system, & 526 publicId=public, baseURI=nullURIref, wfc=.false.) 527#else 528 call register_external_PE(xf%xds, name=name, systemId=system, & 529 publicId=public, baseURI=null(), wfc=.false.) 530#endif 531 endif 532 533 call add_eol(xf) 534 535 call add_to_buffer("<!ENTITY % "//name, xf%buffer, .false.) ! name can never contain whitespace 536 if (present(PEdef)) then 537 if (index(PEdef, """") > 0) then ! FIXME what if PEdef has both " and ' in it 538 call add_to_buffer(" '"//PEdef//"'", xf%buffer, .true.) 539 else 540 call add_to_buffer(" """//PEdef//"""", xf%buffer, .true.) 541 endif 542 call add_to_buffer(">", xf%buffer, .false.) 543 else 544 if (present(public)) then 545 call add_to_buffer(" PUBLIC", xf%buffer, .false.) 546 call add_to_buffer(" """//public//"""", xf%buffer, .true.) 547 else 548 call add_to_buffer(" SYSTEM", xf%buffer, .false.) 549 endif 550 if (scan(system, """")/=0) then 551 call add_to_buffer(" '"//system//"'", xf%buffer, .true.) 552 else 553 call add_to_buffer(" """//system//"""", xf%buffer, .true.) 554 endif 555 call add_to_buffer(">", xf%buffer) 556 endif 557 558 contains 559 function checkExistingRefs() result(p) 560 logical :: p 561 562 integer :: i1, i2 563 564 ! Here we assume we have syntactic well-formedness as 565 ! checked by checkPEDef. 566 567 p = .false. 568 i1 = index(PEDef, '%') 569 i2 = 0 570 do while (i1 > 0) 571 i1 = i2 + i1 572 i2 = index(PEDef(i1+1:),';') 573 if (i2 == 0) return 574 i2 = i1 + i2 575 if (.not.existing_entity(xf%xds%PEList, PEDef(i1+1:i2-1))) & 576 return 577 i1 = index(PEDef(i2+1:), '%') 578 enddo 579 p = .true. 580 581 end function checkExistingRefs 582#endif 583 end subroutine xml_AddParameterEntity 584 585 586 subroutine xml_AddInternalEntity(xf, name, value) 587 type(xmlf_t), intent(inout) :: xf 588 character(len=*), intent(in) :: name 589 character(len=*), intent(in) :: value 590 591#ifndef DUMMYLIB 592#ifdef PGF90 593 type(URI), pointer :: nullURI 594 nullURI => null() 595#endif 596 call check_xf(xf) 597 598 if (xf%namespace) then 599 if (.not.checkNCName(name, xf%xds%xml_version)) & 600 call wxml_error("Invalid Name in DTD "//name) 601 else 602 if (.not.checkName(name, xf%xds%xml_version)) & 603 call wxml_error("Invalid Name in DTD "//name) 604 endif 605 606 if (.not.checkChars(value, xf%xds%xml_version)) call wxml_error("xml_AddInternalEntity: Invalid character in value") 607 608 if (xf%state_3 == WXML_STATE_3_DURING_DTD) then 609 call add_to_buffer(" [", xf%buffer) 610 xf%state_3 = WXML_STATE_3_INSIDE_INTSUBSET 611 endif 612 613 if (xf%state_3 /= WXML_STATE_3_INSIDE_INTSUBSET) & 614 call wxml_fatal("Cannot define Entity here: "//name) 615 616 if (xf%state_2 == WXML_STATE_2_INSIDE_PI) then 617 call close_start_tag(xf) 618 xf%state_2 = WXML_STATE_2_OUTSIDE_TAG 619 endif 620 621 if (.not.checkName(name, xf%xds%xml_version)) & 622 call wxml_error("xml_AddInternalEntity: Invalid Name: "//name) 623#ifdef PGF90 624 call register_internal_GE(xf%xds, name=name, text=value, baseURI=nullURI, wfc=.false.) 625#else 626 call register_internal_GE(xf%xds, name=name, text=value, baseURI=null(), wfc=.false.) 627#endif 628 629 call add_eol(xf) 630 631 !FIXME - valid entity values? 632 call add_to_buffer("<!ENTITY "//name//" ", xf%buffer, .false.) ! name cannot contain whitespace 633 if (index(value, """") > 0) then 634 call add_to_buffer("'"//value//"'>", xf%buffer, .true.) 635 else 636 call add_to_buffer(""""//value//""">", xf%buffer, .true.) 637 endif 638#endif 639 end subroutine xml_AddInternalEntity 640 641 642 subroutine xml_AddExternalEntity(xf, name, system, public, notation) 643 type(xmlf_t), intent(inout) :: xf 644 character(len=*), intent(in) :: name 645 character(len=*), intent(in) :: system 646 character(len=*), intent(in), optional :: public 647 character(len=*), intent(in), optional :: notation 648 649#ifndef DUMMYLIB 650 type(URI), pointer :: URIref 651#ifdef PGF90 652 type(URI), pointer :: nullURI 653 nullURI => null() 654#endif 655 call check_xf(xf) 656 657 if (xf%namespace) then 658 if (.not.checkNCName(name, xf%xds%xml_version)) & 659 call wxml_error("Invalid Name in DTD "//name) 660 else 661 if (.not.checkName(name, xf%xds%xml_version)) & 662 call wxml_error("Invalid Name in DTD "//name) 663 endif 664 URIref => parseURI(system) 665 if (.not.associated(URIref)) call wxml_error("xml_AddExternalEntity: Invalid SYSTEM URI") 666 call destroyURI(URIref) 667 if (present(public)) then 668 if (.not.checkPublicId(public)) call wxml_error("xml_AddExternalEntity: Invalid PUBLIC ID") 669 endif 670 if (present(notation)) then 671 if (xf%namespace) then 672 if (.not.checkNCName(notation, xf%xds%xml_version)) & 673 call wxml_error("Invalid Name in DTD "//name) 674 else 675 if (.not.checkName(notation, xf%xds%xml_version)) & 676 call wxml_error("Invalid Name in DTD "//name) 677 endif 678 endif 679 680 if (xf%namespace) then 681 if (.not.checkNCName(name, xf%xds%xml_version)) & 682 call wxml_error("Invalid Name in DTD "//name) 683 else 684 if (.not.checkName(name, xf%xds%xml_version)) & 685 call wxml_error("Invalid Name in DTD "//name) 686 endif 687 688 if (xf%state_3 == WXML_STATE_3_DURING_DTD) then 689 call add_to_buffer(" [", xf%buffer, .false.) 690 xf%state_3 = WXML_STATE_3_INSIDE_INTSUBSET 691 endif 692 693 if (xf%state_3 /= WXML_STATE_3_INSIDE_INTSUBSET) & 694 call wxml_fatal("Cannot define Entity here: "//name) 695 696 if (xf%state_2 == WXML_STATE_2_INSIDE_PI) then 697 call close_start_tag(xf) 698 xf%state_2 = WXML_STATE_2_OUTSIDE_TAG 699 endif 700 701 ! Notation only needs checked if not already registered - done above. 702#ifdef PGF90 703 call register_external_GE(xf%xds, name=name, & 704 systemID=system, publicId=public, notation=notation, & 705 baseURI=nullURI, wfc=.false.) 706#else 707 call register_external_GE(xf%xds, name=name, & 708 systemID=system, publicId=public, notation=notation, & 709 baseURI=null(), wfc=.false.) 710#endif 711 712 call add_eol(xf) 713 714 call add_to_buffer("<!ENTITY "//name, xf%buffer, .false.) 715 if (present(public)) then 716 call add_to_buffer(" PUBLIC", xf%buffer, .false.) 717 call add_to_buffer(" """//public//"""", xf%buffer, .true.) 718 else 719 call add_to_buffer(" SYSTEM", xf%buffer, .false.) 720 endif 721 if (scan(system, """")/=0) then 722 call add_to_buffer(" '"//system//"'", xf%buffer, .true.) 723 else 724 call add_to_buffer(" """//system//"""", xf%buffer, .true.) 725 endif 726 if (present(notation)) then 727 call add_to_buffer(" NDATA "//notation, xf%buffer, .false.) 728 endif 729 call add_to_buffer(">", xf%buffer, .false.) 730#endif 731 end subroutine xml_AddExternalEntity 732 733 734 subroutine xml_AddNotation(xf, name, system, public) 735 type(xmlf_t), intent(inout) :: xf 736 character(len=*), intent(in) :: name 737 character(len=*), intent(in), optional :: system 738 character(len=*), intent(in), optional :: public 739 740#ifndef DUMMYLIB 741 type(URI), pointer :: URIref 742 call check_xf(xf) 743 744 if (xf%namespace) then 745 if (.not.checkNCName(name, xf%xds%xml_version)) & 746 call wxml_error("Invalid Name in DTD "//name) 747 else 748 if (.not.checkName(name, xf%xds%xml_version)) & 749 call wxml_error("Invalid Name in DTD "//name) 750 endif 751 if (present(system)) then 752 URIref => parseURI(system) 753 if (.not.associated(URIref)) call wxml_error("xml_AddNotation: Invalid SYSTEM URI") 754 call destroyURI(URIref) 755 endif 756 if (present(public)) then 757 if (.not.checkPublicId(public)) call wxml_error("xml_AddNotation: Invalid PUBLIC ID") 758 endif 759 760 if (xf%state_3 == WXML_STATE_3_DURING_DTD) then 761 call add_to_buffer(" [", xf%buffer, .false.) 762 xf%state_3 = WXML_STATE_3_INSIDE_INTSUBSET 763 endif 764 765 if (xf%state_3 /= WXML_STATE_3_INSIDE_INTSUBSET) & 766 call wxml_fatal("Cannot define Notation here: "//name) 767 768 if (xf%state_2 == WXML_STATE_2_INSIDE_PI) then 769 call close_start_tag(xf) 770 xf%state_2 = WXML_STATE_2_OUTSIDE_TAG 771 endif 772 773 if (notation_exists(xf%xds%nList, name)) & 774 call wxml_error("Tried to create duplicate notation: "//name) 775 776 call add_eol(xf) 777 778 call add_notation(xf%xds%nList, name, system, public) 779 call add_to_buffer("<!NOTATION "//name, xf%buffer, .false.) 780 if (present(public)) then 781 call add_to_buffer(" PUBLIC", xf%buffer, .false.) 782 call add_to_buffer(" """//public//"""", xf%buffer, .true.) 783 elseif (present(system)) then 784 call add_to_buffer(" SYSTEM", xf%buffer, .false.) 785 endif 786 if (present(system)) then 787 if (index(system, """") > 0) then 788 call add_to_buffer(" '"//system//"'", xf%buffer, .true.) 789 else 790 call add_to_buffer(" """//system//"""", xf%buffer, .true.) 791 endif 792 endif 793 call add_to_buffer(">", xf%buffer, .false.) 794#endif 795 end subroutine xml_AddNotation 796 797 798 subroutine xml_AddElementToDTD(xf, name, declaration) 799 type(xmlf_t), intent(inout) :: xf 800 character(len=*), intent(in) :: name 801 character(len=*), intent(in) :: declaration 802 803#ifndef DUMMYLIB 804 type(error_stack) :: stack 805#ifdef PGF90 806 type (element_t), pointer :: nullElement 807 808 nullElement => null() 809#endif 810 call check_xf(xf) 811 812 if (.not.checkChars(declaration,xf%xds%xml_version)) call wxml_error("xml_AddElementToDTD: Invalid character in declaration") 813 814 if (xf%namespace) then 815 if (.not.checkQName(name, xf%xds%xml_version)) & 816 call wxml_error("Invalid Element Name in DTD "//name) 817 else 818 if (.not.checkName(name, xf%xds%xml_version)) & 819 call wxml_error("Invalid Element Name in DTD "//name) 820 endif 821#ifdef PGF90 822 call parse_dtd_element(declaration, xf%xds%xml_version, stack, nullElement, .true.) 823#else 824 call parse_dtd_element(declaration, xf%xds%xml_version, stack, null(), .true.) 825#endif 826 if (in_error(stack)) call wxml_error(xf, "Invalid ELEMENT declaration") 827 828 if (xf%state_3 == WXML_STATE_3_DURING_DTD) then 829 call add_to_buffer(" [", xf%buffer, .false.) 830 xf%state_3 = WXML_STATE_3_INSIDE_INTSUBSET 831 endif 832 833 if (xf%state_3 /= WXML_STATE_3_INSIDE_INTSUBSET) & 834 call wxml_fatal("Cannot write to DTD here: xml_AddElementToDTD") 835 836 if (xf%state_2 == WXML_STATE_2_INSIDE_PI) then 837 call close_start_tag(xf) 838 xf%state_2 = WXML_STATE_2_OUTSIDE_TAG 839 endif 840 841 call add_eol(xf) 842 call add_to_buffer("<!ELEMENT "//name//" "//declaration//">", xf%buffer, .false.) 843#endif 844 end subroutine xml_AddElementToDTD 845 846 847 subroutine xml_AddAttlistToDTD(xf, name, declaration) 848 type(xmlf_t), intent(inout) :: xf 849 character(len=*), intent(in) :: name 850 character(len=*), intent(in) :: declaration 851 852#ifndef DUMMYLIB 853 type(error_stack) :: stack 854#ifdef PGF90 855 type (element_t), pointer :: nullElement 856 857 nullElement => null() 858#endif 859 call check_xf(xf) 860 861 if (.not.checkChars(declaration,xf%xds%xml_version)) call wxml_error("xml_AddAttListToDTD: Invalid character in declaration") 862 863 if (xf%namespace) then 864 if (.not.checkQName(name, xf%xds%xml_version)) & 865 call wxml_error("Invalid Attribute Name in DTD "//name) 866 else 867 if (.not.checkName(name, xf%xds%xml_version)) & 868 call wxml_error("Invalid Attribute Name in DTD "//name) 869 endif 870 871#ifdef PGF90 872 call parse_dtd_attlist(declaration, xf%xds%xml_version, & 873 validCheck=.false., namespaces=xf%namespace, stack=stack, & 874 elem=nullElement, internal=.true.) 875#else 876 call parse_dtd_attlist(declaration, xf%xds%xml_version, & 877 validCheck=.false., namespaces=xf%namespace, stack=stack, & 878 elem=null(), internal=.true.) 879#endif 880 881 if (in_error(stack)) call wxml_error(xf, "Invalid ATTLIST declaration") 882 883 if (xf%state_3 == WXML_STATE_3_DURING_DTD) then 884 call add_to_buffer(" [", xf%buffer, .false.) 885 xf%state_3 = WXML_STATE_3_INSIDE_INTSUBSET 886 endif 887 888 if (xf%state_3 /= WXML_STATE_3_INSIDE_INTSUBSET) & 889 call wxml_fatal("Cannot write to DTD here: xml_AddAttlistToDTD") 890 891 if (xf%state_2 == WXML_STATE_2_INSIDE_PI) then 892 call close_start_tag(xf) 893 xf%state_2 = WXML_STATE_2_OUTSIDE_TAG 894 endif 895 896 call add_eol(xf) 897 call add_to_buffer("<!ATTLIST "//name//" "//declaration//">", xf%buffer, .false.) 898#endif 899 end subroutine xml_AddAttlistToDTD 900 901 902 subroutine xml_AddPEReferenceToDTD(xf, name) 903 type(xmlf_t), intent(inout) :: xf 904 character(len=*), intent(in) :: name 905 906#ifndef DUMMYLIB 907 call check_xf(xf) 908 909 if (xf%namespace) then 910 if (.not.checkNCName(name, xf%xds%xml_version)) & 911 call wxml_error("Invalid PE Name in DTD "//name) 912 else 913 if (.not.checkName(name, xf%xds%xml_version)) & 914 call wxml_error("Invalid PE Name in DTD "//name) 915 endif 916 917 call wxml_warning(xf, "Adding PEReference to DTD. Cannot guarantee well-formedness") 918 if (.not.existing_entity(xf%xds%PEList, name)) then 919 if (.not.xf%xds%standalone) then 920 call wxml_warning(xf, "Tried to reference possibly unregistered parameter entity in DTD: "//name) 921 else 922 call wxml_error("Tried to reference unregistered parameter entity in DTD "//name) 923 endif 924 else 925 if (is_unparsed_entity(xf%xds%PEList, name)) & 926 call wxml_error("Tried to reference unparsed parameter entity in DTD "//name) 927 endif 928 929 if (xf%state_3 == WXML_STATE_3_DURING_DTD) then 930 call add_to_buffer(" [", xf%buffer, .false.) 931 xf%state_3 = WXML_STATE_3_INSIDE_INTSUBSET 932 endif 933 934 if (xf%state_3 /= WXML_STATE_3_INSIDE_INTSUBSET) & 935 call wxml_fatal("Cannot write to DTD here: xml_AddPEReferenceToDTD") 936 937 if (xf%state_2 == WXML_STATE_2_INSIDE_PI) then 938 call close_start_tag(xf) 939 xf%state_2 = WXML_STATE_2_OUTSIDE_TAG 940 endif 941 942 call add_eol(xf) 943 call add_to_buffer("%"//name//";", xf%buffer, .false.) 944 945#endif 946 end subroutine xml_AddPEReferenceToDTD 947 948 949 subroutine xml_AddXMLStylesheet(xf, href, type, title, media, charset, alternate) 950 type(xmlf_t), intent(inout) :: xf 951 character(len=*), intent(in) :: href 952 character(len=*), intent(in) :: type 953 character(len=*), intent(in), optional :: title 954 character(len=*), intent(in), optional :: media 955 character(len=*), intent(in), optional :: charset 956 logical, intent(in), optional :: alternate 957 958#ifndef DUMMYLIB 959 call check_xf(xf) 960 ! Don't bother checking name - all pseudoatts get checked anyway. 961 962 if (xf%state_1 /= WXML_STATE_1_JUST_OPENED & 963 .and. xf%state_1 /= WXML_STATE_1_BEFORE_ROOT) & 964 call wxml_error("Cannot add stylesheet here: "//href) 965 966 call close_start_tag(xf) 967 968 call xml_AddXMLPI(xf, 'xml-stylesheet', xml=.true.) 969 call xml_AddPseudoAttribute(xf, 'href', href) 970 call xml_AddPseudoAttribute(xf, 'type', type) 971 972 if (present(title)) call xml_AddPseudoAttribute(xf, 'title', title) 973 if (present(media)) call xml_AddPseudoAttribute(xf, 'media', media) 974 if (present(charset)) call xml_AddPseudoAttribute(xf, 'charset', charset) 975 if (present(alternate)) then 976 if (alternate) then 977 call xml_AddPseudoAttribute(xf, 'alternate', 'yes') 978 else 979 call xml_AddPseudoAttribute(xf, 'alternate', 'no') 980 endif 981 endif 982 if (xf%state_1 == WXML_STATE_1_JUST_OPENED) & 983 xf%state_1 = WXML_STATE_1_BEFORE_ROOT 984 xf%state_2 = WXML_STATE_2_INSIDE_PI 985#endif 986 end subroutine xml_AddXMLStylesheet 987 988 989 subroutine xml_AddXMLPI(xf, name, data, xml, ws_significant) 990 type(xmlf_t), intent(inout) :: xf 991 character(len=*), intent(in) :: name 992 character(len=*), intent(in), optional :: data 993 logical, intent(in), optional :: xml 994 logical, intent(in), optional :: ws_significant 995 996 logical :: xml_ 997#ifndef DUMMYLIB 998 call check_xf(xf) 999 1000 if (present(xml)) then 1001 xml_ = xml 1002 else 1003 xml_ = .false. 1004 endif 1005 1006 if (xf%namespace) then 1007 if (.not.checkNCName(name, xf%xds%xml_version)) & 1008 call wxml_error("Invalid PI target "//name) 1009 else 1010 if (.not.checkName(name, xf%xds%xml_version)) & 1011 call wxml_error("Invalid PI target "//name) 1012 endif 1013 if (.not.xml_) then 1014 if (len(name)==3.and.(toLower(name)=="xml")) & 1015 call wxml_error("Invalid PI target "//name) 1016 endif 1017 1018 if (present(data)) then 1019 if (.not.checkChars(data,xf%xds%xml_version)) & 1020 call wxml_error("xml_AddXMLPI: Invalid character in data") 1021 endif 1022 1023 select case (xf%state_1) 1024 case (WXML_STATE_1_JUST_OPENED) 1025 xf%state_1 = WXML_STATE_1_BEFORE_ROOT 1026 case (WXML_STATE_1_DURING_ROOT) 1027 call close_start_tag(xf) 1028 if (xf%pretty_print) call add_eol(xf) 1029 case default 1030 call close_start_tag(xf) 1031 call add_eol(xf) 1032 end select 1033 call add_to_buffer("<?" // name, xf%buffer, .false.) 1034 if (present(data)) then 1035 if (len(data)>0) then 1036 if (index(data, '?>') > 0) & 1037 call wxml_error(xf, "Tried to output invalid PI data "//data) 1038 call add_to_buffer(' ', xf%buffer, .false.) 1039 call add_to_buffer(data//'?>', xf%buffer, ws_significant) 1040 ! state_2 is now OUTSIDE_TAG from close_start_tag 1041 else 1042 xf%state_2 = WXML_STATE_2_INSIDE_PI 1043 call reset_dict(xf%dict) 1044 endif 1045 else 1046 xf%state_2 = WXML_STATE_2_INSIDE_PI 1047 call reset_dict(xf%dict) 1048 endif 1049#endif 1050 end subroutine xml_AddXMLPI 1051 1052 1053 subroutine xml_AddComment(xf, comment, ws_significant) 1054 type(xmlf_t), intent(inout) :: xf 1055 character(len=*), intent(in) :: comment 1056 logical, intent(in), optional :: ws_significant 1057 1058#ifndef DUMMYLIB 1059 call check_xf(xf) 1060 if (.not.checkChars(comment,xf%xds%xml_version)) call wxml_error("xml_AddComment: Invalid character in comment") 1061 1062 select case (xf%state_1) 1063 case (WXML_STATE_1_JUST_OPENED) 1064 xf%state_1 = WXML_STATE_1_BEFORE_ROOT 1065 case (WXML_STATE_1_DURING_ROOT) 1066 call close_start_tag(xf) 1067 if (xf%pretty_print.and.xf%state_2 == WXML_STATE_2_OUTSIDE_TAG) call add_eol(xf) 1068 case default 1069 call close_start_tag(xf) 1070 call add_eol(xf) 1071 end select 1072 1073 if (index(comment,'--') > 0 .or. comment(len(comment):) == '-') & 1074 call wxml_error("Tried to output invalid comment "//comment) 1075 1076 call add_to_buffer("<!--", xf%buffer, .false.) 1077 call add_to_buffer(comment, xf%buffer, ws_significant) 1078 call add_to_buffer("-->", xf%buffer, .false.) 1079#endif 1080 end subroutine xml_AddComment 1081 1082 1083 subroutine xml_NewElement(xf, name) 1084 type(xmlf_t), intent(inout) :: xf 1085 character(len=*), intent(in) :: name 1086 1087#ifndef DUMMYLIB 1088 call check_xf(xf) 1089 1090 if (xf%namespace) then 1091 if (.not.checkQName(name, xf%xds%xml_version)) & 1092 call wxml_error("Invalid Element Name "//name) 1093 else 1094 if (.not.checkName(name, xf%xds%xml_version)) & 1095 call wxml_error("Invalid Element Name "//name) 1096 endif 1097 1098 select case (xf%state_1) 1099 case (WXML_STATE_1_JUST_OPENED, WXML_STATE_1_BEFORE_ROOT) 1100 if (xf%xds%valid) then 1101 if (size(xf%name)==0) then 1102 call wxml_error(xf, "No DTD specified for document") 1103 elseif (str_vs(xf%name) /= name) then 1104 call wxml_error(xf, "Root element name does not match DTD") 1105 endif 1106 endif 1107 call close_start_tag(xf) 1108 if (xf%state_3 /= WXML_STATE_3_BEFORE_DTD) then 1109 select case (xf%state_3) 1110 case (WXML_STATE_3_DURING_DTD) 1111 call add_to_buffer('>', xf%buffer, .false.) 1112 xf%state_3 = WXML_STATE_3_AFTER_DTD 1113 case (WXML_STATE_3_INSIDE_INTSUBSET) 1114 xf%state_3 = WXML_STATE_3_AFTER_DTD 1115 call add_eol(xf) 1116 call add_to_buffer(']>', xf%buffer, .false.) 1117 end select 1118 endif 1119 call add_eol(xf) 1120 case (WXML_STATE_1_DURING_ROOT) 1121 call close_start_tag(xf) 1122 if (xf%pretty_print) call add_eol(xf) 1123 case (WXML_STATE_1_AFTER_ROOT) 1124 call wxml_error(xf, "Two root elements: "//name) 1125 end select 1126 1127 if (xf%namespace) then 1128 if (len(prefixOfQName(name)) > 0) then 1129 if (.not.isPrefixInForce(xf%nsDict, prefixOfQName(name))) & 1130 call wxml_error(xf, "Namespace prefix not registered: "//prefixOfQName(name)) 1131 endif 1132 endif 1133 1134 call push_elstack(xf%stack, name) 1135 call add_to_buffer("<"//name, xf%buffer, .false.) 1136 xf%state_2 = WXML_STATE_2_INSIDE_ELEMENT 1137 call reset_dict(xf%dict) 1138 xf%indent = xf%indent + indent_inc 1139 xf%state_1 = WXML_STATE_1_DURING_ROOT 1140#endif 1141 end subroutine xml_NewElement 1142 1143 1144 subroutine xml_AddCharacters_ch(xf, chars, parsed, ws_significant) 1145 type(xmlf_t), intent(inout) :: xf 1146 character(len=*), intent(in) :: chars 1147 logical, intent(in), optional :: parsed 1148 logical, intent(in), optional :: ws_significant 1149 1150#ifndef DUMMYLIB 1151 logical :: pc 1152 1153 call check_xf(xf) 1154 if (.not.checkChars(chars, xf%xds%xml_version)) call wxml_error("xml_AddCharacters: Invalid character in chars") 1155 1156 if (xf%state_1 /= WXML_STATE_1_DURING_ROOT) & 1157 call wxml_fatal("Tried to add text section in wrong place: "//chars) 1158 1159 if (present(parsed)) then 1160 pc = parsed 1161 else 1162 pc = .true. 1163 endif 1164 1165 call close_start_tag(xf) 1166 1167 if (pc) then 1168 call add_to_buffer(escape_string(chars, xf%xds%xml_version), xf%buffer, ws_significant) 1169 else 1170 ! FIXME what if we try and output two separate character events? 1171 ! need to keep track of this ... 1172 if (index(chars,']]>') > 0) & 1173 call wxml_fatal("Tried to output invalid CDATA: "//chars) 1174 call add_to_buffer("<![CDATA["//chars//"]]>", xf%buffer, ws_significant) 1175 endif 1176 1177 xf%state_2 = WXML_STATE_2_IN_CHARDATA 1178#endif 1179 end subroutine xml_AddCharacters_Ch 1180 1181 1182 subroutine xml_AddNewline(xf) 1183 type(xmlf_t), intent(inout) :: xf 1184 1185#ifndef DUMMYLIB 1186 call xml_AddCharacters(xf, "") ! To ensure we are in a text section 1187 call add_eol(xf) 1188#endif 1189 end subroutine xml_AddNewline 1190 1191 1192 subroutine xml_AddEntityReference(xf, name) 1193 type(xmlf_t), intent(inout) :: xf 1194 character(len=*), intent(in) :: name 1195 1196#ifndef DUMMYLIB 1197 call check_xf(xf) 1198 1199 if (likeCharacterEntityReference(name)) then 1200 if (.not.checkCharacterEntityReference(name, xf%xds%xml_version)) & 1201 call wxml_error("Invalid Character Entity Reference "//name) 1202 elseif (xf%namespace) then 1203 if (.not.checkNCName(name, xf%xds%xml_version)) & 1204 call wxml_error("Invalid Entity Name "//name) 1205 else 1206 if (.not.checkName(name, xf%xds%xml_version)) & 1207 call wxml_error("Invalid Entity Name "//name) 1208 endif 1209 1210 call close_start_tag(xf) 1211 1212 if (xf%state_2 /= WXML_STATE_2_OUTSIDE_TAG .and. & 1213 xf%state_2 /= WXML_STATE_2_IN_CHARDATA) & 1214 call wxml_fatal("Tried to add entity reference in wrong place: "//name) 1215 1216 if (.not.checkCharacterEntityReference(name, xf%xds%xml_version)) then 1217 !it's not just a unicode entity 1218 call wxml_warning(xf, "Entity reference added - document may not be well-formed") 1219 if (.not.existing_entity(xf%xds%entityList, name)) then 1220 if (xf%xds%standalone) then 1221 call wxml_error("Tried to reference unregistered entity") 1222 else 1223 call wxml_warning(xf, "Tried to reference unregistered entity") 1224 endif 1225 else 1226 if (is_unparsed_entity(xf%xds%entityList, name)) & 1227 call wxml_error("Tried to reference unparsed entity") 1228 endif 1229 endif 1230 1231 call add_to_buffer('&'//name//';', xf%buffer, .false.) 1232 xf%state_2 = WXML_STATE_2_IN_CHARDATA 1233#endif 1234 end subroutine xml_AddEntityReference 1235 1236 1237 subroutine xml_AddAttribute_Ch(xf, name, value, escape, type, ws_significant) 1238 type(xmlf_t), intent(inout) :: xf 1239 character(len=*), intent(in) :: name 1240 character(len=*), intent(in) :: value 1241 logical, intent(in), optional :: escape 1242 character(len=*), intent(in), optional :: type 1243 logical, intent(in), optional :: ws_significant 1244 1245#ifndef DUMMYLIB 1246 logical :: esc 1247 character, pointer :: type_(:) 1248 1249 if (present(type)) then 1250 if (type/='CDATA'.and.type/='ID'.and.type/='IDREF'.and.type/='IDREFS'.and.type/='NMTOKEN'.and.type/='NMTOKENS' & 1251 .and.type/='ENTITY'.and.type/='ENTITIES'.and.type/='NOTATION') then 1252 call wxml_fatal("Invalid type in xml_AddAttribute: "//type) 1253 endif 1254 type_ => vs_str_alloc(type) 1255 else 1256 ! We assume CDATA, but need to worry about whether the caller cares about whitespace ... 1257 if (present(ws_significant)) then 1258 if (ws_significant) then 1259 type_ => vs_str_alloc('CDATA') 1260 else 1261 type_ => vs_str_alloc('CDANO') ! CDAta, whitespace Not significant 1262 endif 1263 else 1264 type_ => vs_str_alloc('CDAMB') ! CDAta, whitespace MayBe significant 1265 endif 1266 endif 1267 1268 call check_xf(xf) 1269 1270 if (.not.checkChars(value, xf%xds%xml_version)) call wxml_error("xml_AddAttribute: Invalid character in value") 1271 1272 if (xf%namespace) then 1273 if (.not.checkQName(name, xf%xds%xml_version)) & 1274 call wxml_error("Invalid Attribute Name "//name) 1275 else 1276 if (.not.checkName(name, xf%xds%xml_version)) & 1277 call wxml_error("Invalid Attribute Name "//name) 1278 endif 1279 1280 if (present(escape)) then 1281 esc = escape 1282 else 1283 esc = .true. 1284 endif 1285 1286 if (name=="xml:space") then 1287 ! The value can only be "default" or "preserve", by 2.10 1288 if (.not.esc) then 1289 if (value/="default".and.value/="preserve") & 1290 call wxml_fatal("Invalid value for xml:space attrbute") 1291 endif 1292 endif 1293 1294 ! FIXME when escape is false we should still do full verification 1295 ! where possible. 1296 ! Currently - minimal check: only extra allowed is character entity references. 1297 ! We check they exist, and are not unparsed. 1298 ! Ideally we would fully expand all entity references (at least for 1299 ! a standalone document where we can) and then 1300 ! match the resultant production against [XML]-3.3.1. This is 1301 ! initially too much work though, so we just check simple 1302 ! syntactic constraint. 1303 1304 if (.not.esc) then 1305 if (.not.checkAttValue(value, xf%xds%xml_version)) & 1306 call wxml_error(xf, "Invalid attribute value: "//value) 1307 if (index(value, '&') > 0) then 1308 ! There are entity references 1309 ! They should exist (unless we are not standalone) and they must not be unparsed. 1310 if (.not.checkExistingRefsInAttValue()) then 1311 if (xf%xds%standalone) then 1312 call wxml_error(xf, "outputting unknown entity. Cannot guarantee validity.") 1313 else 1314 call wxml_warning(xf, "Warning: outputting unknown entity. Cannot guarantee validity.") 1315 endif 1316 endif 1317 if (.not.checkParsedRefsInAttValue()) & 1318 call wxml_error(xf, "Warning: outputting unknown entity. Cannot guarantee validity.") 1319 endif 1320 endif 1321 1322 if (xf%state_2 /= WXML_STATE_2_INSIDE_ELEMENT) & 1323 call wxml_error(xf, "attributes outside element content: "//name) 1324 1325 if (hasKey(xf%dict,name)) then 1326 call wxml_error(xf, "duplicate att name: "//name) 1327 elseif (xf%namespace) then 1328 if (hasKey(xf%dict, & 1329 getnamespaceURI(xf%nsDict,prefixOfQname(name)), localpartofQname(name))) then 1330 call wxml_error(xf, "duplicate att after namespace processing: "//name) 1331 endif 1332 endif 1333 1334 if (xf%namespace) then 1335 if (len(prefixOfQName(name))>0) then 1336 if (prefixOfQName(name)/="xml".and.prefixOfQName(name)/="xmlns") then 1337 if (.not.isPrefixInForce(xf%nsDict, prefixOfQName(name))) & 1338 call wxml_error(xf, "namespace prefix not registered: "//prefixOfQName(name)) 1339 endif 1340 if (esc) then 1341 call add_item_to_dict(xf%dict, localpartofQname(name), escape_string(value, xf%xds%xml_version), prefixOfQName(name), & 1342 getnamespaceURI(xf%nsDict,prefixOfQname(name)), type=str_vs(type_)) 1343 else 1344 call add_item_to_dict(xf%dict, localpartofQname(name), value, prefixOfQName(name), & 1345 getnamespaceURI(xf%nsDict,prefixOfQName(name)), type=str_vs(type_)) 1346 endif 1347 else 1348 if (esc) then 1349 call add_item_to_dict(xf%dict, name, escape_string(value, xf%xds%xml_version), type=str_vs(type_)) 1350 else 1351 call add_item_to_dict(xf%dict, name, value, type=str_vs(type_)) 1352 endif 1353 endif 1354 else 1355 if (esc) then 1356 call add_item_to_dict(xf%dict, name, escape_string(value, xf%xds%xml_version), type=str_vs(type_)) 1357 else 1358 call add_item_to_dict(xf%dict, name, value, type=str_vs(type_)) 1359 endif 1360 endif 1361 1362 !FIXME need to deallocate this when we move to better error handling 1363 deallocate(type_) 1364 1365 contains 1366 function checkExistingRefsInAttValue() result(p) 1367 logical :: p 1368 1369 integer :: i1, i2 1370 1371 ! Here we assume we have syntactic well-formedness as 1372 ! checked by checkAttValue. 1373 ! We also assume we do not have simply one entity as 1374 ! the contents - that is checked by checkAttValueEntity 1375 1376 p = .false. 1377 i1 = index(value, '&') 1378 i2 = 0 1379 do while (i1 > 0) 1380 i1 = i2 + i1 1381 i2 = index(value(i1+1:),';') 1382 if (i2 == 0) return 1383 i2 = i1 + i2 1384 if (.not.existing_entity(xf%xds%entityList, value(i1+1:i2-1)) .and. & 1385 .not.checkCharacterEntityReference(value(i1+1:i2-1), xf%xds%xml_version)) & 1386 return 1387 i1 = index(value(i2+1:), '&') 1388 enddo 1389 p = .true. 1390 1391 end function checkExistingRefsInAttValue 1392 1393 function checkParsedRefsInAttValue() result(p) 1394 logical :: p 1395 1396 integer :: i1, i2 1397 1398 ! Here we assume we have syntactic well-formedness as 1399 ! checked by checkAttValue. 1400 1401 p = .false. 1402 i1 = index(value, '&') 1403 i2 = 0 1404 do while (i1 > 0) 1405 i1 = i1 + i2 1406 i2 = index(value(i1+1:),';') 1407 if (i2 == 0) return 1408 i2 = i1 + i2 1409 if (is_unparsed_entity(xf%xds%entityList, value(i1+1:i2-1))) & 1410 return 1411 i1 = index(value(i2+1:), '&') 1412 enddo 1413 p = .true. 1414 1415 end function checkParsedRefsInAttValue 1416#endif 1417 end subroutine xml_AddAttribute_Ch 1418 1419 1420 subroutine xml_AddPseudoAttribute_Ch(xf, name, value, escape, ws_significant) 1421 type(xmlf_t), intent(inout) :: xf 1422 character(len=*), intent(in) :: name 1423 character(len=*), intent(in) :: value 1424 logical, intent(in), optional :: escape 1425 logical, intent(in), optional :: ws_significant 1426 1427#ifndef DUMMYLIB 1428 logical :: esc 1429 character(len=5) :: type 1430 1431 call check_xf(xf) 1432 if (.not.checkChars(name, xf%xds%xml_version)) call wxml_error("xml_AddPseudoAttribute: Invalid character in name") 1433 if (.not.checkChars(value, xf%xds%xml_version)) call wxml_error("xml_AddPseudoAttribute: Invalid character in value") 1434 1435 if (present(escape)) then 1436 esc = escape 1437 else 1438 esc = .true. 1439 endif 1440 if (present(ws_significant)) then 1441 if (ws_significant) then 1442 type='CDATA' 1443 else 1444 type='CDANO' ! CDAta, whitespace Not significant 1445 endif 1446 else 1447 type='CDAMB' ! CDAta, whitespace MayBe significant 1448 endif 1449 1450 if (index(value, '?>') > 0) & 1451 call wxml_error(xf, "Invalid pseudo-attribute value: "//value) 1452 if (.not.esc) then 1453 if (.not.checkPseudoAttValue(value, xf%xds%xml_version)) & 1454 call wxml_error(xf, "Invalid pseudo-attribute value: "//value) 1455 endif 1456 1457 if (xf%state_2 /= WXML_STATE_2_INSIDE_PI) & 1458 call wxml_error("PI pseudo-attribute outside PI: "//name) 1459 1460 ! This is mostly ad-hoc, pseudo-attribute names are not defined anywhere. 1461 if (.not.checkName(name, xf%xds%xml_version)) & 1462 call wxml_error("Invalid pseudo-attribute name: "//name) 1463 1464 if (hasKey(xf%dict,name)) & 1465 call wxml_error(xf, "duplicate pseudo-attribute name: "//name) 1466 1467 if (index(value, '?>') > 0) & 1468 call wxml_error(xf, "Invalid pseudo-attribute data: "//value) 1469 1470 if (esc) then 1471 call add_item_to_dict(xf%dict, name, escape_string(value, xf%xds%xml_version), type=type) 1472 else 1473 call add_item_to_dict(xf%dict, name, value, type=type) 1474 endif 1475#endif 1476 end subroutine xml_AddPseudoAttribute_Ch 1477 1478 1479 subroutine xml_EndElement(xf, name) 1480 type(xmlf_t), intent(inout) :: xf 1481 character(len=*), intent(in) :: name 1482 1483 character :: dummy 1484#ifndef DUMMYLIB 1485 call check_xf(xf) 1486 ! No point in doing checkChars, name is compared to stack anyway. 1487 1488 if (len(xf%stack) == 0) & 1489 call wxml_fatal(xf,'Trying to close '//name//' but no tags are open.') 1490 1491 if (get_top_elstack(xf%stack) /= name) & 1492 call wxml_fatal(xf, 'Trying to close '//name//' but '//get_top_elstack(xf%stack)// & 1493 ' is open. Either you have failed to open '//name//& 1494 ' or you have failed to close '//get_top_elstack(xf%stack)//'.') 1495 xf%indent = xf%indent - indent_inc 1496 1497 if (xf%state_2==WXML_STATE_2_INSIDE_ELEMENT) then 1498 if (xf%namespace) call checkNamespacesWriting(xf%dict, xf%nsDict, len(xf%stack)) 1499 if (getLength(xf%dict) > 0) call write_attributes(xf) 1500 if (xf%minimize_overrun) call add_eol(xf) 1501 endif 1502 if (xf%state_2==WXML_STATE_2_INSIDE_ELEMENT.and..not.xf%canonical) then 1503 call add_to_buffer("/>", xf%buffer, .false.) 1504 else 1505 if (xf%state_2==WXML_STATE_2_INSIDE_ELEMENT) & 1506 call add_to_buffer('>', xf%buffer, .false.) 1507 if (xf%state_2==WXML_STATE_2_INSIDE_PI) & 1508 call close_start_tag(xf) 1509 if (xf%state_2==WXML_STATE_2_OUTSIDE_TAG.and.xf%pretty_print) & 1510 call add_eol(xf) 1511! XLF does a weird thing here, and if pop_elstack is called as an 1512! argument to the add_to_buffer, it gets called twice. So we have to separate 1513! out get_top_... from pop_... 1514 call add_to_buffer("</" //get_top_elstack(xf%stack), xf%buffer, .false.) 1515 if (xf%minimize_overrun) call add_eol(xf) 1516 call add_to_buffer(">", xf%buffer, .false.) 1517 endif 1518 dummy = pop_elstack(xf%stack) 1519 1520 if (xf%namespace) call checkEndNamespaces(xf%nsDict, len(xf%stack)+1) 1521 if (is_empty(xf%stack)) then 1522 xf%state_1 = WXML_STATE_1_AFTER_ROOT 1523 endif 1524 xf%state_2 = WXML_STATE_2_OUTSIDE_TAG 1525#endif 1526 end subroutine xml_EndElement 1527 1528 1529 subroutine xml_DeclareNamespace(xf, nsURI, prefix, xml) 1530 type(xmlf_t), intent(inout) :: xf 1531 character(len=*), intent(in) :: nsURI 1532 character(len=*), intent(in), optional :: prefix 1533 logical, intent(in), optional :: xml 1534 1535#ifndef DUMMYLIB 1536 call check_xf(xf) 1537 if (.not.xf%namespace) call wxml_error("Cannot declare a namespace in a non-namespaced document") 1538 1539 !if (.not.checkNCName(nsURI, xf%xds%xml_version)) call wxml_error("xml_DeclareNamespace: Invalid nsURI") 1540 if (present(prefix)) then 1541 if (.not.checkNCName(prefix, xf%xds%xml_version)) call wxml_error("xml_DeclareNamespace: Invalid prefix") 1542 endif 1543 1544 if (xf%state_1 == WXML_STATE_1_AFTER_ROOT) & 1545 call wxml_error(xf, "adding namespace outside element content") 1546 1547 if (len(nsURI) == 0) then 1548 if (present(prefix).and.xf%xds%xml_version==XML1_0) & 1549 call wxml_error(xf, "prefixed namespace with empty URI forbidden in XML 1.0") 1550 endif 1551 1552 if (present(prefix)) then 1553 call addPrefixedNS(xf%nsDict, prefix, nsURI, len(xf%stack)+1, xf%xds, xml) 1554 else 1555 call addDefaultNS(xf%nsDict, nsURI, len(xf%stack)+1) 1556 endif 1557#endif 1558 end subroutine xml_DeclareNamespace 1559 1560 1561 subroutine xml_UndeclareNamespace(xf, prefix) 1562 type(xmlf_t), intent(inout) :: xf 1563 character(len=*), intent(in), optional :: prefix 1564 1565#ifndef DUMMYLIB 1566 call check_xf(xf) 1567 !No need to checkChars, prefix is checked against stack 1568 if (.not.xf%namespace) call wxml_error("Cannot declare a namespace in a non-namespaced document") 1569 1570 if (present(prefix).and.xf%xds%xml_version==XML1_0) & 1571 call wxml_error("cannot undeclare prefixed namespaces in XML 1.0") 1572 1573 if (xf%state_1 == WXML_STATE_1_AFTER_ROOT) & 1574 call wxml_error(xf, "Undeclaring namespace outside element content") 1575 1576 if (present(prefix)) then 1577 call addPrefixedNS(xf%nsDict, prefix, "", len(xf%stack)+1, xf%xds) 1578 else 1579 call addDefaultNS(xf%nsDict, "", len(xf%stack)+1) 1580 endif 1581#endif 1582 end subroutine xml_UndeclareNamespace 1583 1584 1585 subroutine xml_Close(xf, empty) 1586 type(xmlf_t), intent(inout) :: xf 1587 logical, optional :: empty 1588 1589#ifndef DUMMYLIB 1590 logical :: empty_ 1591 1592 if (present(empty)) then 1593 empty_ = empty 1594 else 1595 empty_ = .false. 1596 endif 1597 1598 if (xf%lun == -1) & 1599 call wxml_fatal('Tried to close XML file which is not open') 1600 1601 if (xf%state_2 == WXML_STATE_2_INSIDE_PI) & 1602 call close_start_tag(xf) 1603 1604 if (xf%state_3 /= WXML_STATE_3_BEFORE_DTD & 1605 .and. xf%state_3 /= WXML_STATE_3_AFTER_DTD) then 1606 select case (xf%state_3) 1607 case (WXML_STATE_3_DURING_DTD) 1608 call add_to_buffer('>', xf%buffer, .false.) 1609 case (WXML_STATE_3_INSIDE_INTSUBSET) 1610 call add_eol(xf) 1611 call add_to_buffer(']>', xf%buffer, .false.) 1612 end select 1613 xf%state_3 = WXML_STATE_3_AFTER_DTD 1614 endif 1615 1616 do while (xf%state_1 == WXML_STATE_1_DURING_ROOT) 1617 call xml_EndElement(xf, get_top_elstack(xf%stack)) 1618 enddo 1619 1620 if (xf%state_1 /= WXML_STATE_1_AFTER_ROOT) then 1621 if (empty_) then 1622 call wxml_warning(xf, 'Invalid XML document produced: No root element') 1623 else 1624 call wxml_error(xf, 'Invalid XML document produced: No root element') 1625 endif 1626 endif 1627 1628 call dump_buffer(xf%buffer) 1629 close(unit=xf%lun) 1630 xf%lun = -1 1631 1632 call destroy_dict(xf%dict) 1633 call destroy_elstack(xf%stack) 1634 1635 if (xf%namespace) & 1636 call destroyNamespaceDictionary(xf%nsDict) 1637 call destroy_xml_doc_state(xf%xds) 1638 1639 deallocate(xf%name) 1640#endif 1641 end subroutine xml_Close 1642 1643 subroutine xmlf_SetPretty_print(xf, new_value) 1644 type(xmlf_t), intent(inout) :: xf 1645 logical, intent(in) :: new_value 1646#ifndef DUMMYLIB 1647 xf%pretty_print = new_value 1648#endif 1649 end subroutine xmlf_SetPretty_print 1650 1651 pure function xmlf_GetPretty_print(xf) result(value) 1652 logical :: value 1653 type(xmlf_t), intent(in) :: xf 1654#ifdef DUMMYLIB 1655 value = .false. 1656#else 1657 value = xf%pretty_print 1658#endif 1659 end function xmlf_GetPretty_print 1660 1661! xf%extended data is an integer so that writers 1662! can change there behaviour depending on some 1663! stored information. Currently only used for 1664! wcml 'validate' argument (which is intended to 1665! check some of the more troublesome aspects of 1666! the CML schema 1667 subroutine xmlf_SetExtendedData(xf, new_value) 1668 type(xmlf_t), intent(inout) :: xf 1669 integer, intent(in) :: new_value 1670#ifndef DUMMYLIB 1671 xf%extended_data = new_value 1672#endif 1673 end subroutine xmlf_SetExtendedData 1674 1675 pure function xmlf_GetExtendedData(xf) result(value) 1676 integer :: value 1677 type(xmlf_t), intent(in) :: xf 1678#ifdef DUMMYLIB 1679 value = .false. 1680#else 1681 value = xf%extended_data 1682#endif 1683 end function xmlf_GetExtendedData 1684 1685 pure function xmlf_name(xf) result(fn) 1686 type (xmlf_t), intent(in) :: xf 1687#ifdef DUMMYLIB 1688 character(len=1) :: fn 1689 fn = " " 1690#else 1691 character(len=size(xf%xds%documentURI)) :: fn 1692 fn = str_vs(xf%xds%documentURI) 1693#endif 1694 end function xmlf_name 1695 1696#ifndef DUMMYLIB 1697 pure function xmlf_opentag_len(xf) result(n) 1698 type (xmlf_t), intent(in) :: xf 1699 integer :: n 1700 1701 if (xf%lun == -1) then 1702 n = 0 1703 elseif (is_empty(xf%stack)) then 1704 n = 0 1705 else 1706 n = len(get_top_elstack(xf%stack)) 1707 endif 1708 end function xmlf_opentag_len 1709#endif 1710 1711 function xmlf_opentag(xf) result(fn) 1712 type (xmlf_t), intent(in) :: xf 1713#ifdef DUMMYLIB 1714 character(len=1) :: fn 1715 fn = " " 1716#else 1717 character(len=xmlf_opentag_len(xf)) :: fn 1718 1719 if (xf%lun == -1) then 1720 fn = '' 1721 elseif (is_empty(xf%stack)) then 1722 fn = '' 1723 else 1724 fn = get_top_elstack(xf%stack) 1725 endif 1726#endif 1727 end function xmlf_opentag 1728 1729#ifndef DUMMYLIB 1730 1731 subroutine check_xf(xf) 1732 type(xmlf_t), intent(inout) :: xf 1733 if (xf%lun == -1) & 1734 call wxml_fatal("Tried to manipulate an XML File which is not open") 1735 1736 end subroutine check_xf 1737 1738 1739 subroutine add_eol(xf) 1740 type(xmlf_t), intent(inout) :: xf 1741 1742 integer :: indent_level 1743 1744 ! In case we still have a zero-length stack, we must make 1745 ! sure indent_level is not less than zero. 1746 if (xf%state_3 == WXML_STATE_3_INSIDE_INTSUBSET) then 1747 indent_level = indent_inc 1748 else 1749 indent_level = xf%indent 1750 endif 1751 1752 !We must flush here (rather than just adding an eol character) 1753 !since we don't know what the eol character is on this system. 1754 !Flushing with a linefeed will get it automatically, though. 1755 call dump_buffer(xf%buffer, lf=.true.) 1756 call reset_buffer(xf%buffer, xf%lun, xf%xds%xml_version) 1757 1758 if (xf%pretty_print) & 1759 call add_to_buffer(repeat(' ',indent_level),xf%buffer, .false.) 1760 1761 end subroutine add_eol 1762 1763 1764 subroutine close_start_tag(xf) 1765 type(xmlf_t), intent(inout) :: xf 1766 1767 select case (xf%state_2) 1768 case (WXML_STATE_2_INSIDE_ELEMENT) 1769 if (xf%namespace) call checkNamespacesWriting(xf%dict, xf%nsDict, len(xf%stack)) 1770 if (getLength(xf%dict) > 0) call write_attributes(xf) 1771 if (xf%minimize_overrun) call add_eol(xf) 1772 call add_to_buffer('>', xf%buffer, .false.) 1773 xf%state_2 = WXML_STATE_2_OUTSIDE_TAG 1774 case (WXML_STATE_2_INSIDE_PI) 1775 if (getLength(xf%dict) > 0) call write_attributes(xf) 1776 call add_to_buffer('?>', xf%buffer, .false.) 1777 if (xf%pretty_print.and.xf%state_3/=WXML_STATE_3_INSIDE_INTSUBSET) call add_eol(xf) 1778 xf%state_2 = WXML_STATE_2_OUTSIDE_TAG 1779 case (WXML_STATE_2_IN_CHARDATA) 1780 continue 1781 case (WXML_STATE_2_OUTSIDE_TAG) 1782 continue 1783 end select 1784 1785 end subroutine close_start_tag 1786 1787 1788 subroutine write_attributes(xf) 1789 type(xmlf_t), intent(inout) :: xf 1790 1791 integer :: i, j, size 1792 1793 if (xf%state_2 /= WXML_STATE_2_INSIDE_PI .and. & 1794 xf%state_2 /= WXML_STATE_2_INSIDE_ELEMENT) & 1795 call wxml_fatal("Internal library error") 1796 1797 if (xf%canonical) call sortAttrs(xf%dict) 1798 1799 do i = 1, getLength(xf%dict) 1800 size = len(get_key(xf%dict, i)) + len(get_value(xf%dict, i)) + 4 1801 if (xf%minimize_overrun.and.(len(xf%buffer) + size) > COLUMNS) then 1802 call add_eol(xf) 1803 else 1804 call add_to_buffer(" ", xf%buffer, .false.) 1805 endif 1806 call add_to_buffer(get_key(xf%dict, i), xf%buffer, .false.) 1807 call add_to_buffer("=", xf%buffer, .false.) 1808 call add_to_buffer('"',xf%buffer, .false.) 1809 j = getWhiteSpaceHandling(xf%dict, i) 1810 if (j==0) then 1811 call add_to_buffer(get_value(xf%dict, i), xf%buffer, .true.) 1812 elseif (j==1) then 1813 call add_to_buffer(get_value(xf%dict, i), xf%buffer) 1814 else 1815 call add_to_buffer(get_value(xf%dict, i), xf%buffer, .false.) 1816 endif 1817 call add_to_buffer('"', xf%buffer, .false.) 1818 enddo 1819 1820 end subroutine write_attributes 1821 1822 subroutine wxml_warning_xf(xf, msg) 1823 ! Emit warning, but carry on. 1824 type(xmlf_t), intent(in) :: xf 1825 character(len=*), intent(in) :: msg 1826 1827 if (FoX_get_fatal_warnings()) then 1828 write(6,'(a)') 'FoX warning made fatal' 1829 call wxml_fatal_xf(xf, msg) 1830 endif 1831 1832 if (xf%xds%warning) then 1833 write(6,'(a)') 'WARNING(wxml) in writing to file ', xmlf_name(xf) 1834 write(6,'(a)') msg 1835 endif 1836 1837 end subroutine wxml_warning_xf 1838 1839 1840 subroutine wxml_error_xf(xf, msg) 1841 ! Emit error message, clean up file and stop. 1842 type(xmlf_t), intent(inout) :: xf 1843 character(len=*), intent(in) :: msg 1844 1845 if (FoX_get_fatal_errors()) then 1846 write(6,'(a)') 'FoX error made fatal' 1847 call wxml_fatal_xf(xf, msg) 1848 endif 1849 1850 write(6,'(a)') 'ERROR(wxml) in writing to file ', xmlf_name(xf) 1851 write(6,'(a)') msg 1852 1853 !call xml_Close(xf) 1854 stop 1855 1856 end subroutine wxml_error_xf 1857 1858 1859 subroutine wxml_fatal_xf(xf, msg) 1860 !Emit error message and abort with coredump. Does not try to 1861 !close file, so should be used from anything xml_Close might 1862 !itself call (to avoid infinite recursion!) 1863 1864 type(xmlf_t), intent(in) :: xf 1865 character(len=*), intent(in) :: msg 1866 1867 write(6,'(a)') 'ERROR(wxml) in writing to file ', xmlf_name(xf) 1868 write(6,'(a)') msg 1869 1870 call pxfabort() 1871 stop 1872 1873 end subroutine wxml_fatal_xf 1874 1875#endif 1876 1877end module m_wxml_core 1878