home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OS9000
/
APPS
/
rcs.lzh
/
rcs1
/
srcin.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-04-22
|
22KB
|
809 lines
static char RCSid[]="$Header: srcin.c_v 1.11 96/04/23 01:59:03 hiro Exp $";
/************************************************************************
Copyright (c) 1993 ARK Systems USA
All rights reserved.
Program: srcin - "ci" check-in utility
File: srcin.c
$Date: 96/04/23 01:59:03 $
$Revision: 1.11 $
$Log: srcin.c_v $
* Revision 1.11 96/04/23 01:59:03 hiro
* Excluded inclusion of <stdlib.h> for OS-9.
*
* Revision 1.10 96/04/21 01:20:58 hiro
* Ported to OS-9000.
*
* Revision 1.9 96/04/07 00:29:24 hiro
* Ported to OS-9000.
*
* Revision 1.8 94/05/29 16:59:31 hiro
* Update
* ================================================================
* Added -r option for forced revision number.
* ================================================================
*
* Revision 1.7 93/12/09 01:59:48 hiro
* Prototype
* ================================================================
* Added automatic update of edition numbers.
* ================================================================
*
* Revision 1.6 93/10/31 22:28:25 hiro
* Prototype
* ================================================================
* Added $(ENV_PREFIX)_float treatment.
* -N and -n options are no longer valid.
* ================================================================
*
* Revision 1.5 93/04/06 22:23:05 hiro
* Prototype
* ================================================================
* Added -n/-N option that is passed to ci.
* ================================================================
*
* Revision 1.4 93/04/03 01:23:41 hiro
* Update
* ================================================================
* 1. Refined copyright message for initial check-in.
* 2. Temporarily removed original modification time stamp recovery
* logic.
* ================================================================
*
* Revision 1.4 93/04/03 01:21:09 hiro
* Update
* ================================================================
* 1. Refined copyright message for initial check-in.
* 2. Temporariry removed original modification recovery.
* ================================================================
*
************************************************************************/
#ifdef _UCC
_asm("_sysedit: equ 3");
#else
@_sysedit: equ 3
#define remove unlink
#endif
#ifdef _OS9000
#include <io.h>
#else
#include <sysio.h>
#endif
#include <stdio.h>
#if defined(__STDC__) || defined(_OS9000)
#include <stdlib.h>
#else
extern void *malloc();
extern char *getenv();
#endif
#include <strings.h>
#include <ctype.h>
#include <time.h>
#include <errno.h>
#include <modes.h>
#include <rbf.h>
FILE *namefile;
char **files;
char *nextfile();
extern char *_prgname();
#ifdef _OS9000
#define environ _environ
#define mod_exec mh_com
extern int _os_fork();
#else
extern int os9forkc();
#endif
extern mod_exec *modlink(), *modloadp();
#ifdef __STDC__
extern char *tmpnam();
#else
#define tmpnam(s) mktemp(strcpy((s),"_srcin$XXXXXX"))
extern char *mktemp();
#endif
#ifndef SEEK_SET
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif
#ifndef EXEC_
#define READ_ S_IREAD
#define EXEC_ S_IEXEC
#endif
#ifndef L_tmpnam
#define L_tmpnam 14
#endif
extern char *environ;
#define CIPROG "ci"
#define RLPROG "rlog"
char *ENVFILENAME = "ENVIRONMENT";
char *ENV_PREFIX;
char tfname[L_tmpnam], *logmsg, *nopt;
mod_exec *cimp, *edmp, *rlmp;
int stop;
char revision[80];
/*---------------------------------------------------------
! clean-up procedure at exit
*/
void cleanup(err, cstr, a)
int err;
char *cstr, *a;
{
if (tfname[0])
remove(tfname);
if (cimp)
munlink(cimp);
if (edmp)
munlink(edmp);
if (cstr)
exit(_errmsg(err, cstr, a));
else exit(err);
}
/*---------------------------------------------------------
! fork and wait a program
*/
int runprog(args)
char *args[];
{
int status;
#ifdef _OS9000
process_id pid;
if (errno = os9kexec(_os_fork, 0, 3, *args, args, environ,
0, &pid, mktypelang(MT_PROGRAM, ML_OBJECT), 0))
#else
int pid;
if ((pid = os9exec(os9forkc, *args, args, environ, 0, 0, 3)) == -1)
#endif
cleanup(errno, "can't fork \"%s\". ", *args);
while (wait(&status) != pid)
;
return status;
}
/*---------------------------------------------------------
! fork and wait ci program
*/
int runci(opt1, opt2, file)
char *opt1, *opt2, *file;
{
static char *args[] = {CIPROG, "-u", NULL, NULL, NULL, NULL, NULL, NULL, NULL};
int i;
char floatbuf[256];
args[2] = opt1;
if (args[i = 3] = opt2)
i++;
sprintf(floatbuf, "-N%s_float", ENV_PREFIX);
if (revision[0])
args[i++] = revision;
args[i++] = floatbuf;
args[i++] = file;
args[i++] = NULL;
return runprog(args);
}
/*---------------------------------------------------------
! initial check-in
*/
void initci(file)
register char *file;
{
static char *dirbuf = NULL, buf[256], desc[L_tmpnam+10];
static int numdirs;
FILE *fp;
register int i, dfsize;
register char *p;
fputs("Is this a new check-in? [yn Esc to abort] (y) ", stderr);
fflush(stderr);
if (!fgets(buf, sizeof buf, stdin))
cleanup(0, "Aborted.\n", NULL);
if (toupper(buf[0]) != 'Y' && buf[0] != '\n')
{
fprintf(stderr, "** \"%s\" skipped... **\n", file);
return;
}
/* set up RCS directory list if this is the first time */
if (!dirbuf)
if (fp = fopen("RCSDIR", "r"))
{
fseek(fp, 0L, SEEK_END);
dfsize = ftell(fp);
if (!(dirbuf = malloc(dfsize + 10)))
cleanup(errno, "can't allocate directory name buffer. ", NULL);
rewind(fp);
for (p = dirbuf, numdirs = 1; fgets(p, dfsize, fp); )
if (*p && *p != '#' && *p != '*' && !isspace(*p))
{
p += strlen(p);
if (*(p - 1) == '\n')
*(p - 1) = '\0';
else p++;
numdirs++;
}
fclose(fp);
strcpy(p, "RCS");
}
else
{
dirbuf = "RCS";
numdirs = 1;
}
/* choose a directory to check-in into */
for (p = dirbuf, i = numdirs; i > 0; p += strlen(p) + 1, i--)
{
do
{
fprintf(stderr, "Check-in into directory \"%s\"? [yn] (y) ", p);
fflush(stderr);
} while (!fgets(buf, sizeof buf, stdin));
if (toupper(buf[0]) == 'Y' || buf[0] == '\n')
{
if (!tfname[0])
{/* set up description file */
time_t today;
if (!(fp = fopen(tmpnam(tfname), "w")))
{
_errmsg(errno, "can't create descrition temporary file \"%s\".\n",
tfname);
tfname[0] = '\0';
goto failed;
}
time(&today);
#ifdef __STDC__
strftime(buf, sizeof buf, "%Y", localtime(&today));
#else
sprintf(buf, "%d", localtime(&today)->tm_year + 1900);
#endif
fprintf(fp, "*******************************************\n\n");
fprintf(fp, " Unless otherwise noted, this program is:\n\n");
fprintf(fp, " Copyright %s ARK Systems USA\n", buf);
fprintf(fp, " All rights reserved.\n");
fprintf(fp, "*******************************************\n");
fclose(fp);
sprintf(desc, "-t%s", tfname);
}
sprintf(buf, "%s/%s_v", p, file);
runci(desc, nopt, buf);
return;
}
}
failed:
fprintf(stderr, "** \"%s\" was not checked-in **\n", file);
}
/*---------------------------------------------------------
! check-in into existing RCS file
*/
void doci(file)
register char *file;
{
runci(logmsg, NULL, file);
}
/*---------------------------------------------------------
* look for 2 tokens from the beginning
* return location of 3rd token (must be a number)
*/
char *gettokens(buf, tok1, tok2)
register char *buf, *tok1, *tok2;
{
int tlen;
if (strncmp(buf, tok1, tlen = strlen(tok1)))
return NULL;
buf += tlen;
if (!isspace(*buf))
return NULL;
do
buf++;
while (isspace(*buf));
if (strncmp(buf, tok2, tlen = strlen(tok2)))
return NULL;
buf += tlen;
if (!isspace(*buf))
return NULL;
do
buf++;
while (isspace(*buf));
return isdigit(*buf) ? buf : NULL;
}
/*---------------------------------------------------------
* look for possible token and return edition number position
*/
char *foundit(buf, fname)
char *buf, *fname;
{
register char *p;
if (!strcmp(fname + strlen(fname) - 2, ".a"))
{
if (p = gettokens(buf, "edition", "equ"))
return p;
if (p = gettokens(buf, "edition:", "equ"))
return p;
if (p = gettokens(buf, "Edition", "equ"))
return p;
if (p = gettokens(buf, "Edition:", "equ"))
return p;
return NULL;
}
if (!strcmp(fname + strlen(fname) - 2, ".c"))
{
/* first, check old CC style #asm and @ */
if (p = gettokens(buf, "_sysedit:", "equ"))
return p;
if (p = gettokens(buf, "@_sysedit:", "equ"))
return p;
/* next, check UCC style _asm() */
while (isspace(*buf))
buf++; /* skip leading spaces */
if (strncmp(buf, "_asm", 4))
return NULL;
buf += 4;
while (isspace(*buf))
buf++;
if (*buf != '(')
return NULL;
do
buf++;
while (isspace(*buf));
return gettokens(buf, "\"_sysedit:", "equ");
}
return NULL;
}
/*---------------------------------------------------------
* update edition number
*/
char *updateit(fname, buf, p)
register char *fname, *buf, *p;
{
int edition = atoi(p) + 1;
char tbuf[10];
fprintf(stderr, "`%.*s' -> ", strlen(buf) - 1, buf);
if (edition == 10 || edition == 100 || edition == 1000 || edition == 10000)
memcpy(p + 1, p, strlen(p)); /* make more room */
sprintf(tbuf, "%d", edition);
memcpy(p, tbuf, strlen(tbuf));
fprintf(stderr, "`%s\'.\n", tbuf);
return buf;
}
/*---------------------------------------------------------
* process edition number in a file
*/
void procedition(fname)
register char *fname;
{
register FILE *fp, *tfp;
register char *p, *tname;
char buf[256], answer[10];
int updated = 0;
#ifdef __STDC__
tname = tmpnam(NULL);
#else
static char template[] = "srcin$XXXXXX";
tname = mktemp(template);
#endif
if (!(tfp = fopen(tname, "w")))
exit(_errmsg(errno, "can't open temporary file \"%s\". ", tname));
if (!(fp = fopen(fname, "r")))
exit(_errmsg(errno, "can't open \"%s\". ", fname));
/* process each line */
while (fgets(buf, sizeof buf, fp))
{
if (p = foundit(buf, fname))
{
fprintf(stderr, "%s: `%.*s' found; update? ([y]/n) ",
fname, strlen(buf) - 1, buf);
fflush(stderr);
if (fgets(answer, sizeof answer, stdin)
&& toupper(answer[0]) != 'N')
{
updateit(fname, buf, p);
updated++;
}
}
fputs(buf, tfp);
}
/*
if (updated)
_ss_attr(fileno(fp), _gs_attr(fileno(fp))|S_IWRITE|S_PWRITE);
*/
fclose(fp);
fclose(tfp);
if (updated) {
fprintf(stderr, "%s: updating edition number...\n", fname);
if (rename(tname, fname))
exit(_errmsg(errno, "can't rename \"%s\" to \"%s\". ",tname,fname));
putc('\n', stderr);
}
else {
if (remove(tname))
exit(_errmsg(errno, "can't remove \"%s\". ", tname));
}
}
/*---------------------------------------------------------
! process each file
*/
void process(file)
register char *file;
{
static char *args[4] = {RLPROG, "-b%w: %r", NULL, NULL};
register char *p;
int pn;
#if 0
struct fd orgfd, tmpfd;
if ((pn = open(file, 0)) == -1)
{
fprintf(stderr, "** \"%s\" not found. Skipped... **\n", file);
return;
}
_gs_gfd(pn, &orgfd, 16);
close(pn);
#endif
procedition(file);
args[2] = file;
if (runprog(args))
initci(file);
else doci(file);
#if 0
/* recover original modified date/time */
if (!(orgfd.fd_att & S_IWRITE))
{
if ((pn = open(file, 0)) == -1)
{
fprintf(stderr, "** \"%s\" was found but now not. Strange... **\n", file);
goto failed;
}
_ss_attr(pn, orgfd.fd_att | S_IWRITE);
close(pn);
}
if ((pn = open(file, S_IREAD+S_IWRITE)) == -1)
{
fprintf(stderr, "** \"%s\" can't be opened for date/time recovery **\n", file);
goto failed;
}
_gs_gfd(pn, &tmpfd, 16);
memcpy(&orgfd.fd_own, &tmpfd.fd_own, 2);
_ss_pfd(pn, &orgfd, 16);
_ss_attr(pn, orgfd.fd_att);
close(pn);
failed:
#endif
if (stop)
cleanup(stop, "Stopped by signal.\n", NULL);
}
mod_exec *mlinkload(mod)
char *mod;
{
mod_exec *mp;
if ((int)(mp = modlink(mod, mktypelang(MT_PROGRAM, ML_OBJECT))) == -1 &&
(int)(mp = modloadp(mod, EXEC_, NULL)) == -1 &&
(int)(mp = modloadp(mod, READ_, NULL)) == -1)
cleanup(errno, "can't find \"%s\". ", mod);
}
void put_env(pp, p)
char **pp, *p;
{
if (!(*pp = malloc(strlen(p)+1)))
exit(_errmsg(errno, "can't allocate buffer. "));
strcpy(*pp, p);
}
void getenvironment()
{
register FILE *fp;
register char *p;
char buf[256];
if (!(fp = fopen(ENVFILENAME, "r")))
exit(_errmsg(errno, "can't open environment file \"%s\". ", ENVFILENAME));
while ((p = fgets(buf, sizeof buf, fp)))
{
if (p[strlen(p) - 1] == '\n')
p[strlen(p) - 1] = '\0';
if (!strncmp(p, "ENV_PREFIX=", 11) && isalpha(p[1]))
put_env(&ENV_PREFIX, p + 11);
}
if (!ENV_PREFIX)
exit(_errmsg(1, "can't find ENV_PREFIX.\n"));
fclose(fp);
}
void intcpt(sig)
{
stop = sig;
}
main(argc, argv)
int argc;
char *argv[];
{
register char *file, *cstr = NULL, *editor = NULL;
register char *p, **fpp;
register int ch, waseq = 0;
long tfsize;
register FILE *cfp = NULL, *tfp;
char buf[80], *args[3];
files = fpp = argv;
while (--argc)
{
if (*(p = *++argv) == '-')
{
++p;
while (ch = *p++)
{
waseq = *p == '=';
if (waseq)
++p;
switch (ch)
{
case 'c':
if (cstr)
exit(_errmsg(1, "only one log comment string allowed.\n"));
else if (cfp)
exit(_errmsg(1, "either comment string or file allowed.\n"));
else if (!*(cstr = p))
exit(_errmsg(1, "empty log comment string.\n"));
break;
case 'C':
if (cfp)
exit(_errmsg(1, "only one log comment file allowed.\n"));
else if (cstr)
exit(_errmsg(1, "either comment string or file allowed.\n"));
else if (!(cfp = fopen(p, "r")))
exit(_errmsg(errno, "can't open log comment file \"%s\". ", p));
break;
case 'n':
case 'N':
if (waseq)
exit(_errmsg(1, "n/N options can't have '='.\n"));
nopt = p - 2;
break;
case 'r':
sprintf(revision, "-u%s", p);
break;
case 'e':
editor = p;
break;
case 'z':
if (namefile)
exit(_errmsg(
1,"only one file of names allowed.\n"));
if (waseq)
{
if ((namefile = fopen(p,"r")) == NULL)
exit(_errmsg(errno,
"can't open \"%s\". ",p));
}
else
{
namefile = stdin;
continue;
}
break;
default:
prtuse(_errmsg(1,"unknown option '%c'.\n\n",ch));
case '?':
prtuse(0);
}
break;
}
}
else *fpp++ = p;
}
*fpp = NULL;
if (fpp == files && namefile == NULL)
exit(_errmsg(1, "no files to check in.\n"));
else if (!editor && !(editor = getenv("EDITOR")))
exit(_errmsg(1, "no editor selected.\n"));
getenvironment();
cimp = mlinkload(CIPROG);
edmp = mlinkload(editor);
rlmp = mlinkload(RLPROG);
/* set up comment file */
if (!(tfp = fopen(tmpnam(tfname), "w+")))
exit(_errmsg(errno, "can't create comment temporary file \"%s\". ", tfname));
/* ask for reason to change interactively */
fputs("\nReason for change:\n\n", stderr);
fputs(" P - Prototype\n B - Bug fix\n E - Enhancement\n R - Code review\n", stderr);
fputs(" U - Update\n A - Abort\n\n", stderr);
while (1)
{
fputs("Enter P, B, E, R, U, or A: ", stderr);
fflush(stderr);
fgets(buf, sizeof(buf), stdin);
switch (toupper(*buf))
{
case 'P':
fputs("Prototype\n", tfp); break;
case 'B':
fputs("Bug Fix #\n", tfp); break;
case 'E':
fputs("Enhancement\n", tfp); break;
case 'R':
fputs("Code Review\n", tfp); break;
case 'U':
fputs("Update\n", tfp); break;
case 'A':
cleanup(0, NULL, NULL);
default:
continue;
}
break;
}
fputs("================================================================\n", tfp);
if (cstr)
fprintf(tfp, "%s\n", cstr);
else if (cfp)
{
while ((ch = getc(cfp)) != EOF)
putc(ch, tfp);
putc('\n', tfp);
fclose(cfp);
}
fseek(tfp, 0L, SEEK_END);
tfsize = ftell(tfp);
fclose(tfp);
/* invoke editor */
args[0] = editor;
args[1] = tfname;
args[2] = NULL;
do
{
if (ch = runprog(args))
cleanup(ch, NULL, NULL);
while (1)
{
fputs("Abort, Edit, Continue? (C) ", stderr);
fflush(stderr);
fgets(buf, sizeof(buf), stdin);
switch (toupper(*buf))
{
case 'A':
cleanup(0, NULL, NULL);
case 'E':
case 'C':
break;
default:
continue;
}
break;
}
} while (toupper(*buf) != 'C');
if (!(tfp = fopen(tfname, "r+")))
cleanup(errno, "can't create log message temporary file \"%s\". ", tfname);
fseek(tfp, 0L, SEEK_END);
if (tfsize == ftell(tfp))
{/* size not changed */
fprintf(stderr, "\nNo log message entered - Forced check-in.\n");
logmsg = "-mForced check-in.\n";
}
else
{
fseek(tfp, -1, SEEK_END);
if (getc(tfp) != '\n')
putc('\n', tfp);
fputs("================================================================\n", tfp);
fseek(tfp, 0L, SEEK_END);
if (!(logmsg = malloc((ch = ftell(tfp)) + 10)))
cleanup(errno, "can't alloacte logmessage buffer. ", NULL);
strcpy(logmsg, "-m");
rewind(tfp);
fread(logmsg + 2, ch, 1, tfp);
logmsg[ch + 2] = '\0';
}
fclose(tfp);
remove(tfname);
tfname[0] = '\0';
while (file = nextfile())
process(file);
cleanup(0, NULL, NULL);
}
char *nextfile()
{
register char *file = NULL;
static char nambuf[120];
if (file = *files)
++files;
else if (namefile)
{
if ((file = fgets(nambuf,sizeof nambuf,namefile)) == NULL)
{
if (ferror(namefile))
exit(_errmsg(errno,"can't read name file.\n"));
fclose(namefile);
namefile = NULL;
}
else *(file + strlen(file) - 1) = '\0';
}
return file;
}
/**--------------------------------------------------------------
! cmds[] - array of pointers to strings of help text
!*/
static char *cmds[] = {
"Function: check in files\n",
"Options:\n",
" -c=<log> log comment string\n",
" -C=<file> read log comment strings from file\n",
" -e=<editor> use <editor> instead of $EDITOR\n",
#if 0 /* removed for ***_float is introduced */
" -n<symbolic label> assign <symbolic label> to this revision\n",
" -N<symbolic label> force to assign <symbolic label> to this revision\n",
#endif
" -r<revision> check in as <revision>\n",
" -z[=<file>] read list of files from standard input or <file>\n"
};
/**--------------------------------------------------------------
! printuse - print the help text to standard error.
!*/
static prtuse(stat)
int stat;
{
register char **p = cmds,
**e = cmds + sizeof cmds / sizeof (char *);
fprintf(stderr,"Syntax: %s {<opts>} [<file>] {<opts>}\n", _prgname());
while (p < e)
fputs(*p++,stderr);
exit(stat);
}