A way to use C in (Pure) batch

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
NunoLava1998
Posts: 10
Joined: 01 Mar 2015 10:06

A way to use C in (Pure) batch

#1 Post by NunoLava1998 » 29 Jan 2017 08:26

Well, not so pure because you have to have a compiler. This batch file uses tcc.
Works fine for me:

Code: Select all

// >nul 2>&1 & @echo off
int dummy0(void) { // >nul 2>&1
   int i; // >nul 2>&1 & goto bat
   return 0; // >nul 2>&1
} // >nul 2>&1
#include <stdio.h>
int main(void)
{
   printf("Welcome to the C/Batch hybrid!");
   return 0;
};

/* >nul 2>&1
:bat
;@echo off
type %~n0.bat >> %~n0_C.c
tcc -o %~n0.exe %~n0_C.c
del %~n0_C.c
call %~n0.exe %*
del %~n0.exe
exit /b

*/ // >nul 2>&1


Output:
Image

How do you change the compiler?

Change the line

Code: Select all

tcc -o %~n0.exe %~n0_C.c
to something else. Be sure to specify %~n0_C.c as the file you want to compile and %~n0.exe as the file you want to be generated.

Well, what if you WANT more batch?

Just add it in the multi-line comment. There are a few additions to trick the C code and to trick the Batch code, so it doesn't give a bunch of errors when loading this.

But how does it work???

Code: Select all

// >nul 2>&1 & @echo off
This piece of code works in both C and Batch. It's meaningless in C, but meaningful in Batch. It's basically "@echo off".

C Compiler perspective:
Hey, look, //! That's a single-line comment. I'm gonna ignore everything here, which in this case is ">nul 2>&1 & @echo off".
Batch Parser perspective:
I don't know what is the command //. Redirect it to stdout instead of stderr and redirect it to nul beacuse of >nul 2>&1. Wait, what's this &? Another command. This one says to do @echo off. I can do that! (does @echo off)

Code: Select all

int dummy0(void) { // >nul 2>&1
   int i; // >nul 2>&1 & goto bat
   return 0; // >nul 2>&1
} // >nul 2>&1


C Compiler perspective:
So basically, we make a function "dummy0" with int return type that returns 0 and defines "i".
Batch perspective:
What is that first line? Ignoring it.
The second? Hmm... so go to the label "bat". Okay.
The other ones? Yep, just ignore them.

Code: Select all

#include <stdio.h>
int main(void)
{
   printf("Welcome to the C/Batch hybrid!");
   return 0;
};


C Compiler perspective:
Print "Welcome to the C/Batch hybrid!" and leave.
Batch perspective:
(never loads this)

Code: Select all

/* >nul 2>&1


C perspective: Multi line comment! Ignoring...
Batch perspective: What is /*? Oh well, ignoring it.

Code: Select all

:bat

C perspective: Comment...
Batch perspective: Look, the label we were looking for! Go!

Code: Select all

;@echo off
type %~n0.bat >> %~n0_C.c
tcc -o %~n0.exe %~n0_C.c
del %~n0_C.c
call %~n0.exe %*
del %~n0.exe
exit /b


C perspective: Still a comment...
Batch perspective: So @echo off, and type this program's code to %~n0_C.c.
Alright, what's next? Ah, use tcc. Then, delete %~n0_C.c and let's call %~n0.exe with all of our arguments.
Next, we'll delete it and exit.

Code: Select all

*/ // >nul 2>&1


C perspective: End of multiline comment and start of single line comment. It contains >nul 2>&1.
Batch parser perspective: I have no idea what is */ //, but i'll not give an error.

NunoLava1998
Posts: 10
Joined: 01 Mar 2015 10:06

Re: A way to use C in (Pure) batch

#2 Post by NunoLava1998 » 29 Jan 2017 14:18

An example of what can be done (This is a color text program, in this case):

Code: Select all

// >nul 2>&1 & @echo off
int dummy0(void) { // >nul 2>&1
   int i; // >nul 2>&1 & goto bat
   return 0; // >nul 2>&1
} // >nul 2>&1
#include <windows.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
   HANDLE h_std_out = GetStdHandle(STD_OUTPUT_HANDLE);
   CONSOLE_SCREEN_BUFFER_INFO csbi;
   GetConsoleScreenBufferInfo( h_std_out, &csbi );
   SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), atoi(*argv[1]);
   printf("%s", argv[2]);
   SetConsoleTextAttribute( h_std_out, csbi.wAttributes );
   return 0;
};

/* >nul 2>&1
:bat
;@echo off
echo Batch execution started.
type %~n0.bat >> %~n0_C.c
tcc -o %~n0.exe %~n0_C.c
del %~n0_C.c
echo C mode starting.
call %~n0.exe %*
echo C mode terminated.
del %~n0.exe
echo Batch execution terminated.
goto :eof

:end
*/ // >nul 2>&1 & exit /b


Output:

Image

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

Re: A way to use C in (Pure) batch

#3 Post by penpen » 29 Jan 2017 15:24

NunoLava1998 wrote:Well, not so pure because you have to have a compiler.
That' not a reason why it shouldn't be hybrid:
Any hybrid needs another executable to use the same file in different ways.
For example a typical JScript/bat hybrid needs cmd.exe (for batch) and CScript.exe/WScript.exe (for JScript).

The main reason for hybrid files is to avoid temporary additional files.
Because of that your solution is a little bit sub-optimal (you create an additional temporary ".c" file).
One could say because of that it may be not a real hybrid file - although the source is "C/bat" hybrid.

I'm not familiar with tcc, but i know that the Microsoft C/C++ compiler (used by Visual Studio) is able
to use any text file as an input source file by using the appropriate option(s) /Tc /TC /Tp /TP.

If something like that is also possible using tcc, then you better should use that (and then it 'really' is a hybrid).


penpen

Aacini
Expert
Posts: 1914
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: A way to use C in (Pure) batch

#4 Post by Aacini » 29 Jan 2017 15:33

I think that the combination of different source codes is simpler this way:

Code: Select all

/* 2>nul & @echo off

echo Batch code here

goto :EOF

*/

C code here...

And the compilation of the same file in C can be done this way (independently of compiler options):

Code: Select all

(
ren "%0" "%~n0.c"
tcc -o %~n0.exe %~n0.c
ren "%~n0.c" "%0"
)

Antonio

NunoLava1998
Posts: 10
Joined: 01 Mar 2015 10:06

Re: A way to use C in (Pure) batch

#5 Post by NunoLava1998 » 30 Jan 2017 01:56

penpen wrote:
NunoLava1998 wrote:Well, not so pure because you have to have a compiler.
That' not a reason why it shouldn't be hybrid:
Any hybrid needs another executable to use the same file in different ways.
For example a typical JScript/bat hybrid needs cmd.exe (for batch) and CScript.exe/WScript.exe (for JScript).

The main reason for hybrid files is to avoid temporary additional files.
Because of that your solution is a little bit sub-optimal (you create an additional temporary ".c" file).
One could say because of that it may be not a real hybrid file - although the source is "C/bat" hybrid.

I'm not familiar with tcc, but i know that the Microsoft C/C++ compiler (used by Visual Studio) is able
to use any text file as an input source file by using the appropriate option(s) /Tc /TC /Tp /TP.

If something like that is also possible using tcc, then you better should use that (and then it 'really' is a hybrid).


penpen


Because you can't rename your own file and tcc does not support compiling .C files, I have to write the contents of the file into another file with a .c extension. I can then compile that. Besides, I wanted a batch file that just ran C. What this basically is:

A file that can be compiled with both C and Batch compilers (gcc may give an error that dummy0(); isn't used) which uses the advantage of comments and multi-line comments.

Post Reply