File: cmd.h

package info (click to toggle)
s-nail 14.9.25-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,836 kB
  • sloc: ansic: 75,681; sh: 14,364; cpp: 4,287; perl: 562; makefile: 144; php: 5
file content (210 lines) | stat: -rw-r--r-- 9,327 bytes parent folder | download | duplicates (3)
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/*@ S-nail - a mail user agent derived from Berkeley Mail.
 *@ Actual command table, `help', `list', etc., and the cmd_arg() parser.
 *
 * Copyright (c) 2012 - 2020 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
 * SPDX-License-Identifier: ISC
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#ifndef mx_CMD_H
#define mx_CMD_H

#include <mx/nail.h>

#define mx_HEADER
#include <su/code-in.h>

enum mx_cmd_arg_flags{ /* TODO Most of these need to change, in fact in v15
   * TODO i rather see the mechanism that is used in c_bind() extended and used
   * TODO anywhere, i.e. n_cmd_arg_parse().
   * TODO Note we may NOT support arguments with su_cs_len()>=U32_MAX (?) */
   mx_CMD_ARG_TYPE_MSGLIST = 0, /* Message list type */
   mx_CMD_ARG_TYPE_NDMLIST = 1, /* Message list, no defaults */
   mx_CMD_ARG_TYPE_RAWDAT = 2, /* The plain string in an argv[] */
     mx_CMD_ARG_TYPE_STRING = 3, /* A pure string TODO obsolete */
   mx_CMD_ARG_TYPE_WYSH = 4, /* getrawlist(), sh(1) compatible */
      mx_CMD_ARG_TYPE_RAWLIST = 5, /* getrawlist(), old style TODO obsolete */
     mx_CMD_ARG_TYPE_WYRA = 6, /* _RAWLIST or _WYSH (with `wysh') TODO obs. */
   mx_CMD_ARG_TYPE_ARG = 7, /* n_cmd_arg_desc/n_cmd_arg() new-style */
   mx_CMD_ARG_TYPE_MASK = 7, /* Mask of the above */

   mx_CMD_ARG_A = 1u<<4, /* Needs an active mailbox */
   mx_CMD_ARG_F = 1u<<5, /* Is a conditional command */
   mx_CMD_ARG_G = 1u<<6, /* Is supposed to produce "gabby" history */
   mx_CMD_ARG_H = 1u<<7, /* Never place in `history' */
   mx_CMD_ARG_I = 1u<<8, /* Interactive command bit */
   mx_CMD_ARG_L = 1u<<9, /* Supports `local' prefix (only WYSH/WYRA) */
   mx_CMD_ARG_M = 1u<<10, /* Legal from send mode bit */
   mx_CMD_ARG_O = 1u<<11, /* n_OBSOLETE()d command */
   mx_CMD_ARG_P = 1u<<12, /* Autoprint dot after command */
   mx_CMD_ARG_R = 1u<<13, /* Forbidden in compose mode recursion */
   mx_CMD_ARG_SC = 1u<<14, /* Forbidden pre-n_PSO_STARTED_CONFIG */
   mx_CMD_ARG_S = 1u<<15, /* Forbidden pre-n_PSO_STARTED (POSIX) */
   mx_CMD_ARG_T = 1u<<16, /* Is a transparent command */
   mx_CMD_ARG_V = 1u<<17, /* Supports `vput' prefix (only WYSH/WYRA) */
   mx_CMD_ARG_W = 1u<<18, /* Invalid when read only bit */
   mx_CMD_ARG_X = 1u<<19, /* Valid command in n_PS_COMPOSE_FORKHOOK mode */
   /* XXX Note that CMD_ARG_EM implies a _real_ return value for $! */
   mx_CMD_ARG_EM = 1u<<30 /* If error: n_pstate_err_no (4 $! aka. ok_v___em) */
};

enum mx_cmd_arg_desc_flags{
   /* - A type */
   mx_CMD_ARG_DESC_SHEXP = 1u<<0, /* sh(1)ell-style token */
   /* TODO All MSGLIST arguments can only be used last and are always greedy
    * TODO (but MUST be _GREEDY, and MUST NOT be _OPTION too!).
    * MSGLIST_AND_TARGET may create a NULL target */
   mx_CMD_ARG_DESC_MSGLIST = 1u<<1,  /* Message specification(s) */
   mx_CMD_ARG_DESC_NDMSGLIST = 1u<<2,
   mx_CMD_ARG_DESC_MSGLIST_AND_TARGET = 1u<<3,

   mx__CMD_ARG_DESC_TYPE_MASK = mx_CMD_ARG_DESC_SHEXP |
         mx_CMD_ARG_DESC_MSGLIST | mx_CMD_ARG_DESC_NDMSGLIST |
         mx_CMD_ARG_DESC_MSGLIST_AND_TARGET,

   /* - Optional flags */
   /* It is not an error if an optional argument is missing; once an argument
    * has been declared optional only optional arguments may follow */
   mx_CMD_ARG_DESC_OPTION = 1u<<16,
   /* GREEDY: parse as many of that type as possible; must be last entry */
   mx_CMD_ARG_DESC_GREEDY = 1u<<17,
   /* If greedy, join all given arguments separated by ASCII SP right away */
   mx_CMD_ARG_DESC_GREEDY_JOIN = 1u<<18,
   /* Honour an overall "stop" request in one of the arguments (\c@ or #) */
   mx_CMD_ARG_DESC_HONOUR_STOP = 1u<<19,
   /* With any MSGLIST, only one message may be give or ERR_NOTSUP (default) */
   mx_CMD_ARG_DESC_MSGLIST_NEEDS_SINGLE = 1u<<20,

   mx__CMD_ARG_DESC_FLAG_MASK = mx_CMD_ARG_DESC_OPTION |
         mx_CMD_ARG_DESC_GREEDY | mx_CMD_ARG_DESC_GREEDY_JOIN |
         mx_CMD_ARG_DESC_HONOUR_STOP |
         mx_CMD_ARG_DESC_MSGLIST_NEEDS_SINGLE,

   /* We may include something for n_pstate_err_no */
   mx_CMD_ARG_DESC_ERRNO_SHIFT = 21u,
   mx_CMD_ARG_DESC_ERRNO_MASK = (1u<<10) - 1
};
#define mx_CMD_ARG_DESC_ERRNO_TO_ORBITS(ENO) \
   (S(u32,ENO) << mx_CMD_ARG_DESC_ERRNO)
#define mx_CMD_ARG_DESC_TO_ERRNO(FLAGCARRIER) \
   ((S(u32,FLAGCARRIER) >> mx_CMD_ARG_DESC_ERRNO_SHIFT) &\
      mx_CMD_ARG_DESC_ERRNO_MASK)

struct mx_cmd_arg_desc{
   char cad_name[12]; /* Name of command */
   u32 cad_no; /* Number of entries in cad_ent_flags */
   /* [enum cmd_arg_desc_flags,arg-dep] */
   u32 cad_ent_flags[VFIELD_SIZE(0)][2];
};

/* ISO C(99) does not allow initialization of "flex array" */
#define mx_CMD_ARG_DESC_SUBCLASS_DEF(CMD,NO,VAR) \
   mx_CMD_ARG_DESC_SUBCLASS_DEF_NAME(CMD, su_STRING(CMD), NO, VAR)
#define mx_CMD_ARG_DESC_SUBCLASS_DEF_NAME(CMD,NAME,NO,VAR) \
   static struct mx_cmd_arg_desc_ ## CMD {\
      char cad_name[12];\
      u32 cad_no;\
      u32 cad_ent_flags[NO][2];\
   } const VAR = { NAME "\0", NO,
#define mx_CMD_ARG_DESC_SUBCLASS_DEF_END }
#define mx_CMD_ARG_DESC_SUBCLASS_CAST(P) su_R(struct mx_cmd_arg_desc const*,P)

struct mx_cmd_arg_ctx{
   struct mx_cmd_arg_desc const *cac_desc; /* Input: description of command */
   char const *cac_indat; /* Input that shall be parsed */
   uz cac_inlen; /* Input length (UZ_MAX: do a su_cs_len()) */
   u32 cac_msgflag; /* Input (option): required flags of messages */
   u32 cac_msgmask; /* Input (option): relevant flags of messages */
   uz cac_no; /* Output: number of parsed arguments */
   struct mx_cmd_arg *cac_arg; /* Output: parsed arguments */
   char const *cac_vput; /* "Output": vput prefix used: varname */
};

struct mx_cmd_arg{
   struct mx_cmd_arg *ca_next;
   char const *ca_indat; /*[PRIV] Pointer into cmd_arg_ctx.cac_indat */
   uz ca_inlen; /*[PRIV] of .ca_indat of this arg (no NUL) */
   u32 ca_ent_flags[2]; /* Copy of cmd_arg_desc.cad_ent_flags[X] */
   u32 ca_arg_flags; /* [Output: _WYSH: copy of parse result flags] */
   u8 ca__dummy[4];
   union{
      struct str ca_str; /* _CMD_ARG_DESC_SHEXP */
      int *ca_msglist; /* _CMD_ARG_DESC_MSGLIST+ */
   } ca_arg; /* Output: parsed result */
};

struct mx_cmd_desc{
   char const *cd_name; /* Name of command */
   int (*cd_func)(void*); /* Implementor of command */
   enum mx_cmd_arg_flags cd_caflags;
   u32 cd_mflags_o_minargs; /* Message flags or min. args WYSH/WYRA/RAWLIST */
   u32 cd_mmask_o_maxargs; /* Ditto, mask or max. args */
   /* XXX requires cmd.h initializer changes u8 cd__pad[4];*/
   struct mx_cmd_arg_desc const *cd_cadp;
#ifdef mx_HAVE_DOCSTRINGS
   char const *cd_doc; /* One line doc for command */
#endif
};

/* Isolate the command from the arguments, return pointer to end of cmd name */
EXPORT char const *mx_cmd_isolate_name(char const *cmd);

/* Whether cmd is a valid command name (and not a modifier, for example) */
EXPORT boole mx_cmd_is_valid_name(char const *cmd);

/* First command which fits for cmd, or NULL */
EXPORT struct mx_cmd_desc const *mx_cmd_firstfit(char const *cmd);

/* Get the default command for the empty line */
EXPORT struct mx_cmd_desc const *mx_cmd_default(void);

/* Or NIL if cmd is invalid, or su_empty if !HAVE_DOCSTRINGS */
INLINE char const *mx_cmd_get_brief_doc(struct mx_cmd_desc const *cdp_or_nil){
   char const *rv;

   if(cdp_or_nil != NIL){
#ifdef mx_HAVE_DOCSTRINGS
      rv = cdp_or_nil->cd_doc;
#else
      rv = su_empty;
#endif
   }else
      rv = NIL;
   return rv;
}

/* True if I/O succeeded (or nothing was printed).
 * If fp is NIL we dump via err(), and return true. */
EXPORT boole mx_cmd_print_synopsis(struct mx_cmd_desc const *cdp_or_nil,
      FILE *fp_or_nil);

/* Scan an entire command argument line, return whether result can be used,
 * otherwise no resources are allocated (in ->cac_arg).
 * For _WYSH arguments the flags _TRIM_SPACE (v15 _not_ _TRIM_IFSSPACE) and
 * _LOG are implicit, _META_SEMICOLON is starting with the last (non-optional)
 * argument, and then a trailing empty argument is ignored, too */
EXPORT boole mx_cmd_arg_parse(struct mx_cmd_arg_ctx *cacp);

/* Save away the data from autorec memory, and restore it to that.
 * The heap storage is a single pointer to be n_free() by users */
EXPORT void *mx_cmd_arg_save_to_heap(struct mx_cmd_arg_ctx const *cacp);
EXPORT struct mx_cmd_arg_ctx *mx_cmd_arg_restore_from_heap(void *vp);

/* Scan out the list of string arguments according to rm, return -1 on error;
 * res_dat is NULL terminated unless res_size is 0 or error occurred */
EXPORT int /* TODO v15*/ getrawlist(boole wysh, char **res_dat, uz res_size,
                  char const *line, uz linesize);

#include <su/code-ou.h>
#endif /* mx_CMD_H */
/* s-it-mode */