+static int GetComma (StrBuf* B)
+/* Expects and skips a comma in B. Prints an error and returns zero if no
+** comma is found. Return a value <> 0 otherwise.
+*/
+{
+ SB_SkipWhite (B);
+ if (SB_Get (B) != ',') {
+ Error ("Comma expected");
+ return 0;
+ }
+ SB_SkipWhite (B);
+ return 1;
+}
+
+
+
+static int GetString (StrBuf* B, StrBuf* S)
+/* Expects and skips a string in B. Prints an error and returns zero if no
+** string is found. Returns a value <> 0 otherwise.
+*/
+{
+ if (!SB_GetString (B, S)) {
+ Error ("String literal expected");
+ return 0;
+ }
+ return 1;
+}
+
+
+
+static int GetNumber (StrBuf* B, long* Val)
+/* Expects and skips a number in B. Prints an eror and returns zero if no
+** number is found. Returns a value <> 0 otherwise.
+*/
+{
+ if (!SB_GetNumber (B, Val)) {
+ Error ("Constant integer expected");
+ return 0;
+ }
+ return 1;
+}
+
+
+
+static IntStack* GetWarning (StrBuf* B)
+/* Get a warning name from the string buffer. Returns a pointer to the intstack
+** that holds the state of the warning, and NULL in case of errors. The
+** function will output error messages in case of problems.
+*/
+{
+ IntStack* S = 0;
+ StrBuf W = AUTO_STRBUF_INITIALIZER;
+
+ /* The warning name is a symbol but the '-' char is allowed within */
+ if (SB_GetSym (B, &W, "-")) {
+
+ /* Map the warning name to an IntStack that contains its state */
+ S = FindWarning (SB_GetConstBuf (&W));
+
+ /* Handle errors */
+ if (S == 0) {
+ Error ("Pragma expects a warning name as first argument");
+ }
+ }
+
+ /* Deallocate the string */
+ SB_Done (&W);
+
+ /* Done */
+ return S;
+}
+
+
+
+static int HasStr (StrBuf* B, const char* E)
+/* Checks if E follows in B. If so, skips it and returns true */
+{
+ unsigned Len = strlen (E);
+ if (SB_GetLen (B) - SB_GetIndex (B) >= Len) {
+ if (strncmp (SB_GetConstBuf (B) + SB_GetIndex (B), E, Len) == 0) {
+ /* Found */
+ SB_SkipMultiple (B, Len);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+
+static PushPopResult ParsePushPop (StrBuf* B)
+/* Check for and parse the "push" and "pop" keywords. In case of "push", a
+** following comma is expected and skipped.
+*/
+{
+ StrBuf Ident = AUTO_STRBUF_INITIALIZER;
+ PushPopResult Res = PP_NONE;
+
+ /* Remember the current string index, so we can go back in case of errors */
+ unsigned Index = SB_GetIndex (B);
+
+ /* Try to read an identifier */
+ if (SB_GetSym (B, &Ident, 0)) {
+
+ /* Check if we have a first argument named "pop" */
+ if (SB_CompareStr (&Ident, "pop") == 0) {
+
+ Res = PP_POP;
+
+ /* Check if we have a first argument named "push" */
+ } else if (SB_CompareStr (&Ident, "push") == 0) {
+
+ Res = PP_PUSH;
+
+ /* Skip the following comma */
+ if (!GetComma (B)) {
+ /* Error already flagged by GetComma */
+ Res = PP_ERROR;
+ }
+
+ } else {
+
+ /* Unknown keyword, roll back */
+ SB_SetIndex (B, Index);
+ }
+ }
+
+ /* Free the string buffer and return the result */
+ SB_Done (&Ident);
+ return Res;
+}
+
+
+
+static void PopInt (IntStack* S)
+/* Pops an integer from an IntStack. Prints an error if the stack is empty */