1 /* ----------------------------------------------------------------------- * 2 * 3 * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved 4 * Copyright 2013 Intel Corporation; author: H. Peter Anvin 5 * 6 * Permission is hereby granted, free of charge, to any person 7 * obtaining a copy of this software and associated documentation 8 * files (the "Software"), to deal in the Software without 9 * restriction, including without limitation the rights to use, 10 * copy, modify, merge, publish, distribute, sublicense, and/or 11 * sell copies of the Software, and to permit persons to whom 12 * the Software is furnished to do so, subject to the following 13 * conditions: 14 * 15 * The above copyright notice and this permission notice shall 16 * be included in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 * OTHER DEALINGS IN THE SOFTWARE. 26 * 27 * ----------------------------------------------------------------------- */ 28 29 /* 30 * argv.c 31 * 32 * Parse the MS-DOS command line into argc and argv (argc is return value.) 33 * memptr points to available memory. 34 */ 35 36 #include <inttypes.h> 37 #include <stddef.h> 38 #include <stdbool.h> 39 #include "mystuff.h" 40 41 #define ALIGN_UP(p,t) ((t *)(((uintptr_t)(p) + (sizeof(t)-1)) & ~(sizeof(t)-1))) 42 43 extern char __heap_start[]; 44 void *__mem_end = &__heap_start; /* Global variable for use by malloc() */ 45 46 int __parse_argv(char ***argv) 47 { 48 char *mem = __mem_end; 49 const char *str, *p; 50 char *q = mem; 51 char c, *r; 52 char **arg; 53 bool wasspace; 54 int argc; 55 int len; 56 size_t offs; 57 int nulls; 58 uint16_t nstr; 59 60 /* Find and copy argv[0] after the environment block */ 61 set_fs(_PSP.environment); 62 offs = 0; 63 nulls = 0; 64 do { 65 if (get_8_fs(offs++) == '\0') 66 nulls++; 67 else 68 nulls = 0; 69 } while (nulls < 2); 70 71 nstr = get_16_fs(offs); 72 offs += 2; 73 74 /* Copy the null-terminated filename string */ 75 if (nstr >= 1) { 76 while ((c = get_8_fs(offs++))) 77 *q++ = c; 78 } 79 *q++ = '\0'; 80 81 /* Now for the command line tail... */ 82 83 len = _PSP.cmdlen; 84 str = _PSP.cmdtail; 85 argc = 1; 86 wasspace = true; 87 88 /* Copy the command tail, turning whitespace runs into nulls */ 89 for (p = str;; p++) { 90 if (!len || *p <= ' ') { 91 if (!wasspace) { 92 wasspace = true; 93 *q++ = '\0'; 94 } 95 } else { 96 if (wasspace) { 97 argc++; 98 wasspace = false; 99 } 100 *q++ = *p; 101 } 102 103 /* This test is AFTER we have processed the end byte; 104 we treat it as a whitespace character so it terminates 105 the last argument */ 106 if (!len--) 107 break; 108 } 109 110 /* Now create argv */ 111 arg = ALIGN_UP(q, char *); 112 *argv = arg; 113 *arg++ = mem; /* argv[0] */ 114 115 q--; /* Point q to terminal character */ 116 for (r = mem; r < q; r++) { 117 if (*r == '\0') { 118 *arg++ = r + 1; 119 } 120 } 121 122 *arg++ = NULL; /* Null pointer at the end */ 123 __mem_end = arg; /* End of memory we used */ 124 125 return argc; 126 } 127