int xsd_equal(char *typ,char *val,char *s,int n) { if(!xsd_allows(typ,"",val,strlen(val))) { (*error_handler)(XSD_ER_VAL,val); return 0; } if(!xsd_allows(typ,"",s,n)) return 0; switch(s_tab(typ,typtab,NTYP)) { /*primitive*/ case TYP_STRING: return s_cmpn(val,s,n)==0; case TYP_BOOLEAN: return (s_tokcmpn("true",val,strlen(val))==0||s_tokcmpn("1",val,strlen(val))==0)==(s_tokcmpn("true",s,n)==0||s_tokcmpn("1",s,n)==0); case TYP_DECIMAL: return deccmp(val,strlen(val),s,n)==0; case TYP_FLOAT: case TYP_DOUBLE: return dblcmpn(val,s,n)==0; case TYP_DURATION: return duracmp(val,s,n)==0; case TYP_DATE_TIME: return dtcmpn(val,s,n,"ymdtz")==0; case TYP_DATE: return dtcmpn(val,s,n,"ymdz")==0; case TYP_TIME: return dtcmpn(val,s,n,"tz")==0; case TYP_G_YEAR_MONTH: return dtcmpn(val,s,n,"ymz")==0; case TYP_G_YEAR: return dtcmpn(val,s,n,"yz")==0; case TYP_G_MONTH_DAY: return dtcmpn(val,s,n,"mdz")==0; case TYP_G_DAY: return dtcmpn(val,s,n,"dz")==0; case TYP_G_MONTH: return dtcmpn(val,s,n,"mz")==0; case TYP_HEX_BINARY: return hexcmpn(val,s,n)==0; case TYP_BASE64_BINARY: return b64cmpn(val,s,n)==0; case TYP_ANY_URI: return s_tokcmpn(val,s,n)==0; case TYP_QNAME: case TYP_NOTATION: return qncmpn(val,s,n)==0; /*derived*/ case TYP_NORMALIZED_STRING: return nrmcmpn(val,s,n)==0; case TYP_TOKEN: case TYP_LANGUAGE: case TYP_NMTOKEN: case TYP_NMTOKENS: case TYP_NAME: case TYP_NCNAME: case TYP_ID: case TYP_IDREF: case TYP_IDREFS: case TYP_ENTITY: case TYP_ENTITIES: return s_tokcmpn(val,s,n)==0; case TYP_INTEGER: case TYP_POSITIVE_INTEGER: case TYP_NON_NEGATIVE_INTEGER: case TYP_NON_POSITIVE_INTEGER: case TYP_NEGATIVE_INTEGER: case TYP_BYTE: case TYP_UNSIGNED_BYTE: case TYP_SHORT: case TYP_UNSIGNED_SHORT: case TYP_INT: case TYP_UNSIGNED_INT: case TYP_LONG: case TYP_UNSIGNED_LONG: return deccmp(val,strlen(val),s,n)==0; case NTYP: (*error_handler)(XSD_ER_TYP,typ); return 0; default: assert(0); } return 0; }
static void advance(struct rnc_source *sp) { sp->cur=!sp->cur; for(;;) { NXT(sp).line=sp->line; NXT(sp).col=sp->col; if(newline(sp->v)||whitespace(sp->v)) {getv(sp); continue;} switch(sp->v) { case -1: NXT(sp).sym=SYM_EOF; return; case '#': getv(sp); if(sp->v=='#') { int i=0; for(;;) { do getv(sp); while(sp->v=='#'); if(whitespace(sp->v)) getv(sp); for(;;) { if(i+U_MAXLEN>NXT(sp).slen) realloc_s(&NXT(sp),2*(i+U_MAXLEN)); if(newline(sp->v)) { do getv(sp); while(whitespace(sp->v)); if(sp->v=='#') {getv(sp); if(sp->v=='#') {NXT(sp).s[i++]='\n'; break;} skip_comment(sp); } NXT(sp).s[i]=0; NXT(sp).sym=SYM_DOCUMENTATION; return; } else i+=u_put(NXT(sp).s+i,sp->v); getv(sp); } } } else {skip_comment(sp); continue;} case '=': getv(sp); NXT(sp).sym=SYM_ASGN; return; case ',': getv(sp); NXT(sp).sym=SYM_GROUP; return; case '|': getv(sp); if(sp->v=='=') { getv(sp); NXT(sp).sym=SYM_ASGN_CHOICE; return; } NXT(sp).sym=SYM_CHOICE; return; case '&': getv(sp); if(sp->v=='=') {getv(sp); NXT(sp).sym=SYM_ASGN_ILEAVE;} else NXT(sp).sym=SYM_ILEAVE; return; case '?': getv(sp); NXT(sp).sym=SYM_OPTIONAL; return; case '*': getv(sp); NXT(sp).sym=SYM_ZERO_OR_MORE; return; /* SYM_ANY_NAME */ case '+': getv(sp); NXT(sp).sym=SYM_ONE_OR_MORE; return; case '-': getv(sp); NXT(sp).sym=SYM_EXCEPT; return; case '~': getv(sp); NXT(sp).sym=SYM_CONCAT; return; case '(': getv(sp); NXT(sp).sym=SYM_LPAR; return; case ')': getv(sp); NXT(sp).sym=SYM_RPAR; return; case '{': getv(sp); NXT(sp).sym=SYM_LCUR; return; case '}': getv(sp); NXT(sp).sym=SYM_RCUR; return; case '[': getv(sp); NXT(sp).sym=SYM_LSQU; return; case ']': getv(sp); NXT(sp).sym=SYM_RSQU; return; case '>': getv(sp); if(sp->v!='>') error(0,sp,RNC_ER_LEXP,sp->fn,sp->line,sp->col,'>'); getv(sp); NXT(sp).sym=SYM_FOLLOW_ANNOTATION; return; case '"': case '\'': { int q=sp->v; int triple=0; int i=0; getv(sp); if(sp->v==q) {getv(sp); if(sp->v==q) { /* triply quoted string */ triple=1; getv(sp); } else { NXT(sp).s[0]='\0'; NXT(sp).sym=SYM_LITERAL; return; } } for(;;) { if(sp->v==q) { if(triple) { if(i>=2 && NXT(sp).s[i-2]==q && NXT(sp).s[i-1]==q) { NXT(sp).s[i-2]='\0'; break; } else i+=u_put(NXT(sp).s+i,sp->v); } else {NXT(sp).s[i]='\0'; break;} } else if(sp->v<=0) { if(sp->v==-1 || !triple) { error(0,sp,RNC_ER_LLIT,sp->fn,sp->line,sp->col); NXT(sp).s[i]='\0'; break; } else NXT(sp).s[i++]='\n'; } else i+=u_put(NXT(sp).s+i,sp->v); getv(sp); if(i+U_MAXLEN>NXT(sp).slen) realloc_s(&NXT(sp),2*(i+U_MAXLEN)); } getv(sp); NXT(sp).sym=SYM_LITERAL; return; } default: { int escaped=0,prefixed=0; if(sp->v=='\\') {escaped=1; getv(sp);} if(name_start(sp->v)) { int i=0; for(;;) { i+=u_put(NXT(sp).s+i,sp->v); if(i+U_MAXLEN>NXT(sp).slen) realloc_s(&NXT(sp),2*(i+U_MAXLEN)); getv(sp); if(!name_char(sp->v)) {NXT(sp).s[i]='\0'; break;} if(sp->v==':') prefixed=1; } if(!(escaped||prefixed)) { int kwd; if((kwd=s_tab(NXT(sp).s,kwdtab,NKWD))!=NKWD) { NXT(sp).sym=kwd; return; } } if(prefixed) { if(NXT(sp).s[i-1]==':'&&sp->v=='*') { getv(sp); NXT(sp).s[i-1]='\0'; NXT(sp).sym=SYM_NSNAME; } else NXT(sp).sym=SYM_QNAME; } else NXT(sp).sym=SYM_IDENT; return; } else { error(0,sp,RNC_ER_LILL,sp->fn,sp->line,sp->col,sp->v); getv(sp); continue; } } } } }
int xsd_allows(char *typ,char *ps,char *s,int n) { int ok=1,length; int dt=s_tab(typ,typtab,NTYP); struct facets fct = { 0, {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}, 0, 0,0,0,0,0, 0,0,0,0, 0}; fct.set=0; fct.npat=0; switch(dt) { case TYP_INTEGER: fct.pattern[fct.npat++]=PAT_INTEGER; dt=TYP_DECIMAL; break; case TYP_POSITIVE_INTEGER: fct.pattern[fct.npat++]=PAT_POSITIVE; dt=TYP_DECIMAL; fct.set|=1<<FCT_MIN_INCLUSIVE; fct.minInclusive="1"; break; case TYP_NON_NEGATIVE_INTEGER: fct.pattern[fct.npat++]=PAT_NON_NEGATIVE; dt=TYP_DECIMAL; fct.set|=1<<FCT_MIN_INCLUSIVE; fct.minInclusive="0"; break; case TYP_NON_POSITIVE_INTEGER: fct.pattern[fct.npat++]=PAT_NON_POSITIVE; dt=TYP_DECIMAL; fct.set|=1<<FCT_MAX_INCLUSIVE; fct.maxInclusive="0"; break; case TYP_NEGATIVE_INTEGER: fct.pattern[fct.npat++]=PAT_NEGATIVE; dt=TYP_DECIMAL; fct.set|=1<<FCT_MAX_INCLUSIVE; fct.maxInclusive="-1"; break; case TYP_BYTE: fct.pattern[fct.npat++]=PAT_INTEGER; dt=TYP_DECIMAL; fct.set|=FCT_IBOUNDS; fct.minInclusive="-128"; fct.maxInclusive="127"; break; case TYP_UNSIGNED_BYTE: fct.pattern[fct.npat++]=PAT_NON_NEGATIVE; dt=TYP_DECIMAL; fct.set|=FCT_IBOUNDS; fct.minInclusive="0"; fct.maxInclusive="255"; break; case TYP_SHORT: fct.pattern[fct.npat++]=PAT_INTEGER; dt=TYP_DECIMAL; fct.set|=FCT_IBOUNDS; fct.minInclusive="-32768"; fct.maxInclusive="32767"; break; case TYP_UNSIGNED_SHORT: fct.pattern[fct.npat++]=PAT_NON_NEGATIVE; dt=TYP_DECIMAL; fct.set|=FCT_IBOUNDS; fct.minInclusive="0"; fct.maxInclusive="65535"; break; case TYP_INT: fct.pattern[fct.npat++]=PAT_INTEGER; dt=TYP_DECIMAL; fct.set|=FCT_IBOUNDS; fct.minInclusive="-2147483648"; fct.maxInclusive="2147483647"; break; case TYP_UNSIGNED_INT: fct.pattern[fct.npat++]=PAT_NON_NEGATIVE; dt=TYP_DECIMAL; fct.set|=FCT_IBOUNDS; fct.minInclusive="0"; fct.maxInclusive="4294967295"; break; case TYP_LONG: fct.pattern[fct.npat++]=PAT_INTEGER; dt=TYP_DECIMAL; fct.set|=FCT_IBOUNDS; fct.minInclusive="-9223372036854775808"; fct.maxInclusive="9223372036854775807"; break; case TYP_UNSIGNED_LONG: fct.pattern[fct.npat++]=PAT_NON_NEGATIVE; dt=TYP_DECIMAL; fct.set|=FCT_IBOUNDS; fct.minInclusive="0"; fct.maxInclusive="18446744073709551615"; break; } { int n; while((n=strlen(ps))) { char *key=ps,*val=key+n+1,*end,i; switch(i=s_tab(key,fcttab,NFCT)) { case FCT_LENGTH: fct.length=(int)strtol(val,&end,10); if(!*val||*end) (*error_handler)(XSD_ER_PARVAL,key,val); break; case FCT_MAX_LENGTH: fct.maxLength=(int)strtol(val,&end,10); if(!*val||*end) (*error_handler)(XSD_ER_PARVAL,key,val); break; case FCT_MIN_LENGTH: fct.minLength=(int)strtol(val,&end,10); if(!*val||*end) (*error_handler)(XSD_ER_PARVAL,key,val); break; case FCT_FRACTION_DIGITS: fct.fractionDigits=(int)strtol(val,&end,10); if(!*val||*end) (*error_handler)(XSD_ER_PARVAL,key,val); break; case FCT_TOTAL_DIGITS: fct.totalDigits=(int)strtol(val,&end,10); if(!*val||*end) (*error_handler)(XSD_ER_PARVAL,key,val); break; case FCT_PATTERN: if(fct.npat==NPAT) (*error_handler)(XSD_ER_NPAT); else { fct.pattern[fct.npat++]=val; } break; case FCT_MAX_EXCLUSIVE: fct.maxExclusive=val; break; case FCT_MAX_INCLUSIVE: fct.maxInclusive=val; break; case FCT_MIN_EXCLUSIVE: fct.minExclusive=val; break; case FCT_MIN_INCLUSIVE: fct.minInclusive=val; break; case FCT_WHITE_SPACE: (*error_handler)(XSD_ER_WS); break; case FCT_ENUMERATION: (*error_handler)(XSD_ER_ENUM); break; case NFCT: (*error_handler)(XSD_ER_PAR,key); break; default: assert(0); } fct.set|=1<<i; ps=val+strlen(val)+1; } } fct.whiteSpace=WS_COLLAPSE; length=INT_MAX; switch(dt) { /*primitive*/ case TYP_STRING: fct.whiteSpace=WS_PRESERVE; length=u_strnlen(s,n); break; case TYP_BOOLEAN: fct.pattern[fct.npat++]="true|false|1|0"; break; case TYP_DECIMAL: fct.pattern[fct.npat++]=PAT_FIXED; if(fct.set&(1<<FCT_FRACTION_DIGITS)) ok=ok&&fdiglenn(s,n)<=fct.fractionDigits; if(fct.set&(1<<FCT_TOTAL_DIGITS)) ok=ok&&diglenn(s,n)<=fct.totalDigits; if(fct.set&FCT_BOUNDS) ok=ok&chkdec(&fct,s,n); break; case TYP_FLOAT: case TYP_DOUBLE: /* float and double is the same type */ fct.pattern[fct.npat++]=PAT_FLOATING; if(fct.set&FCT_BOUNDS) ok=ok&chkdbl(&fct,s,n); break; case TYP_DURATION: fct.pattern[fct.npat++]=PAT_DURATION; break; case TYP_DATE_TIME: fct.pattern[fct.npat++]=PAT_DATE_TIME; if(fct.set&FCT_BOUNDS) ok=ok&chktm(typ,"ymdtz",&fct,s,n); break; case TYP_DATE: fct.pattern[fct.npat++]=PAT_DATE; if(fct.set&FCT_BOUNDS) ok=ok&chktm(typ,"ymdz",&fct,s,n); break; case TYP_TIME: fct.pattern[fct.npat++]=PAT_TIME; if(fct.set&FCT_BOUNDS) ok=ok&chktm(typ,"tz",&fct,s,n); break; case TYP_G_YEAR_MONTH: fct.pattern[fct.npat++]=PAT_YEAR_MONTH; if(fct.set&FCT_BOUNDS) ok=ok&chktm(typ,"ymz",&fct,s,n); break; case TYP_G_YEAR: fct.pattern[fct.npat++]=PAT_YEAR; if(fct.set&FCT_BOUNDS) ok=ok&chktm(typ,"yz",&fct,s,n); break; case TYP_G_MONTH_DAY: fct.pattern[fct.npat++]=PAT_MONTH_DAY; if(fct.set&FCT_BOUNDS) ok=ok&chktm(typ,"mdz",&fct,s,n); break; case TYP_G_DAY: fct.pattern[fct.npat++]=PAT_DAY; if(fct.set&FCT_BOUNDS) ok=ok&chktm(typ,"dz",&fct,s,n); break; case TYP_G_MONTH: fct.pattern[fct.npat++]=PAT_MONTH; if(fct.set&FCT_BOUNDS) ok=ok&chktm(typ,"mz",&fct,s,n); break; case TYP_HEX_BINARY: fct.pattern[fct.npat++]=PAT_HEX_BINARY; length=(toklenn(s,n)+1)/2; break; case TYP_BASE64_BINARY: fct.pattern[fct.npat++]=PAT_BASE64_BINARY; length=b64lenn(s,n); break; case TYP_ANY_URI: fct.pattern[fct.npat++]=PAT_ANY_URI; length=toklenn(s,n); break; case TYP_QNAME: case TYP_NOTATION: fct.pattern[fct.npat++]=PAT_QNAME; fct.set&=~(1<<FCT_LENGTH|1<<FCT_MIN_LENGTH|1<<FCT_MAX_LENGTH); /* the errata states that any value is valid */ break; /*derived*/ case TYP_NORMALIZED_STRING: fct.whiteSpace=WS_REPLACE; length=u_strnlen(s,n); break; case TYP_TOKEN: length=toklenn(s,n); break; case TYP_LANGUAGE: fct.pattern[fct.npat++]=PAT_LANGUAGE; length=toklenn(s,n); break; case TYP_NMTOKEN: fct.pattern[fct.npat++]=PAT_NMTOKEN; length=toklenn(s,n); break; case TYP_NMTOKENS: fct.pattern[fct.npat++]=PAT_NMTOKENS; length=tokcntn(s,n); break; case TYP_NAME: fct.pattern[fct.npat++]=PAT_NAME; length=toklenn(s,n); break; case TYP_NCNAME: fct.pattern[fct.npat++]=PAT_NCNAME; length=toklenn(s,n); break; case TYP_ID: fct.pattern[fct.npat++]=PAT_NCNAME; length=toklenn(s,n); break; case TYP_IDREF: fct.pattern[fct.npat++]=PAT_NCNAME; length=toklenn(s,n); break; case TYP_IDREFS: fct.pattern[fct.npat++]=PAT_NCNAMES; length=tokcntn(s,n); break; case TYP_ENTITY: fct.pattern[fct.npat++]=PAT_NCNAME; length=toklenn(s,n); break; case TYP_ENTITIES: fct.pattern[fct.npat++]=PAT_NCNAMES; length=tokcntn(s,n); break; case NTYP: (*error_handler)(XSD_ER_TYP,typ); break; default: assert(0); } while(fct.npat--) ok=ok&&match[fct.whiteSpace](fct.pattern[fct.npat],s,n); if(fct.set&(1<<FCT_LENGTH)) ok=ok&&length==fct.length; if(fct.set&(1<<FCT_MAX_LENGTH)) ok=ok&&length<=fct.maxLength; if(fct.set&(1<<FCT_MIN_LENGTH)) ok=ok&&length>=fct.minLength; return ok; }