tokenizer.c (148814) | tokenizer.c (148834) |
---|---|
1/*- 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Christos Zoulas of Cornell University. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. | 1/*- 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Christos Zoulas of Cornell University. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. |
16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors | 16 * 3. Neither the name of the University nor the names of its contributors |
21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * | 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * |
36 * $NetBSD: tokenizer.c,v 1.6 2000/09/04 22:06:33 lukem Exp $ | 32 * $NetBSD: tokenizer.c,v 1.14 2003/12/05 13:37:48 lukem Exp $ |
37 */ 38 39#if !defined(lint) && !defined(SCCSID) 40static char sccsid[] = "@(#)tokenizer.c 8.1 (Berkeley) 6/4/93"; 41#endif /* not lint && not SCCSID */ 42#include <sys/cdefs.h> | 33 */ 34 35#if !defined(lint) && !defined(SCCSID) 36static char sccsid[] = "@(#)tokenizer.c 8.1 (Berkeley) 6/4/93"; 37#endif /* not lint && not SCCSID */ 38#include <sys/cdefs.h> |
43__FBSDID("$FreeBSD: head/lib/libedit/tokenizer.c 148814 2005-08-07 08:35:39Z stefanf $"); | 39__FBSDID("$FreeBSD: head/lib/libedit/tokenizer.c 148834 2005-08-07 20:55:59Z stefanf $"); |
44 45/* 46 * tokenize.c: Bourne shell like tokenizer 47 */ 48#include "sys.h" 49#include <string.h> 50#include <stdlib.h> | 40 41/* 42 * tokenize.c: Bourne shell like tokenizer 43 */ 44#include "sys.h" 45#include <string.h> 46#include <stdlib.h> |
51#include "tokenizer.h" | 47#include "histedit.h" |
52 53typedef enum { 54 Q_none, Q_single, Q_double, Q_one, Q_doubleone 55} quote_t; 56 57#define IFS "\t \n" 58 59#define TOK_KEEP 1 60#define TOK_EAT 2 61 62#define WINCR 20 63#define AINCR 10 64 | 48 49typedef enum { 50 Q_none, Q_single, Q_double, Q_one, Q_doubleone 51} quote_t; 52 53#define IFS "\t \n" 54 55#define TOK_KEEP 1 56#define TOK_EAT 2 57 58#define WINCR 20 59#define AINCR 10 60 |
61#define tok_strdup(a) strdup(a) |
|
65#define tok_malloc(a) malloc(a) 66#define tok_free(a) free(a) 67#define tok_realloc(a, b) realloc(a, b) 68 69 70struct tokenizer { 71 char *ifs; /* In field separator */ 72 int argc, amax; /* Current and maximum number of args */ --- 29 unchanged lines hidden (view full) --- 102/* tok_init(): 103 * Initialize the tokenizer 104 */ 105public Tokenizer * 106tok_init(const char *ifs) 107{ 108 Tokenizer *tok = (Tokenizer *) tok_malloc(sizeof(Tokenizer)); 109 | 62#define tok_malloc(a) malloc(a) 63#define tok_free(a) free(a) 64#define tok_realloc(a, b) realloc(a, b) 65 66 67struct tokenizer { 68 char *ifs; /* In field separator */ 69 int argc, amax; /* Current and maximum number of args */ --- 29 unchanged lines hidden (view full) --- 99/* tok_init(): 100 * Initialize the tokenizer 101 */ 102public Tokenizer * 103tok_init(const char *ifs) 104{ 105 Tokenizer *tok = (Tokenizer *) tok_malloc(sizeof(Tokenizer)); 106 |
110 tok->ifs = strdup(ifs ? ifs : IFS); | 107 if (tok == NULL) 108 return NULL; 109 tok->ifs = tok_strdup(ifs ? ifs : IFS); 110 if (tok->ifs == NULL) { 111 tok_free((ptr_t)tok); 112 return NULL; 113 } |
111 tok->argc = 0; 112 tok->amax = AINCR; 113 tok->argv = (char **) tok_malloc(sizeof(char *) * tok->amax); | 114 tok->argc = 0; 115 tok->amax = AINCR; 116 tok->argv = (char **) tok_malloc(sizeof(char *) * tok->amax); |
114 if (tok->argv == NULL) 115 return (NULL); | 117 if (tok->argv == NULL) { 118 tok_free((ptr_t)tok->ifs); 119 tok_free((ptr_t)tok); 120 return NULL; 121 } |
116 tok->argv[0] = NULL; 117 tok->wspace = (char *) tok_malloc(WINCR); | 122 tok->argv[0] = NULL; 123 tok->wspace = (char *) tok_malloc(WINCR); |
118 if (tok->wspace == NULL) 119 return (NULL); | 124 if (tok->wspace == NULL) { 125 tok_free((ptr_t)tok->argv); 126 tok_free((ptr_t)tok->ifs); 127 tok_free((ptr_t)tok); 128 return NULL; 129 } |
120 tok->wmax = tok->wspace + WINCR; 121 tok->wstart = tok->wspace; 122 tok->wptr = tok->wspace; 123 tok->flags = 0; 124 tok->quote = Q_none; 125 126 return (tok); 127} --- 25 unchanged lines hidden (view full) --- 153 tok_free((ptr_t) tok->wspace); 154 tok_free((ptr_t) tok->argv); 155 tok_free((ptr_t) tok); 156} 157 158 159 160/* tok_line(): | 130 tok->wmax = tok->wspace + WINCR; 131 tok->wstart = tok->wspace; 132 tok->wptr = tok->wspace; 133 tok->flags = 0; 134 tok->quote = Q_none; 135 136 return (tok); 137} --- 25 unchanged lines hidden (view full) --- 163 tok_free((ptr_t) tok->wspace); 164 tok_free((ptr_t) tok->argv); 165 tok_free((ptr_t) tok); 166} 167 168 169 170/* tok_line(): |
161 * Bourne shell like tokenizing 162 * Return: 163 * -1: Internal error 164 * 3: Quoted return 165 * 2: Unmatched double quote 166 * 1: Unmatched single quote 167 * 0: Ok | 171 * Bourne shell (sh(1)) like tokenizing 172 * Arguments: 173 * tok current tokenizer state (setup with tok_init()) 174 * line line to parse 175 * Returns: 176 * -1 Internal error 177 * 3 Quoted return 178 * 2 Unmatched double quote 179 * 1 Unmatched single quote 180 * 0 Ok 181 * Modifies (if return value is 0): 182 * argc number of arguments 183 * argv argument array 184 * cursorc if !NULL, argv element containing cursor 185 * cursorv if !NULL, offset in argv[cursorc] of cursor |
168 */ 169public int | 186 */ 187public int |
170tok_line(Tokenizer *tok, const char *line, int *argc, char ***argv) | 188tok_line(Tokenizer *tok, const LineInfo *line, 189 int *argc, const char ***argv, int *cursorc, int *cursoro) |
171{ 172 const char *ptr; | 190{ 191 const char *ptr; |
192 int cc, co; |
|
173 | 193 |
174 for (;;) { 175 switch (*(ptr = line++)) { | 194 cc = co = -1; 195 ptr = line->buffer; 196 for (ptr = line->buffer; ;ptr++) { 197 if (ptr >= line->lastchar) 198 ptr = ""; 199 if (ptr == line->cursor) { 200 cc = tok->argc; 201 co = tok->wptr - tok->wstart; 202 } 203 switch (*ptr) { |
176 case '\'': 177 tok->flags |= TOK_KEEP; 178 tok->flags &= ~TOK_EAT; 179 switch (tok->quote) { 180 case Q_none: 181 tok->quote = Q_single; /* Enter single quote 182 * mode */ 183 break; --- 82 unchanged lines hidden (view full) --- 266 return (-1); 267 } 268 break; 269 270 case '\n': 271 tok->flags &= ~TOK_EAT; 272 switch (tok->quote) { 273 case Q_none: | 204 case '\'': 205 tok->flags |= TOK_KEEP; 206 tok->flags &= ~TOK_EAT; 207 switch (tok->quote) { 208 case Q_none: 209 tok->quote = Q_single; /* Enter single quote 210 * mode */ 211 break; --- 82 unchanged lines hidden (view full) --- 294 return (-1); 295 } 296 break; 297 298 case '\n': 299 tok->flags &= ~TOK_EAT; 300 switch (tok->quote) { 301 case Q_none: |
274 tok_finish(tok); 275 *argv = tok->argv; 276 *argc = tok->argc; 277 return (0); | 302 goto tok_line_outok; |
278 279 case Q_single: 280 case Q_double: 281 *tok->wptr++ = *ptr; /* Add the return */ 282 break; 283 284 case Q_doubleone: /* Back to double, eat the '\n' */ 285 tok->flags |= TOK_EAT; --- 13 unchanged lines hidden (view full) --- 299 case '\0': 300 switch (tok->quote) { 301 case Q_none: 302 /* Finish word and return */ 303 if (tok->flags & TOK_EAT) { 304 tok->flags &= ~TOK_EAT; 305 return (3); 306 } | 303 304 case Q_single: 305 case Q_double: 306 *tok->wptr++ = *ptr; /* Add the return */ 307 break; 308 309 case Q_doubleone: /* Back to double, eat the '\n' */ 310 tok->flags |= TOK_EAT; --- 13 unchanged lines hidden (view full) --- 324 case '\0': 325 switch (tok->quote) { 326 case Q_none: 327 /* Finish word and return */ 328 if (tok->flags & TOK_EAT) { 329 tok->flags &= ~TOK_EAT; 330 return (3); 331 } |
307 tok_finish(tok); 308 *argv = tok->argv; 309 *argc = tok->argc; 310 return (0); | 332 goto tok_line_outok; |
311 312 case Q_single: 313 return (1); 314 315 case Q_double: 316 return (2); 317 318 case Q_doubleone: --- 43 unchanged lines hidden (view full) --- 362 363 } 364 break; 365 } 366 367 if (tok->wptr >= tok->wmax - 4) { 368 size_t size = tok->wmax - tok->wspace + WINCR; 369 char *s = (char *) tok_realloc(tok->wspace, size); | 333 334 case Q_single: 335 return (1); 336 337 case Q_double: 338 return (2); 339 340 case Q_doubleone: --- 43 unchanged lines hidden (view full) --- 384 385 } 386 break; 387 } 388 389 if (tok->wptr >= tok->wmax - 4) { 390 size_t size = tok->wmax - tok->wspace + WINCR; 391 char *s = (char *) tok_realloc(tok->wspace, size); |
370 /* SUPPRESS 22 */ 371 int offs = s - tok->wspace; | |
372 if (s == NULL) 373 return (-1); 374 | 392 if (s == NULL) 393 return (-1); 394 |
375 if (offs != 0) { | 395 if (s != tok->wspace) { |
376 int i; | 396 int i; |
377 for (i = 0; i < tok->argc; i++) 378 tok->argv[i] = tok->argv[i] + offs; 379 tok->wptr = tok->wptr + offs; 380 tok->wstart = tok->wstart + offs; 381 tok->wmax = s + size; | 397 for (i = 0; i < tok->argc; i++) { 398 tok->argv[i] = 399 (tok->argv[i] - tok->wspace) + s; 400 } 401 tok->wptr = (tok->wptr - tok->wspace) + s; 402 tok->wstart = (tok->wstart - tok->wspace) + s; |
382 tok->wspace = s; 383 } | 403 tok->wspace = s; 404 } |
405 tok->wmax = s + size; |
|
384 } 385 if (tok->argc >= tok->amax - 4) { 386 char **p; 387 tok->amax += AINCR; 388 p = (char **) tok_realloc(tok->argv, 389 tok->amax * sizeof(char *)); 390 if (p == NULL) 391 return (-1); 392 tok->argv = p; 393 } 394 } | 406 } 407 if (tok->argc >= tok->amax - 4) { 408 char **p; 409 tok->amax += AINCR; 410 p = (char **) tok_realloc(tok->argv, 411 tok->amax * sizeof(char *)); 412 if (p == NULL) 413 return (-1); 414 tok->argv = p; 415 } 416 } |
417 tok_line_outok: 418 if (cc == -1 && co == -1) { 419 cc = tok->argc; 420 co = tok->wptr - tok->wstart; 421 } 422 if (cursorc != NULL) 423 *cursorc = cc; 424 if (cursoro != NULL) 425 *cursoro = co; 426 tok_finish(tok); 427 *argv = (const char **)tok->argv; 428 *argc = tok->argc; 429 return (0); |
|
395} | 430} |
431 432/* tok_str(): 433 * Simpler version of tok_line, taking a NUL terminated line 434 * and splitting into words, ignoring cursor state. 435 */ 436public int 437tok_str(Tokenizer *tok, const char *line, int *argc, const char ***argv) 438{ 439 LineInfo li; 440 441 memset(&li, 0, sizeof(li)); 442 li.buffer = line; 443 li.cursor = li.lastchar = strchr(line, '\0'); 444 return (tok_line(tok, &li, argc, argv, NULL, NULL)); 445} |
|