Author Topic: Glitch in PUT with set length strings.  (Read 2320 times)

0 Members and 1 Guest are viewing this topic.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Glitch in PUT with set length strings.
« on: December 09, 2020, 03:07:36 pm »
Some very simple code to illustrate the issue:

Code: QB64: [Select]
  1. DIM b(0) AS STRING * 1
  2.  
  3. OPEN "temp.txt" FOR BINARY AS #1
  4. b(0) = "A"
  5.  
  6. PUT #1, 1, b()
  7.  
  8. a$ = " "
  9. GET #1, 1, a$
  10.  

And our error message:

Code: [Select]
..\\temp\\main.txt:8:100: error: lvalue required as unary '&' operand
 sub_put( 1 , 1 ,byte_element((uint64)(&(qbs_new_fixed(&((uint8*)(__ARRAY_STRING1_B[0]))[(0)*1],1,1))),(1*(__ARRAY_STRING1_B[2]&1)*__ARRAY_STRING1_B[5])-(1*(0)),byte_element_1),1);
                                                                                                    ^
compilation terminated due to -Wfatal-errors.

And the full c-translation of our code:
Code: C++: [Select]
  1. S_0:;
  2.  
  3. sub_open(qbs_new_txt_len("temp.txt",8), 2 ,NULL,NULL, 1 ,NULL,0);
  4. qbs_cleanup(qbs_tmp_base,0);
  5. tmp_long=( 0 )-__ARRAY_STRING1_B[4];
  6. if (!new_error) qbs_set(qbs_new_fixed(&((uint8*)(__ARRAY_STRING1_B[0]))[tmp_long*1],1,1),qbs_new_txt_len("A",1));
  7. qbs_cleanup(qbs_tmp_base,0);
  8. sub_put( 1 , 1 ,byte_element((uint64)(&(qbs_new_fixed(&((uint8*)(__ARRAY_STRING1_B[0]))[(0)*1],1,1))),(1*(__ARRAY_STRING1_B[2]&1)*__ARRAY_STRING1_B[5])-(1*(0)),byte_element_1),1);
  9. qbs_cleanup(qbs_tmp_base,0);
  10. qbs_set(__STRING_A,qbs_new_txt_len(" ",1));
  11. qbs_cleanup(qbs_tmp_base,0);
  12. sub_get2( 1 , 1 ,__STRING_A,1);
  13. qbs_cleanup(qbs_tmp_base,0);
  14. tqbs=qbs_new(0,0);
  15. qbs_set(tqbs,__STRING_A);
  16. if (new_error) goto skip2;
  17. makefit(tqbs);
  18. qbs_print(tqbs,0);
  19. qbs_print(nothingstring,1);
  20. skip2:
  21. qbs_free(tqbs);
  22. qbs_cleanup(qbs_tmp_base,0);
  23. sub_end();
  24. return;
  25. }
  26.  

GET and PUT doesn't work anymore with arrays of fixed-length strings.  The glitch seems like it's probably something very simple missing in here, but the machine translation is such that my poor skills in c can't sort the issue out.  We can get and put bytes properly, and at the end of the day, a string is nothing more than a bunch of bytes read as ASCII characters instead of ASCII values, so this shouldn't be that hard for someone to sort out who can decipher the issue for us.

It looks like we're missing an & in there somewhere in the translated code.  The question is..  WHERE?   

Anyone with any ideas on this one?
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Glitch in PUT with set length strings.
« Reply #1 on: December 09, 2020, 03:18:11 pm »
Could you get C code with control (_CHECKING) turned on? Not that I could decipher it, but I suppose it would reveal the mistake itself.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Glitch in PUT with set length strings.
« Reply #2 on: December 09, 2020, 04:02:38 pm »
Could you get C code with control (_CHECKING) turned on? Not that I could decipher it, but I suppose it would reveal the mistake itself.

You can, but it just obfuscates things even further with error checking to see if we've closed the program window (or CTRL-C/CTRL-BREAK to stop the program).

If we remove the & from the following line, we can compile and run the program:

sub_put( 1 , 1 ,byte_element((uint64)(&(qbs_new_fixed(&((uint8*)(__ARRAY_STRING1_B[0]))[(0)*1],1,1))),(1*(__ARRAY_STRING1_B[2]&1)*__ARRAY_STRING1_B[5])-(1*(0)),byte_element_1),1);

The only problem with removing the & there (which is what happens if we PUT #1, 1, b(0) instead of PUT #1, 1, b()), we end up putting wrongful information to the drive.  Instead of putting 65 in the file, we end up putting a value of 165 (or whatever the accented "e" is) there instead.

The change lets it compile, but the offset is off somewhere, as we're printing the wrong values.  I'm on the hunt for where/what to change, but I still haven't found the  proper little tweak to make it work for us.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Glitch in PUT with set length strings.
« Reply #3 on: December 09, 2020, 05:34:28 pm »
@SMcNeill

The problem is not just with GET and PUT, we found similar problem trying to copy arrays using _MEM methods, worked fine for numeric types but not fixed strings. The method was not one you would use because you offered an alternate approach for copying arrays (if I recall correctly) but the approach I tried worked with numbers but not fixed strings.

I might dig it up if you want to see again.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Glitch in PUT with set length strings.
« Reply #4 on: December 09, 2020, 08:25:38 pm »
Well I ran across the code putting together my Christmas Album:

Code: QB64: [Select]
  1. _TITLE "Mem test for array copy" 'B+ 2019-09-06
  2.  
  3. ' Don't forget _Memfree
  4.  
  5. DIM a(1 TO 20), a1(1 TO 20) AS STRING * 100 'cant do variable length strings , apparently not fixed strings either
  6. REDIM bCopy(0), b1Copy(0) AS STRING * 100
  7.  
  8. FOR i = 1 TO 20
  9.     a(i) = INT(10000 * RND) / 100
  10.     a1(i) = STR$(a(i))
  11.  
  12. sngArrCopy a(), bCopy()
  13. FixStr100ArrCopy a1(), b1Copy()
  14. FOR i = 1 TO 20
  15.     PRINT i, bCopy(i), _TRIM$(b1Copy(i))
  16.  
  17. 'example Steve's for MemFill
  18. DIM b(1 TO 10) AS INTEGER, m AS _MEM
  19. m = _MEM(b())
  20. _MEMFILL m, m.OFFSET, m.SIZE, &HFFFE AS INTEGER '<--- Presto!  It's now full with 10 values of 65535 (&HFFFF)
  21. FOR i = 1 TO 10
  22.     PRINT b(i)
  23.  
  24.  
  25. SUB sngArrCopy (A!(), copyB!())
  26.     REDIM copyB!(LBOUND(a!) TO UBOUND(a!)) 'container for _memget is ready
  27.     DIM m AS _MEM
  28.     m = _MEM(A!())
  29.     _MEMGET m, m.OFFSET, copyB!()
  30.     _MEMFREE m '<<<<<<<<<<<<<<<<<<<<<<<<<< like freeimage very important
  31.  
  32. 'this wont work C++ doesn't like it
  33. 'SUB FixStr100ArrCopy (A() AS STRING * 100, copyB() AS STRING * 100)
  34. '    REDIM copyB(LBOUND(a) TO UBOUND(a)) AS STRING * 100 'container for _memget is ready
  35. '    DIM m AS _MEM
  36. '    m = _MEM(A())
  37. '    _MEMGET m, m.OFFSET, copyB()
  38. 'END SUB
  39.  
  40. 'Steve's fix for strings
  41. SUB FixStr100ArrCopy (A() AS STRING * 100, copyB() AS STRING * 100)
  42.     REDIM copyB(LBOUND(a) TO UBOUND(a)) AS STRING * 100 'container for _memget is ready
  43.     DIM m AS _MEM, m1 AS _MEM
  44.     m = _MEM(A()): m1 = _MEM(copyB())
  45.     _MEMCOPY m, m.OFFSET, m.SIZE TO m1, m1.OFFSET
  46.     _MEMFREE m
  47.     _MEMFREE m1
  48.  
  49.  
  50.