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

  1. Newsgroups: comp.sources.misc
  2. From: Lutz Prechelt <prechelt@i41s14.ira.uka.de>
  3. Subject:  v22i065:  crefine - C-Refine preprocessor, Part03/04
  4. Message-ID: <1991Aug26.032423.15215@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: f27aca5f22d709d7316a65fc7595cf99
  6. Date: Mon, 26 Aug 1991 03:24:23 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 65
  11. Archive-name: crefine/part03
  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:  cr_getln.c cr_talk.c crefine.1 getargs.c patchlevel.h
  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 3 (of 4)."'
  24. if test -f 'cr_getln.c' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'cr_getln.c'\"
  26. else
  27.   echo shar: Extracting \"'cr_getln.c'\" \(16193 characters\)
  28.   sed "s/^X//" >'cr_getln.c' <<'END_OF_FILE'
  29. X
  30. X/*************************************************************************
  31. XProject : C-Refine Precompiler
  32. XModule  : Line Scanner
  33. XAuthor  : Lutz Prechelt, Karlsruhe
  34. XDate    : 11.06.91  Version 16
  35. XCompiler: ANSI C
  36. X**************************************************************************/
  37. X/*
  38. X    Copyright (C) 1988,89,90,91 by Lutz Prechelt, Karlsruhe
  39. X
  40. X    This program is free software; you can redistribute it and/or modify
  41. X    it under the terms of the GNU General Public License as published by
  42. X    the Free Software Foundation; either version 1, or (at your option)
  43. X    any later version.
  44. X    This program is distributed in the hope that it will be useful,
  45. X    but WITHOUT ANY WARRANTY; without even the implied warranty of
  46. X    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  47. X    GNU General Public License for more details.
  48. X    You should have received a copy of the GNU General Public License
  49. X    along with this program; if not, write to the Free Software
  50. X    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  51. X*/
  52. X
  53. X/************************************************************************
  54. X*********************** C - R e f i n e *********************************
  55. X*************************************************************************/
  56. X
  57. X#include <stdio.h>
  58. X#include <string.h>
  59. X#include <ctype.h>
  60. X
  61. X#include "cr_decl.h"  /* globale Funktionen, Typen und Daten */
  62. X
  63. X/******************* lokale Funktionen ************************************/
  64. X
  65. Xstatic void  push_refinement_name A(());
  66. Xstatic int   normal_scanner A((LINE_INFO*));
  67. Xstatic int   comment_scanner A((LINE_INFO*));
  68. Xstatic int   text_scanner A((LINE_INFO*));
  69. Xstatic int   char_scanner A((LINE_INFO*));
  70. X
  71. X/*************************** defines ***************************************/
  72. X
  73. X#define push(ch) *(s++) = (char)ch
  74. X
  75. X#define leave_sequence    "leave"   /* e.g. "leave" (no leading blank!) */
  76. X#define leave_sequence_length  5
  77. X
  78. X#define normal_end_of_line       1   /* real end of line */
  79. X#define continueing_end_of_line  2   /* logical end of line */
  80. X#define refinementsymbol_found   3
  81. X#define leave_keyword_found      4
  82. X
  83. X/*********************** Lokale Daten ************************************/
  84. X
  85. X/***** one line buffer *****/
  86. Xstatic char *act;             /* current position in b */
  87. X
  88. X/***** Control *****/
  89. X#if ansi
  90. Xstatic int (*scanner) (LINE_INFO*) = normal_scanner;
  91. X#else
  92. Xstatic int (*scanner) ()           = normal_scanner;
  93. X#endif
  94. X/***** Status *****/
  95. Xstatic int  level = 0,                      /* brace-nesting */
  96. X            just_was = normal_end_of_line,  /* event memory */
  97. X            event = normal_end_of_line,
  98. X            semicolon_count,
  99. X            lines_in_denoter,
  100. X            old_indent;
  101. X
  102. X/*********************** get_line ****************************************/
  103. X
  104. Xextern void get_line (fp, l, semicolons)
  105. X  FILE       *fp;
  106. X  LINE_INFO  *l;
  107. X  int        *semicolons;  /* is increased only ! */
  108. X{
  109. X  /* Reads on line from file fp and sets up l accordingly.
  110. X     The preprocessed line is copied to *s and s is increased appropriately.
  111. X     (A null terminator is appended.)
  112. X     The line is a complete line only, if there is no refinement involved
  113. X     with that line:
  114. X     For refinement calls and refinement declaration headers a separate line
  115. X     is generated.
  116. X     At end of file stop_processing is set to true. Problems yield a
  117. X     message and let 'errors' or 'warnings' increase.
  118. X     This function uses the option indicator variables.
  119. X  */
  120. X  charp old_s = s;    /* store s to compute length later */
  121. X  bool stop = false;
  122. X  bool three_witches;
  123. X  semicolon_count = 0;
  124. X  {   /* init_l  (Level 1) */
  125. X#if debug
  126. X    printf ("get_line:");
  127. X#endif
  128. X    l->level   = level;   /* level is defined as level at start of line! */
  129. X    l->start   = s;
  130. X    l->indent  = 0;
  131. X    l->type    = normal;
  132. X  }
  133. X  if (just_was == normal_end_of_line) {
  134. X     {   /* read_line  (Level 1) */
  135. X     l->line_no = ++line_no;
  136. X     act = (char*)fgets (b, b_size, fp);  /* get next line*/
  137. X#if debug
  138. X     printf ("->%s<-", act == NULL ? "(NULL)" : (char*)act);
  139. X#endif
  140. X     if (act == NULL) {                /* check for EOF */
  141. X        stop_processing = true;
  142. X        l->type = empty;
  143. X        if (level > 0)
  144. X           error (Eeof_brace, NULL, line_no);
  145. X        if (scanner == comment_scanner)
  146. X           error (Eeof_comment, NULL, line_no);
  147. X        if (scanner == text_scanner)
  148. X           error (Eeof_string, NULL, line_no);
  149. X        if (scanner == char_scanner)
  150. X           error (Eeof_char, NULL, line_no);
  151. X        return;
  152. X     }
  153. X     }
  154. X     {   /* get_indent  (Level 1) */
  155. X     while (!stop)
  156. X        if (*act == ' ') {
  157. X           l->indent++;
  158. X           act++;
  159. X        }
  160. X        else if (*act == TAB) {    /* expand Tabs */
  161. X           l->indent = (l->indent/tabsize + 1) * tabsize;
  162. X           act++;
  163. X        }
  164. X        else
  165. X           stop = true;
  166. X     old_indent = l->indent;    /* store for next call */
  167. X     }
  168. X  }
  169. X  else {                       /* continued line */
  170. X     l->indent = old_indent;
  171. X     l->line_no = line_no;
  172. X  }
  173. X  {   /* handle_line  (Level 1) */
  174. X  three_witches = l->indent == 0 && level > 0 && scanner == normal_scanner;
  175. X  if (three_witches && (int)*act == refinementsymbol)
  176. X       {   /* handle_refinement_declaration  (Level 2) */
  177. X       act++;                     /* skip refinementsymbol */
  178. X       push_refinement_name ();
  179. X       if (*act != ':')
  180. X          error (Erefdecl_syntax, act, line_no);
  181. X       else
  182. X          act++;
  183. X       if (level > 1)
  184. X          error (Erefdecl_nested, NULL, line_no);
  185. X       l->type = refdecl;
  186. X       just_was = (*act == '\n' || *act == 0) ? normal_end_of_line :
  187. X                                                continueing_end_of_line;
  188. X       }
  189. X  else {
  190. X     {   /* check_column_0  (Level 2) */
  191. X     if (three_witches && !iscntrl (*act) &&
  192. X         just_was != continueing_end_of_line &&
  193. X         *act != '}' && *act != '#' && *act != '*' && *act != '/')
  194. X        warning (Wcol0, act, line_no, 1);
  195. X     }
  196. X     if (just_was != refinementsymbol_found &&
  197. X         just_was != leave_keyword_found)
  198. X        event = (*scanner) (l);
  199. X     {   /* handle_event  (Level 2) */
  200. X     if (event == refinementsymbol_found || event == leave_keyword_found)
  201. X        {   /* handle_refinementcall_or_leave  (Level 3) */
  202. X        if (s - old_s == 0) {        /* line empty */
  203. X           push_refinement_name ();
  204. X           l->type = event == leave_keyword_found ? leave : refcall;
  205. X           {   /* skip_semicolon_and_blanks  (Level 4) */
  206. X           if (*act == ';') {        /* skip semikolon if present */
  207. X              act++;
  208. X              semicolon_count++;
  209. X              if (l->type == refcall)
  210. X                 l->type = refcallr;   /* note the removed ";" */
  211. X           }
  212. X           while (*(act++) == ' ')   /* skip following blanks */
  213. X                   ;
  214. X           act--;                    /* recover char after last blank */
  215. X           }
  216. X           just_was = (*act == 0 || *act == '\n') ? normal_end_of_line :
  217. X                                                    continueing_end_of_line;
  218. X        }
  219. X        else
  220. X           just_was = event;
  221. X        }
  222. X     else
  223. X        just_was = normal_end_of_line;
  224. X     }
  225. X     if (option_small || event == normal_end_of_line)
  226. X       {   /* delete_trailing_blanks  (Level 2) */
  227. X       while (*(s-1) == ' ')      /* remove trailing blanks */
  228. X          s--;
  229. X       }
  230. X  }
  231. X  l->length = s - old_s;
  232. X  if (l->length == 0)
  233. X     l->type = empty;
  234. X  push (0);  /* String Terminator */
  235. X  {   /* perhaps_warn_for_level_changes  (Level 2) */
  236. X  int lev = level;
  237. X  if (lev < 0) {  /* Syntax error!  (or C-Refine does not work...) */
  238. X     if (option_anyway)
  239. X        error (Emany_braces, NULL, line_no);
  240. X     else
  241. X        fatal_error (Emany_braces, NULL, line_no);
  242. X  }
  243. X  else if (lev > 5 && level > l->level)
  244. X        warning (Wnesting, NULL, line_no, 3);
  245. X  else if (l->indent > 35 && (
  246. X  l->type == refcall || l->type == refcallr)
  247. X  && !option_small)
  248. X        warning (Wmuch_indent, NULL, line_no, 3);
  249. X  }
  250. X  assert (!(l->type == refdecl && semicolon_count != 0));
  251. X  *semicolons += semicolon_count;
  252. X  }
  253. X}
  254. X
  255. X/********************** push_refinement_name *******************************/
  256. X
  257. Xstatic void push_refinement_name ()
  258. X{
  259. X  /* reads input using 'act' and generates output using 's'.
  260. X     reads all following blanks, letters, digits and underscores (that is,
  261. X     stops on other characters) and generates from that a C identifier
  262. X     on the output by suppressing leading and trailing blanks.
  263. X     With option_ibmchars the Umlaute and Accentcharacters from the
  264. X     IBM International Charset are also allowed.
  265. X  */
  266. X#define is_legal(ch)  (isalnum(ch) || (ch) == ' ' || ch == '_' || \
  267. X                       (option_ibmchars && \
  268. X                           (((ch) >= 128 && (ch) <= 167)) || (ch) == 225))
  269. X  int ch;
  270. X  charp old_s = s, start = s;
  271. X  {   /* suppress_leading_blanks  (Level 1) */
  272. X  while (*act == ' ')               /* suppress leading blanks */
  273. X     act++;
  274. X  }
  275. X  {   /* copy_legal_chars  (Level 1) */
  276. X  do {                              /* copy legal chars */
  277. X    ch = *(act++);
  278. X    push (ch);
  279. X  }
  280. X  while (is_legal (ch));
  281. X  s--; act--;                       /* unpush illegal last char */
  282. X  }
  283. X  {   /* suppress_trailing_blanks  (Level 1) */
  284. X  while (*(s-1) == ' ' && s > old_s) /* suppress trailing blanks */
  285. X     s--;
  286. X  }
  287. X  assert (*(s-1) != ' ');
  288. X  assert (*old_s != ' ');
  289. X  assert (s - old_s >= 0);
  290. X  {   /* change_inner_blanks_to_underlines  (Level 1) */
  291. X  for (start++; start < s; start++) /* change inner blanks to underlines */
  292. X     if (*start == ' ')
  293. X        *start = '_';
  294. X#undef is_legal
  295. X  }
  296. X  if (s - old_s == 0)
  297. X     error (Erefname_missing, act, line_no);
  298. X}
  299. X
  300. X/***********************  S C A N N I N G  *********************************/
  301. X
  302. X#define q    39      /* Quote */
  303. X#define dq   34      /* Double-Quote */
  304. X
  305. X/*********************** normal_scanner ***********************************/
  306. X
  307. Xstatic int normal_scanner (l)
  308. X  LINE_INFO *l;
  309. X{
  310. X  /* Changes to reading comments, strings or quoted chars as necessary.
  311. X     Ends only at the end of a line.
  312. X     Tries to identify refinement calls and refinement declarations;
  313. X     in these cases the lines are reduced to only the refinement name.
  314. X  */
  315. X  register int ch;
  316. X  for (;;) {
  317. X    ch = *(act++);
  318. X    switch (ch) {
  319. X      case '\n':
  320. X      case 0   : return (normal_end_of_line);
  321. X      case '/' : if (*act == '*')              /* start of comment ? */
  322. X                    {   /* handle_normal_comment  (Level 1) */
  323. X                    if (!option_small) {
  324. X                       push (ch); push ('*');
  325. X                    }
  326. X                    act++;
  327. X                    scanner = comment_scanner;
  328. X                    return ((*scanner) (l));
  329. X                    }
  330. X                 else if (*act == '/' && option_cplusplus)
  331. X                    {   /* handle_doubleslash_style_comment  (Level 1) */
  332. X                    if (option_small)
  333. X                       return (normal_end_of_line);   /* just pgnore
  334. Xrest of line */
  335. X                    push (ch); push (ch);             /*  put  //   */
  336. X                    act++;
  337. X                    while (*act != '\n' && *act != 0)   /* put rest of line */
  338. X                       push (*(act++));
  339. X                    return (normal_end_of_line);
  340. X                    }
  341. X                 else                           /* No --> normal */
  342. X                    push (ch);
  343. X                 break;
  344. X      case dq  :
  345. X                 {   /* handle_text_denoter  (Level 1) */
  346. X                 push (ch);
  347. X                 scanner = text_scanner;
  348. X                 lines_in_denoter = 0;
  349. X                 return ((*scanner) (l));
  350. X                 }
  351. X      case q   :
  352. X                 {   /* handle_char_denoter  (Level 1) */
  353. X                 push (ch);
  354. X                 scanner = char_scanner;
  355. X                 lines_in_denoter = 0;
  356. X                 return ((*scanner) (l));
  357. X                 }
  358. X      case ';' : semicolon_count++;
  359. X                 push (';');
  360. X                 break;
  361. X      case '{' : level++;
  362. X                 push (ch);
  363. X                 break;
  364. X      case '}' : level--;
  365. X                 push (ch);
  366. X                 break;
  367. X      default  :
  368. X                 if (ch == refinementsymbol)
  369. X                   {   /* check_for_leave_or_refinement_call  (Level 1) */
  370. X                   /* Precondition: Refinement symbol found, 'act' is
  371. Xright behind it.
  372. X                      if a 'leave' surrounded by blanks is found in
  373. Xfront of the
  374. X                      refinement symbol, it and its blanks are stripped and
  375. X                      leave_keyword_found is returned.
  376. X                      Otherwise refinementsymbol_found gemeldet is returned
  377. X                   */
  378. X                   charp old_s = s--;
  379. X                   while (*s == ' ')
  380. X                      s--;
  381. X                   s++;
  382. X                   if (!memcmp (s - leave_sequence_length, leave_sequence,
  383. X                                leave_sequence_length)) {
  384. X                      s -= leave_sequence_length;     /* Remove
  385. Xleave_sequence from Output */
  386. X                      return (leave_keyword_found);
  387. X                   }
  388. X                   else {
  389. X                      s = old_s;
  390. X                      return (refinementsymbol_found);
  391. X                   }
  392. X                   }
  393. X                 else
  394. X                   push (ch);
  395. X    }
  396. X  }
  397. X}
  398. X
  399. X/********************* comment_scanner *************************************/
  400. X
  401. Xstatic int comment_scanner (l)
  402. X  LINE_INFO *l;
  403. X{
  404. X  /* Precondition: position is right behind a start of a comment
  405. X     (which is already copied if not option_small is true)
  406. X     Postcondition: position is right after a comment end.
  407. X  */
  408. X  register int ch;
  409. X  for (;;) {
  410. X    ch = *(act++);
  411. X    switch (ch) {
  412. X      case '\n':
  413. X      case 0   : return (normal_end_of_line);
  414. X      case '*' : if (*act == '/')       /* end of comment : */
  415. X                    {   /* handle_comment_end  (Level 1) */
  416. X                    if (!option_small) {
  417. X                       push (ch); push ('/');
  418. X                    }
  419. X                    act++;
  420. X                    scanner = normal_scanner;   /* change to normal scanner */
  421. X                    return ((*scanner) (l));    /* and continue scanning */
  422. X                    }
  423. X                 /* no break ! */
  424. X      default  : if (!option_small)
  425. X                    push (ch);
  426. X    }
  427. X  }
  428. X}
  429. X
  430. X/********************* text_scanner *************************************/
  431. X
  432. Xstatic int text_scanner (l)
  433. X  LINE_INFO *l;
  434. X{
  435. X  /* Precondition: position is right behind the (already copied)
  436. X                   double quote that starts a string denoter
  437. X                   (string literal)
  438. X     Postcondition:position is right behind the closing double
  439. X                   quote of a string denoter
  440. X  */
  441. X  register int ch;
  442. X  lines_in_denoter++;
  443. X  for (;;) {
  444. X    ch = *(act++);
  445. X    switch (ch) {
  446. X      case '\n':
  447. X      case 0   : return (normal_end_of_line);  /* allowed ??? */
  448. X      case dq  : 
  449. X      {   /* end_of_stringdenoter  (Level 1) */
  450. X      push (ch);
  451. X      if (lines_in_denoter > 1)
  452. X         warning (Wlong_string, act-1, line_no,
  453. X                  lines_in_denoter > 5 ? 1 : 2);
  454. X      scanner = normal_scanner;
  455. X      return ((*scanner) (l));
  456. X      }
  457. X      case '\\': push (ch);
  458. X                 if (*act == dq || *act == '\\') {
  459. X                    push (*act);
  460. X                    act++;
  461. X                 }
  462. X                 break;
  463. X      default  : push (ch);
  464. X    }
  465. X }
  466. X}
  467. X
  468. X/********************* char_scanner *************************************/
  469. X
  470. Xstatic int char_scanner (l)
  471. X  LINE_INFO *l;
  472. X{
  473. X  /* Is analogous to text scanner, but uses single quote instead of double
  474. X     quote.
  475. X  */
  476. X  int ch;
  477. X  lines_in_denoter++;
  478. X  for (;;) {
  479. X    ch = *(act++);
  480. X    switch (ch) {
  481. X      case '\n':
  482. X      case 0   : return (normal_end_of_line);  /* allowed ??? */
  483. X      case q   : 
  484. X      {   /* end_of_chardenoter  (Level 1) */
  485. X      push (ch);
  486. X      if (lines_in_denoter > 1)
  487. X         warning (Wlong_char, act-1, line_no,
  488. X                  lines_in_denoter > 5 ? 1 : 2);
  489. X      scanner = normal_scanner;
  490. X      return ((*scanner) (l));
  491. X      }
  492. X      case '\\': push (ch);
  493. X                 if (*act == q || *act == '\\') {
  494. X                    push (*act);
  495. X                    act++;
  496. X                 }
  497. X                 break;
  498. X      default  : push (ch);
  499. X    }
  500. X  }
  501. X}
  502. X
  503. END_OF_FILE
  504.   if test 16193 -ne `wc -c <'cr_getln.c'`; then
  505.     echo shar: \"'cr_getln.c'\" unpacked with wrong size!
  506.   fi
  507.   # end of 'cr_getln.c'
  508. fi
  509. if test -f 'cr_talk.c' -a "${1}" != "-c" ; then 
  510.   echo shar: Will not clobber existing file \"'cr_talk.c'\"
  511. else
  512.   echo shar: Extracting \"'cr_talk.c'\" \(3406 characters\)
  513.   sed "s/^X//" >'cr_talk.c' <<'END_OF_FILE'
  514. X
  515. X/*************************************************************************
  516. XProject : C-Refine Precompiler
  517. XModule  : Output functions for messages
  518. XAuthor  : Lutz Prechelt, Karlsruhe
  519. XDate    : 11.06.91  Version 16
  520. XCompiler: ANSI C, C-Refine
  521. X**************************************************************************/
  522. X/*
  523. X    Copyright (C) 1988,89,90,91 by Lutz Prechelt, Karlsruhe
  524. X
  525. X    This program is free software; you can redistribute it and/or modify
  526. X    it under the terms of the GNU General Public License as published by
  527. X    the Free Software Foundation; either version 1, or (at your option)
  528. X    any later version.
  529. X    This program is distributed in the hope that it will be useful,
  530. X    but WITHOUT ANY WARRANTY; without even the implied warranty of
  531. X    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  532. X    GNU General Public License for more details.
  533. X    You should have received a copy of the GNU General Public License
  534. X    along with this program; if not, write to the Free Software
  535. X    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  536. X*/
  537. X
  538. X/************************************************************************
  539. X*********************** C - R e f i n e *********************************
  540. X*************************************************************************/
  541. X
  542. X#include <stdio.h>
  543. X#include <string.h>
  544. X
  545. X#include "cr_decl.h"   /* global Functions, Types and Data */
  546. X#include "cr_texts.h"  /* message texts */
  547. X
  548. Xstatic void error_message A((charp[], charp[], charp, int));
  549. X
  550. X/************************* cout *******************************************/
  551. X
  552. Xextern void cout (i)
  553. X  int i;
  554. X{
  555. X  /* Writes number i on stderr (which is assumed to be a screen)
  556. X     with length five and positions the cursor back to the starting
  557. X     position with five backspaces.
  558. X     This is not very fast, but that doesn't matter.
  559. X  */
  560. X  fprintf (stderr, "%5d\b\b\b\b\b", i);
  561. X}
  562. X
  563. X/************************ error *******************************************/
  564. X
  565. Xstatic void error_message (type, message, object, line)
  566. X  charp type[], message[];
  567. X  charp object;
  568. X  int   line;
  569. X{
  570. X  fprintf (stdout, "\"%s\", line %d, %s: %s\n", name_in,
  571. X           line, type[msg_type], message[msg_type]);
  572. X  if (object != NULL) {
  573. X    char *nl = strchr (object, '\n');
  574. X    if (nl != NULL)     /* remove newline from object */
  575. X      *nl = 0;
  576. X   fprintf (stdout, "    %s \"%s\"\n", Tnear[msg_type], object);
  577. X   if (nl != NULL)
  578. X     *nl = '\n';
  579. X  }
  580. X}
  581. X
  582. X
  583. Xextern void error (message, object, line)
  584. X  charp message[];
  585. X  charp object;
  586. X  int   line;
  587. X{
  588. X  error_message (Terror, message, object, line);
  589. X  if (++errors > maxerrors)
  590. X     fatal_error (Emany_errors, "(-----ManteldesSchweigens-----)", line);
  591. X  error_in_this_function = true;
  592. X}
  593. X
  594. X/************************ fatal_error *************************************/
  595. X
  596. Xextern void fatal_error (message, object, line)
  597. X  charp message[];
  598. X  charp object;
  599. X  int   line;
  600. X{
  601. X  error_message (Tfatal_error, message, object, line);
  602. X  stop_processing = true;
  603. X  errors++;
  604. X}
  605. X
  606. X/************************ warning *****************************************/
  607. X
  608. Xextern void warning (message, object, line, level)
  609. X  charp message[];
  610. X  charp object;
  611. X  int   line, level;
  612. X{
  613. X  if (!error_in_this_function && level <= warning_level) {
  614. X     /* don't be too verbose */
  615. X     error_message (Twarning, message, object, line);
  616. X     if (++warnings > maxwarnings)
  617. X        fatal_error (Emany_warnings, NULL, line);
  618. X  }
  619. X}
  620. X
  621. END_OF_FILE
  622.   if test 3406 -ne `wc -c <'cr_talk.c'`; then
  623.     echo shar: \"'cr_talk.c'\" unpacked with wrong size!
  624.   fi
  625.   # end of 'cr_talk.c'
  626. fi
  627. if test -f 'crefine.1' -a "${1}" != "-c" ; then 
  628.   echo shar: Will not clobber existing file \"'crefine.1'\"
  629. else
  630.   echo shar: Extracting \"'crefine.1'\" \(17842 characters\)
  631.   sed "s/^X//" >'crefine.1' <<'END_OF_FILE'
  632. X.TH CREFINE 1 "22 August 1991"
  633. X.SH NAME
  634. Xcrefine \- refinement preprocessor for C and C++
  635. X.SH SYNOPSIS
  636. X.B crefine
  637. X[
  638. X.B options
  639. X]
  640. X.I inputfile
  641. X[
  642. X.I outputfile
  643. X]
  644. X.SH DESCRIPTION
  645. X.B crefine (C-Refine)
  646. X(spoken like 'see refine') is a preprocessor that adds a new language
  647. Xconstruct to C and C++: the 
  648. X.I refinement.
  649. Xcrefine massages a source code file to produce plain C output from
  650. XC input with refinements or plain C++ from C++ with refinements.
  651. XThe syntax of refinements is described in the USAGE section.
  652. XOnly a single source file may be processed with one call; the name of the
  653. Xoutput file, if not given, is derived from the name of the input file
  654. Xby removing its last 
  655. Xcharacter, if that is an 
  656. X.B r
  657. X(which is the filename convention for C\-Refine).
  658. XIf the last character of
  659. Xthe input filename is not an 
  660. X.B r
  661. X, the output filename is derived from it
  662. Xby appending
  663. X.B RRR
  664. Xinstead.
  665. XInput and output is always to and from named
  666. Xfiles. Error messages go to the standard output. The startup message,
  667. Xif not suppressed, goes to standard error.
  668. X
  669. XC\-Refine does not act in any way upon the directives for the
  670. XC preprocessor. This especially means that include files have to be 
  671. Xprocessed separately. Usually, this will not be necessary, since they do
  672. Xnot typically contain anything that C\-Refine should work on.
  673. XA second consequence is, that it is possible for C\-Refine to give error
  674. Xmessages on correct programs, because it does not see the effects of 
  675. Xrunning the preprocessor. In these cases you either have to change your 
  676. Xsource code or run the C preprocessor before C\-Refine.
  677. X.SH OPTIONS
  678. X.TP
  679. X.B \-a
  680. Xanyway. Normally, if any error was detected by C\-Refine, the output file 
  681. Xwill automatically be deleted. This option says not to do so.
  682. X.TP
  683. X.B \-c
  684. Xcomment refinement names in the output. Any inserted 
  685. Xrefiement body in the output is titled by a comment giving the refinement
  686. Xname and the refinement nesting level.
  687. X.TP
  688. X.B \-f
  689. Xfeedback that you work. For the homo ludens in the programmer or people
  690. Xwith incredibly overloaded machines. Shows running line numbers on standard
  691. Xerror.
  692. X.TP
  693. X.B \-i
  694. Xindent the 
  695. X.I #line
  696. Xdirectives in the resulting output to the appropriate
  697. Xindentation level as indicated by the nesting of refinements. Not an 
  698. Xespecially important option, but since this is a true UNIX program, it is
  699. Xpresent anyway.
  700. X.TP
  701. X.B \-l
  702. Xlist all refinement names.
  703. XThe names of all processed refinements are listed
  704. Xto the standard output along with their line numbers. 
  705. XI do not know exactly what this option may be good
  706. Xfor, but I believe someday somebody will need it.
  707. X.TP
  708. X.B \-m<ch>
  709. Xmessage language. Originally, C\-Refine was written by a typical german
  710. Xprogrammer in the typical german programmer schizophrenia situation: 
  711. Xas a german the native tongue is german,
  712. Xas a programmer the native tongue is
  713. Xenglish. So both languages were supported for the error messages.
  714. XEven worse, since I believe the whole data processing world is much too
  715. Xserious, I liked to have a humourous version either. So now any of the 
  716. Xcharacters 
  717. X.B d,D,g,G
  718. Ximmediately after the option character m gives you
  719. Xgerman error and warning messages, 
  720. X.B e
  721. Xor
  722. X.B E
  723. Xgives english ones (which, 
  724. Xfor sake of internationality, is the default) and every other letter lets
  725. Xyou stick to (german) humor.
  726. X.TP
  727. X.B \-n<num>
  728. Xnumbering with
  729. X.I #line
  730. Xcommands. By default, every insertion of a
  731. Xrefinement body is accompanied by a #line preprocessor directive in the 
  732. Xoutput. This is the default numbering level 3.
  733. XBy giving a smaller number just after the option character
  734. X.B n
  735. X, the amount of
  736. X.I #line
  737. Xdirectives used can be 
  738. Xreduced (level 2 or 1) or set to zero (level 0). What is best depends on 
  739. Xthe behavior of your local C or C++ compiler.
  740. XJust try it out, beginning with the default level 3.
  741. X.TP
  742. X.B \-p
  743. Xplus. The C++ mode. The only difference between C mode and C++ mode for
  744. XC\-Refine is, that in C++ mode the C++ doubleslash comment convention is
  745. Xobeyed, while in C mode it is not. This is possible because C\-Refine knows
  746. Xvery little about the actual syntax of these two languages.
  747. XSo in most cases, this difference makes no difference at all.
  748. X.TP
  749. X.B \-q
  750. Xquiet mode. Suppresses the startup message of C\-Refine.
  751. X.TP
  752. X.B \-r<ch>
  753. Xrefinement symbol. Select what character shall be recognized as the 
  754. Xrefinement symbol in the input file. The character to chose must be given
  755. Xon the command line immediately after the option character
  756. X.B r.
  757. XThis is the
  758. Xbackquote (ASCII code 95) by default. Since there are only two printable
  759. XASCII characters that are unused in the syntax of C (the backquote, 
  760. Xcode 96, and the dollar or currency sign, code 36) there is very little 
  761. Xchoice on a machine with 7 bit character set. This choice is further 
  762. Xrestricted because on some systems (such as VMS) the dollar sign is
  763. Xacutally being allowed and used for identifiers.
  764. XSome more possiblilities arise when having an 8 bit character set, such
  765. Xas the IBM international character set (proposed symbol there is the
  766. Xlittle double right angle bracket, code 175, which really looks nice),
  767. Xbut take into account that any change in refinement symbol is bad
  768. Xfor the portability of your source files.
  769. X.TP
  770. X.B \-R<num>
  771. Xrefinement symbol. Same as before, but the new symbol is given by its
  772. Xcharacter code instead of by itself.
  773. X.TP
  774. X.B \-s
  775. Xstrip. Produces smaller output by stripping of all indentation, whether
  776. Xpresent in the input or generated by C\-Refine, and all comments.
  777. XThis is on by default. To switch it off, use the syntax 
  778. X.B \-s\-
  779. X.TP
  780. X.B \-w<num>
  781. Xwarning level. C\-Refine is able to give various warnings about your
  782. Xsource code. These can be suppressed in three stages. The default warning
  783. Xlevel is 3 (all warnings). You can chose any level from 0 (no warnings)
  784. Xto 3 by giving the appropriate number right after the option character
  785. X.B w
  786. Xon the command line.
  787. X.TP
  788. X.B \-B<num>
  789. Xbuffer. Select the size of the source code buffer
  790. Xin which C\-Refine holds the
  791. Xcode for a function while processing it. The default is 150000 bytes.
  792. X.TP
  793. X.B \-E<num>
  794. Xerrors. Select the maximum number of errors that may occur in the input
  795. Xbefore C\-Refine stops processing prematurely. The default is 20.
  796. X.TP
  797. X.B \-L<num>
  798. Xlines. Select the maximum number of source code lines per single function
  799. Xthat C\-Refine is able to hold. The default is 2500. 
  800. X.TP
  801. X.B \-N<num>
  802. Xnumber of refinements per function.
  803. XSelects the maximum number of refinement
  804. Xdeclarations that may be present within any single function. 
  805. XThe default is 200.
  806. X.TP
  807. X.B \-T<num>
  808. Xtab size. Select the number of spaces to which a TAB character expands.
  809. XC\-Refine expands all TAB characters at the beginning of a line, i.e. those
  810. Xthat act as indentation. Other TABs are left untouched. The default is 1.
  811. X.TP
  812. X.B \-W<num>
  813. Xwarnings. Select the maximum number of warnings that may occur
  814. Xbefore C\-Refine stops processing prematurely. The default is 30.
  815. X.SH USAGE
  816. XThere are three new syntactic elements with C\-Refine:
  817. Xthe refinement definition, the refinement call and the leave construct.
  818. XThe purpose of refinements is to support
  819. Xthe Top\-Down style of programming
  820. X(a) within a function and (b) in both, thinking and writing.
  821. XEssentially, refinements are just parameterless macros with
  822. Xlong descriptive names.
  823. XRefinements are in any case local to a function. They may be called 
  824. Xbefore they are declared; declaration and definition of a 
  825. Xrefinement are one.
  826. XThe syntax of refinements as defined by C\-Refine is
  827. X.I not
  828. Xformat free, but lays significance upon whether a special symbol (the
  829. Xrefinement symbol) is occuring in column 0 or somewhere else.
  830. X
  831. XAlong with the new language constructs are some layout restrictions
  832. Xfor the program text being defined. This is necessary, because (a) the
  833. Xsyntax of the refinement constructs breaks basic syntactic rules of C and
  834. X(b) the C\-Refine preprocessor relies on some simple formatting rules, so
  835. Xits algorithms can be kept simple and the whole thing small, portable,
  836. Xrobust, reliable and fast.
  837. X
  838. XHere are the (very informal) descriptions of the syntax and semantics of
  839. Xthe language elements introduced by C\-Refine:
  840. X.TP
  841. Xrefinement names
  842. XA 
  843. X.I refinement name
  844. Xis just a normal C identifier, with one important addition:
  845. Xblanks are allowed within (!)
  846. Xit (i.e. anywhere after the first nonblank character
  847. Xof the name and before the last nonblank one); they are equivalent to
  848. Xunderscores. The end of a refinement name is always detected by the
  849. Xappearence of a special symbol, typically a semicolon, a colon or an
  850. Xoperator.
  851. XA refinement name must, however, be on a single line.
  852. X.TP
  853. X.B refinement calls
  854. XA
  855. X.I refinement call
  856. Xconsists of the refinement symbol, immediately followed
  857. Xby a refinement name. The refinement symbol must not be in colums 0 of the
  858. Xsource line. Refinement calls are principally allowed anywhere within 
  859. Xa function. The called refinement must be defined in that function, although
  860. Xthe definition may (and usually will) appear later than the call.
  861. XThe semantics of a refinement call is as follows:
  862. XA 
  863. X.I procedural refinement
  864. X(i.e. one that contains at least one semicolon in
  865. Xits body) is inserted instead of its call, surrounded by a pair of curly 
  866. Xbraces. This insertion is recursively applied to nested refinements.
  867. XA 
  868. X.I valued refinement
  869. X(i.e. one that contains just an expression and no 
  870. Xsemicolon in its body) is inserted instead of its call, surrounded by 
  871. Xa pair of parentheses.
  872. XThis insertion is recursively applied to nested valued refinements.
  873. XSo procedural refinements can be called anywhere where a block statement is
  874. Xlegal. Valued refinements can be called anywhere where a parenthesed 
  875. Xexpression is legal.
  876. XAn illegal form of refinement call will be detected by C\-Refine.
  877. X.TP
  878. X.B refinement definitions
  879. Xa refinement definition consists of the refinement symbol, immediately 
  880. Xfollowed by a refinement name, followed by a colon. 
  881. XThe refinement symbol must be in column 0 of the
  882. Xsource line. Refinement definitions are allowed only on block nesting
  883. Xlevel 1, i.e. in the outermost block of a function.
  884. XThe body of a refinement is examined to decide what type of
  885. Xrefinement it is:
  886. XAll refinements that contain one or more semicolons in their body,
  887. Xthat are not part of a comment, character denoter or string denoter, 
  888. Xare called
  889. X.I procedural refinements,
  890. Xsince they contain statements.
  891. XAll other refinements are called
  892. X.I valued refinements,
  893. Xsince they only contain an expression and thus return a value.
  894. XIllegal syntax of a refinement declaration and the declaration of 
  895. Xrefinements that are never used will be detected by C\-Refine.
  896. X.TP
  897. X.B leave
  898. XThe 
  899. X.I leave construct
  900. Xmay be used from within any procedural refinement at any place where a 
  901. Xstatement is legal. It consists of the keyword
  902. X.B leave
  903. Xfollowed by the refinement symbol, followed by a refinement name
  904. X.I ref.
  905. XThe semantics of this construct is, that a 
  906. X.I goto
  907. Xstatement is inserted instead of the leave construct, that jumps to
  908. Xa point right after the last statement of the refinement 
  909. X.I ref.
  910. XFor this to be legal
  911. X.I ref
  912. Xmust be present in the current static nesting of refinement calls.
  913. XThis means that not only the current refinement can be left with 
  914. X.I leave,
  915. Xbut any number of refinements that are statically nested at that point
  916. Xof your code. Illegal use of the leave construct is detected by C\-Refine.
  917. X
  918. XAs by now, I assume, almost any understanding that may initially have been
  919. Xthere, will probably have vanished. I will try to get it back to you by 
  920. Xmeans of the following example. This is a (very simple\-minded) version
  921. Xof the Sieve of Eratosthenes. It should not be thought that I believe the
  922. Xrefinement technique to be especially well suited to this problem, but this
  923. Xwas the smallest 'real' problem I could think of to demonstrate at least
  924. Xmost of what the possibilities of C\-Refine are. So here it is:
  925. X
  926. X.nf
  927. X#define MAX        10000
  928. X#define PRIME      0
  929. X#define NON_PRIME  1
  930. X
  931. Xstatic int sieve[MAX+1];
  932. X
  933. Xint main ()
  934. X{
  935. X  `initialize;
  936. X  `do sieve;
  937. X  `make output;
  938. X  return (0);
  939. X  
  940. X`initialize:
  941. X  int current;
  942. X  for (current = 2; current <= MAX; current++)
  943. X    sieve[current] = PRIME;
  944. X    
  945. X`do sieve:
  946. X  int current_prime = 1;
  947. X  for (;;) {
  948. X    `find next bigger prime;  /* perhaps STOP here */
  949. X    `delete all multiples of current_prime;
  950. X  }
  951. X
  952. X`find next bigger prime:
  953. X  int current_candidate = current_prime + 1;
  954. X  while (sieve[current_candidate] == NON_PRIME)
  955. X    if (current_candidate == MAX)
  956. X      leave `do sieve;    /* leave two refinements at once */
  957. X    else
  958. X      current_candidate++;
  959. X  /* now current_candidate is a prime (or we leave `sieve) */
  960. X  current_prime = current_candidate;
  961. X  
  962. X`delete all multiples of current_prime:
  963. X  int current = `first multiple of current_prime;
  964. X  while (current <= MAX) {
  965. X    sieve[current] = NON_PRIME;
  966. X    current += current_prime;
  967. X  }
  968. X  
  969. X`first multiple of current_prime:
  970. X  2 * current_prime
  971. X
  972. X`make output:
  973. X  int current;  /* different from 'current' above */
  974. X  printf ("The primes between 2 and %d are\n", MAX);
  975. X  for (current = 2; current <= MAX; current++)
  976. X    if (`current is prime)
  977. X      printf ("%5d ", current);
  978. X
  979. X`current is prime:
  980. X  sieve[current] == PRIME
  981. X
  982. X} /* end of main() */
  983. X
  984. X/***** End of example *****/
  985. X.fi
  986. XTo make the self documentation aspect of C\-Refine more clear, look at
  987. Xthe following example: A function that tests, whether its parameters
  988. Xform a pythagorean triple:
  989. X.nf
  990. Xbool pythagorean (double x, double y, double z)
  991. X{
  992. X  return (`all legs positive && `one is hypotenuse)
  993. X  
  994. X`all legs positive:
  995. X   x > 0  &&  y > 0  &&  z > 0
  996. X
  997. X`one is hypotenuse:
  998. X  `x is hypotenuse || `y is hypotenuse || `z is hypotenuse
  999. X  
  1000. X`x is hypotenuse:
  1001. X  x*x == y*y + z*z 
  1002. X
  1003. X`y is hypotenuse:
  1004. X  y*y == x*x + z*z
  1005. X
  1006. X`z is hypotenuse:
  1007. X  z*z == x*x + y*y
  1008. X  
  1009. X}
  1010. X.fi
  1011. XThis is good style: you write down just what you want to express and
  1012. Xwith an optimizing compiler such code will also be perfectly efficient.
  1013. XTry to imagine what this would have looked like, if it had all been 
  1014. Xin a single parenthesesed expression.
  1015. X.SH FILES
  1016. X.PD 0
  1017. X.TP 18
  1018. Xbin/crefine
  1019. Xthe executable program
  1020. X.TP
  1021. Xfilename.cr
  1022. XC\-with\-refinements input file.
  1023. X.TP
  1024. Xfilename.c
  1025. XC output file.
  1026. X.TP
  1027. Xfilename.ccr
  1028. XC++\-with\-refinements input file.
  1029. X.TP
  1030. Xfilename.cc
  1031. XC++ output file.
  1032. X.TP
  1033. XotherfileRRR
  1034. Xoutput file from input file
  1035. X.I otherfile
  1036. X.PD
  1037. X.SH EXAMPLES
  1038. X.TP
  1039. Xcrefine firsttest.cr
  1040. Xprocess the input file firsttest.cr producing the output file firsttest.c
  1041. X.TP
  1042. Xcrefine -p+ -q+ -w2 next.ccr outfile
  1043. Xprocess the C++ inputfile next.ccr producing the output file outfile.
  1044. XThe startup message is suppressed, C++ mode is selected and the 
  1045. Xwarning level is reduced to 2.
  1046. X.TP
  1047. Xcrefine -pqw2 next.ccr outfile
  1048. Xsame as before.
  1049. X.TP
  1050. Xcrefine -p+a-l-qw2 next.ccr outfile
  1051. Xsame as before.
  1052. X.TP
  1053. Xcrefine -c -s- -n0 -T8 last.cr
  1054. Xprocess the inputfile last.cr in order to get a readable C source.
  1055. XComments and indentation are not stripped, inserted refinement bodies 
  1056. Xare tagged by an additional comment giving the refinement name,
  1057. Xall 
  1058. X.I #line
  1059. Xpreprocessor directives are left out and leading tabs expand
  1060. Xto 8 spaces.
  1061. X.TP
  1062. Xcrefine -cs-n0T8 last.cr
  1063. Xsame as before.
  1064. X.SH DIAGNOSTICS
  1065. XThe warnings and error messages are intended to be self explanatory. If you
  1066. Xdo not understand one of them anyway: chose a different language for
  1067. Xthe messages (see option \-m), get yourself a dictionary or interpreter and
  1068. Xtry again.
  1069. X.SH SEE ALSO
  1070. Xcc(1), cpp(1), make(1)
  1071. X.SH BUGS
  1072. XSince preprocessor directives are not handled by C\-Refine, strange things 
  1073. Xcan happen if you use #ifdef or #if. This is especially the case, if you
  1074. Xuse these directives to put large comments into your source files: if there
  1075. Xare any comments or string literals (double quotes) or char 
  1076. Xliterals (single quotes) beginning in that area that are not properly 
  1077. Xclosed within it, C\-Refine will run to nirvana searching for their end and 
  1078. Xgive you lots of wrong error and warning messages.
  1079. XWatch out for apostrophes (e.g. in "don't") especially!
  1080. X.LP
  1081. XC\-Refine should be able to act according to #line commands, so that 
  1082. Xthe above problems could be avoided by running the preprocessor first.
  1083. X.LP
  1084. XThose people, who use such stupid macros as
  1085. X.nf
  1086. X   #define BEGIN {
  1087. X   #define END   }
  1088. X.fi
  1089. Xor similar craizy stuff, will have to change their habits in order
  1090. Xto use C\-Refine.
  1091. X.LP
  1092. XThe output of C\-Refine may be code that exceeds certain compiler limits of
  1093. Xyour C or C++ compiler. Since the body of every procedural refinement is
  1094. Xenclosed in a block and the body of every value returning refinement is
  1095. Xenclosed in parentheses, the block nexting limits or expression complexity 
  1096. Xlimits of your compiler may be reached when you make very heavy use of
  1097. Xnested refinements.
  1098. X.LP
  1099. XSome compilers may handle the #line directive improperly, yielding wrongly
  1100. Xtagged error messages.
  1101. X.LP
  1102. XProbably C\-Refine will also work with Objective\-C,
  1103. Xbut I am not absolutely sure about that.
  1104. X.LP
  1105. XThere should be a mode to use C\-Refine for Lisp also.
  1106. X.LP
  1107. XC\-Refine reacts poor on some types of syntactic errors.
  1108. X.LP
  1109. XIt should optionally be possible to let C\-Refine run the 
  1110. XC preprocessor and react correctly to 
  1111. X.I #line
  1112. Xdirectives.
  1113. X.LP
  1114. XIn C++, when a "leave" has to jump across a variable initialization, some 
  1115. XCompilers will complain, that the goto is illegal. This is not true, 
  1116. Xbecause the goto jumps to (or even beyond) the very end of the block 
  1117. Xwhere that variable is in
  1118. X[precisely: the jump is to an empty statement, which is the last statement
  1119. Xin the block], but these compilers do not recognize that fact.
  1120. X.SH VERSION
  1121. XThis is for C\-Refine Version 2.4
  1122. X.LP
  1123. XIt is likely that the command syntax be changed in the next version in the
  1124. Xfollowing way: multiple filenames can be given, all of which 
  1125. X.I must
  1126. Xend with an 'r'. The output filename is constructed implicitly by 
  1127. Xremoving that 'r' from the inputfilename. So you better do not use output
  1128. Xfile names in your makefiles.
  1129. X.SH AUTHOR
  1130. XLutz Prechelt, 
  1131. XInstitut fuer Programmstrukturen und Datenorganisation,
  1132. XUniversitaet Karlsruhe,
  1133. XD-7500 Karlsruhe,
  1134. XGermany.
  1135. X(prechelt@ira.uka.de)
  1136. END_OF_FILE
  1137.   if test 17842 -ne `wc -c <'crefine.1'`; then
  1138.     echo shar: \"'crefine.1'\" unpacked with wrong size!
  1139.   fi
  1140.   # end of 'crefine.1'
  1141. fi
  1142. if test -f 'getargs.c' -a "${1}" != "-c" ; then 
  1143.   echo shar: Will not clobber existing file \"'getargs.c'\"
  1144. else
  1145.   echo shar: Extracting \"'getargs.c'\" \(12454 characters\)
  1146.   sed "s/^X//" >'getargs.c' <<'END_OF_FILE'
  1147. X/*************************************************************************
  1148. XModule  : getargs -- command line option processor
  1149. XAuthor  : Lutz Prechelt, Karlsruhe
  1150. XDate    : 11.06.91  Version 2
  1151. XCompiler: should be portable
  1152. X          tried: MS-DOS 3.2, Microsoft C 5.0 (ANSI-C)
  1153. X          SUN-OS 4.03, 4.1 (K&R C); GNU gcc 1.39
  1154. X**************************************************************************/
  1155. X/*
  1156. X    Copyright (C) 1988,91 by Lutz Prechelt, Karlsruhe
  1157. X
  1158. X    This program is free software; you can redistribute it and/or modify
  1159. X    it under the terms of the GNU General Public License as published by
  1160. X    the Free Software Foundation; either version 1, or (at your option)
  1161. X    any later version.
  1162. X    This program is distributed in the hope that it will be useful,
  1163. X    but WITHOUT ANY WARRANTY; without even the implied warranty of
  1164. X    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1165. X    GNU General Public License for more details.
  1166. X    You should have received a copy of the GNU General Public License
  1167. X    along with this program; if not, write to the Free Software
  1168. X    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1169. X*/
  1170. X
  1171. X
  1172. X/************************************************************************
  1173. X*********************** g e t a r g s ***********************************
  1174. X*************************************************************************/
  1175. X#if 0
  1176. X
  1177. XVarianten:
  1178. X#define deutsch 1   waehlt deutsche Meldungen statt englische
  1179. X#define ansi    1   waehlt Funktionsdefinitionen mit Parameterliste
  1180. X                    statt ohne
  1181. X#define ms_dos  1   erlaubt "/" als Optionszeichen zusaetzlich zu "-"
  1182. X
  1183. XDies ist ein Utility zum bequemeren Auswerten von Optionen auf der
  1184. XKommandozeile (d.h. mit argc, argv).
  1185. X
  1186. XEs wird dazu vom Benutzer eine Tabelle ("argtab") aufgestellt, in der zu
  1187. Xjeder Option der Optionsbuchstabe, ein Argumententyp 
  1188. X(BOOL, CHAR, INT, STRING) und eine Variable angegeben werden,
  1189. Xin der das Resultat abgelegt werden soll.
  1190. XFerner kann man hier noch einen Kommentarstring zu jeder Option angeben.
  1191. X
  1192. XDie Funktion getargs (&argc, argv, argtab, argtabsize) bearbeitet nun den
  1193. Xargv Vektor derart, dass alle Optionen, die in argtab angegeben sind, gemaess
  1194. Xihrem Eintrag behandelt werden und aus argv entfernt (dazu wird argc und argv
  1195. Xmodifiziert, jedoch nur Pointer veraendert, keine argv-Eintraege selbst)
  1196. XEs duerfen beim Aufruf die Optionen beliebig mit den uebrigen Parametern
  1197. Xvermischt und mehrere Optionen hinter einem Optionssymbol angegeben
  1198. Xwerden.
  1199. X
  1200. XEs werden unbekannte Optionen festgestellt und angemeckert (nach stderr)
  1201. XAls Resultat wird die Anzahl angemeckerter Optionen geliefert.
  1202. X
  1203. XDie Funktion print_usage (program_name, usage_text, argtab, argtabsize)
  1204. Xgibt unter Benutzung der Kommentarstrings aus argtab eine Kurzbeschreibung zum
  1205. Xkorrekten Aufruf aller Optionen und des Gesamtprogramms nach stderr aus.
  1206. X
  1207. XBeispiel:
  1208. X  #include <getargs.h>
  1209. X  int a = 1, b = 'B', c;
  1210. X  char *d = "";
  1211. X  ARG argtab[] = { {'a', BOOLEAN,  &a,       "use alternate mode" },
  1212. X                   {'b', CHARACTER,&b,       "Character for boldface" },
  1213. X                   {'c', INTEGER,  &c,       "count of pages to print" },
  1214. X                   {'d', STRING  , (int*)&d, "File description" } };
  1215. X  void main (int argc, char **argv) {
  1216. X     if (getargs (&argc, argv, argtab, ARGTABSIZE (argtab)))
  1217. X        print_usage (argv[0], "[options] filetoprint [options]", argtab,
  1218. X                     ARGTABSIZE (argtab));
  1219. X  }
  1220. X
  1221. XEnthalte argtab also die Liste der Optionen fuer das Programm "fileprt", das
  1222. X(wie in print_usage angegeben) noch einen Dateinamen als weiteren Parameter
  1223. Xverlangt.
  1224. X
  1225. XDann waeren korrekte Aufrufe etwa:
  1226. X
  1227. Xfileprt -a file
  1228. Xfileprt -a+ file -bB
  1229. Xfileprt -c14 file -dMyFile
  1230. Xfileprt file -abBc14
  1231. X
  1232. XVerkehrt waere dagegen zum Beispiel:
  1233. X
  1234. Xfileprt -dMy File file       weil <File> ein eigenes Argument ist
  1235. Xfileprt -p file              weil es die Option p nicht gibt
  1236. Xfileprt -bx28 file           weil CHAR immer nur ein Zeichen umfasst
  1237. X
  1238. XDieser letzte Aufruf haette im Beispiel ungefaehr folgenden Output nach
  1239. Xstderr zur Folge:
  1240. X
  1241. XUnbekannte Option : -bx28
  1242. Xusage: C:\MYDIR\FILEPRT.EXE [options] filetoprint [options]
  1243. XErlaubte Optionen sind:
  1244. X-a<+/-> use alternate mode                       (Wert: TRUE)
  1245. X-b<ch>  Character for boldface                   (Wert: B)
  1246. X-c<num> count of pages to print                  (Wert: 0)
  1247. X-d<str> File description                         (Wert: "")
  1248. X
  1249. XDer genaue Grund fuer die Fehlermeldung ist, dass der Interpreter der Option
  1250. Xb den Wert x zuweist und dann nach der (nicht auffindbaren) Option 2 sucht !
  1251. X
  1252. XDie "Wert"-Angaben beim print_usage entstehen aus den Vorbelegungen der
  1253. XVariablen a, b, c, d;
  1254. X
  1255. X#endif
  1256. X
  1257. X/**************************************************************************/
  1258. X
  1259. X#include "std.h"
  1260. X#include <stdio.h>
  1261. X#include <ctype.h>
  1262. X#include "getargs.h"
  1263. X
  1264. X#if deutsch
  1265. X#define ERRMSG         "Unbekannte Option"
  1266. X#define USAGE          "Aufruf"
  1267. X#define VALID_OPT_ARE  "Erlaubte Optionen sind"
  1268. X#else
  1269. X#define ERRMSG         "unknown option"
  1270. X#define USAGE          "usage"
  1271. X#define VALID_OPT_ARE  "valid options are"
  1272. X#endif
  1273. X
  1274. X#if ms_dos
  1275. X#define is_option(a) (a == '-' || a == '/')   /* MS-DOS option marker */
  1276. X#else
  1277. X#define is_option(a) (a == '-')   /* option marker for Unix etc. */
  1278. X#endif
  1279. X
  1280. Xstatic int  set_argument A((ARG* entry, char **optiontext));
  1281. Xstatic ARG* find_argument A((int optionname, ARG *argtab, int argtablength));
  1282. Xstatic int  stoi A((char ** linep));
  1283. X
  1284. X/*---------------------------------------------------------
  1285. X *    getargs
  1286. X *---------------------------------------------------------*/
  1287. X
  1288. Xextern int getargs (argc, argv, tabp, tabsize)
  1289. X  int  *argc;    /* changed */
  1290. X  char **argv;   /* changed */
  1291. X  ARG  *tabp;
  1292. X  int  tabsize;
  1293. X{
  1294. X  /* Hauptroutine. Wertet alle Argumente in argv bis argc aus:
  1295. X     Es duerfen Optionen (erkannt am ersten Zeichen gemaess Makro is_option)
  1296. X     und andere Argumente beliebig gemischt auftreten.
  1297. X     Optionen werden in tabp gesucht und durch Linksschieben der restlichen
  1298. X     Argumente aus argv entfernt.
  1299. X     Sie werden gemaess ihrem tabp-Eintrag behandelt:
  1300. X     Bei Nichtvorhandensein oder unerlaubten Werten wird gemeckert,
  1301. X     andernfalls die betreffende Variable mit dem Wert der Option bestueckt.
  1302. X     Nur Nicht-Optionen bleiben in argv enthalten, ihre Anzahl wird in argc
  1303. X     vermerkt.
  1304. X     Das Resultat ist die Anzahl angemeckerter Optionen.
  1305. X  */
  1306. X  int    nargc;   /* remaining argc after removing options */
  1307. X  char **nargv, *p;
  1308. X  int    errors = 0, error;
  1309. X  ARG   *argp;
  1310. X  for (nargv = ++argv, nargc = 1 /* keep name */; --(*argc) > 0; argv++) {
  1311. X    if (!is_option (**argv)) {
  1312. X       *nargv++ = *argv;        /* No Option -> keep it */
  1313. X       nargc++;
  1314. X    }
  1315. X    else {
  1316. X       p = (*argv) + 1;         /* Option -> handle it */
  1317. X       while (*p) {
  1318. X          error = 0;
  1319. X          /* One Optionsign can have multiple Options following */
  1320. X          if (argp = find_argument ((int)*p, tabp, tabsize)) /* if exists */
  1321. X             error = !set_argument (argp, &p);          /* then read it */
  1322. X          if (!argp || error) {   /* if not exists or invalid value */
  1323. X             fprintf (stderr, "%s : %s\n", ERRMSG, *argv);   /* then #$% */
  1324. X             errors++;
  1325. X             break;
  1326. X          }
  1327. X       }
  1328. X    }
  1329. X  }
  1330. X  *argc = nargc;
  1331. X  return (errors);
  1332. X}
  1333. X
  1334. X/*---------------------------------------------------------
  1335. X *    set_argument
  1336. X *---------------------------------------------------------*/
  1337. X
  1338. Xstatic int set_argument (argp, linep)
  1339. X  ARG  *argp;
  1340. X  char **linep;
  1341. X{
  1342. X  /* Holt den Wert fuer die (bereits in argtab als vorhanden erkannte)
  1343. X     Option in die zugehoerige in argtab angegebene Variable.
  1344. X     Es wird linep so weit weitergeschaltet, wie Daten zur Bestimmung der
  1345. X     Variablen entnommen werden, d.h. bei STRING auf NULL, bei CHARACTER
  1346. X     um 1 Zeichen, bei INTEGER bis zum Ende der Zahl
  1347. X     (oder gar nicht, falls keine kommt) und bei BOOLEAN um 0 oder 1,
  1348. X     je nachdem ob ein + oder - angegeben wurde oder nicht.
  1349. X     Liefert 0 falls ein nicht erlaubter Wert festgestellt wurde, sonst 0.
  1350. X  */
  1351. X#define p (argp->variable)
  1352. X  char *oldp;
  1353. X  ++(*linep);   /* skip Optionname */
  1354. X  oldp = *linep;
  1355. X  switch (argp->type) {
  1356. X        case INTEGER:
  1357. X              *p = stoi (linep);
  1358. X              return (oldp != *linep);
  1359. X        case BOOLEAN:
  1360. X              if (**linep == '-' || **linep == '+') {  /* + or - given */
  1361. X                 *p = (**linep == '+');
  1362. X                 ++(*linep);              /* then take it and evaluate */
  1363. X              }
  1364. X              else                        /* else assume TRUE */
  1365. X                 *p = 1;
  1366. X              return (1);
  1367. X        case CHARACTER:
  1368. X              *p = (int)**linep;
  1369. X              ++(*linep);      /* go on one char */
  1370. X              return (*p != 0);
  1371. X        case STRING:
  1372. X              *(char **)p = *linep;
  1373. X              *linep = "";   /* take all the rest */
  1374. X              return (1);
  1375. X  }
  1376. X#undef p
  1377. X}
  1378. X
  1379. X/*---------------------------------------------------------
  1380. X *    find_argument
  1381. X *---------------------------------------------------------*/
  1382. X
  1383. Xstatic ARG* find_argument (optionname, tabp, tabsize)
  1384. X  int  optionname;
  1385. X  ARG *tabp;
  1386. X  int  tabsize;
  1387. X{
  1388. X  for (; --tabsize >= 0; tabp++)
  1389. X      if (tabp->arg == optionname)
  1390. X         return (tabp);
  1391. X  return (0);  /* not found */
  1392. X}
  1393. X
  1394. X/*---------------------------------------------------------
  1395. X *    print_usage
  1396. X *---------------------------------------------------------*/
  1397. X
  1398. Xextern void print_usage (progname, usage, tabp, tabsize)
  1399. X  char *progname, *usage;
  1400. X  ARG  *tabp;
  1401. X  int  tabsize;
  1402. X{
  1403. X  /* Druckt die Optionsbeschreibungen laut tabp incl. momentaner Werte der
  1404. X     zugeh. Variablen sowie zuvor eine "usage:" Zeile mit den Texten
  1405. X     progname und usage.
  1406. X  */
  1407. X  char *p;
  1408. X  int  i;
  1409. X  fprintf (stderr, "\n%s: %s %s\n%s:\n", USAGE, progname,
  1410. X       usage, VALID_OPT_ARE);
  1411. X  for (i = 0; i < tabsize; i++, tabp++) {
  1412. X      fprintf (stderr, "-%c", tabp->arg);
  1413. X      p = tabp->errmsg;
  1414. X      switch (tabp->type) {
  1415. X            case INTEGER:
  1416. X                  fprintf (stderr, "<num> %-45s (%d)\n",
  1417. X                           p, *(tabp->variable));
  1418. X                  break;
  1419. X            case BOOLEAN:
  1420. X                  fprintf (stderr, "<+/-> %-45s (%s)\n",
  1421. X                           p, *(tabp->variable) ? "TRUE" : "FALSE");
  1422. X                  break;
  1423. X            case CHARACTER:
  1424. X                  fprintf (stderr, "<ch>  %-45s (%c)\n",
  1425. X                           p, (char)*(tabp->variable));
  1426. X                  break;
  1427. X            case STRING:
  1428. X                  fprintf (stderr, "<str> %-45s (\"%s\")\n",
  1429. X                           p, *(char **)tabp->variable);
  1430. X                  break;
  1431. X            }
  1432. X      }
  1433. X}
  1434. X
  1435. X
  1436. X/********************* Hilfsfunktionen ************************************/
  1437. X
  1438. X
  1439. X/*---------------------------------------------------------
  1440. X *    stoi
  1441. X *---------------------------------------------------------*/
  1442. X
  1443. Xstatic int stoi (instr)
  1444. X  register char **instr;
  1445. X{
  1446. X  int  num = 0;
  1447. X  int  sign = 0;  /* Betrag und neg. Vorzeichen des Resultats */
  1448. X  char *str = *instr;
  1449. X  while (isspace (*str))
  1450. X        str++;
  1451. X  if (*str == '-') {
  1452. X     sign = -1;
  1453. X     str++;
  1454. X  }
  1455. X  if (*str == '0') {
  1456. X     ++str;
  1457. X     if (toupper (*str) == 'X') {
  1458. X        str++;
  1459. X        while(isxdigit(*str)) {
  1460. X              num *= 16;
  1461. X              num += isdigit (*str) ? *str - '0' 
  1462. X                            : toupper (*str) - 'A'+ 10;
  1463. X              str++;
  1464. X        }
  1465. X     }
  1466. X     else {
  1467. X        while ('0' <= *str && *str <= '7') {
  1468. X              num *= 8;
  1469. X              num += *str++ - '0';
  1470. X        }
  1471. X     }
  1472. X  }
  1473. X  else {
  1474. X     while (isdigit (*str)) {
  1475. X           num *= 10;
  1476. X           num += *str++ - '0';
  1477. X     }
  1478. X  }
  1479. X  *instr = str;
  1480. X  return (sign ? -num : num);
  1481. X}
  1482. X
  1483. X/************* Hauptprogramm zum Testen **********************************/
  1484. X
  1485. X#if 0
  1486. X
  1487. X  int a, b, c;
  1488. X  char *d;
  1489. X  ARG argtab[] = { {'a', BOOLEAN, &a, "Option a" },
  1490. X                   {'b', CHARACTER,&b, "Option b" },
  1491. X                   {'c', INTEGER, &c, "Option c" },
  1492. X                   {'d', STRING  , (int*)printf, "Option d" } };
  1493. X
  1494. Xvoid main (int argc, char **argv)
  1495. X{
  1496. X  int i, n;
  1497. X  printf ("Argumentpointer argv[i]: ");
  1498. X  for (i = 0; i < argc; i++)
  1499. X      printf ("%d ", (int)argv[i]);
  1500. X  printf ("\n");
  1501. X  n = getargs (&argc, argv, argtab, ARGTABSIZE (argtab));
  1502. X  if (n)
  1503. X     print_usage (argv [0], "rabarber", argtab, ARGTABSIZE (argtab));
  1504. X  printf ("\n\n RESULTATE (%d): a = %d, b = %c, c = %d, d = \"%s\"\n\n",
  1505. X          n, a, (char)b, c, d);
  1506. X  printf ("ARGV: ");
  1507. X  for (i = 0; i < argc; i++)
  1508. X      printf ("<%s> ", argv[i]);
  1509. X}
  1510. X
  1511. X#endif
  1512. X
  1513. END_OF_FILE
  1514.   if test 12454 -ne `wc -c <'getargs.c'`; then
  1515.     echo shar: \"'getargs.c'\" unpacked with wrong size!
  1516.   fi
  1517.   # end of 'getargs.c'
  1518. fi
  1519. if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  1520.   echo shar: Will not clobber existing file \"'patchlevel.h'\"
  1521. else
  1522.   echo shar: Extracting \"'patchlevel.h'\" \(139 characters\)
  1523.   sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
  1524. X/* This file is not really used. Please look into cr_texts.h */
  1525. X
  1526. X#define version  "C-Refine Version 2.4"
  1527. X#define patchlevel "Patchlevel 1"
  1528. END_OF_FILE
  1529.   if test 139 -ne `wc -c <'patchlevel.h'`; then
  1530.     echo shar: \"'patchlevel.h'\" unpacked with wrong size!
  1531.   fi
  1532.   # end of 'patchlevel.h'
  1533. fi
  1534. echo shar: End of archive 3 \(of 4\).
  1535. cp /dev/null ark3isdone
  1536. MISSING=""
  1537. for I in 1 2 3 4 ; do
  1538.     if test ! -f ark${I}isdone ; then
  1539.     MISSING="${MISSING} ${I}"
  1540.     fi
  1541. done
  1542. if test "${MISSING}" = "" ; then
  1543.     echo You have unpacked all 4 archives.
  1544.     rm -f ark[1-9]isdone
  1545. else
  1546.     echo You still must unpack the following archives:
  1547.     echo "        " ${MISSING}
  1548. fi
  1549. exit 0
  1550. exit 0 # Just in case...
  1551.