Add error feedback to batch script

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
settinger
Posts: 2
Joined: 26 Apr 2016 02:13

Add error feedback to batch script

#1 Post by settinger » 26 Apr 2016 03:00

Hey all,

Here's my code, the description of what it does is below it.

Code: Select all

:: Batch script: convert plaintext coordinates into arduino-usable .ino file

@ECHO off
SETLOCAL enabledelayedexpansion

(
  :: Create a line counter
  SET /a line=0
  :: Opening of the .ino file
  ECHO.float waypoints[][3] = {
  :: Load file line-by-line, commas as delimiters
  FOR /f "tokens=1,2,3 delims=," %%a IN (path.txt) DO (
    :: Increment line count (unused)
    SET /a line+=1

    SET x=%%a
    :: Remove any spaces
    SET x=!x: =!
    SET y=%%b
    :: Remove any spaces
    SET y=!y: =!
    SET z=%%c
    :: Remove any spaces
    SET z=!z: =!
    ECHO.{!x!, !y!, !z!},
  )
  :: Close the .ino file
  ECHO.};
)>path.ino


* * * * *

I'm very new to batch scripting. Right now I have a .bat that takes a file "path.txt," formats each line, and writes the output to "path.ino" in a format that Arduino can compile. Each line of "path.txt" is supposed to have three comma-separated numbers (extra spaces are stripped, the comma is the delimiter). So, for example, if "path.txt" looked like

Code: Select all

0.0, 0.0, 0.0
1.0, -1.3, -0.6
2 , 41, -3.14

then "path.ino" would look like

Code: Select all

float waypoints[][3] = {
{0.0, 0.0, 0.0},
{1.0, -1.3, -0.6},
{2, 41, -3.14},
};


The script I pasted above works fine for this purpose. HOWEVER, I'm trying to add some type of error handling--that is, if the script encounters a line with fewer than three numbers, or if there are non-numeric characters present, I'd like to be able to tell the user "Problem occurred on line #[whatever]", and abort the script (without creating path.ino). How can this be done?

I'm sorry I don't have any attempts to show you right now. I am still struggling to plan out the next step, I thought I'd go ahead and ask before I make my own attempt.

Let me know what else I can contribute!

Thanks,
Sam

thefeduke
Posts: 211
Joined: 05 Apr 2015 13:06
Location: MA South Shore, USA

Re: Add error feedback to batch script

#2 Post by thefeduke » 27 Apr 2016 01:58

This uses your structure to check for the errors as you described. I added a blank to the delimiters in the main FOR command so there is no need to compress the gas. I am not sophisticated enough to handle %%a, %%b and %%c in one pass.

Code: Select all

:: Batch script: convert plaintext coordinates into arduino-usable .ino file

@ECHO off
SETLOCAL enabledelayedexpansion

  :: Create a test file
(
  ECHO.0.0, 0.0, 0.0
  ECHO.0.0, 0x.0, 0.0
  ECHO.1.0, -1.3, -0.6
  ECHO.1.0, -1.3, -0.6 4
  ECHO.2 , 41, -3.14
  ECHO.2 , 41
  ECHO.    41
  ECHO.2 , , +3.14
  ECHO.2 , , 3.14
)>%Temp%\%~n0_in.txt

(
  :: Create a line counter
  SET /a line=0
  SET   "BadLines= "
  :: Opening of the .ino file
  ECHO.float waypoints[][3] = {
  :: Load file line-by-line, commas as delimiters
  FOR /f "tokens=1,2,3* delims=, " %%a IN (%Temp%\%~n0_in.txt) DO (
    :: Increment line count
    SET /a line+=1
    IF .%%d NEQ . (
        Set "Errline[!line!]=Line '!line!' has extra information '%%d'"
        Set "BadLines=!BadLines! !Line!"
    )
    IF .%%c EQU . (
        Set "Errline[!line!]=Line '!line!' is missing third number."
        Set "BadLines=!BadLines! !Line!"
    )
    for /f "delims=-0.123456789" %%V in ("%%c") do (
        Set "Errline[!line!]=Line '!line!' has invalid character '%%V'."
        Set "BadLines=!BadLines! !Line!"
    )
    IF .%%b EQU . (
        Set "Errline[!line!]=Line '!line!' has only one number."
        Set "BadLines=!BadLines! !Line!"
    )
    for /f "delims=-0.123456789" %%V in ("%%b") do (
        Set "Errline[!line!]=Line '!line!' has invalid character '%%V'."
        Set "BadLines=!BadLines! !Line!"
    )
    for /f "delims=-0.123456789" %%V in ("%%a") do (
        Set "Errline[!line!]=Line '!line!' has invalid character '%%V'."
        Set "BadLines=!BadLines! !Line!"
    )
    ECHO.{%%a, %%b, %%c},
  )
  :: Close the .ino file
  ECHO.};
)>%Temp%\%~n0_out.txt

  IF "%BadLines%" EQU " " (
      ECHO.Creating .ino file.
      Copy /Y %Temp%\%~n0_out.txt %~n0.ino
  ) Else (
      ECHO.Error messages:
      :: These variables can be used for error display
      Set "BadLines"
      Set Err
      Exit /B 1
  )

  Exit /b


John A.

penpen
Expert
Posts: 1992
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Add error feedback to batch script

#3 Post by penpen » 27 Apr 2016 02:17

If you want to provide an error feedback without creating the ".ino"-output file,
then you have to seperate the file-creation-step; maybe you could:
- use a temporary file to store the intermediate file, or
- you could read the complete file into ram (in this case environment variables).

Because you are writing some sort of compiler, i would not abort the script on problems, so the user may see all problems listed.
I also would differ between warnings (may be errors, but the compile step would complete successfully) and
errors (the compilation cannot complete).

The first possibility should be used if the amount of data is big, or unknown.
In this case these files are short (3 lines allowed, and i guess each line is <8000 bytes long),
so i would prefer the second solution ("process.bat"):

Code: Select all

@echo off
setlocal enableExtensions disableDelayedExpansion
set /a "warnings=errors=0"

:: loading
:: read file specified in first argument
for /f "tokens=1* delims=:" %%a in ('findstr /n "^" "%~1"') do if %%~a leq 4 set "line[%%~a]=%%~b"

setlocal enableDelayedExpansion
:: preprocessing
:: normalize file: Remove unwanted spaces (all except the one after each comma which must be present)
:: you should use another space removing algorithm to avoid numbers like "123 456.4" to be recognized as valid numbers
for /l %%a in (1, 1, 3) do (
   set "line[%%~a]=!line[%%~a]: =!"
   set "line[%%~a]=!line[%%~a]:,=, !"
)
:: ...

:: error handling
:: check for the right line numbers value
for /l %%a in (1, 1, 3) do if not defined line[%%~a] set /a "errors+=1" & echo(Problem occurred on line %%~a: Line %%~a is empty.
if defined "line[4]" set /a "warnings+=1" & echo(Warning: Problem occurred on line 4: Found more than 4 lines.

:: check for unwanted characters, if no error occured
for /l %%a in (1, 1, 3) do (
   set "test=!line[%%~a]!"
   for %%b in ("+" "-" 0 1 2 3 4 5 6 7 8 9 "." "," " ") do set "test=!test:%%~b=!"
   if defined test set /a "errors+=1" & echo(Error: Problem occurred on line %%~a: Found unwanted character^(s^): "!test!".
)

:: check if all values are present and no more
for /l %%A in (1, 1, 3) do for /f "tokens=1-4" %%a in ("!line[%%~A]!") do (
   if "%%~a" == ""  set /a "errors+=1" & echo(Error: Problem occurred on line %%~a: Value x not found.".
   if "%%~b" == "" set /a "errors+=1" & echo(Error: Problem occurred on line %%~a: Value y not found.".
   if "%%~c" == "" set /a "errors+=1" & echo(Error: Problem occurred on line %%~a: Value z not found.".
   if not "%%~d" == "" set /a "warnings+=1" & echo(Warning: Problem occurred on line %%~a: Found more than 3 values.".
)


:: ...


:: processing
for /l %%a in (1, 1, 3) do set "line[%%~a]={!line[%%~a]!},"
:: if you would prefer to have no comma on line 3 use the next line
:: set "line[3]=!line[3]:~0,-1!"


:: output file if no error is present, else output error
set /a "problems=warnings+errors"
if %problems% == 0 (
(
      echo(float waypoints^[^]^[3^] = ^{
      for /l %%a in (1, 1, 3) do echo(!line[%%~a]!
      echo(^}^;
   )
   pause
) else if %errors% == 0 (
   echo(Found !warnings! warnings.
   rem maybe optional compile such as "Do you want to compile anyway? [Y,N]: " instead of pausing
   pause
) else (
   echo(Found !warnings! warnings and !errors! errors.
   pause
)

endlocal
endlocal
(I hope there is no error in it: Actually i cannot test it.

Use this to process path.txt:

Code: Select all

"process.bat" "path.txt"
This has the advantage, that you could drag "path.txt" files and drop it on "process.bat".


penpen

Edit: Thanks to thefeduke for testing, i also removed another flaw: Should work now.
Last edited by penpen on 29 Apr 2016 07:19, edited 1 time in total.

settinger
Posts: 2
Joined: 26 Apr 2016 02:13

Re: Add error feedback to batch script

#4 Post by settinger » 27 Apr 2016 22:18

thefeduke wrote:I added a blank to the delimiters in the main FOR command so there is no need to compress the gas

I see. I thought having multiple delimiters would create additional tokens in-between the commas and spaces, thank you for correcting this. I'm not sure what you mean by "compress the gas," though...

Even without handling all the tokens in one pass, this is a great solution. Thanks, John (and penpen)!

sambul35
Posts: 192
Joined: 18 Jan 2012 10:13

Re: Add error feedback to batch script

#5 Post by sambul35 » 28 Apr 2016 07:54

@penpen

Thanks for useful code ideas, and willingness to share broad programming experience. :D
Last edited by sambul35 on 28 Apr 2016 16:22, edited 1 time in total.

thefeduke
Posts: 211
Joined: 05 Apr 2015 13:06
Location: MA South Shore, USA

Re: Add error feedback to batch script

#6 Post by thefeduke » 28 Apr 2016 14:58

sambul35 wrote:@penpen

Thanks for useful code ideas. :D
I'll second that. I liked the organization so much that I tried to run it, and so became a tester for penpen.
penpen wrote:(I hope there is no error in it: Actually i cannot test it.
I found it to function when I made the following changes:

Code: Select all

****** ******************************** Top of Data **********************************
------ ------------------------------------------------------------- < 000001 > ------
000002 :: penpen - Post subject: Re: Add error feedback to batch script               
000003 :: http://www.dostips.com/forum/viewtopic.php?p=46427#p46427                   
------ ------------------------------------------------------------- < 000005 > ------
000009 for /f "usebackq tokens=1* delims=:" %%a in (`findstr /n "^" "%~1"`) do (     
000010 Rem.Added back-quotes to IN                                                   
------ ------------------------------------------------------------- < 000008 > ------
000019 Rem.Added array subscripts                                                     
000020    set "line[%%a]=!line[%%a]: =!"                                             
------ ------------------------------------------------------------- < 000007 > ------
000028 for /l %%a in (1, 1, 3) do if not defined line[%%~a] set /a "errors+=1" & echo(
000029 Rem.Removed double quotes from defined                                         
000030 if defined line[4] set /a "warnings+=1" & echo(Warning: Problem occurred on lin
------ ------------------------------------------------------------- < 000003 > ------
000034 Rem.Added array subscript                                                     
000035    set "test=!line[%%a]!"                                                     
------ ------------------------------------------------------------- < 000041 > ------
****** ******************************* Bottom of Data   ********************************
I must admire anyone who can write that much code without testing.

John A.

Post Reply