#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "../lpi.h"

void print(struct macro macros[], int size, int base, int space, int group);
int cmp(const void *, const void *);

int
main(void)
{
    struct macro statMacros[] = {
        "S_IWOTH", S_IWOTH,
        "S_IROTH", S_IROTH,
        "S_IRWXO", S_IRWXO,
        "S_IXGRP", S_IXGRP,
        "S_IWGRP", S_IWGRP,
        "S_IRGRP", S_IRGRP,
        "S_IRWXG", S_IRWXG,
        "S_IXUSR", S_IXUSR,
        "S_IWUSR", S_IWUSR,
        "S_IRUSR", S_IRUSR,
        "S_IRWXU", S_IRWXU,
        "S_ISVTX", S_ISVTX,
        "S_ISGID", S_ISGID,
        "S_ISUID", S_ISUID,
        "S_IFIFO", S_IFIFO,
        "S_IFCHR", S_IFCHR,
        "S_IFDIR", S_IFDIR,
        "S_IFBLK", S_IFBLK,
        "S_IFREG", S_IFREG,
        "S_IFLNK", S_IFLNK,
        "S_IFSOCK", S_IFSOCK,
        "S_IFMT", S_IFMT,
        "S_IXOTH", S_IXOTH
    };

    struct macro openFlags[] = {
        "O_RDONLY", O_RDONLY,
        "O_WRONLY", O_WRONLY,
        "O_RDWR", O_RDWR,
        "O_CLOEXEC", O_CLOEXEC,
        "O_CREAT", O_CREAT,
        "O_DIRECTORY", O_DIRECTORY,
        "O_EXCL", O_EXCL,
        "O_NOCTTY", O_NOCTTY,
        "O_NOFOLLOW", O_NOFOLLOW,
        "O_TRUNC", O_TRUNC,
        "O_APPEND", O_APPEND,
        "O_ASYNC", O_ASYNC,
        "O_DSYNC", O_DSYNC,
        "O_NONBLOCK", O_NONBLOCK,
        "O_SYNC", O_SYNC,
        "O_PATH", O_PATH,
        "O_TMPFILE", O_TMPFILE,
        "O_DIRECT", O_DIRECT,
        "O_LARGEFILE", O_LARGEFILE,
        "O_NOATIME", O_NOATIME,
    };

    qsort(statMacros, NELEM(statMacros), sizeof(statMacros[0]), cmp);
    printf("st_mode in OCTAL format\n");
    print(statMacros, NELEM(statMacros), 8, 6, 3);

    qsort(openFlags, NELEM(openFlags), sizeof(openFlags[0]), cmp);
    printf("\nopen() flags in HEX format\n");
    print(openFlags, NELEM(openFlags), 16, 6, 4);
    exit(EXIT_SUCCESS);
}

void
print(struct macro macros[], int nelem, int base, int space, int group)
{
    int i;
    for (i = 0; i < nelem; i++) {
        printf("%-14s %7s\n",
                macros[i].name,
                toBase(macros[i].value, base, space, group, ' '));
    }
}

int
cmp(const void *p1, const void *p2)
{
    const struct macro *a = p1;
    const struct macro *b = p2;

    if (a->value > b->value)
        return 1;
    else if (a->value == b->value)
        return 0;
    else
        return -1;
}
