home *** CD-ROM | disk | FTP | other *** search
- From: Adam Bryant <adb@cs.bu.edu>
- Subject: v02i041: cextract - (Ver. 1.7) C prototyper/header file generator, Part03/05
- Newsgroups: comp.sources.reviewed
- Approved: csr@calvin.dgbt.doc.ca
-
- 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...
-