💾 Archived View for icolotl.com › repos › morgrot › old_version › morgrot.c captured on 2024-05-26 at 14:47:41.

View Raw

More Information

-=-=-=-=-=-=-

/* SPDX-License-Identifier: GPL-3.0-or-later */
/*
 * MORGROT.C
 * Morgana's Offline-First Rot13 Program (original kluge-ish C edition)
 * Copyright (C) 2024 Grace Morgana <morgana@icolotl.com>
 * 
 * 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 3 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, see <https://www.gnu.org/licenses/>.
 */

#include <stdio.h>
#include <stdlib.h> 
#include <errno.h>
#include <string.h>

int main(int argc, char* argv[]) {

    // Shift amount in chars, positive = forward (e.g. A+2 -> C)
    long shift;

    // No Arguments, default = 13
    if (argc == 1) {
        shift = 13;
    // One Argument, extract shift
    } else if (argc == 2) {
        // Detect help flags, provide usage
        if (strncmp(argv[1], "-h", 2) == 0 || strncmp(argv[1], "--help", 6) == 0) {
            puts("morgrot: usage:\n  morgrot [base]");
            return 0;
        }
        // Extract shift with strtol for error checking
        char *end;
        shift = strtol(argv[1], &end, 10); 
        // Check for (empty string || chars after digits || errno check)
        if (end == argv[1] || *end != '\0' || errno == ERANGE) {
            fprintf(stderr, "morgrot: %s: Invalid integer\n", argv[1]);
            return -1;
        }
    // 2+ Args, error
    } else {
        fputs("morgrot: usage error: Too many parameters\n", stderr);
        return -1;
    }
    
    // Convert to shift modulo between 0 and 25
    shift = shift % 26;
    if (shift < 0) {
        shift += 26;
    }
    // Setup dynamic output array, initial size 16
    int* output = malloc(4 * sizeof(unsigned char));
    size_t used = 0;
    size_t size = 4;

    // Process chars from input until EOF
    unsigned char c;
    // Explicit casts as conversion may change values
    const unsigned char END_OF_FILE = (unsigned char)-1;
    while ((c = (unsigned char)getchar()) != END_OF_FILE) {
        // Resize if necessary
        if (used == size) {
            size *= 2;
            output = realloc(output, size * sizeof(int));
        }
        // Shift lowercase chars
        if ('a' <= c && c <= 'z') {
            c += (unsigned char)shift;
            if (c > 'z') {
                c -= 26;
            }
        // Shift uppercase chars
        } else if ('A' <= c && c <= 'Z') {
            c += (unsigned char)shift;
            if (c > 'Z') {
                c -= 26;
            }
        }
        // Add char to dynamic array
        output[used++] = c;
    }

    // Display array
    for (size_t i = 0; i < size; i++) {
        putchar(output[i]);
    }

    // Free dynamic array
    free(output);
    
}