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 **ss_parse (sci_idx, line_ptr, argc_ptr) 57 int sci_idx; 58 char *line_ptr; 59 int *argc_ptr; 60 { 61 char **argv, *cp; 62 char **newargv; 63 int argc; 64 enum parse_mode parse_mode; 65 66 argv = (char **) malloc (sizeof(char *)); 67 if (argv == (char **)NULL) { 68 ss_error(sci_idx, errno, "Can't allocate storage"); 69 *argc_ptr = 0; 70 return(argv); 71 } 72 *argv = (char *)NULL; 73 74 argc = 0; 75 76 parse_mode = WHITESPACE; /* flushing whitespace */ 77 cp = line_ptr; /* cp is for output */ 78 while (1) { 79 #ifdef DEBUG 80 { 81 printf ("character `%c', mode %d\n", *line_ptr, parse_mode); 82 } 83 #endif 84 while (parse_mode == WHITESPACE) { 85 if (*line_ptr == '\0') 86 goto end_of_line; 87 if (*line_ptr == ' ' || *line_ptr == '\t') { 88 line_ptr++; 89 continue; 90 } 91 if (*line_ptr == '"') { 92 /* go to quoted-string mode */ 93 parse_mode = QUOTED_STRING; 94 cp = line_ptr++; 95 newargv = NEW_ARGV (argv, argc); 96 if (newargv == NULL) { 97 out_of_mem_in_argv: 98 free(argv); 99 ss_error(sci_idx, errno, "Can't allocate storage"); 100 *argc_ptr = 0; 101 return NULL; 102 } 103 argv = newargv; 104 argv[argc++] = cp; 105 argv[argc] = NULL; 106 } 107 else { 108 /* random-token mode */ 109 parse_mode = TOKEN; 110 cp = line_ptr; 111 newargv = NEW_ARGV (argv, argc); 112 if (newargv == NULL) 113 goto out_of_mem_in_argv; 114 argv = newargv; 115 argv[argc++] = line_ptr; 116 argv[argc] = NULL; 117 } 118 } 119 while (parse_mode == TOKEN) { 120 if (*line_ptr == '\0') { 121 *cp++ = '\0'; 122 goto end_of_line; 123 } 124 else if (*line_ptr == ' ' || *line_ptr == '\t') { 125 *cp++ = '\0'; 126 line_ptr++; 127 parse_mode = WHITESPACE; 128 } 129 else if (*line_ptr == '"') { 130 line_ptr++; 131 parse_mode = QUOTED_STRING; 132 } 133 else { 134 *cp++ = *line_ptr++; 135 } 136 } 137 while (parse_mode == QUOTED_STRING) { 138 if (*line_ptr == '\0') { 139 ss_error (sci_idx, 0, 140 "Unbalanced quotes in command line"); 141 free (argv); 142 *argc_ptr = 0; 143 return NULL; 144 } 145 else if (*line_ptr == '"') { 146 if (*++line_ptr == '"') { 147 *cp++ = '"'; 148 line_ptr++; 149 } 150 else { 151 parse_mode = TOKEN; 152 } 153 } 154 else { 155 *cp++ = *line_ptr++; 156 } 157 } 158 } 159 end_of_line: 160 *argc_ptr = argc; 161 #ifdef DEBUG 162 { 163 int i; 164 printf ("argc = %d\n", argc); 165 for (i = 0; i <= argc; i++) 166 printf ("\targv[%2d] = `%s'\n", i, 167 argv[i] ? argv[i] : "<NULL>"); 168 } 169 #endif 170 return(argv); 171 } 172