[comp.sources.bugs] sc 6.1 - Allow ANSI pre-processor and read-only strings

cudcv@warwick.ac.uk (Rob McMahon) (04/02/89)

There are two problems with compiling sc with an ANSI compiler such as gcc.
The first is the ctl macro relies on a non-ANSI pre-processor which will do
replacement of macro arguments within strings, this will stop it compiling at
all.  The second is that it tries to write to strings constants, which may be
in read-only memory, so that it dumps core as soon as you try to run it.
These patches fix both of these problems, most of the patches are for the ctl
macro, the first two of the patches to sc.c are for read-only strings.

RCS file: cmds.c,v
retrieving revision 1.1
diff -c -r1.1 cmds.c
*** /tmp/,RCSt1a12449	Sat Apr  1 20:34:58 1989
--- cmds.c	Sat Apr  1 18:04:10 1989
***************
*** 319,337 ****
  	case 'r':
  	case 'l':
  	case 'h':
! 	case ctl(f):
! 	case ctl(b):	return ('r');
  
  	case 'c':
  	case 'j':
  	case 'k':
! 	case ctl(p):
! 	case ctl(n):	return ('c');
  
  	case 'm':	return ((ch == 'p') ? 'm' : 0);
  
  	case ESC:
! 	case ctl (g):	return (ESC);
  
  	default:	return (0);
      }
--- 319,337 ----
  	case 'r':
  	case 'l':
  	case 'h':
! 	case ctl('f'):
! 	case ctl('b'):	return ('r');
  
  	case 'c':
  	case 'j':
  	case 'k':
! 	case ctl('p'):
! 	case ctl('n'):	return ('c');
  
  	case 'm':	return ((ch == 'p') ? 'm' : 0);
  
  	case ESC:
! 	case ctl('g'):	return (ESC);
  
  	default:	return (0);
      }
===================================================================
RCS file: lex.c,v
retrieving revision 1.1
diff -c -r1.1 lex.c
*** /tmp/,RCSt1a12449	Sat Apr  1 20:35:05 1989
--- lex.c	Sat Apr  1 18:04:15 1989
***************
*** 65,71 ****
  #include "statres.h"
      0, 0};
  
! #define ctl(x) ('x'&037)
  
  yylex ()
  {
--- 65,71 ----
  #include "statres.h"
      0, 0};
  
! #define ctl(x) ((x)&037)
  
  yylex ()
  {
***************
*** 255,264 ****
         c = getchar();
  
      switch (c) {
!     case SMG$K_TRM_LEFT:  c = ctl(b); break;
!     case SMG$K_TRM_RIGHT: c = ctl(f); break;
!     case SMG$K_TRM_UP:    c = ctl(p); break;
!     case SMG$K_TRM_DOWN:  c = ctl(n); break;
      default:   c = c & 0x7f;
      }
      return (c);
--- 255,264 ----
         c = getchar();
  
      switch (c) {
!     case SMG$K_TRM_LEFT:  c = ctl('b'); break;
!     case SMG$K_TRM_RIGHT: c = ctl('f'); break;
!     case SMG$K_TRM_UP:    c = ctl('p'); break;
!     case SMG$K_TRM_DOWN:  c = ctl('n'); break;
      default:   c = c & 0x7f;
      }
      return (c);
***************
*** 320,328 ****
  #endif
  
  char dont_use[] = {
!     ctl(z), ctl(r), ctl(l), ctl(b), ctl(c), ctl(f), ctl(g), ctl([),
!     ctl(h), ctl(m), ctl(j), ctl(n), ctl(p), ctl(q), ctl(s), ctl(t),
!     ctl(u), ctl(v), ctl(e), ctl(a), ctl(i), ctl(w), 0,
  };
  
  charout(c)
--- 320,329 ----
  #endif
  
  char dont_use[] = {
!     ctl('z'), ctl('r'), ctl('l'), ctl('b'), ctl('c'), ctl('f'), ctl('g'),
!     ctl('['), ctl('h'), ctl('m'), ctl('j'), ctl('n'), ctl('p'), ctl('q'),
!     ctl('s'), ctl('t'), ctl('u'), ctl('v'), ctl('e'), ctl('a'), ctl('i'),
!     ctl('w'), 0,
  };
  
  charout(c)
***************
*** 342,351 ****
      if (tgetent(buf, getenv("TERM")) <= 0)
  	return;
  
!     km[0].k_str = tgetstr("kl", &p); km[0].k_val = ctl(b);
!     km[1].k_str = tgetstr("kr", &p); km[1].k_val = ctl(f);
!     km[2].k_str = tgetstr("ku", &p); km[2].k_val = ctl(p);
!     km[3].k_str = tgetstr("kd", &p); km[3].k_val = ctl(n);
      ktmp = tgetstr("ks",&p);
      if (ktmp)  {
  	(void) strcpy(ks_buf, ktmp);
--- 343,352 ----
      if (tgetent(buf, getenv("TERM")) <= 0)
  	return;
  
!     km[0].k_str = tgetstr("kl", &p); km[0].k_val = ctl('b');
!     km[1].k_str = tgetstr("kr", &p); km[1].k_val = ctl('f');
!     km[2].k_str = tgetstr("ku", &p); km[2].k_val = ctl('p');
!     km[3].k_str = tgetstr("kd", &p); km[3].k_val = ctl('n');
      ktmp = tgetstr("ks",&p);
      if (ktmp)  {
  	(void) strcpy(ks_buf, ktmp);
***************
*** 375,383 ****
  #ifdef TIOCSLTC
      (void)ioctl(fileno(stdin), TIOCGLTC, (char *)&old_chars);
      new_chars = old_chars;
!     if (old_chars.t_lnextc == ctl(v))
  	new_chars.t_lnextc = -1;
!     if (old_chars.t_rprntc == ctl(r))
  	new_chars.t_rprntc = -1;
      (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&new_chars);
  #endif
--- 376,384 ----
  #ifdef TIOCSLTC
      (void)ioctl(fileno(stdin), TIOCGLTC, (char *)&old_chars);
      new_chars = old_chars;
!     if (old_chars.t_lnextc == ctl('v'))
  	new_chars.t_lnextc = -1;
!     if (old_chars.t_rprntc == ctl('r'))
  	new_chars.t_rprntc = -1;
      (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&new_chars);
  #endif
***************
*** 502,511 ****
  
      c = getch();
      switch (c) {
!     case KEY_LEFT:  c = ctl(b); break;
!     case KEY_RIGHT: c = ctl(f); break;
!     case KEY_UP:    c = ctl(p); break;
!     case KEY_DOWN:  c = ctl(n); break;
  #ifdef KEY_C1
  /* This stuff works for a wyse wy75 in ANSI mode under 5.3.  Good luck. */
  /* It is supposed to map the curses keypad back to the numeric equiv. */
--- 503,512 ----
  
      c = getch();
      switch (c) {
!     case KEY_LEFT:  c = ctl('b'); break;
!     case KEY_RIGHT: c = ctl('f'); break;
!     case KEY_UP:    c = ctl('p'); break;
!     case KEY_DOWN:  c = ctl('n'); break;
  #ifdef KEY_C1
  /* This stuff works for a wyse wy75 in ANSI mode under 5.3.  Good luck. */
  /* It is supposed to map the curses keypad back to the numeric equiv. */
***************
*** 520,526 ****
      case KEY_F(10): c = '8'; break;
      case KEY_F0:    c = '9'; break;
      case KEY_C3:    c = '.'; break;
!     case KEY_ENTER: c = ctl(m); break;
  #endif
  #ifndef INTERNATIONAL
      default:   c = c & 0x7f; 
--- 521,527 ----
      case KEY_F(10): c = '8'; break;
      case KEY_F0:    c = '9'; break;
      case KEY_C3:    c = '.'; break;
!     case KEY_ENTER: c = ctl('m'); break;
  #endif
  #ifndef INTERNATIONAL
      default:   c = c & 0x7f; 
===================================================================
RCS file: sc.c,v
retrieving revision 1.1
diff -c -r1.1 sc.c
*** /tmp/,RCSt1a12449	Sat Apr  1 20:35:11 1989
--- sc.c	Sat Apr  1 20:26:43 1989
***************
*** 82,88 ****
  
  int  lastmx, lastmy;	/* Screen address of the cursor */
  int  lastcol;		/* Spreadsheet Column the cursor was in last */
! char *under_cursor = " "; /* Data under the < cursor */
  
  #ifdef VMS
  int VMS_read_raw = 0;
--- 82,88 ----
  
  int  lastmx, lastmy;	/* Screen address of the cursor */
  int  lastcol;		/* Spreadsheet Column the cursor was in last */
! char under_cursor[] = " "; /* Data under the < cursor */
  
  #ifdef VMS
  int VMS_read_raw = 0;
***************
*** 514,522 ****
  repaint(x, y, len)
  int x, y, len;
  {
!     char *buf;
  
!     buf = " ";
  
      while(len-- > 0) {
  	(void) move(y,x);
--- 514,522 ----
  repaint(x, y, len)
  int x, y, len;
  {
!     char buf[2];
  
!     buf[1] = '\0';
  
      while(len-- > 0) {
  	(void) move(y,x);
***************
*** 659,665 ****
  	if ((c < ' ') || ( c == DEL ))
  	    switch (c) {
  #ifdef SIGTSTP
! 		case ctl (z):
  		    deraw();
  		    (void) kill(getpid(),SIGTSTP);
  
--- 659,665 ----
  	if ((c < ' ') || ( c == DEL ))
  	    switch (c) {
  #ifdef SIGTSTP
! 		case ctl('z'):
  		    deraw();
  		    (void) kill(getpid(),SIGTSTP);
  
***************
*** 668,681 ****
  		    goraw();
  		    break;
  #endif
! 		case ctl (r):
! 		case ctl (l):
  		    FullUpdate++;
! 		    if (c == ctl (r))
  			showneed = 1;
  		    (void) clearok(stdscr,1);
  		    break;
! 		case ctl (x):
  		    FullUpdate++;
  		    showexpr = 1;
  		    (void) clearok(stdscr,1);
--- 668,681 ----
  		    goraw();
  		    break;
  #endif
! 		case ctl('r'):
! 		case ctl('l'):
  		    FullUpdate++;
! 		    if (c == ctl('r'))
  			showneed = 1;
  		    (void) clearok(stdscr,1);
  		    break;
! 		case ctl('x'):
  		    FullUpdate++;
  		    showexpr = 1;
  		    (void) clearok(stdscr,1);
***************
*** 683,707 ****
  		default:
  		    error ("No such command (^%c)", c + 0100);
  		    break;
! 		case ctl (b):
  		    backcol(arg);
  		    break;
! 		case ctl (c):
  		    running = 0;
  		    break;
  
! 		case ctl (e):
  
  		    switch (nmgetch()) {
! 		    case ctl (p): case 'k':	doend (-1, 0);	break;
! 		    case ctl (n): case 'j':	doend ( 1, 0);	break;
! 		    case ctl (b): case 'h':
! 		    case ctl (h):		doend ( 0,-1);	break;
! 		    case ctl (f): case 'l':
! 		    case ctl (i): case ' ':	doend ( 0, 1);	break;
  
  		    case ESC:
! 		    case ctl (g):
  			break;
  
  		    default:
--- 683,707 ----
  		default:
  		    error ("No such command (^%c)", c + 0100);
  		    break;
! 		case ctl('b'):
  		    backcol(arg);
  		    break;
! 		case ctl('c'):
  		    running = 0;
  		    break;
  
! 		case ctl('e'):
  
  		    switch (nmgetch()) {
! 		    case ctl('p'): case 'k':	doend (-1, 0);	break;
! 		    case ctl('n'): case 'j':	doend ( 1, 0);	break;
! 		    case ctl('b'): case 'h':
! 		    case ctl('h'):		doend ( 0,-1);	break;
! 		    case ctl('f'): case 'l':
! 		    case ctl('i'): case ' ':	doend ( 0, 1);	break;
  
  		    case ESC:
! 		    case ctl('g'):
  			break;
  
  		    default:
***************
*** 711,721 ****
  
  		    break;
  
! 		case ctl (f):
  		    forwcol(arg);
  		    break;
! 		case ctl (g):
! 		case ESC:	/* ctl ([) */
  		    showrange = 0;
  		    linelim = -1;
  		    (void) move (1, 0);
--- 711,721 ----
  
  		    break;
  
! 		case ctl('f'):
  		    forwcol(arg);
  		    break;
! 		case ctl('g'):
! 		case ESC:	/* ctl('[') */
  		    showrange = 0;
  		    linelim = -1;
  		    (void) move (1, 0);
***************
*** 722,728 ****
  		    (void) clrtoeol ();
  		    break;
  		case DEL:
! 		case ctl (h):
  		    if (linelim <= 0) {	/* not editing line */
  			backcol(arg);	/* treat like ^B    */
  			break;
--- 722,728 ----
  		    (void) clrtoeol ();
  		    break;
  		case DEL:
! 		case ctl('h'):
  		    if (linelim <= 0) {	/* not editing line */
  			backcol(arg);	/* treat like ^B    */
  			break;
***************
*** 730,736 ****
  		    while (--arg>=0) if (linelim > 0)
  			line[--linelim] = 0;
  		    break;
! 		case ctl (i): 		/* tab */
  		    if (linelim <= 0) {	/* not editing line */
  			forwcol(arg);
  			break;
--- 730,736 ----
  		    while (--arg>=0) if (linelim > 0)
  			line[--linelim] = 0;
  		    break;
! 		case ctl('i'): 		/* tab */
  		    if (linelim <= 0) {	/* not editing line */
  			forwcol(arg);
  			break;
***************
*** 747,754 ****
  		    }
  		    linelim = strlen (line);
  		    break;
! 		case ctl (m):
! 		case ctl (j):
  		    showrange = 0;
  		    if (linelim < 0)
  			line[linelim = 0] = 0;
--- 747,754 ----
  		    }
  		    linelim = strlen (line);
  		    break;
! 		case ctl('m'):
! 		case ctl('j'):
  		    showrange = 0;
  		    if (linelim < 0)
  			line[linelim = 0] = 0;
***************
*** 758,774 ****
  			linelim = -1;
  		    }
  		    break;
! 		case ctl (n):
  		    forwrow(arg);
  		    break;
! 		case ctl (p):
  		    backrow(arg);
  		    break;
! 		case ctl (q):
  		    break;	/* ignore flow control */
! 		case ctl (s):
  		    break;	/* ignore flow control */
! 		case ctl (t):
  		    error(
  "Toggle:  a:auto  c:cell  e:ext funcs  n:numeric  t:top  x:encrypt  $:pre-scale");
  		    (void) refresh();
--- 758,774 ----
  			linelim = -1;
  		    }
  		    break;
! 		case ctl('n'):
  		    forwrow(arg);
  		    break;
! 		case ctl('p'):
  		    backrow(arg);
  		    break;
! 		case ctl('q'):
  		    break;	/* ignore flow control */
! 		case ctl('s'):
  		    break;	/* ignore flow control */
! 		case ctl('t'):
  		    error(
  "Toggle:  a:auto  c:cell  e:ext funcs  n:numeric  t:top  x:encrypt  $:pre-scale");
  		    (void) refresh();
***************
*** 815,821 ****
  				    extfunc? "en" : "dis");
  			    break;
  			case ESC:
! 			case ctl (g):
  			    break;
  			default:
  			    error ("Invalid toggle command");
--- 815,821 ----
  				    extfunc? "en" : "dis");
  			    break;
  			case ESC:
! 			case ctl('g'):
  			    break;
  			default:
  			    error ("Invalid toggle command");
***************
*** 823,842 ****
  		    FullUpdate++;
  		    modflg++;
  		    break;
! 		case ctl (u):
  		    narg = arg * 4;
  		    nedistate = 1;
  		    break;
! 		case ctl (v):	/* insert variable name */
  		    if (linelim > 0) {
  		    (void) sprintf (line+linelim,"%s", v_name(currow, curcol));
  			linelim = strlen (line);
  		    }
  		    break;
! 		case ctl (w):	/* insert variable expression */
  		    if (linelim > 0) editexp(currow,curcol);
  		    break;
! 		case ctl (a):	/* insert variable value */
  		    if (linelim > 0) {
  			struct ent *p = tbl[currow][curcol];
  
--- 823,842 ----
  		    FullUpdate++;
  		    modflg++;
  		    break;
! 		case ctl('u'):
  		    narg = arg * 4;
  		    nedistate = 1;
  		    break;
! 		case ctl('v'):	/* insert variable name */
  		    if (linelim > 0) {
  		    (void) sprintf (line+linelim,"%s", v_name(currow, curcol));
  			linelim = strlen (line);
  		    }
  		    break;
! 		case ctl('w'):	/* insert variable expression */
  		    if (linelim > 0) editexp(currow,curcol);
  		    break;
! 		case ctl('a'):	/* insert variable value */
  		    if (linelim > 0) {
  			struct ent *p = tbl[currow][curcol];
  
***************
*** 1033,1039 ****
  				break;
  				
  			    case ESC:
! 			    case ctl (g):
  				break;
  			   default:
  				error("Invalid region command");
--- 1033,1039 ----
  				break;
  				
  			    case ESC:
! 			    case ctl('g'):
  				break;
  			   default:
  				error("Invalid region command");
***************
*** 1062,1068 ****
  
  				error ("");	/* clear line */
  
! 				if ( rcqual == ESC || rcqual == ctl(g))
  				    break;
  
  				switch (c) {
--- 1062,1068 ----
  
  				error ("");	/* clear line */
  
! 				if ( rcqual == ESC || rcqual == ctl('g'))
  				    break;
  
  				switch (c) {
***************
*** 1474,1480 ****
   	if (ch != 'n' && ch != 'N') {
   	    if (writefile(curfile, 0, 0, maxrow, maxcol) < 0)
   		return (1);
! 	} else if (ch == ctl (g) || ch == ESC) return(1);
      } else if (modflg) {
  	char ch, lin[100];
  
--- 1474,1480 ----
   	if (ch != 'n' && ch != 'N') {
   	    if (writefile(curfile, 0, 0, maxrow, maxcol) < 0)
   		return (1);
! 	} else if (ch == ctl('g') || ch == ESC) return(1);
      } else if (modflg) {
  	char ch, lin[100];
  
===================================================================
RCS file: sc.h,v
retrieving revision 1.1
diff -c -r1.1 sc.h
*** /tmp/,RCSt1a12449	Sat Apr  1 20:35:19 1989
--- sc.h	Sat Apr  1 18:04:28 1989
***************
*** 138,144 ****
  #define is_leftflush 0010
  #define is_deleted   0020
  
! #define ctl(c) ('c'&037)
  #define ESC 033
  #define DEL 0177
  
--- 138,144 ----
  #define is_leftflush 0010
  #define is_deleted   0020
  
! #define ctl(c) ((c)&037)
  #define ESC 033
  #define DEL 0177
  

Rob
-- 
UUCP:   ...!mcvax!ukc!warwick!cudcv	PHONE:  +44 203 523037
JANET:  cudcv@uk.ac.warwick             ARPA:   cudcv@warwick.ac.uk
Rob McMahon, Computing Services, Warwick University, Coventry CV4 7AL, England

koblas@mips.COM (David Koblas) (04/03/89)

In article <137@titania.warwick.ac.uk> cudcv@warwick.ac.uk (Rob McMahon) writes:
>  
>! #define ctl(x) ('x'&037)
>  
>--- 65,71 ----
>  
>! #define ctl(x) ((x)&037)
>  

Instead of doing this change there is a much simpler solution, which
of course allows you to not make such a huge change to existing code.

#ifdef __STDC___
# define ctl(x)	(#x[0]&037)
#else
# define ctl(x) ('x'&037)
#endif


-- 
name : David Koblas                  uucp  : {ames,decwrl}!mips!koblas 
place: MIPS Computers Systems        domain: koblas@mips.com
quote: "It was never ment to be a game, NEVER." -- Rollerball

john@frog.UUCP (John Woods) (04/04/89)

In article <16445@yoyodyne.mips.COM>, koblas@mips.COM (David Koblas) writes:
> In article <137@titania.warwick.ac.uk> cudcv@warwick.ac.uk (Rob McMahon) writes:
> >! #define ctl(x) ('x'&037)
> >--- 65,71 ----
> >! #define ctl(x) ((x)&037)
> 
> Instead of doing this change there is a much simpler solution, which
> of course allows you to not make such a huge change to existing code.
> 
> #ifdef __STDC___
> # define ctl(x)	(#x[0]&037)
> #else
> # define ctl(x) ('x'&037)
> #endif
> 
However, this solution does not handle the case of non-ANSI compilers which
do not have the undocumented Reiser CPP features.  The first solution is
correct for Classic C as documented in "The Old Testament" (K&R I), and for
all existing (correct) C compilers, Reiserish or not.



-- 
John Woods, Charles River Data Systems, Framingham MA, (508) 626-1101
...!decvax!frog!john, john@frog.UUCP, ...!mit-eddie!jfw, jfw@eddie.mit.edu

			Remainder Khomeini!

rgb@sequent.UUCP (Bob Bond) (04/04/89)

With regards to the SC 6.1 release:
From article <137@titania.warwick.ac.uk>, by cudcv@warwick.ac.uk (Rob McMahon):
> The first [problem] is the ctl macro relies on a non-ANSI
> pre-processor which will do replacement of macro arguments within
> strings, this will stop it compiling at all.

This release has been interesting from this perspective.  The ctl()
macro has been "shipping" like this for 3+ years and I have never had a
complaint before now.  I have received at least 5 separate complaints
since the 6.1 release last month.  I draw a couple of conclusions - gcc
is a real force in the market and ANSI is breaking some things they
should have standarized.

I will fix this in the next release.   If I get enough other bug
reports and I have the time (not likely before May), I may send out a
patch.  

> The second is that it tries to write to strings constants, which may be
> in read-only memory, so that it dumps core as soon as you try to run it.

Who said compilers could put strings somewhere other than data space?  :-)

						Bob

bill@twwells.uucp (T. William Wells) (04/04/89)

In article <16445@yoyodyne.mips.COM> koblas@mips.COM (David Koblas) writes:
: In article <137@titania.warwick.ac.uk> cudcv@warwick.ac.uk (Rob McMahon) writes:
: >
: >! #define ctl(x) ('x'&037)
: >
: >--- 65,71 ----
: >
: >! #define ctl(x) ((x)&037)
: >
:
: Instead of doing this change there is a much simpler solution, which
: of course allows you to not make such a huge change to existing code.
:
: #ifdef __STDC___
: # define ctl(x)       (#x[0]&037)
: #else
: # define ctl(x) ('x'&037)
: #endif

What makes you think that it is only ANSI that doesn't allow the 'x'
to be expanded? Well, here's some news: there are comparatively few
compilers that will expand the 'x'. Most don't. ANSI is merely
formalizing this situation.

Also, I wouldn't use your suggestion for ANSI: unless you have a
smart compiler writer, that is likely to generate allocated memory
for the string even though the string is never used.

---
Bill                            { uunet | novavax } !twwells!bill
(BTW, I'm may be looking for a new job sometime in the next few
months.  If you know of a good one where I can be based in South
Florida do send me e-mail.)

tkacik@rphroy.UUCP (Tom Tkacik) (04/06/89)

In article <13774@sequent.UUCP> rgb@sequent.UUCP (Bob Bond) writes:
>With regards to the SC 6.1 release:
>From article <137@titania.warwick.ac.uk>, by cudcv@warwick.ac.uk (Rob McMahon):
>> The first [problem] is the ctl macro relies on a non-ANSI
>> pre-processor which will do replacement of macro arguments within
>> strings, this will stop it compiling at all.
>
>This release has been interesting from this perspective.  The ctl()
>macro has been "shipping" like this for 3+ years and I have never had a
>complaint before now.  I have received at least 5 separate complaints
>since the 6.1 release last month.  I draw a couple of conclusions - gcc
>is a real force in the market and ANSI is breaking some things they
>should have standarized.

Or at least GCC is making people aware of the differences between
K&R C and ANSI C.  They show up more frequently than most people believe.
I do not think that ANSI is breaking things they should have standardized,
but that perhaps there were some bad (less than desirable:-)) coding
practices that have become standard because early compilers (and preprocessors)
allowed them.  It is a good idea to try and break these practices
rather than formally standardize them.

>
>> The second is that it tries to write to strings constants, which may be
>> in read-only memory, so that it dumps core as soon as you try to run it.
>
>Who said compilers could put strings somewhere other than data space?  :-)

The pANS says that string constants can be put in text space.
I believe that this was so that strings constants could be shared, and that
they could also be put in ROM.  Current K&R C does not allow this.

To compile SC 6.1 with gcc use
   gcc -traditional -fwritable-strings

These are the two most common cases of pANS C being different from K&R C.

It seems that ANSI C is getting close enough that old code should be looked
at to see if it can be made to conform to both.
For example, the ctl() macro should be made to take its argument already a
character literal, (ie.  ctl('x') instead of ctl(x) ).
This will work with both K&R and ANSI C.

Other differences are not so easy, like string concatenation which is done
in incompatable ways.  But that which can be made to conform should.

---
Tom Tkacik
GM Research Labs,   Warren MI  48090
uunet!edsews!rphroy!megatron!tkacik