view helpgen/cout.c @ 21:1c9dac05d040

Add lint-style FALLTHROUGH annotations to fallthrough cases. (in the parse engine and thus the output code) Document this, because the old output causes warnings with gcc10.
author David A. Holland
date Mon, 13 Jun 2022 00:04:38 -0400
parents 13d2b8934445
children
line wrap: on
line source

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "topic.h"
#include "helpgen.h"

static void dumpstring(FILE *f, const char *s, int multiline) {
  int column = 0;
  unsigned char ch;

  while (*s) {
    if (column == 0) {
      if (multiline) fprintf(f, "  ");
      fprintf(f, "\"");
    }
    ch = *s++;

    if (ch >= 32 && ch < 127 && ch != '"' && ch != '\\') {
      fprintf(f, "%c", ch);
      column++;
    }
    else if (ch == '\n') {
      fprintf(f, "\\n");
      column += 2;
    }
    else {
      assert(ch != '\r');
      fprintf(f, "\\%03o", ch);
      column += 4;
    }

    if (multiline && column > 72) {
      fprintf(f, "\"\n");
      column = 0;
    }
  }

  if (column) {
    fprintf(f, "\"");
    if (multiline) fprintf(f, "\n");
  }
}

static void fcout(FILE *f, struct topic **topics, int ntopics) {
  int i, j, n;
  unsigned numentries = 0;

  fprintf(f, "/* Automatically generated - do not edit */\n\n");

  fprintf(f, "struct HelpTopic {\n");
  fprintf(f, "  const char *title;\n");
  fprintf(f, "  const char *body;\n");
  fprintf(f, "};\n\n");


  for (i=0; i<ntopics; i++) {
    struct topic *t = topics[i];
    const char *title = topic_gettitle(t, 0);
    const char *body = topic_getbody(t); 

    if (!body) body = "";

    fprintf(f, "static const char body_%d[] = \n", i);
    dumpstring(f, body, 1 /* multiline */);
    fprintf(f, ";\n");

    fprintf(f, "static const HelpTopic topic_%d = \n  { ", i);
    dumpstring(f, title, 0 /* not multiline */);
    fprintf(f, ", body_%d };\n\n", i);
  }


  fprintf(f, "static const char *topiclist[] = {\n");
  for (i=0; i<ntopics; i++) {
    struct topic *t = topics[i];
    const char *title = topic_gettitle(t, 0);

    fprintf(f, "  ");
    dumpstring(f, title, 0 /* not multiline */);
    fprintf(f, ",\n");
  }
  fprintf(f, "};\n");
  fprintf(f, "static const unsigned numtopiclist = %d;\n\n", ntopics);


  fprintf(f, "struct helpentry {\n");
  fprintf(f, "  const char *topic;\n");
  fprintf(f, "  const HelpTopic *data;\n");
  fprintf(f, "};\n\n");

  fprintf(f, "static helpentry helptable[] = {\n");
  for (i=0; i<ntopics; i++) {
    struct topic *t = topics[i];

    n = topic_getnumtitles(t);
    for (j=0; j<n; j++) {
      fprintf(f, "{ ");
      dumpstring(f, topic_gettitle(t, j), 0 /* not multiline */);
      fprintf(f, ", &topic_%d },\n", i);
      numentries++;
    }
  }
  fprintf(f, "};\n");
  fprintf(f, "static const unsigned helptablenum = %u;\n\n", numentries);
}

void cout(const char *file, struct topic **topics, int ntopics) {
  FILE *f;

  f = fopen(file, "w");
  if (!f) {
    fprintf(stderr, "%s: fopen failed", file);
    exit(1);
  }

  fcout(f, topics, ntopics);

  if (ferror(f)) {
    fprintf(stderr, "%s: write error", file);
    exit(1);
  }
  if (fclose(f)) {
    fprintf(stderr, "%s: fclose failed", file);
    exit(1);
  }
}