diskwrit.c
上传用户:szhypcb168
上传日期:2007-01-06
资源大小:2187k
文件大小:27k
源码类别:

语音压缩

开发平台:

Unix_Linux

  1. /*  ----------------------  DATA FILE WRITE ROUTINES  ----------------------  */
  2. /*  ------  designed by dpk, rpc & committee; coded by rpc      ------------  */
  3. /*  ---------------------  Version 1.4    August 1988  ---------------------  */
  4. /*  ------------------------------------------------------------------------  */
  5. /*   RELEASE NOTES:
  6.      Version 1.1:  Eliminated large fixed-size buffers for default values by
  7. writing them after values were saved, rather than before.  Eliminated large
  8. fixed-size buffers for saved values, by using malloc and realloc.
  9.      Version 1.2:  Added the auto error reporting feature.  This feature is
  10. enabled or disabled via disk_io_erh(flag) which is in its own source file.
  11. Changed the algorithm for assigning buffers for saved values.  Also fixed a few
  12. subtle bugs and made minor code changes.
  13.      Version 1.3:  Increased the amount of text in error reporting and changed
  14. it to print on stderr instead of stdout.
  15.      Version 1.4:  Fixed bug in end_block that made 0 length format file when
  16. open_type is 3.
  17. */
  18. #include "diskio.h"
  19. #include <stdio.h>
  20. #include <strings.h>
  21. #include <sys/file.h>
  22. /*    variable type definitions:
  23.  *
  24.  *    TYPE  #  |  C TYPE  |  # of BYTES  |  FORTRAN TYPE
  25.  *    --------------------------------------------------
  26.  *       1     |  short   |      2       |  integer*2
  27.  *       2     |   int   |      4       |  integer*4
  28.  *       3     |  float   |      4       |    real*4
  29.  */
  30. static short bytes_in[] = { 2, 4, 4 }; /* number of bytes in the data types */
  31. #define MAX_BYTES_PER_VAL      4    /* must be set to max value of bytes_in[] */
  32. #define NUM_DATA_TYPES sizeof(bytes_in)/sizeof(bytes_in[0]) /* elements in bytes_in */
  33. struct file_data {
  34.    char filename[MAX_FILENAME_LENG + 1];   /* file name, without extension */
  35.    int fd;                                 /* file descriptor */
  36.    short format[2 + 2*MAX_VARS_PER_BLK];   /* block information */
  37.    char vnames[MAX_VARS_PER_BLK][MAX_VARNAME_LENG];/* variable names in block */
  38.    short open_type;                        /* file open type */
  39.    int bytes_p_blk;                        /* bytes per block */
  40.    short defined;                          /* =1 when block defined */
  41.    short var_count;                        /* inc when variable added */
  42.    };
  43. static struct file_data fd[MAX_FILES];
  44. struct variable_data {
  45.    short number;         /* number of values per block */
  46.    short bytes;          /* number of bytes per value */
  47.    char *base_addr;      /* pointer to location for first saved value */
  48.    short num_saved;      /* number of values saved since last block end */
  49.    char *bufp;           /* pointer to location for next saved value */
  50.    char def_val[MAX_BYTES_PER_VAL]; /* storage for default value */
  51.    };
  52. static struct variable_data vd[MAX_FILES * MAX_VARS_PER_BLK];
  53. #define PARAM_OK -999
  54. struct errs {
  55.    char routine[20];               /* name of routine where error was */
  56.    char name[MAX_FILENAME_LENG+1]; /* filename or variable name */
  57.    int param;                      /* illegal argument of call in error */
  58.    };
  59. static struct errs ervar = { "", "", PARAM_OK };
  60. #define DFE   ".sg_data"
  61. #define FFE   ".sg_format"
  62. extern int errno;
  63. extern short auto_er;     /* flag to enable/disable auto error report & halt */
  64. extern long lseek();
  65. extern char *malloc(), *realloc();
  66. extern char *strcat(), *strcpy(), *strncpy();
  67. /*  -------------------------  OPEN FILE ROUTINE  -------------------------  */
  68. /*   DESCRIPTION:
  69.      file_id = open_file ( filename, open_type )
  70.      This routine opens the file "filename" so that data may be written to it.
  71. The parameter "open_type" specifies the following:
  72.      1 - delete any prior contents of specified file
  73.      2 - append to prior contents of specified file
  74.      3 - if specified file doesn't exist: delete any prior contents
  75.          if specified file does exist: don't open it and return an appropriate
  76.          error message
  77. Returned value:
  78.      If there are no errors, the returned value is a file id which is used to
  79. identify this open file when using several other of the disk write routines.
  80. A valid file id is >= 0.  If an error occurs, the returned value is < 0.
  81. The following errors are detected:
  82.      - file "filename" is already open
  83.      - filename is too long
  84.      - the number of files currently open is the maximum
  85.      - could not create a format file
  86.      - could not create a data file
  87.      - could not open filename.sg_format for reading
  88.      - could not open filename.sg_data for writing
  89.      - file "filename" exists and open_type prohibits overwriting
  90.      - invalid open_type
  91. */
  92. open_file ( filename, open_type )
  93. char filename[];
  94. int open_type;
  95. {
  96.    int file_id, i, tempfd;
  97.    char dname[MAX_FILENAME_LENG + sizeof(DFE)];
  98.    char fname[MAX_FILENAME_LENG + sizeof(FFE)];
  99.    strcpy(ervar.routine, "open_file");
  100.    strncpy(ervar.name, filename, MAX_FILENAME_LENG);
  101.    strcat(ervar.name, "");
  102. /*
  103.  *    check to see if this file has already been opened:
  104.  *    NOTE: The first call relies on open_type set to 0 by the compiler
  105.  */
  106.    for (i=0; i<MAX_FILES; i++)
  107.    {
  108.       if (fd[i].open_type != 0)  /* this file_id is in use, so check name */
  109.       {
  110.          if (strcmp(filename, fd[i].filename) == 0)   /* file already open */
  111.          {
  112.             if (auto_er) error_exit(-8);
  113.             return(-8);
  114.          }
  115.       }
  116.    }
  117. /*
  118.  *    look for the first available file_id:
  119.  */
  120.    file_id = -1;
  121.    for (i=0; i<MAX_FILES; i++)
  122.    {
  123.       if (fd[i].open_type == 0)  /* this file_id is available */
  124.       {
  125.          file_id = i;
  126.          break;
  127.       }
  128.    }
  129.    if (file_id == -1)    /* all files are currently open */
  130.    {
  131.       if (auto_er) error_exit(-1);
  132.       return(-1);
  133.    }
  134. /*
  135.  *    append the data and format extensions to requested filename:
  136.  */
  137.    if (strlen(filename) > MAX_FILENAME_LENG)    /* filename too long */
  138.    {
  139.       if (auto_er) error_exit(-9);
  140.       return(-9);
  141.    }
  142.    strcpy(dname, filename);
  143.    strcat(dname, DFE);
  144.    strcpy(fname, filename);
  145.    strcat(fname, FFE);
  146.    if (open_type == 1 || open_type == 3) /* new file or check for file */
  147.    {
  148.       if ( (open_type==3) && (access(dname, F_OK)==0) )   /* file exists */
  149.       {
  150.          if (auto_er) error_exit(-6);
  151.          return(-6);
  152.       }
  153. /*
  154.  *    create an empty format file (to be written in first end_block call):
  155.  */
  156.       tempfd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0644);
  157.       if (tempfd == -1)    /* can't create format file */
  158.       {
  159.          perror("The system call error in disk write is");
  160.          if (auto_er) error_exit(-2);
  161.          return(-2);
  162.       }
  163.       close(tempfd);       /* close the format file */
  164. /*
  165.  *    create an empty data file:
  166.  */
  167.       tempfd = open(dname, O_WRONLY | O_CREAT | O_TRUNC, 0644);
  168.       if (tempfd == -1)    /* can't create data file */
  169.       {
  170.          perror("The system call error in disk write is");
  171.          if (auto_er) error_exit(-3);
  172.          return(-3);
  173.       }
  174.    }
  175.    else if (open_type == 2)   /* append to file 'filename' */
  176.    {
  177.       if (access(fname, R_OK) == -1)  /* can't read format file */
  178.       {
  179.          perror("The system call error in disk write is");
  180.          if (auto_er) error_exit(-4);
  181.          return(-4);
  182.       }
  183.       tempfd = open(dname, O_WRONLY);      /* open data file for writing */
  184.       if (tempfd == -1)         /* couldn't open data file for writing */
  185.       {
  186.          perror("The system call error in disk write is");
  187.          if (auto_er) error_exit(-5);
  188.          return(-5);
  189.       }
  190.       lseek(tempfd, (long) 0 , 2);      /* go to end of file to append */
  191.    }
  192.    else       /* invalid open_type */
  193.    {
  194.       ervar.param = open_type;
  195.       if (auto_er) error_exit(-7);
  196.       return(-7);
  197.    }
  198. /*
  199.  *    define the fd variables:
  200.  */
  201.    strcpy(fd[file_id].filename, filename);
  202.    fd[file_id].open_type = open_type;
  203.    fd[file_id].fd = tempfd;
  204.    fd[file_id].defined = 0;
  205.    fd[file_id].var_count = 0;
  206.    fd[file_id].bytes_p_blk = 0;
  207. /*
  208.  *    For each variable this file may have, set vd[i].bytes = 0.  This enables
  209.  *    the error of saving before defining to be detected.
  210.  */
  211.    for(i=0; i<MAX_VARS_PER_BLK; i++)  vd[var_id_gen(file_id, i+1)].bytes = 0;
  212.    return(file_id);
  213. }
  214. /*  ----------------------  DEFINE VARIABLE ROUTINE  ----------------------  */
  215. /*   DESCRIPTION:
  216.      
  217.      var_id = def_variable ( file_id, name, type, number, def_val )
  218.      This routine defines parameters of a variable to be saved.  The
  219. parameters are the variable's name, data type, number per block, and default
  220. value.  Variables may be defined until the first call to end_block, which ends
  221. the variable definition process.  The string used as the variable's name does
  222. not have to be the name the calling program uses to reference the variable's
  223. values.  It can be some other string of the programmer's choosing.  This name
  224. is used to select the variable for reading by the disk read routines.  It is
  225. also used to select and label variables in SUNGRAPH.  This routine does NOT
  226. check for duplication of variable names, so be sure that each file variable has
  227. a unique name.  The default value is a pointer to a variable that has been
  228. initialized to the desired default value.  This variable must be of the type
  229. specified in the argument list of this function (i.e. "type").  It is NOT a
  230. pointer to a character string.  The default value is written if the user saves
  231. fewer than "number" values per block. 
  232. Returned value:
  233.      When no error occurs, the returned value is a variable id which is used
  234. to identify this variable when saving its values with the save variable routine.
  235. A valid variable id is >= 0.  If an error occurs, the returned value is < 0.
  236. The following errors are detected:
  237.      - 'file_id' is out of range
  238.      - 'file_id' corresponds to an unopened file
  239.      - the file variables have already been defined
  240.      - invalid data type specified
  241.      - invalid number of values specified
  242.      - the maximum number of variables have already been defined
  243.      - variable name is too long
  244.      - could not get a buffer for saved values
  245. */
  246. def_variable ( file_id, name, type, number, def_val )
  247. char name[], def_val[];
  248. int file_id, type, number;
  249. {
  250.    int i, var_id, var_num, var;
  251.    char *base, *tpntr;
  252.    strcpy(ervar.routine, "def_variable");
  253.    strncpy(ervar.name, name, MAX_FILENAME_LENG);
  254.    strcat(ervar.name, "");
  255. /*
  256.  *    do the easy error checking:
  257.  */
  258.    if (file_id < 0 || file_id >= MAX_FILES)        /* invalid id */
  259.    {
  260.       ervar.param = file_id;
  261.       if (auto_er) error_exit(-11);
  262.       return(-11);
  263.    }
  264.    if (fd[file_id].open_type == 0)                 /* file not open */
  265.    {
  266.       ervar.param = file_id;
  267.       if (auto_er) error_exit(-12);
  268.       return(-12);
  269.    }
  270.    if (fd[file_id].defined == 1)                   /* all variables defined */
  271.    {
  272.       if (auto_er) error_exit(-13);
  273.       return(-13);
  274.    }
  275.    if (type < 1 || type > NUM_DATA_TYPES)          /* invalid type */
  276.    {
  277.       ervar.param = type;
  278.       if (auto_er) error_exit(-14);
  279.       return(-14);
  280.    }
  281.    if (number < 1 || number > MAX_VALUES_PER_VAR)  /* invalid number */
  282.    {
  283.       ervar.param = number;
  284.       if (auto_er) error_exit(-15);
  285.       return(-15);
  286.    }
  287.    if (fd[file_id].var_count == MAX_VARS_PER_BLK)  /* too many variables */
  288.    {
  289.       if (auto_er) error_exit(-16);
  290.       return(-16);
  291.    }
  292.    if (strlen(name) > MAX_VARNAME_LENG)            /* name too long */
  293.    {
  294.       if (auto_er) error_exit(-17);
  295.       return(-17);
  296.    }
  297. /*
  298.  *    assign a variable id and set fd variables:
  299.  */
  300.    var_num = 1 + fd[file_id].var_count++;
  301.    var_id = var_id_gen( file_id, var_num );
  302.    fd[file_id].format[2*var_num] = type;
  303.    fd[file_id].format[2*var_num+1] = number;
  304.    fd[file_id].bytes_p_blk += bytes_in[type-1] * number;
  305.    strcpy(&fd[file_id].vnames[var_num-1][0], name);
  306. /*
  307.  *    set vd variables:
  308.  */
  309.    vd[var_id].number = number;
  310.    vd[var_id].num_saved = 0;
  311.    vd[var_id].bytes = bytes_in[type-1];
  312.    for (i=0; i<vd[var_id].bytes; i++) vd[var_id].def_val[i] = def_val[i];
  313. /*
  314.  *    allocate memory and assign base address:
  315.  */
  316.    if (var_num == 1)  /* first variable in this file */
  317.    {
  318.       vd[var_id].base_addr = malloc( (unsigned) fd[file_id].bytes_p_blk);
  319.       if (vd[var_id].base_addr == 0)   /* couldn't get memory */
  320.       {
  321.          if (auto_er) error_exit(-10);
  322.          return(-10);
  323.       }
  324.    }
  325.    else               /* add a variable to the file */
  326.    {
  327.       base = vd[var_id_gen(file_id, 1)].base_addr;
  328.       tpntr = realloc(base, (unsigned) fd[file_id].bytes_p_blk);
  329.       if (tpntr == 0)      /* could not get memory */
  330.       {
  331.          if (auto_er) error_exit(-10);
  332.          return(-10);
  333.       }
  334.       if (tpntr != base)   /* buffer was moved by realloc */
  335.       {                    /* so, move pointers for prior variables */
  336.          for (i=1; i<fd[file_id].var_count; i++)
  337.          {
  338.             var = var_id_gen(file_id, i);
  339.             vd[var].base_addr += tpntr - base;
  340.             vd[var].bufp      += tpntr - base;
  341.          }
  342.          free(base);       /* and release the old buffer */
  343.       }
  344.       vd[var_id].base_addr = vd[var_id-1].base_addr
  345.                            + vd[var_id-1].bytes * vd[var_id-1].number;
  346.    }
  347.    vd[var_id].bufp = vd[var_id].base_addr;
  348.    return(var_id);
  349. }
  350. /*  -----------------------  SAVE VARIABLE ROUTINE  -----------------------  */
  351. /*   DESCRIPTION:
  352.      status = save_variable ( var_id, values, num )
  353.      This routine saves values of a variable that has been defined.  "values"
  354. is the array of which "num" values will be saved.  The data type of the values
  355. array must match that declared when the variable was defined.  The routine does
  356. NOT test for such a match.  The number of values saved per call can be from 1
  357. to the number per block specified when the variable was defined via def_var.
  358. The total number of values saved per variable cannot exceed the number defined
  359. when the variable was defined.  When saving a single value, be sure that
  360. "values" is a POINTER to that value.
  361. Returned value:
  362.      The returned value indicates whether or not the routine encountered an
  363. error.  If no error occurs, the returned value is 0.  If an error occurs, the
  364. returned value is < 0.
  365. The following errors are detected:
  366.      - attempt to save less than one variable
  367.      - 'var_id' is out of range
  368.      - 'var_id' corresponds to an undefined variable
  369.      - all values of this variable have been saved since last end_block
  370.      - saved less than the specified number of values
  371. */
  372. save_variable ( var_id, values, num )
  373. register char *values;
  374. int var_id, num;
  375. {
  376.    register char *bufp, *endp;
  377.    int values_left, error;
  378.    strcpy(ervar.routine, "save_variable");
  379.    strcpy(ervar.name, "UNKNOWN");  /* the first 2 errors have no f or v name */
  380. /*
  381.  *    do the easy error checking:
  382.  */
  383.    if (var_id < 0 || var_id >= MAX_FILES * MAX_VARS_PER_BLK) /* out of range */
  384.    {
  385.       ervar.param = var_id;
  386.       if (auto_er) error_exit(-19);
  387.       return(-19);
  388.    }
  389.    if (vd[var_id].bytes == 0)       /* undefined variable */
  390.    {
  391.       ervar.param = var_id;
  392.       if (auto_er) error_exit(-20);
  393.       return(-20);
  394.    }
  395.    strcpy(ervar.name, fd[var_id/MAX_VARS_PER_BLK].vnames[var_id%MAX_VARS_PER_BLK]);
  396.    if (num < 1)                     /* saving less than one value */
  397.    {
  398.       if (auto_er) error_exit(-18);
  399.       return(-18);
  400.    }
  401. /*
  402.  *    find out if the requested amount of values can be saved:
  403.  */
  404.    values_left = vd[var_id].number - vd[var_id].num_saved;
  405.    if (values_left == 0)       /* all values already saved */
  406.    {
  407.       if (auto_er) error_exit(-21);
  408.       return(-21);
  409.    }
  410.    error = 0;
  411.    if (num > values_left)        /* not enough space to save all values */
  412.    {
  413.       num = values_left;         /* truncate number saved to number left */
  414.       error = -22;               /* and report this error */
  415.    }
  416.    vd[var_id].num_saved += num;  /* account for the number of values saved */
  417. /*
  418.  *    move the new values to the data buffer:
  419.  */
  420.    bufp = vd[var_id].bufp;          /* fetch buffer pointer, for register use */
  421.    endp = vd[var_id].bufp + num * vd[var_id].bytes;        /* end of transfer */
  422.    while (bufp < endp) *bufp++ = *values++;     /* move values & inc pointers */
  423.    vd[var_id].bufp = bufp;             /* restore the advanced buffer pointer */
  424.    if (error<0 && auto_er) error_exit(error);
  425.    return(error);
  426. }
  427. /*  -------------------------  END BLOCK ROUTINE  -------------------------  */
  428. /*   DESCRIPTION:
  429.      status = end_block ( file_id )
  430.      This routine terminates the saving of variables for a block.  The values
  431. in the block are written to the data file.  This is the ONLY routine which
  432. writes values to the data file.  The first call to this routine terminates the
  433. variable definition process, i.e. def_var can no longer be called for this
  434. file_id.
  435. Returned value:
  436.      The returned value indicates whether or not the routine encountered an
  437. error.  If no error occurs, the returned value is 0.  If an error occurs, the
  438. returned value is < 0.
  439. The following errors are detected:
  440.      - 'file_id' is out of range
  441.      - 'file_id' corresponds to an unopened file
  442.      - current variable definition differs from that of appended file
  443.      - error when writing format file
  444.      - error when writing data buffer to disk
  445.      - no variables have been defined
  446. */
  447. end_block ( file_id )
  448. int file_id;
  449. {
  450.    register int i;
  451.    int var_id, bytes, tempfd, vnum;
  452.    short format[2 + 2*MAX_VARS_PER_BLK];
  453.    char fname[MAX_FILENAME_LENG + sizeof(FFE)];
  454.    strcpy(ervar.routine, "end_block");
  455.    strcpy(ervar.name, "UNKNOWN");  /* the first 2 errors have no f or v name */
  456. /*
  457.  *    do the easy error checking:
  458.  */
  459.    if (file_id < 0 || file_id >= MAX_FILES)   /* bogus file_id */
  460.    {
  461.       ervar.param = file_id;
  462.       if (auto_er) error_exit(-11);
  463.       return(-11);
  464.    }
  465.    if (fd[file_id].open_type == 0)            /* file not open */
  466.    {
  467.       ervar.param = file_id;
  468.       if (auto_er) error_exit(-12);
  469.       return(-12);
  470.    }
  471.    strcpy(ervar.name, fd[file_id].filename);
  472. /*
  473.  *    for all variables in this file, put default values into unused locations:
  474.  */
  475.    for (vnum=1; vnum<=fd[file_id].var_count; vnum++)
  476.    {
  477.       var_id = var_id_gen(file_id, vnum);
  478.       while (vd[var_id].num_saved++ < vd[var_id].number)
  479.       {
  480.          for (i=0; i<vd[var_id].bytes; i++)
  481.             *vd[var_id].bufp++ = vd[var_id].def_val[i];
  482.       }
  483.    }
  484. /*
  485.  *    If this is the first time end_block is called for this file_id:
  486.  *       if appending, compare format of old file with current definition;
  487.  *       if writing a new file, write the format information.
  488.  */
  489.    if (fd[file_id].defined == 0)   /*  first call for this file_id  */
  490.    {
  491.       if (fd[file_id].var_count == 0)  /* no variables defined */
  492.       {
  493.          if (auto_er) error_exit(-28);
  494.          return(-28);
  495.       }
  496.       fd[file_id].format[0] = 1;  /* disk-resident data */
  497.       fd[file_id].format[1] = fd[file_id].var_count;
  498.       fd[file_id].defined = 1;    /* indicate that the block has been defined */
  499. /*
  500.  *    make the format file name:
  501.  */
  502.       strcpy(fname, fd[file_id].filename);
  503.       strcat(fname, FFE);
  504.       if (fd[file_id].open_type == 2)   /* appending to current file */
  505.       {
  506.          tempfd = open(fname, O_RDONLY);
  507.          read(tempfd, format, 4);  /* read the first 2 format values */
  508.          if (format[1] != fd[file_id].format[1])   /* # of vars different */
  509.          {
  510.             close(tempfd);   /*  close the format file  */
  511.             if (auto_er) error_exit(-25);
  512.             return(-25);
  513.          }
  514.          read(tempfd, &format[2], 4*format[1]); /* read var definitions */
  515.          for (i=2; i < 2 + 2*format[1]; i++)
  516.          {
  517.             if (format[i] != fd[file_id].format[i]) /* type or # different */
  518.             {
  519.                close(tempfd);   /*  close the format file  */
  520.                if (auto_er) error_exit(-25);
  521.                return(-25);
  522.             }
  523.          }
  524.          close(tempfd);
  525.       }
  526.       else   /* new file; write format info */
  527.       {
  528.          tempfd = open(fname, O_WRONLY);
  529. /*
  530.  *       write the format array:
  531.  */
  532.          bytes = 4 + 4 * fd[file_id].var_count;
  533.          if (bytes != write(tempfd, fd[file_id].format, bytes) )
  534.          {
  535.             close(tempfd);   /*  close the format file  */
  536.             if (bytes == -1) perror("The system call error in disk write is");
  537.             if (auto_er) error_exit(-26);
  538.             return(-26);
  539.          }
  540. /*
  541.  *       write the variable names:
  542.  */
  543.          bytes = fd[file_id].var_count * MAX_VARNAME_LENG;
  544.          if (bytes != write(tempfd, fd[file_id].vnames, bytes) )
  545.          {
  546.             close(tempfd);   /*  close the format file  */
  547.             if (bytes == -1) perror("The system call error in disk write is");
  548.             if (auto_er) error_exit(-26);
  549.             return(-26);
  550.          }
  551.          close(tempfd);   /*  close the format file  */
  552.       }
  553.    }
  554. /*
  555.  *    reset bufp & num_saved in preparation to save the next block:
  556.  */
  557.    for (vnum=1; vnum<=fd[file_id].var_count; vnum++)
  558.    {
  559.       var_id = var_id_gen(file_id, vnum);
  560.       vd[var_id].bufp = vd[var_id].base_addr;
  561.       vd[var_id].num_saved = 0;
  562.    }
  563. /*
  564.  *    write the block buffer:
  565.  */
  566.    bytes = fd[file_id].bytes_p_blk;
  567.    if (bytes != write(fd[file_id].fd, vd[var_id_gen(file_id, 1)].base_addr, bytes) )
  568.    {
  569.       if (bytes == -1) perror("The system call error in disk write is");
  570.       if (auto_er) error_exit(-27);
  571.       return(-27);
  572.    }
  573.    return(0);
  574. }
  575. /*  -------------------------  CLOSE FILE ROUTINE  -------------------------  */
  576. /*   DESCRIPTION:
  577.      status = close_file ( file_id )
  578.      This routine closes the file associated with "file_id".  In the event that
  579. more files need to be written than can be opened simultaneously, this routine
  580. provides a way to close a file so that another can be opened.
  581. Returned value:
  582.      The returned value indicates whether or not the routine encountered an
  583. error.  If no error occurs, the returned value is 0.  If an error occurs, the
  584. returned value is < 0.
  585. The following errors are detected:
  586.      - 'file_id' is out of range
  587.      - 'file_id' corresponds to an unopened file
  588. */
  589. close_file ( file_id )
  590. int file_id;
  591. {
  592.    strcpy(ervar.routine, "close_file");
  593.    strcpy(ervar.name, "UNKNOWN");  /* can't determine associated file name */
  594. /*
  595.  *    do the easy error checking:
  596.  */
  597.    if (file_id < 0 || file_id >= MAX_FILES)   /* bogus file_id */
  598.    {
  599.       ervar.param = file_id;
  600.       if (auto_er) error_exit(-11);
  601.       return(-11);
  602.    }
  603.    if (fd[file_id].open_type == 0)            /* file not open */
  604.    {
  605.       ervar.param = file_id;
  606.       if (auto_er) error_exit(-12);
  607.       return(-12);
  608.    }
  609.    close(fd[file_id].fd);
  610.    free(vd[var_id_gen(file_id,1)].base_addr);  /* free the saved value buffer */
  611.    fd[file_id].open_type = 0;    /* make file_id available */
  612.    return(0);
  613. }
  614. /*  -------------------  PRINT DISK WRITE ERROR ROUTINE  -------------------  */
  615. /*   DESCRIPTION:
  616.      print_disk_write_error ( err_num )
  617.      This routine prints an error message which corresponds to "err_num".
  618. It is printed on stderr.
  619. */
  620. print_disk_write_error ( err_num )
  621. int err_num;
  622. {
  623.    char *disk_write_error();
  624.    if (err_num < 0)
  625.    {
  626.       fprintf(stderr, "Disk_IO error in routine '%s'.n", ervar.routine);
  627.       fprintf(stderr, "The filename or variable name associated with the offending call is:n");
  628.       fprintf(stderr, "%sn", ervar.name);
  629.       fprintf(stderr, disk_write_error(err_num) );
  630.       if (ervar.param != PARAM_OK)
  631.       {
  632.          fprintf(stderr, "Its value was: %dn", ervar.param);
  633.          ervar.param = PARAM_OK;
  634.       }
  635.    }
  636.    else fprintf(stderr, disk_write_error(err_num) );
  637.    return;
  638. }
  639. /*  ----------------------  DISK WRITE ERROR ROUTINE  ----------------------  */
  640. /*   DESCRIPTION:
  641.      error_string = disk_write_error ( err_num )
  642.      The disk_write_error routine returns a brief error message which
  643. corresponds to "err_num".
  644. */
  645. char *disk_write_error ( err_num )
  646. int err_num;
  647. {
  648.    static char err_string[70];
  649.    static char *err_msg[] = {
  650. "No error",                                                      /* 0 */
  651. /*
  652.  * OPEN FILE ERRORS:
  653.  */
  654. "The number of files currently open is the maximum",             /* 1 */
  655. "Could not create a format file",                                /* 2 */
  656. "Could not create a data file",                                  /* 3 */
  657. "Could not open 'filename'.sg_format for reading",               /* 4 */
  658. "Could not open 'filename'.sg_data for writing",                 /* 5 */
  659. "File 'filename' exists and you want to protect it",             /* 6 */
  660. "Invalid 'open_type'",                                           /* 7 */
  661. "File 'filename' is already open",                               /* 8 */
  662. "Filename is too long",                                          /* 9 */
  663. /*
  664.  * DEFINE VARIABLE ERRORS:
  665.  */
  666. "Could not get a buffer for saved values",                      /* 10 */
  667. "'file_id' is out of range",                                    /* 11 */
  668. "'file_id' corresponds to an unopened file",                    /* 12 */
  669. "The file variables have already been defined",                 /* 13 */
  670. "The specified data type is not valid",                         /* 14 */
  671. "The specified number of values is not valid",                  /* 15 */
  672. "The maximum number of variables have already been defined",    /* 16 */
  673. "Variable name is too long",                                    /* 17 */
  674. /*
  675.  * SAVE VARIABLE ERRORS:
  676.  */
  677. "Attempt to save less than one value",                          /* 18 */
  678. "'var_id' is out of range",                                     /* 19 */
  679. "'var_id' corresponds to an undefined variable",                /* 20 */
  680. "All values of this variable have been saved",                  /* 21 */
  681. "Number of values saved exceeded amount defined",               /* 22 */
  682. "unassigned",                                                   /* 22 */
  683. "unassigned",                                                   /* 24 */
  684. /*
  685.  * END BLOCK ERRORS:
  686.  */
  687. /*  uses errors 11 & 12 from define variable  */
  688. "Current variable definition does not match that of old file",  /* 25 */
  689. "Error when writing format file",                               /* 26 */
  690. "Error when writing data buffer to disk",                       /* 27 */
  691. "No variables have been defined",                               /* 28 */
  692. /*
  693.  * CLOSE FILE ERRORS:
  694.  */
  695. /*  uses errors 11 & 12 from define variable  */
  696. "unassigned",                                                   /* 29 */
  697. /*
  698.  * ALL OTHER ERRORS:
  699.  */
  700. "Bad value for error number"                                    /* 30 */
  701. };
  702. #define NUM 30
  703.    if (err_num > 0) err_num = 0; /* force positive arguments to give no error */
  704.    strcpy(err_string, (-err_num < NUM) ? err_msg[-err_num] : err_msg[NUM] );
  705.    strcat(err_string,".n");
  706.    return(err_string);
  707. }
  708. /*  --------------------------  SUPPORT ROUTINES  --------------------------  */
  709. /*  -----------------------------  VAR_ID_GEN  -----------------------------  */
  710. /*   DESCRIPTION:
  711.      Given a file_id and variable number, this routine returns a variable id.
  712. The variable number range is 1 to MAX_VARS_PER_BLK inclusive.
  713. */
  714. static var_id_gen ( file_id, var_num )
  715. int file_id, var_num;
  716. {
  717.    return(file_id * MAX_VARS_PER_BLK + var_num - 1);
  718. }
  719. /*  -----------------------------  ERROR_EXIT  -----------------------------  */
  720. static error_exit(err_num)
  721. int err_num;
  722. {
  723.    print_disk_write_error(err_num);
  724.    exit(-1);
  725. }