mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-11 03:45:33 +00:00
Branches: main, 11.07 trace/mercury_trace_tables.c: Fix a spot where uninitialized local variables were being used.
1999 lines
65 KiB
C
1999 lines
65 KiB
C
/*
|
|
** vim: ts=4 sw=4 expandtab
|
|
*/
|
|
/*
|
|
** Copyright (C) 1998-2007, 2011 The University of Melbourne.
|
|
** This file may only be copied under the terms of the GNU Library General
|
|
** Public License - see the file COPYING.LIB in the Mercury distribution.
|
|
*/
|
|
|
|
/*
|
|
** This file manages a table listing the debuggable modules of the program,
|
|
** and subsidiary tables listing the procedures of each of those modules.
|
|
**
|
|
** Main author: Zoltan Somogyi.
|
|
*/
|
|
|
|
#include "mercury_imp.h"
|
|
#include "mercury_label.h"
|
|
#include "mercury_array_macros.h"
|
|
#include "mercury_stack_layout.h"
|
|
#include "mercury_stack_trace.h"
|
|
#include "mercury_dlist.h"
|
|
|
|
#include "mercury_trace_tables.h"
|
|
#include "mercury_trace_internal.h"
|
|
#include "mercury_trace.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
MR_TraceEventSet *MR_trace_event_sets = NULL;
|
|
int MR_trace_event_set_next = 0;
|
|
int MR_trace_event_set_max = 0;
|
|
|
|
MR_bool MR_trace_event_sets_are_all_consistent = MR_TRUE;
|
|
int MR_trace_event_sets_max_num_attr = -1;
|
|
|
|
/*
|
|
** We record module layout structures in two tables. The MR_module_infos
|
|
** array contains one pointer to every module layout structure, and is ordered
|
|
** by the fully qualified module name. The MR_module_nickname array contains
|
|
** one reference to every module layout structure by every one of the module's
|
|
** (zero or more) less-than-fully-qualified names (which we call `nickname'
|
|
** here), ordered by the nickname.
|
|
*/
|
|
|
|
typedef struct {
|
|
const char *MR_nick_name;
|
|
MR_Dlist *MR_nick_layouts;
|
|
/* the list entries are MR_ModuleLayouts */
|
|
} MR_Module_Nick;
|
|
|
|
static MR_Module_Nick *MR_module_nicks;
|
|
static int MR_module_nick_next = 0;
|
|
static int MR_module_nick_max = 0;
|
|
|
|
static int MR_module_info_proc_count = 0;
|
|
|
|
#define INIT_MODULE_TABLE_SIZE 10
|
|
|
|
static const MR_ModuleLayout
|
|
*MR_search_module_info_by_name(const char *name);
|
|
static MR_Dlist *MR_search_module_info_by_nickname(const char *name);
|
|
static const MR_ModuleLayout
|
|
*MR_search_module_info_by_unique_name(FILE *fp,
|
|
const char *name);
|
|
|
|
static void MR_insert_module_info(const MR_ModuleLayout *module);
|
|
static void MR_process_matching_procedures_in_module(
|
|
const MR_ModuleLayout *module, MR_ProcSpec *spec,
|
|
void f(void *, const MR_ProcLayout *),
|
|
void *data);
|
|
static void MR_process_line_layouts(const MR_ModuleFileLayout
|
|
*file_layout, int line,
|
|
MR_file_line_callback callback_func,
|
|
int callback_arg);
|
|
|
|
static MR_bool MR_module_in_arena(const char *name, char **names,
|
|
int num_names);
|
|
|
|
static int MR_compare_proc_layout_by_name(const void *ptr1,
|
|
const void *ptr2);
|
|
static int MR_compare_type_ctor_by_name(const void *ptr1,
|
|
const void *ptr2);
|
|
static int MR_compare_functor_by_name(const void *ptr1,
|
|
const void *ptr2);
|
|
|
|
static MR_bool MR_parse_trailing_number(char *start, char **end,
|
|
int *number);
|
|
static void MR_translate_double_underscores(char *str);
|
|
static char *MR_get_module_info_name(int slot);
|
|
|
|
typedef struct {
|
|
MR_PredFunc MR_complete_pf;
|
|
|
|
/*
|
|
** The word to complete, with `__' translated into '.'.
|
|
*/
|
|
char *MR_complete_name;
|
|
int MR_complete_name_len;
|
|
MR_bool MR_complete_name_is_qualified;
|
|
|
|
/*
|
|
** Slot number of a module for which we should return all
|
|
** procedures as completions, -1 if there is none.
|
|
*/
|
|
int MR_unambiguous_matching_module;
|
|
|
|
/*
|
|
** Length of the part of the word to skip when testing for module
|
|
** qualified completions in the current module, zero if we
|
|
** shouldn't test for module qualified completions in the
|
|
** current module.
|
|
*/
|
|
int MR_complete_word_matches_module;
|
|
int MR_complete_current_module;
|
|
int MR_complete_current_proc;
|
|
} MR_ProcCompleterData;
|
|
|
|
static char *MR_trace_proc_spec_completer_next(const char *word,
|
|
size_t word_len, MR_CompleterData *completer_data);
|
|
static void MR_trace_proc_spec_completer_init_module(
|
|
MR_ProcCompleterData *data);
|
|
static char *MR_trace_complete_proc(MR_ProcCompleterData *data);
|
|
static char *MR_format_proc_spec_completion(MR_PredFunc pred_or_func,
|
|
const char *module, const char *name);
|
|
static void MR_free_proc_completer_data(MR_CompleterData completer_data);
|
|
|
|
void
|
|
MR_register_all_modules_and_procs(FILE *fp, MR_bool verbose)
|
|
{
|
|
static MR_bool done = MR_FALSE;
|
|
|
|
if (! done) {
|
|
if (verbose) {
|
|
fprintf(fp, "Registering debuggable procedures... ");
|
|
fflush(fp);
|
|
}
|
|
|
|
MR_trace_init_modules();
|
|
done = MR_TRUE;
|
|
if (verbose) {
|
|
fprintf(fp, "done.\n");
|
|
if (MR_module_info_next == 0) {
|
|
fprintf(fp, "There are no debuggable modules.\n");
|
|
} else if (MR_module_info_next == 1) {
|
|
fprintf(fp,
|
|
"There is one debuggable module, with %d procedures.\n",
|
|
MR_module_info_proc_count);
|
|
} else {
|
|
fprintf(fp, "There are %d debuggable modules, "
|
|
"with a total of %d procedures.\n",
|
|
MR_module_info_next, MR_module_info_proc_count);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#define MR_INIT_EVENT_SET_TABLE_SIZE 10
|
|
|
|
void
|
|
MR_register_module_layout_real(const MR_ModuleLayout *module)
|
|
{
|
|
/*
|
|
** MR_register_module_layout_real should only be called from
|
|
** the initialization function of a module, which should be
|
|
** called only once. The check here whether the module layout
|
|
** already exists in the table is really only for paranoia.
|
|
*/
|
|
|
|
if (MR_search_module_info_by_name(module->MR_ml_name) == NULL) {
|
|
MR_insert_module_info(module);
|
|
|
|
if (module->MR_ml_user_event_set_desc != NULL) {
|
|
int i;
|
|
MR_bool found;
|
|
const char *event_set_name;
|
|
MR_TraceEventSet *trace_event_set;
|
|
|
|
event_set_name = module->MR_ml_user_event_set_name;
|
|
|
|
found = MR_FALSE;
|
|
for (i = 0; i < MR_trace_event_set_next; i++) {
|
|
if (MR_streq(MR_trace_event_sets[i].MR_tes_name,
|
|
event_set_name))
|
|
{
|
|
trace_event_set = &MR_trace_event_sets[i];
|
|
if (MR_strdiff(trace_event_set->MR_tes_desc,
|
|
module->MR_ml_user_event_set_desc))
|
|
{
|
|
trace_event_set->MR_tes_is_consistent = MR_FALSE;
|
|
fprintf(MR_mdb_out,
|
|
"The executable's modules were compiled with "
|
|
"inconsistent definitions of "
|
|
"user event set `%s'.\n",
|
|
event_set_name);
|
|
}
|
|
|
|
found = MR_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
MR_ensure_room_for_next(MR_trace_event_set,
|
|
MR_TraceEventSet, MR_INIT_EVENT_SET_TABLE_SIZE);
|
|
trace_event_set =
|
|
&MR_trace_event_sets[MR_trace_event_set_next];
|
|
MR_trace_event_set_next++;
|
|
|
|
trace_event_set->MR_tes_name = event_set_name;
|
|
trace_event_set->MR_tes_desc =
|
|
module->MR_ml_user_event_set_desc;
|
|
trace_event_set->MR_tes_is_consistent = MR_TRUE;
|
|
trace_event_set->MR_tes_num_specs =
|
|
module->MR_ml_num_user_event_specs;
|
|
trace_event_set->MR_tes_specs =
|
|
module->MR_ml_user_event_specs;
|
|
trace_event_set->MR_tes_event_set =
|
|
MR_read_event_set("no input file",
|
|
trace_event_set->MR_tes_desc);
|
|
|
|
if (trace_event_set->MR_tes_event_set == NULL) {
|
|
fprintf(MR_mdb_out,
|
|
"Internal error: could not parse "
|
|
"the specification of event set `%s'.\n",
|
|
event_set_name);
|
|
}
|
|
|
|
if (MR_trace_event_sets_max_num_attr <
|
|
module->MR_ml_user_event_max_num_attr)
|
|
{
|
|
MR_trace_event_sets_max_num_attr =
|
|
module->MR_ml_user_event_max_num_attr;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static const MR_ModuleLayout *
|
|
MR_search_module_info_by_name(const char *name)
|
|
{
|
|
int slot;
|
|
MR_bool found;
|
|
|
|
MR_bsearch(MR_module_info_next, slot, found,
|
|
strcmp(MR_module_infos[slot]->MR_ml_name, name));
|
|
if (found) {
|
|
return MR_module_infos[slot];
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static MR_Dlist *
|
|
MR_search_module_info_by_nickname(const char *name)
|
|
{
|
|
int slot;
|
|
MR_bool found;
|
|
|
|
MR_bsearch(MR_module_nick_next, slot, found,
|
|
strcmp(MR_module_nicks[slot].MR_nick_name, name));
|
|
if (found) {
|
|
return MR_module_nicks[slot].MR_nick_layouts;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static const MR_ModuleLayout *
|
|
MR_search_module_info_by_unique_name(FILE *fp, const char *name)
|
|
{
|
|
const MR_ModuleLayout *module;
|
|
const MR_Dlist *modules;
|
|
const MR_Dlist *element_ptr;
|
|
|
|
module = MR_search_module_info_by_name(name);
|
|
if (module == NULL) {
|
|
modules = MR_search_module_info_by_nickname(name);
|
|
if (modules == NULL) {
|
|
fprintf(fp,
|
|
"There is no debugging info about module `%s'\n", name);
|
|
return NULL;
|
|
} else if (MR_dlist_length(modules) != 1) {
|
|
fprintf(fp, "Module name `%s' is ambiguous.\n", name);
|
|
fprintf(fp, "The matches are:\n");
|
|
MR_for_dlist (element_ptr, modules) {
|
|
module = (const MR_ModuleLayout *) MR_dlist_data(element_ptr);
|
|
fprintf(fp, "%s\n", module->MR_ml_name);
|
|
}
|
|
|
|
return NULL;
|
|
} else {
|
|
module = (const MR_ModuleLayout *) MR_dlist_first(modules);
|
|
}
|
|
}
|
|
|
|
return module;
|
|
}
|
|
|
|
static void
|
|
MR_insert_module_info(const MR_ModuleLayout *module)
|
|
{
|
|
int slot;
|
|
MR_bool found;
|
|
const char *nickname;
|
|
|
|
MR_insert_module_info_into_module_table(module);
|
|
|
|
MR_module_info_proc_count += module->MR_ml_proc_count;
|
|
|
|
nickname = strchr(module->MR_ml_name, '.');
|
|
while (nickname != NULL) {
|
|
nickname++; /* step over the '.' */
|
|
MR_bsearch(MR_module_nick_next, slot, found,
|
|
strcmp(MR_module_nicks[slot].MR_nick_name, nickname));
|
|
if (found) {
|
|
MR_module_nicks[slot].MR_nick_layouts =
|
|
MR_dlist_addtail(MR_module_nicks[slot].MR_nick_layouts,
|
|
module);
|
|
} else {
|
|
MR_GC_ensure_room_for_next(MR_module_nick, MR_Module_Nick,
|
|
INIT_MODULE_TABLE_SIZE, NULL);
|
|
MR_prepare_insert_into_sorted(MR_module_nicks, MR_module_nick_next,
|
|
slot, strcmp(MR_module_nicks[slot].MR_nick_name, nickname));
|
|
MR_module_nicks[slot].MR_nick_name = nickname;
|
|
MR_module_nicks[slot].MR_nick_layouts = MR_dlist_makelist(module);
|
|
}
|
|
|
|
nickname = strchr(nickname, '.');
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_process_file_line_layouts(const char *file, int line,
|
|
MR_file_line_callback callback_func, int callback_arg)
|
|
{
|
|
const MR_ModuleFileLayout *file_layout;
|
|
int i;
|
|
int j;
|
|
|
|
for (i = 0; i < MR_module_info_next; i++) {
|
|
for (j = 0; j < MR_module_infos[i]->MR_ml_filename_count; j++) {
|
|
file_layout = MR_module_infos[i]->MR_ml_module_file_layout[j];
|
|
if (MR_streq(file_layout->MR_mfl_filename, file)) {
|
|
MR_process_line_layouts(file_layout, line, callback_func,
|
|
callback_arg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
MR_process_line_layouts(const MR_ModuleFileLayout *file_layout, int line,
|
|
MR_file_line_callback callback_func, int callback_arg)
|
|
{
|
|
int k;
|
|
MR_bool found;
|
|
|
|
MR_bsearch(file_layout->MR_mfl_label_count, k, found,
|
|
file_layout->MR_mfl_label_lineno[k] - line);
|
|
|
|
if (found) {
|
|
/*
|
|
** The binary search found *one* label with the given linenumber;
|
|
** we now find the *first* such label.
|
|
*/
|
|
|
|
while (k > 0 && file_layout->MR_mfl_label_lineno[k - 1] == line) {
|
|
k--;
|
|
}
|
|
|
|
while (k < file_layout->MR_mfl_label_count
|
|
&& file_layout->MR_mfl_label_lineno[k] == line)
|
|
{
|
|
(*callback_func)(file_layout->MR_mfl_label_layout[k],
|
|
callback_arg);
|
|
k++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_dump_module_tables(FILE *fp, MR_bool separate, MR_bool uci,
|
|
char *module_name)
|
|
{
|
|
const MR_ModuleLayout *module;
|
|
const MR_ProcLayout *proc;
|
|
int i;
|
|
int j;
|
|
|
|
if (module_name != NULL) {
|
|
module = MR_search_module_info_by_unique_name(fp, module_name);
|
|
if (module == NULL) {
|
|
/* The error message has already been printed */
|
|
return;
|
|
}
|
|
} else {
|
|
module = NULL;
|
|
}
|
|
|
|
for (i = 0; i < MR_module_info_next; i++) {
|
|
if (module == NULL || module == MR_module_infos[i]) {
|
|
for (j = 0; j < MR_module_infos[i]->MR_ml_proc_count; j++) {
|
|
proc = MR_module_infos[i]->MR_ml_procs[j];
|
|
if (uci || !MR_PROC_LAYOUT_IS_UCI(proc)) {
|
|
if (separate) {
|
|
MR_print_proc_separate(fp, proc);
|
|
} else {
|
|
MR_print_proc_id(fp, proc);
|
|
}
|
|
|
|
fprintf(fp, "\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_dump_module_list(FILE *fp)
|
|
{
|
|
int i;
|
|
|
|
fprintf(fp, "List of debuggable modules\n\n");
|
|
for (i = 0; i < MR_module_info_next; i++) {
|
|
fprintf(fp, "%s\n", MR_module_infos[i]->MR_ml_name);
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_dump_module_procs(FILE *fp, const char *name)
|
|
{
|
|
const MR_ModuleLayout *module;
|
|
MR_ConstString decl_module;
|
|
int i;
|
|
|
|
module = MR_search_module_info_by_unique_name(fp, name);
|
|
if (module == NULL) {
|
|
/* The error message has already been printed */
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "List of procedures in module `%s'\n\n", name);
|
|
for (i = 0; i < module->MR_ml_proc_count; i++) {
|
|
decl_module = MR_get_proc_decl_module(module->MR_ml_procs[i]);
|
|
/*
|
|
** Only show procs which are declared in the module.
|
|
*/
|
|
if (MR_streq(decl_module, module->MR_ml_name)) {
|
|
MR_print_proc_id_and_nl(fp, module->MR_ml_procs[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
static MR_bool
|
|
MR_module_in_arena(const char *name, char **names, int num_names)
|
|
{
|
|
int i;
|
|
|
|
if (num_names == 0) {
|
|
return MR_TRUE;
|
|
}
|
|
|
|
for (i = 0; i < num_names; i++) {
|
|
if (MR_streq(name, names[i])) {
|
|
return MR_TRUE;
|
|
}
|
|
}
|
|
|
|
return MR_FALSE;
|
|
}
|
|
|
|
#define MR_proc_compare_name(proc1, proc2) \
|
|
strcmp(proc1->MR_sle_user.MR_user_name, \
|
|
proc2->MR_sle_user.MR_user_name)
|
|
|
|
#define MR_proc_compare_module_name(proc1, proc2) \
|
|
strcmp(proc1->MR_sle_user.MR_user_decl_module, \
|
|
proc2->MR_sle_user.MR_user_decl_module)
|
|
|
|
#define MR_proc_compare_pf(proc1, proc2) \
|
|
((int) proc1->MR_sle_user.MR_user_pred_or_func - \
|
|
(int) proc2->MR_sle_user.MR_user_pred_or_func)
|
|
|
|
#define MR_proc_compare_arity(proc1, proc2) \
|
|
(MR_sle_user_adjusted_arity(proc1) - MR_sle_user_adjusted_arity(proc2))
|
|
|
|
#define MR_proc_compare_mode(proc1, proc2) \
|
|
(proc1->MR_sle_user.MR_user_mode - proc2->MR_sle_user.MR_user_mode)
|
|
|
|
#define MR_proc_same_name(proc1, proc2) \
|
|
(MR_proc_compare_name(proc1, proc2) == 0)
|
|
|
|
#define MR_proc_same_module_name(proc1, proc2) \
|
|
(MR_proc_compare_module_name(proc1, proc2) == 0)
|
|
|
|
#define MR_proc_same_pf(proc1, proc2) \
|
|
(MR_proc_compare_pf(proc1, proc2) == 0)
|
|
|
|
#define MR_proc_same_arity(proc1, proc2) \
|
|
(MR_proc_compare_arity(proc1, proc2) == 0)
|
|
|
|
#define MR_proc_same_name_module_pf_arity(proc1, proc2) \
|
|
(MR_proc_same_name(proc1, proc2) && \
|
|
MR_proc_same_module_name(proc1, proc2) && \
|
|
MR_proc_same_pf(proc1, proc2) && \
|
|
MR_proc_same_arity(proc1, proc2))
|
|
|
|
static int
|
|
MR_compare_proc_layout_by_name(const void *ptr1, const void *ptr2)
|
|
{
|
|
const MR_ProcLayout **proc_addr1;
|
|
const MR_ProcLayout **proc_addr2;
|
|
const MR_ProcLayout *proc1;
|
|
const MR_ProcLayout *proc2;
|
|
int result;
|
|
|
|
proc_addr1 = (const MR_ProcLayout **) ptr1;
|
|
proc_addr2 = (const MR_ProcLayout **) ptr2;
|
|
proc1 = *proc_addr1;
|
|
proc2 = *proc_addr2;
|
|
|
|
result = MR_proc_compare_name(proc1, proc2);
|
|
if (result != 0) {
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
** Return equal only if the module name, pred_or_func and the arity
|
|
** are the same as well, in order to group all procedures of a predicate
|
|
** or function together.
|
|
*/
|
|
|
|
result = MR_proc_compare_module_name(proc1, proc2);
|
|
if (result != 0) {
|
|
return result;
|
|
}
|
|
|
|
result = MR_proc_compare_pf(proc1, proc2);
|
|
if (result != 0) {
|
|
return result;
|
|
}
|
|
|
|
result = MR_proc_compare_arity(proc1, proc2);
|
|
if (result != 0) {
|
|
return result;
|
|
}
|
|
|
|
return MR_proc_compare_mode(proc1, proc2);
|
|
}
|
|
|
|
#define MR_type_compare_name(type1, type2) \
|
|
strcmp(type1->MR_type_ctor_name, type2->MR_type_ctor_name)
|
|
|
|
#define MR_type_compare_module_name(type1, type2) \
|
|
strcmp(type1->MR_type_ctor_module_name, type2->MR_type_ctor_module_name)
|
|
|
|
#define MR_type_compare_arity(type1, type2) \
|
|
(type1->MR_type_ctor_arity - type2->MR_type_ctor_arity)
|
|
|
|
#define MR_type_same_name(type1, type2) \
|
|
(MR_type_compare_name(type1, type2) == 0)
|
|
|
|
#define MR_type_same_module_name(type1, type2) \
|
|
(MR_type_compare_module_name(type1, type2) == 0)
|
|
|
|
static int
|
|
MR_compare_type_ctor_by_name(const void *ptr1, const void *ptr2)
|
|
{
|
|
const MR_TypeCtorInfo *type_ctor_addr1;
|
|
const MR_TypeCtorInfo *type_ctor_addr2;
|
|
MR_TypeCtorInfo type_ctor1;
|
|
MR_TypeCtorInfo type_ctor2;
|
|
int result;
|
|
|
|
type_ctor_addr1 = (const MR_TypeCtorInfo *) ptr1;
|
|
type_ctor_addr2 = (const MR_TypeCtorInfo *) ptr2;
|
|
type_ctor1 = *type_ctor_addr1;
|
|
type_ctor2 = *type_ctor_addr2;
|
|
result = MR_type_compare_name(type_ctor1, type_ctor2);
|
|
if (result != 0) {
|
|
return result;
|
|
}
|
|
|
|
result = MR_type_compare_module_name(type_ctor1, type_ctor2);
|
|
if (result != 0) {
|
|
return result;
|
|
}
|
|
|
|
return MR_type_compare_arity(type_ctor1, type_ctor2);
|
|
}
|
|
|
|
typedef struct {
|
|
const char *MR_functor_name;
|
|
int MR_functor_arity;
|
|
const char *MR_functor_type_module;
|
|
const char *MR_functor_type_name;
|
|
int MR_functor_type_arity;
|
|
} MR_FunctorTypeCtor;
|
|
|
|
#define MR_functor_compare_name(functor1, functor2) \
|
|
strcmp((functor1).MR_functor_name, (functor2).MR_functor_name)
|
|
|
|
#define MR_functor_same_name(functor1, functor2) \
|
|
(MR_functor_compare_name(functor1, functor2) == 0)
|
|
|
|
#define MR_functor_compare_arity(functor1, functor2) \
|
|
((functor1).MR_functor_arity - (functor2).MR_functor_arity)
|
|
|
|
#define MR_functor_compare_type_module(functor1, functor2) \
|
|
strcmp((functor1).MR_functor_type_module, (functor2).MR_functor_type_module)
|
|
|
|
#define MR_functor_compare_type_name(functor1, functor2) \
|
|
strcmp((functor1).MR_functor_type_name, (functor2).MR_functor_type_name)
|
|
|
|
#define MR_functor_compare_type_arity(functor1, functor2) \
|
|
((functor1).MR_functor_type_arity - (functor2).MR_functor_type_arity)
|
|
|
|
static int
|
|
MR_compare_functor_by_name(const void *ptr1, const void *ptr2)
|
|
{
|
|
const MR_FunctorTypeCtor *addr1;
|
|
const MR_FunctorTypeCtor *addr2;
|
|
int result;
|
|
|
|
addr1 = (const MR_FunctorTypeCtor *) ptr1;
|
|
addr2 = (const MR_FunctorTypeCtor *) ptr2;
|
|
|
|
result = MR_functor_compare_name(*addr1, *addr2);
|
|
if (result != 0) {
|
|
return result;
|
|
}
|
|
|
|
result = MR_functor_compare_arity(*addr1, *addr2);
|
|
if (result != 0) {
|
|
return result;
|
|
}
|
|
|
|
result = MR_functor_compare_type_module(*addr1, *addr2);
|
|
if (result != 0) {
|
|
return result;
|
|
}
|
|
|
|
result = MR_functor_compare_type_name(*addr1, *addr2);
|
|
if (result != 0) {
|
|
return result;
|
|
}
|
|
|
|
return MR_functor_compare_type_arity(*addr1, *addr2);
|
|
}
|
|
|
|
void
|
|
MR_print_ambiguities(FILE *fp, MR_bool print_procs, MR_bool print_types,
|
|
MR_bool print_functors, char **arena_module_names, int arena_num_modules)
|
|
{
|
|
int module_num;
|
|
int proc_num;
|
|
int type_num;
|
|
int functor_num;
|
|
int end_proc_num;
|
|
int end_type_num;
|
|
int end_functor_num;
|
|
int num_procs;
|
|
int num_all_types;
|
|
int num_types;
|
|
int num_functors;
|
|
int next_proc_num;
|
|
int procs_in_module;
|
|
const MR_ModuleLayout *module;
|
|
const MR_ProcLayout **procs;
|
|
const MR_ProcLayout *cur_proc;
|
|
MR_TypeCtorInfo *type_ctors;
|
|
MR_TypeCtorInfo type_ctor_info;
|
|
MR_FunctorTypeCtor *functors;
|
|
MR_Dlist *type_ctor_list;
|
|
MR_Dlist *element_ptr;
|
|
MR_bool *report;
|
|
MR_EnumFunctorDesc **enum_functors;
|
|
MR_DuFunctorDesc **du_functors;
|
|
MR_MaybeResAddrFunctorDesc *res_functors;
|
|
MR_NotagFunctorDesc *notag_functor;
|
|
int num_distinct;
|
|
int num_ambiguous;
|
|
int num_ambiguous_total;
|
|
int num_ambiguous_max;
|
|
int i;
|
|
|
|
/*
|
|
** We compute each data structure regardless of the settings of
|
|
** print_procs, print_types and print_functors because the implementation
|
|
** of one may depend on the other; e.g. we calculate how many function
|
|
** symbols to reserve space for while we build the types array.
|
|
*/
|
|
|
|
num_procs = 0;
|
|
for (module_num = 0; module_num < MR_module_info_next; module_num++) {
|
|
num_procs += MR_module_infos[module_num]->MR_ml_proc_count;
|
|
}
|
|
|
|
/*
|
|
** num_procs is a conservative estimate of the number of user defined
|
|
** procedures.
|
|
*/
|
|
|
|
procs = malloc(sizeof(const MR_ProcLayout *) * num_procs);
|
|
if (procs == NULL) {
|
|
fprintf(MR_mdb_err, "Error: could not allocate sufficient memory\n");
|
|
return;
|
|
}
|
|
|
|
report = malloc(sizeof(MR_bool) * num_procs);
|
|
if (report == NULL) {
|
|
fprintf(MR_mdb_err, "Error: could not allocate sufficient memory\n");
|
|
return;
|
|
}
|
|
|
|
next_proc_num = 0;
|
|
for (module_num = 0; module_num < MR_module_info_next; module_num++) {
|
|
module = MR_module_infos[module_num];
|
|
if (MR_module_in_arena(module->MR_ml_name,
|
|
arena_module_names, arena_num_modules))
|
|
{
|
|
procs_in_module = MR_module_infos[module_num]->MR_ml_proc_count;
|
|
for (proc_num = 0; proc_num < procs_in_module; proc_num++) {
|
|
cur_proc = module->MR_ml_procs[proc_num];
|
|
if (! MR_PROC_LAYOUT_IS_UCI(cur_proc)) {
|
|
procs[next_proc_num] = cur_proc;
|
|
next_proc_num++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
num_procs = next_proc_num;
|
|
qsort(procs, num_procs, sizeof(const MR_ProcLayout *),
|
|
MR_compare_proc_layout_by_name);
|
|
|
|
if (print_procs) {
|
|
fprintf(fp, "Ambiguous procedure names:\n");
|
|
num_ambiguous = 0;
|
|
num_ambiguous_total = 0;
|
|
num_ambiguous_max = 0;
|
|
|
|
proc_num = 0;
|
|
while (proc_num < num_procs) {
|
|
end_proc_num = proc_num + 1;
|
|
while (end_proc_num < num_procs &&
|
|
MR_proc_same_name(procs[proc_num], procs[end_proc_num]))
|
|
{
|
|
end_proc_num++;
|
|
}
|
|
|
|
if (end_proc_num > proc_num + 1) {
|
|
report[proc_num] = MR_TRUE;
|
|
num_distinct = 1;
|
|
|
|
for (i = proc_num + 1; i < end_proc_num; i++) {
|
|
if (MR_proc_same_name_module_pf_arity(procs[i-1],
|
|
procs[i]))
|
|
{
|
|
report[i] = MR_FALSE;
|
|
} else {
|
|
report[i] = MR_TRUE;
|
|
num_distinct++;
|
|
}
|
|
}
|
|
|
|
if (num_distinct > 1) {
|
|
num_ambiguous++;
|
|
num_ambiguous_total += (end_proc_num - proc_num);
|
|
if ((end_proc_num - proc_num) > num_ambiguous_max) {
|
|
num_ambiguous_max = end_proc_num - proc_num;
|
|
}
|
|
|
|
fprintf(fp, "\n");
|
|
for (i = proc_num; i < end_proc_num; i++) {
|
|
if (report[i]) {
|
|
fprintf(fp, "%s %s.%s/%d\n",
|
|
(procs[i]->MR_sle_user.MR_user_pred_or_func
|
|
== MR_PREDICATE ? "pred" : "func"),
|
|
procs[i]->MR_sle_user.MR_user_decl_module,
|
|
procs[i]->MR_sle_user.MR_user_name,
|
|
MR_sle_user_adjusted_arity(procs[i]));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
proc_num = end_proc_num;
|
|
}
|
|
|
|
if (num_ambiguous == 0) {
|
|
fprintf(fp, "\nNone\n\n");
|
|
} else {
|
|
fprintf(fp, "\nTotal: %d names used %d times, ",
|
|
num_ambiguous, num_ambiguous_total);
|
|
fprintf(fp, "maximum %d, average: %.2f\n\n",
|
|
num_ambiguous_max,
|
|
(float) num_ambiguous_total / (float) num_ambiguous);
|
|
}
|
|
}
|
|
|
|
free(procs);
|
|
free(report);
|
|
|
|
type_ctor_list = MR_all_type_ctor_infos(&num_all_types);
|
|
type_ctors = malloc(sizeof(MR_TypeCtorInfo) * num_all_types);
|
|
if (type_ctors == NULL) {
|
|
fprintf(MR_mdb_err, "Error: could not allocate sufficient memory\n");
|
|
return;
|
|
}
|
|
|
|
num_functors = 0;
|
|
type_num = 0;
|
|
MR_for_dlist (element_ptr, type_ctor_list) {
|
|
type_ctor_info = (MR_TypeCtorInfo) MR_dlist_data(element_ptr);
|
|
if (MR_module_in_arena(type_ctor_info->MR_type_ctor_module_name,
|
|
arena_module_names, arena_num_modules))
|
|
{
|
|
type_ctors[type_num] = type_ctor_info;
|
|
|
|
switch (MR_type_ctor_rep(type_ctor_info)) {
|
|
case MR_TYPECTOR_REP_ENUM:
|
|
case MR_TYPECTOR_REP_ENUM_USEREQ:
|
|
case MR_TYPECTOR_REP_DUMMY:
|
|
case MR_TYPECTOR_REP_DU:
|
|
case MR_TYPECTOR_REP_DU_USEREQ:
|
|
case MR_TYPECTOR_REP_RESERVED_ADDR:
|
|
case MR_TYPECTOR_REP_RESERVED_ADDR_USEREQ:
|
|
case MR_TYPECTOR_REP_NOTAG:
|
|
case MR_TYPECTOR_REP_NOTAG_USEREQ:
|
|
case MR_TYPECTOR_REP_NOTAG_GROUND:
|
|
case MR_TYPECTOR_REP_NOTAG_GROUND_USEREQ:
|
|
num_functors += type_ctor_info->MR_type_ctor_num_functors;
|
|
#if 0
|
|
/* for debugging only */
|
|
fprintf(fp,
|
|
"TYPE %s.%s/%" MR_INTEGER_LENGTH_MODIFIER "d\t%s\t%d\n",
|
|
type_ctors[type_num]->MR_type_ctor_module_name,
|
|
type_ctors[type_num]->MR_type_ctor_name,
|
|
type_ctors[type_num]->MR_type_ctor_arity,
|
|
MR_ctor_rep_name[
|
|
MR_type_ctor_rep(type_ctors[type_num])],
|
|
num_functors);
|
|
#endif
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
type_num++;
|
|
}
|
|
}
|
|
|
|
num_types = type_num;
|
|
qsort(type_ctors, num_types, sizeof(MR_TypeCtorInfo),
|
|
MR_compare_type_ctor_by_name);
|
|
|
|
if (print_types) {
|
|
fprintf(fp, "Ambiguous type names:\n");
|
|
num_ambiguous = 0;
|
|
num_ambiguous_total = 0;
|
|
num_ambiguous_max = 0;
|
|
|
|
type_num = 0;
|
|
while (type_num < num_types) {
|
|
end_type_num = type_num + 1;
|
|
while (end_type_num < num_types &&
|
|
MR_type_same_name(type_ctors[type_num],
|
|
type_ctors[end_type_num]))
|
|
{
|
|
end_type_num++;
|
|
}
|
|
|
|
if (end_type_num > type_num + 1) {
|
|
num_ambiguous++;
|
|
num_ambiguous_total += (end_type_num - type_num);
|
|
if ((end_type_num - type_num) > num_ambiguous_max) {
|
|
num_ambiguous_max = end_type_num - type_num;
|
|
}
|
|
|
|
fprintf(fp, "\n");
|
|
|
|
for (i = type_num; i < end_type_num; i++) {
|
|
fprintf(fp, "%s.%s/%" MR_INTEGER_LENGTH_MODIFIER "d\n",
|
|
type_ctors[i]->MR_type_ctor_module_name,
|
|
type_ctors[i]->MR_type_ctor_name,
|
|
type_ctors[i]->MR_type_ctor_arity);
|
|
}
|
|
}
|
|
|
|
type_num = end_type_num;
|
|
}
|
|
|
|
if (num_ambiguous == 0) {
|
|
fprintf(fp, "\nNone\n\n");
|
|
} else {
|
|
fprintf(fp, "\nTotal: %d names used %d times, ",
|
|
num_ambiguous, num_ambiguous_total);
|
|
fprintf(fp, "maximum %d, average: %.2f\n\n",
|
|
num_ambiguous_max,
|
|
(float) num_ambiguous_total / (float) num_ambiguous);
|
|
}
|
|
}
|
|
|
|
functors = malloc(sizeof(MR_FunctorTypeCtor) * num_functors);
|
|
if (functors == NULL) {
|
|
fprintf(MR_mdb_err, "Error: could not allocate sufficient memory\n");
|
|
return;
|
|
}
|
|
|
|
functor_num = 0;
|
|
for (type_num = 0; type_num < num_types; type_num++) {
|
|
type_ctor_info = type_ctors[type_num];
|
|
|
|
#if 0
|
|
/* for debugging only */
|
|
fprintf(fp, "FUNCTYPE %s.%s/%" MR_INTEGER_LENGTH_MODIFIER "d\n",
|
|
type_ctors[type_num]->MR_type_ctor_module_name,
|
|
type_ctors[type_num]->MR_type_ctor_name,
|
|
type_ctors[type_num]->MR_type_ctor_arity);
|
|
#endif
|
|
|
|
switch (MR_type_ctor_rep(type_ctor_info)) {
|
|
case MR_TYPECTOR_REP_ENUM:
|
|
case MR_TYPECTOR_REP_ENUM_USEREQ:
|
|
case MR_TYPECTOR_REP_DUMMY:
|
|
enum_functors =
|
|
MR_type_ctor_functors(type_ctor_info).MR_functors_enum;
|
|
i = 0;
|
|
while (i < type_ctor_info->MR_type_ctor_num_functors) {
|
|
functors[functor_num].MR_functor_name =
|
|
enum_functors[i]->MR_enum_functor_name;
|
|
functors[functor_num].MR_functor_arity = 0;
|
|
functors[functor_num].MR_functor_type_module =
|
|
type_ctor_info->MR_type_ctor_module_name;
|
|
functors[functor_num].MR_functor_type_name =
|
|
type_ctor_info->MR_type_ctor_name;
|
|
functors[functor_num].MR_functor_type_arity =
|
|
type_ctor_info->MR_type_ctor_arity;
|
|
functor_num++;
|
|
i++;
|
|
}
|
|
break;
|
|
|
|
case MR_TYPECTOR_REP_DU:
|
|
case MR_TYPECTOR_REP_DU_USEREQ:
|
|
du_functors =
|
|
MR_type_ctor_functors(type_ctor_info).MR_functors_du;
|
|
i = 0;
|
|
while (i < type_ctor_info->MR_type_ctor_num_functors) {
|
|
functors[functor_num].MR_functor_name =
|
|
du_functors[i]->MR_du_functor_name;
|
|
functors[functor_num].MR_functor_arity =
|
|
du_functors[i]->MR_du_functor_orig_arity;
|
|
functors[functor_num].MR_functor_type_module =
|
|
type_ctor_info->MR_type_ctor_module_name;
|
|
functors[functor_num].MR_functor_type_name =
|
|
type_ctor_info->MR_type_ctor_name;
|
|
functors[functor_num].MR_functor_type_arity =
|
|
type_ctor_info->MR_type_ctor_arity;
|
|
functor_num++;
|
|
i++;
|
|
}
|
|
break;
|
|
|
|
case MR_TYPECTOR_REP_RESERVED_ADDR:
|
|
case MR_TYPECTOR_REP_RESERVED_ADDR_USEREQ:
|
|
res_functors =
|
|
MR_type_ctor_functors(type_ctor_info).MR_functors_res;
|
|
i = 0;
|
|
while (i < type_ctor_info->MR_type_ctor_num_functors) {
|
|
functors[functor_num].MR_functor_name =
|
|
res_functors[i].MR_maybe_res_name;
|
|
functors[functor_num].MR_functor_arity =
|
|
res_functors[i].MR_maybe_res_arity;
|
|
functors[functor_num].MR_functor_type_module =
|
|
type_ctor_info->MR_type_ctor_module_name;
|
|
functors[functor_num].MR_functor_type_name =
|
|
type_ctor_info->MR_type_ctor_name;
|
|
functors[functor_num].MR_functor_type_arity =
|
|
type_ctor_info->MR_type_ctor_arity;
|
|
functor_num++;
|
|
i++;
|
|
}
|
|
break;
|
|
break;
|
|
|
|
case MR_TYPECTOR_REP_NOTAG:
|
|
case MR_TYPECTOR_REP_NOTAG_USEREQ:
|
|
case MR_TYPECTOR_REP_NOTAG_GROUND:
|
|
case MR_TYPECTOR_REP_NOTAG_GROUND_USEREQ:
|
|
notag_functor =
|
|
MR_type_ctor_functors(type_ctor_info).MR_functors_notag;
|
|
functors[functor_num].MR_functor_name =
|
|
notag_functor->MR_notag_functor_name;
|
|
functors[functor_num].MR_functor_arity = 1;
|
|
functors[functor_num].MR_functor_type_module =
|
|
type_ctor_info->MR_type_ctor_module_name;
|
|
functors[functor_num].MR_functor_type_name =
|
|
type_ctor_info->MR_type_ctor_name;
|
|
functors[functor_num].MR_functor_type_arity =
|
|
type_ctor_info->MR_type_ctor_arity;
|
|
functor_num++;
|
|
break;
|
|
|
|
default:
|
|
/*
|
|
** Other kinds of types do not have user-defined function
|
|
** symbols.
|
|
*/
|
|
break;
|
|
}
|
|
}
|
|
|
|
qsort(functors, num_functors, sizeof(MR_FunctorTypeCtor),
|
|
MR_compare_functor_by_name);
|
|
|
|
if (print_functors) {
|
|
fprintf(fp, "Ambiguous function symbols:\n");
|
|
num_ambiguous = 0;
|
|
num_ambiguous_total = 0;
|
|
num_ambiguous_max = 0;
|
|
|
|
functor_num = 0;
|
|
while (functor_num < num_functors) {
|
|
end_functor_num = functor_num + 1;
|
|
while (end_functor_num < num_functors &&
|
|
MR_functor_same_name(functors[functor_num],
|
|
functors[end_functor_num]))
|
|
{
|
|
end_functor_num++;
|
|
}
|
|
|
|
if (end_functor_num > functor_num + 1) {
|
|
num_ambiguous++;
|
|
num_ambiguous_total += (end_functor_num - functor_num);
|
|
if ((end_functor_num - functor_num) > num_ambiguous_max) {
|
|
num_ambiguous_max = end_functor_num - functor_num;
|
|
}
|
|
|
|
fprintf(fp, "\n");
|
|
for (i = functor_num; i < end_functor_num; i++) {
|
|
fprintf(fp, "%s/%d ",
|
|
functors[i].MR_functor_name,
|
|
functors[i].MR_functor_arity);
|
|
fprintf(fp, "%s.%s/%d\n",
|
|
functors[i].MR_functor_type_module,
|
|
functors[i].MR_functor_type_name,
|
|
functors[i].MR_functor_type_arity);
|
|
}
|
|
}
|
|
|
|
functor_num = end_functor_num;
|
|
}
|
|
|
|
if (num_ambiguous == 0) {
|
|
fprintf(fp, "\nNone\n\n");
|
|
} else {
|
|
fprintf(fp, "\nTotal: %d names used %d times, ",
|
|
num_ambiguous, num_ambiguous_total);
|
|
fprintf(fp, "maximum %d, average: %.2f\n\n",
|
|
num_ambiguous_max,
|
|
(float) num_ambiguous_total / (float) num_ambiguous);
|
|
}
|
|
}
|
|
|
|
free(type_ctors);
|
|
free(functors);
|
|
}
|
|
|
|
MR_bool
|
|
MR_parse_proc_spec(char *str, MR_ProcSpec *spec)
|
|
{
|
|
char *dash;
|
|
char *start;
|
|
char *end;
|
|
int n;
|
|
int len;
|
|
MR_bool found;
|
|
|
|
spec->MR_proc_module = NULL;
|
|
spec->MR_proc_name = NULL;
|
|
spec->MR_proc_arity = -1;
|
|
spec->MR_proc_mode = -1;
|
|
spec->MR_proc_prefix = (MR_ProcPrefix) -1;
|
|
|
|
len = strlen(str);
|
|
|
|
/*
|
|
** Check for the optional trailing arity and mode number.
|
|
** This also checks for filename:linenumber breakpoint specifiers.
|
|
*/
|
|
end = str + len - 1;
|
|
if (MR_parse_trailing_number(str, &end, &n)) {
|
|
if (end == str) {
|
|
/* the string contains only a number */
|
|
return MR_FALSE;
|
|
}
|
|
end--;
|
|
if (*end == ':') {
|
|
/* filename:linenumber */
|
|
return MR_FALSE;
|
|
} else if (*end == '-') {
|
|
spec->MR_proc_mode = n;
|
|
|
|
/*
|
|
** Avoid modifying the string until we're sure
|
|
** the parse can't fail.
|
|
*/
|
|
dash = end;
|
|
|
|
end--;
|
|
if (MR_parse_trailing_number(str, &end, &n)) {
|
|
if (end == str) {
|
|
/* the string contains only a number */
|
|
return MR_FALSE;
|
|
}
|
|
end--;
|
|
if (*end == '/') {
|
|
*end = '\0';
|
|
spec->MR_proc_arity = n;
|
|
end--;
|
|
}
|
|
}
|
|
*dash = '\0';
|
|
} else if (*end == '/') {
|
|
*end = '\0';
|
|
end--;
|
|
spec->MR_proc_arity = n;
|
|
}
|
|
}
|
|
|
|
if (MR_strneq(str, "pred*", 5)) {
|
|
spec->MR_proc_prefix = MR_PREFIX_PRED;
|
|
str += 5;
|
|
} else if (MR_strneq(str, "func*", 5)) {
|
|
spec->MR_proc_prefix = MR_PREFIX_FUNC;
|
|
str += 5;
|
|
} else if (MR_strneq(str, "unif*", 5)) {
|
|
spec->MR_proc_prefix = MR_PREFIX_UNIF;
|
|
str += 5;
|
|
} else if (MR_strneq(str, "comp*", 5)) {
|
|
spec->MR_proc_prefix = MR_PREFIX_COMP;
|
|
str += 5;
|
|
} else if (MR_strneq(str, "indx*", 5)) {
|
|
spec->MR_proc_prefix = MR_PREFIX_INDX;
|
|
str += 5;
|
|
} else if (MR_strneq(str, "init*", 5)) {
|
|
spec->MR_proc_prefix = MR_PREFIX_INIT;
|
|
str += 5;
|
|
}
|
|
|
|
/*
|
|
** Search backwards for the end of the final module qualifier.
|
|
** There must be at least one character before the qualifier.
|
|
*/
|
|
|
|
while (end > str) {
|
|
if (*end == '.' || (*end == '_' && *(end + 1) == '_')) {
|
|
if (*end == '.') {
|
|
spec->MR_proc_name = end + 1;
|
|
} else {
|
|
spec->MR_proc_name = end + 2;
|
|
}
|
|
|
|
if (strlen(spec->MR_proc_name) == 0) {
|
|
spec->MR_proc_name = NULL;
|
|
}
|
|
|
|
/*
|
|
** Convert all occurences of '__' to '.'.
|
|
*/
|
|
*end = '\0';
|
|
MR_translate_double_underscores(str);
|
|
|
|
spec->MR_proc_module = str;
|
|
|
|
return MR_TRUE;
|
|
} else {
|
|
end--;
|
|
}
|
|
}
|
|
|
|
/* There was no module qualifier. */
|
|
spec->MR_proc_name = str;
|
|
if (strlen(spec->MR_proc_name) == 0) {
|
|
spec->MR_proc_name = NULL;
|
|
}
|
|
return MR_TRUE;
|
|
}
|
|
|
|
/*
|
|
** Convert all occurrences of `__' to `.'.
|
|
*/
|
|
|
|
static void
|
|
MR_translate_double_underscores(char *start)
|
|
{
|
|
int double_underscores = 0;
|
|
char *str;
|
|
|
|
str = start;
|
|
while (*str) {
|
|
if (*str == '_' && *(str + 1) == '_') {
|
|
*(str - double_underscores) = '.';
|
|
double_underscores++;
|
|
str++;
|
|
} else {
|
|
*(str - double_underscores) = *str;
|
|
}
|
|
str++;
|
|
}
|
|
*(str - double_underscores) = '\0';
|
|
}
|
|
|
|
/*
|
|
** Go backwards over a string starting at `end', stopping at `start',
|
|
** parsing the trailing integer and storing it in `*n'.
|
|
** On return, `*end' points to the start of the trailing number.
|
|
** If no number was found, `*end' is unchanged.
|
|
*/
|
|
|
|
static MR_bool
|
|
MR_parse_trailing_number(char *start, char **end, int *number)
|
|
{
|
|
MR_bool found_digit;
|
|
int power_of_10;
|
|
char c;
|
|
char *tmp_end;
|
|
|
|
found_digit = MR_FALSE;
|
|
power_of_10 = 1;
|
|
*number = 0;
|
|
|
|
tmp_end = *end + 1;
|
|
while (tmp_end > start && MR_isdigit(*(tmp_end - 1))) {
|
|
found_digit = MR_TRUE;
|
|
*number += power_of_10 * (*(tmp_end - 1) - '0');
|
|
power_of_10 *= 10;
|
|
tmp_end--;
|
|
}
|
|
if (found_digit) {
|
|
*end = tmp_end;
|
|
}
|
|
return found_digit;
|
|
}
|
|
|
|
#define MR_INIT_MATCH_PROC_SIZE 8
|
|
|
|
static void
|
|
MR_register_matches(void *data, const MR_ProcLayout *entry)
|
|
{
|
|
MR_MatchesInfo *m;
|
|
|
|
m = (MR_MatchesInfo *) data;
|
|
MR_ensure_room_for_next(m->match_proc, const MR_ProcLayout *,
|
|
MR_INIT_MATCH_PROC_SIZE);
|
|
m->match_procs[m->match_proc_next] = entry;
|
|
m->match_proc_next++;
|
|
}
|
|
|
|
MR_MatchesInfo
|
|
MR_search_for_matching_procedures(MR_ProcSpec *spec)
|
|
{
|
|
MR_MatchesInfo m;
|
|
|
|
m.match_procs = NULL;
|
|
m.match_proc_max = 0;
|
|
m.match_proc_next = 0;
|
|
MR_process_matching_procedures(spec, MR_register_matches, &m);
|
|
return m;
|
|
}
|
|
|
|
/*
|
|
** This struct is for communication between
|
|
** MR_register_match and MR_search_for_matching_procedure.
|
|
*/
|
|
|
|
typedef struct {
|
|
const MR_ProcLayout *matching_entry;
|
|
MR_bool match_unique;
|
|
} MR_MatchInfo;
|
|
|
|
static void
|
|
MR_register_match(void *data, const MR_ProcLayout *entry)
|
|
{
|
|
MR_MatchInfo *m;
|
|
|
|
m = (MR_MatchInfo *) data;
|
|
if (m->matching_entry == NULL) {
|
|
m->matching_entry = entry;
|
|
} else {
|
|
m->match_unique = MR_FALSE;
|
|
}
|
|
}
|
|
|
|
const MR_ProcLayout *
|
|
MR_search_for_matching_procedure(MR_ProcSpec *spec, MR_bool *unique)
|
|
{
|
|
MR_MatchInfo m;
|
|
|
|
m.matching_entry = NULL;
|
|
m.match_unique = MR_TRUE;
|
|
MR_process_matching_procedures(spec, MR_register_match, &m);
|
|
*unique = m.match_unique;
|
|
return m.matching_entry;
|
|
}
|
|
|
|
void
|
|
MR_process_matching_procedures(MR_ProcSpec *spec,
|
|
void f(void *, const MR_ProcLayout *), void *data)
|
|
{
|
|
if (spec->MR_proc_module != NULL) {
|
|
const MR_ModuleLayout *module;
|
|
|
|
module = MR_search_module_info_by_name(spec->MR_proc_module);
|
|
if (module != NULL) {
|
|
MR_process_matching_procedures_in_module(module, spec, f, data);
|
|
} else {
|
|
const MR_Dlist *modules;
|
|
const MR_Dlist *element_ptr;
|
|
|
|
modules = MR_search_module_info_by_nickname(spec->MR_proc_module);
|
|
MR_for_dlist (element_ptr, modules) {
|
|
module = (const MR_ModuleLayout *) MR_dlist_data(element_ptr);
|
|
MR_process_matching_procedures_in_module(module, spec, f,
|
|
data);
|
|
}
|
|
}
|
|
} else {
|
|
int i;
|
|
|
|
for (i = 0; i < MR_module_info_next; i++) {
|
|
MR_process_matching_procedures_in_module(MR_module_infos[i], spec,
|
|
f, data);
|
|
}
|
|
}
|
|
}
|
|
|
|
#define match_user_proc_name(spec, cur) \
|
|
(((spec)->MR_proc_name == NULL) || \
|
|
MR_streq((spec)->MR_proc_name, cur->MR_sle_user.MR_user_name))
|
|
|
|
#define match_user_proc_arity(spec, cur) \
|
|
(((spec)->MR_proc_arity < 0) || \
|
|
(spec)->MR_proc_arity == MR_sle_user_adjusted_arity(cur))
|
|
|
|
#define match_user_proc_mode(spec, cur) \
|
|
(((spec)->MR_proc_mode < 0) || \
|
|
(spec)->MR_proc_mode == cur->MR_sle_user.MR_user_mode)
|
|
|
|
#define match_user_proc_pf(spec, cur) \
|
|
(((int) (spec)->MR_proc_prefix < 0) || \
|
|
( ( ((spec)->MR_proc_prefix == MR_PREFIX_PRED) && \
|
|
cur->MR_sle_user.MR_user_pred_or_func == MR_PREDICATE) || \
|
|
( ((spec)->MR_proc_prefix == MR_PREFIX_FUNC) && \
|
|
cur->MR_sle_user.MR_user_pred_or_func == MR_FUNCTION) \
|
|
))
|
|
|
|
#define match_uci_type_name(spec, cur) \
|
|
(((spec)->MR_proc_name == NULL) || \
|
|
MR_streq((spec)->MR_proc_name, cur->MR_sle_uci.MR_uci_type_name))
|
|
|
|
#define match_uci_type_arity(spec, cur) \
|
|
(((spec)->MR_proc_arity < 0) || \
|
|
(spec)->MR_proc_arity == cur->MR_sle_uci.MR_uci_type_arity)
|
|
|
|
#define match_uci_proc_mode(spec, cur) \
|
|
(((spec)->MR_proc_mode < 0) || \
|
|
(spec)->MR_proc_mode == cur->MR_sle_uci.MR_uci_mode)
|
|
|
|
#define match_uci_pred_name(spec, cur) \
|
|
(((int) (spec)->MR_proc_prefix < 0) || \
|
|
( ( ((spec)->MR_proc_prefix == MR_PREFIX_UNIF) && \
|
|
MR_streq(cur->MR_sle_uci.MR_uci_pred_name, "__Unify__")) || \
|
|
( ((spec)->MR_proc_prefix == MR_PREFIX_COMP) && \
|
|
MR_streq(cur->MR_sle_uci.MR_uci_pred_name, "__Compare__")) || \
|
|
( ((spec)->MR_proc_prefix == MR_PREFIX_INDX) && \
|
|
MR_streq(cur->MR_sle_uci.MR_uci_pred_name, "__Index__")) \
|
|
))
|
|
|
|
static void
|
|
MR_process_matching_procedures_in_module(const MR_ModuleLayout *module,
|
|
MR_ProcSpec *spec, void f(void *, const MR_ProcLayout *), void *data)
|
|
{
|
|
const MR_ProcLayout *proc;
|
|
int j;
|
|
|
|
for (j = 0; j < module->MR_ml_proc_count; j++) {
|
|
proc = module->MR_ml_procs[j];
|
|
if (MR_PROC_LAYOUT_IS_UCI(proc)) {
|
|
if (match_uci_type_name(spec, proc) &&
|
|
match_uci_type_arity(spec, proc) &&
|
|
match_uci_proc_mode(spec, proc) &&
|
|
match_uci_pred_name(spec, proc))
|
|
{
|
|
f(data, proc);
|
|
}
|
|
} else {
|
|
if (match_user_proc_name(spec, proc) &&
|
|
match_user_proc_arity(spec, proc) &&
|
|
match_user_proc_mode(spec, proc) &&
|
|
match_user_proc_pf(spec, proc))
|
|
{
|
|
f(data, proc);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_filter_user_preds(MR_MatchesInfo *matches)
|
|
{
|
|
const MR_ProcLayout *entry;
|
|
int filter_pos;
|
|
int i;
|
|
|
|
filter_pos = 0;
|
|
for(i = 0; i < matches->match_proc_next; i++) {
|
|
entry = matches->match_procs[i];
|
|
if (!MR_PROC_LAYOUT_IS_UCI(entry) &&
|
|
(entry->MR_sle_user).MR_user_mode == 0)
|
|
{
|
|
matches->match_procs[filter_pos] = entry;
|
|
filter_pos++;
|
|
}
|
|
}
|
|
matches->match_proc_next = filter_pos;
|
|
}
|
|
|
|
MR_CompleterList *
|
|
MR_trace_module_completer(const char *word, size_t word_len)
|
|
{
|
|
return MR_trace_sorted_array_completer(word, word_len, MR_module_info_next,
|
|
MR_get_module_info_name);
|
|
}
|
|
|
|
static char *
|
|
MR_get_module_info_name(int slot)
|
|
{
|
|
return (char *) MR_module_infos[slot]->MR_ml_name;
|
|
}
|
|
|
|
MR_CompleterList *
|
|
MR_trace_proc_spec_completer(const char *word, size_t word_len)
|
|
{
|
|
MR_ProcCompleterData *data;
|
|
int slot;
|
|
MR_bool found;
|
|
|
|
MR_register_all_modules_and_procs(MR_mdb_out, MR_FALSE);
|
|
|
|
data = MR_NEW(MR_ProcCompleterData);
|
|
|
|
if (MR_strneq(word, "pred*", 5)) {
|
|
data->MR_complete_pf = MR_PREDICATE;
|
|
word += 5;
|
|
} else if (MR_strneq(word, "func*", 5)) {
|
|
data->MR_complete_pf = MR_FUNCTION;
|
|
word += 5;
|
|
} else {
|
|
/*
|
|
** We don't complete on the names of special (unify, index compare,
|
|
** or init) predicates.
|
|
*/
|
|
|
|
data->MR_complete_pf = -1;
|
|
}
|
|
|
|
data->MR_complete_name = MR_copy_string(word);
|
|
MR_translate_double_underscores(data->MR_complete_name);
|
|
data->MR_complete_name_len = strlen(data->MR_complete_name);
|
|
data->MR_complete_name_is_qualified =
|
|
strchr(data->MR_complete_name, '.') != NULL;
|
|
data->MR_complete_word_matches_module = 0;
|
|
data->MR_complete_current_module = -1;
|
|
data->MR_complete_current_proc= -1;
|
|
|
|
/*
|
|
** Handle the case where the word matches the first part of a module name.
|
|
** If the word unambiguously determines the module name we want to return
|
|
** module qualified completions for all the procedures in that module.
|
|
** Otherwise, we just complete on the names of all of the matching modules
|
|
** and unqualified procedure names.
|
|
**
|
|
** For example, given word to complete `f' and modules `foo' and `bar',
|
|
** we want to return all the procedures in module `foo' as completions,
|
|
** as well as all procedures whose unqualified names begin with `f'.
|
|
** Given word to complete `foo.' and modules `foo' and `foo.bar' we want to
|
|
** return `foo.bar.' and all the procedures in module `foo' as completions.
|
|
*/
|
|
|
|
MR_bsearch(MR_module_info_next, slot, found,
|
|
strncmp(MR_module_infos[slot]->MR_ml_name,
|
|
data->MR_complete_name, data->MR_complete_name_len));
|
|
if (found) {
|
|
data->MR_unambiguous_matching_module = slot;
|
|
if (slot > 0 &&
|
|
MR_strneq(MR_module_infos[slot - 1]->MR_ml_name,
|
|
data->MR_complete_name, data->MR_complete_name_len))
|
|
{
|
|
data->MR_unambiguous_matching_module = -1;
|
|
}
|
|
if (slot < MR_module_info_next - 1 &&
|
|
MR_strneq(MR_module_infos[slot + 1]->MR_ml_name,
|
|
data->MR_complete_name, data->MR_complete_name_len))
|
|
{
|
|
data->MR_unambiguous_matching_module = -1;
|
|
}
|
|
} else {
|
|
data->MR_unambiguous_matching_module = -1;
|
|
}
|
|
|
|
return MR_new_completer_elem(MR_trace_proc_spec_completer_next,
|
|
(MR_CompleterData) data, MR_free_proc_completer_data);
|
|
}
|
|
|
|
static char *
|
|
MR_trace_proc_spec_completer_next(const char *dont_use_this_word,
|
|
size_t dont_use_this_len, MR_CompleterData *completer_data)
|
|
{
|
|
MR_ProcCompleterData *data;
|
|
char *name;
|
|
size_t name_len;
|
|
const char *module_name;
|
|
int module_name_len;
|
|
char *completion;
|
|
|
|
data = (MR_ProcCompleterData *) *completer_data;
|
|
|
|
name = data->MR_complete_name;
|
|
name_len = data->MR_complete_name_len;
|
|
|
|
try_completion:
|
|
if (data->MR_complete_current_module == -1 ||
|
|
data->MR_complete_current_proc == -1 ||
|
|
data->MR_complete_current_proc >=
|
|
MR_module_infos[data->MR_complete_current_module]->MR_ml_proc_count)
|
|
{
|
|
/*
|
|
** Move on to the next module.
|
|
*/
|
|
|
|
data->MR_complete_current_module++;
|
|
if (data->MR_complete_current_module >= MR_module_info_next) {
|
|
return NULL;
|
|
}
|
|
MR_trace_proc_spec_completer_init_module(data);
|
|
|
|
/*
|
|
** Complete on the module name if we aren't finding
|
|
** qualified completions in this module.
|
|
*/
|
|
|
|
module_name = MR_module_infos[data->MR_complete_current_module]
|
|
->MR_ml_name;
|
|
if (data->MR_complete_word_matches_module == 0 &&
|
|
MR_strneq(name, module_name, name_len))
|
|
{
|
|
return MR_format_proc_spec_completion(data->MR_complete_pf,
|
|
module_name, "");
|
|
} else {
|
|
goto try_completion;
|
|
}
|
|
} else {
|
|
/*
|
|
** Complete on the next procedure in the current module.
|
|
*/
|
|
completion = MR_trace_complete_proc(data);
|
|
|
|
if (completion != NULL) {
|
|
return completion;
|
|
} else {
|
|
goto try_completion;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Set up the completer data for processing a module.
|
|
*/
|
|
|
|
static void
|
|
MR_trace_proc_spec_completer_init_module(MR_ProcCompleterData *data)
|
|
{
|
|
char *name;
|
|
size_t name_len;
|
|
char *module_name;
|
|
int module_name_len;
|
|
|
|
name = data->MR_complete_name;
|
|
name_len = data->MR_complete_name_len;
|
|
|
|
module_name = (char *)
|
|
MR_module_infos[data->MR_complete_current_module]->MR_ml_name;
|
|
module_name_len = strlen(module_name);
|
|
|
|
/*
|
|
** Work out whether we should find qualified completions
|
|
** for procedures in this module.
|
|
*/
|
|
|
|
if (MR_strneq(module_name, name, module_name_len)
|
|
&& name_len > module_name_len
|
|
&& name[module_name_len] == '.'
|
|
&& strchr(name + module_name_len + 1, '.') == NULL)
|
|
{
|
|
/*
|
|
** The name to complete matches the module name completely.
|
|
** When searching for qualified completions skip past
|
|
** the module name and the trailing '.'.
|
|
*/
|
|
|
|
data->MR_complete_word_matches_module = module_name_len + 1;
|
|
} else if (data->MR_complete_current_module ==
|
|
data->MR_unambiguous_matching_module)
|
|
{
|
|
/*
|
|
** The name to complete matches the module name partially,
|
|
** and does not match any other module name. We will be
|
|
** matching all procedures, use the empty string as the
|
|
** name to match against.
|
|
*/
|
|
|
|
data->MR_complete_word_matches_module = name_len;
|
|
} else {
|
|
data->MR_complete_word_matches_module = 0;
|
|
}
|
|
|
|
/*
|
|
** If the name to complete is qualified, we should only
|
|
** complete on procedures if the module name matches.
|
|
*/
|
|
if (data->MR_complete_name_is_qualified &&
|
|
data->MR_complete_word_matches_module == 0)
|
|
{
|
|
data->MR_complete_current_proc = -1;
|
|
} else {
|
|
data->MR_complete_current_proc = 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Check whether the current procedure matches the word to be completed.
|
|
** To do: complete on arity and mode number.
|
|
*/
|
|
|
|
static char *
|
|
MR_trace_complete_proc(MR_ProcCompleterData *data)
|
|
{
|
|
char *completion;
|
|
char *name;
|
|
int name_len;
|
|
char *unqualified_name;
|
|
int unqualified_name_len;
|
|
char *complete_module;
|
|
const MR_ModuleLayout *module_layout;
|
|
const MR_ProcLayout *proc_layout;
|
|
|
|
name = data->MR_complete_name;
|
|
name_len = data->MR_complete_name_len;
|
|
|
|
unqualified_name = name + data->MR_complete_word_matches_module;
|
|
unqualified_name_len = name_len - data->MR_complete_word_matches_module;
|
|
|
|
module_layout = MR_module_infos[data->MR_complete_current_module];
|
|
proc_layout = module_layout->MR_ml_procs[data->MR_complete_current_proc];
|
|
|
|
if (
|
|
! MR_PROC_LAYOUT_IS_UCI(proc_layout) &&
|
|
( data->MR_complete_pf == -1 ||
|
|
proc_layout->MR_sle_user.MR_user_pred_or_func == data->MR_complete_pf
|
|
) &&
|
|
MR_strneq(proc_layout->MR_sle_user.MR_user_name, unqualified_name,
|
|
unqualified_name_len))
|
|
{
|
|
if (data->MR_complete_word_matches_module != 0) {
|
|
complete_module = (char *) module_layout->MR_ml_name;
|
|
} else {
|
|
complete_module = NULL;
|
|
}
|
|
completion = MR_format_proc_spec_completion(data->MR_complete_pf,
|
|
complete_module, proc_layout->MR_sle_user.MR_user_name);
|
|
} else {
|
|
completion = NULL;
|
|
}
|
|
|
|
/*
|
|
** Move on to the next procedure in the current module.
|
|
*/
|
|
|
|
data->MR_complete_current_proc++;
|
|
|
|
if (data->MR_complete_word_matches_module != 0
|
|
&& data->MR_complete_current_proc >= module_layout->MR_ml_proc_count
|
|
&& ! data->MR_complete_name_is_qualified)
|
|
{
|
|
/*
|
|
** We've finished checking for module qualified completions
|
|
** in this module, now check for unqualified completions
|
|
** if the word to complete doesn't contain a qualifier.
|
|
*/
|
|
data->MR_complete_word_matches_module = 0;
|
|
data->MR_complete_current_proc = 0;
|
|
}
|
|
|
|
return completion;
|
|
}
|
|
|
|
static char *
|
|
MR_format_proc_spec_completion(MR_PredFunc pred_or_func,
|
|
const char *module, const char *name)
|
|
{
|
|
int size;
|
|
int module_len;
|
|
int offset;
|
|
char *completion;
|
|
|
|
size = strlen(name);
|
|
if (pred_or_func != -1) {
|
|
size += 5;
|
|
}
|
|
if (module != NULL) {
|
|
/* +1 for the '.' */
|
|
module_len = strlen(module);
|
|
size += module_len + 1;
|
|
} else {
|
|
module_len = 0; /* avoid a warning */
|
|
}
|
|
completion = MR_malloc(size + 1);
|
|
|
|
offset = 0;
|
|
if (pred_or_func == MR_PREDICATE) {
|
|
strcpy(completion, "pred*");
|
|
offset += 5;
|
|
} else if (pred_or_func == MR_FUNCTION) {
|
|
strcpy(completion, "func*");
|
|
offset += 5;
|
|
}
|
|
|
|
if (module != NULL) {
|
|
strcpy(completion + offset, module);
|
|
offset += module_len;
|
|
completion[offset] = '.';
|
|
offset++;
|
|
}
|
|
|
|
strcpy(completion + offset, name);
|
|
|
|
return completion;
|
|
}
|
|
|
|
static void
|
|
MR_free_proc_completer_data(MR_CompleterData completer_data)
|
|
{
|
|
MR_ProcCompleterData *data;
|
|
|
|
data = (MR_ProcCompleterData *) completer_data;
|
|
|
|
MR_free(data->MR_complete_name);
|
|
MR_free(data);
|
|
}
|
|
|
|
void
|
|
MR_print_proc_id_and_nl(FILE *fp, const MR_ProcLayout *entry_layout)
|
|
{
|
|
MR_print_proc_id(fp, entry_layout);
|
|
fprintf(fp, "\n");
|
|
}
|
|
|
|
MR_ConstString
|
|
MR_get_proc_decl_module(const MR_ProcLayout *proc)
|
|
{
|
|
if (MR_PROC_LAYOUT_IS_UCI(proc)) {
|
|
return (&proc->MR_sle_uci)->MR_uci_type_module;
|
|
} else {
|
|
return (&proc->MR_sle_user)->MR_user_decl_module;
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_print_pred_id_and_nl(FILE *fp, const MR_ProcLayout *entry_layout)
|
|
{
|
|
MR_print_pred_id(fp, entry_layout);
|
|
fprintf(fp, "\n");
|
|
}
|
|
|
|
void
|
|
MR_proc_layout_stats(FILE *fp)
|
|
{
|
|
const MR_ModuleLayout *module_layout;
|
|
const MR_ProcLayout *proc_layout;
|
|
int module_num, proc_num;
|
|
MR_Determinism detism;
|
|
int total;
|
|
int histogram[MR_DETISM_MAX + 1];
|
|
|
|
total = 0;
|
|
for (detism = 0; detism <= MR_DETISM_MAX; detism++) {
|
|
histogram[detism] = 0;
|
|
}
|
|
|
|
for (module_num = 0; module_num < MR_module_info_next; module_num++) {
|
|
module_layout = MR_module_infos[module_num];
|
|
|
|
for (proc_num = 0;
|
|
proc_num < module_layout->MR_ml_proc_count;
|
|
proc_num++)
|
|
{
|
|
proc_layout = module_layout->MR_ml_procs[proc_num];
|
|
|
|
total++;
|
|
if (0 <= proc_layout->MR_sle_detism &&
|
|
proc_layout->MR_sle_detism <= MR_DETISM_MAX)
|
|
{
|
|
histogram[proc_layout->MR_sle_detism]++;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (detism = 0; detism <= MR_DETISM_MAX; detism++) {
|
|
if (histogram[detism] > 0) {
|
|
fprintf(fp, "%-10s %10d (%5.2f%%)\n", MR_detism_names[detism],
|
|
histogram[detism], ((float) 100 * histogram[detism]) / total);
|
|
}
|
|
}
|
|
fprintf(fp, "%-10s %10d\n", "all ", total);
|
|
}
|
|
|
|
void
|
|
MR_label_layout_stats(FILE *fp)
|
|
{
|
|
const MR_ModuleLayout *module_layout;
|
|
const MR_ModuleFileLayout *file_layout;
|
|
const MR_LabelLayout *label_layout;
|
|
int module_num;
|
|
int file_num;
|
|
int label_num;
|
|
MR_TracePort port;
|
|
int total;
|
|
int histogram[MR_PORT_NUM_PORTS];
|
|
int var_count_neg;
|
|
int var_count_zero;
|
|
int var_count_pos;
|
|
int var_count_total;
|
|
int no_long;
|
|
int some_long;
|
|
int long_total;
|
|
|
|
var_count_neg = 0;
|
|
var_count_zero = 0;
|
|
var_count_pos = 0;
|
|
no_long = 0;
|
|
some_long = 0;
|
|
|
|
total = 0;
|
|
for (port = 0; port < MR_PORT_NUM_PORTS; port++) {
|
|
histogram[port] = 0;
|
|
}
|
|
|
|
for (module_num = 0; module_num < MR_module_info_next; module_num++) {
|
|
module_layout = MR_module_infos[module_num];
|
|
|
|
for (file_num = 0;
|
|
file_num < module_layout->MR_ml_filename_count;
|
|
file_num++)
|
|
{
|
|
file_layout = module_layout->MR_ml_module_file_layout[file_num];
|
|
|
|
for (label_num = 0;
|
|
label_num < file_layout->MR_mfl_label_count;
|
|
label_num++)
|
|
{
|
|
label_layout = file_layout->MR_mfl_label_layout[label_num];
|
|
|
|
total++;
|
|
if (0 <= label_layout->MR_sll_port &&
|
|
label_layout->MR_sll_port < MR_PORT_NUM_PORTS)
|
|
{
|
|
histogram[label_layout->MR_sll_port]++;
|
|
}
|
|
|
|
if (label_layout->MR_sll_var_count < 0) {
|
|
var_count_neg++;
|
|
} else if (label_layout->MR_sll_var_count == 0) {
|
|
var_count_zero++;
|
|
} else {
|
|
var_count_pos++;
|
|
}
|
|
|
|
if (MR_long_desc_var_count(label_layout) > 0) {
|
|
some_long++;
|
|
} else {
|
|
no_long++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (port = 0; port < MR_PORT_NUM_PORTS; port++) {
|
|
fprintf(fp, "%4s %10d (%5.2f%%)\n", MR_actual_port_names[port],
|
|
histogram[port], ((float) 100 * histogram[port]) / total);
|
|
}
|
|
fprintf(fp, "%s %10d\n\n", "all ", total);
|
|
|
|
var_count_total = var_count_neg + var_count_zero + var_count_pos;
|
|
fprintf(fp, "var_count <0: %6d (%5.2f)\n",
|
|
var_count_neg, (float) var_count_neg / (float) var_count_total);
|
|
fprintf(fp, "var_count =0: %6d (%5.2f)\n",
|
|
var_count_zero, (float) var_count_zero / (float) var_count_total);
|
|
fprintf(fp, "var_count >0: %6d (%5.2f)\n\n",
|
|
var_count_pos, (float) var_count_pos / (float) var_count_total);
|
|
|
|
long_total = no_long + some_long;
|
|
fprintf(fp, "no long: %6d (%5.2f)\n",
|
|
no_long, (float) no_long / (float) long_total);
|
|
fprintf(fp, "some long: %6d (%5.2f)\n\n",
|
|
some_long, (float) some_long / (float) long_total);
|
|
}
|
|
|
|
void
|
|
MR_var_name_stats(FILE *fp)
|
|
{
|
|
const MR_ModuleLayout *module_layout;
|
|
const MR_ProcLayout *proc_layout;
|
|
const MR_uint_least32_t *var_names;
|
|
int module_num;
|
|
int proc_num;
|
|
int var_num;
|
|
int num_var_nums;
|
|
int total_string_table_bytes;
|
|
int total_var_num_table_entries;
|
|
int total_used_var_num_table_entries;
|
|
int total_unused_var_num_table_entries;
|
|
int total_num_procs;
|
|
|
|
total_string_table_bytes = 0;
|
|
total_var_num_table_entries = 0;
|
|
total_used_var_num_table_entries = 0;
|
|
total_num_procs = 0;
|
|
|
|
for (module_num = 0; module_num < MR_module_info_next; module_num++) {
|
|
module_layout = MR_module_infos[module_num];
|
|
|
|
total_string_table_bytes += module_layout->MR_ml_string_table_size;
|
|
|
|
for (proc_num = 0;
|
|
proc_num < module_layout->MR_ml_proc_count;
|
|
proc_num++)
|
|
{
|
|
proc_layout = module_layout->MR_ml_procs[proc_num];
|
|
total_num_procs += 1;
|
|
|
|
if (! MR_PROC_LAYOUT_HAS_EXEC_TRACE(proc_layout)) {
|
|
continue;
|
|
}
|
|
|
|
var_names = proc_layout->MR_sle_used_var_names;
|
|
if (var_names != NULL) {
|
|
num_var_nums = proc_layout->MR_sle_max_named_var_num + 1;
|
|
|
|
total_var_num_table_entries += num_var_nums;
|
|
for (var_num = 0; var_num < num_var_nums; var_num++) {
|
|
if (var_names[var_num] != 0) {
|
|
total_used_var_num_table_entries++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fprintf(fp, "%d modules, %d bytes in string tables, average %.2f\n",
|
|
MR_module_info_next, total_string_table_bytes,
|
|
(float) total_string_table_bytes / MR_module_info_next);
|
|
fprintf(fp, "%d procedures, %d var numbers, average %.2f\n",
|
|
total_num_procs, total_var_num_table_entries,
|
|
(float) total_var_num_table_entries / total_num_procs);
|
|
fprintf(fp, "%d procedures, %d used var numbers, average %.2f\n",
|
|
total_num_procs, total_used_var_num_table_entries,
|
|
(float) total_used_var_num_table_entries / total_num_procs);
|
|
fprintf(fp, "%d var numbers, %d used, average %.2f%%\n",
|
|
total_var_num_table_entries,
|
|
total_used_var_num_table_entries,
|
|
(float) 100 * total_used_var_num_table_entries /
|
|
total_var_num_table_entries);
|
|
total_unused_var_num_table_entries =
|
|
total_var_num_table_entries - total_used_var_num_table_entries;
|
|
fprintf(fp, "%d unused var numbers, %d bytes\n",
|
|
total_unused_var_num_table_entries,
|
|
4 * total_unused_var_num_table_entries);
|
|
}
|