diff options
Diffstat (limited to 'Build/source/utils/sam2p/minips.hpp')
-rw-r--r-- | Build/source/utils/sam2p/minips.hpp | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/Build/source/utils/sam2p/minips.hpp b/Build/source/utils/sam2p/minips.hpp new file mode 100644 index 00000000000..a833f28bd26 --- /dev/null +++ b/Build/source/utils/sam2p/minips.hpp @@ -0,0 +1,327 @@ +/* minips.hpp -- mini-PostScript parser and structure builder + * by pts@fazekas.hu at Sat Mar 9 21:33:04 CET 2002 + */ + +#ifdef __GNUC__ +#pragma interface +#endif + +#ifndef MINIPS_HPP +#define MINIPS_HPP 1 + +#include "config2.h" +#include "gensi.hpp" +#include "error.hpp" + +class MiniPS { + public: + #if SIZEOF_VOID_P <= SIZEOF_INT + typedef signed int ii_t; + #elif SIZEOF_VOID_P <= SIZEOF_LONG + typedef signed long ii_t; + #elif SIZEOF_VOID_P <= SIZEOF_CFG_LONGEST + typedef signed PTS_CFG_LONGEST ii_t; + #else + #error No integral data type to hold a ptr. + #endif + + class Real; + + /*union*/ struct TokVal { + SimBuffer::B *bb; + ii_t i; + /* double d; */ + /*MiniPS::*/Real *r; + }; + /** minips tokenizer */ + class Tokenizer { + public: + BEGIN_STATIC_ENUM1(int) EOFF=-1, NO_UNGOT=-2 END_STATIC_ENUM() + Tokenizer(GenBuffer::Readable& in_); + /** Reads and returns next token. + * Token types are named for their first character: + * '1': integertype: 31 bits signed (-1073741824 .. 1073741823) is + * guaranteed. VALUED + * '.': realtype (NOT implemented), double guaranteed. VALUED + * 'E': Ename (name without a slash). VALUED + * '/': Sname (name beginning with a slash). VALUED + * '(': stringtype (also with `<hexadecimal>') VALUED + * '[': beginning-of-array (also with `{') + * ']': end-of-array (also with '}') + * '<': beginning-of-dict (`<<') + * '>': end-of-dict (`>>') + * -1: EOF + */ + int yylex(); + inline TokVal const& lastTokVal() const { return tv; } + protected: + /** Data for last token read. */ + TokVal tv; + SimBuffer::B b; + GenBuffer::Readable& in; + /* NO_UNGOT for nothing, EOFF for EOF, 0..255 otherwise */ + int ungot; + }; + + /* This is somewhat similar to Ruby */ + typedef ii_t VALUE; + /** Qundef is the undefined hash key or array elements. It is an _invalid_ VALUE! */ + BEGIN_STATIC_ENUM1(VALUE) Qfalse=0, Qtrue=2, Qnull=4, Qundef=6, Qpop=8, Qerror=10, Qmax_=10 END_STATIC_ENUM() + + BEGIN_STATIC_ENUM1(unsigned) T_NULL=1, T_BOOLEAN=2, T_INTEGER=3, T_REAL=4, + T_STRING=5, T_ARRAY=6, T_DICT=7, T_SNAME=8, T_ENAME=9, T_VOID=10, + S_SENUM=20, /* must be a dict-member; meta-type used by scanf_dict() */ + S_FUNC=21, /* call a function to determine; meta-type used by scanf_dict() */ + S_UINTEGER=22, /* non-negative integer; meta-type used by scanf_dict() */ + S_ANY=23, /* anything; meta-type used by scanf_dict() */ + S_PINTEGER=24, /* positive integer; meta-type used by scanf_dict() */ + S_RGBSTR=25, /* an optional 3-byte string, representing an RGB color triplet */ + S_NUMBER=26, /* real or integer */ + S_PNUMBER=27 /* positive real or integer */ + END_STATIC_ENUM() + + /** No virtual methods because of special types. MiniPS composite values + * really _contain_ their components; one Value has exactly one reference: + * its container component. + */ + class Value { public: + inline ii_t getLength() const { return len; } + inline ii_t getType() const { return ty; } + inline bool hasPtr() const { return ptr!=NULLP; } + inline bool isDumping() const { return dumping; } + inline char const* getCstr() const { return (char const*)ptr; } + inline char* begin_() const { return (char*)ptr; } + inline char const* operator()() const { return (char const*)ptr; } + protected: + ii_t len; void *ptr; unsigned char ty; bool dumping; + }; + /** ptr contains a `void*'. Won't be freed. */ + class Void: public Value { public: + inline Void(void *ptr_) { ptr=ptr_; ty=T_VOID; } + inline void *getPtr() const { return ptr; } + }; + /** Always null-terminated. */ + class String: public Value { public: + /** Copies from ptr_ */ + String(char const*ptr_, ii_t len_); + /** Replaces (this) with a copy of (a).(b) */ + void replace(char const*ap, slen_t alen, char const*bp, slen_t blen); + }; + class Sname: public Value { public: + /** ptr_ must begin with '/' */ + Sname(char const*ptr_, ii_t len_); + bool equals(Sname const&other); + bool equals(char const*other); + }; + class Ename: public Value { public: + Ename(char const*ptr_, ii_t len_); + bool equals(Ename const&other); + bool equals(char const*other); + bool equals(char const*other, slen_t otherlen); + }; + class Real: public Value { public: + typedef unsigned char metric_t; + inline Real(double d_): d(d_), metric(0), dumpPS(false) { ty=T_REAL; ptr=(char*)NULLP; } + /** Also supply a string representation of the value (to avoid possible + * loss of precision when converting string -> double -> string). + */ + Real(double d_, char const*ptr_, ii_t len_); + // inline bool isZero() const { return d==0.0; } + inline double getBp() const { return d*me_factor[metric]; } + inline void setDumpPS(bool g) { dumpPS=g; } + inline void setMetric(metric_t metric_) { metric=metric_; } + /** Return true iff the specified null-terminated string is a valid + * dimen. + */ + static bool isDimen(char const *); + void dump(GenBuffer::Writable &out_, bool dumpPS_force=false); + /** @return ME_count on invalid */ + static metric_t str2metric(char const str[2]); + BEGIN_STATIC_ENUM1(metric_t) + ME_bp=0, /* 1 bp = 1 bp (big point) */ + ME_in=1, /* 1 in = 72 bp (inch) */ + ME_pt=2, /* 1 pt = 72/72.27 bp (point) */ + ME_pc=3, /* 1 pc = 12*72/72.27 bp (pica) */ + ME_dd=4, /* 1 dd = 1238/1157*72/72.27 bp (didot point) [about 1.06601110141206 bp] */ + ME_cc=5, /* 1 cc = 12*1238/1157*72/72.27 bp (cicero) */ + ME_sp=6, /* 1 sp = 72/72.27/65536 bp (scaled point) */ + ME_cm=7, /* 1 cm = 72/2.54 bp (centimeter) */ + ME_mm=8, /* 1 mm = 7.2/2.54 bp (millimeter) */ + ME_COUNT=9 + END_STATIC_ENUM() + protected: + double d; + /* vvv metric added at Sat Sep 7 12:26:08 CEST 2002 */ + metric_t metric; + /** Allow PostScript operators such as `div' to appear in the dump */ + bool dumpPS; + /** Factor to convert to bp */ + static const double me_factor[ME_COUNT]; + /** PostScript code to do multiplication by me_factor */ + static char const* const me_psfactor[ME_COUNT]; + }; + class Array: public Value { public: + Array(); + void free(); + void dump(GenBuffer::Writable &out_, unsigned indent); + void push(VALUE v); + VALUE get(ii_t index); + /** Cannot extend. Calls delete0() when overwriting an element */ + void set(ii_t index, VALUE val); + /** val: out */ + void getFirst(VALUE *&val); + /** val: in_out */ + void getNext(VALUE *&val); + protected: + ii_t alloced; + void extend(ii_t newlen); + }; + /** Keys must be Snames here! (i.e no integer keys allowed). The current + * implementation does a linear string search :-(. Dat: might not work + * on extremely long keys if slen_t can hold a larger integer than + * ii_t. + */ + class Dict: public Value { public: + Dict(); + void free(); + void dump(GenBuffer::Writable &out_, unsigned indent, bool dump_delimiters=true); + /** @return val or Qundef */ + VALUE get(char const*key, slen_t keylen); + /** A hack: get and touch. */ + VALUE get1(char const*key, slen_t keylen); + void untouch(char const*key, slen_t keylen); + /** Can extend. */ + void put(char const*key, VALUE val); + /** Calls delete0() when overwriting an element */ + void put(char const*key, slen_t keylen, VALUE val); + /** @return old value for key `key', or Qundef */ + VALUE push(char const*key, slen_t keylen, VALUE val); + /** key: out, val: out */ + void getFirst(char const*const*& key, slen_t &keylen, VALUE *&val, bool &touched); + /** key: in_out, val: in_out */ + void getNext (char const*const*& key, slen_t &keylen, VALUE *&val, bool &touched); + // void getFirst(VALUE *&key, VALUE *&val); + // void getNext(VALUE *&key, VALUE *&val); + protected: + ii_t alloced; + void extend(ii_t newlen); + }; + + static inline Value* RVALUE(VALUE v) { return static_cast<Value*>((void*)v); } + static inline Void* RVOID(VALUE v) { return static_cast<Void*>((void*)v); } + static inline Array* RARRAY(VALUE v) { return static_cast<Array*>((void*)v); } + static inline String* RSTRING(VALUE v){ return static_cast<String*>((void*)v); } + static inline Dict* RDICT(VALUE v) { return static_cast<Dict*>((void*)v); } + static inline Real* RREAL(VALUE v) { return static_cast<Real*>((void*)v); } + static inline Sname* RSNAME(VALUE v) { return static_cast<Sname*>((void*)v); } + static inline Ename* RENAME(VALUE v) { return static_cast<Ename*>((void*)v); } + static inline bool isDirect(VALUE v) { return (v&1)!=0 || v<=Qmax_; } + /** T_NULL .. T_DICT */ + static unsigned getType(VALUE v); + /** "null" .. "dict", "name" (T_SNAME), "ename" (T_ENAME, non-std-PS) */ + static char const* getTypeStr(unsigned u); + static void delete0(VALUE v); + /** The current implementation dumps dict keys in order of insertion, but + * this is very likely to change soon to an _arbitrary_ order. + */ + static void dump(GenBuffer::Writable& out_, VALUE v, unsigned indent=0); + static void dump(VALUE v, unsigned indent=0); + static inline VALUE Qinteger(ii_t v) { return (v<<1)+1; } + static inline ii_t int2ii(VALUE v) { return v>>1; } + /** Fortunate coincidence that 2x+1>0 <=> x>0 */ + static inline bool isPositive(VALUE v) { return v>0; } + static inline VALUE undef2null(VALUE v) { return v==Qundef ? Qnull : v; } + // static SimBuffer::B scale72(VALUE v, double d); + + class Parser { + /** Define this to avoid including <stdio.h> */ + typedef class _anon_filet_ {} *FILEP; + public: + BEGIN_STATIC_ENUM1(int) EOF_ALLOWED=Tokenizer::EOFF, EOF_ILLEGAL=-2, EOF_ILLEGAL_POP=-3 END_STATIC_ENUM() + /** Maximum depth of `run' file inclusions. */ + BEGIN_STATIC_ENUM1(unsigned) MAX_DEPTH=17 END_STATIC_ENUM() + Parser(char const *filename_); + /** The caller is responsible for closing the FILE* */ + Parser(FILEP f_); + Parser(GenBuffer::Readable *rd_); + Parser(Tokenizer *tok_); + ~Parser(); + /** Allocates and returns. Qundef is returned on EOF + * @param closer: EOF_ILLEGAL, EOF_ALLOWED, '>' or ']' + */ + VALUE parse1(int closer=EOF_ILLEGAL, int sev=Error::EERROR); + void setDepth(unsigned depth_); + /** Sets special filename for the `run' operator. `run' will read that + * special file from param `rd_', and then it will call rd_->vi_rewind(). + * Example usage: .addSpecRun("%stdin", new Files::FileR(stdin)); + */ + void addSpecRun(char const* filename_, GenBuffer::Readable *rd_); + /*MiniPS::*/Dict *getSpecRuns() const { return specRuns; } + /** Does not copy the dict, but sets the pointer. */ + void setSpecRuns(/*MiniPS::*/Dict *); + protected: + Parser(Parser *master_); + // VALUE parse1_real(int closer); + /* 0=nothing, 1=master 2=tok, 3=tok+rd, 4=tok+rd+f */ + unsigned free_level; + Parser *master; + Tokenizer *tok; + GenBuffer::Readable *rd; + FILEP f; + int unread; + unsigned depth; + /*MiniPS::*/Dict *specRuns; + /** Should MiniPS::delete0() be called on specRuns upon destruction of + * (this)? + */ + bool specRunsDelete; + }; + + /** Assumes that param `job' is a dict, extracts its elements into ..., + * emits errors for elements (not found and having default==Qundef), emits + * warnings for elements found in `job', but undescribed in `...' (only + * if show_warnings==true). Example: + * + * MiniPS::scanf_dict(job, true, + * "InputFile", MiniPS::T_STRING, MiniPS::Qundef, &InputFile, + * "OutputFile", MiniPS::T_STRING, MiniPS::Qundef, &OutputFile, + * "Profiles", MiniPS::T_ARRAY, MiniPS::Qundef, &Profiles + * NULLP + * ); + */ + static void scanf_dict(VALUE job, bool show_warnings, ...); + static void setDumpPS(VALUE v, bool g); + /** @param v must be T_REAL or T_INTEGER */ + static bool isZero(VALUE v); + /** @param v must be T_REAL or T_INTEGER + * @return true iff v==i + */ + static bool isEq(VALUE v, double d); + /** Dumps the human-readable real or integer value of the sum (m/72)*a+b+c-sub + * to `out'. + * @param rounding 0: nothing. 1: round the sum _up_ to integers. 2: + * round the sum _up_ to non-negative integers + * @param a must be T_REAL or T_INTEGER + * @param b must be T_REAL or T_INTEGER + * @param c must be T_REAL or T_INTEGER + * @param sub must be T_REAL or T_INTEGER + */ + static void dumpAdd3(GenBuffer::Writable &out, VALUE m, VALUE a, VALUE b, VALUE c, VALUE sub, unsigned rounding=0); + static void dumpScale(GenBuffer::Writable &out, VALUE v); +}; + +/* Fri Aug 16 17:07:14 CEST 2002 */ +#if 0 /* doesn't work because MiniPS::VALUE is really an `int', so there will be an ambiguous overload */ +inline GenBuffer::Writable& operator<<(GenBuffer::Writable& out_, MiniPS::VALUE v) { + MiniPS::dump(out_, v); + return out_; +} +#endif +inline GenBuffer::Writable& operator<<(GenBuffer::Writable& out_, MiniPS::Value *v) { + MiniPS::dump(out_, (MiniPS::VALUE)v); + return out_; +} + +// GenBuffer::Writable& operator<<(GenBuffer::Writable& out_, MiniPS::Value *v) { + +#endif |