From 0a8fc0c0ee55b46288b8a23d7d8301ddcea30ff8 Mon Sep 17 00:00:00 2001 From: Dylan Lom Date: Tue, 26 Jan 2021 17:36:07 +1100 Subject: [PATCH 1/9] (#4) Add link and variable to header example * Add sh_prefix variable to be used soon TM * Rename header_list_to_html to header_list_process * Move macros so they wrap the functions that use them --- examples/header.shmd | 5 ++++- shmd.c | 22 ++++++++++++++-------- shmd.h | 2 +- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/examples/header.shmd b/examples/header.shmd index 3223340..35647a9 100644 --- a/examples/header.shmd +++ b/examples/header.shmd @@ -1,9 +1,12 @@ /* * title "My Markdown Article" * author "Dylan Lom" - * charset "utf8" + * charset utf8 + * link stylesheet /main.css */ +# $(echo $title) + ## Body Here Built: $(date) diff --git a/shmd.c b/shmd.c index 86b9e4e..e215a84 100644 --- a/shmd.c +++ b/shmd.c @@ -6,6 +6,11 @@ #include "shmd.h" const char* argv0; +/* + * Not a great name, but this is used for variables that we want avaiable to the + * shell when we start, ie. the header stuff. + */ +char* sh_prefix; struct str_list header_split(char* s) { struct str_list l = STR_LIST_INIT(); @@ -34,7 +39,10 @@ struct str_list header_split(char* s) { return l; } -char* header_list_to_html(struct str_list l) { +#define HTML_SPRINTF(l_min, fmt, ...) if (l.size < l_min) return ""; \ + html = STR_EALLOC(sizeof(fmt) + vals_size + 1); \ + sprintf(html, fmt, __VA_ARGS__) +char* header_list_process(struct str_list l) { if (l.size < 1) return ""; char** vals = l.values; /* work out the total length of all strings */ @@ -47,9 +55,6 @@ char* header_list_to_html(struct str_list l) { * TODO: This is gross... I did it like this to make the if ... else * statement readable... need a better abstraction though */ -#define HTML_SPRINTF(l_min, fmt, ...) if (l.size < l_min) return ""; \ - html = STR_EALLOC(sizeof(fmt) + vals_size + 1); \ - sprintf(html, fmt, __VA_ARGS__) /* Known HEAD tags */ if (strcmp(vals[0], "charset") == 0) { HTML_SPRINTF(2, "", vals[1]); @@ -60,13 +65,13 @@ char* header_list_to_html(struct str_list l) { } else { HTML_SPRINTF(2, "", vals[0], vals[1]); } -#undef HTML_SPRINTF return html; } +#undef HTML_SPRINTF -char* header_substitute(FILE* fp) { #define HEADER_ISEND(s) (strlen(s) >= 2 && s[0] == '*' && s[1] == '/') +char* header_substitute(FILE* fp) { char* result = str_concat(1, ""); size_t line_size = 250; @@ -87,7 +92,7 @@ char* header_substitute(FILE* fp) { if (*lp == '\0') continue; struct str_list list = header_split(lp); - char* line_html = header_list_to_html(list); + char* line_html = header_list_process(list); str_list_free(&list); /* concat html to result */ @@ -99,8 +104,8 @@ char* header_substitute(FILE* fp) { result = str_concat(3, result, "\n", ""); free(tmp); return result; -#undef HEADER_ISEND } +#undef HEADER_ISEND char* command_execute(const char* command) { FILE *pp; @@ -189,5 +194,6 @@ int process_input(FILE* fp) { int main(int argc, char* argv[]) { SET_ARGV0(); + sh_prefix = STR_EALLOC(100); return process_input(stdin); } diff --git a/shmd.h b/shmd.h index 2187252..e055641 100644 --- a/shmd.h +++ b/shmd.h @@ -7,7 +7,7 @@ const char* argv0; struct str_list header_split (char* s); -char* header_list_to_html (struct str_list l); +char* header_list_process (struct str_list l); char* header_substitute (FILE* fp); /** From e46eb734683b022e93b163b4cdf05f361ab7dafd Mon Sep 17 00:00:00 2001 From: Dylan Lom Date: Tue, 26 Jan 2021 18:08:40 +1100 Subject: [PATCH 2/9] (#4) Make header properties available as variables --- shmd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/shmd.c b/shmd.c index e215a84..0cd127a 100644 --- a/shmd.c +++ b/shmd.c @@ -66,6 +66,11 @@ char* header_list_process(struct str_list l) { HTML_SPRINTF(2, "", vals[0], vals[1]); } + /* Add to sh_prefix so that values are available in the shell environment */ + char* tmp = sh_prefix; + sh_prefix = str_concat(5, sh_prefix, l.values[0], "=\"", l.values[l.size-1], "\"; "); + free(tmp); + return html; } #undef HTML_SPRINTF @@ -109,7 +114,7 @@ char* header_substitute(FILE* fp) { char* command_execute(const char* command) { FILE *pp; - pp = popen(command, "r"); + pp = popen(str_concat(2, sh_prefix, command), "r"); if (pp == NULL) edie("popen: "); char* result = STR_EALLOC(1); From 1a7fb05cdb3c83f3aab1e7bd8d1481906b06ea41 Mon Sep 17 00:00:00 2001 From: Dylan Lom Date: Tue, 26 Jan 2021 18:36:20 +1100 Subject: [PATCH 3/9] (#4) Implement header functions * Need to backslash *any* quotes in function bodys. Should change how quoting works so that any quotes within an outer quote are preserved. --- examples/header.shmd | 7 +++++-- shmd.c | 12 ++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/examples/header.shmd b/examples/header.shmd index 35647a9..f4e4a12 100644 --- a/examples/header.shmd +++ b/examples/header.shmd @@ -1,12 +1,15 @@ /* - * title "My Markdown Article" - * author "Dylan Lom" + * title 'My Markdown Article' + * author 'Dylan Lom' * charset utf8 * link stylesheet /main.css + * sh_node() 'echo \"console.log($1)\" | node' */ # $(echo $title) ## Body Here +Date according to node: `$(sh_node "new Date().toISOString()")` + Built: $(date) diff --git a/shmd.c b/shmd.c index 0cd127a..4241686 100644 --- a/shmd.c +++ b/shmd.c @@ -68,7 +68,14 @@ char* header_list_process(struct str_list l) { /* Add to sh_prefix so that values are available in the shell environment */ char* tmp = sh_prefix; - sh_prefix = str_concat(5, sh_prefix, l.values[0], "=\"", l.values[l.size-1], "\"; "); + size_t val0_length = strlen(vals[0]) - 1; + if (vals[0][val0_length-1] == '(' && vals[0][val0_length] == ')') { + /* Function */ + sh_prefix = str_concat(5, sh_prefix, vals[0], " { ", vals[l.size-1], "; }; "); + } else { + /* Variable */ + sh_prefix = str_concat(5, sh_prefix, vals[0], "=\"", vals[l.size-1], "\"; "); + } free(tmp); return html; @@ -114,7 +121,8 @@ char* header_substitute(FILE* fp) { char* command_execute(const char* command) { FILE *pp; - pp = popen(str_concat(2, sh_prefix, command), "r"); + char* c = str_concat(2, sh_prefix, command); + pp = popen(c, "r"); if (pp == NULL) edie("popen: "); char* result = STR_EALLOC(1); From 9f4ac595a82d3cfba50c6ea12599b17d8d88c521 Mon Sep 17 00:00:00 2001 From: Dylan Lom Date: Tue, 26 Jan 2021 18:40:27 +1100 Subject: [PATCH 4/9] (#4) Ignore nested quotes in header If there is an opening quotation (ie. `'`), internal quotes (ie. `"`) will be preserved. This allows for cleaner function declarations. --- examples/header.shmd | 2 +- shmd.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/header.shmd b/examples/header.shmd index f4e4a12..43becb0 100644 --- a/examples/header.shmd +++ b/examples/header.shmd @@ -3,7 +3,7 @@ * author 'Dylan Lom' * charset utf8 * link stylesheet /main.css - * sh_node() 'echo \"console.log($1)\" | node' + * sh_node() 'echo "console.log($1)" | node' */ # $(echo $title) diff --git a/shmd.c b/shmd.c index 4241686..fe740de 100644 --- a/shmd.c +++ b/shmd.c @@ -27,8 +27,8 @@ struct str_list header_split(char* s) { continue; } else if (*s == '\\' && !in_escape) { in_escape = 1; continue; } - else if (*s == '"' && !in_escape) { in_dquote ^= 1; continue; } - else if (*s == '\'' && !in_escape) { in_squote ^= 1; continue; } + else if (*s == '"' && !in_escape && !in_squote) { in_dquote ^= 1; continue; } + else if (*s == '\'' && !in_escape && !in_dquote) { in_squote ^= 1; continue; } word_size = str_pushc(word, *s, word_size, 100); /* It's just simpler to reset this after every iteration */ From f9d07ac21aca3762ae84c4e42ceb34c7b45db535 Mon Sep 17 00:00:00 2001 From: Dylan Lom Date: Tue, 26 Jan 2021 19:27:23 +1100 Subject: [PATCH 5/9] Format util.h * Formalise usage function with argument type void. --- util.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/util.h b/util.h index af9d4c8..b96b5db 100644 --- a/util.h +++ b/util.h @@ -3,15 +3,15 @@ #define SHIFT_ARGS() argv++; argc-- #define SET_ARGV0() argv0 = argv[0]; SHIFT_ARGS() -void die(const char* fmt, ...); -void edie(const char* fmt, ...); -void usage(); +void die (const char* fmt, ...); +void edie (const char* fmt, ...); +void usage (void); -void* ecalloc(size_t nmemb, size_t size); +void* ecalloc (size_t nmemb, size_t size); -size_t str_pushc(char* s, char c, size_t s_size, size_t realloc_amount); -int str_trimr(char* s, char c, int max_num); -char* str_concat(int count, ...); +size_t str_pushc (char* s, char c, size_t s_size, size_t realloc_amount); +int str_trimr (char* s, char c, int max_num); +char* str_concat (int count, ...); #define STR_EALLOC(s) ecalloc(s, sizeof(char)) #define STR_MALLOC(s) calloc(s, sizeof(char)) @@ -20,8 +20,8 @@ struct str_list { char** values; }; -struct str_list* str_list_add(struct str_list* l, char* s); -struct str_list str_list_new(int count, ...); -void str_list_free(struct str_list* l); +struct str_list* str_list_add (struct str_list* l, char* s); +struct str_list str_list_new (int count, ...); +void str_list_free (struct str_list* l); #define STR_LIST_INIT() str_list_new(0) From 14910e79674e9efd8cc1b675c725cf2df73e6431 Mon Sep 17 00:00:00 2001 From: Dylan Lom Date: Thu, 4 Feb 2021 19:21:14 +1100 Subject: [PATCH 6/9] Merge 'master' into #4 Squashed commit of the following: commit 74b0e7aa54a9b79335ed76396e3d03373209418a Author: Dylan Lom Date: Tue Jan 26 13:01:39 2021 +1100 Fix bug with link elements Link tags in the header were using "vals=" instead of "href="... --- shmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shmd.c b/shmd.c index fe740de..4c41579 100644 --- a/shmd.c +++ b/shmd.c @@ -61,7 +61,7 @@ char* header_list_process(struct str_list l) { } else if (strcmp(vals[0], "title") == 0) { HTML_SPRINTF(2, "%s", vals[1]); } else if (strcmp(vals[0], "link") == 0) { - HTML_SPRINTF(3, "", vals[1], vals[2]); + HTML_SPRINTF(3, "", vals[1], vals[2]); } else { HTML_SPRINTF(2, "", vals[0], vals[1]); } From 8fbbc8e19232dfe6f71ff2d04312e0158060e512 Mon Sep 17 00:00:00 2001 From: Dylan Lom Date: Sat, 6 Feb 2021 16:18:03 +1100 Subject: [PATCH 7/9] (#6) Start refactoring header logic REGRESSION: Headers and functions are currently in a BROKEN state, but at least the code base is a little nicer right? :) --- .gitignore | 1 + examples/index.shmd | 12 +++ examples/tutorial.md | 12 +++ shmd.c | 195 +++++++++++++++++++++++-------------------- shmd.h | 32 +++++-- 5 files changed, 154 insertions(+), 98 deletions(-) create mode 100644 examples/index.shmd create mode 100644 examples/tutorial.md diff --git a/.gitignore b/.gitignore index daaff45..be98eff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ a.out shmd *.swp +tags diff --git a/examples/index.shmd b/examples/index.shmd new file mode 100644 index 0000000..a4394ce --- /dev/null +++ b/examples/index.shmd @@ -0,0 +1,12 @@ +# Index + +Files in examples/ + +$( + for f in examples/*; do + echo "* [$(basename $f)]($f)" + done; +) + +Pretty cool :) + diff --git a/examples/tutorial.md b/examples/tutorial.md new file mode 100644 index 0000000..32236a0 --- /dev/null +++ b/examples/tutorial.md @@ -0,0 +1,12 @@ +/* + * title "SHMD Tutorial" + * author "Dylan Lom" + * func1() 'echo "hello!"' + */ + +# $(echo "$title") + +Embed shell commands with `\$(echo "hi!")` + +You can write functions: $(func1 "$(whoami)") + diff --git a/shmd.c b/shmd.c index 4c41579..99d937b 100644 --- a/shmd.c +++ b/shmd.c @@ -2,119 +2,134 @@ #include #include #include +#include #include "shmd.h" -const char* argv0; -/* - * Not a great name, but this is used for variables that we want avaiable to the - * shell when we start, ie. the header stuff. - */ -char* sh_prefix; +const char *argv0; +char *sh_prefix; -struct str_list header_split(char* s) { - struct str_list l = STR_LIST_INIT(); - size_t word_size = 100; - char* word = STR_EALLOC(word_size); +char *header_process_extract_field(FILE *fp) +{ + char c; + size_t dest_size = 100; + char *dest = STR_EALLOC(dest_size); - /* Keep track of whether we're inside of a quoted or escaped string */ - int in_dquote = 0, in_squote = 0, in_escape = 0; - - for ( ; *s != '\0'; s++) { - if (*s == ' ' && !in_squote && !in_dquote) { - str_list_add(&l, word); - word = STR_EALLOC(word_size); /* Allocate memory for next word */ - continue; + bool is_escaped = false, + is_dquoted = false, + is_squoted = false; + while ( + (c = fgetc(fp)) != '\0' && !( + !is_dquoted + && !is_squoted + && !is_escaped + && (c == ' ' || c == '\n') + ) + ) { + if (!is_escaped) { + if (c == '"' && !is_squoted) { + is_dquoted = !is_dquoted; + continue; + } else if (c == '\'' && !is_dquoted) { + is_squoted = !is_squoted; + continue; + } else if (c == '\\') { + is_escaped = true; + continue; + } } - else if (*s == '\\' && !in_escape) { in_escape = 1; continue; } - else if (*s == '"' && !in_escape && !in_squote) { in_dquote ^= 1; continue; } - else if (*s == '\'' && !in_escape && !in_dquote) { in_squote ^= 1; continue; } - - word_size = str_pushc(word, *s, word_size, 100); - /* It's just simpler to reset this after every iteration */ - in_escape = 0; + dest_size = str_pushc(dest, c, dest_size, 50); } - - if (strlen(word) > 0) str_list_add(&l, word); - return l; + return dest; } -#define HTML_SPRINTF(l_min, fmt, ...) if (l.size < l_min) return ""; \ - html = STR_EALLOC(sizeof(fmt) + vals_size + 1); \ - sprintf(html, fmt, __VA_ARGS__) -char* header_list_process(struct str_list l) { - if (l.size < 1) return ""; - char** vals = l.values; - /* work out the total length of all strings */ - size_t vals_size = 0; - for (int i = 0; i < l.size; i++) - vals_size += strlen(vals[i]); - - char* html; - /* - * TODO: This is gross... I did it like this to make the if ... else - * statement readable... need a better abstraction though - */ - /* Known HEAD tags */ - if (strcmp(vals[0], "charset") == 0) { - HTML_SPRINTF(2, "", vals[1]); - } else if (strcmp(vals[0], "title") == 0) { - HTML_SPRINTF(2, "%s", vals[1]); - } else if (strcmp(vals[0], "link") == 0) { - HTML_SPRINTF(3, "", vals[1], vals[2]); - } else { - HTML_SPRINTF(2, "", vals[0], vals[1]); +size_t header_field_count(enum header_field_type type) +{ + size_t count = 0; + switch (type) { + case E_HEADER_FIELD_CHARSET: + count = 1; + break; + case E_HEADER_FIELD_TITLE: + count = 1; + break; + case E_HEADER_FIELD_LINK: + count = 2; + break; + case E_HEADER_FIELD_META: + count = 1; + break; } - - /* Add to sh_prefix so that values are available in the shell environment */ - char* tmp = sh_prefix; - size_t val0_length = strlen(vals[0]) - 1; - if (vals[0][val0_length-1] == '(' && vals[0][val0_length] == ')') { - /* Function */ - sh_prefix = str_concat(5, sh_prefix, vals[0], " { ", vals[l.size-1], "; }; "); - } else { - /* Variable */ - sh_prefix = str_concat(5, sh_prefix, vals[0], "=\"", vals[l.size-1], "\"; "); - } - free(tmp); - - return html; + return count; } -#undef HTML_SPRINTF -#define HEADER_ISEND(s) (strlen(s) >= 2 && s[0] == '*' && s[1] == '/') +char **header_process_fields(FILE *fp, enum header_field_type type) +{ + size_t values_count = header_field_count(type); + char **values = ecalloc(values_count, sizeof(char*)); + + for (int i = 0; i < values_count; i++) { + values[i] = header_process_extract_field(fp); + } + + return values; +} + +/* Process a header record */ +char *header_process(FILE *fp) +{ + size_t name_size = 100; + char* name = STR_EALLOC(name_size); + char c; + while ((c = fgetc(fp)) != '\0' && c != ' ') { + name_size = str_pushc(name, c, name_size, 100); + } + + enum header_field_type type; + if (strcmp(name, "charset") == 0) + type = E_HEADER_FIELD_CHARSET; + else if (strcmp(name, "title") == 0) + type = E_HEADER_FIELD_TITLE; + else if (strcmp(name, "link") == 0) + type = E_HEADER_FIELD_LINK; + else + type = E_HEADER_FIELD_META; + + char **values = header_process_fields(fp, type); + size_t values_count = header_field_count(type); + + return name; +} + +#define HEADER_ISEND(b, c) (b == '*' && c == '/') char* header_substitute(FILE* fp) { char* result = str_concat(1, ""); - size_t line_size = 250; - char* line = STR_EALLOC(line_size); - char* lp; - char* tmp; - while (fgets(line, line_size, fp) != NULL) { - str_trimr(line, '\n', 1); - lp = line; + char b = '\0'; + char c; + while ((c = fgetc(fp)) != '\0') { /* * Non-alphabetical characters (e.g. whitespace, '*') in the header are * ignored, advance lp to the start of input, while also making sure we * don't reach the end of the line ('\0') or the end of the header * section ('* /' without the space). */ - while (!isalpha(*lp) && *lp != '\0' && !HEADER_ISEND(lp)) { lp++; } - if (HEADER_ISEND(lp)) break; - if (*lp == '\0') continue; + while ( + !isalpha(c) + && c != '"' + && c != '\'' + && c != '\0' + && !HEADER_ISEND(b, c) + ) { + b = c; + c = fgetc(fp); + } + if (c == '\0') continue; + if (HEADER_ISEND(b, c)) break; - struct str_list list = header_split(lp); - char* line_html = header_list_process(list); - str_list_free(&list); - - /* concat html to result */ - tmp = result; - result = str_concat(3, result, "\n\t", line_html); - free(tmp); + ungetc(c, fp); + header_process(fp); } - tmp = result; - result = str_concat(3, result, "\n", ""); - free(tmp); return result; } #undef HEADER_ISEND diff --git a/shmd.h b/shmd.h index e055641..7bc38cf 100644 --- a/shmd.h +++ b/shmd.h @@ -1,14 +1,30 @@ #include "util.h" + + /** * #argv0 * value of argv[0] at the start of execution (ie. the program's name). */ -const char* argv0; +const char *argv0; +char *sh_prefix; + +enum header_field_type +{ + E_HEADER_FIELD_CHARSET, + E_HEADER_FIELD_TITLE, + E_HEADER_FIELD_LINK, + E_HEADER_FIELD_META +}; +/* Read the next field from @fp */ +char *header_process_extract_field(FILE *fp); +/* Get the number of properties for header type @type */ +size_t header_field_count(enum header_field_type type); +/* Read space-seperated fields from @fp */ +char **header_process_fields(FILE *fp, enum header_field_type type); +char *header_process(FILE *fp); +char *header_substitute(FILE *fp); -struct str_list header_split (char* s); -char* header_list_process (struct str_list l); -char* header_substitute (FILE* fp); /** * #command_execute @@ -17,7 +33,7 @@ char* header_substitute (FILE* fp); * @return: stdout returned when running @command, with at most one trailing * newline stripped. */ -char* command_execute (const char* command); +char *command_execute(const char *command); /** * #command_substitute * Read @fp until the next unmatched `)` character and execute. This process is @@ -26,7 +42,7 @@ char* command_execute (const char* command); * @fp: file pointer to read from. * @return: the output of running #execute_command on the input read. */ -char* command_substitute (FILE* fp); +char *command_substitute (FILE *fp); -int process_input (FILE* fp); -int main (int argc, char* argv[]); +int process_input(FILE *fp); +int main(int argc, char *argv[]); From cc017a28bfc140edf68b8804c64b188543ccacdc Mon Sep 17 00:00:00 2001 From: Dylan Lom Date: Sat, 6 Feb 2021 17:38:57 +1100 Subject: [PATCH 8/9] (#6) Re-implement header and functions better --- examples/header.shmd | 2 +- shmd.c | 55 ++++++++++++++++++++++++++++++++++++++++---- shmd.h | 13 ++++++++--- 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/examples/header.shmd b/examples/header.shmd index 43becb0..6cb1e51 100644 --- a/examples/header.shmd +++ b/examples/header.shmd @@ -6,7 +6,7 @@ * sh_node() 'echo "console.log($1)" | node' */ -# $(echo $title) +# $(echo "$title") ## Body Here diff --git a/shmd.c b/shmd.c index 99d937b..7ddbbd7 100644 --- a/shmd.c +++ b/shmd.c @@ -75,8 +75,51 @@ char **header_process_fields(FILE *fp, enum header_field_type type) return values; } -/* Process a header record */ -char *header_process(FILE *fp) +char *header_to_html(enum header_field_type type, char *name, char **values) +{ + char *result; + switch (type) { + case E_HEADER_FIELD_CHARSET: + result = str_concat(3, ""); + break; + case E_HEADER_FIELD_TITLE: + result = str_concat(3, "", values[0], ""); + break; + case E_HEADER_FIELD_LINK: + result = str_concat( + 5, "" + ); + break; + case E_HEADER_FIELD_META: + result = str_concat( + 5, "" + ); + break; + } + return result; +} + +char *header_to_sh(enum header_field_type type, char *name, char **values) +{ + char *result; + size_t name_size = strlen(name); + // name=(last value) + char *value = values[header_field_count(type) - 1]; + bool is_function = ( + type == E_HEADER_FIELD_META + && name[name_size-2] == '(' + && name[name_size-1] == ')' + ); + + if (is_function) { + result = str_concat(4, name, " { ", value, "; }; "); + } else { + result = str_concat(4, name, "='", value, "'; "); + } + return result; +} + +void header_process(FILE *fp) { size_t name_size = 100; char* name = STR_EALLOC(name_size); @@ -98,7 +141,11 @@ char *header_process(FILE *fp) char **values = header_process_fields(fp, type); size_t values_count = header_field_count(type); - return name; + char *tmp = str_concat(2, sh_prefix, header_to_sh(type, name, values)); + free(sh_prefix); + sh_prefix = tmp; + + puts(header_to_html(type, name, values)); } #define HEADER_ISEND(b, c) (b == '*' && c == '/') @@ -222,6 +269,6 @@ int process_input(FILE* fp) { int main(int argc, char* argv[]) { SET_ARGV0(); - sh_prefix = STR_EALLOC(100); + sh_prefix = STR_EALLOC(1); return process_input(stdin); } diff --git a/shmd.h b/shmd.h index 7bc38cf..465302d 100644 --- a/shmd.h +++ b/shmd.h @@ -1,7 +1,5 @@ #include "util.h" - - /** * #argv0 * value of argv[0] at the start of execution (ie. the program's name). @@ -22,7 +20,16 @@ char *header_process_extract_field(FILE *fp); size_t header_field_count(enum header_field_type type); /* Read space-seperated fields from @fp */ char **header_process_fields(FILE *fp, enum header_field_type type); -char *header_process(FILE *fp); +/* Get the html-ized version of a header */ +char *header_to_html(enum header_field_type type, char *name, char **values); +/* + * Get the shell-executable assignment of a header, using the last value as + * the value. + * In the special case @type is E_HEADER_FIELD_META and @name ends in '()', + * will return a posix-style function declaration. + */ +char *header_to_sh(enum header_field_type type, char *name, char **values); +void header_process(FILE *fp); char *header_substitute(FILE *fp); From c7d1b0b97ac7a40eb8a90db2bedc7437eac972b1 Mon Sep 17 00:00:00 2001 From: Dylan Lom Date: Sat, 6 Feb 2021 17:43:29 +1100 Subject: [PATCH 9/9] Remove unused variable Reformat tmp-free pattern in header_process so it's the same as the rest of the codebase. --- shmd.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/shmd.c b/shmd.c index 7ddbbd7..ec360ff 100644 --- a/shmd.c +++ b/shmd.c @@ -139,11 +139,10 @@ void header_process(FILE *fp) type = E_HEADER_FIELD_META; char **values = header_process_fields(fp, type); - size_t values_count = header_field_count(type); - char *tmp = str_concat(2, sh_prefix, header_to_sh(type, name, values)); - free(sh_prefix); - sh_prefix = tmp; + char *tmp = sh_prefix; + sh_prefix = str_concat(2, sh_prefix, header_to_sh(type, name, values)); + free(tmp); puts(header_to_html(type, name, values)); }