9static char* resize(
char** buffer, 
size_t* size, 
size_t increment)
 
   11  const size_t nsize = *size + increment;
 
   12  char* tmp = realloc(*buffer, nsize);
 
   16                  "Could not reallocate string buffer from %" PRIuz 
" to %" PRIuz 
" bytes.\n",
 
   21  memset(&tmp[*size], 
'\0', increment);
 
   27static char* append(
char** buffer, 
size_t* size, 
const char* str)
 
   29  const size_t len = strnlen(*buffer, *size);
 
   30  const size_t add = strlen(str);
 
   31  const size_t required = len + add + 1;
 
   35    if (!resize(buffer, size, required - *size))
 
   38  strncpy(&(*buffer)[len], str, add);
 
   42static LPSTR tr_esc_str(LPCSTR arg, 
bool format, 
int* failed)
 
   44  const char* str = NULL;
 
   53  const size_t s = strlen(arg) + 1;
 
   54  if (!resize(&tmp, &ds, s))
 
   60  for (
size_t x = 0; x < s; x++)
 
   67        if (!append(&tmp, &ds, str))
 
   80        if (!append(&tmp, &ds, str))
 
   93        if (!append(&tmp, &ds, str))
 
  102        if (!append(&tmp, &ds, str))
 
  110        if (!append(&tmp, &ds, 
"\\&."))
 
  119        if (!append(&tmp, &ds, 
"\n.br\n"))
 
  128        if (!append(&tmp, &ds, data))
 
  140int main(
int argc, 
char* argv[])
 
  143  size_t elements = 
sizeof(global_cmd_args) / 
sizeof(global_cmd_args[0]);
 
  147    (void)fprintf(stderr, 
"Usage: %s <output file name>\n", argv[0]);
 
  151  const char* fname = argv[1];
 
  153  (void)fprintf(stdout, 
"Generating manpage file '%s'\n", fname);
 
  154  FILE* fp = fopen(fname, 
"w");
 
  157    (void)fprintf(stderr, 
"Could not open '%s' for writing.\n", fname);
 
  162  (void)fprintf(fp, 
".SH \"OPTIONS\"\n");
 
  166    (void)fprintf(stderr, 
"The argument array 'args' is empty, writing an empty file.\n");
 
  170  for (
size_t x = 0; x < elements - 1; x++)
 
  174    char* name = tr_esc_str(arg->Name, FALSE, &failed);
 
  175    char* alias = tr_esc_str(arg->Alias, FALSE, &failed);
 
  176    char* format = tr_esc_str(arg->Format, TRUE, &failed);
 
  177    char* text = tr_esc_str(arg->Text, FALSE, &failed);
 
  189    (void)fprintf(fp, 
".PP\n");
 
  193      (void)fprintf(fp, 
"%s\\fB", first ? 
"" : 
", ");
 
  195      if (arg->Flags == COMMAND_LINE_VALUE_BOOL)
 
  196        (void)fprintf(fp, 
"%s", arg->Default ? 
"\\-" : 
"+");
 
  198        (
void)fprintf(fp, 
"/");
 
  200      (void)fprintf(fp, 
"%s\\fR", name);
 
  204        if (arg->Flags == COMMAND_LINE_VALUE_OPTIONAL)
 
  205          (void)fprintf(fp, 
"[");
 
  207        (void)fprintf(fp, 
":%s", format);
 
  209        if (arg->Flags == COMMAND_LINE_VALUE_OPTIONAL)
 
  210          (void)fprintf(fp, 
"]");
 
  219    (void)fprintf(fp, 
"\n");
 
  223      (void)fprintf(fp, 
".RS 4\n");
 
  224      const int hasText = text && (strnlen(text, 2) > 0);
 
  226        (void)fprintf(fp, 
"%s", text);
 
  228      if (arg->Flags & COMMAND_LINE_VALUE_BOOL &&
 
  229          (!arg->Default || arg->Default == BoolValueTrue))
 
  230        (
void)fprintf(fp, 
" (default:%s)\n", arg->Default ? 
"on" : 
"off");
 
  231      else if (arg->Default)
 
  233        char* value = tr_esc_str(arg->Default, FALSE, &failed);
 
  239        (void)fprintf(fp, 
" (default:%s)\n", value);
 
  243        (void)fprintf(fp, 
"\n");
 
  246    (void)fprintf(fp, 
".RE\n");
 
  258    (void)fprintf(stdout, 
"successfully generated '%s'\n", fname);
 
  260    (
void)fprintf(stdout, 
"failed to generate '%s'\n", fname);