
/*
 *      Copyright (c) 2023, an unpublished work by CodeSecure, Inc.
 *                      ALL RIGHTS RESERVED
 *
 *      Copyright (c) 2005-2023, an unpublished work by GrammaTech, Inc.
 *                      ALL RIGHTS RESERVED
 *
 *      This software is furnished under a license and may be used and
 *      copied only in accordance with the terms of such license and the       
 *      inclusion of the above copyright notice.  This software or any
 *      other copies thereof may not be provided or otherwise made
 *      available to any other person.  Title to and ownership of the
 *      software is retained by CodeSecure, Inc.
 */

#ifdef __CODESONAR__


/* All files that use the Extension API must include csonar.h and
 * stdlib.h. */
#include <stdlib.h>
#include "csonar.h"
#include "my_iterator.h"


/* Define a new \link Extensions/Attributes.html attribute 
 * \endlink called validitychecked. 
 * We will use this to keep track of whether the my_iterator_IsValid
 * check has been performed since the last time the iterator was moved
 * (or initialized).*/

CSONAR_DEFINE_ATTRIBUTE(validitychecked);

it *my_iterator_New(void);

#define __CSURF_MARKER_LIBRARY_FUNCTION__ 1

/* The specially-named \link Extensions/Prototypes.html#csonar_replace
 * csonar_replace_my_iterator_New()\endlink will intercept 
 * all calls to my_iterator_New (and similarly for all other
 * procedures with names of the form csonar_replace_functionname).
 *
 * Note that the symbol \link
 * Extensions/Prototypes.html#csurf_marker_library_function
 * __CSURF_MARKER_LIBRARY_FUNCTION__ \endlink is defined
 * (as 1) before the definitions of the csonar_replace_*
 * functions. This marks them as LIBRARY FUNCTIONS: any warnings
 * triggered inside a replacement function will be reported at the
 * appropriate call site to that function, not inside the function
 * itself.*/

it *csonar_replace_my_iterator_New(void){

    /* The intercepting function should call the real my_iterator_New
     * so that the iterator is allocated exactly as it would have been
     * if the original call were not intercepted. Note that calls to
     * my_iterator_New from within the body of
     * csonar_replace_my_iterator_New are not intercepted, unlike
     * calls from anywhere else.*/
    it *i =  my_iterator_New();

    /* Since space for i was only just allocated, we have not yet had the
     * opportunity to call my_iterator_IsValid(i). Therefore, we set
     * the value of the validitychecked attribute of i to 0.*/
    csonar_set_validitychecked(i,0);
    return i;
}

void my_iterator_Init(it *i);
void csonar_replace_my_iterator_Init(it *i){
  csonar_set_validitychecked(i,0);
  my_iterator_Init(i);
}

void my_iterator_First(it *i);
void csonar_replace_my_iterator_First(it *i){
   csonar_set_validitychecked(i,0);
   my_iterator_First(i);
}

int my_iterator_Next(it *i);
int csonar_replace_my_iterator_Next(it *i){
   csonar_set_validitychecked(i,0);
   return my_iterator_Next(i);
}

int my_iterator_IsValid(it *i);
int csonar_replace_my_iterator_IsValid(it *i){
    /* my_iterator_IsValid(i) has been called, so we set the value of
     * the validitychecked attribute of i to 1.*/
    csonar_set_validitychecked(i,1);
    return my_iterator_IsValid(i);
}

int my_iterator_GetVal(it *i);
int csonar_replace_my_iterator_GetVal(it *i){
    /* Triggers a "validity not checked before GetVal" warning if the
     * current value of the validitychecked attribute of i is not 1,
     * since that would mean that i has not been checked with
     * my_iterator_IsValid since the last time the iterator was moved
     * (or initialized).*/
    csonar_trigger_m( csonar_get_validitychecked(i), "==", 0, 
                    "validity not checked before GetVal", "CI:1;GT_TESTING", csws_reliability );
    return my_iterator_GetVal(i);
}

void my_iterator_SetVal(it *i, int val);
void csonar_replace_my_iterator_SetVal(it *i, int val){
   my_iterator_SetVal(i,val);
}

#endif
