]> git.pond.sub.org Git - empserver/blob - src/lib/gen/parse.c
5e5042edc2a9b3a4c25eb6ea79d2dd2c19412071
[empserver] / src / lib / gen / parse.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2012, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                Ken Stevens, Steve McClure, Markus Armbruster
5  *
6  *  Empire is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  *  ---
20  *
21  *  See files README, COPYING and CREDITS in the root of the source
22  *  tree for related information and legal notices.  It is expected
23  *  that future projects/authors will amend these files as needed.
24  *
25  *  ---
26  *
27  *  parse.c: Parse an Empire command line
28  *
29  *  Known contributors to this file:
30  *
31  */
32
33 #include <config.h>
34
35 #include <ctype.h>
36 #include "prototypes.h"
37
38 /*
39  * Parse user command in BUF.
40  * BUF is UTF-8.
41  * Command name and arguments are copied into SPACE[], whose size must
42  * be at least strlen(BUF) + 1.
43  * Set ARG[0] to the zero-terminated command name.
44  * Set ARG[1..N] to the zero-terminated arguments, where N is the
45  * number of arguments.  Set ARG[N+1..127] to NULL.
46  * Set TAIL[0..N] to beginning of ARG[0] in BUF[].
47  * If CONDP is not null, recognize conditional argument syntax, and
48  * set *CONDP to the conditional argument if present, else NULL.
49  * If REDIR is not null, recognize redirection syntax, and set *REDIR
50  * to UTF-8 redirection string if present, else NULL.
51  * Return number of slots used in ARG[], or -1 on error.
52  */
53 int
54 parse(char *buf, char *space, char **arg,
55       char **tail, char **condp, char **redir)
56 {
57     int i, quoted, argnum;
58
59     if (redir)
60         *redir = NULL;
61     if (condp)
62         *condp = NULL;
63
64     for (argnum = 0; argnum < 127;) {
65         for (; isspace(*(unsigned char *)buf); buf++) ;
66         if (!*buf)
67             break;
68
69         /* recognize redirection syntax */
70         if (redir && (*buf == '>' || *buf == '|')) {
71             *redir = buf;
72             break;
73         }
74
75         if (condp && *buf == '?') {
76             buf++;
77             *condp = space;
78         } else {
79             if (tail)
80                 tail[argnum] = buf;
81             arg[argnum++] = space;
82         }
83
84         /* copy argument */
85         quoted = 0;
86         for (; *buf && (quoted || !isspace(*(unsigned char *)buf)); buf++) {
87             if (*buf == '"')
88                 quoted = !quoted;
89             else if ((*buf >= 0x20 && *buf <= 0x7e) || *buf == '\t')
90                 *space++ = *buf;
91             /* else funny character; ignore */
92         }
93         *space++ = 0;
94     }
95
96     for (i = argnum; i < 128; i++) {
97         arg[i] = NULL;
98         if (tail)
99             tail[i] = NULL;
100     }
101
102     return argnum;
103 }