1*12db70c8Szrj /* $NetBSD: tokenizer.c,v 1.28 2016/04/11 18:56:31 christos Exp $ */
232fe07f8SJohn Marino
332fe07f8SJohn Marino /*-
432fe07f8SJohn Marino * Copyright (c) 1992, 1993
532fe07f8SJohn Marino * The Regents of the University of California. All rights reserved.
632fe07f8SJohn Marino *
732fe07f8SJohn Marino * This code is derived from software contributed to Berkeley by
832fe07f8SJohn Marino * Christos Zoulas of Cornell University.
932fe07f8SJohn Marino *
1032fe07f8SJohn Marino * Redistribution and use in source and binary forms, with or without
1132fe07f8SJohn Marino * modification, are permitted provided that the following conditions
1232fe07f8SJohn Marino * are met:
1332fe07f8SJohn Marino * 1. Redistributions of source code must retain the above copyright
1432fe07f8SJohn Marino * notice, this list of conditions and the following disclaimer.
1532fe07f8SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
1632fe07f8SJohn Marino * notice, this list of conditions and the following disclaimer in the
1732fe07f8SJohn Marino * documentation and/or other materials provided with the distribution.
1832fe07f8SJohn Marino * 3. Neither the name of the University nor the names of its contributors
1932fe07f8SJohn Marino * may be used to endorse or promote products derived from this software
2032fe07f8SJohn Marino * without specific prior written permission.
2132fe07f8SJohn Marino *
2232fe07f8SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2332fe07f8SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2432fe07f8SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2532fe07f8SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2632fe07f8SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2732fe07f8SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2832fe07f8SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2932fe07f8SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3032fe07f8SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3132fe07f8SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3232fe07f8SJohn Marino * SUCH DAMAGE.
3332fe07f8SJohn Marino */
3432fe07f8SJohn Marino
3532fe07f8SJohn Marino #ifndef NARROWCHAR
3632fe07f8SJohn Marino #include "config.h"
3732fe07f8SJohn Marino #endif
3832fe07f8SJohn Marino
3932fe07f8SJohn Marino #if !defined(lint) && !defined(SCCSID)
4032fe07f8SJohn Marino #if 0
4132fe07f8SJohn Marino static char sccsid[] = "@(#)tokenizer.c 8.1 (Berkeley) 6/4/93";
4232fe07f8SJohn Marino #else
43*12db70c8Szrj __RCSID("$NetBSD: tokenizer.c,v 1.28 2016/04/11 18:56:31 christos Exp $");
4432fe07f8SJohn Marino #endif
4532fe07f8SJohn Marino #endif /* not lint && not SCCSID */
4632fe07f8SJohn Marino
4732fe07f8SJohn Marino /* We build this file twice, once as NARROW, once as WIDE. */
4832fe07f8SJohn Marino /*
4932fe07f8SJohn Marino * tokenize.c: Bourne shell like tokenizer
5032fe07f8SJohn Marino */
5132fe07f8SJohn Marino #include <stdlib.h>
52*12db70c8Szrj #include <string.h>
53*12db70c8Szrj
5432fe07f8SJohn Marino #include "histedit.h"
5532fe07f8SJohn Marino
5632fe07f8SJohn Marino typedef enum {
5732fe07f8SJohn Marino Q_none, Q_single, Q_double, Q_one, Q_doubleone
5832fe07f8SJohn Marino } quote_t;
5932fe07f8SJohn Marino
6032fe07f8SJohn Marino #define TOK_KEEP 1
6132fe07f8SJohn Marino #define TOK_EAT 2
6232fe07f8SJohn Marino
6332fe07f8SJohn Marino #define WINCR 20
6432fe07f8SJohn Marino #define AINCR 10
6532fe07f8SJohn Marino
6632fe07f8SJohn Marino #define IFS STR("\t \n")
6732fe07f8SJohn Marino
6832fe07f8SJohn Marino #define tok_malloc(a) malloc(a)
6932fe07f8SJohn Marino #define tok_free(a) free(a)
7032fe07f8SJohn Marino #define tok_realloc(a, b) realloc(a, b)
7132fe07f8SJohn Marino
72*12db70c8Szrj #ifdef NARROWCHAR
73*12db70c8Szrj #define Char char
74*12db70c8Szrj #define FUN(prefix, rest) prefix ## _ ## rest
75*12db70c8Szrj #define TYPE(type) type
76*12db70c8Szrj #define STR(x) x
77*12db70c8Szrj #define Strchr(s, c) strchr(s, c)
78*12db70c8Szrj #define tok_strdup(s) strdup(s)
79*12db70c8Szrj #else
80*12db70c8Szrj #define Char wchar_t
81*12db70c8Szrj #define FUN(prefix, rest) prefix ## _w ## rest
82*12db70c8Szrj #define TYPE(type) type ## W
83*12db70c8Szrj #define STR(x) L ## x
84*12db70c8Szrj #define Strchr(s, c) wcschr(s, c)
85*12db70c8Szrj #define tok_strdup(s) wcsdup(s)
86*12db70c8Szrj #endif
8732fe07f8SJohn Marino
TYPE(tokenizer)8832fe07f8SJohn Marino struct TYPE(tokenizer) {
8932fe07f8SJohn Marino Char *ifs; /* In field separator */
9032fe07f8SJohn Marino size_t argc, amax; /* Current and maximum number of args */
9132fe07f8SJohn Marino Char **argv; /* Argument list */
9232fe07f8SJohn Marino Char *wptr, *wmax; /* Space and limit on the word buffer */
9332fe07f8SJohn Marino Char *wstart; /* Beginning of next word */
9432fe07f8SJohn Marino Char *wspace; /* Space of word buffer */
9532fe07f8SJohn Marino quote_t quote; /* Quoting state */
9632fe07f8SJohn Marino int flags; /* flags; */
9732fe07f8SJohn Marino };
9832fe07f8SJohn Marino
9932fe07f8SJohn Marino
100*12db70c8Szrj static void FUN(tok,finish)(TYPE(Tokenizer) *);
10132fe07f8SJohn Marino
10232fe07f8SJohn Marino
10332fe07f8SJohn Marino /* FUN(tok,finish)():
10432fe07f8SJohn Marino * Finish a word in the tokenizer.
10532fe07f8SJohn Marino */
106*12db70c8Szrj static void
FUN(tok,finish)10732fe07f8SJohn Marino FUN(tok,finish)(TYPE(Tokenizer) *tok)
10832fe07f8SJohn Marino {
10932fe07f8SJohn Marino
11032fe07f8SJohn Marino *tok->wptr = '\0';
11132fe07f8SJohn Marino if ((tok->flags & TOK_KEEP) || tok->wptr != tok->wstart) {
11232fe07f8SJohn Marino tok->argv[tok->argc++] = tok->wstart;
11332fe07f8SJohn Marino tok->argv[tok->argc] = NULL;
11432fe07f8SJohn Marino tok->wstart = ++tok->wptr;
11532fe07f8SJohn Marino }
11632fe07f8SJohn Marino tok->flags &= ~TOK_KEEP;
11732fe07f8SJohn Marino }
11832fe07f8SJohn Marino
11932fe07f8SJohn Marino
12032fe07f8SJohn Marino /* FUN(tok,init)():
12132fe07f8SJohn Marino * Initialize the tokenizer
12232fe07f8SJohn Marino */
TYPE(Tokenizer)123*12db70c8Szrj TYPE(Tokenizer) *
12432fe07f8SJohn Marino FUN(tok,init)(const Char *ifs)
12532fe07f8SJohn Marino {
12632fe07f8SJohn Marino TYPE(Tokenizer) *tok = tok_malloc(sizeof(*tok));
12732fe07f8SJohn Marino
12832fe07f8SJohn Marino if (tok == NULL)
12932fe07f8SJohn Marino return NULL;
13032fe07f8SJohn Marino tok->ifs = tok_strdup(ifs ? ifs : IFS);
13132fe07f8SJohn Marino if (tok->ifs == NULL) {
13232fe07f8SJohn Marino tok_free(tok);
13332fe07f8SJohn Marino return NULL;
13432fe07f8SJohn Marino }
13532fe07f8SJohn Marino tok->argc = 0;
13632fe07f8SJohn Marino tok->amax = AINCR;
13732fe07f8SJohn Marino tok->argv = tok_malloc(sizeof(*tok->argv) * tok->amax);
13832fe07f8SJohn Marino if (tok->argv == NULL) {
13932fe07f8SJohn Marino tok_free(tok->ifs);
14032fe07f8SJohn Marino tok_free(tok);
14132fe07f8SJohn Marino return NULL;
14232fe07f8SJohn Marino }
14332fe07f8SJohn Marino tok->argv[0] = NULL;
14432fe07f8SJohn Marino tok->wspace = tok_malloc(WINCR * sizeof(*tok->wspace));
14532fe07f8SJohn Marino if (tok->wspace == NULL) {
14632fe07f8SJohn Marino tok_free(tok->argv);
14732fe07f8SJohn Marino tok_free(tok->ifs);
14832fe07f8SJohn Marino tok_free(tok);
14932fe07f8SJohn Marino return NULL;
15032fe07f8SJohn Marino }
15132fe07f8SJohn Marino tok->wmax = tok->wspace + WINCR;
15232fe07f8SJohn Marino tok->wstart = tok->wspace;
15332fe07f8SJohn Marino tok->wptr = tok->wspace;
15432fe07f8SJohn Marino tok->flags = 0;
15532fe07f8SJohn Marino tok->quote = Q_none;
15632fe07f8SJohn Marino
15732fe07f8SJohn Marino return tok;
15832fe07f8SJohn Marino }
15932fe07f8SJohn Marino
16032fe07f8SJohn Marino
16132fe07f8SJohn Marino /* FUN(tok,reset)():
16232fe07f8SJohn Marino * Reset the tokenizer
16332fe07f8SJohn Marino */
164*12db70c8Szrj void
FUN(tok,reset)16532fe07f8SJohn Marino FUN(tok,reset)(TYPE(Tokenizer) *tok)
16632fe07f8SJohn Marino {
16732fe07f8SJohn Marino
16832fe07f8SJohn Marino tok->argc = 0;
16932fe07f8SJohn Marino tok->wstart = tok->wspace;
17032fe07f8SJohn Marino tok->wptr = tok->wspace;
17132fe07f8SJohn Marino tok->flags = 0;
17232fe07f8SJohn Marino tok->quote = Q_none;
17332fe07f8SJohn Marino }
17432fe07f8SJohn Marino
17532fe07f8SJohn Marino
17632fe07f8SJohn Marino /* FUN(tok,end)():
17732fe07f8SJohn Marino * Clean up
17832fe07f8SJohn Marino */
179*12db70c8Szrj void
FUN(tok,end)18032fe07f8SJohn Marino FUN(tok,end)(TYPE(Tokenizer) *tok)
18132fe07f8SJohn Marino {
18232fe07f8SJohn Marino
18332fe07f8SJohn Marino tok_free(tok->ifs);
18432fe07f8SJohn Marino tok_free(tok->wspace);
18532fe07f8SJohn Marino tok_free(tok->argv);
18632fe07f8SJohn Marino tok_free(tok);
18732fe07f8SJohn Marino }
18832fe07f8SJohn Marino
18932fe07f8SJohn Marino
19032fe07f8SJohn Marino
19132fe07f8SJohn Marino /* FUN(tok,line)():
19232fe07f8SJohn Marino * Bourne shell (sh(1)) like tokenizing
19332fe07f8SJohn Marino * Arguments:
19432fe07f8SJohn Marino * tok current tokenizer state (setup with FUN(tok,init)())
19532fe07f8SJohn Marino * line line to parse
19632fe07f8SJohn Marino * Returns:
19732fe07f8SJohn Marino * -1 Internal error
19832fe07f8SJohn Marino * 3 Quoted return
19932fe07f8SJohn Marino * 2 Unmatched double quote
20032fe07f8SJohn Marino * 1 Unmatched single quote
20132fe07f8SJohn Marino * 0 Ok
20232fe07f8SJohn Marino * Modifies (if return value is 0):
20332fe07f8SJohn Marino * argc number of arguments
20432fe07f8SJohn Marino * argv argument array
20532fe07f8SJohn Marino * cursorc if !NULL, argv element containing cursor
20632fe07f8SJohn Marino * cursorv if !NULL, offset in argv[cursorc] of cursor
20732fe07f8SJohn Marino */
208*12db70c8Szrj int
FUN(tok,line)20932fe07f8SJohn Marino FUN(tok,line)(TYPE(Tokenizer) *tok, const TYPE(LineInfo) *line,
21032fe07f8SJohn Marino int *argc, const Char ***argv, int *cursorc, int *cursoro)
21132fe07f8SJohn Marino {
21232fe07f8SJohn Marino const Char *ptr;
21332fe07f8SJohn Marino int cc, co;
21432fe07f8SJohn Marino
21532fe07f8SJohn Marino cc = co = -1;
21632fe07f8SJohn Marino ptr = line->buffer;
21732fe07f8SJohn Marino for (ptr = line->buffer; ;ptr++) {
21832fe07f8SJohn Marino if (ptr >= line->lastchar)
21932fe07f8SJohn Marino ptr = STR("");
22032fe07f8SJohn Marino if (ptr == line->cursor) {
22132fe07f8SJohn Marino cc = (int)tok->argc;
22232fe07f8SJohn Marino co = (int)(tok->wptr - tok->wstart);
22332fe07f8SJohn Marino }
22432fe07f8SJohn Marino switch (*ptr) {
22532fe07f8SJohn Marino case '\'':
22632fe07f8SJohn Marino tok->flags |= TOK_KEEP;
22732fe07f8SJohn Marino tok->flags &= ~TOK_EAT;
22832fe07f8SJohn Marino switch (tok->quote) {
22932fe07f8SJohn Marino case Q_none:
23032fe07f8SJohn Marino tok->quote = Q_single; /* Enter single quote
23132fe07f8SJohn Marino * mode */
23232fe07f8SJohn Marino break;
23332fe07f8SJohn Marino
23432fe07f8SJohn Marino case Q_single: /* Exit single quote mode */
23532fe07f8SJohn Marino tok->quote = Q_none;
23632fe07f8SJohn Marino break;
23732fe07f8SJohn Marino
23832fe07f8SJohn Marino case Q_one: /* Quote this ' */
23932fe07f8SJohn Marino tok->quote = Q_none;
24032fe07f8SJohn Marino *tok->wptr++ = *ptr;
24132fe07f8SJohn Marino break;
24232fe07f8SJohn Marino
24332fe07f8SJohn Marino case Q_double: /* Stay in double quote mode */
24432fe07f8SJohn Marino *tok->wptr++ = *ptr;
24532fe07f8SJohn Marino break;
24632fe07f8SJohn Marino
24732fe07f8SJohn Marino case Q_doubleone: /* Quote this ' */
24832fe07f8SJohn Marino tok->quote = Q_double;
24932fe07f8SJohn Marino *tok->wptr++ = *ptr;
25032fe07f8SJohn Marino break;
25132fe07f8SJohn Marino
25232fe07f8SJohn Marino default:
25332fe07f8SJohn Marino return -1;
25432fe07f8SJohn Marino }
25532fe07f8SJohn Marino break;
25632fe07f8SJohn Marino
25732fe07f8SJohn Marino case '"':
25832fe07f8SJohn Marino tok->flags &= ~TOK_EAT;
25932fe07f8SJohn Marino tok->flags |= TOK_KEEP;
26032fe07f8SJohn Marino switch (tok->quote) {
26132fe07f8SJohn Marino case Q_none: /* Enter double quote mode */
26232fe07f8SJohn Marino tok->quote = Q_double;
26332fe07f8SJohn Marino break;
26432fe07f8SJohn Marino
26532fe07f8SJohn Marino case Q_double: /* Exit double quote mode */
26632fe07f8SJohn Marino tok->quote = Q_none;
26732fe07f8SJohn Marino break;
26832fe07f8SJohn Marino
26932fe07f8SJohn Marino case Q_one: /* Quote this " */
27032fe07f8SJohn Marino tok->quote = Q_none;
27132fe07f8SJohn Marino *tok->wptr++ = *ptr;
27232fe07f8SJohn Marino break;
27332fe07f8SJohn Marino
27432fe07f8SJohn Marino case Q_single: /* Stay in single quote mode */
27532fe07f8SJohn Marino *tok->wptr++ = *ptr;
27632fe07f8SJohn Marino break;
27732fe07f8SJohn Marino
27832fe07f8SJohn Marino case Q_doubleone: /* Quote this " */
27932fe07f8SJohn Marino tok->quote = Q_double;
28032fe07f8SJohn Marino *tok->wptr++ = *ptr;
28132fe07f8SJohn Marino break;
28232fe07f8SJohn Marino
28332fe07f8SJohn Marino default:
28432fe07f8SJohn Marino return -1;
28532fe07f8SJohn Marino }
28632fe07f8SJohn Marino break;
28732fe07f8SJohn Marino
28832fe07f8SJohn Marino case '\\':
28932fe07f8SJohn Marino tok->flags |= TOK_KEEP;
29032fe07f8SJohn Marino tok->flags &= ~TOK_EAT;
29132fe07f8SJohn Marino switch (tok->quote) {
29232fe07f8SJohn Marino case Q_none: /* Quote next character */
29332fe07f8SJohn Marino tok->quote = Q_one;
29432fe07f8SJohn Marino break;
29532fe07f8SJohn Marino
29632fe07f8SJohn Marino case Q_double: /* Quote next character */
29732fe07f8SJohn Marino tok->quote = Q_doubleone;
29832fe07f8SJohn Marino break;
29932fe07f8SJohn Marino
30032fe07f8SJohn Marino case Q_one: /* Quote this, restore state */
30132fe07f8SJohn Marino *tok->wptr++ = *ptr;
30232fe07f8SJohn Marino tok->quote = Q_none;
30332fe07f8SJohn Marino break;
30432fe07f8SJohn Marino
30532fe07f8SJohn Marino case Q_single: /* Stay in single quote mode */
30632fe07f8SJohn Marino *tok->wptr++ = *ptr;
30732fe07f8SJohn Marino break;
30832fe07f8SJohn Marino
30932fe07f8SJohn Marino case Q_doubleone: /* Quote this \ */
31032fe07f8SJohn Marino tok->quote = Q_double;
31132fe07f8SJohn Marino *tok->wptr++ = *ptr;
31232fe07f8SJohn Marino break;
31332fe07f8SJohn Marino
31432fe07f8SJohn Marino default:
31532fe07f8SJohn Marino return -1;
31632fe07f8SJohn Marino }
31732fe07f8SJohn Marino break;
31832fe07f8SJohn Marino
31932fe07f8SJohn Marino case '\n':
32032fe07f8SJohn Marino tok->flags &= ~TOK_EAT;
32132fe07f8SJohn Marino switch (tok->quote) {
32232fe07f8SJohn Marino case Q_none:
32332fe07f8SJohn Marino goto tok_line_outok;
32432fe07f8SJohn Marino
32532fe07f8SJohn Marino case Q_single:
32632fe07f8SJohn Marino case Q_double:
32732fe07f8SJohn Marino *tok->wptr++ = *ptr; /* Add the return */
32832fe07f8SJohn Marino break;
32932fe07f8SJohn Marino
33032fe07f8SJohn Marino case Q_doubleone: /* Back to double, eat the '\n' */
33132fe07f8SJohn Marino tok->flags |= TOK_EAT;
33232fe07f8SJohn Marino tok->quote = Q_double;
33332fe07f8SJohn Marino break;
33432fe07f8SJohn Marino
33532fe07f8SJohn Marino case Q_one: /* No quote, more eat the '\n' */
33632fe07f8SJohn Marino tok->flags |= TOK_EAT;
33732fe07f8SJohn Marino tok->quote = Q_none;
33832fe07f8SJohn Marino break;
33932fe07f8SJohn Marino
34032fe07f8SJohn Marino default:
34132fe07f8SJohn Marino return 0;
34232fe07f8SJohn Marino }
34332fe07f8SJohn Marino break;
34432fe07f8SJohn Marino
34532fe07f8SJohn Marino case '\0':
34632fe07f8SJohn Marino switch (tok->quote) {
34732fe07f8SJohn Marino case Q_none:
34832fe07f8SJohn Marino /* Finish word and return */
34932fe07f8SJohn Marino if (tok->flags & TOK_EAT) {
35032fe07f8SJohn Marino tok->flags &= ~TOK_EAT;
35132fe07f8SJohn Marino return 3;
35232fe07f8SJohn Marino }
35332fe07f8SJohn Marino goto tok_line_outok;
35432fe07f8SJohn Marino
35532fe07f8SJohn Marino case Q_single:
35632fe07f8SJohn Marino return 1;
35732fe07f8SJohn Marino
35832fe07f8SJohn Marino case Q_double:
35932fe07f8SJohn Marino return 2;
36032fe07f8SJohn Marino
36132fe07f8SJohn Marino case Q_doubleone:
36232fe07f8SJohn Marino tok->quote = Q_double;
36332fe07f8SJohn Marino *tok->wptr++ = *ptr;
36432fe07f8SJohn Marino break;
36532fe07f8SJohn Marino
36632fe07f8SJohn Marino case Q_one:
36732fe07f8SJohn Marino tok->quote = Q_none;
36832fe07f8SJohn Marino *tok->wptr++ = *ptr;
36932fe07f8SJohn Marino break;
37032fe07f8SJohn Marino
37132fe07f8SJohn Marino default:
37232fe07f8SJohn Marino return -1;
37332fe07f8SJohn Marino }
37432fe07f8SJohn Marino break;
37532fe07f8SJohn Marino
37632fe07f8SJohn Marino default:
37732fe07f8SJohn Marino tok->flags &= ~TOK_EAT;
37832fe07f8SJohn Marino switch (tok->quote) {
37932fe07f8SJohn Marino case Q_none:
38032fe07f8SJohn Marino if (Strchr(tok->ifs, *ptr) != NULL)
38132fe07f8SJohn Marino FUN(tok,finish)(tok);
38232fe07f8SJohn Marino else
38332fe07f8SJohn Marino *tok->wptr++ = *ptr;
38432fe07f8SJohn Marino break;
38532fe07f8SJohn Marino
38632fe07f8SJohn Marino case Q_single:
38732fe07f8SJohn Marino case Q_double:
38832fe07f8SJohn Marino *tok->wptr++ = *ptr;
38932fe07f8SJohn Marino break;
39032fe07f8SJohn Marino
39132fe07f8SJohn Marino
39232fe07f8SJohn Marino case Q_doubleone:
39332fe07f8SJohn Marino *tok->wptr++ = '\\';
39432fe07f8SJohn Marino tok->quote = Q_double;
39532fe07f8SJohn Marino *tok->wptr++ = *ptr;
39632fe07f8SJohn Marino break;
39732fe07f8SJohn Marino
39832fe07f8SJohn Marino case Q_one:
39932fe07f8SJohn Marino tok->quote = Q_none;
40032fe07f8SJohn Marino *tok->wptr++ = *ptr;
40132fe07f8SJohn Marino break;
40232fe07f8SJohn Marino
40332fe07f8SJohn Marino default:
40432fe07f8SJohn Marino return -1;
40532fe07f8SJohn Marino
40632fe07f8SJohn Marino }
40732fe07f8SJohn Marino break;
40832fe07f8SJohn Marino }
40932fe07f8SJohn Marino
41032fe07f8SJohn Marino if (tok->wptr >= tok->wmax - 4) {
41132fe07f8SJohn Marino size_t size = (size_t)(tok->wmax - tok->wspace + WINCR);
41232fe07f8SJohn Marino Char *s = tok_realloc(tok->wspace,
41332fe07f8SJohn Marino size * sizeof(*s));
41432fe07f8SJohn Marino if (s == NULL)
41532fe07f8SJohn Marino return -1;
41632fe07f8SJohn Marino
41732fe07f8SJohn Marino if (s != tok->wspace) {
41832fe07f8SJohn Marino size_t i;
41932fe07f8SJohn Marino for (i = 0; i < tok->argc; i++) {
42032fe07f8SJohn Marino tok->argv[i] =
42132fe07f8SJohn Marino (tok->argv[i] - tok->wspace) + s;
42232fe07f8SJohn Marino }
42332fe07f8SJohn Marino tok->wptr = (tok->wptr - tok->wspace) + s;
42432fe07f8SJohn Marino tok->wstart = (tok->wstart - tok->wspace) + s;
42532fe07f8SJohn Marino tok->wspace = s;
42632fe07f8SJohn Marino }
42732fe07f8SJohn Marino tok->wmax = s + size;
42832fe07f8SJohn Marino }
42932fe07f8SJohn Marino if (tok->argc >= tok->amax - 4) {
43032fe07f8SJohn Marino Char **p;
43132fe07f8SJohn Marino tok->amax += AINCR;
43232fe07f8SJohn Marino p = tok_realloc(tok->argv, tok->amax * sizeof(*p));
433*12db70c8Szrj if (p == NULL) {
434*12db70c8Szrj tok->amax -= AINCR;
43532fe07f8SJohn Marino return -1;
436*12db70c8Szrj }
43732fe07f8SJohn Marino tok->argv = p;
43832fe07f8SJohn Marino }
43932fe07f8SJohn Marino }
44032fe07f8SJohn Marino tok_line_outok:
44132fe07f8SJohn Marino if (cc == -1 && co == -1) {
44232fe07f8SJohn Marino cc = (int)tok->argc;
44332fe07f8SJohn Marino co = (int)(tok->wptr - tok->wstart);
44432fe07f8SJohn Marino }
44532fe07f8SJohn Marino if (cursorc != NULL)
44632fe07f8SJohn Marino *cursorc = cc;
44732fe07f8SJohn Marino if (cursoro != NULL)
44832fe07f8SJohn Marino *cursoro = co;
44932fe07f8SJohn Marino FUN(tok,finish)(tok);
45032fe07f8SJohn Marino *argv = (const Char **)tok->argv;
45132fe07f8SJohn Marino *argc = (int)tok->argc;
45232fe07f8SJohn Marino return 0;
45332fe07f8SJohn Marino }
45432fe07f8SJohn Marino
45532fe07f8SJohn Marino /* FUN(tok,str)():
45632fe07f8SJohn Marino * Simpler version of tok_line, taking a NUL terminated line
45732fe07f8SJohn Marino * and splitting into words, ignoring cursor state.
45832fe07f8SJohn Marino */
459*12db70c8Szrj int
FUN(tok,str)46032fe07f8SJohn Marino FUN(tok,str)(TYPE(Tokenizer) *tok, const Char *line, int *argc,
46132fe07f8SJohn Marino const Char ***argv)
46232fe07f8SJohn Marino {
46332fe07f8SJohn Marino TYPE(LineInfo) li;
46432fe07f8SJohn Marino
46532fe07f8SJohn Marino memset(&li, 0, sizeof(li));
46632fe07f8SJohn Marino li.buffer = line;
46732fe07f8SJohn Marino li.cursor = li.lastchar = Strchr(line, '\0');
468*12db70c8Szrj return FUN(tok,line)(tok, &li, argc, argv, NULL, NULL);
46932fe07f8SJohn Marino }
470