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