🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: de.comp.sources.unix
1 messages
1 total messages Started by Frank Kaefer Thu, 06 Aug 1992 21:10
v01i012: Crefine - C language extension, Part04/06
#14
Author: Frank Kaefer
Date: Thu, 06 Aug 1992 21:10
1341 lines
48928 bytes
Submitted-by: prechelt@ira.uka.de (Lutz Prechelt)
Posting-number: Volume 1, Issue 12
Archive-name: crefine/part04

#! /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 6)."
# Contents:  crefine/cr_getln.c crefine/crefine.man
# Wrapped by fkk@stasys on Thu Aug  6 22:49:35 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'crefine/cr_getln.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'crefine/cr_getln.c'\"
else
echo shar: Extracting \"'crefine/cr_getln.c'\" \(20195 characters\)
sed "s/^X//" >'crefine/cr_getln.c' <<'END_OF_FILE'
X
X/*************************************************************************
XProject : C-Refine Precompiler
XModule  : Line Scanner
XAuthor  : Lutz Prechelt, Karlsruhe
XDate    : 08.05.92  Version 17
XCompiler: 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 <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*));
Xstatic int   preprocessor_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*);
X#else
Xstatic int (*scanner) ();
X#endif
X/***** Status *****/
Xstatic int  level,                 /* brace-nesting */
X            just_was, event,       /* event memory */
X            semicolon_count,
X            lines_in_denoter,
X            old_indent;
X
X/*********************** init_scanner ************************************/
X
Xextern void init_scanner ()
X{
X  /* Initializes the state of this module */
X  level = 0;
X  just_was = event = normal_end_of_line;
X  scanner = normal_scanner;
X}
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, and the variables
X     line_no and commanded_line_no.
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_line;
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_line;
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_line;
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_line : refcall_line;
X           {   /* skip_semicolon_and_blanks  (Level 4) */
X           if (*act == ';') {        /* skip semikolon if present */
X              act++;
X              semicolon_count++;
X              if (l->type == refcall_line)
X                 l->type = refcallr_line;   /* 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_line;
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_line || l->type == refcallr_line)
X  && !option_small)
X        warning (Wmuch_indent, NULL, line_no, 3);
X  }
X  assert (!(l->type == refdecl_line && 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, quoted chars or preprocessor
X     directives 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 rest 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 '#' : 
X      {   /* handle_preprocessor_directive  (Level 1) */
X      push (ch);
X      scanner = preprocessor_scanner;
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 right behind it.
X                      if a 'leave' surrounded by blanks is found in front 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 leave_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
X/********************* preprocessor_scanner ******************************/
X
Xstatic int preprocessor_scanner (l)
X  LINE_INFO *l;
X{
X  /* Scans a line with a preprocessor directive on it.
X     If this line contains a #line directive, reads the line number and
X     file name and sets line_no and name_in accordingly.
X     This scanner is called immediately after the # has been seen.
X     The line is copied verbatim.
X  */
X  int ch;
X  ch = *(act++);
X  {   /* skip_whitespace  (Level 1) */
X  for (;;) {
X    switch (ch) {
X      case ' ' :
X      case TAB : push (ch);
X                 break;
X      case '\n':
X      case 0   : scanner = normal_scanner;
X                 return (normal_end_of_line);
X      default  : 
X  goto skip_whitespace_1;
X    }
X    ch = *(act++);
X  }
Xskip_whitespace_1: ;
X  }
X  {   /* try_to_read_line_command  (Level 1) */
X  /* precondition:  ch = <first nonwhitespace character after '#' >
X     postcondition: ch = <first char not belonging to line command>
X  */
X  {   /* read_the_command_token  (Level 2) */
X  /* ch = <first nonwhitespace character after '#' > */
X  if (strncmp ("line", act, 4)) {
X    if (!isdigit (ch))
X  goto try_to_read_line_command_1;
X  }
X  else {
X    push (*(act++));
X    push (*(act++));
X    push (*(act++));
X    push (*(act++));
X    ch = *(act++);
X    if (ch != ' ' && ch != TAB)  /* 'line<something> without whitespace */
X  goto try_to_read_line_command_1;
X  }
X  }
X  {   /* skip_whitespace  (Level 2) */
X  for (;;) {
X    switch (ch) {
X      case ' ' :
X      case TAB : push (ch);
X                 break;
X      case '\n':
X      case 0   : scanner = normal_scanner;
X                 return (normal_end_of_line);
X      default  : 
X  goto skip_whitespace_2;
X    }
X    ch = *(act++);
X  }
Xskip_whitespace_2: ;
X  }
X  {   /* read_the_line_number  (Level 2) */
X  int number = 0;
X  while (isdigit (ch)) {
X    push (ch);
X    number = 10*number + (ch - '0');
X    ch = *(act++);
X  }
X  line_no = commanded_line_no = number - 1;
X  }
X  {   /* skip_whitespace  (Level 2) */
X  for (;;) {
X    switch (ch) {
X      case ' ' :
X      case TAB : push (ch);
X                 break;
X      case '\n':
X      case 0   : scanner = normal_scanner;
X                 return (normal_end_of_line);
X      default  : 
X  goto skip_whitespace_3;
X    }
X    ch = *(act++);
X  }
Xskip_whitespace_3: ;
X  }
X  {   /* read_the_filename  (Level 2) */
X  bool has_quotes = ch == '\"';
X  char *current_letter = name_in;
X  if (has_quotes) {
X    push (ch);
X    ch = *(act++);
X  }
X  for (;;) {
X    switch (ch) {
X      case '\n':
X      case 0   : 
X      {   /* terminate_name_in  (Level 3) */
X      if (current_letter != name_in)  /* if new name present */
X        *current_letter = 0;  /* terminate name */
X      copy_with_doubled_backslashes (name_in, modified_name_in);
X      }
X                 if (has_quotes)
X                   warning (Eunterminated, name_in, line_no, warning_level);
X                 scanner = normal_scanner;
X                 return (normal_end_of_line);
X      case dq  : 
X      {   /* terminate_name_in  (Level 3) */
X      if (current_letter != name_in)  /* if new name present */
X        *current_letter = 0;  /* terminate name */
X      copy_with_doubled_backslashes (name_in, modified_name_in);
X      }
X  goto read_the_filename_1;
X      default  : push (ch);
X                 *(current_letter++) = ch;
X    }
X    ch = *(act++);
X  }
Xread_the_filename_1: ;
X  }
Xtry_to_read_line_command_1: ;
X  }
X  {   /* copy_rest_of_line  (Level 1) */
X  for (;;) {
X    switch (ch) {
X      case '\n':
X      case 0   : scanner = normal_scanner;
X                 return (normal_end_of_line);
X      default  : push (ch);
X    }
X    ch = *(act++);
X  }
X  }
X}
X
END_OF_FILE
if test 20195 -ne `wc -c <'crefine/cr_getln.c'`; then
    echo shar: \"'crefine/cr_getln.c'\" unpacked with wrong size!
fi
# end of 'crefine/cr_getln.c'
fi
if test -f 'crefine/crefine.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'crefine/crefine.man'\"
else
echo shar: Extracting \"'crefine/crefine.man'\" \(23665 characters\)
sed "s/^X//" >'crefine/crefine.man' <<'END_OF_FILE'
X
X
X
XCREFINE(1)               USER COMMANDS                 CREFINE(1)
X
X
X
XNAME
X     crefine - refinement preprocessor for C and C++
X
XSYNOPSIS
X     crefine [ options ] inputfile ...
X
XDESCRIPTION
X     crefine (C-Refine) (spoken like 'see refine') is  a  prepro-
X     cessor  that adds a new language construct to C and C++: the
X     refinement. crefine massages source code  files  to  produce
X     plain  C  output  from C input with refinements or plain C++
X     from C++ with refinements and so on.  The syntax of  refine-
X     ments  is  described  in the USAGE section.  The name of the
X     output file, if not given  explicitly  with  option  -o,  is
X     derived from the name of the input file by removing its last
X     character, if that is an r (which is the filename convention
X     for  C-Refine).   Stdin  and stdout can be referenced as '-'
X     Error messages go to the standard output. The  startup  mes-
X     sage, if not suppressed, goes to standard error.
X
X     C-Refine does not act in any way upon the directives for the
X     C  preprocessor  (except  #line). This especially means that
X     include files have to be processed separately. Usually, this
X     will  not  be necessary, since they do not typically contain
X     anything that C-Refine should work on.  A second consequence
X     is,  that it is possible for C-Refine to give error messages
X     on correct programs, because it does not see the effects  of
X     running  the preprocessor. In these cases you either have to
X     change your source code or run  the  C  preprocessor  before
X     C-Refine.  In  the latter case, C-Refine will correctly pro-
X     cess the #line directives that the preprocessor inserts into
X     your  code in its output and thus give you messages with the
X     correct line numbers.
X
XOPTIONS
X     -a   anyway.  Normally,  if  any  error  was   detected   by
X          C-Refine,   the   output  file  will  automatically  be
X          deleted. This option says not to do so.
X
X     -c   comment refinement names in the  output.  Any  inserted
X          refinement  body  in  the output is titled by a comment
X          giving the refinement name and the  refinement  nesting
X          level.
X
X     -i   indent the #line directives in the resulting output  to
X          the  appropriate  indentation level as indicated by the
X          nesting of refinements.  Not  an  especially  important
X          option,  but  since  this is a true UNIX program, it is
X          present anyway.
X
X     -l   list all refinement names.  The names of all  processed
X          refinements  are  listed  to  the standard output along
X
X
X
XSun Release 4.1     Last change: 12 June 1992                   1
X
X
X
X
X
X
XCREFINE(1)               USER COMMANDS                 CREFINE(1)
X
X
X
X          with their line numbers. I do  not  know  exactly  what
X          this  option  may  be  good  for, but I believe someday
X          somebody will need it.
X
X     -m<ch>
X          message language. Originally, C-Refine was written by a
X          typical  german  programmer  in the typical german pro-
X          grammer schizophrenia situation: as a german the native
X          tongue  is german, as a programmer the native tongue is
X          english. So both languages were supported for the error
X          messages.   Use  -mg  for  German  and  -me for English
X          (which is the default).  Even worse,  since  I  believe
X          the  whole data processing world is much too serious, I
X          liked to have a somewhat humorous version either.   Use
X          -mG  for  german humorous messages, and -mE for english
X          humorous messages.
X
X     -n<num>
X          numbering with #line commands. By default, every inser-
X          tion  of  a  refinement  body is accompanied by a #line
X          preprocessor directive  in  the  output.  This  is  the
X          default  numbering level 3.  By giving a smaller number
X          just after the option character n , the amount of #line
X          directives used can be reduced (level 2 or 1) or set to
X          zero (level 0). What is best depends on the behavior of
X          your  local C or C++ compiler.  Just try it out, begin-
X          ning with the default level 3.
X
X     -o<string>
X          set name of output file explicitly. Normally, the  name
X          of  the  output file is the name of the input file with
X          an 'r' stripped off of the end (and stdout  when  input
X          is stdin). This can be overridden with this option.
X
X     -p   plus. The C++ mode. The only difference between C  mode
X          and  C++ mode for C-Refine is, that in C++ mode the C++
X          doubleslash comment convention is obeyed,  while  in  C
X          mode it is not. This is possible because C-Refine knows
X          very little  about  the  actual  syntax  of  these  two
X          languages.   So in most cases, this difference makes no
X          difference at all.
X
X     -v   verbose mode. Makes C-Refine display a startup message.
X
X     -r<ch>
X          refinement  symbol.  Select  what  character  shall  be
X          recognized  as the refinement symbol in the input file.
X          The character to chose must be  given  on  the  command
X          line   after  the  option  character  r.  This  is  the
X          backquote (ASCII code 95) by default. Since  there  are
X          only  two printable ASCII characters that are unused in
X          the syntax of C (the backquote, code 96, and the dollar
X
X
X
XSun Release 4.1     Last change: 12 June 1992                   2
X
X
X
X
X
X
XCREFINE(1)               USER COMMANDS                 CREFINE(1)
X
X
X
X          or  currency sign, code 36) there is very little choice
X          on a machine with 7 bit character set. This  choice  is
X          further  restricted  because  on  some systems (such as
X          VMS) the dollar sign is acutally being allowed and used
X          for  identifiers.   Some more possiblilities arise when
X          having an 8 bit character set, such as the IBM interna-
X          tional character set (proposed symbol there is the lit-
X          tle double right angle bracket, code 175, which  really
X          looks  nice),  but take into account that any change in
X          refinement symbol is bad for the  portability  of  your
X          source  files.   Note  that  some characters have to be
X          quoted in the shell.
X
X     -R<num>
X          refinement symbol. Same as before, but the  new  symbol
X          is given by its character code instead of by itself.
X
X     -s   strip. Produces smaller  output  by  stripping  of  all
X          indentation,  whether present in the input or generated
X          by C-Refine, and all comments.  This is on by  default.
X          To switch it off, use the syntax -s-
X
X     -w<num>
X          warning level. C-Refine is able to give  various  warn-
X          ings about your source code. These can be suppressed in
X          three stages. The default warning level is 3 (all warn-
X          ings).  You can chose any level from 0 (no warnings) to
X          3 by giving the appropriate  number  after  the  option
X          character w on the command line.
X
X     -B<num>
X          buffer. Select the size of the source code  buffer  (in
X          bytes)  in which C-Refine holds the code for a function
X          while processing it. The default is 150000 bytes.
X
X     -E<num>
X          errors. Select the maximum number of  errors  that  may
X          occur  in  the  input  before C-Refine stops processing
X          prematurely. The default is 20.
X
X     -L<num>
X          lines. Select the maximum number of source  code  lines
X          per  single function that C-Refine is able to hold. The
X          default is 2500.
X
X     -M<num>
X          maximum number of characters per line.  The default  is
X          500.
X
X     -N<num>
X          number of refinements per function.  Selects  the  max-
X          imum  number  of  refinement  declarations  that may be
X
X
X
XSun Release 4.1     Last change: 12 June 1992                   3
X
X
X
X
X
X
XCREFINE(1)               USER COMMANDS                 CREFINE(1)
X
X
X
X          present within any single function. The default is 200.
X
X     -P<num>
X          interval of progress display. For the  homo  ludens  in
X          the  programmer  or  people  with incredibly overloaded
X          machines.   After  every  <num>  lines  of   processing
X          C-Refine echoes the current line number to stdout.  The
X          default  is  0,  which  means  that  this  function  is
X          suppressed.
X
X     -T<num>
X          tab size. Select the number of spaces to  which  a  TAB
X          character expands.  C-Refine expands all TAB characters
X          at the beginning of a line,  i.e.  those  that  act  as
X          indentation. Other TABs are left untouched. The default
X          is 1.
X
X     -W<num>
X          warnings. Select the maximum number  of  warnings  that
X          may occur before C-Refine stops processing prematurely.
X          The default is 30.
X
X     --   indicate 'end of options'. You may use a  dash  as  the
X          input  filename (to use C-Refine as a filter from stan-
X          dard input to standard output), but it  can  be  recog-
X          nized  only  after you have used a double dash to indi-
X          cate that it is not an option.
X
XUSAGE
X     There are three new syntactic elements  with  C-Refine:  the
X     refinement  definition,  the  refinement  call and the leave
X     construct.  The purpose of refinements  is  to  support  the
X     Top-Down  style of programming (a) within a function and (b)
X     in both, thinking and writing.  Essentially, refinements are
X     just  parameterless  macros  with  long  descriptive  names.
X     Refinements are in any case local to a function. They may be
X     called  before they are declared; declaration and definition
X     of a refinement are  one.   The  syntax  of  refinements  as
X     defined  by  C-Refine  is not format free, but lays signifi-
X     cance upon whether a special symbol (the refinement  symbol)
X     is occuring in column 0 or somewhere else.
X
X     Along with the new language constructs are some layout  res-
X     trictions for the program text being defined. This is neces-
X     sary, because (a) the syntax of  the  refinement  constructs
X     breaks  basic  syntactic  rules  of  C  and (b) the C-Refine
X     preprocessor relies on some simple formatting rules, so  its
X     algorithms  can  be  kept  simple and the whole thing small,
X     portable, robust, reliable, and fast.
X
X     Here are the (very informal) descriptions of the syntax  and
X     semantics of the language elements introduced by C-Refine:
X
X
X
XSun Release 4.1     Last change: 12 June 1992                   4
X
X
X
X
X
X
XCREFINE(1)               USER COMMANDS                 CREFINE(1)
X
X
X
X     refinement names
X          A refinement name is just a normal C  identifier,  with
X          one  important  addition: blanks are allowed within (!)
X          it (i.e. anywhere after the first nonblank character of
X          the  name  and  before the last nonblank one); they are
X          equivalent to underscores. The end of a refinement name
X          is  always detected by the appearence of a special sym-
X          bol, typically a semicolon, a colon or an operator.   A
X          refinement name must, however, be on a single line.
X
X     refinement calls
X          A refinement call consists of  the  refinement  symbol,
X          immediately  followed by a refinement name. The refine-
X          ment symbol must not be in colums 0 of the source line.
X          Refinement   calls  are  principally  allowed  anywhere
X          within  a  function.  The  called  refinement  must  be
X          defined  in  that function, although the definition may
X          (and usually will) appear later  than  the  call.   The
X          semantics  of  a  refinement call is as follows: A pro-
X          cedural refinement (i.e. one that contains at least one
X          semicolon in its body) is inserted instead of its call,
X          surrounded by a pair of curly braces. This insertion is
X          recursively  applied  to  nested refinements.  A valued
X          refinement (i.e. one that contains just  an  expression
X          and  no  semicolon  in its body) is inserted instead of
X          its call, surrounded by a pair  of  parentheses.   This
X          insertion  is  recursively  applied  to  nested  valued
X          refinements.  So procedural refinements can  be  called
X          anywhere  where  a  block  statement  is  legal. Valued
X          refinements can be called anywhere where a  parenthesed
X          expression  is  legal.   An  illegal form of refinement
X          call will be detected by C-Refine.
X
X     refinement definitions
X          a refinement definition consists of the refinement sym-
X          bol,  immediately  followed  by a refinement name, fol-
X          lowed by a colon. The  refinement  symbol  must  be  in
X          column 0 of the source line. Refinement definitions are
X          allowed only on block nesting  level  1,  i.e.  in  the
X          outermost  block  of a function.  The body of a refine-
X          ment is examined to decide what type of  refinement  it
X          is: All refinements that contain one or more semicolons
X          in their body, that are not part of a comment,  charac-
X          ter  denoter  or  string denoter, are called procedural
X          refinements, since they contain statements.  All  other
X          refinements  are  called valued refinements, since they
X          only contain an expression and  thus  return  a  value.
X          Illegal  syntax  of  a  refinement  declaration and the
X          declaration of refinements that are never used will  be
X          detected by C-Refine.
X
X     leave
X
X
X
XSun Release 4.1     Last change: 12 June 1992                   5
X
X
X
X
X
X
XCREFINE(1)               USER COMMANDS                 CREFINE(1)
X
X
X
X          The leave construct may be used from  within  any  pro-
X          cedural  refinement  at  any place where a statement is
X          legal. It consists of the keyword leave followed by the
X          refinement  symbol,  followed by a refinement name ref.
X          The semantics of this construct is, that a goto  state-
X          ment  is  inserted instead of the leave construct, that
X          jumps to a point right after the last statement of  the
X          refinement  ref.  For  this  to  be  legal  ref must be
X          present in the current  static  nesting  of  refinement
X          calls.  This means that not only the current refinement
X          can be left with leave, but any number  of  refinements
X          that  are statically nested at that point of your code.
X          Illegal use of  the  leave  construct  is  detected  by
X          C-Refine.
X
X          As by now, I assume, almost any understanding that  may
X          initially have been there, will probably have vanished.
X          I will try to get it back to you by means of  the  fol-
X          lowing  example. This is a (very simple-minded) version
X          of the Sieve of Eratosthenes. It should not be  thought
X          that  I  believe  the  refinement technique to be espe-
X          cially well suited to this problem, but  this  was  the
X          smallest 'real' problem I could think of to demonstrate
X          at least most of what  the  possibilities  of  C-Refine
X          are. So here it is:
X
X          #define MAX        10000
X          #define PRIME      0
X          #define NON_PRIME  1
X
X          static int sieve[MAX+1];
X
X          int 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
X
X
XSun Release 4.1     Last change: 12 June 1992                   6
X
X
X
X
X
X
XCREFINE(1)               USER COMMANDS                 CREFINE(1)
X
X
X
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          To make the self documentation aspect of C-Refine  more
X          clear,  look  at the following example: A function that
X          tests, whether its parameters form a  pythagorean  tri-
X          ple:
X          bool pythagorean (int x, int y, int 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
X
X
XSun Release 4.1     Last change: 12 June 1992                   7
X
X
X
X
X
X
XCREFINE(1)               USER COMMANDS                 CREFINE(1)
X
X
X
X          `z is hypotenuse:
X            z*z == x*x + y*y
X
X          }
X          This is good style: you write down just what  you  want
X          to  express  and  with an optimizing compiler such code
X          will also be perfectly efficient.  Try to imagine  what
X          this  would  have  looked like, if it had all been in a
X          single parenthesesed expression.
X
XFILES
X     crefine           the executable program
X     filename.cr       C-with-refinements input file.
X     filename.c        C output file.
X     filename.ccr      C++-with-refinements input file.
X     filename.cc       C++ output file.
X
XEXAMPLES
X     crefine firsttest.cr
X          process the input file firsttest.cr producing the  out-
X          put file firsttest.c
X
X     crefine -p+ -q+ -o outfile -w 2 next.ccr
X          process the C++-Refine inputfile next.ccr producing the
X          output   file   outfile.    The   startup   message  is
X          suppressed, C++ mode is selected and the warning  level
X          is reduced to 2.
X
X     crefine -pqw2 -ooutfile next.ccr
X          same as before.
X
X     crefine -o outfile -p+a-l-qw2 next.ccr
X          same as before.
X
X     crefine -c -s- -n0 -T8 last.cr
X          process the inputfile last.cr in order to get  a  read-
X          able  C  source.   Comments  and  indentation  are  not
X          stripped, inserted refinement bodies are tagged  by  an
X          additional  comment  giving  the  refinement  name, all
X          #line preprocessor directives are left out and  leading
X          tabs expand to 8 spaces.
X
X     crefine -cs-n0T8 last.cr
X          same as before.
X
XDIAGNOSTICS
X     The warnings and error messages  are  intended  to  be  self
X     explanatory.  If  you  do not understand one of them anyway:
X     chose a different language for the messages (see option -m),
X     get yourself a dictionary or interpreter and try again.
X
X
X
X
X
XSun Release 4.1     Last change: 12 June 1992                   8
X
X
X
X
X
X
XCREFINE(1)               USER COMMANDS                 CREFINE(1)
X
X
X
XSEE ALSO
X     cc(1), ccr(1), cpp(1), make(1)
X
XBUGS
X     Since preprocessor directives are not handled  by  C-Refine,
X     strange  things can happen if you use #ifdef or #if. This is
X     especially the case if you use these directives to put large
X     comments  into  your source files: if there are any comments
X     or string literals (double quotes) or char literals  (single
X     quotes)  beginning in that area that are not properly closed
X     within it, C-Refine will run to nirvana searching for  their
X     end  and  give you lots of wrong error and warning messages.
X     Watch out for apostrophes (e.g. in "don't") especially!
X
X     Those people, who use such stupid macros as
X        #define BEGIN {
X        #define END   }
X     or similar craizy stuff, will have to change their habits or
X     run the preprocessor first in order to use C-Refine.
X
X     When using a call to  a  value  returning  refinement  as  a
X     parameter  to  a macro, most preprocessors will complain the
X     #line directive when numbering level 3 is being used. -n2 or
X     -n1  can  be used to overcome this problem although this may
X     be a bit unsatisfactory.
X
X     The output of C-Refine may be code that exceeds certain com-
X     piler  limits  of  your C or C++ compiler. Since the body of
X     every procedural refinement is enclosed in a block  and  the
X     body  of  every  value  returning  refinement is enclosed in
X     parentheses, the block nesting limits or expression complex-
X     ity  limits  of  your  compiler may be reached when you make
X     very heavy use of nested refinements.
X
X     Some compilers may handle the  #line  directive  improperly,
X     yielding wrongly tagged error messages. Bad luck.
X
X     Probably C-Refine will also work with Objective-C, but I  am
X     not  absolutely  sure about that. Perhaps somebody will give
X     me some feedback on this issue ?
X
X     There should be a mode to use C-Refine for Lisp also.
X
X     And for several other languages, too.
X
X     C-Refine reacts poor on some types of syntactic errors.
X
X     C-Refine will not work good if your filenames  contain  cer-
X     tain strange characters (e.g. double quotes).
X
X     In C++, when a "leave" has to jump across  a  variable  ini-
X     tialization,  some compilers will complain, that the goto is
X
X
X
XSun Release 4.1     Last change: 12 June 1992                   9
X
X
X
X
X
X
XCREFINE(1)               USER COMMANDS                 CREFINE(1)
X
X
X
X     illegal. This is not true, because the  goto  jumps  to  (or
X     even  beyond)  the very end of the block where that variable
X     is in [precisely: the jump is to an empty  statement,  which
X     is  the last statement in the block], but these compilers do
X     not recognize that fact.
X
X     You must have C-Refine in order to be able  to  use  refine-
X     ments.   This  is actually not a bug in C-Refine but in your
X     compiler.
X
X     Although much easier than without, programming is still dif-
X     ficult  even  with  C-Refine.  This is a bug in you. Contact
X     darwin@nirvana.edu or root@headquarter.heaven.gov  for  com-
X     plaints.
X
XVERSION
X     This manpage is for C-Refine Version 3.0  (internally  named
X     Version 17)
X
XAUTHOR
X     Lutz Prechelt  (prechelt@ira.uka.de)
X     Institut fuer Programmstrukturen und Datenorganisation
X     Universitaet Karlsruhe
X     D-7500 Karlsruhe
X     Germany
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
XSun Release 4.1     Last change: 12 June 1992                  10
X
X
X
END_OF_FILE
if test 23665 -ne `wc -c <'crefine/crefine.man'`; then
    echo shar: \"'crefine/crefine.man'\" unpacked with wrong size!
fi
# end of 'crefine/crefine.man'
fi
echo shar: End of archive 4 \(of 6\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 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
-- 
Frank Kaefer # fkk@stasys.sta.sub.org # Starnberg, Germany
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