This is files.c in view mode; [Download] [Up]
/*
docgen Objective C Document Generator
Copyright (C) 1995 Bill Bereza.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Email:
berezaw@river.it.gvsu.edu
S-mail:
Bill Bereza
9526 Judson Rd.
Ravenna, MI 49451-9427
*/
/* docgen Objective C Document Generator
* Copyright (c) 1994 Bill Bereza
*
* $Log: files.c,v $
* Revision 1.7 96/01/07 01:29:26 berezaw
* added hashtable caching of return values for findfile
* a %700 increase in performance!
*
* Revision 1.6 95/07/26 21:46:18 berezaw
* *** empty log message ***
*
* Revision 1.5 95/07/21 21:40:12 berezaw
* *** empty log message ***
*
* Revision 1.4 95/07/20 00:30:19 berezaw
* changed struct direct to struct dirent through the entire file
*
* Revision 1.3 95/03/02 03:44:43 berezaw
* using GNU regex library
* rewrote recmp() as docgen_recmp()
* added GPL stuff to each file
* increase rev. to 0.1.9
*
* Revision 1.2 94/11/28 12:08:32 berezaw
* *** empty log message ***
*
*
* $Header: /Users/berezaw/src/docgen/test/RCS/files.c,v 1.7 96/01/07 01:29:26 berezaw Exp $
*/
#include "docgen.h"
#include <assert.h>
#define H_SIZE 1024
char null_string[]="...";
char **file_hash;
char **file_val;
static void init_hash() {
int loop;
file_hash=calloc(H_SIZE, sizeof(char *));
file_val =calloc(H_SIZE, sizeof(char *));
if(V_USELESS)
fprintf(stderr, "init_hash\n");
for(loop=0;loop<H_SIZE;loop++) {
file_val[loop]=file_hash[loop]=NULL;
}
}
static int shash(char *st) {
int hash, loop, len;
len=strlen(st);
hash=st[0];
for(loop=0;loop<len;loop++) {
hash=(hash * 32 + st[loop]) % H_SIZE;
}
return hash;
}
static int find_val(char *key) {
int coll=0, pos;
pos=shash(key);
while(file_hash[pos] && strcmp(key, file_hash[pos]) && coll<H_SIZE) {
assert(pos<H_SIZE);
coll++;
pos=pos+2*coll-1;
if(pos>=H_SIZE)
pos-=H_SIZE;
}
if(file_hash[pos]) {
if(V_USELESS)
fprintf(stderr, "find_val:found val %s for key %s at pos %d\n", file_val[pos], key, pos);
}
else {
if(V_USELESS)
fprintf(stderr, "find_val:could not find val for key %s at pos %d\n", key, pos);
}
return pos;
}
static void add_key_val(char *key, char *val) {
char *valcp=NULL;
char *keycp=NULL;
int pos;
keycp=malloc(strlen(key)+1);
if(!keycp)
return;
strcpy(keycp, key);
pos=find_val(key);
if(val) {
valcp=malloc(strlen(val)+1);
if(!valcp) {
free(keycp);
return;
}
strcpy(valcp, val);
}
if(!file_hash[pos]) {
file_hash[pos]=keycp;
file_val[pos]=(valcp ? valcp : null_string) ;
if(V_USELESS)
fprintf(stderr, "findfile: adding key %s, val %s, pos %d\n", key, val, pos);
}
else {
free(keycp);
free(valcp);
}
}
char *_findfile(char *, char *);
char *findfile(char *name, char *dir)
{
static int first=1;
char *ret;
int pos;
char *full;
char *t;
if(first) {
init_hash();
first=0;
}
full=dirfile(dir, name);
pos=find_val(full);
if(file_hash[pos]) {
if(V_USELESS)
fprintf(stderr, "findfile: returning %s from hashtable\n", file_val[pos]);
free(full);
ret = (!strcmp(file_val[pos], null_string)) ? NULL : file_val[pos];
if(!ret) return NULL;
t=malloc(strlen(ret)+1);
if(!t) return NULL;
strcpy(t,ret);
return t;
}
else {
ret=_findfile(name, dir);
add_key_val(full, ret);
free(full);
return ret;
}
}
/* Just in case I switch over to requiring Objective-C
char *findfile(char *name, char *dir)
{
static HashTable fileTable=nil;
char *value;
char *key;
char nulls[]="...";
char *valcp;
if(!fileTable) {
fileTable=[[HashTable alloc] initKeyDesc:"*" valueDesc:"*"];
}
key=dirfile(dir, name);
value=(char *)[fileTable valueForKey:key];
if(!value) {
value=_findfile(name, dir);
if(value) {
valcp=malloc(strlen(value)+1);
strcpy(valcp, value);
}
else {
valcp=nulls;
}
[fileTable insertKey:key value:valcp];
}
if(!strcmp(value, nulls)) {
return NULL;
}
else {
return value;
}
}
*/
char *_findfile(char *name, char *dir)
{
struct dirent *dp;
DIR *dfd;
static char errmess[1024];
char *newf=NULL;
char *fulldir;
struct stat stbuf;
#ifndef NODEBUG
if(V_USELESS)
fprintf(stderr, "findfile(%s, %s)\n", dir, name);
#endif
if((dfd=opendir(dir)) == NULL) {
sprintf(errmess, "findfile: Are you sure about this dir?\n%.1000s",dir);
if(V_BADERR)
perror(errmess);
return NULL;
}
while (((dp=readdir(dfd)) != NULL) && (newf==NULL)) {
if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
continue; /* skip self and parent */
fulldir=dirfile(dir, dp->d_name);
if(stat(fulldir, &stbuf) == -1) {
#ifndef NODEBUG
if(V_ERR)
fprintf(stderr,"findfile: error getting stats of \n%s\n", fulldir);
#endif
free(fulldir);
continue;
}
else if((stbuf.st_mode & S_IFMT) == S_IFDIR) {
newf=_findfile(name, fulldir);
free(fulldir);
}
else if(!strcmp(dp->d_name, name))
newf=fulldir;
else
free(fulldir);
}
closedir(dfd);
#ifndef NODEBUG
if(V_USELESS)
fprintf(stderr, "findfile: returning\n%s\n",newf);
#endif
return newf;
}
/* blatantly copied from K&R */
void dirwalk(char *dir, void (*fcn)(char *, char *, char *, char *), char *odir, char *hdir)
{
struct dirent *dp;
DIR *dfd;
char errmess[1024];
#ifndef NODEBUG
if(V_USELESS)
fprintf(stderr, "dirwalk(%s, func, %s, %s)\n", dir, odir, hdir);
#endif
if((dfd=opendir(dir)) == NULL) {
sprintf(errmess, "dirwalk: Are you sure about this dir?\n%.1000s",dir);
if(V_BADERR)
perror(errmess);
return;
}
while ((dp=readdir(dfd)) != NULL) {
if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
continue; /* skip self and parent */
(*fcn)(dp->d_name, dir, odir, hdir);
}
closedir(dfd);
#ifndef NODEBUG
if(V_USELESS)
fprintf(stderr, "dirwalk: returning\n");
#endif
}
void procfile(char *name, char *idir, char *odir, char *hdir)
{
struct stat stbuf;
char *dir;
char errmess[1024];
dir=dirfile(idir, name);
#ifndef NODEBUG
if(V_USELESS)
printf("procfile( %s, %s, %s, %s)\n", name, idir, odir, hdir);
#endif
if(stat(dir, &stbuf) == -1) {
sprintf(errmess,"procfile: can't access this file\n%.800s/%.200s",idir, name);
if(V_BADERR)
perror(errmess);
return;
}
if((stbuf.st_mode & S_IFMT) == S_IFDIR)
dirwalk(dir, procfile, odir, hdir);
else if(strstr(&name[strlen(name)-3], ".m") != NULL)
procm(name, idir, odir, hdir);
free(dir);
#ifndef NODEBUG
if(V_USELESS)
fprintf(stderr, "procfile: returning\n");
#endif
}
char *dirfile(char *idir, char *name)
{
DSTRING *ddir;
char *dir;
#ifndef NODEBUG
if(V_USELESS)
fprintf(stderr, "dirfile(%s, %s)\n", idir, name);
#endif
ddir=dstrarr(idir);
dstrarrcat(ddir, "/");
dstrarrcat(ddir, name);
dir=arrdstr(ddir);
freedstr(ddir);
#ifndef NODEBUG
if(V_USELESS)
fprintf(stderr, "dirfile: returning with %s\n", dir);
#endif
return dir;
}
void procm(char *mname, char *idir, char *odir, char *hdir)
{
DSTRING *dhname;
char *hname, *fqmname, *fqhname, *rtfname, *fqrtfname;
int parseret;
#ifndef NODEBUG
if(V_USELESS)
fprintf(stderr,"procm(%s, %s, %s, %s)\n",mname, idir, odir, hdir);
#endif
/* remove '.m' from file name and add '.h' */
dhname=dstrarr(mname);
free(arrdstrrmfromtail(dhname, 2)); /* This function allocates memory
* so it must be free'd
*/
dstrarrcat(dhname, ".h");
hname=arrdstr(dhname); /* plain name of '.h' file */
/* mname is the plain name of the '.m' file */
/* remove '.h' from file name and add '.rtf' */
free(arrdstrrmfromtail(dhname, 2));
daddchar(dhname,'.');
dstrarrcat(dhname, [[myForm class] fileExtension]);
rtfname=arrdstr(dhname); /* plain name of '.rtf' file */
fqmname= dirfile(idir, mname); /* FQN of '.m' file */
fqhname= dirfile(idir, hname); /* FQN of '.h' file */
fqrtfname= dirfile(odir, rtfname); /* FQN of '.rtf' file */
parseret=parseobjc(fqmname, fqhname, fqrtfname, hdir);
#ifndef NODEBUG
if(parseret<0)
if(V_STAT)
fprintf(stderr, "Couldn't parse with the following args\nidir = [%s]\nfqmname = [%s]\nfqhanem = [%s]\nodir = [%s]\nhdir = [%s]\n", idir, fqmname, fqhname, odir, hdir);
#endif
/* free all the things we've created */
freedstr(dhname);
free(hname); free(fqmname); free(fqhname); free(rtfname); free(fqrtfname);
#ifndef NODEBUG
if(V_USELESS)
fprintf(stderr, "procm: returning\n");
#endif
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.