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

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