+int SB_GetNumber (StrBuf* B, long* Val)
+/* Get a number from the string buffer. Accepted formats are decimal, octal,
+ * hex and character constants. Numeric constants may be preceeded by a
+ * minus or plus sign. The function returns 1 if a number was found and
+ * zero otherwise. Errors are only output for invalid numbers.
+ */
+{
+ int Sign;
+ char C;
+ unsigned Base;
+ unsigned DigitVal;
+
+
+ /* Initialize Val */
+ *Val = 0;
+
+ /* Handle character constants */
+ if (SB_Peek (B) == '\'') {
+
+ /* Character constant */
+ SB_Skip (B);
+ *Val = SignExtendChar (TgtTranslateChar (ParseChar (B)));
+ if (SB_Peek (B) != '\'') {
+ Error ("`\'' expected");
+ return 0;
+ } else {
+ /* Skip the quote */
+ SB_Skip (B);
+ return 1;
+ }
+ }
+
+ /* Check for a sign. A sign must be followed by a digit, otherwise it's
+ * not a number
+ */
+ Sign = 1;
+ switch (SB_Peek (B)) {
+ case '-':
+ Sign = -1;
+ /* FALLTHROUGH */
+ case '+':
+ if (!IsDigit (SB_LookAt (B, SB_GetIndex (B) + 1))) {
+ return 0;
+ }
+ SB_Skip (B);
+ break;
+ }
+
+ /* We must have a digit now, otherwise its not a number */
+ C = SB_Peek (B);
+ if (!IsDigit (C)) {
+ return 0;
+ }
+
+ /* Determine the base */
+ if (C == '0') {
+ /* Hex or octal */
+ SB_Skip (B);
+ if (tolower (SB_Peek (B)) == 'x') {
+ SB_Skip (B);
+ Base = 16;
+ if (!IsXDigit (SB_Peek (B))) {
+ Error ("Invalid hexadecimal number");
+ return 0;
+ }
+ } else {
+ Base = 8;
+ }
+ } else {
+ Base = 10;
+ }
+
+ /* Read the number */
+ while (IsXDigit (C = SB_Peek (B)) && (DigitVal = HexVal (C)) < Base) {
+ *Val = (*Val * Base) + DigitVal;
+ SB_Skip (B);
+ }
+
+ /* Allow optional 'U' and 'L' modifiers */
+ C = SB_Peek (B);
+ if (C == 'u' || C == 'U') {
+ SB_Skip (B);
+ C = SB_Peek (B);
+ if (C == 'l' || C == 'L') {
+ SB_Skip (B);
+ }
+ } else if (C == 'l' || C == 'L') {
+ SB_Skip (B);
+ C = SB_Peek (B);
+ if (C == 'u' || C == 'U') {
+ SB_Skip (B);
+ }
+ }
+
+ /* Success, value read is in Val */
+ *Val *= Sign;
+ return 1;
+}
+
+
+