blob: e2928e22943c6bf9f462ba52d2b7f202768ff87b [file] [log] [blame]
yuezonghe824eb0c2024-06-27 02:32:26 -07001/*
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#include "config.h"
15#ifdef HAS_STDLIB_H
16#include <stdlib.h>
17#endif
18#include <string.h>
19#ifdef HAVE_ERRNO_H
20#include <errno.h>
21#endif
22
23#include "ss_internal.h"
24
25enum parse_mode { WHITESPACE, TOKEN, QUOTED_STRING };
26
27/*
28 * parse(line_ptr, argc_ptr)
29 *
30 * Function:
31 * Parses line, dividing at whitespace, into tokens, returns
32 * the "argc" and "argv" values.
33 * Arguments:
34 * line_ptr (char *)
35 * Pointer to text string to be parsed.
36 * argc_ptr (int *)
37 * Where to put the "argc" (number of tokens) value.
38 * Returns:
39 * argv (char **)
40 * Series of pointers to parsed tokens.
41 */
42
43#define NEW_ARGV(old,n) (char **)realloc((char *)old,\
44 (unsigned)(n+2)*sizeof(char*))
45
46char **ss_parse(int sci_idx, register char *line_ptr, int *argc_ptr)
47{
48 register char **argv, *cp;
49 register int argc;
50 register enum parse_mode parse_mode;
51
52 argv = (char **) malloc (sizeof(char *));
53 if (argv == (char **)NULL) {
54 ss_error(sci_idx, errno, "Can't allocate storage");
55 *argc_ptr = 0;
56 return(argv);
57 }
58 *argv = (char *)NULL;
59
60 argc = 0;
61
62 parse_mode = WHITESPACE; /* flushing whitespace */
63 cp = line_ptr; /* cp is for output */
64 while (1) {
65#ifdef DEBUG
66 {
67 printf ("character `%c', mode %d\n", *line_ptr, parse_mode);
68 }
69#endif
70 while (parse_mode == WHITESPACE) {
71 if (*line_ptr == '\0')
72 goto end_of_line;
73 if (*line_ptr == ' ' || *line_ptr == '\t') {
74 line_ptr++;
75 continue;
76 }
77 if (*line_ptr == '"') {
78 /* go to quoted-string mode */
79 parse_mode = QUOTED_STRING;
80 cp = line_ptr++;
81 argv = NEW_ARGV (argv, argc);
82 argv[argc++] = cp;
83 argv[argc] = NULL;
84 }
85 else {
86 /* random-token mode */
87 parse_mode = TOKEN;
88 cp = line_ptr;
89 argv = NEW_ARGV (argv, argc);
90 if (argv == NULL) {
91 *argc_ptr = errno;
92 return argv;
93 }
94 argv[argc++] = line_ptr;
95 argv[argc] = NULL;
96 }
97 }
98 while (parse_mode == TOKEN) {
99 if (*line_ptr == '\0') {
100 *cp++ = '\0';
101 goto end_of_line;
102 }
103 else if (*line_ptr == ' ' || *line_ptr == '\t') {
104 *cp++ = '\0';
105 line_ptr++;
106 parse_mode = WHITESPACE;
107 }
108 else if (*line_ptr == '"') {
109 line_ptr++;
110 parse_mode = QUOTED_STRING;
111 }
112 else {
113 *cp++ = *line_ptr++;
114 }
115 }
116 while (parse_mode == QUOTED_STRING) {
117 if (*line_ptr == '\0') {
118 ss_error (sci_idx, 0,
119 "Unbalanced quotes in command line");
120 free (argv);
121 *argc_ptr = 0;
122 return NULL;
123 }
124 else if (*line_ptr == '"') {
125 if (*++line_ptr == '"') {
126 *cp++ = '"';
127 line_ptr++;
128 }
129 else {
130 parse_mode = TOKEN;
131 }
132 }
133 else {
134 *cp++ = *line_ptr++;
135 }
136 }
137 }
138end_of_line:
139 *argc_ptr = argc;
140#ifdef DEBUG
141 {
142 int i;
143 printf ("argc = %d\n", argc);
144 for (i = 0; i <= argc; i++)
145 printf ("\targv[%2d] = `%s'\n", i,
146 argv[i] ? argv[i] : "<NULL>");
147 }
148#endif
149 return(argv);
150}