You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
3.5 KiB
159 lines
3.5 KiB
/*
|
|
* Copyright 1987, 1988 by MIT Student Information Processing Board
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software and
|
|
* its documentation for any purpose is hereby granted, provided that
|
|
* the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
|
|
* advertising or publicity pertaining to distribution of the software
|
|
* without specific, written prior permission. M.I.T. and the
|
|
* M.I.T. S.I.P.B. make no representations about the suitability of
|
|
* this software for any purpose. It is provided "as is" without
|
|
* express or implied warranty.
|
|
*/
|
|
|
|
#include "config.h"
|
|
#ifdef HAS_STDLIB_H
|
|
#include <stdlib.h>
|
|
#endif
|
|
#include <string.h>
|
|
#ifdef HAVE_ERRNO_H
|
|
#include <errno.h>
|
|
#endif
|
|
|
|
#include "ss_internal.h"
|
|
|
|
enum parse_mode { WHITESPACE, TOKEN, QUOTED_STRING };
|
|
|
|
/*
|
|
* parse(line_ptr, argc_ptr)
|
|
*
|
|
* Function:
|
|
* Parses line, dividing at whitespace, into tokens, returns
|
|
* the "argc" and "argv" values.
|
|
* Arguments:
|
|
* line_ptr (char *)
|
|
* Pointer to text string to be parsed.
|
|
* argc_ptr (int *)
|
|
* Where to put the "argc" (number of tokens) value.
|
|
* Returns:
|
|
* argv (char **)
|
|
* Series of pointers to parsed tokens.
|
|
*/
|
|
|
|
#define NEW_ARGV(old,n) (char **)realloc((char *)old,\
|
|
(unsigned)(n+2)*sizeof(char*))
|
|
|
|
char **ss_parse(int sci_idx, register char *line_ptr, int *argc_ptr)
|
|
{
|
|
register char **argv, **new_argv, *cp;
|
|
register int argc;
|
|
register enum parse_mode parse_mode;
|
|
|
|
argv = (char **) malloc (sizeof(char *));
|
|
if (argv == (char **)NULL) {
|
|
ss_error(sci_idx, errno, "Can't allocate storage");
|
|
*argc_ptr = 0;
|
|
return(argv);
|
|
}
|
|
*argv = (char *)NULL;
|
|
|
|
argc = 0;
|
|
|
|
parse_mode = WHITESPACE; /* flushing whitespace */
|
|
cp = line_ptr; /* cp is for output */
|
|
while (1) {
|
|
#ifdef DEBUG
|
|
{
|
|
printf ("character `%c', mode %d\n", *line_ptr, parse_mode);
|
|
}
|
|
#endif
|
|
while (parse_mode == WHITESPACE) {
|
|
if (*line_ptr == '\0')
|
|
goto end_of_line;
|
|
if (*line_ptr == ' ' || *line_ptr == '\t') {
|
|
line_ptr++;
|
|
continue;
|
|
}
|
|
if (*line_ptr == '"') {
|
|
/* go to quoted-string mode */
|
|
parse_mode = QUOTED_STRING;
|
|
cp = line_ptr++;
|
|
new_argv = NEW_ARGV (argv, argc);
|
|
if (new_argv == NULL) {
|
|
free(argv);
|
|
*argc_ptr = 0;
|
|
return NULL;
|
|
}
|
|
argv = new_argv;
|
|
argv[argc++] = cp;
|
|
argv[argc] = NULL;
|
|
}
|
|
else {
|
|
/* random-token mode */
|
|
parse_mode = TOKEN;
|
|
cp = line_ptr;
|
|
new_argv = NEW_ARGV (argv, argc);
|
|
if (new_argv == NULL) {
|
|
free(argv);
|
|
*argc_ptr = 0;
|
|
return NULL;
|
|
}
|
|
argv = new_argv;
|
|
argv[argc++] = line_ptr;
|
|
argv[argc] = NULL;
|
|
}
|
|
}
|
|
while (parse_mode == TOKEN) {
|
|
if (*line_ptr == '\0') {
|
|
*cp++ = '\0';
|
|
goto end_of_line;
|
|
}
|
|
else if (*line_ptr == ' ' || *line_ptr == '\t') {
|
|
*cp++ = '\0';
|
|
line_ptr++;
|
|
parse_mode = WHITESPACE;
|
|
}
|
|
else if (*line_ptr == '"') {
|
|
line_ptr++;
|
|
parse_mode = QUOTED_STRING;
|
|
}
|
|
else {
|
|
*cp++ = *line_ptr++;
|
|
}
|
|
}
|
|
while (parse_mode == QUOTED_STRING) {
|
|
if (*line_ptr == '\0') {
|
|
ss_error (sci_idx, 0,
|
|
"Unbalanced quotes in command line");
|
|
free (argv);
|
|
*argc_ptr = 0;
|
|
return NULL;
|
|
}
|
|
else if (*line_ptr == '"') {
|
|
if (*++line_ptr == '"') {
|
|
*cp++ = '"';
|
|
line_ptr++;
|
|
}
|
|
else {
|
|
parse_mode = TOKEN;
|
|
}
|
|
}
|
|
else {
|
|
*cp++ = *line_ptr++;
|
|
}
|
|
}
|
|
}
|
|
end_of_line:
|
|
*argc_ptr = argc;
|
|
#ifdef DEBUG
|
|
{
|
|
int i;
|
|
printf ("argc = %d\n", argc);
|
|
for (i = 0; i <= argc; i++)
|
|
printf ("\targv[%2d] = `%s'\n", i,
|
|
argv[i] ? argv[i] : "<NULL>");
|
|
}
|
|
#endif
|
|
return(argv);
|
|
}
|