diff --git a/SCinter.c b/SCinter.c index fcdcc5eb..9fcfd259 100644 --- a/SCinter.c +++ b/SCinter.c @@ -35,6 +35,8 @@ IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + + M. Zolliker, Sept 2000, introduced formal aliases, modifications marked M.Z ---------------------------------------------------------------------------*/ #include #include @@ -51,6 +53,8 @@ #include "devexec.h" #include "servlog.h" #include "macro.h" +/* M.Z. */ +#include "definealias.h" #define MAXLEN 256 #define MAXPAR 100 @@ -68,6 +72,7 @@ return NULL; } pInter->pCList = NULL; + pInter->AList.pFirst = NULL; /* M.Z. */ pInter->pTcl = (void *)MacroInit(pInter); if(!pInter->pTcl) { @@ -91,6 +96,7 @@ strcpy(pBueffel,pName); strtolower(pBueffel); + RemoveAlias(&pInterp->AList,pBueffel); /* M.Z. */ if(FindCommand(pInterp,pBueffel) != NULL) { return 0; @@ -276,7 +282,7 @@ extern char *SkipSpace(char *pPtr); CommandList *FindCommand(SicsInterp *self, char *pName) { CommandList *pCurrent = NULL; - char pBueffel[256]; + char pBueffel[256], *pCmd; assert(self); @@ -287,12 +293,15 @@ extern char *SkipSpace(char *pPtr); strcpy(pBueffel,pName); strtolower(pBueffel); + + pCmd=TranslateAlias(&self->AList, pBueffel); /* M.Z. */ + pCurrent = self->pCList; while(pCurrent) { if(pCurrent->pName != NULL) { - if(strcmp(pCurrent->pName, pBueffel) == 0 ) + if(strcmp(pCurrent->pName, pCmd) == 0 ) /* M.Z. */ { return pCurrent; } @@ -371,6 +380,8 @@ extern char *SkipSpace(char *pPtr); pCurrent = pTemp; } + FreeAliasList(&self->AList); /* M.Z. */ + /* clear Tcl_Interpreter. Must be AFTER deleting command list because some devices may have Tcl drivers which need to be accessed for proper closing of devices. @@ -512,3 +523,4 @@ extern char *SkipSpace(char *pPtr); } return NULL; } + diff --git a/SCinter.h b/SCinter.h index b8be9d91..1b83e597 100644 --- a/SCinter.h +++ b/SCinter.h @@ -10,6 +10,8 @@ #ifndef SICSINTERPRETER #define SICSINTERPRETER #include "Scommon.h" +/* M.Z. */ +#include "definealias.i" typedef struct __SConnection *pSConnection; typedef struct __SINTER *pSicsInterp; @@ -35,6 +37,7 @@ typedef struct __SINTER OutCode eOut; void *pTcl; int iDeleting; + AliasList AList; /* M.Z. */ }SicsInterp; /*-------------------------------------------------------------------------*/ @@ -128,5 +131,6 @@ typedef struct __SINTER to the commands data structure is retuned. Else NULL */ void *FindCommandData(SicsInterp *pSics, char *name, char *comclass); + #endif diff --git a/definealias.c b/definealias.c new file mode 100644 index 00000000..5845cb9c --- /dev/null +++ b/definealias.c @@ -0,0 +1,217 @@ +/*--------------------------------------------------------------------------- + + One more approach for the implementation of Aliases + + + + Markus Zolliker, September 2000 + + Copyright: + + Labor fuer Neutronenstreuung + Paul Scherrer Institut + CH-5423 Villigen-PSI + + + The authors hereby grant permission to use, copy, modify, distribute, + and license this software and its documentation for any purpose, provided + that existing copyright notices are retained in all copies and that this + notice is included verbatim in any distributions. No written agreement, + license, or royalty fee is required for any of the authorized uses. + Modifications to this software may be copyrighted by their authors + and need not follow the licensing terms described here, provided that + the new terms are clearly indicated on the first page of each file where + they apply. + + IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY + FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY + DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE + IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE + NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +---------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include "fortify.h" +#include "definealias.h" + +typedef struct __Aitem { + struct __Aitem *pNext; + char *pName; + char *pCmd; + } AliasItem; + +/*------------------------------------------------------------------------*/ + char *TranslateAlias(AliasList *pAList, char *pCmd) + { + AliasItem *pAlias; + + assert(pAList!=NULL && pCmd!=NULL); + + pAlias=pAList->pFirst; + while (pAlias!=NULL) + { + if (0 == strcmp(pAlias->pName, pCmd)) + { + pCmd = pAlias->pCmd; /* note that there may be cascaded translations */ + } + pAlias = pAlias->pNext; + } + return(pCmd); + } +/*------------------------------------------------------------------------*/ + int RemoveAlias(AliasList *pAList, char *pCmd) + { + AliasItem *pAlias = NULL, *pPrev = NULL; + + assert(pAList!=NULL && pCmd!=NULL); + + pPrev=(AliasItem *)pAList; + pAlias=pAList->pFirst; + while (pAlias != NULL && 0 != strcmp(pAlias->pName, pCmd)) + { + pPrev = pAlias; + pAlias = pAlias->pNext; + } + if (pAlias==NULL) + { + return 0; /* not found */ + } + + /* remove it */ + pPrev->pNext = pAlias->pNext; + free(pAlias->pName); + free(pAlias->pCmd); + free(pAlias); + return(1); + } +/*------------------------------------------------------------------------*/ + void FreeAliasList(AliasList *pAList) + { + AliasItem *pAlias = NULL, *pNext = NULL; + + assert(pAList!=NULL); + + pAlias=pAList->pFirst; + while (pAlias != NULL) + { + pNext=pAlias->pNext; + free(pAlias->pName); + free(pAlias->pCmd); + free(pAlias); + pAlias = pNext; + } + } +/*------------------------------------------------------------------------*/ + char *CreateAlias(AliasList *pAList, char *pName, char *pTranslation) + { /* arguments must be lower case */ + AliasItem *pAlias = NULL, *pNew = NULL, *pTail = NULL; + char *pCmd; + + /* translate 2nd argument */ + pCmd=TranslateAlias(pAList, pTranslation); + if (0==strcmp(pName, pCmd)) /* translation matches */ + { + return "recursive alias not allowed"; + } + + /* find last element pTail and check that alias does not yet exist */ + pTail = (AliasItem *)pAList; + pAlias = pAList->pFirst; + while (pAlias!=NULL) + { + pTail=pAlias; + if (0 == strcmp(pAlias->pName, pName)) + { + return "alias already exists"; + } + pAlias = pAlias->pNext; + } + + /* allocate the list entry */ + pNew = malloc(sizeof(AliasItem)); + if (pNew!=NULL) + { + pNew->pNext = NULL; + pNew->pName = strdup(pName); + if (pNew->pName!=NULL) + { + pNew->pCmd = strdup(pCmd); + if (pNew->pCmd!=NULL) + { + /* insert at tail */ + pTail->pNext = pNew; + return NULL; /* o.k. */ + } + } + } + return "not enough memory to create an alias"; + + } + +/*------------------------------------------------------------------------*/ + int DefineAlias(pSConnection pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]) + { + char pBueffel[256]; + int iRet; + CommandList *pCom = NULL; + char *pErr; + + if(!SCMatchRights(pCon,usMugger)) + { + SCWrite(pCon,"ERROR: only managers may define aliases", + eError); + return 0; + } + + argtolower(argc,argv); + + if(argc == 2) /* remove case */ + { + iRet=RemoveAlias(&pSics->AList, argv[1]); + if (iRet==0) + { + SCWrite(pCon,"ERROR: alias not found", + eError); + return 0; + } + return 1; + } + if(argc != 3) + { + SCWrite(pCon,"ERROR: illegal number of arguments to DefineAlias", + eError); + return 0; + } + + pCom = FindCommand(pSics, argv[1]); + if (pCom!=NULL) + { + SCWrite(pCon,"ERROR: an alias must not overwrite a command", + eError); + return 0; + } + + /* remove the old alias, if any */ + RemoveAlias(&pSics->AList, argv[1]); + + pErr=CreateAlias(&pSics->AList, argv[1], argv[2]); + if (pErr!=NULL) + { + sprintf(pBueffel,"ERROR: %s", pErr); + SCWrite(pCon,pBueffel,eError); + return 0; + } + + return 1; + } + diff --git a/definealias.h b/definealias.h new file mode 100644 index 00000000..9fbb5a55 --- /dev/null +++ b/definealias.h @@ -0,0 +1,93 @@ +/*-------------------------------------------------------------------------- + + D E F I N E A L I A S E S . C + + Markus Zolliker, September 2000 + + copyright: see implementation file + + More general and safe Aliases: + + - an alias may be defined even if the corresponding command + does not yet exist + + - SICS does not crash when the original command of an alias is + removed + +---------------------------------------------------------------------------*/ +#ifndef DEFINE_ALIAS +#define DEFINE_ALIAS +#include "conman.h" +#include "definealias.i" + +/*---------------------------------------------------------------------------*/ + char *TranslateAlias(AliasList *pAList, char *pCmd); + /* + translate the command *pCmd + - the translation may go through several steps + - if no translation is found, the return value is equal to pCmd + - no strings are copied + - the return value becomes invalid when the corresponding alias is removed + - *pCmd must be lowercase + */ + +/*---------------------------------------------------------------------------*/ + int RemoveAlias(AliasList *pAList, char *pCmd); + /* + remove the alias *pCmd + - returns 1 when the alias existed, 0 otherwise + - *pCmd must be lowercase + */ + +/*---------------------------------------------------------------------------*/ + void FreeAliasList(AliasList *pAList); + /* + dispose the alias list + */ + +/*---------------------------------------------------------------------------*/ + char *CreateAlias(AliasList *pAList, char *pName, char *pTranslation); + + /* + create a new alias *pName with the translation *pTranslation + + - the alias *pName must not yet exist + - *pTranslation is translated first + - recursive definitions are prohibited + - *pName and *pTranslation must be lowercase + + if the creation is successful, the return value is NULL, otherwise + it points to one of the following error messages: + + "recursive alias not allowed" + "alias already exists" + "not enough memory to create an alias" + + */ + +/*---------------------------------------------------------------------------*/ + int DefineAlias(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); + + /* this command requires manager privileges + + argv[1]: the alias to define + - must not be a proper SICS command + - if an alias with this name exists already, it is removed first + + argv[2]: the original command + - if omitted, the alias is removed + - if it is an alias the definiton refers to it's translation + - may be an unknown command (probably defined later) + + - AddCommand removes an eventual alias matching the command name + + - RemoveCommand does not remove it's aliases + Trying to use an alias of a removed command leads to the error message + "object > ... < NOT found" + + - trying to define a recursive alias leads the error message + "recursive alias not allowed" + */ + +#endif diff --git a/definealias.i b/definealias.i new file mode 100644 index 00000000..fa0b1741 --- /dev/null +++ b/definealias.i @@ -0,0 +1,20 @@ +/*-------------------------------------------------------------------------- + + AliasList datastructure + + Markus Zolliker, September 2000 + + copyright: see implementation file + +---------------------------------------------------------------------------*/ +#ifndef DEFINE_ALIAS_I +#define DEFINE_ALIAS_I + +typedef struct { + void *pFirst; + } AliasList; + + /* + initialize pFirst to NULL to create an empty list + */ +#endif diff --git a/ofac.c b/ofac.c index 0d073bb1..cdd73c7c 100644 --- a/ofac.c +++ b/ofac.c @@ -248,6 +248,7 @@ AddCommand(pInter,"MakeRuenBuffer",InitBufferSys,NULL,NULL); AddCommand(pInter,"MakeO2T",CreateO2T,NULL,NULL); AddCommand(pInter,"SicsAlias",SicsAlias,NULL,NULL); + AddCommand(pInter,"DefineAlias",DefineAlias,NULL,NULL); /* M.Z. */ AddCommand(pInter,"InitDMC",InitDmc,NULL,NULL); AddCommand(pInter,"InitSANS",InitSANS,NULL,NULL); AddCommand(pInter,"MakeHM",MakeHistMemory,NULL,NULL);