Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/libsaio/stringTable.c

1/*
2 * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 2.0 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24/*
25 * Copyright 1993 NeXT, Inc.
26 * All rights reserved.
27 */
28
29#include "libsaio.h"
30#include "bootstruct.h"
31#include "platform.h"
32#include "xml.h"
33
34static char * AllocInitStringWithLength(const char * oldString, int len);
35static char * AllocInitZeroEndedStringWithLength(const char * oldString, int len);
36
37#ifndef MIN
38#define MIN(x, y) ((x) < (y) ? (x) : (y))
39#endif
40
41#define ASSERT_CONFIG \
42if (config == DEFAULT_BOOT_CONFIG) \
43config = &bootInfo->bootConfig ; \
44else if (config == DEFAULT_SYSTEM_CONFIG) \
45config = &bootInfo->SystemConfig ; \
46else if (config == DEFAULT_OVERRIDE_CONFIG) \
47config = &bootInfo->overrideConfig ; \
48else if (config == DEFAULT_SMBIOS_CONFIG) \
49config = &bootInfo->smbiosConfig ; \
50else if (config == DEFAULT_HELPER_CONFIG) \
51config = &bootInfo->helperConfig ;
52
53#if UNUSED
54/*
55 * Compare a string to a key with quoted characters
56 */
57static inline int
58keyncmp(const char *str, const char *key, int n)
59{
60 int c;
61 while (n--) {
62c = *key++;
63if (c == '\\') {
64switch(c = *key++) {
65case 'n':
66c = '\n';
67break;
68case 'r':
69c = '\r';
70break;
71case 't':
72c = '\t';
73break;
74default:
75break;
76}
77} else if (c == '\"') {
78/* Premature end of key */
79return 1;
80}
81if (c != *str++) {
82return 1;
83}
84 }
85 return 0;
86}
87
88static void eatThru(char val, const char **table_p)
89{
90register const char *table = *table_p;
91register bool found = false;
92
93while (*table && !found)
94{
95if (*table == '\\') table += 2;
96else
97{
98if (*table == val) found = true;
99table++;
100}
101}
102*table_p = table;
103}
104
105/* Remove key and its associated value from the table. */
106
107bool
108removeKeyFromTable(const char *key, char *table)
109{
110 register int len;
111 register char *tab;
112 char *buf;
113
114 len = strlen(key);
115 tab = (char *)table;
116 buf = (char *)malloc(len + 3);
117
118 sprintf(buf, "\"%s\"", key);
119 len = strlen(buf);
120
121 while(*tab) {
122 if(strncmp(buf, tab, len) == 0) {
123 char c;
124
125 while((c = *(tab + len)) != ';') {
126 if(c == 0) {
127 len = -1;
128 goto out;
129 }
130 len++;
131 }
132 len++;
133 if(*(tab + len) == '\n') len++;
134 goto out;
135 }
136 tab++;
137 }
138 len = -1;
139out:
140 free(buf);
141
142 if(len == -1) return false;
143
144 while((*tab = *(tab + len))) {
145 tab++;
146 }
147
148 return true;
149}
150
151char *
152newStringFromList(
153 char **list,
154 int *size
155 )
156{
157 char *begin = *list, *end;
158 char *newstr;
159 int newsize = *size;
160 int bufsize;
161
162 while (*begin && newsize && isspace(*begin)) {
163begin++;
164newsize--;
165 }
166 end = begin;
167 while (*end && newsize && !isspace(*end)) {
168end++;
169newsize--;
170 }
171 if (begin == end)
172return 0;
173 bufsize = end - begin + 1;
174 newstr = malloc(bufsize);
175 strlcpy(newstr, begin, bufsize);
176 *list = end;
177 *size = newsize;
178 return newstr;
179}
180
181/*
182 * compress == compress escaped characters to one character
183 */
184int stringLength(const char *table, int compress)
185{
186int ret = 0;
187
188while (*table)
189{
190if (*table == '\\')
191{
192table += 2;
193ret += 1 + (compress ? 0 : 1);
194}
195else
196{
197if (*table == '\"') return ret;
198ret++;
199table++;
200}
201}
202return ret;
203}
204#endif
205
206bool getValueForConfigTableKey(config_file_t *config, const char *key, const char **val, int *size)
207{
208 ASSERT_CONFIG
209
210if (config->dictionary != 0 ) {
211// Look up key in XML dictionary
212TagPtr value;
213value = XMLGetProperty(config->dictionary, key);
214if (value != 0) {
215if (value->type != kTagTypeString) {
216error("Non-string tag '%s' found in config file\n",
217 key);
218return false;
219}
220*val = value->string;
221*size = strlen(value->string);
222return true;
223}
224} else {
225
226// Legacy plist-style table
227
228}
229
230return false;
231}
232
233#if UNUSED
234
235/*
236 * Returns a new malloc'ed string if one is found
237 * in the string table matching 'key'. Also translates
238 * \n escapes in the string.
239 */
240char *newStringForStringTableKey(
241 char *table,
242 char *key,
243 config_file_t *config
244 )
245{
246 const char *val;
247 char *newstr, *p;
248 int size;
249
250 ASSERT_CONFIG
251
252 if (getValueForConfigTableKey(config, key, &val, &size)) {
253newstr = (char *)malloc(size+1);
254for (p = newstr; size; size--, p++, val++) {
255if ((*p = *val) == '\\') {
256switch (*++val) {
257case 'r':
258*p = '\r';
259break;
260case 'n':
261*p = '\n';
262break;
263case 't':
264*p = '\t';
265break;
266default:
267*p = *val;
268break;
269}
270size--;
271}
272}
273*p = '\0';
274return newstr;
275 } else {
276return 0;
277 }
278}
279
280#endif
281
282char *
283newStringForKey(char *key, config_file_t *config)
284{
285 const char *val;
286 char *newstr;
287 int size;
288
289 ASSERT_CONFIG
290
291 if (getValueForKey(key, &val, &size, config) && size) {
292newstr = (char *)malloc(size + 1);
293strlcpy(newstr, val, size + 1);
294return newstr;
295 } else {
296return 0;
297 }
298}
299
300/* parse a command line
301 * in the form: [<argument> ...] [<option>=<value> ...]
302 * both <option> and <value> must be either composed of
303 * non-whitespace characters, or enclosed in quotes.
304 */
305
306static const char *getToken(const char *line, const char **begin, int *len)
307{
308 if (*line == '\"') {
309*begin = ++line;
310while (*line && *line != '\"')
311line++;
312*len = line++ - *begin;
313 } else {
314*begin = line;
315while (*line && !isspace(*line) && *line != '=')
316line++;
317*len = line - *begin;
318 }
319 return line;
320}
321
322bool getValueForBootKey(const char *line, const char *match, const char **matchval, int *len)
323{
324 const char *key, *value;
325 int key_len, value_len;
326 bool retval = false;
327
328 while (*line) {
329/* look for keyword or argument */
330while (isspace(*line)) line++;
331
332/* now look for '=' or whitespace */
333line = getToken(line, &key, &key_len);
334/* line now points to '=' or space */
335if (*line && !isspace(*line)) {
336line = getToken(++line, &value, &value_len);
337} else {
338value = line;
339value_len = 0;
340}
341if ((strlen(match) == key_len)
342&& strncmp(match, key, key_len) == 0) {
343*matchval = value;
344*len = value_len;
345retval = true;
346 /* Continue to look for this key; last one wins. */
347}
348 }
349 return retval;
350}
351
352/* Return NULL if no option has been successfully retrieved, or the string otherwise */
353const char * getStringForKey(const char * key, config_file_t *config)
354{
355static const char* value =0;
356int len=0;
357
358 ASSERT_CONFIG
359
360if(!getValueForKey(key, &value, &len, config)) value = 0;
361return value;
362}
363
364
365/* Returns TRUE if a value was found, FALSE otherwise.
366 * The boolean value of the key is stored in 'val'.
367 */
368
369bool getBoolForKey( const char *key, bool *result_val, config_file_t *config )
370{
371 const char *key_val;
372 int size;
373
374 ASSERT_CONFIG
375
376 if (getValueForKey(key, &key_val, &size, config)) {
377 if ( (size >= 1) && (key_val[0] == 'Y' || key_val[0] == 'y') ) {
378 *result_val = true;
379 } else {
380 *result_val = false;
381 }
382 return true;
383 }
384 return false;
385}
386
387bool getIntForKey( const char *key, int *value, config_file_t *config )
388{
389 const char *val;
390 int size, sum;
391 bool negative = false;
392
393 ASSERT_CONFIG
394
395 if (getValueForKey(key, &val, &size, config))
396{
397if ( size )
398{
399if (*val == '-')
400{
401negative = true;
402val++;
403size--;
404}
405
406for (sum = 0; size > 0; size--)
407{
408if (*val < '0' || *val > '9')
409return false;
410
411sum = (sum * 10) + (*val++ - '0');
412}
413
414if (negative)
415sum = -sum;
416
417*value = sum;
418return true;
419}
420}
421 return false;
422}
423
424config_file_t *resolveConfig(config_file_t *config)
425{
426ASSERT_CONFIG
427config_file_t *new_config = config;
428return new_config;
429}
430#if UNUSED
431/*
432 *
433 */
434
435bool getDimensionForKey( const char *key, unsigned int *value, config_file_t *config, unsigned int dimension_max, unsigned int object_size )
436{
437const char *val;
438
439 int size = 0;
440int sum = 0;
441
442bool negative = false;
443bool percentage = false;
444
445 ASSERT_CONFIG
446
447 if (getValueForKey(key, &val, &size, config))
448{
449if ( size )
450{
451if (*val == '-')
452{
453negative = true;
454val++;
455size--;
456}
457
458if (val[size-1] == '%')
459{
460percentage = true;
461size--;
462}
463
464// convert string to integer
465for (sum = 0; size > 0; size--)
466{
467if (*val < '0' || *val > '9')
468return false;
469
470sum = (sum * 10) + (*val++ - '0');
471}
472
473if (percentage)
474sum = ( dimension_max * sum ) / 100;
475
476// calculate offset from opposite origin
477if (negative)
478sum = ( ( dimension_max - object_size ) - sum );
479
480} else {
481
482// null value calculate center
483sum = ( dimension_max - object_size ) / 2;
484
485}
486
487*value = (uint16_t) sum;
488return true;
489}
490
491// key not found
492 return false;
493}
494
495/*
496 *get color value from plist format #RRGGBB
497 */
498
499bool getColorForKey( const char *key, unsigned int *value, config_file_t *config )
500{
501 const char *val;
502 int size;
503
504 ASSERT_CONFIG
505
506 if (getValueForKey(key, &val, &size, config))
507{
508if (*val == '#')
509{
510 val++;
511*value = strtol(val, NULL, 16);
512return true;
513 }
514 }
515 return false;
516}
517#endif
518
519bool getValueForKey( const char *key, const char **val, int *size, config_file_t *config )
520{
521 const char *overrideVal;
522 int overrideSize;
523 bool ret;
524
525 if (getValueForBootKey(bootArgs->CommandLine, key, val, size))
526 return true;
527
528 ASSERT_CONFIG
529
530 ret = getValueForConfigTableKey(config, key, val, size);
531
532 // Try to find alternate keys in bootInfo->overrideConfig
533 // and prefer its values with the exceptions for
534 // "Kernel"="mach_kernel" and "Kernel Flags"="".
535
536 if (config->canOverride)
537 {
538 if (getValueForConfigTableKey(&bootInfo->overrideConfig, key, &overrideVal, &overrideSize) && overrideSize)
539 {
540 *val = overrideVal;
541 *size = overrideSize;
542 return true;
543 }
544 else if (getValueForConfigTableKey(&bootInfo->SystemConfig, key, &overrideVal, &overrideSize) && overrideSize)
545 {
546 *val = overrideVal;
547 *size = overrideSize;
548 return true;
549 }
550 else if (getValueForConfigTableKey(&bootInfo->bootConfig, key, &overrideVal, &overrideSize) && overrideSize)
551 {
552 *val = overrideVal;
553 *size = overrideSize;
554 return true;
555 }
556 }
557
558 return ret;
559}
560
561
562#if UNUSED
563void
564printSystemConfig(char *p1)
565{
566 char *p2 = p1, tmp;
567
568 while (*p1 != '\0') {
569while (*p2 != '\0' && *p2 != '\n') p2++;
570tmp = *p2;
571*p2 = '\0';
572printf("%s\n", p1);
573*p2 = tmp;
574if (tmp == '\0') break;
575p1 = ++p2;
576 }
577}
578#endif
579
580//==========================================================================
581// ParseXMLFile
582// Modifies the input buffer.
583// Expects to see one dictionary in the XML file.
584// Puts the first dictionary it finds in the
585// tag pointer and returns 0, or returns -1 if not found
586// (and does not modify dict pointer).
587// Prints an error message if there is a parsing error.
588//
589int ParseXMLFile( char * buffer, TagPtr * dict )
590{
591 long length, pos;
592 TagPtr tag;
593 pos = 0;
594 char *configBuffer;
595
596 configBuffer = malloc(strlen(buffer)+1);
597 if (!configBuffer) {
598 return -1;
599 }
600
601 strcpy(configBuffer, buffer);
602
603 while (1)
604 {
605 length = XMLParseNextTag(configBuffer + pos, &tag);
606 if (length == -1) break;
607
608 pos += length;
609
610 if (tag == 0) continue;
611 if (tag->type == kTagTypeDict) break;
612
613 XMLFreeTag(tag);
614 }
615 free(configBuffer);
616 if (length < 0) {
617 error ("Error parsing plist file\n");
618 return -1;
619 }
620 *dict = tag;
621 return 0;
622}
623
624/* loadConfigFile
625 *
626 * Returns 0 - successful.
627 * -1 - unsuccesful.
628 */
629int loadConfigFile (const char *configFile, config_file_t *config)
630{
631int fd, count, fixedsize;
632
633 ASSERT_CONFIG
634
635if ((fd = open(configFile)) < 0) {
636return -1;
637}
638
639 fixedsize = MIN(file_size(fd),IO_CONFIG_DATA_SIZE);
640
641// read file
642count = read(fd, config->plist, fixedsize);
643close(fd);
644 if (count != fixedsize) return -1;
645
646// build xml dictionary
647return ParseXMLFile(config->plist, &config->dictionary);
648}
649
650/* loadBooterConfig
651 *
652 * Returns 0 - successful.
653 * -1 - unsuccesful.
654 */
655int loadBooterConfig(void)
656{
657char *dirspec[] = {
658"rd(0,0)/Extra/com.apple.Boot.plist",
659"/Extra/com.apple.Boot.plist",
660"bt(0,0)/Extra/com.apple.Boot.plist",
661"rd(0,0)/Extra/org.chameleon.Boot.plist", // Add compatibility with the trunk
662"/Extra/org.chameleon.Boot.plist", // Add compatibility with the trunk
663"bt(0,0)/Extra/org.chameleon.Boot.plist" // Add compatibility with the trunk
664
665};
666
667 config_file_t *config = &bootInfo->bootConfig;
668
669int i, fd, count, ret=-1, fixedsize;
670
671for(i = 0; (unsigned)i< sizeof(dirspec)/sizeof(dirspec[0]); i++)
672{
673if ((fd = open(dirspec[i])) >= 0)
674{
675// read file
676 fixedsize = MIN(file_size(fd),IO_CONFIG_DATA_SIZE);
677count = read(fd, config->plist, fixedsize);
678close(fd);
679 if (count != fixedsize) continue;
680
681// build xml dictionary
682ParseXMLFile(config->plist, &config->dictionary);
683 safe_set_env(envSysConfigValid,true);
684ret=0;
685
686// enable canOverride flag
687config->canOverride = true;
688
689break;
690}
691}
692#ifdef BOOT_HELPER_SUPPORT
693if(ret == -1)
694{
695ret = loadHelperConfig();
696}
697#endif
698
699return ret;
700}
701
702/* loadOverrideConfig
703 *
704 * Returns 0 - successful.
705 * -1 - unsuccesful.
706 */
707int loadOverrideConfig(void)
708{
709char *dirspec[] = {
710"/Extra/com.apple.Boot.plist",
711"/Extra/org.chameleon.Boot.plist"
712};
713
714 config_file_t *config = &bootInfo->overrideConfig;
715
716
717int i, fd, count, ret=-1, fixedsize;
718
719for(i = 0; (unsigned)i< sizeof(dirspec)/sizeof(dirspec[0]); i++)
720{
721if ((fd = open(dirspec[i])) >= 0)
722{
723// read file
724fixedsize = MIN(file_size(fd),IO_CONFIG_DATA_SIZE);
725count = read(fd, config->plist, fixedsize);
726close(fd);
727 if (count != fixedsize) continue;
728
729// build xml dictionary
730ParseXMLFile(config->plist, &config->dictionary);
731 safe_set_env(envSysConfigValid,true);
732ret=0;
733break;
734}
735}
736#ifdef BOOT_HELPER_SUPPORT
737if(ret == -1)
738{
739ret = loadHelperConfig();
740}
741#endif
742
743return ret;
744}
745
746/* loadSystemConfig
747 *
748 * Returns 0 - successful.
749 * -1 - unsuccesful.
750 */
751int loadSystemConfig(void)
752{
753char *dirspec[] = {
754 "rd(0,0)/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
755"/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
756"bt(0,0)/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
757 "rd(0,0)/OS X Install Data/com.apple.Boot.plist",
758"/OS X Install Data/com.apple.Boot.plist",
759"bt(0,0)/OS X Install Data/com.apple.Boot.plist",
760 "rd(0,0)/Mac OS X Install Data/com.apple.Boot.plist",
761"/Mac OS X Install Data/com.apple.Boot.plist",
762"bt(0,0)/Mac OS X Install Data/com.apple.Boot.plist"
763};
764
765 config_file_t *config = &bootInfo->SystemConfig;
766
767
768int i, fd, count, ret=-1, fixedsize;
769
770for(i = 0; (unsigned)i< sizeof(dirspec)/sizeof(dirspec[0]); i++)
771{
772if ((fd = open(dirspec[i])) >= 0)
773{
774// read file
775fixedsize = MIN(file_size(fd),IO_CONFIG_DATA_SIZE);
776count = read(fd, config->plist, fixedsize);
777close(fd);
778 if (count != fixedsize) continue;
779
780// build xml dictionary
781ParseXMLFile(config->plist, &config->dictionary);
782 safe_set_env(envSysConfigValid,true);
783ret=0;
784break;
785}
786}
787
788return ret;
789}
790
791#ifdef BOOT_HELPER_SUPPORT
792
793/* loadHelperConfig
794 *
795 * Returns 0 - successful.
796 * -1 - unsuccesful.
797 */
798int loadHelperConfig(void)
799{
800int rfd, pfd, sfd, count, ret=-1, fixedsize;
801
802char *dirspec[] = {
803"/com.apple.boot.P/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
804"/com.apple.boot.R/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
805"/com.apple.boot.S/Library/Preferences/SystemConfiguration/com.apple.Boot.plist"
806};
807
808 config_file_t *config = &bootInfo->helperConfig;
809
810
811// This is a simple rock - paper scissors algo. R beats S, P beats R, S beats P
812// If all three, S is used for now. This should be change dto something else (say, timestamp?)
813
814pfd = open(dirspec[0]);
815if(pfd >= 0)// com.apple.boot.P exists
816{
817sfd = open(dirspec[2]); // com.apple.boot.S takes precidence if it also exists
818if(sfd >= 0)
819{
820// Use sfd
821 fixedsize = MIN(file_size(sfd),IO_CONFIG_DATA_SIZE);
822count = read(sfd, config->plist, fixedsize);
823close(sfd);
824close(pfd);
825 if (count != fixedsize) return -1;
826
827// build xml dictionary
828ParseXMLFile(config->plist, &config->dictionary);
829 safe_set_env(envSysConfigValid,true);
830ret=0;
831
832}
833else
834{
835// used pfd
836 fixedsize = MIN(file_size(pfd),IO_CONFIG_DATA_SIZE);
837count = read(pfd, config->plist, fixedsize);
838close(pfd);
839 if (count != fixedsize) return -1;
840
841// build xml dictionary
842ParseXMLFile(config->plist, &config->dictionary);
843 safe_set_env(envSysConfigValid,true);
844ret=0;
845}
846
847}
848else
849{
850rfd = open(dirspec[1]); // com.apple.boot.R exists
851if(rfd >= 0)
852{
853pfd = open(dirspec[2]); // com.apple.boot.P takes recidence if it exists
854if(pfd >= 0)
855{
856// use sfd
857 fixedsize = MIN(file_size(pfd),IO_CONFIG_DATA_SIZE);
858count = read(pfd, config->plist, fixedsize);
859close(pfd);
860close(rfd);
861 if (count != fixedsize) return -1;
862
863// build xml dictionary
864ParseXMLFile(config->plist, &config->dictionary);
865 safe_set_env(envSysConfigValid,true);
866ret=0;
867
868}
869else
870{
871// use rfd
872 fixedsize = MIN(file_size(rfd),IO_CONFIG_DATA_SIZE);
873count = read(rfd, config->plist, fixedsize);
874close(rfd);
875 if (count != fixedsize) return -1;
876
877// build xml dictionary
878ParseXMLFile(config->plist, &config->dictionary);
879 safe_set_env(envSysConfigValid,true);
880ret=0;
881
882}
883
884}
885else
886{
887sfd = open(dirspec[2]); // com.apple.boot.S exists, but nothing else does
888if(sfd >= 0)
889{
890// use sfd
891 fixedsize = MIN(file_size(sfd),IO_CONFIG_DATA_SIZE);
892count = read(sfd, config->plist, fixedsize);
893close(sfd);
894 if (count != fixedsize) return -1;
895
896// build xml dictionary
897ParseXMLFile(config->plist, &config->dictionary);
898 safe_set_env(envSysConfigValid,true);
899ret=0;
900
901}
902}
903
904}
905
906return ret;
907}
908#endif
909
910static char * AllocInitStringWithLength(const char * oldString, int len)
911{
912char *Buf = NULL;
913Buf = malloc(len);
914if (Buf == NULL) return NULL;
915
916if (oldString != NULL)
917strlcpy(Buf, oldString,len);
918
919return Buf;
920}
921
922static char * AllocInitZeroEndedStringWithLength(const char * oldString, int len)
923{
924if (len > 0)
925{
926return AllocInitStringWithLength( oldString, len + 1);
927}
928return NULL;
929}
930
931char * newString(const char * oldString)
932{
933 if ( oldString )
934{
935int len = strlen(oldString);
936
937if (len > 0)
938{
939return AllocInitZeroEndedStringWithLength(oldString, len);
940}
941}
942 return NULL;
943}
944
945char * newStringWithLength(const char * oldString, int len)
946{
947if (len > 0)
948{
949return AllocInitZeroEndedStringWithLength(oldString, len);
950}
951 return NULL;
952}
953
954char * newEmptyStringWithLength(int len)
955{
956if (len > 0)
957{
958return AllocInitZeroEndedStringWithLength(NULL, len);
959}
960 return NULL;
961}
962
963/*
964 * Extracts the next argument from the command line, double quotes are allowed here.
965 */
966char * getNextArg(char ** argPtr, char * val)
967{
968char * ptr = *argPtr;
969const char * strStart;
970int len = 0;
971bool isQuoted = false;
972
973*val = '\0';
974
975// Scan for the next non-whitespace character.
976while ( *ptr && (*ptr == ' ' || *ptr == '=') )
977{
978ptr++;
979}
980
981strStart = ptr;
982
983// Skip the leading double quote character.
984if (*ptr == '\"')
985{
986isQuoted = true;
987ptr++;
988strStart++;
989}
990
991// Scan for the argument terminator character.
992// This can be either a NULL character - in case we reach the end of the string,
993// a double quote in case of quoted argument,
994// or a whitespace character (' ' or '=') for non-quoted argument.
995while (*ptr && !( (isQuoted && (*ptr == '\"')) ||
996 (!isQuoted && (*ptr == ' ' || *ptr == '=')) )
997 )
998{
999ptr++;
1000}
1001
1002len = ptr - strStart;
1003
1004// Skip the closing double quote character and adjust
1005// the starting pointer for the next getNextArg call.
1006if (*ptr && isQuoted && *ptr == '\"')
1007ptr++;
1008
1009// Copy the extracted argument to val.
1010strncat(val, strStart, len);
1011
1012// Set command line pointer.
1013*argPtr = ptr;
1014
1015return ptr;
1016}
1017

Archive Download this file

Revision: 1972