/*nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn * PROGRAMMER: Roger W. Ehrich * DATE: October 23, 2001 * * CALL: status = pos_number (string, number) * * PURPOSE: Parse a line containing a non-negative integer or *. If *, return * 32767, and if the string is empty, return 1. The parser uses a * deterministic finite state machine (DFA). * * PARAMETERS: string char *, a string containing the input number * number int *, returns a positive number from the parse * * RETURNS: status int, 0 upon a successful parse or the index of the first * character in error (first position is 1) * * NOTES: State 0: Skipping leading blanks or control characters * State 1: Found a sequence of consecutive numerals * State 2: Found a * * State 3: Skip trailing blanks or control characters * State 4: A trap state that indicates an error has occurred * * class (char) classifies a character into one of 8 categories uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu*/ int pos_number (char *string, int *number) { char next_state[4][8] = // State transition matrix { {0, 0, 4, 2, 4, 4, 1, 4}, {3, 3, 4, 4, 4, 4, 1, 4}, {3, 3, 4, 4, 4, 4, 4, 4}, {3, 3, 4, 4, 4, 4, 4, 4} }; char action[4][8] = // Action matrix { {1, 1, 5, 2, 5, 5, 3, 5}, {1, 1, 5, 5, 5, 5, 4, 5}, {1, 1, 5, 5, 5, 5, 5, 5}, {1, 1, 5, 5, 5, 5, 5, 5} }; char state = 1; // The initial state char act; // The action to be taken char star = 0; // Haven't found a * yet when 0 int status = 0; // Good parse when 0 int nlength = 0; // The number of digits found int sum = 0; // The partial sum of weighted digits int input; // The class of the input character int j, ptr; // Character offsets // Return a 1 on an empty string if (string[0] == '\0') { *number = 1; return status; } // Parse the string using the DFA for (j = 0 ; string[j] != '\0' ; j++) { input = class (string[j]); act = action[state][input]; state = next_state[state][input]; // Decide what action to take, given present state and input character switch (act) { case 1: break; // Act 1 - No action case 2: star = string[j]; // Act 2 - Record a * break; case 3: ptr = j; // Act 3 - Initialize a number nlength = 1; break; case 4: nlength++; // Act 4 - Append a digit break; case 5: status = j + 1; // Act 5 - Return an error *number = 0; return status; } } // Decode the number and check the bounds (maximum = 32767) if (star != 0) *number = 32767; else if (nlength == 0) *number = 1; else { for (j = 0 ; j < nlength ; j++) { sum += sum * 10 + string[ptr+j] - 48; if (sum > 32767) sum = 32767; } *number = sum; } return status; }