Created
October 29, 2010 22:57
-
-
Save Minoru/654618 to your computer and use it in GitHub Desktop.
VERY simple Haskell shell to C translator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <sys/wait.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <errno.h> | |
int exec_command(const char**); | |
int exec_command(const char* cmd[]) { | |
/* | |
* Executes specified command | |
* | |
* Returns exit status of executed command, or, if command was killed by a | |
* signal, 128+signum, or -1 if fork() failed | |
*/ | |
pid_t pid = fork(); | |
if(pid == -1) { | |
perror("Error in fork()"); | |
// returning -1 is bad, but what should I do? | |
return 126; | |
} | |
if(pid) { | |
int retval; | |
waitpid(pid, &retval, 0); | |
if(WIFEXITED(retval)) { | |
return WEXITSTATUS(retval); | |
} else { | |
// killed by signal | |
// return 128+number of signal that teminated our child | |
return 128 + WTERMSIG(retval); | |
} | |
} else { | |
execvp(cmd[0], (char * const*)cmd); | |
perror("Error in execvp()"); | |
switch (errno) { | |
case EACCES: | |
_exit(127); | |
break; | |
default: | |
_exit(126); | |
} | |
} | |
return 0; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- task1.hs | |
-- Task: | |
-- write a simple generator of C code (in Haskell) | |
-- | |
-- Let's say you have a list of commands, each represented by a list of strings. | |
-- Write a Haskell function which would generate a complete C program executing | |
-- those commands. | |
-- | |
-- As I said above, you might want to pull as much code as possible outside the | |
-- generator. To achieve this, create a C file ("library") with auxiliary | |
-- functions. | |
type Command = [String] | |
type C = String | |
genC :: [Command] -> C | |
genC (x:xs) = helper "" "" 0 (x:xs) | |
where helper :: C -> C -> Int -> [Command] -> C | |
helper definitions code n [] = "#include \"routines.h\"\nint main(){\n" ++ definitions ++ code ++ "}\n" | |
helper definitions code n (x:[]) = helper (definitions ++ "const char* cmd" ++ show n ++ "[] = { " ++ createArray x ++ "};\nint retval;\n") (code ++ "retval = exec_command (cmd" ++ show n ++ ");\nreturn retval;\n") (n+1) [] | |
helper definitions code n (x:xs) = helper (definitions ++ "const char* cmd" ++ show n ++ "[] = { " ++ createArray x ++ "};\n") (code ++ "exec_command (cmd" ++ show n ++ ");\n") (n+1) xs | |
createArray :: Command -> C | |
createArray (x:[]) = "\"" ++ x ++ "\", NULL" | |
createArray (x:xs) = "\"" ++ x ++ "\", " ++ createArray xs | |
genC _ = "" | |
main = putStr (genC [["ping", "-c1", "google.com"], ["date"], ["tuch", "example.file"], ["ncal"], ["echo", "Hello, world!"]]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment