//
// aegis - project change supervisor
// Copyright (C) 1994, 1995, 1997, 1999, 2001-2008 Peter Miller
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see
// .
//
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
static string_ty *input;
static string_ty *output;
static string_list_ty arg;
void
report_parse_filename_set(string_ty *fn)
{
trace(("report_parse_filename_set(fn = \"%s\")\n{\n", fn->str_text));
assert(!input);
input = str_copy(fn);
trace(("}\n"));
}
void
report_parse_output_set(string_ty *fn)
{
trace(("report_parse_output_set(fn = \"%s\")\n{\n", fn->str_text));
assert(!output);
output = str_copy(fn);
trace(("}\n"));
}
void
report_parse_argument_set(string_list_ty *a)
{
trace(("report_parse_argument_set()\n{\n"));
assert(!arg.nstrings);
arg = *a;
trace(("}\n"));
}
static void
find_filename_process(string_ty *name, string_ty *dir, const char *nondir,
rptidx_where_list_ty *result)
{
string_ty *fn;
int err;
rptidx_ty *data;
trace(("find_filename_process()\n{\n"));
fn = str_format("%s/%s", dir->str_text, nondir);
os_become_orig();
err = os_readable(fn);
if (err)
{
os_become_undo();
str_free(fn);
trace(("}\n"));
return;
}
data = rptidx_read_file(fn);
os_become_undo();
str_free(fn);
if (data->where)
{
size_t j, k;
for (j = 0; j < data->where->length; ++j)
{
rptidx_where_ty *in;
rptidx_where_ty *out;
rptidx_where_ty **out_p;
meta_type *type_p;
int have_it_already;
in = data->where->list[j];
if (!in->name || !in->filename)
continue;
trace(("arglex_compare(\"%s\", \"%s\")\n",
in->name->str_text, name->str_text));
if (!arglex_compare(in->name->str_text, name->str_text, 0))
continue;
//
// If we already have this one, ignore it.
// (Duplicate entries in AEGIS_PATH will cause
// in exact duplicates in the result list.)
//
have_it_already = 0;
for (k = 0; k < result->length; ++k)
{
out = result->list[k];
if (str_equal(in->name, out->name))
{
have_it_already = 1;
break;
}
}
if (have_it_already)
continue;
assert(result);
out_p =
(rptidx_where_ty **)
rptidx_where_list_type.list_parse(result, &type_p);
assert(type_p == &rptidx_where_type);
out = (rptidx_where_ty *)rptidx_where_type.alloc();
*out_p = out;
out->name = str_copy(in->name);
if (in->description)
out->description = str_copy(in->description);
else
out->description = str_copy(in->name);
if (in->filename->str_text[0] == '/')
out->filename = str_copy(in->filename);
else
out->filename = os_path_join(dir, in->filename);
trace(("out->filename = \"%s\";\n", out->filename->str_text));
}
}
rptidx_type.free(data);
trace(("}\n"));
}
static string_ty *
find_filename(string_ty *name)
{
rptidx_where_list_ty *result;
string_ty *tmp;
size_t j;
//
// find all reports matching the name given
//
trace(("find_filename(name = \"%s\")\n{\n", name->str_text));
string_list_ty path;
gonzo_report_path(&path);
result = (rptidx_where_list_ty *)rptidx_where_list_type.alloc();
for (j = 0; j < path.nstrings; ++j)
{
find_filename_process(name, path.string[j], "report.index", result);
find_filename_process(name, path.string[j], "report.local", result);
}
//
// it is an error if there was no matching report
//
trace(("test if no answer\n"));
if (!result->length)
{
sub_context_ty *scp;
scp = sub_context_new();
rptidx_where_list_type.free(result);
sub_var_set_string(scp, "Name", name);
fatal_intl(scp, i18n("no report $name"));
// NOTREACHED
sub_context_delete(scp);
}
//
// it is an error if there is more than one matching report
//
trace(("test if too many answers\n"));
if (result->length > 1)
{
string_list_ty path2;
for (j = 0; j < result->length; ++j)
path2.push_back_unique(result->list[j]->name);
rptidx_where_list_type.free(result);
tmp = path2.unsplit(", ");
sub_context_ty *scp = sub_context_new();
sub_var_set_string(scp, "Name", name);
sub_var_set_string(scp, "Name_List", tmp);
sub_var_optional(scp, "Name_List");
fatal_intl(scp, i18n("report $name ambig"));
// NOTREACHED
sub_context_delete(scp);
}
//
// is there is exactly one,
// we are done
//
trace(("but this bowl was just right\n"));
trace(("result->list[0]->filename = \"%s\";\n",
result->list[0]->filename->str_text));
tmp = str_copy(result->list[0]->filename);
trace(("rptidx_where_list_type.free(result);\n"));
rptidx_where_list_type.free(result);
trace(("return \"%s\";\n", tmp->str_text));
trace(("}\n"));
return tmp;
}
void
report_parse__init_arg()
{
rpt_value_list *p = new rpt_value_list();
rpt_value::pointer list(p);
for (size_t j = 1; j < arg.nstrings; ++j)
{
p->append(rpt_value_string::create(nstring(arg.string[j])));
}
rpt_value::pointer value = rpt_value_reference::create(list);
rpt_expr_name__init("arg", value);
}
void
report_run()
{
//
// find the input file is none has been named
//
trace(("report_run()\n{\n"));
assert(arg.nstrings);
if (!input)
{
trace(("find the report script\n"));
input = find_filename(arg.string[0]);
}
//
// parse the report
//
trace(("open the input file\n"));
os_become_orig();
rpt_lex_open(input);
trace(("parse the report\n"));
aer_report_parse();
trace(("close the input file\n"));
rpt_lex_close();
os_become_undo();
//
// execute the report
//
trace(("open the output file\n"));
assert(!rpt_func_print__colp);
rpt_func_print__colp = col::open(output);
trace(("interpret the report\n"));
report_interpret();
trace(("close the output file\n"));
rpt_func_print__colp.reset();
//
// release dynamic memory
//
assert(input);
str_free(input);
if (output)
str_free(output);
arg.clear();
trace(("}\n"));
}