clientuserdbg.cc #1

  • //
  • guest/
  • perforce_software/
  • p4/
  • 2016-1/
  • client/
  • clientuserdbg.cc
  • View
  • Commits
  • Open Download .zip Download (4 KB)
/*
 * Copyright 1995, 1996 Perforce Software.  All rights reserved.
 *
 * This file is part of Perforce - the FAST SCM System.
 */

# include <stdhdrs.h>

# include <strbuf.h>
# include <strops.h>
# include <enviro.h>
# include <error.h>
# include <strarray.h>
# include <strdict.h>
# include <strtable.h>
# include <spec.h>
# include <options.h>

# include <filesys.h>

# include "clientuser.h"
# include "clientuserdbg.h"

/*
 * ClientUserDebug -- version of output that always to stdout
 */

void
ClientUserDebug::OutputError( const char *errBuf )
{
	OutputTag( "error", errBuf, strlen( errBuf ) );
}

void
ClientUserDebug::OutputInfo( char level, const char *data )
{
	switch( level )
	{
	default: OutputTag( "info", data, strlen( data ) ); break;
	case '1': OutputTag( "info1", data, strlen( data ) ); break;
	case '2': OutputTag( "info2", data, strlen( data ) ); break;
	}
}

void
ClientUserDebug::OutputText( const char *data, int length )
{
	OutputTag( "text", data, length );
}

void
ClientUserDebug::OutputTag( const char *tag, const char *data, int length )
{
	char *p;

	while( p = (char *)memchr( data, '\n', length ) )
	{
	    printf( "%s: ", tag );
	    fwrite( data, 1, p + 1 - data, stdout );
	    length -= p + 1 - data;
	    data = p + 1;
	}

	if( length )
	{
	    printf( "%s: ", tag );
	    fwrite( data, 1, length, stdout );
	    printf( "\n" );
	}
}

/*
 * ClientUserDebugMsg -- message debugging ("-e" global opt)
 */

void
ClientUserDebugMsg::Message( Error *err )
{
	ClientUserDebug::Message( err );

	// print error subcodes for each ErrorId

	ErrorId* id;
	for ( int i = 0 ; id = err->GetId( i ) ; i++ )
	    printf( "code%d %d (sub %d sys %d gen %d args %d sev %d uniq %d)\n",
		i,
		id->code,
		id->SubCode(),
		id->Subsystem(),
		id->Generic(),
		id->ArgCount(),
		id->Severity(),
		id->UniqueCode() );

	// use base ClientUser OutputStat/Info() to print dict

	ClientUser ui;
	if ( err->GetDict() )
	    ui.OutputStat( err->GetDict() );
}

/*
 * ClientUserFmt -- user-specified formatting ("-F" global opt)
 */

void
ClientUserFmt::Message( Error *err )
{
	OutputStat( err->GetDict() );
}

void
ClientUserFmt::OutputStat( StrDict *dict )
{
	if( !dict )
	    return;

	StrBuf out;
	StrOps::Expand2( out, *fmt, *dict );
	if( out.Length() )
	    printf( "%s\n", out.Text() );
}

/*
 * ClientUserMunge -- user-specified munging ("--field" global opt)
 */

ClientUserMunge::ClientUserMunge( Options &opts )
{
	// Get the list of field substitutions from the Options.
	
	const StrPtr *s;

	for( int i = 0 ; s = opts.GetValue( Options::Field, i ) ; i++ )
	    fields.Put( *s );
}

void 
ClientUserMunge::OutputStat( StrDict *dict )
{
	Munge( dict, &fields, this );
}

void
ClientUserMunge::Munge( StrDict *dict, StrPtrArray *fields, ClientUser *ui )
{
	StrPtr *specdef = dict->GetVar( "specdef" );
	if( !specdef )
	    return ui->OutputError( "This command did not return a spec."
				    "  Try 'p4 (spectype) -o'?\n" );

	Error e;

	// Build the spec.

	Spec spec( specdef->Text(), "", &e );
	if( e.Test() )
	    return ui->HandleError( &e );

	// Copy and modify the dict.

	StrBufDict d( *dict );
	StrBuf field, value;

	for( int i = 0 ; i < fields->Count() ; i++ )
	{
	    const StrPtr *s = fields->Get( i );
	    int plus = 0;

	    const char *eq = s->Contains( StrRef( "=" ) );
	    if( !eq || eq == s->Text() )
		return ui->OutputError( "Usage: --field Field=value\n" );

	    field.Set( s->Text(), eq - s->Text() );
	    if( field.Text()[ field.Length() - 1 ] == '+' )
	    {
		plus = 1;
		field.SetLength( field.Length() - 1 );
	    }
	    field.Terminate();

	    SpecElem *elem = spec.Find( field, &e );
	    if( !elem )
		return ui->HandleError( &e );

	    value.Clear();
	    int x = 0;

	    if( plus && !elem->IsList() )
	    {
		// Single entry, get existing.

		if( d.GetVar( field ) )
		    value.Append( d.GetVar( field ) );
	    }
	    if( elem->IsList() )
	    {
		// List entry, get index for last item.

		for( int j = 0 ; d.GetVar( field, j ) ; j++ )
		    x = j + 1;
	    }
	    if( x && !plus )
	    {
		// Go back and remove existing list items.

		StrBuf fn;
		StrNum y;
		while( x )
		{
		    x--;
		    fn = field;
		    y = x;
		    fn.Append( y.Text() );
		    d.RemoveVar( fn );
		}
	    }

	    value.Append( eq + 1 );
	    
	    if( elem->IsList() )
		d.SetVar( field, x, value );
	    else
	        d.ReplaceVar( field, value );
	}

	// Format spec.

	SpecDataTable data( &d );
	StrBuf result;
	spec.Format( &data, &result );

	ui->OutputText( result.Text(), result.Length() );
}
# Change User Description Committed
#1 19472 Liz Lam Initial add of the 2016.1 p4/p4api source code.