home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga GigaPD 3
/
Amiga_GigaPD_v3_3of3.iso
/
fred_fish
/
fish_601-700_lha
/
fish_624.lha
/
CSH
/
csh519s.lha
/
sub.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-24
|
23KB
|
1,233 lines
/*
* SUB.C
*
* (c)1986 Matthew Dillon 9 October 1986
*
* Version 2.07M by Steve Drew 10-Sep-87
* Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
* Version 5.00L by Urban Mueller 17-Feb-91
*
*/
#include "shell.h"
static void del_history( void );
static int dnext( DPTR *dp, char **pname, int *stat);
static char *svfile( char *s1, char *s2, FIB *fib);
static void quicksort( char **av, int n );
void
seterr( int err )
{
static int LastErr;
char buf[32], *val;
int stat=0;
Lastresult=err;
if( LastErr!=err ) {
LastErr=err;
sprintf(buf, "%d", err);
set_var(LEVEL_SET, v_lasterr, buf);
if( val=get_var(LEVEL_SET, v_stat))
stat = atoi(val);
if (stat < Lastresult) set_var(LEVEL_SET, v_stat, buf);
}
}
char *
next_word( char *str )
{
while (*str && ! ISSPACE(*str)) ++str;
while (*str && ISSPACE(*str)) ++str;
return str;
}
/*
* FREE(ptr) --frees without actually freeing, so the data is still good
* immediately after the free.
*/
void
Free( void *ptr )
{
static char *old_ptr;
if (old_ptr) free (old_ptr);
old_ptr = ptr;
}
/*
* Add new string to history (H_head, H_tail, H_len,
* S_histlen
*/
void
add_history( char *str )
{
HIST *hist;
char *get;
for( get=str; *get; get++ )
if( (*get&127)<' ')
*get=' ';
if (H_head != NULL && !strcmp(H_head->line, str))
return;
while (H_len > S_histlen)
del_history();
hist = (HIST *)salloc (sizeof(HIST));
if (H_head == NULL) {
H_head = H_tail = hist;
hist->next = NULL;
} else {
hist->next = H_head;
H_head->prev = hist;
H_head = hist;
}
hist->prev = NULL;
hist->line = salloc (strlen(str) + 1);
strcpy (hist->line, str);
++H_len;
H_num= H_tail_base+ H_len;
}
static void
del_history()
{
if (H_tail) {
--H_len;
++H_tail_base;
free (H_tail->line);
if (H_tail->prev) {
H_tail = H_tail->prev;
free (H_tail->next);
H_tail->next = NULL;
} else {
free (H_tail);
H_tail = H_head = NULL;
}
}
}
char *
get_history( char *ptr )
{
int hnum=find_history( ptr+1, 1 );
HIST *hist;
for( hist=H_head; hist && hnum--; hist=hist->next) ;
if( !hist ) {
fprintf(stderr,"History failed\n");
return "";
}
fprintf(stderr, "%s\n", hist->line );
return hist->line;
}
int
find_history( char *ptr, int min )
{
HIST *hist;
int len, num;
if ( *ptr=='!' )
return 1;
else if( *ptr=='-' )
return atoi(ptr+1);
else if (*ptr >= '0' && *ptr <= '9')
return H_len-(atoi(ptr)-H_tail_base)-1;
len = strlen(ptr);
for (hist=H_head,num=0; hist; hist=hist->next, num++)
if ( !Strncmp(hist->line, ptr, len) && num>=min)
return num;
return -1;
}
void
replace_head( char *str )
{
if (str && strlen(str) && H_head) {
free (H_head->line);
H_head->line = salloc (strlen(str)+1);
strcpy (H_head->line, str);
}
}
void
pError(char *str )
{
int ierr = (long)IoErr();
ierror(str, ierr);
}
ierror( char *str, int err )
{
PERROR *per = Perror;
setioerror(err);
if (err) {
for (; per->errstr; ++per) {
if (per->errnum == err) {
fprintf (stderr, "%s%s%s\n",
per->errstr,
(str) ? ": " : "",
(str) ? str : "");
return err;
}
}
fprintf (stderr, "Unknown DOS error %d: %s\n", err, (str) ? str : "");
}
return err;
}
void
setioerror( int err )
{
static int LastIoError=-1;
char buf[20];
IoError=err;
if( IoError<0 ) IoError=0;
if( LastIoError!=IoError) {
LastIoError=IoError;
sprintf(buf, "%d", IoError);
set_var(LEVEL_SET, v_ioerr, buf);
}
}
char *
ioerror(int num)
{
PERROR *per = Perror;
for ( ; per->errstr; ++per)
if (per->errnum == num)
return per->errstr;
return NULL;
}
/*
* Disk directory routines
*
* dptr = dopen(name, stat)
* DPTR *dptr;
* char *name;
* int *stat;
*
* dnext(dptr, name, stat)
* DPTR *dptr;
* char **name;
* int *stat;
*
* dclose(dptr) -may be called with NULL without harm
*
* dopen() returns a struct DPTR, or NULL if the given file does not
* exist. stat will be set to 1 if the file is a directory. If the
* name is "", then the current directory is openned.
*
* dnext() returns 1 until there are no more entries. The **name and
* *stat are set. *stat != 0 if the file is a directory.
*
* dclose() closes a directory channel.
*
*/
DPTR *
dopen( char *name, int *stat)
{
DPTR *dp;
IoError=0;
*stat = 0;
dp = (DPTR *)salloc(sizeof(DPTR));
if (*name == '\0')
dp->lock = DupLock(Myprocess->pr_CurrentDir);
else
dp->lock = Lock (name,ACCESS_READ);
if (dp->lock == NULL) {
IoError=IoErr();
free (dp);
return NULL;
}
dp->fib = (FIB *)SAllocMem((long)sizeof(FIB), MEMF_PUBLIC);
if (!Examine (dp->lock, dp->fib)) {
pError (name);
dclose (dp);
return NULL;
}
if (dp->fib->fib_DirEntryType >= 0) *stat = 1;
return dp;
}
static int
dnext( DPTR *dp, char **pname, int *stat)
{
if (dp == NULL) return (0);
if (ExNext (dp->lock, dp->fib)) {
*stat = 0;
if( dp->fib->fib_DirEntryType >= 0)
*stat= dp->fib->fib_DirEntryType!=ST_USERDIR ? 2 : 1;
*pname = dp->fib->fib_FileName;
return 1;
}
return 0;
}
int
dclose( DPTR *dp )
{
if (dp == NULL)
return 1;
if (dp->fib)
FreeMem (dp->fib,(long)sizeof(*dp->fib));
if (dp->lock)
UnLock (dp->lock);
free (dp);
return 1;
}
int
isdir( char *file )
{
DPTR *dp;
int stat;
stat = 0;
if (dp = dopen (file, &stat))
dclose(dp);
return (stat!=0);
}
void
free_expand( char **av )
{
char **get = av;
if (av) {
while (*get)
free (*get++-sizeof(FILEINFO));
free (av);
}
}
/*
* EXPAND(base,pac)
* base - char * (example: "df0:*.c")
* pac - int * will be set to # of arguments.
*
* 22-May-87 SJD. Heavily modified to allow recursive wild carding and
* simple directory/file lookups. Returns a pointer to
* an array of pointers that contains the full file spec
* eg. 'df0:c/sear*' would result in : 'df0:C/Search'
*
* Now no longer necessary to Examine the files a second time
* in do_dir since expand will return the full file info
* appended to the file name. Set by formatfile().
*
* Caller must call free_expand when done with the array.
*
* base bname = ename =
* ------ ------- -------
* "*" "" "*"
* "!*.info" "" "*.info" (wild_exclude set)
* "su*d/*" "" "*" (tail set)
* "file.*" "" "file.*"
* "df0:c/*" "df0:c" "*"
* "" "" "*"
* "df0:.../*" "df0:" "*" (recur set)
* "df0:sub/.../*" "df0:sub" "*" (recur set)
*
* ---the above base would be provided by execom.c or do_dir().
* ---the below base would only be called from do_dir().
*
* "file.c" "file.c" "" if (dp == 0) fail else get file.c
* "df0:" "df0:" "*"
* "file/file" "file/file" "" if (dp == 0) fail
* "df0:.../" "df0:" "*" (recur set)
*
*/
char **
expand( char *base, int *pac )
{
char *ptr;
char **eav = (char **)salloc(sizeof(char *) * (2));
short eleft, eac;
char *name;
char *bname, *ename, *tail;
int stat, recur, scr, bl;
DPTR *dp;
PATTERN *pat;
IoError = *pac = recur = eleft = eac = 0;
base = strcpy(salloc(strlen(base)+1), base);
for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);
if (!*ptr) /* no wild cards */
--ptr;
else
for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
if (ptr < base) {
bname = strcpy (salloc(1), "");
} else {
scr = ptr[1];
ptr[1] = '\0';
if (!strcmp(ptr-3,".../")) {
recur = 1;
*(ptr-3) = '\0';
}
bname = strcpy (salloc(strlen(base)+2), base);
ptr[1] = scr;
}
bl = strlen(bname);
ename = ++ptr;
for (; *ptr && *ptr != '/'; ++ptr);
scr = *ptr;
*ptr = '\0';
if (scr) ++ptr;
tail = ptr;
if ((dp = dopen (bname, &stat)) == NULL || (stat == 0 && *ename)) {
free (bname);
free (base);
free (eav);
return NULL;
}
if (!stat) { /* eg. 'dir file' */
char *p,*s;
for(s = p = bname; *p; ++p) if (*p == '/' || *p == ':') s = p;
if (*s=='/' || *s==':') s++;
*s=0;
eav[eac++] = svfile(bname,dp->fib->fib_FileName,dp->fib);
goto done;
}
if (!*ename) ename = "*"; /* eg. dir df0: */
if (*bname && bname[bl-1] != ':' && bname[bl-1] != '/') { /* dir df0:c */
bname[bl] = '/';
bname[++bl] = '\0';
}
pat= compare_preparse( ename, 0 );
while ((dnext (dp, &name, &stat)) && !breakcheck()) {
int match = compare_ok( pat, name);
if (match && (recur || !*tail)) {
if (eleft < 2) {
char **scrav = (char **)salloc(sizeof(char *) * (eac + 10));
memmove (scrav, eav, (eac + 1) << 2);
free (eav);
eav = scrav;
eleft = 10;
}
eav[eac++] = svfile(bname,name,dp->fib);
--eleft;
}
if ((*tail && match) || recur) {
int alt_ac;
char *search, **alt_av, **scrav;
BPTR lock;
if (stat!=1) /* expect more dirs, but this not a dir */
continue;
lock = CurrentDir (dp->lock);
search = salloc(strlen(ename)+strlen(name)+strlen(tail)+6);
strcpy (search, name);
strcat (search, "/");
if (recur) {
strcat(search, ".../");
strcat(search, ename);
}
strcat (search, tail);
scrav = alt_av = expand (search, &alt_ac);
free(search);
CurrentDir (lock);
if (scrav) {
while (*scrav) {
int l;
if (eleft < 2) {
char **scrav = (char **)salloc(sizeof(char *)*(eac+10));
memmove ( scrav, eav, (eac + 1) << 2);
free (eav);
eav = scrav;
eleft = 10;
}
l = strlen(*scrav);
eav[eac] = salloc(bl+l+1+sizeof(FILEINFO));
memcpy( eav[eac], *scrav-sizeof(FILEINFO),sizeof(FILEINFO));
eav[eac]+=sizeof(FILEINFO);
strcpy( eav[eac], bname);
strcat( eav[eac], *scrav);
free (*scrav-sizeof(FILEINFO));
++scrav;
--eleft, ++eac;
}
free (alt_av);
}
}
}
compare_free( pat );
done:
dclose (dp);
*pac = eac;
eav[eac] = NULL;
free (bname);
free (base);
if (eac) {
int i, j, len;
QuickSort( eav, eac );
for( i=0; i<eac-1; i++ ) {
len=strlen(eav[i]);
for( j=i+1; j<eac && !Strncmp(eav[i],eav[j],len); j++ )
if( !Strcmp(eav[j]+len,".info")) {
((FILEINFO*)eav[i]-1)->flags |= INFO_INFO;
break;
}
}
return eav;
}
free (eav);
return NULL;
}
char *
strupr( char *s )
{
char *old=s;
while (*s) *s=toupper(*s), s++;
return old;
}
char *
strlwr( char *s )
{
char *old=s;
while (*s) *s=tolower(*s), s++;
return old;
}
/*
* Compare a wild card name with a normal name
*/
extern void *PatternBase;
PATTERN *
compare_preparse( char *wild, int casedep )
{
struct pattern *pat=salloc(256);
pat->casedep=casedep;
if (pat->queryflag=(*wild=='&')) wild++;
if (*wild=='!') *wild='~';
if( !casedep ) strlwr( wild );
if( !PatternBase )
PreParse(wild, pat->pattern);
else
if((pat->patptr= AllocPattern( wild, 0 ))<0) {
free(pat);
return NULL;
}
return pat;
}
int
compare_ok( PATTERN *pat, char *name )
{
char buf[260], *lowname=name;
if( !pat )
return 0;
if (!pat->casedep) {
strncpy(buf,name,256);
strlwr(buf);
lowname=buf;
}
if( !PatternBase ) {
if ( !PatternMatch(pat->pattern,lowname))
return 0;
} else {
if( MatchThePattern(pat->patptr,lowname )!=1)
return 0;
}
if (pat->queryflag) {
printf("Select %s%-16s%s [y/n] ? ",o_hilite,name,o_lolite);
gets(buf);
return (toupper(*buf)=='Y');
}
return 1;
}
void
compare_free( PATTERN *pat )
{
if( !pat )
return;
if( PatternBase )
FreePattern(pat->patptr);
free( pat );
}
#if 0
int
compare_strings( char *pattern, char *str, int casedep )
{
PATTERN *pat=compare_preparse( pattern, casedep );
int ret=compare_ok(pat,str);
compare_free(pat);
return ret;
}
#endif
static char *
svfile( char *s1, char *s2, FIB *fib)
{
FILEINFO *info=salloc(sizeof(FILEINFO)+strlen(s1)+strlen(s2)+1);
char *p = (char *)(info+1);
strcpy(p, s1);
strcat(p, s2);
info->flags = fib->fib_Protection | (*fib->fib_Comment ? 1<<30 : 0);
info->size = fib->fib_DirEntryType<0 ? fib->fib_Size : -1;
info->blocks= fib->fib_DirEntryType<0 ? fib->fib_NumBlocks : 0;
info->date = fib->fib_Date;
info->class[0]=1;
return p;
}
static char *FullPath;
static FIB *PrevFile;
static int (*Action)(long, char *, char *);
static long Mask;
static int Queued=0;
static int
passinfo( FIB *fib )
{
char *p = (char *)(PrevFile+1);
int oldlen, ret=0;
if( Queued ) {
oldlen=strlen(FullPath);
TackOn( FullPath, p );
ret=(*Action)( Mask, p, FullPath );
FullPath[oldlen]=0;
Queued=0;
}
if( fib ) {
*PrevFile= *fib;
strcpy( p, fib->fib_FileName);
Queued=1;
}
return ret;
}
static int
nu_recurse( char *name )
{
BPTR lock, cwd;
FIB *fib =(FIB *)SAllocMem(sizeof(FIB),MEMF_PUBLIC);
int oldlen=strlen( FullPath ), ret=0;
TackOn( FullPath, name );
if (lock=Lock(name,ACCESS_READ)) {
if( Mask & SCAN_DIRENTRY )
(*Action)( SCAN_DIRENTRY, name, FullPath );
cwd =CurrentDir(lock);
if (Examine(lock, fib)) {
while (ExNext(lock, fib) && !breakcheck()) {
if (fib->fib_DirEntryType==ST_USERDIR) {
if ( Mask & SCAN_RECURSE ) {
if(!ret && !(ret=passinfo( NULL )))
ret=nu_recurse(fib->fib_FileName);
}
if ( Mask & SCAN_DIR )
if( !ret )
ret=passinfo( fib );
} else if( fib->fib_DirEntryType<0 && Mask & SCAN_FILE )
if( !ret )
ret=passinfo( fib );
}
if( breakcheck() )
ret=5;
if( !ret )
passinfo( NULL );
}
UnLock(CurrentDir(cwd));
if( Mask & SCAN_DIREND )
(*Action)( SCAN_DIREND, name, FullPath );
} else
pError(name);
FullPath[oldlen]=0;
FreeMem(fib, sizeof(FIB));
return ret;
}
int
newrecurse(int mask, char *name, int (*action)FUNCARG(long,char *,char *))
{
int ret;
FullPath = salloc( 512 );
PrevFile = salloc( sizeof(FIB)+108+1 );
Action = action;
Mask = mask;
Queued = 0;
*FullPath= 0;
ret=nu_recurse( name );
free( PrevFile );
free( FullPath );
return ret;
}
/* Sort routines */
static int reverse, factor;
int
cmp( FILEINFO *s1, FILEINFO *s2)
{
return Strcmp( (char *)(s1+1), (char *)(s2+1) );
}
int
sizecmp( FILEINFO *s1, FILEINFO *s2)
{
return s2->size - s1->size;
}
int
datecmp( FILEINFO *s1, FILEINFO *s2 )
{
int r;
struct DateStamp *d1=&s1->date, *d2=&s2->date;
if( !(r= d2->ds_Days - d1->ds_Days))
if( !(r=d2->ds_Minute - d1->ds_Minute ) )
r=d2->ds_Tick - d1->ds_Tick;
return r;
}
int
numcmp( FILEINFO *s1, FILEINFO *s2 )
{
return atoi((char *)(s1+1))-atoi((char *)(s2+1));
}
static void
enterclass( FILEINFO *info )
{
char *class, *iclass=info->class, *t;
if( *iclass==1 ) {
if( class=getclass( (char *)(info+1))) {
strncpy( iclass, class, 11 );
iclass[11]=0;
if( t=index(iclass,0xA0))
*t=0;
} else
iclass[0]=0;
}
}
int
classcmp( FILEINFO *info1, FILEINFO *info2 )
{
int r;
enterclass( info1 );
enterclass( info2 );
r= Strcmp( info1->class, info2->class );
if( !r ) r=Strcmp((char *)(info1+1),(char *)(info2+1));
return r;
}
void
QuickSort( char *av[], int n)
{
reverse=factor=0;
DirQuickSort( av, n, cmp, 0, 0 );
}
static int (*compare)(FILEINFO *, FILEINFO *);
static int
docompare(char *s1,char *s2)
{
FILEINFO *i1=(FILEINFO *)s1-1, *i2=(FILEINFO *)s2-1;
int r=(*compare)( i1,i2 );
if( reverse ) r =-r;
if( factor ) r+= factor*((i2->size<0) - (i1->size<0));
return r;
}
#define QSORT
void
DirQuickSort( char *av[], int n, int (*func)(FILEINFO *,FILEINFO *), int rev, int fac)
{
reverse=rev; compare=func; factor=fac;
quicksort( av, n-1 );
}
static void
quicksort( char **av, int n )
{
char **i, **j, *x, *t;
if( n>0 ) {
i=av; j=av+n; x=av[ n>>1 ];
do {
while( docompare(*i,x)<0 ) i++;
while( docompare(x,*j)<0 ) --j;
if( i<=j )
{ t=*i; *i=*j; *j=t; i++; j--; }
} while( i<=j );
if( j-av < av+n-i ) {
quicksort( av, j-av );
quicksort( i , av+n-i);
} else {
quicksort( i , av+n-i);
quicksort( av, j-av );
}
}
}
int
filesize( char *name )
{
BPTR lock;
struct FileInfoBlock *fib;
int len=0;
if( lock = Lock (name,ACCESS_READ)) {
if( fib=(struct FileInfoBlock *)AllocMem(sizeof(*fib),MEMF_PUBLIC)) {
if (Examine (lock, fib))
len=fib->fib_Size;
FreeMem( fib, sizeof(*fib));
}
UnLock(lock);
}
return len;
}
#ifndef MIN
#define MIN(x,y) ((x)<(y)?(x):(y))
#endif
char **
and( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
{
char **av=(char **)salloc(MIN(ac1,ac2)*sizeof(char *) ), *str;
int i, j, k=0;
for( i=0; i<ac1; i++ )
for( j=0, str=base ? (char*)BaseName(av1[i]) : av1[i]; j<ac2; j++ )
if( !Strcmp(str, base ? (char*)BaseName(av2[j]) : av2[j]))
av[k++]=av1[i];
*ac=k;
return av;
}
char **
without( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
{
char **av=(char **)salloc(ac1*sizeof(char *) ), *str;
int i, j, k=0;
for( i=0; i<ac1; i++ ) {
for( j=0, str=base ? (char*)BaseName(av1[i]) : av1[i]; j<ac2; j++ )
if( !Strcmp(str, base ? (char*)BaseName(av2[j]) : av2[j] ) )
break;
if( j==ac2 )
av[k++]=av1[i];
}
*ac=k;
return av;
}
char **
or( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
{
char **av=(char **)salloc((ac1+ac2)*sizeof(char *) ), *str;
int i, j, k=0;
for( i=0; i<ac1; i++ )
av[k++]=av1[i];
for( i=0; i<ac2; i++ ) {
for( j=0, str=base ? (char*)BaseName(av2[i]) : av2[i]; j<ac1; j++ )
if( !Strcmp(str, base ? (char*)BaseName(av1[j]) : av1[j] ) )
break;
if( j==ac1 )
av[k++]=av2[i];
}
*ac=k;
return av;
}
void
clear_archive_bit( char *name )
{
DPTR *dp;
int stat;
if(dp = dopen(name,&stat) ) {
SetProtection( name, dp->fib->fib_Protection&~FIBF_ARCHIVE);
dclose( dp );
}
}
char *
itoa( int i )
{
static char buf[20];
char *pos=buf+19;
int count=4, flag=0;
if( i<0 )
flag=1, i=-i;
do {
if( !--count )
count=3, *--pos=',';
*--pos= i%10+'0';
} while( i/=10 );
if( flag )
*--pos='-';
return pos;
}
char *
itok( int i )
{
static char buf[16], which;
char *exp=" KMG", *ptr= buf+(which=8-which);
do
i=(i+512)/1024, exp++;
while( i>1024 );
sprintf( ptr,"%d%c",i,*exp);
return ptr;
}
char *
next_a0( char *str )
{
while( *str && (UBYTE)*str!=0xA0 && *str!='=' && *str!=',') str++;
if( *str )
return str+1;
return NULL;
}
static int
gethex( char *str, int l )
{
int i, val=0, n, c;
if( *str=='.' ) return l==2 ? 256 : 0;
for( i=0; i<l || !l; i++ ) {
c=*str++;
if ( c>='0' && c<='9' ) n=c-'0';
else if( c>='a' && c<='f' ) n=c-'a'+10;
else if( c>='A' && c<='F' ) n=c-'A'+10;
else break;;
val=16*val+n;
}
return (l && i!=l) ? -1 : val;
}
strwrdcmp( char *str, char *wrd )
{
PATTERN *pat;
int ret;
char *ind=index(wrd,0xA0);
if( ind ) *ind=0;
pat=compare_preparse( wrd,0 );
ret=compare_ok(pat,str);
compare_free( pat );
if( ind ) *ind=0xA0;
return !ret;
}
int
wrdlen( char *str )
{
char *old=str;
while( *str && (UBYTE)*str!=0xA0 ) str++;
return str-old;
}
char *
getclass(char *file)
{
CLASS *cl;
char *class, *str, *arg, *get, *buf;
int offs, byte, len, fail;
BPTR fh;
if( isdir(file) ) return "dir";
if( !(buf=calloc(1024,1))) return NULL;
if( !(fh=Open(file,MODE_OLDFILE))) return NULL;
len=Read( fh,buf,1023);
Close(fh);
for( cl=CRoot; cl; cl=cl->next ) {
class=cl->name;
if(!(str=next_a0(cl->name))) continue;
while( str ) {
if(!(arg=next_a0( str ))) goto nextclass;
switch( *str ) {
case 's':
if( (offs=strlen(file)-wrdlen(arg))<0 ) break;
if( !strwrdcmp(file+offs,arg)) goto found;
break;
case 'n':
if( !strwrdcmp(BaseName(file),arg) ) goto found;
break;
case 'd':
goto found;
case 'o':
offs=gethex(arg,0);
if( !(arg=index(arg,','))) goto nextclass;
if( offs>len-10 ) break;
for( get=buf+offs, ++arg; (byte=gethex(arg,2))>=0; arg+=2 )
if( (UBYTE)*get++!=byte && byte!=256 )
goto nexttry;
goto found;
case 'c':
if( !len )
break;
for( get=buf, fail=0; get<buf+len; get++ )
if( *get<9 || *get>13 && *get<32 || *get>127 )
fail++;
if( fail*8>len )
break;
goto found;
case 'i':
break;
case 'a':
goto nextclass;
default:
goto nextclass;
}
nexttry: str=next_a0(arg);
}
nextclass: ;
}
free(buf);
return NULL;
found:
free(buf);
return (char *)class;
}
char *
superclass( char *subclass )
{
CLASS *cl;
char *cur;
int len;
for( len=0; subclass[len] && (UBYTE)subclass[len]!=0xA0; len++ ) ;
for( cl=CRoot; cl; cl=cl->next ) {
if( strncmp( cur=cl->name,subclass,len ))
continue;
do
cur=index( cur,0xA0 );
while( cur && *++cur!='i');
if( cur && (cur=index(cur,'=')))
return ++cur;
}
return NULL;
}
char *
getaction( char *class, char *action )
{
CLASS *cl;
char *cur, *ind;
int len;
for( len=0; class[len] && (UBYTE)class[len]!=0xA0; len++ ) ;
for( cl=CRoot; cl; cl=cl->next ) {
if( strncmp( cur=cl->name,class,len ) || !issep(cur[len]))
continue;
do
cur=index( cur,0xA0 );
while( cur && *++cur!='a');
if( cur && (cur=index( ++cur,0xA0 ))) {
do {
if( !(ind=index( ++cur,'=' )))
return NULL;
len=ind-cur;
if( len==strlen(action) && !strncmp(action,cur,len))
return ++ind;
} while( cur=index(cur,0xA0) );
}
}
return NULL;
}
int
doaction( char *file, char *action, char *args )
{
char *class, *com, *c, *copy;
int ret, spc=hasspace(file), i=0;
if( !(class=getclass(file)))
return exists(file) ? 10 : 9;
do
if( com=getaction(class,action))
break;
while( (class=superclass( class )) && ++i<4 );
if( !class )
return 11;
if( c=index(com,0xA0) )
*c=0;
copy=salloc( strlen(com)+strlen(file)+strlen(args)+7 );
sprintf(copy,spc?"%s \"%s\" %s":"%s %s %s", com, file, args);
ret=execute(copy);
free(copy);
if( c )
*c=0xA0;
return ret ? 12 : 0;
}
void *
salloc( int len )
{
void *ret;
if( !len ) len++;
if( !(ret=malloc(len))) {
fprintf(stderr,"Out of memory -- exiting\n");
main_exit( 20 );
}
return ret;
}
void *
SAllocMem( long size, long req )
{
void *ret;
if( !(ret=AllocMem(size,req))) {
fprintf(stderr,"Out of memory -- exiting\n");
main_exit( 20 );
}
return ret;
}
int
issep( char s )
{
return !s || ISSPACE(s) || s=='/' || s==';' || s=='|' || s=='&';
}
char *
filemap( char *buf, int last )
{
char *s=buf, *d, *lcd;
int len;
if( last && *s=='~' && issep(s[1])) {
if (!(lcd=get_var(LEVEL_SET,v_lcd)))
return buf;
len= strlen(lcd);
memmove( s+len, s+1, strlen(s)+1);
memcpy( s, lcd, strlen(lcd));
if( s[len]!='/' )
return buf;
s+=len+1;
}
d=s;
for( ;; ) {
if( s[0]=='.' && issep(s[1]) )
s+=1+(s[1]!=0);
else if( s[0]=='.' && s[1]=='.' && issep(s[2]))
*d++='/', s+=2+(s[2]!=0);
else
break;
}
while( *d++=*s++ ) ;
return buf;
}
char *
safegets( char *buf, FILE *in )
{
char *t;
if( dobreak() )
return NULL;
if( !fgets(buf,249,in) )
return NULL;
if( t=index(buf,'\n' ))
*t=0;
return buf;
}