xref: /freebsd/crypto/krb5/src/util/ss/parse.c (revision f1c4c3daccbaf3820f0e2224de53df12fc952fcc)
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 
56 char **
ss_parse(int sci_idx,char * line_ptr,int * argc_ptr)57 ss_parse(int sci_idx, char *line_ptr, int *argc_ptr)
58 {
59     char **argv, *cp;
60     char **newargv;
61     int argc;
62     enum parse_mode parse_mode;
63 
64     argv = (char **) malloc (sizeof(char *));
65     if (argv == (char **)NULL) {
66         ss_error(sci_idx, errno, "Can't allocate storage");
67         *argc_ptr = 0;
68         return(argv);
69     }
70     *argv = (char *)NULL;
71 
72     argc = 0;
73 
74     parse_mode = WHITESPACE;    /* flushing whitespace */
75     cp = line_ptr;              /* cp is for output */
76     while (1) {
77 #ifdef DEBUG
78         {
79             printf ("character `%c', mode %d\n", *line_ptr, parse_mode);
80         }
81 #endif
82         while (parse_mode == WHITESPACE) {
83             if (*line_ptr == '\0')
84                 goto end_of_line;
85             if (*line_ptr == ' ' || *line_ptr == '\t') {
86                 line_ptr++;
87                 continue;
88             }
89             if (*line_ptr == '"') {
90                 /* go to quoted-string mode */
91                 parse_mode = QUOTED_STRING;
92                 cp = line_ptr++;
93                 newargv = NEW_ARGV (argv, argc);
94                 if (newargv == NULL) {
95                 out_of_mem_in_argv:
96                     free(argv);
97                     ss_error(sci_idx, errno, "Can't allocate storage");
98                     *argc_ptr = 0;
99                     return NULL;
100                 }
101                 argv = newargv;
102                 argv[argc++] = cp;
103                 argv[argc] = NULL;
104             }
105             else {
106                 /* random-token mode */
107                 parse_mode = TOKEN;
108                 cp = line_ptr;
109                 newargv = NEW_ARGV (argv, argc);
110                 if (newargv == NULL)
111                     goto out_of_mem_in_argv;
112                 argv = newargv;
113                 argv[argc++] = line_ptr;
114                 argv[argc] = NULL;
115             }
116         }
117         while (parse_mode == TOKEN) {
118             if (*line_ptr == '\0') {
119                 *cp++ = '\0';
120                 goto end_of_line;
121             }
122             else if (*line_ptr == ' ' || *line_ptr == '\t') {
123                 *cp++ = '\0';
124                 line_ptr++;
125                 parse_mode = WHITESPACE;
126             }
127             else if (*line_ptr == '"') {
128                 line_ptr++;
129                 parse_mode = QUOTED_STRING;
130             }
131             else {
132                 *cp++ = *line_ptr++;
133             }
134         }
135         while (parse_mode == QUOTED_STRING) {
136             if (*line_ptr == '\0') {
137                 ss_error (sci_idx, 0,
138                           "Unbalanced quotes in command line");
139                 free (argv);
140                 *argc_ptr = 0;
141                 return NULL;
142             }
143             else if (*line_ptr == '"') {
144                 if (*++line_ptr == '"') {
145                     *cp++ = '"';
146                     line_ptr++;
147                 }
148                 else {
149                     parse_mode = TOKEN;
150                 }
151             }
152             else {
153                 *cp++ = *line_ptr++;
154             }
155         }
156     }
157 end_of_line:
158     *argc_ptr = argc;
159 #ifdef DEBUG
160     {
161         int i;
162         printf ("argc = %d\n", argc);
163         for (i = 0; i <= argc; i++)
164             printf ("\targv[%2d] = `%s'\n", i,
165                     argv[i] ? argv[i] : "<NULL>");
166     }
167 #endif
168     return(argv);
169 }
170