From 545aa85677811a63e3b9ecb0f0f05e754eff7297 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Mon, 10 Feb 2014 17:25:07 -0800 Subject: [PATCH] SCP: Cleaned up the hierarchical help APIs to follow the same indentation style used in the rest of scp.c. Fixed the help prompt to avoid adding an extra level to the prompt when the current level has no children. --- scp.c | 1182 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 590 insertions(+), 592 deletions(-) diff --git a/scp.c b/scp.c index da0ba46e..e1f080d4 100644 --- a/scp.c +++ b/scp.c @@ -7930,14 +7930,14 @@ typedef struct topic { uint32 flags; uint32 kidwid; #define HLP_MAGIC_TOPIC 1 -} TOPIC; + } TOPIC; static volatile struct { const char *error; const char *prox; size_t block; size_t line; -} help_where = { "", NULL, 0, 0 }; + } help_where = { "", NULL, 0, 0 }; jmp_buf (help_env); #define FAIL(why,text,here) { help_where.error = #text; help_where.prox = here; longjmp (help_env, (why)); } @@ -7945,116 +7945,116 @@ jmp_buf (help_env); * Expands text buffer as necessary. */ -static void appendText (TOPIC *topic, const char *text, size_t len) { - char *newt; - if (!len) { - return; - } +static void appendText (TOPIC *topic, const char *text, size_t len) +{ +char *newt; - newt = (char *)realloc (topic->text, topic->len + len +1); - if (!newt) { - FAIL (SCPE_MEM, No memory, NULL); - } - topic->text = newt; - memcpy (newt + topic->len, text, len); - topic->len +=len; - newt[topic->len] = '\0'; +if (!len) return; + +newt = (char *)realloc (topic->text, topic->len + len +1); +if (!newt) { + FAIL (SCPE_MEM, No memory, NULL); + } +topic->text = newt; +memcpy (newt + topic->len, text, len); +topic->len +=len; +newt[topic->len] = '\0'; +return; } /* Release memory held by a topic and its children. */ -static void cleanHelp (TOPIC *topic) { - TOPIC *child; - size_t i; +static void cleanHelp (TOPIC *topic) +{ +TOPIC *child; +size_t i; - free (topic->title); - free (topic->text); - free (topic->label); - for (i = 0; i < topic->kids; i++) { - child = topic->children[i]; - cleanHelp (child); - free (child); +free (topic->title); +free (topic->text); +free (topic->label); +for (i = 0; i < topic->kids; i++) { + child = topic->children[i]; + cleanHelp (child); + free (child); } - free (topic->children); - return; +free (topic->children); +return; } /* Build a help tree from a string. * Handles substitutions, formatting. */ static TOPIC *buildHelp (TOPIC *topic, struct sim_device *dptr, - struct sim_unit *uptr, const char *htext, va_list ap) { - char *end; - size_t n, ilvl; + struct sim_unit *uptr, const char *htext, va_list ap) +{ +char *end; +size_t n, ilvl; #define VSMAX 100 - char *vstrings[VSMAX]; - size_t vsnum = 0; - char *astrings[VSMAX+1]; - size_t asnum = 0; - char *const *hblock; - const char *ep; - t_bool excluded = FALSE; +char *vstrings[VSMAX]; +size_t vsnum = 0; +char *astrings[VSMAX+1]; +size_t asnum = 0; +char *const *hblock; +const char *ep; +t_bool excluded = FALSE; - /* variable arguments consumed table. - * The scheme used allows arguments to be accessed in random - * order, but for portability, all arguments must be char *. - * If you try to violate this, there ARE machines that WILL break. - */ +/* variable arguments consumed table. + * The scheme used allows arguments to be accessed in random + * order, but for portability, all arguments must be char *. + * If you try to violate this, there ARE machines that WILL break. + */ - memset (vstrings, 0, VSMAX * sizeof (char *)); - memset (astrings, 0, VSMAX * sizeof (char *)); - astrings[asnum++] = (char *) htext; +memset (vstrings, 0, VSMAX * sizeof (char *)); +memset (astrings, 0, VSMAX * sizeof (char *)); +astrings[asnum++] = (char *) htext; - for (hblock = astrings; (htext = *hblock) != NULL; hblock++) { - help_where.block = hblock - astrings; - help_where.line = 0; - while (*htext) { - const char *start; +for (hblock = astrings; (htext = *hblock) != NULL; hblock++) { + help_where.block = hblock - astrings; + help_where.line = 0; + while (*htext) { + const char *start; - help_where.line++; - if (isspace (*htext) || *htext == '+') {/* Topic text, indented topic text */ - if (excluded) { /* Excluded topic text */ - while (*htext && *htext != '\n') { - htext++; - } - if (*htext) - ++htext; - continue; - } - ilvl = 1; - appendText (topic, " ", 4); /* Basic indentation */ - if (*htext == '+') { /* More for each + */ - while (*htext == '+') { - ilvl++; - appendText (topic, " ", 4); - htext++; - } - } - while (*htext && *htext != '\n' && isspace (*htext)) { + help_where.line++; + if (isspace (*htext) || *htext == '+') {/* Topic text, indented topic text */ + if (excluded) { /* Excluded topic text */ + while (*htext && *htext != '\n') htext++; + if (*htext) + ++htext; + continue; } - if (!*htext) { /* Empty after removing leading spaces */ - break; + ilvl = 1; + appendText (topic, " ", 4); /* Basic indentation */ + if (*htext == '+') { /* More for each + */ + while (*htext == '+') { + ilvl++; + appendText (topic, " ", 4); + htext++; + } } - start = htext; - while (*htext) { /* Process line for substitutions */ - if (*htext == '%') { - appendText (topic, start, htext - start); /* Flush up to escape */ - switch (*++htext) { /* Evaluate escape */ + while (*htext && *htext != '\n' && isspace (*htext)) + htext++; + if (!*htext) /* Empty after removing leading spaces */ + break; + start = htext; + while (*htext) { /* Process line for substitutions */ + if (*htext == '%') { + appendText (topic, start, htext - start); /* Flush up to escape */ + switch (*++htext) { /* Evaluate escape */ case 'U': if (dptr) { char buf[129]; n = uptr? uptr - dptr->units: 0; sprintf (buf, "%s%u", dptr->name, (int)n); appendText (topic, buf, strlen (buf)); - } + } break; case 'D': if (dptr) { appendText (topic, dptr->name, strlen (dptr->name)); break; - } + } case 'S': appendText (topic, sim_name, strlen (sim_name)); break; @@ -8067,23 +8067,21 @@ static TOPIC *buildHelp (TOPIC *topic, struct sim_device *dptr, default: /* Check for vararg # */ if (isdigit (*htext)) { n = 0; - while (isdigit (*htext)) { + while (isdigit (*htext)) n += (n * 10) + (*htext++ - '0'); - } if (( *htext != 'H' && *htext != 's') || n == 0 || n >= VSMAX) FAIL (SCPE_ARG, Invalid escape, htext); - while (n > vsnum) { /* Get arg pointer if not cached */ + while (n > vsnum) /* Get arg pointer if not cached */ vstrings[vsnum++] = va_arg (ap, char *); - } start = vstrings[n-1]; /* Insert selected string */ if (*htext == 'H') { /* Append as more input */ if (asnum >= VSMAX) { FAIL (SCPE_ARG, Too many blocks, htext); - } + } astrings[asnum++] = (char *)start; break; - } + } ep = start; while (*ep) { if (*ep == '\n') { @@ -8091,171 +8089,165 @@ static TOPIC *buildHelp (TOPIC *topic, struct sim_device *dptr, appendText (topic, start, ep - start); if (*ep) { /* More past \n, indent */ size_t i; - for (i = 0; i < ilvl; i++) { + for (i = 0; i < ilvl; i++) appendText (topic, " ", 4); } - } start = ep; - } else { + } + else ep++; } - } appendText (topic, start, ep-start); break; - } + } FAIL (SCPE_ARG, Invalid escape, htext); } /* switch (escape) */ - start = ++htext; - continue; /* Current line */ + start = ++htext; + continue; /* Current line */ } /* if (escape) */ - if (*htext == '\n') { /* End of line, append last segment */ - htext++; - appendText (topic, start, htext - start); - break; /* To next line */ + if (*htext == '\n') { /* End of line, append last segment */ + htext++; + appendText (topic, start, htext - start); + break; /* To next line */ } - htext++; /* Regular character */ + htext++; /* Regular character */ } - continue; + continue; } /* topic text line */ - if (isdigit (*htext)) { /* Topic heading */ - TOPIC **children; - TOPIC *newt; - char nbuf[100]; + if (isdigit (*htext)) { /* Topic heading */ + TOPIC **children; + TOPIC *newt; + char nbuf[100]; - n = 0; - start = htext; - while (isdigit (*htext)) { - n += (n * 10) + (*htext++ - '0'); + n = 0; + start = htext; + while (isdigit (*htext)) + n += (n * 10) + (*htext++ - '0'); + if ((htext == start) || !n) { + FAIL (SCPE_ARG, Invalid topic heading, htext); } - if ((htext == start) || !n) { - FAIL (SCPE_ARG, Invalid topic heading, htext); - } - if (n <= topic->level) { /* Find level for new topic */ - while (n <= topic->level) { - topic = topic->parent; - } - } else { - if (n > topic->level +1) { /* Skipping down more than 1 */ - FAIL (SCPE_ARG, Level not contiguous, htext); /* E.g. 1 3, not reasonable */ + if (n <= topic->level) { /* Find level for new topic */ + while (n <= topic->level) + topic = topic->parent; + } + else { + if (n > topic->level +1) { /* Skipping down more than 1 */ + FAIL (SCPE_ARG, Level not contiguous, htext); /* E.g. 1 3, not reasonable */ } } - while (*htext && (*htext != '\n') && isspace (*htext)) { - htext++; + while (*htext && (*htext != '\n') && isspace (*htext)) + htext++; + if (!*htext || (*htext == '\n')) { /* Name missing */ + FAIL (SCPE_ARG, Missing topic name, htext); } - if (!*htext || (*htext == '\n')) { /* Name missing */ - FAIL (SCPE_ARG, Missing topic name, htext); + start = htext; + while (*htext && (*htext != '\n')) + htext++; + if (start == htext) { /* Name NULL */ + FAIL (SCPE_ARG, Null topic name, htext); } - start = htext; - while (*htext && (*htext != '\n')) { - htext++; - } - if (start == htext) { /* Name NULL */ - FAIL (SCPE_ARG, Null topic name, htext); - } - excluded = FALSE; - if (*start == '?') { /* Conditional topic? */ - size_t n = 0; - start++; - while (isdigit (*start)) { /* Get param # */ - n += (n * 10) + (*start++ - '0'); + excluded = FALSE; + if (*start == '?') { /* Conditional topic? */ + size_t n = 0; + start++; + while (isdigit (*start)) /* Get param # */ + n += (n * 10) + (*start++ - '0'); + if (!*start || *start == '\n'|| n == 0 || n >= VSMAX) + FAIL (SCPE_ARG, Invalid parameter number, start); + while (n > vsnum) /* Get arg pointer if not cached */ + vstrings[vsnum++] = va_arg (ap, char *); + end = vstrings[n-1]; /* Check for True */ + if (!end || !(toupper (*end) == 'T' || *end == '1')) { + excluded = TRUE; /* False, skip topic this time */ + if (*htext) + htext++; + continue; } - if (!*start || *start == '\n'|| n == 0 || n >= VSMAX) - FAIL (SCPE_ARG, Invalid parameter number, start); - while (n > vsnum) { /* Get arg pointer if not cached */ - vstrings[vsnum++] = va_arg (ap, char *); - } - end = vstrings[n-1]; /* Check for True */ - if (!end || !(toupper (*end) == 'T' || *end == '1')) { - excluded = TRUE; /* False, skip topic this time */ - if (*htext) - htext++; - continue; - } - } - newt = (TOPIC *) calloc (sizeof (TOPIC), 1); - if (!newt) { - FAIL (SCPE_MEM, No memory, NULL); } - newt->title = (char *) malloc ((htext - start)+1); - if (!newt->title) { - free (newt); - FAIL (SCPE_MEM, No memory, NULL); + newt = (TOPIC *) calloc (sizeof (TOPIC), 1); + if (!newt) { + FAIL (SCPE_MEM, No memory, NULL); } - memcpy (newt->title, start, htext - start); - newt->title[htext - start] = '\0'; - if (*htext) - htext++; + newt->title = (char *) malloc ((htext - start)+1); + if (!newt->title) { + free (newt); + FAIL (SCPE_MEM, No memory, NULL); + } + memcpy (newt->title, start, htext - start); + newt->title[htext - start] = '\0'; + if (*htext) + htext++; - if (newt->title[0] == '$') { - newt->flags |= HLP_MAGIC_TOPIC; - } + if (newt->title[0] == '$') + newt->flags |= HLP_MAGIC_TOPIC; - children = (TOPIC **) realloc (topic->children, - (topic->kids +1) * sizeof (TOPIC *)); - if (!children) { - free (newt->title); - free (newt); - FAIL (SCPE_MEM, No memory, NULL); + children = (TOPIC **) realloc (topic->children, + (topic->kids +1) * sizeof (TOPIC *)); + if (!children) { + free (newt->title); + free (newt); + FAIL (SCPE_MEM, No memory, NULL); } - topic->children = children; - topic->children[topic->kids++] = newt; - newt->level = n; - newt->parent = topic; - n = strlen (newt->title); - if (n > topic->kidwid) { - topic->kidwid = n; + topic->children = children; + topic->children[topic->kids++] = newt; + newt->level = n; + newt->parent = topic; + n = strlen (newt->title); + if (n > topic->kidwid) + topic->kidwid = n; + sprintf (nbuf, ".%u", topic->kids); + n = strlen (topic->label) + strlen (nbuf) + 1; + newt->label = (char *) malloc (n); + if (!newt->label) { + free (newt->title); + topic->children[topic->kids -1] = NULL; + free (newt); + FAIL (SCPE_MEM, No memory, NULL); } - sprintf (nbuf, ".%u", topic->kids); - n = strlen (topic->label) + strlen (nbuf) + 1; - newt->label = (char *) malloc (n); - if (!newt->label) { - free (newt->title); - topic->children[topic->kids -1] = NULL; - free (newt); - FAIL (SCPE_MEM, No memory, NULL); - } - sprintf (newt->label, "%s%s", topic->label, nbuf); - topic = newt; - continue; + sprintf (newt->label, "%s%s", topic->label, nbuf); + topic = newt; + continue; } /* digits introducing a topic */ - if (*htext == ';') { /* Comment */ - while (*htext && *htext != '\n') - htext++; - continue; + if (*htext == ';') { /* Comment */ + while (*htext && *htext != '\n') + htext++; + continue; } - FAIL (SCPE_ARG, Unknown line type, htext); /* Unknown line */ + FAIL (SCPE_ARG, Unknown line type, htext); /* Unknown line */ } /* htext not at end */ - memset (vstrings, 0, VSMAX * sizeof (char *)); - vsnum = 0; + memset (vstrings, 0, VSMAX * sizeof (char *)); + vsnum = 0; } /* all strings */ - return topic; +return topic; } /* Create prompt string - top thru current topic * Add prompt at end. */ -static char *helpPrompt ( TOPIC *topic, const char *pstring, t_bool oneword ) { - char *prefix; - char *newp, *newt; +static char *helpPrompt ( TOPIC *topic, const char *pstring, t_bool oneword ) +{ +char *prefix; +char *newp, *newt; - if (topic->level == 0) { - prefix = (char *) calloc (2,1); - if (!prefix) { - FAIL (SCPE_MEM, No memory, NULL); - } - prefix[0] = '\n'; - } else { - prefix = helpPrompt (topic->parent, "", oneword); - } - - newp = (char *) malloc (strlen (prefix) + 1 + strlen (topic->title) + 1 + - strlen (pstring) +1); - if (!newp) { - free (prefix); +if (topic->level == 0) { + prefix = (char *) calloc (2,1); + if (!prefix) { FAIL (SCPE_MEM, No memory, NULL); + } + prefix[0] = '\n'; + } +else + prefix = helpPrompt (topic->parent, "", oneword); + +newp = (char *) malloc (strlen (prefix) + 1 + strlen (topic->title) + 1 + + strlen (pstring) +1); +if (!newp) { + free (prefix); + FAIL (SCPE_MEM, No memory, NULL); } - strcpy (newp, prefix); +strcpy (newp, prefix); +if (topic->children) { if (topic->level != 0) strcat (newp, " "); newt = (topic->flags & HLP_MAGIC_TOPIC)? @@ -8265,137 +8257,143 @@ static char *helpPrompt ( TOPIC *topic, const char *pstring, t_bool oneword ) { while (*newt) { *np++ = blankch (*newt)? '_' : *newt; newt++; - } + } *np = '\0'; - } else { + } + else strcat (newp, newt); - } if (*pstring && *pstring != '?') strcat (newp, " "); - strcat (newp, pstring); - free (prefix); - return newp; + } +strcat (newp, pstring); +free (prefix); +return newp; } -static void displayMagicTopic (FILE *st, struct sim_device *dptr, TOPIC *topic) { - char tbuf[CBUFSIZE]; - size_t i, skiplines; +static void displayMagicTopic (FILE *st, struct sim_device *dptr, TOPIC *topic) +{ +char tbuf[CBUFSIZE]; +size_t i, skiplines; #ifdef _WIN32 - FILE *tmp; - char *tmpnam; - do { - int fd; - tmpnam = _tempnam (NULL, "simh"); - fd = _open (tmpnam, _O_CREAT | _O_RDWR | _O_EXCL, _S_IREAD | _S_IWRITE); - if (fd != -1) { - tmp = _fdopen (fd, "w+"); - break; +FILE *tmp; +char *tmpnam; + +do { + int fd; + tmpnam = _tempnam (NULL, "simh"); + fd = _open (tmpnam, _O_CREAT | _O_RDWR | _O_EXCL, _S_IREAD | _S_IWRITE); + if (fd != -1) { + tmp = _fdopen (fd, "w+"); + break; } } while (1); #else - FILE *tmp = tmpfile(); +FILE *tmp = tmpfile(); #endif - if (!tmp) { - fprintf (st, "Unable to create temporary file: %s\n", strerror (errno)); - return; +if (!tmp) { + fprintf (st, "Unable to create temporary file: %s\n", strerror (errno)); + return; } - if (topic->title) - fprintf (st, "%s\n", topic->title+1); +if (topic->title) + fprintf (st, "%s\n", topic->title+1); - skiplines = 0; - if (!strcmp (topic->title+1, "Registers")) { - fprint_reg_help (tmp, dptr) ; - skiplines = 1; - } else if (!strcmp (topic->title+1, "Set commands")) { +skiplines = 0; +if (!strcmp (topic->title+1, "Registers")) { + fprint_reg_help (tmp, dptr) ; + skiplines = 1; + } +else + if (!strcmp (topic->title+1, "Set commands")) { fprint_set_help (tmp, dptr); skiplines = 3; - } else if (!strcmp (topic->title+1, "Show commands")) { - fprint_show_help (tmp, dptr); - skiplines = 3; - } - rewind (tmp); - - /* Discard leading blank lines/redundant titles */ - - for (i =0; i < skiplines; i++) { - fgets (tbuf, sizeof (tbuf), tmp); - } - - while (fgets (tbuf, sizeof (tbuf), tmp)) { - if (tbuf[0] != '\n') { - fputs (" ", st); } - fputs (tbuf, st); + else + if (!strcmp (topic->title+1, "Show commands")) { + fprint_show_help (tmp, dptr); + skiplines = 3; + } +rewind (tmp); + +/* Discard leading blank lines/redundant titles */ + +for (i =0; i < skiplines; i++) + fgets (tbuf, sizeof (tbuf), tmp); + +while (fgets (tbuf, sizeof (tbuf), tmp)) { + if (tbuf[0] != '\n') + fputs (" ", st); + fputs (tbuf, st); } - fclose (tmp); +fclose (tmp); #ifdef _WIN32 - remove (tmpnam); - free (tmpnam); +remove (tmpnam); +free (tmpnam); #endif - return; +return; } /* Flatten and display help for those who say they prefer it. */ static t_stat displayFlatHelp (FILE *st, struct sim_device *dptr, struct sim_unit *uptr, int32 flag, - TOPIC *topic, va_list ap ) { - size_t i; + TOPIC *topic, va_list ap ) +{ +size_t i; - if (topic->flags & HLP_MAGIC_TOPIC) { - fprintf (st, "\n%s ", topic->label); - displayMagicTopic (st, dptr, topic); - } else { - fprintf (st, "\n%s %s\n", topic->label, topic->title); +if (topic->flags & HLP_MAGIC_TOPIC) { + fprintf (st, "\n%s ", topic->label); + displayMagicTopic (st, dptr, topic); } +else + fprintf (st, "\n%s %s\n", topic->label, topic->title); - /* Topic text (for magic topics, follows for explanations) - * It's possible/reasonable for a magic topic to have no text. - */ +/* Topic text (for magic topics, follows for explanations) + * It's possible/reasonable for a magic topic to have no text. + */ - if (topic->text) - fputs (topic->text, st); +if (topic->text) + fputs (topic->text, st); - for (i = 0; i < topic->kids; i++) { - displayFlatHelp (st, dptr, uptr, flag, topic->children[i], ap); - } +for (i = 0; i < topic->kids; i++) + displayFlatHelp (st, dptr, uptr, flag, topic->children[i], ap); - return SCPE_OK; +return SCPE_OK; } #define HLP_MATCH_AMBIGUOUS (~0u) #define HLP_MATCH_WILDCARD (~1U) #define HLP_MATCH_NONE 0 -static int matchHelpTopicName (TOPIC *topic, const char *token) { - size_t i, match; - char cbuf[CBUFSIZE], *cptr; +static int matchHelpTopicName (TOPIC *topic, const char *token) +{ +size_t i, match; +char cbuf[CBUFSIZE], *cptr; - if (!strcmp (token, "*")) { - return HLP_MATCH_WILDCARD; - } - match = 0; - for (i = 0; i < topic->kids; i++) { - strcpy (cbuf,topic->children[i]->title + - ((topic->children[i]->flags & HLP_MAGIC_TOPIC)? 1 : 0)); - cptr = cbuf; - while (*cptr) { - if (blankch (*cptr)) { - *cptr++ = '_'; - } else { - *cptr = toupper (*cptr); - cptr++; +if (!strcmp (token, "*")) + return HLP_MATCH_WILDCARD; + +match = 0; +for (i = 0; i < topic->kids; i++) { + strcpy (cbuf,topic->children[i]->title + + ((topic->children[i]->flags & HLP_MAGIC_TOPIC)? 1 : 0)); + cptr = cbuf; + while (*cptr) { + if (blankch (*cptr)) { + *cptr++ = '_'; + } + else { + *cptr = toupper (*cptr); + cptr++; } } - if (!strncmp (cbuf, token, strlen (token))) { - if (match) { - return HLP_MATCH_AMBIGUOUS; - } - match = i+1; + if (!strncmp (cbuf, token, strlen (token))) { + if (match) + return HLP_MATCH_AMBIGUOUS; + match = i+1; } } - return match; +return match; } /* Main help routine @@ -8404,234 +8402,230 @@ static int matchHelpTopicName (TOPIC *topic, const char *token) { t_stat scp_vhelp (FILE *st, struct sim_device *dptr, struct sim_unit *uptr, int32 flag, - const char *help, const char *cptr, va_list ap) { + const char *help, const char *cptr, va_list ap) +{ - TOPIC top = { 0, NULL, NULL, &top, NULL, 0, NULL, 0, 0}; - TOPIC *topic = ⊤ - int failed; - size_t match; - size_t i; - char *p; - t_bool flat_help = FALSE; - char cbuf [CBUFSIZE], gbuf[CBUFSIZE]; +TOPIC top = { 0, NULL, NULL, &top, NULL, 0, NULL, 0, 0}; +TOPIC *topic = ⊤ +int failed; +size_t match; +size_t i; +char *p; +t_bool flat_help = FALSE; +char cbuf [CBUFSIZE], gbuf[CBUFSIZE]; - static const char attach_help[] = { " ATTACH" }; - static const char brief_help[] = { "%s help. Type to exit, HELP for navigation help" }; - static const char onecmd_help[] = { "%s help." }; - static const char help_help[] = { - /****|***********************80 column width guide********************************/ - " This help command provides hierarchical help. To see more information,\n" - " type an offered subtopic name. To move back a level, just type .\n" - " To review the current topic/subtopic, type \"?\".\n" - " To view all subtopics, type \"*\".\n" - " To exit help at any time, type EXIT.\n" +static const char attach_help[] = { " ATTACH" }; +static const char brief_help[] = { "%s help. Type to exit, HELP for navigation help" }; +static const char onecmd_help[] = { "%s help." }; +static const char help_help[] = { + + /****|***********************80 column width guide********************************/ + " This help command provides hierarchical help. To see more information,\n" + " type an offered subtopic name. To move back a level, just type .\n" + " To review the current topic/subtopic, type \"?\".\n" + " To view all subtopics, type \"*\".\n" + " To exit help at any time, type EXIT.\n" }; - if ((failed = setjmp (help_env)) != 0) { - fprintf (stderr, "\nHelp was unable to process the help for this device.\n" - "Error in block %u line %u: %s\n" - "%s%*.*s%s" - " Please contact the device maintainer.\n", - (int)help_where.block, (int)help_where.line, help_where.error, - help_where.prox ? "Near '" : "", - help_where.prox ? 15 : 0, help_where.prox ? 15 : 0, - help_where.prox ? help_where.prox : "", - help_where.prox ? "'" : ""); - cleanHelp (&top); - return failed; +if ((failed = setjmp (help_env)) != 0) { + fprintf (stderr, "\nHelp was unable to process the help for this device.\n" + "Error in block %u line %u: %s\n" + "%s%*.*s%s" + " Please contact the device maintainer.\n", + (int)help_where.block, (int)help_where.line, help_where.error, + help_where.prox ? "Near '" : "", + help_where.prox ? 15 : 0, help_where.prox ? 15 : 0, + help_where.prox ? help_where.prox : "", + help_where.prox ? "'" : ""); + cleanHelp (&top); + return failed; } - /* Compile string into navigation tree */ +/* Compile string into navigation tree */ - /* Root */ +/* Root */ - if (dptr) { - p = dptr->name; - flat_help = (dptr->flags & DEV_FLATHELP) != 0; - } else { - p = sim_name; +if (dptr) { + p = dptr->name; + flat_help = (dptr->flags & DEV_FLATHELP) != 0; } - top.title = (char *) malloc (strlen (p) + ((flag & SCP_HELP_ATTACH)? sizeof (attach_help)-1: 0) +1); - for (i = 0; p[i]; i++ ) { - top.title[i] = toupper (p[i]); - } - top.title[i] = '\0'; - if (flag & SCP_HELP_ATTACH) { - strcpy (top.title+i, attach_help); +else + p = sim_name; +top.title = (char *) malloc (strlen (p) + ((flag & SCP_HELP_ATTACH)? sizeof (attach_help)-1: 0) +1); +for (i = 0; p[i]; i++ ) + top.title[i] = toupper (p[i]); +top.title[i] = '\0'; +if (flag & SCP_HELP_ATTACH) + strcpy (top.title+i, attach_help); + +top.label = (char *) malloc (sizeof ("1")); +strcpy (top.label, "1"); + +flat_help = flat_help || !sim_ttisatty() || (flag & SCP_HELP_FLAT); + +if (flat_help) { + flag |= SCP_HELP_FLAT; + if (sim_ttisatty()) + fprintf (st, "%s help.\nThis help is also available in hierarchical form.\n", top.title); + else + fprintf (st, "%s help.\n", top.title); } +else + fprintf (st, ((flag & SCP_HELP_ONECMD)? onecmd_help: brief_help), top.title); - top.label = (char *) malloc (sizeof ("1")); - strcpy (top.label, "1"); +/* Add text and subtopics */ - flat_help = flat_help || !sim_ttisatty() || (flag & SCP_HELP_FLAT); +(void) buildHelp (&top, dptr, uptr, help, ap); - if (flat_help) { - flag |= SCP_HELP_FLAT; - if (sim_ttisatty()) { - fprintf (st, "%s help.\nThis help is also available in hierarchical form.\n", top.title); - } else { - fprintf (st, "%s help.\n", top.title); +/* Go to initial topic if provided */ + +while (cptr && *cptr) { + cptr = get_glyph (cptr, gbuf, 0); + if (!gbuf[0]) + break; + if (!strcmp (gbuf, "HELP")) { /* HELP (about help) */ + fprintf (st, "\n"); + fputs (help_help, st); + break; } - } else { - fprintf (st, ((flag & SCP_HELP_ONECMD)? onecmd_help: brief_help), top.title); - } - - /* Add text and subtopics */ - - (void) buildHelp (&top, dptr, uptr, help, ap); - - /* Go to initial topic if provided */ - - while (cptr && *cptr) { - cptr = get_glyph (cptr, gbuf, 0); - if (!gbuf[0]) { - break; - } - if (!strcmp (gbuf, "HELP")) { /* HELP (about help) */ - fprintf (st, "\n"); - fputs (help_help, st); - break; - } - match = matchHelpTopicName (topic, gbuf); - if (match == HLP_MATCH_WILDCARD) { - displayFlatHelp (st, dptr, uptr, flag, topic, ap); - cleanHelp (&top); - return SCPE_OK; - } - if (match == HLP_MATCH_AMBIGUOUS) { - fprintf (st, "\n%s is ambiguous in %s\n", gbuf, topic->title); - break; - } - if (match == HLP_MATCH_NONE) { - fprintf (st, "\n%s is not available in %s\n", gbuf, topic->title); - break; - } - topic = topic->children[match-1]; - } - cptr = NULL; - - if (flat_help) { + match = matchHelpTopicName (topic, gbuf); + if (match == HLP_MATCH_WILDCARD) { displayFlatHelp (st, dptr, uptr, flag, topic, ap); cleanHelp (&top); return SCPE_OK; + } + if (match == HLP_MATCH_AMBIGUOUS) { + fprintf (st, "\n%s is ambiguous in %s\n", gbuf, topic->title); + break; + } + if (match == HLP_MATCH_NONE) { + fprintf (st, "\n%s is not available in %s\n", gbuf, topic->title); + break; + } + topic = topic->children[match-1]; } +cptr = NULL; - /* Interactive loop displaying help */ - - while (TRUE) { - char *pstring; - const char *prompt[2] = {"? ", "Subtopic? "}; - - /* Some magic topic names for help from data structures */ - - if (topic->flags & HLP_MAGIC_TOPIC) { - fputc ('\n', st); - displayMagicTopic (st, dptr, topic); - } else { - fprintf (st, "\n%s\n", topic->title); - } - - /* Topic text (for magic topics, follows for explanations) - * It's possible/reasonable for a magic topic to have no text. - */ - - if (topic->text) - fputs (topic->text, st); - - if (topic->kids) { - size_t w = 0; - char *p; - char tbuf[CBUFSIZE]; - - fprintf (st, "\n Additional information available:\n\n"); - for (i = 0; i < topic->kids; i++) { - strcpy (tbuf, topic->children[i]->title + - ((topic->children[i]->flags & HLP_MAGIC_TOPIC)? 1 : 0)); - for (p = tbuf; *p; p++) { - if (blankch (*p)) - *p = '_'; - } - w += 4 + topic->kidwid; - if (w > 80) { - w = 4 + topic->kidwid; - fputc ('\n', st); - } - fprintf (st, " %-*s", topic->kidwid, tbuf); - } - fprintf (st, "\n\n"); - if (flag & SCP_HELP_ONECMD) { - pstring = helpPrompt (topic, "", TRUE); - fprintf (st, "To view additional topics, type HELP %s topicname\n", pstring+1); - free (pstring); - break; - } - } - - if (!sim_ttisatty() || (flag & SCP_HELP_ONECMD)) - break; - - reprompt: - if (!cptr || !*cptr) { - pstring = helpPrompt (topic, prompt[topic->kids != 0], FALSE); - - cptr = read_line_p (pstring, cbuf, sizeof (cbuf), stdin); - free (pstring); - } - - if (!cptr) /* EOF, exit help */ - break; - - cptr = get_glyph (cptr, gbuf, 0); - if (!strcmp (gbuf, "*")) { /* Wildcard */ - displayFlatHelp (st, dptr, uptr, flag, topic, ap); - gbuf[0] = '\0'; /* Displayed all subtopics, go up */ - } - if (!gbuf[0]) { /* Blank, up a level */ - if (topic->level == 0) - break; - topic = topic->parent; - continue; - } - if (!strcmp (gbuf, "?")) { /* ?, repaint current topic */ - continue; - } - if (!strcmp (gbuf, "HELP")) { /* HELP (about help) */ - fputs (help_help, st); - goto reprompt; - } - if (!strcmp (gbuf, "EXIT") || !strcmp (gbuf, "QUIT")) { /* EXIT (help) */ - break; - } - - /* String - look for that topic */ - - if (!topic->kids) { - fprintf (st, "No additional help at this level.\n"); - cptr = NULL; - goto reprompt; - } - match = matchHelpTopicName (topic, gbuf); - if (match == HLP_MATCH_AMBIGUOUS) { - fprintf (st, "%s is ambiguous, please type more of the topic name\n", gbuf); - cptr = NULL; - goto reprompt; - } - - if (match == HLP_MATCH_NONE) { - fprintf (st, "Help for %s is not available\n", gbuf); - cptr = NULL; - goto reprompt; - } - /* Found, display subtopic */ - - topic = topic->children[match-1]; - } - - /* Free structures and return */ - +if (flat_help) { + displayFlatHelp (st, dptr, uptr, flag, topic, ap); cleanHelp (&top); - return SCPE_OK; + } + +/* Interactive loop displaying help */ + +while (TRUE) { + char *pstring; + const char *prompt[2] = {"? ", "Subtopic? "}; + + /* Some magic topic names for help from data structures */ + + if (topic->flags & HLP_MAGIC_TOPIC) { + fputc ('\n', st); + displayMagicTopic (st, dptr, topic); + } + else + fprintf (st, "\n%s\n", topic->title); + + /* Topic text (for magic topics, follows for explanations) + * It's possible/reasonable for a magic topic to have no text. + */ + + if (topic->text) + fputs (topic->text, st); + + if (topic->kids) { + size_t w = 0; + char *p; + char tbuf[CBUFSIZE]; + + fprintf (st, "\n Additional information available:\n\n"); + for (i = 0; i < topic->kids; i++) { + strcpy (tbuf, topic->children[i]->title + + ((topic->children[i]->flags & HLP_MAGIC_TOPIC)? 1 : 0)); + for (p = tbuf; *p; p++) { + if (blankch (*p)) + *p = '_'; + } + w += 4 + topic->kidwid; + if (w > 80) { + w = 4 + topic->kidwid; + fputc ('\n', st); + } + fprintf (st, " %-*s", topic->kidwid, tbuf); + } + fprintf (st, "\n\n"); + if (flag & SCP_HELP_ONECMD) { + pstring = helpPrompt (topic, "", TRUE); + fprintf (st, "To view additional topics, type HELP %s topicname\n", pstring+1); + free (pstring); + break; + } + } + + if (!sim_ttisatty() || (flag & SCP_HELP_ONECMD)) + break; + + reprompt: + if (!cptr || !*cptr) { + pstring = helpPrompt (topic, prompt[topic->kids != 0], FALSE); + + cptr = read_line_p (pstring, cbuf, sizeof (cbuf), stdin); + free (pstring); + } + + if (!cptr) /* EOF, exit help */ + break; + + cptr = get_glyph (cptr, gbuf, 0); + if (!strcmp (gbuf, "*")) { /* Wildcard */ + displayFlatHelp (st, dptr, uptr, flag, topic, ap); + gbuf[0] = '\0'; /* Displayed all subtopics, go up */ + } + if (!gbuf[0]) { /* Blank, up a level */ + if (topic->level == 0) + break; + topic = topic->parent; + continue; + } + if (!strcmp (gbuf, "?")) /* ?, repaint current topic */ + continue; + if (!strcmp (gbuf, "HELP")) { /* HELP (about help) */ + fputs (help_help, st); + goto reprompt; + } + if (!strcmp (gbuf, "EXIT") || !strcmp (gbuf, "QUIT")) /* EXIT (help) */ + break; + + /* String - look for that topic */ + + if (!topic->kids) { + fprintf (st, "No additional help at this level.\n"); + cptr = NULL; + goto reprompt; + } + match = matchHelpTopicName (topic, gbuf); + if (match == HLP_MATCH_AMBIGUOUS) { + fprintf (st, "%s is ambiguous, please type more of the topic name\n", gbuf); + cptr = NULL; + goto reprompt; + } + + if (match == HLP_MATCH_NONE) { + fprintf (st, "Help for %s is not available\n", gbuf); + cptr = NULL; + goto reprompt; + } + /* Found, display subtopic */ + + topic = topic->children[match-1]; + } + +/* Free structures and return */ + +cleanHelp (&top); + +return SCPE_OK; } /* variable argument list shell - most commonly used @@ -8639,15 +8633,16 @@ t_stat scp_vhelp (FILE *st, struct sim_device *dptr, t_stat scp_help (FILE *st, struct sim_device *dptr, struct sim_unit *uptr, int32 flag, - const char *help, const char *cptr, ...) { - t_stat r; - va_list ap; + const char *help, const char *cptr, ...) +{ +t_stat r; +va_list ap; - va_start (ap, cptr); - r = scp_vhelp (st, dptr, uptr, flag, help, cptr, ap); - va_end (ap); +va_start (ap, cptr); +r = scp_vhelp (st, dptr, uptr, flag, help, cptr, ap); +va_end (ap); - return r; +return r; } #if 01 @@ -8661,108 +8656,111 @@ t_stat scp_help (FILE *st, struct sim_device *dptr, t_stat scp_vhelpFromFile (FILE *st, struct sim_device *dptr, struct sim_unit *uptr, int32 flag, const char *helpfile, - const char *cptr, va_list ap) { - FILE *fp; - char *help, *p; - t_offset size, n; - int c; - t_stat r; + const char *cptr, va_list ap) +{ +FILE *fp; +char *help, *p; +t_offset size, n; +int c; +t_stat r; - fp = sim_fopen (helpfile, "r"); - if (fp == NULL) { - if (sim_argv && *sim_argv[0]) { - char fbuf[(4*PATH_MAX)+1]; /* PATH_MAX is ridiculously small on some platforms */ - char *d = NULL; +fp = sim_fopen (helpfile, "r"); +if (fp == NULL) { + if (sim_argv && *sim_argv[0]) { + char fbuf[(4*PATH_MAX)+1]; /* PATH_MAX is ridiculously small on some platforms */ + char *d = NULL; - /* Try to find a path from argv[0]. This won't always - * work (one reason files are probably not a good idea), - * but we might as well try. Some OSs won't include a - * path. Having failed in the CWD, try to find the location - * of the executable. Failing that, try the 'help' subdirectory - * of the executable. Failing that, we're out of luck. - */ - strncpy (fbuf, sim_argv[0], sizeof (fbuf)); - if ((p = match_ext (fbuf, "EXE"))) { - *p = '\0'; - } - if ((p = strrchr (fbuf, '\\'))) { + /* Try to find a path from argv[0]. This won't always + * work (one reason files are probably not a good idea), + * but we might as well try. Some OSs won't include a + * path. Having failed in the CWD, try to find the location + * of the executable. Failing that, try the 'help' subdirectory + * of the executable. Failing that, we're out of luck. + */ + strncpy (fbuf, sim_argv[0], sizeof (fbuf)); + if ((p = match_ext (fbuf, "EXE"))) + *p = '\0'; + if ((p = strrchr (fbuf, '\\'))) { + p[1] = '\0'; + d = "%s\\"; + } + else { + if ((p = strrchr (fbuf, '/'))) { p[1] = '\0'; - d = "%s\\"; - } else { - if ((p = strrchr (fbuf, '/'))) { - p[1] = '\0'; - d = "%s/"; + d = "%s/"; #ifdef VMS - } else { - if ((p = strrchr (fbuf, ']'))) { - p[1] = '\0'; - d = "[%s]"; + } + else { + if ((p = strrchr (fbuf, ']'))) { + p[1] = '\0'; + d = "[%s]"; } #endif } } - if (p && (strlen (fbuf) + strlen (helpfile) +1) <= sizeof (fbuf)) { - strcat (fbuf, helpfile); - fp = sim_fopen (fbuf, "r"); + if (p && (strlen (fbuf) + strlen (helpfile) +1) <= sizeof (fbuf)) { + strcat (fbuf, helpfile); + fp = sim_fopen (fbuf, "r"); } - if (!fp && p && (strlen (fbuf) + strlen (d) + sizeof ("help") + - strlen (helpfile) +1) <= sizeof (fbuf)) { - sprintf (p+1, d, "help"); - strcat (p+1, helpfile); - fp = sim_fopen (fbuf, "r"); + if (!fp && p && (strlen (fbuf) + strlen (d) + sizeof ("help") + + strlen (helpfile) +1) <= sizeof (fbuf)) { + sprintf (p+1, d, "help"); + strcat (p+1, helpfile); + fp = sim_fopen (fbuf, "r"); } } } - if (fp == NULL) { - fprintf (stderr, "Unable to open %s\n", helpfile); - return SCPE_UNATT; +if (fp == NULL) { + fprintf (stderr, "Unable to open %s\n", helpfile); + return SCPE_UNATT; } - size = sim_fsize_ex (fp); /* Estimate; line endings will vary */ - - help = (char *) malloc ((size_t) size +1); - if (!help) { - fclose (fp); - return SCPE_MEM; - } - p = help; - n = 0; - - while ((c = fgetc (fp)) != EOF) { - if (++n > size) { -#define XPANDQ 512 - p = (char *) realloc (help, ((size_t)size) + XPANDQ +1); - if (!p) { - free (help); - fclose (fp); - return SCPE_MEM; - } - help = p; - size += XPANDQ; - p += n; - } - *p++ = c; - } - *p++ = '\0'; +size = sim_fsize_ex (fp); /* Estimate; line endings will vary */ +help = (char *) malloc ((size_t) size +1); +if (!help) { fclose (fp); + return SCPE_MEM; + } +p = help; +n = 0; - r = scp_vhelp (st, dptr, uptr, flag, help, cptr, ap); - free (help); +while ((c = fgetc (fp)) != EOF) { + if (++n > size) { +#define XPANDQ 512 + p = (char *) realloc (help, ((size_t)size) + XPANDQ +1); + if (!p) { + free (help); + fclose (fp); + return SCPE_MEM; + } + help = p; + size += XPANDQ; + p += n; + } + *p++ = c; + } +*p++ = '\0'; - return r; +fclose (fp); + +r = scp_vhelp (st, dptr, uptr, flag, help, cptr, ap); +free (help); + +return r; } t_stat scp_helpFromFile (FILE *st, struct sim_device *dptr, struct sim_unit *uptr, int32 flag, - const char *helpfile, const char *cptr, ...) { - t_stat r; - va_list ap; + const char *helpfile, const char *cptr, ...) +{ +t_stat r; +va_list ap; - va_start (ap, cptr); - r = scp_vhelpFromFile (st, dptr, uptr, flag, helpfile, cptr, ap); - va_end (ap); +va_start (ap, cptr); +r = scp_vhelpFromFile (st, dptr, uptr, flag, helpfile, cptr, ap); +va_end (ap); - return r; +return r; } #endif