📄 toke.c
字号:
/* FALL THROUGH */ default: defchar: if (d[1] == '*' || (d[1] == '{' && d[2] == '0') || d[1] == '?') { e = d; break; } d++; } } if (d == t) { str_free(tmpstr); return; } *d = '\0'; tmpstr->str_cur = d - t; if (d == t+len) spat->spat_flags |= SPAT_ALL; if (*origstring != '^') spat->spat_flags |= SPAT_SCANFIRST; spat->spat_short = tmpstr; spat->spat_slen = d - t;}char *scanpat(s)register char *s;{ register SPAT *spat; register char *d; register char *e; int len; SPAT savespat; STR *str = Str_new(93,0); char delim; Newz(801,spat,1,SPAT); spat->spat_next = curstash->tbl_spatroot; /* link into spat list */ curstash->tbl_spatroot = spat; switch (*s++) { case 'm': s++; break; case '/': break; case '?': spat->spat_flags |= SPAT_ONCE; break; default: fatal("panic: scanpat"); } s = str_append_till(str,s,bufend,s[-1],patleave); if (s >= bufend) { str_free(str); yyerror("Search pattern not terminated"); yylval.arg = Nullarg; return s; } delim = *s++; while (*s == 'i' || *s == 'o' || *s == 'g') { if (*s == 'i') { s++; sawi = TRUE; spat->spat_flags |= SPAT_FOLD; } if (*s == 'o') { s++; spat->spat_flags |= SPAT_KEEP; } if (*s == 'g') { s++; spat->spat_flags |= SPAT_GLOBAL; } } len = str->str_cur; e = str->str_ptr + len; if (delim == '\'') d = e; else d = str->str_ptr; for (; d < e; d++) { if (*d == '\\') d++; else if ((*d == '$' && d[1] && d[1] != '|' && d[1] != ')') || (*d == '@')) { register ARG *arg; spat->spat_runtime = arg = op_new(1); arg->arg_type = O_ITEM; arg[1].arg_type = A_DOUBLE; arg[1].arg_ptr.arg_str = str_smake(str); d = scanident(d,bufend,buf); (void)stabent(buf,TRUE); /* make sure it's created */ for (; d < e; d++) { if (*d == '\\') d++; else if (*d == '$' && d[1] && d[1] != '|' && d[1] != ')') { d = scanident(d,bufend,buf); (void)stabent(buf,TRUE); } else if (*d == '@') { d = scanident(d,bufend,buf); if (strEQ(buf,"ARGV") || strEQ(buf,"ENV") || strEQ(buf,"SIG") || strEQ(buf,"INC")) (void)stabent(buf,TRUE); } } goto got_pat; /* skip compiling for now */ } } if (spat->spat_flags & SPAT_FOLD) StructCopy(spat, &savespat, SPAT); scanconst(spat,str->str_ptr,len); if ((spat->spat_flags & SPAT_ALL) && (spat->spat_flags & SPAT_SCANFIRST)) { fbmcompile(spat->spat_short, spat->spat_flags & SPAT_FOLD); spat->spat_regexp = regcomp(str->str_ptr,str->str_ptr+len, spat->spat_flags & SPAT_FOLD); /* Note that this regexp can still be used if someone says * something like /a/ && s//b/; so we can't delete it. */ } else { if (spat->spat_flags & SPAT_FOLD) StructCopy(&savespat, spat, SPAT); if (spat->spat_short) fbmcompile(spat->spat_short, spat->spat_flags & SPAT_FOLD); spat->spat_regexp = regcomp(str->str_ptr,str->str_ptr+len, spat->spat_flags & SPAT_FOLD); hoistmust(spat); } got_pat: str_free(str); yylval.arg = make_match(O_MATCH,stab2arg(A_STAB,defstab),spat); return s;}char *scansubst(start)char *start;{ register char *s = start; register SPAT *spat; register char *d; register char *e; int len; STR *str = Str_new(93,0); char term = *s; if (term && (d = index("([{< )]}> )]}>",term))) term = d[5]; Newz(802,spat,1,SPAT); spat->spat_next = curstash->tbl_spatroot; /* link into spat list */ curstash->tbl_spatroot = spat; s = str_append_till(str,s+1,bufend,term,patleave); if (s >= bufend) { str_free(str); yyerror("Substitution pattern not terminated"); yylval.arg = Nullarg; return s; } len = str->str_cur; e = str->str_ptr + len; for (d = str->str_ptr; d < e; d++) { if (*d == '\\') d++; else if ((*d == '$' && d[1] && d[1] != '|' && /*(*/ d[1] != ')') || *d == '@' ) { register ARG *arg; spat->spat_runtime = arg = op_new(1); arg->arg_type = O_ITEM; arg[1].arg_type = A_DOUBLE; arg[1].arg_ptr.arg_str = str_smake(str); d = scanident(d,e,buf); (void)stabent(buf,TRUE); /* make sure it's created */ for (; *d; d++) { if (*d == '$' && d[1] && d[-1] != '\\' && d[1] != '|') { d = scanident(d,e,buf); (void)stabent(buf,TRUE); } else if (*d == '@' && d[-1] != '\\') { d = scanident(d,e,buf); if (strEQ(buf,"ARGV") || strEQ(buf,"ENV") || strEQ(buf,"SIG") || strEQ(buf,"INC")) (void)stabent(buf,TRUE); } } goto get_repl; /* skip compiling for now */ } } scanconst(spat,str->str_ptr,len);get_repl: if (term != *start) s++; s = scanstr(s, SCAN_REPL); if (s >= bufend) { str_free(str); yyerror("Substitution replacement not terminated"); yylval.arg = Nullarg; return s; } spat->spat_repl = yylval.arg; if ((spat->spat_repl[1].arg_type & A_MASK) == A_SINGLE) spat->spat_flags |= SPAT_CONST; else if ((spat->spat_repl[1].arg_type & A_MASK) == A_DOUBLE) { STR *tmpstr; register char *t; spat->spat_flags |= SPAT_CONST; tmpstr = spat->spat_repl[1].arg_ptr.arg_str; e = tmpstr->str_ptr + tmpstr->str_cur; for (t = tmpstr->str_ptr; t < e; t++) { if (*t == '$' && t[1] && (index("`'&+0123456789",t[1]) || (t[1] == '{' /*}*/ && isDIGIT(t[2])) )) spat->spat_flags &= ~SPAT_CONST; } } while (*s == 'g' || *s == 'i' || *s == 'e' || *s == 'o') { int es = 0; if (*s == 'e') { s++; es++; if ((spat->spat_repl[1].arg_type & A_MASK) == A_DOUBLE) spat->spat_repl[1].arg_type = A_SINGLE; spat->spat_repl = make_op( (!es && spat->spat_repl[1].arg_type == A_SINGLE ? O_EVALONCE : O_EVAL), 2, spat->spat_repl, Nullarg, Nullarg); spat->spat_flags &= ~SPAT_CONST; } if (*s == 'g') { s++; spat->spat_flags |= SPAT_GLOBAL; } if (*s == 'i') { s++; sawi = TRUE; spat->spat_flags |= SPAT_FOLD; if (!(spat->spat_flags & SPAT_SCANFIRST)) { str_free(spat->spat_short); /* anchored opt doesn't do */ spat->spat_short = Nullstr; /* case insensitive match */ spat->spat_slen = 0; } } if (*s == 'o') { s++; spat->spat_flags |= SPAT_KEEP; } } if (spat->spat_short && (spat->spat_flags & SPAT_SCANFIRST)) fbmcompile(spat->spat_short, spat->spat_flags & SPAT_FOLD); if (!spat->spat_runtime) { spat->spat_regexp = regcomp(str->str_ptr,str->str_ptr+len, spat->spat_flags & SPAT_FOLD); hoistmust(spat); } yylval.arg = make_match(O_SUBST,stab2arg(A_STAB,defstab),spat); str_free(str); return s;}voidhoistmust(spat)register SPAT *spat;{ if (!spat->spat_short && spat->spat_regexp->regstart && (!spat->spat_regexp->regmust || spat->spat_regexp->reganch & ROPT_ANCH) ) { if (!(spat->spat_regexp->reganch & ROPT_ANCH)) spat->spat_flags |= SPAT_SCANFIRST; else if (spat->spat_flags & SPAT_FOLD) return; spat->spat_short = str_smake(spat->spat_regexp->regstart); } else if (spat->spat_regexp->regmust) {/* is there a better short-circuit? */ if (spat->spat_short && str_eq(spat->spat_short,spat->spat_regexp->regmust)) { if (spat->spat_flags & SPAT_SCANFIRST) { str_free(spat->spat_short); spat->spat_short = Nullstr; } else { str_free(spat->spat_regexp->regmust); spat->spat_regexp->regmust = Nullstr; return; } } if (!spat->spat_short || /* promote the better string */ ((spat->spat_flags & SPAT_SCANFIRST) && (spat->spat_short->str_cur < spat->spat_regexp->regmust->str_cur) )){ str_free(spat->spat_short); /* ok if null */ spat->spat_short = spat->spat_regexp->regmust; spat->spat_regexp->regmust = Nullstr; spat->spat_flags |= SPAT_SCANFIRST; } }}char *scantrans(start)char *start;{ register char *s = start; ARG *arg = l(make_op(O_TRANS,2,stab2arg(A_STAB,defstab),Nullarg,Nullarg)); STR *tstr; STR *rstr; register char *t; register char *r; register short *tbl; register int i; register int j; int tlen, rlen; int squash; int delete; int complement; New(803,tbl,256,short); arg[2].arg_type = A_NULL; arg[2].arg_ptr.arg_cval = (char*) tbl; s = scanstr(s, SCAN_TR); if (s >= bufend) { yyerror("Translation pattern not terminated"); yylval.arg = Nullarg; return s; } tstr = yylval.arg[1].arg_ptr.arg_str; yylval.arg[1].arg_ptr.arg_str = Nullstr; arg_free(yylval.arg); t = tstr->str_ptr; tlen = tstr->str_cur; if (s[-1] == *start) s--; s = scanstr(s, SCAN_TR|SCAN_REPL); if (s >= bufend) { yyerror("Translation replacement not terminated"); yylval.arg = Nullarg; return s; } rstr = yylval.arg[1].arg_ptr.arg_str; yylval.arg[1].arg_ptr.arg_str = Nullstr; arg_free(yylval.arg); r = rstr->str_ptr; rlen = rstr->str_cur; complement = delete = squash = 0; while (*s == 'c' || *s == 'd' || *s == 's') { if (*s == 'c') complement = 1; else if (*s == 'd') delete = 2; else squash = 1; s++; } arg[2].arg_len = delete|squash; yylval.arg = arg; if (complement) { Zero(tbl, 256, short); for (i = 0; i < tlen; i++) tbl[t[i] & 0377] = -1; for (i = 0, j = 0; i < 256; i++) { if (!tbl[i]) { if (j >= rlen) { if (delete) tbl[i] = -2; else if (rlen) tbl[i] = r[j-1] & 0377; else tbl[i] = i; } else tbl[i] = r[j++] & 0377; } } } else { if (!rlen && !delete) { r = t; rlen = tlen; } for (i = 0; i < 256; i++) tbl[i] = -1; for (i = 0, j = 0; i < tlen; i++,j++) { if (j >= rlen) { if (delete) { if (tbl[t[i] & 0377] == -1) tbl[t[i] & 0377] = -2; continue; } --j; } if (tbl[t[i] & 0377] == -1) tbl[t[i] & 0377] = r[j] & 0377; } } str_free(tstr); str_free(rstr); return s;}char *scanstr(start, in_what)char *start;int in_what;{ register char *s = start; register char term; register char *d; register ARG *arg; register char *send; register bool makesingle = FALSE; register STAB *stab; bool alwaysdollar = FALSE; bool hereis = FALSE; STR *herewas; STR *str; /* which backslash sequences to keep */ char *leave = (in_what & SCAN_TR) ? "\\$@nrtfbeacx0123456789-" : "\\$@nrtfbeacx0123456789[{]}lLuUE"; int len; arg = op_new(1); yylval.arg = arg; arg->arg_type = O_ITEM; switch (*s) { default: /* a substitution replacement */ arg[1].arg_type = A_DOUBLE; makesingle = TRUE; /* maybe disable runtime scanning */ term = *s; if (term == '\'') leave = Nullch; goto snarf_it; case '0': { unsigned long i; int shift; arg[1].arg_type = A_SINGLE; if (s[1] == 'x') { shift = 4; s += 2; } else if (s[1] == '.') goto decimal; else shift = 3; i = 0; for (;;) { switch (*s) { default: goto out; case '_': s++; break; case '8': case '9': if (shift != 4) yyerror("Illegal octal digit"); /* FALL THROUGH */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': i <<= shift; i += *s++ & 15; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': if (shift != 4) goto out; i <<= 4; i += (*s++ & 7) + 9; break; } } out: str = Str_new(92,0); str_numset(str,(double)i); if (str->str_ptr) { Safefree(str->str_ptr); str->str_ptr = Nullch; str->str_len = str->str_cur = 0; } arg[1].arg_ptr.arg_str = str; } break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': decimal: arg[1].arg_type = A_SINGLE; d = tokenbuf; while (isDIGIT(*s) || *s == '_') { if (*s == '_') s++; else *d++ = *s++; } if (*s == '.' && s[1] != '.') { *d++ = *s++; while (isDIGIT(*s) || *s == '_') { if (*s == '_') s++; else *d++ = *s++; } } if (*s && index("eE",*s) && index("+-0123456789",s[1])) { *d++ = *s++; if (*s == '+' || *s == '-') *d++ = *s++; while (isDIGIT(*s)) *d++ = *s++; } *d = '\0'; str = Str_new(92,0); str_numset(str,atof(tokenbuf)); if (str->str_ptr) { Safefree(str->str_ptr); str->str_ptr = Nullch; str->str_len = str->str_cur = 0; } arg[1].arg_ptr.arg_str = str; break; case '<': if (in_what & (SCAN_REPL|SCAN_TR)) goto do_double; if (*++s == '<') { hereis = TRUE; d = tokenbuf; if (!rsfp) *d++ = '\n'; if (*++s && index("`'\"",*s)) { term = *s++; s = cpytill(d,s,bufend,term,&len); if (s < bufend) s++; d += len; } else { if (*s == '\\') s++, term = '\''; else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -