view anagram/agcore/sums.syn @ 21:1c9dac05d040

Add lint-style FALLTHROUGH annotations to fallthrough cases. (in the parse engine and thus the output code) Document this, because the old output causes warnings with gcc10.
author David A. Holland
date Mon, 13 Jun 2022 00:04:38 -0400
parents 13d2b8934445
children
line wrap: on
line source

{
/*
 * AnaGram, A System for Syntax Directed Programming
 * Copyright 1993-2002 Parsifal Software. All Rights Reserved.
 * Copyright 2006 David A. Holland. All Rights Reserved.
 * See the file COPYING for license and usage terms.
 *
 * sums.syn - read checksum and build information
 */

#include "port.h"

#include "agstack.h"
#include "agstring.h"
#include "build.h"
#include "checksum.h"
#include "sums-defs.h"

//#define INCLUDE_LOGGING
#include "log.h"
}

[
  //pointer input
  event driven
  parser name = parseSumData
  parser file name = "#.cpp"
  line numbers path = "sumparse.syn"
]

eof = 0
digit = '0-9'
ascii = 32..126

(void) inserted data $
 -> checksum data, build date, build os, eof

(void) build date
 -> "Build date:", text, '\n' = build_date = stringbuf;

(void) build os
 -> "Build OS:", text, '\n' = build_os = stringbuf;

(void) checksum data
 -> "Checksum data:\n", sum entry?...

(void) sum entry
 -> summable:w, '=', length:l, ',', sum:s, offset:o, '\n' = addsum(w,l,s,o);

(summable) summable
 -> "ag1"  = SUM_AG1;
 -> "ag"   = SUM_AG;
 -> "agcl" = SUM_AGCL;

(unsigned long) length
  -> integer:i = i;

(unsigned long) sum
  -> integer:i = i;

(unsigned long) offset
  ->                = 0;
  -> '@', integer:i = i;

(unsigned long) integer
 -> digit:d            = d - '0';
 -> integer:i, digit:d = 10*i + d - '0';

(void) text
 -> ascii:c       = startstring(c);
 -> text, ascii:c = addstring(c);

{
#define SYNTAX_ERROR {\
   char buf[500];\
   sprintf(buf,"%s, line %d, column %d\n", \
  (PCB).error_message, (PCB).line, (PCB).column);\
  LOGV(buf);\
}

  /* note - cannot compute skiplen at runtime */
  static char sumInfo[512] = "Checksum data:\n";
  static const size_t skiplen = 15; /* length of "Checksum data:\n" */

  static AgStack<sumentry> sums;

  static char stringbuf[128];
  static size_t stringbufpos;

  AgString build_date, build_os;

  static void addstring(int ch) {
    if (stringbufpos < sizeof(stringbuf)-1) {
      stringbuf[stringbufpos++] = ch;
      stringbuf[stringbufpos] = 0;
    }
  }

  static void startstring(int ch) {
    stringbufpos = 0;
    addstring(ch);
  }

  static void addsum(summable what, unsigned long len, unsigned long sum,
		     unsigned long offset) {
    sumentry se;
    se.what = what;
    se.offset = offset;
    se.correct.length = len;
    se.correct.sum = sum;
    se.observed.length = 0;
    se.observed.sum = 0;
    sums.push(se);
  }

  const char *checksums_ok(void) {
    LOGSECTION("checksums_ok");

    char *p = sumInfo;
    size_t i;

    init_parseSumData();

    for (i=0; i<sizeof(sumInfo); i++) {
      unsigned char c = (unsigned char)p[i];
      if (i >= skiplen) {
        c ^= PADBYTE;
      }
      //LOGV(c)
      PCB.input_code = c;
      if (PCB.exit_flag == AG_RUNNING_CODE) parseSumData();
      if (c == 0) break;
    }

    if (PCB.exit_flag != AG_SUCCESS_CODE) {
      LOGV(PCB.exit_flag);
      return "Parse error in checksum data";
    }

    if (sums.size() == 0) {
      LOGS("no sums");
      return "Checksum data empty";
    }

    for (i=0; i<sums.size(); i++) {
      observeSum(&sums[i]);
    }

    for (i=0; i<sums.size(); i++) {
      LOGV(sums[i].what) LCV(sums[i].offset);
      LOGV(sums[i].correct.length) LCV(sums[i].correct.sum);
      LOGV(sums[i].observed.length) LCV(sums[i].observed.sum);

      if (sums[i].observed != sums[i].correct) {
	switch (sums[i].what) {
	  case SUM_AG1: return "Bad checksum for ag1 shared library";
	  case SUM_AG: return "Bad checksum for ag executable";
	  case SUM_AGCL: return "Bad checksum for agcl executable";
	}
	// this shouldn't happen
        return "Bad checksum for unknown object (?)";
      }
    }

    // ok
    return NULL;
  }
}