home *** CD-ROM | disk | FTP | other *** search
- /*
- devlib: command line routines.
-
- Do not put Sherlock macros in this file.
-
- source: cmndline.c
- started: November 4, 1993.
- version:
- September 25, 1995.
- Use on_str and off_str in init_args.
- January 9, 1994.
- Abort if the argument file can not be found.
- */
-
- #include <LIBlib.h>
- #include <LIBcmnd.h>
- #include <LIBend.h>
- #include <LIBmem.h>
-
- #include <stdio.h>
- #include <stdlib.h>
-
- #define arg_is_ws(c) ((c)==' ' || (c)=='\t' || (c)=='\n' || (c)=='\r')
-
- static void init_massage (register char * s);
- static char * init_skip_arg (register char * p);
- static char * init_skip_ws (register char * p);
- static void init_err (char *message, char *file_name);
-
- /*
- Initialize the argv vector from a file.
- */
- void
- init_args(int * argc, char *** argvp, char * name)
- {
- long size, read_size;
- char * buffer;
-
- FILE * init_arg_file = fopen(name, "r");
-
- if (init_arg_file == NULL) {
- *argc = 1;
- init_err("Can not open", name);
- end_usage();
- }
-
- /* Find out how big the file is by seeking to the end. */
- if (fseek(init_arg_file, 0L, SEEK_END) != 0) {
- *argc = 1;
- init_err("Can not seek on", name);
- return;
- }
- size = ftell(init_arg_file);
-
- /* Reposition the file at the start. */
- if (fseek(init_arg_file, 0L, SEEK_SET) != 0) {
- *argc = 1;
- init_err("Can not re-seek on", name);
- return;
- }
-
- /* Allocate a buffer big enough to hold the whole file. */
- buffer = lib_calloc( (size_t) 1, size+10);
- if (buffer == NULL) {
- *argc = 1;
- init_err("Can not allocate buffer for", name);
- return;
- }
-
- /* Read the whole file into the buffer. */
- read_size = fread(buffer, 1, size, init_arg_file);
- buffer[read_size] = '\0';
-
- /* Create the arguments. */
- init_massage(buffer);
- *argc = init_arg_parse(argvp, buffer);
- }
-
- /*
- Print a file error message.
- */
- static void
- init_err(char *message, char *name)
- {
- es(message); eblank(); es(name); enl();
- }
-
- /*
- Eliminate comments that start with ! and go to the end of the line.
- Either '\n' or '\r' end lines and both are converted to blanks.
- */
- static void
- init_massage(register char * s)
- {
- register char * s2 = s;
- char delim;
- char * line_start = s;
-
- /*
- Do not put Sherlock macros here: Sherlock has not been initialized!
- */
-
- /* Bug fix: 9/14/91 */
- if (s == NULL) {
- return;
- }
-
- for(;;) {
- switch (*s) {
-
- case '\0':
-
- /* Finish off the string. */
- *s2 = '\0';
- return;
-
- case '\'':
- case '"':
- case '`':
- {
- /* Copy strings */
- delim = *s;
- *s2++ = *s++;
- while (*s != delim) {
- if (*s == '\n' || *s == '\r' || *s == '\0') {
- *s = '\0';
- init_err("Run on string in argument list:", line_start);
- end_usage();
- }
- *s2++ = *s++;
- }
- *s2++ = *s++;
- break;
- }
-
- case '!':
-
- /* Skip comments. */
- while(*s && *s != '\n' && *s != '\r') {
- s++;
- }
- break;
-
- case '\r':
- case '\n':
-
- /* Convert end of line characters to blanks. */
- *s2++ = ' ';
- s++;
- line_start = s;
- break;
-
- default:
- /* Copy all other characters. */
- *s2++ = *s++;
- }
- }
- }
-
- /*
- Convert the string in buf into a list of pointers to the elements.
- Set *argvp pointing to the newly created list.
-
- On exit, argc is:
-
- 1. One LESS than the total number of elements in the argv vector,
- counting the NULL element at the end.
- 2. The number of arguments in the argv vector, counting the zeroth
- argument, but not counting the NULL element at the end.
- 3. One MORE than the number of user arguments, not counting the
- zeroth argument.
- */
- int
- init_arg_parse(char *** argvp, register char * buf)
- {
- register int argc;
- register char ** argv;
- register int i;
- register char * p;
- static char * ftag = "init_arg_parse";
-
- /*
- Do not put Sherlock macros here: Sherlock has not been initialized!
- */
-
- /* Bug fix: 9/14/91 */
- if (buf == NULL) {
- return 0;
- }
-
- /* Find out how many entries argv will contain. */
- for (p = buf, argc = 0; ;) {
- p = init_skip_ws(p);
- if (!*p) { break; }
- argc++;
- p = init_skip_arg(p);
- }
- if (argc == 0) { return argc; }
-
- /* Allocate space for the array. */
- argv = (char **) lib_calloc ( (size_t) 1, (argc+2)*sizeof(char *));
- *argvp = argv;
-
- /* Set up the argv array. */
- for (p = buf, i = 0; ;) {
-
- p = init_skip_ws(p);
- if (!*p) { break; }
-
- if (*p == '"' || *p == '\'' || *p == '`') {
- argv[i++] = p+1;
- }
- else {
- argv[i++] = p;
- }
- p = init_skip_arg(p);
-
- /* Step back over the delimiter, so it will be replaced by '\0' */
- if (*(p-1) == '"' || *(p-1) == '\'' || *(p-1) == '`') {
- p--;
- }
-
- /* End the argument. */
- if (!*p) {
- break;
- }
- else {
- *p++ = '\0';
- }
- }
-
- /* Put a trailing null argument. */
- argv[i] = NULL;
-
- return argc;
- }
-
- /*
- Skip over an argument.
-
- Allow string arguments containing white space and backslash double quotes.
- */
- static char *
- init_skip_arg(register char * p)
- {
- char * start_p = p;
- char delim;
-
- if (*p == '"' || *p == '\'' || *p == '`') {
-
- /* Skip the beginning quote. */
- delim = *p++;
-
- /* Skip until end of string */
- for(;;) {
- if (!*p) {
- init_err("Unterminated argument string: ", start_p);
- end_usage();
- }
- else if (*p == '\\' && *(p+1) == delim) {
- p += 2;
- }
- else if (*p == delim) {
- p++;
- break;
- }
- else {
- p++;
- }
- }
- } else {
- /* Skip until non white space */
- while(*p && !arg_is_ws(*p)) {
- p++;
- }
- }
- return p;
- }
-
- /*
- Skip over white space.
- */
- static char *
- init_skip_ws(register char * p)
- {
- while(arg_is_ws(*p)) {
- p++;
- }
- return p;
- }
-