%{
   /* ----------------------------------------------------------------
    *   xlog_parser.y
    * $Header: xlog_parser.y,v 1.2 89/02/02 17:00:18 dillon Exp $ 
    *
    *   YACC parser source for testxlog.c
    *   (improvised from amiint parser code)
    * ----------------------------------------------------------------
    */
   
#include "testxlog.h"
   
#define BEGIN
#define END \
{ \
    fflush(stdout); \
    if (gc_pointer != NULL) { \
        free(gc_pointer); \
        gc_pointer = NULL;  \
    } \
    return; \
}

Pointer gc_pointer;

typedef union {
   int  Ival;
   TransactionId xidval;
} YYSTYPE;

%}

%token <Ival> COMMITXACT ABORTXACT CLEARXACT SHOW GET HELP RESET QUIT
%token <Ival> INDEX RANGE DIR
%token <Ival> LPAREN COMMA RPAREN SEMI QMARK
%token <Ival> INT
%token <xidval> XID
   
%start Commands

%nonassoc low
%nonassoc high

%%

Commands: Command Commands
   |
   ;

Command:
   CommitStmt
   | AbortStmt
   | ClearStmt
   | GetStmt
   | HelpStmt
   | ResetStmt
   | ShowStmt
   | QuitStmt
   ;

CommitStmt:
   COMMITXACT integerVal SEMI
        { BEGIN; 
          { TransactionId xid;
            xid = IntMakeXid($<Ival>2); gc_pointer = (Pointer) xid;
            TransactionIdCommit(xid);
          }
        END; }

   | COMMITXACT transactionId SEMI
        { BEGIN; TransactionIdCommit($<xidval>2); END; }
   ;


AbortStmt:
   ABORTXACT integerVal SEMI
        { BEGIN; 
          { TransactionId xid;
            xid = IntMakeXid($<Ival>2); gc_pointer = (Pointer) xid;
            TransactionIdAbort(xid);
          }
        END; }

   | ABORTXACT transactionId SEMI
        { BEGIN; TransactionIdAbort($<xidval>2); END; }
   ;

ClearStmt:
   CLEARXACT integerVal SEMI
        { BEGIN; 
          { TransactionId xid;
            xid = IntMakeXid($<Ival>2); gc_pointer = (Pointer) xid;
            TransactionIdSetInProgress(xid);
          }
        END; }

   | CLEARXACT transactionId SEMI
        { BEGIN; TransactionIdSetInProgress($<xidval>2); END; }
   ;

GetStmt:
   GET integerVal SEMI
         { BEGIN; 
	   { TransactionId xid;
             xid = IntMakeXid($<xidval>2); gc_pointer = (Pointer) xid;
	     GetTransactionStatus(xid);
	   }
	 END; }

   | GET transactionId SEMI
         { BEGIN; GetTransactionStatus($<xidval>2); END; }
   ;

HelpStmt:
   HELP
        { BEGIN; PrintCommands(); END; }
   | HELP SEMI
        { BEGIN; PrintCommands(); END; }
   | QMARK
        { BEGIN; PrintCommands(); END; }
   ;

ResetStmt:
   RESET
        { BEGIN; yyerrok; yyclearin; END; }
   ;

ShowStmt:
   SHOW transactionId SEMI
        { BEGIN; ShowLogBlockTuple($<xidval>2); END; }
        
   | SHOW integerVal SEMI
        { BEGIN; ShowLogBlockTupleByIndex($<Ival>2); END; }

   | SHOW INDEX SEMI
        { BEGIN; ShowEntireIndex(); END; }

   | SHOW RANGE integerVal COMMA integerVal SEMI
	{ BEGIN; ShowRangeIndex($<Ival>3, $<Ival>5); END; }

   | SHOW DIR transactionId SEMI
	{ BEGIN; ShowTimeDirectoryTuple($<Ival>3); END; }

   | SHOW DIR integerVal SEMI
	{ BEGIN; ShowTimeDirectoryTupleByIndex($<Ival>3); END; }

   | SHOW DIR LPAREN transactionId RPAREN SEMI
	{ BEGIN; ShowTimeBlockTuple($<xidval>4); END; }

   | SHOW DIR LPAREN integerVal COMMA integerVal RPAREN SEMI
	{ BEGIN; ShowTimeBlockTupleByIndex($<Ival>4, $<Ival>6); END; }

   ;
                
QuitStmt:
   QUIT
        { yywrap(); }
   | QUIT SEMI
        { yywrap(); }
   ;

transactionId:
   XID
        {
          TransactionId xid;
          xid = IntMakeXid(lval);
          $<xidval>$ = (TransactionId) xid;
          gc_pointer = (Pointer) xid;
        }
   ;

integerVal:
   INT
        {
          $<Ival>$ = lval;
        }
   ;

%%
   ;
/* ----------------------------------------------------------------
 *			     utilities
 * ----------------------------------------------------------------
 */

/* ----------------
 *      IntMakeXid
 * ----------------
 */
   
TransactionId FUNCTION
   IntMakeXid(i)
int i;
{
   TransactionId xid;
   TransactionIdValueData xidv;

   xid = (TransactionId) malloc(TransactionIdDataSize);
   xidv = i;
   TransactionIdValueSetTransactionId(&xidv, xid);

   return xid;
}

/* ----------------
 *      ShowEntireIndex
 * ----------------
 */
  
void FUNCTION
   ShowEntireIndex()
{
   SpamIndex index = GlobalLogControl->spamIndex;
   int start, end;

   start = 0;
   end = index->numberIndexTuples;
                
   PrintSpamIndex(GlobalLogControl, start, end);
}

/* ----------------
 *      ShowRangeIndex
 * ----------------
 */
  
void FUNCTION
   ShowRangeIndex(start, end)
int start, end;  
{
   PrintSpamIndex(GlobalLogControl, start, end);
}

/* ----------------------------------------------------------------
 *		   show log block tuple routines
 * ----------------------------------------------------------------
 */

/* ----------------
 *      IndexTupleShowLogBlockTuple
 * ----------------
 */

void FUNCTION
   IndexTupleShowLogBlockTuple(indextuple)
SpamIndexTuple indextuple;
{
   String tupleStr;
   LogBlockTuple logblocktuple;

   logblocktuple = (LogBlockTuple)
      IndexTupleGetLogBlockTuple(indextuple);
   tupleStr = (String)
      LogBlockTupleFormString(logblocktuple);
      
   puts("log block tuple\n");
   puts(tupleStr);
      
   pfree(tupleStr);      
}

/* ----------------
 *      ShowLogBlockTuple
 * ----------------
 */

void FUNCTION
   ShowLogBlockTuple(xid)
TransactionId xid;
{
   SpamKey key;
   SpamResult result;
  
   key = CreateSpamKey(INFO_TRANSACTIONID,
                      xid, TransactionIdDataSize);
   result = SearchSpamIndex(GlobalLogControl, key);
  
   if (result->status != SEARCH_SUCCESSFUL) {
      printf("\nsearch failed\n");
   } else {
      SpamIndexTuple indextuple;
      indextuple = (SpamIndexTuple) result->result;
      IndexTupleShowLogBlockTuple(indextuple);
   }
   pfree(result);
   pfree(key);
}

/* ----------------
 *      ShowLogBlockTupleByIndex
 * ----------------
 */

void FUNCTION
   ShowLogBlockTupleByIndex(i)
int i;
{
   SpamIndex index = GlobalLogControl->spamIndex;
   SpamIndexTuple indextuple;

   if (i == 0 || i >= index->numberIndexTuples) {
      puts("index out of bounds");
      return;
   }
      
   indextuple = (SpamIndexTuple)
      index->tupleTable[ i ];
   
   IndexTupleShowLogBlockTuple(indextuple);
}


/* ----------------------------------------------------------------
 *		show time directory tuple routines
 * ----------------------------------------------------------------
 */

/* ----------------
 *      IndexTupleShowTimeDirectoryTuple
 * ----------------
 */

void FUNCTION
   IndexTupleShowTimeDirectoryTuple(indextuple)
SpamIndexTuple indextuple;
{
   String tupleStr;
   TimeDirectoryTuple timeDirectoryTuple;

   timeDirectoryTuple = (TimeDirectoryTuple)
      indextuple->timeDirectoryTuple;
   tupleStr = (String)
      TimeDirectoryTupleFormString(timeDirectoryTuple);
      
   puts("time directory tuple\n");
   puts(tupleStr);
      
   pfree(tupleStr);      
}

/* ----------------
 *      ShowTimeDirectoryTuple
 * ----------------
 */

void FUNCTION
   ShowTimeDirectoryTuple(xid)
TransactionId xid;
{
   SpamKey key;
   SpamResult result;
  
   key = CreateSpamKey(INFO_TRANSACTIONID,
                      xid, TransactionIdDataSize);
   result = SearchSpamIndex(GlobalLogControl, key);
  
   if (result->status != SEARCH_SUCCESSFUL) {
      printf("\nsearch failed\n");
   } else {
      SpamIndexTuple indextuple;
      indextuple = (SpamIndexTuple) result->result;
      IndexTupleShowTimeDirectoryTuple(indextuple);
   }

   pfree(result);
   pfree(key);
}


/* ----------------
 *      ShowTimeDirectoryTupleByIndex
 * ----------------
 */

void FUNCTION
   ShowTimeDirectoryTupleByIndex(i)
int i;
{
   SpamIndex index = GlobalLogControl->spamIndex;
   SpamIndexTuple indextuple;

   if (i == 0 || i >= index->numberIndexTuples) {
      puts("index out of bounds");
      return;
   }
      
   indextuple = (SpamIndexTuple)
      index->tupleTable[ i ];
   
   IndexTupleShowTimeDirectoryTuple(indextuple);
}

/* ----------------------------------------------------------------
 *		   show time block tuple routines
 * ----------------------------------------------------------------
 */

/* ----------------
 *	IndexTupleShowTimeBlockTuple
 * ----------------
 */

void FUNCTION
   IndexTupleShowTimeBlockTuple(indextuple, tupindex)
SpamIndexTuple  indextuple;
Index		tupindex;
{
   String tupleStr;
   TimeDirectoryTuple dirtup;
   SpamBlockLocation location;
   TimeBlockTuple timeBlockTuple;

   dirtup = (TimeDirectoryTuple)
      indextuple->timeDirectoryTuple;

   location = TimeDirectoryTupleGetBlockLocation(dirtup, tupindex);
   
   timeBlockTuple = BlockLocationGetTimeBlockTuple(location);
   
   tupleStr = (String)
      TimeBlockTupleFormString(timeBlockTuple);
      
   puts(tupleStr);
   pfree(tupleStr);      
}

/* ----------------
 *	ShowTimeBlockTuple
 * ----------------
 */

void FUNCTION
   ShowTimeBlockTuple(xid)
TransactionId xid;
{
   SpamKey key;
   SpamResult result;
  
   key = CreateSpamKey(INFO_TRANSACTIONID,
                      xid, TransactionIdDataSize);
   result = SearchSpamIndex(GlobalLogControl, key);
  
   if (result->status != SEARCH_SUCCESSFUL) {
      printf("\nsearch failed\n");
   } else {
      SpamIndexTuple indextuple;
      TransactionId baseXid;
      Index tupindex;
      
      indextuple = (SpamIndexTuple) result->result;
      baseXid = (TransactionId) indextuple->key->data;
      tupindex = TransactionIdGetTimeDirectoryTupleIndex(xid, baseXid);
      
      IndexTupleShowTimeBlockTuple(indextuple, tupindex);
   }

   pfree(result);
   pfree(key);
}

/* ----------------
 *	ShowTimeBlockTupleByIndex
 * ----------------
 */

void FUNCTION
   ShowTimeBlockTupleByIndex(indindex, tupindex)
Index indindex;
Index tupindex;
{
   SpamIndex index = GlobalLogControl->spamIndex;
   SpamIndexTuple indextuple;

   if (indindex == 0 || indindex >= index->numberIndexTuples) {
      puts("index out of bounds");
      return;
   }
      
   indextuple = (SpamIndexTuple)
      index->tupleTable[ indindex ];
   
   IndexTupleShowTimeBlockTuple(indextuple, tupindex);   
}





/* ----------------
 *	GetTransactionStatus
 * ----------------
 */

void FUNCTION
   GetTransactionStatus(xid)
TransactionId xid;
{
   Time time;
   long longtime;
   String s;
   Boolean didCommit;

   if (!TransactionIdIsValid(xid)) {
      puts("invalid transaction id");
      return;
   }
      
   didCommit = (Boolean) TransactionIdDidCommit(xid);
   time = TransactionIdGetCommitTime(xid);

   Puts("transaction: ");
   
   if (didCommit) 
      Puts("[committed]");
   else
      Puts("[not committed]");

   if (time != InvalidTime) {
      longtime = time;
      s = (String) ctime(&longtime);
      Puts(s);
   } else
      Puts(" -invalid time- ");

   fflush(stdout);
}

/* ----------------
 *      PrintCommands
 * ----------------
 */

void FUNCTION
   PrintCommands()
{
   puts("\nwelcome to help");
   puts("    here is a list of commands. Note <xid>, <val> etc represent");
   puts("    sequences of digits to be considered unsigned integers");
   puts(" ");
   puts("commands:");
   puts("    commit $<xid> ;       - commits transaction <xid>");
   puts("    commit <val> ;        - same as commit $<xid>");
   puts("    abort  $<xid> ;       - aborts transaction <xid>");
   puts("    abort  <val> ;        - same as abort $<xid>");
   puts("    clear  $<xid> ;       - clears transaction <xid>");
   puts("    clear  <val> ;        - same as clear $<xid>");
   puts("    get    $<xid> ;	   - get status of transaction <xid>");
   puts("    get    <val> ;	   - same as get $<xid>");
   puts("    help [;]              - print this help message");
   puts("    ?                     - same as help");
   puts("    reset                 - clear yyerror conditions");
   puts("    show $<xid> ;         - show log block tup containing <xid>");
   puts("    show <val> ;          - show log block tup ref by index tup <val>");
   puts("    show index ;          - show all index tuples");
   puts("    show range <x>, <y> ; - show index tuples <x> through <y>");
   puts("    show dir $<xid> ;     - show time dir tup containing <xid>");
   puts("    show dir <val> ;      - show time dir tup ref by index tup <val>");
   puts("    quit [;]              - return to the shell");
   puts(" ");
   puts("command abbreviations:");
   puts("    c - commit    a - abort    cl - clear    g - get    s - show");
   puts("    q - quit      i - index    r - range     d - dir");
   puts(" ");
   puts("    comments begin with a '#' and end with a newline");
   puts(" ");
}
