static void hash_init (unsigned int modulus, unsigned int entry_tab_size) { struct htab *htab_r; htab_r = (struct htab *) xmalloc (sizeof (struct htab) + sizeof (struct entry *) * modulus); htab_r->entry_tab = (struct entry *) xmalloc (sizeof (struct entry) * entry_tab_size); htab_r->modulus = modulus; htab_r->entry_tab_size = entry_tab_size; htab = htab_r; hash_reset (); }
void index_merge(const struct of *of, struct mparse *mp, struct buf *dbuf, struct buf *buf, DB *hash, struct mdb *mdb, struct recs *recs, const char *basedir) { recno_t rec; int ch, skip; DBT key, val; DB *files; /* temporary file name table */ char emptystring[1] = {'\0'}; struct mdoc *mdoc; struct man *man; char *p; const char *fn, *msec, *march, *mtitle; uint64_t mask; size_t sv; unsigned seq; uint64_t vbuf[2]; char type; if (warnings) { files = NULL; hash_reset(&files); } rec = 0; for (of = of->first; of; of = of->next) { fn = of->fname; /* * Try interpreting the file as mdoc(7) or man(7) * source code, unless it is already known to be * formatted. Fall back to formatted mode. */ mparse_reset(mp); mdoc = NULL; man = NULL; if ((MANDOC_SRC & of->src_form || ! (MANDOC_FORM & of->src_form)) && MANDOCLEVEL_FATAL > mparse_readfd(mp, -1, fn)) mparse_result(mp, &mdoc, &man); if (NULL != mdoc) { msec = mdoc_meta(mdoc)->msec; march = mdoc_meta(mdoc)->arch; if (NULL == march) march = ""; mtitle = mdoc_meta(mdoc)->title; } else if (NULL != man) { msec = man_meta(man)->msec; march = ""; mtitle = man_meta(man)->title; } else { msec = of->sec; march = of->arch; mtitle = of->title; } /* * Check whether the manual section given in a file * agrees with the directory where the file is located. * Some manuals have suffixes like (3p) on their * section number either inside the file or in the * directory name, some are linked into more than one * section, like encrypt(1) = makekey(8). Do not skip * manuals for such reasons. */ skip = 0; assert(of->sec); assert(msec); if (strcasecmp(msec, of->sec)) WARNING(fn, basedir, "Section \"%s\" manual " "in \"%s\" directory", msec, of->sec); /* * Manual page directories exist for each kernel * architecture as returned by machine(1). * However, many manuals only depend on the * application architecture as returned by arch(1). * For example, some (2/ARM) manuals are shared * across the "armish" and "zaurus" kernel * architectures. * A few manuals are even shared across completely * different architectures, for example fdformat(1) * on amd64, i386, sparc, and sparc64. * Thus, warn about architecture mismatches, * but don't skip manuals for this reason. */ assert(of->arch); assert(march); if (strcasecmp(march, of->arch)) WARNING(fn, basedir, "Architecture \"%s\" " "manual in \"%s\" directory", march, of->arch); /* * By default, skip a file if the title given * in the file disagrees with the file name. * Do not warn, this happens for all MLINKs. */ assert(of->title); assert(mtitle); if (strcasecmp(mtitle, of->title)) skip = 1; /* * Build a title string for the file. If it matches * the location of the file, remember the title as * found; else, remember it as missing. */ if (warnings) { buf->len = 0; buf_appendb(buf, mtitle, strlen(mtitle)); buf_appendb(buf, "(", 1); buf_appendb(buf, msec, strlen(msec)); if ('\0' != *march) { buf_appendb(buf, "/", 1); buf_appendb(buf, march, strlen(march)); } buf_appendb(buf, ")", 2); for (p = buf->cp; '\0' != *p; p++) *p = tolower(*p); key.data = buf->cp; key.size = buf->len; val.data = NULL; val.size = 0; if (0 == skip) val.data = emptystring; else { ch = (*files->get)(files, &key, &val, 0); if (ch < 0) { perror("hash"); exit((int)MANDOCLEVEL_SYSERR); } else if (ch > 0) { val.data = (void *)fn; val.size = strlen(fn) + 1; } else val.data = NULL; } if (NULL != val.data && (*files->put)(files, &key, &val, 0) < 0) { perror("hash"); exit((int)MANDOCLEVEL_SYSERR); } } if (skip && !use_all) continue; /* * The index record value consists of a nil-terminated * filename, a nil-terminated manual section, and a * nil-terminated description. Use the actual * location of the file, such that the user can find * it with man(1). Since the description may not be * set, we set a sentinel to see if we're going to * write a nil byte in its place. */ dbuf->len = 0; type = mdoc ? 'd' : (man ? 'a' : 'c'); buf_appendb(dbuf, &type, 1); buf_appendb(dbuf, fn, strlen(fn) + 1); buf_appendb(dbuf, of->sec, strlen(of->sec) + 1); buf_appendb(dbuf, of->title, strlen(of->title) + 1); buf_appendb(dbuf, of->arch, strlen(of->arch) + 1); sv = dbuf->len; /* * Collect keyword/mask pairs. * Each pair will become a new btree node. */ hash_reset(&hash); if (mdoc) pmdoc_node(hash, buf, dbuf, mdoc_node(mdoc), mdoc_meta(mdoc)); else if (man) pman_node(hash, buf, dbuf, man_node(man)); else pformatted(hash, buf, dbuf, of, basedir); /* Test mode, do not access any database. */ if (NULL == mdb->db || NULL == mdb->idx) continue; /* * Make sure the file name is always registered * as an .Nm search key. */ buf->len = 0; buf_append(buf, of->title); hash_put(hash, buf, TYPE_Nm); /* * Reclaim an empty index record, if available. * Use its record number for all new btree nodes. */ if (recs->cur > 0) { recs->cur--; rec = recs->stack[(int)recs->cur]; } else if (recs->last > 0) { rec = recs->last; recs->last = 0; } else rec++; vbuf[1] = htobe64(rec); /* * Copy from the in-memory hashtable of pending * keyword/mask pairs into the database. */ seq = R_FIRST; while (0 == (ch = (*hash->seq)(hash, &key, &val, seq))) { seq = R_NEXT; assert(sizeof(uint64_t) == val.size); memcpy(&mask, val.data, val.size); vbuf[0] = htobe64(mask); val.size = sizeof(vbuf); val.data = &vbuf; dbt_put(mdb->db, mdb->dbn, &key, &val); } if (ch < 0) { perror("hash"); exit((int)MANDOCLEVEL_SYSERR); } /* * Apply to the index. If we haven't had a description * set, put an empty one in now. */ if (dbuf->len == sv) buf_appendb(dbuf, "", 1); key.data = &rec; key.size = sizeof(recno_t); val.data = dbuf->cp; val.size = dbuf->len; if (verb) printf("%s: Adding to index: %s\n", basedir, fn); dbt_put(mdb->idx, mdb->idxn, &key, &val); } /* * Iterate the remembered file titles and check that * all files can be found by their main title. */ if (warnings) { seq = R_FIRST; while (0 == (*files->seq)(files, &key, &val, seq)) { seq = R_NEXT; if (val.size) WARNING((char *)val.data, basedir, "Probably unreachable, title " "is %s", (char *)key.data); } (*files->close)(files); } }
static int hash_insert (ino_t ino, dev_t dev) { struct htab *htab_r = htab; /* Initially a copy of the global `htab'. */ if (htab_r->first_free_entry >= htab_r->entry_tab_size) { int i; struct entry *ep; unsigned modulus; unsigned entry_tab_size; /* Increase the number of hash entries, and re-hash the data. The method of shrimping and increasing is made to compactify the heap. If twice as much data would be allocated straightforwardly, we would never re-use a byte of memory. */ /* Let `htab' shrimp. Keep only the header, not the pointer vector. */ htab_r = (struct htab *) xrealloc ((char *) htab_r, sizeof (struct htab)); modulus = 2 * htab_r->modulus; entry_tab_size = 2 * htab_r->entry_tab_size; /* Increase the number of possible entries. */ htab_r->entry_tab = (struct entry *) xrealloc ((char *) htab_r->entry_tab, sizeof (struct entry) * entry_tab_size); /* Increase the size of htab again. */ htab_r = (struct htab *) xrealloc ((char *) htab_r, sizeof (struct htab) + sizeof (struct entry *) * modulus); htab_r->modulus = modulus; htab_r->entry_tab_size = entry_tab_size; htab = htab_r; i = htab_r->first_free_entry; /* Make the increased hash table empty. The entries are still available in htab->entry_tab. */ hash_reset (); /* Go through the entries and install them in the pointer vector htab->hash. The items are actually inserted in htab->entry_tab at the position where they already are. The htab->coll_link need however be updated. Could be made a little more efficient. */ for (ep = htab_r->entry_tab; i > 0; i--) { hash_insert2 (htab_r, ep->ino, ep->dev); ep++; } } return hash_insert2 (htab_r, ino, dev); }
static void du_files (char **files) { struct saved_cwd cwd; ino_t initial_ino; /* Initial directory's inode. */ dev_t initial_dev; /* Initial directory's device. */ int i; /* Index in FILES. */ if (save_cwd (&cwd)) exit (1); /* Remember the inode and device number of the current directory. */ if (stat (".", &stat_buf)) error (1, errno, _("current directory")); initial_ino = stat_buf.st_ino; initial_dev = stat_buf.st_dev; for (i = 0; files[i]; i++) { char *arg; int s; arg = files[i]; /* Delete final slash in the argument, unless the slash is alone. */ s = strlen (arg) - 1; if (s != 0) { if (arg[s] == '\\') arg[s] = 0; str_copyc (path, arg); } else if (arg[0] == '\\') str_trunc (path, 0); /* Null path for root directory. */ else str_copyc (path, arg); if (!opt_combined_arguments) hash_reset (); count_entry (arg, 1, 0); /* chdir if `count_entry' has changed the working directory. */ if (stat (".", &stat_buf)) error (1, errno, "."); if (stat_buf.st_ino != initial_ino || stat_buf.st_dev != initial_dev) { if (restore_cwd (&cwd, _("starting directory"), NULL)) exit (1); } } if (opt_combined_arguments) { if (opt_human_readable) { char buf[LONGEST_HUMAN_READABLE + 1]; printf("%s\ttotal\n", human_readable (tot_size, buf, LONGEST_HUMAN_READABLE + 1)); } else { printf (_("%ld\ttotal\n"), output_size == size_bytes ? tot_size : convert_blocks (tot_size, output_size == size_kilobytes)); } fflush (stdout); } free_cwd (&cwd); }
int main(int argc, char **argv) { char buf[1024]; char *string[1024]; char *ptr, *chkstr; int loop, ctr = 0; hash_t *hash; testinfo("creating hash table"); if(!(hash = hash_create(0, strkey, free))) errkill(-1, "failed (%s)", strerror(errno)); passed(); /* load strings */ printf("\nloading strings from stdin:\n"); while(fgets(buf, sizeof(buf), stdin)) { printf("reading %i:", ctr); fflush(stdout); /* chomp newline */ ptr = ((buf + strlen(buf)) - 1); if((ptr >= buf) && (*ptr == '\n')) *ptr = 0; if(!ctr && !(chkstr = strdup(buf))) errkill(-1, "error loading strings"); if(!(string[ctr++] = strdup(buf))) errkill(-1, "error loading strings"); printf("[%s]\n", string[ctr - 1]); if(ctr >= 1024) break; } /* store strings in hash */ printf("\nstoring strings in hash:\n"); for(loop=0; loop<ctr; loop++) { testinfo("storing [%s]...", string[loop]); if(hash_set(hash, string[loop], string[loop])) errkill(-1, "failed"); passed(); } /* test values */ printf("\nlooking up stored values:\n"); for(loop=0; loop<ctr; loop++) { testinfo("testing [%s]", string[loop]); if(!(ptr = hash_get(hash, string[loop]))) errkill(-1, "failed"); if(strcmp(ptr, string[loop])) errkill(-1, "error"); passed(); } testinfo("\ntesting hash reset"); hash_reset(hash); if(hash_get(hash, chkstr)) errkill(-1, "reset failed"); free(chkstr); passed(); testinfo("\nfreeing hash table"); hash_free(hash); passed(); printf("\n-- all tests passed --\n\n"); return(0); }
/* mutator_reset */ int mutator_reset(Mutator * mutator) { return hash_reset(mutator); }
int compress (char* input_file_name) { int ret, c; FILE* input_file; int hash_elem_pointer; //pointer to the actual node input_file = fopen(input_file_name, "r"); //read a character and perform the compression until EOF is found while(1){ c = getc(input_file); again: if (c == EOF) { //emit the last father_index ret = emit((uint64_t)hash_elem_pointer); if (ret < 0) { fprintf(stderr, "Unable to emit the last symbol\n"); free(hash_table); return -1; } //emit the EOF value ret = emit((uint64_t)0); if (ret < 0) { fprintf(stderr, "Unable to emit the EOF\n"); free(hash_table); return -1; } break; } //search the character into the hash table ret = hash_search(hash_elem_pointer, (char)c); if (ret != 0) { //correspondent child was found so simply advance the pointer hash_elem_pointer = ret; } else { //emit the father_index ret = emit((uint64_t)hash_elem_pointer); if (ret < 0) { fprintf(stderr, "Unable to emit the EOF\n"); free(hash_table); return -1; } if (++hash_elem_counter == dictionary_size) hash_reset(); else{ //add the new node ret = hash_add(hash_elem_pointer, (char)c); if (ret != 0){ fprintf(stderr, "Error in hash_add"); free(hash_table); return -1; } } //restart the search from the root hash_elem_pointer = 0; //now search the character c again goto again; } } free(hash_table); return 0; }
/* * resets the hash table using hash_reset() */ void (conf_hashreset)(void) { hash_reset(); }