End_Error help, Using unbounded Strings in Ada - string

Can someone please tell me why I am getting an End_Error exception, I do not see how I am getting past the end of the file if I have a loop that opts out before it reaches this point. If there is an easy fix, I'd love to hear it, I've been stuck for a while and unbounded strings are not really my forte.
with Ada.Text_IO;
use Ada.Text_IO;
with Ada.Strings.Unbounded;
use Ada.Strings.Unbounded;
with Ada.Strings.Unbounded.Text_IO;
use Ada.Strings.UNbounded.Text_IO;
procedure checker is
InWord : Unbounded_String;
dictionary : File_Type;
count : Integer;
begin
Ada.Text_IO.Open
(File => dictionary, Mode => In_File, Name => "dictionary.txt");
loop
exit when End_of_File;
InWord := Get_Line(File => dictionary);
Put(InWord);
New_Line;
end loop;
end checker;
raised ADA.IO_EXCEPTIONS.END_ERROR : a-textio.adb:690

You have
exit when End_of_File;
but since you’re looking for EOF on the input file it should be
exit when End_Of_File(File => Dictionary);
I’m not sure why you see the effect you do - when I tried it, nothing happened until I typed a couple of RETs and then I got the End_Error exception.
As you see, it’s nothing to do with strings, unbounded or otherwise!

As stated in the ARM, End_Of_File without parameters refers to the current input file.
In your case, it just refers to the standard input and not to your file.
Considering Simon's answer and the behaviour you got, I think you use your program with a redirection of the standard input (something like "cat myFile.txt | checker"). Am I right ?

Related

Using assign inside $test$plusargs in systemverilog

In my code, I want to do some connections using assign statement for all my tests except one test for which I added a runtime argument "HB_CONN_DISABLE" in my testlist. When I code as follows,I get the below error
if (!$test$plusargs("HB_CONN_DISABLE"))
begin
assign iol.hb_valid_in = dp_if_tx_inject.hb_bar_val_in;
assign iol.hb_in = dp_if_tx_inject.heartbeat_in;
end
Error-[V2KGEUV] Unknown or bad value for genvar
-I-:/nfs/hd/disks/mgr_0240/...............soc_post.sv, 543
Instance/Generate block name: iolc_tb
-I-: Elaboration time unknown or bad value encountered for generate if-statement
-I-: condition expression.
-I-: Please make sure it is elaboration time constant.
I also tried something like below, but in this case it doesn't recognize hb_bar_param in this line if(hb_bar_param==0) may be because by that time the parameter doesn't get the value
initial begin
if ($test$plusargs("HB_BAR_TI_CONN_DISABLE"))
begin
parameter hb_bar_param=1;
end
else
begin
parameter hb_bar_param=0;
end
end
if(hb_bar_param==0)
begin
assign statements......
end
I also tried using assign with ternary operator like the following
assign iol.hb_valid_in = ($test$plusargs("...somthing..")) ? (... some value ...) : (... some other value ...);
but in that case I will still end up assigning something if the testplus args is false, but for me the requirement is that I dont want to assign at all if the testplus args is there, please help me with this problem
Basically I want the following code for all my tests except one test for which I added testplus args.Is this illegal or is there any way to do it.
assign iol.hb_valid_in = dp_if_tx_inject.hb_bar_val_in;
assign iol.hb_in = dp_if_tx_inject.heartbeat_in;
A parameter is a compile time (elaboration time) construct which is defined before you run the program.
The if statements in your case which are the first-rank members in the module code are a generate construct which is also a compile-time thing.
Plusargs are passed to the already compiled model when you run it and $test$plusargs is a dynamic function executed at run time. Therefore it cannot be used to modify the generated part.
assign is a continuous assignment and is used to assign wires. Therefore, lhs always has to be assigned. Therefore, you desire to not assign something is using this statement is not possible.
However in case you declare the hb_valid_in as reg or as logic, you can just create a latch statement as the following:
always #*
if (!$test$plusargs("HB_CONN_DISABLE"))
iol.hb_valid_in = some_value;
So, it will assign a 'some_value' to 'hb_valid_in' only if the condition is true. Otherwise it will not.
This is all under assumption that you create a non-synthesizable test bench module.

Error failed to expand the variable

I have a model to read a file and do some operation on it and print the output in to a file. I got an error which I'm unable resolve it. The below code shows the declaration and assignment of the input data to an 2d array.
Real Data_2D[:,:]"data from input file as 2D matrix";
length := Streams.countLines(Infile)"length of the input file";
/*collect the data from input file in to 2D matrix */
for i in 1:length loop
currentLine := Streams.readLine(Infile, indexDataStart+i-1);
nextIndex := 1;
for j in 1:noColumns loop
(Data_2D[i,j],nextIndex) := Strings.scanReal(currentLine, startIndex=nextIndex,unsigned=false, message="readCoefficientsHawc2.mo c[i,j] : Real scan not successful");
end for;
end for;
I got the following error "Failed to expand the vairable Data_2D"
It would be verymuch helpful if I get a solution.
Modelica tools in general do not like unknown dimensions during compilation. Modelica Specification says that all arrays sizes should be known at compile time.
In your case Data_2D has unknown dimensions. Also, from your code I don't see what type of component is length and Data_2D. Are they parameters, constants?
In your case it might be possible to use Modelica.Blocks.Tables.CombiTable2D to read the table from file.

How to check if the first variable passed into a method is a string. Perl

I have no idea how to check for this. My method(if condition in method) should only work (execute) if the first argument passed in is a string. I know how to check other types, but I can't seem to find anything for checking for a string.
For a hash I would do something like;
if(ref eq 'HASH') {...}
If someone could provide a simple example I'm sure I would be able to apply it to what I'm doing. I will put up the code for the method and an explanation for the whole operational details of the method if needed.
Added Information
This is a method for handling different types of errors in the software, here are the 3 possible input formats:
$class->new("error string message")
$class->new("error string message", code => "UNABLE_TO_PING_SWITCH_ERROR")
$class->new("error string message", code => "UNABLE_TO_PING_SWITCH_ERROR", switch_ip => $ip3, timeout => $timeout)
There will always be an error message string first.
With the 1st case there is also a hashref to an error hash structure that is located in a library,
this method new will go into a template processing if the word "code" exists as an arg. where the longer detailed error message is constructed. (I already have the logic for this).
But I have to add logic so that the error message string is added to the hash, so the output is one hash, and not strings.
The second case is very similar to the first, where there are parameters eg. switch_ip , which are inserted into the string using a similar template processing logic, (already have this too).
So I think the first and second cases can be handled in the same way, but I'm not sure, so separated them in this question.
The last case is just can error message string by itself, which at the minute I just insert it into a one key message hash { message => "error string}.
So after all that how should I be checking or dividing up these error cases, At the minute my idea for the ones with code , is to dump the arguments into a hash and just use something like:
if(exists($param{code}) { doTemplateProcess()...}
I need to ensure that there is a string passed in first though. Which was my original question. Does any of my context information help? I hope I didn't go off the topic of my question, if so I'll open this a new question. Thanks.
Error hash - located in Type.pm
use constant ERROR_CODE => {
UNABLE_TO_PING_SWITCH_ERROR => {
category => 'Connection Error:',
template => 'Could not ping switch %s in %s minutes',
tt => {template => 'disabled'},
fatal => 1,
wiki_page => www.error-solution.com/,
},
}
From comments:
These will be called in the software's code like so
ASC::Builder::Error->new(
"Phase x this occured because y was happening:",
code => UNABLE_TO_PING_SWITCH_ERROR,
switch_ip => $ip3,
timeout => 30,
);
Putting the wisdom of your particular problem aside and channeling Jeff Foxworthy:
If you have a scalar and it's not a reference, you might have a string.
If your non-reference scalar doesn't look like a number, it might be a string.
If your non-reference scalar looks like a number, it can still be a string.
If your non-reference scalar has a different string and number value, it might be a dualvar.
You know that your argument list is just that: a list. A list is a collection of scalar values. A scalar can be a reference or not a reference. I think you're looking for the not a reference case:
die "You can't do that" if ref $first_argument;
Past that, you'd have to do fancier things to determine if it's the sort of value that you want. This might also mean that you reject objects that pretend to be strings through overloading and whatnot.
Perhaps you can make the first argument part of the key-value pairs that you pass. You can then access that key to extract the value and delete it before you use the remaining pairs.
You may easily check only whether the error string is a simple scalar value or a reference. You would do that with ref, but you must consider what you want to do if the first parameter isn't a string
You should write your constructor in the ASC::Builder::Error package along these lines
sub new {
my $class = shift;
my ($error, %options) = #_;
die if ref $error;
bless { string => $error }, $class;
}
This example simply dies, and so kills the program, if it is called with anything other than a simple string or number as the first parameter
You may call it as
ASC::Builder::Error->new('error')
or
ASC::Builder::Error->new(42)
and all will be well. If you try
ASC::Builder::Error->new('message', 'code')
then you will see a warning
Odd number of elements in hash assignment
And you may make that warning fatal
If there is anything more then you should explain
Supporting all of the following is simple:
$class->new("s")
$class->new("s", code => "s")
$class->new("s", code => "s", switch_ip => "s", timeout => "s")
All you need is the following:
sub new {
my ($class, $msg, %opts) = #_;
...
}
You can checks such as the following to examine what the called provided:
if (exists($opts{code}))
if (defined($opts{code}))
if ($opts{code})
Despite saying that the string will always be provided, you now ask how to check if was provided. As such, you are probably trying to perform validation rather than polymorphism. You shouldn't waste your time doing this.
Let's look at the hash reference example you gave. ref($arg) eq 'HASH' is wrong. That returns false for some hash references, and it returns false for some things that act like a reference to a hash. The following is a more proper check:
eval { %$arg; 1 }
The equivalent for strings would be the following:
eval { "$arg"; 1 }
Unfortunately, it will always return true! Every value can act as a string. That means the best thing you can do is simply to check if any argument is provided.
use Carp qw( croak );
croak("usage") if !#_;
It's rare for Perl subs to perform argument validation. Not only is it tricky, it's also expensive. It also provides very little benefits. Bad or missing arguments usually results in exceptions or warnings shortly after.
You might see suggestions to use croak("usage") if ref($arg); (or worse, die if ref($arg);), but keep in mind that those will cause the rejection of perfectly fine objects that overload stringification (which is somewhat common), and they will fail to detect the problem with ASC::Builder::Error->new(code => ...) because code produces a string. Again, performing type-based argument validation is an expensive and buggy practice in Perl.

SYBASE cursor declare as for read only become infinitive

There is a simple cursor, which has 260 records. Inside the loop not only print but update some tables. There is not only code, but explanation
/*Declare cursor for read only*/
DECLARE crsr_one CURSOR FOR
SELECT a,b,c,d
FROM table_name
WHERE a>=100
for read only
OPEN crsr_one /*open cursor*/
DECLARE #a,#b,#c,#d /*declare loop variables*/
while (1=1) /*start while loop*/
BEGIN
FETCH crsr_one into #a,#b,#c,#d /*fetch into variable */
IF (##sqlstatus = 2) /*Break if no more records*/
break
/*some other code with select and update table*/
print "%1! %2! %3! %4!", #a,#b,#c,#d /*Print variables*/
END
The problem is:
In the while loop it became infinitive and brings the same data.
Any idea why and how to correct it?
Your code looks good (except that the syntax for the DECLARE is invalid).
If the loop doesn't break on ##sqlstatus = 2, then the obvious question is: what value does it have? It can also be '1', indicating an error. To find out, print the value.
To be fully correct you should therefor also test for ##sqlstatus = 1. The easiest way to do this is to test for ##sqlstatus != 0 which covers both values 1 and 2.

String concatenation within an exception

In my trigger procedures I use RAISE EXCEPTION for messages. I have no problem with simple messages, but if I want to give the user some more complex feedback, I face a problem: the concatenation operator doesn't work within RAISE EXCEPTION statement.
First, I tried this:
CREATE OR REPLACE FUNCTION hlidej_datum_kon() RETURNS trigger AS $$
DECLARE
od date;
BEGIN
SELECT a.datum_od FROM akce AS a WHERE a.kod_akce = (
SELECT b.kod_akce FROM sj AS b WHERE b.kod_sj = NEW.kod_sj
) INTO od;
IF NEW.datum < od THEN
RAISE EXCEPTION 'Kontext nemohl být odkryt před začátkem akce ('||TO_CHAR(od)||')!'
ROLLBACK;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
Didn't work. So I tried to put the whole text to a text variable, but I didn't find how to put the variable's contents to the exception statement so that it would be printed as a message.
My question is: how to print a message containing variables in a PostgreSQL trigger function?
Just for sake of completeness, here is my trigger:
CREATE TRIGGER hlidej_datum_kon
AFTER INSERT OR UPDATE ON kontext
FOR EACH ROW
EXECUTE PROCEDURE hlidej_datum_kon();
END;
You not need to use concat. You can use wildcards instead:
RAISE EXCEPTION 'Kontext nemohl být odkryt před začátkem akce (%)!', od;
There are two bugs
first parameter of RAISE statement is format string - this string should be constant. It can contains a substitution symbols '%' and values for these symbols are places as others parameters of RAISE statement.
There should not be used ROLLBACK statement. RAISE EXCEPTION throws exceptions and ROLLBACK statement is newer executed. You cannot control transaction explicitly in PL/pgSQL - so you cannot use ROLLBACK or COMMIT statement in plpgsql ever.You can use a exception trapping
BEGIN
RAISE EXCEPTION 'blabla';
EXCEPTION WHEN some_exception_identif_see_list_of_exception_in_doc THEN
.. do some or do nothing
END;

Resources