esrever-utf-8.c
A few days ago I wrote a program that writes its reversed input to output. Here’s an UTF-8 version of that program. Beware, this program is not non-UTF-8 safe. Have fun. On second thoughts, maybe the source file should be named 8-ftu-esrever.c.
/*
esrever-utf-8.c -- Write the reversed input to output.
Copyright © 2015 Trond Endrestøl <Trond.Endrestol@ximalas.info>
This program 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 2 of the License, or
(at your option) any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
#include <errno.h>
#include <stdio.h>
#include <string.h>
static char *strrev(char *p);
int main(int argc, char **argv)
{
FILE *in = stdin, *out = stdout;
if (argc >= 2) {
if ((in = fopen(argv[1], "r")) == NULL) {
fprintf(stderr,
"%s:%s:%d: fopen(\"%s\", \"r\") = %s (%d) \n",
argv[0], __FILE__, __LINE__, argv[1], strerror(errno), errno);
return 1;
} // if
if (argc >= 3) {
if ((out = fopen(argv[2], "w")) == NULL) {
fprintf(stderr,
"%s:%s:%d: fopen(\"%s\", \"w\") = %s (%d) \n",
argv[0], __FILE__, __LINE__, argv[2], strerror(errno), errno);
return 1;
} // if
} // if
} // if
do {
char buffer[4096], *p;
if (fgets(buffer, sizeof(buffer), in) == NULL) {
if (ferror(in) && !feof(in)) {
fprintf(stderr,
"%s:%s:%d: ferror() on \"%s\", possibly %s (%d) \n",
argv[0], __FILE__, __LINE__, (in == stdin) ? "/dev/stdin" : argv[1], strerror(errno), errno);
return 1;
} // if
} // if
if (feof(in))
break;
if ( (p = strchr(buffer, '\n')) != NULL)
*p = '\0'; // Change newline to NUL terminator
strrev(buffer);
if (p != NULL)
*p = '\n'; // Put newline back.
if (fputs(buffer, out) == EOF) {
if (ferror(out)) {
fprintf(stderr,
"%s:%s:%d: ferror() on \"%s\", possibly %s (%d) \n",
argv[0], __FILE__, __LINE__, (out == stdout) ? "/dev/stdout" : argv[2], strerror(errno), errno);
return 1;
} // if
} // if
} while (!ferror(in) && !ferror(out)); // do-while
return 0;
} // main()
char *strrev(char *p)
{
size_t start = 0, end;
if (p == NULL || (end = strlen(p)) == 0)
return NULL;
end--; // Leave the NUL terminator alone.
while (start < end) {
p[start] ^= p[end];
p[end] ^= p[start];
p[start] ^= p[end];
start++;
end--;
} // while
// Fixup any UTF-8 character sequences. This is not non-UTF-8 safe!
start = 0;
while (p[start] != '\0') {
if (p[start] & 0x80 && p[start + 1] & 0x80) {
p[start] ^= p[start + 1];
p[start + 1] ^= p[start];
p[start] ^= p[start + 1];
} // if
start++;
} // while
return p;
} // strrev()
// esrever-utf-8.c