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