📄 str.c
字号:
/* $RCSfile: str.c,v $$Revision: 4.0.1.7 $$Date: 1993/02/05 19:43:47 $ * * Copyright (c) 1991, Larry Wall * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. * * $Log: str.c,v $ * Revision 4.0.1.7 1993/02/05 19:43:47 lwall * patch36: the non-std stdio input code wasn't null-proof * * Revision 4.0.1.6 92/06/11 21:14:21 lwall * patch34: quotes containing subscripts containing variables didn't parse right * * Revision 4.0.1.5 92/06/08 15:40:43 lwall * patch20: removed implicit int declarations on functions * patch20: Perl now distinguishes overlapped copies from non-overlapped * patch20: paragraph mode now skips extra newlines automatically * patch20: fixed memory leak in doube-quote interpretation * patch20: made /\$$foo/ look for literal '$foo' * patch20: "$var{$foo'bar}" didn't scan subscript correctly * patch20: a splice on non-existent array elements could dump core * patch20: running taintperl explicitly now does checks even if $< == $> * * Revision 4.0.1.4 91/11/05 18:40:51 lwall * patch11: $foo .= <BAR> could overrun malloced memory * patch11: \$ didn't always make it through double-quoter to regexp routines * patch11: prepared for ctype implementations that don't define isascii() * * Revision 4.0.1.3 91/06/10 01:27:54 lwall * patch10: $) and $| incorrectly handled in run-time patterns * * Revision 4.0.1.2 91/06/07 11:58:13 lwall * patch4: new copyright notice * patch4: taint check on undefined string could cause core dump * * Revision 4.0.1.1 91/04/12 09:15:30 lwall * patch1: fixed undefined environ problem * patch1: substr($ENV{"PATH"},0,0) = "/foo:" didn't modify environment * patch1: $foo .= <BAR> could cause core dump for certain lengths of $foo * * Revision 4.0 91/03/20 01:39:55 lwall * 4.0 baseline. * */#include "EXTERN.h"#include "perl.h"#include "perly.h"static void ucase();static void lcase();#ifndef str_getchar *str_get(str)STR *str;{#ifdef TAINT tainted |= str->str_tainted;#endif return str->str_pok ? str->str_ptr : str_2ptr(str);}#endif/* dlb ... guess we have a "crippled cc". * dlb the following functions are usually macros. */#ifndef str_trueintstr_true(Str)STR *Str;{ if (Str->str_pok) { if (*Str->str_ptr > '0' || Str->str_cur > 1 || (Str->str_cur && *Str->str_ptr != '0')) return 1; return 0; } if (Str->str_nok) return (Str->str_u.str_nval != 0.0); return 0;}#endif /* str_true */#ifndef str_gnumdouble str_gnum(Str)STR *Str;{#ifdef TAINT tainted |= Str->str_tainted;#endif /* TAINT*/ if (Str->str_nok) return Str->str_u.str_nval; return str_2num(Str);}#endif /* str_gnum *//* dlb ... end of crutch */char *str_grow(str,newlen)register STR *str;#ifndef DOSISHregister int newlen;#elseunsigned long newlen;#endif{ register char *s = str->str_ptr;#ifdef MSDOS if (newlen >= 0x10000) { fprintf(stderr, "Allocation too large: %lx\n", newlen); exit(1); }#endif /* MSDOS */ if (str->str_state == SS_INCR) { /* data before str_ptr? */ str->str_len += str->str_u.str_useful; str->str_ptr -= str->str_u.str_useful; str->str_u.str_useful = 0L; Move(s, str->str_ptr, str->str_cur+1, char); s = str->str_ptr; str->str_state = SS_NORM; /* normal again */ if (newlen > str->str_len) newlen += 10 * (newlen - str->str_cur); /* avoid copy each time */ } if (newlen > str->str_len) { /* need more room? */ if (str->str_len) Renew(s,newlen,char); else New(703,s,newlen,char); str->str_ptr = s; str->str_len = newlen; } return s;}voidstr_numset(str,num)register STR *str;double num;{ if (str->str_pok) { str->str_pok = 0; /* invalidate pointer */ if (str->str_state == SS_INCR) Str_Grow(str,0); } str->str_u.str_nval = num; str->str_state = SS_NORM; str->str_nok = 1; /* validate number */#ifdef TAINT str->str_tainted = tainted;#endif}char *str_2ptr(str)register STR *str;{ register char *s; int olderrno; if (!str) return ""; if (str->str_nok) { STR_GROW(str, 30); s = str->str_ptr; olderrno = errno; /* some Xenix systems wipe out errno here */#if defined(scs) && defined(ns32000) gcvt(str->str_u.str_nval,20,s);#else#ifdef apollo if (str->str_u.str_nval == 0.0) (void)strcpy(s,"0"); else#endif /*apollo*/ (void)sprintf(s,"%.20g",str->str_u.str_nval);#endif /*scs*/ errno = olderrno; while (*s) s++;#ifdef hcx if (s[-1] == '.') s--;#endif } else { if (str == &str_undef) return No; if (dowarn) warn("Use of uninitialized variable"); STR_GROW(str, 30); s = str->str_ptr; } *s = '\0'; str->str_cur = s - str->str_ptr; str->str_pok = 1;#ifdef DEBUGGING if (debug & 32) fprintf(stderr,"0x%lx ptr(%s)\n",str,str->str_ptr);#endif return str->str_ptr;}doublestr_2num(str)register STR *str;{ if (!str) return 0.0; if (str->str_state == SS_INCR) Str_Grow(str,0); /* just force copy down */ str->str_state = SS_NORM; if (str->str_len && str->str_pok) str->str_u.str_nval = atof(str->str_ptr); else { if (str == &str_undef) return 0.0; if (dowarn) warn("Use of uninitialized variable"); str->str_u.str_nval = 0.0; } str->str_nok = 1;#ifdef DEBUGGING if (debug & 32) fprintf(stderr,"0x%lx num(%g)\n",str,str->str_u.str_nval);#endif return str->str_u.str_nval;}/* Note: str_sset() should not be called with a source string that needs * be reused, since it may destroy the source string if it is marked * as temporary. */voidstr_sset(dstr,sstr)STR *dstr;register STR *sstr;{#ifdef TAINT if (sstr) tainted |= sstr->str_tainted;#endif if (sstr == dstr || dstr == &str_undef) return; if (!sstr) dstr->str_pok = dstr->str_nok = 0; else if (sstr->str_pok) { /* * Check to see if we can just swipe the string. If so, it's a * possible small lose on short strings, but a big win on long ones. * It might even be a win on short strings if dstr->str_ptr * has to be allocated and sstr->str_ptr has to be freed. */ if (sstr->str_pok & SP_TEMP) { /* slated for free anyway? */ if (dstr->str_ptr) { if (dstr->str_state == SS_INCR) dstr->str_ptr -= dstr->str_u.str_useful; Safefree(dstr->str_ptr); } dstr->str_ptr = sstr->str_ptr; dstr->str_len = sstr->str_len; dstr->str_cur = sstr->str_cur; dstr->str_state = sstr->str_state; dstr->str_pok = sstr->str_pok & ~SP_TEMP;#ifdef TAINT dstr->str_tainted = sstr->str_tainted;#endif sstr->str_ptr = Nullch; sstr->str_len = 0; sstr->str_pok = 0; /* wipe out any weird flags */ sstr->str_state = 0; /* so sstr frees uneventfully */ } else { /* have to copy actual string */ if (dstr->str_ptr) { if (dstr->str_state == SS_INCR) { Str_Grow(dstr,0); } } str_nset(dstr,sstr->str_ptr,sstr->str_cur); } /*SUPPRESS 560*/ if (dstr->str_nok = sstr->str_nok) dstr->str_u.str_nval = sstr->str_u.str_nval; else {#ifdef STRUCTCOPY dstr->str_u = sstr->str_u;#else dstr->str_u.str_nval = sstr->str_u.str_nval;#endif if (dstr->str_cur == sizeof(STBP)) { char *tmps = dstr->str_ptr; if (*tmps == 'S' && bcmp(tmps,"StB",4) == 0) { if (dstr->str_magic && dstr->str_magic->str_rare == 'X') { str_free(dstr->str_magic); dstr->str_magic = Nullstr; } if (!dstr->str_magic) { dstr->str_magic = str_smake(sstr->str_magic); dstr->str_magic->str_rare = 'X'; } } } } } else if (sstr->str_nok) str_numset(dstr,sstr->str_u.str_nval); else { if (dstr->str_state == SS_INCR) Str_Grow(dstr,0); /* just force copy down */#ifdef STRUCTCOPY dstr->str_u = sstr->str_u;#else dstr->str_u.str_nval = sstr->str_u.str_nval;#endif dstr->str_pok = dstr->str_nok = 0; }}voidstr_nset(str,ptr,len)register STR *str;register char *ptr;register STRLEN len;{ if (str == &str_undef) return; STR_GROW(str, len + 1); if (ptr) Move(ptr,str->str_ptr,len,char); str->str_cur = len; *(str->str_ptr+str->str_cur) = '\0'; str->str_nok = 0; /* invalidate number */ str->str_pok = 1; /* validate pointer */#ifdef TAINT str->str_tainted = tainted;#endif}voidstr_set(str,ptr)register STR *str;register char *ptr;{ register STRLEN len; if (str == &str_undef) return; if (!ptr) ptr = ""; len = strlen(ptr); STR_GROW(str, len + 1); Move(ptr,str->str_ptr,len+1,char); str->str_cur = len; str->str_nok = 0; /* invalidate number */ str->str_pok = 1; /* validate pointer */#ifdef TAINT str->str_tainted = tainted;#endif}voidstr_chop(str,ptr) /* like set but assuming ptr is in str */register STR *str;register char *ptr;{ register STRLEN delta; if (!ptr || !(str->str_pok)) return; delta = ptr - str->str_ptr; str->str_len -= delta; str->str_cur -= delta; str->str_ptr += delta; if (str->str_state == SS_INCR) str->str_u.str_useful += delta; else { str->str_u.str_useful = delta; str->str_state = SS_INCR; } str->str_nok = 0; /* invalidate number */ str->str_pok = 1; /* validate pointer (and unstudy str) */}voidstr_ncat(str,ptr,len)register STR *str;register char *ptr;register STRLEN len;{ if (str == &str_undef) return; if (!(str->str_pok)) (void)str_2ptr(str); STR_GROW(str, str->str_cur + len + 1); Move(ptr,str->str_ptr+str->str_cur,len,char); str->str_cur += len; *(str->str_ptr+str->str_cur) = '\0'; str->str_nok = 0; /* invalidate number */ str->str_pok = 1; /* validate pointer */#ifdef TAINT str->str_tainted |= tainted;#endif}voidstr_scat(dstr,sstr)STR *dstr;register STR *sstr;{ if (!sstr) return;#ifdef TAINT tainted |= sstr->str_tainted;#endif if (!(sstr->str_pok)) (void)str_2ptr(sstr); if (sstr) str_ncat(dstr,sstr->str_ptr,sstr->str_cur);}voidstr_cat(str,ptr)register STR *str;register char *ptr;{ register STRLEN len; if (str == &str_undef) return; if (!ptr) return; if (!(str->str_pok)) (void)str_2ptr(str); len = strlen(ptr); STR_GROW(str, str->str_cur + len + 1); Move(ptr,str->str_ptr+str->str_cur,len+1,char); str->str_cur += len; str->str_nok = 0; /* invalidate number */ str->str_pok = 1; /* validate pointer */#ifdef TAINT str->str_tainted |= tainted;#endif}char *str_append_till(str,from,fromend,delim,keeplist)register STR *str;register char *from;register char *fromend;register int delim;char *keeplist;{ register char *to; register STRLEN len; if (str == &str_undef) return Nullch; if (!from) return Nullch; len = fromend - from; STR_GROW(str, str->str_cur + len + 1); str->str_nok = 0; /* invalidate number */ str->str_pok = 1; /* validate pointer */ to = str->str_ptr+str->str_cur; for (; from < fromend; from++,to++) { if (*from == '\\' && from+1 < fromend && delim != '\\') { if (!keeplist) { if (from[1] == delim || from[1] == '\\') from++; else *to++ = *from++; } else if (from[1] && index(keeplist,from[1])) *to++ = *from++; else from++; } else if (*from == delim) break; *to = *from; } *to = '\0'; str->str_cur = to - str->str_ptr; return from;}STR *#ifdef LEAKTESTstr_new(x,len)int x;#elsestr_new(len)#endifSTRLEN len;{ register STR *str; if (freestrroot) { str = freestrroot; freestrroot = str->str_magic; str->str_magic = Nullstr; str->str_state = SS_NORM; } else { Newz(700+x,str,1,STR); } if (len) STR_GROW(str, len + 1); return str;}voidstr_magic(str, stab, how, name, namlen)register STR *str;STAB *stab;int how;char *name;STRLEN namlen;{ if (str == &str_undef || str->str_magic) return; str->str_magic = Str_new(75,namlen); str = str->str_magic; str->str_u.str_stab = stab; str->str_rare = how; if (name) str_nset(str,name,namlen);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -