#endif
#include "../config.h"
-
int debug = FALSE;
int statistics = FALSE;
};
-void logmsg(char *prefix, FILE *out, const char *format, va_list args)
+static void logmsg(char *prefix, FILE *out, const char *format, va_list args)
{
if (prefix)
fprintf(out, "%s", prefix);
fprintf(out, "\n");
}
-void DBG(const char *format, ...)
+static void DBG(const char *format, ...)
{
va_list args;
va_end(args);
}
-void ERR(const char *format, ...)
+static void ERR(const char *format, ...)
{
va_list args;
va_end(args);
}
-int srd_log(void *cb_data, int loglevel, const char *format, va_list args)
+static int sr_log(void *cb_data, int loglevel, const char *format, va_list args)
+{
+ (void)cb_data;
+
+ if (loglevel == SR_LOG_ERR || loglevel == SR_LOG_WARN)
+ logmsg("Error: sr: ", stderr, format, args);
+ else if (debug)
+ logmsg("DBG: sr: ", stdout, format, args);
+
+ return SRD_OK;
+}
+
+static int srd_log(void *cb_data, int loglevel, const char *format, va_list args)
{
(void)cb_data;
if (loglevel == SRD_LOG_ERR || loglevel == SRD_LOG_WARN)
logmsg("Error: srd: ", stderr, format, args);
- else if (loglevel >= SRD_LOG_DBG && debug)
+ else if (debug)
logmsg("DBG: srd: ", stdout, format, args);
return SRD_OK;
}
-void usage(char *msg)
+static void usage(char *msg)
{
if (msg)
fprintf(stderr, "%s\n", msg);
- //while((c = getopt(argc, argv, "dP:p:o:i:O:f:S")) != -1) {
printf("Usage: runtc [-dPpoiOf]\n");
printf(" -d Debug\n");
printf(" -P <protocol decoder>\n");
}
+/* This is a neutered version of libsigrokdecode's py_str_as_str(). It
+ * does no error checking, but then the only strings it processes are
+ * generated by Python's repr(), so are known good. */
+static char *py_str_as_str(const PyObject *py_str)
+{
+ PyObject *py_encstr;
+ char *str, *outstr;
+
+ py_encstr = PyUnicode_AsEncodedString((PyObject *)py_str, "utf-8", NULL);
+ str = PyBytes_AS_STRING(py_encstr);
+ outstr = g_strdup(str);
+ Py_DecRef(py_encstr);
+
+ return outstr;
+}
+
+static void srd_cb_py(struct srd_proto_data *pdata, void *cb_data)
+{
+ struct output *op;
+ PyObject *pydata, *pyrepr;
+ GString *out;
+ char *s;
+
+ DBG("Python output from %s", pdata->pdo->di->inst_id);
+ op = cb_data;
+ pydata = pdata->data;
+ DBG("ptr %p", pydata);
+
+ if (strcmp(pdata->pdo->di->inst_id, op->pd))
+ /* This is not the PD selected for output. */
+ return;
+
+ if (!(pyrepr = PyObject_Repr(pydata))) {
+ ERR("Invalid Python object.");
+ return;
+ }
+ s = py_str_as_str(pyrepr);
+ Py_DecRef(pyrepr);
+
+ /* Output format for testing is '<ss>-<es> <inst-id>: <repr>\n' */
+ out = g_string_sized_new(128);
+ g_string_printf(out, "%"PRIu64"-%"PRIu64" %s: %s\n",
+ pdata->start_sample, pdata->end_sample,
+ pdata->pdo->di->inst_id, s);
+ g_free(s);
+ if (write(op->outfd, out->str, out->len) == -1)
+ ERR("SRD_OUTPUT_PYTHON callback write failure!");
+ DBG("wrote '%s'", out->str);
+ g_string_free(out, TRUE);
+
+}
+
+static void srd_cb_bin(struct srd_proto_data *pdata, void *cb_data)
+{
+ struct srd_proto_data_binary *pdb;
+ struct output *op;
+ GString *out;
+ unsigned int i;
+
+ DBG("Binary output from %s", pdata->pdo->di->inst_id);
+ op = cb_data;
+ pdb = pdata->data;
+
+ if (strcmp(pdata->pdo->di->inst_id, op->pd))
+ /* This is not the PD selected for output. */
+ return;
+
+ if (op->class_idx != -1 && op->class_idx != pdb->bin_class)
+ /*
+ * This output takes a specific binary class,
+ * but not the one that just came in.
+ */
+ return;
+
+ out = g_string_sized_new(128);
+ g_string_printf(out, "%"PRIu64"-%"PRIu64" %s:",
+ pdata->start_sample, pdata->end_sample,
+ pdata->pdo->di->inst_id);
+ for (i = 0; i < pdb->size; i++) {
+ g_string_append_printf(out, " %.2x", pdb->data[i]);
+ }
+ g_string_append(out, "\n");
+ if (write(op->outfd, out->str, out->len) == -1)
+ ERR("SRD_OUTPUT_BINARY callback write failure!");
+
+}
+
static void srd_cb_ann(struct srd_proto_data *pdata, void *cb_data)
{
struct srd_decoder *dec;
int i;
char **dec_ann;
- DBG("Annotation from %s", pdata->pdo->di->inst_id);
+ DBG("Annotation output from %s", pdata->pdo->di->inst_id);
op = cb_data;
pda = pdata->data;
dec = pdata->pdo->di->decoder;
-
if (strcmp(pdata->pdo->di->inst_id, op->pd))
/* This is not the PD selected for output. */
return;
if (op->class_idx != -1 && op->class_idx != pda->ann_format)
- /* This output takes a specific annotation class,
- * but not the one that just came in. */
+ /*
+ * This output takes a specific annotation class,
+ * but not the one that just came in.
+ */
return;
dec_ann = g_slist_nth_data(dec->annotations, pda->ann_format);
g_string_append_printf(line, " \"%s\"", pda->ann_text[i]);
g_string_append(line, "\n");
if (write(op->outfd, line->str, line->len) == -1)
- ERR("Oops!");
+ ERR("SRD_OUTPUT_ANN callback write failure!");
g_string_free(line, TRUE);
}
}
-int get_stats(int stats[2])
-{
- FILE *f;
- size_t len;
- int tmp;
- char *buf;
-
- stats[0] = stats[1] = -1;
- if (!(f = fopen("/proc/self/status", "r")))
- return FALSE;
- len = 128;
- buf = malloc(len);
- while (getline(&buf, &len, f) != -1) {
- if (strcasestr(buf, "vmpeak:")) {
- stats[0] = strtoul(buf + 10, NULL, 10);
- } else if (strcasestr(buf, "vmsize:")) {
- tmp = strtoul(buf + 10, NULL, 10);
- if (tmp > stats[0])
- stats[0] = tmp;
- } else if (strcasestr(buf, "vmhwm:")) {
- stats[1] = strtoul(buf + 6, NULL, 10);
- } else if (strcasestr(buf, "vmrss:")) {
- tmp = strtoul(buf + 10, NULL, 10);
- if (tmp > stats[0])
- stats[0] = tmp;
- }
- }
- free(buf);
- fclose(f);
-
- return TRUE;
-}
-
static int run_testcase(char *infile, GSList *pdlist, struct output *op)
{
struct srd_session *sess;
struct srd_decoder *dec;
struct srd_decoder_inst *di, *prev_di;
+ srd_pd_output_callback_t cb;
struct pd *pd;
struct probe *probe;
struct option *option;
GVariant *gvar;
GHashTable *probes, *opts;
- GSList *pdl, *l, *annl;
+ GSList *pdl, *l;
int idx;
- char **dec_ann;
+ char **decoder_class;
if (op->outfile) {
if ((op->outfd = open(op->outfile, O_CREAT|O_WRONLY, 0600)) == -1) {
if (srd_session_new(&sess) != SRD_OK)
return FALSE;
sr_session_datafeed_callback_add(sr_cb, sess);
- srd_pd_output_callback_add(sess, SRD_OUTPUT_ANN, srd_cb_ann, op);
+ switch (op->type) {
+ case SRD_OUTPUT_ANN:
+ cb = srd_cb_ann;
+ break;
+ case SRD_OUTPUT_BINARY:
+ cb = srd_cb_bin;
+ break;
+ case SRD_OUTPUT_PYTHON:
+ cb = srd_cb_py;
+ break;
+ default:
+ return FALSE;
+ }
+ srd_pd_output_callback_add(sess, op->type, cb, op);
prev_di = NULL;
pd = NULL;
g_hash_table_destroy(probes);
}
-
/* If this is not the first decoder in the list, stack it
* on top of the previous one. */
if (prev_di) {
dec = srd_decoder_get_by_id(pd->name);
if (op->class) {
if (op->type == SRD_OUTPUT_ANN)
- annl = dec->annotations;
- /* TODO can't dereference this for binary yet
+ l = dec->annotations;
else if (op->type == SRD_OUTPUT_BINARY)
- annl = dec->binary;
- */
+ l = dec->binary;
else
- /* Only annotations and binary for now. */
+ /* Only annotations and binary can have a class. */
return FALSE;
idx = 0;
- while(annl) {
- dec_ann = annl->data;
- /* TODO can't dereference this for binary yet */
- if (!strcmp(dec_ann[0], op->class)) {
+ while (l) {
+ decoder_class = l->data;
+ if (!strcmp(decoder_class[0], op->class)) {
op->class_idx = idx;
break;
} else
idx++;
- annl = annl->next;
+ l = l->next;
}
if (op->class_idx == -1) {
ERR("Output class '%s' not found in decoder %s.",
op->class, pd->name);
return FALSE;
- }
+ } else
+ DBG("Class %s index is %d", op->class, op->class_idx);
}
sr_session_start();
struct probe *probe;
struct option *option;
struct output *op;
+ int ret;
char c, *opt_infile, **kv, **opstr;
op = malloc(sizeof(struct output));
pdlist = NULL;
opt_infile = NULL;
pd = NULL;
- while((c = getopt(argc, argv, "dP:p:o:i:O:f:S")) != -1) {
+ while ((c = getopt(argc, argv, "dP:p:o:i:O:f:S")) != -1) {
switch(c) {
case 'd':
debug = TRUE;
if (!op->pd || op->type == -1)
usage(NULL);
+ sr_log_callback_set(sr_log, NULL);
if (sr_init(&ctx) != SR_OK)
return 1;
srd_log_callback_set(srd_log, NULL);
- if (srd_init(NULL) != SRD_OK)
+ if (srd_init(DECODERS_DIR) != SRD_OK)
return 1;
- run_testcase(opt_infile, pdlist, op);
+ ret = 0;
+ if (!run_testcase(opt_infile, pdlist, op))
+ ret = 1;
srd_exit();
sr_exit(ctx);
- return 0;
+ return ret;
}
-
-