home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume27
/
aegis-2.1
/
part07
< prev
next >
Wrap
Text File
|
1993-09-24
|
155KB
|
6,464 lines
Newsgroups: comp.sources.unix
From: pmiller@bmr.gov.au (Peter Miller)
Subject: v27i042: aegis - project change supervisor (V2.1), Part07/19
References: <1.748951883.12788@gw.home.vix.com>
Sender: unix-sources-moderator@gw.home.vix.com
Approved: vixie@gw.home.vix.com
Submitted-By: pmiller@bmr.gov.au (Peter Miller)
Posting-Number: Volume 27, Issue 42
Archive-Name: aegis-2.1/part07
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 7 (of 19)."
# Contents: aegis/aecd.c aegis/aeibu.c aegis/aencu.c aegis/aermpr.c
# aegis/aerp.c aegis/aerpu.c aegis/commit.c aux/Makefile.sh
# common/arglex.c doc/c5.0.so fmtgen/id.c fmtgen/lex.c
# fmtgen/parse.y test/00/t0006a.sh test/00/t0009a.sh
# Wrapped by vixie@gw.home.vix.com on Sat Sep 25 03:00:37 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'aegis/aecd.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'aegis/aecd.c'\"
else
echo shar: Extracting \"'aegis/aecd.c'\" \(9595 characters\)
sed "s/^X//" >'aegis/aecd.c' <<'END_OF_FILE'
X/*
X * aegis - project change supervisor
X * Copyright (C) 1991, 1992, 1993 Peter Miller.
X * All rights reserved.
X *
X * This program is free software; you can redistribute it and/or modify
X * it under the terms of the GNU General Public License as published by
X * the Free Software Foundation; either version 2 of the License, or
X * (at your option) any later version.
X *
X * This program is distributed in the hope that it will be useful,
X * but WITHOUT ANY WARRANTY; without even the implied warranty of
X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X * GNU General Public License for more details.
X *
X * You should have received a copy of the GNU General Public License
X * along with this program; if not, write to the Free Software
X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X *
X * MANIFEST: functions to change directory or determine paths
X */
X
X#include <stdio.h>
X#include <stdlib.h>
X
X#include <aecd.h>
X#include <ael.h>
X#include <arglex2.h>
X#include <change.h>
X#include <error.h>
X#include <help.h>
X#include <option.h>
X#include <os.h>
X#include <project.h>
X#include <trace.h>
X#include <user.h>
X
X
Xstatic void change_directory_usage _((void));
X
Xstatic void
Xchange_directory_usage()
X{
X char *progname;
X
X progname = option_progname_get();
X fprintf(stderr, "usage: %s -Change_Directory [ <option>... ][ <subdir> ]\n", progname);
X fprintf(stderr, " %s -Change_Directory -List [ <option>... ]\n", progname);
X fprintf(stderr, " %s -Change_Directory -Help\n", progname);
X quit(1);
X}
X
X
Xstatic void change_directory_help _((void));
X
Xstatic void
Xchange_directory_help()
X{
X static char *text[] =
X {
X"NAME",
X" %s -Change_Directory - change directory",
X"",
X"SYNOPSIS",
X" %s -Change_Directory [ <option>... ][ <relative-path> ]",
X" %s -Change_Directory -List [ <option>... ]",
X" %s -Change_Directory -Help",
X"",
X"DESCRIPTION",
X" The %s -Change_Directory command is used to obtain a",
X" path to change directory to. If the relative-path is",
X" supplied, this will be added to the output.",
X"",
X" This command is usually used to calculate an argument for",
X" cd(1), howver it can also be used to abtain an absolute",
X" path for change and project files.",
X"",
X"OPTIONS",
X" The following options are understood:",
X"",
X" -BaseLine",
X" This option may be used to specify that the",
X" project baseline is the subject of the command.",
X"",
X" -Change <number>",
X" This option may be used to specify a particular",
X" change within a project. When no -Change option is",
X" specified, the AEGIS_CHANGE environment variable is",
X" consulted. If that does not exist, the user's",
X" $HOME/.aegisrc file is examined for a default change",
X" field (see aeuconf(5) for more information). If",
X" that does not exist, when the user is only working",
X" on one change within a project, that is the default",
X" change number. Otherwise, it is an error.",
X"",
X" -Development_Directory",
X" This option is ised to specify that the",
X" development directory is the subject of the",
X" command. This is only useful for a change which",
X" is in the 'being_integrated' state, when the",
X" default is the integration directory.",
X"",
X" -Help",
X" This option may be used to obtain more",
X" information about how to use the %s program.",
X"",
X" -List",
X" This option may be used to obtain a list of",
X" suitable subjects for this command. The list may",
X" be more general than expected.",
X"",
X" -Project <name>",
X" This option may be used to select the project of",
X" interest. When no -Project option is specified, the",
X" AEGIS_PROJECT environment variable is consulted. If",
X" that does not exist, the user's $HOME/.aegisrc file",
X" is examined for a default project field (see",
X" aeuconf(5) for more information). If that does not",
X" exist, when the user is only working on changes",
X" within a single project, the project name defaults",
X" to that project. Otherwise, it is an error.",
X"",
X" -TERse",
X" This option may be used to cause listings to",
X" produce the bare minimum of information. It is",
X" usually useful for shell scripts.",
X"",
X" -Verbose",
X" This option may be used to cause %s to produce",
X" more output. By default %s only produces",
X" output on errors. When used with the -List",
X" option this option causes column headings to be",
X" added.",
X"",
X" All options are case insensitive. Options may be",
X" abbreviated; the abbreviation is the upper case letters.",
X" Options and other command line arguments may be mixed",
X" arbitrarily on the command line.",
X"",
X"RECOMMENDED ALIAS",
X" The recommended alias for this command is",
X" csh%% alias aecd 'cd `%s -cd \\!* -v`'",
X" sh$ aecd(){cd `%s -cd $* -v`}",
X"",
X"ERRORS",
X" It is an error if the specified change is not in a state",
X" where it has a directory to change to.",
X"",
X"EXIT STATUS",
X" The %s command will exit with a status of 1 on any",
X" error. The %s command will only exit with a status of",
X" 0 if there are no errors.",
X"",
X"COPYRIGHT",
X" %C",
X"",
X"AUTHOR",
X" %A",
X };
X
X help(text, SIZEOF(text), change_directory_usage);
X}
X
X
Xstatic void change_directory_list _((void));
X
Xstatic void
Xchange_directory_list()
X{
X string_ty *project_name;
X
X trace(("change_directory_list()\n{\n"/*}*/));
X arglex();
X project_name = 0;
X while (arglex_token != arglex_token_eoln)
X {
X switch (arglex_token)
X {
X default:
X generic_argument(change_directory_usage);
X continue;
X
X case arglex_token_project:
X if (arglex() != arglex_token_string)
X change_directory_usage();
X if (project_name)
X fatal("duplicate -Project option");
X project_name = str_from_c(arglex_value.alv_string);
X break;
X }
X arglex();
X }
X list_changes_in_state_mask
X (
X project_name,
X (
X (1 << cstate_state_being_developed)
X |
X (1 << cstate_state_being_reviewed)
X |
X (1 << cstate_state_awaiting_integration)
X |
X (1 << cstate_state_being_integrated)
X )
X );
X if (project_name)
X str_free(project_name);
X trace((/*{*/"}\n"));
X}
X
X
Xstatic void change_directory_main _((void));
X
Xstatic void
Xchange_directory_main()
X{
X char *subdir = 0;
X int devdir = 0;
X cstate cstate_data;
X string_ty *d;
X int baseline = 0;
X string_ty *project_name;
X project_ty *pp;
X long change_number;
X change_ty *cp;
X user_ty *up;
X
X trace(("change_directory_main()\n{\n"/*}*/));
X project_name = 0;
X change_number = 0;
X while (arglex_token != arglex_token_eoln)
X {
X switch (arglex_token)
X {
X default:
X generic_argument(change_directory_usage);
X continue;
X
X case arglex_token_string:
X if (subdir)
X fatal("too many subdirectories specified");
X subdir = arglex_value.alv_string;
X if (!*subdir || *subdir == '/')
X fatal("subdirectory must be relative");
X break;
X
X case arglex_token_development_directory:
X if (devdir)
X fatal("duplicate -Develompent_Directory option");
X if (baseline)
X {
X bad_combo:
X fatal
X (
X "only one of -BaseLine and -Development_Directory may be specified"
X );
X }
X devdir = 1;
X break;
X
X case arglex_token_baseline:
X if (baseline)
X fatal("duplicate -BaseLine option");
X if (devdir)
X goto bad_combo;
X baseline = 1;
X break;
X
X case arglex_token_change:
X if (arglex() != arglex_token_number)
X change_directory_usage();
X /* fall through... */
X
X case arglex_token_number:
X if (change_number)
X fatal("duplicate -Change option");
X change_number = arglex_value.alv_number;
X if (change_number < 1)
X fatal("change %ld out of range", change_number);
X break;
X
X case arglex_token_project:
X if (arglex() != arglex_token_string)
X change_directory_usage();
X if (project_name)
X fatal("duplicate -Project option");
X project_name = str_from_c(arglex_value.alv_string);
X break;
X }
X arglex();
X }
X
X /*
X * locate project data
X */
X if (!project_name)
X project_name = user_default_project();
X pp = project_alloc(project_name);
X str_free(project_name);
X project_bind_existing(pp);
X
X /*
X * locate user data
X */
X up = user_executing(pp);
X
X /*
X * figure out where to go
X */
X if (baseline)
X {
X if (change_number)
X {
X fatal
X (
X "the -BaseLine and -Change options are mutually exclusive"
X );
X }
X d = project_baseline_path_get(pp, 0);
X cp = 0;
X }
X else
X {
X /*
X * locate change data
X */
X if (!change_number)
X change_number = user_default_change(up);
X cp = change_alloc(pp, change_number);
X change_bind_existing(cp);
X
X cstate_data = change_cstate_get(cp);
X switch (cstate_data->state)
X {
X default:
X change_fatal(cp, "no directory");
X
X case cstate_state_being_integrated:
X if (!devdir)
X {
X d = change_integration_directory_get(cp, 0);
X break;
X }
X /* fall through... */
X
X case cstate_state_awaiting_integration:
X case cstate_state_being_reviewed:
X case cstate_state_being_developed:
X d = change_development_directory_get(cp, 0);
X break;
X }
X }
X
X /*
X * Add in the extra path elements as necessary.
X * Flatten it out if they go up the tree (etc).
X */
X if (subdir)
X {
X string_ty *tmp;
X
X tmp = str_format("%S/%s", d, subdir);
X user_become(up);
X d = os_pathname(tmp, 0);
X user_become_undo();
X str_free(tmp);
X }
X
X /*
X * print out the path
X */
X printf("%s\n", d->str_text);
X if (!cp)
X project_verbose(pp, "%s", d->str_text);
X else
X {
X change_verbose(cp, "%s", d->str_text);
X change_free(cp);
X }
X project_free(pp);
X user_free(up);
X trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xchange_directory()
X{
X trace(("change_directory()\n{\n"/*}*/));
X switch (arglex())
X {
X default:
X change_directory_main();
X break;
X
X case arglex_token_help:
X change_directory_help();
X break;
X
X case arglex_token_list:
X change_directory_list();
X break;
X }
X trace((/*{*/"}\n"));
X}
END_OF_FILE
if test 9595 -ne `wc -c <'aegis/aecd.c'`; then
echo shar: \"'aegis/aecd.c'\" unpacked with wrong size!
fi
# end of 'aegis/aecd.c'
fi
if test -f 'aegis/aeibu.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'aegis/aeibu.c'\"
else
echo shar: Extracting \"'aegis/aeibu.c'\" \(10341 characters\)
sed "s/^X//" >'aegis/aeibu.c' <<'END_OF_FILE'
X/*
X * aegis - project change supervisor
X * Copyright (C) 1991, 1992, 1993 Peter Miller.
X * All rights reserved.
X *
X * This program is free software; you can redistribute it and/or modify
X * it under the terms of the GNU General Public License as published by
X * the Free Software Foundation; either version 2 of the License, or
X * (at your option) any later version.
X *
X * This program is distributed in the hope that it will be useful,
X * but WITHOUT ANY WARRANTY; without even the implied warranty of
X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X * GNU General Public License for more details.
X *
X * You should have received a copy of the GNU General Public License
X * along with this program; if not, write to the Free Software
X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X *
X * MANIFEST: functions for implementing integrate begin undo
X */
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X#include <aeibu.h>
X#include <ael.h>
X#include <arglex2.h>
X#include <commit.h>
X#include <change.h>
X#include <dir.h>
X#include <error.h>
X#include <file.h>
X#include <help.h>
X#include <lock.h>
X#include <log.h>
X#include <option.h>
X#include <os.h>
X#include <project.h>
X#include <sub.h>
X#include <trace.h>
X#include <undo.h>
X#include <user.h>
X
X
Xstatic void integrate_begin_undo_usage _((void));
X
Xstatic void
Xintegrate_begin_undo_usage()
X{
X char *progname;
X
X progname = option_progname_get();
X fprintf(stderr, "usage: %s -Integrate_Begin_Undo [ <option>... ]\n", progname);
X fprintf(stderr, " %s -Integrate_Begin_Undo -List [ <option>... ]\n", progname);
X fprintf(stderr, " %s -Integrate_Begin_Undo -Help\n", progname);
X quit(1);
X}
X
X
Xstatic void integrate_begin_undo_help _((void));
X
Xstatic void
Xintegrate_begin_undo_help()
X{
X static char *text[] =
X {
X"NAME",
X" %s -Integrate_Begin_Undo - reverse the aeib command",
X"",
X"SYNOPSIS",
X" %s -Integrate_Begin_Undo [ <option>... ]",
X" %s -Integrate_Begin_Undo -List [ <option>... ]",
X" %s -Integrate_Begin_Undo -Help",
X"",
X"DESCRIPTION",
X" The %s -Integrate_Begin_Undo command is used to",
X" reverse the actions of the '%s -Integrate_Begin'",
X" command.",
X"",
X" Successful execution of this command will move the change",
X" from the 'being_integrated' state to the",
X" 'awaiting_integration' state. The integration directory",
X" will be deleted. The change will cease to be assigned to",
X" the current user.",
X"",
X"OPTIONS",
X" The following options are understood:",
X"",
X" -Change <number>",
X" This option may be used to specify a particular",
X" change within a project. When no -Change option is",
X" specified, the AEGIS_CHANGE environment variable is",
X" consulted. If that does not exist, the user's",
X" $HOME/.aegisrc file is examined for a default change",
X" field (see aeuconf(5) for more information). If",
X" that does not exist, when the user is only working",
X" on one change within a project, that is the default",
X" change number. Otherwise, it is an error.",
X"",
X" -Help",
X" This option may be used to obtain more",
X" information about how to use the %s program.",
X"",
X" -Keep",
X" This option may be used to retain files and/or",
X" directories usually deleted by the command.",
X"",
X" -List",
X" This option may be used to obtain a list of",
X" suitable subjects for this command. The list may",
X" be more general than expected.",
X"",
X" -Project <name>",
X" This option may be used to select the project of",
X" interest. When no -Project option is specified, the",
X" AEGIS_PROJECT environment variable is consulted. If",
X" that does not exist, the user's $HOME/.aegisrc file",
X" is examined for a default project field (see",
X" aeuconf(5) for more information). If that does not",
X" exist, when the user is only working on changes",
X" within a single project, the project name defaults",
X" to that project. Otherwise, it is an error.",
X"",
X" -TERse",
X" This option may be used to cause listings to",
X" produce the bare minimum of information. It is",
X" usually useful for shell scripts.",
X"",
X" -Verbose",
X" This option may be used to cause %s to produce",
X" more output. By default %s only produces",
X" output on errors. When used with the -List",
X" option this option causes column headings to be",
X" added.",
X"",
X" All options may be abbreviated; the abbreviation is",
X" documented as the upper case letters, all lower case",
X" letters and underscores (_) are optional. You must use",
X" consecutive sequences of optional letters.",
X"",
X" All options are case insensitive, you may type them in",
X" upper case or lower case or a combination of both, case",
X" is not important.",
X"",
X" For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
X" are all interpreted to mean the -Project option. The",
X" argument \"-prj\" will not be understood, because",
X" consecutive optional characters were not supplied.",
X"",
X" Options and other command line arguments may be mixed",
X" arbitrarily on the command line, after the function",
X" selectors.",
X"",
X" The GNU long option names are understood. Since all",
X" option names for aegis are long, this means ignoring the",
X" extra leading '-'. The \"--option=value\" convention is",
X" also understood.",
X"",
X"RECOMMENDED ALIAS",
X" The recommended alias for this command is",
X" csh%% alias aeibu '%s -ibu \\!* -v'",
X" sh$ aeibu(){%s -ibu $* -v}",
X"",
X"ERRORS",
X" It is an error if the change is not in the",
X" 'being_integrated' state.",
X" It is an error if the change is not assigned to the",
X" current user.",
X"",
X"EXIT STATUS",
X" The %s command will exit with a status of 1 on any",
X" error. The %s command will only exit with a status of",
X" 0 if there are no errors.",
X"",
X"COPYRIGHT",
X" %C",
X"",
X"AUTHOR",
X" %A",
X };
X
X help(text, SIZEOF(text), integrate_begin_undo_usage);
X}
X
X
Xstatic void integrate_begin_undo_list _((void (*)(void)));
X
Xstatic void
Xintegrate_begin_undo_list(usage)
X void (*usage)_((void));
X{
X string_ty *project_name;
X
X trace(("integrate_begin_undo_list()\n{\n"/*}*/));
X arglex();
X project_name = 0;
X while (arglex_token != arglex_token_eoln)
X {
X switch (arglex_token)
X {
X default:
X generic_argument(usage);
X continue;
X
X case arglex_token_project:
X if (arglex() != arglex_token_string)
X usage();
X if (project_name)
X fatal("duplicate -Project option");
X project_name = str_from_c(arglex_value.alv_string);
X break;
X }
X arglex();
X }
X list_changes_in_state_mask
X (
X project_name,
X 1 << cstate_state_being_integrated
X );
X if (project_name)
X str_free(project_name);
X trace((/*{*/"}\n"));
X}
X
X
Xstatic void integrate_begin_undo_main _((void));
X
Xstatic void
Xintegrate_begin_undo_main()
X{
X cstate cstate_data;
X pstate pstate_data;
X cstate_history history_data;
X string_ty *dir;
X string_ty *project_name;
X project_ty *pp;
X long change_number;
X change_ty *cp;
X user_ty *up;
X
X trace(("integrate_begin_main()\n{\n"/*}*/));
X project_name = 0;
X change_number = 0;
X while (arglex_token != arglex_token_eoln)
X {
X switch (arglex_token)
X {
X default:
X generic_argument(integrate_begin_undo_usage);
X continue;
X
X case arglex_token_change:
X if (arglex() != arglex_token_number)
X integrate_begin_undo_usage();
X /* fall through... */
X
X case arglex_token_number:
X if (change_number)
X fatal("duplicate -Change option");
X change_number = arglex_value.alv_number;
X if (change_number < 1)
X fatal("change %ld out of range", change_number);
X break;
X
X case arglex_token_project:
X if (arglex() != arglex_token_string)
X integrate_begin_undo_usage();
X /* fall through... */
X
X case arglex_token_string:
X if (project_name)
X fatal("duplicate -Project option");
X project_name = str_from_c(arglex_value.alv_string);
X break;
X }
X arglex();
X }
X
X /*
X * locate project data
X */
X if (!project_name)
X project_name = user_default_project();
X pp = project_alloc(project_name);
X str_free(project_name);
X project_bind_existing(pp);
X
X /*
X * locate user data
X */
X up = user_executing(pp);
X
X /*
X * locate change data
X */
X if (!change_number)
X change_number = user_default_change(up);
X cp = change_alloc(pp, change_number);
X change_bind_existing(cp);
X
X /*
X * lock the change for writing
X */
X project_pstate_lock_prepare(pp);
X change_cstate_lock_prepare(cp);
X user_ustate_lock_prepare(up);
X lock_take();
X cstate_data = change_cstate_get(cp);
X pstate_data = project_pstate_get(pp);
X
X /*
X * it is an error if the change is not in the 'being_integrated' state.
X */
X if (cstate_data->state != cstate_state_being_integrated)
X change_fatal(cp, "not in 'being_integrated' state");
X if (!str_equal(change_integrator_name(cp), user_name(up)))
X {
X change_fatal
X (
X cp,
X "user \"%S\" is not the integrator",
X user_name(up)
X );
X }
X
X /*
X * Change the state.
X * Add to the change's history.
X */
X cstate_data->state = cstate_state_awaiting_integration;
X history_data = change_history_new(cp, up);
X history_data->what = cstate_history_what_integrate_begin_undo;
X
X /*
X * remove it from the user's change list
X */
X user_own_remove(up, project_name_get(pp), change_number);
X
X /*
X * Note that the project has no current integration
X */
X pstate_data->currently_integrating_change = 0;
X dir = str_copy(change_integration_directory_get(cp, 1));
X change_integration_directory_clear(cp);
X cstate_data->build_time = 0;
X cstate_data->delta_number = 0;
X
X /*
X * Complain if they are in the integration directory,
X * because the rmdir at the end can't then run to completion.
X */
X os_become_orig();
X if (os_below_dir(dir, os_curdir()))
X change_fatal(cp, "please leave the integration directory");
X os_become_undo();
X
X /*
X * write out the data and release the locks
X */
X change_cstate_write(cp);
X user_ustate_write(up);
X project_pstate_write(pp);
X user_become(up);
X commit_rmdir_tree_errok(dir);
X user_become_undo();
X str_free(dir);
X commit();
X lock_release();
X
X /*
X * verbose success message
X */
X change_verbose(cp, "integrate begin undo");
X change_free(cp);
X project_free(pp);
X user_free(up);
X trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xintegrate_begin_undo()
X{
X trace(("integrate_begin_undo()\n{\n"/*}*/));
X switch (arglex())
X {
X default:
X integrate_begin_undo_main();
X break;
X
X case arglex_token_help:
X integrate_begin_undo_help();
X break;
X
X case arglex_token_list:
X integrate_begin_undo_list(integrate_begin_undo_usage);
X break;
X }
X trace((/*{*/"}\n"));
X}
END_OF_FILE
if test 10341 -ne `wc -c <'aegis/aeibu.c'`; then
echo shar: \"'aegis/aeibu.c'\" unpacked with wrong size!
fi
# end of 'aegis/aeibu.c'
fi
if test -f 'aegis/aencu.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'aegis/aencu.c'\"
else
echo shar: Extracting \"'aegis/aencu.c'\" \(9535 characters\)
sed "s/^X//" >'aegis/aencu.c' <<'END_OF_FILE'
X/*
X * aegis - project change supervisor
X * Copyright (C) 1991, 1992, 1993 Peter Miller.
X * All rights reserved.
X *
X * This program is free software; you can redistribute it and/or modify
X * it under the terms of the GNU General Public License as published by
X * the Free Software Foundation; either version 2 of the License, or
X * (at your option) any later version.
X *
X * This program is distributed in the hope that it will be useful,
X * but WITHOUT ANY WARRANTY; without even the implied warranty of
X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X * GNU General Public License for more details.
X *
X * You should have received a copy of the GNU General Public License
X * along with this program; if not, write to the Free Software
X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X *
X * MANIFEST: functions to implement new change undo
X */
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <time.h>
X
X#include <aeca.h>
X#include <ael.h>
X#include <aencu.h>
X#include <arglex2.h>
X#include <cattr.h>
X#include <change.h>
X#include <col.h>
X#include <commit.h>
X#include <common.h>
X#include <error.h>
X#include <help.h>
X#include <lock.h>
X#include <option.h>
X#include <os.h>
X#include <project.h>
X#include <trace.h>
X#include <user.h>
X
X
Xstatic void new_change_undo_usage _((void));
X
Xstatic void
Xnew_change_undo_usage()
X{
X char *progname;
X
X progname = option_progname_get();
X fprintf(stderr, "usage: %s -New_Change_Undo [ <option>... ]\n", progname);
X fprintf(stderr, " %s -New_Change_Undo -List [ <option>... ]\n", progname);
X fprintf(stderr, " %s -New_Change_Undo -Help\n", progname);
X quit(1);
X}
X
X
Xstatic void new_change_undo_help _((void));
X
Xstatic void
Xnew_change_undo_help()
X{
X static char *text[] =
X {
X"NAME",
X" %s -New_Change_Undo - remove a new change from a project",
X"",
X"SYNOPSIS",
X" %s -New_Change_Undo [ <option>... ]",
X" %s -New_Change_Undo -List [ <option>... ]",
X" %s -New_Change_Undo -Help",
X"",
X"DESCRIPTION",
X" The %s -New_Change_Undo command is used to remove a",
X" new change from a project.",
X"",
X" It wan't called '%s -Remove_Change' in order to",
X" emphasize that fact the the change must be in the",
X" 'awaiting_development' state. In practice it is",
X" possible, with a combination of commands, to remove any",
X" change which has not reached the 'completed' state.",
X"",
X"OPTIONS",
X" The following options are understood:",
X"",
X" -Change <number>",
X" This option may be used to specify a particular",
X" change within a project. When no -Change option is",
X" specified, the AEGIS_CHANGE environment variable is",
X" consulted. If that does not exist, the user's",
X" $HOME/.aegisrc file is examined for a default change",
X" field (see aeuconf(5) for more information). If",
X" that does not exist, when the user is only working",
X" on one change within a project, that is the default",
X" change number. Otherwise, it is an error.",
X"",
X" -Help",
X" This option may be used to obtain more",
X" information about how to use the %s program.",
X"",
X" -List",
X" This option may be used to obtain a list of",
X" suitable subjects for this command. The list may",
X" be more general than expected.",
X"",
X" -Project <name>",
X" This option may be used to select the project of",
X" interest. When no -Project option is specified, the",
X" AEGIS_PROJECT environment variable is consulted. If",
X" that does not exist, the user's $HOME/.aegisrc file",
X" is examined for a default project field (see",
X" aeuconf(5) for more information). If that does not",
X" exist, when the user is only working on changes",
X" within a single project, the project name defaults",
X" to that project. Otherwise, it is an error.",
X"",
X" -TERse",
X" This option may be used to cause listings to",
X" produce the bare minimum of information. It is",
X" usually useful for shell scripts.",
X"",
X" -Verbose",
X" This option may be used to cause %s to produce",
X" more output. By default %s only produces",
X" output on errors. When used with the -List",
X" option this option causes column headings to be",
X" added.",
X"",
X" All options may be abbreviated; the abbreviation is",
X" documented as the upper case letters, all lower case",
X" letters and underscores (_) are optional. You must use",
X" consecutive sequences of optional letters.",
X"",
X" All options are case insensitive, you may type them in",
X" upper case or lower case or a combination of both, case",
X" is not important.",
X"",
X" For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
X" are all interpreted to mean the -Project option. The",
X" argument \"-prj\" will not be understood, because",
X" consecutive optional characters were not supplied.",
X"",
X" Options and other command line arguments may be mixed",
X" arbitrarily on the command line, after the function",
X" selectors.",
X"",
X" The GNU long option names are understood. Since all",
X" option names for aegis are long, this means ignoring the",
X" extra leading '-'. The \"--option=value\" convention is",
X" also understood.",
X"",
X"RECOMMENDED ALIAS",
X" The recommended alias for this command is",
X" csh%% alias aencu '%s -ncu \\!* -v'",
X" sh$ aencu(){%s -ncu $* -v}",
X"",
X"ERRORS",
X" It is an error if the change is not in the",
X" 'awaiting_development' state.",
X" It is an error if the current user is not an",
X" administrator of the project.",
X"",
X"EXIT STATUS",
X" The %s command will exit with a status of 1 on any",
X" error. The %s command will only exit with a status of",
X" 0 if there are no errors.",
X"",
X"COPYRIGHT",
X" %C",
X"",
X"AUTHOR",
X" %A",
X };
X
X help(text, SIZEOF(text), new_change_undo_usage);
X}
X
X
Xstatic void new_change_undo_list _((void));
X
Xstatic void
Xnew_change_undo_list()
X{
X string_ty *project_name;
X
X trace(("new_change_list()\n{\n"/*}*/));
X arglex();
X project_name = 0;
X while (arglex_token != arglex_token_eoln)
X {
X switch (arglex_token)
X {
X default:
X generic_argument(new_change_undo_usage);
X continue;
X
X case arglex_token_project:
X if (arglex() != arglex_token_string)
X new_change_undo_usage();
X if (project_name)
X fatal("duplicate -Project option");
X project_name = str_from_c(arglex_value.alv_string);
X break;
X }
X arglex();
X }
X list_changes_in_state_mask
X (
X project_name,
X 1 << cstate_state_awaiting_development
X );
X if (project_name)
X str_free(project_name);
X trace((/*{*/"}\n"));
X}
X
X
Xstatic void new_change_undo_main _((void));
X
Xstatic void
Xnew_change_undo_main()
X{
X string_ty *project_name;
X long change_number;
X project_ty *pp;
X user_ty *up;
X change_ty *cp;
X cstate cstate_data;
X pstate pstate_data;
X
X trace(("new_change_undo_main()\n{\n"/*}*/));
X project_name = 0;
X change_number = 0;
X while (arglex_token != arglex_token_eoln)
X {
X switch (arglex_token)
X {
X default:
X generic_argument(new_change_undo_usage);
X continue;
X
X case arglex_token_change:
X if (arglex() != arglex_token_number)
X new_change_undo_usage();
X /* fall through... */
X
X case arglex_token_number:
X if (change_number)
X fatal("duplicate -Change option");
X change_number = arglex_value.alv_number;
X if (change_number < 1)
X fatal("change %ld out of range", change_number);
X break;
X
X case arglex_token_project:
X if (arglex() != arglex_token_string)
X new_change_undo_usage();
X /* fall through... */
X
X case arglex_token_string:
X if (project_name)
X fatal("duplicate -Project option");
X project_name = str_from_c(arglex_value.alv_string);
X break;
X }
X arglex();
X }
X
X /*
X * locate project data
X */
X if (!project_name)
X project_name = user_default_project();
X pp = project_alloc(project_name);
X str_free(project_name);
X project_bind_existing(pp);
X
X /*
X * locate user data
X */
X up = user_executing(pp);
X
X /*
X * locate change data
X *
X * The change number must be given on the command line,
X * even if there is only one appropriate change.
X * The is the "least surprizes" principle at work,
X * even though we could sometimes work this out for ourself.
X */
X if (!change_number)
X change_number = user_default_change(up);
X cp = change_alloc(pp, change_number);
X change_bind_existing(cp);
X
X /*
X * Take an advisory write lock on the project state
X * and the change state.
X */
X project_pstate_lock_prepare(pp);
X change_cstate_lock_prepare(cp);
X lock_take();
X cstate_data = change_cstate_get(cp);
X pstate_data = project_pstate_get(pp);
X
X /*
X * Extract the appropriate row of the change table.
X * It is an error if the change is not in the
X * awaiting_development state.
X */
X if (cstate_data->state != cstate_state_awaiting_development)
X change_fatal(cp, "not in 'awaiting_development' state");
X if (!project_administrator_query(pp, user_name(up)))
X {
X project_fatal
X (
X pp,
X "user \"%S\" is not an administrator",
X user_name(up)
X );
X }
X
X /*
X * tell the project to forget this change
X */
X project_change_delete(pp, change_number);
X
X /*
X * delete the change state file
X */
X project_become(pp);
X commit_unlink_errok(cp->filename);
X project_become_undo();
X
X /*
X * Update change table row (and change history table).
X * Update user table row.
X * Release advisory write locks.
X */
X project_pstate_write(pp);
X commit();
X lock_release();
X
X /*
X * verbose success message
X */
X change_verbose(cp, "removed");
X change_free(cp);
X project_free(pp);
X user_free(up);
X trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xnew_change_undo()
X{
X trace(("new_change_undo()\n{\n"/*}*/));
X switch (arglex())
X {
X default:
X new_change_undo_main();
X break;
X
X case arglex_token_help:
X new_change_undo_help();
X break;
X
X case arglex_token_list:
X new_change_undo_list();
X break;
X }
X trace((/*{*/"}\n"));
X}
END_OF_FILE
if test 9535 -ne `wc -c <'aegis/aencu.c'`; then
echo shar: \"'aegis/aencu.c'\" unpacked with wrong size!
fi
# end of 'aegis/aencu.c'
fi
if test -f 'aegis/aermpr.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'aegis/aermpr.c'\"
else
echo shar: Extracting \"'aegis/aermpr.c'\" \(8594 characters\)
sed "s/^X//" >'aegis/aermpr.c' <<'END_OF_FILE'
X/*
X * aegis - project change supervisor
X * Copyright (C) 1993 Peter Miller.
X * All rights reserved.
X *
X * This program is free software; you can redistribute it and/or modify
X * it under the terms of the GNU General Public License as published by
X * the Free Software Foundation; either version 2 of the License, or
X * (at your option) any later version.
X *
X * This program is distributed in the hope that it will be useful,
X * but WITHOUT ANY WARRANTY; without even the implied warranty of
X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X * GNU General Public License for more details.
X *
X * You should have received a copy of the GNU General Public License
X * along with this program; if not, write to the Free Software
X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X *
X * MANIFEST: functions to implement remove project
X */
X
X#include <stdio.h>
X
X#include <ael.h>
X#include <aermpr.h>
X#include <arglex2.h>
X#include <change.h>
X#include <commit.h>
X#include <error.h>
X#include <gonzo.h>
X#include <help.h>
X#include <lock.h>
X#include <option.h>
X#include <project.h>
X#include <str.h>
X#include <trace.h>
X#include <user.h>
X
X
Xstatic void remove_project_usage _((void));
X
Xstatic void
Xremove_project_usage()
X{
X char *progname;
X
X progname = option_progname_get();
X fprintf
X (
X stderr,
X "usage: %s -ReMove_PRoject [ <option>... ]\n",
X progname
X );
X fprintf
X (
X stderr,
X " %s -ReMove_PRoject -List [ <option>... ]\n",
X progname
X );
X fprintf(stderr, " %s -ReMove_PRoject -Help\n", progname);
X quit(1);
X}
X
X
Xstatic void remove_project_help _((void));
X
Xstatic void
Xremove_project_help()
X{
X static char *text[] =
X {
X"NAME",
X" %s -ReMove_PRoject - remove project",
X"",
X"SYNOPSIS",
X" %s -ReMove_Project <project-name> [ <option>... ]",
X" %s -ReMove_Project -List [ <option>... ]",
X" %s -ReMove_Project -Help",
X"",
X"DESCRIPTION",
X" The %s -ReMove_PRoject command is used to remove a",
X" project, either entirely, or just from %s' supervision.",
X"",
X"OPTIONS",
X" The following options are understood:",
X"",
X" -Keep",
X" This option may be used to retain files and/or",
X" directories usually deleted by the command.",
X"",
X" -LIBrary <abspath>",
X" This option may be used to specify a directory to be",
X" searched for global state files and user state",
X" files. (See aegstate(5) and aeustate(5) for more",
X" information.) Several library options may be present",
X" on the command line, and are search in the order",
X" given. Appended to this explicit search path are",
X" the directories specified by the AEGIS enviroment",
X" variable (colon separated), and finally,",
X" /usr/local/lib/%s is always searched. All paths",
X" specified, either on the command line or in the",
X" AEGIS environment variable, must be absolute.",
X"",
X" -List",
X" This option may be used to obtain a list of suitable",
X" subjects for this command. The list may be more",
X" general than expected.",
X"",
X" -Help",
X" This option may be used to obtain more information",
X" about how to use the %s program.",
X"",
X" -Project <name>",
X" This option may be used to select the project of",
X" interest. When no -Project option is specified, the",
X" AEGIS_PROJECT environment variable is consulted. If",
X" that does not exist, the user's $HOME/.aegisrc file",
X" is examined for a default project field (see",
X" aeuconf(5) for more information). If that does not",
X" exist, when the user is only working on changes",
X" within a single project, the project name defaults",
X" to that project. Otherwise, it is an error.",
X"",
X" -TERse",
X" This option may be used to cause listings to produce",
X" the bare minimum of information. It is usually",
X" useful for shell scripts.",
X"",
X" -Verbose",
X" This option may be used to cause %s to produce",
X" more output. By default %s only produces output",
X" on errors. When used with the -List option this",
X" option causes column headings to be added.",
X"",
X" All options may be abbreviated; the abbreviation is",
X" documented as the upper case letters, all lower case",
X" letters and underscores (_) are optional. You must use",
X" consecutive sequences of optional letters.",
X"",
X" All options are case insensitive, you may type them in",
X" upper case or lower case or a combination of both, case",
X" is not important.",
X"",
X" For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
X" are all interpreted to mean the -Project option. The",
X" argument \"-prj\" will not be understood, because",
X" consecutive optional characters were not supplied.",
X"",
X" Options and other command line arguments may be mixed",
X" arbitrarily on the command line, after the function",
X" selectors.",
X"",
X" The GNU long option names are understood. Since all",
X" option names for aegis are long, this means ignoring the",
X" extra leading '-'. The \"--option=value\" convention is",
X" also understood.",
X"",
X"RECOMMENDED ALIAS",
X" The recommended alias for this command is",
X" csh%% alias aermpr '%s -rmpr \\!* -v'",
X" sh$ aermpr(){%s -rmpr $* -v}",
X"",
X"ERRORS",
X" It is an error if the project has any changes between the",
X" being developed and being integrated states, inclusive.",
X" It is an error if the current user is not an administrator.",
X"",
X"EXIT STATUS",
X" The %s command will exit with a status of 1 on any error.",
X" The %s command will only exit with a status of 0 if there",
X" are no errors.",
X"",
X"COPYRIGHT",
X" %C",
X"",
X"AUTHOR",
X" %A",
X };
X
X help(text, SIZEOF(text), remove_project_usage);
X}
X
X
Xstatic void remove_project_list _((void));
X
Xstatic void
Xremove_project_list()
X{
X arglex();
X while (arglex_token != arglex_token_eoln)
X generic_argument(remove_project_usage);
X list_projects(0, 0);
X}
X
X
Xstatic void remove_project_main _((void));
X
Xstatic void
Xremove_project_main()
X{
X long nerr;
X int j;
X pstate pstate_data;
X string_ty *project_name;
X project_ty *pp;
X change_ty *cp;
X cstate cstate_data;
X user_ty *up;
X int keep;
X
X trace(("remove_project_main()\n{\n"/*}*/));
X keep = 0;
X project_name = 0;
X while (arglex_token != arglex_token_eoln)
X {
X switch (arglex_token)
X {
X default:
X generic_argument(remove_project_usage);
X continue;
X
X case arglex_token_keep:
X if (keep)
X {
X error
X (
X "duplicate \"%s\" option",
X arglex_value.alv_string
X );
X remove_project_usage();
X }
X keep = 1;
X break;
X
X case arglex_token_project:
X if (arglex() != arglex_token_string)
X remove_project_usage();
X /* fall through... */
X
X case arglex_token_string:
X if (project_name)
X fatal("duplicate -Project option");
X project_name = str_from_c(arglex_value.alv_string);
X break;
X }
X arglex();
X }
X
X /*
X * locate project data
X */
X if (!project_name)
X fatal("project must be named explicitly");
X pp = project_alloc(project_name);
X str_free(project_name);
X project_bind_existing(pp);
X
X /*
X * locate user data
X */
X up = user_executing(pp);
X
X /*
X * lock the project
X */
X project_pstate_lock_prepare(pp);
X gonzo_gstate_lock_prepare_new();
X lock_take();
X pstate_data = project_pstate_get(pp);
X
X /*
X * it is an error if any of the changes are active
X */
X nerr = 0;
X for (j = 0; j < pstate_data->change->length; ++j)
X {
X long change_number;
X
X change_number = pstate_data->change->list[j];
X cp = change_alloc(pp, change_number);
X change_bind_existing(cp);
X cstate_data = change_cstate_get(cp);
X if
X (
X cstate_data->state >= cstate_state_being_developed
X &&
X cstate_data->state <= cstate_state_being_integrated
X )
X {
X change_error(cp, "still active");
X ++nerr;
X }
X change_free(cp);
X }
X
X /*
X * it is an error if the current user is not an administrator
X */
X if (!project_administrator_query(pp, user_name(up)))
X {
X project_error
X (
X pp,
X "user \"%S\" is not an administrator",
X user_name(up)
X );
X nerr++;
X }
X if (nerr)
X quit(1);
X
X /*
X * remove the project directory
X */
X if (!keep)
X {
X project_verbose(pp, "remove project directory");
X project_become(pp);
X commit_rmdir_tree_errok(project_home_path_get(pp));
X project_become_undo();
X }
X
X /*
X * tell gonzo to forget about this project
X */
X gonzo_project_delete(pp);
X gonzo_gstate_write();
X
X /*
X * release the locks
X */
X commit();
X lock_release();
X
X /*
X * verbose success message
X */
X project_verbose(pp, "removed");
X
X /*
X * clean up and go home
X */
X project_free(pp);
X user_free(up);
X trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xremove_project()
X{
X trace(("remove_project()\n{\n"/*}*/));
X switch (arglex())
X {
X default:
X remove_project_main();
X break;
X
X case arglex_token_help:
X remove_project_help();
X break;
X
X case arglex_token_list:
X remove_project_list();
X break;
X }
X trace((/*{*/"}\n"));
X}
END_OF_FILE
if test 8594 -ne `wc -c <'aegis/aermpr.c'`; then
echo shar: \"'aegis/aermpr.c'\" unpacked with wrong size!
fi
# end of 'aegis/aermpr.c'
fi
if test -f 'aegis/aerp.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'aegis/aerp.c'\"
else
echo shar: Extracting \"'aegis/aerp.c'\" \(9365 characters\)
sed "s/^X//" >'aegis/aerp.c' <<'END_OF_FILE'
X/*
X * aegis - project change supervisor
X * Copyright (C) 1991, 1992, 1993 Peter Miller.
X * All rights reserved.
X *
X * This program is free software; you can redistribute it and/or modify
X * it under the terms of the GNU General Public License as published by
X * the Free Software Foundation; either version 2 of the License, or
X * (at your option) any later version.
X *
X * This program is distributed in the hope that it will be useful,
X * but WITHOUT ANY WARRANTY; without even the implied warranty of
X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X * GNU General Public License for more details.
X *
X * You should have received a copy of the GNU General Public License
X * along with this program; if not, write to the Free Software
X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X *
X * MANIFEST: functions to implement review pass
X */
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X#include <ael.h>
X#include <aerp.h>
X#include <arglex2.h>
X#include <change.h>
X#include <commit.h>
X#include <dir.h>
X#include <error.h>
X#include <file.h>
X#include <help.h>
X#include <lock.h>
X#include <mem.h>
X#include <option.h>
X#include <os.h>
X#include <project.h>
X#include <sub.h>
X#include <trace.h>
X#include <undo.h>
X#include <user.h>
X
X
Xstatic void review_pass_usage _((void));
X
Xstatic void
Xreview_pass_usage()
X{
X char *progname;
X
X progname = option_progname_get();
X fprintf(stderr, "usage: %s -Review_PASS <change_number> [ <option>... ]\n", progname);
X fprintf(stderr, " %s -Review_PASS -List [ <option>... ]\n", progname);
X fprintf(stderr, " %s -Review_PASS -Help\n", progname);
X quit(1);
X}
X
X
Xstatic void review_pass_help _((void));
X
Xstatic void
Xreview_pass_help()
X{
X static char *text[] =
X {
X"NAME",
X" %s -Review_PASS - pass a change review",
X"",
X"SYNOPSIS",
X" %s -Review_PASS [ <option>... ]",
X" %s -Review_PASS -List [ <option>... ]",
X" %s -Review_PASS -Help",
X"",
X"DESCRIPTION",
X" The %s -Review_PASS command is used to notify",
X" %s that a change has passed review.",
X"",
X" The change will be advenced from the 'being_reviewed'",
X" state to the 'awaitiong_integration' state.",
X"",
X"OPTIONS",
X" The following options are understood:",
X"",
X" -Change <number>",
X" This option may be used to specify a particular",
X" change within a project. When no -Change option is",
X" specified, the AEGIS_CHANGE environment variable is",
X" consulted. If that does not exist, the user's",
X" $HOME/.aegisrc file is examined for a default change",
X" field (see aeuconf(5) for more information). If",
X" that does not exist, when the user is only working",
X" on one change within a project, that is the default",
X" change number. Otherwise, it is an error.",
X"",
X" -Help",
X" This option may be used to obtain more",
X" information about how to use the %s program.",
X"",
X" -List",
X" This option may be used to obtain a list of",
X" suitable subjects for this command. The list may",
X" be more general than expected.",
X"",
X" -Project <name>",
X" This option may be used to select the project of",
X" interest. When no -Project option is specified, the",
X" AEGIS_PROJECT environment variable is consulted. If",
X" that does not exist, the user's $HOME/.aegisrc file",
X" is examined for a default project field (see",
X" aeuconf(5) for more information). If that does not",
X" exist, when the user is only working on changes",
X" within a single project, the project name defaults",
X" to that project. Otherwise, it is an error.",
X"",
X" -TERse",
X" This option may be used to cause listings to",
X" produce the bare minimum of information. It is",
X" usually useful for shell scripts.",
X"",
X" -Verbose",
X" This option may be used to cause %s to produce",
X" more output. By default %s only produces",
X" output on errors. When used with the -List",
X" option this option causes column headings to be",
X" added.",
X"",
X" All options may be abbreviated; the abbreviation is",
X" documented as the upper case letters, all lower case",
X" letters and underscores (_) are optional. You must use",
X" consecutive sequences of optional letters.",
X"",
X" All options are case insensitive, you may type them in",
X" upper case or lower case or a combination of both, case",
X" is not important.",
X"",
X" For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
X" are all interpreted to mean the -Project option. The",
X" argument \"-prj\" will not be understood, because",
X" consecutive optional characters were not supplied.",
X"",
X" Options and other command line arguments may be mixed",
X" arbitrarily on the command line, after the function",
X" selectors.",
X"",
X" The GNU long option names are understood. Since all",
X" option names for aegis are long, this means ignoring the",
X" extra leading '-'. The \"--option=value\" convention is",
X" also understood.",
X"",
X"RECOMMENDED ALIAS",
X" The recommended alias for this command is",
X" csh%% alias aerp '%s -rp \\!* -v'",
X" sh$ aerp(){%s -rp $* -v}",
X"",
X"ERRORS",
X" It is an error if the change is not in the",
X" 'being_reviewed' state.",
X" It is an error if the current user is not a reviewer of",
X" the project.",
X" Its is an error if the current user developed the change",
X" and the project is configured to disallow developers to",
X" review their own changes (default).",
X"",
X"EXIT STATUS",
X" The %s command will exit with a status of 1 on any",
X" error. The %s command will only exit with a status of",
X" 0 if there are no errors.",
X"",
X"COPYRIGHT",
X" %C",
X"",
X"AUTHOR",
X" %A",
X };
X
X help(text, SIZEOF(text), review_pass_usage);
X}
X
X
Xstatic void review_pass_list _((void (*usage)(void)));
X
Xstatic void
Xreview_pass_list(usage)
X void (*usage)_((void));
X{
X string_ty *project_name;
X
X trace(("review_pass_list()\n{\n"/*}*/));
X project_name = 0;
X arglex();
X while (arglex_token != arglex_token_eoln)
X {
X switch (arglex_token)
X {
X default:
X generic_argument(usage);
X continue;
X
X case arglex_token_project:
X if (arglex() != arglex_token_string)
X usage();
X /* fall through... */
X
X case arglex_token_string:
X if (project_name)
X fatal("duplicate -Project option");
X project_name = str_from_c(arglex_value.alv_string);
X break;
X }
X arglex();
X }
X list_changes_in_state_mask
X (
X project_name,
X 1 << cstate_state_being_reviewed
X );
X if (project_name)
X str_free(project_name);
X trace((/*{*/"}\n"));
X}
X
X
Xstatic void review_pass_main _((void));
X
Xstatic void
Xreview_pass_main()
X{
X cstate cstate_data;
X pstate pstate_data;
X cstate_history history_data;
X string_ty *project_name;
X project_ty *pp;
X long change_number;
X change_ty *cp;
X user_ty *up;
X
X trace(("review_pass_main()\n{\n"/*}*/));
X project_name = 0;
X change_number = 0;
X while (arglex_token != arglex_token_eoln)
X {
X switch (arglex_token)
X {
X default:
X generic_argument(review_pass_usage);
X continue;
X
X case arglex_token_change:
X if (arglex() != arglex_token_number)
X review_pass_usage();
X /* fall through... */
X
X case arglex_token_number:
X if (change_number)
X fatal("duplicate -Change option");
X change_number = arglex_value.alv_number;
X if (change_number < 1)
X fatal("change %ld out of range", change_number);
X break;
X
X case arglex_token_project:
X if (arglex() != arglex_token_string)
X review_pass_usage();
X /* fall through... */
X
X case arglex_token_string:
X if (project_name)
X fatal("duplicate -Project option");
X project_name = str_from_c(arglex_value.alv_string);
X break;
X }
X arglex();
X }
X
X /*
X * locate project data
X */
X if (!project_name)
X project_name = user_default_project();
X pp = project_alloc(project_name);
X str_free(project_name);
X project_bind_existing(pp);
X
X /*
X * locate user data
X */
X up = user_executing(pp);
X
X /*
X * locate change data
X */
X if (!change_number)
X change_number = user_default_change(up);
X cp = change_alloc(pp, change_number);
X change_bind_existing(cp);
X
X /*
X * lock the change for writing
X */
X change_cstate_lock_prepare(cp);
X lock_take();
X cstate_data = change_cstate_get(cp);
X pstate_data = project_pstate_get(pp);
X
X /*
X * it is an error if the change is not in the 'being_reviewed' state.
X */
X if (cstate_data->state != cstate_state_being_reviewed)
X change_fatal(cp, "not in 'being_reviewed' state");
X if (!project_reviewer_query(pp, user_name(up)))
X {
X project_fatal
X (
X pp,
X "user \"%S\" is not a reviewer",
X user_name(up)
X );
X }
X if
X (
X !pstate_data->developer_may_review
X &&
X str_equal(change_developer_name(cp), user_name(up))
X )
X change_fatal(cp, "developer may not review");
X
X /*
X * change the state
X * remember who reviewed it
X * add to the change's history
X */
X cstate_data->state = cstate_state_awaiting_integration;
X history_data = change_history_new(cp, up);
X history_data->what = cstate_history_what_review_pass;
X
X /*
X * write out the data and release the locks
X */
X change_cstate_write(cp);
X commit();
X lock_release();
X
X /*
X * run the notify command
X */
X change_run_review_pass_notify_command(cp);
X
X /*
X * verbose success message
X */
X change_verbose(cp, "passed review");
X change_free(cp);
X project_free(pp);
X user_free(up);
X trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xreview_pass()
X{
X trace(("review_pass()\n{\n"/*}*/));
X switch (arglex())
X {
X default:
X review_pass_main();
X break;
X
X case arglex_token_help:
X review_pass_help();
X break;
X
X case arglex_token_list:
X review_pass_list(review_pass_usage);
X break;
X }
X trace((/*{*/"}\n"));
X}
END_OF_FILE
if test 9365 -ne `wc -c <'aegis/aerp.c'`; then
echo shar: \"'aegis/aerp.c'\" unpacked with wrong size!
fi
# end of 'aegis/aerp.c'
fi
if test -f 'aegis/aerpu.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'aegis/aerpu.c'\"
else
echo shar: Extracting \"'aegis/aerpu.c'\" \(9352 characters\)
sed "s/^X//" >'aegis/aerpu.c' <<'END_OF_FILE'
X/*
X * aegis - project change supervisor
X * Copyright (C) 1991, 1992, 1993 Peter Miller.
X * All rights reserved.
X *
X * This program is free software; you can redistribute it and/or modify
X * it under the terms of the GNU General Public License as published by
X * the Free Software Foundation; either version 2 of the License, or
X * (at your option) any later version.
X *
X * This program is distributed in the hope that it will be useful,
X * but WITHOUT ANY WARRANTY; without even the implied warranty of
X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X * GNU General Public License for more details.
X *
X * You should have received a copy of the GNU General Public License
X * along with this program; if not, write to the Free Software
X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X *
X * MANIFEST: functions to implement review pass undo
X */
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X#include <ael.h>
X#include <aerpu.h>
X#include <arglex2.h>
X#include <change.h>
X#include <commit.h>
X#include <dir.h>
X#include <error.h>
X#include <file.h>
X#include <help.h>
X#include <lock.h>
X#include <mem.h>
X#include <option.h>
X#include <os.h>
X#include <project.h>
X#include <sub.h>
X#include <trace.h>
X#include <undo.h>
X#include <user.h>
X
X
Xstatic void review_pass_undo_usage _((void));
X
Xstatic void
Xreview_pass_undo_usage()
X{
X char *progname;
X
X progname = option_progname_get();
X fprintf(stderr, "usage: %s -Review_Pass_Undo <change_number> [ <option>... ]\n", progname);
X fprintf(stderr, " %s -Review_Pass_Undo -List [ <option>... ]\n", progname);
X fprintf(stderr, " %s -Review_Pass_Undo -Help\n", progname);
X quit(1);
X}
X
X
Xstatic void review_pass_undo_help _((void));
X
Xstatic void
Xreview_pass_undo_help()
X{
X static char *text[] =
X {
X"NAME",
X" %s -Review_Pass_Undo - rescind a change review pass",
X"",
X"SYNOPSIS",
X" %s -Review_Pass_Undo [ <option>... ]",
X" %s -Review_Pass_Undo -List [ <option>... ]",
X" %s -Review_Pass_Undo -Help",
X"",
X"DESCRIPTION",
X" The %s -Review_Pass_Undo command is used to notify %s",
X" that a change review pass has been rescinded.",
X"",
X" The change will be moved from the 'awaiting_integration'",
X" state to the 'being_reviewed' state.",
X"",
X"OPTIONS",
X" The following options are understood:",
X"",
X" -Change <number>",
X" This option may be used to specify a particular",
X" change within a project. When no -Change option is",
X" specified, the AEGIS_CHANGE environment variable is",
X" consulted. If that does not exist, the user's",
X" $HOME/.aegisrc file is examined for a default change",
X" field (see aeuconf(5) for more information). If",
X" that does not exist, when the user is only working",
X" on one change within a project, that is the default",
X" change number. Otherwise, it is an error.",
X"",
X" -Help",
X" This option may be used to obtain more information",
X" about how to use the %s program.",
X"",
X" -List",
X" This option may be used to obtain a list of suitable",
X" subjects for this command. The list may be more",
X" general than expected.",
X"",
X" -Project <name>",
X" This option may be used to select the project of",
X" interest. When no -Project option is specified, the",
X" AEGIS_PROJECT environment variable is consulted. If",
X" that does not exist, the user's $HOME/.aegisrc file",
X" is examined for a default project field (see",
X" aeuconf(5) for more information). If that does not",
X" exist, when the user is only working on changes",
X" within a single project, the project name defaults",
X" to that project. Otherwise, it is an error.",
X"",
X" -TERse",
X" This option may be used to cause listings to produce",
X" the bare minimum of information. It is usually",
X" useful for shell scripts.",
X"",
X" -Verbose",
X" This option may be used to cause %s to produce",
X" more output. By default %s only produces output",
X" on errors. When used with the -List option this",
X" option causes column headings to be added.",
X"",
X" All options may be abbreviated; the abbreviation is",
X" documented as the upper case letters, all lower case",
X" letters and underscores (_) are optional. You must use",
X" consecutive sequences of optional letters.",
X"",
X" All options are case insensitive, you may type them in",
X" upper case or lower case or a combination of both, case",
X" is not important.",
X"",
X" For example: the arguments \"-project, \"-PROJ\" and \"-p\"",
X" are all interpreted to mean the -Project option. The",
X" argument \"-prj\" will not be understood, because",
X" consecutive optional characters were not supplied.",
X"",
X" Options and other command line arguments may be mixed",
X" arbitrarily on the command line, after the function",
X" selectors.",
X"",
X" The GNU long option names are understood. Since all",
X" option names for aegis are long, this means ignoring the",
X" extra leading '-'. The \"--option=value\" convention is",
X" also understood.",
X"",
X"RECOMMENDED ALIAS",
X" The recommended alias for this command is",
X" csh%% alias aerpu '%s -rp \\!* -v'",
X" sh$ aerpu(){%s -rp $* -v}",
X"",
X"ERRORS",
X" It is an error if the change is not in the",
X" 'awaiting_integration' state.",
X" It is an error if the current user is not the reviewer of",
X" the change.",
X"",
X"EXIT STATUS",
X" The %s command will exit with a status of 1 on any error.",
X" The %s command will only exit with a status of 0 if there",
X" are no errors.",
X"",
X"COPYRIGHT",
X" %C",
X"",
X"AUTHOR",
X" %A",
X"NAME",
X"",
X"COPYRIGHT",
X" %C",
X"",
X"AUTHOR",
X" %A",
X };
X
X help(text, SIZEOF(text), review_pass_undo_usage);
X}
X
X
Xstatic void review_pass_undo_list _((void (*usage)(void)));
X
Xstatic void
Xreview_pass_undo_list(usage)
X void (*usage)_((void));
X{
X string_ty *project_name;
X
X trace(("review_list()\n{\n"/*}*/));
X project_name = 0;
X arglex();
X while (arglex_token != arglex_token_eoln)
X {
X switch (arglex_token)
X {
X default:
X generic_argument(usage);
X continue;
X
X case arglex_token_project:
X if (arglex() != arglex_token_string)
X usage();
X /* fall through... */
X
X case arglex_token_string:
X if (project_name)
X fatal("duplicate -Project option");
X project_name = str_from_c(arglex_value.alv_string);
X break;
X }
X arglex();
X }
X list_changes_in_state_mask
X (
X project_name,
X 1 << cstate_state_awaiting_integration
X );
X if (project_name)
X str_free(project_name);
X trace((/*{*/"}\n"));
X}
X
X
Xstatic void review_pass_undo_main _((void));
X
Xstatic void
Xreview_pass_undo_main()
X{
X cstate cstate_data;
X pstate pstate_data;
X cstate_history history_data;
X string_ty *project_name;
X project_ty *pp;
X long change_number;
X change_ty *cp;
X user_ty *up;
X
X trace(("review_pass_undo_main()\n{\n"/*}*/));
X project_name = 0;
X change_number = 0;
X while (arglex_token != arglex_token_eoln)
X {
X switch (arglex_token)
X {
X default:
X generic_argument(review_pass_undo_usage);
X continue;
X
X case arglex_token_change:
X if (arglex() != arglex_token_number)
X review_pass_undo_usage();
X /* fall through... */
X
X case arglex_token_number:
X if (change_number)
X fatal("duplicate -Change option");
X change_number = arglex_value.alv_number;
X if (change_number < 1)
X fatal("change %ld out of range", change_number);
X break;
X
X case arglex_token_project:
X if (arglex() != arglex_token_string)
X review_pass_undo_usage();
X /* fall through... */
X
X case arglex_token_string:
X if (project_name)
X fatal("duplicate -Project option");
X project_name = str_from_c(arglex_value.alv_string);
X break;
X }
X arglex();
X }
X
X /*
X * locate project data
X */
X if (!project_name)
X project_name = user_default_project();
X pp = project_alloc(project_name);
X str_free(project_name);
X project_bind_existing(pp);
X
X /*
X * locate user data
X */
X up = user_executing(pp);
X
X /*
X * locate change data
X */
X if (!change_number)
X change_number = user_default_change(up);
X cp = change_alloc(pp, change_number);
X change_bind_existing(cp);
X
X /*
X * lock the change for writing
X */
X change_cstate_lock_prepare(cp);
X lock_take();
X cstate_data = change_cstate_get(cp);
X pstate_data = project_pstate_get(pp);
X
X /*
X * it is an error if the change is not in the 'being_reviewed' state.
X * it is an error if the current user is not the original reviewer
X */
X if (cstate_data->state != cstate_state_awaiting_integration)
X change_fatal(cp, "not in 'awaiting_integration' state");
X if (!str_equal(change_reviewer_name(cp), user_name(up)))
X {
X change_fatal
X (
X cp,
X "user \"%S\" is not the reviewer",
X user_name(up)
X );
X }
X
X /*
X * change the state
X * add to the change's history
X */
X cstate_data->state = cstate_state_being_reviewed;
X history_data = change_history_new(cp, up);
X history_data->what = cstate_history_what_review_pass_undo;
X
X /*
X * write out the data and release the locks
X */
X change_cstate_write(cp);
X commit();
X lock_release();
X
X /*
X * run the notify command
X */
X change_run_review_pass_undo_notify_command(cp);
X
X /*
X * verbose success message
X */
X change_verbose(cp, "review pass rescinded");
X change_free(cp);
X project_free(pp);
X user_free(up);
X trace((/*{*/"}\n"));
X}
X
X
Xvoid
Xreview_pass_undo()
X{
X trace(("review_pass_undo()\n{\n"/*}*/));
X switch (arglex())
X {
X default:
X review_pass_undo_main();
X break;
X
X case arglex_token_help:
X review_pass_undo_help();
X break;
X
X case arglex_token_list:
X review_pass_undo_list(review_pass_undo_usage);
X break;
X }
X trace((/*{*/"}\n"));
X}
END_OF_FILE
if test 9352 -ne `wc -c <'aegis/aerpu.c'`; then
echo shar: \"'aegis/aerpu.c'\" unpacked with wrong size!
fi
# end of 'aegis/aerpu.c'
fi
if test -f 'aegis/commit.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'aegis/commit.c'\"
else
echo shar: Extracting \"'aegis/commit.c'\" \(9183 characters\)
sed "s/^X//" >'aegis/commit.c' <<'END_OF_FILE'
X/*
X * aegis - project change supervisor
X * Copyright (C) 1991, 1992, 1993 Peter Miller.
X * All rights reserved.
X *
X * This program is free software; you can redistribute it and/or modify
X * it under the terms of the GNU General Public License as published by
X * the Free Software Foundation; either version 2 of the License, or
X * (at your option) any later version.
X *
X * This program is distributed in the hope that it will be useful,
X * but WITHOUT ANY WARRANTY; without even the implied warranty of
X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X * GNU General Public License for more details.
X *
X * You should have received a copy of the GNU General Public License
X * along with this program; if not, write to the Free Software
X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X *
X * MANIFEST: functions to store and enact file manipulations for commit
X */
X
X#include <commit.h>
X#include <dir.h>
X#include <mem.h>
X#include <os.h>
X#include <trace.h>
X#include <undo.h>
X
X/*
X * This file contains "commit" functions.
X *
X * The idea is that aegis can be interrupted, or fail from errors,
X * and behave as if "nothing" had happened.
X * That is, no user discernable difference to their environment,
X * and certainly no changes to aegis' data base.
X *
X * To do this, many database functions write updates to temporary files
X * "near" where they are to go, eventually. A commit and an abort function
X * are both issued, one to put the new file where it really goes, and one
X * to remove it. Exactly one option will be exercised.
X *
X * Commit actions will be performed with the user-id set the same as was
X * set at the time the commit call was issued.
X */
X
Xenum what_ty
X{
X what_rename,
X what_unlink_errok,
X what_rmdir_errok,
X what_rmdir_tree_errok
X};
Xtypedef enum what_ty what_ty;
X
Xtypedef struct action_ty action_ty;
Xstruct action_ty
X{
X what_ty what;
X string_ty *path1;
X string_ty *path2;
X action_ty *next;
X int uid;
X int gid;
X int umask;
X};
X
Xstatic action_ty *head1;
Xstatic action_ty *tail1;
Xstatic action_ty *head2;
X
X
X/*
X * NAME
X * link1
X *
X * SYNOPSIS
X * void link1(what_ty action, string_ty *path1, string_ty *path2);
X *
X * DESCRIPTION
X * The link1 function is used to
X * add an new item to the head of chain1.
X *
X * ARGUMENTS
X * action - what to do
X * path1 - mandatory argument
X * path2 - optional argument (NULL if not used)
X */
X
Xstatic void link1 _((what_ty, string_ty *, string_ty *));
X
Xstatic void
Xlink1(what, path1, path2)
X what_ty what;
X string_ty *path1;
X string_ty *path2;
X{
X action_ty *new;
X
X trace(("commit::link1(what = %d, path1 = %08lX, path2 = %08lX)\n{\n"/*}*/, what, path1, path2));
X new = (action_ty *)mem_alloc(sizeof(action_ty));
X new->what = what;
X os_become_query(&new->uid, &new->gid, &new->umask);
X new->path1 = str_copy(path1);
X if (path2)
X new->path2 = str_copy(path2);
X else
X new->path2 = 0;
X new->next = 0;
X if (head1)
X {
X tail1->next = new;
X tail1 = new;
X }
X else
X head1 = tail1 = new;
X trace((/*{*/"}\n"));
X}
X
X
X/*
X * NAME
X * link2
X *
X * SYNOPSIS
X * void link2(what_ty action, string_ty *path1, string_ty *path2);
X *
X * DESCRIPTION
X * The link2 function is used to
X * add an new item to the head of chain2
X *
X * ARGUMENTS
X * action - what to do
X * path1 - mandatory argument
X * path2 - optional argument (NULL if not used)
X */
X
Xstatic void link2 _((what_ty, string_ty *, string_ty *));
X
Xstatic void
Xlink2(what, path1, path2)
X what_ty what;
X string_ty *path1;
X string_ty *path2;
X{
X action_ty *new;
X
X trace(("commit::link2(what = %d, path1 = %08lX, path2 = %08lX)\n{\n"/*}*/, what, path1, path2));
X new = (action_ty *)mem_alloc(sizeof(action_ty));
X new->what = what;
X os_become_query(&new->uid, &new->gid, &new->umask);
X new->path1 = str_copy(path1);
X if (path2)
X new->path2 = str_copy(path2);
X else
X new->path2 = 0;
X new->next = head2;
X head2 = new;
X trace((/*{*/"}\n"));
X}
X
X
X/*
X * NAME
X * commit_rename
X *
X * SYNOPSIS
X * void commit_rename(void);
X *
X * DESCRIPTION
X * The commit_rename function is used to
X * submit a commit request to rename a file.
X *
X * ARGUMENTS
X * from - path of file now
X * to - path of file after commit
X */
X
Xvoid
Xcommit_rename(from, to)
X string_ty *from;
X string_ty *to;
X{
X trace(("commit_rename(from = %08lX, to = %08lX)\n{\n"/*}*/, from, to));
X trace_string(from->str_text);
X trace_string(to->str_text);
X link1(what_rename, from, to);
X trace((/*{*/"}\n"));
X}
X
X
X/*
X * NAME
X * commit_unlink_errok
X *
X * SYNOPSIS
X * void commit_unlink_errok(void);
X *
X * DESCRIPTION
X * The commit_unlink_errok function is used to
X * unlink a file on commit.
X * It will not be an error if the file does not exist.
X *
X * ARGUMENTS
X * path - path of file to be unlinked
X */
X
Xvoid
Xcommit_unlink_errok(path)
X string_ty *path;
X{
X trace(("commit_unlink_errok(path = %08lX)\n{\n"/*}*/, path));
X trace_string(path->str_text);
X link2(what_unlink_errok, path, (string_ty *)0);
X trace((/*{*/"}\n"));
X}
X
X
X/*
X * NAME
X * commit_rmdir_errok
X *
X * SYNOPSIS
X * void commit_rmdir_errok(string_ty *path);
X *
X * DESCRIPTION
X * The commit_rmdir_errok function is used to
X * delete an empty directory on commit.
X * It will not be an error if the directory does not exist.
X * It will not be an error if the directory is not empty.
X *
X * ARGUMENTS
X * path - path of directory to be deleted
X */
X
Xvoid
Xcommit_rmdir_errok(path)
X string_ty *path;
X{
X trace(("commit_rmdir_errok(path = %08lX)\n{\n"/*}*/, path));
X trace_string(path->str_text);
X link2(what_rmdir_errok, path, (string_ty *)0);
X trace((/*{*/"}\n"));
X}
X
X
X/*
X * NAME
X * commit_rmdir_tree_errok
X *
X * SYNOPSIS
X * void commit_rmdir_tree_errok(string_ty *path);
X *
X * DESCRIPTION
X * The commit_rmdir_tree_errok function is used to
X * delete a directory tree on commit.
X * It will not be an error if the directory does not exist.
X * It will not be an error if the directory, or any subtree, is not empty.
X *
X * ARGUMENTS
X * path - path of directory to be deleted
X */
X
Xvoid
Xcommit_rmdir_tree_errok(path)
X string_ty *path;
X{
X trace(("commit_rmdir_tree_errok(path = %08lX)\n{\n"/*}*/, path));
X trace_string(path->str_text);
X link2(what_rmdir_tree_errok, path, (string_ty *)0);
X trace((/*{*/"}\n"));
X}
X
X
X/*
X * NAME
X * rmdir_tree_callback
X *
X * SYNOPSIS
X * void rmdir_tree_callback(void * arg, dir_walk_message_ty message,
X * string_ty *path, struct stat *st);
X *
X * DESCRIPTION
X * The rmdir_tree_callback function is used to
X * perform an action while walking a directory tree's structure.
X *
X * This function is the one that actually deletes things out of the
X * directory tree as it is walked.
X * Note that the directory should be deleted last,
X * after all contents have been nuked.
X *
X * Some sleight-of-hand is involved here,
X * as this function pushes extra stuff onto the lists of
X * things to be deleted, rather than really doing it itself.
X *
X * ARGUMENTS
X * arg - argument given to dir_walk for us
X * message - what sort of file system entity we are looking at
X * path - the absolute path of the file system entity
X * st - pointer to stat structure describing file system entity
X */
X
Xstatic void rmdir_tree_callback _((void *, dir_walk_message_ty,
X string_ty *path, struct stat *));
X
Xstatic void
Xrmdir_tree_callback(arg, message, path, stat)
X void *arg;
X dir_walk_message_ty message;
X string_ty *path;
X struct stat *stat;
X{
X trace(("rmdir_tree_callback(message = %d, path = %08lX, \
Xstat = %08lX)\n{\n"/*}*/, message, path, stat));
X trace_string(path->str_text);
X switch (message)
X {
X case dir_walk_dir_before:
X commit_rmdir_errok(path);
X os_chmod_errok(path, 0750);
X break;
X
X case dir_walk_dir_after:
X break;
X
X case dir_walk_file:
X case dir_walk_special:
X case dir_walk_symlink:
X commit_unlink_errok(path);
X break;
X }
X trace((/*{*/"}\n"));
X}
X
X
X/*
X * NAME
X * commit
X *
X * SYNOPSIS
X * void commit(void);
X *
X * DESCRIPTION
X * The commit function is used to
X * perform all the actions queued using the commit_* functions.
X *
X * After it has completed successfully, further calls to commit()
X * will be NOPs, until new commit_* functions are used.
X *
X * When the commit has succeeded, the undo list is cancelled,
X * since there is now no reason to undo anything.
X */
X
Xvoid
Xcommit()
X{
X trace(("commit()\n{\n"/*}*/));
X while (head1 || head2)
X {
X action_ty *action;
X
X /*
X * Take the first item off the list.
X * Note that actions may append more items to the list.
X */
X if (head1)
X {
X action = head1;
X head1 = action->next;
X if (!head1)
X tail1 = 0;
X }
X else
X {
X action = head2;
X head2 = action->next;
X }
X
X /*
X * Do the action.
X */
X os_become(action->uid, action->gid, action->umask);
X switch (action->what)
X {
X case what_rename:
X os_rename(action->path1, action->path2);
X undo_rename(action->path2, action->path1);
X break;
X
X case what_unlink_errok:
X os_unlink_errok(action->path1);
X break;
X
X case what_rmdir_errok:
X os_rmdir_errok(action->path1);
X break;
X
X case what_rmdir_tree_errok:
X dir_walk(action->path1, rmdir_tree_callback, 0);
X break;
X }
X os_become_undo();
X
X /*
X * Free the list element.
X */
X str_free(action->path1);
X if (action->path2)
X str_free(action->path2);
X mem_free((char *)action);
X }
X
X /*
X * it's all committed, nothing left to undo.
X */
X undo_cancel();
X trace((/*{*/"}\n"));
X}
END_OF_FILE
if test 9183 -ne `wc -c <'aegis/commit.c'`; then
echo shar: \"'aegis/commit.c'\" unpacked with wrong size!
fi
# end of 'aegis/commit.c'
fi
if test -f 'aux/Makefile.sh' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'aux/Makefile.sh'\"
else
echo shar: Extracting \"'aux/Makefile.sh'\" \(8640 characters\)
sed "s/^X//" >'aux/Makefile.sh' <<'END_OF_FILE'
X#! /bin/sh
X#
X# aegis - project change supervisor
X# Copyright (C) 1991, 1992, 1993 Peter Miller.
X# All rights reserved.
X#
X# This program is free software; you can redistribute it and/or modify
X# it under the terms of the GNU General Public License as published by
X# the Free Software Foundation; either version 2 of the License, or
X# (at your option) any later version.
X#
X# This program is distributed in the hope that it will be useful,
X# but WITHOUT ANY WARRANTY; without even the implied warranty of
X# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X# GNU General Public License for more details.
X#
X# You should have received a copy of the GNU General Public License
X# along with this program; if not, write to the Free Software
X# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X#
X# MANIFEST: shell script to generate the Mafile file
X#
Xfmtgen_files=
Xaegis_files=
Xtest_files=
Xclean_files="core bin/fmtgen"
Xecho "#"
Xecho "# You may need to change this for your system."
Xecho "# The \`\`h'' directory supplements your system, not replacing it."
Xecho "# The first variation is for gcc when it isn't the native complier,"
Xecho "# the second variation is for systems with missing ANSI C include files,"
Xecho "# the third variation is for conforming ANSI C implementations."
Xecho "#"
Xecho "# H = -I/usr/local/lib/gcc-include -I/usr/include -Ih"
Xecho "# H = -I/usr/include -Ih"
Xecho "H ="
Xecho "# H = # SunOS"
Xecho "# H = # ConvexOS"
Xecho "# H = # dgux"
Xecho "# H = # dcosx (pyramid)"
Xecho "# H = # ULTRIX"
Xecho "# H = # hpux"
Xecho "# H = # SCO"
Xecho "# H = # IRIX"
Xecho
Xecho "#"
Xecho "# the name of the compiler to use"
Xecho "#"
Xecho "CC = cc"
Xecho "# CC = gcc"
Xecho "# CC = cc # SunOS"
Xecho "# CC = cc # ConvexOS"
Xecho "# CC = cc # dgux"
Xecho "# CC = /usr/ucb/cc # dcosx (pyramid)"
Xecho "# CC = cc # ULTRIX"
Xecho "# CC = cc # hpux"
Xecho "# CC = rcc # SCO"
Xecho "# CC = cc # IRIX"
Xecho
Xecho "#"
Xecho "# The compiler flags to use, except for include path."
Xecho "#"
Xecho "CFLAGS = -O"
Xecho "# CFLAGS = -g"
Xecho "# CFLAGS = -O # SunOS"
Xecho "# CFLAGS = -O # ConvexOS"
Xecho "# CFLAGS = -O # dgux"
Xecho "# CFLAGS = -O -Wall -ansi # gcc"
Xecho "# CFLAGS = -O -Xt -U__STDC__ # dcosx (pyramid /usr/ucb/cc is brain-dead)"
Xecho "# CFLAGS = -O # ULTRIX"
Xecho "# CFLAGS = -O # hpux"
Xecho "# CFLAGS = -O # SCO"
Xecho "# CFLAGS = -O # IRIX"
Xecho
Xecho "#"
Xecho "# which yacc to use"
Xecho "#"
Xecho "YACC = yacc"
Xecho "# YACC = byacc # Berkeley"
Xecho "# YACC = bison -y # GNU"
Xecho ""
Xecho "#"
Xecho "# where to put the library directory"
Xecho "# (not used in testing mode)"
Xecho "#"
Xecho "LIB = /usr/local/lib/aegis"
Xecho ""
Xecho "#"
Xecho "# where to put the executables"
Xecho "#"
Xecho "BIN = /usr/local/bin"
Xecho ""
Xecho "#"
Xecho "# where to put the manual entries"
Xecho "#"
Xecho "MAN = /usr/local/man"
Xecho ""
Xecho "#"
Xecho "# extra libraries required for your system"
Xecho "#"
Xecho "LIBRARIES ="
Xecho "# LIBRARIES = -lbsd"
Xecho "# LIBRARIES = # SunOS"
Xecho "# LIBRARIES = # ConvexOS"
Xecho "# LIBRARIES = # dgux"
Xecho "# LIBRARIES = -lucb # dcosx (pyramid)"
Xecho "# LIBRARIES = # ULTRIX"
Xecho "# LIBRARIES = # hpux"
Xecho "# LIBRARIES = -lsocket # SCO"
Xecho "# LIBRARIES = # IRIX"
Xecho ""
Xecho "#"
Xecho "# shell to use to run the tests"
Xecho "# make sure there are no spaces after the definition,"
Xecho "# many flavours of make(1) can't cope with them."
Xecho "#"
Xecho "SHELL = /bin/sh"
Xecho "# SHELL = /bin/sh # SunOS"
Xecho "# SHELL = /bin/sh # ConvexOS"
Xecho "# SHELL = /bin/sh # dgux"
Xecho "# SHELL = /bin/sh # dcosx (pyramid)"
Xecho "# SHELL = /bin/sh5 # ULTRIX"
Xecho "# SHELL = /bin/ksh # apollo"
Xecho "# SHELL = /bin/sh # hpux"
Xecho "# SHELL = /bin/sh # SCO"
Xecho "# SHELL = /bin/sh # IRIX"
Xecho ""
Xecho "# You should not need to alter anything below this point."
Xecho "#------------------------------------------------------------"
Xecho ""
Xecho "all: bin/aegis"
Xecho
Xrm -f common/conf.h
Xcp /dev/null common/conf.h
Xfor file in $*
Xdo
X case $file in
X
X fmtgen/*.y)
X root=`basename $file .y`
X dep=`c_incl -Ifmtgen -Icommon -ns -nc $file`
X echo
X echo "fmtgen/${root}.gen.c fmtgen/${root}.gen.h: $file"
X echo " $(YACC) -d $file"
X echo " sed \"s/[yY][yY]/${root}_/g\" < y.tab.c > fmtgen/${root}.gen.c"
X echo " rm y.tab.c"
X echo " sed \"s/[yY][yY]/${root}_/g\" < y.tab.h > fmtgen/${root}.gen.h"
X echo " rm y.tab.h"
X clean_files="$clean_files fmtgen/${root}.gen.c fmtgen/${root}.gen.h"
X echo
X echo "fmtgen/${root}.gen.o: fmtgen/${root}.gen.c" $dep
X echo " $(CC) $(CFLAGS) -Ifmtgen -Icommon $(H) -c fmtgen/${root}.gen.c"
X echo " mv ${root}.gen.o fmtgen/${root}.gen.o"
X fmtgen_files="$fmtgen_files fmtgen/${root}.gen.o"
X clean_files="$clean_files fmtgen/${root}.gen.o"
X ;;
X
X fmtgen/*.c)
X root=`basename $file .c`
X dep=`c_incl -Ifmtgen -Icommon -ns -nc $file`
X echo
X echo "fmtgen/${root}.o: $file" $dep
X echo " $(CC) $(CFLAGS) -Ifmtgen -Icommon $(H) -c fmtgen/${root}.c"
X echo " mv ${root}.o fmtgen/${root}.o"
X fmtgen_files="$fmtgen_files fmtgen/${root}.o"
X clean_files="$clean_files fmtgen/${root}.o"
X ;;
X
X aegis/*.def)
X root=`basename $file .def`
X dep=`c_incl -Iaegis -ns -nc $file`
X echo
X echo "aegis/${root}.c aegis/${root}.h: $file bin/fmtgen" $dep
X echo " bin/fmtgen -Iaegis $file aegis/${root}.c aegis/${root}.h"
X clean_files="$clean_files aegis/${root}.c aegis/${root}.h"
X echo
X dep=`c_incl -Iaegis -Icommon -ns -nc aegis/${root}.c`
X echo "aegis/${root}.o: aegis/${root}.c" $dep
X echo " $(CC) $(CFLAGS) -Iaegis -Icommon $(H) -c aegis/${root}.c"
X echo " mv ${root}.o aegis/${root}.o"
X aegis_files="$aegis_files aegis/${root}.o"
X clean_files="$clean_files aegis/${root}.o"
X ;;
X
X aegis/*.y)
X root=`basename $file .y`
X dep=`c_incl -Iaegis -Icommon -ns -nc $file`
X echo
X echo "aegis/${root}.gen.c aegis/${root}.gen.h: $file"
X echo " $(YACC) -d $file"
X echo " sed \"s/[yY][yY]/${root}_/g\" < y.tab.c > aegis/${root}.gen.c"
X echo " rm y.tab.c"
X echo " sed \"s/[yY][yY]/${root}_/g\" < y.tab.h > aegis/${root}.gen.h"
X echo " rm y.tab.h"
X clean_files="$clean_files aegis/${root}.gen.c aegis/${root}.gen.h"
X echo
X echo "aegis/${root}.gen.o: aegis/${root}.gen.c" $dep
X echo " $(CC) $(CFLAGS) -Iaegis -Icommon $(H) -c aegis/${root}.gen.c"
X echo " mv ${root}.gen.o aegis/${root}.gen.o"
X aegis_files="$aegis_files aegis/${root}.gen.o"
X clean_files="$clean_files aegis/${root}.gen.o"
X ;;
X
X aegis/*.c)
X root=`basename $file .c`
X dep=`c_incl -Iaegis -Icommon -ns -nc $file`
X echo
X echo "aegis/${root}.o: $file" $dep
X oflg=
X if [ $root = gonzo ]
X then
X oflg="-D'LIB=\"$(LIB)\"'"
X fi
X echo " $(CC) $(CFLAGS) $oflg -Iaegis -Icommon $(H) -c $file"
X echo " mv ${root}.o aegis/${root}.o"
X aegis_files="$aegis_files aegis/${root}.o"
X clean_files="$clean_files aegis/${root}.o"
X ;;
X
X common/*.c)
X root=`basename $file .c`
X dep=`c_incl -Icommon -ns -nc $file`
X echo
X echo "common/${root}.o: $file" $dep
X echo " $(CC) $(CFLAGS) -Icommon $(H) -c $file"
X echo " mv ${root}.o common/${root}.o"
X aegis_files="$aegis_files common/${root}.o"
X fmtgen_files="$fmtgen_files common/${root}.o"
X clean_files="$clean_files common/${root}.o"
X ;;
X
X test/*/*)
X root=`basename $file .sh`
X echo ""
X echo "${root}: all $file"
X echo " $(SHELL) $file"
X test_files="$test_files $root"
X ;;
X
X *)
X ;;
X esac
Xdone
X
X#
X# clean up the area
X#
Xecho ''
Xecho 'clean:'
Xecho ' rm -f' $clean_files
Xecho ''
Xecho 'realclean: clean'
Xecho ' rm -f bin/aegis'
Xecho ''
Xecho 'clobber: realclean'
Xecho ' rm -f common/conf.h'
X
X#
X# default the conf.h file
X# if they have forgotten to set it
X#
Xecho ''
Xecho 'common/conf.h:'
Xecho ' echo "#include <../conf/`uname -s`-`uname -r`>" > common/conf.h'
X
Xecho
Xecho "FmtgenFiles = $fmtgen_files"
Xecho
Xecho "bin/fmtgen: $(FmtgenFiles)"
Xecho " if test ! -d bin; then mkdir bin; fi; exit 0"
Xecho " $(CC) -o bin/fmtgen $(FmtgenFiles) $(LIBRARIES)"
X
Xecho
Xecho "AegisFiles = $aegis_files"
Xecho
Xecho "bin/aegis: $(AegisFiles)"
Xecho " if test ! -d bin; then mkdir bin; fi; exit 0"
Xecho " $(CC) -o bin/aegis $(AegisFiles) $(LIBRARIES)"
X
Xecho
Xecho "sure:" $test_files
Xecho " @echo Passed All Tests"
X
Xecho
Xecho "install: all"
Xecho " cp bin/aegis $(BIN)"
Xecho " chown root $(BIN)/aegis"
Xecho " chmod a+x,u+s $(BIN)/aegis"
Xecho " -mkdir $(LIB)"
Xecho " chmod 0755 $(LIB)"
Xecho " cp lib/* $(LIB)"
Xecho " chmod a+r $(LIB)/*"
Xecho " chmod a+x $(LIB)/*.sh"
Xecho " chown bin $(LIB)"
Xecho " chgrp bin $(LIB)"
Xecho " $(SHELL) man1/install.sh $(MAN)/man1"
Xecho " $(SHELL) man5/install.sh $(MAN)/man5"
X
Xrm common/conf.h
Xexit 0
END_OF_FILE
if test 8640 -ne `wc -c <'aux/Makefile.sh'`; then
echo shar: \"'aux/Makefile.sh'\" unpacked with wrong size!
fi
# end of 'aux/Makefile.sh'
fi
if test -f 'common/arglex.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'common/arglex.c'\"
else
echo shar: Extracting \"'common/arglex.c'\" \(10257 characters\)
sed "s/^X//" >'common/arglex.c' <<'END_OF_FILE'
X/*
X * aegis - project change supervisor
X * Copyright (C) 1991, 1992, 1993 Peter Miller.
X * All rights reserved.
X *
X * This program is free software; you can redistribute it and/or modify
X * it under the terms of the GNU General Public License as published by
X * the Free Software Foundation; either version 2 of the License, or
X * (at your option) any later version.
X *
X * This program is distributed in the hope that it will be useful,
X * but WITHOUT ANY WARRANTY; without even the implied warranty of
X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X * GNU General Public License for more details.
X *
X * You should have received a copy of the GNU General Public License
X * along with this program; if not, write to the Free Software
X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X *
X * MANIFEST: lexical analysis of command line arguments
X */
X
X#include <stddef.h>
X#include <string.h>
X#include <ctype.h>
X
X#include <arglex.h>
X#include <error.h>
X#include <option.h>
X#include <str.h>
X#include <trace.h>
X
Xstatic arglex_table_ty table[] =
X{
X { "-", arglex_token_stdio, },
X { "-Help", arglex_token_help, },
X { "-VERSion", arglex_token_version, },
X { "-TRace", arglex_token_trace, },
X};
X
Xstatic int argc;
Xstatic char **argv;
X arglex_value_ty arglex_value;
X arglex_token_ty arglex_token;
Xstatic arglex_table_ty *utable;
Xstatic char *partial;
X
X
X/*
X * NAME
X * arglex_init
X *
X * SYNOPSIS
X * void arglex_init(int ac, char **av, arglex_table-t *tp);
X *
X * DESCRIPTION
X * The arglex_init function is used to initialize the
X * command line processing.
X *
X * ARGUMENTS
X * ac - aergument count, from main
X * av - argument values, from main
X * tp - pointer to table of options
X *
X * CAVEAT
X * Must be called before the arglex() function.
X */
X
Xvoid
Xarglex_init(ac, av, tp)
X int ac;
X char **av;
X arglex_table_ty *tp;
X{
X option_progname_set(av[0]);
X argc = ac - 1;
X argv = av + 1;
X utable = tp;
X}
X
X
X/*
X * NAME
X * arglex_compare
X *
X * SYNOPSIS
X * int arglex_compare(char *formal, char *actual);
X *
X * DESCRIPTION
X * The arglex_compare function is used to compare
X * a command line string with a formal spec of the option,
X * to see if they compare equal.
X *
X * The actual is case-insensitive. Uppercase in the formal
X * means a mandatory character, while lower case means optional.
X * Any number of consecutive optional characters may be supplied
X * by actual, but none may be skipped, unless all are skipped to
X * the next non-lower-case letter.
X *
X * The underscore (_) is like a lower-case minus,
X * it matches "", "-" and "_".
X *
X * The "*" in a pattern matches everything to the end of the line,
X * anything after the "*" is ignored. The rest of the line is pointed
X * to by the "partial" variable as a side-effect (else it will be 0).
X * This rather ugly feature is to support "-I./dir" type options.
X *
X * A backslash in a pattern nominates an exact match required,
X * case must matche excatly here.
X * This rather ugly feature is to support "-I./dir" type options.
X *
X * For example: "-project" and "-P' both match "-Project",
X * as does "-proJ", but "-prj" does not.
X *
X * For example: "-devDir" and "-d_d' both match "-Development_Directory",
X * but "-dvlpmnt_drctry" does not.
X *
X * For example: to match include path specifications, use a pattern
X * such as "-\\I*", and the partial global variable will have the
X * path in it on return.
X *
X * ARGUMENTS
X * formal - the "pattern" for the option
X * actual - what the user supplied
X *
X * RETURNS
X * int; zero if no match,
X * non-zero if they do match.
X */
X
Xint
Xarglex_compare(formal, actual)
X char *formal;
X char *actual;
X{
X char fc;
X char ac;
X int result;
X
X trace(("arglex_compare(formal = \"%s\", actual = \"%s\")\n{\n",
X formal, actual));
X for (;;)
X {
X trace_string(formal);
X trace_string(actual);
X ac = *actual++;
X if (isupper(ac))
X ac = tolower(ac);
X fc = *formal++;
X switch (fc)
X {
X case 0:
X result = !ac;
X goto done;
X
X case '_':
X if (ac == '-')
X break;
X /* fall through... */
X
X case 'a': case 'b': case 'c': case 'd': case 'e':
X case 'f': case 'g': case 'h': case 'i': case 'j':
X case 'k': case 'l': case 'm': case 'n': case 'o':
X case 'p': case 'q': case 'r': case 's': case 't':
X case 'u': case 'v': case 'w': case 'x': case 'y':
X case 'z':
X /*
X * optional characters
X */
X if (ac == fc && arglex_compare(formal, actual))
X {
X result = 1;
X goto done;
X }
X
X /*
X * skip forward to next
X * mandatory character, or after '_'
X */
X while (islower(*formal))
X ++formal;
X if (*formal == '_')
X {
X ++formal;
X if (ac == '_' || ac == '-')
X ++actual;
X }
X --actual;
X break;
X
X case '*':
X /*
X * This is a hack, it should really
X * check for a match match the stuff after
X * the '*', too, a la glob.
X */
X if (!ac)
X {
X result = 0;
X goto done;
X }
X partial = actual - 1;
X result = 1;
X goto done;
X
X case '\\':
X if (actual[-1] != *formal++)
X {
X result = 0;
X goto done;
X }
X break;
X
X case 'A': case 'B': case 'C': case 'D': case 'E':
X case 'F': case 'G': case 'H': case 'I': case 'J':
X case 'K': case 'L': case 'M': case 'N': case 'O':
X case 'P': case 'Q': case 'R': case 'S': case 'T':
X case 'U': case 'V': case 'W': case 'X': case 'Y':
X case 'Z':
X fc = tolower(fc);
X /* fall through... */
X
X default:
X /*
X * mandatory characters
X */
X if (fc != ac)
X {
X result = 0;
X goto done;
X }
X break;
X }
X }
X done:
X trace(("return %d;\n}\n", result));
X return result;
X}
X
X
X/*
X * NAME
X * is_a_number
X *
X * SYNOPSIS
X * int is_a_number(char *s);
X *
X * DESCRIPTION
X * The is_a_number function is used to determine if the
X * argument is a number.
X *
X * The value is placed in arglex_value.alv_number as
X * a side effect.
X *
X * Negative and positive signs are accepted.
X * The C conventions for decimal, octal and hexadecimal are understood.
X *
X * There may be no white space anywhere in the string,
X * and the string must end after the last digit.
X * Trailing garbage will be interpreted to mean it is not a string.
X *
X * ARGUMENTS
X * s - string to be tested and evaluated
X *
X * RETURNS
X * int; zero if not a number,
X * non-zero if is a number.
X */
X
Xstatic int is_a_number _((char *));
X
Xstatic int
Xis_a_number(s)
X char *s;
X{
X long n;
X int sign;
X
X n = 0;
X switch (*s)
X {
X case '-':
X ++s;
X sign = -1;
X break;
X
X case '+':
X ++s;
X sign = 1;
X break;
X
X default:
X sign = 1;
X break;
X }
X switch (*s)
X {
X case '0':
X if ((s[1] == 'x' || s[1] == 'X') && s[2])
X {
X s += 2;
X for (;;)
X {
X switch (*s)
X {
X case '0': case '1': case '2': case '3':
X case '4': case '5': case '6': case '7':
X case '8': case '9':
X n = n * 16 + *s++ - '0';
X continue;
X
X case 'A': case 'B': case 'C':
X case 'D': case 'E': case 'F':
X n = n * 16 + *s++ - 'A' + 10;
X continue;
X
X case 'a': case 'b': case 'c':
X case 'd': case 'e': case 'f':
X n = n * 16 + *s++ - 'a' + 10;
X continue;
X }
X break;
X }
X }
X else
X {
X for (;;)
X {
X switch (*s)
X {
X case '0': case '1': case '2': case '3':
X case '4': case '5': case '6': case '7':
X n = n * 8 + *s++ - '0';
X continue;
X }
X break;
X }
X }
X break;
X
X case '1': case '2': case '3': case '4':
X case '5': case '6': case '7': case '8': case '9':
X for (;;)
X {
X switch (*s)
X {
X case '0': case '1': case '2': case '3':
X case '4': case '5': case '6': case '7':
X case '8': case '9':
X n = n * 10 + *s++ - '0';
X continue;
X }
X break;
X }
X break;
X
X default:
X return 0;
X }
X if (*s)
X return 0;
X arglex_value.alv_number = n * sign;
X return 1;
X}
X
X
X/*
X * NAME
X * arglex
X *
X * SYNOPSIS
X * arglex_token_ty arglex(void);
X *
X * DESCRIPTION
X * The arglex function is used to perfom lexical analysis
X * on the command line arguments.
X *
X * Unrecognised options are returned as arglex_token_option
X * for anything starting with a '-', or
X * arglex_token_string otherwise.
X *
X * RETURNS
X * The next token in the token stream.
X * When the end is reached, arglex_token_eoln is returned forever.
X *
X * CAVEAT
X * Must call arglex_init befor this function is called.
X */
X
Xarglex_token_ty
Xarglex()
X{
X arglex_table_ty *tp;
X int j;
X arglex_table_ty *hit[20];
X int nhit;
X static char *pushback;
X char *arg;
X
X trace(("arglex()\n{\n"));
X if (pushback)
X {
X /*
X * the second half of a "-foo=bar" style argument.
X */
X arg = pushback;
X pushback = 0;
X }
X else
X {
X if (argc <= 0)
X {
X arglex_token = arglex_token_eoln;
X arg = "";
X goto done;
X }
X arg = argv[0];
X argc--;
X argv++;
X
X /*
X * See if it looks like a GNU "-foo=bar" option.
X * Split it at the '=' to make it something the
X * rest of the code understands.
X */
X if (arg[0] == '-' && arg[1] != '=')
X {
X char *eqp;
X
X eqp = strchr(arg, '=');
X if (eqp)
X {
X pushback = eqp + 1;
X *eqp = 0;
X }
X }
X
X /*
X * Turn the GNU-style leading "--"
X * into "-" if necessary.
X */
X if
X (
X arg[0] == '-'
X &&
X arg[1] == '-'
X &&
X arg[2]
X &&
X !is_a_number(arg + 1)
X )
X ++arg;
X }
X
X /*
X * see if it is a number
X */
X if (is_a_number(arg))
X {
X arglex_token = arglex_token_number;
X goto done;
X }
X
X /*
X * scan the tables to see what it matches
X */
X nhit = 0;
X partial = 0;
X for (tp = table; tp < ENDOF(table); tp++)
X {
X if (arglex_compare(tp->t_name, arg))
X hit[nhit++] = tp;
X }
X if (utable)
X {
X for (tp = utable; tp->t_name; tp++)
X {
X if (arglex_compare(tp->t_name, arg))
X hit[nhit++] = tp;
X }
X }
X
X /*
X * deal with unknown or ambiguous options
X */
X switch (nhit)
X {
X case 0:
X /*
X * not found in the tables
X */
X if (*arg == '-')
X arglex_token = arglex_token_option;
X else
X arglex_token = arglex_token_string;
X break;
X
X case 1:
X arglex_token = hit[0]->t_token;
X if (partial)
X arg = partial;
X else
X arg = hit[0]->t_name;
X break;
X
X default:
X {
X string_ty *s1;
X string_ty *s2;
X
X s1 = str_from_c(hit[0]->t_name);
X for (j = 1; j < nhit; ++j)
X {
X s2 = str_format("%S, %s", s1, hit[j]->t_name);
X str_free(s1);
X s2 = s2;
X }
X fatal
X (
X "option \"%s\" abmiguous (%s)",
X arg,
X s1->str_text
X );
X }
X }
X
X /*
X * here for all exits
X */
X done:
X arglex_value.alv_string = arg;
X trace(("return %d; /* %s */\n", arglex_token, arglex_value.alv_string));
X trace((/*{*/"}\n"));
X return arglex_token;
X}
END_OF_FILE
if test 10257 -ne `wc -c <'common/arglex.c'`; then
echo shar: \"'common/arglex.c'\" unpacked with wrong size!
fi
# end of 'common/arglex.c'
fi
if test -f 'doc/c5.0.so' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'doc/c5.0.so'\"
else
echo shar: Extracting \"'doc/c5.0.so'\" \(10142 characters\)
sed "s/^X//" >'doc/c5.0.so' <<'END_OF_FILE'
X.\"
X.\" aegis - project change supervisor
X.\" Copyright (C) 1991, 1992, 1993 Peter Miller.
X.\" All rights reserved.
X.\"
X.\" This program is free software; you can redistribute it and/or modify
X.\" it under the terms of the GNU General Public License as published by
X.\" the Free Software Foundation; either version 2 of the License, or
X.\" (at your option) any later version.
X.\"
X.\" This program is distributed in the hope that it will be useful,
X.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
X.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X.\" GNU General Public License for more details.
X.\"
X.\" You should have received a copy of the GNU General Public License
X.\" along with this program; if not, write to the Free Software
X.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X.\"
X.\" MANIFEST: User Guide, The Project Attributes
X.\"
X.bp
X.1C
X.nh 1 "The Project Attributes"
X.LP
XThe project attributes are manipulated using the
X.I aepa (1)
Xcommand.
XThis command reads a project attributes file to set the project attributes.
XThis file can be thought of as having several sections,
Xeach of which will be covered by this chapter.
XYou should see the
X.I aepattr (5)
Xmanual entry for more details.
X.nh 2 "Description and Access"
X.LP
XThe
X.I description
Xfield is a string which contains
Xa description of the project.
XLarge amounts of prose are not required;
Xa single line is sufficient.
X.LP
XThe
X.I default_development_directory
Xfield is a string which contains
Xthe pathname of where to place new development directories.
XThe pathname must be absolute.
XThis field is only
Xconsulted if the
X.I uconf (5)
Xfield of the same name is not set.
XDefaults to
X.I $HOME .
X.LP
XThe
X.I umask
Xfield is an integer which is set to the
Xfile permission mode mask.
XSee
X.I umask (2)
Xfor more information.
XThis value will always be OR'ed with 022,
Xbecause aegis is paranoid.
X.nh 2 "Notification Commands"
X.LP
XThe
X.I develop_end_notify_command
Xfield is a string which contains a command to be used to
Xnotify that a change requires reviewing.
XAll of the substitutions described in
X.I aesub (5)
Xare available.
XThis field is optional, if it is not specified no notification will be issued.
XThis command could also be used to notify other management systems,
Xsuch as progress and defect tracking,
Xin addition to notifying users.
X.LP
XThe
X.I develop_end_undo_notify_command
Xfield is a string containing a command used to
Xnotify that a change has been withdrawn from review
Xfor further development.
XAll of the substitutions described in
X.I aesub (5)
Xare available.
XThis field is optional, if it is not specified no notification will be issued.
XThis command could also be used to notify other management systems,
Xsuch as progress and defect tracking,
Xin addition to notifying users.
X.LP
XThe
X.I review_pass_notify_command
Xfield is a string containing the command to
Xnotify that the review has passed.
XAll of the substitutions described in
X.I aesub (5)
Xare available.
XThis field is optional, if it is not specified no notification will be issued.
XThis command could also be used to notify other management systems,
Xsuch as progress and defect tracking,
Xin addition to notifying users.
X.LP
XThe
X.I review_pass_undo_notify_command
Xfield is a string containing the command to
Xnotify that a review pass has has been rescinded.
XAll of the substitutions described in
X.I aesub (5)
Xare available.
XThis field is optional, and defaults to the
X.I develop_end_notify_command
Xfield if not specified.
XIf neither is specified, no notification will be issued.
XThis command could also be used to notify other management systems,
Xsuch as progress and defect tracking,
Xin addition to notifying users.
X.LP
XThe
X.I review_fail_notify_command
Xfield is a string containing the command to
Xnotify that the review has failed.
XAll of the substitutions described in
X.I aesub (5)
Xare available.
XThis field is optional, if it is not specified no notification will be issued.
XThis command could also be used to notify other management systems,
Xsuch as progress and defect tracking,
Xin addition to notifying users.
X.LP
XThe
X.I integrate_pass_notify_command
Xfield is a string containing the command to
Xnotify that the integration has passed.
XAll of the substitutions described in
X.I aesub (5)
Xare available.
XThis field is optional, if it is not specified no notification will be issued.
XThis command could also be used to notify other management systems,
Xsuch as progress and defect tracking,
Xin addition to notifying users.
X.LP
XThe
X.I integrate_fail_notify_command
Xfield is a string containing the command to
Xnotify that the integration has failed.
XAll of the substitutions described in
X.I aesub (5)
Xare available.
XThis field is optional, if it is not specified no notification will be issued.
XThis command could also be used to notify other management systems,
Xsuch as progress and defect tracking,
Xin addition to notifying users.
X.nh 3 "Notification by email"
X.LP
XThe aegis command is distributed with a set of shell scripts to
Xperform these notifications by email.
XThey are installed into the
X.I /usr/local/lib/aegis
Xdirectory.
XThe entries in the project attribute file look like this:
X.E(
Xdevelop_end_notify_command =
X "sh /usr/local/lib/aegis/de.sh $project $change \e
X $developer";
Xdevelop_end_undo_notify_command =
X "sh /usr/local/lib/aegis/deu.sh $project $change \e
X $developer";
Xreview_pass_notify_command =
X "sh /usr/local/lib/aegis/rp.sh $project $change \e
X $developer $reviewer";
Xreview_pass_undo_notify_command =
X "sh /usr/local/lib/aegis/rpu.sh $project $change \e
X $developer $reviewer";
Xreview_fail_notify_command =
X "sh /usr/local/lib/aegis/rf.sh $project $change \e
X $developer $reviewer";
Xintegrate_pass_notify_command =
X "sh /usr/local/lib/aegis/ip.sh $project $change \e
X $developer $reviewer $integrator";
Xintegrate_fail_notify_command =
X "sh /usr/local/lib/aegis/if.sh $project $change \e
X $developer $reviewer $integrator";
X.E)
X.nh 3 "Notification by USENET"
X.LP
XThe aegis command is distributed with a set of shell scripts to
Xperform these notifications by USENET.
XThey are installed into the
X.I /usr/local/lib/aegis
Xdirectory.
XThe entries in the project attribute file look like this:
X.E(
Xdevelop_end_notify_command =
X "sh /usr/local/lib/aegis/de.inews.sh $p $c alt.$p";
Xdevelop_end_undo_notify_command =
X "sh /usr/local/lib/aegis/deu.inews.sh $p $c alt.$p";
Xreview_pass_notify_command =
X "sh /usr/local/lib/aegis/rp.inews.sh $p $c alt.$p";
Xreview_pass_undo_notify_command =
X "sh /usr/local/lib/aegis/rpu.inews.sh $p $c alt.$p";
Xreview_fail_notify_command =
X "sh /usr/local/lib/aegis/rf.inews.sh $p $c alt.$p";
Xintegrate_pass_notify_command =
X "sh /usr/local/lib/aegis/ip.inews.sh $p $c alt.$p";
Xintegrate_fail_notify_command =
X "sh /usr/local/lib/aegis/if.inews.sh $p $c alt.$p";
X.E)
X.LP
XThe last argument to each command is the newsgroup to post the article in,
Xyou may want to use some other group.
XNote that "$p" is an abbreviation for "$project"
Xand "$c" is an abbreviation for "$change".
X.nh 2 "Exemption Controls"
X.LP
XThe
X.I developer_may_review
Xfield is a boolean.
XIf this field is true,
Xthen a developer may review her own change.
XThis is probably only a good idea for projects of less than 3 people.
XThe idea is for as many people as possible to critically examine a change.
X.LP
XThe
X.I developer_may_integrate
Xfield is a boolean.
XIf this field is true,
Xthen a developer may integrate her own change.
XThis is probably only a good idea for projects of less than 3 people.
XThe idea is for as many people as possible to critically examine a change.
X.LP
XThe
X.I reviewer_may_integrate
Xfield is a boolean.
XIf this field is true,
Xthen a reviewer may integrate a change she reviewed.
XThis is probably only a good idea for projects of less than 3 people.
XThe idea is for as many people as possible to critically examine a change.
X.LP
XThe
X.I developers_may_create_changes
Xfield is a boolean.
XThis field is true if developers may created changes,
Xin addition to administrators.
XThis tends to be a very useful thing,
Xsince developers find most of the bugs.
X.LP
XThe
X.I default_test_exemption
Xfield is a boolean.
XThis field contains what to do when a change is created with
Xno test exemption specified.
XThe default is "false", i.e. no testing exemption,
Xtests must be provided.
X.LP
XThis kind of blanket exemption should only be set when
Xa project has absolutely no functionality available from the command line;
Xexamples include X11 programs.
XThe program could possibly be improved by providing access to
Xthe functionality from the command line,
Xthus allowing tests to be written.
X.nh 3 "One Person Projects"
X.LP
XThe entries in the project attributes file for a
Xone person project look like this:
X.E(
Xdeveloper_may_review = true;
Xdeveloper_may_integrate = true;
Xreviewer_may_integrate = true;
Xdevelopers_may_create_changes = true;
X.E)
X.LP
XAll of the staff roles
X(administrator, developer, reviewer and integrator)
Xare all set to be the same user.
X.nh 3 "Two Person Projects"
X.LP
XA two person project has the opportunity for each to review the other's work.
X.LP
XThe entries in the project attributes file for a
Xone person project look like this:
X.E(
Xdeveloper_may_review = false.
Xdeveloper_may_integrate = true;
Xreviewer_may_integrate = true;
Xdevelopers_may_create_changes = true;
X.E)
X.LP
XAll of the staff roles
X(developer, reviewer and integrator)
Xare all set to allow both users.
X.nh 3 "Larger Projects"
X.LP
XOnce you have 3 or more staff on a project,
Xyou can assign all of the roles to separate people.
XThe idea is for the greatest number of eyes to see each change
Xand detect flaws before they reach the baseline.
X.LP
XThe entries in the project attributes file for a
Xone person project look like this:
X.E(
Xdeveloper_may_review = false.
Xdeveloper_may_integrate = false;
Xreviewer_may_integrate = false;
Xdevelopers_may_create_changes = true;
X.E)
X.LP
XFor smaller teams,
Xeveryone may be a developer.
XAs the teams get larger,
Xthe more experienced staff are often the reviewers,
Xrather than everyone.
END_OF_FILE
if test 10142 -ne `wc -c <'doc/c5.0.so'`; then
echo shar: \"'doc/c5.0.so'\" unpacked with wrong size!
fi
# end of 'doc/c5.0.so'
fi
if test -f 'fmtgen/id.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'fmtgen/id.c'\"
else
echo shar: Extracting \"'fmtgen/id.c'\" \(9297 characters\)
sed "s/^X//" >'fmtgen/id.c' <<'END_OF_FILE'
X/*
X * aegis - project change supervisor
X * Copyright (C) 1991, 1992, 1993 Peter Miller.
X * All rights reserved.
X *
X * This program is free software; you can redistribute it and/or modify
X * it under the terms of the GNU General Public License as published by
X * the Free Software Foundation; either version 2 of the License, or
X * (at your option) any later version.
X *
X * This program is distributed in the hope that it will be useful,
X * but WITHOUT ANY WARRANTY; without even the implied warranty of
X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X * GNU General Public License for more details.
X *
X * You should have received a copy of the GNU General Public License
X * along with this program; if not, write to the Free Software
X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X *
X * MANIFEST: symbol table manipulation
X */
X
X#include <stddef.h>
X#include <stdlib.h>
X#include <string.h>
X
X#include <main.h>
X#include <id.h>
X#include <word.h>
X#include <mem.h>
X#include <error.h>
X
X
X#define HEADER \
X string_ty *id_name; \
X str_hash_ty id_hash; \
X id *id_next; \
X id_class_ty id_class;
X
Xtypedef struct id id;
Xstruct id
X{
X HEADER
X};
X
Xtypedef struct id_int id_int;
Xstruct id_int
X{
X HEADER
X int id_value;
X};
X
Xtypedef struct id_void id_void;
Xstruct id_void
X{
X HEADER
X void *id_value;
X};
X
Xstatic id **hash_table;
Xstatic str_hash_ty hash_modulus;
Xstatic str_hash_ty hash_cutover;
Xstatic str_hash_ty hash_cutover_mask;
Xstatic str_hash_ty hash_cutover_split_mask;
Xstatic str_hash_ty hash_split;
Xstatic str_hash_ty hash_load;
X
X
X/*
X * NAME
X * id_initialize - start up symbol table
X *
X * SYNOPSIS
X * void id_initialize(void);
X *
X * DESCRIPTION
X * The id_initialize function is used to create the hash table.
X *
X * CAVEAT
X * Assumes the str_initialize function has been called already.
X */
X
Xvoid
Xid_initialize()
X{
X str_hash_ty j;
X
X hash_modulus = 1<<8; /* MUST be a power of 2 */
X hash_cutover = hash_modulus;
X hash_split = hash_modulus - hash_cutover;
X hash_cutover_mask = hash_cutover - 1;
X hash_cutover_split_mask = (hash_cutover * 2) - 1;
X hash_load = 0;
X hash_table = (id **)mem_alloc(hash_modulus * sizeof(id *));
X for (j = 0; j < hash_modulus; ++j)
X hash_table[j] = 0;
X}
X
X
X/*
X * NAME
X * split - reduce symbol table load
X *
X * SYNOPSIS
X * void split(void);
X *
X * DESCRIPTION
X * The split function is used to split symbols in the bucket indicated by
X * the split point. The symbols are split between that bucket and the one
X * after the current end of the table.
X *
X * CAVEAT
X * It is only sensable to do this when the symbol table load exceeds some
X * reasonable threshold. A threshold of 80% is suggested.
X */
X
Xstatic void split _((void));
X
Xstatic void
Xsplit()
X{
X id *p;
X id **ipp;
X id *p2;
X str_hash_ty index;
X
X /*
X * get the list to be split across buckets
X */
X p = hash_table[hash_split];
X hash_table[hash_split] = 0;
X
X /*
X * increase the modulus by one
X */
X hash_modulus++;
X mem_change_size((char **)&hash_table, hash_modulus * sizeof(id *));
X hash_table[hash_modulus - 1] = 0;
X hash_split = hash_modulus - hash_cutover;
X if (hash_split >= hash_cutover)
X {
X hash_cutover = hash_modulus;
X hash_split = 0;
X hash_cutover_mask = hash_cutover - 1;
X hash_cutover_split_mask = (hash_cutover * 2) - 1;
X }
X
X /*
X * now redistribute the list elements
X *
X * It is important to preserve the order of the links because
X * they can be push-down stacks, and to simply add them to the
X * head of the list will reverse the order of the stack!
X */
X while (p)
X {
X p2 = p;
X p = p2->id_next;
X p2->id_next = 0;
X
X index = p2->id_hash & hash_cutover_mask;
X if (index < hash_split)
X index = p2->id_hash & hash_cutover_split_mask;
X for (ipp = &hash_table[index]; *ipp; ipp = &(*ipp)->id_next)
X ;
X *ipp = p2;
X }
X}
X
X
X/*
X * NAME
X * copy - copy a symbol value
X *
X * SYNOPSIS
X * void copy(id *p, long *valuep);
X *
X * DESCRIPTION
X * The copy function is used to copy the passed value of a symbol into the
X * storage of that symbol.
X */
X
Xstatic void copy _((id *, long *));
X
Xstatic void
Xcopy(p, valuep)
X id *p;
X long *valuep;
X{
X switch (p->id_class)
X {
X case ID_CLASS_KEYWORD:
X {
X id_int *ip;
X
X ip = (id_int *)p;
X *valuep = ip->id_value;
X }
X break;
X
X case ID_CLASS_ENUMEL:
X case ID_CLASS_FIELD:
X case ID_CLASS_TYPE:
X {
X id_void *ip;
X
X ip = (id_void *)p;
X *(void **)valuep = ip->id_value;
X }
X break;
X }
X}
X
X
X/*
X * NAME
X * id_search - search for a variable
X *
X * SYNOPSIS
X * int id_search(string_ty *name, id_class_ty class, long *value);
X *
X * DESCRIPTION
X * Id_search is used to reference a variable.
X *
X * RETURNS
X * If the variable has been defined, the function returns a non-zero value
X * and the value is returned through the 'value' pointer.
X * If the variable has not been defined, it returns zero,
X * and 'value' is unaltered.
X *
X * CAVEAT
X * The value returned from this function, when returned, is allocated
X * in dynamic memory (it is a copy of the value remembered by this module).
X * It is the responsibility of the caller to free it when finished with,
X * by a wl_free() call.
X */
X
X/*VARARGS2*/
Xint
Xid_search(name, class, valuep)
X string_ty *name;
X id_class_ty class;
X long *valuep;
X{
X str_hash_ty myhash;
X str_hash_ty index;
X id *p;
X
X myhash = name->str_hash + (int)class;
X index = myhash & hash_cutover_mask;
X if (index < hash_split)
X index = myhash & hash_cutover_split_mask;
X for (p = hash_table[index]; p; p = p->id_next)
X {
X if (p->id_class == class && str_equal(name, p->id_name))
X {
X copy(p, valuep);
X return 1;
X }
X }
X return 0;
X}
X
X
X/*
X * NAME
X * assign - set value of symbol
X *
X * SYNOPSIS
X * void assign(id *p, long value);
X *
X * DESCRIPTION
X * The assign function is used to change the value of a symbol.
X *
X * CAVEAT
X * The value is not released first, so use stomp if necessary.
X */
X
Xstatic void assign _((id *, long));
X
Xstatic void
Xassign(p, value)
X id *p;
X long value;
X{
X switch (p->id_class)
X {
X case ID_CLASS_KEYWORD:
X {
X id_int *ip;
X
X ip = (id_int *)p;
X ip->id_value = value;
X }
X break;
X
X case ID_CLASS_TYPE:
X case ID_CLASS_FIELD:
X case ID_CLASS_ENUMEL:
X {
X id_void *ip;
X
X ip = (id_void *)p;
X ip->id_value = (void *)value;
X }
X break;
X }
X}
X
X
X/*
X * NAME
X * size_by_class - determine symbol size
X *
X * SYNOPSIS
X * size_t size_by_class(id_class_ty class);
X *
X * DESCRIPTION
X * The size_by_class function is used to determine the correct size to
X * allocate for symbol storage.
X *
X * RETURNS
X * size_t: the correct size to malloc.
X *
X * CAVEAT
X * Never malloc(sizeof(id)) as this will be too small.
X */
X
Xstatic size_t size_by_class _((id_class_ty));
X
Xstatic size_t
Xsize_by_class(class)
X id_class_ty class;
X{
X switch ((int)class)
X {
X default:
X assert(0);
X
X case ID_CLASS_KEYWORD:
X return sizeof(id_int);
X
X case ID_CLASS_TYPE:
X case ID_CLASS_FIELD:
X case ID_CLASS_ENUMEL:
X return sizeof(id_void);
X }
X}
X
X
X/*
X * NAME
X * id_assign - assign a variable
X *
X * SYNOPSIS
X * void id_assign(string_ty *name, id_class_ty class, long value);
X *
X * DESCRIPTION
X * Id_assign is used to assign a value to a given variable.
X *
X * CAVEAT
X * The name and value are copied by id_assign, so the user may
X * modify or free them at a later date without affecting the
X * variable.
X */
X
X/*VARARGS2*/
Xvoid
Xid_assign(name, class, value)
X string_ty *name;
X id_class_ty class;
X long value;
X{
X str_hash_ty myhash;
X str_hash_ty index;
X id *p;
X
X myhash = name->str_hash + (int)class;
X index = myhash & hash_cutover_mask;
X if (index < hash_split)
X index = myhash & hash_cutover_split_mask;
X
X for (p = hash_table[index]; p; p = p->id_next)
X {
X if (p->id_class == class && str_equal(name, p->id_name))
X {
X assign(p, value);
X return;
X }
X }
X
X p = (id *)mem_alloc_clear(size_by_class(class));
X p->id_name = str_copy(name);
X p->id_next = hash_table[index];
X p->id_class = class;
X p->id_hash = myhash;
X hash_table[index] = p;
X assign(p, value);
X
X hash_load++;
X while (hash_load * 10 >= hash_modulus * 8)
X split();
X}
X
X
X/*
X * NAME
X * id_dump - dump id table
X *
X * SYNOPSIS
X * void id_dump(char *title, int mask);
X *
X * DESCRIPTION
X * The id_dump function is used to dump the contents of the id table.
X * The title will be used to indicate why the table was dumped. The mask
X * may be used to selectively dump the table, 0 means everything, bits
X * correspond directly with ID_CLASS defines.
X *
X * CAVEAT
X * This function is only available when symbol DEBUG is defined.
X */
X
X#ifdef DEBUG
X
Xvoid
Xid_dump(s, mask)
X char *s;
X int mask;
X{
X int j;
X id *p;
X
X if (!mask)
X mask = ~0;
X error("id table %s = {"/*}*/, s);
X for (j = 0; j < hash_modulus; ++j)
X {
X for (p = hash_table[j]; p; p = p->id_next)
X {
X if (mask & (1<< (int)p->id_class))
X switch ((int)p->id_class)
X {
X default:
X error
X (
X "name = \"%s\", class = %d",
X p->id_name->str_text,
X p->id_class
X );
X break;
X
X case ID_CLASS_KEYWORD:
X {
X id_int *ip;
X
X ip = (id_int*)p;
X error
X (
X "name = \"%s\", class = %d, value = %d",
X p->id_name->str_text,
X p->id_class,
X ip->id_value
X );
X }
X break;
X
X case ID_CLASS_TYPE:
X case ID_CLASS_FIELD:
X {
X id_void *ip;
X
X ip = (id_void *)p;
X error
X (
X "name = \"%s\", class = %d, value = %08X",
X p->id_name->str_text,
X p->id_class,
X ip->id_value
X );
X }
X break;
X }
X }
X }
X error(/*{*/"}");
X}
X
X#endif
END_OF_FILE
if test 9297 -ne `wc -c <'fmtgen/id.c'`; then
echo shar: \"'fmtgen/id.c'\" unpacked with wrong size!
fi
# end of 'fmtgen/id.c'
fi
if test -f 'fmtgen/lex.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'fmtgen/lex.c'\"
else
echo shar: Extracting \"'fmtgen/lex.c'\" \(9885 characters\)
sed "s/^X//" >'fmtgen/lex.c' <<'END_OF_FILE'
X/*
X * aegis - project change supervisor
X * Copyright (C) 1991, 1992, 1993 Peter Miller.
X * All rights reserved.
X *
X * This program is free software; you can redistribute it and/or modify
X * it under the terms of the GNU General Public License as published by
X * the Free Software Foundation; either version 2 of the License, or
X * (at your option) any later version.
X *
X * This program is distributed in the hope that it will be useful,
X * but WITHOUT ANY WARRANTY; without even the implied warranty of
X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X * GNU General Public License for more details.
X *
X * You should have received a copy of the GNU General Public License
X * along with this program; if not, write to the Free Software
X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X *
X * MANIFEST: lexical analyzer
X */
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X#include <errno.h>
X
X#include <error.h>
X#include <id.h>
X#include <lex.h>
X#include <mem.h>
X#include <s-v-arg.h>
X#include <str.h>
X#include <type.h>
X#include <parse.gen.h> /* must be last */
X
X
X#define strel(a, op, b) (strcmp(a, b) op 0)
X
Xtypedef struct file_ty file_ty;
Xstruct file_ty
X{
X FILE *fp;
X int line_number;
X char *file_name;
X file_ty *next;
X};
X
Xstatic file_ty *file;
Xstatic int error_count;
Xextern parse_STYPE parse_lval;
Xstatic wlist ifiles;
Xstatic wlist include_path;
X
X
X/*
X * NAME
X * lex_initialize - look for keywords
X *
X * SYNOPSIS
X * int lex_initialize(void);
X *
X * DESCRIPTION
X * The lex_initialize function adds all the keywords to the symbol table.
X *
X * CAVEAT
X * The keywords are intentionally case sensitive.
X * Assumes that str_initialize has already been called.
X */
X
Xstatic void lex_initialize _((void));
X
Xstatic void
Xlex_initialize()
X{
X typedef struct keyword_ty keyword_ty;
X struct keyword_ty
X {
X char *k_name;
X int k_token;
X };
X
X static keyword_ty keyword[] =
X {
X { "type", TYPE, },
X { "string", STRING, },
X { "integer", INTEGER, },
X { "include", INCLUDE, },
X };
X keyword_ty *kp;
X static int done;
X
X if (done)
X return;
X done = 1;
X for (kp = keyword; kp < ENDOF(keyword); ++kp)
X {
X string_ty *s;
X
X s = str_from_c(kp->k_name);
X id_assign(s, ID_CLASS_KEYWORD, kp->k_token);
X str_free(s);
X }
X}
X
X
Xvoid
Xlex_open(s)
X char *s;
X{
X file_ty *f;
X
X f = (file_ty *)mem_alloc_clear(sizeof(file_ty));
X if (!file)
X {
X lex_initialize();
X f->file_name = mem_copy_string(s);
X f->fp = fopen(s, "r");
X if (!f->fp)
X nfatal("%s", s);
X }
X else
X {
X int j;
X
X f->fp = 0;
X for (j = 0; j < include_path.wl_nwords; ++j)
X {
X char buffer[2000];
X
X sprintf(buffer, "%s/%s", include_path.wl_word[j]->str_text, s);
X f->fp = fopen(buffer, "r");
X if (f->fp)
X {
X f->file_name = mem_copy_string(buffer);
X break;
X }
X if (errno != ENOENT)
X nfatal("%s", buffer);
X }
X if (!f->fp)
X {
X f->fp = fopen(s, "r");
X if (!f->fp)
X nfatal("%s", s);
X f->file_name = mem_copy_string(s);
X }
X f->next = file;
X wl_append_unique(&ifiles, str_from_c(s));
X }
X f->line_number = 1;
X file = f;
X}
X
X
Xvoid
Xlex_close()
X{
X if (error_count)
X exit(1);
X fclose(file->fp);
X free(file->file_name);
X free(file);
X}
X
X
Xstatic int lex_getc _((void));
X
Xstatic int
Xlex_getc()
X{
X int c;
X
X for (;;)
X {
X file_ty *old;
X
X c = fgetc(file->fp);
X if (c != EOF)
X break;
X if (ferror(file->fp))
X nfatal("%s", file->file_name);
X if (!file->next)
X break;
X old = file;
X file = old->next;
X fclose(old->fp);
X free(old->file_name);
X free(old);
X }
X if (c == '\n')
X file->line_number++;
X return c;
X}
X
X
Xstatic void lex_getc_undo _((int));
X
Xstatic void
Xlex_getc_undo(c)
X int c;
X{
X switch (c)
X {
X case EOF:
X break;
X
X case '\n':
X file->line_number--;
X /* fall through... */
X
X default:
X ungetc(c, file->fp);
X break;
X }
X}
X
X
Xint
Xparse_lex()
X{
X int line_number_start;
X char buffer[1<<12];
X char *cp;
X
X for (;;)
X {
X int c;
X
X c = lex_getc();
X switch (c)
X {
X case ' ':
X case '\t':
X case '\f':
X case '\n':
X break;
X
X case '0':
X case '1':
X case '2':
X case '3':
X case '4':
X case '5':
X case '6':
X case '7':
X case '8':
X case '9':
X parse_lval.lv_integer = 0;
X for (;;)
X {
X parse_lval.lv_integer = 10 * parse_lval.lv_integer + c - '0';
X c = lex_getc();
X if (c < '0' || c > '9')
X {
X lex_getc_undo(c);
X break;
X }
X }
X return INTEGER_CONSTANT;
X
X case 'A': case 'B': case 'C': case 'D': case 'E':
X case 'F': case 'G': case 'H': case 'I': case 'J':
X case 'K': case 'L': case 'M': case 'N': case 'O':
X case 'P': case 'Q': case 'R': case 'S': case 'T':
X case 'U': case 'V': case 'W': case 'X': case 'Y':
X case 'Z': case '_': case 'a': case 'b': case 'c':
X case 'd': case 'e': case 'f': case 'g': case 'h':
X case 'i': case 'j': case 'k': case 'l': case 'm':
X case 'n': case 'o': case 'p': case 'q': case 'r':
X case 's': case 't': case 'u': case 'v': case 'w':
X case 'x': case 'y': case 'z':
X {
X char *cp;
X char buffer[1000];
X string_ty *s;
X long tok;
X
X cp = buffer;
X for (;;)
X {
X *cp++ = c;
X c = lex_getc();
X switch (c)
X {
X case '0': case '1': case '2': case '3':
X case '4': case '5': case '6': case '7':
X case '8': case '9':
X case 'A': case 'B': case 'C': case 'D':
X case 'E': case 'F': case 'G': case 'H':
X case 'I': case 'J': case 'K': case 'L':
X case 'M': case 'N': case 'O': case 'P':
X case 'Q': case 'R': case 'S': case 'T':
X case 'U': case 'V': case 'W': case 'X':
X case 'Y': case 'Z': case '_': case 'a':
X case 'b': case 'c': case 'd': case 'e':
X case 'f': case 'g': case 'h': case 'i':
X case 'j': case 'k': case 'l': case 'm':
X case 'n': case 'o': case 'p': case 'q':
X case 'r': case 's': case 't': case 'u':
X case 'v': case 'w': case 'x': case 'y':
X case 'z':
X continue;
X }
X lex_getc_undo(c);
X *cp = 0;
X break;
X }
X s = str_from_c(buffer);
X if (id_search(s, ID_CLASS_KEYWORD, &tok))
X {
X str_free(s);
X return tok;
X }
X parse_lval.lv_string = s;
X return NAME;
X }
X
X case '/':
X c = lex_getc();
X if (c != '*')
X {
X lex_getc_undo(c);
X return '/';
X }
X for (;;)
X {
X for (;;)
X {
X c = lex_getc();
X if (c == EOF)
X {
X bad_comment:
X parse_error("end-of-file inside comment");
X exit(1);
X }
X if (c == '*')
X break;
X }
X for (;;)
X {
X c = lex_getc();
X if (c == EOF)
X goto bad_comment;
X if (c != '*')
X break;
X }
X if (c == '/')
X break;
X }
X break;
X
X case '<':
X line_number_start = file->line_number;
X cp = buffer;
X for (;;)
X {
X c = lex_getc();
X if (c == EOF)
X goto str_eof;
X if (c == '\n')
X goto str_eoln;
X if (c == '>')
X break;
X *cp++ = c;
X }
X *cp = 0;
X parse_lval.lv_string = str_from_c(buffer);
X return STRING_CONSTANT;
X
X case '"':
X line_number_start = file->line_number;
X cp = buffer;
X for (;;)
X {
X c = lex_getc();
X if (c == EOF)
X {
X str_eof:
X file->line_number = line_number_start;
X parse_error("end-of-file within string");
X break;
X }
X if (c == '\n')
X {
X str_eoln:
X file->line_number = line_number_start;
X parse_error("end-of-line within string");
X break;
X }
X if (c == '"')
X break;
X if (c == '\\')
X {
X c = lex_getc();
X switch (c)
X {
X default:
X parse_error("unknown '\\%c' escape", c);
X break;
X
X case '\n':
X break;
X
X case EOF:
X goto str_eof;
X
X case 'b':
X *cp++ = '\b';
X break;
X
X case 'n':
X *cp++ = '\n';
X break;
X
X case 'r':
X *cp++ = '\r';
X break;
X
X case 't':
X *cp++ = '\t';
X break;
X
X case 'f':
X *cp++ = '\f';
X break;
X
X case '"':
X case '\\':
X *cp++ = c;
X break;
X
X case '0':
X case '1':
X case '2':
X case '3':
X case '4':
X case '5':
X case '6':
X case '7':
X {
X int n;
X int v;
X
X v = 0;
X for (n = 0; n < 3; ++n)
X {
X v = v * 8 + c - '0';
X c = lex_getc();
X switch (c)
X {
X case '0':
X case '1':
X case '2':
X case '3':
X case '4':
X case '5':
X case '6':
X case '7':
X continue;
X
X default:
X lex_getc_undo(c);
X break;
X }
X break;
X }
X *cp++ = v;
X }
X break;
X }
X }
X else
X *cp++ = c;
X }
X *cp = 0;
X parse_lval.lv_string = str_from_c(buffer);
X return STRING_CONSTANT;
X
X default:
X return c;
X }
X }
X}
X
X
Xvoid
Xparse_error(s sva_last)
X char *s;
X sva_last_decl
X{
X va_list ap;
X char buffer[1000];
X
X sva_init(ap, s);
X vsprintf(buffer, s, ap);
X va_end(ap);
X error("%s: %d: %s", file->file_name, file->line_number, buffer);
X if (++error_count >= 20)
X error("%s: too many errors, bye!", file->file_name);
X}
X
X
Xint
Xlex_in_include_file()
X{
X return !!file->next;
X}
X
X
Xvoid
Xlex_include_path(s)
X char *s;
X{
X wl_append_unique(&include_path, str_from_c(s));
X}
END_OF_FILE
if test 9885 -ne `wc -c <'fmtgen/lex.c'`; then
echo shar: \"'fmtgen/lex.c'\" unpacked with wrong size!
fi
# end of 'fmtgen/lex.c'
fi
if test -f 'fmtgen/parse.y' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'fmtgen/parse.y'\"
else
echo shar: Extracting \"'fmtgen/parse.y'\" \(9538 characters\)
sed "s/^X//" >'fmtgen/parse.y' <<'END_OF_FILE'
X/*
X * aegis - project change supervisor
X * Copyright (C) 1991, 1992, 1993 Peter Miller.
X * All rights reserved.
X *
X * This program is free software; you can redistribute it and/or modify
X * it under the terms of the GNU General Public License as published by
X * the Free Software Foundation; either version 2 of the License, or
X * (at your option) any later version.
X *
X * This program is distributed in the hope that it will be useful,
X * but WITHOUT ANY WARRANTY; without even the implied warranty of
X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X * GNU General Public License for more details.
X *
X * You should have received a copy of the GNU General Public License
X * along with this program; if not, write to the Free Software
X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X *
X * MANIFEST: grammar and functions to parse aegis file contents definitions
X */
X
X%{
X
X#include <ctype.h>
X#include <string.h>
X#include <stdlib.h>
X
X#include <error.h>
X#include <id.h>
X#include <indent.h>
X#include <lex.h>
X#include <mem.h>
X#include <parse.h>
X#include <str.h>
X#include <trace.h>
X#include <type.h>
X
X#ifdef DEBUG
X#define YYDEBUG 1
Xextern int yydebug;
X#define printf trace_where, trace_printf
X#endif
X
X%}
X
X%token TYPE
X%token NAME
X%token STRING
X%token STRING_CONSTANT
X%token INTEGER
X%token INTEGER_CONSTANT
X%token INCLUDE
X
X%union
X{
X string_ty *lv_string;
X long lv_integer;
X parse_list_ty *lv_parse_list;
X type_ty *lv_type;
X}
X
X%type <lv_string> NAME
X%type <lv_integer> INTEGER_CONSTANT
X%type <lv_parse_list> field_list enum_list
X%type <lv_type> type structure list enumeration
X%type <lv_string> type_name field field_name enum_name STRING_CONSTANT
X
X%{
X
Xtypedef struct name_ty name_ty;
Xstruct name_ty
X{
X string_ty *name;
X name_ty *prev;
X};
X
Xstatic parse_list_ty *type_root;
Xstatic name_ty *name_root;
X
X
Xstatic void pl_append _((parse_list_ty **, string_ty *));
X
Xstatic void
Xpl_append(listp, s)
X parse_list_ty **listp;
X string_ty *s;
X{
X parse_list_ty *plp;
X
X trace(("pl_append(listp = %08lX, s = \"%s\")\n{\n"/*}*/, listp, s->str_text));
X while (*listp)
X listp = &(*listp)->next;
X plp = (parse_list_ty *)mem_alloc(sizeof(parse_list_ty));
X plp->name = str_copy(s);
X plp->next = 0;
X *listp = plp;
X trace((/*{*/"}\n"));
X}
X
X
Xstatic void push_name _((string_ty *));
X
Xstatic void
Xpush_name(s)
X string_ty *s;
X{
X name_ty *np;
X
X trace(("push_name(s = \"%s\")\n{\n"/*}*/, s->str_text));
X assert(name_root);
X np = (name_ty *)mem_alloc(sizeof(name_ty));
X np->name = str_format("%S_%S", name_root->name, s);
X np->prev = name_root;
X name_root = np;
X trace((/*{*/"}\n"));
X}
X
X
Xstatic void push_name_abs _((string_ty *));
X
Xstatic void
Xpush_name_abs(s)
X string_ty *s;
X{
X name_ty *np;
X
X trace(("push_name_abs(s = \"%s\")\n{\n"/*}*/, s->str_text));
X np = (name_ty *)mem_alloc(sizeof(name_ty));
X np->name = str_copy(s);
X np->prev = name_root;
X name_root = np;
X trace((/*{*/"}\n"));
X}
X
X
Xstatic void pop_name _((void));
X
Xstatic void
Xpop_name()
X{
X name_ty *np;
X
X trace(("pop_name()\n{\n"/*}*/));
X np = name_root;
X name_root = np->prev;
X str_free(np->name);
X free(np);
X trace((/*{*/"}\n"));
X}
X
X
Xstatic string_ty *get_name _((void));
X
Xstatic string_ty *
Xget_name()
X{
X return str_copy(name_root->name);
X}
X
X
Xstatic void define_type _((string_ty *, type_ty *));
X
Xstatic void
Xdefine_type(name, type)
X string_ty *name;
X type_ty *type;
X{
X trace(("define_type(name = \"%s\")\n{\n"/*}*/, name->str_text));
X type->included_flag = lex_in_include_file();
X pl_append(&type_root, name);
X trace((/*{*/"}\n"));
X}
X
X
Xstatic char *basename _((char *));
X
Xstatic char *
Xbasename(s)
X char *s;
X{
X static char buffer[256];
X char *cp;
X
X cp = strrchr(s, '/');
X if (cp)
X ++cp;
X else
X cp = s;
X strcpy(buffer, cp);
X cp = strrchr(buffer, '.');
X if (cp)
X *cp = 0;
X for (cp = buffer; *cp; ++cp)
X {
X if (!isalnum(*cp))
X *cp = '_';
X }
X return buffer;
X}
X
X
Xvoid
Xparse(definition_file, code_file, include_file)
X char *definition_file;
X char *code_file;
X char *include_file;
X{
X string_ty *s;
X char *cp1;
X parse_list_ty *tnp;
X
X trace(("parse(def = \"%s\", c = \"%s\", h = \"%s\")\n{\n"/*}*/,
X definition_file, code_file, include_file));
X#ifdef DEBUG
X yydebug = trace_pretest_;
X#endif
X
X s = str_from_c(basename(definition_file));
X push_name_abs(s);
X
X lex_open(definition_file);
X trace(("yyparse()\n{\n"/*}*/));
X yyparse();
X trace((/*{*/"}\n"));
X lex_close();
X
X pop_name();
X
X indent_open(include_file);
X cp1 = basename(include_file);
X indent_putchar('\n');
X indent_printf("#ifndef %s_H\n", cp1);
X indent_printf("#define %s_H\n", cp1);
X indent_putchar('\n');
X indent_printf("#include <main.h>\n");
X indent_printf("#include <type.h>\n");
X indent_printf("#include <str.h>\n");
X indent_printf("#include <parse.h>\n");
X for (tnp = type_root; tnp; tnp = tnp->next)
X {
X type_ty *tp;
X
X if (!id_search(tnp->name, ID_CLASS_TYPE, (long *)&tp))
X fatal("type \"%s\" lost!", tnp->name->str_text);
X type_gen_include(tp, tnp->name);
X }
X indent_putchar('\n');
X indent_printf
X (
X "void %s_write_file _((char *filename, %s value));\n",
X s->str_text,
X s->str_text
X );
X indent_printf
X (
X "%s %s_read_file _((char *filename));\n",
X s->str_text,
X s->str_text
X );
X indent_putchar('\n');
X indent_printf("#endif /* %s_H */\n", cp1);
X indent_close();
X
X cp1 = strrchr(include_file, '/');
X if (cp1)
X cp1++;
X else
X cp1 = include_file;
X
X indent_open(code_file);
X indent_putchar('\n');
X indent_printf("#include <stddef.h>\n");
X indent_printf("#include <stdio.h>\n");
X indent_putchar('\n');
X indent_printf("#include <%s>\n", cp1);
X indent_printf("#include <error.h>\n");
X indent_printf("#include <indent.h>\n");
X indent_printf("#include <io.h>\n");
X indent_printf("#include <mem.h>\n");
X indent_printf("#include <os.h>\n");
X indent_printf("#include <trace.h>\n");
X indent_printf("#include <type.h>\n");
X cp1 = basename(code_file);
X for (tnp = type_root; tnp; tnp = tnp->next)
X {
X type_ty *tp;
X
X if (!id_search(tnp->name, ID_CLASS_TYPE, (long *)&tp))
X fatal("type \"%s\" lost!", tnp->name->str_text);
X if (tp->included_flag)
X continue;
X type_gen_code(tp, tnp->name);
X }
X indent_putchar('\n');
X indent_printf("%s\n", cp1);
X indent_printf("%s_read_file(filename)\n", s->str_text);
X indent_more();
X indent_printf("%s\1*filename;\n", "char");
X indent_less();
X indent_printf("{\n"/*}*/);
X indent_printf("%s\1result;\n\n", cp1);
X indent_printf("trace((\"%s_read_file(filename = \\\"%%s\\\")\\n{\\n\"/*}*/, filename));\n", cp1);
X indent_printf("os_become_must_be_active();\n");
X indent_printf
X (
X "result = (%s)parse(filename, &%s_type);\n",
X s->str_text,
X s->str_text
X );
X indent_printf("trace((\"return %%08lX;\\n\", result));\n");
X indent_printf("trace((/*{*/\"}\\n\"));\n");
X indent_printf("return result;\n");
X indent_printf(/*{*/"}\n");
X indent_putchar('\n');
X indent_printf("void\n");
X indent_printf("%s_write_file(filename, value)\n", s->str_text);
X indent_more();
X indent_printf("%s\1*filename;\n", "char");
X indent_printf("%s\1value;\n", s->str_text);
X indent_less();
X indent_printf("{\n"/*}*/);
X indent_printf("trace((\"%s_write_file(filename = \\\"%%s\\\", value = %%08lX)\\n{\\n\"/*}*/, filename, value));\n", cp1);
X indent_printf("if (filename)\n");
X indent_more();
X indent_printf("os_become_must_be_active();\n");
X indent_less();
X indent_printf("indent_open(filename);\n");
X indent_printf("%s_write(value);\n", s->str_text);
X indent_printf("indent_close();\n");
X indent_printf("trace((/*{*/\"}\\n\"));\n");
X indent_printf(/*{*/"}\n");
X indent_close();
X
X str_free(s);
X trace((/*{*/"}\n"));
X}
X
X%}
X
X%%
X
Xdescription
X : typedef_list field_list
X {
X string_ty *s;
X type_ty *type;
X
X s = get_name();
X type = type_create_struct(s, $2, 1);
X define_type(s, type);
X }
X ;
X
Xtypedef_list
X : /* empty */
X | typedef_list typedef
X ;
X
Xtypedef
X : TYPE type_name '=' type ';'
X {
X str_free($2);
X pop_name();
X }
X | '#' INCLUDE STRING_CONSTANT
X {
X lex_open($3->str_text);
X str_free($3);
X }
X ;
X
Xtype_name
X : NAME
X {
X $$ = $1;
X push_name_abs($1);
X }
X ;
X
Xfield
X : field_name '=' type ';'
X {
X id_assign($1, ID_CLASS_FIELD, (long)$3);
X $$ = $1;
X pop_name();
X }
X ;
X
Xfield_name
X : NAME
X {
X push_name($1);
X $$ = $1;
X }
X ;
X
Xtype
X : STRING
X {
X $$ = type_create_string();
X }
X | INTEGER
X {
X $$ = type_create_integer();
X }
X | NAME
X {
X type_ty *tp;
X
X if (id_search($1, ID_CLASS_TYPE, (long *)&tp))
X {
X /* $$ = type_create_ref(get_name(), $1); */
X $$ = tp;
X }
X else
X {
X yyerror("type \"%s\" undefined", $1->str_text);
X $$ = type_create_integer();
X }
X str_free($1);
X }
X | structure
X { $$ = $1; }
X | list
X { $$ = $1; }
X | enumeration
X { $$ = $1; }
X ;
X
Xstructure
X : '{' field_list '}'
X {
X string_ty *s;
X
X s = get_name();
X $$ = type_create_struct(s, $2, 0);
X define_type(s, $$);
X }
X ;
X
Xfield_list
X : /* empty */
X {
X $$ = 0;
X }
X | field_list field
X {
X $$ = $1;
X pl_append(&$$, $2);
X }
X ;
X
Xlist
X : '[' type ']'
X {
X string_ty *s;
X static string_ty *list;
X
X if (!list)
X list = str_from_c("list");
X push_name(list);
X s = get_name();
X $$ = type_create_list(s, $2);
X define_type(s, $$);
X pop_name();
X }
X ;
X
Xenumeration
X : '(' enum_list optional_comma ')'
X {
X string_ty *s;
X
X s = get_name();
X $$ = type_create_enum(s, $2);
X define_type(s, $$);
X }
X ;
X
Xoptional_comma
X : /* empty */
X | ','
X ;
X
Xenum_list
X : enum_name
X {
X $$ = 0;
X pl_append(&$$, $1);
X }
X | enum_list ',' enum_name
X {
X $$ = $1;
X pl_append(&$$, $3);
X }
X ;
X
Xenum_name
X : NAME
X {
X string_ty *s;
X
X push_name($1);
X s = get_name();
X pop_name();
X id_assign(s, ID_CLASS_ENUMEL, (long)$1);
X $$ = s;
X }
X ;
END_OF_FILE
if test 9538 -ne `wc -c <'fmtgen/parse.y'`; then
echo shar: \"'fmtgen/parse.y'\" unpacked with wrong size!
fi
# end of 'fmtgen/parse.y'
fi
if test -f 'test/00/t0006a.sh' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'test/00/t0006a.sh'\"
else
echo shar: Extracting \"'test/00/t0006a.sh'\" \(8528 characters\)
sed "s/^X//" >'test/00/t0006a.sh' <<'END_OF_FILE'
X#! /bin/sh
X#
X# aegis - project change supervisor
X# Copyright (C) 1991, 1992, 1993 Peter Miller.
X# All rights reserved.
X#
X# This program is free software; you can redistribute it and/or modify
X# it under the terms of the GNU General Public License as published by
X# the Free Software Foundation; either version 2 of the License, or
X# (at your option) any later version.
X#
X# This program is distributed in the hope that it will be useful,
X# but WITHOUT ANY WARRANTY; without even the implied warranty of
X# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X# GNU General Public License for more details.
X#
X# You should have received a copy of the GNU General Public License
X# along with this program; if not, write to the Free Software
X# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X#
X# MANIFEST: Test 'aegis -DIFFerence' when the edit number is out-of-date.
X#
X# The bug results in a string of length 0 being passed.
X#
X
Xunset AEGIS_PROJECT
Xunset AEGIS_CHANGE
Xumask 022
X
XUSER=${USER:-${LOGNAME:-`whoami`}}
X
XPAGER=cat
Xexport PAGER
Xwork=${AEGIS_TMP:-/tmp}/$$
X
Xfail()
X{
X set +x
X echo "FAILED test of 'aegis -DIFFerence' when the edit number is out-of-date" 1>&2
X find $work -type d -user $USER -exec chmod u+w {} \;
X rm -rf $work
X exit 1
X}
Xpass()
X{
X set +x
X echo PASSED 1>&2
X find $work -type d -user $USER -exec chmod u+w {} \;
X rm -rf $work
X exit 0
X}
Xtrap "fail" 1 2 3 15
X
X#
X# some variable to make things earier to read
X#
Xworklib=$work/lib
Xworkproj=$work/foo.proj
Xworkchan=$work/foo.chan
Xworkchan3=$work/foo.chan3
Xtmp=$work/tmp
X
X#
X# echo commands so we can tell what failed
X#
Xset -x
X
X#
X# make the directories
X#
Xmkdir $work
X
X#
X# make a new project
X# and check files it should have made
X#
X./bin/aegis -newpro foo -dir $workproj -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# change project attributes
X#
Xcat > $tmp << 'end'
Xdescription = "A bogus project created to test things.";
Xdeveloper_may_review = true;
Xdeveloper_may_integrate = true;
Xreviewer_may_integrate = true;
Xend
X./bin/aegis -proatt $tmp -proj foo -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# create a new change
X# make sure it creates the files it should
X#
Xcat > $tmp << 'end'
Xbrief_description = "This change is used to test the aegis functionality \
Xwith respect to change descriptions.";
Xcause = internal_bug;
Xend
X./bin/aegis -new_change $tmp -project foo -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# create a second change
X# make sure it creates the files it should
X#
Xcat > $tmp << 'end'
Xbrief_description = "This change was added to make the various listings \
Xmuch more interesting.";
Xcause = internal_bug;
Xend
X./bin/aegis -new_change $tmp -project foo -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# create a third change
X#
Xcat > $tmp << 'end'
Xbrief_description = "change three";
Xcause = internal_bug;
Xend
X./bin/aegis -new_change $tmp -project foo -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# add a new developer
X#
X./bin/aegis -newdev $USER -p foo -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# begin development of a change
X# check it made the files it should
X#
X./bin/aegis -devbeg 1 -p foo -dir $workchan -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# add a new files to the change
X#
X./bin/aegis -new_file $workchan/main.c -nl -v -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -new_file $workchan/config -nl -v -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xcat > $workchan/main.c << 'end'
Xvoid
Xmain()
X{
X exit(0);
X}
Xend
Xcat > $workchan/config << 'end'
Xbuild_command = "rm -f foo; cc -o foo -D'VERSION=\"$version\"' main.c";
Xlink_integration_directory = true;
X
Xhistory_get_command =
X "co -u'$e' -p $h,v > $o";
Xhistory_create_command =
X "ci -u -m/dev/null -t/dev/null $i $h,v; rcs -U $h,v";
Xhistory_put_command =
X "ci -u -m/dev/null -t/dev/null $i $h,v; rcs -U $h,v";
Xhistory_query_command =
X "rlog -r $h,v | awk '/^head:/ {print $$2}'";
X
Xdiff_command = "set +e; diff $orig $i > $out; test $$? -le 1";
X
Xdiff3_command = "(diff3 -e $mr $orig $i | sed -e '/^w$$/d' -e '/^q$$/d'; \
X echo '1,$$p' ) | ed - $mr > $out";
Xend
X
X#
X# create a new test
X#
X./bin/aegis -nt -l -v -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -nt -v -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xcat > $workchan/test/00/t0001a.sh << 'end'
X#!/bin/sh
X#
X# Project: "foo"
X# Change: 1
X#
X
Xfail()
X{
X echo SHUZBUTT 1>&2
X exit 1
X}
Xpass()
X{
X exit 0
X}
Xtrap "fail" 1 2 3 15
X
X./foo
Xq=$?
X
X# check for signals
Xif test $q -ge 128
Xthen
X fail
Xfi
X
X# should not complain
Xif test $q -ne 0
Xthen
X fail
Xfi
X
X# it probably worked
Xpass
Xend
X
X#
X# let the clock tick over, so the build will be happy
X#
Xsleep 1
X
X#
X# build the change
X#
X./bin/aegis -build -nl -v -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X
X#
X# difference the change
X#
X./bin/aegis -diff -nl -v -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X
X#
X# test the change
X#
X./bin/aegis -test -nl -v -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X
X#
X# finish development of the change
X#
X./bin/aegis -dev_end -v -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X
X#
X# add a new reviewer
X#
X./bin/aegis -newrev $USER -p foo -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# pass the review
X#
X./bin/aegis -review_pass -chan 1 -proj foo -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# add an integrator
X#
X./bin/aegis -newint $USER -p foo -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# start integrating
X#
X./bin/aegis -intbeg 1 -p foo -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# integrate build
X#
Xsleep 1
X./bin/aegis -build -nl -v -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -test -nl -v -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X
X#
X# pass the integration
X#
X./bin/aegis -intpass -nl -v -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X
X#
X# start work on change 2
X#
X./bin/aegis -devbeg 2 -p foo -v -dir $workchan -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# start work on change 3
X#
X./bin/aegis -devbeg 3 -p foo -v -dir $workchan3 -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# copy a file into change 2
X#
X./bin/aegis -cp $workchan/main.c -nl -v -lib $worklib -c 2 -p foo
Xif test $? -ne 0 ; then fail; fi
X
X#
X# copy a file into change 3
X#
X./bin/aegis -cp $workchan3/main.c -nl -v -lib $worklib -c 3 -p foo
Xif test $? -ne 0 ; then fail; fi
X
X#
X# change the file
X#
Xcat > $workchan/main.c << 'end'
X
X#include <stdio.h>
X
Xvoid
Xmain(argc, argv)
X int argc;
X char **argv;
X{
X if (argc != 1)
X {
X fprintf(stderr, "usage: %s\n", argv[0]);
X exit(1);
X }
X printf("hello, world\n");
X exit(0);
X}
Xend
X
X#
X# need another test
X#
X./bin/aegis -nt -v -lib $worklib -c 2 -p foo
Xif test $? -ne 0 ; then fail; fi
Xcat > $workchan/test/00/t0002a.sh << 'end'
X#!/bin/sh
X#
X# Project: "foo"
X# Change: 2
X#
X
Xfail()
X{
X echo SHUZBUTT 1>&2
X exit 1
X}
Xpass()
X{
X exit 0
X}
Xtrap "fail" 1 2 3 15
X
X./foo ickky
Xq=$?
X
X# check for signals
Xif test $q -ge 128
Xthen
X fail
Xfi
X
X# should have complained
Xif test $q -eq 0
Xthen
X fail
Xfi
X
X# it probably worked
Xpass
Xend
X
X#
X# tick over clock to keep build happy
X#
Xsleep 1
X
X#
X# build the change
X# diff the change
X# test the change
X#
X./bin/aegis -b -nl -v -lib $worklib -c 2 -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -diff -nl -v -lib $worklib -c 2 -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -test -nl -v -lib $worklib -c 2 -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -test -bl -nl -v -lib $worklib -c 2 -p foo
Xif test $? -ne 0 ; then fail; fi
X
X#
X# end development
X# review pass
X# start integrating
X#
X./bin/aegis -devend -v -lib $worklib -c 2 -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -revpass -v -c 2 -p foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -intbeg -v -c 2 -p foo -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# build the integration
X# test the integration
X# test the integration against the baseline
X#
Xsleep 1
X./bin/aegis -b -nl -v -lib $worklib -c 2 -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -t -nl -v -lib $worklib -c 2 -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -t -bl -nl -v -lib $worklib -c 2 -p foo
Xif test $? -ne 0 ; then fail; fi
X
X#
X# pass the integration
X# make sure it create the files, etc
X#
X./bin/aegis -intpass -nl -lib $worklib -c 2 -p foo
Xif test $? -ne 0 ; then fail; fi
X
X#
X# difference change 3
X#
X./bin/aegis -diff -nl -c 3 -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X
X# should be no automatic logging
Xif test "`find $work -name 'aegis.log' -print`" != "" ; then fail; fi
X
X#
X# the things tested in this test, worked
X#
Xpass
END_OF_FILE
if test 8528 -ne `wc -c <'test/00/t0006a.sh'`; then
echo shar: \"'test/00/t0006a.sh'\" unpacked with wrong size!
fi
# end of 'test/00/t0006a.sh'
fi
if test -f 'test/00/t0009a.sh' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'test/00/t0009a.sh'\"
else
echo shar: Extracting \"'test/00/t0009a.sh'\" \(8705 characters\)
sed "s/^X//" >'test/00/t0009a.sh' <<'END_OF_FILE'
X#! /bin/sh
X#
X# aegis - project change supervisor
X# Copyright (C) 1991, 1992, 1993 Peter Miller.
X# All rights reserved.
X#
X# This program is free software; you can redistribute it and/or modify
X# it under the terms of the GNU General Public License as published by
X# the Free Software Foundation; either version 2 of the License, or
X# (at your option) any later version.
X#
X# This program is distributed in the hope that it will be useful,
X# but WITHOUT ANY WARRANTY; without even the implied warranty of
X# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X# GNU General Public License for more details.
X#
X# You should have received a copy of the GNU General Public License
X# along with this program; if not, write to the Free Software
X# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X#
X# MANIFEST: Test -New_ReLeaSe functionality.
X#
X
Xunset AEGIS_PROJECT
Xunset AEGIS_CHANGE
Xumask 022
X
XUSER=${USER:-${LOGNAME:-`whoami`}}
X
XPAGER=cat
Xexport PAGER
Xwork=${AEGIS_TMP:-/tmp}/$$
X
Xfail()
X{
X set +x
X echo FAILED test of -New_ReLeaSe functionality 1>&2
X find $work -type d -user $USER -exec chmod u+w {} \;
X rm -rf $work
X exit 1
X}
Xpass()
X{
X set +x
X echo PASSED 1>&2
X find $work -type d -user $USER -exec chmod u+w {} \;
X rm -rf $work
X exit 0
X}
Xtrap "fail" 1 2 3 15
X
X#
X# some variable to make things earier to read
X#
Xworklib=$work/lib
Xworkproj=$work/foo.proj
Xworkproj2=$work/foo.proj2
Xworkchan=$work/foo.chan
Xtmp=$work/tmp
X
X#
X# echo commands so we can tell what failed
X#
Xset -x
X
X#
X# make the directories
X#
Xmkdir $work
X
X#
X# make a new project
X# and check files it should have made
X#
X./bin/aegis -newpro foo -dir $workproj -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# change project attributes
X#
Xcat > $tmp << 'end'
Xdescription = "A bogus project created to test things.";
Xdeveloper_may_review = true;
Xdeveloper_may_integrate = true;
Xreviewer_may_integrate = true;
Xend
X./bin/aegis -proatt $tmp -proj foo -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# create a new change
X#
Xcat > $tmp << 'end'
Xbrief_description = "This change is used to test the aegis functionality \
Xwith respect to change descriptions.";
Xcause = internal_bug;
Xend
X./bin/aegis -new_change $tmp -project foo -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# add a new developer
X#
X./bin/aegis -newdev $USER -p foo -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# begin development of a change
X#
X./bin/aegis -devbeg 1 -p foo -dir $workchan -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# add a new files to the change
X#
X./bin/aegis -new_file $workchan/main.c -nl -v -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -new_file $workchan/config -nl -v -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xcat > $workchan/main.c << 'end'
Xvoid
Xmain()
X{
X exit(0);
X}
Xend
Xif test $? -ne 0 ; then fail; fi
Xcat > $workchan/config << 'end'
Xbuild_command = "rm -f foo; cc -o foo -D'VERSION=\"$v\"' main.c";
Xlink_integration_directory = true;
X
Xhistory_get_command =
X "co -u'$e' -p $h,v > $o";
Xhistory_create_command =
X "ci -u -m/dev/null -t/dev/null $i $h,v; rcs -U $h,v";
Xhistory_put_command =
X "ci -u -m/dev/null -t/dev/null $i $h,v; rcs -U $h,v";
Xhistory_query_command =
X "rlog -r $h,v | awk '/^head:/ {print $$2}'";
X
Xdiff_command = "set +e; diff $orig $i > $out; test $$? -le 1";
X
Xdiff3_command = "(diff3 -e $mr $orig $i | sed -e '/^w$$/d' -e '/^q$$/d'; \
X echo '1,$$p' ) | ed - $mr > $out";
Xend
Xif test $? -ne 0 ; then fail; fi
X
X#
X# create a new test
X#
X./bin/aegis -nt -v -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
Xcat > $workchan/test/00/t0001a.sh << 'end'
X#!/bin/sh
X#
X# Project: "foo"
X# Change: 1
X#
X
Xfail()
X{
X echo SHUZBUTT 1>&2
X exit 1
X}
Xpass()
X{
X exit 0
X}
Xtrap "fail" 1 2 3 15
X
X./foo
Xq=$?
X
X# check for signals
Xif test $q -ge 128
Xthen
X fail
Xfi
X
X# should not complain
Xif test $q -ne 0
Xthen
X fail
Xfi
X
X# it probably worked
Xpass
Xend
Xif test $? -ne 0 ; then fail; fi
X
X#
X# let the clock tick over, so the build will be happy
X#
Xsleep 1
X
X#
X# build the change
X#
X./bin/aegis -build -nl -v -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X
X#
X# difference the change
X#
X./bin/aegis -diff -nl -v -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X
X#
X# test the change
X#
X./bin/aegis -test -nl -v -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X
X#
X# finish development of the change
X#
X./bin/aegis -dev_end -v -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X
X#
X# add a new reviewer
X#
X./bin/aegis -newrev $USER -p foo -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# pass the review
X#
X./bin/aegis -review_pass -chan 1 -proj foo -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# add an integrator
X#
X./bin/aegis -newint $USER -p foo -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# start integrating
X#
X./bin/aegis -intbeg 1 -p foo -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# integrate build
X#
Xsleep 1
X./bin/aegis -build -nl -v -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -test -nl -v -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X
X#
X# pass the integration
X#
X./bin/aegis -intpass -nl -v -lib $worklib -p foo
Xif test $? -ne 0 ; then fail; fi
X
X#
X# create the new release
X#
X./bin/aegis -nrls -l -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -nrls -v foo -dir $workproj2 -lib $worklib -nl
Xif test $? -ne 0 ; then fail; fi
Xls -lRA $workproj2
Xcat $workproj2/info/change/0/001
Xif test $? -ne 0 ; then fail; fi
Xcat $workproj2/info/state
Xif test $? -ne 0 ; then fail; fi
Xls -lgRA $worklib
X./bin/aegis -nrls -l -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# create a second change
X# make sure it creates the files it should
X#
Xcat > $tmp << 'end'
Xbrief_description = "Second change of second project";
Xcause = internal_enhancement;
Xend
X./bin/aegis -new_change $tmp -project foo.1.1 -v -lib $worklib
Xif test $? -ne 0 ; then fail; fi
Xcat $workproj2/info/change/0/002
Xif test $? -ne 0 ; then fail; fi
X
X#
X# start work on change 2 of foo.1.1
X#
X./bin/aegis -devbeg 2 -p foo.1.1 -v -dir $workchan -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# copy a file into the change
X#
X./bin/aegis -cp $workchan/main.c -v -nl -lib $worklib -p foo.1.1
Xif test $? -ne 0 ; then fail; fi
Xcat $workproj2/info/change/0/002
Xif test $? -ne 0 ; then fail; fi
Xcat $workproj2/info/state
Xif test $? -ne 0 ; then fail; fi
Xcat $worklib/user/$USER
Xif test $? -ne 0 ; then fail; fi
Xls -lRA $work
X
X#
X# change the file
X#
Xcat > $workchan/main.c << 'end'
X
X#include <stdio.h>
X
Xvoid
Xmain(argc, argv)
X int argc;
X char **argv;
X{
X if (argc != 1)
X {
X fprintf(stderr, "usage: %s\n", argv[0]);
X exit(1);
X }
X printf("hello, world\n");
X exit(0);
X}
Xend
X
X#
X# need another test
X#
X./bin/aegis -nt -v -lib $worklib -p foo.1.1
Xif test $? -ne 0 ; then fail; fi
Xcat > $workchan/test/00/t0002a.sh << 'end'
X#!/bin/sh
X#
X# Project: "foo.1.1"
X# Change: 2
X#
X
Xfail()
X{
X echo SHUZBUTT 1>&2
X exit 1
X}
Xpass()
X{
X exit 0
X}
Xtrap "fail" 1 2 3 15
X
X./foo ickky
Xif test $? -ne 1 ; then fail; fi
X
X# it probably worked
Xpass
Xend
X
X#
X# tick over clock to keep build happy
X#
Xsleep 1
X
X#
X# build the change
X# diff the change
X# test the change
X#
X./bin/aegis -b -nl -v -lib $worklib -p foo.1.1
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -diff -nl -v -lib $worklib -p foo.1.1
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -test -nl -v -lib $worklib -p foo.1.1
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -test -bl -nl -v -lib $worklib -p foo.1.1
Xif test $? -ne 0 ; then fail; fi
Xcat $workchan/main.c,D
Xif test $? -ne 0 ; then fail; fi
X
X
X#
X# end development
X# review pass
X# start integrating
X#
X./bin/aegis -devend -v -lib $worklib -p foo.1.1
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -revpass -v -c 2 -p foo.1.1 -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -intbeg -v -c 2 -p foo.1.1 -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X#
X# build the integration
X# test the integration
X# test the integration against the baseline
X#
Xsleep 1
X./bin/aegis -b -nl -v -lib $worklib -p foo.1.1
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -t -nl -v -lib $worklib -p foo.1.1
Xif test $? -ne 0 ; then fail; fi
X./bin/aegis -t -bl -nl -v -lib $worklib -p foo.1.1
Xif test $? -ne 0 ; then fail; fi
X
X#
X# pass the integration
X# make sure it create the files, etc
X#
X./bin/aegis -intpass -nl -lib $worklib -p foo.1.1
Xif test $? -ne 0 ; then fail; fi
Xcat $workproj2/info/change/0/002
Xif test $? -ne 0 ; then fail; fi
Xcat $workproj2/info/state
Xif test $? -ne 0 ; then fail; fi
Xcat $worklib/user/$USER
Xif test $? -ne 0 ; then fail; fi
Xls -lR $work
X./bin/aegis -l projhist -v -p foo.1.1 -lib $worklib
Xif test $? -ne 0 ; then fail; fi
X
X# should be no automatic logging
Xif test "`find $work -name 'aegis.log' -print`" != "" ; then fail; fi
X
X#
X# the things tested in this test, worked
X#
Xpass
END_OF_FILE
if test 8705 -ne `wc -c <'test/00/t0009a.sh'`; then
echo shar: \"'test/00/t0009a.sh'\" unpacked with wrong size!
fi
# end of 'test/00/t0009a.sh'
fi
echo shar: End of archive 7 \(of 19\).
cp /dev/null ark7isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 19 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0