void MR_trace_report(FILE *fp) { if (MR_trace_event_number > 0) { // This means that the executable was compiled with tracing, // which implies that the user wants trace info on abort. if (MR_trace_report_msg != NULL) { fprintf(fp, "%s\n", MR_trace_report_msg); } if (MR_standardize_event_details) { fprintf(fp, "Last trace event was event #E%ld.\n", (long) MR_standardize_event_num(MR_trace_event_number)); } else { fprintf(fp, "Last trace event was event #%ld.\n", (long) MR_trace_event_number); } #ifdef MR_TRACE_HISTOGRAM { FILE *hfp; char errbuf[MR_STRERROR_BUF_SIZE]; hfp = fopen(MR_TRACE_HISTOGRAM_FILENAME, "w"); if (hfp != NULL) { MR_trace_print_histogram(hfp, "All-inclusive", MR_trace_histogram_all, MR_trace_histogram_hwm); if (fclose(hfp) == 0) { fprintf(fp, "Event histogram put into file `%s'.\n", MR_TRACE_HISTOGRAM_FILENAME); } else { fprintf(fp, "Cannot put event histogram into `%s': %s." MR_TRACE_HISTOGRAM_FILENAME, MR_strerror(errno, errbuf, sizeof(errbuf))); } } else { fprintf(fp, "Cannot open `%s': %s.\n" MR_TRACE_HISTOGRAM_FILENAME, MR_strerror(errno, errbuf, sizeof(errbuf))); } } #endif // MR_TRACE_HISTOGRAM } }
void MR_checked_atexit(void (*func)(void)) { char errbuf[MR_STRERROR_BUF_SIZE]; errno = 0; if (atexit(func) != 0) { fprintf(stderr, "Mercury runtime: error in call to atexit: %s\n", MR_strerror(errno, errbuf, sizeof(errbuf))); exit(EXIT_FAILURE); } }
void MR_checked_fclose(FILE *file, const char *filename) { char errbuf[MR_STRERROR_BUF_SIZE]; errno = 0; if (fclose(file) != 0) { fprintf(stderr, "Mercury runtime: error closing file `%s': %s\n", filename, MR_strerror(errno, errbuf, sizeof(errbuf))); exit(EXIT_FAILURE); } }
FILE * MR_checked_fopen(const char *filename, const char *message, const char *mode) { FILE *file; char errbuf[MR_STRERROR_BUF_SIZE]; errno = 0; file = fopen(filename, mode); if (file == NULL) { fprintf(stderr, "Mercury runtime: couldn't %s file `%s': %s\n", message, filename, MR_strerror(errno, errbuf, sizeof(errbuf))); exit(EXIT_FAILURE); } return file; }
void MR_trace_record_label_exec_counts(void *dummy) { FILE *fp; char *name; unsigned name_len; MR_bool summarize; MR_bool keep; char *slash; const char *program_name; char errbuf[MR_STRERROR_BUF_SIZE]; program_name = MR_copy_string(MR_progname); slash = strrchr(program_name, '/'); if (slash != NULL) { program_name = slash + 1; } summarize = MR_FALSE; keep = MR_FALSE; if (MR_trace_count_summary_file != NULL) { if (MR_FILE_EXISTS(MR_trace_count_summary_file)) { int i; // 30 bytes must be enough for the dot, the value of i, and '\0'. name_len = strlen(MR_trace_count_summary_file) + 30; name = MR_malloc(name_len); fp = NULL; // Search for a suffix that doesn't exist yet. for (i = 1; i <= MR_trace_count_summary_max; i++) { snprintf(name, name_len, "%s.%d", MR_trace_count_summary_file, i); if (! MR_FILE_EXISTS(name)) { // File doesn't exist, commit to this one. if (i == MR_trace_count_summary_max) { summarize = MR_TRUE; } break; } } } else { // The summary file doesn't yet exist, create it. name = MR_copy_string(MR_trace_count_summary_file); } } else if (MR_trace_counts_file) { name = MR_copy_string(MR_trace_counts_file); keep = MR_TRUE; } else { char *s; // If no trace counts file name is provided, then we generate // a file name. // 100 bytes must be enough for the process id, dots and '\0'. name_len = strlen(MERCURY_TRACE_COUNTS_PREFIX) + strlen(program_name) + 100; name = MR_malloc(name_len); snprintf(name, name_len, ".%s.%s.%d", MERCURY_TRACE_COUNTS_PREFIX, program_name, getpid()); // Make sure name is an acceptable filename. for (s = name; *s != '\0'; s++) { if (*s == '/') { *s = '_'; } } } fp = fopen(name, "w"); if (fp != NULL) { unsigned num_written; num_written = MR_trace_write_label_exec_counts(fp, program_name, MR_coverage_test_enabled); (void) fclose(fp); if (num_written == 0 && !keep) { // We did not write out any trace counts, so there is nothing // to gather. (void) unlink(name); summarize = MR_FALSE; } } else { fprintf(stderr, "%s: %s\n", name, MR_strerror(errno, errbuf, sizeof(errbuf))); // You can't summarize a file list if you can't create // one of its files. summarize = MR_FALSE; } free(name); if (summarize) { char *cmd; unsigned cmd_len; int summary_status; int mv_status; int unlink_status; int i; const char *old_options; // 30 bytes must be enough for the dot, the value of i, and space. name_len = strlen(MR_trace_count_summary_file) + 30; name = MR_malloc(name_len); cmd_len = strlen(MR_trace_count_summary_cmd) + 4; cmd_len += strlen(MR_trace_count_summary_file) + strlen(TEMP_SUFFIX) + 1; cmd_len += (MR_trace_count_summary_max + 1) * name_len; cmd_len += 100; cmd = MR_malloc(cmd_len); strcpy(cmd, MR_trace_count_summary_cmd); strcat(cmd, " -o "); strcat(cmd, MR_trace_count_summary_file); strcat(cmd, TEMP_SUFFIX); strcat(cmd, " "); strcat(cmd, MR_trace_count_summary_file); for (i = 1; i <= MR_trace_count_summary_max; i++) { snprintf(name, name_len, "%s.%d", MR_trace_count_summary_file, i); strcat(cmd, " "); strcat(cmd, name); } strcat(cmd, " > /dev/null 2>&1"); old_options = getenv("MERCURY_OPTIONS"); if (old_options != NULL) { (void) MR_setenv("MERCURY_OPTIONS", "", MR_TRUE); summary_status = system(cmd); (void) MR_setenv("MERCURY_OPTIONS", old_options, MR_TRUE); } else { summary_status = system(cmd); } if (summary_status == 0) { strcpy(cmd, "mv "); strcat(cmd, MR_trace_count_summary_file); strcat(cmd, TEMP_SUFFIX); strcat(cmd, " "); strcat(cmd, MR_trace_count_summary_file); mv_status = system(cmd); if (mv_status == 0) { // Delete all files whose data is now in the summary file. for (i = 1; i <= MR_trace_count_summary_max; i++) { snprintf(name, name_len, "%s.%d", MR_trace_count_summary_file, i); unlink_status = unlink(name); if (unlink_status != 0) { MR_fatal_error( "couldn't create summary of trace data"); } } } else { MR_fatal_error("couldn't create summary of trace data"); } } else { MR_fatal_error("couldn't create summary of trace data"); } free(name); free(cmd); } }