rejetto forum

variable showing wrong value...?

raybob · 9 · 4790

0 Members and 1 Guest are viewing this topic.

Offline raybob

  • Tireless poster
  • ****
    • Posts: 454
    • View Profile
    • FileSplat.com
Copied from a macro log:

Code: [Select]
for each|user||raybob|{:{.if|{.^user.}|{: {.load|ftpdata-anonymous.xml.tpl.} :}.}:}
    {.if||{: {.load|ftpdata-anonymous.xml.tpl.} :}.}{.if|raybob|{: {.load|ftpdata-anonymous.xml.tpl.} :}.}

if||{: {.load|ftpdata-anonymous.xml.tpl.} :}

if|raybob|{: {.load|ftpdata-anonymous.xml.tpl.} :}
    {.load|ftpdata-anonymous.xml.tpl.}

load|ftpdata-anonymous.xml.tpl
    <Permission Dir="{.from table|installvars|CONTENTDIR.}\content-users\{.^user.}\shared"> <Aliases> <Alias>/{.^user.}</Alias> </Aliases> <Option Name="FileRead">1</Option> <Option Name="FileWrite">0</Option> <Option Name="FileDelete">0</Option> <Option Name="FileAppend">0</Option> <Option Name="DirCreate">0</Option> <Option Name="DirDelete">0</Option> <Option Name="DirList">{.if|{.^boolean|{.^notes|{.^user.}|ftp-publist.}.}|1|0.}</Option> <Option Name="DirSubdirs">{.if|{.^boolean|{.^notes|{.^user.}|ftp-publist.}.}|1|0.}</Option> <Option Name="IsHome">0</Option> <Option Name="AutoCreate">0</Option> </Permission>

from table|installvars|CONTENTDIR
    C:\Program Files\FHFS

^user
    2


The value of ^user should be raybob but it's morphing itself into 2...
« Last Edit: November 03, 2013, 02:03:00 AM by raybob »


Offline rejetto

  • Administrator
  • Tireless poster
  • *****
    • Posts: 13510
    • View Profile
I'm not sure because I'm not home now, but I guess "user" exists only inside the loop


Offline Mars

  • Operator
  • Tireless poster
  • *****
    • Posts: 2059
    • View Profile
inside the loop, the variable "user" receives each of the N values, ​​at the end the variable receives the value "N"

{.for each|user||raybob|{:{.if|{.^user.}|{: {.load|ftpdata-anonymous.xml.tpl.} :}.}:}.}


any variable that is placed between the quotes is replaced by its literal value and inserted as it in the html result, the previus line is replaced by

{.if||{:{.load|ftpdata-anonymous.xml.tpl.} :}.}{.if|raybob|{: {.load|ftpdata-anonymous.xml.tpl.} :}.}
and at this time what is ^user is replaced by the count of values  --> 2

the next step is the analysis of IF-->the fist return nothing , the second return {.load|ftpdata-anonymous.xml.tpl.} and the content of ftpdata as a string text if path contains any \ or /


using  {.for each|user||raybob|{:{.if|{.^user.}|{:{.dequote| {.load|ftpdata-anonymous.xml.tpl.}.} :}.}:}.} use content of ftpdata as  interpreted text


« Last Edit: November 05, 2013, 04:49:32 PM by Mars »


Offline raybob

  • Tireless poster
  • ****
    • Posts: 454
    • View Profile
    • FileSplat.com
I don't quite understand.  I don't think I'm accessing ^ftpuser outside of the loop.  (I changed 'user' to 'ftpuser' btw)

Here's what I got:

Code: [Select]

{.delete|filezilla-bin\FileZilla Server.xml|bin=0.}

{.if not|{.load|ftpconfig.xml.}|{:{.save|ftpconfig.xml|{.load|ftpdata-settings.xml.tpl.}.}:}.}

{.save|filezilla-bin\FileZilla Server.xml|{.trim|

<FileZillaServer>

{.load|ftpconfig.xml.}

<Groups />

<Users>

{.load|ftpdata-anon1.xml.tpl.}

{.for each|#ftpuser|{.replace|;|{.no pipe||.}|{.^#data|ftpusers|users.}.}|{:{.if|{.^#boolean|{.^#notes|{.^#ftpuser.}|ftp-enabled.}.}|{:

{.set|#ftpuser|{.^#ftpuser.}.}{.load|ftpdata-anonymous.xml.tpl.}

:}.}:}.}

{.load|ftpdata-anon2.xml.tpl.}

{.for each|#ftpuser|{.replace|;|{.no pipe||.}|{.^#data|ftpusers|users.}.}|{:{.if|{.^#boolean|{.^#notes|{.^#ftpuser.}|ftp-enabled.}.}|{:

{.set|#ftpuser|{.^#ftpuser.}.}{.load|ftpdata-user.xml.tpl.}

:}.}:}.}

</Users>

</FileZillaServer>

.}.}

You'll notice this:

Code: [Select]
{.set|#ftpuser|{.^#ftpuser.}.}
That's the very strange work around I discovered that passes the correct value.  So the code as I have it written above works, but I don't understand why I have to set the variable a second time.
« Last Edit: November 05, 2013, 08:30:14 PM by raybob »


Offline rejetto

  • Administrator
  • Tireless poster
  • *****
    • Posts: 13510
    • View Profile
as an optimization, i don't actually create a variable but just replace the text that SHOULD be the variable with the value.
At the end of the loop the variable is truly created.

Anyway there's a bug, and the last value of the variable is the index instead of the real value.

for your information, in the current implementation, since "for each" is thought to be used with few iterations, like tens, or hundreds, it actually unroll it, first.


Offline Mars

  • Operator
  • Tireless poster
  • *****
    • Posts: 2059
    • View Profile
Code: [Select]
Hi Rejetto, I have a fairly simple solution that will also raybob to get a good result and a real use of macros "for" and "for each"  as would be expected to operate

must simply set the variable used at the beginning of each assessment loops

procedure foreach();
  var
    i, e: integer;
    code: string;
  begin
  e:=pars.count-2; // 3 parameters minimum (the check is outside)
  code:=macroDequote(par(pars.count-1));
  with TfastStringAppend.create do
    try
      for i:=1 to e do
append(format(MARKER_OPEN+'set|%s|%s'+MARKER_CLOSE,[p,par(i)])+code);
      result:=reset();
      setVar(p, intToStr(e)); // leave last value in the var
    finally free end;
  end; // foreach

  procedure for_();
  var
    b, e, i, d: integer;
    code: string;
  begin
  try
    b:=strToInt(par(1));
    e:=strToInt(par(2));
    try
      d:=strToInt(par(3));
      code:=par(4);
    except
      d:=1;
      code:=par(3);
      end;
    if d = 0 then exit;
    if (e < b) and (d > 0) then d:=-d; // we care
    code:=macroDequote(code);
    with TfastStringAppend.create do
      try
        for i:=1 to (e-b) div d+1 do
          begin
           append(format(MARKER_OPEN+'set|%s|%s'+MARKER_CLOSE,[p,intToStr(b)])+code);
           inc(b, d);
          end;
        result:=reset();
      finally free end;
    setVar(p, intToStr(e)); // leave last value in the var
  except end;
  end; // for_

now here's what happens:
if file.tpl containt -->  is {.^user.}

{.for each|user|rejetto|raybob|{:{.^user} {.load|file.tpl.} <p>:}.}  give

rejetto {.load|file.tpl.} <p>  -->>  rejetto  is {.^user.} -->>> rejetto is 2
raybob {.load|file.tpl.} <p>  -->>  raybob  is {.^user.} -->>> raybob is 2

and in the near future ....

{.for each|user|rejetto|raybob|{:{.^user} {.load|file.tpl.} <p>:}.}   will give

{.set|user|rejetto}{.^user.}{.load|file.tpl.} <p> 
-->> {.set|user|rejetto}{.^user.}  is {.^user.}
-->> rejetto is rejetto

and the same with raybob  ;D

Now, user  is not replaced by its equivalent in each loop, but a macro "set" is inserted at the beginning of the chain to be implemented in the template, as it would be done simply by hand in a text editor

this alternative may work as well, but I'm not sure the result will be identical to the first solution
Code: [Select]
    try
      for i:=1 to e do
        begin
         setVar(p, intToStr(e));
append(code);
        end
      result:=reset();
      setVar(p, intToStr(e)); // leave last value in the var
    finally free end;



Offline rejetto

  • Administrator
  • Tireless poster
  • *****
    • Posts: 13510
    • View Profile
i will do something similar to your second suggestion
Code: [Select]
  procedure foreach();
  var
    i, e: integer;
    s, code: string;
  begin
  e:=pars.count-2; // 3 parameters minimum (the check is outside)
  code:=macroDequote(par(pars.count-1));
  with TfastStringAppend.create do
    try
      for i:=1 to e do
        begin
        setVar(p, par(i));
        s:=code;
        applyMacrosAndSymbols(s, cbMacros, cbData);
        append(s);
        end;
      result:=reset();
    finally free end;
  end; // foreach

  procedure for_();
  var
    b, e, i, d: integer;
    s, code: string;
  begin
  try
    b:=strToInt(par(1));
    e:=strToInt(par(2));
    try
      d:=strToInt(par(3));
      code:=par(4);
    except
      d:=1;
      code:=par(3);
      end;
    if d = 0 then exit;
    if (e < b) and (d > 0) then d:=-d; // we care
    code:=macroDequote(code);
    with TfastStringAppend.create do
      try
        for i:=1 to (e-b) div d+1 do
          begin
          setVar(p, intToStr(b));
          s:=code;
          applyMacrosAndSymbols(s, cbMacros, cbData);
          append(s);
          inc(b, d);
          end;
        result:=reset();
      finally free end;
  except end;
  end; // for_


ready for #286


Offline Mars

  • Operator
  • Tireless poster
  • *****
    • Posts: 2059
    • View Profile
Quote from: raybob
Yay!   :D
+1  ;D

is it possible to have an extra version compiled with my proposition, i would like to imagine some short scripts to check the order of evaluation of macros because of the use of applyMacrosAndSymbols precisely.