The -4518 error is usually caused by running out of a resource known as temporary string space. Solutions include:
This error can be caused by any of the following coding structures:
CASE dummy_var WHEN 0 ..... WHEN 1 ..... WHEN 2 ..... END CASE instead of this: CASE WHEN dummy_var = 0 ..... WHEN dummy_var = 1 ..... WHEN dummy_var = 2 ..... END CASE
let l_str1 = '$$$$$$$$.$$'
PRINT l_number USING l_str1
DEFINE x, y CHAR(10) LET y = NULL LET x[3,5] = y
CALL something(my_variable) ... FUNCTION something()
From: heiker@quietsch.ping.de (Christian Heiker)
There is an Informix-Lib *(undocumented function)* called "acdealloc()" which job it is to clear the stack.
From a 4gl-program you can call this function with "CALL acdealloc()". With RDS you have to hook this function into your fguser.c module.
Here are the steps do do it with RDS:
int acdealloc(); #include "fgicfunc.h" cfunc_t usrcfuncs[] = { "acdealloc", acdealloc, 0, 0, 0, 0 };
You should pay attention that you make the call in an upper hierachy, for example after a FINISH REPORT.
There is no guarantee that other important data may be deleted from the stack (because nobody nows what is at which time on the stack).
BEWARE: There seems to be a bug in 4GL/ID (4.1 at least) which causes TSS problems to occur after the interrupt key has been pressed, which isn't very helpful if you're trying to find TSS problems in your program!!!
Generate a REPORT with 0 TOP, LEFT, RIGHT & BOTTOM MARGINs and 1 line PAGE LENGTH.
If you're talking about loading data which has been exported from another system you should just use the LOAD command.
If you want to do something sexier like suck in the output from a Unix command use either the routine in Appendix B (100% 4GL code) or Appendix C (a 'C' routine).
From: dennisp@informix.com (Dennis Pimple)
Here's a short article that addresses this and other INPUT ARRAY issues:
Emulating "NEXT ROW" syntax in INPUT ARRAY until version 5.0.
SCREEN { [a ][b ][c ][n] ... } ATTRIBUTES a = ... b = ... c = ... n = FORMONLY.ne TYPE CHAR, NOENTRY; INSTRUCTIONS ... SCREEN RECORD s_array[##] (...,FORMONLY.ne) END
DEFINE ma_array ARRAY[##] OF RECORD ... ne CHAR(1) END RECORD ...
DEFINE arr SMALLINT DEFINE scr SMALLINT DEFINE act SMALLINT DEFINE arrg SMALLINT
LET arrg = 1 LET act = number of rows filled in the array already WHILE arrg > 0 CALL set_count(act) INPUT ARRAY ma_array WITHOUT DEFAULTS FROM s_array.* BEFORE ROW LET arr = arr_curr() LET scr = scr_line() IF arrg > arr THEN # this means we want to go to a row below us in the # array, so NEXT FIELD the NOENTRY field, which means # jump to the next row NEXT FIELD ne END IF # reset arrg to 0 if we get to this point, which allows # us to leave the WHILE loop around the INPUT ARRAY if # the user hits the ACCEPT or INTERRUPT key LET arrg = 0 ... AFTER ROW # I have found that AFTER ROW is the best place to track # the last filled in row. LET act = arr_count() ... # below is an example of how we can implement a function key # to act as a HOME key. When the user types the function key # designated as HOME, the cursor will move to array row 1 ON KEY (F##) LET arrg = 1 EXIT INPUT ... # below is an example of how we can implement a function key # to act as an END key. When the user types the function key # designated as END, the cursor will move to the last filled # in row. ON KEY (F##) IF arr .lt. act THEN # if we're not on the last row now, go there LET arrg = act NEXT FIELD ne END IF ... END INPUT # in case we're looping we need to track arr_count here # because an EXIT INPUT call avoids the AFTER ROW block LET act = arr_count() END WHILE IF int_flag THEN ...
The only drawback to this approach is that for very large arrays the looping can take some time. But for arrays that are 50 rows or less, this is suitable.
BUG #11364 WORK AROUND
The only problem, now, is that with version 4.10 there is a bug that causes exiting from an AUTONEXT field into the NOENTRY field (and thus to the next row) to put the cursor into an infinite loop. This bug (#11364) is scheduled for a fix in version 4.10.UE1, which is currently shipping on some platforms. If you can't get the fixed version, there are two approaches to fixing the problem.
The first approach is to remove the AUTONEXT from the field just before the NOENTRY field. This is the simplest, and thus recommended, approach. If your user can't live with hitting the RETURN key after this field, though, you can use some of the new 4.10 library functions as a work around:
... AFTER FIELD before_ne IF fgl_lastkey() = fgl_keyval("autonext") THEN IF arr < maximum array size THEN # go to the next row, avoiding bug 11364 LET arrg = arr + 1 ELSE # we're on the last row already, loop back to the top LET arrg = 1 END IF EXIT INPUT END IF ...
"before_ne" in the example above is the name of the AUTONEXT field that is listed just before the NOENTRY field in the screen record, and "maximum array size" is the size of array ma_array.
This work around has the same problem as the jumping solution in that for very large arrays a lot of screen repainting is done to get back down to the desired row.
There is an undocumented environment variable called DBSCREENOUT which you need to set to the name of the file you wish you to use for your screendumps.
eg: DBSCREENOUT=screen.out
Now press CONTROL-P when the screen you want is displayed and it will be appended to your output file (screen.out in the above example).
NOTE: There is a similar environment variable called DBSCREENDUMP which includes some ESCape sequencing, so isn't as readable.
A 4GL function which, surprize, surprize, draws boxes. It has now been documented in one of the 4GL for Windows manuals, but does exist on other platforms too.
The optional "color" parameter uses an integer code where 0=white, 7=black, and miscellaneous other colors in between.
This command wasn't made "official" until 4.0, but it does exist in earlier releases. It frees memory used by a cursor, and should be used only once you've completely finished with a cursor (ie: after a CLOSE)
statement-id is the name of a statement that has been PREPAREd
cursor-name is the name of a cursor whose DECLARE statement includes the keywords SELECT or INSERT
In 6.00, you can free a statement-id after you have declared the cursor. Also, in 6.00 you should free both the statement-id and the cursor.
SELECT ACOS(col1), ASIN(col1), ATAN(col1), ATAN2(col1,col2), COS(col1), HEX(col1), LOG10(col1), LOGN(col1), ROUND(col1), SIN(col1), SQRT(col1), TAN(col1), TRUNC(col1) FROM foo_table;
In 4GL 4.1 and above you can use the fgl_lastkey function, but June Tong has a solution for pre-4.1 users:
Here is some information about the undocumented/unsupported/ replaced-by-fgl_lastkey() feature called eflastkey:
There is a global variable called eflastkey which is set in effin.c which holds the value of the last key typed. eflastkey is a short integer which will contain the ascii value of 'regular' keys typed and special values for keys for which 4GL does a 'mapping'. The ACCEPT KEY, for example is defined as 2016, LEFT arrow is defined as 2002 and RIGHT arrow is defined as 2003. If your linker accepts multiple global definitions of the same variable (treating one as the primary declaration and all others as extern) then you can simply include the variable eflastkey in the globals section of your 4GL program:
GLOBALS DEFINE eflastkey SMALLINT END GLOBALS Then, during your INPUT statement, you can test the value: CASE eflastkey WHEN 2000 # UP ARROW WHEN 2001 # DOWN ARROW WHEN 2002 # LEFT ARROW WHEN 2003 # RIGHT ARROW OTHERWISE # Some other key END CASE
If your linker gives you a problem with the definition of eflastkey, you can always call a C function such as CALL lastkey from your INPUT statement as:
lastkey() { extern short eflastkey; switch (eflastkey) { case 2000: ... case 2001: ... case 2002: ... case 2003: ... default: ... } }
You can test for other special mapped values such as INTERRUPT KEY which will set eflastkey to 2011 (assuming it has been DEFERed of course).