LCOV - code coverage report
Current view: top level - zxid - zxns.c (source / functions) Hit Total Coverage
Test: ZXID Code Coverage Lines: 207 226 91.6 %
Date: 2010-12-19 Functions: 16 16 100.0 %
Branches: 134 205 65.4 %

           Branch data     Line data    Source code
       1                 :            : /* zxns.c  -  Namespace manipulation functions for generated (and other) code
       2                 :            :  * Copyright (c) 2010 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
       3                 :            :  * Copyright (c) 2006-2008 Symlabs (symlabs@symlabs.com), All Rights Reserved.
       4                 :            :  * Author: Sampo Kellomaki (sampo@iki.fi)
       5                 :            :  * This is confidential unpublished proprietary source code of the author.
       6                 :            :  * NO WARRANTY, not even implied warranties. Contains trade secrets.
       7                 :            :  * Distribution prohibited unless authorized in writing.
       8                 :            :  * Licensed under Apache License 2.0, see file COPYING.
       9                 :            :  * $Id: zxns.c,v 1.7 2009-08-22 13:56:34 sampo Exp $
      10                 :            :  *
      11                 :            :  * 28.5.2006, created --Sampo
      12                 :            :  * 8.8.2006,  moved lookup functions to generated code --Sampo
      13                 :            :  * 12.8.2006, added special scanning of xmlns to avoid backtracking elem recognition --Sampo
      14                 :            :  * 26.8.2006, significant Common Subexpression Elimination (CSE) --Sampo
      15                 :            :  * 30.9.2007, rework namespaces, esp. previously unknown namespaces  --Sampo
      16                 :            :  * 7.10.2008, added documentation --Sampo
      17                 :            :  * 27.10.2010, re-engineered namespace handling --Sampo
      18                 :            :  */
      19                 :            : 
      20                 :            : #include <string.h>
      21                 :            : 
      22                 :            : #include "errmac.h"
      23                 :            : #include "zx.h"
      24                 :            : #include "c/zx-data.h"
      25                 :            : #include "c/zx-ns.h"
      26                 :            : 
      27                 :            : /* ------------- All the manner namespace management ------------- */
      28                 :            : 
      29                 :            : #if 0
      30                 :            : /* Called by: */
      31                 :            : void zx_fix_any_elem_dec(struct zx_ctx* c, struct zx_elem_s* x, const char* nam, int namlen)
      32                 :            : {
      33                 :            :   char* p = memchr(nam, ':', namlen);
      34                 :            :   if (p) {
      35                 :            :     x->gg.g.ns = zx_locate_ns_by_prefix(c, p-nam, nam);
      36                 :            :     ++p;
      37                 :            :     namlen -= p-nam;
      38                 :            :     nam = p;
      39                 :            :   }
      40                 :            :   x->name = (char*)nam;
      41                 :            :   x->name_len = namlen;
      42                 :            : }
      43                 :            : 
      44                 :            : /*() Given known namespace, does the prefix refer to it, either natively or through an alias. */
      45                 :            : 
      46                 :            : /* Called by: */
      47                 :            : int zx_is_ns_prefix(struct zx_ns_s* ns, int len, const char* prefix)
      48                 :            : {
      49                 :            :   struct zx_ns_s* alias;
      50                 :            :   if (!ns)
      51                 :            :     return 0;
      52                 :            :   if (ns->prefix_len == len && (!len || !memcmp(ns->prefix, prefix, len)))
      53                 :            :     return 1;
      54                 :            :   for (alias = ns->n; alias; alias = alias->n)
      55                 :            :     if (alias->prefix_len == len && (!len || !memcmp(alias->prefix, prefix, len)))
      56                 :            :       return 1;
      57                 :            :   return 0;
      58                 :            : }
      59                 :            : #endif
      60                 :            : 
      61                 :            : /*() Debugging function. You can say in gdb: print zx_dump_ns_tab(c,0) */
      62                 :            : 
      63                 :            : /* Called by: */
      64                 :            : int zx_dump_ns_tab(struct zx_ctx* c, int flags)
      65                 :          2 : {
      66                 :            :   struct zx_ns_s* ns;
      67                 :            :   struct zx_ns_s* alias;
      68                 :          2 :   int n_ns = c->n_ns;
      69                 :          2 :   int n=0;
      70         [ -  + ]:          2 :   for (ns = c->ns_tab; n < n_ns; ++ns) {
      71                 :          0 :     printf("%3d NS  %8.*s %.*s\n", ++n, ns->prefix_len, ns->prefix, ns->url_len, ns->url);
      72         [ #  # ]:          0 :     for (alias = ns->n; alias; alias = alias->n)
      73                 :          0 :       printf("%3d   A %8.*s %.*s\n", ++n, alias->prefix_len, alias->prefix, alias->url_len, alias->url);
      74                 :            :   }
      75         [ -  + ]:          2 :   for (alias = c->unknown_ns; alias; alias = alias->n) {
      76                 :          0 :     printf("%3d UNK %8.*s %.*s\n", ++n, alias->prefix_len, alias->prefix, alias->url_len, alias->url);
      77                 :            :   }
      78                 :          2 :   return n;
      79                 :            : }
      80                 :            : 
      81                 :            : /* Profiling of 0.69 on 20101024 shows that 31% of the enc-dec time is spent here.
      82                 :            :  * Surprisingly, the namespace is never found! The only return that executes is 0.
      83                 :            :  * Input was t/azrq1.xml, where in our understanding all prefixes are known.
      84                 :            :  * After fixing a bug related to xmlns declarations being fed to here, the function
      85                 :            :  * was never called. Could we safely delete this? */
      86                 :            : 
      87                 :            : /* Called by:  zx_fix_any_elem_dec, zx_init_tok_tab, zx_prefix_seen_whine, zx_xmlns_decl */
      88                 :            : static struct zx_ns_s* zx_locate_ns_by_prefix(struct zx_ctx* c, int len, const char* prefix)
      89                 :      12359 : {
      90                 :            :   struct zx_ns_s* ns;
      91                 :            :   struct zx_ns_s* alias;
      92         [ +  + ]:      14008 :   for (ns = c->unknown_ns; ns; ns = ns->n)
      93   [ +  +  +  +  :       7720 :     if (ns->prefix_len == len && (!len || !memcmp(ns->prefix, prefix, len)))
                   +  + ]
      94                 :       6071 :       return ns;
      95         [ -  + ]:       6288 :   for (ns = c->ns_tab; ns->url_len; ++ns) {
      96   [ #  #  #  #  :          0 :     if (ns->prefix_len == len && (!len || !memcmp(ns->prefix, prefix, len)))
                   #  # ]
      97                 :          0 :       return ns;
      98         [ #  # ]:          0 :     for (alias = ns->n; alias; alias = alias->n)
      99   [ #  #  #  #  :          0 :       if (alias->prefix_len == len && (!len || !memcmp(alias->prefix, prefix, len)))
                   #  # ]
     100                 :          0 :         return ns;
     101                 :            :   }
     102                 :       6288 :   return 0;
     103                 :            : }
     104                 :            : 
     105                 :            : /* Profiling of 0.69 on 20101024 shows that 64% of the enc-dec time is spent here.
     106                 :            :  * Here the namespace is always found via return ns, but not before searching through
     107                 :            :  * oodles of aliases. After bug fix, this consumes 95% of the zxencdectest run time!
     108                 :            :  * After further bug fixing eliminating scanning (and accumulation) of aliases, the run time went
     109                 :            :  * down by two orders of magnitude. Final solution is the namespace hash lookup. */
     110                 :            : 
     111                 :            : /* Called by:  zx_xmlns_decl */
     112                 :            : static struct zx_ns_s* zx_locate_ns_by_url(struct zx_ctx* c, int len, const char* url)
     113                 :     722460 : {
     114                 :            :   struct zx_ns_s* ns;
     115         [ +  + ]:     987256 :   for (ns = c->unknown_ns; ns; ns = ns->n)
     116   [ +  +  +  -  :     293087 :     if (ns->url_len == len && (!len || !memcmp(ns->url, url, len)))
                   +  + ]
     117                 :      28291 :       return ns;
     118                 :     694169 :   return zx_url2ns(url, len);  /* lookup in perfect hash generated by xsd2sg and gperf */
     119                 :            : }
     120                 :            : 
     121                 :            : /* Called by:  zx_xmlns_decl */
     122                 :            : static struct zx_ns_s* zx_new_known_ns(struct zx_ctx* c, int prefix_len, const char* prefix, struct zx_ns_s* known_ns)
     123                 :     718370 : {
     124                 :     718370 :   struct zx_ns_s* ns = ZX_ZALLOC(c, struct zx_ns_s);
     125                 :     718370 :   ns->prefix_len = prefix_len;
     126                 :     718370 :   ns->prefix     = prefix;
     127                 :     718370 :   ns->url_len    = known_ns->url_len;
     128                 :     718370 :   ns->url        = known_ns->url;
     129                 :     718370 :   ns->master     = known_ns;
     130                 :     718370 :   return ns;
     131                 :            : }
     132                 :            : 
     133                 :            : /* Called by:  zx_prefix_seen_whine, zx_xmlns_decl */
     134                 :            : static struct zx_ns_s* zx_new_unknown_ns(struct zx_ctx* c, int prefix_len, const char* prefix, int url_len, const char* url)
     135                 :       6288 : {
     136                 :       6288 :   struct zx_ns_s* ns = ZX_ZALLOC(c, struct zx_ns_s);
     137                 :       6288 :   ns->prefix_len = prefix_len;
     138                 :       6288 :   ns->url_len = url_len;
     139                 :            :   /* Reallocating these is necessary for unknown namespaces */
     140                 :       6288 :   ns->prefix = ZX_ALLOC(c, prefix_len+1);
     141         [ +  + ]:       6288 :   if (prefix_len)
     142                 :       2142 :     memcpy((char*)ns->prefix, prefix, prefix_len);
     143                 :       6288 :   *((char*)ns->prefix+prefix_len) = 0;
     144                 :       6288 :   ns->url = ZX_ALLOC(c, url_len+1);
     145         [ +  - ]:       6288 :   if (url_len)
     146                 :       6288 :     memcpy((char*)ns->url, url, url_len);
     147                 :       6288 :   *((char*)ns->url+url_len) = 0;
     148                 :       6288 :   return ns;
     149                 :            : }
     150                 :            : 
     151                 :            : /*() Process XML namespace declaration, trying to match it by its declared namespace URI.
     152                 :            :  * Should this fail, we will attempt to match by customary (at least in our opinion)
     153                 :            :  * namespace prefixes. If duplicate namespaces are detected, they are handled as aliases. */
     154                 :            : 
     155                 :            : /* Called by:  zx_push_seen x2 */
     156                 :            : static struct zx_ns_s* zx_xmlns_decl(struct zx_ctx* c, int prefix_len, const char* prefix, int url_len, const char* url)
     157                 :     722460 : {
     158                 :            :   struct zx_ns_s* alias;
     159                 :            :   struct zx_ns_s* new_ns;
     160                 :            :   struct zx_ns_s* ns;
     161                 :            : 
     162                 :     722460 :   ns = zx_locate_ns_by_url(c, url_len, url);
     163         [ +  + ]:     722460 :   if (!ns) {
     164   [ +  +  -  + ]:       4090 :     D("Namespace(%.*s) not found by URL(%.*s) (probably unknown or wrong namespace URL)", prefix_len, prefix, url_len, url);
     165                 :       4090 :     zx_xml_parse_dbg(c, '-', __FUNCTION__, "Namespace here");
     166                 :       4090 :     ns = zx_locate_ns_by_prefix(c, prefix_len, prefix);
     167         [ +  - ]:       4090 :     if (!ns) {
     168                 :            :       /* Namespace not known by compiled in schemata. */
     169   [ +  +  -  + ]:       4090 :       D("Namespace not found by prefix(%.*s) or URL(%.*s) (probably unknown or wrong namespace URL)", prefix_len, prefix, url_len, url);
     170                 :       4090 :       new_ns = zx_new_unknown_ns(c, prefix_len, prefix, url_len, url);
     171                 :       4090 :       new_ns->n = c->unknown_ns;
     172                 :       4090 :       c->unknown_ns = new_ns;
     173                 :       4090 :       return new_ns;
     174                 :            :     }
     175                 :            :   }
     176                 :            :   /* Always alloc a new one because we may need to push to stack multiple instances of same ns. */
     177                 :     718370 :   new_ns = zx_new_known_ns(c, prefix_len, prefix, ns);
     178                 :            : 
     179                 :            :   /* Avoid adding to alias list if prefix is already known. */
     180   [ +  +  +  +  :     718370 :   if (ns->prefix_len == prefix_len && (!prefix_len || !memcmp(ns->prefix, prefix, prefix_len)))
                   +  + ]
     181                 :            :     goto known_prefix;
     182         [ -  + ]:       1752 :   for (alias = ns->n; alias; alias = alias->n)
     183   [ #  #  #  #  :          0 :     if (alias->prefix_len == prefix_len && (!prefix_len || !memcmp(alias->prefix, prefix, prefix_len)))
                   #  # ]
     184                 :            :       goto known_prefix;
     185                 :            :   
     186   [ +  +  -  + ]:       1752 :   D("New prefix(%.*s) known URL(%.*s)", prefix_len, prefix, url_len, url);
     187                 :       1752 :   ns->n = new_ns->n;
     188                 :       1752 :   new_ns->n = ns;
     189                 :     718370 : known_prefix:
     190                 :     718370 :   return new_ns;
     191                 :            : }
     192                 :            : 
     193                 :            : /*() Scan the seen list (expected to be relatively short so scan
     194                 :            :  * is not a perfomance issue). The scan walks the doubly linked
     195                 :            :  * list of currently active seen prefixes (as opposed to seen_pop). */
     196                 :            : 
     197                 :            : /* Called by:  zx_prefix_seen_whine, zx_push_seen, zxsig_validate */
     198                 :            : struct zx_ns_s* zx_prefix_seen(struct zx_ctx* c, int len, const char* prefix)
     199                 :    3116687 : {
     200                 :            :   struct zx_ns_s* ns;
     201   [ +  +  +  + ]:    3116687 :   if (len == 3 && !memcmp(prefix, "xml", 3))
     202                 :       1503 :       return zx_ns_tab + (zx_xml_NS >> ZX_TOK_NS_SHIFT);
     203         [ +  + ]:    5426537 :   for (ns = c->guard_seen_n.seen_n; ns->seen_n; ns = ns->seen_n)
     204   [ +  +  +  +  :    4695810 :     if (ns->prefix_len == len && (!len || !memcmp(ns->prefix, prefix, len)))
                   +  + ]
     205                 :    2384457 :       return ns;
     206                 :     730727 :   return 0;
     207                 :            : }
     208                 :            : 
     209                 :            : #define zx_unknown_prefix "urn:zxid:unknown-ns-prefix"
     210                 :            : 
     211                 :            : /*() zx_prefix_seen_whine() is a good place to detect, and add stub for,
     212                 :            :  * wholly unknown prefixes. Seldom returns NULL, just always makes something up. */
     213                 :            : 
     214                 :            : /* Called by:  zx_attr_lookup, zx_el_lookup */
     215                 :            : struct zx_ns_s* zx_prefix_seen_whine(struct zx_ctx* c, int len, const char* prefix, const char* logkey, int mk_dummy_ns)
     216                 :     839465 : {
     217                 :            :   struct zx_str* url;
     218                 :     839465 :   struct zx_ns_s* ns = zx_prefix_seen(c, len, prefix);
     219         [ +  + ]:     839465 :   if (!ns) {
     220                 :            :     /* Try to locate the namespace by the prefix from among the namespaces
     221                 :            :      * naturally known to zxid. */
     222                 :       8269 :     ns = zx_locate_ns_by_prefix(c, len, prefix);
     223         [ +  + ]:       8269 :     if (!ns) {
     224         [ +  - ]:       2198 :       if (mk_dummy_ns) {
     225         [ +  + ]:       2198 :         url = zx_strf(c, "%s:%s:%.*s", zx_unknown_prefix, logkey, len, STRNULLCHK(prefix));
     226                 :       2198 :         ns = zx_new_unknown_ns(c, len, prefix, url->len, url->s);
     227                 :       2198 :         ns->n = c->unknown_ns;
     228                 :       2198 :         c->unknown_ns = ns;
     229   [ +  +  -  + ]:       2198 :         D("Undefined namespace prefix(%.*s). NS not known from any context. Creating dummy ns(%.*s).", len, prefix, url->len, url->s);
     230                 :       2198 :         ZX_FREE(c, url);
     231                 :            :       } else {
     232   [ #  #  #  # ]:          0 :         D("Undefined namespace prefix(%.*s) at(%s). NS not known from any context.", len, prefix, logkey);
     233                 :          0 :         return 0;
     234                 :            :       }
     235                 :            :     } else {
     236   [ -  +  #  # ]:       6071 :       if (len != 3 || memcmp(prefix, "xml", 3)) {
     237   [ +  +  -  + ]:       6071 :         D("Undefined namespace prefix(%.*s) at(%s) mapped to uri(%.*s) by built-in table.", len, prefix, logkey, ns->url_len, ns->url);
     238                 :            :       }
     239                 :            :     }
     240                 :            :   }
     241                 :     839465 :   return ns;
     242                 :            : }
     243                 :            : 
     244                 :            : /*() See if prefix has been seen, and in the same meaning. If not, allocate
     245                 :            :  * a new node and push or add it to the doubly linked list as well as to the
     246                 :            :  * pop_seen list. Returns 0 if no addition was done (i.e. ns had been seen already). */
     247                 :            : 
     248                 :            : /* Called by:  zx_add_xmlns_if_not_seen, zx_len_xmlns_if_not_seen, zx_scan_xmlns */
     249                 :            : static struct zx_ns_s* zx_push_seen(struct zx_ctx* c, int prefix_len, const char* prefix, int url_len, const char* url, struct zx_ns_s** pop_seen)
     250                 :    2277221 : {
     251                 :            :   struct zx_ns_s* old_ns;
     252                 :            :   struct zx_ns_s* ns;
     253                 :    2277221 :   old_ns = zx_prefix_seen(c, prefix_len, prefix);
     254         [ +  + ]:    2277221 :   if (old_ns) {
     255   [ +  +  +  -  :    1554763 :     if (old_ns->url_len == url_len && (!url_len || !memcmp(old_ns->url, url, url_len)))
                   +  - ]
     256                 :    1554761 :       return 0;
     257                 :          2 :     ns = zx_xmlns_decl(c, prefix_len, prefix, url_len, url);
     258                 :          2 :     ns->seen = old_ns;            /* Push */
     259                 :          2 :     ns->seen_n = old_ns->seen_n;  /* Replace old_ns in middle of the list */
     260                 :          2 :     ns->seen_p = old_ns->seen_p;
     261                 :          2 :     old_ns->seen_n->seen_p = ns;
     262                 :          2 :     old_ns->seen_p->seen_n = ns;
     263                 :            :   } else {
     264                 :     722458 :     ns = zx_xmlns_decl(c, prefix_len, prefix, url_len, url);
     265                 :     722458 :     ns->seen_n = c->guard_seen_n.seen_n;  /* Add to beginning of seen_n list. */
     266                 :     722458 :     c->guard_seen_n.seen_n = ns;
     267                 :     722458 :     ns->seen_n->seen_p = ns;
     268                 :     722458 :     ns->seen_p = &c->guard_seen_n;
     269                 :            :   }
     270                 :     722460 :   ns->seen_pop = *pop_seen;
     271                 :     722460 :   *pop_seen = ns;
     272                 :     722460 :   return ns;
     273                 :            : }
     274                 :            : 
     275                 :            : /* Called by:  TXENC_SO_ELNAME, TXLEN_SO_ELNAME, zx_DEC_elem, zx_ENC_WO_any_elem, zx_LEN_WO_any_elem, zxsig_validate */
     276                 :            : void zx_pop_seen(struct zx_ns_s* ns)
     277                 :    2837107 : {
     278         [ +  + ]:    3559715 :   for (; ns; ns = ns->seen_pop) {
     279         [ +  + ]:     722608 :     if (ns->seen) {
     280                 :          2 :       ns->seen->seen_n = ns->seen_n;   /* Replace ns with old_ns (ns->seen) in middle of list */
     281                 :          2 :       ns->seen->seen_p = ns->seen_p;
     282                 :          2 :       ns->seen_n->seen_p = ns->seen;
     283                 :          2 :       ns->seen_p->seen_n = ns->seen;
     284                 :            :     } else {
     285                 :     722606 :       ns->seen_n->seen_p = ns->seen_p; /* Remove ns from middle of the seen_n list. */
     286                 :     722606 :       ns->seen_p->seen_n = ns->seen_n;
     287                 :            :     }
     288                 :            :   }
     289                 :    2837107 : }
     290                 :            : 
     291                 :            : /*() Collect namespaces from element */
     292                 :            : 
     293                 :            : /* Called by:  sig_validate x3, zxid_chk_sig, zxid_sp_dig_sso_a7n, zxid_sp_sso_finalize */
     294                 :            : void zx_see_elem_ns(struct zx_ctx* c, struct zx_ns_s** pop_seen, struct zx_elem_s* el)
     295                 :        145 : {
     296                 :            :   struct zx_ns_s* ns;
     297         [ +  + ]:        293 :   for (ns = el->xmlns; ns; ns = ns->n) {
     298                 :            :     /*zx_push_seen(c, xmlns->);*/
     299                 :        148 :     ns->seen_n = c->guard_seen_n.seen_n;  /* Add to beginning of seen_n list. */
     300                 :        148 :     c->guard_seen_n.seen_n = ns;
     301                 :        148 :     ns->seen_n->seen_p = ns;
     302                 :        148 :     ns->seen_p = &c->guard_seen_n;
     303                 :        148 :     ns->seen_pop = *pop_seen;
     304                 :        148 :     *pop_seen = ns;
     305                 :            :   }
     306                 :        145 : }
     307                 :            : 
     308                 :            : /*() When trying to scan an element, an annoying feature of XML namespaces is that the
     309                 :            :  * namespace may be declared in a xmlns attribute within the element itself. Thus
     310                 :            :  * at the time of scanning the <ns:element part we can't know its namespace. What
     311                 :            :  * a lousy design. In order to handle this we need to either backtrack or
     312                 :            :  * make a special case forward scan for xmlns attributes (which is redundant with
     313                 :            :  * normal attribute scanning). It seems simpler to do the latter, so here goes...
     314                 :            :  * (besides, the forward scan will prime the cache)
     315                 :            :  *
     316                 :            :  * The return value represents the list of namespaces that were newly declared
     317                 :            :  * at this level, i.e. pushed to the seen stacks. This list is used to pop the
     318                 :            :  * seen stacks after we are through with the element. */
     319                 :            : 
     320                 :            : /* Called by:  zx_el_lookup */
     321                 :            : struct zx_ns_s* zx_scan_xmlns(struct zx_ctx* c)
     322                 :     730174 : {
     323                 :     730174 :   struct zx_ns_s* pop_seen = 0;  /* build a list of namespaces declared here */
     324                 :            :   const char* prefix;
     325                 :            :   const char* url;
     326                 :     730174 :   const char* p = c->p;  /* We need to keep the original c->p so normal attrs can be scanned. */
     327                 :            :   char quote;
     328                 :            :   int prefix_len, url_len;
     329                 :            : 
     330                 :            :   /* The tag name has already been detected. Process attributes until '>' */
     331                 :            :   
     332                 :     717120 :   for ( ; 1; ++p) {
     333         [ -  + ]:    1447294 :     ZX_SKIP_WS_P(c, p, pop_seen);
     334   [ +  +  +  + ]:    1447294 :     if (ONE_OF_2(*p, '>', '/'))
     335                 :            :       break;
     336         [ +  + ]:     717120 :     if (!memcmp(p, "xmlns", sizeof("xmlns")-1)) {
     337      [ +  +  - ]:     219503 :       switch (p[5]) {
     338                 :            :       case '=':  /* Default namespace decl. */
     339                 :       2017 :         prefix = p += 5;
     340                 :       2017 :         goto scan_URL;
     341                 :            :       case ':':  /* Qualified namespace decl. */
     342                 :     217486 :         prefix = p += 6;
     343                 :     217486 :         quote = '=';
     344         [ +  - ]:     217486 :         ZX_LOOK_FOR_P(c,'=',p);
     345                 :     219503 :       scan_URL:
     346                 :     219503 :         ++p;
     347   [ +  +  -  + ]:     219503 :         if (!ONE_OF_2(*p, '"', '\''))
     348                 :          0 :           return pop_seen;
     349                 :     219503 :         quote = *p;
     350                 :     219503 :         url = ++p;
     351         [ +  - ]:     219503 :         ZX_LOOK_FOR_P(c, quote, p);
     352                 :            : 
     353                 :     219503 :         prefix_len = (url - 2) - prefix;
     354                 :     219503 :         url_len = p - url;
     355                 :     219503 :         zx_push_seen(c, prefix_len, prefix, url_len, url, &pop_seen);
     356                 :     219503 :         goto next;
     357                 :            :       default:
     358                 :          0 :         zx_xml_parse_err(c, p[5], (const char*)__FUNCTION__, "Illformed attributes. Bad char");
     359                 :          0 :         return pop_seen;
     360                 :            :       }
     361                 :            :     }
     362                 :            :     
     363                 :            :     /* Skip over any other attributes. */
     364                 :            :     
     365                 :     497617 :     quote = '=';
     366         [ +  - ]:     497617 :     ZX_LOOK_FOR_P(c,'=',p);
     367                 :     497617 :     ++p;
     368   [ -  +  #  # ]:     497617 :     if (!ONE_OF_2(*p, '"', '\''))
     369                 :          0 :       return pop_seen;
     370                 :     497617 :     quote = *p;
     371                 :     497617 :     ++p;
     372         [ +  - ]:     497617 :     ZX_LOOK_FOR_P(c,quote,p);
     373                 :     717120 :   next:
     374                 :            :     continue;
     375                 :     717120 :   }
     376                 :     730174 :   return pop_seen;
     377                 :            : 
     378                 :          0 :  look_for_not_found:
     379                 :          0 :   zx_xml_parse_err(c, quote, (const char*)__FUNCTION__, "char not found");
     380                 :          0 :   return pop_seen;
     381                 :            : }
     382                 :            : 
     383                 :            : #if 0  /* *** schedule to remove */
     384                 :            : /*() Disambiguate token by considering its namespace.
     385                 :            :  * See zx_attr_lookup(), zx_elem_lookup()
     386                 :            :  * For attributes the namespaceless case is considered. */
     387                 :            : 
     388                 :            : /* Called by: */
     389                 :            : const struct zx_tok* zx_tok_by_ns(const struct zx_tok* zt, const struct zx_tok* lim, int len, const char* name, struct zx_ns_s* ns)
     390                 :            : {
     391                 :            :   struct zx_ns_s* alias;
     392                 :            :   const struct zx_tok* ztt;
     393                 :            : 
     394                 :            :   /* First find token whose name matches. The token table CAN have duplicate entries,
     395                 :            :    * see -D flag to gperf. */
     396                 :            :   for (; zt < lim && (memcmp(zt->name, name, len) || zt->name[len]); ++zt) ;
     397                 :            :   if (zt >= lim)
     398                 :            :     return 0;  /* Not found! */
     399                 :            :   ztt = zt;  /* Remember first "hit" in case we fail. */
     400                 :            : 
     401                 :            :   /* If no namespace was specified, then token must also be namespaceless */
     402                 :            :   if (!ns) {
     403                 :            :     if (!zt->ns)
     404                 :            :       return zt;
     405                 :            :     for (; zt < lim && (!memcmp(zt->name, name, len) && !zt->name[len]); ++zt)
     406                 :            :       if (!zt->ns)
     407                 :            :         return zt;
     408                 :            :     return ztt;
     409                 :            :   }
     410                 :            :   /* Now check for namespace match. */
     411                 :            :   for (; zt < lim && (!memcmp(zt->name, name, len) && !zt->name[len]); ++zt)
     412                 :            :     for (alias = zt->ns; alias; alias = alias->n)
     413                 :            :       if (alias == ns)
     414                 :            :         return zt;
     415                 :            :   return ztt;
     416                 :            : }
     417                 :            : #endif
     418                 :            : 
     419                 :            : #if 0
     420                 :            : /*(-) N.B. Generally this function is not needed since tokens can be arranged
     421                 :            :  * to point to respective struct zx_ns_s at compile time using static
     422                 :            :  * initialization. This is handled by xsd2sg.pl */
     423                 :            : 
     424                 :            : /* Called by: */
     425                 :            : int zx_init_tok_tab(struct zx_ctx* c, struct zx_tok* tok_tab, struct zx_tok* tok_tab_lim)
     426                 :            : {
     427                 :            :   for (; tok_tab < tok_tab_lim; ++tok_tab)
     428                 :            :     if (!(tok_tab->ns = zx_locate_ns_by_prefix(c, strlen(tok_tab->prefix), (char*)tok_tab->prefix)))
     429                 :            :       return 0;
     430                 :            :   return 1;
     431                 :            : 
     432                 :            :   /*if (!zx_init_tok_tab(&ctx, zx_elems, zx_elems + sizeof(zx_elems) / sizeof(struct zx_tok)))  DIE("Inconsistency between tokens and namespaces");*/
     433                 :            : }
     434                 :            : #endif
     435                 :            : 
     436                 :            : /* Called by:  zx_LEN_WO_any_elem x2, zx_len_inc_ns */
     437                 :            : int zx_len_xmlns_if_not_seen(struct zx_ctx* c, struct zx_ns_s* ns, struct zx_ns_s** pop_seenp)
     438                 :    1511632 : {
     439         [ +  + ]:    1511632 :   if (!ns)
     440                 :     482773 :     return 0;
     441         [ +  + ]:    1028859 :   if (!zx_push_seen(c, ns->prefix_len, ns->prefix, ns->url_len, ns->url, pop_seenp))
     442                 :     776945 :     return 0;
     443                 :            :   /* Check for undeclared empty prefix, as seen in namespaceless XML */
     444   [ +  -  +  +  :     251914 :   if ((!ns->prefix || !*ns->prefix)
                   +  - ]
     445                 :            :       && !memcmp(ns->url, zx_unknown_prefix, sizeof(zx_unknown_prefix))-1)
     446                 :      11434 :     return 0;
     447         [ +  + ]:     240480 :   return sizeof(" xmlns")-1
     448                 :            :     + (ns->prefix_len ? ns->prefix_len+1 : 0) + 2 + ns->url_len + 1;
     449                 :            : }
     450                 :            : 
     451                 :            : /*() For WO encoder the order of xmlns declarations is not known at compile
     452                 :            :  * time. Thus we first add them to the pop_seen list using insertion
     453                 :            :  * sort (pop_seen is smallest and prefixes grow from there) and
     454                 :            :  * then later render the list using zx_enc_seen(). */
     455                 :            : 
     456                 :            : /* Called by:  zx_ENC_WO_any_elem, zx_add_inc_ns, zx_see_attr_ns */
     457                 :            : void zx_add_xmlns_if_not_seen(struct zx_ctx* c, struct zx_ns_s* ns, struct zx_ns_s** pop_seenp)
     458                 :    1511632 : {
     459                 :    1511632 :   struct zx_ns_s* pop_seen_dummy=0;
     460                 :            :   struct zx_ns_s* new_ns;
     461                 :            :   int res;
     462         [ +  + ]:    1511632 :   if (!ns)
     463                 :     482773 :     return;
     464                 :    1028859 :   new_ns = zx_push_seen(c, ns->prefix_len, ns->prefix, ns->url_len, ns->url, &pop_seen_dummy);
     465         [ +  + ]:    1028859 :   if (!new_ns)
     466                 :     776945 :     return;
     467         [ +  + ]:     251914 :   if (!*pop_seenp) {
     468                 :     213531 :     *pop_seenp = new_ns;
     469                 :     213531 :     return;
     470                 :            :   }
     471         [ -  + ]:      38383 :   if (!new_ns->prefix_len) {       /* Default namespace (empty prefix) sorts first. */
     472                 :        247 : first:
     473                 :        247 :     new_ns->seen_pop = *pop_seenp;
     474                 :        247 :     *pop_seenp = new_ns;
     475                 :        247 :     return;
     476                 :            :   }
     477                 :            : 
     478                 :      38383 :   ns = *pop_seenp;
     479         [ +  - ]:      38383 :   if (ns->prefix_len) {
     480                 :      38383 :     res = memcmp(ns->prefix, new_ns->prefix, MIN(ns->prefix_len, new_ns->prefix_len));
     481   [ +  +  -  +  :      38383 :     if (res > 0 || !res && ns->prefix_len >= new_ns->prefix_len)
                   #  # ]
     482                 :            :       goto first;
     483                 :            :   }
     484         [ +  + ]:      38136 :   for (; ns->seen_pop; ns = ns->seen_pop) {
     485                 :        943 :     res = memcmp(ns->seen_pop->prefix, new_ns->prefix,
     486                 :            :                  MIN(ns->seen_pop->prefix_len, new_ns->prefix_len));
     487   [ -  +  #  #  :        943 :     if (res > 0 || !res && ns->seen_pop->prefix_len >= new_ns->prefix_len)
                   #  # ]
     488                 :            :       break;
     489                 :            :   }
     490                 :      38136 :   new_ns->seen_pop = ns->seen_pop;
     491                 :      38136 :   ns->seen_pop = new_ns;
     492                 :            : }
     493                 :            : 
     494                 :            : /*() Render the namespaces that have been seen. The list is assumed to be already sorted. */
     495                 :            : 
     496                 :            : /* Called by:  TXENC_SO_ELNAME, zx_ENC_WO_any_elem x2 */
     497                 :            : char* zx_enc_seen(char* p, struct zx_ns_s* ns)
     498                 :     933745 : {
     499         [ +  + ]:    1185659 :   for (; ns; ns = ns->seen_pop) {
     500                 :            :     /* Check for undeclared empty prefix, as seen in namespaceless XML */
     501   [ +  -  +  +  :     251914 :     if ((!ns->prefix || !*ns->prefix)
                   +  - ]
     502                 :            :         && !memcmp(ns->url, zx_unknown_prefix, sizeof(zx_unknown_prefix))-1)
     503                 :      11434 :       continue;
     504                 :     240480 :     ZX_OUT_MEM(p, " xmlns", sizeof(" xmlns")-1);
     505         [ +  + ]:     240480 :     if (ns->prefix_len) {
     506                 :     240470 :       ZX_OUT_CH(p, ':');
     507                 :     240470 :       ZX_OUT_MEM(p, ns->prefix, ns->prefix_len);
     508                 :            :     }
     509                 :     240480 :     ZX_OUT_CH(p, '=');
     510                 :     240480 :     ZX_OUT_CH(p, '"');
     511                 :     240480 :     ZX_OUT_MEM(p, ns->url, ns->url_len);
     512                 :     240480 :     ZX_OUT_CH(p, '"');
     513                 :            :   }
     514                 :     933745 :   return p;
     515                 :            : }
     516                 :            : 
     517                 :            : /*() dec-templ.c CSE elimination. */
     518                 :            : 
     519                 :            : /* Called by:  zx_attr_lookup x2 */
     520                 :            : struct zx_ns_s* zx_xmlns_detected(struct zx_ctx* c, struct zx_elem_s* x, const char* url)
     521                 :     219503 : {
     522                 :            :   struct zx_ns_s* ns;
     523                 :            :   const char* prefix;
     524                 :            :   /* Scan backwards to find beginning of name. Already cached. Scan is cheaper than arg. */
     525   [ +  +  +  +  :     219503 :   for (prefix = url-2; !ONE_OF_5(*prefix, ':', ' ', '\n', '\r', '\t'); --prefix) ;
          +  -  +  -  +  
                      - ]
     526                 :     219503 :   ++prefix;
     527                 :            :   DD("xmlns detected(%.*s)", url-2-prefix, prefix);
     528                 :     219503 :   ns = ZX_ZALLOC(c, struct zx_ns_s);
     529                 :     219503 :   ns->url = url;
     530                 :     219503 :   ns->url_len = c->p - url;
     531                 :     219503 :   ns->prefix_len = url-2-prefix;
     532                 :     219503 :   ns->prefix = prefix;
     533                 :     219503 :   ns->n = x->xmlns;
     534                 :     219503 :   x->xmlns = ns;
     535                 :     219503 :   return ns;
     536                 :            : }
     537                 :            : 
     538                 :            : /* EOF -- zxns.c */

Generated by: LCOV version 1.9