char *fget_next_line(FILE *fd) { t_struct tbl; static char buf[BUF_SIZE]; static int i = 0; static int lu = 0; if (!init_struct(&tbl)) return (0); while (1) { if (i >= lu) { lu = (int)fread(buf, 1, BUF_SIZE, fd); if (lu == 0) return ((tbl.s[0]) ? (end_of(tbl.s, tbl.j)) : (0)); i = 0; } if ((tbl.j + 1) == tbl.taille) realloc_s(&tbl); if (buf[i] == '\n' || !buf[i]) { i++; return (end_of(tbl.s, tbl.j)); } tbl.s[tbl.j++] = buf[i++]; } }
int StringConcat(String* src, const String* added) { unsigned int i; realloc_s(&src->data, (added->size + src->size + 1) * sizeof(char)); if(src->data == NULL) return 1; src->size += added->size; for(i = 0; i < added->size; i++) src->data[i + src->size - added->size] = added->data[i]; src->data[src->size] = '\0'; return 0; }
int StringConcatChar(String* src, const char* added) { unsigned int size, i; for(size = 0; added[size] != '\0'; size++); //size--; realloc_s(&src->data, (size + src->size + 1) * sizeof(char)); if(src->data == NULL) return 1; src->size += size; for(i = 0; i < size; i++) src->data[i + src->size - size] = added[i]; src->data[src->size] = '\0'; return 0; }
/* advance, join literal fragments and skip annotations and documentation comments */ static void getsym(struct rnc_source *sp) { advance(sp); for(;;) { switch(CUR(sp).sym) { case SYM_DOCUMENTATION: advance(sp); continue; case SYM_FOLLOW_ANNOTATION: advance(sp); if(CUR(sp).sym<0||CUR(sp).sym>SYM_QNAME) { error(0,sp,RNC_ER_SEXP,sp->fn,CUR(sp).line,CUR(sp).col,"identifier, prefixed name or keyword",sym2str(CUR(sp).sym)); while(CUR(sp).sym!=SYM_LSQU&&CUR(sp).sym!=SYM_EOF) advance(sp); } else { advance(sp); if(CUR(sp).sym!=SYM_LSQU) error(0,sp,RNC_ER_SEXP,sp->fn,CUR(sp).line,CUR(sp).col,sym2str(SYM_LSQU),sym2str(CUR(sp).sym)); } case SYM_LSQU: skipAnnotationContent(sp); continue; case SYM_LITERAL: /* alternatively, either a non-terminal, or a separate filter; - one more filtering layer is not worth the effort, - the non-terminal would later need extra buffer for concatenated strings. Since the concatenation is only applied to constants anyway, merging them into a single terminal looks appropriate. */ if(NXT(sp).sym==SYM_CONCAT) { sp->cur=!sp->cur; advance(sp); if(NXT(sp).sym!=SYM_LITERAL) { error(0,sp,RNC_ER_SEXP,sp->fn,NXT(sp).line,NXT(sp).col,sym2str(SYM_LITERAL),sym2str(NXT(sp).sym)); break; } { int newslen=strlen(CUR(sp).s)+strlen(NXT(sp).s)+1; if(newslen>CUR(sp).slen) realloc_s(&CUR(sp),newslen); } strcat(CUR(sp).s,NXT(sp).s); sp->cur=!sp->cur; advance(sp); continue; } break; } return; } }
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; } } } } }