Reputation: 31
Thought I was done and ready to submit this little project until I got this unexpected curveball.
The objective is to make a parser using a token lexer.
Essentially
<underline><red> R <green> G </green> <blue> B </blue> and back to red </red></underline>
will output as: "RGB and back to red" in their respective colors and attributes.
Everything works fine on windows but when I moved it over to the Linux systems it outputs the color codes with nothing happening.
#include <iostream>
#include <sstream>
#include <stack>
#include <map>
#include <cstdlib>
#include <vector>
#include "cmd.h"
#include "Lexer.h" // you should make use of the provided Lexer
#include "term_control.h"
#include "error_handling.h"
using namespace std;
map<string, term_colors_t> colorMap;
map<string, term_attrib_t> attribMap;
string display(const string& expression)
{
if(validate(expression) == "VALID") {
Lexer lex;
Token tok;
vector<term_colors_t> colorVect;
vector<term_attrib_t> attribVect;
lex.set_input(expression);
while(lex.has_more_token()){
tok = lex.next_token();
string sTok = tok.value;
if(tok.type == TAG && tok.value.at(0) != '/'){
cout<<term_cc(colorMap[tok.value], DEFAULT_COLOR, attribMap[tok.value]);
colorVect.push_back(colorMap[tok.value]);
attribVect.push_back(attribMap[tok.value]);
}
if(tok.type == TAG && tok.value.at(0) == '/'){
colorVect.pop_back();
cout<<term_cc(colorVect.back(), DEFAULT_COLOR, attribVect.back());
}
if(tok.type != TAG){
cout<<tok.value;
}
}
}
else if(validate(expression) != "VALID") return validate(expression);
return "";
}
_
cout<term_cc(Color, DEFAULT_COLOR, Attribute)
is the specfic method where the problem is hiding I have been searching around and can't seem to find the proper method.
cout<<term_fg(color)
that method properly displays color on the Linux system but I cannot have attributes with that method.
Everything I've been reading pertained only to color not color and attributes they were also using the echo command and hard coded colors for specific terminals. These would require serious changes in all my code and cause it to not work on Windows and only on Linux so I'm trying to avoid this.
Thanks in advance for any advice on this problem everyone I appreciate it hopefully I'll be able to get this in before 12!
Upvotes: 0
Views: 389
Reputation: 241701
It's not clear to me where colorMap
and attribMap
are initialized and to what values, and I'm just going on instinct here, but it seems likely that the keys for colorMap
are colours and the keys for attribMap
are attributes. In that case underline
is not a key in colorMap
and red
is not a key in attribMap
.
In your program, you do the following:
if(tok.type == TAG && tok.value.at(0) != '/'){
cout<<term_cc(colorMap[tok.value], DEFAULT_COLOR, attribMap[tok.value]);
which assumes that every TAG
is present in both colorMap
and attribMap
. But if the tag is a colour like "red"
, it is (probably) only in colorMap
and if it is an attribute like "underline"
, it is (probably) only in attribMap
.
Now, what happens when you execute colorMap["underline"]
? Here, the convenience of C++'s standard library can be a bit of a disadvantage because it silently hides an error. The answer is that a mapping from "underline"
to the default value of a term_colors_t
is added to the map so that the lookup will always return something. term_colors_t
is an enum, so its default value is 0
(not '0'
).
Now, term_cc
-- if it is the same term_cc
that @MikePetch dug up -- does not check its arguments for validity; it just assumes that they are valid ANSI digits ('0'
through '9'
, or in other words a number between 48 and 57, inclusive.) Since it doesn't check them, it just outputs includes them as they are in its output, and since you're (probably) calling term_cc
with an attributes argument of 0 -- that is, a NUL
character -- it outputs the NUL
as part of the supposed console code.
I checked xterm
, konsole
and the Linux console, and all of them ignore the NUL
character. (I believe that is the expected behaviour; DEC terminals like the VT-100 ignored NUL
s, although in some circumstances you needed to insert them because the terminal would also ignore any character if the previous control took too long.) I don't know what terminal emulator you are using, and it is quite possible that it has different behaviour, such as terminating the control code sequence. term_cc
outputs the attribute first, even though it is the third argument, so it could well be that a NUL
attribute would cause the terminal emulator to simply print something like ;31;49m
instead of setting the foreground colour to red.
Some other bugs:
You never pop attribVect
; only colorVect
. So I don't see how the attributes will be properly restored.
You don't initialize colorVect
to a DEFAULT_COLOR
. So after the first tag is popped, you'll pop the (only) element off of colorVect
, leaving it empty, and then call colorVect.back()
, which is undefined if colorVect
is empty.
Those were just the things I notice on a quick skim through the code. There might be other problems.
Upvotes: 1