xref: /freebsd/crypto/krb5/src/util/ss/parse.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  * Copyright 2007 Massachusetts Institute of Technology.
4  * All Rights Reserved.
5  *
6  * Export of this software from the United States of America may
7  *   require a specific license from the United States Government.
8  *   It is the responsibility of any person or organization contemplating
9  *   export to obtain such a license before exporting.
10  *
11  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
12  * distribute this software and its documentation for any purpose and
13  * without fee is hereby granted, provided that the above copyright
14  * notice appear in all copies and that both that copyright notice and
15  * this permission notice appear in supporting documentation, and that
16  * the name of M.I.T. not be used in advertising or publicity pertaining
17  * to distribution of the software without specific, written prior
18  * permission.  Furthermore if you modify this software you must label
19  * your software as modified software and not distribute it in such a
20  * fashion that it might be confused with the original M.I.T. software.
21  * M.I.T. makes no representations about the suitability of
22  * this software for any purpose.  It is provided "as is" without express
23  * or implied warranty.
24  */
25 /*
26  * Copyright 1987, 1988 by MIT Student Information Processing Board
27  *
28  * For copyright info, see copyright.h.
29  */
30 
31 #include "ss_internal.h"
32 #include "copyright.h"
33 #include <errno.h>
34 
35 enum parse_mode { WHITESPACE, TOKEN, QUOTED_STRING };
36 
37 /*
38  * parse(line_ptr, argc_ptr)
39  *
40  * Function:
41  *      Parses line, dividing at whitespace, into tokens, returns
42  *      the "argc" and "argv" values.
43  * Arguments:
44  *      line_ptr (char *)
45  *              Pointer to text string to be parsed.
46  *      argc_ptr (int *)
47  *              Where to put the "argc" (number of tokens) value.
48  * Returns:
49  *      argv (char **)
50  *              Series of pointers to parsed tokens in the original string.
51  */
52 
53 #define NEW_ARGV(old,n) (char **)realloc((char *)old,                   \
54                                          (unsigned)(n+2)*sizeof(char*))
55 
ss_parse(sci_idx,line_ptr,argc_ptr)56 char **ss_parse (sci_idx, line_ptr, argc_ptr)
57     int sci_idx;
58     char *line_ptr;
59     int *argc_ptr;
60 {
61     char **argv, *cp;
62     char **newargv;
63     int argc;
64     enum parse_mode parse_mode;
65 
66     argv = (char **) malloc (sizeof(char *));
67     if (argv == (char **)NULL) {
68         ss_error(sci_idx, errno, "Can't allocate storage");
69         *argc_ptr = 0;
70         return(argv);
71     }
72     *argv = (char *)NULL;
73 
74     argc = 0;
75 
76     parse_mode = WHITESPACE;    /* flushing whitespace */
77     cp = line_ptr;              /* cp is for output */
78     while (1) {
79 #ifdef DEBUG
80         {
81             printf ("character `%c', mode %d\n", *line_ptr, parse_mode);
82         }
83 #endif
84         while (parse_mode == WHITESPACE) {
85             if (*line_ptr == '\0')
86                 goto end_of_line;
87             if (*line_ptr == ' ' || *line_ptr == '\t') {
88                 line_ptr++;
89                 continue;
90             }
91             if (*line_ptr == '"') {
92                 /* go to quoted-string mode */
93                 parse_mode = QUOTED_STRING;
94                 cp = line_ptr++;
95                 newargv = NEW_ARGV (argv, argc);
96                 if (newargv == NULL) {
97                 out_of_mem_in_argv:
98                     free(argv);
99                     ss_error(sci_idx, errno, "Can't allocate storage");
100                     *argc_ptr = 0;
101                     return NULL;
102                 }
103                 argv = newargv;
104                 argv[argc++] = cp;
105                 argv[argc] = NULL;
106             }
107             else {
108                 /* random-token mode */
109                 parse_mode = TOKEN;
110                 cp = line_ptr;
111                 newargv = NEW_ARGV (argv, argc);
112                 if (newargv == NULL)
113                     goto out_of_mem_in_argv;
114                 argv = newargv;
115                 argv[argc++] = line_ptr;
116                 argv[argc] = NULL;
117             }
118         }
119         while (parse_mode == TOKEN) {
120             if (*line_ptr == '\0') {
121                 *cp++ = '\0';
122                 goto end_of_line;
123             }
124             else if (*line_ptr == ' ' || *line_ptr == '\t') {
125                 *cp++ = '\0';
126                 line_ptr++;
127                 parse_mode = WHITESPACE;
128             }
129             else if (*line_ptr == '"') {
130                 line_ptr++;
131                 parse_mode = QUOTED_STRING;
132             }
133             else {
134                 *cp++ = *line_ptr++;
135             }
136         }
137         while (parse_mode == QUOTED_STRING) {
138             if (*line_ptr == '\0') {
139                 ss_error (sci_idx, 0,
140                           "Unbalanced quotes in command line");
141                 free (argv);
142                 *argc_ptr = 0;
143                 return NULL;
144             }
145             else if (*line_ptr == '"') {
146                 if (*++line_ptr == '"') {
147                     *cp++ = '"';
148                     line_ptr++;
149                 }
150                 else {
151                     parse_mode = TOKEN;
152                 }
153             }
154             else {
155                 *cp++ = *line_ptr++;
156             }
157         }
158     }
159 end_of_line:
160     *argc_ptr = argc;
161 #ifdef DEBUG
162     {
163         int i;
164         printf ("argc = %d\n", argc);
165         for (i = 0; i <= argc; i++)
166             printf ("\targv[%2d] = `%s'\n", i,
167                     argv[i] ? argv[i] : "<NULL>");
168     }
169 #endif
170     return(argv);
171 }
172