Recent

Author Topic: Problem with c style macros  (Read 4099 times)

Чебурашка

  • Hero Member
  • *****
  • Posts: 593
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Problem with c style macros
« on: October 20, 2023, 02:18:04 pm »
Code: Pascal  [Select][+][-]
  1. program testmacro;
  2. uses
  3.   Classes, SysUtils;
  4. begin
  5.   {$MACRO ON}
  6.   {$define main_macro_text:=X_, X_D}
  7.   Writeln({$define X_:=start}'main_macro_text, ' + {$define X_:=end}'main_macro_text');
  8.   {$MACRO OFF}
  9. end.
  10.  

expected output:

Code: Bash  [Select][+][-]
  1. start, startD, end, endD
  2.  

actual output:

Code: Bash  [Select][+][-]
  1. main_macro_text, main_macro_text
  2.  

What am I doing wrong?
« Last Edit: October 20, 2023, 02:19:56 pm by Чебурашка »
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

TRon

  • Hero Member
  • *****
  • Posts: 4377
Re: Problem with c style macros
« Reply #1 on: October 20, 2023, 02:54:44 pm »
What am I doing wrong?
You are not doing anything wrong.

Free Pascal does not support macro parameters, at least not in the way you seem to think it does. Macro features for Free Pascal are very limited, see also https://www.freepascal.org/docs-html/prog/progse5.html

Unfortunately the C-macro you showed can not be converted into a Pascal macro. It is as simple as that.

Today is tomorrow's yesterday.

Чебурашка

  • Hero Member
  • *****
  • Posts: 593
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: Problem with c style macros
« Reply #2 on: October 20, 2023, 03:02:30 pm »
Yes true.
I also did a more detailed test with C and I got bad results: it doesn't event compile at defines level, not in main_macro_text expression.

Code: C  [Select][+][-]
  1. #include <stdio.h>
  2.  
  3. int main(int argv, char** argc)
  4. {
  5.     #define X_ start
  6.     #define main_macro_text X_, X_D
  7.     printf("main_macro_text");
  8.    
  9.     return 0;
  10. }
  11.  

Simply my idea how how macros work is wrong, both in C and in FPC.
« Last Edit: October 20, 2023, 03:04:11 pm by Чебурашка »
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

Чебурашка

  • Hero Member
  • *****
  • Posts: 593
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: Problem with c style macros
« Reply #3 on: October 20, 2023, 03:31:32 pm »
Instead this does the trick

Code: Pascal  [Select][+][-]
  1. program testmacro;
  2. uses
  3.   Classes, SysUtils;
  4. begin
  5.   {$MACRO ON}
  6.   {$define main_macro_text:=X_ + ', ' + X_ + 'D'}
  7.   Writeln({$define X_:='start'}main_macro_text + ', ' + {$define X_:='end'}main_macro_text);
  8.   Writeln({$define X_:='end'}main_macro_text + ', ' + {$define X_:='start'}main_macro_text);
  9.   {$MACRO OFF}
  10. end.
  11.  

Code: Bash  [Select][+][-]
  1. start, startD, end, endD
  2. end, endD, start, startD
  3.  

But this does not create the string at compile time, it does the operation on the code during runtime, not what I wanted.

 :'(
« Last Edit: October 20, 2023, 03:36:29 pm by Чебурашка »
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

ASerge

  • Hero Member
  • *****
  • Posts: 2492
Re: Problem with c style macros
« Reply #4 on: October 20, 2023, 05:34:55 pm »
Macros only confuse the code.
Code: Pascal  [Select][+][-]
  1. {$APPTYPE CONSOLE}
  2.  
  3. function DoubleWithD(const S: string): string;
  4. begin
  5.   Result := S + ', ' + S + 'D';
  6. end;
  7.  
  8. begin
  9.   Writeln(DoubleWithD('start'), ', ', DoubleWithD('end'));
  10.   Writeln(DoubleWithD('end'), ', ', DoubleWithD('start'));
  11.   Readln;
  12. end.

Zvoni

  • Hero Member
  • *****
  • Posts: 3367
Re: Problem with c style macros
« Reply #5 on: October 23, 2023, 09:32:28 am »
Instead this does the trick

Code: Pascal  [Select][+][-]
  1. program testmacro;
  2. uses
  3.   Classes, SysUtils;
  4. begin
  5.   {$MACRO ON}
  6.   {$define main_macro_text:=X_ + ', ' + X_ + 'D'}
  7.   Writeln({$define X_:='start'}main_macro_text + ', ' + {$define X_:='end'}main_macro_text);
  8.   Writeln({$define X_:='end'}main_macro_text + ', ' + {$define X_:='start'}main_macro_text);
  9.   {$MACRO OFF}
  10. end.
  11.  

Code: Bash  [Select][+][-]
  1. start, startD, end, endD
  2. end, endD, start, startD
  3.  

But this does not create the string at compile time, it does the operation on the code during runtime, not what I wanted.

 :'(
You're trying to "stringify" some strings.
As i said before: C-Programmers are lazy buggers.
Stuff like that always confused the hell out of me
Write it out and be done with it.

btw: What exactly are you trying to achieve?
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Чебурашка

  • Hero Member
  • *****
  • Posts: 593
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: Problem with c style macros
« Reply #6 on: October 23, 2023, 09:47:03 am »
btw: What exactly are you trying to achieve?

Maybe I am actually looking for trouble, but the intent was create a set of sql1 view creation statements similar but not equal (similar processing on different field name) in a consistent way, so the if in future I need to extend (as it happened already) I can make it in a single place and have them updated safely/consistently everywhere.

I will make it in a runtime way using SysUtils.Format, but I am partly unhappy with this because these strings are compile time. I will not tell my daughter about that.



1 ORM is the Viet Nam of computer science (cit.)



A very small extract of what I am doing here:

Code: Pascal  [Select][+][-]
  1.   viewFieldsFrag          := 'startDate   , startDateS                                              , startDateSM                                 , startDateSW                                                                                             , startDateSD                                     , startDateSH                                       , endDate, endDateS                                           , endDateSM                              , endDateSW                                                                                       , endDateSD                                 , endDateSH                                    ';
  2.   viewQuerySQLiteFrag     := 'startDate   , strftime(''%Y-%m-%d %H:%M:%S'', startDate)              , strftime(''%Y-%m'', startDate)              , strftime(''%Y-%W'', startDate)                                                                          , strftime(''%Y-%m-%d'', startDate)               , strftime(''%Y-%m-%d %H'', startDate)              , endDate, strftime(''%Y-%m-%d %H:%M:%S'', endDate)           , strftime(''%Y-%m'', endDate)           , strftime(''%Y-%W'', endDate)                                                                    , strftime(''%Y-%m-%d'', endDate)           , strftime(''%Y-%m-%d %H'', endDate)           ';
  3.   viewQueryPostgreSQLFrag := 'startDate   , to_char(startDate, ''YYYY-MM-DD HH24:MI:SS'')           , to_char(startDate, ''YYYY-MM'')             , to_char(startDate, ''YYYY-WW'')                                                                         , to_char(startDate, ''YYYY-MM-DD'')              , to_char(startDate, ''YYYY-MM-DD HH24'')           , endDate, to_char(endDate, ''YYYY-MM-DD HH24:MI:SS'')        , to_char(endDate, ''YYYY-MM'')          , to_char(endDate, ''YYYY-WW'')                                                                   , to_char(endDate, ''YYYY-MM-DD'')          , to_char(endDate, ''YYYY-MM-DD HH24'')        ';
  4.   viewQuerySQLServerFrag  := 'startDate   , format(startDate, ''yyyy-MM-dd hh:mm:ss'', ''en-US'')   , format(startDate, ''yyyy-MM'', ''en-US'')   , concat(format(startDate, ''yyyy-'', ''en-US''), cast(datepart(iso_week, startDate) as varchar(2)))      , format(startDate, ''yyyy-MM-dd'', ''en-US'')    , format(startDate, ''yyyy-MM-dd hh'', ''en-US'')   , endDate, format(endDate, ''yyyy-MM-dd hh:mm:ss'', ''en-US''), format(endDate, ''yyyy-MM'', ''en-US''), concat(format(endDate, ''yyyy-'', ''en-US''), cast(datepart(iso_week, startDate) as varchar(2))), format(endDate, ''yyyy-MM-dd'', ''en-US''), format(endDate, ''yyyy-MM-dd hh'', ''en-US'')';
  5.   {%REGION 'V1101_RepCache_PowerOns' /fold}
  6.   dbo := TDBObjectsEnum.dbo__V1101_RepCache_PowerOns;
  7.   BlankTLiquibaseCreationScriptsDBDependent(lqds);
  8.   lqds[TMEPLiquibaseDatabaseType.ldtSQLite] :=       '<createView fullDefinition="true" viewName="V1101_RepCache_PowerOns">' + LineEnding
  9.                                                    + 'create view V1101_RepCache_PowerOns(machine   , id, ' + viewFieldsFrag + ', durationSeconds, durationMinutes    , durationHours       , totalEnergyWh, totalEnergykWh      )' + LineEnding
  10.                                                    + ' as select                          refMachine, id, ' + viewQuerySQLiteFrag + ', durationSeconds, durationSeconds/60 , durationSeconds/3600, totalEnergyWh, totalEnergyWh / 1000 from T1101_RepCache_PowerOns' + LineEnding
  11.                                                    + '</createView>' + LineEnding;
  12.   lqds[TMEPLiquibaseDatabaseType.ldtPostgreSQL] :=   '<createView fullDefinition="true" viewName="V1101_RepCache_PowerOns">' + LineEnding
  13.                                                    + 'create view V1101_RepCache_PowerOns(machine   , id, ' + viewFieldsFrag + '         , durationSeconds, durationMinutes   , durationHours       , totalEnergyWh, totalEnergykWh     )' + LineEnding
  14.                                                    + ' as select                          refMachine, id, ' + viewQueryPostgreSQLFrag + ', durationSeconds, durationSeconds/60, durationSeconds/3600, totalEnergyWh, totalEnergyWh/1000 from T1101_RepCache_PowerOns' + LineEnding
  15.                                                    + '</createView>' + LineEnding;
  16.   lqds[TMEPLiquibaseDatabaseType.ldtSQLServer] :=    '<createView fullDefinition="true" viewName="V1101_RepCache_PowerOns">' + LineEnding
  17.                                                    + 'create view V1101_RepCache_PowerOns(machine   , id, ' + viewFieldsFrag + '         , durationSeconds, durationMinutes   , durationHours       , totalEnergyWh, totalEnergykWh     )' + LineEnding
  18.                                                    + ' as select                          refMachine, id, ' + viewQuerySQLServerFrag +  ', durationSeconds, durationSeconds/60, durationSeconds/3600, totalEnergyWh, totalEnergyWh/1000 from T1101_RepCache_PowerOns' + LineEnding
  19.                                                    + '</createView>' + LineEnding;
  20.  
  21.   DBObjectDescriptors[dbo] := TDBObjectDescriptor.CreateView({Name}'V1101_RepCache_PowerOns',
  22.   {CreateScript}  'create view V1101_RepCache_PowerOns                             '
  23.                 + '(                                                                     '
  24.                 + '        machine    , id, startDateS                                , startDateSD                      , startDateSH                         , endDateS                                , endDateSD                      , endDateSH                         , durationSeconds, durationMinutes    , durationHours       , totalEnergyWh, totalEnergykWh      '
  25.                 + ') '
  26.                 + 'as '
  27.                 + ' select refMachine , id, strftime(''%Y-%m-%d %H:%M:%S'', startDate), strftime(''%Y-%m-%d'', startDate), strftime(''%Y-%m-%d %H'', startDate), strftime(''%Y-%m-%d %H:%M:%S'', endDate), strftime(''%Y-%m-%d'', endDate), strftime(''%Y-%m-%d %H'', endDate), durationSeconds, durationSeconds/60 , durationSeconds/3600, totalEnergyWh, totalEnergyWh / 1000'
  28.                 + ' from T1101_RepCache_PowerOns',
  29.   {LiquibaseCreateDBSpecifci}lqds,
  30.   {DropScript}'drop view V1101_RepCache_PowerOns');
  31.   {%ENDREGION}
  32.  

« Last Edit: October 23, 2023, 10:07:44 am by Чебурашка »
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

Zvoni

  • Hero Member
  • *****
  • Posts: 3367
Re: Problem with c style macros
« Reply #7 on: October 23, 2023, 10:09:58 am »
Maybe I am actually looking for trouble, but the intent was create a set of sql view creation statements *snipp*
What i thought......
I'm doing something similiar, but i'm using Arrays/Const

Code: Pascal  [Select][+][-]
  1. program Project1;
  2. Uses SysUtils, Classes;
  3.  
  4. Const
  5.   ViewStartEnd: Array[0..3] Of String =  ('start', 'startD', 'end', 'endD');
  6.   ViewEndStart: Array[0..3] Of String =  ('end', 'endD', 'start', 'startD');
  7.  
  8. begin
  9.   Writeln(String.Join(', ',ViewStartEnd));
  10.   Writeln(String.Join(', ',ViewEndStart));
  11. end.

Returns
Code: [Select]
start, startD, end, endD
end, endD, start, startD

So, basically, instead of fully writing out the Statements, i keep Arrays of those Fields, and then i just choose the Array(s) i need, join them on the fly, and done

Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. Uses SysUtils, Classes;
  4.  
  5. Const
  6.   FieldsTable:Array[0..1] Of Array[0..2] Of String =
  7.     (
  8.       ('Table1', 'Column1', 'Column2'),
  9.       ('Table2', 'Col1', 'Col2')
  10.     );
  11. Var
  12.   i:Integer;
  13. begin
  14.   For i:=0 To 1 Do
  15.     Writeln('SELECT '+String.Join(', ', FieldsTable[i],1,Length(FieldsTable[i])-1)+' FROM '+FieldsTable[i][0]);
  16. end.
« Last Edit: October 23, 2023, 10:27:54 am by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Чебурашка

  • Hero Member
  • *****
  • Posts: 593
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: Problem with c style macros
« Reply #8 on: October 23, 2023, 11:06:10 am »
So, basically....

I don't want to generate all the DDL like that, I did it in my life, but is difficult to read afterwards.

My problem, is more related to  some parts of sql code that are used multiple times with variations (rdbms oddities) to be managed consistently. Basically I need a templating system for them.
I would like to make it at compile but, even if the macros were supporting it, I realize that is better use the old good Format().
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

Zvoni

  • Hero Member
  • *****
  • Posts: 3367
Re: Problem with c style macros
« Reply #9 on: October 23, 2023, 12:34:09 pm »
So, basically....

I don't want to generate all the DDL like that, I did it in my life, but is difficult to read afterwards.

My problem, is more related to  some parts of sql code that are used multiple times with variations (rdbms oddities) to be managed consistently. Basically I need a templating system for them.
I would like to make it at compile but, even if the macros were supporting it, I realize that is better use the old good Format().

Look again at my Example above.
Instead of the first dimension referencing different tables, you could do something like

Code: Pascal  [Select][+][-]
  1.     program Project1;
  2.      
  3.     Uses SysUtils, Classes;
  4.      
  5.     Const
  6.       FieldsTable:Array[0..1] Of Array[0..1] Of String =
  7.         (
  8.           ('startDate', 'strftime(''%Y-%m-%d %H:%M:%S'', startDate)'), {For SQLite}
  9.           ('startDate', 'to_char(startDate, ''YYYY-MM-DD HH24:MI:SS'')') {For MySQL}
  10.         );  
  11.     begin
  12.         Writeln('For SQLite: ', 'SELECT '+String.Join(', ', FieldsTable[0])+' FROM SomeTable;');
  13.         Writeln('For MySQL: ', 'SELECT '+String.Join(', ', FieldsTable[1])+' FROM SomeTable;');
  14.     end.
  15.  
And then it's just a choice of the correct Index
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

 

TinyPortal © 2005-2018