Linked Lists in Batch Files

A few days ago (as this is being written), I discovered that it is possible to create and manipulate linked lists of environment variables in batch language. Since this concept is so new to me, I really can't say much about its uses.

A linked list is a list of items organized through pointers - each list item contains a pointer to the next item in the list. Doubly linked lists contain pointers to both the previous and following items. The items do not have to be placed in any particular order in memory, since the address, or in this case, the name, of the adjoining items is contained in each item.

The initial proof-of-concept code consists of these three files:


 MKLST.BAT
  @echo off
  set start=x001 head start
  set x001=x002 start 001
  set x002=x003 x001 002
  set x003=stop x002 003
  set stop=tail x003 stop
  set current=start
  :end
which generates a doubly linked list by brute force (and sets the current item pointer to point to the head of the list),

 NEXT.BAT
  @echo off
  %1 %2
  if "%current%" == "" goto start
  %0 goto pass2 %current%
  :start
  %0 goto pass2 start
  :pass2
  if "%3" == "" goto end
  echo set current=%%%3%% > }{.bat
  call }{
  :end
which changes the pointer to the current item to point to the next item, and

 WALKUP.BAT
  @echo off
  %1 %2
  :loop
  %0 goto pass2 %current%
  :pass2
  if %3 == tail goto end
  call next
  echo %current%
  %0
  :end
which walks up the list from head to tail.

Obviously, these could be combined into one program, but at this stage in the development of the concept, it is better that they remain separate.

In the above test list, the structure is item_name=next_item previous_item data but there is no reason to consider that to be any sort of limit or restriction. The data could just as well be code to be executed by an interpreter or an item in another list (or the name of an item in any list).

At this point, I have only one reasonable use for linked lists in mind: to provide a solution to the general problem of deleting or replacing batch files that are nominally executing at the time. There is supposed to be a solution to the problem of having a batch file delete itself, but it's difficult to implement, unreliable, and inapplicable to recursive programs - and I have forgotten what it is, and will ignore it here.

To do this, we must have at least one auxiliary file: the interpreter for the list based language that will do the work. This program is one that counts as a general program, to be kept available at all times, rather than a part of the batch file in question, and therefore the inability to delete it without generating an error is not part of the problem at hand.

The idea is that we create a list based language, which I will name BLISP, for Batch LISt Processor. For the purpose at hand, it need only be able to execute a small subset of the batch language, and can therefore be very simple. The interpreter is based on WALKUP.BAT and NEXT.BAT:


 BLISP1.BAT
  @echo off
  %1 %2
  :loop
  %0 goto pass2 %IP%
  :pass2
  if exist %TFILE%.bat del %TFILE%.bat
  if %3 == tail goto end
  echo set INST=%%%3%% > %TFILE%.bat
  echo %0 goto pass3 %%INST%% >> %TFILE%.bat
  %TFILE%
  :pass3
  set IP=%3
  %4 %5 %6 %7 %8 %9
  goto loop
  :end
Note that the current item pointer has been renamed IP, for Instruction Pointer, and that the name of the transient batch file has been made variable, so that each batch file using the interpreter can avoid conflict with other batch files running in different DOS sessions but in the same directory. Note that this version does not delete the program from memory when it finishes.

The batch file to test the concept will be one that makes a copy of itself, transfer control to the copy, and deletes the copy. It puts DIR x%0.bat commands before and after the deletion to demonstrate the deletion. It also uses a singly linked list.


 TEST.BAT
  @echo off
  if exist xtest.bat goto iscopy
  copy %0.bat x%0.bat
  x%0.bat
  :iscopy
  set t001=t002 dir xtest.bat
  set t002=t003 del xtest.bat
  set t003=tail dir xtest.bat
  set IP=t001
  set TFILE=}{t
  blisp1
  echo this line never executes
  :end
There is, naturally enough, an easier way to accomplish the task of making a file delete itself, given that an additional, permanent utility file can exist:

 TEST.BAT
  @echo off
  dobat del test.bat
  :end
where DOBAT.BAT is simply

 @%1 %2 %3 %4 %5 %6 %7 %8 %9
and has numerous other uses as well. However, the object here is to explore the concept of linked lists and their applications. Note that DOBAT cannot handle multiple commands.
  ** Copyright 1995, Ted Davis - all rights reserved ** 

Input and feedback from readers are welcome. NOTE: the subject of the message must contain the word "batch" for the message to get past the spam filter.

Back to the Table of Contents page

Back to my personal links page - back to my home page