Thread View: comp.sources.reviewed
1 messages
1 total messages
Started by Adam Bryant
Tue, 03 Nov 1992 22:12
v02i042: cextract - (Ver. 1.7) C prototyper/header file generator, Part04/05
Author: 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
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