delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2000/07/08/17:31:00

Sender: rich AT phekda DOT freeserve DOT co DOT uk
Message-ID: <396792CB.85E1BCDE@phekda.freeserve.co.uk>
Date: Sat, 08 Jul 2000 21:44:59 +0100
From: Richard Dawe <rich AT phekda DOT freeserve DOT co DOT uk>
X-Mailer: Mozilla 4.51 [en] (X11; I; Linux 2.2.14 i586)
X-Accept-Language: de,fr
MIME-Version: 1.0
To: DJGPP workers <djgpp-workers AT delorie DOT com>
Subject: mkdoc patch, take 2
Reply-To: djgpp-workers AT delorie DOT com

This is a multi-part message in MIME format.
--------------606FDF1B771A43BACB82D4B1
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hello.

Please find attached revision two of my mkdoc patch. Attached are a diff
for mkdoc.cc, wc204.txi and a new sample file, to show the new features
off.

The distinction between C89 and C99 is a special case of a more general
problem, so I decided to rework the way the portability info is done, in a
backwards-compatible way. Here's how the new system works. The whole thing
is table-driven. Each portability target has several "qualifiers". So
there's an ANSI ISO/C target "ansi", for which there are qualifiers
"-c89", "-c99". Each target has a default status for each qualifier, so if
you just use:

@portability ansi

it defaults to C89 portability. You could have:

@portability ansi-c89, !ansi-c99

The portability notes can refer to a whole target, or to individual
qualifiers, e.g:

@port-note ansi-c89 Blah blah blah
@port-note ansi-c99 Yadda yadda yadda

We now have a "unix" target, which has the qualifier "98" for
Unix98/SUSv2:

@portability unix98

We might want to add 4.2BSD or 4.4BSD too, e.g. unix-4.2-bsd,
unix-4.4-bsd.

Here's an example of the output, from sample2.txh:

    Portability
    -----------

    ANSI/ISO C   not C89 (see note 1); not C99
    POSIX        1003.2-1992 (see note 2)
    Unix         Unix98 (partial) (see note 3)

    Notes:

      1. You must be joking!

      2. Perhaps this can be put into the combined POSIX & Unix98 combined
         standard? Hmm, maybe not.

      3. Naah, only joking.

Of course, the distinction between C89 and C99 means that what was
previously one entry per row is now back to the multiple entries per row,
which I caused me to suggest changing in mkdoc in the first place. Ah
well. ;)

I have a couple of questions:

1. When producing @multitable in texinfo, is there an easy way to make a
column consume the rest of the table? The problem here is that we have a
2-column table. The left-hand column's width can be calculated easily, but
the right column should use the remaining space. I have a hack based on an
assumption of 80-columns width.

2. With the default qualifiers for the ansi target, C89 compatibility is
set to yes, but C99 is set to unknown. Should the unknown part be
displayed in the portability? I think this could be confusing for users.

A couple of other improvements for mkdoc spring to mind:

1. Add an option to dump out the table of targets and their qualifiers.
2. Make @port-note be a multi-line @ command, e.g.

@port-note ansi
This
uses
four
lines.
@end port-note

or:

@port-note ansi {This uses one line.}

Thanks, bye, Rich =]

-- 
Richard Dawe
[ mailto:richdawe AT bigfoot DOT com | http://www.bigfoot.com/~richdawe/ ]
--------------606FDF1B771A43BACB82D4B1
Content-Type: text/plain; charset=us-ascii;
 name="mkdoc3-2.cc.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="mkdoc3-2.cc.diff"

*** mkdoc.cc.orig	Mon Jul  3 21:48:59 2000
--- mkdoc3.cc	Sat Jul  8 18:11:32 2000
***************
*** 1,3 ****
--- 1,4 ----
+ /* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */
***************
*** 29,47 ****
  
  typedef void (*TFunc)(Node *);
  
! 
! #define NUM_PORT_TARGETS 2
  
  #define PORT_UNKNOWN 0
  #define PORT_NO      1
  #define PORT_PARTIAL 2
  #define PORT_YES     3
  
! /* Tokens for use in .txh files */
! char *port_target[NUM_PORT_TARGETS] = { "ansi", "posix" };
! /* Strings to output in .txi files */
! char *port_target_string[NUM_PORT_TARGETS] = { "ANSI", "POSIX" };
! 
  
  struct Tree {
    TreeNode *nodes;
--- 30,94 ----
  
  typedef void (*TFunc)(Node *);
  
! #define PORT_TARGET_NONE              0x00
! /* ANSI/ISO C */
! #define PORT_TARGET_ANSI_C89          0x10
! #define PORT_TARGET_ANSI_C99          0x11
! /* POSIX */
! #define PORT_TARGET_POSIX_1003_2_1992 0x20
! /* Single Unix Specification(s) (SUS) */
! #define PORT_TARGET_UNIX_98           0x30
  
  #define PORT_UNKNOWN 0
  #define PORT_NO      1
  #define PORT_PARTIAL 2
  #define PORT_YES     3
  
! /* This structure is used to store both the default information about a
!  * particular porting target and the information parsed from the texinfo.
!  * For the default case, complete specifies the default value for this
!  * qualifier if the prefix is matched, but the suffix is not. */
! typedef struct {
!   char *suffix_token;  /* Suffix token used in texinfo, e.g. 'c89' */
!   char *suffix_name;   /* Portability qualifier name, e.g. C89 */
!   int target;          /* One of PORT_TARGET_* */
!   int complete;        /* One of PORT_UNKNOWN, etc. */
! } PortQualifier;
! 
! #define MAX_PORT_QUALIFIERS 2
! 
! typedef struct {
!   char *prefix_token; /* Token used in texinfo, e.g. 'ansi' */
!   char *prefix_name;  /* Actual textual name for token, e.g. ANSI/ISO C */
!   PortQualifier pq[MAX_PORT_QUALIFIERS];
! } PortInfo;
! 
! #define NUM_PORT_TARGETS    3
! 
! PortInfo port_target[] = {
!   /* ANSI/ISO C */
!   { "ansi",  "ANSI/ISO C",
!     {
!       { "-c89", "C89", PORT_TARGET_ANSI_C89, PORT_YES     },
!       { "-c99", "C99", PORT_TARGET_ANSI_C99, PORT_UNKNOWN }
!     }
!   },
!   /* POSIX */
!   { "posix", "POSIX",
!     {
!       { "-1003.2-1992", "1003.2-1992",
! 	PORT_TARGET_POSIX_1003_2_1992, PORT_YES },
!       { 0 }
!     }
!   },
!   /* SUS */
!   { "unix",  "Unix",
!     {
!       { "98", "Unix98", PORT_TARGET_UNIX_98, PORT_UNKNOWN },
!       { 0 }
!     }
!   }
! };
  
  struct Tree {
    TreeNode *nodes;
***************
*** 59,65 ****
  
  struct PortNote {
    struct PortNote *next;
!   int target;
    int number;
    char *note;
  };
--- 106,113 ----
  
  struct PortNote {
    struct PortNote *next;
!   PortInfo *pi;
!   PortQualifier *pq;
    int number;
    char *note;
  };
***************
*** 73,79 ****
    Line *lastline;
    Tree subnodes;
    char *filename;
!   int port_info[NUM_PORT_TARGETS];
    PortNote *port_notes;
    PortNote *last_port_note;
    Node(char *name, char *cat);
--- 121,127 ----
    Line *lastline;
    Tree subnodes;
    char *filename;
!   PortInfo port_info[NUM_PORT_TARGETS];
    PortNote *port_notes;
    PortNote *last_port_note;
    Node(char *name, char *cat);
***************
*** 107,113 ****
    cat = strdup(Pcat);
    lines = 0;
    lastline = 0;
!   for (int i = 0; i < NUM_PORT_TARGETS; i++) port_info[i] = PORT_UNKNOWN;
    port_notes = NULL;
    last_port_note = NULL;
  }
--- 155,162 ----
    cat = strdup(Pcat);
    lines = 0;
    lastline = 0;
!   for (int i = 0; i < NUM_PORT_TARGETS; i++)
!     bzero(&port_info[i], sizeof(port_info[i]));
    port_notes = NULL;
    last_port_note = NULL;
  }
***************
*** 151,159 ****
  Node::read_portability_note(char *str)
  {
    char *work_str = strdup (str);
!   char *s = work_str;
    char *target;
!   int targ_num;
  
    while (isspace(*s)) s++;
    target = s;
--- 200,208 ----
  Node::read_portability_note(char *str)
  {
    char *work_str = strdup (str);
!   char *s = work_str, *x = NULL;
    char *target;
!   int i, j;
  
    while (isspace(*s)) s++;
    target = s;
***************
*** 162,182 ****
    while (isspace(*s)) s++;
    dj_strlwr (target);
  
!   for (targ_num = 0; targ_num < NUM_PORT_TARGETS; targ_num++)
!     if (!strcmp (target, port_target[targ_num])) break;
  
!   if (targ_num == NUM_PORT_TARGETS)
!   {
      error ("unrecognised portability note target `%s' ignored.\n", target);
!   }
!   else
!   {
      PortNote *p = new PortNote;
      p->next = NULL;
      p->number = 0;
!     p->target = targ_num;
      p->note = strdup ("");
  
      if (port_notes)
      {
        last_port_note->next = p;
--- 211,245 ----
    while (isspace(*s)) s++;
    dj_strlwr (target);
  
!   for (i = 0; i < NUM_PORT_TARGETS; i++) {
!     if (   (strlen (target) >= strlen (port_target[i].prefix_token))
! 	&& !strncmp (target, port_target[i].prefix_token,
! 		     strlen (port_target[i].prefix_token)))
!       break;
!   }
  
!   if (i == NUM_PORT_TARGETS) {
      error ("unrecognised portability note target `%s' ignored.\n", target);
!   } else {
      PortNote *p = new PortNote;
      p->next = NULL;
      p->number = 0;
!     p->pi = &port_target[i];
!     p->pq = NULL;
      p->note = strdup ("");
+     
+     /* Try to match the portability note to a portability qualifier. */
+     x = target + strlen (p->pi->prefix_token);
+ 
+     for (j = 0; j < MAX_PORT_QUALIFIERS; j++) {
+       if (port_target[i].pq[j].suffix_token == NULL) continue;
+       if (!strcmp (x, port_target[i].pq[j].suffix_token)) break;
+     }
+ 
+     if (j < MAX_PORT_QUALIFIERS)
+       p->pq = &p->pi->pq[j];
  
+     /* Attach portability note to note chain. */
      if (port_notes)
      {
        last_port_note->next = p;
***************
*** 196,203 ****
  Node::read_portability(char *str)
  {
    char *targets = dj_strlwr (strdup (str));
!   char *x, *target = targets;
!   int type,i;
  
    while (isspace (*target)) target++;
    while (*target) {
--- 259,266 ----
  Node::read_portability(char *str)
  {
    char *targets = dj_strlwr (strdup (str));
!   char *p = NULL, *x = NULL, *target = targets;
!   int type, i, j;
  
    while (isspace (*target)) target++;
    while (*target) {
***************
*** 217,228 ****
      if (*x) *x++ = 0;
  
      for (i = 0; i < NUM_PORT_TARGETS; i++)
!       if (!strcmp (target, port_target[i])) break;
  
!     if (i < NUM_PORT_TARGETS)
!       port_info[i] = type;
!     else
        error ("unrecognised portability target `%s' ignored.\n", target);
  
      target = x;
      while (isspace (*target)) target++;
--- 280,310 ----
      if (*x) *x++ = 0;
  
      for (i = 0; i < NUM_PORT_TARGETS; i++)
!       if (   (strlen (target) >= strlen (port_target[i].prefix_token))
! 	  && !strncmp (target, port_target[i].prefix_token,
! 		       strlen (port_target[i].prefix_token)))
! 	break;
  
!     if (i < NUM_PORT_TARGETS) {
!       /* Now match the portability qualifier, if present. */
!       p  = target + strlen (port_target[i].prefix_token);
! 
!       if (port_info[i].prefix_name == NULL) {
! 	/* Copy default portability information to uninitialised port
! 	 * info, qualifier list. */
! 	memcpy(&port_info[i], &port_target[i], sizeof(port_target[i]));
!       }
! 
!       for (j = 0; j < MAX_PORT_QUALIFIERS; j++) {
! 	if (port_target[i].pq[j].suffix_token == NULL) continue;
! 	if (!strcmp (p, port_target[i].pq[j].suffix_token)) break;
!       }
! 
!       if (j < NUM_PORT_TARGETS)
! 	port_info[i].pq[j].complete = type;
!     } else {
        error ("unrecognised portability target `%s' ignored.\n", target);
+     }
  
      target = x;
      while (isspace (*target)) target++;
***************
*** 233,263 ****
  
  void
  Node::write_portability()
! {
    char buffer[1024] = { 0 };
    int note_number = 1;
  
!   for (int i = 0; i < NUM_PORT_TARGETS; i++)
!   {
!     switch (port_info[i])
      {
        case PORT_NO:
  	strcat (buffer, "not ");
! 	strcat (buffer, port_target_string[i]);
  	break;
        case PORT_YES:
! 	strcat (buffer, port_target_string[i]);
  	break;
        case PORT_PARTIAL:
! 	strcat (buffer, "partially ");
! 	strcat (buffer, port_target_string[i]);
  	break;
!     }
!     if (port_info[i] != PORT_UNKNOWN)
!     {
!       for (PortNote *p = port_notes; p; p = p->next)
        {
! 	if (p->target == i)
  	{
  	  char smallbuffer[20];
  	  p->number = note_number++;
--- 315,409 ----
  
  void
  Node::write_portability()
! {  
!   /* Column-width calculation variables */
!   size_t maxsize = 0;
!   ssize_t size = 0;
!   static int largest_target = -1;
!   static char rightpad[80] = { 0 };
! 
    char buffer[1024] = { 0 };
+   int qualifier_number = 0;
+   PortNote *p = NULL;
    int note_number = 1;
+   int i, j;
  
!   /* Deduce the largest target name length, for table's left-hand column. */
!   if (largest_target == -1)
!   {    
!     for (i = 0; i < NUM_PORT_TARGETS; i++)
      {
+       if (strlen(port_target[i].prefix_name) > maxsize)
+       {
+ 	maxsize = strlen(port_target[i].prefix_name);
+ 	largest_target = i;
+       }
+     }
+   }
+ 
+   /* Make the right-hand column 80 columns less the left-hand column width,
+    * less some more for safety. */
+   if (rightpad[0] == '\0') {
+     size = sizeof(rightpad) - maxsize - 10;
+     if (size > 0) memset(rightpad, (int) 'x', size);
+   }
+ 
+   strcat (buffer, "@multitable {");
+   strcat (buffer, port_target[largest_target].prefix_name);
+   strcat (buffer, "} {");  
+   strcat (buffer, rightpad);
+   strcat (buffer, "}\n");
+ 
+   for (i = 0; i < NUM_PORT_TARGETS; i++)
+   {
+     strcat (buffer, "@item ");
+     strcat (buffer, port_target[i].prefix_name);
+     strcat (buffer, " @tab ");
+ 
+     for (qualifier_number = j = 0; j < MAX_PORT_QUALIFIERS; j++) {
+       /* No information given => unknown. */
+       if (port_info[i].prefix_name == NULL) {
+ 	strcat (buffer, "Unknown");
+ 	break;
+       }
+ 
+       if (port_info[i].pq[j].suffix_name == NULL) continue;
+ 
+       switch (port_info[i].pq[j].complete)
+       {
        case PORT_NO:
+       case PORT_YES:
+       case PORT_PARTIAL:
+ 	qualifier_number++;
+ 	if (qualifier_number > 1) strcat (buffer, "; ");
+ 	break;
+       default:
+ 	break;
+       }
+       
+       switch (port_info[i].pq[j].complete)
+       {
+       case PORT_NO:	
  	strcat (buffer, "not ");
! 	strcat (buffer, port_info[i].pq[j].suffix_name);
  	break;
        case PORT_YES:
! 	strcat (buffer, port_info[i].pq[j].suffix_name);
  	break;
        case PORT_PARTIAL:
! 	strcat (buffer, port_info[i].pq[j].suffix_name);
! 	strcat (buffer, " (partial)");
  	break;
!       default:	
! 	break;
!       }
! 
!       /* Attach any qualifier-specific portability notes. */
!       for (p = port_notes; p; p = p->next)
        {
! 	if (   !strcmp (p->pi->prefix_token, port_info[i].prefix_token)
! 	    && (p->pq != NULL)
! 	    && !strcmp (p->pq->suffix_token, port_info[i].pq[j].suffix_token))
  	{
  	  char smallbuffer[20];
  	  p->number = note_number++;
***************
*** 266,284 ****
  	  break;
  	}
        }
-       strcat (buffer, ", ");
      }
-   }
  
!   {
!     char *ch = strchr (buffer, 0) - 2;
!     if (*ch == ',')
!       *ch = 0;
!     else
!       strcpy (buffer, "Unknown.");
    }
  
!   strcat (buffer, "\n\n");
    add(buffer);
  
    if (note_number > 1)
--- 412,439 ----
  	  break;
  	}
        }
      }
  
!     /* Attach any target-specific portability notes. */
!     for (p = port_notes; p; p = p->next)
!     {
!       if (   (port_info[i].prefix_token != NULL)
! 	  && !strcmp (p->pi->prefix_token, port_info[i].prefix_token)
! 	  && (p->pq == NULL))
!       {
! 	char smallbuffer[20];
! 	p->number = note_number++;
! 	sprintf (smallbuffer, " (see note %d)", p->number);
! 	strcat (buffer, smallbuffer);
! 	break;
!       }
!     }
! 
!     strcat (buffer, "\n");
    }
  
!   strcat (buffer, "@end multitable\n\n");
! 
    add(buffer);
  
    if (note_number > 1)
***************
*** 288,294 ****
      add("\n");
      add("@enumerate\n");
  
!     for (int i = 1; i < note_number; i++)
      {
        add("@item\n");
        for (PortNote *p = port_notes; p; p = p->next)
--- 443,449 ----
      add("\n");
      add("@enumerate\n");
  
!     for (i = 1; i < note_number; i++)
      {
        add("@item\n");
        for (PortNote *p = port_notes; p; p = p->next)
***************
*** 495,501 ****
    Node *curnode;
    DIR *d = opendir(which);
    struct dirent *de;
!   while (de = readdir(d))
    {
      if (de->d_name[0] == '.')
        continue;
--- 650,656 ----
    Node *curnode;
    DIR *d = opendir(which);
    struct dirent *de;
!   while ((de = readdir(d)) != NULL)
    {
      if (de->d_name[0] == '.')
        continue;


--------------606FDF1B771A43BACB82D4B1
Content-Type: text/plain; charset=us-ascii;
 name="wc204.txi.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="wc204.txi.diff"

*** wc204.txi.orig	Mon Jul  3 21:52:28 2000
--- wc204.txi	Mon Jul  3 21:57:21 2000
***************
*** 54,56 ****
--- 54,59 ----
  @findex fsdb AT r{, check for EXE extension}
  @code{fsdb} checks for executables and loads them even if
  the extension @file{.exe} isn't given in the command line.
+ 
+ The portability information in the library documentation is now presented in
+ tabular form, for easier interpretation.


--------------606FDF1B771A43BACB82D4B1
Content-Type: text/plain; charset=us-ascii;
 name="sample2.txh"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="sample2.txh"

@c ----------------------------------------------------------------------
@node gesticulate, officelib
@subheading Syntax

@example
#include <officelib.h>

int gesticulate(int wildly);
@end example

@subheading Description

When you call @code{gesticulate}, an Office Assistant appears, in order to
help you debug your OfficeScript scripts by using indicative gestures while
whispering soothing words of advice. If it's particularly late at night,
it may be useful to use the @var{wildly} parameter to make its intent
more obvious. Alternatively, a black coffee or Jolt Cola may increase
your awareness, so as to make the @var{wildly} option unnecessary.

@subheading Return Value

This function returns zero on success or non-zero if it fails. The error is
stored in @var{oerrno} - possible errors are:

@table @samp
@item EAGAIN
It's too late - the Office Assistant is asleep.
@item EBUSY
The Office Assistant isn't back from the pub yet.
@item ECHILD
You're too young to be debugging at this time of night!
@item ENODEV
The Office Assistant has no arms to gesticulate with.
@item ENOENT
The Office Assistant discovered that no bugs exist in your code. You're being
paranoid!
@end table

@subheading Portability

@port-note ansi-c89 You must be joking!
@port-note posix Perhaps this can be put into the combined POSIX & Unix98 combined standard? Hmm, maybe not.
@port-note unix98 Naah, only joking.

@portability !ansi-c89, !ansi-c99, !posix, ~unix98

@subheading Example

@example
if (gesticulate() == -1) @{
    oerror("crashnburn");
    GPF();
@}
@end example



--------------606FDF1B771A43BACB82D4B1--

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019