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