comparison src/dmargs.c @ 2400:01c6a5261962

Sync commandline argument help printing/handling changes from th-libs.
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 12 Jan 2020 19:25:52 +0200
parents c801995cbb13
children 263093248f26
comparison
equal deleted inserted replaced
2399:5d391c31ebc9 2400:01c6a5261962
173 173
174 return optionsOK; 174 return optionsOK;
175 } 175 }
176 176
177 177
178 static void dmPad(FILE *outFile, int count) 178 void dmPrintPad(FILE *fh, int count, const char och)
179 { 179 {
180 while (count--) 180 while (count--)
181 fputc(' ', outFile); 181 fputc(och, fh);
182 } 182 }
183 183
184 184
185 static void dmPrintWrap(FILE *fh, const char *str, int spad, int rpad, int width) 185 /**
186 * Print given string indented in such a way that it is automatically
187 * line-wrapped as necessary, taking hard linefeeds into account as well.
188 * @param fh stdio file handle to output to
189 * @param str string to output
190 * @param spad starting pad/indent of the first line
191 * @param rpad how much to pad the other lines
192 * @param width total line width to wrap at
193 */
194 void dmPrintWrap(FILE *fh, const char *str,
195 const int spad, int const rpad, const int width)
186 { 196 {
187 size_t pos = 0; 197 size_t pos = 0;
188 BOOL first = TRUE; 198 BOOL first = TRUE;
189 199
190 while (str[pos]) 200 while (str[pos])
191 { 201 {
192 // Pre-pad line 202 // Pre-pad line
193 int linelen = first ? spad : rpad; 203 int linelen = first ? spad : rpad;
194 dmPad(fh, first ? 0 : rpad); 204 dmPrintPad(fh, first ? 0 : rpad, ' ');
195 first = FALSE; 205 first = FALSE;
196 206
197 // Skip whitespace at line start 207 // Skip whitespace at line start
198 while (isspace(str[pos]) || str[pos] == '\n') pos++; 208 while (isspace(str[pos]) || str[pos] == '\n')
209 pos++;
199 210
200 // Handle each word 211 // Handle each word
201 while (str[pos] && str[pos] != '\n') 212 while (str[pos] && str[pos] != '\n')
202 { 213 {
203 size_t next; 214 size_t next;
204 int wlen; 215 int wlen;
205 for (wlen = 0, next = pos; str[next] && !isspace(str[next]) && str[next] != '\n'; next++, wlen++); 216
206 // fprintf(stdout, "X '%c', %d .. linelen=%d/%d, wlen=%d\n", str[pos], pos, linelen, width, wlen); 217 // Find word length and next break
207 if (linelen + wlen < width) 218 for (wlen = 0, next = pos;
208 { 219 str[next] && !isspace(str[next]) &&
209 for (;pos < next; pos++, linelen++) 220 str[next] != '\n';
210 fputc(str[pos], fh); 221 next++, wlen++);
211 222
212 if (str[next] == '\n' || str[next] == 0) 223 // Check if we have too much of text?
213 { 224 if (linelen + wlen >= width)
214 fprintf(fh, "\n"); 225 break;
215 break; 226
216 } 227 // Print what we have
217 else 228 for (;pos < next; pos++, linelen++)
218 { 229 fputc(str[pos], fh);
219 fputc(str[pos], fh); 230
220 pos++; 231 // Check if we are at end of input or hard linefeed
221 linelen++; 232 if (str[next] == '\n' || str[next] == 0)
222 } 233 break;
223 }
224 else 234 else
225 { 235 {
226 fprintf(fh, "\n"); 236 fputc(str[pos], fh);
227 break; 237 pos++;
228 } 238 linelen++;
229 } 239 }
240 }
241 fprintf(fh, "\n");
242 }
243 }
244
245
246 static inline const char *dmArgsGetOptArg(const DMOptArg *opt)
247 {
248 #ifdef DM_USE_OPT_ARG
249 return opt->o_arg != NULL ? opt->o_arg : "ARG";
250 #else
251 (void) opt;
252 return "ARG";
253 #endif
254 }
255
256
257 static void dmArgsPrintHelpPrintItem(FILE *fh, const DMOptArg *opt, int *lineWidth, const int maxLineWidth, const BOOL doPrint)
258 {
259 const char *arg = dmArgsGetOptArg(opt);
260 char fmtBuf[32];
261 int padWidth;
262 BOOL hasLongOpt = opt->o_long != NULL;
263
264 if (opt->o_short != 0)
265 {
266 if (!hasLongOpt && (opt->flags & OPT_ARGREQ))
267 {
268 snprintf(fmtBuf, sizeof(fmtBuf), " -%c <%s>",
269 opt->o_short, arg);
270 }
271 else
272 {
273 snprintf(fmtBuf, sizeof(fmtBuf), " -%c,",
274 opt->o_short);
275 }
276
277 *lineWidth = strlen(fmtBuf);
278 if (doPrint)
279 padWidth = hasLongOpt ? 2 : maxLineWidth - *lineWidth;
280 else
281 padWidth = 2;
282 }
283 else
284 {
285 fmtBuf[0] = 0;
286 *lineWidth = 0;
287 padWidth = 4 + 2;
288 }
289
290 if (doPrint)
291 {
292 fputs(fmtBuf, fh);
293 dmPrintPad(fh, padWidth, ' ');
294 }
295 *lineWidth += padWidth;
296
297 if (hasLongOpt)
298 {
299 if (opt->flags & OPT_ARGREQ)
300 {
301 snprintf(fmtBuf, sizeof(fmtBuf), "--%s=<%s>",
302 opt->o_long, arg);
303 }
304 else
305 {
306 snprintf(fmtBuf, sizeof(fmtBuf), "--%s",
307 opt->o_long);
308 }
309
310 *lineWidth += strlen(fmtBuf);
311 }
312 else
313 fmtBuf[0] = 0;
314
315 if (doPrint)
316 {
317 padWidth = hasLongOpt ? maxLineWidth - *lineWidth : 0;
318 *lineWidth += padWidth;
319
320 fputs(fmtBuf, fh);
321 dmPrintPad(fh, padWidth, ' ');
322 dmPrintWrap(fh, opt->desc, *lineWidth, *lineWidth, 79);
230 } 323 }
231 } 324 }
232 325
233 326
234 /** 327 /**
236 * @param fh stdio file handle to output to 329 * @param fh stdio file handle to output to
237 * @param opts options list array 330 * @param opts options list array
238 * @param nopts number of elements in options list array 331 * @param nopts number of elements in options list array
239 * @param flags flags (currently unused) 332 * @param flags flags (currently unused)
240 */ 333 */
241 void dmArgsPrintHelp(FILE *fh, 334 void dmArgsPrintHelp(FILE *fh, const DMOptArg *opts,
242 const DMOptArg *opts, const int nopts, 335 const int nopts, const int flags)
243 const int flags) 336 {
244 { 337 int index, maxLineWidth;
245 int index; 338
246 (void) flags; 339 (void) flags;
247 340
248 // Print out option list 341 // Determine width of the options and arguments
342 maxLineWidth = 0;
249 for (index = 0; index < nopts; index++) 343 for (index = 0; index < nopts; index++)
250 { 344 {
251 const DMOptArg *opt = &opts[index]; 345 int lineWidth = 0;
252 char tmpStr[128]; 346 dmArgsPrintHelpPrintItem(NULL, &opts[index], &lineWidth, 0, FALSE);
253 347 if (lineWidth > maxLineWidth)
254 // Print short option 348 maxLineWidth = lineWidth;
255 if (opt->o_short != 0) 349 }
256 { 350
257 snprintf(tmpStr, sizeof(tmpStr), 351 maxLineWidth += 2;
258 "-%c,", opt->o_short); 352
259 } 353 // Print out the formatted option list
260 else 354 for (index = 0; index < nopts; index++)
261 tmpStr[0] = 0; 355 {
262 356 int lineWidth;
263 fprintf(fh, " %-5s", tmpStr); 357 dmArgsPrintHelpPrintItem(fh, &opts[index], &lineWidth, maxLineWidth, TRUE);
264 358 }
265 // Print long option 359 }
266 if (opt->o_long != NULL)
267 {
268 snprintf(tmpStr, sizeof(tmpStr), "--%s%s",
269 opt->o_long,
270 (opt->flags & OPT_ARGREQ) ? "=ARG" : "");
271 }
272 else
273 tmpStr[0] = 0;
274
275 fprintf(fh, "%-18s", tmpStr);
276
277 dmPrintWrap(fh, opt->desc, 24, 24, 79);
278 }
279 }