aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2012-09-25 17:31:24 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2012-09-25 17:45:23 +0300
commit455e12faaf5efd997ff74ad04c0fcc62608477a5 (patch)
tree46d24aba487fb2ea76078ef4da60357ff0a340e4
parent2f5d961c798802f1e467de1cd310f661e0a45fa7 (diff)
downloadeclat-455e12faaf5efd997ff74ad04c0fcc62608477a5.tar.gz
eclat-455e12faaf5efd997ff74ad04c0fcc62608477a5.tar.bz2
Use forlan to format the output.
* lib/forlan.h (forlan_lex_begin): Remove (forlan_lex_from_buffer) (forlan_lex_from_file): New protos. (forlan_parse): Remove. (forlan_parse_bufferm,forlan_parse_file): New protos. * lib/forlangrm.y (forlan_parse): Remove. (forlan_parse_bufferm,forlan_parse_file): New functions. * lib/forlanlex.l (YY_INPUT): Optionally, read input from file. (forlan_lex_begin): Remove (forlan_lex_from_buffer) (forlan_lex_from_file): New functions. * src/cmdline.opt: New options: --format, --sort * src/config.c: New statement: format. * src/eclat.c: Use output format scripts, if provided. * src/eclat.conf: Define output format for DescribeTags. * src/eclat.h: Include forlan.h (define_format): New proto. * tests/tforlan.c: New option: -s
-rw-r--r--lib/forlan.h11
-rw-r--r--lib/forlangrm.y24
-rw-r--r--lib/forlanlex.l34
-rw-r--r--src/cmdline.opt12
-rw-r--r--src/config.c32
-rw-r--r--src/eclat.c123
-rw-r--r--src/eclat.conf17
-rw-r--r--src/eclat.h3
-rw-r--r--tests/tforlan.c49
9 files changed, 264 insertions, 41 deletions
diff --git a/lib/forlan.h b/lib/forlan.h
index b789d7e..300ef57 100644
--- a/lib/forlan.h
+++ b/lib/forlan.h
@@ -23,11 +23,14 @@ typedef struct forlan_eval_env *forlan_eval_env_t;
extern int forlan_dbg;
void forlan_init();
-void forlan_lex_begin(const char *input, size_t length,
- struct grecs_locus_point *pt);
+void forlan_lex_from_buffer(const char *input, size_t length,
+ struct grecs_locus_point *pt);
+void forlan_lex_from_file(FILE *fp, struct grecs_locus_point *pt);
+
void forlan_lex_end(void);
-forlan_eval_env_t forlan_parse(const char *input, size_t length,
- struct grecs_locus_point *pt);
+forlan_eval_env_t forlan_parse_buffer(const char *input, size_t length,
+ struct grecs_locus_point *pt);
+forlan_eval_env_t forlan_parse_file(FILE *fp, struct grecs_locus_point *pt);
union forlan_node; /* Declared below */
diff --git a/lib/forlangrm.y b/lib/forlangrm.y
index e8e3436..6261c5e 100644
--- a/lib/forlangrm.y
+++ b/lib/forlangrm.y
@@ -385,12 +385,32 @@ forlan_parser()
}
forlan_eval_env_t
-forlan_parse(const char *input, size_t length, struct grecs_locus_point *pt)
+forlan_parse_buffer(const char *input, size_t length,
+ struct grecs_locus_point *pt)
{
int rc;
forlan_eval_env_t env = NULL;
- forlan_lex_begin(input, length, pt);
+ forlan_lex_from_buffer(input, length, pt);
+ rc = forlan_parser();
+ forlan_lex_end();
+ grecs_symtab_free(forlan_symtab);
+ forlan_symtab = NULL;
+
+ if (rc == 0)
+ env = forlan_create_environment(forlan_parse_tree,
+ forlan_variable_count);
+
+ return env;
+}
+
+forlan_eval_env_t
+forlan_parse_file(FILE *fp, struct grecs_locus_point *pt)
+{
+ int rc;
+ forlan_eval_env_t env = NULL;
+
+ forlan_lex_from_file(fp, pt);
rc = forlan_parser();
forlan_lex_end();
grecs_symtab_free(forlan_symtab);
diff --git a/lib/forlanlex.l b/lib/forlanlex.l
index e3f9f26..c3797dd 100644
--- a/lib/forlanlex.l
+++ b/lib/forlanlex.l
@@ -16,6 +16,7 @@
along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
#include "libeclat.h"
+#include <sysexits.h>
#include <grecs.h>
#include <grecs-locus.h>
#include "forlangrm.h"
@@ -28,14 +29,17 @@ static size_t forlan_input_pos;
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) \
do { \
- size_t __s = forlan_input_len - forlan_input_pos; \
- if (__s > max_size) \
- __s = max_size; \
- if (__s > 0) { \
- memcpy(buf, forlan_input_base, __s); \
- forlan_input_pos += __s; \
- } \
- result = __s; \
+ if (forlan_input_base) { \
+ size_t __s = forlan_input_len - forlan_input_pos; \
+ if (__s > max_size) \
+ __s = max_size; \
+ if (__s > 0) { \
+ memcpy(buf, forlan_input_base, __s); \
+ forlan_input_pos += __s; \
+ } \
+ result = __s; \
+ } else \
+ result = fread(buf, 1, max_size, yyin); \
} while(0)
#define YY_USER_ACTION do { \
@@ -120,8 +124,8 @@ yywrap()
}
void
-forlan_lex_begin(const char *input, size_t length,
- struct grecs_locus_point *pt)
+forlan_lex_from_buffer(const char *input, size_t length,
+ struct grecs_locus_point *pt)
{
forlan_input_base = input;
forlan_input_len = length;
@@ -131,6 +135,16 @@ forlan_lex_begin(const char *input, size_t length,
}
void
+forlan_lex_from_file(FILE *fp, struct grecs_locus_point *pt)
+{
+ yyin = fp;
+ forlan_input_base = NULL;
+ grecs_current_locus_point = *pt;
+ yy_flex_debug = debug_level(forlan_dbg) >= FORLAN_DBG_LEX;
+ grecs_line_acc_create();
+}
+
+void
forlan_lex_end()
{
grecs_line_acc_free();
diff --git a/src/cmdline.opt b/src/cmdline.opt
index 1f8d56d..a17f2b8 100644
--- a/src/cmdline.opt
+++ b/src/cmdline.opt
@@ -127,6 +127,18 @@ BEGIN
use_ssl = 1;
END
+OPTION(format,F,FILE,
+ [<use FILE to format the output>])
+BEGIN
+ format_file = optarg;
+END
+
+OPTION(sort,s,,
+ [<sort the returned XML teee prior to outputting it>])
+BEGIN
+ sort_option = 1;
+END
+
GROUP(Preprocessor control)
OPTION(include-directory,I,DIR,
diff --git a/src/config.c b/src/config.c
index b718486..82033d3 100644
--- a/src/config.c
+++ b/src/config.c
@@ -96,6 +96,34 @@ cb_region(enum grecs_callback_command cmd,
return 0;
}
+static int
+cb_format(enum grecs_callback_command cmd,
+ grecs_locus_t *locus,
+ void *varptr,
+ grecs_value_t *value,
+ void *cb_data)
+{
+ struct ec2_param *p, key;
+ int install = 1;
+
+ if (cmd != grecs_callback_set_value) {
+ grecs_error(locus, 0, "Unexpected block statement");
+ return 1;
+ }
+ if (!value || value->type != GRECS_TYPE_ARRAY || value->v.arg.c != 2) {
+ grecs_error(locus, 0, "expected two strings");
+ return 1;
+ }
+ if (value->v.arg.v[0]->type != GRECS_TYPE_STRING ||
+ value->v.arg.v[1]->type != GRECS_TYPE_STRING) {
+ grecs_error(locus, 0, "expected two strings");
+ return 1;
+ }
+ define_format(value->v.arg.v[0]->v.string,
+ value->v.arg.v[1]->v.string,
+ &value->v.arg.v[1]->locus);
+}
+
static struct grecs_keyword eclat_kw[] = {
{ "default-endpoint", "hostname",
"Set default EC2 endpoint",
@@ -109,7 +137,9 @@ static struct grecs_keyword eclat_kw[] = {
{ "default-region", "name",
"Define default AWS region",
grecs_type_string, GRECS_DFLT, &region_name },
-
+ { "format", "<command: string> <format: string>",
+ "Set default format for the <command>",
+ grecs_type_string, GRECS_MULT, NULL, 0, cb_format },
{ NULL }
};
diff --git a/src/eclat.c b/src/eclat.c
index 86b4627..a26ef7d 100644
--- a/src/eclat.c
+++ b/src/eclat.c
@@ -26,6 +26,8 @@ int use_ssl;
char *access_key;
char *secret_key;
char *region_name;
+char *format_file;
+int sort_option;
enum eclat_command eclat_command;
@@ -179,15 +181,105 @@ write_callback(void *ptr, size_t size, size_t nmemb, void *data)
return realsize;
}
+static int
+node_ident_cmp(struct grecs_node const *a, struct grecs_node const *b)
+{
+ return strcmp(a->ident, b->ident);
+}
+
#include "cmdline.h"
-eclat_command_handler_t handler_tab[] = {
- NULL,
- eclat_start_instance,
- eclat_stop_instance,
- eclat_describe_tags
+struct command {
+ const char *name;
+ eclat_command_handler_t handler;
+ char *fmt;
+ struct grecs_locus locus;
+};
+
+struct command command_tab[] = {
+ { NULL, NULL },
+ { "StartInstances", eclat_start_instance },
+ { "StopInstances", eclat_stop_instance },
+ { "DescribeTags", eclat_describe_tags }
};
+
+struct command *
+find_command(const char *name)
+{
+ struct command *cp;
+
+ for (cp = command_tab + 1;
+ cp < command_tab + sizeof(command_tab)/sizeof(command_tab[0]);
+ cp++) {
+ if (strcmp(cp->name, name) == 0)
+ return cp;
+ }
+ return NULL;
+}
+
+void
+define_format(const char *name, const char *format, grecs_locus_t *locus)
+{
+ struct command *cp = find_command(name);
+
+ if (!cp) {
+ grecs_error(locus, 0, "unknown command");
+ return;
+ }
+
+ if (cp->fmt) {
+ grecs_error(locus, 0, "format %s redefined", name);
+ grecs_error(&cp->locus, 0, "this is the location of "
+ "the previous definition");
+ free(cp->fmt);
+ }
+
+ cp->fmt = grecs_strdup(format);
+ cp->locus = *locus;
+}
+forlan_eval_env_t
+compile_format_file(const char *fmtfile)
+{
+ forlan_eval_env_t env;
+ FILE *fp;
+ struct grecs_locus_point pt;
+
+ fp = fopen(fmtfile, "r");
+ if (!fp)
+ die(EX_UNAVAILABLE, "cannot open format file \"%s\": %s",
+ fmtfile, strerror(errno));
+
+ pt.file = fmtfile;
+ pt.line = 1;
+ pt.col = 0;
+
+ env = forlan_parse_file(fp, &pt);
+ fclose(fp);
+ if (!env)
+ exit(EX_UNAVAILABLE);
+
+ return env;
+}
+
+forlan_eval_env_t
+compile_default_format()
+{
+ forlan_eval_env_t env;
+
+ if (!command_tab[eclat_command].fmt)
+ return;
+ env = forlan_parse_buffer(command_tab[eclat_command].fmt,
+ strlen(command_tab[eclat_command].fmt),
+ &command_tab[eclat_command].locus.beg);
+ if (!env)
+ exit(EX_UNAVAILABLE);
+
+ return env;
+}
+
+
+
int
main(int argc, char **argv)
{
@@ -197,9 +289,11 @@ main(int argc, char **argv)
XML_Parser parser;
eclat_partial_tree_t part;
struct grecs_node *xmltree;
+ forlan_eval_env_t env = NULL;
set_program_name(argv[0]);
debug_init();
+ forlan_init();
config_init();
parse_options(argc, argv, &index);
@@ -230,6 +324,12 @@ main(int argc, char **argv)
} else
die(EX_OSFILE, "cannot access \"%s\": %s",
conffile, strerror(errno));
+
+ if (format_file)
+ env = compile_format_file(format_file);
+ else
+ env = compile_default_format();
+
if (lint_mode)
exit(0);
@@ -261,7 +361,6 @@ main(int argc, char **argv)
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION,
eclat_trace_fun);
}
-
/* Create XML parser */
parser = XML_ParserCreate("UTF-8");
@@ -279,15 +378,21 @@ main(int argc, char **argv)
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, parser);
- rc = handler_tab[eclat_command](curl, argc, argv);
+ rc = command_tab[eclat_command].handler(curl, argc, argv);
curl_easy_cleanup(curl);
XML_Parse(parser, "", 0, 1);
xmltree = eclat_partial_tree_finish(part);
- grecs_print_node(xmltree, GRECS_NODE_FLAG_DEFAULT, stdout);
- fputc('\n', stdout);
+ if (sort_option)
+ grecs_tree_sort(xmltree, node_ident_cmp);
+ if (env) {
+ forlan_run(env, xmltree);
+ } else {
+ grecs_print_node(xmltree, GRECS_NODE_FLAG_DEFAULT, stdout);
+ fputc('\n', stdout);
+ }
exit(rc);
}
diff --git a/src/eclat.conf b/src/eclat.conf
index 1562d52..ef212e7 100644
--- a/src/eclat.conf
+++ b/src/eclat.conf
@@ -25,3 +25,20 @@ region ap-southeast-1 ec2.ap-southeast-1.amazonaws.com;
region ap-northeast-1 ec2.ap-northeast-1.amazonaws.com;
# South America (Sao Paulo) Region
region sa-east-1 ec2.sa-east-1.amazonaws.com;
+
+format "DescribeTags" <<\EOT
+if (.DescribeTagsResponse) {
+ for (var in .DescribeTagsResponse.tagSet.item) {
+ print(var.resourceId,"\t",
+ var.resourceType,"\t",
+ var.key,"\t",
+ var.value,"\n");
+ }
+} else if (.Response.Errors)
+ error("Error: ",.Response.Errors.Error.Message,"\n");
+else {
+ error("Unrecognized response:\n");
+ dump(.);
+}
+EOT;
+
diff --git a/src/eclat.h b/src/eclat.h
index e588b57..9b909c4 100644
--- a/src/eclat.h
+++ b/src/eclat.h
@@ -27,6 +27,7 @@
#include "grecs.h"
#include "wordsplit.h"
#include "libeclat.h"
+#include "forlan.h"
#define ECLAT_DEBCAT_MAIN 0
#define ECLAT_DEBCAT_CFGRAM 1
@@ -68,3 +69,5 @@ int eclat_stop_instance(CURL *curl, int argc, char **argv);
int eclat_describe_tags(CURL *curl, int argc, char **argv);
char *region_to_endpoint(const char *region);
+
+void define_format(const char *name, const char *format, grecs_locus_t *locus);
diff --git a/tests/tforlan.c b/tests/tforlan.c
index 8969c6d..403438e 100644
--- a/tests/tforlan.c
+++ b/tests/tforlan.c
@@ -31,7 +31,13 @@
void
usage()
{
- printf("usage: %s [-dD] FILE [INPUT]\n");
+ printf("usage: %s [OPTIONS] FILE [INPUT]\n", program_name);
+ printf("OPTIONS are:\n");
+ printf(" -D dump parse tree\n");
+ printf(" -d LEVEL set debug level\n");
+ printf(" -f use file interface\n");
+ printf(" -s sort XML tree\n");
+ printf(" -h produce this help list\n");
}
struct grecs_node *
@@ -75,6 +81,10 @@ node_ident_cmp(struct grecs_node const *a, struct grecs_node const *b)
return strcmp(a->ident, b->ident);
}
+#define OPT_DUMP 0x01
+#define OPT_SORT 0x02
+#define OPT_FILE 0x04
+
int
main(int argc, char **argv)
{
@@ -84,17 +94,16 @@ main(int argc, char **argv)
struct stat st;
struct grecs_locus_point pt;
int rc;
- int dump_option = 0;
- int sort_option = 0;
+ int options = 0;
forlan_eval_env_t env;
set_program_name(argv[0]);
forlan_init();
- while ((rc = getopt(argc, argv, "Dd:hs")) != EOF)
+ while ((rc = getopt(argc, argv, "Dd:fhs")) != EOF)
switch (rc) {
case 'D':
- dump_option++;
+ options |= OPT_DUMP;
break;
case 'd':
@@ -102,12 +111,16 @@ main(int argc, char **argv)
die(EX_USAGE, "bad debug category or level");
break;
+ case 'f':
+ options |= OPT_FILE;
+ break;
+
case 'h':
usage();
return 0;
case 's':
- sort_option = 1;
+ options |= OPT_SORT;
break;
default:
@@ -122,25 +135,31 @@ main(int argc, char **argv)
if (stat(argv[0], &st))
die(EX_UNAVAILABLE, "cannot stat input file \"%s\": %s",
argv[0], strerror(errno));
- len = st.st_size;
- buf = grecs_malloc(len);
+
fp = fopen(argv[0], "r");
if (!fp)
die(EX_UNAVAILABLE, "cannot open input file \"%s\": %s",
argv[0], strerror(errno));
- if (fread(buf, len, 1, fp) != 1)
- die(EX_UNAVAILABLE, "error reading from \"%s\": %s",
- argv[0], strerror(errno));
- fclose(fp);
pt.file = argv[0];
pt.line = 1;
pt.col = 0;
- env = forlan_parse(buf, len, &pt);
+ if (options & OPT_FILE) {
+ env = forlan_parse_file(fp, &pt);
+ } else {
+ len = st.st_size;
+ buf = grecs_malloc(len);
+ if (fread(buf, len, 1, fp) != 1)
+ die(EX_UNAVAILABLE, "error reading from \"%s\": %s",
+ argv[0], strerror(errno));
+ env = forlan_parse_buffer(buf, len, &pt);
+ }
+ fclose(fp);
+
if (!env)
return EX_UNAVAILABLE;
- if (dump_option)
+ if (options & OPT_DUMP)
forlan_dump_tree(stdout, env);
if (argv[1]) {
@@ -154,7 +173,7 @@ main(int argc, char **argv)
tree = parse_xml(fp);
fclose(fp);
- if (sort_option)
+ if (options & OPT_SORT)
grecs_tree_sort(tree, node_ident_cmp);
forlan_run(env, tree);

Return to:

Send suggestions and report system problems to the System administrator.