Skip to content

Commit

Permalink
require(): Extend syntax to "require(TYPE VALUE)".
Browse files Browse the repository at this point in the history
"require(package VALUE)" is the new version of "require(PACKAGE)";
for backwards compatibility "require(PACKAGE)" also works.

The idea is to pave the way for, say, "require(library VALUE)", which might
be a version of #include.
  • Loading branch information
kohler committed Jan 27, 2010
1 parent 094280c commit d4ad754
Show file tree
Hide file tree
Showing 17 changed files with 163 additions and 111 deletions.
8 changes: 4 additions & 4 deletions bsdmodule/config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@ read_classes(Element *, void *)

class BSDModuleLexerExtra : public LexerExtra { public:
BSDModuleLexerExtra() { }
void require(String, ErrorHandler *);
void require(String type, String value, ErrorHandler *errh);
};

void
BSDModuleLexerExtra::require(String r, ErrorHandler *errh)
BSDModuleLexerExtra::require(String type, String value, ErrorHandler *errh)
{
if (!click_has_provision(r.c_str()))
errh->error("unsatisfied requirement `%s'", r.c_str());
if (type.equals("package", 7) && !click_has_provision(value.c_str()))
errh->error("unsatisfied requirement %<%s%>", value.c_str());
}

static Router *
Expand Down
12 changes: 6 additions & 6 deletions doc/click.5
Original file line number Diff line number Diff line change
Expand Up @@ -515,15 +515,15 @@ elementclass Test { $a, $b | /* nothing */ || ... }
.SH "REQUIREMENTS"
'
A configuration can say that it depends on optional packages by using the
`require' statement. Its argument is a comma-separated list of package
names:
`require' statement. Its argument is a comma-separated list of require
statements, such as package names:
.Rs
require(fastclassifier, specialcode);
require(package fastclassifier, package specialcode);
.Re
Installation programs can use the package names to find and upload any
necessary package code. Furthermore, the required package names are checked
against a list of currently active packages when a configuration is
installed. If any required packages are unavailable, an error is reported.
necessary package code. The required package names are also checked against
a list of currently active packages when a configuration is installed. If
any required packages are unavailable, an error is reported.
'
.SH "PARAMETER DEFINITIONS"
'
Expand Down
2 changes: 1 addition & 1 deletion etc/samplepackage/test.click
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require(sample);
require(package "sample");

test :: SamplePackageElement;

Expand Down
2 changes: 1 addition & 1 deletion include/click/lexer.hh
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ class LexerExtra { public:
LexerExtra() { }
virtual ~LexerExtra() { }

virtual void require(String, ErrorHandler *);
virtual void require(String type, String value, ErrorHandler *errh);

};

Expand Down
9 changes: 1 addition & 8 deletions include/click/router.hh
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,7 @@ class Router { public:
inline void use();
void unuse();

inline const Vector<String>& requirements() const;
void add_requirement(const String& requirement);
void add_requirement(const String &type, const String &value);
int add_element(Element *e, const String &name, const String &conf, const String &filename, unsigned lineno);
int add_connection(int from_idx, int from_port, int to_idx, int to_port);
#if CLICK_LINUXMODULE
Expand Down Expand Up @@ -426,12 +425,6 @@ Router::root_element() const
return _root_element;
}

inline const Vector<String>&
Router::requirements() const
{
return _requirements;
}

inline ThreadSched*
Router::thread_sched() const
{
Expand Down
12 changes: 6 additions & 6 deletions lib/driver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -354,20 +354,20 @@ namespace {

class RequireLexerExtra : public LexerExtra { public:
RequireLexerExtra(const Vector<ArchiveElement> *a) : _archive(a) { }
void require(String, ErrorHandler *);
void require(String type, String value, ErrorHandler *errh);
private:
const Vector<ArchiveElement> *_archive;
};

void
RequireLexerExtra::require(String name, ErrorHandler *errh)
RequireLexerExtra::require(String type, String value, ErrorHandler *errh)
{
# ifdef HAVE_DYNAMIC_LINKING
if (!click_has_provision(name.c_str()))
clickdl_load_requirement(name, _archive, errh);
if (type.equals("package", 7) && !click_has_provision(value.c_str()))
clickdl_load_requirement(value, _archive, errh);
# endif
if (!click_has_provision(name.c_str()))
errh->error("requirement %<%s%> not available", name.c_str());
if (type.equals("package", 7) && !click_has_provision(value.c_str()))
errh->error("requirement %<%s%> not available", value.c_str());
}

}
Expand Down
60 changes: 39 additions & 21 deletions lib/lexer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* Copyright (c) 2001-2003 International Computer Science Institute
* Copyright (c) 2004-2007 Regents of the University of California
* Copyright (c) 2008 Meraki, Inc.
* Copyright (c) 2010 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
Expand Down Expand Up @@ -1471,34 +1472,51 @@ Lexer::ycompound(String name)
void
Lexer::yrequire()
{
if (expect('(')) {
if (!expect('('))
return;

String requirement = lex_config();
expect(')');
// pre-read ';' to make it easier to write parsing extensions
expect(';', false);

Vector<String> args;
String word;
cp_argvec(requirement, args);

String compact_config_str = String::make_stable("compact_config", 14);
String package_str = String::make_stable("package", 7);

for (int i = 0; i < args.size(); i++) {
Vector<String> words;
cp_spacevec(args[i], words);
if (words.size() == 0)
/* do nothing */;
else if (!cp_word(words[0], &word))
lerror("bad requirement: not a word");
else if (words.size() > 1)
lerror("bad requirement: too many words");
else {
if (word.equals("compact_config", 14)) {
Vector<String> words;
cp_spacevec(args[i], words);
if (words.size() == 0)
continue; // do nothing

String type, value;
(void) cp_word(words[0], &type);
// "require(UNKNOWN)" means "require(package UNKNOWN)"
if (type && type != compact_config_str && type != package_str
&& words.size() == 1) {
words.push_back(type);
type = package_str;
}

if (type == compact_config_str && words.size() == 1) {
_compact_config = true;
word = word.compact();
} else if (_lextra)
_lextra->require(word, _errh);
_requirements.push_back(word);
}
type = compact_config_str;
} else if (type == package_str && words.size() == 2
&& cp_string(words[1], &value))
/* OK */;
else {
lerror("syntax error at requirement");
continue;
}

if (_lextra)
_lextra->require(type, value, _errh);
_requirements.push_back(type);
_requirements.push_back(value);
}
}
}

void
Expand Down Expand Up @@ -1712,8 +1730,8 @@ Lexer::create_router(Master *master)
router->add_connection((*cp)[1].idx, (*cp)[1].port, (*cp)[0].idx, (*cp)[0].port);

// add requirements to router
for (int i = 0; i < _requirements.size(); i++)
router->add_requirement(_requirements[i]);
for (int i = 0; i < _requirements.size(); i += 2)
router->add_requirement(_requirements[i], _requirements[i+1]);

return router;
}
Expand All @@ -1724,7 +1742,7 @@ Lexer::create_router(Master *master)
//

void
LexerExtra::require(String, ErrorHandler *)
LexerExtra::require(String, String, ErrorHandler *)
{
}

Expand Down
20 changes: 14 additions & 6 deletions lib/router.cc
Original file line number Diff line number Diff line change
Expand Up @@ -428,11 +428,12 @@ Router::add_connection(int from_idx, int from_port, int to_idx, int to_port)
}

void
Router::add_requirement(const String &r)
Router::add_requirement(const String &type, const String &requirement)
{
assert(cp_is_word(r));
_requirements.push_back(r);
if (r.equals("compact_config", 14)) {
assert(cp_is_word(type));
_requirements.push_back(type);
_requirements.push_back(requirement);
if (type.equals("compact_config", 14)) {
_have_configuration = false;
_configuration = String();
}
Expand Down Expand Up @@ -1890,8 +1891,15 @@ void
Router::unparse_requirements(StringAccum &sa, const String &indent) const
{
// requirements
if (_requirements.size())
sa << indent << "require(" << cp_unargvec(_requirements) << ");\n\n";
if (_requirements.size()) {
sa << indent << "require(";
for (int i = 0; i < _requirements.size(); i += 2) {
sa << (i ? ", " : "") << _requirements[i];
if (_requirements[i+1])
sa << " " << cp_quote(_requirements[i+1]);
}
sa << ");\n\n";
}
}

/** @brief Unparse declarations of the router's elements into @a sa.
Expand Down
8 changes: 4 additions & 4 deletions linuxmodule/config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@ read_classes(Element *, void *)

class LinuxModuleLexerExtra : public LexerExtra { public:
LinuxModuleLexerExtra() { }
void require(String, ErrorHandler *);
void require(String type, String value, ErrorHandler *errh);
};

void
LinuxModuleLexerExtra::require(String r, ErrorHandler *errh)
LinuxModuleLexerExtra::require(String type, String value, ErrorHandler *errh)
{
if (!click_has_provision(r.c_str()))
errh->error("unsatisfied requirement '%s'", r.c_str());
if (type.equals("package", 7) && !click_has_provision(value.c_str()))
errh->error("unsatisfied requirement %<%s%>", value.c_str());
}

static Router *
Expand Down
11 changes: 6 additions & 5 deletions tools/click-devirtualize/click-devirtualize.cc
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,11 @@ reverse_transformation(RouterT *r, ErrorHandler *)

// remove requirements
{
Vector<String> requirements = r->requirements();
for (int i = 0; i < requirements.size(); i++)
if (requirements[i].substring(0, 12) == "devirtualize")
r->remove_requirement(requirements[i]);
Vector<String> requirements = r->requirements();
for (int i = 0; i < requirements.size(); i += 2)
if (requirements[i].equals("package", 7)
&& requirements[i+1].substring(0, 12) == "devirtualize")
r->remove_requirement(requirements[i], requirements[i+1]);
}

// remove archive elements
Expand Down Expand Up @@ -441,7 +442,7 @@ particular purpose.\n");
md5_free(&pms);
package_name = "clickdv_" + String(buf, buflen);
}
router->add_requirement(package_name);
router->add_requirement("package", package_name);

// output
StringAccum header, source;
Expand Down
15 changes: 8 additions & 7 deletions tools/click-fastclassifier/click-fastclassifier.cc
Original file line number Diff line number Diff line change
Expand Up @@ -369,8 +369,8 @@ classifiers_program(RouterT *r, const Vector<ElementT *> &classifiers)

ElementT *idle = nr->add_anon_element(ElementClassT::base_type("Idle"));
const Vector<String> &old_requirements = r->requirements();
for (int i = 0; i < old_requirements.size(); i++)
nr->add_requirement(old_requirements[i]);
for (int i = 0; i < old_requirements.size(); i += 2)
nr->add_requirement(old_requirements[i], old_requirements[i+1]);

// copy AlignmentInfos and AddressInfos
copy_elements(r, nr, ElementClassT::base_type("AlignmentInfo"));
Expand Down Expand Up @@ -633,7 +633,7 @@ compile_classifiers(RouterT *r, const String &package_name,
analyze_classifiers(nr, classifiers, errh);

// add requirement
r->add_requirement(package_name);
r->add_requirement("package", package_name);

// write Classifier programs
for (int i = 0; i < all_programs.size(); i++)
Expand Down Expand Up @@ -758,10 +758,11 @@ reverse_transformation(RouterT *r, ErrorHandler *)

// remove requirements
{
Vector<String> requirements = r->requirements();
for (int i = 0; i < requirements.size(); i++)
if (requirements[i].substring(0, 14) == "fastclassifier")
r->remove_requirement(requirements[i]);
Vector<String> requirements = r->requirements();
for (int i = 0; i < requirements.size(); i += 2)
if (requirements[i].equals("package", 7)
&& requirements[i+1].substring(0, 14) == "fastclassifier")
r->remove_requirement(requirements[i], requirements[i+1]);
}

// remove archive elements
Expand Down
17 changes: 11 additions & 6 deletions tools/click-install/click-install.cc
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,15 @@ static void
compile_archive_packages(RouterT *r, HashTable<String, int> &packages,
ErrorHandler *errh)
{
Vector<String> requirements = r->requirements();
bool tmpdir_populated = false;

// go over requirements
for (int i = 0; i < requirements.size(); i++) {
const String &req = requirements[i];
Vector<String> requirements = r->requirements();
for (int i = 0; i < requirements.size(); i += 2) {
if (!requirements[i].equals("package", 7))
continue;

const String &req = requirements[i+1];

// skip if already have object file
if (r->archive_index(req + OBJSUFFIX) >= 0
Expand Down Expand Up @@ -221,11 +224,13 @@ install_required_packages(RouterT *r, HashTable<String, int> &packages,
// check for uncompiled archive packages and try to compile them
compile_archive_packages(r, packages, errh);

// go over requirements
Vector<String> requirements = r->requirements();
for (int i = 0; i < requirements.size(); i += 2) {
if (!requirements[i].equals("package", 7))
continue;

// go over requirements
for (int i = 0; i < requirements.size(); i++) {
String req = requirements[i];
String req = requirements[i+1];

// look for object in archive
int obj_aei = r->archive_index(req + OBJSUFFIX);
Expand Down
7 changes: 5 additions & 2 deletions tools/lib/elementmap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -644,8 +644,11 @@ ElementMap::parse_requirement_files(RouterT *r, const String &default_path, Erro

// parse elementmaps for requirements in required order
const Vector<String> &requirements = r->requirements();
for (int i = 0; i < requirements.size(); i++) {
String req = requirements[i];
for (int i = 0; i < requirements.size(); i += 2) {
if (!requirements[i].equals("package", 7))
continue;

String req = requirements[i+1];
String mapname = "elementmap-" + req + ".xml";
String mapname2 = "elementmap." + req;

Expand Down
Loading

0 comments on commit d4ad754

Please sign in to comment.