diff options
| author | Charles Cabergs <me@cacharle.xyz> | 2020-08-22 19:43:03 +0200 |
|---|---|---|
| committer | Charles Cabergs <me@cacharle.xyz> | 2020-08-22 19:43:03 +0200 |
| commit | c40f79737a4ce6ae0cd8bd6ea7f302217333e486 (patch) | |
| tree | 5afe1af26880bd7f8b16ee33fb8e14f99f665938 /tr.c | |
| parent | f204fe59bd5fa537bf84cb522339c92b16f5a909 (diff) | |
| download | coreutils-c40f79737a4ce6ae0cd8bd6ea7f302217333e486.tar.gz coreutils-c40f79737a4ce6ae0cd8bd6ea7f302217333e486.tar.bz2 coreutils-c40f79737a4ce6ae0cd8bd6ea7f302217333e486.zip | |
Added Makefile
Diffstat (limited to 'tr.c')
| -rw-r--r-- | tr.c | 229 |
1 files changed, 0 insertions, 229 deletions
@@ -1,229 +0,0 @@ -#define _POSIX_C_SOURCE 2 -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <ctype.h> -#include <stdbool.h> -#include <string.h> -#include <assert.h> - -typedef enum -{ - FLAG_COMPLEMENT = 1 << 0, - FLAG_DELETE = 1 << 1, - FLAG_SQUEEZE = 1 << 2, -} t_flags; - - -typedef enum -{ - MTAG_CHAR, - MTAG_CLASS, - MTAG_RANGE, - /* MTAG_REPEAT, */ - /* MTAG_EQUIVALENT, */ // e.g [=e=] == eéèê -} t_matcher_tag; - -typedef struct -{ - t_matcher_tag tag; - union - { - char c; - int (*class)(int c); - char range[2]; - struct - { - char c; - size_t count; - } repeat; - }; -} t_matcher; - -struct char_class_entry { - char *id; - int (*func)(int c); -}; - -struct char_class_entry char_classes[] = { - {"[:alnum:]", isalnum}, - {"[:alpha:]", isalpha}, - {"[:blank:]", isblank}, - {"[:cntrl:]", iscntrl}, - {"[:digit:]", isdigit}, - {"[:graph:]", isgraph}, - {"[:lower:]", islower}, - {"[:print:]", isprint}, - {"[:punct:]", ispunct}, - {"[:space:]", isspace}, - {"[:upper:]", isupper}, - {"[:xdigit:]", isxdigit}, -}; - -typedef struct -{ - t_matcher *array; - size_t count; -} t_matchers; - -void matchers_push(t_matchers *matchers, t_matcher_tag tag, void *data) -{ - t_matcher *pushed; - - matchers->count++; - matchers->array = realloc(matchers->array, matchers->count); - assert(matchers->array != NULL); - pushed = &matchers->array[matchers->count - 1]; - pushed->tag = tag; - switch (tag) - { - case MTAG_CHAR: - pushed->c = *(char*)data; - break; - case MTAG_CLASS: - pushed->class = (int (*)(int))data; - break; - case MTAG_RANGE: - pushed->range[0] = ((short)data & 0x00ff) >> 0; - pushed->range[1] = ((short)data & 0xff00) >> 8; - break; - default: - abort(); - } -} - -bool isodigit(char c) { return c >= '0' && c <= '7'; } - -void parse(t_matchers *matchers, char *s) -{ - for (size_t i = 0; s[i] != '\0'; i++) - { - if (s[i] == '\\') - { - memmove(&s[i], &s[i + 1], strlen(&s[i + 1])); - - switch (s[i]) - { - case 'a': s[i] = '\a'; break; - case 'b': s[i] = '\b'; break; - case 'f': s[i] = '\f'; break; - case 'n': s[i] = '\n'; break; - case 'r': s[i] = '\r'; break; - case 't': s[i] = '\t'; break; - case 'v': s[i] = '\v'; break; - } - - if (isodigit(s[i])) - { - char num[4] = {'\0'}; - strncpy(num, &s[i], 3); - char *end; - s[i] = strtol(num, &end, 8); - memmove(&s[i + 1], &s[i + 1 + (end - num)], strlen(&s[i + 1 + (end - num)])); - } - matchers_push(matchers, MTAG_CHAR, (void*)s[i]); - } - else if (s[i + 1] == '-' && s[i + 2] != '\0') - matchers_push(matchers, MTAG_RANGE, (void*)(s[i] | (s[i] << 8))); - else if (s[i] == '[' && s[i + 1] == ':') - { - /* for (size_t j = 0; j < sizeof(char_classes) / sizeof(char_class_entry); j++) */ - /* { */ - /* if (strncmp( */ - /* } */ - } - else - matchers_push(matchers, MTAG_CHAR, (void*)s[i]); - } -} - -char *g_name = "tr"; - -void fatal(const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - fprintf(stderr, "%s: ", g_name); - vfprintf(stderr, format, ap); - va_end(ap); - exit(EXIT_FAILURE); -} - -#define BUFFER_SIZE 256 - -/* -** no 't' flag, truncate is the default behavior -*/ - -int main(int argc, char **argv) -{ - int option; - t_flags flags = 0; - - while ((option = getopt(argc, argv, "cCds")) != -1) - { - switch (option) - { - case 'c': - case 'C': - flags |= FLAG_COMPLEMENT; - break; - case 'd': - flags |= FLAG_DELETE; - break; - case 's': - flags |= FLAG_SQUEEZE; - break; - } - } - if (optind == argc) - fatal("missing operand\n"); - if (argc - optind == 3) - fatal("extra operand '%s'\n", argv[argc - 1]); - - if (flags & FLAG_DELETE && flags & FLAG_SQUEEZE && argc - optind != 2) - fatal("missing operand after '%s'\n" - "Two strings must be given when both deleting and squezzing repeats.\n", - argv[optind]); - - if (flags & FLAG_DELETE && argc - optind != 1) - fatal("extra operand '%s'\n", - "Only one string may be given when deleting without squeezing repeats.\n", - argv[optind + 1]); - - t_matchers set1 = { .array = NULL, .count = 0 }; - t_matchers set2 = { .array = NULL, .count = 0 }; - - char buf[BUFFER_SIZE + 1] = {'\0'}; - size_t read_size; - - while ((read_size = fread(buf, sizeof(char), BUFFER_SIZE, stdin)) > 0) - { - for (size_t i = 0; i < read_size; i++) - { - if (flags & FLAG_DELETE && flags & FLAG_SQUEEZE) - { - - } - else if (flags & FLAG_DELETE && match()) - { - memmove(&buf[i], &buf[i + 1], read_size - i); - - else if (flags & FLAG_SQUEEZE) - { - while (match(s[i + 1])) - - memmove(&buf[i + 1], &buf[i + 2], read_size - i); - } - else - { - if (match()) - buf[i] = set2 - } - } - } - - return EXIT_SUCCESS; -} |
