PMC T-Shell Practical Methods of Application

- Program Cooperation Based on MicroScript and C Language -


All the source programs appearing and explained in this article are recorded on the attached CD-ROM [TN].

Introduction

In "PMC T-Shell Practical Methods of Application" in Vol. 82 of this magazine, we explained the method of employing C language as one application development technique using PMC T-Shell. In this issue, as a continuation of that, we will explain one more development technique--the technique of developing programs by making MicroScript and C language cooperate.

Concerning MicroScript

MicroScript is a language processing environment that is loaded as standard equipment on PMC T-Shell. With it, there is the advantage of being able to easily develop applications that possess a GUI.

In the previous issue, we explained a program that realizes simple GUI parts using C language, but inside that, it was necessary to use system calls provided by PMC T-Shell and PMC T-Kernel Extension, and knowledge of those was required.

On the other hand, with MicroScript, we arrange figure elements (things such as polygons and images, which we call segments) inside the screen, and we can easily describe programs that carry out processing by receiving actions (press operations, etc.) from the user vis-à-vis those figure elements. For example, if we implement in MicroScript the program we took last in the previous issue, it becomes as in List 1 (actually, outside of this, preparation of a little additional code and some figure elements (segments) by means of the figure editor will become necessary).

In comparison to the method based on C language, in which various initial settings and the like were necessary, the program we ought to describe has become remarkably small, and even calling up the APIs of PMC T-Shell and PMC T-Kernel Extension is unnecessary.

Moreover, in the method based on C language, applications had to receive and process events that had occurred. On the other hand, in MicroScript, we can pair together segments and actions toward them (operations such as press, click, and double click) and define subroutines. And then, we describe inside those subroutines processing for when events that satisfy those conditions have occurred.

For example, we write

ACTION subroutine name (parameters . . . ) PRESS MS_EXIT

as the definition of a subroutine that runs when the segment called MS_EXIT is pressed. This means that control moves to this subroutine if the MS_EXIT segment is pressed.

In this manner, in MicroScript, it has become easy to implement event driven applications [1]. Moreover, the syntax itself possesses the atmosphere of BASIC or LOGO, and learning it is also easy.

The Reason for Making C Language and MicroScript Cooperate

As we explained in the previous issue, there are respective merits and demerits to development based on C language and development based on MicroScript. Therefore, let's try thinking, in particular, from the side of developing an application that possesses a GUI.

As for the merit of utilizing MicroScript, we can arrange various figure elements on the screen and easily write the processes that respond interactively to the operations of the user toward these. As mentioned above, the event processing events that the operating system possesses have nicely been made abstract, and there are also no cases in which one is bothered with the description of complex event processing or drawing processing. One can develop by concentrating on the original processing necessary to the application.

Moreover, because MicroScript has adopted an execution method based on an interpreter format, efficient development is possible even in cases in which the correction and execution phases are frequently repeated. In applications that possess a GUI, in particular in screen development where trial and error cannot be avoided, this point is a great merit of MicroScript.

On the other hand, there are also aspects at which MicroScript is weak. It cannot freely draw arbitrary figures and characters at arbitrary places inside a screen. Additionally, there are also limits to freely opening and closing windows and accessing files. Furthermore, one can mention that conversion into intermediate code is carried out, and thus if we compare it to execution in native code, there are cases where consideration toward efficiency falling is necessary.

Continuing on, let's try considering the merits of utilizing C language. It becomes an inside-out relationship with the case of MicroScript. In other words, you directly use the functions of PMC T-Shell and PMC T-Kernel Extension, and thus on the other hand of being able to freely control screen drawing, window management, and file access, sufficient knowledge of PMC T-Shell and PMC T-Kernel Extension become necessary.

As we have mentioned above, development based on C language and MicroScript have their respective merits. Accordingly, in PMC T-Shell, by using in parallel and making both C language and MicroScript programs cooperate in a manner that makes use of the merits of both, it has come about that we can configure them as one application.

In other words, dividing according to use in which for the GUI (design) parts, where an overall framework and trial and error are necessary, we utilize MicroScript, and for the finely detailed control that cannot be realized with that we use C language, becomes possible.

In the subsection below, we will go on to explain the techniques of cooperation between C language and MicroScript while changing examples.

Methods of Cooperation between C Language and MicroScript

As we explained in the previous issue also, in carrying out cooperation between programs based on MicroScript and C language, several techniques are conceivable. In this article, among those, we will explain a method in which we employ cooperation by using an inter-process message between MicroScript and a process base application described by means of C language.

In handling inter-process messaging in a C language program, we mainly use b_snd_msg(), b_rcv_msg(), and b_clr_msg, which are provided in T-Kernel Extension (please refer to the PMC T-Kernel Extension manual for the respective full details). Also, on the MicroScript side, we use the PROCESS statement, the MSEND statement, and the MRECV statement.

With cooperation between C language and MicroScript, we move the processing forward according to the following plan.

(1)
Execute the program based on MicroScript

(2)
Execute the program based on C language that you want to cooperate by means of the PROCESS statement from MicroScript (or, execute beforehand and put in place the program based on C language that you want to cooperate)

(3)
Send out a request to the program based on C language from MicroScript
 
a. We transmit a message (request) to
-- the program based on C language by
-- means of the MSEND statement from
-- MicroScript
 
b. In the program based on C language,
-- we receive the message (request) by
-- means of b_rcv_msg()
 
c. We execute the processing that complies
-- with the received request

(4)
From the program based on C language, we respond to MicroScript
 
a. By means of b_snd_msg(), we transmit a
-- message (response of the results) to the
-- to MicroScript, which was the
-- transmission origin of the request
 
b. In MicroScript, we receive the message
-- (response) by means of the MRECV statement
 
c. We process the response results that were
-- received

In this manner, at the point in time processing that is difficult to realize in MicroScript has become necessary, transmitting a message vis-à-vis a program based on C language that is cooperating is the basic plan. By replying to MicroScript with the results that were processed in the program based on C language, we can realize processing by mutually cooperating [2].

Well then, from the next section, while giving examples in concrete terms we will proceed with an explanation of what kind of implementation we actually make.

Methods of Using Inter-Process Messaging

Messages in PMC T-Kernel are things for communicating among particular processes. The message queue is attached to a process. Moreover, we do not make a mailbox in the manner of T-Kernel or ITRON, rather at the necessary time we directly send a message by means of b_snd_msg(), and we directly receive a message with b_rcv_msg() [3].

An inter-process message is not a simple byte string, rather it must be contents in accordance with a message structure. Moreover, inter-process messages are not things that are used only among applications that the user has created, rather they are frequently used (in the dark) also in order for the system to proceed with processing. For that reason, messages are classified for each use into 31 types, and the ones that can be freely used among the applications the user has created are limited to eight types among the 31 types.

Sending and Receiving of Messages among C Language-Based Processes

First, to begin with, we will give examples in which we send and receive messages among processes described by means of C language. In the sending and receiving of inter-process messages, we mainly use the following APIs defined in PMC T-Kernel Extension.

  • b_snd_msg()
Transmission of message
  • b_rcv_msg()
Reception of message
  • b_clr_msg()
Clearing of message

b_snd_msg() transmits a message vis-à-vis a particular process, and b_rcv_msg() receives the message that was transmitted. b_clr_msg() deletes messages that have collected in the message queue of the process.

We show in List 2 (prog_1-main.c) an example in which we receive a message. Moreover, we show in List 3 (prog_2-main.c) an example in which we transmit a message.

There is a program execution sequence, so please execute first without fail prog_1. When you begin execution with prog_1, you immediately enter into wait for reception of a message based on b_rcv_msg(). Next, when you execute prog_2, you transmit a message vis-à-vis prog_1 of a moment ago [4], and then you terminate as is. prog_1 receives the message sent from prog_2, displays the received contents as a debugging message, and then terminates.

By doing things in this manner, we can carry out synchronous processing by using inter-process messaging between two different processes.

Sending and Receiving of Messages among C Language-Based Programs and MicroScript

Continuing on, we will give an example in which we carry out interchange using inter-process messaging between a process described by means of C language and an application based on MicroScript.

In using inter-process messages in MicroScript, we employ the following instructions.

  • MSEND
Transmission of an inter-process message
  • MRECV
Reception of an inter-process message

The MSEND statement, if we talk about it in terms of the method based on C language of a moment ago, corresponds to b_snd_msg(), and the MRECV statement corresponds to b_rcv_msg().

In a case where we use inter-process messages in MicroScript, the messages that can utilized are limited to eight types. What we call these eight types are the same message types we can freely use in applications that were previously mentioned. To put this another way, it comes down to saying that in MicroScript, messages of the type that the system uses in the dark cannot be handled (both reception and transmission of them are impossible).

Moreover, in a case where we use inter-process messages in MicroScript, in the process based on C language that does the receiving, a message with the following structure must be interpreted as the thing that was transmitted.

typedef struct {
  W   msg_type;    /* Message type */
  W   msg_size;    /* Message size */
  W   ext_size;
  UB  msg_body[1]; /* Actually, variable length */
} MSCRIPT_MSG;

Compared to the MESSAGE structure, attention is necessary to the fact that the item called ext_size has been added before msg_body (furthermore, in PMC T-Shell, 0 is always stored in this value). Moreover, msg_size becomes a value to which this ext_size part is added.

In List 4 (prog_3-main.c), we show the C language-based program that receives the message with b_rcv_msg(), and in List 5 (prog_m2), we show the MicroScript that transmits

In this example also, it is necessary to by all means execute and put in place beforehand prog_3. When we execute prog_m1 on the MicroScript side, it immediately transmits a message vis-à-vis prog_3, and then terminates as is. prog_3 that has received the message makes the debug output of the received contents and terminates.

Cooperation Application Example

In up to the previous section, we have explained the basics of cooperation between MicroScript and C language. From this section, we shall give slightly more complicated application examples.

As we mentioned in the beginning, MicroScript is not very good at a drawing straight lines and curved lines at arbitrary spots on the screen. On the other hand, preparing and putting into place beforehand figures/images called buttons and switches, and making the system display figures decided upon as GUI parts and acquiring user actions to them can be accomplished easily [5].

Accordingly, let's try test manufacturing an application (the source program is recorded in this issue's attached CD-ROM) of the type in which we decide to implement only the GUI in MicroScript, and then, when screen drawing has become necessary, we send out a request to a C language process using an inter-process message and make it do the screen drawing there.

Figure 1 Screen example of the MicroScript side

When we start up this application, the screen in Fig. 1 appears. Here, when we type characters from the keyboard, the characters are input in the text box portion. The four button that are at the top edge are things for selecting the contents we wish to draw. The selector in the middle part is something for selecting color. Select the color you like from the eight colors. The lower half of the screen is the part for displaying the contents drawn by the C language-based program.

After clicking either "Straight Line," "Rectangular Frame," or "Circle/Ellipse," click two appropriate locations in the region of the lower half of the screen. By means of these operations, you specify the start point and the end point. For example, after clicking the "Straight Line" button, respectively click appropriate locations (upper left part and lower right part, etc.). When you do that, a straight line connecting the clicked parts will be drawn on the screen in the selected color.

Figure 2 Execution examples

If it's a rectangular frame, the application draws a square in which the start point and the end point are made the outermost points; and, if it's a circle/ellipse, the application draws a circle (ellipse) inscribed in a frame in which the start point and the end point are made the outermost points. After a click on "Character String," click just one time in the region in the lower part of the screen. When you do that, you make the point clicked the upper left start point, and you draw the character string that has been input in the text box (Fig. 2).

Configuration and Message Contents

In order to create this application, we make it so that we force a division of roles between MicroScript and C language in the following manner.

MicroScript Side [prog_m3]
  • We make it the parent process.
  • We make only GUI realization the purpose, and arbitrary figures and characters on the screen are not drawn with it.
  • Using parts, we specify the figure types and characters we wish to draw.
  • We specify such things as color and shape also with parts.
C Language Side [prog_4]
  • We make it the child process.
  • We make only drawing on the screen the purpose, and we do not implement the GUI with it.
  • As long as there are no instructions from the MicroScript parent (as long as a message hasn't been transmitted), drawing is not executed.
  • Notification will be made from the MicroScript parent as to the figure types and characters, colors and shapes to draw.
Inter-process messaging is done with the following content
  • We will use MS_TYPE7 as the message type [6].
  • The contents to be transmitted and received are application independent forms (structures) [7, 8, 9]
  • From MicroScript, we transmit only the contents that match the request.
  • From the C language-based process, we reply with (transmit) only the processed results matched to the requested contents.
  • We make as one processing unit the transmitting of the message from MicroScript and up to the reception of the results from the C language-based process, and by means of this we attempt synchronization.

Contents of the Process Based on C Language

First, we will briefly explain the contents from the C language-based process that serves as the child process.

At the point in time the process has started up, it immediately stores the process ID of the self process in the global name [prog_4]. This is something for the purpose of making it so that we can give and receive messages from the MicroScript script we wish to cooperate with. This is the same thing we carried out between prog_3 (the C language-based process) and prog_m2 (MicroScript script) in the previous section [10].

If the process has succeed in the basic initialization, the process enters a loop in which it continuously issues b_rcv_msg(). In this C language-based process, as long as a message that matches a request is not transmitted in, processing is not carried out, and the process continues to wait until it receives a message.

After receiving a message, the process searches for contents that match the header. This is for the purpose of making it so that there will not be any malfunction even if a message with unrelated contents is transmitted in the same message type. We take the four-byte region immediately after the message length (msg_size and ext_size), and we load the character string "SMPL" there as an identifier. If the character string "SMPL" exists in the identifier of a received message, the process makes the judgment that the received contents are certainly something that has been sent in from a cooperating opposite address. Furthermore, at this point in time, the process has not acquired the overall message. We make it so that the actual acquiring is done after doing a confirmation of these headers. Moreover, deletion of the message also has not yet been carried out (in b_rcv_msg(), we specify NOCLR).

Once we have confirmed the header and judged it as a message that it is all right to receive, next we receive the message in its entirety. If we receive the entirety, because it is not necessary for the message to be left at the top of a queue, we delete the message by specifying CLR in b_rcv_msg().

Last, from the number of the request contents that is described in the header portion of the contents, the process judges the contents to be processed, and then executes the respective processing.

During each processing, at the point in time the process has finished the processing from start to end, it sends a message in return to the transmission source of the request. In this example, we have made it so that it only returns with an error code whether or not a error has occurred during processing, but, if necessary, it is also possible to embed arbitrary binary data inside the message and reply.

When the message transmission corresponding to the reply is completed, the process once again returns to the previous wait for reception of message loop, and then enters into waiting until receiving a message corresponding to a request.

Furthermore, in this program, we have used the following APIs in order to find out the window that possesses the request transmission source process plus that window's drawing environment (window management APIs inside PMC T-Shell).

  • b_wlst_wnd()
Window list up
  • b_wget_gid()
Retrieve window drawing environment ID

b_wlst_wnd() is normally used in retrieving a window ID list that corresponds to a list of the windows that are open. However, as a special function, it possesses a function through which a specific process acquires a list of windows that are opened. Here, utilizing that function, we are making it so that we find out the window ID of the opposite window that is opened and acquire the drawing environment ID from that window ID.

We are doing something that is a little confusing, but this is because MicroScript cannot find out the window ID of its own window that is opened. On the cooperating C language process side, we are making it so that we guess the window ID of the window that is opened in the MicroScript opposite and retrieving the drawing environment ID from that.

Also, we have made it so that we have a general-purpose memory drawing environment as the work region. As to why, this is because we cannot make all the resources common, since the C language-based process and the MicroScript script at the cooperation address are different processes. For that reason, on the side of the C language-based process, we prepare a general-purpose memory drawing environment in order to preserve the contents corresponding to the screen display contents, and through appropriate timing we copy and display those in the MicroScript script window at the cooperation address.

However, because this C language-based process does not do anything other than a passive operation, we have made it so that redrawing timing is measured on the MicroScript side. In other words, on the MicroScript side, at appropriate points in time, we are transmitting a request corresponding to redrawing to the C language-based process, and the new contents are displayed on the screen.

Contents of the MicroScript Side

On the MicroScript side, we have mainly implemented only parts that correspond to the GUI. On top of the window, button types for selecting the contents you wish to draw, selectors for use in specifying the color, and an area for showing frames corresponding to a work region are arranged [11].

Concerning the respective segments, when we do pointer operations such as strike the touch panel, we execute the respective corresponding event. Because generated events are sent vis-à-vis segments, we go on to implement processing in regard to operations such as pointer presses and clicks for each segment. In concrete terms, we utilize the ACTION statement as shown at the beginning of prog_m1.

As a part outside of the GUI, there is also a part that moves processing forward by giving and receiving messages with a C language-based process at a cooperation address. In this example, the process at the cooperation address is the C language-based application called prog_4; in order to exchange messages with this process, it is necessary to find out the process ID of the opposite. In this case, as we explained previously, because the opposite's process ID is stored in the global name called [prog_4], we can acquire those contents by means of getgnm(). Furthermore, in a case where this global name doesn't exist, the program judges it as an error and the transmission and reception of messages is not carried out (we have made it so that it terminates MicroScript itself in a case where the program has judged an error at the point in time of initialization processing during startup).

When transmitting a message, caution concerning data strings is necessary. The opposite process we wish to cooperate with is described in C language, and the contents that will be given and received are defined with structures. However, MicroScript cannot handle the structures in C language. Therefore, it comes down to describing the contents as arbitrary strings. For this reason, the messages we exchange use type B arrays.

When transmitting a message, we secure a region that can only store the contents we will transmit, and we write in order there the contents in accord with the contents we would like to transmit (we make into byte strings and store the contents that correspond to W type, H type, and TC type character strings). Moreover, in this example, because we have implemented on the premise of little endian for the CPU endian, correction is necessary in a case where we are using a big endian CPU.

When we transmit a message to an opposite we would like to cooperate with, continuing on, we wait for a reply from the opposite. When the reply is received, in the same manner as the case of the previous C language-based process, we confirm the contents corresponding to the header. If it is judged that it has been received from the assumed opposite, we make it so that the program further interprets the received contents. In this example, because we have made it so that only an error code comes back in reply as the result for the requested contents, we do a read-in of the error code.

In this manner, we make it so that we proceed with processing while maintaining cooperation by transmitting to an opposite messages corresponding to requests, and receiving from the opposite messages corresponding to the results of those requests.

Method of Using the Cooperation Example

We will now explain the method of using the sample program that we took up here last.

First, in the beginning, we start up and put in place prog_4, which will become the child process. Because MicroScript prog_m3 that will become the parent process is made so that it proceeds with processing on the premise that prog_4 has completed startup, please be careful [12]. If the program succeeds at startup, prog_4 displays a self process ID as a debug message, and then enters as is into a message reception wait loop.

Next, the program starts up MicroScript prog_m3 that will become the parent process. Immediately after startup, the parent process transmits a request corresponding to start communications and initialization vis-à-vis child process prog_4. At this time, if prog_4 hadn't been started up and initialization had failed, MicroScript prog_m3 would regard it as an error having occurred, and it would terminate as is.

Moreover, among the request contents received in child process prog_4, we output a portion of the contents as a debug message. We can confirm with the debug message what type of requests have been received and the processing that is being done. When an error occurs, because we output those contents in a debug message, we can also find out its cause.

If the program succeeds in initialization, it enters into a so-called event loop on the MicroScript side, and it displays the window in Fig. 1.

Conclusion

Describing only in C language the GUI application taken up last is, of course, also possible. In this case, one must go on to implement one by one the basic things in the development of a GUI, such as opening windows, arranging parts such as buttons, and processing corresponding to the execution of the respective parts. Accordingly, even if we are just simply specifying two appropriate points on the screen and drawing a line, knowledge of such concerning PMC T-Kernel Extension and PMC T-Shell is necessary.

On the other hand, if we use MicroScript, the labor in implementation is greatly reduced, because MicroScript processes for us the GUI, where there is a lot of effort and trouble in that type of implementation.

In this article, we have explained a concrete example of GUI application development using PMC T-Shell. In the program we took up last, we developed the drawing portion in C language, and then we adopted the form of calling that up from MicroScript. Because the overall framework of the application is realized in MicroScript, making improvements while repeating through trial and error the user interface and design can be carried out efficiently.

MicroScript can be easily learned if you have acquired knowledge of one general programming language or another. It also has become easy to adopt a division of labor system in which multiple persons in charge are matched to each's field of charge and technical skill.

Through this article, we believe that you have understood that efficient development, in which by using PMC T-Shell's MicroScript and C language in parallel and making use of the respective merits, can proceed. We would be happy if the reader feels the possibilities of T-Engine by making full use of the functions of PMC T-Shell.

____________________

List 1 prog_m1 (parts execution example based on MicroScript)
#
#	- prog_m1 -
#
#	(C) Copyright 2003 by Personal Media Corporation.
#

VERSION 3
#
# Press processing vis-à-vis MS_EXIT
#
ACTION PD_PRESS(seg:S, idx:I, x:I, y:I) PRESS MS_EXIT
	LOCAL	flg:B		# == 0 : outside range    != 0 : inside range

	flg = 0

	# Overlapping the picture inside press
	MOVE MS_FRAM_P:seg.X, seg.Y, @

	# Event loop while pressing MS_EXIT
	REPEAT
		IF (($PDX > seg.X) && ($PDX < seg.X + seg.W) && \
		    ($PDY > seg.Y) && ($PDY < seg.Y + seg.H))
			# Inside parts region
			IF (flg == 0)
				flg = 1
				APPEAR MS_FRAM_P
			ENDIF

		ELSE
			# Outside parts region
			flg = 0
			DISAPPEAR MS_FRAM_P
		ENDIF

		IF ($PDB == 0)
			# Released the PD
			DISAPPEAR MS_FRAM_P
			BREAK
		ENDIF
	ENDREPEAT
	DISAPPEAR MS_FRAM_P

	# MS_EXIT was clicked
	IF (flg != 0)
		FINISH
	ENDIF
END
#
# Start of program
#
PROLOGUE
	FULLWIND
	APPEAR MS_EXIT
END

List 2 prog_1-main.c (reception side: receives message from prog_2-main.c)
/*
 *	prog_1-main.c (T-Shell Sample/Main)
 *
 *	(C) Copyright 2003 by Personal Media Corporation.
 */


#include	<basic.h>
#include	<btron/outer.h>
#include	<tcode.h>
#include	<stdio.h>
#include	<stdlib.h>


/* Internal variables */
LOCAL	TC	PROG_1_NM[8] = {	/* [prog_1]	*/
			TK_p, TK_r, TK_o, TK_g, TK_USCR, TK_1,
			TNULL
		};


/* ---------------------------------------------------- main(cli style main) */
/*
 * main(cli style main)
 */
EXPORT	W	main(W ac, TC *av[])
{
	W	rv;
	W	l;
	W	pid;                   /* Self process ID */
	W	mpid;                  /* Process ID of message transmission source */
	W	msize;                 /* Message size (byte units) */
	MESSAGE	dmy;			   /* Message temporary reception use */
	MESSAGE	*msg;			   /* Received message */

	rv = 0;
	msg = NULL;

	/* Acquisition of self process ID */
	pid = b_prc_sts(0, NULL, NULL);
	if (pid < ER_OK) {
		rv = pid;
		printf("b_prc_sts : %d, %d\n", rv, rv >> 16);
		goto EXIT;
	}

	/* Create global name and store self process ID */
	rv = b_cre_nam(PROG_1_NM, pid, N_FORCE | DELEXIT);
	if (rv < ER_OK) {
		printf("b_cre_nam : %d, %d\n", rv, rv >> 16);
		goto EXIT;
	}

	/* Message reception wait */
	for ( ; ; ) {
		/* Free previous reception region */
		if (msg != NULL) {
			free(msg);
			msg = NULL;
		}

		/* Message temporary reception */
		mpid = b_rcv_msg(MM_TYPE7, &dmy, sizeof(MESSAGE), WAIT|NOCLR);
		if ((mpid < ER_OK) && (mpid != ER_PAR)) {
			/* Error occurred (ER_PAR ignore) */
			rv = mpid;
			printf("b_rcv_msg(dummy) : %d, %d\n", rv, rv >> 16);
			break;
		}

		/* Reject if not an application message 7 */
		if (dmy.msg_type != MS_TYPE7) {
			/* Not needed, so discard */
			b_clr_msg(MM_ALL, MM_ALL);
			continue;
		}

		/* Secure reception region */
		msize = dmy.msg_size + sizeof(W) * 2;
		msg = (MESSAGE *)(malloc(msize));
		if (msg == NULL) {
			rv = ER_NOMEM;
			printf("memory allocation error.\n");
			break;
		}

		/* Reception */
		rv = b_rcv_msg(MM_TYPE7, msg, msize, NOWAIT | CLR);
		if (rv < ER_OK) {
			/* Error occurred */
			printf("b_rcv_msg(main) : %d, %d\n", rv, rv >> 16);
			break;
		} else if (rv != mpid) {
			/* Process of transmission source different (no normal startup) */
			printf("not match process ID\n");
			;	/* Return to loop */
		} else {
			/* Show the received contents and terminate */
			printf("sender PID       : %d\n", mpid);
			printf("all message size : %d\n", msize);
			printf("MESSAGE.msg_type : 0x%08x\n", msg->msg_type);
			printf("MESSAGE.msg_size : 0x%08x\n", msg->msg_size);
			printf("MESSAGE.msg_body :\n");
			for (l = 0; l < msg->msg_size; l++) {
				printf("%02x ", msg->msg_body.ANYMSG.msg_str[l]);
			}
			printf("\n");
			break;
		}
	}

EXIT:
	if (msg != NULL) {
		free(msg);
	}
	b_ext_prc(rv);
	return rv;
}
--------------------
#
#	@(#)Makefile (prog_1)
#		    For use with GNU make
#
#	make method
#	 make
#		Create release use regular version
#	 make mode=debug
#		Create for use in debugging
#	 make clean
#		Delete all files created with make 
#	 make install
#		Install in prescribed place (for actual machine use only)
#
# Version
version = 0x1000
# Set release use to default
#mode =
# Source dependencies-related file (automatically created)
DEPS = Dependencies
DEPENDENCIES_OUTPUT := $(DEPS)
# Application standard rules
include $(BD)/bappl/etc/makerules
# ----------------------------------------------------------------------------
# Create target
TARGET = prog_1
# Search path of source file
S = ./ ../src
VPATH = $(S)
# Header file directory addition
HEADER := $(S) $(HEADER)
# Source file
SRC =	main.c
OBJ = $(addsuffix .o, $(basename $(SRC)))
WC_SRC = $(filter %.C, $(SRC))
DBFLAGS += -l
ifeq ($(mode), debug)
    CFLAGS += -Wall
endif
# ----------------------------------------------------------------------------
.PHONY: all clean
INST = $(addprefix $(TARGET), .bz .map)
INST2 = $(addprefix $(TARGET), .out)
all: $(INST)
$(TARGET).out: $(OBJ)
	$(LINK.o) $(LDOBJS) $^ $(LOADLIBES) $(LDLIBS) $(OUTPUT_OPTION)
clean:
	$(RM) $(OBJ)
	$(RM) $(WC_SRC:%.C=%.c) $(DBSRC)
	$(RM) $(INST) $(INST2) *.lst $(DEPS)
# Compression archive
$(TARGET).bz: $(INST2)
	$(CP) $(TARGET).out _t
	$(STRIP) _t
	$(MKBTF) -o$@ -a0x8003 -c -tprog_1 \
		9.$(CPU_TYPE)._t
	$(RM) _t
# Source dependencies related
$(WC_SRC:%.C=%.c):
ifdef DEPENDENCIES_OUTPUT
$(DEPS):	; touch $(DEPS)
else
$(DEPS): $(SRC)	; $(MAKEDEPS) $@ $?
endif
include $(DEPS)

List 3 prog_2-main.c (transmission side: transmits message to prog_1-main.c)
/*
 *	prog_2-main.c (T-Shell Sample/Main)
 *
 *	(C) Copyright 2003 by Personal Media Corporation.
 */


#include	<basic.h>
#include	<btron/outer.h>
#include	<tcode.h>
#include	<stdio.h>


/* Internal type declarations */
typedef	struct {
	W	msg_type;		/* Same as MESSAGE.msg_type	*/
	W	msg_size;		/* Same as MESSAGE.msg_size	*/
	W	data;			/* Suitable contents */
} MSG_SAMPLE;


/* Internal variables */
LOCAL	TC	PROG_1_NM[8] = {	/* [‚‚’‚‚‡Q‚P]		*/
			TK_p, TK_r, TK_o, TK_g, TK_USCR, TK_1,
			TNULL
		};


/* --------------------------------------------------- Main(cli style main) */
/*
 * main(cli style main)
 */
EXPORT	W	main(W ac, TC *av[])
{
	W	rv;
	W	spid;
	MSG_SAMPLE	msg;

	rv = 0;

	/* Acquisition of the transmission target process ID */
	rv = b_get_nam(PROG_1_NM, &spid);
	if (rv < ER_OK) {
		printf("b_get_nam : %d, %d\n", rv, rv >> 16);
	} else {
		/* Prepare contents to be transmitted */
		msg.msg_type = MS_TYPE7;
		msg.msg_size = sizeof(MSG_SAMPLE) - offsetof(MSG_SAMPLE, data);
		msg.data = 0x12345678;	/* Suitable contents */

		/* Transmit message */
		rv = b_snd_msg(spid, (MESSAGE *)(&msg), NOWAIT);
		if (rv < ER_OK) {
			printf("b_snd_msg : %d, %d\n", rv, rv >> 16);
		}
	}

	b_ext_prc(rv);
	return rv;
}
--------------------
#
#	@(#)Makefile (prog_2)
#		    For use with GNU make
#
#	make method
#	 make
#		Create release use regular version
#	 make mode=debug
#		Create for use in debugging
#	 make clean
#		Delete all files created with make
#	 make install
#		Install in the prescribed place (for actual machine use only)
#
# Version
version = 0x1000
# Set release use to default
#mode =
# Source dependencies-related file (automatically created)
DEPS = Dependencies
DEPENDENCIES_OUTPUT := $(DEPS)
# Application standard rules
include $(BD)/bappl/etc/makerules
# ----------------------------------------------------------------------------
# Create target
TARGET = prog_2
# Search path of source file
S = ./ ../src
VPATH = $(S)
# Header file directory addition
HEADER := $(S) $(HEADER)
# Source file
SRC =	main.c
OBJ = $(addsuffix .o, $(basename $(SRC)))
WC_SRC = $(filter %.C, $(SRC))
DBFLAGS += -l
ifeq ($(mode), debug)
    CFLAGS += -Wall
endif
# ----------------------------------------------------------------------------
.PHONY: all clean
INST = $(addprefix $(TARGET), .bz .map)
INST2 = $(addprefix $(TARGET), .out)
all: $(INST)
$(TARGET).out: $(OBJ)
	$(LINK.o) $(LDOBJS) $^ $(LOADLIBES) $(LDLIBS) $(OUTPUT_OPTION)
clean:
	$(RM) $(OBJ)
	$(RM) $(WC_SRC:%.C=%.c) $(DBSRC)
	$(RM) $(INST) $(INST2) *.lst $(DEPS)
# Compression archive
$(TARGET).bz: $(INST2)
	$(CP) $(TARGET).out _t
	$(STRIP) _t
	$(MKBTF) -o$@ -a0x8003 -c -tprog_2 \
		9.$(CPU_TYPE)._t
	$(RM) _t
# Source dependencies related
$(WC_SRC:%.C=%.c):
ifdef DEPENDENCIES_OUTPUT
$(DEPS):	; touch $(DEPS)
else
$(DEPS): $(SRC)	; $(MAKEDEPS) $@ $?
endif
include $(DEPS)

List 4 prog_3-main.c (reception side: receives message from prog_m2)
/*
 *	prog_3-main.c (T-Shell Sample/Main)
 *
 *	(C) Copyright 2003 by Personal Media Corporation.
 */


#include	<basic.h>
#include	<btron/outer.h>
#include	<tcode.h>
#include	<stdio.h>
#include	<stdlib.h>


/* Internal type declarations */
typedef	struct {        /* Format handed over from MSCRIPT */
	W	msg_type;       /* Same as MESSAGE.msg_type */
	W	msg_size;       /* Same as MESSAGE.msg_size */
	W	ext_size;       /* Ordinarily 0 in T-Shell */
	UB	msg_body[1];    /* Same as MESSAGE.msg_body */
} MSCRIPT_MSG;


/* Internal variables */
LOCAL	TC	PROG_1_NM[8] = {	/* [prog_3] */
			TK_p, TK_r, TK_o, TK_g, TK_USCR, TK_3,
			TNULL
		};


/* ---------------------------------------------------- main(cli style main) */
/*
 * main(cli style main)
 */
EXPORT	W	main(W ac, TC *av[])
{
	W	rv;
	W	l;
	W	pid;            /* Self process ID */
	W	mpid;           /* Message transmission source process ID*/
	W	msize;          /* Message size(byte units) */
	MESSAGE	dmy;        /* Message temporary reception use */
	MSCRIPT_MSG	*msg;   /* Received message */

	rv = 0;
	msg = NULL;

	/* Acquisition of self process ID */
	pid = b_prc_sts(0, NULL, NULL);
	if (pid < ER_OK) {
		rv = pid;
		printf("b_prc_sts : %d, %d\n", rv, rv >> 16);
		goto EXIT;
	}
	/* Create global name */
	rv = b_cre_nam(PROG_1_NM, pid, N_FORCE | DELEXIT);
	if (rv < ER_OK) {
		printf("b_cre_nam : %d, %d\n", rv, rv >> 16);
		goto EXIT;
	}

	/* Message reception wait */
	for ( ; ; ) {
		/* Free previous reception region */
		if (msg != NULL) {
			free(msg);
			msg = NULL;
		}

		/* Message temporary reception */
		mpid = b_rcv_msg(MM_TYPE7, &dmy, sizeof(MESSAGE), WAIT|NOCLR);
		if ((mpid < ER_OK) && (mpid != ER_PAR)) {
			/* Error occurred (ER_PAR ignore) */
			rv = mpid;
			printf("b_rcv_msg(dummy) : %d, %d\n", rv, rv >> 16);
			break;
		}

		/* Refuse if not application message 7 */
		if (dmy.msg_type != MS_TYPE7) {
			/* Not needed, so discard */
			b_clr_msg(MM_ALL, MM_ALL);
			continue;
		}

		/* Secure reception region */
		msize = dmy.msg_size + sizeof(W) * 2;
		msg = (MSCRIPT_MSG *)(malloc(msize));
		if (msg == NULL) {
			rv = ER_NOMEM;
			printf("memory allocation error.\n");
			break;
		}

		/* Reception */
		rv = b_rcv_msg(MM_TYPE7, (MESSAGE *)(msg), msize, NOWAIT|CLR);
		if (rv < ER_OK) {
			/* Error occurred */
			printf("b_rcv_msg(main) : %d, %d\n", rv, rv >> 16);
			break;
		} else if (rv != mpid) {
			/* Process of transmission source different (no normal startup) */
			printf("not match process ID\n");
			;	/* Return to loop */
		} else {
			/* Show the received contents and terminate */
			printf("sender PID       : %d\n", mpid);
			printf("all message size : %d\n", msize);
			printf("MESSAGE.msg_type : 0x%08x\n", msg->msg_type);
			printf("MESSAGE.msg_size : 0x%08x\n", msg->msg_size);
			printf("MESSAGE.ext_size : 0x%08x\n", msg->ext_size);
			printf("MESSAGE.msg_body :\n");
			for (l = 0; l < (msg->msg_size - sizeof(W)); l++) {
				printf("%02x ", msg->msg_body[l]);
			}
			printf("\n");
			break;
		}
	}

EXIT:
	if (msg != NULL) {
		free(msg);
	}
	b_ext_prc(rv);
	return rv;
}
--------------------
#
#	@(#)Makefile (prog_3)
#		    For use with GNU make
#
#	make method
#	 make
#		Create release use regular version
#	 make mode=debug
#		Create for use in debugging
#	 make clean
#		Delete all files created with make
#	 make install
#		Install in the prescribed place (for actual machine use only)
#
# Version
version = 0x1000
# Set release use to default
#mode =
# Source dependencies-related file (automatically created)
DEPS = Dependencies
DEPENDENCIES_OUTPUT := $(DEPS)
# Application standard rules
include $(BD)/bappl/etc/makerules
# ----------------------------------------------------------------------------
# Create target
TARGET = prog_3
# Search path of source file
S = ./ ../src
VPATH = $(S)
# Header file directory addition
HEADER := $(S) $(HEADER)
# Source file
SRC =	main.c
OBJ = $(addsuffix .o, $(basename $(SRC)))
WC_SRC = $(filter %.C, $(SRC))
DBFLAGS += -l
ifeq ($(mode), debug)
    CFLAGS += -Wall
endif
# ----------------------------------------------------------------------------
.PHONY: all clean
INST = $(addprefix $(TARGET), .bz .map)
INST2 = $(addprefix $(TARGET), .out)
all: $(INST)
$(TARGET).out: $(OBJ)
	$(LINK.o) $(LDOBJS) $^ $(LOADLIBES) $(LDLIBS) $(OUTPUT_OPTION)
clean:
	$(RM) $(OBJ)
	$(RM) $(WC_SRC:%.C=%.c) $(DBSRC)
	$(RM) $(INST) $(INST2) *.lst $(DEPS)
# Compression archive
$(TARGET).bz: $(INST2)
	$(CP) $(TARGET).out _t
	$(STRIP) _t
	$(MKBTF) -o$@ -a0x8003 -c -tprog_3 \
		9.$(CPU_TYPE)._t
	$(RM) _t
# Source dependencies related
$(WC_SRC:%.C=%.c):
ifdef DEPENDENCIES_OUTPUT
$(DEPS):	; touch $(DEPS)
else
$(DEPS): $(SRC)	; $(MAKEDEPS) $@ $?
endif
include $(DEPS)

List 5 prog_m2 (transmission side: transmits message to prog_3-main.c)
#
#	- prog_m2 -
#
#	(C) Copyright 2003 by Personal Media Corporation.
#

VERSION 3
#
# Start of program
#
PROLOGUE
	LOCAL	spid:I;
	LOCAL	data:I[1];

	# Acquisition of global name
	spid = getgnm("prog_3")
	IF (valid(spid))
		# Prepare contents to be transmitted
		data[0] = 0x12345678	# Suitable contents

		# Transmit message
		MSEND spid, 7, 4, data
	ELSE
		LOG "not found [prog_3]"
	ENDIF

	# Terminate
	FINISH
END

prog_m3
#
#	- prog_m3 -
#
#	(C) Copyright 2003 by Personal Media Corporation.
#
# Basically implemented in little endian
# prog_4, which becomes the opposite address for cooperation, must be executed first
#

# Basic declarations
VERSION 3				# Number of version used
DEBUG	0				# debug mode

# Constants
DEFINE	ER_OK        0

DEFINE	NULL         0
DEFINE	TNULL        0x0000

DEFINE	True	     1
DEFINE	False	     0
DEFINE	WND_XPOS     0              # Horizontal position
DEFINE	WND_YPOS     0              # Vertical position
DEFINE	WND_WIDTH    240            # Width
DEFINE	WND_HEIGHT   296            # Height

DEFINE	SMPL_MSGTYPE 7              # Message type used (MS_TYPE7 equivalent)
DEFINE	SMPL_MSGMASK 0x80           # Message type used (MM_TYPE7 equivalent)
DEFINE	PROG_4_NM    "prog_4"	    # Global name cooperation target sets
DEFINE	MSGRCV_TMOUT 5              # Request reply wait([sec units])

DEFINE	MSG_MAGIC0   ('S' - 0x2300) # Identifier
DEFINE	MSG_MAGIC1   ('M' - 0x2300) # Identifier
DEFINE	MSG_MAGIC2   ('P' - 0x2300) # Identifier
DEFINE	MSG_MAGIC3   ('L' - 0x2300) # Identifier

DEFINE	HD_MAGIC0    0
DEFINE	HD_MAGIC1    1
DEFINE	HD_MAGIC2    2
DEFINE	HD_MAGIC3    3
DEFINE	HD_TYPE0     7              # cmd_type UW type
DEFINE	HD_TYPE1     6
DEFINE	HD_TYPE2     5
DEFINE	HD_TYPE3     4
DEFINE	HD_ERR0      11             # err_code ERR(W) type
DEFINE	HD_ERR1      10
DEFINE	HD_ERR2      9
DEFINE	HD_ERR3      8

DEFINE	MTREQ_START  0x00010001     # Requests
DEFINE	MTREQ_FINISH 0x00010002
DEFINE	MTREQ_REDRAW 0x00010003
DEFINE	MTREQ_LINE   0x00010004
DEFINE	MTREQ_BOX    0x00010005
DEFINE	MTREQ_CIRCLE 0x00010006
DEFINE	MTREQ_TEXT   0x00010007

DEFINE	MTRSP_NORMAL 0x00020001     # Replies

DEFINE	REDRAW_TIME  100            # Redraw frequency time([msec] units)

# Global variables
VARIABLE	isBusy:B		# True : execution processing in progress
VARIABLE	act_type:I		# Execution contents(< 0 : processing undecided)
VARIABLE	sel_col:I		# Selected color(permutation number)
VARIABLE	sp:I[2]			# Start point
VARIABLE	ep:I[2]			# End point
VARIABLE	col_tbl:I[8]    # Table of colors


# ------------------------------------------------------------- prog_4 Calls(key)
#
# Find [prog_4] of call target
#
FUNC	srch_prog4()

	LOCAL	pid:I

	pid = getgnm(PROG_4_NM)
	IF (!(valid(pid)))
		pid = -1
	ENDIF

	EXIT pid

END

#
# Send request to prog_4 
#
FUNC	snd_msg(msg_dat:B[], msg_len:I)

	LOCAL	rv:I
	LOCAL	pid:I

	rv = 0

	# Find call target(confirm existence each time)
	pid = srch_prog4()
	IF (pid > ER_OK)
		# Send request
		MSEND pid, SMPL_MSGTYPE, msg_len, msg_dat
		IF ($ERR != ER_OK)
			rv = -$ERR
		ELSE
			rv = pid
		ENDIF
	ENDIF

	EXIT rv

END

#
# Receive reply from prog_4
#
FUNC	rcv_msg(ret_dat:B[], ret_len:I, ppid:I)

	LOCAL	rv:I
	LOCAL	pid:I
	LOCAL	type:I
	LOCAL	len:I
	LOCAL	buf:B[4095]

	rv = ER_OK
	$MMASK = SMPL_MSGMASK

	# Reception
	MRECV SMPL_MSGMASK, pid, type, len, buf: MSGRCV_TMOUT
	IF ($ERR != ER_OK)
		# Reception error
		rv = -$ERR
	ELSEIF (pid != ppid)
		# Message from something unrelated
		rv = 0
	ELSE
		# Return contents
		rv = len
		REPEAT len
			ret_dat[$CNT] = buf[$CNT]
			IF (($CNT + 1) >= ret_len)
				BREAK
			ENDIF
		ENDREPEAT
	ENDIF

	EXIT rv

END

#
# Send and receive messages with prog_4
#
FUNC	snr_msg(snd_dat:B[], snd_len:I, rcv_dat:B[], rcv_len:I, isPeriod:B)

	LOCAL	rv:I
	LOCAL	pid:I

	rv = ER_OK

	# Make busy temporarily
	IF (!(isPeriod))
		$PDS = 14
		isBusy = True
	ENDIF

	# Transmission
	pid = snd_msg(snd_dat, snd_len)
	IF (pid > ER_OK)
		# Reception (receive reply)
		rv = rcv_msg(rcv_dat, rcv_len, pid)
	ELSE
		# Failure
		rv = pid
	ENDIF

	# Release busy
	IF (!(isPeriod))
		$PDS = 0
		isBusy = False
	ENDIF

	EXIT rv

END

# ------------------------------------------ prog_4 Calls (processing of structures)
#
# Setting the header part
#
FUNC	head_setup(msg_dat:B[], type:I)

	# Setting the identifiers
	msg_dat[HD_MAGIC0] = MSG_MAGIC0
	msg_dat[HD_MAGIC1] = MSG_MAGIC1
	msg_dat[HD_MAGIC2] = MSG_MAGIC2
	msg_dat[HD_MAGIC3] = MSG_MAGIC3

	# Setting the type numbers
	msg_dat[HD_TYPE0] = ((type & 0xff000000) >> 24)
	msg_dat[HD_TYPE1] = ((type & 0x00ff0000) >> 16)
	msg_dat[HD_TYPE2] = ((type & 0x0000ff00) >>  8)
	msg_dat[HD_TYPE3] =  (type & 0x000000ff)

	EXIT

END

#
#  Setting int(W)-type contents in arbitrary positions
#
FUNC	set_intdat(msg_dat:B[], idx:I, val:I)

	msg_dat[idx + 3] = ((val & 0xff000000) >> 24)
	msg_dat[idx + 2] = ((val & 0x00ff0000) >> 16)
	msg_dat[idx + 1] = ((val & 0x0000ff00) >>  8)
	msg_dat[idx    ] =  (val & 0x000000ff)

	EXIT

END

#
# Setting H(UH)-type contents in arbitrary position
#
FUNC	set_worddat(msg_dat:B[], idx:I, val:I)

	msg_dat[idx + 1] = ((val & 0xff00) >> 8)
	msg_dat[idx    ] =  (val & 0x00ff)

	EXIT

END

#
# Setting TC string contents in arbitrary positions
#
#  Call
#	msg_dat[]:B : Contents you want to send
#	idx:I       : Position you want to set
#	dat_str[]:C : Contents you want to set
#	dat_len:I   : Contents length you want to set (TC units)
#
#  Return
#	None
#
FUNC	set_tcstrdat(msg_dat:B[], idx:I, dat_str:C[], dat_len:I)

	REPEAT dat_len
		msg_dat[idx + 1] = ((dat_str[$CNT] & 0xff00) >> 8)
		msg_dat[idx    ] =  (dat_str[$CNT] & 0x00ff)
		idx = idx + 2
	ENDREPEAT

	EXIT

END

#
# Collation of reply contents
#
FUNC	check_ret(msg_dat:B[])

	LOCAL	type:I

	type = -1			# Initial value type undefined

	# Compare identifiers
	IF ((msg_dat[HD_MAGIC0] == MSG_MAGIC0) && \
	    (msg_dat[HD_MAGIC1] == MSG_MAGIC1) && \
	    (msg_dat[HD_MAGIC2] == MSG_MAGIC2) && \
	    (msg_dat[HD_MAGIC3] == MSG_MAGIC3))
		# Acquire type
		type = ((msg_dat[HD_TYPE0] << 24) | \
			(msg_dat[HD_TYPE1] << 16) | \
			(msg_dat[HD_TYPE2] <<  8) | \
			(msg_dat[HD_TYPE3]      ))
	ENDIF

	EXIT type

END

#
# Acquire error code of reply contents
#
FUNC	get_errcode(msg_dat:B[])

	LOCAL	rv:I

	# Acquisition of contents (because multiplying by -1 is received as ERR)
	rv = -((msg_dat[HD_ERR0] << 24) | (msg_dat[HD_ERR1] << 16) | \
	       (msg_dat[HD_ERR2] <<  8) | (msg_dat[HD_ERR3]      ))

	EXIT rv

END

#
# Start of calls
#
FUNC	req_start()

	LOCAL	rv:I
	LOCAL	rtype:I
	LOCAL	sbuf:B[16]		# 4 + 4 + 2 * 4
	LOCAL	rbuf:B[12]		# 4 + 4 + 4

	rv = ER_OK

	# Preparing the transmission contents
	CALL head_setup(sbuf, MTREQ_START)
	CALL set_worddat(sbuf, 8, WORK_AREA.X)
	CALL set_worddat(sbuf, 10, WORK_AREA.Y)
	CALL set_worddat(sbuf, 12, WORK_AREA.X + WORK_AREA.W)
	CALL set_worddat(sbuf, 14, WORK_AREA.Y + WORK_AREA.H)

	# Transmission reception
	rv = snr_msg(sbuf, 16, rbuf, 12, False)
	IF (rv > 0)
		# Operation was successful, so confirm the reply contents
		rtype = check_ret(rbuf)
		IF (rtype == MTRSP_NORMAL)
			# Acquisition of the error code
			rv = get_errcode(rbuf)
		ENDIF
	ELSEIF (rv == 0)
		# Transmission reception failure (no opposite to cooperate)
		rv = -1
	ENDIF

	EXIT rv

END

#
# Terminate call
#
FUNC	req_finish()

	LOCAL	rv:I
	LOCAL	rtype:I
	LOCAL	sbuf:B[8]		# 4 + 4
	LOCAL	rbuf:B[12]		# 4 + 4 + 4

	rv = ER_OK

	# Prepare transmission contents
	CALL head_setup(sbuf, MTREQ_FINISH)

	# Transmission reception
	rv = snr_msg(sbuf, 8, rbuf, 12, False)
	IF (rv > 0)
		# Operation was successful, so confirm the reply contents
		rtype = check_ret(rbuf)
		IF (rtype == MTRSP_NORMAL)
			# Acquire the error code
			rv = get_errcode(rbuf)
		ENDIF
	ELSEIF (rv == 0)
		# Transmission reception failure(no opposite to cooperate)
		rv = -1
	ENDIF

	EXIT rv

END

#
# Request to redraw
#
FUNC	req_redraw(left:I, top:I, right:I, bottom:I, isPeriod:B)

	LOCAL	rv:I
	LOCAL	i:I
	LOCAL	rtype:I
	LOCAL	sbuf:B[16]		# 4 + 4 + 2 * 4
	LOCAL	rbuf:B[12]		# 4 + 4 + 4

	rv = ER_OK

	IF (left >= right)
		i = left
		left = right
		right = i
	ENDIF
	IF (top >= bottom)
		i = top
		top = bottom
		bottom = i
	ENDIF

	# Prepare transmission contents
	CALL head_setup(sbuf, MTREQ_REDRAW)
	CALL set_worddat(sbuf, 8, left)
	CALL set_worddat(sbuf, 10, top)
	CALL set_worddat(sbuf, 12, right)
	CALL set_worddat(sbuf, 14, bottom)

	# Transmission reception
	rv = snr_msg(sbuf, 16, rbuf, 12, isPeriod)
	IF (rv > 0)
		# Operation was successful, so confirm the reply contents
		rtype = check_ret(rbuf)
		IF (rtype == MTRSP_NORMAL)
			# Error code acquisition
			rv = get_errcode(rbuf)
		ENDIF
	ELSEIF (rv == 0)
		# Transmission reception failure (no opposite to cooperate)
		rv = -1
	ENDIF

	EXIT rv

END

#
# Draw straight line
#
FUNC	req_line(spX:I, spY:I, epX:I, epY:I)

	LOCAL	rv:I
	LOCAL	rtype:I
	LOCAL	sbuf:B[20]		# 4 + 4 + 2 * 2 + 2 * 2 + 4
	LOCAL	rbuf:B[12]		# 4 + 4 + 4

	rv = ER_OK

	# Prepare transmission contents
	CALL head_setup(sbuf, MTREQ_LINE)
	CALL set_worddat(sbuf, 8, spX)
	CALL set_worddat(sbuf, 10, spY)
	CALL set_worddat(sbuf, 12, epX)
	CALL set_worddat(sbuf, 14, epY)
	CALL set_intdat(sbuf, 16, col_tbl[sel_col])

	# Transmission reception
	rv = snr_msg(sbuf, 20, rbuf, 12, False)
	IF (rv > 0)
		# Operation was successful, so confirm the reply contents
		rtype = check_ret(rbuf)
		IF (rtype == MTRSP_NORMAL)
			# Error code acquisition
			rv = get_errcode(rbuf)
		ENDIF
	ELSEIF (rv == 0)
		# Transmission reception failure (no opposite to cooperate)
		rv = -1
	ENDIF

	EXIT rv

END

#
# Draw rectangular frame
#
FUNC	req_box(left:I, top:I, right:I, bottom:I)

	LOCAL	rv:I
	LOCAL	i:I
	LOCAL	rtype:I
	LOCAL	sbuf:B[20]		# 4 + 4 + 2 * 4 + 4
	LOCAL	rbuf:B[12]		# 4 + 4 + 4

	rv = ER_OK

	IF (left >= right)
		i = left
		left = right
		right = i
	ENDIF
	IF (top >= bottom)
		i = top
		top = bottom
		bottom = i
	ENDIF

	# Prepare transmission contents
	CALL head_setup(sbuf, MTREQ_BOX)
	CALL set_worddat(sbuf, 8, left)
	CALL set_worddat(sbuf, 10, top)
	CALL set_worddat(sbuf, 12, right)
	CALL set_worddat(sbuf, 14, bottom)
	CALL set_intdat(sbuf, 16, col_tbl[sel_col])

	# Transmission reception
	rv = snr_msg(sbuf, 20, rbuf, 12, False)
	IF (rv > 0)
		# Operation was successful, so confirm the reply contents
		rtype = check_ret(rbuf)
		IF (rtype == MTRSP_NORMAL)
			# Error code acquisition
			rv = get_errcode(rbuf)
		ENDIF
	ELSEIF (rv == 0)
		# Transmission reception failure (no opposite to cooperate)
		rv = -1
	ENDIF

	EXIT rv

END

#
# Draw circle/ellipse
#
FUNC	req_circle(left:I, top:I, right:I, bottom:I)

	LOCAL	rv:I
	LOCAL	i:I
	LOCAL	rtype:I
	LOCAL	sbuf:B[20]		# 4 + 4 + 2 * 4 + 4
	LOCAL	rbuf:B[12]		# 4 + 4 + 4

	rv = ER_OK

	IF (left >= right)
		i = left
		left = right
		right = i
	ENDIF
	IF (top >= bottom)
		i = top
		top = bottom
		bottom = i
	ENDIF

	# Prepare transmission contents
	CALL head_setup(sbuf, MTREQ_CIRCLE)
	CALL set_worddat(sbuf, 8, left)
	CALL set_worddat(sbuf, 10, top)
	CALL set_worddat(sbuf, 12, right)
	CALL set_worddat(sbuf, 14, bottom)
	CALL set_intdat(sbuf, 16, col_tbl[sel_col])

	# Transmission reception
	rv = snr_msg(sbuf, 20, rbuf, 12, False)
	IF (rv > 0)
		# Operation was successful, so confirm the reply contents
		rtype = check_ret(rbuf)
		IF (rtype == MTRSP_NORMAL)
			# Error code acquisition
			rv = get_errcode(rbuf)
		ENDIF
	ELSEIF (rv == 0)
		# Transmission reception error (no opposite to cooperate)
		rv = -1
	ENDIF

	EXIT rv

END

#
# Draw character string
#
FUNC	req_text(pX:I, pY:I)

	LOCAL	rv:I
	LOCAL	rtype:I
	LOCAL	sbuf:B[530]		# 4 + 4 + 2 * 2 + 4 + arbitrary ((256+1) * 2)
	LOCAL	rbuf:B[12]		# 4 + 4 + 4

	# Prepare transmission contents
	CALL head_setup(sbuf, MTREQ_TEXT)
	CALL set_worddat(sbuf, 8, pX)
	CALL set_worddat(sbuf, 10, pY)
	CALL set_intdat(sbuf, 12, col_tbl[sel_col])
	CALL set_tcstrdat(sbuf, 16, TB_TEXT.TX, TB_TEXT.TL)
	CALL set_worddat(sbuf, 16 + TB_TEXT.TL * 2, TNULL)

	# Transmission reception
	rv = snr_msg(sbuf, 16 + (TB_TEXT.TL + 1) * 2, rbuf, 12, False)
	IF (rv > 0)
		# Operation was successful, so confirm the reply contents
		rtype = check_ret(rbuf)
		IF (rtype == MTRSP_NORMAL)
			# Error code acquisition
			rv = get_errcode(rbuf)
		ENDIF
	ELSEIF (rv == 0)
		# Transmission reception failure (no opposite to cooperate)
		rv = -1
	ENDIF

	EXIT rv

END

# ------------------------------------------ Segment operations(basic parts types)
#
# MS_PARTS  press (event loop)
#
FUNC	press_MS_PARTS(seg:S)

	LOCAL	flg:B

	flg = False

	IF ($WACT == 0)
		# Synchronization not carried out in window switching
	ELSE
		# Overlapping pictures during a press
		MOVE MS_FRAME_P:seg.X, seg.Y, @

		# Event loop during press
		REPEAT
			IF (($PDX > seg.X) && ($PDX < seg.X + seg.W) && \
			    ($PDY > seg.Y) && ($PDY < seg.Y + seg.H))
				# Inside the parts region
				IF (!(flg))
					flg = True
					APPEAR MS_FRAME_P
				ENDIF
			ELSE
				# Outside the parts region
				flg = False
				DISAPPEAR MS_FRAME_P
			ENDIF

			IF ($PDB == 0)
				# Released the PD
				DISAPPEAR MS_FRAME_P
				BREAK
			ENDIF
		ENDREPEAT
		DISAPPEAR MS_FRAME_P
	ENDIF

	EXIT flg

END

#
# Press processing (event loop) of WS_PARTS
#
FUNC	press_WS_PARTS(seg:S, oseg:S, oimg:S, iimg:S)

	LOCAL	flg:B

	flg = False

	IF ($WACT == 0)
		# Synchronization not carried out in window switching
	ELSE
		# Overlapping pictures during press
		MOVE oimg:oseg.X, oseg.Y, @
		MOVE iimg:seg.X, seg.Y + 4, @

		# Event loop during press
		REPEAT
			IF (($PDX > seg.X) && ($PDX < seg.X + seg.W) && \
			    ($PDY > seg.Y) && ($PDY < seg.Y + seg.H))
				# Inside the parts region
				IF (!(flg))
					flg = True
					APPEAR oimg
					APPEAR iimg
				ENDIF
			ELSE
				# Outside the parts region
				flg = False
				DISAPPEAR oimg
				DISAPPEAR iimg
			ENDIF
			IF ($PDB == 0)
				# Released the PD
				DISAPPEAR oimg
				DISAPPEAR iimg
				BREAK
			ENDIF
		ENDREPEAT
		DISAPPEAR oimg
		DISAPPEAR iimg
	ENDIF

	EXIT flg

END

#
# Execution processing part of each MS_PARTS
#
ACTION	act_MS_DRAW(seg:S, idx:I, x:I, y:I) PRESS MS_LINE, MS_BOX, MS_CIRCLE, MS_TEXT

	IF (isBusy)
		EXIT
	ENDIF

	IF (press_MS_PARTS(seg))
		act_type = idx
	ENDIF

	EXIT

END

#
# Execution processing part of TB_PARTS used to input character strings
#
ACTION	act_TB_TEXT(seg:S, idx:I, x:I, y:I) CLICK TB_TEXT

	KINPUT seg, x, y

	EXIT

END

#
# Execution part of WS_PARTS for color selection
#
ACTION	act_WS_COLOR(seg:S, idx:I, x:I, y:I) PRESS WS_BLACK, WS_BLUE, WS_RED, 
        WS_MAGENTA, WS_GREEN, WS_CYAN, WS_YELLOW, WS_WHITE # Join with above line

	IF (isBusy)
		EXIT
	ENDIF

	IF (idx == sel_col)
		CALL press_WS_PARTS(seg, WS_FRAME, WS_FRAME_P, AS_IND_ONP)
	ELSE
		IF (press_WS_PARTS(seg, WS_FRAME, WS_FRAME_P, AS_IND_OFFP))
			sel_col = idx
			MOVE AS_IND_ON:seg.X, seg.Y + 4, @
		ENDIF
	ENDIF

	EXIT

END

#
# Execution processing part of work area
#
ACTION	act_WORK_AREA(seg:S, idx:I, x:I, y:I) CLICK WORK_AREA

	IF ((isBusy) || (act_type < 0))
		EXIT
	ENDIF

	x = x - seg.X
	y = y - seg.Y
	IF (act_type == 3)
		# Character string immediately executed with a click
		sp[0] = x
		sp[1] = y
		CALL req_text(sp[0], sp[1])
		act_type = -1
	ELSE
		# Otherwise, two points specified
		IF (act_type < 10)
			# Start point_
			sp[0] = x
			sp[1] = y
			act_type = act_type + 10
		ELSE
			# End point
			ep[0] = x
			ep[1] = y
			SWITCH (act_type)
				CASE 10
					# Straight line
					CALL req_line(sp[0],sp[1],ep[0],ep[1])
					BREAK
				CASE 11
					# Rectangular frame
					CALL req_box(sp[0],sp[1],ep[0],ep[1])
					BREAK
				CASE 12
					# Circle/ellipse
					CALL req_circle(sp[0],sp[1],ep[0],ep[1])
					BREAK
			ENDCASE
			act_type = -1
		ENDIF
	ENDIF

	EXIT

END

# ------------------------------------------------------------------ Main processes
#
# Initialization of internal state
#
FUNC	init_proc()

	LOCAL	rv:I

	rv = ER_OK

	isBusy = False
	act_type = -1
	sel_col = 0
	sp[0] = 0
	sp[1] = 0
	ep[0] = 0
	ep[1] = 0
	col_tbl[0] = 0x10000000		# Black
	col_tbl[1] = 0x100000ff		# Blue
	col_tbl[2] = 0x10ff0000		# Red
	col_tbl[3] = 0x10ff00ff		# Magenta
	col_tbl[4] = 0x1000ff00		# Green
	col_tbl[5] = 0x1000ffff		# Cyan
	col_tbl[6] = 0x10ffff00		# Yellow
	col_tbl[7] = 0x10ffffff		# White

	# Initialize processes of call targets
	rv = req_start()

	EXIT rv

END

#
# Initialization of each segment
#
FUNC	init_seg()

	LOCAL	rv:I

	rv = ER_OK

	# Stop display
	UPDATE 0

	# Initialization of the contents of each segments
	TEXT TB_TEXT, ""

	SWITCH (sel_col)
		CASE 0
			MOVE AS_IND_ON:WS_BLACK.X, WS_BLACK.Y + 4, @
			BREAK
		CASE 1
			MOVE AS_IND_ON:WS_BLUE.X, WS_BLUE.Y + 4, @
			BREAK
		CASE 2
			MOVE AS_IND_ON:WS_RED.X, WS_RED.Y + 4, @
			BREAK
		CASE 3
			MOVE AS_IND_ON:WS_MAGENTA.X, WS_MAGENTA.Y + 4, @
			BREAK
		CASE 4
			MOVE AS_IND_ON:WS_GREEN.X, WS_GREEN.Y + 4, @
			BREAK
		CASE 5
			MOVE AS_IND_ON:WS_CYAN.X, WS_CYAN.Y + 4, @
			BREAK
		CASE 6
			MOVE AS_IND_ON:WS_YELLOW.X, WS_YELLOW.Y + 4, @
			BREAK
		CASE 7
			MOVE AS_IND_ON:WS_WHITE.X, WS_WHITE.Y + 4, @
			BREAK
	ENDCASE

	# Display each segment
	APPEAR AS_IND_ON
	APPEAR MS_LINE
	APPEAR MS_BOX
	APPEAR MS_CIRCLE
	APPEAR MS_TEXT
	APPEAR TB_TEXT
	APPEAR WS_BLACK
	APPEAR WS_BLUE
	APPEAR WS_RED
	APPEAR WS_MAGENTA
	APPEAR WS_GREEN
	APPEAR WS_CYAN
	APPEAR WS_YELLOW
	APPEAR WS_WHITE
	APPEAR WS_FRAME
	APPEAR WORK_AREA

	# Reopen display
	UPDATE 1

	CALL req_redraw(0, 0, 0, 0, False)

	# Execute and put in place the text box
	KINPUT TB_TEXT

	EXIT rv

END

#
# Periodic redrawing
#
MACTION	period_redraw()

	REPEAT
		IF (REDRAW_TIME > 0)
			SLEEP REDRAW_TIME
		ENDIF

		# Issue redraw request
		CALL req_redraw(0, 0, 0, 0, True)
	ENDREPEAT

	# Doesn't come here
	EXIT

END

#
# Main processing part of application
#
FUNC	main_proc()

	LOCAL	rv:I

	# Initialization processing
	rv = init_proc()
	IF (rv != ER_OK)
		FINISH	# Crash
	ENDIF
	rv = init_seg()
	IF (rv != ER_OK)
		FINISH	# Crash
	ENDIF

	# Make carry out periodic redrawing
	EXECUTE period_redraw()

	EXIT
END

# --------------------------------- Basic processes(startup/termination processing)
#
# Startup processing
#
PROLOGUE

	# Adjust window position
	IF (($WDX != WND_XPOS) || ($WDY != WND_YPOS))
		WMOVE WND_XPOS, WND_YPOS
	ENDIF

	# Adjust window size
	IF (($WDW != WND_WIDTH) || ($WDH != WND_HEIGHT))
		WSIZE WND_WIDTH, WND_HEIGHT
	ENDIF

	# Start
	CALL main_proc()

END

#
# Termination processing
#
EPILOGUE

	# Stop periodic processes
	TERMINATE

	# Stop call targets
#	CALL req_finish()

	WSAVE

END

prog_4-main.c
/*
 *	prog_4-main.c (T-Shell sample/Main)
 *
 *	(C) Copyright 2003 by Personal Media Corporation.
 */


#include	"sample.h"


/* Internal variables */
LOCAL	TC	PROG_4_NM[8] = {	/* [prog_4] */
			TK_p, TK_r, TK_o, TK_g, TK_USCR, TK_4,
			TNULL
		};


/* Internal function prototypes */
LOCAL	ERR	init_proc(VOID);
LOCAL	VOID	fin_proc(VOID);


/* ------------------------------------------------------ Internal functions */
/*
 * Initialization processing
 */
LOCAL	ERR	init_proc(VOID)
{
	ERR	er;
	W	pid;

	er = ER_OK;

	/* Acquisition of self process ID */
	pid = b_prc_sts(0, NULL, NULL);
	printf("b_prc_sts : %d, %d\n", pid, pid >> 16);

	/* Set global name */
	er = b_cre_nam(PROG_4_NM, pid, N_CREATE | DELEXIT);
	if (er < ER_OK) {
		printf("b_cre_nam : %d, %d\n", er, er >> 16);
		goto EXIT;
	}

	/* Initialization of drawing processes */
	er = draw_init();
	if (er < ER_OK) {
		printf("draw_init : %d, %d\n", er, er >> 16);
	}

EXIT:
	return er;
}


/*
 * Termination processing
 */
LOCAL	VOID	fin_proc(VOID)
{
	/* Resource freeing of drawing processes */
	draw_fin();

	return;
}


/* ---------------------------------------------------- main(cli style main) */
/*
 * main (cli style main)
 */
EXPORT	W	main(W ac, TC *av[])
{
	W	rv;

	rv = 0;

	/* Initialization processing */
	rv = init_proc();
	if (rv >= ER_OK) {
		/* Start event loop */
		rv = event_loop();
	}

	/* Termination processing */
	fin_proc();

	b_ext_prc(rv);
	return rv;
}
--------------------
/*
 *	prog_4-draw.c (T-Shell Sample/Drawing Processes)
 *
 *	(C) Copyright 2003 by Personal Media Corporation.
 */


#include	"sample.h"


/* Internal macros */
#define	DEF_BMP		(BMP){1, 0, 0x0000, {{0, 0, 0, 0}}, {NULL}}
#define	rectwidth(r)	((r).c.right - (r).c.left)
#define	rectheight(r)	((r).c.bottom - (r).c.top)


/* Internal variables */
LOCAL	W       gid = -1;       /* Drawing environment ID of the drawing target	*/
LOCAL	W       bgid = 1;       /* Drawing environment ID for work use */
LOCAL	BMP     bmp = DEF_BMP;  /* Bitmap for work use */
LOCAL	PAT     pat;            /* Patterns for color specification use */
LOCAL	RECT    dr;             /* Rectangular region of the display address */


/* Internal function prototype */
LOCAL	ERR	disp_buffer(VOID);


/* ---------------------------------------------------------------- Internal functions */
/*
 * Making the contents of the work region reflect on the screen
 */
LOCAL	ERR	disp_buffer(VOID)
{
	ERR	er;

	er = b_gcop_bmp(bgid, &bmp.bounds, gid, &dr, NULL, G_STORE | G_CVCOLOR | G_CVFORM);
	if (er < ER_OK) {
		printf("b_gcop_bmp : %d, %d\n", er, er >> 16);
	}

	return er;
}




/* ================================================================ Global functions */
/* -------------------------------------------------------------- Main processes */
/*
 * Initialization processing (mainly equivalent to a constructor)
 */
EXPORT	ERR	draw_init(VOID)
{
	ERR	er;

	er = ER_OK;

	/* Initialize each variable */
	gid = -1;
	bgid = -1;
	bmp = DEF_BMP;
	dr = (RECT){{0, 0, 0, 0}};

	/* Set patterns */
	pat = (PAT){{0, 16, 16, 0x10000000, 0x80000000, FILL100}};
	return er;
}


/*
 * Termination processing (Mainly equivalent to a destructor)
 */
EXPORT	VOID	draw_fin(VOID)
{
	/* Free each resource */
	if (bgid >= 0) {
		b_gcls_env(bgid);
	}
	if (bmp.baseaddr[0] != NULL) {
		free(bmp.baseaddr[0]);
	}

	/* Return variables to initials */
	gid = -1;
	bgid = -1;
	bmp = DEF_BMP;
	dr = (RECT){{0, 0, 0, 0}};

	return;
}


/* ---------------------------------------------------------------- Drawing related */
/*
 * Creation of the work region
 */
EXPORT	ERR	draw_gen_workarea(W pgid, RECT r)
{
	ERR	er;
	CSPEC	csp = {0x0001, {0x1008, 0x0808, 0x0008, 0}, NULL};

	er = ER_OK;

	/* Remember display address */
	gid = pgid;
	dr = r;

	/* Create work region (create environment of 16.70 million colors) */
	bmp.planes = 1;
	bmp.pixbits = 0x2018;
	bmp.bounds.p.lefttop = (PNT){0, 0};
	bmp.bounds.c.right = rectwidth(r);
	bmp.bounds.c.bottom = rectheight(r);
	bmp.rowbytes = rectwidth(r) << 2;
	bmp.baseaddr[0] = (UB *)(malloc(bmp.rowbytes * rectheight(r)));
	printf("bmp.bounds : %d, %d, %d, %d\n", bmp.bounds.c.left, bmp.bounds.c.top, bmp.bounds.c.right, bmp.bounds.c.bottom);
	if (bmp.baseaddr[0] == NULL) {
		er = ER_NOMEM;
		printf("memory allocation error.\n");
	} else {
		/* Create drawing environment of the work region */
		bgid = b_gopn_mem(NULL, &bmp, (B *)(&csp));
		printf("b_gopn_mem : %d, %d\n", bgid, bgid >> 16);
		if (bgid < ER_OK) {
			er = bgid;
		} else {
			/* Initialize contents (paint over with white) */
			b_gfil_rec(bgid, bmp.bounds, WHITE0, 0, G_STORE);

			/* Reflect in display */
			er = disp_buffer();
		}
	}


	return er;
}


/*
 * Redraw
 */
EXPORT	ERR	draw_redraw(RECT r)
{
	ERR	er;
	RECT	vr;

	er = ER_OK;

	/* Remember original display region */
	b_gget_vis(gid, &vr);

	/* Switch to redraw region */
/*	printf("r : %d, %d, %d, %d\n", r.c.left, r.c.top, r.c.right, r.c.bottom); */
	if ((r.c.left < r.c.right) && (r.c.top < r.c.bottom)) {
		b_gset_vis(gid, r);
	}

	/* Draw contents */
	er = disp_buffer();

	/* Return display region */
	b_gset_vis(gid, vr);

	return er;
}


/*
 * Draw straight line
 */
EXPORT	ERR	draw_line(PNT sp, PNT ep, COLOR col)
{
	ERR	er;

	er = ER_OK;

	/* Set color */
	pat.spat.fgcol = col;

	/* Draw line */
	printf("sp : %d, %d    ep : %d, %d    col : 0x%08x\n", sp.x, sp.y, ep.x, ep.y, col);
	er = b_gdra_lin(bgid, sp, ep, 0x0001, &pat, G_STORE);
	if (er < ER_OK) {
		printf("b_gdra_lin : %d, %d\n", er, er >> 16);
	} else {
		/* Reflect in display */
		er = disp_buffer();
	}

	return er;
}


/*
 * Draw rectangular frame
 */
EXPORT	ERR	draw_box(RECT r, COLOR col)
{
	ERR	er;

	er = ER_OK;

	/* Set color */
	pat.spat.fgcol = col;

	/* Draw line */
	printf("r : %d, %d, %d, %d    col : 0x%08x\n", r.c.left, r.c.top, r.c.right, r.c.bottom, col);
	er = b_gfra_rec(bgid, r, 0x0001, &pat, 0, G_STORE);
	if (er < ER_OK) {
		printf("b_gfra_rec : %d, %d\n", er, er >> 16);
	} else {
		/* Reflect in display */
		er = disp_buffer();
	}

	return er;
}


/*
 * Draw circle/ellipse
 */
EXPORT	ERR	draw_circle(RECT r, COLOR col)
{
	ERR	er;

	er = ER_OK;

	/* Set color */
	pat.spat.fgcol = col;

	/* Draw line */
	printf("r : %d, %d, %d, %d    col : 0x%08x\n", r.c.left, r.c.top, r.c.right, r.c.bottom, col);
	er = b_gfra_ovl(bgid, r, 0x0001, &pat, 0, G_STORE);
	if (er < ER_OK) {
		printf("b_gfra_ovl : %d, %d\n", er, er >> 16);
	} else {
		/* Reflect in display */
		er = disp_buffer();
	}

	return er;
}


/*
 * Draw character string
 */
EXPORT	ERR	draw_text(PNT p, COLOR col, const TC *str)
{
	ERR	er;
	WERR	rv;

	er = ER_OK;

	/* Set color */
	b_gset_chc(bgid, col, 0x80000000);

	/* Switch language/script specification */
	b_gset_scr(bgid, TSC_SYS);

	/* Draw character string */
	printf("p : %d, %d    col : 0x%08x\n", p.x, p.y, col);
	printf("text : %S\n", str);
	rv = b_gdra_stp(bgid, p.x, p.y + 16, (TC *)(str), tc_strlen(str), G_STORE);
	if (rv < ER_OK) {
		er = rv;
		printf("b_gdra_stp : &%d, %d\n", er, er >> 16);
	} else {
		/* Reflect in display */
		er = disp_buffer();
	}

	return er;
}
--------------------
/*
 *	prog_4-evt.c (T-Shell Sample/Event Loop)
 *
 *	(C) Copyright 2003 by Personal Media Corporation.
 */


#include	"sample.h"


/* Internal function prototype */
LOCAL	Bool	chk_header(const MSG_ANY *msg);


/* Global variable */
EXPORT	Bool	doloop = False;		/* True : Internal functions */


/* ---------------------------------------------------------------- Internal functions */
/*
 * Confirm the header
 */
LOCAL	Bool	chk_header(const MSG_ANY *msg)
{
	Bool	flg;

	flg = False;			/* Initial value does not match */

	/* Confirmation of message type used */
	if (msg->hd.msg_type != SMPL_MSGTYPE) {
		printf("not match message type.\n");
		goto EXIT;
	}

	/* Confirmation of minimum length */
	if (msg->hd.msg_size < (sizeof(MSG_HEAD) - offsetof(MSG_HEAD,ext_size))) {
		printf("not enough size.\n");
		goto EXIT;
	}

	/* Collation of identifiers */
	if ((msg->hd.magic[0] != MSG_MAGIC0) ||
	    (msg->hd.magic[1] != MSG_MAGIC1) ||
	    (msg->hd.magic[2] != MSG_MAGIC2) ||
	    (msg->hd.magic[3] != MSG_MAGIC3)) {
		printf("not match magic.\n");
		goto EXIT;
	}

	/* Recognition */
	flg = True;

EXIT:
	return flg;
}


/* -------------------------------------------------------------- Main processes */
/*
 * Event loop of message reception wait
 */
EXPORT	WERR	event_loop(VOID)
{
	WERR	rv;
	W	pid;
	MSG_ANY	dmy;			/* Temporary reception use */

	rv = ER_OK;

	doloop = True;
	do {
		/* Temporary reception */
		pid = b_rcv_msg(SMPL_MSGMASK, (MESSAGE *)(&dmy), sizeof(dmy), WAIT | NOCLR);
		if ((pid < ER_OK) && (pid != ER_PAR)) {
			rv = pid;
			printf("b_rcv_msg : %d, %d\n", rv, rv >> 16);
			break;
		}

		/* Verification of header part */
		if (chk_header(&dmy)) {
			/* Main reception */
			rv = recv_main(&dmy);
			if (rv < ER_OK) {
				printf("recv_main : %d, %d\n", rv);
			}
		} else {
			/* Discard as it does not seem related */
			b_clr_msg(MM_ALL, MM_ALL);
			continue;
		}
	} while (doloop);

	return rv;
}
--------------------
/*
 *	prog_4-gval.h (T-Shell Sample/Global Variable Declaration)
 *
 *	(C) Copyright 2003 by Personal Media Corporation.
 */


#ifndef	_PROG_4_GVAL_H
#define	_PROG_4_GVAL_H


/* from main.c */

/* from evt.c */
IMPORT	Bool	doloop;			/* True : continue event loop */

/* from rcvmsg.c */

/* from sndmsg.c */

/* from draw.c */

#endif	/* _PROG_4_GVAL_H */
--------------------
/*
 *	prog_4-msg.h (T-Shell Sample/Message Definitions)
 *
 *	(C) Copyright 2003 by Personal Media Corporation.
 */


#ifndef	_PROG_4_MSG_H
#define	_PROG_4_MSG_H


/* ---------------------------------------------------------------- Basic definitions */
#define	SMPL_MSGTYPE	MS_TYPE7
#define	SMPL_MSGMASK	MM_TYPE7

#define	MSG_MAGIC0	'S'		/* Identifier */
#define	MSG_MAGIC1	'M'
#define	MSG_MAGIC2	'P'
#define	MSG_MAGIC3	'L'

#define	MSG_TYPEID_MASK	0xffff0000
#define	MSG_OPE_MASK	0x0000ffff

enum MSG_TYPEID {
	MSG_TYPEID_REQ = 0x00010000,
	MSG_TYPEID_RSP = 0x00020000
};

typedef	struct {        /* Header part*/
	W	msg_type;       /* Same as MESSAGE.msg_type */
	W	msg_size;       /* Same as MESSAGE.msg_size */
	W	ext_size;
	UB	magic[4];       /* Identifier */
	UW	type;			/* Call contents classification */
} MSG_HEAD;

typedef	struct {        /* Arbitrary format*/
	MSG_HEAD	hd;     /* Header part */
	UB		dt[1];      /* Some kind of data string */
} MSG_ANY;


/* ------------------------------------------------------------------ Requests */
enum MSGTYPE_REQ {			/* Classification numbers of requests */
	MSGTYPE_REQ_START  = 0x00010001,
	MSGTYPE_REQ_FINISH = 0x00010002,
	MSGTYPE_REQ_REDRAW = 0x00010003,
	MSGTYPE_REQ_LINE   = 0x00010004,
	MSGTYPE_REQ_BOX    = 0x00010005,
	MSGTYPE_REQ_CIRCLE = 0x00010006,
	MSGTYPE_REQ_TEXT   = 0x00010007
};

typedef	struct {        /* Call start */
	MSG_HEAD	hd;     /* Header part */
	RECT		r;      /* Rectangular range corresponding to work region */
} MSG_REQ_START;

typedef	struct {        /* Call termination (process termination) */
	MSG_HEAD	hd;     /* Header part */
	;
} MSG_REQ_FINISH;

typedef	struct {        /* Redraw request */
	MSG_HEAD	hd;     /* Header part */
	RECT		r;      /* Redraw region (entire, if empty) */
} MSG_REQ_REDRAW;

typedef	struct {        /* Straight line */
	MSG_HEAD	hd;     /* Header part */
	PNT		sp;         /* Start point */
	PNT		ep;         /* End point */
	COLOR		col;    /* Color (absolute color specification desirable) */
} MSG_REQ_LINE;

typedef	struct {        /* Rectangular frame */
	MSG_HEAD	hd;     /* Header part */
	RECT		r;      /* Rectangular shape range */
	COLOR		col;    /* Color (absolute color specification desirable) */
} MSG_REQ_BOX;

typedef	struct {        /* Circle/ellipse */
	MSG_HEAD	hd;     /* Header part */
	RECT		r;      /* Rectangular region (external connect) */
	COLOR		col;    /* Color (absolute color specification desirable) */
} MSG_REQ_CIRCLE;

typedef	struct {
	MSG_HEAD	hd;     /* Header part */
	PNT		p;          /* Drawing start point (upper left) */
	COLOR		col;    /* Color (absolute color specification desirable) */
	TC		str[1];     /* Character string (Actually, variable length/TNULL terminus) */
} MSG_REQ_TEXT;

typedef	union {         /* Union */
	MSG_REQ_START	start;
	MSG_REQ_FINISH	finish;
	MSG_REQ_REDRAW	redraw;
	MSG_REQ_LINE	line;
	MSG_REQ_BOX	box;
	MSG_REQ_CIRCLE	circle;
	MSG_REQ_TEXT	text;
} MSG_REQ;


/* ------------------------------------------------------------------ Replies */
enum MSGTYPE_RSP {			/* Classification numbers of replies */
	MSGTYPE_RSP_NORMAL = 0x00020001
};

typedef	struct {        /* Normal reply */
	MSG_HEAD	hd;     /* Header part */
	ERR		er;         /* Error code */
} MSG_RSP_NORMAL;

typedef	union {         /* Union */
	MSG_RSP_NORMAL	normal;
} MSG_RSP;

#endif	/* _PROG_4_MSG_H */
--------------------
/*
 *	prog_4-proto.h (T-Shell Sample/Global Function Prototype Declarations)
 *
 *	(C) Copyright 2003 by Personal Media Corporation.
 */


#ifndef	_PROG_4_PROTO_H
#define	_PROG_4_PROTO_H


/* from main.c */

/* from evt.c */
IMPORT	WERR	event_loop(VOID);

/* from rcvmsg.c */
IMPORT	ERR	recv_main(const MSG_ANY *dmy);

/* from sndmsg.c */
IMPORT	ERR	send_rsp_normal(W pid, ERR err);

/* from draw.c */
IMPORT	ERR	draw_init(VOID);
IMPORT	VOID	draw_fin(VOID);
IMPORT	ERR	draw_gen_workarea(W pgid, RECT r);
IMPORT	ERR	draw_redraw(RECT r);
IMPORT	ERR	draw_line(PNT sp, PNT ep, COLOR col);
IMPORT	ERR	draw_box(RECT r, COLOR col);
IMPORT	ERR	draw_circle(RECT r, COLOR col);
IMPORT	ERR	draw_text(PNT p, COLOR col, const TC *str);

#endif	/* _PROG_4_PROTO_H */
--------------------
/*
 *	prog_4-rcvmsg.c (T-Shell Sample/Message Reception Processing Part)
 *
 *	(C) Copyright 2003 by Personal Media Corporation.
 */


#include	"sample.h"


/* Internal type declarations */
typedef	struct {        /* Request processing function table */
	UW	type;           /* Request classifications */
	FUNCP	fn;         /* Execution functions */
} RCVFN;


/* Internal function prototypes */
LOCAL	ERR	req_start(W pid, const MSG_REQ *msg);
LOCAL	ERR	req_finish(W pid, const MSG_REQ *msg);
LOCAL	ERR	req_redraw(W pid, const MSG_REQ *msg);
LOCAL	ERR	req_line(W pid, const MSG_REQ *msg);
LOCAL	ERR	req_box(W pid, const MSG_REQ *msg);
LOCAL	ERR	req_circle(W pid, const MSG_REQ *msg);
LOCAL	ERR	req_test(W pid, const MSG_REQ *msg);


/* Request processing functions table */
LOCAL	RCVFN	rcvfn_tbl[] = {
			{MSGTYPE_REQ_START, req_start},
			{MSGTYPE_REQ_FINISH, req_finish},
			{MSGTYPE_REQ_REDRAW, req_redraw},
			{MSGTYPE_REQ_LINE, req_line},
			{MSGTYPE_REQ_BOX, req_box},
			{MSGTYPE_REQ_CIRCLE, req_circle},
			{MSGTYPE_REQ_TEXT, req_test},
			{0xffffffff, NULL}	/* Terminus */
		};


/* ---------------------------------------------------------------- Internal functions */
/*
 * Call start
 */
LOCAL	ERR	req_start(W pid, const MSG_REQ *msg)
{
	ERR	er;
	W	cnt;
	W	wid;
	W	gid;

	printf("req_start()\n");

	er = ER_OK;

	/* Acquire window ID of window possessing request source process */
	cnt = b_wlst_wnd(-pid, 1, &wid);
	if (cnt < ER_OK) {
		er = cnt;
		printf("b_wlst_wnd : %d, %d\n", er, er >> 16);
		goto EXIT;
	}
	printf("process ID : %d    window ID : %d\n", pid, wid);

	/* Acquire drawing environment ID */
	gid = b_wget_gid(wid);
	if (gid < ER_OK) {
		er = gid;
		printf("b_wget_gid : %d, %d\n", er, er >> 16);
		goto EXIT;
	}
	printf("gid : %d\n", gid);

	/* Creation of work region */
	er = draw_gen_workarea(gid, msg->start.r);
	if (er < ER_OK) {
		printf("draw_gen_workarea : %d, %d\n", er, er >> 16);
	}

EXIT:
	/* Reply */
	send_rsp_normal(pid, er);
	return er;
}


/*
 * Call termination
 */
LOCAL	ERR	req_finish(W pid, const MSG_REQ *msg)
{
	printf("req_finish()\n");

	/* Event loop termination */
	doloop = False;

	/* Reply */
	send_rsp_normal(pid, ER_OK);
	return (ER_OK);			/* Usually, ER_OK */
}


/*
 * Redraw request
 */
LOCAL	ERR	req_redraw(W pid, const MSG_REQ *msg)
{
	ERR	er;

/*	printf("req_redraw()\n"); */

	/* Execute redraw */
	er = draw_redraw(msg->redraw.r);

	/* Reply */
	send_rsp_normal(pid, er);

	return er;
}


/*
 * Draw straight line
 */
LOCAL	ERR	req_line(W pid, const MSG_REQ *msg)
{
	ERR	er;

	printf("req_line()\n");

	/* Execute drawing */
	er = draw_line(msg->line.sp, msg->line.ep, msg->line.col);

	/* Reply */
	send_rsp_normal(pid, er);

	return er;
}


/*
 * Draw rectangular frame
 */
LOCAL	ERR	req_box(W pid, const MSG_REQ *msg)
{
	ERR	er;

	printf("req_box()\n");

	/* Execute drawing */
	er = draw_box(msg->box.r, msg->box.col);

	/* Reply */
	send_rsp_normal(pid, er);

	return er;
}


/*
 * Draw circle/ellipse
 */
LOCAL	ERR	req_circle(W pid, const MSG_REQ *msg)
{
	ERR	er;

	printf("req_circle()\n");

	/* •`Execute drawing */
	er = draw_circle(msg->circle.r, msg->circle.col);

	/* Reply */
	send_rsp_normal(pid, er);

	return er;
}


/*
 * Draw character string
 */
LOCAL	ERR	req_test(W pid, const MSG_REQ *msg)
{
	ERR	er;
	W	len;

	printf("req_test()\n");

	/* Execute drawing */
	er = draw_text(msg->text.p, msg->text.col, msg->text.str);

	/* Reply */
	send_rsp_normal(pid, er);

	return er;
}


/* -------------------------------------------------------------- Main processes */
/*
 * Message main reception
 *
 * Here, messages are erased without fail
 */
EXPORT	ERR	recv_main(const MSG_ANY *dmy)
{
	ERR	er;
	W	l;
	W	pid;
	W	msize;
	MSG_ANY	*msg;

	er = ER_OK;
	msg = NULL;

	/* Securing the region */
	msize = dmy->hd.msg_size + offsetof(MSG_HEAD, ext_size);
	msg = (MSG_ANY *)(malloc(msize));
	if (msg == NULL) {
		er = ER_NOMEM;
		printf("memory allocation error.\n");
		b_clr_msg(MM_ALL, MM_ALL);	/* Message erased */
		goto EXIT;
	}

	/* Reception (reception in erasure) */
	pid = b_rcv_msg(MSGMASK(dmy->hd.msg_type), (MESSAGE*)(msg), msize, NOWAIT | CLR);
	if (pid < ER_OK) {
		er = pid;
		printf("b_rcv_msg : %d, %d\n", er, er >> 16);
		b_clr_msg(MM_ALL, MM_ALL);	/* Message erased */
		goto EXIT;
	}

	/* Branch in received contents */
	for (l = 0; rcvfn_tbl[l].type != 0xffffffff; l++) {
		if (rcvfn_tbl[l].type == msg->hd.type) {
			if (rcvfn_tbl[l].fn != NULL) {
				er = (rcvfn_tbl[l].fn)(pid, (const MSG_REQ *)(msg));
			}
			break;
		}
	}

EXIT:
	if (msg != NULL) {
		free(msg);
	}
	return er;
}
--------------------
/*
 *	prog_4-sample.h (T-Shell Sample/Common Header)
 *
 *	(C) Copyright 2003 by Personal Media Corporation.
 */

#ifndef	_PROG_4_SAMPLE_H
#define	_PROG_4_SAMPLE_H

#include	<basic.h>
#include	<btron/outer.h>
#include	<btron/dp.h>
#include	<tcode.h>
#include	<stdio.h>
#include	<stdlib.h>
#include	<tlang.h>
#include	<tstring.h>

/* Message definition */
#include	"msg.h"

/* Global variable */
#include	"gval.h"

/* Global function prototype */
#include	"proto.h"

#endif	/* _PROG_4_SAMPLE_H */
--------------------
/*
 *	prog_4-sndmsg.c (T-Shell Sample/Message Transmissions)
 *
 *	(C) Copyright 2003 by Personal Media Corporation.
 */


#include	"sample.h"


/* Internal function prototypes */
LOCAL	ERR	send_mesg(W pid, MSG_ANY *msg, UW type);


/* ---------------------------------------------------------------- Internal functions */
/*
 * Transmit message
 */
LOCAL	ERR	send_mesg(W pid, MSG_ANY *msg, UW type)
{
	ERR	er;

	er = ER_OK;

	/* Write in header part */
	msg->hd.msg_type = SMPL_MSGTYPE;
	msg->hd.ext_size = 0;		/* Usually, 0 */
	msg->hd.magic[0] = MSG_MAGIC0;
	msg->hd.magic[1] = MSG_MAGIC1;
	msg->hd.magic[2] = MSG_MAGIC2;
	msg->hd.magic[3] = MSG_MAGIC3;
	msg->hd.type = type;

	/* Message transmission */
	er = b_snd_msg(pid, (MESSAGE *)(msg), NOWAIT);
	if (er < ER_OK) {
		printf("b_snd_msg : %d, %d\n", er, er >> 16);
	}

	return er;
}


/* -------------------------------------------------------------- Main processes */
/*
 * Transmit normal response
 */
EXPORT	ERR	send_rsp_normal(W pid, ERR err)
{
	ERR	er;
	MSG_RSP_NORMAL	msg;

	er = ER_OK;

	/* Prepare contents */
	msg.er = err;
	msg.hd.msg_size = sizeof(MSG_RSP_NORMAL) - offsetof(MSG_HEAD,ext_size);

	/* Transmission */
	er = send_mesg(pid, (MSG_ANY *)(&msg), MSGTYPE_RSP_NORMAL);
	if (er < ER_OK) {
		printf("send_mesg : %d, %d\n", er, er >> 16);
	}

	return er;
}
--------------------
#
#	@(#)Makefile (prog_4)
#		    For use with GNU make
#
#	make method
#	 make
#		Create release use regular version
#	 make mode=debug
#		Create for use in debugging
#	 make clean
#		Delete all files created with make
#	 make install
#		Install in the prescribed place (for actual machine use only)
#
# Version
version = 0x1000
# Set release use to default
#mode =
# Source dependencies-related file (automatically created)
DEPS = Dependencies
DEPENDENCIES_OUTPUT := $(DEPS)
# Application standard rules
include $(BD)/bappl/etc/makerules
# ----------------------------------------------------------------------------
# Create target
TARGET = prog_4
# Search path of source files
S = ./ ../src
VPATH = $(S)
# Header file directory addition
HEADER := $(S) $(HEADER)
# Source files
SRC =	main.c    \
	evt.c         \
	rcvmsg.c      \
	sndmsg.c      \
	draw.c
OBJ = $(addsuffix .o, $(basename $(SRC)))
WC_SRC = $(filter %.C, $(SRC))
DBFLAGS += -l
ifeq ($(mode), debug)
    CFLAGS += -Wall
endif
# ----------------------------------------------------------------------------
.PHONY: all clean
INST = $(addprefix $(TARGET), .bz .map)
INST2 = $(addprefix $(TARGET), .out)
all: $(INST)
$(TARGET).out: $(OBJ)
	$(LINK.o) $(LDOBJS) $^ $(LOADLIBES) $(LDLIBS) $(OUTPUT_OPTION)
clean:
	$(RM) $(OBJ)
	$(RM) $(WC_SRC:%.C=%.c) $(DBSRC)
	$(RM) $(INST) $(INST2) *.lst $(DEPS)
# Compression archive
$(TARGET).bz: $(INST2)
	$(CP) $(TARGET).out _t
	$(STRIP) _t
	$(MKBTF) -o$@ -a0x8003 -c -tprog_4 \
		9.$(CPU_TYPE)._t
	$(RM) _t
# Source dependencies related
$(WC_SRC:%.C=%.c):
ifdef DEPENDENCIES_OUTPUT
$(DEPS):	; touch $(DEPS)
else
$(DEPS): $(SRC)	; $(MAKEDEPS) $@ $?
endif
include $(DEPS)

ReadMe
The sample programs are recorded in the directory configuration below.

tshell83/
        prog_1/    : b_rcv_msg() (used in parallel with prog_2)
        prog_2/    : b_snd_msg() (used in parallel with prog_1)
        prog_3/    : b_rcv_msg() (receives things transmitted from MSCRIPT)
        prog_4/    : Example that cooperates with MSCRIPT
        prog_m.bpk : Sample program in MSCRIPT (Packing Box)

Furthermore, because prog_m.bpk is made up in packing box format, please 
decompress it by means of BPACK (Book Packer) by taking out conversion file as a
packing box with the File Converter on top of Cho Kanji, etc. 

When decompressed, a real object called prog_m will be created, in which the 
the contents below are recorded.

prog_m
        prog_m1 : Example that realizes parts in MSCRIPT
        prog_m2 : MSEND (transmits messages vis-à-vis prog_3)
        prog_m3 : Example that cooperates with MSCRIPT (used in parallel with 
                  prog_4)

From prog_1/ through prog_4/, on the development host, please carry out compile 
matched to the CPU of the T-Engine you will use. 

From prog_m1 through prog_m3, please copy as real objects onto disk, etc., on which
you have installed T-Shell the things in which the respective formats are made up
as scripts, and then execute them on top of T-Shell.

____________________

[1] In this example, because we have decided on a state during a pointer press, we have implemented an event loop during pressing. In MicroScript, because it is also possible to describe in a manner in which processing is executed in cases where a segment has been clicked, if we use this, it will come about that we will be finished with the present program of several lines.

[2] Here, we have made a program based on MicroScript and C language the subject, but cooperation based on inter-process messaging is also used even with C language-based programs themselves, and thus it is a method of very high general purposeness.

[3] Furthermore, concerning synchronization and cooperation among processes, outside of inter-process messaging in PMC T-Kernel Extension that we take up on this occasion, functions such as semaphore, event flag, mailbox (message buffer), and rendezvous, which are frequently used with T-Kernel and ITRON, are also provided.

[4] In doing b_snd_msg(), it is necessary to know the process ID of the transmission target. Here, in prog_1 of the receiving side, we store the process ID of the self process in the global name [prog_1]. In prog_2 of the transmitting side, we make it so that we use the value obtained from this global name as the process ID of the transmission target.

[5] Outside of this, because MicroScript cannot freely handle a drawing environment, it also cannot acquire currently displayed screen contents.

[6] The message types that can be handled with MicroScript are in the form of the eight types from MS_TYPE0 to MS_TYPE7. As for the message types we can specify with the MSEND statement, they are the values from 0 to 7, and we specify the values of this range with anything from MS_TYPE0 up to MS_TYPE7.

[7] Because structures cannot be handled in MicroScript, this becomes a simple byte string. For that reason, paying attention to the CPU endian and alignment is necessary.

[8] When transmitting with the MSEND statement, MESSAGE.msg_type, MESSAGE.msg_size, and MESSAGE.msg_body are specified as respectively different arguments. For that reason, inside the main body of the message we want to transmit, contents corresponding to MESSAGE.msg_type and MESSAGE.msg_size must not be included (we specify only contents corresponding to MESSAGE.msg_body).

[9] For the contents of the structure that transmits and receives, please refer to the source of the sample program that is recorded on the CD-ROM.

[10] In this example, as differs with the previous, in b_cre_nam(), it has become the N_CREATE specification. In this case, if something with the same name already exists, b_cre_nam() becomes an error, but there are cases where this is used for the purpose avoiding duplicating and starting up the same application.

[11] Accurately, these are things that are arranged as segments; in actuality, it is not a case in which we are arranging parts called buttons and selectors. In MicroScript, by skillfully operating these segments, we implement in a manner in which they behave as parts.

[12] By means of the PROCESS statement, it is also possible to start up the process at the cooperation destination from MicroScript. However, please be careful, because we have to switch the binary that should start up for the CPU of the T-Engine we will use.

[TN] All the programs loaded on the CD-ROM mentioned here have been translated and appear at the end of this article. The interface parts of the MicroScript programs are shown below together with prog_m2, which has no interface parts. These were packed in the prog_m.bpk file.

Reference Documentation

[1] Sakamura, Ken Gen. Ed.; PMC Institute Ed.: Maikurosukuriputo nyuumon [An Introduction to BTRON MicroScript] , Personal Media Corp., 1999. (ISBN4-89362-160-2)

[2] Sakamura, Ken Gen. Ed.; PMC Institute Ed.: BTRON Maikurosukuriputo [BTRON MicroScript Reference Manual], Personal Media Corp., 1997. (ISBN4-89362-155-6)


The above article on PMC T-Shell appeared on pages 32-40 in Vol. 83 of TRONWARE . It was translated and loaded onto this Web page with the permission of Personal Media Corporation.

Copyright © 2003 Personal Media Corporation

Copyright © 2008 Sakamura Laboratory, University Museum, University of Tokyo