home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-08-26 | 53.5 KB | 1,551 lines |
- Newsgroups: comp.sources.misc
- From: Lutz Prechelt <prechelt@i41s14.ira.uka.de>
- Subject: v22i065: crefine - C-Refine preprocessor, Part03/04
- Message-ID: <1991Aug26.032423.15215@sparky.IMD.Sterling.COM>
- X-Md4-Signature: f27aca5f22d709d7316a65fc7595cf99
- Date: Mon, 26 Aug 1991 03:24:23 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: Lutz Prechelt <prechelt@i41s14.ira.uka.de>
- Posting-number: Volume 22, Issue 65
- Archive-name: crefine/part03
- Environment: UNIX, MS-DOS, TOS, C, C++, Objective-C
-
- #! /bin/sh
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: cr_getln.c cr_talk.c crefine.1 getargs.c patchlevel.h
- # Wrapped by kent@sparky on Sun Aug 25 21:56:46 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 3 (of 4)."'
- if test -f 'cr_getln.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cr_getln.c'\"
- else
- echo shar: Extracting \"'cr_getln.c'\" \(16193 characters\)
- sed "s/^X//" >'cr_getln.c' <<'END_OF_FILE'
- X
- X/*************************************************************************
- XProject : C-Refine Precompiler
- XModule : Line Scanner
- XAuthor : Lutz Prechelt, Karlsruhe
- XDate : 11.06.91 Version 16
- XCompiler: ANSI C
- X**************************************************************************/
- X/*
- X Copyright (C) 1988,89,90,91 by Lutz Prechelt, Karlsruhe
- X
- X This program is free software; you can redistribute it and/or modify
- X it under the terms of the GNU General Public License as published by
- X the Free Software Foundation; either version 1, or (at your option)
- X any later version.
- X This program is distributed in the hope that it will be useful,
- X but WITHOUT ANY WARRANTY; without even the implied warranty of
- X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X GNU General Public License for more details.
- X You should have received a copy of the GNU General Public License
- X along with this program; if not, write to the Free Software
- X Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X*/
- X
- X/************************************************************************
- X*********************** C - R e f i n e *********************************
- X*************************************************************************/
- X
- X#include <stdio.h>
- X#include <string.h>
- X#include <ctype.h>
- X
- X#include "cr_decl.h" /* globale Funktionen, Typen und Daten */
- X
- X/******************* lokale Funktionen ************************************/
- X
- Xstatic void push_refinement_name A(());
- Xstatic int normal_scanner A((LINE_INFO*));
- Xstatic int comment_scanner A((LINE_INFO*));
- Xstatic int text_scanner A((LINE_INFO*));
- Xstatic int char_scanner A((LINE_INFO*));
- X
- X/*************************** defines ***************************************/
- X
- X#define push(ch) *(s++) = (char)ch
- X
- X#define leave_sequence "leave" /* e.g. "leave" (no leading blank!) */
- X#define leave_sequence_length 5
- X
- X#define normal_end_of_line 1 /* real end of line */
- X#define continueing_end_of_line 2 /* logical end of line */
- X#define refinementsymbol_found 3
- X#define leave_keyword_found 4
- X
- X/*********************** Lokale Daten ************************************/
- X
- X/***** one line buffer *****/
- Xstatic char *act; /* current position in b */
- X
- X/***** Control *****/
- X#if ansi
- Xstatic int (*scanner) (LINE_INFO*) = normal_scanner;
- X#else
- Xstatic int (*scanner) () = normal_scanner;
- X#endif
- X/***** Status *****/
- Xstatic int level = 0, /* brace-nesting */
- X just_was = normal_end_of_line, /* event memory */
- X event = normal_end_of_line,
- X semicolon_count,
- X lines_in_denoter,
- X old_indent;
- X
- X/*********************** get_line ****************************************/
- X
- Xextern void get_line (fp, l, semicolons)
- X FILE *fp;
- X LINE_INFO *l;
- X int *semicolons; /* is increased only ! */
- X{
- X /* Reads on line from file fp and sets up l accordingly.
- X The preprocessed line is copied to *s and s is increased appropriately.
- X (A null terminator is appended.)
- X The line is a complete line only, if there is no refinement involved
- X with that line:
- X For refinement calls and refinement declaration headers a separate line
- X is generated.
- X At end of file stop_processing is set to true. Problems yield a
- X message and let 'errors' or 'warnings' increase.
- X This function uses the option indicator variables.
- X */
- X charp old_s = s; /* store s to compute length later */
- X bool stop = false;
- X bool three_witches;
- X semicolon_count = 0;
- X { /* init_l (Level 1) */
- X#if debug
- X printf ("get_line:");
- X#endif
- X l->level = level; /* level is defined as level at start of line! */
- X l->start = s;
- X l->indent = 0;
- X l->type = normal;
- X }
- X if (just_was == normal_end_of_line) {
- X { /* read_line (Level 1) */
- X l->line_no = ++line_no;
- X act = (char*)fgets (b, b_size, fp); /* get next line*/
- X#if debug
- X printf ("->%s<-", act == NULL ? "(NULL)" : (char*)act);
- X#endif
- X if (act == NULL) { /* check for EOF */
- X stop_processing = true;
- X l->type = empty;
- X if (level > 0)
- X error (Eeof_brace, NULL, line_no);
- X if (scanner == comment_scanner)
- X error (Eeof_comment, NULL, line_no);
- X if (scanner == text_scanner)
- X error (Eeof_string, NULL, line_no);
- X if (scanner == char_scanner)
- X error (Eeof_char, NULL, line_no);
- X return;
- X }
- X }
- X { /* get_indent (Level 1) */
- X while (!stop)
- X if (*act == ' ') {
- X l->indent++;
- X act++;
- X }
- X else if (*act == TAB) { /* expand Tabs */
- X l->indent = (l->indent/tabsize + 1) * tabsize;
- X act++;
- X }
- X else
- X stop = true;
- X old_indent = l->indent; /* store for next call */
- X }
- X }
- X else { /* continued line */
- X l->indent = old_indent;
- X l->line_no = line_no;
- X }
- X { /* handle_line (Level 1) */
- X three_witches = l->indent == 0 && level > 0 && scanner == normal_scanner;
- X if (three_witches && (int)*act == refinementsymbol)
- X { /* handle_refinement_declaration (Level 2) */
- X act++; /* skip refinementsymbol */
- X push_refinement_name ();
- X if (*act != ':')
- X error (Erefdecl_syntax, act, line_no);
- X else
- X act++;
- X if (level > 1)
- X error (Erefdecl_nested, NULL, line_no);
- X l->type = refdecl;
- X just_was = (*act == '\n' || *act == 0) ? normal_end_of_line :
- X continueing_end_of_line;
- X }
- X else {
- X { /* check_column_0 (Level 2) */
- X if (three_witches && !iscntrl (*act) &&
- X just_was != continueing_end_of_line &&
- X *act != '}' && *act != '#' && *act != '*' && *act != '/')
- X warning (Wcol0, act, line_no, 1);
- X }
- X if (just_was != refinementsymbol_found &&
- X just_was != leave_keyword_found)
- X event = (*scanner) (l);
- X { /* handle_event (Level 2) */
- X if (event == refinementsymbol_found || event == leave_keyword_found)
- X { /* handle_refinementcall_or_leave (Level 3) */
- X if (s - old_s == 0) { /* line empty */
- X push_refinement_name ();
- X l->type = event == leave_keyword_found ? leave : refcall;
- X { /* skip_semicolon_and_blanks (Level 4) */
- X if (*act == ';') { /* skip semikolon if present */
- X act++;
- X semicolon_count++;
- X if (l->type == refcall)
- X l->type = refcallr; /* note the removed ";" */
- X }
- X while (*(act++) == ' ') /* skip following blanks */
- X ;
- X act--; /* recover char after last blank */
- X }
- X just_was = (*act == 0 || *act == '\n') ? normal_end_of_line :
- X continueing_end_of_line;
- X }
- X else
- X just_was = event;
- X }
- X else
- X just_was = normal_end_of_line;
- X }
- X if (option_small || event == normal_end_of_line)
- X { /* delete_trailing_blanks (Level 2) */
- X while (*(s-1) == ' ') /* remove trailing blanks */
- X s--;
- X }
- X }
- X l->length = s - old_s;
- X if (l->length == 0)
- X l->type = empty;
- X push (0); /* String Terminator */
- X { /* perhaps_warn_for_level_changes (Level 2) */
- X int lev = level;
- X if (lev < 0) { /* Syntax error! (or C-Refine does not work...) */
- X if (option_anyway)
- X error (Emany_braces, NULL, line_no);
- X else
- X fatal_error (Emany_braces, NULL, line_no);
- X }
- X else if (lev > 5 && level > l->level)
- X warning (Wnesting, NULL, line_no, 3);
- X else if (l->indent > 35 && (
- X l->type == refcall || l->type == refcallr)
- X && !option_small)
- X warning (Wmuch_indent, NULL, line_no, 3);
- X }
- X assert (!(l->type == refdecl && semicolon_count != 0));
- X *semicolons += semicolon_count;
- X }
- X}
- X
- X/********************** push_refinement_name *******************************/
- X
- Xstatic void push_refinement_name ()
- X{
- X /* reads input using 'act' and generates output using 's'.
- X reads all following blanks, letters, digits and underscores (that is,
- X stops on other characters) and generates from that a C identifier
- X on the output by suppressing leading and trailing blanks.
- X With option_ibmchars the Umlaute and Accentcharacters from the
- X IBM International Charset are also allowed.
- X */
- X#define is_legal(ch) (isalnum(ch) || (ch) == ' ' || ch == '_' || \
- X (option_ibmchars && \
- X (((ch) >= 128 && (ch) <= 167)) || (ch) == 225))
- X int ch;
- X charp old_s = s, start = s;
- X { /* suppress_leading_blanks (Level 1) */
- X while (*act == ' ') /* suppress leading blanks */
- X act++;
- X }
- X { /* copy_legal_chars (Level 1) */
- X do { /* copy legal chars */
- X ch = *(act++);
- X push (ch);
- X }
- X while (is_legal (ch));
- X s--; act--; /* unpush illegal last char */
- X }
- X { /* suppress_trailing_blanks (Level 1) */
- X while (*(s-1) == ' ' && s > old_s) /* suppress trailing blanks */
- X s--;
- X }
- X assert (*(s-1) != ' ');
- X assert (*old_s != ' ');
- X assert (s - old_s >= 0);
- X { /* change_inner_blanks_to_underlines (Level 1) */
- X for (start++; start < s; start++) /* change inner blanks to underlines */
- X if (*start == ' ')
- X *start = '_';
- X#undef is_legal
- X }
- X if (s - old_s == 0)
- X error (Erefname_missing, act, line_no);
- X}
- X
- X/*********************** S C A N N I N G *********************************/
- X
- X#define q 39 /* Quote */
- X#define dq 34 /* Double-Quote */
- X
- X/*********************** normal_scanner ***********************************/
- X
- Xstatic int normal_scanner (l)
- X LINE_INFO *l;
- X{
- X /* Changes to reading comments, strings or quoted chars as necessary.
- X Ends only at the end of a line.
- X Tries to identify refinement calls and refinement declarations;
- X in these cases the lines are reduced to only the refinement name.
- X */
- X register int ch;
- X for (;;) {
- X ch = *(act++);
- X switch (ch) {
- X case '\n':
- X case 0 : return (normal_end_of_line);
- X case '/' : if (*act == '*') /* start of comment ? */
- X { /* handle_normal_comment (Level 1) */
- X if (!option_small) {
- X push (ch); push ('*');
- X }
- X act++;
- X scanner = comment_scanner;
- X return ((*scanner) (l));
- X }
- X else if (*act == '/' && option_cplusplus)
- X { /* handle_doubleslash_style_comment (Level 1) */
- X if (option_small)
- X return (normal_end_of_line); /* just pgnore
- Xrest of line */
- X push (ch); push (ch); /* put // */
- X act++;
- X while (*act != '\n' && *act != 0) /* put rest of line */
- X push (*(act++));
- X return (normal_end_of_line);
- X }
- X else /* No --> normal */
- X push (ch);
- X break;
- X case dq :
- X { /* handle_text_denoter (Level 1) */
- X push (ch);
- X scanner = text_scanner;
- X lines_in_denoter = 0;
- X return ((*scanner) (l));
- X }
- X case q :
- X { /* handle_char_denoter (Level 1) */
- X push (ch);
- X scanner = char_scanner;
- X lines_in_denoter = 0;
- X return ((*scanner) (l));
- X }
- X case ';' : semicolon_count++;
- X push (';');
- X break;
- X case '{' : level++;
- X push (ch);
- X break;
- X case '}' : level--;
- X push (ch);
- X break;
- X default :
- X if (ch == refinementsymbol)
- X { /* check_for_leave_or_refinement_call (Level 1) */
- X /* Precondition: Refinement symbol found, 'act' is
- Xright behind it.
- X if a 'leave' surrounded by blanks is found in
- Xfront of the
- X refinement symbol, it and its blanks are stripped and
- X leave_keyword_found is returned.
- X Otherwise refinementsymbol_found gemeldet is returned
- X */
- X charp old_s = s--;
- X while (*s == ' ')
- X s--;
- X s++;
- X if (!memcmp (s - leave_sequence_length, leave_sequence,
- X leave_sequence_length)) {
- X s -= leave_sequence_length; /* Remove
- Xleave_sequence from Output */
- X return (leave_keyword_found);
- X }
- X else {
- X s = old_s;
- X return (refinementsymbol_found);
- X }
- X }
- X else
- X push (ch);
- X }
- X }
- X}
- X
- X/********************* comment_scanner *************************************/
- X
- Xstatic int comment_scanner (l)
- X LINE_INFO *l;
- X{
- X /* Precondition: position is right behind a start of a comment
- X (which is already copied if not option_small is true)
- X Postcondition: position is right after a comment end.
- X */
- X register int ch;
- X for (;;) {
- X ch = *(act++);
- X switch (ch) {
- X case '\n':
- X case 0 : return (normal_end_of_line);
- X case '*' : if (*act == '/') /* end of comment : */
- X { /* handle_comment_end (Level 1) */
- X if (!option_small) {
- X push (ch); push ('/');
- X }
- X act++;
- X scanner = normal_scanner; /* change to normal scanner */
- X return ((*scanner) (l)); /* and continue scanning */
- X }
- X /* no break ! */
- X default : if (!option_small)
- X push (ch);
- X }
- X }
- X}
- X
- X/********************* text_scanner *************************************/
- X
- Xstatic int text_scanner (l)
- X LINE_INFO *l;
- X{
- X /* Precondition: position is right behind the (already copied)
- X double quote that starts a string denoter
- X (string literal)
- X Postcondition:position is right behind the closing double
- X quote of a string denoter
- X */
- X register int ch;
- X lines_in_denoter++;
- X for (;;) {
- X ch = *(act++);
- X switch (ch) {
- X case '\n':
- X case 0 : return (normal_end_of_line); /* allowed ??? */
- X case dq :
- X { /* end_of_stringdenoter (Level 1) */
- X push (ch);
- X if (lines_in_denoter > 1)
- X warning (Wlong_string, act-1, line_no,
- X lines_in_denoter > 5 ? 1 : 2);
- X scanner = normal_scanner;
- X return ((*scanner) (l));
- X }
- X case '\\': push (ch);
- X if (*act == dq || *act == '\\') {
- X push (*act);
- X act++;
- X }
- X break;
- X default : push (ch);
- X }
- X }
- X}
- X
- X/********************* char_scanner *************************************/
- X
- Xstatic int char_scanner (l)
- X LINE_INFO *l;
- X{
- X /* Is analogous to text scanner, but uses single quote instead of double
- X quote.
- X */
- X int ch;
- X lines_in_denoter++;
- X for (;;) {
- X ch = *(act++);
- X switch (ch) {
- X case '\n':
- X case 0 : return (normal_end_of_line); /* allowed ??? */
- X case q :
- X { /* end_of_chardenoter (Level 1) */
- X push (ch);
- X if (lines_in_denoter > 1)
- X warning (Wlong_char, act-1, line_no,
- X lines_in_denoter > 5 ? 1 : 2);
- X scanner = normal_scanner;
- X return ((*scanner) (l));
- X }
- X case '\\': push (ch);
- X if (*act == q || *act == '\\') {
- X push (*act);
- X act++;
- X }
- X break;
- X default : push (ch);
- X }
- X }
- X}
- X
- END_OF_FILE
- if test 16193 -ne `wc -c <'cr_getln.c'`; then
- echo shar: \"'cr_getln.c'\" unpacked with wrong size!
- fi
- # end of 'cr_getln.c'
- fi
- if test -f 'cr_talk.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cr_talk.c'\"
- else
- echo shar: Extracting \"'cr_talk.c'\" \(3406 characters\)
- sed "s/^X//" >'cr_talk.c' <<'END_OF_FILE'
- X
- X/*************************************************************************
- XProject : C-Refine Precompiler
- XModule : Output functions for messages
- XAuthor : Lutz Prechelt, Karlsruhe
- XDate : 11.06.91 Version 16
- XCompiler: ANSI C, C-Refine
- X**************************************************************************/
- X/*
- X Copyright (C) 1988,89,90,91 by Lutz Prechelt, Karlsruhe
- X
- X This program is free software; you can redistribute it and/or modify
- X it under the terms of the GNU General Public License as published by
- X the Free Software Foundation; either version 1, or (at your option)
- X any later version.
- X This program is distributed in the hope that it will be useful,
- X but WITHOUT ANY WARRANTY; without even the implied warranty of
- X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X GNU General Public License for more details.
- X You should have received a copy of the GNU General Public License
- X along with this program; if not, write to the Free Software
- X Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X*/
- X
- X/************************************************************************
- X*********************** C - R e f i n e *********************************
- X*************************************************************************/
- X
- X#include <stdio.h>
- X#include <string.h>
- X
- X#include "cr_decl.h" /* global Functions, Types and Data */
- X#include "cr_texts.h" /* message texts */
- X
- Xstatic void error_message A((charp[], charp[], charp, int));
- X
- X/************************* cout *******************************************/
- X
- Xextern void cout (i)
- X int i;
- X{
- X /* Writes number i on stderr (which is assumed to be a screen)
- X with length five and positions the cursor back to the starting
- X position with five backspaces.
- X This is not very fast, but that doesn't matter.
- X */
- X fprintf (stderr, "%5d\b\b\b\b\b", i);
- X}
- X
- X/************************ error *******************************************/
- X
- Xstatic void error_message (type, message, object, line)
- X charp type[], message[];
- X charp object;
- X int line;
- X{
- X fprintf (stdout, "\"%s\", line %d, %s: %s\n", name_in,
- X line, type[msg_type], message[msg_type]);
- X if (object != NULL) {
- X char *nl = strchr (object, '\n');
- X if (nl != NULL) /* remove newline from object */
- X *nl = 0;
- X fprintf (stdout, " %s \"%s\"\n", Tnear[msg_type], object);
- X if (nl != NULL)
- X *nl = '\n';
- X }
- X}
- X
- X
- Xextern void error (message, object, line)
- X charp message[];
- X charp object;
- X int line;
- X{
- X error_message (Terror, message, object, line);
- X if (++errors > maxerrors)
- X fatal_error (Emany_errors, "(-----ManteldesSchweigens-----)", line);
- X error_in_this_function = true;
- X}
- X
- X/************************ fatal_error *************************************/
- X
- Xextern void fatal_error (message, object, line)
- X charp message[];
- X charp object;
- X int line;
- X{
- X error_message (Tfatal_error, message, object, line);
- X stop_processing = true;
- X errors++;
- X}
- X
- X/************************ warning *****************************************/
- X
- Xextern void warning (message, object, line, level)
- X charp message[];
- X charp object;
- X int line, level;
- X{
- X if (!error_in_this_function && level <= warning_level) {
- X /* don't be too verbose */
- X error_message (Twarning, message, object, line);
- X if (++warnings > maxwarnings)
- X fatal_error (Emany_warnings, NULL, line);
- X }
- X}
- X
- END_OF_FILE
- if test 3406 -ne `wc -c <'cr_talk.c'`; then
- echo shar: \"'cr_talk.c'\" unpacked with wrong size!
- fi
- # end of 'cr_talk.c'
- fi
- if test -f 'crefine.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'crefine.1'\"
- else
- echo shar: Extracting \"'crefine.1'\" \(17842 characters\)
- sed "s/^X//" >'crefine.1' <<'END_OF_FILE'
- X.TH CREFINE 1 "22 August 1991"
- X.SH NAME
- Xcrefine \- refinement preprocessor for C and C++
- X.SH SYNOPSIS
- X.B crefine
- X[
- X.B options
- X]
- X.I inputfile
- X[
- X.I outputfile
- X]
- X.SH DESCRIPTION
- X.B crefine (C-Refine)
- X(spoken like 'see refine') is a preprocessor that adds a new language
- Xconstruct to C and C++: the
- X.I refinement.
- Xcrefine massages a source code file to produce plain C output from
- XC input with refinements or plain C++ from C++ with refinements.
- XThe syntax of refinements is described in the USAGE section.
- XOnly a single source file may be processed with one call; the name of the
- Xoutput file, if not given, is derived from the name of the input file
- Xby removing its last
- Xcharacter, if that is an
- X.B r
- X(which is the filename convention for C\-Refine).
- XIf the last character of
- Xthe input filename is not an
- X.B r
- X, the output filename is derived from it
- Xby appending
- X.B RRR
- Xinstead.
- XInput and output is always to and from named
- Xfiles. Error messages go to the standard output. The startup message,
- Xif not suppressed, goes to standard error.
- X
- XC\-Refine does not act in any way upon the directives for the
- XC preprocessor. This especially means that include files have to be
- Xprocessed separately. Usually, this will not be necessary, since they do
- Xnot typically contain anything that C\-Refine should work on.
- XA second consequence is, that it is possible for C\-Refine to give error
- Xmessages on correct programs, because it does not see the effects of
- Xrunning the preprocessor. In these cases you either have to change your
- Xsource code or run the C preprocessor before C\-Refine.
- X.SH OPTIONS
- X.TP
- X.B \-a
- Xanyway. Normally, if any error was detected by C\-Refine, the output file
- Xwill automatically be deleted. This option says not to do so.
- X.TP
- X.B \-c
- Xcomment refinement names in the output. Any inserted
- Xrefiement body in the output is titled by a comment giving the refinement
- Xname and the refinement nesting level.
- X.TP
- X.B \-f
- Xfeedback that you work. For the homo ludens in the programmer or people
- Xwith incredibly overloaded machines. Shows running line numbers on standard
- Xerror.
- X.TP
- X.B \-i
- Xindent the
- X.I #line
- Xdirectives in the resulting output to the appropriate
- Xindentation level as indicated by the nesting of refinements. Not an
- Xespecially important option, but since this is a true UNIX program, it is
- Xpresent anyway.
- X.TP
- X.B \-l
- Xlist all refinement names.
- XThe names of all processed refinements are listed
- Xto the standard output along with their line numbers.
- XI do not know exactly what this option may be good
- Xfor, but I believe someday somebody will need it.
- X.TP
- X.B \-m<ch>
- Xmessage language. Originally, C\-Refine was written by a typical german
- Xprogrammer in the typical german programmer schizophrenia situation:
- Xas a german the native tongue is german,
- Xas a programmer the native tongue is
- Xenglish. So both languages were supported for the error messages.
- XEven worse, since I believe the whole data processing world is much too
- Xserious, I liked to have a humourous version either. So now any of the
- Xcharacters
- X.B d,D,g,G
- Ximmediately after the option character m gives you
- Xgerman error and warning messages,
- X.B e
- Xor
- X.B E
- Xgives english ones (which,
- Xfor sake of internationality, is the default) and every other letter lets
- Xyou stick to (german) humor.
- X.TP
- X.B \-n<num>
- Xnumbering with
- X.I #line
- Xcommands. By default, every insertion of a
- Xrefinement body is accompanied by a #line preprocessor directive in the
- Xoutput. This is the default numbering level 3.
- XBy giving a smaller number just after the option character
- X.B n
- X, the amount of
- X.I #line
- Xdirectives used can be
- Xreduced (level 2 or 1) or set to zero (level 0). What is best depends on
- Xthe behavior of your local C or C++ compiler.
- XJust try it out, beginning with the default level 3.
- X.TP
- X.B \-p
- Xplus. The C++ mode. The only difference between C mode and C++ mode for
- XC\-Refine is, that in C++ mode the C++ doubleslash comment convention is
- Xobeyed, while in C mode it is not. This is possible because C\-Refine knows
- Xvery little about the actual syntax of these two languages.
- XSo in most cases, this difference makes no difference at all.
- X.TP
- X.B \-q
- Xquiet mode. Suppresses the startup message of C\-Refine.
- X.TP
- X.B \-r<ch>
- Xrefinement symbol. Select what character shall be recognized as the
- Xrefinement symbol in the input file. The character to chose must be given
- Xon the command line immediately after the option character
- X.B r.
- XThis is the
- Xbackquote (ASCII code 95) by default. Since there are only two printable
- XASCII characters that are unused in the syntax of C (the backquote,
- Xcode 96, and the dollar or currency sign, code 36) there is very little
- Xchoice on a machine with 7 bit character set. This choice is further
- Xrestricted because on some systems (such as VMS) the dollar sign is
- Xacutally being allowed and used for identifiers.
- XSome more possiblilities arise when having an 8 bit character set, such
- Xas the IBM international character set (proposed symbol there is the
- Xlittle double right angle bracket, code 175, which really looks nice),
- Xbut take into account that any change in refinement symbol is bad
- Xfor the portability of your source files.
- X.TP
- X.B \-R<num>
- Xrefinement symbol. Same as before, but the new symbol is given by its
- Xcharacter code instead of by itself.
- X.TP
- X.B \-s
- Xstrip. Produces smaller output by stripping of all indentation, whether
- Xpresent in the input or generated by C\-Refine, and all comments.
- XThis is on by default. To switch it off, use the syntax
- X.B \-s\-
- X.TP
- X.B \-w<num>
- Xwarning level. C\-Refine is able to give various warnings about your
- Xsource code. These can be suppressed in three stages. The default warning
- Xlevel is 3 (all warnings). You can chose any level from 0 (no warnings)
- Xto 3 by giving the appropriate number right after the option character
- X.B w
- Xon the command line.
- X.TP
- X.B \-B<num>
- Xbuffer. Select the size of the source code buffer
- Xin which C\-Refine holds the
- Xcode for a function while processing it. The default is 150000 bytes.
- X.TP
- X.B \-E<num>
- Xerrors. Select the maximum number of errors that may occur in the input
- Xbefore C\-Refine stops processing prematurely. The default is 20.
- X.TP
- X.B \-L<num>
- Xlines. Select the maximum number of source code lines per single function
- Xthat C\-Refine is able to hold. The default is 2500.
- X.TP
- X.B \-N<num>
- Xnumber of refinements per function.
- XSelects the maximum number of refinement
- Xdeclarations that may be present within any single function.
- XThe default is 200.
- X.TP
- X.B \-T<num>
- Xtab size. Select the number of spaces to which a TAB character expands.
- XC\-Refine expands all TAB characters at the beginning of a line, i.e. those
- Xthat act as indentation. Other TABs are left untouched. The default is 1.
- X.TP
- X.B \-W<num>
- Xwarnings. Select the maximum number of warnings that may occur
- Xbefore C\-Refine stops processing prematurely. The default is 30.
- X.SH USAGE
- XThere are three new syntactic elements with C\-Refine:
- Xthe refinement definition, the refinement call and the leave construct.
- XThe purpose of refinements is to support
- Xthe Top\-Down style of programming
- X(a) within a function and (b) in both, thinking and writing.
- XEssentially, refinements are just parameterless macros with
- Xlong descriptive names.
- XRefinements are in any case local to a function. They may be called
- Xbefore they are declared; declaration and definition of a
- Xrefinement are one.
- XThe syntax of refinements as defined by C\-Refine is
- X.I not
- Xformat free, but lays significance upon whether a special symbol (the
- Xrefinement symbol) is occuring in column 0 or somewhere else.
- X
- XAlong with the new language constructs are some layout restrictions
- Xfor the program text being defined. This is necessary, because (a) the
- Xsyntax of the refinement constructs breaks basic syntactic rules of C and
- X(b) the C\-Refine preprocessor relies on some simple formatting rules, so
- Xits algorithms can be kept simple and the whole thing small, portable,
- Xrobust, reliable and fast.
- X
- XHere are the (very informal) descriptions of the syntax and semantics of
- Xthe language elements introduced by C\-Refine:
- X.TP
- Xrefinement names
- XA
- X.I refinement name
- Xis just a normal C identifier, with one important addition:
- Xblanks are allowed within (!)
- Xit (i.e. anywhere after the first nonblank character
- Xof the name and before the last nonblank one); they are equivalent to
- Xunderscores. The end of a refinement name is always detected by the
- Xappearence of a special symbol, typically a semicolon, a colon or an
- Xoperator.
- XA refinement name must, however, be on a single line.
- X.TP
- X.B refinement calls
- XA
- X.I refinement call
- Xconsists of the refinement symbol, immediately followed
- Xby a refinement name. The refinement symbol must not be in colums 0 of the
- Xsource line. Refinement calls are principally allowed anywhere within
- Xa function. The called refinement must be defined in that function, although
- Xthe definition may (and usually will) appear later than the call.
- XThe semantics of a refinement call is as follows:
- XA
- X.I procedural refinement
- X(i.e. one that contains at least one semicolon in
- Xits body) is inserted instead of its call, surrounded by a pair of curly
- Xbraces. This insertion is recursively applied to nested refinements.
- XA
- X.I valued refinement
- X(i.e. one that contains just an expression and no
- Xsemicolon in its body) is inserted instead of its call, surrounded by
- Xa pair of parentheses.
- XThis insertion is recursively applied to nested valued refinements.
- XSo procedural refinements can be called anywhere where a block statement is
- Xlegal. Valued refinements can be called anywhere where a parenthesed
- Xexpression is legal.
- XAn illegal form of refinement call will be detected by C\-Refine.
- X.TP
- X.B refinement definitions
- Xa refinement definition consists of the refinement symbol, immediately
- Xfollowed by a refinement name, followed by a colon.
- XThe refinement symbol must be in column 0 of the
- Xsource line. Refinement definitions are allowed only on block nesting
- Xlevel 1, i.e. in the outermost block of a function.
- XThe body of a refinement is examined to decide what type of
- Xrefinement it is:
- XAll refinements that contain one or more semicolons in their body,
- Xthat are not part of a comment, character denoter or string denoter,
- Xare called
- X.I procedural refinements,
- Xsince they contain statements.
- XAll other refinements are called
- X.I valued refinements,
- Xsince they only contain an expression and thus return a value.
- XIllegal syntax of a refinement declaration and the declaration of
- Xrefinements that are never used will be detected by C\-Refine.
- X.TP
- X.B leave
- XThe
- X.I leave construct
- Xmay be used from within any procedural refinement at any place where a
- Xstatement is legal. It consists of the keyword
- X.B leave
- Xfollowed by the refinement symbol, followed by a refinement name
- X.I ref.
- XThe semantics of this construct is, that a
- X.I goto
- Xstatement is inserted instead of the leave construct, that jumps to
- Xa point right after the last statement of the refinement
- X.I ref.
- XFor this to be legal
- X.I ref
- Xmust be present in the current static nesting of refinement calls.
- XThis means that not only the current refinement can be left with
- X.I leave,
- Xbut any number of refinements that are statically nested at that point
- Xof your code. Illegal use of the leave construct is detected by C\-Refine.
- X
- XAs by now, I assume, almost any understanding that may initially have been
- Xthere, will probably have vanished. I will try to get it back to you by
- Xmeans of the following example. This is a (very simple\-minded) version
- Xof the Sieve of Eratosthenes. It should not be thought that I believe the
- Xrefinement technique to be especially well suited to this problem, but this
- Xwas the smallest 'real' problem I could think of to demonstrate at least
- Xmost of what the possibilities of C\-Refine are. So here it is:
- X
- X.nf
- X#define MAX 10000
- X#define PRIME 0
- X#define NON_PRIME 1
- X
- Xstatic int sieve[MAX+1];
- X
- Xint main ()
- X{
- X `initialize;
- X `do sieve;
- X `make output;
- X return (0);
- X
- X`initialize:
- X int current;
- X for (current = 2; current <= MAX; current++)
- X sieve[current] = PRIME;
- X
- X`do sieve:
- X int current_prime = 1;
- X for (;;) {
- X `find next bigger prime; /* perhaps STOP here */
- X `delete all multiples of current_prime;
- X }
- X
- X`find next bigger prime:
- X int current_candidate = current_prime + 1;
- X while (sieve[current_candidate] == NON_PRIME)
- X if (current_candidate == MAX)
- X leave `do sieve; /* leave two refinements at once */
- X else
- X current_candidate++;
- X /* now current_candidate is a prime (or we leave `sieve) */
- X current_prime = current_candidate;
- X
- X`delete all multiples of current_prime:
- X int current = `first multiple of current_prime;
- X while (current <= MAX) {
- X sieve[current] = NON_PRIME;
- X current += current_prime;
- X }
- X
- X`first multiple of current_prime:
- X 2 * current_prime
- X
- X`make output:
- X int current; /* different from 'current' above */
- X printf ("The primes between 2 and %d are\n", MAX);
- X for (current = 2; current <= MAX; current++)
- X if (`current is prime)
- X printf ("%5d ", current);
- X
- X`current is prime:
- X sieve[current] == PRIME
- X
- X} /* end of main() */
- X
- X/***** End of example *****/
- X.fi
- XTo make the self documentation aspect of C\-Refine more clear, look at
- Xthe following example: A function that tests, whether its parameters
- Xform a pythagorean triple:
- X.nf
- Xbool pythagorean (double x, double y, double z)
- X{
- X return (`all legs positive && `one is hypotenuse)
- X
- X`all legs positive:
- X x > 0 && y > 0 && z > 0
- X
- X`one is hypotenuse:
- X `x is hypotenuse || `y is hypotenuse || `z is hypotenuse
- X
- X`x is hypotenuse:
- X x*x == y*y + z*z
- X
- X`y is hypotenuse:
- X y*y == x*x + z*z
- X
- X`z is hypotenuse:
- X z*z == x*x + y*y
- X
- X}
- X.fi
- XThis is good style: you write down just what you want to express and
- Xwith an optimizing compiler such code will also be perfectly efficient.
- XTry to imagine what this would have looked like, if it had all been
- Xin a single parenthesesed expression.
- X.SH FILES
- X.PD 0
- X.TP 18
- Xbin/crefine
- Xthe executable program
- X.TP
- Xfilename.cr
- XC\-with\-refinements input file.
- X.TP
- Xfilename.c
- XC output file.
- X.TP
- Xfilename.ccr
- XC++\-with\-refinements input file.
- X.TP
- Xfilename.cc
- XC++ output file.
- X.TP
- XotherfileRRR
- Xoutput file from input file
- X.I otherfile
- X.PD
- X.SH EXAMPLES
- X.TP
- Xcrefine firsttest.cr
- Xprocess the input file firsttest.cr producing the output file firsttest.c
- X.TP
- Xcrefine -p+ -q+ -w2 next.ccr outfile
- Xprocess the C++ inputfile next.ccr producing the output file outfile.
- XThe startup message is suppressed, C++ mode is selected and the
- Xwarning level is reduced to 2.
- X.TP
- Xcrefine -pqw2 next.ccr outfile
- Xsame as before.
- X.TP
- Xcrefine -p+a-l-qw2 next.ccr outfile
- Xsame as before.
- X.TP
- Xcrefine -c -s- -n0 -T8 last.cr
- Xprocess the inputfile last.cr in order to get a readable C source.
- XComments and indentation are not stripped, inserted refinement bodies
- Xare tagged by an additional comment giving the refinement name,
- Xall
- X.I #line
- Xpreprocessor directives are left out and leading tabs expand
- Xto 8 spaces.
- X.TP
- Xcrefine -cs-n0T8 last.cr
- Xsame as before.
- X.SH DIAGNOSTICS
- XThe warnings and error messages are intended to be self explanatory. If you
- Xdo not understand one of them anyway: chose a different language for
- Xthe messages (see option \-m), get yourself a dictionary or interpreter and
- Xtry again.
- X.SH SEE ALSO
- Xcc(1), cpp(1), make(1)
- X.SH BUGS
- XSince preprocessor directives are not handled by C\-Refine, strange things
- Xcan happen if you use #ifdef or #if. This is especially the case, if you
- Xuse these directives to put large comments into your source files: if there
- Xare any comments or string literals (double quotes) or char
- Xliterals (single quotes) beginning in that area that are not properly
- Xclosed within it, C\-Refine will run to nirvana searching for their end and
- Xgive you lots of wrong error and warning messages.
- XWatch out for apostrophes (e.g. in "don't") especially!
- X.LP
- XC\-Refine should be able to act according to #line commands, so that
- Xthe above problems could be avoided by running the preprocessor first.
- X.LP
- XThose people, who use such stupid macros as
- X.nf
- X #define BEGIN {
- X #define END }
- X.fi
- Xor similar craizy stuff, will have to change their habits in order
- Xto use C\-Refine.
- X.LP
- XThe output of C\-Refine may be code that exceeds certain compiler limits of
- Xyour C or C++ compiler. Since the body of every procedural refinement is
- Xenclosed in a block and the body of every value returning refinement is
- Xenclosed in parentheses, the block nexting limits or expression complexity
- Xlimits of your compiler may be reached when you make very heavy use of
- Xnested refinements.
- X.LP
- XSome compilers may handle the #line directive improperly, yielding wrongly
- Xtagged error messages.
- X.LP
- XProbably C\-Refine will also work with Objective\-C,
- Xbut I am not absolutely sure about that.
- X.LP
- XThere should be a mode to use C\-Refine for Lisp also.
- X.LP
- XC\-Refine reacts poor on some types of syntactic errors.
- X.LP
- XIt should optionally be possible to let C\-Refine run the
- XC preprocessor and react correctly to
- X.I #line
- Xdirectives.
- X.LP
- XIn C++, when a "leave" has to jump across a variable initialization, some
- XCompilers will complain, that the goto is illegal. This is not true,
- Xbecause the goto jumps to (or even beyond) the very end of the block
- Xwhere that variable is in
- X[precisely: the jump is to an empty statement, which is the last statement
- Xin the block], but these compilers do not recognize that fact.
- X.SH VERSION
- XThis is for C\-Refine Version 2.4
- X.LP
- XIt is likely that the command syntax be changed in the next version in the
- Xfollowing way: multiple filenames can be given, all of which
- X.I must
- Xend with an 'r'. The output filename is constructed implicitly by
- Xremoving that 'r' from the inputfilename. So you better do not use output
- Xfile names in your makefiles.
- X.SH AUTHOR
- XLutz Prechelt,
- XInstitut fuer Programmstrukturen und Datenorganisation,
- XUniversitaet Karlsruhe,
- XD-7500 Karlsruhe,
- XGermany.
- X(prechelt@ira.uka.de)
- END_OF_FILE
- if test 17842 -ne `wc -c <'crefine.1'`; then
- echo shar: \"'crefine.1'\" unpacked with wrong size!
- fi
- # end of 'crefine.1'
- fi
- if test -f 'getargs.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'getargs.c'\"
- else
- echo shar: Extracting \"'getargs.c'\" \(12454 characters\)
- sed "s/^X//" >'getargs.c' <<'END_OF_FILE'
- X/*************************************************************************
- XModule : getargs -- command line option processor
- XAuthor : Lutz Prechelt, Karlsruhe
- XDate : 11.06.91 Version 2
- XCompiler: should be portable
- X tried: MS-DOS 3.2, Microsoft C 5.0 (ANSI-C)
- X SUN-OS 4.03, 4.1 (K&R C); GNU gcc 1.39
- X**************************************************************************/
- X/*
- X Copyright (C) 1988,91 by Lutz Prechelt, Karlsruhe
- X
- X This program is free software; you can redistribute it and/or modify
- X it under the terms of the GNU General Public License as published by
- X the Free Software Foundation; either version 1, or (at your option)
- X any later version.
- X This program is distributed in the hope that it will be useful,
- X but WITHOUT ANY WARRANTY; without even the implied warranty of
- X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X GNU General Public License for more details.
- X You should have received a copy of the GNU General Public License
- X along with this program; if not, write to the Free Software
- X Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X*/
- X
- X
- X/************************************************************************
- X*********************** g e t a r g s ***********************************
- X*************************************************************************/
- X#if 0
- X
- XVarianten:
- X#define deutsch 1 waehlt deutsche Meldungen statt englische
- X#define ansi 1 waehlt Funktionsdefinitionen mit Parameterliste
- X statt ohne
- X#define ms_dos 1 erlaubt "/" als Optionszeichen zusaetzlich zu "-"
- X
- XDies ist ein Utility zum bequemeren Auswerten von Optionen auf der
- XKommandozeile (d.h. mit argc, argv).
- X
- XEs wird dazu vom Benutzer eine Tabelle ("argtab") aufgestellt, in der zu
- Xjeder Option der Optionsbuchstabe, ein Argumententyp
- X(BOOL, CHAR, INT, STRING) und eine Variable angegeben werden,
- Xin der das Resultat abgelegt werden soll.
- XFerner kann man hier noch einen Kommentarstring zu jeder Option angeben.
- X
- XDie Funktion getargs (&argc, argv, argtab, argtabsize) bearbeitet nun den
- Xargv Vektor derart, dass alle Optionen, die in argtab angegeben sind, gemaess
- Xihrem Eintrag behandelt werden und aus argv entfernt (dazu wird argc und argv
- Xmodifiziert, jedoch nur Pointer veraendert, keine argv-Eintraege selbst)
- XEs duerfen beim Aufruf die Optionen beliebig mit den uebrigen Parametern
- Xvermischt und mehrere Optionen hinter einem Optionssymbol angegeben
- Xwerden.
- X
- XEs werden unbekannte Optionen festgestellt und angemeckert (nach stderr)
- XAls Resultat wird die Anzahl angemeckerter Optionen geliefert.
- X
- XDie Funktion print_usage (program_name, usage_text, argtab, argtabsize)
- Xgibt unter Benutzung der Kommentarstrings aus argtab eine Kurzbeschreibung zum
- Xkorrekten Aufruf aller Optionen und des Gesamtprogramms nach stderr aus.
- X
- XBeispiel:
- X #include <getargs.h>
- X int a = 1, b = 'B', c;
- X char *d = "";
- X ARG argtab[] = { {'a', BOOLEAN, &a, "use alternate mode" },
- X {'b', CHARACTER,&b, "Character for boldface" },
- X {'c', INTEGER, &c, "count of pages to print" },
- X {'d', STRING , (int*)&d, "File description" } };
- X void main (int argc, char **argv) {
- X if (getargs (&argc, argv, argtab, ARGTABSIZE (argtab)))
- X print_usage (argv[0], "[options] filetoprint [options]", argtab,
- X ARGTABSIZE (argtab));
- X }
- X
- XEnthalte argtab also die Liste der Optionen fuer das Programm "fileprt", das
- X(wie in print_usage angegeben) noch einen Dateinamen als weiteren Parameter
- Xverlangt.
- X
- XDann waeren korrekte Aufrufe etwa:
- X
- Xfileprt -a file
- Xfileprt -a+ file -bB
- Xfileprt -c14 file -dMyFile
- Xfileprt file -abBc14
- X
- XVerkehrt waere dagegen zum Beispiel:
- X
- Xfileprt -dMy File file weil <File> ein eigenes Argument ist
- Xfileprt -p file weil es die Option p nicht gibt
- Xfileprt -bx28 file weil CHAR immer nur ein Zeichen umfasst
- X
- XDieser letzte Aufruf haette im Beispiel ungefaehr folgenden Output nach
- Xstderr zur Folge:
- X
- XUnbekannte Option : -bx28
- Xusage: C:\MYDIR\FILEPRT.EXE [options] filetoprint [options]
- XErlaubte Optionen sind:
- X-a<+/-> use alternate mode (Wert: TRUE)
- X-b<ch> Character for boldface (Wert: B)
- X-c<num> count of pages to print (Wert: 0)
- X-d<str> File description (Wert: "")
- X
- XDer genaue Grund fuer die Fehlermeldung ist, dass der Interpreter der Option
- Xb den Wert x zuweist und dann nach der (nicht auffindbaren) Option 2 sucht !
- X
- XDie "Wert"-Angaben beim print_usage entstehen aus den Vorbelegungen der
- XVariablen a, b, c, d;
- X
- X#endif
- X
- X/**************************************************************************/
- X
- X#include "std.h"
- X#include <stdio.h>
- X#include <ctype.h>
- X#include "getargs.h"
- X
- X#if deutsch
- X#define ERRMSG "Unbekannte Option"
- X#define USAGE "Aufruf"
- X#define VALID_OPT_ARE "Erlaubte Optionen sind"
- X#else
- X#define ERRMSG "unknown option"
- X#define USAGE "usage"
- X#define VALID_OPT_ARE "valid options are"
- X#endif
- X
- X#if ms_dos
- X#define is_option(a) (a == '-' || a == '/') /* MS-DOS option marker */
- X#else
- X#define is_option(a) (a == '-') /* option marker for Unix etc. */
- X#endif
- X
- Xstatic int set_argument A((ARG* entry, char **optiontext));
- Xstatic ARG* find_argument A((int optionname, ARG *argtab, int argtablength));
- Xstatic int stoi A((char ** linep));
- X
- X/*---------------------------------------------------------
- X * getargs
- X *---------------------------------------------------------*/
- X
- Xextern int getargs (argc, argv, tabp, tabsize)
- X int *argc; /* changed */
- X char **argv; /* changed */
- X ARG *tabp;
- X int tabsize;
- X{
- X /* Hauptroutine. Wertet alle Argumente in argv bis argc aus:
- X Es duerfen Optionen (erkannt am ersten Zeichen gemaess Makro is_option)
- X und andere Argumente beliebig gemischt auftreten.
- X Optionen werden in tabp gesucht und durch Linksschieben der restlichen
- X Argumente aus argv entfernt.
- X Sie werden gemaess ihrem tabp-Eintrag behandelt:
- X Bei Nichtvorhandensein oder unerlaubten Werten wird gemeckert,
- X andernfalls die betreffende Variable mit dem Wert der Option bestueckt.
- X Nur Nicht-Optionen bleiben in argv enthalten, ihre Anzahl wird in argc
- X vermerkt.
- X Das Resultat ist die Anzahl angemeckerter Optionen.
- X */
- X int nargc; /* remaining argc after removing options */
- X char **nargv, *p;
- X int errors = 0, error;
- X ARG *argp;
- X for (nargv = ++argv, nargc = 1 /* keep name */; --(*argc) > 0; argv++) {
- X if (!is_option (**argv)) {
- X *nargv++ = *argv; /* No Option -> keep it */
- X nargc++;
- X }
- X else {
- X p = (*argv) + 1; /* Option -> handle it */
- X while (*p) {
- X error = 0;
- X /* One Optionsign can have multiple Options following */
- X if (argp = find_argument ((int)*p, tabp, tabsize)) /* if exists */
- X error = !set_argument (argp, &p); /* then read it */
- X if (!argp || error) { /* if not exists or invalid value */
- X fprintf (stderr, "%s : %s\n", ERRMSG, *argv); /* then #$% */
- X errors++;
- X break;
- X }
- X }
- X }
- X }
- X *argc = nargc;
- X return (errors);
- X}
- X
- X/*---------------------------------------------------------
- X * set_argument
- X *---------------------------------------------------------*/
- X
- Xstatic int set_argument (argp, linep)
- X ARG *argp;
- X char **linep;
- X{
- X /* Holt den Wert fuer die (bereits in argtab als vorhanden erkannte)
- X Option in die zugehoerige in argtab angegebene Variable.
- X Es wird linep so weit weitergeschaltet, wie Daten zur Bestimmung der
- X Variablen entnommen werden, d.h. bei STRING auf NULL, bei CHARACTER
- X um 1 Zeichen, bei INTEGER bis zum Ende der Zahl
- X (oder gar nicht, falls keine kommt) und bei BOOLEAN um 0 oder 1,
- X je nachdem ob ein + oder - angegeben wurde oder nicht.
- X Liefert 0 falls ein nicht erlaubter Wert festgestellt wurde, sonst 0.
- X */
- X#define p (argp->variable)
- X char *oldp;
- X ++(*linep); /* skip Optionname */
- X oldp = *linep;
- X switch (argp->type) {
- X case INTEGER:
- X *p = stoi (linep);
- X return (oldp != *linep);
- X case BOOLEAN:
- X if (**linep == '-' || **linep == '+') { /* + or - given */
- X *p = (**linep == '+');
- X ++(*linep); /* then take it and evaluate */
- X }
- X else /* else assume TRUE */
- X *p = 1;
- X return (1);
- X case CHARACTER:
- X *p = (int)**linep;
- X ++(*linep); /* go on one char */
- X return (*p != 0);
- X case STRING:
- X *(char **)p = *linep;
- X *linep = ""; /* take all the rest */
- X return (1);
- X }
- X#undef p
- X}
- X
- X/*---------------------------------------------------------
- X * find_argument
- X *---------------------------------------------------------*/
- X
- Xstatic ARG* find_argument (optionname, tabp, tabsize)
- X int optionname;
- X ARG *tabp;
- X int tabsize;
- X{
- X for (; --tabsize >= 0; tabp++)
- X if (tabp->arg == optionname)
- X return (tabp);
- X return (0); /* not found */
- X}
- X
- X/*---------------------------------------------------------
- X * print_usage
- X *---------------------------------------------------------*/
- X
- Xextern void print_usage (progname, usage, tabp, tabsize)
- X char *progname, *usage;
- X ARG *tabp;
- X int tabsize;
- X{
- X /* Druckt die Optionsbeschreibungen laut tabp incl. momentaner Werte der
- X zugeh. Variablen sowie zuvor eine "usage:" Zeile mit den Texten
- X progname und usage.
- X */
- X char *p;
- X int i;
- X fprintf (stderr, "\n%s: %s %s\n%s:\n", USAGE, progname,
- X usage, VALID_OPT_ARE);
- X for (i = 0; i < tabsize; i++, tabp++) {
- X fprintf (stderr, "-%c", tabp->arg);
- X p = tabp->errmsg;
- X switch (tabp->type) {
- X case INTEGER:
- X fprintf (stderr, "<num> %-45s (%d)\n",
- X p, *(tabp->variable));
- X break;
- X case BOOLEAN:
- X fprintf (stderr, "<+/-> %-45s (%s)\n",
- X p, *(tabp->variable) ? "TRUE" : "FALSE");
- X break;
- X case CHARACTER:
- X fprintf (stderr, "<ch> %-45s (%c)\n",
- X p, (char)*(tabp->variable));
- X break;
- X case STRING:
- X fprintf (stderr, "<str> %-45s (\"%s\")\n",
- X p, *(char **)tabp->variable);
- X break;
- X }
- X }
- X}
- X
- X
- X/********************* Hilfsfunktionen ************************************/
- X
- X
- X/*---------------------------------------------------------
- X * stoi
- X *---------------------------------------------------------*/
- X
- Xstatic int stoi (instr)
- X register char **instr;
- X{
- X int num = 0;
- X int sign = 0; /* Betrag und neg. Vorzeichen des Resultats */
- X char *str = *instr;
- X while (isspace (*str))
- X str++;
- X if (*str == '-') {
- X sign = -1;
- X str++;
- X }
- X if (*str == '0') {
- X ++str;
- X if (toupper (*str) == 'X') {
- X str++;
- X while(isxdigit(*str)) {
- X num *= 16;
- X num += isdigit (*str) ? *str - '0'
- X : toupper (*str) - 'A'+ 10;
- X str++;
- X }
- X }
- X else {
- X while ('0' <= *str && *str <= '7') {
- X num *= 8;
- X num += *str++ - '0';
- X }
- X }
- X }
- X else {
- X while (isdigit (*str)) {
- X num *= 10;
- X num += *str++ - '0';
- X }
- X }
- X *instr = str;
- X return (sign ? -num : num);
- X}
- X
- X/************* Hauptprogramm zum Testen **********************************/
- X
- X#if 0
- X
- X int a, b, c;
- X char *d;
- X ARG argtab[] = { {'a', BOOLEAN, &a, "Option a" },
- X {'b', CHARACTER,&b, "Option b" },
- X {'c', INTEGER, &c, "Option c" },
- X {'d', STRING , (int*)printf, "Option d" } };
- X
- Xvoid main (int argc, char **argv)
- X{
- X int i, n;
- X printf ("Argumentpointer argv[i]: ");
- X for (i = 0; i < argc; i++)
- X printf ("%d ", (int)argv[i]);
- X printf ("\n");
- X n = getargs (&argc, argv, argtab, ARGTABSIZE (argtab));
- X if (n)
- X print_usage (argv [0], "rabarber", argtab, ARGTABSIZE (argtab));
- X printf ("\n\n RESULTATE (%d): a = %d, b = %c, c = %d, d = \"%s\"\n\n",
- X n, a, (char)b, c, d);
- X printf ("ARGV: ");
- X for (i = 0; i < argc; i++)
- X printf ("<%s> ", argv[i]);
- X}
- X
- X#endif
- X
- END_OF_FILE
- if test 12454 -ne `wc -c <'getargs.c'`; then
- echo shar: \"'getargs.c'\" unpacked with wrong size!
- fi
- # end of 'getargs.c'
- fi
- if test -f 'patchlevel.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'patchlevel.h'\"
- else
- echo shar: Extracting \"'patchlevel.h'\" \(139 characters\)
- sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
- X/* This file is not really used. Please look into cr_texts.h */
- X
- X#define version "C-Refine Version 2.4"
- X#define patchlevel "Patchlevel 1"
- END_OF_FILE
- if test 139 -ne `wc -c <'patchlevel.h'`; then
- echo shar: \"'patchlevel.h'\" unpacked with wrong size!
- fi
- # end of 'patchlevel.h'
- fi
- echo shar: End of archive 3 \(of 4\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 4 archives.
- rm -f ark[1-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-