mirror of https://github.com/GnoConsortium/gno.git
Initial checkin. This version of the sources matches that used to
build the GNO v2.0.4 distribution.
This commit is contained in:
parent
784e3de7cd
commit
31e9970070
|
@ -0,0 +1,37 @@
|
||||||
|
alarm (1)
|
||||||
|
|
||||||
|
NAME
|
||||||
|
alarm - alarm clock reminder
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
alarm [+]#### [<delay> ["<message>"]]
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
alarm is a reminder program. Typically it is executed in the
|
||||||
|
background. The program sleeps until the alarm time, and so
|
||||||
|
uses very little CPU.
|
||||||
|
|
||||||
|
The first argument defines the time, or time delay, for the
|
||||||
|
alarm to ring. It must consist of an optional leading plus
|
||||||
|
sign followed by four decimal digits. If the plus sign is
|
||||||
|
present the alarm will ring in 'hhmm' hours. If the plus sign
|
||||||
|
is absent, the alarm will ring at time 'hhmm' in 24-hour
|
||||||
|
format. The alarm rings five times, each time delivering a
|
||||||
|
beep, with beeps two seconds apart. The second argument, if
|
||||||
|
present, changes the time between beeps. The third argument,
|
||||||
|
if present, is echoed to stdout after each beep as a reminder
|
||||||
|
message.
|
||||||
|
|
||||||
|
EXAMPLES
|
||||||
|
alarm +0080 5 "Your TV show is on in five minutes" &
|
||||||
|
rings the bell every five seconds and delivers the
|
||||||
|
message eighty minutes after the current time.
|
||||||
|
|
||||||
|
alarm 1955
|
||||||
|
rings the bell every two seconds at 7:55 PM
|
||||||
|
|
||||||
|
FILES
|
||||||
|
none
|
||||||
|
|
||||||
|
AUTHOR
|
||||||
|
Christopher Neufeld (neufeld@physics.utoronto.ca)
|
|
@ -0,0 +1,83 @@
|
||||||
|
/* Alarm v1.0. Copyright 1994 by Christopher Neufeld */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <gno/gno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#pragma stacksize 512
|
||||||
|
|
||||||
|
#define BEEP putchar((char)0x07)
|
||||||
|
#define TBEEPS 2 /* Time between beeps in seconds */
|
||||||
|
|
||||||
|
#define MAXBEEPS 5
|
||||||
|
|
||||||
|
#define SECSPERDAY (60 * 60 * 24)
|
||||||
|
|
||||||
|
#define DIGTOI(x) ((int) ((x) - '0'))
|
||||||
|
|
||||||
|
void usage(char *exename)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Alarm program. Copyright 1994 by Christopher Neufeld\n");
|
||||||
|
fprintf(stderr, "Usage: %s [+]#### [<delay> [\"<message>\"]]\n", exename);
|
||||||
|
fprintf(stderr, "Where #### is a time in hhmm format, ie. 0010 is ten past midnight\n");
|
||||||
|
fprintf(stderr, " +#### indicates that number of hhmm after the current time.\n");
|
||||||
|
fprintf(stderr, " delay is the time delay between beeps or messages, if any.\n");
|
||||||
|
fprintf(stderr, " message is delivered to stdout at alarm condition\n\n");
|
||||||
|
fprintf(stderr, "This executable contains linked runtime libraries copyrighted\n");
|
||||||
|
fprintf(stderr, "by The Byte Works. Used with Permission.\n\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *ptr1, *tptr, *msg;
|
||||||
|
static struct tm timenow, timethen;
|
||||||
|
static time_t curtime, alarmtime;
|
||||||
|
static int i, mins, hrs, offset, message, deltat;
|
||||||
|
unsigned long initwait;
|
||||||
|
|
||||||
|
message = 0;
|
||||||
|
deltat = TBEEPS;
|
||||||
|
if (argc < 2 || argc > 4) usage(argv[0]);
|
||||||
|
if (argc > 2) {
|
||||||
|
deltat = (int) strtoul(argv[2], &ptr1, 0);
|
||||||
|
if (*ptr1 != 0) usage(argv[0]); /* Unable to parse delay time */
|
||||||
|
if (argc == 4) {
|
||||||
|
msg = argv[3];
|
||||||
|
message = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tptr = argv[1] + (offset = (argv[1][0] == '+'));
|
||||||
|
if (strlen(tptr) != 4) usage(argv[0]);
|
||||||
|
for (i=0;i<4;i++)
|
||||||
|
if (!isdigit(tptr[i])) usage(argv[0]);
|
||||||
|
hrs = 10 * DIGTOI(tptr[0]) + DIGTOI(tptr[1]);
|
||||||
|
mins = atoi(tptr + 2);
|
||||||
|
if (mins > 59) {
|
||||||
|
if (offset) hrs++;
|
||||||
|
else usage(argv[0]);
|
||||||
|
}
|
||||||
|
if (hrs > 23 && !offset) usage(argv[0]);
|
||||||
|
if (!offset) {
|
||||||
|
curtime = time(NULL);
|
||||||
|
timethen = *localtime(&curtime);
|
||||||
|
timethen.tm_sec = 0;
|
||||||
|
timethen.tm_min = mins;
|
||||||
|
timethen.tm_hour = hrs;
|
||||||
|
alarmtime = mktime(&timethen);
|
||||||
|
initwait = difftime(alarmtime, curtime);
|
||||||
|
if (initwait <= 0) initwait += SECSPERDAY;
|
||||||
|
} else initwait = 60 * (mins + 60 * hrs);
|
||||||
|
sleep(initwait);
|
||||||
|
for (i=0;i<MAXBEEPS;i++) {
|
||||||
|
BEEP;
|
||||||
|
fflush(stdout);
|
||||||
|
if (message) printf("%s\n", msg);
|
||||||
|
sleep(deltat);
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
|
@ -0,0 +1,253 @@
|
||||||
|
#pragma keep "AppleWorks"
|
||||||
|
|
||||||
|
#pragma stacksize 2048
|
||||||
|
|
||||||
|
#pragma optimize -1
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#pragma lint -1
|
||||||
|
|
||||||
|
|
||||||
|
#define PROG_VERSION "0.70"
|
||||||
|
#define DATE "11/21/92"
|
||||||
|
|
||||||
|
FILE *f;
|
||||||
|
char SFMinVers; /* Minimum AppleWorks Version required */
|
||||||
|
int MultRulers; /* Boolean - Multiple Rulers */
|
||||||
|
char Ruler[80]; /* Ruler for Tab Stops */
|
||||||
|
int *input;
|
||||||
|
int lcv;
|
||||||
|
int *ID1, *ID2;
|
||||||
|
char Center; /* Boolean - Centering on */
|
||||||
|
char Codes; /* Boolean - Special Codes switch */
|
||||||
|
char NewPage; /* Boolean - Use New Page */
|
||||||
|
char LeftMargin; /* Size of left margin (tenths of an inch) */
|
||||||
|
char RightMargin; /* Size of right margin (tenths of an inch) */
|
||||||
|
char PlatenWidth; /* Width of platen (tenths of an inch) */
|
||||||
|
char argument;
|
||||||
|
char ShowNames; /* Boolean - Show names of file being processed */
|
||||||
|
|
||||||
|
void usage (void)
|
||||||
|
|
||||||
|
{
|
||||||
|
fprintf (stderr, " Version %s (%s)\n", PROG_VERSION, DATE);
|
||||||
|
fprintf (stderr, " Robert Hill\n");
|
||||||
|
fprintf (stderr, " INTERNET: rhill@oread.cc.ukans.edu\n AOL: RobertHill\n\n");
|
||||||
|
fprintf (stderr, "Usage: appleworks [-cn] filename\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int initialize (void)
|
||||||
|
|
||||||
|
{
|
||||||
|
fseek (f, 4L, SEEK_SET);
|
||||||
|
*input = (char) fgetc (f);
|
||||||
|
|
||||||
|
if (*input != 79) {
|
||||||
|
fprintf (stderr, "appleworks: File is not an AppleWorks file.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (lcv = 0; lcv < 80; ++lcv) {
|
||||||
|
Ruler [lcv] = (char) fgetc (f);
|
||||||
|
if (Ruler[lcv] == EOF) {
|
||||||
|
fprintf (stderr, "appleworks: File is corrupted.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek (f, 177L, SEEK_SET);
|
||||||
|
MultRulers = (char) fgetc (f);
|
||||||
|
fseek (f, 184L, SEEK_SET);
|
||||||
|
SFMinVers = (char) fgetc (f);
|
||||||
|
fseek (f, 300L, SEEK_SET);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int TextLine (void)
|
||||||
|
|
||||||
|
{
|
||||||
|
char indent;
|
||||||
|
int length;
|
||||||
|
float location;
|
||||||
|
|
||||||
|
*input = (char) fgetc (f);
|
||||||
|
|
||||||
|
if (*input == EOF)
|
||||||
|
return -1;
|
||||||
|
indent = (*input & 127);
|
||||||
|
for (lcv = 0; lcv < indent; ++ lcv)
|
||||||
|
printf (" ");
|
||||||
|
|
||||||
|
*input = (char) fgetc (f);
|
||||||
|
|
||||||
|
if (*input == EOF)
|
||||||
|
return -1;
|
||||||
|
length = (*input) & 127;
|
||||||
|
|
||||||
|
if (Center) {
|
||||||
|
location = (((PlatenWidth - RightMargin - LeftMargin) / 10.0) -
|
||||||
|
length) / 2.0;
|
||||||
|
for (lcv = 0; lcv < (int) location; ++ lcv)
|
||||||
|
printf (" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (lcv = 0; lcv < length; ++ lcv) {
|
||||||
|
*input = (char) fgetc (f);
|
||||||
|
if (*input == EOF)
|
||||||
|
return -1;
|
||||||
|
else if (((*input) > 0x18) && ((*input) <= 0x7F))
|
||||||
|
printf ("%c", *input);
|
||||||
|
else switch (*input) {
|
||||||
|
case 0x01 : printf ("%c", 15); /* Boldface on */
|
||||||
|
break;
|
||||||
|
case 0x02 : printf ("%c", 14); /* Boldface off */
|
||||||
|
break;
|
||||||
|
case 0x07 : printf ("%c", 15); /* Underline on */
|
||||||
|
break;
|
||||||
|
case 0x08 : printf ("%c", 14); /* Underline off */
|
||||||
|
break;
|
||||||
|
case 0x16 : printf (" ");
|
||||||
|
++indent;
|
||||||
|
while ((Ruler[indent]=='=') && (indent < 81)) {
|
||||||
|
printf (" "); /* Tab */
|
||||||
|
++indent;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void HandleCommand (int *ID1, int *ID2)
|
||||||
|
|
||||||
|
{
|
||||||
|
switch (*ID2) {
|
||||||
|
case 0xD8 : PlatenWidth = *ID1;
|
||||||
|
if (Codes)
|
||||||
|
printf ("---Platen Width=%.1f inches\n",
|
||||||
|
(float) (PlatenWidth / 10));
|
||||||
|
break;
|
||||||
|
case 0xD9 : LeftMargin = *ID1;
|
||||||
|
if (Codes)
|
||||||
|
printf ("---Left Margin=%.1f inches\n",
|
||||||
|
(float) (LeftMargin / 10));
|
||||||
|
break;
|
||||||
|
case 0xDA : RightMargin = *ID1;
|
||||||
|
if (Codes)
|
||||||
|
printf ("---Right Margin=%.1f inches\n",
|
||||||
|
(float) (RightMargin / 10));
|
||||||
|
break;
|
||||||
|
case 0xE0 : Center = 0;
|
||||||
|
if (Codes)
|
||||||
|
printf ("---Unjustified\n");
|
||||||
|
break;
|
||||||
|
case 0xE1 : Center = 1;
|
||||||
|
if (Codes)
|
||||||
|
printf ("---Center\n");
|
||||||
|
break;
|
||||||
|
case 0xE9 : if (NewPage)
|
||||||
|
printf ("%c", 12);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
argument = 1;
|
||||||
|
Codes = NewPage = ShowNames = 0;
|
||||||
|
|
||||||
|
input = (int *) malloc (sizeof(int));
|
||||||
|
ID1 = (int *) malloc (sizeof(int));
|
||||||
|
ID2 = (int *) malloc (sizeof(int));
|
||||||
|
|
||||||
|
if (argc == 1)
|
||||||
|
usage ();
|
||||||
|
else {
|
||||||
|
while (argc > argument) {
|
||||||
|
Center = 0;
|
||||||
|
LeftMargin = RightMargin = 10;
|
||||||
|
PlatenWidth = 80;
|
||||||
|
if ((argument == 1) && (argv[1][0] == '-')) {
|
||||||
|
lcv = 1;
|
||||||
|
while (argv[1][lcv] != 0x00) {
|
||||||
|
switch (argv[1][lcv]) {
|
||||||
|
case 'c' : Codes = 1;
|
||||||
|
break;
|
||||||
|
case 'n' : NewPage = 1;
|
||||||
|
break;
|
||||||
|
case 's' : ShowNames = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++lcv;
|
||||||
|
}
|
||||||
|
if (argc > 2) {
|
||||||
|
++argument;
|
||||||
|
f = fopen (argv[2], "rb");
|
||||||
|
if (f == NULL) {
|
||||||
|
fprintf (stderr,
|
||||||
|
"appleworks: Could not open %s.\n",
|
||||||
|
argv[2]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (ShowNames)
|
||||||
|
printf ("appleworks: %s\n\n", argv[2]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
usage ();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
f = fopen (argv[argument], "rb");
|
||||||
|
if (f == NULL) {
|
||||||
|
fprintf (stderr, "appleworks: Could not open %s.\n",
|
||||||
|
argv[argument]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (ShowNames)
|
||||||
|
printf ("appleworks: %s\n\n", argv[argument]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initialize () == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
while ((!((*ID1==0xFF) && (*ID2==0xFF))) &&
|
||||||
|
(!((*ID1==EOF) || (*ID2==EOF)))) {
|
||||||
|
|
||||||
|
*ID1 = fgetc (f);
|
||||||
|
*ID2 = fgetc (f);
|
||||||
|
|
||||||
|
if ((*ID1 != EOF) && (*ID2 != EOF)) {
|
||||||
|
if (*ID2==0x00)
|
||||||
|
if (TextLine () == -1) {
|
||||||
|
fprintf (stderr,
|
||||||
|
"appleworks: %s is corrupted.\n",
|
||||||
|
argv[argument]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (*ID2==0xD0)
|
||||||
|
printf ("\n");
|
||||||
|
if ((*ID2) > 0xD0)
|
||||||
|
HandleCommand (ID1, ID2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*ID1 = *ID2 = 0;
|
||||||
|
++argument;
|
||||||
|
printf ("\n");
|
||||||
|
fclose (f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
banner: banner.c
|
||||||
|
compile banner.c keep=banner
|
||||||
|
link banner 2/direct256 keep=banner
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,40 @@
|
||||||
|
BANNER(6) MISCELLANEOUS BANNER(6)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
NAME
|
||||||
|
banner - print large banner on printer
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
/usr/games/banner [ -w n ] message ...
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
Banner prints a large, high quality banner on the standard
|
||||||
|
output. If the message is omitted, it prompts for and reads
|
||||||
|
one line of its standard input. If -w is given, the output
|
||||||
|
is scrunched down from a width of 132 to n , suitable for a
|
||||||
|
narrow terminal. If n is omitted, it defaults to 80.
|
||||||
|
|
||||||
|
The output should be printed on a hard-copy device, up to
|
||||||
|
132 columns wide, with no breaks between the pages. The
|
||||||
|
volume is great enough that you may want a printer or a fast
|
||||||
|
hardcopy terminal, but if you are patient, a decwriter or
|
||||||
|
other 300 baud terminal will do.
|
||||||
|
|
||||||
|
BUGS
|
||||||
|
Several ASCII characters are not defined, notably <, >, [,
|
||||||
|
], \,^, _, {, }, |, and ~. Also, the characters ", ', and &
|
||||||
|
are funny looking (but in a useful way.)
|
||||||
|
|
||||||
|
The -w option is implemented by skipping some rows and
|
||||||
|
columns. The smaller it gets, the grainier the output.
|
||||||
|
Sometimes it runs letters together.
|
||||||
|
|
||||||
|
AUTHOR
|
||||||
|
Mark Horton
|
||||||
|
|
||||||
|
ACKNOWLEDGEMENTS
|
||||||
|
Copyright (c) 1980 The Regents of the University of
|
||||||
|
California. All rights reserved. This product includes
|
||||||
|
software developed by the University of California, Berkeley
|
||||||
|
and its contributors
|
|
@ -0,0 +1,5 @@
|
||||||
|
cal.a: cal.cc
|
||||||
|
compile cal.cc keep=cal
|
||||||
|
|
||||||
|
cal: cal.a
|
||||||
|
link cal 2/direct256 keep=cal
|
|
@ -0,0 +1,223 @@
|
||||||
|
/* static char rcsid[] = "$Header: /nobackup/gdr/copy-of-cvs-from-tekarra/gno/usr.bin/cal/cal.c,v 1.1 1998/03/09 15:29:53 gdr-ftp Exp $";
|
||||||
|
|
||||||
|
#ifdef __ORCAC__
|
||||||
|
#pragma stacksize 1024
|
||||||
|
#pragma optimize 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef lint
|
||||||
|
static char sccsid[] = "@(#)cal.c 4.3 (Berkeley) 83/08/11";
|
||||||
|
#endif */
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
char dayw[] = {
|
||||||
|
" S M Tu W Th F S"
|
||||||
|
};
|
||||||
|
char *smon[]= {
|
||||||
|
"January", "February", "March", "April",
|
||||||
|
"May", "June", "July", "August",
|
||||||
|
"September", "October", "November", "December",
|
||||||
|
};
|
||||||
|
char string[432];
|
||||||
|
char *progname;
|
||||||
|
|
||||||
|
main(argc, argv)
|
||||||
|
char *argv[];
|
||||||
|
{
|
||||||
|
register y, i, j;
|
||||||
|
int m;
|
||||||
|
extern int _INITGNOSTDIO(void);
|
||||||
|
|
||||||
|
_INITGNOSTDIO();
|
||||||
|
/* setvbuf(stdout, NULL,_IOFBF, 1024l); */
|
||||||
|
progname = argv[0];
|
||||||
|
|
||||||
|
if(argc < 2) {
|
||||||
|
fprintf(stderr, "usage: %s [month] year\n",progname);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
if(argc == 2)
|
||||||
|
goto xlong;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* print out just month
|
||||||
|
*/
|
||||||
|
|
||||||
|
m = number(argv[1]);
|
||||||
|
if(m<1 || m>12)
|
||||||
|
goto badarg;
|
||||||
|
y = number(argv[2]);
|
||||||
|
if(y<1 || y>9999)
|
||||||
|
goto badarg;
|
||||||
|
printf(" %s %u\n", smon[m-1], y);
|
||||||
|
printf("%s\n", dayw);
|
||||||
|
cal(m, y, string, 24);
|
||||||
|
for(i=0; i<6*24; i+=24)
|
||||||
|
pstr(string+i, 24);
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* print out complete year
|
||||||
|
*/
|
||||||
|
|
||||||
|
xlong:
|
||||||
|
y = number(argv[1]);
|
||||||
|
if(y<1 || y>9999)
|
||||||
|
goto badarg;
|
||||||
|
printf("\n\n\n");
|
||||||
|
printf(" %u\n", y);
|
||||||
|
printf("\n");
|
||||||
|
for(i=0; i<12; i+=3) {
|
||||||
|
for(j=0; j<6*72; j++)
|
||||||
|
string[j] = '\0';
|
||||||
|
printf(" %.3s", smon[i]);
|
||||||
|
printf(" %.3s", smon[i+1]);
|
||||||
|
printf(" %.3s\n", smon[i+2]);
|
||||||
|
printf("%s %s %s\n", dayw, dayw, dayw);
|
||||||
|
cal(i+1, y, string, 72);
|
||||||
|
cal(i+2, y, string+23, 72);
|
||||||
|
cal(i+3, y, string+46, 72);
|
||||||
|
for(j=0; j<6*72; j+=72)
|
||||||
|
pstr(string+j, 72);
|
||||||
|
}
|
||||||
|
printf("\n\n\n");
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
badarg:
|
||||||
|
printf("Bad argument\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
number(str)
|
||||||
|
char *str;
|
||||||
|
{
|
||||||
|
register n, c;
|
||||||
|
register char *s;
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
s = str;
|
||||||
|
while(c = *s++) {
|
||||||
|
if(c<'0' || c>'9')
|
||||||
|
return(0);
|
||||||
|
n = n*10 + c-'0';
|
||||||
|
}
|
||||||
|
return(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
pstr(str, n)
|
||||||
|
char *str;
|
||||||
|
{
|
||||||
|
register i;
|
||||||
|
register char *s;
|
||||||
|
|
||||||
|
s = str;
|
||||||
|
i = n;
|
||||||
|
while(i--)
|
||||||
|
if(*s++ == '\0')
|
||||||
|
s[-1] = ' ';
|
||||||
|
i = n+1;
|
||||||
|
while(i--)
|
||||||
|
if(*--s != ' ')
|
||||||
|
break;
|
||||||
|
s[1] = '\0';
|
||||||
|
printf("%s\n", str);
|
||||||
|
}
|
||||||
|
|
||||||
|
char mon[] = {
|
||||||
|
0,
|
||||||
|
31, 29, 31, 30,
|
||||||
|
31, 30, 31, 31,
|
||||||
|
30, 31, 30, 31,
|
||||||
|
};
|
||||||
|
|
||||||
|
cal(m, y, p, w)
|
||||||
|
char *p;
|
||||||
|
{
|
||||||
|
register d, i;
|
||||||
|
register char *s;
|
||||||
|
|
||||||
|
s = p;
|
||||||
|
d = jan1(y);
|
||||||
|
mon[2] = 29;
|
||||||
|
mon[9] = 30;
|
||||||
|
|
||||||
|
switch((jan1(y+1)+7-d)%7) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* non-leap year
|
||||||
|
*/
|
||||||
|
case 1:
|
||||||
|
mon[2] = 28;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 1752
|
||||||
|
*/
|
||||||
|
default:
|
||||||
|
mon[9] = 19;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* leap year
|
||||||
|
*/
|
||||||
|
case 2:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
for(i=1; i<m; i++)
|
||||||
|
d += mon[i];
|
||||||
|
d %= 7;
|
||||||
|
s += 3*d;
|
||||||
|
for(i=1; i<=mon[m]; i++) {
|
||||||
|
if(i==3 && mon[m]==19) {
|
||||||
|
i += 11;
|
||||||
|
mon[m] += 11;
|
||||||
|
}
|
||||||
|
if(i > 9)
|
||||||
|
*s = i/10+'0';
|
||||||
|
s++;
|
||||||
|
*s++ = i%10+'0';
|
||||||
|
s++;
|
||||||
|
if(++d == 7) {
|
||||||
|
d = 0;
|
||||||
|
s = p+w;
|
||||||
|
p = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* return day of the week
|
||||||
|
* of jan 1 of given year
|
||||||
|
*/
|
||||||
|
|
||||||
|
jan1(yr)
|
||||||
|
{
|
||||||
|
register y, d;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* normal gregorian calendar
|
||||||
|
* one extra day per four years
|
||||||
|
*/
|
||||||
|
|
||||||
|
y = yr;
|
||||||
|
d = 4+y+(y+3)/4;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* julian calendar
|
||||||
|
* regular gregorian
|
||||||
|
* less three days per 400
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(y > 1800) {
|
||||||
|
d -= (y-1701)/100;
|
||||||
|
d += (y-1601)/400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* great calendar changeover instant
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(y > 1752)
|
||||||
|
d += 3;
|
||||||
|
|
||||||
|
return(d%7);
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
To install the calendar program, create a file called "Calendar" in your
|
||||||
|
home directory, and put a line:
|
||||||
|
:bin:calendar
|
||||||
|
in your "gshrc" file.
|
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
CALENDAR(1) CALENDAR(1)
|
||||||
|
|
||||||
|
NAME
|
||||||
|
calendar - reminder service
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
calendar
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
calendar consults the file calendar in the current directory and prints
|
||||||
|
out lines that contain today's or tomorrow's date anywhere in the line.
|
||||||
|
Most reasonable month-day dates such as ``Aug. 24,'' ``august 24,''
|
||||||
|
``8/24,'' etc., are recognized, but not ``24 August'' or ``24/8''. On
|
||||||
|
weekends ``tomorrow'' extends through Monday.
|
||||||
|
|
||||||
|
BUGS
|
||||||
|
calendar's extended idea of ``tomorrow'' does not account for holidays.
|
||||||
|
|
||||||
|
Page 1 Release 4.0.5 May 1992
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
/* Calendar file v1.0. Copyright 1994 by Christopher Neufeld */
|
||||||
|
/* The executable for this file contains linked runtime libraries
|
||||||
|
copyrighted by The Byte Works. Used with permission. */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#pragma stacksize 512
|
||||||
|
|
||||||
|
#define NMONTHS 12
|
||||||
|
#define NDAYS 31
|
||||||
|
#define MAXLINELEN 255
|
||||||
|
|
||||||
|
#define CALFILE "calendar"
|
||||||
|
|
||||||
|
#define SECSPERDAY (24 * 60 * 60)
|
||||||
|
|
||||||
|
const char months[NMONTHS][] = {"jan", "feb", "mar", "apr", "may", "jun",
|
||||||
|
"jul", "aug", "sep", "oct", "nov", "dec"};
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
FILE *ifile;
|
||||||
|
time_t t1, t2;
|
||||||
|
struct tm st1, st2;
|
||||||
|
int monthnum, daynum, dayschk, i, j;
|
||||||
|
char *ptr1, *ptr2, holdmnth[4];
|
||||||
|
static char thislin[MAXLINELEN+1];
|
||||||
|
long deltat;
|
||||||
|
|
||||||
|
if ((ifile = fopen(CALFILE, "r")) == NULL) exit(0);
|
||||||
|
t1 = time(NULL);
|
||||||
|
st1 = *localtime(&t1);
|
||||||
|
st1.tm_sec = st1.tm_min = st1.tm_hour = 0;
|
||||||
|
t1 = mktime(&st1);
|
||||||
|
dayschk = (st1.tm_wday >= 5) ? 8 - st1.tm_wday : 1;
|
||||||
|
thislin[MAXLINELEN] = 0;
|
||||||
|
while (!feof(ifile)) {
|
||||||
|
fgets(thislin, MAXLINELEN, ifile);
|
||||||
|
ptr1 = thislin;
|
||||||
|
while (isspace(*ptr1) && *ptr1 != 0) ptr1++;
|
||||||
|
if (*ptr1 == 0) continue; /* Blank line */
|
||||||
|
monthnum = -1;
|
||||||
|
if (isdigit(*ptr1)) { /* month/day format */
|
||||||
|
monthnum = strtoul(ptr1, &ptr2, 10) - 1;
|
||||||
|
daynum = strtoul(ptr2+1, NULL, 10);
|
||||||
|
if (monthnum < 0 || monthnum >= NMONTHS || daynum < 0 || daynum > NDAYS)
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
for (i=0; i<3; i++) holdmnth[i] = tolower(ptr1[i]);
|
||||||
|
holdmnth[3] = 0;
|
||||||
|
for (i = 0; i < NMONTHS; i++)
|
||||||
|
if (!(strcmp(holdmnth, months[i]))) {
|
||||||
|
monthnum = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (monthnum == -1) continue;
|
||||||
|
while (!isspace(*ptr1) && *ptr1 != 0) ptr1++;
|
||||||
|
if (*ptr1 == 0) continue;
|
||||||
|
while (isspace(*ptr1) && *ptr1 != 0) ptr1++;
|
||||||
|
if (*ptr1 == 0) continue;
|
||||||
|
daynum = atoi(ptr1);
|
||||||
|
if (daynum < 1 || daynum > NDAYS) continue;
|
||||||
|
}
|
||||||
|
st2.tm_sec = st2.tm_min = st2.tm_hour = st2.tm_isdst = 0;
|
||||||
|
st2.tm_mday = daynum;
|
||||||
|
st2.tm_mon = monthnum;
|
||||||
|
st2.tm_year = st1.tm_year;
|
||||||
|
t2 = mktime(&st2);
|
||||||
|
if ((deltat = difftime(t2, t1)) < 0) { /* Next year */
|
||||||
|
st2.tm_year++;
|
||||||
|
t2 = mktime(&st2);
|
||||||
|
deltat = difftime(t2, t1);
|
||||||
|
}
|
||||||
|
if (deltat <= dayschk * SECSPERDAY) printf(thislin);
|
||||||
|
}
|
||||||
|
fclose(ifile);
|
||||||
|
exit(0);
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
Dec 25 No more shopping days until Christmas.
|
||||||
|
Jul 1 A Canadian holiday
|
|
@ -0,0 +1,152 @@
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1990 The Regents of the University of California.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Kevin Ruddy.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef lint
|
||||||
|
char copyright[] =
|
||||||
|
"@(#) Copyright (c) 1990 The Regents of the University of California.\n\
|
||||||
|
All rights reserved.\n";
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
#ifndef lint
|
||||||
|
static char sccsid[] = "@(#)fold.c 5.5 (Berkeley) 6/1/90";
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define DEFLINEWIDTH 80
|
||||||
|
|
||||||
|
main(argc, argv)
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
|
{
|
||||||
|
extern int errno, optind;
|
||||||
|
extern char *optarg;
|
||||||
|
register int ch;
|
||||||
|
int width;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
width = -1;
|
||||||
|
while ((ch = getopt(argc, argv, "0123456789w:")) != EOF)
|
||||||
|
switch (ch) {
|
||||||
|
case 'w':
|
||||||
|
if ((width = atoi(optarg)) <= 0) {
|
||||||
|
(void)fprintf(stderr,
|
||||||
|
"fold: illegal width value.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
|
if (width == -1) {
|
||||||
|
p = argv[optind - 1];
|
||||||
|
if (p[0] == '-' && p[1] == ch && !p[2])
|
||||||
|
width = atoi(++p);
|
||||||
|
else
|
||||||
|
width = atoi(argv[optind] + 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
(void)fprintf(stderr,
|
||||||
|
"usage: fold [-w width] [file ...]\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
argv += optind;
|
||||||
|
argc -= optind;
|
||||||
|
|
||||||
|
if (width == -1)
|
||||||
|
width = DEFLINEWIDTH;
|
||||||
|
if (!*argv)
|
||||||
|
fold(width);
|
||||||
|
else for (; *argv; ++argv)
|
||||||
|
if (!freopen(*argv, "r", stdin)) {
|
||||||
|
(void)fprintf(stderr,
|
||||||
|
"fold: %s: %s\n", *argv, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
} else
|
||||||
|
fold(width);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fold(width)
|
||||||
|
register int width;
|
||||||
|
{
|
||||||
|
register int ch, col, new;
|
||||||
|
|
||||||
|
for (col = 0;;) {
|
||||||
|
switch (ch = getchar()) {
|
||||||
|
case EOF:
|
||||||
|
return;
|
||||||
|
case '\b':
|
||||||
|
new = col ? col - 1 : 0;
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
case '\r':
|
||||||
|
new = 0;
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
new = (col + 8) & ~7;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
new = col + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new > width) {
|
||||||
|
putchar('\n');
|
||||||
|
col = 0;
|
||||||
|
}
|
||||||
|
putchar(ch);
|
||||||
|
|
||||||
|
switch (ch) {
|
||||||
|
case '\b':
|
||||||
|
if (col > 0)
|
||||||
|
--col;
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
case '\r':
|
||||||
|
col = 0;
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
col += 8;
|
||||||
|
col &= ~7;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
++col;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
tsort.a: tsort.c
|
||||||
|
compile tsort.c keep=tsort
|
||||||
|
|
||||||
|
tsort: tsort.a
|
||||||
|
link tsort 2/direct256 keep=tsort
|
|
@ -0,0 +1,8 @@
|
||||||
|
a b
|
||||||
|
b c
|
||||||
|
c f
|
||||||
|
c o
|
||||||
|
o m
|
||||||
|
m d
|
||||||
|
f b
|
||||||
|
|
|
@ -0,0 +1,380 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1989 The Regents of the University of California.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* Michael Rendell of Memorial University of Newfoundland.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __ORCAC__
|
||||||
|
#pragma stacksize 3072
|
||||||
|
#pragma optimize -1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef lint
|
||||||
|
char copyright[] =
|
||||||
|
"@(#) Copyright (c) 1989 The Regents of the University of California.\n\
|
||||||
|
All rights reserved.\n";
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
#ifndef lint
|
||||||
|
static char sccsid[] = "@(#)tsort.c 5.3 (Berkeley) 6/1/90";
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Topological sort. Input is a list of pairs of strings seperated by
|
||||||
|
* white space (spaces, tabs, and/or newlines); strings are written to
|
||||||
|
* standard output in sorted order, one per line.
|
||||||
|
*
|
||||||
|
* usage:
|
||||||
|
* tsort [inputfile]
|
||||||
|
* If no input file is specified, standard input is read.
|
||||||
|
*
|
||||||
|
* Should be compatable with AT&T tsort HOWEVER the output is not identical
|
||||||
|
* (i.e. for most graphs there is more than one sorted order, and this tsort
|
||||||
|
* usually generates a different one then the AT&T tsort). Also, cycle
|
||||||
|
* reporting seems to be more accurate in this version (the AT&T tsort
|
||||||
|
* sometimes says a node is in a cycle when it isn't).
|
||||||
|
*
|
||||||
|
* Michael Rendell, michael@stretch.cs.mun.ca - Feb 26, '90
|
||||||
|
*/
|
||||||
|
#define HASHSIZE 53 /* doesn't need to be big */
|
||||||
|
#define NF_MARK 0x1 /* marker for cycle detection */
|
||||||
|
#define NF_ACYCLIC 0x2 /* this node is cycle free */
|
||||||
|
|
||||||
|
typedef struct node_str NODE;
|
||||||
|
|
||||||
|
struct node_str {
|
||||||
|
char *n_name; /* name of this node */
|
||||||
|
NODE **n_prevp; /* pointer to previous node's n_next */
|
||||||
|
NODE *n_next; /* next node in graph */
|
||||||
|
NODE *n_hash; /* next node in hash table */
|
||||||
|
int n_narcs; /* number of arcs in n_arcs[] */
|
||||||
|
int n_arcsize; /* size of n_arcs[] array */
|
||||||
|
NODE **n_arcs; /* array of arcs to other nodes */
|
||||||
|
int n_refcnt; /* # of arcs pointing to this node */
|
||||||
|
int n_flags; /* NF_* */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _buf {
|
||||||
|
char *b_buf;
|
||||||
|
int b_bsize;
|
||||||
|
} BUF;
|
||||||
|
|
||||||
|
NODE *add_node(char *), *find_node(char *);
|
||||||
|
void add_arc(char *,char *), no_memory(void), remove_node(NODE *), tsort(void);
|
||||||
|
char *grow_buf(char *, int);
|
||||||
|
char *strdup(char*);
|
||||||
|
|
||||||
|
extern int errno;
|
||||||
|
NODE *graph;
|
||||||
|
NODE *hashtable[HASHSIZE];
|
||||||
|
NODE **cycle_buf;
|
||||||
|
NODE **longest_cycle;
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
register BUF *b;
|
||||||
|
register int c, n;
|
||||||
|
FILE *fp;
|
||||||
|
int bsize, nused;
|
||||||
|
BUF bufs[2];
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
fp = stdin;
|
||||||
|
else if (argc > 2) {
|
||||||
|
(void)fprintf(stderr, "usage: tsort [ inputfile ]\n");
|
||||||
|
exit(1);
|
||||||
|
} else if (!(fp = fopen(argv[1], "r"))) {
|
||||||
|
(void)fprintf(stderr, "tsort: %s.\n", strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (b = bufs, n = 2; --n >= 0; b++)
|
||||||
|
b->b_buf = grow_buf((char *)NULL, b->b_bsize = 1024);
|
||||||
|
|
||||||
|
/* parse input and build the graph */
|
||||||
|
for (n = 0, c = getc(fp);;) {
|
||||||
|
while (c != EOF && isspace(c))
|
||||||
|
c = getc(fp);
|
||||||
|
if (c == EOF)
|
||||||
|
break;
|
||||||
|
|
||||||
|
nused = 0;
|
||||||
|
b = &bufs[n];
|
||||||
|
bsize = b->b_bsize;
|
||||||
|
do {
|
||||||
|
b->b_buf[nused++] = c;
|
||||||
|
if (nused == bsize) {
|
||||||
|
bsize *= 2;
|
||||||
|
b->b_buf = grow_buf(b->b_buf, bsize);
|
||||||
|
}
|
||||||
|
c = getc(fp);
|
||||||
|
} while (c != EOF && !isspace(c));
|
||||||
|
|
||||||
|
b->b_buf[nused] = '\0';
|
||||||
|
b->b_bsize = bsize;
|
||||||
|
if (n)
|
||||||
|
add_arc(bufs[0].b_buf, bufs[1].b_buf);
|
||||||
|
n = !n;
|
||||||
|
}
|
||||||
|
(void)fclose(fp);
|
||||||
|
if (n) {
|
||||||
|
(void)fprintf(stderr, "tsort: odd data count.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do the sort */
|
||||||
|
tsort();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* double the size of oldbuf and return a pointer to the new buffer. */
|
||||||
|
char *grow_buf(char *bp, int size)
|
||||||
|
{
|
||||||
|
if (!(bp = realloc(bp, (u_int)size)))
|
||||||
|
no_memory();
|
||||||
|
return(bp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* add an arc from node s1 to node s2 in the graph. If s1 or s2 are not in
|
||||||
|
* the graph, then add them.
|
||||||
|
*/
|
||||||
|
void add_arc(char *s1, char *s2)
|
||||||
|
{
|
||||||
|
register NODE *n1;
|
||||||
|
NODE *n2;
|
||||||
|
int bsize;
|
||||||
|
|
||||||
|
n1 = find_node(s1);
|
||||||
|
if (!n1)
|
||||||
|
n1 = add_node(s1);
|
||||||
|
|
||||||
|
if (!strcmp(s1, s2))
|
||||||
|
return;
|
||||||
|
|
||||||
|
n2 = find_node(s2);
|
||||||
|
if (!n2)
|
||||||
|
n2 = add_node(s2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* could check to see if this arc is here already, but it isn't
|
||||||
|
* worth the bother -- there usually isn't and it doesn't hurt if
|
||||||
|
* there is (I think :-).
|
||||||
|
*/
|
||||||
|
if (n1->n_narcs == n1->n_arcsize) {
|
||||||
|
if (!n1->n_arcsize)
|
||||||
|
n1->n_arcsize = 10;
|
||||||
|
bsize = n1->n_arcsize * sizeof(*n1->n_arcs) * 2;
|
||||||
|
n1->n_arcs = (NODE **)grow_buf((char *)n1->n_arcs, bsize);
|
||||||
|
n1->n_arcsize = bsize / sizeof(*n1->n_arcs);
|
||||||
|
}
|
||||||
|
n1->n_arcs[n1->n_narcs++] = n2;
|
||||||
|
++n2->n_refcnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hash_string(char *s)
|
||||||
|
{
|
||||||
|
register int hash, i;
|
||||||
|
|
||||||
|
for (hash = 0, i = 1; *s; s++, i++)
|
||||||
|
hash += *s * i;
|
||||||
|
return(hash % HASHSIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find a node in the graph and return a pointer to it - returns null if not
|
||||||
|
* found.
|
||||||
|
*/
|
||||||
|
NODE *find_node(char *name)
|
||||||
|
{
|
||||||
|
register NODE *n;
|
||||||
|
|
||||||
|
for (n = hashtable[hash_string(name)]; n; n = n->n_hash)
|
||||||
|
if (!strcmp(n->n_name, name))
|
||||||
|
return(n);
|
||||||
|
return((NODE *)NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add a node to the graph and return a pointer to it. */
|
||||||
|
NODE *add_node(char *name)
|
||||||
|
{
|
||||||
|
register NODE *n;
|
||||||
|
int hash;
|
||||||
|
|
||||||
|
if (!(n = (NODE *)malloc(sizeof(NODE))) || !(n->n_name = strdup(name)))
|
||||||
|
no_memory();
|
||||||
|
|
||||||
|
n->n_narcs = 0;
|
||||||
|
n->n_arcsize = 0;
|
||||||
|
n->n_arcs = (NODE **)NULL;
|
||||||
|
n->n_refcnt = 0;
|
||||||
|
n->n_flags = 0;
|
||||||
|
|
||||||
|
/* add to linked list */
|
||||||
|
if (n->n_next = graph)
|
||||||
|
graph->n_prevp = &n->n_next;
|
||||||
|
n->n_prevp = &graph;
|
||||||
|
graph = n;
|
||||||
|
|
||||||
|
/* add to hash table */
|
||||||
|
hash = hash_string(name);
|
||||||
|
n->n_hash = hashtable[hash];
|
||||||
|
hashtable[hash] = n;
|
||||||
|
return(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do topological sort on graph */
|
||||||
|
void tsort(void)
|
||||||
|
{
|
||||||
|
register NODE *n, *next;
|
||||||
|
register int cnt;
|
||||||
|
|
||||||
|
while (graph) {
|
||||||
|
/*
|
||||||
|
* keep getting rid of simple cases until there are none left,
|
||||||
|
* if there are any nodes still in the graph, then there is
|
||||||
|
* a cycle in it.
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
for (cnt = 0, n = graph; n; n = next) {
|
||||||
|
next = n->n_next;
|
||||||
|
if (n->n_refcnt == 0) {
|
||||||
|
remove_node(n);
|
||||||
|
++cnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (graph && cnt);
|
||||||
|
|
||||||
|
if (!graph)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!cycle_buf) {
|
||||||
|
/*
|
||||||
|
* allocate space for two cycle logs - one to be used
|
||||||
|
* as scratch space, the other to save the longest
|
||||||
|
* cycle.
|
||||||
|
*/
|
||||||
|
for (cnt = 0, n = graph; n; n = n->n_next)
|
||||||
|
++cnt;
|
||||||
|
cycle_buf =
|
||||||
|
(NODE **)malloc((u_int)sizeof(NODE *) * cnt);
|
||||||
|
longest_cycle =
|
||||||
|
(NODE **)malloc((u_int)sizeof(NODE *) * cnt);
|
||||||
|
if (!cycle_buf || !longest_cycle)
|
||||||
|
no_memory();
|
||||||
|
}
|
||||||
|
for (n = graph; n; n = n->n_next)
|
||||||
|
if (!(n->n_flags & NF_ACYCLIC)) {
|
||||||
|
if (cnt = find_cycle(n, n, 0, 0)) {
|
||||||
|
register int i;
|
||||||
|
|
||||||
|
(void)fprintf(stderr,
|
||||||
|
"tsort: cycle in data.\n");
|
||||||
|
for (i = 0; i < cnt; i++)
|
||||||
|
(void)fprintf(stderr,
|
||||||
|
"tsort: %s.\n", longest_cycle[i]->n_name);
|
||||||
|
remove_node(n);
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
/* to avoid further checks */
|
||||||
|
n->n_flags = NF_ACYCLIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!n) {
|
||||||
|
(void)fprintf(stderr,
|
||||||
|
"tsort: internal error -- could not find cycle.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* print node and remove from graph (does not actually free node) */
|
||||||
|
void remove_node(NODE *n)
|
||||||
|
{
|
||||||
|
register NODE **np;
|
||||||
|
register int i;
|
||||||
|
|
||||||
|
(void)printf("%s\n", n->n_name);
|
||||||
|
for (np = n->n_arcs, i = n->n_narcs; --i >= 0; np++)
|
||||||
|
--(*np)->n_refcnt;
|
||||||
|
n->n_narcs = 0;
|
||||||
|
*n->n_prevp = n->n_next;
|
||||||
|
if (n->n_next)
|
||||||
|
n->n_next->n_prevp = n->n_prevp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* look for the longest cycle from node from to node to. */
|
||||||
|
int find_cycle(NODE *from, NODE *to, int longest_len, int depth)
|
||||||
|
{
|
||||||
|
register NODE **np;
|
||||||
|
register int i, len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* avoid infinite loops and ignore portions of the graph known
|
||||||
|
* to be acyclic
|
||||||
|
*/
|
||||||
|
if (from->n_flags & (NF_MARK|NF_ACYCLIC))
|
||||||
|
return(0);
|
||||||
|
from->n_flags = NF_MARK;
|
||||||
|
|
||||||
|
for (np = from->n_arcs, i = from->n_narcs; --i >= 0; np++) {
|
||||||
|
cycle_buf[depth] = *np;
|
||||||
|
if (*np == to) {
|
||||||
|
if (depth + 1 > longest_len) {
|
||||||
|
longest_len = depth + 1;
|
||||||
|
(void)memcpy((char *)longest_cycle,
|
||||||
|
(char *)cycle_buf,
|
||||||
|
longest_len * sizeof(NODE *));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
len = find_cycle(*np, to, longest_len, depth + 1);
|
||||||
|
if (len > longest_len)
|
||||||
|
longest_len = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
from->n_flags &= ~NF_MARK;
|
||||||
|
return(longest_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void no_memory(void)
|
||||||
|
{
|
||||||
|
(void)fprintf(stderr, "tsort: %s.\n", strerror(ENOMEM));
|
||||||
|
exit(1);
|
||||||
|
}
|
Loading…
Reference in New Issue