summaryrefslogtreecommitdiff
path: root/src/escpos/stack.rl
blob: a051318d383813b4bc833ff213bbc577612a3015 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include "stack.h"
#include <stdlib.h>
#include <assert.h>
#include <err.h>

void
varbuf_begin(struct varbuf *var)
{
   assert(var);
   var->offset = var->buf.written;
   assert(var->offset <= var->buf.mem.len);
}

void
varbuf_reset(struct varbuf *var)
{
   assert(var);
   var->offset = var->buf.written = 0;
}

void
varbuf_remove_last(struct varbuf *var)
{
   assert(var);
   assert(var->buf.written >= var->offset);
   const size_t size = var->buf.written - var->offset;
   assert(var->buf.written >= size);
   var->buf.written -= size;
   assert(var->buf.written <= var->buf.mem.len);
}

static void
stack_check_type(const struct stack *stack, const enum stack_type type)
{
   assert(stack);

   if (stack->type == type)
      return;

   const char *got = (type == STACK_STR ? "str" : "num"), *expected = (stack->type == STACK_STR ? "str" : "num");
   errx(EXIT_FAILURE, "tried to get '%s' from stack, but the last pushed type was '%s'", got, expected);
}

const struct escpos_mem*
stack_get_str(const struct stack *stack)
{
   stack_check_type(stack, STACK_STR);
   return &stack->str;
}

uint8_t
stack_get_num(const struct stack *stack)
{
   stack_check_type(stack, STACK_NUM);
   return stack->num;
}

%%{
   machine escpos_stack;

   action stack_num {
      const char *byte = (char*)stack.var.buf.mem.data + stack.var.offset;
      stack.type = STACK_NUM;
      stack.num = *byte;
      varbuf_remove_last(&stack.var);
   }

   action stack_str {
      membuf_terminate(&stack.var.buf, (char[]){ 0 }, 1);
      stack.type = STACK_STR;
      stack.str = stack.var.buf.mem;
      stack.str.len = stack.var.buf.written;
   }

   action store {
      membuf_append(&stack.var.buf, fpc1);
   }

   action begin_num {
      varbuf_begin(&stack.var);
   }

   action begin_str {
      varbuf_reset(&stack.var);
   }

   NUL = 0x00;
   TEXT = 32..127;

   stack_num = -128..127 >begin_num $store %stack_num;
   stack_str = TEXT* $store >begin_str :>> NUL %stack_str;
}%%