ncdf4a13/ncgen/load.c

Go to the documentation of this file.
00001 /*********************************************************************
00002  *   Copyright 1993, UCAR/Unidata
00003  *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
00004  *   $Id: load.c,v 1.32 2004/11/16 21:37:24 russ Exp $
00005  *********************************************************************/
00006 
00007 #include <stdio.h>
00008 #include <stdlib.h>
00009 #include <string.h>
00010 #include <ctype.h>
00011 #include <netcdf.h>
00012 #include "generic.h"
00013 #include "ncgen.h"
00014 #include "genlib.h"
00015 
00016 extern int netcdf_flag;
00017 extern int c_flag;
00018 extern int fortran_flag;
00019 
00020 #define fpr    (void) fprintf
00021 
00022 
00023 /*
00024  * Remove trailing zeros (after decimal point) but not trailing decimal
00025  * point from ss, a string representation of a floating-point number that
00026  * might include an exponent part.
00027  */
00028 static void
00029 tztrim(
00030     char *ss                    /* returned string representing dd */
00031     )
00032 {
00033     char *cp, *ep;
00034     
00035     cp = ss;
00036     if (*cp == '-')
00037       cp++;
00038     while(isdigit((int)*cp) || *cp == '.')
00039       cp++;
00040     if (*--cp == '.')
00041       return;
00042     ep = cp+1;
00043     while (*cp == '0')
00044       cp--;
00045     cp++;
00046     if (cp == ep)
00047       return;
00048     while (*ep)
00049       *cp++ = *ep++;
00050     *cp = '\0';
00051     return;
00052 }
00053 
00054 
00055 /* generate C to put netCDF record from in-memory data */
00056 static void
00057 gen_load_c(
00058     void *rec_start
00059     )
00060 {
00061     int  idim, ival;
00062     char *val_string;
00063     char *charvalp;
00064     short *shortvalp;
00065     int *intvalp;
00066     float *floatvalp;
00067     double *doublevalp;
00068     char stmnt[C_MAX_STMNT];
00069     size_t stmnt_len;
00070     char s2[C_MAX_STMNT];
00071 
00072     if (!vars[varnum].has_data)
00073         return;
00074 
00075     cline("");
00076     sprintf(stmnt, "   {\t\t\t/* store %s */", vars[varnum].name);
00077     cline(stmnt);
00078 
00079     if (vars[varnum].ndims > 0) {
00080         if (vars[varnum].dims[0] == rec_dim) {
00081             sprintf(stmnt, "    static size_t %s_start[RANK_%s];",
00082                     vars[varnum].lname, vars[varnum].lname);
00083             cline(stmnt);
00084 
00085             sprintf(stmnt, "    static size_t %s_count[RANK_%s];",
00086                     vars[varnum].lname, vars[varnum].lname);
00087             cline(stmnt);
00088         }
00089         
00090         /* load variable with data values using static initialization */
00091         sprintf(stmnt, "    static %s %s[] = {",
00092                 ncctype(vars[varnum].type),
00093                 vars[varnum].lname);
00094         
00095         stmnt_len = strlen(stmnt);
00096         switch (vars[varnum].type) {
00097           case NC_CHAR:
00098             val_string = cstrstr((char *) rec_start, var_len);
00099             sprintf(s2, "%s", val_string);
00100             strncat(stmnt, s2, C_MAX_STMNT - strlen(stmnt) );
00101             free(val_string);
00102             break;
00103           default:
00104             switch (vars[varnum].type) {
00105               case NC_BYTE:
00106                 charvalp = (char *) rec_start;
00107                 break;
00108               case NC_SHORT:
00109                 shortvalp = (short *) rec_start;
00110                 break;
00111               case NC_INT:
00112                 intvalp = (int *) rec_start;
00113                 break;
00114               case NC_FLOAT:
00115                 floatvalp = (float *) rec_start;
00116                 break;
00117               case NC_DOUBLE:
00118                 doublevalp = (double *) rec_start;
00119                 break;
00120             }
00121             for (ival = 0; ival < var_len-1; ival++) {
00122                 switch (vars[varnum].type) {
00123                   case NC_BYTE:
00124                         sprintf(s2, "%d, ", *charvalp++);
00125                     break;
00126                   case NC_SHORT:
00127                         sprintf(s2, "%d, ", *shortvalp++);
00128                     break;
00129                   case NC_INT:
00130                         sprintf(s2, "%ld, ", (long)*intvalp++);
00131                     break;
00132                   case NC_FLOAT:
00133                         sprintf(s2, "%.8g, ", *floatvalp++);
00134                     break;
00135                   case NC_DOUBLE:
00136                         sprintf(s2, "%#.16g", *doublevalp++);
00137                         tztrim(s2);
00138                         strcat(s2, ", ");
00139                     break;
00140                 }
00141                 stmnt_len += strlen(s2);
00142                 if (stmnt_len < C_MAX_STMNT)
00143                   strcat(stmnt, s2);
00144                 else {
00145                     cline(stmnt);
00146                     strcpy(stmnt,s2);
00147                     stmnt_len = strlen(stmnt);
00148                 }
00149             }
00150             for (;ival < var_len; ival++) {
00151                 switch (vars[varnum].type) {
00152                   case NC_BYTE:
00153                         sprintf(s2, "%d", *charvalp);
00154                     break;
00155                   case NC_SHORT:
00156                         sprintf(s2, "%d", *shortvalp);
00157                     break;
00158                   case NC_INT:
00159                         sprintf(s2, "%ld", (long)*intvalp);
00160                     break;
00161                   case NC_FLOAT:
00162                         sprintf(s2, "%.8g", *floatvalp);
00163                     break;
00164                   case NC_DOUBLE:
00165                         sprintf(s2, "%#.16g", *doublevalp++);
00166                         tztrim(s2);
00167                     break;
00168                 }
00169                 stmnt_len += strlen(s2);
00170                 if (stmnt_len < C_MAX_STMNT)
00171                   strcat(stmnt, s2);
00172                 else {
00173                     cline(stmnt);
00174                     strcpy(stmnt,s2);
00175                     stmnt_len = strlen(stmnt);
00176                 }
00177             }
00178             break;
00179         }
00180         strcat(stmnt,"};");
00181         cline(stmnt);
00182 
00183         if (vars[varnum].dims[0] == rec_dim) {
00184             sprintf(stmnt,
00185                     "    %s_len = %lu;                  /* number of records of %s data */",
00186                     dims[rec_dim].lname,
00187                     (unsigned long)vars[varnum].nrecs, /* number of recs for this variable */
00188                     vars[varnum].name);
00189             cline(stmnt);
00190             
00191             for (idim = 0; idim < vars[varnum].ndims; idim++) {
00192                 sprintf(stmnt, "    %s_start[%d] = 0;",
00193                         vars[varnum].lname,
00194                         idim);
00195                 cline(stmnt);
00196             }
00197 
00198             for (idim = 0; idim < vars[varnum].ndims; idim++) {
00199                 sprintf(stmnt, "    %s_count[%d] = %s_len;",
00200                         vars[varnum].lname,
00201                         idim,
00202                         dims[vars[varnum].dims[idim]].lname);
00203                 cline(stmnt);
00204             }
00205         }
00206         
00207         if (vars[varnum].dims[0] == rec_dim) {
00208             sprintf(stmnt,
00209                     "    stat = nc_put_vara_%s(ncid, %s_id, %s_start, %s_count, %s);",
00210                     ncstype(vars[varnum].type),
00211                     vars[varnum].lname,
00212                     vars[varnum].lname,
00213                     vars[varnum].lname,
00214                     vars[varnum].lname);
00215         } else {                /* non-record variables */
00216             sprintf(stmnt,
00217                     "    stat = nc_put_var_%s(ncid, %s_id, %s);",
00218                     ncstype(vars[varnum].type),
00219                     vars[varnum].lname,
00220                     vars[varnum].lname);
00221         }
00222         cline(stmnt);
00223     } else {                    /* scalar variables */
00224         /* load variable with data values using static initialization */
00225         sprintf(stmnt, "    static %s %s = ",
00226                 ncctype(vars[varnum].type),
00227                 vars[varnum].lname);
00228         
00229         switch (vars[varnum].type) {
00230           case NC_CHAR:
00231             val_string = cstrstr((char *) rec_start, var_len);
00232             val_string[strlen(val_string)-1] = '\0';
00233             sprintf(s2, "'%s'", &val_string[1]);
00234             free(val_string);
00235             break;
00236           case NC_BYTE:
00237             charvalp = (char *) rec_start;
00238             sprintf(s2, "%d", *charvalp);
00239             break;
00240           case NC_SHORT:
00241             shortvalp = (short *) rec_start;
00242             sprintf(s2, "%d", *shortvalp);
00243             break;
00244           case NC_INT:
00245             intvalp = (int *) rec_start;
00246             sprintf(s2, "%ld", (long)*intvalp);
00247             break;
00248           case NC_FLOAT:
00249             floatvalp = (float *) rec_start;
00250             sprintf(s2, "%.8g", *floatvalp);
00251             break;
00252           case NC_DOUBLE:
00253             doublevalp = (double *) rec_start;
00254             sprintf(s2, "%#.16g", *doublevalp++);
00255             tztrim(s2);
00256             break;
00257         }
00258         strncat(stmnt, s2, C_MAX_STMNT - strlen(stmnt) );
00259         strcat(stmnt,";");
00260         cline(stmnt);
00261         sprintf(stmnt,
00262                 "    stat = nc_put_var_%s(ncid, %s_id, &%s);",
00263                 ncstype(vars[varnum].type),
00264                 vars[varnum].lname,
00265                 vars[varnum].lname);
00266         cline(stmnt);
00267     }
00268     cline("    check_err(stat,__LINE__,__FILE__);");
00269     cline("   }");
00270 }
00271     
00272 
00273 /*
00274  * Add to a partial Fortran statement, checking if it's too long.  If it is too
00275  * long, output the first part of it as a single statement with continuation
00276  * characters and start a new (probably invalid) statement with the remainder.
00277  * This will cause a Fortran compiler error, but at least all the information
00278  * will be available.
00279  */
00280 static void
00281 fstrcat(
00282     char *s,                    /* source string of stement being built */
00283     const char *t,                      /* string to be appended to source */
00284     size_t *slenp                       /* pointer to length of source string */
00285     )
00286 {
00287     *slenp += strlen(t);
00288     if (*slenp >= FORT_MAX_STMNT) {
00289         derror("FORTRAN statement too long: %s",s);
00290         fline(s);
00291         strcpy(s, t);
00292         *slenp = strlen(s);
00293     } else {
00294         strcat(s, t);
00295     }
00296 }
00297 
00298 /*
00299  * Create Fortran data statement to initialize numeric variable with
00300  * values.
00301  */
00302 static void
00303 f_var_init(
00304     int varnum,                 /* which variable */
00305     void *rec_start             /* start of data */
00306     )
00307 {
00308     char *val_string;
00309     char *charvalp;
00310     short *shortvalp;
00311     int *intvalp;
00312     float *floatvalp;
00313     double *doublevalp;
00314     char stmnt[FORT_MAX_STMNT];
00315     size_t stmnt_len;
00316     char s2[FORT_MAX_STMNT];
00317     int ival;
00318     
00319     /* load variable with data values  */
00320     sprintf(stmnt, "data %s /",vars[varnum].lname);
00321     stmnt_len = strlen(stmnt);
00322     switch (vars[varnum].type) {
00323     case NC_BYTE:
00324         charvalp = (char *) rec_start;
00325         for (ival = 0; ival < var_len-1; ival++) {
00326             val_string = fstring(NC_BYTE,(void *)charvalp++,0);
00327             sprintf(s2, "%s, ", val_string);
00328             fstrcat(stmnt, s2, &stmnt_len);
00329             free(val_string);
00330         }
00331         val_string = fstring(NC_BYTE,(void *)charvalp++,0);
00332         fstrcat(stmnt, val_string, &stmnt_len);
00333         free(val_string);
00334         break;
00335     case NC_SHORT:
00336         shortvalp = (short *) rec_start;
00337         for (ival = 0; ival < var_len-1; ival++) {
00338             sprintf(s2, "%d, ", *shortvalp++);
00339             fstrcat(stmnt, s2, &stmnt_len);
00340         }
00341         sprintf(s2, "%d", *shortvalp);
00342         fstrcat(stmnt, s2, &stmnt_len);
00343         break;
00344     case NC_INT:
00345         intvalp = (int *) rec_start;
00346         for (ival = 0; ival < var_len-1; ival++) {
00347             sprintf(s2, "%ld, ", (long)*intvalp++);
00348             fstrcat(stmnt, s2, &stmnt_len);
00349         }
00350         sprintf(s2, "%ld", (long)*intvalp);
00351         fstrcat(stmnt, s2, &stmnt_len);
00352         break;
00353     case NC_FLOAT:
00354         floatvalp = (float *) rec_start;
00355         for (ival = 0; ival < var_len-1; ival++) {
00356             sprintf(s2, "%.8g, ", *floatvalp++);
00357             fstrcat(stmnt, s2, &stmnt_len);
00358         }
00359         sprintf(s2, "%.8g", *floatvalp);
00360         fstrcat(stmnt, s2, &stmnt_len);
00361         break;
00362     case NC_DOUBLE:
00363         doublevalp = (double *) rec_start;
00364         for (ival = 0; ival < var_len-1; ival++) {
00365             sprintf(s2, "%#.16g", *doublevalp++);
00366             tztrim(s2);
00367             expe2d(s2); /* change 'e' to 'd' in exponent */
00368             fstrcat(s2, ", ", &stmnt_len);
00369             fstrcat(stmnt, s2, &stmnt_len);
00370         }
00371         sprintf(s2, "%#.16g", *doublevalp++);
00372         tztrim(s2);
00373         expe2d(s2);
00374         fstrcat(stmnt, s2, &stmnt_len);
00375         break;
00376     default:
00377         derror("fstrstr: bad type");
00378         break;
00379     }
00380     fstrcat(stmnt, "/", &stmnt_len);
00381 
00382     /* For record variables, store data statement for later use;
00383       otherwise, just print it. */
00384     if (vars[varnum].ndims > 0 && vars[varnum].dims[0] == rec_dim) {
00385         char *dup_stmnt = emalloc(strlen(stmnt)+1);
00386         strcpy(dup_stmnt, stmnt); /* ULTRIX missing strdup */
00387         vars[varnum].data_stmnt = dup_stmnt;
00388     } else {
00389         fline(stmnt);
00390     }
00391 }
00392 
00393 
00394 /* make Fortran to put record */
00395 static void
00396 gen_load_fortran(
00397     void *rec_start
00398     )
00399 {
00400     char stmnt[FORT_MAX_STMNT];
00401     struct vars *v = &vars[varnum];
00402 
00403     if (!v->has_data)
00404         return;
00405 
00406     if (v->ndims == 0 || v->dims[0] != rec_dim) {
00407         sprintf(stmnt, "* store %s", v->name);
00408         fline(stmnt);
00409     }
00410 
00411     /* generate code to initialize variable with values found in CDL input */
00412     if (v->type != NC_CHAR) {
00413         f_var_init(varnum, rec_start);
00414     } else {
00415         v->data_stmnt = fstrstr(rec_start, valnum);
00416     }
00417     
00418     if (v->ndims >0 && v->dims[0] == rec_dim) {
00419         return;
00420     }
00421     if (v->type != NC_CHAR) {
00422         sprintf(stmnt, "iret = nf_put_var_%s(ncid, %s_id, %s)",
00423                 nfftype(v->type), v->lname, v->lname);
00424     } else {
00425         char *char_expr = fstrstr(rec_start, valnum);
00426         sprintf(stmnt, "iret = nf_put_var_%s(ncid, %s_id, %s)",
00427                 nfftype(v->type), v->lname, char_expr);
00428         free(char_expr);
00429     }
00430     
00431     fline(stmnt);
00432     fline("call check_err(iret)");
00433 }
00434 
00435 
00436 /* invoke netcdf calls (or generate C or Fortran code) to load netcdf variable
00437  * from in-memory data.  Assumes following global variables set from yacc
00438  * parser:
00439  * int varnum        - number of variable to be loaded.
00440  * struct vars[varnum] - structure containing info on variable, specifically
00441  *                     name, type, ndims, dims, fill_value, has_data
00442  * int rec_dim       - id of record dimension, or -1 if none
00443  * struct dims[]     - structure containing name and size of dimensions.
00444  */
00445 int
00446 put_variable(
00447     void *rec_start             /* points to data to be loaded  */
00448     )
00449 {
00450     if (netcdf_flag)
00451       load_netcdf(rec_start);   /* put variable values */
00452     if (c_flag)                 /* create C code to put values */
00453       gen_load_c(rec_start);
00454     if (fortran_flag)           /* create Fortran code to put values */
00455       gen_load_fortran(rec_start);
00456 
00457     return 0;
00458 }
00459 
00460 
00461 /* write out variable's data from in-memory structure */
00462 void
00463 load_netcdf(
00464     void *rec_start
00465     )
00466 {
00467     int idim;
00468     int stat = NC_NOERR;
00469     size_t start[NC_MAX_VAR_DIMS];
00470     size_t count[NC_MAX_VAR_DIMS];
00471     char *charvalp;
00472     short *shortvalp;
00473     int *intvalp;
00474     float *floatvalp;
00475     double *doublevalp;
00476 
00477     /* load values into variable */
00478 
00479     switch (vars[varnum].type) {
00480       case NC_CHAR:
00481       case NC_BYTE:
00482         charvalp = (char *) rec_start;
00483         break;
00484       case NC_SHORT:
00485         shortvalp = (short *) rec_start;
00486         break;
00487       case NC_INT:
00488         intvalp = (int *) rec_start;
00489         break;
00490       case NC_FLOAT:
00491         floatvalp = (float *) rec_start;
00492         break;
00493       case NC_DOUBLE:
00494         doublevalp = (double *) rec_start;
00495         break;
00496     }
00497     if (vars[varnum].ndims > 0) {
00498         /* initialize start to upper left corner (0,0,0,...) */
00499         start[0] = 0;
00500         if (vars[varnum].dims[0] == rec_dim) {
00501             count[0] = vars[varnum].nrecs;
00502         }
00503         else {
00504             count[0] = dims[vars[varnum].dims[0]].size;
00505         }
00506     }
00507 
00508     for (idim = 1; idim < vars[varnum].ndims; idim++) {
00509         start[idim] = 0;
00510         count[idim] = dims[vars[varnum].dims[idim]].size;
00511     }
00512     
00513     switch (vars[varnum].type) {
00514       case NC_BYTE:
00515         stat = nc_put_vara_schar(ncid, varnum, start, count,
00516                                  (signed char *)charvalp);
00517         break;
00518       case NC_CHAR:
00519         stat = nc_put_vara_text(ncid, varnum, start, count, charvalp);
00520         break;
00521       case NC_SHORT:
00522         stat = nc_put_vara_short(ncid, varnum, start, count, shortvalp);
00523         break;
00524       case NC_INT:
00525         stat = nc_put_vara_int(ncid, varnum, start, count, intvalp);
00526         break;
00527       case NC_FLOAT:
00528         stat = nc_put_vara_float(ncid, varnum, start, count, floatvalp);
00529         break;
00530       case NC_DOUBLE:
00531         stat = nc_put_vara_double(ncid, varnum, start, count, doublevalp);
00532         break;
00533     }
00534     check_err(stat);
00535 }

Generated on Thu Mar 16 18:10:14 2006 for nco by  doxygen 1.4.4