This is an automated email from the ASF dual-hosted git repository.
xiaokang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-graphar.git
The following commit(s) were added to refs/heads/main by this push:
new 0042a6cf fix(C++): remove redundant `inline` keyword (#858)
0042a6cf is described below
commit 0042a6cf46fa1697430a4fb052ecf62bb0ecd09c
Author: Jason Yao <[email protected]>
AuthorDate: Thu Feb 26 10:03:28 2026 +0800
fix(C++): remove redundant `inline` keyword (#858)
* fix(C++): remove redundant inline keyword
Signed-off-by: syaojun <[email protected]>
* fix(ci): add missing arrow libs for benchmark
Signed-off-by: syaojun <[email protected]>
* fix(ci): ignore unused function
Signed-off-by: syaojun <[email protected]>
---------
Signed-off-by: syaojun <[email protected]>
---
cpp/CMakeLists.txt | 8 +++++--
cpp/src/graphar/arrow/chunk_writer.h | 6 +++---
cpp/src/graphar/expression.h | 4 ++--
cpp/src/graphar/graph_info.h | 10 ++++-----
cpp/src/graphar/high-level/edges_builder.h | 25 +++++++++++----------
cpp/src/graphar/high-level/graph_reader.h | 10 ++++-----
cpp/src/graphar/high-level/vertices_builder.h | 31 +++++++++++++--------------
cpp/src/graphar/result.h | 4 ++--
cpp/src/graphar/status.h | 8 +++----
cpp/src/graphar/types.h | 18 ++++++++--------
cpp/src/graphar/util.h | 10 ++++-----
cpp/src/graphar/version_parser.h | 4 ++--
12 files changed, 70 insertions(+), 68 deletions(-)
diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index 14c89c34..ef53c556 100644
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -110,7 +110,7 @@ if(MSVC)
# Avoid GCC/Clang-specific flags on MSVC.
# C++17 is already enforced via CMAKE_CXX_STANDARD/target features.
else()
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -Wextra
-Wno-unused-parameter -Wno-empty-body")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -Wextra
-Wno-unused-parameter -Wno-unused-function -Wno-empty-body")
endif()
if (APPLE)
@@ -665,7 +665,11 @@ if (BUILD_BENCHMARKS)
add_executable(${target} ${add_test_SRCS})
target_compile_features(${target} PRIVATE cxx_std_${GAR_CXX_STANDARD})
target_include_directories(${target} PRIVATE
${PROJECT_SOURCE_DIR}/thirdparty)
- target_link_libraries(${target} PRIVATE benchmark::benchmark_main
graphar ${CMAKE_DL_LIBS})
+ if(APPLE)
+ target_link_libraries(${target} PRIVATE benchmark::benchmark_main
graphar Arrow::arrow_shared Parquet::parquet_shared ${CMAKE_DL_LIBS})
+ else()
+ target_link_libraries(${target} PRIVATE benchmark::benchmark_main
graphar parquet arrow ${CMAKE_DL_LIBS})
+ endif()
if (BUILD_ARROW_FROM_SOURCE)
target_include_directories(${target} SYSTEM BEFORE PRIVATE
${GAR_ARROW_INCLUDE_DIR})
if (APPLE)
diff --git a/cpp/src/graphar/arrow/chunk_writer.h
b/cpp/src/graphar/arrow/chunk_writer.h
index 76066f28..fa05cece 100644
--- a/cpp/src/graphar/arrow/chunk_writer.h
+++ b/cpp/src/graphar/arrow/chunk_writer.h
@@ -77,7 +77,7 @@ class VertexPropertyWriter {
*
* @param validate_level The validate level to set.
*/
- inline void SetValidateLevel(const ValidateLevel& validate_level) {
+ void SetValidateLevel(const ValidateLevel& validate_level) {
if (validate_level == ValidateLevel::default_validate) {
return;
}
@@ -89,7 +89,7 @@ class VertexPropertyWriter {
*
* @return The validate level of this writer.
*/
- inline ValidateLevel GetValidateLevel() const { return validate_level_; }
+ ValidateLevel GetValidateLevel() const { return validate_level_; }
/**
* @brief Write the number of vertices into the file.
@@ -354,7 +354,7 @@ class EdgeChunkWriter {
*
* @return The validate level of this writer.
*/
- inline ValidateLevel GetValidateLevel() const { return validate_level_; }
+ ValidateLevel GetValidateLevel() const { return validate_level_; }
/**
* @brief Write the number of edges into the file.
diff --git a/cpp/src/graphar/expression.h b/cpp/src/graphar/expression.h
index 3b784a13..a578dc3a 100644
--- a/cpp/src/graphar/expression.h
+++ b/cpp/src/graphar/expression.h
@@ -138,8 +138,8 @@ class ExpressionBinaryOp : public Expression {
~ExpressionBinaryOp() = default;
protected:
- inline Status CheckNullArgs(std::shared_ptr<Expression> lhs,
- std::shared_ptr<Expression> rhs) noexcept {
+ Status CheckNullArgs(std::shared_ptr<Expression> lhs,
+ std::shared_ptr<Expression> rhs) noexcept {
if (lhs == nullptr || rhs == nullptr) {
return Status::Invalid("Invalid expression: lhs or rhs is null");
}
diff --git a/cpp/src/graphar/graph_info.h b/cpp/src/graphar/graph_info.h
index 54d5870d..32c3de2d 100644
--- a/cpp/src/graphar/graph_info.h
+++ b/cpp/src/graphar/graph_info.h
@@ -89,13 +89,13 @@ class PropertyGroup {
*
* @return The file type of group.
*/
- inline FileType GetFileType() const { return file_type_; }
+ FileType GetFileType() const { return file_type_; }
/** Get the prefix of property group chunk file.
*
* @return The path prefix of group.
*/
- inline const std::string& GetPrefix() const { return prefix_; }
+ const std::string& GetPrefix() const { return prefix_; }
/**
* Check if the property group is validated.
@@ -143,21 +143,21 @@ class AdjacentList {
*
* @return The type of adjacent list
*/
- inline AdjListType GetType() const { return type_; }
+ AdjListType GetType() const { return type_; }
/**
* @brief Get the file type of adjacent list
*
* @return The file type of adjacent list
*/
- inline FileType GetFileType() const { return file_type_; }
+ FileType GetFileType() const { return file_type_; }
/**
* @brief Get the prefix of adjacent list
*
* @return The path prefix of adjacent list
*/
- inline const std::string& GetPrefix() const { return prefix_; }
+ const std::string& GetPrefix() const { return prefix_; }
/**
* Returns whether the adjacent list is validated.
diff --git a/cpp/src/graphar/high-level/edges_builder.h
b/cpp/src/graphar/high-level/edges_builder.h
index 93f6af0e..ce847f4e 100644
--- a/cpp/src/graphar/high-level/edges_builder.h
+++ b/cpp/src/graphar/high-level/edges_builder.h
@@ -58,21 +58,21 @@ class Edge {
*
* @return true/false.
*/
- inline bool Empty() const noexcept { return empty_; }
+ bool Empty() const noexcept { return empty_; }
/**
* @brief Get source id of the edge.
*
* @return The id of the source vertex.
*/
- inline IdType GetSource() const noexcept { return src_id_; }
+ IdType GetSource() const noexcept { return src_id_; }
/**
* @brief Get destination id of the edge.
*
* @return The id of the destination vertex.
*/
- inline IdType GetDestination() const noexcept { return dst_id_; }
+ IdType GetDestination() const noexcept { return dst_id_; }
/**
* @brief Add a property to the edge.
@@ -81,7 +81,7 @@ class Edge {
* @param val The value of the property.
*/
// TODO(@acezen): Enable the property to be a vector(list).
- inline void AddProperty(const std::string& name, const std::any& val) {
+ void AddProperty(const std::string& name, const std::any& val) {
empty_ = false;
properties_[name] = val;
}
@@ -92,7 +92,7 @@ class Edge {
* @param property The name of the property.
* @return The value of the property.
*/
- inline const std::any& GetProperty(const std::string& property) const {
+ const std::any& GetProperty(const std::string& property) const {
return properties_.at(property);
}
@@ -101,8 +101,7 @@ class Edge {
*
* @return The map containing all properties of the edge.
*/
- inline const std::unordered_map<std::string, std::any>& GetProperties()
- const {
+ const std::unordered_map<std::string, std::any>& GetProperties() const {
return properties_;
}
@@ -112,7 +111,7 @@ class Edge {
* @param property The name of the property.
* @return true/false.
*/
- inline bool ContainProperty(const std::string& property) const {
+ bool ContainProperty(const std::string& property) const {
return (properties_.find(property) != properties_.end());
}
@@ -207,7 +206,7 @@ class EdgesBuilder {
*
* @param validate_level The validate level to set.
*/
- inline void SetValidateLevel(const ValidateLevel& validate_level) {
+ void SetValidateLevel(const ValidateLevel& validate_level) {
if (validate_level == ValidateLevel::default_validate) {
return;
}
@@ -220,7 +219,7 @@ class EdgesBuilder {
* @return The writerOptions provides configuration options for different
file
* format writers.
*/
- inline void SetWriterOptions(std::shared_ptr<WriterOptions> writer_options) {
+ void SetWriterOptions(std::shared_ptr<WriterOptions> writer_options) {
this->writer_options_ = writer_options;
}
/**
@@ -229,7 +228,7 @@ class EdgesBuilder {
* @param writerOptions The writerOptions provides configuration options for
* different file format writers.
*/
- inline std::shared_ptr<WriterOptions> GetWriterOptions() {
+ std::shared_ptr<WriterOptions> GetWriterOptions() {
return this->writer_options_;
}
@@ -238,12 +237,12 @@ class EdgesBuilder {
*
* @return The validate level of this writer.
*/
- inline ValidateLevel GetValidateLevel() const { return validate_level_; }
+ ValidateLevel GetValidateLevel() const { return validate_level_; }
/**
* @brief Clear the edges in this EdgesBuilder.
*/
- inline void Clear() {
+ void Clear() {
edges_.clear();
num_edges_ = 0;
is_saved_ = false;
diff --git a/cpp/src/graphar/high-level/graph_reader.h
b/cpp/src/graphar/high-level/graph_reader.h
index 88c94d0f..0a0ae102 100644
--- a/cpp/src/graphar/high-level/graph_reader.h
+++ b/cpp/src/graphar/high-level/graph_reader.h
@@ -62,7 +62,7 @@ class Vertex {
*
* @return The id of the vertex.
*/
- inline IdType id() const noexcept { return id_; }
+ IdType id() const noexcept { return id_; }
/**
* @brief Get the property value of the vertex.
@@ -86,7 +86,7 @@ class Vertex {
* @param property The property name.
* @return True if value at the property is valid, False otherwise.
*/
- inline bool IsValid(const std::string& property) const {
+ bool IsValid(const std::string& property) const {
if (properties_.find(property) != properties_.end()) {
return properties_.at(property).has_value();
}
@@ -123,14 +123,14 @@ class Edge {
*
* @return The id of the source vertex.
*/
- inline IdType source() const noexcept { return src_id_; }
+ IdType source() const noexcept { return src_id_; }
/**
* @brief Get destination id of the edge.
*
* @return The id of the destination vertex.
*/
- inline IdType destination() const noexcept { return dst_id_; }
+ IdType destination() const noexcept { return dst_id_; }
/**
* @brief Get the property value of the edge.
@@ -147,7 +147,7 @@ class Edge {
* @param property The property name.
* @return True if value at the property is valid, False otherwise.
*/
- inline bool IsValid(const std::string& property) const {
+ bool IsValid(const std::string& property) const {
if (properties_.find(property) != properties_.end()) {
return properties_.at(property).has_value();
}
diff --git a/cpp/src/graphar/high-level/vertices_builder.h
b/cpp/src/graphar/high-level/vertices_builder.h
index b60ebd11..dc78c002 100644
--- a/cpp/src/graphar/high-level/vertices_builder.h
+++ b/cpp/src/graphar/high-level/vertices_builder.h
@@ -65,21 +65,21 @@ class Vertex {
*
* @return The id of the vertex.
*/
- inline IdType GetId() const noexcept { return id_; }
+ IdType GetId() const noexcept { return id_; }
/**
* @brief Set id of the vertex.
*
* @param id The id of the vertex.
*/
- inline void SetId(IdType id) { id_ = id; }
+ void SetId(IdType id) { id_ = id; }
/**
* @brief Check if the vertex is empty.
*
* @return true/false.
*/
- inline bool Empty() const noexcept { return empty_; }
+ bool Empty() const noexcept { return empty_; }
/**
* @brief Add a property to the vertex.
@@ -88,13 +88,13 @@ class Vertex {
* @param val The value of the property.
*/
// TODO(@acezen): Enable the property to be a vector(list).
- inline void AddProperty(const std::string& name, const std::any& val) {
+ void AddProperty(const std::string& name, const std::any& val) {
empty_ = false;
properties_[name] = val;
}
- inline void AddProperty(const Cardinality cardinality,
- const std::string& name, const std::any& val) {
+ void AddProperty(const Cardinality cardinality, const std::string& name,
+ const std::any& val) {
if (cardinality == Cardinality::SINGLE) {
cardinalities_[name] = Cardinality::SINGLE;
AddProperty(name, val);
@@ -123,7 +123,7 @@ class Vertex {
* @param property The name of the property.
* @return The value of the property.
*/
- inline const std::any& GetProperty(const std::string& property) const {
+ const std::any& GetProperty(const std::string& property) const {
return properties_.at(property);
}
@@ -132,8 +132,7 @@ class Vertex {
*
* @return The map containing all properties of the vertex.
*/
- inline const std::unordered_map<std::string, std::any>& GetProperties()
- const {
+ const std::unordered_map<std::string, std::any>& GetProperties() const {
return properties_;
}
@@ -143,11 +142,11 @@ class Vertex {
* @param property The name of the property.
* @return true/false.
*/
- inline bool ContainProperty(const std::string& property) {
+ bool ContainProperty(const std::string& property) {
return (properties_.find(property) != properties_.end());
}
- inline bool IsMultiProperty(const std::string& property) const {
+ bool IsMultiProperty(const std::string& property) const {
return (cardinalities_.find(property) != cardinalities_.end() &&
cardinalities_.at(property) != Cardinality::SINGLE);
}
@@ -260,7 +259,7 @@ class VerticesBuilder {
/**
* @brief Clear the vertices in this VerciesBuilder.
*/
- inline void Clear() {
+ void Clear() {
vertices_.clear();
num_vertices_ = 0;
is_saved_ = false;
@@ -272,7 +271,7 @@ class VerticesBuilder {
* @return The writerOptions provides configuration options for different
file
* format writers.
*/
- inline void SetWriterOptions(std::shared_ptr<WriterOptions> writer_options) {
+ void SetWriterOptions(std::shared_ptr<WriterOptions> writer_options) {
this->writer_options_ = writer_options;
}
@@ -282,7 +281,7 @@ class VerticesBuilder {
* @param writerOptions The writerOptions provides configuration options for
* different file format writers.
*/
- inline std::shared_ptr<WriterOptions> GetWriterOptions() {
+ std::shared_ptr<WriterOptions> GetWriterOptions() {
return this->writer_options_;
}
@@ -291,7 +290,7 @@ class VerticesBuilder {
*
* @param validate_level The validate level to set.
*/
- inline void SetValidateLevel(const ValidateLevel& validate_level) {
+ void SetValidateLevel(const ValidateLevel& validate_level) {
if (validate_level == ValidateLevel::default_validate) {
return;
}
@@ -303,7 +302,7 @@ class VerticesBuilder {
*
* @return The validate level of this writer.
*/
- inline ValidateLevel GetValidateLevel() const { return validate_level_; }
+ ValidateLevel GetValidateLevel() const { return validate_level_; }
/**
* @brief Add a vertex with the given index.
diff --git a/cpp/src/graphar/result.h b/cpp/src/graphar/result.h
index 3d85c3b4..c1b15ca7 100644
--- a/cpp/src/graphar/result.h
+++ b/cpp/src/graphar/result.h
@@ -107,11 +107,11 @@ namespace graphar::internal {
// Extract Status from Status or Result<T>
// Useful for the status check macros such as RETURN_NOT_OK.
template <typename T>
-inline const Status& GenericToStatus(const Result<T>& res) {
+const Status& GenericToStatus(const Result<T>& res) {
return res.status();
}
template <typename T>
-inline Status GenericToStatus(Result<T>&& res) {
+Status GenericToStatus(Result<T>&& res) {
return std::move(res).status();
}
diff --git a/cpp/src/graphar/status.h b/cpp/src/graphar/status.h
index ae89fde8..1ef388f5 100644
--- a/cpp/src/graphar/status.h
+++ b/cpp/src/graphar/status.h
@@ -147,12 +147,12 @@ class Status {
state_->msg = std::move(msg);
}
/** Copy the specified status. */
- inline Status(const Status& s)
+ Status(const Status& s)
: state_((s.state_ == nullptr) ? nullptr : new State(*s.state_)) {}
/** Move the specified status. */
- inline Status(Status&& s) noexcept : state_(s.state_) { s.state_ = nullptr; }
+ Status(Status&& s) noexcept : state_(s.state_) { s.state_ = nullptr; }
/** Move assignment operator. */
- inline Status& operator=(Status&& s) noexcept {
+ Status& operator=(Status&& s) noexcept {
delete state_;
state_ = s.state_;
s.state_ = nullptr;
@@ -160,7 +160,7 @@ class Status {
}
/** Returns a success status. */
- inline static Status OK() { return {}; }
+ static Status OK() { return {}; }
template <typename... Args>
static Status FromArgs(StatusCode code, Args... args) {
diff --git a/cpp/src/graphar/types.h b/cpp/src/graphar/types.h
index dce7aa94..1a9d8baf 100644
--- a/cpp/src/graphar/types.h
+++ b/cpp/src/graphar/types.h
@@ -97,7 +97,7 @@ class DataType {
child_(std::move(other.child_)),
user_defined_type_name_(std::move(other.user_defined_type_name_)) {}
- inline DataType& operator=(const DataType& other) = default;
+ DataType& operator=(const DataType& other) = default;
bool Equals(const DataType& other) const {
if (id_ != other.id_ ||
@@ -195,7 +195,7 @@ constexpr AdjListType operator&(AdjListType lhs,
AdjListType rhs) {
static_cast<std::underlying_type_t<AdjListType>>(rhs));
}
-static inline const char* AdjListTypeToString(AdjListType adj_list_type) {
+static const char* AdjListTypeToString(AdjListType adj_list_type) {
static const std::map<AdjListType, const char*> adj_list2string{
{AdjListType::unordered_by_source, "unordered_by_source"},
{AdjListType::unordered_by_dest, "unordered_by_dest"},
@@ -204,8 +204,8 @@ static inline const char* AdjListTypeToString(AdjListType
adj_list_type) {
return adj_list2string.at(adj_list_type);
}
-static inline AdjListType OrderedAlignedToAdjListType(
- bool ordered, const std::string& aligned) {
+static AdjListType OrderedAlignedToAdjListType(bool ordered,
+ const std::string& aligned) {
if (ordered) {
return aligned == "src" ? AdjListType::ordered_by_source
: AdjListType::ordered_by_dest;
@@ -214,7 +214,7 @@ static inline AdjListType OrderedAlignedToAdjListType(
: AdjListType::unordered_by_dest;
}
-static inline std::pair<bool, std::string> AdjListTypeToOrderedAligned(
+static std::pair<bool, std::string> AdjListTypeToOrderedAligned(
AdjListType adj_list_type) {
switch (adj_list_type) {
case AdjListType::unordered_by_source:
@@ -230,7 +230,7 @@ static inline std::pair<bool, std::string>
AdjListTypeToOrderedAligned(
}
}
-static inline FileType StringToFileType(const std::string& str) {
+static FileType StringToFileType(const std::string& str) {
static const std::map<std::string, FileType> str2file_type{
{"csv", FileType::CSV},
{"json", FileType::JSON},
@@ -243,7 +243,7 @@ static inline FileType StringToFileType(const std::string&
str) {
}
}
-static inline const char* FileTypeToString(FileType file_type) {
+static const char* FileTypeToString(FileType file_type) {
static const std::map<FileType, const char*> file_type2string{
{FileType::CSV, "csv"},
{FileType::JSON, "json"},
@@ -252,7 +252,7 @@ static inline const char* FileTypeToString(FileType
file_type) {
return file_type2string.at(file_type);
}
-static inline Cardinality StringToCardinality(const std::string& str) {
+static Cardinality StringToCardinality(const std::string& str) {
static const std::map<std::string, Cardinality> str2cardinality{
{"single", Cardinality::SINGLE},
{"list", Cardinality::LIST},
@@ -265,7 +265,7 @@ static inline Cardinality StringToCardinality(const
std::string& str) {
}
}
-static inline const char* CardinalityToString(Cardinality cardinality) {
+static const char* CardinalityToString(Cardinality cardinality) {
static const std::map<Cardinality, const char*> cardinality2string{
{Cardinality::SINGLE, "single"},
{Cardinality::LIST, "list"},
diff --git a/cpp/src/graphar/util.h b/cpp/src/graphar/util.h
index 9bdd1d20..1ef13a3e 100644
--- a/cpp/src/graphar/util.h
+++ b/cpp/src/graphar/util.h
@@ -203,7 +203,7 @@ struct IndexConverter {
std::vector<IdType> edge_chunk_nums_;
};
-static inline IdType IndexPairToGlobalChunkIndex(
+static IdType IndexPairToGlobalChunkIndex(
const std::vector<IdType>& edge_chunk_nums, IdType vertex_chunk_index,
IdType edge_chunk_index) {
IdType global_edge_chunk_index = 0;
@@ -214,7 +214,7 @@ static inline IdType IndexPairToGlobalChunkIndex(
}
// convert edge global chunk index to <vertex_chunk_index, edge_chunk_index>
-static inline std::pair<IdType, IdType> GlobalChunkIndexToIndexPair(
+static std::pair<IdType, IdType> GlobalChunkIndexToIndexPair(
const std::vector<IdType>& edge_chunk_nums, IdType global_index) {
std::pair<IdType, IdType> index_pair(0, 0);
for (size_t i = 0; i < edge_chunk_nums.size(); ++i) {
@@ -238,7 +238,7 @@ std::shared_ptr<arrow::Array> GetArrowArrayByChunkIndex(
Result<const void*> GetArrowArrayData(
std::shared_ptr<arrow::Array> const& array);
-static inline std::string ConcatStringWithDelimiter(
+static std::string ConcatStringWithDelimiter(
const std::vector<std::string>& str_vec, const std::string& delimiter) {
return std::accumulate(
std::begin(str_vec), std::end(str_vec), std::string(),
@@ -249,7 +249,7 @@ static inline std::string ConcatStringWithDelimiter(
template <typename T>
struct ValueGetter {
- inline static T Value(const void* data, int64_t offset) {
+ static T Value(const void* data, int64_t offset) {
return reinterpret_cast<const T*>(data)[offset];
}
};
@@ -259,7 +259,7 @@ struct ValueGetter<std::string> {
static std::string Value(const void* data, int64_t offset);
};
-static inline arrow::Status OpenParquetArrowReader(
+static arrow::Status OpenParquetArrowReader(
const std::string& file_path, arrow::MemoryPool* pool,
std::unique_ptr<parquet::arrow::FileReader>* parquet_reader) {
std::shared_ptr<arrow::io::RandomAccessFile> input;
diff --git a/cpp/src/graphar/version_parser.h b/cpp/src/graphar/version_parser.h
index ae5d5a6f..6b1b041b 100644
--- a/cpp/src/graphar/version_parser.h
+++ b/cpp/src/graphar/version_parser.h
@@ -57,7 +57,7 @@ class InfoVersion {
/** Copy constructor */
InfoVersion(const InfoVersion& other) = default;
/** Copy assignment */
- inline InfoVersion& operator=(const InfoVersion& other) = default;
+ InfoVersion& operator=(const InfoVersion& other) = default;
/** Check if two InfoVersion are equal */
bool operator==(const InfoVersion& other) const {
@@ -87,7 +87,7 @@ class InfoVersion {
}
/** Check if type is supported by version. */
- inline bool CheckType(const std::string& type_str) const {
+ bool CheckType(const std::string& type_str) const {
auto& types = version2types.at(version_);
// check if type_str is in supported types of version
if (std::find(types.begin(), types.end(), type_str) != types.end()) {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]