netcdf-c/ncgen/main.c
dmh c99058741a [NCF-265]
Ncgen is unable to resolve
ambiguous references to an enum
constant when two different enums
have same econstant name.

Solved by allowing more specific
forms for econstant references.
1. /.../enumname.enumconstname
2. enumname.enumconstname
3. enumconstname

Case 1 is resolved by using the econstant
in the specific enum definition. If none is
found, an error is reported.

Case 2 is resolved by
1. finding an enclosing group with an
   enum definition with the specified name
   and containing the specified econstant.
   If there are more than one, then an error is reported
2. finding all enum definitions in the dataset that have
   the specified enum name and contain the specified
   econstant. If more than one is found, then an error is reported.
If the above two methods fail, then report an error.

Case 3 is similar to case 2, but all enums, irrespective
of name are used if they contains the specified enum constant.

The ref_tst_econst.cdl test in ncdump is causing ncdump
to fail. So there may be yet some problem.
2013-09-20 20:43:09 -06:00

444 lines
10 KiB
C

/*********************************************************************
* Copyright 1993, UCAR/Unidata
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
*********************************************************************/
/* $Id: main.c,v 1.33 2010/05/26 21:43:36 dmh Exp $ */
/* $Header: /upc/share/CVS/netcdf-3/ncgen/main.c,v 1.33 2010/05/26 21:43:36 dmh Exp $ */
#include "includes.h"
#include "offsets.h"
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
#ifdef _MSC_VER
#include "XGetopt.h"
#define snprintf _snprintf
int opterr;
int optind;
#endif
/* Default is netcdf-3 mode 1 */
#define DFALTCMODE 0
extern void init_netcdf(void);
extern void parse_init(void);
extern int ncgparse(void);
/* For error messages */
char* progname;
char* cdlname;
/* option flags */
int nofill_flag;
char* mainname; /* name to use for main function; defaults to "main"*/
Language l_flag;
int syntax_only;
int header_only;
/* flags for tracking what output format to use */
int k_flag; /* > 0 => -k was specified on command line*/
int format_flag; /* _Format attribute value (same range as -k flag) */
int enhanced_flag; /* 1 => netcdf-4 constructs appear in the parse */
int specials_flag; /* 1=> special attributes are present */
int usingclassic;
int cmode_modifier;
int diskless;
char* binary_ext = ".nc";
size_t nciterbuffersize;
struct Vlendata* vlendata;
char *netcdf_name; /* command line -o file name */
char *datasetname; /* name from the netcdf <name> {} */
extern FILE *ncgin;
/* Forward */
static char* ubasename(char*);
void usage( void );
int main( int argc, char** argv );
/* Define tables vs modes for legal -k values*/
struct Kvalues legalkinds[NKVALUES] = {
{"1", 1},
{"classic", 1},
/* The 64-bit offset kind (2) should only be used if actually needed */
{"2", 2},
{"64-bit-offset", 2},
{"64-bit offset", 2},
/* NetCDF-4 HDF5 format*/
{"3", 3},
{"hdf5", 3},
{"netCDF-4", 3},
{"netcdf-4", 3},
{"netcdf4", 3},
{"enhanced", 3},
/* NetCDF-4 HDF5 format, but using only nc3 data model */
{"4", 4},
{"hdf5-nc3", 4},
{"netCDF-4 classic model", 4},
{"enhanced-nc3", 4},
/* null terminate*/
{NULL,0}
};
struct Languages {
char* name;
Language flag;
} legallanguages[] = {
{"b", L_BINARY},
{"c", L_C},
{"C", L_C},
{"f77", L_F77},
{"fortran77", L_F77},
{"Fortran77", L_F77},
{"j", L_JAVA},
{"java", L_JAVA},
{NULL,0}
};
/* The default minimum iterator size depends
on whether we are doing binary or language
based output.
*/
#define DFALTBINNCITERBUFFERSIZE 0x40000 /* about 250k bytes */
#define DFALTLANGNCITERBUFFERSIZE 0x4000 /* about 15k bytes */
/* strip off leading path */
/* result is malloc'd */
static char *
ubasename(char *logident)
{
char* sep;
sep = strrchr(logident,'/');
#ifdef MSDOS
if(sep == NULL) sep = strrchr(logident,'\\');
#endif
if(sep == NULL) return logident;
sep++; /* skip past the separator */
return sep;
}
void
usage(void)
{
derror("Usage: %s [ -b ] [ -c ] [ -f ] [ -k kind ] [ -x ] [-S struct-format] [-M <name> [ -o outfile] [ file ... ]",
progname);
derror("netcdf library version %s", nc_inq_libvers());
}
int
main(
int argc,
char *argv[])
{
int c;
FILE *fp;
#ifdef __hpux
setlocale(LC_CTYPE,"");
#endif
init_netcdf();
opterr = 1; /* print error message if bad option */
progname = ubasename(argv[0]);
cdlname = "-";
netcdf_name = NULL;
datasetname = NULL;
l_flag = 0;
nofill_flag = 0;
syntax_only = 0;
header_only = 0;
mainname = "main";
nciterbuffersize = 0;
k_flag = 0;
format_flag = 0;
enhanced_flag = 0;
specials_flag = 0;
diskless = 0;
#if _CRAYMPP && 0
/* initialize CRAY MPP parallel-I/O library */
(void) par_io_init(32, 32);
#endif
while ((c = getopt(argc, argv, "hbcfk:l:no:v:xdM:D:B:P")) != EOF)
switch(c) {
case 'd':
debug = 1;
break;
case 'D':
debug = atoi(optarg);
break;
case 'c': /* for c output, old version of "-lc" */
if(l_flag != 0) {
fprintf(stderr,"Please specify only one language\n");
return 1;
}
l_flag = L_C;
fprintf(stderr,"-c is deprecated: please use -lc\n");
break;
case 'f': /* for f77 output, old version of "-lf" */
if(l_flag != 0) {
fprintf(stderr,"Please specify only one language\n");
return 1;
}
l_flag = L_F77;
fprintf(stderr,"-f is deprecated: please use -lf77\n");
break;
case 'b': /* for binary netcdf output, ".nc" extension */
if(l_flag != 0) {
fprintf(stderr,"Please specify only one language\n");
return 1;
}
l_flag = L_BINARY;
break;
case 'h':
header_only = 1;
break;
case 'l': /* specify language, instead of using -c or -f or -b */
{
if(l_flag != 0) {
fprintf(stderr,"Please specify only one language\n");
return 1;
}
struct Languages* langs;
char* lang_name = (char*) emalloc(strlen(optarg)+1);
(void)strcpy(lang_name, optarg);
for(langs=legallanguages;langs->name != NULL;langs++) {
if(strcmp(lang_name,langs->name)==0) {
l_flag = langs->flag;
break;
}
}
if(langs->name == NULL) {
derror("%s: output language %s not implemented",
progname, lang_name);
return(1);
}
}
break;
case 'n': /* old version of -b, uses ".cdf" extension */
if(l_flag != 0) {
fprintf(stderr,"Please specify only one language\n");
return 1;
}
l_flag = L_BINARY;
binary_ext = ".cdf";
break;
case 'o': /* to explicitly specify output name */
netcdf_name = nulldup(optarg);
break;
case 'x': /* set nofill mode to speed up creation of large files */
nofill_flag = 1;
break;
case 'v': /* a deprecated alias for "kind" option */
/*FALLTHRU*/
case 'k': /* for specifying variant of netCDF format to be generated
Possible values are:
1 (=> classic 32 bit)
2 (=> classic 64 bit)
3 (=> enhanced)
4 (=> classic, but stored in an enhanced file format)
Also provide string versions of above
"classic"
"64-bit-offset"
"64-bit offset"
"enhanced" | "hdf5" | "netCDF-4"
"enhanced-nc3" | "hdf5-nc3" | "netCDF-4 classic model"
*/
{
struct Kvalues* kvalue;
char *kind_name = (char *) emalloc(strlen(optarg)+1);
if (! kind_name) {
derror ("%s: out of memory", progname);
return(1);
}
(void)strcpy(kind_name, optarg);
for(kvalue=legalkinds;kvalue->name;kvalue++) {
if(strcmp(kind_name,kvalue->name) == 0) {
k_flag = kvalue->k_flag;
break;
}
}
if(kvalue->name == NULL) {
derror("Invalid format: %s",kind_name);
return 2;
}
}
break;
case 'M': /* Determine the name for the main function */
mainname = nulldup(optarg);
break;
case 'B':
nciterbuffersize = atoi(optarg);
break;
case 'P': /* diskless with persistence */
diskless = 1;
break;
case '?':
usage();
return(8);
}
if(l_flag == 0) {
l_flag = L_BINARY; /* default */
/* Treat -k or -o as an implicit -lb assuming no other -l flags */
if(k_flag == 0 && netcdf_name == NULL)
syntax_only = 1;
}
/* Compute/default the iterator buffer size */
if(l_flag == L_BINARY) {
if(nciterbuffersize == 0 )
nciterbuffersize = DFALTBINNCITERBUFFERSIZE;
} else {
if(nciterbuffersize == 0)
nciterbuffersize = DFALTLANGNCITERBUFFERSIZE;
}
#ifndef ENABLE_C
if(c_flag) {
fprintf(stderr,"C not currently supported\n");
exit(1);
}
#endif
#ifndef ENABLE_BINARY
if(l_flag == L_BINARY) {
fprintf(stderr,"Binary netcdf not currently supported\n");
exit(1);
}
#endif
#ifndef ENABLE_JAVA
if(l_flag == L_JAVA) {
fprintf(stderr,"Java not currently supported\n");
exit(1);
}
#else
if(l_flag == L_JAVA && strcmp(mainname,"main")==0)
mainname = "Main";
#endif
#ifndef ENABLE_F77
if(l_flag == L_F77) {
fprintf(stderr,"F77 not currently supported\n");
exit(1);
}
#endif
if(l_flag != L_BINARY)
diskless = 0;
argc -= optind;
argv += optind;
if (argc > 1) {
derror ("%s: only one input file argument permitted",progname);
return(6);
}
fp = stdin;
if (argc > 0 && strcmp(argv[0], "-") != 0) {
if ((fp = fopen(argv[0], "r")) == NULL) {
derror ("can't open file %s for reading: ", argv[0]);
perror("");
return(7);
}
cdlname = (char*)emalloc(NC_MAX_NAME);
cdlname = nulldup(argv[0]);
if(strlen(cdlname) > NC_MAX_NAME) cdlname[NC_MAX_NAME] = '\0';
}
/* Standard Unidata java interface => usingclassic */
parse_init();
ncgin = fp;
if(debug >= 2) {ncgdebug=1;}
if(ncgparse() != 0)
return 1;
/* Compute the k_flag (1st pass) using rules in the man page (ncgen.1).*/
#ifndef USE_NETCDF4
if(enhanced_flag) {
derror("CDL input is enhanced mode, but --disable-netcdf4 was specified during build");
return 0;
}
#endif
if(l_flag == L_JAVA || l_flag == L_F77) {
k_flag = 1;
if(enhanced_flag) {
derror("Java or Fortran requires classic model CDL input");
return 0;
}
}
if(k_flag == 0)
k_flag = format_flag;
if(enhanced_flag && k_flag == 0)
k_flag = 3;
if(enhanced_flag && k_flag != 3) {
derror("-k or _Format conflicts with enhanced CDL input");
return 0;
}
if(specials_flag > 0 && k_flag == 0)
#ifdef USE_NETCDF4
k_flag = 3;
#else
k_flag = 1;
#endif
if(k_flag == 0)
k_flag = 1;
usingclassic = (k_flag <= 2?1:0);
/* compute cmode_modifier */
switch (k_flag) {
case 1: cmode_modifier = 0; break;
case 2: cmode_modifier = NC_64BIT_OFFSET; break;
case 3: cmode_modifier = NC_NETCDF4; break;
case 4: cmode_modifier = NC_NETCDF4 | NC_CLASSIC_MODEL; break;
default: ASSERT(0); /* cannot happen */
}
if(diskless)
cmode_modifier |= (NC_DISKLESS|NC_NOCLOBBER);
processsemantics();
if(!syntax_only && error_count == 0)
define_netcdf();
return 0;
}
END_OF_MAIN();
void
init_netcdf(void) /* initialize global counts, flags */
{
compute_alignments();
memset((void*)&nullconstant,0,sizeof(NCConstant));
fillconstant = nullconstant;
fillconstant.nctype = NC_FILLVALUE;
codebuffer = bbNew();
stmt = bbNew();
error_count = 0; /* Track # of errors */
}