epsilon-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Request to abstract write operations to stdout and stderr in jitter


From: Mohammad-Reza Nabipoor
Subject: Request to abstract write operations to stdout and stderr in jitter
Date: Sun, 8 Nov 2020 21:03:38 +0330

Hi, Luca.

As you know, poke provides a `libpoke` library that can be used in other
programs (like GUI, or head-less daemons).

But there's huge problem for those programs:
    Jitter writes stuff directly to the `stdout` and `stderr`.

So the user of `libpoke` doesn't access to all data (those generated by jitter).
Consider the following C program (`pk-dis.c`); it has a `BUF` struct to
capture the disassembly of `plus1` function. But it only contains the
operands of the instructions, not the full disassembly.
Please look at the line that contains the word `bufstrcmp` below.

I've installed the `poke` using `make install DESTDIR=/tmp`. And I'm using the
`libpoke.a` static library.
I think you should change the `RTPATH` macro at line 3.


```
// gcc -o pk-dis pk-dis.c -I/tmp/usr/include /tmp/usr/lib/libpoke.a -lgc

#define RTPATH "/tmp/usr/share/poke"

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

#include <err.h>

#include <libpoke.h>

struct buf
{
  char *begin;
  char *end;
  char *cur; // cursor
};
static void bufinit (struct buf *b, char *mem, size_t msz);
static int bufempty (struct buf *b);
static void bufappendv (struct buf *b, const char *fmt, va_list ap);
static void bufappend (struct buf *b, const char *fmt, ...);
static int bufstrcmp (struct buf *b, const char *str);

static struct buf BUF;

static void
tif_flush (void)
{
}

static void
tif_puts (const char *s)
{
  bufappend (&BUF, "%s", s);
}

static void
tif_printf (const char *fmt, ...)
{
  va_list ap;

  va_start (ap, fmt);
  bufappendv (&BUF, fmt, ap);
  va_end (ap);
}

static void
tif_indent (unsigned int lvl, unsigned int chr)
{
  char *L;

  L = alloca (lvl + 1);
  memset (L, chr, lvl);
  L[lvl] = '\0';

  bufappend (&BUF, "%s", L);
}

static void
tif_class (const char *cls)
{
}

static void
tif_class_end (const char *cls)
{
}

static void
tif_hlink (const char *url, const char *id)
{
  bufappend (&BUF, "%s", url);
}

static void
tif_hlink_end (void)
{
}

int
main ()
{
  struct pk_term_if term = {
    .flush_fn = tif_flush,
    .puts_fn = tif_puts,
    .printf_fn = tif_printf,
    .indent_fn = tif_indent,
    .class_fn = tif_class,
    .end_class_fn = tif_class_end,
    .hyperlink_fn = tif_hlink,
    .end_hyperlink_fn = tif_hlink_end,
  };
  pk_compiler pkc;
  int ok;

  // init buffer
  {
    enum
    {
      BSZ = 1024, // 1 KiB
    };
    char *mem;

    if ((mem = malloc (BSZ)) == NULL)
      err (1, "malloc() failed");
    bufinit (&BUF, mem, BSZ);
  }

  if ((pkc = pk_compiler_new (RTPATH, &term)) == NULL)
    errx (1, "pk_compiler_new() failed");

  {
    const char *prg = "fun plus1 = (int x) int: {return x + 1;}";

    ok = pk_compile_buffer (pkc, prg, NULL);
    assert (ok != 0);
  }

  assert (bufempty (&BUF));
  pk_disassemble_function (pkc, "plus1", 0);
  assert (!bufempty (&BUF));
  assert (bufstrcmp (&BUF, "\"plus1\"100x1111Exception {code=0x3,msg=\"no "
                           "return\",exit_status=0x1}1")
          == 0);

  pk_compiler_free (pkc);
  free (BUF.begin);
  return 0;
}

static void
bufinit (struct buf *b, char *mem, size_t msz)
{
  assert (b != NULL);
  assert (mem != NULL);

  b->begin = mem;
  b->end = b->begin + msz;
  b->cur = b->begin;
}

static int
bufempty (struct buf *b)
{
  assert (b != NULL);

  return b->cur == b->begin;
}

static void
bufappendv (struct buf *b, const char *fmt, va_list ap)
{
  assert (b != NULL);

  int n;

  if (!(b->cur < b->end))
    errx (1, "memory full");

  n = vsnprintf (b->cur, b->end - b->cur, fmt, ap);
  if (n < 0)
    errx (1, "vsnprintf() failed");

  b->cur += n;
}

static void
bufappend (struct buf *b, const char *fmt, ...)
{
  assert (b != NULL);
  assert (fmt != NULL);

  va_list ap;

  va_start (ap, fmt);
  bufappendv (b, fmt, ap);
  va_end (ap);
}

static int
bufstrcmp (struct buf *b, const char *str)
{
  assert (b != NULL);

  return strncmp (b->begin, str, b->cur - b->begin);
}
```

The output of `./pk-dis` is:

```
        note
$L1:
        prolog
        pushf
        regvar
        pushf
        pushvar 0x1, 0x0
        push
        addi
        nip2
        popf
        popf
        return
        popf
        push
        raise
        popf
        return
        exitvm
```

So, do you have any solution for this?
It'd be nice if you abstract these operations using macros or functions.


Thanks,
Mohammad-Reza


reply via email to

[Prev in Thread] Current Thread [Next in Thread]