Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
CMake
CMake
Commits
c8fa6581
Commit
c8fa6581
authored
Sep 13, 2004
by
Andy Cedilnik
Browse files
ENH: Move command line argument parsing code to kwsys
parent
3e03bed0
Changes
4
Hide whitespace changes
Inline
Side-by-side
Source/kwsys/CMakeLists.txt
View file @
c8fa6581
...
...
@@ -78,6 +78,7 @@ IF(NOT KWSYS_NAMESPACE)
SET
(
KWSYS_USE_Process 1
)
SET
(
KWSYS_USE_RegularExpression 1
)
SET
(
KWSYS_USE_SystemTools 1
)
SET
(
KWSYS_USE_CommandLineArguments 1
)
ENDIF
(
NOT KWSYS_NAMESPACE
)
#-----------------------------------------------------------------------------
...
...
@@ -248,12 +249,20 @@ IF(KWSYS_USE_SystemTools)
ENDIF
(
KWSYS_USE_SystemTools
)
# Add selected C++ classes.
FOREACH
(
c Directory RegularExpression SystemTools
)
FOREACH
(
c Directory RegularExpression SystemTools
CommandLineArguments
)
IF
(
KWSYS_USE_
${
c
}
)
SET
(
KWSYS_CLASSES
${
KWSYS_CLASSES
}
${
c
}
)
ENDIF
(
KWSYS_USE_
${
c
}
)
ENDFOREACH
(
c
)
IF
(
KWSYS_USE_CommandLineArguments
)
IF
(
NOT ParaView_SOURCE_DIR
)
IF
(
NOT KWSYS_STANDALONE
)
MESSAGE
(
"Command Line Arguments is experimental code for now"
)
ENDIF
(
NOT KWSYS_STANDALONE
)
ENDIF
(
NOT ParaView_SOURCE_DIR
)
ENDIF
(
KWSYS_USE_CommandLineArguments
)
# Add selected C components.
FOREACH
(
c Process Base64
)
IF
(
KWSYS_USE_
${
c
}
)
...
...
@@ -411,9 +420,11 @@ IF(KWSYS_STANDALONE)
ADD_EXECUTABLE
(
testIOS testIOS.cxx
)
ADD_EXECUTABLE
(
testProcess testProcess.c
)
ADD_EXECUTABLE
(
test1 test1.cxx
)
ADD_EXECUTABLE
(
testCommandLineArguments testCommandLineArguments.cxx
)
TARGET_LINK_LIBRARIES
(
testIOS
${
KWSYS_NAMESPACE
}
)
TARGET_LINK_LIBRARIES
(
testProcess
${
KWSYS_NAMESPACE
}
_c
)
TARGET_LINK_LIBRARIES
(
test1
${
KWSYS_NAMESPACE
}
)
TARGET_LINK_LIBRARIES
(
testCommandLineArguments
${
KWSYS_NAMESPACE
}
)
IF
(
BUILD_TESTING
)
ADD_TEST
(
testProcess-1 testProcess 1
)
...
...
Source/kwsys/CommandLineArguments.cxx
0 → 100644
View file @
c8fa6581
/*=========================================================================
Program: KWSys - Kitware System Library
Module: $RCSfile$
Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "kwsysPrivate.h"
#include KWSYS_HEADER(CommandLineArguments.hxx)
#include KWSYS_HEADER(Configure.hxx)
#include KWSYS_HEADER(stl/vector)
#include KWSYS_HEADER(stl/map)
#include KWSYS_HEADER(stl/set)
#include KWSYS_HEADER(ios/sstream)
#include <stdio.h>
namespace
KWSYS_NAMESPACE
{
//----------------------------------------------------------------------------
//============================================================================
class
CommandLineArgumentsString
:
public
kwsys_stl
::
string
{
public:
typedef
kwsys_stl
::
string
StdString
;
CommandLineArgumentsString
()
:
StdString
()
{}
CommandLineArgumentsString
(
const
value_type
*
s
)
:
StdString
(
s
)
{}
CommandLineArgumentsString
(
const
value_type
*
s
,
size_type
n
)
:
StdString
(
s
,
n
)
{}
CommandLineArgumentsString
(
const
StdString
&
s
,
size_type
pos
=
0
,
size_type
n
=
npos
)
:
StdString
(
s
,
pos
,
n
)
{}
};
class
CommandLineArgumentsVectorOfStrings
:
public
kwsys_stl
::
vector
<
CommandLineArgumentsString
>
{};
class
CommandLineArgumentsSetOfStrings
:
public
kwsys_stl
::
set
<
CommandLineArgumentsString
>
{};
class
CommandLineArgumentsMapOfStrucs
:
public
kwsys_stl
::
map
<
CommandLineArgumentsString
,
CommandLineArguments
::
CallbackStructure
>
{};
class
CommandLineArgumentsInternal
{
public:
CommandLineArgumentsInternal
()
{
this
->
UnknownArgumentCallback
=
0
;
this
->
ClientData
=
0
;
this
->
LastArgument
=
0
;
}
typedef
CommandLineArgumentsVectorOfStrings
VectorOfStrings
;
typedef
CommandLineArgumentsMapOfStrucs
CallbacksMap
;
typedef
CommandLineArgumentsString
String
;
typedef
CommandLineArgumentsSetOfStrings
SetOfStrings
;
VectorOfStrings
Argv
;
CallbacksMap
Callbacks
;
CommandLineArguments
::
ErrorCallbackType
UnknownArgumentCallback
;
void
*
ClientData
;
VectorOfStrings
::
size_type
LastArgument
;
};
//============================================================================
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
CommandLineArguments
::
CommandLineArguments
()
{
this
->
Internals
=
new
CommandLineArguments
::
Internal
;
this
->
Help
=
""
;
this
->
LineLength
=
80
;
}
//----------------------------------------------------------------------------
CommandLineArguments
::~
CommandLineArguments
()
{
delete
this
->
Internals
;
}
//----------------------------------------------------------------------------
void
CommandLineArguments
::
Initialize
(
int
argc
,
char
*
argv
[])
{
int
cc
;
this
->
Initialize
();
for
(
cc
=
1
;
cc
<
argc
;
cc
++
)
{
this
->
ProcessArgument
(
argv
[
cc
]);
}
}
//----------------------------------------------------------------------------
void
CommandLineArguments
::
Initialize
()
{
this
->
Internals
->
Argv
.
clear
();
this
->
Internals
->
LastArgument
=
0
;
}
//----------------------------------------------------------------------------
void
CommandLineArguments
::
ProcessArgument
(
const
char
*
arg
)
{
this
->
Internals
->
Argv
.
push_back
(
arg
);
}
//----------------------------------------------------------------------------
int
CommandLineArguments
::
Parse
()
{
CommandLineArguments
::
Internal
::
VectorOfStrings
::
size_type
cc
;
CommandLineArguments
::
Internal
::
VectorOfStrings
matches
;
for
(
cc
=
0
;
cc
<
this
->
Internals
->
Argv
.
size
();
cc
++
)
{
matches
.
clear
();
CommandLineArguments
::
Internal
::
String
&
arg
=
this
->
Internals
->
Argv
[
cc
];
CommandLineArguments
::
Internal
::
CallbacksMap
::
iterator
it
;
// Does the argument match to any we know about?
for
(
it
=
this
->
Internals
->
Callbacks
.
begin
();
it
!=
this
->
Internals
->
Callbacks
.
end
();
it
++
)
{
const
CommandLineArguments
::
Internal
::
String
&
parg
=
it
->
first
;
CommandLineArguments
::
CallbackStructure
*
cs
=
&
it
->
second
;
if
(
cs
->
ArgumentType
==
CommandLineArguments
::
NO_ARGUMENT
||
cs
->
ArgumentType
==
CommandLineArguments
::
SPACE_ARGUMENT
)
{
if
(
arg
==
parg
)
{
matches
.
push_back
(
parg
);
}
}
else
if
(
arg
.
find
(
parg
)
==
0
)
{
matches
.
push_back
(
parg
);
}
}
if
(
matches
.
size
()
>
0
)
{
// Ok, we found one or more arguments that match what user specified.
// Let's find the longest one.
CommandLineArguments
::
Internal
::
VectorOfStrings
::
size_type
kk
;
CommandLineArguments
::
Internal
::
VectorOfStrings
::
size_type
maxidx
=
0
;
CommandLineArguments
::
Internal
::
String
::
size_type
maxlen
=
0
;
for
(
kk
=
0
;
kk
<
matches
.
size
();
kk
++
)
{
if
(
matches
[
kk
].
size
()
>
maxlen
)
{
maxlen
=
matches
[
kk
].
size
();
maxidx
=
kk
;
}
}
// So, the longest one is probably the right one. Now see if it has any
// additional value
const
char
*
value
=
0
;
CommandLineArguments
::
CallbackStructure
*
cs
=
&
this
->
Internals
->
Callbacks
[
matches
[
maxidx
]];
const
CommandLineArguments
::
Internal
::
String
&
sarg
=
matches
[
maxidx
];
if
(
cs
->
ArgumentType
==
NO_ARGUMENT
)
{
// No value
}
else
if
(
cs
->
ArgumentType
==
SPACE_ARGUMENT
)
{
if
(
cc
==
this
->
Internals
->
Argv
.
size
()
-
1
)
{
return
0
;
}
// Value is the next argument
value
=
this
->
Internals
->
Argv
[
cc
+
1
].
c_str
();
cc
++
;
}
else
if
(
cs
->
ArgumentType
==
EQUAL_ARGUMENT
)
{
if
(
arg
.
size
()
==
sarg
.
size
()
||
*
(
arg
.
c_str
()
+
sarg
.
size
())
!=
'='
)
{
return
0
;
}
// Value is everythng followed the '=' sign
value
=
arg
.
c_str
()
+
sarg
.
size
()
+
1
;
}
else
if
(
cs
->
ArgumentType
==
CONCAT_ARGUMENT
)
{
// Value is whatever follows the argument
value
=
arg
.
c_str
()
+
sarg
.
size
();
}
// Call the callback
if
(
cs
->
Callback
)
{
if
(
!
cs
->
Callback
(
sarg
.
c_str
(),
value
,
cs
->
CallData
)
)
{
return
0
;
}
}
if
(
cs
->
Variable
)
{
kwsys_stl
::
string
var
=
"1"
;
if
(
value
)
{
var
=
value
;
}
if
(
cs
->
VariableType
==
CommandLineArguments
::
INT_TYPE
)
{
int
*
variable
=
static_cast
<
int
*>
(
cs
->
Variable
);
char
*
res
=
0
;
*
variable
=
strtol
(
var
.
c_str
(),
&
res
,
10
);
//if ( res && *res )
// {
// Can handle non-int
// }
}
else
if
(
cs
->
VariableType
==
CommandLineArguments
::
DOUBLE_TYPE
)
{
double
*
variable
=
static_cast
<
double
*>
(
cs
->
Variable
);
char
*
res
=
0
;
*
variable
=
strtod
(
var
.
c_str
(),
&
res
);
//if ( res && *res )
// {
// Can handle non-int
// }
}
else
if
(
cs
->
VariableType
==
CommandLineArguments
::
STRING_TYPE
)
{
char
**
variable
=
static_cast
<
char
**>
(
cs
->
Variable
);
if
(
*
variable
)
{
delete
[]
*
variable
;
*
variable
=
0
;
}
*
variable
=
new
char
[
strlen
(
var
.
c_str
())
+
1
];
strcpy
(
*
variable
,
var
.
c_str
());
}
else
if
(
cs
->
VariableType
==
CommandLineArguments
::
STL_STRING_TYPE
)
{
kwsys_stl
::
string
*
variable
=
static_cast
<
kwsys_stl
::
string
*>
(
cs
->
Variable
);
*
variable
=
var
;
}
else
if
(
cs
->
VariableType
==
CommandLineArguments
::
BOOL_TYPE
)
{
bool
*
variable
=
static_cast
<
bool
*>
(
cs
->
Variable
);
if
(
var
==
"1"
||
var
==
"ON"
||
var
==
"TRUE"
||
var
==
"true"
||
var
==
"on"
||
var
==
"True"
||
var
==
"yes"
||
var
==
"Yes"
||
var
==
"YES"
)
{
*
variable
=
true
;
}
else
{
*
variable
=
false
;
}
}
else
{
cerr
<<
"Got unknown argument type:
\"
"
<<
cs
->
VariableType
<<
"
\"
"
<<
endl
;
return
0
;
}
}
}
else
{
// Handle unknown arguments
if
(
this
->
Internals
->
UnknownArgumentCallback
)
{
if
(
!
this
->
Internals
->
UnknownArgumentCallback
(
arg
.
c_str
(),
this
->
Internals
->
ClientData
)
)
{
return
0
;
}
return
1
;
}
else
{
cerr
<<
"Got unknown argument:
\"
"
<<
arg
.
c_str
()
<<
"
\"
"
<<
endl
;
return
0
;
}
}
}
// We are done parsing, so remember what was the last argument
this
->
Internals
->
LastArgument
=
cc
;
return
1
;
}
//----------------------------------------------------------------------------
void
CommandLineArguments
::
GetRemainingArguments
(
int
*
argc
,
char
***
argv
)
{
CommandLineArguments
::
Internal
::
VectorOfStrings
::
size_type
size
=
this
->
Internals
->
Argv
.
size
()
-
this
->
Internals
->
LastArgument
+
1
;
CommandLineArguments
::
Internal
::
VectorOfStrings
::
size_type
cc
;
char
**
args
=
new
char
*
[
size
];
args
[
0
]
=
new
char
[
this
->
Internals
->
Argv
[
0
].
size
()
+
1
];
strcpy
(
args
[
0
],
this
->
Internals
->
Argv
[
0
].
c_str
());
int
cnt
=
1
;
for
(
cc
=
this
->
Internals
->
LastArgument
;
cc
<
this
->
Internals
->
Argv
.
size
();
cc
++
)
{
args
[
cnt
]
=
new
char
[
this
->
Internals
->
Argv
[
cc
].
size
()
+
1
];
strcpy
(
args
[
cnt
],
this
->
Internals
->
Argv
[
cc
].
c_str
());
cnt
++
;
}
*
argc
=
cnt
;
*
argv
=
args
;
}
//----------------------------------------------------------------------------
void
CommandLineArguments
::
AddCallback
(
const
char
*
argument
,
ArgumentTypeEnum
type
,
CallbackType
callback
,
void
*
call_data
,
const
char
*
help
)
{
CommandLineArguments
::
CallbackStructure
s
;
s
.
Argument
=
argument
;
s
.
ArgumentType
=
type
;
s
.
Callback
=
callback
;
s
.
CallData
=
call_data
;
s
.
VariableType
=
CommandLineArguments
::
NO_VARIABLE_TYPE
;
s
.
Variable
=
0
;
s
.
Help
=
help
;
this
->
Internals
->
Callbacks
[
argument
]
=
s
;
this
->
GenerateHelp
();
}
//----------------------------------------------------------------------------
void
CommandLineArguments
::
AddArgument
(
const
char
*
argument
,
ArgumentTypeEnum
type
,
VariableTypeEnum
vtype
,
void
*
variable
,
const
char
*
help
)
{
CommandLineArguments
::
CallbackStructure
s
;
s
.
Argument
=
argument
;
s
.
ArgumentType
=
type
;
s
.
Callback
=
0
;
s
.
CallData
=
0
;
s
.
VariableType
=
vtype
;
s
.
Variable
=
variable
;
s
.
Help
=
help
;
this
->
Internals
->
Callbacks
[
argument
]
=
s
;
this
->
GenerateHelp
();
}
//----------------------------------------------------------------------------
void
CommandLineArguments
::
AddArgument
(
const
char
*
argument
,
ArgumentTypeEnum
type
,
int
*
variable
,
const
char
*
help
)
{
this
->
AddArgument
(
argument
,
type
,
CommandLineArguments
::
INT_TYPE
,
variable
,
help
);
}
//----------------------------------------------------------------------------
void
CommandLineArguments
::
AddArgument
(
const
char
*
argument
,
ArgumentTypeEnum
type
,
double
*
variable
,
const
char
*
help
)
{
this
->
AddArgument
(
argument
,
type
,
CommandLineArguments
::
DOUBLE_TYPE
,
variable
,
help
);
}
//----------------------------------------------------------------------------
void
CommandLineArguments
::
AddArgument
(
const
char
*
argument
,
ArgumentTypeEnum
type
,
char
**
variable
,
const
char
*
help
)
{
this
->
AddArgument
(
argument
,
type
,
CommandLineArguments
::
STRING_TYPE
,
variable
,
help
);
}
//----------------------------------------------------------------------------
void
CommandLineArguments
::
AddArgument
(
const
char
*
argument
,
ArgumentTypeEnum
type
,
kwsys_stl
::
string
*
variable
,
const
char
*
help
)
{
this
->
AddArgument
(
argument
,
type
,
CommandLineArguments
::
STL_STRING_TYPE
,
variable
,
help
);
}
//----------------------------------------------------------------------------
void
CommandLineArguments
::
AddArgument
(
const
char
*
argument
,
ArgumentTypeEnum
type
,
bool
*
variable
,
const
char
*
help
)
{
this
->
AddArgument
(
argument
,
type
,
CommandLineArguments
::
BOOL_TYPE
,
variable
,
help
);
}
//----------------------------------------------------------------------------
void
CommandLineArguments
::
AddBooleanArgument
(
const
char
*
argument
,
bool
*
variable
,
const
char
*
help
)
{
this
->
AddArgument
(
argument
,
CommandLineArguments
::
NO_ARGUMENT
,
CommandLineArguments
::
BOOL_TYPE
,
variable
,
help
);
}
//----------------------------------------------------------------------------
void
CommandLineArguments
::
AddBooleanArgument
(
const
char
*
argument
,
int
*
variable
,
const
char
*
help
)
{
this
->
AddArgument
(
argument
,
CommandLineArguments
::
NO_ARGUMENT
,
CommandLineArguments
::
INT_TYPE
,
variable
,
help
);
}
//----------------------------------------------------------------------------
void
CommandLineArguments
::
SetClientData
(
void
*
client_data
)
{
this
->
Internals
->
ClientData
=
client_data
;
}
//----------------------------------------------------------------------------
void
CommandLineArguments
::
SetUnknownArgumentCallback
(
CommandLineArguments
::
ErrorCallbackType
callback
)
{
this
->
Internals
->
UnknownArgumentCallback
=
callback
;
}
//----------------------------------------------------------------------------
const
char
*
CommandLineArguments
::
GetHelp
(
const
char
*
arg
)
{
CommandLineArguments
::
Internal
::
CallbacksMap
::
iterator
it
=
this
->
Internals
->
Callbacks
.
find
(
arg
);
if
(
it
==
this
->
Internals
->
Callbacks
.
end
()
)
{
return
0
;
}
// Since several arguments may point to the same argument, find the one this
// one point to if this one is pointing to another argument.
CommandLineArguments
::
CallbackStructure
*
cs
=
&
(
it
->
second
);
while
(
1
)
{
CommandLineArguments
::
Internal
::
CallbacksMap
::
iterator
hit
=
this
->
Internals
->
Callbacks
.
find
(
cs
->
Help
);
if
(
hit
==
this
->
Internals
->
Callbacks
.
end
()
)
{
return
cs
->
Help
;
}
cs
=
&
(
hit
->
second
);
}
// Should never happened
return
0
;
}
//----------------------------------------------------------------------------
void
CommandLineArguments
::
GenerateHelp
()
{
kwsys_ios
::
ostringstream
str
;
// Collapse all arguments into the map of vectors of all arguments that do
// the same thing.
CommandLineArguments
::
Internal
::
CallbacksMap
::
iterator
it
;
typedef
kwsys_stl
::
map
<
CommandLineArguments
::
Internal
::
String
,
CommandLineArguments
::
Internal
::
SetOfStrings
>
MapArgs
;
MapArgs
mp
;
MapArgs
::
iterator
mpit
,
smpit
;
for
(
it
=
this
->
Internals
->
Callbacks
.
begin
();
it
!=
this
->
Internals
->
Callbacks
.
end
();
it
++
)
{
CommandLineArguments
::
CallbackStructure
*
cs
=
&
(
it
->
second
);
mpit
=
mp
.
find
(
cs
->
Help
);
if
(
mpit
!=
mp
.
end
()
)
{
mpit
->
second
.
insert
(
it
->
first
);
mp
[
it
->
first
].
insert
(
it
->
first
);
}
else
{
mp
[
it
->
first
].
insert
(
it
->
first
);
}
}
for
(
it
=
this
->
Internals
->
Callbacks
.
begin
();
it
!=
this
->
Internals
->
Callbacks
.
end
();
it
++
)
{
CommandLineArguments
::
CallbackStructure
*
cs
=
&
(
it
->
second
);
mpit
=
mp
.
find
(
cs
->
Help
);
if
(
mpit
!=
mp
.
end
()
)
{
mpit
->
second
.
insert
(
it
->
first
);
smpit
=
mp
.
find
(
it
->
first
);
CommandLineArguments
::
Internal
::
SetOfStrings
::
iterator
sit
;
for
(
sit
=
smpit
->
second
.
begin
();
sit
!=
smpit
->
second
.
end
();
sit
++
)
{
mpit
->
second
.
insert
(
*
sit
);
}
mp
.
erase
(
smpit
);
}
else
{
mp
[
it
->
first
].
insert
(
it
->
first
);
}
}
// Find the length of the longest string
CommandLineArguments
::
Internal
::
String
::
size_type
maxlen
=
0
;
for
(
mpit
=
mp
.
begin
();
mpit
!=
mp
.
end
();
mpit
++
)
{
CommandLineArguments
::
Internal
::
SetOfStrings
::
iterator
sit
;
for
(
sit
=
mpit
->
second
.
begin
();
sit
!=
mpit
->
second
.
end
();
sit
++
)
{
CommandLineArguments
::
Internal
::
String
::
size_type
clen
=
sit
->
size
();
switch
(
this
->
Internals
->
Callbacks
[
*
sit
].
ArgumentType
)
{
case
CommandLineArguments
::
NO_ARGUMENT
:
clen
+=
0
;
break
;
case
CommandLineArguments
::
CONCAT_ARGUMENT
:
clen
+=
6
;
break
;
case
CommandLineArguments
::
SPACE_ARGUMENT
:
clen
+=
7
;
break
;
case
CommandLineArguments
::
EQUAL_ARGUMENT
:
clen
+=
7
;
break
;
}
if
(
clen
>
maxlen
)
{
maxlen
=
clen
;
}
}
}
// Create format for that string
char
format
[
80
];
sprintf
(
format
,
"%%%ds"
,
static_cast
<
unsigned
int
>
(
maxlen
));
// Print help for each option
for
(
mpit
=
mp
.
begin
();
mpit
!=
mp
.
end
();
mpit
++
)
{
CommandLineArguments
::
Internal
::
SetOfStrings
::
iterator
sit
;
for
(
sit
=
mpit
->
second
.
begin
();
sit
!=
mpit
->
second
.
end
();
sit
++
)
{
str
<<
endl
;
char
argument
[
100
];
sprintf
(
argument
,
sit
->
c_str
());
switch
(
this
->
Internals
->
Callbacks
[
*
sit
].
ArgumentType
)
{
case
CommandLineArguments
::
NO_ARGUMENT
:
break
;
case
CommandLineArguments
::
CONCAT_ARGUMENT
:
strcat
(
argument
,
"option"
);
break
;
case
CommandLineArguments
::
SPACE_ARGUMENT
:
strcat
(
argument
,
" option"
);
break
;
case
CommandLineArguments
::
EQUAL_ARGUMENT
:
strcat
(
argument
,
"=option"
);
break
;
}
char
buffer
[
80
];
sprintf
(
buffer
,
format
,
argument
);
str
<<
buffer
;
}
str
<<
"
\t
"
;
const
char
*
ptr
=
this
->
Internals
->
Callbacks
[
mpit
->
first
].
Help
;
int
len
=
strlen
(
ptr
);
int
cnt
=
0
;
while
(
len
>
0
)
{
// If argument with help is longer than line length, split it on previous
// space (or tab) and continue on the next line
CommandLineArguments
::
Internal
::
String
::
size_type
cc
;
for
(
cc
=
0
;
ptr
[
cc
];
cc
++
)
{
if
(
*
ptr
==
' '
||
*
ptr
==
'\t'
)
{
ptr
++
;
len
--
;
}
}
if
(
cnt
>
0
)
{
for
(
cc
=
0
;
cc
<
maxlen
;
cc
++
)
{
str
<<
" "
;