{"thread":{"id":"6559","subject":"[PATCH] Teach for-each-ref about a little language called Tcl.","startedAt":"2007-01-27T07:22:58Z","lastAt":"2007-01-27T11:30:56Z","messageCount":2,"participants":["Shawn O. Pearce","Sergey Vlasov"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"32809","messageId":"20070127072258.GA10512@spearce.org","threadId":"6559","inReplyTo":null,"subject":"[PATCH] Teach for-each-ref about a little language called Tcl.","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-01-27T07:22:58Z","receivedAt":"2007-01-27T07:22:58Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Love it or hate it, some people actually still program in Tcl.  Some\nof those programs are meant for interfacing with Git.  Programs such as\ngitk and git-gui.  It may be useful to have Tcl-safe output available\nfrom for-each-ref, just like shell, Perl and Python already enjoy.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n Documentation/git-for-each-ref.txt |    4 ++--\n builtin-for-each-ref.c             |   10 ++++++++++\n quote.c                            |   16 ++++++++++++++++\n quote.h                            |    1 +\n 4 files changed, 29 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt\nindex 06e7ab1..da52eba 100644\n--- a/Documentation/git-for-each-ref.txt\n+++ b/Documentation/git-for-each-ref.txt\n@@ -7,7 +7,7 @@ git-for-each-ref - Output information on each ref\n \n SYNOPSIS\n --------\n-'git-for-each-ref' [--count=<count>]\\* [--shell|--perl|--python] [--sort=<key>]\\* [--format=<format>] [<pattern>]\n+'git-for-each-ref' [--count=<count>]\\* [--shell|--perl|--python|--tcl] [--sort=<key>]\\* [--format=<format>] [<pattern>]\n \n DESCRIPTION\n -----------\n@@ -49,7 +49,7 @@ OPTIONS\n \tusing fnmatch(3).  Refs that do not match the pattern\n \tare not shown.\n \n---shell, --perl, --python::\n+--shell, --perl, --python, --tcl::\n \tIf given, strings that substitute `%(fieldname)`\n \tplaceholders are quoted as string literals suitable for\n \tthe specified host language.  This is meant to produce\ndiff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c\nindex af72a12..9d5f266 100644\n--- a/builtin-for-each-ref.c\n+++ b/builtin-for-each-ref.c\n@@ -12,6 +12,7 @@\n #define QUOTE_SHELL 1\n #define QUOTE_PERL 2\n #define QUOTE_PYTHON 3\n+#define QUOTE_TCL 4\n \n typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type;\n \n@@ -723,6 +724,9 @@ static void print_value(struct refinfo *ref, int atom, int quote_style)\n \tcase QUOTE_PYTHON:\n \t\tpython_quote_print(stdout, v->s);\n \t\tbreak;\n+\tcase QUOTE_TCL:\n+\t\ttcl_quote_print(stdout, v->s);\n+\t\tbreak;\n \t}\n }\n \n@@ -834,6 +838,12 @@ int cmd_for_each_ref(int ac, const char **av, char *prefix)\n \t\t\tquote_style = QUOTE_PYTHON;\n \t\t\tcontinue;\n \t\t}\n+\t\tif (!strcmp(arg, \"--tcl\") ) {\n+\t\t\tif (0 <= quote_style)\n+\t\t\t\tdie(\"more than one quoting style?\");\n+\t\t\tquote_style = QUOTE_TCL;\n+\t\t\tcontinue;\n+\t\t}\n \t\tif (!strncmp(arg, \"--count=\", 8)) {\n \t\t\tif (maxcount)\n \t\t\t\tdie(\"more than one --count?\");\ndiff --git a/quote.c b/quote.c\nindex a418a0f..ab0e971 100644\n--- a/quote.c\n+++ b/quote.c\n@@ -387,3 +387,19 @@ void python_quote_print(FILE *stream, const char *src)\n \t}\n \tfputc(sq, stream);\n }\n+\n+void tcl_quote_print(FILE *stream, const char *src)\n+{\n+\tconst char lb = '{';\n+\tconst char rb = '}';\n+\tconst char bq = '\\\\';\n+\tchar c;\n+\n+\tfputc(lb, stream);\n+\twhile ((c = *src++)) {\n+\t\tif (c == lb || c == rb || c == bq)\n+\t\t\tfputc(bq, stream);\n+\t\tfputc(c, stream);\n+\t}\n+\tfputc(rb, stream);\n+}\ndiff --git a/quote.h b/quote.h\nindex b55e699..bdc3610 100644\n--- a/quote.h\n+++ b/quote.h\n@@ -55,5 +55,6 @@ extern void write_name_quoted(const char *prefix, int prefix_len,\n /* quoting as a string literal for other languages */\n extern void perl_quote_print(FILE *stream, const char *src);\n extern void python_quote_print(FILE *stream, const char *src);\n+extern void tcl_quote_print(FILE *stream, const char *src);\n \n #endif\n-- \n1.5.0.rc2.g8a816\n"},{"id":"32828","messageId":"20070127143056.d19e80da.vsu@altlinux.ru","threadId":"6559","inReplyTo":"20070127072258.GA10512@spearce.org","subject":"Re: [PATCH] Teach for-each-ref about a little language called Tcl.","fromName":"Sergey Vlasov","fromEmail":"vsu@altlinux.ru","sentAt":"2007-01-27T11:30:56Z","receivedAt":"2007-01-27T11:30:56Z","isPatch":true,"sender":{"key":"vsu@altlinux.ru","avatar":"https://avatars.githubusercontent.com/u/616082?v=4"},"body":"On Sat, 27 Jan 2007 02:22:58 -0500 Shawn O. Pearce wrote:\n\n> Love it or hate it, some people actually still program in Tcl.  Some\n> of those programs are meant for interfacing with Git.  Programs such as\n> gitk and git-gui.  It may be useful to have Tcl-safe output available\n> from for-each-ref, just like shell, Perl and Python already enjoy.\n[...]\n> +void tcl_quote_print(FILE *stream, const char *src)\n> +{\n> +\tconst char lb = '{';\n> +\tconst char rb = '}';\n> +\tconst char bq = '\\\\';\n> +\tchar c;\n> +\n> +\tfputc(lb, stream);\n> +\twhile ((c = *src++)) {\n> +\t\tif (c == lb || c == rb || c == bq)\n> +\t\t\tfputc(bq, stream);\n> +\t\tfputc(c, stream);\n> +\t}\n> +\tfputc(rb, stream);\n> +}\n\nNo, this is broken - backslashes cannot be used to quote special\ncharacters in braces.\n\n      If  the  first character of a word is an open brace (``{'') then\n      the word is terminated by  the  matching  close  brace  (``}'').\n      Braces  nest  within  the  word:  for each additional open brace\n      there must be an additional close brace  (however,  if  an  open\n      brace  or close brace within the word is quoted with a backslash\n      then it is not counted in locating the  matching  close  brace).\n      No  substitutions  are  performed  on the characters between the\n      braces  except  for  backslash-newline  substitutions  described\n      below,  nor  do  semi-colons, newlines, close brackets, or white\n      space receive any special interpretation.  The word will consist\n      of  exactly the characters between the outer braces, not includ-\n      ing the braces themselves.\n\nThe problem is that using '\\{' will protect from nonmatching braces,\nbut the backslash will stay in the resulting string - it will not be\nremoved.  Similarly for '\\}' and '\\\\'.\n\nTcl itself checks whether using braces is safe (it could be safe if\nthe text does not have nonmatching braces and does not have an odd\nnumber of backslash characters at end of line), and uses just\nbackslashes if braces cannot be used.  See tclUtil.c,\nTcl_ScanCountedElement() and Tcl_ConvertCountedElement().\nThis code adds a backslash before ']', '[', '$', ';', ' ', '\\\\', '\"',\n'{', '}', and also converts special characters '\\f', '\\n', '\\r', '\\t',\n'\\v' to C-style escape sequences.\n\nUntested code (output will not look very nice, but it is not intended\nfor human consumption anyway):\n\nvoid tcl_quote_print(FILE *stream, const char *src)\n{\n\tchar c;\n\n\twhile ((c = *src++)) {\n\t\tswitch (c) {\n\t\tcase ']':\n\t\tcase '[':\n\t\tcase '$':\n\t\tcase ';':\n\t\tcase ' ':\n\t\tcase '\\\\':\n\t\tcase '\"':\n\t\tcase '{':\n\t\tcase '}':\n\t\t\tfputc('\\\\', stream);\n\t\tdefault:\n\t\t\tfputc(c, stream);\n\t\t\tbreak;\n\n\t\tcase '\\f':\n\t\t\tfputs(\"\\\\f\", stream);\n\t\t\tbreak;\n\t\tcase '\\n':\n\t\t\tfputs(\"\\\\n\", stream);\n\t\t\tbreak;\n\t\tcase '\\r':\n\t\t\tfputs(\"\\\\r\", stream);\n\t\t\tbreak;\n\t\tcase '\\t':\n\t\t\tfputs(\"\\\\t\", stream);\n\t\t\tbreak;\n\t\tcase '\\v':\n\t\t\tfputs(\"\\\\v\", stream);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n"}]}