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

📄 gb_save.w

📁 模拟器提供了一个简单易用的平台
💻 W
📖 第 1 页 / 共 3 页
字号:
      (char*)(v+1)<=cur_block->end_addr && cur_block->cat==vrt;v++) {    lookup(v->arcs,'A');    lookup(v->u,g->util_types[0]);    lookup(v->v,g->util_types[1]);    lookup(v->w,g->util_types[2]);    lookup(v->x,g->util_types[3]);    lookup(v->y,g->util_types[4]);    lookup(v->z,g->util_types[5]);  }}@ @<Explore a block of supposed arc records@>={@+register Arc*a;  for (a=(Arc*)cur_block->start_addr;@|      (char*)(a+1)<=cur_block->end_addr && cur_block->cat==ark;a++) {    lookup(a->tip,'V');    lookup(a->next,'A');    lookup(a->a,g->util_types[6]);    lookup(a->b,g->util_types[7]);  }}@ OK, the first pass is complete. And the second pass is routine:@<Translate |g| into external format@>=@<Orient the |blocks| table for translation@>;@<Initialize the output buffer mechanism and output the first line@>;@<Translate the |Graph| record@>;@<Translate the |Vertex| records@>;@<Translate the |Arc| records@>;@<Output the checksum line@>;@ During this pass we decrease the |end_addr| field of a |block_rep|,so that it points to the first byte ofthe final record in a |vrt| or |ark| block.The variables |m| and |n| are set to the number of arc records andvertex records, respectively.@<Local variables for |save...@>=long m; /* total number of |Arc| records to be translated */long n; /* total number of |Vertex| records to be translated */register long s; /* accumulator register for arithmetic calculations */@ One tricky point needs to be observed, in the unusual case thatthere are two or more blocks of \&{Vertex} records: The base block|g->vertices| must come first in the final ordering. (This is the onlyexception to the rule that \&{Vertex} and \&{Arc} records each retaintheir relative order with respect to less-than and greater-than.)@<Orient the |blocks| table for translation@>=m=0;@+@<Set |n| to the size of the block that starts with |g->vertices|@>;for (cur_block=blocks+block_count-1;cur_block>=blocks;cur_block--) {  if (cur_block->cat==vrt) {    s=(cur_block->end_addr-cur_block->start_addr)/sizeof(Vertex);    cur_block->end_addr=cur_block->start_addr+((s-1)*sizeof(Vertex));    if (cur_block->start_addr!=(char*)g->vertices) {      cur_block->offset=n;@+ n+=s;    } /* otherwise |cur_block->offset| remains zero */  }@+else if (cur_block->cat==ark) {    s=(cur_block->end_addr-cur_block->start_addr)/sizeof(Arc);    cur_block->end_addr=cur_block->start_addr+((s-1)*sizeof(Arc));    cur_block->offset=m;    m+=s;  }}@ @<Set |n| to the size of the block that starts with |g->vertices|@>=n=0;for (cur_block=blocks+block_count-1;cur_block>=blocks;cur_block--)  if (cur_block->start_addr==(char *)g->vertices) {    n=(cur_block->end_addr-cur_block->start_addr)/sizeof(Vertex);    break;  }@ We will store material to be output in the |buffer| array,so that we can compute the correct checksum.@<Private v...@>=static char *buf_ptr; /* the first unfilled position in |buffer| */static long magic; /* the checksum */@ @<Private f...@>=static void flushout() /* output the buffer to |save_file| */{  *buf_ptr++='\n';  *buf_ptr='\0';  magic=new_checksum(buffer,magic);  fputs(buffer,save_file);  buf_ptr=buffer;}@ If a supposed string pointer is zero, we output the null string.(This case arises when a string field has not been initialized,for example in vertices and arcs that have been allocated but not used.)@<Private f...@>=static void prepare_string(s)  char *s; /* string that is moved to |item_buf| */{@+register char *p,*q;  item_buf[0]='"';  p=&item_buf[1];  if (s==0) goto sready;  for (q=s;*q&&p<=&item_buf[MAX_SV_STRING];q++,p++)    if (*q=='"'||*q=='\n'||*q=='\\'||imap_ord(*q)==unexpected_char) {      anomalies |= bad_string_char;      *p='?';    }@+else *p=*q;  if (*q) anomalies |= string_too_long;sready:  *p='"';  *(p+1)='\0';}@ The main idea of this part of the program is to format an item into|item_buf|, then move it to |buffer|, making sure that there is alwaysroom for a comma.@d append_comma *buf_ptr++=','@<Private f...@>=static void move_item(){@+register long l=strlen(item_buf);  if (buf_ptr+l>&buffer[78]) {    if (l<=78) flushout();    else {@+register char *p=item_buf;      if (buf_ptr>&buffer[77]) flushout();           /* no room for initial \.{\char`\"} */      do@+{        for (;buf_ptr<&buffer[78];buf_ptr++,p++,l--) *buf_ptr=*p;        *buf_ptr++='\\';        flushout();      }@+while(l>78);    strcpy(buffer,p);    buf_ptr=&buffer[l];    return;    }  }  strcpy(buf_ptr,item_buf);  buf_ptr+=l;}   @ @<Initialize the output buffer mechanism and output the first line@>=buf_ptr=buffer;magic=0;fputs("* GraphBase graph (util_types ",save_file);{@+register char*p;  for (p=g->util_types;p<g->util_types+14;p++)    if (*p=='Z'||*p=='I'||*p=='V'||*p=='S'||*p=='A') fputc(*p,save_file);    else fputc('Z',save_file);}fprintf(save_file,",%ldV,%ldA)\n",n,m);@ A macro called |trans|, which is sort of an inverse to |fillin|,takes care of the main work in the second pass.@d trans(l,t) translate_field((util*)&(l),t)@<Private f...@>=static void translate_field(l,t)  util *l; /* address of field to be output in symbolic form */  char t; /* type of formatting desired */{@+register block_rep *cur_block;  register char* loc;  register long tcat; /* category corresponding to |t| */  register long tsize; /* record size corresponding to |t| */  if (comma_expected) append_comma;  else comma_expected=1;  switch (t) { default: anomalies|=bad_type_code;    /* fall through to case \.Z */ case 'Z': buf_ptr--; /* forget spurious comma */  if (l->I) anomalies|=ignored_data;  return; case 'I': numeric: sprintf(item_buf,"%ld",l->I);@+goto ready; case 'S': prepare_string(l->S);@+goto ready; case 'V': if (l->I==1) goto numeric;    tcat=vrt;@+tsize=sizeof(Vertex);@+break; case 'A': tcat=ark;@+tsize=sizeof(Arc);@+break;  }  @<Translate a pointer variable@>;ready:move_item();}@ @<Translate a pointer variable@>=loc=(char*)l->V;item_buf[0]='0';@+item_buf[1]='\0'; /* |NULL| will be the default */if (loc==NULL) goto ready;for (cur_block=blocks; cur_block->start_addr>loc; cur_block++) ;if (loc>cur_block->end_addr) {  anomalies|=addr_not_in_data_area;  goto ready;}if (cur_block->cat!=tcat||(loc-cur_block->start_addr)%tsize!=0) {  anomalies|=addr_in_mixed_block;  goto ready;}sprintf(item_buf,"%c%ld",t,  cur_block->offset+((loc-cur_block->start_addr)/tsize));@ @<Translate the |Graph| record@>=prepare_string(g->id);if (strlen(g->id)>MAX_SV_ID) {  strcpy(item_buf+MAX_SV_ID+1,"\"");  anomalies|=string_too_long;}move_item();comma_expected=1;trans(g->n,'I');trans(g->m,'I');trans(g->uu,g->util_types[8]);trans(g->vv,g->util_types[9]);trans(g->ww,g->util_types[10]);trans(g->xx,g->util_types[11]);trans(g->yy,g->util_types[12]);trans(g->zz,g->util_types[13]);flushout();@ @<Translate the |Vertex| records@>={@+register Vertex* v;  fputs("* Vertices\n",save_file);  for (cur_block=blocks+block_count-1;cur_block>=blocks;cur_block--)    if (cur_block->cat==vrt && cur_block->offset==0)      @<Translate all |Vertex| records in |cur_block|@>;  for (cur_block=blocks+block_count-1;cur_block>=blocks;cur_block--)    if (cur_block->cat==vrt && cur_block->offset!=0)      @<Translate all |Vertex| records in |cur_block|@>;}@ @<Translate all |Vertex| records in |cur_block|@>=for (v=(Vertex*)cur_block->start_addr;     v<=(Vertex*)cur_block->end_addr;v++) {  comma_expected=0;  trans(v->name,'S');  trans(v->arcs,'A');  trans(v->u,g->util_types[0]);  trans(v->v,g->util_types[1]);  trans(v->w,g->util_types[2]);  trans(v->x,g->util_types[3]);  trans(v->y,g->util_types[4]);  trans(v->z,g->util_types[5]);  flushout();}@ @<Translate the |Arc| records@>={@+register Arc* a;  fputs("* Arcs\n",save_file);  for (cur_block=blocks+block_count-1;cur_block>=blocks;cur_block--)    if (cur_block->cat==ark)      for (a=(Arc*)cur_block->start_addr;a<=(Arc*)cur_block->end_addr;a++) {        comma_expected=0;        trans(a->tip,'V');        trans(a->next,'A');        trans(a->len,'I');        trans(a->a,g->util_types[6]);        trans(a->b,g->util_types[7]);        flushout();      }}@ @<Output the checksum line@>=fprintf(save_file,"* Checksum %ld\n",magic);@ @<Make notes at the end of the file about any changes that were necessary@>=if (anomalies) {  fputs("> WARNING: I had trouble making this file from the given graph!\n",    save_file);  if (anomalies&bad_type_code)    fputs(">> The original util_types had to be corrected.\n",save_file);  if (anomalies&ignored_data)    fputs(">> Some data suppressed by Z format was actually nonzero.\n",      save_file);  if (anomalies&string_too_long)    fputs(">> At least one long string had to be truncated.\n",      save_file);  if (anomalies&bad_string_char)    fputs(">> At least one string character had to be changed to '?'.\n",      save_file);  if (anomalies&addr_not_in_data_area)    fputs(">> At least one pointer led out of the data area.\n",save_file);  if (anomalies&addr_in_mixed_block)    fputs(">> At least one data block had an illegal mixture of records.\n",      save_file);  if (anomalies&(addr_not_in_data_area+addr_in_mixed_block))    fputs(">>  (Pointers to improper data have been changed to 0.)\n",      save_file);  fputs("> You should be able to read this file with restore_graph,\n",      save_file);  fputs("> but the graph you get won't be exactly like the original.\n",      save_file);}@* Index. Here is a list that shows where the identifiers of this program aredefined and used.

⌨️ 快捷键说明

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