{ Who says you can't have dynamically allocated memory in NoLife ;) } PROGRAM LinkedList ; VAR listhead : INTEGER ; { This is the backend storage for *alloc functions. DO NOT access them directly! } { To change the ammount of memory available, simply alter the size of the arrays. } { Note that changes must match in *MEM, *REF, *SIZE, and in the *alloc functions! } NoLifeLibmallocCMEM : ARRAY [ 1 .. 10240 ] OF CHARACTER ; NoLifeLibmallocIMEM : ARRAY [ 1 .. 10240 ] OF INTEGER ; NoLifeLibmallocFMEM : ARRAY [ 1 .. 10240 ] OF FLOAT ; { These are the 'pointers' into the NoLifeLibmalloc*MEM arrays. } NoLifeLibmallocCREF : ARRAY [ 1 .. 10240 ] OF INTEGER ; NoLifeLibmallocIREF : ARRAY [ 1 .. 10240 ] OF INTEGER ; NoLifeLibmallocFREF : ARRAY [ 1 .. 10240 ] OF INTEGER ; { These track how large a space was allocated to a pointer. } NoLifeLibmallocCSIZE : ARRAY [ 1 .. 10240 ] OF INTEGER ; NoLifeLibmallocISIZE : ARRAY [ 1 .. 10240 ] OF INTEGER ; NoLifeLibmallocFSIZE : ARRAY [ 1 .. 10240 ] OF INTEGER ; { These track how much of the *MEM arrays have been allocated. } NoLifeLibmallocCNPTR, NoLifeLibmallocINPTR, NoLifeLibmallocFNPTR : INTEGER ; FUNCTION mallocC ( size : INTEGER ) : INTEGER ; BEGIN RETURN callocC(size,1) END ; FUNCTION callocC ( num,size : INTEGER ) : INTEGER ; VAR sz,ptr,i : INTEGER ; BEGIN sz := num * size ; ptr := NoLifeLibmallocCNPTR ; IF sz < 1 OR ptr+sz-1 > 10240 THEN RETURN 0 ; NoLifeLibmallocCNPTR := NoLifeLibmallocCNPTR+sz ; i := 1 ; WHILE NoLifeLibmallocCSIZE[i] > 0 DO i := i+1 ; NoLifeLibmallocCSIZE[i] := sz ; NoLifeLibmallocCREF[i] := ptr ; RETURN i END ; FUNCTION reallocC ( ptr,size : INTEGER ) : INTEGER ; VAR nptr : INTEGER ; BEGIN nptr := mallocC(size); IF nptr THEN BEGIN IF size < NoLifeLibmallocCSIZE[ptr] THEN memcpyC(nptr,ptr,size) ELSE memcpyC(nptr,ptr,NoLifeLibmallocCSIZE[ptr]) ; freeC(ptr) ; RETURN nptr END ELSE RETURN 0 END ; FUNCTION setheapC ( ptr,off : INTEGER ; val : CHARACTER ) : CHARACTER ; BEGIN IF ptr < 0 OR ptr > 10240 OR off >= NoLifeLibmallocCSIZE[ptr] THEN RETURN 'a' ELSE BEGIN NoLifeLibmallocCMEM[NoLifeLibmallocCREF[ptr]+off] := val ; RETURN NoLifeLibmallocCMEM[NoLifeLibmallocCREF[ptr]+off] END END ; FUNCTION getheapC ( ptr,off : INTEGER ) : CHARACTER ; BEGIN IF ptr < 0 OR ptr > 10240 OR off >= NoLifeLibmallocCSIZE[ptr] THEN RETURN 'a' ELSE RETURN NoLifeLibmallocCMEM[NoLifeLibmallocCREF[ptr]+off] END ; FUNCTION memcpyC ( dst,src,size : INTEGER ) : INTEGER ; VAR i,sz : INTEGER ; BEGIN IF size < 1 THEN RETURN dst ; IF dst < 1 OR dst > 10240 OR NoLifeLibmallocCSIZE[dst] < 1 THEN RETURN dst ; IF src < 1 OR src > 10240 OR NoLifeLibmallocCSIZE[src] < 1 THEN RETURN dst ; sz := size ; IF sz > NoLifeLibmallocCSIZE[dst] THEN sz := NoLifeLibmallocCSIZE[dst] ; IF sz > NoLifeLibmallocCSIZE[src] THEN sz := NoLifeLibmallocCSIZE[src] ; i := 0 ; WHILE i < sz DO BEGIN setheapC(dst,i,getheapC(src,i)) ; i := i+1 END ; RETURN dst END ; PROCEDURE freeC ( ptr : INTEGER ) ; VAR i,sz : INTEGER ; BEGIN IF ptr < 1 OR ptr > 10240 OR NoLifeLibmallocCSIZE[ptr] < 1 THEN RETURN 0 ; sz := NoLifeLibmallocCSIZE[ptr] ; i := NoLifeLibmallocCREF[ptr] ; WHILE i < NoLifeLibmallocCNPTR-sz DO BEGIN NoLifeLibmallocCMEM[i] := NoLifeLibmallocCMEM[i+sz] ; i := i+1 END ; i := 1 ; WHILE i < 10240 DO BEGIN IF NoLifeLibmallocCREF[i] > NoLifeLibmallocCREF[ptr] THEN NoLifeLibmallocCREF[i] := NoLifeLibmallocCREF[i]-sz ; i := i+1 END ; NoLifeLibmallocCNPTR := NoLifeLibmallocCNPTR-sz ; NoLifeLibmallocCREF[ptr] := 0 ; NoLifeLibmallocCSIZE[ptr] := 0 END ; PROCEDURE initC ; VAR i : INTEGER ; BEGIN i := 1 ; WHILE i <= 10240 DO BEGIN NoLifeLibmallocCMEM[i] := 'a' ; NoLifeLibmallocCREF[i] := 0 ; NoLifeLibmallocCSIZE[i] := 0 ; i := i+1 END ; NoLifeLibmallocCNPTR := 1 END ; FUNCTION mallocI ( size : INTEGER ) : INTEGER ; BEGIN RETURN callocI(size,1) END ; FUNCTION callocI ( num,size : INTEGER ) : INTEGER ; VAR sz,ptr,i : INTEGER ; BEGIN sz := num * size ; ptr := NoLifeLibmallocINPTR ; IF sz < 1 OR ptr+sz-1 > 10240 THEN RETURN 0 ; NoLifeLibmallocINPTR := NoLifeLibmallocINPTR+sz ; i := 1 ; WHILE NoLifeLibmallocISIZE[i] > 0 DO i := i+1 ; NoLifeLibmallocISIZE[i] := sz ; NoLifeLibmallocIREF[i] := ptr ; RETURN i END ; FUNCTION reallocI ( ptr,size : INTEGER ) : INTEGER ; VAR nptr : INTEGER ; BEGIN nptr := mallocI(size); IF nptr THEN BEGIN IF size < NoLifeLibmallocISIZE[ptr] THEN memcpyI(nptr,ptr,size) ELSE memcpyI(nptr,ptr,NoLifeLibmallocISIZE[ptr]) ; freeI(ptr) ; RETURN nptr END ELSE RETURN 0 END ; FUNCTION setheapI ( ptr,off,val : INTEGER ) : INTEGER ; BEGIN IF ptr < 0 OR ptr > 10240 OR off >= NoLifeLibmallocISIZE[ptr] THEN RETURN 0 ELSE BEGIN NoLifeLibmallocIMEM[NoLifeLibmallocIREF[ptr]+off] := val ; RETURN NoLifeLibmallocIMEM[NoLifeLibmallocIREF[ptr]+off] END END ; FUNCTION getheapI ( ptr,off : INTEGER ) : INTEGER ; BEGIN IF ptr < 0 OR ptr > 10240 OR off >= NoLifeLibmallocISIZE[ptr] THEN RETURN 0 ELSE RETURN NoLifeLibmallocIMEM[NoLifeLibmallocIREF[ptr]+off] END ; FUNCTION memcpyI ( dst,src,size : INTEGER ) : INTEGER ; VAR i,sz : INTEGER ; BEGIN IF size < 1 THEN RETURN dst ; IF dst < 1 OR dst > 10240 OR NoLifeLibmallocISIZE[dst] < 1 THEN RETURN dst ; IF src < 1 OR src > 10240 OR NoLifeLibmallocISIZE[src] < 1 THEN RETURN dst ; sz := size ; IF sz > NoLifeLibmallocISIZE[dst] THEN sz := NoLifeLibmallocISIZE[dst] ; IF sz > NoLifeLibmallocISIZE[src] THEN sz := NoLifeLibmallocISIZE[src] ; i := 0 ; WHILE i < sz DO BEGIN setheapI(dst,i,getheapI(src,i)) ; i := i+1 END ; RETURN dst END ; PROCEDURE freeI ( ptr : INTEGER ) ; VAR i,sz : INTEGER ; BEGIN IF ptr < 1 OR ptr > 10240 OR NoLifeLibmallocISIZE[ptr] < 1 THEN RETURN 0 ; sz := NoLifeLibmallocISIZE[ptr] ; i := NoLifeLibmallocIREF[ptr] ; WHILE i < NoLifeLibmallocINPTR-sz DO BEGIN NoLifeLibmallocIMEM[i] := NoLifeLibmallocIMEM[i+sz] ; i := i+1 END ; i := 1 ; WHILE i < 10240 DO BEGIN IF NoLifeLibmallocIREF[i] > NoLifeLibmallocIREF[ptr] THEN NoLifeLibmallocIREF[i] := NoLifeLibmallocIREF[i]-sz ; i := i+1 END ; NoLifeLibmallocINPTR := NoLifeLibmallocINPTR-sz ; NoLifeLibmallocIREF[ptr] := 0 ; NoLifeLibmallocISIZE[ptr] := 0 END ; PROCEDURE initI ; VAR i : INTEGER ; BEGIN i := 1 ; WHILE i <= 10240 DO BEGIN NoLifeLibmallocIMEM[i] := 'a' ; NoLifeLibmallocIREF[i] := 0 ; NoLifeLibmallocISIZE[i] := 0 ; i := i+1 END ; NoLifeLibmallocINPTR := 1 END ; FUNCTION mallocF ( size : INTEGER ) : INTEGER ; BEGIN RETURN callocF(size,1) END ; FUNCTION callocF ( num,size : INTEGER ) : INTEGER ; VAR sz,ptr,i : INTEGER ; BEGIN sz := num * size ; ptr := NoLifeLibmallocFNPTR ; IF sz < 1 OR ptr+sz-1 > 10240 THEN RETURN 0 ; NoLifeLibmallocFNPTR := NoLifeLibmallocFNPTR+sz ; i := 1 ; WHILE NoLifeLibmallocFSIZE[i] > 0 DO i := i+1 ; NoLifeLibmallocFSIZE[i] := sz ; NoLifeLibmallocFREF[i] := ptr ; RETURN i END ; FUNCTION reallocF ( ptr,size : INTEGER ) : INTEGER ; VAR nptr : INTEGER ; BEGIN nptr := mallocF(size); IF nptr THEN BEGIN IF size < NoLifeLibmallocFSIZE[ptr] THEN memcpyF(nptr,ptr,size) ELSE memcpyF(nptr,ptr,NoLifeLibmallocFSIZE[ptr]) ; freeF(ptr) ; RETURN nptr END ELSE RETURN 0 END ; FUNCTION setheapF ( ptr,off : INTEGER ; val : FLOAT ) : FLOAT ; BEGIN IF ptr < 0 OR ptr > 10240 OR off >= NoLifeLibmallocFSIZE[ptr] THEN RETURN 0.0 ELSE BEGIN NoLifeLibmallocFMEM[NoLifeLibmallocFREF[ptr]+off] := val ; RETURN NoLifeLibmallocFMEM[NoLifeLibmallocFREF[ptr]+off] END END ; FUNCTION getheapF ( ptr,off : INTEGER ) : FLOAT ; BEGIN IF ptr < 0 OR ptr > 10240 OR off >= NoLifeLibmallocFSIZE[ptr] THEN RETURN 0.0 ELSE RETURN NoLifeLibmallocFMEM[NoLifeLibmallocFREF[ptr]+off] END ; FUNCTION memcpyF ( dst,src,size : INTEGER ) : INTEGER ; VAR i,sz : INTEGER ; BEGIN IF size < 1 THEN RETURN dst ; IF dst < 1 OR dst > 10240 OR NoLifeLibmallocFSIZE[dst] < 1 THEN RETURN dst ; IF src < 1 OR src > 10240 OR NoLifeLibmallocFSIZE[src] < 1 THEN RETURN dst ; sz := size ; IF sz > NoLifeLibmallocFSIZE[dst] THEN sz := NoLifeLibmallocFSIZE[dst] ; IF sz > NoLifeLibmallocFSIZE[src] THEN sz := NoLifeLibmallocFSIZE[src] ; i := 0 ; WHILE i < sz DO BEGIN setheapF(dst,i,getheapF(src,i)) ; i := i+1 END ; RETURN dst END ; PROCEDURE freeF ( ptr : INTEGER ) ; VAR i,sz : INTEGER ; BEGIN IF ptr < 1 OR ptr > 10240 OR NoLifeLibmallocFSIZE[ptr] < 1 THEN RETURN 0 ; sz := NoLifeLibmallocFSIZE[ptr] ; i := NoLifeLibmallocFREF[ptr] ; WHILE i < NoLifeLibmallocFNPTR-sz DO BEGIN NoLifeLibmallocFMEM[i] := NoLifeLibmallocFMEM[i+sz] ; i := i+1 END ; i := 1 ; WHILE i < 10240 DO BEGIN IF NoLifeLibmallocFREF[i] > NoLifeLibmallocFREF[ptr] THEN NoLifeLibmallocFREF[i] := NoLifeLibmallocFREF[i]-sz ; i := i+1 END ; NoLifeLibmallocFNPTR := NoLifeLibmallocFNPTR-sz ; NoLifeLibmallocFREF[ptr] := 0 ; NoLifeLibmallocFSIZE[ptr] := 0 END ; PROCEDURE initF ; VAR i : INTEGER ; BEGIN i := 1 ; WHILE i <= 10240 DO BEGIN NoLifeLibmallocFMEM[i] := 'a' ; NoLifeLibmallocFREF[i] := 0 ; NoLifeLibmallocFSIZE[i] := 0 ; i := i+1 END ; NoLifeLibmallocFNPTR := 1 END ; FUNCTION newNode : INTEGER ; VAR ret : INTEGER ; BEGIN ret := callocI(3,1) ; IF ret THEN setheapI(ret,1,mallocF(1)) ; RETURN ret END ; PROCEDURE freeNode ( node : INTEGER ) ; BEGIN freeF(getheapI(node,1)) ; freeI(node) END ; FUNCTION setnext ( node,next : INTEGER ) : INTEGER ; BEGIN setheapI(node,2,next) ; RETURN next(node) END ; FUNCTION next ( node : INTEGER ) : INTEGER ; BEGIN RETURN getheapI(node,2) END ; FUNCTION setprev ( node,prev : INTEGER ) : INTEGER ; BEGIN setheapI(node,0,next) ; RETURN next(node) END ; FUNCTION prev ( node : INTEGER ) : INTEGER ; BEGIN RETURN getheapI(node,0) END ; FUNCTION setval ( node : INTEGER ; val : FLOAT ) : FLOAT ; BEGIN setheapF(getheapI(node,1),0,val) ; RETURN val(node) END ; FUNCTION val ( node : INTEGER ) : FLOAT ; BEGIN RETURN getheapF(getheapI(node,1),0) END ; FUNCTION prependNode ( node,list : INTEGER ) : INTEGER ; BEGIN setnext(node,list) ; setprev(list,node) ; IF next(node) = list THEN RETURN node ELSE RETURN list END ; FUNCTION appendNode ( node,list : INTEGER ) : INTEGER ; VAR i : INTEGER ; BEGIN IF list < 1 THEN RETURN node ; i := list ; WHILE next(i) <> 0 DO i := next(i) ; setnext(i,node) ; setprev(node,i) ; RETURN list END ; FUNCTION insertNode ( node,list,index : INTEGER ) : INTEGER ; VAR i,ptr : INTEGER ; BEGIN IF index < 1 THEN RETURN prependNode(node,list) ; IF list < 1 THEN RETURN node ; ptr := list ; i := 1 ; WHILE i <> index AND next(ptr) <> 0 DO BEGIN ptr := next(ptr) ; i := i+1 END ; setprev(next(ptr),node) ; setnext(node,next(ptr)) ; setprev(node,ptr) ; setnext(ptr,node) ; RETURN list END ; FUNCTION removeNode ( node : INTEGER ) : INTEGER ; VAR ptr : INTEGER ; BEGIN setnext(prev(node),next(node)) ; setprev(next(node),prev(node)) ; setnext(node,0) ; setprev(node,0) ; RETURN node END ; FUNCTION removeNodeAt ( list,index : INTEGER ) : INTEGER ; VAR i,ptr : INTEGER ; BEGIN IF index < 1 OR list < 1 THEN RETURN list ; ptr := list ; i := 1 ; WHILE i <> index AND next(ptr) <> 0 DO BEGIN ptr := next(ptr) ; i := i+1 END ; RETURN removeNode(ptr) END ; BEGIN WRITE ( 'TODO: Write a program using the linked-list functions...' ) END