⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ctangle.w

📁 模拟器提供了一个简单易用的平台
💻 W
📖 第 1 页 / 共 4 页
字号:
% This file is part of CWEB.% 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 3.62 --- September 2000% (same as Version 3.5 except for minor typographic/stylistic corrections)% (also quotes backslashes in file names of #line directives)% Copyright (C) 1987,1990,1993,2000 Silvio Levy and Donald E. Knuth% Permission is granted to make and distribute verbatim copies of this% document provided that the copyright notice and this permission notice% are preserved on all copies.% Permission is granted to copy and distribute modified versions of this% document under the conditions for verbatim copying, provided that the% entire resulting derived work is given a different name and distributed% under the terms of a permission notice identical to this one.% Here is TeX material that gets inserted after \input cwebmac\def\hang{\hangindent 3em\indent\ignorespaces}\def\pb{$\.|\ldots\.|$} % C brackets (|...|)\def\v{\char'174} % vertical (|) in typewriter font\mathchardef\RA="3221 % right arrow\mathchardef\BA="3224 % double arrow\def\title{CTANGLE (Version 3.62)}\def\topofcontents{\null\vfill  \centerline{\titlefont The {\ttitlefont CTANGLE} processor}  \vskip 15pt  \centerline{(Version 3.62)}  \vfill}\def\botofcontents{\vfill\noindentCopyright \copyright\ 1987, 1990, 1993, 2000 Silvio Levy and Donald E. Knuth\bigskip\noindentPermission is granted to make and distribute verbatim copies of thisdocument provided that the copyright notice and this permission noticeare preserved on all copies.\smallskip\noindentPermission is granted to copy and distribute modified versions of thisdocument under the conditions for verbatim copying, provided that theentire resulting derived work is given a different name and distributedunder the terms of a permission notice identical to this one.}\pageno=\contentspagenumber \advance\pageno by 1\let\maybe=\iftrue@s not_eq normal @q unreserve a C++ keyword @>@** Introduction.This is the \.{CTANGLE} program by Silvio Levy and Donald E. Knuth,based on \.{TANGLE} by Knuth.We are thankful toNelson Beebe, Hans-Hermann Bode (to whom the \CPLUSPLUS/ adaptation is due),Klaus Guntermann, Norman Ramsey, Tomas Rokicki, Joachim Schnitter,Joachim Schrod, Lee Wittenberg, and others who have contributed improvements.The ``banner line'' defined here should be changed whenever \.{CTANGLE}is modified.@d banner "This is CTANGLE (Version 3.62)\n"@c@<Include files@>@/@h@<Common code for \.{CWEAVE} and \.{CTANGLE}@>@/@<Typedef declarations@>@/@<Global variables@>@/@<Predeclaration of procedures@>@/@ We predeclare several standard system functions here instead of includingtheir system header files, because the names of the header files are not asstandard as the names of the functions. (For example, some \CEE/ environmentshave \.{<string.h>} where others have \.{<strings.h>}.)@<Predecl...@>=extern int strlen(); /* length of string */extern int strcmp(); /* compare strings lexicographically */extern char* strcpy(); /* copy one string to another */extern int strncmp(); /* compare up to $n$ string characters */extern char* strncpy(); /* copy up to $n$ string characters */@ \.{CTANGLE} has a fairly straightforward outline.  It operates intwo phases: First it reads the source file, saving the \CEE/ code incompressed form; then it shuffles and outputs the code.Please read the documentation for \.{common}, the set of routines commonto \.{CTANGLE} and \.{CWEAVE}, before proceeding further.@cint main (ac, av)int ac;char **av;{  argc=ac; argv=av;  program=ctangle;  @<Set initial values@>;  common_init();  if (show_banner) printf(banner); /* print a ``banner line'' */  phase_one(); /* read all the user's text and compress it into |tok_mem| */  phase_two(); /* output the contents of the compressed tables */  return wrap_up(); /* and exit gracefully */}@ The following parameters were sufficient in the original \.{TANGLE} tohandle \TEX/,so they should be sufficient for most applications of \.{CTANGLE}.If you change |max_bytes|, |max_names|, or |hash_size| you should alsochange them in the file |"common.w"|.@d max_bytes 90000 /* the number of bytes in identifiers,  index entries, and section names; used in |"common.w"| */@d max_toks 270000 /* number of bytes in compressed \CEE/ code */@d max_names 4000 /* number of identifiers, strings, section names;  must be less than 10240; used in |"common.w"| */@d max_texts 2500 /* number of replacement texts, must be less than 10240 */@d hash_size 353 /* should be prime; used in |"common.w"| */@d longest_name 10000 /* section names shouldn't be longer than this */@d stack_size 50 /* number of simultaneous levels of macro expansion */@d buf_size 100 /* for \.{CWEAVE} and \.{CTANGLE} */@ The next few sections contain stuff from the file |"common.w"| that mustbe included in both |"ctangle.w"| and |"cweave.w"|. It appears infile |"common.h"|, which needs to be updated when |"common.w"| changes.@i common.h@* Data structures exclusive to {\tt CTANGLE}.We've already seen that the |byte_mem| array holds the names of identifiers,strings, and sections;the |tok_mem| array holds the replacement textsfor sections. Allocation is sequential, since things are deleted onlyduring Phase II, and only in a last-in-first-out manner.A \&{text} variable is a structure containing a pointer into|tok_mem|, which tells where the corresponding text starts, and aninteger |text_link|, which, as we shall see later, is used to connectpieces of text that have the same name.  All the \&{text}s are stored inthe array |text_info|, and we use a |text_pointer| variable to referto them.The first position of |tok_mem| that is unoccupied byreplacement text is called |tok_ptr|, and the first unused location of|text_info| is called |text_ptr|.  Thus we usually have the identity|text_ptr->tok_start==tok_ptr|.If your machine does not support |unsigned char| you should changethe definition of \&{eight\_bits} to |unsigned short|.@^system dependencies@>@<Typed...@>=typedef struct {  eight_bits *tok_start; /* pointer into |tok_mem| */  sixteen_bits text_link; /* relates replacement texts */} text;typedef text *text_pointer;@ @<Glob...@>=text text_info[max_texts];text_pointer text_info_end=text_info+max_texts-1;text_pointer text_ptr; /* first unused position in |text_info| */eight_bits tok_mem[max_toks];eight_bits *tok_mem_end=tok_mem+max_toks-1;eight_bits *tok_ptr; /* first unused position in |tok_mem| */@ @<Set init...@>=text_info->tok_start=tok_ptr=tok_mem;text_ptr=text_info+1; text_ptr->tok_start=tok_mem;  /* this makes replacement text 0 of length zero */@ If |p| is a pointer to a section name, |p->equiv| is a pointer to itsreplacement text, an element of the array |text_info|.@d equiv equiv_or_xref /* info corresponding to names */@ @<Set init...@>=name_dir->equiv=(char *)text_info; /* the undefined section has no replacement text */@ Here's the procedure that decides whether a name of length |l|starting at position |first| equals the identifier pointed to by |p|:@cint names_match(p,first,l)name_pointer p; /* points to the proposed match */char *first; /* position of first character of string */int l; /* length of identifier */{  if (length(p)!=l) return 0;  return !strncmp(first,p->byte_start,l);}@ The common lookup routine refers to separate routines |init_node| and|init_p| when the data structure grows. Actually |init_p| is called only by\.{CWEAVE}, but we need to declare a dummy version so thatthe loader won't complain of its absence.@cvoidinit_node(node)name_pointer node;{    node->equiv=(char *)text_info;}voidinit_p() {}@* Tokens.Replacement texts, which represent \CEE/ code in a compressed format,appear in |tok_mem| as mentioned above. The codes inthese texts are called `tokens'; some tokens occupy two consecutiveeight-bit byte positions, and the others take just one byte.If $p$ points to a replacement text, |p->tok_start| is the |tok_mem| positionof the first eight-bit code of that text. If |p->text_link==0|,this is the replacement text for a macro, otherwise it is the replacementtext for a section. In the latter case |p->text_link| is either equal to|section_flag|, which means that there is no further text for this section, or|p->text_link| points to a continuation of this replacement text; suchlinks are created when several sections have \CEE/ texts with the samename, and they also tie together all the \CEE/ texts of unnamed sections.The replacement text pointer for the first unnamed section appears in|text_info->text_link|, and the most recent such pointer is |last_unnamed|.@d section_flag max_texts /* final |text_link| in section replacement texts */@<Glob...@>=text_pointer last_unnamed; /* most recent replacement text of unnamed section */@ @<Set init...@>= last_unnamed=text_info; text_info->text_link=0;@ If the first byte of a token is less than |0200|, the token occupies asingle byte. Otherwise we make a sixteen-bit token by combining two consecutivebytes |a| and |b|. If |0200<=a<0250|, then |(a-0200)@t${}\times2^8$@>+b|points to an identifier; if |0250<=a<0320|, then|(a-0250)@t${}\times2^8$@>+b| points to a section name(or, if it has the special value |output_defs_flag|,to the area where the preprocessor definitions are stored); and if|0320<=a<0400|, then |(a-0320)@t${}\times2^8$@>+b| is the number of the sectionin which the current replacement text appears.Codes less than |0200| are 7-bit |char| codes that represent themselves.Some of the 7-bit codes will not be present, however, so we canuse them for special purposes. The following symbolic names are used:\yskip \hang |join| denotes the concatenation of adjacent items with nospace or line breaks allowed between them (the \.{@@\&} operation of \.{CWEB}).\hang |string| denotes the beginning or end of a string, verbatimconstruction or numerical constant.@^ASCII code dependencies@>@d string 02 /* takes the place of extended ASCII \.{\char2} */@d join 0177 /* takes the place of ASCII delete */@d output_defs_flag (2*024000-1)@ The following procedure is used to enter a two-byte value into|tok_mem| when a replacement text is being generated.@cvoidstore_two_bytes(x)sixteen_bits x;{  if (tok_ptr+2>tok_mem_end) overflow("token");  *tok_ptr++=x>>8; /* store high byte */  *tok_ptr++=x&0377; /* store low byte */}@** Stacks for output.  The output process uses a stack to keep trackof what is going on at different ``levels'' as the sections are beingwritten out.  Entries on this stack have five parts:\yskip\hang |end_field| is the |tok_mem| location where the replacementtext of a particular level will end;\hang |byte_field| is the |tok_mem| location from which the next tokenon a particular level will be read;\hang |name_field| points to the name corresponding to a particular level;\hang |repl_field| points to the replacement text currently being readat a particular level;\hang |section_field| is the section number, or zero if this is a macro.\yskip\noindent The current values of these five quantities are referred toquite frequently, so they are stored in a separate place instead of inthe |stack| array. We call the current values |cur_end|, |cur_byte|,|cur_name|, |cur_repl|, and |cur_section|.The global variable |stack_ptr| tells how many levels of output arecurrently in progress. The end of all output occurs when the stack isempty, i.e., when |stack_ptr==stack|.@<Typed...@>=typedef struct {  eight_bits *end_field; /* ending location of replacement text */  eight_bits *byte_field; /* present location within replacement text */  name_pointer name_field; /* |byte_start| index for text being output */  text_pointer repl_field; /* |tok_start| index for text being output */  sixteen_bits section_field; /* section number or zero if not a section */} output_state;typedef output_state *stack_pointer;@ @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 */@d cur_section cur_state.section_field /* current section number being expanded */@<Global...@>=output_state cur_state; /* |cur_end|, |cur_byte|, |cur_name|, |cur_repl|,  and |cur_section| */output_state stack[stack_size+1]; /* info for non-current levels */stack_pointer stack_ptr; /* first unused location in the output state stack */stack_pointer stack_end=stack+stack_size; /* end of |stack| */@ To get the output process started, we will perform the followinginitialization steps. We may assume that |text_info->text_link| is nonzero,since it points to the \CEE/ text in the first unnamed section that generatescode; if there are no such sections, there is nothing to output, and anerror message will have been generated before we do any of the initialization.@<Initialize the output stacks@>=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;@ When the replacement text for name |p| is to be inserted into the output,the following subroutine is called to save the old level of output and getthe new one going.We assume that the \CEE/ compiler can copy structures.@^system dependencies@>@cvoidpush_level(p) /* suspends the current level */name_pointer p;{  if (stack_ptr==stack_end) overflow("stack");  *stack_ptr=cur_state;  stack_ptr++;  if (p!=NULL) { /* |p==NULL| means we are in |output_defs| */    cur_name=p; cur_repl=(text_pointer)p->equiv;    cur_byte=cur_repl->tok_start; cur_end=(cur_repl+1)->tok_start;    cur_section=0;  }}@ When we come to the end of a replacement text, the |pop_level| subroutinedoes the right thing: It either moves to the continuation of this replacementtext or returns the state to the most recently stacked level.@cvoidpop_level(flag) /* do this when |cur_byte| reaches |cur_end| */int flag; /* |flag==0| means we are in |output_defs| */{  if (flag && cur_repl->text_link<section_flag) { /* link to a continuation */    cur_repl=cur_repl->text_link+text_info; /* stay on the same level */    cur_byte=cur_repl->tok_start; cur_end=(cur_repl+1)->tok_start;    return;  }  stack_ptr--; /* go down to the previous level */  if (stack_ptr>stack) cur_state=*stack_ptr;}@ The heart of the output procedure is the function |get_output|,which produces the next token of output and sends it on to the lower-levelfunction |out_char|. The main purpose of |get_output| is to handle thenecessary stacking and unstacking. It sends the value |section_number|if the next output begins or ends the replacement text of some section,in which case |cur_val| is that section's number (if beginning) or thenegative of that value (if ending). (A section number of 0 indicatesnot the beginning or ending of a section, but a \&{\#line} command.)And it sends the value |identifier|if the next output is an identifier, in which case|cur_val| points to that identifier name.@d section_number 0201 /* code returned by |get_output| for section numbers */@d identifier 0202 /* code returned by |get_output| for identifiers */@<Global...@>=int cur_val; /* additional information corresponding to output token */@ If |get_output| finds that no more output remains, it returns with|stack_ptr==stack|.@^high-bit character handling@>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -