How to display messages from a message file on a display screen using RPGLE? - file

I have designed a screen using SDA in AS/400 that takes an ID number as input and searches in two PFs for that ID and displays corresponding values fetched from those PFs in the respective fields on screen. Below is the DSPF code:
A*%%TS SD 20180813 084626 PATELDH REL-V7R1M0 5770-WDS
A*%%EC
A DSPSIZ(24 80 *DS3)
A R HEADER
A*%%TS SD 20180802 075026 PATELDH REL-V7R1M0 5770-WDS
A 2 2USER
A 2 30'PRODUCT INQUIRY SCREEN'
A COLOR(WHT)
A 2 63DATE
A EDTCDE(Y)
A 3 63TIME
A R FOOTER
A*%%TS SD 20180802 074433 PATELDH REL-V7R1M0 5770-WDS
A OVERLAY
A 22 4'F3=EXIT'
A R DETAIL
A*%%TS SD 20180813 073420 PATELDH REL-V7R1M0 5770-WDS
A CA03(03 'EXIT')
A CA12(12 'PREVIOUS')
A OVERLAY
A 7 16'ID:'
A 10 16'NAME:'
A 12 16'CATEGORY:'
A #ID R I 7 20REFFLD(CATEGORIES/ID AS400KT2/RCATE-
A GORY)
A #NAME R O 10 22REFFLD(PRODUCTS/NAME AS400KT2/RPROD-
A UCTS)
A #CATEGORY R O 12 26REFFLD(CATEGORIES/CATEGORY AS400KT2-
A /RCATEGORY)
A R MSGSFL SFL
A*%%TS SD 20180803 054959 PATELDH REL-V7R1M0 5770-WDS
A SFLMSGRCD(24)
A MSGKEY SFLMSGKEY
A MSGQ SFLPGMQ(10)
A R MSGCTL SFLCTL(MSGSFL)
A*%%TS SD 20180813 084626 PATELDH REL-V7R1M0 5770-WDS
A OVERLAY
A SFLDSP
A SFLDSPCTL
A SFLINZ
A 01 SFLEND
A SFLSIZ(0002)
A SFLPAG(0001)
A MSGQ SFLPGMQ(10)
I have written a free format RPGLE code that makes this screen work. Below is the RPGLE code:
FDSPPRD CF E WorkStn
FRPRODUCTS IF E K DISK
FRCATEGORY IF E K DISK
FRPRODCATEGO A E K DISK
DtempID S LIKE(ID)
DmsgID S 7A
DmsgF S 10A
D getMsg PR EXTPGM('MSGSFLCL')
D msgID 7A
D msgF 10A
/Free
DoW *In03 = *Off;
Write HEADER;
Write FOOTER;
ExFmt DETAIL;
If #ID = *Zeros;
msgID = 'MSG0001';
msgF = 'ASGNMSGF';
getMsg(msgID:msgF);
Else;
Chain #ID RPRODUCTS;
If %Found(RPRODUCTS);
#NAME = NAME;
Chain ID RCATEGORY;
If %Found(RCATEGORY);
#CATEGORY = CATEGORY;
EndIf;
EndIf;
EndIf;
EndDo;
*InLR = *On;
/End-Free
Below is the CL program called by RPGLE program to get the message text from the msgfile:
PGM PARM(&MSGID &MSGF)
DCL VAR(&MSGID) TYPE(*CHAR) LEN(7)
DCL VAR(&MSGF) TYPE(*CHAR) LEN(10)
SNDPGMMSG MSGID(&MSGID) MSGF(&MSGF)
ENDPGM
Below are the two PFs from which the records are read:
RPRODUCTS-
A R PRODUCTS
A ID 2P 0
A NAME 16A
A K ID
RCATEGORY-
A R CATEGORIES
A ID 2P 0
A CATEGORY 15A
A K ID
All the above codes compile successfully. But the problem is that the msg from the msgf does not appear on the screen. Rest all works. Just the msg from msgf is not being displayed when I press 'Enter' key with a blank ID on screen. Can someone please suggest an information source from where I can learn the concepts of such applications. Also, a help with this one would be appreciated.

You are not writing the MSGCTL record. If you don't write that, then the message subfile will not be displayed. You are also not providing a value for MSGQ.
When using a message subfile, I generally get the program name out of the program status data structure, and put that into MSGQ during program initialization time. It should never change. I also pass that to my procedure that sends the message to the message queue. That way I know that both values will be the same. If they are not the messages will not display.
Here is my message subfile definition:
A* ========================================================================
A* Message Subfile
A* ------------------------------------------------------------------------
A R MSGSFL SFL
A SFLMSGRCD(27)
A MSGKEY SFLMSGKEY
A PGMQ SFLPGMQ(10)
A* ------------------------------------------------------------------------
A* Message Subfile Control
A* ------------------------------------------------------------------------
A R MSGCTL SFLCTL(MSGSFL)
A SFLPAG(1)
A SFLSIZ(2)
A SFLDSP SFLDSPCTL
A SFLINZ
A 53
AON53 SFLEND
A PGMQ SFLPGMQ(10)
There are only a few differences from yours. Lets go through them.
A SFLMSGRCD(27)
This is 27 because I am using the *DS4 screen size. Not an issue.
You are using OVERLAY, I'm not because I write that format first, but as long as you write MSGCTL after you write HEADER you should be good there.
You are using SFLCLR. That is unnecessary, remove it.
A 53
AON53 SFLEND
This is a bit different. I do this because SFLEND requires a conditioning indicator, but I really don't care, I want SFLEND active no matter what that indicator says. (I use *In53 as my SFLEND for regular subfiles too, and I don't want to have to worry whether it is on or off.
I use a sub-procedure to send the message: here is my code for that:
// ----------------------------------------
// SndDspfMsg - sends an *INFO message to the
// message subfile in a display file.
//
// Parameters:
// StackEntry - The program call stack entry to which the message is sent.
// Usually the program name. This must be the same value that
// is placed in the SFLPGMQ variable in the message subfile
// control format.
// MsgId - The Message ID from message file JCMSGF to be sent to the program
// message Queue.
// MsgDta - (optional) Data to be used by the message to provide dynamic
// message content. Defaults to blank.
// MsgDtaLen - (optional) The length of the message data provided above.
// This parameter is required if MsgDta is provided. Defaults
// to zero. If this is not provided or is zero, MsgDta is ignored.
// ----------------------------------------
dcl-proc SndDspfMsg Export;
dcl-pi *n;
StkEnt Char(10) Const;
MsgId Char(7) Const;
MsgDta Char(512) Const Options(*VarSize: *NoPass);
MsgDtaLen Int(10) Const Options(*NoPass);
end-pi;
dcl-s Name_t Char(10) Template Inz('');
// Call Stack Qualifier - used by message handling APIs
dcl-ds CallStackQual_t Qualified Template Inz;
Module Like(Name_t) Inz('*NONE');
Program Like(Name_t) Inz('*NONE');
end-ds;
// Qualified Name
dcl-ds QualName_t Qualified Template Inz;
Name Like(Name_t) Inz('');
User Like(Name_t) Inz('');
end-ds;
// Standard Error Code Format
dcl-ds ErrorCdType1_t Qualified Template Inz;
BytesProv Int(10) Inz(%size(ErrorCdType1_t));
BytesAvail Int(10);
MsgId Char(7);
Data Char(1024) Pos(17);
end-ds;
dcl-ds MsgFile LikeDs(QualName_t) Inz(*LikeDs);
dcl-ds ErrorCd LikeDs(ErrorCdType1_t) Inz(*LikeDs);
dcl-s pmMsgDta Char(512) Inz('');
dcl-s pmMsgDtaLen Int(10) Inz(0);
dcl-s pmMsgTyp Char(10) Inz('*INFO');
dcl-s pmStkCnt Int(10) Inz(0);
dcl-s pmMsgKey Char(4) Inz('');
// Send Program Message
dcl-pr qmhsndpm ExtPgm('QMHSNDPM');
MessageId Char(7) Const;
MessageFile LikeDs(QualName_t) Const;
MessageDta Char(512) Const Options(*Varsize);
MessageLen Int(10) Const;
MessageType Char(10) Const;
StackEntry Char(4102) Const Options(*Varsize);
StackCounter Int(10) Const;
MessageKey Char(4);
Error LikeDs(ErrorCdType1_t);
StackEntryLen Int(10) Const Options(*NoPass);
StackEntryQual LikeDs(CallStackQual_t)
Const Options(*NoPass);
ScreenWaitTime Int(10) Const Options(*NoPass);
StackEntryType Char(10) Const Options(*NoPass);
Ccsid Int(10) Const Options(*NoPass);
end-pr;
// Handle *NoPass Parms
if %parms() >= %parmnum(MsgDtaLen);
pmMsgDtaLen = MsgDtaLen;
endif;
// if Message Data is provided,
if pmMsgDtaLen > 0;
pmMsgDtaLen = min(%size(pmMsgDta): pmMsgDtaLen);
pmMsgDta = %subst(MsgDta: 1: pmMsgDtaLen);
endif;
MsgFile.Name = 'JCMSGF';
qmhsndpm(MsgId: MsgFile: pmMsgDta: pmMsgDtaLen:
pmMsgTyp: StkEnt: pmStkCnt: pmMsgKey:
ErrorCd);
end-proc;
This should get your message subfile working. As for why the other fields are not populating, maybe your product ID and category ID are not found in the file. Note, the product ID and category ID will be the same value when this program runs because ID is mapped to the display file, the product file, and the category file. This doesn't seem to be what you want. If you have trouble dealing with that, ask a new question.

Related

matlab assigning text file data to age and gender

Okay so my assignment is for an engineering project and I have talked to my teacher many times but without much success. the code reads data that comes from a rotary encoder in a text file. The question I have is how do I make two sets of arrays with age and gender and link it to each text file thats read in. For example the first text file comes from a girl that is 10; that spun a crank and output data to a text file. How do i code so that someway i can assign the first text file to an age and gender? Heres my code so far any help is appreciated.
%% ME 208 Project Group 21
clear; close all; clc;
%Constants
dt=.1;
%Translate Data
mass = 10; %values are in units of Kilograms
radius = 1; %values are in units of meters
inertia = mass*radius^(2);
for ii=1:2
%File Name Variable
filename=['sub_' num2str(ii) '.txt'];
%Data is Collected
Data1=dlmread(filename,'\t',0,0);
%Times for data
t1=dt:dt:length(Data1)*dt;
%Vel
[ang_vel1, ang_acc1]=dxdt_d2xdt2(Data1,2,dt);
torq1 = inertia*ang_acc1;
%Calculations of parameters
meanrt1(ii) = rms(torq1);
maxrt1(ii) = max(torq1);
end
%Plot
figure(1);plot(t1,torq1,t2,torq2); grid minor;

dbWriteTable in RMySQL error in name pasting

i have many data.frames() that i am trying to send to MySQL database via RMySQL().
# Sends data frame to database without a problem
dbWriteTable(con3, name="SPY", value=SPY , append=T)
# stock1 contains a character vector of stock names...
stock1 <- c("SPY.A")
But when I try to loop it:
i= 1
while(i <= length(stock1)){
# converts "SPY.A" into SPY
name <- print(paste0(str_sub(stock1, start = 1, end = -3))[i], quote=F)
# sends data.frame to database
dbWriteTable(con3,paste0(str_sub(stock1, start = 1, end = -3))[i], value=name, append=T)
i <- 1+i
}
The following warning is returned & nothing was sent to database
In addition: Warning message:
In file(fn, open = "r") :
cannot open file './SPY': No such file or directory
However, I believe that the problem is with pasting value onto dbWriteTable() since writing dbWriteTable(con3, "SPY", SPY, append=T) works but dbWriteTable(con3, "SPY", name, append=T) will not...
You are probably using a non-base package for str_sub and I'm guessing you get the same behavior with substr. Does this succeed?
dbWriteTable(con3, substr( stock1, 1,3) , get(stock1), append=T)

Read from text file and assign data to new variable

Python 3 program allows people to choose from list of employee names.
Data held on text file look like this: ('larry', 3, 100)
(being the persons name, weeks worked and payment)
I need a way to assign each part of the text file to a new variable,
so that the user can enter a new amount of weeks and the program calculates the new payment.
Below is my code and attempt at figuring it out.
import os
choices = [f for f in os.listdir(os.curdir) if f.endswith(".txt")]
print (choices)
emp_choice = input("choose an employee:")
file = open(emp_choice + ".txt")
data = file.readlines()
name = data[0]
weeks_worked = data[1]
weekly_payment= data[2]
new_weeks = int(input ("Enter new number of weeks"))
new_payment = new_weeks * weekly_payment
print (name + "will now be paid" + str(new_payment))
currently you are assigning the first three lines form the file to name, weeks_worked and weekly_payment. but what you want (i think) is to separate a single line, formatted as ('larry', 3, 100) (does each file have only one line?).
so you probably want code like:
from re import compile
# your code to choose file
line_format = compile(r"\s*\(\s*'([^']*)'\s*,\s*(\d+)\s*,\s*(\d+)\s*\)")
file = open(emp_choice + ".txt")
line = file.readline() # read the first line only
match = line_format.match(line)
if match:
name, weeks_worked, weekly_payment = match.groups()
else:
raise Exception('Could not match %s' % line)
# your code to update information
the regular expression looks complicated, but is really quite simple:
\(...\) matches the parentheses in the line
\s* matches optional spaces (it's not clear to me if you have spaces or not
in various places between words, so this matches just in case)
\d+ matches a number (1 or more digits)
[^']* matches anything except a quote (so matches the name)
(...) (without the \ backslashes) indicates a group that you want to read
afterwards by calling .groups()
and these are built from simpler parts (like * and + and \d) which are described at http://docs.python.org/2/library/re.html
if you want to repeat this for many lines, you probably want something like:
name, weeks_worked, weekly_payment = [], [], []
for line in file.readlines():
match = line_format.match(line)
if match:
name.append(match.group(1))
weeks_worked.append(match.group(2))
weekly_payment.append(match.group(3))
else:
raise ...

Programmatically input data in X509 Certificate using OpenSSL

I am trying to create a ecdsa certificate but I would like to generate it programatically. I am using openssl and C programming.
When I generate a certificate from the command line multiple questions are asked me to answer in other to use in the certificate.
I would like to know how to define this questions, input this data programatically.
This is what I have found on the web, but I don't understand how to insert more information and this really works:
X509 *x;
x=X509_new();
X509_NAME *name = X509_get_subject_name(x);
X509_set_version(x, 2);
ASN1_INTEGER_set(X509_get_serialNumber(x), 3);
X509_gmtime_adj(X509_get_notBefore(x), 0);
X509_gmtime_adj(X509_get_notAfter(x), (long) 60 * 60 * 24 * 365);
X509_set_pubkey(x, pk);
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (const unsigned char*) "PT", -1, -1, 0);
The X509_NAME_add_entry_by_txt function I realise it's the answer to the country, but what does this "C" means? How is this function composed? Can I put whatever I want in the place of "C" and in the place of "PT"?
The C is the standard way of denoting the country and PT is the correct selection for Portugal (see this list for other country options).
You can use the X509_NAME_add_entry_by_txt function to set other values in the distinguished name, using the correct prefix:
C = country
ST = state
L = locality
O = organisation
OU = organisational unit
CN = common name
Only the country field has a fixed range of choices.
See also the example given on the manual page: http://www.openssl.org/docs/crypto/X509_NAME_add_entry_by_txt.html#EXAMPLES

Custom cmdline parsing algorithm

Im trying on an implementation for custom cmd line having cmds specific for my application.
commands are either single word or multiple words.
say for e.g.
-#version //single word cmd
-#show input pressure //Multiple word cmds
-#show input temp
In order to parse and call the corresponding function pointers i have two tables for the above cmds.
Table1: Basic Cmd Table
typedef struct CommandStruct{
char (*f)(uint8 argn, const char **argv);
char *fname;
char *help;
}CommandStruct;
/*Help information*/
char version_help[] = " Usage:Version \n Command Displays the version information.\n";
char ShowInput_help[] = " \nUsage: \n show input pressure --Shows input pressure \n \
show input temp -- shows input temperature \n";
/*Table1 - Basic set of commands*/
CommandStruct basic_command_list[] =
{
/* function name , cmd name , help information */
{version , "version" , version_help },
{clear , "clear" ,"Clear the screen" },
{quit , "quit" ,"Exit from the prompt" },
{ShowInput , "show input", ShowInput_help },
{NULL , NULL , NULL }
};
-#show input pressure
-#show input temp
The above 2 cmds fall under "show input" in table1.
In the current algorithm, on splitting the input string to tokens ,I check if its a single word or double word. In case of single word i directly call the function.
In case of more than a single word(e.g.Show input temp) ,I take the first 2 tokens (i.e. 'show input' and try to filter and search in the sub table.(here its table2).
/*Table 2 : Sub cmd for the cmds starting with 'show input' */
CommandStruct show_input_command_list[] =
{
/* function name , cmd name , help information */
{ShowInputPressure , "pressure", ShowInput_help },
{ShowInputTemp , "temp",ShowInput_help},
{NULL , NULL , NULL }
};
This way i continue say for the below cmds I compare and find "show network" once that's matched then i search the table3 which has the network commands.
Some of the other cmds are like
show network ipaddress
show network ipsubnet
show network abcd<#>
set network ipaddress <#>
set network ipsubnet <#>
set network abcd <#> <#>
So i have to add ShowNetwork to table 1 and create a new table show_network_command_list[] and add the three other cmd .etc .
How to improve this algorithm ? Please suggest me if there is a better solution. Thanks.

Resources