119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Copyright 1987, 1988 by MIT Student Information Processing Board
319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Permission to use, copy, modify, and distribute this software and
519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * its documentation for any purpose is hereby granted, provided that
619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * advertising or publicity pertaining to distribution of the software
819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * without specific, written prior permission.  M.I.T. and the
919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * M.I.T. S.I.P.B. make no representations about the suitability of
1019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * this software for any purpose.  It is provided "as is" without
1119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * express or implied warranty.
1219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
1319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
1419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef HAS_STDLIB_H
1519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdlib.h>
1619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
1719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <string.h>
1819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef HAVE_ERRNO_H
1919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <errno.h>
2019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
2119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "ss_internal.h"
2319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectenum parse_mode { WHITESPACE, TOKEN, QUOTED_STRING };
2519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
2719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * parse(line_ptr, argc_ptr)
2819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
2919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Function:
3019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *      Parses line, dividing at whitespace, into tokens, returns
3119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *      the "argc" and "argv" values.
3219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Arguments:
3319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *      line_ptr (char *)
3419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *              Pointer to text string to be parsed.
3519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *      argc_ptr (int *)
3619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *              Where to put the "argc" (number of tokens) value.
3719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Returns:
3819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *      argv (char **)
3919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *              Series of pointers to parsed tokens.
4019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
4119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
4219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#define NEW_ARGV(old,n) (char **)realloc((char *)old,\
4319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					 (unsigned)(n+2)*sizeof(char*))
4419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
4519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectchar **ss_parse (sci_idx, line_ptr, argc_ptr)
4619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project    int sci_idx;
4719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project    register char *line_ptr;
4819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project    int *argc_ptr;
4919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
5019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project    register char **argv, *cp;
5119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project    register int argc;
5219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project    register enum parse_mode parse_mode;
5319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
5419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project    argv = (char **) malloc (sizeof(char *));
5519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project    if (argv == (char **)NULL) {
5619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ss_error(sci_idx, errno, "Can't allocate storage");
5719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	*argc_ptr = 0;
5819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return(argv);
5919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project    }
6019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project    *argv = (char *)NULL;
6119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
6219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project    argc = 0;
6319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
6419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project    parse_mode = WHITESPACE;	/* flushing whitespace */
6519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project    cp = line_ptr;		/* cp is for output */
6619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project    while (1) {
6719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef DEBUG
6819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	{
6919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    printf ("character `%c', mode %d\n", *line_ptr, parse_mode);
7019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
7119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
7219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	while (parse_mode == WHITESPACE) {
7319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    if (*line_ptr == '\0')
7419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		goto end_of_line;
7519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    if (*line_ptr == ' ' || *line_ptr == '\t') {
7619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		line_ptr++;
7719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		continue;
7819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    }
7919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    if (*line_ptr == '"') {
8019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		/* go to quoted-string mode */
8119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		parse_mode = QUOTED_STRING;
8219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		cp = line_ptr++;
8319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		argv = NEW_ARGV (argv, argc);
8419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		argv[argc++] = cp;
8519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		argv[argc] = NULL;
8619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    }
8719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    else {
8819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		/* random-token mode */
8919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		parse_mode = TOKEN;
9019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		cp = line_ptr;
9119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		argv = NEW_ARGV (argv, argc);
9219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		argv[argc++] = line_ptr;
9319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		argv[argc] = NULL;
9419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    }
9519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
9619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	while (parse_mode == TOKEN) {
9719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    if (*line_ptr == '\0') {
9819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		*cp++ = '\0';
9919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		goto end_of_line;
10019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    }
10119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    else if (*line_ptr == ' ' || *line_ptr == '\t') {
10219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		*cp++ = '\0';
10319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		line_ptr++;
10419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		parse_mode = WHITESPACE;
10519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    }
10619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    else if (*line_ptr == '"') {
10719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		line_ptr++;
10819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		parse_mode = QUOTED_STRING;
10919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    }
11019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    else {
11119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		*cp++ = *line_ptr++;
11219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    }
11319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
11419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	while (parse_mode == QUOTED_STRING) {
11519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    if (*line_ptr == '\0') {
11619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ss_error (sci_idx, 0,
11719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			  "Unbalanced quotes in command line");
11819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		free (argv);
11919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		*argc_ptr = 0;
12019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return NULL;
12119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    }
12219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    else if (*line_ptr == '"') {
12319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (*++line_ptr == '"') {
12419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    *cp++ = '"';
12519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    line_ptr++;
12619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
12719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		else {
12819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    parse_mode = TOKEN;
12919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
13019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    }
13119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    else {
13219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		*cp++ = *line_ptr++;
13319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    }
13419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
13519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project    }
13619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectend_of_line:
13719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project    *argc_ptr = argc;
13819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef DEBUG
13919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project    {
14019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int i;
14119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	printf ("argc = %d\n", argc);
14219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	for (i = 0; i <= argc; i++)
14319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    printf ("\targv[%2d] = `%s'\n", i,
14419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    argv[i] ? argv[i] : "<NULL>");
14519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project    }
14619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
14719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project    return(argv);
14819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
149