This source file includes following definitions.
- stringList
- BraceExpand
- Tilde
- Tcl_Glob
#ifndef lint
static char rcsid[] = "$Header: /sprite/src/lib/tcl/RCS/tclGlob.c,v 1.2 89/06/12 17:00:39 shirriff Exp $ SPRITE (Berkeley)";
#endif
#include <string.h>
#include <list.h>
#include <pwd.h>
#include <tcl.h>
extern int errno;
extern char *sys_errlist[];
extern char *ckalloc(), *sprintf(), *getlogin();
extern char **glob_filename();
typedef struct {
List_Links links;
char *str;
} stringList;
#define FREE(list) \
while (!List_IsEmpty((list))) { \
stringElt=(stringList *)List_First((list)); \
List_Remove((List_Links *)stringElt); \
if (stringElt->str != NULL) { \
ckfree(stringElt->str); \
} \
ckfree((char *)stringElt); \
} \
ckfree((char *)(list))
static char*
BraceExpand(str,inBrace,strList)
char *str;
int inBrace;
List_Links **strList;
{
List_Links *headerPtr;
stringList *stringElt;
List_Links *leftHdr;
List_Links *rightHdr;
char *strPtr;
char *next;
int len;
List_Links *leftPtr;
char *left;
int leftLen;
List_Links *rightPtr;
char *right;
headerPtr = (List_Links *)ckalloc(sizeof(List_Links));
List_Init(headerPtr);
if (inBrace) {
strPtr = strpbrk(str,"{,}");
} else {
strPtr = strchr(str,'{');
}
if (strPtr==NULL || *strPtr=='}' || *strPtr==',') {
if (strPtr==NULL) {
len = strlen(str);
strPtr = str+len;
}
else {
len = strPtr-str;
}
stringElt = (stringList *)ckalloc(sizeof(stringList));
List_InitElement((List_Links *)stringElt);
stringElt->str = (char *)ckalloc((unsigned)len+1);
(void) strncpy(stringElt->str,str,len);
stringElt->str[len] = '\0';
List_Insert((List_Links *)stringElt,
LIST_ATFRONT(headerPtr));
*strList = headerPtr;
return strPtr;
}
len = strPtr-str;
leftHdr = (List_Links *)ckalloc(sizeof(List_Links));
List_Init(leftHdr);
if (*str=='{') {
next = strPtr;
while (1) {
next = BraceExpand(++next,1,&rightHdr);
if (next==NULL) {
*strList = rightHdr;
return NULL;
} else if (*next=='\0') {
FREE(leftHdr);
FREE(rightHdr);
stringElt = (stringList *)ckalloc(sizeof(stringList));
List_InitElement((List_Links *)stringElt);
stringElt->str = "Missing }.";
List_Insert((List_Links *)stringElt,
LIST_ATREAR(headerPtr));
*strList = headerPtr;
return NULL;
}
else {
List_ListInsert(rightHdr, LIST_ATREAR(leftHdr));
ckfree((char *)rightHdr);
if (*next=='}') {
strPtr = next+1;
break;
}
}
}
} else {
stringElt = (stringList *)ckalloc(sizeof(stringList));
List_InitElement((List_Links *)stringElt);
stringElt->str = (char *)ckalloc((unsigned)len+1);
(void) strncpy(stringElt->str,str,len);
stringElt->str[len] = '\0';
List_Insert((List_Links *)stringElt,
LIST_ATFRONT(leftHdr));
}
if (*strPtr=='\0' || (*strPtr==',' && inBrace)) {
*strList = leftHdr;
ckfree((char *)headerPtr);
return strPtr;
}
next = BraceExpand(strPtr,inBrace,&rightHdr);
if (next==NULL) {
ckfree((char *)leftHdr);
ckfree((char *)headerPtr);
*strList = rightHdr;
return NULL;
}
LIST_FORALL(leftHdr,leftPtr) {
left = ((stringList *)leftPtr)->str;
leftLen = strlen(left);
LIST_FORALL(rightHdr,rightPtr) {
right = ((stringList *)rightPtr)->str;
stringElt = (stringList *)ckalloc(sizeof(stringList));
List_InitElement((List_Links *)stringElt);
stringElt->str = (char *)ckalloc((unsigned)strlen(left)+
strlen(right)+1);
(void)strcpy(stringElt->str,left);
(void)strcpy(stringElt->str+leftLen,right);
List_Insert((List_Links *)stringElt,
LIST_ATREAR(headerPtr));
}
}
FREE(leftHdr);
FREE(rightHdr);
*strList = headerPtr;
return next;
}
#define VALID "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\
0123456789-"
static int
Tilde(pattern,interp,result)
char *pattern;
Tcl_Interp *interp;
char **result;
{
int len;
struct passwd *pwPtr;
char *strPtr;
int ret;
pattern++;
len = strspn(pattern,VALID);
if (len==0) {
strPtr = (char *)getlogin();
if (strPtr==NULL) {
interp->result = "no home directory";
return TCL_ERROR;
}
}
else {
strPtr = (char *)ckalloc((unsigned)len+1);
strncpy(strPtr,pattern,len);
strPtr[len] = '\0';
}
pwPtr = getpwnam(strPtr);
if (pwPtr==NULL) {
sprintf(interp->result,"Unknown user: %s.",strPtr);
ret = TCL_ERROR;
}
else {
*result = (char *)ckalloc((unsigned)strlen(pattern+len)+
strlen(pwPtr->pw_dir)+1);
(void) strcpy(*result,pwPtr->pw_dir);
(void) strcpy(*result+strlen(pwPtr->pw_dir),pattern+len);
ret = TCL_OK;
}
if (len>0) {
ckfree(strPtr);
}
return ret;
}
int
Tcl_Glob(interp, argc, argv)
Tcl_Interp *interp;
int argc;
char *argv[];
{
List_Links *stringHdr;
stringList *stringElt;
List_Links *resultList;
List_Links *linkPtr;
int length = 0;
char *strPtr;
char *str2Ptr;
char **fileList;
char **fileList1;
int i;
resultList = (List_Links *) ckalloc(sizeof(List_Links));
List_Init(resultList);
for (i=1;i<argc;i++) {
if (!strcmp(argv[i],"{") || !strcmp(argv[i],"{}")) {
stringElt = (stringList *)ckalloc(sizeof(stringList));
List_InitElement((List_Links *)stringElt);
stringElt->str = (char *)ckalloc((unsigned)strlen(argv[i])+1);
(void)strcpy(stringElt->str,argv[i]);
List_Insert((List_Links *)stringElt,
LIST_ATREAR(resultList));
} else if (BraceExpand(argv[i],0,&stringHdr)==NULL) {
strcpy(interp->result,
((stringList *)List_First(stringHdr))->str);
FREE(resultList);
FREE(stringHdr);
return TCL_ERROR;
} else {
List_ListInsert(stringHdr,LIST_ATREAR(resultList));
ckfree((char *)stringHdr);
}
}
stringHdr = (List_Links *)ckalloc(sizeof(List_Links));
List_Init(stringHdr);
LIST_FORALL(resultList,linkPtr) {
strPtr = ((stringList *)linkPtr)->str;
if (*strPtr == '~') {
if (Tilde(strPtr,interp,&str2Ptr) != TCL_OK) {
FREE(resultList);
FREE(stringHdr);
return TCL_ERROR;
} else {
ckfree(strPtr);
((stringList *)linkPtr)->str = str2Ptr;
strPtr = str2Ptr;
}
}
if (glob_pattern_p(strPtr)) {
fileList = (char **)glob_filename(strPtr);
if ((int)fileList==-1) {
strcpy(interp->result,sys_errlist[errno]);
FREE(resultList);
FREE(stringHdr);
return TCL_ERROR;
} else {
for (fileList1=fileList; *fileList1!='\0'; fileList1++) {
length += strlen(*fileList1)+1;
stringElt = (stringList *)ckalloc(sizeof(stringList));
List_InitElement((List_Links *)stringElt);
stringElt->str =
(char *)ckalloc((unsigned)strlen(*fileList1)+1);
strcpy(stringElt->str,*fileList1);
List_Insert((List_Links *)stringElt,
LIST_ATREAR(stringHdr));
ckfree(*fileList1);
}
ckfree((char *)fileList);
}
} else {
length += strlen(strPtr)+1;
stringElt = (stringList *)ckalloc(sizeof(stringList));
List_InitElement((List_Links *)stringElt);
stringElt->str = strPtr;
((stringList *)linkPtr)->str = NULL;
List_Insert((List_Links *)stringElt,LIST_ATREAR(stringHdr));
}
}
FREE(resultList);
if (List_IsEmpty(stringHdr)) {
FREE(stringHdr);
sprintf(interp->result,"%.50s couldn't find file that matches pattern",
argv[0]);
return TCL_ERROR;
}
strPtr = (char *)ckalloc((unsigned) length);
interp->result = strPtr;
interp->dynamic = 1;
LIST_FORALL(stringHdr,linkPtr) {
strcpy(strPtr,((stringList *)linkPtr)->str);
strPtr += strlen(strPtr)+1;
strPtr[-1] = ' ';
}
strPtr[-1] = '\0';
FREE(stringHdr);
return TCL_OK;
}