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