Append one argv element to the command line using the Microsoft C runtime * quoting rules (see MS "Parsing C Command-Line Arguments"). CreateProcess takes * a SINGLE string that the child re-parses back into argv, so any element with a * space, tab or double-quote must be wrapped in quotes and its embedded quotes / * preceding backslashes escaped. Without this a JSON argument like * {"repo_pa
| 159 | * non-zero at JSON-arg parse, misattributed to the last-marked file). POSIX is |
| 160 | * unaffected: cbm_run_posix passes the argv array straight to execv. */ |
| 161 | static size_t cbm_cmdline_append_arg(char *buf, size_t cap, size_t pos, const char *arg, bool first, |
| 162 | bool *ovf) { |
| 163 | if (!first) { |
| 164 | pos = cbm_cmdline_put(buf, cap, pos, ' ', ovf); |
| 165 | } |
| 166 | pos = cbm_cmdline_put(buf, cap, pos, '"', ovf); |
| 167 | for (const char *p = arg; *p;) { |
| 168 | size_t nbs = 0; |
| 169 | while (*p == '\\') { |
| 170 | nbs++; |
| 171 | p++; |
| 172 | } |
| 173 | if (*p == '\0') { |
| 174 | /* Trailing backslashes precede the closing quote: double them so the |
| 175 | * quote stays a delimiter, not an escaped literal. */ |
| 176 | for (size_t k = 0; k < nbs * 2; k++) { |
| 177 | pos = cbm_cmdline_put(buf, cap, pos, '\\', ovf); |
| 178 | } |
| 179 | break; |
| 180 | } |
| 181 | if (*p == '"') { |
| 182 | /* N backslashes then a quote -> 2N+1 backslashes then an escaped quote. */ |
| 183 | for (size_t k = 0; k < nbs * 2 + 1; k++) { |
| 184 | pos = cbm_cmdline_put(buf, cap, pos, '\\', ovf); |
| 185 | } |
| 186 | pos = cbm_cmdline_put(buf, cap, pos, '"', ovf); |
| 187 | p++; |
| 188 | } else { |
| 189 | for (size_t k = 0; k < nbs; k++) { |
| 190 | pos = cbm_cmdline_put(buf, cap, pos, '\\', ovf); |
| 191 | } |
| 192 | pos = cbm_cmdline_put(buf, cap, pos, *p, ovf); |
| 193 | p++; |
| 194 | } |
| 195 | } |
| 196 | pos = cbm_cmdline_put(buf, cap, pos, '"', ovf); |
| 197 | return pos; |
| 198 | } |
| 199 | |
| 200 | /* Build a full Windows CreateProcess command line from a NULL-terminated argv, |
| 201 | * applying the MS C runtime quoting rules so the child re-parses byte-identical |
no test coverage detected