[Pntool-developers] SF.net SVN: pntool:[265] present_version
Brought to you by:
compaqdrew,
miordache
From: <mio...@us...> - 2012-08-15 23:47:24
|
Revision: 265 http://pntool.svn.sourceforge.net/pntool/?rev=265&view=rev Author: miordache Date: 2012-08-15 23:47:15 +0000 (Wed, 15 Aug 2012) Log Message: ----------- version 1.2 Modified Paths: -------------- present_version/LICENSE/README.txt present_version/Makefile-linux.mak present_version/doc/GettingStarted.htm present_version/examples/README present_version/examples/inteq.sp present_version/newcodegen/Makefile-cygwin.mak present_version/newcodegen/Makefile-linux.mak present_version/newcodegen/ProcessTemplate.c present_version/newcodegen/SupervisorTemplate.c present_version/newcodegen/codegen.h present_version/newcodegen/filltmpl.lex present_version/newcodegen/plantCompiler.c present_version/newcodegen/spcommon.h present_version/newcodegen/supervisorCompiler.c present_version/parser/Makefile present_version/parser/actions.c present_version/parser/read.h present_version/parser/read.lex present_version/parser/read.y present_version/pnheaders/general.c present_version/pnheaders/insert.c present_version/pnheaders/insert.h present_version/pnheaders/main_function2.c present_version/pnheaders/pns.c present_version/pnheaders/pns.h present_version/spnbox/matrixmath.c present_version/spnbox/spnbox.h Added Paths: ----------- present_version/doc/format2.sp present_version/examples/reader.sp present_version/newcodegen/Makefile present_version/newcodegen/fl2str.lex Removed Paths: ------------- present_version/README.txt present_version/doc/format2.hl present_version/doc/input2.sp Modified: present_version/LICENSE/README.txt =================================================================== --- present_version/LICENSE/README.txt 2012-08-15 20:59:28 UTC (rev 264) +++ present_version/LICENSE/README.txt 2012-08-15 23:47:15 UTC (rev 265) @@ -2,8 +2,6 @@ The software uses third-party code as follows. -ANTLR has been used to generate a translator for specifications written in a Petri net description language. ANTLR is released under the BSD license. See ANTLR3_LICENSE.txt. - LPSOLVE is used to solve the linear and integer linear programs of the spnbox functions. LPSOLVE is released under the LGPL license. MEMWATCH has been used to debug the spnbox functions. MEMWATCH is released under the GPL license. Modified: present_version/Makefile-linux.mak =================================================================== --- present_version/Makefile-linux.mak 2012-08-15 20:59:28 UTC (rev 264) +++ present_version/Makefile-linux.mak 2012-08-15 23:47:15 UTC (rev 265) @@ -30,4 +30,3 @@ cd $(CODEGEN); make -f Makefile-linux.mak clean cd $(TRANSLATOR); make clean cd $(SPNBOX); make clean - Deleted: present_version/README.txt =================================================================== --- present_version/README.txt 2012-08-15 20:59:28 UTC (rev 264) +++ present_version/README.txt 2012-08-15 23:47:15 UTC (rev 265) @@ -1,10 +0,0 @@ -After building the software you may use it as follows: - -1) Write the specification file. - -2) Copy ProcessTemplate.c, SupervisorTemplate.c, and spcommon.h from newcodegen to the working directory. These are skeleton files for the concurrency code. - -3) Run the concurrency software. This will build the source code files specified in the specification file. - -4) Build your application with the generated makefile. - Modified: present_version/doc/GettingStarted.htm =================================================================== --- present_version/doc/GettingStarted.htm 2012-08-15 20:59:28 UTC (rev 264) +++ present_version/doc/GettingStarted.htm 2012-08-15 23:47:15 UTC (rev 265) @@ -9,24 +9,28 @@ <p><b>A Concurrency Tool Suite--Getting Started</b> -<p>The software is intended for Unix operating systems. If you use a Windows computer, you may download cygwin from <a href="http://www.cygwin.com">http://www.cygwin.com</a>. The cygwin program runs in Windows and emulates Linux. Thus, you may run the software in Windows by means of cygwin. +<p>The software is intended for Unix operating systems. It can be used also in Windows within the <a href="http://www.cygwin.com">cygwin</a> environment. +<ul> +<li>To build the software in Linux, open a terminal program and run <i>make -f Makefile-linux.mak</i> in the main directory of the source code. +<li>To build the software in cygwin, open a terminal program and run <i>make -f Makefile-cygwin.mak</i> in the main directory of the source code. If your gcc version supports the <i>-pthread</i> option, you may use <i>Makefile-linux.mak</i> instead of <i>Makefile-cygwin.mak</i>. +</ul> +The executable file of the program is called <i>ct</i>. It is generated in the same directory. -<p>To build the software, type the command "make" in the main directory of the source code. This will execute the commands of the file called "Makefile" and build an executable file called "ct.exe". In spite of its extension, this is not a Windows executable file. It can only be executed within cygwin or in Unix. +<p>To see the command line options of the program, run <i>./ct</i> in the terminal window. To generate a concurrent program based on a specification file <i>spec.sp</i> that is located in the same directory, run <i>./ct spec.sp</i>. -<p>If you run ct.exe you can see a description of its options. - -<p>In order to run the program on a specification file: +<p>In order to build an application using <i>ct</i>: <ul> -<li> Copy the files SupervisorTemplate.c ProcessTemplate.c and spcommon.h from the newcodegen directory to your working directory. -<li> Run ct.exe on your specification file. For instance, if spec.sp is the specification file, you could type "./ct.exe -d4 spec.sp". The d4 option can be used in order to have ct.exe display messages describing what it is doing. -<li>If the specification file is correct, ct.exe will exit normally and create a number of sources files allowing you to build your program. -<li> You can build your program using "make" and the makefile generated by ct.exe. For instance, to build the program from the source code generated for spec.sp, type "make -f spec.mak". -<li> The previous step will generate an executable file. When you run it, you can force it to terminate with Ctrl-c. This should terminate also all other processes (if any) started by the executable file. +<li>Run <i>ct</i> on the specification file. +<li>If the specification file is correct, <i>ct</i> will exit normally and generate a header file <i>spcommon.h</i>, several C files, and a make file. +<li>The application can be built using <i>make</i> and the make file generated by <i>ct</i>. For instance, if <i>ct</i> is run on a specification file <i>spec.sp</i>, it will generate several files including a make file <i>spec.mak</i>.Then, the application can be built with the command <i>make -f spec.mak</i>. +<li>The previous step will generate an executable file. When the executable file is run, it can be terminated at any point with the SIGINT signal (that is, with <i>Ctrl-c</i> when the program is run in the foreground). This should terminate the main process together with its child processes. (Only the child processes defined in the specification file will be terminated.) +<li>Due to the somewhat large number of files that is generated, it is recommended to use a separate directory for each specification file. </ul> -<p>To create your own specification files: +<p>To create specification files: <ul> -<li>Check format2.hl for a description of the specification format. +<li>See <i>format2.sp</i> in the <i>doc</i> directory for a description of the specification format. +<li>See also the <i>examples</i> directory. </ul> @@ -34,7 +38,7 @@ <hr> <!-- Created: Fri May 13 17:16:03 CDT 2011 --> <!-- hhmts start --> -Last modified: Fri May 13 17:43:01 CDT 2011 +Last modified: Tue Aug 14 16:40:10 CDT 2012 <!-- hhmts end --> </body> </html> Deleted: present_version/doc/format2.hl =================================================================== --- present_version/doc/format2.hl 2012-08-15 20:59:28 UTC (rev 264) +++ present_version/doc/format2.hl 2012-08-15 23:47:15 UTC (rev 265) @@ -1,188 +0,0 @@ -// This file describes the specification language. -// July 6, 2011. - -// In this document both threads and processes are called processes. - -// The specification describes processes and how they should be coordinated. -// The program implementing the specification consists of a coordinator -// that runs the processes described in the specification and supervises -// their execution. The coordinator is called supervisor. - -// The specification defines groups of processes. A group may have any number -// of processes (0, 1, 2, ...). This number may change during the execution of -// the program. The specification determines the initial number of processes -// in a group and how this number may change. Processes in a group are -// identical in the sense that they have the same executable code. However, -// processes in the same group do not have to be in the same stage of -// execution. - -// A group of processes is implemented by means of executable programs if -// it is defined with the keyword "process". Otherwise, it is implemented -// by means of threads of the supervisor if it is defined with the keyword -// "thread". - -// The following defines a group or processes - -process p1 { - - // The following defines the Petri net representation of the process - - places: p1 p2 p3 - transitions: t0 - transitions: t1 t2 t3 t4 - - // The following describes the arcs connecting places and transitions - - (p1, t0) - (p1, t1, p3) - - // A semicolon must be used between instructions on the same row - - (p3, t4, p1); (t3, p3) - - // The following arc is conditional. The generated program will - // contain an "if(i >= 1)" instruction before attempting to fire t2. Thus, - // the variable i must be defined in the context of the C code associated - // with the place p2. - - (p2, t2) {i >= 1} - -} - -// The following defines a group or processes implemented as threads - - -thread t1 { - - // The following defines the Petri net representation of the process - - places: p1 p2 p3 - transitions: t1 t2 t3 t4 - - // The following describes the arcs connecting places and transitions - - (p1, t1) - (p1, t2, p3) - (p3, t3, p2); (p2, t4, p1); - -} - - -// The Petri net associated with a supervisor is generated automatically. -// However, the user has the option to specify additional components to be -// included in the Petri net of the supervisor. The following block defines -// such a component. - -supervisor sc { - places: p1 p2 - transitions: t1 - - (p1, t1, p2) -} - - -// The following synchronizes the transition t1 of process p1 with the -// transition t3 of the process t1. - -sync p1.t1 t1.t3 - -// Constraints can be described by means of inequalities - -2*p1.q.t2 - t1.p3 <= 1 // firing vector element: process.q.transition - // marking vector element: process.place - -t1.v.t1 <= t1.v.t2 // Parikh vector element: process.v.transition - - -// The following describes the initial number of processes in each group. -// It also describes the stage in which each process should be started. - -initialize: p1(p1:1, p2:2) -initialize: t1(p2:1) sc(p1:5) - -// The group p1 will have three processes: one starting in p1 and two starting -// in p2. The group t1 will have only one process and that process will start -// in p2. Now, sc is not a process group but a supervisor component. The -// initialization of sc requests that the Petri net of sc will have an initial -// marking with 5 tokens in p1. - -// By default, a group of processes is initialized with zero processes. - -// Transitions that should be live can be specified as follows. -// NOTE: Avoid this instruction when possible, since the synthesis of a -// deadlock prevention policy is computationally intensive and can take much -// time. - -live: t1.t2 // the supervisor should ensure that the transition t2 of the - // process group t1 is live. - - -// The following blocks are OPTIONAL. - -// A segment of code can be associated with each place. The following -// instruction defines the code of the place p3 of the process p1. - -p1.p3 { - i = i + 1; - j = 10*i; -} - -// Any instructions that a process should execute when it is started -// can be specified by means of a main block - -p1.main { - i = 0; - j = 1; -} - -// Header files and other definitions that should appear in the source file of -// a process can be specified by means of an include block - -p1.include { - #include"string.h" - #define MAX 10 - - int i, j; - - struct myarray { int i; float k; }; - - static struct myarray array[MAX]; -} - -// Instructions on how to build the executable file associated with a process -// can be specified in a build block. Note that the software will replace $$$ -// with the name of the file defining the process (without extension). - -p1.build { gcc -g -o $$$.exe $$$.c } - -// Copies of a process group can be specified as follows - -p1c = p1 // p1c is another process group - -// Note that p1 has been defined with the keyword 'process'. Thus, p1c will -// also be of the type 'process'. If the copy should have a different type, -// the desired type should be stated before the assignment. - -thread p1c2 = p1 - -// On the line above, p1c2 is defined as a copy of p1 of the type 'thread'. - -// Instructions that the supervisor should execute when it is started -// can be specified by means of a main block - -main { - fprintf(stdout, "The supervisor is starting ..."); -} - -// An include block can also be defined for the supervisor - -include { - #define MAX_INP 3 - #include"ctype.h" -} - - -// The build block of the supervisor can be used to specify additional -// command line parameters that should be used when building the program - -build { -I. } Added: present_version/doc/format2.sp =================================================================== --- present_version/doc/format2.sp (rev 0) +++ present_version/doc/format2.sp 2012-08-15 23:47:15 UTC (rev 265) @@ -0,0 +1,220 @@ +// This file describes the specification language. +// Creataed on July 6, 2011. Updated in July 2012. + +// In this document both threads and processes are called processes. + +// The specification describes processes and how they should be coordinated. +// The program implementing the specification consists of a coordinator +// that runs the processes described in the specification and supervises +// their execution. The coordinator is called supervisor. + +// The specification defines groups of processes. A group may have any number +// of processes (0, 1, 2, ...). This number may change during the execution of +// the program. The specification determines the initial number of processes +// in a group and how this number may change. Processes in a group are +// identical in the sense that they have the same executable code. However, +// processes in the same group do not have to be in the same stage of +// execution. + +// A group of processes is implemented by means of executable programs if +// it is defined with the keyword "process". Otherwise, it is implemented +// by means of threads of the supervisor if it is defined with the keyword +// "thread". + +// The following defines a group or processes + +process p1 { + + // The following defines the Petri net representation of the process + + places: p1 p2 p3 + transitions: t0 + transitions: t1 t2 t3 t4 + + // The following describes the arcs connecting places and transitions + + (p1, t0) + (p1, t1, p3) + + // A semicolon must be used between instructions on the same row + + (p3, t4, p1); (t3, p3) + + // The following arc is conditional. The generated program will + // contain an "if(i >= 1)" instruction before attempting to fire t2. Thus, + // the variable i must be defined in the context of the C code associated + // with the place p2. + + (p2, t2) {i >= 1} + +} + +// The following defines a group or processes implemented as threads + + +thread t1 { + + // The following defines the Petri net representation of the process + + places: p1 p2 p3 + transitions: t1 t2 t3 t4 + + // The following describes the arcs connecting places and transitions + + (p1, t1) + (p1, t2, p3) + (p3, t3, p2); (p2, t4, p1); + +} + + +// The Petri net associated with a supervisor is generated automatically. +// However, the user has the option to specify additional components to be +// included in the Petri net of the supervisor. The following block defines +// such a component. + +supervisor sc { + places: p1 p2 + transitions: t1 + + (p1, t1, p2) +} + + +// The following synchronizes the transition t1 of process p1 with the +// transition t3 of the process t1. + +sync p1.t1 t1.t3 + +// Constraints can be described by means of inequalities + +2*p1.q.t2 - t1.p3 <= 1 // firing vector element: process.q.transition + // marking vector element: process.place + +t1.v.t1 <= t1.v.t2 // Parikh vector element: process.v.transition + + +// The following describes the initial number of processes in each group. +// It also describes the stage in which each process should be started. + +initialize: p1(p1:1, p2:2) +initialize: t1(p2:1) sc(p1:5) + +// The group p1 will have three processes: one starting in p1 and two starting +// in p2. The group t1 will have only one process and that process will start +// in p2. Now, sc is not a process group but a supervisor component. The +// initialization of sc requests that the Petri net of sc will have an initial +// marking with 5 tokens in p1. + +// By default, a group of processes is initialized with zero processes. + +// Transitions that should be live can be specified as follows. +// NOTE: Avoid this instruction when possible, since the synthesis of a +// deadlock prevention policy is computationally intensive and can take much +// time. + +live: t1.t2 // the supervisor should ensure that the transition t2 of the + // process group t1 is live. + + +// The following blocks are OPTIONAL. + +// A segment of code can be associated with each place. The following +// instruction defines the code of the place p3 of the process p1. + +p1.p3 { + i = i + 1; + j = 10*i; +} + +// If several transitions could be fired from a place (that is, their +// conditions, if any, are satisfied and the supervisor could fire any of them) +// the next transition will be selected randomly. However, if the programmer +// defines a "select function" and assigns it to the place, the fired +// transition will be determined by the select function. Thus, conditions +// labeling a transition are implemented only if no select function is defined. +// The following line requests that p1_select() be called in order to +// determine the transition that should be fired from the place p1 of the +// process p1. Note the requirements on the select function below. + +p1.p1.select { p1_select(___TR); /* ___TR: defined in context of call */ } + +// Requirements on the select function: +// - It must return the number of transitions written to ___TR. +// - The select function should write to ___TR[0], ___TR[1], ... +// the ___TRData element of the selected transitions, in the order +// of preference. See the definition of the p1_select function in this file. +// - The parameters of the function may be arbitrary. +// - The code generator will write: +// ___i = [select function call] +// where [select function call] stands for whatever is written between +// braces in the select command. For instance, the select command above +// is implemented as +// ___i = p1_select(___TR); /* ___TR: defined in context of call */ + + +// Any instructions that a process should execute when it is started +// can be specified by means of a main block + +p1.main { + i = 0; + j = 1; +} + +// Header files and other definitions that should appear in the source file of +// a process can be specified by means of an include block + +p1.include { + #include"string.h" + #define MAX 10 + + int i, j; + + struct myarray { int i; float k; }; + + static struct myarray array[MAX]; + + static int p1_select(struct ___trans* ___TR) { + // Selects the transitions 0 and 1 and gives precedence to transition 1. + ___TR[0] = ___TRData[1]; ___TR[1] = ___TRData[0]; + return 2; // returns the number of entries written to ___TR + } +} + +// Instructions on how to build the executable file associated with a process +// can be specified in a build block. Note that the software will replace $$$ +// with the name of the file defining the process (without extension). + +p1.build { gcc -g -o $$$.exe $$$.c } + +// Copies of a process group can be specified as follows + +p1c = p1 // p1c is another process group + +// Note that p1 has been defined with the keyword 'process'. Thus, p1c will +// also be of the type 'process'. If the copy should have a different type, +// the desired type should be stated before the assignment. + +thread p1c2 = p1 + +// On the line above, p1c2 is defined as a copy of p1 of the type 'thread'. + +// Instructions that the supervisor should execute when it is started +// can be specified by means of a main block + +main { + fprintf(stdout, "The supervisor is starting ..."); +} + +// An include block can also be defined for the supervisor + +include { + #define MAX_INP 3 + #include"ctype.h" +} + + +// The build block of the supervisor can be used to specify additional +// command line parameters that should be used when building the program + +build { -I. } Deleted: present_version/doc/input2.sp =================================================================== --- present_version/doc/input2.sp 2012-08-15 20:59:28 UTC (rev 264) +++ present_version/doc/input2.sp 2012-08-15 23:47:15 UTC (rev 265) @@ -1,343 +0,0 @@ -// THIS DOCUMENT DESCRIBES THE *OLD* VERSION OF THE SPECIFICATION LANGUAGE. -// SEE format2.hl FOR A DESCRIPTION OF THE CURRENT SPECIFICATION LANGUAGE. - -// FOR REFERENCE ONLY. ON ONE HAND, NOT ALL FEATURES HAVE BEEN IMPLEMENTED -// IN THE TRANSLATOR. ON THE OTHER HAND, SOME IMPLEMENTED FEATURES ARE NOT -// DESCRIBED HERE. THIS FILE MAY NOT DESCRIBE THE ENTIRE SYNTAX. SEE THE -// EXAMPLES FOR INFORMATION ON THE SYNTAX. - -// Version 2.1.1 - 04/21/2011 -// The keyword "init" was added for initialization code. -// Version 2.1 - 05/19/2009 -// Compared to version 2, the following keywords were added: -// "nondeterministic", "select", "uncontrollable", and "unobservable". -// The low level (PN level) specification language is illustrated on a -// specification of independent reader and writer processes with shared memory. -// The high level language has not been developed yet. - -// The concurrent programming tool operates as follows. -// -// Given a specification file (say input.sp), the tool generates -// - input.c containing the code of the supervisor; -// - input.mak a makefile; -// - additional c files, one for each process defined below. -// -// After the application is built, the user can start it by -// running the supervisor program (say input.exe). The supervisor program -// will start all other processes and ensure that they operate -// correctly. Terminating the supervisor program will also -// terminate children processes. - - -// The specification file consists of three parts containing -// - process-type declarations -// - definitions -// - process declarations and dependencies -// - instructions on supervisor design - -// 1. PROCESS-TYPE DECLARATIONS - -// Format: -// -// process type // Write here the name of the process type. - // Note that all processes of the same type have the same - // executable file. -// build command: // Write here the line(s) used to build the executable. - // For instance: 'make -f process_name.mak' or - // 'gcc -o process_name process_name.sp.c functions.c ...' - // Note that process_name.sp.c is the c file generated - // by the concurrent programing tool for the process_name - // type. -// include: // Write here what should be included at the beginning of - // process_name.sp.c, such as #include directives. -// extern process type // Declares a process type for which the tool should - // not generate code. Such a process type may describe - // hardware or software functions already implemented. - // If such external processes impose relevant - // constraints, the specification should - // describe them. This may help: - // - simplify some supervisory control methods - // - reveal potential deadlock situations - // A process may not be external unless all transitions - // unique to the process are uncontrollable and - // unobservable. - -process type READER - -build command: make -f reader.mak - -include: { - #include<stdio.h> - #include<string.h> - - int state = 0; /* variables can be declared here as well */ -} - - -init: { - // include here declarations and initialization code -} - -process type WRITER - -build command: make -f writer.mak - -include: #include "writer.h" - - -extern process type ARBITER // Note that no build or include commands follow - // the declaration of an external process type. - - -// 2. DEFINITIONS - -// This version of the specification format describes only a low level PN -// definition of the processes. - -// Format: - -// process_name.PN: -// places: list of place names -// transitions: list of transition names -// place.code: gives the C code associated with a place. The C code -// is not parsed here! Rather the "text" structure associated -// to the PN place is initialized with the position of the C code. -// *place: list of input transitions -// place*: list of the output transition of place -// ([place], transition, [place, ...])[.{c code}] where items between -// square brackets are optional. -// Note that the c code is not parsed but its position is copied to a "text" -// structure associated with the arc. - - - -ARBITER.PN: - -places: p1 p2 // place names do not have to start with a 'p' - -transitions: t1 t2 // transition names do not have to start with a 't' - -// Note the absence of place.code lines for an external process. - -*p1: t1 -p1*: t2 -*p2: t2 -p2*: t1 - - -// The format *place: input transition(s), place*: output transition(s) -// is ideal for representing a PN structure and this is what we need for an -// external process. However, the format it is ambiguous for the processes for -// which code should be generated. For instance, assume a transition t such -// that *t: p1 p2 and t*: p3 p4. Recall that each process of type X is a -// token in the underlying PN. Thus, assuming two processes, one in the stage -// p1 and one in the stage p2, it is not clear what action should be taken -// when t is fired. The following format will be used to describe the outcome -// of firing t. -// 1. The process in p1 goes to p3 and the one in p2 to p4 -// (p1, t, p3) (p2, t, p4) -// 2. The process in p1 goes to p3 and forks one child process in p4. The -// process in p2 terminates. -// (p1, t, p3, p4) (p2, t) -// 3. Both processes in p1 and p2 terminate and two new processes are created -// in p3 and p4. -// (p1, t) (p2, t) (t, p3) (t, p4) -// 4. ... -// ... - -READER.PN: - -places: p1 p1b p2 p3 - -transitions: t1 t2 t3 t4 ti t_end - -p1.code: initialize_r(); - -p1b.code: initialize_r_b(); - -p2.code: { - str = read_data(); -} - -p3.code: process_data(str); - -// The following lines describe the structure of the PN - -(p1b, ti, p1) -(p1, t1, p2).{i != 0} // the transition will be taken only if the condition - // between braces is TRUE. -// The expression between braces should only be copied; it does not have to -// be parsed. - -(p2, t2, p3) -(p3, t3, p1) -(p1, t_end).{exit_v == TRUE} -(p1, t4, p3) - -// Note that a process in p1 has three choices. -// if(i != 0) then fire t1 -// else if(exit_v == TRUE) then fire t_end -// else fire t4 - -// Instead of using the conditions above to determine which transitions to -// fire, a function to select them could be specified. - -select function p1.{select_t} // select_t is the name of the function - -// Thus, when there is a token in p1, the function select_f is invoked to -// to determine which transition should be fired. - -nondeterministic places: p1 - -// By default a place p is deterministic. For a deterministic place, one of the -// enabled output transition is selected and then the process waits until the -// supervisor permits its firing. However, if the place p is nondeterministic, -// a protocol such as the one below is used. -// -// 1. The select function is invoked to produce the list of enabled transitions -// in the order of firing preference (first in list is the transition the -// process is most interested to fire). -// 1.b. Optionally, the supervisor is inquired about the transitions it -// enables. However, note that the set of transitions enabled by the -// supervisor can change before the process asks the supervisor for -// permission to fire. -// 2. The list of transitions is sent to the supervisor. Then, the process -// sleeps until the supervisor replies. -// 4. The supervisor gives permission to fire one of the transitions on the -// list. -// -// The main difference between a deterministic and a nondetermistic place is -// as follows. For a deterministic place a transition is selected and then the -// process sleeps until it can continue by firing that transition. For a -// nondeterministic place the choice of the next transition depends on the -// transitions enabled by the supervisor. - - - -WRITER.PN: - -places: p pwr_1 pwr2 - -transitions: t1 t2 t3 t4 - -p.code: process_wrdata(); - -pwr_1.code: write_dest1(); - -pwr_2.code: write_dest2(); - -(p, t1, pwr_1).{dest == 1} -(p, t2, pwr_2) -(pwr_1, t3, p) -(pwr_2, t4, p) - - - -// 3. PROCESS DECLARATIONS - -READER r_group(p1:2, p3:1) // This declares a group of 2+1= 3 READER - // processes. Two processes begin in the state - // p1 and one in the state p3. - // The name of this group of processes is 'r_group'. - // They will be implemented by the READER.PN with - // initial marking m(p1) = 2 and m(p3) = 1. - -READER reader1(p1b) // This declares a single READER process that begins in - // the state p1b. The name of the process is reader1. - -WRITER writer1(p) - -WRITER w_group(p:2) - -ARBITER arbiter(p1) - - -// DEPENDENCIES (transitions that processes synchronize on their own) - -sync reader1.t1 arbiter.t1 - // mentions that the two transitions are synchronized - // (they take place simultaneously). - -sync writer1.t2 arbiter.t2 - -// Remark: all transitions of the external processes are considered to be -// uncontrollable and unobservable, excepting the transitions synchronized -// with transitions of internal processes. Such transitions have the type -// specified by the internal process. - - -// 4. INSTRUCTIONS ON THE DESIGN OF THE SUPERVISOR - -// These describe what the objectives of the supervisor. -// - 'start' commands describe what processes the supervisor should start -// - 'constraints' commands describe what constraints should be enforced -// Constraints have the form -// weighted sum <= free term -// Since we deal with integers, <, >, and >= are all equivalent to this -// form. For instance, a < b is the same as a <= b - 1. -// Disjunctive constraints are also allowed -// (weighted sum <= free term) || (weighted sum 2 <= free term 2) -// The keyword 'live' is used to introduce a list of transitions that -// should always be eventually firable. -// Similarly, the keywords "uncontrollable" and "unobservable" introduce -// lists of transitions that the supervisor should not attempt to control -// and observe, respectively. - -start r_group w_group reader1 writer1 // Unimplemented as of May 2011. - - -// CONSTRAINTS - -r_group.constraints: // these are constraints on the PN of r_group - -live: t2 t4 // requests that the transitions t2 and t4 of r_group be live - // (i.e. they never deadlock). - -uncontrollable: t1 t_end t4 - -unobservable: t1 t_end t4 - - -w_group.constraints: // these are constraints on the PN of w_group - -// Here are some constraints that two writers may not be at the same time -// in the same critical section. - -pwr_1 <= 1 // requests that the marking of pwr_1 does not exceed 1 -pwr_2 <= 1 // requests that the marking of pwr_2 does not exceed 1 - -live: all // requests all transitions of w_group to be live. - - -// NOTE: Some constraint features are not implemented as of May 2011. - -global.constraints: // these are constraints on all PNs - -(r_group.p2 <= 0) || (w_group.pwr_1 <= 0) - -// The line above requests that at all times either the place p2 of r_group -// has no tokens or the place pwr_1 of w_group has no tokens. That is, any -// number of readers may be at the same time in the critical section, but -// a reader and a writer may not be there at the same time. - -q.reader1.t1 - writer1.p <= 0 //'q.' denotes the firing vector. The constraint - // requires that t1 of reader1 may be fired only - // if there is one token in the place p of - // writer1. - -2*reader1.t1 - 2*reader1.t2 + w_group.pwr_2 <= 2 -// reader1.t1 denotes the number of firings of t1. This constraint is -// another way of requesting 2*reader1.p2 + w_group.pwr_2 <= 2 - - - -// More general constraints, such as requiring a certain language to be -// generated, will be implemented when the need will arise. - - - -// 5. OTHER COMMANDS - -print supervisor to debug.log // 'print supervisor to file_name' requests the - // PN produced by the supervisory control - // algorithms to be written to file_name. Modified: present_version/examples/README =================================================================== --- present_version/examples/README 2012-08-15 20:59:28 UTC (rev 264) +++ present_version/examples/README 2012-08-15 23:47:15 UTC (rev 265) @@ -3,16 +3,19 @@ inteq.sp: a simple example illustrating how to write concurrent program specifications. It specifies a concurrent program for finding integer solutions to the equation w^2 = x^2 + y^2 + z^2. -The following files were converted to the present specification format by Micah Martin and Basil Hall. +test2.sp: This is a test file intended to check the code generation module. It generates a process that creates periodically a thread until it terminates. There are synchronizations between the process and the threads it generates. -test2.sp: This is a test file intended to check the code generation module. It generates a process that can creates periodically a thread until it terminates. There are synchronizations between the process and the threads it generates. +The test3 files below consider the dining philosopher problem. - -test3: A dining philosopher example. - test3a.sp: Tests that the deadlock prevention function works fine when no deadlock is possible. Only one philosopher with two resources. test3c.sp: A test involving 5 philosophers. test3d.sp: A test involving 5 philosophers. Here, the resources (chopsticks) are defined as supervisor components, not as threads. + + +reader.sp: this is a reader/deleter/inserter example. It illustrates more complex marking and firing vector constraints. + + +The examples test2.sp, test3a, test3c, and test3d were converted to the current specification format by Micah Martin and Basil Hall. Modified: present_version/examples/inteq.sp =================================================================== --- present_version/examples/inteq.sp 2012-08-15 20:59:28 UTC (rev 264) +++ present_version/examples/inteq.sp 2012-08-15 23:47:15 UTC (rev 265) @@ -1,4 +1,4 @@ -// inteq.hl -- a concurrent program for finding integer solutions to the +// inteq.sp -- a concurrent program for finding integer solutions to the // equation w^2 = x^2 + y^2 + z^2 // Fastest if built with the option -s2 @@ -116,4 +116,6 @@ fprintf(stdout, "%d^2 = %d^2 + %d^2 + %d^2\n", w, x, y, z);fflush(0); } } -} \ No newline at end of file +} + +build { -lm } // so that math library is included by gcc; needed for sqrt Added: present_version/examples/reader.sp =================================================================== --- present_version/examples/reader.sp (rev 0) +++ present_version/examples/reader.sp 2012-08-15 23:47:15 UTC (rev 265) @@ -0,0 +1,56 @@ +// This implements the reader/deleter/inserter example + +thread READER { + places: pv pc pd; + transitions: tv tc td; + + (pv, tv, pc); (pc, tc, pd); (pd, td, pv); +} + + +READER.include { +#include<pthread.h> +} + + +READER.pv { + fprintf(stderr, "\n%s %x entering the pv block", ___INSTANCE, (int)pthread_self()); + sleep(1); +} + + +READER.pc { + fprintf(stderr, "\n%s %x entering the critical section", ___INSTANCE, (int)pthread_self()); + sleep(1); +} + + +READER.pd { + fprintf(stderr, "\n%s %x entering the pd block", ___INSTANCE, (int)pthread_self()); + sleep(1); +} + + +DELETER = READER // create a deleter thread group of identical structure +INSERTER = READER // create an inserter thread group of identical structure + +supervisor sc { + places: pa; + transitions: t0 t1 t2; + + (t1, pa); (pa, t0); +} + +initialize: READER(pv:5); +initialize: INSERTER(pv:3); +initialize: DELETER(pv:3); +// No initialize command needed for sc since its initial marking is zero. + +sync sc.t1 sc.t2 READER.tv + +sc.q.t1 <= DELETER.pv +3*sc.q.t2 + 3*sc.q.t0 <= 3 - DELETER.pv + 3*DELETER.pc +sc.pa <= 5 +6*DELETER.pc + READER.pc + INSERTER.pc <= 6 +INSERTER.pc <= 1 + Added: present_version/newcodegen/Makefile =================================================================== --- present_version/newcodegen/Makefile (rev 0) +++ present_version/newcodegen/Makefile 2012-08-15 23:47:15 UTC (rev 265) @@ -0,0 +1,28 @@ +COMPILER=gcc -g +PNDIR=../pnheaders/ + +static: plantCompiler.o filltmpl.fl.o supervisorCompiler.o templates.o + +compexample.o: compexample.c *.h $(PNDIR)*.h + $(COMPILER) -c -I$(PNDIR) compexample.c + +plantCompiler.o: plantCompiler.c *.h $(PNDIR)*.h + $(COMPILER) -c -I$(PNDIR) plantCompiler.c + +supervisorCompiler.o: supervisorCompiler.c *.h $(PNDIR)*.h + $(COMPILER) -c -D ___USE_PTHREAD_LIB -I$(PNDIR) supervisorCompiler.c + +filltmpl.fl.o: filltmpl.lex + flex -Pfl -ofilltmpl.fl.c filltmpl.lex + $(COMPILER) -c filltmpl.fl.c -I$(PNDIR) + +templates.o: fl2str SupervisorTemplate.c ProcessTemplate.c spcommon.h + ./fl2str templates.c SupervisorTemplate.c ProcessTemplate.c spcommon.h + $(COMPILER) -c templates.c + +fl2str: fl2str.lex + flex -ofl2str.yy.c fl2str.lex + $(COMPILER) -o fl2str fl2str.yy.c + +clean: + rm *.o obj/*.o || true \ No newline at end of file Modified: present_version/newcodegen/Makefile-cygwin.mak =================================================================== --- present_version/newcodegen/Makefile-cygwin.mak 2012-08-15 20:59:28 UTC (rev 264) +++ present_version/newcodegen/Makefile-cygwin.mak 2012-08-15 23:47:15 UTC (rev 265) @@ -1,12 +1,8 @@ COMPILER=gcc -g PNDIR=../pnheaders/ -comp: plantCompiler.o compexample.o filltmpl.fl.o supervisorCompiler.o - make -f pnexample.mak -C$(PNDIR) - $(COMPILER) -o compexample plantCompiler.o compexample.o filltmpl.fl.o $(PNDIR)matrix.o $(PNDIR)general.o $(PNDIR)pns.o $(PNDIR)insert.o supervisorCompiler.o +static: plantCompiler.o filltmpl.fl.o supervisorCompiler.o templates.o -static: plantCompiler.o filltmpl.fl.o supervisorCompiler.o - compexample.o: compexample.c *.h $(PNDIR)*.h $(COMPILER) -c -I$(PNDIR) compexample.c @@ -18,7 +14,15 @@ filltmpl.fl.o: filltmpl.lex flex -Pfl -ofilltmpl.fl.c filltmpl.lex - $(COMPILER) -c filltmpl.fl.c + $(COMPILER) -c filltmpl.fl.c -I$(PNDIR) +templates.o: fl2str SupervisorTemplate.c ProcessTemplate.c spcommon.h + ./fl2str templates.c SupervisorTemplate.c ProcessTemplate.c spcommon.h + $(COMPILER) -c templates.c + +fl2str: fl2str.lex + flex -ofl2str.yy.c fl2str.lex + $(COMPILER) -o fl2str fl2str.yy.c + clean: - rm *.o || true + rm *.o obj/*.o || true \ No newline at end of file Modified: present_version/newcodegen/Makefile-linux.mak =================================================================== --- present_version/newcodegen/Makefile-linux.mak 2012-08-15 20:59:28 UTC (rev 264) +++ present_version/newcodegen/Makefile-linux.mak 2012-08-15 23:47:15 UTC (rev 265) @@ -1,12 +1,8 @@ COMPILER=gcc -g PNDIR=../pnheaders/ -comp: plantCompiler.o compexample.o filltmpl.fl.o supervisorCompiler.o - make -f pnexample.mak -C$(PNDIR) - $(COMPILER) -o compexample plantCompiler.o compexample.o filltmpl.fl.o $(PNDIR)matrix.o $(PNDIR)general.o $(PNDIR)pns.o $(PNDIR)insert.o supervisorCompiler.o +static: plantCompiler.o filltmpl.fl.o supervisorCompiler.o templates.o -static: plantCompiler.o filltmpl.fl.o supervisorCompiler.o - compexample.o: compexample.c *.h $(PNDIR)*.h $(COMPILER) -c -I$(PNDIR) compexample.c @@ -18,7 +14,15 @@ filltmpl.fl.o: filltmpl.lex flex -Pfl -ofilltmpl.fl.c filltmpl.lex - $(COMPILER) -c filltmpl.fl.c + $(COMPILER) -c filltmpl.fl.c -I$(PNDIR) +templates.o: fl2str SupervisorTemplate.c ProcessTemplate.c spcommon.h + ./fl2str templates.c SupervisorTemplate.c ProcessTemplate.c spcommon.h + $(COMPILER) -c templates.c + +fl2str: fl2str.lex + flex -ofl2str.yy.c fl2str.lex + $(COMPILER) -o fl2str fl2str.yy.c + clean: - rm *.o || true + rm *.o obj/*.o || true \ No newline at end of file Modified: present_version/newcodegen/ProcessTemplate.c =================================================================== --- present_version/newcodegen/ProcessTemplate.c 2012-08-15 20:59:28 UTC (rev 264) +++ present_version/newcodegen/ProcessTemplate.c 2012-08-15 23:47:15 UTC (rev 265) @@ -15,7 +15,7 @@ extern int ___debug; // corresponds to variable of supervisor #endif -#include"spcommon.h" +#include"spcommon.h"//--- ANY change on this line MUST be reflected in BOTH SupervisorTemplate.c and filltmpl.lex, in order that filltmpl.lex may be able to replace this line with the adequate include directive static void* ___main_function(void* ___v); @@ -76,7 +76,7 @@ #ifndef ___THREAD ___ctime += (int) getpid(); #else - ___ctime += (int) getpid() + (int)___pthr->id; + ___ctime += (int) getpid() + (int)(long)___pthr->id; // (long) avoids warning #ifndef SINGLE_READ_CHANNEL // block SIGUSR1 which may be used to notify main program of new messages sigemptyset(&___set); @@ -147,7 +147,7 @@ if(___pthr || ___pc) { asprintf(&___s2, "\nThe following parameters were received:\n"); if(___pthr) - asprintf(&___s3, "id = %d debug = %d initial state = %d", (int)___pthr->id, (int)___pthr->debug, (int)___pthr->state); + asprintf(&___s3, "id = %d debug = %d initial state = %d", (int)(long)___pthr->id, (int)___pthr->debug, (int)___pthr->state); if(___pc) asprintf(&___s4, " write end = %d", (int)___pc->pwrite); } Modified: present_version/newcodegen/SupervisorTemplate.c =================================================================== --- present_version/newcodegen/SupervisorTemplate.c 2012-08-15 20:59:28 UTC (rev 264) +++ present_version/newcodegen/SupervisorTemplate.c 2012-08-15 23:47:15 UTC (rev 265) @@ -40,7 +40,7 @@ char* ___name; -#include"spcommon.h" +#include"spcommon.h"//--- ANY change on this line MUST be reflected in BOTH ProcessTemplate.c and filltmpl.lex, in order that filltmpl.lex may be able to replace this line with the adequate include directive // The following is used for unnamed pipe communication between plant // and supervisor. @@ -228,6 +228,8 @@ #ifdef ZERO_LABEL_TRANS + int ___i, ___flag, ___tr; + for(___flag = 1; ___flag; ) { ___flag = 0; for(___i = 0; ___i < ZERO_LABEL_TRANS; ___i++) { @@ -1238,19 +1240,19 @@ int main(int argc, char* argv[]) { int ___i, ___j; - char *___str, ___help_msg[] = "\nOptions: \n\ - -e: suppress error and status messages\n\ - -s: start the program right away without displaying introductory message\n\n\ + char *___str, ___help_msg[] = "\nCommand line options: \n\ + -d: display error and status messages\n\ + -s: start the program right away without displaying this introductory message\n\n\ Ctrl-C (SIGINT) can be used to stop the program. This will terminate all\n\ its processes.\n"; - ___debug = 1; + ___debug = 0; ___start_flag = (argc <= 1); for(___i = 1; ___i < argc; ___i++) { - if(!strcmp(argv[___i], "-e")) - ___debug = 0; + if(!strcmp(argv[___i], "-d")) + ___debug = 1; else if(!strcmp(argv[___i], "-h") || !strcmp(argv[___i], "--help")) { - fprintf(stdout, ___help_msg); + fputs(___help_msg, stdout); return 0; } else if(!strcmp(argv[___i], "-s")) { Modified: present_version/newcodegen/codegen.h =================================================================== --- present_version/newcodegen/codegen.h 2012-08-15 20:59:28 UTC (rev 264) +++ present_version/newcodegen/codegen.h 2012-08-15 23:47:15 UTC (rev 265) @@ -1,6 +1,6 @@ /* codegen.h - This header file was created for the 2010 version of the code generation tools. + This header file was created for the 2010 version of the code generation tools. Updated in 2012. */ /* The code generation module expects processes satisfying the following @@ -11,9 +11,12 @@ from the supervisor. (NOT YET IMPLEMENTED.) - The supervisor format: It is assumed that each transition has a - unique label. Process transitions that are synchronized are assumed to - have the same label. The supervisor is connected to the plant using the - conventional parallel composition of PNs. + one label. (That is, though multiple transitions may share a common + label, the expectation is that exactly one label (no more, no less) + is assigned to each transition.) Process transitions that are + synchronized are assumed to have the same label. The supervisor is + connected to the plant using the conventional parallel composition of + PNs. - The select function: If defined, it should return the number of transitions selected. Let n be that number. The select function writes the @@ -35,9 +38,33 @@ #define DBG3 is_verbose()>=3 +#define LINEDIR "/*___LINEDIR*/" // Read lines below before changing! +// The string of LINEDIR is not completely arbitrary: FillTemplate assumes +// that the first character is not repeated, excepting the last character. +// LINEDIR is inserted within the text sent to FillTemplate in order to mark +// points at which #line directives should be inserted redirecting +// error messages from the compiler to the actual file that is compiled. -int FillTemplate(FILE* template, FILE* outp, ...); // in filltmpl.lex +struct input { // the nonzero field among 'buf' and 'file' is to be used + FILE *file; + char *buf; +}; + + +int FillTemplate(struct input template, FILE* outp, char* outpname, \ + char* inclname, char* preamble, ...); // in filltmpl.lex +// This function uses 'template' in order to generate a customized output file. +// 'outpname' denotes the name of the outp file. +// 'outp' is the file that FillTemplate writes. +// 'preamble', if nonzero, is written at the beginning of this file. +// If 'inclname' is nonzero, it is used to replace spcommon.h in +// #include"spcommon.h" with 'inclname'. +// This function expects cblock objects for the optional arguments. +// If no 'line' directives should be written, the 'file' field of +// the cblock object should be zero. + + FILE* searchTemplate(char* s); // in plantCompiler.c char* GetFileName(const char* s, const char *ext); Modified: present_version/newcodegen/filltmpl.lex =================================================================== --- present_version/newcodegen/filltmpl.lex 2012-08-15 20:59:28 UTC (rev 264) +++ present_version/newcodegen/filltmpl.lex 2012-08-15 23:47:15 UTC (rev 265) @@ -5,33 +5,85 @@ %{ #include<stdio.h> #include<stdarg.h> + #include"pns.h" + #include"codegen.h" - int flag, skip, i, j; - va_list param; - FILE *out; - char *stmp, cc; + static const char lntxt[] = LINEDIR; + static int flag, skip, i, j, k, line, lntxtlen; + static va_list param; + static FILE *out; + static char *stmp, cc, *fileName; + static cblock bl; + static char *inclname; + void mfprint(char *str, ...) { // updates line based on the format string + int ii; + va_list par; + + for(ii = 0; str[ii]; ii++) + line += (str[ii] == '\n'); + + va_start(par, str); + vfprintf(out, str, par); + va_end(par); + } + %} %% +\#include\"spcommon\.h\"\/\/\-\-\-[^\n]* { + if(inclname) + fprintf(out, "#include\"%s\"", inclname); + else + fputs("#include\"spcommon.h\"", out); + } + + {LABEL}/{IDENTIFIER} { flag = 0; skip = 1; - fprintf(out, "%s (BEGINNING OF CODE)\n", yytext); + // mfprint used in order to update 'line' automatically + mfprint("%s (BEGINNING OF CODE)\n", yytext); for(i = 0; yytext[i] == ' ' || yytext[i] == '\t'; i++); cc = yytext[i]; - yytext[i] = 0; // get indentation string - stmp = va_arg(param, char*); // get string to insert + yytext[i] = 0; // get indentation string in yytext + bl = va_arg(param, cblock); // get string to insert + stmp = bl.text; if(stmp) { - for(j = 0; stmp[j]; j++) { - fwrite(stmp+j, sizeof(stmp[j]), 1, out); - if(stmp[j] == '\r' || stmp[j] == '\n') - fprintf(out, "%s", yytext); + if(bl.file) { + mfprint("#line %d \"%s\"\n", bl.line, bl.file); + for(j = 0; stmp[j]; j++) { + fwrite(stmp+j, sizeof(stmp[j]), 1, out); + if(stmp[j] == '\r' || stmp[j] == '\n') { + fprintf(out, "%s", yytext); // print indentation + line += (stmp[j] == '\n'); + } + } + mfprint("\n#line %d \"%s\"\n", line+2, fileName); } + else { // look for LINEDIR requests + for(j = 0, k = 0; stmp[j]; j++, k++) { + if(stmp[j] == lntxt[k]) + continue; + if(!lntxt[k]) { // a LINEDIR request was found + mfprint("\n#line %d \"%s\"\n",line+2, fileName); + k = -1; + continue; + } + for(j = j - k; k >= 0; k--, j++) + fwrite(stmp+j, sizeof(*stmp), 1, out); + j--; + if(stmp[j] == '\r' || stmp[j] == '\n') { + fprintf(out, "%s", yytext); // print indentation + line += (stmp[j] == '\n'); + } + } + } } yytext[i] = cc; // restore yytext - fprintf(out, "\n%s (END OF CODE)\n", yytext); + // mfprint used in order to update 'line' automatically + mfprint("\n%s (END OF CODE)\n", yytext); } {IDENTIFIER} { @@ -48,6 +100,7 @@ \n|\r { skip = 0; fprintf(out, "%s", yytext); + line += (yytext[0] == '\n'); } %% @@ -57,19 +110,38 @@ return 1; } -int FillTemplate(FILE* template, FILE* outp, ...) { +int FillTemplate(struct input template, FILE* outp, char* outpname, \ + char* incname, char* preamble, ...) { + static int fl = 0; - va_start(param, outp); + if(!template.file && !template.buf) + merror(0, "CODE GENERATION: Invalid template input"); + line = 1; + inclname = incname; + + va_start(param, preamble); + flag = 0; skip = 0; + fileName = outpname; - yyin = template; + lntxtlen = strlen(LINEDIR); + out = outp; - if(fl) - yyrestart(template); + if(template.file) { + yyin = template.file; + if(fl) + yyrestart(template.file); + } + else + yy_scan_string(template.buf); + + if(preamble) + mfprint(preamble); // this will also update 'line' + yylex(); va_end(param); Added: present_version/newcodegen/fl2str.lex =================================================================== --- present_version/newcodegen/fl2str.lex (rev 0) +++ present_version/newcodegen/fl2str.lex 2012-08-15 23:47:15 UTC (rev 265) @@ -0,0 +1,90 @@ + +%{ + +#include<stdio.h> + + static FILE *f; + +%} + +%% + +\\ fputs("\\\\", f); +\" fputs("\\\"", f); + +\r fputs("\\r", f); +\n fputs("\\n", f); +\t fputs("\\t", f); + +. fputc(yytext[0], f); + +%% + +int yywrap(void) { + return 1; + } + +int main(int na, char* argv[]) { + int i, j; + char flag, c; + + if(na <= 2) { + printf("\nThis program converts text files to strings that can be used within C programs"); + printf("\n\nUsage: %s output_file input_file [input_files]\n", argv[0]); + return 0; + } + + f = fopen(argv[1], "w"); + if(!f) { + printf("\nThe file %s cannot be written\n", argv[1]); + return 1; + } + + for(i = 2, flag = 0; i < na; i++) { + yyin = fopen(argv [i], "r"); + if(!yyin) { + flag = 1; + printf("\nThe file %s could not be opened\n", argv[i]); + } + else + fclose(yyin); + } + + if(flag) + return 1; + + // fprintf(f, "/* This is %s generated with the command line:\n %s %s", argv[1], argv[0], argv[1]); + //for(i = 2; i < na; i++) + // fprintf(f, " %s", argv[i]); + // fputs("\n*/\n\n", f); + + for(i = 2; i < na; i++) { + yyin = fopen(argv[i], "r"); + if(!yyin) { + printf("\nCould not reopen the file %s\n", argv[i]); + fclose(f); + return 1; + } + + fputs("\nchar ", f); + for(j = 0; argv[i][j]; j++) { + c = argv[i][j]; + if(c == '.') + fputc('_', f); + else + fputc(c, f); + } + fputs("[] = \"", f); + + if(i >= 3) + yyrestart(yyin); + yylex(); + fclose(yyin); + + fputs("\";\n", f); + } + + fclose(f); + return 0; +} + Modified: present_version/newcodegen/plantCompiler.c =================================================================== --- present_version/newcodegen/plantCompiler.c 2012-08-15 20:59:28 UTC (rev 264) +++ present_version/newcodegen/plantCompiler.c 2012-08-15 23:47:15 UTC (rev 265) @@ -2,9 +2,12 @@ plantCompiler.c -- Generates the c code for the plant PNs This is the 2010 version. The 2010 version was written by M. V. Iordache. Created: May 2010. -Last updated: June 2010. +Last updated: Nov 2011. ****************************************************************************/ +// TO DO: +// For each transition ti create "#define ti___data(x) {(x).t = ...;(x).l = ...; ...}" allowing to initialize ___TR[j] to the data of ti. This is for the select function + #include<stdio.h> #include<stdarg.h> #include<time.h> @@ -14,6 +17,8 @@ #define TEMPL "ProcessTemplate.c" +extern char ProcessTemplate_c[]; +extern char *inc_name; FILE* searchTemplate(char* s) { // In future versions this should do a search in some default paths. @@ -30,9 +35,9 @@ } -struct myinsert genDefineBlock(specs *sp, process* pr, TrData* TrInfo) { +struct myinsert genDefineBlock(specs *sp, process* pr, TrData* TrInfo, int* actlabels) { struct myinsert ins; - int i, j, k, ntr; + int i, j, k, ntr, t, no_place, out_place, label; pns *pn; ins = InitInsert(512); @@ -63,6 +68,9 @@ } ins = SInsert("};", ins); + if(pr->dfns) + ins = FSInsert(ins, "\n\n%s", pr->dfns); + if(pr->thread) { ins = FSInsert(ins, "\n\n\ void* ___start_%s(void* ___v) {\n\ @@ -81,6 +89,39 @@ //if(DBG3) // if yes, then generated executables should also be in debug mode // incl = SInsert("\n#define ___DEBUG\n", incl); + + // Determine whether it is useful to generate the TRdata array + // (This unlikely to be necessary apart from select functions.) + + i = pn->pnum; + if(pn) + if(pn->select) + for(i = 0; i < pn->pnum; i++) + if(pn->select[i].text != 0) + break; + // Select functions have been defined if i != pn->pnum + // Then write the TRdata array + if(i != pn->pnum) { + ins = SInsert("\nstatic const struct ___trans ___TRData[] = {", ins); + for(t = 0; t < pn->tnum; t++) { + out_place = -1; + no_place = 1; + for(j = 0; j < pn->pnum; j++) + if(GetMatrixEl(&(pn->in), j, t)) { // if arc from t to j + out_place = j; + no_place = 0; + break; + } + label = 0; + if(pn->t) + label = pn->t[t].l; + if(t) + ins = SInsert(", ", ins); + ins = FSInsert(ins,"{%d, %d, %d, %d, %d}", no_place, out_place, label, actlabels[t], t); + } + ins = SInsert("};\n", ins); + } + return ins; } @@ -100,7 +141,13 @@ for(i = 0; i < pn->pnum; i++) { ins = FSInsert(ins, "\ncase %d:\n", i); if(pn->segment) - ins = SInsert(pn->segment[i], ins); + if(pn->segment[i].text) { + if(pr->file) + ins = FSInsert(ins,"#line %d \"%s\"\n", pn->segment[i].line, pr->file); + ins = SInsert(pn->segment[i].text, ins); + if(pr->file) + ins = SInsert(LINEDIR, ins); + } // Inserting/creating select functions // The output of the select function is the ___TR list. @@ -113,9 +160,14 @@ // The code will not progress until a transition is enabled fl = 0; if(pn->select) - fl = (pn->select[i] != 0); - if(fl) // if select function already provided - ins = FSInsert(ins, "\n___i = %s;", pn->select[i]); + fl = (pn->select[i].text != 0); + if(fl) { // if select function already provided + if(pr->file) + ins = FSInsert(ins,"\n#line %d \"%s\"", pn->select[i].line, pr->file); + ins = FSInsert(ins, "\n___i = %s;", pn->select[i].text); + if(pr->file) + ins = SInsert(LINEDIR, ins); + } else { // write the operations involved in selecting the next transition for(t = 0; t < pn->tnum; t++) { if(GetMatrixEl(&(pn->out), i, t)) { // if there is an arc (p,t) @@ -123,7 +175,7 @@ if(pn->arc_list) { for(arcp = pn->arc_list[t]; arcp; arcp = arcp->next) if(arcp->in_place == i) { - if(arcp->condition) + if(arcp->condition.text) flag = 1; break; } @@ -140,7 +192,11 @@ if(pn->t) label = pn->t[t].l; if(flag) { // if the transition is conditionally enabled - ins = FSInsert(ins, "\nif(%s)", arcp->condition); + if(pr->file) + ins = FSInsert(ins,"\n#line %d \"%s\"", arcp->condition.line, pr->file); + ins = FSInsert(ins, "\nif(%s)", arcp->condition.text); + if(pr->file) + ins = SInsert(LINEDIR, ins); ins = FSInsert(ins, "\n___i = ___AddToTR(___TR, ___i, %d, %d, %d, %d, %d);",\ no_place, out_place, label, t, actlabels[t]); } @@ -180,11 +236,19 @@ int i, j; char *fileName, *tmp; - FILE* plantFile, *f; + FILE* plantFile; time_t currentTime; - struct myinsert incl, mblock; + struct myinsert incl, mblock, pre; + cblock bl1, bl2; + struct input in; - f = searchTemplate(TEMPL); + if(sp->templ) { + in.file = searchTemplate(TEMPL); in.buf = 0; + rewind(in.file); + } + else { + in.file = 0; in.buf = ProcessTemplate_c; + } for(i = 0; i < nbrElements; i++) { fileName = GetFileName(procArray[i]->name, "c"); @@ -196,35 +260,42 @@ // Write header of file + pre = InitInsert(128); time(¤tTime); - fprintf(plantFile,"\ + + pre = FSInsert(pre, "\ // This is %s generated from template %s.\n\ // %s\n\n", fileName, TEMPL, asctime(localtime(¤tTime))); - if(procArray[i]->thread) fprintf(plantFile,"\n#define ___THREAD\n"); - else fprintf(plantFile,"\n#define ___PROCESS\n")... [truncated message content] |