Created
March 29, 2015 18:32
-
-
Save b4n/4c100d6f1defd4751217 to your computer and use it in GitHub Desktop.
test for build_replace_placeholder()
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* test for build_replace_placeholder(). | |
* USAGE: [-q | -Q] [basename [dirname [basename-without-ext [line [project]]]]] | |
* | |
* example: | |
* test-build-replace-placeholders -Q "file name" "/dir/name" "file name" 42 < test-build-replace-placeholders.input | |
*/ | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <glib.h> | |
#define SETPTR(a, b) do { gpointer t = (b); g_free(a); a = t; } while(0) | |
/* Replaces %f, %d, %e, %l and %p placeholders in a shell-style string. | |
* | |
* This functions reads @p src as a shell-style input, understanding quoting (with "" and '') | |
* as well as nested sub-commands (with `` and $(), up to 16 levels). It makes sure the | |
* placeholder replacements are properly quoted. | |
* | |
* If @quote is FALSE, it only replaces placeholders without adding any quoting. This is | |
* useful if replacing placeholders in a non-shell string, like working directory. | |
* | |
* Returns: an UTF-8 string with placeholders replaced. */ | |
static gchar *build_replace_placeholder(const gchar *f_, | |
const gchar *d_, | |
const gchar *e_, | |
gint l_, | |
const gchar *p_, | |
const gchar *src, gboolean quote) | |
{ | |
GString *stack; | |
struct { | |
gchar quote; | |
gchar terminator; | |
} nesting[16] = {{ 0, 0 }}; | |
guint level = 0; | |
/* replacements, %<letter> */ | |
gchar *f = g_strdup(f_); /* %f: basename */ | |
gchar *d = g_strdup(d_); /* %d: dirname */ | |
gchar *e = g_strdup(e_); /* %e: basename without extension */ | |
gint l = l_; /* %l: current 1-based line number */ | |
gchar *p = g_strdup(p_); /* %p: project (absolute) base directory */ | |
/*g_return_val_if_fail(doc == NULL || doc->is_valid, NULL);*/ | |
if (src == NULL) | |
return NULL; | |
/*if (doc != NULL && doc->file_name != NULL) | |
{ | |
gchar *filename = utils_get_utf8_from_locale(doc->file_name); | |
f = g_path_get_basename(filename); | |
d = g_path_get_dirname(filename); | |
e = utils_remove_ext_from_filename(f); | |
g_free(filename); | |
} | |
if (doc != NULL) | |
l = sci_get_current_line(doc->editor->sci) + 1; | |
if (app->project) | |
p = project_get_base_path();*/ | |
if (quote) | |
{ | |
/* quote the replacements */ | |
if (f) SETPTR(f, g_shell_quote(f)); | |
if (d) SETPTR(d, g_shell_quote(d)); | |
if (e) SETPTR(e, g_shell_quote(e)); | |
if (p) SETPTR(p, g_shell_quote(p)); | |
} | |
stack = g_string_new(NULL); | |
for (; *src; src++) | |
{ | |
if (*src == nesting[level].terminator && | |
! nesting[level].quote) | |
{ | |
g_string_append_c(stack, *src); | |
level--; | |
continue; | |
} | |
switch (*src) | |
{ | |
case '`': | |
g_string_append_c(stack, *src); | |
if (nesting[level].quote != '\'' && | |
level < G_N_ELEMENTS(nesting)) | |
{ | |
level ++; | |
nesting[level].quote = 0; | |
nesting[level].terminator = *src; | |
} | |
break; | |
case '$': | |
g_string_append_c(stack, *src); | |
if (nesting[level].quote != '\'' && | |
level < G_N_ELEMENTS(nesting) && | |
src[1] == '(') | |
{ | |
src++; | |
g_string_append_c(stack, *src); | |
level ++; | |
nesting[level].quote = 0; | |
nesting[level].terminator = ')'; | |
} | |
break; | |
case '"': | |
case '\'': | |
if (! nesting[level].quote) | |
nesting[level].quote = *src; | |
else if (nesting[level].quote == *src) | |
nesting[level].quote = 0; | |
g_string_append_c(stack, *src); | |
break; | |
case '%': | |
src++; | |
if (quote && nesting[level].quote) /* close the quote */ | |
g_string_append_c(stack, nesting[level].quote); | |
if (*src == 'f' && f) | |
g_string_append(stack, f); | |
else if (*src == 'd' && d) | |
g_string_append(stack, d); | |
else if (*src == 'e' && e) | |
g_string_append(stack, e); | |
else if (*src == 'l') | |
g_string_append_printf(stack, "%d", l); | |
else if (*src == 'p') | |
{ | |
if (p) | |
g_string_append(stack, p); | |
else | |
{ /* fallback to %d */ | |
/*ui_set_statusbar(FALSE, _("failed to substitute %%p, no project active"));*/ | |
if (d) | |
g_string_append(stack, d); | |
} | |
} | |
else | |
{ /* just leave the placeholder */ | |
g_string_append_c(stack, '%'); | |
g_string_append_c(stack, *src); | |
} | |
if (quote && nesting[level].quote) /* re-open quote */ | |
g_string_append_c(stack, nesting[level].quote); | |
break; | |
case '\\': | |
g_string_append_c(stack, *src); | |
src++; | |
/* fallthrough */ | |
default: | |
g_string_append_c(stack, *src); | |
break; | |
} | |
} | |
g_free (f); | |
g_free (d); | |
g_free (e); | |
g_free (p); | |
return g_string_free(stack, FALSE); | |
} | |
#define CONSUME_ARG(c, v) (c--, v++) | |
int main (int argc, char **argv) | |
{ | |
const gchar *f = NULL; | |
const gchar *d = NULL; | |
const gchar *e = NULL; | |
gint l = 0; | |
const gchar *p = NULL; | |
gboolean quote = FALSE; | |
gchar input[1024] = {0}; | |
fprintf(stderr, "USAGE: [-q | -Q] [basename [dirname [basename-without-ext [line [project]]]]]\n\n"); | |
if (argc > 1 && !strcmp(argv[1], "-q")) { | |
quote = TRUE; | |
CONSUME_ARG(argc, argv); | |
} else if (argc > 1 && !strcmp(argv[1], "-Q")) { | |
quote = FALSE; | |
CONSUME_ARG(argc, argv); | |
} | |
if (argc > 1) { | |
f = argv[1]; | |
CONSUME_ARG(argc, argv); | |
} | |
if (argc > 1) { | |
d = argv[1]; | |
CONSUME_ARG(argc, argv); | |
} | |
if (argc > 1) { | |
e = argv[1]; | |
CONSUME_ARG(argc, argv); | |
} | |
if (argc > 1) { | |
l = atoi(argv[1]); | |
CONSUME_ARG(argc, argv); | |
} | |
if (argc > 1) { | |
p = argv[1]; | |
CONSUME_ARG(argc, argv); | |
} | |
while (fgets(input, sizeof input, stdin)) | |
{ | |
gchar *res; | |
size_t len = strlen(input); | |
if (len > 0 && input[len - 1] == '\n') | |
input[len - 1] = 0; | |
res = build_replace_placeholder(f, d, e, l, p, input, quote); | |
fprintf(stdout, "in: %s\nout: %s\n\n", input, res); | |
g_free(res); | |
} | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
foo bar %f | |
hello "%f" | |
some "$(cat "%f")-stuff" | |
some "`cat "%f"`-stuff" | |
some '$(cat "%f")-stuff' | |
some '`cat "%f"`-stuff' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment