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.