Why auto generate a c header file?



The following is part of some kind of chat line program for FreeBSD.

/*opttab.c*/
#include "party.h"

/* This is the table of options available in the party program.
* Note that all channel options must be first, followed by all
* system options, and then all user options.
*/

struct optent opt[] = {

/* All PF_CHN options must be first. These are always reset
to their
* default values before entering a new channel. They are
normally
* the only ones you would be setting in the chantab.
*/

{ "askname", PF_CHN|PF_NO, 0, NULL },
{ "chanintro", PF_CHN|PF_NO|PF_STR, 0, "" },
{ "keeplog", PF_CHN|PF_NO|PF_SHOW, 0, NULL},
{ "idleout", PF_CHN|PF_NO|PF_STR|PF_NUM, 0,
DFLT_IDLEOUT },
{ "makenoise", PF_CHN|PF_NO|PF_STR|PF_SHOW, 1,
DFLT_MAKENOISE },
{ "mapname", PF_CHN|PF_NO|PF_STR, 0, "" },
#ifndef NOCLOSE
{ "mayclose", PF_CHN|PF_NO|PF_SHOW, 0, NULL},
#endif
{ "readlim", PF_CHN|PF_STR|PF_NUM|PF_SHOW, 0,
DFLT_READLIM },
{ "rename", PF_CHN|PF_NO|PF_SHOW, 0, NULL },
{ "randname", PF_CHN|PF_NO|PF_STR, 0, "" },
{ "uidname", PF_CHN|PF_NO, 1, NULL },
{ "uniquename", PF_CHN|PF_NO, 1, NULL },

/* The options below are set only in the partytab */

{ "chantab", PF_SYS|PF_STR, 1, DFLT_CHANTAB },
{ "dir", PF_SYS|PF_STR, 1, DFLT_DIR },
{ "userlist", PF_SYS|PF_NO, 0, NULL },
{ "whofile", PF_SYS|PF_STR, 1, DFLT_WHOFILE },
{ "capacity", PF_SYS|PF_NO|PF_STR|PF_NUM, 0,
DFLT_CAPACITY },

/* The options below are set by the user or in the partytab */

{ "alias", PF_STR|PF_SHOW, 1, NULL },
{ "arg", PF_NO, 1, NULL },
{ "bs", PF_NO|PF_SEE|PF_SHOW, 1, NULL },
{ "back", PF_NUM|PF_STR, 1, DFLT_BACK },
{ "cols", PF_NUM|PF_STR|PF_SHOW, 1, DFLT_COLS },
{ "colon", PF_NO, 1, NULL },
{ "control", PF_NO|PF_SEE|PF_SHOW, 1, NULL },
{ "debug", PF_NO|PF_STR, 0, DFLT_DEBUG },
{ "env", PF_NO, 1, NULL },
{ "fastshell", PF_NO|PF_SHOW, 1, NULL },
{ "filter", PF_STR|PF_NO|PF_SHOW, 1, DFLT_FILTER },
{ "firstchar", PF_NO|PF_SHOW, 0, NULL },
{ "fullmesg", PF_STR, 1,
DFLT_FULLMESG },
{ "help", PF_NO|PF_STR, 1, DFLT_HELP },
{ "intro", PF_STR, 1, DFLT_INTRO },
#ifndef NOCLOSE
{ "knockwait", PF_NUM|PF_STR, 1,
DFLT_KNOCKWAIT },
#endif
{ "maildir", PF_STR|PF_SHOW, 1, DFLT_MAILDIR },
{ "prompt", PF_STR, 1, DFLT_PROMPT },
{ "raw", PF_NO, 0, NULL },
{ "repeat", PF_NO|PF_SHOW, 1, NULL },
{ "shell", PF_NO|PF_STR|PF_SHOW, 1, DFLT_SHELL },
{ "shownoise", PF_NO|PF_SHOW, 1, NULL },
{ "showread", PF_NO|PF_SHOW, 1, NULL },
{ "showevent", PF_NO|PF_SHOW, 1, NULL },
{ "spaceonly", PF_NO|PF_STR, 0,
DFLT_SPACEONLY },
{ "start", PF_STR, 1, DFLT_START },
{ "tpmorp", PF_STR, 1, DFLT_TPMORP },
{ "wrap", PF_NO|PF_SHOW|PF_STR|PF_NUM, 0, "10" },

/* This marks the end of the option list */

{ NULL, 0, 0, NULL } };


/* This is the table of commands recognized at the colon prompt. They
need
* be in no partitular order. The numbers are the minimum length that
is
* recognized as an abbreviation of the command.
*/

struct cmdent cmd[] = {
{"back", 1},
{"chantab", 1},
#ifndef NOCLOSE
{"close", 2},
#endif
{"help", 1},
#ifndef NOIGNORE
{"ignore", 2},
#endif
#ifndef NOCLOSE
{"invite", 2},
#endif
{"join", 1},
{"list", 1},
{"name", 1},
{"noises", 3},
#ifndef NOIGNORE
{"notice", 3},
#endif
#ifndef NOCLOSE
{"open", 1},
#endif
{"print", 1},
{"pwho", 2},
{"quit", 1},
{"read", 1},
{"save", 2},
{"set", 1},
{"shell", 2},
{"version", 1},
{"who", 1},
/* This marks the end of the command list */
{ NULL, 0}};


/*makeopt.c*/
#include <stdio.h>
#include "party.h"

void define(char *prefix, char *string, int val)
{
char *p;

printf("#define %s_",prefix);
for (p=string;*p;p++)
if (islower(*p))
putchar(toupper(*p));
else
putchar(*p);
if (strlen(string) < 4) putchar('\t');
printf("\t%d\n",val);
}

main()
{
int i;
int chn_done = 0;

printf("/* Don't bother editing this file.\n");
printf(" * It is generated from opttab.c by the makeopt program.
\n");
printf(" */\n\n");

/* Print the option defines */

printf("#define OPT_NONE\t-1\n");
for (i=0;opt[i].name;i++)
{
if (!chn_done && !(opt[i].pf & PF_CHN))
{
printf("#define NCOPT\t\t%d\n",i);
chn_done=1;
}

define("OPT",opt[i].name,i);
}
printf("#define NOPT\t\t%d\n",i);

/* Print the command defines */

for (i=0;cmd[i].name;i++)
define("CMD",cmd[i].name,i);

printf("#define NCMD\t\t%d\n",i);

exit(0);
}

This produces a header called opt.h. The header file looks like the
following:
/* Don't bother editing this file.
* It is generated from opttab.c by the makeopt program.
*/

#define OPT_NONE -1
#define OPT_ASKNAME 0
#define OPT_CHANINTRO 1
#define OPT_KEEPLOG 2
#define OPT_IDLEOUT 3
#define OPT_MAKENOISE 4
#define OPT_MAPNAME 5
#define OPT_MAYCLOSE 6
#define OPT_READLIM 7
#define OPT_RENAME 8
#define OPT_RANDNAME 9
#define OPT_UIDNAME 10
#define OPT_UNIQUENAME 11
#define NCOPT 12
#define OPT_CHANTAB 12
#define OPT_DIR 13
#define OPT_USERLIST 14
#define OPT_WHOFILE 15
#define OPT_CAPACITY 16
#define OPT_ALIAS 17
/*etc*/

Two questions
1)Why autogenerate the header file? In the programs documentation, the
author says that it's easier to add options and commands by using auto
generating the header file. I don't see how. Wouldn't it just be
easier to edit the header file vs going through the effort of making a
program to auto generate a header file?

2)In makeopt.c, the data looks like it is being written to stdout.
However, the data is appearing in opt.h. How can the author do this
without redirecting the file handle?

.



Relevant Pages