view oldclasslib/source/charsink.cpp @ 12:aab9ff6af791

Strengthen the build hack for non-DOS targets.
author David A. Holland
date Tue, 31 May 2022 00:58:42 -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;
}