aboutsummaryrefslogtreecommitdiff
path: root/src/tt.options.c
blob: f502a7a2707d637e39e8aa9686c0ea27669d988e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// Command-line flags
// ============================================================================

// tt can be configured by changing the value of three variables:
// -> declarations

char *code_prefix; /* string with which code lines should start */
char *doc_prefix;  /* string with which documentation lines should start */
char *out_prefix;  /* string to which the output file name should be appended */

// The default values are the following: -> main.options

  code_prefix = "    "; /* code lines should begin with four spaces */
  doc_prefix = "";      /* other lines are documentation lines */
  out_prefix = "out/";  /* all output files go in the out/ directory */

// Each variable is controlled by a single-letter command-line flag, which
// should then be immediately -- without any space -- followed by the
// desired value. For example, -dfinal. would set out_prefix to "final.".

// This convention allows for a very simple parsing loop: -> main.options

  for (i = 1; i < argc; i++)
    if (argv[i][0] == '-') {
      switch(argv[i][1]) {
        case 'c':
          code_prefix = argv[i] + 2;
          break;
        case 'd':
          doc_prefix = argv[i] + 2;
          break;
        case 'o':
          out_prefix = argv[i] + 2;
          break;
        case '-':
          i++;
          goto end;
        default:
          die(USAGE);
      }
    } else
      break;
end:

// If the given argument begins with a hyphen, it is interpreted as a flag.
// If the flag is --, then tt ignores the argument and stops looking for flags.
// If the flag is unrecognized, the program dies. If the argument does not
// begin with a hyphen, it and anything following it will not be interpreted
// as a flag.

// USAGE contains information about how to use tt: -> definitions

#define USAGE "usage: %s [-cCODE_PREFIX] [-dDOC_PREFIX] [-oOUTPREFIX] destination ...\n", argv[0]

// Of course, we can't just trust the user to provide reasonable values, so we
// ensure that the code_prefix and out_prefix are not identical and that the
// out_prefix is not empty -- otherwise, tt would overwrite all destination
// files: -> main.options

  if (strcmp(code_prefix, doc_prefix) == 0)
    die("code_prefix and doc_prefix cannot be identical\n");
  if (strlen(out_prefix) == 0)
    die("out_prefix cannot be empty\n");

// Command-line arguments
// ============================================================================

// Having finished parsing command-line flags, it is time to collect the
// remaining command-line arguments, which should be one or more destination
// files. Our loop above, when broken out of or finished naturally, has set
// the i variable to the position of the first non-flag argument in argv (or
// simply the position after the last flag in argv).

// First, we check if there actually are any further argument, or if i is past
// the end of the array: -> main.options

  if (i == argc) die(USAGE);

// At least one destination file is required. Then, we save the position of the
// first destination file in argv in a special variable for later use:
// -> main.options

offset = i;

// -> main.declarations

int offset;

// Now, we have successfully finished parsing both flags and arguments, and are
// ready to read the lines on the standard input.