////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2001-2026 Alexey Kuryakin daqgroup@mail.ru under MIT license //
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// This file is part of the CRW-DAQ project by DaqGroup - component CRWLIB.   //
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Purpose:                                                                   //
// This unit implement ParamStrList - list of system objects.                 //
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// History:                                                                   //
// 20250808 - Created by A.K.                                                 //
////////////////////////////////////////////////////////////////////////////////

unit _crw_prmstrlst; // ParamStrListOf.

{$I _crw_sysdef.inc}

{$I _crw_sysmode.inc}

interface

uses
 //////////////////////////////////////////////////////
 {$I _crw_uses_first.inc} // NB: MUST BE FIRST USES !!!
 //////////////////////////////////////////////////////
 sysutils, classes, math,
 Graphics, Forms,
 _crw_alloc, _crw_rtc, _crw_fpu, _crw_ef, _crw_fifo,
 _crw_str, _crw_fio, _crw_proc, _crw_polling, _crw_task,
 _crw_spcfld, _crw_wmctrl, _crw_hl, _crw_sysid, _crw_netif,
 _crw_colors, _crw_uri, _crw_serio, _crw_environ, _crw_uac,
 _crw_mimeapps, _crw_daqtags, _crw_curves, _crw_mimeglob,
 _crw_appforms;

 {
 -------------------------------------------------------------------------------
 ParamStrListOf(arg) и ParamStr('ListOf '+arg) - получить список параметров из
 запрошенной системной таблицы (например, pids - список работающих процессов).
 -------------------------------------------------------------------------------
 Вызов  Таблица     Ключи where key=value  Комментарий
 -------------------------------------------------------------------------------
 ListOf tables      (name)                 Список доступных для чтения таблиц
 ListOf keys        (name)                 Список ключей для таблицы (name)
 ListOf pids        (pid,ppid,name)        Список процессов PID,PPID,PRIO,NAME
 ListOf processes   (pid,ppid,name)        Список процессов PID,PPID,PRIO,NAME,STATE,THREADS,CMDLINE
 ListOf modules     (pid)                  Список модулей для процесса PID
 ListOf windows     (pid,class,title)      Список окон на Рабочем Столе
 ListOf threads     (name)                 Список потоков Polling
 ListOf tasks       (tid,pid)              Список задач task_xxx
 ListOf colors      (name,code,format)     Список цветов с выборкой по коду/цвету
 ListOf netifs      (mode)                 Список сетевых интерфейсов
 ListOf specfolders (name)                 Список специальных именованных каталогов
 ListOf services    (name,port,protocol)   Список сетевых сервисов (портов tcp,udp)
 ListOf comports    (name,path)            Список COM-портов
 ListOf users       (name)                 Список пользователей (users)
 ListOf hosts       (name)                 Список известных компьютеров (hosts)
 ListOf groups      (name)                 Список членства в группах (groups)
 ListOf environs    (name)                 Список переменных окружения
 ListOf ftypes      (name)                 Список ftype(Windows)/mime(Unix)
 ListOf assocs      (name)                 Список assoc(Windows/Unix)
 ListOf daq_tags    (name)                 Список тегов DAQ системы
 ListOf daq_curves  (name)                 Список кривых DAQ системы
 ListOf daq_devices (name,family,model)    Список устройств DAQ системы
 ListOf daq_windows (name,type,kind)       Список окон DAQ системы
 ListOf sections    (name)                 Список [секций] в файле name
 -------------------------------------------------------------------------------
 Например:
  s:=paramstr('ListOf pids where name=firebird');
  s:=paramstr('ListOf colors where code=$FF0000');
 -------------------------------------------------------------------------------
 }
function ParamStrListOf(const arg:LongString):LongString;

implementation

uses
 _crw_daqdev,
 _crw_daqsys;

//////////////////////////////////////////
// Private Hasher for fast string parsing.
//////////////////////////////////////////
type
 TStringIdentifier = (
  sid_Unknown,
  sid_Pids,
  sid_Processes,
  sid_Modules,
  sid_Windows,
  sid_Threads,
  sid_Tasks,
  sid_Colors,
  sid_Netifs,
  sid_Specfolders,
  sid_Services,
  sid_Comports,
  sid_Users,
  sid_Hosts,
  sid_Groups,
  sid_Environs,
  sid_Ftypes,
  sid_Assocs,
  sid_Daq_Tags,
  sid_Daq_Curves,
  sid_Daq_Devices,
  sid_Daq_Windows,
  sid_Sections,
  sid_Keys,
  sid_Tables,
  sid_Unused
 );

const
 Hasher:THashList=nil;

procedure FreeHasher;
begin
 Kill(Hasher);
end;

procedure InitHasher;
 procedure AddSid(const key:LongString; sid:TStringIdentifier);
 begin
  Hasher.KeyedLinks[key]:=Ord(sid);
 end;
begin
 if (Hasher<>nil) then Exit;
 Hasher:=NewHashList(false,HashList_DefaultHasher);
 Hasher.Master:=@Hasher;
 ////////////////////////////////////////////
 // Hash List for fast strings identification
 ////////////////////////////////////////////
 AddSid( 'pids'                , sid_Pids);
 AddSid( 'processes'           , sid_Processes);
 AddSid( 'modules'             , sid_Modules);
 AddSid( 'windows'             , sid_Windows);
 AddSid( 'threads'             , sid_Threads);
 AddSid( 'tasks'               , sid_Tasks);
 AddSid( 'colors'              , sid_Colors);
 AddSid( 'netifs'              , sid_Netifs);
 AddSid( 'specfolders'         , sid_Specfolders);
 AddSid( 'services'            , sid_Services);
 AddSid( 'comports'            , sid_Comports);
 AddSid( 'users'               , sid_Users);
 AddSid( 'hosts'               , sid_Hosts);
 AddSid( 'groups'              , sid_Groups);
 AddSid( 'environs'            , sid_Environs);
 AddSid( 'ftypes'              , sid_Ftypes);
 AddSid( 'assocs'              , sid_Assocs);
 AddSid( 'daq_tags'            , sid_Daq_Tags);
 AddSid( 'daq_curves'          , sid_Daq_Curves);
 AddSid( 'daq_devices'         , sid_Daq_Devices);
 AddSid( 'daq_windows'         , sid_Daq_Windows);
 AddSid( 'sections'            , sid_Sections);
 AddSid( 'keys'                , sid_Keys);
 AddSid( 'tables'              , sid_Tables);
end;

function Identify(const key:LongString):TStringIdentifier;
var sid:Integer;
begin
 if (Hasher=nil) then InitHasher;
 sid:=Hasher.KeyedLinks[key];
 if (sid>=Ord(Low(TStringIdentifier))) and (sid<=Ord(High(TStringIdentifier)))
 then Result:=TStringIdentifier(sid)
 else Result:=sid_Unknown;
end;

 //////////////////////
 // List of any objects
 //////////////////////

function FetchCookie(const arg,key:LongString):LongString;
begin
 Result:=CookieScan(arg,key,Ord(','));
end;

function ListOf_pids(const arg:LongString; Detail:Boolean=False):LongString;
var pid,ppid:TPid; name:LongString; Flags:Integer;
begin
 Flags:=glops_Default;
 LiftFlags(Flags,glops_MaxInfo);
 name:=Trim(FetchCookie(arg,'name'));
 pid:=StrToIntDef(FetchCookie(arg,'pid'),0);
 ppid:=StrToIntDef(FetchCookie(arg,'ppid'),0);
 Result:=GetListOfProcesses(pid,ppid,name,Detail,Flags);
end;

function ListOf_modules(const arg:LongString):LongString;
var List:TStringList; pid:TPid;
begin
 Result:='';
 pid:=StrToIntDef(FetchCookie(arg,'pid'),GetCurrentProcessId);
 List:=GetListOfModules(TStringList.Create,pid);
 try
  Result:=List.Text;
 finally
  Kill(List);
 end;
end;

function ListOf_windows(const arg:LongString):LongString;
var pid:TPid; wClass,wTitle:LongString; mode:Integer;
begin
 Result:='';
 wClass:=FetchCookie(arg,'class');
 wTitle:=FetchCookie(arg,'title');
 pid:=StrToIntDef(FetchCookie(arg,'pid'),0);
 mode:=StrToIntDef(FetchCookie(arg,'mode'),0);
 Result:=wmctrl.ListWindows(pid,wClass,wTitle,mode);
end;

function ListOf_threads(const arg:LongString):LongString;
var List:TStringList; i:Integer; p:TPolling; name:LongString;
begin
 Result:='';
 List:=TStringList.Create;
 try
  name:=Trim(FetchCookie(arg,'name'));
  for i:=0 to FullPollingList.Count-1 do begin
   p:=TPolling(FullPollingList[i]);
   if TObject(p) is TPolling then begin
    if IsNonEmptyStr(name) and not SameText(name,p.Name) then continue;
    List.Add(Format(' %-32s = %4d, %s',[p.Name,p.Delay,GetPriorityName(p.Priority)]));
   end;
  end;
  Result:=List.Text;
 finally
  Kill(List);
 end;
end;

function ListOf_tasks(const arg:LongString):LongString;
var List:TStringList; tid,pid,wtid,wpid:Integer; row:LongString;
begin
 Result:='';
 List:=TStringList.Create;
 try
  wtid:=StrToIntDef(FetchCookie(arg,'tid'),0);
  wpid:=StrToIntDef(FetchCookie(arg,'pid'),0);
  for tid:=task_ref_min to task_ref_max do
  if (task_ref(tid)=nil) then continue else begin
   pid:=task_pid(tid);
   if (wtid<>0) and (wtid<>tid) then continue;
   if (wpid<>0) and (wpid<>pid) then continue;
   row:=Format('%-4d  %-5d  %-7s  %-8s  %s',[tid,pid,ExtractWord(1+Ord(task_wait(tid,0)),'Stopped,Running',ScanSpaces),
             task_ctrl(tid,'ProcessPriority'),task_ctrl(tid,'CmdLine')]);
   List.Add(row);
  end;
  Result:=List.Text;
 finally
  Kill(List);
 end;
end;

function FormatColor(color:TColor; form,def:LongString):LongString;
begin
 Result:='';
 form:=TrimDef(form,def);
 case WordIndex(form,'str,num,hex,web,rgb',ScanSpaces) of
  1: Result:=ColorToString(color);
  2: Result:=ColorToNumber(color);
  3: Result:=ColorToHexNum(color);
  4: Result:=ColorToWebNum(color);
  5: Result:=ColorToRgbNum(color);
 end;
end;

function ListOf_colors(const arg:LongString):LongString;
var m:Integer; code,name,form:LongString; color:TColor;
begin
 Result:='';
 code:=FetchCookie(arg,'code');
 name:=FetchCookie(arg,'name');
 form:=FetchCookie(arg,'format');
 if IsEmptyStr(arg) then Exit(KnownColorsListAsText(0));
 if IsLexeme(code,lex_IParam) then begin
  color:=StrToIntDef(code,clNone);
  Exit(FormatColor(color,form,'str'));
 end;
 if IsLexeme(name,lex_Name) then begin
  color:=StringToColor(name,clNone);
  Exit(FormatColor(color,form,'num'));
 end;
 if (WordIndex(form,'txt,pas,crc,htm',ScanSpaces)>0) then begin
  m:=WordIndex(form,'pas,crc,htm',ScanSpaces);
  Result:=KnownColorsListAsText(m);
  Exit;
 end;
end;

function ListOf_specfolders(const arg:LongString):LongString;
var name:LongString;
begin
 Result:='';
 if IsEmptyStr(arg) then Exit(CSIDL_ListAllAsText);
 name:=Trim(FetchCookie(arg,'name'));
 if (name<>'') then Result:=CSIDL_FolderByName(name,'');
end;

function ListOf_netifs(const arg:LongString):LongString;
var m:Integer;
begin
 m:=StrToIntDef(FetchCookie(arg,'mode'),-1);
 Result:=GetListOfNetworkInterfaces(m);
end;

function ListOf_services(const arg:LongString):LongString;
var name,port,prot:LongString;
begin
 Result:='';
 if IsEmptyStr(arg) then Exit(UriMan.ServicePortList);
 name:=Trim(FetchCookie(arg,'name'));
 port:=Trim(FetchCookie(arg,'port'));
 prot:=Trim(FetchCookie(arg,'protocol'));
 if (name<>'') then Exit(UriMan.ServicePortInfo(UriMan.FindServicePort(name,prot)));
 if (port<>'') then Exit(UriMan.ServicePortInfo(UriMan.FindServicePort(port,prot)));
end;

function ListOf_comports(const arg:LongString):LongString;
var Table,line,name,path:LongString; i:Integer;
begin
 Result:='';
 Table:=SerPortMap.Table;
 if IsEmptyStr(arg) then Exit(Table);
 name:=Trim(FetchCookie(arg,'name'));
 path:=Trim(FetchCookie(arg,'path'));
 if (name<>'') or (path<>'') then begin
  for i:=1 to WordCount(Table,EolnDelims) do begin
   line:=ExtractWord(i,Table,EolnDelims);
   if SameText(name,ExtractWord(1,line,JustSpaces))
   or SameText(path,ExtractWord(2,line,JustSpaces))
   then Result:=Result+line+EOL;
  end;
 end;
end;

function ListOf_users(const arg:LongString):LongString;
var name,users:LongString; ni:Integer;
begin
 Result:='';
 users:=StringReplace(Trim(GetUserList),EOL,',',[rfReplaceAll]);
 if IsEmptyStr(arg) then Exit(users);
 name:=Trim(FetchCookie(arg,'name')); ni:=0;
 if (name<>'') then ni:=WordIndex(name,users,ScanSpaces);
 if (ni>0) then Result:=ExtractWord(ni,users,ScanSpaces);
end;

function ListOf_hosts(const arg:LongString):LongString;
var name,hosts:LongString; ni:Integer;
begin
 Result:='';
 hosts:=StringReplace(Trim(GetHostList),EOL,',',[rfReplaceAll]);
 if IsEmptyStr(arg) then Exit(hosts);
 name:=Trim(FetchCookie(arg,'name')); ni:=0;
 if (name<>'') then ni:=WordIndex(name,hosts,ScanSpaces);
 if (ni>0) then Result:=ExtractWord(ni,hosts,ScanSpaces);
end;

function ListOf_groups(const arg:LongString):LongString;
var name,groups:LongString; ni:Integer;
begin
 Result:='';
 groups:=GetListOfUserMembership(',');
 if IsEmptyStr(arg) then Exit(groups);
 name:=Trim(FetchCookie(arg,'name')); ni:=0;
 if (name<>'') then ni:=WordIndex(name,groups,ScanSpaces);
 if (ni>0) then Result:=ExtractWord(ni,groups,ScanSpaces);
end;

function ListOf_environs(const arg:LongString):LongString;
var name:LongString;
begin
 Result:='';
 if IsEmptyStr(arg) then Exit(EnvironmentVariableList.Text);
 name:=Trim(FetchCookie(arg,'name'));
 if (name<>'') then Result:=GetEnv(name);
end;

function ListOf_ftypes(const arg:LongString):LongString;
var name,ftypes,ans:LongString;
begin
 Result:=''; ans:='';
 if IsUnix then ftypes:=MimeAppsListAsText;
 if IsWindows and RunCommand('cmd.exe /c ftype',ans) then ftypes:=ValidateEol(ans);
 if IsEmptyStr(arg) then Exit(ftypes);
 name:=Trim(FetchCookie(arg,'name'));
 if (name<>'') then Result:=CookieScan(ftypes,name);
end;

function ListOf_assocs(const arg:LongString):LongString;
var name,assocs,ans:LongString;
begin
 Result:=''; ans:='';
 if IsUnix then assocs:=MimeGlob.ListExtToMime;
 if IsWindows and RunCommand('cmd.exe /c assoc',ans) then assocs:=ValidateEol(ans);
 if IsEmptyStr(arg) then Exit(assocs);
 name:=Trim(FetchCookie(arg,'name'));
 if (name<>'') then Result:=CookieScan(assocs,name);
end;

function ListOf_daq_tags(const arg:LongString):LongString;
var name,key:LongString; tag,typ:Integer; List:TStringList;
begin
 Result:='';
 List:=TStringList.Create;
 try
  if (arg='') then name:='' else name:=Trim(FetchCookie(arg,'name'));
  for tag:=TAG_REF_MIN to TAG_REF_MAX do begin
   typ:=TypeTag(tag); if (typ=tag_type_nil) then continue;
   key:=NameTag(tag); if (name<>'') and not SameText(name,key) then continue;
   case typ of
    tag_type_int    : List.Values[key]:=Format('Integer %d',[iGetTag(tag)]);
    tag_type_real   : List.Values[key]:=Format('Real %g',[rGetTag(tag)]);
    tag_type_string : List.Values[key]:=Format('String %s',[sGetTag(tag)]);
   end;
  end;
  Result:=List.Text;
 finally
  Kill(List);
 end;
end;

function ListOf_daq_curves(const arg:LongString):LongString;
var name,key,line:LongString; i:Integer; List:TStringList; Crv:TCurve;
begin
 Result:='';
 List:=TStringList.Create;
 try
  if (arg='') then name:='' else name:=Trim(FetchCookie(arg,'name'));
  for i:=0 to Daq.Curves.Count-1 do begin
   crv:=Daq.Curves[i]; if not Assigned(Crv) then continue;
   key:=Crv.Name; if (name<>'') and not SameText(name,key) then continue;
   line:='Curve '+IntToStr(Crv.Count)+' '+IntToStr(Crv.Step);
   line:=line+' '+ColorToString(Crv.Color)+' '+IntToStr(Crv.Style and 15);
   line:=line+' '+IntToStr((Crv.Style div 16) and 15);
   List.Values[key]:=line;
  end;
  Result:=List.Text;
 finally
  Kill(List);
 end;
end;

function ListOf_daq_devices(const arg:LongString):LongString;
var name,key,family,model,line:LongString; i:Integer; List:TStringList; Dev:TDaqDevice;
begin
 Result:='';
 List:=TStringList.Create;
 try
  if (arg='') then name:='' else name:=Trim(FetchCookie(arg,'name'));
  if (arg='') then family:='' else family:=Trim(FetchCookie(arg,'family'));
  if (arg='') then model:='' else model:=Trim(FetchCookie(arg,'model'));
  for i:=0 to FullDaqDeviceList.Count-1 do begin
   Dev:=FullDaqDeviceList[i]; if not Assigned(Dev) then continue;
   key:=Dev.Name; if (name<>'') and not SameText(name,key) then continue;
   if (family<>'') and not SameText(family,Dev.Family) then continue;
   if (model<>'') and not SameText(model,Dev.Model) then continue;
   line:='Device '+Dev.Family+' '+Dev.Model;
   List.Values[key]:=line;
  end;
  Result:=List.Text;
 finally
  Kill(List);
 end;
end;

function KeyOfWin(Win:TMasterForm; kind:Integer):LongString;
begin
 Result:='';
 case kind of
  1: Result:=Win.WinCaption;
  2: Result:=Win.WinPrimeName;
  3: Result:=Win.WinAlterName;
 end;
end;

function ListOf_daq_windows(const arg:LongString):LongString;
var name,key,typa,typw:LongString; i,kind:Integer;
const KindList='Caption,PrimeName,AlterName';
var List:TStringList; Win:TMasterForm;
begin
 Result:='';
 List:=TStringList.Create;
 try
  if (arg='') then name:='' else name:=Trim(FetchCookie(arg,'name'));
  if (arg='') then typa:='' else typa:=Trim(FetchCookie(arg,'type'));
  if (arg='') then kind:=1  else kind:=WordIndex(Trim(FetchCookie(arg,'kind')),KindList,ScanSpaces);
  kind:=EnsureRange(kind,1,3);
  typw:='CURVE_WINDOW';
  if (typa='') or SameText(typa,typw) then
  for i:=0 to Daq.CurWinList.Count-1 do begin
   Win:=Daq.CurWinList[i]; if not Assigned(Win) then continue;
   if (name<>'') and not Win.IsWinNameMatch(name) then continue;
   key:=KeyOfWin(Win,kind); if (key='') then continue;
   List.Values[key]:=typw;
  end;
  typw:='TAB_WINDOW';
  if (typa='') or SameText(typa,typw) then
  for i:=0 to Daq.TabWinList.Count-1 do begin
   Win:=Daq.TabWinList[i]; if not Assigned(Win) then continue;
   if (name<>'') and not Win.IsWinNameMatch(name) then continue;
   key:=KeyOfWin(Win,kind); if (key='') then continue;
   List.Values[key]:=typw;
  end;
  typw:='CIRCUIT_WINDOW';
  if (typa='') or SameText(typa,typw) then
  for i:=0 to Daq.CirWinList.Count-1 do begin
   Win:=Daq.CirWinList[i]; if not Assigned(Win) then continue;
   if (name<>'') and not Win.IsWinNameMatch(name) then continue;
   key:=KeyOfWin(Win,kind); if (key='') then continue;
   List.Values[key]:=typw;
  end;
  typw:='SPECTR_WINDOW';
  if (typa='') or SameText(typa,typw) then
  for i:=0 to Daq.SpeWinList.Count-1 do begin
   Win:=Daq.SpeWinList[i]; if not Assigned(Win) then continue;
   if (name<>'') and not Win.IsWinNameMatch(name) then continue;
   key:=KeyOfWin(Win,kind); if (key='') then continue;
   List.Values[key]:=typw;
  end;
  Result:=List.Text;
 finally
  Kill(List);
 end;
end;

function ListOf_tables(const arg:LongString):LongString;
var List:TStringList; i:Integer; name,key:LongString;
begin
 Result:='';
 name:=FetchCookie(arg,'name');
 List:=TStringList.Create;
 try
  for i:=0 to Hasher.Count-1 do begin
   key:=Hasher.Keys[i];
   if (key='') then continue;
   if IsNonEmptyStr(name) and not SameText(name,key) then continue;
   List.Add(key);
  end;
  Result:=List.CommaText;
 finally
  Kill(List);
 end;
end;

function ListOf_sections(const arg:LongString):LongString;
var name,fname:LongString;
begin
 Result:='';
 name:=FetchCookie(arg,'name'); fname:=SmartFileRef(name);
 if FileIsReadable(fname) then Result:=ExtractListOfSections(fname);
end;

function sid_name(sid:TStringIdentifier):LongString;
var i:Integer;
begin
 Result:='';
 if (sid<sid_Unused) then
 if (sid>sid_Unknown) then
 for i:=0 to Hasher.Count-1 do
 if (Hasher.Links[i]=Ord(sid))
 then Exit(Hasher.Keys[i]);
end;

function ListOf_keys(const arg:LongString):LongString;
var sid:TStringIdentifier; tab,keys,name:LongString;
begin
 Result:='';
 if IsEmptyStr(arg) then begin
  for sid:=Succ(sid_Unknown) to Pred(sid_Unused) do begin
   tab:=sid_name(sid);
   if (tab='') then continue;
   keys:=ListOf_keys('name='+tab);
   if (keys='') then continue;
   Result:=Result+Format('%s keys: %s',[tab,keys])+EOL;
  end;
  Exit;
 end;
 name:=FetchCookie(arg,'name');
 if IsEmptyStr(name) then Exit;
 case Identify(name) of
  sid_Pids:        Result:='pid,ppid,name';
  sid_Processes:   Result:='pid,ppid,name';
  sid_Modules:     Result:='pid';
  sid_Windows:     Result:='pid,class,title,mode';
  sid_Threads:     Result:='name';
  sid_Tasks:       Result:='tid,pid';
  sid_Colors:      Result:='name,code,format';
  sid_Netifs:      Result:='mode';
  sid_Specfolders: Result:='name';
  sid_Services:    Result:='name,port,protocol';
  sid_Comports:    Result:='name,path';
  sid_Users:       Result:='name';
  sid_Hosts:       Result:='name';
  sid_Groups:      Result:='name';
  sid_Environs:    Result:='name';
  sid_FTypes:      Result:='name';
  sid_Assocs:      Result:='name';
  sid_Daq_Tags:    Result:='name';
  sid_Daq_Curves:  Result:='name';
  sid_Daq_Devices: Result:='name,family,model';
  sid_Daq_Windows: Result:='name,type,kind';
  sid_Sections:    Result:='name';
  sid_Keys:        Result:='name';
  sid_Tables:      Result:='name';
 end;
end;

function WhereParams(const arg:LongString):LongString;
begin
 Result:=SkipWords(1,arg,JustSpaces);
 if SameText(ExtractWord(1,Result,JustSpaces),'where')
 then Result:=SkipWords(1,Result,JustSpaces);
end;

function ParamStrListOf(const arg:LongString):LongString;
begin
 Result:='';
 try
  if (arg='') then Exit(ListOf_tables(''));
  case Identify(ExtractWord(1,arg,JustSpaces)) of
   sid_Pids:        Result:=ListOf_pids(WhereParams(arg));
   sid_Processes:   Result:=ListOf_pids(WhereParams(arg),True);
   sid_Modules:     Result:=ListOf_modules(WhereParams(arg));
   sid_Windows:     Result:=ListOf_windows(WhereParams(arg));
   sid_Threads:     Result:=ListOf_threads(WhereParams(arg));
   sid_Tasks:       Result:=ListOf_tasks(WhereParams(arg));
   sid_Colors:      Result:=ListOf_colors(WhereParams(arg));
   sid_Netifs:      Result:=ListOf_netifs(WhereParams(arg));
   sid_Specfolders: Result:=ListOf_specfolders(WhereParams(arg));
   sid_Services:    Result:=ListOf_services(WhereParams(arg));
   sid_Comports:    Result:=ListOf_comports(WhereParams(arg));
   sid_Users:       Result:=ListOf_users(WhereParams(arg));
   sid_Hosts:       Result:=ListOf_hosts(WhereParams(arg));
   sid_Groups:      Result:=ListOf_groups(WhereParams(arg));
   sid_Environs:    Result:=ListOf_environs(WhereParams(arg));
   sid_FTypes:      Result:=ListOf_ftypes(WhereParams(arg));
   sid_Assocs:      Result:=ListOf_assocs(WhereParams(arg));
   sid_Daq_Tags:    Result:=ListOf_daq_tags(WhereParams(arg));
   sid_Daq_Curves:  Result:=ListOf_daq_curves(WhereParams(arg));
   sid_Daq_Devices: Result:=ListOf_daq_devices(WhereParams(arg));
   sid_Daq_Windows: Result:=ListOf_daq_windows(WhereParams(arg));
   sid_Sections:    Result:=ListOf_sections(WhereParams(arg));
   sid_Keys:        Result:=ListOf_keys(WhereParams(arg));
   sid_Tables:      Result:=ListOf_tables(WhereParams(arg));
  end;
 except
  on E:Exception do BugReport(E,nil,'ParamStrListOf');
 end;
end;

///////////////////////////////////////
// Unit initialization and finalization
///////////////////////////////////////

procedure Init_crw_prmstrlst;
begin
 InitHasher;
end;

procedure Free_crw_prmstrlst;
begin
 FreeHasher;
end;

initialization

 Init_crw_prmstrlst;

finalization

 Free_crw_prmstrlst;

end.

//////////////
// END OF FILE
//////////////

