17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * Copyright 1987, 1988 by MIT Student Information Processing Board
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * For copyright info, see copyright.h.
57c478bd9Sstevel@tonic-gate */
67c478bd9Sstevel@tonic-gate
7*6d084746S /*
8*6d084746S * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
9*6d084746S * Use is subject to license terms.
10*6d084746S */
11*6d084746S
127c478bd9Sstevel@tonic-gate #include "ss_internal.h"
137c478bd9Sstevel@tonic-gate #include "copyright.h"
1456a424ccSmp153739 #include <errno.h>
157c478bd9Sstevel@tonic-gate
167c478bd9Sstevel@tonic-gate enum parse_mode { WHITESPACE, TOKEN, QUOTED_STRING };
177c478bd9Sstevel@tonic-gate
18*6d084746S
19*6d084746S /*
20*6d084746S * Solaris Kerberos:
21*6d084746S * ss_parse has been modified slightly from the original in two ways.
22*6d084746S * 1) A new parameter "quiet" has been added which is used to silence
23*6d084746S * error or warning messages.
24*6d084746S * 2) ss_parse now returns an error status instead of argv - this is to
25*6d084746S * allow an error to be distinguished from no tokens when parsing an empty
26*6d084746S * string.
27*6d084746S * Both of these changes allow ss_parse to be used during tab-completion.
28*6d084746S */
29*6d084746S
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate * parse(line_ptr, argc_ptr)
327c478bd9Sstevel@tonic-gate *
337c478bd9Sstevel@tonic-gate * Function:
347c478bd9Sstevel@tonic-gate * Parses line, dividing at whitespace, into tokens, returns
357c478bd9Sstevel@tonic-gate * the "argc" and "argv" values.
367c478bd9Sstevel@tonic-gate * Arguments:
377c478bd9Sstevel@tonic-gate * line_ptr (char *)
387c478bd9Sstevel@tonic-gate * Pointer to text string to be parsed.
397c478bd9Sstevel@tonic-gate * argc_ptr (int *)
407c478bd9Sstevel@tonic-gate * Where to put the "argc" (number of tokens) value.
41*6d084746S * argv_ptr (char ***)
42*6d084746S * Where to put the series of pointers to parsed tokens.
437c478bd9Sstevel@tonic-gate * Returns:
44*6d084746S * error (0 - success, non-zero on failure)
457c478bd9Sstevel@tonic-gate */
467c478bd9Sstevel@tonic-gate
477c478bd9Sstevel@tonic-gate #define NEW_ARGV(old,n) (char **)realloc((char *)old,\
487c478bd9Sstevel@tonic-gate (unsigned)(n+2)*sizeof(char*))
497c478bd9Sstevel@tonic-gate
ss_parse(sci_idx,line_ptr,argc_ptr,argv_ptr,quiet)50*6d084746S int ss_parse (sci_idx, line_ptr, argc_ptr, argv_ptr, quiet)
517c478bd9Sstevel@tonic-gate int sci_idx;
527c478bd9Sstevel@tonic-gate register char *line_ptr;
537c478bd9Sstevel@tonic-gate int *argc_ptr;
54*6d084746S char ***argv_ptr;
55*6d084746S int quiet;
567c478bd9Sstevel@tonic-gate {
577c478bd9Sstevel@tonic-gate register char **argv, *cp;
587c478bd9Sstevel@tonic-gate register int argc;
597c478bd9Sstevel@tonic-gate register enum parse_mode parse_mode;
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate argv = (char **) malloc (sizeof(char *));
627c478bd9Sstevel@tonic-gate if (argv == (char **)NULL) {
63*6d084746S if (!quiet)
647c478bd9Sstevel@tonic-gate ss_error(sci_idx, errno, "Can't allocate storage");
657c478bd9Sstevel@tonic-gate *argc_ptr = 0;
66*6d084746S *argv_ptr = argv;
67*6d084746S return(ENOMEM);
687c478bd9Sstevel@tonic-gate }
697c478bd9Sstevel@tonic-gate *argv = (char *)NULL;
707c478bd9Sstevel@tonic-gate
717c478bd9Sstevel@tonic-gate argc = 0;
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gate parse_mode = WHITESPACE; /* flushing whitespace */
747c478bd9Sstevel@tonic-gate cp = line_ptr; /* cp is for output */
757c478bd9Sstevel@tonic-gate while (1) {
767c478bd9Sstevel@tonic-gate #ifdef DEBUG
777c478bd9Sstevel@tonic-gate {
7856a424ccSmp153739 printf ("character `%c', mode %d\n", *line_ptr, parse_mode);
797c478bd9Sstevel@tonic-gate }
807c478bd9Sstevel@tonic-gate #endif
817c478bd9Sstevel@tonic-gate while (parse_mode == WHITESPACE) {
827c478bd9Sstevel@tonic-gate if (*line_ptr == '\0')
837c478bd9Sstevel@tonic-gate goto end_of_line;
847c478bd9Sstevel@tonic-gate if (*line_ptr == ' ' || *line_ptr == '\t') {
857c478bd9Sstevel@tonic-gate line_ptr++;
867c478bd9Sstevel@tonic-gate continue;
877c478bd9Sstevel@tonic-gate }
887c478bd9Sstevel@tonic-gate if (*line_ptr == '"') {
897c478bd9Sstevel@tonic-gate /* go to quoted-string mode */
907c478bd9Sstevel@tonic-gate parse_mode = QUOTED_STRING;
917c478bd9Sstevel@tonic-gate cp = line_ptr++;
927c478bd9Sstevel@tonic-gate argv = NEW_ARGV (argv, argc);
937c478bd9Sstevel@tonic-gate argv[argc++] = cp;
947c478bd9Sstevel@tonic-gate argv[argc] = NULL;
957c478bd9Sstevel@tonic-gate }
967c478bd9Sstevel@tonic-gate else {
977c478bd9Sstevel@tonic-gate /* random-token mode */
987c478bd9Sstevel@tonic-gate parse_mode = TOKEN;
997c478bd9Sstevel@tonic-gate cp = line_ptr;
1007c478bd9Sstevel@tonic-gate argv = NEW_ARGV (argv, argc);
1017c478bd9Sstevel@tonic-gate argv[argc++] = line_ptr;
1027c478bd9Sstevel@tonic-gate argv[argc] = NULL;
1037c478bd9Sstevel@tonic-gate }
1047c478bd9Sstevel@tonic-gate }
1057c478bd9Sstevel@tonic-gate while (parse_mode == TOKEN) {
1067c478bd9Sstevel@tonic-gate if (*line_ptr == '\0') {
1077c478bd9Sstevel@tonic-gate *cp++ = '\0';
1087c478bd9Sstevel@tonic-gate goto end_of_line;
1097c478bd9Sstevel@tonic-gate }
1107c478bd9Sstevel@tonic-gate else if (*line_ptr == ' ' || *line_ptr == '\t') {
1117c478bd9Sstevel@tonic-gate *cp++ = '\0';
1127c478bd9Sstevel@tonic-gate line_ptr++;
1137c478bd9Sstevel@tonic-gate parse_mode = WHITESPACE;
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate else if (*line_ptr == '"') {
1167c478bd9Sstevel@tonic-gate line_ptr++;
1177c478bd9Sstevel@tonic-gate parse_mode = QUOTED_STRING;
1187c478bd9Sstevel@tonic-gate }
1197c478bd9Sstevel@tonic-gate else {
1207c478bd9Sstevel@tonic-gate *cp++ = *line_ptr++;
1217c478bd9Sstevel@tonic-gate }
1227c478bd9Sstevel@tonic-gate }
1237c478bd9Sstevel@tonic-gate while (parse_mode == QUOTED_STRING) {
1247c478bd9Sstevel@tonic-gate if (*line_ptr == '\0') {
125*6d084746S if (!quiet)
1267c478bd9Sstevel@tonic-gate ss_error (sci_idx, 0,
1277c478bd9Sstevel@tonic-gate "Unbalanced quotes in command line");
1287c478bd9Sstevel@tonic-gate free (argv);
1297c478bd9Sstevel@tonic-gate *argc_ptr = 0;
130*6d084746S *argv_ptr = NULL;
131*6d084746S return (-1);
1327c478bd9Sstevel@tonic-gate }
1337c478bd9Sstevel@tonic-gate else if (*line_ptr == '"') {
1347c478bd9Sstevel@tonic-gate if (*++line_ptr == '"') {
1357c478bd9Sstevel@tonic-gate *cp++ = '"';
1367c478bd9Sstevel@tonic-gate line_ptr++;
1377c478bd9Sstevel@tonic-gate }
1387c478bd9Sstevel@tonic-gate else {
1397c478bd9Sstevel@tonic-gate parse_mode = TOKEN;
1407c478bd9Sstevel@tonic-gate }
1417c478bd9Sstevel@tonic-gate }
1427c478bd9Sstevel@tonic-gate else {
1437c478bd9Sstevel@tonic-gate *cp++ = *line_ptr++;
1447c478bd9Sstevel@tonic-gate }
1457c478bd9Sstevel@tonic-gate }
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate end_of_line:
1487c478bd9Sstevel@tonic-gate *argc_ptr = argc;
1497c478bd9Sstevel@tonic-gate #ifdef DEBUG
1507c478bd9Sstevel@tonic-gate {
1517c478bd9Sstevel@tonic-gate int i;
1527c478bd9Sstevel@tonic-gate printf ("argc = %d\n", argc);
1537c478bd9Sstevel@tonic-gate for (i = 0; i <= argc; i++)
1547c478bd9Sstevel@tonic-gate printf ("\targv[%2d] = `%s'\n", i,
1557c478bd9Sstevel@tonic-gate argv[i] ? argv[i] : "<NULL>");
1567c478bd9Sstevel@tonic-gate }
1577c478bd9Sstevel@tonic-gate #endif
158*6d084746S *argv_ptr = argv;
159*6d084746S return(0);
1607c478bd9Sstevel@tonic-gate }
161