https://sintheta.nexus/blog/feed.xml

Real programmers

2024-11-25

... 'script' in C! #!/usr/bin/tcc -run is all it takes.

  • Practicality: ... 8/10 (believe it or not)
    • bash is great for gluing sys utilities together but not a great programming language per se
    • small C applications
      • are easy to write, read, modify
      • are performant (even if compiled ad-hoc before execution)
        • (though of course compilation is always an option)
      • can use C's stdlib
      • can have inlined assembly & manual memory management (great for learning)
      • no system of mine lacks tcc or C's stdlib
        • for me just as universal as any script could be
      • need not be super robust (target user is onself)
  • Fun: 11/10

Now what constitutes scripting v programming and whether or not this is one or the other, just don't take it too seriously :)

#!/usr/bin/tcc -run

#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void print_bitstring(uint32_t b);
void print_numbvalue(char* s);
void printfn(char* s);
void shiftl(uint32_t num, uint32_t shiftval);
void shiftr(uint32_t num, uint32_t shiftval);
void AND(uint32_t num, uint32_t bitmask);
void OR(uint32_t num, uint32_t bitmask);
void XOR(uint32_t num, uint32_t bitmask);
void NOT(uint32_t num);

void print_bitstring(uint32_t b)
{
    int bitcount = sizeof(b) * 8;

    printf("%d bits: ", bitcount);

    for (int i = bitcount - 1; i >= 0; i--) {
        printf("%d", (b >> i) & 1);
        if (i % 4 == 0) printf("\'");
    }
    printf("\n");
}

void print_numbvalue(char* s)
{
    int val = 0;

    for (size_t i = 0; i < strlen(s); i++) {
        if (s[i] == '1')
            val = (val << 1) | 1;
        else if (s[i] == '0')
            val = val << 1;
        else
            exit(EXIT_FAILURE);
    }

    print_bitstring(val);
    printf("%d\n", val);
    printfn("");
}

void printfn(char* s)
{
    printf("%s\n", s);
}

void shiftl(uint32_t num, uint32_t shiftval)
{
    printfn("");
    printf("value : "); print_bitstring(num);
    printf("result: "); print_bitstring(num << shiftval);
    printfn("");
}

void shiftr(uint32_t num, uint32_t shiftval)
{
    printfn("");
    printf("value : "); print_bitstring(num);
    printf("result: "); print_bitstring(num >> shiftval);
    printfn("");
}

void AND(uint32_t num, uint32_t bitmask)
{
    printfn("");
    printf("value  : "); print_bitstring(num);
    printf("bitmask: "); print_bitstring(bitmask);
    printf("result : "); print_bitstring(num & bitmask);
    printfn("");
}

void OR(uint32_t num, uint32_t bitmask)
{
    printfn("");
    printf("value  : "); print_bitstring(num);
    printf("bitmask: "); print_bitstring(bitmask);
    printf("result : "); print_bitstring(num | bitmask);
    printfn("");
}

void XOR(uint32_t num, uint32_t bitmask)
{
    printfn("");
    printf("value  : "); print_bitstring(num);
    printf("bitmask: "); print_bitstring(bitmask);
    printf("result : "); print_bitstring(num ^ bitmask);
    printfn("");
}

void NOT(uint32_t num)
{
    printfn("");
    printf("value  : "); print_bitstring(num);
    printf("result : "); print_bitstring(~num);
    printfn("");
}

int main(void)
{
    printfn("bit-analysis auxilary program");

    int choice;
    uint32_t number;
    uint32_t shiftval;
    uint32_t bitmask;
    char string[33];

    while (1)
    {
        choice = number = shiftval = bitmask = 0;

        printfn("-------------------------");
        printfn("  0) val to bitstring");
        printfn("  1) bitstring to val");
        printfn("  2) << n");
        printfn("  3) >> n");
        printfn("  4) &  n");
        printfn("  5) |  n");
        printfn("  6) ^  n");
        printfn("  7) ~  n");
        printfn("(any other digit: exit)");
        printfn("-------------------------");

        choice = getchar();
        while (getchar() != '\n');

        switch (choice) {
            case '0':
                printf("enter num: ");
                if (scanf("%i", &number) != 1) 
                    exit(EXIT_FAILURE);
                print_bitstring(number);
                break;
            case '1':
                printf("enter string: ");
                if (scanf("%32s", string) != 1) 
                    exit(EXIT_FAILURE);
                print_numbvalue(string);
                break;
            case '2':
                printf("enter number  : ");
                if (scanf("%i", &number) != 1) 
                    exit(EXIT_FAILURE);
                printf("enter shiftval: ");
                if (scanf("%i", &shiftval) != 1) 
                    exit(EXIT_FAILURE);
                shiftl(number, shiftval);
                break;
            case '3':
                printf("enter num: ");
                if (scanf("%i", &number) != 1) 
                    exit(EXIT_FAILURE);
                printf("enter shiftval: ");
                if (scanf("%i", &shiftval) != 1) 
                    exit(EXIT_FAILURE);
                shiftr(number, shiftval);
                break;
            case '4':
                printf("enter num: ");
                if (scanf("%i", &number) != 1) 
                    exit(EXIT_FAILURE);
                printf("enter bitmask: ");
                if (scanf("%i", &bitmask) != 1) 
                    exit(EXIT_FAILURE);
                AND(number, bitmask);
                break;
            case '5':
                printf("enter num: ");
                if (scanf("%i", &number) != 1) 
                    exit(EXIT_FAILURE);
                printf("enter bitmask: ");
                if (scanf("%i", &bitmask) != 1) 
                    exit(EXIT_FAILURE);
                OR(number, bitmask);
                break;
            case '6':
                printf("enter num: ");
                if (scanf("%i", &number) != 1) 
                    exit(EXIT_FAILURE);
                printf("enter bitmask: ");
                if (scanf("%i", &bitmask) != 1) 
                    exit(EXIT_FAILURE);
                XOR(number, bitmask);
                break;
            case '7':
                printf("enter num: ");
                if (scanf("%i", &number) != 1) 
                    exit(EXIT_FAILURE);
                NOT(number);
                break;
            default:
                return 0;
        }

        while (getchar() != '\n');
    }
}