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

📄 common.w

📁 模拟器提供了一个简单易用的平台
💻 W
📖 第 1 页 / 共 4 页
字号:
was printed but no serious errors were detected; |error_message| means thatat least one error was found; |fatal_message| means that the programterminated abnormally. The value of |history| does not influence thebehavior of the program; it is simply computed for the convenienceof systems that might want to use such information.@d spotless 0 /* |history| value for normal jobs */@d harmless_message 1 /* |history| value when non-serious info was printed */@d error_message 2 /* |history| value when an error was noted */@d fatal_message 3 /* |history| value when we had to stop prematurely */@d mark_harmless {if (history==spotless) history=harmless_message;}@d mark_error history=error_message@<Definit...@>=int history=spotless; /* indicates how bad this run was */@ The command `|err_print("! Error message")|' will report a syntax error tothe user, by printing the error message at the beginning of a new line andthen giving an indication of where the error was spotted in the source file.Note that no period follows the error message, since the error routinewill automatically supply a period. A newline is automatically suppliedif the string begins with |"!"|.@<Predecl...@>=void  err_print();@ @cvoiderr_print(s) /* prints `\..' and location of error message */char *s;{  char *k,*l; /* pointers into |buffer| */  printf(*s=='!'? "\n%s" : "%s",s);  if(web_file_open) @<Print error location based on input buffer@>;  update_terminal; mark_error;}@ The error locations can be indicated by using the global variables|loc|, |cur_line|, |cur_file_name| and |changing|,which tell respectively the firstunlooked-at position in |buffer|, the current line number, the currentfile, and whether the current line is from |change_file| or |cur_file|.This routine should be modified on systems whose standard text editorhas special line-numbering conventions.@^system dependencies@>@<Print error location based on input 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);l= (loc>=limit? limit: loc);if (l>buffer) {  for (k=buffer; k<l; k++)    if (*k=='\t') putchar(' ');    else putchar(*k); /* print the characters already read */  putchar('\n');  for (k=buffer; k<l; k++) putchar(' '); /* space out the next line */}for (k=l; k<limit; k++) putchar(*k); /* print the part not yet read */if (*limit=='|') putchar('|'); /* end of \CEE/ text in section names */putchar(' '); /* to separate the message from future asterisks */}@ When no recovery from some error has been provided, we have to wrapup and quit as graciously as possible.  This is done by calling thefunction |wrap_up| at the end of the code.\.{CTANGLE} and \.{CWEAVE} have their own notions about how toprint the job statistics.@<Prede...@>=int wrap_up();extern void print_stats();@ Some implementations may wish to pass the |history| value to theoperating system so that it can be used to govern whether or not otherprograms are started. Here, for instance, we pass the operating systema status of 0 if and only if only harmless messages were printed.@^system dependencies@>@cint wrap_up() {  putchar('\n');  if (show_stats)    print_stats(); /* print statistics about memory usage */  @<Print the job |history|@>;  if (history > harmless_message) return(1);  else return(0);}@ @<Print the job |history|@>=switch (history) {case spotless: if (show_happiness) printf("(No errors were found.)\n"); break;case harmless_message:  printf("(Did you see the warning message above?)\n"); break;case error_message:  printf("(Pardon me, but I think I spotted something wrong.)\n"); break;case fatal_message: printf("(That was a fatal error, my friend.)\n");} /* there are no other cases */@ When there is no way to recover from an error, the |fatal| subroutine isinvoked. This happens most often when |overflow| occurs.@<Predec...@>=void fatal(), overflow();@ The two parameters to |fatal| are strings that are essentiallyconcatenated to print the final error message.@c voidfatal(s,t)  char *s,*t;{  if (*s) printf(s);  err_print(t);  history=fatal_message; exit(wrap_up());}@ An overflow stop occurs if \.{CWEB}'s tables aren't large enough.@c voidoverflow(t)  char *t;{  printf("\n! Sorry, %s capacity exceeded",t); fatal("","");}@.Sorry, capacity exceeded@>@ Sometimes the program's behavior is far different from what it should be,and \.{CWEB} prints an error message that is really for the \.{CWEB}maintenance person, not the user. In such cases the program says|confusion("indication of where we are")|.@d confusion(s) fatal("! This can't happen: ",s)@.This can't happen@>@** Command line arguments.The user calls \.{CWEAVE} and \.{CTANGLE} with arguments on the command line.These are either file names or flags to be turned off (beginning with |"-"|)or flags to be turned on (beginning with |"+"|).The following globals are for communicating the user's desires to the restof the program. The various file name variables contain strings withthe names of those files. Most of the 128 flags are undefined but availablefor future extensions.@d show_banner flags['b'] /* should the banner line be printed? */@d show_progress flags['p'] /* should progress reports be printed? */@d show_stats flags['s'] /* should statistics be printed at end of run? */@d show_happiness flags['h'] /* should lack of errors be announced? */@<Defin...@>=int argc; /* copy of |ac| parameter to |main| */char **argv; /* copy of |av| parameter to |main| */char C_file_name[max_file_name_length]; /* name of |C_file| */char tex_file_name[max_file_name_length]; /* name of |tex_file| */char idx_file_name[max_file_name_length]; /* name of |idx_file| */char scn_file_name[max_file_name_length]; /* name of |scn_file| */boolean flags[128]; /* an option for each 7-bit code */@ The |flags| will be initially zero. Some of them are set to~1 beforescanning the arguments; if additional flags are 1 by default theyshould be set before calling |common_init|.@<Set the default options common to \.{CTANGLE} and \.{CWEAVE}@>=show_banner=show_happiness=show_progress=1;@ We now must look at the command line arguments and set the file namesaccordingly.  At least one file name must be present: the \.{CWEB}file.  It may have an extension, or it may omit the extension to get |".w"| or|".web"| added.  The \TEX/ output file name is formed by replacing the \.{CWEB}file name extension by |".tex"|, and the \CEE/ file name by replacingthe extension by |".c"|, after removing the directory name (if any).If there is a second file name present among the arguments, it is thechange file, again either with an extension or without one to get |".ch"|.An omitted change file argument means that |"/dev/null"| should be used,when no changes are desired.@^system dependencies@>If there's a third file name, it will be the output file.@<Pred...@>=void scan_args();@ @cvoidscan_args(){  char *dot_pos; /* position of |'.'| in the argument */  char *name_pos; /* file name beginning, sans directory */  register char *s; /* register for scanning strings */  boolean found_web=0,found_change=0,found_out=0;             /* have these names been seen? */  boolean flag_change;  while (--argc > 0) {    if ((**(++argv)=='-'||**argv=='+')&&*(*argv+1)) @<Handle flag argument@>@;    else {      s=name_pos=*argv;@+dot_pos=NULL;      while (*s) {        if (*s=='.') dot_pos=s++;        else if (*s=='/') dot_pos=NULL,name_pos=++s;        else s++;      }      if (!found_web) @<Make       |web_file_name|, |tex_file_name|, and |C_file_name|@>@;      else if (!found_change) @<Make |change_file_name| from |fname|@>@;      else if (!found_out) @<Override |tex_file_name| and |C_file_name|@>@;        else @<Print usage error message and quit@>;    }  }  if (!found_web) @<Print usage error message and quit@>;  if (found_change<=0) strcpy(change_file_name,"/dev/null");}@ We use all of |*argv| for the |web_file_name| if there is a |'.'| in it,otherwise we add |".w"|. If this file can't be opened, we prepare an|alt_web_file_name| by adding |"web"| after the dot.The other file names come from adding other thingsafter the dot.  We must check that there is enough room in|web_file_name| and the other arrays for the argument.@<Make |web_file_name|...@>={  if (s-*argv > max_file_name_length-5)    @<Complain about argument length@>;  if (dot_pos==NULL)    sprintf(web_file_name,"%s.w",*argv);  else {    strcpy(web_file_name,*argv);    *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 */  sprintf(idx_file_name,"%s.idx",name_pos);  sprintf(scn_file_name,"%s.scn",name_pos);  sprintf(C_file_name,"%s.c",name_pos);  found_web=1;}@ @<Make |change_file_name|...@>={  if (strcmp(*argv,"-")==0) found_change=-1;  else {    if (s-*argv > max_file_name_length-4)      @<Complain about argument length@>;    if (dot_pos==NULL)      sprintf(change_file_name,"%s.ch",*argv);    else strcpy(change_file_name,*argv);    found_change=1;  }}@ @<Override...@>={  if (s-*argv > max_file_name_length-5)    @<Complain about argument length@>;  if (dot_pos==NULL) {    sprintf(tex_file_name,"%s.tex",*argv);    sprintf(idx_file_name,"%s.idx",*argv);    sprintf(scn_file_name,"%s.scn",*argv);    sprintf(C_file_name,"%s.c",*argv);  } else {    strcpy(tex_file_name,*argv);    strcpy(C_file_name,*argv);    if (flags['x']) { /* indexes will be generated */      *dot_pos=0;      sprintf(idx_file_name,"%s.idx",*argv);      sprintf(scn_file_name,"%s.scn",*argv);    }  }  found_out=1;}@ @<Handle flag...@>={  if (**argv=='-') flag_change=0;  else flag_change=1;  for(dot_pos=*argv+1;*dot_pos>'\0';dot_pos++)    flags[*dot_pos]=flag_change;}@ @<Print usage error message and quit@>={if (program==ctangle)  fatal("! Usage: ctangle [options] webfile[.w] [{changefile[.ch]|-} [outfile[.c]]]\n"   ,"");@.Usage:@>else fatal("! Usage: cweave [options] webfile[.w] [{changefile[.ch]|-} [outfile[.tex]]]\n"   ,"");}@ @<Complain about arg...@>= fatal("! Filename too long\n", *argv);@.Filename too long@>@** Output. Here is the code that opens the output file:@^system dependencies@>@<Defin...@>=FILE *C_file; /* where output of \.{CTANGLE} goes */FILE *tex_file; /* where output of \.{CWEAVE} goes */FILE *idx_file; /* where index from \.{CWEAVE} goes */FILE *scn_file; /* where list of sections from \.{CWEAVE} goes */FILE *active_file; /* currently active file for \.{CWEAVE} output */@ @<Scan arguments and open output files@>=scan_args();if (program==ctangle) {  if ((C_file=fopen(C_file_name,"w"))==NULL)    fatal("! Cannot open output file ", C_file_name);@.Cannot open output file@>}else {  if ((tex_file=fopen(tex_file_name,"w"))==NULL)    fatal("! Cannot open output file ", tex_file_name);}@ The |update_terminal| procedure is called when we wantto make sure that everything we have output to the terminal so far hasactually left the computer's internal buffers and been sent.@^system dependencies@>@d update_terminal fflush(stdout) /* empty the terminal output buffer */@ Terminal output uses |putchar| and |putc| when we have totranslate from \.{CWEB}'s code into the external character code,and |printf| when we just want to print strings.Several macros make other kinds of output convenient.@^system dependencies@>@d new_line putchar('\n') @d putxchar putchar@d term_write(a,b) fflush(stdout),fwrite(a,sizeof(char),b,stdout)@d C_printf(c,a) fprintf(C_file,c,a)@d C_putc(c) putc(c,C_file) /* isn't \CEE/ wonderfully consistent? */@ 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 */@** Index.

⌨️ 快捷键说明

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