|
1 // command_base.cpp |
|
2 // |
|
3 // Copyright (c) 2005 - 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 "iocons.h" |
|
14 #include "ioutils.h" |
|
15 #include "command_base.h" |
|
16 #include <fshell/ltkutils.h> |
|
17 |
|
18 using namespace IoUtils; |
|
19 |
|
20 #define RETURN_IF_ERROR(x) {TInt _err = (x); if (_err<0) return _err;} |
|
21 |
|
22 // |
|
23 // Constants. |
|
24 // |
|
25 |
|
26 _LIT(KHelpName, "help"); |
|
27 _LIT(KHelpDescription, "Display help."); |
|
28 _LIT(KOptConsole, "console"); |
|
29 _LIT(KOptConsoleTitle, "console-title"); |
|
30 _LIT(KOptConsoleSize, "console-size"); |
|
31 _LIT(KOptPersistentConsole, "persistent-console"); |
|
32 _LIT(KDllExt, ".dll"); |
|
33 _LIT(KNewLine, "\r\n"); |
|
34 |
|
35 const TUint KValueTypeUninitialized = 0x0000ffff; |
|
36 const TUint KValueTypeFlagMultiple = 0x00010000; |
|
37 const TUint KValueTypeFlagMask = 0x0000ffff; |
|
38 const TUint KPublicFlagsMask = 0x0000ffff; |
|
39 const TUint KPrivateFlagsMask = 0xffff0000; |
|
40 |
|
41 |
|
42 // |
|
43 // Misc. |
|
44 // |
|
45 |
|
46 void IoUtils::Panic(TCmdBasePanic aReason) |
|
47 { |
|
48 _LIT(KCategory, "iocli"); |
|
49 User::Panic(KCategory, aReason); |
|
50 } |
|
51 |
|
52 // If any of these asserts fail, it constitutes a BC break |
|
53 __ASSERT_COMPILE(sizeof(RChildProcess) == 7*4); |
|
54 __ASSERT_COMPILE(sizeof(RCommandOptionList) == 8*4); |
|
55 __ASSERT_COMPILE(sizeof(RCommandArgumentList) == 8*4); |
|
56 __ASSERT_COMPILE(sizeof(RIoConsoleReadHandle) == 6*4); |
|
57 __ASSERT_COMPILE(sizeof(RIoReadHandle) == 2*4); |
|
58 __ASSERT_COMPILE(sizeof(RIoConsoleWriteHandle) == 2*4); |
|
59 |
|
60 // The member variables of CCommandBase actually sum to 59 words, and from subclasses' point of view it's 59 words, |
|
61 // but EABI rounds the sizeof up to an 8-byte boundary. We can't change CCommandBase to be 60 words so that it's |
|
62 // handled the same on all platforms, because that in itself would be a BC break. |
|
63 #ifdef __EABI__ |
|
64 __ASSERT_COMPILE(sizeof(CCommandBase) == 60*4); |
|
65 #else |
|
66 __ASSERT_COMPILE(sizeof(CCommandBase) == 59*4); |
|
67 #endif |
|
68 |
|
69 // |
|
70 // TEnumLex. |
|
71 // |
|
72 |
|
73 class TEnumLex |
|
74 { |
|
75 public: |
|
76 TEnumLex(const TDesC& aCommaSeparatedList); |
|
77 TBool More(); |
|
78 TPtrC Next(); |
|
79 private: |
|
80 TPtrC iRemainder; |
|
81 }; |
|
82 |
|
83 TEnumLex::TEnumLex(const TDesC& aCommaSeparatedList) |
|
84 : iRemainder(aCommaSeparatedList) |
|
85 { |
|
86 } |
|
87 |
|
88 |
|
89 TBool TEnumLex::More() |
|
90 { |
|
91 return iRemainder.Length() > 0; |
|
92 } |
|
93 |
|
94 _LIT(KComma, ","); |
|
95 |
|
96 TPtrC TEnumLex::Next() |
|
97 { |
|
98 TInt commaPos = iRemainder.Find(KComma); |
|
99 if (commaPos<0) commaPos = iRemainder.Length(); |
|
100 TPtrC value(iRemainder.Mid(0, commaPos)); |
|
101 iRemainder.Set(iRemainder.Mid(commaPos)); |
|
102 if (iRemainder.Length()) iRemainder.Set(iRemainder.Mid(1)); |
|
103 return value; |
|
104 } |
|
105 |
|
106 |
|
107 // |
|
108 // TEnum. |
|
109 // |
|
110 |
|
111 EXPORT_C TEnum::TEnum() |
|
112 { |
|
113 } |
|
114 |
|
115 EXPORT_C TEnum::TEnum(const TDesC& aEnumValueList) |
|
116 : iEnumValueList(aEnumValueList) |
|
117 { |
|
118 ValidateValues(); |
|
119 } |
|
120 |
|
121 EXPORT_C TEnum::TEnum(const TDesC& aEnumValueList, const TDesC& aEnumDescriptionList) |
|
122 : iEnumValueList(aEnumValueList), iEnumDescriptionList(aEnumDescriptionList) |
|
123 { |
|
124 ValidateValues(); |
|
125 } |
|
126 |
|
127 TInt TEnum::GetMatches(const TDesC& aString, RArray<TInt>& aMatches, TInt& aExactMatch) |
|
128 { |
|
129 TEnumLex lex(iEnumValueList); |
|
130 TInt i = 0; |
|
131 aExactMatch = KErrNotFound; |
|
132 while ((lex.More()) && (aExactMatch == KErrNotFound)) |
|
133 { |
|
134 TPtrC value(lex.Next()); |
|
135 if (value.Compare(aString)==0) |
|
136 { |
|
137 aExactMatch = i; |
|
138 } |
|
139 if (value.Find(aString)==0) |
|
140 { |
|
141 TInt err = aMatches.Append(i); |
|
142 if (err) return err; |
|
143 } |
|
144 ++i; |
|
145 } |
|
146 return KErrNone; |
|
147 } |
|
148 |
|
149 EXPORT_C TInt TEnum::Parse(const TDesC& aString, TInt& aValue) |
|
150 { |
|
151 RArray<TInt> matches; |
|
152 TInt exactMatch; |
|
153 TInt err = GetMatches(aString, matches, exactMatch); |
|
154 if (err==KErrNone) |
|
155 { |
|
156 if (exactMatch != KErrNotFound) |
|
157 { |
|
158 aValue = exactMatch; |
|
159 } |
|
160 else if (matches.Count()==1) |
|
161 { |
|
162 aValue = matches[0]; |
|
163 } |
|
164 else |
|
165 { |
|
166 err = KErrArgument; |
|
167 } |
|
168 } |
|
169 matches.Close(); |
|
170 return err; |
|
171 } |
|
172 |
|
173 EXPORT_C TInt TEnum::ParseL(const TDesC& aString) |
|
174 { |
|
175 RArray<TInt> matches; |
|
176 TInt exactMatch; |
|
177 CleanupClosePushL(matches); |
|
178 User::LeaveIfError(GetMatches(aString, matches, exactMatch)); |
|
179 |
|
180 TInt value = 0; |
|
181 if ((matches.Count()==1) || (exactMatch != KErrNotFound)) |
|
182 { |
|
183 value = exactMatch != KErrNotFound ? exactMatch : matches[0]; |
|
184 } |
|
185 else if (matches.Count()==0) |
|
186 { |
|
187 if (CCommandBase::HaveStatic()) |
|
188 { |
|
189 CTextBuffer* buf = CTextBuffer::NewLC(0x20); |
|
190 buf->AppendL(_L("String '")); |
|
191 buf->AppendL(aString); |
|
192 buf->AppendL(_L("' does not match any of ")); |
|
193 AppendValuesL(*buf); |
|
194 PrintError(KErrArgument, buf->Descriptor()); |
|
195 } |
|
196 User::Leave(KErrArgument); |
|
197 } |
|
198 else |
|
199 { |
|
200 if (CCommandBase::HaveStatic()) |
|
201 { |
|
202 CTextBuffer* buf = CTextBuffer::NewLC(0x20); |
|
203 buf->AppendL(_L("String '")); |
|
204 buf->AppendL(aString); |
|
205 buf->AppendL(_L("' does not match a unique value (matches ")); |
|
206 TInt enumCount = -1; |
|
207 TEnumLex lex(iEnumValueList); |
|
208 // here we rely on the fact the matches will be sorted, due to the way the array was populated above. |
|
209 for (TInt i=0; i<matches.Count(); ++i) |
|
210 { |
|
211 TPtrC enumValue; |
|
212 while (matches[i]>enumCount) |
|
213 { |
|
214 ++enumCount; |
|
215 enumValue.Set(lex.Next()); |
|
216 } |
|
217 buf->AppendL(enumValue); |
|
218 if (i<matches.Count()-1) buf->AppendL(_L(", ")); |
|
219 } |
|
220 buf->AppendL(')'); |
|
221 PrintError(KErrArgument, buf->Descriptor()); |
|
222 } |
|
223 User::Leave(KErrArgument); |
|
224 } |
|
225 CleanupStack::PopAndDestroy(); //matches |
|
226 return value; |
|
227 } |
|
228 |
|
229 EXPORT_C const TDesC& TEnum::ValueList() const |
|
230 { |
|
231 return iEnumValueList; |
|
232 } |
|
233 |
|
234 EXPORT_C const TDesC& TEnum::DescriptionList() const |
|
235 { |
|
236 return iEnumDescriptionList; |
|
237 } |
|
238 |
|
239 void TEnum::ValidateValues() const |
|
240 { |
|
241 for (TInt i=0; i<iEnumValueList.Length(); ++i) |
|
242 { |
|
243 __ASSERT_ALWAYS(!TChar(iEnumValueList[i]).IsSpace(), IoUtils::Panic(EEnumValueContainsSpace)); |
|
244 } |
|
245 } |
|
246 |
|
247 EXPORT_C void TEnum::AppendValuesL(CTextBuffer& aBuf) const |
|
248 { |
|
249 TEnumLex values(iEnumValueList); |
|
250 while (values.More()) |
|
251 { |
|
252 aBuf.AppendL(values.Next()); |
|
253 if (values.More()) |
|
254 { |
|
255 aBuf.AppendL(_L(", ")); |
|
256 } |
|
257 } |
|
258 } |
|
259 |
|
260 EXPORT_C const TPtrC TEnum::GetString(TInt aIndex) const |
|
261 { |
|
262 TEnumLex lex(iEnumValueList); |
|
263 while (aIndex) |
|
264 { |
|
265 lex.Next(); |
|
266 --aIndex; |
|
267 __ASSERT_ALWAYS(lex.More(), Panic(EEnumValueOutOfRange)); |
|
268 } |
|
269 return lex.Next(); |
|
270 } |
|
271 |
|
272 EXPORT_C void TEnum::SetValueList(const TDesC& aValueList) |
|
273 { |
|
274 __ASSERT_ALWAYS(iEnumValueList.Length() == 0, IoUtils::Panic(EEnumValueListAlreadySet)); |
|
275 iEnumValueList.Set(aValueList); |
|
276 } |
|
277 |
|
278 EXPORT_C void TEnum::SetDescriptionList(const TDesC& aDescriptionList) |
|
279 { |
|
280 __ASSERT_ALWAYS(iEnumDescriptionList.Length() == 0, IoUtils::Panic(EEnumDescriptionListAlreadySet)); |
|
281 iEnumDescriptionList.Set(aDescriptionList); |
|
282 } |
|
283 |
|
284 EXPORT_C void TEnum::operator=(const TEnum& aEnum) |
|
285 { |
|
286 iEnumValueList.Set(aEnum.iEnumValueList); |
|
287 iEnumDescriptionList.Set(aEnum.iEnumDescriptionList); |
|
288 } |
|
289 |
|
290 |
|
291 // |
|
292 // TValue. |
|
293 // |
|
294 |
|
295 TValue::TValue(TUint aValueType, void* aValuePointer, const TDesC& aName) |
|
296 : iValueType(aValueType), iValue(aValuePointer), iIsSet(EFalse), iEnum(KNullDesC, KNullDesC), iName(aName) |
|
297 { |
|
298 } |
|
299 |
|
300 TValue::TValue(TUint aValueType, void* aValuePointer, const TDesC& aName, const TDesC& aDescription, const TDesC& aEnvVar) |
|
301 : iValueType(aValueType), iValue(aValuePointer), iIsSet(EFalse), iEnvVar(aEnvVar), iEnum(KNullDesC, KNullDesC), iName(aName), iDescription(aDescription) |
|
302 { |
|
303 __ASSERT_ALWAYS(aValueType != KValueTypeEnum, IoUtils::Panic(EInvalidUseOfEnum)); |
|
304 } |
|
305 |
|
306 TValue::TValue(TUint aValueType, const TDesC& aEnumValueList, const TDesC& aEnumDescriptionList, void* aValuePointer, const TDesC& aName, const TDesC& aDescription, const TDesC& aEnvVar) |
|
307 : iValueType(aValueType), iValue(aValuePointer), iIsSet(EFalse), iEnvVar(aEnvVar), iEnum(aEnumValueList, aEnumDescriptionList), iName(aName), iDescription(aDescription) |
|
308 { |
|
309 } |
|
310 |
|
311 TUint TValue::ValueType() const |
|
312 { |
|
313 return iValueType; |
|
314 } |
|
315 |
|
316 EXPORT_C TUint TValue::Type() const |
|
317 { |
|
318 return iValueType & KPublicFlagsMask; |
|
319 } |
|
320 |
|
321 void TValue::SetValue() |
|
322 { |
|
323 __ASSERT_ALWAYS((iValueType & KValueTypeFlagMask) == KValueTypeBool, IoUtils::Panic(EIncorrectCommandOptionType1)); |
|
324 if (iValueType & KValueTypeFlagMultiple) |
|
325 { |
|
326 (*(TInt*)iValue)++; |
|
327 } |
|
328 else |
|
329 { |
|
330 *(TBool*)iValue = ETrue; |
|
331 } |
|
332 iIsSet = ETrue; |
|
333 } |
|
334 |
|
335 void TValue::SetValueL(TInt aInt) |
|
336 { |
|
337 __ASSERT_ALWAYS((iValueType & KValueTypeFlagMask) == KValueTypeInt, IoUtils::Panic(EIncorrectCommandOptionType2)); |
|
338 if (iValueType & KValueTypeFlagMultiple) |
|
339 { |
|
340 User::LeaveIfError(((RArray<TInt>*)iValue)->Append(aInt)); |
|
341 } |
|
342 else |
|
343 { |
|
344 *(TInt*)iValue = aInt; |
|
345 } |
|
346 iIsSet = ETrue; |
|
347 } |
|
348 |
|
349 void TValue::SetValueL(TInt64 aInt) |
|
350 { |
|
351 __ASSERT_ALWAYS((iValueType & KValueTypeFlagMask) == KValueTypeInt64, IoUtils::Panic(EIncorrectCommandOptionType11)); |
|
352 if (iValueType & KValueTypeFlagMultiple) |
|
353 { |
|
354 User::LeaveIfError(((RArray<TInt64>*)iValue)->Append(aInt)); |
|
355 } |
|
356 else |
|
357 { |
|
358 *(TInt64*)iValue = aInt; |
|
359 } |
|
360 iIsSet = ETrue; |
|
361 } |
|
362 |
|
363 void TValue::SetValueL(TUint aUint) |
|
364 { |
|
365 __ASSERT_ALWAYS((iValueType & KValueTypeFlagMask) == KValueTypeUint, IoUtils::Panic(EIncorrectCommandOptionType3)); |
|
366 if (iValueType & KValueTypeFlagMultiple) |
|
367 { |
|
368 User::LeaveIfError(((RArray<TUint>*)iValue)->Append(aUint)); |
|
369 } |
|
370 else |
|
371 { |
|
372 *(TUint*)iValue = aUint; |
|
373 } |
|
374 iIsSet = ETrue; |
|
375 } |
|
376 |
|
377 void TValue::SetValueL(TUint64 aUint) |
|
378 { |
|
379 __ASSERT_ALWAYS((iValueType & KValueTypeFlagMask) == KValueTypeUint64, IoUtils::Panic(EIncorrectCommandOptionType10)); |
|
380 if (iValueType & KValueTypeFlagMultiple) |
|
381 { |
|
382 User::LeaveIfError(((RArray<TUint64>*)iValue)->Append(aUint)); |
|
383 } |
|
384 else |
|
385 { |
|
386 *(TUint64*)iValue = aUint; |
|
387 } |
|
388 iIsSet = ETrue; |
|
389 } |
|
390 |
|
391 void TValue::SetValueL(TReal64 aReal) |
|
392 { |
|
393 __ASSERT_ALWAYS((iValueType & KValueTypeFlagMask) == KValueTypeReal, IoUtils::Panic(EIncorrectCommandOptionType4)); |
|
394 if (iValueType & KValueTypeFlagMultiple) |
|
395 { |
|
396 User::LeaveIfError(((RArray<TReal64>*)iValue)->Append(aReal)); |
|
397 } |
|
398 else |
|
399 { |
|
400 *(TReal64*)iValue = aReal; |
|
401 } |
|
402 iIsSet = ETrue; |
|
403 } |
|
404 |
|
405 void TValue::SetValueL(HBufC* aString) |
|
406 { |
|
407 __ASSERT_ALWAYS( ((iValueType & KValueTypeFlagMask) == KValueTypeString) || (iValueType & KValueTypeFlagMask) == KValueTypeEnum, IoUtils::Panic(EIncorrectCommandOptionType5)); |
|
408 if ((iValueType & KValueTypeFlagMask) == KValueTypeEnum) |
|
409 { |
|
410 TInt value = iEnum.ParseL(*aString); |
|
411 if (iValueType & KValueTypeFlagMultiple) |
|
412 { |
|
413 User::LeaveIfError(((RArray<TInt>*)iValue)->Append(value)); |
|
414 } |
|
415 else |
|
416 { |
|
417 *(TInt*)iValue = value; |
|
418 } |
|
419 iIsSet = ETrue; |
|
420 } |
|
421 else // string |
|
422 { |
|
423 if (iValueType & KValueTypeFlagMultiple) |
|
424 { |
|
425 User::LeaveIfError(((RPointerArray<HBufC>*)iValue)->Append(aString)); |
|
426 } |
|
427 else |
|
428 { |
|
429 *(HBufC**)iValue = aString; |
|
430 } |
|
431 iIsSet = ETrue; |
|
432 } |
|
433 } |
|
434 |
|
435 void TValue::SetValueL(const TFileName2& aFileName, RFs& aFs) |
|
436 { |
|
437 __ASSERT_ALWAYS((iValueType & KValueTypeFlagMask) == KValueTypeFileName, IoUtils::Panic(EIncorrectCommandOptionType6)); |
|
438 |
|
439 if (AcceptsMultiple()) |
|
440 { |
|
441 if (aFileName.IsWild()) |
|
442 { |
|
443 CDir* matches; |
|
444 User::LeaveIfError(aFs.GetDir(aFileName, KEntryAttMaskSupported, ESortByName, matches)); |
|
445 CleanupStack::PushL(matches); |
|
446 for (TInt i = 0; i < matches->Count(); ++i) |
|
447 { |
|
448 TFileName2 expandedFileName((*matches)[i].iName); |
|
449 expandedFileName.MakeAbsoluteL(aFileName.DriveAndPath()); |
|
450 ((RArray<TFileName2>*)iValue)->AppendL(expandedFileName); |
|
451 } |
|
452 CleanupStack::PopAndDestroy(matches); |
|
453 } |
|
454 else |
|
455 { |
|
456 ((RArray<TFileName2>*)iValue)->AppendL(aFileName); |
|
457 } |
|
458 } |
|
459 else |
|
460 { |
|
461 ((TFileName2*)iValue)->SetL(aFileName); |
|
462 } |
|
463 |
|
464 iIsSet = ETrue; |
|
465 } |
|
466 |
|
467 void TValue::SetEnumValues(const TEnum& aEnum) |
|
468 { |
|
469 iEnum = aEnum; |
|
470 } |
|
471 |
|
472 TBool TValue::IsSet() const |
|
473 { |
|
474 return iIsSet; |
|
475 } |
|
476 |
|
477 EXPORT_C TBool TValue::AcceptsMultiple() const |
|
478 { |
|
479 return (iValueType & KValueTypeFlagMultiple); |
|
480 } |
|
481 |
|
482 EXPORT_C const TDesC& TValue::EnumValueList() const |
|
483 { |
|
484 __ASSERT_ALWAYS((iValueType & KValueTypeFlagMask) == KValueTypeEnum, IoUtils::Panic(EIncorrectCommandOptionType7)); |
|
485 return iEnum.ValueList(); |
|
486 } |
|
487 |
|
488 const TDesC& TValue::EnumDescriptionList() const |
|
489 { |
|
490 __ASSERT_ALWAYS((iValueType & KValueTypeFlagMask) == KValueTypeEnum, IoUtils::Panic(EIncorrectCommandOptionType8)); |
|
491 return iEnum.DescriptionList(); |
|
492 } |
|
493 |
|
494 EXPORT_C const TDesC& TValue::EnvVar() const |
|
495 { |
|
496 return iEnvVar; |
|
497 } |
|
498 |
|
499 EXPORT_C const TDesC& TValue::Name() const |
|
500 { |
|
501 return iName; |
|
502 } |
|
503 |
|
504 const TDesC& TValue::Description() const |
|
505 { |
|
506 return iDescription; |
|
507 } |
|
508 |
|
509 EXPORT_C void* TValue::ValuePtr() const |
|
510 { |
|
511 return iValue; |
|
512 } |
|
513 |
|
514 TPtrC TValue::AsString() const |
|
515 { |
|
516 if (!IsSet()) return KNullDesC(); |
|
517 if (AcceptsMultiple()) return KNullDesC(); |
|
518 switch (iValueType) |
|
519 { |
|
520 case KValueTypeString: |
|
521 return *(HBufC*)iValue; |
|
522 case KValueTypeFileName: |
|
523 return *(TFileName2*)iValue; |
|
524 case KValueTypeEnum: |
|
525 return iEnum.GetString(*(TInt*)iValue); |
|
526 default: |
|
527 return KNullDesC(); |
|
528 } |
|
529 } |
|
530 |
|
531 void TValue::AppendEnumValuesL(CTextBuffer& aBuf) const |
|
532 { |
|
533 __ASSERT_ALWAYS((iValueType & KValueTypeFlagMask) == KValueTypeEnum, IoUtils::Panic(EIncorrectCommandOptionType9)); |
|
534 return iEnum.AppendValuesL(aBuf); |
|
535 } |
|
536 |
|
537 void TValue::Combine(const TValue& aValue) |
|
538 { |
|
539 __ASSERT_ALWAYS(iDescription.Ptr() == NULL, IoUtils::Panic(EValueDescriptionAlreadySet)); |
|
540 |
|
541 iValueType = aValue.iValueType; |
|
542 iDescription.Set(aValue.iDescription); |
|
543 if ((iValueType & KValueTypeFlagMask) == KValueTypeEnum) |
|
544 { |
|
545 if (aValue.iEnum.ValueList().Length() > 0) |
|
546 { |
|
547 iEnum.SetValueList(aValue.iEnum.ValueList()); |
|
548 } |
|
549 if (aValue.iEnum.DescriptionList().Length() > 0) |
|
550 { |
|
551 iEnum.SetDescriptionList(aValue.iEnum.DescriptionList()); |
|
552 } |
|
553 } |
|
554 iEnvVar.Set(aValue.EnvVar()); |
|
555 } |
|
556 |
|
557 |
|
558 // |
|
559 // TCommandOption. |
|
560 // |
|
561 |
|
562 TCommandOption::TCommandOption(TUint aValueType, void* aValuePointer, const TDesC& aLongName) |
|
563 : TValue(aValueType, aValuePointer, aLongName) |
|
564 { |
|
565 } |
|
566 |
|
567 TCommandOption::TCommandOption(TUint aValueType, void* aValuePointer, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, const TDesC& aEnvVar) |
|
568 : TValue(aValueType, aValuePointer, aLongName, aDescription, aEnvVar), iShortName(aShortName) |
|
569 { |
|
570 } |
|
571 |
|
572 TCommandOption::TCommandOption(void* aValuePointer, TUint aValueType, const TDesC& aCommaSeparatedValueList, const TDesC& aCommaSeparatedDescriptionList, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, const TDesC& aEnvVar) |
|
573 : TValue(aValueType, aCommaSeparatedValueList, aCommaSeparatedDescriptionList, aValuePointer, aLongName, aDescription, aEnvVar), iShortName(aShortName) |
|
574 { |
|
575 } |
|
576 |
|
577 TChar TCommandOption::ShortName() const |
|
578 { |
|
579 return iShortName; |
|
580 } |
|
581 |
|
582 void TCommandOption::Combine(const TCommandOption& aOption) |
|
583 { |
|
584 TValue::Combine(aOption); |
|
585 iShortName = aOption.iShortName; |
|
586 } |
|
587 |
|
588 |
|
589 // |
|
590 // RCommandOptionList. |
|
591 // |
|
592 |
|
593 void RCommandOptionList::Close() |
|
594 { |
|
595 iOptions.Close(); |
|
596 } |
|
597 |
|
598 EXPORT_C void RCommandOptionList::AppendBoolL(TBool& aBool, const TDesC& aLongName) |
|
599 { |
|
600 iOptions.AppendL(TCommandOption(KValueTypeBool, &aBool, aLongName)); |
|
601 } |
|
602 |
|
603 EXPORT_C void RCommandOptionList::AppendBoolL(RArray<TBool>& aBools, const TDesC& aLongName) |
|
604 { |
|
605 iOptions.AppendL(TCommandOption(KValueTypeBool | KValueTypeFlagMultiple, &aBools, aLongName)); |
|
606 } |
|
607 |
|
608 EXPORT_C void RCommandOptionList::AppendIntL(TInt& aInt, const TDesC& aLongName) |
|
609 { |
|
610 iOptions.AppendL(TCommandOption(KValueTypeInt, &aInt, aLongName)); |
|
611 } |
|
612 |
|
613 EXPORT_C void RCommandOptionList::AppendIntL(RArray<TInt>& aInts, const TDesC& aLongName) |
|
614 { |
|
615 iOptions.AppendL(TCommandOption(KValueTypeInt | KValueTypeFlagMultiple, &aInts, aLongName)); |
|
616 } |
|
617 |
|
618 EXPORT_C void RCommandOptionList::AppendIntL(TInt64& aInt, const TDesC& aLongName) |
|
619 { |
|
620 iOptions.AppendL(TCommandOption(KValueTypeInt64, &aInt, aLongName)); |
|
621 } |
|
622 |
|
623 EXPORT_C void RCommandOptionList::AppendIntL(RArray<TInt64>& aInts, const TDesC& aLongName) |
|
624 { |
|
625 iOptions.AppendL(TCommandOption(KValueTypeInt64 | KValueTypeFlagMultiple, &aInts, aLongName)); |
|
626 } |
|
627 |
|
628 EXPORT_C void RCommandOptionList::AppendUintL(TUint& aUint, const TDesC& aLongName) |
|
629 { |
|
630 iOptions.AppendL(TCommandOption(KValueTypeUint, &aUint, aLongName)); |
|
631 } |
|
632 |
|
633 EXPORT_C void RCommandOptionList::AppendUintL(RArray<TUint>& aUints, const TDesC& aLongName) |
|
634 { |
|
635 iOptions.AppendL(TCommandOption(KValueTypeUint | KValueTypeFlagMultiple, &aUints, aLongName)); |
|
636 } |
|
637 |
|
638 EXPORT_C void RCommandOptionList::AppendUintL(TUint64& aUint, const TDesC& aLongName) |
|
639 { |
|
640 iOptions.AppendL(TCommandOption(KValueTypeUint64, &aUint, aLongName)); |
|
641 } |
|
642 |
|
643 EXPORT_C void RCommandOptionList::AppendUintL(RArray<TUint64>& aUints, const TDesC& aLongName) |
|
644 { |
|
645 iOptions.AppendL(TCommandOption(KValueTypeUint64 | KValueTypeFlagMultiple, &aUints, aLongName)); |
|
646 } |
|
647 |
|
648 EXPORT_C void RCommandOptionList::AppendRealL(TReal64& aReal, const TDesC& aLongName) |
|
649 { |
|
650 iOptions.AppendL(TCommandOption(KValueTypeReal, &aReal, aLongName)); |
|
651 } |
|
652 |
|
653 EXPORT_C void RCommandOptionList::AppendRealL(RArray<TReal64>& aReals, const TDesC& aLongName) |
|
654 { |
|
655 iOptions.AppendL(TCommandOption(KValueTypeReal | KValueTypeFlagMultiple, &aReals, aLongName)); |
|
656 } |
|
657 |
|
658 EXPORT_C void RCommandOptionList::AppendStringL(HBufC*& aBuf, const TDesC& aLongName) |
|
659 { |
|
660 iOptions.AppendL(TCommandOption(KValueTypeString, &aBuf, aLongName)); |
|
661 } |
|
662 |
|
663 EXPORT_C void RCommandOptionList::AppendStringL(RPointerArray<HBufC>& aBufs, const TDesC& aLongName) |
|
664 { |
|
665 iOptions.AppendL(TCommandOption(KValueTypeString | KValueTypeFlagMultiple, &aBufs, aLongName)); |
|
666 } |
|
667 |
|
668 EXPORT_C void RCommandOptionList::AppendFileNameL(TFileName2& aFileName, const TDesC& aLongName) |
|
669 { |
|
670 iOptions.AppendL(TCommandOption(KValueTypeFileName, &aFileName, aLongName)); |
|
671 } |
|
672 |
|
673 EXPORT_C void RCommandOptionList::AppendFileNameL(RArray<TFileName2>& aFileNames, const TDesC& aLongName) |
|
674 { |
|
675 iOptions.AppendL(TCommandOption(KValueTypeFileName | KValueTypeFlagMultiple, &aFileNames, aLongName)); |
|
676 } |
|
677 |
|
678 EXPORT_C void RCommandOptionList::AppendEnumL(TInt& aEnum, const TDesC& aLongName) |
|
679 { |
|
680 iOptions.AppendL(TCommandOption(KValueTypeEnum, &aEnum, aLongName)); |
|
681 } |
|
682 |
|
683 EXPORT_C void RCommandOptionList::AppendEnumL(TInt& aEnum, const TDesC& aLongName, const TDesC& aCommaSeparatedValueList) |
|
684 { |
|
685 TCommandOption opt(KValueTypeEnum, &aEnum, aLongName); |
|
686 opt.SetEnumValues(TEnum(aCommaSeparatedValueList)); |
|
687 iOptions.AppendL(opt); |
|
688 } |
|
689 |
|
690 EXPORT_C void RCommandOptionList::AppendEnumL(RArray<TInt>& aEnum, const TDesC& aLongName) |
|
691 { |
|
692 iOptions.AppendL(TCommandOption(KValueTypeEnum | KValueTypeFlagMultiple, &aEnum, aLongName)); |
|
693 } |
|
694 |
|
695 EXPORT_C void RCommandOptionList::AppendEnumL(RArray<TInt>& aEnum, const TDesC& aLongName, const TDesC& aCommaSeparatedValueList) |
|
696 { |
|
697 TCommandOption opt(KValueTypeEnum | KValueTypeFlagMultiple, &aEnum, aLongName); |
|
698 opt.SetEnumValues(TEnum(aCommaSeparatedValueList)); |
|
699 iOptions.AppendL(opt); |
|
700 } |
|
701 |
|
702 EXPORT_C void RCommandOptionList::AppendBoolL(TBool& aBool, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
703 { |
|
704 TCommandOption option(KValueTypeBool | aFlags, &aBool, aShortName, aLongName, aDescription, aEnvVar); |
|
705 Validate(option); |
|
706 iOptions.AppendL(option); |
|
707 } |
|
708 |
|
709 EXPORT_C void RCommandOptionList::AppendBoolL(RArray<TBool>& aBools, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
710 { |
|
711 TCommandOption option(KValueTypeBool | KValueTypeFlagMultiple | aFlags, &aBools, aShortName, aLongName, aDescription, aEnvVar); |
|
712 Validate(option); |
|
713 iOptions.AppendL(option); |
|
714 } |
|
715 |
|
716 EXPORT_C void RCommandOptionList::AppendIntL(TInt& aInt, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
717 { |
|
718 TCommandOption option(KValueTypeInt | aFlags, &aInt, aShortName, aLongName, aDescription, aEnvVar); |
|
719 Validate(option); |
|
720 iOptions.AppendL(option); |
|
721 } |
|
722 |
|
723 EXPORT_C void RCommandOptionList::AppendIntL(RArray<TInt>& aInts, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
724 { |
|
725 TCommandOption option(KValueTypeInt | KValueTypeFlagMultiple | aFlags, &aInts, aShortName, aLongName, aDescription, aEnvVar); |
|
726 Validate(option); |
|
727 iOptions.AppendL(option); |
|
728 } |
|
729 |
|
730 EXPORT_C void RCommandOptionList::AppendIntL(TInt64& aInt, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
731 { |
|
732 TCommandOption option(KValueTypeInt64 | aFlags, &aInt, aShortName, aLongName, aDescription, aEnvVar); |
|
733 Validate(option); |
|
734 iOptions.AppendL(option); |
|
735 } |
|
736 |
|
737 EXPORT_C void RCommandOptionList::AppendIntL(RArray<TInt64>& aInts, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
738 { |
|
739 TCommandOption option(KValueTypeInt64 | KValueTypeFlagMultiple | aFlags, &aInts, aShortName, aLongName, aDescription, aEnvVar); |
|
740 Validate(option); |
|
741 iOptions.AppendL(option); |
|
742 } |
|
743 |
|
744 EXPORT_C void RCommandOptionList::AppendUintL(TUint& aUint, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
745 { |
|
746 TCommandOption option(KValueTypeUint | aFlags, &aUint, aShortName, aLongName, aDescription, aEnvVar); |
|
747 Validate(option); |
|
748 iOptions.AppendL(option); |
|
749 } |
|
750 |
|
751 EXPORT_C void RCommandOptionList::AppendUintL(RArray<TUint>& aUints, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
752 { |
|
753 TCommandOption option(KValueTypeUint | KValueTypeFlagMultiple | aFlags, &aUints, aShortName, aLongName, aDescription, aEnvVar); |
|
754 Validate(option); |
|
755 iOptions.AppendL(option); |
|
756 } |
|
757 |
|
758 EXPORT_C void RCommandOptionList::AppendUintL(TUint64& aUint, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
759 { |
|
760 TCommandOption option(KValueTypeUint64 | aFlags, &aUint, aShortName, aLongName, aDescription, aEnvVar); |
|
761 Validate(option); |
|
762 iOptions.AppendL(option); |
|
763 } |
|
764 |
|
765 EXPORT_C void RCommandOptionList::AppendUintL(RArray<TUint64>& aUints, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
766 { |
|
767 TCommandOption option(KValueTypeUint64 | KValueTypeFlagMultiple | aFlags, &aUints, aShortName, aLongName, aDescription, aEnvVar); |
|
768 Validate(option); |
|
769 iOptions.AppendL(option); |
|
770 } |
|
771 |
|
772 EXPORT_C void RCommandOptionList::AppendRealL(TReal64& aReal, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
773 { |
|
774 TCommandOption option(KValueTypeReal | aFlags, &aReal, aShortName, aLongName, aDescription, aEnvVar); |
|
775 Validate(option); |
|
776 iOptions.AppendL(option); |
|
777 } |
|
778 |
|
779 EXPORT_C void RCommandOptionList::AppendRealL(RArray<TReal64>& aReals, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
780 { |
|
781 TCommandOption option(KValueTypeReal | KValueTypeFlagMultiple | aFlags, &aReals, aShortName, aLongName, aDescription, aEnvVar); |
|
782 Validate(option); |
|
783 iOptions.AppendL(option); |
|
784 } |
|
785 |
|
786 EXPORT_C void RCommandOptionList::AppendStringL(HBufC*& aBuf, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
787 { |
|
788 TCommandOption option(KValueTypeString | aFlags, &aBuf, aShortName, aLongName, aDescription, aEnvVar); |
|
789 Validate(option); |
|
790 iOptions.AppendL(option); |
|
791 } |
|
792 |
|
793 EXPORT_C void RCommandOptionList::AppendStringL(RPointerArray<HBufC>& aBufs, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
794 { |
|
795 TCommandOption option(KValueTypeString | KValueTypeFlagMultiple | aFlags, &aBufs, aShortName, aLongName, aDescription, aEnvVar); |
|
796 Validate(option); |
|
797 iOptions.AppendL(option); |
|
798 } |
|
799 |
|
800 EXPORT_C void RCommandOptionList::AppendFileNameL(TFileName2& aFileName, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
801 { |
|
802 TCommandOption option(KValueTypeFileName | aFlags, &aFileName, aShortName, aLongName, aDescription, aEnvVar); |
|
803 Validate(option); |
|
804 iOptions.AppendL(option); |
|
805 } |
|
806 |
|
807 EXPORT_C void RCommandOptionList::AppendFileNameL(RArray<TFileName2>& aFileNames, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
808 { |
|
809 TCommandOption option(KValueTypeFileName | KValueTypeFlagMultiple | aFlags, &aFileNames, aShortName, aLongName, aDescription, aEnvVar); |
|
810 Validate(option); |
|
811 iOptions.AppendL(option); |
|
812 } |
|
813 |
|
814 EXPORT_C void RCommandOptionList::AppendEnumL(TInt& aEnum, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, const TDesC& aCommaSeparatedValueList, TUint aFlags, const TDesC& aEnvVar) |
|
815 { |
|
816 TCommandOption option(&aEnum, KValueTypeEnum | aFlags, aCommaSeparatedValueList, KNullDesC, aShortName, aLongName, aDescription, aEnvVar); |
|
817 Validate(option); |
|
818 iOptions.AppendL(option); |
|
819 } |
|
820 |
|
821 EXPORT_C void RCommandOptionList::AppendEnumL(TInt& aEnum, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, const TDesC& aCommaSeparatedValueList, const TDesC& aCommaSeparatedDescriptionList, TUint aFlags, const TDesC& aEnvVar) |
|
822 { |
|
823 TCommandOption option(&aEnum, KValueTypeEnum | aFlags, aCommaSeparatedValueList, aCommaSeparatedDescriptionList, aShortName, aLongName, aDescription, aEnvVar); |
|
824 Validate(option); |
|
825 iOptions.AppendL(option); |
|
826 } |
|
827 |
|
828 EXPORT_C void RCommandOptionList::AppendEnumL(RArray<TInt>& aEnum, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, const TDesC& aCommaSeparatedValueList, TUint aFlags, const TDesC& aEnvVar) |
|
829 { |
|
830 TCommandOption option(&aEnum, KValueTypeEnum | KValueTypeFlagMultiple | aFlags, aCommaSeparatedValueList, KNullDesC, aShortName, aLongName, aDescription, aEnvVar); |
|
831 Validate(option); |
|
832 iOptions.AppendL(option); |
|
833 } |
|
834 |
|
835 EXPORT_C void RCommandOptionList::AppendEnumL(RArray<TInt>& aEnum, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, const TDesC& aCommaSeparatedValueList, const TDesC& aCommaSeparatedDescriptionList, TUint aFlags, const TDesC& aEnvVar) |
|
836 { |
|
837 TCommandOption option(&aEnum, KValueTypeEnum | KValueTypeFlagMultiple | aFlags, aCommaSeparatedValueList, aCommaSeparatedDescriptionList, aShortName, aLongName, aDescription, aEnvVar); |
|
838 Validate(option); |
|
839 iOptions.AppendL(option); |
|
840 } |
|
841 |
|
842 void RCommandOptionList::Validate(const TCommandOption& aOption) |
|
843 { |
|
844 __ASSERT_ALWAYS(!(aOption.ValueType() & KValueTypeFlagLast), Panic(EOptionTaggedAsLast)); |
|
845 __ASSERT_ALWAYS((aOption.ShortName() == 0) || (FindShort(aOption.ShortName()) == KErrNotFound), Panic(EDuplicateShortOptionName)); |
|
846 TInt pos = Find(aOption.Name()); |
|
847 if (pos >= 0) |
|
848 { |
|
849 iOptions.Remove(pos); // Allow a newly added option of the same long name as an existing one to replace it. Primarily of use in .cif files via the "==include" directive to support command class hierarchies. |
|
850 } |
|
851 } |
|
852 |
|
853 EXPORT_C TInt RCommandOptionList::Count() const |
|
854 { |
|
855 return iOptions.Count(); |
|
856 } |
|
857 |
|
858 EXPORT_C TCommandOption& RCommandOptionList::operator[](TInt aIndex) |
|
859 { |
|
860 return iOptions[aIndex]; |
|
861 } |
|
862 |
|
863 EXPORT_C const TCommandOption& RCommandOptionList::operator[](TInt aIndex) const |
|
864 { |
|
865 return iOptions[aIndex]; |
|
866 } |
|
867 |
|
868 TInt RCommandOptionList::FindShort(TChar aShortName) const |
|
869 { |
|
870 const TInt count = Count(); |
|
871 for (TInt i = 0; i < count; ++i) |
|
872 { |
|
873 if (iOptions[i].ShortName() == aShortName) |
|
874 { |
|
875 return i; |
|
876 } |
|
877 } |
|
878 return KErrNotFound; |
|
879 } |
|
880 |
|
881 TInt RCommandOptionList::Find(const TDesC& aLongName) const |
|
882 { |
|
883 const TInt count = Count(); |
|
884 for (TInt i = 0; i < count; ++i) |
|
885 { |
|
886 if (iOptions[i].Name() == aLongName) |
|
887 { |
|
888 return i; |
|
889 } |
|
890 } |
|
891 return KErrNotFound; |
|
892 } |
|
893 |
|
894 EXPORT_C TBool RCommandOptionList::IsPresent(void* aValuePointer) const |
|
895 { |
|
896 const TInt count = Count(); |
|
897 for (TInt i = 0; i < count; ++i) |
|
898 { |
|
899 if (iOptions[i].ValuePtr() == aValuePointer) |
|
900 { |
|
901 return iOptions[i].IsSet(); |
|
902 } |
|
903 } |
|
904 return EFalse; |
|
905 } |
|
906 |
|
907 EXPORT_C TPtrC RCommandOptionList::AsString(void* aValuePointer) const |
|
908 { |
|
909 const TInt count = Count(); |
|
910 for (TInt i = 0; i < count; ++i) |
|
911 { |
|
912 if (iOptions[i].ValuePtr() == aValuePointer) |
|
913 { |
|
914 return iOptions[i].AsString(); |
|
915 } |
|
916 } |
|
917 return KNullDesC(); |
|
918 } |
|
919 |
|
920 |
|
921 // |
|
922 // TCommandArgument. |
|
923 // |
|
924 |
|
925 TCommandArgument::TCommandArgument(TUint aValueType, void* aValuePointer, const TDesC& aName) |
|
926 : TValue(aValueType, aValuePointer, aName) |
|
927 { |
|
928 } |
|
929 |
|
930 TCommandArgument::TCommandArgument(TUint aValueType, void* aValuePointer, const TDesC& aName, const TDesC& aDescription, const TDesC& aEnvVar) |
|
931 : TValue(aValueType, aValuePointer, aName, aDescription, aEnvVar) |
|
932 { |
|
933 } |
|
934 |
|
935 TCommandArgument::TCommandArgument(void* aValuePointer, TUint aValueType, const TDesC& aName, const TDesC& aDescription, const TDesC& aCommaSeparatedValueList, const TDesC& aCommaSeparatedDescriptionList, const TDesC& aEnvVar) |
|
936 : TValue(aValueType, aCommaSeparatedValueList, aCommaSeparatedDescriptionList, aValuePointer, aName, aDescription, aEnvVar) |
|
937 { |
|
938 } |
|
939 |
|
940 TBool TCommandArgument::IsOptional() const |
|
941 { |
|
942 return ValueType() & KValueTypeFlagOptional; |
|
943 } |
|
944 |
|
945 TBool TCommandArgument::IsLast() const |
|
946 { |
|
947 return ValueType() & KValueTypeFlagLast; |
|
948 } |
|
949 |
|
950 |
|
951 // |
|
952 // RCommandArgumentList. |
|
953 // |
|
954 |
|
955 void RCommandArgumentList::Close() |
|
956 { |
|
957 iArguments.Close(); |
|
958 } |
|
959 |
|
960 EXPORT_C void RCommandArgumentList::AppendIntL(TInt& aInt, const TDesC& aName) |
|
961 { |
|
962 iArguments.AppendL(TCommandArgument(KValueTypeInt, &aInt, aName)); |
|
963 } |
|
964 |
|
965 EXPORT_C void RCommandArgumentList::AppendIntL(RArray<TInt>& aInts, const TDesC& aName) |
|
966 { |
|
967 iArguments.AppendL(TCommandArgument(KValueTypeInt | KValueTypeFlagMultiple, &aInts, aName)); |
|
968 } |
|
969 |
|
970 EXPORT_C void RCommandArgumentList::AppendIntL(TInt64& aInt, const TDesC& aName) |
|
971 { |
|
972 iArguments.AppendL(TCommandArgument(KValueTypeInt64, &aInt, aName)); |
|
973 } |
|
974 |
|
975 EXPORT_C void RCommandArgumentList::AppendIntL(RArray<TInt64>& aInts, const TDesC& aName) |
|
976 { |
|
977 iArguments.AppendL(TCommandArgument(KValueTypeInt64 | KValueTypeFlagMultiple, &aInts, aName)); |
|
978 } |
|
979 |
|
980 EXPORT_C void RCommandArgumentList::AppendUintL(TUint& aUint, const TDesC& aName) |
|
981 { |
|
982 iArguments.AppendL(TCommandArgument(KValueTypeUint, &aUint, aName)); |
|
983 } |
|
984 |
|
985 EXPORT_C void RCommandArgumentList::AppendUintL(RArray<TUint>& aUints, const TDesC& aName) |
|
986 { |
|
987 iArguments.AppendL(TCommandArgument(KValueTypeUint | KValueTypeFlagMultiple, &aUints, aName)); |
|
988 } |
|
989 |
|
990 EXPORT_C void RCommandArgumentList::AppendUintL(TUint64& aUint, const TDesC& aName) |
|
991 { |
|
992 iArguments.AppendL(TCommandArgument(KValueTypeUint64, &aUint, aName)); |
|
993 } |
|
994 |
|
995 EXPORT_C void RCommandArgumentList::AppendUintL(RArray<TUint64>& aUints, const TDesC& aName) |
|
996 { |
|
997 iArguments.AppendL(TCommandArgument(KValueTypeUint64 | KValueTypeFlagMultiple, &aUints, aName)); |
|
998 } |
|
999 |
|
1000 EXPORT_C void RCommandArgumentList::AppendRealL(TReal64& aReal, const TDesC& aName) |
|
1001 { |
|
1002 iArguments.AppendL(TCommandArgument(KValueTypeReal, &aReal, aName)); |
|
1003 } |
|
1004 |
|
1005 EXPORT_C void RCommandArgumentList::AppendRealL(RArray<TReal64>& aReals, const TDesC& aName) |
|
1006 { |
|
1007 iArguments.AppendL(TCommandArgument(KValueTypeReal | KValueTypeFlagMultiple, &aReals, aName)); |
|
1008 } |
|
1009 |
|
1010 EXPORT_C void RCommandArgumentList::AppendStringL(HBufC*& aBuf, const TDesC& aName) |
|
1011 { |
|
1012 iArguments.AppendL(TCommandArgument(KValueTypeString, &aBuf, aName)); |
|
1013 } |
|
1014 |
|
1015 EXPORT_C void RCommandArgumentList::AppendStringL(RPointerArray<HBufC>& aBufs, const TDesC& aName) |
|
1016 { |
|
1017 iArguments.AppendL(TCommandArgument(KValueTypeString | KValueTypeFlagMultiple, &aBufs, aName)); |
|
1018 } |
|
1019 |
|
1020 EXPORT_C void RCommandArgumentList::AppendFileNameL(TFileName2& aFileName, const TDesC& aName) |
|
1021 { |
|
1022 iArguments.AppendL(TCommandArgument(KValueTypeFileName, &aFileName, aName)); |
|
1023 } |
|
1024 |
|
1025 EXPORT_C void RCommandArgumentList::AppendFileNameL(RArray<TFileName2>& aFileNames, const TDesC& aName) |
|
1026 { |
|
1027 iArguments.AppendL(TCommandArgument(KValueTypeFileName | KValueTypeFlagMultiple, &aFileNames, aName)); |
|
1028 } |
|
1029 |
|
1030 EXPORT_C void RCommandArgumentList::AppendEnumL(TInt& aEnum, const TDesC& aName) |
|
1031 { |
|
1032 iArguments.AppendL(TCommandArgument(KValueTypeEnum, &aEnum, aName)); |
|
1033 } |
|
1034 |
|
1035 EXPORT_C void RCommandArgumentList::AppendEnumL(TInt& aEnum, const TDesC& aName, const TDesC& aCommaSeparatedValueList) |
|
1036 { |
|
1037 TCommandArgument arg(KValueTypeEnum, &aEnum, aName); |
|
1038 arg.SetEnumValues(TEnum(aCommaSeparatedValueList)); |
|
1039 iArguments.AppendL(arg); |
|
1040 } |
|
1041 |
|
1042 EXPORT_C void RCommandArgumentList::AppendEnumL(RArray<TInt>& aEnum, const TDesC& aName) |
|
1043 { |
|
1044 iArguments.AppendL(TCommandArgument(KValueTypeEnum | KValueTypeFlagMultiple, &aEnum, aName)); |
|
1045 } |
|
1046 |
|
1047 EXPORT_C void RCommandArgumentList::AppendEnumL(RArray<TInt>& aEnum, const TDesC& aName, const TDesC& aCommaSeparatedValueList) |
|
1048 { |
|
1049 TCommandArgument arg(KValueTypeEnum | KValueTypeFlagMultiple, &aEnum, aName); |
|
1050 arg.SetEnumValues(TEnum(aCommaSeparatedValueList)); |
|
1051 iArguments.AppendL(arg); |
|
1052 } |
|
1053 |
|
1054 EXPORT_C void RCommandArgumentList::AppendIntL(TInt& aInt, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
1055 { |
|
1056 TCommandArgument argument(KValueTypeInt | aFlags, &aInt, aName, aDescription, aEnvVar); |
|
1057 Validate(argument); |
|
1058 iArguments.AppendL(argument); |
|
1059 } |
|
1060 |
|
1061 EXPORT_C void RCommandArgumentList::AppendIntL(RArray<TInt>& aInts, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
1062 { |
|
1063 TCommandArgument argument(KValueTypeInt | KValueTypeFlagMultiple | aFlags, &aInts, aName, aDescription, aEnvVar); |
|
1064 Validate(argument); |
|
1065 iArguments.AppendL(argument); |
|
1066 } |
|
1067 |
|
1068 EXPORT_C void RCommandArgumentList::AppendIntL(TInt64& aInt, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
1069 { |
|
1070 TCommandArgument argument(KValueTypeInt64 | aFlags, &aInt, aName, aDescription, aEnvVar); |
|
1071 Validate(argument); |
|
1072 iArguments.AppendL(argument); |
|
1073 } |
|
1074 |
|
1075 EXPORT_C void RCommandArgumentList::AppendIntL(RArray<TInt64>& aInts, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
1076 { |
|
1077 TCommandArgument argument(KValueTypeInt64 | KValueTypeFlagMultiple | aFlags, &aInts, aName, aDescription, aEnvVar); |
|
1078 Validate(argument); |
|
1079 iArguments.AppendL(argument); |
|
1080 } |
|
1081 |
|
1082 EXPORT_C void RCommandArgumentList::AppendUintL(TUint& aUint, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
1083 { |
|
1084 TCommandArgument argument(KValueTypeUint | aFlags, &aUint, aName, aDescription, aEnvVar); |
|
1085 Validate(argument); |
|
1086 iArguments.AppendL(argument); |
|
1087 } |
|
1088 |
|
1089 EXPORT_C void RCommandArgumentList::AppendUintL(RArray<TUint>& aUints, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
1090 { |
|
1091 TCommandArgument argument(KValueTypeUint | KValueTypeFlagMultiple | aFlags, &aUints, aName, aDescription, aEnvVar); |
|
1092 Validate(argument); |
|
1093 iArguments.AppendL(argument); |
|
1094 } |
|
1095 |
|
1096 EXPORT_C void RCommandArgumentList::AppendUintL(TUint64& aUint, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
1097 { |
|
1098 TCommandArgument argument(KValueTypeUint64 | aFlags, &aUint, aName, aDescription, aEnvVar); |
|
1099 Validate(argument); |
|
1100 iArguments.AppendL(argument); |
|
1101 } |
|
1102 |
|
1103 EXPORT_C void RCommandArgumentList::AppendUintL(RArray<TUint64>& aUints, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
1104 { |
|
1105 TCommandArgument argument(KValueTypeUint64 | KValueTypeFlagMultiple | aFlags, &aUints, aName, aDescription, aEnvVar); |
|
1106 Validate(argument); |
|
1107 iArguments.AppendL(argument); |
|
1108 } |
|
1109 |
|
1110 EXPORT_C void RCommandArgumentList::AppendRealL(TReal64& aReal, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
1111 { |
|
1112 TCommandArgument argument(KValueTypeReal | aFlags, &aReal, aName, aDescription, aEnvVar); |
|
1113 Validate(argument); |
|
1114 iArguments.AppendL(argument); |
|
1115 } |
|
1116 |
|
1117 EXPORT_C void RCommandArgumentList::AppendRealL(RArray<TReal64>& aReals, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
1118 { |
|
1119 TCommandArgument argument(KValueTypeReal | KValueTypeFlagMultiple | aFlags, &aReals, aName, aDescription, aEnvVar); |
|
1120 Validate(argument); |
|
1121 iArguments.AppendL(argument); |
|
1122 } |
|
1123 |
|
1124 EXPORT_C void RCommandArgumentList::AppendStringL(HBufC*& aBuf, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
1125 { |
|
1126 TCommandArgument argument(KValueTypeString | aFlags, &aBuf, aName, aDescription, aEnvVar); |
|
1127 Validate(argument); |
|
1128 iArguments.AppendL(argument); |
|
1129 } |
|
1130 |
|
1131 EXPORT_C void RCommandArgumentList::AppendStringL(RPointerArray<HBufC>& aBufs, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
1132 { |
|
1133 TCommandArgument argument(KValueTypeString | KValueTypeFlagMultiple | aFlags, &aBufs, aName, aDescription, aEnvVar); |
|
1134 Validate(argument); |
|
1135 iArguments.AppendL(argument); |
|
1136 } |
|
1137 |
|
1138 EXPORT_C void RCommandArgumentList::AppendFileNameL(TFileName2& aFileName, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
1139 { |
|
1140 TCommandArgument argument(KValueTypeFileName | aFlags, &aFileName, aName, aDescription, aEnvVar); |
|
1141 Validate(argument); |
|
1142 iArguments.AppendL(argument); |
|
1143 } |
|
1144 |
|
1145 EXPORT_C void RCommandArgumentList::AppendFileNameL(RArray<TFileName2>& aFileNames, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar) |
|
1146 { |
|
1147 TCommandArgument argument(KValueTypeFileName | KValueTypeFlagMultiple | aFlags, &aFileNames, aName, aDescription, aEnvVar); |
|
1148 Validate(argument); |
|
1149 iArguments.AppendL(argument); |
|
1150 } |
|
1151 |
|
1152 EXPORT_C void RCommandArgumentList::AppendEnumL(TInt& aEnum, const TDesC& aName, const TDesC& aDescription, const TDesC& aCommaSeparatedValueList, TUint aFlags, const TDesC& aEnvVar) |
|
1153 { |
|
1154 TCommandArgument argument(&aEnum, KValueTypeEnum | aFlags, aName, aDescription, aCommaSeparatedValueList, KNullDesC, aEnvVar); |
|
1155 Validate(argument); |
|
1156 iArguments.AppendL(argument); |
|
1157 } |
|
1158 |
|
1159 EXPORT_C void RCommandArgumentList::AppendEnumL(TInt& aEnum, const TDesC& aName, const TDesC& aDescription, const TDesC& aCommaSeparatedValueList, const TDesC& aCommaSeparatedDescriptionList, TUint aFlags, const TDesC& aEnvVar) |
|
1160 { |
|
1161 TCommandArgument argument(&aEnum, KValueTypeEnum | aFlags, aName, aDescription, aCommaSeparatedValueList, aCommaSeparatedDescriptionList, aEnvVar); |
|
1162 Validate(argument); |
|
1163 iArguments.AppendL(argument); |
|
1164 } |
|
1165 |
|
1166 EXPORT_C void RCommandArgumentList::AppendEnumL(RArray<TInt>& aEnum, const TDesC& aName, const TDesC& aDescription, const TDesC& aCommaSeparatedValueList, TUint aFlags, const TDesC& aEnvVar) |
|
1167 { |
|
1168 TCommandArgument argument(&aEnum, KValueTypeEnum | KValueTypeFlagMultiple | aFlags, aName, aDescription, aCommaSeparatedValueList, KNullDesC, aEnvVar); |
|
1169 Validate(argument); |
|
1170 iArguments.AppendL(argument); |
|
1171 } |
|
1172 |
|
1173 EXPORT_C void RCommandArgumentList::AppendEnumL(RArray<TInt>& aEnum, const TDesC& aName, const TDesC& aDescription, const TDesC& aCommaSeparatedValueList, const TDesC& aCommaSeparatedDescriptionList, TUint aFlags, const TDesC& aEnvVar) |
|
1174 { |
|
1175 TCommandArgument argument(&aEnum, KValueTypeEnum | KValueTypeFlagMultiple | aFlags, aName, aDescription, aCommaSeparatedValueList, aCommaSeparatedDescriptionList, aEnvVar); |
|
1176 Validate(argument); |
|
1177 iArguments.AppendL(argument); |
|
1178 } |
|
1179 |
|
1180 EXPORT_C TBool RCommandArgumentList::IsPresent(TInt aIndex) const |
|
1181 { |
|
1182 __ASSERT_ALWAYS((aIndex >= 0) && (aIndex < Count()), Panic(EInvalidArgumentIndex)); |
|
1183 return iArguments[aIndex].IsSet(); |
|
1184 } |
|
1185 |
|
1186 EXPORT_C TBool RCommandArgumentList::IsPresent(void* aValuePointer) const |
|
1187 { |
|
1188 const TInt count = Count(); |
|
1189 for (TInt i = 0; i < count; ++i) |
|
1190 { |
|
1191 if (iArguments[i].ValuePtr() == aValuePointer) |
|
1192 { |
|
1193 return iArguments[i].IsSet(); |
|
1194 } |
|
1195 } |
|
1196 return EFalse; |
|
1197 } |
|
1198 |
|
1199 void RCommandArgumentList::Validate(const TCommandArgument& aArgument) |
|
1200 { |
|
1201 TUint valueType = aArgument.ValueType(); |
|
1202 __ASSERT_ALWAYS(!(valueType & KValueTypeFlagLast) || (valueType & KValueTypeString), Panic(ELastArgNotStringType)); |
|
1203 __ASSERT_ALWAYS(!(valueType & KValueTypeFlagLast) || !(valueType & KValueTypeFlagMultiple), Panic(ELastArgMultiple)); |
|
1204 if (iArguments.Count() > 0) |
|
1205 { |
|
1206 __ASSERT_ALWAYS(!iArguments[iArguments.Count() - 1].AcceptsMultiple(), Panic(EArgumentFollowsMultipleArgument)); |
|
1207 __ASSERT_ALWAYS(valueType & KValueTypeFlagOptional || !iArguments[iArguments.Count() - 1].IsOptional(), Panic(ENonOptionalArgumentFollowsOptionalArgument)); |
|
1208 } |
|
1209 TInt pos = Find(aArgument.Name()); |
|
1210 if (pos >= 0) |
|
1211 { |
|
1212 iArguments.Remove(pos); // Allow a newly added argument of the same long name as an existing one to replace it. Primarily of use in .cif files via the "==include" directive to support command class hierarchies. |
|
1213 } |
|
1214 } |
|
1215 |
|
1216 EXPORT_C TInt RCommandArgumentList::Count() const |
|
1217 { |
|
1218 return iArguments.Count(); |
|
1219 } |
|
1220 |
|
1221 TCommandArgument& RCommandArgumentList::operator[](TInt aIndex) |
|
1222 { |
|
1223 return iArguments[aIndex]; |
|
1224 } |
|
1225 |
|
1226 EXPORT_C const TCommandArgument& RCommandArgumentList::operator[](TInt aIndex) const |
|
1227 { |
|
1228 return iArguments[aIndex]; |
|
1229 } |
|
1230 |
|
1231 EXPORT_C TBool RCommandArgumentList::AllSet() const |
|
1232 { |
|
1233 TBool allSet(ETrue); |
|
1234 const TInt count = Count(); |
|
1235 for (TInt i = 0; i < count; ++i) |
|
1236 { |
|
1237 const TCommandArgument& thisArgument = iArguments[i]; |
|
1238 if (!thisArgument.IsOptional() && !thisArgument.IsSet() && !(thisArgument.ValueType() == (KValueTypeFileName | KValueTypeFlagMultiple))) // Note, allow multiple file names because "dir\*" might not produces any matches, but we don't want to report that as a syntax error. Instead expect commands to cope with zero file names. |
|
1239 { |
|
1240 allSet = EFalse; |
|
1241 break; |
|
1242 } |
|
1243 } |
|
1244 return allSet; |
|
1245 } |
|
1246 |
|
1247 TInt RCommandArgumentList::Find(const TDesC& aName) const |
|
1248 { |
|
1249 const TInt count = Count(); |
|
1250 for (TInt i = 0; i < count; ++i) |
|
1251 { |
|
1252 if (iArguments[i].Name() == aName) |
|
1253 { |
|
1254 return i; |
|
1255 } |
|
1256 } |
|
1257 return KErrNotFound; |
|
1258 } |
|
1259 |
|
1260 EXPORT_C TPtrC RCommandArgumentList::AsString(void* aValuePointer) const |
|
1261 { |
|
1262 for (TInt i=0; i<Count(); ++i) |
|
1263 { |
|
1264 if (iArguments[i].ValuePtr() == aValuePointer) |
|
1265 { |
|
1266 return iArguments[i].AsString(); |
|
1267 } |
|
1268 } |
|
1269 return KNullDesC(); |
|
1270 } |
|
1271 |
|
1272 |
|
1273 // |
|
1274 // CCommandBase. |
|
1275 // |
|
1276 |
|
1277 EXPORT_C TInt CCommandBase::RunCommand() |
|
1278 { |
|
1279 TRAPD(err, RunCommandL()); |
|
1280 return err; |
|
1281 } |
|
1282 |
|
1283 EXPORT_C void CCommandBase::RunCommandL() |
|
1284 { |
|
1285 RunCommandL(NULL, NULL); |
|
1286 } |
|
1287 |
|
1288 EXPORT_C TInt CCommandBase::RunCommand(const TDesC* aCommandLine, CEnvironment* aEnv) |
|
1289 { |
|
1290 TRAPD(err, RunCommandL(aCommandLine, aEnv)); |
|
1291 return err; |
|
1292 } |
|
1293 |
|
1294 NONSHARABLE_CLASS(TExitController) : public MCommandBaseObserver |
|
1295 { |
|
1296 public: |
|
1297 TExitController(); |
|
1298 TBool IsComplete() const; |
|
1299 TInt CompletionError() const; |
|
1300 void WaitForCompletion(); |
|
1301 private: |
|
1302 virtual void HandleCommandComplete(CCommandBase& aCommand, TInt aError); |
|
1303 private: |
|
1304 TBool iSchedulerStarted; |
|
1305 TBool iComplete; |
|
1306 TInt iCompletionError; |
|
1307 }; |
|
1308 |
|
1309 TExitController::TExitController() |
|
1310 : iSchedulerStarted(EFalse), iComplete(EFalse), iCompletionError(KErrNone) |
|
1311 { |
|
1312 } |
|
1313 |
|
1314 TBool TExitController::IsComplete() const |
|
1315 { |
|
1316 return iComplete; |
|
1317 } |
|
1318 |
|
1319 TInt TExitController::CompletionError() const |
|
1320 { |
|
1321 return iCompletionError; |
|
1322 } |
|
1323 |
|
1324 void TExitController::WaitForCompletion() |
|
1325 { |
|
1326 iSchedulerStarted = ETrue; |
|
1327 CActiveScheduler::Start(); |
|
1328 } |
|
1329 |
|
1330 void TExitController::HandleCommandComplete(CCommandBase&, TInt aError) |
|
1331 { |
|
1332 iComplete = ETrue; |
|
1333 iCompletionError = aError; |
|
1334 if (iSchedulerStarted) |
|
1335 { |
|
1336 CActiveScheduler::Stop(); |
|
1337 iSchedulerStarted = EFalse; |
|
1338 } |
|
1339 } |
|
1340 |
|
1341 void CCommandBase::CreateHandlesL() |
|
1342 { |
|
1343 // This function is called *before* the command line is parsed, so things like iConsoleImplementation and iConsoleSize are not available. |
|
1344 // UpdateHandlesL is called *after* the command line is parsed to change the handles if necessary. |
|
1345 |
|
1346 TFullName name; |
|
1347 LtkUtils::GetFriendlyThreadName(RThread(), name); |
|
1348 RIoConsole console; |
|
1349 CleanupClosePushL(console); |
|
1350 |
|
1351 TInt err = iStdin.Open(iIoSession); |
|
1352 if (err == KErrNone) |
|
1353 { |
|
1354 User::LeaveIfError(iStdout.Open(iIoSession)); |
|
1355 User::LeaveIfError(iStderr.Open(iIoSession)); |
|
1356 } |
|
1357 else |
|
1358 { |
|
1359 console.CreateL(iIoSession, name, TSize(KConsFullScreen, KConsFullScreen), RIoConsole::ELazyCreate); |
|
1360 DoCreateHandlesL(console, iStdin, iStdout, iStderr); |
|
1361 } |
|
1362 |
|
1363 CleanupStack::PopAndDestroy(&console); // Console (if used) will be held open by the read and write handles. |
|
1364 |
|
1365 if (iFlags & ENotifyStdinChanges) |
|
1366 { |
|
1367 iReadChangeNotifier = new(ELeave)CReaderChangeNotifier(*this, iStdin); |
|
1368 iReadChangeNotifier->Notify(); |
|
1369 } |
|
1370 } |
|
1371 |
|
1372 void CCommandBase::UpdateHandlesL() |
|
1373 { |
|
1374 TFullName name; |
|
1375 LtkUtils::GetFriendlyThreadName(RThread(), name); |
|
1376 RIoConsole console; |
|
1377 CleanupClosePushL(console); |
|
1378 |
|
1379 if (iPersistentConsoleName) |
|
1380 { |
|
1381 ((RIoPersistentConsole&)console).CreateL(iIoSession, *iPersistentConsoleName, (iConsoleTitle == NULL) ? name : *iConsoleTitle); |
|
1382 } |
|
1383 else |
|
1384 { |
|
1385 TSize size(KConsFullScreen, KConsFullScreen); |
|
1386 if (iConsoleSize.Count() > 0) |
|
1387 { |
|
1388 size.iWidth = iConsoleSize[0]; |
|
1389 } |
|
1390 if (iConsoleSize.Count() > 1) |
|
1391 { |
|
1392 size.iHeight = iConsoleSize[1]; |
|
1393 } |
|
1394 RIoConsole underlyingConsole; |
|
1395 underlyingConsole.OpenL(iIoSession, iStdout); |
|
1396 CleanupClosePushL(underlyingConsole); |
|
1397 console.CreateL(iIoSession, *iConsoleImplementation, underlyingConsole, (iConsoleTitle == NULL) ? name : *iConsoleTitle, size); |
|
1398 CleanupStack::PopAndDestroy(&underlyingConsole); |
|
1399 RIoConsoleReadHandle stdin; |
|
1400 CleanupClosePushL(stdin); |
|
1401 RIoConsoleWriteHandle stdout; |
|
1402 CleanupClosePushL(stdout); |
|
1403 RIoConsoleWriteHandle stderr; |
|
1404 CleanupClosePushL(stderr); |
|
1405 DoCreateHandlesL(console, stdin, stdout, stderr); |
|
1406 if (iFlags & ENotifyStdinChanges) |
|
1407 { |
|
1408 CReaderChangeNotifier* readChangeNotifier = new(ELeave)CReaderChangeNotifier(*this, iStdin); |
|
1409 delete iReadChangeNotifier; |
|
1410 iReadChangeNotifier = readChangeNotifier; |
|
1411 } |
|
1412 iStdin.Close(); |
|
1413 iStdin = stdin; |
|
1414 iStdout.Close(); |
|
1415 iStdout = stdout; |
|
1416 iStderr.Close(); |
|
1417 iStderr = stderr; |
|
1418 CleanupStack::Pop(3, &stdin); |
|
1419 if (iFlags & ENotifyStdinChanges) |
|
1420 { |
|
1421 iReadChangeNotifier->Notify(); |
|
1422 } |
|
1423 } |
|
1424 |
|
1425 CleanupStack::PopAndDestroy(&console); // Console (if used) will be held open by the read and write handles. |
|
1426 } |
|
1427 |
|
1428 void CCommandBase::DoCreateHandlesL(RIoConsole& aConsole, RIoConsoleReadHandle& aStdin, RIoConsoleWriteHandle& aStdout, RIoConsoleWriteHandle& aStderr) |
|
1429 { |
|
1430 TFullName name; |
|
1431 LtkUtils::GetFriendlyThreadName(RThread(), name); |
|
1432 |
|
1433 TName consImpl; |
|
1434 TInt err = aConsole.Implementation(consImpl); |
|
1435 if (err != KErrOverflow) |
|
1436 { |
|
1437 User::LeaveIfError(err); |
|
1438 } |
|
1439 if (consImpl.Right(KDllExt().Length()).CompareF(KDllExt)==0) |
|
1440 { |
|
1441 consImpl.SetLength(consImpl.Length() - KDllExt().Length()); |
|
1442 } |
|
1443 if (name.Length() + consImpl.Length() + 1 > name.MaxLength()) |
|
1444 { |
|
1445 name.SetLength(name.MaxLength() - (name.Length() + consImpl.Length() + 1)); |
|
1446 } |
|
1447 name.Insert(0, _L("_")); |
|
1448 name.Insert(0, consImpl); |
|
1449 |
|
1450 iIoSession.SetObjectNameL(aConsole.SubSessionHandle(), name); |
|
1451 |
|
1452 aStdin.CreateL(iIoSession); |
|
1453 _LIT(KStdin, "_stdin"); |
|
1454 name.Append(KStdin); |
|
1455 iIoSession.SetObjectNameL(aStdin.SubSessionHandle(), name); |
|
1456 |
|
1457 aStdout.CreateL(iIoSession); |
|
1458 name.Delete(name.Length() - KStdin().Length(), KStdin().Length()); |
|
1459 _LIT(KStdout, "_stdout"); |
|
1460 name.Append(KStdout); |
|
1461 iIoSession.SetObjectNameL(aStdout.SubSessionHandle(), name); |
|
1462 |
|
1463 aStderr.CreateL(iIoSession); |
|
1464 User::LeaveIfError(aStderr.SetIsStdErr(ETrue)); |
|
1465 name.Delete(name.Length() - KStdout().Length(), KStdout().Length()); |
|
1466 _LIT(KStderr, "_stderr"); |
|
1467 name.Append(KStderr); |
|
1468 iIoSession.SetObjectNameL(aStderr.SubSessionHandle(), name); |
|
1469 |
|
1470 aConsole.AttachL(aStdin, RIoEndPoint::EForeground); |
|
1471 aConsole.AttachL(aStdout); |
|
1472 aConsole.AttachL(aStderr); |
|
1473 |
|
1474 aStdin.SetUnderlyingConsoleL(aConsole); |
|
1475 aStdout.SetUnderlyingConsoleL(aConsole); |
|
1476 aStderr.SetUnderlyingConsoleL(aConsole); |
|
1477 } |
|
1478 |
|
1479 EXPORT_C void CCommandBase::RunCommandL(const TDesC* aCommandLine, CEnvironment* aEnv) |
|
1480 { |
|
1481 iFlags |= EOwnsHandles; |
|
1482 |
|
1483 User::LeaveIfError(iIoSession.Connect()); |
|
1484 if (iFlags & ESharableIoSession) |
|
1485 { |
|
1486 User::LeaveIfError(iIoSession.ShareAuto()); |
|
1487 } |
|
1488 |
|
1489 TBool commandLineOnStack(EFalse); |
|
1490 const TDesC* commandLine = aCommandLine; |
|
1491 if (aCommandLine == NULL) |
|
1492 { |
|
1493 commandLine = ReadCommandLineLC(); |
|
1494 commandLineOnStack = ETrue; |
|
1495 } |
|
1496 |
|
1497 CreateEnvironmentL(aEnv); |
|
1498 CreateHandlesL(); |
|
1499 |
|
1500 TExitController exitController; |
|
1501 RunCommand(iIoSession, iStdin, iStdout, iStderr, commandLine, iEnv, &exitController); |
|
1502 if (!exitController.IsComplete()) |
|
1503 { |
|
1504 exitController.WaitForCompletion(); |
|
1505 } |
|
1506 |
|
1507 TInt completionError = exitController.CompletionError(); |
|
1508 if (completionError != KErrNone) |
|
1509 { |
|
1510 User::Leave(completionError); |
|
1511 } |
|
1512 |
|
1513 if (commandLineOnStack) |
|
1514 { |
|
1515 CleanupStack::PopAndDestroy((TAny*)commandLine); |
|
1516 } |
|
1517 } |
|
1518 |
|
1519 EXPORT_C TInt CCommandBase::RunCommand(RIoSession& aIoSession, RIoReadHandle& aStdin, RIoWriteHandle& aStdout, RIoWriteHandle& aStderr, const TDesC* aCommandLine, CEnvironment* aEnv) |
|
1520 { |
|
1521 TExitController exitController; |
|
1522 RunCommand(aIoSession, aStdin, aStdout, aStderr, aCommandLine, aEnv, &exitController); |
|
1523 if (exitController.IsComplete()) |
|
1524 { |
|
1525 return exitController.CompletionError(); |
|
1526 } |
|
1527 else |
|
1528 { |
|
1529 exitController.WaitForCompletion(); |
|
1530 return exitController.CompletionError(); |
|
1531 } |
|
1532 } |
|
1533 |
|
1534 EXPORT_C void CCommandBase::RunCommandL(RIoSession& aIoSession, RIoReadHandle& aStdin, RIoWriteHandle& aStdout, RIoWriteHandle& aStderr, const TDesC* aCommandLine, CEnvironment* aEnv) |
|
1535 { |
|
1536 User::LeaveIfError(RunCommand(aIoSession, aStdin, aStdout, aStderr, aCommandLine, aEnv)); |
|
1537 } |
|
1538 |
|
1539 EXPORT_C void CCommandBase::RunCommand(RIoSession& aIoSession, RIoReadHandle& aStdin, RIoWriteHandle& aStdout, RIoWriteHandle& aStderr, const TDesC* aCommandLine, CEnvironment* aEnv, MCommandBaseObserver* aObserver) |
|
1540 { |
|
1541 TRAPD(err, RunCommandL(aIoSession, aStdin, aStdout, aStderr, aCommandLine, aEnv, aObserver)); |
|
1542 if (err) |
|
1543 { |
|
1544 Complete(err); |
|
1545 } |
|
1546 } |
|
1547 |
|
1548 EXPORT_C TUint CCommandBase::Flags() const |
|
1549 { |
|
1550 return (iFlags & KPublicFlagsMask); |
|
1551 } |
|
1552 |
|
1553 EXPORT_C void CCommandBase::SetFlags(TUint aFlags) |
|
1554 { |
|
1555 TUint privateFlags = (iFlags & KPrivateFlagsMask); |
|
1556 iFlags = (aFlags & KPublicFlagsMask); |
|
1557 iFlags |= privateFlags; |
|
1558 if (iFlags & ECompleteOnRunL) |
|
1559 { |
|
1560 iFlags |= EManualComplete; |
|
1561 } |
|
1562 } |
|
1563 |
|
1564 EXPORT_C void CCommandBase::SetCif(const CCommandInfoFile& aCif) |
|
1565 { |
|
1566 ASSERT((iCif == NULL) && !(iFlags & EOwnsCif)); |
|
1567 iCif = &const_cast<CCommandInfoFile&>(aCif); |
|
1568 } |
|
1569 |
|
1570 EXPORT_C const CCommandInfoFile* CCommandBase::Cif() const |
|
1571 { |
|
1572 return iCif; |
|
1573 } |
|
1574 |
|
1575 void CCommandBase::RunCommandL(RIoSession& aIoSession, RIoReadHandle& aStdin, RIoWriteHandle& aStdout, RIoWriteHandle& aStderr, const TDesC* aCommandLine, CEnvironment* aEnv, MCommandBaseObserver* aObserver) |
|
1576 { |
|
1577 iIoSession = aIoSession; |
|
1578 iStdin = aStdin; |
|
1579 iStdout = aStdout; |
|
1580 iStderr = aStderr; |
|
1581 iObserver = aObserver; |
|
1582 |
|
1583 CreateEnvironmentL(aEnv); |
|
1584 |
|
1585 if (aCommandLine) |
|
1586 { |
|
1587 RunL(*aCommandLine); |
|
1588 } |
|
1589 else |
|
1590 { |
|
1591 const TDesC* commandLine = ReadCommandLineLC(); |
|
1592 RunL(*commandLine); |
|
1593 CleanupStack::PopAndDestroy((TAny*)commandLine); |
|
1594 } |
|
1595 } |
|
1596 |
|
1597 void CCommandBase::RunL(const TDesC& aCommandLine) |
|
1598 { |
|
1599 TInt err = ParseCommandLine(aCommandLine); |
|
1600 if (iFlags & ECifReadFailed) |
|
1601 { |
|
1602 // No point in trying to display help. |
|
1603 Complete(err); |
|
1604 } |
|
1605 else if (err || iDisplayHelp) |
|
1606 { |
|
1607 if (err && !iDisplayHelp) |
|
1608 { |
|
1609 DisplayHelpAndComplete(err, _L("Couldn't parse command line")); |
|
1610 } |
|
1611 else |
|
1612 { |
|
1613 DisplayHelpAndComplete(); |
|
1614 } |
|
1615 } |
|
1616 else |
|
1617 { |
|
1618 if (iConsoleImplementation || iPersistentConsoleName) |
|
1619 { |
|
1620 UpdateHandlesL(); |
|
1621 } |
|
1622 |
|
1623 TBool deleted(EFalse); |
|
1624 iDeleted = &deleted; |
|
1625 // Note, commands that manually complete may call CCommandBase::Complete from their DoRunL, which in the case |
|
1626 // of "local" fshell commands (i.e. ones that run in the context of fshell's thread) will result in the object |
|
1627 // being deleted. This flag detects this to avoid code later in this function blowing up. |
|
1628 TRAP(err, DoRunL()); |
|
1629 if (err) |
|
1630 { |
|
1631 HandleLeave(err); |
|
1632 } |
|
1633 else if (!deleted && !(iFlags & EManualComplete) && !IsActive() && !(iFlags & ECompleted)) |
|
1634 { |
|
1635 Complete(); |
|
1636 } |
|
1637 if (!deleted) |
|
1638 { |
|
1639 iDeleted = NULL; |
|
1640 } |
|
1641 } |
|
1642 } |
|
1643 |
|
1644 EXPORT_C CCommandBase::CCommandBase() |
|
1645 : CActive(CActive::EPriorityStandard) |
|
1646 { |
|
1647 // These are protected so could be accessed directly, hence can't move |
|
1648 // The asserts have to be scoped inside a CCommandBase function because the member vars are protected. They don't generate any code. |
|
1649 __ASSERT_COMPILE(_FOFF(CCommandBase, iOptions) == 7*4); |
|
1650 __ASSERT_COMPILE(_FOFF(CCommandBase, iArguments) == 15*4); |
|
1651 |
|
1652 CActiveScheduler::Add(this); |
|
1653 if (Dll::Tls() == NULL) |
|
1654 { |
|
1655 Dll::SetTls(this); |
|
1656 iFlags |= ETlsSet; |
|
1657 } |
|
1658 } |
|
1659 |
|
1660 EXPORT_C CCommandBase::CCommandBase(TUint aFlags) |
|
1661 : CActive(CActive::EPriorityStandard), iFlags(aFlags) |
|
1662 { |
|
1663 CActiveScheduler::Add(this); |
|
1664 if (Dll::Tls() == NULL) |
|
1665 { |
|
1666 Dll::SetTls(this); |
|
1667 iFlags |= ETlsSet; |
|
1668 } |
|
1669 |
|
1670 // Ensure EManualComplete is set if ECompleteOnRunL is. |
|
1671 SetFlags(Flags()); |
|
1672 } |
|
1673 |
|
1674 EXPORT_C CCommandBase::~CCommandBase() |
|
1675 { |
|
1676 delete iReadChangeNotifier; |
|
1677 delete iCompleter; |
|
1678 iFs.Close(); |
|
1679 if (iFlags & EOwnsHandles) |
|
1680 { |
|
1681 iStderr.Close(); |
|
1682 iStdout.Close(); |
|
1683 iStdin.Close(); |
|
1684 iIoSession.Close(); |
|
1685 } |
|
1686 |
|
1687 if (iFlags & EOwnsEnv) |
|
1688 { |
|
1689 delete iEnv; |
|
1690 } |
|
1691 delete iConsoleImplementation; |
|
1692 delete iConsoleTitle; |
|
1693 delete iPersistentConsoleName; |
|
1694 iConsoleSize.Close(); |
|
1695 iOptions.Close(); |
|
1696 iArguments.Close(); |
|
1697 if (iFlags & EOwnsCif) |
|
1698 { |
|
1699 delete iCif; |
|
1700 } |
|
1701 if (iDeleted) |
|
1702 { |
|
1703 *iDeleted = ETrue; |
|
1704 } |
|
1705 if (iFlags & ETlsSet) |
|
1706 { |
|
1707 Dll::SetTls(NULL); |
|
1708 } |
|
1709 } |
|
1710 |
|
1711 EXPORT_C void CCommandBase::BaseConstructL() |
|
1712 { |
|
1713 iCompleter = new(ELeave)CCommandCompleter(*this); |
|
1714 } |
|
1715 |
|
1716 EXPORT_C CEnvironment& CCommandBase::Env() |
|
1717 { |
|
1718 __ASSERT_ALWAYS(iEnv, Panic(ENoEnvironment)); |
|
1719 return *iEnv; |
|
1720 } |
|
1721 |
|
1722 EXPORT_C const CEnvironment& CCommandBase::Env() const |
|
1723 { |
|
1724 __ASSERT_ALWAYS(iEnv, Panic(ENoEnvironment)); |
|
1725 return *iEnv; |
|
1726 } |
|
1727 |
|
1728 void CCommandBase::CompleteCallback(TInt aError) |
|
1729 { |
|
1730 Complete(aError); |
|
1731 } |
|
1732 |
|
1733 EXPORT_C void CCommandBase::Complete() |
|
1734 { |
|
1735 Complete(KErrNone); |
|
1736 } |
|
1737 |
|
1738 EXPORT_C void CCommandBase::Complete(TInt aError) |
|
1739 { |
|
1740 __ASSERT_ALWAYS(!(iFlags & ECompleted), Panic(EAlreadyCompleted)); |
|
1741 iFlags |= ECompleted; |
|
1742 iCompletionReason = aError; |
|
1743 if (aError < 0) |
|
1744 { |
|
1745 RProcess::Rendezvous(aError); |
|
1746 const TDesC& name = Name(); |
|
1747 PrintError(aError, _L("Unable to run \"%S\""), &name); |
|
1748 } |
|
1749 if (iObserver) |
|
1750 { |
|
1751 iObserver->HandleCommandComplete(*this, aError); |
|
1752 } |
|
1753 } |
|
1754 |
|
1755 EXPORT_C void CCommandBase::Complete(TRefByValue<const TDesC> aFmt, ...) |
|
1756 { |
|
1757 VA_LIST list; |
|
1758 VA_START(list, aFmt); |
|
1759 TBuf<0x100> buf; |
|
1760 TOverflowTruncate overflow; |
|
1761 buf.AppendFormatList(aFmt, list, &overflow); |
|
1762 VA_END(list); |
|
1763 iStdout.Write(buf); |
|
1764 Complete(); |
|
1765 } |
|
1766 |
|
1767 EXPORT_C void CCommandBase::Complete(TInt aError, TRefByValue<const TDesC> aFmt, ...) |
|
1768 { |
|
1769 if (iFlags & EErrorReported) |
|
1770 { |
|
1771 Complete(aError); |
|
1772 } |
|
1773 else |
|
1774 { |
|
1775 RProcess::Rendezvous(aError); // This isn't right for thread commands - not sure how to distinguish. Probably won't cause a problem though. (We also rendezvous in Complete(TInt), but to avoid deadlocks in server commands we need to rendezvous before writing anything (in the error case) |
|
1776 VA_LIST list; |
|
1777 VA_START(list, aFmt); |
|
1778 PrintErrorList(aError, aFmt, list); |
|
1779 Complete(aError); |
|
1780 VA_END(list); |
|
1781 } |
|
1782 } |
|
1783 |
|
1784 EXPORT_C void CCommandBase::CompleteAsync(TInt aError) |
|
1785 { |
|
1786 iCompleter->Complete(aError); |
|
1787 } |
|
1788 |
|
1789 EXPORT_C void CCommandBase::CompleteAsync(TInt aError, TRefByValue<const TDesC> aFmt, ...) |
|
1790 { |
|
1791 if (iFlags & EErrorReported) |
|
1792 { |
|
1793 iCompleter->Complete(aError); |
|
1794 } |
|
1795 else |
|
1796 { |
|
1797 VA_LIST list; |
|
1798 VA_START(list, aFmt); |
|
1799 TBuf<0x100> buf; |
|
1800 FormatErrorText(buf, aError, aFmt, list); |
|
1801 VA_END(list); |
|
1802 iCompleter->Complete(aError, buf, iStderr); |
|
1803 } |
|
1804 } |
|
1805 |
|
1806 EXPORT_C void CCommandBase::ReadL(TDes& aData) |
|
1807 { |
|
1808 User::LeaveIfError(iStdin.Read(aData)); |
|
1809 } |
|
1810 |
|
1811 EXPORT_C void CCommandBase::Write(const TDesC& aData) |
|
1812 { |
|
1813 iStdout.Write(aData); // Ignore error. |
|
1814 } |
|
1815 |
|
1816 EXPORT_C void CCommandBase::Printf(TRefByValue<const TDesC> aFmt, ...) |
|
1817 { |
|
1818 VA_LIST list; |
|
1819 VA_START(list, aFmt); |
|
1820 PrintList(aFmt, list); |
|
1821 VA_END(list); |
|
1822 } |
|
1823 |
|
1824 EXPORT_C void CCommandBase::Printf(TRefByValue<const TDesC8> aFmt, ...) |
|
1825 { |
|
1826 VA_LIST list; |
|
1827 VA_START(list, aFmt); |
|
1828 PrintList(aFmt, list); |
|
1829 VA_END(list); |
|
1830 } |
|
1831 |
|
1832 EXPORT_C void CCommandBase::PrintError(TInt aError, TRefByValue<const TDesC> aFmt, ...) |
|
1833 { |
|
1834 VA_LIST list; |
|
1835 VA_START(list, aFmt); |
|
1836 PrintErrorList(aError, aFmt, list); |
|
1837 VA_END(list); |
|
1838 } |
|
1839 |
|
1840 EXPORT_C void CCommandBase::PrintWarning(TRefByValue<const TDesC> aFmt, ...) |
|
1841 { |
|
1842 VA_LIST list; |
|
1843 VA_START(list, aFmt); |
|
1844 PrintWarningList(aFmt, list); |
|
1845 VA_END(list); |
|
1846 } |
|
1847 |
|
1848 EXPORT_C void CCommandBase::PrintList(TRefByValue<const TDesC> aFmt, VA_LIST& aList) |
|
1849 { |
|
1850 TOverflowTruncate overflow; |
|
1851 TBuf<0x100> buf; |
|
1852 buf.AppendFormatList(aFmt, aList, &overflow); |
|
1853 iStdout.Write(buf); |
|
1854 } |
|
1855 |
|
1856 EXPORT_C void CCommandBase::PrintList(TRefByValue<const TDesC8> aFmt, VA_LIST& aList) |
|
1857 { |
|
1858 TOverflowTruncate8 overflow; |
|
1859 TBuf8<0x200> buf; |
|
1860 buf.AppendFormatList(aFmt, aList, &overflow); |
|
1861 if (buf.Length() > 0x100) buf.SetLength(0x100); // Truncate to half the buffer size so that the call to Expand doesn't panic |
|
1862 TPtrC wideBuf = buf.Expand(); |
|
1863 iStdout.Write(wideBuf); |
|
1864 } |
|
1865 |
|
1866 EXPORT_C void CCommandBase::PrintErrorList(TInt aError, TRefByValue<const TDesC> aFmt, VA_LIST& aList) |
|
1867 { |
|
1868 if (!Stderr().SubSessionHandle()) |
|
1869 { |
|
1870 // Only can happen if we error during say command line parsing, which occurs before the handles are set up. |
|
1871 return; |
|
1872 } |
|
1873 |
|
1874 if (iSupressingErrors > 0 || ((iFlags & EErrorReported) && !(iFlags & EReportAllErrors))) |
|
1875 { |
|
1876 return; |
|
1877 } |
|
1878 |
|
1879 CheckNewLine(); |
|
1880 TBuf<0x100> buf; |
|
1881 FormatErrorText(buf, aError, aFmt, aList); |
|
1882 iStderr.Write(buf); |
|
1883 iFlags |= EErrorReported; |
|
1884 } |
|
1885 |
|
1886 EXPORT_C void CCommandBase::PrintWarningList(TRefByValue<const TDesC> aFmt, VA_LIST& aList) |
|
1887 { |
|
1888 if (!Stderr().SubSessionHandle()) |
|
1889 { |
|
1890 // Only can happen if we error during say command line parsing, which occurs before the handles are set up. |
|
1891 return; |
|
1892 } |
|
1893 CheckNewLine(); |
|
1894 TBuf<0x100> buf; |
|
1895 FormatWarningText(buf, aFmt, aList); |
|
1896 iStderr.Write(buf); |
|
1897 } |
|
1898 |
|
1899 EXPORT_C void CCommandBase::LeaveIfFileExists(const TDesC& aFileName) |
|
1900 { |
|
1901 TFileName2 fileName(aFileName); |
|
1902 if (fileName.Exists(FsL())) |
|
1903 { |
|
1904 PrintError(KErrAlreadyExists, _L("\"%S\" already exists"), &aFileName); |
|
1905 User::Leave(KErrAlreadyExists); |
|
1906 } |
|
1907 } |
|
1908 |
|
1909 EXPORT_C void CCommandBase::LeaveIfFileNotFound(const TDesC& aFileName) |
|
1910 { |
|
1911 TEntry e; |
|
1912 TInt err = FsL().Entry(aFileName, e); |
|
1913 if (err == KErrNotFound) |
|
1914 { |
|
1915 PrintError(err, _L("\"%S\" not found"), &aFileName); |
|
1916 } |
|
1917 else if (err) |
|
1918 { |
|
1919 PrintError(err, _L("Couldn't read \"%S\""), &aFileName); |
|
1920 } |
|
1921 User::LeaveIfError(err); |
|
1922 } |
|
1923 |
|
1924 EXPORT_C RFs& CCommandBase::Fs() |
|
1925 { |
|
1926 __ASSERT_ALWAYS(iFs.Handle(), Panic(ERFsNotConnected)); |
|
1927 return iFs; |
|
1928 } |
|
1929 |
|
1930 EXPORT_C const RFs& CCommandBase::Fs() const |
|
1931 { |
|
1932 __ASSERT_ALWAYS(iFs.Handle(), Panic(ERFsNotConnected)); |
|
1933 return iFs; |
|
1934 } |
|
1935 |
|
1936 EXPORT_C RFs& CCommandBase::FsL() |
|
1937 { |
|
1938 if (iFs.Handle() == 0) |
|
1939 { |
|
1940 User::LeaveIfError(iFs.Connect()); |
|
1941 const TDesC& pwd = Env().Pwd(); |
|
1942 TInt err = iFs.SetSessionPath(pwd); |
|
1943 if (err) |
|
1944 { |
|
1945 // Could fail if, for eg, we have no capabilities and the fshell we were launched from had \sys\bin as its cwd. In such a case shouldn't be considered an error, only a warning. |
|
1946 PrintWarning(_L("Couldn't set session path for %S to '%S'. (err = %d)\r\n"), &Name(), &pwd, err); |
|
1947 } |
|
1948 } |
|
1949 return iFs; |
|
1950 } |
|
1951 |
|
1952 EXPORT_C const RFs& CCommandBase::FsL() const |
|
1953 { |
|
1954 return const_cast<CCommandBase*>(this)->FsL(); |
|
1955 } |
|
1956 |
|
1957 EXPORT_C RIoSession& CCommandBase::IoSession() |
|
1958 { |
|
1959 return iIoSession; |
|
1960 } |
|
1961 |
|
1962 EXPORT_C RIoConsoleReadHandle& CCommandBase::Stdin() |
|
1963 { |
|
1964 return iStdin; |
|
1965 } |
|
1966 |
|
1967 EXPORT_C RIoConsoleWriteHandle& CCommandBase::Stdout() |
|
1968 { |
|
1969 return iStdout; |
|
1970 } |
|
1971 |
|
1972 EXPORT_C RIoConsoleWriteHandle& CCommandBase::Stderr() |
|
1973 { |
|
1974 return iStderr; |
|
1975 } |
|
1976 |
|
1977 EXPORT_C void CCommandBase::OptionsL(RCommandOptionList&) |
|
1978 { |
|
1979 } |
|
1980 |
|
1981 EXPORT_C void CCommandBase::ArgumentsL(RCommandArgumentList&) |
|
1982 { |
|
1983 } |
|
1984 |
|
1985 EXPORT_C TInt CCommandBase::Extension_(TUint aExtensionId, TAny*& a0, TAny* a1) |
|
1986 { |
|
1987 return CActive::Extension_(aExtensionId, a0, a1); |
|
1988 } |
|
1989 |
|
1990 EXPORT_C void CCommandBase::HandleLeave(TInt aError) |
|
1991 { |
|
1992 const TDesC& name = Name(); |
|
1993 Complete(aError, _L("Command \"%S\" failed"), &name); |
|
1994 } |
|
1995 |
|
1996 void HandleEscapeL(TLex& aLex, CTextBuffer& aBuf) |
|
1997 { |
|
1998 _LIT(KBell, "\a"); |
|
1999 _LIT(KBackspace, "\b"); |
|
2000 _LIT(KFormFeed, "\f"); |
|
2001 _LIT(KHorizontalTab, "\t"); |
|
2002 _LIT(KVerticalTab, "\v"); |
|
2003 _LIT(KNewLine, "\n"); |
|
2004 _LIT(KCarriageReturn, "\r"); |
|
2005 if (!aLex.Eos()) |
|
2006 { |
|
2007 TChar c2 = aLex.Get(); |
|
2008 switch (c2) |
|
2009 { |
|
2010 case 'a': |
|
2011 aBuf.AppendL(KBell); |
|
2012 break; |
|
2013 case 'b': |
|
2014 aBuf.AppendL(KBackspace); |
|
2015 break; |
|
2016 case 'f': |
|
2017 aBuf.AppendL(KFormFeed); |
|
2018 break; |
|
2019 case 't': |
|
2020 aBuf.AppendL(KHorizontalTab); |
|
2021 break; |
|
2022 case 'v': |
|
2023 aBuf.AppendL(KVerticalTab); |
|
2024 break; |
|
2025 case 'n': |
|
2026 aBuf.AppendL(KNewLine); |
|
2027 break; |
|
2028 case 'r': |
|
2029 aBuf.AppendL(KCarriageReturn); |
|
2030 break; |
|
2031 case 'x': |
|
2032 case 'X': |
|
2033 if (aLex.Remainder().Length() >= 2) |
|
2034 { |
|
2035 TLex lex(aLex.Remainder().Mid(0, 2)); // Note, can't use aLex directly because there could be hex characters following the 2 that relate to this escape sequence. |
|
2036 TUint16 val; |
|
2037 User::LeaveIfError(lex.Val(val, EHex)); |
|
2038 aBuf.AppendL(TPtrC(&val, 1)); |
|
2039 aLex.Inc(2); |
|
2040 } |
|
2041 break; |
|
2042 case 'u': |
|
2043 if (aLex.Remainder().Length() >= 4) |
|
2044 { |
|
2045 TLex lex(aLex.Remainder().Mid(0, 4)); // Note, can't use aLex directly because there could be hex characters following the 4 that relate to this escape sequence. |
|
2046 TUint16 val; |
|
2047 User::LeaveIfError(lex.Val(val, EHex)); |
|
2048 aBuf.AppendL(TChar(val)); |
|
2049 aLex.Inc(4); |
|
2050 } |
|
2051 break; |
|
2052 case 'U': |
|
2053 if (aLex.Remainder().Length() >= 8) |
|
2054 { |
|
2055 TLex lex(aLex.Remainder().Mid(0, 8)); // Note, can't use aLex directly because there could be hex characters following the 8 that relate to this escape sequence. |
|
2056 TUint32 val; |
|
2057 User::LeaveIfError(lex.Val(val, EHex)); |
|
2058 aBuf.AppendL(TChar(val)); |
|
2059 aLex.Inc(8); |
|
2060 } |
|
2061 break; |
|
2062 default: |
|
2063 aBuf.AppendL(TPtrC((TUint16*)&c2, 1)); |
|
2064 break; |
|
2065 } |
|
2066 } |
|
2067 } |
|
2068 |
|
2069 EXPORT_C HBufC* Stringify::ReadLC(TLex& aLex, const TChar& aEscapeChar) |
|
2070 { |
|
2071 return ReadLC(aLex, aEscapeChar, NULL, 0); |
|
2072 } |
|
2073 |
|
2074 EXPORT_C HBufC* Stringify::ReadLC(TLex& aLex, const TChar& aEscapeChar, CCommandBase& aErrorContext) |
|
2075 { |
|
2076 return ReadLC(aLex, aEscapeChar, &aErrorContext, 0); |
|
2077 } |
|
2078 |
|
2079 EXPORT_C HBufC* Stringify::ReadLC(TLex& aLex, const TChar& aEscapeChar, TUint aReadMode) |
|
2080 { |
|
2081 return ReadLC(aLex, aEscapeChar, NULL, aReadMode); |
|
2082 } |
|
2083 |
|
2084 EXPORT_C HBufC* Stringify::ReadLC(TLex& aLex, const TChar& aEscapeChar, CCommandBase& aErrorContext, TUint aReadMode) |
|
2085 { |
|
2086 return ReadLC(aLex, aEscapeChar, &aErrorContext, aReadMode); |
|
2087 } |
|
2088 |
|
2089 #define ReadLCLeaveIfErr(_command, _error, _errorFmtString...) do {if (_command) {CommandLeaveIfErr(*_command, _error, _errorFmtString);} else User::LeaveIfError(_error); } while(0) |
|
2090 |
|
2091 HBufC* Stringify::ReadLC(TLex& aLex, const TChar& aEscapeChar, CCommandBase* aErrorContext, TUint aReadMode) |
|
2092 { |
|
2093 CTextBuffer* buf = CTextBuffer::NewLC(20); |
|
2094 while (!aLex.Eos()) |
|
2095 { |
|
2096 TChar c = aLex.Get(); |
|
2097 if (c == aEscapeChar) |
|
2098 { |
|
2099 HandleEscapeL(aLex, *buf); |
|
2100 } |
|
2101 else if (c == '\'') |
|
2102 { |
|
2103 TBool foundClose = EFalse; |
|
2104 while (!aLex.Eos()) |
|
2105 { |
|
2106 c = aLex.Get(); |
|
2107 if ((c == aEscapeChar) && !aLex.Eos() && (aLex.Peek() == '\'')) |
|
2108 { |
|
2109 // Allow quoted single quote characters. Note, the is a departure from Bash behaviour, but is in line with Perl and is generally helpful. |
|
2110 buf->AppendL('\''); |
|
2111 aLex.Get(); |
|
2112 } |
|
2113 else if (c == '\'') |
|
2114 { |
|
2115 foundClose = ETrue; |
|
2116 break; |
|
2117 } |
|
2118 else |
|
2119 { |
|
2120 buf->AppendL(c); |
|
2121 } |
|
2122 } |
|
2123 if (!foundClose) |
|
2124 { |
|
2125 ReadLCLeaveIfErr(aErrorContext, KErrArgument, _L("Unmatched single quote")); |
|
2126 } |
|
2127 } |
|
2128 else if (c == '"') |
|
2129 { |
|
2130 TBool foundClose = EFalse; |
|
2131 while (!aLex.Eos()) |
|
2132 { |
|
2133 c = aLex.Get(); |
|
2134 if (c == aEscapeChar) |
|
2135 { |
|
2136 HandleEscapeL(aLex, *buf); |
|
2137 } |
|
2138 else if (c == '"') |
|
2139 { |
|
2140 foundClose = ETrue; |
|
2141 break; |
|
2142 } |
|
2143 else |
|
2144 { |
|
2145 buf->AppendL(c); |
|
2146 } |
|
2147 } |
|
2148 if (!foundClose) |
|
2149 { |
|
2150 ReadLCLeaveIfErr(aErrorContext, KErrArgument, _L("Unmatched double quote")); |
|
2151 } |
|
2152 } |
|
2153 else if (c.IsSpace() || ((c == ',') && (aReadMode & EBreakOnComma))) |
|
2154 { |
|
2155 aLex.UnGet(); |
|
2156 break; |
|
2157 } |
|
2158 else |
|
2159 { |
|
2160 buf->AppendL(c); |
|
2161 } |
|
2162 } |
|
2163 |
|
2164 HBufC* hbuf = buf->Descriptor().AllocL(); |
|
2165 CleanupStack::PopAndDestroy(buf); |
|
2166 CleanupStack::PushL(hbuf); |
|
2167 return hbuf; |
|
2168 } |
|
2169 |
|
2170 EXPORT_C HBufC* Stringify::WidenLC(const TDesC8& aDes) |
|
2171 { |
|
2172 HBufC* buf = HBufC::NewLC(aDes.Length()); |
|
2173 buf->Des().Copy(aDes); |
|
2174 return buf; |
|
2175 } |
|
2176 |
|
2177 EXPORT_C HBufC8* Stringify::NarrowLC(const TDesC& aDes) |
|
2178 { |
|
2179 HBufC8* buf = HBufC8::NewLC(aDes.Length()); |
|
2180 buf->Des().Copy(aDes); |
|
2181 return buf; |
|
2182 } |
|
2183 |
|
2184 EXPORT_C HBufC* Stringify::EscapeLC(const TDesC& aDes, const TChar& aEscapeChar) |
|
2185 { |
|
2186 const TInt origLength = aDes.Length(); |
|
2187 TInt newLength = origLength; |
|
2188 for (TInt i = 0; i < origLength; ++i) |
|
2189 { |
|
2190 if (!TChar(aDes[i]).IsPrint()) |
|
2191 { |
|
2192 // Hmmm, is this going to go horribly wrong with surrogate pairs? |
|
2193 newLength += 5; // 5 because <unprintable-char> -> '^unnnn' |
|
2194 } |
|
2195 } |
|
2196 HBufC* buf = HBufC::NewLC(newLength); |
|
2197 TPtr bufPtr(buf->Des()); |
|
2198 for (TInt i = 0; i < origLength; ++i) |
|
2199 { |
|
2200 if (TChar(aDes[i]).IsPrint()) |
|
2201 { |
|
2202 bufPtr.Append(aDes[i]); |
|
2203 } |
|
2204 else |
|
2205 { |
|
2206 bufPtr.Append(aEscapeChar); |
|
2207 bufPtr.Append('u'); |
|
2208 bufPtr.AppendNumFixedWidthUC(aDes[i], EHex, 4); |
|
2209 } |
|
2210 } |
|
2211 return buf; |
|
2212 } |
|
2213 |
|
2214 EXPORT_C HBufC8* Stringify::EscapeLC(const TDesC8& aDes, const TChar& aEscapeChar) |
|
2215 { |
|
2216 const TInt origLength = aDes.Length(); |
|
2217 TInt newLength = origLength; |
|
2218 for (TInt i = 0; i < origLength; ++i) |
|
2219 { |
|
2220 if (!TChar(aDes[i]).IsPrint()) |
|
2221 { |
|
2222 newLength += 3; // 3 because <unprintable-char> -> '^xnn' |
|
2223 } |
|
2224 } |
|
2225 HBufC8* buf = HBufC8::NewLC(newLength); |
|
2226 TPtr8 bufPtr(buf->Des()); |
|
2227 for (TInt i = 0; i < origLength; ++i) |
|
2228 { |
|
2229 if (TChar(aDes[i]).IsPrint()) |
|
2230 { |
|
2231 bufPtr.Append(aDes[i]); |
|
2232 } |
|
2233 else |
|
2234 { |
|
2235 bufPtr.Append(aEscapeChar); |
|
2236 bufPtr.Append('x'); |
|
2237 bufPtr.AppendNumFixedWidthUC(aDes[i], EHex, 2); |
|
2238 } |
|
2239 } |
|
2240 return buf; |
|
2241 } |
|
2242 |
|
2243 TRadix Radix(TLex& aLex) |
|
2244 { |
|
2245 _LIT(KBinPrefix, "0b"); |
|
2246 _LIT(KOctPrefix, "0."); |
|
2247 _LIT(KHexPrefix, "0x"); |
|
2248 |
|
2249 TRadix radix(EDecimal); |
|
2250 |
|
2251 if (aLex.Remainder().Length() > 2) |
|
2252 { |
|
2253 TLexMark mark; |
|
2254 aLex.Mark(mark); |
|
2255 aLex.Inc(2); |
|
2256 TPtrC prefix(aLex.MarkedToken(mark)); |
|
2257 if (prefix == KBinPrefix) |
|
2258 { |
|
2259 radix = EBinary; |
|
2260 } |
|
2261 else if (prefix == KOctPrefix) |
|
2262 { |
|
2263 radix = EOctal; |
|
2264 } |
|
2265 else if (prefix == KHexPrefix) |
|
2266 { |
|
2267 radix = EHex; |
|
2268 } |
|
2269 |
|
2270 if (radix == EDecimal) |
|
2271 { |
|
2272 aLex.UnGetToMark(mark); |
|
2273 } |
|
2274 } |
|
2275 |
|
2276 return radix; |
|
2277 } |
|
2278 |
|
2279 void CCommandBase::SetValueL(TLex& aLex, TValue& aValue) |
|
2280 { |
|
2281 TBool more((aValue.ValueType() & KValueTypeFlagMultiple) && !(aValue.ValueType() & KValueTypeFlagLast)); |
|
2282 if (aValue.IsSet() && !(aValue.ValueType() & KValueTypeFlagMultiple)) User::Leave(KErrArgument); // Can't set the same parameter repeatedly unless it has the multiple attribute |
|
2283 do |
|
2284 { |
|
2285 switch (aValue.ValueType() & KValueTypeFlagMask) |
|
2286 { |
|
2287 case KValueTypeBool: |
|
2288 { |
|
2289 aValue.SetValue(); |
|
2290 break; |
|
2291 } |
|
2292 case KValueTypeInt: |
|
2293 { |
|
2294 aLex.SkipSpace(); |
|
2295 TInt val; |
|
2296 if (aLex.Val(val) < 0) |
|
2297 { |
|
2298 User::Leave(KErrArgument); |
|
2299 } |
|
2300 aValue.SetValueL(val); |
|
2301 break; |
|
2302 } |
|
2303 case KValueTypeInt64: |
|
2304 { |
|
2305 aLex.SkipSpace(); |
|
2306 TInt64 val; |
|
2307 if (aLex.Val(val) < 0) |
|
2308 { |
|
2309 User::Leave(KErrArgument); |
|
2310 } |
|
2311 aValue.SetValueL(val); |
|
2312 break; |
|
2313 } |
|
2314 case KValueTypeUint: |
|
2315 { |
|
2316 aLex.SkipSpace(); |
|
2317 TUint val; |
|
2318 if (aLex.Val(val, Radix(aLex)) < 0) |
|
2319 { |
|
2320 User::Leave(KErrArgument); |
|
2321 } |
|
2322 aValue.SetValueL(val); |
|
2323 break; |
|
2324 } |
|
2325 case KValueTypeUint64: |
|
2326 { |
|
2327 aLex.SkipSpace(); |
|
2328 TInt64 val; // There's no implementation of TLex16::Val(TUint64&, TRadix), so we'll have to use the TInt64 version instead. |
|
2329 if (aLex.Val(val, Radix(aLex)) < 0) |
|
2330 { |
|
2331 User::Leave(KErrArgument); |
|
2332 } |
|
2333 aValue.SetValueL((TUint64)val); |
|
2334 break; |
|
2335 } |
|
2336 case KValueTypeReal: |
|
2337 { |
|
2338 aLex.SkipSpace(); |
|
2339 TReal64 val; |
|
2340 if (aLex.Val(val) < 0) |
|
2341 { |
|
2342 User::Leave(KErrArgument); |
|
2343 } |
|
2344 aValue.SetValueL(val); |
|
2345 break; |
|
2346 } |
|
2347 case KValueTypeString: |
|
2348 { |
|
2349 if (aValue.ValueType() & KValueTypeFlagLast) |
|
2350 { |
|
2351 TLexMark mark; |
|
2352 aLex.Mark(mark); |
|
2353 HBufC* string = ReadStringLC(aLex, 0); |
|
2354 if ((aLex.Remainder().Length() == 0) || (aLex.Remainder() == KNewLine)) |
|
2355 { |
|
2356 // ReadStringLC consumed the whole of the remainder of the command line. This means the |
|
2357 // user must have either provided a just single word, or explicitly quoted / escaped the whitespace |
|
2358 // between multiple words. |
|
2359 // Either way, we've got a single argument to satisfy 'last' so we'll use what ReadStringLC |
|
2360 // returned. |
|
2361 aValue.SetValueL(string); |
|
2362 CleanupStack::Pop(string); |
|
2363 } |
|
2364 else |
|
2365 { |
|
2366 // ReadStringLC didn't consume the remainder of the command line. This means the user must have |
|
2367 // provided multiple words, but didn't quote or escape the whitespace. In this case take the |
|
2368 // string they provided unaltered (which is equivalent to adding quotes around the whole string |
|
2369 // and passing it back through ReadStringLC). |
|
2370 CleanupStack::PopAndDestroy(string); |
|
2371 aLex.UnGetToMark(mark); |
|
2372 aValue.SetValueL(aLex.Remainder().AllocLC()); |
|
2373 CleanupStack::Pop(); |
|
2374 aLex.Inc(aLex.Remainder().Length()); |
|
2375 } |
|
2376 } |
|
2377 else |
|
2378 { |
|
2379 HBufC* string = ReadStringLC(aLex, (aValue.ValueType() & KValueTypeFlagLast) ? 0 : EDisallowLeadingHyphen); |
|
2380 aValue.SetValueL(string); |
|
2381 CleanupStack::Pop(string); |
|
2382 } |
|
2383 break; |
|
2384 } |
|
2385 case KValueTypeFileName: |
|
2386 { |
|
2387 HBufC* string = ReadStringLC(aLex, EDisallowLeadingHyphen); |
|
2388 TFileName2 fileName(*string); |
|
2389 CleanupStack::PopAndDestroy(string); |
|
2390 if (fileName.Length() == 0) |
|
2391 { |
|
2392 User::Leave(KErrArgument); |
|
2393 } |
|
2394 fileName.MakeAbsoluteL(iEnv->Pwd()); |
|
2395 aValue.SetValueL(fileName, FsL()); |
|
2396 break; |
|
2397 } |
|
2398 case KValueTypeEnum: |
|
2399 { |
|
2400 HBufC* string = ReadStringLC(aLex, EDisallowLeadingHyphen); |
|
2401 aValue.SetValueL(string); |
|
2402 CleanupStack::PopAndDestroy(string); |
|
2403 break; |
|
2404 } |
|
2405 default: |
|
2406 { |
|
2407 __ASSERT_ALWAYS(EFalse, Panic(EInvalidCommandOptionType)); |
|
2408 break; |
|
2409 } |
|
2410 } |
|
2411 |
|
2412 if (more) |
|
2413 { |
|
2414 TLexMark mark; |
|
2415 aLex.Mark(mark); |
|
2416 aLex.SkipSpace(); |
|
2417 if (aLex.Peek() == ',') |
|
2418 { |
|
2419 aLex.Get(); |
|
2420 aLex.SkipSpace(); |
|
2421 // Loop again to process the next value in the set. |
|
2422 } |
|
2423 else |
|
2424 { |
|
2425 aLex.UnGetToMark(mark); |
|
2426 more = EFalse; |
|
2427 } |
|
2428 } |
|
2429 } |
|
2430 while (more); |
|
2431 } |
|
2432 |
|
2433 void CCommandBase::SetValueFromEnvL(TValue& aValue) |
|
2434 { |
|
2435 if (!aValue.IsSet() && (aValue.EnvVar().Length() > 0) && iEnv->IsDefined(aValue.EnvVar())) |
|
2436 { |
|
2437 TUint type = aValue.ValueType() & KValueTypeFlagMask; |
|
2438 if ((type == KValueTypeString) || (type == KValueTypeEnum)) |
|
2439 { |
|
2440 HBufC* value = iEnv->GetAsDesL(aValue.EnvVar()).AllocLC(); |
|
2441 aValue.SetValueL(value); |
|
2442 CleanupStack::Pop(value); |
|
2443 } |
|
2444 else if (type == KValueTypeFileName) |
|
2445 { |
|
2446 TFileName2 fileName(iEnv->GetAsDesL(aValue.EnvVar())); |
|
2447 fileName.MakeAbsoluteL(iEnv->Pwd()); |
|
2448 aValue.SetValueL(fileName, FsL()); |
|
2449 } |
|
2450 else |
|
2451 { |
|
2452 TLex lex(iEnv->GetAsDesL(aValue.EnvVar())); |
|
2453 SetValueL(lex, aValue); |
|
2454 } |
|
2455 } |
|
2456 } |
|
2457 |
|
2458 |
|
2459 |
|
2460 template <class T> TBool ValueTypesConsistent(const T& aList) |
|
2461 { |
|
2462 // class T is expected to be either RCommandArgumentList or RCommandOptionList. |
|
2463 // Returns true if either all the list values have an uninitialized value type, or all have an initialized value type. |
|
2464 // Returns false if there is a mixture of unitialized and uninitialized value types. |
|
2465 |
|
2466 TBool unitialized(EFalse); |
|
2467 const TInt count = aList.Count(); |
|
2468 if (count > 0) |
|
2469 { |
|
2470 for (TInt i = 0; i < count; ++i) |
|
2471 { |
|
2472 if (i == 0) |
|
2473 { |
|
2474 unitialized = (aList[i].ValueType() == KValueTypeUninitialized); |
|
2475 } |
|
2476 else if (!unitialized != !(aList[i].ValueType() == KValueTypeUninitialized)) |
|
2477 { |
|
2478 return EFalse; |
|
2479 } |
|
2480 } |
|
2481 } |
|
2482 return ETrue; |
|
2483 } |
|
2484 |
|
2485 template <class T> TBool ValueTypesInitialized(const T& aList) |
|
2486 { |
|
2487 return !(aList[0].ValueType() == KValueTypeUninitialized); |
|
2488 } |
|
2489 |
|
2490 |
|
2491 TBool ValueTypesInitializedL(const RCommandArgumentList& aArguments, const RCommandOptionList& aOptions) |
|
2492 { |
|
2493 if (!ValueTypesConsistent(aArguments)) |
|
2494 { |
|
2495 StaticLeaveIfErr(KErrArgument, _L("Arguments inconsistently or incompletely initialized.")); |
|
2496 } |
|
2497 if (!ValueTypesConsistent(aOptions)) |
|
2498 { |
|
2499 StaticLeaveIfErr(KErrArgument, _L("Options inconsistently or incompletely initialized.")); |
|
2500 } |
|
2501 if (aArguments.Count() && aOptions.Count()) |
|
2502 { |
|
2503 TBool argumentsInitialized(ValueTypesInitialized(aArguments)); |
|
2504 TBool optionsInitialized(ValueTypesInitialized(aOptions)); |
|
2505 if (!argumentsInitialized != !optionsInitialized) |
|
2506 { |
|
2507 StaticLeaveIfErr(KErrArgument, _L("Arguments and options inconsistently or incompletely initialized.")); |
|
2508 } |
|
2509 } |
|
2510 if (aArguments.Count()) |
|
2511 { |
|
2512 return ValueTypesInitialized(aArguments); |
|
2513 } |
|
2514 else if (aOptions.Count()) |
|
2515 { |
|
2516 return ValueTypesInitialized(aOptions); |
|
2517 } |
|
2518 else |
|
2519 { |
|
2520 return ETrue; |
|
2521 } |
|
2522 } |
|
2523 |
|
2524 EXPORT_C TInt CCommandBase::ParseCommandLine(const TDesC& aCommandLine) |
|
2525 { |
|
2526 TRAPD(err, DoParseCommandLineL(aCommandLine)); |
|
2527 return err; |
|
2528 } |
|
2529 |
|
2530 void CCommandBase::DoParseCommandLineL(const TDesC& aCommandLine) |
|
2531 { |
|
2532 // Read the CIF if required. |
|
2533 if (CifReadRequired()) |
|
2534 { |
|
2535 ReadCifL(); |
|
2536 } |
|
2537 |
|
2538 // Add command specific arguments and options. |
|
2539 ArgumentsL(iArguments); |
|
2540 OptionsL(iOptions); |
|
2541 |
|
2542 if (iCif) |
|
2543 { |
|
2544 TRAPD(err, iCif->AssignL(iArguments, iOptions)); |
|
2545 if (err) |
|
2546 { |
|
2547 iFlags |= ECifReadFailed; |
|
2548 User::Leave(err); |
|
2549 } |
|
2550 __ASSERT_ALWAYS(ValueTypesInitializedL(iArguments, iOptions), Panic(EIncompleteArgumentOrOptionInitialization)); |
|
2551 } |
|
2552 |
|
2553 // Add global options. |
|
2554 iOptions.AppendBoolL(iDisplayHelp, TChar('h'), KHelpName, KHelpDescription); |
|
2555 iOptions.AppendStringL(iConsoleImplementation, TChar(0), KOptConsole, KNullDesC); |
|
2556 iOptions.AppendStringL(iConsoleTitle, TChar(0), KOptConsoleTitle, KNullDesC); |
|
2557 iOptions.AppendUintL(iConsoleSize, TChar(0), KOptConsoleSize, KNullDesC); |
|
2558 iOptions.AppendStringL(iPersistentConsoleName, TChar(0), KOptPersistentConsole, KNullDesC); |
|
2559 |
|
2560 // Parse the command line. |
|
2561 ParseCommandLineL(aCommandLine); |
|
2562 |
|
2563 // Set optional arguments that haven't been set explicitly from environment variables if applicable. |
|
2564 const TInt numArgs = iArguments.Count(); |
|
2565 for (TInt i = 0; i < numArgs; ++i) |
|
2566 { |
|
2567 SetValueFromEnvL(iArguments[i]); |
|
2568 } |
|
2569 |
|
2570 // Set options that haven't been set explicitly from environment variables if applicable. |
|
2571 const TInt numOpts = iOptions.Count(); |
|
2572 for (TInt i = 0; i < numOpts; ++i) |
|
2573 { |
|
2574 SetValueFromEnvL(iOptions[i]); |
|
2575 } |
|
2576 |
|
2577 if (!iArguments.AllSet()) |
|
2578 { |
|
2579 User::Leave(KErrArgument); |
|
2580 } |
|
2581 } |
|
2582 |
|
2583 TBool CCommandBase::CifReadRequired() const |
|
2584 { |
|
2585 if (iCif) |
|
2586 { |
|
2587 return EFalse; |
|
2588 } |
|
2589 |
|
2590 // Call the virtual Description function to see if the sub-class has implemented it. |
|
2591 // If not, it is assumed that it expects a CIF file to be read. |
|
2592 Description(); |
|
2593 return (iFlags & EReadCif); |
|
2594 } |
|
2595 |
|
2596 void CCommandBase::ReadCifL() |
|
2597 { |
|
2598 TRAPD(err, DoReadCifL()); |
|
2599 if (err) |
|
2600 { |
|
2601 iFlags |= ECifReadFailed; |
|
2602 } |
|
2603 } |
|
2604 |
|
2605 void CCommandBase::DoReadCifL() |
|
2606 { |
|
2607 iCif = CCommandInfoFile::NewL(FsL(), Env(), Name()); |
|
2608 iFlags |= EOwnsCif; |
|
2609 } |
|
2610 |
|
2611 EXPORT_C TBool CCommandBase::UsingCif() const |
|
2612 { |
|
2613 if (iCif) |
|
2614 { |
|
2615 return ETrue; |
|
2616 } |
|
2617 return (CifReadRequired()); |
|
2618 } |
|
2619 |
|
2620 EXPORT_C void CCommandBase::ParseCommandLineL(const TDesC& aCommandLine) |
|
2621 { |
|
2622 TInt argumentIndex = 0; |
|
2623 TLex lex(aCommandLine); |
|
2624 lex.SkipSpace(); |
|
2625 TBool lastArgSeen(EFalse); |
|
2626 while (!lex.Eos()) |
|
2627 { |
|
2628 TBool isOption = EFalse; |
|
2629 if (!lastArgSeen && (lex.Peek() == TChar('-'))) |
|
2630 { // Start of an option. |
|
2631 isOption = ETrue; |
|
2632 lex.Get(); |
|
2633 TChar peek = lex.Peek(); |
|
2634 if (peek == TChar('-')) |
|
2635 { // Start of a long named option. |
|
2636 lex.Get(); |
|
2637 lex.Mark(); |
|
2638 lex.SkipCharacters(); |
|
2639 TInt optionIndex = iOptions.Find(lex.MarkedToken()); |
|
2640 if (optionIndex < 0) |
|
2641 { |
|
2642 User::Leave(KErrArgument); |
|
2643 } |
|
2644 SetValueL(lex, iOptions[optionIndex]); |
|
2645 } |
|
2646 else if (peek.IsDigit()) |
|
2647 { |
|
2648 // It could be a negative integer argument, providing there aren't any numeric short options. |
|
2649 // If there are, they take precedence, so don't use a digit as a short option unless you don't care about negative arguments |
|
2650 TInt optionIndex = iOptions.FindShort(peek); |
|
2651 if (optionIndex < 0) |
|
2652 { |
|
2653 isOption = EFalse; // get to the argument clause below |
|
2654 lex.UnGet(); // So the minus sign is picked up |
|
2655 } |
|
2656 } |
|
2657 |
|
2658 if (isOption) |
|
2659 { // Start of a short option (or block of short options). |
|
2660 while (!lex.Eos() && !lex.Peek().IsSpace() && (lex.Peek() != TChar('-'))) |
|
2661 { |
|
2662 TInt optionIndex = iOptions.FindShort(lex.Get()); |
|
2663 if (optionIndex < 0) |
|
2664 { |
|
2665 User::Leave(KErrArgument); |
|
2666 } |
|
2667 SetValueL(lex, iOptions[optionIndex]); |
|
2668 } |
|
2669 } |
|
2670 } |
|
2671 |
|
2672 if (!isOption) |
|
2673 { // Start of an argument. |
|
2674 if (argumentIndex < iArguments.Count()) |
|
2675 { |
|
2676 TCommandArgument& argument = iArguments[argumentIndex]; |
|
2677 SetValueL(lex, argument); |
|
2678 if (!(argument.ValueType() & KValueTypeFlagMultiple)) |
|
2679 { |
|
2680 ++argumentIndex; |
|
2681 } |
|
2682 lastArgSeen = (argument.ValueType() & KValueTypeFlagLast); |
|
2683 // Look ahead to see if the next argument is the last, and if so set lastArgSeen early. This allows the next argument to be an option, but be treated as part of the 'last' string not an option for this command. |
|
2684 if (!lastArgSeen && (argumentIndex < iArguments.Count())) |
|
2685 { |
|
2686 lastArgSeen = (iArguments[argumentIndex].ValueType() & KValueTypeFlagLast); |
|
2687 } |
|
2688 } |
|
2689 else |
|
2690 { |
|
2691 User::Leave(KErrArgument); |
|
2692 } |
|
2693 } |
|
2694 |
|
2695 lex.SkipSpace(); |
|
2696 } |
|
2697 } |
|
2698 |
|
2699 const TDesC* CCommandBase::ReadCommandLineLC() |
|
2700 { |
|
2701 #ifdef EKA2 |
|
2702 HBufC* commandLine = HBufC::NewLC(User::CommandLineLength()); |
|
2703 TPtr commandLinePtr(commandLine->Des()); |
|
2704 User::CommandLine(commandLinePtr); |
|
2705 #else |
|
2706 RProcess process; |
|
2707 HBufC* commandLine = HBufC::NewLC(process.CommandLineLength()); |
|
2708 TPtr commandLinePtr(commandLine->Des()); |
|
2709 process.CommandLine(commandLinePtr); |
|
2710 #endif |
|
2711 return commandLine; |
|
2712 } |
|
2713 |
|
2714 void AppendHeadingL(const TDesC& aHeading, CTextBuffer& aBuffer) |
|
2715 { |
|
2716 _LIT(KFormat, "\r\n=head1 %S\r\n\r\n"); |
|
2717 aBuffer.AppendFormatL(KFormat, &aHeading); |
|
2718 } |
|
2719 |
|
2720 void AppendSubCommandL(TInt aIndent, CTextBuffer& aBuffer, const CCommandInfoFile& aCif) |
|
2721 { |
|
2722 aBuffer.AppendSpacesL(aIndent); |
|
2723 aBuffer.AppendL(aCif.Name()); |
|
2724 aBuffer.AppendL(KNewLine); |
|
2725 |
|
2726 TInt numSubCommands = aCif.NumSubCommands(); |
|
2727 for (TInt i = 0; i < numSubCommands; ++i) |
|
2728 { |
|
2729 AppendSubCommandL(aIndent + 2, aBuffer, aCif.SubCommand(i)); |
|
2730 } |
|
2731 } |
|
2732 |
|
2733 EXPORT_C const CTextBuffer* CCommandBase::GetHelpTextL() |
|
2734 { |
|
2735 CTextBuffer* buffer = CTextBuffer::NewLC(0x100); |
|
2736 |
|
2737 AppendHeadingL(_L("SYNTAX"), *buffer); |
|
2738 buffer->AppendFormatL(_L(" %S"), &Name()); |
|
2739 |
|
2740 const TInt numOptions = iOptions.Count(); |
|
2741 if (numOptions > 0) |
|
2742 { |
|
2743 buffer->AppendL(_L(" [options]")); |
|
2744 } |
|
2745 |
|
2746 const TInt numArguments = iArguments.Count(); |
|
2747 if (numArguments > 0) |
|
2748 { |
|
2749 for (TInt i = 0; i < numArguments; ++i) |
|
2750 { |
|
2751 const TCommandArgument& thisArgument = iArguments[i]; |
|
2752 TBool isOptional = thisArgument.IsOptional(); |
|
2753 if (isOptional) |
|
2754 { |
|
2755 buffer->AppendL(_L(" [<")); |
|
2756 } |
|
2757 else |
|
2758 { |
|
2759 buffer->AppendL(_L(" <")); |
|
2760 } |
|
2761 buffer->AppendL(thisArgument.Name()); |
|
2762 if (isOptional) |
|
2763 { |
|
2764 buffer->AppendL(_L(">]")); |
|
2765 } |
|
2766 else |
|
2767 { |
|
2768 buffer->AppendL(_L(">")); |
|
2769 } |
|
2770 |
|
2771 if (thisArgument.AcceptsMultiple()) |
|
2772 { |
|
2773 buffer->AppendL(_L(" ...")); |
|
2774 } |
|
2775 } |
|
2776 } |
|
2777 buffer->AppendL(_L("\r\n")); |
|
2778 |
|
2779 if (numOptions > 0) |
|
2780 { |
|
2781 AppendHeadingL(_L("OPTIONS"), *buffer); |
|
2782 buffer->AppendL(_L("=over 5\r\n\r\n")); |
|
2783 for (TInt i = 0; i < numOptions; ++i) |
|
2784 { |
|
2785 const TCommandOption& thisOption = iOptions[i]; |
|
2786 TChar shortName(thisOption.ShortName()); |
|
2787 if (shortName) |
|
2788 { |
|
2789 buffer->AppendFormatL(_L("=item -%c (--%S)"), (TUint)shortName, &thisOption.Name()); |
|
2790 switch (thisOption.ValueType() & KValueTypeFlagMask) |
|
2791 { |
|
2792 case KValueTypeBool: |
|
2793 { |
|
2794 // Do nothing. |
|
2795 break; |
|
2796 } |
|
2797 case KValueTypeInt: |
|
2798 { |
|
2799 buffer->AppendL(_L(" <int>")); |
|
2800 break; |
|
2801 } |
|
2802 case KValueTypeInt64: |
|
2803 { |
|
2804 buffer->AppendL(_L(" <int64>")); |
|
2805 break; |
|
2806 } |
|
2807 case KValueTypeUint: |
|
2808 { |
|
2809 buffer->AppendL(_L(" <uint>")); |
|
2810 break; |
|
2811 } |
|
2812 case KValueTypeUint64: |
|
2813 { |
|
2814 buffer->AppendL(_L(" <uint64>")); |
|
2815 break; |
|
2816 } |
|
2817 case KValueTypeString: |
|
2818 { |
|
2819 buffer->AppendL(_L(" <string>")); |
|
2820 break; |
|
2821 } |
|
2822 case KValueTypeFileName: |
|
2823 { |
|
2824 buffer->AppendL(_L(" <filename>")); |
|
2825 break; |
|
2826 } |
|
2827 case KValueTypeEnum: |
|
2828 { |
|
2829 buffer->AppendL(_L(" <enum>")); |
|
2830 break; |
|
2831 } |
|
2832 case KValueTypeReal: |
|
2833 { |
|
2834 buffer->AppendL(_L(" <real>")); |
|
2835 break; |
|
2836 } |
|
2837 default: |
|
2838 { |
|
2839 __ASSERT_ALWAYS(EFalse, Panic(EInvalidCommandOptionType)); |
|
2840 break; |
|
2841 } |
|
2842 } |
|
2843 buffer->AppendFormatL(_L("\r\n\r\n%S"), &thisOption.Description()); |
|
2844 if ((thisOption.ValueType() & KValueTypeFlagMask) == KValueTypeEnum) |
|
2845 { |
|
2846 if (thisOption.EnumDescriptionList().Length() > 0) |
|
2847 { |
|
2848 FormatEnumL(thisOption, *buffer); |
|
2849 } |
|
2850 else |
|
2851 { |
|
2852 buffer->AppendL(_L(" [")); |
|
2853 thisOption.AppendEnumValuesL(*buffer); |
|
2854 buffer->AppendL(']'); |
|
2855 } |
|
2856 } |
|
2857 if (thisOption.ValueType() & KValueTypeFlagMultiple) |
|
2858 { |
|
2859 buffer->AppendL(_L(" Can be specified more than once.")); |
|
2860 } |
|
2861 if (thisOption.EnvVar().Length() > 0) |
|
2862 { |
|
2863 const TDesC& envVar = thisOption.EnvVar(); |
|
2864 buffer->AppendFormatL(_L(" Can also be specified by defining the environment variable \"%S\"."), &envVar); |
|
2865 } |
|
2866 buffer->AppendL(_L("\r\n\r\n")); |
|
2867 } |
|
2868 } |
|
2869 buffer->AppendL(_L("=back\r\n")); |
|
2870 } |
|
2871 |
|
2872 if (numArguments > 0) |
|
2873 { |
|
2874 AppendHeadingL(_L("ARGUMENTS"), *buffer); |
|
2875 buffer->AppendL(_L("=over 5\r\n\r\n")); |
|
2876 for (TInt i = 0; i < numArguments; ++i) |
|
2877 { |
|
2878 buffer->AppendL(_L("=item ")); |
|
2879 const TCommandArgument& thisArgument = iArguments[i]; |
|
2880 TBool isOptional = thisArgument.IsOptional(); |
|
2881 if (isOptional) |
|
2882 { |
|
2883 buffer->AppendL(_L("[<")); |
|
2884 } |
|
2885 else |
|
2886 { |
|
2887 buffer->AppendL(_L("<")); |
|
2888 } |
|
2889 buffer->AppendL(thisArgument.Name()); |
|
2890 if (isOptional) |
|
2891 { |
|
2892 buffer->AppendL(_L(">]\r\n\r\n")); |
|
2893 } |
|
2894 else |
|
2895 { |
|
2896 buffer->AppendL(_L(">\r\n\r\n")); |
|
2897 } |
|
2898 |
|
2899 buffer->AppendL(thisArgument.Description()); |
|
2900 |
|
2901 if (thisArgument.ValueType() & KValueTypeFlagMultiple) |
|
2902 { |
|
2903 buffer->AppendL(_L(" Can be specified more than once.")); |
|
2904 } |
|
2905 |
|
2906 if (thisArgument.EnvVar().Length() > 0) |
|
2907 { |
|
2908 const TDesC& envVar = thisArgument.EnvVar(); |
|
2909 buffer->AppendFormatL(_L(" Can also be specified by defining the environment variable \"%S\"."), &envVar); |
|
2910 } |
|
2911 |
|
2912 if (thisArgument.IsLast()) |
|
2913 { |
|
2914 buffer->AppendFormatL(_L(" Any further arguments or options will be coalesced into this one.")); |
|
2915 } |
|
2916 |
|
2917 TBool noClosingSquareBracket(EFalse); |
|
2918 |
|
2919 switch (thisArgument.ValueType() & KValueTypeFlagMask) |
|
2920 { |
|
2921 case KValueTypeInt: |
|
2922 { |
|
2923 buffer->AppendL(_L(" [int")); |
|
2924 break; |
|
2925 } |
|
2926 case KValueTypeInt64: |
|
2927 { |
|
2928 buffer->AppendL(_L(" [int64")); |
|
2929 break; |
|
2930 } |
|
2931 case KValueTypeUint: |
|
2932 { |
|
2933 buffer->AppendL(_L(" [uint")); |
|
2934 break; |
|
2935 } |
|
2936 case KValueTypeUint64: |
|
2937 { |
|
2938 buffer->AppendL(_L(" [uint64")); |
|
2939 break; |
|
2940 } |
|
2941 case KValueTypeString: |
|
2942 { |
|
2943 buffer->AppendL(_L(" [string")); |
|
2944 break; |
|
2945 } |
|
2946 case KValueTypeFileName: |
|
2947 { |
|
2948 buffer->AppendL(_L(" [filename")); |
|
2949 break; |
|
2950 } |
|
2951 case KValueTypeEnum: |
|
2952 { |
|
2953 if (thisArgument.EnumDescriptionList().Length() > 0) |
|
2954 { |
|
2955 FormatEnumL(thisArgument, *buffer); |
|
2956 noClosingSquareBracket = ETrue; |
|
2957 } |
|
2958 else |
|
2959 { |
|
2960 buffer->AppendL(_L(" [")); |
|
2961 thisArgument.AppendEnumValuesL(*buffer); |
|
2962 } |
|
2963 break; |
|
2964 } |
|
2965 case KValueTypeReal: |
|
2966 { |
|
2967 buffer->AppendL(_L(" [real")); |
|
2968 break; |
|
2969 } |
|
2970 default: |
|
2971 { |
|
2972 __ASSERT_ALWAYS(EFalse, Panic(EInvalidCommandArgumentType)); |
|
2973 break; |
|
2974 } |
|
2975 } |
|
2976 |
|
2977 if (!noClosingSquareBracket) |
|
2978 { |
|
2979 if (thisArgument.ValueType() & KValueTypeFlagMultiple) |
|
2980 { |
|
2981 buffer->AppendL(_L("(s)]\r\n\r\n")); |
|
2982 } |
|
2983 else |
|
2984 { |
|
2985 buffer->AppendL(_L("]\r\n\r\n")); |
|
2986 } |
|
2987 } |
|
2988 } |
|
2989 buffer->AppendL(_L("=back\r\n")); |
|
2990 } |
|
2991 |
|
2992 AppendHeadingL(_L("DESCRIPTION"), *buffer); |
|
2993 buffer->AppendL(Description()); |
|
2994 buffer->AppendL(_L("\r\n\r\n")); |
|
2995 if (iCif && iCif->LongDescription().Length()) |
|
2996 { |
|
2997 buffer->AppendL(iCif->LongDescription()); |
|
2998 buffer->AppendL(_L("\r\n\r\n")); |
|
2999 } |
|
3000 |
|
3001 if (iCif && iCif->SeeAlso().Length()) |
|
3002 { |
|
3003 AppendHeadingL(_L("SEE ALSO"), *buffer); |
|
3004 buffer->AppendL(iCif->SeeAlso()); |
|
3005 buffer->AppendL(_L("\r\n\r\n")); |
|
3006 } |
|
3007 |
|
3008 if (iCif && (iCif->NumSubCommands() > 0)) |
|
3009 { |
|
3010 AppendHeadingL(_L("SUB-COMMANDS"), *buffer); |
|
3011 TInt numSubCommands = iCif->NumSubCommands(); |
|
3012 for (TInt i = 0; i < numSubCommands; ++i) |
|
3013 { |
|
3014 AppendSubCommandL(2, *buffer, iCif->SubCommand(i)); |
|
3015 } |
|
3016 } |
|
3017 |
|
3018 if (iCif && iCif->Copyright().Length()) |
|
3019 { |
|
3020 AppendHeadingL(_L("COPYRIGHT"), *buffer); |
|
3021 buffer->AppendL(iCif->Copyright()); |
|
3022 buffer->AppendL(_L("\r\n\r\n")); |
|
3023 } |
|
3024 |
|
3025 CTextFormatter* textFormatter = CTextFormatter::NewLC(Stdout()); |
|
3026 textFormatter->AppendPodL(buffer->Descriptor()); |
|
3027 CleanupStack::Pop(textFormatter); |
|
3028 CleanupStack::PopAndDestroy(buffer); |
|
3029 return textFormatter; |
|
3030 } |
|
3031 |
|
3032 void CCommandBase::DisplayHelpAndComplete() |
|
3033 { |
|
3034 const CTextBuffer* helpText = NULL; |
|
3035 TRAPD(err, helpText = GetHelpTextL()); |
|
3036 if (err) |
|
3037 { |
|
3038 Complete(err, _L("Error displaying help")); |
|
3039 } |
|
3040 else |
|
3041 { |
|
3042 CleanupStack::PushL(const_cast<CTextBuffer*>(helpText)); |
|
3043 CheckNewLine(); |
|
3044 PageL(*helpText); |
|
3045 Complete(); |
|
3046 CleanupStack::PopAndDestroy(const_cast<CTextBuffer*>(helpText)); |
|
3047 } |
|
3048 } |
|
3049 |
|
3050 void CCommandBase::DisplayHelpAndComplete(TInt aError, const TDesC& aText) |
|
3051 { |
|
3052 CheckNewLine(); |
|
3053 PrintError(aError, aText); |
|
3054 const CTextBuffer* helpText = NULL; |
|
3055 TRAPD(err, helpText = GetHelpTextL()); |
|
3056 if (err == KErrNone) |
|
3057 { |
|
3058 CleanupStack::PushL(const_cast<CTextBuffer*>(helpText)); |
|
3059 PageL(*helpText); |
|
3060 CleanupStack::PopAndDestroy(const_cast<CTextBuffer*>(helpText)); |
|
3061 } |
|
3062 Complete(aError); |
|
3063 } |
|
3064 |
|
3065 void CCommandBase::FormatErrorText(TDes& aDes, TInt aError, TRefByValue<const TDesC> aFmt, VA_LIST& aList) const |
|
3066 { |
|
3067 TOverflowTruncate overflow; |
|
3068 aDes = _L("Error: "); |
|
3069 aDes.AppendFormatList(aFmt, aList, &overflow); |
|
3070 aDes.AppendFormat(_L(" : %S (%d)\r\n"), &overflow, Stringify::Error(aError), aError); |
|
3071 } |
|
3072 |
|
3073 void CCommandBase::FormatWarningText(TDes& aDes, TRefByValue<const TDesC> aFmt, VA_LIST& aList) const |
|
3074 { |
|
3075 TOverflowTruncate overflow; |
|
3076 aDes = _L("Warning: "); |
|
3077 aDes.AppendFormatList(aFmt, aList, &overflow); |
|
3078 if ((aDes.Length() < KNewLine().Length()) || ((aDes.Right(KNewLine().Length()) != KNewLine))) |
|
3079 { |
|
3080 aDes.AppendFormat(KNewLine, &overflow); |
|
3081 } |
|
3082 } |
|
3083 |
|
3084 void CCommandBase::CheckNewLine() |
|
3085 { |
|
3086 if (iStderr.AttachedToConsole()) |
|
3087 { |
|
3088 TPoint cursorPos(0, 0); |
|
3089 iStderr.GetCursorPos(cursorPos); |
|
3090 if (cursorPos.iX != 0) |
|
3091 { |
|
3092 iStderr.Write(_L("\r\n")); |
|
3093 } |
|
3094 } |
|
3095 } |
|
3096 |
|
3097 void CCommandBase::FormatEnumL(const TValue& aValue, CTextBuffer& aBuffer) const |
|
3098 { |
|
3099 aBuffer.AppendL(_L(" Supported values are:\r\n\r\n=over 5\r\n\r\n")); |
|
3100 TLex descLex(aValue.EnumDescriptionList()); |
|
3101 TLex valLex(aValue.EnumValueList()); |
|
3102 while (!valLex.Eos()) |
|
3103 { |
|
3104 HBufC* value = ReadStringLC(valLex, EBreakOnComma); |
|
3105 __ASSERT_ALWAYS(!descLex.Eos(), IoUtils::Panic(EEnumDescriptionMissing)); |
|
3106 HBufC* description = ReadStringLC(descLex, EBreakOnComma); |
|
3107 aBuffer.AppendFormatL(_L("=item %S\r\n\r\n%S\r\n\r\n"), value, description); |
|
3108 CleanupStack::PopAndDestroy(2, value); |
|
3109 } |
|
3110 aBuffer.AppendL(_L("=back\r\n\r\n")); |
|
3111 } |
|
3112 |
|
3113 EXPORT_C void CCommandBase::CreateEnvironmentL(CEnvironment* aEnv) |
|
3114 { |
|
3115 if (aEnv) |
|
3116 { |
|
3117 iEnv = aEnv; |
|
3118 } |
|
3119 else |
|
3120 { |
|
3121 iEnv = CEnvironment::NewL(); |
|
3122 iFlags |= EOwnsEnv; |
|
3123 #ifdef EKA2 |
|
3124 const TInt length = User::ParameterLength(KEnvironmentProcessSlot); |
|
3125 if (length > 0) |
|
3126 { |
|
3127 HBufC8* buf = HBufC8::NewLC(length); |
|
3128 TPtr8 bufPtr(buf->Des()); |
|
3129 User::LeaveIfError(User::GetDesParameter(KEnvironmentProcessSlot, bufPtr)); |
|
3130 iEnv->InternalizeL(bufPtr); |
|
3131 CleanupStack::PopAndDestroy(buf); |
|
3132 } |
|
3133 #endif |
|
3134 } |
|
3135 } |
|
3136 |
|
3137 EXPORT_C void CCommandBase::RunL() |
|
3138 { |
|
3139 if (iFlags & ECompleteOnRunL) |
|
3140 { |
|
3141 Complete(iStatus.Int()); |
|
3142 } |
|
3143 else |
|
3144 { |
|
3145 // if a derived class ever makes this Active Object active, it must also override this unless ECompleteOnRunL is specified. |
|
3146 Panic(EActiveObjectRunLNotOverridden); |
|
3147 } |
|
3148 } |
|
3149 |
|
3150 EXPORT_C void CCommandBase::DoCancel() |
|
3151 { |
|
3152 // if a derived class ever makes this Active Object active, it must also override this. |
|
3153 Panic(EActiveObjectRunLNotOverridden); |
|
3154 } |
|
3155 |
|
3156 EXPORT_C TInt CCommandBase::RunError(TInt aError) |
|
3157 { |
|
3158 HandleLeave(aError); |
|
3159 return KErrNone; |
|
3160 } |
|
3161 |
|
3162 EXPORT_C CConsoleBase* CCommandBase::GetConsoleBaseL() |
|
3163 { |
|
3164 CIoConsole* console = new(ELeave) CIoConsole(Stdin(), Stdout()); |
|
3165 return console; |
|
3166 } |
|
3167 |
|
3168 EXPORT_C CColorConsoleBase* CCommandBase::GetColorConsoleBaseL() |
|
3169 { |
|
3170 // CIoConsole now derives from CColorConsoleBase so implementation is the same as GetConsoleBaseL |
|
3171 CIoConsole* console = new(ELeave) CIoConsole(Stdin(), Stdout()); |
|
3172 return console; |
|
3173 } |
|
3174 |
|
3175 EXPORT_C CCommandBase& CCommandBase::Static() |
|
3176 { |
|
3177 CCommandBase* self = static_cast<CCommandBase*>(Dll::Tls()); |
|
3178 __ASSERT_ALWAYS(self, Panic(ENoStaticCommand)); |
|
3179 return *self; |
|
3180 } |
|
3181 |
|
3182 EXPORT_C TBool CCommandBase::HaveStatic() |
|
3183 { |
|
3184 CCommandBase* self = static_cast<CCommandBase*>(Dll::Tls()); |
|
3185 return (self != NULL); |
|
3186 } |
|
3187 |
|
3188 EXPORT_C void CCommandBase::StdinChange(TUint /*aChange*/) |
|
3189 { |
|
3190 } |
|
3191 |
|
3192 EXPORT_C void CCommandBase::DisplayHelp() |
|
3193 { |
|
3194 const CTextBuffer* helpText = NULL; |
|
3195 TRAPD(err, helpText = GetHelpTextL()); |
|
3196 if (err) |
|
3197 { |
|
3198 PrintError(err, _L("Error displaying help")); |
|
3199 } |
|
3200 else |
|
3201 { |
|
3202 CleanupStack::PushL(const_cast<CTextBuffer*>(helpText)); |
|
3203 CheckNewLine(); |
|
3204 PageL(*helpText); |
|
3205 CleanupStack::PopAndDestroy(const_cast<CTextBuffer*>(helpText)); |
|
3206 } |
|
3207 } |
|
3208 |
|
3209 namespace IoUtils |
|
3210 { |
|
3211 class MLineReader |
|
3212 { |
|
3213 public: |
|
3214 virtual TInt GetNextLine(CTextBuffer& aText) = 0; |
|
3215 virtual void InitializeL() {} |
|
3216 }; |
|
3217 |
|
3218 NONSHARABLE_CLASS(TTextBufferLineReader) : public MLineReader |
|
3219 { |
|
3220 public: |
|
3221 TTextBufferLineReader(const CTextBuffer& aBuffer); |
|
3222 public: // From MLineReader. |
|
3223 virtual TInt GetNextLine(CTextBuffer& aText); |
|
3224 private: |
|
3225 const CTextBuffer& iBuffer; |
|
3226 TInt iPos; |
|
3227 }; |
|
3228 |
|
3229 NONSHARABLE_CLASS(TReadHandleLineReader) : public MLineReader |
|
3230 { |
|
3231 public: |
|
3232 TReadHandleLineReader(RIoReadHandle& aHandle); |
|
3233 public: // From MLineReader. |
|
3234 virtual void InitializeL(); |
|
3235 virtual TInt GetNextLine(CTextBuffer& aText); |
|
3236 private: |
|
3237 RIoReadHandle& iHandle; |
|
3238 TBuf<512> iLineBuf; // Note, the code in CCommandBase::PageL(MLineReader&) doesn't properly handle the situation where a given line of input is longer than this buffer. |
|
3239 }; |
|
3240 } |
|
3241 |
|
3242 TTextBufferLineReader::TTextBufferLineReader(const CTextBuffer& aBuffer) |
|
3243 : iBuffer(aBuffer), iPos(0) |
|
3244 { |
|
3245 } |
|
3246 |
|
3247 TInt TTextBufferLineReader::GetNextLine(CTextBuffer& aText) |
|
3248 { |
|
3249 aText.Zero(); |
|
3250 TInt newLinePos = iBuffer.Descriptor().Mid(iPos).Find(KNewLine); |
|
3251 if (newLinePos < 0) |
|
3252 { |
|
3253 if (iPos < iBuffer.Length()) |
|
3254 { |
|
3255 aText.AppendL(iBuffer, iPos); |
|
3256 return KErrNone; |
|
3257 } |
|
3258 return KErrNotFound; |
|
3259 } |
|
3260 else |
|
3261 { |
|
3262 const TInt lineLength = newLinePos + KNewLine().Length(); |
|
3263 aText.AppendL(iBuffer, iPos, lineLength); |
|
3264 iPos += lineLength; |
|
3265 return KErrNone; |
|
3266 } |
|
3267 } |
|
3268 |
|
3269 TReadHandleLineReader::TReadHandleLineReader(RIoReadHandle& aHandle) |
|
3270 : iHandle(aHandle) |
|
3271 { |
|
3272 } |
|
3273 |
|
3274 void TReadHandleLineReader::InitializeL() |
|
3275 { |
|
3276 iHandle.SetReadModeL(RIoReadHandle::ELine); |
|
3277 } |
|
3278 |
|
3279 TInt TReadHandleLineReader::GetNextLine(CTextBuffer& aText) |
|
3280 { |
|
3281 aText.Zero(); |
|
3282 TInt err = iHandle.Read(iLineBuf); |
|
3283 if (err == KErrNone) |
|
3284 { |
|
3285 aText.AppendL(iLineBuf); |
|
3286 } |
|
3287 else if (err == KErrEof) |
|
3288 { |
|
3289 err = KErrNotFound; |
|
3290 } |
|
3291 return err; |
|
3292 } |
|
3293 |
|
3294 |
|
3295 EXPORT_C void CCommandBase::PageL(const CTextBuffer& aText) |
|
3296 { |
|
3297 TTextBufferLineReader lineReader(aText); |
|
3298 lineReader.InitializeL(); |
|
3299 PageL(lineReader); |
|
3300 } |
|
3301 |
|
3302 EXPORT_C void CCommandBase::PageL(RIoReadHandle& aInput) |
|
3303 { |
|
3304 TReadHandleLineReader lineReader(aInput); |
|
3305 lineReader.InitializeL(); |
|
3306 PageL(lineReader); |
|
3307 } |
|
3308 |
|
3309 void CCommandBase::PageL(MLineReader& aLineReader) |
|
3310 { |
|
3311 _LIT(KPrompt, "--More--"); |
|
3312 _LIT(KRemovePrompt, "\x08\x08\x08\x08\x08\x08\x08\x08 \x08\x08\x08\x08\x08\x08\x08\x08"); |
|
3313 |
|
3314 if (iStdout.AttachedToConsole()) |
|
3315 { |
|
3316 RIoConsole console; |
|
3317 console.OpenL(IoSession(), iStdout); |
|
3318 CleanupClosePushL(console); |
|
3319 RIoConsoleReadHandle consReader; |
|
3320 consReader.CreateL(IoSession()); |
|
3321 CleanupClosePushL(consReader); |
|
3322 console.AttachL(consReader, RIoEndPoint::EForeground); |
|
3323 consReader.CaptureAllKeysL(); |
|
3324 TSize consoleSize = iStdout.GetScreenSizeL(); |
|
3325 CTextBuffer* lineBuf = CTextBuffer::NewLC(0x100); |
|
3326 TInt linesPrinted = 0; |
|
3327 TBool finished(EFalse); |
|
3328 while (!finished) |
|
3329 { |
|
3330 if (linesPrinted < (consoleSize.iHeight - 1)) |
|
3331 { |
|
3332 if (lineBuf->Length() == 0) |
|
3333 { |
|
3334 TInt err = aLineReader.GetNextLine(*lineBuf); |
|
3335 if (err == KErrNotFound) |
|
3336 { |
|
3337 finished = ETrue; |
|
3338 } |
|
3339 else if (err) |
|
3340 { |
|
3341 User::Leave(err); |
|
3342 } |
|
3343 } |
|
3344 |
|
3345 if (!finished && lineBuf->Length()) |
|
3346 { |
|
3347 const TInt lineLength = lineBuf->Length(); |
|
3348 const TInt numConsoleLines = ((lineLength / consoleSize.iWidth) + ((lineLength % consoleSize.iWidth) ? 1 : 0)); |
|
3349 const TInt numFreeLines = consoleSize.iHeight - linesPrinted - 1; |
|
3350 TInt lengthToWrite; |
|
3351 if (numConsoleLines < numFreeLines) |
|
3352 { |
|
3353 lengthToWrite = lineLength; |
|
3354 } |
|
3355 else |
|
3356 { |
|
3357 lengthToWrite = Min(lineLength, numFreeLines * consoleSize.iWidth); |
|
3358 } |
|
3359 |
|
3360 lineBuf->Write(iStdout, 0, lengthToWrite); |
|
3361 linesPrinted += ((lengthToWrite / consoleSize.iWidth) + ((lengthToWrite % consoleSize.iWidth) ? 1 : 0)); |
|
3362 lineBuf->Delete(0, lengthToWrite); |
|
3363 |
|
3364 if (lineBuf->Length() == 0) |
|
3365 { |
|
3366 TInt err = aLineReader.GetNextLine(*lineBuf); |
|
3367 if (err == KErrNotFound) |
|
3368 { |
|
3369 finished = ETrue; |
|
3370 } |
|
3371 else if (err) |
|
3372 { |
|
3373 User::Leave(err); |
|
3374 } |
|
3375 } |
|
3376 } |
|
3377 } |
|
3378 else |
|
3379 { |
|
3380 iStdout.Write(KPrompt); |
|
3381 switch ((TInt)consReader.ReadKey()) |
|
3382 { |
|
3383 case 'q': |
|
3384 case 'Q': |
|
3385 case EKeyNull: |
|
3386 { |
|
3387 finished = ETrue; |
|
3388 break; |
|
3389 } |
|
3390 case EKeyEnter: |
|
3391 { |
|
3392 --linesPrinted; |
|
3393 break; |
|
3394 } |
|
3395 default: |
|
3396 { |
|
3397 linesPrinted = 0; |
|
3398 break; |
|
3399 } |
|
3400 } |
|
3401 iStdout.Write(KRemovePrompt); |
|
3402 } |
|
3403 } |
|
3404 CleanupStack::PopAndDestroy(3, &console); |
|
3405 } |
|
3406 else |
|
3407 { |
|
3408 // Not attached to a console, so just copy stdin to stdout. |
|
3409 CTextBuffer* lineBuf = CTextBuffer::NewLC(0x100); |
|
3410 while (aLineReader.GetNextLine(*lineBuf) == KErrNone) |
|
3411 { |
|
3412 iStdout.Write(lineBuf->Descriptor()); |
|
3413 } |
|
3414 CleanupStack::PopAndDestroy(lineBuf); |
|
3415 } |
|
3416 } |
|
3417 |
|
3418 EXPORT_C const TDesC& CCommandBase::Description() const |
|
3419 { |
|
3420 if (iCif == NULL) |
|
3421 { |
|
3422 const_cast<CCommandBase*>(this)->iFlags |= EReadCif; |
|
3423 return KNullDesC; // Dummy return value. |
|
3424 } |
|
3425 return iCif->ShortDescription(); |
|
3426 } |
|
3427 |
|
3428 EXPORT_C const TDesC* CCommandBase::ConsoleImplementation() |
|
3429 { |
|
3430 return iConsoleImplementation; |
|
3431 } |
|
3432 |
|
3433 EXPORT_C void CCommandBase::SetErrorReported(TBool aReported) |
|
3434 { |
|
3435 if (aReported) |
|
3436 { |
|
3437 iFlags |= EErrorReported; |
|
3438 } |
|
3439 else |
|
3440 { |
|
3441 iFlags &= ~EErrorReported; |
|
3442 } |
|
3443 } |
|
3444 |
|
3445 EXPORT_C void CCommandBase::StartSupressingErrors() |
|
3446 { |
|
3447 iSupressingErrors++; |
|
3448 } |
|
3449 |
|
3450 EXPORT_C void CCommandBase::StopSupressingErrors() |
|
3451 { |
|
3452 iSupressingErrors--; |
|
3453 } |
|
3454 |
|
3455 EXPORT_C TBool CCommandBase::IsComplete() const |
|
3456 { |
|
3457 return (iFlags & ECompleted); |
|
3458 } |
|
3459 |
|
3460 EXPORT_C TInt CCommandBase::CompletionReason() const |
|
3461 { |
|
3462 __ASSERT_ALWAYS(IsComplete(), Panic(ENotYetComplete)); |
|
3463 return iCompletionReason; |
|
3464 } |
|
3465 |
|
3466 HBufC* CCommandBase::ReadStringLC(TLex& aLex, TUint aOptions) const |
|
3467 { |
|
3468 while (!aLex.Eos() && (aLex.Peek().IsSpace() || ((aOptions & EBreakOnComma) && (aLex.Peek() == ',')))) |
|
3469 { |
|
3470 aLex.Inc(); |
|
3471 } |
|
3472 |
|
3473 if (aLex.Eos()) |
|
3474 { |
|
3475 // There aren't any characters at all. This can be considered a syntax error because if an empty string was intended |
|
3476 // it should have been written as "" or ''. |
|
3477 CommandLeaveIfErr(*const_cast<CCommandBase*>(this), KErrArgument, _L("Missing argument")); |
|
3478 } |
|
3479 |
|
3480 TChar c = aLex.Peek(); |
|
3481 TBool quoted = ((c == '\'') || (c == '"') || (c == iEnv->EscapeChar())); |
|
3482 TUint readMode = 0; |
|
3483 if (aOptions & EBreakOnComma) |
|
3484 { |
|
3485 readMode |= Stringify::EBreakOnComma; |
|
3486 } |
|
3487 HBufC* string = Stringify::ReadLC(aLex, iEnv->EscapeChar(), *const_cast<CCommandBase*>(this), readMode); |
|
3488 if ((aOptions & EDisallowLeadingHyphen) && (string->Length() > 0) && ((*string)[0] == '-') && !quoted) |
|
3489 { |
|
3490 CommandLeaveIfErr(*const_cast<CCommandBase*>(this), KErrArgument, _L("Argument \"%S\" appears to be an option - probable missing argument"), string); |
|
3491 } |
|
3492 return string; |
|
3493 } |
|
3494 |
|
3495 EXPORT_C void RChildProcess::Close() |
|
3496 { |
|
3497 iStderr.Close(); |
|
3498 iStdout.Close(); |
|
3499 iStdin.Close(); |
|
3500 iProcess.Close(); |
|
3501 } |
|
3502 |
|
3503 void SetIoObjectName(RIoSession& aIoSession, TInt aObjHandle, TRefByValue<const TDesC> aFmt, ...) |
|
3504 { |
|
3505 TOverflowTruncate overflow; |
|
3506 VA_LIST list; |
|
3507 VA_START(list, aFmt); |
|
3508 TFullName name; |
|
3509 name.AppendFormatList(aFmt, list, &overflow); |
|
3510 VA_END(list); |
|
3511 aIoSession.SetObjectName(aObjHandle, name); |
|
3512 } |
|
3513 |
|
3514 EXPORT_C void RChildProcess::CreateL(const TDesC& aExecutableName, const TDesC& aCommandLine, RIoSession& aIoSession, RIoReadHandle& aStdin, RIoWriteHandle& aStdout, RIoWriteHandle& aStderr) |
|
3515 { |
|
3516 DoCreateL(aExecutableName, aCommandLine, aIoSession, aStdin, aStdout, aStderr, NULL); |
|
3517 } |
|
3518 |
|
3519 EXPORT_C void RChildProcess::CreateL(const TDesC& aExecutableName, const TDesC& aCommandLine, RIoSession& aIoSession, RIoReadHandle& aStdin, RIoWriteHandle& aStdout, RIoWriteHandle& aStderr, const CEnvironment& aEnv) |
|
3520 { |
|
3521 DoCreateL(aExecutableName, aCommandLine, aIoSession, aStdin, aStdout, aStderr, &aEnv); |
|
3522 } |
|
3523 |
|
3524 EXPORT_C void RChildProcess::CreateL(const TDesC& aExecutableName, const TDesC& aCommandLine, RIoSession& aIoSession, RIoConsole& aConsole, const CEnvironment* aEnv) |
|
3525 { |
|
3526 CleanupClosePushL(*this); |
|
3527 iStdin.CreateL(aIoSession); |
|
3528 iStdout.CreateL(aIoSession); |
|
3529 iStderr.CreateL(aIoSession); |
|
3530 |
|
3531 NameHandles(aExecutableName, aIoSession); |
|
3532 |
|
3533 aConsole.AttachL(iStdin, RIoEndPoint::EForeground); |
|
3534 iStdin.SetUnderlyingConsoleL(aConsole); |
|
3535 aConsole.AttachL(iStdout); |
|
3536 iStdout.SetUnderlyingConsoleL(aConsole); |
|
3537 aConsole.AttachL(iStderr); |
|
3538 iStderr.SetUnderlyingConsoleL(aConsole); |
|
3539 |
|
3540 ProcessCreateL(aExecutableName, aCommandLine, aEnv); |
|
3541 |
|
3542 CleanupStack::Pop(); |
|
3543 } |
|
3544 |
|
3545 void RChildProcess::NameHandles(const TDesC& aExecutableName, RIoSession& aIoSession) |
|
3546 { |
|
3547 // Give the handles a name to aid debugging (makes the iosvr logs easier to understand). |
|
3548 SetIoObjectName(aIoSession, iStdin.SubSessionHandle(), _L("%S_stdin"), &aExecutableName); |
|
3549 SetIoObjectName(aIoSession, iStdout.SubSessionHandle(), _L("%S_stdout"), &aExecutableName); |
|
3550 SetIoObjectName(aIoSession, iStderr.SubSessionHandle(), _L("%S_stderr"), &aExecutableName); |
|
3551 } |
|
3552 |
|
3553 void RChildProcess::DoCreateL(const TDesC& aExecutableName, const TDesC& aCommandLine, RIoSession& aIoSession, RIoReadHandle& aStdin, RIoWriteHandle& aStdout, RIoWriteHandle& aStderr, const CEnvironment* aEnv) |
|
3554 { |
|
3555 CleanupClosePushL(*this); |
|
3556 |
|
3557 // Create a set of I/O handles for the new process. |
|
3558 User::LeaveIfError(iStdin.Create(aIoSession)); |
|
3559 User::LeaveIfError(iStdout.Create(aIoSession)); |
|
3560 User::LeaveIfError(iStderr.Create(aIoSession)); |
|
3561 |
|
3562 NameHandles(aExecutableName, aIoSession); |
|
3563 |
|
3564 // Make the newly created handles duplicates of the ones that were passed in. |
|
3565 // This makes them attached to the same I/O end-points (consoles, files, etc) |
|
3566 // as the passed in handles. |
|
3567 User::LeaveIfError(iStdin.Duplicate(aStdin)); |
|
3568 User::LeaveIfError(iStdin.SetToForeground()); |
|
3569 User::LeaveIfError(iStdout.Duplicate(aStdout)); |
|
3570 User::LeaveIfError(iStderr.Duplicate(aStderr)); |
|
3571 |
|
3572 // Create the process. |
|
3573 ProcessCreateL(aExecutableName, aCommandLine, aEnv); |
|
3574 |
|
3575 CleanupStack::Pop(this); |
|
3576 } |
|
3577 |
|
3578 void RChildProcess::ProcessCreateL(const TDesC& aExecutableName, const TDesC& aCommandLine, const CEnvironment* aEnv) |
|
3579 { |
|
3580 User::LeaveIfError(iProcess.Create(aExecutableName, aCommandLine)); |
|
3581 |
|
3582 #ifdef EKA2 |
|
3583 if (aEnv) |
|
3584 { |
|
3585 // Attach a copy of aEnv as a parameter. |
|
3586 HBufC8* envBuf = aEnv->ExternalizeLC(); |
|
3587 User::LeaveIfError(iProcess.SetParameter(IoUtils::KEnvironmentProcessSlot, *envBuf)); |
|
3588 CleanupStack::PopAndDestroy(envBuf); |
|
3589 } |
|
3590 #endif |
|
3591 |
|
3592 // Make the main thread of the new process the owner of the I/O handles. |
|
3593 // This makes it possible for the new process to subsequently open them and |
|
3594 // avoid having to create a new set (which would prevent end-point sharing). |
|
3595 TFullName fullName(iProcess.Name()); |
|
3596 _LIT(KThreadName,"::Main"); |
|
3597 fullName.Append(KThreadName); |
|
3598 RThread thread; |
|
3599 User::LeaveIfError(thread.Open(fullName)); |
|
3600 TThreadId threadId(thread.Id()); |
|
3601 thread.Close(); |
|
3602 User::LeaveIfError(iStdin.SetOwner(threadId)); |
|
3603 User::LeaveIfError(iStdout.SetOwner(threadId)); |
|
3604 User::LeaveIfError(iStderr.SetOwner(threadId)); |
|
3605 } |
|
3606 |
|
3607 EXPORT_C void RChildProcess::Run(TRequestStatus& aStatus) |
|
3608 { |
|
3609 iProcess.Logon(aStatus); |
|
3610 if (aStatus != KRequestPending) |
|
3611 { |
|
3612 iProcess.Kill(KErrAbort); |
|
3613 } |
|
3614 else |
|
3615 { |
|
3616 iProcess.Resume(); |
|
3617 } |
|
3618 } |
|
3619 |
|
3620 EXPORT_C void RChildProcess::Detach() |
|
3621 { |
|
3622 iProcess.Resume(); |
|
3623 } |
|
3624 |
|
3625 EXPORT_C RProcess& RChildProcess::Process() |
|
3626 { |
|
3627 return iProcess; |
|
3628 } |
|
3629 |
|
3630 EXPORT_C const RProcess& RChildProcess::Process() const |
|
3631 { |
|
3632 return iProcess; |
|
3633 } |
|
3634 |
|
3635 #define CASE_RETURN_LIT(XXX) case XXX: { _LIT(_KLit, #XXX); return &_KLit; } |
|
3636 #define CASE_RETURN_LIT2(XXX, YYY) case XXX: { _LIT(_KLit, YYY); return &_KLit; } |
|
3637 #define DEFAULT_RETURN_LIT(XXX) default: { _LIT(_KLit, XXX); return &_KLit; } |
|
3638 |
|
3639 EXPORT_C const TDesC* Stringify::Error(TInt aError) |
|
3640 { |
|
3641 enum TThingsNotAvailableEverywhere |
|
3642 { |
|
3643 KErrNoSecureTime = -49, |
|
3644 KErrCorruptSurrogateFound = -50, |
|
3645 }; |
|
3646 |
|
3647 switch (aError) |
|
3648 { |
|
3649 CASE_RETURN_LIT(KErrNone); |
|
3650 CASE_RETURN_LIT(KErrNotFound); |
|
3651 CASE_RETURN_LIT(KErrGeneral); |
|
3652 CASE_RETURN_LIT(KErrCancel); |
|
3653 CASE_RETURN_LIT(KErrNoMemory); |
|
3654 CASE_RETURN_LIT(KErrNotSupported); |
|
3655 CASE_RETURN_LIT(KErrArgument); |
|
3656 CASE_RETURN_LIT(KErrTotalLossOfPrecision); |
|
3657 CASE_RETURN_LIT(KErrBadHandle); |
|
3658 CASE_RETURN_LIT(KErrOverflow); |
|
3659 CASE_RETURN_LIT(KErrUnderflow); |
|
3660 CASE_RETURN_LIT(KErrAlreadyExists); |
|
3661 CASE_RETURN_LIT(KErrPathNotFound); |
|
3662 CASE_RETURN_LIT(KErrDied); |
|
3663 CASE_RETURN_LIT(KErrInUse); |
|
3664 CASE_RETURN_LIT(KErrServerTerminated); |
|
3665 CASE_RETURN_LIT(KErrServerBusy); |
|
3666 CASE_RETURN_LIT(KErrCompletion); |
|
3667 CASE_RETURN_LIT(KErrNotReady); |
|
3668 CASE_RETURN_LIT(KErrUnknown); |
|
3669 CASE_RETURN_LIT(KErrCorrupt); |
|
3670 CASE_RETURN_LIT(KErrAccessDenied); |
|
3671 CASE_RETURN_LIT(KErrLocked); |
|
3672 CASE_RETURN_LIT(KErrWrite); |
|
3673 CASE_RETURN_LIT(KErrDisMounted); |
|
3674 CASE_RETURN_LIT(KErrEof); |
|
3675 CASE_RETURN_LIT(KErrDiskFull); |
|
3676 CASE_RETURN_LIT(KErrBadDriver); |
|
3677 CASE_RETURN_LIT(KErrBadName); |
|
3678 CASE_RETURN_LIT(KErrCommsLineFail); |
|
3679 CASE_RETURN_LIT(KErrCommsFrame); |
|
3680 CASE_RETURN_LIT(KErrCommsOverrun); |
|
3681 CASE_RETURN_LIT(KErrCommsParity); |
|
3682 CASE_RETURN_LIT(KErrTimedOut); |
|
3683 CASE_RETURN_LIT(KErrCouldNotConnect); |
|
3684 CASE_RETURN_LIT(KErrCouldNotDisconnect); |
|
3685 CASE_RETURN_LIT(KErrDisconnected); |
|
3686 CASE_RETURN_LIT(KErrBadLibraryEntryPoint); |
|
3687 CASE_RETURN_LIT(KErrBadDescriptor); |
|
3688 CASE_RETURN_LIT(KErrAbort); |
|
3689 CASE_RETURN_LIT(KErrTooBig); |
|
3690 CASE_RETURN_LIT(KErrDivideByZero); |
|
3691 CASE_RETURN_LIT(KErrBadPower); |
|
3692 CASE_RETURN_LIT(KErrDirFull); |
|
3693 CASE_RETURN_LIT(KErrHardwareNotAvailable); |
|
3694 #ifdef EKA2 |
|
3695 CASE_RETURN_LIT(KErrSessionClosed); |
|
3696 CASE_RETURN_LIT(KErrPermissionDenied); |
|
3697 CASE_RETURN_LIT(KErrExtensionNotSupported); |
|
3698 CASE_RETURN_LIT(KErrCommsBreak); |
|
3699 CASE_RETURN_LIT(KErrNoSecureTime); |
|
3700 CASE_RETURN_LIT(KErrCorruptSurrogateFound); |
|
3701 #endif |
|
3702 DEFAULT_RETURN_LIT("*** ERROR UNKNOWN ***"); |
|
3703 } |
|
3704 } |
|
3705 |
|
3706 EXPORT_C void IoUtils::ReadL(TDes& aData) |
|
3707 { |
|
3708 CCommandBase::Static().ReadL(aData); |
|
3709 } |
|
3710 |
|
3711 EXPORT_C void IoUtils::Write(const TDesC& aData) |
|
3712 { |
|
3713 CCommandBase::Static().Write(aData); |
|
3714 } |
|
3715 |
|
3716 EXPORT_C void IoUtils::Printf(TRefByValue<const TDesC> aFmt, ...) |
|
3717 { |
|
3718 VA_LIST list; |
|
3719 VA_START(list, aFmt); |
|
3720 CCommandBase::Static().PrintList(aFmt, list); |
|
3721 VA_END(list); |
|
3722 } |
|
3723 |
|
3724 EXPORT_C void IoUtils::Printf(TRefByValue<const TDesC8> aFmt, ...) |
|
3725 { |
|
3726 VA_LIST list; |
|
3727 VA_START(list, aFmt); |
|
3728 CCommandBase::Static().PrintList(aFmt, list); |
|
3729 VA_END(list); |
|
3730 } |
|
3731 |
|
3732 EXPORT_C void IoUtils::PrintError(TInt aError, TRefByValue<const TDesC> aFmt, ...) |
|
3733 { |
|
3734 VA_LIST list; |
|
3735 VA_START(list, aFmt); |
|
3736 CCommandBase::Static().PrintErrorList(aError, aFmt, list); |
|
3737 VA_END(list); |
|
3738 } |
|
3739 |
|
3740 EXPORT_C void IoUtils::PrintWarning(TRefByValue<const TDesC> aFmt, ...) |
|
3741 { |
|
3742 VA_LIST list; |
|
3743 VA_START(list, aFmt); |
|
3744 CCommandBase::Static().PrintWarningList(aFmt, list); |
|
3745 VA_END(list); |
|
3746 } |
|
3747 |
|
3748 |
|
3749 // |
|
3750 // CCommandCompleter. |
|
3751 // |
|
3752 |
|
3753 CCommandCompleter::CCommandCompleter(IoUtils::CCommandBase& aCmd) |
|
3754 : CActive(CActive::EPriorityStandard), iCmd(aCmd) |
|
3755 { |
|
3756 CActiveScheduler::Add(this); |
|
3757 } |
|
3758 |
|
3759 CCommandCompleter::~CCommandCompleter() |
|
3760 { |
|
3761 Cancel(); |
|
3762 delete iTextBuffer; |
|
3763 } |
|
3764 |
|
3765 void CCommandCompleter::Complete(TInt aError) |
|
3766 { |
|
3767 TRequestStatus* status = &iStatus; |
|
3768 User::RequestComplete(status, aError); |
|
3769 SetActive(); |
|
3770 } |
|
3771 |
|
3772 void CCommandCompleter::Complete(TInt aError, const TDesC& aText, RIoWriteHandle& aWhere) |
|
3773 { |
|
3774 TOverflowTruncate overflow; |
|
3775 iBuf.AppendFormat(aText, &overflow); |
|
3776 iError = aError; |
|
3777 aWhere.Write(iBuf, iStatus); |
|
3778 SetActive(); |
|
3779 } |
|
3780 |
|
3781 void CCommandCompleter::Complete(TInt aError, const CTextBuffer* aTextBuffer, RIoWriteHandle& aWhere) |
|
3782 { |
|
3783 ASSERT(iTextBuffer == NULL); |
|
3784 iTextBuffer = aTextBuffer; |
|
3785 iError = aError; |
|
3786 iTextBuffer->Write(aWhere, iStatus); |
|
3787 SetActive(); |
|
3788 } |
|
3789 |
|
3790 void CCommandCompleter::RunL() |
|
3791 { |
|
3792 iCmd.CompleteCallback(iError ? iError : iStatus.Int()); |
|
3793 } |
|
3794 |
|
3795 void CCommandCompleter::DoCancel() |
|
3796 { |
|
3797 } |
|
3798 |
|
3799 |
|
3800 // |
|
3801 // CReaderChangeNotifier. |
|
3802 // |
|
3803 |
|
3804 CReaderChangeNotifier::CReaderChangeNotifier(IoUtils::CCommandBase& aCmd, RIoReadHandle& aReadHandle) |
|
3805 : CActive(CActive::EPriorityStandard) |
|
3806 , iCmd(aCmd) |
|
3807 , iReadHandle(aReadHandle) |
|
3808 { |
|
3809 CActiveScheduler::Add(this); |
|
3810 } |
|
3811 |
|
3812 CReaderChangeNotifier::~CReaderChangeNotifier() |
|
3813 { |
|
3814 Cancel(); |
|
3815 } |
|
3816 |
|
3817 void CReaderChangeNotifier::Notify() |
|
3818 { |
|
3819 iReadHandle.NotifyChange(iChangeType, iStatus); |
|
3820 SetActive(); |
|
3821 } |
|
3822 |
|
3823 void CReaderChangeNotifier::RunL() |
|
3824 { |
|
3825 if (iStatus.Int()==KErrNone) |
|
3826 { |
|
3827 TUint change = iChangeType(); |
|
3828 Notify(); |
|
3829 iCmd.StdinChange(change); |
|
3830 } |
|
3831 } |
|
3832 |
|
3833 void CReaderChangeNotifier::DoCancel() |
|
3834 { |
|
3835 iReadHandle.CancelNotifyChange(); |
|
3836 } |
|
3837 |
|
3838 |