ftp.nice.ch/pub/next/unix/calendars/remind.3.0.13.N.bs.tar.gz#/remind-3.0.13/var.c

This is var.c in view mode; [Download] [Up]

/***************************************************************/
/*                                                             */
/*  VAR.C                                                      */
/*                                                             */
/*  This file contains routines, structures, etc for           */
/*  user- and system-defined variables.                        */
/*                                                             */
/*  This file is part of REMIND.                               */
/*  Copyright (C) 1992, 1993, 1994 by David F. Skoll           */
/*                                                             */
/***************************************************************/

#include "config.h"
#include <stdio.h>
#include <string.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include <ctype.h>
#include "types.h"
#include "expr.h"
#include "globals.h"
#include "protos.h"
#include "err.h"

#define UPPER(c) (islower(c) ? toupper(c) : c)

/* The variable hash table */
#define VAR_HASH_SIZE 64
#define VARIABLE ErrMsg[E_VAR]
#define VALUE    ErrMsg[E_VAL]
#define UNDEF	 ErrMsg[E_UNDEF]

static Var *VHashTbl[VAR_HASH_SIZE];

/***************************************************************/
/*                                                             */
/*  HashVal                                                    */
/*  Given a string, compute the hash value.                    */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC unsigned int HashVal(const char *str)
#else
unsigned int HashVal(str)
char *str;
#endif
{
   register unsigned int i=0;
   register unsigned int j=1;
   register unsigned int len=0;

   while(*str && len < VAR_NAME_LEN) {
      i += j * (unsigned int) UPPER(*str);
      str++;
      len++;
      j = 3-j;
   }
   return i;
}

/***************************************************************/
/*                                                             */
/*  FindVar                                                    */
/*  Given a string, find the variable whose name is that       */
/*  string.  If create is 1, create the variable.              */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC Var *FindVar(const char *str, int create)
#else
Var *FindVar(str, create)
char *str;
int create;
#endif
{
   register int h;
   register Var *v;
   register Var *prev;

   h = HashVal(str) % VAR_HASH_SIZE;
   v = VHashTbl[h];
   prev = NULL;

   while(v) {
      if (! StrinCmp(str, v->name, VAR_NAME_LEN)) return v;
      prev = v;
      v = v-> next;
   }
   if (!create) return v;

/* Create the variable */
   v = NEW(Var);
   if (!v) return v;
   v->next = NULL;
   v->v.type = INT_TYPE;
   v->v.v.val = 0;
   v->preserve = 0;
   StrnCpy(v->name, str, VAR_NAME_LEN);

   if (prev) prev->next = v; else VHashTbl[h] = v;
   return v;
}

/***************************************************************/
/*                                                             */
/*  DeleteVar                                                  */
/*  Given a string, find the variable whose name is that       */
/*  string and delete it.                                      */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DeleteVar(const char *str)
#else
int DeleteVar(str)
char *str;
#endif
{
   register int h;
   register Var *v;
   register Var *prev;

   h = HashVal(str) % VAR_HASH_SIZE;
   v = VHashTbl[h];
   prev = NULL;

   while(v) {
      if (! StrinCmp(str, v->name, VAR_NAME_LEN)) break;
      prev = v;
      v = v-> next;
   }
   if (!v) return E_NOSUCH_VAR;
   DestroyValue(v->v);
   if (prev) prev->next = v->next; else VHashTbl[h] = v->next;
   free(v);
   return OK;
}

/***************************************************************/
/*                                                             */
/*  SetVar                                                     */
/*                                                             */
/*  Set the indicate variable to the specified value.          */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int SetVar(const char *str, Value *val)
#else
int SetVar(str, val)
char *str;
Value *val;
#endif
{
   Var *v = FindVar(str, 1);

   if (!v) return E_NO_MEM;  /* Only way FindVar can fail */

   DestroyValue(v->v);
   v->v = *val;
   return OK;
}

/***************************************************************/
/*                                                             */
/*  GetVarValue                                                */
/*                                                             */
/*  Get a copy of the value of the variable.                   */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int GetVarValue(const char *str, Value *val, Var *locals)
#else
int GetVarValue(str, val, locals)
char *str;
Value *val;
Var *locals;
#endif
{
   Var *v;

   /* Try searching local variables first */
   v = locals;
   while (v) {
      if (! StrinCmp(str, v->name, VAR_NAME_LEN))
	 return CopyValue(val, &v->v);
      v = v->next;
   }

   v=FindVar(str, 0);

   if (!v) {
     Eprint("%s: %s", ErrMsg[E_NOSUCH_VAR], str);
     return E_NOSUCH_VAR;
   }
   return CopyValue(val, &v->v);
}

/***************************************************************/
/*                                                             */
/*  DoSet - set a variable.                                    */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DoSet (Parser *p)
#else
int DoSet (p)
Parser *p;
#endif
{
   Value v;
   int r;

   r = ParseIdentifier(p, TokBuffer);
   if (r) return r;

   r = EvaluateExpr(p, &v);
   if (r) return r;

   if (*TokBuffer == '$') return SetSysVar(TokBuffer+1, &v);
   else return SetVar(TokBuffer, &v);
}

/***************************************************************/
/*                                                             */
/*  DoUnset - delete a bunch of variables.                     */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DoUnset (Parser *p)
#else
int DoUnset (p)
Parser *p;
#endif
{
   int r;

   r = ParseToken(p, TokBuffer);
   if (r) return r;
   if (!*TokBuffer) return E_EOLN;

   (void) DeleteVar(TokBuffer);  /* Ignore error - nosuchvar */

/* Keep going... */
   while(1) {
      r = ParseToken(p, TokBuffer);
      if (r) return r;
      if (!*TokBuffer) return OK;
      (void) DeleteVar(TokBuffer);
   }
}

/***************************************************************/
/*                                                             */
/*  DoDump                                                     */
/*                                                             */
/*  Command file command to dump variable table.               */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DoDump(ParsePtr p)
#else
int DoDump(p)
ParsePtr p;
#endif
{
   int r;
   Var *v;

   r = ParseToken(p, TokBuffer);
   if (r) return r;
   if (!*TokBuffer || *TokBuffer == '#' || *TokBuffer == ';') {
      DumpVarTable();
      return OK;
   }
   fprintf(ErrFp, "%*s  %s\n\n", VAR_NAME_LEN, VARIABLE, VALUE);
   while(1) {
      if (*TokBuffer == '$') {
         DumpSysVarByName(TokBuffer+1);
      } else {
         v = FindVar(TokBuffer, 0);
         TokBuffer[VAR_NAME_LEN] = 0;
         if (!v) fprintf(ErrFp, "%*s  %s\n", VAR_NAME_LEN, TokBuffer, UNDEF);
         else {
            fprintf(ErrFp, "%*s  ", VAR_NAME_LEN, v->name);
            PrintValue(&(v->v), ErrFp);
            fprintf(ErrFp, "\n");
         }
      }
      r = ParseToken(p, TokBuffer);
      if (r) return r;
      if (!*TokBuffer || *TokBuffer == '#' || *TokBuffer == ';') return OK;
   }
}

/***************************************************************/
/*                                                             */
/*  DumpVarTable                                               */
/*                                                             */
/*  Dump the variable table to stderr.                         */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC void DumpVarTable(void)
#else
void DumpVarTable()
#endif
{
   register Var *v;
   register int i;

   fprintf(ErrFp, "%*s  %s\n\n", VAR_NAME_LEN, VARIABLE, VALUE);

   for (i=0; i<VAR_HASH_SIZE; i++) {
      v = VHashTbl[i];
      while(v) {
         fprintf(ErrFp, "%*s  ", VAR_NAME_LEN, v->name);
         PrintValue(&(v->v), ErrFp);
         fprintf(ErrFp, "\n");
	 v = v->next;
      }
   }
}

/***************************************************************/
/*                                                             */
/*  DestroyVars                                                */
/*                                                             */
/*  Free all the memory used by variables, but don't delete    */
/*  preserved variables unless ALL is non-zero.                */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC void DestroyVars(int all)
#else
void DestroyVars(all)
int all;
#endif
{
   int i;
   Var *v, *next, *prev;

   for (i=0; i<VAR_HASH_SIZE; i++) {
      v = VHashTbl[i];
      VHashTbl[i] = NULL;
      prev = NULL;
      while(v) {
         if (all || !v->preserve) {
            DestroyValue(v->v);
   	    next = v->next;
	    free(v);
	 } else {
	    if (prev) prev->next = v;
	    else VHashTbl[i] = v;
	    prev = v;
	    next = v->next;
	    v->next = NULL;
         }
	 v = next;
      }
   }
}

/***************************************************************/
/*                                                             */
/*  PreserveVar                                                */
/*                                                             */
/*  Given the name of a variable, "preserve" it.               */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int PreserveVar(char *name)
#else
int PreserveVar(name)
char *name;
#endif
{
   Var *v;

   v = FindVar(name, 1);
   if (!v) return E_NO_MEM;
   v->preserve = 1;
   return OK;
}

/***************************************************************/
/*                                                             */
/*  DoPreserve - preserve a bunch of variables.                */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DoPreserve (Parser *p)
#else
int DoPreserve (p)
Parser *p;
#endif
{
   int r;

   r = ParseToken(p, TokBuffer);
   if (r) return r;
   if (!*TokBuffer) return E_EOLN;

   r = PreserveVar(TokBuffer);
   if (r) return r;

/* Keep going... */
   while(1) {
      r = ParseToken(p, TokBuffer);
      if (r) return r;
      if (!*TokBuffer) return OK;
      r = PreserveVar(TokBuffer);
      if (r) return r;
   }
}

/***************************************************************/
/*                                                             */
/*  SYSTEM VARIABLES                                           */
/*                                                             */
/*  Interface for modifying and reading system variables.      */
/*                                                             */
/***************************************************************/

/* The structure of a system variable */
typedef struct {
   char *name;
   char modifiable;
   int type;
   void *value;
   int min;
   int max;
} SysVar;

/* If the type of a sys variable is STR_TYPE, then min is redefined
   to be a flag indicating whether or not the value has been malloc'd. */
#define been_malloced min

/* Flag for no min/max constraint */
#define ANY 4532
/* All of the system variables sorted alphabetically */
static SysVar SysVarArr[] = {
       /* name		  mod	type		value		min/mal	max */
   {   "CalcUTC",	  1,	INT_TYPE,	&CalculateUTC,	0,	1   },
   {   "CalMode",	  0,	INT_TYPE,	&DoCalendar,	0,	0   },
   {   "Daemon",	  0,	INT_TYPE,	&Daemon,	0,	0   },
   {   "DefaultPrio",	  1,	INT_TYPE,	&DefaultPrio,	0,	9999 },
   {   "DontFork",	  0,	INT_TYPE,	&DontFork,	0,	0   },
   {   "DontQueue",	  0,	INT_TYPE,	&DontQueue,	0,	0   },
   {   "DontTrigAts",	  0,	INT_TYPE,	&DontIssueAts,	0,	0   },
   {   "EndSent",	  1,	STR_TYPE,	&EndSent,	0,	0   },
   {   "EndSentIg",	  1,	STR_TYPE,	&EndSentIg,	0,	0   },
   {   "FirstIndent",	  1,	INT_TYPE,	&FirstIndent,	0,	132 },
   {   "FoldYear",	  1,	INT_TYPE,	&FoldYear,	0,	1   },
   {   "FormWidth",	  1,	INT_TYPE,	&FormWidth,	20,	132 },
   {   "HushMode",	  0,	INT_TYPE,	&Hush,		0,	0   },
   {   "IgnoreOnce",	  0,	INT_TYPE,	&IgnoreOnce,	0,	0   },
   {   "InfDelta",	  0,	INT_TYPE,	&InfiniteDelta,	0,	0   },
   {   "LatDeg",	  1,	INT_TYPE,	&LatDeg,	-90,	90  },
   {   "LatMin",	  1,	INT_TYPE,	&LatMin,	-59,	59  },
   {   "LatSec",	  1,	INT_TYPE,	&LatSec,	-59,	59  },
   {   "Location",	  1,	STR_TYPE,	&Location,	0,	0   },
   {   "LongDeg",	  1,	INT_TYPE,	&LongDeg,	-180,	180  },
   {   "LongMin",	  1,	INT_TYPE,	&LongMin,	-59,	59  },
   {   "LongSec",	  1,	INT_TYPE,	&LongSec,	-59,	59  },
   {   "MaxSatIter",	  1,	INT_TYPE,	&MaxSatIter,	10,	ANY },
   {   "MinsFromUTC",	  1,	INT_TYPE,	&MinsFromUTC,	-13*60,	13*60 },
   {   "NextMode",	  0,	INT_TYPE,	&NextMode,	0,	0   },
   {   "NumQueued",	  0,	INT_TYPE,	&NumQueued,	0,	0   },
   {   "NumTrig",	  0,	INT_TYPE,	&NumTriggered,	0,	0   },
   {   "PSCal",		  0,	INT_TYPE,	&PsCal,		0,	0   },
   {   "RunOff",	  0,	INT_TYPE,	&RunDisabled,	0,	0   },
   {   "SimpleCal",	  0,	INT_TYPE,	&DoSimpleCalendar,	0,  0 },
   {   "SortByDate",	  0,	INT_TYPE,	&SortByDate,	0,	0},
   {   "SortByPrio",	  0,	INT_TYPE,	&SortByPrio,	0,	0},
   {   "SortByTime",	  0,	INT_TYPE,	&SortByTime,	0,	0},
   {   "SubsIndent",	  1,	INT_TYPE,	&SubsIndent,	0,	132}
};

#define NUMSYSVARS ( sizeof(SysVarArr) / sizeof(SysVar) )
PRIVATE SysVar *FindSysVar ARGS((const char *name));
PRIVATE void DumpSysVar ARGS((const char *name, const SysVar *v));
/***************************************************************/
/*                                                             */
/*  SetSysVar                                                  */
/*                                                             */
/*  Set a system variable to the indicated value.              */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int SetSysVar(const char *name, Value *value)
#else
int SetSysVar(name, value)
char *name;
Value *value;
#endif
{
   SysVar *v = FindSysVar(name);
   if (!v) return E_NOSUCH_VAR;
   if (v->type != value->type) return E_BAD_TYPE;
   if (!v->modifiable) {
      Eprint("%s: '$%s'", ErrMsg[E_CANT_MODIFY], name);
      return E_CANT_MODIFY;
   }

/* If it's a string variable, special measures must be taken */
   if (v->type == STR_TYPE) {
      if (v->been_malloced) free(*((char **)(v->value)));
      v->been_malloced = 1;
      *((char **) v->value) = value->v.str;
      value->type = ERR_TYPE;  /* So that it's not accidentally freed */
   } else {
      if (v->max != ANY && value->v.val > v->max) return E_2HIGH;
      if (v->min != ANY && value->v.val < v->min) return E_2LOW;
      *((int *)v->value) = value->v.val;
   }
   return OK;
}

/***************************************************************/
/*                                                             */
/*  GetSysVar                                                  */
/*                                                             */
/*  Get the value of a system variable                         */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int GetSysVar(const char *name, Value *val)
#else
int GetSysVar(name, val)
char *name;
Value *val;
#endif
{
   SysVar *v = FindSysVar(name);

   val->type = ERR_TYPE;
   if (!v) return E_NOSUCH_VAR;
   if (v->type == STR_TYPE) {
      val->v.str = StrDup(*((char **) v->value));
      if (!val->v.str) return E_NO_MEM;
   } else {
      val->v.val = *((int *) v->value);
   }
   val->type = v->type;
   return OK;
}

/***************************************************************/
/*                                                             */
/* FindSysVar                                                  */
/*                                                             */
/* Find a system var with specified name.                      */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE SysVar *FindSysVar(const char *name)
#else
static SysVar *FindSysVar(name)
char *name;
#endif
{
   int top=NUMSYSVARS-1, bottom=0;
   int mid=(top + bottom) / 2;
   int r;

   while (top >= bottom) {
      r = StrCmpi(name, SysVarArr[mid].name);
      if (!r) return &SysVarArr[mid];
      else if (r>0) bottom = mid+1;
      else	    top = mid-1;
      mid = (top+bottom) / 2;
   }
   return NULL;
}
   
/***************************************************************/
/*                                                             */
/*  DumpSysVarByName                                           */
/*                                                             */
/*  Given the name of a system variable, display it.           */
/*  If name is "", dump all system variables.                  */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC void DumpSysVarByName(const char *name)
#else
void DumpSysVarByName(name)
char *name;
#endif
{
   int i;
   SysVar *v;

   if (!name || !*name) {
      for (i=0; i<NUMSYSVARS; i++) DumpSysVar(name, SysVarArr + i);
      return;
   }
   
   v = FindSysVar(name);
   DumpSysVar(name, v);
   return;
}

/***************************************************************/
/*                                                             */
/*  DumpSysVar                                                 */
/*                                                             */
/*  Dump the system variable.                                  */
/*                                                             */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void DumpSysVar(const char *name, const SysVar *v)
#else
static void DumpSysVar(name, v)
char *name;
SysVar *v;
#endif
{
   char buffer[VAR_NAME_LEN+10];

   if (name && !*name) name=NULL;
   if (!v && !name) return;  /* Shouldn't happen... */
   
   buffer[0]='$'; buffer[1] = 0;
   if (name) strcat(buffer, name); else strcat(buffer, v->name);
   fprintf(ErrFp, "%*s  ", VAR_NAME_LEN, buffer);
   if (v) {
      if (v->type == STR_TYPE) {
         char *s = *((char **)v->value);
	 int y;
	 putc('"', ErrFp);
	 for (y=0; y<MAX_PRT_LEN && *s; y++) putc(*s++, ErrFp);
	 putc('"', ErrFp);
	 if (*s) fprintf(ErrFp, "...");
	 putc('\n', ErrFp);
      } else {
         if (!v->modifiable) fprintf(ErrFp, "%d\n", *((int *)v->value));
         else {
            fprintf(ErrFp, "%-10d  ", *((int *)v->value));
   	    if (v->min == ANY) fprintf(ErrFp, "(-Inf, ");
	    else                         fprintf(ErrFp, "[%d, ", v->min);
	    if (v->max == ANY) fprintf(ErrFp, "Inf)\n");
	    else                         fprintf(ErrFp, "%d]\n", v->max);
         }
      }
   } else   fprintf(ErrFp, "%s\n", UNDEF);

   return;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.