- Fixes for FOCUS 2D
- Mapped fileeval to exe manager - Updates for TRICS file formats SKIPPED: psi/libpsi.a psi/sinqhmdriv.c psi/sinqhttp.c psi/tabledrive.c psi/tasscan.c psi/hardsup/asynsrv_utility.c psi/hardsup/sinqhm.c
This commit is contained in:
@ -21,6 +21,37 @@ The TAS requires the following initializations in its instrument file:
|
||||
<dt>MakeTasUB tasub
|
||||
<dd>Installs the TAS crystallographic calculation module into SICS. It will
|
||||
have the name tasub (recommended).
|
||||
<dt>MakeTasUB tasub a1 a2 mcv mch a3 a4 sgu sgl a5 a6 acv ach
|
||||
<dd>Installs the TAS crystallographic calculation module into SICS. It will
|
||||
have the name tasub (recommended). This versions allows to specifiy motor names for functions. If there is no motor for
|
||||
a function it can be replaced with a placeholder in the parameter list, like dummy. This is only allowed for the
|
||||
curvature motors. The motor functions:
|
||||
<dl>
|
||||
<dt>a1
|
||||
<dd>monochormator rotation
|
||||
<dt>a2
|
||||
<dd>monochromator two theta
|
||||
<dt>mcv
|
||||
<dd>monochromator vertical curvature
|
||||
<dt>mch
|
||||
<dd>monochromator horizontal curvature
|
||||
<dt>a3
|
||||
<dd> sample rotation
|
||||
<dt>a4
|
||||
<dd>sample tow theta
|
||||
<dt>sgu
|
||||
<dd>sample tilt
|
||||
<dt>sgl
|
||||
<dd>second sample tilt
|
||||
<dt>a5
|
||||
<dd>analyzer rotation
|
||||
<dt>a6
|
||||
<dd>analyzer two theta
|
||||
<dt>acv
|
||||
<dd>analyzer vertical curvature
|
||||
<dt>ach
|
||||
<dd>analyzer horizontal curvature
|
||||
</dl>
|
||||
<dt>MakeTasScan iscan tasub
|
||||
<dd>Installs the module with the TAS specific scan functions into SICS. The
|
||||
TAS implements its own data format resembling the ILL TAS data format.
|
||||
|
@ -58,7 +58,12 @@ most useful for SICS clients watching the progress of the experiment.
|
||||
<dt>exe append some text
|
||||
<dd> Appends a line with everything after append to the upload buffer
|
||||
<dt>exe save filename
|
||||
<dd>saves the recently uploaded buffer under filename on the SICS server.
|
||||
<dd>saves the recently uploaded buffer under filename on the SICS server. Does not overwrite
|
||||
existing files.
|
||||
<dt>exe forcesave filename
|
||||
<dd>saves the recently uploaded buffer under filename on the SICS server. Overwrites existing file.
|
||||
<dt>exe clearupload
|
||||
<dd>clears any pending upload operations.
|
||||
</dl>
|
||||
</P>
|
||||
</BODY>
|
||||
|
2
exe.w
2
exe.w
@ -171,6 +171,8 @@ int MakeExeManager(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int runExeBatchBuffer(void *pData, SConnection *pCon, SicsInterp *pSics,
|
||||
char *name);
|
||||
@}
|
||||
|
||||
@o exeman.i -d @{
|
||||
|
4
exebuf.h
4
exebuf.h
@ -1,5 +1,5 @@
|
||||
|
||||
#line 207 "exe.w"
|
||||
#line 209 "exe.w"
|
||||
|
||||
/**
|
||||
* Buffer handling code for the Exe Buffer batch file processing
|
||||
@ -89,7 +89,7 @@
|
||||
*/
|
||||
char *exeBufName(pExeBuf self);
|
||||
|
||||
#line 220 "exe.w"
|
||||
#line 222 "exe.w"
|
||||
|
||||
|
||||
#endif
|
||||
|
4
exebuf.i
4
exebuf.i
@ -1,5 +1,5 @@
|
||||
|
||||
#line 198 "exe.w"
|
||||
#line 200 "exe.w"
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Internal header file for the exe buffer module. Do not edit. This is
|
||||
@ -16,6 +16,6 @@ typedef struct __EXEBUF{
|
||||
int lineno;
|
||||
} ExeBuf;
|
||||
|
||||
#line 203 "exe.w"
|
||||
#line 205 "exe.w"
|
||||
|
||||
|
||||
|
39
exeman.c
39
exeman.c
@ -15,13 +15,13 @@
|
||||
#include <ctype.h>
|
||||
#include "fortify.h"
|
||||
#include "sics.h"
|
||||
#include "exebuf.h"
|
||||
#include "exeman.h"
|
||||
#include "sdynar.h"
|
||||
#include "dynstring.h"
|
||||
#include "lld.h"
|
||||
#include "exeman.i"
|
||||
#include "splitter.h"
|
||||
#include "exebuf.h"
|
||||
#include "exeman.i"
|
||||
#include "exeman.h"
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
static void KillExeMan(void *data){
|
||||
@ -175,9 +175,9 @@ static pDynString locateBatchBuffer(pExeMan self, char *name){
|
||||
DeleteDynString(result);
|
||||
return NULL;
|
||||
}
|
||||
/*-------------------------------------------------------------------*/
|
||||
/*--------------------------------------------------------------------*/
|
||||
static int runBatchBuffer(pExeMan self, SConnection *pCon,
|
||||
SicsInterp *pSics, char *name){
|
||||
SicsInterp *pSics, char *name){
|
||||
pDynString filePath = NULL;
|
||||
char pBueffel[256];
|
||||
pExeBuf buffer = NULL;
|
||||
@ -214,6 +214,17 @@ static int runBatchBuffer(pExeMan self, SConnection *pCon,
|
||||
self->exeStackPtr--;
|
||||
return status;
|
||||
}
|
||||
/*-------------------------------------------------------------------*/
|
||||
int runExeBatchBuffer(void *pData, SConnection *pCon,
|
||||
SicsInterp *pSics, char *name){
|
||||
int status, oldEcho;
|
||||
pExeMan self = (pExeMan)pData;
|
||||
oldEcho = self->echo;
|
||||
self->echo = 1;
|
||||
status = runBatchBuffer(self,pCon,pSics,name);
|
||||
self->echo = oldEcho;
|
||||
return status;
|
||||
}
|
||||
/*========================== path management ========================*/
|
||||
static int handleBatchPath(pExeMan self, SConnection *pCon, int argc,
|
||||
char *argv[]){
|
||||
@ -374,6 +385,18 @@ static int startUpload(pExeMan self, SConnection *pCon){
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------*/
|
||||
static int clearUpload(pExeMan self, SConnection *pCon){
|
||||
if(SCGetRights(pCon) > usUser){
|
||||
SCWrite(pCon,"ERROR: no permission to clear buffer upload",eError);
|
||||
return 0;
|
||||
}
|
||||
if(self->uploadBuffer != NULL){
|
||||
exeBufDelete(self->uploadBuffer);
|
||||
self->uploadBuffer = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static int appendLine(pExeMan self, SConnection *pCon,
|
||||
int argc, char *argv[]){
|
||||
@ -958,6 +981,12 @@ int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
SCSendOK(pCon);
|
||||
}
|
||||
return status;
|
||||
}else if(strcmp(argv[1],"clearupload") == 0){
|
||||
status = clearUpload(self,pCon);
|
||||
if(status){
|
||||
SCSendOK(pCon);
|
||||
}
|
||||
return status;
|
||||
}else if(strcmp(argv[1],"info") == 0){
|
||||
status = infoHandler(self,pCon,argc,argv);
|
||||
return status;
|
||||
|
2
exeman.h
2
exeman.h
@ -13,5 +13,7 @@ int MakeExeManager(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int runExeBatchBuffer(void *pData, SConnection *pCon, SicsInterp *pSics,
|
||||
char *name);
|
||||
|
||||
#endif
|
||||
|
4
exeman.i
4
exeman.i
@ -1,5 +1,5 @@
|
||||
|
||||
#line 176 "exe.w"
|
||||
#line 178 "exe.w"
|
||||
|
||||
/*-------------------------------------------------------------------
|
||||
Internal header file for the exe manager module. Do not edit. This
|
||||
@ -20,5 +20,5 @@ typedef struct __EXEMAN{
|
||||
int echo;
|
||||
}ExeMan, *pExeMan;
|
||||
|
||||
#line 181 "exe.w"
|
||||
#line 183 "exe.w"
|
||||
|
||||
|
41
fomerge.c
41
fomerge.c
@ -483,11 +483,34 @@ static int updateHMFMData(SicsInterp *pSics, SConnection *pCon)
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------*/
|
||||
static int *calculateSum(HistInt *data, int iDet, int iTime)
|
||||
static int *calculateDetSum(HistInt *data, int iDet, int iTime)
|
||||
{
|
||||
int i, j, iIndex;
|
||||
int *sum = NULL;
|
||||
|
||||
sum = (int *)malloc(iDet*sizeof(int));
|
||||
if(!sum)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
memset(sum,0,iDet*sizeof(int));
|
||||
|
||||
for(i = 0; i < iDet; i++)
|
||||
{
|
||||
iIndex = i * iTime;
|
||||
for(j = 0; j < iTime; j++)
|
||||
{
|
||||
sum[i] += data[iIndex+j];
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
/*-------------------------------------------------------------------*/
|
||||
static int *calculateTimeSum(HistInt *data, int iDet, int iTime)
|
||||
{
|
||||
int i, j;
|
||||
int *sum = NULL;
|
||||
|
||||
sum = (int *)malloc(iTime*sizeof(int));
|
||||
if(!sum)
|
||||
{
|
||||
@ -495,16 +518,16 @@ static int *calculateSum(HistInt *data, int iDet, int iTime)
|
||||
}
|
||||
memset(sum,0,iTime*sizeof(int));
|
||||
|
||||
for(i = 0; i < iDet; i++)
|
||||
for(i = 0; i < iTime; i++)
|
||||
{
|
||||
iIndex = i * iTime;
|
||||
for(j = 0; j < iTime; j++)
|
||||
for(j = 0; j < iDet; j++)
|
||||
{
|
||||
sum[i] += data[iIndex+j];
|
||||
sum[i] += data[j*iTime + i];
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
static void checkSum(HistInt *sum, int iDet, char *name, SConnection *pCon){
|
||||
int i, count;
|
||||
@ -530,6 +553,8 @@ static int putSum(SicsInterp *pSics, SConnection *pCon,
|
||||
HistInt *sum = NULL;
|
||||
int iDet, iTime, i, j, iIndex, status;
|
||||
|
||||
return 1;
|
||||
|
||||
iTime = getFMdim(TIMEBIN);
|
||||
if(strcmp(name,"upper") == 0)
|
||||
{
|
||||
@ -557,7 +582,7 @@ static int putSum(SicsInterp *pSics, SConnection *pCon,
|
||||
return NX_ERROR;
|
||||
}
|
||||
|
||||
sum = calculateSum(data,iDet,iTime);
|
||||
sum = calculateDetSum(data,iDet,iTime);
|
||||
if(!sum)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: out of memory summing bank",eError);
|
||||
@ -582,6 +607,8 @@ static int putElastic(SicsInterp *pSics, SConnection *pCon,
|
||||
pHistMem pMem = NULL;
|
||||
float fCenter, fFWHM, fStdDev, fVal;
|
||||
|
||||
return 1;
|
||||
|
||||
pMem = (pHistMem)FindCommandData(pSics,"hm2","HistMem");
|
||||
if(pMem == NULL)
|
||||
{
|
||||
@ -592,7 +619,7 @@ static int putElastic(SicsInterp *pSics, SConnection *pCon,
|
||||
}
|
||||
fTimeBin = GetHistTimeBin(pMem,&iTime);
|
||||
iDet = getFMdim(MIDDLE);
|
||||
sum = calculateSum(GetHistogramPointer(pMem,pCon),iDet,iTime);
|
||||
sum = calculateTimeSum(GetHistogramPointer(pMem,pCon),iDet,iTime);
|
||||
if(!sum)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: out of memory calculating elastic peak position",
|
||||
|
@ -11,14 +11,14 @@
|
||||
#ifndef FOURTABLE
|
||||
#define FOURTABLE
|
||||
|
||||
int MakeFourCircleTable(void);
|
||||
int MakeFourCircleTable();
|
||||
void DeleteFourCircleTable(int handle);
|
||||
int HandleFourCircleCommands(int *table, SConnection *pCon,
|
||||
int HandleFourCircleCommands(int *handle, SConnection *pCon,
|
||||
int argc, char *argv[], int *err);
|
||||
char *GetFourCircleScanVar(int handle, double two_theta);
|
||||
int GetFourCircleScanNP(int handle, double two_theta);
|
||||
double GetFourCircleStep(int handle, double two_theta);
|
||||
float GetFourCirclePreset(int handle, double two_theta);
|
||||
int SaveFourCircleTable(int handle, char *objName, FILE *fd);
|
||||
float GetFourCirclePreset(int handle, double twoTheta);
|
||||
int GetFourCircleScanNP(int handle, double twoTheta);
|
||||
|
||||
#endif
|
||||
|
10
lin2ang.c
10
lin2ang.c
@ -70,7 +70,7 @@
|
||||
return 0;
|
||||
|
||||
fprintf(fd,"%s length %f\n",name, self->length);
|
||||
fprintf(fd,"%s zero %f\n",name, self->zero);
|
||||
fprintf(fd,"%s softzero %f\n",name, self->zero);
|
||||
return 1;
|
||||
|
||||
}
|
||||
@ -275,20 +275,20 @@
|
||||
}
|
||||
}
|
||||
/* zero point */
|
||||
if(strcmp(argv[1],"zero") == 0)
|
||||
if(strcmp(argv[1],"softzero") == 0)
|
||||
{
|
||||
if(argc >= 3)
|
||||
{
|
||||
iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&dVal);
|
||||
if(iRet != TCL_OK)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: zero parameter not recognised as number",
|
||||
SCWrite(pCon,"ERROR: softzero parameter not recognised as number",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
if(!SCMatchRights(pCon,usUser))
|
||||
{
|
||||
SCWrite(pCon,"ERROR: Insufficient privilege to change zero point",
|
||||
SCWrite(pCon,"ERROR: Insufficient privilege to change softzero point",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
@ -298,7 +298,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"%s.zero = %f",argv[0],self->zero);
|
||||
sprintf(pBueffel,"%s.softzero = %f",argv[0],self->zero);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
|
40
macro.c
40
macro.c
@ -71,6 +71,7 @@
|
||||
#include "Dbg.h"
|
||||
#include "servlog.h"
|
||||
#include "stringdict.h"
|
||||
#include "exeman.h"
|
||||
|
||||
#define SICSERROR "005567SICS"
|
||||
/*----------------------------------------------------------------------------
|
||||
@ -431,6 +432,21 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp,
|
||||
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int MacroFileEvalNew(SConnection *pCon, SicsInterp *pInter, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
void *pCom = NULL;
|
||||
pCom = FindCommandData(pInter,"exe","ExeManager");
|
||||
assert(pCom != NULL);
|
||||
|
||||
if(argc < 2){
|
||||
SCWrite(pCon,"ERROR: no batch buffer to execute specified",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
return runExeBatchBuffer(pCom,pCon,pInter,argv[1]);
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
int MacroFileEval(SConnection *pCon, SicsInterp *pInter, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
@ -459,8 +475,8 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp,
|
||||
/* open filename */
|
||||
if( argc < 2)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: No filename specified ",eError);
|
||||
return 0;
|
||||
SCWrite(pCon,"ERROR: No filename specified ",eError);
|
||||
return 0;
|
||||
}
|
||||
fp = fopen(argv[1],"r");
|
||||
if(!fp)
|
||||
@ -490,7 +506,7 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp,
|
||||
{
|
||||
iChar = fgetc(fp);
|
||||
if(iChar == EOF)
|
||||
{
|
||||
{
|
||||
iChar = (int)'\n';
|
||||
iRun = 0;
|
||||
}
|
||||
@ -505,11 +521,11 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp,
|
||||
SetStatus(eEager);
|
||||
FirstWord(pCom,pBueffel);
|
||||
if(FindCommand(pInter,pBueffel) != NULL)
|
||||
{
|
||||
{
|
||||
sprintf(pBueffel,"%s:%d>> %s",pFile,iLine,pCom);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
if(pWhere != NULL)
|
||||
{
|
||||
{
|
||||
free(pWhere);
|
||||
}
|
||||
pWhere = strdup(pBueffel);
|
||||
@ -524,16 +540,16 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp,
|
||||
{ /* Tcl error */
|
||||
if(strlen(pTcl->result) > 2)
|
||||
{
|
||||
/*
|
||||
local copy in order to resolve a valgrind error
|
||||
*/
|
||||
strncpy(pBueffel,pTcl->result,511);
|
||||
/*
|
||||
local copy in order to resolve a valgrind error
|
||||
*/
|
||||
strncpy(pBueffel,pTcl->result,511);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
}
|
||||
pCom = Tcl_DStringValue(&command);
|
||||
SCWrite(pCon,"ERROR: in Tcl block:",eError);
|
||||
SCWrite(pCon,"ERROR: in Tcl block:",eError);
|
||||
SCWrite(pCon,pCom,eError);
|
||||
SCWrite(pCon,"ERROR: end of Tcl error block",eError);
|
||||
SCWrite(pCon,"ERROR: end of Tcl error block",eError);
|
||||
}
|
||||
else /* SICS error */
|
||||
{
|
||||
@ -546,7 +562,7 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp,
|
||||
fclose(fp);
|
||||
Tcl_DStringFree(&command);
|
||||
SCWrite(pCon,"ERROR: batch processing interrupted",eError);
|
||||
SetStatus(eEager);
|
||||
SetStatus(eEager);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
|
@ -4,6 +4,7 @@
|
||||
# This is the scripted version using nxscript
|
||||
#
|
||||
# Mark Koennecke, May 2004
|
||||
# This is a special version for virtual DMC on lns00
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
proc storeMonochromator {} {
|
||||
@ -75,14 +76,34 @@ proc makeLinks {} {
|
||||
nxscript makelink dana dtnstep
|
||||
nxscript makelink dana mlambda
|
||||
}
|
||||
#------------------------------------------------------------------------
|
||||
proc makeSimFileName args {
|
||||
global datahome
|
||||
sicsdatanumber incr
|
||||
set num [SplitReply [sicsdatanumber]]
|
||||
return [makeSimForNum $num]
|
||||
}
|
||||
#------------------------------------------------------------------------
|
||||
proc makeSimForNum {num} {
|
||||
global datahome
|
||||
set pre [string trim [SplitReply [sicsdataprefix]]]
|
||||
set po [string trim [SplitReply [sicsdatapostfix]]]
|
||||
return [format "%s/%s2006n%6.6d%s" $datahome $pre $num $po]
|
||||
}
|
||||
#-------------------------------------------------------------------------
|
||||
# store DMC data
|
||||
#-------------------------------------------------------------------------
|
||||
proc storedata {} {
|
||||
global home
|
||||
set fil [newFileName]
|
||||
global home wwwMode
|
||||
|
||||
if {$wwwMode == 1} {
|
||||
set fil [makeSimFileName]
|
||||
} else {
|
||||
set fil [newFileName]
|
||||
}
|
||||
lastdatafile $fil
|
||||
clientput "Opening $fil for writing"
|
||||
nxscript create4 $fil $home/dmc.dic
|
||||
nxscript createxml $fil $home/dmc.dic
|
||||
|
||||
writeStandardAttributes $fil
|
||||
writeTextVar etitle title
|
||||
|
@ -1,13 +1,19 @@
|
||||
# --------------------------------------------------------------------------
|
||||
#--------------------------------------------------------------------------
|
||||
# Initialization script for a virtual DMC instrument using a McStas
|
||||
# simulationas a data source
|
||||
#
|
||||
# Dr. Mark Koennecke, June 2005
|
||||
#---------------------------------------------------------------------------
|
||||
# O P T I O N S
|
||||
# wwwMode = 1 when running for the WWW-VDMC application
|
||||
set wwwMode 1
|
||||
|
||||
set home $env(HOME)/src/workspace/sics/mcstas/dmc
|
||||
|
||||
if {$wwwMode == 1} {
|
||||
set home /home/lnswww/vinstrument/mcstas/dmc
|
||||
set datahome /home/lnswww/www/vinstrument
|
||||
} else {
|
||||
set home $env(HOME)/src/workspace/sics/mcstas/dmc
|
||||
}
|
||||
#--------------------------------- first all the server options are set
|
||||
#ServerOption RedirectFile $home/stdcdmc
|
||||
ServerOption ReadTimeOut 10
|
||||
@ -120,18 +126,20 @@ SicsDataPrefix vdmc
|
||||
#--------- make data number
|
||||
MakeDataNumber SicsDataNumber $home/DataNumber
|
||||
VarMake SicsDataPostFix Text Internal
|
||||
SicsDataPostFix ".hdf"
|
||||
SicsDataPostFix ".xml"
|
||||
VarMake Adress Text User
|
||||
VarMake phone Text User
|
||||
VarMake fax Text User
|
||||
VarMake email Text User
|
||||
VarMake sample_mur Float User
|
||||
VarMake lastdatafile Text User
|
||||
#--------------------------------------------------------------------------
|
||||
# P R O C E D U R E S
|
||||
#--------------------------------------------------------------------------
|
||||
MakeDrive
|
||||
MakeBatchManager
|
||||
MakeNXScript
|
||||
MakeRuenBuffer
|
||||
#-------------------- initialize scripted commands
|
||||
source $home/vdmccom.tcl
|
||||
#-------------------- configure commandlog
|
||||
|
@ -15,6 +15,7 @@ if { [info exists vdmcinit] == 0 } {
|
||||
Publish copydmcdata User
|
||||
Publish sample User
|
||||
Publish wwwsics Spy
|
||||
Publish wwwfilefornumber Spy
|
||||
mcinstall
|
||||
}
|
||||
source $home/log.tcl
|
||||
@ -38,12 +39,19 @@ proc washlazy {name} {
|
||||
if { [string first "H K L THETA 2THETA D VALUE" $line] > 0} {
|
||||
break
|
||||
}
|
||||
#-------- A second version to treat the messed up lazy pulverix files
|
||||
# uploaded through the WWW-interface
|
||||
if { [string first "H K L THETA" $line] >= 0} {
|
||||
break
|
||||
}
|
||||
}
|
||||
#------- process data lines
|
||||
puts $out "// mult Q(hkl) F2 DW w"
|
||||
clientput "HKL found at: $line"
|
||||
while { [gets $in line] >= 0} {
|
||||
set num [scan $line "%d %d %d %f %f %f %f %f %d %d %d %f %f %f %f %f %d"\
|
||||
h k l th th2 d di sin h2 k2 l2 I F A B ang mul]
|
||||
clientput "Line = $num, $line"
|
||||
if { $num == 17} {
|
||||
set q [expr (2.*3.14159265358979323846)/$d]
|
||||
set f2 [expr $F * $F]
|
||||
@ -363,7 +371,7 @@ proc wwwpar {type mot} {
|
||||
}
|
||||
#------------- wwwuser formats user information into a html table
|
||||
proc wwwuser {} {
|
||||
lappend list title sample user email phone adress
|
||||
lappend list title user email phone adress
|
||||
append txt "<table>"
|
||||
foreach e $list {
|
||||
set ret [catch {$e} msg]
|
||||
@ -376,6 +384,11 @@ proc wwwuser {} {
|
||||
}
|
||||
return $txt
|
||||
}
|
||||
#------------- wwwfilefornumber returns the path to a data file for a
|
||||
# number
|
||||
proc wwwfilefornumber {num} {
|
||||
return [makeSimForNum $num]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
79
mesure.c
79
mesure.c
@ -32,6 +32,7 @@
|
||||
#include "nxscript.h"
|
||||
#include "fourtable.h"
|
||||
#include "lld.h"
|
||||
#include "stdscan.h"
|
||||
|
||||
extern void SNXFormatTime(char *pBueffel, int iLen);
|
||||
extern float nintf(float f);
|
||||
@ -65,6 +66,7 @@
|
||||
int iLogFile; /* log file num at connection */
|
||||
SConnection *pCon; /* log file owning connection */
|
||||
char *pCurrentFile; /* current file root */
|
||||
char headerTemplate[512];
|
||||
int iCount; /* count of reflection */
|
||||
int CountMode; /* timer or preset */
|
||||
int np; /* number of scan points */
|
||||
@ -146,7 +148,7 @@ static void ListMesure(pMesure self, char *name, SConnection *pCon)
|
||||
pMesure CreateMesure(pHKL pCryst, pScanData pScanner, pMotor pOmega,
|
||||
char *pOm, pMotor p2Theta, char *p2t,
|
||||
char *pFileRoot,
|
||||
pDataNumber pDanu)
|
||||
pDataNumber pDanu, char *hdTemplate)
|
||||
{
|
||||
pMesure pNew = NULL;
|
||||
|
||||
@ -197,7 +199,8 @@ static void ListMesure(pMesure self, char *name, SConnection *pCon)
|
||||
pNew->lCounts = (long *)malloc(90*sizeof(long));
|
||||
#endif
|
||||
pNew->lCounts = (long *)malloc(50*sizeof(long));
|
||||
pNew->stepTable = MakeFourCircleTable();
|
||||
pNew->stepTable = MakeFourCircleTable();
|
||||
strncpy(pNew->headerTemplate,hdTemplate,511);
|
||||
return pNew;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
@ -249,7 +252,7 @@ static void ListMesure(pMesure self, char *name, SConnection *pCon)
|
||||
/* check no of parameters
|
||||
inicom name hkl scan omega root danu
|
||||
*/
|
||||
if(argc < 8)
|
||||
if(argc < 9)
|
||||
{
|
||||
SCWrite(pCon,
|
||||
"ERROR: Insufficient number of parameters to MesureFactory",eError);
|
||||
@ -336,7 +339,7 @@ static void ListMesure(pMesure self, char *name, SConnection *pCon)
|
||||
|
||||
/* finally create the thing */
|
||||
pNew = CreateMesure(pCryst,pScan,pMot,argv[4], pMot2, argv[5],
|
||||
argv[6],pDanu);
|
||||
argv[6],pDanu,argv[8]);
|
||||
if(!pNew)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: no memory in MesureFactory",eError);
|
||||
@ -759,7 +762,7 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
||||
char *pFile = NULL, *pPtr;
|
||||
float zero, pos;
|
||||
pMotor pMot = NULL;
|
||||
|
||||
FILE *temp = NULL;
|
||||
|
||||
assert(self);
|
||||
assert(pCon);
|
||||
@ -813,6 +816,19 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
||||
SCSetInterrupt(pCon,eAbortBatch);
|
||||
return 0;
|
||||
}
|
||||
temp = fopen(self->headerTemplate,"r");
|
||||
if(temp == NULL)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: failed to open header template",eError);
|
||||
}
|
||||
if(temp != NULL && self->fRefl != NULL)
|
||||
{
|
||||
WriteTemplate(self->fRefl, temp, pFilename, NULL,
|
||||
pCon, pServ->pSics);
|
||||
fclose(temp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* open hkl-data file */
|
||||
strcpy(pFilename,pRoot);
|
||||
@ -855,59 +871,6 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
||||
sprintf(pBuff,"user = %s",pVar->text);
|
||||
strcat(pBueffel,pBuff);
|
||||
}
|
||||
fprintf(self->fRefl,"%s\n",pBueffel);
|
||||
fprintf(self->fRefl,"lambda = %f Angstroem\n",fVal);
|
||||
fprintf(self->fRefl,
|
||||
"UB = %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f\n",
|
||||
fUB[0], fUB[1],fUB[2],fUB[3],fUB[4],fUB[5],fUB[6],fUB[7],fUB[8]);
|
||||
|
||||
|
||||
/*
|
||||
* zero points for Juerg
|
||||
*/
|
||||
pBueffel[0] = '\0';
|
||||
if(self->pCryst->pTheta != NULL){
|
||||
MotorGetPar(self->pCryst->pTheta,"softzero",&zero);
|
||||
snprintf(pBuff,131,"stt.zero = %f ", zero);
|
||||
strcat(pBueffel,pBuff);
|
||||
}
|
||||
if(self->pCryst->pOmega != NULL){
|
||||
MotorGetPar(self->pCryst->pOmega,"softzero",&zero);
|
||||
snprintf(pBuff,131,"om.zero = %f ", zero);
|
||||
strcat(pBueffel,pBuff);
|
||||
}
|
||||
if(self->pCryst->pChi != NULL){
|
||||
MotorGetPar(self->pCryst->pChi,"softzero",&zero);
|
||||
snprintf(pBuff,131,"chi.zero = %f ", zero);
|
||||
strcat(pBueffel,pBuff);
|
||||
}
|
||||
if(self->pCryst->pPhi != NULL){
|
||||
MotorGetPar(self->pCryst->pPhi,"softzero",&zero);
|
||||
snprintf(pBuff,131,"phi.zero = %f ", zero);
|
||||
strcat(pBueffel,pBuff);
|
||||
}
|
||||
fprintf(self->fRefl,"%s\n",pBueffel);
|
||||
|
||||
/*
|
||||
* CEX motors ....
|
||||
*/
|
||||
pBueffel[0] = '\0';
|
||||
pMot = FindCommandData(pServ->pSics,"cex1","Motor");
|
||||
if(pMot != NULL){
|
||||
MotorGetSoftPosition(pMot,pCon,&pos);
|
||||
snprintf(pBuff,131,"cex1 = %f ",pos);
|
||||
strcat(pBueffel,pBuff);
|
||||
}
|
||||
pMot = FindCommandData(pServ->pSics,"cex2","Motor");
|
||||
if(pMot != NULL){
|
||||
MotorGetSoftPosition(pMot,pCon,&pos);
|
||||
snprintf(pBuff,131,"cex2 = %f ",pos);
|
||||
strcat(pBueffel,pBuff);
|
||||
}
|
||||
if(strlen(pBueffel) > 1) {
|
||||
fprintf(self->fRefl,"%s\n",pBueffel);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
4
mesure.h
4
mesure.h
@ -17,8 +17,8 @@
|
||||
/*--------------------- live & death --------------------------------------*/
|
||||
pMesure CreateMesure(pHKL pCryst, pScanData pScanner,
|
||||
pMotor pOmega, char *pom,
|
||||
pMotor p2Theta, char *p2t,
|
||||
char *pFileRoot,pDataNumber pDanu);
|
||||
pMotor p2Theta, char *p2t,
|
||||
char *pFileRoot,pDataNumber pDanu, char *headerTemplate);
|
||||
void DeleteMesure(void *pData);
|
||||
|
||||
int MesureFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
|
@ -30,7 +30,8 @@ $\langle$mesureint {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@/*--------------------- live & death --------------------------------------*/@\\
|
||||
\mbox{}\verb@ pMesure CreateMesure(pHKL pCryst, pScanData pScanner, @\\
|
||||
\mbox{}\verb@ pMotor pOmega, char *pom,@\\
|
||||
\mbox{}\verb@ char *pFileRoot,pDataNumber pDanu);@\\
|
||||
\mbox{}\verb@ pMotor p2Theta, char *p2t,@\\
|
||||
\mbox{}\verb@ char *pFileRoot,pDataNumber pDanu, char *headerTemplate);@\\
|
||||
\mbox{}\verb@ void DeleteMesure(void *pData);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int MesureFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
@ -117,11 +118,13 @@ $\langle$fourtableint {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int MakeFourCircleTable();@\\
|
||||
\mbox{}\verb@ void DeleteFourCircleTable(int handle);@\\
|
||||
\mbox{}\verb@ int HandleFourCircleCommands(int handle, SConnection *pCon, @\\
|
||||
\mbox{}\verb@ int HandleFourCircleCommands(int *handle, SConnection *pCon, @\\
|
||||
\mbox{}\verb@ int argc, char *argv[], int *err);@\\
|
||||
\mbox{}\verb@ char *GetFourCircleScanVar(int handle, double two_theta);@\\
|
||||
\mbox{}\verb@ double GetFourCircleStep(int handle, double two_theta);@\\
|
||||
\mbox{}\verb@ int SaveFourCircleTable(int handle, char *objName, FILE *fd);@\\
|
||||
\mbox{}\verb@ float GetFourCirclePreset(int handle, double twoTheta);@\\
|
||||
\mbox{}\verb@ int GetFourCircleScanNP(int handle, double twoTheta);@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
|
6
mesure.w
6
mesure.w
@ -26,7 +26,7 @@ The interface to this object consists of these functions:
|
||||
pMesure CreateMesure(pHKL pCryst, pScanData pScanner,
|
||||
pMotor pOmega, char *pom,
|
||||
pMotor p2Theta, char *p2t,
|
||||
char *pFileRoot,pDataNumber pDanu);
|
||||
char *pFileRoot,pDataNumber pDanu, char *headerTemplate);
|
||||
void DeleteMesure(void *pData);
|
||||
|
||||
int MesureFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
@ -100,11 +100,13 @@ interface to this module is:
|
||||
@d fourtableint @{
|
||||
int MakeFourCircleTable();
|
||||
void DeleteFourCircleTable(int handle);
|
||||
int HandleFourCircleCommands(int handle, SConnection *pCon,
|
||||
int HandleFourCircleCommands(int *handle, SConnection *pCon,
|
||||
int argc, char *argv[], int *err);
|
||||
char *GetFourCircleScanVar(int handle, double two_theta);
|
||||
double GetFourCircleStep(int handle, double two_theta);
|
||||
int SaveFourCircleTable(int handle, char *objName, FILE *fd);
|
||||
float GetFourCirclePreset(int handle, double twoTheta);
|
||||
int GetFourCircleScanNP(int handle, double twoTheta);
|
||||
@}
|
||||
Many functions takes as the first argument a handle to the four circle table as
|
||||
created by MakeFourCircleTable.
|
||||
|
28
network.c
28
network.c
@ -555,7 +555,7 @@ int NETReadTillTerm(mkChannel *self, long timeout,
|
||||
char *pTerm, char *pBuffer, int iBufLen)
|
||||
{
|
||||
struct timeval start, now;
|
||||
int bufPtr = 0, status, i, length;
|
||||
int bufPtr = 0, status, i, length, matchIndex=1;
|
||||
char c;
|
||||
long dif;
|
||||
|
||||
@ -583,11 +583,29 @@ int NETReadTillTerm(mkChannel *self, long timeout,
|
||||
{
|
||||
return status;
|
||||
}
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
if(c == pTerm[i])
|
||||
if ('&' != pTerm[0]) {
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
return bufPtr+1;
|
||||
if(c == pTerm[i])
|
||||
{
|
||||
return bufPtr+1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (matchIndex == 1 && c == pTerm[1]) {
|
||||
matchIndex++;
|
||||
} else {
|
||||
if (c== pTerm[matchIndex] && matchIndex < length -1) {
|
||||
matchIndex++;
|
||||
} else {
|
||||
if (c == pTerm[matchIndex] && matchIndex == length - 1) {
|
||||
bufPtr = bufPtr - matchIndex + 1;
|
||||
pBuffer[bufPtr] = '\0';
|
||||
return bufPtr;
|
||||
} else {
|
||||
matchIndex == 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c == 0 && *pTerm != 0)
|
||||
|
10
nxscript.c
10
nxscript.c
@ -394,10 +394,12 @@ static void updateHMDim(NXScript *self, pHistMem mem){
|
||||
timeBin = GetHistTimeBin(mem,&timeLength);
|
||||
if(timeLength > 2){
|
||||
sprintf(dummy,"%d",timeLength);
|
||||
status = NXDupdate(self->dictHandle,"timedim",dummy);
|
||||
if(status == 0) {
|
||||
NXDadd(self->dictHandle,"timedim",dummy);
|
||||
}
|
||||
} else {
|
||||
sprintf(dummy,"%d",1);
|
||||
}
|
||||
status = NXDupdate(self->dictHandle,"timedim",dummy);
|
||||
if(status == 0) {
|
||||
NXDadd(self->dictHandle,"timedim",dummy);
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------
|
||||
|
12
ofac.c
12
ofac.c
@ -207,8 +207,11 @@
|
||||
/* permanent commands */
|
||||
AddCommand(pInter,"Sics_Exitus",SicsExit,NULL,NULL);
|
||||
AddCommand(pInter,"FileEval",MacroFileEval,NULL,NULL);
|
||||
|
||||
AddCommand(pInter,"InternEval",InternalFileEval,NULL,NULL);
|
||||
/*
|
||||
AddCommand(pInter,"FileWhere",MacroWhere,WhereKill,NULL);
|
||||
*/
|
||||
AddCommand(pInter,"ClientPut",ClientPut,NULL,NULL);
|
||||
AddCommand(pInter,"broadcast",Broadcast,NULL,NULL);
|
||||
AddCommand(pInter,"transact",TransactAction,NULL,NULL);
|
||||
@ -423,18 +426,15 @@
|
||||
InitGeneral();
|
||||
|
||||
/* general initialization */
|
||||
InitIniCommands(pSics,pServ->pTasker);
|
||||
|
||||
/* create a connection */
|
||||
pCon = SCCreateDummyConnection(pSics);
|
||||
if(!pCon)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/* removed (gives double output to stdout)
|
||||
pCon->iFiles = 1;
|
||||
pCon->pFiles[0] = stdout;
|
||||
*/
|
||||
MakeExeManager(pCon,pSics,NULL,1, NULL);
|
||||
InitIniCommands(pSics,pServ->pTasker);
|
||||
|
||||
pCon->iFiles = 0;
|
||||
|
||||
/* evaluate the file */
|
||||
|
37
scan.tex
37
scan.tex
@ -52,6 +52,7 @@ $\langle$scanvar {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ float fStep;@\\
|
||||
\mbox{}\verb@ float *fData;@\\
|
||||
\mbox{}\verb@ int dataList;@\\
|
||||
\mbox{}\verb@ int logVar;@\\
|
||||
\mbox{}\verb@ }VarEntry, *pVarEntry;@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
@ -88,6 +89,14 @@ $\langle$scanvarint {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ pVarEntry MakeScanVar(SicsInterp *pSics, SConnection *pCon, char@\\
|
||||
\mbox{}\verb@ *name, float start, float step);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * make a variable which is logged during the scan but not driven.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param pSics The interpreter in order to locate the variable.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param pCon A connection object for error reporting@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param name The name of the variable to log@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ pVarEntry MakeLogVar(SicsInterp *pSics, @\\
|
||||
\mbox{}\verb@ SConnection *pCon, char *name);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * InitScanVar clears the list of scan points@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param pvar The scna variable to clear@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
@ -145,6 +154,21 @@ $\langle$scanvarint {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param np The number of slots in fData.@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ void CopyScanVar(pVarEntry pVar, float *fData, int np);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * CheckScanVar checks if the scan variable can be driven through the@\\
|
||||
\mbox{}\verb@ * whole range.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param pVar The scan variable to check@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param pCon The connection object to which to report errors.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param np The number of points to check for.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@return 0 on failuyre, 1 on success@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ int CheckScanVar(pVarEntry pVar, SConnection *pCon, int np);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * queries if the variable is alogged variable or a drive one.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param pVar The variable to query.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@return 1 if log var, 0 else@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ int isLogVar(pVarEntry pVar);@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
@ -451,6 +475,15 @@ $\langle$stdscan {\footnotesize ?}$\rangle\equiv$
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * make a filename according to SICS rules for this scan@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ char *ScanMakeFileName(SicsInterp *pSics, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ /*@\\
|
||||
\mbox{}\verb@ * write the header bits from the template@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ void WriteTemplate(FILE *fd, FILE *temp, char *filename, pScanData pScan, @\\
|
||||
\mbox{}\verb@ SConnection *pCon, SicsInterp *pSics);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * write the header of the scan file@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ int WriteHeader(pScanData self);@\\
|
||||
@ -474,6 +507,10 @@ $\langle$stdscan {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ */ @\\
|
||||
\mbox{}\verb@ int NonCheckPrepare(pScanData self);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * prepare for a scan without complaining...@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ int SilentPrepare(pScanData self);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * ScanDrive handles driving to the scan point iPoint.@\\
|
||||
\mbox{}\verb@ */ @\\
|
||||
\mbox{}\verb@ int ScanDrive(pScanData self, int iPoint);@\\
|
||||
|
37
scan.w
37
scan.w
@ -47,6 +47,7 @@ Scan variables are held in this data structure:
|
||||
float fStep;
|
||||
float *fData;
|
||||
int dataList;
|
||||
int logVar;
|
||||
}VarEntry, *pVarEntry;
|
||||
@}
|
||||
The VarEntry structure holds the data for each single scan variable.
|
||||
@ -69,6 +70,14 @@ Scan variables have an interface:
|
||||
*/
|
||||
pVarEntry MakeScanVar(SicsInterp *pSics, SConnection *pCon, char
|
||||
*name, float start, float step);
|
||||
/**
|
||||
* make a variable which is logged during the scan but not driven.
|
||||
* @@param pSics The interpreter in order to locate the variable.
|
||||
* @@param pCon A connection object for error reporting
|
||||
* @@param name The name of the variable to log
|
||||
*/
|
||||
pVarEntry MakeLogVar(SicsInterp *pSics,
|
||||
SConnection *pCon, char *name);
|
||||
/**
|
||||
* InitScanVar clears the list of scan points
|
||||
* @@param pvar The scna variable to clear
|
||||
@ -127,6 +136,21 @@ Scan variables have an interface:
|
||||
* @@param np The number of slots in fData.
|
||||
*/
|
||||
void CopyScanVar(pVarEntry pVar, float *fData, int np);
|
||||
/**
|
||||
* CheckScanVar checks if the scan variable can be driven through the
|
||||
* whole range.
|
||||
* @@param pVar The scan variable to check
|
||||
* @@param pCon The connection object to which to report errors.
|
||||
* @@param np The number of points to check for.
|
||||
* @@return 0 on failuyre, 1 on success
|
||||
*/
|
||||
int CheckScanVar(pVarEntry pVar, SConnection *pCon, int np);
|
||||
/**
|
||||
* queries if the variable is alogged variable or a drive one.
|
||||
* @@param pVar The variable to query.
|
||||
* @@return 1 if log var, 0 else
|
||||
*/
|
||||
int isLogVar(pVarEntry pVar);
|
||||
@}
|
||||
|
||||
\subsubsection{The Scan Object}
|
||||
@ -396,6 +420,15 @@ format of this template is documented in the SICS managers
|
||||
documentation.
|
||||
|
||||
@d stdscan @{
|
||||
/**
|
||||
* make a filename according to SICS rules for this scan
|
||||
*/
|
||||
char *ScanMakeFileName(SicsInterp *pSics, SConnection *pCon);
|
||||
/*
|
||||
* write the header bits from the template
|
||||
*/
|
||||
void WriteTemplate(FILE *fd, FILE *temp, char *filename, pScanData pScan,
|
||||
SConnection *pCon, SicsInterp *pSics);
|
||||
/**
|
||||
* write the header of the scan file
|
||||
*/
|
||||
@ -419,6 +452,10 @@ documentation.
|
||||
* second version of PrepareScan which does not check scan limits
|
||||
*/
|
||||
int NonCheckPrepare(pScanData self);
|
||||
/**
|
||||
* prepare for a scan without complaining...
|
||||
*/
|
||||
int SilentPrepare(pScanData self);
|
||||
/**
|
||||
* ScanDrive handles driving to the scan point iPoint.
|
||||
*/
|
||||
|
45
scanvar.h
45
scanvar.h
@ -21,7 +21,7 @@
|
||||
float fStep;
|
||||
float *fData;
|
||||
int dataList;
|
||||
int logVar;
|
||||
int logVar;
|
||||
}VarEntry, *pVarEntry;
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
@ -35,22 +35,21 @@
|
||||
* @param start The start position from which to scan
|
||||
* @param step The step width with which to scan.
|
||||
* @return A pointer to a new scan variable object on success, NULL
|
||||
* else NULL
|
||||
* else
|
||||
*/
|
||||
pVarEntry MakeScanVar(SicsInterp *pSics, SConnection *pCon, char
|
||||
*name, float start, float step);
|
||||
/*
|
||||
* Make a variable which is logged during the scan
|
||||
* @param pSics The SICS interpreter to search for the variable
|
||||
* @param pCon A connection to report problems to
|
||||
* @param name The name of the variable to log
|
||||
* @return A pointer to a new scan variable object on success, NULL
|
||||
* else NULL
|
||||
/**
|
||||
* make a variable which is logged during the scan but not driven.
|
||||
* @param pSics The interpreter in order to locate the variable.
|
||||
* @param pCon A connection object for error reporting
|
||||
* @param name The name of the variable to log
|
||||
*/
|
||||
pVarEntry MakeLogVar(SicsInterp *pSics, SConnection *pCon, char *name);
|
||||
pVarEntry MakeLogVar(SicsInterp *pSics,
|
||||
SConnection *pCon, char *name);
|
||||
/**
|
||||
* InitScanVar clears the list of scan points
|
||||
* @param pvar The scan variable to clear
|
||||
* @param pvar The scna variable to clear
|
||||
*/
|
||||
void InitScanVar(pVarEntry pVar);
|
||||
/**
|
||||
@ -76,14 +75,6 @@
|
||||
* @return The step width for the scan.
|
||||
*/
|
||||
float ScanVarStep(pVarEntry pVar);
|
||||
/**
|
||||
* check if the scan is possible, i.e the scan variable does
|
||||
* not violate the limits in the scan
|
||||
* @param pVar The scan variable to check
|
||||
* @param pCon The connection to report errors to
|
||||
* @return 1 when OK, 0 when the limits are violated.
|
||||
*/
|
||||
int CheckScanVar(pVarEntry pVar, SConnection *pCon, int np);
|
||||
/**
|
||||
* StartScanVar starts the scan variable to drive to the next
|
||||
* position.
|
||||
@ -115,7 +106,19 @@
|
||||
*/
|
||||
void CopyScanVar(pVarEntry pVar, float *fData, int np);
|
||||
/**
|
||||
* enquires if a variable is a logged variable or a proper scan variable
|
||||
*/
|
||||
* CheckScanVar checks if the scan variable can be driven through the
|
||||
* whole range.
|
||||
* @param pVar The scan variable to check
|
||||
* @param pCon The connection object to which to report errors.
|
||||
* @param np The number of points to check for.
|
||||
* @return 0 on failuyre, 1 on success
|
||||
*/
|
||||
int CheckScanVar(pVarEntry pVar, SConnection *pCon, int np);
|
||||
/**
|
||||
* queries if the variable is alogged variable or a drive one.
|
||||
* @param pVar The variable to query.
|
||||
* @return 1 if log var, 0 else
|
||||
*/
|
||||
int isLogVar(pVarEntry pVar);
|
||||
|
||||
#endif
|
||||
|
232
stdscan.c
232
stdscan.c
@ -64,8 +64,240 @@ static char *fixExtension(char *filename)
|
||||
}
|
||||
return fixExtension(pRes);
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void WriteTemplate(FILE *fd, FILE *temp, char *filename, pScanData pScan,
|
||||
SConnection *pCon, SicsInterp *pSics)
|
||||
{
|
||||
char pBuffer[512], pError[512], *pPtr, *pName;
|
||||
CommandList *pCom = NULL;
|
||||
pSicsVariable pVar = NULL;
|
||||
pDummy pDum = NULL;
|
||||
pIDrivable pDriv = NULL;
|
||||
pMotor pMot = NULL;
|
||||
pVarEntry pScanVar = NULL;
|
||||
void *pVoid = NULL;
|
||||
float fVal;
|
||||
int iRet;
|
||||
|
||||
/* loop through description file and act along the way */
|
||||
while(fgets(pBuffer,511,temp) != NULL)
|
||||
{
|
||||
pPtr = strstr(pBuffer,"!!VAR(");
|
||||
if(pPtr) /* handle a Sics variable */
|
||||
{
|
||||
/* extract the name */
|
||||
pName = pPtr + 6; /* first char of name */
|
||||
*pPtr = '\0'; /* this is the starter of the line */
|
||||
pPtr = pName;
|
||||
while( (*pPtr != '\0') && (*pPtr != ')') )
|
||||
{
|
||||
pPtr++;
|
||||
}
|
||||
*pPtr = '\0';
|
||||
/* find the variable */
|
||||
pCom = FindCommand(pSics,pName);
|
||||
if(!pCom)
|
||||
{
|
||||
sprintf(pError,"ERROR: variable %s NOT found",pName);
|
||||
SCWrite(pCon,pError,eError);
|
||||
continue;
|
||||
}
|
||||
pVar = (pSicsVariable)pCom->pData;
|
||||
if(!pVar)
|
||||
{
|
||||
sprintf(pError,"ERROR: variable %s NOT found",pName);
|
||||
SCWrite(pCon,pError,eError);
|
||||
continue;
|
||||
}
|
||||
switch(pVar->eType)
|
||||
{
|
||||
case veFloat:
|
||||
sprintf(pError,"%f",pVar->fVal);
|
||||
break;
|
||||
case veInt:
|
||||
sprintf(pError,"%d",pVar->iVal);
|
||||
break;
|
||||
case veText:
|
||||
sprintf(pError,"%s",pVar->text);
|
||||
break;
|
||||
}
|
||||
/* finally write */
|
||||
fprintf(fd,"%s %s\n",pBuffer,pError);
|
||||
continue;
|
||||
}/* end variable */
|
||||
/*------- Drivable */
|
||||
pPtr = strstr(pBuffer,"!!DRIV(");
|
||||
if(pPtr)
|
||||
{
|
||||
/* extract the name */
|
||||
pName = pPtr + 7; /* first char of name */
|
||||
*pPtr = '\0'; /* this is the starter of the line */
|
||||
pPtr = pName;
|
||||
while( (*pPtr != '\0') && (*pPtr != ')') )
|
||||
{
|
||||
pPtr++;
|
||||
}
|
||||
*pPtr = '\0';
|
||||
/* find the variable */
|
||||
pCom = FindCommand(pSics,pName);
|
||||
if(!pCom)
|
||||
{
|
||||
sprintf(pError,"ERROR: variable %s NOT found",pName);
|
||||
SCWrite(pCon,pError,eError);
|
||||
continue;
|
||||
}
|
||||
pDum = (pDummy)pCom->pData;
|
||||
if(!pDum)
|
||||
{
|
||||
sprintf(pError,"ERROR: variable %s is NOT drivable",pName);
|
||||
SCWrite(pCon,pError,eError);
|
||||
continue;
|
||||
}
|
||||
pDriv = (pIDrivable)pDum->pDescriptor->GetInterface(pDum,DRIVEID);
|
||||
if(!pDriv)
|
||||
{
|
||||
sprintf(pError,"ERROR: variable %s is NOT drivable",pName);
|
||||
SCWrite(pCon,pError,eError);
|
||||
continue;
|
||||
}
|
||||
fVal = pDriv->GetValue(pDum,pCon);
|
||||
fprintf(fd,"%s %f\n",pBuffer,fVal);
|
||||
continue;
|
||||
} /* end drive */
|
||||
/*------- zero point */
|
||||
pPtr = strstr(pBuffer,"!!ZERO(");
|
||||
if(pPtr)
|
||||
{
|
||||
/* extract the name */
|
||||
pName = pPtr + 7; /* first char of name */
|
||||
*pPtr = '\0'; /* this is the starter of the line */
|
||||
pPtr = pName;
|
||||
while( (*pPtr != '\0') && (*pPtr != ')') )
|
||||
{
|
||||
pPtr++;
|
||||
}
|
||||
*pPtr = '\0';
|
||||
/* find the motor */
|
||||
pMot = FindMotor(pSics,pName);
|
||||
if(!pMot)
|
||||
{
|
||||
sprintf(pError,"ERROR: motor %s NOT found",pName);
|
||||
SCWrite(pCon,pError,eError);
|
||||
continue;
|
||||
}
|
||||
iRet = MotorGetPar(pMot,"softzero",&fVal);
|
||||
if(!iRet)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: failed to read zero point",eError);
|
||||
continue;
|
||||
}
|
||||
fprintf(fd,"%s %f\n",pBuffer,fVal);
|
||||
continue;
|
||||
} /* end zero point */
|
||||
/*---------- scripted info */
|
||||
pPtr = strstr(pBuffer,"!!SCRIPT(");
|
||||
if(pPtr)
|
||||
{
|
||||
/* extract the name */
|
||||
pName = pPtr + 9; /* first char of name */
|
||||
*pPtr = '\0'; /* this is the starter of the line */
|
||||
pPtr = pName;
|
||||
while( (*pPtr != '\0') && (*pPtr != ')') )
|
||||
{
|
||||
pPtr++;
|
||||
}
|
||||
*pPtr = '\0';
|
||||
if(Tcl_Eval(InterpGetTcl(pSics),pName) == TCL_OK)
|
||||
{
|
||||
fprintf(fd,"%s\n",Tcl_GetStringResult(InterpGetTcl(pSics)));
|
||||
}
|
||||
else
|
||||
{
|
||||
SCWrite(pCon,"ERROR: failed to execute Tcl command",eError);
|
||||
strncpy(pBuffer, Tcl_GetStringResult(InterpGetTcl(pSics)), 511);
|
||||
SCWrite(pCon,pBuffer,eError);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* ------- date */
|
||||
pPtr = strstr(pBuffer,"!!DATE!!");
|
||||
if(pPtr)
|
||||
{
|
||||
*pPtr = '\0';
|
||||
SNXFormatTime(pError,511);
|
||||
fprintf(fd,"%s %s\n",pBuffer,pError);
|
||||
continue;
|
||||
}
|
||||
/*-------- filename */
|
||||
pPtr = strstr(pBuffer,"!!FILE!!");
|
||||
if(pPtr)
|
||||
{
|
||||
*pPtr = '\0';
|
||||
fprintf(fd,"%s %s\n",pBuffer,filename);
|
||||
continue;
|
||||
}
|
||||
/*------------ scanzero */
|
||||
pPtr = strstr(pBuffer,"!!SCANZERO!!");
|
||||
if(pPtr && pScan != NULL)
|
||||
{
|
||||
*pPtr = '\0';
|
||||
/* write zero point of first scan variable if motor */
|
||||
DynarGet(pScan->pScanVar,0,&pVoid);
|
||||
pScanVar = (pVarEntry)pVoid;
|
||||
if(pScanVar)
|
||||
{
|
||||
pMot = NULL;
|
||||
pMot = FindMotor(pSics,ScanVarName(pScanVar));
|
||||
if(pMot != NULL)
|
||||
{
|
||||
MotorGetPar(pMot,"softzero",&fVal);
|
||||
fprintf(fd,"%s zero = %8.3f\n",ScanVarName(pScanVar),
|
||||
fVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* --------- plain text */
|
||||
fprintf(fd,"%s",pBuffer);
|
||||
} /* end while */
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int WriteHeader(pScanData self)
|
||||
{
|
||||
int i, iRet;
|
||||
FILE *fd;
|
||||
|
||||
assert(self->pSics);
|
||||
assert(self->pCon);
|
||||
|
||||
/* open data file */
|
||||
self->fd = fopen(self->pFile,"w");
|
||||
if(!self->fd)
|
||||
{
|
||||
SCWrite(self->pCon,"ERROR: cannot write data file",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* open header description file */
|
||||
fd = fopen(self->pHeaderFile,"r");
|
||||
if(!fd)
|
||||
{
|
||||
SCWrite(self->pCon,"ERROR: cannot open header description file",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
WriteTemplate(self->fd,fd,self->pFile,
|
||||
self, self->pCon, self->pSics);
|
||||
|
||||
/* remember position for seeking to it for writing data */
|
||||
self->lPos = ftell(self->fd);
|
||||
|
||||
fclose(fd);
|
||||
fclose(self->fd);
|
||||
self->fd = NULL;
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int WriteHeaderOld(pScanData self)
|
||||
{
|
||||
int i, iRet;
|
||||
FILE *fd;
|
||||
|
13
stdscan.h
13
stdscan.h
@ -11,8 +11,15 @@
|
||||
#ifndef SICSSTDSCAN
|
||||
#define SICSSTDSCAN
|
||||
|
||||
/**
|
||||
* make a filename according to SICS rules for this scan
|
||||
*/
|
||||
char *ScanMakeFileName(SicsInterp *pSics, SConnection *pCon);
|
||||
|
||||
/*
|
||||
* write the header bits from the template
|
||||
*/
|
||||
void WriteTemplate(FILE *fd, FILE *temp, char *filename, pScanData pScan,
|
||||
SConnection *pCon, SicsInterp *pSics);
|
||||
/**
|
||||
* write the header of the scan file
|
||||
*/
|
||||
@ -36,7 +43,9 @@
|
||||
* second version of PrepareScan which does not check scan limits
|
||||
*/
|
||||
int NonCheckPrepare(pScanData self);
|
||||
|
||||
/**
|
||||
* prepare for a scan without complaining...
|
||||
*/
|
||||
int SilentPrepare(pScanData self);
|
||||
/**
|
||||
* ScanDrive handles driving to the scan point iPoint.
|
||||
|
53
tasscanub.c
53
tasscanub.c
@ -197,6 +197,8 @@ static int TASUBHeader(pScanData self)
|
||||
int fx;
|
||||
tasReflection r;
|
||||
double kfix;
|
||||
pSicsVariable sVar = NULL;
|
||||
float f1, f2, f3, f4;
|
||||
|
||||
assert(self);
|
||||
assert(pTAS);
|
||||
@ -345,6 +347,57 @@ static int TASUBHeader(pScanData self)
|
||||
r.qe.qk,
|
||||
r.qe.ql);
|
||||
|
||||
/*
|
||||
* write mupad stuff if available
|
||||
*/
|
||||
sVar = FindCommandData(pServ->pSics,"w1","SicsVariable");
|
||||
if(sVar != NULL)
|
||||
{
|
||||
f1 = sVar->fVal;
|
||||
sVar = FindCommandData(pServ->pSics,"w2","SicsVariable");
|
||||
if(sVar != NULL)
|
||||
{
|
||||
f2 = sVar->fVal;
|
||||
}
|
||||
sVar = FindCommandData(pServ->pSics,"w3","SicsVariable");
|
||||
if(sVar != NULL)
|
||||
{
|
||||
f3 = sVar->fVal;
|
||||
}
|
||||
sVar = FindCommandData(pServ->pSics,"w4","SicsVariable");
|
||||
if(sVar != NULL)
|
||||
{
|
||||
f4 = sVar->fVal;
|
||||
}
|
||||
fprintf(self->fd,"PARAM: W1=%8.4f, W2=%8.4f, W3=%8.4f, W4=%8.4f\n",
|
||||
f1, f2, f3, f4);
|
||||
|
||||
sVar = FindCommandData(pServ->pSics,"p1","SicsVariable");
|
||||
if(sVar != NULL)
|
||||
{
|
||||
f1 = sVar->fVal;
|
||||
}
|
||||
sVar = FindCommandData(pServ->pSics,"p2","SicsVariable");
|
||||
if(sVar != NULL)
|
||||
{
|
||||
f2 = sVar->fVal;
|
||||
}
|
||||
sVar = FindCommandData(pServ->pSics,"p3","SicsVariable");
|
||||
if(sVar != NULL)
|
||||
{
|
||||
f3 = sVar->fVal;
|
||||
}
|
||||
sVar = FindCommandData(pServ->pSics,"p4","SicsVariable");
|
||||
if(sVar != NULL)
|
||||
{
|
||||
f4 = sVar->fVal;
|
||||
}
|
||||
fprintf(self->fd,"PARAM: P1=%8.4f, P2=%8.4f, P3=%8.4f, P4=%8.4f\n",
|
||||
f1, f2, f3, f4);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
write currents if in polarisation mode
|
||||
*/
|
||||
|
51
tasub.c
51
tasub.c
@ -241,6 +241,10 @@ int TasUBFactory(SConnection *pCon,SicsInterp *pSics, void *pData,
|
||||
SCWrite(pCon,"ERROR: need name to install tasUB",eError);
|
||||
return 0;
|
||||
}
|
||||
if(argc > 2 && argc < 14){
|
||||
SCWrite(pCon,"ERROR: not enough motor names specified form MakeTasUB",eError);
|
||||
return 0;
|
||||
}
|
||||
pNew = MakeTasUB();
|
||||
if(pNew == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory creating tasUB",eError);
|
||||
@ -250,19 +254,39 @@ int TasUBFactory(SConnection *pCon,SicsInterp *pSics, void *pData,
|
||||
/*
|
||||
assign motors
|
||||
*/
|
||||
pNew->motors[0] = FindMotor(pSics,"a1");
|
||||
pNew->motors[1] = FindMotor(pSics,"a2");
|
||||
pNew->motors[2] = FindMotor(pSics,"mcv");
|
||||
pNew->motors[3] = FindMotor(pSics,"mch");
|
||||
pNew->motors[4] = FindMotor(pSics,"a3");
|
||||
pNew->motors[5] = FindMotor(pSics,"a4");
|
||||
pNew->motors[6] = FindMotor(pSics,"sgu");
|
||||
pNew->motors[7] = FindMotor(pSics,"sgl");
|
||||
pNew->motors[8] = FindMotor(pSics,"a5");
|
||||
pNew->motors[9] = FindMotor(pSics,"a6");
|
||||
pNew->motors[10] = FindMotor(pSics,"acv");
|
||||
pNew->motors[11] = FindMotor(pSics,"ach");
|
||||
|
||||
if(argc < 14){
|
||||
/*
|
||||
* default names and assignement
|
||||
*/
|
||||
pNew->motors[0] = FindMotor(pSics,"a1");
|
||||
pNew->motors[1] = FindMotor(pSics,"a2");
|
||||
pNew->motors[2] = FindMotor(pSics,"mcv");
|
||||
pNew->motors[3] = FindMotor(pSics,"mch");
|
||||
pNew->motors[4] = FindMotor(pSics,"a3");
|
||||
pNew->motors[5] = FindMotor(pSics,"a4");
|
||||
pNew->motors[6] = FindMotor(pSics,"sgu");
|
||||
pNew->motors[7] = FindMotor(pSics,"sgl");
|
||||
pNew->motors[8] = FindMotor(pSics,"a5");
|
||||
pNew->motors[9] = FindMotor(pSics,"a6");
|
||||
pNew->motors[10] = FindMotor(pSics,"acv");
|
||||
pNew->motors[11] = FindMotor(pSics,"ach");
|
||||
} else {
|
||||
/*
|
||||
* user defined names
|
||||
*/
|
||||
pNew->motors[0] = FindMotor(pSics,argv[2]);
|
||||
pNew->motors[1] = FindMotor(pSics,argv[3]);
|
||||
pNew->motors[2] = FindMotor(pSics,argv[4]);
|
||||
pNew->motors[3] = FindMotor(pSics,argv[5]);
|
||||
pNew->motors[4] = FindMotor(pSics,argv[6]);
|
||||
pNew->motors[5] = FindMotor(pSics,argv[7]);
|
||||
pNew->motors[6] = FindMotor(pSics,argv[8]);
|
||||
pNew->motors[7] = FindMotor(pSics,argv[9]);
|
||||
pNew->motors[8] = FindMotor(pSics,argv[10]);
|
||||
pNew->motors[9] = FindMotor(pSics,argv[11]);
|
||||
pNew->motors[10] = FindMotor(pSics,argv[12]);
|
||||
pNew->motors[11] = FindMotor(pSics,argv[13]);
|
||||
}
|
||||
/*
|
||||
curvature motors may be missing, anything else is a serious problem
|
||||
*/
|
||||
@ -275,6 +299,7 @@ int TasUBFactory(SConnection *pCon,SicsInterp *pSics, void *pData,
|
||||
status += testMotor(pNew, pCon,"a5",A5);
|
||||
status += testMotor(pNew, pCon,"a6",A6);
|
||||
if(status != 8){
|
||||
SCWrite(pCon,"ERROR: a required motor is mssing, tasub NOT installed",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
11
ubcalc.c
11
ubcalc.c
@ -541,6 +541,7 @@ static int cellFromUBWrapper(pUBCALC self, SConnection *pCon){
|
||||
int UBCalcWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]){
|
||||
pUBCALC self = (pUBCALC)pData;
|
||||
char pBuffer[512];
|
||||
|
||||
assert(self);
|
||||
if(argc < 2){
|
||||
@ -550,7 +551,15 @@ int UBCalcWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
strtolower(argv[1]);
|
||||
|
||||
if(strcmp(argv[1],"cell") == 0){
|
||||
return readCell(pCon, self, argc, argv);
|
||||
if(argc > 3){
|
||||
return readCell(pCon, self, argc, argv);
|
||||
} else {
|
||||
snprintf(pBuffer,511,"ubcalc cell = %f %f %f %f %f %f",
|
||||
self->direct.a, self->direct.b, self->direct.c,
|
||||
self->direct.alpha, self->direct.beta,self->direct.gamma);
|
||||
SCWrite(pCon,pBuffer,eValue);
|
||||
return 1;
|
||||
}
|
||||
} else if(strcmp(argv[1],"ref1") == 0){
|
||||
return readReflection(pCon,pSics, &self->r1,argc,argv);
|
||||
} else if(strcmp(argv[1],"ref2") ==0){
|
||||
|
Reference in New Issue
Block a user