// cstring.c // // by John D. de Boer #include "common.h" #include "cstring.h" // String copy and concatenation functions string fillstring(int LEN, char C) { char *R,*P,*E; if (LEN<1) return NULL; R=pointer(LEN + 1); E= R + LEN; for (P=R;P0) R=pointer(LEN + 1); else R=NULL; if (R) { E=R; if (L1) BlockMove(S1,E,L1); E+=L1; if (L2) BlockMove(S2,E,L2); E+=L2; *E=0; } if (D & 1) old(S1); if (D & 2) old(S2); return R; } string cat3(int D, char *S1, char *S2, char *S3) { int L1,L2,L3,LEN; char *R,*E; L1=length(S1); L2=length(S2); L3=length(S3); LEN= L1 + L2 + L3; if (LEN>0) R=pointer(LEN + 1); else R=NULL; if (R) { E=R; if (L1) BlockMove(S1,E,L1); E+=L1; if (L2) BlockMove(S2,E,L2); E+=L2; if (L3) BlockMove(S3,E,L3); E+=L3; *E=0; } if (D & 1) old(S1); if (D & 2) old(S2); if (D & 4) old(S3); return R; } string cat4(int D, char *S1, char *S2, char *S3, char *S4) { int L1,L2,L3,L4,LEN; char *R,*E; L1=length(S1); L2=length(S2); L3=length(S3); L4=length(S4); LEN= L1 + L2 + L3 + L4; if (LEN>0) R=pointer(LEN + 1); else R=NULL; if (R) { E=R; if (L1) BlockMove(S1,E,L1); E+=L1; if (L2) BlockMove(S2,E,L2); E+=L2; if (L3) BlockMove(S3,E,L3); E+=L3; if (L4) BlockMove(S4,E,L4); E+=L4; *E=0; } if (D & 1) old(S1); if (D & 2) old(S2); if (D & 4) old(S3); if (D & 8) old(S4); return R; } string cat5(int D, char *S1, char *S2, char *S3, char *S4, char *S5) { int L1,L2,L3,L4,L5,LEN; char *R,*E; L1=length(S1); L2=length(S2); L3=length(S3); L4=length(S4); L5=length(S5); LEN= L1 + L2 + L3 + L4 + L5; if (LEN>0) R=pointer(LEN + 1); else R=NULL; if (R) { E=R; if (L1) BlockMove(S1,E,L1); E+=L1; if (L2) BlockMove(S2,E,L2); E+=L2; if (L3) BlockMove(S3,E,L3); E+=L3; if (L4) BlockMove(S4,E,L4); E+=L4; if (L5) BlockMove(S5,E,L5); E+=L5; *E=0; } if (D & 1) old(S1); if (D & 2) old(S2); if (D & 4) old(S3); if (D & 8) old(S4); if (D & 16) old(S5); return R; } string leftstr(const char *S, int N) { return copy(S,lsr(N,length(S))); } string leftex(const char *S, int N) { return copy(S,gtr(0,length(S) - N)); } string rightstr(const char *S, int N) { int L; N=lsr(N,L=length(S)); return copy(S + L - N,N); } string rightex(const char *S, int N) { return copy(S + N,gtr(0,length(S) - N)); } string first(const char *S) { char *F; return (F=firstocc(' ',S)) ? copy(S,F - S) : copyof(S); } string firstrem(const char *S) { char *F; return (F=firstocc(' ',S)) ? copyof(F + 1) : NULL; } string last(const char *S) { char *L; return (L=lastocc(' ',S)) ? copyof(L + 1) : copyof(S); } string lastrem(const char *S) { char *L; return (L=lastocc(' ',S)) ? copy(S,L - S) : NULL; } string cstring(const uchar *PascalString) { if (!PascalString) return NULL; return leftstr((char *)PascalString + 1,*PascalString); } // String modification functions void nextword(char **S) { char *P,C; if (!S) return; P=*S; if (!P) return; while (1) { C=*P; if (!C || C==' ' || linebreak(C)) break; P++; } while (1) { C=*P; if (C!=' ' && !linebreak(C)) break; P++; } *S= C ? P : NULL; } void nextline(char **S) { char *P,C; if (!S || !(P=*S)) return; while (1) { C=*P; if (!C || linebreak(C)) break; P++; } while (1) { C=*P; if (C!=' ' && !linebreak(C)) break; P++; } *S= C ? P : NULL; } void capitalise(char *S) { if (!S) return; if (lowercase(*S)) (*S)+= 'A' - 'a'; } void makelowercase(char *S) { if (!S) return; for (;*S;S++) if (uppercase(*S)) (*S)+= 'a' - 'A'; } void makeuppercase(char *S) { if (!S) return; for (;*S;S++) if (lowercase(*S)) (*S)+= 'A' - 'a'; } void removechars(char *S, int REM) { int L; if (!S || REM<1) return; L=length(S); if (REM>L) REM=L; BlockMove(S + REM,S,L - REM + 1); } void repstring(string *A, const char *B, const char *C, bool Word) { int LA,LB,LC,KEEP; char *F,*New,*EndC; if (!A || !*A || !B || !*B) return; LA=length(*A); LB=length(B); LC=length(C); F=*A; while (1) { F=position(B,F); if (!F) return; if (Word && ((F>*A && !wordbreak(F[-1])) || (F[LB] && !wordbreak(F[LB])))) { F++; continue; } LA+= LC - LB; New=pointer(LA + 1); KEEP= F - *A; EndC= New + KEEP + LC; copyto(*A,New,KEEP); copyto(C,New + KEEP,LC); copyto(F + LB,EndC,LA - LC - KEEP); old(*A); *A=New; F=EndC; } } void replace(string *A, const char *B, const char *C) { repstring(A,B,C,0); } void repword(string *A, const char *B, const char *C) { repstring(A,B,C,1); } void repover(char *A, const char *B, const char *C) { int LA,LB,LC,DIFF; char *E; if (!A || !*A || !B || !*B) return; LA=length(A); LB=length(B); LC=lsr(length(C),LB); DIFF= LB - LC; E= A + LA; while (A0 && S[0]==' ') BlockMove(S + 1,S,--L); while (L>0 && S[L - 1]==' ') L--; while (L>3) { DB=position(" ",S); if (!DB) break; BlockMove(DB + 1,DB,S + (--L) - DB); } S[L]=0; } static void cleanquotes(char *S, int L, char Q) { char *B,*E; int N; if (!S || L<1) return; B=NULL; for (N=0;N=0;N--) if (quotechar(S[N]) && (N == L - 1 || S[N + 1]==' ')) { E= S + N; break; } if (B) *B=Q; if (E) *E=Q; if (!B || !E || B>=E) return; cleanquotes(B + 1,E - B - 1,Q=='"' ? '\'' : '"'); } void clean(char *S) { int L; if (!S) return; cleanspaces(S); L=length(S); while (L>0 && firstocc(S[L - 1],".!,")) S[--L]=0; cleanquotes(S,L,'"'); makelowercase(S); } void addcr(string *S) { if (!S) return; *S=cat(1,*S,"\r"); } // Decimal-string functions string intstring(long VAL, int FLD, char LR) { char Dig[64]; int DIG,i; bool Neg; char *R; Neg=(VAL<0); if (Neg) VAL=-VAL; for (DIG=0;VAL;VAL/=10) Dig[DIG++]= '0' + (VAL % 10); if (!DIG) Dig[DIG++]='0'; if (Neg) Dig[DIG++]='-'; FLD=gtr(FLD,DIG); R=pointer(FLD + 1); if (LR=='L') { for (i=0;i9) break; VAL*=10; VAL+=DIG; } *Q= Neg ? -VAL : VAL; return 1; } long value(const char *S) { bool Ok; long R; Ok=parseinteger(S,&R); if (!Ok) return 0; return R; } // Miscellaneous string functions char *oserrormsg(int E) { char *ME; ME=osmemerrormsg(E); if (ME) return ME; switch (E) { case dirFulErr: return "file directory is full"; case dskFulErr: return "all allocation blocks on the volume are full"; case eofErr: return "logical end-of-file reached during read operation"; case fnfErr: return "file not found"; case fnOpnErr: return "file not open"; case fBsyErr: return "file busy, dir. not empty, or working dir. control block open"; case ioErr: return "I/O error"; case nsvErr: return "specified volume doesn't exist"; case opWrErr: return "only one path can allow writing per file"; case permErr: return "attempt to open locked file for writing"; case posErr: return "attempt to position before start of file"; case rfNumErr: return "ref. num. specifies non-existent access path"; case wPrErr: return "volume is locked by a hardware setting"; case dupFNErr: return "duplicate filename (rename)"; case paramErr: return "error in user parameter list"; case errInvalidWindowPtr: return "bad WindowRef argument"; case errUnsupportedWindowAttributesForClass: return "unsupported window attributes for class"; } return cat(0,"system error #",fig(E)); } static const int romanwidth[10] = { 0,1,2,3,2,1,2,3,4,2 }; static const char roman1[4] = { 'I','X','C','M' }; static const char roman5[4] = { 'V','L','D','?' }; string romannumeral(int VAL) { int i,C[4],L,I,V; char *R,*P; if (VAL<0 || VAL>3999) return copyof("OVT OF RANGE"); if (VAL==0) return copyof("NVLL"); L=0; for (i=0;i<4;i++) { C[i]= VAL % 10; VAL/=10; L+=romanwidth[C[i]]; } R=pointer(L + 1); if (!R) return NULL; P=R; for (i=3;i>=0;i--) { I= C[i] % 5; V= C[i] / 5; if (I==4) { *(P++)=roman1[i]; *(P++)= V ? roman1[i + 1] : roman5[i]; continue; } if (V) *(P++)=roman5[i]; while (I--) *(P++)=roman1[i]; } if (R - P != L) halt("romannumeral() length error"); *P=0; return R; } // QuickDraw interface routines /* void odrawold(string S) { if (!S) return; drawstr(S); old(S); } void odrawint(long X) { odrawold(fig(X)); } void ocentreint(long X) { char *S; centrestr(S=fig(X)); old(S); } void odrawexponent(int EXP) { int SIZE,FONT,HORZ; CGrafPtr port; GDHandle gdh; GetGWorld(&port,&gdh); FONT=GetPortTextFont(port); SIZE=GetPortTextSize(port); if (!SIZE) error("drawexponent() error #1"); HORZ= SIZE / 4; Move(HORZ,-0.2 * SIZE); TextSize(0.75 * SIZE); TextFont(MonacoFontID); drawstr("x"); TextFont(FONT); Move(HORZ, 0.2 * SIZE); TextSize(SIZE); drawstr("10"); Move(HORZ,-0.4 * SIZE); TextSize(0.75 * SIZE); odrawint(EXP); Move(HORZ, 0.4 * SIZE); TextSize(SIZE); }*/ // String lists void initstringlist(stringlist *L) { if (!L) return; L->num=0; L->list=(string **)handle(0); } bool stringisinlist(const stringlist *L, const char *S) { int i; if (!L || !L->list || !S) return 0; for (i=0;inum;i++) if (streq(S,(*(L->list))[i])) return 1; return 0; } void addstringtolist(stringlist *L, string S) { if (!L || !L->list || !S) return; minimumsize((L->list),L->num + 1,sizeof(string)); (*(L->list))[L->num++]=S; } void purgestringlist(stringlist *L) { if (!L || !L->list) return; while (L->num>0) old((*(L->list))[--L->num]); } // Removing comments static void remcstylecomments(char *S) { char *B,*E,*N; if (!S || !*S) return; while (1) { B=position("/*",S); if (!B) return; E=position("*/",B + 2); if (!E) { *B=0; return; } E+=2; N=E; while (*N) N++; BlockMove(E,B,N - E + 1); S=B; } } static void remcppstylecomments(char *S) { char *B,*E,*N; if (!S || !*S) return; while (1) { B=position("//",S); if (!B) return; E=firstoccoflist("\n\r",B + 2); if (!E) { *B=0; return; } N=E; while (*N) N++; BlockMove(E,B,N - E + 1); S=B; } } void removecomments(char *S) { remcstylecomments(S); remcppstylecomments(S); } static char *firstextraspace(const char *S) { if (!S || !*S) return NULL; if (*S==' ') return (char *)S; while (1) { S=firstocc(' ',S); if (!S) return NULL; S++; if (!*S) return (char *)S - 1; if (*S==' ') return (char *)S; } return NULL; } void cleanwhitespace(char *S) { char *P,*B; if (!S || !*S) return; for (P=S;*P;P++) if ((*P>=8 && *P<=13) || *P=='\t'/*same as HT=9?*/) *P=' '; // could define func like linebreak()? P=firstextraspace(S); if (!P) return; B=P; while (*B==' ') B++; while (1) { char *E; bool Last; long L; E=firstextraspace(B); Last=!E; // E is now either the first extraneous space after B, if (!E) { E=B; while (*E) E++; E++; } // or the first byte after the terminating nul. L= E - B; BlockMove(B,P,L); if (Last) return; P+=L; B=E; while (*B==' ') B++; } } // dividing long strings into two void dividestring(string *S1, string *S2) { int i,j,L; char *S; if (!S1 || !*S1 || !S2 || *S2) return; S=*S1; L=length(S); i=j= L / 2; while (i>0 && S[i]!=' ' && S[j]!=' ') { i--; j++; } if (j= L - 1 || S[i]!=' ') return; *S1=leftstr(S,i); *S2=copyof(S + i + 1); old(S); }