159 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			159 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * 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);
 | |
| }
 |