home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
pdksh-4.9-src.tgz
/
tar.out
/
contrib
/
pdksh
/
sh
/
misc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-28
|
7KB
|
435 lines
/*
* Miscellaneous functions
*/
#ifndef lint
static char *RCSid = "$Id: misc.c,v 1.4 93/05/05 21:16:54 sjg Exp $";
#endif
#include "stdh.h"
#include <signal.h>
#include <errno.h>
#include <setjmp.h>
#include "sh.h"
#include "expand.h"
#ifndef NOSTDHDRS
# include <limits.h>
#else
# define UCHAR_MAX 0xFF
#endif
char ctypes [UCHAR_MAX+1]; /* type bits for unsigned char */
static char * cclass ARGS((char *p, int sub));
/*
* Fast character classes
*/
void
setctypes(s, t)
register /* const */ char *s;
register int t;
{
register int i;
if ((t&C_IFS)) {
for (i = 0; i < UCHAR_MAX+1; i++)
ctypes[i] &=~ C_IFS;
ctypes[0] |= C_IFS; /* include \0 in C_IFS */
}
ctypes[(unsigned char) *s++] |= t; /* allow leading \0 in string */
while (*s != 0)
ctypes[(unsigned char) *s++] |= t;
}
void
initctypes()
{
register int c;
for (c = 'a'; c <= 'z'; c++)
ctypes[c] |= C_ALPHA;
for (c = 'A'; c <= 'Z'; c++)
ctypes[c] |= C_ALPHA;
ctypes['_'] |= C_ALPHA;
setctypes("0123456789", C_DIGIT);
setctypes("\0 \t\n|&;<>()", C_LEX1);
setctypes("*@#!$-?", C_VAR1);
setctypes("=-+?#%", C_SUBOP);
}
/* convert unsigned long to base N string */
char *
ulton(n, base)
register unsigned long n;
int base;
{
register char *p;
static char buf [20];
p = &buf[sizeof(buf)];
*--p = '\0';
do {
*--p = "0123456789ABCDEF"[n%base];
n /= base;
} while (n != 0);
return p;
}
char *
strsave(s, ap)
register char *s;
Area *ap;
{
return s ? strcpy((char*) alloc((size_t)strlen(s)+1, ap), s) : NULL;
}
static struct option {
char *name;
int flag;
} options[] = {
{"allexport", FEXPORT},
{"bgnice", FBGNICE},
#if defined(EDIT) && defined(EMACS)
{"emacs", FEMACS},
#endif
{"errexit", FERREXIT},
{"hashall", FHASHALL},
{"ignoreeof", FIGNEOF},
{"interactive", FTALKING},
{"keyword", FKEYWORD},
{"markdirs", FMARKDIRS},
{"monitor", FMONITOR},
{"noexec", FNOEXEC},
{"noglob", FNOGLOB},
{"nounset", FNOUNSET},
{"privileged", FPRIVILEGED},
{"stdin", FSTDIN},
{"trackall", FHASHALL},
{"verbose", FVERBOSE},
#if defined(EDIT) && defined(VI)
{"vi", FVI},
#endif
{"xtrace", FXTRACE},
{NULL, 0}
};
/*
* translate -o option into F* constant
*/
int
option(n)
const char *n;
{
register struct option *op;
for (op = options; op->name != NULL; op++)
if (strcmp(op->name, n) == 0)
return op->flag;
return 0;
}
char *
getoptions()
{
register int c;
char m [26+1];
register char *cp = m;
for (c = 'a'; c <= 'z'; c++)
if (flag[FLAG(c)])
*cp++ = (char) c;
*cp = 0;
return strsave(m, ATEMP);
}
void
printoptions()
{
register struct option *op;
for (op = options; op->name != NULL; op++)
if (flag[op->flag])
shellf("%s ", op->name);
shellf("\n");
}
/* atoi with error detection */
getn(as)
char *as;
{
register char *s;
register int n;
s = as;
if (*s == '-')
s++;
for (n = 0; digit(*s); s++)
n = (n*10) + (*s-'0');
if (*s)
errorf("%s: bad number\n", as);
return (*as == '-') ? -n : n;
}
/* since I'm using a shared library, there's no reason NOT to use the
system strerror() function under amigaos. */
#ifndef amigaos
/*
* stripped down strerror for kill and exec
*/
char *
strerror(i)
int i;
{
switch (i) {
case EINVAL:
return "Invalid argument";
case EACCES:
return "Permission denied";
case ESRCH:
return "No such process";
case EPERM:
return "Not owner";
case ENOENT:
return "No such file or directory";
case ENOTDIR:
return "Not a directory";
case ENOEXEC:
return "Exec format error";
case ENOMEM:
return "Not enough memory";
case E2BIG:
return "Argument list too long";
default:
return "Unknown system error";
}
}
#endif
/* -------- gmatch.c -------- */
/*
* int gmatch(string, pattern)
* char *string, *pattern;
*
* Match a pattern as in sh(1).
* pattern character are prefixed with MAGIC by expand.
*/
static char *cclass ARGS((char *, int c));
int
gmatch(s, p)
register char *s, *p;
{
register int sc, pc;
if (s == NULL || p == NULL)
return 0;
while ((pc = *p++) != 0) {
sc = *s++;
if (pc == MAGIC)
switch (*p++) {
case '[':
if (sc == 0 || (p = cclass(p, sc)) == NULL)
return (0);
break;
case '?':
if (sc == 0)
return (0);
break;
case '*':
s--;
do {
if (*p == '\0' || gmatch(s, p))
return (1);
} while (*s++ != '\0');
return (0);
default:
if (sc != p[-1])
return 0;
break;
}
else
if (sc != pc)
return 0;
}
return (*s == 0);
}
static char *
cclass(p, sub)
register char *p;
register int sub;
{
register int c, d, not, found = 0;
if ((not = (*p == MAGIC && *++p == NOT)))
p++;
do {
if (*p == MAGIC)
p++;
if (*p == '\0')
return NULL;
c = *p;
if (p[1] == '-' && p[2] != ']') {
d = p[2];
p++;
} else
d = c;
if (c == sub || (c <= sub && sub <= d))
found = 1;
} while (*++p != ']');
return (found != not) ? p+1 : NULL;
}
/* -------- qsort.c -------- */
/*
* quick sort of array of generic pointers to objects.
*/
void
qsortp(base, n, f)
void **base; /* base address */
size_t n; /* elements */
int (*f)(); /* compare function */
{
qsort1(base, base + n, f);
}
#define swap2(a, b) {\
register void *t; t = *(a); *(a) = *(b); *(b) = t;\
}
#define swap3(a, b, c) {\
register void *t; t = *(a); *(a) = *(c); *(c) = *(b); *(b) = t;\
}
qsort1(base, lim, f)
void **base, **lim;
int (*f)();
{
register void **i, **j;
register void **lptr, **hptr;
size_t n;
int c;
top:
n = (lim - base) / 2;
if (n == 0)
return;
hptr = lptr = base+n;
i = base;
j = lim - 1;
for (;;) {
if (i < lptr) {
if ((c = (*f)(*i, *lptr)) == 0) {
lptr --;
swap2(i, lptr);
continue;
}
if (c < 0) {
i += 1;
continue;
}
}
begin:
if (j > hptr) {
if ((c = (*f)(*hptr, *j)) == 0) {
hptr ++;
swap2(hptr, j);
goto begin;
}
if (c > 0) {
if (i == lptr) {
hptr ++;
swap3(i, hptr, j);
i = lptr += 1;
goto begin;
}
swap2(i, j);
j -= 1;
i += 1;
continue;
}
j -= 1;
goto begin;
}
if (i == lptr) {
if (lptr-base >= lim-hptr) {
qsort1(hptr+1, lim, f);
lim = lptr;
} else {
qsort1(base, lptr, f);
base = hptr+1;
}
goto top;
}
lptr -= 1;
swap3(j, lptr, i);
j = hptr -= 1;
}
}
int
xstrcmp(p1, p2)
void *p1, *p2;
{
return (strcmp((char *)p1, (char *)p2));
}
void
cleanpath(pwd, dir, clean)
char *pwd, *dir, *clean;
{
register char *s, *d, *p;
char *slash = "/";
register int inslash = 0;
d = clean;
if (*dir != '/') {
s = pwd;
while (*d++ = *s++)
;
if (d >= clean + 2 && *(d - 2) == '/')
d--;
else
*(d - 1) = '/';
}
s = dir;
while (*s) {
if ((*d++ = *s++) == '/' && d > clean + 1) {
if (*(p = d - 2) == '/') {
--d;
} else if (*p == '.') {
if (*--p == '/') {
d -= 2;
} else if (*p == '.' && *--p == '/') {
while (p > clean && *--p != '/')
;
d = p + 1;
}
}
}
if (!*s && !inslash && *(s - 1) != '/') {
inslash = 1;
s = slash;
}
}
if (*(d - 1) == '/' && (d - 1) > clean)
d--;
*d = '\0';
}