1 /*
2 * Copyright 1987, 1988 by MIT Student Information Processing Board
3 *
4 * Permission to use, copy, modify, and distribute this software and
5 * its documentation for any purpose is hereby granted, provided that
6 * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
7 * advertising or publicity pertaining to distribution of the software
8 * without specific, written prior permission. M.I.T. and the
9 * M.I.T. S.I.P.B. make no representations about the suitability of
10 * this software for any purpose. It is provided "as is" without
11 * express or implied warranty.
12 */
13
14 #ifdef HAS_STDLIB_H
15 #include <stdlib.h>
16 #endif
17 #include <string.h>
18 #ifdef HAVE_ERRNO_H
19 #include <errno.h>
20 #endif
21
22 #include "ss_internal.h"
23
24 enum parse_mode { WHITESPACE, TOKEN, QUOTED_STRING };
25
26 /*
27 * parse(line_ptr, argc_ptr)
28 *
29 * Function:
30 * Parses line, dividing at whitespace, into tokens, returns
31 * the "argc" and "argv" values.
32 * Arguments:
33 * line_ptr (char *)
34 * Pointer to text string to be parsed.
35 * argc_ptr (int *)
36 * Where to put the "argc" (number of tokens) value.
37 * Returns:
38 * argv (char **)
39 * Series of pointers to parsed tokens.
40 */
41
42 #define NEW_ARGV(old,n) (char **)realloc((char *)old,\
43 (unsigned)(n+2)*sizeof(char*))
44
ss_parse(sci_idx,line_ptr,argc_ptr)45 char **ss_parse (sci_idx, line_ptr, argc_ptr)
46 int sci_idx;
47 register char *line_ptr;
48 int *argc_ptr;
49 {
50 register char **argv, *cp;
51 register int argc;
52 register enum parse_mode parse_mode;
53
54 argv = (char **) malloc (sizeof(char *));
55 if (argv == (char **)NULL) {
56 ss_error(sci_idx, errno, "Can't allocate storage");
57 *argc_ptr = 0;
58 return(argv);
59 }
60 *argv = (char *)NULL;
61
62 argc = 0;
63
64 parse_mode = WHITESPACE; /* flushing whitespace */
65 cp = line_ptr; /* cp is for output */
66 while (1) {
67 #ifdef DEBUG
68 {
69 printf ("character `%c', mode %d\n", *line_ptr, parse_mode);
70 }
71 #endif
72 while (parse_mode == WHITESPACE) {
73 if (*line_ptr == '\0')
74 goto end_of_line;
75 if (*line_ptr == ' ' || *line_ptr == '\t') {
76 line_ptr++;
77 continue;
78 }
79 if (*line_ptr == '"') {
80 /* go to quoted-string mode */
81 parse_mode = QUOTED_STRING;
82 cp = line_ptr++;
83 argv = NEW_ARGV (argv, argc);
84 argv[argc++] = cp;
85 argv[argc] = NULL;
86 }
87 else {
88 /* random-token mode */
89 parse_mode = TOKEN;
90 cp = line_ptr;
91 argv = NEW_ARGV (argv, argc);
92 argv[argc++] = line_ptr;
93 argv[argc] = NULL;
94 }
95 }
96 while (parse_mode == TOKEN) {
97 if (*line_ptr == '\0') {
98 *cp++ = '\0';
99 goto end_of_line;
100 }
101 else if (*line_ptr == ' ' || *line_ptr == '\t') {
102 *cp++ = '\0';
103 line_ptr++;
104 parse_mode = WHITESPACE;
105 }
106 else if (*line_ptr == '"') {
107 line_ptr++;
108 parse_mode = QUOTED_STRING;
109 }
110 else {
111 *cp++ = *line_ptr++;
112 }
113 }
114 while (parse_mode == QUOTED_STRING) {
115 if (*line_ptr == '\0') {
116 ss_error (sci_idx, 0,
117 "Unbalanced quotes in command line");
118 free (argv);
119 *argc_ptr = 0;
120 return NULL;
121 }
122 else if (*line_ptr == '"') {
123 if (*++line_ptr == '"') {
124 *cp++ = '"';
125 line_ptr++;
126 }
127 else {
128 parse_mode = TOKEN;
129 }
130 }
131 else {
132 *cp++ = *line_ptr++;
133 }
134 }
135 }
136 end_of_line:
137 *argc_ptr = argc;
138 #ifdef DEBUG
139 {
140 int i;
141 printf ("argc = %d\n", argc);
142 for (i = 0; i <= argc; i++)
143 printf ("\targv[%2d] = `%s'\n", i,
144 argv[i] ? argv[i] : "<NULL>");
145 }
146 #endif
147 return(argv);
148 }
149