Author | Jamozed <[email protected]> |
Date | 2021-01-15 01:08:47 |
Commit | 8e5fd79617a63e4877d24408528bc36594e2f6c9 |
Restore OSH 0.2.1 to Git
Diffstat
A | .gitignore | | | 5 | +++++ |
A | BuildUNIX.sh | | | 10 | ++++++++++ |
A | CHANGELOG | | | 18 | ++++++++++++++++++ |
A | CMakeLists.txt | | | 13 | +++++++++++++ |
A | LICENCE | | | 24 | ++++++++++++++++++++++++ |
A | README.md | | | 24 | ++++++++++++++++++++++++ |
A | src/alias.c | | | 84 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/alias.h | | | 48 | ++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/bltn.c | | | 69 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/bltn.h | | | 39 | +++++++++++++++++++++++++++++++++++++++ |
A | src/bltns/cd.c | | | 59 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/bltns/pwd.c | | | 58 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/exec.c | | | 82 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/exec.h | | | 40 | ++++++++++++++++++++++++++++++++++++++++ |
A | src/lex.c | | | 78 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/lex.h | | | 46 | ++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/lib/error.c | | | 55 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/lib/error.h | | | 43 | +++++++++++++++++++++++++++++++++++++++++++ |
A | src/lib/optget.c | | | 122 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/lib/optget.h | | | 55 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/main.c | | | 79 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/parse.c | | | 58 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/parse.h | | | 40 | ++++++++++++++++++++++++++++++++++++++++ |
A | src/str.h | | | 75 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
24 files changed, 1224 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5497595 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/.cache/ +/bin/ +/build/ +/compile_commands.json +/lib/ diff --git a/BuildUNIX.sh b/BuildUNIX.sh new file mode 100755 index 0000000..d59505f --- /dev/null +++ b/BuildUNIX.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env sh +dir="$(dirname $(realpath "$0"))" + +cmake -S "${dir}" -B "${dir}/build" \ + -DCMAKE_BUILD_TYPE:STRING=Release \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=1 + +cmake --build "${dir}/build" + +mv -f "${dir}/build/compile_commands.json" "${dir}/compile_commands.json" diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..5973569 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,18 @@ +0.2.1, 2021-01-15 +* Implement SIGSTOP and SIGQUIT handling +* Update buld scripts +* Update lib dependencies + +0.2.0, 2020-04-16 +* Implement SIGINT and EOF handling +* Improve builtin execution +* Implement command return value handling +* Add PWD builtin +* Move to token based parsing +* Add rudimentary support for multi-line commands +* Rebrand to OSH, OMKOV Shell + +0.1.0, 2020-01-31 +* Implement basic shell loop +* Implement program execution +* Implement builtins cd, help and exit diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..cfea3e4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,13 @@ +# CMakeLists.txt +# CMakeLists file for OSH + +CMAKE_MINIMUM_REQUIRED(VERSION 3.12) +PROJECT(OSH VERSION 0.2.1 LANGUAGES C) + +SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin) +ADD_COMPILE_DEFINITIONS(PROJECT_VERSION="${PROJECT_VERSION}") + +FILE(GLOB LIBSRC ${CMAKE_SOURCE_DIR}/src/lib/*) +FILE(GLOB SOURCES ${CMAKE_SOURCE_DIR}/src/*) + +ADD_EXECUTABLE(osh ${SOURCES} ${LIBSRC}) diff --git a/LICENCE b/LICENCE new file mode 100644 index 0000000..5e4b579 --- /dev/null +++ b/LICENCE @@ -0,0 +1,24 @@ +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..b32a757 --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# OSH + +> OMKOV Shell + +OSH is a modern shell with an emphasis on performance. + +## Build Instructions + +OSH uses CMake to build. +Binaries will be located in the `bin` directory. + +### UNIX Build + +Run `BuildUNIX.sh`, or + +```sh +cmake -S . -B build && cmake --build build +``` + +## Meta + +Copyright (C) 2020, Jakob Wakeling +All rights reserved. +[OMKOV Permissive Licence](https://www.omkov.net/OLPE) diff --git a/src/alias.c b/src/alias.c new file mode 100644 index 0000000..b226a94 --- /dev/null +++ b/src/alias.c @@ -0,0 +1,84 @@ +// alias.c +// Alias source file for OSH +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#include "alias.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +akas_t akas; +static const aka_t AKA = {NULL, NULL}; + +void initalias(void) { + akas.cap = 16; akas.len = 0; + akas.dat = (aka_t *)malloc(sizeof(aka_t) * akas.cap); + akas.dat[0].str = NULL; + return; +} + +void freealias(void) { + for (aka_t *a = akas.dat; a->str; ++a) { + free(a->str); free(a->com); + } free(akas.dat); + return; +} + +void pushalias(akas_t *akas, aka_t aka) { + if (akas->len + 1 > akas->cap) { akas->cap *= 2; + akas->dat = (aka_t *)realloc(akas->dat, sizeof(aka_t) * akas->cap); + } akas->dat[akas->len] = aka; akas->dat[++akas->len] = AKA; + return; +} + +int bltn_alias(char *argv[]) { + if (!argv[1]) { for (aka_t *a = akas.dat; a->str; ++a) { + printf("alias %s='%s'\n", a->str, a->com); + } return 0; } + + for (int i = 0; argv[i]; ++i) { + char *c = strchr(argv[i], '='); + if (c) { aka_t aka; + size_t slen = c - argv[i], clen = strlen(++c); + aka.str = (char *)malloc(slen + 1); strncpy(aka.str, argv[i], slen); + aka.com = (char *)malloc(clen + 1); strncpy(aka.com, c, clen); + pushalias(&akas, aka); + } + else for (aka_t *a = akas.dat; a->str; ++a) { + if (strcmp(argv[i], a->str) == 0) { + printf("alias %s='%s'\n", a->str, a->com); break; + } + } + } + + return 0; +} diff --git a/src/alias.h b/src/alias.h new file mode 100644 index 0000000..a44041e --- /dev/null +++ b/src/alias.h @@ -0,0 +1,48 @@ +// alias.h +// Alias header file for OSH +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#ifndef OSH_ALIAS_H_0BXOPDLM +#define OSH_ALIAS_H_0BXOPDLM + +#include <stddef.h> + +typedef struct { char *str, *com; } aka_t; +typedef struct { aka_t *dat; size_t cap, len; } akas_t; +extern akas_t akas; + +extern void initalias(void); +extern void freealias(void); +extern void pushalias(akas_t *akas, aka_t aka); + +extern int bltn_alias(char *argv[]); + +#endif // OSH_ALIAS_H_0BXOPDLM diff --git a/src/bltn.c b/src/bltn.c new file mode 100644 index 0000000..7624fd0 --- /dev/null +++ b/src/bltn.c @@ -0,0 +1,69 @@ +// bltn.c +// Builtin source file for OSH +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#include "bltns/cd.c" +#include "bltns/pwd.c" + +#include "alias.h" +#include "bltn.h" +#include "exec.h" + +#include "lib/error.h" +#include "lib/optget.h" + +#include <stdio.h> + +static int bltn_eval(char *av[]) { return execute(&av[1]); } +static int bltn_exit(char *av[]) { (void)(av); _loop = 0; return 0; } +static int bltn_false(char *av[]) { (void)(av); return 1; } +static int bltn_help(char *av[]); +static int bltn_true(char *av[]) { (void)(av); return 0; } + +static int getret(char *argv[]) { printf("%d\n", _ret); return 0; } + +bltn_t bltns[] = { + {"alias", &bltn_alias}, + {"cd", &bltn_cd}, + {"eval", &bltn_eval}, + {"exit", &bltn_exit}, + {"false", &bltn_false}, + {"help", &bltn_help}, + {"pwd", &bltn_pwd}, + {"true", &bltn_true}, + {"ret", &getret}, + {NULL, NULL} +}; + +static int bltn_help(char *argv[]) { + puts("OSH, version " PROJECT_VERSION); + return 0; +} diff --git a/src/bltn.h b/src/bltn.h new file mode 100644 index 0000000..9b7c5f9 --- /dev/null +++ b/src/bltn.h @@ -0,0 +1,39 @@ +// bltn.h +// Builtin header file for OSH +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#ifndef OSH_BLTN_H_XQ5D812A +#define OSH_BLTN_H_XQ5D812A + +typedef struct { const char *str; int (*fun)(char *[]); } bltn_t; +extern bltn_t bltns[]; + +#endif // OSH_BLTN_H_XQ5D812A diff --git a/src/bltns/cd.c b/src/bltns/cd.c new file mode 100644 index 0000000..edc9dd2 --- /dev/null +++ b/src/bltns/cd.c @@ -0,0 +1,59 @@ +// cd.c, version 0.1.0 +// cd builtin source file for OSH +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#include "../lib/optget.h" + +#include <unistd.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static int bltn_cd(char *av[]) { + struct opt opt = OPTGET_INIT; opt.str = "LP"; opt.lops = NULL; + for (int o; (o = optget(&opt, av, 1)) != -1;) switch (o) { + case 'L': { break; } + case 'P': { break; } + default: { return 1; } + } + + char *path = av[1] ? av[1] : getenv("HOME"); + if (chdir(path)) { + fprintf(stderr, "%s: %s: %s\n", av[0], path, strerror(errno)); + return 1; + } + + path = getcwd(NULL, 0); setenv("PWD", path, 1); + + free(path); return 0; +} diff --git a/src/bltns/pwd.c b/src/bltns/pwd.c new file mode 100644 index 0000000..a21e380 --- /dev/null +++ b/src/bltns/pwd.c @@ -0,0 +1,58 @@ +// pwd.c, version 1.0.2b +// OMKOV coreutils pwd adapted as a OSH builtin +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#include "../lib/optget.h" + +#include <unistd.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> + +static int bltn_pwd(char *av[]) { int mode = 0; + struct opt opt = OPTGET_INIT; opt.str = "LP"; opt.lops = NULL; + for (int o; (o = optget(&opt, av, 1)) != -1;) switch (o) { + case 'L': { mode = 0; break; } + case 'P': { mode = 1; break; } + default: { return 1; } + } + +pwd:; + char *cwd = mode ? getcwd(NULL, 0) : getenv("PWD"); + if (!cwd && !mode) { mode = 1; goto pwd; } + else if (!cwd) { perror(av[0]); return 1; } + + fputs(cwd, stdout); fputc('\n', stdout); + + if (mode) { free(cwd); } + return 0; +} diff --git a/src/exec.c b/src/exec.c new file mode 100644 index 0000000..2a22041 --- /dev/null +++ b/src/exec.c @@ -0,0 +1,82 @@ +// exec.c +// Exec source file for OSH +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#include "bltn.h" +#include "exec.h" + +#include <sys/wait.h> +#include <unistd.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static int launch(char *argv[]); +static void launcherror(char *s); + +/* + Execute a command +*/ +int execute(char *argv[]) { + if (!argv[0]) { return _ret; } + for (bltn_t *b = bltns; b->str; ++b) { + if (strcmp(argv[0], b->str) == 0) { return b->fun(argv); } + } return launch(argv); +} + +/* + Fork and execute an executable +*/ +static int launch(char *argv[]) { + pid_t pid, wpid; int status; + + pid = fork(); + if (pid == 0) { + signal(SIGINT, SIG_DFL); + if (execvp(argv[0], argv) == -1) { + if (errno == ENOENT) { launcherror(argv[0]); } + else { perror(argv[0]); } exit(1); + } + } + else if (pid == -1) { puts("test"); perror(argv[0]); } + else { waitpid(pid, &status, 0); } + return WEXITSTATUS(status); +} + +static void launcherror(char *s) { + for (char *p = s; *p; ++p) { + if (*p == '\n') { fputs("\\n", stderr); } + else { fputc(*p, stderr); } + } fputs(": Command not found\n", stderr); + return; +} diff --git a/src/exec.h b/src/exec.h new file mode 100644 index 0000000..8d9fa61 --- /dev/null +++ b/src/exec.h @@ -0,0 +1,40 @@ +// exec.h +// Exec header file for OSH +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#ifndef OSH_EXEC_H_VI5E8LVV +#define OSH_EXEC_H_VI5E8LVV + +extern int _loop, _ret; + +extern int execute(char *argv[]); + +#endif // OSH_EXEC_H_VI5E8LVV diff --git a/src/lex.c b/src/lex.c new file mode 100644 index 0000000..d3092b0 --- /dev/null +++ b/src/lex.c @@ -0,0 +1,78 @@ +// lex.c +// Lexer source file for OSH +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#include "lex.h" +#include "str.h" + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define GETC c = fgetc(file) + +tok_t lex(FILE *file) { tok_t tok; tok.str = NULL; + int c = fgetc(file); + +skip:; + for (; isspace(c) && c != '\n'; GETC); + if (c == '\n') { tok.tok = NEWLINE; return tok; } + if (c == EOF) { tok.tok = EOF; return tok; } + if (c == '#') { for (GETC; !(c == EOF || c == '\n'); GETC) {} goto skip; } + + str_t str = sinit(); + if (0) {} + else { tok.tok = WORD; goto word; + for (;;) { GETC; +word: if (c == '\\') { c = fgetc(file); + if (c == '\n') { fputs("> ", stdout); continue; } + else { spush(&str, '\\'); } + } + else if (c == '\'') for (;;) { c = fgetc(file); + if (c == '\'') { break; } else { spush(&str, c); } + } + else if (c == '\"') for (;;) { c = fgetc(file); + if (c == '\\') { c = fgetc(file); + if (c == '$' || c == '`' || c == '\"' || c == '\\'); + else if (c == '\n') { continue; } + else { spush(&str, '\\'); } spush(&str, c); + } + else if (c == '\"') { break; } else { spush(&str, c); } + } + else if (isspace(c) && c != '\n') { break; } + else if (c == '\n' || c == EOF) { ungetc('\n', file); break; } + else { spush(&str, c); } + } tok.str = str.dat; + } + + return tok; +} diff --git a/src/lex.h b/src/lex.h new file mode 100644 index 0000000..11f4da7 --- /dev/null +++ b/src/lex.h @@ -0,0 +1,46 @@ +// lex.h +// Lexer header file for OSH +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#ifndef OSH_LEX_H_MA6B50VH +#define OSH_LEX_H_MA6B50VH + +#include <stdio.h> + +enum token { + END = EOF, NUL = 0, NEWLINE, WORD +}; + +typedef struct { enum token tok; char *str; } tok_t; + +extern tok_t lex(FILE *file); + +#endif // OSH_LEX_H_MA6B50VH diff --git a/src/lib/error.c b/src/lib/error.c new file mode 100644 index 0000000..f246723 --- /dev/null +++ b/src/lib/error.c @@ -0,0 +1,55 @@ +// error.c, version 1.0.1 +// Error source file for OMKOV lib +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#include "error.h" + +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +char *A0 = NULL; + +_Noreturn void error(int status, const char *format, ...) { + fflush(stdout); if (A0) { fputs(A0, stderr); fputs(": ", stderr); } + va_list ap; va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap); + fputc('\n', stderr); exit(status); +} + +void warn(const char *format, ...) { + fflush(stdout); if (A0) { fputs(A0, stderr); fputs(": ", stderr); } + va_list ap; va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap); + fputc('\n', stderr); return; +} + +char *serr(void) { return strerror(errno); } diff --git a/src/lib/error.h b/src/lib/error.h new file mode 100644 index 0000000..d0d4585 --- /dev/null +++ b/src/lib/error.h @@ -0,0 +1,43 @@ +// error.h, version 1.0.1 +// Error header file for OMKOV lib +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#ifndef OMKOV_LIB_ERROR_H_38W06M3W +#define OMKOV_LIB_ERROR_H_38W06M3W + +extern char *A0; + +extern _Noreturn void error(int status, const char *format, ...); +extern void warn(const char *format, ...); + +extern char *serr(void); + +#endif // OMKOV_LIB_ERROR_H_38W06M3W diff --git a/src/lib/optget.c b/src/lib/optget.c new file mode 100644 index 0000000..da61ebd --- /dev/null +++ b/src/lib/optget.c @@ -0,0 +1,122 @@ +// optget.h, version 1.6.0 +// optget source file for OMKOV lib +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#include "error.h" +#include "optget.h" + +#include <stddef.h> +#include <stdio.h> +#include <string.h> + +#define cur av[opt->ind] + +const struct opt OPTGET_INIT = { 1, 0, 1, 0, NULL, NULL, NULL, NULL }; + +static inline void permute(char **av, int i, int n); + +int optget(struct opt *opt, char *av[], int flags) { + if (flags & 1) { + for (; cur && (cur[0] != '-' || cur[1] == 0); ++opt->ind, ++opt->nop); + if (!cur) { opt->ind -= opt->nop; opt->nop = 0; return -1; } + } + else if (!cur || (cur[0] != '-' || cur[1] == 0)) { return -1; } + + int optind = opt->ind, optret; + + if (cur[1] == '-') { + if (cur[2] == 0) { if (opt->nop) { + permute(av, opt->ind++, opt->nop); + opt->ind -= opt->nop; opt->nop = 0; + } else { ++opt->ind; } return -1; + } + + int optend, lop; optret = '?'; opt->opt = 0; opt->lop = cur; + if (!opt->lops) { goto nol; } + for (optend = 2; cur[optend] != '=' && cur[optend] != 0; ++optend); + + for (lop = 0; opt->lops[lop].str; ++lop) { + if (strncmp(&cur[2], opt->lops[lop].str, (size_t)optend - 2) == 0) { + if (!opt->lops[lop].str[optend - 2]) { + optret = opt->opt = opt->lops[lop].val; break; + } + } + } + + if (opt->lops[lop].arg > ARG_NUL) { + if (cur[optend]) { opt->arg = &cur[optend + 1]; } + else if (av[opt->ind + 1]) { opt->arg = av[++opt->ind]; } + else { + if (opt->lops[lop].arg == ARG_REQ) { optret = ':'; } + opt->arg = NULL; + } + } + else { opt->arg = NULL; } + +nol: opt->pos = 0; + } + else { + optret = opt->opt = cur[opt->pos++]; opt->lop = NULL; + const char *optchr = strchr(opt->str, opt->opt); + + if (!optchr) { optret = '?'; } + else if (optchr[1] == ':') { + if (cur[opt->pos]) { opt->arg = &cur[opt->pos]; } + else if (av[opt->ind + 1]) { opt->arg = av[++opt->ind]; } + else { opt->arg = NULL; optret = ':'; } + opt->pos = 0; + } + else { opt->arg = NULL; } + } + + if (!opt->pos || !cur[opt->pos]) { + ++opt->ind; opt->pos = 1; + if (opt->nop) for (; optind < opt->ind; ++optind) { + permute(av, optind, opt->nop); + } + } + + if (optret == '?' && opt->str[0] != ':') { + if (opt->opt) { warn("%c: invalid option", opt->opt); } + else if (opt->lop) { warn("%s: invalid option", opt->lop); } + } + if (optret == ':' && opt->str[0] != ':') { + if (opt->opt) { warn("%c: option requires argument", opt->opt); } + else if (opt->lop) { warn("%s: option requires argument", opt->lop); } + } + + return optret; +} + +static inline void permute(char **av, int i, int n) { + char *a = av[i]; memmove(&av[i - n + 1], &av[i - n], n * sizeof (av)); + av[i - n] = a; return; +} diff --git a/src/lib/optget.h b/src/lib/optget.h new file mode 100644 index 0000000..f83d132 --- /dev/null +++ b/src/lib/optget.h @@ -0,0 +1,55 @@ +// optget.h, version 1.6.0 +// optget header file for OMKOV lib +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#ifndef OMKOV_LIB_OPTGET_H_W3LIZK1S +#define OMKOV_LIB_OPTGET_H_W3LIZK1S + +#define ARG_NUL 0 +#define ARG_REQ 1 +#define ARG_OPT 2 + +struct lop { + char *str; + int arg, val; +}; + +struct opt { + int ind, opt, pos, nop; + char *arg, *lop, *str; + struct lop *lops; +}; + +extern const struct opt OPTGET_INIT; + +extern int optget(struct opt *opt, char *av[], int flags); + +#endif // OMKOV_LIB_OPTGET_H_W3LIZK1S diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..a301d4a --- /dev/null +++ b/src/main.c @@ -0,0 +1,79 @@ +// main.c +// Main source file for OSH +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#include "alias.h" +#include "exec.h" +#include "lex.h" +#include "parse.h" + +#include <setjmp.h> +#include <signal.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +int _loop = 1, _ret; + +static sigjmp_buf jmp; +static sig_atomic_t jmpflag = false; + +static void reset(int signo); + +int main(int argc, char *argv[]) { (void)(argc); + signal(SIGINT, &reset); signal(SIGSTOP, SIG_IGN); signal(SIGQUIT, SIG_IGN); + + initalias(); + + do { + if (sigsetjmp(jmp, 1)) { fputc('\n', stdout); } jmpflag = true; + + char **args = NULL; + + fputs("$ ", stdout); + + args = parse(stdin); + _ret = execute(args); + +end: free(args); + } while (_loop); + + fputc('\n', stdout); + freealias(); + + return 0; +} + +static void reset(int signo) { (void)(signo); + if (jmpflag) { siglongjmp(jmp, 1); } +} diff --git a/src/parse.c b/src/parse.c new file mode 100644 index 0000000..2c14ea4 --- /dev/null +++ b/src/parse.c @@ -0,0 +1,58 @@ +// parse.c +// Parser source file for OSH +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#include "exec.h" +#include "lex.h" +#include "parse.h" +#include "str.h" + +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +char **parse(FILE *file) { + size_t cap = 64, len = 0; char *arg = NULL; + char **argv = (char **)malloc(cap * sizeof(char *)); + if (!argv) { return NULL; } + + for (tok_t tok = lex(file); tok.tok != NEWLINE; tok = lex(file)) { + if (tok.tok == EOF) { _loop = false; break; } + if (tok.tok == WORD) { argv[len++] = tok.str; } + + if (len == cap) { + cap *= 2; argv = (char **)realloc(argv, cap * sizeof(char *)); + if (!argv) { return NULL; } + } + } + + argv[len] = NULL; return argv; +} diff --git a/src/parse.h b/src/parse.h new file mode 100644 index 0000000..e27e8c5 --- /dev/null +++ b/src/parse.h @@ -0,0 +1,40 @@ +// parse.h +// Parser header file for OSH +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#ifndef OSH_PARSE_H_G9TJ04KR +#define OSH_PARSE_H_G9TJ04KR + +#include <stdio.h> + +extern char **parse(FILE *file); + +#endif // OSH_PARSE_H_G9TJ04KR diff --git a/src/str.h b/src/str.h new file mode 100644 index 0000000..ead6846 --- /dev/null +++ b/src/str.h @@ -0,0 +1,75 @@ +// str.h +// Dynamic string header file for OSH +// Copyright (C) 2020, Jakob Wakeling +// All rights reserved. + +/* +OMKOV Permissive Licence, version 1.0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimers in the documentation and/or + other materials provided with the distribution. +* Neither the names of the copyright holders, nor the names of its contributors + may be used to endorse or promote products derived from this Software without + specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. +*/ + +#ifndef OSH_STR_H_LJ7LE814 +#define OSH_STR_H_LJ7LE814 + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +typedef struct { char *dat; size_t cap, len; } str_t; + +static inline str_t sinit(void) { + str_t str; str.cap = 64; str.len = 0; + str.dat = (char *)malloc(str.cap); + return str; +} + +static void spush(str_t *str, char c) { + if (str->len + 1 > str->cap) { str->cap *= 2; + str->dat = (char *)realloc(str->dat, str->cap); + } str->dat[str->len] = c; str->dat[++str->len] = 0; + return; +} + +static char spop(str_t *str) { + char c = str->dat[--str->len]; + str->dat[str->len] = 0; + return c; +} + +static void sapp(str_t *str, char *s) { + size_t len = strlen(s); + if (str->len + len > str->cap) { + str->cap += len * 2; str->dat = (char *)realloc(str->dat, str->cap); + } memcpy(&str->dat[str->len], s, len); + str->len += len; str->dat[str->len] = 0; + return; +} + +static inline void sclear(str_t *str) { + str->len = 0; str->dat[0] = 0; + return; +} + +#endif // OSH_STR_H_LJ7LE814