🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: comp.sources.reviewed
1 messages
1 total messages Started by Adam Bryant Tue, 03 Nov 1992 22:11
v02i041: cextract - (Ver. 1.7) C prototyper/header file generator, Part03/05
#10
Author: Adam Bryant
Date: Tue, 03 Nov 1992 22:11
939 lines
28365 bytes
Submitted-by: Adam Bryant <adb@cs.bu.edu>
Posting-number: Volume 2, Issue 41
Archive-name: cextract/part03
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 3 (of 5)."
# Contents:  main.c
# Wrapped by adb@csa on Fri Oct 30 16:20:36 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.c'\"
else
echo shar: Extracting \"'main.c'\" \(24410 characters\)
sed "s/^X//" >'main.c' <<'END_OF_FILE'
X/*
X *
X * The purpose of this program is to extract the function descriptions
X * (prototypes) from C source code.  It also provides for the creation
X * of documentation based on those prototypes.
X *
X * The specific reason for the creation of this program was to
X * provide a method for automatically creating header files to
X * describe all of the functions to be used within a multi-file
X * program.
X *
X * This file makes use of code in the companion files parse.c and io.c.
X *
X * Copyright (c) 1990, 1991, 1992 by Adam Bryant
X *
X * See Copyright notice in the file parse.c or in the manual page.
X *
X */
X/*
X * Version history:
X *
X * For Version 0.30:  file parse functions were separated out into a
X *   separate file so that other programs could make use of them.  The
X *   functions descriptions are now stored in dynamic memory and
X *   functions are provided to allow the manipulation of those
X *   descriptions.
X * Version 0.31:  Only a few minor adjustments were made to cextract...
X *   only as much as was needed to build the cextdoc program using the
X *   cproto.[ch] files.
X * Version 0.40:  Totally rewrote the parsing code so that the use of
X *   temporary files is unnecessary.  Instead, two dynamic storage
X *   elements have been created.  Besides being much faster, this
X *   method is also much more elegant than the prior method.
X * Version 0.41:  Switched the NOSETBUFFER to a SETBUFFER flag.
X *   Added in the ability to handle the vararg system to convert it
X *   to the "..." for ANSI C.
X *
X * ... change notes for later versions in parse.c
X *
X * Note on Version 1.0: merged the cextract and cextdoc into one
X *   program, with differential being made based on the command line
X *   or in the program name.  Version sent to comp.sources.reviewed.
X *
X */
X#include "xtract.h"
X#ifndef VMS
X#include <sys/types.h>
X#include <sys/stat.h>
X#else
X#include <types.h>
X#include <stat.h>
X#endif /* VMS */
X
X/* definition strings to be set when the C preprocessor runs */
X#ifndef VAXC
X#define CPP_GIVEN "-D__CEXTRACT__"
X#define CPP_GIVEN2 "-D__CEXTDOC__"
X#else
X#define CPP_GIVEN "/define=__CEXTRACT__"
X#define CPP_GIVEN2 "/define=__CEXTDOC__"
X#endif /* VAXC */
X
X/* output filter from the parsing routines */
Xvoid
Xout_char(type, outch)
X  int type, outch;
X{
X  /* to keep track of where the output list is */
X  int tab_width = get_option(OPT_TABWIDTH);
X  static P_BUFDATA curbuf[2] = { NULL, NULL };
X  static int curpos[2] = { 0, 0 };
X  static int tab_count = 0;
X
X  /* split output properly */
X  switch (type) {
X  case 0:
X    /* documentation mode should never get this */
X    if (doc_extract != DOC_NONE) {
X      fprintf(stderr, "Serious Internal Error: bad out_char() data\n");
X      exit(1);
X    }
X  case 1:
X    /* give it to the first one */
X    if (tempbuf[type] == NULL) {
X
X      /* start the list */
X      if ((tempbuf[type] = (P_BUFDATA) malloc(sizeof(S_BUFDATA))) == NULL) {
X	fprintf(stderr, "Memory Allocation Error\n");
X	exit(1);
X      }
X      tempbuf[type]->next = NULL;
X      curbuf[type] = tempbuf[type];
X    }
X
X    /* have we got enough in this one? */
X    if (curpos[type] == MID_SIZE) {
X
X      /* finish it off */
X    build_memory:
X      curbuf[type]->data[MID_SIZE] = '\0';
X      curpos[type] = 0;
X
X      /* start the next one */
X      if ((curbuf[type]->next =
X	   (P_BUFDATA) malloc(sizeof(S_BUFDATA))) == NULL) {
X	fprintf(stderr, "Memory Allocation Error\n");
X	exit(1);
X      }
X      curbuf[type] = curbuf[type]->next;
X      curbuf[type]->next = NULL;
X
X    }
X
X    /* special output filter for the documentation mode */
X    if (doc_extract != DOC_NONE) {
X
X      /* tab expansion? */
X      if (tab_width > 0) {
X	if (outch == '\t') {
X	  /* fill out tabs properly */
X	  while (tab_count++ < tab_width) {
X
X	    /* check that it will fit */
X	    if (curpos[type] == MID_SIZE) {
X	      tab_count--;
X	      goto build_memory;
X	    }
X
X	    /* put out the space */
X	    curbuf[type]->data[(curpos[type])++] = ' ';
X
X	  }
X	  tab_count = 0;
X	  break;
X	} else if (outch == '\\') {
X	  /* account for font changes */
X	  tab_count -= 2;
X	} else if (outch == '\n') {
X	  /* now on a new line */
X	  tab_count = 0;
X	} else {
X	  /* just count */
X	  if (++tab_count == tab_width) {
X	    tab_count = 0;
X	  }
X	}
X      }
X
X    }
X
X    /* now store it */
X    curbuf[type]->data[(curpos[type])++] = outch;
X    break;
X  case -1:
X    /* close everything up */
X    if (curbuf[0] != NULL) {
X      curbuf[0]->data[curpos[0]] = '\0';
X    }
X    if (curbuf[1] != NULL) {
X      curbuf[1]->data[curpos[1]] = '\0';
X    }
X    break;
X  default:
X    /* ain't one of mine */
X    fprintf(stderr, "Serious Internal Error: bad data to out_char()\n");
X    break;
X  }
X
X}
X
X/* show the version of the program */
Xvoid
Xshow_version ()
X{
X  fprintf(stderr, "%s: version %d.%d, Copyright 1992 by Adam Bryant\n",
X	  prog_name, VERSION, PATCHLEVEL);
X}
X
X/* quickly show a sting and indicate if it is on or off */
Xstatic void
Xquick_show (str, mode)
X  char *str;
X  int mode;
X{
X  fprintf(stderr, "\t%s is %s.\n", str, mode ? "on":"off");
X}
X
X/* show all of the settings */
Xvoid
Xshow_settings ()
X{
X  P_MACRO macro_temp;
X  P_SUBST sub_tmp;
X
X  /* give the version info and current settings */
X  show_version();
X  fprintf(stderr, "\n  List of current settings:\n");
X  fprintf(stderr, "\tC preprocessor in use: %s\n", cpp_prog);
X  switch (doc_extract) {
X  case DOC_NONE:
X    fprintf(stderr, "\tfunction prototype extraction mode.\n");
X    if (output_file[0][0] != '\0') {
X      fprintf(stderr, "\tthe output file is \"%s\".\n", output_file[0]);
X    }
X    if (header_string[0] != '\0') {
X      fprintf(stderr, "\tthe header string is \"%s\".\n", header_string);
X    }
X    quick_show("merged ANSI and K&R C output", get_option(OPT_COMPACT));
X    if (!get_option(OPT_COMPACT)) {
X      quick_show("showing both ANSI and K&R C", get_option(OPT_BOTHUSE));
X      if (!get_option(OPT_BOTHUSE)) {
X	quick_show("ANSI C output format", get_option(OPT_STDCUSE));
X      }
X    }
X    quick_show("showing prototypes at all times", get_option(OPT_SHOWANYWAY));
X    break;
X  case DOC_NORMAL:
X    fprintf(stderr, "\ttext documentation mode.\n");
X    if (output_file[1][0] != '\0') {
X      fprintf(stderr, "\tthe output file is \"%s\".\n", output_file[1]);
X    }
X    break;
X  case DOC_ROFF:
X    fprintf(stderr, "\ttroff documentation mode.\n");
X    if (output_file[1][0] != '\0') {
X      fprintf(stderr, "\tthe output file is \"%s\".\n", output_file[1]);
X    }
X    break;
X  default:
X    fprintf(stderr, "\tError, unknown mode.\n\n");
X    exit(1);
X    break;
X  }
X  if (get_option(OPT_SORTMODE) == SORT_ALL) {
X    quick_show("sorting for all functions", TRUE);
X  } else if (get_option(OPT_SORTMODE) == SORT_FILE) {
X    quick_show("sorting for each file", TRUE);
X  } else {
X    quick_show("sorting", FALSE);
X  }
X  if (get_option(OPT_WRAPPOINT) > 0) {
X    fprintf(stderr, "\tlong prototype lists wrap at column %d.\n",
X	    get_option(OPT_WRAPPOINT));
X  } else {
X    quick_show("wrapping of long prototypes", FALSE);
X  }
X  quick_show("separating function name and type", get_option(OPT_TYPEWRAP));
X  quick_show("showing first comment in each file",
X	     get_option(OPT_FIRSTCOMMENT));
X  quick_show("sending file name with first comment",
X	     get_option(OPT_PREPEND));
X  quick_show("comment capturing", get_option(OPT_COMMENTS));
X  if (get_option(OPT_STATICMODE) == ONLY_STATICS) {
X    quick_show("only static functions are searched for", TRUE);
X  } else {
X    quick_show("including static functions in search",
X	       get_option(OPT_STATICMODE) == ANY_STATICS);
X  }
X  quick_show("prepending extern to function declarations",
X	     get_option(OPT_EXTERNS));
X  quick_show("testing for multi-line comments",
X	     !get_option(OPT_SINGLECOMMENTS));
X
X  /* now show all of the macro definitions */
X  if (macro_list != NULL) {
X    fprintf(stderr, "\n  List of preprocessor definitions:\n");
X    for (macro_temp = macro_list;
X	 macro_temp != NULL;
X	 macro_temp = macro_temp->next) {
X      /* use? */
X      if ((macro_temp->usewhen != 2) &&
X	  (macro_temp->usewhen != (doc_extract != DOC_NONE))) continue;
X      fprintf(stderr, "\t%s\n", macro_temp->m_str);
X    }
X  }
X
X  /* now check the substitutions */
X  if (subst_list != NULL) {
X    fprintf(stderr, "\n  List of prototype substitutions:\n");
X    for (sub_tmp = subst_list;
X	 sub_tmp != NULL;
X	 sub_tmp = sub_tmp->next) {
X      /* used? */
X      if ((sub_tmp->usewhen != 2) &&
X	  (sub_tmp->usewhen != (doc_extract != DOC_NONE))) continue;
X
X      /* check it */
X      switch (sub_tmp->submode) {
X      case SUBST_FULL:
X	/* the full string needs replacing? */
X	fprintf(stderr, "\treplace 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	fprintf(stderr, "\treplace 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	fprintf(stderr, "\treplace name \"%s\" with \"%s\"\n",
X		sub_tmp->from_str, sub_tmp->to_str);
X	break;
X      }
X    }
X  }
X
X  /* all done */
X  fprintf(stderr, "\n");
X  exit(0);
X}
X
X/* quick function to copy a "string" */
Xint
Xcopy_str (o_str, in_str)
X  char *o_str, *in_str;
X{
X  int ch, count = 0, ch_read = 0;
X
X  /* find the beginning of the string */
X  while ((*in_str != '"') &&
X	 (*in_str != '\0')) {
X    ch_read++;
X    in_str++;
X  }
X
X  /* now was a string found? */
X  if (*in_str == '\0') {
X    return(-1);
X  }
X  ch_read++;
X  in_str++;
X
X  /* copy all of the string */
X  while (((ch = *(in_str)) != '\0') &&
X	 (ch != '"')) {
X    /* copy it */
X    o_str[count++] = ch;
X    ch_read++;
X    in_str++;
X  }
X  if (ch == '"') ch_read++;
X
X  /* finish up and get out */
X  o_str[count] = '\0';
X  return(ch_read);
X}
X
X/* show the usage for the program */
Xvoid
Xshow_usage()
X{
X#ifndef VMS
X  fprintf(stderr,
X	  "Usage: %s [-Q#] [+AaBbPpNnVvxZ -Hstr -Yprg -o ofile] [[-opts] file ... ]\n",
X	  prog_name);
X  fprintf(stderr, "\t+A        alphabetically sort all functions [incompatable with +C]\n");
X  fprintf(stderr, "\t+a        alphabetically sort functions within each file [default off]\n");
X  fprintf(stderr, "\t-B        build a system configuration file based on settings\n");
X  fprintf(stderr, "\t-b        build a configuration file in the current directory\n");
X  fprintf(stderr, "\t+C        include first comment from each file\n");
X  fprintf(stderr, "\t+c        include comments immediately preceding functions\n");
X  fprintf(stderr, "\t-Dexpr    send a macro definition to the C preprocessor\n");
X  fprintf(stderr, "\t+E        add a preceding 'extern' to each function definition\n");
X  fprintf(stderr, "\t+F        toggle prepending of file name to first comment [need +C]\n");
X  fprintf(stderr, "\t-f#cc     in troff doc-mode set various font styles\n");
X  fprintf(stderr, "\t-Hstring  build header file with read test on string\n");
X  fprintf(stderr, "\t-Idir     add directory to search list for include files\n");
X  fprintf(stderr, "\t-o file   send output to a file instead of standard output\n");
X  fprintf(stderr, "\t           [take first non-flag as filename for output]\n");
X  fprintf(stderr, "\t+m        allow multi-line comments when parsing comments\n");
X  fprintf(stderr, "\t-N        do documentation output in troff ms format\n");
X  fprintf(stderr, "\t-n        do documentation output in normal text\n");
X  fprintf(stderr, "\t+P        create output in both ANSI and non-ANSI prototypes\n");
X  fprintf(stderr, "\t+p        create output in ANSI C prototype format\n");
X  fprintf(stderr, "\t-Q#       do not read in config files, or only those specified\n");
X  fprintf(stderr, "\t-qfile    read in a specified configuration file\n");
X  fprintf(stderr, "\t+r        remove variable names prior to output\n");
X  fprintf(stderr, "\t+S        show parameters for non-ANSI portion of output\n");
X  fprintf(stderr, "\t+s        include static function definitions\n");
X  fprintf(stderr, "\t-s=only   capture only static function definitions\n");
X  fprintf(stderr, "\t-s=none   exclude static function definitions\n");
X  fprintf(stderr, "\t-s=any    include static function definitions\n");
X  fprintf(stderr, "\t-TN       set tab width in doc-mode to N characters [0 = off]\n");
X  fprintf(stderr, "\t-Uname    undefine the given macro name\n");
X  fprintf(stderr, "\t-V        display the program settings then exit\n");
X  fprintf(stderr, "\t-v        display version information then exit\n");
X  fprintf(stderr, "\t+W        place function type on a separate line.\n");
X  fprintf(stderr, "\t+w#       wrap long parameter output [dflt length 72]\n");
X  fprintf(stderr, "\t-x        run program in extraction mode\n");
X  fprintf(stderr, "\t-Yprog    specify program to use as a C preprocessor\n");
X  fprintf(stderr, "\t+Z        create the output as a compact, merged list\n");
X#else /* VMS */
X  fprintf(stderr, "USAGE: %s [/READ-CONFIG=#] [/OUTPUT=outfile] [[/OPTS] FILE ... ]\n",
X	  prog_name);
X#endif /* VMS */
X  exit(1);
X}
X
X/* set the value of a global option */
Xvoid
Xset_option(which, how, value)
X  Optype which;
X  int how, value;
X{
X#ifdef CHECK_INPUTS
X  /* check input values */
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  if ((how < 0) ||
X      (how > 2)) {
X    fprintf(stderr, "SERIOUS ERROR: Internal option method out of range %d\n",
X	    how);
X    exit(1);
X  }
X#endif /* CHECK_INPUTS */
X
X  /* now set properly */
X  if (how == 2) {
X    global_opts[0][which] = value;
X    global_opts[1][which] = value;
X  } else {
X    global_opts[how][which] = value;
X  }
X}
X
X/* retrieve the value of a global option */
Xint
Xget_option(which)
X  Optype which;
X{
X#ifdef CHECK_INPUTS
X  /* check input values */
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
X  /* return whichever setting is needed */
X  if (doc_extract == DOC_NONE) {
X    return(global_opts[0][which]);
X  }
X  return(global_opts[1][which]);
X}
X
X/* set configuration settings based on the initial name */
Xstatic void
Xcext_init()
X{
X  /* enter the proper mode */
X  if (strncmp(CEXTDOC_NAME, prog_name, strlen(prog_name)) == 0) {
X    doc_extract = DOC_NORMAL;
X  } else {
X    doc_extract = DOC_NONE;
X  }
X
X  /* set documentation mode options properly */
X  set_option(OPT_COMMENTS, 1, TRUE);
X  set_option(OPT_STATICMODE, 1, ANY_STATICS);
X  set_option(OPT_EXTERNS, 1, FALSE);
X  set_option(OPT_STDCUSE, 1, TRUE);
X  set_option(OPT_SORTMODE, 1, SORT_FILE);
X
X  /* set extraction mode options now */
X  set_option(OPT_COMMENTS, 0, FALSE);
X  set_option(OPT_STATICMODE, 0, NO_STATICS);
X  set_option(OPT_EXTERNS, 0, TRUE);
X  set_option(OPT_STDCUSE, 0, FALSE);
X  set_option(OPT_SORTMODE, 0, SORT_NONE);
X
X  /* now set common options */
X  set_option(OPT_NONAMES, 2, FALSE);
X  set_option(OPT_COMPACT, 2, FALSE);
X  set_option(OPT_TYPEWRAP, 2, FALSE);
X  set_option(OPT_WRAPPOINT, 2, 0);
X  set_option(OPT_BOTHUSE, 2, TRUE);
X  set_option(OPT_SINGLECOMMENTS, 2, TRUE);
X  set_option(OPT_FIRSTCOMMENT, 2, FALSE);
X  set_option(OPT_SHOWANYWAY, 2, TRUE);
X  set_option(OPT_PREPEND, 2, FALSE);
X  set_option(OPT_TABWIDTH, 2, 8);
X}
X
X/* return FALSE if character is not a normal part of a filename */
Xint
Xfname_char(ch)
X  int ch;
X{
X  switch (ch) {
X#ifdef MS_DOS
X  case '\\':
X#endif /* MS_DOS */
X#ifdef VMS
X  case ']':
X  case ':':
X#endif /* VMS */
X  case '/':
X    /* nope */
X    return(FALSE);
X  }
X  return(TRUE);
X}
X
X/* routine to build the macros onto the prototype line */
Xstatic void
Xappend_macros(str_out)
X  char *str_out;
X{
X  P_MACRO macro_temp;
X
X#ifndef VAXC
X  for (macro_temp = macro_list;
X       macro_temp != NULL;
X       macro_temp = macro_temp->next) {
X
X    /* check for use */
X    if ((macro_temp->usewhen != 2) &&
X	(macro_temp->usewhen != (doc_extract != DOC_NONE))) continue;
X
X    /* use it */
X    strcat(str_out, macro_temp->m_str);
X    strcat(str_out, " ");
X
X  }
X#else
X  char und_str[MID_SIZE], def_str[MID_SIZE], inc_str[MID_SIZE];
X  int und_uses = 0, def_uses = 0, inc_uses = 0;
X  int und_len = strlen(UNDEF_LEADER);
X  int inc_len = strlen(UNDEF_LEADER);
X  int def_len = strlen(DEF_LEADER);
X
X  /* initialize */
X  und_str[0] = '\0';
X  def_str[0] = '\0';
X  inc_str[0] = '\0';
X
X  /* properly build the command line for the C compiler */
X  for (macro_temp = macro_list;
X       macro_temp != NULL;
X       macro_temp = macro_temp->next) {
X
X    /* check for use */
X    if ((macro_temp->usewhen != 2) &&
X	(macro_temp->usewhen != (doc_extract != DOC_NONE))) continue;
X
X    /* check for the definition statement */
X    if (strncmp(DEF_LEADER, macro_temp->m_str, def_len) == 0) {
X      if (def_uses++ > 0) {
X	strcat(def_str, ",");
X      }
X      if (macro_temp->m_str[def_len] == '(') {
X	strcat(def_str, macro_temp->m_str + def_len + 1);
X	def_str[strlen(def_str) - 1] = '\0';
X	def_uses++;
X      } else {
X	strcat(def_str, macro_temp->m_str + def_len);
X      }
X    } else if (strncmp(UNDEF_LEADER, macro_temp->m_str, und_len) == 0) {
X      if (und_uses++ > 0) {
X	strcat(und_str, ",");
X      }
X      if (macro_temp->m_str[und_len] == '(') {
X	strcat(und_str, macro_temp->m_str + und_len + 1);
X	und_str[strlen(und_str) - 1] = '\0';
X	def_uses++;
X      } else {
X	strcat(und_str, macro_temp->m_str + und_len);
X      }
X    } else if (strncmp(INC_LEADER, macro_temp->m_str, inc_len) == 0) {
X      if (inc_uses++ > 0) {
X	strcat(inc_str, ",");
X      }
X      if (macro_temp->m_str[inc_len] == '(') {
X	strcat(inc_str, macro_temp->m_str + inc_len + 1);
X	und_str[strlen(inc_str) - 1] = '\0';
X	def_uses++;
X      } else {
X	strcat(inc_str, macro_temp->m_str + inc_len);
X      }
X    } else {
X      strcat(str_out, macro_temp->m_str);
X    }
X
X  }
X
X  /* now finish everything off */
X  if (def_uses > 0) {
X    strcat(str_out, DEF_LEADER);
X    if (def_uses > 1) strcat(str_out, "(");
X    strcat(str_out, def_str);
X    if (def_uses > 1) strcat(str_out, ")");
X  }
X  if (und_uses > 0) {
X    strcat(str_out, UNDEF_LEADER);
X    if (und_uses > 1) strcat(str_out, "(");
X    strcat(str_out, und_str);
X    if (und_uses > 1) strcat(str_out, ")");
X  }
X  if (inc_uses > 0) {
X    strcat(str_out, INC_LEADER);
X    if (inc_uses > 1) strcat(str_out, "(");
X    strcat(str_out, inc_str);
X    if (inc_uses > 1) strcat(str_out, ")");
X  }
X  strcat(str_out, " ");
X#endif /* VAXC */
X}
X
X/* control program flow and command line options */
Xint
Xmain (argc, argv)
X  int argc;
X  char **argv;
X{
X  char cur_argstr[MID_SIZE], sysl_out[MID_SIZE];
X  extern int getpid();
X  struct stat fst;
X  int count, j, len;
X
X  /* initialize some things */
X  fpout = stdout;
X  len = strlen(argv[0]);
X  for (j = len - 1; j > 0; j--) {
X    if (fname_char(argv[0][j]) == FALSE) {
X      j++;
X      break;
X    }
X  }
X  strcpy(prog_name, &(argv[0][j]));
X  out_filenum = 0;
X  start_comment[0] = '\0';
X  header_string[0] = '\0';
X  cur_cfg_file[0] = '\0';
X  output_file[0][0] = '\0';
X  output_file[1][0] = '\0';
X  cfg_file[0] = '\0';
X  sprintf(cpp_prog, "%s %s", CPP, CPP_COMMENTS);
X  macro_list = last_macro = NULL;
X  cext_init();
X
X  /* check for config file flags */
X  count = 1;
X  if ((count < argc) &&
X      is_switch(argv[count][0])) {
X
X#ifndef VMS
X    /* are we skipping config files? */
X    if (argv[count][1] == 'Q') {
X
X      /* check the type */
X      if (isdigit(argv[count][2])) {
X	cfg_switch = argv[count][2] - '0';
X	if ((cfg_switch < 0) ||
X	    (cfg_switch > 7) ||
X	    (argv[count][3] != '\0')) {
X	  fprintf(stderr, "Invalid value for -Q flag\n");
X	  show_usage();
X	}
X      } else if (argv[count][2] != '\0') {
X	fprintf(stderr, "Invalid data following the -Q flag\n");
X	show_usage();
X      } else {
X	cfg_switch = 0;
X      }
X
X      /* processed this one */
X      count++;
X    } else {
X#endif /* VMS */
X
X      /* now test for full length string */
X      if (minmatch_str(&(argv[count][1]), "read-config", 4)) {
X	len = strlen(argv[count]);
X	for (j = 4; j < len; j++) {
X	  if ((argv[count][j] == ':') ||
X	      (argv[count][j] == '=')) {
X	    j++;
X	    break;
X	  }
X	}
X	if (j == len) {
X	  cfg_switch = 0;
X	} else if (isdigit(argv[count][j])) {
X	  cfg_switch = argv[count][j] - '0';
X	  if ((cfg_switch < 0) ||
X	      (cfg_switch > 7) ||
X	      (argv[count][j + 1] != '\0')) {
X	    fprintf(stderr, "Invalid value for -read-config flag\n");
X	    show_usage();
X	  }
X	} else {
X	  fprintf(stderr, "Invalid data following the -read-config flag\n");
X	  show_usage();
X	}
X	count++;
X      }
X
X#ifndef VMS
X    }
X#endif /* VMS */
X  }
X
X  /* now do the configurations */
X  add_macro(2, CPP_GIVEN);
X  add_macro(1, CPP_GIVEN2);
X  do_config();
X
X  /* go through the entire argument list */
X  while (count 	< argc) {
X
X    /* check for any switches */
X    if (is_switch(argv[count][0])) {
X
X      /* call the routine for command line parsing */
X      if (argv[count][0] == '-') {
X	j = FALSE;
X      } else {
X	j = TRUE;
X      }
X      strcpy(cur_argstr, &(argv[count][1]));
X      parse_cmd(cur_argstr, j, TRUE);
X
X    } else {
X
X      /* treat it as a file name */
X      if (out_filenum == 1) {
X
X	/* store the output file name */
X	strcpy(output_file[0], argv[count]);
X	strcpy(output_file[1], argv[count]);
X	out_filenum = 2;
X
X      } else {
X
X	/* check if both C and A are on */
X	if (get_option(OPT_FIRSTCOMMENT) &&
X	    (get_option(OPT_SORTMODE) == SORT_ALL)) {
X	  fprintf(stderr, "Sorting all functions and displaying file names does not mix\n");
X	  show_usage();
X	}
X
X	/* yes, a file has been parsed */
X	out_filenum = 3;
X
X	/* process the file for input */
X	strcpy(file_name, argv[count]);
X	strcpy(errout_filename, file_name);
X	line_count = 1;
X
X	/* check if the file exits */
X	if (stat( file_name, &fst ) != 0) {
X	  sprintf(cur_argstr, "error: could not access file <%s>",
X		  file_name);
X	  err_msg(cur_argstr);
X	  exit(1);
X	} else if ((fpin = fopen(file_name, "r")) == NULL) {
X	  sprintf(cur_argstr, "error: could not read file <%s>",
X		  file_name);
X	  err_msg(cur_argstr);
X	  exit(1);
X	}
X	fclose(fpin);
X
X	/* build /lib/cpp line */
X	sprintf(sysl_out, "%s ", cpp_prog);
X	append_macros(sysl_out);
X	strcat(sysl_out, file_name);
X 
X	/* open it */
X	if ((fpin = open_input(sysl_out, "r")) == NULL) {
X	  sprintf(tmp_str, "unable to open CPP \"pipe\" to file <%s>",
X		  file_name);
X	  err_msg(tmp_str);
X	  exit(1);
X	}
X
X#ifdef SETBUFFER
X	/* now set the buffer */
X	setbuffer(fpin, inbuffer, BUFFER_SIZE);
X#endif /* SETBUFFER */
X
X	/* now do it */
X	parse_file();
X	files_parsed++;
X	if (get_option(OPT_SORTMODE) != SORT_ALL) {
X	  send_file();
X	}
X	close_input(fpin);
X
X      }
X
X    }
X
X    /* now go to the next argument */
X    count++;
X  }
X
X  /* check if -o flag is unprocessed */
X  if (out_filenum == 1) {
X    fprintf(stderr, "No output file specified\n");
X    show_usage();
X  }
X  if ((out_filenum == 2) || (out_filenum == 0)) {
X    fprintf(stderr, "No files for parsing specified\n");
X    show_usage();
X  }
X
X  /* send out everything, if it hasn't been done */
X  if (get_option(OPT_SORTMODE) == SORT_ALL) {
X    send_file();
X  }
X
X  /* now close things up and combine if needed */
X  cxt_close();
X  exit(0);
X  return(0);
X}
X
X/* transmit the currently stored comment to the output file */
Xvoid
Xsend_first_comment(begin_str)
X  char *begin_str;
X{
X  int mode;
X
X  /* check for last comment */
X  if (start_comment[0] != '\0') {
X
X    /* check the mode */
X    if (doc_extract == DOC_NONE) {
X      mode = 0;
X    } else {
X      mode = 1;
X    }
X
X    /* give the header for troff output */
X    dont_space = FALSE;
X    if (doc_extract == DOC_ROFF) {
X      start_block = TRUE;
X      init_roff(1);
X      if (total_out > 0) {
X	out_str(1, ".bp\n");
X	out_str(1, ".sp 0.5i\n");
X      }
X      out_str(1, ".KS\n");
X      out_str(1, ".nf\n");
X      out_str(1, ".ft 2\n");
X    } else {
X      out_char(mode, '\n');
X    }
X
X    /* duplicate if needed */
X    if (!get_option(OPT_COMPACT) &&
X	(doc_extract == DOC_NONE) &&
X	(get_option(OPT_SHOWANYWAY) &&
X	 get_option(OPT_BOTHUSE))) {
X      out_char(1, '\n');
X      out_str(0, begin_str);
X      out_str(1, begin_str);
X      out_str(0, start_comment);
X      out_str(1, start_comment);
X      out_char(0, '\n');
X      out_char(1, '\n');
X    } else {
X      out_str(mode, begin_str);
X      out_str(mode, start_comment);
X      out_char(mode, '\n');
X    }
X
X  }
X}
X
X#ifdef TEST
X/* dummy function that will never be used but makes a nice test */
Xchar (*(*test_it())[])(same_foo, x, y, fpfoo, z, fpp2)
X  int *x, z;
X  FILE* fpfoo, fpp2;
X  char (*(*same_foo())[])();
X  int *y;
X{
X  /* As scary a bit of code as I could think of.  Is it valid? */
X}
X#endif /*TEST*/
END_OF_FILE
if test 24410 -ne `wc -c <'main.c'`; then
    echo shar: \"'main.c'\" unpacked with wrong size!
fi
# end of 'main.c'
fi
echo shar: End of archive 3 \(of 5\).
cp /dev/null ark3isdone
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
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads