Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/polly/lib/External/isl/isl_arg.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2008-2009 Katholieke Universiteit Leuven
3
 *
4
 * Use of this software is governed by the MIT license
5
 *
6
 * Written by Sven Verdoolaege, K.U.Leuven, Departement
7
 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
8
 */
9
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <string.h>
13
14
#include <isl/arg.h>
15
#include <isl/ctx.h>
16
#include <isl_config.h>
17
18
static struct isl_arg help_arg[] = {
19
ISL_ARG_PHANTOM_BOOL('h', "help", NULL, "print this help, then exit")
20
};
21
22
static void set_default_choice(struct isl_arg *arg, void *opt)
23
11.6k
{
24
11.6k
  if (arg->offset == (size_t) -1)
25
1.29k
    return;
26
10.3k
  *(unsigned *)(((char *)opt) + arg->offset) = arg->u.choice.default_value;
27
10.3k
}
28
29
static void set_default_flags(struct isl_arg *arg, void *opt)
30
1.29k
{
31
1.29k
  *(unsigned *)(((char *)opt) + arg->offset) = arg->u.flags.default_value;
32
1.29k
}
33
34
static void set_default_bool(struct isl_arg *arg, void *opt)
35
36.1k
{
36
36.1k
  if (arg->offset == (size_t) -1)
37
0
    return;
38
36.1k
  *(unsigned *)(((char *)opt) + arg->offset) = arg->u.b.default_value;
39
36.1k
}
40
41
static void set_default_child(struct isl_arg *arg, void *opt)
42
0
{
43
0
  void *child;
44
0
45
0
  if (arg->offset == (size_t) -1)
46
0
    child = opt;
47
0
  else {
48
0
    child = calloc(1, arg->u.child.child->options_size);
49
0
    *(void **)(((char *)opt) + arg->offset) = child;
50
0
  }
51
0
52
0
  if (child)
53
0
    isl_args_set_defaults(arg->u.child.child, child);
54
0
}
55
56
static void set_default_user(struct isl_arg *arg, void *opt)
57
0
{
58
0
  arg->u.user.init(((char *)opt) + arg->offset);
59
0
}
60
61
static void set_default_int(struct isl_arg *arg, void *opt)
62
2.58k
{
63
2.58k
  *(int *)(((char *)opt) + arg->offset) = arg->u.i.default_value;
64
2.58k
}
65
66
static void set_default_long(struct isl_arg *arg, void *opt)
67
0
{
68
0
  *(long *)(((char *)opt) + arg->offset) = arg->u.l.default_value;
69
0
}
70
71
static void set_default_ulong(struct isl_arg *arg, void *opt)
72
1.29k
{
73
1.29k
  *(unsigned long *)(((char *)opt) + arg->offset) = arg->u.ul.default_value;
74
1.29k
}
75
76
static void set_default_str(struct isl_arg *arg, void *opt)
77
1.29k
{
78
1.29k
  const char *str = NULL;
79
1.29k
  if (arg->u.str.default_value)
80
1.29k
    str = strdup(arg->u.str.default_value);
81
1.29k
  *(const char **)(((char *)opt) + arg->offset) = str;
82
1.29k
}
83
84
static void set_default_str_list(struct isl_arg *arg, void *opt)
85
0
{
86
0
  *(const char ***)(((char *) opt) + arg->offset) = NULL;
87
0
  *(int *)(((char *) opt) + arg->u.str_list.offset_n) = 0;
88
0
}
89
90
void isl_args_set_defaults(struct isl_args *args, void *opt)
91
1.29k
{
92
1.29k
  int i;
93
1.29k
94
56.8k
  for (i = 0; args->args[i].type != isl_arg_end; 
++i55.5k
) {
95
55.5k
    switch (args->args[i].type) {
96
55.5k
    case isl_arg_choice:
97
11.6k
      set_default_choice(&args->args[i], opt);
98
11.6k
      break;
99
55.5k
    case isl_arg_flags:
100
1.29k
      set_default_flags(&args->args[i], opt);
101
1.29k
      break;
102
55.5k
    case isl_arg_bool:
103
36.1k
      set_default_bool(&args->args[i], opt);
104
36.1k
      break;
105
55.5k
    case isl_arg_child:
106
0
      set_default_child(&args->args[i], opt);
107
0
      break;
108
55.5k
    case isl_arg_user:
109
0
      set_default_user(&args->args[i], opt);
110
0
      break;
111
55.5k
    case isl_arg_int:
112
2.58k
      set_default_int(&args->args[i], opt);
113
2.58k
      break;
114
55.5k
    case isl_arg_long:
115
0
      set_default_long(&args->args[i], opt);
116
0
      break;
117
55.5k
    case isl_arg_ulong:
118
1.29k
      set_default_ulong(&args->args[i], opt);
119
1.29k
      break;
120
55.5k
    case isl_arg_arg:
121
1.29k
    case isl_arg_str:
122
1.29k
      set_default_str(&args->args[i], opt);
123
1.29k
      break;
124
1.29k
    case isl_arg_str_list:
125
0
      set_default_str_list(&args->args[i], opt);
126
0
      break;
127
1.29k
    case isl_arg_alias:
128
1.29k
    case isl_arg_footer:
129
1.29k
    case isl_arg_version:
130
1.29k
    case isl_arg_end:
131
1.29k
      break;
132
55.5k
    }
133
55.5k
  }
134
1.29k
}
135
136
static void free_args(struct isl_arg *arg, void *opt);
137
138
static void free_child(struct isl_arg *arg, void *opt)
139
0
{
140
0
  if (arg->offset == (size_t) -1)
141
0
    free_args(arg->u.child.child->args, opt);
142
0
  else
143
0
    isl_args_free(arg->u.child.child,
144
0
          *(void **)(((char *)opt) + arg->offset));
145
0
}
146
147
static void free_str_list(struct isl_arg *arg, void *opt)
148
0
{
149
0
  int i;
150
0
  int n = *(int *)(((char *) opt) + arg->u.str_list.offset_n);
151
0
  char **list = *(char ***)(((char *) opt) + arg->offset);
152
0
153
0
  for (i = 0; i < n; ++i)
154
0
    free(list[i]);
155
0
  free(list);
156
0
}
157
158
static void free_user(struct isl_arg *arg, void *opt)
159
0
{
160
0
  if (arg->u.user.clear)
161
0
    arg->u.user.clear(((char *)opt) + arg->offset);
162
0
}
163
164
static void free_args(struct isl_arg *arg, void *opt)
165
1.26k
{
166
1.26k
  int i;
167
1.26k
168
55.8k
  for (i = 0; arg[i].type != isl_arg_end; 
++i54.5k
) {
169
54.5k
    switch (arg[i].type) {
170
54.5k
    case isl_arg_child:
171
0
      free_child(&arg[i], opt);
172
0
      break;
173
54.5k
    case isl_arg_arg:
174
1.26k
    case isl_arg_str:
175
1.26k
      free(*(char **)(((char *)opt) + arg[i].offset));
176
1.26k
      break;
177
1.26k
    case isl_arg_str_list:
178
0
      free_str_list(&arg[i], opt);
179
0
      break;
180
1.26k
    case isl_arg_user:
181
0
      free_user(&arg[i], opt);
182
0
      break;
183
53.2k
    case isl_arg_alias:
184
53.2k
    case isl_arg_bool:
185
53.2k
    case isl_arg_choice:
186
53.2k
    case isl_arg_flags:
187
53.2k
    case isl_arg_int:
188
53.2k
    case isl_arg_long:
189
53.2k
    case isl_arg_ulong:
190
53.2k
    case isl_arg_version:
191
53.2k
    case isl_arg_footer:
192
53.2k
    case isl_arg_end:
193
53.2k
      break;
194
54.5k
    }
195
54.5k
  }
196
1.26k
}
197
198
void isl_args_free(struct isl_args *args, void *opt)
199
1.26k
{
200
1.26k
  if (!opt)
201
0
    return;
202
1.26k
203
1.26k
  free_args(args->args, opt);
204
1.26k
205
1.26k
  free(opt);
206
1.26k
}
207
208
/* Data structure for collecting the prefixes of ancestor nodes.
209
 *
210
 * n is the number of prefixes.
211
 * prefix[i] for i < n is a prefix of an ancestor.
212
 * len[i] for i < n is the length of prefix[i].
213
 */
214
struct isl_prefixes {
215
  int n;
216
  const char *prefix[10];
217
  size_t len[10];
218
};
219
220
/* Add "prefix" to the list of prefixes and return the updated
221
 * number of prefixes.
222
 */
223
static int add_prefix(struct isl_prefixes *prefixes, const char *prefix)
224
0
{
225
0
  int n = prefixes->n;
226
0
227
0
  if (!prefix)
228
0
    return n;
229
0
230
0
  if (prefixes->n >= 10) {
231
0
    fprintf(stderr, "too many prefixes\n");
232
0
    exit(EXIT_FAILURE);
233
0
  }
234
0
  prefixes->len[prefixes->n] = strlen(prefix);
235
0
  prefixes->prefix[prefixes->n] = prefix;
236
0
  prefixes->n++;
237
0
238
0
  return n;
239
0
}
240
241
/* Drop all prefixes starting at "first".
242
 */
243
static void drop_prefix(struct isl_prefixes *prefixes, int first)
244
0
{
245
0
  prefixes->n = first;
246
0
}
247
248
/* Print the prefixes in "prefixes".
249
 */
250
static int print_prefixes(struct isl_prefixes *prefixes)
251
0
{
252
0
  int i;
253
0
  int len = 0;
254
0
255
0
  if (!prefixes)
256
0
    return 0;
257
0
258
0
  for (i = 0; i < prefixes->n; ++i) {
259
0
    printf("%s-", prefixes->prefix[i]);
260
0
    len += strlen(prefixes->prefix[i]) + 1;
261
0
  }
262
0
263
0
  return len;
264
0
}
265
266
/* Check if "name" starts with one or more of the prefixes in "prefixes",
267
 * starting at *first.  If so, advance the pointer beyond the prefixes
268
 * and return the updated pointer.  Additionally, update *first to
269
 * the index after the last prefix found.
270
 */
271
static const char *skip_prefixes(const char *name,
272
  struct isl_prefixes *prefixes, int *first)
273
0
{
274
0
  int i;
275
0
276
0
  for (i = first ? *first : 0; i < prefixes->n; ++i) {
277
0
    size_t len = prefixes->len[i];
278
0
    const char *prefix = prefixes->prefix[i];
279
0
    if (strncmp(name, prefix, len) == 0 && name[len] == '-') {
280
0
      name += len + 1;
281
0
      if (first)
282
0
        *first = i + 1;
283
0
    }
284
0
  }
285
0
286
0
  return name;
287
0
}
288
289
static int print_arg_help(struct isl_arg *decl, struct isl_prefixes *prefixes,
290
  int no)
291
0
{
292
0
  int len = 0;
293
0
294
0
  if (!decl->long_name) {
295
0
    printf("  -%c", decl->short_name);
296
0
    return 4;
297
0
  }
298
0
299
0
  if (decl->short_name) {
300
0
    printf("  -%c, --", decl->short_name);
301
0
    len += 8;
302
0
  } else if (decl->flags & ISL_ARG_SINGLE_DASH) {
303
0
    printf("  -");
304
0
    len += 3;
305
0
  } else {
306
0
    printf("      --");
307
0
    len += 8;
308
0
  }
309
0
310
0
  if (no) {
311
0
    printf("no-");
312
0
    len += 3;
313
0
  }
314
0
  len += print_prefixes(prefixes);
315
0
  printf("%s", decl->long_name);
316
0
  len += strlen(decl->long_name);
317
0
318
0
  while ((++decl)->type == isl_arg_alias) {
319
0
    printf(", --");
320
0
    len += 4;
321
0
    if (no) {
322
0
      printf("no-");
323
0
      len += 3;
324
0
    }
325
0
    printf("%s", decl->long_name);
326
0
    len += strlen(decl->long_name);
327
0
  }
328
0
329
0
  return len;
330
0
}
331
332
const void *isl_memrchr(const void *s, int c, size_t n)
333
0
{
334
0
  const char *p = s;
335
0
  while (n-- > 0)
336
0
    if (p[n] == c)
337
0
      return p + n;
338
0
  return NULL;
339
0
}
340
341
static int wrap_msg(const char *s, int indent, int pos)
342
0
{
343
0
  int len;
344
0
  int wrap_len = 75 - indent;
345
0
346
0
  if (pos + 1 >= indent)
347
0
    printf("\n%*s", indent, "");
348
0
  else
349
0
    printf("%*s", indent - pos, "");
350
0
351
0
  len = strlen(s);
352
0
  while (len > wrap_len) {
353
0
    const char *space = isl_memrchr(s, ' ', wrap_len);
354
0
    int l;
355
0
356
0
    if (!space)
357
0
      space = strchr(s + wrap_len, ' ');
358
0
    if (!space)
359
0
      break;
360
0
    l = space - s;
361
0
    printf("%.*s", l, s);
362
0
    s = space + 1;
363
0
    len -= l + 1;
364
0
    printf("\n%*s", indent, "");
365
0
  }
366
0
367
0
  printf("%s", s);
368
0
  return len;
369
0
}
370
371
static int print_help_msg(struct isl_arg *decl, int pos)
372
0
{
373
0
  if (!decl->help_msg)
374
0
    return pos;
375
0
376
0
  return wrap_msg(decl->help_msg, 30, pos);
377
0
}
378
379
static void print_default(struct isl_arg *decl, const char *def, int pos)
380
0
{
381
0
  const char *default_prefix = "[default: ";
382
0
  const char *default_suffix = "]";
383
0
  int len;
384
0
385
0
  len = strlen(default_prefix) + strlen(def) + strlen(default_suffix);
386
0
387
0
  if (!decl->help_msg) {
388
0
    if (pos >= 29)
389
0
      printf("\n%30s", "");
390
0
    else
391
0
      printf("%*s", 30 - pos, "");
392
0
  } else {
393
0
    if (pos + len >= 48)
394
0
      printf("\n%30s", "");
395
0
    else
396
0
      printf(" ");
397
0
  }
398
0
  printf("%s%s%s", default_prefix, def, default_suffix);
399
0
}
400
401
static void print_default_choice(struct isl_arg *decl, void *opt, int pos)
402
0
{
403
0
  int i;
404
0
  const char *s = "none";
405
0
  unsigned *p;
406
0
407
0
  p = (unsigned *)(((char *) opt) + decl->offset);
408
0
  for (i = 0; decl->u.choice.choice[i].name; ++i)
409
0
    if (decl->u.choice.choice[i].value == *p) {
410
0
      s = decl->u.choice.choice[i].name;
411
0
      break;
412
0
    }
413
0
414
0
  print_default(decl, s, pos);
415
0
}
416
417
static void print_choice_help(struct isl_arg *decl,
418
  struct isl_prefixes *prefixes, void *opt)
419
0
{
420
0
  int i;
421
0
  int pos;
422
0
423
0
  pos = print_arg_help(decl, prefixes, 0);
424
0
  printf("=");
425
0
  pos++;
426
0
427
0
  for (i = 0; decl->u.choice.choice[i].name; ++i) {
428
0
    if (i) {
429
0
      printf("|");
430
0
      pos++;
431
0
    }
432
0
    printf("%s", decl->u.choice.choice[i].name);
433
0
    pos += strlen(decl->u.choice.choice[i].name);
434
0
  }
435
0
436
0
  pos = print_help_msg(decl, pos);
437
0
  print_default_choice(decl, opt, pos);
438
0
439
0
  printf("\n");
440
0
}
441
442
static void print_default_flags(struct isl_arg *decl, void *opt, int pos)
443
0
{
444
0
  int i, first;
445
0
  const char *default_prefix = "[default: ";
446
0
  const char *default_suffix = "]";
447
0
  int len = strlen(default_prefix) + strlen(default_suffix);
448
0
  unsigned *p;
449
0
450
0
  p = (unsigned *)(((char *) opt) + decl->offset);
451
0
  for (i = 0; decl->u.flags.flags[i].name; ++i)
452
0
    if ((*p & decl->u.flags.flags[i].mask) ==
453
0
         decl->u.flags.flags[i].value)
454
0
      len += strlen(decl->u.flags.flags[i].name);
455
0
456
0
  if (!decl->help_msg) {
457
0
    if (pos >= 29)
458
0
      printf("\n%30s", "");
459
0
    else
460
0
      printf("%*s", 30 - pos, "");
461
0
  } else {
462
0
    if (pos + len >= 48)
463
0
      printf("\n%30s", "");
464
0
    else
465
0
      printf(" ");
466
0
  }
467
0
  printf("%s", default_prefix);
468
0
469
0
  for (first = 1, i = 0; decl->u.flags.flags[i].name; ++i)
470
0
    if ((*p & decl->u.flags.flags[i].mask) ==
471
0
         decl->u.flags.flags[i].value) {
472
0
      if (!first)
473
0
        printf(",");
474
0
      printf("%s", decl->u.flags.flags[i].name);
475
0
      first = 0;
476
0
    }
477
0
478
0
  printf("%s", default_suffix);
479
0
}
480
481
static void print_flags_help(struct isl_arg *decl,
482
  struct isl_prefixes *prefixes, void *opt)
483
0
{
484
0
  int i, j;
485
0
  int pos;
486
0
487
0
  pos = print_arg_help(decl, prefixes, 0);
488
0
  printf("=");
489
0
  pos++;
490
0
491
0
  for (i = 0; decl->u.flags.flags[i].name; ++i) {
492
0
    if (i) {
493
0
      printf(",");
494
0
      pos++;
495
0
    }
496
0
    for (j = i;
497
0
         decl->u.flags.flags[j].mask == decl->u.flags.flags[i].mask;
498
0
         ++j) {
499
0
      if (j != i) {
500
0
        printf("|");
501
0
        pos++;
502
0
      }
503
0
      printf("%s", decl->u.flags.flags[j].name);
504
0
      pos += strlen(decl->u.flags.flags[j].name);
505
0
    }
506
0
    i = j - 1;
507
0
  }
508
0
509
0
  pos = print_help_msg(decl, pos);
510
0
  print_default_flags(decl, opt, pos);
511
0
512
0
  printf("\n");
513
0
}
514
515
static void print_bool_help(struct isl_arg *decl,
516
  struct isl_prefixes *prefixes, void *opt)
517
0
{
518
0
  int pos;
519
0
  unsigned *p = opt ? (unsigned *)(((char *) opt) + decl->offset) : NULL;
520
0
  int no = p ? *p == 1 : 0;
521
0
  pos = print_arg_help(decl, prefixes, no);
522
0
  pos = print_help_msg(decl, pos);
523
0
  if (decl->offset != (size_t) -1)
524
0
    print_default(decl, no ? "yes" : "no", pos);
525
0
  printf("\n");
526
0
}
527
528
static int print_argument_name(struct isl_arg *decl, const char *name, int pos)
529
0
{
530
0
  printf("%c<%s>", decl->long_name ? '=' : ' ', name);
531
0
  return pos + 3 + strlen(name);
532
0
}
533
534
static void print_int_help(struct isl_arg *decl,
535
  struct isl_prefixes *prefixes, void *opt)
536
0
{
537
0
  int pos;
538
0
  char val[20];
539
0
  int *p = (int *)(((char *) opt) + decl->offset);
540
0
  pos = print_arg_help(decl, prefixes, 0);
541
0
  pos = print_argument_name(decl, decl->argument_name, pos);
542
0
  pos = print_help_msg(decl, pos);
543
0
  snprintf(val, sizeof(val), "%d", *p);
544
0
  print_default(decl, val, pos);
545
0
  printf("\n");
546
0
}
547
548
static void print_long_help(struct isl_arg *decl,
549
  struct isl_prefixes *prefixes, void *opt)
550
0
{
551
0
  int pos;
552
0
  long *p = (long *)(((char *) opt) + decl->offset);
553
0
  pos = print_arg_help(decl, prefixes, 0);
554
0
  if (*p != decl->u.l.default_selected) {
555
0
    printf("[");
556
0
    pos++;
557
0
  }
558
0
  printf("=long");
559
0
  pos += 5;
560
0
  if (*p != decl->u.l.default_selected) {
561
0
    printf("]");
562
0
    pos++;
563
0
  }
564
0
  print_help_msg(decl, pos);
565
0
  printf("\n");
566
0
}
567
568
static void print_ulong_help(struct isl_arg *decl,
569
  struct isl_prefixes *prefixes)
570
0
{
571
0
  int pos;
572
0
  pos = print_arg_help(decl, prefixes, 0);
573
0
  printf("=ulong");
574
0
  pos += 6;
575
0
  print_help_msg(decl, pos);
576
0
  printf("\n");
577
0
}
578
579
static void print_str_help(struct isl_arg *decl,
580
  struct isl_prefixes *prefixes, void *opt)
581
0
{
582
0
  int pos;
583
0
  const char *a = decl->argument_name ? decl->argument_name : "string";
584
0
  const char **p = (const char **)(((char *) opt) + decl->offset);
585
0
  pos = print_arg_help(decl, prefixes, 0);
586
0
  pos = print_argument_name(decl, a, pos);
587
0
  pos = print_help_msg(decl, pos);
588
0
  if (*p)
589
0
    print_default(decl, *p, pos);
590
0
  printf("\n");
591
0
}
592
593
static void print_str_list_help(struct isl_arg *decl,
594
  struct isl_prefixes *prefixes)
595
0
{
596
0
  int pos;
597
0
  const char *a = decl->argument_name ? decl->argument_name : "string";
598
0
  pos = print_arg_help(decl, prefixes, 0);
599
0
  pos = print_argument_name(decl, a, pos);
600
0
  pos = print_help_msg(decl, pos);
601
0
  printf("\n");
602
0
}
603
604
static void print_help(struct isl_arg *arg,
605
  struct isl_prefixes *prefixes, void *opt)
606
0
{
607
0
  int i;
608
0
  int any = 0;
609
0
610
0
  for (i = 0; arg[i].type != isl_arg_end; ++i) {
611
0
    if (arg[i].flags & ISL_ARG_HIDDEN)
612
0
      continue;
613
0
    switch (arg[i].type) {
614
0
    case isl_arg_flags:
615
0
      print_flags_help(&arg[i], prefixes, opt);
616
0
      any = 1;
617
0
      break;
618
0
    case isl_arg_choice:
619
0
      print_choice_help(&arg[i], prefixes, opt);
620
0
      any = 1;
621
0
      break;
622
0
    case isl_arg_bool:
623
0
      print_bool_help(&arg[i], prefixes, opt);
624
0
      any = 1;
625
0
      break;
626
0
    case isl_arg_int:
627
0
      print_int_help(&arg[i], prefixes, opt);
628
0
      any = 1;
629
0
      break;
630
0
    case isl_arg_long:
631
0
      print_long_help(&arg[i], prefixes, opt);
632
0
      any = 1;
633
0
      break;
634
0
    case isl_arg_ulong:
635
0
      print_ulong_help(&arg[i], prefixes);
636
0
      any = 1;
637
0
      break;
638
0
    case isl_arg_str:
639
0
      print_str_help(&arg[i], prefixes, opt);
640
0
      any = 1;
641
0
      break;
642
0
    case isl_arg_str_list:
643
0
      print_str_list_help(&arg[i], prefixes);
644
0
      any = 1;
645
0
      break;
646
0
    case isl_arg_alias:
647
0
    case isl_arg_version:
648
0
    case isl_arg_arg:
649
0
    case isl_arg_footer:
650
0
    case isl_arg_child:
651
0
    case isl_arg_user:
652
0
    case isl_arg_end:
653
0
      break;
654
0
    }
655
0
  }
656
0
657
0
  for (i = 0; arg[i].type != isl_arg_end; ++i) {
658
0
    void *child;
659
0
    int first;
660
0
661
0
    if (arg[i].type != isl_arg_child)
662
0
      continue;
663
0
    if (arg[i].flags & ISL_ARG_HIDDEN)
664
0
      continue;
665
0
666
0
    if (any)
667
0
      printf("\n");
668
0
    if (arg[i].help_msg)
669
0
      printf(" %s\n", arg[i].help_msg);
670
0
    if (arg[i].offset == (size_t) -1)
671
0
      child = opt;
672
0
    else
673
0
      child = *(void **)(((char *) opt) + arg[i].offset);
674
0
    first = add_prefix(prefixes, arg[i].long_name);
675
0
    print_help(arg[i].u.child.child->args, prefixes, child);
676
0
    drop_prefix(prefixes, first);
677
0
    any = 1;
678
0
  }
679
0
}
680
681
static const char *prog_name(const char *prog)
682
0
{
683
0
  const char *slash;
684
0
685
0
  slash = strrchr(prog, '/');
686
0
  if (slash)
687
0
    prog = slash + 1;
688
0
  if (strncmp(prog, "lt-", 3) == 0)
689
0
    prog += 3;
690
0
691
0
  return prog;
692
0
}
693
694
static int any_version(struct isl_arg *decl)
695
0
{
696
0
  int i;
697
0
698
0
  for (i = 0; decl[i].type != isl_arg_end; ++i) {
699
0
    switch (decl[i].type) {
700
0
    case isl_arg_version:
701
0
      return 1;
702
0
    case isl_arg_child:
703
0
      if (any_version(decl[i].u.child.child->args))
704
0
        return 1;
705
0
      break;
706
0
    default:
707
0
      break;
708
0
    }
709
0
  }
710
0
711
0
  return 0;
712
0
}
713
714
static void print_help_and_exit(struct isl_arg *arg, const char *prog,
715
  void *opt)
716
0
{
717
0
  int i;
718
0
  struct isl_prefixes prefixes = { 0 };
719
0
720
0
  printf("Usage: %s [OPTION...]", prog_name(prog));
721
0
722
0
  for (i = 0; arg[i].type != isl_arg_end; ++i)
723
0
    if (arg[i].type == isl_arg_arg)
724
0
      printf(" %s", arg[i].argument_name);
725
0
726
0
  printf("\n\n");
727
0
728
0
  print_help(arg, &prefixes, opt);
729
0
  printf("\n");
730
0
  if (any_version(arg))
731
0
    printf("  -V, --version\n");
732
0
  print_bool_help(help_arg, NULL, NULL);
733
0
734
0
  for (i = 0; arg[i].type != isl_arg_end; ++i) {
735
0
    if (arg[i].type != isl_arg_footer)
736
0
      continue;
737
0
    wrap_msg(arg[i].help_msg, 0, 0);
738
0
    printf("\n");
739
0
  }
740
0
741
0
  exit(0);
742
0
}
743
744
static int match_long_name(struct isl_arg *decl,
745
  const char *start, const char *end)
746
0
{
747
0
  do {
748
0
    if (end - start == strlen(decl->long_name) &&
749
0
        !strncmp(start, decl->long_name, end - start))
750
0
      return 1;
751
0
  } while ((++decl)->type == isl_arg_alias);
752
0
753
0
  return 0;
754
0
}
755
756
static const char *skip_dash_dash(struct isl_arg *decl, const char *arg)
757
0
{
758
0
  if (!strncmp(arg, "--", 2))
759
0
    return arg + 2;
760
0
  if ((decl->flags & ISL_ARG_SINGLE_DASH) && arg[0] == '-')
761
0
    return arg + 1;
762
0
  return NULL;
763
0
}
764
765
static const char *skip_name(struct isl_arg *decl, const char *arg,
766
  struct isl_prefixes *prefixes, int need_argument, int *has_argument)
767
0
{
768
0
  const char *equal;
769
0
  const char *name;
770
0
  const char *end;
771
0
772
0
  if (arg[0] == '-' && arg[1] && arg[1] == decl->short_name) {
773
0
    if (need_argument && !arg[2])
774
0
      return NULL;
775
0
    if (has_argument)
776
0
      *has_argument = arg[2] != '\0';
777
0
    return arg + 2;
778
0
  }
779
0
  if (!decl->long_name)
780
0
    return NULL;
781
0
782
0
  name = skip_dash_dash(decl, arg);
783
0
  if (!name)
784
0
    return NULL;
785
0
786
0
  equal = strchr(name, '=');
787
0
  if (need_argument && !equal)
788
0
    return NULL;
789
0
790
0
  if (has_argument)
791
0
    *has_argument = !!equal;
792
0
  end = equal ? equal : name + strlen(name);
793
0
794
0
  name = skip_prefixes(name, prefixes, NULL);
795
0
796
0
  if (!match_long_name(decl, name, end))
797
0
    return NULL;
798
0
799
0
  return equal ? equal + 1 : end;
800
0
}
801
802
static int parse_choice_option(struct isl_arg *decl, char **arg,
803
  struct isl_prefixes *prefixes, void *opt)
804
0
{
805
0
  int i;
806
0
  int has_argument;
807
0
  const char *choice;
808
0
809
0
  choice = skip_name(decl, arg[0], prefixes, 0, &has_argument);
810
0
  if (!choice)
811
0
    return 0;
812
0
813
0
  if (!has_argument && (!arg[1] || arg[1][0] == '-')) {
814
0
    unsigned u = decl->u.choice.default_selected;
815
0
    if (decl->offset != (size_t) -1)
816
0
      *(unsigned *)(((char *)opt) + decl->offset) = u;
817
0
    if (decl->u.choice.set)
818
0
      decl->u.choice.set(opt, u);
819
0
820
0
    return 1;
821
0
  }
822
0
823
0
  if (!has_argument)
824
0
    choice = arg[1];
825
0
826
0
  for (i = 0; decl->u.choice.choice[i].name; ++i) {
827
0
    unsigned u;
828
0
829
0
    if (strcmp(choice, decl->u.choice.choice[i].name))
830
0
      continue;
831
0
832
0
    u = decl->u.choice.choice[i].value;
833
0
    if (decl->offset != (size_t) -1)
834
0
      *(unsigned *)(((char *)opt) + decl->offset) = u;
835
0
    if (decl->u.choice.set)
836
0
      decl->u.choice.set(opt, u);
837
0
838
0
    return has_argument ? 1 : 2;
839
0
  }
840
0
841
0
  return 0;
842
0
}
843
844
static int set_flag(struct isl_arg *decl, unsigned *val, const char *flag,
845
  size_t len)
846
0
{
847
0
  int i;
848
0
849
0
  for (i = 0; decl->u.flags.flags[i].name; ++i) {
850
0
    if (strncmp(flag, decl->u.flags.flags[i].name, len))
851
0
      continue;
852
0
853
0
    *val &= ~decl->u.flags.flags[i].mask;
854
0
    *val |= decl->u.flags.flags[i].value;
855
0
856
0
    return 1;
857
0
  }
858
0
859
0
  return 0;
860
0
}
861
862
static int parse_flags_option(struct isl_arg *decl, char **arg,
863
  struct isl_prefixes *prefixes, void *opt)
864
0
{
865
0
  int has_argument;
866
0
  const char *flags;
867
0
  const char *comma;
868
0
  unsigned val;
869
0
870
0
  flags = skip_name(decl, arg[0], prefixes, 0, &has_argument);
871
0
  if (!flags)
872
0
    return 0;
873
0
874
0
  if (!has_argument && !arg[1])
875
0
    return 0;
876
0
877
0
  if (!has_argument)
878
0
    flags = arg[1];
879
0
880
0
  val = 0;
881
0
882
0
  while ((comma = strchr(flags, ',')) != NULL) {
883
0
    if (!set_flag(decl, &val, flags, comma - flags))
884
0
      return 0;
885
0
    flags = comma + 1;
886
0
  }
887
0
  if (!set_flag(decl, &val, flags, strlen(flags)))
888
0
    return 0;
889
0
890
0
  *(unsigned *)(((char *)opt) + decl->offset) = val;
891
0
892
0
  return has_argument ? 1 : 2;
893
0
}
894
895
static int parse_bool_option(struct isl_arg *decl, char **arg,
896
  struct isl_prefixes *prefixes, void *opt)
897
0
{
898
0
  const char *name;
899
0
  unsigned *p = (unsigned *)(((char *)opt) + decl->offset);
900
0
  int next_prefix;
901
0
902
0
  if (skip_name(decl, arg[0], prefixes, 0, NULL)) {
903
0
    if ((decl->flags & ISL_ARG_BOOL_ARG) && arg[1]) {
904
0
      char *endptr;
905
0
      int val = strtol(arg[1], &endptr, 0);
906
0
      if (*endptr == '\0' && (val == 0 || val == 1)) {
907
0
        if (decl->offset != (size_t) -1)
908
0
          *p = val;
909
0
        if (decl->u.b.set)
910
0
          decl->u.b.set(opt, val);
911
0
        return 2;
912
0
      }
913
0
    }
914
0
    if (decl->offset != (size_t) -1)
915
0
      *p = 1;
916
0
    if (decl->u.b.set)
917
0
      decl->u.b.set(opt, 1);
918
0
919
0
    return 1;
920
0
  }
921
0
922
0
  if (!decl->long_name)
923
0
    return 0;
924
0
925
0
  name = skip_dash_dash(decl, arg[0]);
926
0
  if (!name)
927
0
    return 0;
928
0
929
0
  next_prefix = 0;
930
0
  name = skip_prefixes(name, prefixes, &next_prefix);
931
0
932
0
  if (strncmp(name, "no-", 3))
933
0
    return 0;
934
0
  name += 3;
935
0
936
0
  name = skip_prefixes(name, prefixes, &next_prefix);
937
0
938
0
  if (match_long_name(decl, name, name + strlen(name))) {
939
0
    if (decl->offset != (size_t) -1)
940
0
      *p = 0;
941
0
    if (decl->u.b.set)
942
0
      decl->u.b.set(opt, 0);
943
0
944
0
    return 1;
945
0
  }
946
0
947
0
  return 0;
948
0
}
949
950
static int parse_str_option(struct isl_arg *decl, char **arg,
951
  struct isl_prefixes *prefixes, void *opt)
952
0
{
953
0
  int has_argument;
954
0
  const char *s;
955
0
  char **p = (char **)(((char *)opt) + decl->offset);
956
0
957
0
  s = skip_name(decl, arg[0], prefixes, 0, &has_argument);
958
0
  if (!s)
959
0
    return 0;
960
0
961
0
  if (has_argument) {
962
0
    free(*p);
963
0
    *p = strdup(s);
964
0
    return 1;
965
0
  }
966
0
967
0
  if (arg[1]) {
968
0
    free(*p);
969
0
    *p = strdup(arg[1]);
970
0
    return 2;
971
0
  }
972
0
973
0
  return 0;
974
0
}
975
976
static int isl_arg_str_list_append(struct isl_arg *decl, void *opt,
977
  const char *s)
978
0
{
979
0
  int *n = (int *)(((char *) opt) + decl->u.str_list.offset_n);
980
0
  char **list = *(char ***)(((char *) opt) + decl->offset);
981
0
982
0
  list = realloc(list, (*n + 1) * sizeof(char *));
983
0
  if (!list)
984
0
    return -1;
985
0
  *(char ***)(((char *) opt) + decl->offset) = list;
986
0
  list[*n] = strdup(s);
987
0
  (*n)++;
988
0
  return 0;
989
0
}
990
991
static int parse_str_list_option(struct isl_arg *decl, char **arg,
992
  struct isl_prefixes *prefixes, void *opt)
993
0
{
994
0
  int has_argument;
995
0
  const char *s;
996
0
997
0
  s = skip_name(decl, arg[0], prefixes, 0, &has_argument);
998
0
  if (!s)
999
0
    return 0;
1000
0
1001
0
  if (has_argument) {
1002
0
    isl_arg_str_list_append(decl, opt, s);
1003
0
    return 1;
1004
0
  }
1005
0
1006
0
  if (arg[1]) {
1007
0
    isl_arg_str_list_append(decl, opt, arg[1]);
1008
0
    return 2;
1009
0
  }
1010
0
1011
0
  return 0;
1012
0
}
1013
1014
static int parse_int_option(struct isl_arg *decl, char **arg,
1015
  struct isl_prefixes *prefixes, void *opt)
1016
0
{
1017
0
  int has_argument;
1018
0
  const char *val;
1019
0
  char *endptr;
1020
0
  int *p = (int *)(((char *)opt) + decl->offset);
1021
0
1022
0
  val = skip_name(decl, arg[0], prefixes, 0, &has_argument);
1023
0
  if (!val)
1024
0
    return 0;
1025
0
1026
0
  if (has_argument) {
1027
0
    *p = atoi(val);
1028
0
    return 1;
1029
0
  }
1030
0
1031
0
  if (arg[1]) {
1032
0
    int i = strtol(arg[1], &endptr, 0);
1033
0
    if (*endptr == '\0') {
1034
0
      *p = i;
1035
0
      return 2;
1036
0
    }
1037
0
  }
1038
0
1039
0
  return 0;
1040
0
}
1041
1042
static int parse_long_option(struct isl_arg *decl, char **arg,
1043
  struct isl_prefixes *prefixes, void *opt)
1044
0
{
1045
0
  int has_argument;
1046
0
  const char *val;
1047
0
  char *endptr;
1048
0
  long *p = (long *)(((char *)opt) + decl->offset);
1049
0
1050
0
  val = skip_name(decl, arg[0], prefixes, 0, &has_argument);
1051
0
  if (!val)
1052
0
    return 0;
1053
0
1054
0
  if (has_argument) {
1055
0
    long l = strtol(val, NULL, 0);
1056
0
    *p = l;
1057
0
    if (decl->u.l.set)
1058
0
      decl->u.l.set(opt, l);
1059
0
    return 1;
1060
0
  }
1061
0
1062
0
  if (arg[1]) {
1063
0
    long l = strtol(arg[1], &endptr, 0);
1064
0
    if (*endptr == '\0') {
1065
0
      *p = l;
1066
0
      if (decl->u.l.set)
1067
0
        decl->u.l.set(opt, l);
1068
0
      return 2;
1069
0
    }
1070
0
  }
1071
0
1072
0
  if (decl->u.l.default_value != decl->u.l.default_selected) {
1073
0
    *p = decl->u.l.default_selected;
1074
0
    if (decl->u.l.set)
1075
0
      decl->u.l.set(opt, decl->u.l.default_selected);
1076
0
    return 1;
1077
0
  }
1078
0
1079
0
  return 0;
1080
0
}
1081
1082
static int parse_ulong_option(struct isl_arg *decl, char **arg,
1083
  struct isl_prefixes *prefixes, void *opt)
1084
0
{
1085
0
  int has_argument;
1086
0
  const char *val;
1087
0
  char *endptr;
1088
0
  unsigned long *p = (unsigned long *)(((char *)opt) + decl->offset);
1089
0
1090
0
  val = skip_name(decl, arg[0], prefixes, 0, &has_argument);
1091
0
  if (!val)
1092
0
    return 0;
1093
0
1094
0
  if (has_argument) {
1095
0
    *p = strtoul(val, NULL, 0);
1096
0
    return 1;
1097
0
  }
1098
0
1099
0
  if (arg[1]) {
1100
0
    unsigned long ul = strtoul(arg[1], &endptr, 0);
1101
0
    if (*endptr == '\0') {
1102
0
      *p = ul;
1103
0
      return 2;
1104
0
    }
1105
0
  }
1106
0
1107
0
  return 0;
1108
0
}
1109
1110
static int parse_option(struct isl_arg *decl, char **arg,
1111
  struct isl_prefixes *prefixes, void *opt);
1112
1113
static int parse_child_option(struct isl_arg *decl, char **arg,
1114
  struct isl_prefixes *prefixes, void *opt)
1115
0
{
1116
0
  void *child;
1117
0
  int first, parsed;
1118
0
1119
0
  if (decl->offset == (size_t) -1)
1120
0
    child = opt;
1121
0
  else
1122
0
    child = *(void **)(((char *)opt) + decl->offset);
1123
0
1124
0
  first = add_prefix(prefixes, decl->long_name);
1125
0
  parsed = parse_option(decl->u.child.child->args, arg, prefixes, child);
1126
0
  drop_prefix(prefixes, first);
1127
0
1128
0
  return parsed;
1129
0
}
1130
1131
static int parse_option(struct isl_arg *decl, char **arg,
1132
  struct isl_prefixes *prefixes, void *opt)
1133
0
{
1134
0
  int i;
1135
0
1136
0
  for (i = 0; decl[i].type != isl_arg_end; ++i) {
1137
0
    int parsed = 0;
1138
0
    switch (decl[i].type) {
1139
0
    case isl_arg_choice:
1140
0
      parsed = parse_choice_option(&decl[i], arg,
1141
0
              prefixes, opt);
1142
0
      break;
1143
0
    case isl_arg_flags:
1144
0
      parsed = parse_flags_option(&decl[i], arg,
1145
0
              prefixes, opt);
1146
0
      break;
1147
0
    case isl_arg_int:
1148
0
      parsed = parse_int_option(&decl[i], arg, prefixes, opt);
1149
0
      break;
1150
0
    case isl_arg_long:
1151
0
      parsed = parse_long_option(&decl[i], arg,
1152
0
              prefixes, opt);
1153
0
      break;
1154
0
    case isl_arg_ulong:
1155
0
      parsed = parse_ulong_option(&decl[i], arg,
1156
0
              prefixes, opt);
1157
0
      break;
1158
0
    case isl_arg_bool:
1159
0
      parsed = parse_bool_option(&decl[i], arg,
1160
0
              prefixes, opt);
1161
0
      break;
1162
0
    case isl_arg_str:
1163
0
      parsed = parse_str_option(&decl[i], arg, prefixes, opt);
1164
0
      break;
1165
0
    case isl_arg_str_list:
1166
0
      parsed = parse_str_list_option(&decl[i], arg, prefixes,
1167
0
              opt);
1168
0
      break;
1169
0
    case isl_arg_child:
1170
0
      parsed = parse_child_option(&decl[i], arg,
1171
0
              prefixes, opt);
1172
0
      break;
1173
0
    case isl_arg_alias:
1174
0
    case isl_arg_arg:
1175
0
    case isl_arg_footer:
1176
0
    case isl_arg_user:
1177
0
    case isl_arg_version:
1178
0
    case isl_arg_end:
1179
0
      break;
1180
0
    }
1181
0
    if (parsed)
1182
0
      return parsed;
1183
0
  }
1184
0
1185
0
  return 0;
1186
0
}
1187
1188
static void print_version(struct isl_arg *decl)
1189
0
{
1190
0
  int i;
1191
0
1192
0
  for (i = 0; decl[i].type != isl_arg_end; ++i) {
1193
0
    switch (decl[i].type) {
1194
0
    case isl_arg_version:
1195
0
      decl[i].u.version.print_version();
1196
0
      break;
1197
0
    case isl_arg_child:
1198
0
      print_version(decl[i].u.child.child->args);
1199
0
      break;
1200
0
    default:
1201
0
      break;
1202
0
    }
1203
0
  }
1204
0
}
1205
1206
static void print_version_and_exit(struct isl_arg *decl)
1207
0
{
1208
0
  print_version(decl);
1209
0
1210
0
  exit(0);
1211
0
}
1212
1213
static int drop_argument(int argc, char **argv, int drop, int n)
1214
0
{
1215
0
  for (; drop + n < argc; ++drop)
1216
0
    argv[drop] = argv[drop + n];
1217
0
1218
0
  return argc - n;
1219
0
}
1220
1221
static int n_arg(struct isl_arg *arg)
1222
1
{
1223
1
  int i;
1224
1
  int n_arg = 0;
1225
1
1226
44
  for (i = 0; arg[i].type != isl_arg_end; 
++i43
)
1227
43
    if (arg[i].type == isl_arg_arg)
1228
0
      n_arg++;
1229
1
1230
1
  return n_arg;
1231
1
}
1232
1233
static int next_arg(struct isl_arg *arg, int a)
1234
0
{
1235
0
  for (++a; arg[a].type != isl_arg_end; ++a)
1236
0
    if (arg[a].type == isl_arg_arg)
1237
0
      return a;
1238
0
1239
0
  return -1;
1240
0
}
1241
1242
/* Unless ISL_ARG_SKIP_HELP is set, check if "arg" is
1243
 * equal to "--help" and if so call print_help_and_exit.
1244
 */
1245
static void check_help(struct isl_args *args, char *arg, char *prog, void *opt,
1246
  unsigned flags)
1247
0
{
1248
0
  if (ISL_FL_ISSET(flags, ISL_ARG_SKIP_HELP))
1249
0
    return;
1250
0
1251
0
  if (strcmp(arg, "--help") == 0)
1252
0
    print_help_and_exit(args->args, prog, opt);
1253
0
}
1254
1255
int isl_args_parse(struct isl_args *args, int argc, char **argv, void *opt,
1256
  unsigned flags)
1257
1
{
1258
1
  int a = -1;
1259
1
  int skip = 0;
1260
1
  int i;
1261
1
  int n;
1262
1
  struct isl_prefixes prefixes = { 0 };
1263
1
1264
1
  n = n_arg(args->args);
1265
1
1266
1
  for (i = 1; i < argc; 
++i0
) {
1267
0
    if ((strcmp(argv[i], "--version") == 0 ||
1268
0
         strcmp(argv[i], "-V") == 0) && any_version(args->args))
1269
0
      print_version_and_exit(args->args);
1270
0
  }
1271
1
1272
1
  while (argc > 1 + skip) {
1273
0
    int parsed;
1274
0
    if (argv[1 + skip][0] != '-') {
1275
0
      a = next_arg(args->args, a);
1276
0
      if (a >= 0) {
1277
0
        char **p;
1278
0
        p = (char **)(((char *)opt)+args->args[a].offset);
1279
0
        free(*p);
1280
0
        *p = strdup(argv[1 + skip]);
1281
0
        argc = drop_argument(argc, argv, 1 + skip, 1);
1282
0
        --n;
1283
0
      } else if (ISL_FL_ISSET(flags, ISL_ARG_ALL)) {
1284
0
        fprintf(stderr, "%s: extra argument: %s\n",
1285
0
              prog_name(argv[0]), argv[1 + skip]);
1286
0
        exit(-1);
1287
0
      } else
1288
0
        ++skip;
1289
0
      continue;
1290
0
    }
1291
0
    check_help(args, argv[1 + skip], argv[0], opt, flags);
1292
0
    parsed = parse_option(args->args, &argv[1 + skip],
1293
0
          &prefixes, opt);
1294
0
    if (parsed)
1295
0
      argc = drop_argument(argc, argv, 1 + skip, parsed);
1296
0
    else if (ISL_FL_ISSET(flags, ISL_ARG_ALL)) {
1297
0
      fprintf(stderr, "%s: unrecognized option: %s\n",
1298
0
          prog_name(argv[0]), argv[1 + skip]);
1299
0
      exit(-1);
1300
0
    } else
1301
0
      ++skip;
1302
0
  }
1303
1
1304
1
  if (n > 0) {
1305
0
    fprintf(stderr, "%s: expecting %d more argument(s)\n",
1306
0
        prog_name(argv[0]), n);
1307
0
    exit(-1);
1308
0
  }
1309
1
1310
1
  return argc;
1311
1
}