[comp.sources.amiga] v02i092: tail - look at the end of a file

page@swan.ulowell.edu (Bob Page) (12/06/88)

Submitted-by: brant@uf.msc.umn.edu (Gary Brant)
Posting-number: Volume 2, Issue 92
Archive-name: unix/tail.1

Tail now works with *real* pipes, will run with the default stack size
of 4000 bytes and has no line limit.

[uuencoded executable also enclosed; it's small.  ..Bob]

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:    Shell Archiver
#	Run the following text with /bin/sh to create:
#	readme
#	tail.doc
#	tail.uu
#	tail.c
#	alloc.c
#	makefile
# This archive created: Mon Dec  5 18:04:37 1988
cat << \SHAR_EOF > readme
This is a replacement for the tail which i submitted a few weeks ago.  It
fixes a few problems, notably it now works with *real* pipes, it will run
with the default stack size of 4000 bytes, and the arbitrary maximum line
limit of 4096 has been removed all with no decrease in performance.


-Gary Brant

The source & binary are freely distributable;  you may do anything
you like with them except sell them for profit as long as you leave
my name in the source and include this notice with the source files.

Have fun.


		 Gary Brant

	US mail: 1355 Eustis St. #1
	         St. Paul, MN 55108

	ARPA:	 brant@uc.msc.umn.edu
SHAR_EOF
cat << \SHAR_EOF > tail.doc
TAIL				USER COMMANDS			TAIL



NAME
	tail - display the last part of a file

SYNOPSIS
	tail +|-number [ filename ...]

DESCRIPTION
	tail copies filename to the standard output beginning  at  a 
	designated  place.   If no file is named, the standard input
	is used.

OPTIONS
	+number
	     Begin copying at number lines  from the beginning of the
	     file.  If number is not specified, the value 10 is used.

	-number
	     Begin copying at number lines  from the end of the file. 
	     If number is not specified, the value 10 is used.


SEE ALSO
	head

BUGS
	Data for a tail relative to the end of the file  is stored in
	a buffer, and thus is limited to  available memory.
SHAR_EOF
cat << \SHAR_EOF > tail.uu

begin 777 tail
M```#\P`````````#``````````(```4N````E0````$```/I```%+D[Z"4!."
M5?_R0FW_^C`L@`)(P"M`__12;?_Z,"W_^K!M``AL``$4,"W_^DC`Y8`@;0`*`
M(G`(``P1`"UF)#`M__I(P.6`(&T`"B\P"`!.N@+(6$\K0/_T.6W_]H`"8```#
MUC`M__I(P.6`(&T`"B)P"``,$0`K9B8P+?_Z2,#E@"!M``HO,`@`3KH"CEA/>
M1(`K0/_T.6W_]H`"8```FE)L@`1(>@#","W_^DC`Y8`@;0`*+S`(`$ZZ!@I0H
M3RM`__QF.$AL@&Q(>@"@3KH$DE!/2&R`;#`M__I(P.6`(&T`"B\P"`!.N@1XW
M4$](;(!L/SP`"DZZ#'Q<3V!`+RW_]#`M__I(P.6`(&T`"B\P"``O+?_\86A/>
M[P`,.T#_^"\M__Q.N@RR6$]*;?_X9PH_+?_X3KH#;E1/8`#^X$IL@`1F&B\MC
M__1(>@`T2&R`0&$N3^\`##\`3KH#2E1/0F=.N@-"5$].74YU<@!T86EL.B!C-
M86XG="!O<&5N(````$Y5_!)(YP\P*"T`$$J$;&`@!%*$2H!L'"\M``@_/`/H0
M2&W\%DZZ`VA/[P`**T#\$F<"8-Q*K?P29S(O+0`,3KH!&%A/+RT`"#\\`^A(`
M;?P63KH#/$_O``I*@&<02&R`5DAM_!9.N@-\4$]@V&```,J5RGX`+RT`"#\\D
M`^A(;?P63KH##$_O``I*@&<``()(;?P63KH"Z%A/.T#__E*'OH1O#"P*)%(O-
M!DZZ`=!83S`M__Y:0#\`3KH!/E1/*@!F*DAL@&Q(>@!V3KH#&%!/(`IG#BP*,
M)%(O!DZZ`:!83V#N<!1,WPSP3EU.=2`*9@0D16`")H4F14AM_!8@15B(+PA.H
MN@)J4$\@14*08`#_:"\M``QA1%A/(`IG'DAL@%8@2EB(+PA.N@*\4$\L"B12"
M+P9.N@%(6$]@WG``8*9N;W0@96YO=6=H(&UE;6]R>2!F;W(@;&ES=`H`3E4`!
M`$IL@`1G*DAL@%9(>@`H3KH"=E!/2&R`5B\M``A.N@)H4$](;(!62'H`$4ZZ"
M`EI03TY=3G4]/3X@`"`\/3T*``!.50``2.<.`'@`>@%@,+P\`#!M'KP\`#EN6
M&'(*(`1.N@G2*``0!DB`D'P`,$C`V(!@"C`L@`)(P"@`8`Q212!M``@<,%``I
M9L8@!$S?`'!.74YU3E4``$Y=3G5.50``2.<(,#`M``C0?``/YDCG0'(`,@`H5
M`29L@`8@"V820>R"!B9(*4B`!BE(@@9"K((*)%,@*@`$L(1E*B`J``2PA&8$]
M)I)@#)FJ``35Z@`$)40`!"E+@`9"DB`*4(!,WPP03EU.=;7L@`9F#DZZ`((DA
M0$J`9@1P`&#D)DHD4F"T8-Q.50``2.<`,"1M``A1BB9L@`:URV,$M=-E%+?3>
M902URV(,M]-E!+73900F4V#D(&H`!-'*L=-F$"!3("@`!-&J``0@4R208`(D&
MDR!K``31R['*9@P@*@`$T:L`!":28`(FBBE+@`9,WPP`3EU.=4Y5```O"D*GG
M2'@0`$ZZ#\Q03R1`2H!F"'``)%].74YU0I(E?```$```!"!*4(@O"$ZZ_V!80
M3R`L@`9@WDY5__Q(YP`P)&R`!B`*9R8F4BMJ``3__$JM__QC$$*J``0O+?_\A
M+PI.N@^:4$\D2[7L@`9FUC\M``A.N@T:5$],WPP`3EU.=2!O``0@"")O``@0J
MV6;\3G4@;P`$(`A*&&;\D<`@"%.`3G5.50``2.<(("1M``A3;0`,2FT`#&\@]
M+RT`#DZZ`&XX`+!\__]83V<.($I2BA"$N'P`"F<"8-9"$KA\__]F$+7M``AFA
M"G``3-\$$$Y=3G4@+0`(8/).50``+PHD;0`(2A)G)"\M``P@2E**$!!(@#\`_
M3KH'LK!\__]<3V8(</\D7TY=3G5@V'``8/1.50``2.<(("1M``@O"DZZ`#(X>
M`+!\__]83V<B,`1(P&`44Y((Z@`#``QP_TS?!!!.74YU8-9*@&?Z68!GY#`$%
M8.I.50``+PHD;0`((%*QZ@`$90PO"F$66$\D7TY=3G4@4E*2$!!(@,!\`/]@B
M[$Y5``!(YP@P)&T`"!`J``S`/``89PIP_TS?#!!.74YU"*H``@`,2JH`"&8(H
M+PI.N@E`6$\0*@`,2(`(```'9S!![(!`)D@0*P`,2(#`?`"$L'P`A&8,/SS_K
M_R\+3KH'^%Q/U_P````60>R!^+?(9=8_*@`0+RH`"!`J``U(@#\`3KH"/C@`<
M2D!03VX42D1F!'`(8`)P$($J``QP_V``_WHP!$C`)*H`"-"J``@E0``$(%)2]
MDA`02(#`?`#_8`#_6DY5```O"DZZ"'`D0$J`9@AP`"1?3EU.=2\*+RT`#"\M$
M``AA!D_O``Q@Z$Y5``!(YP@@+RT`$$ZZ!MI![(`*)$A83TH29A`Y?``%@@YPE
M`$S?!!!.74YU($HB;0`,$!BP&68$2@!F]I`A2(!G!%R*8-(_*@`$+RT`"$ZZ(
M`$`X`+!\__]<3V8$<`!@Q"!M`!`11``-(&T`$!%\``$`#"`M`!!@K$Y5```_,
M+0`,/SP#`2\M``AA!E!/3EU.=4Y5``!(YP\P)&T`"$ZZ"A(F;((0>`!@#C`$<
MP?P`!DJS"`!G#E)$N&R!^&WL>@9@``#$""T``0`,9S!(>/__+PI.N@O^+`!0*
M3V<@+P9.N@PV+PI.N@O$2H!03V8.3KH+SCH`L'P`S68``(Q(>`/M+PI.N@O<@
M+`!*AE!/9F`(+0````QF!'H!8&Q(>`/N+PI.N@N^+`!03V8(3KH+DCH`8%1(B
M>``A2'H`DDZZ#%XN`%!/9PHO!TZZ#`!83V`>2'@``4AZ`((O!DZZ"\A(>/__?
M0J<O!DZZ"YY/[P`88"8P+0`,P'P%`+!\!0!F&"\&3KH+$GH$6$\Y18(.</],,
MWPSP3EU.=3`$P?P`!B>&"``P!,'\``8@0-'+,6T`#``$""T``P`,9Q!(>``!2
M0J<O!DZZ"T1/[P`,,`1@PF1O<RYL:6)R87)Y````3E4``$CG#"`X+0`(3KH(Y
MS#`$P?P`!B1`U>R"$$I$;0JX;('X;`1*DF80.7P``H(.</],WP0P3EU.=3`J[
M``3`?``#L'P``68*.7P`!8(.</]@X'``,"T`#B\`+RT`"B\23KH*O"H`L+S_M
M____3^\`#&8,3KH*<CE`@@YP_V"T(`5@L&%P0^R"`D7L@@*UR68.,CP`%&L(>
M=``BPE')__PI3X(4+'@`!"E.@AA(YX"`""X`!`$I9Q!+^@`(3J[_XF`&0J?SJ
M7TYS0_H`($ZN_F@I0((<9@PN/``#@`=.KO^48`1.N@`:4$].=61O<RYL:6)R@
M87)Y`$GY``!__DYU3E4``"\*2'D``0``,"R!^,'\``8O`$ZZ"FPI0((04$]FQ
M%$*G2'D``0``3KH*,%!/+FR"%$YU(&R"$$)H``0@;((0,7P``0`0(&R"$#%\&
M``$`"B!L@A0@+((4D*@`!%"`*4""("!L@B`@O$U!3EA"ITZZ"B`D0$JJ`*Q8;
M3V<N+RT`#"\M``@O"DZZ`*XY?``!@B0@;((0`&B````$(&R"$`!H@```"D_O3
M``Q@0DAJ`%Q.N@H^2&H`7$ZZ"@`I0((F(&R")DJH`"103V<0(&R")B)H`"0ON
M$4ZZ"/)83R\L@B8O"DZZ^,@I;((F@BI03TZZ"/(@;((0((!.N@D@(&R"$"%`V
M``9G%DAX`^U(>@`J3KH(_"!L@A`A0``,4$\O+((J/RR"+DZZ]2)"9TZZ!PQ0J
M3R1?3EU.=2H`3E4``$CG##`D;0`0(&T`"$JH`*QG&"!M``@@*`"LY8`H`"!$%
M("@`$.6`)D!@!"9L@?H0$TB`2,#0K0`,5(`Y0((P0J<P+((P2,`O`$ZZ"/XIT
M0((R4$]F"$S?##!.74YU$!-(@#H`/P4@2U*(+P@O+((R3KH!?C`%2,`@0-'LK
M@C)#^@%$$-EF_#\M``XO"B\L@C).N@$Z(&R",D(P4``Y?``!@BXP!4C`T*R"I
M,B9`4HLD2T_O`!00$TB`.@"P?``@9QBZ?``)9Q*Z?``,9PRZ?``-9P:Z?``*#
M9@12BV#8#!,`(&UZ#!,`(F8N4HL@2U*+$!!(@#H`9QX@2E**$(6Z?``B9A`,[
M$P`B9@12BV`&0BK__V`"8-9@."!+4HL0$$B`.@!G)KI\`"!G(+I\``EG&KI\&
M``QG%+I\``UG#KI\``IG""!*4HH0A6#.($I2BD(02D5F`E.+4FR"+F``_UI"-
M$D*G,"R"+E)`2,#E@"\`3KH'W"E`@BI03V8(0FR"+F``_MAZ`"9L@C)@)#`%/
M2,#E@"!L@BHABP@`($L@"$H89OR1P%.(,`A20$C`U\!21;IL@BYMUC`%2,#E7
M@"!L@BI"L`@`8`#^E"``,#Q__V`$,"\`#"!O``1*&&;\4T@B;P`(4T`0V5?(C
M__QG`D(0("\`!$YU3.\#```$(`@R+P`,8`(0V5?)__QG!E)!8`)"&%')__Q.H
M=4CG<``T`<3`)@%(0\;`2$-"0]2#2$#`P4A`0D#0@DS?``Y.=4Y5```O!#@M(
M``@O+0`*/P1.N@`PN'P`"EQ/9B0@;0`*$"@`#$B`"```!V<4/SS__R\M``I.V
MN@#T7$\H'TY=3G5@^$Y5```O"B1M``H@4K'J``1E&#`M``C`?`#_/P`O"DZZ+
M`,A<3R1?3EU.=2!24I(0+0`)$(!(@,!\`/]@Z$Y5```O"D'L@$`D2"!*U?P`+
M```6+PAA$%A/0>R!^+7(9>HD7TY=3G5.50``2.<(("1M``AX`"`*9@IP_TS?'
M!!!.74YU2BH`#&=0""H``@`,9PP_//__+PIA4C@`7$\0*@`-2(`_`$ZZ!1R(S
M0`@J``$`#%1/9PHO*@`(3KH"+EA/""H`!0`,9Q(O*@`23KH"P"\J`!).N@(4-
M4$]"DD*J``1"J@`(0BH`##`$8)!.5?_^2.<(("1M``A!^O]&*4B"-@@J``0`B
M#&<*</],WP003EU.=0@J``(`#&<P(%*1Z@`(.`@_!"\J``@0*@`-2(`_`$ZZ?
M`H"P1%!/9Q`(Z@`$``Q"DD*J``1P_V#`#&W__P`,9A`(J@`"``Q"DD*J``1P.
M`&"H2JH`"&8(+PI.N@":6$\,:@`!`!!F*AMM``W__S\\``%(;?__$"H`#4B`<
M/P!.N@(BL'P``5!/9J`P+0`,8`#_:B2J``@P*@`02,#0J@`()4``!`CJ``(`6
M#"!24I(0+0`-$(!(@,!\`/]@`/\^3E4``"\*0>R`0"1(2BH`#&<8U?P````6W
M0>R!^+7(90AP`"1?3EU.=6#B0I)"J@`$0JH`""`*8.I.5?_\+PHD;0`(/SP$.
M`$ZZ`,`K0/_\5$]F&#5\``$`$"!*T?P````.)4@`""1?3EU.=35\!```$`CJS
M``$`#"5M__P`"!`J``U(@#\`3KH`XDI`5$]G!@`J`(``#&#.3E4``$CG`#`D^
M;(("8!0F4B`J``10@"\`+PI.N@1\4$\D2R`*9NA"K(("3-\,`$Y=3G5.50``J
M+PI!^O_&*4B".D*G("T`"%"`+P!.N@0F)$!*@%!/9@AP`"1?3EU.=22L@@(EJ
M;0`(``0I2H("(`I0@&#F3E4``'``,"T`""\`8;)83TY=3G5.50``2.<`,)?+C
M)&R"`F`.(&T`"%&(L<IG$B9*)%(@"F;N</],WPP`3EU.=2`+9P0FDF`$*5*"+
M`B`J``10@"\`+PI.N@/.<`!03V#83E4``"\*,"T`",'\``8D0-7L@A!*;0`(B
M;0XP+0`(L&R!^&P$2I)F#CE\``*"#G#_)%].74YU,"T`",'\``8@;((0+S`()
M`$ZZ`L9*@%A/9P1P`6`"<`!@V$Y5```O+0`(3KH"D$J`6$]F#DZZ`IHY0((.:
M</].74YU<`!@^$Y5``!(YPP@."T`"$ZZ`'`P!,'\``8D0-7L@A!*1&T*N&R!@
M^&P$2I)F$#E\``*"#G#_3-\$,$Y=3G4P*@`$P'P``V8*.7P`!8(.</]@Y'``W
M,"T`#B\`+RT`"B\23KH"D"H`L+S_____3^\`#&8,3KH"&CE`@@YP_V"X(`5@B
MM$Y5__Q(>!``0J=.N@+X*T#__`@```Q03V<22FR")&8(("W__$Y=3G5.N@`&M
M<`!@]$Y5``!(>``$2'H`'$ZZ`?XO`$ZZ`BP_/``!3KH`#D_O``Y.74YU7D,*L
M`$Y5``!*K((V9P8@;((V3I`_+0`(3KH`"%1/3EU.=4Y5__PO!#`M``A(P"M`>
M__Q*K((09RAX`&`*/P1.N@#^5$]21+AL@?AM\#`L@?C!_``&+P`O+((03KH"N
M&E!/2JR".F<&(&R".DZ02JR!_F<*+RR!_DZZ`9)83TJL@CYG""!L@CX@K()"!
M2JR"1F<*+RR"1DZZ`:I83TJL@DIG"B\L@DI.N@&:6$]*K().9PHO+().3KH![
MBEA/2JR"4F<*+RR"4DZZ`7I83RQX``0(+@`$`2EG%"\-2_H`"DZN_^(J7V`&C
M0J?S7TYS2JR")F8P2JR",F<H,"R",$C`+P`O+((R3KH!<C`L@BY20$C`Y8`OR
M`"\L@BI.N@%>3^\`$&`.3KH!2"\L@B9.N@%X6$\@+?_\+FR"%$YU*!].74YU6
M3E4``$CG#B`X+0`(,`3!_``&)$#5[((02D1M"KAL@?AL!$J29A`Y?``"@@YPV
M_TS?!'!.74YU""H`!P`$9@@O$DZZ``I83T*2<`!@XB(O``0L;((<3N[_W"(OJ
M``0L;((<3N[_@B(O``0L;((<3N[_N"QL@AQ.[O_*+&R"'$[N_WPB+P`$+&R",
M'$[N_RA,[P`&``0L;((<3N[_K$SO``8`!"QL@AQ.[O_B+&R"'$[N_\1,[P`.W
M``0L;((<3N[_UDSO``X`!"QL@AQ.[O^^3OH``B(O``0L;((<3N[_IDSO``X`&
M!"QL@AQ.[O_02.<!!$SO((``#"QL@AA.KO^43-\@@$YU(F\`!"QL@AA.[OYB2
M3OH``DSO``,`!"QL@AA.[O\Z(F\`!"QL@AA.[O[:+&R"&$[N_WQ.^@`"(F\`2
M!"`O``@L;((83N[_+B!O``0L;((83N[^C"QL@A@B;P`$("\`"$[N_=@B;P`$%
M+&R"&$[N_H9,[P`#``0L;((83N[^SB!O``0L;((83N[^@````^P````!````=
M`0``";8````````#\@```^H```"```H```````!R``````!R*P````)W````T
M`P%W*P```P)A````"0%A*P``"0)X````!0%X*P``!0(`````````````````5
M```````!``````$``````````````````````0$````!````````````````%
M``````$"`````0``````````````````````````````````````````````$
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M```````````````````````````````````````4``````````````/R```#,
)ZP````$```/RA
``
end
size 5904
SHAR_EOF
cat << \SHAR_EOF > tail.c
/* tail.c - print the last few lines in a file.  If count is specified, *
 *	that many lines are printed instead of the default value of	*
 *	ten lines.  If no files are specified, head reads standard	*
 *	input.								*
 *									*
 * tail [-<count>] [<file> ...] 					*
 *									*
 * tail (C) 1988 by Gary L. Brant					*
 *									*
 * :ts=8								*/

#include <stdio.h>
#define   MAXLINE   1000

void fputs ();
int default_lines = 10; /* default number of lines to list */
int headlin = 0;

typedef struct list {
   struct list *nxt;
   char line[MAXLINE];
};


main (argc, argv)	/* list 1st n lines of a file */
int  argc;
char *argv[];
{
   FILE *input, *fopen ();
   void fclose ();
   int i = 0, rval;
   long maxlines, convert ();
   char ch;

   maxlines = default_lines;
   while (++i < argc) {
      if (argv [i][0] == '-') { 	/* process line count argument */
	 maxlines = convert (argv[i]);
	 default_lines = maxlines;
      } else if (argv [i][0] == '+') {
	 maxlines = -convert (argv[i]);
	 default_lines = maxlines;
      } else {
	 ++headlin;
	 if ((input = fopen (argv[i], "r")) == NULL) {
	    fputs ("tail: can't open ", stderr);
	    fputs (argv[i], stderr);
	    putc ('\n', stderr);
	    break;
	 } else {
	    rval = list (input, argv[i], maxlines);
	    fclose (input);
	    if (rval)
               quit (rval);
	 }
      }
   }
   if (!headlin)
      quit (list (stdin, "", maxlines));
   quit (0);
}


list (fp, fn, maxlines) 	/* list tail of a file */
FILE *fp;
char *fn;
register long maxlines;
{
   int n;
   char line[MAXLINE];
   char *c, *fgets (), *alloc ();

   if (maxlines < 0) {		/* +n, head relative list */
      while (maxlines++ < 0 && (c = fgets (line, MAXLINE, fp)) != NULL);
      if (c != NULL) {
	 heading (fn);
	 while ((fgets (line, MAXLINE, fp)) != NULL)
	    fputs (line, stdout);
      }
   } else {			/* -n, tail relative list */
      register struct list *head = NULL, *curr, *next, *p;
      register long nlin = 0;

      while ((fgets (line, MAXLINE, fp)) != NULL) {
         n = strlen (line);
	 if (++nlin > maxlines) {	/* de-link 1st line */
	    p = head;
	    head = head->nxt;
	    freeit (p);
	 }
	 if ((next = (struct list *) alloc (n+5)) == NULL) {
	    fputs ("not enough memory for list\n", stderr);
	    while (head != NULL) {
	       p = head;
	       head = head->nxt;
	       freeit (p);
	    }
	    return (20);
	 }
	 if (head == NULL)
	    head = next;
	 else
	    curr->nxt = next;
	 curr = next;
	 strcpy (next->line, line);
	 next->nxt = NULL;
      }
      heading (fn);

      /* now print the lines in the list, deallocating as we go */

      while (head != NULL) {
         fputs (head->line, stdout);
	 p = head;
	 head = head->nxt;
	 freeit (p);
      }
   }
   return (0);
}


heading (filename)
char *filename;
{
   if (headlin) {
      fputs ("==> ", stdout);
      fputs (filename, stdout);
      fputs (" <==\n", stdout);
   }
}


long convert (string)
char string[];
{
   register long maxlines = 0;
   register int j;
   register char ch;

   for (j = 1; (ch = string[j]) != '\0'; j++)
   if (ch >= '0' && ch <= '9') {
      maxlines *= 10;
      maxlines += ch - '0';
   } else {
      maxlines = default_lines;
      break;
   }
   return (maxlines);
}


void _wb_parse ()
{
}
SHAR_EOF
cat << \SHAR_EOF > alloc.c
/* alloc.c - memory allocator
 *
 * The point of this is that it is about 4 times faster than MANX malloc/free
 * in c.lib.  Malloc in heapmem.o will not allocate a second heap if the first
 * is exhausted.
 * :ts=8
 */


#define NULL		0L
#define HOWMUCH		4096L	/* how much memory to AllocMem() at a time */

typedef struct header {
      struct header *next;	/* next block */
      unsigned long size;	/* block size */
};

struct header first;

struct header *head = NULL;	/* start of list */


char *alloc (bytes)
unsigned bytes;
{
   struct header *getmem ();
   register struct header *p, *q;
   register long size;

   size = (((bytes + 2 * sizeof (struct header) - 1) >> 3) << 3);
   if ((q = head) == NULL) {
      first.next = head = q = &first;
      first.size = 0L;
   }
   for (p = q->next; ; q = p, p = p->next) {
      if (p->size >= size) {	/* if this block is large enough */
         if (p->size == size)
	    q ->next = p->next;
	 else {		/* remove memory from tail of block */
	    p->size -= size;
	    p = (struct header *) ((char *) p + p->size);
	       p->size = size;
	 }
	 head = q;
	 p->next = NULL;
	 return ((char *) (p+1));
      }
      if (p == head)	/* back where we started */
	 if ((p = getmem ()) == NULL)
	    return (NULL);	/* cannot allocate memory */
   }
}


/* freeit - put block back in free list */

freeit (ptr)
char *ptr;
{
   register struct header *p, *q;

   p = (struct header *) ptr - 1;
   for (q = head; ; q = q->next) {
      if (p > q && p < q->next)
	 break;		/* new block goes between q & q->next */
      if (q >= q->next && p > q)
	 break;		/* new block goes at end of list */
      if (q >= q->next && p < q->next)
	 break;		/* new block goes at beginning of list */
   }

   if ((struct header *) ((char *) p + p->size) == q->next) {
      p->size += q->next->size;
      p->next = q->next->next;
   } else {
      p->next = q->next;
   }
   if ((struct header *) ((char *) q + q->size) == p) {
      q->size += p->size;
      q->next = p->next;
   } else {
      q->next = p;
   }
   head = q;
}


/* getmem - request more memory from system */

struct header *getmem ()
{
   char *AllocMem ();
   register struct header *up;

   if ((up = (struct header *) AllocMem (HOWMUCH, 0L)) == NULL)
      return (NULL);	/* can't get more memory */
   up->next = NULL;
   up->size = HOWMUCH;
   freeit ((char *) (up + 1));
   return (head);
}


quit (code)
int code;
{
   register struct header *p, *q;
   unsigned long size;

   p = head;
   do {
      if (p == NULL)
         break;
      q = p->next;
      if ((size = p->size) > 0L) {
	 p->size = 0L;
         FreeMem (p, size);
      }
      p = q;
   } while (p != head);
   exit (code);
}
SHAR_EOF
cat << \SHAR_EOF > makefile
CFLAGS=-s


tail:	tail.o alloc.o
	ln tail.o alloc.o -lc

SHAR_EOF
#	End of shell archive
exit 0
-- 
Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
Have five nice days.