GCC Code Coverage Report


Directory: src/solver/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 87.5% 386 / 0 / 441
Functions: 93.8% 15 / 0 / 16
Branches: 76.1% 216 / 0 / 284

input.c
Line Branch Exec Source
1 //-----------------------------------------------------------------------------
2 // input.c
3 //
4 // Project: EPA SWMM5
5 // Version: 5.2
6 // Date: 06/01/22 (Build 5.2.1)
7 // Author: L. Rossman
8 //
9 // Input data processing functions.
10 //
11 // Update History
12 // ==============
13 // Build 5.1.007:
14 // - Support added for climate adjustment input data.
15 // Build 5.1.011:
16 // - Support added for reading hydraulic event dates.
17 // Build 5.1.015:
18 // - Support added for multiple infiltration methods within a project.
19 // Build 5.2.0:
20 // - Support added for Streets and Inlets.
21 // - Support added for named variables & math expressions in control rules.
22 // Build 5.2.1:
23 // - Possible integer underflow avoided in getTokens() function.
24 //-----------------------------------------------------------------------------
25 #define _CRT_SECURE_NO_DEPRECATE
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <math.h>
30 #include "headers.h"
31 #include "lid.h"
32
33 //-----------------------------------------------------------------------------
34 // Constants
35 //-----------------------------------------------------------------------------
36 static const int MAXERRS = 100; // Max. input errors reported
37
38 //-----------------------------------------------------------------------------
39 // Shared variables
40 //-----------------------------------------------------------------------------
41 static char *Tok[MAXTOKS]; // String tokens from line of input
42 static int Ntokens; // Number of tokens in line of input
43 static int Mobjects[MAX_OBJ_TYPES]; // Working number of objects of each type
44 static int Mnodes[MAX_NODE_TYPES]; // Working number of node objects
45 static int Mlinks[MAX_LINK_TYPES]; // Working number of link objects
46 static int Mevents; // Working number of event periods
47
48 //-----------------------------------------------------------------------------
49 // External Functions (declared in funcs.h)
50 //-----------------------------------------------------------------------------
51 // input_countObjects (called by swmm_open in swmm5.c)
52 // input_readData (called by swmm_open in swmm5.c)
53
54 //-----------------------------------------------------------------------------
55 // Local functions
56 //-----------------------------------------------------------------------------
57 static int addObject(int objType, char* id);
58 static int getTokens(char *s);
59 static int parseLine(int sect, char* line);
60 static int readOption(char* line);
61 static int readTitle(char* line);
62 static int readControl(char* tok[], int ntoks);
63 static int readNode(int type);
64 static int readLink(int type);
65 static int readEvent(char* tok[], int ntoks);
66
67 //=============================================================================
68
69 61 int input_countObjects()
70 //
71 // Input: none
72 // Output: returns error code
73 // Purpose: reads input file to determine number of system objects.
74 //
75 {
76 char line[MAXLINE+1]; // line from input data file
77 char wLine[MAXLINE+1]; // working copy of input line
78 char *tok; // first string token of line
79 61 int sect = -1, newsect; // input data sections
80 61 int errcode = 0; // error code
81 61 int errsum = 0; // number of errors found
82 int i;
83 61 long lineCount = 0;
84
85 // --- initialize number of objects & set default values
86
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if ( ErrorCode ) return ErrorCode;
87 61 error_setInpError(0, "");
88
2/2
✓ Branch 0 taken 1098 times.
✓ Branch 1 taken 61 times.
1159 for (i = 0; i < MAX_OBJ_TYPES; i++) Nobjects[i] = 0;
89
2/2
✓ Branch 0 taken 305 times.
✓ Branch 1 taken 61 times.
366 for (i = 0; i < MAX_NODE_TYPES; i++) Nnodes[i] = 0;
90
2/2
✓ Branch 0 taken 305 times.
✓ Branch 1 taken 61 times.
366 for (i = 0; i < MAX_LINK_TYPES; i++) Nlinks[i] = 0;
91 61 controls_init();
92
93 // --- make pass through data file counting number of each object
94
2/2
✓ Branch 1 taken 17838 times.
✓ Branch 2 taken 61 times.
17899 while ( fgets(line, MAXLINE, Finp.file) != NULL )
95 {
96 // --- skip blank lines & those beginning with a comment
97 17838 lineCount++;
98 17838 sstrncpy(wLine, line, MAXLINE); // make working copy of line
99 17838 tok = strtok(wLine, SEPSTR); // get first text token on line
100
2/2
✓ Branch 0 taken 1364 times.
✓ Branch 1 taken 16474 times.
17838 if ( tok == NULL ) continue;
101
2/2
✓ Branch 0 taken 1125 times.
✓ Branch 1 taken 15349 times.
16474 if ( *tok == ';' ) continue;
102
103 // --- check if line begins with a new section heading
104
2/2
✓ Branch 0 taken 1194 times.
✓ Branch 1 taken 14155 times.
15349 if ( *tok == '[' )
105 {
106 // --- look for heading in list of section keywords
107 1194 newsect = findmatch(tok, SectWords);
108
1/2
✓ Branch 0 taken 1194 times.
✗ Branch 1 not taken.
1194 if ( newsect >= 0 )
109 {
110 1194 sect = newsect;
111 1194 continue;
112 }
113 else
114 {
115 sect = -1;
116 errcode = ERR_KEYWORD;
117 }
118 }
119
120 // --- if in OPTIONS section then read the option setting
121 // otherwise add object and its ID name (tok) to project
122
2/2
✓ Branch 0 taken 1537 times.
✓ Branch 1 taken 12618 times.
14155 if ( sect == s_OPTION ) errcode = readOption(line);
123
1/2
✓ Branch 0 taken 12618 times.
✗ Branch 1 not taken.
12618 else if ( sect >= 0 ) errcode = addObject(sect, tok);
124
125 // --- report any error found
126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14155 times.
14155 if ( errcode )
127 {
128 report_writeInputErrorMsg(errcode, sect, line, lineCount);
129 errsum++;
130 if (errsum >= MAXERRS ) break;
131 }
132 }
133
134 // --- set global error code if input errors were found
135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if ( errsum > 0 ) ErrorCode = ERR_INPUT;
136 61 return ErrorCode;
137 }
138
139 //=============================================================================
140
141 61 int input_readData()
142 //
143 // Input: none
144 // Output: returns error code
145 // Purpose: reads input file to determine input parameters for each object.
146 //
147 {
148 char line[MAXLINE+1]; // line from input data file
149 char wLine[MAXLINE+1]; // working copy of input line
150 char* comment; // ptr. to start of comment in input line
151 int sect, newsect; // data sections
152 int inperr, errsum; // error code & total error count
153 int lineLength; // number of characters in input line
154 int i;
155 61 long lineCount = 0;
156
157 // --- initialize working item count arrays
158 // (final counts in Mobjects, Mnodes & Mlinks should
159 // match those in Nobjects, Nnodes and Nlinks).
160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if ( ErrorCode ) return ErrorCode;
161 61 error_setInpError(0, "");
162
2/2
✓ Branch 0 taken 1098 times.
✓ Branch 1 taken 61 times.
1159 for (i = 0; i < MAX_OBJ_TYPES; i++) Mobjects[i] = 0;
163
2/2
✓ Branch 0 taken 305 times.
✓ Branch 1 taken 61 times.
366 for (i = 0; i < MAX_NODE_TYPES; i++) Mnodes[i] = 0;
164
2/2
✓ Branch 0 taken 305 times.
✓ Branch 1 taken 61 times.
366 for (i = 0; i < MAX_LINK_TYPES; i++) Mlinks[i] = 0;
165 61 Mevents = 0;
166
167 // --- initialize starting date for all time series
168
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 61 times.
193 for ( i = 0; i < Nobjects[TSERIES]; i++ )
169 {
170 132 Tseries[i].lastDate = StartDate + StartTime;
171 }
172
173 // --- read each line from input file
174 61 sect = 0;
175 61 errsum = 0;
176 61 rewind(Finp.file);
177
2/2
✓ Branch 1 taken 17838 times.
✓ Branch 2 taken 61 times.
17899 while ( fgets(line, MAXLINE, Finp.file) != NULL )
178 {
179 // --- make copy of line and scan for tokens
180 17838 lineCount++;
181 17838 sstrncpy(wLine, line, MAXLINE);
182 17838 Ntokens = getTokens(wLine);
183
184 // --- skip blank lines and comments
185
2/2
✓ Branch 0 taken 2489 times.
✓ Branch 1 taken 15349 times.
17838 if ( Ntokens == 0 ) continue;
186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15349 times.
15349 if ( *Tok[0] == ';' ) continue;
187
188 // --- check if max. line length exceeded
189 15349 lineLength = (int)strlen(line);
190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15349 times.
15349 if ( lineLength >= MAXLINE )
191 {
192 // --- don't count comment if present
193 comment = strchr(line, ';');
194 if ( comment ) lineLength = (int)(comment - line); // Pointer math here
195 if ( lineLength >= MAXLINE )
196 {
197 inperr = ERR_LINE_LENGTH;
198 report_writeInputErrorMsg(inperr, sect, line, lineCount);
199 errsum++;
200 }
201 }
202
203 // --- check if at start of a new input section
204
2/2
✓ Branch 0 taken 1194 times.
✓ Branch 1 taken 14155 times.
15349 if (*Tok[0] == '[')
205 {
206 // --- match token against list of section keywords
207 1194 newsect = findmatch(Tok[0], SectWords);
208
1/2
✓ Branch 0 taken 1194 times.
✗ Branch 1 not taken.
1194 if (newsect >= 0)
209 {
210 // --- SPECIAL CASE FOR TRANSECTS
211 // finish processing the last set of transect data
212
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1184 times.
1194 if ( sect == s_TRANSECT )
213 10 transect_validate(Nobjects[TRANSECT]-1);
214
215 // --- begin a new input section
216 1194 sect = newsect;
217 1194 continue;
218 }
219 else
220 {
221 inperr = error_setInpError(ERR_KEYWORD, Tok[0]);
222 report_writeInputErrorMsg(inperr, sect, line, lineCount);
223 errsum++;
224 break;
225 }
226 }
227
228 // --- otherwise parse tokens from input line
229 else
230 {
231 14155 inperr = parseLine(sect, line);
232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14155 times.
14155 if ( inperr > 0 )
233 {
234 errsum++;
235 if ( errsum > MAXERRS ) report_writeLine(FMT19);
236 else report_writeInputErrorMsg(inperr, sect, line, lineCount);
237 }
238 }
239
240 // --- stop if reach end of file or max. error count
241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14155 times.
14155 if (errsum > MAXERRS) break;
242 } /* End of while */
243
244 // --- check for errors
245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if (errsum > 0) ErrorCode = ERR_INPUT;
246 61 return ErrorCode;
247 }
248
249 //=============================================================================
250
251 12618 int addObject(int objType, char* id)
252 //
253 // Input: objType = object type index
254 // id = object's ID string
255 // Output: returns an error code
256 // Purpose: adds a new object to the project.
257 //
258 {
259 12618 int errcode = 0;
260
26/26
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 96 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 60 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 267 times.
✓ Branch 6 taken 112 times.
✓ Branch 7 taken 40 times.
✓ Branch 8 taken 4 times.
✓ Branch 9 taken 299 times.
✓ Branch 10 taken 9 times.
✓ Branch 11 taken 10 times.
✓ Branch 12 taken 8 times.
✓ Branch 13 taken 6 times.
✓ Branch 14 taken 25 times.
✓ Branch 15 taken 12 times.
✓ Branch 16 taken 58 times.
✓ Branch 17 taken 676 times.
✓ Branch 18 taken 7237 times.
✓ Branch 19 taken 171 times.
✓ Branch 20 taken 99 times.
✓ Branch 21 taken 100 times.
✓ Branch 22 taken 6 times.
✓ Branch 23 taken 3 times.
✓ Branch 24 taken 8 times.
✓ Branch 25 taken 3256 times.
12618 switch( objType )
261 {
262 40 case s_RAINGAGE:
263
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
40 if ( !project_addObject(GAGE, id, Nobjects[GAGE]) )
264 errcode = error_setInpError(ERR_DUP_NAME, id);
265 40 Nobjects[GAGE]++;
266 40 break;
267
268 96 case s_SUBCATCH:
269
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 96 times.
96 if ( !project_addObject(SUBCATCH, id, Nobjects[SUBCATCH]) )
270 errcode = error_setInpError(ERR_DUP_NAME, id);
271 96 Nobjects[SUBCATCH]++;
272 96 break;
273
274 4 case s_AQUIFER:
275
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ( !project_addObject(AQUIFER, id, Nobjects[AQUIFER]) )
276 errcode = error_setInpError(ERR_DUP_NAME, id);
277 4 Nobjects[AQUIFER]++;
278 4 break;
279
280 60 case s_UNITHYD:
281 // --- the same Unit Hydrograph can span several lines
282
2/2
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 45 times.
60 if ( project_findObject(UNITHYD, id) < 0 )
283 {
284
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
15 if ( !project_addObject(UNITHYD, id, Nobjects[UNITHYD]) )
285 errcode = error_setInpError(ERR_DUP_NAME, id);
286 15 Nobjects[UNITHYD]++;
287 }
288 60 break;
289
290 12 case s_SNOWMELT:
291 // --- the same Snowmelt object can appear on several lines
292
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 9 times.
12 if ( project_findObject(SNOWMELT, id) < 0 )
293 {
294
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ( !project_addObject(SNOWMELT, id, Nobjects[SNOWMELT]) )
295 errcode = error_setInpError(ERR_DUP_NAME, id);
296 3 Nobjects[SNOWMELT]++;
297 }
298 12 break;
299
300 267 case s_JUNCTION:
301
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 267 times.
267 if ( !project_addObject(NODE, id, Nobjects[NODE]) )
302 errcode = error_setInpError(ERR_DUP_NAME, id);
303 267 Nobjects[NODE]++;
304 267 Nnodes[JUNCTION]++;
305 267 break;
306
307 112 case s_OUTFALL:
308
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 112 times.
112 if ( !project_addObject(NODE, id, Nobjects[NODE]) )
309 errcode = error_setInpError(ERR_DUP_NAME, id);
310 112 Nobjects[NODE]++;
311 112 Nnodes[OUTFALL]++;
312 112 break;
313
314 40 case s_STORAGE:
315
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
40 if ( !project_addObject(NODE, id, Nobjects[NODE]) )
316 errcode = error_setInpError(ERR_DUP_NAME, id);
317 40 Nobjects[NODE]++;
318 40 Nnodes[STORAGE]++;
319 40 break;
320
321 4 case s_DIVIDER:
322
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ( !project_addObject(NODE, id, Nobjects[NODE]) )
323 errcode = error_setInpError(ERR_DUP_NAME, id);
324 4 Nobjects[NODE]++;
325 4 Nnodes[DIVIDER]++;
326 4 break;
327
328 299 case s_CONDUIT:
329
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 299 times.
299 if ( !project_addObject(LINK, id, Nobjects[LINK]) )
330 errcode = error_setInpError(ERR_DUP_NAME, id);
331 299 Nobjects[LINK]++;
332 299 Nlinks[CONDUIT]++;
333 299 break;
334
335 9 case s_PUMP:
336
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
9 if ( !project_addObject(LINK, id, Nobjects[LINK]) )
337 errcode = error_setInpError(ERR_DUP_NAME, id);
338 9 Nobjects[LINK]++;
339 9 Nlinks[PUMP]++;
340 9 break;
341
342 10 case s_ORIFICE:
343
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if ( !project_addObject(LINK, id, Nobjects[LINK]) )
344 errcode = error_setInpError(ERR_DUP_NAME, id);
345 10 Nobjects[LINK]++;
346 10 Nlinks[ORIFICE]++;
347 10 break;
348
349 8 case s_WEIR:
350
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if ( !project_addObject(LINK, id, Nobjects[LINK]) )
351 errcode = error_setInpError(ERR_DUP_NAME, id);
352 8 Nobjects[LINK]++;
353 8 Nlinks[WEIR]++;
354 8 break;
355
356 6 case s_OUTLET:
357
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if ( !project_addObject(LINK, id, Nobjects[LINK]) )
358 errcode = error_setInpError(ERR_DUP_NAME, id);
359 6 Nobjects[LINK]++;
360 6 Nlinks[OUTLET]++;
361 6 break;
362
363 25 case s_POLLUTANT:
364
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
25 if ( !project_addObject(POLLUT, id, Nobjects[POLLUT]) )
365 errcode = error_setInpError(ERR_DUP_NAME, id);
366 25 Nobjects[POLLUT]++;
367 25 break;
368
369 12 case s_LANDUSE:
370
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
12 if ( !project_addObject(LANDUSE, id, Nobjects[LANDUSE]) )
371 errcode = error_setInpError(ERR_DUP_NAME, id);
372 12 Nobjects[LANDUSE]++;
373 12 break;
374
375 58 case s_PATTERN:
376 // --- a time pattern can span several lines
377
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 40 times.
58 if ( project_findObject(TIMEPATTERN, id) < 0 )
378 {
379
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
18 if ( !project_addObject(TIMEPATTERN, id, Nobjects[TIMEPATTERN]) )
380 errcode = error_setInpError(ERR_DUP_NAME, id);
381 18 Nobjects[TIMEPATTERN]++;
382 }
383 58 break;
384
385 676 case s_CURVE:
386 // --- a Curve can span several lines
387
2/2
✓ Branch 1 taken 63 times.
✓ Branch 2 taken 613 times.
676 if ( project_findObject(CURVE, id) < 0 )
388 {
389
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
63 if ( !project_addObject(CURVE, id, Nobjects[CURVE]) )
390 errcode = error_setInpError(ERR_DUP_NAME, id);
391 63 Nobjects[CURVE]++;
392
393 // --- check for a conduit shape curve
394 63 id = strtok(NULL, SEPSTR);
395
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 59 times.
63 if ( findmatch(id, CurveTypeWords) == SHAPE_CURVE )
396 4 Nobjects[SHAPE]++;
397 }
398 676 break;
399
400 7237 case s_TIMESERIES:
401 // --- a Time Series can span several lines
402
2/2
✓ Branch 1 taken 132 times.
✓ Branch 2 taken 7105 times.
7237 if ( project_findObject(TSERIES, id) < 0 )
403 {
404
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 132 times.
132 if ( !project_addObject(TSERIES, id, Nobjects[TSERIES]) )
405 errcode = error_setInpError(ERR_DUP_NAME, id);
406 132 Nobjects[TSERIES]++;
407 }
408 7237 break;
409
410 171 case s_CONTROL:
411
2/2
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 133 times.
171 if ( match(id, w_RULE) ) Nobjects[CONTROL]++;
412 133 else controls_addToCount(id);
413 171 break;
414
415 99 case s_TRANSECT:
416 // --- for TRANSECTS, ID name appears as second entry on X1 line
417
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 87 times.
99 if ( match(id, "X1") )
418 {
419 12 id = strtok(NULL, SEPSTR);
420
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if ( id )
421 {
422
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
12 if ( !project_addObject(TRANSECT, id, Nobjects[TRANSECT]) )
423 errcode = error_setInpError(ERR_DUP_NAME, id);
424 12 Nobjects[TRANSECT]++;
425 }
426 }
427 99 break;
428
429 100 case s_LID_CONTROL:
430 // --- an LID object can span several lines
431
2/2
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 73 times.
100 if ( project_findObject(LID, id) < 0 )
432 {
433
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
27 if ( !project_addObject(LID, id, Nobjects[LID]) )
434 {
435 errcode = error_setInpError(ERR_DUP_NAME, id);
436 }
437 27 Nobjects[LID]++;
438 }
439 100 break;
440
441 6 case s_EVENT: NumEvents++; break;
442
443 3 case s_STREET:
444
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if ( !project_addObject(STREET, id, Nobjects[STREET]) )
445 errcode = error_setInpError(ERR_DUP_NAME, id);
446 3 Nobjects[STREET]++;
447 3 break;
448
449 8 case s_INLET:
450 // --- an INLET object can span several lines
451
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 1 time.
8 if (project_findObject(INLET, id) < 0)
452 {
453
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if ( !project_addObject(INLET, id, Nobjects[INLET]) )
454 errcode = error_setInpError(ERR_DUP_NAME, id);
455 7 Nobjects[INLET]++;
456 }
457 8 break;
458 }
459 12618 return errcode;
460 }
461
462 //=============================================================================
463
464 14155 int parseLine(int sect, char *line)
465 //
466 // Input: sect = current section of input file
467 // *line = line of text read from input file
468 // Output: returns error code or 0 if no error found
469 // Purpose: parses contents of a tokenized line of text read from input file.
470 //
471 {
472 int j, err;
473
47/48
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 40 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 90 times.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 96 times.
✓ Branch 6 taken 96 times.
✓ Branch 7 taken 92 times.
✓ Branch 8 taken 4 times.
✓ Branch 9 taken 10 times.
✓ Branch 10 taken 8 times.
✓ Branch 11 taken 12 times.
✓ Branch 12 taken 267 times.
✓ Branch 13 taken 112 times.
✓ Branch 14 taken 40 times.
✓ Branch 15 taken 4 times.
✓ Branch 16 taken 299 times.
✓ Branch 17 taken 9 times.
✓ Branch 18 taken 10 times.
✓ Branch 19 taken 8 times.
✓ Branch 20 taken 6 times.
✓ Branch 21 taken 317 times.
✓ Branch 22 taken 99 times.
✓ Branch 23 taken 131 times.
✓ Branch 24 taken 25 times.
✓ Branch 25 taken 12 times.
✓ Branch 26 taken 37 times.
✓ Branch 27 taken 37 times.
✓ Branch 28 taken 36 times.
✓ Branch 29 taken 94 times.
✓ Branch 30 taken 10 times.
✓ Branch 31 taken 58 times.
✓ Branch 32 taken 3 times.
✓ Branch 33 taken 60 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 15 times.
✓ Branch 36 taken 676 times.
✓ Branch 37 taken 7237 times.
✓ Branch 38 taken 171 times.
✓ Branch 39 taken 333 times.
✓ Branch 40 taken 13 times.
✓ Branch 41 taken 100 times.
✓ Branch 42 taken 30 times.
✓ Branch 43 taken 6 times.
✓ Branch 44 taken 3 times.
✓ Branch 45 taken 8 times.
✓ Branch 46 taken 14 times.
✓ Branch 47 taken 3260 times.
14155 switch (sect)
474 {
475 141 case s_TITLE:
476 141 return readTitle(line);
477
478 40 case s_RAINGAGE:
479 40 j = Mobjects[GAGE];
480 40 err = gage_readParams(j, Tok, Ntokens);
481 40 Mobjects[GAGE]++;
482 40 return err;
483
484 18 case s_TEMP:
485 18 return climate_readParams(Tok, Ntokens);
486
487 90 case s_EVAP:
488 90 return climate_readEvapParams(Tok, Ntokens);
489
490 8 case s_ADJUST:
491 8 return climate_readAdjustments(Tok, Ntokens);
492
493 96 case s_SUBCATCH:
494 96 j = Mobjects[SUBCATCH];
495 96 err = subcatch_readParams(j, Tok, Ntokens);
496 96 Mobjects[SUBCATCH]++;
497 96 return err;
498
499 96 case s_SUBAREA:
500 96 return subcatch_readSubareaParams(Tok, Ntokens);
501
502 92 case s_INFIL:
503 92 return infil_readParams(InfilModel, Tok, Ntokens);
504
505 4 case s_AQUIFER:
506 4 j = Mobjects[AQUIFER];
507 4 err = gwater_readAquiferParams(j, Tok, Ntokens);
508 4 Mobjects[AQUIFER]++;
509 4 return err;
510
511 10 case s_GROUNDWATER:
512 10 return gwater_readGroundwaterParams(Tok, Ntokens);
513
514 8 case s_GWF:
515 8 return gwater_readFlowExpression(Tok, Ntokens);
516
517 12 case s_SNOWMELT:
518 12 return snow_readMeltParams(Tok, Ntokens);
519
520 267 case s_JUNCTION:
521 267 return readNode(JUNCTION);
522
523 112 case s_OUTFALL:
524 112 return readNode(OUTFALL);
525
526 40 case s_STORAGE:
527 40 return readNode(STORAGE);
528
529 4 case s_DIVIDER:
530 4 return readNode(DIVIDER);
531
532 299 case s_CONDUIT:
533 299 return readLink(CONDUIT);
534
535 9 case s_PUMP:
536 9 return readLink(PUMP);
537
538 10 case s_ORIFICE:
539 10 return readLink(ORIFICE);
540
541 8 case s_WEIR:
542 8 return readLink(WEIR);
543
544 6 case s_OUTLET:
545 6 return readLink(OUTLET);
546
547 317 case s_XSECTION:
548 317 return link_readXsectParams(Tok, Ntokens);
549
550 99 case s_TRANSECT:
551 99 return transect_readParams(&Mobjects[TRANSECT], Tok, Ntokens);
552
553 131 case s_LOSSES:
554 131 return link_readLossParams(Tok, Ntokens);
555
556 25 case s_POLLUTANT:
557 25 j = Mobjects[POLLUT];
558 25 err = landuse_readPollutParams(j, Tok, Ntokens);
559 25 Mobjects[POLLUT]++;
560 25 return err;
561
562 12 case s_LANDUSE:
563 12 j = Mobjects[LANDUSE];
564 12 err = landuse_readParams(j, Tok, Ntokens);
565 12 Mobjects[LANDUSE]++;
566 12 return err;
567
568 37 case s_BUILDUP:
569 37 return landuse_readBuildupParams(Tok, Ntokens);
570
571 37 case s_WASHOFF:
572 37 return landuse_readWashoffParams(Tok, Ntokens);
573
574 36 case s_COVERAGE:
575 36 return subcatch_readLanduseParams(Tok, Ntokens);
576
577 94 case s_INFLOW:
578 94 return inflow_readExtInflow(Tok, Ntokens);
579
580 10 case s_DWF:
581 10 return inflow_readDwfInflow(Tok, Ntokens);
582
583 58 case s_PATTERN:
584 58 return inflow_readDwfPattern(Tok, Ntokens);
585
586 3 case s_RDII:
587 3 return rdii_readRdiiInflow(Tok, Ntokens);
588
589 60 case s_UNITHYD:
590 60 return rdii_readUnitHydParams(Tok, Ntokens);
591
592 case s_LOADING:
593 return subcatch_readInitBuildup(Tok, Ntokens);
594
595 15 case s_TREATMENT:
596 15 return treatmnt_readExpression(Tok, Ntokens);
597
598 676 case s_CURVE:
599 676 return table_readCurve(Tok, Ntokens);
600
601 7237 case s_TIMESERIES:
602 7237 return table_readTimeseries(Tok, Ntokens);
603
604 171 case s_CONTROL:
605 171 return readControl(Tok, Ntokens);
606
607 333 case s_REPORT:
608 333 return report_readOptions(Tok, Ntokens);
609
610 13 case s_FILE:
611 13 return iface_readFileParams(Tok, Ntokens);
612
613 100 case s_LID_CONTROL:
614 100 return lid_readProcParams(Tok, Ntokens);
615
616 30 case s_LID_USAGE:
617 30 return lid_readGroupParams(Tok, Ntokens);
618
619 6 case s_EVENT:
620 6 return readEvent(Tok, Ntokens);
621
622 3 case s_STREET:
623 3 return street_readParams(Tok, Ntokens);
624
625 8 case s_INLET:
626 8 return inlet_readDesignParams(Tok, Ntokens);
627
628 14 case s_INLET_USAGE:
629 14 return inlet_readUsageParams(Tok, Ntokens);
630
631 3260 default: return 0;
632 }
633 }
634
635 //=============================================================================
636
637 171 int readControl(char* tok[], int ntoks)
638 //
639 // Input: tok[] = array of string tokens
640 // ntoks = number of tokens
641 // Output: returns error code
642 // Purpose: reads a line of input for a control rule.
643 //
644 {
645 int index;
646 int keyword;
647
648 // --- check for minimum number of tokens
649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 171 times.
171 if ( ntoks < 2 ) return error_setInpError(ERR_ITEMS, "");
650
651
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 168 times.
171 if (match(tok[0], w_VARIABLE))
652 3 return controls_addVariable(tok, ntoks);
653
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 162 times.
168 if (match(tok[0], w_EXPRESSION))
654 6 return controls_addExpression(tok, ntoks);
655
656 // --- get index of control rule keyword
657 162 keyword = findmatch(tok[0], RuleKeyWords);
658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162 times.
162 if ( keyword < 0 ) return error_setInpError(ERR_KEYWORD, tok[0]);
659
660 // --- if line begins a new control rule, add rule ID to the database
661
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 124 times.
162 if ( keyword == 0 )
662 {
663
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
38 if ( !project_addObject(CONTROL, tok[1], Mobjects[CONTROL]) )
664 {
665 return error_setInpError(ERR_DUP_NAME, Tok[1]);
666 }
667 38 Mobjects[CONTROL]++;
668 }
669
670 // --- get index of last control rule processed
671 162 index = Mobjects[CONTROL] - 1;
672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162 times.
162 if ( index < 0 ) return error_setInpError(ERR_RULE, "");
673
674 // --- add current line as a new clause to the control rule
675 162 return controls_addRuleClause(index, keyword, Tok, Ntokens);
676 }
677
678 //=============================================================================
679
680 1537 int readOption(char* line)
681 //
682 // Input: line = line of input data
683 // Output: returns error code
684 // Purpose: reads an input line containing a project option.
685 //
686 {
687 1537 Ntokens = getTokens(line);
688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1537 times.
1537 if ( Ntokens < 2 ) return 0;
689 1537 return project_readOption(Tok[0], Tok[1]);
690 }
691
692 //=============================================================================
693
694 141 int readTitle(char* line)
695 //
696 // Input: line = line from input file
697 // Output: returns error code
698 // Purpose: reads project title from line of input.
699 //
700 {
701 int i, n;
702
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 2 times.
243 for (i = 0; i < MAXTITLE; i++)
703 {
704 // --- find next empty Title entry
705
2/2
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 102 times.
241 if ( strlen(Title[i]) == 0 )
706 {
707 // --- strip line feed character from input line
708 139 n = (int)strlen(line);
709
1/2
✓ Branch 0 taken 139 times.
✗ Branch 1 not taken.
139 if (line[n-1] == 10) line[n-1] = ' ';
710
711 // --- copy input line into Title entry
712 139 sstrncpy(Title[i], line, MAXMSG);
713 139 break;
714 }
715 }
716 141 return 0;
717 }
718
719 //=============================================================================
720
721 423 int readNode(int type)
722 //
723 // Input: type = type of node
724 // Output: returns error code
725 // Purpose: reads data for a node from a line of input.
726 //
727 {
728 423 int j = Mobjects[NODE];
729 423 int k = Mnodes[type];
730 423 int err = node_readParams(j, type, k, Tok, Ntokens);
731 423 Mobjects[NODE]++;
732 423 Mnodes[type]++;
733 423 return err;
734 }
735
736 //=============================================================================
737
738 332 int readLink(int type)
739 //
740 // Input: type = type of link
741 // Output: returns error code
742 // Purpose: reads data for a link from a line of input.
743 //
744 {
745 332 int j = Mobjects[LINK];
746 332 int k = Mlinks[type];
747 332 int err = link_readParams(j, type, k, Tok, Ntokens);
748 332 Mobjects[LINK]++;
749 332 Mlinks[type]++;
750 332 return err;
751 }
752
753 //=============================================================================
754
755 6 int readEvent(char* tok[], int ntoks)
756 {
757 DateTime x[4];
758
759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if ( ntoks < 4 ) return error_setInpError(ERR_ITEMS, "");
760
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if ( !datetime_strToDate(tok[0], &x[0]) )
761 return error_setInpError(ERR_DATETIME, tok[0]);
762
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if ( !datetime_strToTime(tok[1], &x[1]) )
763 return error_setInpError(ERR_DATETIME, tok[1]);
764
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if ( !datetime_strToDate(tok[2], &x[2]) )
765 return error_setInpError(ERR_DATETIME, tok[2]);
766
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if ( !datetime_strToTime(tok[3], &x[3]) )
767 return error_setInpError(ERR_DATETIME, tok[3]);
768
769 6 Event[Mevents].start = x[0] + x[1];
770 6 Event[Mevents].end = x[2] + x[3];
771
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if ( Event[Mevents].start >= Event[Mevents].end )
772 return error_setInpError(ERR_DATETIME, " - start date exceeds end date");
773 6 Mevents++;
774 6 return 0;
775 }
776
777 //=============================================================================
778
779 7187 int findmatch(char *s, char *keyword[])
780 //
781 // Input: s = character string
782 // keyword = array of keyword strings
783 // Output: returns index of matching keyword or -1 if no match found
784 // Purpose: finds match between string and array of keyword strings.
785 //
786 {
787 7187 int i = 0;
788
2/2
✓ Branch 0 taken 91413 times.
✓ Branch 1 taken 216 times.
91629 while (keyword[i] != NULL)
789 {
790
2/2
✓ Branch 1 taken 6971 times.
✓ Branch 2 taken 84442 times.
91413 if (match(s, keyword[i])) return(i);
791 84442 i++;
792 }
793 216 return(-1);
794 }
795
796 //=============================================================================
797
798 92556 int match(char *str, char *substr)
799 //
800 // Input: str = character string being searched
801 // substr = sub-string being searched for
802 // Output: returns 1 if sub-string found, 0 if not
803 // Purpose: sees if a sub-string of characters appears in a string
804 // (not case sensitive).
805 //
806 {
807 int i,j,k;
808
809 // --- fail if substring is empty
810
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 92552 times.
92556 if (!substr[0]) return(0);
811
812 // --- skip leading blanks of str
813
1/2
✓ Branch 0 taken 92552 times.
✗ Branch 1 not taken.
92552 for (k = 0; str[k]; k++)
814 {
815
1/2
✓ Branch 0 taken 92552 times.
✗ Branch 1 not taken.
92552 if (str[k] != ' ') break;
816 }
817
818 // --- check if substr matches remainder of str
819
2/2
✓ Branch 0 taken 200819 times.
✓ Branch 1 taken 7241 times.
208060 for (i = k,j = 0; substr[j]; i++,j++)
820 {
821
8/12
✓ Branch 0 taken 200795 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 669 times.
✓ Branch 3 taken 200126 times.
✓ Branch 4 taken 669 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 200795 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 85287 times.
✓ Branch 11 taken 115508 times.
200819 if (!str[i] || UCHAR(str[i]) != UCHAR(substr[j])) return(0);
822 }
823 7241 return(1);
824 }
825
826 //=============================================================================
827
828 17 int getInt(char *s, int *y)
829 //
830 // Input: s = a character string
831 // Output: y = converted value of s,
832 // returns 1 if conversion successful, 0 if not
833 // Purpose: converts a string to an integer number.
834 //
835 {
836 double x;
837
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 if ( getDouble(s, &x) )
838 {
839
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if ( x < 0.0 ) x -= 0.01;
840 17 else x += 0.01;
841 17 *y = (int)x;
842 17 return 1;
843 }
844 *y = 0;
845 return 0;
846 }
847
848 //=============================================================================
849
850 int getFloat(char *s, float *y)
851 //
852 // Input: s = a character string
853 // Output: y = converted value of s,
854 // returns 1 if conversion successful, 0 if not
855 // Purpose: converts a string to a single precision floating point number.
856 //
857 {
858 char *endptr;
859 *y = (float) strtod(s, &endptr);
860 if (*endptr > 0) return(0);
861 return(1);
862 }
863
864 //=============================================================================
865
866 26168 int getDouble(char *s, double *y)
867 //
868 // Input: s = a character string
869 // Output: y = converted value of s,
870 // returns 1 if conversion successful, 0 if not
871 // Purpose: converts a string to a double precision floating point number.
872 //
873 {
874 char *endptr;
875 26168 *y = strtod(s, &endptr);
876
2/2
✓ Branch 0 taken 7039 times.
✓ Branch 1 taken 19129 times.
26168 if (*endptr > 0) return(0);
877 19129 return(1);
878 }
879
880 //=============================================================================
881
882 19375 int getTokens(char *s)
883 //
884 // Input: s = a character string
885 // Output: returns number of tokens found in s
886 // Purpose: scans a string for tokens, saving pointers to them
887 // in shared variable Tok[].
888 //
889 // Notes: Tokens can be separated by the characters listed in SEPSTR
890 // (spaces, tabs, newline, carriage return) which is defined
891 // in CONSTS.H. Text between quotes is treated as a single token.
892 //
893 {
894 int len, n;
895 int m;
896 char *c;
897
898 // --- begin with no tokens
899
2/2
✓ Branch 0 taken 775000 times.
✓ Branch 1 taken 19375 times.
794375 for (n = 0; n < MAXTOKS; n++) Tok[n] = NULL;
900 19375 n = 0;
901
902 // --- truncate s at start of comment
903 19375 c = strchr(s,';');
904
2/2
✓ Branch 0 taken 1125 times.
✓ Branch 1 taken 18250 times.
19375 if (c) *c = '\0';
905 19375 len = (int)strlen(s);
906
907 // --- scan s for tokens until nothing left
908
3/4
✓ Branch 0 taken 311050 times.
✓ Branch 1 taken 19375 times.
✓ Branch 2 taken 311050 times.
✗ Branch 3 not taken.
330425 while (len > 0 && n < MAXTOKS)
909 {
910 311050 m = (int)strcspn(s,SEPSTR); // find token length
911
2/2
✓ Branch 0 taken 250822 times.
✓ Branch 1 taken 60228 times.
311050 if (m == 0) s++; // no token found
912 else
913 {
914
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 60135 times.
60228 if (*s == '"') // token begins with quote
915 {
916 93 s++; // start token after quote
917 93 len--; // reduce length of s
918 93 m = (int)strcspn(s,"\"\n"); // find end quote or new line
919 }
920 60228 s[m] = '\0'; // null-terminate the token
921 60228 Tok[n] = s; // save pointer to token
922 60228 n++; // update token count
923 60228 s += m+1; // begin next token
924 }
925 311050 len -= m+1; // update length of s
926 }
927 19375 return n;
928 }
929
930 //=============================================================================
931