Allow git-svnimport to take "" as the trunk directory.
[gitweb.git] / quote.c
diff --git a/quote.c b/quote.c
index dcc23266109ce30e3fd098f3c76799b67b75a332..d88bf7515932bba96c694478c3b51c85549fa92a 100644 (file)
--- a/quote.c
+++ b/quote.c
  *  a!b      ==> a'\!'b    ==> 'a'\!'b'
  */
 #undef EMIT
-#define EMIT(x) ( (++len < n) && (*bp++ = (x)) )
+#define EMIT(x) do { if (++len < n) *bp++ = (x); } while(0)
 
 static inline int need_bs_quote(char c)
 {
        return (c == '\'' || c == '!');
 }
 
-size_t sq_quote_buf(char *dst, size_t n, const char *src)
+static size_t sq_quote_buf(char *dst, size_t n, const char *src)
 {
        char c;
        char *bp = dst;
@@ -45,18 +45,84 @@ size_t sq_quote_buf(char *dst, size_t n, const char *src)
        return len;
 }
 
-char *sq_quote(const char *src)
+void sq_quote_print(FILE *stream, const char *src)
 {
-       char *buf;
-       size_t cnt;
+       char c;
+
+       fputc('\'', stream);
+       while ((c = *src++)) {
+               if (need_bs_quote(c)) {
+                       fputs("'\\", stream);
+                       fputc(c, stream);
+                       fputc('\'', stream);
+               } else {
+                       fputc(c, stream);
+               }
+       }
+       fputc('\'', stream);
+}
+
+char *sq_quote_argv(const char** argv, int count)
+{
+       char *buf, *to;
+       int i;
+       size_t len = 0;
+
+       /* Count argv if needed. */
+       if (count < 0) {
+               for (count = 0; argv[count]; count++)
+                       ; /* just counting */
+       }
+
+       /* Special case: no argv. */
+       if (!count)
+               return xcalloc(1,1);
+
+       /* Get destination buffer length. */
+       for (i = 0; i < count; i++)
+               len += sq_quote_buf(NULL, 0, argv[i]) + 1;
 
-       cnt = sq_quote_buf(NULL, 0, src) + 1;
-       buf = xmalloc(cnt);
-       sq_quote_buf(buf, cnt, src);
+       /* Alloc destination buffer. */
+       to = buf = xmalloc(len + 1);
+
+       /* Copy into destination buffer. */
+       for (i = 0; i < count; ++i) {
+               *to++ = ' ';
+               to += sq_quote_buf(to, len, argv[i]);
+       }
 
        return buf;
 }
 
+/*
+ * Append a string to a string buffer, with or without shell quoting.
+ * Return true if the buffer overflowed.
+ */
+int add_to_string(char **ptrp, int *sizep, const char *str, int quote)
+{
+       char *p = *ptrp;
+       int size = *sizep;
+       int oc;
+       int err = 0;
+
+       if (quote)
+               oc = sq_quote_buf(p, size, str);
+       else {
+               oc = strlen(str);
+               memcpy(p, str, (size <= oc) ? size - 1 : oc);
+       }
+
+       if (size <= oc) {
+               err = 1;
+               oc = size - 1;
+       }
+
+       *ptrp += oc;
+       **ptrp = '\0';
+       *sizep -= oc;
+       return err;
+}
+
 char *sq_dequote(char *arg)
 {
        char *dst = arg;
@@ -122,7 +188,8 @@ static int quote_c_style_counted(const char *name, int namelen,
 #define EMITQ() EMIT('\\')
 
        const char *sp;
-       int ch, count = 0, needquote = 0;
+       unsigned char ch;
+       int count = 0, needquote = 0;
 
        if (!no_dq)
                EMIT('"');
@@ -131,7 +198,7 @@ static int quote_c_style_counted(const char *name, int namelen,
                if (!ch)
                        break;
                if ((ch < ' ') || (ch == '"') || (ch == '\\') ||
-                   (ch == 0177)) {
+                   (quote_path_fully && (ch >= 0177))) {
                        needquote = 1;
                        switch (ch) {
                        case '\a': EMITQ(); ch = 'a'; break;
@@ -271,3 +338,75 @@ void write_name_quoted(const char *prefix, int prefix_len,
        else
                goto no_quote;
 }
+
+/* quoting as a string literal for other languages */
+
+void perl_quote_print(FILE *stream, const char *src)
+{
+       const char sq = '\'';
+       const char bq = '\\';
+       char c;
+
+       fputc(sq, stream);
+       while ((c = *src++)) {
+               if (c == sq || c == bq)
+                       fputc(bq, stream);
+               fputc(c, stream);
+       }
+       fputc(sq, stream);
+}
+
+void python_quote_print(FILE *stream, const char *src)
+{
+       const char sq = '\'';
+       const char bq = '\\';
+       const char nl = '\n';
+       char c;
+
+       fputc(sq, stream);
+       while ((c = *src++)) {
+               if (c == nl) {
+                       fputc(bq, stream);
+                       fputc('n', stream);
+                       continue;
+               }
+               if (c == sq || c == bq)
+                       fputc(bq, stream);
+               fputc(c, stream);
+       }
+       fputc(sq, stream);
+}
+
+void tcl_quote_print(FILE *stream, const char *src)
+{
+       char c;
+
+       fputc('"', stream);
+       while ((c = *src++)) {
+               switch (c) {
+               case '[': case ']':
+               case '{': case '}':
+               case '$': case '\\': case '"':
+                       fputc('\\', stream);
+               default:
+                       fputc(c, stream);
+                       break;
+               case '\f':
+                       fputs("\\f", stream);
+                       break;
+               case '\r':
+                       fputs("\\r", stream);
+                       break;
+               case '\n':
+                       fputs("\\n", stream);
+                       break;
+               case '\t':
+                       fputs("\\t", stream);
+                       break;
+               case '\v':
+                       fputs("\\v", stream);
+                       break;
+               }
+       }
+       fputc('"', stream);
+}