From 8beb83454679b80f349b0bfc9fccc2d4b082cfc1 Mon Sep 17 00:00:00 2001 From: Andreas Scherer Date: Sun, 6 Jun 2021 10:46:19 +0200 Subject: [PATCH] CWEB - release 4.4, 2021-06-06. This is a service release for CWEB 4.3: * All buffer sizes were reset to their original values from CWEB 3.64c. * A few old and new (typographical) bugs were fixed. * Tons of minutiae were addressed in 'fullmanual' --- Makefile | 10 +- README.md | 4 +- comm-mac.ch | 4 +- comm-pc.ch | 2 +- comm-ql.ch | 18 +-- common.c | 193 +++++++++++++-------------- common.h | 24 ++-- common.w | 31 ++--- ctang-bs.ch | 63 +++------ ctang-pc.ch | 15 ++- ctang-ql.ch | 8 +- ctang-vms.ch | 4 +- ctang-w32.ch | 4 +- ctangle.c | 322 +++++++++++++++++++++++---------------------- ctangle.w | 146 ++++++++++----------- cweav-bs.ch | 8 +- cweav-man.ch | 2 +- cweav-pc.ch | 8 +- cweav-ql.ch | 8 +- cweav-vms.ch | 4 +- cweav-w32.ch | 4 +- cweave.w | 359 ++++++++++++++++++++++++--------------------------- cwebmac.tex | 8 +- cwebman.tex | 31 ++--- prod.w | 6 +- 25 files changed, 607 insertions(+), 679 deletions(-) diff --git a/Makefile b/Makefile index 5859421..85986b6 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # This file is part of CWEB. # It is distributed WITHOUT ANY WARRANTY, express or implied. -# Version 4.3 --- May 2021 +# Version 4.4 --- June 2021 # Copyright (C) 1987,1990,1993,2000 Silvio Levy and Donald E. Knuth @@ -149,16 +149,16 @@ cweave.c: cweave.w $(WCHANGES) common.h prod.w doc: $(SOURCES:.w=.dvi) usermanual: cwebman.tex cwebmac.tex - tex cwebman + $(PDF)tex cwebman fullmanual: usermanual $(SOURCES) comm-man.ch ctang-man.ch cweav-man.ch make cweave ./cweave common.w comm-man.ch - tex common.tex + $(PDF)tex common.tex ./cweave ctangle.w ctang-man.ch - tex ctangle.tex + $(PDF)tex ctangle.tex ./cweave cweave.w cweav-man.ch - tex cweave.tex + $(PDF)tex cweave.tex # be sure to leave ctangle.c and common.c for bootstrapping clean: diff --git a/README.md b/README.md index fa56c6e..d62c1fc 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# cweb 4.3 +# cweb 4.4 people have been accumulating several decades of experience with [cweb](http://www-cs-faculty.stanford.edu/~uno/cweb.html), and we know that @@ -19,7 +19,7 @@ details in the besides for further development, this ‘project’ is used as an – obviously incomplete – repository of original release versions of levy/knuth [cweb](http://www-cs-faculty.stanford.edu/~uno/cweb.html). you can either -compile these sources directly or stick the recent version “cweb-4.3” into my +compile these sources directly or stick the recent version “cweb-4.4” into my [cwebbin](https://github.com/ascherer/cwebbin), which introduces convenient extensions and prepares cweb for inclusion in the “tex live” distribution. diff --git a/comm-mac.ch b/comm-mac.ch index 895566d..aa67bf6 100644 --- a/comm-mac.ch +++ b/comm-mac.ch @@ -4,9 +4,9 @@ No changes to CTANGLE or CWEAVE are needed. (Contributed 13 Oct 2000 by AndPio@aol.com; slightly edited by Don Knuth) @x in limbo, change the title page document to specify Mac version - \centerline{(Version 4.3)} + \centerline{(Version 4.4)} @y - \centerline{(Version 4.3 for MacOS)} + \centerline{(Version 4.4 for MacOS)} @z @x section 23: Make input_ln accept \n, \r, \n\r, or \r\n as line endings diff --git a/comm-pc.ch b/comm-pc.ch index 9e156ad..5a29188 100644 --- a/comm-pc.ch +++ b/comm-pc.ch @@ -8,7 +8,7 @@ Note: The change to section 16 is not necessary if using a compiler that allows >64K arrays. @x section 16 -@d max_bytes 1000000 /* the number of bytes in identifiers, +@d max_bytes 90000 /* the number of bytes in identifiers, @y @d max_bytes (unsigned)60000 /* the number of bytes in identifiers, @z diff --git a/comm-ql.ch b/comm-ql.ch index bde4a1a..a50abbf 100644 --- a/comm-ql.ch +++ b/comm-ql.ch @@ -10,24 +10,24 @@ ex cc;'-v -h -c -=500000 -DCWEBINPUTS=flp2_ common_c' @x \def\v{\char'174} % vertical (|) in typewriter font -\def\title{Common code for CTANGLE and CWEAVE (Version 4.3)} +\def\title{Common code for CTANGLE and CWEAVE (Version 4.4)} \def\topofcontents{\null\vfill \centerline{\titlefont Common code for {\ttitlefont CTANGLE} and {\ttitlefont CWEAVE}} \vskip 15pt - \centerline{(Version 4.3)} + \centerline{(Version 4.4)} \vfill} \def\botofcontents{\vfill \noindent @y \def\v{\char'174} % vertical (|) in typewriter font -\def\title{Common code for CTANGLE and CWEAVE (QL Version 4.3)} +\def\title{Common code for CTANGLE and CWEAVE (QL Version 4.4)} \def\topofcontents{\null\vfill \centerline{\titlefont Common code for {\ttitlefont CTANGLE} and {\ttitlefont CWEAVE}} \vskip 15pt - \centerline{(Version 4.3)} + \centerline{(Version 4.4)} \vfill} \def\botofcontents{\vfill \noindent @@ -40,7 +40,7 @@ for the file name plus one character as string terminator. (Note that (current) QDOS/SMSQ file systems have a limitation of 36 characters as maximum length for a file name. @x -@d max_file_name_length 1024 +@d max_file_name_length 60 @y @d max_file_name_length 42 @z @@ -148,7 +148,7 @@ the routine as if it would work. sprintf(web_file_name,"%s.w",*argv); else { strcpy(web_file_name,*argv); - *dot_pos=0; /* string now ends where the dot was */ + *dot_pos='\0'; /* string now ends where the dot was */ } sprintf(alt_web_file_name,"%s.web",*argv); sprintf(tex_file_name,"%s.tex",name_pos); /* strip off directory name */ @@ -166,7 +166,7 @@ the routine as if it would work. sprintf(web_file_name,"%s_w",*argv); else { strcpy(web_file_name,*argv); - *dot_pos=0; /* string now ends where the dot was */ + *dot_pos='\0'; /* string now ends where the dot was */ } sprintf(alt_web_file_name,"%s_web",*argv); sprintf(tex_file_name,"%s_tex",name_pos); /* strip off directory name */ @@ -219,7 +219,7 @@ the routine as if it would work. strcpy(tex_file_name,*argv); strcpy(C_file_name,*argv); if (make_xrefs) { /* indexes will be generated */ - *dot_pos=0; + *dot_pos='\0'; sprintf(idx_file_name,"%s.idx",*argv); sprintf(scn_file_name,"%s.scn",*argv); } @@ -240,7 +240,7 @@ the routine as if it would work. strcpy(tex_file_name,*argv); strcpy(C_file_name,*argv); if (make_xrefs) { /* indexes will be generated */ - *dot_pos=0; + *dot_pos='\0'; sprintf(idx_file_name,"%s_idx",*argv); sprintf(scn_file_name,"%s_scn",*argv); } diff --git a/common.c b/common.c index 3480c86..16733c1 100644 --- a/common.c +++ b/common.c @@ -49,7 +49,7 @@ #define max_include_depth 10 \ -#define max_file_name_length 1024 +#define max_file_name_length 60 #define cur_file file[include_depth] #define cur_file_name file_name[include_depth] #define cur_line line[include_depth] @@ -57,7 +57,7 @@ #define web_file_name file_name[0] \ #define length(c) (size_t) ((c+1) ->byte_start-(c) ->byte_start) -#define print_id(c) term_write((c) ->byte_start,length((c) ) ) +#define print_id(c) term_write((c) ->byte_start,length(c) ) #define llink link #define rlink dummy.Rlink #define root name_dir->rlink \ @@ -82,32 +82,29 @@ #define new_line putchar('\n') #define term_write(a,b) fflush(stdout) ,fwrite(a,sizeof(char) ,b,stdout) \ -#define max_bytes 1000000 \ +#define buf_size 100 +#define longest_name 10000 \ -#define max_toks 1000000 -#define max_names 10239 \ +#define long_buf_size (buf_size+longest_name) +#define max_bytes 90000 \ -#define max_sections 4000 -#define max_texts 10239 -#define longest_name 10000 -#define stack_size 500 -#define buf_size 1000 -#define long_buf_size (buf_size+longest_name) \ +#define max_names 4000 \ + +#define max_sections 2000 \ #define lines_dont_match (change_limit-change_buffer!=limit-buffer|| \ strncmp(buffer,change_buffer,(size_t) (limit-buffer) ) ) \ -#define if_section_start_make_pending(b) { \ +#define if_section_start_make_pending(b) \ *limit= '!'; \ for(loc= buffer;xisspace(*loc) ;loc++) ; \ *limit= ' '; \ if(*loc=='@'&&(xisspace(*(loc+1) ) ||*(loc+1) =='*') ) change_pending= b; \ -} \ #define too_long() {include_depth--; \ err_print("! Include file name too long") ;goto restart;} \ -#define hash_size 8501 \ +#define hash_size 353 \ #define first_chunk(p) ((p) ->byte_start+2) #define prefix_length(p) (int) ((eight_bits) *((p) ->byte_start) *256+ \ @@ -279,7 +276,7 @@ static char change_buffer[buf_size]; static char*change_limit; /*:26*//*37:*/ -#line 396 "common.w" +#line 393 "common.w" sixteen_bits section_count; boolean changed_section[max_sections]; @@ -288,7 +285,7 @@ boolean change_pending; boolean print_where= false; /*:37*//*43:*/ -#line 593 "common.w" +#line 590 "common.w" char byte_mem[max_bytes]; char*byte_mem_end= byte_mem+max_bytes-1; @@ -296,25 +293,25 @@ name_info name_dir[max_names]; name_pointer name_dir_end= name_dir+max_names-1; /*:43*//*44:*/ -#line 604 "common.w" +#line 601 "common.w" char*byte_ptr; name_pointer name_ptr; /*:44*//*46:*/ -#line 624 "common.w" +#line 621 "common.w" name_pointer hash[hash_size]; hash_pointer hash_end= hash+hash_size-1; hash_pointer h; /*:46*//*65:*/ -#line 1006 "common.w" +#line 1003 "common.w" int history= spotless; /*:65*//*73:*/ -#line 1129 "common.w" +#line 1126 "common.w" int argc; char**argv; @@ -325,7 +322,7 @@ char scn_file_name[max_file_name_length]; boolean flags[128]; /*:73*//*83:*/ -#line 1272 "common.w" +#line 1269 "common.w" FILE*C_file; FILE*tex_file; @@ -379,22 +376,22 @@ static boolean input_ln(FILE*); static void prime_the_change_buffer(void); /*:28*//*33:*/ -#line 337 "common.w" +#line 334 "common.w" static void check_change(void); /*:33*//*55:*/ -#line 767 "common.w" +#line 764 "common.w" static int web_strcmp(char*,int,char*,int); static name_pointer add_section_name(name_pointer,int,char*,char*,boolean); static void extend_section_name(name_pointer,char*,char*,boolean); /*:55*//*64:*/ -#line 994 "common.w" +#line 991 "common.w" static int section_name_cmp(char**,int,name_pointer); /*:64*//*76:*/ -#line 1189 "common.w" +#line 1186 "common.w" static void scan_args(void); /*:76*/ @@ -408,7 +405,7 @@ void common_init(void) { /*45:*/ -#line 608 "common.w" +#line 605 "common.w" name_dir->byte_start= byte_ptr= byte_mem; name_ptr= name_dir+1; @@ -416,7 +413,7 @@ name_ptr->byte_start= byte_mem; root= NULL; /*:45*//*47:*/ -#line 631 "common.w" +#line 628 "common.w" for(h= hash;h<=hash_end;*h++= NULL); @@ -424,7 +421,7 @@ for(h= hash;h<=hash_end;*h++= NULL); #line 99 "common.w" /*74:*/ -#line 1142 "common.w" +#line 1139 "common.w" show_banner= show_happiness= show_progress= make_xrefs= true; @@ -432,7 +429,7 @@ show_banner= show_happiness= show_progress= make_xrefs= true; #line 100 "common.w" /*84:*/ -#line 1279 "common.w" +#line 1276 "common.w" scan_args(); if(program==ctangle){ @@ -517,10 +514,8 @@ return; /*31:*/ #line 270 "common.w" -{ change_limit= change_buffer+(ptrdiff_t)(limit-buffer); strncpy(change_buffer,buffer,(size_t)(limit-buffer+1)); -} /*:31*/ #line 234 "common.w" @@ -528,7 +523,7 @@ strncpy(change_buffer,buffer,(size_t)(limit-buffer+1)); } /*:27*//*32:*/ -#line 299 "common.w" +#line 296 "common.w" static void check_change(void) @@ -551,7 +546,7 @@ return; if(limit> buffer+1&&buffer[0]=='@'){ char xyz_code= xisupper(buffer[1])?tolower((eight_bits)buffer[1]):buffer[1]; /*34:*/ -#line 339 "common.w" +#line 336 "common.w" if(xyz_code=='x'||xyz_code=='z'){ loc= buffer+2;err_print("! Where is the matching @y?"); @@ -569,19 +564,17 @@ return; } /*:34*/ -#line 321 "common.w" +#line 318 "common.w" } /*31:*/ #line 270 "common.w" -{ change_limit= change_buffer+(ptrdiff_t)(limit-buffer); strncpy(change_buffer,buffer,(size_t)(limit-buffer+1)); -} /*:31*/ -#line 323 "common.w" +#line 320 "common.w" changing= false;cur_line++; while(!input_ln(cur_file)){ @@ -597,14 +590,14 @@ if(lines_dont_match)n++; } /*:32*//*35:*/ -#line 359 "common.w" +#line 356 "common.w" void reset_input(void) { limit= buffer;loc= buffer+1;buffer[0]= ' '; /*36:*/ -#line 374 "common.w" +#line 371 "common.w" if((web_file= fopen(web_file_name,"r"))==NULL){ strcpy(web_file_name,alt_web_file_name); @@ -618,7 +611,7 @@ if((change_file= fopen(change_file_name,"r"))==NULL) fatal("! Cannot open change file ",change_file_name); /*:36*/ -#line 364 "common.w" +#line 361 "common.w" include_depth= cur_line= change_line= 0; change_depth= include_depth; @@ -627,14 +620,14 @@ limit= buffer;loc= buffer+1;buffer[0]= ' ';input_has_ended= false; } /*:35*//*38:*/ -#line 403 "common.w" +#line 400 "common.w" boolean get_line(void) { restart: if(changing&&include_depth==change_depth) /*41:*/ -#line 511 "common.w" +#line 508 "common.w" { change_line++; if(!input_ln(change_file)){ @@ -665,11 +658,11 @@ prime_the_change_buffer();changing= !changing;print_where= true; } /*:41*/ -#line 408 "common.w" +#line 405 "common.w" if(!changing||include_depth> change_depth){ /*40:*/ -#line 494 "common.w" +#line 491 "common.w" { cur_line++; while(!input_ln(cur_file)){ @@ -688,7 +681,7 @@ if(change_limit> change_buffer)check_change(); } /*:40*/ -#line 410 "common.w" +#line 407 "common.w" if(changing&&include_depth==change_depth)goto restart; } @@ -709,7 +702,7 @@ goto restart; } include_depth++; /*39:*/ -#line 448 "common.w" +#line 445 "common.w" { char temp_file_name[max_file_name_length]; char*cur_file_name_end= cur_file_name+max_file_name_length-1; @@ -757,14 +750,14 @@ include_depth--;err_print("! Cannot open include file");goto restart; } /*:39*/ -#line 429 "common.w" +#line 426 "common.w" } return true; } /*:38*//*42:*/ -#line 543 "common.w" +#line 540 "common.w" void check_complete(void){ @@ -778,7 +771,7 @@ err_print("! Change file entry did not match"); } /*:42*//*48:*/ -#line 636 "common.w" +#line 633 "common.w" name_pointer id_lookup( @@ -793,17 +786,17 @@ name_pointer p; if(last==NULL)for(last= first;*last!='\0';last++); l= (int)(last-first); /*49:*/ -#line 659 "common.w" +#line 656 "common.w" h= (eight_bits)*i; while(++ilink; @@ -813,10 +806,10 @@ p->link= hash[h];hash[h]= p; } /*:50*/ -#line 650 "common.w" +#line 647 "common.w" if(p==name_ptr)/*51:*/ -#line 679 "common.w" +#line 676 "common.w" { if(byte_ptr+l> byte_mem_end)overflow("byte memory"); if(name_ptr>=name_dir_end)overflow("name"); @@ -826,13 +819,13 @@ init_p(p,t); } /*:51*/ -#line 651 "common.w" +#line 648 "common.w" return p; } /*:48*//*52:*/ -#line 711 "common.w" +#line 708 "common.w" void print_section_name( @@ -851,7 +844,7 @@ if(q)term_write("...",3); } /*:52*//*53:*/ -#line 728 "common.w" +#line 725 "common.w" void sprint_section_name( @@ -871,7 +864,7 @@ s= p->byte_start; } /*:53*//*54:*/ -#line 746 "common.w" +#line 743 "common.w" void print_prefix_name( @@ -884,7 +877,7 @@ if(s+l<(p+1)->byte_start)term_write("...",3); } /*:54*//*56:*/ -#line 772 "common.w" +#line 769 "common.w" static int web_strcmp( char*j, @@ -902,7 +895,7 @@ else return greater; } /*:56*//*57:*/ -#line 801 "common.w" +#line 798 "common.w" static name_pointer add_section_name( @@ -932,7 +925,7 @@ return par==NULL?(root= p):c==less?(par->llink= p):(par->rlink= p); } /*:57*//*58:*/ -#line 829 "common.w" +#line 826 "common.w" static void extend_section_name( @@ -956,7 +949,7 @@ if(ispref)*(byte_ptr-1)= ' '; } /*:58*//*59:*/ -#line 857 "common.w" +#line 854 "common.w" name_pointer section_lookup( @@ -971,7 +964,7 @@ name_pointer par= NULL; int name_len= (int)(last-first)+1; /*60:*/ -#line 881 "common.w" +#line 878 "common.w" while(p){ c= web_strcmp(first,name_len,first_chunk(p),prefix_length(p)); @@ -998,19 +991,19 @@ p= q,q= NULL; } /*:60*/ -#line 871 "common.w" +#line 868 "common.w" /*61:*/ -#line 906 "common.w" +#line 903 "common.w" if(r==NULL) return add_section_name(par,c,first,last+1,ispref); /*:61*/ -#line 872 "common.w" +#line 869 "common.w" /*62:*/ -#line 914 "common.w" +#line 911 "common.w" switch(section_name_cmp(&first,name_len,r)){ @@ -1044,12 +1037,12 @@ err_print(">"); return r; /*:62*/ -#line 873 "common.w" +#line 870 "common.w" } /*:59*//*63:*/ -#line 962 "common.w" +#line 959 "common.w" static int section_name_cmp( char**pfirst, @@ -1083,18 +1076,18 @@ default:return c; } /*:63*//*66:*/ -#line 1016 "common.w" +#line 1013 "common.w" void err_print( const char*s) { -char*k,*l; printf(*s=='!'?"\n%s":"%s",s); if(web_file_open)/*67:*/ -#line 1036 "common.w" +#line 1032 "common.w" -{if(changing&&include_depth==change_depth) +{char*k,*l; +if(changing&&include_depth==change_depth) printf(". (l. %d of change file)\n",change_line); else if(include_depth==0)printf(". (l. %d)\n",cur_line); else printf(". (l. %d of include file %s)\n",cur_line,cur_file_name); @@ -1112,20 +1105,20 @@ putchar(' '); } /*:67*/ -#line 1023 "common.w" +#line 1019 "common.w" update_terminal;mark_error; } /*:66*//*68:*/ -#line 1068 "common.w" +#line 1065 "common.w" int wrap_up(void){ if(show_progress)new_line; if(show_stats) print_stats(); /*69:*/ -#line 1078 "common.w" +#line 1075 "common.w" switch(history){ case spotless: @@ -1139,14 +1132,14 @@ puts("(That was a fatal error, my friend.)"); } /*:69*/ -#line 1073 "common.w" +#line 1070 "common.w" if(history> harmless_message)return EXIT_FAILURE; else return EXIT_SUCCESS; } /*:68*//*70:*/ -#line 1096 "common.w" +#line 1093 "common.w" void fatal( const char*s,const char*t) @@ -1157,7 +1150,7 @@ history= fatal_message;exit(wrap_up()); } /*:70*//*71:*/ -#line 1107 "common.w" +#line 1104 "common.w" void overflow( const char*t) @@ -1167,7 +1160,7 @@ printf("\n! Sorry, %s capacity exceeded",t);fatal("",""); /*:71*//*75:*/ -#line 1160 "common.w" +#line 1157 "common.w" static void scan_args(void) @@ -1181,13 +1174,13 @@ boolean found_web= false,found_change= false,found_out= false; strcpy(change_file_name,"/dev/null"); while(--argc> 0){ if((**(++argv)=='-'||**argv=='+')&&*(*argv+1))/*80:*/ -#line 1250 "common.w" +#line 1247 "common.w" for(dot_pos= *argv+1;*dot_pos> '\0';dot_pos++) flags[(eight_bits)*dot_pos]= flag_change; /*:80*/ -#line 1172 "common.w" +#line 1169 "common.w" else{ s= name_pos= *argv;dot_pos= NULL; @@ -1196,23 +1189,23 @@ if(*s=='.')dot_pos= s++; else if(*s=='/')dot_pos= NULL,name_pos= ++s; else s++; if(!found_web)/*77:*/ -#line 1198 "common.w" +#line 1195 "common.w" { if(s-*argv> max_file_name_length-5) /*82:*/ -#line 1266 "common.w" +#line 1263 "common.w" fatal("! Filename too long\n",*argv); /*:82*/ -#line 1201 "common.w" +#line 1198 "common.w" if(dot_pos==NULL) sprintf(web_file_name,"%s.w",*argv); else{ strcpy(web_file_name,*argv); -*dot_pos= 0; +*dot_pos= '\0'; } sprintf(alt_web_file_name,"%s.web",*argv); sprintf(tex_file_name,"%s.tex",name_pos); @@ -1223,21 +1216,21 @@ found_web= true; } /*:77*/ -#line 1180 "common.w" +#line 1177 "common.w" else if(!found_change)/*78:*/ -#line 1216 "common.w" +#line 1213 "common.w" { if(strcmp(*argv,"-")!=0){ if(s-*argv> max_file_name_length-4) /*82:*/ -#line 1266 "common.w" +#line 1263 "common.w" fatal("! Filename too long\n",*argv); /*:82*/ -#line 1220 "common.w" +#line 1217 "common.w" if(dot_pos==NULL) sprintf(change_file_name,"%s.ch",*argv); @@ -1247,20 +1240,20 @@ found_change= true; } /*:78*/ -#line 1181 "common.w" +#line 1178 "common.w" else if(!found_out)/*79:*/ -#line 1228 "common.w" +#line 1225 "common.w" { if(s-*argv> max_file_name_length-5) /*82:*/ -#line 1266 "common.w" +#line 1263 "common.w" fatal("! Filename too long\n",*argv); /*:82*/ -#line 1231 "common.w" +#line 1228 "common.w" if(dot_pos==NULL){ sprintf(tex_file_name,"%s.tex",*argv); @@ -1271,7 +1264,7 @@ sprintf(C_file_name,"%s.c",*argv); strcpy(tex_file_name,*argv); strcpy(C_file_name,*argv); if(make_xrefs){ -*dot_pos= 0; +*dot_pos= '\0'; sprintf(idx_file_name,"%s.idx",*argv); sprintf(scn_file_name,"%s.scn",*argv); } @@ -1280,10 +1273,10 @@ found_out= true; } /*:79*/ -#line 1182 "common.w" +#line 1179 "common.w" else/*81:*/ -#line 1254 "common.w" +#line 1251 "common.w" { if(program==ctangle) @@ -1297,12 +1290,12 @@ else fatal( } /*:81*/ -#line 1183 "common.w" +#line 1180 "common.w" } } if(!found_web)/*81:*/ -#line 1254 "common.w" +#line 1251 "common.w" { if(program==ctangle) @@ -1316,7 +1309,7 @@ else fatal( } /*:81*/ -#line 1186 "common.w" +#line 1183 "common.w" } diff --git a/common.h b/common.h index 0f8ec18..17717a5 100644 --- a/common.h +++ b/common.h @@ -2,7 +2,7 @@ % This program by Silvio Levy and Donald E. Knuth % is based on a program by Knuth. % It is distributed WITHOUT ANY WARRANTY, express or implied. -% Version 4.3 --- May 2021 (works also with later versions) +% Version 4.4 --- June 2021 (works also with later versions) % Copyright (C) 1987,1990,1993 Silvio Levy and Donald E. Knuth @@ -99,7 +99,7 @@ extern char *limit; /* points to the last character in the buffer */ @f line x /* make |line| an unreserved word */ @d max_include_depth 10 /* maximum number of source files open simultaneously, not counting the change file */ -@d max_file_name_length 1024 +@d max_file_name_length 60 @d cur_file file[include_depth] /* current file */ @d cur_file_name file_name[include_depth] /* current file name */ @d cur_line line[include_depth] /* number of current line in current file */ @@ -134,7 +134,7 @@ extern boolean print_where; /* tells \.{CTANGLE} to print line and file info */ @ Code related to identifier and section name storage: @d length(c) (size_t)((c+1)->byte_start-(c)->byte_start) /* the length of a name */ -@d print_id(c) term_write((c)->byte_start,length((c))) /* print identifier */ +@d print_id(c) term_write((c)->byte_start,length(c)) /* print identifier */ @d llink link /* left link in binary search tree for section names */ @d rlink dummy.Rlink /* right link in binary search tree for section names */ @d root name_dir->rlink /* the root of the binary search tree @@ -230,16 +230,14 @@ extern void print_stats(void); handle \TEX/, so they should be sufficient for most applications of \.{CWEB}. -@d max_bytes 1000000 /* the number of bytes in identifiers, - index entries, and section names */ -@d max_toks 1000000 /* number of bytes in compressed \CEE/ code */ -@d max_names 10239 /* number of identifiers, strings, section names; - must be less than 10240 */ -@d max_sections 4000 /* greater than the total number of sections */ -@d max_texts 10239 /* number of replacement texts, must be less than 10240 */ -@d longest_name 10000 /* file and section names and section texts shouldn't be longer than this */ -@d stack_size 500 /* number of simultaneous levels of macro expansion */ -@d buf_size 1000 /* maximum length of input line, plus one */ +@d buf_size 100 /* maximum length of input line, plus one */ +@d longest_name 10000 /* file names, section names, and section texts + shouldn't be longer than this */ @d long_buf_size (buf_size+longest_name) /* for \.{CWEAVE} */ +@d max_bytes 90000 /* the number of bytes in identifiers, + index entries, and section names; must be less than $2^{24}$ */ +@d max_names 4000 /* number of identifiers, strings, section names; + must be less than 10240 */ +@d max_sections 2000 /* greater than the total number of sections */ @ End of \.{COMMON} interface. diff --git a/common.w b/common.w index d6e0702..dba1967 100644 --- a/common.w +++ b/common.w @@ -2,7 +2,7 @@ % This program by Silvio Levy and Donald E. Knuth % is based on a program by Knuth. % It is distributed WITHOUT ANY WARRANTY, express or implied. -% Version 4.3 --- May 2021 +% Version 4.4 --- June 2021 % Copyright (C) 1987,1990,1993,2000 Silvio Levy and Donald E. Knuth @@ -22,12 +22,12 @@ \def\v{\char'174} % vertical (|) in typewriter font -\def\title{Common code for CTANGLE and CWEAVE (Version 4.3)} +\def\title{Common code for CTANGLE and CWEAVE (Version 4.4)} \def\topofcontents{\null\vfill \centerline{\titlefont Common code for {\ttitlefont CTANGLE} and {\ttitlefont CWEAVE}} \vskip 15pt - \centerline{(Version 4.3)} + \centerline{(Version 4.4)} \vfill} \def\botofcontents{\vfill \noindent @@ -178,7 +178,7 @@ FILE *fp) /* what file to read from */ @ Now comes the problem of deciding which file to read from next. Recall that the actual text that \.{CWEB} should process comes from two streams: a |web_file|, which can contain possibly nested include -commands \.{@@i}, and a |change_file|, which might also contain +commands~\.{@@i}, and a |change_file|, which might also contain includes. The |web_file| together with the currently open include files form a stack |file|, whose names are stored in a parallel stack |file_name|. The boolean |changing| tells whether or not we're reading @@ -268,10 +268,8 @@ do { } while (limit==buffer); @ @= -{ - change_limit=change_buffer+(ptrdiff_t)(limit-buffer); - strncpy(change_buffer,buffer,(size_t)(limit-buffer+1)); -} +change_limit=change_buffer+(ptrdiff_t)(limit-buffer); +strncpy(change_buffer,buffer,(size_t)(limit-buffer+1)); @ The following procedure is used to see if the next change entry should go into effect; it is called only when |changing| is |false|. @@ -289,12 +287,11 @@ either `\.{@@*}' or `\.{@@\ }' (possibly preceded by whitespace). This procedure is called only when |buffer0) { - if (k+l+2>=cur_file_name_end) too_long(); + if (k+l+2>=cur_file_name_end) too_long(); @.Include file name ...@> for (; k>=cur_file_name; k--) *(k+l+1)=*k; strcpy(cur_file_name,temp_file_name); @@ -619,7 +616,7 @@ function |names_match|, which is slightly different in \.{CWEAVE} and \.{CTANGLE}. If there is no match for the identifier, it is inserted into the table. -@d hash_size 8501 /* should be prime */ +@d hash_size 353 /* should be prime */ @= name_pointer hash[hash_size]; /* heads of hash lists */ @@ -886,7 +883,7 @@ while (p) { /* compare shortest prefix of |p| with new name */ par=p; p=(c==less?p->llink:p->rlink); } else { /* new name matches |p| */ - if (r!=NULL) { /* and also |r|: illegal */ + if (r!=NULL) { /* and also |r|: illegal */ fputs("\n! Ambiguous prefix: matches <",stdout); @.Ambiguous prefix ... @> print_prefix_name(p); @@ -1018,7 +1015,6 @@ void err_print( /* prints `\..' and location of error message */ const char *s) { - char *k,*l; /* pointers into |buffer| */ printf(*s=='!'? "\n%s" : "%s",s); if (web_file_open) @@; update_terminal; mark_error; @@ -1034,7 +1030,8 @@ has special line-numbering conventions. @^system dependencies@> @= -{if (changing && include_depth==change_depth) +{char *k,*l; /* pointers into |buffer| */ +if (changing && include_depth==change_depth) printf(". (l. %d of change file)\n", change_line); else if (include_depth==0) printf(". (l. %d)\n", cur_line); else printf(". (l. %d of include file %s)\n", cur_line, cur_file_name); @@ -1203,7 +1200,7 @@ after the dot. We must check that there is enough room in sprintf(web_file_name,"%s.w",*argv); else { strcpy(web_file_name,*argv); - *dot_pos=0; /* string now ends where the dot was */ + *dot_pos='\0'; /* string now ends where the dot was */ } sprintf(alt_web_file_name,"%s.web",*argv); sprintf(tex_file_name,"%s.tex",name_pos); /* strip off directory name */ @@ -1238,7 +1235,7 @@ after the dot. We must check that there is enough room in strcpy(tex_file_name,*argv); strcpy(C_file_name,*argv); if (make_xrefs) { /* indexes will be generated */ - *dot_pos=0; + *dot_pos='\0'; sprintf(idx_file_name,"%s.idx",*argv); sprintf(scn_file_name,"%s.scn",*argv); } diff --git a/ctang-bs.ch b/ctang-bs.ch index fcd2706..fa4b90c 100644 --- a/ctang-bs.ch +++ b/ctang-bs.ch @@ -17,12 +17,12 @@ by using "huge" pointers. The ``banner line'' defined here should be changed whenever \.{CTANGLE} is modified. -@d banner "This is CTANGLE (Version 4.3)" +@d banner "This is CTANGLE (Version 4.4)" @y The ``banner line'' defined here should be changed whenever \.{CTANGLE} is modified. -@d banner "This is CTANGLE (Version 4.3pc/big)" +@d banner "This is CTANGLE (Version 4.4pc/big)" @z @@ -84,49 +84,6 @@ extern hash_pointer h; /* index into hash-head array */ @z -@x Section 17. -@ The following parameters were sufficient in the original \.{WEB} to -handle \TEX/, so they should be sufficient for most applications of -\.{CWEB}. - -@d max_bytes 1000000 /* the number of bytes in identifiers, - index entries, and section names */ -@d max_toks 1000000 /* number of bytes in compressed \CEE/ code */ -@d max_names 10239 /* number of identifiers, strings, section names; - must be less than 10240 */ -@d max_sections 4000 /* greater than the total number of sections */ -@d max_texts 10239 /* number of replacement texts, must be less than 10240 */ -@d longest_name 10000 /* file and section names and section texts shouldn't be longer than this */ -@d stack_size 500 /* number of simultaneous levels of macro expansion */ -@d buf_size 1000 /* maximum length of input line, plus one */ -@y -@ The following parameters were sufficient in the original \.{WEB} to -handle \TEX/, so they should be sufficient for most applications of -\.{CWEB}. - -(This is a modified version of \.{CTANGLE}, and in fact one of the parameters -has been reduced in value. The parameter |max_toks| -has been reduced from 270000 [which -was sufficient to handle \TEX/] to -170000, so that \.{CTANGLE} -may be run on {\mc MSDOS} -systems that are tight on memory. Consider, for -instance, an 80286-based machine with several TSRs and drivers, trying -to run \.{CTANGLE} from a makefile.) - -@d max_bytes 90000 /* the number of bytes in identifiers, - index entries, and section names */ -@d max_toks 170000 /* number of bytes in compressed \CEE/ code */ -@d max_names 4000 /* number of identifiers, strings, section names; - must be less than 10240 */ -@d max_sections 4000 /* greater than the total number of sections */ -@d max_texts 2500 /* number of replacement texts, must be less than 10240 */ -@d longest_name 10000 /* file and section names and section texts shouldn't be longer than this */ -@d stack_size 50 /* number of simultaneous levels of macro expansion */ -@d buf_size 100 /* for \.{CWEAVE} */ -@z - - @x Section 19. eight_bits *tok_start; /* pointer into |tok_mem| */ sixteen_bits text_link; /* relates replacement texts */ @@ -141,6 +98,22 @@ typedef text *text_pointer; @x Section 20. +@ @d max_texts 2500 /* number of replacement texts, must be less than 10240 */ +@d max_toks 270000 /* number of bytes in compressed \CEE/ code */ +@y +@ (This is a modified version of \.{CTANGLE}, and in fact one of the parameters +has been reduced in value. The parameter |max_toks| +has been reduced from 270000 [which +was sufficient to handle \TEX/] to +170000, so that \.{CTANGLE} +may be run on {\mc MSDOS} +systems that are tight on memory. Consider, for +instance, an 80286-based machine with several TSRs and drivers, trying +to run \.{CTANGLE} from a makefile.) +@d max_texts 2500 /* number of replacement texts, must be less than 10240 */ +@d max_toks 170000 /* number of bytes in compressed \CEE/ code */ +@z +@x static eight_bits tok_mem[max_toks]; static eight_bits *tok_mem_end=tok_mem+max_toks-1; static eight_bits *tok_ptr; /* first unused position in |tok_mem| */ diff --git a/ctang-pc.ch b/ctang-pc.ch index 025790e..f84c798 100644 --- a/ctang-pc.ch +++ b/ctang-pc.ch @@ -9,16 +9,19 @@ that allows >64K arrays. If you need lots of bytes and toks, try the alternate change files with -bs suffix instead of -pc. @x section 1 -@d banner "This is CTANGLE (Version 4.3)" +@d banner "This is CTANGLE (Version 4.4)" @y -@d banner "This is CTANGLE (Version 4.3pc)" +@d banner "This is CTANGLE (Version 4.4pc)" @z @x section 17 -@d max_bytes 1000000 /* the number of bytes in identifiers, - index entries, and section names */ -@d max_toks 1000000 /* number of bytes in compressed \CEE/ code */ +@d max_bytes 90000 /* the number of bytes in identifiers, + index entries, and section names; must be less than $2^{24}$ */ @y (note that CWEAVE itself needs only about 42K toks) @d max_bytes (unsigned)60000 /* the number of bytes in identifiers, - index entries, and section names */ + index entries, and section names; must be less than $2^{24}$ */ +@z +@x section 20 +@d max_toks 270000 /* number of bytes in compressed \CEE/ code */ +@y @d max_toks (unsigned)60000 /* number of bytes in compressed \CEE/ code */ @z diff --git a/ctang-ql.ch b/ctang-ql.ch index 6d5fe6b..27a7d01 100644 --- a/ctang-ql.ch +++ b/ctang-ql.ch @@ -7,15 +7,15 @@ ex cc;"-v -h -c -=500000 ctangle_c" @x -\def\title{CTANGLE (Version 4.3)} +\def\title{CTANGLE (Version 4.4)} @y -\def\title{CTANGLE (QL Version 4.3)} +\def\title{CTANGLE (QL Version 4.4)} @z @x section 1 -@d banner "This is CTANGLE (Version 4.3)" +@d banner "This is CTANGLE (Version 4.4)" @y -@d banner "This is CTANGLE (QL Version 4.3)" +@d banner "This is CTANGLE (QL Version 4.4)" @z @x diff --git a/ctang-vms.ch b/ctang-vms.ch index 753e8d9..a72de29 100644 --- a/ctang-vms.ch +++ b/ctang-vms.ch @@ -10,9 +10,9 @@ created: (these changes not necessary for initial bootstrapping) @x section 1 (01-FEB-1992 ST) -@d banner "This is CTANGLE (Version 4.3)" +@d banner "This is CTANGLE (Version 4.4)" @y -@d banner "This is CTANGLE (VAX/VMS Version 4.3)" +@d banner "This is CTANGLE (VAX/VMS Version 4.4)" @z @x section 4 (01-FEB-1992 ST) diff --git a/ctang-w32.ch b/ctang-w32.ch index 9d9be12..ceba0fe 100644 --- a/ctang-w32.ch +++ b/ctang-w32.ch @@ -4,9 +4,9 @@ This is the change file for CWEB's CTANGLE under Win32 Changes necessary for compiling with Borland C/C++ @x section 1 -@d banner "This is CTANGLE (Version 4.3)" +@d banner "This is CTANGLE (Version 4.4)" @y -@d banner "This is CTANGLE (Version 4.3win32)" +@d banner "This is CTANGLE (Version 4.4win32)" @z @x diff --git a/ctangle.c b/ctangle.c index 26407b4..14a0732 100644 --- a/ctangle.c +++ b/ctangle.c @@ -15,7 +15,7 @@ /*:4*/ #line 67 "ctangle.w" -#define banner "This is CTANGLE (Version 4.3)" \ +#define banner "This is CTANGLE (Version 4.4)" \ #define ctangle false #define cweave true \ @@ -51,7 +51,7 @@ #define max_include_depth 10 \ -#define max_file_name_length 1024 +#define max_file_name_length 60 #define cur_file file[include_depth] #define cur_file_name file_name[include_depth] #define cur_line line[include_depth] @@ -59,7 +59,7 @@ #define web_file_name file_name[0] \ #define length(c) (size_t) ((c+1) ->byte_start-(c) ->byte_start) -#define print_id(c) term_write((c) ->byte_start,length((c) ) ) +#define print_id(c) term_write((c) ->byte_start,length(c) ) #define llink link #define rlink dummy.Rlink #define root name_dir->rlink \ @@ -84,18 +84,18 @@ #define new_line putchar('\n') #define term_write(a,b) fflush(stdout) ,fwrite(a,sizeof(char) ,b,stdout) \ -#define max_bytes 1000000 \ +#define buf_size 100 +#define longest_name 10000 \ -#define max_toks 1000000 -#define max_names 10239 \ +#define long_buf_size (buf_size+longest_name) +#define max_bytes 90000 \ -#define max_sections 4000 -#define max_texts 10239 -#define longest_name 10000 -#define stack_size 500 -#define buf_size 1000 -#define long_buf_size (buf_size+longest_name) \ +#define max_names 4000 \ +#define max_sections 2000 \ + +#define max_texts 2500 +#define max_toks 270000 #define equiv equiv_or_xref \ #define macro 0 @@ -106,6 +106,7 @@ #define join 0177 #define output_defs_flag (2*024000-1) \ +#define stack_size 50 #define cur_end cur_state.end_field #define cur_byte cur_state.byte_field #define cur_name cur_state.name_field @@ -138,7 +139,11 @@ #define section_name 0311 #define new_section 0312 \ -#define app_repl(c) {if(tok_ptr==tok_mem_end) overflow("token") ;*tok_ptr++= c;} \ +#define app_repl(c) {if(tok_ptr==tok_mem_end) overflow("token") ;*(tok_ptr++) = c;} \ + +#define store_id(a) a= id_lookup(id_first,id_loc,0) -name_dir; \ +app_repl((a/0400) +0200) ; \ +app_repl(a%0400) ; \ #define keep_digit_separators flags['k'] \ @@ -257,7 +262,7 @@ sixteen_bits text_link; typedef text*text_pointer; /*:19*//*31:*/ -#line 273 "ctangle.w" +#line 274 "ctangle.w" typedef struct{ eight_bits*end_field; @@ -272,7 +277,7 @@ typedef output_state*stack_pointer; #line 70 "ctangle.w" /*20:*/ -#line 129 "ctangle.w" +#line 131 "ctangle.w" static text text_info[max_texts]; static text_pointer text_info_end= text_info+max_texts-1; @@ -282,12 +287,12 @@ static eight_bits*tok_mem_end= tok_mem+max_toks-1; static eight_bits*tok_ptr; /*:20*//*26:*/ -#line 199 "ctangle.w" +#line 200 "ctangle.w" static text_pointer last_unnamed; /*:26*//*32:*/ -#line 289 "ctangle.w" +#line 291 "ctangle.w" static output_state cur_state; @@ -296,18 +301,18 @@ static stack_pointer stack_end= stack+stack_size; static stack_pointer stack_ptr; /*:32*//*37:*/ -#line 365 "ctangle.w" +#line 367 "ctangle.w" static int cur_val; /*:37*//*42:*/ -#line 456 "ctangle.w" +#line 458 "ctangle.w" static eight_bits out_state; static boolean protect; /*:42*//*45:*/ -#line 487 "ctangle.w" +#line 489 "ctangle.w" static name_pointer output_files[max_files]; static name_pointer*cur_out_file,*end_output_files,*an_output_file; @@ -315,33 +320,33 @@ static char cur_section_name_char; static char output_file_name[longest_name+1]; /*:45*//*52:*/ -#line 584 "ctangle.w" +#line 589 "ctangle.w" static boolean output_defs_seen= false; /*:52*//*57:*/ -#line 696 "ctangle.w" +#line 701 "ctangle.w" static char translit[128][translit_length]; /*:57*//*62:*/ -#line 775 "ctangle.w" +#line 777 "ctangle.w" static eight_bits ccode[256]; /*:62*//*66:*/ -#line 835 "ctangle.w" +#line 837 "ctangle.w" static boolean comment_continues= false; /*:66*//*68:*/ -#line 872 "ctangle.w" +#line 874 "ctangle.w" static name_pointer cur_section_name; static boolean no_where; /*:68*//*82:*/ -#line 1189 "ctangle.w" +#line 1188 "ctangle.w" static text_pointer cur_text; static eight_bits next_control; @@ -384,57 +389,57 @@ extern void common_init(void); extern void print_stats(void); /*:16*//*30:*/ -#line 245 "ctangle.w" +#line 246 "ctangle.w" static void store_two_bytes(sixteen_bits); /*:30*//*35:*/ -#line 328 "ctangle.w" +#line 330 "ctangle.w" static void push_level(name_pointer); static void pop_level(boolean); /*:35*//*39:*/ -#line 401 "ctangle.w" +#line 403 "ctangle.w" static void get_output(void); /*:39*//*44:*/ -#line 477 "ctangle.w" +#line 479 "ctangle.w" static void flush_buffer(void); /*:44*//*49:*/ -#line 551 "ctangle.w" +#line 556 "ctangle.w" static void phase_two(void); /*:49*//*53:*/ -#line 587 "ctangle.w" +#line 592 "ctangle.w" static void output_defs(void); static void out_char(eight_bits); /*:53*//*65:*/ -#line 815 "ctangle.w" +#line 817 "ctangle.w" static eight_bits skip_ahead(void); static boolean skip_comment(boolean); /*:65*//*70:*/ -#line 922 "ctangle.w" +#line 924 "ctangle.w" static eight_bits get_next(void); /*:70*//*84:*/ -#line 1215 "ctangle.w" +#line 1214 "ctangle.w" static void scan_repl(eight_bits); /*:84*//*91:*/ -#line 1396 "ctangle.w" +#line 1397 "ctangle.w" static void scan_section(void); /*:91*//*99:*/ -#line 1477 "ctangle.w" +#line 1474 "ctangle.w" static void phase_one(void); /*:99*//*101:*/ -#line 1511 "ctangle.w" +#line 1507 "ctangle.w" static void skip_limbo(void); /*:101*/ @@ -451,28 +456,28 @@ char**av) argc= ac;argv= av; program= ctangle; /*21:*/ -#line 137 "ctangle.w" +#line 139 "ctangle.w" text_info->tok_start= tok_ptr= tok_mem; text_ptr= text_info+1;text_ptr->tok_start= tok_mem; /*:21*//*23:*/ -#line 147 "ctangle.w" +#line 149 "ctangle.w" init_node(name_dir); /*:23*//*27:*/ -#line 202 "ctangle.w" +#line 203 "ctangle.w" last_unnamed= text_info;text_info->text_link= macro; /*:27*//*46:*/ -#line 497 "ctangle.w" +#line 499 "ctangle.w" cur_out_file= end_output_files= output_files+max_files; /*:46*//*58:*/ -#line 699 "ctangle.w" +#line 704 "ctangle.w" { int i; @@ -480,7 +485,7 @@ for(i= 0;i<128;i++)sprintf(translit[i],"X%02X",(unsigned int)(128+i)); } /*:58*//*63:*/ -#line 778 "ctangle.w" +#line 780 "ctangle.w" { int c; for(c= 0;c<256;c++)ccode[c]= ignore; @@ -500,7 +505,7 @@ ccode['<']= ccode['(']= section_name; ccode['\'']= ord; /*:63*//*78:*/ -#line 1111 "ctangle.w" +#line 1112 "ctangle.w" section_text[0]= ' '; /*:78*/ @@ -514,7 +519,7 @@ return wrap_up(); } /*:2*//*24:*/ -#line 153 "ctangle.w" +#line 155 "ctangle.w" boolean names_match( name_pointer p, @@ -522,12 +527,11 @@ const char*first, size_t l, eight_bits t) {(void)t; -if(length(p)!=l)return false; -return!strncmp(first,p->byte_start,l); +return length(p)==l&&strncmp(first,p->byte_start,l)==0; } /*:24*//*25:*/ -#line 169 "ctangle.w" +#line 170 "ctangle.w" void init_node( @@ -539,7 +543,7 @@ void init_p(name_pointer p,eight_bits t){(void)p;(void)t;} /*:25*//*29:*/ -#line 235 "ctangle.w" +#line 236 "ctangle.w" static void store_two_bytes( @@ -551,7 +555,7 @@ if(tok_ptr+2> tok_mem_end)overflow("token"); } /*:29*//*34:*/ -#line 313 "ctangle.w" +#line 315 "ctangle.w" static void push_level( @@ -568,7 +572,7 @@ cur_section= 0; } /*:34*//*36:*/ -#line 336 "ctangle.w" +#line 338 "ctangle.w" static void pop_level( @@ -584,7 +588,7 @@ if(stack_ptr> stack)cur_state= *stack_ptr; } /*:36*//*38:*/ -#line 372 "ctangle.w" +#line 374 "ctangle.w" static void get_output(void) @@ -607,7 +611,7 @@ switch(a/024000){ case 0:cur_val= a;out_char(identifier);break; case 1:if(a==output_defs_flag)output_defs(); else/*40:*/ -#line 406 "ctangle.w" +#line 408 "ctangle.w" { a-= 024000; @@ -621,7 +625,7 @@ goto restart; } /*:40*/ -#line 393 "ctangle.w" +#line 395 "ctangle.w" break; default:cur_val= a-050000;if(cur_val> 0)cur_section= cur_val; @@ -631,7 +635,7 @@ out_char(section_number); } /*:38*//*43:*/ -#line 464 "ctangle.w" +#line 466 "ctangle.w" static void flush_buffer(void) @@ -646,29 +650,30 @@ cur_line++; } /*:43*//*48:*/ -#line 516 "ctangle.w" +#line 518 "ctangle.w" static void phase_two(void){ +phase= 2; web_file_open= false; cur_line= 1; /*33:*/ -#line 302 "ctangle.w" +#line 304 "ctangle.w" stack_ptr= stack+1;cur_name= name_dir;cur_repl= text_info->text_link+text_info; cur_byte= cur_repl->tok_start;cur_end= (cur_repl+1)->tok_start;cur_section= 0; /*:33*/ -#line 521 "ctangle.w" +#line 524 "ctangle.w" /*51:*/ -#line 580 "ctangle.w" +#line 585 "ctangle.w" if(!output_defs_seen) output_defs(); /*:51*/ -#line 522 "ctangle.w" +#line 525 "ctangle.w" if(text_info->text_link==macro&&cur_out_file==end_output_files){ fputs("\n! No program text was specified.",stdout);mark_harmless; @@ -676,8 +681,10 @@ fputs("\n! No program text was specified.",stdout);mark_harmless; } else{ if(cur_out_file==end_output_files){ -if(show_progress) +if(show_progress){ printf("\nWriting the output file (%s):",C_file_name); +update_terminal; +} } else{ if(show_progress){ @@ -691,7 +698,7 @@ if(text_info->text_link==macro)goto writeloop; while(stack_ptr> stack)get_output(); flush_buffer(); writeloop:/*50:*/ -#line 557 "ctangle.w" +#line 562 "ctangle.w" for(an_output_file= end_output_files;an_output_file> cur_out_file;){ an_output_file--; @@ -703,7 +710,7 @@ fatal("! Cannot open output file ",output_file_name); if(show_progress){printf("\n(%s)",output_file_name);update_terminal;} cur_line= 1; stack_ptr= stack+1; -cur_name= (*an_output_file); +cur_name= *an_output_file; cur_repl= (text_pointer)cur_name->equiv; cur_byte= cur_repl->tok_start; cur_end= (cur_repl+1)->tok_start; @@ -712,7 +719,7 @@ flush_buffer(); } /*:50*/ -#line 543 "ctangle.w" +#line 548 "ctangle.w" if(show_happiness){ if(show_progress)new_line; @@ -722,7 +729,7 @@ fputs("Done.",stdout); } /*:48*//*54:*/ -#line 594 "ctangle.w" +#line 599 "ctangle.w" static void output_defs(void) @@ -762,7 +769,7 @@ pop_level(false); } /*:54*//*55:*/ -#line 637 "ctangle.w" +#line 642 "ctangle.w" static void out_char( @@ -775,25 +782,22 @@ case'\n':if(protect&&out_state!=verbatim)C_putc(' '); if(protect||out_state==verbatim)C_putc('\\'); flush_buffer();if(out_state!=verbatim)out_state= normal;break; /*59:*/ -#line 705 "ctangle.w" +#line 710 "ctangle.w" case identifier: if(out_state==num_or_id)C_putc(' '); -j= (cur_val+name_dir)->byte_start; -k= (cur_val+name_dir+1)->byte_start; -while(jbyte_start,k= (cur_val+name_dir+1)->byte_start; +j 0)C_printf("/*%d:*/",cur_val); @@ -804,12 +808,12 @@ cur_char= '\n'; goto restart; }else{ sixteen_bits a; -a= 0400**cur_byte++; +a= *cur_byte++*0400; a+= *cur_byte++; C_printf("\n#line %d \"",a); -cur_val= *cur_byte++; -cur_val= 0400*(cur_val-0200)+*cur_byte++; +cur_val= (*cur_byte++-0200)*0400; +cur_val+= *cur_byte++; for(j= (cur_val+name_dir)->byte_start,k= (cur_val+name_dir+1)->byte_start; j');C_putc('*');out_state= normal; break; /*:56*/ -#line 650 "ctangle.w" +#line 655 "ctangle.w" case'=':case'>':C_putc(cur_char);C_putc(' '); out_state= normal;break; @@ -863,7 +867,7 @@ default:C_putc(cur_char);out_state= normal;break; } /*:55*//*64:*/ -#line 799 "ctangle.w" +#line 801 "ctangle.w" static eight_bits skip_ahead(void) @@ -881,7 +885,7 @@ if(c!=ignore||*(loc-1)=='>')return c; } /*:64*//*67:*/ -#line 838 "ctangle.w" +#line 840 "ctangle.w" static boolean skip_comment( boolean is_long_comment) @@ -915,7 +919,7 @@ else loc++; } /*:67*//*69:*/ -#line 879 "ctangle.w" +#line 881 "ctangle.w" static eight_bits get_next(void) @@ -929,9 +933,10 @@ if(get_line()==false)return new_section; else if(print_where&&!no_where){ print_where= false; /*85:*/ -#line 1221 "ctangle.w" +#line 1224 "ctangle.w" { +eight_bits a; store_two_bytes(0150000); if(changing&&include_depth==change_depth){ id_first= change_file_name; @@ -941,12 +946,11 @@ id_first= cur_file_name; store_two_bytes((sixteen_bits)cur_line); } id_loc= id_first+strlen(id_first); -{int a_l= id_lookup(id_first,id_loc,0)-name_dir;app_repl((a_l/0400)+0200); -app_repl(a_l%0400);} +store_id(a); } /*:85*/ -#line 891 "ctangle.w" +#line 893 "ctangle.w" } else return'\n'; @@ -960,7 +964,7 @@ else continue; } loc++; if(xisdigit(c)||c=='.')/*73:*/ -#line 963 "ctangle.w" +#line 965 "ctangle.w" { boolean hex_flag= false; id_first= loc-1; @@ -994,13 +998,13 @@ return constant; } /*:73*/ -#line 903 "ctangle.w" +#line 905 "ctangle.w" else if(c=='\''||c=='"' ||((c=='L'||c=='u'||c=='U')&&(*loc=='\''||*loc=='"')) ||((c=='u'&&*loc=='8')&&(*(loc+1)=='\''||*(loc+1)=='"'))) /*74:*/ -#line 1000 "ctangle.w" +#line 1002 "ctangle.w" { char delim= c; id_first= section_text+1; @@ -1044,11 +1048,11 @@ return string; } /*:74*/ -#line 907 "ctangle.w" +#line 909 "ctangle.w" else if(isalpha(c)||isxalpha(c)||ishigh(c)) /*72:*/ -#line 954 "ctangle.w" +#line 956 "ctangle.w" { id_first= --loc; do @@ -1059,11 +1063,11 @@ id_loc= loc;return identifier; } /*:72*/ -#line 909 "ctangle.w" +#line 911 "ctangle.w" else if(c=='@')/*75:*/ -#line 1045 "ctangle.w" -{ +#line 1047 "ctangle.w" + switch(c= ccode[(eight_bits)*loc++]){ case ignore:continue; case translit_code:err_print("! Use @l in limbo only");continue; @@ -1077,13 +1081,12 @@ continue; case section_name: cur_section_name_char= *(loc-1); /*77:*/ -#line 1091 "ctangle.w" +#line 1092 "ctangle.w" { -char*k; +char*k= section_text; /*79:*/ -#line 1113 "ctangle.w" +#line 1114 "ctangle.w" -k= section_text; while(true){ if(loc> limit&&get_line()==false){ err_print("! Input ended in section name"); @@ -1128,7 +1131,7 @@ printf("...");mark_harmless; if(*k==' '&&k> section_text)k--; /*:79*/ -#line 1093 "ctangle.w" +#line 1094 "ctangle.w" if(k-section_text> 3&&strncmp(k-2,"...",3)==0) cur_section_name= section_lookup(section_text+1,k-3,true); @@ -1137,7 +1140,7 @@ else cur_section_name= section_lookup(section_text+1,k,false); if(cur_section_name_char=='(') /*47:*/ -#line 501 "ctangle.w" +#line 503 "ctangle.w" { for(an_output_file= cur_out_file; @@ -1151,30 +1154,29 @@ else overflow("output files"); } /*:47*/ -#line 1101 "ctangle.w" +#line 1102 "ctangle.w" return section_name; } /*:77*/ -#line 1058 "ctangle.w" +#line 1060 "ctangle.w" case string:/*81:*/ #line 1159 "ctangle.w" -{ + id_first= loc++;*(limit+1)= '@';*(limit+2)= '>'; while(*loc!='@'||*(loc+1)!='>')loc++; if(loc>=limit)err_print("! Verbatim string didn't end"); id_loc= loc;loc+= 2; return string; -} /*:81*/ -#line 1059 "ctangle.w" +#line 1061 "ctangle.w" case ord:/*76:*/ -#line 1071 "ctangle.w" +#line 1072 "ctangle.w" id_first= loc; if(*loc=='\\') @@ -1196,14 +1198,13 @@ loc++; return ord; /*:76*/ -#line 1060 "ctangle.w" +#line 1062 "ctangle.w" default:return c; } -} /*:75*/ -#line 910 "ctangle.w" +#line 912 "ctangle.w" else if(xisspace(c)){ if(!preprocessing||loc> limit)continue; @@ -1212,7 +1213,7 @@ else return' '; } else if(c=='#'&&loc==buffer+1)preprocessing= true; mistake:/*71:*/ -#line 931 "ctangle.w" +#line 933 "ctangle.w" switch(c){ case'+':if(*loc=='+')compress(plus_plus);break; @@ -1237,14 +1238,14 @@ case'!':if(*loc=='=')compress(non_eq);break; } /*:71*/ -#line 917 "ctangle.w" +#line 919 "ctangle.w" return c; } } /*:69*//*83:*/ -#line 1193 "ctangle.w" +#line 1192 "ctangle.w" static void scan_repl( @@ -1252,9 +1253,10 @@ eight_bits t) { sixteen_bits a; if(t==section_name)/*85:*/ -#line 1221 "ctangle.w" +#line 1224 "ctangle.w" { +eight_bits a; store_two_bytes(0150000); if(changing&&include_depth==change_depth){ id_first= change_file_name; @@ -1264,24 +1266,21 @@ id_first= cur_file_name; store_two_bytes((sixteen_bits)cur_line); } id_loc= id_first+strlen(id_first); -{int a_l= id_lookup(id_first,id_loc,0)-name_dir;app_repl((a_l/0400)+0200); -app_repl(a_l%0400);} +store_id(a); } /*:85*/ -#line 1199 "ctangle.w" +#line 1198 "ctangle.w" while(true)switch(a= get_next()){ /*86:*/ -#line 1236 "ctangle.w" +#line 1239 "ctangle.w" -case identifier:a= id_lookup(id_first,id_loc,0)-name_dir; -app_repl((a/0400)+0200); -app_repl(a%0400);break; +case identifier:store_id(a);break; case section_name:if(t!=section_name)goto done; else{ /*87:*/ -#line 1269 "ctangle.w" +#line 1270 "ctangle.w" { char*try_loc= loc; while(*try_loc==' '&&try_loctok_start= tok_ptr; } /*:83*//*90:*/ -#line 1363 "ctangle.w" +#line 1364 "ctangle.w" static void scan_section(void) @@ -1460,7 +1459,7 @@ printf("*%d",section_count);update_terminal; next_control= ignore; while(true){ /*92:*/ -#line 1404 "ctangle.w" +#line 1405 "ctangle.w" while(next_controltext_link= macro; -} /*:93*/ -#line 1379 "ctangle.w" +#line 1380 "ctangle.w" continue; } @@ -1502,14 +1498,14 @@ p= name_dir;break; if(next_control==section_name){ p= cur_section_name; /*94:*/ -#line 1436 "ctangle.w" +#line 1434 "ctangle.w" while((next_control= get_next())=='+'); if(next_control!='='&&next_control!=eq_eq) continue; /*:94*/ -#line 1387 "ctangle.w" +#line 1388 "ctangle.w" break; } @@ -1517,23 +1513,23 @@ return; } no_where= print_where= false; /*95:*/ -#line 1441 "ctangle.w" +#line 1439 "ctangle.w" /*96:*/ -#line 1446 "ctangle.w" +#line 1444 "ctangle.w" store_two_bytes((sixteen_bits)(0150000+section_count)); /*:96*/ -#line 1442 "ctangle.w" +#line 1440 "ctangle.w" scan_repl(section_name); /*97:*/ -#line 1450 "ctangle.w" +#line 1448 "ctangle.w" if(p==name_dir||p==NULL){ -(last_unnamed)->text_link= cur_text-text_info;last_unnamed= cur_text; +last_unnamed->text_link= cur_text-text_info;last_unnamed= cur_text; } else if(p->equiv==(void*)text_info)p->equiv= (void*)cur_text; @@ -1547,16 +1543,16 @@ cur_text->text_link= section_flag; /*:97*/ -#line 1444 "ctangle.w" +#line 1442 "ctangle.w" /*:95*/ -#line 1393 "ctangle.w" +#line 1394 "ctangle.w" } /*:90*//*98:*/ -#line 1465 "ctangle.w" +#line 1463 "ctangle.w" static void phase_one(void){ @@ -1566,26 +1562,24 @@ reset_input(); skip_limbo(); while(!input_has_ended)scan_section(); check_complete(); -phase= 2; } /*:98*//*100:*/ -#line 1482 "ctangle.w" +#line 1479 "ctangle.w" static void skip_limbo(void) { -char c; while(true){ if(loc> limit&&get_line()==false)return; *(limit+1)= '@'; while(*loc!='@')loc++; if(loc++<=limit){ -c= *loc++; +char c= *loc++; if(ccode[(eight_bits)c]==new_section)break; switch(ccode[(eight_bits)c]){ case translit_code:/*102:*/ -#line 1513 "ctangle.w" +#line 1509 "ctangle.w" while(xisspace(*loc)&&loc@/ @@ -126,7 +126,9 @@ typedef struct { } text; typedef text *text_pointer; -@ @= +@ @d max_texts 2500 /* number of replacement texts, must be less than 10240 */ +@d max_toks 270000 /* number of bytes in compressed \CEE/ code */ +@= static text text_info[max_texts]; static text_pointer text_info_end=text_info+max_texts-1; static text_pointer text_ptr; /* first unused position in |text_info| */ @@ -156,9 +158,8 @@ name_pointer p, /* points to the proposed match */ const char *first, /* position of first character of string */ size_t l, /* length of identifier */ eight_bits t) /* not used by \.{TANGLE} */ -{@+(void)t; - if (length(p)!=l) return false; - return !strncmp(first,p->byte_start,l); +{@+(void)t;@/ + return length(p)==l && strncmp(first,p->byte_start,l)==0; } @ The common lookup routine refers to separate routines |init_node| and @@ -227,7 +228,7 @@ or line breaks allowed between them (the \.{@@\&} operation of \.{CWEB}). @d string 02 /* takes the place of ASCII \.{STX} */ @d constant 03 /* takes the place of ASCII \.{ETX} */ @d join 0177 /* takes the place of ASCII \.{DEL} */ -@d output_defs_flag (2*024000-1) +@d output_defs_flag (2*024000-1) /* |024000==(0250-0200)*0400| */ @ The following procedure is used to enter a two-byte value into |tok_mem| when a replacement text is being generated. @@ -280,7 +281,8 @@ typedef struct { } output_state; typedef output_state *stack_pointer; -@ @d cur_end cur_state.end_field /* current ending location in |tok_mem| */ +@ @d stack_size 50 /* number of simultaneous levels of macro expansion */ +@d cur_end cur_state.end_field /* current ending location in |tok_mem| */ @d cur_byte cur_state.byte_field /* location of next output byte in |tok_mem|*/ @d cur_name cur_state.name_field /* pointer to current name being expanded */ @d cur_repl cur_state.repl_field /* pointer to current replacement text */ @@ -516,6 +518,7 @@ output. @c static void phase_two (void) { + phase=2; web_file_open=false; cur_line=1; @@; @@ -525,9 +528,11 @@ phase_two (void) { @.No program text...@> } else { - if(cur_out_file==end_output_files) { - if(show_progress) + if (cur_out_file==end_output_files) { + if (show_progress) { printf("\nWriting the output file (%s):",C_file_name); + update_terminal; + } } else { if (show_progress) { @@ -565,7 +570,7 @@ for (an_output_file=end_output_files; an_output_file>cur_out_file;) { if (show_progress) { printf("\n(%s)",output_file_name); update_terminal; } cur_line=1; stack_ptr=stack+1; - cur_name=(*an_output_file); + cur_name=*an_output_file; cur_repl=(text_pointer)cur_name->equiv; cur_byte=cur_repl->tok_start; cur_end=(cur_repl+1)->tok_start; @@ -705,14 +710,11 @@ static char translit[128][translit_length]; @ @=@t\1\quad@> case identifier: if (out_state==num_or_id) C_putc(' '); - j=(cur_val+name_dir)->byte_start; - k=(cur_val+name_dir+1)->byte_start; - while (jbyte_start, k=(cur_val+name_dir+1)->byte_start; + j else C_printf("%s",translit[(eight_bits)(*j)-0200]); - j++; - } out_state=num_or_id; break; @ @=@t\1\quad@> @@ -725,12 +727,12 @@ case section_number: goto restart; } else { sixteen_bits a; - a=0400* *cur_byte++; + a=*cur_byte++ *0400; a+=*cur_byte++; /* gets the line number */ C_printf("\n#line %d \"",a); @:line}{\.{\#line}@> - cur_val=*cur_byte++; - cur_val=0400*(cur_val-0200)+ *cur_byte++; /* points to the file name */ + cur_val=(*cur_byte++-0200)*0400; + cur_val+=*cur_byte++; /* points to the file name */ for (j=(cur_val+name_dir)->byte_start, k=(cur_val+name_dir+1)->byte_start; j=@+static eight_bits get_next(void); @ The following code assigns values to the combinations \.{++}, -\.{--}, \.{->}, \.{>=}, \.{<=}, \.{==}, \.{<<}, \.{>>}, \.{!=}, \.{||} and -\.{\&\&}, and to the \CPLUSPLUS/ +\.{--}, \.{->}, \.{>=}, \.{<=}, \.{==}, \.{<<}, \.{>>}, \.{!=}, %\.{||} +\.{\v\v} and~\.{\&\&}, and to the \CPLUSPLUS/ combinations \.{...}, \.{::}, \.{.*} and \.{->*}. The compound assignment operators (e.g., \.{+=}) are treated as separate tokens. @@ -1042,24 +1044,23 @@ convention, but do not allow the string to be longer than |longest_name|. @ After an \.{@@} sign has been scanned, the next character tells us whether there is more work to do. -@= { - switch(c=ccode[(eight_bits)*loc++]) { - case ignore: continue; - case translit_code: err_print("! Use @@l in limbo only"); continue; +@= +switch(c=ccode[(eight_bits)*loc++]) { + case ignore: continue; + case translit_code: err_print("! Use @@l in limbo only"); continue; @.Use @@l in limbo...@> - case control_text: while ((c=skip_ahead())=='@@'); - /* only \.{@@@@} and \.{@@>} are expected */ - if (*(loc-1)!='>') - err_print("! Double @@ should be used in control text"); + case control_text: while ((c=skip_ahead())=='@@'); + /* only \.{@@@@} and \.{@@>} are expected */ + if (*(loc-1)!='>') + err_print("! Double @@ should be used in control text"); @.Double @@ should be used...@> - continue; - case section_name: - cur_section_name_char=*(loc-1); - @@; - case string: @@; - case ord: @@; - default: return c; - } + continue; + case section_name: + cur_section_name_char=*(loc-1); + @@; + case string: @@; + case ord: @@; + default: return c; } @ After scanning a valid ASCII constant that follows @@ -1089,7 +1090,7 @@ thus, \.{@@'\\nopq'} gives the same result as \.{@@'\\n'}. return ord; @ @= { - char *k; /* pointer into |section_text| */ + char *k=section_text; /* pointer into |section_text| */ @@; if (k-section_text>3 && strncmp(k-2,"...",3)==0) cur_section_name=section_lookup(section_text+1,k-3,true); @@ -1111,7 +1112,6 @@ character of the name.) @=section_text[0]=' '; @ @= -k=section_text; while (true) { if (loc>limit && get_line()==false) { err_print("! Input ended in section name"); @@ -1156,14 +1156,13 @@ have |*(loc-1)==string|; we set |id_first| to the beginning of the string itself, and |id_loc| to its ending-plus-one location in the buffer. We also set |loc| to the position just after the ending delimiter. -@= { - id_first=loc++; *(limit+1)='@@'; *(limit+2)='>'; - while (*loc!='@@' || *(loc+1)!='>') loc++; - if (loc>=limit) err_print("! Verbatim string didn't end"); +@= +id_first=loc++; *(limit+1)='@@'; *(limit+2)='>'; +while (*loc!='@@' || *(loc+1)!='>') loc++; +if (loc>=limit) err_print("! Verbatim string didn't end"); @.Verbatim string didn't end@> - id_loc=loc; loc+=2; - return string; -} +id_loc=loc; loc+=2; +return string; @* Scanning a macro definition. The rules for generating the replacement texts corresponding to macros and @@ -1184,7 +1183,7 @@ ANSI \CEE/ preprocessor sometimes requires it. acted, |cur_text| will point to the replacement text just generated, and |next_control| will contain the control code that terminated the activity. -@d app_repl(c) {if (tok_ptr==tok_mem_end) overflow("token"); *tok_ptr++=c;} +@d app_repl(c) {if (tok_ptr==tok_mem_end) overflow("token"); *(tok_ptr++)=c;} @= static text_pointer cur_text; /* replacement text formed by |scan_repl| */ @@ -1198,7 +1197,7 @@ eight_bits t) sixteen_bits a; /* the current token */ if (t==section_name) @@; while (true) switch (a=get_next()) { - @@@; @@ -1218,8 +1217,13 @@ eight_bits t) to |0150000|; then the numeric line number; then a pointer to the file name. +@d store_id(a) a=id_lookup(id_first,id_loc,0)-name_dir;@/ + app_repl((a / 0400)+0200); + app_repl(a % 0400); + @= { + eight_bits a; /* shadow variable |a| */ store_two_bytes(0150000); if (changing && include_depth==change_depth) { /* correction made Feb 2017 */ id_first=change_file_name; @@ -1229,14 +1233,11 @@ file name. store_two_bytes((sixteen_bits)cur_line); } id_loc=id_first+strlen(id_first); - {int a_l=id_lookup(id_first,id_loc,0)-name_dir; app_repl((a_l / 0400)+0200); - app_repl(a_l % 0400);} + store_id(a); } @ @=@t\1\quad@> -case identifier: a=id_lookup(id_first,id_loc,0)-name_dir; - app_repl((a / 0400)+0200); - app_repl(a % 0400); break; +case identifier: store_id(a); break; case section_name: if (t!=section_name) goto done; else { @@; @@ -1375,11 +1376,11 @@ scan_section(void) while (true) { @@; - if (next_control == definition) { /* \.{@@d} */ + if (next_control == definition) { /* \.{@@d} */ @@; continue; } - if (next_control == begin_C) { /* \.{@@c} or \.{@@p} */ + if (next_control == begin_C) { /* \.{@@c} or \.{@@p} */ p=name_dir; break; } if (next_control == section_name) { /* \.{@@<} or \.{@@(} */ @@ -1408,22 +1409,19 @@ while (next_control= { - while ((next_control=get_next())=='\n'); /* allow newline before definition */ - if (next_control!=identifier) { - err_print("! Definition flushed, must start with identifier"); +@ @= +while ((next_control=get_next())=='\n'); /* allow newline before definition */ +if (next_control!=identifier) { + err_print("! Definition flushed, must start with identifier"); @.Definition flushed...@> - continue; - } - app_repl(((a=id_lookup(id_first,id_loc,0)-name_dir) / 0400)+0200); - /* append the lhs */ - app_repl(a % 0400); - if (*loc!='(') { /* identifier must be separated from replacement text */ - app_repl(string); app_repl(' '); app_repl(string); - } - scan_repl(macro); - cur_text->text_link=macro; + continue; +} +store_id(a); /* append the lhs */ +if (*loc!='(') { /* identifier must be separated from replacement text */ + app_repl(string); app_repl(' '); app_repl(string); } +scan_repl(macro); +cur_text->text_link=macro; @ If the section name is not followed by \.{=} or \.{+=}, no \CEE/ code is forthcoming: the section is being cited, not being @@ -1449,7 +1447,7 @@ store_two_bytes((sixteen_bits)(0150000+section_count)); @ @= if (p==name_dir||p==NULL) { /* unnamed section, or bad section name */ - (last_unnamed)->text_link=cur_text-text_info; last_unnamed=cur_text; + last_unnamed->text_link=cur_text-text_info; last_unnamed=cur_text; } else if (p->equiv==(void *)text_info) p->equiv=(void *)cur_text; /* first section of this name */ @@ -1471,7 +1469,6 @@ phase_one(void) { skip_limbo(); while (!input_has_ended) scan_section(); check_complete(); - phase=2; } @ @=@+static void phase_one(void); @@ -1483,13 +1480,12 @@ processing is straightforward. static void skip_limbo(void) { - char c; while (true) { if (loc>limit && get_line()==false) return; *(limit+1)='@@'; while (*loc!='@@') loc++; if (loc++<=limit) { - c=*loc++; + char c=*loc++; if (ccode[(eight_bits)c]==new_section) break; switch (ccode[(eight_bits)c]) { case translit_code: @@; break; diff --git a/cweav-bs.ch b/cweav-bs.ch index ee919d7..c05ce06 100644 --- a/cweav-bs.ch +++ b/cweav-bs.ch @@ -20,12 +20,12 @@ This file contributed by Barry Schwartz, trashman@crud.mn.org, 28 Jun 94. The ``banner line'' defined here should be changed whenever \.{CWEAVE} is modified. -@d banner "This is CWEAVE (Version 4.3)" +@d banner "This is CWEAVE (Version 4.4)" @y The ``banner line'' defined here should be changed whenever \.{CWEAVE} is modified. -@d banner "This is CWEAVE (Version 4.3pc/big)" +@d banner "This is CWEAVE (Version 4.4pc/big)" @z @@ -219,7 +219,7 @@ static char huge* cur_byte; /* index into |byte_mem| */ @x Section 264. -switch (cur_name->ilk) {@+char *j; +switch (cur_name->ilk) {@+char *j;@+@t}\6{\4@> @y -switch (cur_name->ilk) {@+char huge* j; +switch (cur_name->ilk) {@+char huge* j;@+@t}\6{\4@> @z diff --git a/cweav-man.ch b/cweav-man.ch index 6cfcc8f..366cda6 100644 --- a/cweav-man.ch +++ b/cweav-man.ch @@ -16,7 +16,7 @@ under the terms of a permission notice identical to this one. } @y \def\botofcontents{\vfill\titlefalse} -\def\contentspagenumber{109} +\def\contentspagenumber{108} \def\title{APPENDIX F: CWEAVE} \let\K=\leftarrow @z diff --git a/cweav-pc.ch b/cweav-pc.ch index f0f7770..0c95dcf 100644 --- a/cweav-pc.ch +++ b/cweav-pc.ch @@ -11,18 +11,18 @@ that allows >64K arrays. (If you need lots more bytes, try the alternate change files that have -bs in their name instead of -pc.) @x section 1 -@d banner "This is CWEAVE (Version 4.3)" +@d banner "This is CWEAVE (Version 4.4)" @y -@d banner "This is CWEAVE (Version 4.3pc)" +@d banner "This is CWEAVE (Version 4.4pc)" @z @x section 17 -@d max_bytes 1000000 /* the number of bytes in identifiers, +@d max_bytes 90000 /* the number of bytes in identifiers, @y @d max_bytes (unsigned)60000 /* the number of bytes in identifiers, @z @x -@d max_refs 65535 /* number of cross-references; must be less than 65536 */ +@d max_refs 20000 /* number of cross-references; must be less than 65536 */ @y @d max_refs 10000 /* number of cross-references; must be less than 65536 */ @z diff --git a/cweav-ql.ch b/cweav-ql.ch index fa809a5..d10fc1d 100644 --- a/cweav-ql.ch +++ b/cweav-ql.ch @@ -7,15 +7,15 @@ ex cc;"-v -h -c =500000 cweave_c" @x -\def\title{CWEAVE (Version 4.3)} +\def\title{CWEAVE (Version 4.4)} @y -\def\title{CWEAVE (QL Version 4.3)} +\def\title{CWEAVE (QL Version 4.4)} @z @x section 1 -@d banner "This is CWEAVE (Version 4.3)" +@d banner "This is CWEAVE (Version 4.4)" @y -@d banner "This is CWEAVE (QL Version 4.3)" +@d banner "This is CWEAVE (QL Version 4.4)" @z @x diff --git a/cweav-vms.ch b/cweav-vms.ch index a4416a7..f443d7e 100644 --- a/cweav-vms.ch +++ b/cweav-vms.ch @@ -13,9 +13,9 @@ modified: (also modified by Don Knuth to keep version numbers uptodate) @x section 1 (01-FEB-1992 ST) -@d banner "This is CWEAVE (Version 4.3)" +@d banner "This is CWEAVE (Version 4.4)" @y -@d banner "This is CWEAVE (VAX/VMS Version 4.3)" +@d banner "This is CWEAVE (VAX/VMS Version 4.4)" @z @x section 4 (01-FEB-1992 ST) diff --git a/cweav-w32.ch b/cweav-w32.ch index 2fec067..013ca70 100644 --- a/cweav-w32.ch +++ b/cweav-w32.ch @@ -2,9 +2,9 @@ This is the change file for CWEB's CWEAVE under Win32 (Contributed by Fabrice Popineau, February 2002) @x section 1 -@d banner "This is CWEAVE (Version 4.3)" +@d banner "This is CWEAVE (Version 4.4)" @y -@d banner "This is CWEAVE (Version 4.3win32)" +@d banner "This is CWEAVE (Version 4.4win32)" @z @x diff --git a/cweave.w b/cweave.w index 30bcedb..ffd835e 100644 --- a/cweave.w +++ b/cweave.w @@ -2,7 +2,7 @@ % This program by Silvio Levy and Donald E. Knuth % is based on a program by Knuth. % It is distributed WITHOUT ANY WARRANTY, express or implied. -% Version 4.3 --- May 2021 +% Version 4.4 --- June 2021 % Copyright (C) 1987,1990,1993,2000 Silvio Levy and Donald E. Knuth @@ -32,11 +32,11 @@ \def\skipxTeX{\\{skip\_\TEX/}} \def\copyxTeX{\\{copy\_\TEX/}} -\def\title{CWEAVE (Version 4.3)} +\def\title{CWEAVE (Version 4.4)} \def\topofcontents{\null\vfill \centerline{\titlefont The {\ttitlefont CWEAVE} processor} \vskip 15pt - \centerline{(Version 4.3)} + \centerline{(Version 4.4)} \vfill} \def\botofcontents{\vfill \noindent @@ -67,7 +67,7 @@ Crusius, and others who have contributed improvements. The ``banner line'' defined here should be changed whenever \.{CWEAVE} is modified. -@d banner "This is CWEAVE (Version 4.3)" +@d banner "This is CWEAVE (Version 4.4)" @c @@/ @@ -116,8 +116,8 @@ handle \TEX/, so they should be sufficient for most applications of \.{CWEAVE}. @d line_length 80 /* lines of \TEX/ output have at most this many characters; should be less than 256 */ -@d max_refs 65535 /* number of cross-references; must be less than 65536 */ -@d max_scraps 10000 /* number of tokens in \CEE/ texts being parsed */ +@d max_refs 20000 /* number of cross-references; must be less than 65536 */ +@d max_scraps 2000 /* number of tokens in \CEE/ texts being parsed */ @* Data structures exclusive to {\tt CWEAVE}. As explained in \.{common.w}, the field of a |name_info| structure @@ -152,7 +152,7 @@ formatted. @d roman 1 /* normal index entries have |roman| ilk */ @d wildcard 2 /* user-formatted index entries have |wildcard| ilk */ @d typewriter 3 /* `typewriter type' entries have |typewriter| ilk */ -@d abnormal(a) (a->ilk>typewriter) /* tells if a name is special */ +@d abnormal(a) ((a)->ilk>typewriter) /* tells if a name is special */ @d func_template 4 /* identifiers that can be followed by optional template */ @d custom 5 /* identifiers with user-given control sequence */ @d alfop 22 /* alphabetic operators like \&{and} or \&{not\_eq} */ @@ -167,7 +167,7 @@ formatted. @d delete_like 48 /* \&{delete} */ @d raw_ubin 49 /* `\.\&' or `\.*' when looking for \&{const} following */ @d const_like 50 /* \&{const}, \&{volatile} */ -@d raw_int 51 /* \&{int}, \&{char}, \dots; also structure and class names */ +@d raw_int 51 /* \&{int}, \&{char}, \dots; also structure and class names */ @d int_like 52 /* same, when not followed by left parenthesis or \DC\ */ @d case_like 53 /* \&{case}, \&{return}, \&{goto}, \&{break}, \&{continue} */ @d sizeof_like 54 /* \&{sizeof} */ @@ -246,9 +246,9 @@ If one were careful, one could probably make more changes around section @d append_xref(c) if (xref_ptr==xmem_end) overflow("cross-reference"); else (++xref_ptr)->num=c; -@d no_xref (!make_xrefs) -@d is_tiny(p) (length(p)==1) -@d unindexed(a) (ailk>=custom) +@d no_xref !make_xrefs +@d is_tiny(p) length(p)==1 +@d unindexed(a) ((a)ilk>=custom) /* tells if uses of a name are to be indexed */ @= @@ -335,6 +335,11 @@ that is unoccupied by replacement text is called |tok_ptr|, and the first unused location of |tok_start| is called |text_ptr|. Thus, we usually have |*text_ptr==tok_ptr|. +@d max_toks 20000 /* number of symbols in \CEE/ texts being parsed; + must be less than 65536 */ +@d max_texts 4000 /* number of phrases in \CEE/ texts being parsed; + must be less than 10240 */ + @= static token tok_mem[max_toks]; /* tokens */ static token_pointer tok_mem_end = tok_mem+max_toks-1; /* end of |tok_mem| */ @@ -378,14 +383,9 @@ name_pointer p) p->xref=(void *)xmem; } -static void -update_node( -name_pointer p) -{ - p->xref=(void *)xref_ptr; -} +@ And here's a small helper function to simplify the code. -@ @=@+static void update_node(name_pointer p); +@d update_node(p) (p)->xref=(void *)xref_ptr @ We have to get \CEE/'s and \CPLUSPLUS/'s reserved words into the hash table, and the simplest way to do this is @@ -505,7 +505,7 @@ id_lookup("typename",NULL,struct_like); id_lookup("undef",NULL,if_like); id_lookup("union",NULL,struct_like); id_lookup("unsigned",NULL,raw_int); -id_lookup("using",NULL,using_like); +id_lookup("using",NULL,using_like);@/ id_lookup("va_dcl",NULL,decl); /* Berkeley's variable-arg-list convention */ id_lookup("va_list",NULL,raw_int); /* ditto */ id_lookup("virtual",NULL,int_like); @@ -626,11 +626,12 @@ skip_limbo(void) { if (loc>limit && get_line()==false) return; *(limit+1)='@@'; while (*loc!='@@') loc++; /* look for `\.{@@}', then skip two chars */ - if (loc++ <=limit) { int c=ccode[(eight_bits)*loc++]; - if (c==new_section) return; - if (c==noop) skip_restricted(); - else if (c==format_code) @@; - } + if (loc++ <=limit) + switch (ccode[(eight_bits)*loc++]) { + case new_section: return; + case noop: skip_restricted(); break; + case format_code: @@; + } } } @@ -775,8 +776,8 @@ the last character was a \.\\. } @ The following code assigns values to the combinations \.{++}, -\.{--}, \.{->}, \.{>=}, \.{<=}, \.{==}, \.{<<}, \.{>>}, \.{!=}, \.{\v\v}, and -\.{\&\&}, and to the \CPLUSPLUS/ +\.{--}, \.{->}, \.{>=}, \.{<=}, \.{==}, \.{<<}, \.{>>}, \.{!=}, %\.{||} +\.{\v\v} and~\.{\&\&}, and to the \CPLUSPLUS/ combinations \.{...}, \.{::}, \.{.*} and \.{->*}. The compound assignment operators (e.g., \.{+=}) are treated as separate tokens. @@ -828,7 +829,7 @@ On output, the \.{\ } that replaces \.{'} in \CPLUSPLUS/ literals will become Notice that in this section and the next, |id_first| and |id_loc| are pointers into the array |section_text|, not into |buffer|. -@d gather_digits_while(t) while (t || *loc=='\'') +@d gather_digits_while(t) while ((t) || *loc=='\'') if (*loc=='\'') { /* \CPLUSPLUS/-style digit separator */ *id_loc++=' '; loc++; /* insert a little bit of space */ }@+else *id_loc++=*loc++; @@ -935,28 +936,26 @@ convention, but do not allow the string to be longer than |longest_name|. @ After an \.{@@} sign has been scanned, the next character tells us whether there is more work to do. -@= { - c=*loc++; - switch(ccode[(eight_bits)c]) { - case translit_code: err_print("! Use @@l in limbo only"); continue; +@= +switch(ccode[(eight_bits)(c=*loc++)]) { + case translit_code: err_print("! Use @@l in limbo only"); continue; @.Use @@l in limbo...@> - case underline: xref_switch=def_flag; continue; - case trace: tracing=c-'0'; continue; - case xref_roman: case xref_wildcard: case xref_typewriter: case noop: - case TeX_string: skip_restricted(); return ccode[(eight_bits)c]; - case section_name: - @@; - case verbatim: @@; - case ord: @@; - default: return ccode[(eight_bits)c]; - } + case underline: xref_switch=def_flag; continue; + case trace: tracing=c-'0'; continue; + case section_name: + @@; + case verbatim: @@; + case ord: @@; + case xref_roman: case xref_wildcard: case xref_typewriter: case noop: + case TeX_string: skip_restricted(); + default: return ccode[(eight_bits)c]; } @ The occurrence of a section name sets |xref_switch| to zero, because the section name might (for example) follow \&{int}. @= { - char *k; /* pointer into |section_text| */ + char *k=section_text; /* pointer into |section_text| */ cur_section_char=*(loc-1); @@; if (k-section_text>3 && strncmp(k-2,"...",3)==0) @@ -975,7 +974,6 @@ character of the name.) @=section_text[0]=' '; @ @= -k=section_text; while (true) { if (loc>limit && get_line()==false) { err_print("! Input ended in section name"); @@ -1043,14 +1041,13 @@ have |*(loc-1)==verbatim|; we set |id_first| to the beginning of the string itself, and |id_loc| to its ending-plus-one location in the buffer. We also set |loc| to the position just after the ending delimiter. -@= { - id_first=loc++; *(limit+1)='@@'; *(limit+2)='>'; - while (*loc!='@@' || *(loc+1)!='>') loc++; - if (loc>=limit) err_print("! Verbatim string didn't end"); +@= +id_first=loc++; *(limit+1)='@@'; *(limit+2)='>'; +while (*loc!='@@' || *(loc+1)!='>') loc++; +if (loc>=limit) err_print("! Verbatim string didn't end"); @.Verbatim string didn't end@> - id_loc=loc; loc+=2; - return verbatim; -} +id_loc=loc; loc+=2; +return verbatim; @** Phase one processing. We now have accumulated enough subroutines to make it possible to carry out @@ -1077,7 +1074,6 @@ phase_one(void) { @@; changed_section[section_count]=change_exists; /* the index changes if anything does */ - phase=2; /* prepare for second phase */ @@; } @@ -1128,11 +1124,10 @@ static void C_xref( /* makes cross-references for \CEE/ identifiers */ eight_bits spec_ctrl) { - name_pointer p; /* a referenced name */ while (next_control=identifier && next_control<=xref_typewriter) { - if (next_control>identifier) @@; - p=id_lookup(id_first, id_loc,next_control-identifier); new_xref(p); + if (next_control>identifier) @@; + new_xref(id_lookup(id_first,id_loc,next_control-identifier)); } if (next_control==section_name) { section_xref_switch=cite_flag; @@ -1184,8 +1179,8 @@ while (true) { case noop: case section_name: loc-=2; next_control=get_next(); /* scan to \.{@@>} */ if (next_control>=xref_roman && next_control<=xref_typewriter) { - @@; - new_xref(id_lookup(id_first, id_loc,next_control-identifier)); + @@; + new_xref(id_lookup(id_first,id_loc,next_control-identifier)); } break; } @@ -1261,19 +1256,17 @@ discover should be unindexed. definition is found in limbo. @= -{ - if (get_next()!=identifier) - err_print("! Missing left identifier of @@s"); +if (get_next()!=identifier) + err_print("! Missing left identifier of @@s"); @.Missing left identifier...@> - else { - lhs=id_lookup(id_first,id_loc,normal); - if (get_next()!=identifier) - err_print("! Missing right identifier of @@s"); +else { + lhs=id_lookup(id_first,id_loc,normal); + if (get_next()!=identifier) + err_print("! Missing right identifier of @@s"); @.Missing right identifier...@> - else { - rhs=id_lookup(id_first,id_loc,normal); - lhs->ilk=rhs->ilk; - } + else { + rhs=id_lookup(id_first,id_loc,normal); + lhs->ilk=rhs->ilk; } } @@ -1281,7 +1274,7 @@ definition is found in limbo. |next_control>=begin_C|. @= -if (next_control<=section_name) { /* |begin_C| or |section_name| */ +if (next_control<=section_name) { /* |begin_C| or |section_name| */ if (next_control==begin_C) section_xref_switch=0; else { section_xref_switch=def_flag; @@ -1315,8 +1308,7 @@ name_pointer p) /* print anomalies in subtree |p| */ if (p) { section_check(p->llink); cur_xref=(xref_pointer)p->xref; - if (cur_xref->num==file_flag) {an_output=true; cur_xref=cur_xref->xlink;} - else an_output=false; + if ((an_output=(cur_xref->num==file_flag))==true) cur_xref=cur_xref->xlink; if (cur_xref->num '); mark_harmless; @@ -1499,7 +1491,7 @@ sixteen_bits n) { char s[6]; sprintf(s,"%d",n); out_str(s); - if(changed_section[n]) out_str ("\\*"); + if (changed_section[n]) out_str("\\*"); @.\\*@> } @@ -1660,7 +1652,7 @@ if (c=='@@') { } } else { if (c=='\\' && *loc!='@@') { - if (phase==2) app_tok(*(loc++))@; else loc++; + if (phase==2) app_tok(*(loc++))@t;@>@; else loc++; } } @@ -1847,15 +1839,7 @@ static char cat_name[256][12]; @ This code allows \.{CWEAVE} to display its parsing steps. -@c -static void -print_cat( /* symbolic printout of a category */ -eight_bits c) -{ - fputs(cat_name[c],stdout); -} - -@ @=@+static void print_cat(eight_bits); +@d print_cat(c) fputs(cat_name[(eight_bits)(c)],stdout) @ The token lists for translated \TEX/ output contain some special control symbols as well as ordinary characters. These control symbols are @@ -2001,8 +1985,8 @@ with discretionary breaks in between. \.;&|semi|: \.;&maybe\cr \.:&|colon|: \.:&no\cr \.\# (within line)&|ubinop|: \.{\\\#}&yes\cr -\.\# (at beginning)&|lproc|: |force| |preproc_line| \.{\\\#}&no\cr -end of \.\# line&|rproc|: |force|&no\cr +\.\# (at beginning)&|lproc|: |force| |preproc_line| \.{\\\#}&no\cr +end of \.\# line&|rproc|: |force|&no\cr identifier&|exp|: \.{\\\\\{}identifier with underlines and dollar signs quoted\.\}&maybe\cr \.{alignas}&|alignas_like|: \stars&maybe\cr @@ -2127,10 +2111,10 @@ identifier&|exp|: \.{\\\\\{}identifier with underlines and \.{xor}&|alfop|: \stars&yes\cr \.{xor\_eq}&|alfop|: \stars&yes\cr \.{@@,}&|insert|: \.{\\,}&maybe\cr -\.{@@\v}&|insert|: |opt| \.0&maybe\cr -\.{@@/}&|insert|: |force|&no\cr -\.{@@\#}&|insert|: |big_force|&no\cr -\.{@@+}&|insert|: |big_cancel| \.{\{\}} |break_space| +\.{@@\v}&|insert|: |opt| \.0&maybe\cr +\.{@@/}&|insert|: |force|&no\cr +\.{@@\#}&|insert|: |big_force|&no\cr +\.{@@+}&|insert|: |big_cancel| \.{\{\}} |break_space| \.{\{\}} |big_cancel|&no\cr \.{@@;}&|semi|: &maybe\cr \.{@@[@q]@>}&|begin_arg|: &maybe\cr @@ -2150,7 +2134,7 @@ identifier&|exp|: \.{\\\\\{}identifier with underlines and \smallskip The construction \.{@@t}\thinspace stuff\/\thinspace\.{@@>} contributes -\.{\\hbox\{}\thinspace stuff\/\thinspace\.\} to the following scrap. +\.{\\hbox\{}\thinspace stuff\/\thinspace\.\} to the following scrap. @i prod.w @@ -2191,7 +2175,7 @@ typedef struct { eight_bits cat; eight_bits mathness; union { - text_pointer Trans; + text_pointer Trans;@+@t}\6{@> @@; } trans_plus; } scrap; @@ -2231,10 +2215,10 @@ items for \TEX/ output. translated without line-break controls. @d id_flag 10240 /* signifies an identifier */ -@d res_flag 2*id_flag /* signifies a reserved word */ -@d section_flag 3*id_flag /* signifies a section name */ -@d tok_flag 4*id_flag /* signifies a token list */ -@d inner_tok_flag 5*id_flag /* signifies a token list in `\pb' */ +@d res_flag (2*id_flag) /* signifies a reserved word */ +@d section_flag (3*id_flag) /* signifies a section name */ +@d tok_flag (4*id_flag) /* signifies a token list */ +@d inner_tok_flag (5*id_flag) /* signifies a token list in `\pb' */ @c static void @@ -2347,7 +2331,7 @@ If we combine two scraps and the right boundary of the first has a different mathness from the left boundary of the second, we insert a \.{\$} in between. Similarly, if at printing time some irreducible scrap has a |yes_math| boundary the scrap gets preceded -or followed by a \.{\$}. The left boundary is |maybe_math| if and +or followed by a~\.{\$}. The left boundary is |maybe_math| if and only if the right boundary is. The code below is an exact translation of the production rules into @@ -2377,7 +2361,7 @@ static void app_str( const char *s) { - while (*s) app_tok(*(s++)); + while (*s) app_tok(*s++); } static void @@ -2439,16 +2423,16 @@ code needs to be provided with a proper environment. && pp->cat!=operator_like) /* not a production with left side length 1 */ -@= { - if (cat1==end_arg && lhs_not_simple) - if (pp->cat==begin_arg) squash(pp,2,exp,-2,124); - else squash(pp,2,end_arg,-1,125); - else if (pp->cat==rbrack) squash(pp,1,rpar,-3,130); - else if (pp->cat==using_like) squash(pp,1,int_like,-3,140); - else if (cat1==insert) squash(pp,2,pp->cat,-2,0); - else if (cat2==insert) squash(pp+1,2,(pp+1)->cat,-1,0); - else if (cat3==insert) squash(pp+2,2,(pp+2)->cat,0,0); - else +@= +if (cat1==end_arg && lhs_not_simple) + if (pp->cat==begin_arg) squash(pp,2,exp,-2,124); + else squash(pp,2,end_arg,-1,125); +else if (pp->cat==rbrack) squash(pp,1,rpar,-3,130); +else if (pp->cat==using_like) squash(pp,1,int_like,-3,140); +else if (cat1==insert) squash(pp,2,pp->cat,-2,0); +else if (cat2==insert) squash(pp+1,2,(pp+1)->cat,-1,0); +else if (cat3==insert) squash(pp+2,2,(pp+2)->cat,0,0); +else switch (pp->cat) { case exp: @@; @+break; case lpar: @@; @+break; @@ -2503,8 +2487,7 @@ code needs to be provided with a proper environment. case attr: @@; @+break; case default_like: @@; @+break; } - pp++; /* if no match was found, we move to the right */ -} +pp++; /* if no match was found, we move to the right */ @ In \CEE/, new specifier names can be defined via |typedef|, and we want to make the parser recognize future occurrences of the identifier thus @@ -2578,14 +2561,12 @@ scrap_pointer p) if ((tok_loc=find_first_ident(p->trans))<=operator_found) return; /* this should not happen */ tok_value=*tok_loc; - for (;p<=scrap_ptr; p==lo_ptr? p=hi_ptr: p++) { - if (p->cat==exp) { + for (;p<=scrap_ptr; p==lo_ptr? p=hi_ptr: p++) + if (p->cat==exp) if (**(p->trans)==tok_value) { p->cat=raw_int; **(p->trans)=tok_value%id_flag+res_flag; } - } - } (name_dir+(sixteen_bits)(tok_value%id_flag))->ilk=raw_int; *tok_loc=tok_value%id_flag+res_flag; } @@ -2693,7 +2674,7 @@ else if (cat1==colcol && cat2==int_like) squash(pp,3,int_like,-2,152); @ @= if ((cat1==exp||cat1==ubinop) && cat2==rpar) squash(pp,3,exp,-2,11); else if (cat1==rpar) { - big_app1(pp); app('\\'); app(','); big_app1(pp+1); + big_app1(pp); app_str("\\,"); big_app1(pp+1); @.\\,@> reduce(pp,2,exp,-2,12); } @@ -2860,7 +2841,7 @@ if (cat1==function || cat1==decl || cat1==stmt) { @ @= if (cat1==rbrace) { - big_app1(pp); app('\\'); app(','); big_app1(pp+1); + big_app1(pp); app_str("\\,"); big_app1(pp+1); @.\\,@> reduce(pp,2,stmt,-1,54); } @@ -3012,7 +2993,7 @@ app('>'); reduce(pp,1,binop,-2,85); @= if (cat1==prerangle) { - big_app1(pp); app('\\'); app(','); big_app1(pp+1); + big_app1(pp); app_str("\\,"); big_app1(pp+1); @.\\,@> reduce(pp,2,cast,-1,86); } @@ -3022,14 +3003,14 @@ else if (cat1==decl_head || cat1==int_like || cat1==exp) { big_app3(pp); app(opt); app('9'); reduce(pp,3,langle,0,88); } } -else if (cat1==struct_like) { - if ((cat2==exp || cat2==int_like) && (cat3==comma || cat3==prerangle)) { +else if ((cat1==struct_like) @| + && (cat2==exp || cat2==int_like) @| + && (cat3==comma || cat3==prerangle)) { make_underlined(pp+2); if (reserve_typenames) make_reserved(pp+2); big_app2(pp); big_app(' '); big_app2(pp+2); if (cat3==comma) reduce(pp,4,langle,0,153); else reduce(pp,4,cast,-1,154); } -} @ @= if (cat1==exp && cat2==prelangle) squash(pp+2,1,langle,2,89); @@ -3124,7 +3105,7 @@ else if (cat1==ubinop && (cat2==ubinop || cat2==cast)) { @ @= if (cat1==lpar && cat2==rpar) { - big_app2(pp); app('\\'); app(','); big_app1(pp+2); + big_app2(pp); app_str("\\,"); big_app1(pp+2); @.\\,@> reduce(pp,3,delete_like,0,121); } @@ -3193,7 +3174,7 @@ because no ending point for the current list has been stored in the |tok_start| array. After saying |freeze_text|, the old current token list becomes legitimate, and its number is the current value of |text_ptr-1| since |text_ptr| has been increased. The new -current token list is empty and ready to be appended to. +current token list is empty and ready to be appended~to. Note that |freeze_text| does not check to see that |text_ptr| hasn't gotten too large, since it is assumed that this test was done beforehand. @@ -3282,7 +3263,7 @@ stored, since zero does not match anything in a production. @= if (lo_ptrcat=hi_ptr->cat; lo_ptr->mathness=(hi_ptr)->mathness; + (++lo_ptr)->cat=hi_ptr->cat; lo_ptr->mathness=hi_ptr->mathness; lo_ptr->trans=(hi_ptr++)->trans; } for (i=lo_ptr+1;i<=pp+3;i++) i->cat=0; @@ -3302,15 +3283,15 @@ static int tracing=off; /* can be used to show parsing details */ @ @= if (tracing==fully) { - scrap_pointer k_l; /* pointer into |scrap_info| */ + scrap_pointer k; /* pointer into |scrap_info|; shadows |short k| */ printf("\n%d:",n); - for (k_l=scrap_base; k_l<=lo_ptr; k_l++) { - if (k_l==pp) putchar('*'); else putchar(' '); - if (k_l->mathness %4 == yes_math) putchar('+'); - else if (k_l->mathness %4 == no_math) putchar('-'); - print_cat(k_l->cat); - if (k_l->mathness /4 == yes_math) putchar('+'); - else if (k_l->mathness /4 == no_math) putchar('-'); + for (k=scrap_base; k<=lo_ptr; k++) { + if (k==pp) putchar('*'); else putchar(' '); + if (k->mathness %4 == yes_math) putchar('+'); + else if (k->mathness %4 == no_math) putchar('-'); + print_cat(k->cat); + if (k->mathness /4 == yes_math) putchar('+'); + else if (k->mathness /4 == no_math) putchar('-'); } if (hi_ptr<=scrap_ptr) printf("..."); /* indicate that more is coming */ } @@ -3347,17 +3328,16 @@ we concatenate the translations of all remaining scraps, separated by blank spaces, with dollar signs surrounding the translations of scraps where appropriate. -@= { - @@; - for (j=scrap_base; j<=lo_ptr; j++) { - if (j!=scrap_base) app(' '); - if (j->mathness % 4 == yes_math) app('$'); - app1(j); - if (j->mathness / 4 == yes_math) app('$'); - if (tok_ptr+6>tok_mem_end) overflow("token"); - } - freeze_text; return text_ptr-1; +@= +@@; +for (j=scrap_base; j<=lo_ptr; j++) { + if (j!=scrap_base) app(' '); + if (j->mathness % 4 == yes_math) app('$'); + app1(j); + if (j->mathness / 4 == yes_math) app('$'); + if (tok_ptr+6>tok_mem_end) overflow("token"); } +freeze_text; return text_ptr-1; @ @= if (lo_ptr>scrap_base && tracing==partly) { @@ -3470,10 +3450,10 @@ switch (next_control) { case ',': app(',');@+app_scrap(comma,yes_math);@+break; case ';': app(';');@+app_scrap(semi,maybe_math);@+break; case ':': app(':');@+app_scrap(colon,no_math);@+break;@/ - @t\4@> @@; + @t\4@> @@; case thin_space: app_str("\\,");@+app_scrap(insert,maybe_math);@+break; @.\\,@> - case math_break: app(opt);@+app_str("0");@+ + case math_break: app(opt);@+app('0');@+ app_scrap(insert,maybe_math);@+break; case line_break: app(force);@+app_scrap(insert,no_math);@+break; case left_preproc: app(force);@+app(preproc_line);@+app_str("\\#"); @@ -3573,7 +3553,7 @@ while (id_first @.\\\\@> @@ -3649,7 +3629,7 @@ boolean scrapping) /* are we making this into a scrap? */ } else { app(res_flag+(int)(p-name_dir)); if (scrapping) { - if (p->ilk==alfop) app_scrap(ubinop,yes_math)@; + if (p->ilk==alfop) app_scrap(ubinop,yes_math)@t;@>@; else app_scrap(p->ilk,maybe_math); } } @@ -3717,7 +3697,7 @@ outer_parse(void) /* makes scraps from \CEE/ tokens and comments */ if (make_pb) app_str("\\PB{"); @.\\PB@> app(inner_tok_flag+(int)(q-tok_start)); - if (make_pb) app_tok('}'); + if (make_pb) app_tok('}'); if (next_control=='|') { bal=copy_comment(is_long_comment,bal); next_control=ignore; @@ -3735,7 +3715,7 @@ So far our programs have only built up multi-layered token lists in the desired final form. The job of converting token lists to characters in the \TEX/ output file is not difficult, although it is an implicitly recursive process. Four main considerations had to be kept in mind when -this part of \.{CWEAVE} was designed. (a) There are two modes of output: +this part of \.{CWEAVE} was designed. (a) There are two modes of output: |outer| mode, which translates tokens like |force| into line-breaking control sequences, and |inner| mode, which ignores them except that blank spaces take the place of line breaks. (b) The |cancel| instruction applies @@ -3743,7 +3723,7 @@ to adjacent token or tokens that are output, and this cuts across levels of recursion since `|cancel|' occurs at the beginning or end of a token list on one level. (c) The \TEX/ output file will be semi-readable if line breaks are inserted after the result of tokens like |break_space| and -|force|. (d) The final line break should be suppressed, and there should +|force|. (d) The final line break should be suppressed, and there should be no |force| token output immediately after `\.{\\Y\\B}'. @ The output process uses a stack to keep track of what is going on at @@ -3779,7 +3759,8 @@ typedef struct { } output_state; typedef output_state *stack_pointer; -@ @d cur_end cur_state.end_field /* current ending location in |tok_mem| */ +@ @d stack_size 400 /* number of simultaneous output levels */ +@d cur_end cur_state.end_field /* current ending location in |tok_mem| */ @d cur_tok cur_state.tok_field /* location of next output token in |tok_mem| */ @d cur_mode cur_state.mode_field /* current mode of interpretation */ @d init_stack stack_ptr=stack;cur_mode=outer /* initialize the stack */ @@ -3975,7 +3956,7 @@ if (a==identifier) { out(*p=='_'? 'x': *p=='$'? 'X': *p); break; } - else if (is_tiny(cur_name)) out('|')@; + else if (is_tiny(cur_name)) out('|')@t;@>@; @.\\|@> else { delim='.'; for (p=cur_name->byte_start;p<(cur_name+1)->byte_start;p++) @@ -4014,7 +3995,7 @@ if (a if (a==opt) { b=get_output(); /* |opt| is followed by a digit */ - if (b!='0' || force_lines==false) out(b)@; + if (b!='0' || force_lines==false) out(b)@t;@>@; else out_str("{-1}"); /* |force_lines| encourages more \.{@@\v} breaks */ } } else if (a==opt) b=get_output(); /* ignore digit following |opt| */ @@ -4073,31 +4054,29 @@ routines, since the name may contain \CEE/ code embedded in input buffer and the translation process uses the end of the active |tok_mem| area. -@= { - out_str("\\X"); +@= +out_str("\\X"); @.\\X@> - cur_xref=(xref_pointer)cur_name->xref; - if (cur_xref->num==file_flag) {an_output=true; cur_xref=cur_xref->xlink;} - else an_output=false; - if (cur_xref->num>=def_flag) { - out_section(cur_xref->num-def_flag); - if (phase==3) { - cur_xref=cur_xref->xlink; - while (cur_xref->num>=def_flag) { - out_str(", "); - out_section(cur_xref->num-def_flag); - cur_xref=cur_xref->xlink; - } +cur_xref=(xref_pointer)cur_name->xref; +if ((an_output=(cur_xref->num==file_flag))==true) cur_xref=cur_xref->xlink; +if (cur_xref->num>=def_flag) { + out_section(cur_xref->num-def_flag); + if (phase==3) { + cur_xref=cur_xref->xlink; + while (cur_xref->num>=def_flag) { + out_str(", "); + out_section(cur_xref->num-def_flag); + cur_xref=cur_xref->xlink; } } - else out('0'); /* output the section number, or zero if it was undefined */ - out(':'); - if (an_output) out_str("\\.{"@q}@>); -@.\\.@> - @@; - if (an_output) out_str(@q{@>" }"); - out_str("\\X"); } +else out('0'); /* output the section number, or zero if it was undefined */ +out(':'); +if (an_output) out_str("\\.{"@q}@>); +@.\\.@> +@@; +if (an_output) out_str(@q{@>" }"); +out_str("\\X"); @ @= sprint_section_name(scratch,cur_name); @@ -4126,7 +4105,7 @@ while (k@; else { @@; save_loc=loc; save_limit=limit; loc=limit+2; limit=j+1; @@ -4186,10 +4165,12 @@ actually output the \TEX/ material instead of merely looking at the @c static void phase_two(void) { -reset_input(); if (show_progress) fputs("\nWriting the output file...",stdout); +phase=2; reset_input(); +if (show_progress) fputs("\nWriting the output file...",stdout); @.Writing the output file...@> section_count=0; format_visible=true; copy_limbo(); -finish_line(); flush_buffer(out_buf,false,false); /* insert a blank line, it looks nice */ +finish_line(); flush_buffer(out_buf,false,false); + /* insert a blank line, it looks nice */ while (!input_has_ended) @@; } @@ -4233,7 +4214,7 @@ static boolean group_found=false; /* has a starred section occurred? */ output with the \TEX/ control sequence `\.{\\M}', followed by the section number. Similarly, `\.{@@*}' sections lead to the control sequence `\.{\\N}'. In this case there's an additional parameter, representing one plus the -specified depth, immediately after the \.{\\N}. +specified depth, immediately after the~\.{\\N}. If the section has changed, we put \.{\\*} just after the section number. @= @@ -4262,7 +4243,7 @@ out('{'); out_section(section_count); out('}'); @ In the \TEX/ part of a section, we simply copy the source text, except that index entries are not copied and \CEE/ text within \pb\ is translated. -@= do { +@= do switch (next_control=copy_TeX()) { case '|': init_stack; output_C(); break; case '@@': out('@@'); break; @@ -4279,7 +4260,7 @@ index entries are not copied and \CEE/ text within \pb\ is translated. err_print("! You can't do that in TeX text"); break; @.You can't do that...@> } -} while (next_control=format_code|, and the token memory is in its initial empty state. @@ -4411,7 +4392,7 @@ if (next_control<=section_name) { @scrap_info) { } @ @= -switch (cur_name->ilk) {@+char *j; +switch (cur_name->ilk) {@+char *j;@+@t}\6{\4@> case normal: case func_template: if (is_tiny(cur_name)) out_str("\\|"); else { diff --git a/cwebmac.tex b/cwebmac.tex index a4686ad..4673573 100644 --- a/cwebmac.tex +++ b/cwebmac.tex @@ -1,8 +1,8 @@ % standard macros for CWEB listings (in addition to plain.tex) -% Version 4.3 --- May 2021 +% Version 4.4 --- June 2021 \ifx\renewenvironment\undefined\else\endinput\fi % LaTeX will use other macros -\xdef\fmtversion{\fmtversion+CWEB4.3} -\chardef\cwebversion=4 \chardef\cwebrevision=1 +\xdef\fmtversion{\fmtversion+CWEB4.4} +\chardef\cwebversion=4 \chardef\cwebrevision=4 \newif\ifpdf \ifx\pdf+\pdftrue\fi % Uncomment the following line if you want PDF goodies to be the default @@ -350,7 +350,7 @@ % \def\$##1{\egroup_{\,\rm##1}\bgroup}% suffix to constant % versions < 3.67 \def\$##1{\egroup_{\rm##1}\bgroup}% suffix to constant % in version 3.67 \def\_{\cdot 10^{\aftergroup}}% power of ten (via dirty trick) - \def\%{\cdot 16^{\aftergroup}}% power of sixteen (via dirty trick) + \def\%{\cdot 2^{\aftergroup}}% power of two (via dirty trick) \let\~=\oct \let\^=\hex \let\\=\bin {#1}$}} \def\U{\note{This code is used in section}} % xref for use of a section \def\Us{\note{This code is used in sections}} % xref for uses of a section diff --git a/cwebman.tex b/cwebman.tex index 4d4206e..e7706db 100644 --- a/cwebman.tex +++ b/cwebman.tex @@ -35,7 +35,7 @@ \def\lheader{\mainfont\the\pageno\hfill\sc\runninghead\hfill} \def\rheader{\hfill\sc\runninghead\hfill\mainfont\the\pageno} -\def\runninghead{{\tentt CWEB} USER MANUAL (VERSION 4.3)} +\def\runninghead{{\tentt CWEB} USER MANUAL (VERSION 4.4)} % This verbatim mode assumes that ! marks are !! in the text being copied. \def\verbatim{\begingroup @@ -49,7 +49,7 @@ \null\vfill \centerline{\titlefont The {\ttitlefont CWEB} System of Structured Documentation} -\vskip 18pt\centerline{(Version 4.3 --- May 2021)} +\vskip 18pt\centerline{(Version 4.4 --- June 2021)} \vskip 24pt \centerline{\authorfont Donald E. Knuth and Silvio Levy} \vfill @@ -139,7 +139,7 @@ The philosophy behind \.{CWEB} is that programmers who want to provide the best possible documentation for their programs need two things -simultaneously: a language like \TEX/ for formatting, and a language like +simultaneously: a language like \TEX/ for formatting, and a language like \CEE/ for programming. Neither type of language can provide the best documentation by itself. But when both are appropriately combined, we obtain a system that is much more useful than either language separately. @@ -432,7 +432,7 @@ $$ \displaylines{ \hbox{\.{if} \.{(x==0)} \.{@}} \cr -\hbox{\.{...} \.{using} \.{the} \.{algorithm} +\hbox{\.{...} \.{using} \.{the} \.{algorithm} \.{in} \.{|@|.}} } $$ The first of these excerpts @@ -480,7 +480,7 @@ Similarly, \.{CWEAVE} prints the hexadecimal \CEE/ constant `\.{0x20}' as \T{\^20/}. The use of italic font for octal digits and typewriter font for hexadecimal digits makes the meaning of such constants clearer in -a document. For consistency, then, you should type `\.{|040|}' or +a document. For consistency, then, you should type `\.{|040|}' or `\.{|0x20|}' in the \TEX/ part of the section. And if you type a binary constant like `\.{0b00101010}', \.{CWEAVE} prints @@ -845,7 +845,8 @@ $$\lpile{\.{if (condition) macro @;}\cr \.{else break;}\cr}$$ where \\{macro} is defined to be a compound statement (enclosed in braces). -This is a well-known infelicity of \CEE/ syntax. +This is a well-known infelicity of \CEE/ syntax. You can add a visible +semicolon with \.{@t;@>} (before \.{@;}). \@{[} [MC] See \.{@]}. @@ -1262,15 +1263,13 @@ } while (limit==buffer); @ @= -{ - change_limit=change_buffer+(ptrdiff_t)(limit-buffer); - strncpy(change_buffer,buffer,(size_t)(limit-buffer+1)); -} +change_limit=change_buffer+(ptrdiff_t)(limit-buffer); +strncpy(change_buffer,buffer,(size_t)(limit-buffer+1)); !endgroup \endgroup \vfill\eject -\def\runninghead{APPENDIX A --- TRANSLATION BY {\tentt CTANGLE}} +\def\runninghead{APPENDIX A --- TRANSLATION BY {\tentt CTANGLE}} Here's the portion of the \CEE/ code generated by \.{CTANGLE} that corresponds to the source on the preceding page. Notice that sections~29, 30 and~31 @@ -1324,10 +1323,8 @@ /*31:*/ #line 270 "common.w" -{ change_limit= change_buffer+(ptrdiff_t)(limit-buffer); strncpy(change_buffer,buffer,(size_t)(limit-buffer+1)); -} /*:31*/ #line 234 "common.w" @@ -1496,12 +1493,10 @@ \M{31}\B\X31:Move \PB{\\{buffer}} and \PB{\\{limit}} to \PB{\\{change\_buffer}} and \PB{\\{change\_limit}}\X${}\E{}$\6 -${}\{{}$\1\6 -${}\\{change\_limit}\K\\{change\_buffer}+(\&{ptrdiff\_t})(\\{limit}-% +$\\{change\_limit}\K\\{change\_buffer}+(\&{ptrdiff\_t})(\\{limit}-% \\{buffer});{}$\6 ${}\\{strncpy}(\\{change\_buffer},\39\\{buffer},\39(\&{size\_t})(\\{limit}-% -\\{buffer}+\T{1}));{}$\6 -\4${}\}{}$\2\par +\\{buffer}+\T{1})){}$;\par \Us27\ET32.\fi \vfil\eject\titletrue \rightskip=0pt % get out of C mode (cf. \B) @@ -1597,7 +1592,7 @@ \.{ { }\\titlefalse \% include headline on the contents page}\cr \.{ { }\\def\\rheader\{\\mainfont The \{\\tt CWEAVE\}{ }processor\\hfil\}}\cr \.{ { }\\centerline\{\\titlefont The \{\\ttitlefont CWEAVE\}{ }processor\}}\cr - \.{ { }\\vskip 15pt \\centerline\{(Version 4.3)\}{ }\\vfill\}}\cr}$$ + \.{ { }\\vskip 15pt \\centerline\{(Version 4.4)\}{ }\\vfill\}}\cr}$$ Redefining \.{\\rheader}, which is the headline for right-hand pages, suffices in this case to put the desired information at the top of the contents page. diff --git a/prod.w b/prod.w index f7994a1..c4c75e0 100644 --- a/prod.w +++ b/prod.w @@ -68,8 +68,8 @@ We use \\{in}, \\{out}, \\{back}, \\{bsp}, and \\{din} as shorthands for \+& |exp| |semi| & |stmt| & |x=0;|\cr \+& |exp| |colon| & |tag| \hfill $E^*C$ & |found:|\cr \+& |exp| |rbrace| & |stmt| |rbrace| & end of \&{enum} list\cr -\+& |exp| \alt {|lpar| |rpar|} |cast| \alt|const_like| |case_like| & - |exp| \alt {|lpar| |rpar|} |cast| \hfill +\+& |exp| \alt {|lpar| |rpar|} |cast| \alt|const_like| |case_like| & + |exp| \alt {|lpar| |rpar|} |cast| \hfill \alt $R=R\.\ C$ $C_1=C_1\.\ C_2$ & \malt {|f() const|} {|f(int) throw|} \cr \+& |exp| \alt |exp| |cast| & |exp| & |time()|\cr @@ -161,7 +161,7 @@ We use \\{in}, \\{out}, \\{back}, \\{bsp}, and \\{din} as shorthands for \+& |else_like| |lbrace| & |else_head| |lbrace| & \&{else} $\{$\cr \+& |else_like| |stmt| & |stmt| \hfill $|force|\,E\,\\{in}\,\\{bsp}\,S\,\\{out}\,|force|$ & $\!\!$|else x=0;|\cr -\+& |else_head| \alt|stmt| |exp| & |stmt| \hfill +\+& |else_head| \alt|stmt| |exp| & |stmt| \hfill $|force|\,E\,\\{bsp}\,|noop|\,|cancel|\,S\,\\{bsp}$ & $\!\!$|else{x=0;}|\cr \+& |if_clause| |lbrace| & |if_head| |lbrace| & |if (x) {|\cr \+& |if_clause| |stmt| |else_like| |if_like| & |if_like| \hfill