Subscribe for automatic updates: RSS icon RSS

Login icon Sign in for full access | Help icon Help
Advanced search

Pages: [1]
  Reply  |  Print  
Author Topic: Why to recompile after changing global constant value?  (Read 9299 times)
Anderson P.
Posts: 82


« on: July 05, 2017, 01:51:13 pm »

Hello

We have several constants declared inside a globals block, that is imported at other programs using the "globals" command.

If we change the value of some constant in this external file, all the programs that import this constants present the error "The global 'gc_letras_com_acento' has been redefined with a different constant-value." and we have to recompile the programs to solve this.

My question is, why don't Genero simply assumes this new constant value, instead of presenting the error? It has already loaded the constant value for doing the compare. We are trying to understand why it gives this error instead of assuming the new value.

Thanks for your attention.
Sebastien F.
Four Js
Posts: 487


« Reply #1 on: July 05, 2017, 03:38:47 pm »

Hello Anderson,

In fact global files are "included" in the module where they are used, similarly to a preprocessor include <file>...

I assume you doing something like this (using the Genero linker):

Code
  1. $ cat glob.4gl
  2. GLOBALS
  3.  CONSTANT c1 = "abc"
  4. END GLOBALS
  5.  
  6. $ cat main.4gl
  7. GLOBALS "glob.4gl"
  8. MAIN
  9.    DISPLAY c1
  10.    CALL test()
  11. END MAIN
  12.  
  13. $ cat mod1.4gl
  14. GLOBALS "glob.4gl"
  15. FUNCTION test()
  16.    DISPLAY c1
  17. END FUNCTION
  18.  
  19. $ fglcomp mod1.4gl
  20.  
  21. $ vi glob.4gl  -- change constant
  22.  
  23. $ cat glob.4gl
  24. GLOBALS
  25.  CONSTANT c1 = "abcdef"
  26. END GLOBALS
  27.  
  28. $ fglcomp main.4gl
  29.  
  30. $ fgllink -o main.42r main.42m mod1.42m
  31. ERROR(-6216):The global 'c1' has been redefined with a different constant-value.
  32.  

So yes, you have to recompile all the modules using your globals file, if this file was modified.
You may want to define file dependencies with the tool you are using (make, GST?)

For new developments, consider to review globals usage, an use IMPORT FGL with PUBLIC definitions in modules.
This allows automatic chained compilation, see for ex:

Code
  1. $ cat glob2.4gl
  2. PUBLIC CONSTANT c1 = "abcdef"
  3.  
  4. $ cat main.4gl
  5. IMPORT FGL glob2
  6. IMPORT FGL mod1
  7. MAIN
  8.    DISPLAY c1
  9.    CALL test()
  10. END MAIN
  11.  
  12. $ cat mod1.4gl
  13. IMPORT FGL glob2
  14. FUNCTION test()
  15.    DISPLAY c1
  16. END FUNCTION
  17.  
  18. $ ls
  19. glob2.4gl  main.4gl  mod1.4gl
  20.  
  21. $ fglcomp main          -- no need to compile glob2.4gl nor mod1.4gl !
  22.  
  23. $ ls
  24. glob.4gl  glob2.42m  glob2.4gl  main.42m  main.4gl  mod1.42m  mod1.4gl
  25.  
  26. $ fglrun main
  27. abcdef
  28. abcdef
  29.  
  30. $ vi glob2.4gl  -- change constant
  31.  
  32. $ cat glob2.4gl
  33. PUBLIC CONSTANT c1 = "abcdefghi"
  34.  
  35. $ fglcomp main && fglrun main
  36. abcdefghi
  37. abcdefghi
  38.  

Doc refs for IMPORT FGL:

3.00: http://4js.com/online_documentation/fjs-fgl-manual-html/#c_fgl_programs_IMPORT_FGL.html
3.10 EAP: https://4js.com/techdocs/fjs-fgl-manual/index.html#c_fgl_programs_IMPORT_FGL.html
Anderson P.
Posts: 82


« Reply #2 on: July 05, 2017, 04:19:46 pm »

Sebastien, thanks for your reply.

We are aware that this "globals" approach is kind of depreciated, the problem is that all of our programs use a default global set of functions and variables, and seems like we can't have a "globals" and a "import fgl" at the same file, is one or other. Is that right?

So we would have to replace the globals in all our programs with the import fgl, and to archive this will be necessary to change all the global set functions usage to include the module name.

That's why we still use globals and can't use import fgl. I don't know if there is some workaround to use globals and import fgl at the same file.
Sebastien F.
Four Js
Posts: 487


« Reply #3 on: July 05, 2017, 05:29:50 pm »

Not sure to understand 100% what you mean by "global functions"...
Obviously all functions of a program are "global", we have no concept of "local" function (that you could define inside another function for example, in local scope).
With Genero, functions can be PRIVATE or PUBLIC.

Theoretically, you can mix GLOBAL and IMPORT FGL:

Code
  1. $ cat glob.4gl
  2. GLOBALS
  3.  CONSTANT c0 = "abcdef"
  4. END GLOBALS
  5.  
  6. $ cat glob2.4gl
  7. PUBLIC CONSTANT c1 = "abcdefghi"
  8.  
  9. $ cat main.4gl
  10. IMPORT FGL glob2
  11. IMPORT FGL mod1
  12. GLOBALS "glob.4gl"
  13. MAIN
  14.    DISPLAY c0
  15.    DISPLAY c1
  16.    CALL test()
  17. END MAIN
  18.  
  19. $ cat mod1.4gl
  20. IMPORT FGL glob2
  21. FUNCTION test()
  22.    DISPLAY c1
  23. END FUNCTION
  24.  
  25. $ fglcomp main.4gl
  26.  
  27. $ fglrun main
  28. abcdef
  29. abcdefghi
  30. abcdefghi
  31.  

However, I can imagine that with real application code, it's not that simple to migrate to a new pattern.

Furthermore, you can mix IMPORT FGL and fgllink linking.

Please read carefully this page and get back to us, if you can't find the information you need:

https://4js.com/techdocs/fjs-fgl-manual/index.html#c_fgl_programs_IMPORT_FGL.html

Seb
Anderson P.
Posts: 82


« Reply #4 on: July 05, 2017, 07:01:31 pm »

By global functions I meant functions that was defined inside a module imported using "globals", guess I expressed myself poorly.

And yes, indeed we can mix global and import fgl, but doing so we got a "warning" for every function that is inside the module imported using "globals". I remembered that we had some problems when we tested this, but don't remembered what was it, now i remembered that the problem was this warnings.

But I have seen that the documentation you sent me talk about this -8406 warning, we will investigate this a bit more.

Thanks for your attention.


* IMG_05072017_134221_0.png (28.71 KB, 1119x260 - viewed 778 times.)
Sebastien F.
Four Js
Posts: 487


« Reply #5 on: July 05, 2017, 07:59:22 pm »

Oh I think I start to understand what you do...

I guess you do following ( would be better that YOU provide the samples ;-) ):

Code
  1. $ cat glob.4gl
  2. GLOBALS
  3.  CONSTANT c0 = "abcdef"
  4. END GLOBALS
  5. FUNCTION g_func()
  6.  DISPLAY "in g_func!"
  7. END FUNCTION
  8.  
  9. $ cat main.4gl
  10. GLOBALS "glob.4gl"
  11. MAIN
  12.    DISPLAY c0
  13.    CALL g_func()
  14. END MAIN
  15.  
  16. $ fglcomp main.4gl
  17.  
  18. $ fglcomp glob.4gl
  19.  
  20. $ fgllink -o main.42r main.42m glob.42m
  21.  
  22. $ fglrun main.42r
  23. abcdef
  24. in g_func!

Honestly, I have never seen functions declared in a globals file after the GLOBALS .. END GLOBALS block!

I think this is supported by Genero to compile old legacy 4GL code, an undocumented c4gl feature...

When the module is "included" with GLOBALS "glob.4gl", the compilers takes only global variables definitions.

When the glob.4gl module is compiled, the global variables AND the functions are compiled, and then it can be linked as a regular module!

Think of GLOBALS "file.4gl" as "include the GLOBALS ... END GLOBALS block from file.4gl".
(You could in fact repeat the complete GLOBALS .. END GLOBALS block in each module, GLOBALS "file.4gl" is a shortcut)

To late for me today to test with Informix c4gl, but after a quick look at the Informix 4gl books, I can see that this usage is not really legal:

Quote
Usage

In general, a program variable is in scope only in the same FUNCTION, MAIN,
or REPORT program block in which it was declared. To make its scope of
reference the entire source module, you must specify a modular declaration,
by locating the DEFINE statement outside of any program block.
To extend the visibility of one or more module variables beyond the source
module in which they are declared, you must take the following steps:

1. Declare variables in GLOBALS…END GLOBALS declarations (in files
containing only GLOBALS, DEFINE, and DATABASE statements).

2. Specify the files in GLOBALS “filename” statements in each additional
source module that includes statements referencing the variables.


Here the Genero doc for GLOBALS:
https://4js.com/techdocs/fjs-fgl-manual/index.html#c_fgl_Globals_003.html

Summary: We can try to support undocumented c4gl features to allow you to compile old legacy code, but it gets hard for us to allow mixing such usage with new new Genero features... (sorry!)

Seb
Anderson P.
Posts: 82


« Reply #6 on: July 05, 2017, 08:58:55 pm »

Sebastien, I understand, and indeed this module is a very old code that we use in all our programs to perform the user login.

We have always used it, and will take a considerable work do change it, but I guess it has to be done.

I think that the behavior is correct, when I created the topic it was not clear for me that the globals work just like the include, but now I understand.

Thanks for all your attention, now it's up to us to convert this globals to fgl import.
Sebastien F.
Four Js
Posts: 487


« Reply #7 on: July 05, 2017, 09:12:12 pm »

No prob Anderson, our goal is to help you.

Just tested with Informix c4gl....

This test confirms that it is a behavior from I4GL (at least in C-compiled mode):
Code
  1. $ c4gl -V
  2. IBM INFORMIX-4GL Version 7.51.FC2  
  3. Software Serial Number RDS#N000000
  4.  
  5. $ cat glob.4gl
  6. GLOBALS
  7.  DEFINE v0 VARCHAR(50)
  8. END GLOBALS
  9. FUNCTION g_func()
  10.  DISPLAY "in g_func: v0=", v0
  11. END FUNCTION
  12.  
  13. $ cat main.4gl
  14. GLOBALS "glob.4gl"
  15. MAIN
  16.    LET v0 = "abcdef"
  17.    DISPLAY "in main: v0=", v0
  18.    CALL g_func()
  19. END MAIN
  20.  
  21. $ c4gl -o main.bin main.4gl glob.4gl
  22.  
  23. $ ./main.bin
  24. in main: v0=abcdef
  25. in g_func: v0=abcdef
  26.  

Seb
Sebastien F.
Four Js
Posts: 487


« Reply #8 on: July 05, 2017, 09:21:58 pm »

Oh...  In fact it is documented Genero feature !!!

https://4js.com/techdocs/fjs-fgl-manual/index.html#c_fgl_Globals_006.html

Seb
Reuben B.
Four Js
Posts: 949


« Reply #9 on: July 06, 2017, 12:42:51 am »

Sebastien, thanks for your reply.

We are aware that this "globals" approach is kind of depreciated, the problem is that all of our programs use a default global set of functions and variables, and seems like we can't have a "globals" and a "import fgl" at the same file, is one or other. Is that right?

So we would have to replace the globals in all our programs with the import fgl, and to archive this will be necessary to change all the global set functions usage to include the module name.

That's why we still use globals and can't use import fgl. I don't know if there is some workaround to use globals and import fgl at the same file.

with regard to your comment "and to archive (I think you meant achieve) this will be necessary to change all the global set functions usage to include the module name"
if the function name / variable name was unique, you would not have to "change all the global set functions usage to include the module name"

Code
  1. #!foo.4gl
  2. PUBLIC DEFINE x INTEGER
  3. PUBLIC CONSTANT ZERO=0
  4. FUNCTION bar()
  5.   DISPLAY "bar"
  6. END FUNCTION
  7.  
  8. #!main.4gl
  9. IMPORT FGL foo
  10. MAIN
  11.   CALL bar()
  12.   LET x = 0
  13.   DISPLAY x
  14.   DISPLAY ZERO
  15. END MAIN



>fglcomp foo.4gl
>fglcomp main.4gl
>fglrun main.42m
bar
0
0

Whilst it would be preferable and I'd argue a good standard to adhere to prefix with the module name e.g. in the above code I would rather see DISPLAY foo.bar() LET foo.x = 0 DISPLAY foo.ZERO etc, it isn't necessary if the imported function/variable/constant name is unique.

With "gc_letras_com_acento" I'm guessing gc stands for global constant, so it should be unique enough that your code change is GLOBALS "globals_file" TO IMPORT FGL globals_file, and changing CONSTANT gc_letras_com_acento ... to PUBLIC CONSTANT gc_letras_com_acento ..., and you should not have to change all references of gc_letras_com_acento to globals_file.gc_letras_com_acento, if that is what you are afraid of.


Also with your original question ...
Code
  1. My question is, why don't Genero simply assumes this new constant value, instead of presenting the error? It has already loaded the constant value for doing the compare. We are trying to understand why it gives this error instead of assuming the new value.
  2.  
... to help understand, do something like od -c program-name.42r or strings program-name.42r, and  fglrun -r module-name.42m  (you might need to create a small example to make it all easier to read and interpret).   A common misconception is that a .42r is like a binary executable, it is not.  All the computational logic is inside each .42m. The fglrun -r shows some of this logic, you'll see it pushing constants onto a stack, pointers to the constant values etc
Number of constants:   1
   0   INTEGER   `100'
Global variables:
   HUNDRED   0   INTEGER
...
pushGlb   HUNDRED

This is repeated in each of the .42m.  So if the runner detects where the global constant in one .42m is different than the value of the same global constant in another .42m, then the decision is made to stop rather than assuming one value is more correct than the other. 

Hope that helps

Reuben



Product Consultant (Asia Pacific)
Developer Relations Manager (Worldwide)
Author of https://4js.com/ask-reuben
Contributor to https://github.com/FourjsGenero
Pages: [1]
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines