/* * Copyright 2000 Perforce Software. All rights reserved. * * This file is part of Perforce - the FAST SCM System. */ /* * SIOUXTool.cc - Standalone Command Line Tool for the Macintosh * * The purpose of this tool is to create a command-line client * that can stand on its own without MPW. * * In its current incarnation, the tool only reponds to AppleEvents * you can send it AppleEvents to set Environment Variables and to * run Perforce Commands * */ // // TABS in this file are set to 4 // // // This file cannot be compiled unless the target is for the Macintosh // #ifdef OS_MAC #include <SIOUX.h> #include <SIOUXGlobals.h> #include <clientapi.h> #include <strarray.h> #include <strtable.h> #define kPerforceAESuite 'p4cs' #define kPerforceMainMethodEvent 'main' #define kPerforceSetEnvEvent 'stev' #define kPerforceP4Event 'p4cm' #define ZeroAEDesc(x) x.descriptorType = NULL; \ x.dataHandle = NULL /****************************************************************************** ** ** ** PUBLIC FUNCTION DECLARATIONS ** ** ** *****************************************************************************/ int getArgsFromStrArray( StrArray * array, unsigned int *argc, char *** argv ); int tool_main( int argc, char **argv ); void SetupAppleEventHandlers( void ); StrArray * GetArgVFromAppleEvent( const AppleEvent * theAppleEvent); pascal OSErr HandleMainMethod( const AppleEvent *theAppleEvent, AppleEvent *reply, long myRefCon ); pascal OSErr HandleSetEnv( const AppleEvent *theAppleEvent, AppleEvent *reply, long myRefCon ); pascal OSErr HandleQuit( const AppleEvent *theAppleEvent, AppleEvent *reply, long myRefCon ); pascal OSErr HandleP4Method( const AppleEvent *theAppleEvent, AppleEvent *reply, long myRefCon ); void printArgs( unsigned int argc, char ** argv ); /****************************************************************************** ** ** ** GLOBALS ** ** ** *****************************************************************************/ // // The Apple Events work by just placing a request for a command in these global // variables for retrieval from the main loop. // static char ** gArgv = NULL; static unsigned int gArgc = 0; static bool quitting = false; // This determines if the program should exit static StrBufDict environment; // The "environment" for this process /*===========================================================================*\ * * Routine: getenv() * * Comments: Simulates an actual environment variable space with the use * of the global variable, "environment". * * This call overrides the call that is in Metrowerks * standard library for the mac. * \*===========================================================================*/ extern "C" { char * getenv(const char * name) { StrPtr *temp = environment.GetVar( name ); if ( temp ) { return temp->Text(); } else { return NULL; } } } /*===========================================================================*\ * * Routine: main() * * Comments: The entry point for the program. * \*===========================================================================*/ int main() { // // If we don't set this, the SIOUX window will just // sit there until we choose Quit from the fle menu. // The asktosaveonclose stops SIOUX from asking whether // or not to save the contents of console window. // SIOUXSettings.autocloseonquit = true; SIOUXSettings.asktosaveonclose = false; SIOUXSettings.userwindowtitle = "\pP4"; // SIOUXSettings.showstatusline = true; // // This ensures that if we don't receive any AppleEvents // to set the environment, we can pick it out of a // <name>=<value> delimited file called p4.config // in the current directory (likely the same dir as the app) // environment.SetVar( "P4CONFIG", "p4.config" ); // // This merely starts up the SIOUX console and starts the // SIOUX Event handling to happen. You have to print // something to get it up because it is lazy. // fprintf(stderr, "\n"); // // Register our AppleEvents // SetupAppleEventHandlers(); // // Main event loop // // While SIOUX doesn't want to quit and we don't want // to quit, run the loop. // while ( !SIOUXQuitting && !quitting ) { SIOUXHandleOneEvent(NULL); // // wait until we get some args from the apple event // if (gArgc) { // // print the arguments to the console // printArgs( gArgc, gArgv ); printf( "\n" ); // // Pass it off to the Perforce Client "engine" // tool_main( gArgc, gArgv ); // // Clean up // delete gArgv; gArgv = NULL; gArgc = 0; } } return 0; } /*===========================================================================*\ * * Routine: GetArgVFromAppleEvent() * * Comments: Gets an array of string arguments from an Apple Event. * * Of course, you can only pass in Apple Events that take a * list of typeChar records as their direct parameter. * \*===========================================================================*/ StrArray * GetArgVFromAppleEvent( const AppleEvent *theAppleEvent) { AEKeyword keyword; AEDescList docList; long numberOfDocuments, i; DescType returnedType; Size actualSize; char argTempStorage[1024]; char *javaPath = NULL; StrArray * args = new StrArray(); OSErr err = noErr; // // (1) Paths to all the files dragged on me. // { // // Get the list of files // if ((err = AEGetParamDesc( theAppleEvent, keyDirectObject, typeAEList, &docList)) != noErr) goto bail; // // How many documents were dropped on us? // if ((err = AECountItems( &docList, &numberOfDocuments)) != noErr) goto bail; // // Iterate through them // for ( i = 1; i <= numberOfDocuments; i++ ) { // // Get the i"th" item as a string // if ((err = AEGetNthPtr( &docList, i, typeChar, &keyword, &returnedType, (Ptr)argTempStorage, 1024, &actualSize)) != noErr) goto bail; // // Null the end of the string // argTempStorage[actualSize] = NULL; // // add it to the returned StringArray // { StrBuf * temp = args->Put(); temp->Set( argTempStorage ); } } // // clean up // err = AEDisposeDesc(&docList); } return args; bail: // // clean up // err = AEDisposeDesc(&docList); return args; } /*===========================================================================*\ * * Routine: getArgsFromStrArray() * * Comments: Converts a String Array into the argument format suitable * for "main" methods. * * Allocates all the memory for you. * \*===========================================================================*/ int getArgsFromStrArray( StrArray * array, unsigned int *argc, char *** argv ) { unsigned int i = 0; // // Allocate an array of char * to use in argv // char ** tempArgv = (char **)malloc( array->Count() * sizeof(char*) ); // // for each item in array, copy it to a string in argv // for ( i = 0; i < array->Count(); i++ ) { // // Get a reference to the current item in array // const StrBuf * temp = array->Get( i ); // // Allocate and initialize memory for string // tempArgv[i] = (char *)malloc( temp->Length() + 1 ); tempArgv[i][0] = NULL; // // Copy the memory out of array // strcpy( tempArgv[i], temp->Text()); } // // Set up our return values // *argc = array->Count(); *argv = tempArgv; return 1; } /*===========================================================================*\ * * Routine: printArgs() * * Comments: Prints a set of arguments to the command line. * * Puts quotes around args with spaces in them * \*===========================================================================*/ void printArgs( unsigned int argc, char ** argv ) { int i = 0; for ( i = 0; i < argc; i++ ) { if ( strchr( argv[i], ' ' ) ) { printf( "\"%s\" ", gArgv[i] ); } else { printf( "%s ", gArgv[i] ); } } printf( "\n" ); } /*===========================================================================*\ * * Routine: tool_main() * * Comments: The main method into the perforce client engine. * * This code taken realy verbatim from the Readme for the API. * \*===========================================================================*/ int tool_main( int argc, char **argv ) { ClientUser ui; ClientApi client; Error e; // Connect to server client.Init( &e ); e.Abort(); // Run the command "argv[1] argv[2...]" client.SetArgv( argc - 2, argv + 2 ); client.Run( argv[1], &ui ); // Close connection client.Final( &e ); e.Abort(); return 0; } /*===========================================================================*\ * * Routine: HandleQuit() * * Comments: Handles receiving a QuitApplication AppleEvent. * \*===========================================================================*/ pascal OSErr HandleQuit( const AppleEvent *theAppleEvent, AppleEvent *reply, long myRefCon ) { theAppleEvent; reply; myRefCon; // unused quitting = true; return noErr; } /*===========================================================================*\ * * Routine: HandleMainMethod() * * Comments: Handles receiving a Execute Main method AppleEvent. * \*===========================================================================*/ pascal OSErr HandleMainMethod( const AppleEvent *theAppleEvent, AppleEvent *reply, long myRefCon ) { OSErr err = 0; StrArray * array = NULL; reply; myRefCon; // unused // // Get the args out of the AppleEvent // array = GetArgVFromAppleEvent(theAppleEvent); // // copy the arguments to our global variables // getArgsFromStrArray( array, &gArgc, &gArgv ); return err; } /*===========================================================================*\ * * Routine: HandleP4Method() * * Comments: Handles receiving a P4 method AppleEvent. * \*===========================================================================*/ pascal OSErr HandleP4Method( const AppleEvent *theAppleEvent, AppleEvent *reply, long myRefCon ) { OSErr err = 0; StrArray theArgs; StrArray * array = NULL; reply; myRefCon; // unused // // Get the args out of the AppleEvent // array = GetArgVFromAppleEvent(theAppleEvent); theArgs.Put()->Set( "p4" ); int i; for ( i = 0; i < array->Count(); i++ ) { theArgs.Put()->Set( array->Get( i ) ); } // // copy the arguments to our global variables // getArgsFromStrArray( &theArgs, &gArgc, &gArgv ); return err; } /*===========================================================================*\ * * Routine: HandleSetEnv() * * Comments: Handles receiving a SetEnv method AppleEvent. * * A SetEnv AppleEvent is sent to change the environment for * our standard C app. * \*===========================================================================*/ pascal OSErr HandleSetEnv( const AppleEvent *theAppleEvent, AppleEvent *reply, long myRefCon ) { OSErr err = 0; StrArray * array = NULL; reply; myRefCon; // unused // // Get the args out of the AppleEvent // array = GetArgVFromAppleEvent(theAppleEvent); // // Check to see if they passed us invalid arguments // if ( array->Count() < 1 ) { return -1; } else if ( array->Count() < 2 ) { // // We were passed only one parameter so set only one parameter // environment.SetVar( array->Get(0)->Text() ); // printf( "setenv( %s, NULL )\n", array->Get(0)->Text() ); } else { // // Set both a name/value pair // environment.SetVar( array->Get(0)->Text(), array->Get(1) ); if ( strcmp( array->Get(0)->Text(), "P4PASSWD" ) ) { // printf( "setenv( %s, %s )\n", array->Get(0)->Text(), array->Get(1)->Text() ); } else { // printf( "setenv( %s, [hey, it's a secret] )\n", array->Get(0)->Text() ); } } delete array; return err; } /*===========================================================================*\ * * Routine: SetupAppleEventHandlers() * * Comments: Registers our AppleEventHandler Callbacks. * \*===========================================================================*/ void SetupAppleEventHandlers( void ) { AEEventHandlerUPP ExecHandler; AEEventHandlerUPP P4Handler; AEEventHandlerUPP SetEnvHandler; AEEventHandlerUPP QuitHandler; ExecHandler = NewAEEventHandlerUPP( HandleMainMethod ); P4Handler = NewAEEventHandlerUPP( HandleP4Method ); SetEnvHandler = NewAEEventHandlerUPP( HandleSetEnv ); QuitHandler = NewAEEventHandlerUPP( HandleQuit ); // // install the event handers // AEInstallEventHandler( kPerforceAESuite, kPerforceP4Event, P4Handler, 0, false ); AEInstallEventHandler( kPerforceAESuite, kPerforceMainMethodEvent, ExecHandler, 0, false ); AEInstallEventHandler( kPerforceAESuite, kPerforceSetEnvEvent, SetEnvHandler, 0, false ); AEInstallEventHandler( kCoreEventClass, kAEQuitApplication, QuitHandler, 0, false ); } #endif // OS_MAC
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#3 | 1092 | mbishop |
Synced in source from the mainline into siouxtool to make it similar to the internal version. Features added: New AppleEvent called "p4" Previously, in your AppleScripts, you would say, "main {"p4","client"}" Now, you are also able to say, "p4 {"client"}" They are identical and you are encouraged to discontinue using "main" and use "p4" instead. Syncing the source from the mainline also added in support for the source to be built under Carbon. |
||
#2 | 410 | Michael Bishop | Removed dependency on macutil.h | ||
#1 | 409 | Michael Bishop | Initial Checkin of SIOUX Gizmo |