feat(coreutils): implement coreutils and compile it using cmake

Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
2025-03-10 02:29:14 +00:00
parent 88a3b0912b
commit 87540ab0b9
9 changed files with 322 additions and 2 deletions

1
Userspace/coreutils/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
build

View File

@ -0,0 +1,51 @@
cmake_minimum_required(VERSION 3.10)
project(FennixCoreUtilities VERSION 1.0.0)
if(NOT DEFINED ENV{WORKSPACE_DIR})
set(STANDALONE_BUILD ON)
message(STATUS "Compiling standalone")
else()
set(STANDALONE_BUILD OFF)
message(STATUS "Compiling within workspace")
endif()
set(CMAKE_C_COMPILER "$ENV{CC}")
set(CMAKE_CXX_COMPILER "$ENV{CXX}")
set(CMAKE_ASM_COMPILER "$ENV{AS}")
set(CMAKE_AR "$ENV{AR}")
set(CMAKE_LINKER "$ENV{LD}")
if(DEFINED ENV{DEBUG} AND "$ENV{DEBUG}" STREQUAL "1")
set(CMAKE_C_FLAGS "-ggdb3 -O0 -DDEBUG")
else()
set(CMAKE_C_FLAGS "-O2")
endif()
include_directories(${CMAKE_SOURCE_DIR}/include)
file(GLOB SINGLE_SOURCE "src/*.c")
foreach(file ${SINGLE_SOURCE})
get_filename_component(name ${file} NAME_WE)
add_executable(${name} ${file})
target_compile_definitions(${name} PRIVATE
PROGRAM_NAME="${name}"
PROGRAM_VERSION="${PROJECT_VERSION}"
)
install(TARGETS ${name} DESTINATION bin)
endforeach()
file(GLOB_RECURSE GROUP_SOURCES "src/*/*.c")
foreach(file ${GROUP_SOURCES})
get_filename_component(name ${file} DIRECTORY)
get_filename_component(name ${name} NAME)
list(APPEND GROUP_MAP_${name} ${file})
endforeach()
foreach(name IN LISTS GROUP_MAP_)
add_executable(${name} ${GROUP_MAP_${name}})
target_compile_definitions(${name} PRIVATE
PROGRAM_NAME="${name}"
PROGRAM_VERSION="${PROJECT_VERSION}"
)
install(TARGETS ${name} DESTINATION bin)
endforeach()

View File

@ -0,0 +1,38 @@
/*
This file is part of Fennix Core Utilities.
Fennix Core Utilities is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Core Utilities is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Core Utilities. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _COREUTILS_H
#define _COREUTILS_H
#ifndef PROGRAM_NAME
#define PROGRAM_NAME "<unknown>"
#endif
#ifndef PROGRAM_VERSION
#define PROGRAM_VERSION "<unknown>"
#endif
#define BUILD_YEAR (__DATE__ + 7)
#define PRINTF_VERSION \
printf("%s %s\n", PROGRAM_NAME, PROGRAM_VERSION); \
printf("Fennix Core Utilities Copyright (C) %s EnderIce2\n", BUILD_YEAR); \
printf("This program comes with ABSOLUTELY NO WARRANTY\n"); \
printf("This is free software, and you are welcome to redistribute it\n"); \
printf("under certain conditions\n")
#endif // _COREUTILS_H

View File

@ -0,0 +1,183 @@
/*
This file is part of Fennix Core Utilities.
Fennix Core Utilities is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Core Utilities is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Core Utilities. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <coreutils.h>
void PrintHelp()
{
printf("Usage: echo [OPTION]... [STRING]...\n");
printf("Echo the STRING(s) to standard output.\n\n");
printf(" -n do not output the trailing newline\n");
printf(" -e enable interpretation of backslash escapes\n");
printf(" -E disable interpretation of backslash escapes (default)\n");
printf(" --help display this help and exit\n");
printf(" --version output version information and exit\n\n");
printf("If -e is specified, the following sequences are recognized:\n");
printf(" \\\\ backslash\n");
printf(" \\a alert (BEL)\n");
printf(" \\b backspace\n");
printf(" \\c produce no further output\n");
printf(" \\e escape\n");
printf(" \\f form feed\n");
printf(" \\n new line\n");
printf(" \\r carriage return\n");
printf(" \\t horizontal tab\n");
printf(" \\v vertical tab\n");
}
static void PrintEscaped(const char *str)
{
while (*str)
{
if (*str == '\\')
{
str++;
switch (*str)
{
case 'n':
putchar('\n');
break;
case 't':
putchar('\t');
break;
case '\\':
putchar('\\');
break;
case 'a':
putchar('\a');
break;
case 'b':
putchar('\b');
break;
case 'r':
putchar('\r');
break;
case 'v':
putchar('\v');
break;
case 'f':
putchar('\f');
break;
case '0' ... '7':
{
int octal = 0;
for (int i = 0; i < 3 && *str >= '0' && *str <= '7'; i++, str++)
{
octal = octal * 8 + (*str - '0');
}
putchar(octal);
str--;
break;
}
case 'x':
{
int hex = 0;
str++;
for (int i = 0; i < 2 && ((*str >= '0' && *str <= '9') ||
(*str >= 'a' && *str <= 'f') ||
(*str >= 'A' && *str <= 'F'));
i++, str++)
{
if (*str >= '0' && *str <= '9')
hex = hex * 16 + (*str - '0');
else if (*str >= 'a' && *str <= 'f')
hex = hex * 16 + (*str - 'a' + 10);
else if (*str >= 'A' && *str <= 'F')
hex = hex * 16 + (*str - 'A' + 10);
}
putchar(hex);
str--;
break;
}
default:
putchar(*str);
break;
}
}
else
{
putchar(*str);
}
str++;
}
}
int main(int argc, char *argv[])
{
bool newline = true;
bool interpret_escapes = false;
int arg_start = 1;
if (argc == 2)
{
if (strcmp(argv[1], "--help") == 0)
{
PrintHelp();
exit(EXIT_SUCCESS);
}
else if (strcmp(argv[1], "--version") == 0)
{
PRINTF_VERSION;
exit(EXIT_SUCCESS);
}
}
if (argc > 1)
{
for (int i = 1; i < argc; i++)
{
if (argv[i][0] == '-' && argv[i][1] != '\0')
{
for (size_t j = 1; argv[i][j] != '\0'; j++)
{
if (argv[i][j] == 'n')
newline = false;
else if (argv[i][j] == 'e')
interpret_escapes = true;
else if (argv[i][j] == 'E')
interpret_escapes = false;
else
goto print_args;
}
arg_start++;
}
else
{
break;
}
}
}
print_args:
for (int i = arg_start; i < argc; i++)
{
if (interpret_escapes)
PrintEscaped(argv[i]);
else
fputs(argv[i], stdout);
if (i < argc - 1)
putchar(' ');
}
if (newline)
putchar('\n');
return 0;
}