home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / reviewed / volume02 / crefine / part04 < prev    next >
Encoding:
Internet Message Format  |  1992-07-14  |  40.7 KB

  1. From: Lutz Prechelt <prechelt@ira.uka.de>
  2. Subject: v02i017: crefine - (Ver. 3.0) C language extension, Part04/06
  3. Newsgroups: comp.sources.reviewed
  4. Approved: csr@calvin.dgbt.doc.ca
  5.  
  6. Submitted-by: Lutz Prechelt <prechelt@ira.uka.de>
  7. Posting-number: Volume 2, Issue 17
  8. Archive-name: crefine/part04
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of shell archive."
  17. # Contents:  cr_getln.cr cr_talk.cr erato.cr getargs.cr
  18. # Wrapped by prechelt@Sansibar on Fri Jun 12 13:13:44 1992
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'cr_getln.cr' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'cr_getln.cr'\"
  22. else
  23. echo shar: Extracting \"'cr_getln.cr'\" \(18326 characters\)
  24. sed "s/^X//" >'cr_getln.cr' <<'END_OF_FILE'
  25. X/*************************************************************************
  26. XProject : C-Refine Precompiler
  27. XModule  : Line Scanner
  28. XAuthor  : Lutz Prechelt, Karlsruhe
  29. XDate    : 08.05.92  Version 17
  30. XCompiler: C, C-Refine
  31. X**************************************************************************/
  32. X/*
  33. X    Copyright (C) 1988,89,90,91 by Lutz Prechelt, Karlsruhe
  34. X
  35. X    This program is free software; you can redistribute it and/or modify
  36. X    it under the terms of the GNU General Public License as published by
  37. X    the Free Software Foundation; either version 1, or (at your option)
  38. X    any later version.
  39. X    This program is distributed in the hope that it will be useful,
  40. X    but WITHOUT ANY WARRANTY; without even the implied warranty of
  41. X    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  42. X    GNU General Public License for more details.
  43. X    You should have received a copy of the GNU General Public License
  44. X    along with this program; if not, write to the Free Software
  45. X    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  46. X*/
  47. X
  48. X/************************************************************************
  49. X*********************** C - R e f i n e *********************************
  50. X*************************************************************************/
  51. X
  52. X#include <stdio.h>
  53. X#include <ctype.h>
  54. X
  55. X#include "cr_decl.h"  /* globale Funktionen, Typen und Daten */
  56. X
  57. X/******************* lokale Funktionen ************************************/
  58. X
  59. Xstatic void  push_refinement_name A(());
  60. Xstatic int   normal_scanner A((LINE_INFO*));
  61. Xstatic int   comment_scanner A((LINE_INFO*));
  62. Xstatic int   text_scanner A((LINE_INFO*));
  63. Xstatic int   char_scanner A((LINE_INFO*));
  64. Xstatic int   preprocessor_scanner A((LINE_INFO*));
  65. X
  66. X/*************************** defines ***************************************/
  67. X
  68. X#define push(ch) ((*((s)++)) = (char)(ch))
  69. X
  70. X#define leave_sequence    "leave"   /* e.g. "leave" (no leading blank!) */
  71. X#define leave_sequence_length  5
  72. X
  73. X#define normal_end_of_line       1   /* real end of line */
  74. X#define continueing_end_of_line  2   /* logical end of line */
  75. X#define refinementsymbol_found   3
  76. X#define leave_keyword_found      4
  77. X
  78. X/*********************** Lokale Daten ************************************/
  79. X
  80. X/***** one line buffer *****/
  81. Xstatic char *act;             /* current position in b */
  82. X
  83. X/***** Control *****/
  84. X#if ansi
  85. Xstatic int (*scanner) (LINE_INFO*);
  86. X#else
  87. Xstatic int (*scanner) ();
  88. X#endif
  89. X/***** Status *****/
  90. Xstatic int  level,                 /* brace-nesting */
  91. X            just_was, event,       /* event memory */
  92. X            semicolon_count,
  93. X            lines_in_denoter,
  94. X            old_indent;
  95. X
  96. X/*********************** init_scanner ************************************/
  97. X
  98. Xextern void init_scanner ()
  99. X{
  100. X  /* Initializes the state of this module */
  101. X  level = 0;
  102. X  just_was = event = normal_end_of_line;
  103. X  scanner = normal_scanner;
  104. X}
  105. X
  106. X/*********************** get_line ****************************************/
  107. X
  108. Xextern void get_line (fp, l, semicolons)
  109. X  FILE       *fp;
  110. X  LINE_INFO  *l;
  111. X  int        *semicolons;  /* is increased only ! */
  112. X{
  113. X  /* Reads on line from file fp and sets up l accordingly.
  114. X     The preprocessed line is copied to *s and s is increased appropriately.
  115. X     (A null terminator is appended.)
  116. X     The line is a complete line only, if there is no refinement involved 
  117. X     with that line:
  118. X     For refinement calls and refinement declaration headers a separate line
  119. X     is generated.
  120. X     At end of file stop_processing is set to true. Problems yield a 
  121. X     message and let 'errors' or 'warnings' increase.
  122. X     This function uses the option indicator variables, and the variables
  123. X     line_no and commanded_line_no.
  124. X  */
  125. X  charp old_s = s;    /* store s to compute length later */
  126. X  bool stop = false;
  127. X  bool three_witches;
  128. X  semicolon_count = 0;
  129. X  `init l;
  130. X  if (just_was == normal_end_of_line) {
  131. X     `read line;
  132. X     `get indent;
  133. X  }
  134. X  else {                       /* continued line */
  135. X     l->indent = old_indent;
  136. X     l->line_no = line_no;
  137. X  }
  138. X  `handle line;
  139. X
  140. X`init l:
  141. X#if debug
  142. X  printf ("get_line:");
  143. X#endif
  144. X  l->level   = level;   /* level is defined as level at start of line! */
  145. X  l->start   = s;
  146. X  l->indent  = 0;
  147. X  l->type    = normal_line;
  148. X
  149. X`read line:
  150. X  l->line_no = ++line_no;
  151. X  act = (char*)fgets (b, b_size, fp);  /* get next line*/
  152. X#if debug
  153. X  printf ("->%s<-", act == NULL ? "(NULL)" : (char*)act);
  154. X#endif
  155. X  if (act == NULL) {                /* check for EOF */
  156. X     stop_processing = true;
  157. X     l->type = empty_line;
  158. X     if (level > 0)
  159. X        error (Eeof_brace, NULL, line_no);
  160. X     if (scanner == comment_scanner)
  161. X        error (Eeof_comment, NULL, line_no);
  162. X     if (scanner == text_scanner)
  163. X        error (Eeof_string, NULL, line_no);
  164. X     if (scanner == char_scanner)
  165. X        error (Eeof_char, NULL, line_no);
  166. X     return;
  167. X  }
  168. X
  169. X`get indent:
  170. X   while (!stop)
  171. X      if (*act == ' ') {
  172. X         l->indent++;
  173. X         act++;
  174. X      }
  175. X      else if (*act == TAB) {    /* expand Tabs */
  176. X         l->indent = (l->indent/tabsize + 1) * tabsize;
  177. X         act++;
  178. X      }
  179. X      else
  180. X         stop = true;
  181. X   old_indent = l->indent;    /* store for next call */
  182. X
  183. X`handle line:
  184. X   three_witches = l->indent == 0 && level > 0 && scanner == normal_scanner;
  185. X   if (three_witches && (int)*act == refinementsymbol)
  186. X        `handle_refinement_declaration;
  187. X   else {
  188. X      `check column 0;
  189. X      if (just_was != refinementsymbol_found &&
  190. X          just_was != leave_keyword_found)
  191. X         event = (*scanner) (l);
  192. X      `handle_event;
  193. X      if (option_small || event == normal_end_of_line)
  194. X        `delete trailing blanks;
  195. X   }
  196. X   l->length = s - old_s;
  197. X   if (l->length == 0)
  198. X      l->type = empty_line;
  199. X   push (0);  /* String Terminator */
  200. X   `perhaps warn for level changes;
  201. X   assert (!(l->type == refdecl_line && semicolon_count != 0));
  202. X   *semicolons += semicolon_count;
  203. X
  204. X`handle_refinement_declaration:
  205. X   act++;                     /* skip refinementsymbol */
  206. X   push_refinement_name ();
  207. X   if (*act != ':')
  208. X      error (Erefdecl_syntax, act, line_no);
  209. X   else
  210. X      act++;
  211. X   if (level > 1)
  212. X      error (Erefdecl_nested, NULL, line_no);
  213. X   l->type = refdecl_line;
  214. X   just_was = (*act == '\n' || *act == 0) ? normal_end_of_line :
  215. X                                            continueing_end_of_line;
  216. X
  217. X`check column 0:
  218. X  if (three_witches && !iscntrl (*act) &&
  219. X      just_was != continueing_end_of_line &&
  220. X      *act != '}' && *act != '#' && *act != '*' && *act != '/')
  221. X     warning (Wcol0, act, line_no, 1);
  222. X
  223. X`handle_event:
  224. X  if (event == refinementsymbol_found || event == leave_keyword_found)
  225. X     `handle refinementcall or leave;
  226. X  else
  227. X     just_was = normal_end_of_line;
  228. X
  229. X`handle refinementcall or leave:
  230. X   if (s - old_s == 0) {        /* line empty */
  231. X      push_refinement_name ();
  232. X      l->type = event == leave_keyword_found ? leave_line : refcall_line;
  233. X      `skip semicolon and blanks;
  234. X      just_was = (*act == 0 || *act == '\n') ? normal_end_of_line :
  235. X                                               continueing_end_of_line;
  236. X   }
  237. X   else
  238. X      just_was = event;
  239. X
  240. X`skip semicolon and blanks:
  241. X   if (*act == ';') {        /* skip semikolon if present */
  242. X      act++;
  243. X      semicolon_count++;
  244. X      if (l->type == refcall_line)
  245. X         l->type = refcallr_line;   /* note the removed ";" */
  246. X   }
  247. X   while (*(act++) == ' ')   /* skip following blanks */
  248. X           ;
  249. X   act--;                    /* recover char after last blank */
  250. X
  251. X`delete trailing blanks:
  252. X   while (*(s-1) == ' ')      /* remove trailing blanks */
  253. X     s--;
  254. X
  255. X`perhaps warn for level changes:
  256. X   int lev = level;
  257. X   if (lev < 0) {  /* Syntax error!  (or C-Refine does not work...) */
  258. X      if (option_anyway)
  259. X         error (Emany_braces, NULL, line_no);
  260. X      else
  261. X         fatal_error (Emany_braces, NULL, line_no);
  262. X   }
  263. X   else if (lev > 5 && level > l->level)
  264. X         warning (Wnesting, NULL, line_no, 3);
  265. X   else if (l->indent > 35 && `is refcall && !option_small)
  266. X         warning (Wmuch_indent, NULL, line_no, 3);
  267. X
  268. X`is refcall:
  269. X   l->type == refcall_line || l->type == refcallr_line
  270. X}
  271. X
  272. X/********************** push_refinement_name *******************************/
  273. X
  274. Xstatic void push_refinement_name ()
  275. X{
  276. X  /* reads input using 'act' and generates output using 's'.
  277. X     reads all following blanks, letters, digits and underscores (that is,
  278. X     stops on other characters) and generates from that a C identifier
  279. X     on the output by suppressing leading and trailing blanks.
  280. X     With option_ibmchars the Umlaute and Accentcharacters from the
  281. X     IBM International Charset are also allowed.
  282. X  */
  283. X#define is_legal(ch)  (isalnum(ch) || (ch) == ' ' || ch == '_' || \
  284. X                       (option_ibmchars && \
  285. X                           (((ch) >= 128 && (ch) <= 167)) || (ch) == 225))
  286. X  int ch;
  287. X  charp old_s = s, start = s;
  288. X  `suppress leading blanks;
  289. X  `copy legal chars;
  290. X  `suppress trailing blanks;
  291. X  assert (*(s-1) != ' ');
  292. X  assert (*old_s != ' ');
  293. X  assert (s - old_s >= 0);
  294. X  `change inner blanks to underlines;
  295. X  if (s - old_s == 0)
  296. X     error (Erefname_missing, act, line_no);
  297. X
  298. X`suppress leading blanks:
  299. X   while (*act == ' ')               /* suppress leading blanks */
  300. X     act++;
  301. X
  302. X`copy legal chars:
  303. X   do {                              /* copy legal chars */
  304. X     ch = *(act++);
  305. X     push (ch);
  306. X   }
  307. X   while (is_legal (ch));
  308. X   s--; act--;                       /* unpush illegal last char */
  309. X
  310. X`suppress trailing blanks:
  311. X   while (*(s-1) == ' ' && s > old_s) /* suppress trailing blanks */
  312. X      s--;
  313. X
  314. X`change inner blanks to underlines:
  315. X   for (start++; start < s; start++) /* change inner blanks to underlines */
  316. X     if (*start == ' ')
  317. X        *start = '_';
  318. X#undef is_legal
  319. X}
  320. X
  321. X/***********************  S C A N N I N G  *********************************/
  322. X
  323. X#define q    39      /* Quote */
  324. X#define dq   34      /* Double-Quote */
  325. X
  326. X/*********************** normal_scanner ***********************************/
  327. X
  328. Xstatic int normal_scanner (l)
  329. X  LINE_INFO *l;
  330. X{
  331. X  /* Changes to reading comments, strings, quoted chars or preprocessor
  332. X     directives as necessary.
  333. X     Ends only at the end of a line.
  334. X     Tries to identify refinement calls and refinement declarations;
  335. X     in these cases the lines are reduced to only the refinement name.
  336. X  */
  337. X  register int ch;
  338. X  for (;;) {
  339. X    ch = *(act++);
  340. X    switch (ch) {
  341. X      case '\n':
  342. X      case 0   : return (normal_end_of_line);
  343. X      case '/' : if (*act == '*')              /* start of comment ? */
  344. X                    `handle normal comment;
  345. X                 else if (*act == '/' && option_cplusplus)
  346. X                    `handle doubleslash style comment;
  347. X                 else                           /* No --> normal */
  348. X                    push (ch);
  349. X                 break;
  350. X      case dq  : `handle text denoter;
  351. X      case q   : `handle char denoter;
  352. X      case '#' : `handle preprocessor directive;
  353. X      case ';' : semicolon_count++;
  354. X                 push (';');
  355. X                 break;
  356. X      case '{' : level++;
  357. X                 push (ch);
  358. X                 break;
  359. X      case '}' : level--;
  360. X                 push (ch);
  361. X                 break;
  362. X      default  :
  363. X                 if (ch == refinementsymbol)
  364. X                   `check for leave or refinement call;
  365. X                 else
  366. X                   push (ch);
  367. X    }
  368. X  }
  369. X
  370. X`handle normal comment:
  371. X   if (!option_small) {
  372. X      push (ch); push ('*');
  373. X   }
  374. X   act++;
  375. X   scanner = comment_scanner;
  376. X   return ((*scanner) (l));
  377. X
  378. X`handle doubleslash style comment:
  379. X   if (option_small)
  380. X      return (normal_end_of_line);   /* just pgnore rest of line */
  381. X   push (ch); push (ch);             /*  put  //   */
  382. X   act++;
  383. X   while (*act != '\n' && *act != 0)   /* put rest of line */
  384. X      push (*(act++));
  385. X   return (normal_end_of_line);
  386. X
  387. X`handle text denoter:
  388. X   push (ch);
  389. X   scanner = text_scanner;
  390. X   lines_in_denoter = 0;
  391. X   return ((*scanner) (l));
  392. X
  393. X`handle char denoter:
  394. X   push (ch);
  395. X   scanner = char_scanner;
  396. X   lines_in_denoter = 0;
  397. X   return ((*scanner) (l));
  398. X
  399. X`handle preprocessor directive:
  400. X   push (ch);
  401. X   scanner = preprocessor_scanner;
  402. X   return ((*scanner) (l));
  403. X
  404. X`check for leave or refinement call :
  405. X   /* Precondition: Refinement symbol found, 'act' is right behind it.
  406. X      if a 'leave' surrounded by blanks is found in front of the 
  407. X      refinement symbol, it and its blanks are stripped and 
  408. X      leave_keyword_found is returned.
  409. X      Otherwise refinementsymbol_found gemeldet is returned
  410. X   */
  411. X   charp old_s = s--;
  412. X   while (*s == ' ')
  413. X      s--;
  414. X   s++;
  415. X   if (!memcmp (s - leave_sequence_length, leave_sequence,
  416. X                leave_sequence_length)) {
  417. X      s -= leave_sequence_length;     /* Remove leave_sequence from Output */
  418. X      return (leave_keyword_found);
  419. X   }
  420. X   else {
  421. X      s = old_s;
  422. X      return (refinementsymbol_found);
  423. X   }
  424. X}
  425. X
  426. X/********************* comment_scanner *************************************/
  427. X
  428. Xstatic int comment_scanner (l)
  429. X  LINE_INFO *l;
  430. X{
  431. X  /* Precondition: position is right behind a start of a comment 
  432. X     (which is already copied if not option_small is true)
  433. X     Postcondition: position is right after a comment end.
  434. X  */
  435. X  register int ch;
  436. X  for (;;) {
  437. X    ch = *(act++);
  438. X    switch (ch) {
  439. X      case '\n':
  440. X      case 0   : return (normal_end_of_line);
  441. X      case '*' : if (*act == '/')       /* end of comment : */
  442. X                    `handle comment end;
  443. X                 /* no break ! */
  444. X      default  : if (!option_small)
  445. X                    push (ch);
  446. X    }
  447. X  }
  448. X
  449. X`handle comment end:
  450. X   if (!option_small) {
  451. X      push (ch); push ('/');
  452. X   }
  453. X   act++;
  454. X   scanner = normal_scanner;   /* change to normal scanner */
  455. X   return ((*scanner) (l));    /* and continue scanning */
  456. X
  457. X}
  458. X
  459. X/********************* text_scanner *************************************/
  460. X
  461. Xstatic int text_scanner (l)
  462. X  LINE_INFO *l;
  463. X{
  464. X  /* Precondition: position is right behind the (already copied) 
  465. X                   double quote that starts a string denoter 
  466. X                   (string literal)
  467. X     Postcondition:position is right behind the closing double
  468. X                   quote of a string denoter
  469. X  */
  470. X  register int ch;
  471. X  lines_in_denoter++;
  472. X  for (;;) {
  473. X    ch = *(act++);
  474. X    switch (ch) {
  475. X      case '\n':
  476. X      case 0   : return (normal_end_of_line);  /* allowed ??? */
  477. X      case dq  : `end of stringdenoter;
  478. X      case '\\': push (ch);
  479. X                 if (*act == dq || *act == '\\') {
  480. X                    push (*act);
  481. X                    act++;
  482. X                 }
  483. X                 break;
  484. X      default  : push (ch);
  485. X    }
  486. X }
  487. X
  488. X`end of stringdenoter:
  489. X   push (ch);
  490. X   if (lines_in_denoter > 1)
  491. X      warning (Wlong_string, act-1, line_no,
  492. X               lines_in_denoter > 5 ? 1 : 2);
  493. X   scanner = normal_scanner;
  494. X   return ((*scanner) (l));
  495. X
  496. X}
  497. X
  498. X/********************* char_scanner *************************************/
  499. X
  500. Xstatic int char_scanner (l)
  501. X  LINE_INFO *l;
  502. X{
  503. X  /* Is analogous to text scanner, but uses single quote instead of double
  504. X     quote.
  505. X  */
  506. X  int ch;
  507. X  lines_in_denoter++;
  508. X  for (;;) {
  509. X    ch = *(act++);
  510. X    switch (ch) {
  511. X      case '\n':
  512. X      case 0   : return (normal_end_of_line);  /* allowed ??? */
  513. X      case q   : `end of chardenoter;
  514. X      case '\\': push (ch);
  515. X                 if (*act == q || *act == '\\') {
  516. X                    push (*act);
  517. X                    act++;
  518. X                 }
  519. X                 break;
  520. X      default  : push (ch);
  521. X    }
  522. X  }
  523. X
  524. X`end of chardenoter:
  525. X   push (ch);
  526. X   if (lines_in_denoter > 1)
  527. X      warning (Wlong_char, act-1, line_no,
  528. X               lines_in_denoter > 5 ? 1 : 2);
  529. X   scanner = normal_scanner;
  530. X   return ((*scanner) (l));
  531. X
  532. X}
  533. X
  534. X/********************* preprocessor_scanner ******************************/
  535. X
  536. Xstatic int preprocessor_scanner (l)
  537. X  LINE_INFO *l;
  538. X{
  539. X  /* Scans a line with a preprocessor directive on it.
  540. X     If this line contains a #line directive, reads the line number and
  541. X     file name and sets line_no and name_in accordingly. 
  542. X     This scanner is called immediately after the # has been seen.
  543. X     The line is copied verbatim.
  544. X  */
  545. X  int ch;
  546. X  ch = *(act++);
  547. X  `skip whitespace;
  548. X  `try to read line command;
  549. X  `copy rest of line;
  550. X  
  551. X`skip whitespace:
  552. X   for (;;) {
  553. X     switch (ch) {
  554. X       case ' ' :
  555. X       case TAB : push (ch);
  556. X                  break;
  557. X       case '\n':
  558. X       case 0   : scanner = normal_scanner;
  559. X                  return (normal_end_of_line);
  560. X       default  : leave `skip whitespace;
  561. X     }
  562. X     ch = *(act++);
  563. X   }
  564. X
  565. X`try to read line command:
  566. X   /* precondition:  ch = <first nonwhitespace character after '#' >
  567. X      postcondition: ch = <first char not belonging to line command>
  568. X   */
  569. X   `read the command token;
  570. X   `skip whitespace;
  571. X   `read the line number;
  572. X   `skip whitespace;
  573. X   `read the filename;
  574. X  
  575. X`read the command token:
  576. X   /* ch = <first nonwhitespace character after '#' > */
  577. X   if (strncmp ("line", act, 4)) {
  578. X     if (!isdigit (ch))
  579. X       leave `try to read line command;
  580. X   }
  581. X   else {
  582. X     push (*(act++));
  583. X     push (*(act++));
  584. X     push (*(act++));
  585. X     push (*(act++));
  586. X     ch = *(act++);
  587. X     if (ch != ' ' && ch != TAB)  /* 'line<something> without whitespace */
  588. X       leave `try to read line command;
  589. X   }
  590. X
  591. X`read the line number:
  592. X   int number = 0;
  593. X   while (isdigit (ch)) {
  594. X     push (ch);
  595. X     number = 10*number + (ch - '0');
  596. X     ch = *(act++);
  597. X   }
  598. X   line_no = commanded_line_no = number - 1;
  599. X
  600. X`read the filename:
  601. X   bool has_quotes = ch == '\"';
  602. X   char *current_letter = name_in;
  603. X   if (has_quotes) {
  604. X     push (ch);
  605. X     ch = *(act++);
  606. X   }
  607. X   for (;;) {
  608. X     switch (ch) {
  609. X       case '\n':
  610. X       case 0   : `terminate name_in;
  611. X                  if (has_quotes)
  612. X                    warning (Eunterminated, name_in, line_no, warning_level);
  613. X                  scanner = normal_scanner;
  614. X                  return (normal_end_of_line);
  615. X       case dq  : `terminate name_in;
  616. X                  leave `read the filename;
  617. X       default  : push (ch);
  618. X                  *(current_letter++) = ch;
  619. X     }
  620. X     ch = *(act++);
  621. X   }
  622. X
  623. X`terminate name_in:
  624. X   if (current_letter != name_in)  /* if new name present */
  625. X     *current_letter = 0;  /* terminate name */
  626. X   copy_with_doubled_backslashes (name_in, modified_name_in);
  627. X
  628. X`copy rest of line:
  629. X   for (;;) {
  630. X     switch (ch) {
  631. X       case '\n':
  632. X       case 0   : scanner = normal_scanner;
  633. X                  return (normal_end_of_line);
  634. X       default  : push (ch);
  635. X     }
  636. X     ch = *(act++);
  637. X   }
  638. X
  639. X}
  640. X
  641. END_OF_FILE
  642. if test 18326 -ne `wc -c <'cr_getln.cr'`; then
  643.     echo shar: \"'cr_getln.cr'\" unpacked with wrong size!
  644. fi
  645. # end of 'cr_getln.cr'
  646. fi
  647. if test -f 'cr_talk.cr' -a "${1}" != "-c" ; then 
  648.   echo shar: Will not clobber existing file \"'cr_talk.cr'\"
  649. else
  650. echo shar: Extracting \"'cr_talk.cr'\" \(3380 characters\)
  651. sed "s/^X//" >'cr_talk.cr' <<'END_OF_FILE'
  652. X/*************************************************************************
  653. XProject : C-Refine Precompiler
  654. XModule  : Output functions for messages
  655. XAuthor  : Lutz Prechelt, Karlsruhe
  656. XDate    : 08.05.92  Version 17
  657. XCompiler: C, C-Refine
  658. X**************************************************************************/
  659. X/*
  660. X    Copyright (C) 1988,89,90,91 by Lutz Prechelt, Karlsruhe
  661. X
  662. X    This program is free software; you can redistribute it and/or modify
  663. X    it under the terms of the GNU General Public License as published by
  664. X    the Free Software Foundation; either version 1, or (at your option)
  665. X    any later version.
  666. X    This program is distributed in the hope that it will be useful,
  667. X    but WITHOUT ANY WARRANTY; without even the implied warranty of
  668. X    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  669. X    GNU General Public License for more details.
  670. X    You should have received a copy of the GNU General Public License
  671. X    along with this program; if not, write to the Free Software
  672. X    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  673. X*/
  674. X
  675. X/************************************************************************
  676. X*********************** C - R e f i n e *********************************
  677. X*************************************************************************/
  678. X
  679. X#include <stdio.h>
  680. X
  681. X#include "cr_decl.h"   /* global Functions, Types and Data */
  682. X#include "cr_texts.h"  /* message texts */
  683. X
  684. Xstatic void error_message A((charp[], charp[], charp, int));
  685. X
  686. X/************************* cout *******************************************/
  687. X
  688. Xextern void cout (i)
  689. X  int i;
  690. X{
  691. X  /* Writes number i on stderr (which is assumed to be a screen)
  692. X     with length five and positions the cursor back to the starting
  693. X     position with five backspaces.
  694. X     This is not very fast, but that doesn't matter.
  695. X  */
  696. X  fprintf (stderr, "%5d\b\b\b\b\b", i);
  697. X}
  698. X
  699. X/************************ error *******************************************/
  700. X
  701. Xstatic void error_message (type, message, object, line)
  702. X  charp type[], message[];
  703. X  charp object;
  704. X  int   line;
  705. X{
  706. X  fprintf (stdout, "\"%s\", line %d, %s: %s\n", name_in,
  707. X           line, type[msg_type], message[msg_type]);
  708. X  if (object != NULL) {
  709. X    char *nl = strchr (object, '\n');
  710. X    if (nl != NULL)     /* remove newline from object */
  711. X      *nl = 0;
  712. X   fprintf (stdout, "    %s \"%s\"\n", Tnear[msg_type], object);
  713. X   if (nl != NULL)
  714. X     *nl = '\n';
  715. X  }
  716. X}
  717. X
  718. X
  719. Xextern void error (message, object, line)
  720. X  charp message[];
  721. X  charp object;
  722. X  int   line;
  723. X{
  724. X  error_message (Terror, message, object, line);
  725. X  if (++errors > maxerrors)
  726. X     fatal_error (Emany_errors, "(-----ManteldesSchweigens-----)", line);
  727. X  error_in_this_function = true;
  728. X}
  729. X
  730. X/************************ fatal_error *************************************/
  731. X
  732. Xextern void fatal_error (message, object, line)
  733. X  charp message[];
  734. X  charp object;
  735. X  int   line;
  736. X{
  737. X  error_message (Tfatal_error, message, object, line);
  738. X  stop_processing = true;
  739. X  errors++;
  740. X}
  741. X
  742. X/************************ warning *****************************************/
  743. X
  744. Xextern void warning (message, object, line, level)
  745. X  charp message[];
  746. X  charp object;
  747. X  int   line, level;
  748. X{
  749. X  if (!error_in_this_function && level <= warning_level) {
  750. X     /* don't be too verbose */
  751. X     error_message (Twarning, message, object, line);
  752. X     if (++warnings > maxwarnings)
  753. X        fatal_error (Emany_warnings, NULL, line);
  754. X  }
  755. X}
  756. X
  757. END_OF_FILE
  758. if test 3380 -ne `wc -c <'cr_talk.cr'`; then
  759.     echo shar: \"'cr_talk.cr'\" unpacked with wrong size!
  760. fi
  761. # end of 'cr_talk.cr'
  762. fi
  763. if test -f 'erato.cr' -a "${1}" != "-c" ; then 
  764.   echo shar: Will not clobber existing file \"'erato.cr'\"
  765. else
  766. echo shar: Extracting \"'erato.cr'\" \(2305 characters\)
  767. sed "s/^X//" >'erato.cr' <<'END_OF_FILE'
  768. X/*************************************************************************
  769. XModule  : C-Refine example program
  770. XAuthor  : Lutz Prechelt, Karlsruhe
  771. XDate    : 23.01.91
  772. X**************************************************************************
  773. X/*
  774. X    Copyright (C) 1988,90 by Lutz Prechelt, Karlsruhe
  775. X
  776. X    This program is free software; you can redistribute it and/or modify
  777. X    it under the terms of the GNU General Public License as published by
  778. X    the Free Software Foundation; either version 1, or (at your option)
  779. X    any later version.
  780. X    This program is distributed in the hope that it will be useful,
  781. X    but WITHOUT ANY WARRANTY; without even the implied warranty of
  782. X    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  783. X    GNU General Public License for more details.
  784. X    You should have received a copy of the GNU General Public License
  785. X    along with this program; if not, write to the Free Software
  786. X    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  787. X*/
  788. X
  789. X#define MAX        10000
  790. X#define PRIME      0
  791. X#define NON_PRIME  1
  792. X
  793. Xstatic int sieve[MAX+1];
  794. X
  795. Xint main ()
  796. X{
  797. X  `initialize;
  798. X  `do sieve;
  799. X  `make output;
  800. X  return (0);
  801. X  
  802. X`initialize:
  803. X  int current;
  804. X  for (current = 2; current <= MAX; current++)
  805. X    sieve[current] = PRIME;
  806. X    
  807. X`do sieve:
  808. X  int current_prime = 1;
  809. X  for (;;) {
  810. X    `find next bigger prime;  /* perhaps STOP here */
  811. X    `delete all multiples of current_prime;
  812. X  }
  813. X
  814. X`find next bigger prime:
  815. X  int current_candidate = current_prime + 1;
  816. X  while (sieve[current_candidate] == NON_PRIME)
  817. X    if (current_candidate == MAX)
  818. X      leave `do sieve;    /* leave two refinements at once */
  819. X    else
  820. X      current_candidate++;
  821. X  /* now current_candidate is a prime (or we leave `sieve) */
  822. X  current_prime = current_candidate;
  823. X  
  824. X`delete all multiples of current_prime:
  825. X  int current = `first multiple of current_prime;
  826. X  while (current <= MAX) {
  827. X    sieve[current] = NON_PRIME;
  828. X    current += current_prime;
  829. X  }
  830. X  
  831. X`first multiple of current_prime:
  832. X  2 * current_prime
  833. X
  834. X`make output:
  835. X  int current;  /* different from 'current' above */
  836. X  printf ("The primes between 2 and %d are\n", MAX);
  837. X  for (current = 2; current <= MAX; current++)
  838. X    if (`current is prime)
  839. X      printf ("%5d ", current);
  840. X
  841. X`current is prime:
  842. X  sieve[current] == PRIME
  843. X
  844. X} /* end of main() */
  845. END_OF_FILE
  846. if test 2305 -ne `wc -c <'erato.cr'`; then
  847.     echo shar: \"'erato.cr'\" unpacked with wrong size!
  848. fi
  849. # end of 'erato.cr'
  850. fi
  851. if test -f 'getargs.cr' -a "${1}" != "-c" ; then 
  852.   echo shar: Will not clobber existing file \"'getargs.cr'\"
  853. else
  854. echo shar: Extracting \"'getargs.cr'\" \(14031 characters\)
  855. sed "s/^X//" >'getargs.cr' <<'END_OF_FILE'
  856. X/*************************************************************************
  857. XModule  : getargs -- command line option processor
  858. XAuthor  : Lutz Prechelt, Karlsruhe
  859. XDate    : 15.11.91  Version 3
  860. XCompiler: should be portable (ANSI-C or K&R-C)
  861. X**************************************************************************/
  862. X/*
  863. X    Copyright (C) 1988,91 by Lutz Prechelt, Karlsruhe
  864. X
  865. X    This program is free software; you can redistribute it and/or modify
  866. X    it under the terms of the GNU General Public License as published by
  867. X    the Free Software Foundation; either version 1, or (at your option)
  868. X    any later version.
  869. X    This program is distributed in the hope that it will be useful,
  870. X    but WITHOUT ANY WARRANTY; without even the implied warranty of
  871. X    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  872. X    GNU General Public License for more details.
  873. X    You should have received a copy of the GNU General Public License
  874. X    along with this program; if not, write to the Free Software
  875. X    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  876. X*/
  877. X
  878. X
  879. X/************************************************************************
  880. X*********************** g e t a r g s ***********************************
  881. X*************************************************************************/
  882. X#if 0
  883. X
  884. XVarianten:
  885. X#define deutsch  1   waehlt deutsche Meldungen statt englische
  886. X#define __STDC__ 1   waehlt Funktionsdefinitionen mit Parameterliste
  887. X                     statt ohne
  888. X#define ms_dos   1   erlaubt "/" als Optionszeichen zusaetzlich zu "-"
  889. X
  890. XDies ist ein Utility zum bequemeren Auswerten von Optionen auf der
  891. XKommandozeile (d.h. mit argc, argv).
  892. X
  893. XEs wird dazu vom Benutzer eine Tabelle ("argtab") aufgestellt, in der zu
  894. Xjeder Option der Optionsbuchstabe, ein Argumententyp 
  895. X(BOOL, CHAR, INT, STRING) und eine Variable angegeben werden,
  896. Xin der das Resultat abgelegt werden soll.
  897. XFerner kann man hier noch einen Kommentarstring zu jeder Option angeben.
  898. X
  899. XDie Funktion getargs (&argc, argv, argtab, argtabsize) bearbeitet nun den
  900. Xargv Vektor derart, dass alle Optionen, die in argtab angegeben sind, gemaess
  901. Xihrem Eintrag behandelt werden und aus argv entfernt (dazu wird argc und argv
  902. Xmodifiziert, jedoch nur Pointer veraendert, keine argv-Eintraege selbst)
  903. XEs duerfen beim Aufruf die Optionen beliebig mit den uebrigen Parametern
  904. Xvermischt und mehrere Optionen hinter einem Optionssymbol angegeben
  905. Xwerden.
  906. X
  907. XEs werden unbekannte Optionen festgestellt und angemeckert (nach stderr)
  908. XAls Resultat wird die Anzahl angemeckerter Optionen geliefert.
  909. X
  910. XDie Funktion print_usage (program_name, usage_text, argtab, argtabsize)
  911. Xgibt unter Benutzung der Kommentarstrings aus argtab eine Kurzbeschreibung zum
  912. Xkorrekten Aufruf aller Optionen und des Gesamtprogramms nach stderr aus.
  913. X
  914. XBeispiel:
  915. X  #include <getargs.h>
  916. X  int a = 1, b = 'B', c;
  917. X  char *d = "";
  918. X  ARG argtab[] = { {'a', BOOLEAN,  &a,       "use alternate mode" },
  919. X                   {'b', CHARACTER,&b,       "Character for boldface" },
  920. X                   {'c', INTEGER,  &c,       "count of pages to print" },
  921. X                   {'d', STRING  , (int*)&d, "File description" } };
  922. X  void main (int argc, char **argv) {
  923. X     if (getargs (&argc, argv, argtab, ARGTABSIZE (argtab)))
  924. X        print_usage (argv[0], "[options] filetoprint [options]", argtab,
  925. X                     ARGTABSIZE (argtab));
  926. X  }
  927. X
  928. XEnthalte argtab also die Liste der Optionen fuer das Programm "fileprt", das
  929. X(wie in print_usage angegeben) noch einen Dateinamen als weiteren Parameter
  930. Xverlangt.
  931. X
  932. XDann waeren korrekte Aufrufe etwa:
  933. X
  934. Xfileprt -a file
  935. Xfileprt -a+ file -bB
  936. Xfileprt -c14 file -dMyFile
  937. Xfileprt file -abBc14
  938. X
  939. XVerkehrt waere dagegen zum Beispiel:
  940. X
  941. Xfileprt -dMy File file       weil <File> ein eigenes Argument ist
  942. Xfileprt -p file              weil es die Option p nicht gibt
  943. Xfileprt -bx28 file           weil CHAR immer nur ein Zeichen umfasst
  944. X
  945. XDieser letzte Aufruf haette im Beispiel ungefaehr folgenden Output nach
  946. Xstderr zur Folge:
  947. X
  948. XUnknown option : -bx28
  949. Xusage: fileprt [options] filetoprint
  950. Xvalid options are:
  951. X-a<+/-> use alternate mode                       (Wert: TRUE)
  952. X-b<ch>  Character for boldface                   (Wert: B)
  953. X-c<num> count of pages to print                  (Wert: 0)
  954. X-d<str> File description                         (Wert: "")
  955. X
  956. XDer genaue Grund fuer die Fehlermeldung ist, dass der Interpreter der Option
  957. Xb den Wert x zuweist und dann nach der (nicht auffindbaren) Option 2 sucht !
  958. X
  959. XDie "Wert"-Angaben beim print_usage entstehen aus den Vorbelegungen der
  960. XVariablen a, b, c, d;
  961. X
  962. X#endif
  963. X
  964. X/**************************************************************************/
  965. X
  966. X#include "std.h"
  967. X#include <stdio.h>
  968. X#include <ctype.h>
  969. X#include "getargs.h"
  970. X
  971. X#if deutsch
  972. X#define ERRMSG         "Unbekannte oder falsch benutzte Option"
  973. X#define USAGE          "Aufruf"
  974. X#define VALID_OPT_ARE  "Erlaubte Optionen sind"
  975. X#else
  976. X#define ERRMSG         "unknown or malformed option"
  977. X#define USAGE          "usage"
  978. X#define VALID_OPT_ARE  "valid options are"
  979. X#endif
  980. X
  981. X#define is_option(a) (*(a) == '-' && *(a+1) != 0)
  982. X
  983. Xstatic int  set_argument A((ARG* entry, char **optiontext, char **next_arg));
  984. Xstatic ARG* find_argument A((int optionname, ARG *argtab, int argtablength));
  985. Xstatic int  stoi A((char **linep, int *result));
  986. X
  987. X/*---------------------------------------------------------
  988. X *    getargs
  989. X *---------------------------------------------------------*/
  990. X
  991. Xextern int getargs (argc, argv, tabp, tabsize)
  992. X  int    *argc;    /* changed */
  993. X  char ***argv;    /* changed */
  994. X  ARG    *tabp;
  995. X  int     tabsize;
  996. X{
  997. X  /* Main routine. Evaluates all arguments in argv up to argc:
  998. X     Options (known from first letter as given by macro is_option)
  999. X     are followed by other arguments.
  1000. X     -- forces end of options.
  1001. X     options are searched for in tabp and are removed from argv by
  1002. X     shifting the remaining arguments left.
  1003. X     options are handled according to their tabp entry, 
  1004. X     illegal options or missing or illegal values are complained.
  1005. X     Otherwise the corresponding variable is set according to the value
  1006. X     given with the option. 
  1007. X     Only non-options are still in argv after this procedure, their 
  1008. X     number is given back in *argc.
  1009. X     The return value is the number of errors found.
  1010. X  */
  1011. X  char  *p, *argv0 = **argv, *nilarg = "";
  1012. X  int    errors = 0, error;
  1013. X  ARG   *argp;
  1014. X  for ((*argv)++; --(*argc) > 0; (*argv)++)
  1015. X    `handle this arg;
  1016. X  (*argv)--;
  1017. X  **argv = argv0;   /* restore program name */
  1018. X  return (errors);
  1019. X
  1020. X`handle this arg:
  1021. X   if (`is end of options) {
  1022. X      **argv = argv0;  /* restore program name */
  1023. X      return (errors);
  1024. X   }
  1025. X   else if (!is_option (**argv)) {
  1026. X      (*argv)--; (*argc)++;
  1027. X      **argv = argv0;   /* restore program name */
  1028. X      return (errors);
  1029. X   }
  1030. X   else {
  1031. X      char **next_arg = *argc > 1 ? (*argv)+1 : &nilarg;
  1032. X      p = (**argv) + 1;         /* Option -> handle it */
  1033. X      while (*p) {
  1034. X        error = 0;
  1035. X        /* One Optionsign can have multiple Options following */
  1036. X        if (argp = find_argument ((int)*p, tabp, tabsize)) /* if exists */
  1037. X          `read option value;
  1038. X        if (!argp || error) {   /* if not exists or invalid value */
  1039. X           fprintf (stderr, "%s : %s\n", ERRMSG, **argv);   /* then #$% */
  1040. X           errors++;
  1041. X           break;
  1042. X        }
  1043. X        if (*next_arg == 0) {  /* Next argv element already used up */
  1044. X          (*argv)++;
  1045. X          (*argc)--;
  1046. X        }
  1047. X      }
  1048. X    }
  1049. X
  1050. X`is end of options:
  1051. X  /* the argument "--" forces end of option processing */
  1052. X  (*argv)[0][0] == '-'  &&  (*argv)[0][1] == '-'  &&  (*argv)[0][2] == 0
  1053. X
  1054. X`read option value:
  1055. X   error = !set_argument (argp, &p, next_arg);
  1056. X
  1057. X}
  1058. X
  1059. X/*---------------------------------------------------------
  1060. X *    set_argument
  1061. X *---------------------------------------------------------*/
  1062. X
  1063. Xstatic int set_argument (argp, linep, next_arg)
  1064. X  ARG  *argp;
  1065. X  char **linep, **next_arg;
  1066. X{
  1067. X  /* Gets the argument for the current option into the corresponding
  1068. X     variable as given in argtab.
  1069. X     linep is incremented as much as necessary (as much as data is
  1070. X     used for the value).
  1071. X     If no value can be found in linep, next_arg is searched for it,
  1072. X     and, if found, set to 0.
  1073. X     Returns 1 (or 0 on errors, i.e. illegal or missing values)
  1074. X  */
  1075. X#define p (argp->variable)
  1076. X  char *old_linep, *old_next_arg = *next_arg;
  1077. X  ++(*linep);   /* skip Optionname */
  1078. X  old_linep = *linep;
  1079. X  switch (argp->type) {
  1080. X        case INTEGER:    `get integer;
  1081. X        case BOOLEAN:    `get bool;
  1082. X        case CHARACTER:  `get char;
  1083. X        case STRING:     `get string;
  1084. X  }
  1085. X  return (0);  /* just to keep certain compilers quiet */
  1086. X
  1087. X`get integer:
  1088. X   stoi (linep, p);
  1089. X   if (old_linep == *linep) {  /* no integer found in linep */
  1090. X     stoi (next_arg, p);
  1091. X     if (old_next_arg != *next_arg)
  1092. X       *next_arg = 0;
  1093. X   }
  1094. X   return (old_linep != *linep || *next_arg == 0);
  1095. X
  1096. X`get bool:
  1097. X   if (`plus or minus follows) {  /* + or - given right behind */
  1098. X      *p = (**linep == '+');
  1099. X      ++(*linep);
  1100. X   }
  1101. X   else if (`other things follow)  /* no value given */
  1102. X      *p = 1;   /* assume true */
  1103. X   else if (`next arg is plus or minus) {
  1104. X      *p = **next_arg == '+';
  1105. X      *next_arg = 0;
  1106. X   }
  1107. X   else                        /* else assume TRUE */
  1108. X      *p = 1;
  1109. X   return (1);
  1110. X
  1111. X`plus or minus follows:
  1112. X   **linep == '-' || **linep == '+'
  1113. X
  1114. X`other things follow:
  1115. X   **linep != 0
  1116. X
  1117. X`next arg is plus or minus:
  1118. X   (**next_arg == '-' || **next_arg == '+') &&
  1119. X   (*next_arg)[1] == 0
  1120. X
  1121. X`get char:
  1122. X   *p = (int)**linep;
  1123. X   if (*p != 0) {
  1124. X     ++(*linep);      /* go on one char */
  1125. X     return (1);
  1126. X   }
  1127. X   /* we must get character from next_arg, if possible */
  1128. X   if (`next_arg is a character) {
  1129. X     *p = **next_arg;
  1130. X     *next_arg = 0;
  1131. X     return (1);
  1132. X   }
  1133. X   else
  1134. X     return (0);
  1135. X     
  1136. X`next_arg is a character:
  1137. X   (*next_arg)[0] != 0  &&  (*next_arg)[1] == 0
  1138. X
  1139. X`get string:
  1140. X   if (**linep != 0) {
  1141. X     *(char **)p = *linep;
  1142. X     *linep = "";   /* take all the rest */
  1143. X     return (1);
  1144. X   }
  1145. X   /* we must get string from next_arg */
  1146. X   *(char **)p = *next_arg;
  1147. X   *next_arg = 0;
  1148. X   return (1);
  1149. X
  1150. X#undef p
  1151. X}
  1152. X
  1153. X/*---------------------------------------------------------
  1154. X *    find_argument
  1155. X *---------------------------------------------------------*/
  1156. X
  1157. Xstatic ARG* find_argument (optionname, tabp, tabsize)
  1158. X  int  optionname;
  1159. X  ARG *tabp;
  1160. X  int  tabsize;
  1161. X{
  1162. X  for (; --tabsize >= 0; tabp++)
  1163. X      if (tabp->arg == optionname)
  1164. X         return (tabp);
  1165. X  return (0);  /* not found */
  1166. X}
  1167. X
  1168. X/*---------------------------------------------------------
  1169. X *    print_usage
  1170. X *---------------------------------------------------------*/
  1171. X
  1172. Xextern void print_usage (progname, usage, tabp, tabsize)
  1173. X  char *progname, *usage;
  1174. X  ARG  *tabp;
  1175. X  int  tabsize;
  1176. X{
  1177. X  /* Druckt die Optionsbeschreibungen laut tabp incl. momentaner Werte der
  1178. X     zugeh. Variablen sowie zuvor eine "usage:" Zeile mit den Texten
  1179. X     progname und usage.
  1180. X  */
  1181. X  char *p;
  1182. X  int  i;
  1183. X  fprintf (stderr, "\n%s: %s %s\n%s:\n", USAGE, progname,
  1184. X       usage, VALID_OPT_ARE);
  1185. X  for (i = 0; i < tabsize; i++, tabp++) {
  1186. X      fprintf (stderr, "-%c", tabp->arg);
  1187. X      p = tabp->errmsg;
  1188. X      switch (tabp->type) {
  1189. X            case INTEGER:
  1190. X                  fprintf (stderr, "<num> %-45s (%d)\n",
  1191. X                           p, *(tabp->variable));
  1192. X                  break;
  1193. X            case BOOLEAN:
  1194. X                  fprintf (stderr, "<+/-> %-45s (%s)\n",
  1195. X                           p, *(tabp->variable) ? "TRUE" : "FALSE");
  1196. X                  break;
  1197. X            case CHARACTER:
  1198. X                  fprintf (stderr, "<ch>  %-45s (%c)\n",
  1199. X                           p, (char)*(tabp->variable));
  1200. X                  break;
  1201. X            case STRING:
  1202. X                  fprintf (stderr, "<str> %-45s (\"%s\")\n",
  1203. X                           p, *(char **)tabp->variable);
  1204. X                  break;
  1205. X            }
  1206. X      }
  1207. X}
  1208. X
  1209. X
  1210. X/********************* Hilfsfunktionen ************************************/
  1211. X
  1212. X
  1213. X/*---------------------------------------------------------
  1214. X *    stoi
  1215. X *---------------------------------------------------------*/
  1216. X
  1217. Xstatic int stoi (instr, result)
  1218. X  char **instr;
  1219. X  int   *result;
  1220. X{
  1221. X  /* tries to read a decimal, octal or hexadecimal number from *instr
  1222. X     and advances *instr accordingly.
  1223. X     returns whether a number could successfully be read.
  1224. X     the number read is returned in *result.
  1225. X  */
  1226. X  int  error = 1;
  1227. X  int  num = 0;
  1228. X  int  sign = 0;  /* Betrag und neg. Vorzeichen des Resultats */
  1229. X  char *str = *instr;
  1230. X  while (isspace (*str))
  1231. X        str++;
  1232. X  if (*str == '-') {
  1233. X     sign = -1;
  1234. X     str++;
  1235. X  }
  1236. X  if (*str == '0')
  1237. X    `read octal or hex;
  1238. X  else
  1239. X    `read decimal;
  1240. X  if (error)
  1241. X    return (error);
  1242. X  *instr = str;
  1243. X  *result = sign ? -num : num;
  1244. X  return (0);
  1245. X
  1246. X`read octal or hex:
  1247. X   ++str;
  1248. X   error = 0;
  1249. X   if (toupper (*str) == 'X') {
  1250. X      str++;
  1251. X      while(isxdigit(*str)) {
  1252. X            num *= 16;
  1253. X            num += isdigit (*str) ? *str - '0' 
  1254. X                              : toupper (*str) - 'A'+ 10;
  1255. X            str++;
  1256. X      }
  1257. X   }
  1258. X   else {
  1259. X      while ('0' <= *str && *str <= '7') {
  1260. X            num *= 8;
  1261. X            num += *str++ - '0';
  1262. X      }
  1263. X   }
  1264. X
  1265. X`read decimal:
  1266. X   while (isdigit (*str)) {
  1267. X     error = 0;
  1268. X     num *= 10;
  1269. X     num += *str++ - '0';
  1270. X
  1271. X   }
  1272. X
  1273. X}
  1274. X
  1275. X/************* Hauptprogramm zum Testen **********************************/
  1276. X
  1277. X#if 0
  1278. X
  1279. X  int a = 0, b = 'b', c = 3;
  1280. X  char *d = "";
  1281. X  ARG argtab[] = { {'a', BOOLEAN,     &a,  "Option a" },
  1282. X                   {'b', CHARACTER,   &b,  "Option b" },
  1283. X                   {'c', INTEGER,     &c,  "Option c" },
  1284. X                   {'d', STRING, (int*)&d,  "Option d" } };
  1285. X
  1286. Xvoid main (int argc, char **argv)
  1287. X{
  1288. X  int i, n;
  1289. X  printf ("Argumentpointer argv[i]: ");
  1290. X  for (i = 0; i < argc; i++)
  1291. X      printf ("%d ", (int)argv[i]);
  1292. X  printf ("\n");
  1293. X  n = getargs (&argc, argv, argtab, ARGTABSIZE (argtab));
  1294. X  if (n)
  1295. X     print_usage (argv [0], "rabarber", argtab, ARGTABSIZE (argtab));
  1296. X  printf ("\n RESULTATE (%d): a = %d, b = '%c', c = %d, d = \"%s\"\n",
  1297. X          n, a, (char)b, c, d);
  1298. X  printf ("ARGV: ");
  1299. X  for (i = 0; i < argc; i++)
  1300. X      printf ("<%s> ", argv[i]);
  1301. X}
  1302. X
  1303. X#endif
  1304. X
  1305. END_OF_FILE
  1306. if test 14031 -ne `wc -c <'getargs.cr'`; then
  1307.     echo shar: \"'getargs.cr'\" unpacked with wrong size!
  1308. fi
  1309. # end of 'getargs.cr'
  1310. fi
  1311. echo shar: End of shell archive.
  1312. exit 0
  1313.  
  1314. exit 0 # Just in case...
  1315.