Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "defs.h"

static int      hasslash(char *);
static int      haspercent(char *);
static void     rehash(void);

/* simple linear hash.  hash function is sum of
   characters mod hash table size.
*/
static int
hashloc(char *s)
{
int i;
int hashval;
char *t;

hashval = 0;

for(t=s; *t!='\0' ; ++t)
        hashval += *t;

hashval %= hashsize;

for(i=hashval;
        hashtab[i]!=0 && !equal(s,hashtab[i]->namep);
        i = i >= hashsize-1 ? 0 : i+1) ;

return i;
}


nameblkp
srchname(char *s)
{
return  hashtab[hashloc(s)] ;
}



nameblkp
makename(char *s)
{
nameblkp p;

if(nhashed > hashthresh)
        rehash();

++nhashed;
hashtab[hashloc(s)] = p = ALLOC(nameblock);
p->nxtnameblock = firstname;
p->namep = copys(s);    /* make a fresh copy of the string s */
/* p->linep = 0; p->done = 0; p->septype = 0; p->modtime = 0; */

firstname = p;
if(mainname==NULL && !haspercent(s) && (*s!='.' || hasslash(s)) )
        mainname = p;

return p;
}


static int
hasslash(char *s)
{
for( ; *s ; ++s)
        if(*s == '/')
                return YES;
return NO;
}

static int
haspercent(char *s)
{
for( ; *s ; ++s)
        if(*s == '%')
                return YES;
return NO;
}

int
hasparen(char *s)
{
for( ; *s ; ++s)
        if(*s == '(')
                return YES;
return NO;
}

static void
rehash(void)
{
nameblkp *ohash;
nameblkp p, *hp, *endohash;
hp = ohash = hashtab;
endohash = hashtab + hashsize;

newhash(2*hashsize);

while( hp<endohash )
        if(p = *hp++)
                hashtab[hashloc(p->namep)] = p;

free( (char *) ohash);
}


void
newhash(int newsize)
{
hashsize = newsize;
hashtab = (nameblkp *) ckalloc(hashsize * sizeof(nameblkp));
hashthresh = (2*hashsize)/3;
}



nameblkp chkname(char *s)
{
nameblkp p;
time_t k;
/*TEMP NEW */
if(hasparen(s))
        {
        k = lookarch(s);
/*TEMP  fprintf(stderr, "chkname(%s): look=%d\n", s, k); */
        if(k == 0)
                return NULL;
        }
if(p = srchname(s))
        return p;
dirsrch(s);
return srchname(s);
}



char *
copys(char *s)
{
char *t;

if( (t = malloc( strlen(s)+1 ) ) == NULL)
        fatal("out of memory");
strcpy(t, s);
return t;
}



char *
concat(char *a, char *b, char *c)   /* c = concatenation of a and b */
{
char *t;
t = c;

while(*t = *a++) t++;
while(*t++ = *b++);
return c;
}


int
suffix(char *a, char *b, char *p)  /* is b the suffix of a?  if so, set p = prefix */
{
char *a0,*b0;
a0 = a;
b0 = b;

while(*a++);
while(*b++);

if( (a-a0) < (b-b0) ) return 0;

while(b>b0)
        if(*--a != *--b) return 0;

while(a0<a) *p++ = *a0++;
*p = '\0';

return 1;
}

int *
ckalloc(int n)
{
int *p;

if( p = (int *) calloc(1,n) )
        return p;

fatal("out of memory");
/* NOTREACHED */
return 0;
}

/* copy string a into b, substituting for arguments */
char *
subst(char *a, char *b, char *e)
{
static depth    = 0;
char *s;
char vname[100];
struct varblock *vbp;
char closer;

if(++depth > 100)
        fatal("infinitely recursive macro?");
if(a)  while(*a)
        {
        if(*a!='$' || a[1]=='\0' || *++a=='$')
                /* if a non-macro character copy it.  if $$ or $\0, copy $ */
                *b++ = *a++;
        else    {
                s = vname;
                if( *a=='(' || *a=='{' )
                        {
                        closer = ( *a=='(' ? ')' : '}');
                        ++a;
                        while(*a == ' ') ++a;
                        while(*a!=' ' && *a!=closer && *a!='\0') *s++ = *a++;
                        while(*a!=closer && *a!='\0') ++a;
                        if(*a == closer) ++a;
                        }
                else    *s++ = *a++;

                *s = '\0';
                if( (vbp = varptr(vname)) ->varval != 0)
                        {
                        b = subst(vbp->varval, b, e);
                        vbp->used = YES;
                        }
                }
                if(b >= e)
                        fatal("macro expanded too far");
        }

*b = '\0';
--depth;
return b;
}

void
setvar(char *v, char *s, int dyn)
{
struct varblock *p;

p = varptr(v);
if( ! p->noreset )
        {
        p->varval = s;
        p->noreset = inarglist;
        if(p->used && !dyn)
                fprintf(stderr, "Warning: %s changed after being used\n",v);
        if(p->export)
                {
                /* change string pointed to by environment to new v=s */
                char *t;
                int lenv;
                lenv = strlen(v);
                *(p->export) = t = (char *) ckalloc(lenv + strlen(s) + 2);
                strcpy(t,v);
                t[lenv] = '=';
                strcpy(t+lenv+1, s);
                }
        else
                p->export = envpp;
        }
}


/* for setting Bradford's *D and *F family of macros whens setting * etc */
void
set3var(char *macro, char *value)
{
char *s;
char macjunk[8], *lastslash, *dirpart, *filepart;

setvar(macro, value, YES);
if(value == CHNULL)
        dirpart = filepart = CHNULL;
else
        {
        lastslash = CHNULL;
        for(s = value; *s; ++s)
                if(*s == '/')
                        lastslash = s;
        if(lastslash)
                {
                dirpart = copys(value);
                filepart = dirpart + (lastslash-value);
                filepart[-1] = '\0';
                }
        else
                {
                dirpart = "";
                filepart = value;
                }
        }
setvar(concat(macro, "D", macjunk), dirpart, YES);
setvar(concat(macro, "F", macjunk), filepart, YES);
}


int
eqsign(char *a)   /*look for arguments with equal signs but not colons */
{
char *s, *t;
char c;

while(*a == ' ') ++a;
for(s=a  ;   *s!='\0' && *s!=':'  ; ++s)
        if(*s == '=')
                {
                for(t = a ; *t!='=' && *t!=' ' && *t!='\t' ;  ++t );
                c = *t;
                *t = '\0';

                for(++s; *s==' ' || *s=='\t' ; ++s);
                setvar(a, copys(s), NO);
                *t = c;
                return YES;
                }

return NO;
}

struct varblock *
varptr(char *v)
{
struct varblock *vp;

/* for compatibility, $(TGS) = $^ */
if(equal(v, "TGS") )
        v = "^";
for(vp = firstvar; vp ; vp = vp->nxtvarblock)
        if(equal(v , vp->varname))
                return vp;

vp = ALLOC(varblock);
vp->nxtvarblock = firstvar;
firstvar = vp;
vp->varname = copys(v);
vp->varval = 0;
return vp;
}

int
dynmacro(char *line)
{
char *s;
char endc, *endp;
if(!isalpha(line[0]))
        return NO;
for(s=line+1 ; *s && (isalpha(*s) | isdigit(*s)) ; ++s)
        ;
endp = s;
while( isspace(*s) )
        ++s;
if(s[0]!=':' || s[1]!='=')
        return NO;

endc = *endp;
*endp = '\0';
setvar(line, copys(s+2), YES);
*endp = endc;

return YES;
}


void
fatal1(char *s, char *t)
{
char buf[100];
sprintf(buf, s, t);
fatal(buf);
}


void
fatal(char *s)
{
fflush(stdout);
if(s)
        fprintf(stderr, "Make: %s.  Stop.\n", s);
else
        fprintf(stderr, "\nStop.\n");

waitstack(0);
exit(1);
}



/* appends to the chain for $? and $^ */
chainp
appendq(chainp head, char *tail)
{
chainp p, q;

p = ALLOC(chain);
p->datap = tail;

if(head)
        {
        for(q = head ; q->nextp ; q = q->nextp)
                ;
        q->nextp = p;
        return head;
        }
else
        return p;
}





/* builds the value for $? and $^ */
char *
mkqlist(chainp p, char *qbuf)
{
char *qbufp, *s;

if(p == NULL)
        return "";

qbufp = qbuf;

for( ; p ; p = p->nextp)
        {
        s = p->datap;
        if(qbufp+strlen(s) > &qbuf[QBUFMAX-3])
                {
                fprintf(stderr, "$? list too long\n");
                break;
                }
        while (*s)
                *qbufp++ = *s++;
        *qbufp++ = ' ';
        }
*--qbufp = '\0';
return qbuf;
}

wildp
iswild(char *name)
{
char *s;
wildp p;

for(s=name; *s; ++s)
        if(*s == '%')
                {
                p = ALLOC(wild);
                *s = '\0';
                p->left = copys(name);
                *s = '%';
                p->right = copys(s+1);
                p->llen = strlen(p->left);
                p->rlen = strlen(p->right);
                p->totlen = p->llen + p->rlen;
                return p;
                }
return NULL;
}


char *
wildmatch(wildp p, char *name, int len)
{
char *stem;
char *s;
char c;

if(len < p->totlen ||
   strncmp(name, p->left, p->llen) ||
   strncmp(s = name+len-p->rlen, p->right, p->rlen) )
        return CHNULL;

/*TEMP fprintf(stderr, "wildmatch(%s)=%s%%%s)\n", name,p->left,p->right); */
c = *s;
*s = '\0';
stem = copys(name + p->llen);
*s = c;
return stem;
}



/* substitute stem for any % marks */
char *
wildsub(char *pat, char *stem)
{
static char temp[100];
char *s, *t;

s = temp;
for(; *pat; ++pat)
        if(*pat == '%')
                for(t = stem ; *t; )
                        *s++ = *t++;
        else
                *s++ = *pat;
*s = '\0';
return temp;
}