untermud/DOC/
untermud/DOC/U/
untermud/DOC/U/U-examples/
untermud/DOC/internals/
untermud/DOC/wizard/
untermud/MISC/
untermud/MISC/dbchk/
untermud/RWHO/
untermud/RWHO/rwhod/
/*
    Copyright (C) 1991, Marcus J. Ranum. All rights reserved.
*/

/* configure all options BEFORE including system stuff. */
#include    "config.h"
#include    "mud.h"
#include    "vars.h"
#include    "sbuf.h"
#include    "match.h"

/* WARNING - globals will robinson, globals! */
char typ_str[] = "str";
char typ_int[] = "int";
char typ_cmd[] = "cmd";
char typ_list[] = "lst";
char typ_bool[] = "boo";
char typ_obj[] = "obj";
char typ_flag[] = "flg";
char typ_u[] = "U";


char var_loc[] = "loc";
char var_cont[] = "con";
char var_xit[] = "xit";
char var_dest[] = "dst";
char var_dropto[] = "drpto";
char var_lock[] = "lok";
char var_jump[] = "jmp";
char var_link[] = "lnk";
char var_ply[] = "ply";
char var_owner[] = "own";
char var_nam[] = "nam";
char var_desc[] = "desc";
char var_text[] = "txt";
char var_pass[] = "pass";
char var_using[] = "use";
char var_wiz[] = "_wz";
char var_fail[] = "fail";
char var_ofail[] = "ofail";
char var_succ[] = "succ";
char var_osucc[] = "osucc";
char var_drop[] = "drop";
char var_odrop[] = "odrop";
char var_isplay[] = "_pl";
char var_isdark[] = "dark";
char var_isroom[] = "_rm";
char var_islocal[] = "lcl";
char var_newsart[] = "newsarticle";
char var_subive[] = "subv";
char var_Subve[] = "Subv";
char var_objive[] = "objv";
char var_Objve[] = "Objv";
char var_posive[] = "posv";
char var_Posve[] = "Posv";
char var_home[] = "home";
char var_linkmsg[] = "linkmsg";
char var_wearing[] = "_wear";


#ifdef  COMBAT
char var_strength[] = "_stren";
char var_Strength[] = "_Stren";
char var_endurance[] = "_endur";
char var_Endurance[] = "_Endur";
char var_willpower[] = "_willp";
char var_Willpower[] = "_Willp";
char var_agility[] = "_dextr";
char var_Agility[] = "_Dextr";
char var_magic[] = "_magic";
char var_Magic[] = "_Magic";
char var_action[] = "_actup";
char var_Action[] = "_Actup";
char var_power[] = "_power";
char var_counters[] = "counter";
char var_lastupd[] = "_lupd";
char var_lasthit[] = "_lhit";
char var_lastatt[] = "_latt";
char var_isdead[] = "_dead";
char var_weapon[] = "_weapon";
/* flags */
char var_isweapon[] = "_isweap";
char var_isarmor[] = "_isarm";
#endif


/* system object related stuff. */
char system_object[] = "sysobj";
char var_objcnt[] = "_objcnt";
char var_syslimbo[] = "_syslimbo";
char var_wizs[] = "_wizards";
char var_bsequence[] = "_backupseq";


/* variable type table */
TypTab ttab[] = {
  {typ_str},
  {typ_int},
  {typ_cmd},
  {typ_list},
  {typ_bool},
  {typ_obj},
  {typ_flag},
  {typ_u},
  {0}
};

/* Newusers allowed flag? */
char newusers = 0;


/*
variable permissions and other whatnots table. these should be
roughly in order of preference, since "set" chooses based on first
match
*/
VarTab vtab[] = {
  {var_desc, "description", typ_str, VAR_LOC_PUBLIC,
    "description"},

  {var_text, "text", typ_str, VAR_LOC_PUBLIC,
    "text inscription"},

  {var_fail, "failure", typ_str, VAR_MTYP,
    "failure message/command"},

  {var_ofail, "ofailure", typ_str, VAR_MTYP,
    "other player failure message/command"},

  {var_succ, "success", typ_str, VAR_MTYP,
    "success message/command"},

  {var_osucc, "osuccess", typ_str, VAR_MTYP,
    "other player success message/command"},

  {var_drop, "drop", typ_str, VAR_MTYP,
    "drop message/command"},

  {var_odrop, "odrop", typ_str, VAR_MTYP,
    "other player drop message/command"},

  {var_subive, "subjective", typ_str, VAR_LOC_PUBLIC,
    "subjective pronoun"},

  {var_Subve, "Subjective", typ_str, VAR_LOC_PUBLIC,
    "subjective pronoun (capitalized)"},

  {var_objive, "objective", typ_str, VAR_LOC_PUBLIC,
    "objective pronoun"},

  {var_Objve, "Objective", typ_str, VAR_LOC_PUBLIC,
    "objective pronoun (capitalized)"},

  {var_posive, "possessive", typ_str, VAR_LOC_PUBLIC,
    "possessive pronoun"},

  {var_Posve, "Possessive", typ_str, VAR_LOC_PUBLIC,
    "possessive pronoun (capitalized)"},


#ifdef  PLAYER_NAMECHANGING
  {var_nam, "name", typ_str, VAR_PUBLIC,
    "name"},
#else
  {var_nam, "name", typ_str, VAR_PRIVPLY | VAR_PUBLIC,
    "name"},
#endif


  {var_pass, "password", typ_str, VAR_PRIV,
    "object's password"},

  {var_owner, "owners", typ_list, 0,
    "object owner list"},

  {var_ply, "players", typ_list, VAR_LOC_PUBLIC | VAR_PRIV,
    "room player list"},

  {var_cont, "contents", typ_list, VAR_LOC_PUBLIC | VAR_PRIV,
    "contents list"},

  {var_xit, "exits", typ_list, VAR_PRIV,
    "room exit list"},

  {var_wizs, "wizardlist", typ_list, VAR_PRIV,
    "valid wizards"},

  {var_loc, "location", typ_obj, VAR_PRIV,
    "location of an object"},

  {var_dest, "destination", typ_obj, VAR_PRIV,
    "exit destination"},

  {var_dropto, "dropto", typ_obj, 0,
    "dropto destination"},

  {var_using, "holding", typ_obj, VAR_PRIV,
    "object being held by player"},

  {var_using, "using", typ_obj, VAR_PRIV,
    "object being used by player"},

  {var_home, "home", typ_obj, 0,
    "object's home location"},

  {var_jump, "jump", typ_bool, VAR_MTYP,
    "object access lock"},

  {var_lock, "lock", typ_bool, VAR_MTYP,
    "object access lock"},

  {var_link, "linkok", typ_bool, 0,
    "link permissions"},

  {var_isdark, "isdark", typ_flag, 0,
    "object is dark"},

  {var_islocal, "local", typ_flag, 0,
    "object is local"},

  {var_wiz, "wizard", typ_flag, VAR_PRIV,
    "object is a wizard"},

  {var_isplay, "isplayer", typ_flag, VAR_PRIV,
    "object is a player"},

  {var_isroom, "isroom", typ_flag, VAR_PRIV,
    "object is a room"},

  {var_newsart, "newsarticle", typ_int, 0,
    "last read news article"},

  {var_linkmsg, "linkmessage", typ_str, VAR_PRIV,
    "portal player moved through"},

  {var_wearing, "wearing", typ_list, VAR_PRIV,
    "player garments"},

#ifdef  COMBAT
  {var_strength, "strength", typ_int, VAR_PRIV,
    "player current strength"},

  {var_Strength, "Strength", typ_int, VAR_PRIV,
    "player maximum strength"},

  {var_endurance, "endurance", typ_int, VAR_PRIV,
    "player current endurance"},

  {var_Endurance, "Endurance", typ_int, VAR_PRIV,
    "player maximum endurance"},

  {var_willpower, "willpower", typ_int, VAR_PRIV,
    "player current willpower"},

  {var_Willpower, "Willpower", typ_int, VAR_PRIV,
    "player maximum willpower"},

  {var_agility, "agility", typ_int, VAR_PRIV,
    "player current agility"},

  {var_Agility, "Agility", typ_int, VAR_PRIV,
    "player maximum agility"},

  {var_magic, "magic", typ_int, VAR_PRIV,
    "player current magic level"},

  {var_Magic, "Magic", typ_int, VAR_PRIV,
    "player maximum magic level"},

  {var_action, "action", typ_int, VAR_PRIV,
    "player current action points"},

  {var_Action, "Action", typ_int, VAR_PRIV,
    "player maximum action points"},

  {var_counters, "counters", typ_list, 0,
    "player counterattack list"},

  {var_power, "power", typ_int, VAR_PRIV,
    "player current power level"},

  {var_lastupd, "lastupd", typ_str, VAR_PRIV,
    "player last combat stats update time"},

  {var_lasthit, "lasthit", typ_obj, VAR_PRIV,
    "player last attacker that hit"},

  {var_lastatt, "lastatt", typ_obj, VAR_PRIV,
    "player last attacker"},

  {var_isdead, "isdead", typ_flag, VAR_PRIV,
    "player killed by something"},

  {var_weapon, "weapon", typ_obj, VAR_PRIV,
    "player weapon in use"},

  {var_isweapon, "isweapon", typ_flag, VAR_PRIV,
    "object is weapon flag"},

  {var_isarmor, "isarmor", typ_flag, VAR_PRIV,
    "object is armor flag"},
#endif

  {0, 0, 0, 0,
    0}
};




/* return nonzero if the variable is public */
int var_ispublic (char *vn, char *who, char *aswho, char *what)
{
  char *dst;
  int exitsees = 0;
  VarTab *vp = vtab;

  /* If we're an exit, we can see also local_public at our dst */
  if (dst = ut_getatt (aswho, 0, typ_obj, var_dest, (char *) 0))
    exitsees = (!strcmp (ut_loc (what), dst));

  if (*vn == LOC_PUB_COOKIE) {
    return (!strcmp (ut_loc (who), ut_loc (what)) ||
      !strcmp (who, ut_loc (what)) ||
      !strcmp (ut_loc (who), what) || exitsees);
  }
  while (vp->vnam != (char *) 0) {
    if (!strcmp (vp->vnam, vn)) {
      if (vp->flg & VAR_PUBLIC)
        return (1);
      if (vp->flg & VAR_LOC_PUBLIC) {
        if (ut_flagged (what, var_isdark))
          return (0);
        return (!strcmp (ut_loc (who), ut_loc (what)) ||
          !strcmp (who, ut_loc (what)) ||
          !strcmp (ut_loc (who), what) || exitsees);
      }
    }
    vp++;
  }
  return (0);
}




static int set_help (char *who)
{
  VarTab *vp = vtab;
  TypTab *tp = ttab;
  char line[60];

  /* TODO - prettier format ? */
  say (who, "\nData types known to this MUD:\n", (char *) 0);
  while (tp->tnam != (char *) 0) {
    say (who, tp->tnam, " ", (char *) 0);
    tp++;
  }
  say (who, "\n\n", (char *) 0);
  say (who, "Attributes known to this MUD:\n", (char *) 0);
  say (who, "-long name- -(type :  shortname)-     -description-\n",
    (char *) 0);
  while (vp->vnam != (char *) 0) {
    snprintf (line, sizeof (line), "%-13.13s(%-5.5s:%11.11s) %23.23s",
      vp->vlong, vp->deftyp, vp->vnam, vp->desc);
    say (who, line, (char *) 0);
    if (vp->flg & VAR_PUBLIC)
      say (who, " (public)", (char *) 0);
    if (vp->flg & VAR_PRIV)
      say (who, " (wiz-only)", (char *) 0);
    if (vp->flg & VAR_MTYP)
      say (who, " (multi-type)", (char *) 0);
    if (vp->flg & VAR_PRIVPLY)
      say (who, " (wiz-only on players)", (char *) 0);
    say (who, "\n", (char *) 0);
    vp++;
  }
  say (who, "\n", (char *) 0);
  return (UERR_NONE);
}



static VarTab *var_tabfind (char *nam)
{
  VarTab *vp = vtab;

  while (vp->vnam != (char *) 0) {
    if (!strcmp (vp->vnam, nam) || !strcmp (vp->vlong, nam))
      return (vp);
    vp++;
  }
  return ((VarTab *) 0);
}



/* resolve a possible long-form name to short form */
char *var_namatch (char *nam)
{
  VarTab *vp;

  if ((vp = var_tabfind (nam)) == (VarTab *) 0)
    return ((char *) 0);
  return (vp->vnam);
}




/* ARGSUSED */
int cmd_set (int argc, char *argv[], char *who, char *aswho)
{
  char ob[MAXOID];
  char *typp;
  char *atpp;
  char *vapp;

  if (argc == 2 && !strcmp (argv[1], "help"))
    return (set_help (who));

  if (argc < 3 || argc > 5) {
    say (who, "usage: set thing [type] attribute value\n", (char *) 0);
    say (who, "or \"set help\" for help using \"set\"\n", (char *) 0);
    return (UERR_ARGCNT);
  }

  if (matchlocal (who, argv[1], ut_loc (who),
      MTCH_UNIQ | MTCH_NONLOC | MTCH_MEOK, ob))
    return (UERR_NOMATCH);

  typp = (char *) 0;
  atpp = argv[2];
  vapp = argv[3];

  /* type spec given ? */
  if (argc > 4) {
    typp = argv[2];
    atpp = argv[3];
    vapp = argv[4];
  }


  return (var_set_internal (who, aswho, ob, typp, atpp, vapp, 1));
}




/*
internal set routine -
very gross!!  but all this gook has to fit someplace
called also from U-interpreter code.
*/
int var_set_internal (char *who, char *aswho, char *ob,
  char *typp, char *atpp, char *vapp, int vbose)
{
  VarTab *vp;
  int izlist = 0;
  int wiz;

  /* can we find a match in the variable table? */
  if ((vp = var_tabfind (atpp)) != (VarTab *) 0) {
    if (typp == (char *) 0)
      typp = vp->deftyp;
    atpp = vp->vnam;
  }

  /* if it's not one of the known attributes, we need its type */
  if (typp == (char *) 0) {
    if (vbose)
      say (who, "\"", atpp, "\" type unknown. Provide its type.\n",
        (char *) 0);
    return (UERR_ILLASGN);
  }

  if (strlen (typp) == 0 || strlen (atpp) == 0 ||
    index (typp, '=') != (char *) 0 || index (atpp, '=') != (char *) 0) {
    if (vbose)
      say (who,
        "Attributes and types must be non-blank and contain no = characters.\n",
        (char *) 0);
    return (UERR_ILLASGN);
  }

  /* is this a priv'd attribute? */
  wiz = ut_flagged (aswho, var_wiz);


  /* stamp out type clash - usually - only wizards may typeclash */
  if (vp != (VarTab *) 0 && !wiz && !(vp->flg & VAR_MTYP) &&
    strcmp (typp, vp->deftyp)) {
    if (vbose)
      say (who, vp->vlong, " is only a ", vp->deftyp,
        ". You cannot set it to be a ", typp, ".\n", (char *) 0);
    return (UERR_ILLASGN);
  }


  /* priv'd attribute */
  if (vp != (VarTab *) 0 && (vp->flg & VAR_PRIV) && !wiz) {
    if (vbose)
      say (who, "You must be a wizard to set ", vp->vlong, ".\n", (char *) 0);
    return (UERR_PERM);
  }


  /* check for wiz-only on player */
  if (vp != (VarTab *) 0 && (vp->flg & VAR_PRIVPLY) && !wiz &&
    ut_flagged (ob, var_isplay)) {
    if (vbose)
      say (who, "You must be a wizard to set ", vp->vlong, " for a player.\n",
        (char *) 0);
    return (UERR_PERM);
  }

  /* next: do we own the thang?? */
  if (!wiz && !ut_isobjown (aswho, ob)) {
    if (vbose)
      say (who, "You don't own ", ut_name (ob), ".\n", (char *) 0);
    return (UERR_PERM);
  }

  /* if the type is a flag, trap it here */
  if (!strcmp (typp, typ_flag)) {
    /* Special case for DARK */

    if (!wiz && !strcmp (atpp, var_isdark) && !ut_flagged (ob, var_isroom)) {
      if (vbose)
        say (who, "You can't set a non-room dark!\n", (char *) 0);
      return (UERR_ILLASGN);
    }
    if (ut_set (who, ob, typp, atpp, ""))
      return (UERR_FATAL);
    if (vbose && run_level () == 0)
      say (who, "Set flag ", atpp, "\n", (char *) 0);
    return (UERR_NONE);
  }

  /* at this point, we need another arg at least */
  if (vapp == (char *) 0) {
    if (vbose)
      say (who, "Set ", typp, " ", atpp, " to what?\n", (char *) 0);
    return (UERR_ARGCNT);
  }

  /* do not allow strings starting with '#' */
  if (!wiz && !strcmp (typp, typ_str) && vapp[0] == '#') {
    if (vbose)
      say (who, "You cannot start a string with '#'.\n", (char *) 0);
    return (UERR_ILLASGN);
  }

  /* do re-writing and syntax checks on booleans */
  if (!strcmp (typp, typ_bool)) {
    Sbuf suf;

    sbuf_initstatic (&suf);
    if (bool_rewrite (who, vapp, &suf)) {
      if (vbose)
        say (who, "Bad Boolean expression.\n", (char *) 0);
      sbuf_freestatic (&suf);
      return (UERR_SYNTAX);
    }


    vapp = sbuf_buf (&suf);
    if (bool_syntax (who, vapp)) {
      sbuf_freestatic (&suf);
      return (UERR_SYNTAX);
    }
    if (ut_set (who, ob, typp, atpp, vapp)) {
      sbuf_freestatic (&suf);
      return (UERR_FATAL);
    }
    if (vbose && run_level () == 0)
      say (who, "Set ", atpp, ".\n", (char *) 0);
    sbuf_freestatic (&suf);
    return (UERR_NONE);
  }


  /* special case for lists and objects being set to NULL */
  izlist = !strcmp (typp, typ_list);
  if ((izlist || !strcmp (typp, typ_obj)) && vapp[0] == '\0') {
    if (ut_unset (who, ob, atpp))
      return (UERR_FATAL);
    if (vbose)
      say (who, "Nulled out ", atpp, "\n", (char *) 0);
    return (UERR_NONE);
  }


  /* special case for lists +thing and -thing */
  if (izlist && (vapp[0] == '+' || vapp[0] == '-')) {
    char *thang;

    if (!strcmp ("me", &vapp[1]))
      thang = aswho;
    else if (!strcmp ("here", &vapp[1]))
      thang = ut_loc (who);
    else
      thang = &vapp[1];

    if (vapp[0] == '-') {
      if (ut_listdel (who, ob, atpp, thang))
        return (UERR_FATAL);
      if (vbose && run_level () == 0)
        say (who, "Dropped ", thang, " from ", atpp, "\n", (char *) 0);
      return (UERR_NONE);
    }

    /* Must be adding it. Special case owners list. Xtra chex. */
    if (!strcmp (atpp, var_owner) &&
      (!ut_isgoodid (thang) || !cache_check (thang))) {
      if (vbose && run_level () == 0)
        say (who, "Cannot add ", thang, " to owners list.\n", (char *) 0);
      return (UERR_BADOID);
    }

    /* add away */
    if (ut_listadd (who, ob, atpp, thang))
      return (UERR_FATAL);
    if (vbose && run_level () == 0)
      say (who, "Added ", thang, " to ", atpp, "\n", (char *) 0);
    return (UERR_NONE);
  }
  if (!wiz && izlist && vbose && run_level () == 0) {
    say (who, "Use + or - to manipulate lists, please.\n", (char *) 0);
    return (UERR_ILLASGN);
  }

  /* special case for droptos */
  if (!strcmp (atpp, var_dropto)) {
    /* We setting this on a room? */
    if (!wiz && !ut_flagged (ob, var_isroom)) {
      if (vbose)
        say (who, "Can't set a dropto on a non-room.\n", (char *) 0);
      return (UERR_ILLASGN);
    }
    /* Can we link to that? */
    if (!wiz && strcmp (vapp, "home") && !ut_flagged (vapp, var_isroom)) {
      if (vbose)
        say (who, "Can't set a dropto to a non-room.\n", (char *) 0);
      return (UERR_ILLASGN);
    }

    if (!wiz && strcmp (vapp, "home") && !ut_isobjown (aswho, vapp)
      && bool_locked (aswho, vapp, ut_loc (aswho), var_link, 1)) {
      if (vbose)
        say (who, "You can't link a dropto to ", vapp, ".\n", (char *) 0);
      return (UERR_ILLASGN);
    }
  }

  /* special case for homes */
  if (!strcmp (atpp, var_home)) {
    char hm[MAXOID];

    if (matchlocal (who, vapp, ut_loc (who),
        MTCH_UNIQ | MTCH_NONLOC | MTCH_MEOK, hm)) {
      if (vbose)
        say (who, "I can't find ", vapp, ".\n", (char *) 0);
      return (UERR_NOMATCH);
    }
    /* Can we set the home to it? */
    if (!wiz && !ut_isobjown (aswho, hm) &&
      bool_locked (aswho, hm, ut_loc (aswho), var_link, 1)) {
      if (vbose)
        say (who, "You can't set home to ", vapp, ".\n", (char *) 0);
      return (UERR_PERM);
    }
    if (!wiz && ut_flagged (ob, var_isplay)) {
      if (!ut_flagged (hm, var_isroom)) {
        if (vbose)
          say (who, vapp, " isn't a room!\n", (char *) 0);
        return (UERR_ILLASGN);
      }
    } else if (!wiz) {
      if (!ut_flagged (hm, var_isroom) && !ut_flagged (hm, var_isplay)) {
        if (vbose)
          say (who, "You can't set home to ", vapp, ".\n", (char *) 0);
        return (UERR_ILLASGN);
      }
    }
    if (index (hm, '@') == (char *) 0) {
      /* Flesh the object ID out fully */
      /* Be anal retentive about it    */
      if (strlen (hm) + strlen (mud_getname ()) + 1 > MAXOID) {
        if (vbose)
          say (who, "You can't set home to ", vapp, ".\n", (char *) 0);
        return (UERR_ILLASGN);
      }
      strcat (hm, "@");
      strcat (hm, mud_getname ());
    }
    if (ut_set (who, ob, typp, atpp, hm))
      return (UERR_FATAL);
    if (vbose && run_level () == 0)
      say (who, "Set ", atpp, "\n", (char *) 0);
    return (UERR_NONE);
  }

#ifdef  PLAYER_NAMECHANGING
  /* log name changes - why not ? */
  if (!wiz && !strcmp (atpp, var_nam) && ut_flagged (ob, var_isplay)) {
    if (index (vapp, '\'') || index (vapp, '\"') || index (vapp, ';')) {
      if (vbose)
        say (who, "Illegal character in name.\n", (char *) 0);
      return (UERR_ILLASGN);
    }
    plogf ("%s changed %s name to %s\n", who, ob, vapp);
  }
#endif

  if (ut_set (who, ob, typp, atpp, vapp))
    return (UERR_FATAL);
  if (vbose && run_level () == 0)
    say (who, "Set ", atpp, "\n", (char *) 0);
  return (UERR_NONE);
}





/* ARGSUSED */
int cmd_unset (int argc, char *argv[], char *who, char *aswho)
{
  char ob[MAXOID];

  if (matchlocal (who, argv[1], ut_loc (who),
      MTCH_UNIQ | MTCH_NONLOC | MTCH_MEOK, ob))
    return (UERR_NOMATCH);
  return (var_unset_internal (who, aswho, ob, argv[2], 1));
}




int var_unset_internal (char *who, char *aswho, char *ob, char *atpp,
  int vbose)
{
  int wiz;
  VarTab *vp = vtab;

  while (vp->vnam != (char *) 0) {
    if (!strcmp (vp->vnam, atpp))
      break;
    if (!strcmp (vp->vlong, atpp)) {
      atpp = vp->vnam;
      break;
    }
    vp++;
  }

  wiz = ut_flagged (aswho, var_wiz);
  if (vp->vnam != (char *) 0 && (vp->flg & VAR_PRIV) && !wiz) {
    if (vbose)
      say (who, "You must be a wizard to unset ", vp->vlong, ".\n",
        (char *) 0);
    return (UERR_PERM);
  }


  if ((vp->flg & VAR_PRIVPLY) && !wiz && ut_flagged (ob, var_isplay)) {
    if (vbose)
      say (who, "You must be a wizard to unset ", vp->vlong,
        " for a player.\n", (char *) 0);
    return (UERR_PERM);
  }

  if (!wiz && !ut_isobjown (aswho, ob)) {
    if (vbose)
      say (who, "You don't own ", ut_name (ob), ".\n", (char *) 0);
    return (UERR_PERM);
  }

  if (ut_unset (who, ob, atpp))
    return (UERR_FATAL);
  if (vbose && run_level () == 0)
    say (who, "Unset ", atpp, "\n", (char *) 0);
  return (UERR_NONE);
}





/* check if this is a known attribute and possibly */
/* get the long name (to use as a title) */
void fndvnam (char *vt,         /* the attribute */
  char *buf,                    /* long name? */
  int siz)
{
  VarTab *vp;

  /* can we find a match in the variable table? */
  for (vp = vtab; vp->vnam != (char *) 0; ++vp) {
    if (!strcmp (vp->vnam, vt)) {
      if (buf != (char *) 0)
        strncpy (buf, vp->vlong, siz - 2);
      return;
    }
  }
  if (buf != (char *) 0)
    strncpy (buf, vt, siz - 2); /* gotta tell'em something... */
  buf[siz - 1] = '\0';
}



int fndtyp (char *vt)
{
  TypTab *tp;

  for (tp = ttab; tp->tnam != (char *) 0; tp++)
    if (!strcmp (vt, tp->tnam))
      return (1);
  return (0);
}