% cat newado.mail From seismo!umcp-cs!elsie!ado Sun Sep 23 20:43:29 1984 Received: by decvax.UUCP (4.12/1.0) id AA04152; Sun, 23 Sep 84 20:43:24 edt From: seismo!umcp-cs!elsie!ado Received: from umcp-cs.UUCP by seismo.ARPA with UUCP; Sun, 23 Sep 84 19:01:23 EDT Received: by maryland.ARPA (4.12/4.7) id AA11780; Sun, 23 Sep 84 18:52:09 edt Date: Sun, 23 Sep 84 18:52:09 edt Message-Id: <8409232252.AA11780@maryland.ARPA> To: minow@decvax Subject: A truly pathological bug...and (less kludgy?) line numbering fixes Status: R 1. The truly pathological bug is the treatment of lines like: #include "a /* comment */ b" which tell you about being unable to open file "a b". (I suppose SOME pervert could name a file "a/**/b".) The "fix" to "doinclude": #ifdef OLDVERSION while ((c = get()) != EOF_CHAR && c != '\n' && c != delim) { #if COMMENT_INVISIBLE if (c != COM_SPACE) save(c); #else save(c); #endif } save(EOS); if (c != delim) goto incerr; #else instring = TRUE; while ((c = get()) != delim) if (c == EOF_CHAR || c == '\n') goto incerr; else save(c); save(EOS); instring = FALSE; #endif 2. Here's my latest combination of changes to the last "cpp1.c" you sent that's designed to deal with line numbering. It seems a bit better than my last set to me. First, eliminate newline faking in "addfile": > #ifdef OLDVERSION > file->buffer[0] = '\n'; /* Fake initial newline to */ > file->buffer[1] = EOS; /* initialize for first read */ > line = 0; /* Note correct line number */ > #else > file->buffer[0] = EOS; > line = 1; > #endif Since we no longer put in the phony new line, we avoid diddling "line" in "cppmain": > /* > * Explicitly output a #line at the start of cpp output so > * that lint (etc.) knows the name of the original source > * file. If we don't do this explicitly, we may get > * the name of the first #include file instead. > */ > #ifdef OLDVERSION > line = 1; > sharp(); > line = 0; > #else > sharp(); > #endif We also need not worry about the count being off the first time we do a "sharp" call, so the X #ifdef OLDVERSION X if (counter > 4) /* pending newlines. */ X #else X /* pending newlines. */ X if (line == counter) X --counter; /* Forget addfile's fake '\n' */ X if (counter > 4) X #endif business of my last letter reverts to > if (counter > 4) /* pending newlines. */ Double counting of lines is STILL a problem; the line skipping loop is still: > #ifdef OLDVERSION > for (counter = 0;; counter++) { > #else > counter = 0; > for ( ; ; ) { > #endif > while (type[(c = get())] == SPA) /* Skip leading blanks */ > ; /* in this line. */ > if (c == '\n') /* If line's all blank, */ > #ifdef OLDVERSION > ; /* Do nothing now */ > #else > ++counter; /* just count it */ > #endif > else if (c == '#') /* Is 1st non-space '#' */ > counter = control(counter); /* Yes, do a #command */ > else if (c == EOF_CHAR) /* At end of file? */ > break; > #ifdef OLDVERSION > else if (flevel > 0) /* #ifdef false? */ > skipnl(); /* Skip to newline */ > #else > else if (flevel > 0) { /* #ifdef false? */ > skipnl(); /* Skip to newline */ > ++counter; > } > #endif > else { > break; /* Actual token */ > } > } We also STILL toss in the extra newline in "sharp" when appropriate: > FILE_LOCAL > sharp() > /* > * Output a line number line. > */ > { > register char *name; > > #ifndef OLDVERSION > if (keepcomments) > putchar('\n'); > #endif We still fix the typo in "control": > #ifdef OLDVERSION > if (control > 0 && (hash == L_line || hash == L_option)) { > #else > if (counter > 0 && (hash == L_line || hash == L_option)) { > #endif And finally, we get to make this change in "control", to ensure that the first line of an included file does not disappear: > #if 1 > #ifdef OLDVERSION > skipnl(); /* Dump rest of control line */ > counter++; /* Count it, too. */ > #else > if (hash != L_include) { /* If haven't already eaten line */ > skipnl(); /* Dump rest of control line */ > counter++; /* Count it, too. */ > } > #endif > #else --ado From tektronix!tomk@orca Sun Sep 23 21:54:48 1984 Received: by decvax.UUCP (4.12/1.0) id AA04987; Sun, 23 Sep 84 21:54:43 edt From: tektronix!tomk@orca To: tektronix!decvax!minow Fcc: outbox Return-Path: Received: from orca.TEK by tektronix ; 23 Sep 84 13:33:23 PDT Received: by orca.TEK (1.138/Tek) , id AA03938; Sun, 23 Sep 84 13:33:49 pdt Message-Id: <8409232033.AA03938@orca.TEK> Date: Sun, 23 Sep 84 13:33:41 PDT Subject: DECUS C bugs, etc. Status: R Hi! I just grabbed your cpp submission off the net. Looks like an interesting addition to DECUS C. I totally forgot that you offered to send me a test copy earlier. I discovered a bug in "t" running under RT11 a few months ago. If there's a null character stuck in a line, "t" refuses to print everything after the null. DIR.SAV seems to stick a null at the first of a line when there's only one file in the directory. DIR probably shouldn't stick the null there, but I developed a quick and sleazy fix to "t" to eliminate the bug. Here's the change to "t.h" (Nov'83 version): [input to SLP] -3 * Kloos version of 09-Jun-84 -35 #ifndef rt11 -36 #else #define FWILDMODE "ru" -37 #endif / Do you know of any problems with "sortc" as distributed in the Nov'83 release? When I have less than about 43K of user memory and a big file to sort, it munches the output. Extra characters appear in some places and a few are missing from others. I haven't had the time to dissect the code yet and am hoping that someone else may have fixed it already. Any hints? Are there any updates to the RT-11 version of DECUS C since the last care package I received from you (late May)? Regards, -Tom Kloos, Tektronix, Wilsonville, Oregon Ignore paths in header. Use this: uucp: ..{ucbvax,decvax,uw-beaver,hplabs,allegra}!tektronix!orca!tomk From seismo!umcp-cs!elsie!ado Mon Sep 24 12:26:31 1984 Received: by decvax.UUCP (4.12/1.0) id AA17918; Mon, 24 Sep 84 12:26:24 edt From: seismo!umcp-cs!elsie!ado Received: from umcp-cs.UUCP by seismo.ARPA with UUCP; Mon, 24 Sep 84 12:04:14 EDT Received: by maryland.ARPA (4.12/4.7) id AA26652; Mon, 24 Sep 84 11:37:58 edt Date: Mon, 24 Sep 84 11:37:58 edt Message-Id: <8409241537.AA26652@maryland.ARPA> To: minow@decvax Subject: Re: re: cpp1.c Status: R Got your letter--thanks. Here's a notion--submitted for your approval. It's the code to squelch output of comments that are either 1. on preprocessor directive lines or 2. in conditionally-compiled code that's not being emitted. Fairly straightforward changes, actually: a. Add this at the top of cpp1.c: > int keepcomments = FALSE; /* Write out comments flag */ > #ifndef OLDVERSION > static int cflag = FALSE; /* as per command line */ > #endif b. Add this to "dooptions": > case 'C': /* Keep comments */ > #ifndef OLDVERSION > cflag = TRUE; > #endif > keepcomments = TRUE; > break; > c. And finally, change the call to "docontrol": > else if (c == '#') /* Is 1st non-space '#' */ > #ifdef OLDVERSION > counter = control(counter); /* Yes, do a #command */ > #else > { > keepcomments = FALSE; > counter = control(counter); > keepcomments = cflag && (flevel == 0); > } > #endif Should cut down the computer usage bills of lint users. --ado From seismo!umcp-cs!elsie!ado Mon Sep 24 12:26:51 1984 Received: by decvax.UUCP (4.12/1.0) id AA17925; Mon, 24 Sep 84 12:26:44 edt From: seismo!umcp-cs!elsie!ado Received: from umcp-cs.UUCP by seismo.ARPA with UUCP; Mon, 24 Sep 84 12:04:23 EDT Received: by maryland.ARPA (4.12/4.7) id AA26659; Mon, 24 Sep 84 11:38:08 edt Date: Mon, 24 Sep 84 11:38:08 edt Message-Id: <8409241538.AA26659@maryland.ARPA> To: minow@decvax Subject: Perfect hashing and a warped human mind Status: R Here's a possible replacement for "perfect hashing" in cpp1.c. It makes for both a smaller cpp1.c source file and (at least on our system) a smaller executable cpp. It may also be easier for folks to understand. --ado #ifdef OLDVERSION /* * The following is generated by a "perfect hash" routine. */ #define L_else 4 #define L_line 5 #define L_define 6 #define L_elif 7 #define L_endif 8 #define L_if 9 #define L_undef 10 #define L_include 11 #define L_ifdef 12 #define L_ifndef 13 #define L_assert 14 #define L_option 15 #define FIRST 'a' #define LAST 'u' static int px_assoc[] = { 0, /* 'a' */ -1, /* 'b' */ -1, /* 'c' */ 0, /* 'd' */ 0, /* 'e' */ 3, /* 'f' */ -1, /* 'g' */ -1, /* 'h' */ 4, /* 'i' */ -1, /* 'j' */ -1, /* 'k' */ 1, /* 'l' */ -1, /* 'm' */ 9, /* 'n' */ 0, /* 'o' */ -1, /* 'p' */ -1, /* 'q' */ -1, /* 'r' */ -1, /* 's' */ 8, /* 't' */ 2, /* 'u' */ }; static char *px_table[] = { NULL, /* 0 */ NULL, /* 1 */ NULL, /* 2 */ NULL, /* 3 */ "else", /* 4 */ "line", /* 5 */ "define", /* 6 */ "elif", /* 7 */ "endif", /* 8 */ "if", /* 9 */ "undef", /* 10 */ "include", /* 11 */ "ifdef", /* 12 */ "ifndef", /* 13 */ "assert", /* 14 */ "option", /* 15 */ }; FILE_LOCAL int control(counter) int counter; /* Pending newline counter */ /* * Process #control lines. Simple commands are processed inline, * while complex commands have their own subroutines. * * The counter is used to force out a newline before #line, and * #option commands. This prevents these commands from ending up at * the end of the previous line if cpp is invoked with the -C option. */ { register int c; register char *tp; register int hash; char *ep; c = skipws(); if (c == '\n' || c == EOF_CHAR) return (counter + 1); if (!isdigit(c)) scanid(c); /* Get #word to token[] */ else { unget(); /* Hack -- allow #123 as a */ strcpy(token, "line"); /* synonym for #line 123 */ } /* * Look for keyword (string of alpha) in the perfect hash table. * Set hash to the index (L_xxx value) or 0 if not found */ if (token[0] < FIRST || token[0] > LAST) hash = 0; else { for (tp = token; isalpha(*tp); tp++) ; hash = (tp - token); if (*--tp < FIRST || *tp > LAST) hash = 0; else { hash += px_assoc[*token - FIRST] + px_assoc[*tp - FIRST]; if (px_table[hash] == NULL || !streq(token, px_table[hash])) hash = 0; } } /* * hash is now set to a unique value corresponding to the * control keyword (or zero if it's not in the table). */ #else /* * The following is generated by human perverseness. */ #define L_else ('e' + ('s' << 1)) #define L_line ('l' + ('n' << 1)) #define L_define ('d' + ('f' << 1)) #define L_elif ('e' + ('i' << 1)) #define L_endif ('e' + ('d' << 1)) #define L_if ('i' + (EOS << 1)) #define L_undef ('u' + ('d' << 1)) #define L_include ('i' + ('c' << 1)) #define L_ifdef ('i' + ('d' << 1)) #define L_ifndef ('i' + ('n' << 1)) #define L_assert ('a' + ('s' << 1)) #define L_option ('o' + ('t' << 1)) FILE_LOCAL int control(counter) int counter; /* Pending newline counter */ /* * Process #control lines. Simple commands are processed inline, * while complex commands have their own subroutines. * * The counter is used to force out a newline before #line, and * #option commands. This prevents these commands from ending up at * the end of the previous line if cpp is invoked with the -C option. */ { register int c; register char *tp; register int hash; char *ep; c = skipws(); if (c == '\n' || c == EOF_CHAR) return (counter + 1); if (!isdigit(c)) scanid(c); /* Get #word to token[] */ else { unget(); /* Hack -- allow #123 as a */ strcpy(token, "line"); /* synonym for #line 123 */ } switch (hash = token[0] + (token[2] << 1)) { case L_else: tp = "else"; break; case L_line: tp = "line"; break; case L_define: tp = "define"; break; case L_elif: tp = "elif"; break; case L_endif: tp = "endif"; break; case L_if: tp = "if"; break; case L_undef: tp = "undef"; break; case L_include: tp = "include"; break; case L_ifdef: tp = "ifdef"; break; case L_ifndef: tp = "ifndef"; break; case L_assert: tp = "assert"; break; case L_option: tp = "option"; break; default: tp = ""; hash = 0; break; } if (!streq(tp, token)) hash = 0; /* * hash is now set to a unique value corresponding to the * control keyword (or zero if we think it's nonsense). */ #endif --ado From seismo!umcp-cs!elsie!ado Tue Sep 25 14:27:42 1984 Received: by decvax.UUCP (4.12/1.0) id AA13453; Tue, 25 Sep 84 14:27:38 edt From: seismo!umcp-cs!elsie!ado Received: from umcp-cs.UUCP by seismo.ARPA with UUCP; Tue, 25 Sep 84 13:03:08 EDT Received: by maryland.ARPA (4.12/4.7) id AA13754; Tue, 25 Sep 84 12:27:47 edt Date: Tue, 25 Sep 84 12:27:47 edt Message-Id: <8409251627.AA13754@maryland.ARPA> To: minow@decvax Subject: cpp.h addition Status: R Appending a extern char *sprintf(); lint to "cpp.h" saves a bit of "lint" grief. --ado From seismo!cmcl2!hipl!tony Fri Sep 28 03:19:55 1984 Received: by decvax.UUCP (4.12/1.0) id AA15286; Fri, 28 Sep 84 03:19:30 edt Received: from cmcl2.UUCP by seismo.ARPA with UUCP; Thu, 27 Sep 84 20:51:40 EDT Received: by NYU-CMCL2.ARPA; Thu, 27 Sep 84 19:06:13 edt Received: by hipl.UUCP (4.12/4.7) id AA01328; Thu, 27 Sep 84 18:28:22 edt Date: Thu, 27 Sep 84 18:28:22 edt From: seismo!cmcl2!hipl!tony (Tony Movshon) Message-Id: <8409272228.AA01328@hipl.UUCP> To: minow@decvax Subject: cpp Status: R I retrieved cpp from net.sources and have installed it under RT11. I have not tested it exhaustively, but it appears to work fine. One minor point: in cppdef.h, you have it define HOST as SYS_RSX even if the compiler predefines "rt11" (this was presumably for testing). It would be more humane to have it define HOST as SYS_RT11. You mentioned some bug-fixes affecting RT11 that you installed since the last DECUS release: could you send them to me for my planned RT11 resubmission? %