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