|
1 // command_info_file.cpp |
|
2 // |
|
3 // Copyright (c) 2009 - 2010 Accenture. All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of the "Eclipse Public License v1.0" |
|
6 // which accompanies this distribution, and is available |
|
7 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 // |
|
9 // Initial Contributors: |
|
10 // Accenture - Initial contribution |
|
11 // |
|
12 |
|
13 #include <f32file.h> |
|
14 #include "ioutils.h" |
|
15 #include "command_base.h" |
|
16 |
|
17 _LIT(KCifExt, ".cif"); |
|
18 _LIT(KCifPathVar, "CIF_PATH"); |
|
19 _LIT(KCifPath, "\\resource\\cif\\fshell"); |
|
20 _LIT(KEnumSeparator, ","); |
|
21 _LIT(KEnumQuote, "\""); |
|
22 _LIT(KNewLine, "\r\n"); |
|
23 _LIT(KPartialCommandStart, "=="); |
|
24 _LIT(KCommandStart, "\r\n=="); |
|
25 _LIT(KCmndName, "name"); |
|
26 _LIT(KCmndShortDescription, "short-description"); |
|
27 _LIT(KCmndLongDescription, "long-description"); |
|
28 _LIT(KCmndSeeAlso, "see-also"); |
|
29 _LIT(KCmndCopyright, "copyright"); |
|
30 _LIT(KCmndArgument, "argument"); |
|
31 _LIT(KCmndOption, "option"); |
|
32 _LIT(KCmndInclude, "include"); |
|
33 _LIT(KCmndSubCommand, "sub-command"); |
|
34 _LIT(KCmndEnumValue, "enum-value"); |
|
35 _LIT(KCmndFlagOptional, "optional"); |
|
36 _LIT(KCmndFlagMultiple, "multiple"); |
|
37 _LIT(KCmndFlagLast, "last"); |
|
38 _LIT(KTypeBool, "bool"); |
|
39 _LIT(KTypeInt, "int"); |
|
40 _LIT(KTypeUint, "uint"); |
|
41 _LIT(KTypeString, "string"); |
|
42 _LIT(KTypeFileName, "filename"); |
|
43 _LIT(KTypeEnum, "enum"); |
|
44 _LIT(KTypeReal, "real"); |
|
45 _LIT(KTypeUint64, "uint64"); |
|
46 _LIT(KTypeInt64, "int64"); |
|
47 |
|
48 using namespace IoUtils; |
|
49 |
|
50 TInt SkipTo(TLex& aLex, const TDesC& aDes) |
|
51 { |
|
52 TInt ret = aLex.Remainder().Find(aDes); |
|
53 if (ret >= 0) |
|
54 { |
|
55 aLex.Inc(ret); |
|
56 return KErrNone; |
|
57 } |
|
58 return KErrNotFound; |
|
59 } |
|
60 |
|
61 TInt SkipToEnd(TLex& aLex, const TDesC& aDes) |
|
62 { |
|
63 TInt ret = aLex.Remainder().Find(aDes); |
|
64 if (ret >= 0) |
|
65 { |
|
66 aLex.Inc(ret + aDes.Length()); |
|
67 return KErrNone; |
|
68 } |
|
69 return KErrNotFound; |
|
70 } |
|
71 |
|
72 TInt SkipToNextCommand(TLex& aLex) |
|
73 { |
|
74 if ((aLex.Offset() == 0) && (aLex.Remainder().Find(KPartialCommandStart) == 0)) |
|
75 { |
|
76 return KErrNone; |
|
77 } |
|
78 |
|
79 return SkipTo(aLex, KCommandStart); |
|
80 } |
|
81 |
|
82 TPtrC NextCommand(TLex& aLex) |
|
83 { |
|
84 TPtrC command; |
|
85 if (SkipToNextCommand(aLex) == KErrNone) |
|
86 { |
|
87 SkipToEnd(aLex, KPartialCommandStart); |
|
88 aLex.Mark(); |
|
89 aLex.SkipCharacters(); |
|
90 command.Set(aLex.MarkedToken()); |
|
91 } |
|
92 else |
|
93 { |
|
94 aLex.Inc(aLex.Remainder().Length()); |
|
95 } |
|
96 return command; |
|
97 } |
|
98 |
|
99 TPtrC LineRemainder(TLex& aLex) |
|
100 { |
|
101 aLex.Mark(); |
|
102 if (SkipTo(aLex, KNewLine) == KErrNone) |
|
103 { |
|
104 return aLex.MarkedToken(); |
|
105 } |
|
106 else |
|
107 { |
|
108 return aLex.Remainder(); |
|
109 } |
|
110 } |
|
111 |
|
112 TPtrC NextWord(TLex& aLex) |
|
113 { |
|
114 aLex.SkipSpaceAndMark(); |
|
115 aLex.SkipCharacters(); |
|
116 TPtrC word(aLex.MarkedToken()); |
|
117 return word; |
|
118 } |
|
119 |
|
120 TPtrC TextToNextCommand(TLex& aLex) |
|
121 { |
|
122 aLex.Mark(); |
|
123 |
|
124 if (SkipToNextCommand(aLex) != KErrNone) |
|
125 { |
|
126 aLex.Inc(aLex.Remainder().Length()); |
|
127 } |
|
128 |
|
129 TLex lex(aLex.MarkedToken()); |
|
130 |
|
131 // Strip leading white space. |
|
132 while (!lex.Eos()) |
|
133 { |
|
134 if (lex.Peek().IsSpace()) |
|
135 { |
|
136 lex.Get(); |
|
137 } |
|
138 else |
|
139 { |
|
140 break; |
|
141 } |
|
142 } |
|
143 lex.Mark(); |
|
144 TInt startOffset = lex.Offset(); |
|
145 |
|
146 // Remove trailing white space. |
|
147 lex.Inc(lex.Remainder().Length()); |
|
148 while (lex.Offset() > startOffset) |
|
149 { |
|
150 lex.UnGet(); |
|
151 if (!lex.Peek().IsSpace()) |
|
152 { |
|
153 lex.Get(); |
|
154 break; |
|
155 } |
|
156 } |
|
157 |
|
158 return lex.MarkedToken(); |
|
159 } |
|
160 |
|
161 void AppendL(RBuf& aBuf, const TDesC& aDes, TBool aQuote) |
|
162 { |
|
163 const TInt requiredSpace = aDes.Length() + ((aBuf.Length() == 0) ? 0 : KEnumSeparator().Length()) + (aQuote ? 2 : 0); |
|
164 if ((aBuf.Length() + requiredSpace) > aBuf.MaxLength()) |
|
165 { |
|
166 aBuf.ReAllocL(Max(aBuf.Length() * 2, aBuf.Length() + requiredSpace)); |
|
167 } |
|
168 if (aBuf.Length() > 0) |
|
169 { |
|
170 aBuf.Append(KEnumSeparator); |
|
171 } |
|
172 if (aQuote) |
|
173 { |
|
174 aBuf.Append(KEnumQuote); |
|
175 } |
|
176 aBuf.Append(aDes); |
|
177 if (aQuote) |
|
178 { |
|
179 aBuf.Append(KEnumQuote); |
|
180 } |
|
181 } |
|
182 |
|
183 void GetEnumValuesL(TLex& aLex, RBuf& aValues, RBuf& aDescriptions) |
|
184 { |
|
185 aValues.CreateL(0x100); |
|
186 aDescriptions.CreateL(0x100); |
|
187 |
|
188 while (!aLex.Eos()) |
|
189 { |
|
190 TLexMark mark; |
|
191 aLex.Mark(mark); |
|
192 TPtrC command(NextCommand(aLex)); |
|
193 if (command == KCmndEnumValue) |
|
194 { |
|
195 TPtrC value(NextWord(aLex)); |
|
196 TPtrC description(TextToNextCommand(aLex)); |
|
197 if (value.Length() == 0) |
|
198 { |
|
199 User::Leave(KErrArgument); |
|
200 } |
|
201 AppendL(aValues, value, EFalse); |
|
202 if (description.Length() > 0) |
|
203 { |
|
204 AppendL(aDescriptions, description, ETrue); |
|
205 } |
|
206 } |
|
207 else |
|
208 { |
|
209 aLex.UnGetToMark(mark); |
|
210 break; |
|
211 } |
|
212 } |
|
213 } |
|
214 |
|
215 |
|
216 EXPORT_C CCommandInfoFile* CCommandInfoFile::NewL(RFs& aFs, const TDesC& aFileName) |
|
217 { |
|
218 CCommandInfoFile* self = new(ELeave) CCommandInfoFile(aFileName); |
|
219 CleanupStack::PushL(self); |
|
220 self->ConstructL(aFs); |
|
221 CleanupStack::Pop(self); |
|
222 return self; |
|
223 } |
|
224 |
|
225 EXPORT_C CCommandInfoFile* CCommandInfoFile::NewL(RFs& aFs, const CEnvironment& aEnvironment, const TDesC& aCommandName) |
|
226 { |
|
227 TFileName2 fileName; |
|
228 TRAPD(err, fileName.Copy(aEnvironment.GetAsDesL(KCifPathVar))); |
|
229 if (err) fileName.Copy(KCifPath); |
|
230 |
|
231 // Search the drive the command is running from first (rather than what the session path happens to be, which was the previous behaviour) |
|
232 if (!fileName.HasDriveLetter()) fileName.Insert(0, _L("?:")); |
|
233 fileName[0] = RProcess().FileName()[0]; |
|
234 |
|
235 fileName.AppendComponentL(aCommandName); |
|
236 fileName.SetExtL(KCifExt); |
|
237 StaticLeaveIfErr(fileName.FindFile(aFs), _L("Couldn't find \"%S\""), &fileName); |
|
238 |
|
239 CCommandInfoFile* cif = CCommandInfoFile::NewL(aFs, fileName); |
|
240 if (cif->Name() != aCommandName) |
|
241 { |
|
242 CleanupStack::PushL(cif); |
|
243 StaticLeaveIfErr(KErrArgument, _L("Command named \"%S\" in implementation but \"%S\" in \"%S\""), &aCommandName, &cif->Name(), &fileName); |
|
244 } |
|
245 return cif; |
|
246 } |
|
247 |
|
248 void CCommandInfoFile::ConstructL(RFs& aFs) |
|
249 { |
|
250 ReadFileL(aFs, iFileName); |
|
251 } |
|
252 |
|
253 void CCommandInfoFile::ReadFileL(RFs& aFs, const TDesC& aFileName) |
|
254 { |
|
255 // Read the file into a buffer. |
|
256 RFile file; |
|
257 StaticLeaveIfErr(file.Open(aFs, aFileName, EFileRead | EFileShareReadersOnly), _L("Couldn't open '%S' for reading"), &aFileName); |
|
258 CleanupClosePushL(file); |
|
259 TInt fileSize; |
|
260 User::LeaveIfError(file.Size(fileSize)); |
|
261 RBuf8 buf8; |
|
262 buf8.CreateL(fileSize); |
|
263 buf8.CleanupClosePushL(); |
|
264 User::LeaveIfError(file.Read(buf8)); |
|
265 RBuf& buf = NewBuffer(); |
|
266 buf.CreateL(fileSize); |
|
267 buf.Copy(buf8); |
|
268 CleanupStack::PopAndDestroy(2, &file); |
|
269 TLex lex(buf); |
|
270 while (!lex.Eos()) |
|
271 { |
|
272 if (iProcessInclude || !iCurrentChild) |
|
273 { |
|
274 ReadDetailsL(lex, aFs, aFileName); |
|
275 } |
|
276 else |
|
277 { |
|
278 iCurrentChild->ReadDetailsL(lex, aFs, aFileName); |
|
279 } |
|
280 } |
|
281 } |
|
282 |
|
283 void CCommandInfoFile::ReadDetailsL(TLex& aLex, RFs& aFs, const TDesC& aFileName) |
|
284 { |
|
285 SkipToNextCommand(aLex); // Ignore everything before the first '==' command. |
|
286 |
|
287 while (!aLex.Eos()) |
|
288 { |
|
289 TLexMark mark; |
|
290 aLex.Mark(mark); |
|
291 TPtrC command(NextCommand(aLex)); |
|
292 if (command == KNullDesC) |
|
293 { |
|
294 // Do nothing - we're at the end of the string. |
|
295 } |
|
296 else if (command == KCmndName) |
|
297 { |
|
298 aLex.SkipSpaceAndMark(); |
|
299 aLex.SkipCharacters(); |
|
300 iName.Set(aLex.MarkedToken()); |
|
301 } |
|
302 else if (command == KCmndShortDescription) |
|
303 { |
|
304 iShortDescription.Set(TextToNextCommand(aLex)); |
|
305 } |
|
306 else if (command == KCmndLongDescription) |
|
307 { |
|
308 iLongDescription.Set(TextToNextCommand(aLex)); |
|
309 } |
|
310 else if (command == KCmndSeeAlso) |
|
311 { |
|
312 iSeeAlso.Set(TextToNextCommand(aLex)); |
|
313 } |
|
314 else if (command == KCmndCopyright) |
|
315 { |
|
316 iCopyright.Set(TextToNextCommand(aLex)); |
|
317 } |
|
318 else if (command == KCmndArgument) |
|
319 { |
|
320 ReadArgumentL(aLex, aFileName); |
|
321 } |
|
322 else if (command == KCmndOption) |
|
323 { |
|
324 ReadOptionL(aLex, aFileName); |
|
325 } |
|
326 else if (command == KCmndInclude) |
|
327 { |
|
328 if (iParent == NULL) |
|
329 { |
|
330 iProcessInclude = EFalse; |
|
331 TLex lineLex(LineRemainder(aLex)); |
|
332 TPtrC fileName(NextWord(lineLex)); |
|
333 TFileName2* fullFileName = new(ELeave) TFileName2(aFileName); |
|
334 CleanupStack::PushL(fullFileName); |
|
335 fullFileName->SetNameAndExtL(fileName); |
|
336 ReadFileL(aFs, *fullFileName); |
|
337 CleanupStack::PopAndDestroy(fullFileName); |
|
338 break; |
|
339 } |
|
340 else |
|
341 { |
|
342 // We're a sub-command. Let control return to the root to handle the include. |
|
343 aLex.UnGetToMark(mark); |
|
344 iParent->ProcessInclude(*this); |
|
345 break; |
|
346 } |
|
347 } |
|
348 else if (command == KCmndSubCommand) |
|
349 { |
|
350 if (iParent == NULL) |
|
351 { |
|
352 TLex lineLex(LineRemainder(aLex)); |
|
353 AddSubCommandL(lineLex, aLex, aFs, aFileName); |
|
354 } |
|
355 else |
|
356 { |
|
357 // We're a sub-command. Let control return to the root to handle the next sub-command. |
|
358 aLex.UnGetToMark(mark); |
|
359 iParent->ProcessNewChild(); |
|
360 break; |
|
361 } |
|
362 } |
|
363 else |
|
364 { |
|
365 StaticLeaveIfErr(KErrArgument, _L("Unknown command \"%S\" in \"%S\""), &command, &aFileName); |
|
366 } |
|
367 } |
|
368 } |
|
369 |
|
370 void CCommandInfoFile::ReadArgumentL(TLex& aLex, const TDesC& aFileName) |
|
371 { |
|
372 TLex lineLex(LineRemainder(aLex)); |
|
373 TUint flags = 0; |
|
374 TBool multiple(EFalse); |
|
375 TPtrC argType(NextWord(lineLex)); |
|
376 TPtrC argName(NextWord(lineLex)); |
|
377 TPtrC envVar; |
|
378 while (!lineLex.Eos()) |
|
379 { |
|
380 TPtrC word(NextWord(lineLex)); |
|
381 if (word == KCmndFlagOptional) |
|
382 { |
|
383 flags |= KValueTypeFlagOptional; |
|
384 } |
|
385 else if (word == KCmndFlagMultiple) |
|
386 { |
|
387 multiple = ETrue; |
|
388 } |
|
389 else if (word == KCmndFlagLast) |
|
390 { |
|
391 flags |= KValueTypeFlagLast; |
|
392 } |
|
393 else |
|
394 { |
|
395 envVar.Set(word); |
|
396 } |
|
397 } |
|
398 |
|
399 if (argType.Length() == 0) |
|
400 { |
|
401 StaticLeaveIfErr(KErrArgument, _L("Argument missing type")); |
|
402 } |
|
403 else if (argName.Length() == 0) |
|
404 { |
|
405 StaticLeaveIfErr(KErrArgument, _L("Argument missing name")); |
|
406 } |
|
407 else |
|
408 { |
|
409 TPtrC argDescription = TextToNextCommand(aLex); |
|
410 if (argType == KTypeEnum) |
|
411 { |
|
412 RBuf& enumValues = NewBuffer(); |
|
413 RBuf& enumDescriptions = NewBuffer(); |
|
414 GetEnumValuesL(aLex, enumValues, enumDescriptions); |
|
415 if (multiple) |
|
416 { |
|
417 RArray<TInt> dummyArray; |
|
418 if (enumDescriptions.Length() > 0) |
|
419 { |
|
420 iArguments.AppendEnumL(dummyArray, argName, argDescription, enumValues, enumDescriptions, flags, envVar); |
|
421 } |
|
422 else |
|
423 { |
|
424 iArguments.AppendEnumL(dummyArray, argName, argDescription, enumValues, flags, envVar); |
|
425 } |
|
426 } |
|
427 else |
|
428 { |
|
429 TInt dummyInt; |
|
430 if (enumDescriptions.Length() > 0) |
|
431 { |
|
432 iArguments.AppendEnumL(dummyInt, argName, argDescription, enumValues, enumDescriptions, flags, envVar); |
|
433 } |
|
434 else |
|
435 { |
|
436 iArguments.AppendEnumL(dummyInt, argName, argDescription, enumValues, flags, envVar); |
|
437 } |
|
438 } |
|
439 } |
|
440 else if (argType == KTypeInt) |
|
441 { |
|
442 if (multiple) |
|
443 { |
|
444 RArray<TInt> dummyArray; |
|
445 iArguments.AppendIntL(dummyArray, argName, argDescription, flags, envVar); |
|
446 } |
|
447 else |
|
448 { |
|
449 TInt dummyInt; |
|
450 iArguments.AppendIntL(dummyInt, argName, argDescription, flags, envVar); |
|
451 } |
|
452 } |
|
453 else if (argType == KTypeUint) |
|
454 { |
|
455 if (multiple) |
|
456 { |
|
457 RArray<TUint> dummyArray; |
|
458 iArguments.AppendUintL(dummyArray, argName, argDescription, flags, envVar); |
|
459 } |
|
460 else |
|
461 { |
|
462 TUint dummyUint; |
|
463 iArguments.AppendUintL(dummyUint, argName, argDescription, flags, envVar); |
|
464 } |
|
465 } |
|
466 else if (argType == KTypeString) |
|
467 { |
|
468 if (multiple) |
|
469 { |
|
470 RPointerArray<HBufC> dummyArray; |
|
471 iArguments.AppendStringL(dummyArray, argName, argDescription, flags, envVar); |
|
472 } |
|
473 else |
|
474 { |
|
475 HBufC* dummyHBufC; |
|
476 iArguments.AppendStringL(dummyHBufC, argName, argDescription, flags, envVar); |
|
477 } |
|
478 } |
|
479 else if (argType == KTypeFileName) |
|
480 { |
|
481 if (multiple) |
|
482 { |
|
483 RArray<TFileName2> dummyArray; |
|
484 iArguments.AppendFileNameL(dummyArray, argName, argDescription, flags, envVar); |
|
485 } |
|
486 else |
|
487 { |
|
488 TFileName2 dummyFileName; |
|
489 iArguments.AppendFileNameL(dummyFileName, argName, argDescription, flags, envVar); |
|
490 } |
|
491 } |
|
492 else if (argType == KTypeReal) |
|
493 { |
|
494 if (multiple) |
|
495 { |
|
496 RArray<TReal64> dummyArray; |
|
497 iArguments.AppendRealL(dummyArray, argName, argDescription, flags, envVar); |
|
498 } |
|
499 else |
|
500 { |
|
501 TReal64 dummyReal; |
|
502 iArguments.AppendRealL(dummyReal, argName, argDescription, flags, envVar); |
|
503 } |
|
504 } |
|
505 else if (argType == KTypeUint64) |
|
506 { |
|
507 if (multiple) |
|
508 { |
|
509 RArray<TUint64> dummyArray; |
|
510 iArguments.AppendUintL(dummyArray, argName, argDescription, flags, envVar); |
|
511 } |
|
512 else |
|
513 { |
|
514 TUint64 dummyUint64; |
|
515 iArguments.AppendUintL(dummyUint64, argName, argDescription, flags, envVar); |
|
516 } |
|
517 } |
|
518 else if (argType == KTypeInt64) |
|
519 { |
|
520 if (multiple) |
|
521 { |
|
522 RArray<TInt64> dummyArray; |
|
523 iArguments.AppendIntL(dummyArray, argName, argDescription, flags, envVar); |
|
524 } |
|
525 else |
|
526 { |
|
527 TInt64 dummyInt64; |
|
528 iArguments.AppendIntL(dummyInt64, argName, argDescription, flags, envVar); |
|
529 } |
|
530 } |
|
531 else |
|
532 { |
|
533 StaticLeaveIfErr(KErrArgument, _L("Unknown argument type \"%S\" in \"%S\""), &argType, &aFileName); |
|
534 } |
|
535 } |
|
536 } |
|
537 |
|
538 void CCommandInfoFile::ReadOptionL(TLex& aLex, const TDesC& aFileName) |
|
539 { |
|
540 TLex lineLex(LineRemainder(aLex)); |
|
541 TBool multiple(EFalse); |
|
542 TPtrC optType(NextWord(lineLex)); |
|
543 TPtrC optShortName(NextWord(lineLex)); |
|
544 TPtrC optLongName(NextWord(lineLex)); |
|
545 TPtrC envVar; |
|
546 while (!lineLex.Eos()) |
|
547 { |
|
548 TPtrC word(NextWord(lineLex)); |
|
549 if (word == KCmndFlagMultiple) |
|
550 { |
|
551 multiple = ETrue; |
|
552 } |
|
553 else |
|
554 { |
|
555 envVar.Set(word); |
|
556 } |
|
557 } |
|
558 |
|
559 if (optType.Length() == 0) |
|
560 { |
|
561 StaticLeaveIfErr(KErrArgument, _L("Option missing type")); |
|
562 } |
|
563 else if (optShortName.Length() == 0) |
|
564 { |
|
565 StaticLeaveIfErr(KErrArgument, _L("Option missing short name")); |
|
566 } |
|
567 else if (optShortName.Length() != 1) |
|
568 { |
|
569 StaticLeaveIfErr(KErrArgument, _L("Option short name not a single character")); |
|
570 } |
|
571 else if (optLongName.Length() == 0) |
|
572 { |
|
573 StaticLeaveIfErr(KErrArgument, _L("Option missing long name")); |
|
574 } |
|
575 else |
|
576 { |
|
577 TPtrC argDescription = TextToNextCommand(aLex); |
|
578 if (optType == KTypeEnum) |
|
579 { |
|
580 RBuf& enumValues = NewBuffer(); |
|
581 RBuf& enumDescriptions = NewBuffer(); |
|
582 GetEnumValuesL(aLex, enumValues, enumDescriptions); |
|
583 if (multiple) |
|
584 { |
|
585 RArray<TInt> dummyArray; |
|
586 if (enumDescriptions.Length() > 0) |
|
587 { |
|
588 iOptions.AppendEnumL(dummyArray, optShortName[0], optLongName, argDescription, enumValues, enumDescriptions, 0, envVar); |
|
589 } |
|
590 else |
|
591 { |
|
592 iOptions.AppendEnumL(dummyArray, optShortName[0], optLongName, argDescription, enumValues, 0, envVar); |
|
593 } |
|
594 } |
|
595 else |
|
596 { |
|
597 TInt dummyInt; |
|
598 if (enumDescriptions.Length() > 0) |
|
599 { |
|
600 iOptions.AppendEnumL(dummyInt, optShortName[0], optLongName, argDescription, enumValues, enumDescriptions, 0, envVar); |
|
601 } |
|
602 else |
|
603 { |
|
604 iOptions.AppendEnumL(dummyInt, optShortName[0], optLongName, argDescription, enumValues, 0, envVar); |
|
605 } |
|
606 } |
|
607 } |
|
608 else if (optType == KTypeBool) |
|
609 { |
|
610 if (multiple) |
|
611 { |
|
612 RArray<TBool> dummyArray; |
|
613 iOptions.AppendBoolL(dummyArray, optShortName[0], optLongName, argDescription, 0, envVar); |
|
614 } |
|
615 else |
|
616 { |
|
617 TBool dummyBool; |
|
618 iOptions.AppendBoolL(dummyBool, optShortName[0], optLongName, argDescription, 0, envVar); |
|
619 } |
|
620 } |
|
621 else if (optType == KTypeInt) |
|
622 { |
|
623 if (multiple) |
|
624 { |
|
625 RArray<TInt> dummyArray; |
|
626 iOptions.AppendIntL(dummyArray, optShortName[0], optLongName, argDescription, 0, envVar); |
|
627 } |
|
628 else |
|
629 { |
|
630 TInt dummyInt; |
|
631 iOptions.AppendIntL(dummyInt, optShortName[0], optLongName, argDescription, 0, envVar); |
|
632 } |
|
633 } |
|
634 else if (optType == KTypeUint) |
|
635 { |
|
636 if (multiple) |
|
637 { |
|
638 RArray<TUint> dummyArray; |
|
639 iOptions.AppendUintL(dummyArray, optShortName[0], optLongName, argDescription, 0, envVar); |
|
640 } |
|
641 else |
|
642 { |
|
643 TUint dummyUint; |
|
644 iOptions.AppendUintL(dummyUint, optShortName[0], optLongName, argDescription, 0, envVar); |
|
645 } |
|
646 } |
|
647 else if (optType == KTypeString) |
|
648 { |
|
649 if (multiple) |
|
650 { |
|
651 RPointerArray<HBufC> dummyArray; |
|
652 iOptions.AppendStringL(dummyArray, optShortName[0], optLongName, argDescription, 0, envVar); |
|
653 } |
|
654 else |
|
655 { |
|
656 HBufC* dummyHBufC; |
|
657 iOptions.AppendStringL(dummyHBufC, optShortName[0], optLongName, argDescription, 0, envVar); |
|
658 } |
|
659 } |
|
660 else if (optType == KTypeFileName) |
|
661 { |
|
662 if (multiple) |
|
663 { |
|
664 RArray<TFileName2> dummyArray; |
|
665 iOptions.AppendFileNameL(dummyArray, optShortName[0], optLongName, argDescription, 0, envVar); |
|
666 } |
|
667 else |
|
668 { |
|
669 TFileName2 dummyFileName; |
|
670 iOptions.AppendFileNameL(dummyFileName, optShortName[0], optLongName, argDescription, 0, envVar); |
|
671 } |
|
672 } |
|
673 else if (optType == KTypeReal) |
|
674 { |
|
675 if (multiple) |
|
676 { |
|
677 RArray<TReal64> dummyArray; |
|
678 iOptions.AppendRealL(dummyArray, optShortName[0], optLongName, argDescription, 0, envVar); |
|
679 } |
|
680 else |
|
681 { |
|
682 TReal64 dummyReal; |
|
683 iOptions.AppendRealL(dummyReal, optShortName[0], optLongName, argDescription, 0, envVar); |
|
684 } |
|
685 } |
|
686 else if (optType == KTypeUint64) |
|
687 { |
|
688 if (multiple) |
|
689 { |
|
690 RArray<TUint64> dummyArray; |
|
691 iOptions.AppendUintL(dummyArray, optShortName[0], optLongName, argDescription, 0, envVar); |
|
692 } |
|
693 else |
|
694 { |
|
695 TUint64 dummyUint64; |
|
696 iOptions.AppendUintL(dummyUint64, optShortName[0], optLongName, argDescription, 0, envVar); |
|
697 } |
|
698 } |
|
699 else if (optType == KTypeInt64) |
|
700 { |
|
701 if (multiple) |
|
702 { |
|
703 RArray<TInt64> dummyArray; |
|
704 iOptions.AppendIntL(dummyArray, optShortName[0], optLongName, argDescription, 0, envVar); |
|
705 } |
|
706 else |
|
707 { |
|
708 TInt64 dummyInt64; |
|
709 iOptions.AppendIntL(dummyInt64, optShortName[0], optLongName, argDescription, 0, envVar); |
|
710 } |
|
711 } |
|
712 else |
|
713 { |
|
714 StaticLeaveIfErr(KErrArgument, _L("Unknown option type \"%S\" in \"%S\""), &optType, &aFileName); |
|
715 } |
|
716 } |
|
717 } |
|
718 |
|
719 void CCommandInfoFile::ProcessNewChild() |
|
720 { |
|
721 if (iParent) |
|
722 { |
|
723 iParent->ProcessNewChild(); |
|
724 } |
|
725 else |
|
726 { |
|
727 ASSERT(!iProcessInclude); |
|
728 iCurrentChild = NULL; |
|
729 } |
|
730 } |
|
731 |
|
732 void CCommandInfoFile::ProcessInclude(CCommandInfoFile& aChild) |
|
733 { |
|
734 if (iParent) |
|
735 { |
|
736 iParent->ProcessInclude(aChild); |
|
737 } |
|
738 else |
|
739 { |
|
740 iProcessInclude = ETrue; |
|
741 iCurrentChild = &aChild; |
|
742 } |
|
743 } |
|
744 |
|
745 void CCommandInfoFile::AddSubCommandL(TLex& aNameLex, TLex& aDataLex, RFs& aFs, const TDesC& aFileName) |
|
746 { |
|
747 TPtrC subCommandName(NextWord(aNameLex)); |
|
748 TBool found(EFalse); |
|
749 for (TInt i = (iChildren.Count() - 1); i >= 0; --i) |
|
750 { |
|
751 if (iChildren[i]->Name() == subCommandName) |
|
752 { |
|
753 iChildren[i]->AddSubCommandL(aNameLex, aDataLex, aFs, aFileName); |
|
754 found = ETrue; |
|
755 break; |
|
756 } |
|
757 } |
|
758 __ASSERT_ALWAYS(found || (aNameLex.Remainder().Length() == 0), IoUtils::Panic(ECifSubCommandParentNotFound)); |
|
759 if (!found) |
|
760 { |
|
761 CCommandInfoFile* subCommand = new(ELeave) CCommandInfoFile(*this); |
|
762 CleanupStack::PushL(subCommand); |
|
763 subCommand->iName.Set(subCommandName); |
|
764 subCommand->ReadDetailsL(aDataLex, aFs, aFileName); |
|
765 iChildren.AppendL(subCommand); |
|
766 CleanupStack::Pop(subCommand); |
|
767 } |
|
768 } |
|
769 |
|
770 RBuf& CCommandInfoFile::NewBuffer() |
|
771 { |
|
772 RBuf buf; |
|
773 iBufs.AppendL(buf); |
|
774 return iBufs[iBufs.Count() - 1]; |
|
775 } |
|
776 |
|
777 EXPORT_C CCommandInfoFile::~CCommandInfoFile() |
|
778 { |
|
779 iArguments.Close(); |
|
780 iOptions.Close(); |
|
781 |
|
782 const TInt numBufs = iBufs.Count(); |
|
783 for (TInt i = 0; i < numBufs; ++i) |
|
784 { |
|
785 iBufs[i].Close(); |
|
786 } |
|
787 iBufs.Close(); |
|
788 iChildren.ResetAndDestroy(); |
|
789 } |
|
790 |
|
791 EXPORT_C const TDesC& CCommandInfoFile::Name() const |
|
792 { |
|
793 return iName; |
|
794 } |
|
795 |
|
796 EXPORT_C const TDesC& CCommandInfoFile::ShortDescription() const |
|
797 { |
|
798 return iShortDescription; |
|
799 } |
|
800 |
|
801 EXPORT_C const TDesC& CCommandInfoFile::LongDescription() const |
|
802 { |
|
803 return iLongDescription; |
|
804 } |
|
805 |
|
806 EXPORT_C const TDesC& CCommandInfoFile::SeeAlso() const |
|
807 { |
|
808 return iSeeAlso; |
|
809 } |
|
810 |
|
811 EXPORT_C const TDesC& CCommandInfoFile::Copyright() const |
|
812 { |
|
813 return iCopyright; |
|
814 } |
|
815 |
|
816 EXPORT_C const RCommandArgumentList& CCommandInfoFile::Arguments() |
|
817 { |
|
818 return iArguments; |
|
819 } |
|
820 |
|
821 EXPORT_C const RCommandOptionList& CCommandInfoFile::Options() const |
|
822 { |
|
823 return iOptions; |
|
824 } |
|
825 |
|
826 template <class T> void CombineL(const T& aSourceList, T& aDestinationList, const TDesC& aListType, const TDesC& aCifName) |
|
827 { |
|
828 const TInt sourceCount = aSourceList.Count(); |
|
829 const TInt destinationCount = aDestinationList.Count(); |
|
830 |
|
831 if (sourceCount < destinationCount) // Note, allow the source to have more than the destination because some things are compile time configurable but CIF files don't support this. |
|
832 { |
|
833 StaticLeaveIfErr(KErrArgument, _L("%S count mismatch between \"%S\" (%d) and implementation (%d)"), &aListType, &aCifName, sourceCount, destinationCount); |
|
834 } |
|
835 |
|
836 for (TInt i = 0; i < destinationCount; ++i) |
|
837 { |
|
838 const TDesC& destinationName = aDestinationList[i].Name(); |
|
839 TInt sourcePos = aSourceList.Find(destinationName); |
|
840 if (sourcePos < 0) |
|
841 { |
|
842 StaticLeaveIfErr(KErrArgument, _L("Couldn't find %S \"%S\" in \"%S\""), &aListType, &destinationName, &aCifName); |
|
843 } |
|
844 |
|
845 TUint sourceType = aSourceList[sourcePos].ValueType(); |
|
846 TUint sourceTypeForComparison = sourceType & ~(KValueTypeFlagOptional|KValueTypeFlagLast); // destType can't know about these flags, so clear them from sourceType so we don't have problems when destType doesn't set them |
|
847 TUint destType = aDestinationList[i].ValueType(); |
|
848 if (sourceTypeForComparison != destType) |
|
849 { |
|
850 StaticLeaveIfErr(KErrArgument, _L("Type mismatch for %S '%S' between \"%S\" (0x%x) and implementation (0x%x)"), &aListType, &destinationName, &aCifName, sourceType, destType); |
|
851 } |
|
852 aDestinationList[i].Combine(aSourceList[sourcePos]); |
|
853 } |
|
854 } |
|
855 |
|
856 EXPORT_C void CCommandInfoFile::AssignL(RCommandArgumentList& aArguments, RCommandOptionList& aOptions) const |
|
857 { |
|
858 CombineL(iArguments, aArguments, _L("Argument"), iFileName); |
|
859 CombineL(iOptions, aOptions, _L("Option"), iFileName); |
|
860 } |
|
861 |
|
862 EXPORT_C TInt CCommandInfoFile::NumSubCommands() const |
|
863 { |
|
864 return iChildren.Count(); |
|
865 } |
|
866 |
|
867 EXPORT_C const CCommandInfoFile& CCommandInfoFile::SubCommand(TInt aIndex) const |
|
868 { |
|
869 return *(iChildren[aIndex]); |
|
870 } |
|
871 |
|
872 EXPORT_C const CCommandInfoFile* CCommandInfoFile::SubCommand(const TDesC& aSubCommandName) const |
|
873 { |
|
874 for (TInt i = (NumSubCommands() - 1); i >= 0; --i) |
|
875 { |
|
876 const CCommandInfoFile& thisSubCommand = SubCommand(i); |
|
877 if (thisSubCommand.Name() == aSubCommandName) |
|
878 { |
|
879 return &thisSubCommand; |
|
880 } |
|
881 } |
|
882 return NULL; |
|
883 } |
|
884 |
|
885 CCommandInfoFile::CCommandInfoFile(const TDesC& aFileName) |
|
886 : iFileName(aFileName) |
|
887 { |
|
888 } |
|
889 |
|
890 CCommandInfoFile::CCommandInfoFile(CCommandInfoFile& aParent) |
|
891 : iFileName(aParent.iFileName), iParent(&aParent) |
|
892 { |
|
893 } |