cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

list.c (5983B)


      1// list.c
      2
      3#include <stdio.h>
      4#include <stdarg.h>
      5#include <stdlib.h>
      6#include <stdbool.h>
      7#include <string.h>
      8//#include <assert.h>
      9//#include <ctype.h>
     10//#include <signal.h>
     11
     12#include "list.h"
     13
     14// From lcc.c
     15extern void *alloc(int);
     16extern char *strsave(const char *str);
     17extern char *stringf(const char *fmt, ...);
     18extern char *path_stripext(char *name);
     19extern int matches_ext(const char * filename, const char * ext);
     20extern int verbose;
     21
     22
     23
     24/* append - append a node with string str onto list, return new list */
     25List append(char *str, List list) {
     26    List p = alloc(sizeof *p);
     27
     28    p->str = str;
     29    if (list) {
     30        p->link = list->link;
     31        list->link = p;
     32    }
     33    else
     34        p->link = p;
     35    return p;
     36}
     37
     38
     39/* find - find 1st occurrence of str in list, return list node or 0 */
     40List find(char *str, List list) {
     41    List b;
     42
     43    b = list;
     44    if (b)
     45        do {
     46            if (strcmp(str, b->str) == 0)
     47                return b;
     48        } while ((b = b->link) != list);
     49        return 0;
     50}
     51
     52
     53/* path2list - convert a colon- or semicolon-separated list to a list */
     54List path2list(const char *path) {
     55    List list = NULL;
     56    char sep = ':';
     57
     58    if (path == NULL)
     59        return NULL;
     60    if (strchr(path, ';'))
     61        sep = ';';
     62    while (*path) {
     63        char *p, buf[512];
     64        p = strchr(path, sep);
     65        if (p) {
     66            size_t len = p - path;
     67            if(len >= sizeof(buf)) len = sizeof(buf)-1;
     68            strncpy(buf, path, len);
     69            buf[len] = '\0';
     70        }
     71        else {
     72            strncpy(buf, path, sizeof(buf));
     73            buf[sizeof(buf)-1] = '\0';
     74        }
     75        if (!find(buf, list))
     76            list = append(strsave(buf), list);
     77        if (p == 0)
     78            break;
     79        path = p + 1;
     80    }
     81    return list;
     82}
     83
     84
     85// Replace extensions for filenames in a list
     86void list_rewrite_exts(List list_in, char * ext_match, char * ext_new)
     87{
     88    char * filepath_old;
     89
     90    // Iterate through list and replace file extensions
     91    if (list_in) {
     92        List list_t = list_in;
     93        do {
     94            if (list_t->str) {
     95                // Check to see if filname has desired extension
     96                if (matches_ext(list_t->str, ext_match)) {
     97
     98                    // Save a copy to free after re-assignment
     99                    filepath_old = list_t->str;
    100                    // Create a new string with the replaced suffix (stringf() allocs)
    101                    list_t->str = stringf("%s%s", path_stripext(list_t->str), ext_new);
    102                    if (verbose > 0) fprintf(stderr,"lcc: rename link obj (from -autobank): %s -> %s\n", filepath_old, list_t->str);
    103                }
    104            }
    105            // Move to next list item, exit if start of list is reached
    106            list_t = list_t->link;
    107        } while (list_t != list_in);
    108    }
    109}
    110
    111
    112// Duplicate items with [ext_match] into new list items with [ext_new]
    113void list_duplicate_to_new_exts(List list_in, char * ext_match, char * ext_new)
    114{
    115    // List may have entries appended, cache original start
    116    List list_start = list_in;
    117
    118    // Iterate through list and replace file extensions
    119    if (list_in) {
    120        List list_t = list_in;
    121        do {
    122            if (list_t->str) {
    123                // Check to see if filname has desired extension
    124                if (matches_ext(list_t->str, ext_match)) {
    125                    // Make a copy with the replaced extension into the list
    126                    list_in = append(stringf("%s%s", path_stripext(list_t->str), ext_new), list_in);
    127                    if (verbose > 0) fprintf(stderr,"lcc: add to rmlist (from -autobank): %s -> %s\n", list_t->str, stringf("%s%s", path_stripext(list_t->str), ext_new));
    128                }
    129            }
    130            // Move to next list item, exit if start of list is reached
    131            list_t = list_t->link;
    132        } while (list_t != list_start);
    133    }
    134}
    135
    136
    137// Remove all items from a list
    138List list_remove_all(List list_in) {
    139
    140    // Well... the custom alloc() used for lists makes it hard to free their memory.
    141    // Instead just set the list to NULL to erase it and let cleanup happen on program exit.
    142    return NULL;
    143
    144    /*
    145    List list_next;
    146    // Iterate through list and free memory
    147    if (list_in) {
    148        List list_t = list_in->link; // Advance to next item
    149        list_in->link = NULL; // Break list to create a stopping point
    150
    151        do {
    152            // Copy next link before freeing the current item
    153            list_next = list_t->link;
    154            if (list_t) {
    155                free(list_t);
    156                list_t = NULL;
    157            }
    158            // Move to next list item, exit if start of list is reached
    159            list_t = list_next;
    160        } while (list_t && list_t->link);
    161    }
    162    return NULL;
    163    */
    164}
    165
    166
    167// Copies all items from [list_src] to [list_dest]
    168// * optionally prefix items from [list_src] with [str_prefix]
    169// * optionally append() a separate [str_add_before] for each item in [list_src] (use for space separated flags)
    170List list_add_to_another(List list_dest, List list_src, char * str_prefix, char * str_add_before) {
    171
    172    if (list_src) {
    173        List list_t = list_src->link; // Start at first list item (list usually points to END)
    174
    175        // Iterate through [list_src] and copy into to [list_dest], exit once start is reached again
    176        do {
    177            if (list_t->str)
    178                // Add str_add_before string as a separate item if present
    179                if (str_add_before)
    180                    list_dest = append( stringf("%s", str_add_before), list_dest);
    181
    182                // pre-pend string prefix if present
    183                if (str_prefix)
    184                    list_dest = append( stringf("%s%s", str_prefix, list_t->str), list_dest);
    185                else
    186                    list_dest = append( stringf("%s", list_t->str), list_dest);
    187            // Move to next list item
    188            list_t = list_t->link;
    189        } while (list_t != list_src);
    190    }
    191
    192    return list_dest; // Return updated list
    193}