2N/A/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2N/A/*
2N/A * Copyright 1987, 1988 by MIT Student Information Processing Board
2N/A *
2N/A * For copyright info, see copyright.h.
2N/A */
2N/A/*
2N/A * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include "ss_internal.h"
2N/A#include "copyright.h"
2N/A#include <errno.h>
2N/A
2N/Aenum parse_mode { WHITESPACE, TOKEN, QUOTED_STRING };
2N/A
2N/A
2N/A/*
2N/A * Solaris Kerberos:
2N/A * ss_parse has been modified slightly from the original in two ways.
2N/A * 1) A new parameter "quiet" has been added which is used to silence
2N/A * error or warning messages.
2N/A * 2) ss_parse now returns an error status instead of argv - this is to
2N/A * allow an error to be distinguished from no tokens when parsing an empty
2N/A * string.
2N/A * Both of these changes allow ss_parse to be used during tab-completion.
2N/A */
2N/A
2N/A/*
2N/A * parse(line_ptr, argc_ptr)
2N/A *
2N/A * Function:
2N/A * Parses line, dividing at whitespace, into tokens, returns
2N/A * the "argc" and "argv" values.
2N/A * Arguments:
2N/A * line_ptr (char *)
2N/A * Pointer to text string to be parsed.
2N/A * argc_ptr (int *)
2N/A * Where to put the "argc" (number of tokens) value.
2N/A * argv_ptr (char ***)
2N/A * Where to put the series of pointers to parsed tokens.
2N/A * Returns:
2N/A * error (0 - success, non-zero on failure)
2N/A */
2N/A
2N/A#define NEW_ARGV(old,n) (char **)realloc((char *)old,\
2N/A (unsigned)(n+2)*sizeof(char*))
2N/A
2N/Aint ss_parse (sci_idx, line_ptr, argc_ptr, argv_ptr, quiet)
2N/A int sci_idx;
2N/A register char *line_ptr;
2N/A int *argc_ptr;
2N/A char ***argv_ptr;
2N/A int quiet;
2N/A{
2N/A register char **argv, *cp;
2N/A register int argc;
2N/A register enum parse_mode parse_mode;
2N/A
2N/A argv = (char **) malloc (sizeof(char *));
2N/A if (argv == (char **)NULL) {
2N/A if (!quiet)
2N/A ss_error(sci_idx, errno, "Can't allocate storage");
2N/A *argc_ptr = 0;
2N/A *argv_ptr = argv;
2N/A return(ENOMEM);
2N/A }
2N/A *argv = (char *)NULL;
2N/A
2N/A argc = 0;
2N/A
2N/A parse_mode = WHITESPACE; /* flushing whitespace */
2N/A cp = line_ptr; /* cp is for output */
2N/A while (1) {
2N/A#ifdef DEBUG
2N/A {
2N/A printf ("character `%c', mode %d\n", *line_ptr, parse_mode);
2N/A }
2N/A#endif
2N/A while (parse_mode == WHITESPACE) {
2N/A if (*line_ptr == '\0')
2N/A goto end_of_line;
2N/A if (*line_ptr == ' ' || *line_ptr == '\t') {
2N/A line_ptr++;
2N/A continue;
2N/A }
2N/A if (*line_ptr == '"') {
2N/A /* go to quoted-string mode */
2N/A parse_mode = QUOTED_STRING;
2N/A cp = line_ptr++;
2N/A argv = NEW_ARGV (argv, argc);
2N/A argv[argc++] = cp;
2N/A argv[argc] = NULL;
2N/A }
2N/A else {
2N/A /* random-token mode */
2N/A parse_mode = TOKEN;
2N/A cp = line_ptr;
2N/A argv = NEW_ARGV (argv, argc);
2N/A argv[argc++] = line_ptr;
2N/A argv[argc] = NULL;
2N/A }
2N/A }
2N/A while (parse_mode == TOKEN) {
2N/A if (*line_ptr == '\0') {
2N/A *cp++ = '\0';
2N/A goto end_of_line;
2N/A }
2N/A else if (*line_ptr == ' ' || *line_ptr == '\t') {
2N/A *cp++ = '\0';
2N/A line_ptr++;
2N/A parse_mode = WHITESPACE;
2N/A }
2N/A else if (*line_ptr == '"') {
2N/A line_ptr++;
2N/A parse_mode = QUOTED_STRING;
2N/A }
2N/A else {
2N/A *cp++ = *line_ptr++;
2N/A }
2N/A }
2N/A while (parse_mode == QUOTED_STRING) {
2N/A if (*line_ptr == '\0') {
2N/A if (!quiet)
2N/A ss_error (sci_idx, 0,
2N/A "Unbalanced quotes in command line");
2N/A free (argv);
2N/A *argc_ptr = 0;
2N/A *argv_ptr = NULL;
2N/A return (-1);
2N/A }
2N/A else if (*line_ptr == '"') {
2N/A if (*++line_ptr == '"') {
2N/A *cp++ = '"';
2N/A line_ptr++;
2N/A }
2N/A else {
2N/A parse_mode = TOKEN;
2N/A }
2N/A }
2N/A else {
2N/A *cp++ = *line_ptr++;
2N/A }
2N/A }
2N/A }
2N/Aend_of_line:
2N/A *argc_ptr = argc;
2N/A#ifdef DEBUG
2N/A {
2N/A int i;
2N/A printf ("argc = %d\n", argc);
2N/A for (i = 0; i <= argc; i++)
2N/A printf ("\targv[%2d] = `%s'\n", i,
2N/A argv[i] ? argv[i] : "<NULL>");
2N/A }
2N/A#endif
2N/A *argv_ptr = argv;
2N/A return(0);
2N/A}