Jump to content











Photo
- - - - -

Writing to the Grub4dos' keyboard buffer possible?

grub4dos

  • Please log in to reply
79 replies to this topic

#76 deomsh

deomsh

    Member

  • Members
  • 47 posts
  •  
    Netherlands

Posted A week ago

The board is set for giving limited capabilities to posters will less than 50 posts (this is because of spammers editing previous posts to add links to crappy sites), you are near to reach that number of posts, from then on you will have no more time limits on editing previous posts.

Thanks a lot, now this is clear to me.

 

The %* is ALL parameters excluded the %0 one.

 

In batch you have the shift command to manipulate parameter numbers/order, but the grub4dos implementation does not accept shift -1 if I recall correctly (not that it is usually needed).

Good to know about %*.

 

What I do not like so much about using shift in the main routine is losing arguments (with regard to in this 'function'-project). And if there are many arguments, it is a waste of variables, needed to hold the values of the arguments.

 

In one of my projects I was because of this *thing* condemned to endless debugging with varsleft.g4b (I believe it's from steve6375 - no author 'inside'. It's a very handy debugging-tool).

 

I experimented with call :%1 %* - seems to give no problems, I only have to test if shift inside a sub-routine does the same, without losing anything in the main routine.

 

I have been thinking about the dll-'idea' I should 'not attribute' to you.

To give this sort of call's a more unified structure, should their not be error-handling too? Although I have only vague notions of, for instance, the windows API, I know many different error-codes are needed.

 

To exemplify I made a function I really need: counting number of labels. My latest count (105 labels) took me a very long time, and I was not even sure about the final number. So I made the function 'cntlabel'. Still not very high-level, just meant to give an idea about a possible general structure.

!BAT
#FUNCTION.G4B by deomsh; thanks to Wonko the Sane
#DLL for Grub4Dos
#Arguments: function, mandatory arguments, optional arguments; errormsg: 0=No function given, 1=Function not supported
#Implemented: cntlabel (20210717)
debug off
setlocal && set *
if "%~1"=="" && set /a errormsg=0 > nul
if not exist errormsg && call :dbfunc %~1
if not exist errormsg && call :%~1 %*
endlocal && set result=%result% && set errormsg=%errormsg%
echo %1: result=%result% errormsg=%errormsg%
goto :eof

:cntlabel #Function: count number of labels; Argument: FILE; Optional: dos or mac; errormsg: 2=FILE not given, 3=FILE does not exist
setlocal && set *
if "%~2"=="" && endlocal && set /a errormsg=2 > nul && goto :eof
if not exist %~2 && endlocal && set /a errormsg=3 > nul && goto :eof
if /i "%~3"=="dos" && set EOL=\x0D\x0A ! set EOL=\x0A
if /i "%~3"=="mac" && set EOL=\x0D
echo EOL=%EOL%
cat --locate=%EOL%\x3A %~2 > nul &; set /a result=%@retval% > nul
endlocal && set result=%result%
goto :eof

:dbfunc #database of available functions
setlocal && set *
if not /i %~1==cntlabel && endlocal && set /a errormsg=1 > nul && goto :eof
endlocal
goto :eof

This is the 'print-screen' of the output (the optional argument gives also more possible uses of cntlabel):

grub> (hd0,0)/function.g4b
: result: errormsg=0 
grub> (hd0,00/function.g4b cntlabe 
cntlabe: result= errormsg=1 
grub> (hd0,0)/function.g4b cntlabel (hd0,0)/fattext.g4d
cntlabel: result= errormsg=3 
grub> (hd0,0)/function.g4b cntlabel (hd0,0)/fattext.g4b 
EOL=\x0A 
cntlabel: result=102 errormsg= 
grub> (hd0,0)/function.g4b cntlabel (hd0,0)/fattext.g4b dos 
EOL=\x0D0A 
cntlabel: result=102 errormsg= 
grub> (hd0,0)/function.g4b cntlabel (hd0,0)/fattext.g4b mac 
EOL=\X0D 
cntlabel: result= errormsg= 
grub> (hd0,0)/function.g4b cntlabel (hd0,0)/fattext.g4b ms-dos 
EOL=\0Ax 
cntlabel: result=102 errormsg= 
grub>

BTW I tried to make textual error messages too, but today I was plagued again by Error 16 Inconsistent filesystem structure. Has something to do with editing files in Windows in combination with Imdisk to have access to VBox in combination with 'saving' grub4dos-sessions in VBox. After 'refreshing everything' Error 16 disappeared.

 

What do you think about error-handling?
 



#77 deomsh

deomsh

    Member

  • Members
  • 47 posts
  •  
    Netherlands

Posted A week ago

Edit 'print-screen':

OCR was bad this time, my eyes too. The echo of the three last EOL-codes should have been the following ones:

EOL=\x0D\x0A

EOL=\x0D

EOL=\x0A

Edited by deomsh, A week ago.


#78 Wonko the Sane

Wonko the Sane

    The Finder

  • Advanced user
  • 15707 posts
  • Location:The Outside of the Asylum (gate is closed)
  •  
    Italy

Posted A week ago

Every time you use call or invoke a file with parameters, it is a different stack of % parameters.

Using shift in "main" will shift the "main" ones, if you use shift in a subroutine it will shift the "call" parameters.

No problem there.

 

About error checking/handling, it could be a nice feature, but (IMHO) not needed and actually overkill in the specific case of "dividing" a large batch in a "main program"+"functions library".

 

I mean - unlke the mathfunc.g4b (lousy) example, the idea of a .lll file is that it is "never" called from command line, but only by programs, so it is the program Author that is responsible for calling the library (rectius the function in it) with the correct parameters.

 

If the idea is that of using these functions from command line, it would still make sense to have an intermediate level (not entirely unlike the rundll32.exe) that takes care of validating the user input/parameters and echo result(s) in a suitable format.

 

:duff:

Wonko


  • deomsh likes this

#79 deomsh

deomsh

    Member

  • Members
  • 47 posts
  •  
    Netherlands

Posted 14 hours ago

@Wonko
I played a bit with your (?) idea of 'Loosely Linked Libraries' and I 'found' following structure.

Because with call :%1 %* it is possible to link to other .LLL-files, I think it could be useful, from a developmental perspective, to split the FUNCTION-file you envisioned in 'Implemented' and 'Linked' functions. The 'Linked' functions can be still in development, while the 'Implemented' functions are (more or less) 'ready'. Also the .LLL-files have the same structure, so can be tested from the command-line too (Grub4Dos doesn't care, as long !BAT is on the first line). After finishing a 'Linked' function, all that has to be done is copying the call-part to the main FUNCTION.G4B. For example I found my function 'CntLabel' counted '::' at the beginning of a line too, so already a (small) revision was needed (I always use # before a comment).

Below the structure of the general file FUNCTION.G4B and as an example MAKEUUID.LLL (echos should be commented out later).

!BAT
#FUNCTION.G4B v0.1.5 by deomsh, based on idea of Wonko the Sane
#DLL for Grub4Dos (version: from 2019)
#Arguments: Function, Mandatory Arguments, Optional Arguments
#Implemented: CntLabel; CntLine;
#Linked to .lll-file: CopyFile; IsMaxLen; ParseArg; ParseCmd; MakeUuid
debug status > nul ;; set debugsts=%@retval% ;; debug 0
echo %*
call :%~1 %*
echo Function: %1 result=%result%
debug %debugsts%
set debugsts=
goto :eof

:CopyFile
call CopyFile.lll %*
goto :eof

:IsMaxLen
call IsMaxLen.lll %*
goto :eof

:ParseArg
call ParseArg.lll %*
goto :eof

:ParseCmd
call ParseCmd.lll %*
goto :eof

:MakeUuid
call MakeUuid.lll %*
goto :eof

:CntLabel
#Function: count number of labels; Argument: FILE; Optional: dos or mac
setlocal && set *
set file=%~2 &; if "%file:~0,4%"=="(md)" && set FILE=%~dnx2 ! set FILE=%~dpnx2
if /i "%~3"=="dos" && set EOL=\x0D\x0A ! set EOL=\x0A
if /i "%~3"=="mac" && set EOL=\x0D
cat --locate=%EOL%\x3A %FILE% > nul &; set /a count1=%@retval% > nul
cat --locate=%EOL%\x3A\x3A %FILE% > nul &; set /a count2=%@retval% > nul
set /a result=%count1% > nul && if exist count2 && set /a result=%count1%-%count2% > nul
endlocal && set result=%result%
goto :eof

:CntLine
#Count lines in textfile; Argument: FILE; Optional: dos|unix|mac; Default: dos
setlocal && set *
set file=%~2 &; if "%file:~0,4%"=="(md)" && set FILE=%~dnx2 ! set FILE=%~dpnx2
if /i not "%~3"=="" if /i not "%~3"=="dos" || set EOL=\x0D\x0A &; cat --locate=%EOL% %FILE% > nul &; set /a result=%@retval% > nul
if /i "%~3"=="dos" && set EOL=\x0D\x0A &; cat --locate=%EOL% %FILE% > nul &; set /a result=%@retval% > nul
if /i "%~3"=="unix" && set EOL=\x0A &; cat --locate=\x0D %FILE% > nul |; cat --locate=%EOL% %FILE% > nul &; set /a result=%@retval% > nul
if /i "%~3"=="mac" && set EOL=\x0D &; cat --locate=\x0A %FILE% > nul |; cat --locate=%EOL% %FILE% > nul &; set /a result=%@retval% > nul
if not exist result && set /a result=0 > nul
endlocal && set result=%result%
goto :eof

:CleanMd
#cleans md-device with '00'
#Arguments: MdBase, Sectors; Optional: Skip
setlocal && set *
set /A basemd=%~2 > nul
set /A memrange=%~3 > nul
set /A skipmem=%~4 > nul
set /A "basemd=%basemd% * 0x200 + %skipmem%" > nul
set /A "memrange=%memrange% * 0x200 - %skipmem%" > nul
call Fn.24 %basemd% 0x00 %memrange% > nul
set /A result=%@retval% > nul
if %result%>=1 && set /a result=1 > nul ! set /a result=0 > nul
endlocal && set result=%result%
goto :eof

!BAT
#MAKEUUID.LLL v0.1 (20210727), by deomsh. Based on unpublished VOLUUID.G4B (20200615)
#Generate MS-DOS Volume Serial Number
#Mandarory Argument: MakeUuid
echo %*
call :%~1
echo Function: %~1 result=%result%
goto :eof

:MakeUuid
setlocal && set *
#debug 0
set date=%@date%
set /a year=%date:~0,4% > nul
set /a month=%date:~5,2% > nul
set /a day=%date:~8,2% > nul
#echo date: %day%-%month%-%year% 
set time=%@time%
set /a hour=%time:~0,2% > nul
set /a minute=%time:~3,2% > nul
set /a second=%time:~6,2% > nul
set /a minute=%time:~3,2% > nul
#set /a smallsec= > nul
#echo time: %hour%:%minute%:%second%:%smallsec%
if not exist smallsec && set /a random=%@random% > nul ! set /a random=%smallsec% > nul
#echo random: %random%
if %random%>=100 && set /A smallsec=%random% / 10 > nul
if %random%>=1000 && set /A smallsec=%random% / 100 > nul
if %random%>=10000 && set /A smallsec=%random% / 1000 > nul
set /A month=%date:~5,2% * 0x100  > nul
set /A second=%time:~6,2% * 0x100 > nul
#echo month: %month% day: %day% second: %second% smallsec: %smallsec%
set /A uuidlow=%month% + %day% + %second% + %smallsec% > nul
set /a llow=%@retval% > nul
#echo llow: %llow%
#echo uuidlow: %uuidlow%
set /A hour=%time:~0,2% * 0x100 > nul
#echo hour: %hour% minute: %minute% year: %year%
set /A uuidhigh=%hour% + %minute% + %year% > nul
set /a lhigh=%@retval% > nul
#echo lhigh: %lhigh%
#echo uuidhigh: %uuidhigh%
echo Volume Serial Number: %uuidlow:~2,4%-%uuidhigh:~2,4% 
if %lhigh%==6 && if %llow%==6 && set volumeid=x%uuidhigh:~4,2%\x%uuidhigh:~2,2%\x%uuidlow:~4,2%\x%uuidlow:~2,2% > nul
if %lhigh%==6 && if %llow%==5 && set volumeid=x%uuidhigh:~4,2%\x%uuidhigh:~2,2%\x%uuidlow:~3,2%\x0%uuidlow:~2,1% > nul
if %lhigh%==5 && if %llow%==6 && set volumeid=x%uuidhigh:~3,2%\x0%uuidhigh:~2,1%\x%uuidlow:~4,2%\x%uuidlow:~2,2% > nul
if %lhigh%==5 && if %llow%==5 && set volumeid=x%uuidhigh:~3,2%\x0%uuidhigh:~2,1%\x%uuidlow:~3,2%\x0%uuidlow:~2,1% > nul
#echo Volume Serial Number little-endian: \%volumeid% (write (md)-ready)
#echo Volume Serial Number big-endian: %uuidlow:~2,4%%%uuidhigh:~2,4%
#endlocal && set volumeid=%volumeid%
endlocal && set result=%volumeid%
goto :eof

BTW Use of the .G4B-extension for FUNCTION.G4B seems more 'universal' to me (in case of use of command --set-ext=.g4b in MENU.LST).

 

BTW2 Central use of setlocal/ endlocal doesn't seem flexible enough to me if more than one variable, or an unknown number of variables is returned.

BTW3 Calling such batch-files by accident (without %1 = Function) seems 'safe' to me, nothing has been changed (in case of FUNCTION.G4B unless variable debugsts is used before - may be better not centralized too?).

What bothers me is the question of 'Memory Management'.

If a function needs working memory, I wonder if it would be better to use the main routine allocating memory to a function (with an optional argument), or use (a set of) fixed memory-addresses for all functions (which the main routine shouldn't use)?


Edited by deomsh, 14 hours ago.


#80 Wonko the Sane

Wonko the Sane

    The Finder

  • Advanced user
  • 15707 posts
  • Location:The Outside of the Asylum (gate is closed)
  •  
    Italy

Posted 4 hours ago

It seems nice to me. :)

 

Though (if the idea is to save memory/variables) you don't really-really need to assign all variables, unless you need in the formula to parse the values.

I.e.:

:CleanMd
#cleans md-device with '00'
#Arguments: MdBase, Sectors; Optional: Skip
setlocal && set *
set /A basemd=%~2 > nul
set /A memrange=%~3 > nul
set /A skipmem=%~4 > nul
set /A "basemd=%basemd% * 0x200 + %skipmem%" > nul
set /A "memrange=%memrange% * 0x200 - %skipmem%" > nul
call Fn.24 %basemd% 0x00 %memrange% > nul
set /A result=%@retval% > nul
if %result%>=1 && set /a result=1 > nul ! set /a result=0 > nul
endlocal && set result=%result%
goto :eof

could well be:

:CleanMd
#cleans md-device with '00'
#Arguments: MdBase, Sectors; Optional: Skip
setlocal && set *
set /A "basemd=%~2 * 0x200 + %~4" > nul
set /A "memrange=%~3 * 0x200 - %~4" > nul
call Fn.24 %basemd% 0x00 %memrange% > nul
set /A result=%@retval% > nul
if %result%>=1 && set /a result=1 > nul ! set /a result=0 > nul
endlocal && set result=%result%
goto :eof

Three variable assignments removed, not noticeable at all, particularly because the function will be run once or very rarely, still, as a general rule using as much as possible the call parameters reduces usage of variables ...

 

As a side-note/OT question, the UUID generator uses the officially unofficial DOS algorithms, doesn't it? :unsure:

 

https://msfn.org/boa...&comment=980297

 

https://msfn.org/boa...#comment-987748

 

A couple small nitpicks (at first sight)  in:

 

#echo date: %day%-%month%-%year%
set time=%@time%
set /a hour=%time:~0,2% > nul
set /a minute=%time:~3,2% > nul
set /a second=%time:~6,2% > nul
set /a minute=%time:~3,2% > nul
#set /a smallsec= > nul
#echo time: %hour%:%minute%:%second%:%smallsec%
if not exist smallsec && set /a random=%@random% > nul ! set /a random=%smallsec% > nul
#echo random: %random%
if %random%>=100 && set /A smallsec=%random% / 10 > nul
if %random%>=1000 && set /A smallsec=%random% / 100 > nul
if %random%>=10000 && set /A smallsec=%random% / 1000 > nul

 

 

#1 You have duplicated the minute assignment, probably a copy/paste effect :unsure:

#2 I am not too convinced of the formula for reducing the random value into a 0<=x<=99 range  :dubbio: I have to think about it ...

 

:duff:

Wonko

 

P.S.: No, I confirm, dividing by 10/100/1000 doesn't give "random enough" results, you'd better get two digits, i.e. *something like*:

set smallsec=%@random::~-2%

or (to avoid possible leading 0, and get an actual numeric value)

set /a smallsec=1%@random::~-2%-100

or

set /a smallsec=1%@random::~-1%1%@random::~-1%-100







Also tagged with one or more of these keywords: grub4dos

1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users