-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: Initial implementation of rev(1). * chore: No need to use printf() if we could just puts(). * chore: Close string correctly. * chore: Mention new rev(1B) implementation at CHANGES. * chore: rev refactor. * feat: Added (rudimentary) multibyte support for rev.c. * feat: Full support for UTF-8 multibyte at rev(1). Borrowed from suckless sbase implementation, as mentioned on the header. * chore: Update CHANGES * docs: Added manual page for rev(1). * chore: Added rev/ to the build list at the top 'makefile'. * chore: Mention where UTF-8 support at rev(1) comes from in CHANGES
- Loading branch information
Showing
5 changed files
with
167 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
all: rev | ||
|
||
rev: rev.o | ||
$(LD) $(LDFLAGS) rev.o $(LCOMMON) $(LWCHAR) $(LIBS) -o rev | ||
|
||
rev.o: rev.c | ||
$(CC) $(CFLAGSU) $(CPPFLAGS) $(ICOMMON) $(IWCHAR) -c rev.c | ||
|
||
install: all | ||
$(UCBINST) -c rev $(ROOT)$(DEFBIN)/rev | ||
$(STRIP) $(ROOT)$(DEFBIN)/rev | ||
$(MANINST) -c -m 644 rev.1 $(ROOT)$(MANDIR)/man1/rev.1 | ||
|
||
clean: | ||
rm -f rev rev.o core log *~ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
.\" | ||
.\" Copyright (c) 2024 Luiz Antônio Rangel | ||
.\" | ||
.\" SPDX-Licence-Identifier: Zlib | ||
.\" | ||
.TH REV 1 "07/21/24" "Heirloom Toolchest" "User Commands" | ||
.SH NAME | ||
rev \- reverse lines of a file | ||
.SH SYNOPSIS | ||
\fBrev\fR [\fIfile\fR] | ||
.SH DESCRIPTION | ||
.I Rev | ||
copies the lines of the specified | ||
files to the standard output, but | ||
reversing the order of characters. | ||
If no file is specified, it reads | ||
from the standard input. | ||
.SH NOTES | ||
This | ||
.I rev | ||
supports internationalisation. In | ||
varietate concordia. | ||
.SH HISTORY | ||
A | ||
.I rev | ||
command first appeared in UNIX 6th | ||
Edition. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
/* | ||
* rev.c - reverse lines of a file | ||
* | ||
* A little bit based on Luiz' implementation | ||
*/ | ||
/* | ||
* Copyright (C) 2024: Luiz Antônio Rangel (takusuman) | ||
* Copyright (C) 2024: Samuel Brederodes (callsamu) | ||
* | ||
* SPDX-Licence-Identifier: Zlib | ||
* | ||
* UTF-8 support borrowed from suckless sbase implementation. | ||
* Copyright (C) 2016 Mattias Andrée ([email protected]) | ||
* SPDX-Licence-Identifier: MIT | ||
*/ | ||
|
||
#include <errno.h> | ||
#include <fcntl.h> | ||
#include <stdbool.h> | ||
#include <stddef.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <unistd.h> | ||
|
||
#if defined(__linux__) || defined(__dietlibc__) | ||
#define _XOPEN_SOURCE 600L | ||
#endif | ||
|
||
#define NULL_BYTE '\0' | ||
|
||
static char *progname; | ||
|
||
int copy_line(FILE *from, char *to_buffer, size_t to_buffer_size) { | ||
for (int i = 0; i < to_buffer_size; i++) { | ||
int c = fgetc(from); | ||
|
||
switch (c) { | ||
case EOF: | ||
to_buffer[i] = NULL_BYTE; | ||
return EOF; | ||
case '\n': | ||
to_buffer[i] = '\n'; | ||
to_buffer[(i + 1)] = NULL_BYTE; | ||
return 0; | ||
default: | ||
to_buffer[i] = c; | ||
} | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
bool isutf8chr(char c) { | ||
if ((c & 0xC0) == 0x80) { | ||
return true; | ||
} else { | ||
return false; | ||
} | ||
} | ||
|
||
void reverse_string(char *string) { | ||
int len = strlen(string), | ||
i = 0, | ||
lf = 0; | ||
|
||
lf = len && string[(len - 1)] == '\n'; | ||
len -= lf; | ||
i = len; | ||
for (len = 0; i--;) { | ||
switch (isutf8chr(string[i])) { | ||
case true: | ||
len++; | ||
break; | ||
default: /* "Else", "false", call it what you like. */ | ||
fwrite((string + i), 1, | ||
(len + 1), stdout); | ||
len = 0; | ||
break; | ||
} | ||
} | ||
|
||
if (len) fwrite(string, 1, len, stdout); | ||
if (lf) fputc('\n', stdout); | ||
} | ||
|
||
int main(int argc, char *argv[]) { | ||
progname = argv[0]; | ||
|
||
int fdinput = STDIN_FILENO; | ||
if (argc > 1) { | ||
fdinput = open(argv[1], O_RDONLY); | ||
|
||
if (fdinput < 0) { | ||
fprintf(stderr, "%s: %s\n", | ||
progname, strerror(errno)); | ||
return EXIT_FAILURE; | ||
} | ||
} | ||
|
||
FILE *input = fdopen(fdinput, "r"); | ||
if (!input) { | ||
fprintf(stderr, "%s: cannot open stream at descriptor %d: %s\n", | ||
progname, fdinput, strerror(errno)); | ||
return EXIT_FAILURE; | ||
} | ||
|
||
char buffer[BUFSIZ]; | ||
|
||
while (true) { | ||
int eof = copy_line(input, buffer, BUFSIZ); | ||
reverse_string(buffer); | ||
|
||
if (eof == EOF) { | ||
if (fdinput) { | ||
fclose(input); | ||
} | ||
return EXIT_SUCCESS; | ||
} | ||
} | ||
} |