/* /% C %/ */
/***********************************************************************
* WildCard , CINT + Tcl/Tk on Windows-NT/95
************************************************************************
* source file cintlib.c
************************************************************************
* Description:
* wildc.dll initialization
************************************************************************
* Copyright(c) 1996-1997 Masaharu Goto (MXJ02154@niftyserve.or.jp)
*
* This file is modified based on example.c from Tcl7.5/Tk4.1 binary
* distribution from Sun-Microsystems.
************************************************************************/
/*
* example.c --
*
* This file is an example of a Tcl dynamically loadable extension.
*
* Copyright (c) 1996 by Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* SCCS: @(#) example.c 1.4 96/04/26 10:42:55
*/
#include <tcl.h>
#undef G__SPECIALSTDIO
#include "G__ci.h"
#if defined(__WIN32__) || defined(G__WIN32)
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# undef WIN32_LEAN_AND_MEAN
/*
* VC++ has an alternate entry point called DllMain, so we need to rename
* our entry point.
*/
# if defined(_MSC_VER)
# define EXPORT(a,b) __declspec(dllexport) a b
# define DllEntryPoint DllMain
# else
# if defined(__BORLANDC__)
# define EXPORT(a,b) a _export b
# else
# define EXPORT(a,b) a b
# endif
# endif
#else
# define EXPORT(a,b) a b
#endif
/*
* Declarations for functions defined in this file.
*/
extern void G__add_setup_func(char *libname,G__incsetup func);
extern int G__security_recover(FILE* fout);
extern int G__process_cmd(char *cmd,char *prompt,int *more);
extern void G__c_setupwildc();
extern void WildCard_MainLoop();
extern void WildCard_Exit();
extern int WildCard_AllocConsole();
extern int WildCard_FreeConsole();
#ifdef G__OLDIMPLEMENTATION562
static int G__noconsole=1;
static int G__lockstdio=0;
extern FILE *G__stdout;
extern FILE *G__stderr;
extern FILE *G__stdin;
#endif
#ifdef G__OLDIMPLEMENTATION614
extern FILE *G__serr;
extern FILE *G__sout;
extern FILE *G__sin;
#endif
EXTERN EXPORT(int,Wildc_Init) _ANSI_ARGS_((Tcl_Interp *interp));
Tcl_Interp *interp;
/***************************************************************************
* G__concatcommand()
***************************************************************************/
int G__concatcommand(char *command,char *arg)
{
static int brace = 0;
static int doublequote = 0 ;
static int singlequote = 0 ;
static int pos = 0;
int i,len;
int backslash=0;
len = strlen(arg);
for(i=0;i<len;i++) {
switch(arg[i]) {
case '"':
if(0==singlequote) doublequote ^= 1;
break;
case '\'':
if(0==doublequote) singlequote ^= 1;
break;
case '{':
if(0==singlequote&&0==doublequote) ++brace;
break;
case '}':
if(0==singlequote&&0==doublequote) --brace;
break;
case '\\':
++i;
if(i==len) {
arg[i-1]=' ';
backslash=1;
}
break;
}
}
strcpy(command+pos,arg);
pos = strlen(command);
if(0==singlequote&&0==doublequote&&0==brace&&0==backslash) {
pos=0;
return(1);
}
else return(0);
}
/**********************************************************************
* G__TclInserted()
*
* Tcl/tk script can be inserted in a C/C++ source code. G__TclInserted
* is a callback function when #pragma tcl statement appears in C/C++.
*
* #pragma tcl [interp] <var1 <var2 <var3 <...>>>>
* -----------------------------------
* args
**********************************************************************/
void G__TclInserted(args)
char *args;
{
char line[G__LONGLINE];
char argbuf[G__LONGLINE];
int argn=0;
char *arg[G__MAXARG];
int code;
Tcl_Interp *localinterp = (Tcl_Interp*)NULL;
int flag;
char tempfilename[G__MAXFILENAME];
FILE *fp;
char command[G__LONGLINE];
int p;
/* pragma arguments */
char argbufb[G__ONELINE];
char *argv[G__MAXARG];
int argc=0;
int i;
G__value reg;
/*************************************************************
* execute tcl script only in following case
* prerun in global scope
* execution in function
*************************************************************/
G__set_asm_noverflow(0); /* Disable loop compilation */
if(0==G__get_no_exec() && 0==G__get_no_exec_compile() &&
((1==G__getPrerun() && -1==G__getFuncNow()) ||
(0==G__getPrerun() && -1!=G__getFuncNow()))){
flag=1;
}
else {
flag=0;
}
/*************************************************************
* parse '#pragma tcl' arguments
*************************************************************/
if(flag) {
/*************************************************************
* Split arguments
*************************************************************/
strcpy(argbufb,args);
G__split(args,argbufb,&argc,argv);
if(0==argc) {
WildCard_AllocConsole();
fprintf(G__getSerr(),"Error: %s\n",args);
G__genericerror(" Usage:#pragma tcl [interp] <var1 <var2 <var3<...>>>>");
G__setReturn(2);
return;
}
else {
/*************************************************************
* Get Tcl interp
*************************************************************/
localinterp = (Tcl_Interp*)G__int(G__calc(argv[1]));
if(!localinterp) localinterp = interp;
/*************************************************************
* Link Variable
*************************************************************/
for(i=2;i<=argc;i++) {
reg = G__calc(argv[i]);
if(reg.ref) {
switch(reg.type) {
case 'C':
Tcl_LinkVar(localinterp,argv[i],(char*)reg.ref,TCL_LINK_STRING);
break;
case 'i':
Tcl_LinkVar(localinterp,argv[i],(char*)reg.ref,TCL_LINK_INT);
break;
case 'd':
Tcl_LinkVar(localinterp,argv[i],(char*)reg.ref,TCL_LINK_DOUBLE);
break;
default:
WildCard_AllocConsole();
fprintf(G__getSerr()
,"Error: #pragma tcl, variable %s improper type"
,argv[i]);
G__genericerror(NULL);
G__setReturn(2);
while((--i)>0) Tcl_UnlinkVar(localinterp,argv[i]);
return;
}
}
else {
WildCard_AllocConsole();
fprintf(G__getSerr()
,"Error: #pragma tcl, variable %s can not get reference"
,argv[i]);
G__genericerror(NULL);
G__setReturn(2);
while((--i)>0) Tcl_UnlinkVar(localinterp,argv[i]);
return;
}
}
/*************************************************************
* get tmpnam for tmp file
*************************************************************/
}
}
/*************************************************************
* Read and Evaluate Tcl/Tk command
*************************************************************/
if(G__getDispsource()) WildCard_AllocConsole();
/* Read and copy Tcl statements until #pragma endtcl or EOF */
while((argn<2 || strcmp(arg[1],"#pragma")!=0 || strcmp(arg[2],"endtcl")!=0)
&& G__readline(G__getIfileFp(),line,argbuf,&argn,arg)) {
G__incIfileLineNumber();
if(G__getDispsource()) G__fprintf(G__getSerr(),"%s\n%-4d "
,arg[0],G__getIfileLineNumber());
if(0==argn || '#'!=arg[1][0]) {
if(flag) {
if(G__concatcommand(command,arg[0])) {
code=Tcl_Eval(localinterp,command);
if(TCL_OK!=code) {
WildCard_AllocConsole();
fprintf(G__getSerr(),"%s",localinterp->result);
G__printlinenum();
}
}
}
}
}
/*
if(flag) {
if(G__NOMAIN==G__getIsMain()) G__setIsMain(G__TCLMAIN);
}
*/
/*************************************************************
* Unlink variable
*************************************************************/
i=argc;
while(i>1) {
Tcl_UnlinkVar(localinterp,argv[i]);
--i;
}
/*************************************************************
* If source file ended without #pragma endtcl, Tcl/Tk's Event
* loop appears as frontend.
*************************************************************/
if((argn<2 || strcmp(arg[1],"#pragma")!=0 || strcmp(arg[2],"endtcl")!=0)) {
G__setPrerun(0);
G__setDebug(G__getDebugTrace());
G__setStep(G__getStepTrace());
G__setdebugcond();
/* WildCard_MainLoop(); */
}
}
/**********************************************************************
* G__cinttk_init()
*
* Add Tcl/Tk specific #pragma statement in cint parser.
**********************************************************************/
void G__cinttk_init()
{
G__addpragma("tcl",G__TclInserted);
}
/**********************************************************************
* C/C++ expression evaluater in the Tcl wrapper
*
* ceval [expression] => G__calc(expression)
**********************************************************************/
static int WildcCmd(clientData, localinterp, argc, argv)
ClientData clientData;
Tcl_Interp *localinterp;
int argc;
char **argv;
{
/*
* Note that we must be very careful not to use TCL_DYNAMIC here
* if we are compiling with a compiler other than Borland C++ 4.5
* because the malloc/free routines are different. Instead, we
* should explicitly set the free proc to point to the free()
* supplied with the run-time library used by the extension.
*/
FILE *fpstdout;
FILE *fpstderr;
FILE *fpstdin;
char *arg[] = { "cint" , "" };
interp=localinterp;
G__setothermain(2);
#ifndef G__OLDIMPLEMENTATION614
G__setautoconsole(1);
G__setmasksignal(1);
#endif
G__main(argc,argv);
#ifndef G__OLDIMPLEMENTATION614
G__security_recover(G__getSerr());
#else
G__security_recover(G__serr);
#endif
return TCL_OK;
}
/**********************************************************************
* C/C++ expression evaluater in the Tcl wrapper
*
* ceval [expression] => G__calc(expression)
**********************************************************************/
static int CevalCmd(clientdata,localinterp,argc,argv)
ClientData clientdata;
Tcl_Interp *localinterp;
int argc;
char *argv[];
{
G__value result;
char buf[G__LONGLINE];
char *p;
int i;
/***************************************************
* concatinate arguments
***************************************************/
p = buf;
*p='\0';
for (i=1;i<argc;i++) {
sprintf(p,"%s ",argv[i]);
p = p+strlen(p);
}
/***************************************************
* evaluate C/C++ expression by CINT
***************************************************/
result=G__calc(buf);
/***************************************************
* return result to Tcl interpreter
***************************************************/
switch(result.type) {
case 'd':
case 'f':
sprintf(buf,"%g",G__double(result));
break;
case 'C':
sprintf(buf,"%s",(char*)G__int(result));
break;
case '\0':
strcpy(buf,"NULL");
break;
default:
sprintf(buf,"%d",G__int(result));
break;
}
Tcl_SetResult(localinterp,buf,TCL_VOLATILE);
#ifndef G__OLDIMPLEMENTATION614
G__security_recover(G__getSerr());
#else
G__security_recover(G__serr);
#endif
return(TCL_OK);
}
/**********************************************************************
* C/C++ declaration
*
* cdecl [declaration] => G__process_cmd(expression)
**********************************************************************/
static int CdeclCmd(clientdata,localinterp,argc,argv)
ClientData clientdata;
Tcl_Interp *localinterp;
int argc;
char *argv[];
{
int result;
char buf[G__LONGLINE];
char *p;
int i;
char prompt[G__ONELINE];
int more=0;
/***************************************************
* concatinate arguments
***************************************************/
p = buf;
*p='{';
++p;
*p='\0';
for (i=1;i<argc;i++) {
sprintf(p,"%s ",argv[i]);
p = p+strlen(p);
}
*p=';';
++p;
*p='}';
++p;
*p='\0';
/***************************************************
* evaluate C/C++ expression by CINT
***************************************************/
result=G__process_cmd(buf,prompt,&more);
sprintf(buf,"%d",result);
Tcl_SetResult(localinterp,buf,TCL_VOLATILE);
#ifndef G__OLDIMPLEMENTATION614
G__security_recover(G__getSerr());
#else
G__security_recover(G__serr);
#endif
return(TCL_OK);
}
/*
*----------------------------------------------------------------------
*
* DllEntryPoint --
*
* This wrapper function is used by Windows to invoke the
* initialization code for the DLL. If we are compiling
* with Visual C++, this routine will be renamed to DllMain.
* routine.
*
* Results:
* Returns TRUE;
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
#ifdef __WIN32__
BOOL APIENTRY
DllEntryPoint(hInst, reason, reserved)
HINSTANCE hInst; /* Library instance handle. */
DWORD reason; /* Reason this function is being called. */
LPVOID reserved; /* Not used. */
{
switch (reason) {
case DLL_PROCESS_ATTACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
G__scratch_all();
break;
}
return TRUE;
}
#endif
/*
*----------------------------------------------------------------------
*
* Example_Init --
*
* This procedure initializes the example command.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
EXPORT(int,Wildc_Init)(localinterp)
Tcl_Interp *localinterp;
{
char *arg[] = { "cint" , "" };
interp=localinterp;
Tcl_CreateCommand(localinterp, "wildc", WildcCmd, NULL, NULL);
Tcl_CreateCommand(localinterp, "ceval", CevalCmd, NULL, NULL);
Tcl_CreateCommand(localinterp, "cdecl",CdeclCmd,NULL,NULL);
G__add_setup_func("CINTLIB",G__c_setupwildc);
G__setothermain(2);
#ifndef G__OLDIMPLEMENTATION614
G__setautoconsole(1);
G__setmasksignal(1);
#endif
G__main(1,arg);
return Tcl_PkgProvide(localinterp, "cint", "1.0");
}
/**********************************************************************
* cintfront()
* WindCard_MainLoop()
*
* Tcl/Tk Event Loop and CINT prompt switched by SIGINT
**********************************************************************/
static void cintfront(sigdmy)
int sigdmy;
{
/* signal(SIGINT,cintfront); */
while(0==G__pause());
/* signal(SIGINT,cintfront); */
fprintf(stdout,"%% ");
fflush(stdout);
}
void WildCard_MainLoop() {
/* signal(SIGINT,cintfront); */
G__init_process_cmd();
Tk_MainLoop();
}
/**********************************************************************
* WildCard_Exit();
*
* Tcl/Tk Event Loop and CINT prompt switched by SIGINT
**********************************************************************/
void WildCard_Exit() {
/*
* Don't exit directly, but rather invoke the Tcl "exit" command.
* This gives the application the opportunity to redefine "exit"
* to do additional cleanup.
*/
static int flag=0;
if(0==flag) {
flag=1;
G__scratch_all();
Tcl_Eval(interp, "exit");
exit(1);
}
}
#if 1
/**************************************************************************
* Create new console window and re-open stdio ports
**************************************************************************/
/**************************************************************************
* WildCard_AllocConsole()
**************************************************************************/
int WildCard_AllocConsole()
{
#ifndef G__OLDIMPLEMENTATION562
return(G__AllocConsole());
#else
BOOL result=TRUE;
if(G__noconsole) {
result=FreeConsole();
result = AllocConsole();
SetConsoleTitle("WILDC++(CINT-Tcl/Tk)");
if(TRUE==result) {
G__stdout=G__sout=freopen("CONOUT$","w",stdout);
G__stderr=G__serr=freopen("CONOUT$","w",stderr);
G__stdin=G__sin=freopen("CONIN$","r",stdin);
}
G__noconsole=0;
}
return result;
#endif
}
/**************************************************************************
* WildCard_FreeConsole()
**************************************************************************/
int WildCard_FreeConsole()
{
#ifndef G__OLDIMPLEMENTATION562
return(G__FreeConsole());
#else
int result;
if(!G__noconsole && !G__lockstdio) {
G__noconsole=1;
result=FreeConsole();
}
else {
result=FALSE;
}
return result;
#endif
}
#ifdef G__OLDIMPLEMENTATION562
/**************************************************************************
* G__printf()
**************************************************************************/
int G__printf(char *fmt,...)
{
int result;
va_list argptr;
va_start(argptr,fmt);
G__lockstdio=1;
if(G__noconsole) WildCard_AllocConsole();
result = vprintf(fmt,argptr);
G__lockstdio=0;
va_end(argptr);
return(result);
}
/**************************************************************************
* G__fprintf()
**************************************************************************/
int G__fprintf(FILE *fp,char *fmt,...)
{
int result;
va_list argptr;
va_start(argptr,fmt);
G__lockstdio=1;
if(stdout==fp||stderr==fp) {
if(G__noconsole) WildCard_AllocConsole();
}
result = vfprintf(fp,fmt,argptr);
G__lockstdio=0;
va_end(argptr);
return(result);
}
/**************************************************************************
* G__fputc()
**************************************************************************/
int G__fputc(int character,FILE *fp)
{
int result;
G__lockstdio=1;
if(stdout==fp||stderr==fp) {
if(G__noconsole) WildCard_AllocConsole();
}
result=fputc(character,fp);
G__lockstdio=0;
return(result);
}
/**************************************************************************
* G__putchar()
**************************************************************************/
int G__putchar(int character)
{
int result;
G__lockstdio=1;
if(G__noconsole) WildCard_AllocConsole();
result=putchar(character);
G__lockstdio=0;
return(result);
}
/**************************************************************************
* G__fputs()
**************************************************************************/
int G__fputs(char *string,FILE *fp)
{
int result;
G__lockstdio=1;
if(stdout==fp||stderr==fp) {
if(G__noconsole) WildCard_AllocConsole();
}
result=fputs(string,fp);
G__lockstdio=0;
return(result);
}
/**************************************************************************
* G__puts()
**************************************************************************/
int G__puts(char *string)
{
int result;
G__lockstdio=1;
if(G__noconsole) WildCard_AllocConsole();
result=puts(string);
G__lockstdio=0;
return(result);
}
/**************************************************************************
* G__fgets()
**************************************************************************/
char *G__fgets(char *string,int n,FILE *fp)
{
char *result;
G__lockstdio=1;
if(fp==stdin) {
if(G__noconsole) WildCard_AllocConsole();
}
result=fgets(string,n,fp);
G__lockstdio=0;
return(result);
}
/**************************************************************************
* G__gets()
**************************************************************************/
char *G__gets(char *buffer)
{
char *result;
G__lockstdio=1;
if(G__noconsole) WildCard_AllocConsole();
result=gets(buffer);
G__lockstdio=0;
return(result);
}
#endif /* ON562 */
#else /* following case is never used */
/**************************************************************************
* STDIO function emulated by Tcl puts
**************************************************************************/
#define G__DISP1
/**************************************************************************
* G__TclDisplay()
**************************************************************************/
int G__TclDisplay(char *string)
{
#if defined(G__DISP2)
char com[G__ONELINE];
char *p;
static int stat=1;
static int line=0;
if(stat) {
sprintf(com,"text .G__text -relief raised -bd 2");
Tcl_Eval(interp,com);
sprintf(com,"pack .G__text");
Tcl_Eval(interp,com);
stat=0;
}
p = strchr(string,'\n');
if(p) {
++line;
if(line>15) {
line=0;
sprintf(com,".G__text delete 1.0 end");
Tcl_Eval(interp,com);
}
}
sprintf(com,".G__text insert end {%s}",string);
Tcl_Eval(interp,com);
#elif defined(G__DISP1)
char com[G__LONGLINE];
sprintf(com,"puts -nonewline {%s}",string);
Tcl_Eval(interp,com);
#else
static char buf[G__LONGLINE];
static int pos=0;
char com[G__LONGLINE];
int i;
int len;
len=strlen(string);
for(i=0;i<len;i++) {
switch(string[i]) {
case '\n':
buf[pos]='\0';
sprintf(com,"puts {%s}",buf);
Tcl_Eval(interp,com);
pos=0;
break;
default:
buf[pos++] = string[i];
break;
}
}
#endif
return 1;
}
/**************************************************************************
* G__printf()
**************************************************************************/
int G__printf(char *fmt,...)
{
char buf[G__LONGLINE];
int result;
va_list argptr;
va_start(argptr,fmt);
result = vsprintf(buf,fmt,argptr);
va_end(argptr);
G__TclDisplay(buf);
return(result);
}
/**************************************************************************
* G__fprintf()
**************************************************************************/
int G__fprintf(FILE *fp,char *fmt,...)
{
char buf[G__LONGLINE];
int result;
va_list argptr;
va_start(argptr,fmt);
if(stdout==fp||stderr==fp) {
result = vsprintf(buf,fmt,argptr);
G__TclDisplay(buf);
}
else {
result = vfprintf(fp,fmt,argptr);
}
va_end(argptr);
return(result);
}
/**************************************************************************
* G__fputc()
**************************************************************************/
int G__fputc(int character,FILE *fp)
{
char buf[10];
if(stdout==fp||stderr==fp) {
sprintf(buf,"%c",character);
G__TclDisplay(buf);
}
else {
fputc(character,fp);
}
return(character);
}
/**************************************************************************
* G__putchar()
**************************************************************************/
int G__putchar(int character)
{
char buf[10];
sprintf(buf,"%c",character);
G__TclDisplay(buf);
return(character);
}
/**************************************************************************
* G__fputs()
**************************************************************************/
int G__fputs(char *string,FILE *fp)
{
if(stdout==fp||stderr==fp) {
G__TclDisplay(string);
}
else {
return(fputs(string,fp));
}
}
/**************************************************************************
* G__puts()
**************************************************************************/
int G__puts(char *string)
{
G__TclDisplay(string);
return(1);
}
/**************************************************************************
* G__fgets()
**************************************************************************/
char *G__fgets(char *string,int n,FILE *fp)
{
static int stat=1;
if(fp==stdin) {
if(stat) {
stat=0;
G__printf("Warning: fgets() can not use\n");
return("");
}
}
else {
return(fgets(string,n,fp));
}
}
/**************************************************************************
* G__gets()
**************************************************************************/
char *G__gets(char *buffer)
{
static int stat=1;
if(stat) {
stat=0;
G__printf("Warning: gets() can not use\n");
}
return("");
}
#endif /* G__SPECIALSTDIO */