[comp.sys.ibm.pc] >expand, unexpand for dos

m_hanft@msn.rmi.de (Matthias Hanft) (09/07/89)

>
> jbjones@marlin.NOSC.MIL (John B. Jones) writes:
>
> Does anyone have a DOS utility similar to the Un*x EXPAND and UNEXPAND?
> Expand converts tabs in an ascii document to equivalent spaces.
>

  Although I don't know Unix's EXPAND, I have written a short Turbo
  Pascal (3.0) utility which expands TABs into SPACEs.

  Since the program is only 79 lines long, I hope I may post it into
  this newsgroup. It handles lines longer than 255 characters and
  takes care of embedded backspaces.

  Matthias Hanft (m_hanft@msn.rmi.de)

--- cut here---
(*$C-,G512,P512,U-*)
program tab; (* converts tabs to equivalent spaces *)
  type longstring=record
                    len:integer;
                    data:array[1..16384] of char
                  end; (* longstring *)
  var line,space:longstring;
      p,i,real_pos:integer;

  function pos(c:char;s:longstring):integer;
    var i:integer;
    begin (* pos *)
      for i:=1 to s.len do begin
        if s.data[i]=c then begin
          pos:=i;
          exit
        end (* if s.data[i]=c *)
      end; (* for i:=1 to s.len *)
      pos:=0
    end; (* pos *)

  procedure delete(var s:longstring;p,l:integer);
    var i:integer;
    begin (* delete *)
      if p>s.len then exit; (* would delete behind end of string *)
      for i:=1 to l do begin
        s.len:=pred(s.len); (* one char shorter in any case *)
        if p>s.len then exit; (* nothing more left *)
        move(s.data[succ(p)],s.data[p],succ(s.len-p))
      end (* for i:=1 to l do begin *)
    end; (* delete *)

  procedure insert(si:longstring;var s:longstring;p:integer);
    begin (* insert *)
      if si.len=0 then exit;
      move(s.data[p],s.data[p+si.len],succ(s.len-p));
      move(si.data,s.data[p],si.len);
      s.len:=s.len+si.len
    end; (* insert *)

  begin (* tab *)
    space.len:=1;
    space.data[1]:=' ';
    while not eof do begin
      with line do begin
        len:=0;
        repeat
          len:=succ(len);
          if eof then
            data[len]:=^J
          else (* -> not eof *)
            read(data[len])
        until data[len]=^J;
        while ((data[len]=^M) or (data[len]=^J)) and (len>0) do
          len:=pred(len)
      end; (* with line *)
      p:=pos(^I,line);
      while p>0 do begin
        real_pos:=1;
        for i:=1 to p do
          if line.data[i]=^H then
            real_pos:=pred(real_pos)
          else (* -> line.data[i]<>^H *)
            real_pos:=succ(real_pos);
        delete(line,p,1);
        insert(space,line,p);
        p:=succ(p);
        while (pred(real_pos) and 7)<>0 do begin
          insert(space,line,p);
          p:=succ(p);
          real_pos:=succ(real_pos)
        end; (* while (pred(real_pos) and 7)<>0 *)
        p:=pos(^I,line)
      end; (* while p>0 *)
      for p:=1 to line.len do
        write(line.data[p]);
      writeln
    end (* while not eof *)
  end. (* tab *)
--- cut here ---