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 #ifdef HAS_STDLIB_H 15 #include <stdlib.h> 16 #endif 17 #include <string.h> 18 #ifdef HAVE_ERRNO_H 19 #include <errno.h> 20 #endif 21 22 #include "ss_internal.h" 23 24 enum parse_mode { WHITESPACE, TOKEN, QUOTED_STRING }; 25 26 /* 27 * parse(line_ptr, argc_ptr) 28 * 29 * Function: 30 * Parses line, dividing at whitespace, into tokens, returns 31 * the "argc" and "argv" values. 32 * Arguments: 33 * line_ptr (char *) 34 * Pointer to text string to be parsed. 35 * argc_ptr (int *) 36 * Where to put the "argc" (number of tokens) value. 37 * Returns: 38 * argv (char **) 39 * Series of pointers to parsed tokens. 40 */ 41 42 #define NEW_ARGV(old,n) (char **)realloc((char *)old,\ 43 (unsigned)(n+2)*sizeof(char*)) 44 45 char **ss_parse (sci_idx, line_ptr, argc_ptr) 46 int sci_idx; 47 register char *line_ptr; 48 int *argc_ptr; 49 { 50 register char **argv, *cp; 51 register int argc; 52 register enum parse_mode parse_mode; 53 54 argv = (char **) malloc (sizeof(char *)); 55 if (argv == (char **)NULL) { 56 ss_error(sci_idx, errno, "Can't allocate storage"); 57 *argc_ptr = 0; 58 return(argv); 59 } 60 *argv = (char *)NULL; 61 62 argc = 0; 63 64 parse_mode = WHITESPACE; /* flushing whitespace */ 65 cp = line_ptr; /* cp is for output */ 66 while (1) { 67 #ifdef DEBUG 68 { 69 printf ("character `%c', mode %d\n", *line_ptr, parse_mode); 70 } 71 #endif 72 while (parse_mode == WHITESPACE) { 73 if (*line_ptr == '\0') 74 goto end_of_line; 75 if (*line_ptr == ' ' || *line_ptr == '\t') { 76 line_ptr++; 77 continue; 78 } 79 if (*line_ptr == '"') { 80 /* go to quoted-string mode */ 81 parse_mode = QUOTED_STRING; 82 cp = line_ptr++; 83 argv = NEW_ARGV (argv, argc); 84 argv[argc++] = cp; 85 argv[argc] = NULL; 86 } 87 else { 88 /* random-token mode */ 89 parse_mode = TOKEN; 90 cp = line_ptr; 91 argv = NEW_ARGV (argv, argc); 92 argv[argc++] = line_ptr; 93 argv[argc] = NULL; 94 } 95 } 96 while (parse_mode == TOKEN) { 97 if (*line_ptr == '\0') { 98 *cp++ = '\0'; 99 goto end_of_line; 100 } 101 else if (*line_ptr == ' ' || *line_ptr == '\t') { 102 *cp++ = '\0'; 103 line_ptr++; 104 parse_mode = WHITESPACE; 105 } 106 else if (*line_ptr == '"') { 107 line_ptr++; 108 parse_mode = QUOTED_STRING; 109 } 110 else { 111 *cp++ = *line_ptr++; 112 } 113 } 114 while (parse_mode == QUOTED_STRING) { 115 if (*line_ptr == '\0') { 116 ss_error (sci_idx, 0, 117 "Unbalanced quotes in command line"); 118 free (argv); 119 *argc_ptr = 0; 120 return NULL; 121 } 122 else if (*line_ptr == '"') { 123 if (*++line_ptr == '"') { 124 *cp++ = '"'; 125 line_ptr++; 126 } 127 else { 128 parse_mode = TOKEN; 129 } 130 } 131 else { 132 *cp++ = *line_ptr++; 133 } 134 } 135 } 136 end_of_line: 137 *argc_ptr = argc; 138 #ifdef DEBUG 139 { 140 int i; 141 printf ("argc = %d\n", argc); 142 for (i = 0; i <= argc; i++) 143 printf ("\targv[%2d] = `%s'\n", i, 144 argv[i] ? argv[i] : "<NULL>"); 145 } 146 #endif 147 return(argv); 148 } 149