🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.sources.reviewed
Article #11

v02i042: cextract - (Ver. 1.7) C prototyper/header file generator, Part04/05

#11
From: Adam Bryant
Date: Tue, 03 Nov 1992 22:12
2278 lines
60726 bytes
Submitted-by: Adam Bryant <adb@cs.bu.edu>
Posting-number: Volume 2, Issue 42
Archive-name: cextract/part04
Supersedes: cextract: Volume 1, Issue 4-8

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 4 (of 5)."
# Contents:  io.c
# Wrapped by adb@csa on Fri Oct 30 16:20:37 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'io.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'io.c'\"
else
echo shar: Extracting \"'io.c'\" \(54108 characters\)
sed "s/^X//" >'io.c' <<'END_OF_FILE'
X/*
X *
X * cextract input/output routines.
X *
X * Copyright (c) 1992 by Adam Bryant
X *
X * See the Copyright notice in the file parse.c or in the manual page.
X *
X */
X#include "xtract.h"
X#ifndef VAXC
X#include <pwd.h>
X#ifdef cyber
Xextern struct passwd *getpwuid();
X#endif /* cyber */
X#ifdef CLIX
Xextern struct passwd *getpwuid();
X#endif /* CLIX */
X#endif /* VAXC */
X
X/* declarations */
Xchar cur_cfg_file[FNAME_SIZE], header_string[MID_SIZE];
Xint out_filenum = 0;
X
X/* storage for the temporary buffers */
XP_BUFDATA tempbuf[2] = { NULL, NULL };
X#ifdef SETBUFFER
Xchar outbuffer[BUFFER_SIZE], inbuffer[BUFFER_SIZE];
X#endif /* SETBUFFER */
X
X/* output file */
XFILE *fpout;
Xchar output_file[2][MID_SIZE];
X
X/* preprocessor */
Xchar cpp_prog[MID_SIZE];
X
X#ifdef NO_STRSTR
X/*
X * This function was written to handle Xenix sites without strstr().
X * [It is a straightforward function, which I cannot take credit for,
X * which was given by an anonymous c.s.r reviewer.]
X */
Xchar *
Xstrstr(hoststr, search)
X  char *hoststr;
X  char *search;
X{
X  int len1 = 0, len2 = 0, index = 0;
X  char *ptr1, *ptr2, *loc_ptr;
X
X  len1 = strlen(hoststr);
X  len2 = strlen(search);
X  while ( len1 >= len2 ) {
X    index = len2;
X    loc_ptr = hoststr;
X    ptr1 = hoststr;
X    ptr2 = search;
X    while ( (index > 0) && (loc_ptr != NULL) ) {
X      if ( (*ptr1) == (*ptr2) ) {
X	++ptr1;
X	++ptr2;
X	--index;
X      } else {
X	loc_ptr = NULL;
X      }
X    }
X    if ( loc_ptr != NULL ) {
X      return( loc_ptr );
X    } else {
X      ++hoststr;
X      --len1;
X    }
X  }
X  return( NULL );
X}
X#endif /* NO_STRSTR */
X
X/* indicate if on or off */
Xstatic void
Xquick_rc (str, mode, fp)
X  char *str;
X  int mode;
X  FILE *fp;
X{
X  sprintf(tmp_str, "%s%s\n", mode ? "":"!", str);
X  fput_string(tmp_str, fp);
X}
X
X/* check for divergent options */
Xstatic void
Xopt_quickrc (which, str, fp)
X  Optype which;
X  char *str;
X  FILE *fp;
X{
X#ifdef CHECK_INPUTS
X  if ((which < 0) ||
X      (which >= OPT_NUMBER)) {
X    fprintf(stderr, "SERIOUS ERROR: Internal option value out of range %d\n",
X	    which);
X    exit(1);
X  }
X#endif /* CHECK_INPUTS */
X  if (global_opts[0][which] != global_opts[1][which]) {
X    fput_string("extract-only ", fp);
X    quick_rc(str, global_opts[0][which], fp);
X    fput_string("doc-only ", fp);
X  }
X  quick_rc(str, global_opts[1][which], fp);
X}
X
X/* check for divergent numeric options */
Xstatic void
Xopt_numericrc (which, str, fp)
X  Optype which;
X  char *str;
X  FILE *fp;
X{
X#ifdef CHECK_INPUTS
X  if ((which < 0) ||
X      (which >= OPT_NUMBER)) {
X    fprintf(stderr, "SERIOUS ERROR: Internal option value out of range %d\n",
X	    which);
X    exit(1);
X  }
X#endif /* CHECK_INPUTS */
X  if (global_opts[0][which] != global_opts[1][which]) {
X    fput_string("extract-only ", fp);
X    sprintf(tmp_str, "%s: %d\n", str, global_opts[0][which]);
X    fput_string(tmp_str, fp);
X    fput_string("doc-only ", fp);
X  }
X  sprintf(tmp_str, "%s: %d\n", str, global_opts[1][which]);
X  fput_string(tmp_str, fp);
X}
X
X/* choose between three modes of the given option */
Xstatic void
Xopt_triplerc (which, str0, str1, str2, fp)
X  Optype which;
X  char *str0, *str1, *str2;
X  FILE *fp;
X{
X#ifdef CHECK_INPUTS
X  if ((which < 0) ||
X      (which >= OPT_NUMBER)) {
X    fprintf(stderr, "SERIOUS ERROR: Internal option value out of range %d\n",
X	    which);
X    exit(1);
X  }
X#endif /* CHECK_INPUTS */
X  if (global_opts[0][which] != global_opts[1][which]) {
X
X    /* first on */
X    fput_string("extract-only ", fp);
X    switch (global_opts[0][which]) {
X    case 1:
X      fput_string(str1, fp);
X      break;
X    case 2:
X      fput_string(str2, fp);
X      break;
X    default:
X      fput_string(str0, fp);
X      break;
X    }
X    fput_string("\ndoc-only ", fp);
X
X  }
X
X  /* second on */
X  switch (global_opts[1][which]) {
X  case 1:
X    fput_string(str1, fp);
X    break;
X  case 2:
X    fput_string(str2, fp);
X    break;
X  default:
X    fput_string(str0, fp);
X    break;
X  }
X  fput_string("\n", fp);
X}
X
X/* display string appropriately */
Xstatic void
Xopt_stringrc (ind, str, fp)
X  int ind;
X  char *str;
X  FILE *fp;
X{
X  if (ind != 2) {
X    if (ind == 1) {
X      fput_string("doc-only ", fp);
X    } else {
X      fput_string("extract-only ", fp);
X    }
X  }
X  fput_string(str, fp);
X}
X
X/* attempt build of system config file */
Xstatic void
Xbuild_rc (fname)
X  char *fname;
X{
X  int undlen = strlen(UNDEF_LEADER);
X  int deflen = strlen(DEF_LEADER);
X  int inclen = strlen(INC_LEADER);
X  P_MACRO macro_temp;
X  P_SUBST sub_tmp;
X  FILE *rc_fp;
X  int len;
X
X  /* open and write to config file */
X  if ((rc_fp = fopen(fname, "w")) == NULL) {
X    err_msg("unable to open system configuration file for writing");
X    exit(1);
X  }
X
X  /* provide header */
X  sprintf(tmp_str, "#\n# File: %s\n#\n", fname);
X  fput_string(tmp_str, rc_fp);
X  fput_string("#   This config file was generated by ", rc_fp);
X  sprintf(tmp_str, "version %d.%d of %s.\n",
X	  VERSION, PATCHLEVEL, prog_name);
X  fput_string(tmp_str, rc_fp);
X  fput_string("#   Edit carefully.\n", rc_fp);
X  fput_string("#\n#   Created: ", rc_fp);
X  strcpy(tmp_str, mach_time());
X  len = strlen(tmp_str);
X  if ((len > 0) && (tmp_str[len - 1] == '\n')) {
X    tmp_str[len - 1] = '\0';
X  }
X  fput_string(tmp_str, rc_fp);
X  fput_string("\n#\n", rc_fp);
X
X  /* first varargs */
X  if (vargs_find()) {
X    fprintf(stderr,
X	    "The generation of the varargs and FILE replacements might have\n");
X    fprintf(stderr,
X	    "failed.  You may want to manually enter the necessary \"replace\"\n");
X    fprintf(stderr,
X	    "commands into the system configuration file.\n");
X  }
X
X  /* begin with the CPP */
X  if (cpp_prog[0] != '\0') {
X    sprintf(tmp_str, "cpp-program: %s\n", cpp_prog);
X    fput_string(tmp_str, rc_fp);
X  }
X
X  /* handle output file */
X  if (strcmp(output_file[0], output_file[1]) != 0) {
X    if (output_file[0][0] != '\0') {
X      fput_string("extract-only ", rc_fp);
X      sprintf(tmp_str, "output-file: %s\n", output_file[0]);
X      fput_string(tmp_str, rc_fp);
X    }
X    if (output_file[1][0] != '\0') {
X      fput_string("doc-only ", rc_fp);
X    }
X  }
X  if (output_file[1][0] != '\0') {
X    sprintf(tmp_str, "output-file: %s\n", output_file[1]);
X    fput_string(tmp_str, rc_fp);
X  }
X
X  /* differentiate modes */
X#ifdef NOT_DONE
X  switch (doc_extract) {
X  case DOC_NONE:
X    fput_string("extract-mode\n", rc_fp);
X    break;
X  case DOC_NORMAL:
X    fput_string("doc-mode\n", rc_fp);
X    break;
X  case DOC_ROFF:
X    fput_string("troff-mode\n", rc_fp);
X    break;
X  default:
X    fprintf(stderr, "\tError, unknown mode.\n\n");
X    exit(1);
X    break;
X  }
X#else
X  if (doc_extract == DOC_ROFF) {
X    fput_string("doc-only troff-mode\n", rc_fp);
X  }
X#endif /* NOT_DONE */
X
X  /* output all options */
X  if (header_string[0] != '\0') {
X    sprintf(tmp_str, "header-string: %s\n", header_string);
X    fput_string(tmp_str, rc_fp);
X  }
X  opt_quickrc(OPT_COMPACT, "merge-output", rc_fp);
X  opt_quickrc(OPT_BOTHUSE, "dual-output", rc_fp);
X  opt_quickrc(OPT_STDCUSE, "ansi-code", rc_fp);
X  opt_quickrc(OPT_SHOWANYWAY, "show-anyway", rc_fp);
X  opt_triplerc(OPT_SORTMODE, "!sort", "sort-by-files", "sort-all", rc_fp);
X  opt_numericrc(OPT_WRAPPOINT, "wrap-parameters", rc_fp);
X  opt_numericrc(OPT_TABWIDTH, "tab-width", rc_fp);
X  opt_quickrc(OPT_TYPEWRAP, "break-after-types", rc_fp);
X  opt_quickrc(OPT_FIRSTCOMMENT, "first-comments", rc_fp);
X  opt_quickrc(OPT_PREPEND, "prepend-filename", rc_fp);
X  opt_quickrc(OPT_COMMENTS, "yank-comments", rc_fp);
X  opt_triplerc(OPT_STATICMODE, "statics: none", "statics: only",
X	       "statics: any", rc_fp);
X  opt_quickrc(OPT_EXTERNS, "externs", rc_fp);
X  opt_quickrc(OPT_SINGLECOMMENTS, "single-comments", rc_fp);
X
X  /* show all macros */
X  if (macro_list != NULL) {
X
X    for (macro_temp = macro_list;
X	 macro_temp != NULL;
X	 macro_temp = macro_temp->next) {
X      if (strncmp(DEF_LEADER, macro_temp->m_str, deflen) == 0) {
X	sprintf(tmp_str, "define: %s\n",
X		macro_temp->m_str + deflen);
X      } else if (strncmp(INC_LEADER, macro_temp->m_str, inclen) == 0) {
X	sprintf(tmp_str, "include: %s\n",
X		macro_temp->m_str + inclen);
X      } else if (strncmp(UNDEF_LEADER, macro_temp->m_str, undlen) == 0) {
X	sprintf(tmp_str, "undefine: %s\n",
X		macro_temp->m_str + deflen);
X      } else {
X	fprintf(stderr, "unknown macro encountered: %s\n",
X		macro_temp->m_str);
X	continue;
X      }
X      opt_stringrc(macro_temp->usewhen, tmp_str, rc_fp);
X	
X    }
X  }
X
X  /* check substitutions */
X  if (subst_list != NULL) {
X
X    for (sub_tmp = subst_list;
X	 sub_tmp != NULL;
X	 sub_tmp = sub_tmp->next) {
X
X      /* check it */
X      switch (sub_tmp->submode) {
X      case SUBST_FULL:
X	/* the full string needs replacing? */
X	sprintf(tmp_str, "replace all \"%s\" with \"%s\"\n",
X		sub_tmp->from_str, sub_tmp->to_str);
X	break;
X      case SUBST_TYPE:
X	/* the type only needs replacing? */
X	sprintf(tmp_str, "replace type \"%s\" with \"%s\"\n",
X		sub_tmp->from_str, sub_tmp->to_str);
X	break;
X      case SUBST_NAME:
X	/* the variable only needs replacing? WHY!? */
X	sprintf(tmp_str, "replace name \"%s\" with \"%s\"\n",
X		sub_tmp->from_str, sub_tmp->to_str);
X	break;
X      }
X      opt_stringrc(sub_tmp->usewhen, tmp_str, rc_fp);
X
X    }
X  }
X
X  /* done */
X  fput_string("#\n", rc_fp);
X  fclose(rc_fp);
X}
X
X/* close up properly; sending out final output */
Xvoid
Xcxt_close()
X{
X  P_BUFDATA holdbuf;
X  int len;
X
X  /* close up buffers and open file */
X  out_char(-1, '\0');
X  if (output_file[doc_extract != DOC_NONE][0] != '\0') {
X    if ((fpout = fopen(output_file[doc_extract != DOC_NONE], "w")) == NULL) {
X      sprintf(tmp_str, "unable to open output file <%s>",
X	      output_file[doc_extract != DOC_NONE]);
X      err_msg(tmp_str);
X      exit(1);
X    }
X  }
X
X#ifdef SETBUFFER
X  /* now set the buffer */
X  setbuffer(fpout, outbuffer, BUFFER_SIZE);
X#endif /* SETBUFFER */
X
X  /* send everything straight out in doc modes */
X  if (doc_extract != DOC_NONE) {
X
X    /* do all */
X    for (; tempbuf[1] != NULL; tempbuf[1] = holdbuf) {
X      /* output and free */
X      holdbuf = tempbuf[1]->next;
X      fput_string(tempbuf[1]->data, fpout);
X      free(tempbuf[1]);
X    }
X
X    /* close up */
X    if (fpout != stdout) {
X      if (fclose(fpout) == EOF) {
X	err_msg("Error in closing output file");
X	exit(1);
X      }
X    }
X    return;
X  }
X
X  /* start header */
X  fput_string("/*\n *   This file was automatically generated by ", fpout);
X  sprintf(tmp_str, "version %d.%d of %s.\n",
X	  VERSION, PATCHLEVEL, prog_name);
X  fput_string(tmp_str, fpout);
X  fput_string(" *   Manual editing not recommended.\n", fpout);
X  fput_string(" *\n *   Created: ", fpout);
X  strcpy(tmp_str, mach_time());
X  len = strlen(tmp_str);
X  if ((len > 0) && (tmp_str[len - 1] == '\n')) {
X    tmp_str[len - 1] = '\0';
X  }
X  fput_string(tmp_str, fpout);
X  fput_string("\n */\n", fpout);
X
X  /* enclosing directives */
X  if (header_string[0] != '\0') {
X    sprintf(tmp_str, "#ifndef %s\n", header_string);
X    fput_string(tmp_str, fpout);
X  } else {
X    fput_string("#ifndef __CEXTRACT__\n", fpout);
X  }
X  if (header_string[0] != '\0') {
X    sprintf(tmp_str, "#define %s\n", header_string);
X    fput_string(tmp_str, fpout);
X  }
X  if (get_option(OPT_COMPACT)) {
X    fput_string("#if __STDC__\n", fpout);
X    fput_string("#define PL_(x) x\n", fpout);
X    fput_string("#else\n", fpout);
X    fput_string("#define PL_(x) ( )\n", fpout);
X    fput_string("#endif /* __STDC__ */\n", fpout);
X  } else if (get_option(OPT_BOTHUSE) ||
X	     get_option(OPT_STDCUSE)) {
X    fput_string("#if __STDC__\n", fpout);
X  }
X
X  /* first region */
X  for (; tempbuf[0] != NULL; tempbuf[0] = holdbuf) {
X    /* output and free */
X    holdbuf = tempbuf[0]->next;
X    fput_string(tempbuf[0]->data, fpout);
X    free(tempbuf[0]);
X  }
X
X  /* more? */
X  if (!get_option(OPT_COMPACT) &&
X      get_option(OPT_BOTHUSE)) {
X
X    /* separator */
X    fput_string("\n#else /* __STDC__ */\n", fpout);
X
X    /* send second portion */
X    for (; tempbuf[1] != NULL; tempbuf[1] = holdbuf) {
X      /* output and free */
X      holdbuf = tempbuf[1]->next;
X      fput_string(tempbuf[1]->data, fpout);
X      free(tempbuf[1]);
X    }
X
X  }
X
X  /* finish header */
X  putc('\n', fpout);
X  if (get_option(OPT_COMPACT)) {
X    fput_string("#undef PL_\n", fpout);
X  } else if (get_option(OPT_BOTHUSE) ||
X	     get_option(OPT_STDCUSE)) {
X    fput_string("#endif /* __STDC__ */\n", fpout);
X  }
X  if (header_string[0] != '\0') {
X    sprintf(tmp_str, "#endif /* %s */\n", header_string);
X    fput_string(tmp_str, fpout);
X  } else {
X    fput_string("#endif /* __CEXTRACT__ */\n", fpout);
X  }
X
X  /* close up */
X  if (fpout != stdout) {
X    if (fclose(fpout) == EOF) {
X      err_msg("Error in closing output file");
X      exit(1);
X    }
X  }
X}
X
X/* output results of entire file search */
Xvoid
Xsend_file()
X{
X  /* sort? */
X  if (get_option(OPT_SORTMODE) != SORT_NONE) {
X    sort_proto();
X  }
X
X  /* output everything */
X  while (proto_list != NULL) {
X
X    /* determine type */
X    if (doc_extract == DOC_NONE) {
X
X      /* ANSI? */
X      if (get_option(OPT_COMPACT)) {
X	out_proto(0, proto_list, MODE_ANSI, get_option(OPT_COMMENTS));
X      } else if (get_option(OPT_BOTHUSE)) {
X	out_proto(0, proto_list, MODE_ANSI, get_option(OPT_COMMENTS));
X	out_proto(1, proto_list, MODE_OLDC - get_option(OPT_SHOWANYWAY),
X		  get_option(OPT_SHOWANYWAY) *
X		  get_option(OPT_COMMENTS));
X      } else {
X	if (get_option(OPT_STDCUSE)) {
X	  out_proto(0, proto_list, MODE_ANSI, get_option(OPT_COMMENTS));
X	} else {
X	  out_proto(0, proto_list, MODE_OLDC - get_option(OPT_SHOWANYWAY),
X		    get_option(OPT_COMMENTS));
X	}
X      }
X
X    } else {
X
X      /* ANSI in docs */
X      out_proto(1, proto_list, MODE_ANSI, get_option(OPT_COMMENTS));
X
X    }
X    total_out++;
X    pop_proto();
X
X  }
X}
X
X/* does the string match a minimum number of characters */
Xint
Xminmatch_str(str_in, str_base, num)
X  char *str_in, *str_base;
X  int num;
X{
X  int i;
X
X  for (i = 0; (str_base[i] != '\0') && (str_in[i] != '\0') &&
X       (str_in[i] != ':') && (str_in[i] != '='); i++) {
X    if (str_base[i] != str_in[i]) return(0);
X  }
X  if (i >= num) {
X    return(i);
X  }
X  return(0);
X}
X
X/* send an error message about a config command */
Xstatic void
Xcfg_err(str, cmd_line)
X  char *str;
X  int cmd_line;
X{
X  fprintf(stderr, "%s", str);
X  if (cmd_line) {
X    fprintf(stderr, " on the command line\n");
X  } else if (cur_cfg_file[0] == '\0') {
X    fprintf(stderr, " in a configuration file\n");
X  } else {
X    fprintf(stderr, " in %s\n", cur_cfg_file);
X  }
X}
X
X/* mode selector */
Xstatic int setmode_value;
X
X#ifndef VMS
X/* parse string for single char commands */
Xstatic void
Xsinglechar_cmds(cmd_str, set_val)
X  char *cmd_str;
X  int set_val;
X{
X  int count, len = strlen(cmd_str);
X
X  for (count = 0; count < len; count++) {
X
X    switch (cmd_str[count]) {
X    case 'A':
X      if (files_parsed == 0) {
X	if (set_val) {
X	  set_option(OPT_SORTMODE, setmode_value, SORT_ALL);
X	} else {
X	  set_option(OPT_SORTMODE, setmode_value, SORT_NONE);
X	}
X      } else {
X	fprintf(stderr, "The '-A' flag must precede any file arguments\n");
X	show_usage();
X      }
X      break;
X    case 'a':
X      if (get_option(OPT_SORTMODE) != SORT_ALL) {
X	if (set_val) {
X	  set_option(OPT_SORTMODE, setmode_value, SORT_FILE);
X	} else {
X	  set_option(OPT_SORTMODE, setmode_value, SORT_NONE);
X	}
X      }
X      break;
X    case 'b':
X      build_rc(CONFIG_FILE);
X      exit(0);
X      break;
X    case 'B':
X      build_rc(SYS_CONFIG);
X      exit(0);
X    case 'C':
X      set_option(OPT_FIRSTCOMMENT, setmode_value, set_val);
X      break;
X    case 'c':
X      set_option(OPT_COMMENTS, setmode_value, set_val);
X      break;
X    case 'D':
X    case 'd':
X      /* add to macro list */
X      if (count != 0) {
X	fprintf(stderr, "The -D flag must be a separate argument\n");
X	show_usage();
X      }
X      sprintf(tmp_str, "%s%s", DEF_LEADER, cmd_str + 1);
X      add_macro(setmode_value, tmp_str);
X      return;
X    case 'E':
X      set_option(OPT_EXTERNS, setmode_value, set_val);
X      break;
X    case 'F':
X      set_option(OPT_PREPEND, setmode_value, set_val);
X      break;
X    case 'f':
X      /* set font */
X      if (count != 0) {
X	fprintf(stderr, "The -f flag must be a separate argument\n");
X	show_usage();
X      } else if (files_parsed > 0) {
X	fprintf(stderr, "The -f flag must precede any file arguments\n");
X	show_usage();
X      }
X
X      /* check format */
X      if ((strlen(cmd_str + 1) < 2) ||
X	  (strlen(cmd_str + 1) > 3)) {
X	fprintf(stderr, "A proper troff font must be specified\n");
X	show_usage();
X      }
X
X      /* check font */
X      switch (cmd_str[1]) {
X      case '1':
X      case 't':
X      case 'T':
X	/* title */
X	strncpy(ft_title, &(cmd_str[2]), 2);
X	ft_title[2] = '\0';
X	break;
X      case '2':
X      case 'c':
X      case 'C':
X	/* comment */
X	strncpy(ft_comment, &(cmd_str[2]), 2);
X	ft_comment[2] = '\0';
X	break;
X      case '3':
X      case 'n':
X      case 'N':
X	/* function name */
X	strncpy(ft_name, &(cmd_str[2]), 2);
X	ft_name[2] = '\0';
X	break;
X      case '4':
X      case 'p':
X      case 'P':
X	/* prototype list */
X	strncpy(ft_plist, &(cmd_str[2]), 2);
X	ft_plist[2] = '\0';
X	break;
X      default:
X	/* huh? */
X	fprintf(stderr, "unknown font selector '%c' in %s\n",
X		cmd_str[1], cmd_str);
X	show_usage();
X      }
X      return;
X    case 'H':
X      /* header string */
X      if (files_parsed == 0) {
X	if (count != 0) {
X	  fprintf(stderr, "The -H flag must be a separate argument\n");
X	  show_usage();
X	}
X	if (cmd_str[2] != '\0') {
X	  strcpy(header_string, cmd_str + 1);
X	} else {
X	  fprintf(stderr,
X		  "A string must be specified following the -H flag\n");
X	  show_usage();
X	}
X      } else {
X	fprintf(stderr, "The -H flag must precede any file arguments\n");
X	show_usage();
X      }
X      return;
X    case 'I':
X    case 'i':
X      /* include file */
X      if (count != 0) {
X	fprintf(stderr, "The -I flag must be a separate argument\n");
X	show_usage();
X      }
X      sprintf(tmp_str, "%s%s", INC_LEADER, cmd_str + 1);
X      add_macro(setmode_value, tmp_str);
X      return;
X    case 'm':
X      set_option(OPT_SINGLECOMMENTS, setmode_value, (TRUE ^ set_val));
X      break;
X    case 'N':
X      /* roff mode */
X      if (files_parsed > 0) {
X	fprintf(stderr, "The -N flag must precede any file arguments\n");
X	show_usage();
X      }
X      doc_extract = DOC_ROFF;
X      break;
X    case 'n':
X      /* docs mode */
X      if (files_parsed > 0) {
X	fprintf(stderr, "The -n flag must precede any file arguments\n");
X	show_usage();
X      }
X      doc_extract = DOC_NORMAL;
X      break;
X    case 'o':
X      if (out_filenum < 3) {
X	out_filenum = 1;
X      } else {
X	fprintf(stderr, "The -o flag must precede any file arguments\n");
X	show_usage();
X      }
X      break;
X    case 'p':
X      /* ANSI C prototypes */
X      if (files_parsed == 0) {
X	set_option(OPT_STDCUSE, setmode_value, set_val);
X      } else {
X	fprintf(stderr, "The -p flag must precede any file arguments\n");
X	show_usage();
X      }
X      break;
X    case 'P':
X      /* both ANSI and K&R */
X      if (files_parsed == 0) {
X	set_option(OPT_BOTHUSE, setmode_value, set_val);
X      } else {
X	fprintf(stderr, "The -P flag must precede any file arguments\n");
X	show_usage();
X      }
X      break;
X    case 'Q':
X      /* not here */
X      fprintf(stderr, "The -Q flag must be the very first argument\n");
X      show_usage();
X    case 'q':
X      /* input config file */
X      if (count != 0) {
X	fprintf(stderr, "The -q flag must be a separate argument\n");
X	show_usage();
X      }
X      if (cmd_str[1] != '\0') {
X	parse_config(cmd_str + 1);
X      } else {
X	fprintf(stderr, "No file was specified for the -q argument\n");
X	show_usage();
X      }
X      return;
X    case 'r':
X      /* remove variable names */
X      set_option(OPT_NONAMES, setmode_value, set_val);
X      break;
X    case 'S':
X      /* full info for non-ANSI */
X      set_option(OPT_SHOWANYWAY, setmode_value, set_val);
X      break;
X    case 's':
X      /* static functions */
X      if ((cmd_str[count + 1] == ':') ||
X	  (cmd_str[count + 1] == '=')) {
X	count += 2;
X	switch(cmd_str[count]) {
X	case 'a':
X	  /* all */
X	  set_option(OPT_STATICMODE, setmode_value, ANY_STATICS);
X	  if ((strncmp(cmd_str + count, "all", 3) == 0) ||
X	      (strncmp(cmd_str + count, "any", 3) == 0)) {
X	    count += 3;
X	  } else {
X	    count++;
X	  }
X	  break;
X	case 'o':
X	  /* only statics */
X	  set_option(OPT_STATICMODE, setmode_value, ONLY_STATICS);
X	  if (strncmp(cmd_str + count, "only", 4) == 0) {
X	    count += 4;
X	  } else {
X	    count++;
X	  }
X	  break;
X	case 'n':
X	  /* no statics */
X	  set_option(OPT_STATICMODE, setmode_value, NO_STATICS);
X	  if (strncmp(cmd_str + count, "none", 4) == 0) {
X	    count += 4;
X	  } else if (strncmp(cmd_str + count, "no", 2) == 0) {
X	    count += 2;
X	  } else {
X	    count++;
X	  }
X	  break;
X	default:
X	  /* huh? */
X	  count--;
X	  break;
X	}
X      } else {
X	if (set_val) {
X	  set_option(OPT_STATICMODE, setmode_value, ANY_STATICS);
X	} else {
X	  set_option(OPT_STATICMODE, setmode_value, NO_STATICS);
X	}
X      }
X      break;
X    case 'T':
X      /* tab width */
X      if (count != 0) {
X	fprintf(stderr, "The -T flag must be a separate argument\n");
X	show_usage();
X      }
X      if (len == 2) {
X	set_option(OPT_TABWIDTH, setmode_value, 8);
X      } else {
X	int tab_width = 0;
X	for (count++; count < len; count++) {
X	  if (!isdigit(cmd_str[count])) {
X	    fprintf(stderr, "Unknown tab width in argument %s\n",
X		    cmd_str);
X	    show_usage();
X	  } else {
X	    tab_width *= 10;
X	    tab_width += cmd_str[count] - '0';
X	  }
X	}
X	set_option(OPT_TABWIDTH, setmode_value, tab_width);
X      }
X      return;
X    case 'U':
X    case 'u':
X      /* undefine */
X      if (count != 0) {
X	fprintf(stderr, "The -U flag must be a separate argument\n");
X	show_usage();
X      }
X      if (removed_macro(setmode_value, cmd_str + 1) != TRUE) {
X	sprintf(tmp_str, "%s%s", UNDEF_LEADER, cmd_str + 1);
X	add_macro(setmode_value, tmp_str);
X      }
X      return;
X    case 'V':
X      show_settings();
X    case 'v':
X      show_version();
X      exit(0);
X    case 'W':
X      /* wrapping */
X      set_option(OPT_TYPEWRAP, setmode_value, set_val);
X      break;
X    case 'w':
X      /* more wrapping */
X      if (isdigit(cmd_str[count + 1])) {
X
X	/* use given wrap locale */
X	int wrap_point = 0;
X	for (count++; isdigit(cmd_str[count]); count++) {
X	  wrap_point *= 10;
X	  wrap_point += (cmd_str[count] - '0');
X	}
X	count--;
X	set_option(OPT_WRAPPOINT, setmode_value, wrap_point);	
X
X      } else {
X
X	if (set_val) {
X	  /* default */
X	  set_option(OPT_WRAPPOINT, setmode_value, 72);
X	} else {
X	  /* off */
X	  set_option(OPT_WRAPPOINT, setmode_value, 0);
X	}
X
X      }
X      break;
X    case 'x':
X      /* extraction mode */
X      if (files_parsed > 0) {
X	fprintf(stderr, "The -x flag must precede any file arguments\n");
X	show_usage();
X      }
X      doc_extract = DOC_NONE;
X      break;
X    case 'Y':
X      /* C preprocessor */
X      if (files_parsed == 0) {
X	if (count != 0) {
X	  fprintf(stderr, "The -Y flag must be a separate argument\n");
X	  show_usage();
X	}
X	if (cmd_str[2] != '\0') {
X	  strcpy(cpp_prog, cmd_str + 1);
X	} else {
X	  fprintf(stderr,
X		  "A string must be specified following the -Y flag\n");
X	  show_usage();
X	}
X      } else {
X	fprintf(stderr, "The -Y flag must precede any file arguments\n");
X	show_usage();
X      }
X      break;
X    case 'Z':
X      /* merge output */
X      if (files_parsed == 0) {
X	set_option(OPT_COMPACT, setmode_value, set_val);
X      } else {
X	fprintf(stderr, "The -Z flag must precede any file arguments\n");
X	show_usage();
X      }
X      break;
X    default:
X      /* huh? */
X      fprintf(stderr, "Unknown option '%c' in <%s>\n", cmd_str[count],
X	      cmd_str);
X      show_usage();
X    }
X  }
X}
X#endif /* VMS */
X
X/* determine the configuration command, exit if invalid */
Xvoid
Xparse_cmd (cmd_str, set_val, cmd_line)
X  char *cmd_str;
X  int set_val, cmd_line;
X{
X  int len, count, did_cmd_parse = FALSE, had_start = FALSE;
X  char t2_str[MID_SIZE];
X
X  /* clean ends of spaces */
X  trim_str(cmd_str);
X
X  /* by default, set for both */
X  setmode_value = 2;
X
X  /* non-command line */
X  if (cmd_line == FALSE) {
X
X    /* selection? */
X    if (strncmp("extract-only ", cmd_str, 13) == 0) {
X      setmode_value = 0;
X      for (count = 0; count < 13; count++)
X	cmd_str[count] = ' ';
X      trim_str(cmd_str);
X    } else if (strncmp("doc-only ", cmd_str, 9) == 0) {
X      setmode_value = 1;
X      for (count = 0; count < 9; count++)
X	cmd_str[count] = ' ';
X      trim_str(cmd_str);
X    }
X
X  }
X
X  /* off? */
X  if (cmd_str[0] == '!') {
X    cmd_str[0] = ' ';
X    trim_str(cmd_str);
X    set_val ^= TRUE;
X    had_start = TRUE;
X  } else {
X    if (strncmp("no-", cmd_str, 3) == 0) {
X      for (count = 0; count < 3; count++)
X	cmd_str[count] = ' ';
X      trim_str(cmd_str);
X      set_val ^= TRUE;
X      had_start = TRUE;
X    } else if (strncmp("no", cmd_str, 2) == 0) {
X      for (count = 0; count < 2; count++)
X	cmd_str[count] = ' ';
X      trim_str(cmd_str);
X      set_val ^= TRUE;
X      had_start = TRUE;
X    }
X  }
X  len = strlen(cmd_str);
X
X  /* parse actual command */
X  switch (cmd_str[0]) {
X  case '\0':
X  case '#':
X    /* comment */
X    did_cmd_parse = TRUE;
X    break;
X  case 'a':
X    /* ansi C code */
X    if (minmatch_str(cmd_str, "ansi-code", 4)) {
X      did_cmd_parse = TRUE;
X      if (files_parsed > 0) {
X	if (cmd_line) {
X	  fprintf(stderr, "Error, ansi-code flag found after file argument\n");
X	  exit(1);
X	}
X      } else {
X	set_option(OPT_STDCUSE, setmode_value, set_val);
X      }
X    }
X    break;
X  case 'b':
X    if (minmatch_str(cmd_str, "build-config", 5)) {
X      did_cmd_parse = TRUE;
X      if (cmd_line) {
X	build_rc(CONFIG_FILE);
X	exit(0);
X      } else {
X	cfg_err("warning, the build-config command is unsupported", cmd_line);
X      }
X    } else if (minmatch_str(cmd_str, "break-types", 5) ||
X	       minmatch_str(cmd_str, "break-after-types", 5)) {
X      set_option(OPT_TYPEWRAP, setmode_value, set_val);
X      did_cmd_parse = TRUE;
X    }
X    break;
X  case 'c':
X    /* get comments */
X    if (minmatch_str(cmd_str, "comments", 4)) {
X      set_option(OPT_COMMENTS, setmode_value, set_val);
X      did_cmd_parse = TRUE;
X    } else if (count = minmatch_str(cmd_str, "cpp-program", 3)) {
X      did_cmd_parse = TRUE;
X      if (files_parsed > 0) {
X	if (cmd_line) {
X	  fprintf(stderr,
X		  "Error: cpp-program flag found after file arguments\n");
X	  exit(1);
X	}
X      } else {
X	for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
X	  if ((cmd_str[count] == ':') ||
X	      (cmd_str[count] == '=')) {
X	    count++;
X	    break;
X	  }
X	}
X	strcpy(tmp_str, cmd_str + count);
X	trim_str(tmp_str);
X	if (strlen(tmp_str) > 0) {
X	  strcpy(cpp_prog, tmp_str);
X	} else {
X	  cfg_err("warning, blank cpp-program name", cmd_line);
X	}
X      }
X    } else if (count = minmatch_str(cmd_str, "config-file", 4)) {
X      did_cmd_parse = TRUE;
X      for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
X	if ((cmd_str[count] == ':') ||
X	    (cmd_str[count] == '=')) {
X	  count++;
X	  break;
X	}
X      }
X      strcpy(tmp_str, cmd_str + count);
X      trim_str(tmp_str);
X      if (strlen(tmp_str) > 0) {
X	parse_config(tmp_str);
X      } else {
X	cfg_err("warning, blank config file name", cmd_line);
X      }
X    }
X    break;
X  case 'd':
X    if (minmatch_str(cmd_str, "dual-output", 4)) {
X      did_cmd_parse = TRUE;
X      if (files_parsed > 0) {
X	if (cmd_line) {
X	  fprintf(stderr,
X		  "Error, dual-output flag found after file argument\n");
X	  exit(1);
X	}
X      } else {
X	set_option(OPT_BOTHUSE, setmode_value, set_val);
X      }
X    } else if (minmatch_str(cmd_str, "discard-names", 4)) {
X      set_option(OPT_NONAMES, setmode_value, set_val);
X      did_cmd_parse = TRUE;
X    } else if (minmatch_str(cmd_str, "doc-mode", 3)) {
X      did_cmd_parse = TRUE;
X      if (files_parsed > 0) {
X	if (cmd_line) {
X	  fprintf(stderr, "Error, doc-mode flag found after file argument\n");
X	  exit(1);
X	}
X      } else {
X	doc_extract = DOC_NORMAL;
X      }
X    } else if (count = minmatch_str(cmd_str, "define", 3)) {
X      did_cmd_parse = TRUE;
X      for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
X	if ((cmd_str[count] == ':') ||
X	    (cmd_str[count] == '=')) {
X	  count++;
X	  break;
X	}
X      }
X      strcpy(tmp_str, cmd_str + count);
X      trim_str(tmp_str);
X      if (strlen(tmp_str) > 0) {
X	sprintf(cmd_str, "%s%s", DEF_LEADER, tmp_str);
X	add_macro(setmode_value, cmd_str);
X      } else {
X	cfg_err("warning, blank define command", cmd_line);
X      }
X    }
X    break;
X  case 'e':
X    if (minmatch_str(cmd_str, "externs", 4)) {
X      /* extern prepending */
X      did_cmd_parse = TRUE;
X      set_option(OPT_EXTERNS, setmode_value, set_val);
X    } else if (minmatch_str(cmd_str, "extract-mode", 3)) {
X      /* extract mode */
X      did_cmd_parse = TRUE;
X      if (files_parsed > 0) {
X	if (cmd_line) {
X	  fprintf(stderr, "Error, extract-mode found after file argument\n");
X	  exit(1);
X	}
X      } else {
X	doc_extract = DOC_NONE;
X      }
X    }
X    break;
X  case 'f':
X    if (minmatch_str(cmd_str, "first-comments", 4)) {
X      /* grabs first comments */
X      did_cmd_parse = TRUE;
X      set_option(OPT_FIRSTCOMMENT, setmode_value, set_val);
X    } else if (minmatch_str(cmd_str, "filename", 4)) {
X      /* prepend file name */
X      did_cmd_parse = TRUE;
X      set_option(OPT_PREPEND, setmode_value, set_val);
X    } else if (strncmp("font", cmd_str, 4) == 0) {
X      /* fonts */
X      did_cmd_parse = TRUE;
X      if (files_parsed > 0) {
X	if (cmd_line) {
X	  fprintf(stderr, "Error, -font flag found after file argument\n");
X	  exit(1);
X	}
X      } else {
X	switch (cmd_str[5]) {
X	case '1':
X	case 't':
X	case 'T':
X	  /* title */
X	  if ((cmd_str[6] != '\0') &&
X	      (isalnum(cmd_str[7]) &&
X	       (isalnum(cmd_str[8]) ||
X		(cmd_str[8] == '\0')))) {
X	    ft_title[0] = cmd_str[7];
X	    ft_title[1] = cmd_str[8];
X	    ft_title[2] = '\0';
X	  } else {
X	    fprintf(stderr, "warning: improper font type in:\n");
X	    fprintf(stderr, "   ==> %s\n", cmd_str);
X	    goto prop_font;
X	  }
X	  break;
X	case '2':
X	case 'c':
X	case 'C':
X	  /* comment */
X	  if ((cmd_str[6] != '\0') &&
X	      (isalnum(cmd_str[7]) &&
X	       (isalnum(cmd_str[8]) ||
X		(cmd_str[8] == '\0')))) {
X	    ft_comment[0] = cmd_str[7];
X	    ft_comment[1] = cmd_str[8];
X	    ft_comment[2] = '\0';
X	  } else {
X	    fprintf(stderr, "warning: improper font type in:\n");
X	    fprintf(stderr, "   ==> %s\n", cmd_str);
X	    goto prop_font;
X	  }
X	  break;
X	case '3':
X	case 'n':
X	case 'N':
X	  /* function name */
X	  if ((cmd_str[6] != '\0') &&
X	      (isalnum(cmd_str[7]) &&
X	       (isalnum(cmd_str[8]) ||
X		(cmd_str[8] == '\0')))) {
X	    ft_name[0] = cmd_str[7];
X	    ft_name[1] = cmd_str[8];
X	    ft_name[2] = '\0';
X	  } else {
X	    fprintf(stderr, "warning: improper font type in:\n");
X	    fprintf(stderr, "   ==> %s\n", cmd_str);
X	    goto prop_font;
X	  }
X	  break;
X	case '4':
X	case 'p':
X	case 'P':
X	  /* parameter font */
X	  if ((cmd_str[6] != '\0') &&
X	      (isalnum(cmd_str[7]) &&
X	       (isalnum(cmd_str[8]) ||
X		(cmd_str[8] == '\0')))) {
X	    ft_plist[0] = cmd_str[7];
X	    ft_plist[1] = cmd_str[8];
X	    ft_plist[2] = '\0';
X	  } else {
X	    fprintf(stderr, "warning: improper font type in:\n");
X	    fprintf(stderr, "   ==> %s\n", cmd_str);
X	    goto prop_font;
X	  }
X	  break;
X	default:
X	  /* oops */
X	  fprintf(stderr, "warning: font format invalid\n");
X	prop_font:
X	  if (cmd_line) {
X	    fprintf(stderr, "Proper format:  -font-%%-##\n");
X	  } else {
X	    fprintf(stderr, "Proper format:  font %% ##\n");
X	  }
X	  fprintf(stderr, "Where %% = one of:\n");
X	  fprintf(stderr, "     '1' or 't'  - font for titles\n");
X	  fprintf(stderr, "     '2' or 'c'  - comment font\n");
X	  fprintf(stderr, "     '3' or 'n'  - function name font\n");
X	  fprintf(stderr, "     '4' or 'p'  - parameter list font\n");
X	  fprintf(stderr, "and ## is the one or two character roff font.\n");
X	  break;
X	}
X      }
X    }
X    break;
X  case 'h':
X    /* header string */
X    if (count = minmatch_str(cmd_str, "header-string", 4)) {
X      did_cmd_parse = TRUE;
X      /* can only replace on the command line */
X      if ((header_string[0] != '\0') && !cmd_line) break;
X      for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
X	if ((cmd_str[count] == ':') ||
X	    (cmd_str[count] == '=')) {
X	  count++;
X	  break;
X	}
X      }
X      strcpy(tmp_str, cmd_str + count);
X      trim_str(tmp_str);
X      if (strlen(tmp_str) > 0) {
X	strcpy(header_string, tmp_str);
X      } else {
X	cfg_err("warning: blank header-string command", cmd_line);
X      }
X    }
X    break;
X  case 'i':
X    /* include file */
X    if (count = minmatch_str(cmd_str, "include", 3)) {
X      did_cmd_parse = TRUE;
X      for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
X	if ((cmd_str[count] == ':') ||
X	    (cmd_str[count] == '=')) {
X	  count++;
X	  break;
X	}
X      }
X      strcpy(tmp_str, cmd_str + count);
X      trim_str(tmp_str);
X      if (strlen(tmp_str) > 0) {
X	sprintf(cmd_str, "%s%s", INC_LEADER, tmp_str);
X	add_macro(setmode_value, cmd_str);
X      } else {
X	cfg_err("warning: blank include command", cmd_line);
X      }
X    }
X    break;
X  case 'm':
X    /* multiple comments */
X    if (minmatch_str(cmd_str, "multi-comments", 4) ||
X	minmatch_str(cmd_str, "multiple-comments", 4)) {
X      did_cmd_parse = TRUE;
X      set_option(OPT_SINGLECOMMENTS, setmode_value, (TRUE ^ set_val));
X    } else if (minmatch_str(cmd_str, "merge-output", 5)) {
X      did_cmd_parse = TRUE;
X      if (files_parsed > 0) {
X	if (cmd_line) {
X	  fprintf(stderr,
X		  "Error: merge-output flag found after file argument\n");
X	  exit(1);
X	}
X      } else {
X	set_option(OPT_COMPACT, setmode_value, set_val);
X      }
X    }
X    break;
X  case 'o':
X    /* output file */
X    if (count = minmatch_str(cmd_str, "output-file", 3)) {
X      did_cmd_parse = TRUE;
X      if (files_parsed > 0) {
X	if (cmd_line) {
X	  fprintf(stderr,
X		  "Error: output-file flag found after file arguments\n");
X	  exit(1);
X	}
X      } else {
X	for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
X	  if ((cmd_str[count] == ':') ||
X	      (cmd_str[count] == '=')) {
X	    count++;
X	    break;
X	  }
X	}
X	strcpy(tmp_str, cmd_str + count);
X	trim_str(tmp_str);
X	if (strlen(tmp_str) > 0) {
X	  if ((setmode_value % 2) == 0) {
X	    strcpy(output_file[0], tmp_str);
X	  }
X	  if (setmode_value != 0) {
X	    strcpy(output_file[1], tmp_str);
X	  }
X	  out_filenum = 2;
X	} else if (!cmd_line) {
X	  cfg_err("warning, blank output-file specifier", cmd_line);
X	} else {
X	  out_filenum = 1;
X	}
X      }
X    }
X    break;
X  case 'p':
X    /* prepend the file name to the output */
X    if (minmatch_str(cmd_str, "prepend-filename", 4)) {
X      did_cmd_parse = TRUE;
X      set_option(OPT_PREPEND, setmode_value, set_val);
X    }
X    break;
X  case 'r':
X    if (strncmp(cmd_str, "replace", 7) == 0) {
X
X      if (cmd_line) {
X	fprintf(stderr,
X		"Error, -replace is not a valid command line option\n");
X	exit(1);
X      }
X
X      /* check type */
X      if (strncmp("all ", cmd_str + 8, 4) == 0) {
X	len = 12;
X	count = SUBST_FULL; 
X      } else if (strncmp("type ", cmd_str + 8, 5) == 0) {
X	len = 13;
X	count = SUBST_TYPE;
X      } else if (strncmp("name ", cmd_str + 8, 5) == 0) {
X	len = 13;
X	count = SUBST_NAME;
X      } else if (strncmp("variable ", cmd_str + 8, 9) == 0) {
X	len = 17;
X	count = SUBST_NAME;
X      } else {
X	cfg_err("warning, bad replace format", cmd_line);
X	fprintf(stderr, "   ==> %s\n", cmd_str);
X	count = len = 0;
X	did_cmd_parse = TRUE;
X      }
X
X      /* do it */
X      if (did_cmd_parse == FALSE) {
X
X	did_cmd_parse = TRUE;
X	if ((set_val = copy_str(tmp_str, cmd_str + len)) == -1) {
X	  cfg_err("warning, bad replace format", cmd_line);
X	  fprintf(stderr, "   ==> %s\n", cmd_str);
X	  break;
X	}
X	len += set_val;
X	if ((set_val = copy_str(t2_str, cmd_str + len)) == -1) {
X	  cfg_err("warning, bad replace format", cmd_line);
X	  fprintf(stderr, "   ==> %s\n", cmd_str);
X	  break;
X	}
X
X	/* add substitution macro */
X	add_subst(count, setmode_value, tmp_str, t2_str);
X
X      }
X
X    } else if (minmatch_str(cmd_str, "read-config", 4)) {
X      if (cmd_line) {
X	fprintf(stderr, "The -read-config flag must be the first argument\n");
X	show_usage();
X      } else {
X	cfg_err("The -read-config command is not supported", cmd_line);
X	exit(1);
X      }
X    } else if (minmatch_str(cmd_str, "remove-names", 3)) {
X      /* remove variables? */
X      set_option(OPT_NONAMES, setmode_value, set_val);
X      did_cmd_parse = TRUE;
X    } else if (minmatch_str(cmd_str, "roff-mode", 4)) {
X
X      did_cmd_parse = TRUE;
X      if (files_parsed > 0) {
X	if (cmd_line) {
X	  fprintf(stderr, "Error: -roff-mode found after file argument\n");
X	  exit(1);
X	}
X      } else {
X	doc_extract = DOC_ROFF;
X      }
X
X    }
X    break;
X  case 's':
X    if ((count = minmatch_str(cmd_str, "statics", 4))) {
X
X      /* statics? */
X      for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
X	if ((cmd_str[count] == ':') ||
X	    (cmd_str[count] == '=')) {
X	  count++;
X	  break;
X	}
X      }
X      strcpy(tmp_str, cmd_str + count);
X      trim_str(tmp_str);
X      if (strlen(tmp_str) > 0) {
X
X	/* which? */
X	switch(tmp_str[0]) {
X	case 'a':
X	  /* all statics are allowed */
X	  set_option(OPT_STATICMODE, setmode_value, ANY_STATICS);
X	  did_cmd_parse = TRUE;
X	  break;
X	case 'o':
X	  /* only statics are allowed */
X	  set_option(OPT_STATICMODE, setmode_value, ONLY_STATICS);
X	  did_cmd_parse = TRUE;
X	  break;
X	case 'n':
X	  /* no statics are allowed */
X	  set_option(OPT_STATICMODE, setmode_value, NO_STATICS);
X	  did_cmd_parse = TRUE;
X	  break;
X	default:
X	  /* not one that I know of */
X	  break;
X	}
X
X      } else {
X
X	/* defaults */
X	if (set_val) {
X	  set_option(OPT_STATICMODE, setmode_value, ANY_STATICS);
X	} else {
X	  set_option(OPT_STATICMODE, setmode_value, NO_STATICS);
X	}
X	did_cmd_parse = TRUE;
X
X      }
X
X    } else if (minmatch_str(cmd_str, "sort-all", 4)) {
X      /* sort? */
X      did_cmd_parse = TRUE;
X      if (set_val) {
X	set_option(OPT_SORTMODE, setmode_value, SORT_ALL);
X      } else {
X	set_option(OPT_SORTMODE, setmode_value, SORT_NONE);
X      }
X    } else if (minmatch_str(cmd_str, "show-all", 4) ||
X	       minmatch_str(cmd_str, "show-anyway", 4)) {
X      /* ANSI? */
X      set_option(OPT_SHOWANYWAY, setmode_value, set_val);
X      did_cmd_parse = TRUE;
X    } else if (minmatch_str(cmd_str, "settings", 3)) {
X      did_cmd_parse = TRUE;
X      if (cmd_line) {
X	show_settings();
X      } else {
X	cfg_err("warning, the -settings command is unsupported", cmd_line);
X      }
X    } else if (minmatch_str(cmd_str, "system-build", 6)) {
X      did_cmd_parse = TRUE;
X      if (cmd_line) {
X	build_rc(SYS_CONFIG);
X	exit(0);
X      } else {
X	cfg_err("warning, the -system-build command is unsupported", cmd_line);
X      }
X    } else if (minmatch_str(cmd_str, "sort-by-files", 6)) {
X      /* file sort? */
X      did_cmd_parse = TRUE;
X      if (global_opts[setmode_value == 1][OPT_SORTMODE] != SORT_ALL) {
X	if (set_val) {
X	  set_option(OPT_SORTMODE, setmode_value, SORT_FILE);
X	} else {
X	  set_option(OPT_SORTMODE, setmode_value, SORT_NONE);
X	}
X      }
X    } else if (minmatch_str(cmd_str, "single-comments", 3)) {
X      /* !multiple comments? */
X      did_cmd_parse = TRUE;
X      set_option(OPT_SINGLECOMMENTS, setmode_value, set_val);
X    }
X    break;
X  case 't':
X    if (count = minmatch_str(cmd_str, "tab-width", 3)) {
X      int tab_width;
X      did_cmd_parse = TRUE;
X      for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
X	if ((cmd_str[count] == ':') ||
X	    (cmd_str[count] == '=')) {
X	  count++;
X	  break;
X	}
X      }
X      strcpy(tmp_str, cmd_str + count);
X      trim_str(tmp_str);
X      if (sscanf(tmp_str, "%d", &tab_width) != 1) {
X	tab_width = 0;
X      }
X      set_option(OPT_TABWIDTH, setmode_value, tab_width);
X    } else if (minmatch_str(cmd_str, "troff-mode", 4)) {
X      did_cmd_parse = TRUE;
X      if (files_parsed > 0) {
X	if (cmd_line) {
X	  fprintf(stderr, "Error: -troff-mode found after file argument\n");
X	  exit(1);
X	}
X      } else {
X	doc_extract = DOC_ROFF;
X      }
X    }
X    break;
X  case 'u':
X    /* undefine macro */
X    if (count = minmatch_str(cmd_str, "undefine", 3)) {
X      did_cmd_parse = TRUE;
X      for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
X	if ((cmd_str[count] == ':') ||
X	    (cmd_str[count] == '=')) {
X	  count++;
X	  break;
X	}
X      }
X      strcpy(tmp_str, cmd_str + count);
X      trim_str(tmp_str);
X      if (strlen(tmp_str) > 0) {
X	if (removed_macro(setmode_value, tmp_str) != TRUE) {
X	  sprintf(cmd_str, "%s%s", UNDEF_LEADER, tmp_str);
X	  add_macro(setmode_value, cmd_str);
X	}
X      } else {
X	cfg_err("warning: blank undefine", cmd_line);
X      }
X    }
X    break;
X  case 'v':
X    if (minmatch_str(cmd_str, "version-info", 3)) {
X      did_cmd_parse = TRUE;
X      if (cmd_line) {
X	show_version();
X	exit(0);
X      } else {
X	cfg_err("warning, the -version-info command is unsupported", cmd_line);
X      }
X    }
X    break;
X  case 'w':
X    /* wrapping */
X    if (count = minmatch_str(cmd_str, "wrap-parameters", 4)) {
X      did_cmd_parse = TRUE;
X      for (/* set by minmatch_str */; cmd_str[count] != '\0'; count++) {
X	if ((cmd_str[count] == ':') ||
X	    (cmd_str[count] == '=')) {
X	  count++;
X	  break;
X	}
X      }
X      strcpy(tmp_str, cmd_str + count);
X      trim_str(tmp_str);
X      count = 0;
X      if (isdigit(tmp_str[count])) {
X	/* use given */
X	int wrap_point = 0;
X	for (; isdigit(tmp_str[count]); count++) {
X	  wrap_point *= 10;
X	  wrap_point += (tmp_str[count] - '0');
X	}
X	count--;
X	set_option(OPT_WRAPPOINT, setmode_value, wrap_point);
X      } else if (set_val) {
X	/* default */
X	set_option(OPT_WRAPPOINT, setmode_value, 72);
X      } else {
X	/* off */
X	set_option(OPT_WRAPPOINT, setmode_value, 0);
X      }
X    }
X    break;
X  case 'y':
X    /* get comments */
X    if (minmatch_str(cmd_str, "yank-comments", 4)) {
X      did_cmd_parse = TRUE;
X      set_option(OPT_COMMENTS, setmode_value, set_val);
X    }
X    break;
X  default:
X    /* huh? */
X    break;
X  }
X
X  /* find it? */
X  if (did_cmd_parse == FALSE) {
X#ifndef VMS
X    if (!cmd_line || (had_start == TRUE)) {
X#endif /* VMS */
X      cfg_err("unknown option encountered", cmd_line);
X      fprintf(stderr, "   ==> %s\n", cmd_str);
X      exit(1);
X#ifndef VMS
X    } else {
X      singlechar_cmds(cmd_str, set_val);
X    }
X#endif /* VMS */
X  }
X}
X
X/* function to parse the configuration file */
Xvoid
Xparse_config (conf_fname)
X  char *conf_fname;
X{
X  char conf_data[MID_SIZE], tmp_fname[FNAME_SIZE];
X  FILE *conf_fp;
X
X  /* check input */
X  if ((conf_fp = fopen(conf_fname, "r")) == NULL) return;
X  strcpy(tmp_fname, cur_cfg_file);
X  strcpy(cur_cfg_file, conf_fname);
X
X  /* read it all */
X  while (!feof(conf_fp)) {
X
X    /* get a line */
X    conf_data[0] = '\0';
X    if (fgets(conf_data, MID_SIZE, conf_fp) != NULL) {
X      /* parse it */
X      parse_cmd(conf_data, TRUE, FALSE);
X    }
X
X  }
X
X  /* done */
X  fclose(conf_fp);
X  strcpy(cur_cfg_file, tmp_fname);
X}
X
X/* send a system error message */
Xvoid
Xerr_msg(estr)
X  char *estr;
X{
X#ifdef NO_PERROR
X  fprintf(stderr, "%s: %s\n", prog_name, estr);
X#else
X  fprintf(stderr, "%s\n", estr);
X  perror(prog_name);
X#endif /* NO_PERROR */
X}
X
X/* send a message that their was a syntax error */
Xvoid
Xsyntax_err(estr)
X  char *estr;
X{
X  /* use messages similar to gcc error messages */
X  fprintf(stderr, "%s:%d: %s\n", errout_filename, line_count, estr);
X}
X
X/* routine to check return value of fputs */
Xvoid
Xfput_string (outstr, filep)
X  char *outstr;
X  FILE *filep;
X{
X  /* check the output of fputs */
X  if (fputs(outstr, filep) == EOF) {
X    err_msg("unable to write to file");
X    exit(1);
X  }
X}
X
X/* quickie function to distinquish proper switches */
Xint
Xis_switch (ch)
X  int ch;
X{
X  if (ch == '-') return(TRUE);
X  if (ch == '+') return(TRUE);
X#ifdef VMS
X  if (ch == '/') return(TRUE);
X#endif /* VMS */
X  return(FALSE);
X}
X
X/* call the external routine out_char() and send out all characters */
Xvoid
Xout_str(omode, str)
X  int omode;
X  char *str;
X{
X  /* simple function */
X  if (str != NULL) {
X    while (*str != '\0') {
X      out_char(omode, *str);
X      str++;
X    }
X  }
X}
X
X/* output given function prototype */
Xvoid
Xout_proto(omode, f_ptr, mode, do_comments)
X  int omode;
X  P_PROTO f_ptr;
X  int mode, do_comments;
X{
X  char *ch_out, tempstr[MID_SIZE];
X  int did_leader = FALSE;
X  int outch_cnt = 0, leader_cnt;
X  int wrap_point = get_option(OPT_WRAPPOINT);
X
X  /* stupidity? */
X  if (f_ptr == NULL) return;
X
X  /* initial comment output */
X  if (get_option(OPT_FIRSTCOMMENT) &&
X      (start_comment[0] != '\0')) {
X
X    /* first comment? */
X    strcpy(tempstr, "/*");
X    if (get_option(OPT_PREPEND)) {
X      strcat(tempstr, " ");
X      strcat(tempstr, file_name);
X      strcat(tempstr, ":");
X    }
X    send_first_comment(tempstr);
X    did_leader = TRUE;
X    start_comment[0] = '\0';
X  }
X
X  /* preamble? */
X  if (doc_extract != DOC_NONE) {
X    if (dont_space == FALSE) {
X      if (doc_extract != DOC_ROFF) {
X	out_char(omode, '\n');
X	out_char(omode, '\n');
X      } else {
X	out_str(omode, ".sp 2\n");
X      }
X    } else if (doc_extract == DOC_ROFF) {
X      init_roff(omode);
X    }
X    dont_space = FALSE;
X    if (doc_extract != DOC_ROFF) {
X      out_str(omode, "Function: ");
X      out_str(omode, f_ptr->name);
X      out_str(omode, "\nFile:     ");
X    } else {
X      if (start_block == FALSE) {
X	out_str(omode, ".KS\n");
X      } else {
X	start_block = FALSE;
X      }
X      out_str(omode, ".nf\n");
X      out_str(omode, "\\f1Function: \\f3");
X      out_str(omode, f_ptr->name);
X      out_str(omode, "\n\\f1File:     \\f3");
X    }
X    out_str(omode, f_ptr->fname);
X    out_char(omode, '\n');
X  }
X
X  /* preceeding comment? */
X  if (do_comments) {
X    if (doc_extract != DOC_ROFF) {
X      out_char(omode, '\n');
X      if (f_ptr->comment != NULL) {
X	out_str(omode, f_ptr->comment);
X	out_char(omode, '\n');
X      }
X    } else {
X      out_str(omode, ".sp\n\\f2");
X      out_str(omode, f_ptr->comment);
X      out_char(omode, '\n');
X    }
X  } else if ((doc_extract != DOC_NONE) ||
X	     (total_out == 0) ||
X	     did_leader) {
X    if (doc_extract != DOC_ROFF) {
X      out_char(omode, '\n');
X    } else {
X      out_str(omode, ".sp\n");
X    }
X  }
X
X  /* fill mode for troff? */
X  if (doc_extract == DOC_ROFF) {
X    out_str(omode, ".fi\n");
X    out_str(omode, ".in +0.5i\n");
X    out_str(omode, ".ti -0.5i\n");
X  }
X
X  /* show the full function name and type */
X  if (doc_extract == DOC_ROFF) {
X    out_str(omode, "\\f3");
X    out_str(omode, f_ptr->ftype);
X    out_str(omode, " ( \\c\n\\f4");
X  } else {
X    if (get_option(OPT_TYPEWRAP)) {
X      char *second_half;
X
X      /* split at function name */
X      if (second_half = strstr(f_ptr->ftype, f_ptr->name)) {
X	outch_cnt = strlen(second_half);
X	for (ch_out = f_ptr->ftype;
X	     (ch_out != second_half) &&
X	     ((*ch_out != ' ') ||
X	      (ch_out != second_half - 1));
X	     ch_out++) {
X	  out_char(omode, *ch_out);
X	}
X	out_char(omode, '\n');
X	out_str(omode, second_half);
X      } else {
X	/* normal output */
X	outch_cnt = strlen(f_ptr->ftype);
X	out_str(omode, f_ptr->ftype);
X      }
X    } else {
X      /* normal output */
X      outch_cnt = strlen(f_ptr->ftype);
X      out_str(omode, f_ptr->ftype);
X    }
X    if (get_option(OPT_COMPACT)) {
X      out_str(omode, " PL_((");
X      outch_cnt += 6;
X    } else {
X      out_str(omode, " (");
X      outch_cnt += 2;
X    }
X  }
X  leader_cnt = outch_cnt + 1;
X  
X  if (mode != MODE_OLDC) {
X
X    /* begin comment? */
X    if (mode == MODE_COMMENT) {
X      out_str(omode, "/*");
X      outch_cnt += 2;
X    }
X
X    /* prototype list */
X    if (doc_extract == DOC_ROFF) {
X
X      /* break at each variable */
X      for (ch_out = f_ptr->plist;
X	   *ch_out != '\0';
X	   ch_out++) {
X
X	/* send out list; breaking for ','s */
X	out_char(omode, *ch_out);
X	if (*ch_out == ',') {
X	  out_str(omode, "\\c\n");
X	}
X      }
X
X    } else if ((wrap_point > 0) &&
X	       (f_ptr->plist != NULL) &&
X	       (f_ptr->plist[0] != '\0') &&
X	       (strlen(f_ptr->plist) + outch_cnt > wrap_point - 1)) {
X      char *next_space;
X
X      /* break at appropriate positions */
X      ch_out = f_ptr->plist;
X      next_space = index(f_ptr->plist, ' ');
X      do {
X
X	/* check for break point */
X	if (next_space == NULL) {
X
X	  /* wrap point within reach? */
X	  if (strlen(ch_out) + outch_cnt > wrap_point) {
X	    out_char(omode, '\n');
X	    for (outch_cnt = 0;
X		 outch_cnt < leader_cnt - 1;
X		 outch_cnt++) {
X	      out_char(omode, ' ');
X	    }
X	  }
X	  out_char(omode, ' ');
X	  out_str(omode, ch_out);
X	  ch_out = NULL;
X
X	} else {
X
X	  /* wrap point within reach? */
X	  if (next_space - ch_out + outch_cnt > wrap_point) {
X	    out_char(omode, '\n');
X	    for (outch_cnt = 0;
X		 outch_cnt < leader_cnt;
X		 outch_cnt++) {
X	      out_char(omode, ' ');
X	    }
X	  } else {
X	    out_char(omode, ' ');
X	    outch_cnt++;
X	  }
X	  for (; ch_out < next_space; ch_out++) {
X	    out_char(omode, *ch_out);
X	    outch_cnt++;
X	  }
X	  ch_out = next_space + 1;
X
X	  /* determine the next space location */
X	  next_space = index(next_space + 1, ' ');
X
X	}
X
X      } while (ch_out != NULL);
X      out_char(omode, ' ');
X
X    } else {
X
X      /* send out parameter list */
X      out_char(omode, ' ');
X      out_str(omode, f_ptr->plist);
X      if ((f_ptr->plist) &&
X	  (f_ptr->plist[0] != '\0')) {
X	out_char(omode, ' ');
X      }
X
X    }
X
X    /* end comments? */
X    if (mode == MODE_COMMENT) {
X      out_str(omode, "*/");
X    }
X
X  }
X
X  /* close up */
X  if (doc_extract == DOC_ROFF) {
X    out_str(omode, "\\f3 );\n");
X  } else {
X    if (get_option(OPT_COMPACT)) {
X      out_char(omode, ')');
X    }
X    out_str(omode, ");\n");
X  }
X
X  /* turn off fill for troff */
X  if (doc_extract == DOC_ROFF) {
X    out_str(omode, ".nf\n");
X    out_str(omode, ".in -0.5i\n");
X    out_str(omode, ".KE\n");
X  }
X}
X
X/* set home config file path indicating success */
Xstatic int
Xset_home_config()
X{
X#ifndef VAXC
X  struct passwd *pwtemp = NULL;
X#endif /* VAXC */
X  char home_file[MID_SIZE];
X
X  if (getenv("HOME") != NULL) {
X    strcpy(home_file, (char *)getenv("HOME"));
X#ifndef VAXC
X  } else if ((pwtemp = getpwuid(getuid())) != NULL) {
X    strcpy(home_file, pwtemp->pw_dir);
X#endif /* VAXC */
X  } else {
X#ifdef VMS
X    strcpy(home_file, "sys$login:");
X#else
X    /* oops */
X    return(FALSE);
X#endif /* VMS */
X  }
X
X  /* build the file */
X  strcat(home_file, DIR_SEPARATOR);
X  strcat(home_file, CONFIG_FILE);
X
X  /* record it */
X  strcpy(tmp_str, home_file);
X  return(TRUE);
X}
X
X/* Create test file for varargs and FILE test */
Xstatic int
Xbld_testfile(fname)
X  char *fname;
X{
X  FILE *fp;
X
X  if ((fp = fopen(fname, "w")) == NULL) {
X    sprintf(tmp_str, "Error opening varargs test file <%s>", fname);
X    err_msg(tmp_str);
X    return(TRUE);
X  }
X  fput_string("#include <stdio.h>\n", fp);
X  fput_string("#include <varargs.h>\n", fp);
X  fput_string("int function1(va_alist)\nva_dcl\n", fp);
X  fput_string("{ /* empty function */ }\n", fp);
X  fput_string("int function2(fstrct)\nFILE fstrct;\n", fp);
X  fput_string("{ /* empty function */ }\n", fp);
X  if (fclose(fp) == EOF) {
X    sprintf(tmp_str, "Error closing varargs test file <%s>", fname);
X    err_msg(tmp_str);
X    return(TRUE);
X  }
X  return(FALSE);
X}
X
X/* search for expanded value of the varargs setup */
Xint
Xvargs_find ()
X{
X  char sys_cmd[MID_SIZE], tmpfname[MID_SIZE];
X  char t_instr[MID_SIZE], t_outstr[MID_SIZE];
X  int hold = FALSE, type_select = 0;
X  extern int dont_stop;
X
X  /* build temp file name */
X  sprintf(tmpfname, TMPFILE_FMT, getpid());
X
X  /* generate it */
X  if (bld_testfile(tmpfname)) {
X    return(TRUE);
X  }
X
X  /* launch a CPP process */
X  sprintf(sys_cmd, "%s %s", cpp_prog, tmpfname);
X  if ((fpin = open_input(sys_cmd, "r")) == NULL) {
X    sprintf(tmp_str, "unable to open CPP \"pipe\" to file <%s>",
X	   tmpfname);
X    err_msg(tmp_str);
X    return(TRUE);
X  }
X
X  /* now parse it */
X  dont_stop = TRUE;
X  parse_file();
X  dont_stop = FALSE;
X  close_input(fpin);
X  unlink(tmpfname);
X  fpin = NULL;
X
X  /* retrieve the info */
X  while (proto_list != NULL) {
X
X    /* get proper function */
X    if (strcmp(proto_list->name, "function1") == 0) {
X      /* varargs */
X      if (strcmp(proto_list->plist, "...") == 0) goto skip_it;
X      strcpy(t_instr, proto_list->plist);
X      strcpy(t_outstr, "...");
X      type_select = SUBST_FULL;
X    } else if (strcmp(proto_list->name, "function2") == 0) {
X      /* FILE structure */
X      for (type_select = strlen(proto_list->plist) - 1;
X	   type_select > 0;
X	   type_select--) {
X	if (proto_list->plist[type_select] == ' ') {
X	  proto_list->plist[type_select] = '\0';
X	  break;
X	}
X      }
X      if (strcmp(proto_list->plist, "FILE") == 0) goto skip_it;
X      strcpy(t_instr, proto_list->plist);
X      strcpy(t_outstr, "FILE");
X      type_select = SUBST_TYPE;
X    } else {
X      /* huh? */
X      fprintf(stderr,
X	      "Warning: unable to locate the FILE and varargs replacements\n");
X      hold = TRUE;
X      goto skip_it;
X    }
X
X    /* copy the information */
X    add_subst(type_select, 2, t_instr, t_outstr);
X
X  skip_it:
X    /* clean up */
X    pop_proto();
X  }
X
X  /* get out */
X  return(hold);
X}
X
X/* read in all configuration files */
Xvoid
Xdo_config ()
X{
X  /* system configuration file */
X  if (cfg_switch & 1) {
X    parse_config(SYS_CONFIG);
X  }
X
X  /* personal configuration file */
X  if (cfg_switch & 2) {
X    if (set_home_config()) {
X      parse_config(tmp_str);
X    }
X  }
X
X  /* current directory */
X  if (cfg_switch & 4) {
X    parse_config(CONFIG_FILE);
X  }
X
X  /* random config file */
X  if (cfg_file[0] != '\0') {
X    parse_config(cfg_file);
X  }
X}
X
X/* return pointer to string containing the date */
Xchar *
Xmach_time ()
X{
X  long timeval;
X
X  timeval = time(0);
X  return(ctime(&timeval));
X}
X
X#ifdef NO_POPEN
X/* strings for faking a popen call */
Xchar newcommand[FNAME_SIZE];
Xchar pipetmpfile[FNAME_SIZE];
X#endif /* NO_POPEN */
X
X/* function to open a "pipe" to the input */
XFILE *
Xopen_input (pname, modestr)
X  char *pname, *modestr;
X{
X#ifdef NO_POPEN
X  static int tmpnameset = FALSE;
X
X  /* build file name */
X  if (tmpnameset == FALSE) {
X    sprintf(pipetmpfile, PIPETMP_FMT, getpid());
X    tmpnameset = TRUE;
X  }
X
X  /* this "popen()" hack is only useful for reading from the "pipe" */
X  sprintf(newcommand, PIPEOUT_FMT, pname, pipetmpfile);
X  if (system(newcommand) == SYSCMD_FAILED) {
X    return((FILE *) NULL);
X  }
X  return(fopen(pipetmpfile, modestr));
X#else
X  return(popen(pname, modestr));
X#endif /* NO_POPEN */
X}
X
X/* close up the "pipe" */
Xint
Xclose_input (stream)
X  FILE *stream;
X{
X#ifdef NO_POPEN
X  if (fclose(stream) == EOF) return(-1);
X  return(unlink(pipetmpfile));
X#else
X  return(pclose(stream));
X#endif /* NO_POPEN */
X}
END_OF_FILE
if test 54108 -ne `wc -c <'io.c'`; then
    echo shar: \"'io.c'\" unpacked with wrong size!
fi
# end of 'io.c'
fi
echo shar: End of archive 4 \(of 5\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 5 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

exit 0 # Just in case...
-- 
        Andrew Patrick acting as Comp.Sources.Reviewed Moderator
              Department of Communications, Ottawa, CANADA
                         csr@calvin.dgbt.doc.CA
Technical Details
Message-ID: <1992Nov3.221214.16949@rick.dgbt.doc.ca>
Path: arc1-ca.pugleaf.net!sparky!uunet!utcsri!torn!cunews!dgbt!rick.dgbt.doc.ca!calvin.dgbt.doc.ca!csr

Show Full Headers
Complete Article Headers
Newsgroups: comp.sources.reviewed
Path: arc1-ca.pugleaf.net!sparky!uunet!utcsri!torn!cunews!dgbt!rick.dgbt.doc.ca!calvin.dgbt.doc.ca!csr
From: Adam Bryant <adb@cs.bu.edu>
Subject: v02i042: cextract - (Ver. 1.7) C prototyper/header file generator, Part04/05
Message-ID: <1992Nov3.221214.16949@rick.dgbt.doc.ca>
Originator: csr@calvin.dgbt.doc.ca
Sender: news@rick.dgbt.doc.ca
Nntp-Posting-Host: calvin.dgbt.doc.ca
Organization: Communications Research Centre, Ottawa
Date: Tue, 3 Nov 1992 22:12:14 GMT
Approved: csr@calvin.dgbt.doc.ca
Lines: 2278