1 /* 2 * Copyright 1987, 1988 by MIT Student Information Processing Board 3 * 4 * Permission to use, copy, modify, and distribute this software and 5 * its documentation for any purpose is hereby granted, provided that 6 * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in 7 * advertising or publicity pertaining to distribution of the software 8 * without specific, written prior permission. M.I.T. and the 9 * M.I.T. S.I.P.B. make no representations about the suitability of 10 * this software for any purpose. It is provided "as is" without 11 * express or implied warranty. 12 */ 13 14 #include "config.h" 15 #ifdef HAS_STDLIB_H 16 #include <stdlib.h> 17 #endif 18 #include <string.h> 19 #ifdef HAVE_ERRNO_H 20 #include <errno.h> 21 #endif 22 23 #include "ss_internal.h" 24 25 enum parse_mode { WHITESPACE, TOKEN, QUOTED_STRING }; 26 27 /* 28 * parse(line_ptr, argc_ptr) 29 * 30 * Function: 31 * Parses line, dividing at whitespace, into tokens, returns 32 * the "argc" and "argv" values. 33 * Arguments: 34 * line_ptr (char *) 35 * Pointer to text string to be parsed. 36 * argc_ptr (int *) 37 * Where to put the "argc" (number of tokens) value. 38 * Returns: 39 * argv (char **) 40 * Series of pointers to parsed tokens. 41 */ 42 43 #define NEW_ARGV(old,n) (char **)realloc((char *)old,\ 44 (unsigned)(n+2)*sizeof(char*)) 45 46 char **ss_parse(int sci_idx, register char *line_ptr, int *argc_ptr) 47 { 48 register char **argv, **new_argv, *cp; 49 register int argc; 50 register enum parse_mode parse_mode; 51 52 argv = (char **) malloc (sizeof(char *)); 53 if (argv == (char **)NULL) { 54 ss_error(sci_idx, errno, "Can't allocate storage"); 55 *argc_ptr = 0; 56 return(argv); 57 } 58 *argv = (char *)NULL; 59 60 argc = 0; 61 62 parse_mode = WHITESPACE; /* flushing whitespace */ 63 cp = line_ptr; /* cp is for output */ 64 while (1) { 65 #ifdef DEBUG 66 { 67 printf ("character `%c', mode %d\n", *line_ptr, parse_mode); 68 } 69 #endif 70 while (parse_mode == WHITESPACE) { 71 if (*line_ptr == '\0') 72 goto end_of_line; 73 if (*line_ptr == ' ' || *line_ptr == '\t') { 74 line_ptr++; 75 continue; 76 } 77 if (*line_ptr == '"') { 78 /* go to quoted-string mode */ 79 parse_mode = QUOTED_STRING; 80 cp = line_ptr++; 81 new_argv = NEW_ARGV (argv, argc); 82 if (new_argv == NULL) { 83 free(argv); 84 *argc_ptr = 0; 85 return NULL; 86 } 87 argv = new_argv; 88 argv[argc++] = cp; 89 argv[argc] = NULL; 90 } 91 else { 92 /* random-token mode */ 93 parse_mode = TOKEN; 94 cp = line_ptr; 95 new_argv = NEW_ARGV (argv, argc); 96 if (new_argv == NULL) { 97 free(argv); 98 *argc_ptr = 0; 99 return NULL; 100 } 101 argv = new_argv; 102 argv[argc++] = line_ptr; 103 argv[argc] = NULL; 104 } 105 } 106 while (parse_mode == TOKEN) { 107 if (*line_ptr == '\0') { 108 *cp++ = '\0'; 109 goto end_of_line; 110 } 111 else if (*line_ptr == ' ' || *line_ptr == '\t') { 112 *cp++ = '\0'; 113 line_ptr++; 114 parse_mode = WHITESPACE; 115 } 116 else if (*line_ptr == '"') { 117 line_ptr++; 118 parse_mode = QUOTED_STRING; 119 } 120 else { 121 *cp++ = *line_ptr++; 122 } 123 } 124 while (parse_mode == QUOTED_STRING) { 125 if (*line_ptr == '\0') { 126 ss_error (sci_idx, 0, 127 "Unbalanced quotes in command line"); 128 free (argv); 129 *argc_ptr = 0; 130 return NULL; 131 } 132 else if (*line_ptr == '"') { 133 if (*++line_ptr == '"') { 134 *cp++ = '"'; 135 line_ptr++; 136 } 137 else { 138 parse_mode = TOKEN; 139 } 140 } 141 else { 142 *cp++ = *line_ptr++; 143 } 144 } 145 } 146 end_of_line: 147 *argc_ptr = argc; 148 #ifdef DEBUG 149 { 150 int i; 151 printf ("argc = %d\n", argc); 152 for (i = 0; i <= argc; i++) 153 printf ("\targv[%2d] = `%s'\n", i, 154 argv[i] ? argv[i] : "<NULL>"); 155 } 156 #endif 157 return(argv); 158 } 159