//
// aegis - project change supervisor
// Copyright (C) 2004-2006, 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 // for assert
#include
#include
#include
#include
static bool
extract_change_number(string_ty **project_name_p, long *change_number_p)
{
string_ty *project_name;
char *end;
long change_number;
project_name = *project_name_p;
const char *cp =
(const char *)
memmem(project_name->str_text, project_name->str_length, ".C", 2);
if (!cp)
{
cp =
(const char *)
memmem(project_name->str_text, project_name->str_length, ".c", 2);
}
if (!cp)
return false;
change_number = strtol(cp + 2, &end, 10);
if (end == cp + 2 || *end)
return false;
//
// We have a change number.
//
// NOTE: the caller must free the new project name.
//
*change_number_p = change_number;
*project_name_p =
str_n_from_c(project_name->str_text, cp - project_name->str_text);
return true;
}
static void
reaper(void *p)
{
module_ty *mp = (module_ty *)(p);
mp->reference_count_down();
}
module
module::find(string_ty *name)
{
//
// We cache the answers. A typical session is going to do this
// for many requests, not just one.
//
static symtab_ty *stp;
if (!stp)
{
stp = new symtab_ty(5);
stp->set_reap(reaper);
}
module_ty *mp = (module_ty *)stp->query(name);
if (mp)
{
//
// We increase the reference count, so that the symbol table
// always has a valid reference.
//
assert(mp->reference_count_valid());
mp->reference_count_up();
return mp;
}
//
// We haven't seen this one before,
// create a new instance for it.
//
if (0 == strcmp(name->str_text, "CVSROOT"))
mp = new module_cvsroot();
else
{
long change_number = 0;
if (extract_change_number(&name, &change_number))
mp = module_change_new(name, change_number);
else
mp = module_project_new(name);
}
//
// Stash it away in the symbol table.
//
// The reference count is one when allocated. The symbol table
// has a valid reference at this point.
//
stp->assign(name, mp);
string_ty *name2 = mp->name();
if (!str_equal(name, name2))
{
//
// This isn't supposed to happen, because the client calls
// expand-modules forst.
//
mp->reference_count_up();
stp->assign(name2, mp);
}
//
// We increase the reference count, so that the symbol table
// always has a valid reference AND the caller has a valid reference.
//
mp->reference_count_up();
assert(mp->reference_count_valid());
//
// Report success.
//
return mp;
}
module
module::find_trim(string_ty *arg)
{
string_ty *name = str_field(arg, '/', 0);
module m = find(name);
str_free(name);
return m;
}