Skip to content

Commit

Permalink
codegen: gopts integration
Browse files Browse the repository at this point in the history
  • Loading branch information
kodebach committed Mar 29, 2019
1 parent f22f68d commit 46f1bc1
Show file tree
Hide file tree
Showing 16 changed files with 360 additions and 42 deletions.
8 changes: 8 additions & 0 deletions src/error/specification_highlevel
Expand Up @@ -68,3 +68,11 @@ description:The value passed to the ElektraError ** argument of %1$s was NULL.
args:1
type1:const char *
arg1:function

number:7
severity:error
name:ENSURE_FAILED
description:The given contract could not be ensured: %1$s
args:1
type1:const char *
arg1:reason
4 changes: 4 additions & 0 deletions src/include/elektra.h
Expand Up @@ -65,6 +65,8 @@ typedef struct _Elektra Elektra;
Elektra * elektraOpen (const char * application, KeySet * defaults, ElektraError ** error);
void elektraClose (Elektra * elektra);

void elektraEnsure (Elektra * elektra, KeySet * contract, ElektraError ** error);

// endregion Basics

// region Error-Handling
Expand All @@ -89,6 +91,8 @@ Key * elektraFindKey (Elektra * elektra, const char * name, KDBType type);
Key * elektraFindArrayElementKey (Elektra * elektra, const char * name, kdb_long_long_t index, KDBType type);
void elektraFatalError (Elektra * elektra, ElektraError * fatalError);

Key * elektraHelpKey (Elektra * elektra);

// endregion Helpers for code generation

// region Getters
Expand Down
53 changes: 53 additions & 0 deletions src/libs/highlevel/elektra.c
Expand Up @@ -99,6 +99,44 @@ Elektra * elektraOpen (const char * application, KeySet * defaults, ElektraError
return elektra;
}

/**
* Calls kdbEnsure() on the internal KDB handle of this Elektra instance.
*
* @param elektra Elektra instance to use.
* @param contract The contract to ensure.
* @param error Pass a reference to an ElektraError pointer.
* Will only be set in case of an error.
*
* @see kdbEnsure()
*/
void elektraEnsure (Elektra * elektra, KeySet * contract, ElektraError ** error)
{
if (error == NULL)
{
elektraFatalError (elektra, elektraErrorNullError (__func__));
return;
}

Key * parentKey = keyDup (elektra->parentKey);
int rc = kdbEnsure (elektra->kdb, contract, parentKey);
if (rc == 0)
{
// if successful, refresh config
kdbGet (elektra->kdb, elektra->config, elektra->parentKey);
}
else if (rc == 1)
{
const char * reason = keyString (keyGetMeta (parentKey, "error/reason"));
*error = elektraErrorEnsureFailed (reason);
}
else
{
*error = elektraErrorCreateFromKey (parentKey);
}

keyDel (parentKey);
}

/**
* Promote an ElektraError to fatal and call the fatal error handler.
*
Expand All @@ -111,6 +149,21 @@ void elektraFatalError (Elektra * elektra, ElektraError * fatalError)
elektra->fatalErrorHandler (fatalError);
}

/**
* This function is only intended for use with code-generation.
*
* It looks for the key proc/elektra/gopts/help (absolute name) created by gopts,
* and returns it if found.
*
* @param elektra The Elektra instance to check
*
* @return the help key if found, NULL otherwise
*/
Key * elektraHelpKey (Elektra * elektra)
{
return ksLookupByName (elektra->config, "proc/elektra/gopts/help", 0);
}

/**
* Sets the fatal error handler that will be called, whenever a fatal error occurs.
*
Expand Down
4 changes: 4 additions & 0 deletions src/tools/kdb/gen/elektragen.cpp
Expand Up @@ -805,11 +805,15 @@ kainjow::mustache::data ElektraGenTemplate::getTemplateData (const std::string &
// TODO: make configurable?
auto specloadArg = "--elektra-specload";

kdb::KeySet contract;
contract.append (kdb::Key ("system/plugins/global/gopts", KEY_VALUE, "mounted", KEY_END));

data["keys_count"] = std::to_string (keys.size ());
data["keys"] = keys;
data["enums"] = enums;
data["structs"] = structs;
data["defaults"] = keySetToCCode (spec);
data["contract"] = keySetToCCode (contract);
data["specload_arg"] = specloadArg;

return data;
Expand Down
51 changes: 45 additions & 6 deletions src/tools/kdb/gen/templates/elektra.c.mustache
Expand Up @@ -17,13 +17,17 @@
/*%/ more_headers %*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <kdbhelper.h>
#include <kdbinvoke.h>
#include <kdbopts.h>

#include <elektra/conversion.h>

static Key * helpKey = NULL;

/*%={{ }}=%*/
/**
* Initializes an instance of Elektra for the application '{{{ parent_key }}}'.
Expand All @@ -36,11 +40,12 @@
* @param error A reference to an ElektraError pointer. Will be passed to elektraOpen().
*
* @retval 0 on success, @p elektra will be set, @p error will be unchanged
* @retval -1 on error, @p elektra will be unchanged, @p error will set
* @retval -1 on error, @p elektra will be unchanged, @p error will be set
* @retval 1 specload mode, exit as soon as possible and must DO NOT write anything to stdout,
* @p elektra and @p error are both unchanged
* @retval 2 help mode, '-h' or '--help' was specified call {{{ help_function_name }}} and exit
* @p elektra and @p error are both unchanged
* IMPORTANT: there will be memory leaks, if you don't call {{{ help_function_name }}} !!
*
* @see elektraOpen
*/// {{=/*% %*/=}}
Expand All @@ -54,10 +59,21 @@ int /*%& init_function_name %*/ (Elektra ** elektra, ElektraError ** error)
return -1;
}

if (0 /* TODO: check if help mode */)
KeySet * contract = /*%& contract %*/;

ElektraError * err = NULL;
elektraEnsure (e, contract, &err);

if (err != NULL)
{
*error = err;
return -1;
}

helpKey = elektraHelpKey (e);
if (helpKey != NULL)
{
elektraClose (e);
/*%& help_function_name %*/ ();
return 2;
}

Expand Down Expand Up @@ -102,11 +118,34 @@ void /*%& specload_function_name %*/ (int argc, const char ** argv)
}

/**
* Outputs the help message
* Extracts the help message from the @p errorKey used in elektraGetOpts().
*
* @param errorKey The same Key as passed to elektraGetOpts() as errorKey.
* @param usage If this is not NULL, it will be used instead of the default usage line.
* @param prefix If this is not NULL, it will be inserted between the usage line and the options list.
*
* @return The full help message extracted from @p errorKey, or NULL if no help message was found.
* The returned string has to be freed with elektraFree().
*/
void /*%& help_function_name %*/ (void)

/**
* Outputs the help message to stdout
*
* @param usage If this is not NULL, it will be used instead of the default usage line.
* @param prefix If this is not NULL, it will be inserted between the usage line and the options list.
*/
void /*%& help_function_name %*/ (const char * usage, const char * prefix)
{
// TODO
if (helpKey == NULL)
{
return;
}

char * help = elektraGetOptsHelpMessage (helpKey, usage, prefix);
printf ("%s", help);
elektraFree (help);
keyDel (helpKey);
helpKey = NULL;
}

/*%> partial.enum.c %*/
Expand Down
2 changes: 1 addition & 1 deletion src/tools/kdb/gen/templates/elektra.h.mustache
Expand Up @@ -34,7 +34,7 @@ extern "C" {
/*%> partial.keys.fun.h %*/
int /*%& init_function_name %*/ (Elektra ** elektra, ElektraError ** error);
void /*%& help_function_name %*/ (void);
void /*%& help_function_name %*/ (const char * usage, const char * prefix);
void /*%& specload_function_name %*/ (int argc, const char ** argv);
/*%={{ }}=%*/
Expand Down
54 changes: 48 additions & 6 deletions tests/shell/gen/elektra/empty.expected.c
Expand Up @@ -15,13 +15,17 @@


#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <kdbhelper.h>
#include <kdbinvoke.h>
#include <kdbopts.h>

#include <elektra/conversion.h>

static Key * helpKey = NULL;


/**
* Initializes an instance of Elektra for the application 'tests/script/gen/elektra/empty'.
Expand All @@ -34,11 +38,12 @@
* @param error A reference to an ElektraError pointer. Will be passed to elektraOpen().
*
* @retval 0 on success, @p elektra will be set, @p error will be unchanged
* @retval -1 on error, @p elektra will be unchanged, @p error will set
* @retval -1 on error, @p elektra will be unchanged, @p error will be set
* @retval 1 specload mode, exit as soon as possible and must DO NOT write anything to stdout,
* @p elektra and @p error are both unchanged
* @retval 2 help mode, '-h' or '--help' was specified call printHelpMessage and exit
* @p elektra and @p error are both unchanged
* IMPORTANT: there will be memory leaks, if you don't call printHelpMessage !!
*
* @see elektraOpen
*///
Expand All @@ -54,10 +59,24 @@ int loadConfiguration (Elektra ** elektra, ElektraError ** error)
return -1;
}

if (0 /* TODO: check if help mode */)
KeySet * contract = ksNew (1,
keyNew ("system/plugins/global/gopts", KEY_VALUE, "mounted", KEY_END),
KS_END);
;

ElektraError * err = NULL;
elektraEnsure (e, contract, &err);

if (err != NULL)
{
*error = err;
return -1;
}

helpKey = elektraHelpKey (e);
if (helpKey != NULL)
{
elektraClose (e);
printHelpMessage ();
return 2;
}

Expand Down Expand Up @@ -104,11 +123,34 @@ void specloadCheck (int argc, const char ** argv)
}

/**
* Outputs the help message
* Extracts the help message from the @p errorKey used in elektraGetOpts().
*
* @param errorKey The same Key as passed to elektraGetOpts() as errorKey.
* @param usage If this is not NULL, it will be used instead of the default usage line.
* @param prefix If this is not NULL, it will be inserted between the usage line and the options list.
*
* @return The full help message extracted from @p errorKey, or NULL if no help message was found.
* The returned string has to be freed with elektraFree().
*/

/**
* Outputs the help message to stdout
*
* @param usage If this is not NULL, it will be used instead of the default usage line.
* @param prefix If this is not NULL, it will be inserted between the usage line and the options list.
*/
void printHelpMessage (void)
void printHelpMessage (const char * usage, const char * prefix)
{
// TODO
if (helpKey == NULL)
{
return;
}

char * help = elektraGetOptsHelpMessage (helpKey, usage, prefix);
printf ("%s", help);
elektraFree (help);
keyDel (helpKey);
helpKey = NULL;
}

// clang-format off
Expand Down
2 changes: 1 addition & 1 deletion tests/shell/gen/elektra/empty.expected.h
Expand Up @@ -105,7 +105,7 @@ extern "C" {


int loadConfiguration (Elektra ** elektra, ElektraError ** error);
void printHelpMessage (void);
void printHelpMessage (const char * usage, const char * prefix);
void specloadCheck (int argc, const char ** argv);


Expand Down

0 comments on commit 46f1bc1

Please sign in to comment.