Browse Source

Restore OSH 0.2.1 to Git

master
Jake Wakeling 9 months ago
commit
8e5fd79617
  1. 5
      .gitignore
  2. 10
      BuildUNIX.sh
  3. 18
      CHANGELOG
  4. 13
      CMakeLists.txt
  5. 24
      LICENCE
  6. 24
      README.md
  7. 84
      src/alias.c
  8. 48
      src/alias.h
  9. 69
      src/bltn.c
  10. 39
      src/bltn.h
  11. 59
      src/bltns/cd.c
  12. 58
      src/bltns/pwd.c
  13. 82
      src/exec.c
  14. 40
      src/exec.h
  15. 78
      src/lex.c
  16. 46
      src/lex.h
  17. 55
      src/lib/error.c
  18. 43
      src/lib/error.h
  19. 122
      src/lib/optget.c
  20. 55
      src/lib/optget.h
  21. 79
      src/main.c
  22. 58
      src/parse.c
  23. 40
      src/parse.h
  24. 75
      src/str.h

5
.gitignore

@ -0,0 +1,5 @@
/.cache/
/bin/
/build/
/compile_commands.json
/lib/

10
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"

18
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

13
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})

24
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.

24
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)

84
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;
}

48
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

69
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;
}

39
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

59
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;
}

58
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;
}

82
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;
}

40
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

78
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;
}

46
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

55
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); }

43
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

122
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;
}

55
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

79
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); }
}

58
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;
}

40
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

75
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
Loading…
Cancel
Save