📄 str.c
字号:
if (s > send) fatal("Unmatched brackets in string"); if (*nointrp) { /* we're in a regular expression */ d = checkpoint; if (*d == '{' && s[-1] == '}') { /* maybe {n,m} */ ++d; if (isDIGIT(*d)) { /* matches /^{\d,?\d*}$/ */ if (*++d == ',') ++d; while (isDIGIT(*d)) d++; if (d == s - 1) s = checkpoint; /* Is {n,m}! Backoff! */ } } else if (*d == '[' && s[-1] == ']') { /* char class? */ int weight = 2; /* let's weigh the evidence */ char seen[256]; unsigned char un_char = 0, last_un_char; Zero(seen,256,char); *--s = '\0'; if (d[1] == '^') weight += 150; else if (d[1] == '$') weight -= 3; if (isDIGIT(d[1])) { if (d[2]) { if (isDIGIT(d[2]) && !d[3]) weight -= 10; } else weight -= 100; } for (d++; d < s; d++) { last_un_char = un_char; un_char = (unsigned char)*d; switch (*d) { case '&': case '$': weight -= seen[un_char] * 10; if (isALNUM(d[1])) { d = scanident(d,s,tokenbuf); if (stabent(tokenbuf,FALSE)) weight -= 100; else weight -= 10; } else if (*d == '$' && d[1] && index("[#!%*<>()-=",d[1])) { if (!d[2] || /*{*/ index("])} =",d[2])) weight -= 10; else weight -= 1; } break; case '\\': un_char = 254; if (d[1]) { if (index("wds",d[1])) weight += 100; else if (seen['\''] || seen['"']) weight += 1; else if (index("rnftb",d[1])) weight += 40; else if (isDIGIT(d[1])) { weight += 40; while (d[1] && isDIGIT(d[1])) d++; } } else weight += 100; break; case '-': if (last_un_char < (unsigned char) d[1] || d[1] == '\\') { if (index("aA01! ",last_un_char)) weight += 30; if (index("zZ79~",d[1])) weight += 30; } else weight -= 1; default: if (isALPHA(*d) && d[1] && isALPHA(d[1])) { bufptr = d; if (yylex() != WORD) weight -= 150; d = bufptr; } if (un_char == last_un_char + 1) weight += 5; weight -= seen[un_char]; break; } seen[un_char]++; }#ifdef DEBUGGING if (debug & 512) fprintf(stderr,"[%s] weight %d\n", checkpoint+1,weight);#endif *s++ = ']'; if (weight >= 0) /* probably a character class */ s = checkpoint; } } } if (*t == '@') str_ncat(toparse, "join($\",", 8); if (t[1] == '{' && s[-1] == '}') { str_ncat(toparse, t, 1); str_ncat(toparse, t+2, s - t - 3); } else str_ncat(toparse, t, s - t); if (*t == '@') str_ncat(toparse, ")", 1); t = s; } else s++; } str_ncat(str,t,s-t); if (sawcase) str_ncat(str, "$cE", 3); if (toparse->str_ptr && *toparse->str_ptr == ',') { *toparse->str_ptr = '('; str_ncat(toparse,",$$);",5); str->str_u.str_args = parselist(toparse); str->str_u.str_args->arg_len--; /* ignore $$ reference */ } else str->str_u.str_args = Nullarg; str_free(toparse); str->str_pok |= SP_INTRP; str->str_nok = 0; str_replace(src,str);}STR *interp(str,src,sp)register STR *str;STR *src;int sp;{ register char *s; register char *t; register char *send; register STR **elem; int docase = 0; int l = 0; int u = 0; int L = 0; int U = 0; if (str == &str_undef) return Nullstr; if (!(src->str_pok & SP_INTRP)) { int oldsave = savestack->ary_fill; (void)savehptr(&curstash); curstash = curcmd->c_stash; /* so stabent knows right package */ intrpcompile(src); restorelist(oldsave); } s = src->str_ptr; /* assumed valid since str_pok set */ t = s; send = s + src->str_cur; if (src->str_u.str_args) { (void)eval(src->str_u.str_args,G_ARRAY,sp); /* Assuming we have correct # of args */ elem = stack->ary_array + sp; } str_nset(str,"",0); while (s < send) { if (*s == '$' && s+1 < send) { if (s-t > 0) str_ncat(str,t,s-t); switch(*++s) { default: fatal("panic: unknown interp cookie\n"); break; case 'a': str_scat(str,*++elem); break; case 'b': str_ncat(str,++s,1); break; case 'c': if (docase && str->str_cur >= docase) { char *b = str->str_ptr + --docase; if (L) lcase(b, str->str_ptr + str->str_cur); else if (U) ucase(b, str->str_ptr + str->str_cur); if (u) /* note that l & u are independent of L & U */ ucase(b, b+1); else if (l) lcase(b, b+1); l = u = 0; } docase = str->str_cur + 1; switch (*++s) { case 'u': u = 1; l = 0; break; case 'U': U = 1; L = 0; break; case 'l': l = 1; u = 0; break; case 'L': L = 1; U = 0; break; case 'E': docase = L = U = l = u = 0; break; } break; } t = ++s; } else s++; } if (s-t > 0) str_ncat(str,t,s-t); return str;}static voiducase(s,send)register char *s;register char *send;{ while (s < send) { if (isLOWER(*s)) *s = toupper(*s); s++; }}static voidlcase(s,send)register char *s;register char *send;{ while (s < send) { if (isUPPER(*s)) *s = tolower(*s); s++; }}voidstr_inc(str)register STR *str;{ register char *d; if (!str || str == &str_undef) return; if (str->str_nok) { str->str_u.str_nval += 1.0; str->str_pok = 0; return; } if (!str->str_pok || !*str->str_ptr) { str->str_u.str_nval = 1.0; str->str_nok = 1; str->str_pok = 0; return; } d = str->str_ptr; while (isALPHA(*d)) d++; while (isDIGIT(*d)) d++; if (*d) { str_numset(str,atof(str->str_ptr) + 1.0); /* punt */ return; } d--; while (d >= str->str_ptr) { if (isDIGIT(*d)) { if (++*d <= '9') return; *(d--) = '0'; } else { ++*d; if (isALPHA(*d)) return; *(d--) -= 'z' - 'a' + 1; } } /* oh,oh, the number grew */ STR_GROW(str, str->str_cur + 2); str->str_cur++; for (d = str->str_ptr + str->str_cur; d > str->str_ptr; d--) *d = d[-1]; if (isDIGIT(d[1])) *d = '1'; else *d = d[1];}voidstr_dec(str)register STR *str;{ if (!str || str == &str_undef) return; if (str->str_nok) { str->str_u.str_nval -= 1.0; str->str_pok = 0; return; } if (!str->str_pok) { str->str_u.str_nval = -1.0; str->str_nok = 1; return; } str_numset(str,atof(str->str_ptr) - 1.0);}/* Make a string that will exist for the duration of the expression * evaluation. Actually, it may have to last longer than that, but * hopefully cmd_exec won't free it until it has been assigned to a * permanent location. */static long tmps_size = -1;STR *str_mortal(oldstr)STR *oldstr;{ register STR *str = Str_new(78,0); str_sset(str,oldstr); if (++tmps_max > tmps_size) { tmps_size = tmps_max; if (!(tmps_size & 127)) { if (tmps_size) Renew(tmps_list, tmps_size + 128, STR*); else New(702,tmps_list, 128, STR*); } } tmps_list[tmps_max] = str; if (str->str_pok) str->str_pok |= SP_TEMP; return str;}/* same thing without the copying */STR *str_2mortal(str)register STR *str;{ if (!str || str == &str_undef) return str; if (++tmps_max > tmps_size) { tmps_size = tmps_max; if (!(tmps_size & 127)) { if (tmps_size) Renew(tmps_list, tmps_size + 128, STR*); else New(704,tmps_list, 128, STR*); } } tmps_list[tmps_max] = str; if (str->str_pok) str->str_pok |= SP_TEMP; return str;}STR *str_make(s,len)char *s;STRLEN len;{ register STR *str = Str_new(79,0); if (!len) len = strlen(s); str_nset(str,s,len); return str;}STR *str_nmake(n)double n;{ register STR *str = Str_new(80,0); str_numset(str,n); return str;}/* make an exact duplicate of old */STR *str_smake(old)register STR *old;{ register STR *new = Str_new(81,0); if (!old) return Nullstr; if (old->str_state == SS_FREE) { warn("semi-panic: attempt to dup freed string"); return Nullstr; } if (old->str_state == SS_INCR && !(old->str_pok & 2)) Str_Grow(old,0); if (new->str_ptr) Safefree(new->str_ptr); StructCopy(old,new,STR); if (old->str_ptr) { new->str_ptr = nsavestr(old->str_ptr,old->str_len); new->str_pok &= ~SP_TEMP; } return new;}voidstr_reset(s,stash)register char *s;HASH *stash;{ register HENT *entry; register STAB *stab; register STR *str; register int i; register SPAT *spat; register int max; if (!*s) { /* reset ?? searches */ for (spat = stash->tbl_spatroot; spat != Nullspat; spat = spat->spat_next) { spat->spat_flags &= ~SPAT_USED; } return; } /* reset variables */ if (!stash->tbl_array) return; while (*s) { i = *s; if (s[1] == '-') { s += 2; } max = *s++; for ( ; i <= max; i++) { for (entry = stash->tbl_array[i]; entry; entry = entry->hent_next) { stab = (STAB*)entry->hent_val; str = stab_val(stab); str->str_cur = 0; str->str_nok = 0;#ifdef TAINT str->str_tainted = tainted;#endif if (str->str_ptr != Nullch) str->str_ptr[0] = '\0'; if (stab_xarray(stab)) { aclear(stab_xarray(stab)); } if (stab_xhash(stab)) { hclear(stab_xhash(stab), FALSE); if (stab == envstab) environ[0] = Nullch; } } } }}#ifdef TAINTvoidtaintproper(s)char *s;{#ifdef DEBUGGING if (debug & 2048) fprintf(stderr,"%s %d %d %d\n",s,tainted,uid, euid);#endif if (tainted && (!euid || euid != uid || egid != gid || taintanyway)) { if (!unsafe) fatal("%s", s); else if (dowarn) warn("%s", s); }}voidtaintenv(){ register STR *envstr; envstr = hfetch(stab_hash(envstab),"PATH",4,FALSE); if (envstr == &str_undef || envstr->str_tainted) { tainted = 1; if (envstr->str_tainted == 2) taintproper("Insecure directory in PATH"); else taintproper("Insecure PATH"); } envstr = hfetch(stab_hash(envstab),"IFS",3,FALSE); if (envstr != &str_undef && envstr->str_tainted) { tainted = 1; taintproper("Insecure IFS"); }}#endif /* TAINT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -