• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #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 
25 enum 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 
ss_parse(int sci_idx,register char * line_ptr,int * argc_ptr)46 char **ss_parse(int sci_idx, register char *line_ptr, int *argc_ptr)
47 {
48     register char **argv, **new_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 		new_argv = NEW_ARGV (argv, argc);
82 		if (new_argv == NULL) {
83 			free(argv);
84 			*argc_ptr = 0;
85 			return NULL;
86 		}
87 		argv = new_argv;
88 		argv[argc++] = cp;
89 		argv[argc] = NULL;
90 	    }
91 	    else {
92 		/* random-token mode */
93 		parse_mode = TOKEN;
94 		cp = line_ptr;
95 		new_argv = NEW_ARGV (argv, argc);
96 		if (new_argv == NULL) {
97 			free(argv);
98 			*argc_ptr = 0;
99 			return NULL;
100 		}
101 		argv = new_argv;
102 		argv[argc++] = line_ptr;
103 		argv[argc] = NULL;
104 	    }
105 	}
106 	while (parse_mode == TOKEN) {
107 	    if (*line_ptr == '\0') {
108 		*cp++ = '\0';
109 		goto end_of_line;
110 	    }
111 	    else if (*line_ptr == ' ' || *line_ptr == '\t') {
112 		*cp++ = '\0';
113 		line_ptr++;
114 		parse_mode = WHITESPACE;
115 	    }
116 	    else if (*line_ptr == '"') {
117 		line_ptr++;
118 		parse_mode = QUOTED_STRING;
119 	    }
120 	    else {
121 		*cp++ = *line_ptr++;
122 	    }
123 	}
124 	while (parse_mode == QUOTED_STRING) {
125 	    if (*line_ptr == '\0') {
126 		ss_error (sci_idx, 0,
127 			  "Unbalanced quotes in command line");
128 		free (argv);
129 		*argc_ptr = 0;
130 		return NULL;
131 	    }
132 	    else if (*line_ptr == '"') {
133 		if (*++line_ptr == '"') {
134 		    *cp++ = '"';
135 		    line_ptr++;
136 		}
137 		else {
138 		    parse_mode = TOKEN;
139 		}
140 	    }
141 	    else {
142 		*cp++ = *line_ptr++;
143 	    }
144 	}
145     }
146 end_of_line:
147     *argc_ptr = argc;
148 #ifdef DEBUG
149     {
150 	int i;
151 	printf ("argc = %d\n", argc);
152 	for (i = 0; i <= argc; i++)
153 	    printf ("\targv[%2d] = `%s'\n", i,
154 		    argv[i] ? argv[i] : "<NULL>");
155     }
156 #endif
157     return(argv);
158 }
159