Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Evaluate preprocessor macro on run time in Inno Setup Pascal Script

Tags:

inno-setup

I'm using an Inno Setup #define directive to define all of the information about a software package in my installer and then other directives to extract portions of that string. So for example, using the following, PartNumber(Package1) will return 05414.

#define Package1 "05414 - My Package"
#define PartNumber(str Package) Copy(Package, 1, 5)

I'm using this approach in scripts and code and it works fine. However, I've got a situation where it would be convenient to programmatically generate the string and I'm having trouble getting it to work. For example, I'd like to do something like the following.

procedure Foo(Package: String);
var
  PartNumber: String;
begin
  PartNumber:= ExpandConstant(Format('{#PartNumber(%s)}', [Package]));
end;

procedure Bar();
begin
   Foo(ExpandConstant('{#Package1}')); 
end;

The Package argument to Foo is correct, but I get a compiler error saying

[ISPP] No argument for format '%'".

It seems that it doesn't like the # in the string on the PartNumber line. Even including a # in a normal string gives an "unterminated preprocessor directive" error, so I think it's interpreting the # as a precision specifier or something.

Is there a way to make it treat # as part of the text so that I can programmatically expand this constant? If not, if there some other way I can achieve this?

like image 222
user7134019 Avatar asked Oct 19 '25 17:10

user7134019


1 Answers

This cannot work.

The PartNumber is a preprocessor function/macro. It's evaluated on compile time. It does not exist on run time.


You can, of course, implement an equivalent Pascal Script function:

function PartNumberPascal(Package: string): string;
begin
  Result := Copy(Package, 1, 5);
end;

procedure Foo(Package: String);
var
  PartNumber: String;
begin
  PartNumber := PartNumberPascal(Package);
end;

What probably confuses you, is this call:

Foo(ExpandConstant('{#Package1}')); 

It may give you an impression that the ExpandConstant function expands the Package1 preprocessor define.

It does not!

The {#...} syntax (contrary to the {...}) is not a constant. It's an inline preprocessor directive call, where, when no directive is explicitly specified, the emit is implied. So the {#Package1} is the same as {#emit Package1}. And as every preprocessor construct, it's evaluated on compile time.

If you add SaveToFile preprocessor function call to the end of the script:

procedure Bar();
begin
  Foo(ExpandConstant('{#Package1}')); 
end;

#expr SaveToFile(AddBackslash(SourcePath) + "Preprocessed.iss")

And after compilation, check, what the Preprocessed.iss is like. You will see:

procedure Bar();
begin
  Foo(ExpandConstant('05414 - My Package')); 
end;

The Package1 is expanded to its value. But the ExpandConstant is still there, and hence it's totally useless! (there are no constants in the '05414 - My Package')

This would have the same effect:

procedure Bar();
begin
  Foo('{#Package1}'); 
end;

For a similar question, see:
Evaluate a collection of data from preprocessor on run time in Inno Setup Pascal Script

like image 91
Martin Prikryl Avatar answered Oct 21 '25 17:10

Martin Prikryl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!