• 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 #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(int sci_idx,register char * line_ptr,int * argc_ptr)45 char **ss_parse(int sci_idx, register char *line_ptr, int *argc_ptr)
46 {
47     register char **argv, *cp;
48     register int argc;
49     register enum parse_mode parse_mode;
50 
51     argv = (char **) malloc (sizeof(char *));
52     if (argv == (char **)NULL) {
53 	ss_error(sci_idx, errno, "Can't allocate storage");
54 	*argc_ptr = 0;
55 	return(argv);
56     }
57     *argv = (char *)NULL;
58 
59     argc = 0;
60 
61     parse_mode = WHITESPACE;	/* flushing whitespace */
62     cp = line_ptr;		/* cp is for output */
63     while (1) {
64 #ifdef DEBUG
65 	{
66 	    printf ("character `%c', mode %d\n", *line_ptr, parse_mode);
67 	}
68 #endif
69 	while (parse_mode == WHITESPACE) {
70 	    if (*line_ptr == '\0')
71 		goto end_of_line;
72 	    if (*line_ptr == ' ' || *line_ptr == '\t') {
73 		line_ptr++;
74 		continue;
75 	    }
76 	    if (*line_ptr == '"') {
77 		/* go to quoted-string mode */
78 		parse_mode = QUOTED_STRING;
79 		cp = line_ptr++;
80 		argv = NEW_ARGV (argv, argc);
81 		argv[argc++] = cp;
82 		argv[argc] = NULL;
83 	    }
84 	    else {
85 		/* random-token mode */
86 		parse_mode = TOKEN;
87 		cp = line_ptr;
88 		argv = NEW_ARGV (argv, argc);
89 		if (argv == NULL) {
90 			*argc_ptr = errno;
91 			return argv;
92 		}
93 		argv[argc++] = line_ptr;
94 		argv[argc] = NULL;
95 	    }
96 	}
97 	while (parse_mode == TOKEN) {
98 	    if (*line_ptr == '\0') {
99 		*cp++ = '\0';
100 		goto end_of_line;
101 	    }
102 	    else if (*line_ptr == ' ' || *line_ptr == '\t') {
103 		*cp++ = '\0';
104 		line_ptr++;
105 		parse_mode = WHITESPACE;
106 	    }
107 	    else if (*line_ptr == '"') {
108 		line_ptr++;
109 		parse_mode = QUOTED_STRING;
110 	    }
111 	    else {
112 		*cp++ = *line_ptr++;
113 	    }
114 	}
115 	while (parse_mode == QUOTED_STRING) {
116 	    if (*line_ptr == '\0') {
117 		ss_error (sci_idx, 0,
118 			  "Unbalanced quotes in command line");
119 		free (argv);
120 		*argc_ptr = 0;
121 		return NULL;
122 	    }
123 	    else if (*line_ptr == '"') {
124 		if (*++line_ptr == '"') {
125 		    *cp++ = '"';
126 		    line_ptr++;
127 		}
128 		else {
129 		    parse_mode = TOKEN;
130 		}
131 	    }
132 	    else {
133 		*cp++ = *line_ptr++;
134 	    }
135 	}
136     }
137 end_of_line:
138     *argc_ptr = argc;
139 #ifdef DEBUG
140     {
141 	int i;
142 	printf ("argc = %d\n", argc);
143 	for (i = 0; i <= argc; i++)
144 	    printf ("\targv[%2d] = `%s'\n", i,
145 		    argv[i] ? argv[i] : "<NULL>");
146     }
147 #endif
148     return(argv);
149 }
150