#include #include "fs.h" #include #include #include "hashtable.h" #define _(x) x struct macro { char * name; }; void *copy_macro(void * macro) { struct macro * temp = (struct macro*)(macro), * new = malloc(sizeof(struct macro)); new->name = strdup(temp->name); return (void*)(new); } void free_macro(void * macro) { struct macro * temp = (struct macro*)(macro); free(temp->name); free(temp); } typedef struct hashtable macrotable_t; // init default macros empty macrotable_t default_macros = {}; void build_default_macros() { // default macros currently implemented: // if // lstinputlisting // include // input // includegraphics // graphicspath hashtable_clear(&default_macros); } void macrotable_init(macrotable_t * table) { hashtable_init(table); table->dealloc_data = free_macro; } void macrotable_copy(macrotable_t * to, macrotable_t * from) { if (!to || !from) { return; } hashtable_iterator_t it = hashtable_next(from, NULL); struct entry newEntry; for(; it != hashtable_end(from); it = hashtable_next(from, it)) { // insert it into to newEntry = *it; newEntry.data = copy_macro(newEntry.data); hashtable_add(to, newEntry); } } struct filelist { struct filelist * next; char * path; struct hashtable * macros; }; void free_filelist(struct filelist * list) { if (list == NULL) { return; } struct filelist * next = list->next; while(list->next) { next = list->next; free(next->path); free(next); list->next = list->next->next; } free(list->path); free(list); } int filelist_push(struct filelist * pos, const char * path) { struct filelist * new = malloc(sizeof(struct filelist)); if (!new) { errno = ENOMEM; return -1; } new->next = pos->next; new->path = strdup(path); pos->next = new; return 0; } int good(FILE * file) { return !feof(file); } volatile int line = 0, pos = 0; FILE * fopen_count(const char * path, const char * flags) { line = pos = 0; return fopen(path, flags); } char fgetc_count(FILE *file) { char temp = fgetc(file); if (temp == '\n') { line++; pos = 0; } else { pos++; } return temp; } int add_char(char ** str, char c) { if (str == NULL) { return 0; } if (*str != NULL) { int len = strlen(*str); char *temp = realloc(*str, len + 2); if (temp == NULL) { errno = ENOMEM; return -1; } *str = temp; (*str)[len] = c; (*str)[len+1] = 0; return 0; } *str = malloc(2); if (*str == NULL) { errno = ENOMEM; return -1; } (*str)[0] = c; (*str)[1] = '\0'; return 0; } int macro_limiter(char c) { switch(c) { case '\\': // next macro return 1; case '{': // arguments return 2; case '[': // optional arguments return 3; } return 0; } void eval_macro(struct filelist * last, FILE * file) { char * name = NULL; strhash_t hash = 0; hashtable_iterator_t macro = hashtable_end(last->macros); char current = 0; // read macro name while(good(file) && !macro_limiter(current) && macro == hashtable_end(last->macros)) { current = fgetc_count(file); hash = strhash_add(hash, current); add_char(&name, current); // try to find macro in table macro = hashtable_get_hash(last->macros, hash); } if (macro == hashtable_end(last->macros)) { // no macro with that name found printf("%d:%d:macro not found: %s\n", line, pos, name); } if (!good(file)) { return; } } void eval_file(struct filelist * last) { // open file FILE * file = fopen_count(last->path, "r"); if (file == NULL) { fprintf(stderr, _("could not open file \"%s\":%s\n"), last->path, strerror(errno)); return; } printf("processing file: %s\n", last->path); char current = 1; while(good(file)) { current = fgetc_count(file); switch(current) { case '%': // comment, skip line do { current = fgetc_count(file); } while(good(file) && current != '\n'); break; case '\\': // macro eval_macro(last, file); break; default: printf(_("%d:%d:unrecognized char! %c\n"), line, pos, current); break; } } fclose(file); } #include struct option long_opts[] = { {"output", required_argument, NULL, 'o'}, {"target", required_argument, NULL, 't'}, {}, // terminator }; void help(int argc, char ** args) { printf("%s [OPTIONS] file1 file2...\n" "--output\n" "-o\tby default the program will create a depfile for every input\n" "\tnaming it like the tex file with a .d extension. By giving the -o Option\n" "\tthe output will instead be put in this file exculsivly\n" "--target\n" "-t\tOverride the target name\n", args[0]); } int main(int argc, char ** args) { int long_index = 0; int opt = 0; const char *outfile, *target; while((opt = getopt_long(argc, args, "o:t:", long_opts, &long_index)) != -1) { switch(opt) { case 'o': outfile = optarg; break; case 't': target = optarg; break; case '?': help(argc, args); return 0; } } char * current_file = NULL; // process all files for(;optind < argc; ++optind) { current_file = args[optind]; struct filelist list; list.next = NULL; list.path = current_file; list.macros = malloc(sizeof(macrotable_t)); macrotable_init(list.macros); macrotable_copy(list.macros, &default_macros); eval_file(&list); free_filelist(list.next); } }