parse.c revision d1154eb460efe588eaed3d439c1caaca149fa362
16fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org/*
26fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * Copyright 1987, 1988 by MIT Student Information Processing Board
36fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org *
46fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * Permission to use, copy, modify, and distribute this software and
56fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * its documentation for any purpose is hereby granted, provided that
66fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
76fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * advertising or publicity pertaining to distribution of the software
86fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * without specific, written prior permission.  M.I.T. and the
96fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * M.I.T. S.I.P.B. make no representations about the suitability of
106fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * this software for any purpose.  It is provided "as is" without
1190c5310de3dfbd1b1624502616cbc8aaf9ad25f0johannkoenig@chromium.org * express or implied warranty.
1290c5310de3dfbd1b1624502616cbc8aaf9ad25f0johannkoenig@chromium.org */
1393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org
1493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include "config.h"
1593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#ifdef HAS_STDLIB_H
1693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include <stdlib.h>
1793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
1893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include <string.h>
196fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#ifdef HAVE_ERRNO_H
2093a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#include <errno.h>
2193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
22693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com
236fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#include "ss_internal.h"
246fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org
256fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.orgenum parse_mode { WHITESPACE, TOKEN, QUOTED_STRING };
26693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com
2741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org/*
287765c078fa920ba6c949c15f16b6cc979d8bb95bjohannkoenig@chromium.org * parse(line_ptr, argc_ptr)
297765c078fa920ba6c949c15f16b6cc979d8bb95bjohannkoenig@chromium.org *
307765c078fa920ba6c949c15f16b6cc979d8bb95bjohannkoenig@chromium.org * Function:
317765c078fa920ba6c949c15f16b6cc979d8bb95bjohannkoenig@chromium.org *      Parses line, dividing at whitespace, into tokens, returns
327765c078fa920ba6c949c15f16b6cc979d8bb95bjohannkoenig@chromium.org *      the "argc" and "argv" values.
336fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org * Arguments:
346fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org *      line_ptr (char *)
356fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org *              Pointer to text string to be parsed.
36dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org *      argc_ptr (int *)
3776e516e2154f353aa02c504bac88afb0f95fefa7johannkoenig@chromium.org *              Where to put the "argc" (number of tokens) value.
3893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org * Returns:
39dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org *      argv (char **)
406fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org *              Series of pointers to parsed tokens.
417765c078fa920ba6c949c15f16b6cc979d8bb95bjohannkoenig@chromium.org */
427765c078fa920ba6c949c15f16b6cc979d8bb95bjohannkoenig@chromium.org
4393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#define NEW_ARGV(old,n) (char **)realloc((char *)old,\
446fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org					 (unsigned)(n+2)*sizeof(char*))
45dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org
46dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.orgchar **ss_parse (sci_idx, line_ptr, argc_ptr)
476fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    int sci_idx;
48dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org    register char *line_ptr;
496fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    int *argc_ptr;
506fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org{
51693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com    register char **argv, *cp;
52693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com    register int argc;
53693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com    register enum parse_mode parse_mode;
54693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com
5593a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    argv = (char **) malloc (sizeof(char *));
5693a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    if (argv == (char **)NULL) {
576fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org	ss_error(sci_idx, errno, "Can't allocate storage");
58693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com	*argc_ptr = 0;
59693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com	return(argv);
60ecee051929d6ced19cf324688774acccc9ad4a0ajohannkoenig@chromium.org    }
61ecee051929d6ced19cf324688774acccc9ad4a0ajohannkoenig@chromium.org    *argv = (char *)NULL;
62dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org
63dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org    argc = 0;
64dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org
65dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org    parse_mode = WHITESPACE;	/* flushing whitespace */
666fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org    cp = line_ptr;		/* cp is for output */
67dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org    while (1) {
68dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org#ifdef DEBUG
696fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org	{
70dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org	    printf ("character `%c', mode %d\n", *line_ptr, parse_mode);
71dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org	}
726fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org#endif
7393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org	while (parse_mode == WHITESPACE) {
746fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org	    if (*line_ptr == '\0')
75dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org		goto end_of_line;
766fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org	    if (*line_ptr == ' ' || *line_ptr == '\t') {
776fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org		line_ptr++;
78dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org		continue;
79dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org	    }
80dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org	    if (*line_ptr == '"') {
81dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org		/* go to quoted-string mode */
82dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org		parse_mode = QUOTED_STRING;
836fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org		cp = line_ptr++;
8441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org		argv = NEW_ARGV (argv, argc);
857765c078fa920ba6c949c15f16b6cc979d8bb95bjohannkoenig@chromium.org		argv[argc++] = cp;
866fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org		argv[argc] = NULL;
876fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org	    }
88dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org	    else {
89dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org		/* random-token mode */
906fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org		parse_mode = TOKEN;
91dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org		cp = line_ptr;
926fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org		argv = NEW_ARGV (argv, argc);
93dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org		argv[argc++] = line_ptr;
9487997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org		argv[argc] = NULL;
95dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org	    }
96ecee051929d6ced19cf324688774acccc9ad4a0ajohannkoenig@chromium.org	}
97ecee051929d6ced19cf324688774acccc9ad4a0ajohannkoenig@chromium.org	while (parse_mode == TOKEN) {
9887997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org	    if (*line_ptr == '\0') {
996fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org		*cp++ = '\0';
10087997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org		goto end_of_line;
10187997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org	    }
1026fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org	    else if (*line_ptr == ' ' || *line_ptr == '\t') {
1036fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org		*cp++ = '\0';
1046fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org		line_ptr++;
1056fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org		parse_mode = WHITESPACE;
1066fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org	    }
1076fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org	    else if (*line_ptr == '"') {
108dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org		line_ptr++;
109dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org		parse_mode = QUOTED_STRING;
11087997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org	    }
111dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org	    else {
1126fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org		*cp++ = *line_ptr++;
11387997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org	    }
11487997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org	}
1156fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org	while (parse_mode == QUOTED_STRING) {
1166fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org	    if (*line_ptr == '\0') {
1176fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org		ss_error (sci_idx, 0,
1186fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org			  "Unbalanced quotes in command line");
1196fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org		free (argv);
1206fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org		*argc_ptr = 0;
12193a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org		return NULL;
1226fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org	    }
1236fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org	    else if (*line_ptr == '"') {
1246fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org		if (*++line_ptr == '"') {
1256fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org		    *cp++ = '"';
1266fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org		    line_ptr++;
1276fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org		}
1286fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org		else {
129693441efe611de7ca09c00f4e79776f604b689f4joeyparrish@google.com		    parse_mode = TOKEN;
1306fefe538d859300e7febe78271828198c10f1b52fgalligan@chromium.org		}
131dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org	    }
132dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org	    else {
13393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org		*cp++ = *line_ptr++;
134dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org	    }
135dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org	}
136dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org    }
137dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.orgend_of_line:
138dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org    *argc_ptr = argc;
139dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org#ifdef DEBUG
140e2064011d36b2008099446503f28e64d445060ecjohannkoenig@chromium.org    {
141e2064011d36b2008099446503f28e64d445060ecjohannkoenig@chromium.org	int i;
142e2064011d36b2008099446503f28e64d445060ecjohannkoenig@chromium.org	printf ("argc = %d\n", argc);
14393a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org	for (i = 0; i <= argc; i++)
14493a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org	    printf ("\targv[%2d] = `%s'\n", i,
14587997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org		    argv[i] ? argv[i] : "<NULL>");
146dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org    }
14793a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org#endif
14893a74791c8e808ea76001ee07693aa2a5fdd3500johannkoenig@chromium.org    return(argv);
149dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org}
150dddee1ec7cedf276305b107429f684539b105276johannkoenig@chromium.org