xref: /aosp_15_r20/external/e2fsprogs/lib/ss/parse.c (revision 6a54128f25917bfc36a8a6e9d722c04a0b4641b6)
1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker  * Copyright 1987, 1988 by MIT Student Information Processing Board
3*6a54128fSAndroid Build Coastguard Worker  *
4*6a54128fSAndroid Build Coastguard Worker  * Permission to use, copy, modify, and distribute this software and
5*6a54128fSAndroid Build Coastguard Worker  * its documentation for any purpose is hereby granted, provided that
6*6a54128fSAndroid Build Coastguard Worker  * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
7*6a54128fSAndroid Build Coastguard Worker  * advertising or publicity pertaining to distribution of the software
8*6a54128fSAndroid Build Coastguard Worker  * without specific, written prior permission.  M.I.T. and the
9*6a54128fSAndroid Build Coastguard Worker  * M.I.T. S.I.P.B. make no representations about the suitability of
10*6a54128fSAndroid Build Coastguard Worker  * this software for any purpose.  It is provided "as is" without
11*6a54128fSAndroid Build Coastguard Worker  * express or implied warranty.
12*6a54128fSAndroid Build Coastguard Worker  */
13*6a54128fSAndroid Build Coastguard Worker 
14*6a54128fSAndroid Build Coastguard Worker #include "config.h"
15*6a54128fSAndroid Build Coastguard Worker #ifdef HAS_STDLIB_H
16*6a54128fSAndroid Build Coastguard Worker #include <stdlib.h>
17*6a54128fSAndroid Build Coastguard Worker #endif
18*6a54128fSAndroid Build Coastguard Worker #include <string.h>
19*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_ERRNO_H
20*6a54128fSAndroid Build Coastguard Worker #include <errno.h>
21*6a54128fSAndroid Build Coastguard Worker #endif
22*6a54128fSAndroid Build Coastguard Worker 
23*6a54128fSAndroid Build Coastguard Worker #include "ss_internal.h"
24*6a54128fSAndroid Build Coastguard Worker 
25*6a54128fSAndroid Build Coastguard Worker enum parse_mode { WHITESPACE, TOKEN, QUOTED_STRING };
26*6a54128fSAndroid Build Coastguard Worker 
27*6a54128fSAndroid Build Coastguard Worker /*
28*6a54128fSAndroid Build Coastguard Worker  * parse(line_ptr, argc_ptr)
29*6a54128fSAndroid Build Coastguard Worker  *
30*6a54128fSAndroid Build Coastguard Worker  * Function:
31*6a54128fSAndroid Build Coastguard Worker  *      Parses line, dividing at whitespace, into tokens, returns
32*6a54128fSAndroid Build Coastguard Worker  *      the "argc" and "argv" values.
33*6a54128fSAndroid Build Coastguard Worker  * Arguments:
34*6a54128fSAndroid Build Coastguard Worker  *      line_ptr (char *)
35*6a54128fSAndroid Build Coastguard Worker  *              Pointer to text string to be parsed.
36*6a54128fSAndroid Build Coastguard Worker  *      argc_ptr (int *)
37*6a54128fSAndroid Build Coastguard Worker  *              Where to put the "argc" (number of tokens) value.
38*6a54128fSAndroid Build Coastguard Worker  * Returns:
39*6a54128fSAndroid Build Coastguard Worker  *      argv (char **)
40*6a54128fSAndroid Build Coastguard Worker  *              Series of pointers to parsed tokens.
41*6a54128fSAndroid Build Coastguard Worker  */
42*6a54128fSAndroid Build Coastguard Worker 
43*6a54128fSAndroid Build Coastguard Worker #define NEW_ARGV(old,n) (char **)realloc((char *)old,\
44*6a54128fSAndroid Build Coastguard Worker 					 (unsigned)(n+2)*sizeof(char*))
45*6a54128fSAndroid Build Coastguard Worker 
ss_parse(int sci_idx,register char * line_ptr,int * argc_ptr)46*6a54128fSAndroid Build Coastguard Worker char **ss_parse(int sci_idx, register char *line_ptr, int *argc_ptr)
47*6a54128fSAndroid Build Coastguard Worker {
48*6a54128fSAndroid Build Coastguard Worker     register char **argv, **new_argv, *cp;
49*6a54128fSAndroid Build Coastguard Worker     register int argc;
50*6a54128fSAndroid Build Coastguard Worker     register enum parse_mode parse_mode;
51*6a54128fSAndroid Build Coastguard Worker 
52*6a54128fSAndroid Build Coastguard Worker     argv = (char **) malloc (sizeof(char *));
53*6a54128fSAndroid Build Coastguard Worker     if (argv == (char **)NULL) {
54*6a54128fSAndroid Build Coastguard Worker 	ss_error(sci_idx, errno, "Can't allocate storage");
55*6a54128fSAndroid Build Coastguard Worker 	*argc_ptr = 0;
56*6a54128fSAndroid Build Coastguard Worker 	return(argv);
57*6a54128fSAndroid Build Coastguard Worker     }
58*6a54128fSAndroid Build Coastguard Worker     *argv = (char *)NULL;
59*6a54128fSAndroid Build Coastguard Worker 
60*6a54128fSAndroid Build Coastguard Worker     argc = 0;
61*6a54128fSAndroid Build Coastguard Worker 
62*6a54128fSAndroid Build Coastguard Worker     parse_mode = WHITESPACE;	/* flushing whitespace */
63*6a54128fSAndroid Build Coastguard Worker     cp = line_ptr;		/* cp is for output */
64*6a54128fSAndroid Build Coastguard Worker     while (1) {
65*6a54128fSAndroid Build Coastguard Worker #ifdef DEBUG
66*6a54128fSAndroid Build Coastguard Worker 	{
67*6a54128fSAndroid Build Coastguard Worker 	    printf ("character `%c', mode %d\n", *line_ptr, parse_mode);
68*6a54128fSAndroid Build Coastguard Worker 	}
69*6a54128fSAndroid Build Coastguard Worker #endif
70*6a54128fSAndroid Build Coastguard Worker 	while (parse_mode == WHITESPACE) {
71*6a54128fSAndroid Build Coastguard Worker 	    if (*line_ptr == '\0')
72*6a54128fSAndroid Build Coastguard Worker 		goto end_of_line;
73*6a54128fSAndroid Build Coastguard Worker 	    if (*line_ptr == ' ' || *line_ptr == '\t') {
74*6a54128fSAndroid Build Coastguard Worker 		line_ptr++;
75*6a54128fSAndroid Build Coastguard Worker 		continue;
76*6a54128fSAndroid Build Coastguard Worker 	    }
77*6a54128fSAndroid Build Coastguard Worker 	    if (*line_ptr == '"') {
78*6a54128fSAndroid Build Coastguard Worker 		/* go to quoted-string mode */
79*6a54128fSAndroid Build Coastguard Worker 		parse_mode = QUOTED_STRING;
80*6a54128fSAndroid Build Coastguard Worker 		cp = line_ptr++;
81*6a54128fSAndroid Build Coastguard Worker 		new_argv = NEW_ARGV (argv, argc);
82*6a54128fSAndroid Build Coastguard Worker 		if (new_argv == NULL) {
83*6a54128fSAndroid Build Coastguard Worker 			free(argv);
84*6a54128fSAndroid Build Coastguard Worker 			*argc_ptr = 0;
85*6a54128fSAndroid Build Coastguard Worker 			return NULL;
86*6a54128fSAndroid Build Coastguard Worker 		}
87*6a54128fSAndroid Build Coastguard Worker 		argv = new_argv;
88*6a54128fSAndroid Build Coastguard Worker 		argv[argc++] = cp;
89*6a54128fSAndroid Build Coastguard Worker 		argv[argc] = NULL;
90*6a54128fSAndroid Build Coastguard Worker 	    }
91*6a54128fSAndroid Build Coastguard Worker 	    else {
92*6a54128fSAndroid Build Coastguard Worker 		/* random-token mode */
93*6a54128fSAndroid Build Coastguard Worker 		parse_mode = TOKEN;
94*6a54128fSAndroid Build Coastguard Worker 		cp = line_ptr;
95*6a54128fSAndroid Build Coastguard Worker 		new_argv = NEW_ARGV (argv, argc);
96*6a54128fSAndroid Build Coastguard Worker 		if (new_argv == NULL) {
97*6a54128fSAndroid Build Coastguard Worker 			free(argv);
98*6a54128fSAndroid Build Coastguard Worker 			*argc_ptr = 0;
99*6a54128fSAndroid Build Coastguard Worker 			return NULL;
100*6a54128fSAndroid Build Coastguard Worker 		}
101*6a54128fSAndroid Build Coastguard Worker 		argv = new_argv;
102*6a54128fSAndroid Build Coastguard Worker 		argv[argc++] = line_ptr;
103*6a54128fSAndroid Build Coastguard Worker 		argv[argc] = NULL;
104*6a54128fSAndroid Build Coastguard Worker 	    }
105*6a54128fSAndroid Build Coastguard Worker 	}
106*6a54128fSAndroid Build Coastguard Worker 	while (parse_mode == TOKEN) {
107*6a54128fSAndroid Build Coastguard Worker 	    if (*line_ptr == '\0') {
108*6a54128fSAndroid Build Coastguard Worker 		*cp++ = '\0';
109*6a54128fSAndroid Build Coastguard Worker 		goto end_of_line;
110*6a54128fSAndroid Build Coastguard Worker 	    }
111*6a54128fSAndroid Build Coastguard Worker 	    else if (*line_ptr == ' ' || *line_ptr == '\t') {
112*6a54128fSAndroid Build Coastguard Worker 		*cp++ = '\0';
113*6a54128fSAndroid Build Coastguard Worker 		line_ptr++;
114*6a54128fSAndroid Build Coastguard Worker 		parse_mode = WHITESPACE;
115*6a54128fSAndroid Build Coastguard Worker 	    }
116*6a54128fSAndroid Build Coastguard Worker 	    else if (*line_ptr == '"') {
117*6a54128fSAndroid Build Coastguard Worker 		line_ptr++;
118*6a54128fSAndroid Build Coastguard Worker 		parse_mode = QUOTED_STRING;
119*6a54128fSAndroid Build Coastguard Worker 	    }
120*6a54128fSAndroid Build Coastguard Worker 	    else {
121*6a54128fSAndroid Build Coastguard Worker 		*cp++ = *line_ptr++;
122*6a54128fSAndroid Build Coastguard Worker 	    }
123*6a54128fSAndroid Build Coastguard Worker 	}
124*6a54128fSAndroid Build Coastguard Worker 	while (parse_mode == QUOTED_STRING) {
125*6a54128fSAndroid Build Coastguard Worker 	    if (*line_ptr == '\0') {
126*6a54128fSAndroid Build Coastguard Worker 		ss_error (sci_idx, 0,
127*6a54128fSAndroid Build Coastguard Worker 			  "Unbalanced quotes in command line");
128*6a54128fSAndroid Build Coastguard Worker 		free (argv);
129*6a54128fSAndroid Build Coastguard Worker 		*argc_ptr = 0;
130*6a54128fSAndroid Build Coastguard Worker 		return NULL;
131*6a54128fSAndroid Build Coastguard Worker 	    }
132*6a54128fSAndroid Build Coastguard Worker 	    else if (*line_ptr == '"') {
133*6a54128fSAndroid Build Coastguard Worker 		if (*++line_ptr == '"') {
134*6a54128fSAndroid Build Coastguard Worker 		    *cp++ = '"';
135*6a54128fSAndroid Build Coastguard Worker 		    line_ptr++;
136*6a54128fSAndroid Build Coastguard Worker 		}
137*6a54128fSAndroid Build Coastguard Worker 		else {
138*6a54128fSAndroid Build Coastguard Worker 		    parse_mode = TOKEN;
139*6a54128fSAndroid Build Coastguard Worker 		}
140*6a54128fSAndroid Build Coastguard Worker 	    }
141*6a54128fSAndroid Build Coastguard Worker 	    else {
142*6a54128fSAndroid Build Coastguard Worker 		*cp++ = *line_ptr++;
143*6a54128fSAndroid Build Coastguard Worker 	    }
144*6a54128fSAndroid Build Coastguard Worker 	}
145*6a54128fSAndroid Build Coastguard Worker     }
146*6a54128fSAndroid Build Coastguard Worker end_of_line:
147*6a54128fSAndroid Build Coastguard Worker     *argc_ptr = argc;
148*6a54128fSAndroid Build Coastguard Worker #ifdef DEBUG
149*6a54128fSAndroid Build Coastguard Worker     {
150*6a54128fSAndroid Build Coastguard Worker 	int i;
151*6a54128fSAndroid Build Coastguard Worker 	printf ("argc = %d\n", argc);
152*6a54128fSAndroid Build Coastguard Worker 	for (i = 0; i <= argc; i++)
153*6a54128fSAndroid Build Coastguard Worker 	    printf ("\targv[%2d] = `%s'\n", i,
154*6a54128fSAndroid Build Coastguard Worker 		    argv[i] ? argv[i] : "<NULL>");
155*6a54128fSAndroid Build Coastguard Worker     }
156*6a54128fSAndroid Build Coastguard Worker #endif
157*6a54128fSAndroid Build Coastguard Worker     return(argv);
158*6a54128fSAndroid Build Coastguard Worker }
159