'Difficulty setting pointers in dynamically allocated nested structs

Been at this thing for awhile. I'm writing a C program that parses a csv file into a nested struct. When I pass the ** to the struct into the add_field function, I am able to get all of the pointers until I get to the field[(* f) - 1] pointer of the field array. That always returns NULL and I cannot figure out why. Any help would be greatly appreciated. Thank you.

Sorry for the huge code dump but I didn't want to leave anything out. I've been checking for null after every alloc but haven't incorporated them yet in this rewrite (I’m watching variable values with step in on clion).

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

/* Inline function for handling errors during memory allocation */
extern int errno;
#ifndef error
#define ERROR static inline void *
__attribute((always_inline)) ERROR error() {
    printf("%d\n", errno);
    printf("%s", strerror(errno));
    exit(EXIT_FAILURE);
}
#endif
/* ------------------------------------------------------------ */

#define MAX_BUFFER_SIZE 100


typedef struct data_field {

        char * data;
        size_t fldsize;

    } FIELD;

typedef struct data_set {

        int field_count;
        size_t setsize;
        FIELD ** field;

    } SET;

typedef struct csv_file {

        char * filename;
        int set_count;
        size_t filesize;
        SET ** set;

    } CSV;

CSV * alloc_csv();
void add_set(CSV ** fp, const int * setcnt);
void add_field(SET **sp, char *buffer, const int *f);
char * file_read(char * file_name);



int main()
{
    int b = 0;
    ulong bufcnt = 0;
    int fldcnt = 0;
    int setcnt = 0;
    int bmax = 100;

    char tok1 = '\n';
    char tok2 =  ',';
    char * buffer;
    char * stream;

    stream = file_read("/home/jonathon/Documents/programming/personal/csv/data_files/MOCK_DATA.csv");

    CSV * file = {0};
    void * filetmp = malloc(sizeof(CSV));
    file = filetmp;
    file->set_count = 0;

    void * arrtmp = calloc(1, sizeof(SET *));
    file->set = (SET **)arrtmp;

    void * settmp = calloc(1, sizeof(SET));
    file->set[0] = (SET *)settmp;

    setcnt++;

    void * buftmp = malloc(sizeof(char) * MAX_BUFFER_SIZE);
    buffer = buftmp;

    // read stream until end of field
    buftmp = malloc(sizeof(char) * MAX_BUFFER_SIZE);
    buffer = buftmp;
    for (int c = 0; stream[c] != '\0'; c++)
    {
        if (b >= bmax)
        {
            buftmp = realloc(buffer, sizeof(char) * (MAX_BUFFER_SIZE + bmax));
            buffer = buftmp;
        }

        switch (stream[c])
        {
            case 10:
                buffer[b] == '\0';
                b = 0;
                
                break;
            case 44:
                buffer[b] == '\0';
                add_field(&file->set[setcnt - 1], buffer, &fldcnt);
                fldcnt++;

                b = 0;
                break;
            default:
                buffer[b] = stream[c];
                b++;
                
        }
    }
}

void add_field(SET ** sp, char * buffer, const int * f)
{
    ulong buflen = strlen(buffer + 1);

    if ((*f) == 0)
    {
        (*sp)->field = (FIELD **)calloc(1, sizeof(FIELD *));
    }
    else
    {
        (*sp)->field = (FIELD **)realloc((*sp)->field, sizeof(FIELD *) * ((*f) + 1));
    }

    (*sp)->field[(*f) - 1] = (FIELD *)calloc(1, sizeof(FIELD));

    (*sp)->field[(*f) - 1]->data = (char *)calloc(buflen, sizeof(char));
    memcpy((*sp)->field[(*f) - 1]->data, buffer, buflen * sizeof(char));
}

void free_csv(CSV ** fp, const int * setcnt, const int * fldcnt)
{
    for (int i = 0; i < * setcnt; i++)
    {
        for (int j = 0; j < * fldcnt; j++)
        {
            free((* fp)->set[i]->field[j]->data);
            free((* fp)->set[i]->field[j]);
        }
        free((* fp)->set[i]->field);
        free((* fp)->set[i]);
    }
    free((* fp)->set);
    free(* fp);
}

char *file_read(char* file_name)
{
    FILE *fp = fopen(file_name, "rb");
    size_t file_size;

    char* file_buffer = NULL;

    if (!fp)
    {
        perror("Error: ");
        exit(EXIT_FAILURE);
    }
    else
    {
//              Seek to end of file to get file file_size
        fseek(fp, 0, SEEK_END);
        file_size = ftell(fp);
        file_buffer = (char *)calloc(file_size, sizeof(char));      // Allocate buffer file_size
        if (!file_buffer)
        {
            perror("Error: ");
            exit(EXIT_FAILURE);
        }

//              Seek to beginning of file to read from start.
        fseek(fp, 0, SEEK_SET);
        if (fread(file_buffer, file_size, 1, fp) != 1)        // Read into buffer
        {
            perror("Error: ");
            exit(EXIT_FAILURE);
        }

        fclose(fp);
    }

    return file_buffer;
}```


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source