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