- pattern_entry_t *entry;
- pattern_entry_t **pattern_arr;
- pattern_dumper_t *dump;
- int i, count = pset_count(status->pattern_hash);
-
- printf("\n%d pattern detected\n", count);
-
- if (count <= 0)
- return;
-
- /* creates a dumper */
- dump = new_vcg_dumper("pattern.vcg", 100);
-
- pattern_arr = xmalloc(sizeof(*pattern_arr) * count);
- for (i = 0, entry = pset_first(status->pattern_hash);
- entry && i < count;
- entry = pset_next(status->pattern_hash), ++i) {
- pattern_arr[i] = entry;
- }
- assert(count == i);
- count = i;
-
- /* sort it */
- qsort(pattern_arr, count, sizeof(*pattern_arr), pattern_count_cmp);
-
- for (i = 0; i < count; ++i) {
- entry = pattern_arr[i];
- if (cnt_to_uint(&entry->count) < status->bound)
- continue;
-
- /* dump a pattern */
- pattern_dump_new_pattern(dump, &entry->count);
- decode_node(entry->buf, entry->len, dump);
- pattern_dump_finish_pattern(dump);
- }
-
- /* destroy it */
- pattern_end(dump);
-}
+ FILE *f;
+ pattern_entry_t *entry;
+ int i, count = pset_count(status->pattern_hash);
+
+ if (count <= 0)
+ return;
+
+ f = fopen(fname, "wb");
+ if (! f) {
+ perror(fname);
+ return;
+ } /* if */
+
+ fwrite("FPS1", 4, 1, f);
+ fwrite(&count, sizeof(count), 1, f);
+
+ for (i = 0, entry = (pattern_entry_t*)pset_first(status->pattern_hash);
+ entry && i < count;
+ entry = (pattern_entry_t*)pset_next(status->pattern_hash), ++i) {
+ fwrite(entry, offsetof(pattern_entry_t, buf) + entry->len, 1, f);
+ } /* for */
+ fclose(f);
+} /* store_pattern */
+
+/**
+ * Read collected patterns from a file.
+ *
+ * @param fname filename
+ */
+static HASH_MAP(pattern_entry_t) *read_pattern(const char *fname)
+{
+ FILE *f;
+ pattern_entry_t *entry, tmp;
+ int i, count;
+ unsigned j;
+ char magic[4];
+ HASH_MAP(pattern_entry_t) *pattern_hash = new_pset(pattern_cmp, 8);
+ BYTE buffer[PATTERN_STORE_SIZE];
+ CODE_BUFFER buf;
+
+ f = fopen(fname, "rb");
+ if (! f) {
+ perror(fname);
+ return NULL;
+ } /* if */
+
+ fread(magic, 4, 1, f);
+ count = 0;
+ fread(&count, sizeof(count), 1, f);
+ if (memcmp(magic, "FPS1", 4) != 0 || count <= 0) {
+ fprintf(stderr, "Error: %s is not a Firm pattern store. Ignored.\n", fname);
+ fclose(f);
+ return NULL;
+ } /* if */
+
+ /* read all pattern entries and put them into the hash table. */
+ for (i = 0; i < count; ++i) {
+ init_buf(&buf, buffer, sizeof(buffer));
+ fread(&tmp, offsetof(pattern_entry_t, buf), 1, f);
+ for (j = 0; j < tmp.len; ++j)
+ put_byte(&buf, fgetc(f));
+ entry = pattern_get_entry(&buf, pattern_hash);
+ memcpy(&entry->count, &tmp.count, sizeof(entry->count));
+ } /* for */
+ fclose(f);
+
+ printf("Read %d pattern from %s\n", count, fname);
+ assert(pset_count(pattern_hash) == count);
+
+ return pattern_hash;
+} /* read_pattern */
+
+/**
+ * Write the collected patterns to a VCG file for inspection.
+ *
+ * @param fname name of the VCG file to create
+ */
+static void pattern_output(const char *fname)
+{
+ pattern_entry_t *entry;
+ pattern_entry_t **pattern_arr;
+ pattern_dumper_t *dump;
+ int i, count = pset_count(status->pattern_hash);
+
+ printf("\n%d pattern detected\n", count);
+
+ if (count <= 0)
+ return;
+
+ /* creates a dumper */
+ dump = new_vcg_dumper(fname, 100);
+
+ pattern_arr = XMALLOCN(pattern_entry_t*, count);
+ for (i = 0, entry = (pattern_entry_t*)pset_first(status->pattern_hash);
+ entry && i < count;
+ entry = (pattern_entry_t*)pset_next(status->pattern_hash), ++i) {
+ pattern_arr[i] = entry;
+ } /* for */
+ assert(count == i);
+ count = i;
+
+ /* sort it */
+ qsort(pattern_arr, count, sizeof(*pattern_arr), pattern_count_cmp);
+
+ for (i = 0; i < count; ++i) {
+ entry = pattern_arr[i];
+ if (cnt_to_uint(&entry->count) < status->bound)
+ continue;
+
+ /* dump a pattern */
+ pattern_dump_new_pattern(dump, &entry->count);
+ decode_node(entry->buf, entry->len, dump);
+ pattern_dump_finish_pattern(dump);
+ } /* for */
+
+ /* destroy it */
+ pattern_end(dump);
+} /* pattern_output */