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

📄 cweave.w

📁 模拟器提供了一个简单易用的平台
💻 W
📖 第 1 页 / 共 5 页
字号:
strings will not be entered into the cross reference lists since they are notdefinitions of section names.The program uses the fact that our internal code numbers satisfythe relations |xref_roman==identifier+roman| and |xref_wildcard==identifier+wildcard| and |xref_typewriter==identifier+typewriter|,as well as |normal==0|.@<Predecl...@>=void C_xref();@ @cvoidC_xref( spec_ctrl ) /* makes cross-references for \CEE/ identifiers */  eight_bits spec_ctrl;{  name_pointer p; /* a referenced name */  while (next_control<format_code || next_control==spec_ctrl) {    if (next_control>=identifier && next_control<=xref_typewriter) {      if (next_control>identifier) @<Replace |"@@@@"| by |"@@"| @>@;      p=id_lookup(id_first, id_loc,next_control-identifier); new_xref(p);    }    if (next_control==section_name) {      section_xref_switch=cite_flag;      new_section_xref(cur_section);    }    next_control=get_next();    if (next_control=='|' || next_control==begin_comment ||        next_control==begin_short_comment) return;  }}@ The |outer_xref| subroutine is like |C_xref| except that it beginswith |next_control!='|'| and ends with |next_control>=format_code|. Thus, ithandles \CEE/ text with embedded comments.@<Predecl...@>=void outer_xref();@ @cvoidouter_xref() /* extension of |C_xref| */{  int bal; /* brace level in comment */  while (next_control<format_code)    if (next_control!=begin_comment && next_control!=begin_short_comment)      C_xref(ignore);    else {      boolean is_long_comment=(next_control==begin_comment);      bal=copy_comment(is_long_comment,1); next_control='|';      while (bal>0) {        C_xref(section_name); /* do not reference section names in comments */        if (next_control=='|') bal=copy_comment(is_long_comment,bal);        else bal=0; /* an error message will occur in phase two */      }    }}@ In the \TEX/ part of a section, cross-reference entries are made only forthe identifiers in \CEE/ texts enclosed in \pb, or for control textsenclosed in \.{@@\^}$\,\ldots\,$\.{@@>} or \.{@@.}$\,\ldots\,$\.{@@>}or \.{@@:}$\,\ldots\,$\.{@@>}.@<Store cross-references in the \T...@>=while (1) {  switch (next_control=skip_TeX()) {    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=*(loc-1)-'0'; continue;    case '|': C_xref(section_name); break;    case xref_roman: case xref_wildcard: case xref_typewriter:    case noop: case section_name:      loc-=2; next_control=get_next(); /* scan to \.{@@>} */      if (next_control>=xref_roman && next_control<=xref_typewriter) {        @<Replace |"@@@@"| by |"@@"| @>@;        new_xref(id_lookup(id_first, id_loc,next_control-identifier));      }      break;  }  if (next_control>=format_code) break;}@ @<Replace |"@@@@"| by |"@@"| @>={  char *src=id_first,*dst=id_first;  while(src<id_loc){    if(*src=='@@') src++;    *dst++=*src++;  }  id_loc=dst;  while (dst<src) *dst++=' '; /* clean up in case of error message display */}@ During the definition and \CEE/ parts of a section, cross-referencesare made for all identifiers except reserved words. However, the rightidentifier in a format definition is not referenced, and the leftidentifier is referenced only if it has been explicitlyunderlined (preceded by \.{@@!}).The \TEX/ code in comments is, of course, ignored, except for\CEE/ portions enclosed in \pb; the text of a section name is skippedentirely, even if it contains \pb\ constructions.The variables |lhs| and |rhs| point to the respective identifiers involvedin a format definition.@<Global...@>=name_pointer lhs, rhs; /* pointers to |byte_start| for format identifiers */name_pointer res_wd_end; /* pointer to the first nonreserved identifier */@ When we get to the following code we have |next_control>=format_code|.@<Store cross-references in the d...@>=while (next_control<=definition) { /* |format_code| or |definition| */  if (next_control==definition) {    xref_switch=def_flag; /* implied \.{@@!} */    next_control=get_next();  } else @<Process a format definition@>;  outer_xref();}@ Error messages for improper format definitions will be issued in phasetwo. Our job in phase one is to define the |ilk| of a properly formattedidentifier, and to remove cross-references to identifiers that we nowdiscover should be unindexed.@<Process a form...@>= {  next_control=get_next();  if (next_control==identifier) {    lhs=id_lookup(id_first, id_loc,normal); lhs->ilk=normal;    if (xref_switch) new_xref(lhs);    next_control=get_next();    if (next_control==identifier) {      rhs=id_lookup(id_first, id_loc,normal);      lhs->ilk=rhs->ilk;      if (unindexed(lhs)) { /* retain only underlined entries */        xref_pointer q,r=NULL;        for (q=(xref_pointer)lhs->xref;q>xmem;q=q->xlink)          if (q->num<def_flag)            if (r) r->xlink=q->xlink;            else lhs->xref=(char*)q->xlink;          else r=q;      }      next_control=get_next();    }  }}@ A much simpler processing of format definitions occurs when thedefinition is found in limbo.@<Process simple format in limbo@>={  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");@.Missing right identifier...@>    else {      rhs=id_lookup(id_first,id_loc,normal);      lhs->ilk=rhs->ilk;    }  }}@ Finally, when the \TEX/ and definition parts have been treated, we have|next_control>=begin_C|.@<Store cross-references in the \CEE/...@>=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;    if(cur_section_char=='(' && cur_section!=name_dir)      set_file_flag(cur_section);  }  do {    if (next_control==section_name && cur_section!=name_dir)      new_section_xref(cur_section);    next_control=get_next(); outer_xref();  } while ( next_control<=section_name);}@ After phase one has looked at everything, we want to check that eachsection name was both defined and used.  The variable |cur_xref| will pointto cross-references for the current section name of interest.@<Global...@>=xref_pointer cur_xref; /* temporary cross-reference pointer */boolean an_output; /* did |file_flag| precede |cur_xref|? */@ The following recursive procedurewalks through the tree of section names and prints out anomalies.@^recursion@>@<Predecl...@>=void section_check();@ @cvoidsection_check(p)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=1; cur_xref=cur_xref->xlink;}    else an_output=0;    if (cur_xref->num <def_flag) {      printf("\n! Never defined: <"); print_section_name(p); putchar('>'); mark_harmless;@.Never defined: <section name>@>    }    while (cur_xref->num >=cite_flag) cur_xref=cur_xref->xlink;    if (cur_xref==xmem && !an_output) {      printf("\n! Never used: <"); print_section_name(p); putchar('>'); mark_harmless;@.Never used: <section name>@>    }    section_check(p->rlink);  }}@ @<Print error messages about un...@>=section_check(root)@* Low-level output routines.The \TEX/ output is supposed to appear in lines at most |line_length|characters long, so we place it into an output buffer. During the outputprocess, |out_line| will hold the current line number of the line about tobe output.@<Global...@>=char out_buf[line_length+1]; /* assembled characters */char *out_ptr; /* just after last character in |out_buf| */char *out_buf_end = out_buf+line_length; /* end of |out_buf| */int out_line; /* number of next line to be output */@ The |flush_buffer| routine empties the buffer up to a given breakpoint,and moves any remaining characters to the beginning of the next line.If the |per_cent| parameter is 1 a |'%'| is appended to the linethat is being output; in this case the breakpoint |b| should be strictlyless than |out_buf_end|. If the |per_cent| parameter is |0|,trailing blanks are suppressed.The characters emptied from the buffer form a new line of output;if the |carryover| parameter is true, a |"%"| in that line will becarried over to the next line (so that \TEX/ will ignore the completionof commented-out text).@d c_line_write(c) fflush(active_file),fwrite(out_buf+1,sizeof(char),c,active_file)@d tex_putc(c) putc(c,active_file)@d tex_new_line putc('\n',active_file)@d tex_printf(c) fprintf(active_file,c)@cvoidflush_buffer(b,per_cent,carryover)char *b;  /* outputs from |out_buf+1| to |b|,where |b<=out_ptr| */boolean per_cent,carryover;{  char *j; j=b; /* pointer into |out_buf| */  if (! per_cent) /* remove trailing blanks */    while (j>out_buf && *j==' ') j--;  c_line_write(j-out_buf);  if (per_cent) tex_putc('%');  tex_new_line; out_line++;  if (carryover)    while (j>out_buf)      if (*j--=='%' && (j==out_buf || *j!='\\')) {        *b--='%'; break;      }  if (b<out_ptr) strncpy(out_buf+1,b+1,out_ptr-b);  out_ptr-=b-out_buf;}@ When we are copying \TEX/ source material, we retain line breaksthat occur in the input, except that an empty line is notoutput when the \TEX/ source line was nonempty. For example, a lineof the \TEX/ file that contains only an index cross-reference entrywill not be copied. The |finish_line| routine is called just before|get_line| inputs a new line, and just after a line break token hasbeen emitted during the output of translated \CEE/ text.@cvoidfinish_line() /* do this at the end of a line */{  char *k; /* pointer into |buffer| */  if (out_ptr>out_buf) flush_buffer(out_ptr,0,0);  else {    for (k=buffer; k<=limit; k++)      if (!(xisspace(*k))) return;    flush_buffer(out_buf,0,0);  }}@ In particular, the |finish_line| procedure is called near the verybeginning of phase two. We initialize the output variables in a slightlytricky way so that the first line of the output file will be`\.{\\input cwebmac}'.@<Set init...@>=out_ptr=out_buf+1; out_line=1; active_file=tex_file;*out_ptr='c'; tex_printf("\\input cwebma");@ When we wish to append one character |c| to the output buffer, we write`|out(c)|'; this will cause the buffer to be emptied if it was alreadyfull.  If we want to append more than one character at once, we say|out_str(s)|, where |s| is a string containing the characters.A line break will occur at a space or after a single-nonletter\TEX/ control sequence.@d out(c) {if (out_ptr>=out_buf_end) break_out(); *(++out_ptr)=c;}@cvoidout_str(s) /* output characters from |s| to end of string */char *s;{  while (*s) out(*s++);}@ The |break_out| routine is called just before the output buffer is aboutto overflow. To make this routine a little faster, we initialize position0 of the output buffer to `\.\\'; this character isn't really output.@<Set init...@>=out_buf[0]='\\';@ A long line is broken at a blank space or just before a backslash that isn'tpreceded by another backslash. In the latter case, a |'%'| is output atthe break.@<Predecl...@>=void break_out();@ @cvoidbreak_out() /* finds a way to break the output line */{  char *k=out_ptr; /* pointer into |out_buf| */  while (1) {    if (k==out_buf) @<Print warning message, break the line, |return|@>;    if (*k==' ') {      flush_buffer(k,0,1); return;    }    if (*(k--)=='\\' && *k!='\\') { /* we've decreased |k| */      flush_buffer(k,1,1); return;    }  }}@ We get to this section only in the unusual case that the entire output lineconsists of a string of backslashes followed by a string of nonblanknon-backslashes. In such cases it is almost always safe to break the

⌨️ 快捷键说明

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