/** C99 **/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <inttypes.h>
#include <stdbool.h>
#define APP_NAME "mywc"
#define APP_VERSION "0.01"
#define MAX_FNAMES 100+1
#define MAXLEN_OPTSSTR (2+1) /* max len for an option's short string*/
#define MAXLEN_OPTLSTR (20+1) /* max len for an option's long string */
#define MAXLEN_OPTDESC (128+1) /* max len for an option's description */
#define INFO_VERSION \
"%s (just for fun) %s\n" \
"Copyright (C) 2012 migf1\n" \
"This is free software. You may redistribute copies of it under the terms of\n"\
"the GNU General Public License <http://w...content-available-to-author-only...u.org/licenses/gpl.html>.\n" \
"There is NO WARRANTY, to the extent permitted by law.\n" \
"\n" \
"Written by migf1 <mig_f1@hotmail.com>"
#define INFO_USAGE \
"Usage: %s [OPTION]... [FILE]...\n" \
"Print newline, word, and byte counts for each FILE, and a total line if\n" \
"more than one FILE is specified. With no FILE, or when FILE is -,\n" \
"read standard input."
#define INFO_REPORT_BUGS "Report bugs to <mig_f1@hotmail.com>."
typedef uint16_t Bitmap16;
enum ErrId {
ERR_NOERROR = 0 ,
ERR_INTERNAL,
ERR_NOFILE,
ERR_RDFILE,
ERR_OPTINVALID,
ERR_OPTUNRECOG,
/* not an id, just their total count*/
MAXERRORS
} ;
enum OptionBit {
OBIT_NONE = 0x00 ,
OBIT_BCOUNT = ( 1 << 1 ) ,
OBIT_CCOUNT = ( 1 << 2 ) ,
OBIT_LCOUNT = ( 1 << 3 ) ,
OBIT_MAXLL = ( 1 << 4 ) ,
OBIT_WCOUNT = ( 1 << 5 ) ,
OBIT_HELP = ( 1 << 6 ) ,
OBIT_VERS = ( 1 << 7 )
} ;
enum OptionId {
OID_INVALID = - 1 ,
OID_BCOUNT = 0 ,
OID_CCOUNT,
OID_LCOUNT,
OID_MAXLL,
OID_WCOUNT,
OID_HELP,
OID_VERS,
/* not an id, just their total count*/
MAXOPTIONS
} ;
typedef struct Option {
Bitmap16 obit;
char sstr[ MAXLEN_OPTSSTR ] ; /* short string */
char lstr[ MAXLEN_OPTLSTR ] ; /* long string */
char desc[ MAXLEN_OPTDESC ] ; /* description */
} Option;
typedef struct Count {
uintmax_t nl; /* newlines count */
uintmax_t w; /* words count */
uintmax_t c, b; /* chars & bytes count */
uintmax_t maxlnlen; /* length of maximum line */
} Count;
/*********************************************************/ /**
* @brief Print a different error, according to the value of errid.
*************************************************************
*/
void print_error( enum ErrId errid, Option options[ ] )
{
switch ( errid )
{
case ERR_INTERNAL:
printf ( "%s: Internal error!\n " , APP_NAME
) ; break ;
case ERR_NOFILE:
printf ( "%s: No such file or directory\n " , APP_NAME
) ; break ;
case ERR_RDFILE:
printf ( "%s: File could not be read!\n " , APP_NAME
) ; break ;
case ERR_OPTINVALID:
printf ( "%s: invalid option\n " , APP_NAME
) ; printf ( "Try `%s %s' for more information.\n " , APP_NAME, options[ OID_HELP] .lstr ) ;
break ;
case ERR_OPTUNRECOG:
printf ( "%s: unrecognized option\n " , APP_NAME
) ; printf ( "Try `%s %s' for more information.\n " , APP_NAME, options[ OID_HELP] .lstr ) ;
break ;
case ERR_NOERROR:
printf ( "%s: no error\n " , APP_NAME
) ; break ;
case MAXERRORS:
default :
break ;
}
return ;
}
/*********************************************************/ /**
* @brief Print program-version information.
*************************************************************
*/
void print_version( void )
{
printf ( INFO_VERSION
, APP_NAME
, APP_VERSION
) ;
return ;
}
/*********************************************************/ /**
* @brief Print short & long aliases, and the description of all options.
*************************************************************
*/
void print_options( Option options[ ] )
{
for ( int i= 0 ; i < MAXOPTIONS; i++ )
{
options[ i] .sstr [ 0 ] ? options[ i] .sstr : " " ,
options[ i] .sstr [ 0 ] ? ", " : " " ,
options[ i] .lstr ,
options[ i] .desc ) ;
}
return ;
}
/*********************************************************/ /**
* @brief Display the help screen.
*************************************************************
*/
void print_help( Option options[ ] )
{
printf ( INFO_USAGE
, APP_NAME
) ; print_options( options ) ;
puts ( INFO_REPORT_BUGS
) ;
return ;
}
/*********************************************************/ /**
* @brief Print (one file's) counted elements.
*************************************************************
*/
bool print_counted(
const Count * count,
Bitmap16 obitmap,
Option options[ ] ,
FILE * fp,
const char * fname
)
{
if ( ! count || ! fp)
return false ;
if ( obitmap & OBIT_HELP ) {
print_help( options ) ;
goto ret_ok;
}
if ( obitmap & OBIT_VERS ) {
print_version( ) ;
goto ret_ok;
}
if ( obitmap & OBIT_LCOUNT )
printf ( "%-" PRIuMAX
"\t " , count
-> nl
) ; if ( obitmap & OBIT_WCOUNT )
printf ( "%-" PRIuMAX
"\t " , count
-> w
) ; if ( obitmap & OBIT_CCOUNT )
printf ( "%-" PRIuMAX
"\t " , count
-> c
) ;
if ( obitmap & OBIT_BCOUNT )
printf ( "%-" PRIuMAX
"\t " , count
-> b
) ; if ( obitmap & OBIT_MAXLL )
printf ( "%-" PRIuMAX
"\t " , count
-> maxlnlen
) ;
if ( stdin != fp && fname )
else
ret_ok:
return true ;
}
/*********************************************************/ /**
* @brief Print totals (of all files).
*************************************************************
*/
bool print_totals( const Count * totals, Bitmap16 obitmap )
{
if ( ! totals )
goto ret_fail;
if ( obitmap & OBIT_HELP || obitmap & OBIT_VERS )
goto ret_ok;
if ( obitmap & OBIT_LCOUNT )
printf ( "%-" PRIuMAX
"\t " , totals
-> nl
) ; if ( obitmap & OBIT_WCOUNT )
printf ( "%-" PRIuMAX
"\t " , totals
-> w
) ; if ( obitmap & OBIT_CCOUNT )
printf ( "%-" PRIuMAX
"\t " , totals
-> c
) ;
if ( obitmap & OBIT_BCOUNT )
printf ( "%-" PRIuMAX
"\t " , totals
-> b
) ; if ( obitmap & OBIT_MAXLL )
printf ( "%-" PRIuMAX
"\t " , totals
-> maxlnlen
) ;
ret_ok:
return true ;
ret_fail:
return false ;
}
/*********************************************************/ /**
* @brief True if filename exists, false otherwise.
*************************************************************
*/
bool f_exists( const char * fname)
{
FILE
* fp
= fopen ( fname
, "rb" ) ; if ( ! fp )
return false ;
return true ;
}
/*********************************************************/ /**
* @brief Convert an option alias (short or long string) into an option id.
*************************************************************
*/
enum OptionId ostr2oid( const char * ostr, Option options[ ] )
{
enum OptionId i;
if ( ! ostr || !* ostr )
return OID_INVALID;
for ( i= 0 ; i < MAXOPTIONS; i++ )
if ( 0 == strncmp ( ostr
, options
[ i
] .
sstr , MAXLEN_OPTSSTR
) || 0 == strncmp ( ostr
, options
[ i
] .
lstr , MAXLEN_OPTLSTR
) ) return i;
return OID_INVALID;
}
/*********************************************************/ /**
* @brief Update totals (after a file's elements have been counted).
*************************************************************
*/
bool refresh_totals( Count * totals, const Count * count )
{
if ( ! totals || ! count )
return false ;
totals-> nl += count-> nl;
totals-> w += count-> w;
totals-> b += count-> b;
totals-> maxlnlen += count-> maxlnlen;
return true ;
}
/*********************************************************/ /**
* @brief Count and store a file's elements.
*************************************************************
*/
bool fcount( FILE * fp, Count * count )
{
int c;
bool onword = false ;
uintmax_t lnchars = 0 ;
if ( ! fp || ! count )
return false ;
/* ensure everyting starts zeroed */
memset ( count
, 0 , sizeof ( Count
) ) ;
while ( ( c
= getc ( fp
) ) != EOF
) {
{
if ( '\n ' == c ) {
count-> nl++;
if ( count-> maxlnlen < -- lnchars)
count-> maxlnlen = lnchars;
lnchars = 0 ;
if ( onword ) {
count-> w++;
onword = false ;
}
}
else if ( onword ) {
count-> w++;
onword = false ;
}
}
else
onword = true ;
if ( c != '\n ' )
lnchars++;
count-> c++;
}
count-> b = count-> c / sizeof ( char ) ;
return true ;
}
/*********************************************************/ /**
* @brief Parse the command line arguments, and update accordingly
* a) the specified options (obitmap)
* b) the total numeber of specified filenames (nfiles)
* c) the names of the files (fnames: just pointers to proper argv[i]'s)
*************************************************************
*/
enum ErrId parse_cmdln_args(
char * argv[ ] ,
Option options[ ] ,
char * fnames[ MAX_FNAMES] ,
int * nfiles,
Bitmap16 * obitmap
)
{
int iarg = 1 , ifname = 0 ;
enum OptionId oid = OID_INVALID;
if ( ! obitmap || ! fnames || ! nfiles )
return ERR_INTERNAL;
/* ensure everything starts with default values */
memset ( fnames
, 0 , MAX_FNAMES
* sizeof ( char * ) ) ; * obitmap = OBIT_NONE;
for ( iarg = 1 ; argv[ iarg] ; iarg++ )
{
oid = ostr2oid( argv[ iarg] , options ) ;
if ( OID_INVALID == oid )
{
if ( 0 == strcmp ( "-" , argv
[ iarg
] ) || 0 == strcmp ( "--" , argv
[ iarg
] ) ) continue ;
if ( '-' == argv[ iarg] [ 0 ] ) {
if ( '-' == argv[ iarg] [ 1 ] )
return ERR_OPTUNRECOG;
return ERR_OPTINVALID;
}
if ( ! f_exists( argv[ iarg] ) )
return ERR_NOFILE;
if ( ifname < MAX_FNAMES- 1 )
fnames[ ifname++ ] = argv[ iarg] ;
}
else /* if ( OID_INVALID != oid ) */
* obitmap |= options[ oid] .obit ;
}
* nfiles = ifname;
if ( * obitmap & OBIT_HELP || * obitmap & OBIT_VERS )
return ERR_NOERROR;
if ( OBIT_NONE == * obitmap || 1 == iarg || 0 == * nfiles )
* obitmap = OBIT_LCOUNT + OBIT_WCOUNT + OBIT_BCOUNT;
return ERR_NOERROR;
}
/*********************************************************/ /**
*
*************************************************************
*/
int main( int argc, char * argv[ ] )
{
Option options[ MAXOPTIONS ] = {
/* bitflag sstr lstr desc */
{ OBIT_BCOUNT, "-c" , "--bytes" , "print the byte counts" } ,
{ OBIT_CCOUNT, "-m" , "--chars" , "print the character counts" } ,
{ OBIT_LCOUNT, "-l" , "--lines" , "print the newline counts" } ,
{ OBIT_MAXLL, "-L" , "--max-line-length" , "print the length of the longest line" } ,
{ OBIT_WCOUNT, "-w" , "--words" , "print the word counts" } ,
{ OBIT_HELP, "\0 " , "--help" , "display this help and exit" } ,
{ OBIT_VERS, "\0 " , "--version" , "output version information and exit" }
} ;
FILE * fp = NULL;
int nfiles = 0 ;
char * fnames[ MAX_FNAMES] = { NULL} ;
Bitmap16 obitmap = OBIT_LCOUNT + OBIT_WCOUNT + OBIT_BCOUNT;
Count count, totals;
enum ErrId errid = ERR_NOERROR;
errid = parse_cmdln_args( argv, options, fnames, & nfiles, & obitmap ) ;
if ( ERR_NOERROR != errid ) {
print_error( errid, options ) ;
goto ret_failure;
}
memset ( & totals
, 0 , sizeof ( Count
) ) ; for ( int i= 0 ; ; i++ )
{
if ( NULL == fnames[ i] )
{
if ( i == 0 )
fp = stdin;
else
break ;
}
else if ( NULL
== ( fp
= fopen ( fnames
[ i
] , "rb" ) ) ) { print_error( ERR_RDFILE, options ) ;
goto ret_failure;
}
if ( ! ( obitmap & OBIT_HELP) && ! ( obitmap & OBIT_VERS) )
fcount( fp, & count) ;
print_counted( & count, obitmap, options, fp, fnames[ i] ) ;
refresh_totals( & totals, & count) ;
if ( fp && fp != stdin )
}
if ( nfiles > 1 )
print_totals( & totals, obitmap ) ;
ret_failure:
if ( fp && fp != stdin )
}
LyoqIEM5OSAqKi8KCiNpbmNsdWRlIDxzdGRpby5oPgojaW5jbHVkZSA8c3RkbGliLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUgPGN0eXBlLmg+CiNpbmNsdWRlIDxpbnR0eXBlcy5oPgojaW5jbHVkZSA8c3RkYm9vbC5oPgoKI2RlZmluZQlBUFBfTkFNRQkibXl3YyIKI2RlZmluZQlBUFBfVkVSU0lPTgkiMC4wMSIKCiNkZWZpbmUgTUFYX0ZOQU1FUwkxMDArMQoKI2RlZmluZSBNQVhMRU5fT1BUU1NUUgkoMisxKQkJCS8qIG1heCBsZW4gZm9yIGFuIG9wdGlvbidzIHNob3J0IHN0cmluZyovCiNkZWZpbmUgTUFYTEVOX09QVExTVFIJKDIwKzEpCQkJLyogbWF4IGxlbiBmb3IgYW4gb3B0aW9uJ3MgbG9uZyBzdHJpbmcgKi8KI2RlZmluZSBNQVhMRU5fT1BUREVTQwkoMTI4KzEpCQkJLyogbWF4IGxlbiBmb3IgYW4gb3B0aW9uJ3MgZGVzY3JpcHRpb24gKi8KCiNkZWZpbmUgSU5GT19WRVJTSU9OCQkJCQkJCQkJXAoJIiVzIChqdXN0IGZvciBmdW4pICVzXG4iCQkJCQkJCVwKCSJDb3B5cmlnaHQgKEMpIDIwMTIgbWlnZjFcbiIJCQkJCQkJXAoJIlRoaXMgaXMgZnJlZSBzb2Z0d2FyZS4gIFlvdSBtYXkgcmVkaXN0cmlidXRlIGNvcGllcyBvZiBpdCB1bmRlciB0aGUgdGVybXMgb2ZcbiJcCgkidGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIDxodHRwOi8vdy4uLmNvbnRlbnQtYXZhaWxhYmxlLXRvLWF1dGhvci1vbmx5Li4udS5vcmcvbGljZW5zZXMvZ3BsLmh0bWw+LlxuIglcCgkiVGhlcmUgaXMgTk8gV0FSUkFOVFksIHRvIHRoZSBleHRlbnQgcGVybWl0dGVkIGJ5IGxhdy5cbiIJCQlcCgkiXG4iCQkJCQkJCQkJCVwKCSJXcml0dGVuIGJ5IG1pZ2YxIDxtaWdfZjFAaG90bWFpbC5jb20+IgoKI2RlZmluZSBJTkZPX1VTQUdFCQkJCQkJCQkJXAoJIlVzYWdlOiAlcyBbT1BUSU9OXS4uLiBbRklMRV0uLi5cbiIJCQkJCQlcCgkiUHJpbnQgbmV3bGluZSwgd29yZCwgYW5kIGJ5dGUgY291bnRzIGZvciBlYWNoIEZJTEUsIGFuZCBhIHRvdGFsIGxpbmUgaWZcbiIJXAoJIm1vcmUgdGhhbiBvbmUgRklMRSBpcyBzcGVjaWZpZWQuICBXaXRoIG5vIEZJTEUsIG9yIHdoZW4gRklMRSBpcyAtLFxuIgkJXAoJInJlYWQgc3RhbmRhcmQgaW5wdXQuIgoKI2RlZmluZSBJTkZPX1JFUE9SVF9CVUdTCSJSZXBvcnQgYnVncyB0byA8bWlnX2YxQGhvdG1haWwuY29tPi4iCgp0eXBlZGVmIHVpbnQxNl90IEJpdG1hcDE2OwoKZW51bSBFcnJJZCB7CglFUlJfTk9FUlJPUiA9IDAsCglFUlJfSU5URVJOQUwsCglFUlJfTk9GSUxFLAoJRVJSX1JERklMRSwKCUVSUl9PUFRJTlZBTElELAoJRVJSX09QVFVOUkVDT0csCgkvKiBub3QgYW4gaWQsIGp1c3QgdGhlaXIgdG90YWwgY291bnQqLwoJTUFYRVJST1JTCn07CgplbnVtIE9wdGlvbkJpdCB7CglPQklUX05PTkUJPSAweDAwLAoJT0JJVF9CQ09VTlQJPSAoMSA8PCAxKSwKCU9CSVRfQ0NPVU5UCT0gKDEgPDwgMiksCglPQklUX0xDT1VOVAk9ICgxIDw8IDMpLAoJT0JJVF9NQVhMTAk9ICgxIDw8IDQpLAoJT0JJVF9XQ09VTlQJPSAoMSA8PCA1KSwKCU9CSVRfSEVMUAk9ICgxIDw8IDYpLAoJT0JJVF9WRVJTCT0gKDEgPDwgNykKfTsKCmVudW0gT3B0aW9uSWQgewoJT0lEX0lOVkFMSUQgCT0gLTEsCglPSURfQkNPVU5UIAk9IDAsCglPSURfQ0NPVU5ULAoJT0lEX0xDT1VOVCwKCU9JRF9NQVhMTCwKCU9JRF9XQ09VTlQsCglPSURfSEVMUCwKCU9JRF9WRVJTLAoJLyogbm90IGFuIGlkLCBqdXN0IHRoZWlyIHRvdGFsIGNvdW50Ki8KCU1BWE9QVElPTlMKfTsKCnR5cGVkZWYgc3RydWN0IE9wdGlvbiB7CglCaXRtYXAxNiAJb2JpdDsKCWNoYXIgCQlzc3RyWyBNQVhMRU5fT1BUU1NUUiBdOwkJLyogc2hvcnQgc3RyaW5nICovCgljaGFyIAkJbHN0clsgTUFYTEVOX09QVExTVFIgXTsJCS8qIGxvbmcgc3RyaW5nICovCgljaGFyIAkJZGVzY1sgTUFYTEVOX09QVERFU0MgXTsJCS8qIGRlc2NyaXB0aW9uICovCn1PcHRpb247Cgp0eXBlZGVmIHN0cnVjdCBDb3VudCB7Cgl1aW50bWF4X3Qgbmw7CQkvKiBuZXdsaW5lcyBjb3VudCAqLwoJdWludG1heF90IHc7CQkvKiB3b3JkcyBjb3VudCAgICAqLwoJdWludG1heF90IGMsIGI7CQkvKiBjaGFycyAmIGJ5dGVzIGNvdW50ICAgICovCgl1aW50bWF4X3QgbWF4bG5sZW47CS8qIGxlbmd0aCBvZiBtYXhpbXVtIGxpbmUgKi8KfUNvdW50OwoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8vKioKICogQGJyaWVmCVByaW50IGEgZGlmZmVyZW50IGVycm9yLCBhY2NvcmRpbmcgdG8gdGhlIHZhbHVlIG9mIGVycmlkLgogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKi8Kdm9pZCBwcmludF9lcnJvciggZW51bSBFcnJJZCBlcnJpZCwgT3B0aW9uIG9wdGlvbnNbXSApCnsKCXN3aXRjaCAoIGVycmlkICkKCXsKCQljYXNlIEVSUl9JTlRFUk5BTDoKCQkJcHJpbnRmKCAiJXM6IEludGVybmFsIGVycm9yIVxuIiwgQVBQX05BTUUgKTsKCQkJYnJlYWs7CgoJCWNhc2UgRVJSX05PRklMRToKCQkJcHJpbnRmKCAiJXM6IE5vIHN1Y2ggZmlsZSBvciBkaXJlY3RvcnlcbiIsIEFQUF9OQU1FICk7CgkJCWJyZWFrOwoKCQljYXNlIEVSUl9SREZJTEU6CgkJCXByaW50ZiggIiVzOiBGaWxlIGNvdWxkIG5vdCBiZSByZWFkIVxuIiwgQVBQX05BTUUgKTsKCQkJYnJlYWs7CgoJCWNhc2UgRVJSX09QVElOVkFMSUQ6CgkJCXByaW50ZiggIiVzOiBpbnZhbGlkIG9wdGlvblxuIiwgQVBQX05BTUUgKTsKCQkJcHJpbnRmKCAiVHJ5IGAlcyAlcycgZm9yIG1vcmUgaW5mb3JtYXRpb24uXG4iLAoJCQkJQVBQX05BTUUsIG9wdGlvbnNbT0lEX0hFTFBdLmxzdHIgKTsKCQkJYnJlYWs7CgoJCWNhc2UgRVJSX09QVFVOUkVDT0c6CgkJCXByaW50ZiggIiVzOiB1bnJlY29nbml6ZWQgb3B0aW9uXG4iLCBBUFBfTkFNRSApOwoJCQlwcmludGYoICJUcnkgYCVzICVzJyBmb3IgbW9yZSBpbmZvcm1hdGlvbi5cbiIsCgkJCQlBUFBfTkFNRSwgb3B0aW9uc1tPSURfSEVMUF0ubHN0ciApOwoJCQlicmVhazsKCgkJY2FzZSBFUlJfTk9FUlJPUjoKCQkJcHJpbnRmKCAiJXM6IG5vIGVycm9yXG4iLCBBUFBfTkFNRSApOwoJCQlicmVhazsKCgkJY2FzZSBNQVhFUlJPUlM6CgkJZGVmYXVsdDoKCQkJYnJlYWs7Cgl9CgoJcHV0Y2hhcignXG4nKTsKCglyZXR1cm47Cn0KCgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLy8qKgogKiBAYnJpZWYJUHJpbnQgcHJvZ3JhbS12ZXJzaW9uIGluZm9ybWF0aW9uLgogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKi8Kdm9pZCBwcmludF92ZXJzaW9uKCB2b2lkICkKewoJcHJpbnRmKCBJTkZPX1ZFUlNJT04sIEFQUF9OQU1FLCBBUFBfVkVSU0lPTiApOwoJcHV0cygiXG4iKTsKCglyZXR1cm47Cn0KCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovLyoqCiAqIEBicmllZglQcmludCBzaG9ydCAmIGxvbmcgYWxpYXNlcywgYW5kIHRoZSBkZXNjcmlwdGlvbiBvZiBhbGwgb3B0aW9ucy4KICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICovCnZvaWQgcHJpbnRfb3B0aW9ucyggT3B0aW9uIG9wdGlvbnNbXSApCnsKCWZvciAoaW50IGk9MDsgaSA8IE1BWE9QVElPTlM7IGkrKykKCXsKCQlwcmludGYoICJcdCVzJXMlc1x0XHQlc1xuIiwKCQkJb3B0aW9uc1tpXS5zc3RyWzBdID8gb3B0aW9uc1tpXS5zc3RyIDogIiAgIiwKCQkJb3B0aW9uc1tpXS5zc3RyWzBdID8gIiwgIiA6ICIgICIsCgkJCW9wdGlvbnNbaV0ubHN0ciwKCQkJb3B0aW9uc1tpXS5kZXNjICk7Cgl9CgoJcmV0dXJuOwp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLy8qKgogKiBAYnJpZWYJRGlzcGxheSB0aGUgaGVscCBzY3JlZW4uCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqLwp2b2lkIHByaW50X2hlbHAoIE9wdGlvbiBvcHRpb25zW10gKQp7CglwcmludGYoIElORk9fVVNBR0UsIEFQUF9OQU1FICk7CglwdXRjaGFyKCdcbicpOwoJcHJpbnRfb3B0aW9ucyggb3B0aW9ucyApOwoJcHV0Y2hhcignXG4nKTsKCXB1dHMoIElORk9fUkVQT1JUX0JVR1MgKTsKCXB1dGNoYXIoJ1xuJyk7CgoJcmV0dXJuOwp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLy8qKgogKiBAYnJpZWYJUHJpbnQgKG9uZSBmaWxlJ3MpIGNvdW50ZWQgZWxlbWVudHMuCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqLwpib29sIHByaW50X2NvdW50ZWQoCgljb25zdCBDb3VudCAJKmNvdW50LAoJQml0bWFwMTYgCW9iaXRtYXAsCglPcHRpb24gCQlvcHRpb25zW10sCglGSUxFCQkqZnAsCgljb25zdCBjaGFyIAkqZm5hbWUKKQp7CglpZiAoICFjb3VudCB8fCAhZnApCgkJcmV0dXJuIGZhbHNlOwoKCWlmICggb2JpdG1hcCAmIE9CSVRfSEVMUCApIHsKCQlwcmludF9oZWxwKCBvcHRpb25zICk7CgkJZ290byByZXRfb2s7Cgl9CglpZiAoIG9iaXRtYXAgJiBPQklUX1ZFUlMgKSB7CgkJcHJpbnRfdmVyc2lvbiggKTsKCQlnb3RvIHJldF9vazsKCX0KCglpZiAoIG9iaXRtYXAgJiBPQklUX0xDT1VOVCApCgkJcHJpbnRmKCAiJS0iUFJJdU1BWCJcdCIsIGNvdW50LT5ubCApOwoJaWYgKCBvYml0bWFwICYgT0JJVF9XQ09VTlQgKQoJCXByaW50ZiggIiUtIlBSSXVNQVgiXHQiLCBjb3VudC0+dyApOwoJaWYgKCBvYml0bWFwICYgT0JJVF9DQ09VTlQgKQoJCXByaW50ZiggIiUtIlBSSXVNQVgiXHQiLCBjb3VudC0+YyApOwoKCWlmICggb2JpdG1hcCAmIE9CSVRfQkNPVU5UICkKCQlwcmludGYoICIlLSJQUkl1TUFYIlx0IiwgY291bnQtPmIgKTsKCWlmICggb2JpdG1hcCAmIE9CSVRfTUFYTEwgKQoJCXByaW50ZiggIiUtIlBSSXVNQVgiXHQiLCBjb3VudC0+bWF4bG5sZW4gKTsKCglpZiAoIHN0ZGluICE9IGZwICYmIGZuYW1lICkKCQlwdXRzKCBmbmFtZSApOwoJZWxzZQoJCXB1dGNoYXIoJ1xuJyk7CgpyZXRfb2s6CglyZXR1cm4gdHJ1ZTsKfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8vKioKICogQGJyaWVmCVByaW50IHRvdGFscyAob2YgYWxsIGZpbGVzKS4KICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICovCmJvb2wgcHJpbnRfdG90YWxzKCBjb25zdCBDb3VudCAqdG90YWxzLCBCaXRtYXAxNiBvYml0bWFwICkKewoJaWYgKCAhdG90YWxzICkKCQlnb3RvIHJldF9mYWlsOwoKCWlmICggb2JpdG1hcCAmIE9CSVRfSEVMUCB8fCBvYml0bWFwICYgT0JJVF9WRVJTICkKCQlnb3RvIHJldF9vazsKCglpZiAoIG9iaXRtYXAgJiBPQklUX0xDT1VOVCApCgkJcHJpbnRmKCAiJS0iUFJJdU1BWCJcdCIsIHRvdGFscy0+bmwgKTsKCWlmICggb2JpdG1hcCAmIE9CSVRfV0NPVU5UICkKCQlwcmludGYoICIlLSJQUkl1TUFYIlx0IiwgdG90YWxzLT53ICk7CglpZiAoIG9iaXRtYXAgJiBPQklUX0NDT1VOVCApCgkJcHJpbnRmKCAiJS0iUFJJdU1BWCJcdCIsIHRvdGFscy0+YyApOwoKCWlmICggb2JpdG1hcCAmIE9CSVRfQkNPVU5UICkKCQlwcmludGYoICIlLSJQUkl1TUFYIlx0IiwgdG90YWxzLT5iICk7CglpZiAoIG9iaXRtYXAgJiBPQklUX01BWExMICkKCQlwcmludGYoICIlLSJQUkl1TUFYIlx0IiwgdG90YWxzLT5tYXhsbmxlbiApOwoKCXB1dHMoInRvdGFsIik7CgoJcHV0Y2hhcignXG4nKTsKCnJldF9vazoKCXJldHVybiB0cnVlOwpyZXRfZmFpbDoKCXJldHVybiBmYWxzZTsKfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8vKioKICogQGJyaWVmCVRydWUgaWYgZmlsZW5hbWUgZXhpc3RzLCBmYWxzZSBvdGhlcndpc2UuCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqLwpib29sIGZfZXhpc3RzKGNvbnN0IGNoYXIgKmZuYW1lKQp7CglGSUxFICpmcCA9IGZvcGVuKGZuYW1lLCAicmIiKTsKCWlmICggIWZwICkKCQlyZXR1cm4gZmFsc2U7CgoJZmNsb3NlKGZwKTsKCXJldHVybiB0cnVlOwp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLy8qKgogKiBAYnJpZWYJQ29udmVydCBhbiBvcHRpb24gYWxpYXMgKHNob3J0IG9yIGxvbmcgc3RyaW5nKSBpbnRvIGFuIG9wdGlvbiBpZC4KICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICovCmVudW0gT3B0aW9uSWQgb3N0cjJvaWQoIGNvbnN0IGNoYXIgKm9zdHIsIE9wdGlvbiBvcHRpb25zW10gKQp7CgllbnVtIE9wdGlvbklkIGk7CgoJaWYgKCAhb3N0ciB8fCAhKm9zdHIgKQoJCXJldHVybiBPSURfSU5WQUxJRDsKCglmb3IgKGk9MDsgaSA8IE1BWE9QVElPTlM7IGkrKykKCQlpZiAoIDAgPT0gc3RybmNtcChvc3RyLCBvcHRpb25zW2ldLnNzdHIsIE1BWExFTl9PUFRTU1RSKQoJCXx8IDAgPT0gc3RybmNtcChvc3RyLCBvcHRpb25zW2ldLmxzdHIsIE1BWExFTl9PUFRMU1RSKSApCgkJCXJldHVybiBpOwoKCXJldHVybiBPSURfSU5WQUxJRDsKfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8vKioKICogQGJyaWVmCVVwZGF0ZSB0b3RhbHMgKGFmdGVyIGEgZmlsZSdzIGVsZW1lbnRzIGhhdmUgYmVlbiBjb3VudGVkKS4KICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICovCmJvb2wgcmVmcmVzaF90b3RhbHMoIENvdW50ICp0b3RhbHMsIGNvbnN0IENvdW50ICpjb3VudCApCnsKCWlmICggIXRvdGFscyB8fCAhY291bnQgKQoJCXJldHVybiBmYWxzZTsKCgl0b3RhbHMtPm5sIAkrPSBjb3VudC0+bmw7Cgl0b3RhbHMtPncgIAkrPSBjb3VudC0+dzsKCXRvdGFscy0+YiAgCSs9IGNvdW50LT5iOwoJdG90YWxzLT5tYXhsbmxlbiArPSBjb3VudC0+bWF4bG5sZW47CgoJcmV0dXJuIHRydWU7Cn0KCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovLyoqCiAqIEBicmllZglDb3VudCBhbmQgc3RvcmUgYSBmaWxlJ3MgZWxlbWVudHMuCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqLwpib29sIGZjb3VudCggRklMRSAqZnAsIENvdW50ICpjb3VudCApCnsKCWludCBjOwoJYm9vbCBvbndvcmQgPSBmYWxzZTsKCXVpbnRtYXhfdCBsbmNoYXJzID0gMDsKCglpZiAoICFmcCB8fCAhY291bnQgKQoJCXJldHVybiBmYWxzZTsKCgkvKiBlbnN1cmUgZXZlcnl0aW5nIHN0YXJ0cyB6ZXJvZWQgKi8KCW1lbXNldCggY291bnQsIDAsIHNpemVvZihDb3VudCkgKTsKCglvbndvcmQgPSAoYz1pc3NwYWNlKCBnZXRjKGZwKSApKSA/IGZhbHNlIDogdHJ1ZTsKCXVuZ2V0YyhjLCBmcCk7Cgl3aGlsZSAoIChjPWdldGMoZnApKSAhPSBFT0YgKQoJewoJCWlmICggaXNzcGFjZShjKSApCgkJewoJCQlpZiAoICdcbicgPT0gYyApIHsKCQkJCWNvdW50LT5ubCsrOwoJCQkJaWYgKGNvdW50LT5tYXhsbmxlbiA8IC0tbG5jaGFycykKCQkJCQljb3VudC0+bWF4bG5sZW4gPSBsbmNoYXJzOwoJCQkJbG5jaGFycyA9IDA7CgkJCQlpZiAoIG9ud29yZCApIHsKCQkJCQljb3VudC0+dysrOwoJCQkJCW9ud29yZCA9IGZhbHNlOwoJCQkJfQoJCQl9CgkJCWVsc2UgaWYgKCBvbndvcmQgKSB7CgkJCQljb3VudC0+dysrOwoJCQkJb253b3JkID0gZmFsc2U7CgkJCX0KCQl9CgkJZWxzZQoJCQlvbndvcmQgPSB0cnVlOwoKCQlpZiAoIGMgIT0gJ1xuJykKCQkJbG5jaGFycysrOwoJCWNvdW50LT5jKys7Cgl9CgoJY291bnQtPmIgPSBjb3VudC0+YyAvIHNpemVvZihjaGFyKTsKCglyZXR1cm4gdHJ1ZTsKfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8vKioKICogQGJyaWVmCVBhcnNlIHRoZSBjb21tYW5kIGxpbmUgYXJndW1lbnRzLCBhbmQgdXBkYXRlIGFjY29yZGluZ2x5CiAqCQlhKSB0aGUgc3BlY2lmaWVkIG9wdGlvbnMgKG9iaXRtYXApCiAqCQliKSB0aGUgdG90YWwgbnVtZWJlciBvZiBzcGVjaWZpZWQgZmlsZW5hbWVzIChuZmlsZXMpCiAqCQljKSB0aGUgbmFtZXMgb2YgdGhlIGZpbGVzIChmbmFtZXM6IGp1c3QgcG9pbnRlcnMgdG8gcHJvcGVyIGFyZ3ZbaV0ncykKICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICovCmVudW0gRXJySWQgcGFyc2VfY21kbG5fYXJncygKCWNoYXIgCSphcmd2W10sCglPcHRpb24gCW9wdGlvbnNbXSwKCWNoYXIgCSpmbmFtZXNbTUFYX0ZOQU1FU10sCglpbnQJKm5maWxlcywKCUJpdG1hcDE2ICpvYml0bWFwCikKewoJaW50IGlhcmcgPSAxLCBpZm5hbWUgPSAwOwoJZW51bSBPcHRpb25JZCBvaWQgPSBPSURfSU5WQUxJRDsKCglpZiAoICFvYml0bWFwIHx8ICFmbmFtZXMgfHwgIW5maWxlcyApCgkJcmV0dXJuIEVSUl9JTlRFUk5BTDsKCgkvKiBlbnN1cmUgZXZlcnl0aGluZyBzdGFydHMgd2l0aCBkZWZhdWx0IHZhbHVlcyAqLwoJbWVtc2V0KCBmbmFtZXMsIDAsIE1BWF9GTkFNRVMgKiBzaXplb2YoY2hhciAqKSApOwoJKm9iaXRtYXAgPSBPQklUX05PTkU7CgoJZm9yIChpYXJnID0gMTsgYXJndltpYXJnXTsgaWFyZysrICkKCXsKCQlvaWQgPSBvc3RyMm9pZCggYXJndltpYXJnXSwgb3B0aW9ucyApOwoJCWlmICggT0lEX0lOVkFMSUQgPT0gb2lkICkKCQl7CgkJCWlmICggMCA9PSBzdHJjbXAoICItIiwgYXJndltpYXJnXSkKCQkJfHwgMCA9PSBzdHJjbXAoICItLSIsIGFyZ3ZbaWFyZ10pICkKCQkJCWNvbnRpbnVlOwoKCQkJaWYgKCAnLScgPT0gYXJndltpYXJnXVswXSApIHsKCQkJCWlmICggJy0nID09IGFyZ3ZbaWFyZ11bMV0gKQoJCQkJCXJldHVybiBFUlJfT1BUVU5SRUNPRzsKCQkJCXJldHVybiBFUlJfT1BUSU5WQUxJRDsKCQkJfQoJCQlpZiAoICFmX2V4aXN0cyhhcmd2W2lhcmddKSApCgkJCQlyZXR1cm4gRVJSX05PRklMRTsKCgkJCWlmICggaWZuYW1lIDwgTUFYX0ZOQU1FUy0xICkKCQkJCWZuYW1lc1sgaWZuYW1lKysgXSA9IGFyZ3ZbaWFyZ107CgkJfQoJCWVsc2UgLyogaWYgKCBPSURfSU5WQUxJRCAhPSBvaWQgKSAqLwoJCQkqb2JpdG1hcCB8PSBvcHRpb25zW29pZF0ub2JpdDsKCX0KCgkqbmZpbGVzID0gaWZuYW1lOwoJaWYgKCAqb2JpdG1hcCAmIE9CSVRfSEVMUCB8fCAqb2JpdG1hcCAmIE9CSVRfVkVSUyApCgkJcmV0dXJuIEVSUl9OT0VSUk9SOwoKCWlmICggT0JJVF9OT05FID09ICpvYml0bWFwIHx8IDEgPT0gaWFyZyB8fCAwID09ICpuZmlsZXMgKQoJCSpvYml0bWFwID0gT0JJVF9MQ09VTlQgKyBPQklUX1dDT1VOVCArIE9CSVRfQkNPVU5UOwoKCXJldHVybiBFUlJfTk9FUlJPUjsKfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8vKioKICoKICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICovCmludCBtYWluKCBpbnQgYXJnYywgY2hhciAqYXJndltdICkKewoJT3B0aW9uIG9wdGlvbnNbIE1BWE9QVElPTlMgXSA9IHsKCQkvKiBiaXRmbGFnICAgIHNzdHIgIGxzdHIJCWRlc2MgKi8KCQl7T0JJVF9CQ09VTlQsICItYyIsICItLWJ5dGVzIiwJCSJwcmludCB0aGUgYnl0ZSBjb3VudHMifSwKCQl7T0JJVF9DQ09VTlQsICItbSIsICItLWNoYXJzIiwgCQkicHJpbnQgdGhlIGNoYXJhY3RlciBjb3VudHMifSwKCQl7T0JJVF9MQ09VTlQsICItbCIsICItLWxpbmVzIiwgCQkicHJpbnQgdGhlIG5ld2xpbmUgY291bnRzIn0sCgkJe09CSVRfTUFYTEwsICAiLUwiLCAiLS1tYXgtbGluZS1sZW5ndGgiLCJwcmludCB0aGUgbGVuZ3RoIG9mIHRoZSBsb25nZXN0IGxpbmUifSwKCQl7T0JJVF9XQ09VTlQsICAiLXciLCAiLS13b3JkcyIsIAkicHJpbnQgdGhlIHdvcmQgY291bnRzIn0sCgkJe09CSVRfSEVMUCwgICAgIlwwIiwgIi0taGVscCIsIAkJImRpc3BsYXkgdGhpcyBoZWxwIGFuZCBleGl0In0sCgkJe09CSVRfVkVSUywgICAgIlwwIiwgIi0tdmVyc2lvbiIsIAkib3V0cHV0IHZlcnNpb24gaW5mb3JtYXRpb24gYW5kIGV4aXQifQoJfTsKCglGSUxFIAkJKmZwID0gTlVMTDsKCWludAkJbmZpbGVzID0gMDsKCWNoYXIJCSpmbmFtZXNbTUFYX0ZOQU1FU10gPSB7TlVMTH07CglCaXRtYXAxNiAJb2JpdG1hcCA9IE9CSVRfTENPVU5UICsgT0JJVF9XQ09VTlQgKyBPQklUX0JDT1VOVDsKCUNvdW50IAkJY291bnQsIHRvdGFsczsKCWVudW0gRXJySWQJZXJyaWQgPSBFUlJfTk9FUlJPUjsKCgllcnJpZCA9IHBhcnNlX2NtZGxuX2FyZ3MoIGFyZ3YsIG9wdGlvbnMsIGZuYW1lcywgJm5maWxlcywgJm9iaXRtYXAgKTsKCWlmICggRVJSX05PRVJST1IgIT0gZXJyaWQgKSB7CgkJcHJpbnRfZXJyb3IoIGVycmlkLCBvcHRpb25zICk7CgkJZ290byByZXRfZmFpbHVyZTsKCX0KCgltZW1zZXQoICZ0b3RhbHMsIDAsIHNpemVvZihDb3VudCkgKTsKCWZvciAoaW50IGk9MDsgOyBpKysgKQoJewoJCWlmICggTlVMTCA9PSBmbmFtZXNbaV0gKQoJCXsKCQkJaWYgKGkgPT0gMCkKCQkJCWZwID0gc3RkaW47CgkJCWVsc2UKCQkJCWJyZWFrOwoJCX0KCQllbHNlIGlmICggTlVMTCA9PSAoZnAgPSBmb3BlbihmbmFtZXNbaV0sICJyYiIpKSApIHsKCQkJcHJpbnRfZXJyb3IoIEVSUl9SREZJTEUsIG9wdGlvbnMgKTsKCQkJZ290byByZXRfZmFpbHVyZTsKCQl9CgoJCWlmICggIShvYml0bWFwICYgT0JJVF9IRUxQKSAmJiAhKG9iaXRtYXAgJiBPQklUX1ZFUlMpICkKCQkJZmNvdW50KCBmcCwgJmNvdW50KTsKCQlwcmludF9jb3VudGVkKCAmY291bnQsIG9iaXRtYXAsIG9wdGlvbnMsIGZwLCBmbmFtZXNbaV0gKTsKCgkJcmVmcmVzaF90b3RhbHMoICZ0b3RhbHMsICZjb3VudCk7CgoJCWlmICggZnAgJiYgZnAgIT0gc3RkaW4gKQoJCQlmY2xvc2UoZnApOwoJfQoKCWlmICggbmZpbGVzID4gMSApCgkJcHJpbnRfdG90YWxzKCAmdG90YWxzLCBvYml0bWFwICk7CgoJZXhpdCggRVhJVF9TVUNDRVNTICk7CgpyZXRfZmFpbHVyZToKCWlmICggZnAgJiYgZnAgIT0gc3RkaW4gKQoJCWZjbG9zZShmcCk7CglleGl0KCBFWElUX0ZBSUxVUkUgKTsKfQo=