view oldclasslib/source/charsink.cpp @ 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 607e3be6bad8
children
line wrap: on
line source

/*
 * AnaGram, a System for Syntax Directed Parsing
 * Character Sink Class Definitions
 *
 * Copyright 1993 Parsifal Software. All Rights Reserved.
 *
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
 *    appreciated but is not required.
 * 2. Altered source versions must be plainly marked as such, and must not be
 *    misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 */

#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "charsink.h"



// Output File Class

character_sink &output_file::printf(const char *fmt, ...) {
  va_list argptr;

  assert(file != NULL);
  va_start(argptr, fmt);
  vfprintf(file, fmt, argptr);
  va_end(argptr);
  return *this;
}



// String Accumulator Class


// Constructor

string_accumulator::string_accumulator(int nc, int nx) {
  cs = new char[nc];                 // allocate character storage
  xs = new unsigned[nx];             // allocate index storage
  csx = 0;
  xsx = nx;
  csmax = nc - 1;                    // leave room for a terminating null
  xsmax = nx;
  xs[--xsx] = csx;
  copy_flag = 0;                     // this is live
}


// Copy constructor

void string_accumulator::operator = (const string_accumulator &s) {
  cs = s.cs;
  xs = s.xs;
  csx = s.csx;
  xsx = s.xsx;
  csmax = s.csmax;
  xsmax = s.xsmax;
  copy_flag = s.copy_flag;
}

string_accumulator::string_accumulator(const string_accumulator &s) 
  : character_sink()
{
  *this = s;
  copy_flag++;                       // this is memorex
}


// Destructor

string_accumulator::~string_accumulator() {
  if (copy_flag) return;
  delete[] cs;
  delete[] xs;
}


// Reset string accumulator

string_accumulator &reset(string_accumulator &s) {
  assert(s.copy_flag == 0);
  s.csx = 0;
  s.xsx = s.xsmax;
  s.xs[--s.xsx] = s.csx;
  return s;
}

// postincrement stack level

string_accumulator string_accumulator::operator ++(int){
  string_accumulator cpy(*this);          // make copy for return value
  assert(copy_flag == 0);
  assert(xsx);
  xs[--xsx] = csx;
  return cpy;
}

// post decrement stack level

string_accumulator string_accumulator::operator --(int) {
  string_accumulator cpy(*this);          // make copy for return value
  assert(copy_flag == 0);
  csx = xs[xsx++];
  assert(xsx < xsmax);
  return cpy;
}

// Append data to stack

character_sink &string_accumulator::operator << (const char *str) {
  int k;
  if (str == NULL) return *this;
  k = strlen(str);
  assert(copy_flag == 0);
  assert(csx + k < csmax);           // room for string
  strcpy(&cs[csx],str);
  csx += k;
  return *this;
}

character_sink &string_accumulator::operator << (const unsigned char *str) {
  int k;
  if (str == NULL) return *this;
  k = strlen((char *) str);
  assert(copy_flag == 0);
  assert(csx + k < csmax);
  strcpy(&cs[csx],(char *) str);
  csx += k;
  return *this;
}

character_sink &string_accumulator::printf(const char *fmt, ...) {
  va_list argptr;
  int n;

  assert(copy_flag == 0);
  va_start(argptr, fmt);
  n = vsprintf(&cs[csx], fmt, argptr);
  va_end(argptr);
  assert(csx + n < csmax);
  csx += n;
  return *this;
}

// Pop character from stack

string_accumulator &string_accumulator::operator >> (int &c) {
  assert(copy_flag == 0);
  assert(csx > xs[xsx]);             // not empty
  c = cs[--csx];                     // pop character
  return *this;
}


// Access character on stack

char &string_accumulator::operator [](unsigned i) {
  assert(i < csx - xs[xsx]);         // index in bounds
  return cs[csx - i - 1];            // identify character
}


// Concatenate strings

string_accumulator &concat(string_accumulator &s) {
  assert(s.copy_flag == 0);
  assert(s.xsx < s.xsmax - 1);       // at least two strings
  s.xsx++;
  return s;
}


// Make permanent copy of string

char *copy(const string_accumulator &s) {
  char *c = new char[strlen(s.top())+1];

  strcpy(c,s.top());
  return c;
}