int main(int argc, char *argv[]) { List list; List_node *abc; list_init(&list); check(list_size(&list) == 0); list_insert(&list, "abc"); check(list_size(&list) == 1); abc = list_lookup_data(&list, "abc", cmp_string); check(abc != NULL); check(list_lookup(&list, abc) == abc); check(list_lookup_data(&list, "def", cmp_string) == NULL); check(cmp_string((char *) list_head(&list)->data, "abc") == 0); list_insert(&list, "def"); check(list_size(&list) == 2); check(cmp_string((char *) list_head(&list)->data, "def") == 0); list_delete(&list, abc); check(list_lookup_data(&list, "abc", cmp_string) == NULL); list_delete_data(&list, "def", cmp_string); check(list_size(&list) == 0); list_free(&list, NULL); return 0; }
/* resources are stored first by type, then by name, then by language */ static int cmp_res( const void *ptr1, const void *ptr2 ) { const struct resource *res1 = ptr1; const struct resource *res2 = ptr2; int ret; if ((ret = cmp_string( &res1->type, &res2->type ))) return ret; if ((ret = cmp_string( &res1->name, &res2->name ))) return ret; return res1->lang - res2->lang; }
/* return 1, 60, or 3600, -1 if error */ double convert_time_scale(char *t, Descriptor *des) { double rc = -1.0; if ( cmp_string(t, des[0]._key) ) { rc = 1.0; } else if ( cmp_string(t, des[1]._key) ) { rc = 60.0; } else if ( cmp_string(t, des[2]._key) ) { rc = 3600.0; } return rc; }
void validate_modelo(CuTest* tc, const char * modelo_name) { struct keys { char* align; int fontsize; char* content; char* img; char* barcode_value; char* barcode_type; int barcode_height; int barcode_width; } keytab[] = { "center",1,"{Codigo} - {PedidoId}\\n",NULL,NULL,NULL,-1,-1, "center",-1,NULL,"l2ea",NULL,NULL,-1,-1, "center",-1,NULL,"l2eb",NULL,NULL,-1,-1, "center",2,"EVENTO DEMONSTRATIVO\\n\\nPISTA 5\\nUNISSEX - {Tipo}\\nR$$ {Valor}\\n",NULL,NULL,NULL,-1,-1, "center",1,"1° EDIÇÃO - SERTANEJO NA VEIA\\n",NULL,NULL,NULL,-1,-1, "center",1,"\\n{Codigo}\\n",NULL,"{Codigo}","I2of5",96,2, "center",1,"Visite:\\nwww.<b>TICPLUS</b>.com",NULL,NULL,NULL,-1,-1, }; int numkeys = sizeof(keytab)/sizeof(keytab[0]); dictionary* ini = iniparser_load(modelo_name); int i; CuAssertTrue(tc,NULL!=ini); for (i=0;i<numkeys;i++) { char buf[128]; sprintf(buf,"report_%d:align\0",i+1); CuAssertTrue(tc,0==cmp_string(keytab[i].align,iniparser_getstring(ini,buf,NULL))); sprintf(buf,"report_%d:fontsize\0",i+1); CuAssertTrue(tc,keytab[i].fontsize==iniparser_getint(ini,buf,-1)); sprintf(buf,"report_%d:content\0",i+1); CuAssertTrue(tc,0==cmp_string(keytab[i].content,iniparser_getstring(ini,buf,NULL))); sprintf(buf,"report_%d:img\0",i+1); CuAssertTrue(tc,0==cmp_string(keytab[i].img,iniparser_getstring(ini,buf,NULL))); sprintf(buf,"report_%d:barcode_value\0",i+1); CuAssertTrue(tc,0==cmp_string(keytab[i].barcode_value,iniparser_getstring(ini,buf,NULL))); sprintf(buf,"report_%d:barcode_type\0",i+1); CuAssertTrue(tc,0==cmp_string(keytab[i].barcode_type,iniparser_getstring(ini,buf,NULL))); sprintf(buf,"report_%d:barcode_height\0",i+1); CuAssertTrue(tc,keytab[i].barcode_height==iniparser_getint(ini,buf,-1)); sprintf(buf,"report_%d:barcode_width\0",i+1); CuAssertTrue(tc,keytab[i].barcode_width==iniparser_getint(ini,buf,-1)); } }
FirstDef decipher_keyword(char *pt, Descriptor *des, int sz) { FirstDef rc = def_not_found; for (int jj=0; jj<sz; jj++) { if ( cmp_string(pt, des[jj]._key)) { rc = (FirstDef)jj; break; } } return rc; }
/* get rid of duplicate resources with different versions */ static void remove_duplicate_resources( DLLSPEC *spec ) { unsigned int i, n; for (i = n = 0; i < spec->nb_resources; i++, n++) { if (i && !cmp_string( &spec->resources[i].type, &spec->resources[i-1].type ) && !cmp_string( &spec->resources[i].name, &spec->resources[i-1].name ) && spec->resources[i].lang == spec->resources[i-1].lang) { if (spec->resources[i].version == spec->resources[i-1].version) { char *type_str = format_res_string( &spec->resources[i].type ); char *name_str = format_res_string( &spec->resources[i].name ); error( "winebuild: duplicate resource type %s name %s language %04x version %08x\n", type_str, name_str, spec->resources[i].lang, spec->resources[i].version ); } else n--; /* replace the previous one */ } if (n < i) spec->resources[n] = spec->resources[i]; } spec->nb_resources = n; }
SInt64 JSON::comparef(const JSON& a, const JSON& b) { switch (a.m_type) { case e_null: switch (b.m_type) { case e_null: return cmp_null(a,b); case e_bool: return cmp_bool(a,b); case e_integer: return cmp_integer(a,b); case e_real: return cmp_real(a,b); case e_string: return cmp_string(a,b); case e_array: return cmp_array(a,b); case e_object: return cmp_object(a,b); } case e_bool: switch (b.m_type) { case e_null: return cmp_bool(a,b); case e_bool: return cmp_bool(a,b); case e_integer: return cmp_integer(a,b); case e_real: return cmp_real(a,b); case e_string: return cmp_string(a,b); case e_array: return cmp_array(a,b); case e_object: return cmp_object(a,b); } case e_integer: switch (b.m_type) { case e_null: return cmp_integer(a,b); case e_bool: return cmp_integer(a,b); case e_integer: return cmp_integer(a,b); case e_real: return cmp_real(a,b); case e_string: return cmp_string(a,b); case e_array: return cmp_array(a,b); case e_object: return cmp_object(a,b); } case e_real: switch (b.m_type) { case e_null: return cmp_real(a,b); case e_bool: return cmp_real(a,b); case e_integer: return cmp_real(a,b); case e_real: return cmp_real(a,b); case e_string: return cmp_string(a,b); case e_array: return cmp_array(a,b); case e_object: return cmp_object(a,b); } case e_string: switch (b.m_type) { case e_null: return cmp_string(a,b); case e_bool: return cmp_string(a,b); case e_integer: return cmp_string(a,b); case e_real: return cmp_string(a,b); case e_string: return cmp_string(a,b); case e_array: return cmp_array(a,b); case e_object: return cmp_object(a,b); } case e_array: switch (b.m_type) { case e_null: return cmp_array(a,b); case e_bool: return cmp_array(a,b); case e_integer: return cmp_array(a,b); case e_real: return cmp_array(a,b); case e_string: return cmp_array(a,b); case e_array: return cmp_array(a,b); case e_object: return cmp_object(a,b); } case e_object: switch (b.m_type) { case e_null: return cmp_object(a,b); case e_bool: return cmp_object(a,b); case e_integer: return cmp_object(a,b); case e_real: return cmp_object(a,b); case e_string: return cmp_object(a,b); case e_array: return cmp_object(a,b); case e_object: return cmp_object(a,b); } } Check(); return -1; }
/* build the 3-level (type,name,language) resource tree */ static struct res_tree *build_resource_tree( DLLSPEC *spec, unsigned int *dir_size ) { unsigned int i, k, n, offset, data_offset; struct res_tree *tree; struct res_type *type = NULL; struct res_name *name = NULL; struct resource *res; qsort( spec->resources, spec->nb_resources, sizeof(*spec->resources), cmp_res ); tree = xmalloc( sizeof(*tree) ); tree->types = NULL; tree->nb_types = 0; for (i = 0; i < spec->nb_resources; i++) { if (!i || cmp_string( &spec->resources[i].type, &spec->resources[i-1].type )) /* new type */ { type = add_type( tree, &spec->resources[i] ); name = add_name( type, &spec->resources[i] ); } else if (cmp_string( &spec->resources[i].name, &spec->resources[i-1].name )) /* new name */ { name = add_name( type, &spec->resources[i] ); } else if (spec->resources[i].lang == spec->resources[i-1].lang) { char *type_str = format_res_string( &spec->resources[i].type ); char *name_str = format_res_string( &spec->resources[i].name ); error( "winebuild: duplicate resource type %s name %s language %04x\n", type_str, name_str, spec->resources[i].lang ); } else name->nb_languages++; } /* compute the offsets */ offset = RESDIR_SIZE( tree->nb_types ); for (i = 0, type = tree->types; i < tree->nb_types; i++, type++) { type->dir_offset = offset; offset += RESDIR_SIZE( type->nb_names ); for (n = 0, name = type->names; n < type->nb_names; n++, name++) { name->dir_offset = offset; offset += RESDIR_SIZE( name->nb_languages ); } } data_offset = offset; offset += spec->nb_resources * RESOURCE_DATA_ENTRY_SIZE; for (i = 0, type = tree->types; i < tree->nb_types; i++, type++) { if (type->type->str) { type->name_offset = offset | 0x80000000; offset += (strlenW(type->type->str)+1) * sizeof(WCHAR); } else type->name_offset = type->type->id; for (n = 0, name = type->names; n < type->nb_names; n++, name++) { if (name->name->str) { name->name_offset = offset | 0x80000000; offset += (strlenW(name->name->str)+1) * sizeof(WCHAR); } else name->name_offset = name->name->id; for (k = 0, res = name->res; k < name->nb_languages; k++, res++) { unsigned int entry_offset = (res - spec->resources) * RESOURCE_DATA_ENTRY_SIZE; res->data_offset = data_offset + entry_offset; } } } if (dir_size) *dir_size = (offset + 3) & ~3; return tree; }
char * syscall_open_func( char *name, int mode) { int n; syscall_open_mode=mode; if(!cmp_string(name,"no_mload")) { flag_no_mload=1; return name; } if(flag_no_mload && !cmp_string(name,"/dev/mload")) { return dev_kk; } if(disable_ffs) { if(flag_no_mload && !cmp_string(name,"fat")) { return dev_kk; } } if(!flag_emu || disable_ffs) return name; // RB game identification if (game == 0) { if (!cmp_string(name, "/title/00010000/535a4145")) game = 2; // RB2 if (!cmp_string(name, "/title/00010000/535a4245")) game = 3; // RB3 } // It's time to use emulated files for RB2 if (game_loading && !cmp_string(name, "/title/00010000/535a4145/data/rockbnd2.dat")) { game_loading=0; } // Avoid nand emulation during game loading (RB2) if (game_loading && game == 2 && (!cmp_string(name, "/title/00010005") || !cmp_string(name, "/ticket/00010005"))) { return "/ticket/00010005/00000000.tik"; } // Avoid looking for non existant files if (game == 2) { if (!cmp_string(name, "/ticket/00010005")) { if (!cmp_string(name, "/ticket/00010005/735a4145.tik") || !cmp_string(name, "/ticket/00010005/735a4245.tik") || !cmp_string(name, "/ticket/00010005/735a4345.tik") || !cmp_string(name, "/ticket/00010005/735a4445.tik") || !cmp_string(name, "/ticket/00010005/735a4545.tik")) { } else return "/ticket/00010005/00000000.tik"; } } // Avoid looking for non existant files if (game == 3) { if (!cmp_string(name, "/ticket/00010005")) { if (!cmp_string(name, "/ticket/00010005/735a4145.tik") || !cmp_string(name, "/ticket/00010005/735a4245.tik") || !cmp_string(name, "/ticket/00010005/735a4345.tik") || !cmp_string(name, "/ticket/00010005/735a4445.tik") || !cmp_string(name, "/ticket/00010005/735a4545.tik") || !cmp_string(name, "/ticket/00010005/735a4a45.tik") || !cmp_string(name, "/ticket/00010005/735a4b45.tik") || !cmp_string(name, "/ticket/00010005/735a4c45.tik") || !cmp_string(name, "/ticket/00010005/735a4d45.tik")) { } else return "/ticket/00010005/00000000.tik"; } } if(name[0]=='#') // for example #/title/xxxx : can be used to skip this function to open files { name++; for(n=0; name[n]; n++) sys_name[n+32]=name[n]; sys_name[n+32]=0; name=(char *) sys_name+32; } else if(!cmp_string(name,"/dev/stm/immediate")) { static char stm[] ATTRIBUTE_ALIGN(32)=DEVICE_FAT"/dev/immediate"; name++; for(n=0; stm[n]; n++) sys_name[n+32]=stm[n]; sys_name[n+32]=0; name=(char *) sys_name+32; } else if(sd_mounted>0 && !cmp_string(name,"/dev/sdio"))
// top level function to parse the spt netlist and construct the SUBCATCHMENT object // as well as modifying the Options and Sgraph objects int read_spt_from_file(FILE* F, Subcatchment *SUB, NameStore *NODE_NAMES, SMap *HASH, FILE* out) { FirstDef rc; int r_code; int line_num, good, node_index; source_id src_id; unsigned int n_op,n_node, n_seg, n_junc, n_qs, n_ls, n_bdn; StrBuffer *Prime, *Second; SimpleDblArray dba; double *XX=NULL, *YY=NULL; FlexVec<int, SHORT_ARRY_LENGTH> qsources; // we store index only FlexVec<int, SHORT_ARRY_LENGTH> lsources; FlexVec<int, SHORT_ARRY_LENGTH> asources; ChkSum mychk; char chktmp[10]; Prime = new StrBuffer(1023); // both arrayes can automatically grow if needed Second = new StrBuffer(4095); r_code = -1; // by default, the return code indicates failure /* we first read the option blocks */ rc = def_not_found; line_num = 0; n_op = n_node = n_seg = n_junc = n_qs = n_ls = n_bdn = 0; while (1) { // first do the tally, and a rough check rc = search_block(F, &line_num, Spt_Descriptor, DES_SIZE(Spt_Descriptor), Prime, Second, out); switch (rc) { case p_options: n_op++; break; case p_node: n_node++; break; case p_segment: n_seg++; break; case p_junction: n_junc++; break; case p_qsource: n_qs++; break; case p_lateralsource: n_ls++; break; case p_boundarycondition: n_bdn++; break; case def_not_found: break; case def_error: goto back; break; default: break; } if ( rc == def_not_found ) break; } rewind(F); if (out) { fprintf(out,"[II]: Found %d nodes, %d segmetns, %d junctions, %d q_sources, %d lateral sources, %d bdn condtions, %d options in the netlist\n", n_node, n_seg, n_junc, n_qs, n_ls, n_bdn, n_op); } if ( n_node < 2 ) { if (out) fprintf(out, "Bummer: not enough node statements, unable to procced\n"); goto back; } else if ( n_seg < 1 ) { if (out) fprintf(out, "Bummer: not enough segment statements, unable to procced\n"); goto back; } else if ( n_qs < 1 ) { if (out) fprintf(out, "Bummer: not enough Q source statements, unable to procced\n"); goto back; } else if ( n_bdn < 1 ) { if (out) fprintf(out, "Bummer: not enough boundary condition statements, unable to procced\n"); goto back; } // Copy the stat into the STAT object STAT.N_Nodes() = n_node; STAT.N_Segs() = n_seg; STAT.N_Juncs() = n_junc; STAT.N_Qsrcs() = n_qs; STAT.N_Lsrcs() = n_ls; STAT.N_Bnds() = n_bdn; // do the memory allocation stuff here NODE_NAMES->Init(n_node); SUB->InitGraph(n_node, n_seg, n_junc); //Testing // allocate memory to store the boundary conditions qsources.size(n_node+10); lsources.size(n_node+10); asources.size(n_node+10); for (unsigned int jj=0; jj<n_node+10; jj++) qsources[jj]=-1; for (unsigned int jj=0; jj<n_node+10; jj++) lsources[jj]=-1; for (unsigned int jj=0; jj<n_node+10; jj++) asources[jj]=-1; // we now proess options, otherwise we use default values if ( n_op > 0 ) { char *tmp; double stoptimeunit=1.0, timestepunit=1.0, prtintervalunit=1.0; double stoptime=-1.0, timestep=0.0, prtinterval=0.0; double prtstartunit = 1.0, prtstart = 0.0; double spinuptime = 0.0; rewind(F); rc = def_not_found; line_num = 0; while (1) { rc = search_block(F, &line_num, Spt_Descriptor, DES_SIZE(Spt_Descriptor), Prime, Second, NULL); if (rc == def_not_found ) break; if (rc != p_options ) continue; // read the options, in particular UseMetric! good = Prime->Separate(out); if (good<0) { if (out) fprintf(out,"Bummer: Syntax error in netlist specification at line %d\n", line_num); goto back; } tmp = Prime->Find_Value( Op_Descriptor[0]._key); // USEMETRIC if (tmp) { OPT.UseMetric() = atoi(tmp)>0 ? 1 : 0; if (out) fprintf(out,"[II]: Metric set to %d\n", OPT.UseMetric()); } // we process unit first so that we don't have to worry later tmp = Prime->Find_Value( Op_Descriptor[2]._key); // TIMESTEPUNIT if (tmp) { timestepunit = convert_time_scale(tmp, Time_Descriptor); } if ( timestepunit < 0 ) { if (out) fprintf(out,"[WW]: only accept time unit of SECOND, MINUTE, HOUR for statement on line %d. Use default=SECOND. \n", Prime->LineNumber()); timestepunit = 1.0; } tmp = Prime->Find_Value( Op_Descriptor[1]._key); // TIMESTEP if (tmp) timestep = atof(tmp); tmp = Prime->Find_Value( Op_Descriptor[4]._key); // STOPTIMEUNIT if (tmp) { stoptimeunit = convert_time_scale(tmp, Time_Descriptor); } if ( stoptimeunit < 0 ) { if (out) fprintf(out,"Bummer:only accept time unit of SECOND, MINUTE, HOUR for statement on line %d. Use default=SECOND. \n", Prime->LineNumber()); stoptimeunit = 1.0; } tmp = Prime->Find_Value( Op_Descriptor[3]._key); // STOPTIME if (tmp) stoptime = atof(tmp); // also deal with print interval first tmp = Prime->Find_Value( Op_Descriptor[6]._key); // PRTINTERVALUNIT if (tmp) { prtintervalunit = convert_time_scale(tmp, Time_Descriptor); } if ( prtintervalunit < 0 ) { if (out) fprintf(out,"[WW]: only accept time unit of SECOND, MINUTE, HOUR for statement on line %d. Use default=SECOND. \n", Prime->LineNumber()); prtintervalunit = 1.0; } tmp = Prime->Find_Value( Op_Descriptor[8]._key); // PRTSTARTUNIT if (tmp) { prtstartunit = convert_time_scale(tmp, Time_Descriptor); } if ( prtstartunit < 0 ) { if (out) fprintf(out,"[WW]: only accept time unit of SECOND, MINUTE, HOUR for statement on line %d. Use default=SECOND. \n", Prime->LineNumber()); prtstartunit = 1.0; } tmp = Prime->Find_Value( Op_Descriptor[7]._key); // PRTSTART if (tmp) prtstart = atof(tmp); tmp = Prime->Find_Value( Op_Descriptor[5]._key); // PRTINTERVAL if (tmp) prtinterval = atof(tmp); if ( prtinterval < 0 ) { if (out) fprintf(out,"[WW]: negative print interval specified on line %d. Overwritten with zero!\n", Prime->LineNumber()); prtinterval = 0.0; } tmp = Prime->Find_Value( Op_Descriptor[9]._key); // CHECKONLY if (tmp) { OPT.CheckOnly() = atoi(tmp) > 0 ? 1 : 0; if (out) fprintf(out,"[II]: CheckOnly set to %d\n", OPT.CheckOnly()); } tmp = Prime->Find_Value( Op_Descriptor[10]._key); // SSFILE if (tmp) { STAT.SetSSFile(tmp); if (out) fprintf(out, "[II]: SSFile (SteadyState file) set to \"%s\"\n", tmp); } tmp = Prime->Find_Value( Op_Descriptor[11]._key); // Lmax if (tmp) { OPT.LMax() = atof(tmp); if (out) fprintf(out,"[II]: LMax set to %.4e\n", OPT.LMax() ); } tmp = Prime->Find_Value( Op_Descriptor[12]._key); // Lmin if (tmp) { OPT.LMin() = atof(tmp); if (out) fprintf(out,"[II]: LMin set to %.4e\n", OPT.LMin() ); } tmp = Prime->Find_Value( Op_Descriptor[13]._key); // PrintDepth if (tmp) { OPT.PrintD() = atoi(tmp) > 0 ? 1 : 0; if (out) fprintf(out,"[II]: PrtDepth set to %1d\n", OPT.PrintD() ); } tmp = Prime->Find_Value( Op_Descriptor[14]._key); // PrintSurfElev if (tmp) { OPT.PrintZ() = atoi(tmp) > 0 ? 1 : 0; if (out) fprintf(out,"[II]: PrtSurfElev set to %1d\n", OPT.PrintZ() ); } tmp = Prime->Find_Value( Op_Descriptor[15]._key); // PrintQ if (tmp) { OPT.PrintQ() = atoi(tmp) > 0 ? 1 : 0; if (out) fprintf(out,"[II]: PrtQ set to %1d\n", OPT.PrintQ() ); } tmp = Prime->Find_Value( Op_Descriptor[16]._key); // PrintA if (tmp) { OPT.PrintA() = atoi(tmp) > 0 ? 1 : 0; if (out) fprintf(out,"[II]: PrtA set to %1d\n", OPT.PrintA() ); } tmp = Prime->Find_Value( Op_Descriptor[17]._key); // PrintCoord if (tmp) { OPT.PrintXY() = atoi(tmp) > 0 ? 1 : 0; if (out) fprintf(out,"[II]: PrtCoord set to %1d\n", OPT.PrintXY() ); } tmp = Prime->Find_Value( Op_Descriptor[18]._key); // verbose if (tmp) { OPT.DebugLevel() = atoi(tmp) > 0 ? atoi(tmp) : 0; if (out) fprintf(out,"[II]: Verbose set to %1d\n", OPT.DebugLevel() ); } tmp = Prime->Find_Value( Op_Descriptor[19]._key); // epoch if (tmp) { STAT.SetEpoch(tmp); if (out) fprintf(out, "[II]: Epoch is set to %s\n", STAT.Epoch() ); } tmp = Prime->Find_Value( Op_Descriptor[20]._key); // spinup_time if (tmp) spinuptime = atof(tmp); if ( spinuptime < 0 ) { if (out) fprintf(out,"[WW]: negative spin-up time specified on line %d. Use zero instead (disabled)\n", Prime->LineNumber()); spinuptime = 0.0; } } // check if stoptime is specified (by setting default to 0), // do the scaling, // reason: we might have multiple option blocks if ( timestep < 0 ) { if (out) fprintf(out,"[WW]: negative TimeStep specified. Overwritten with zeor!\n"); } else if (timestep > 0) { timestep *= timestepunit; OPT.FixedStep() = timestep; if (out) fprintf(out,"[II]: TimeStep set to %.3e second.\n", timestep); } if ( prtinterval < 0 ) { if (out) fprintf(out,"[WW]: negative PrInterval specified. Overwritten with zero!\n"); } else if (prtinterval>0) { int tt; prtinterval *= prtintervalunit; tt = (int) round(prtinterval/60.0); tt = tt >=0 ? tt : 0; OPT.PrintInterval() = tt; if (out) fprintf(out,"[II]: PrtInterval set to %d min\n", tt); } if (prtstart < 0) { if (out) fprintf(out,"[WW]: negative PrtStart specified. Overwritten with zero!\n"); } else if ( prtstart > 0) { int tt; prtstart *= prtstartunit; tt = (int)round(prtstart/60.0); tt = tt>=0 ? tt : 0; OPT.PrintStart() = tt; if (out) fprintf(out, "[II]: PrtStart set to %d min\n", tt); } if (stoptime > 0 ) { stoptime *= stoptimeunit; OPT.StopTime() = stoptime; if (out) fprintf(out,"[II]: StopTime set to %.3e second\n", stoptime); } else { if (out) fprintf(out,"Bummer: a positive StopTime is required in order to run the simulation!\n"); goto back; } if ( spinuptime > 0 ) { int tt = (int)spinuptime; const int min_spin = 300; if ( tt > min_spin ) { OPT.SpinUpTime() = tt; if (out) fprintf(out,"[II]: SpinUpTime set to %d second\n", tt); } else { OPT.SpinUpTime() = 0; if (out) fprintf(out,"[WW]: minimal spinup time is %d seconds. Revert back to zero (spinup disabled)\n", min_spin); } } } // add nodes, check duplicate rewind(F); rc = def_not_found; line_num = 0; while (1) { char node_id[MAX_LINE_LENGTH]; char *tmp; double s0, n, h0, z0, width, slope; XsecType xtp; int num_pairs; double q0=0, a0=0; // we will deal with them later double x=-1.0, y=-1.0; // not used rc = search_block(F, &line_num, Spt_Descriptor, DES_SIZE(Spt_Descriptor), Prime, Second, NULL); // we don't check on the error flags since we have done it before if (rc == def_not_found ) break; // we added all nodes if (rc == def_error ) goto back; width = 0.0; slope = 0.0; num_pairs = 0; switch (rc) { case p_node: /* intercept and understand node */ if ( !Second->HasContent()) { if (out) fprintf(out,"Bummer: NODE statement on line %d requires a x-section specification\n", Prime->LineNumber() ); goto back; } good = Prime->Separate(out); good = Second->Separate(out); if (good <0) { if (out) fprintf(out,"Bummer: syntax error in netlist specification in line %d\n", Prime->LineNumber()); goto back; } // parse each field one by one tmp = Prime->Find_Value( Node_Descriptor[0]._key); // "id" if (!tmp) { if (out) fprintf(out, "Bummer: unable to locate field %s for the NODE statement on line %d\n", Node_Descriptor[0]._key, Prime->LineNumber()); goto back; } // the clean node id is now in node_id; strncpy(node_id, tmp, MAX_WORD_LENGTH); node_index = HASH->Check(node_id); if ( node_index != -1 ) { if (out) fprintf(out,"Bummer: duplicated NODE definition of node \"%s\" on line %d\n", node_id, Prime->LineNumber() ); goto back; } node_index = HASH->Create(node_id); NODE_NAMES->Insert(node_id, node_index); tmp = Prime->Find_Value( Node_Descriptor[1]._key); // "sR" if (!tmp) { if (out) fprintf(out, "Bummer: unable to locate field %s for the NODE statement on line %d\n", Node_Descriptor[1]._key, Prime->LineNumber()); goto back; } s0 = atof(tmp); if ( s0 < 1e-6 ) { if (out) fprintf(out, "[WW]: reference slope sR at location %s is nonpositive with value of %.4e. \n", node_id, s0); #if 0 goto back; #endif } tmp = Prime->Find_Value( Node_Descriptor[2]._key); // "n" if (!tmp) { if (out) fprintf(out, "Bummer: unable to locate field %s for the NODE statement on line %d\n", Node_Descriptor[2]._key, Prime->LineNumber()); goto back; } n = atof(tmp); if ( n < OPT.MinN() ) { if (out) fprintf(out,"[WW]: Manning's N at location %s is %.4e, less than threshold value %.4e. Supercritical flow might occur\n", node_id, n, OPT.MinN()); } tmp = Prime->Find_Value( Node_Descriptor[3]._key); // "zR" if (!tmp) { if (out) fprintf(out, "Bummer: unable to locate field %s for the NODE statement on line %d\n", Node_Descriptor[3]._key, Prime->LineNumber()); goto back; } z0 = atof(tmp); tmp = Prime->Find_Value( Node_Descriptor[4]._key); // "hR" if (!tmp) { if (out) fprintf(out, "Bummer: unable to locate field %s for the NODE statement on line %d\n", Node_Descriptor[4]._key, Prime->LineNumber()); goto back; } h0 = atof(tmp); tmp = Prime->Find_Value( Node_Descriptor[5]._key); // "xcoord" if (tmp) { x = atof(tmp); // this is optional } tmp = Prime->Find_Value( Node_Descriptor[6]._key); // "ycoord" if (tmp) { y = atof(tmp); } if ( Second->Cmp_Head(Node_Descriptor[7]._key)) { // "Trapezoidal tmp = Second->Find_Value(Trap_Descriptor[0]._key); // "bottomwidth" if (!tmp) { if (out) fprintf(out, "Bummer: %s x-section on line %d requires field %s\n", Node_Descriptor[5]._key, Second->LineNumber(), Trap_Descriptor[0]._key); goto back; } width = atof(tmp); tmp = Second->Find_Value(Trap_Descriptor[1]._key); // "slope" if (!tmp) { if (out) fprintf(out, "Bummer: %s x-section on line %d requires field %s\n", Node_Descriptor[5]._key, Second->LineNumber(), Trap_Descriptor[1]._key); goto back; } else { slope = atof(tmp); } xtp = TRAP; } else if ( Second->Cmp_Head(Node_Descriptor[8]._key)) { // "Rectangular" tmp = Second->Find_Value(Rect_Descriptor[0]._key); // "bottomwidth" if (!tmp) { if (out) fprintf(out, "Bummer: %s x-section on line %d requires field %s\n", Node_Descriptor[6]._key, Second->LineNumber(), Rect_Descriptor[0]._key); goto back; } else { width = atof(tmp); } xtp = RECT; } else if ( Second->Cmp_Head(Node_Descriptor[9]._key)) { // "XY" if ( Second->NumPairs() % 2 != 0 ) { if (out) fprintf(out,"Bummer: unbalanced XY pairs for %s statement on line %d\n", Node_Descriptor[7]._key,Second->LineNumber()); goto back; } else { // all good, copy the values dba.Reset(); num_pairs = read_2d_arrays(Second, XY_Descriptor, &dba, 0, out); if ( num_pairs <= 0 ) { if (out) fprintf(out,"Bummer: error reading 2D data specified on line %d\n", Second->LineNumber() ); goto back; } } xtp = SPLINE; } else { if (out) fprintf(out,"Bummer: NODE statement on line %d requires at least one of the x-section specification: %s, %s or %s\n", Prime->LineNumber(), Node_Descriptor[5]._key, Node_Descriptor[6]._key, Node_Descriptor[7]._key); goto back; } // at this point, all variables are ready, create the node // use node_idx, s0, n, h0, z0, dba (good) // first do scaling based UseMetric() XX = dba.X(); YY = dba.Y(); if (OPT.UseMetric() == 0 ) { if (xtp == SPLINE) { for (int jj=0; jj<num_pairs; jj++) { XX[jj] *= OPT.FtoM(); YY[jj] *= OPT.FtoM(); } } else { // RECT or TRAP, only change the bottom width, slope is dimensionless width *= OPT.FtoM(); } z0 *= OPT.FtoM(); h0 *= OPT.FtoM(); } if ( xtp == SPLINE ) { #ifdef DBGSPLINE printf("node name %s, id %d\n", node_id, (unsigned int)node_index); #endif SUB->MakeNode((unsigned int)node_index, s0, n, x, y, q0, a0, z0, h0, SPLINE, num_pairs, XX, YY); } else if (xtp == TRAP) { SUB->MakeNode((unsigned int)node_index, s0, n, x, y, q0, a0, z0, h0, TRAP, width, slope); } else if (xtp == RECT) { SUB->MakeNode((unsigned int)node_index, s0, n, x, y, q0, a0, z0, h0, RECT, width); } break; default: break; } // end switch } // while loop, find all nodes // make SUB happy SUB->AssignNodes(); // records Qsrc, Lsrc and Bdn's rewind(F); rc = def_not_found; line_num = 0; while (1) { char node_id[MAX_LINE_LENGTH]; char *tmp; int num_pairs; int loc_index, bnd_is_area; Node *node=NULL; // double geo_scale=1.0; rc = search_block(F, &line_num, Spt_Descriptor, DES_SIZE(Spt_Descriptor), Prime, Second, NULL); // we don't check on the error flags since we have done it before if (rc == def_not_found ) break; // we added all nodes if (rc == def_error ) goto back; num_pairs = 0; switch (rc) { case p_qsource: if (!Second->HasContent()) { if (out) fprintf(out,"Bummer: QSOURCE statement on line %d requires a time series specification\n", Prime->LineNumber() ); goto back; } good = Prime->Separate(out); good = Second->Separate(out); if (good<0) { if (out) fprintf(out,"Bummer: syntax error in netlist specification in line %d\n", line_num); goto back; } tmp = Prime->Find_Value( Qsource_Descriptor[0]._key); // "location" if (!tmp) { if (out) fprintf(out, "Bummer: unable to locate field %s for the QSOURCE statement on line %d\n", Qsource_Descriptor[0]._key, Prime->LineNumber()); goto back; } if ( !Second->Cmp_Head( Qsource_Descriptor[1]._key) ) { // "timeseries" if (out) fprintf(out,"Bummer: QSOURCE statement on line %d requires time series specification: %s\n", Prime->LineNumber(), Qsource_Descriptor[1]._key); goto back; } strncpy(node_id, tmp, MAX_WORD_LENGTH); loc_index = HASH->Check(node_id); if ( loc_index == -1 ) { if (out) fprintf(out, "Bummer: cannot find node \"%s\" specified on line %d\n", node_id, Prime->LineNumber()); goto back; } dba.Reset(); num_pairs = read_2d_arrays(Second, TS_Descriptor, &dba, 1, out); if ( num_pairs <= 0 ) { if (out) fprintf(out,"Bummer: error reading 2D data specified on line %d\n", Second->LineNumber() ); goto back; } // ready to insert Q source, with node and time series in dba (good), remember the // dba.Scale() field, which is the time scale XX = dba.X(); YY = dba.Y(); src_id = SUB->MakeSource(num_pairs, &XX[0], &YY[0], dba.Scale(), (OPT.UseMetric()==0?OPT.F3toM3():1.0) ); if (src_id<0) { if (out) fprintf(out,"Bummer: problem with QSource at node \"%s\" on line %d\n", node_id, Prime->LineNumber()); goto back; } if ( qsources[ loc_index] > -1 ) { if (out) fprintf(out, "Bummer: duplicated definitino of Qsource at node \"%s\"\n", node_id); goto back; } qsources[ loc_index ] = src_id; // store the index break; case p_lateralsource: if (!Second->HasContent()) { if (out) fprintf(out,"Bummer: LATERALSOURCE statement on line %d requires a time series specification\n", Prime->LineNumber() ); goto back; } good = Prime->Separate(out); good = Second->Separate(out); if (good<0) { if (out) fprintf(out,"Bummer: problem with LateralSource on line %d\n", Prime->LineNumber()); goto back; } tmp = Prime->Find_Value( Latsource_Descriptor[0]._key); // "location" if (!tmp) { if (out) fprintf(out, "Bummer: unable to locate field %s for the LATERALSOURCE statement on line %d\n", Latsource_Descriptor[0]._key, Prime->LineNumber()); goto back; } if ( !Second->Cmp_Head( Latsource_Descriptor[1]._key) ) { // "timeseries" if (out) fprintf(out,"Bummer: LATERALSOURCE statement on line %d requires time series specification: %s\n", Prime->LineNumber(), Latsource_Descriptor[1]._key); goto back; } strncpy(node_id, tmp, MAX_WORD_LENGTH); loc_index = HASH->Check(node_id); if ( loc_index == -1 ) { if (out) fprintf(out, "Bummer: cannot find node \"%s\" specified on line %d\n", node_id, Prime->LineNumber()); goto back; } dba.Reset(); num_pairs = read_2d_arrays(Second, TS_Descriptor, &dba, 1, out); if ( num_pairs <= 0 ) { if (out) fprintf(out,"Bummer: error reading 2D data specified on line %d\n", Second->LineNumber() ); goto back; } // ready to insert lateral source, with loc_index and time series in dba (good), // remember dba.Scale() XX = dba.X(); YY = dba.Y(); src_id = SUB->MakeSource(num_pairs, &XX[0], &YY[0], dba.Scale(), (OPT.UseMetric()==0?OPT.F3toM3():1.0) ); if (src_id<0) { if (out) fprintf(out,"Bummer: problem with LATERALSOURCE at node \"%s\" on line %d\n", node_id, Prime->LineNumber()); goto back; } if ( lsources[ loc_index ] > -1 ) { if (out) fprintf(out, "Bummer: duplicated definitino of LATERALSOURCE at node \"%s\"\n", node_id); goto back; } lsources[ loc_index ] = src_id; break; case p_boundarycondition: if (!Second->HasContent()) { if (out) fprintf(out,"Bummer: BOUNDARYCONDITION statement on line %d requires a time series specification\n", Prime->LineNumber() ); goto back; } good = Prime->Separate(out); good = Second->Separate(out); if (good<0) { if (out) fprintf(out,"Bummer: syntax error in BoundaryCondition Statement in line %d\n", Prime->LineNumber()); goto back; } tmp = Prime->Find_Value( Bdn_Descriptor[1]._key); // "type" if (!tmp) { if (out) fprintf(out, "Bummer: unable to locate field %s for the BOUNDARYCONDITION statement on line %d\n", Bdn_Descriptor[1]._key, Prime->LineNumber()); goto back; } if ( cmp_string(tmp, BdnType_Descriptor[0]._key) ) { // "AREA" bnd_is_area = 1; } else if (cmp_string(tmp, BdnType_Descriptor[1]._key) ) { // "DEPTH" bnd_is_area = 0; } else { if (out) fprintf(out, "Bummer: BoundaryCondition has to be either \"%s\" or \"%s\" for statement on line %d\n", BdnType_Descriptor[0]._key, BdnType_Descriptor[1]._key, Prime->LineNumber() ); goto back; } tmp = Prime->Find_Value( Bdn_Descriptor[0]._key); // "location" if (!tmp) { if (out) fprintf(out, "Bummer: unable to locate field %s for the BOUNDARYCONDITION statement on line %d\n", Bdn_Descriptor[0]._key, Prime->LineNumber()); goto back; } strncpy(node_id, tmp, MAX_WORD_LENGTH); loc_index = HASH->Check(node_id); if ( loc_index == -1 ) { if (out) fprintf(out, "Bummer: cannot find node \"%s\" specified on line %d\n", node_id, Prime->LineNumber()); goto back; } if ( !Second->Cmp_Head( Bdn_Descriptor[2]._key) ) { // "timeseries" if (out) fprintf(out,"Bummer: BOUNDARYCONDITION statement on line %d requires time series specification: %s\n", Prime->LineNumber(), Bdn_Descriptor[2]._key); goto back; } dba.Reset(); num_pairs = read_2d_arrays(Second, TS_Descriptor, &dba, 1, out); if ( num_pairs <= 0 ) { if (out) fprintf(out,"Bummer: error reading 2D data specified on line %d\n", Second->LineNumber() ); goto back; } // ready to insert Bdn condition, with loc_index and time series in dba (good), // remember dba.Scale() XX = dba.X(); YY = dba.Y(); if ( bnd_is_area == 0 ) { node = SUB->GetNode( loc_index ); if ( !node ) { if (out) fprintf(out, "Bummer: node \"%s\" not yet defined!\n", node_id); goto back; } } if ( bnd_is_area) { src_id = SUB->MakeSource(num_pairs, &XX[0], &YY[0], dba.Scale(), (OPT.UseMetric()==0?OPT.F2toM2():1.0) ); } else { FlexVec<double> tmp; tmp.size(num_pairs); node = SUB->GetNode( loc_index); for (int jj=0; jj<num_pairs;jj++) { tmp[jj]= node->GetAbyDepth( YY[jj]*(OPT.UseMetric()==0?OPT.FtoM():1.0) ); } src_id = SUB->MakeSource(num_pairs, &XX[0], &tmp[0], dba.Scale(), 1.0); } if (src_id < 0) { if (out) fprintf(out, "Bummer: problem with BoundaryCondition definition on line %d\n", Prime->LineNumber() ); goto back; } if ( asources[ loc_index] >-1 ) { if (out) fprintf(out, "Bummer: duplicated definitino of BOUNDARYCONDITION at node \"%s\"\n", node_id); goto back; } asources[ loc_index ] = src_id; break; default: break; } // end switch } // while loop, found all qsource, lsources and asources // process the rest, segments, junctions rc = def_not_found; rewind(F); line_num = 0; while (1) { int up_idx, down_idx; int up1_idx, up2_idx; double length, coef1, coef2; char *tmp; Node *fp, *tp; rc = search_block(F, &line_num, Spt_Descriptor, DES_SIZE(Spt_Descriptor), Prime, Second, NULL); if (rc == def_error) goto back; if (rc == def_not_found) break; switch ( rc ) { case p_segment: good = Prime->Separate(out); if (good<0) { if (out) fprintf(out,"Bummer: syntax error in netlist specification at line %d\n", Prime->LineNumber()); goto back; } tmp = Prime->Find_Value( Segment_Descriptor[0]._key); // "up" if ( !tmp) { if (out) fprintf(out, "Bummer: SEGMENT statement on line %d requires the \"%s\" field.\n", Prime->LineNumber(), Segment_Descriptor[0]._key); goto back; } up_idx = HASH->Check(tmp); if ( up_idx == -1 ) { if (out) fprintf(out, "Bummer: cannot find node \"%s\" specified on line %d\n", tmp, Prime->LineNumber()); goto back; } tmp = Prime->Find_Value( Segment_Descriptor[1]._key); // "down: if ( !tmp) { if (out) fprintf(out, "Bummer: SEGMENT statement on line %d requires the \"%s\" field.\n", Prime->LineNumber(), Segment_Descriptor[1]._key); goto back; } down_idx = HASH->Check(tmp); if ( down_idx == -1 ) { if (out) fprintf(out, "Bummer: cannot find node \"%s\" specified on line %d\n", tmp, Prime->LineNumber()); goto back; } tmp = Prime->Find_Value( Segment_Descriptor[2]._key); // "length" if ( !tmp ) { if (out) fprintf(out, "Bummer: SEGMENT statement on line %d requires the \"%s\" field.\n", Prime->LineNumber(), Segment_Descriptor[2]._key); goto back; } if ( !is_scientific( tmp ) ) { if (out) fprintf(out, "Bummer: invalid real value specification on line %d\n",Prime->LineNumber()); goto back; } length = atof(tmp); // ready to insert segment, use up_idx, down_idx, length, check length > 0! if ( length <= 0.0 ) { if (out) fprintf(out,"Bummer: found negative or zero length on line %d\n", Prime->LineNumber() ); goto back; } if ( length <= OPT.LMin() ) { if (out) fprintf(out,"[WW]: segment length on line %d is %.4e, less than preferred minimal %.4e\n", Prime->LineNumber(), length, OPT.LMin()); } if ( length >= OPT.LMax() ) { if (out) fprintf(out,"[WW]: segment length on line %d is %.4e, larger than preferred maxium %.4e\n", Prime->LineNumber(), length, OPT.LMax()); } if (OPT.UseMetric() == 0 ) length *= OPT.FtoM(); fp = SUB->GetNode( up_idx ); tp = SUB->GetNode( down_idx ); if (fp == NULL) { if (out) fprintf(out,"Bummer: internal error, unable to locate node at index %d for statement on line %d\n", up_idx, Prime->LineNumber()); goto back; } if (tp == NULL) { if (out) fprintf(out,"Bummer: internal error, unable to locate node at index %d for statement on line %d\n", down_idx, Prime->LineNumber()); goto back; } // in case we have a lateral source src_id = lsources[up_idx]; SUB->MakeStvEquation( up_idx, down_idx, length, src_id ); break; case p_junction: good = Prime->Separate(out); if (good<0) { if (out) fprintf(out,"Bummer: syntax error in netlist specification at line %d\n", Prime->LineNumber()); goto back; } tmp = Prime->Find_Value( Junc_Descriptor[0]._key); // "up1" if (tmp) { up1_idx = HASH->Check(tmp); if ( up1_idx == -1 ) { if (out) fprintf(out, "Bummer: cannot find node \"%s\" specified on line %d\n", tmp, Prime->LineNumber()); goto back; } } else up1_idx = -1; tmp = Prime->Find_Value( Junc_Descriptor[1]._key); // "up2: if (tmp) { up2_idx = HASH->Check(tmp); if ( up2_idx == -1 ) { if (out) fprintf(out, "Bummer: cannot find node \"%s\" specified on line %d\n", tmp, Prime->LineNumber()); goto back; } } else up2_idx = -1; tmp = Prime->Find_Value( Junc_Descriptor[2]._key); // "down" if ( !tmp) { if (out) fprintf(out, "Bummer: JUNCTION statement on line %d requires the \"%s\" field.\n", Prime->LineNumber(), Junc_Descriptor[2]._key); goto back; } down_idx = HASH->Check(tmp); if ( down_idx == -1 ) { if (out) fprintf(out, "Bummer: cannot find node \"%s\" specified on line %d\n", tmp, Prime->LineNumber()); goto back; } tmp = Prime->Find_Value( Junc_Descriptor[3]._key); // "coeff1" if (tmp) { if ( !is_scientific( tmp ) ) { if (out) fprintf(out, "Bummer: invalid real value specification on line %d\n",Prime->LineNumber()); goto back; } coef1 = atof(tmp); if ( coef1 <= 0.0 ) { if (out) fprintf(out, "Bummer: coefficient should be positive on line %d\n",Prime->LineNumber()); goto back; } } else coef1 = -1.0; tmp = Prime->Find_Value( Junc_Descriptor[4]._key); // "coeff2" if ( tmp) { if ( !is_scientific( tmp ) ) { if (out) fprintf(out, "Bummer: invalid real value specification on line %d\n",Prime->LineNumber()); goto back; } coef2 = atof(tmp); if ( coef2 <= 0.0 ) { if (out) fprintf(out, "Bummer: coefficient should be positive on line %d\n",Prime->LineNumber()); goto back; } } else coef2 = -1.0; // ready to insert junction, use up1_idx, up2_idx, down_idx, coef1, coef2, check if ( up1_idx == -1 && up2_idx == -1 ) { if (out) fprintf(out,"Bummer: at least one upstream nodes has to be specified on line %d\n", Prime->LineNumber() ); goto back; } if ( coef1 < 0 && coef2 < 0 ) { if (out) fprintf(out,"Bummer: at least one upstream coefficients has to be specified on line %d\n", Prime->LineNumber() ); goto back; } if ( (up1_idx > 0 && coef1 < 0) || ( up2_idx>0 && coef2<0 ) ) { if (out) fprintf(out,"Bummer: mismatch in upstream node and coefficient specifications on line %d\n", Prime->LineNumber()); goto back; } /* To add: distance check among three nodes, use X() and Y() of each node */ int nn[2]; double rr[2]; if ( up1_idx > 0 && up2_idx > 0 ) { // both nn[0] = up1_idx; nn[1] = up2_idx; rr[0] = coef1; rr[1] = coef2; SUB->MakeDepEquation( down_idx, 2, &nn[0], &rr[0]); } else if ( up1_idx > 0 ) { // up1 only nn[0] = up1_idx; rr[0] = coef1; SUB->MakeDepEquation( down_idx, 1, &nn[0], &rr[0]); } else { // up2 only nn[0] = up2_idx; rr[0] = coef2; SUB->MakeDepEquation( down_idx, 1, &nn[0], &rr[0]); } break; default: break; } } // insert Qsrc, lateral source and Bdn for (int jj=0; jj<STAT.N_Nodes(); jj++) { if ( qsources[jj] > -1) { if ( SUB->GetSource( qsources[jj])->GetParent() >= 0 ) { if (out) fprintf(out, "Bummer: trying to re-use qsource at node index %d\n",jj); goto back; } SUB->MakeQrSrcEquation( jj, qsources[jj] ); } } for (int jj=0; jj<STAT.N_Nodes(); jj++) { if ( asources[jj] > -1 ) { if ( SUB->GetSource( asources[jj] )->GetParent() >= 0 ) { if (out) fprintf(out, "Bummer: trying to re-use asource at node index %d\n",jj); goto back; } SUB->MakeArSrcEquation( jj, asources[jj]); break; // we assume there is only ONE BdnCondition } } r_code = 0; // only at this point we indicate everything is clean // calculate the chksum in case we are going to load something from the data for (int jj=0; jj<STAT.N_Nodes(); jj++) { mychk.add_string( NODE_NAMES->Get(jj) ); } for (int jj=0; jj<STAT.N_Nodes(); jj++) { if ( qsources[jj] > -1 ) { Source *s = (Source*)SUB->GetSource( qsources[jj] ); sprintf(chktmp, "%+.1e", s->Evaluate(0.0)); mychk.add_string(chktmp); } } for (int jj=0; jj<STAT.N_Nodes(); jj++) { if ( asources[jj] > -1 ) { Source *s = (Source*)SUB->GetSource( asources[jj]); sprintf(chktmp, "%+.1e", s->Evaluate(0.0)); mychk.add_string(chktmp); } } for (int jj=0; jj<STAT.N_Nodes(); jj++) { if ( lsources[jj] > -1 ) { Source *s = (Source*)SUB->GetSource( lsources[jj] ); sprintf(chktmp, "%+.1e", s->Evaluate(0.0)); mychk.add_string(chktmp); } } STAT.SetChkSum( mychk.HexCode() ); back: if (Prime) delete Prime; if (Second) delete Second; return r_code; }
FirstDef search_block(FILE *fp, int *cur_ln, Descriptor *des, int sz, StrBuffer *p, StrBuffer *s, FILE *out) { int state; FirstDef found_key=def_not_found; int rc_end, rc_def; int ln_number=*cur_ln; char tmpbuf[1024]; char *pt; const char def[]="DEF"; const char end[]="END"; /* simple state state = 0; nothing, or get ready to return state = 1; found first def, everything goes into first buffer state = 2; found 2nd def, everthing goes into 2nd buffer */ state = 0; found_key = def_not_found; p->Reset(); s->Reset(); while ( (fgets(tmpbuf, MAX_LINE_LENGTH, fp)) != NULL) { ln_number++; if ( tmpbuf[0]=='#'||tmpbuf[0]=='*'||tmpbuf[0]=='%') continue; /* comments */ pt = strtok(tmpbuf, P_DELIM); while (pt!=NULL) { rc_end = cmp_string(pt, end); rc_def = cmp_string(pt, def); if (rc_end == 1) { /* found "end" */ state--; if ( state < 0 ) { if (out) fprintf(out,"Bummer: redundent END statement on line %d\n", ln_number); return def_error; } else if ( state == 0 ) { if (found_key < def_not_found) { p->Finish(); s->Finish(); *cur_ln = ln_number; return(found_key); } } } else if ( rc_def == 1 ) { /* found "def" */ state++; if ( state == 1 ) p->Ready(ln_number); else if ( state == 2 ) s->Ready(ln_number); else if ( state > 2 ) { if (out) fprintf(out,"Bummer: multiple defined DEF on line %d, did you forget an END statement?\n", ln_number); return def_error; } } else { /* found something else */ if ( state ==1 && found_key==def_not_found ) { found_key = decipher_keyword(pt, des, sz); } if ( found_key < def_not_found ) { if (state==1) p->Copy_add_Space(pt); else if ( state == 2 ) s->Copy_add_Space(pt); } else { // we found something we don't recognize if (out) fprintf(out,"Bummer: Don't know how to deciper DEF \"%s\" on line %d\n", pt, ln_number); return (def_error); } } /* get the next token */ pt=strtok(NULL, P_DELIM); } } // at this point, state should be zero! if ( state != 0 ) { if (out) fprintf(out,"Bummer: unbalanced DEF and END statements\n"); found_key = def_error; } *cur_ln = ln_number; return (found_key); }