home *** CD-ROM | disk | FTP | other *** search
- /* iidfun.c - This file holds the utility functions called from iid.y
- */
-
- #include "iiddef.h"
-
- /* ArgListSize - count the size of an arg list so can alloca() enough
- * space for the command.
- */
- int
- ArgListSize(idlp)
- id_list_type * idlp ;
- {
- id_type * idep ;
- int size = 0;
-
- idep = idlp->id_list ;
- while (idep != NULL) {
- size += 1 + strlen(idep->id);
- idep = idep->next_id;
- }
- return size;
- }
-
- /* SetListSize - count the size of a string build up from a set so we can
- * alloca() enough space for args.
- */
- int
- SetListSize(sp)
- set_type * sp ;
- {
- int i ;
- int size = 0 ;
-
- for (i = 0; i < NextFileNum; ++i) {
- if (FileList[i]->mask_word < sp->set_size) {
- if (sp->set_data[FileList[i]->mask_word] & FileList[i]->mask_bit) {
- size += 1 + strlen(FileList[i]->name);
- }
- }
- }
- return size;
- }
-
- /* FlushFiles - clear out the TheFiles array for the start of a new
- * query.
- */
- void
- FlushFiles()
- {
- int i ;
-
- if (TheFiles != NULL) {
- for (i = 0; i <= MaxCurFile; ++i) {
- TheFiles[i] = 0 ;
- }
- }
- MaxCurFile = 0 ;
- }
-
- /* fatal - sometimes the only thing to do is die...
- */
- void
- fatal(s)
- {
- fprintf(stderr,"Fatal error: %s\n",s) ;
- exit(1) ;
- }
-
- /* CountBits - count the number of bits in a bit set. Actually fairly
- * tricky since it needs to deal with sets having infinite tails
- * as a result of a NOT operation.
- */
- int
- CountBits(sp)
- set_type * sp ;
- {
- unsigned long bit_mask ;
- int count = 0 ;
- int i ;
-
- i = 0;
- for ( ; ; ) {
- for (bit_mask = high_bit; bit_mask != 0; bit_mask >>= 1) {
- if (bit_mask == NextMaskBit && i == NextMaskWord) {
- return(count) ;
- }
- if (i < sp->set_size) {
- if (sp->set_data[i] & bit_mask) {
- ++count ;
- }
- } else {
- if (sp->set_tail == 0) return count;
- if (sp->set_tail & bit_mask) {
- ++count;
- }
- }
- }
- ++i;
- }
- }
-
- /* OneDescription - Print a description of a set. This includes
- * the set number, the number of files in the set, and the
- * set description string.
- */
- void
- OneDescription(sp)
- set_type * sp ;
- {
- int elt_count ;
- char setnum[20] ;
-
- sprintf(setnum,"S%d",sp->set_num) ;
- elt_count = CountBits(sp) ;
- printf("%5s %6d %s\n",setnum,elt_count,sp->set_desc) ;
- }
-
- /* DescribeSets - Print description of all the sets.
- */
- void
- DescribeSets()
- {
- int i ;
-
- if (NextSetNum > 0) {
- for (i = 0; i < NextSetNum; ++i) {
- OneDescription(TheSets[i]) ;
- }
- } else {
- printf("No sets defined yet.\n") ;
- }
- }
-
- /* SetList - Go through the bit set and add the file names in
- * it to an identifier list.
- */
- id_list_type *
- SetList(idlp, sp)
- id_list_type * idlp ;
- set_type * sp ;
- {
- int i ;
- id_type * idep ;
-
- for (i = 0; i < NextFileNum; ++i) {
- if (FileList[i]->mask_word < sp->set_size) {
- if (sp->set_data[FileList[i]->mask_word] & FileList[i]->mask_bit) {
- idep = (id_type *)malloc(sizeof(id_type) +
- strlen(FileList[i]->name)) ;
- if (idep == NULL) {
- fatal("Out of memory in SetList") ;
- }
- idep->next_id = NULL ;
- strcpy(idep->id, FileList[i]->name) ;
- idlp = ExtendList(idlp, idep) ;
- }
- }
- }
- return(idlp) ;
- }
-
- /* PrintSet - Go through the bit set and print the file names
- * corresponding to all the set bits.
- */
- void
- PrintSet(sp)
- set_type * sp ;
- {
- int i ;
-
- for (i = 0; i < NextFileNum; ++i) {
- if (FileList[i]->mask_word < sp->set_size) {
- if (sp->set_data[FileList[i]->mask_word] & FileList[i]->mask_bit) {
- printf("%s\n",FileList[i]->name) ;
- }
- }
- }
- }
-
- /* Free up all space used by current set of sets and reset all
- * set numbers.
- */
- void
- FlushSets()
- {
- int i ;
-
- for (i = 0; i < NextSetNum; ++i) {
- free(TheSets[i]->set_desc) ;
- free(TheSets[i]) ;
- }
- NextSetNum = 0 ;
- }
-
- /* InitList - create an empty identifier list.
- */
- id_list_type *
- InitList()
- {
- id_list_type * idlp ;
-
- idlp = (id_list_type *)malloc(sizeof(id_list_type)) ;
- if (idlp == NULL) {
- fatal("Out of memory in InitList") ;
- }
- idlp->id_count = 0 ;
- idlp->end_ptr_ptr = & (idlp->id_list) ;
- idlp->id_list = NULL ;
- return(idlp) ;
- }
-
- /* ExtendList - add one identifier to an ID list.
- */
- id_list_type *
- ExtendList(idlp, idp)
- id_list_type * idlp ;
- id_type * idp ;
- {
- *(idlp->end_ptr_ptr) = idp ;
- idlp->end_ptr_ptr = &(idp->next_id) ;
- return(idlp) ;
- }
-
- /* InitIid - do all initial processing for iid.
- * 1) Determine the size of a unsigned long for bit set stuff.
- * 2) Find out the name of the pager program to use.
- * 3) Create the HelpSet (pointing to the help file).
- * 4) Setup the prompt.
- */
- void
- InitIid()
- {
- unsigned long bit_mask = 1 ; /* find number of bits in long */
- int i ;
- char * page ; /* pager program */
-
- do {
- high_bit = bit_mask ;
- bit_mask <<= 1 ;
- } while (bit_mask != 0) ;
-
- NextMaskBit = high_bit ;
-
- page = getenv("PAGER") ;
- if (page == NULL) {
- page = PAGER ;
- }
- strcpy(Pager, page) ;
-
- FlushFiles() ;
- InstallFile(HELPFILE) ;
- HelpSet = (set_type *)
- malloc(sizeof(set_type) + sizeof(unsigned long) * MaxCurFile) ;
- if (HelpSet == NULL) {
- fatal("No memory for set in InitIid") ;
- }
- HelpSet->set_tail = 0 ;
- HelpSet->set_desc = NULL ;
- HelpSet->set_size = MaxCurFile + 1 ;
- for (i = 0; i <= MaxCurFile; ++i) {
- HelpSet->set_data[i] = TheFiles[i] ;
- }
-
- page = getenv("PS1") ;
- if (page == NULL) {
- page = PROMPT ;
- }
- strcpy(Prompt, page) ;
- }
-
- /* InstallFile - install a file name in the symtab. Return the
- * symbol table pointer of the file.
- */
- symtab_type *
- InstallFile(fp)
- char * fp ;
- {
- char c ;
- unsigned long hash_code ;
- int i ;
- char * sp ;
- symtab_type * symp ;
-
- hash_code = 0 ;
- sp = fp ;
- while ((c = *sp++) != '\0') {
- hash_code <<= 1 ;
- hash_code ^= (unsigned long)(c) ;
- if (hash_code & high_bit) {
- hash_code &= ~ high_bit ;
- hash_code ^= 1 ;
- }
- }
- hash_code %= HASH_SIZE ;
- symp = HashTable[hash_code] ;
- while (symp != NULL && strcmp(symp->name, fp)) {
- symp = symp->hash_link ;
- }
- if (symp == NULL) {
- symp = (symtab_type *)malloc(sizeof(symtab_type) + strlen(fp)) ;
- if (symp == NULL) {
- fatal("No memory for symbol table entry in InstallFile") ;
- }
- strcpy(symp->name, fp) ;
- symp->hash_link = HashTable[hash_code] ;
- HashTable[hash_code] = symp ;
- if (NextMaskWord >= FileSpace) {
- FileSpace += 1000 ;
- if (TheFiles != NULL) {
- TheFiles = (unsigned long *)
- realloc(TheFiles, sizeof(unsigned long) * FileSpace) ;
- } else {
- TheFiles = (unsigned long *)
- malloc(sizeof(unsigned long) * FileSpace) ;
- }
- if (TheFiles == NULL) {
- fatal("No memory for TheFiles in InstallFile") ;
- }
- for (i = NextMaskWord; i < FileSpace; ++i) {
- TheFiles[i] = 0 ;
- }
- }
- symp->mask_word = NextMaskWord ;
- symp->mask_bit = NextMaskBit ;
- NextMaskBit >>= 1 ;
- if (NextMaskBit == 0) {
- NextMaskBit = high_bit ;
- ++NextMaskWord ;
- }
- if (NextFileNum >= ListSpace) {
- ListSpace += 1000 ;
- if (FileList == NULL) {
- FileList = (symtab_type **)
- malloc(sizeof(symtab_type *) * ListSpace) ;
- } else {
- FileList = (symtab_type **)
- realloc(FileList, ListSpace * sizeof(symtab_type *)) ;
- }
- if (FileList == NULL) {
- fatal("No memory for FileList in InstallFile") ;
- }
- }
- FileList[NextFileNum++] = symp ;
- /* put code here to sort the file list by name someday */
- }
- TheFiles[symp->mask_word] |= symp->mask_bit ;
- if (symp->mask_word > MaxCurFile) {
- MaxCurFile = symp->mask_word ;
- }
- return(symp) ;
- }
-
- /* RunPager - run the users pager program on the list of files
- * in the set.
- */
- void
- RunPager(pp, sp)
- char * pp ;
- set_type * sp ;
- {
- char * cmd = (char *)alloca(SetListSize(sp) + strlen(pp) + 2);
- int i ;
- id_type * idep ;
-
- strcpy(cmd, pp) ;
- for (i = 0; i < NextFileNum; ++i) {
- if (FileList[i]->mask_word < sp->set_size) {
- if (sp->set_data[FileList[i]->mask_word] & FileList[i]->mask_bit) {
- strcat(cmd, " ") ;
- strcat(cmd, FileList[i]->name) ;
- }
- }
- }
- system(cmd) ;
- }
-
- /* AddSet - add a new set to the universal list of sets. Assign
- * it the next set number.
- */
- void
- AddSet(sp)
- set_type * sp ;
- {
- if (NextSetNum >= SetSpace) {
- SetSpace += 1000 ;
- if (TheSets != NULL) {
- TheSets = (set_type **)
- realloc(TheSets, sizeof(set_type *) * SetSpace) ;
- } else {
- TheSets = (set_type **)
- malloc(sizeof(set_type *) * SetSpace) ;
- }
- if (TheSets == NULL) {
- fatal("No memory for TheSets in AddSet") ;
- }
- }
- sp->set_num = NextSetNum ;
- TheSets[NextSetNum++] = sp ;
- }
-
- /* RunProg - run a program with arguments from id_list and
- * accept list of file names back from the program which
- * are installed in the symbol table and used to construct
- * a new set.
- */
- set_type *
- RunProg(pp, idlp)
- char * pp ;
- id_list_type * idlp ;
- {
- int c ;
- char * cmd = (char *)alloca(ArgListSize(idlp) + strlen(pp) + 2);
- char * dp ;
- char file [ MAXCMD ] ;
- int i ;
- id_type * idep ;
- id_type * next_id ;
- FILE * prog ;
- set_type * sp ;
-
- FlushFiles() ;
- strcpy(cmd, pp) ;
- idep = idlp->id_list ;
- while (idep != NULL) {
- strcat(cmd, " ") ;
- strcat(cmd, idep->id) ;
- next_id = idep->next_id ;
- free(idep) ;
- idep = next_id ;
- }
- free(idlp) ;
-
- /* run program with popen, reading the output. Assume each
- * white space terminated string is a file name.
- */
- prog = popen(cmd, "r") ;
- dp = file ;
- while ((c = getc(prog)) != EOF) {
- if (isspace(c)) {
- if (dp != file) {
- *dp++ = '\0' ;
- InstallFile(file) ;
- dp = file ;
- }
- } else {
- *dp++ = c ;
- }
- }
- if (dp != file) {
- *dp++ = '\0' ;
- InstallFile(file) ;
- }
- if (pclose(prog) != 0) {
- /* if there was an error make an empty set, who knows what
- * garbage the program printed.
- */
- FlushFiles() ;
- }
-
- sp = (set_type *)
- malloc(sizeof(set_type) + sizeof(unsigned long) * MaxCurFile) ;
- if (sp == NULL) {
- fatal("No memory for set in RunProg") ;
- }
- sp->set_tail = 0 ;
- sp->set_desc = (char *)malloc(strlen(cmd) + 1) ;
- if (sp->set_desc == NULL) {
- fatal("No memory for set description in RunProg") ;
- }
- strcpy(sp->set_desc, cmd) ;
- sp->set_size = MaxCurFile + 1 ;
- for (i = 0; i <= MaxCurFile; ++i) {
- sp->set_data[i] = TheFiles[i] ;
- }
- AddSet(sp) ;
- return(sp) ;
- }
-
- /* SetDirectory - change the working directory. This will
- * determine which ID file is found by the subprograms.
- */
- void
- SetDirectory(dir)
- id_type * dir ;
- {
- if (chdir(dir->id) != 0) {
- fprintf(stderr,"Directory %s not accessible.\n",dir) ;
- }
- free(dir) ;
- }
-
- /* SetIntersect - construct a new set from the intersection
- * of two others. Also construct a new description string.
- */
- set_type *
- SetIntersect(sp1, sp2)
- set_type * sp1 ;
- set_type * sp2 ;
- {
- char * desc ;
- int i ;
- int len1 ;
- int len2 ;
- set_type * new_set ;
- int new_size ;
-
- if (sp1->set_tail || sp2->set_tail) {
- new_size = MAX(sp1->set_size, sp2->set_size) ;
- } else {
- new_size = MIN(sp1->set_size, sp2->set_size) ;
- }
- new_set = (set_type *)malloc(sizeof(set_type) +
- (new_size - 1) * sizeof(unsigned long)) ;
- if (new_set == NULL) {
- fatal("No memory for set in SetIntersect") ;
- }
- len1 = strlen(sp1->set_desc) ;
- len2 = strlen(sp2->set_desc) ;
- desc = (char *)malloc(len1 + len2 + 10) ;
- if (desc == NULL) {
- fatal("No memory for set description in SetIntersect") ;
- }
- new_set->set_desc = desc ;
- strcpy(desc,"(") ;
- ++desc ;
- strcpy(desc, sp1->set_desc) ;
- desc += len1 ;
- strcpy(desc, ") AND (") ;
- desc += 7 ;
- strcpy(desc, sp2->set_desc) ;
- desc += len2 ;
- strcpy(desc, ")") ;
- AddSet(new_set) ;
- new_set->set_size = new_size ;
- for (i = 0; i < new_size; ++i) {
- new_set->set_data[i] =
- ((i < sp1->set_size) ? sp1->set_data[i] : sp1->set_tail) &
- ((i < sp2->set_size) ? sp2->set_data[i] : sp2->set_tail) ;
- }
- new_set->set_tail = sp1->set_tail & sp2->set_tail ;
- return(new_set) ;
- }
-
- /* SetUnion - construct a new set from the union of two others.
- * Also construct a new description string.
- */
- set_type *
- SetUnion(sp1, sp2)
- set_type * sp1 ;
- set_type * sp2 ;
- {
- char * desc ;
- int i ;
- int len1 ;
- int len2 ;
- set_type * new_set ;
- int new_size ;
-
- new_size = MAX(sp1->set_size, sp2->set_size) ;
- new_set = (set_type *)malloc(sizeof(set_type) +
- (new_size - 1) * sizeof(unsigned long)) ;
- if (new_set == NULL) {
- fatal("No memory for set in SetUnion") ;
- }
- len1 = strlen(sp1->set_desc) ;
- len2 = strlen(sp2->set_desc) ;
- desc = (char *)malloc(len1 + len2 + 9) ;
- if (desc == NULL) {
- fatal("No memory for set description in SetUnion") ;
- }
- new_set->set_desc = desc ;
- strcpy(desc,"(") ;
- ++desc ;
- strcpy(desc, sp1->set_desc) ;
- desc += len1 ;
- strcpy(desc, ") OR (") ;
- desc += 6 ;
- strcpy(desc, sp2->set_desc) ;
- desc += len2 ;
- strcpy(desc, ")") ;
- AddSet(new_set) ;
- new_set->set_size = new_size ;
- for (i = 0; i < new_size; ++i) {
- new_set->set_data[i] =
- ((i < sp1->set_size) ? (sp1->set_data[i]) : sp1->set_tail) |
- ((i < sp2->set_size) ? (sp2->set_data[i]) : sp2->set_tail) ;
- }
- new_set->set_tail = sp1->set_tail | sp2->set_tail ;
- return(new_set) ;
- }
-
- /* SetInverse - construct a new set from the inverse of another.
- * Also construct a new description string.
- *
- * This is kind of tricky. An inverse set in iid may grow during
- * the course of a session. By NOTing the set_tail extension the
- * inverse at any given time will be defined as the inverse against
- * a universe that grows as additional queries are made and new files
- * are added to the database.
- *
- * Several alternative definitions were possible (snapshot the
- * universe at the time of the NOT, go read the ID file to
- * determine the complete universe), but this one was the one
- * I picked.
- */
- set_type *
- SetInverse(sp)
- set_type * sp ;
- {
- char * desc ;
- int i ;
- set_type * new_set ;
-
- new_set = (set_type *)malloc(sizeof(set_type) +
- (sp->set_size - 1) * sizeof(unsigned long)) ;
- if (new_set == NULL) {
- fatal("No memory for set in SetInverse") ;
- }
- desc = (char *)malloc(strlen(sp->set_desc) + 5) ;
- if (desc == NULL) {
- fatal("No memory for set description in SetInverse") ;
- }
- new_set->set_desc = desc ;
- strcpy(desc,"NOT ") ;
- desc += 4 ;
- strcpy(desc, sp->set_desc) ;
- AddSet(new_set) ;
- new_set->set_size = sp->set_size ;
- for (i = 0; i < sp->set_size; ++i) {
- new_set->set_data[i] = ~ sp->set_data[i] ;
- }
- new_set->set_tail = ~ sp->set_tail ;
- return(new_set) ;
- }
-
- /* RunShell - run a program with arguments from id_list.
- */
- void
- RunShell(pp, idlp)
- char * pp ;
- id_list_type * idlp ;
- {
- char * cmd = (char *)alloca(ArgListSize(idlp) + strlen(pp) + 2);
- id_type * idep ;
- id_type * next_id ;
-
- strcpy(cmd, pp) ;
- idep = idlp->id_list ;
- while (idep != NULL) {
- strcat(cmd, " ") ;
- strcat(cmd, idep->id) ;
- next_id = idep->next_id ;
- free(idep) ;
- idep = next_id ;
- }
- free(idlp) ;
- system(cmd) ;
- }
-