ftp.nice.ch/pub/next/unix/developer/cvs.950905.s.tar.gz#/cvs-1.5.1/src/parseinfo.c

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

/*
 * Copyright (c) 1992, Brian Berliner and Jeff Polk
 * Copyright (c) 1989-1992, Brian Berliner
 * 
 * You may distribute under the terms of the GNU General Public License as
 * specified in the README file that comes with the CVS 1.4 kit.
 */

#include "cvs.h"

#ifndef lint
static const char rcsid[] = "$CVSid: @(#)parseinfo.c 1.18 94/09/23 $";
USE(rcsid)
#endif

/*
 * Parse the INFOFILE file for the specified REPOSITORY.  Invoke CALLPROC for
 * the first line in the file that matches the REPOSITORY, or if ALL != 0, any lines
 * matching "ALL", or if no lines match, the last line matching "DEFAULT".
 *
 * Return 0 for success, -1 if there was not an INFOFILE, and >0 for failure.
 */
int
Parse_Info (infofile, repository, callproc, all)
    char *infofile;
    char *repository;
    int (*callproc) ();
    int all;
{
    int err = 0;
    FILE *fp_info;
    char infopath[PATH_MAX];
    char line[MAXLINELEN];
    char *default_value = NULL;
    int callback_done, line_number;
    char *cp, *exp, *value, *srepos;
    const char *regex_err;

    if (CVSroot == NULL)
    {
	/* XXX - should be error maybe? */
	error (0, 0, "CVSROOT variable not set");
	return (1);
    }

    /* find the info file and open it */
    (void) sprintf (infopath, "%s/%s/%s", CVSroot,
		    CVSROOTADM, infofile);
    if ((fp_info = fopen (infopath, "r")) == NULL)
	return (0);			/* no file -> nothing special done */

    /* strip off the CVSROOT if repository was absolute */
    srepos = Short_Repository (repository);

    if (trace)
	(void) fprintf (stderr, "-> ParseInfo(%s, %s, %s)\n",
			infopath, srepos, all ? "ALL" : "not ALL");

    /* search the info file for lines that match */
    callback_done = line_number = 0;
    while (fgets (line, sizeof (line), fp_info) != NULL)
    {
	line_number++;

	/* skip lines starting with # */
	if (line[0] == '#')
	    continue;

	/* skip whitespace at beginning of line */
	for (cp = line; *cp && isspace (*cp); cp++)
	    ;

	/* if *cp is null, the whole line was blank */
	if (*cp == '\0')
	    continue;

	/* the regular expression is everything up to the first space */
	for (exp = cp; *cp && !isspace (*cp); cp++)
	    ;
	if (*cp != '\0')
	    *cp++ = '\0';

	/* skip whitespace up to the start of the matching value */
	while (*cp && isspace (*cp))
	    cp++;

	/* no value to match with the regular expression is an error */
	if (*cp == '\0')
	{
	    error (0, 0, "syntax error at line %d file %s; ignored",
		   line_number, infofile);
	    continue;
	}
	value = cp;

	/* strip the newline off the end of the value */
	if ((cp = strrchr (value, '\n')) != NULL)
	    *cp = '\0';

	/* FIXME: probably should allow multiple occurrences of CVSROOT.  */
	/* FIXME-maybe: perhaps should allow CVSREAD and other cvs
	   settings (if there is a need for them, which isn't clear).  */
	/* FIXME-maybe: Should there be a way to substitute arbitrary
	   environment variables?  Probably not, because then what gets
	   substituted would depend on who runs cvs.  A better feature might
	   be to allow a file in CVSROOT to specify variables to be
	   substituted.  */
	{
	    char *p, envname[128];

	    strcpy(envname, "$");
	    /* FIXME: I'm not at all sure this should be CVSROOT_ENV as opposed
	       to literal CVSROOT.  The value we subsitute is the cvs root
	       in use which is not the same thing as the environment variable
	       CVSROOT_ENV.  */
	    strcat(envname, CVSROOT_ENV);

	    cp = xstrdup(value);
	    if ((p = strstr(cp, envname))) {
		if (strlen(line) + strlen(CVSroot) + 1 > MAXLINELEN) {
		    /* FIXME: there is no reason for this arbitrary limit.  */
		    error(0, 0,
			  "line %d in %s too long to expand $CVSROOT, ignored",
			  line_number, infofile);
		    continue;
		}
		if (p > cp) {
		    strncpy(value, cp, p - cp);
		    value[p - cp] = '\0';
		    strcat(value, CVSroot);
		} else
		    strcpy(value, CVSroot);
		strcat(value, p + strlen(envname));
	    }
	    free(cp);
	}

	/*
	 * At this point, exp points to the regular expression, and value
	 * points to the value to call the callback routine with.  Evaluate
	 * the regular expression against srepos and callback with the value
	 * if it matches.
	 */

	/* save the default value so we have it later if we need it */
	if (strcmp (exp, "DEFAULT") == 0)
	{
	    default_value = xstrdup (value);
	    continue;
	}

	/*
	 * For a regular expression of "ALL", do the callback always We may
	 * execute lots of ALL callbacks in addition to *one* regular matching
	 * callback or default
	 */
	if (strcmp (exp, "ALL") == 0)
	{
	    if (all)
		err += callproc (repository, value);
	    else
		error(0, 0, "Keyword `ALL' is ignored at line %d in %s file",
		      line_number, infofile);
	    continue;
	}

	if (callback_done)
	    /* only first matching, plus "ALL"'s */
	    continue;

	/* see if the repository matched this regular expression */
	if ((regex_err = re_comp (exp)) != NULL)
	{
	    error (0, 0, "bad regular expression at line %d file %s: %s",
		   line_number, infofile, regex_err);
	    continue;
	}
	if (re_exec (srepos) == 0)
	    continue;				/* no match */

	/* it did, so do the callback and note that we did one */
	err += callproc (repository, value);
	callback_done = 1;
    }
    (void) fclose (fp_info);

    /* if we fell through and didn't callback at all, do the default */
    if (callback_done == 0 && default_value != NULL)
	err += callproc (repository, default_value);

    /* free up space if necessary */
    if (default_value != NULL)
	free (default_value);

    return (err);
}

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