/*------------------------------------------------------------------ * *------------------------------------------------------------------*/ int main(void) { Hash *iHash; int i; int counter; iHash = HashCreate(sizeof(int),3,compareFunc,hashFunc,NULL); for (i= 1; i<10; i++) HashAdd(iHash,&i); for (i=20; i>10; i--) HashAdd(iHash,&i); for (i=0; i<=21; i++) if (!HashFind(iHash,&i)) printf("didn't find %d\n",i); counter = 1; HashIterate(iHash,iterateFunc,&counter); for (i=-1; i<5; i++) HashDelete(iHash,&i); for (i=21; i>15; i--) HashDelete(iHash,&i); counter = 1; HashIterate(iHash,iterateFunc,&counter); HashDestroy(iHash); return 0; }
void ProcessPreprocessedFile(istream &in, const char *input_file) { Assert(g_working_directory && g_base_directory); // read our entire input into a buffer. Buffer file_buf; ReadInStream(in, &file_buf); // table with contents read so far for HashTable<String*,FileData,String> file_table; // name of the original file which was being parsed, from which we will // get whether this is a C or a C++ file. const char *base_file = NULL; char *pos = (char*) file_buf.base; FileData *cur_data = NULL; while (*pos) { if (*pos == '#' && *(pos+1) == ' ') { // found a preprocessor line directive. // currently we just parse lines of the format '# line "file" ... // eat the '#' pos++; char *end_pos = NULL; long line = strtol(pos, &end_pos, 10); Assert(line >= 1); Assert(end_pos); char *start_quote = strchr(end_pos, '"'); Assert(start_quote); char *end_quote = strchr(start_quote + 1, '"'); Assert(end_quote); char *end_line = strchr(pos, '\n'); Assert(end_line && end_line > end_quote); if (base_file == NULL) { // just mark the first # line directive we see as the base file. base_file = start_quote + 1; } *end_quote = 0; String *file = String::Make(NormalizeFile(start_quote + 1)); Vector<FileData> *entries = file_table.Lookup(file, true); if (entries->Empty()) { entries->PushBack(FileData()); cur_data = &entries->Back(); cur_data->contents = new Buffer(); cur_data->cur_line = 1; } else { Assert(entries->Size() == 1); cur_data = &entries->Back(); } // insert enough newlines so that we've caught up with the # line. while ((long) cur_data->cur_line < line) { cur_data->contents->Append("\n", 1); cur_data->cur_line++; } // in some cases the # line directive will actually rewind the // apparent line to an earlier line, e.g.: // # 250 "foo.c" // something // else // # 250 "foo.c" // finally // in this case we'll replace the earlier newlines with spaces, // getting the string 'something else finally' at line 250. char *last_pos = (char*) cur_data->contents->pos - 1; while ((long) cur_data->cur_line > line) { while (*last_pos != '\n') last_pos--; *last_pos = ' '; cur_data->cur_line--; } pos = end_line + 1; continue; } if (cur_data == NULL) { // we can get here if the input is not actually preprocessed. // make data for the input file itself. Assert(input_file); String *file = String::Make(NormalizeFile(input_file)); Vector<FileData> *entries = file_table.Lookup(file, true); Assert(entries->Empty()); entries->PushBack(FileData()); cur_data = &entries->Back(); cur_data->contents = new Buffer(); cur_data->cur_line = 1; } char *end_line = strchr(pos, '\n'); if (end_line == NULL) { cur_data->contents->Append(pos, strlen(pos)); break; } cur_data->contents->Append(pos, end_line - pos + 1); cur_data->cur_line++; pos = end_line + 1; } // figure out which of the files we read need to be added to the dbs. Transaction *query = new Transaction(); HashIterate(file_table) QueryFileData(query, file_table.ItKey(), file_table.ItValueSingle()); SubmitTransaction(query); // add those files we found in the query. Transaction *dump = new Transaction(); HashIterate(file_table) DumpFileData(query, dump, file_table.ItKey(), file_table.ItValueSingle()); SubmitTransaction(dump); delete query; delete dump; HashIterate(file_table) delete file_table.ItValueSingle().contents; }