home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / ECO30603.ZIP / ECO30603.LZH / ECOLIBII / eco_env.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-04-05  |  11.0 KB  |  483 lines

  1. {$R-,S-,V-,I-,B-,F-}
  2.  
  3. unit eco_env;
  4.  
  5. interface
  6.  
  7. type
  8.   envarray = array[0..32767] of char;
  9.   envarrayptr = ^envarray;
  10.   envrec = record
  11.     envseg : word;              {segment of the environment}
  12.     envlen : word;              {usable length of the environment}
  13.     envptr : pointer;           {nil except when allocated on heap}
  14.   end;
  15.  
  16.  
  17.   procedure masterenv(var env : envrec);
  18.   {-return master environment record}
  19.  
  20.   procedure currentenv(var env : envrec);
  21.   {-return current environment record}
  22.  
  23.   procedure newenv(var env : envrec; size : word);
  24.   {-allocate a new environment on the heap}
  25.  
  26.   procedure disposeenv(var env : envrec);
  27.   {-deallocate an environment previously allocated on heap}
  28.  
  29.   procedure setcurrentenv(env : envrec);
  30.   {-specify a different environment for the current program}
  31.  
  32.   procedure copyenv(src, dest : envrec);
  33.   {-copy contents of src environment to dest environment}
  34.  
  35.   function envfree(env : envrec) : word;
  36.   {-return bytes free in environment}
  37.  
  38.   function getenvstr(env : envrec; search : string) : string;
  39.   {-return a string from the environment}
  40.  
  41.   function setenvstr(env : envrec; search, value : string) : boolean;
  42.   {-set environment string, returning true if successful}
  43.  
  44.   procedure dumpenv(env : envrec);
  45.   {-dump the environment to stdout}
  46.  
  47.   function programstr : string;
  48.   {-return the complete path to the current program, '' if dos < 3.0}
  49.  
  50.   function setprogramstr(env : envrec; path : string) : boolean;
  51.   {-add a program name to the end of an environment if sufficient space}
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59. implementation
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67. type
  68.   so = record
  69.     o : word;
  70.     s : word;
  71.   end;
  72.  
  73.  
  74.   procedure clearenvrec(var env : envrec);
  75.   begin
  76.     fillchar(env, sizeof(env), 0);
  77.   end;
  78.  
  79.  
  80.   procedure masterenv(var env : envrec);
  81.   var
  82.     owner : word;
  83.     mcb : word;
  84.     eseg : word;
  85.     done : boolean;
  86.  
  87.   begin
  88.     with env do begin
  89.       clearenvrec(env);
  90.  
  91.       {interrupt $2e points into command.com}
  92.       owner := memw[0:(2+4*$2e)];
  93.  
  94.       {mcb points to memory control block for command}
  95.       mcb := owner-1;
  96.       if (mem[mcb:0] <> byte('M')) or (memw[mcb:1] <> owner) then
  97.         exit;
  98.  
  99.       {read segment of environment from psp of command}
  100.       eseg := memw[owner:$2c];
  101.  
  102.       {earlier versions of dos don't store environment segment there}
  103.       if eseg = 0 then begin
  104.         {master environment is next block past command}
  105.         mcb := owner+memw[mcb:3];
  106.         if (mem[mcb:0] <> byte('M')) or (memw[mcb:1] <> owner) then
  107.           {not the right memory control block}
  108.           exit;
  109.         eseg := mcb+1;
  110.       end else
  111.         mcb := eseg-1;
  112.  
  113.       {return segment and length of environment}
  114.       envseg := eseg;
  115.       envlen := memw[mcb:3] shl 4;
  116.     end;
  117.   end;
  118.  
  119.  
  120.   procedure currentenv(var env : envrec);
  121.   var
  122.     eseg : word;
  123.     mcb : word;
  124.   begin
  125.     with env do begin
  126.       clearenvrec(env);
  127.       eseg := memw[prefixseg:$2c];
  128.       mcb := eseg-1;
  129.       if (mem[mcb:0] <> byte('M')) or (memw[mcb:1] <> prefixseg) then
  130.         exit;
  131.       envseg := eseg;
  132.       envlen := memw[mcb:3] shl 4;
  133.     end;
  134.   end;
  135.  
  136.  
  137.   procedure newenv(var env : envrec; size : word);
  138.   var mcb : word;
  139.   begin
  140.     with env do if maxavail < size+31 then
  141.       {insufficient space}
  142.       clearenvrec(env)
  143.     else begin
  144.       {31 extra bytes for paragraph alignment, fake mcb}
  145.       getmem(envptr, size+31);
  146.       envseg := so(envptr).s+1;
  147.       if so(envptr).o <> 0 then
  148.         inc(envseg);
  149.       envlen := size;
  150.       {fill it with nulls}
  151.       fillchar(envptr^, size+31, 0);
  152.       {make a fake mcb below it}
  153.       mcb := envseg-1;
  154.       mem[mcb:0] := byte('M');
  155.       memw[mcb:1] := prefixseg;
  156.       memw[mcb:3] := (size+15) shr 4;
  157.     end;
  158.   end;
  159.  
  160.  
  161.   procedure disposeenv(var env : envrec);
  162.   begin
  163.     with env do if envptr <> nil then begin
  164.       freemem(envptr, envlen+31);
  165.       clearenvrec(env);
  166.     end;
  167.   end;
  168.  
  169.  
  170.   procedure setcurrentenv(env : envrec);
  171.   begin
  172.     with env do if envseg <> 0 then memw[prefixseg:$2c] := envseg;
  173.   end;
  174.  
  175.  
  176.   procedure copyenv(src, dest : envrec);
  177.   var
  178.     size : word;
  179.     sptr : envarrayptr;
  180.     dptr : envarrayptr;
  181.  
  182.   begin
  183.     if (src.envseg = 0) or (dest.envseg = 0) then exit;
  184.     if src.envlen <= dest.envlen then size := src.envlen else
  185.       size := dest.envlen-1;
  186.  
  187.     sptr := ptr(src.envseg, 0);
  188.     dptr := ptr(dest.envseg, 0);
  189.     move(sptr^, dptr^, size);
  190.     fillchar(dptr^[size], dest.envlen-size, 0);
  191.   end;
  192.  
  193.  
  194.   procedure skipasciiz(eptr : envarrayptr; var eofs : word);
  195.   begin
  196.     while eptr^[eofs] <> #0 do inc(eofs);
  197.   end;
  198.  
  199.  
  200.   function envnext(eptr : envarrayptr) : word;
  201.   var eofs : word;
  202.   begin
  203.     eofs := 0;
  204.     if eptr <> nil then begin
  205.       while eptr^[eofs] <> #0 do begin
  206.         skipasciiz(eptr, eofs);
  207.         inc(eofs);
  208.       end;
  209.     end;
  210.     envnext := eofs;
  211.   end;
  212.  
  213.  
  214.   function envfree(env : envrec) : word;
  215.   begin
  216.     with env do if (
  217.       envseg <> 0
  218.     ) then envfree := envlen-envnext(ptr(envseg, 0))-1 else envfree := 0;
  219.   end;
  220.  
  221.  
  222.   function stupcase(s : string) : string;
  223.   var
  224.     slen : byte absolute s;
  225.     i : integer;
  226.  
  227.   begin
  228.     for i := 1 to slen do s[i] := upcase(s[i]);
  229.     stupcase := s;
  230.   end;
  231.  
  232.  
  233.   function searchenv(
  234.     eptr: envarrayptr; var search: string
  235.   ) : word;
  236.   {
  237.     Return the position of Search in environment, or $FFFF if not found.
  238.     Prior to calling SearchEnv, assure EPtr is not nil, Search is not empty
  239.   }
  240.   var
  241.     slen : byte absolute search;
  242.     eofs : word;
  243.     mofs : word;
  244.     sofs : word;
  245.     match : boolean;
  246.  
  247.   begin
  248.     search := stupcase(search);
  249.  
  250.     {assure search string ends in =}
  251.     if search[slen] <> '=' then begin
  252.       inc(slen);
  253.       search[slen] := '=';
  254.     end;
  255.  
  256.     eofs := 0;
  257.     while eptr^[eofs] <> #0 do begin
  258.       {at the start of a new environment element}
  259.       sofs := 1;
  260.       mofs := eofs;
  261.       repeat
  262.         match := (eptr^[eofs] = search[sofs]);
  263.         if match then begin
  264.           inc(eofs);
  265.           inc(sofs);
  266.         end;
  267.       until not match or (sofs > slen);
  268.  
  269.       if match then begin
  270.         {found a match, return index of start of match}
  271.         searchenv := mofs;
  272.         exit;
  273.       end;
  274.       {skip to end of this environment string}
  275.       skipasciiz(eptr, eofs);
  276.       {skip to start of next environment string}
  277.       inc(eofs);
  278.     end;
  279.     {no match}
  280.     searchenv := $ffff;
  281.   end;
  282.  
  283.  
  284.   procedure getasciiz(eptr : envarrayptr; var eofs : word; var estr : string);
  285.   var elen : byte absolute estr;
  286.   begin
  287.     elen := 0;
  288.     while (eptr^[eofs] <> #0) and (elen < 255) do begin
  289.       inc(elen);
  290.       estr[elen] := eptr^[eofs];
  291.       inc(eofs);
  292.     end;
  293.   end;
  294.  
  295.  
  296.   function getenvstr(env : envrec; search : string) : string;
  297.   var
  298.     slen : byte absolute search;
  299.     eptr : envarrayptr;
  300.     eofs : word;
  301.     estr : string;
  302.     elen : byte absolute estr;
  303.  
  304.   begin
  305.     with env do begin
  306.       elen := 0;
  307.       if (envseg <> 0) and (slen <> 0) then begin
  308.         {find the search string}
  309.         eptr := ptr(envseg, 0);
  310.         eofs := searchenv(eptr, search);
  311.         if eofs <> $ffff then begin
  312.           {skip over the search string}
  313.           inc(eofs, slen);
  314.           {build the result string}
  315.           getasciiz(eptr, eofs, estr);
  316.         end;
  317.       end;
  318.       getenvstr := estr;
  319.     end;
  320.   end;
  321.  
  322.  
  323.   function setenvstr(env : envrec; search, value : string) : boolean;
  324.   var
  325.     slen : byte absolute search;
  326.     vlen : byte absolute value;
  327.     eptr : envarrayptr;
  328.     enext : word;
  329.     eofs : word;
  330.     mofs : word;
  331.     oldlen : word;
  332.     newlen : word;
  333.     nullen : word;
  334.  
  335.   begin
  336.     with env do begin
  337.       setenvstr := false;
  338.       if (envseg = 0) or (slen = 0) then exit;
  339.       eptr := ptr(envseg, 0);
  340.  
  341.       {find the search string}
  342.       eofs := searchenv(eptr, search);
  343.  
  344.       {get the index of the next available environment location}
  345.       enext := envnext(eptr);
  346.  
  347.       {get total length of new environment string}
  348.       newlen := slen+vlen;
  349.  
  350.       if eofs <> $ffff then begin
  351.         {search string exists}
  352.         mofs := eofs+slen;
  353.         {scan to end of string}
  354.         skipasciiz(eptr, mofs);
  355.         oldlen := mofs-eofs;
  356.         {no extra nulls to add}
  357.         nullen := 0;
  358.       end else begin
  359.         oldlen := 0;
  360.         {one extra null to add}
  361.         nullen := 1;
  362.       end;
  363.  
  364.       if vlen <> 0 then
  365.         {not a pure deletion}
  366.         if enext+newlen+nullen >= envlen+oldlen then
  367.           {new string won't fit}
  368.           exit;
  369.  
  370.       if oldlen <> 0 then begin
  371.         {overwrite previous environment string}
  372.         move(eptr^[mofs+1], eptr^[eofs], enext-mofs-1);
  373.         {more space free now}
  374.         dec(enext, oldlen+1);
  375.       end;
  376.  
  377.       {append new string}
  378.       if vlen <> 0 then begin
  379.         move(search[1], eptr^[enext], slen);
  380.         inc(enext, slen);
  381.         move(value[1], eptr^[enext], vlen);
  382.         inc(enext, vlen);
  383.       end;
  384.  
  385.       {clear out the rest of the environment}
  386.       fillchar(eptr^[enext], envlen-enext, 0);
  387.  
  388.       setenvstr := true;
  389.     end;
  390.   end;
  391.  
  392.  
  393.   procedure dumpenv(env : envrec);
  394.   var
  395.     eofs : word;
  396.     eptr : envarrayptr;
  397.  
  398.   begin
  399.     with env do begin
  400.       if envseg = 0 then exit;
  401.       eptr := ptr(envseg, 0);
  402.       eofs := 0;
  403.       writeln;
  404.       while eptr^[eofs] <> #0 do begin
  405.         while eptr^[eofs] <> #0 do begin
  406.           write(eptr^[eofs]);
  407.           inc(eofs);
  408.         end;
  409.         writeln;
  410.         inc(eofs);
  411.       end;
  412.       writeln('Bytes free: ', envfree(env));
  413.     end;
  414.   end;
  415.  
  416.  
  417.   function dosversion : word;
  418.   inline(
  419.     $b4/$30/  {mov ah,$30}
  420.     $cd/$21/  {int $21}
  421.     $86/$c4   {xchg ah,al}
  422.   );
  423.  
  424.  
  425.   function programstr : string;
  426.   var
  427.     eofs : word;
  428.     env : envrec;
  429.     eptr : envarrayptr;
  430.     pstr : string;
  431.  
  432.   begin
  433.     programstr := '';
  434.     if dosversion < $0300 then exit;
  435.     currentenv(env);
  436.     if env.envseg = 0 then exit;
  437.     {find the end of the current environment}
  438.     eptr := ptr(env.envseg, 0);
  439.     eofs := envnext(eptr);
  440.     {skip to start of path name}
  441.     inc(eofs, 3);
  442.     {collect the path name}
  443.     getasciiz(eptr, eofs, pstr);
  444.     programstr := pstr;
  445.   end;
  446.  
  447.  
  448.   function setprogramstr(env : envrec; path : string) : boolean;
  449.   var
  450.     plen : byte absolute path;
  451.     eofs : word;
  452.     numb : word;
  453.     eptr : envarrayptr;
  454.  
  455.   begin
  456.     setprogramstr := false;
  457.     with env do begin
  458.       if envseg = 0 then exit;
  459.       {find the end of the current environment}
  460.       eptr := ptr(envseg, 0);
  461.       eofs := envnext(eptr);
  462.       {assure space for path}
  463.       if envlen < plen+eofs+4 then exit;
  464.       {put in the count field}
  465.       inc(eofs);
  466.       numb := 1;
  467.       move(numb, eptr^[eofs], 2);
  468.       {skip to start of path name}
  469.       inc(eofs, 2);
  470.       {move the path into place}
  471.       path := stupcase(path);
  472.       move(path[1], eptr^[eofs], plen);
  473.       {null terminate}
  474.       inc(eofs, plen);
  475.       eptr^[eofs] := #0;
  476.       setprogramstr := true;
  477.     end;
  478.   end;
  479.  
  480.  
  481. end.
  482.  
  483.