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