The information specified in a user-defined property is stored in the parse tree that the
UniCon compiler creates while processing UniCon definitions. At an appropriate step in the compilation or build process, the compiler can collect the information associated with a user-defined property and ship it off to an external tool that might need the information.
NOTE: For now, the means for communicating with external tools is builtin to the compiler. Therefore, adding a new tool to the suite of external tools that are known to UniCon requires modification of the UniCon compiler source code. Since this is not a trivial task, this may require help from the UniCon compiler developers.
As mentioned above, the UniCon compiler does not parse or further interpret the value part of a user-defined property. There are hooks in the source code of the compiler, however, for the user to supply C source code fragments to parse and check the semantics of the value part. The UniCon compiler will execute these code fragments at the appropriate times during the compilation and build process.
The UniCon compiler calls two functions when it encounters a user-defined property. The first is a function that executes user-supplied C source code fragments to parse the value part of user-defined properties. The second is a function that executes user-supplied C source code fragments to check the semantics of the value part of user-defined properties.
The first function, uni_user_parse, is the hook in the UniCon compiler for users to add C source code that parses the value of a user-defined property. If the user wishes to have the UniCon compiler parse the value of a user-defined property, (s)he must supply a parsing function with the source code of the UniCon compiler that can be compiled and linked with the other UniCon source when building it. The user adds a C source code fragment directly to the first function, uni_user_parse, in the UniCon source file uni_user_defined.c to parse the value of a user-defined property. The following is an example of such a fragment:
if (uni_strcmp_l (av_pair->attribute_str->string, "some_user_defined_property") == 0) return my_user_defined_property_parser ( av_pair->value.user);In the above example, the function uni_strcmp_l is a utility function provided by the UniCon compiler. The letter "l" in the name refers to the leftmost argument in the argument list. This function performs a string comparison using the C standard library routine strcmp, but first it converts the value of the leftmost argument to lower case letters. The UniCon compiler also provides the two functions uni_strcmp_r and uni_strcmp_b which convert the value of the rightmost argument, and the values of both arguments, to lower case letters, respectively. The return values of these three functions have the same semantics as the return value of the strcmp function.
Also, notice that my_user_defined_property_parser is a user-supplied function that parses the value of the property. All of the information about a particular property is contained in the argument named av_pair, supplied as input to the uni_user_parse routine. av_pair->attribute_str->string points to the string value that is the name part of the property, and av_pair->value.user points to the string value that is the value part of the property. The return value of the user-supplied property parser must be a pointer value. It can be a pointer to an object of any type, since UniCon does not further interpret this value.
The second function, uni_user_semantics, is the hook in the UniCon compiler for users to add C source code that checks the semantics of the value of a user-defined property. If the user wishes to have the UniCon compiler check the semantics of the value of a user-defined property, (s)he must supply a semantics checking function with the source code of the UniCon compiler that can be compiled and linked with the other UniCon source when building it. The user adds a C source code fragment directly to the second function, uni_user_semantics, in the UniCon source file uni_user_defined.c to check the semantics of the value of a user-defined property. The following is an example of such a fragment:
if (uni_strcmp_l (av_pair->attribute_str->string, "some_user_defined_property") == 0) return check_my_user_defined_property_semantics ( av_pair->value.user_temp);Notice that check_my_user_defined_property_semantics is a user-supplied function that checks the semantics of the value part of the property. Also, notice that the argument supplied to this function is av_pair->value.user_temp, rather than av_pair->value.user. This is because the function uni_user_parse places the pointer to the parsed value part of a user-defined property there. The return value of the user-supplied property semantic checker must be a pointer value. It can be a pointer to an object of any type, since UniCon does not further interpret this value.
To include the source files containing the user-supplied parsing and semantic checking functions in the build process, modify the Odinfile in the following UniCon installation directory: ...UniCon/uparse/src. Add a separate line for each file to the uparse system model in the following way. Assume you wish to add the functions in the source files my_parsers.c and my_checkers.c to the UniCon compiler. The system model used to build the original compiler looks as follows:
%uparse.c.sm == << uni_error.c +define=UNI_ERROR_ROUTINE uni_lexer.l uni_main.c uni_parser.y uni_tree_builder.c uni_semantic.c uni_list.c uni_user_defined.c uni_builder.c uni_datause.c uni_fileio.c uni_proccall.c uni_rproccall.c uni_pipe.c uni_rts.c uni_unparse.c uni_utility.c +define=UNI_PROGRESS_ROUTINESimply add the names of the files as separate lines to the end of the system model so that it looks as follows. Be sure to include full directory path information for the new files. It is not recommended that you keep the source in the same directory with the other UniCon source. This is because when you delete an old UniCon installation in order to build a new one, you may forget your source files are there and accidentally delete them:
%uparse.c.sm == << uni_error.c +define=UNI_ERROR_ROUTINE uni_lexer.l uni_main.c uni_parser.y uni_tree_builder.c uni_semantic.c uni_list.c uni_user_defined.c uni_builder.c uni_datause.c uni_fileio.c uni_proccall.c uni_rproccall.c uni_pipe.c uni_rts.c uni_unparse.c uni_utility.c +define=UNI_PROGRESS_ROUTINE /usr/gz/my_parsers.c /usr/gz/my_checkers.cThen, change directory to the root of the installation directory (i.e., ...UniCon) and invoke odin to build uparse: "odin %install_uparse".
User-defined properties, of course, are always optional. If specified, however, there must be a corresponding entry for the propery in a file named "user_defined_properties" in the same directory in the file system from which the UniCon compiler is invoked (i.e., the "local" directory). The entry must be a single line with three fields. The first field is the name of the property, and the other two fields can be anything. All three fields are separated from each other by whitespace. The purpose of the second and third fields has not yet been fixed. These are place holders for future enhancements. The case of the letters for the name in the first field is insignificant.
Subsequent specifications of a user-defined property in a single property list replace earlier specifications (i.e., the last specification is the one that the UniCon compiler uses). Two user-defined attributes are duplicates if the name part is identical (the case of the letters is insignificant) and the value part is identical (the case of the letters is significant for the value part).
COMPONENT KWIC INTERFACE IS TYPE Filter PLAYER input IS StreamIn SIGNATURE ("line") PORTBINDING (stdin) END input PLAYER output IS StreamOut SIGNATURE ("line") PORTBINDING (stdout) END output PLAYER error IS StreamOut SIGNATURE ("line") PORTBINDING (stderr) END error END INTERFACE IMPLEMENTATION IS GUI-SCREEN-SIZE ("(list :real-width 800 :width-unit "" :real-height 350 :height-unit "")") DIRECTORY ("(list "/usr/examples/upcase.uni" "/usr/examples/cshift.uni" "/usr/examples/data.uni" "/usr/examples/converge.uni" "/usr/examples/sort.uni" "/usr/examples/unix-pipe.uni" "/usr/examples/reverse-f.uni")") USES caps INTERFACE upcase GUI-SCREEN-POSITION ("(list :position (@pos 68 123) :player-positions (list (cons "input" (cons `left 0.5)) (cons "error" (cons `right 0.6625)) (cons "output" (cons `right 0.3375))))") END caps (remaining definition omitted) END IMPLEMENTATION END KWIC
Author:
Last Modified: May 12, 1996