home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume22 / crefine / part02 < prev    next >
Encoding:
Text File  |  1991-08-26  |  54.5 KB  |  1,554 lines

  1. Newsgroups: comp.sources.misc
  2. From: Lutz Prechelt <prechelt@i41s14.ira.uka.de>
  3. Subject:  v22i064:  crefine - C-Refine preprocessor, Part02/04
  4. Message-ID: <1991Aug26.032408.15153@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: f783b54bbb32f724abc7cd619662fd4d
  6. Date: Mon, 26 Aug 1991 03:24:08 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: Lutz Prechelt <prechelt@i41s14.ira.uka.de>
  10. Posting-number: Volume 22, Issue 64
  11. Archive-name: crefine/part02
  12. Environment: UNIX, MS-DOS, TOS, C, C++, Objective-C
  13.  
  14. #! /bin/sh
  15. # into a shell via "sh file" or similar.  To overwrite existing files,
  16. # type "sh file -c".
  17. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  18. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  19. # Contents:  INSTALL crefine.cr crefine.man
  20. # Wrapped by kent@sparky on Sun Aug 25 21:56:46 1991
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. echo If this archive is complete, you will see the following message:
  23. echo '          "shar: End of archive 2 (of 4)."'
  24. if test -f 'INSTALL' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'INSTALL'\"
  26. else
  27.   echo shar: Extracting \"'INSTALL'\" \(280 characters\)
  28.   sed "s/^X//" >'INSTALL' <<'END_OF_FILE'
  29. XTo install crefine just put the executable file "crefine" into
  30. Xa directory where executables reside, such as "/usr/local/bin" or
  31. X"/tools/bin" under Unix and put the Manualpage into a directory where
  32. XManpages reside such as "/usr/local/man/man1" or "/tools/man/man1".
  33. X
  34. XThat's all.
  35. END_OF_FILE
  36.   if test 280 -ne `wc -c <'INSTALL'`; then
  37.     echo shar: \"'INSTALL'\" unpacked with wrong size!
  38.   fi
  39.   # end of 'INSTALL'
  40. fi
  41. if test -f 'crefine.cr' -a "${1}" != "-c" ; then 
  42.   echo shar: Will not clobber existing file \"'crefine.cr'\"
  43. else
  44.   echo shar: Extracting \"'crefine.cr'\" \(29204 characters\)
  45.   sed "s/^X//" >'crefine.cr' <<'END_OF_FILE'
  46. X/*************************************************************************
  47. XProject : C-Refine Precompiler
  48. XModule  : main module
  49. XAuthor  : Lutz Prechelt, Karlsruhe
  50. XDate    : 10.06.91  Version 16
  51. XCompiler: ANSI C, C-Refine 2.3 (bootstrapped)
  52. X**************************************************************************/
  53. X/*
  54. X    Copyright (C) 1988,89,90,91 by Lutz Prechelt, Karlsruhe
  55. X
  56. X    This program is free software; you can redistribute it and/or modify
  57. X    it under the terms of the GNU General Public License as published by
  58. X    the Free Software Foundation; either version 1, or (at your option)
  59. X    any later version.
  60. X    This program is distributed in the hope that it will be useful,
  61. X    but WITHOUT ANY WARRANTY; without even the implied warranty of
  62. X    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  63. X    GNU General Public License for more details.
  64. X    You should have received a copy of the GNU General Public License
  65. X    along with this program; if not, write to the Free Software
  66. X    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  67. X*/
  68. X
  69. X/************************************************************************
  70. X*********************** C - R e f i n e *********************************
  71. X*************************************************************************/
  72. X
  73. X#if 0
  74. XREMARK:
  75. X  This program was originally written using german identifiers and
  76. X  comments. I worked through it to change this (at least in most parts)
  77. X  but please do not flame me if there are relicts from this state.
  78. X  I did not find a sensible replacement for the german word 'Klammer' that
  79. X  may stand for any of the characters ( ) [ ] { }  so sometimes I still
  80. X  use the german one.
  81. X
  82. XVariants:
  83. X#define deutsch   fuer deutsche Meldungen statt englische
  84. X#define ms_dos    for  MS-DOS Operating System (Compiler Microsoft C 5.0)
  85. X#define unix      for  Unix
  86. X#define vms       for  VMS
  87. X#define ansi      for  ANSI-C Compiler
  88. X
  89. XFor version changes see refinement startup message and file cr_texts.h
  90. X
  91. X============================== History: ====================================
  92. X
  93. X
  94. XVersion 1.0  (Alpha)    (0, 1)
  95. X
  96. X1987
  97. X  procedural refinements only
  98. X  not comfortable, few error messages
  99. X
  100. X
  101. XVersion 2.0  (Alpha)    (2, 3)
  102. X
  103. XFeb. 88
  104. X  value-returning refinements,
  105. X  improved error handling,
  106. X  Options comment, feedback, list, numbering, refinementsymbol, small
  107. X
  108. X
  109. XVersion 2.1  (Beta)     (4, 5)
  110. X
  111. X09.04.88  ( --> Martin, Ihno, Volker, Beat)
  112. X  improved error handling
  113. X  triple error messages (german, english, german nonsense),
  114. X  Context description in error messages,
  115. X  Options anyway, feedback, ibm chars, message type, tabsize, warning level
  116. X  Expires 31.07.88
  117. X
  118. X
  119. XVersion 2.2             (6, 7, 8)
  120. X
  121. X08.07.88   ( --> Martin)
  122. X  corr: Changes blanks in namen to underscrores again (like in Version 1.0)
  123. X        (otherwise error in goto occur)
  124. X  corr: Removed semicolon after value-returning refinements kept
  125. X        (via introduction of refcallr)
  126. X  improved error handling: Warning for "often used" only for
  127. X  "big" refinements.
  128. X03.08.88
  129. X  corr: When inserting file names in "#line"-commands, backslashes
  130. X        are doubled (backslash is Escape symbol in C string denoters)
  131. X13.09.88
  132. X  corr: empty refinements will not give syntax errors anymore.
  133. X
  134. X
  135. XVersion 2.3             (9, 10, 11, 12, 13)
  136. X
  137. X29.09.88 ( --> Martin, Ihno)
  138. X  corr: refinements with just 1 semicolon are enclosed in braces also
  139. X        (to avoid "else"-conflict)
  140. X  C++ Mode (i.e. // Kommentare) as option p
  141. X17.03.89
  142. X  "std.h" introduced,  #ifdefs for environment switches introduced.
  143. X  Look-through, further "refinementized", several small corrections
  144. X  ported to SUN-OS (Berkeley-Unix)
  145. X  Size restrictions released (500 -> 800 lines, 50 -> 100 Refinements)
  146. X18.03.89
  147. X  dito, expires 31.07.89
  148. X11.09.89
  149. X  ported to PCS maschine under Munix 5.3 (System V)
  150. X  further #ifdefs for deutsch, expire
  151. X  The switches are given in the Makefile
  152. X11.09.89
  153. X  dito, expires 31.10.89
  154. X
  155. X
  156. XVersion 2.4             (14, 15, 16)
  157. X
  158. X27.08.90 ( --> Uni)
  159. X  Line numbering switchable in 4 levels.
  160. X  Quiet-Option
  161. X  Buffersizes selectable via option.
  162. X  New name handling for input/output files
  163. X  
  164. X23.01.91 ( --> Uni, Usenet announcement, iraun1)
  165. X  Names and Comments changed to english (was german before)
  166. X  error in level switching of line numbering fixed.
  167. X  
  168. X10.06.91 ()
  169. X  History translated to english
  170. X  some small corrections
  171. X  corr: REF_INFO storage has to be 0-initialized, 
  172. X        so use calloc instead of malloc
  173. X  Eliminated duplication of function declarations for ansi and non-ansi
  174. X  by introduction of the A(a) macro in std.h  
  175. X
  176. X=============================================================================
  177. X#endif
  178. X
  179. X#include <stdio.h>
  180. X#include <string.h>
  181. X#include <malloc.h>
  182. X#include <time.h>
  183. X
  184. X#define DATA_HERE     /* Here the data declarations are NOT extern */
  185. X#include "cr_decl.h"  /* global Functions, Types and Data */
  186. X#include "getargs.h"
  187. X
  188. X
  189. X/******************* lokal Functions ************************************/
  190. X
  191. Xextern int  main A((int argc,  charp *argv));
  192. Xextern int  crefine A((int argc, charp *argv));
  193. Xstatic void process_c_refine A((FILE *in, FILE *out));
  194. Xstatic void process_line A((FILE *out, int semicolons));
  195. Xstatic void insert_refinements A((FILE *out));
  196. Xstatic void insert_refinement A((FILE *out, LINE_INFO *l, int startindent,
  197. X                               int recursive_level));
  198. Xstatic void line_cmd A((FILE* out, int nr, int indent, int min_level));
  199. Xstatic void put_indent A((FILE *out, int how_much));
  200. Xstatic void put_line A((FILE *out, LINE_INFO *line, int additional_indent,
  201. X                      int min_linenumbering_level));
  202. Xstatic int  refinement_nr A((char *refinementname));
  203. Xstatic void allocate A((charp *buffer, unsigned *size, unsigned minsize));
  204. Xstatic void copy_with_doubled_backslashes A((char *string, char *copy));
  205. Xstatic void do_expire A((int day, int month, int year_in_century));
  206. Xstatic void reset_l_r_s A((void));
  207. X
  208. X/*********************** Lokal Data ************************************/
  209. X
  210. X/***** line info, refinement info *****/
  211. Xstatic LINES l;           /* line info */
  212. Xstatic int   l_pos;
  213. X
  214. Xstatic REFS  r;           /* refinement info */
  215. Xstatic int   r_pos;
  216. X
  217. X/***** Status *****/
  218. Xstatic int   old_level,          /* level at line before */
  219. X             commanded_line_no;  /* line_no according to last line_cmd */
  220. X
  221. X/***** Sonstiges *****/
  222. Xstatic char  blanks[] =  /* indents are made from this. */
  223. X  "                                                                       ";
  224. X/* "blanks" is taken as  72 Blanks long (see put_indent) */
  225. X
  226. Xstatic option_msg;
  227. X
  228. X#define refdecl_line(i)  /* line no of refinement head of r[i] */\
  229. X                          (l [r[i].firstentry].line_no)
  230. X
  231. X/******************************** crefine *********************************/
  232. X
  233. Xextern int main (argc, argv)      /* MAIN */
  234. X  int   argc;
  235. X  charp argv[];
  236. X{
  237. X  return (crefine (argc, argv));
  238. X}
  239. X
  240. Xstatic ARG argtab[] = {
  241. X#if  deutsch
  242. X  {'a', BOOLEAN, &option_anyway,
  243. X   "alle: Ausgabedatei trotz Fehlern nicht loeschen" },
  244. X  {'c', BOOLEAN, &option_comment,  "Refinementnamen-Kommentare in Ausgabe" },
  245. X  {'e', BOOLEAN, &option_indent,   "#line Kommandos einruecken" },
  246. X  {'f', BOOLEAN, &option_feedback, "Fortschrittsanzeige (Zeilennummern)" },
  247. X#if ms_dos
  248. X  {'I', BOOLEAN, &option_ibmchars, 
  249. X   "erlaube IBM internationale Zeichen fuer Namen" },
  250. X#endif
  251. X  {'k', BOOLEAN, &option_comment,  "Refinementnamen-Kommentare in Ausgabe" },
  252. X  {'l', BOOLEAN, &option_list,     "liste alle Refinementnamen" },
  253. X  {'m', CHARACTER, &option_msg,    
  254. X   "Meldungen in: d=deutsch, e=english, sonst humorig" },
  255. X  {'n', INTEGER, &numbering_level,
  256. X   "Stufe der Numerierung mit #line Kommandos" },
  257. X  {'p', BOOLEAN, &option_cplusplus,"C++ Modus" },
  258. X  {'q', BOOLEAN, &option_cplusplus,"keine Startmeldung ausgeben" },
  259. X  {'r', CHARACTER, &refinementsymbol, "Refinementsymbol (als Zeichen)" },
  260. X  {'R', INTEGER, &refinementsymbol, "Refinementsymbol (als Zahl)" },
  261. X  {'s', BOOLEAN, &option_small,    "strippen: Kompaktifizierte Ausgabe" },
  262. X  {'w', INTEGER, &warning_level,   "Warnstufe (0 - 3)" }
  263. X  {'F', INTEGER, &maxerrors,       "Max. Anzahl Fehler" },
  264. X  {'L', INTEGER, &b_size,          "Max. Zeilenlaenge" },
  265. X  {'N', INTEGER, &maxref,          "Max. Refinements je Funktion" },
  266. X  {'P', INTEGER, &s_size,          "Codepuffer in Bytes" },
  267. X  {'T', INTEGER, &tabsize,         "Tabulatorgroesse" },
  268. X  {'W', INTEGER, &maxwarnings,     "Max. Anzahl Warnungen" },
  269. X  {'Z', INTEGER, &maxline,         "Max. Zeilen je Funktion" },
  270. X#else
  271. X  {'a', BOOLEAN, &option_anyway,   "anyway: don't delete output on errors" },
  272. X  {'c', BOOLEAN, &option_comment,  "comment refinement names in output" },
  273. X  {'f', BOOLEAN, &option_feedback, "feedback that you work" },
  274. X  {'i', BOOLEAN, &option_indent,   "indent the #line commands" },
  275. X#if ms_dos
  276. X  {'I', BOOLEAN, &option_ibmchars,
  277. X   "enable IBM International Charset for names" },
  278. X#endif
  279. X  {'l', BOOLEAN, &option_list,     "list all refinement names" },
  280. X  {'m', CHARACTER, &option_msg,  
  281. X   "Messages in: g=german, e=english, else sense of humor ?" },
  282. X  {'n', INTEGER, &numbering_level,
  283. X   "level of numbering with #line commands" },
  284. X  {'p', BOOLEAN, &option_cplusplus,"C++ mode" },
  285. X  {'q', BOOLEAN, &option_quiet,    "quiet mode (no startup message)" },
  286. X  {'r', CHARACTER, &refinementsymbol, "refinementsymbol (character form)" },
  287. X  {'R', INTEGER, &refinementsymbol, "refinementsymbol (decimal form)" },
  288. X  {'s', BOOLEAN, &option_small,    "small compactified output" },
  289. X  {'w', INTEGER, &warning_level,   "warning level (0 - 3)" },
  290. X  {'B', INTEGER, (int*)&s_size,    "code buffer in bytes" },
  291. X  {'E', INTEGER, &maxerrors,       "max errors" },
  292. X  {'L', INTEGER, (int*)&maxline,   "max lines per function" },
  293. X  {'N', INTEGER, (int*)&maxref,    "max refinements per function" },
  294. X  {'T', INTEGER, &tabsize,         "tab size" },
  295. X  {'W', INTEGER, &maxwarnings,     "max warnings" },
  296. X#endif
  297. X};
  298. X
  299. X
  300. Xextern int crefine (argc, argv)    /* C-REFINE */
  301. X  int   argc;
  302. X  charp argv[];
  303. X{
  304. X  /* Analyses options and opens files.
  305. X     Then calls  process_c_refine and closes files again.
  306. X     Returns the number of errors that have been found
  307. X  */
  308. X  bool two_filenames_given;
  309. X  int  wrong_options;
  310. X  FILE *in, *out;
  311. X  `analysis of options;
  312. X  if (wrong_options || argc>>1 != 1) {
  313. X     print_usage (argv[0], usagestring[msg_type],
  314. X                  argtab, ARGTABSIZE (argtab));
  315. X    `startup message;
  316. X     exit (100);
  317. X  }
  318. X  if (!option_quiet)
  319. X    `startup message;
  320. X  `open files and complain if necessary;
  321. X  `reserve memory and complain if necessary;
  322. X  /* here we go: */
  323. X  rewind (in);  /* Begin at the beginning, then proceed until you come */
  324. X                /* to the end, there stop.   (from: Alice in Wonderland) */
  325. X  process_c_refine (in, out);
  326. X  fclose (in);
  327. X  fclose (out);   /* Schliessen vor unlink noetig ! */
  328. X  if (errors && !option_anyway) /* don't produce errorneous outputfiles */
  329. X     unlink (name_out);         /* delete file */
  330. X  if (errors || warnings)
  331. X#if deutsch
  332. X     fprintf (stderr, "%d Fehler%s   %d Warnung%s   Ausgabedatei %s\n",
  333. X              errors,   errors   != 1 ? "" : "",
  334. X              warnings, warnings != 1 ? "en" : "",
  335. X              errors && !option_anyway ?
  336. X                 "geloescht" : (errors ? "dennoch erhalten" 
  337. X                                       : "ist fragwuerdig"));
  338. X#else
  339. X     fprintf (stderr, "%d error%s   %d warning%s   Output %s\n",
  340. X              errors,   errors   != 1 ? "s" : "",
  341. X              warnings, warnings != 1 ? "s" : "",
  342. X              errors && !option_anyway ?
  343. X                 "deleted" : (errors ? "kept anyway" : "is doubtful"));
  344. X#endif
  345. X  return (errors);
  346. X
  347. X`analysis of options:
  348. X  option_anyway = option_feedback = option_indent = option_comment
  349. X                = option_list = option_ibmchars = option_cplusplus
  350. X                = false;
  351. X  option_small = true;
  352. X  numbering_level = 3;
  353. X#if deutsch
  354. X  option_msg  = 'd';
  355. X  msg_type    =  0;  /* deutsche Meldungen als Standard */
  356. X#else
  357. X  option_msg  = 'e';
  358. X  msg_type    =  1;  /* english warnings and errors as default */
  359. X#endif
  360. X  refinementsymbol = std_refinementsymbol;
  361. X  tabsize          = 1;
  362. X  warning_level    = 3;
  363. X  maxline          = STD_MAXLINE;
  364. X  maxref           = STD_MAXREF;
  365. X  b_size           = STD_MAXLINELENGTH;
  366. X  s_size           = STD_S_SIZE;
  367. X  maxerrors        = STD_MAXERRORS;
  368. X  maxwarnings      = STD_MAXWARNINGS;
  369. X  wrong_options = getargs (&argc, argv, argtab, ARGTABSIZE (argtab));
  370. X  if (option_small) {
  371. X     tabsize = 1;
  372. X  }
  373. X  if (option_msg == 'd' || option_msg == 'D' ||
  374. X      option_msg == 'g' || option_msg == 'G')
  375. X     msg_type = 0;
  376. X  else if (option_msg == 'e' || option_msg == 'E')
  377. X     msg_type = 1;
  378. X  else
  379. X     msg_type = 2;
  380. X  two_filenames_given = argc == 3;
  381. X
  382. X`startup message:
  383. X  fprintf (stderr, 
  384. X           "C-Refine Precompiler   %s\n", versionstring[msg_type]);
  385. X  fprintf (stderr, 
  386. X           "Copyright (C) 1988,89,90,91  Lutz Prechelt, Karlsruhe\n");
  387. X
  388. X`open files and complain if necessary:
  389. X  strcpy (name_in, argv[1]);            /* get */
  390. X#if ms_dos
  391. X  in = fopen (name_in, "rt");  /* read, translated mode */
  392. X#else
  393. X  in = fopen (name_in, "r");  /* read */
  394. X#endif
  395. X  if (in == NULL || ferror (in)) {
  396. X     fprintf (stderr, Eopen[msg_type], name_in);
  397. X     exit (100);
  398. X  }
  399. X  copy_with_doubled_backslashes (name_in, modified_name_in);
  400. X  if (two_filenames_given) {            /* if second name given */
  401. X     strcpy (name_out, argv[2]);        /* take it as it is */
  402. X  }
  403. X  else {                                /* else */
  404. X     strcpy (name_out, argv[1]);        /* take first name */
  405. X     if (name_out[strlen(name_out)-1] == 'r')
  406. X       name_out[strlen(name_out)-1] = 0; /* remove 'r' from end */
  407. X     else
  408. X       strcat (name_out, "RRR");         /* or append 'RRR' */
  409. X  }
  410. X#if ms_dos
  411. X  out = fopen (name_out, "wt");  /* write, translated mode */
  412. X#else
  413. X  out = fopen (name_out, "w");  /* write */
  414. X#endif
  415. X  if (out == NULL || ferror (out)) {
  416. X     fprintf (stderr, Eopen[msg_type], name_out);
  417. X     exit (100);
  418. X  }
  419. X
  420. X`reserve memory and complain if necessary:
  421. X  b      = malloc (b_size);
  422. X  r      = (REFS)calloc ((maxref+1), sizeof (REF_INFO));
  423. X  l      = (LINES)malloc ((maxline+1) * sizeof (LINE_INFO));
  424. X  s_root = malloc (s_size);
  425. X  if (!(b && s_root && r && l)) {
  426. X     fprintf (stderr, Ememory[msg_type]);
  427. X     exit (100);
  428. X  }
  429. X
  430. X}
  431. X
  432. X/************************ process_c_refine *********************************/
  433. X
  434. Xstatic void process_c_refine (in, out)
  435. X  FILE *in, *out;
  436. X{
  437. X  /* Reads the file 'in' to the end line by line via 'get_line' and
  438. X     generates the C source code by inserting the refinement bodies for
  439. X     the calls.
  440. X     Generates error messages for undeclares refinements and warnings for
  441. X     unused or often used ones.
  442. X     Uses the variables stop_processing, errors, warnings,
  443. X     s, l, r and the option indicators.
  444. X  */
  445. X  commanded_line_no = line_no = 0;
  446. X  reset_l_r_s ();
  447. X  if (numbering_level > 0)
  448. X    /* we get a linefeed anyway! */
  449. X    fprintf (out, "#line 1 \"%s\"", modified_name_in);
  450. X  while (!stop_processing)
  451. X     `handle next line;
  452. X  if (option_feedback)
  453. X     cout (line_no);
  454. X  free (s_root);
  455. X
  456. X`handle next line:
  457. X     int semicolons = 0;
  458. X     if (option_feedback && line_no % FEEDBACK_INTERVAL == 0)
  459. X        cout (line_no);
  460. X     if (ferror (in))
  461. X        fatal_error (Ereadinput, l[l_pos-1].start, line_no);
  462. X     if (ferror (out))
  463. X        fatal_error (Ewriteoutput, NULL, line_no);
  464. X     get_line (in, l+l_pos, &semicolons);
  465. X     process_line (out, semicolons);
  466. X}
  467. X
  468. X/************************** process_line ************************************/
  469. X
  470. Xstatic void process_line (out, semicolons)
  471. X  FILE *out;
  472. X  int   semicolons;
  473. X{
  474. X  /* Works on the lines up to the current line l[l_pos] in the way that
  475. X     it decides whether a function has ended and thus the insertion of
  476. X     refinements has to be started.
  477. X     On level 0 all lines are copied from in to out immediately.
  478. X     After a state change from level 0 to level 1 all lines (along with
  479. X     a lineinfo) are kept until the next transition to level 0 and the
  480. X     refinement info is being built.
  481. X     If necessary, error messages for overflow or refinement errors and
  482. X     warnings for not or multiply used refinements are generated.
  483. X  */
  484. X  if (r_pos > 0)
  485. X     r[r_pos - 1].semicolons += semicolons;
  486. X  if (old_level == 0)
  487. X     `we came from level 0;
  488. X  else
  489. X     `we were inside a function or so;
  490. X
  491. X`we came from level 0:
  492. X   assert (l_pos == 0);   /* nothing can be stored from level 0 */
  493. X   if (l[0].level == 0 || stop_processing)
  494. X      `remains on level 0 so just copy it;
  495. X   else
  496. X      `function has begun;
  497. X
  498. X`remains on level 0 so just copy it:
  499. X   if (l[0].type != normal && l[0].type != empty)
  500. X      error (Elevel0_ref, l[0].start, line_no);
  501. X   put_line (out, &l[0], 0, 1);
  502. X   reset_l_r_s ();
  503. X
  504. X`function has begun:
  505. X   error_in_this_function = false;
  506. X   old_level = l[0].level;    /* neuen Level merken */
  507. X   if (l[0].type == refdecl && r_pos < maxref) {  /* empty function */
  508. X      r[r_pos].name         = l[0].start;
  509. X      r[r_pos].firstentry   = 0;
  510. X      r[r_pos].active       = false;
  511. X      r[r_pos++].semicolons = 0;
  512. X      warning (Wempty_function, NULL, line_no - 1, 3);
  513. X   }
  514. X   l_pos++;                   /* store line */
  515. X
  516. X`we were inside a function or so:
  517. X   if (l[l_pos].level == 0 || stop_processing)
  518. X      `but now we are outside;
  519. X   else
  520. X      `and still keep being in;
  521. X
  522. X`but now we are outside:
  523. X   insert_refinements (out);
  524. X   put_line (out, &l[l_pos-1], 0, 1);  /* last line (Blockklammer) */
  525. X   put_line (out, &l[l_pos], 0, 1);    /* the level 0 line */
  526. X   error_in_this_function = false;
  527. X   reset_l_r_s ();
  528. X
  529. X`and still keep being in:
  530. X   if (l[l_pos].type == refdecl && r_pos < maxref) {
  531. X      r[r_pos].name         = l[l_pos].start;   /* enter Refinement */
  532. X      r[r_pos].active       = false;
  533. X      r[r_pos].firstentry   = l_pos;
  534. X      r[r_pos++].semicolons = 0;
  535. X   }
  536. X   old_level = l[l_pos].level;/* store new level */
  537. X   l_pos++;                   /* store line */
  538. X   if (l_pos >= maxline)
  539. X      fatal_error (Elines_in_func, l[l_pos].start, line_no);
  540. X   if (s - s_root >= s_size - 150)  /* Reserve too small */
  541. X      fatal_error (Ebytes_in_func, l[l_pos].start, line_no);
  542. X}
  543. X
  544. X/************************ insert_refinements ******************************/
  545. X
  546. Xstatic void insert_refinements (out)
  547. X  FILE *out;
  548. X{
  549. X  /* Replaces the refinement calls with the bodies, after the whole function
  550. X     has been read in.
  551. X     In the output #line statements are generated, except if option 
  552. X     numbering_level is zero. 
  553. X     Comments and indentations are thrown away if option_small is true.
  554. X     Comments stating the refinement names are inserted in the output if
  555. X     option_comment is true.
  556. X  */
  557. X  int  i, end;
  558. X  bool extern_stop = stop_processing;  /* Protect last function against */
  559. X  stop_processing  = false;            /* local use of this variable */
  560. X  r[r_pos].firstentry = l_pos-1;       /* line of Blockklammer */
  561. X  r[r_pos].name       = NULL;
  562. X  `generate refinement list if necessary;
  563. X  `find last line to insert;
  564. X  for (i = 0; i <= end; i++) {  /* lines up to first ref. declaration */
  565. X      switch (l[i].type) {
  566. X         case refcall  :
  567. X         case refcallr :
  568. X                `insert refinement;
  569. X                break;
  570. X         case leave    :
  571. X                `whatshallthatbe;
  572. X                break;
  573. X         case normal   :
  574. X                `insert normal line;
  575. X                break;
  576. X         case empty    :
  577. X                putc ('\n', out);
  578. X                commanded_line_no++;
  579. X                break;
  580. X         case refdecl  :
  581. X         default       :
  582. X                 assert (false);
  583. X      }
  584. X  }
  585. X  `maybe give sermon on refinements;
  586. X  stop_processing = stop_processing || extern_stop;  /* Merging-Restore */
  587. X
  588. X`generate refinement list if necessary:
  589. X  if (option_list && r_pos > 0) {
  590. X     fputc ('\n', stdout);
  591. X     for (i = 0; i < r_pos; i++)
  592. X         fprintf (stdout, "(%d) %s\n", refdecl_line (i), r[i].name);
  593. X  }
  594. X
  595. X`find last line to insert:
  596. X  end = r[0].firstentry - 1;
  597. X  while (l[end].type == empty)   /* suppress trailing empty lines */
  598. X     end--;
  599. X
  600. X`insert refinement:
  601. X   insert_refinement (out, l+i, l[i].indent, 1);
  602. X   if (stop_processing)
  603. X      return;
  604. X
  605. X`whatshallthatbe:
  606. X  assert (false);
  607. X
  608. X`insert normal line:
  609. X   put_line (out, &l[i], 0, 1);
  610. X
  611. X`maybe give sermon on refinements:
  612. X  for (i = 0; i < r_pos; i++)
  613. X      if (r[i].semicolons > 50)
  614. X         warning (Wlong_ref, l[r[i].firstentry].start,
  615. X                  refdecl_line (i), 3);
  616. X      else if (r[i].calls > 5 && r[i].semicolons > 2)
  617. X         warning (Wref_often_used, l[r[i].firstentry].start,
  618. X                  refdecl_line (i), 3);
  619. X      else if (r[i].calls == 0)
  620. X         warning (Wref_unused, l[r[i].firstentry].start,
  621. X                  refdecl_line (i), 1);
  622. X}
  623. X
  624. X/************************* insert_refinement ******************************/
  625. X
  626. Xstatic void insert_refinement (out, z, startindent, recursive_level)
  627. X  FILE *out;
  628. X  LINE_INFO *z;
  629. X  int  startindent, recursive_level;
  630. X{
  631. X  /* Looks for the refinement to insert by its name, computes the range
  632. X     of lines to work on and does then do the same as insert_refinements
  633. X     does.
  634. X     If necessary the refinement name is given as a comment before the
  635. X     body is inserted.
  636. X     The refinement body is enclosed in delimiters:
  637. X       if ref.semicolons == 0 in parentheses (on first and last line)
  638. X       if ref.semicolons >= 1 in curly braces (on separate lines)
  639. X     The refinement calls are counted and maybe messages generated.
  640. X     In case of leave-statements the refinement that shall be leave'd is
  641. X     marked, so a label can be generated.
  642. X     Errors:
  643. X       1. Refinement is not declared
  644. X       2. recursive call to refinement
  645. X       3. leave is impossible because the refinement is not
  646. X          present in static call hierarchy
  647. X  */
  648. X  int i;
  649. X  int  nr, ref_startindent, end;
  650. X  assert (startindent > 0);
  651. X  nr = refinement_nr (`name);  /* search for refinement */
  652. X  if (nr == -1) {
  653. X     error (Eref_not_decl, `name, z->line_no);
  654. X     return;
  655. X  }
  656. X  else if (r[nr].active)
  657. X     `complain for recursive refinement call;
  658. X  else {
  659. X     r[nr].calls++;           /* register the call */
  660. X     r[nr].active   = true;
  661. X     r[nr].leave_it = false;
  662. X  }
  663. X  end = r[nr+1].firstentry - 1;
  664. X  while (l[end].type == empty)   /* suppress trailing empty lines */
  665. X     end--;
  666. X  i = r[nr].firstentry + 1;
  667. X  if (i > end)
  668. X     warning (Wref_empty, l[r[nr].firstentry].start, refdecl_line (nr), 2);
  669. X  else
  670. X     `insert the refinement;
  671. X  r[nr].active = false;
  672. X  return;
  673. X
  674. X`complain for recursive refinement call:
  675. X   error (Erecursive_ref, `name, z->line_no);
  676. X   stop_processing = true;
  677. X   return;
  678. X
  679. X`insert the refinement:
  680. X  /* for an empty refinement, this is not called at all! */
  681. X  `write indentation and opening klammer;
  682. X  ref_startindent = l[i].indent;
  683. X  for ( ; i <= end; i++) {
  684. X      switch (l[i].type) {
  685. X         case refcall  :
  686. X         case refcallr :
  687. X                `insert refinement;
  688. X                break;
  689. X         case leave    :
  690. X                `insert goto statement;
  691. X                break;
  692. X         case normal   :
  693. X                `insert normal line;
  694. X                break;
  695. X         case empty    :
  696. X                putc ('\n', out);
  697. X                commanded_line_no++;
  698. X                break;
  699. X         case refdecl  :
  700. X         default       :
  701. X                 assert (false);
  702. X      }
  703. X  }
  704. X  if (r[nr].leave_it)
  705. X     `generate label;
  706. X  `write closing klammer;
  707. X
  708. X`write indentation and opening klammer:
  709. X  int sc = r[nr].semicolons;
  710. X  if (sc > 0)
  711. X     put_indent (out, startindent);
  712. X  putc (sc > 0 ? '{' : '(', out);  /* Klammer auf */
  713. X  if (option_comment && sc > 0)
  714. X     fprintf (out, Tlistline[msg_type], `name, recursive_level);
  715. X
  716. X`insert refinement:
  717. X   insert_refinement (out, l+i,
  718. X                      startindent + l[i].indent
  719. X                                  - ref_startindent,
  720. X                      recursive_level+1);
  721. X
  722. X`insert goto statement:
  723. X   int leave_nr = refinement_nr (l[i].start);
  724. X   if (leave_nr == -1)
  725. X      error (Eunknown_leave, l[i].start, l[i].line_no);
  726. X   else if (!r[leave_nr].active)
  727. X      error (Eleave_unpresent, l[i].start, l[i].line_no);
  728. X   else {
  729. X      r[leave_nr].leave_it = true;
  730. X      put_indent (out, startindent);
  731. X      fprintf (out, "goto %s_%d;",
  732. X               l[i].start, r[leave_nr].calls);
  733. X   }
  734. X
  735. X`insert normal line:
  736. X   put_line (out, &l[i], startindent - ref_startindent, `num level);
  737. X   
  738. X`num level:
  739. X  r[nr].semicolons == 0 ? 3 : 2
  740. X
  741. X`generate label:
  742. X  fprintf (out, "\n%s_%d: ;", `name, r[nr].calls);
  743. X  commanded_line_no++;
  744. X
  745. X`write closing klammer:
  746. X  int sc = r[nr].semicolons;
  747. X  if (sc > 0) {
  748. X     put_indent (out, startindent);
  749. X     putc ('}', out);
  750. X  }
  751. X  else {
  752. X     putc (')', out);
  753. X     if (z->type == refcallr)  /* semicolon has been removed illegaly */
  754. X        putc (';', out);
  755. X  }
  756. X
  757. X`name:
  758. X  z->start
  759. X}
  760. X
  761. X/************************* line_cmd **************************************/
  762. X
  763. Xstatic void line_cmd (out, nr, indent, min_level)
  764. X  FILE *out;
  765. X  int  nr;
  766. X  int  indent;
  767. X  int  min_level;
  768. X{
  769. X  /* Writes a "preprocessor #line directive" including file name if
  770. X     requested.
  771. X     Is suppressed, if min_level is less than numbering_level.
  772. X     Using numbering_level, option_indent, commanded_line_no and name_in
  773. X  */
  774. X  if (numbering_level >= min_level) {
  775. X     if (option_indent)
  776. X        put_indent (out, indent);
  777. X     else
  778. X        putc ('\n', out);
  779. X     fprintf (out, "#line %d \"%s\"", nr, modified_name_in);
  780. X     commanded_line_no = nr-1; /* #line 3  means: next comes line 3 ! */
  781. X  }
  782. X}
  783. X
  784. X/********************** put_indent **************************************/
  785. X
  786. Xstatic void put_indent (out, how_far)
  787. X  FILE *out;
  788. X  int how_far;
  789. X{
  790. X  putc ('\n', out);      /* begin newline */
  791. X  commanded_line_no++;
  792. X  if (!option_small)
  793. X     fwrite (blanks, how_far > 72 ? 72 : (how_far < 0 ? 0 : how_far),
  794. X             1, out);
  795. X}
  796. X
  797. X/*************************** put_line ***********************************/
  798. X
  799. Xstatic void put_line (out, line, additional_indent, min_level)
  800. X  FILE       *out;
  801. X  LINE_INFO  *line;    /* pointer for efficiency (is big object) */
  802. X  int        additional_indent;
  803. X  int        min_level;
  804. X{
  805. X  /* Writes the line 'line' to 'out' with the appropriate indentation 
  806. X     (which is the line's indentation plus additional_indent).
  807. X     If the current line numbering is not right a line_cmd is made before.
  808. X  */
  809. X  if (line->line_no != commanded_line_no + 1)
  810. X     line_cmd (out, line->line_no, line->indent + additional_indent,
  811. X               min_level);
  812. X  if (line->type == empty) {    /* for empty lines: nothing */
  813. X     putc ('\n', out);
  814. X     commanded_line_no++;
  815. X     return;
  816. X  }
  817. X  else if (option_small || (!option_indent && *line->start == '#')) {
  818. X     putc ('\n', out);
  819. X     commanded_line_no++;
  820. X  }
  821. X  else
  822. X     put_indent (out,
  823. X                 line->indent + additional_indent);  /* starts new line */
  824. X  assert (line->start != NULL);
  825. X  fputs (line->start, out);
  826. X#if debug
  827. X  fprintf (stdout, "put:\"%s\"\n", line->start);
  828. X#endif
  829. X}
  830. X
  831. X/********************** refinement_nr ************************************/
  832. X
  833. Xstatic int refinement_nr (name)
  834. X  char *name;
  835. X{
  836. X  /* computes the number of a refinement from its name 'name'.
  837. X     Uses r from 0 to r_pos. Returns the number or -1 if undeclared.
  838. X     If the refinement is declared more than once an error message is 
  839. X     generated.
  840. X  */
  841. X  int i, match = -1, matches = 0;
  842. X  assert (name != NULL);
  843. X  for (i = 0; i < r_pos; i++)
  844. X      if (!strcmp (name, r[i].name)) {
  845. X         match = i;
  846. X         matches++;
  847. X      }
  848. X  if (matches > 1)
  849. X     error (Eref_multi_decl, r[match].name, refdecl_line (match));
  850. X  return (match);
  851. X}
  852. X
  853. X/********************* Auxiliary functions ******************************/
  854. X
  855. Xstatic void copy_with_doubled_backslashes (string, copy)
  856. X  char *string, *copy;
  857. X{
  858. X  /* copies the string string to the location copy. All backslash
  859. X     characters (code 92) in string are copied twice, so for example
  860. X     "back\slas\\h" is copied to "back\\slas\\\\h".
  861. X     The purpose of this is to make the copy usable as a C string denoter,
  862. X     in which the backslash is interpreted as an escape symbol.
  863. X     No checks are made, thus there must be enough memory allocated
  864. X     to make the copy.
  865. X  */
  866. X  assert (string != NULL);
  867. X  assert (copy != NULL);
  868. X  while (*string != 0) {
  869. X     *copy = *string;
  870. X     string++;
  871. X     if (*copy == 92) {      /* is backslash ? */
  872. X       *(copy + 1) = 92;     /* then put another and */
  873. X       copy += 2;            /* proceed two bytes */
  874. X     }
  875. X     else                    /* else */
  876. X       copy++;               /* proceed one byte */
  877. X  }
  878. X  *copy = 0;
  879. X}
  880. X
  881. X
  882. Xstatic void do_expire (day, month, year)
  883. X  int day, month, year;
  884. X{
  885. X  long act_time;
  886. X  struct tm *t;
  887. X  time (&act_time);
  888. X  t = localtime (&act_time);
  889. X  month--;   /* localtime uses months 0 - 11 ! */
  890. X  if (`has expired) {
  891. X     fprintf (stderr, "\n%s\n\n", Thas_expired[msg_type]);
  892. X     exit (100);
  893. X  }
  894. X
  895. X`has expired :
  896. X  t->tm_year > year || (t->tm_year == year && t->tm_mon > month) ||
  897. X  (t->tm_year == year && t->tm_mon == month && t->tm_mday > day)
  898. X}
  899. X
  900. X
  901. Xstatic void reset_l_r_s ()
  902. X{
  903. X  /* Sets LINE_INFO- and REF_INFO-Arrays 'l' and 'r' into 
  904. X     their empty state.
  905. X  */
  906. X  int i;
  907. X  for (i = 0; i <= r_pos; i++) { /* Alle Refinements loeschen */
  908. X      r[i].name  = NULL;
  909. X      r[i].calls = 0;
  910. X  }
  911. X  s = s_root;                    /* Zeilenspeicher loeschen */
  912. X  l_pos = r_pos = old_level = 0;
  913. X}
  914. X
  915. X
  916. END_OF_FILE
  917.   if test 29204 -ne `wc -c <'crefine.cr'`; then
  918.     echo shar: \"'crefine.cr'\" unpacked with wrong size!
  919.   fi
  920.   # end of 'crefine.cr'
  921. fi
  922. if test -f 'crefine.man' -a "${1}" != "-c" ; then 
  923.   echo shar: Will not clobber existing file \"'crefine.man'\"
  924. else
  925.   echo shar: Extracting \"'crefine.man'\" \(22380 characters\)
  926.   sed "s/^X//" >'crefine.man' <<'END_OF_FILE'
  927. X
  928. X
  929. X
  930. XCREFINE(1)               USER COMMANDS                 CREFINE(1)
  931. X
  932. X
  933. X
  934. XNAME
  935. X     crefine - refinement preprocessor for C and C++
  936. X
  937. XSYNOPSIS
  938. X     crefine [ options ] inputfile [
  939. Xoutputfile ]
  940. X
  941. XDESCRIPTION
  942. X     crefine (C-Refine) (spoken like 'see refine') is  a  prepro-
  943. X     cessor  that adds a new language construct to C and C++: the
  944. X     refinement. crefine massages a source code
  945. Xfile  to  produce
  946. X     plain  C  output  from C input with refinements or plain C++
  947. X     from C++ with refinements.  The  syntax  of  refinements  is
  948. X     described  in  the USAGE section.  Only a single source file
  949. X     may be processed with one call; the name of the output file,
  950. X     if  not given, is derived from the name of the input file by
  951. X     removing its last character, if that is an r (which  is  the
  952. X     filename convention for C-Refine).  If the last character of
  953. X     the input filename is not an r  ,  the  output  filename  is
  954. X     derived  from it by appending RRR instead.  Input and output
  955. X     is always to and from named files. Error messages go to  the
  956. X     standard  output.  The  startup  message, if not suppressed,
  957. X     goes to standard error.
  958. X
  959. X     C-Refine does not act in any way upon the directives for the
  960. X     C  preprocessor.  This  especially  means that include files
  961. X     have to be processed separately. Usually, this will  not  be
  962. X     necessary, since they do not typically contain anything that
  963. X     C-Refine should work on.  A second consequence is,  that  it
  964. X     is  possible  for C-Refine to give error messages on correct
  965. X     programs, because it does not see the effects of running the
  966. X     preprocessor.  In these cases you either have to change your
  967. X     source code or run the C preprocessor before C-Refine.
  968. X
  969. XOPTIONS
  970. X     -a   anyway.  Normally,  if  any  error  was   detected   by
  971. X          C-Refine,   the   output  file  will  automatically  be
  972. X          deleted. This option says not to do so.
  973. X
  974. X     -c   comment refinement names in the  output.  Any  inserted
  975. X          refiement  body  in  the  output is titled by a comment
  976. X          giving the refinement name and the  refinement  nesting
  977. X          level.
  978. X
  979. X     -f   feedback that you work. For the homo ludens in the pro-
  980. X          grammer  or people with incredibly overloaded machines.
  981. X          Shows running line numbers on standard error.
  982. X
  983. X     -i   indent the #line directives in the resulting output  to
  984. X          the  appropriate  indentation level as indicated by the
  985. X          nesting of refinements.  Not  an  especially  important
  986. X          option,  but  since  this is a true UNIX program, it is
  987. X          present anyway.
  988. X
  989. X
  990. X
  991. XSun Release 4.1    Last change: 22 August 1991                  1
  992. X
  993. X
  994. X
  995. X
  996. X
  997. X
  998. XCREFINE(1)               USER COMMANDS                 CREFINE(1)
  999. X
  1000. X
  1001. X
  1002. X     -l   list all refinement names.  The names of all  processed
  1003. X          refinements  are  listed  to  the standard output along
  1004. X          with their line numbers. I do  not  know  exactly  what
  1005. X          this  option  may  be  good  for, but I believe someday
  1006. X          somebody will need it.
  1007. X
  1008. X     -m<ch>
  1009. X          message language. Originally, C-Refine was written by a
  1010. X          typical  german  programmer  in the typical german pro-
  1011. X          grammer schizophrenia situation: as a german the native
  1012. X          tongue  is german, as a programmer the native tongue is
  1013. X          english. So both languages were supported for the error
  1014. X          messages.   Even  worse, since I believe the whole data
  1015. X          processing world is much too serious, I liked to have a
  1016. X          humourous  version either. So now any of the characters
  1017. X          d,D,g,G immediately after the option character m  gives
  1018. X          you  german  error  and  warning messages, e or E gives
  1019. X          english ones (which, for sake of  internationality,  is
  1020. X          the  default)  and every other letter lets you stick to
  1021. X          (german) humor.
  1022. X
  1023. X     -n<num>
  1024. X          numbering with #line commands. By default, every inser-
  1025. X          tion  of  a  refinement  body is accompanied by a #line
  1026. X          preprocessor directive  in  the  output.  This  is  the
  1027. X          default  numbering level 3.  By giving a smaller number
  1028. X          just after the option character n , the amount of #line
  1029. X          directives used can be reduced (level 2 or 1) or set to
  1030. X          zero (level 0). What is best depends on the behavior of
  1031. X          your  local C or C++ compiler.  Just try it out, begin-
  1032. X          ning with the default level 3.
  1033. X
  1034. X     -p   plus. The C++ mode. The only difference between C  mode
  1035. X          and  C++ mode for C-Refine is, that in C++ mode the C++
  1036. X          doubleslash comment convention is obeyed,  while  in  C
  1037. X          mode it is not. This is possible because C-Refine knows
  1038. X          very little  about  the  actual  syntax  of  these  two
  1039. X          languages.   So in most cases, this difference makes no
  1040. X          difference at all.
  1041. X
  1042. X     -q   quiet mode. Suppresses the startup message of C-Refine.
  1043. X
  1044. X     -r<ch>
  1045. X          refinement  symbol.  Select  what  character  shall  be
  1046. X          recognized  as the refinement symbol in the input file.
  1047. X          The character to chose must be  given  on  the  command
  1048. X          line  immediately after the option character r. This is
  1049. X          the backquote (ASCII code 95) by default.  Since  there
  1050. X          are only two printable ASCII characters that are unused
  1051. X          in the syntax of C (the backquote,  code  96,  and  the
  1052. X          dollar  or currency sign, code 36) there is very little
  1053. X          choice on a machine with  7  bit  character  set.  This
  1054. X
  1055. X
  1056. X
  1057. XSun Release 4.1    Last change: 22 August 1991                  2
  1058. X
  1059. X
  1060. X
  1061. X
  1062. X
  1063. X
  1064. XCREFINE(1)               USER COMMANDS                 CREFINE(1)
  1065. X
  1066. X
  1067. X
  1068. X          choice  is  further  restricted because on some systems
  1069. X          (such as VMS) the dollar sign is acutally being allowed
  1070. X          and  used  for  identifiers.   Some more possiblilities
  1071. X          arise when having an 8 bit character set, such  as  the
  1072. X          IBM  international character set (proposed symbol there
  1073. X          is the little double right  angle  bracket,  code  175,
  1074. X          which  really  looks  nice), but take into account that
  1075. X          any change in refinement symbol is bad for  the  porta-
  1076. X          bility of your source files.
  1077. X
  1078. X     -R<num>
  1079. X          refinement symbol. Same as before, but the  new  symbol
  1080. X          is given by its character code instead of by itself.
  1081. X
  1082. X     -s   strip. Produces smaller  output  by  stripping  of  all
  1083. X          indentation,  whether present in the input or generated
  1084. X          by C-Refine, and all comments.  This is on by  default.
  1085. X          To switch it off, use the syntax -s-
  1086. X
  1087. X     -w<num>
  1088. X          warning level. C-Refine is able to give  various  warn-
  1089. X          ings about your source code. These can be suppressed in
  1090. X          three stages. The default warning level is 3 (all warn-
  1091. X          ings).  You can chose any level from 0 (no warnings) to
  1092. X          3 by giving the  appropriate  number  right  after  the
  1093. X          option character w on the command line.
  1094. X
  1095. X     -B<num>
  1096. X          buffer. Select the size of the source  code  buffer  in
  1097. X          which C-Refine holds the code for a function while pro-
  1098. X          cessing it. The default is 150000 bytes.
  1099. X
  1100. X     -E<num>
  1101. X          errors. Select the maximum number of  errors  that  may
  1102. X          occur  in  the  input  before C-Refine stops processing
  1103. X          prematurely. The default is 20.
  1104. X
  1105. X     -L<num>
  1106. X          lines. Select the maximum number of source  code  lines
  1107. X          per  single function that C-Refine is able to hold. The
  1108. X          default is 2500.
  1109. X
  1110. X     -N<num>
  1111. X          number of refinements per function.  Selects  the  max-
  1112. X          imum  number  of  refinement  declarations  that may be
  1113. X          present within any single function. The default is 200.
  1114. X
  1115. X     -T<num>
  1116. X          tab size. Select the number of spaces to  which  a  TAB
  1117. X          character expands.  C-Refine expands all TAB characters
  1118. X          at the beginning of a line,  i.e.  those  that  act  as
  1119. X          indentation. Other TABs are left untouched. The default
  1120. X
  1121. X
  1122. X
  1123. XSun Release 4.1    Last change: 22 August 1991                  3
  1124. X
  1125. X
  1126. X
  1127. X
  1128. X
  1129. X
  1130. XCREFINE(1)               USER COMMANDS                 CREFINE(1)
  1131. X
  1132. X
  1133. X
  1134. X          is 1.
  1135. X
  1136. X     -W<num>
  1137. X          warnings. Select the maximum number  of  warnings  that
  1138. X          may occur before C-Refine stops processing prematurely.
  1139. X          The default is 30.
  1140. X
  1141. XUSAGE
  1142. X     There are three new syntactic elements  with  C-Refine:  the
  1143. X     refinement  definition,  the  refinement  call and the leave
  1144. X     construct.  The purpose of refinements  is  to  support  the
  1145. X     Top-Down  style of programming (a) within a function and (b)
  1146. X     in both, thinking and writing.  Essentially, refinements are
  1147. X     just  parameterless  macros  with  long  descriptive  names.
  1148. X     Refinements are in any case local to a function. They may be
  1149. X     called  before they are declared; declaration and definition
  1150. X     of a refinement are  one.   The  syntax  of  refinements  as
  1151. X     defined  by  C-Refine  is not format free, but lays signifi-
  1152. X     cance upon whether a special symbol (the refinement  symbol)
  1153. X     is occuring in column 0 or somewhere else.
  1154. X
  1155. X     Along with the new language constructs are some layout  res-
  1156. X     trictions for the program text being defined. This is neces-
  1157. X     sary, because (a) the syntax of  the  refinement  constructs
  1158. X     breaks  basic  syntactic  rules  of  C  and (b) the C-Refine
  1159. X     preprocessor relies on some simple formatting rules, so  its
  1160. X     algorithms  can  be  kept  simple and the whole thing small,
  1161. X     portable, robust, reliable and fast.
  1162. X
  1163. X     Here are the (very informal) descriptions of the syntax  and
  1164. X     semantics of the language elements introduced by C-Refine:
  1165. X
  1166. X     refinement names
  1167. X          A refinement name is just a
  1168. Xnormal C  identifier,  with
  1169. X          one  important  addition: blanks are allowed within (!)
  1170. X          it (i.e. anywhere after the first nonblank character of
  1171. X          the  name  and  before the last nonblank one); they are
  1172. X          equivalent to underscores. The end of a refinement name
  1173. X          is  always detected by the appearence of a special sym-
  1174. X          bol, typically a semicolon, a colon or an operator.   A
  1175. X          refinement name must, however, be on a single line.
  1176. X
  1177. X     refinement calls
  1178. X          A refinement call consists of
  1179. Xthe  refinement  symbol,
  1180. X          immediately  followed by a refinement name. The refine-
  1181. X          ment symbol must not be in colums 0 of the source line.
  1182. X          Refinement   calls  are  principally  allowed  anywhere
  1183. X          within  a  function.  The  called  refinement  must  be
  1184. X          defined  in  that function, although the definition may
  1185. X          (and usually will) appear later  than  the  call.   The
  1186. X          semantics  of  a  refinement call is as follows: A pro-
  1187. X          cedural refinement (i.e.
  1188. Xone that contains at least one
  1189. X
  1190. X
  1191. X
  1192. XSun Release 4.1    Last change: 22 August 1991                  4
  1193. X
  1194. X
  1195. X
  1196. X
  1197. X
  1198. X
  1199. XCREFINE(1)               USER COMMANDS                 CREFINE(1)
  1200. X
  1201. X
  1202. X
  1203. X          semicolon in its body) is inserted instead of its call,
  1204. X          surrounded by a pair of curly braces. This insertion is
  1205. X          recursively  applied  to  nested refinements.  A valued
  1206. X          refinement (i.e. one that contains just
  1207. Xan  expression
  1208. X          and  no  semicolon  in its body) is inserted instead of
  1209. X          its call, surrounded by a pair  of  parentheses.   This
  1210. X          insertion  is  recursively  applied  to  nested  valued
  1211. X          refinements.  So procedural refinements can  be  called
  1212. X          anywhere  where  a  block  statement  is  legal. Valued
  1213. X          refinements can be called anywhere where a  parenthesed
  1214. X          expression  is  legal.   An  illegal form of refinement
  1215. X          call will be detected by C-Refine.
  1216. X
  1217. X     refinement definitions
  1218. X          a refinement definition consists of the refinement sym-
  1219. X          bol,  immediately  followed  by a refinement name, fol-
  1220. X          lowed by a colon. The  refinement  symbol  must  be  in
  1221. X          column 0 of the source line. Refinement definitions are
  1222. X          allowed only on block nesting  level  1,  i.e.  in  the
  1223. X          outermost  block  of a function.  The body of a refine-
  1224. X          ment is examined to decide what type of  refinement  it
  1225. X          is: All refinements that contain one or more semicolons
  1226. X          in their body, that are not part of a comment,  charac-
  1227. X          ter  denoter  or  string denoter, are called
  1228. Xprocedural
  1229. X          refinements, since they contain
  1230. Xstatements.  All  other
  1231. X          refinements  are  called valued
  1232. Xrefinements, since they
  1233. X          only contain an expression and  thus  return  a  value.
  1234. X          Illegal  syntax  of  a  refinement  declaration and the
  1235. X          declaration of refinements that are never used will  be
  1236. X          detected by C-Refine.
  1237. X
  1238. X     leave
  1239. X          The leave construct may be used
  1240. Xfrom  within  any  pro-
  1241. X          cedural  refinement  at  any place where a statement is
  1242. X          legal. It consists of the keyword leave followed by the
  1243. X          refinement  symbol,  followed by a refinement name ref.
  1244. X          The semantics of this construct is, that a goto  state-
  1245. X          ment  is  inserted instead of the leave construct, that
  1246. X          jumps to a point right after the last statement of  the
  1247. X          refinement  ref.  For  this  to  be  legal  ref must be
  1248. X          present in the current  static  nesting  of  refinement
  1249. X          calls.  This means that not only the current refinement
  1250. X          can be left with leave, but any number  of  refinements
  1251. X          that  are statically nested at that point of your code.
  1252. X          Illegal use of  the  leave  construct  is  detected  by
  1253. X          C-Refine.
  1254. X
  1255. X          As by now, I assume, almost any understanding that  may
  1256. X          initially have been there, will probably have vanished.
  1257. X          I will try to get it back to you by means of  the  fol-
  1258. X          lowing  example. This is a (very simple-minded) version
  1259. X          of the Sieve of Eratosthenes. It should not be  thought
  1260. X
  1261. X
  1262. X
  1263. XSun Release 4.1    Last change: 22 August 1991                  5
  1264. X
  1265. X
  1266. X
  1267. X
  1268. X
  1269. X
  1270. XCREFINE(1)               USER COMMANDS                 CREFINE(1)
  1271. X
  1272. X
  1273. X
  1274. X          that  I  believe  the  refinement technique to be espe-
  1275. X          cially well suited to this problem, but  this  was  the
  1276. X          smallest 'real' problem I could think of to demonstrate
  1277. X          at least most of what  the  possibilities  of  C-Refine
  1278. X          are. So here it is:
  1279. X
  1280. X          #define MAX        10000
  1281. X          #define PRIME      0
  1282. X          #define NON_PRIME  1
  1283. X
  1284. X          static int sieve[MAX+1];
  1285. X
  1286. X          int main ()
  1287. X          {
  1288. X            `initialize;
  1289. X            `do sieve;
  1290. X            `make output;
  1291. X            return (0);
  1292. X
  1293. X          `initialize:
  1294. X            int current;
  1295. X            for (current = 2; current <= MAX; current++)
  1296. X              sieve[current] = PRIME;
  1297. X
  1298. X          `do sieve:
  1299. X            int current_prime = 1;
  1300. X            for (;;) {
  1301. X              `find next bigger prime;  /* perhaps STOP here */
  1302. X              `delete all multiples of current_prime;
  1303. X            }
  1304. X
  1305. X          `find next bigger prime:
  1306. X            int current_candidate = current_prime + 1;
  1307. X            while (sieve[current_candidate] == NON_PRIME)
  1308. X              if (current_candidate == MAX)
  1309. X                leave `do sieve;    /* leave two refinements at once */
  1310. X              else
  1311. X                current_candidate++;
  1312. X            /* now current_candidate is a prime (or we leave `sieve) */
  1313. X            current_prime = current_candidate;
  1314. X
  1315. X          `delete all multiples of current_prime:
  1316. X            int current = `first multiple of current_prime;
  1317. X            while (current <= MAX) {
  1318. X              sieve[current] = NON_PRIME;
  1319. X              current += current_prime;
  1320. X            }
  1321. X
  1322. X          `first multiple of current_prime:
  1323. X            2 * current_prime
  1324. X
  1325. X          `make output:
  1326. X
  1327. X
  1328. X
  1329. XSun Release 4.1    Last change: 22 August 1991                  6
  1330. X
  1331. X
  1332. X
  1333. X
  1334. X
  1335. X
  1336. XCREFINE(1)               USER COMMANDS                 CREFINE(1)
  1337. X
  1338. X
  1339. X
  1340. X            int current;  /* different from 'current' above */
  1341. X            printf ("The primes between 2 and %d are0, MAX);
  1342. X            for (current = 2; current <= MAX; current++)
  1343. X              if (`current is prime)
  1344. X                printf ("%5d ", current);
  1345. X
  1346. X          `current is prime:
  1347. X            sieve[current] == PRIME
  1348. X
  1349. X          } /* end of main() */
  1350. X
  1351. X          /***** End of example *****/
  1352. X          To make the self documentation aspect of C-Refine  more
  1353. X          clear,  look  at the following example: A function that
  1354. X          tests, whether its parameters form a  pythagorean  tri-
  1355. X          ple:
  1356. X          bool pythagorean (double x, double y, double z)
  1357. X          {
  1358. X            return (`all legs positive && `one is hypotenuse)
  1359. X
  1360. X          `all legs positive:
  1361. X             x > 0  &&  y > 0  &&  z > 0
  1362. X
  1363. X          `one is hypotenuse:
  1364. X            `x is hypotenuse || `y is hypotenuse || `z is hypotenuse
  1365. X
  1366. X          `x is hypotenuse:
  1367. X            x*x == y*y + z*z
  1368. X
  1369. X          `y is hypotenuse:
  1370. X            y*y == x*x + z*z
  1371. X
  1372. X          `z is hypotenuse:
  1373. X            z*z == x*x + y*y
  1374. X
  1375. X          }
  1376. X          This is good style: you write down just what  you  want
  1377. X          to  express  and  with an optimizing compiler such code
  1378. X          will also be perfectly efficient.  Try to imagine  what
  1379. X          this  would  have  looked like, if it had all been in a
  1380. X          single parenthesesed expression.
  1381. X
  1382. XFILES
  1383. X     bin/crefine       the executable program
  1384. X     filename.cr       C-with-refinements input file.
  1385. X     filename.c        C output file.
  1386. X     filename.ccr      C++-with-refinements input file.
  1387. X     filename.cc       C++ output file.
  1388. X     otherfileRRR      output file from input file otherfile
  1389. X
  1390. XEXAMPLES
  1391. X     crefine firsttest.cr
  1392. X
  1393. X
  1394. X
  1395. XSun Release 4.1    Last change: 22 August 1991                  7
  1396. X
  1397. X
  1398. X
  1399. X
  1400. X
  1401. X
  1402. XCREFINE(1)               USER COMMANDS                 CREFINE(1)
  1403. X
  1404. X
  1405. X
  1406. X          process the input file firsttest.cr producing the  out-
  1407. X          put file firsttest.c
  1408. X
  1409. X     crefine -p+ -q+ -w2 next.ccr outfile
  1410. X          process the C++ inputfile next.ccr producing the output
  1411. X          file  outfile.   The startup message is suppressed, C++
  1412. X          mode is selected and the warning level is reduced to 2.
  1413. X
  1414. X     crefine -pqw2 next.ccr outfile
  1415. X          same as before.
  1416. X
  1417. X     crefine -p+a-l-qw2 next.ccr outfile
  1418. X          same as before.
  1419. X
  1420. X     crefine -c -s- -n0 -T8 last.cr
  1421. X          process the inputfile last.cr in order to get  a  read-
  1422. X          able  C  source.   Comments  and  indentation  are  not
  1423. X          stripped, inserted refinement bodies are tagged  by  an
  1424. X          additional  comment  giving  the  refinement  name, all
  1425. X          #line preprocessor directives are left out and  leading
  1426. X          tabs expand to 8 spaces.
  1427. X
  1428. X     crefine -cs-n0T8 last.cr
  1429. X          same as before.
  1430. X
  1431. XDIAGNOSTICS
  1432. X     The warnings and error messages  are  intended  to  be  self
  1433. X     explanatory.  If  you  do not understand one of them anyway:
  1434. X     chose a different language for the messages (see option -m),
  1435. X     get yourself a dictionary or interpreter and try again.
  1436. X
  1437. XSEE ALSO
  1438. X     cc(1), cpp(1), make(1)
  1439. X
  1440. XBUGS
  1441. X     Since preprocessor directives are not handled  by  C-Refine,
  1442. X     strange  things can happen if you use #ifdef or #if. This is
  1443. X     especially the case, if you  use  these  directives  to  put
  1444. X     large comments into your source files: if there are any com-
  1445. X     ments or string literals (double quotes)  or  char  literals
  1446. X     (single quotes) beginning in that area that are not properly
  1447. X     closed within it, C-Refine will run to nirvana searching for
  1448. X     their  end and give you lots of wrong error and warning mes-
  1449. X     sages.  Watch out for apostrophes (e.g.  in  "don't")  espe-
  1450. X     cially!
  1451. X
  1452. X     C-Refine should be able to act according to #line  commands,
  1453. X     so  that  the above problems could be avoided by running the
  1454. X     preprocessor first.
  1455. X
  1456. X     Those people, who use such stupid macros as
  1457. X        #define BEGIN {
  1458. X
  1459. X
  1460. X
  1461. XSun Release 4.1    Last change: 22 August 1991                  8
  1462. X
  1463. X
  1464. X
  1465. X
  1466. X
  1467. X
  1468. XCREFINE(1)               USER COMMANDS                 CREFINE(1)
  1469. X
  1470. X
  1471. X
  1472. X        #define END   }
  1473. X     or similar craizy stuff, will have to change their habits in
  1474. X     order to use C-Refine.
  1475. X
  1476. X     The output of C-Refine may be code that exceeds certain com-
  1477. X     piler  limits  of  your C or C++ compiler. Since the body of
  1478. X     every procedural refinement is enclosed in a block  and  the
  1479. X     body  of  every  value  returning  refinement is enclosed in
  1480. X     parentheses, the block nexting limits or expression complex-
  1481. X     ity  limits  of  your  compiler may be reached when you make
  1482. X     very heavy use of nested refinements.
  1483. X
  1484. X     Some compilers may handle the  #line  directive  improperly,
  1485. X     yielding wrongly tagged error messages.
  1486. X
  1487. X     Probably C-Refine will also work with Objective-C, but I  am
  1488. X     not absolutely sure about that.
  1489. X
  1490. X     There should be a mode to use C-Refine for Lisp also.
  1491. X
  1492. X     C-Refine reacts poor on some types of syntactic errors.
  1493. X
  1494. X     It should optionally be possible to let C-Refine run  the  C
  1495. X     preprocessor and react correctly to #line directives.
  1496. X
  1497. X     In C++, when a "leave" has to jump across  a  variable  ini-
  1498. X     tialization,  some Compilers will complain, that the goto is
  1499. X     illegal. This is not true, because the  goto  jumps  to  (or
  1500. X     even  beyond)  the very end of the block where that variable
  1501. X     is in [precisely: the jump is to an empty  statement,  which
  1502. X     is  the last statement in the block], but these compilers do
  1503. X     not recognize that fact.
  1504. X
  1505. XVERSION
  1506. X     This is for C-Refine Version 2.4
  1507. X
  1508. X     It is likely that the command syntax be changed in the  next
  1509. X     version  in  the  following  way:  multiple filenames can be
  1510. X     given, all of  which  must  end  with  an  'r'.  The  output
  1511. X     filename is constructed implicitly by removing that 'r' from
  1512. X     the inputfilename. So you better  do  not  use  output  file
  1513. X     names in your makefiles.
  1514. X
  1515. XAUTHOR
  1516. X     Lutz Prechelt, Institut fuer Programmstrukturen und Datenor-
  1517. X     ganisation,  Universitaet  Karlsruhe, D-7500 Karlsruhe, Ger-
  1518. X     many.  (prechelt@ira.uka.de)
  1519. X
  1520. X
  1521. X
  1522. X
  1523. X
  1524. X
  1525. X
  1526. X
  1527. XSun Release 4.1    Last change: 22 August 1991                  9
  1528. X
  1529. X
  1530. X
  1531. END_OF_FILE
  1532.   if test 22380 -ne `wc -c <'crefine.man'`; then
  1533.     echo shar: \"'crefine.man'\" unpacked with wrong size!
  1534.   fi
  1535.   # end of 'crefine.man'
  1536. fi
  1537. echo shar: End of archive 2 \(of 4\).
  1538. cp /dev/null ark2isdone
  1539. MISSING=""
  1540. for I in 1 2 3 4 ; do
  1541.     if test ! -f ark${I}isdone ; then
  1542.     MISSING="${MISSING} ${I}"
  1543.     fi
  1544. done
  1545. if test "${MISSING}" = "" ; then
  1546.     echo You have unpacked all 4 archives.
  1547.     rm -f ark[1-9]isdone
  1548. else
  1549.     echo You still must unpack the following archives:
  1550.     echo "        " ${MISSING}
  1551. fi
  1552. exit 0
  1553. exit 0 # Just in case...
  1554.