int sc_add(struct sc_stack *stp,int key,int val,int aux) { int i=stp->top; assert(!sc_locked(stp)); stp->tab[i][0]=key; stp->tab[i][1]=val; stp->tab[i][2]=aux; if(++stp->top==stp->len) stp->tab=(int(*)[SC_RECSIZE])m_stretch( stp->tab,stp->len=stp->top*2,stp->top,sizeof(int[SC_RECSIZE])); return i; }
static void characters(void *userData,const char *s,int len) { if(current!=rn_notAllowed) { int newlen_txt=n_txt+len+1; if(newlen_txt<=LIM_T&&LIM_T<len_txt) newlen_txt=LIM_T; else if(newlen_txt<len_txt) newlen_txt=len_txt; if(len_txt!=newlen_txt) text=(char*)m_stretch(text,len_txt=newlen_txt,n_txt,sizeof(char)); memcpy(text+n_txt,s,len); n_txt+=len; text[n_txt]='\0'; /* '\0' guarantees that the text is bounded, and strto[ld] work for data */ } }
static int accept_p(void) { int j; if((j=ht_get(&ht_p,i_p))==-1) { ht_put(&ht_p,j=i_p); i_p+=p_size[P_TYP(i_p)]; if(i_p+P_SIZE>len_p) pattern=(int*)m_stretch(pattern,len_p=2*(i_p+P_SIZE),i_p,sizeof(int)); } return j; }
static int add_s(char *s) { int len=strlen(s)+1,j; if(i_s+len>len_s) string=(char*)m_stretch( string,len_s=2*(i_s+len),i_s,sizeof(char)); strcpy(string+i_s,s); if((j=ht_get(&ht_s,i_s))==-1) { ht_put(&ht_s,j=i_s); i_s+=len; } return j; }
static int query(void) { int i,j,n,dn, kwd, patno,prevno, ok=0; char *name; n=0; for(;;) { if(n==n_q) { if(len_q-n_q<LEN_B) quebuf=(char*)m_stretch(quebuf,len_q=n_q+LEN_B,n_q,sizeof(char)); dn=read(0,quebuf+n_q,LEN_B); if(dn<0) longjmp(IOER,1); if(dn==0) {errno=EIO; longjmp(IOER,1);} n_q+=dn; } if(quebuf[n++]=='\0') break; } j=endtok(i=tok(0)); if((kwd=s_ntab(quebuf+i,j-i,kwdtab,NKWD))==QUIT) {resp(1,0,0); return 0;} switch(kwd) { case START: j=endtok((i=tok(j))); patno=0; while(i!=j) patno=patno*10+quebuf[i++]-'0'; if(patno>=n_st) goto PROTER; ok=1; patno=starts[patno]; break; case STO: case ATT: case STC: case TXT: case MIX: case ENT: j=endtok((i=tok(j))); if(i==j) goto PROTER; patno=0; do patno=patno*10+quebuf[i++]-'0'; while(i!=j); if(patno==0) goto PROTER; /* 0 is ERROR, not allowed */ switch(kwd) { case STO: case ATT: case STC: case ENT: j=endtok((i=tok(j))); if(i==j||(kwd==ATT&&quebuf[j]=='\0')) goto PROTER; name=quebuf+i; quebuf[j]='\0'; switch(kwd) { case STO: ok=rnv_start_tag_open(&patno,&prevno,name); break; case ATT: ok=rnv_attribute(&patno,&prevno,name,quebuf+j+1); break; case STC: ok=rnv_start_tag_close(&patno,&prevno,name); break; case ENT: ok=rnv_end_tag(&patno,&prevno,name); break; } break; case TXT: case MIX: if(quebuf[j]) ++j; i=j; while(quebuf[j]) ++j; ok=rnv_text(&patno,&prevno,quebuf+i,j-i,kwd==MIX); break; } break; case NKWD: PROTER: (*er_printf)("protocol error\n"); lasterr=0; patno=0; ok=0; break; default: assert(0); } resp(ok,patno,prevno); i=0; while(n!=n_q) quebuf[i++]=quebuf[n++]; n_q=i; return 1; }
static int getid(void) { if(nmtoken(cc)) { int i=0; do { value[i++]=cc; if(i==len_v) value=(char*)m_stretch(value,len_v=2*i,i,sizeof(char)); getcc(); } while(nmtoken(cc)); value[i]='\0'; return 1; } else return 0; }
static void getq(void) { int cq=cc; int i=0; for(;;) { getcc(); if(cc==cq) { if(i!=0&&value[i-1]=='\\') --i; else {getcc(); break;} } else if(cc<' ') {error(ARX_ER_NOQ); break;} value[i++]=cc; if(i==len_v) value=(char*)m_stretch(value,len_v=2*i,i,sizeof(char)); } value[i]='\0'; }
static void getrng(void) { int ircur=-1,i=0; int cc0; for(;;) { cc0=cc; getcc(); if(cc=='}') ircur=i; else if(cc=='>') {if(cc0=='=') {getcc(); break;}} /* use => as terminator */ else if(cc==-1) {error(ARX_ER_EXP,"=>",sym2str(SYM_EOF)); break;} value[i++]=cc; if(i==len_v) value=(char*)m_stretch(value,len_v=2*i,i,sizeof(char)); } if(ircur==-1) {error(ARX_ER_EXP,sym2str(SYM_RCUR),sym2str(SYM_EOF)); ircur=0;} value[ircur]='\0'; }
static int compile(char *rx) { int r=0,p=0,d_r; d_r=add_r(rx); if((r=ht_get(&ht_r,i_r))==-1) { if(rx_compact&&i_p>=P_AVG_SIZE*LIM_P) {rx_clear(); d_r=add_r(rx);} ht_put(&ht_r,r=i_r); i_r+=d_r; bind(r); p=expression(); if(sym!=SYM_END) error(RX_ER_BADCH); r2p[i_2][0]=r; r2p[i_2][1]=p; ht_put(&ht_2,i_2++); if(i_2==len_2) r2p=(int(*)[2])m_stretch(r2p,len_2=2*i_2,i_2,sizeof(int[2])); } else { r2p[i_2][0]=r; p=r2p[ht_get(&ht_2,i_2)][1]; } return p; }
static void expected(int p,int first,int req) { int p1,p2,px=0,i; if(req && rn_nullable(p)) return; switch(RN_P_TYP(p)) { case RN_P_ERROR: break; case RN_P_NOT_ALLOWED: break; case RN_P_EMPTY: break; case RN_P_TEXT: px=p; break; case RN_P_CHOICE: rn_Choice(p,p1,p2); expected(p1,first,req); expected(p2,first,req); break; case RN_P_INTERLEAVE: rn_Interleave(p,p1,p2); expected(p1,first,req); expected(p2,first,req); break; case RN_P_GROUP: rn_Group(p,p1,p2); expected(p1,first,req); expected(p2,first&&rn_nullable(p1),req); break; case RN_P_ONE_OR_MORE: rn_OneOrMore(p,p1); expected(p1,first,req); break; case RN_P_LIST: rn_List(p,p1); expected(p1,first,req); break; case RN_P_DATA: px=p; break; case RN_P_DATA_EXCEPT: rn_DataExcept(p,p1,p2); expected(p1,first,req); break; case RN_P_VALUE: px=p; break; case RN_P_ATTRIBUTE: px=p; break; case RN_P_ELEMENT: px=p; break; case RN_P_AFTER: rn_After(p,p1,p2); expected(p1,first,req); if(rn_nullable(p1)) px=p; break; case RN_P_REF: break; default: assert(0); } if(px&&(first||RN_P_IS(px,RN_P_ATTRIBUTE))) { for(i=0;i!=rnx_n_exp;++i) { if(rnx_exp[i]==px) {px=0; break;} } if(px) { if(rnx_n_exp==len_exp) rnx_exp=(int*)m_stretch(rnx_exp,len_exp=2*rnx_n_exp,rnx_n_exp,sizeof(int)); rnx_exp[rnx_n_exp++]=px; } } }
static void realloc_s(struct rnc_cym *symp,int newslen) { symp->s=(char*)m_stretch(symp->s,newslen,symp->slen,sizeof(char)); symp->slen=newslen; }
static int arx(char *fn) { if((arxfd=open(arxfn=fn,O_RDONLY))==-1) { (*er_printf)("error (%s): %s\n",arxfn,strerror(errno)); return 0; } else { errors=0; len_b=read(arxfd,buf,BUFSIZE); i_b=u_bom(buf,len_b); prevline=-1; line=1; col=0; rnc=0; cc=' '; getsym(); chk_get(SYM_GRMS); chk_get(SYM_LCUR); do { if(i_2==len_2) t2s=(int(*)[2])m_stretch(t2s,len_2=i_2*2,i_2,sizeof(int[2])); if(chksym(SYM_IDNT)) t2s[i_2][0]=add_s(value); getsym(); chk_get(SYM_ASGN); if(chksym(SYM_LTRL)) { if(path2abs) { int len=strlen(arxfn)+strlen(value)+1; if(len>len_v) {value=(char*)m_stretch(value,len,len_v,sizeof(char)); len_v=len;} s_abspath(value,arxfn); } t2s[i_2][1]=add_s(value); } getsym(); ++i_2; } while(sym==SYM_IDNT); chk_get(SYM_RCUR); for(;;) { if(i_r==len_r) rules=(int(*)[3])m_stretch(rules,len_r=i_r*2,i_r,sizeof(int[3])); switch(sym) { case SYM_MTCH: rules[i_r][0]=MATCH; goto REGEXP; case SYM_NMTC: rules[i_r][0]=NOMAT; goto REGEXP; REGEXP: getsym(); if(chksym(SYM_RGXP)) { if(!rx_check(value)) error(ARX_ER_REX); rules[i_r][1]=add_s(value); } getsym(); if(chksym(SYM_IDNT)) rules[i_r][2]=typ2str(); goto NEXT; case SYM_VALD: rules[i_r][0]=VALID; goto RNG; case SYM_NVAL: rules[i_r][0]=INVAL; goto RNG; RNG: getsym(); if(chksym(SYM_RENG)) { char *rncfn=(char*)m_alloc(strlen(arxfn)+strlen("#rnc[]")+12,sizeof(char)); sprintf(rncfn,"%s#rnc[%i]",arxfn,rnc++); if(!(rules[i_r][1]=rnl_s(rncfn,value,strlen(value)))) error(ARX_ER_RNG); m_free(rncfn); } getsym(); if(chksym(SYM_IDNT)) rules[i_r][2]=typ2str(); goto NEXT; default: goto LAST; } NEXT: ++i_r; getsym(); } LAST: chk_get(SYM_EOF); close(arxfd); return !errors; } }
static void accept_m(void) { if(ht_get(&ht_m,i_m)!=-1) ht_del(&ht_m,i_m); ht_put(&ht_m,i_m++); if(i_m>=LIM_M) i_m=0; if(i_m==len_m) memo=(int(*)[M_SIZE])m_stretch(memo,len_m=i_m*2,i_m,sizeof(int[M_SIZE])); }
static int add_r(char *rx) { int len=strlen(rx)+1; if(i_r+len>len_r) regex=(char*)m_stretch(regex,len_r=2*(i_r+len),i_r,sizeof(char)); strcpy(regex+i_r,rx); return len; }
void sc_open(struct sc_stack *stp) { stp->tab[stp->base=stp->top++][1]=BASE; if(stp->top==stp->len) stp->tab=(int(*)[SC_RECSIZE])m_stretch( stp->tab,stp->len*=stp->top*2,stp->top,sizeof(int[SC_RECSIZE])); }