I1 *PointAtListEntry(I8 entry_number, I1 *lst) { while (*lst && entry_number>0) { while (*lst) /* Advance to end of cur entry. */ lst++; lst++; /* Skip trailing zero */ entry_number--; if (*lst=='@') { /* Check for '@' alias list entry*/ entry_number++; lst++; } } if (entry_number) return NULL; else return lst; } I8 MatchListEntry(I1 *src, I1 *lst,I8 flags=0,I8 *ambiguity_overkill_ptr=NULL) /* RETURNS: -2 if Ambiguous, -1 if not found, else entry_number */ { I8 n,entry_num=0,result=-1,unutilized_src; I1 *s; BoolU4 exact_match=FALSE; n=StrLen(src); if (ambiguity_overkill_ptr) *ambiguity_overkill_ptr=n; while (*lst) { if (*lst=='@') { /* Check for '@' alias list entry*/ entry_num--; lst++; } s=src; if (flags & MLE_IGNORE_CASE) while (*s && ToUpper(*s) == ToUpper(*lst)) { s++; lst++; } else while (*s && *s==*lst) { s++; lst++; } unutilized_src=n-(s-src); if (!(*s)) { /* Did we reach end of sourcecout */ if (!(*lst)) { /* Did we reach end of list entrycout */ if (!ambiguity_overkill_ptr) return entry_num; /* Found Exact match */ result=entry_num; exact_match=TRUE; } else { if (result!=-1) { if (ambiguity_overkill_ptr) *ambiguity_overkill_ptr=0; if (!exact_match) result=-2; /* AMBIGUOUS RESPONSE unless later exact match*/ } else { if (!(flags & MLE_EXACT)) result=entry_num; } } } else { if (ambiguity_overkill_ptr && *ambiguity_overkill_ptr>(unutilized_src-1)) *ambiguity_overkill_ptr=unutilized_src-1; } while (*lst) /* Advance to end of cur entry. */ lst++; lst++; /* Skip trailing zero */ entry_num++; } if (ambiguity_overkill_ptr && result==-1) *ambiguity_overkill_ptr=0; return result; } void UndefinedSysText(I1 *name) { coutln "Error: Undefined SysText: '",name,"'."; throw(EXCEPT_UNDEF_SYSTEXT,name); } I1 *SysText(I1 *name) { SysHashEntry *temph=FindLocalHash(name,HTT_SYSTEXT); if (temph) return temph->user_data0; else UndefinedSysText(name); } I1 *SysTextSub(U8 sub,I1 *name) { SysHashEntry *temph=FindLocalHash(name,HTT_SYSTEXT); if (temph) return PointAtListEntry(sub,temph->user_data0); else UndefinedSysText(name); } I8 SysTextSubCount(I1 *name) { SysHashEntry *temph=FindLocalHash(name,HTT_SYSTEXT); if (temph) return temph->user_data1; else UndefinedSysText(name); } I8 MatchSysTextEntry(I1 *src, I1 *lst_name, I8 flags=0,I8 *ambiguity_overkill_ptr=NULL) { return MatchListEntry(src,SysText(lst_name), flags,ambiguity_overkill_ptr); } void PutSysText(I1 *name) { PutS(SysText(name)); } SysHashEntry *LoadStr(I1 *name, I1 *st) { SysHashEntry *temph; temph=MAllocZ(sizeof(SysHashEntry)); temph->type=HTT_SYSTEXT; temph->str=NewStr(name); temph->user_data0=NewStr(st); temph->user_data1=-1; AddSysHashEntry(temph,Fs->hash_table); return temph; } SysHashEntry *LoadList(I1 *name, I1 *st) { U8 cnt=0; I1 *ptr; SysHashEntry *temph; temph=MAllocZ(sizeof(SysHashEntry)); temph->type=HTT_SYSTEXT; temph->str=NewStr(name); ptr=st; while (*ptr) { while (*ptr++); cnt++; } temph->user_data0=MAlloc(ptr+1-st); MemCpy(temph->user_data0,st,ptr+1-st); temph->user_data1=cnt; AddSysHashEntry(temph,Fs->hash_table); return temph; } I8 Occurrences(I1 *src, I8 ch) { I8 i=0; while (*src) if (*src++ == ch) i++; return i; } I8 SpacesToTabs(I1 *dst2,I1 *src) { I1 *src2,*dst=dst2; I8 i,changed=0,space_cnt,space_cnt2,col=0; while (*src) { src2=src; space_cnt=0; while (*src2==CH_SPACE) { space_cnt++; src2++; } if (space_cnt<2) { if (*src==CH_TAB) col=0; else { col++; if (col==8) col=0; } *(dst++)=*(src++); } else { while (col+space_cnt>=8) { space_cnt2=8-col; if (space_cnt2==1) *(dst++)=CH_SPACE; else { *(dst++)=CH_TAB; changed=changed+(space_cnt2-1); } space_cnt=space_cnt-space_cnt2; col=0; } for (i=0;i=l-2) { temp=MAlloc(l<<1); MemCpy(temp,dst,i+1); Free(dst); l<<=1; dst=temp; } } col=j; } else { dst[col]=ch; if (col>=l-2) { temp=MAlloc(l<<1); MemCpy(temp,dst,col+1); Free(dst); l<<=1; dst=temp; } col++; } } dst[col]=0; return dst; } I1 *StrUtil(I1 *u, I8 mask) { I1 *src,*dst; I8 ch; src=u; if (mask & SU_REMOVE_LEADING) while (*src==CH_SPACE || *src==CH_SHIFT_SPACE || *src==CH_TAB) src++; dst=u; while (ch=*src++) { if (ch==CH_SPACE || ch==CH_SHIFT_SPACE || ch==CH_TAB) { if (!(mask & SU_REMOVE_SPACES)) { if (mask & SU_SINGLE_SPACE) { (*dst++) = CH_SPACE; while (ch= *src++ && (ch==CH_SPACE || ch==CH_SHIFT_SPACE || ch==CH_TAB) ); src--; } else (*dst++) = ch; } } else { if (!(mask & SU_REMOVE_CTRL_CHARS) || ch>=CH_SHIFT_SPACE) (*dst++)=ch; } } *dst=0; if (mask & SU_CAP_UNDERSCORES) { src=u; dst=u; while (*src) { *dst++=ToUpper(*src++); while (*src && *src!='_') *dst++=*src++; if (*src=='_') src++; } *dst=0; } if (mask & SU_REMOVE_TRAILING) while ( dst != u && (!*dst || *dst==CH_SPACE || *dst==CH_SHIFT_SPACE || *dst==CH_TAB)) (*dst--)=0; if (mask & SU_DISCARD_PARITY) for (dst=u;*dst;dst++) { ch=*dst; *dst=ch & 127; } if (mask & SU_TO_UPPER) for (dst=u;*dst;dst++) { ch=*dst; if (ch>=0x61 && ch<=0x7A) *dst = ch-0x20; } if (mask & SU_TO_LOWER) for (dst=u;*dst;dst++) { ch=*dst; if (ch>=0x41 && ch<=0x5A) *dst = ch+0x20; } if (mask & SU_SAFE_DOLLAR) for (dst=u;*dst;dst++) { ch=*dst; if (!Bt(safe_dollar_chars_bitmap,*dst)) *dst = '.'; } if (mask & SU_S2T) SpacesToTabs(u,u); return u; } I1 *MStrUtil(I1 *src,U8 flags) //Return a $LK,"MAlloc","MN:MAlloc"$()ed result from StrUtil { I1 *dst=NewStr(src),*dst2,*temp; StrUtil(dst,flags); if (flags & SU_T2S) { temp=TabsToSpaces(dst); Free(dst); dst=temp; } dst2=NewStr(dst); //Shorten Free(dst); return dst2; } I1 *RemoveFirstSeg(I1 *src, I1 *marker, I1 *dst=NULL) { I1 *temp,*temp1,ch; temp = src; temp1= dst; if (dst) { while ( (ch= *src++) && !Occurrences(marker,ch) ) *dst++=ch; *dst = 0; } else while ( (ch= *src++) && !Occurrences(marker,ch) ); if (ch) StrCpy(temp,src); else *temp=0; return temp1; } I1 *RemoveLastSeg(I1 *src, I1 *marker, I1 *dst=NULL) { I1 *temp; temp=src+StrLen(src); while (temp>src && !Occurrences(marker,*temp)) temp--; if (Occurrences(marker,*temp)) { if (dst) StrCpy(dst,temp+1); *temp=0; } else { if (dst) StrCpy(dst,src); *src=0; } return dst; } I1 *SearchStr(I1 *src,I1 *pattern,U8 flags=0) { BoolU4 cont; U1 *src2; I1 *saved_src=src; I8 plen=StrLen(pattern); do { cont=FALSE; if (flags & SS_IGNORE_CASE) src=StrIStr(src,pattern); else src=StrStr(src,pattern); if (src && flags & SS_WHOLE_LABELS) { src2=src+plen; if (Bt(alpha_numeric_bitmap,*src2)) { src++; //TODO: Numbers could be false negative if (*src) cont=TRUE; else src=NULL; } else { if (src!=saved_src) { src2=src-1; if (Bt(alpha_numeric_bitmap,*src2)) { src++; if (*src) cont=TRUE; else src=NULL; } } } } } while (cont); return src; } BoolU8 WildCardMatch(I1 *wild_st,I1 *src_st) { U8 ch1,ch2; while (TRUE) { if ( !(ch1 = *src_st++)) { if (*wild_st) return FALSE; else return TRUE; } else { if ( !(ch2 = *wild_st++)) return FALSE; else { if (ch2 == '*') { if (!(ch2 = *wild_st++)) return TRUE; while (ch2 != ch1) if (!(ch1 = *src_st++)) return FALSE; } else if (ch2!='?') if (ch1!=ch2) return FALSE; } } } } BoolU8 WildFileNameList(I1 *wild_st,I1 *src_st) { BoolU4 result=FALSE; I1 *buf1=NewStr(wild_st), *buf2=MAlloc(StrLen(wild_st)+1); while (TRUE) { RemoveFirstSeg(buf1,";",buf2); if (*buf2) { if (*buf2=='~') { if (WildCardMatch(buf2+1,src_st)) { result=FALSE; break; } } else { if (WildCardMatch(buf2,src_st)) result=TRUE; } } else break; } Free(buf1); Free(buf2); return result; } I1 *Add2Str(I1 *base,I1 *addition) //Concatinates a string onto another string. //Returns new string. //Doubles length when it grows. { I1 *result; I8 blen=StrLen(base),alen=StrLen(addition); I8 bmem=MSize(base); if (blen+alen+1>bmem) { result=MAlloc(bmem<<1+alen+4); MemCpy(result,base,blen); StrCpy(result+blen,addition); Free(base); } else { result=base; StrCpy(result+blen,addition); } return result; } void CheckLTPartition(LTPartition *p) { if (!p || p->ch_L!='L' || p->ch_P!='P' || p->ch_E!='E') throw(EXCEPT_PARTITION,9); } I1 PartitionToDrive(LTPartition *p=NULL) { if (!p) p=Fs->cur_partition; CheckLTPartition(p); return p->drive; } LTPartition *DriveToPartition(I1 drive=0) { LTPartition *p; if (!drive) p=Fs->cur_partition; else if (drive==':') p=default_partition; else p=drive_to_partition[ToUpper(drive)-'A']; CheckLTPartition(p); return p; } void CheckLTBlkDev(LTBlkDev *bdev) { if (!bdev || bdev->ch_L!='L' || bdev->ch_B!='B' || bdev->ch_D!='D') throw(EXCEPT_BLKDEV,1); if (bdev->type<=LTBDT_NULL || bdev->type>LTBDT_NON_LT_FILE) throw(EXCEPT_BLKDEV,2); } LTBlkDev *DriveToBlkDev(I1 drive=0) { LTPartition *p=DriveToPartition(drive); LTBlkDev *bdev=p->bdev; CheckLTBlkDev(bdev); return bdev; } BoolU8 DriveIsWritable(I1 drive=0) { LTBlkDev *bdev=DriveToBlkDev(drive); if (bdev->flags & LTBDF_READ_ONLY) return FALSE; else return TRUE; } I1 *CurDir() { I1 *st=MAlloc(StrLen(Fs->cur_dir)+3); st[0]=PartitionToDrive; st[1]=':'; StrCpy(st+2,Fs->cur_dir); return st; } I1 *AbsoluteDirName(I1 *name) { I8 maxlen; I1 drive[3],*hdir,*cur_dir,*buf2,*buf3,*buf,*my_name,*temp_name; if (!Fs->cur_dir) return NewStr(name); if (!*Fs->cur_dir) return NewStr(name); my_name=MStrUtil(name, SU_REMOVE_LEADING|SU_REMOVE_TRAILING| SU_DISCARD_PARITY|SU_REMOVE_CTRL_CHARS); temp_name=my_name; drive[0]=PartitionToDrive; drive[1]=':'; drive[2]=0; if (*my_name && my_name[1]==':') { if (*my_name==':') drive[0]=default_drive; else drive[0]=*my_name; my_name=my_name+2; cur_dir=NewStr("/"); } else cur_dir=NewStr(Fs->cur_dir); if (*my_name=='/') { Free(cur_dir); cur_dir=NewStr("/"); my_name++; } buf2=NewStr(my_name); maxlen=StrLen(cur_dir)+1+StrLen(buf2)+1; buf3=MAlloc(maxlen); buf =MAlloc(maxlen); StrCpy(buf3,cur_dir); while (*buf2) { RemoveFirstSeg(buf2,"/",buf); if (!*buf) StrCpy(buf3,"/"); else if (!StrCmp(buf,"..")) { RemoveLastSeg(buf3,"/"); if (!*buf3) StrCpy(buf3,"/"); } else if (!StrCmp(buf,".")) { ; } else if (*buf) { if (!StrCmp(buf,"HOME")) { Free(buf3); hdir=HomeDirStr; buf3=MAlloc(maxlen+StrLen(hdir)); StrCpy(buf3,hdir+2); Free(hdir); drive[0]=default_drive; } else { if (StrCmp(buf3,"/")) StrCat(buf3,"/"); StrCat(buf3,buf); } } } Free(cur_dir); cur_dir=MAlloc(StrLen(buf3)+3); StrCpy(cur_dir,drive); StrCpy(cur_dir+2,buf3); Free(buf); Free(buf2); Free(buf3); Free(temp_name); return cur_dir; } I1 *AbsoluteFileName(I1 *name) { I1 *buf,*buf2,*buf3,*my_name,*temp_name,*temp_buf; my_name=MStrUtil(name, SU_REMOVE_LEADING|SU_REMOVE_TRAILING| SU_DISCARD_PARITY|SU_REMOVE_CTRL_CHARS); temp_name=my_name; buf=NewStr(my_name); temp_buf=buf; if (*buf && buf[1]==':') { buf+=2; my_name+=2; } buf2=MAlloc(StrLen(temp_name)+1); RemoveLastSeg(buf,"/",buf2); if (*my_name=='/' && !*buf) StrCpy(buf,"/"); buf3=AbsoluteDirName(temp_buf); Free(temp_buf); buf=MAlloc(StrLen(buf3)+1+StrLen(buf2)+1); StrCpy(buf,buf3); if (buf[StrLen(buf)-1]!='/') StrCat(buf,"/"); StrCat(buf,buf2); Free(buf2); Free(buf3); Free(temp_name); return buf; } I1 *ChangeExtension(I1 *name,I1 *extension) { I1 *result=MAlloc(StrLen(name)+1+StrLen(extension)+1); StrCpy(result,name); if (Occurrences(name,'.')) RemoveLastSeg(result,"."); StrCat(result,"."); StrCat(result,extension); return result; } I1 *DefaultExtension(I1 *name,I1 *extension) { I1 *result=MAlloc(StrLen(name)+1+StrLen(extension)+1); StrCpy(result,name); if (!Occurrences(name,'.')) { StrCat(result,"."); StrCat(result,extension); } return result; } U8 FileAttr(I1 *name,U8 attr=0) { I1 *ptr=name,ch=0; while (*ptr && *ptr!='.') ptr++; if (*ptr=='.') ch=ToUpper(ptr[StrLen(ptr)-1]); if (ch=='Z') attr|=LT_ATTR_COMPRESSED; else attr&=~LT_ATTR_COMPRESSED; //TODO: temporary attr|=LT_ATTR_CONTIGUOUS; return attr; } BoolU8 CheckFileName(I1 *name) { I1 *ptr=name; if (!name) return FALSE; if (!*ptr) return FALSE; if (*ptr=='.') { if (!ptr[1]) return TRUE; if (ptr[1]=='.' && !ptr[2]) return TRUE; } if (StrLen(name)>LT_MAX_FILENAME_LEN) return FALSE; while (*ptr) if (!Bt(filename_chars_bitmap,*ptr++)) return FALSE; return TRUE; } I8 AtoI(I1 *st,I8 radix=10,I1 **end_ptr=NULL) { BoolU4 neg=FALSE; I1 ch; I8 result=0,k=0; if (radix<2||radix>36) return 0; while (*st==CH_SPACE || *st==CH_SHIFT_SPACE || *st==CH_TAB) st++; if (*st=='-') { st++; neg=TRUE; } if (*st=='+') st++; while (ch=ToUpper(*st++)) { k++; if (radix==10) { if (ch>='0' && ch<='9') result=result*10+ch-'0'; else if (k==2 && !result) { if (ch=='X') radix=16; else if (ch=='B') radix=2; else if (ch=='o') radix=8; else break; } else break; } else if (radix>10) { if (ch>='0' && ch<='9') result=result*radix+ch-'0'; else if (ch>='A' && ch<='A'+radix-11) result=result*radix+ch-'A'+10; else break; } else { if (ch>='0' && ch<='0'+radix-1) result=result*radix+ch-'0'; else break; } } if (end_ptr) *end_ptr=st-1; return (neg)? -result:result; }