/* A test program to demonstrate the direct variable interface to ARexx.
 * Opens a public port called "QuickSortPort" and then waits for REXX 
 * messages. The port stays open until a "CLOSE" command is received.
 * Usage:  run >NIL: quicksort
 * Then send commands from within ARexx by "address 'QuickSortPort' command"
 *
 *    This version for Manx. WGL
 */

#include "exec/exec.h"

#include "rexx/storage.h"
#include "rexx/rxslib.h"

#include <stdio.h>
#include <math.h>
#include <functions.h>


struct RexxLib *RexxSysBase;

extern LONG  CheckRexxMsg();
extern LONG  GetRexxMsg();
extern LONG  SetRexxMsg();

main(argc,argv)
int argc;
char **argv;
{
   struct MsgPort MyPort;
   struct RexxMsg *rmptr;
   LONG           test,quitflag,error;
   char           buffer[256];
   char           **strings = 0;
   char           *malloc();
   int            i,left,right,string_number;
   int            atoi(),cmp();
   STRPTR         value;
   
   RexxSysBase = (struct RexxLib *) OpenLibrary("rexxsyslib.library",0L);
   if (RexxSysBase == 0L) {
      printf("Bad News -- no REXX library\n");
      return(20L);
      }

   /* Initialize our message port   */
   InitPort(&MyPort,"QuickSortPort");

   /* Make the port public          */
   AddPort(&MyPort);

   for (;;) {                          /* wait for messages             */
      Wait(1L<<MyPort.mp_SigBit);
      rmptr = (struct RexxMsg *) GetMsg(&MyPort);



      /* Make sure it's a valid context */
      if (CheckRexxMsg(rmptr)) {
         
         if((test = strcmp(rmptr->rm_Args[0],"QSORT")) == 0) {

         /* Get left and right bounds of string array to be sorted       */
         /* when called from and exec program having added QuickSortPort */
         /* as a function host Arg[1] is QuickSortPort                   */
        
            left = atoi(rmptr->rm_Args[1]);
            right = atoi(rmptr->rm_Args[2]);
            string_number = right - left + 1;        
            strings = (char **)AllocMem((long)string_number*4,MEMF_PUBLIC|MEMF_CLEAR);
            if(strings==NULL) goto REPLY ;
            
            /* copy RexxVariable array into strings */
          
            for(i = left; i <= right;i++){

               /* put name of stem in buffer  */

               sprintf(buffer,"%s.%d",rmptr->rm_Args[3],i);

               /* Now get the string from the program */

               if(error = GetRexxVar(rmptr,buffer,&value)) goto REPLY;
 
               strings[i-left] = malloc(strlen((char*)value)+1);
               strcpy(strings[i-left],(char *)value);
            }
            
            /* Now sort the strings array */
           
            qs_string(strings,left-1,right-1) ;

            
               

         /* Put sorted array back in old stem variable */
          
            for(i = left; i <= right;i++){

               /* put name of stem in buffer  */

               sprintf(buffer,"%s.%d",rmptr->rm_Args[3],i);

               /* Now get the string from the program */

               error = SetRexxVar(rmptr,buffer,strings[i-left],(long)strlen(strings[i-left])); 
               if(error) goto REPLY;
               free(strings[i-left]);
               strings[i-left]=NULL;
            }



         }

      /* See whether it's the close command                             */
         else quitflag = test = strcmp(rmptr->rm_Args[0],"CLOSE");
      
      }

REPLY:

     /* send it back                  */
      if(test) {
         rmptr->rm_Result1 = 5L;
         rmptr->rm_Result2 = 1L;
      }
      else {
        rmptr->rm_Result1 = 0L;           /* return code                   */
        rmptr->rm_Result2 = 0L;           /* secondary result              */
      }
      ReplyMsg(rmptr); 

      
      if(strings) {
         for(i = 0 ; i< string_number; i++){
            if( strings[i] ) free(strings[i]);
         } 
         FreeMem(strings,(long)string_number*4L);
         strings = NULL;
      }
 
     if (quitflag == 0L) break;            /* all done?                     */
   }

   RemPort(&MyPort);                   /* unlink it                     */
   FreePort(&MyPort); 
                   /* release the port resources    */

   return(0L);
}

qs_string(item,left,right) 
char *item[];
int left,right;
{

   int i,j;
   char *x,*y;
   i = left; j=right;
   x = item[(left+right)/2];

   do {
     while(strcmpu(item[i],x) < 0 && i <right) i++;
     while(strcmpu(item[j],x) > 0 && j >left)  j--;
     
     if(i<=j) {
        y = item[i];
        item[i] = item[j];
        item[j] = y;
        i++;j--;
     }
   } while(i<=j);

   if(left<j) qs_string(item,left,j);
   if(i<right) qs_string(item,i,right);
}

strcmpu(s1,s2)
char *s1,*s2;
{  
   int swap = 1;
   char *temp;
  
   if (strlen(s1) < strlen(s2)){
      temp = s1;
      s1 = s2;
      s2 = temp;
      swap = -1;
   }

   while(*s1) {
      if(toupper(*s1) - toupper(*s2)) 
         return swap*(toupper(*s1) - toupper(*s2));
      else {
        s1++;
        s2++;
      }
   }
   return 0;
}
