1 /* GNU Mailutils -- a suite of utilities for electronic mail
2    Copyright (C) 2006-2021 Free Software Foundation, Inc.
3 
4    GNU Mailutils is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3, or (at your option)
7    any later version.
8 
9    GNU Mailutils is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
16 
17 #define MH_FMT_DEFAULT 0
18 #define MH_FMT_RALIGN  0x1000
19 #define MH_FMT_ZEROPAD 0x2000
20 #define MH_FMT_COMPWS  0x4000
21 #define MH_WIDTH_MASK  0x0fff
22 
23 enum mh_opcode
24 {
25   /* Stop. Format: mhop_stop */
26   mhop_stop,
27   /* Unconditional branch
28      Format: mhop_branch offset */
29   mhop_branch,
30   /* Branch if num reg is zero.
31      Format: mhop_brz_num dest-off */
32   mhop_brzn,
33   /* Branch if str reg is zero.
34      Format: mhop_brz_str dest-off */
35   mhop_brzs,
36 
37   /* Set numeric register
38      Format: mhop_setn val */
39   mhop_setn,
40 
41   /* Set string register
42      Format: mhop_sets reg length string */
43   mhop_sets,
44 
45   /* Move value bewtween two numeric registers
46      Format: mhop_movn dest src */
47   mhop_movn,
48 
49   /* Move value bewtween two string registers
50      Format: mhop_movs dest src */
51   mhop_movs,
52 
53   /* Load component value into a string register
54      Format: mhop_load reg string */
55   mhop_ldcomp,
56 
57   /* Load first width bytes of message body contents into a string register.
58      Format: mhop_body reg */
59   mhop_ldbody,
60 
61   /* Call a function.
62      Format: mhop_call function-pointer */
63   mhop_call,
64 
65   /* Convert string register to number reg
66      Format: mhop_atoi
67    */
68   mhop_atoi,
69 
70   /* Convert numeric register to string
71      Format: mhop_itoa */
72   mhop_itoa,
73 
74   /* Print num reg */
75   mhop_printn,
76 
77   /* Print str reg */
78   mhop_prints,
79 
80   /* Print literal
81      Format: mhop_printlit length string */
82   mhop_printlit,
83 
84   /* Set format specification.
85      Format: mhop_fmtspec number */
86   mhop_fmtspec,
87 
88   /* Push numeric register */
89   mhop_pushn,
90   /* Pop numeric register */
91   mhop_popn,
92   /* Exchange top of stack value and numeric register */
93   mhop_xchgn,
94 };
95 
96 enum regid { R_REG, R_ARG, R_ACC };
97 #define MH_NREG 3
98 
99 enum mh_type
100 {
101   mhtype_none,
102   mhtype_num,
103   mhtype_str
104 };
105 
106 typedef enum mh_opcode mh_opcode_t;
107 
108 struct mh_machine;
109 typedef void (*mh_builtin_fp) (struct mh_fvm *);
110 
111 typedef union {
112   mh_opcode_t opcode;
113   mh_builtin_fp builtin;
114   long num;
115   void *ptr;
116   size_t size;
117   char str[1]; /* Any number of characters follows */
118 } mh_instr_t;
119 
120 #define MHI_OPCODE(m) (m).opcode
121 #define MHI_BUILTIN(m) (m).builtin
122 #define MHI_NUM(m) (m).num
123 #define MHI_PTR(m) (m).ptr
124 #define MHI_STR(m) (m).str
125 
126 struct mh_format
127 {
128   size_t progmax;          /* Size of allocated program*/
129   size_t progcnt;          /* Actual number of elements used */
130   mh_instr_t *prog;        /* Program itself */
131   /* The tree and pool members are filled only if mh_format_parse
132      was called with MH_FMT_PARSE_TREE flag */
133   struct node *tree;       /* Parse tree */
134   mu_opool_t pool;         /* Literal pool */
135 };
136 
137 #define MHA_DEFAULT       0
138 #define MHA_IGNOREFMT     0x001
139 #define MHA_NOPRINT       0x002
140 #define MHA_PRINT_MASK    0x003
141 
142 #define MHA_OPTARG        0x004
143 #define MHA_OPTARG_NIL    0x008
144 #define MHA_LITERAL       0x010
145 #define MHA_VOID          0x020
146 #define MHA_SPECIAL       0x040
147 #define MHA_ACC           0x080
148 
149 typedef struct mh_builtin mh_builtin_t;
150 
151 struct mh_builtin
152 {
153   char *name;
154   mh_builtin_fp fun;
155   enum mh_type type;
156   enum mh_type argtype;
157   int flags;
158 };
159 
160 struct mh_string
161 {
162   size_t size;
163   char *ptr;
164 };
165 
166 struct mh_fvm
167 {
168   long num[MH_NREG];              /* numeric registers */
169   struct mh_string str[MH_NREG];  /* string registers */
170 
171   long *numstack;           /* Stack of numeric value */
172   size_t maxstack;          /* Stack capacity */
173   size_t tos;               /* Top of stack (next free slot) */
174 
175   size_t pc;                /* Program counter */
176   size_t progcnt;           /* Size of allocated program*/
177   mh_instr_t *prog;         /* Program itself */
178   int stop;                 /* Stop execution immediately */
179 
180   size_t width;             /* Output line width */
181   size_t ind;               /* Output line index */
182   mu_stream_t output;       /* Output stream */
183   int flags;
184 
185   mu_list_t addrlist;       /* The list of email addresses output this far */
186   int fmtflags;             /* Current formatting flags */
187 
188   mu_message_t message;     /* Current message */
189 };
190 
191 mh_builtin_t *mh_lookup_builtin (char *name, size_t len);
192 void mh_print_fmtspec (int fmtspec);
193 
194