|
Post by George on Feb 29, 2020 10:49:13 GMT -5
Robert: A lot of this is very similar to the old FILTER command (Remember that? Before macros came along).
It would take a fair bit of work. And I'm not sure how many users would be willing to create the XForm.EXE. We'd have to create a sample XForm program, just to be able to test out the new code in SPFLite. And then provide that as a skeleton sample for users. What language? I'd use PowerBasic, but nobody else would want it. You'd use C, etc. How many samples are enough? How many could we generate?
I'm doubtful this would generate the user interest.
Users? Comments?
George
|
|
|
Post by nicc on Mar 1, 2020 7:33:45 GMT -5
Well, if I needed something like this I would actually use Rexx to do the Extract and Transform creating a new, permanent, file for editing.
|
|
|
Post by mueh on Mar 1, 2020 12:41:54 GMT -5
I prefer to execute the exe in a macro because it's much more flexible . Here a sample i use . WW.bat opens the SPFLite Tab after the File is created by DASDLS . Elseif FMGet_FListName$ = "DASD" then
tdir = Get_ENVVAR$("Temp")+"\MUSUB\"
ecmd = "cmd /C start cmd /C "+""""+"DASDLS -info -refdt -caldt -hdr "+FMGet_Path$(Get_Arg$(1))+FMGet_Filename$(Get_Arg$(1))+" > "+tdir+replace$(mid$(FMGet_Path$(Get_Arg$(1))+FMGet_Filename$(Get_Arg$(1)),4),ANY "\:",WITH ".")+"."+mid$(FMGet_Path$(Get_Arg$(1))+FMGet_Filename$(Get_Arg$(1)),1,1)
ecmd = ecmd+"&&WW DASD "+tdir+replace$(mid$(FMGet_Path$(Get_Arg$(1))+FMGet_Filename$(Get_Arg$(1)),4),ANY "\:",WITH ".")+"."+mid$(FMGet_Path$(Get_Arg$(1))+FMGet_Filename$(Get_Arg$(1)),1,1)+""""+" -VIEW"
msgbox (4,ecmd)
SPF_EXEC(ecmd)
|
|
|
Post by George on Mar 2, 2020 12:53:37 GMT -5
mueh: Impressive. Would be easier to follow if the values for FMGet_Path$ and FMGet_Filename$ were copied to temp variables 1st), the command strings are hard to follow when they're so long.
George
|
|
|
Post by George on Mar 3, 2020 11:07:11 GMT -5
Robert: If this went anywhere, I would start with the old FILTER code, because it DID do all the creation of the temporary files, call the external tool and reload the manipulated data back into the edit session. Remember, it could Filter a range of lines right up to the whole file. Lots of useful routines there to plagiarize.
George
|
|
|
Post by George on Mar 4, 2020 13:26:57 GMT -5
Doing some overnight thinking on this, before I forget, here's some thoughts.
I think this can be simplified quite a bit. I see no need for temporary files, The XFORM code can directly pass the lines into and out of edit.
I think this could go in fairly easily (famous last words) if I can slip it into the right point in the current file reading and writing routines. I think
it should also support STATE info as well. To be seen if we proceed.
1. Add a new Profile option XFORM, which specifies the name of a macro, I don't see any need to force an XFORM_xxxxx.MACRO naming standard. When specified, there must be a macro of that name in the \MACROS folder.
2. Add two new macro functions:
SPF_XFORM_Put(string) Which inserts 'string' as a new line,
SPFLite controls the insertion point. RC=0 Successful RC=8 Failed, standard error message provided
SPF_XFORM_Get$() Which returns the next text line to be output.
RC=0 Successful RC=4 EOF, no more text lines. RC=8 Failed, standard error message provided
3. Specs for the XFORM macro
Called normally via: Macname [READ | WRITE] filename where
READ means the macro is to process 'filename' and feed the data to SPFLite via SPF_XFORM_Put calls.
When complete the macro ends with a HALT(nnn, message) 'nnn' is the number of lines inserted, SPFLite will verify. or HALT(-1, error-message) if a failure.
WRITE means the macro is to write 'filename' using the text lines fetched via SPF_XFORM_Get$
When complete the macro ends with a
HALT(nnn, message) 'nnn' is the number of lines processed, SPFLite will verify. or HALT(-1, error-message) if a failure.
The XFORM macro has the choice to completely do the transform itself, using whatever thinBasic support is needed. Or if needed it can pass off some work to any external EXE, CMD, BAT etc. as needed, including use of temporary files if required.
The XFORM macro could be quite simple, the following is quick-and-dirty and probably has lots of errors.
' XFORMTEST.MACRO ' Sample, just reads and writes a file ' USES "File" dim recs, RC, fnum as long = 0 dim fname as string = Get_Arg$(2)
if fname = "" then halt(-1, "Missing filename argument")
if Get_Arg$(1) = "READ" then ' A READ request? call ReadFile ' Go Do it elseif Get_Arg$(1) = "WRITE" then ' A WRITE request? call WriteFile ' Go do it else halt(-1, "Unknown operation request - " + Get_Arg$(1)) end if
'----- READ routine function ReadFile() if file_Exists(fname) = %False then halt(-1, "Requested filename does not exist") '---------------------------------------------------- ' At this point the real transform input would take ' place. The code below just does a trivial file read. '---------------------------------------------------- fnum = FILE_OPEN(fname, "INPUT") ' Try opening it if fnum = 0 then halt(-1, "File OPEN failed") ' Oops! do while FILE_EOF(fnum) = %False ' Read file inc recs ' Count RC = SPF_XFORM_Put(FILE_LineInput(RC)) ' Pass line to SPFLite if RC = 8 then ' An error? CLOSE_FILE(fnum) ' Shutdown halt(-1, Get_Err$) ' Echo back the error text end if ' loop ' FILE_CLOSE(fnum) ' Close file now halt(recs, "File loaded successfully) ' Pass record count to SPFLite end function
'----- WRITE routine function ReadFile() dim t as string '---------------------------------------------------- ' At this point the real transform output would take ' place. The code below just does a trivial file write. '---------------------------------------------------- fnum = FILE_OPEN(fname, "OUTPUT") ' Try opening it if fnum = 0 then halt(-1, "File OPEN failed") ' Oops! RC = 0 ' Init for loop do while RC = 0 ' Fetch text lines t = SPF_XFORM_Get$() ' Get a text line RC = SPF_RC ' Get return code if RC = 0 then ' If OK inc recs ' Count it FILE_LinePrint(fnum, t) ' Write the output elseif RC = 4 then ' If EOF FILE_CLOSE(fnum) ' Close it halt(recs, "File written successfully") ' else ' Oops FILE_CLOSE(fnum) ' Close it halt(-1, "SPFLite terminated WRITE") ' Exit end if ' loop ' end function
|
|
|
Post by George on Mar 5, 2020 10:33:38 GMT -5
Robert: Yes it should have been {READ | WRITE}. As to HALT(nn, message), sure, if the message is "" then I'd not issue it.
All READ / WRITE functions in SPFLite are done in one place only, so it's a no-brainer to look for a place to hook something like this in. e.g. even a COPY command to include a file would be supported.
George
|
|
|
Post by Stefan on Mar 31, 2020 9:24:34 GMT -5
Hmm... I already use SPFLite Edit with AUTO colourisation as a viewer for output from home-written REXX routines , e.g. file comparison. It's a bit clunky but saves writing code to display results in an easy-to-read way.
This could allow SPFLite to become a viewer (if not editor) of custom file formats, for example, like
(A) a Hex editor, e.g. groups of 'hex' blocks - followed by a block of ASCII (or other) characters representing the data, rather like mainframe dump output or (B) a disassembler, e.g. hex bytes to represent each instruction, then the Assembler instructions (in ASCII), followed by a character representation as above Not sure there's a lot of demand for the latter, but the former could be useful on occasions as it shows a more 'familiar' hex format than the current HEX command.
The format could be hard-coded in the named 'routine' or could perhaps be loaded from a template. Users could then supply templates for download from your website.
Sorry - Coronavirus house arrest means I have too much time on my hands to play about!
|
|
|
Post by George on Mar 31, 2020 9:39:17 GMT -5
Robert: Stefan:
Yes, if house arrest continues (as I expect it will) I may start poking about with this.
George
|
|
|
Post by George on Mar 31, 2020 14:17:45 GMT -5
OK, Hoping Eros will see this and comment.
I want to call a user-defined thinBasic function and pass it a string, so, for example I create a trial function called SPF_TRY(string)
Using the normal parsing logic
IF thinBasic_CheckOpenParens() THEN ' An Open ( thinBasic_ParseString lTxt ' Then get the string IF thinBasic_CheckCloseParens THEN ' And if closed by ) properly Answer = lTxt ' Got the string END IF ' END IF '
works correctly as long as the string doesn't contain any weird (i.e. low value hex) values. If so, they are not passed.
e.g. If the macro does
local lTxt as string lTxt = "ABC" + CHR$(0,0,0) + "GHI" SPF_TRY(lTxt) what SPF_TRY receives from the ParseString is "ABCGHI"
How do I pass a STRING value without this happening? It seems there are some parse functions that return pointers, but I could not figure out how to get them to work.
George
|
|
|
Post by George on Mar 31, 2020 21:16:01 GMT -5
Robert: Picture: An XFORM macro reads a file. At some point it has data from the file. The data may or may not be manipulated, depends on what the XFORM is doing. It now wants to inject the data into the edit file, the data is in a STRING variable. The macro issues SPF_XFORM_PUT(str-var) If str-var contains some low hex value data (say the XFORM is a binary file viewer) the normal thinBasic STRING parse support is not passing the str-var properly. E. G. My example where str-var = "ABC" + chr$(0,0,0) + "ghi" is parsed and received as "ABCghi"
The thinBasic API has functions that seem to support accessing variable data via pointers, which I thought might be a workaround for this, but I have not been able to figure them out.
Clearer? Hopefully. George
|
|
|
Post by George on Apr 1, 2020 10:39:57 GMT -5
Robert: Found this in testing. A PB STRING can contain ANY of the 256 possible characters, there's no reason to have to fiddle around to handle cases like this. SPFLite doesn't care what data is in a Text line, maybe it won't display correctly depending on the display font in use, but 'funny' characters are perfectly fine.
I'm going to continue today playing with the API pointer type support. There's only comments in the thinBasic.INC file to help, that's why I was hoping Eros might pop in. If I get nowhere, I'll ask on the thinBasic forums for help.
George
[Update] Good, managed to get the thinBasic_ParsePtrToStringAndLen function to work, all characters coming through properly.
Onward!
[\UPDATE]
|
|
|
Post by George on Apr 1, 2020 12:56:47 GMT -5
Robert: If I was still stuck, I would. But right now things have progressed well, the read file stuff is working, meaning macros could be written to allow browsing of oddball file formats, or formatting of the data.
The other half - writing - is not looking good. There are way more wrinkles in handling file enqueing and the handling of SAVE/CREATE/REPLACE/SAVEAS etc. I'm not sure I can crowbar this in as it involves many locations and routines to be altered.
I think I'll shelve the writing half till I do a lot more thinking. In which case I think XFORM should only work in BROWSE, since any kind of file writing would be using the current write code and we could be destroying files.
My guess at the macro code was close, here's the final trial macro for simple reading of a file:
George
' XFORMLOAD.MACRO ' Sample, just reads a file ' USES "File" dim RC, fnum as long = 0 dim fname as string = Get_Arg$(2)
if fname = "" then halt(8, "Missing filename argument") fname = SPF_UnQuote$(fname) ' Remove any quotes
if Get_Arg$(1) = "READ" then ' A READ request? call ReadFile ' Go Do it else halt(8, "Unknown operation request - " + Get_Arg$(1)) end if halt(0)
'----- READ routine function ReadFile() local lText as string if file_Exists(fname) = %False then halt(8, "Requested filename does not exist") '---------------------------------------------------- ' At this point the real transform input would take ' place. The code below just does a trivial file read. '---------------------------------------------------- fnum = FILE_OPEN(fname, "INPUT") ' Try opening it if fnum = 0 then halt(8, "File OPEN failed") ' Oops! do while FILE_EOF(fnum) = %False ' Read file lText = FILE_LineInput(fnum) ' Get a line from the file RC = SPF_XFORM_Put(lText) ' Pass line to SPFLite -- MUST BE A VARIABLE loop ' FILE_CLOSE(fnum) ' Close file now halt(OK, "") ' Say all is well end function
|
|
|
Post by George on Apr 1, 2020 15:37:46 GMT -5
Robert: The XFORM macro is called with a READ / WRITE parameter.
i.e. XFORMLOAD READ file-name or XFORMLOAD WRITE file-name
Maybe the recommendation would be for the WRITE function to use the passed file-name only as the basis for creating the output file. e.g. it could add .XFORM as a new level. This would remove all the problems of writing back to the same named file as is being edited.
I still have to figure out how that involves things with CREATE/REPLACE/SAVEAS etc.
I think I might try and create a FileDump XFORM, like Stefan mentioned, that would display a file in the old mainframe dump format with hex on the left and character on the right. Be interesting to try. Leave the WRITE to mull a bit longer.
George
|
|
|
Post by George on Apr 2, 2020 10:16:00 GMT -5
Robert: Call it IMPORT/EXPORT or READ/WRITE, we're talking the same thing.
The problem is in trying to do this with the minimum disruption to existing logic flow. There is already one 'filter' point, in the file Write routine - and there is only one write routine. But that routine doesn't even know whether the file it's asked to write is the main edit file, a MEDIT sub-file, a CREATE/REPLACE file, etc. making it hard to know whether to pass it to XFORM for handling. The write routine is simply passed an internal file control block and told - Write these lines to that file. It's not as simple as asking whether the current edit file profile specifies an XFORM macro or not.
I'm not saying it can't be done, I just need more time to browse the code and get back to speed on what's going on before I start poking at it.
And the 1st half needs a lot more playing with, I'm sure the bugs are just waiting to fall out of the tree.
George
|
|