Subject: spider.fixes

From: fubinf!thull (Klaus Thull)
Date: Sat, 3 Nov 90 15:19:31 +0100

These changes made spider operational on several suns, one old
16bitter 68000 pcs cadmus, one 32bittter 68020 same,
the sony news 68030, and the sony risc.
please note that these changes refer to a version that came to me
out of its own accord one day last summer and without bearing an exact date.
please note that there is the issue of awk versions. I constantly
have to take along one awk source to be sure to compile spider.
please note that there is one extension as well: there is a symbolic
printout in weave which has, in the case of knuths pascal-web,
proven very handy.
::::::::::::::
common.ch
::::::::::::::
module 19

@d buf_size = 200 /* for \.{WEAVE} and \.{TANGLE} */
@d long_buf_size = 500 /* for \.{WEAVE} */

module 26

@d max_modules = 2000 /* number of identifiers, strings, module names;
  must be less than 10240 */

de-linting...
@x module 29
@ @<Add path name from {\tt -I} to search path@>=
	pathaddname(*argv+2);
@ @<Other...@>=
@y
@ @<Add path name from {\tt -I} to search path@>=
	pathaddname(*argv+2);
@ @<Other...@>=
extern char* getenv();
@z

de-linting...
@x module 33
@ The included file name should only contain visible ASCII characters,
@y
@ The included file name should only contain visible ASCII characters,
@z

@x
      if ((cur_file=pathopen(cur_file_name,"r"))==NULL) {
@y
      if ((cur_file=pathopen(cur_file_name))==NULL) {
@z

@d max_bytes = 90000 /* the number of bytes in identifiers,
  index entries, and module names */
@d max_names = 4000 /* number of identifiers, strings, module names;
  must be less than 10240 */

module 42

@d hash_size = 353 /* should be prime */

@x module 62
@ Some implementations may wish to pass the |history| value to the
@y
@ Some implementations may wish to pass the |history| value to the
@z

activate stats
@x
  @<Print the job |history|@>;
@y
#ifdef STAT
  print_stats();
#endif
  @<Print the job |history|@>;
@z

de-linting...
@x
fatal("! Usage: tangle webfile[.web] [changefile[.ch]] [-Ipathname ...]\n",0)@;
else
fatal("! Usage: weave webfile[.web] [changefile[.ch]] [-x] [-Ipathname ...]\n",
	0);
@y
fatal("! Usage: tangle webfile[.web] [changefile[.ch]] [-Ipathname ...]\n",
	"")@;
else
fatal("! Usage: weave webfile[.web] [changefile[.ch]] [-x] [-Ipathname ...]\n",
	"");
@z
::::::::::::::
spider.ch
::::::::::::::

escape backslash...
(and put titles right)
#x module 11
#  We write tokens out to two files: |scrapfile| for \.{WEAVE}, and
#y
#  We write tokens out to two files: |scrapfile| for \.{WEAVE}, and
#z

|ttokfile| for \.{TANGLE}.
#<Set init...#>=
	scrapfile = "scraps.web"
#x
	print "@*Scrap code generated by {\tt SPIDER}." > scrapfile
	ttokfile = "outtoks.web"
	print "@*Token code generated by {\tt SPIDER}." > scrapfile
#y
	print "@*Scrap code generated by {\\tt SPIDER}." > scrapfile
	ttokfile = "outtoks.web"
	print "@*Token code generated by {\\tt SPIDER}." > ttokfile
#z

escape backslash...
#x module 16
# We use a special file to write grammar information:
#<Set init...#>=
	grammarfile = "grammar.web"
	print "@*Grammar code generated by {\tt SPIDER}." > grammarfile
#y
# We use a special file to write grammar information:
#<Set init...#>=
	grammarfile = "grammar.web"
	print "@*Grammar code generated by {\\tt SPIDER}." > grammarfile
#z

escape backslash...
#x module 62
# This is how we write out the string or constant scrap, at the end.
#y
# This is how we write out the string or constant scrap, at the end.
#z

#x
	" and \TeX\ strings are identified." > scrapfile
#y
	" and \\TeX\\ strings are identified." > scrapfile
#z

#x module 72
# We use an ugly trick to get the token numbers different for
#y
# We use an ugly trick to get the token numbers different for
#z

#x
			temp = temp + #'37 - highesttoken ## hackety hack!
#y
			temp = temp + #'37  + 3 - highesttoken ## hackety hack!
				## +3 because three highest are already defined!
#z

#x module 126
# It's desirable to put the production in a comment, but we have to
get rid of the confusing \vert, or \.{WEAVE} will think it introduces
code.
#<Remove \vert\ from |inputline[n]| and put results in |this_string|#>=
		this_string = inputline[n]
		tempi = index(this_string,"|")
		while (tempi != 0) {
			tempa = substr(this_string,1,tempi-1)
			tempb = substr(this_string,tempi+1)
			this_string = tempa "\\vert " tempb
			tempi = index(this_string,"|")
			}
#y
# It's desirable to put the production in a comment, but we have to
get rid of the confusing \vert, or \.{WEAVE} will think it introduces
code. And of other things as well\dots
#<Remove \vert\ from |inputline[n]| and put results in |this_string|#>=
		tempb = inputline[n]
		tempa = ""
		tempi = index(tempb,"\\")
		while (tempi != 0) {
			tempa = tempa substr(tempb,1,tempi-1) "\\BS "
			tempb = substr(tempb,tempi+1)
			tempi = index(tempb,"\\")
			}
		this_string = tempa tempb
		tempb = this_string
		tempa = ""
		tempi = index(tempb,"##")
		while (tempi != 0) {
			tempa = tempa substr(tempb,1,tempi-1) "\\##"
			tempb = substr(tempb,tempi+1)
			tempi = index(tempb,"##")
			}
		this_string = tempa tempb
		tempb = this_string
		tempa = ""
		tempi = index(tempb,"$")
		while (tempi != 0) {
			tempa = tempa substr(tempb,1,tempi-1) "\\$"
			tempb = substr(tempb,tempi+1)
			tempi = index(tempb,"$")
			}
		this_string = tempa tempb
		tempb = this_string
		tempa = ""
		tempi = index(tempb,"%")
		while (tempi != 0) {
			tempa = tempa substr(tempb,1,tempi-1) "\\%"
			tempb = substr(tempb,tempi+1)
			tempi = index(tempb,"%")
			}
		this_string = tempa tempb
		tempb = this_string
		tempa = ""
		tempi = index(tempb,"^")
		while (tempi != 0) {
			tempa = tempa substr(tempb,1,tempi-1) "\\^"
			tempb = substr(tempb,tempi+1)
			tempi = index(tempb,"^")
			}
		this_string = tempa tempb
		tempb = this_string
		tempa = ""
		tempi = index(tempb,"@")
		while (tempi != 0) {
			tempa = tempa substr(tempb,1,tempi-1) "\\@@"
			tempb = substr(tempb,tempi+1)
			tempi = index(tempb,"@")
			}
		this_string = tempa tempb
		tempi = index(this_string,"|")
		while (tempi != 0) {
			tempa = substr(this_string,1,tempi-1)
			tempb = substr(this_string,tempi+1)
			this_string = tempa "\\vert " tempb
			tempi = index(this_string,"|")
			}
		tempi = index(this_string,"'")
		while (tempi != 0) {
			tempa = substr(this_string,1,tempi-1)
			tempb = substr(this_string,tempi+1)
			this_string = tempa "\\RQ " tempb
			tempi = index(this_string,"'")
			}
		tempi = index(this_string,"`")
		while (tempi != 0) {
			tempa = substr(this_string,1,tempi-1)
			tempb = substr(this_string,tempi+1)
			this_string = tempa "\\LQ " tempb
			tempi = index(this_string,"`")
			}
		tempi = index(this_string,"{")
		while (tempi != 0) {
			tempa = substr(this_string,1,tempi-1)
			tempb = substr(this_string,tempi+1)
			this_string = tempa "\\LB " tempb
			tempi = index(this_string,"{")
			}
		tempi = index(this_string,"}")
		while (tempi != 0) {
			tempa = substr(this_string,1,tempi-1)
			tempb = substr(this_string,tempi+1)
			this_string = tempa "\\RB " tempb
			tempi = index(this_string,"}")
			}
		tempi = index(this_string,"~")
		while (tempi != 0) {
			tempa = substr(this_string,1,tempi-1)
			tempb = substr(this_string,tempi+1)
			this_string = tempa "\\TL " tempb
			tempi = index(this_string,"~")
			}
		tempi = index(this_string,"_")
		while (tempi != 0) {
			tempa = substr(this_string,1,tempi-1)
			tempb = substr(this_string,tempi+1)
			this_string = tempa "\\UL " tempb
			tempi = index(this_string,"_")
			}
		tempi = index(this_string,"&")
		while (tempi != 0) {
			tempa = substr(this_string,1,tempi-1)
			tempb = substr(this_string,tempi+1)
			this_string = tempa "\\AM " tempb
			tempi = index(this_string,"&")
			}
#z

activate this if year is field no 8

 x module 151
#*1Tracking the generation date.
 y
#*1Tracking the generation date.
 z

 x
	year = $7
 y
	year = $8
 z

::::::::::::::
tangle.ch
::::::::::::::

@ The following parameters were sufficient in the original \.{TANGLE} to
handle \TeX, so they should be sufficient for most applications of \.{TANGLE}.

If you change |max_bytes|, |max_names| or |hash_size| you should also
change them in the file |"common.web"|.

@d max_bytes = 90000 /* the number of bytes in identifiers,
  index entries, and module names; used in |"common.web"| */
@d max_toks = 150000 /* number of bytes in compressed \cee\ code */
@d max_names = 4000 /* number of identifiers, strings, module names;
  must be less than 10240; used in |"common.web"| */
@d max_texts = 2000 /* number of replacement texts, must be less than 10240 */
@d hash_size = 353 /* should be prime; used in |"common.web"| */
@d longest_name = 400 /* module names shouldn't be longer than this */
@d stack_size = 50 /* number of simultaneous levels of macro expansion */
@d buf_size = 100 /* for \.{WEAVE} and \.{TANGLE} */

de-linting...
@x
@ Here's the procedure that decides whether a name of length |l|
starting at position |first| equals the identifier pointed to by |p|:

@u
names_match(p,first,l)
name_pointer p; /* points to the proposed match */
ASCII *first; /* position of first character of string */
int l; /* length of identifier */
@y
@ Here's the procedure that decides whether a name of length |l|
starting at position |first| equals the identifier pointed to by |p|:

@u
names_match(p,first,l,t)
name_pointer p; /* points to the proposed match */
ASCII *first; /* position of first character of string */
int l; /* length of identifier */
eight_bits t; /* which is a dummy but lint complains */
  /* it will still complain \dots */
@z

12-char significance
@x module 110
@ We use macros with zero or more parameters, and we give the parameters names.
@y
@ We use macros with zero or more parameters, and we give the parameters names.
@z

@x
@d max_param_name_texts = 256
@y

Identifier conflict with PCS C\dots

@d param_name_texts_end = p_nm_txts_end
@d next_param_name_text = next_p_nm_txt
@#
@d max_param_name_texts = 256
@z

de-linting
@x
@ This function prints out a decimal constant using |app_repl|.
@u
app_decimal(c)
	int c; /* on entry require |c>=0| */
{int power;
@y
@ This function prints out a decimal constant using |app_repl|.
This casting trick is due to Tim Morgan's WEB-C.

@d app_decimal(x) = zapp_decimal((long)(x))

@u
zapp_decimal(c)
	long c; /* on entry require |c>=0| */
{long power;
@z
::::::::::::::
weave.ch
::::::::::::::

@x module 1
#ifdef STAT
  @<Print statistics about memory usage@>;
#endif STAT
@y
@z

module 2
@ The following parameters were sufficient in the original \.{WEAVE} to
handle \TeX, so they should be sufficient for most applications of \.{CWEAVE}.

@d max_bytes = 90000 /* the number of bytes in identifiers,
  index entries, and module names */
@d max_names = 4000 /* number of identifiers, strings, module names;
  must be less than 10240 */
@d max_modules = 2000 /* greater than the total number of modules */
@d hash_size = 353 /* should be prime */
@d buf_size = 100 /* maximum length of input line, plus one */
@d longest_name = 400 /* module names and strings shouldn't be longer than this */
@d long_buf_size = 500 /* |buf_size+longest_name| */
@d line_length = 80 /* lines of \TeX\ output have at most this many characters;
  should be less than 256 */
@d max_refs = 20000 /* number of cross-references; must be less than 65536 */
@d max_toks = 20000 /* number of symbols in \cee\ texts being parsed;
  must be less than 65536 */
@x
@d max_texts = 2000 /* number of phrases in \cee\ texts being parsed;
  must be less than 10240 */
@d max_scraps = 1000 /* number of tokens in \cee\ texts being parsed */
@y
@d max_texts = 4000 /* number of phrases in \cee\ texts being parsed;
  must be less than 10240 */
@d max_scraps = 4000 /* number of tokens in \cee\ texts being parsed */
@z
@d stack_size = 400 /* number of simultaneous output levels */

@x
/* identifier =200 or octal @'310 */
@y
/* identifier =200 or octal |@'310| */
@z

@x module 57
@ In the \TeX\ part of a module, cross-reference entries are made only for
@y
@ In the \TeX\ part of a module, cross-reference entries are made only for
@z

@x doesn't belong here
#ifdef DEBUG
    case trace: tracing=next_control-'0'; continue;
#endif DEBUG
@y
@z

Print symbolically the entire tree

@x module 87
@ Token lists in |@!tok_mem| are composed of the following kinds of
@y
@ Token lists in |@!tok_mem| are composed of the following kinds of
@z

@u
#ifdef DEBUG
@x
print_text(p) /* prints a token list */
text_pointer p;
@y
print_text(p,ind) /* prints a token list */
text_pointer p;
int ind;
@z
{
  token_pointer j; /* index into |tok_mem| */
  sixteen_bits r; /* remainder of token after the flag has been stripped off */
  if (p>=text_ptr) printf("BAD");
  if (p>=text_ptr) printf("BAD");
  else for (j=*p; j<*(p+1); j++) {
    r=*j%id_flag;
    r=*j%id_flag;
    switch (*j/id_flag) {
      case 1: printf("\\{"); print_id((name_dir+r)); printf("}"); break;
 /* |id_flag| */
      case 2: printf("\&{"); print_id((name_dir+r)); printf("}"); break;
 /* |res_flag| */
      case 3: printf("<"); print_id((name_dir+r)); printf(">"); break;
        /* |mod_flag| */
@x
      case 4: printf("[[%d]]",r); break; /* |tok_flag| */
      case 5: printf("|[[%d]]|",r); break; /* |inner_tok_flag| */
@y
      case 4:  /* we make this a recursive prettyprinting here */
		printf("@@/\n");
		{ int i; for (i=0; i<ind; i++) printf(" "); }
		printf("[[%d:",r);
		print_text(r+tok_start,ind+1);
		printf("]]");
		break; /* |tok_flag| */
      case 5:
		printf("@@/\n");
		{ int i; for (i=0; i<ind; i++) printf(" "); }
		printf("|[[%d:",r);
		print_text(r+tok_start,ind+1);
		printf("]]|");
		break; /* |inner_tok_flag| */
@z
      default: @<Print token |r| in symbolic form@>;
    }
  }
}
#endif DEBUG

@x module 106
@ @<If semi-tracing, show the irreducible scraps@>=
#ifdef DEBUG
@y
@ @<If semi-tracing, show the irreducible scraps@>=
#ifdef DEBUG
  if (tracing==2)
  {
    scrap_pointer k;
    printf("\nafter...\n");
    for (k=scrap_base; k<=lo_ptr; k++)
    { print_cat(k->cat); printf(", %ld:<",(long)(k->trans-tok_start)); 
      print_text(k->trans,0); printf(">");
    }
    new_line;
  }
@z
if (lo_ptr>scrap_base && tracing==1) {
  printf("\nIrreducible scrap sequence in section %d:",module_count);
  mark_harmless;
  for (j=scrap_base; j<=lo_ptr; j++) {
    printf(" "); print_cat(j->cat);
  }
}
#endif DEBUG

@x module 107
@ @<If tracing,...@>=
#ifdef DEBUG
if (tracing==2) {
  printf("\nTracing after l. %d:\n",cur_line); mark_harmless;
  if (loc>buffer+50) {
    printf("...");
    ASCII_write(loc-51,51);
  }
  else ASCII_write(buffer+1,loc-buffer);
}
#endif DEBUG
@y
@ @<If tracing,...@>=
#ifdef DEBUG
if (tracing==2) {
  scrap_pointer k;
  printf("\nTracing after l. %d:\n",cur_line); mark_harmless;
  if (loc>buffer+50) {
    printf("...");
    ASCII_write(loc-51,51);
  }
  else ASCII_write(buffer,loc-buffer);
  printf("\nbefore...\n");
  for (k=scrap_base; k<scrap_ptr; k++)
  { print_cat(k->cat); printf(", %ld:<",(long)(k->trans-tok_start)); 
    print_text(k->trans,0); printf(">\n");
  }
  new_line;
}
#endif DEBUG
@z

@x module 144
@ In the \TeX\ part of a module, we simply copy the source text, except that
@y
@ In the \TeX\ part of a module, we simply copy the source text, except that
@z

@x
    case vertical_bar: /* surround vertical bar with \.{\\CD...\\DC} */
@y
#ifdef DEBUG
    case trace: tracing=*(loc-1)-'0'; continue;
#endif DEBUG
    case vertical_bar: /* surround vertical bar with \.{\\CD...\\DC} */
@z

@x module 262
@ @<Print statistics about memory usage@>=
printf(
"\nMemory usage statistics: %d of %d names, %d of %d cross-references,\n",
  name_ptr-name_dir, name_dir_end-name_dir,
  xref_ptr-xmem, xmem_end-xmem);
printf("\t %d of %d bytes;",byte_ptr-byte_mem,byte_mem_end-byte_mem);
printf("\nParsing required %d of %d(%d) scraps, %d of %d(%d) texts,\n",
  max_scr_ptr-scrap_info, max_scraps, max_scraps-SCRAP_SLACK,
  max_text_ptr-tok_start, max_texts, max_texts-TEXT_SLACK
  );
printf("\t %d of %d(%d) tokens, %d of %d levels;\n",
  max_tok_ptr-tok_mem, max_toks, max_toks-TOK_SLACK,
  max_stack_ptr-stack, stack_end-stack
  );
printf("\nSorting required %d levels\n", max_sort_ptr-scrap_info);
@y
@ @u print_stats() {
#ifdef STAT
printf(
"\nMemory usage statistics: %d of %d names, %d of %d cross-references,\n",
  name_ptr-name_dir, name_dir_end-name_dir,
  xref_ptr-xmem, xmem_end-xmem);
printf("\t %d of %d bytes;",byte_ptr-byte_mem,byte_mem_end-byte_mem);
printf("\nParsing required %d of %d(%d) scraps, %d of %d(%d) texts,\n",
  max_scr_ptr-scrap_info, max_scraps, max_scraps-SCRAP_SLACK,
  max_text_ptr-tok_start, max_texts, max_texts-TEXT_SLACK
  );
printf("\t %d of %d(%d) tokens, %d of %d levels;\n",
  max_tok_ptr-tok_mem, max_toks, max_toks-TOK_SLACK,
  max_stack_ptr-stack, stack_end-stack
  );
printf("\nSorting required %d levels\n", max_sort_ptr-scrap_info);
#endif
}
@z

@x
#ifdef STAT
  @<Print statistics about memory usage@>;
#endif STAT
@y
@z