home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 5 / DATAFILE_PDCD5.iso / utilities / m / makedrawf / Source / c / decdrawf next >
Encoding:
Text File  |  1996-12-05  |  17.6 KB  |  565 lines

  1. /* Decode a drawfile into a format mkdrawf (new version) will understand */
  2.  
  3. /* System dependencies:
  4.  *  - I think it assumes 32 bits, LSB first.
  5.  *  - the "lowfile" routines used are RISC OS specific; but you could
  6.  *    substitute |open()| etc on Unix boxes.
  7.  */
  8.  
  9. /* #define ONLINE_MEDIA for a few trivial changes:
  10.  *  - include bbox for text item
  11.  *  - nothing more, so far
  12.  */
  13.  
  14. #define VERSION_STRING "3.07 (4/12/1996)"
  15.  
  16. #include <ctype.h>
  17. #include <stdarg.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include "lowfile.h"
  22.  
  23. static int short_errors=0;
  24. static char *file_name=0;
  25. static int file_handle=0;
  26. static int file_size=0;
  27. static int *space=0;
  28. static int depth=0;
  29. static int return_code=0;
  30. static char *prog_name="decdrawf";
  31. static FILE *sprite_file=0;
  32. static char *sprite_file_name=0;
  33. static int n_sprites=0;
  34. static int n_sprites_space=0;    /* number of sprites space in table */
  35. typedef struct {
  36.   int name[3];    /* 12 bytes, zero-padded, case insignificant */
  37.   int *pos;    /* pointer to place in drawfile */
  38. } sprite_rec;
  39. /* We just have an array, and search sequentially, rather than having
  40.  * a hash table, because (1) it's easier, (2) we generally expect fairly
  41.  * few sprites, and (3) it's more easily extensible.
  42.  */
  43. static sprite_rec *sprites;
  44. /* JPEGs are almost always big. We write each to a separate file.
  45.  */
  46. static char *jpeg_prefix=0;
  47. static int jpeg_next=1;
  48. static char *jpeg_name=0;
  49.  
  50. static double unit=1;    /* number of points per unit */
  51. static char *unit_string="";
  52.  
  53. typedef struct { char *name; char *fullname; double size; } Units;
  54. static Units units[] = {
  55.   { "pt", "$Points", 1. },
  56.   { "in", "$Inches", 72. },
  57.   { "cm", "$Centimetres", 28.3464566929134 },
  58.   { "mm", "$Millimetres", 2.83464566929134 },
  59.   { "sp", "$ScaledPoints", 1./640 },
  60.   { "os", "$OSUnits", 72./180 },
  61.   { 0,0,0 }
  62. };
  63.  
  64. static void err_head(int *a, char *type) {
  65.   if (short_errors) {
  66.     if (a) fprintf(stderr,"At offset %X: %s: ",(a-space)<<2,type);
  67.     else fprintf(stderr,"%s: ",type);
  68.   } else {
  69.     if (a)
  70.       fprintf(stderr,"! %s from %s...\nAt or near offset %X in `%s':\n",
  71.               type, prog_name, (a-space)<<2, file_name);
  72.     else
  73.        fprintf(stderr,"! %s from %s...\nIn `%s':\n",
  74.               type, prog_name, file_name);
  75.   }
  76. }
  77.  
  78. static void warn(int *a, char *s, ...) {
  79.   va_list ap;
  80.   va_start(ap,s);
  81.   err_head(a,"Warning");
  82.   vfprintf(stderr,s,ap);
  83.   va_end(ap);
  84.   fprintf(stderr,".\n");
  85.   if (return_code<4) return_code=4;
  86. }
  87.  
  88. static void error(int *a, char *s, ...) {
  89.   va_list ap;
  90.   va_start(ap,s);
  91.   err_head(a,"Error");
  92.   vfprintf(stderr,s,ap);
  93.   va_end(ap);
  94.   fprintf(stderr,".\n");
  95.   exit(8);
  96. }
  97.  
  98. static void *xmalloc(unsigned int n, char *s) {
  99.   void *p=malloc(n);
  100.   if (p) return p;
  101.   error(0,"Out of space, trying to allocate %d bytes for %s",n,s);
  102.   /* this doesn't happen: */
  103.   return 0;
  104. }
  105.  
  106. static void *xrealloc(void *p,unsigned n,char *s) {
  107.   void *q=realloc(p,n);
  108.   if (q) return q;
  109.   error(0,"Out of space, trying to reallocate space for %s to %d bytes",
  110.         s,n);
  111.   /* this doesn't happen: */
  112.   return 0;
  113. }
  114.  
  115. static void print_coord(int *a) {
  116.   printf("%lg %lg",a[0]/(640*unit),a[1]/(640*unit));
  117. }
  118.  
  119. static void print_line(char *s, ...) {
  120.   va_list ap;
  121.   va_start(ap,s);
  122.   printf("%*s",depth*2,"");
  123.   vprintf(s,ap);
  124.   printf("\n");
  125.   va_end(ap);
  126. }
  127.  
  128. static void indent(void) {
  129.   printf("%*s",depth*2,"");
  130. }
  131.  
  132. static char *int2col(int *a, unsigned int c) {
  133.   static char cc[]="r000g000b000";
  134.   if (c==0xFFFFFFFF) return "Transparent";
  135.   if (c&255) warn(a,"Dodgy RGB colour %08X",c);
  136.   sprintf(cc,"r%dg%db%d",(c>>8)&255,(c>>16)&255,(c>>24)&255);
  137.   return cc;
  138. }
  139.  
  140. static void print_string(char *s) {
  141.   char c;
  142.   putchar('"');
  143.   while ((c=*s++)!=0) {
  144.     if (c=='\\' || c=='"') putchar('\\');
  145.     putchar(c);
  146.   }
  147.   putchar('"');
  148. }
  149.  
  150. /* Return zero for *failure*.
  151.  */
  152. static int open_sprite_file(int *s) {
  153.   n_sprites_space=16;
  154.   sprites=(sprite_rec*)xmalloc(n_sprites*sizeof(sprite_rec),"sprites");
  155.   sprite_file=fopen(sprite_file_name,"w+b");
  156.   if (!sprite_file) {
  157.     warn(s,"Couldn't open sprite file `%s'",sprite_file_name);
  158.     return 0; }
  159.   fseek(sprite_file,12,SEEK_SET);
  160.   return 1;
  161. }
  162.  
  163. /* Write relevant things at start of sprite file, and set its type
  164.  * correctly.
  165.  */
  166. static void close_sprite_file(void) {
  167.   long z[3];
  168.   char cl[300];
  169.   z[0]=n_sprites;
  170.   z[1]=16;
  171.   z[2]=ftell(sprite_file)+4;
  172.   fseek(sprite_file,0,SEEK_SET);
  173.   fwrite(z,12,1,sprite_file);
  174.   fclose(sprite_file);
  175.   sprintf(cl,"SetType %s Sprite",sprite_file_name);
  176.   system(cl);
  177. }
  178.  
  179. /* return non0 if sprite names equivalent:
  180.  */
  181. static int cistreq12(const int *a, const int *b) {
  182.   int i;
  183.   for (i=0;i<12;++i)
  184.     if (tolower(((char*)a)[i])!=tolower(((char*)b)[i]))
  185.       return 0;
  186.   return 1;
  187. }
  188.  
  189. /* |s| points to sprite; |sz| is size in bytes
  190.  */
  191. static void write_sprite(int *s, int sz) {
  192.   if (s[0]!=sz) warn(s,"Sprite size mismatch");
  193.   if (sprite_file_name && (sprite_file || open_sprite_file(s))) {
  194.     /* check whether a sprite with this name has already been written */
  195.     int i;
  196.     for (i=0;i<n_sprites;++i)
  197.       if (cistreq12(sprites[i].name,s+1)) {
  198.         /* Same name. Same sprite? */
  199.         if (!memcmp(sprites[i].pos,s,sz)) goto prn;
  200.         warn(s,"Different sprites with identical name `%.12s'",(char*)(s+1));
  201.         goto zog; }
  202.     /* no earlier sprite had same name */
  203.     if (n_sprites<=n_sprites_space) {
  204.       /* need more space for remembering sprites */
  205.       n_sprites_space<<=1;
  206.       sprites=(sprite_rec*)
  207.               xrealloc(sprites,n_sprites_space*sizeof(sprite_rec),"sprites");
  208.     }
  209. zog:
  210.     memcpy(sprites[n_sprites].name,s+1,12);
  211.     sprites[n_sprites].pos=s;
  212.     if (!fwrite(s,sz,1,sprite_file)) error(s,"Error writing sprite file");
  213.     ++n_sprites;
  214. prn:
  215.     indent();
  216.     printf("FromFile \"%s\" \"%.12s\"\n",sprite_file_name,(char*)(s+1));
  217.   } else {
  218.     int i=0;
  219.     sz>>=2;
  220.     indent();
  221.     while (i<sz) {
  222.       printf("0x%08X",s[i++]);
  223.       if (i&3) printf(" ");
  224.       else if (i<sz) { printf("\n"); indent(); }
  225.     }
  226.     printf("\n");
  227.   }
  228. }
  229.  
  230. static int do_object(int *a) {
  231.   int type; int size;
  232.   type=a[0]; size=a[1]/4;
  233.   if (type!=0) {
  234.     indent(); printf("# BoundingBox  ");
  235.     print_coord(a+2); printf("  "); print_coord(a+4); a+=6;
  236.     printf("\n");
  237.     if (type==11) print_line("# (By the way, those should all have been 0)");
  238.   }
  239.   else a+=2;
  240.   switch(type) {
  241.     case 0: /* font table */
  242.       print_line("FontTable {"); ++depth;
  243.       { char *cp=(char *)a; int i=0,l=(size-2)*4;
  244.         while (i+3<l) {
  245.           indent(); printf("%d ",cp[i++]);
  246.           print_string(cp+i); printf("\n");
  247.           i+=strlen(cp+i)+1;
  248.           /* i=(i+3)&~3; */
  249.         }
  250.       }
  251.       --depth; print_line("}");
  252.       break;
  253.     case 1: /* text */
  254.       print_line("Text {"); ++depth;
  255. #ifdef ONLINE_MEDIA
  256.       indent(); printf("BoundingBox  ");
  257.       print_coord(a-4); printf("  ");
  258.       print_coord(a-2); printf("\n");
  259. #endif
  260. do_text:
  261.       print_line("Colour %s",int2col(a,a[0]));
  262.       print_line("Background %s",int2col(a+1,a[1]));
  263.       print_line("Style %d",a[2]);
  264.       indent(); printf("Size "); print_coord(a+3); printf("\n");
  265.       indent(); printf("StartAt "); print_coord(a+5); printf("\n");
  266.       indent(); printf("Text "); print_string((char *)(a+7));
  267.       printf("\n");
  268.       --depth; print_line("}");
  269.       break;
  270.     case 2: /* path */
  271.       print_line("Path {"); ++depth;
  272.       print_line("FillColour %s",int2col(a,a[0]));
  273.       print_line("OutlineColour %s",int2col(a+1,a[1]));
  274.       print_line("Width %lg",((unsigned int)a[2])/(640*unit));
  275.       { unsigned int st=(unsigned int)a[3];
  276.         if (((st&0xFFFF)!=66) ||
  277.             ((((st&12)==12)||((st&48)==48)) && (st>>16!=0x201))) {
  278.           print_line("Style {"); ++depth;
  279.           print_line("# 0x%.08X",st);
  280.           if (st&3) switch(st&3) {
  281.             case 0: print_line("Mitred"); break;
  282.             case 1: print_line("Round"); break;
  283.             case 2: /* print_line("Bevelled"); */ break;
  284.             default: warn(a+3,"Dodgy join type");
  285.           }
  286.           if ((st>>2)&3) switch((st>>2)&3) {
  287.             case 1: print_line("EndCap Round"); break;
  288.             case 2: print_line("EndCap Square"); break;
  289.             case 3: print_line("EndCap Triangular"); break;
  290.           }
  291.           if ((st>>4)&3) switch((st>>4)&3) {
  292.             case 1: print_line("StartCap Round"); break;
  293.             case 2: print_line("StartCap Square"); break;
  294.             case 3: print_line("StartCap Triangular"); break;
  295.           }
  296.           if (!(st&64)) print_line("WindingRule NonZero");
  297.           if (st&128) {
  298.             int i;
  299.             print_line("Dash {"); ++depth;
  300.             print_line("Offset %lg",a[4]/(640*unit));
  301.             indent();
  302.             for (i=0;i<a[5];++i) printf("%lg ",a[6+i]/(640*unit));
  303.             printf("\n");
  304.             --depth; print_line("}");
  305.           }
  306.           if (st&0xFF00) {
  307.             warn(a+3,"Dodgy path style word");
  308.             print_line("# Something I don't understand");
  309.           }
  310.           if (((st&12)==12)||((st&48)==48)) {
  311.             print_line("CapWidth %d",(st>>16)&255);
  312.             print_line("CapLength %d",(st>>24)&255);
  313.             print_line("# Cap dimensions are in 1/16 of line width");
  314.           }
  315.           --depth; print_line("}");
  316.         }
  317.         else print_line("# Default style");
  318.       }
  319.       { int *b=a+4; int n=0;
  320.         if (a[3]&128) { b+=2+a[5]; }
  321.         while (1) {
  322.           switch(b[n++]) {
  323.             case 0: goto path_done;
  324.             case 2: indent(); printf("Move "); print_coord(b+n); n+=2;
  325.                     printf("\n"); break;
  326.             case 5: print_line("Close"); break;
  327.             case 6: indent(); printf("Curve ");
  328.                     print_coord(b+n); n+=2; printf("  ");
  329.                     print_coord(b+n); n+=2; printf("  ");
  330.                     print_coord(b+n); n+=2;
  331.                     printf("\n"); break;
  332.             case 8: indent(); printf("Line "); print_coord(b+n); n+=2;
  333.                     printf("\n"); break;
  334.             default: warn(b+n-1,"Unknown path item %d",b[n-1]);
  335.           }
  336.         }
  337. path_done: ;
  338.       }
  339.       --depth; print_line("}");
  340.       break;
  341.     case 5: /* sprite */
  342.       print_line("Sprite {"); ++depth;
  343.       indent(); printf("BoundingBox  ");
  344.       print_coord(a-4); printf("  ");
  345.       print_coord(a-2); printf("\n");
  346.       write_sprite(a,(size-6)<<2);
  347.       --depth; print_line("}");
  348.       break;
  349.     case 6: /* group */
  350.       print_line("Group {"); ++depth;
  351.       { char q[13]; int *qq=(int*)q; int n=3; q[12]=0;
  352.         qq[0]=a[0]; qq[1]=a[1]; qq[2]=a[2];
  353.         indent(); printf("Name "); print_string(q); printf("\n");
  354.         while (n<size-6) {
  355.           print_line("# offset-in-group is 0x%X",(n+6)*4);
  356.           n+=do_object(a+n);
  357.         }
  358.       }
  359.       --depth; print_line("}");
  360.       break;
  361.     case 7: /* tagged */
  362.       print_line("Tagged {"); ++depth;
  363.       print_line("Identifier 0x%X",a[0]);
  364.       { int n=1+do_object(a+1);
  365.         a+=n;
  366.         while (n<size-6) { print_line("OtherData 0x%X",*a++); ++n;}
  367.       }
  368.       --depth; print_line("}");
  369.       break;
  370.     case 9: /* text area */
  371.       print_line("TextArea {"); ++depth;
  372.       while (*a) {
  373.         if(a[0]!=10||a[1]!=24) {
  374.           warn(a,"Dodgy non-column in text area");
  375.           print_line("# There should be a column here, but there isn't");
  376.           break;
  377.         }
  378.         indent(); printf("Column ");
  379.         print_coord(a+2); printf("  "); print_coord(a+4); printf("\n");
  380.         a+=6;
  381.       }
  382.       print_line("# Reserved (should be 0): %d %d",a[1],a[2]);
  383.       print_line("Colour %s",int2col(a+3,a[3]));
  384.       print_line("Background %s",int2col(a+4,a[4]));
  385.       print_line("Text {"); ++depth; indent();
  386.       { char *cp=(char*)(a+5); char c;
  387.         while ((c=*cp++)!=0) {
  388.           putchar(c);
  389.           if (c=='\n'&&*cp) indent();
  390.         }
  391.       }
  392.       --depth; print_line("}");
  393.       --depth; print_line("}");
  394.       break;
  395.     case 10: /* text column */
  396.       print_line("# A text column appears here. It shouldn't.");
  397.       warn(a-6,"Misplaced text column");
  398.       break;
  399.     case 11: /* options */
  400.       print_line("Options {"); ++depth;
  401.       indent(); printf("PaperSize %d     # A%d\n",(a[0]>>8)-1,(a[0]>>8)-1);
  402.       print_line("Limits {"); ++depth;
  403.       print_line((a[1]&1)?"Shown":"# not Shown");
  404.       print_line((a[1]&16)?"Landscape":"# Portrait");
  405.       print_line((a[1]&256)?"# Default":"NonDefault");
  406.       --depth; print_line("}");
  407.       print_line("Grid {"); ++depth;
  408.       print_line("Spacing %lg",*((double*)(a+2)));
  409.       print_line("Divisions %d",a[4]);
  410.       print_line(a[5]?"Isometric":"# Rectangular");
  411.       print_line(a[6]?"AutoAdjust":"# no AutoAdjust");
  412.       print_line(a[7]?"Shown":"# not Shown");
  413.       print_line(a[8]?"Lock":"# no Lock");
  414.       print_line(a[9]?"# centimetres":"Inches");
  415.       --depth; print_line("}");
  416.       print_line("Zoom {"); ++depth;
  417.       print_line("Ratio %d %d",a[10],a[11]);
  418.       print_line(a[12]?"Lock":"# no Lock");
  419.       --depth; print_line("}");
  420.       print_line(a[13]?"# toolbox present":"NoToolbox");
  421.       switch(a[14]) {
  422.         case 1: print_line("Mode Line"); break;
  423.         case 2: print_line("Mode ClosedLine"); break;
  424.         case 4: print_line("Mode Curve"); break;
  425.         case 8: print_line("Mode ClosedCurve"); break;
  426.         case 16: print_line("Mode Rectangle"); break;
  427.         case 32: print_line("Mode Ellipse"); break;
  428.         case 64: print_line("Mode Text"); break;
  429.         case 128: print_line("Mode Select"); break;
  430.         default: print_line("# Unknown mode %d",a[14]); break;
  431.       }
  432.       print_line("UndoSize %d",a[15]);
  433.       --depth; print_line("}");
  434.       break;
  435.     case 12: /* xftext */
  436.       print_line("XfText {"); ++depth;
  437.       print_line("Matrix  %lg %lg %lg %lg  %lg %lg",
  438.                  a[0]/65536.,a[1]/65536.,a[2]/65536.,a[3]/65536.,
  439.                  a[4]/(1000*unit),a[5]/(1000*unit));
  440.       indent();
  441.       if (a[6]&1) printf("Kerned ");
  442.       if (a[6]&2) printf("RightToLeft ");
  443.       if ((a[6]&3)!=3) {
  444.         printf("# ");
  445.         if (!(a[6]&1)) printf("not-kerned ");
  446.         if (!(a[6]&2)) printf("left-to-right");
  447.       }
  448.       printf("\n");
  449.       a+=7; goto do_text;
  450.     case 13: /* xfsprite */
  451.       print_line("XfSprite {"); ++depth;
  452.       indent(); printf("BoundingBox  ");
  453.       print_coord(a-4); printf("  ");
  454.       print_coord(a-2); printf("\n");
  455.       print_line("Matrix  %lg %lg %lg %lg  %lg %lg",
  456.                  a[0]/65536.,a[1]/65536.,a[2]/65536.,a[3]/65536.,
  457.                  a[4]/(1000*unit),a[5]/(1000*unit));
  458.       a+=6;
  459.       write_sprite(a,(size-12)<<2);
  460.       --depth; print_line("}");
  461.       break;
  462.     case 16: /* JPEG */
  463.       print_line("JPEG {"); ++depth;
  464.       indent(); printf("BoundingBox  ");
  465.       print_coord(a-4); printf("  ");
  466.       print_coord(a-2); printf("\n");
  467.       indent(); printf("Size "); print_coord(a); printf("\n");
  468.       print_line("DPI %d %d",a[2],a[3]);
  469.       print_line("Matrix  %lg %lg %lg %lg  %lg %lg",
  470.                  a[4]/65536.,a[5]/65536.,a[6]/65536.,a[7]/65536.,
  471.                  a[8]/(1000*unit),a[9]/(1000*unit));
  472.       if (jpeg_prefix) {
  473.         if (jpeg_next>100) {
  474.           warn(a,"Too many JPEGs");
  475.           goto jpeg_done; }
  476.         sprintf(jpeg_name,"%s%.2d",jpeg_prefix,jpeg_next++);
  477.         print_line("FromFile \"%s\"",jpeg_name);
  478.         if (save_file(jpeg_name,a+11,a[10],0xC85)<0)
  479.           warn(a,"Failed to save `%s'",jpeg_name);
  480.       } else {
  481.         int i=0,sz=size-11;
  482.         print_line("Length %d",a[10]); indent();
  483.         while (i<sz) {
  484.           printf("0x%08X",a[11+i++]);
  485.           if (i&3) printf(" ");
  486.           else if (i<sz) { printf("\n"); indent(); }
  487.         }
  488.         printf("\n");
  489.       }
  490. jpeg_done:
  491.       --depth; print_line("}");
  492.       break;
  493.     default:
  494.       warn(a-6,"Unknown object type %d",type);
  495.       printf("# <unknown>\n");
  496.   }
  497.   return size;
  498. }
  499. int main(int ac, char *av[]) {
  500.   int adr=0;
  501.   prog_name=av[0];
  502.   while(++av,--ac) {
  503.     if (!strcmp(*av,"-v")) {
  504.       fprintf(stderr,"This is decdrawf, version " VERSION_STRING ".\n");
  505.       return 0; }
  506.     if (!strcmp(*av,"-s")) {
  507.       if (sprite_file_name) goto usage;
  508.       if (++av,--ac) { sprite_file_name=*av; continue; }
  509.       else goto usage; }
  510.     if (!strcmp(*av,"-j")) {
  511.       if (++av,--ac) { jpeg_prefix=*av; continue; }
  512.       else goto usage; }
  513.     if (!strcmp(*av,"-e")) { short_errors=1; continue; }
  514.     if (!strcmp(*av,"-u")) {
  515.       if (++av,--ac) {
  516.         Units *u=units;
  517.         while (u->name) {
  518.           if (!strcmp(u->name,*av)) {
  519.             unit=u->size; unit_string=u->fullname; break; }
  520.           ++u;
  521.         }
  522.         if (u->name) continue; else goto usage;
  523.       }
  524.       else goto usage; }
  525.     if (file_name) goto usage;
  526.     else file_name=*av;
  527.   }
  528.   if (!file_name) {
  529. usage:
  530.     fprintf(stderr,
  531. "Usage: decdrawf [-s spritefile] [-j jpegpfx] [-u units] [-e] drawfile\n");
  532.     return 4; }
  533.   if (jpeg_prefix)
  534.     jpeg_name=(char*)xmalloc(strlen(jpeg_prefix)+3,"buffer for JPEG filename");
  535.   file_handle=low_open(file_name,low_READ);
  536.   if (!file_handle) error(0,"Couldn't open the input file");
  537.   file_size=low_extent(file_handle);
  538.   space=(int*)xmalloc(file_size,"space for drawfile");
  539.   low_read(file_handle,space,file_size);
  540.   low_close(file_handle);
  541.   if (file_size<40) error(space,"This is not a drawfile");
  542.   if (space[0]!=0x77617244) error(space,"This is not a drawfile");
  543.   printf("# Drawfile `%s'\n",file_name);
  544.   printf("# Decoded by decdrawf.\n\n");
  545.   if (unit!=1.0) printf("Units %s\n\n",unit_string);
  546.   printf("# Header information:\n");
  547.   printf("# Format version %d.%d\n",space[1],space[2]);
  548.   { char q[13]; int *qq=(int*)q; q[12]=0;
  549.     qq[0]=space[3]; qq[1]=space[4]; qq[2]=space[5];
  550.     printf("# Creator: `%s'\n",qq);
  551.   }
  552.   printf("# Global bounding box:  ");
  553.   print_coord(space+6); printf("  "); print_coord(space+8);
  554.   printf("\n");
  555.   adr=10;
  556.   depth=0;
  557.   while (adr<file_size/4) {
  558.     printf("\n\n# At 0x%X\n",adr*4);
  559.     adr+=do_object(space+adr);
  560.   }
  561.   printf("\n# End of decoded drawfile.\n");
  562.   if (sprite_file) close_sprite_file();
  563.   return return_code;
  564. }
  565.