blob: df420aabfae60b8de43b8b54b2b50c03eab2385c [file] [log] [blame]
Theodore Ts'o3839e651997-04-26 13:21:57 +00001/*
2 * Copyright 1987, 1988 by MIT Student Information Processing Board
3 *
Theodore Ts'o27401561999-09-14 20:11:19 +00004 * This file may be copied under the terms of the GNU Public License.
Theodore Ts'o3839e651997-04-26 13:21:57 +00005 */
6
Theodore Ts'of3db3561997-04-26 13:34:30 +00007#ifdef HAS_STDLIB_H
8#include <stdlib.h>
9#endif
Theodore Ts'o19c78dc1997-04-29 16:17:09 +000010#include <string.h>
Theodore Ts'o50e1e101997-04-26 13:58:21 +000011#ifdef HAVE_ERRNO_H
12#include <errno.h>
13#endif
Theodore Ts'of3db3561997-04-26 13:34:30 +000014
Theodore Ts'o3839e651997-04-26 13:21:57 +000015#include "ss_internal.h"
Theodore Ts'o3839e651997-04-26 13:21:57 +000016
Theodore Ts'o3839e651997-04-26 13:21:57 +000017enum parse_mode { WHITESPACE, TOKEN, QUOTED_STRING };
18
19/*
20 * parse(line_ptr, argc_ptr)
21 *
22 * Function:
23 * Parses line, dividing at whitespace, into tokens, returns
24 * the "argc" and "argv" values.
25 * Arguments:
26 * line_ptr (char *)
27 * Pointer to text string to be parsed.
28 * argc_ptr (int *)
29 * Where to put the "argc" (number of tokens) value.
30 * Returns:
31 * argv (char **)
32 * Series of pointers to parsed tokens.
33 */
34
35#define NEW_ARGV(old,n) (char **)realloc((char *)old,\
36 (unsigned)(n+2)*sizeof(char*))
37
38char **ss_parse (sci_idx, line_ptr, argc_ptr)
39 int sci_idx;
40 register char *line_ptr;
41 int *argc_ptr;
42{
43 register char **argv, *cp;
44 register int argc;
45 register enum parse_mode parse_mode;
46
47 argv = (char **) malloc (sizeof(char *));
48 if (argv == (char **)NULL) {
49 ss_error(sci_idx, errno, "Can't allocate storage");
50 *argc_ptr = 0;
51 return(argv);
52 }
53 *argv = (char *)NULL;
54
55 argc = 0;
56
57 parse_mode = WHITESPACE; /* flushing whitespace */
58 cp = line_ptr; /* cp is for output */
59 while (1) {
60#ifdef DEBUG
61 {
62 printf ("character `%c', mode %d\n", *line_ptr, parse_mode);
63 }
64#endif
65 while (parse_mode == WHITESPACE) {
66 if (*line_ptr == '\0')
67 goto end_of_line;
68 if (*line_ptr == ' ' || *line_ptr == '\t') {
69 line_ptr++;
70 continue;
71 }
72 if (*line_ptr == '"') {
73 /* go to quoted-string mode */
74 parse_mode = QUOTED_STRING;
75 cp = line_ptr++;
76 argv = NEW_ARGV (argv, argc);
77 argv[argc++] = cp;
78 argv[argc] = NULL;
79 }
80 else {
81 /* random-token mode */
82 parse_mode = TOKEN;
83 cp = line_ptr;
84 argv = NEW_ARGV (argv, argc);
85 argv[argc++] = line_ptr;
86 argv[argc] = NULL;
87 }
88 }
89 while (parse_mode == TOKEN) {
90 if (*line_ptr == '\0') {
91 *cp++ = '\0';
92 goto end_of_line;
93 }
94 else if (*line_ptr == ' ' || *line_ptr == '\t') {
95 *cp++ = '\0';
96 line_ptr++;
97 parse_mode = WHITESPACE;
98 }
99 else if (*line_ptr == '"') {
100 line_ptr++;
101 parse_mode = QUOTED_STRING;
102 }
103 else {
104 *cp++ = *line_ptr++;
105 }
106 }
107 while (parse_mode == QUOTED_STRING) {
108 if (*line_ptr == '\0') {
109 ss_error (sci_idx, 0,
110 "Unbalanced quotes in command line");
111 free (argv);
112 *argc_ptr = 0;
113 return NULL;
114 }
115 else if (*line_ptr == '"') {
116 if (*++line_ptr == '"') {
117 *cp++ = '"';
118 line_ptr++;
119 }
120 else {
121 parse_mode = TOKEN;
122 }
123 }
124 else {
125 *cp++ = *line_ptr++;
126 }
127 }
128 }
129end_of_line:
130 *argc_ptr = argc;
131#ifdef DEBUG
132 {
133 int i;
134 printf ("argc = %d\n", argc);
135 for (i = 0; i <= argc; i++)
136 printf ("\targv[%2d] = `%s'\n", i,
137 argv[i] ? argv[i] : "<NULL>");
138 }
139#endif
140 return(argv);
141}