/*
 * gcov_io_driver.c
 *
 *  Created on: 2023-2-6
 *      Author: Administrator
 */
#include "stdio.h"
#include "string.h"
#include "malloc.h"
#include "stdlib.h"
//###########################################################################################
//#include "tconfig.h"
#ifndef __GNUC_KF32__
#define __GNUC_KF32__
#endif
//###########################################################################################
#ifndef _FILE_DEFINED

  struct _iobuf {
    char *_ptr;
    int _cnt;

    char *_base;

    int _flag;
    int _file;
    int _charbuf;
    int _bufsiz;
    char *_tmpfname;
  };

  typedef struct _iobuf FILE;

#define _FILE_DEFINED

#endif
  //###########################################################################################
#ifdef __GNUC_KF32__

	#include "stdio.h"

	#ifdef stderr
	#undef stderr
	#endif
	#define stderr  USART2_STREAM

	#ifdef stdout
	#undef stdout
	#endif

	#define stdout  USART2_STREAM

	#define Use_Port_Select USART2_STREAM
#else
	#define USART0_STREAM 		stdout
	#define USART2_STREAM 		stderr
	#define Use_Port_Select 	stderr
#endif
  //###########################################################################################
FILE  _static_temp_File_;

//###########################################################################################
#ifdef __GNUC_KF32__
//***************************************************************
// Minimum sending serial port method of sample adapter chip
//***************************************************************
#define usartSlowRedeal() __asm__("MOV R0,#0x04;\n\tSUB R0,#1;\n\tJNZ $-1");

__attribute__((noinline)) __attribute__((optimize("-O2")))
int  putchar (int c)
{
  (void)c;
  //###############################
  //USART        USARTx_TBUFR
  volatile unsigned int* deref=( unsigned int*)USART0_STREAM;
  asm("DSI");
  deref[3] =c;
  while( 	(deref[2]&(1<<13))  !=0	);
  while( 	(deref[2]&(1<<13)) 	==0	);
  usartSlowRedeal();
  asm("ENI");
  return 0;
}

__attribute__((noinline)) __attribute__((optimize("-O2")))
int  fputchar   (int c,STREAM *stream)
{
//USART         USARTx_TBUFR

  volatile unsigned int* deref=( unsigned int*)stream;
  asm("DSI");
  deref[3] =c;
  while( 	(deref[2]&(1<<13))  !=0	);
  while( 	(deref[2]&(1<<13)) 	==0	);
  usartSlowRedeal();
  asm("ENI");
  return 0;
}
#endif
//###########################################################################################
__attribute__((optimize("-O2")))
FILE* kfv_fopen(const char *name,const char *mode) {
#ifdef __GNUC_KF32__
	//format to parse
	fprintf(stderr,"\n\n#$@gcda:%s\r\n",name);
	memset(	(void*)&_static_temp_File_,	(int)0,	sizeof(_static_temp_File_) );
	return (FILE*)&_static_temp_File_;
#else	
	fprintf(stderr,"\n@driver open file:%s,mode:%s\r\n",name,mode);
	return fopen(name,mode);
#endif
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
__attribute__((optimize("-O2")))
int kfv_fclose(FILE * f) {
#ifdef __GNUC_KF32__
	//fprintf(stderr,"\n@driver close file\r\n");
	memset( (void*)&_static_temp_File_,(int)0, sizeof(FILE) );
#else
	fprintf(stdout,"\n@driver close file\r\n");
	fclose(f);
#endif
	return 1;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
__attribute__((optimize("-O2")))
void kfv_setbuf(FILE *stream, char *buffer)
{
#ifdef __GNUC_KF32__
	//fprintf(stderr,"\n@driver setbuf \r\n");
	stream->_ptr=buffer;
#else
	fprintf(stdout,"\n@driver setbuf \r\n");
	setbuf(stream,buffer);
#endif
}
//###########################################################################################
__attribute__((optimize("-O2")))
int kfv_fwrite(char* buffer,unsigned int size,int block,FILE* fp) {
	unsigned int wsize=size * block;

#ifdef __GNUC_KF32__
	fprintf(stderr,"\n@write length:%d\r\n",wsize);
	while(wsize) {
		//MY_MSG("%c",*buffer);
		fputchar(*buffer,stderr);
		buffer++;
		wsize--;
	}
#else
	fprintf(stdout,"\n@driver write file:%s,length:%d\r\n",buffer,wsize);
	wsize=fwrite(buffer,size,block,fp);
#endif	
	return 1;
}

__attribute__((optimize("-O2")))
int kfv_fread(char* buffer, unsigned int size, unsigned int block, FILE* infile) {
	int wsize=size * block;
	int readoutlength=0;
#ifdef __GNUC_KF32__
	//fprintf(stderr,"\n@driver read file:%s,length:%d\r\n",buffer,wsize);
	return 0;
#else		
	readoutlength =  fread(buffer,size,block,infile);
	fprintf(stdout,"\n@driver read file:%s,bufferlength:%d,readout %d\r\n",buffer,wsize,readoutlength);
	return readoutlength;
#endif
}
//###########################################################################################
__attribute__((optimize("-O2")))
unsigned int kfv_ftell(FILE * file) {
#ifdef __GNUC_KF32__
	//fprintf(stderr,"\n@driver tell file %d\r\n",0);
	return 0;
#else
	int l = ftell(file);
	fprintf(stdout,"\n@driver tell file %d\r\n",l);
	return l;
#endif
}

__attribute__((optimize("-O2")))
void kfv_fseek(FILE *fp,int offset, int mode) {
#ifdef __GNUC_KF32__
	//fprintf(stderr,"\n@driver seek file:%d\r\n",offset);
#else
	fprintf(stdout,"\n@driver seek file:%d\r\n",offset);
	
	fseek (fp, offset, mode);
#endif
	return ;
}
//###########################################################################################
//***************************************************************
//The list of registered exit functions and empty exit functions are not designed, and gcov prints the active call__ gcov_ Exit() function
//***************************************************************
//typedef void (*void_Funciton) (void);
//
//typedef struct void_Funciton_List {
//	void_Funciton function;
//	struct void_Funciton_List *next;
//} void_Funciton_List;
//
//
//void_Funciton_List *  Head_Exit_Function=0;
//void_Funciton_List *  Cur_Exit_Function=0;
//void_Funciton_List *  temp_Exit_Function=0;
//
//void kfv_atexit(void (*pf)(void)) {
//	if(Head_Exit_Function == 0) {
//		Head_Exit_Function=(void_Funciton_List *)malloc(sizeof(void_Funciton_List));
//		Head_Exit_Function->function = pf;
//		Head_Exit_Function->next=0;
//		Cur_Exit_Function = Head_Exit_Function;
//	} else {
//		temp_Exit_Function=(void_Funciton_List *)malloc(sizeof(void_Funciton_List));
//		temp_Exit_Function->function=pf;
//		temp_Exit_Function->next=0;
//		Cur_Exit_Function->next=temp_Exit_Function;
//		Cur_Exit_Function=temp_Exit_Function;
//	}
//}
//#############################################################################

