Author Topic: Preprocessor directives misbehaviour?  (Read 10467 times)

Offline David Serrano

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 503
Preprocessor directives misbehaviour?
« on: 2007 October 28 09:21:40 »
Let's take a break, this doesn't involve image processing ;).

Consider this snippet:

Code: [Select]
#define FOO 5
#define BAR 15
#define BAZ 19

#iflteq FOO 15
      console.writeln ("condition true for ", FOO);
#else
      console.writeln ("condition false for ", FOO);
#endif

#iflteq BAR 15
      console.writeln ("condition true for ", BAR);
#else
      console.writeln ("condition false for ", BAR);
#endif

#iflteq BAZ 15
      console.writeln ("condition true for ", BAZ);
#else
      console.writeln ("condition false for ", BAZ);
#endif


I don't know if "iflteq FOO 15" means "if FOO <= 15" or "if 15 <= FOO" but, in any case, if the condition is true for FOO it should be false for BAZ, right? Well, let's see the output:

Code: [Select]
Processing script file: /home/hue/foo.js
condition false for 5
condition true for 15
condition false for 19


What the heck? It's false for both FOO and BAZ! I've also tested "ifgteq" (3 true results), "iflt" (3 false results), "ifgt" (true, false, true), "eq" (false, true, false (as expected)) and "neq" (true, false, true (as expected)). Quoting the #definitions and/or the #if* conditionals didn't make things better.
--
 David Serrano

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Preprocessor directives misbehaviour?
« Reply #1 on: 2007 October 28 11:00:58 »
Hi David

Conditional directives perform comparisons between strings, not between numeric values. This is the reason why you're getting so odd results.

Here is some useful reference material:

********************************************

This is the current set of supported directives:

#include <file_path> | "file_path"
#define <symbol_id> <value_string>
#undef <symbol_id>
#ifdef <symbol_id>
#ifndef <symbol_id>
#ifeq <symbol_id> <string_value>
#ifneq <symbol_id> <string_value>
#iflt <symbol_id> <string_value>
#ifgt <symbol_id> <string_value>
#iflteq <symbol_id> <string_value>
#ifgteq <symbol_id> <string_value>
#else
#endif
#error <error_message>
#warning <warning_message>
#feature-id <script_name>
#feature-info <text>
#feature-icon <icon_file_path>

(note that the < and > symbols in the description of #include are literal; they are not part of the metalanguage)

********************************************

This is the current set of predefined symbols, available to all scripts:

__FILE__
Current script file, full path.

__LINE__
Current source code line number.

__DATE__
Date of compilation in the format yyyy/mm/dd.

__TIME__
Time of compilation in the format hh:mm:ss.

__JS_VERSION__
Version of the JavaScript engine. Currently equal to "1.7".

__PI_VERSION__
A string representing the version of the core PixInsight application. The format is "MM.mm.rr.bbbb", where MM = major version number, mm = minor version, rr = release number, and bbbb = build number.

__PI_MAJOR__
Major version number of the core PixInsight application.

__PI_MINOR__
Minor version number of the core PixInsight application.

__PI_RELEASE__
Release number of the core PixInsight application.

__PI_BUILD__
Build number of the core PixInsight application.

__PI_BETA__
Equal to a number > 0 if running on a beta version of the core application; undefined otherwise.

__PI_LE__
Equal to "1" if running on a limited version of the core application; undefined otherwise.

__PI_LANG__
ISO 639.2 language code of the core PixInsight application. E.g. "eng" or "spa".

__PI_PLATFORM__
Identifies the current platform. Can be either "LINUX", "MACOSX" or "MSWINDOWS".

********************************************

I think it would be convenient to define a new set of conditional directives that interpret their comparison values as numbers, to perform comparisons based on the resulting values. Something like:

#ifeqn <symbol_id> <numeric_value>
#ifneqn <symbol_id> <numeric_value>
#ifltn <symbol_id> <numeric_value>
#ifgtn <symbol_id> <numeric_value>
#iflteqn <symbol_id> <numeric_value>
#ifgteqn <symbol_id> <numeric_value>

What do you think? This could be ready for the next version; it is very easy to implement.
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline David Serrano

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 503
Preprocessor directives misbehaviour?
« Reply #2 on: 2007 October 28 12:40:46 »
Thanks for all this reference material. Another forum thread to link from the official documentation? ;)


Quote from: "Juan Conejero"
I think it would be convenient to define a new set of conditional directives that interpret their comparison values as numbers [...] What do you think? This could be ready for the next version; it is very easy to implement.


If it's easy and clean, then go on. Nobody's gonna complain :).

My personal opinion, though, is that it would be nice to have a C-like preprocessor. A quick look in the linux source code shows an #if directive that accepts arithmetic, relational, logical and bitwise operations (but you, as a C++ programmer, already know this ;)). I see that as a more programmer-friendly scheme than a whole family of directives, even if their names are logical and intuitive. Plus, it would allow scripts to work with all version-related symbols without a glitch, whereas the current scheme could give problems when, for example, __PI_BUILD__ goes from 999 to 1000. It could also be made to work with strings when, for example, all tokens involved were quoted.

Is there a compelling reason why you didn't implement a C-like #if from the beginning? For me, it would be the one, true way :).
--
 David Serrano

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Preprocessor directives misbehaviour?
« Reply #3 on: 2007 October 29 04:58:27 »
Quote
Is there a compelling reason why you didn't implement a C-like #if from the beginning? For me, it would be the one, true way


Well, it's just that implementing a fully-featured C preprocessor isn't the easiest task. It isn't extremely difficult either, but the current preprocessor is pretty simple now (less than 1000 lines of code) and easy to understand and maintain.

You're undoubtedly right, a true C prep is the best option. However, it isn't incompatible with the current syntax, so for now I'll keep it simple as is :)

The next version won't add new "#if<xxx>n" conditional directives. Instead, the current ones (#ifeq, #iflt, #ifgteq etc) will work by interpreting their arguments as numbers by default. If an argument is enclosed by quotes, it will be interpreted as a string. I think this is the minimal cost solution, and it can work pretty well. Do you agree?
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline David Serrano

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 503
Preprocessor directives misbehaviour?
« Reply #4 on: 2007 October 29 05:33:43 »
Quote from: "Juan Conejero"
the current ones (#ifeq, #iflt, #ifgteq etc) will work by interpreting their arguments as numbers by default. If an argument is enclosed by quotes, it will be interpreted as a string. I think this is the minimal cost solution, and it can work pretty well. Do you agree?


Yep! The only remaining gotcha is when one of the parameters is a number and the other a string. One of them will have to be converted to the other type, and this will have to be specified in the doc.
--
 David Serrano

Offline NKV

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 677
Re: Preprocessor directives misbehaviour?
« Reply #5 on: 2010 January 27 05:57:37 »
What i doing wrong?
Code: [Select]
console.writeln(__PI_VERSION__);
Best regards,
Nikolay.

Offline Niall Saunders

  • PTeam Member
  • PixInsight Jedi Knight
  • *****
  • Posts: 1456
  • We have cookies? Where ?
Re: Preprocessor directives misbehaviour?
« Reply #6 on: 2010 January 27 07:19:33 »
Hi Nikolay,

I am not at my PI computer at the moment, but my first guess was to change your code to (something like)
Code: [Select]
version_data = __PI_VERSION__;
console.writeln(version_data);

In any case
__PI_VERSION__
is not a 'variable' as such, it is not 'evaluated' at run-time. It is a 'declaration' (terminology ??) that is 'converted' to the appropriate text string during compilation.

In your original case, I would imagine that PJSR would then require the converted string to be enclosed in 'quotes' ("...") within the writeln() function parentheses - but this cannot just be done in your version as the 'declaration' would not then be 'converted'. All you would then get is __PI_VERSION__ printed out.

I am sure there is a more elegant solution, but I have been away from PJSR for too long !!

Cheers,
Cheers,
Niall Saunders
Clinterty Observatories
Aberdeen, UK

Altair Astro GSO 10" f/8 Ritchey Chrétien CF OTA on EQ8 mount with homebrew 3D Balance and Pier
Moonfish ED80 APO & Celestron Omni XLT 120
QHY10 CCD & QHY5L-II Colour
9mm TS-OAG and Meade DSI-IIC

Offline NKV

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 677
Re: Preprocessor directives misbehaviour?
« Reply #7 on: 2010 January 27 08:30:06 »
I am not at my PI computer at the moment, but my first guess was to change your code to (something like)
Code: [Select]
version_data = __PI_VERSION__;
console.writeln(version_data);
Hello Niall, thank you, but error is not disappear. And no error with __PI_BUILD__.
Code: [Select]
function main()
{
var version_data1 = __PI_BUILD__;
console.writeln(version_data1);
var version_data2 = __PI_VERSION__;
console.writeln(version_data2);
}

main();

Result:

Offline georg.viehoever

  • PTeam Member
  • PixInsight Jedi Master
  • ******
  • Posts: 2132
Re: Preprocessor directives misbehaviour?
« Reply #8 on: 2010 January 27 10:41:24 »
Hi,

this is because __PI_BUILD__ can be converted into an integer, whereas __PI_VERSION__ cannot (it is a string). See http://gcc.gnu.org/onlinedocs/cpp/Stringification.html and try this version:
Code: [Select]
function main()
{
var version_data1 = __PI_BUILD__;
console.writeln(version_data1);
var version_data2 = #__PI_VERSION__;
console.writeln(version_data2);
}

main();

Georg
Georg (6 inch Newton, unmodified Canon EOS40D+80D, unguided EQ5 mount)

Offline Niall Saunders

  • PTeam Member
  • PixInsight Jedi Knight
  • *****
  • Posts: 1456
  • We have cookies? Where ?
Re: Preprocessor directives misbehaviour?
« Reply #9 on: 2010 January 27 10:54:42 »
Thanks Georg,

I checked it, and it works
Cheers,
Niall Saunders
Clinterty Observatories
Aberdeen, UK

Altair Astro GSO 10" f/8 Ritchey Chrétien CF OTA on EQ8 mount with homebrew 3D Balance and Pier
Moonfish ED80 APO & Celestron Omni XLT 120
QHY10 CCD & QHY5L-II Colour
9mm TS-OAG and Meade DSI-IIC

Offline NKV

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 677
Re: Preprocessor directives misbehaviour?
« Reply #10 on: 2010 January 27 19:16:22 »
Thanks guys!
Best regards,
Nikolay.

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Re: Preprocessor directives misbehaviour?
« Reply #11 on: 2010 January 29 01:00:54 »
I was ready to answer Nikolay's question, but I see you guys have already solved the issue, and really well by the way. Great!  8)

Indeed the __PI_VERSION__ predefined macro requires stringification to be used with Console.writeln().

Just a 2-cent contribution: there is no need to use an intermediate variable; you can write:

Code: [Select]
console.writeln( #__PI_VERSION__ );
Juan Conejero
PixInsight Development Team
http://pixinsight.com/