1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* 3 * Copyright 2007 Massachusetts Institute of Technology. 4 * All Rights Reserved. 5 * 6 * Export of this software from the United States of America may 7 * require a specific license from the United States Government. 8 * It is the responsibility of any person or organization contemplating 9 * export to obtain such a license before exporting. 10 * 11 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 12 * distribute this software and its documentation for any purpose and 13 * without fee is hereby granted, provided that the above copyright 14 * notice appear in all copies and that both that copyright notice and 15 * this permission notice appear in supporting documentation, and that 16 * the name of M.I.T. not be used in advertising or publicity pertaining 17 * to distribution of the software without specific, written prior 18 * permission. Furthermore if you modify this software you must label 19 * your software as modified software and not distribute it in such a 20 * fashion that it might be confused with the original M.I.T. software. 21 * M.I.T. makes no representations about the suitability of 22 * this software for any purpose. It is provided "as is" without express 23 * or implied warranty. 24 */ 25 /* 26 * Copyright 1987, 1988 by MIT Student Information Processing Board 27 * 28 * For copyright info, see copyright.h. 29 */ 30 31 #include "ss_internal.h" 32 #include "copyright.h" 33 #include <errno.h> 34 35 enum parse_mode { WHITESPACE, TOKEN, QUOTED_STRING }; 36 37 /* 38 * parse(line_ptr, argc_ptr) 39 * 40 * Function: 41 * Parses line, dividing at whitespace, into tokens, returns 42 * the "argc" and "argv" values. 43 * Arguments: 44 * line_ptr (char *) 45 * Pointer to text string to be parsed. 46 * argc_ptr (int *) 47 * Where to put the "argc" (number of tokens) value. 48 * Returns: 49 * argv (char **) 50 * Series of pointers to parsed tokens in the original string. 51 */ 52 53 #define NEW_ARGV(old,n) (char **)realloc((char *)old, \ 54 (unsigned)(n+2)*sizeof(char*)) 55 56 char ** 57 ss_parse(int sci_idx, char *line_ptr, int *argc_ptr) 58 { 59 char **argv, *cp; 60 char **newargv; 61 int argc; 62 enum parse_mode parse_mode; 63 64 argv = (char **) malloc (sizeof(char *)); 65 if (argv == (char **)NULL) { 66 ss_error(sci_idx, errno, "Can't allocate storage"); 67 *argc_ptr = 0; 68 return(argv); 69 } 70 *argv = (char *)NULL; 71 72 argc = 0; 73 74 parse_mode = WHITESPACE; /* flushing whitespace */ 75 cp = line_ptr; /* cp is for output */ 76 while (1) { 77 #ifdef DEBUG 78 { 79 printf ("character `%c', mode %d\n", *line_ptr, parse_mode); 80 } 81 #endif 82 while (parse_mode == WHITESPACE) { 83 if (*line_ptr == '\0') 84 goto end_of_line; 85 if (*line_ptr == ' ' || *line_ptr == '\t') { 86 line_ptr++; 87 continue; 88 } 89 if (*line_ptr == '"') { 90 /* go to quoted-string mode */ 91 parse_mode = QUOTED_STRING; 92 cp = line_ptr++; 93 newargv = NEW_ARGV (argv, argc); 94 if (newargv == NULL) { 95 out_of_mem_in_argv: 96 free(argv); 97 ss_error(sci_idx, errno, "Can't allocate storage"); 98 *argc_ptr = 0; 99 return NULL; 100 } 101 argv = newargv; 102 argv[argc++] = cp; 103 argv[argc] = NULL; 104 } 105 else { 106 /* random-token mode */ 107 parse_mode = TOKEN; 108 cp = line_ptr; 109 newargv = NEW_ARGV (argv, argc); 110 if (newargv == NULL) 111 goto out_of_mem_in_argv; 112 argv = newargv; 113 argv[argc++] = line_ptr; 114 argv[argc] = NULL; 115 } 116 } 117 while (parse_mode == TOKEN) { 118 if (*line_ptr == '\0') { 119 *cp++ = '\0'; 120 goto end_of_line; 121 } 122 else if (*line_ptr == ' ' || *line_ptr == '\t') { 123 *cp++ = '\0'; 124 line_ptr++; 125 parse_mode = WHITESPACE; 126 } 127 else if (*line_ptr == '"') { 128 line_ptr++; 129 parse_mode = QUOTED_STRING; 130 } 131 else { 132 *cp++ = *line_ptr++; 133 } 134 } 135 while (parse_mode == QUOTED_STRING) { 136 if (*line_ptr == '\0') { 137 ss_error (sci_idx, 0, 138 "Unbalanced quotes in command line"); 139 free (argv); 140 *argc_ptr = 0; 141 return NULL; 142 } 143 else if (*line_ptr == '"') { 144 if (*++line_ptr == '"') { 145 *cp++ = '"'; 146 line_ptr++; 147 } 148 else { 149 parse_mode = TOKEN; 150 } 151 } 152 else { 153 *cp++ = *line_ptr++; 154 } 155 } 156 } 157 end_of_line: 158 *argc_ptr = argc; 159 #ifdef DEBUG 160 { 161 int i; 162 printf ("argc = %d\n", argc); 163 for (i = 0; i <= argc; i++) 164 printf ("\targv[%2d] = `%s'\n", i, 165 argv[i] ? argv[i] : "<NULL>"); 166 } 167 #endif 168 return(argv); 169 } 170