diff options
Diffstat (limited to 'dos/argv.c')
-rw-r--r-- | dos/argv.c | 62 |
1 files changed, 48 insertions, 14 deletions
@@ -1,6 +1,7 @@ /* ----------------------------------------------------------------------- * * * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2013 Intel Corporation; author: H. Peter Anvin * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -28,48 +29,81 @@ /* * argv.c * - * Parse a single C string into argc and argv (argc is return value.) + * Parse the MS-DOS command line into argc and argv (argc is return value.) * memptr points to available memory. */ #include <inttypes.h> #include <stddef.h> -#include <stdio.h> +#include <stdbool.h> +#include "mystuff.h" #define ALIGN_UP(p,t) ((t *)(((uintptr_t)(p) + (sizeof(t)-1)) & ~(sizeof(t)-1))) extern char __heap_start[]; void *__mem_end = &__heap_start; /* Global variable for use by malloc() */ -int __parse_argv(char ***argv, const char *str) +int __parse_argv(char ***argv) { char *mem = __mem_end; - const char *p = str; + const char *str, *p; char *q = mem; - char *r; + char c, *r; char **arg; - int wasspace = 0; - int argc = 1; + bool wasspace; + int argc; + int len; + size_t offs; + int nulls; + uint16_t nstr; - /* First copy the string, turning whitespace runs into nulls */ + /* Find and copy argv[0] after the environment block */ + set_fs(_PSP.environment); + offs = 0; + nulls = 0; + do { + if (get_8_fs(offs++) == '\0') + nulls++; + else + nulls = 0; + } while (nulls < 2); + + nstr = get_16_fs(offs); + offs += 2; + + /* Copy the null-terminated filename string */ + if (nstr >= 1) { + while ((c = get_8_fs(offs++))) + *q++ = c; + } + *q++ = '\0'; + + /* Now for the command line tail... */ + + len = _PSP.cmdlen; + str = _PSP.cmdtail; + argc = 1; + wasspace = true; + + /* Copy the command tail, turning whitespace runs into nulls */ for (p = str;; p++) { - if (*p <= ' ') { + if (!len || *p <= ' ') { if (!wasspace) { - wasspace = 1; + wasspace = true; *q++ = '\0'; } } else { if (wasspace) { argc++; - wasspace = 0; + wasspace = false; } *q++ = *p; } - /* This test is AFTER we have processed the null byte; + /* This test is AFTER we have processed the end byte; we treat it as a whitespace character so it terminates the last argument */ - if (!*p) + if (!len--) break; } @@ -78,7 +112,7 @@ int __parse_argv(char ***argv, const char *str) *argv = arg; *arg++ = mem; /* argv[0] */ - q--; /* Point q to final null */ + q--; /* Point q to terminal character */ for (r = mem; r < q; r++) { if (*r == '\0') { *arg++ = r + 1; |