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