packed_object_info_detail(): check for corrupt packfile.
[gitweb.git] / quote.c
diff --git a/quote.c b/quote.c
index 7df05a9c7c0935170acd84105289fe531da7f7c3..06792d47c3e324ee9893a4e52035f0642f38005f 100644 (file)
--- a/quote.c
+++ b/quote.c
 #undef EMIT
 #define EMIT(x) ( (++len < n) && (*bp++ = (x)) )
 
+static inline int need_bs_quote(char c)
+{
+       return (c == '\'' || c == '!');
+}
+
 size_t sq_quote_buf(char *dst, size_t n, const char *src)
 {
        char c;
@@ -23,7 +28,7 @@ size_t sq_quote_buf(char *dst, size_t n, const char *src)
 
        EMIT('\'');
        while ((c = *src++)) {
-               if (c == '\'' || c == '!') {
+               if (need_bs_quote(c)) {
                        EMIT('\'');
                        EMIT('\\');
                        EMIT(c);
@@ -52,6 +57,40 @@ char *sq_quote(const char *src)
        return buf;
 }
 
+char *sq_dequote(char *arg)
+{
+       char *dst = arg;
+       char *src = arg;
+       char c;
+
+       if (*src != '\'')
+               return NULL;
+       for (;;) {
+               c = *++src;
+               if (!c)
+                       return NULL;
+               if (c != '\'') {
+                       *dst++ = c;
+                       continue;
+               }
+               /* We stepped out of sq */
+               switch (*++src) {
+               case '\0':
+                       *dst = 0;
+                       return arg;
+               case '\\':
+                       c = *++src;
+                       if (need_bs_quote(c) && *++src == '\'') {
+                               *dst++ = c;
+                               continue;
+                       }
+               /* Fallthrough */
+               default:
+                       return NULL;
+               }
+       }
+}
+
 /*
  * C-style name quoting.
  *
@@ -73,7 +112,8 @@ char *sq_quote(const char *src)
  *     but not enclosed in double-quote pair.  Return value is undefined.
  */
 
-int quote_c_style(const char *name, char *outbuf, FILE *outfp, int no_dq)
+static int quote_c_style_counted(const char *name, int namelen,
+                                char *outbuf, FILE *outfp, int no_dq)
 {
 #undef EMIT
 #define EMIT(c) \
@@ -86,10 +126,12 @@ int quote_c_style(const char *name, char *outbuf, FILE *outfp, int no_dq)
 
        if (!no_dq)
                EMIT('"');
-       for (sp = name; (ch = *sp++); ) {
-
-               if ((ch <= ' ') || (ch == '"') ||
-                   (ch == '\\') || (ch == 0177)) {
+       for (sp = name; sp < name + namelen; sp++) {
+               ch = *sp;
+               if (!ch)
+                       break;
+               if ((ch < ' ') || (ch == '"') || (ch == '\\') ||
+                   (ch == 0177)) {
                        needquote = 1;
                        switch (ch) {
                        case '\a': EMITQ(); ch = 'a'; break;
@@ -102,8 +144,6 @@ int quote_c_style(const char *name, char *outbuf, FILE *outfp, int no_dq)
 
                        case '\\': /* fallthru */
                        case '"': EMITQ(); break;
-                       case ' ':
-                               break;
                        default:
                                /* octal */
                                EMITQ();
@@ -123,6 +163,12 @@ int quote_c_style(const char *name, char *outbuf, FILE *outfp, int no_dq)
        return needquote ? count : 0;
 }
 
+int quote_c_style(const char *name, char *outbuf, FILE *outfp, int no_dq)
+{
+       int cnt = strlen(name);
+       return quote_c_style_counted(name, cnt, outbuf, outfp, no_dq);
+}
+
 /*
  * C-style name unquoting.
  *
@@ -188,28 +234,30 @@ char *unquote_c_style(const char *quoted, const char **endp)
        }
 }
 
-void write_name_quoted(const char *prefix, const char *name,
-                      int quote, FILE *out)
+void write_name_quoted(const char *prefix, int prefix_len,
+                      const char *name, int quote, FILE *out)
 {
        int needquote;
 
        if (!quote) {
        no_quote:
-               if (prefix && prefix[0])
-                       fputs(prefix, out);
+               if (prefix_len)
+                       fprintf(out, "%.*s", prefix_len, prefix);
                fputs(name, out);
                return;
        }
 
        needquote = 0;
-       if (prefix && prefix[0])
-               needquote = quote_c_style(prefix, NULL, NULL, 0);
+       if (prefix_len)
+               needquote = quote_c_style_counted(prefix, prefix_len,
+                                                 NULL, NULL, 0);
        if (!needquote)
                needquote = quote_c_style(name, NULL, NULL, 0);
        if (needquote) {
                fputc('"', out);
-               if (prefix && prefix[0])
-                       quote_c_style(prefix, NULL, out, 1);
+               if (prefix_len)
+                       quote_c_style_counted(prefix, prefix_len,
+                                             NULL, out, 1);
                quote_c_style(name, NULL, out, 1);
                fputc('"', out);
        }