Logo Search packages:      
Sourcecode: fhist version File versions

name.c

/*
 *    fhist - file history and comparison tools
 *    Copyright (C) 1991-1994, 1998-2000, 2002 Peter Miller;
 *    All rights reserved.
 *
 *    Derived from a work
 *    Copyright (C) 1990 David I. Bell.
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
 *
 * MANIFEST: functions to specify a name for an edit of a module.
 */

#include <ac/ctype.h>
#include <ac/errno.h>
#include <ac/stdio.h>
#include <ac/string.h>

#include <breaks.h>
#include <compare.h>
#include <error_intl.h>
#include <fhist.h>
#include <fileio.h>
#include <name.h>
#include <subroutine.h>


/*
 * Create a new name for an edit of a module.
 * Currently this only works for the latest edit.
 */

void
namehistory(char *editname)
{
    FILE            *fp;      /* history file */
    POS             *pp;      /* current entry in position table */
    POS             *postable;      /* position table */
    char            *oldnames;      /* old names for edit */
    char            *newnames;      /* new names for edit */
    int             namelen;  /* length of new name */
    long            edit;     /* current edit number */
    int             saveerror;      /* saved error code on errors */
    sub_context_ty  *scp;

    fp = openhistoryfile(OHF_WRITE);
    if (fc.verbosity)
    {
      scp = sub_context_new();
      sub_var_set_charstar(scp, "Module", sc.modulename);
      sub_var_set_long(scp, "Number", sc.lastedit);
      sub_var_set_charstar(scp, "Name", editname);
      error_intl
      (
          scp,
         i18n("latest edit $number of module \"$module\" being named \"$name\"")
      );
      sub_context_delete(scp);
    }
    postable = readpostable(fp);
    postable++;               /* ignore unused entry */
    pp = postable;
    oldnames = pp->p_names;
    if (oldnames == NULL)           /* single new name */
      pp->p_names = editname;
    else
    {
      /* put name in front of other names */
      namelen = strlen(editname);
      newnames = allocstr((unsigned long)(strlen(oldnames) + namelen + 2));
      strcpy(newnames, editname);
      newnames[namelen] = ' ';
      strcpy(&newnames[namelen+1], oldnames);
      pp->p_names = newnames;
    }
    breaksoff();

    /*
     * Now position back to the beginning of the position table, and write
     * back the table with the new name.  Errors will be handled later.
     */
    seekf(fp, sc.tablepos, sc.historyname);
    pp = postable;
    for (edit = sc.lastedit; edit >= sc.firstedit; edit--, pp++)
    {
      fprintf(fp, (pp->p_names ? "%c %ld %ld %s\n" : "%c %ld %ld\n"),
          T_POSITION, edit, pp->p_pos, pp->p_names);
    }
    fprintf(fp, "%c %ld\n", T_EOF, ftell(fp));

    /*
     * Force the last bit of the output to the file, then check for errors.
     * If an error occurred, write back the original position table without
     * the new name.  This should succeed since it was there previously.
     */
    fflush(fp);
    if (ferror(fp))
    {
      saveerror = errno;
      errno = 0;
      seekf(fp, sc.tablepos, sc.historyname);
      pp = postable;
      pp->p_names = oldnames;
      for (edit = sc.lastedit; edit >= sc.firstedit; edit--, pp++)
      {
          fprintf(fp, (pp->p_names ?  "%c %ld %ld %s\n" : "%c %ld %ld\n"),
            T_POSITION, edit, pp->p_pos, pp->p_names);
      }
      fprintf(fp, "%c %ld\n", T_EOF, ftell(fp));
      if (fflush(fp))
      {
          scp = sub_context_new();
          sub_errno_set(scp);
          sub_var_set_charstar(scp, "File_Name", sc.historyname);
          error_intl(scp, i18n("write \"$filename\": $errno"));
          sub_var_set_charstar(scp, "File_Name", sc.historyname);
          fatal_intl(scp, i18n("file \"$filename\" is damaged"));
      }
      fclose(fp);
      scp = sub_context_new();
      sub_errno_setx(scp, saveerror);
      sub_var_set_charstar(scp, "File_Name", sc.historyname);
      error_intl(scp, i18n("write \"$filename\": $errno"));
      sub_var_set_charstar(scp, "File_Name", sc.historyname);
      fatal_intl(scp, i18n("file \"$filename\" is not damaged"));
    }
    fclose(fp);
    breakson();
}


/*
 * Check to see if a new edit name is valid.
 * Valid names cannot begin with a digit, or contain a plus or minus sign.
 * This routine also lower cases the name.
 */

void
checkeditname(char *editname)
{
    char            *cp;            /* current character of name */
    sub_context_ty  *scp;

    for (cp = editname; *cp; cp++)
      if (isupper((unsigned char)*cp))
          *cp = tolower((unsigned char)*cp);
    cp = editname;
    if ((strcmp(cp, OLDESTNAME) == 0) || (strcmp(cp, NEWESTNAME) == 0))
    {
      scp = sub_context_new();
      sub_var_set_charstar(scp, "Name", editname);
      fatal_intl(scp, i18n("edit name \"$name\" is reserved"));
    }
    if (isdigit((unsigned char)*cp))
    {
      scp = sub_context_new();
      sub_var_set_charstar(scp, "Name", editname);
      fatal_intl(scp, i18n("edit name \"$name\" cannot begin with a digit"));
    }
    while (*cp)
    {
      if ((*cp == '+') || (*cp++ == '-'))
      {
          scp = sub_context_new();
          sub_var_set_charstar(scp, "Name", editname);
          fatal_intl
          (
                  scp,
            i18n("edit name \"$name\" cannot contain plus or minus signs")
          );
      }
    }
}

Generated by  Doxygen 1.6.0   Back to index