Mercurial > ~dholland > hg > ag > index.cgi
view examples/mpp/token.h @ 7:57b2cc9b87f7
Use memcpy instead of strncpy when we know the length anyway.
Modern gcc seems to think it knows how to detect misuse of strncpy,
but it's wrong (in fact: very, very wrong) and the path of least
resistance is to not try to fight with it.
author | David A. Holland |
---|---|
date | Mon, 30 May 2022 23:47:52 -0400 |
parents | 13d2b8934445 |
children |
line wrap: on
line source
/* * AnaGram, a System for Syntax Directed Programming * C Macro preprocessor * Token handling 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. */ #ifndef TOKEN_H #define TOKEN_H #include <assert.h> #include <string.h> #include <stdlib.h> #include "charsink.h" #include "strdict.h" extern string_dictionary td; // define token identification codes enum token_id { END_OF_FILE =0, SPACE =' ', ANDAND ='A', // "&&" ANDassign, // "&=" ARROW, // "->" CONCAT, // "##" DECR, // "--" DIVassign, // "/=" ELLIPSIS, // "..." EQ, // "==" ERassign, // "^=" GE, // ">=" ICR, // "++" LE, // "<=" LS, // "<<" LSassign, // "<<=" MODassign, // "%=" MINUSassign, // "-=" MULTassign, // "*=" NE, // "!=" ORassign, // "|=" OROR, // "||" PLUSassign, // "+=" RS, // ">>" RSassign, // ">>=" CHARACTERconstant, // character constant STRINGliteral, // character string HEXconstant =129, OCTconstant, DECconstant, FLOATconstant, // real NAME, AUTO, // "auto" BREAK, // "break" CASE, // "case" CHAR, // "char" CONSTANT, // "const" CONTINUE, // "continue" DEFAULT, // "default" DO, // "do" DOUBLE, // "double" ELSE, // "else" ENUM, // "enum" EXTERN, // "extern" FLOAT, // "float" FOR, // "for" GOTO, // "goto" IF, // "if" INT, // "int" LONG, // "long" REGISTER, // "register" RETURN, // "return" SHORT, // "short" SIGNED, // "signed" SIZEOF, // "sizeof" STATIC, // "static" STRUCT, // "struct" SWITCH, // "switch" TYPEDEF, // "typedef" UNION, // "union" UNSIGNED, // "unsigned" VOIDkey, // "void" VOLATILE, // "volatile" WHILE, // "while" UNRECOGNIZED }; struct token { unsigned handle; // token dictionary index token_id id; // token type }; // Token sink class class token_sink { public: virtual ~token_sink() {} virtual token_sink &operator << (token) = 0; virtual token_sink &operator << (token *) = 0; friend int error(token_sink &); }; // Token accumulator // Member functions that are not inline are in token.cpp class token_accumulator : public token_sink { token *cs; unsigned *xs; unsigned csx; unsigned xsx; unsigned csmax; unsigned xsmax; public: // Constructor token_accumulator(int nc, int nx = 1); // Destructor ~token_accumulator(); // Reset token accumulator friend token_accumulator &reset(token_accumulator &); // Change levels token_accumulator& operator ++(){ assert(xsx); // Room for another level? xs[--xsx] = csx; return *this; } token_accumulator& operator --() { csx = xs[xsx++]; assert(xsx < xsmax); // Have to leave last level active return *this; } // Push data token_sink& operator << (token c) { assert(csx < csmax); // room for data? cs[csx++] = c; return *this; } token_sink &operator << (token *tp); token_sink &operator << (token_accumulator &t) { assert(this != &t); // prevent disaster return *this << (token *) t; } // Pop data token_accumulator &operator >> (token &c); // Access data //token &operator [](unsigned); operator token *() { cs[csx].id = END_OF_FILE; cs[csx].handle = 0; return &cs[xs[xsx]]; } // Concatenate token strings friend token_accumulator& concat(token_accumulator &); // Make permanent copy of token string friend token *copy(token_accumulator &); // Get size of token string friend unsigned size(token_accumulator &s); // Check for error friend int error(token_accumulator &t); }; inline unsigned size(token_accumulator &s) { return s.csx - s.xs[s.xsx]; } inline int error(token_accumulator &t) { return t.csx >= t.csmax || t.xsx >= t.xsmax; } // Token Translator class class token_translator : public token_sink { character_sink *cs; int space_required; public: // Constructor token_translator(character_sink *sink) { cs = sink; space_required = 0; } // Accept data token_sink &operator << (token t) { if (space_required && t.id > 128) *cs << ' '; *cs << td[t.handle]; space_required = t.id > 128; return *this; } token_sink &operator << (token *tp); // Check for error; friend int error(token_sink &) {return 0;} }; #endif