Home | History | Annotate | Download | only in ss
      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 
     25 enum 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 
     46 char **ss_parse(int sci_idx, register char *line_ptr, int *argc_ptr)
     47 {
     48     register char **argv, **new_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 		new_argv = NEW_ARGV (argv, argc);
     82 		if (new_argv == NULL) {
     83 			free(argv);
     84 			*argc_ptr = 0;
     85 			return NULL;
     86 		}
     87 		argv = new_argv;
     88 		argv[argc++] = cp;
     89 		argv[argc] = NULL;
     90 	    }
     91 	    else {
     92 		/* random-token mode */
     93 		parse_mode = TOKEN;
     94 		cp = line_ptr;
     95 		new_argv = NEW_ARGV (argv, argc);
     96 		if (new_argv == NULL) {
     97 			free(argv);
     98 			*argc_ptr = 0;
     99 			return NULL;
    100 		}
    101 		argv = new_argv;
    102 		argv[argc++] = line_ptr;
    103 		argv[argc] = NULL;
    104 	    }
    105 	}
    106 	while (parse_mode == TOKEN) {
    107 	    if (*line_ptr == '\0') {
    108 		*cp++ = '\0';
    109 		goto end_of_line;
    110 	    }
    111 	    else if (*line_ptr == ' ' || *line_ptr == '\t') {
    112 		*cp++ = '\0';
    113 		line_ptr++;
    114 		parse_mode = WHITESPACE;
    115 	    }
    116 	    else if (*line_ptr == '"') {
    117 		line_ptr++;
    118 		parse_mode = QUOTED_STRING;
    119 	    }
    120 	    else {
    121 		*cp++ = *line_ptr++;
    122 	    }
    123 	}
    124 	while (parse_mode == QUOTED_STRING) {
    125 	    if (*line_ptr == '\0') {
    126 		ss_error (sci_idx, 0,
    127 			  "Unbalanced quotes in command line");
    128 		free (argv);
    129 		*argc_ptr = 0;
    130 		return NULL;
    131 	    }
    132 	    else if (*line_ptr == '"') {
    133 		if (*++line_ptr == '"') {
    134 		    *cp++ = '"';
    135 		    line_ptr++;
    136 		}
    137 		else {
    138 		    parse_mode = TOKEN;
    139 		}
    140 	    }
    141 	    else {
    142 		*cp++ = *line_ptr++;
    143 	    }
    144 	}
    145     }
    146 end_of_line:
    147     *argc_ptr = argc;
    148 #ifdef DEBUG
    149     {
    150 	int i;
    151 	printf ("argc = %d\n", argc);
    152 	for (i = 0; i <= argc; i++)
    153 	    printf ("\targv[%2d] = `%s'\n", i,
    154 		    argv[i] ? argv[i] : "<NULL>");
    155     }
    156 #endif
    157     return(argv);
    158 }
    159