|
|
researchv10 Norman
/* @(#)/usr/src/cmd/make/misc.c 3.4 */
/* @(#)misc.c 3.2 */
#include "defs"
#include "ctype.h"
FSTATIC CHARSTAR nextchar=0;
FSTATIC CHARSTAR lastchar=0;
FSTATIC int *nextint=0;
FSTATIC int *lastint=0;
FSTATIC NAMEBLOCK hashtab[HASHSIZE];
int nhashed=0;
/* simple linear hash. hash function is sum of
characters mod hash table size.
*/
hashloc(s)
CHARSTAR s;
{
register int i;
register int hashval;
register CHARSTAR t;
hashval = 0;
for(t=s; *t!=CNULL ; ++t)
hashval += *t;
hashval %= HASHSIZE;
for(i=hashval;
hashtab[i]!=0 && !equal(s,hashtab[i]->namep);
i = (i+1)%HASHSIZE ) ;
return(i);
}
NAMEBLOCK srchname(s)
register CHARSTAR s;
{
return( hashtab[hashloc(s)] );
}
NAMEBLOCK makename(s)
register CHARSTAR s;
{
/* make a name entry; `s' is presumed to already to have been saved */
register NAMEBLOCK p;
register CHARSTAR t;
if(nhashed++ > HASHSIZE-3)
fatal("Hash table overflow");
p = ALLOC(nameblock);
p->nextname = firstname;
p->backname = NULL;
p->namep = s;
p->linep = 0;
p->done = 0;
p->septype = 0;
p->rundep = 0;
p->modtime = 0;
firstname = p;
hashtab[hashloc(s)] = p;
return(p);
}
#define NOTSHORT sizeof (struct nameblock)
extern CHARSTAR end; /* loader value of end of core */
CHARSTAR copys(s)
register CHARSTAR s;
{
register CHARSTAR t;
register struct
{
int i_i;
CHARSTAR i_s;
} i;
i.i_i = strlen(s) + 1;
if(i.i_i > NOTSHORT)
{
i.i_i = (i.i_i + 1)&~1;
t = (CHARSTAR )calloc(i.i_i, sizeof (*s));
if(t == NULL)
goto fat;
i.i_s = t;
while(*t++ = *s++);
return(i.i_s);
}
if( i.i_i >= (lastchar-nextchar) )
{
i.i_i = (i.i_i + 1)&~1;
if( (nextchar=(CHARSTAR )calloc(i.i_i, sizeof (*s) )) == NULL)
fat:
fatal("Cannot allocate memory");
lastchar = nextchar + i.i_i;
}
t = nextchar;
while(*nextchar++ = *s++);
return(t);
}
CHARSTAR concat(a,b,c) /* c = concatenation of a and b */
register CHARSTAR a, b;
register CHARSTAR c;
{
register CHARSTAR t;
t = c;
while(*t = *a++) t++;
while(*t++ = *b++);
return(c);
}
suffix(a,b,p) /* is b the suffix of a? if so, set p = prefix */
register CHARSTAR a, b, p;
{
CHARSTAR a0, b0;
a0 = a;
b0 = b;
if(!a || !b)
return(0);
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 = CNULL;
return(1);
}
int *intalloc(n)
register int n;
{
register INTSTAR p;
if( p = (int *) calloc(1,n) )
return(p);
fatal("out of memory");
}
/* copy string a into b, substituting for arguments */
extern NAMEBLOCK cur_name;
CHARSTAR subst(a,b)
register CHARSTAR a, b;
{
register CHARSTAR s;
register VARBLOCK vbp;
static depth=0;
char vname[100];
char closer;
if(++depth > 100)
fatal("infinitely recursive macro?");
if(a!=0)
{
while(*a)
{
if(*a != DOLLAR)
*b++ = *a++;
else if(*++a==CNULL || *a==DOLLAR)
*b++ = *a++;
else
{
s = vname;
if( *a==LPAREN || *a==LCURLY )
{
closer=(*a==LPAREN ? RPAREN : RCURLY);
++a;
while(*a == BLANK)
++a;
while( *a!=BLANK &&
*a!=closer &&
*a!=CNULL)
*s++ = *a++;
while(*a!=closer && *a!=CNULL)
++a;
if(*a == closer)
++a;
}
else
*s++ = *a++;
*s = CNULL;
if(amatch(&vname[0], "*:*=*"))
{
b = colontrans(b, vname);
}
else if(amatch(vname, "[@*<%][DF]"))
{
b = dftrans(b, vname);
}
else
{
b = straightrans(b, vname);
}
}
}
}
*b = CNULL;
--depth;
return(b);
}
/*
* Translate the $(name:*=*) type things.
*/
CHARSTAR colontrans(b, vname)
register CHARSTAR b;
char vname[];
{
register int i;
register CHARSTAR ps1;
int fromlen;
char from[30], to[70];
char dftemp[128];
char tmp, nextchr;
CHARSTAR psave, pcolon;
VARBLOCK vbp;
/*
* Mark off the name (up to colon), the from expression (up to '='),
* and the to expresion (up to CNULL).
*/
i = 0;
for(ps1 = &vname[0]; *ps1 != KOLON; ps1++);
pcolon = ps1;
*pcolon = CNULL;
while(*++ps1 != EQUALS)
from[i++] = *ps1;
from[i] = CNULL;
fromlen = i;
i = 0;
while(*++ps1)
to[i++] = *ps1;
to[i] = CNULL;
/*
* Now, tanslate.
*/
if(amatch(vname, "[@*<%][DF]"))
{
dftrans(dftemp, vname);
ps1 = dftemp;
}
else
{
if((vbp = srchvar(vname)) == NULL)
{
return(b);
}
ps1 = vbp->varval;
}
if(ps1 != NULL && *ps1 != NULL)
{
psave = ps1;
while((i = sindex(ps1, from)) >= 0)
{
ps1 = &ps1[i];
tmp = *ps1;
*ps1 = CNULL;
nextchr = *(ps1+fromlen);
if( nextchr == TAB ||
nextchr == BLANK ||
nextchr == CNULL)
{
b = copstr(b, psave);
b = copstr(b, to);
*ps1 = tmp;
ps1 += fromlen;
}
else
{
b = copstr(b, psave);
*b++ = tmp;
*ps1 = tmp;
ps1++;
}
psave = ps1;
}
b = copstr(b, ps1);
}
*pcolon = KOLON;
return(b);
}
/*
* Do the $(@D) type translations.
*/
CHARSTAR dftrans(b, vname)
register CHARSTAR b;
char vname[];
{
char c, c1;
CHARSTAR p1, p2;
VARBLOCK vbp;
c1 = vname[1];
vname[1] = CNULL;
vbp = srchvar(vname);
if(vbp != 0 && vbp->varval != 0)
{
for(p1=p2=vbp->varval;*p1;p1++)
if(*p1 == SLASH)
p2 = p1;
if(*p2 == SLASH)
{
if(c1 == 'D')
{
if(p2 == vbp->varval)
p2++;
c = *p2;
*p2 = CNULL;
b = copstr(b,vbp->varval);
*p2 = c;
}
else
{
b = copstr(b, p2+1);
}
}
else
{
if(c1 == 'D')
b = copstr(b, ".");
else
b = copstr(b, p2);
}
}
vname[1] = c1;
return(b);
}
/*
* Standard trnaslation, nothing fancy.
*/
CHARSTAR straightrans(b, vname)
register CHARSTAR b;
char vname[];
{
register VARBLOCK vbp;
register CHAIN pchain;
register NAMEBLOCK pn;
vbp = srchvar(vname);
if( vbp != 0 && vbp->varval != 0)
{
if(vbp->v_aflg == YES)
{
pchain = (CHAIN)vbp->varval;
for(; pchain; pchain = pchain->nextchain)
{
pn = (NAMEBLOCK)pchain->datap;
if(pn->alias)
b=copstr(b, pn->alias);
else
b=copstr(b,pn->namep);
*b++ = BLANK;
}
}
else
{
b = subst(vbp->varval, b);
}
vbp->used = YES;
}
return(b);
}
/* copy s into t, return the location of the next free character in s */
CHARSTAR copstr(s, t)
register CHARSTAR s, t;
{
if(t == 0)
return(s);
while (*t)
*s++ = *t++;
*s = CNULL;
return(s);
}
setvar(v,s)
register CHARSTAR v, s;
{
register VARBLOCK p;
p = srchvar(v);
if(p == 0)
{
p = varptr(v);
}
if (p->noreset == NO)
{
if(IS_ON(EXPORT))
p->envflg = YES;
p->varval = s;
if(IS_ON(INARGS) || IS_ON(ENVOVER))
p->noreset = YES;
else
p->noreset = NO;
if(IS_ON(DBUG))printf("setvar: %s = %s noreset = %d envflg = %d Mflags = 0%o\n",
v, p->varval, p->noreset, p->envflg, Mflags);
if(p->used && !amatch(v, "[@*<?!%]") )
if(IS_ON(DBUG))
fprintf(stderr, "Warning: %s changed after being used\n",v);
}
}
eqsign(a)
register CHARSTAR a;
{
register CHARSTAR p;
for(p = ":;=$\n\t"; *p; p++)
if(any(a, *p))
{
callyacc(a);
return(YES);
}
return(NO);
}
VARBLOCK varptr(v)
register CHARSTAR v;
{
register VARBLOCK vp;
if((vp = srchvar(v)) != 0)
return(vp);
vp = ALLOC(varblock);
vp->nextvar = firstvar;
firstvar = vp;
vp->varname = copys(v);
vp->varval = 0;
return(vp);
}
VARBLOCK srchvar(vname)
register CHARSTAR vname;
{
register VARBLOCK vp;
for(vp=firstvar; vp != 0 ; vp = vp->nextvar)
if(equal(vname, vp->varname))
return(vp);
return(NO);
}
fatal1(s,t)
CHARSTAR s, t;
{
char buf[100];
sprintf(buf, s, t);
fatal(buf);
}
fatal(s)
CHARSTAR s;
{
if(s)
fprintf(stderr, "Make: %s. Stop.\n", s);
else
fprintf(stderr, "\nStop.\n");
#ifdef unix
exit(1);
#endif
#ifdef gcos
exit(0);
#endif
}
yyerror(s)
CHARSTAR s;
{
char buf[50];
extern int yylineno;
sprintf(buf, "line %d: %s", yylineno, s);
fatal(buf);
}
CHAIN appendq(head,tail)
register CHAIN head;
register CHARSTAR tail;
{
register CHAIN p;
p = ALLOC(chain);
p->datap = tail;
while(head->nextchain)
head = head->nextchain;
head->nextchain = p;
}
CHARSTAR mkqlist(p)
register CHAIN p;
{
register CHARSTAR qbufp, s;
static char qbuf[OUTMAX];
qbufp = qbuf;
for( ; p ; p = p->nextchain)
{
s = p->datap;
if(qbufp != qbuf)
*qbufp++ = BLANK;
if(qbufp+strlen(s) > &qbuf[OUTMAX-3])
{
fprintf(stderr, "$? list too long\n");
break;
}
while (*s)
*qbufp++ = *s++;
}
*qbufp = CNULL;
return(qbuf);
}
any(s,c)
register CHARSTAR s;
register char c;
{
register char d;
while(d = *s++)
{
if(d==c)
return(1);
}
return(0);
}
sindex(s1,s2)
CHARSTAR s1;
CHARSTAR s2;
{
register CHARSTAR p1;
register CHARSTAR p2;
register int flag;
int ii;
p1 = &s1[0];
p2 = &s2[0];
flag = -1;
for(ii = 0; ; ii++)
{
while(*p1 == *p2)
{
if(flag < 0)
flag = ii;
if(*p1++ == CNULL)
return(flag);
p2++;
}
if(*p2 == CNULL)
return(flag);
if(flag >= 0)
{
flag = -1;
p2 = &s2[0];
}
if(*s1++ == CNULL)
return(flag);
p1 = s1;
}
}
#include "sys/types.h"
#include "sys/stat.h"
/*
* findfl(name) (like execvp, but does path search and finds files)
*/
static char fname[128];
char *execat();
CHARSTAR findfl(name)
register CHARSTAR name;
{
register CHARSTAR p;
register VARBLOCK cp;
if(name[0] == SLASH)
return(name);
cp = varptr("VPATH");
if(cp->varval == 0)
p = ":";
else
p = cp->varval;
do
{
p = execat(p, name, fname);
if(access(fname, 4) == 0)
return(fname);
} while (p);
return((CHARSTAR )-1);
}
CHARSTAR execat(s1, s2, si)
register CHARSTAR s1, s2;
CHARSTAR si;
{
register CHARSTAR s;
s = si;
while (*s1 && *s1 != KOLON && *s1 != MINUS)
*s++ = *s1++;
if (si != s)
*s++ = SLASH;
while (*s2)
*s++ = *s2++;
*s = CNULL;
return(*s1? ++s1: 0);
}
/*
* change xx to s.xx or /x/y/z to /x/y/s.z
*/
CHARSTAR trysccs(str)
register CHARSTAR str;
{
register CHARSTAR sstr;
register int i = 2;
sstr = str;
for(; *str; str++);
str[2] = CNULL;
str--;
for(;str >= sstr; str--)
{
if(*str == SLASH)
if(i == 2)
{
i = 0;
*(str+2) = DOT;
*(str+1) = 's';
}
*(str+i) = *str;
}
if(i == 2)
{
*(str+2) = DOT;
*(str+1) = 's';
}
return(sstr);
}
is_sccs(filename)
register CHARSTAR filename;
{
register CHARSTAR p;
for(p = filename; *p; p++)
if(*p == 's')
if(p == filename && p[1] == DOT)
return(YES);
else if(p[-1] == SLASH && p[1] == DOT)
return(YES);
return(NO);
}
/*
* change pfx to /xxx/yy/*zz.* or *zz.*
*/
CHARSTAR addstars(pfx)
register CHARSTAR pfx;
{
register CHARSTAR p1, p2;
for(p1 = pfx; *p1; p1++);
p2 = p1 + 3; /* 3 characters, '*', '.', and '*'. */
p1--;
*p2-- = CNULL;
*p2-- = STAR;
*p2-- = DOT;
while(p1 >= pfx)
{
if(*p1 == SLASH)
{
*p2 = STAR;
return(pfx);
}
*p2-- = *p1--;
}
*p2 = STAR;
return(p2);
}
#define NENV 300
extern CHARSTAR *environ;
/*
* This routine is called just before and exec.
*/
setenv()
{
register CHARSTAR *ea;
register int nenv = 0;
register CHARSTAR p;
CHARSTAR *es;
VARBLOCK vp;
int length;
if(firstvar == 0)
return;
es=ea=(CHARSTAR *)calloc(NENV, sizeof *ea);
if(es == (CHARSTAR *)-1)
fatal("Cannot alloc mem for envp.");
for(vp=firstvar; vp != 0; vp=vp->nextvar)
if(vp->envflg)
{
if(++nenv >= NENV)
fatal("Too many env parameters.");
length = strlen(vp->varname) + strlen(vp->varval) + 2;
if((*ea = (CHARSTAR )calloc(length, sizeof **ea)) == (CHARSTAR )-1)
fatal("Cannot alloc mem for env.");
p = copstr(*ea++, vp->varname);
p = copstr(p, "=");
p = copstr(p, vp->varval);
}
*ea = 0;
if(nenv > 0)
environ=es;
if(IS_ON(DBUG))
printf("nenv = %d\n", nenv);
}
/*
* Called in main
* If a string like "CC=" occurs then CC is not put in environment.
* This is because there is no good way to remove a variable
* from the environment within the shell.
*/
readenv()
{
register CHARSTAR *ea;
register CHARSTAR p;
ea=environ;
for(;*ea; ea++)
{
for(p = *ea; *p && *p != EQUALS; p++);
if(*p == EQUALS)
if(*(p+1))
eqsign(*ea);
}
}
sccstrip(pstr)
register CHARSTAR pstr;
{
register CHARSTAR p2;
register CHARSTAR sstr;
sstr = pstr;
for(; *pstr ; pstr++)
if(*pstr == RCURLY)
{
if(isdigit(pstr[1]))
if(pstr != sstr)
if(pstr[-1] != DOLLAR)
{
for(p2 = pstr; *p2 && (*p2 != LCURLY); p2++);
if(*p2 == CNULL)
break;
strshift(pstr, -(int)(p2-pstr+1) );
}
}
}
/*
* Shift a string `pstr' count places. negative is left, pos is right
* Negative shifts cause char's at front to be lost.
* Positive shifts assume enough space!
*/
CHARSTAR strshift(pstr, count)
register CHARSTAR pstr;
register int count;
{
register CHARSTAR sstr;
sstr = pstr;
if(count < 0)
{
count = -count;
while(pstr[count])
*pstr = pstr++[count];
*pstr = 0;
return(sstr);
}
for(; *pstr; pstr++);
pstr--[count] = 0;
while(pstr != sstr)
pstr[count] = *pstr--;
pstr[count] = *pstr;
return(sstr);
}
/*
* execlp(name, arg,...,0) (like execl, but does path search)
* execvp(name, argv) (like execv, but does path search)
*/
#include <errno.h>
CHARSTAR execat();
extern errno;
execlp(name, argv)
CHARSTAR name, argv;
{
return(execvp(name, &argv));
}
execvp(name, argv)
CHARSTAR name, *argv;
{
register etxtbsy = 1;
register eacces = 0;
register CHARSTAR cp;
CHARSTAR pathstr;
CHARSTAR shell;
char fname[128];
pathstr = varptr("PATH")->varval;
if(pathstr == 0 || *pathstr == CNULL)
pathstr = ":/bin:/usr/bin";
shell = varptr("SHELL")->varval;
if(shell == 0 || *shell == CNULL)
shell = "/bin/sh";
cp = strchr(name, SLASH)? "": pathstr;
do
{
cp = execat(cp, name, fname);
retry:
execv(fname, argv);
switch(errno)
{
case ENOEXEC:
*argv = fname;
*--argv = "sh";
execv(shell, argv);
return(-1);
case ETXTBSY:
if (++etxtbsy > 5)
return(-1);
sleep(etxtbsy);
goto retry;
case EACCES:
eacces++;
break;
case ENOMEM:
case E2BIG:
return(-1);
}
} while (cp);
if (eacces)
errno = EACCES;
return(-1);
}
/*
* get() does an SCCS get on the file ssfile.
* For the get command, get() uses the value of the variable "GET".
* If ssfile has a slash in it, get() does a "chdir" to the appropriate
* directory if the cdflag is set to CD. This assures
* the program finds the ssfile where it belongs when necessary.
* If the rlse string variable is set, get() uses it in the
* get command sequence.
* Thus a possible sequence is:
* set -x;
* cd ../sys/head;
* get -r2.3.4.5 s.stdio.h
*
*/
/*
* The gothead and gotf structures are used to remember
* the names of the files `make' automatically gets so
* `make' can remove them upon exit.
*/
GOTHEAD gotfiles;
get(ssfile, cdflag, rlse)
register CHARSTAR ssfile;
int cdflag;
CHARSTAR rlse;
{
register CHARSTAR pr;
register CHARSTAR pr1;
char gbuf[128];
char sfile[128];
int retval;
GOTF gf;
copstr(sfile, ssfile);
if(!is_sccs(sfile))
trysccs(sfile);
if(access(sfile, 4) != 0 && IS_OFF(GET))
return(NO);
pr = gbuf;
if(IS_OFF(SIL))
pr = copstr(pr, "set -x;\n");
if(cdflag == CD)
if(any(sfile, SLASH))
{
pr = copstr(pr, "cd ");
for(pr1 = sfile; *pr1; pr1++);
while(*pr1 != SLASH)
pr1--;
*pr1 = CNULL;
pr = copstr(pr, sfile);
pr = copstr(pr, ";\n");
*pr1 = SLASH;
}
pr = copstr(pr, varptr("GET")->varval);
pr = copstr(pr, " ");
pr = copstr(pr, varptr("GFLAGS")->varval);
pr = copstr(pr, " ");
pr1 = rlse;
if(pr1 != NULL && pr1[0] != CNULL)
{
if(pr1[0] != MINUS) /* RELEASE doesn't have '-r' */
pr = copstr(pr, "-r");
pr = copstr(pr, pr1);
pr = copstr(pr, " ");
}
pr = copstr(pr, sfile);
/*
* exit codes are opposite of error codes so do the following:
*/
retval = (system(gbuf) == 0) ? YES : NO ;
if(retval == YES)
{
if(gotfiles == 0)
{
gotfiles = ALLOC(gothead);
gf = (GOTF)gotfiles;
gotfiles->gnextp = 0;
gotfiles->endp = (GOTF)gotfiles;
}
else
{
gf = gotfiles->endp;
gf->gnextp = ALLOC(gotf);
gf = gf->gnextp;
gf->gnextp = 0;
}
gf->gnamep = copys(sfile+2); /* `+2' skips `s.' */
gotfiles->endp = gf;
}
return(retval);
}
/*
* subroutine to actually remove to gotten files.
*/
rm_gots()
{
register GOTF gf;
if(IS_ON(GF_KEEP))
return;
for(gf = (GOTF)gotfiles; gf ; gf=gf->gnextp)
if(gf->gnamep)
{
if(IS_ON(DBUG))printf("rm_got: %s\n", gf->gnamep);
unlink(gf->gnamep);
}
}
callyacc(str)
register CHARSTAR str;
{
CHARSTAR lines[2];
FILE *finsave;
CHARSTAR *lpsave;
finsave = fin;
lpsave = linesptr;
fin = 0;
lines[0] = str;
lines[1] = 0;
linesptr = lines;
yyparse();
fin = finsave;
linesptr = lpsave;
}
/*
* exit routine for removing the files `make' automatically
* got.
*/
exit(arg)
{
rm_gots();
if(IS_ON(MEMMAP))
{
prtmem();
}
_cleanup();
_exit(arg);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.