1BSD/ex-1.1/ex_glob.c
#
/*
* Ex - a text editor
* Bill Joy UCB September, 1977
*
* This glob routine mercilessly stolen from the shell.
*/
#include "ex.h"
#include "ex_glob.h"
#include "ex_io.h"
static int gflag;
int tglob(), trim();
static char **av;
static char *string, *strend;
static int ncoll;
static char *gpathp;
static int globbed;
static char *entp;
struct Glob *g;
#define ab g->Ab
#define ava g->Ava
glob(v, g0)
register char *v[];
struct Glob *g0;
{
register char **oav;
g = g0;
av = ava;
string = ab;
strend = ab + 511;
ncoll = 0;
gpathp = file;
gflag = 0;
scan(v, &tglob);
if (gflag == 0)
ncoll++;
while (*v) {
oav = av;
globbed = 0;
expand(*v++);
sort(oav);
}
*av = 0;
if (ncoll == 0)
error("No match@in filename expansion of `*', `/' or `[...]'");
gargc = av - &ava[0];
}
sort(oav)
char **oav;
{
register char **p1, **p2, **c;
p1 = oav;
while (p1 < av-1) {
p2 = p1;
while (++p2 < av) {
if (strcmp(*p1, *p2) > 0) {
c = *p1;
*p1 = *p2;
*p2 = c;
}
}
p1++;
}
}
expand(as)
char *as;
{
register char *cs, *sgpathp;
register int dirf;
static struct {
int ino;
char name[16];
} entry;
int stbuff[18];
sgpathp = gpathp;
cs = as;
while (*cs != '*' && *cs != '?' && *cs != '[') {
if (gpathp >= &file[FNSIZE - 2])
goto gpatherr;
else if ((*gpathp++ = *cs++) == 0) {
if (!globbed)
*av++ = cat(as, "");
else if (stat(file, &stbuff) >= 0) {
*av++ = cat(file, "");
ncoll++;
}
goto endit;
}
}
gpathp = sgpathp;
cs--;
while (cs >= as && *cs != '/')
cs--;
while (as <= cs)
if (gpathp >= &file[FNSIZE])
gpatherr:
error("Path name too long@- editor limit 64 characters");
else
*gpathp++ = *as++;
*gpathp = 0;
dirf = open(file, 0);
if (dirf < 0)
if (globbed)
goto endit;
else
filioerr(file);
globbed++;
cs++;
while (read(dirf, &entry, 16) == 16) {
if (entry.ino==0)
continue;
if (match(entry.name, cs)) {
*av++ = cat(file, entry.name);
ncoll++;
}
}
close(dirf);
endit:
gpathp = sgpathp;
*gpathp = 0;
}
match(s, p)
char *s, *p;
{
register c, sentp;
if (*s == '.' && *p != '.')
return (0);
sentp = entp;
entp = s;
c = amatch(s, p);
entp = sentp;
return (c);
}
amatch(as, ap)
char *as, *ap;
{
register char *s, *p;
register scc;
int c, cc, ok, lc;
char *sgpathp;
int stbuff[18];
s = as;
p = ap;
nextc:
if (scc = *s++ & 0177)
if ((scc =& 0177) == 0)
scc = 0200;
switch (c = *p++) {
case '[':
ok = 0;
lc = 077777;
while (cc = *p++) {
if (cc == ']') {
if (ok)
goto nextc;
else
return (0);
} else if (cc == '-') {
if (lc <= scc && scc <= *p++)
ok++;
} else
if (scc == (lc = cc))
ok++;
}
error("Missing ]@matching [ in filename");
case '*':
if (*p == '\0')
return (1);
else if (*p == '/') {
p++;
goto slash;
}
s--;
while (*s)
if (amatch(s, p))
return (1);
else
s++;
return (0);
case '\0':
return (scc == '\0');
default:
if (c == scc)
goto nextc;
else
return (0);
case '?':
if (scc != '\0')
goto nextc;
else
return (0);
case '/':
if (scc == '\0') {
slash:
s = entp;
sgpathp = gpathp;
while (*gpathp = *s++) {
if (gpathp >= &file[FNSIZE - 3])
error("Path name too long@- editor limit 64 characters");
gpathp++;
}
*gpathp++ = '/';
*gpathp = 0;
if (stat(file, &stbuff) == 0)
if ((stbuff[2] & 060000) == 040000)
if (*p == 0) {
*av++ = cat(file, "");
ncoll++;
} else
expand(p);
gpathp = sgpathp;
*gpathp = 0;
}
return (0);
}
}
cat(as1, as2)
char *as1, *as2;
{
register char *s1, *s2;
s2 = string;
s1 = as1;
while (*s2++ = (*s1++ & 0177))
if (s2 >= strend)
goto toolong;
s1 = as2;
s2--;
while (*s2++ = *s1++)
if (s2 > strend)
toolong:
error("Argument list too long@- editor limit 512 characters");
s1 = string;
string = s2;
return (s1);
}
scan(t, f)
register int *t;
int (*f)();
{
register char *p, c;
while (p = *t++)
while (c = *p)
*p++ = (*f)(c);
}
tglob(c)
register int c;
{
if (any(c, "[?*"))
gflag = 1;
return (c);
}
trim(c)
char c;
{
return (c & 0177);
}
getone()
{
register char *str;
int gv[2], *lp;
struct Glob G;
switch (getargs()) {
case 0:
error("Missing filename@- if you give blanks you must give a name");
case 1:
break;
default:
error("Too many names|Multiple file names allowed only on next command");
}
gv[0] = (lp = genbuf)[0];
gv[1] = 0;
glob(gv, &G);
str = G.Ava[0];
if (G.Ava[1] != NIL)
error("Ambiguous|Pattern is ambiguous, matches more than one file");
if (strlen(str) > 63)
error("Filename too long@- limit 63 characters");
strcpy(file, str);
}
filioerr(cp)
char *cp;
{
register int oerrno;
oerrno = errno;
lprintf("\"%s\"", cp);
errno = oerrno;
ioerror();
}
any(c, s)
int c;
register char *s;
{
register int x;
while (x = *s++)
if (x == c)
return (1);
return (0);
}