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 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