1. Automatic entry point preprocessor
- Posted by ghaberek (admin) May 22, 2014
- 1643 views
Forked from Re: Interesting benchmark results - Euphoria vs. Euphoria
ghaberek said...
mattlewis said...
I think wrapping it in a main() function isn't much cheating, since many languages make you do that anyways.
I do this all the time, simply as a measure of proper practice. It sure would be nice if Euphoria ran a main() routine automatically. (wink wink, nudge nudge)
Oh what the heck, here's a preprocessor that adds an entry point automatically.
Side note: does <eucode> not handle multi-line triple-quotes or multi-line backticks correctly?
entrypoint.e
include std/filesys.e include std/regex.e include std/text.e without type_check without warning constant ENTRY_POINT_FUNC_EMPTY = "" & EOL & "-- automatic entry point" & EOL & "abort( main() ) " & EOL & EOL constant ENTRY_POINT_FUNC_PARAM = "" & EOL & "-- automatic entry point" & EOL & "abort( main(length(command_line()), command_line()) )" & EOL & EOL constant ENTRY_POINT_PROC_EMPTY = "" & EOL & "-- automatic entry point" & EOL & "main()" & EOL & EOL constant ENTRY_POINT_PROC_PARAM = "" & EOL & " -- automatic entry point" & EOL & " main( length(command_line()), command_line() )" & EOL & EOL regex re_main_empty = regex:new(`^(procedure|function)\s+main\(\s*\)`) regex re_main_param = regex:new(`^(procedure|function)\s+main\(\s*integer\s+[a-zA-Z][a-zA-Z0-9_]*\s*,\s*sequence\s+[a-zA-Z][a-zA-Z0-9_]*\s*\)`) public function preprocess( sequence inFileName, sequence outFileName, sequence options = {} ) sequence routine_type = "" -- "function" or "procedure" integer has_params = 0 integer output = open( outFileName, "w" ) if output = -1 then printf( 2, "could not write file: %s", {outFileName} ) return -1 end if integer input = open( inFileName, "r" ) if input = -1 then printf( 2, "could not read file: %s", {inFileName} ) return -1 end if object line = gets( input ) while sequence( line ) do -- trim trailing whitespace line = text:trim_tail( line, "\r\n" ) if equal( line, "without entrypoint" ) then -- stop processing line = gets( input ) exit elsif regex:is_match( re_main_empty, line ) then -- this is an entry point without params sequence matches = regex:matches( re_main_empty, line ) routine_type = matches[2] has_params = 0 elsif regex:is_match( re_main_param, line ) then -- this is an entry point with params sequence matches = regex:matches( re_main_param, line ) routine_type = matches[2] has_params = 1 end if -- write out this line puts( output, line & EOL ) line = gets( input ) if length( routine_type ) then -- stop searching for an entry point exit end if end while while sequence( line ) do -- copy the rest of the lines puts( output, line ) end while close( input ) switch routine_type do -- output the appropriate entry point case "function" then if has_params then puts( output, ENTRY_POINT_FUNC_PARAM ) else puts( output, ENTRY_POINT_FUNC_EMPTY ) end if case "procedure" then if has_params then puts( output, ENTRY_POINT_PROC_PARAM ) else puts( output, ENTRY_POINT_PROC_EMPTY ) end if end switch close( output ) return 0 end function ifdef not EUC_DLL then procedure main() sequence cmds = command_line() sequence inFileName, outFileName for i = 3 to length( cmds ) do switch cmds[i] do case "-i" then inFileName = cmds[i+1] case "-o" then outFileName = cmds[i+1] end switch end for preprocess( inFileName, outFileName ) end procedure main() end ifdef
eu.cfg
[linux] -p ex:entrypoint.sh [windows] -p ex:entrypoint.cmd
entrypoint.sh
#!/bin/sh eui -batch entrypoint.e $*
entrypoint.cmd
@echo off eui.exe -batch entrypoint.e %*
test.ex (input)
namespace test function main( integer argc, sequence argv ) puts( 1, "Hello, world!\n" ) return 0 end function
test.pp.ex (output)
namespace test function main( integer argc, sequence argv ) puts( 1, "Hello, world!\n" ) return 0 end function -- automatic entry point abort( main(length(command_line()), command_line()) )
example
>eui test.ex Hello, world!
-Greg