C template
Monday 6 November 2023

#youtube_video

Current implementation

  1#include <dirent.h>
  2#include <stdbool.h>
  3#include <stdio.h>
  4#include <sys/stat.h>
  5#include <sys/types.h>
  6#include <stdlib.h>
  7#include <string.h>
  8
  9#define TEMPLATE_START "<%"
 10#define TEMPLATE_END "%>"
 11
 12char *moveToChar(char *s, char c) {
 13  while(*s!=0 && *s != c) s++;
 14  return s;
 15}
 16
 17bool startsWith(char *s, char *prefix) {
 18  while(*prefix != 0 && *s != 0 && *prefix == *s ) {
 19    s++;
 20    prefix++;
 21  }
 22  return *prefix == 0;
 23}
 24
 25char *moveToStr(char *s, char *substr) {
 26  for (; *(s = moveToChar(s, *substr)) != 0 && !startsWith(s, substr); s++);
 27  return s;
 28}
 29
 30char *moveToStart(char *c) {return moveToStr(c, TEMPLATE_START);}
 31char *moveToEnd(char *c) {return moveToStr(c, TEMPLATE_END);}
 32
 33char *skipStr(char *s, char *substr) {return s + strlen(substr);}
 34char *skipStart(char *c) { return skipStr(c, TEMPLATE_START); }
 35char *skipEnd(char *c) { return skipStr(c, TEMPLATE_END); }
 36
 37void printEval(FILE *src, char *start, char *end) {
 38  fprintf(src, "StringWrite(w, ");
 39  while (start != end && *start != 0) {
 40    fprintf(src, "%c", *start);
 41    start++;
 42  }
 43  fprintf(src, ");\n");
 44}
 45
 46void printFromTo(FILE *src, char *start, char *end) {
 47  while(start!=end && *start != 0 ){
 48    fprintf(src, "%c", *start);
 49    start++;
 50  }
 51}
 52
 53void printString(FILE *src, char *start, char *end) {
 54  fprintf(src, "StringWrite(w, \"");
 55  while (start != end && *start != 0) {
 56    if (*start == '\"') {
 57      fprintf(src, "\\%c", *start);
 58    } else if (*start == '\n') {
 59      fprintf(src, "\"\n\"");
 60    } else {
 61      fprintf(src, "%c", *start);
 62    }
 63    start++;
 64  }
 65  fprintf(src, "\");\n");
 66}
 67
 68void convertContent(FILE *src, char *content) {
 69  char *offset = content;
 70  while (*offset != 0) {
 71    char *nextOpen = moveToStart(offset);
 72    if (*nextOpen == 0){
 73      printString(src, offset, nextOpen);
 74      return;
 75    }
 76
 77    printString(src, offset, nextOpen);
 78
 79    offset = skipStart(nextOpen);
 80    if (*offset == 0) {
 81      fprintf(stderr, "Can't find end of template: \n\t%s", content);
 82      return;
 83    }
 84
 85    char *nextClose = moveToEnd(offset);
 86    if(*offset == '='){
 87      printEval(src, offset+1, nextClose);
 88    }else{
 89      printFromTo(src, offset, nextClose);
 90    }
 91
 92    offset = skipEnd(nextClose);
 93  }
 94}
 95
 96char *FileContent(const char *path) {
 97  FILE *f = fopen(path, "r");
 98  if (f == NULL) {
 99    return NULL;
100  }
101
102  fseek(f, 0, SEEK_END);
103  int size = ftell(f);
104  char *content = malloc(size + 1);
105
106  fseek(f, 0, SEEK_SET);
107  fread(content, 1, size, f);
108  content[size] = 0;
109  fclose(f);
110
111  return content;
112}
113
114void strreplace(char *c, char *replace, char with) {
115  for(char *rr = replace; *rr != 0; rr++)
116    for(char *cc = c; *cc != 0; cc++)
117      if(*cc == *rr )
118        *cc = with;
119}
120
121void processFile(FILE *header, FILE *src, char *f) {
122  fprintf(stderr, "Processing file: %s\n", f);
123  char *content = FileContent(f);
124
125  char *funcName = strdup(f);
126  strreplace(funcName, "/.", '_');
127  fprintf(header, "char *%s(void *);\n", funcName);
128  fprintf(src, "char *%s(void *input) {\n", funcName);
129  fprintf(src, "String *w = StringNew(NULL);\n");
130  free(funcName);
131
132  convertContent(src, content);
133  free(content);
134
135  fprintf(src, "char *ret = w->value;\nfree(w);\nreturn ret;\n }\n");
136}
137
138void processDir(char *dir) {
139  DIR *dfd;
140  if ((dfd = opendir(dir)) == NULL) {
141    fprintf(stderr, "Can't open %s\n", dir);
142    return;
143  }
144
145  FILE *header = fopen("views_funcs.h", "w");
146  FILE *src = fopen("views_funcs.c", "w");
147
148  char filename_qfd[100];
149  struct dirent *dp;
150
151  fprintf(header, "#include \"./string.h\"\n");
152  fprintf(src, "#include \"views_includes.h\"\n#include \"./string.h\"\n");
153
154  while ((dp = readdir(dfd)) != NULL) {
155    struct stat stbuf;
156    sprintf(filename_qfd, "%s/%s", dir, dp->d_name);
157    if (stat(filename_qfd, &stbuf) == -1) {
158      printf("Unable to stat file: %s\n", filename_qfd);
159      continue;
160    }
161
162    if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
163      continue;
164    } else {
165      processFile(header, src, filename_qfd);
166    }
167  }
168
169  fclose(header);
170  fclose(src);
171  closedir(dfd);
172}
173
174
175int main() {
176  processDir("views");
177}

Social media

See Also