Article View: comp.sources.reviewed
Article #11v02i042: cextract - (Ver. 1.7) C prototyper/header file generator, Part04/05
From: Adam Bryant
Date: Tue, 03 Nov 1992 22:12
Date: Tue, 03 Nov 1992 22:12
2278 lines
60726 bytes
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!csrShow 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